From 54d759a712fc68e257abc3cfb3e78aef07d60e41 Mon Sep 17 00:00:00 2001 From: xerox Date: Fri, 2 Oct 2020 00:33:23 -0700 Subject: [PATCH] all versions of windows 10 working on amd --- Voyager-2/PayLoad/types.h | 14 +- Voyager-2/Voyager-2 (1703-1511)/BootMgfw.c | 178 + Voyager-2/Voyager-2 (1703-1511)/BootMgfw.h | 28 + Voyager-2/Voyager-2 (1703-1511)/HvLoader.c | 151 + Voyager-2/Voyager-2 (1703-1511)/HvLoader.h | 38 + Voyager-2/Voyager-2 (1703-1511)/Hvax64.c | 122 + Voyager-2/Voyager-2 (1703-1511)/Hvax64.h | 34 + Voyager-2/Voyager-2 (1703-1511)/PayLoad.c | 245 + Voyager-2/Voyager-2 (1703-1511)/PayLoad.h | 17 + Voyager-2/Voyager-2 (1703-1511)/ShitHook.c | 36 + Voyager-2/Voyager-2 (1703-1511)/ShitHook.h | 26 + Voyager-2/Voyager-2 (1703-1511)/UefiMain.c | 31 + Voyager-2/Voyager-2 (1703-1511)/Utils.c | 51 + Voyager-2/Voyager-2 (1703-1511)/Utils.h | 35 + .../Voyager-1 (1703-1511).vcxproj | 198 + .../Voyager-1 (1703-1511).vcxproj.filters | 62 + .../Voyager-1 (1703-1511).vcxproj.user | 4 + Voyager-2/Voyager-2 (1703-1511)/WinLoad.c | 58 + Voyager-2/Voyager-2 (1703-1511)/WinLoad.h | 21 + .../edk2/BaseCacheMaintenanceLib.lib | Bin 0 -> 6300 bytes .../Voyager-2 (1703-1511)/edk2/BaseCpuLib.lib | Bin 0 -> 2114 bytes .../edk2/BaseCryptLib.lib | Bin 0 -> 1716454 bytes .../edk2/BaseDebugPrintErrorLevelLib.lib | Bin 0 -> 2698 bytes .../Voyager-2 (1703-1511)/edk2/BaseLib.lib | Bin 0 -> 424732 bytes .../edk2/BaseMemoryLib.lib | Bin 0 -> 65914 bytes .../edk2/BasePrintLib.lib | Bin 0 -> 57382 bytes .../edk2/BaseSynchronizationLib.lib | Bin 0 -> 21532 bytes .../edk2/CryptoPkg/CryptoPkg.dec | 43 + .../edk2/CryptoPkg/CryptoPkg.dsc | 130 + .../edk2/CryptoPkg/CryptoPkg.uni | 25 + .../edk2/CryptoPkg/CryptoPkgExtra.uni | 20 + .../CryptoPkg/Include/Library/BaseCryptLib.h | 2876 ++++++ .../edk2/CryptoPkg/Include/Library/TlsLib.h | 800 ++ .../Library/BaseCryptLib/BaseCryptLib.inf | 102 + .../Library/BaseCryptLib/BaseCryptLib.uni | 25 + .../Library/BaseCryptLib/Cipher/CryptAes.c | 323 + .../BaseCryptLib/Cipher/CryptAesNull.c | 165 + .../Library/BaseCryptLib/Cipher/CryptArc4.c | 211 + .../BaseCryptLib/Cipher/CryptArc4Null.c | 130 + .../Library/BaseCryptLib/Cipher/CryptTdes.c | 370 + .../BaseCryptLib/Cipher/CryptTdesNull.c | 166 + .../Library/BaseCryptLib/Hash/CryptMd4.c | 229 + .../Library/BaseCryptLib/Hash/CryptMd4Null.c | 149 + .../Library/BaseCryptLib/Hash/CryptMd5.c | 231 + .../Library/BaseCryptLib/Hash/CryptSha1.c | 230 + .../Library/BaseCryptLib/Hash/CryptSha256.c | 229 + .../Library/BaseCryptLib/Hash/CryptSha512.c | 446 + .../BaseCryptLib/Hash/CryptSha512Null.c | 281 + .../Library/BaseCryptLib/Hmac/CryptHmacMd5.c | 256 + .../BaseCryptLib/Hmac/CryptHmacMd5Null.c | 165 + .../Library/BaseCryptLib/Hmac/CryptHmacSha1.c | 256 + .../BaseCryptLib/Hmac/CryptHmacSha1Null.c | 165 + .../BaseCryptLib/Hmac/CryptHmacSha256.c | 256 + .../BaseCryptLib/Hmac/CryptHmacSha256Null.c | 165 + .../Library/BaseCryptLib/InternalCryptLib.h | 68 + .../Library/BaseCryptLib/PeiCryptLib.inf | 99 + .../Library/BaseCryptLib/PeiCryptLib.uni | 31 + .../Library/BaseCryptLib/Pem/CryptPem.c | 135 + .../Library/BaseCryptLib/Pem/CryptPemNull.c | 44 + .../BaseCryptLib/Pk/CryptAuthenticode.c | 198 + .../BaseCryptLib/Pk/CryptAuthenticodeNull.c | 51 + .../Library/BaseCryptLib/Pk/CryptDh.c | 312 + .../Library/BaseCryptLib/Pk/CryptDhNull.c | 156 + .../BaseCryptLib/Pk/CryptPkcs5Pbkdf2.c | 101 + .../BaseCryptLib/Pk/CryptPkcs5Pbkdf2Null.c | 56 + .../Library/BaseCryptLib/Pk/CryptPkcs7Sign.c | 200 + .../BaseCryptLib/Pk/CryptPkcs7SignNull.c | 60 + .../BaseCryptLib/Pk/CryptPkcs7VerifyBase.c | 131 + .../BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c | 916 ++ .../BaseCryptLib/Pk/CryptPkcs7VerifyNull.c | 169 + .../BaseCryptLib/Pk/CryptPkcs7VerifyRuntime.c | 45 + .../Library/BaseCryptLib/Pk/CryptRsaBasic.c | 325 + .../Library/BaseCryptLib/Pk/CryptRsaExt.c | 362 + .../Library/BaseCryptLib/Pk/CryptRsaExtNull.c | 125 + .../Library/BaseCryptLib/Pk/CryptTs.c | 665 ++ .../Library/BaseCryptLib/Pk/CryptTsNull.c | 48 + .../Library/BaseCryptLib/Pk/CryptX509.c | 730 ++ .../Library/BaseCryptLib/Pk/CryptX509Null.c | 238 + .../Library/BaseCryptLib/Rand/CryptRand.c | 110 + .../Library/BaseCryptLib/Rand/CryptRandItc.c | 118 + .../Library/BaseCryptLib/Rand/CryptRandNull.c | 63 + .../Library/BaseCryptLib/Rand/CryptRandTsc.c | 118 + .../Library/BaseCryptLib/RuntimeCryptLib.inf | 107 + .../Library/BaseCryptLib/RuntimeCryptLib.uni | 30 + .../Library/BaseCryptLib/SmmCryptLib.inf | 104 + .../Library/BaseCryptLib/SmmCryptLib.uni | 30 + .../BaseCryptLib/SysCall/BaseMemAllocation.c | 118 + .../BaseCryptLib/SysCall/ConstantTimeClock.c | 43 + .../Library/BaseCryptLib/SysCall/CrtWrapper.c | 474 + .../SysCall/RuntimeMemAllocation.c | 461 + .../BaseCryptLib/SysCall/TimerWrapper.c | 174 + .../CryptoPkg/Library/Include/CrtLibSupport.h | 195 + .../edk2/CryptoPkg/Library/Include/assert.h | 15 + .../edk2/CryptoPkg/Library/Include/ctype.h | 15 + .../edk2/CryptoPkg/Library/Include/errno.h | 15 + .../Library/Include/internal/dso_conf.h | 0 .../edk2/CryptoPkg/Library/Include/limits.h | 15 + .../edk2/CryptoPkg/Library/Include/memory.h | 15 + .../Library/Include/openssl/opensslconf.h | 314 + .../edk2/CryptoPkg/Library/Include/stdarg.h | 15 + .../edk2/CryptoPkg/Library/Include/stddef.h | 15 + .../edk2/CryptoPkg/Library/Include/stdio.h | 15 + .../edk2/CryptoPkg/Library/Include/stdlib.h | 15 + .../edk2/CryptoPkg/Library/Include/string.h | 15 + .../edk2/CryptoPkg/Library/Include/strings.h | 15 + .../edk2/CryptoPkg/Library/Include/sys/time.h | 15 + .../CryptoPkg/Library/Include/sys/types.h | 15 + .../edk2/CryptoPkg/Library/Include/syslog.h | 15 + .../edk2/CryptoPkg/Library/Include/time.h | 15 + .../edk2/CryptoPkg/Library/Include/unistd.h | 15 + .../Library/IntrinsicLib/BaseIntrinsicLib.uni | 22 + .../CryptoPkg/Library/IntrinsicLib/CopyMem.c | 23 + .../Library/IntrinsicLib/Ia32/MathLShiftS64.S | 62 + .../Library/IntrinsicLib/Ia32/MathLShiftS64.c | 54 + .../IntrinsicLib/Ia32/MathLShiftS64.nasm | 48 + .../Library/IntrinsicLib/Ia32/MathRShiftU64.S | 66 + .../Library/IntrinsicLib/Ia32/MathRShiftU64.c | 57 + .../IntrinsicLib/Ia32/MathRShiftU64.nasm | 49 + .../Library/IntrinsicLib/IntrinsicLib.inf | 73 + .../Library/IntrinsicLib/MemoryIntrinsics.c | 60 + .../Library/OpensslLib/OpenSSL-HOWTO.txt | 53 + .../Library/OpensslLib/OpensslLib.inf | 597 ++ .../Library/OpensslLib/OpensslLib.uni | 22 + .../Library/OpensslLib/OpensslLibCrypto.inf | 558 ++ .../Library/OpensslLib/OpensslLibCrypto.uni | 22 + .../CryptoPkg/Library/OpensslLib/buildinf.h | 2 + .../Library/OpensslLib/process_files.pl | 224 + .../CryptoPkg/Library/TlsLib/InternalTlsLib.h | 47 + .../edk2/CryptoPkg/Library/TlsLib/TlsConfig.c | 1217 +++ .../edk2/CryptoPkg/Library/TlsLib/TlsInit.c | 269 + .../edk2/CryptoPkg/Library/TlsLib/TlsLib.inf | 56 + .../edk2/CryptoPkg/Library/TlsLib/TlsLib.uni | 19 + .../CryptoPkg/Library/TlsLib/TlsProcess.c | 463 + .../Voyager-2 (1703-1511)/edk2/GlueLib.lib | Bin 0 -> 33434 bytes .../edk2/IntrinsicLib.lib | Bin 0 -> 5208 bytes .../MdePkg/Include/AArch64/ProcessorBind.h | 213 + .../edk2/MdePkg/Include/Arm/ProcessorBind.h | 246 + .../edk2/MdePkg/Include/Base.h | 1319 +++ .../edk2/MdePkg/Include/Ebc/ProcessorBind.h | 162 + .../edk2/MdePkg/Include/Guid/Acpi.h | 46 + .../edk2/MdePkg/Include/Guid/Apriori.h | 30 + .../MdePkg/Include/Guid/AprioriFileName.h | 44 + .../edk2/MdePkg/Include/Guid/Btt.h | 228 + .../edk2/MdePkg/Include/Guid/CapsuleReport.h | 105 + .../edk2/MdePkg/Include/Guid/Cper.h | 1243 +++ .../MdePkg/Include/Guid/DebugImageInfoTable.h | 80 + .../edk2/MdePkg/Include/Guid/DxeServices.h | 28 + .../edk2/MdePkg/Include/Guid/EventGroup.h | 52 + .../MdePkg/Include/Guid/EventLegacyBios.h | 28 + .../edk2/MdePkg/Include/Guid/FileInfo.h | 71 + .../edk2/MdePkg/Include/Guid/FileSystemInfo.h | 63 + .../Include/Guid/FileSystemVolumeLabelInfo.h | 37 + .../Include/Guid/FirmwareContentsSigned.h | 26 + .../MdePkg/Include/Guid/FirmwareFileSystem2.h | 40 + .../MdePkg/Include/Guid/FirmwareFileSystem3.h | 30 + .../edk2/MdePkg/Include/Guid/FmpCapsule.h | 98 + .../edk2/MdePkg/Include/Guid/GlobalVariable.h | 192 + .../edk2/MdePkg/Include/Guid/Gpt.h | 43 + .../MdePkg/Include/Guid/GraphicsInfoHob.h | 51 + .../Include/Guid/HardwareErrorVariable.h | 28 + .../Include/Guid/HiiFormMapMethodGuid.h | 25 + .../MdePkg/Include/Guid/HiiKeyBoardLayout.h | 27 + .../Include/Guid/HiiPlatformSetupFormset.h | 35 + .../edk2/MdePkg/Include/Guid/HobList.h | 30 + .../MdePkg/Include/Guid/ImageAuthentication.h | 352 + .../MdePkg/Include/Guid/MdePkgTokenSpace.h | 25 + .../MdePkg/Include/Guid/MemoryAllocationHob.h | 34 + .../Include/Guid/MemoryAttributesTable.h | 34 + .../Include/Guid/MemoryOverwriteControl.h | 76 + .../edk2/MdePkg/Include/Guid/Mps.h | 35 + .../edk2/MdePkg/Include/Guid/PcAnsi.h | 58 + .../MdePkg/Include/Guid/PropertiesTable.h | 37 + .../edk2/MdePkg/Include/Guid/SalSystemTable.h | 31 + .../edk2/MdePkg/Include/Guid/SmBios.h | 38 + .../Include/Guid/StatusCodeDataTypeId.h | 809 ++ .../MdePkg/Include/Guid/SystemResourceTable.h | 125 + .../MdePkg/Include/Guid/VectorHandoffTable.h | 33 + .../edk2/MdePkg/Include/Guid/WinCertificate.h | 128 + .../edk2/MdePkg/Include/Ia32/Nasm.inc | 28 + .../edk2/MdePkg/Include/Ia32/ProcessorBind.h | 328 + .../MdePkg/Include/IndustryStandard/Acpi.h | 21 + .../MdePkg/Include/IndustryStandard/Acpi10.h | 661 ++ .../MdePkg/Include/IndustryStandard/Acpi20.h | 545 ++ .../MdePkg/Include/IndustryStandard/Acpi30.h | 729 ++ .../MdePkg/Include/IndustryStandard/Acpi40.h | 1309 +++ .../MdePkg/Include/IndustryStandard/Acpi50.h | 2119 +++++ .../MdePkg/Include/IndustryStandard/Acpi51.h | 2139 +++++ .../MdePkg/Include/IndustryStandard/Acpi60.h | 2392 +++++ .../MdePkg/Include/IndustryStandard/Acpi61.h | 2424 +++++ .../MdePkg/Include/IndustryStandard/Acpi62.h | 2960 +++++++ .../MdePkg/Include/IndustryStandard/AcpiAml.h | 175 + .../AlertStandardFormatTable.h | 146 + .../MdePkg/Include/IndustryStandard/Atapi.h | 857 ++ .../Include/IndustryStandard/Bluetooth.h | 62 + .../MdePkg/Include/IndustryStandard/Bmp.h | 48 + .../IndustryStandard/DebugPort2Table.h | 79 + .../Include/IndustryStandard/DebugPortTable.h | 50 + .../MdePkg/Include/IndustryStandard/Dhcp.h | 282 + .../DmaRemappingReportingTable.h | 269 + .../Include/IndustryStandard/ElTorito.h | 147 + .../MdePkg/Include/IndustryStandard/Emmc.h | 297 + .../HighPrecisionEventTimerTable.h | 68 + .../MdePkg/Include/IndustryStandard/Hsti.h | 82 + .../MdePkg/Include/IndustryStandard/Http11.h | 254 + .../IndustryStandard/IScsiBootFirmwareTable.h | 167 + .../IndustryStandard/IoRemappingTable.h | 209 + .../MdePkg/Include/IndustryStandard/Ipmi.h | 61 + .../IpmiFruInformationStorage.h | 92 + .../Include/IndustryStandard/IpmiNetFnApp.h | 1035 +++ .../IndustryStandard/IpmiNetFnBridge.h | 243 + .../IndustryStandard/IpmiNetFnChassis.h | 464 + .../IndustryStandard/IpmiNetFnFirmware.h | 26 + .../IpmiNetFnGroupExtension.h | 26 + .../IndustryStandard/IpmiNetFnSensorEvent.h | 52 + .../IndustryStandard/IpmiNetFnStorage.h | 789 ++ .../IndustryStandard/IpmiNetFnTransport.h | 891 ++ .../IndustryStandard/LegacyBiosMpTable.h | 294 + .../IndustryStandard/LowPowerIdleTable.h | 82 + .../MdePkg/Include/IndustryStandard/Mbr.h | 60 + ...emoryMappedConfigurationSpaceAccessTable.h | 53 + .../MemoryOverwriteRequestControlLock.h | 43 + .../MdePkg/Include/IndustryStandard/Nvme.h | 939 ++ .../MdePkg/Include/IndustryStandard/Pal.h | 3302 +++++++ .../MdePkg/Include/IndustryStandard/Pci.h | 23 + .../MdePkg/Include/IndustryStandard/Pci22.h | 867 ++ .../MdePkg/Include/IndustryStandard/Pci23.h | 133 + .../MdePkg/Include/IndustryStandard/Pci30.h | 79 + .../Include/IndustryStandard/PciCodeId.h | 100 + .../Include/IndustryStandard/PciExpress21.h | 668 ++ .../Include/IndustryStandard/PciExpress30.h | 57 + .../Include/IndustryStandard/PciExpress31.h | 78 + .../Include/IndustryStandard/PciExpress40.h | 89 + .../MdePkg/Include/IndustryStandard/PeImage.h | 756 ++ .../MdePkg/Include/IndustryStandard/Sal.h | 915 ++ .../MdePkg/Include/IndustryStandard/Scsi.h | 412 + .../edk2/MdePkg/Include/IndustryStandard/Sd.h | 181 + .../Include/IndustryStandard/SdramSpd.h | 74 + .../Include/IndustryStandard/SdramSpdDdr3.h | 769 ++ .../Include/IndustryStandard/SdramSpdDdr4.h | 958 ++ .../Include/IndustryStandard/SdramSpdLpDdr.h | 474 + .../SerialPortConsoleRedirectionTable.h | 163 + ...ServiceProcessorManagementInterfaceTable.h | 104 + .../MdePkg/Include/IndustryStandard/SmBios.h | 2602 ++++++ .../MdePkg/Include/IndustryStandard/SmBus.h | 81 + .../IndustryStandard/TcgPhysicalPresence.h | 129 + .../Include/IndustryStandard/TcgStorageCore.h | 401 + .../Include/IndustryStandard/TcgStorageOpal.h | 249 + .../Include/IndustryStandard/TcpaAcpi.h | 58 + .../MdePkg/Include/IndustryStandard/Tls1.h | 107 + .../MdePkg/Include/IndustryStandard/Tpm12.h | 2173 +++++ .../MdePkg/Include/IndustryStandard/Tpm20.h | 1820 ++++ .../Include/IndustryStandard/Tpm2Acpi.h | 59 + .../MdePkg/Include/IndustryStandard/TpmPtp.h | 523 ++ .../MdePkg/Include/IndustryStandard/TpmTis.h | 187 + .../MdePkg/Include/IndustryStandard/Udf.h | 147 + .../IndustryStandard/UefiTcgPlatform.h | 342 + .../MdePkg/Include/IndustryStandard/Usb.h | 386 + .../IndustryStandard/WatchdogActionTable.h | 96 + .../IndustryStandard/WatchdogResourceTable.h | 56 + .../WindowsSmmSecurityMitigationTable.h | 39 + .../IndustryStandard/WindowsUxCapsule.h | 47 + .../edk2/MdePkg/Include/Library/BaseLib.h | 7868 +++++++++++++++++ .../MdePkg/Include/Library/BaseMemoryLib.h | 489 + .../Include/Library/CacheMaintenanceLib.h | 212 + .../edk2/MdePkg/Include/Library/CpuLib.h | 51 + .../edk2/MdePkg/Include/Library/DebugLib.h | 529 ++ .../Include/Library/DebugPrintErrorLevelLib.h | 43 + .../MdePkg/Include/Library/DevicePathLib.h | 567 ++ .../Include/Library/DxeCoreEntryPoint.h | 99 + .../MdePkg/Include/Library/DxeServicesLib.h | 330 + .../Include/Library/DxeServicesTableLib.h | 34 + .../MdePkg/Include/Library/ExtendedSalLib.h | 494 ++ .../Include/Library/ExtractGuidedSectionLib.h | 284 + .../MdePkg/Include/Library/FileHandleLib.h | 507 ++ .../edk2/MdePkg/Include/Library/HobLib.h | 566 ++ .../edk2/MdePkg/Include/Library/HstiLib.h | 158 + .../edk2/MdePkg/Include/Library/IoLib.h | 2815 ++++++ .../Include/Library/MemoryAllocationLib.h | 493 ++ .../Include/Library/MmServicesTableLib.h | 25 + .../Include/Library/OrderedCollectionLib.h | 425 + .../edk2/MdePkg/Include/Library/PalLib.h | 63 + .../edk2/MdePkg/Include/Library/PcdLib.h | 2260 +++++ .../edk2/MdePkg/Include/Library/PciCf8Lib.h | 1094 +++ .../MdePkg/Include/Library/PciExpressLib.h | 1062 +++ .../edk2/MdePkg/Include/Library/PciLib.h | 1062 +++ .../Include/Library/PciSegmentInfoLib.h | 41 + .../MdePkg/Include/Library/PciSegmentLib.h | 1049 +++ .../Include/Library/PeCoffExtraActionLib.h | 53 + .../Include/Library/PeCoffGetEntryPointLib.h | 122 + .../edk2/MdePkg/Include/Library/PeCoffLib.h | 392 + .../Include/Library/PeiCoreEntryPoint.h | 138 + .../MdePkg/Include/Library/PeiServicesLib.h | 567 ++ .../Library/PeiServicesTablePointerLib.h | 74 + .../MdePkg/Include/Library/PeimEntryPoint.h | 109 + .../MdePkg/Include/Library/PerformanceLib.h | 772 ++ .../edk2/MdePkg/Include/Library/PostCodeLib.h | 150 + .../edk2/MdePkg/Include/Library/PrintLib.h | 1051 +++ .../Include/Library/ReportStatusCodeLib.h | 492 ++ .../Include/Library/ResourcePublicationLib.h | 42 + .../edk2/MdePkg/Include/Library/RngLib.h | 86 + .../MdePkg/Include/Library/S3BootScriptLib.h | 602 ++ .../edk2/MdePkg/Include/Library/S3IoLib.h | 2677 ++++++ .../edk2/MdePkg/Include/Library/S3PciLib.h | 1052 +++ .../MdePkg/Include/Library/S3PciSegmentLib.h | 1037 +++ .../edk2/MdePkg/Include/Library/S3SmbusLib.h | 455 + .../edk2/MdePkg/Include/Library/S3StallLib.h | 39 + .../edk2/MdePkg/Include/Library/SafeIntLib.h | 3030 +++++++ .../edk2/MdePkg/Include/Library/SalLib.h | 59 + .../MdePkg/Include/Library/SerialPortLib.h | 180 + .../edk2/MdePkg/Include/Library/SmbusLib.h | 497 ++ .../Include/Library/SmiHandlerProfileLib.h | 87 + .../edk2/MdePkg/Include/Library/SmmIoLib.h | 42 + .../edk2/MdePkg/Include/Library/SmmLib.h | 89 + .../edk2/MdePkg/Include/Library/SmmMemLib.h | 138 + .../Include/Library/SmmPeriodicSmiLib.h | 184 + .../Include/Library/SmmServicesTableLib.h | 43 + .../Library/StandaloneMmDriverEntryPoint.h | 131 + .../Include/Library/SynchronizationLib.h | 293 + .../edk2/MdePkg/Include/Library/TimerLib.h | 114 + .../Library/UefiApplicationEntryPoint.h | 154 + .../Library/UefiBootServicesTableLib.h | 34 + .../Include/Library/UefiDecompressLib.h | 108 + .../Include/Library/UefiDriverEntryPoint.h | 195 + .../edk2/MdePkg/Include/Library/UefiLib.h | 1802 ++++ .../MdePkg/Include/Library/UefiRuntimeLib.h | 587 ++ .../Library/UefiRuntimeServicesTableLib.h | 32 + .../edk2/MdePkg/Include/Library/UefiScsiLib.h | 1181 +++ .../edk2/MdePkg/Include/Library/UefiUsbLib.h | 563 ++ .../edk2/MdePkg/Include/Pi/PiBootMode.h | 42 + .../edk2/MdePkg/Include/Pi/PiDependency.h | 47 + .../edk2/MdePkg/Include/Pi/PiDxeCis.h | 744 ++ .../edk2/MdePkg/Include/Pi/PiFirmwareFile.h | 501 ++ .../edk2/MdePkg/Include/Pi/PiFirmwareVolume.h | 253 + .../edk2/MdePkg/Include/Pi/PiHob.h | 518 ++ .../edk2/MdePkg/Include/Pi/PiI2c.h | 307 + .../edk2/MdePkg/Include/Pi/PiMmCis.h | 351 + .../edk2/MdePkg/Include/Pi/PiMultiPhase.h | 185 + .../edk2/MdePkg/Include/Pi/PiPeiCis.h | 1070 +++ .../edk2/MdePkg/Include/Pi/PiS3BootScript.h | 59 + .../edk2/MdePkg/Include/Pi/PiSmmCis.h | 206 + .../edk2/MdePkg/Include/Pi/PiStatusCode.h | 1200 +++ .../edk2/MdePkg/Include/PiDxe.h | 25 + .../edk2/MdePkg/Include/PiMm.h | 25 + .../edk2/MdePkg/Include/PiPei.h | 27 + .../edk2/MdePkg/Include/PiSmm.h | 25 + .../edk2/MdePkg/Include/Ppi/BlockIo.h | 238 + .../edk2/MdePkg/Include/Ppi/BlockIo2.h | 223 + .../MdePkg/Include/Ppi/BootInRecoveryMode.h | 30 + .../edk2/MdePkg/Include/Ppi/Capsule.h | 136 + .../edk2/MdePkg/Include/Ppi/CpuIo.h | 428 + .../edk2/MdePkg/Include/Ppi/Decompress.h | 74 + .../MdePkg/Include/Ppi/DeviceRecoveryModule.h | 144 + .../edk2/MdePkg/Include/Ppi/DxeIpl.h | 72 + .../edk2/MdePkg/Include/Ppi/EndOfPeiPhase.h | 31 + .../edk2/MdePkg/Include/Ppi/FirmwareVolume.h | 294 + .../MdePkg/Include/Ppi/FirmwareVolumeInfo.h | 68 + .../MdePkg/Include/Ppi/FirmwareVolumeInfo2.h | 72 + .../edk2/MdePkg/Include/Ppi/Graphics.h | 85 + .../Include/Ppi/GuidedSectionExtraction.h | 104 + .../edk2/MdePkg/Include/Ppi/I2cMaster.h | 108 + .../edk2/MdePkg/Include/Ppi/IsaHc.h | 119 + .../edk2/MdePkg/Include/Ppi/LoadFile.h | 77 + .../edk2/MdePkg/Include/Ppi/LoadImage.h | 52 + .../edk2/MdePkg/Include/Ppi/MasterBootMode.h | 32 + .../MdePkg/Include/Ppi/MemoryDiscovered.h | 32 + .../edk2/MdePkg/Include/Ppi/MpServices.h | 283 + .../edk2/MdePkg/Include/Ppi/Pcd.h | 860 ++ .../edk2/MdePkg/Include/Ppi/PcdInfo.h | 105 + .../edk2/MdePkg/Include/Ppi/PciCfg2.h | 184 + .../MdePkg/Include/Ppi/PeiCoreFvLocation.h | 48 + .../edk2/MdePkg/Include/Ppi/PiPcd.h | 432 + .../edk2/MdePkg/Include/Ppi/PiPcdInfo.h | 82 + .../MdePkg/Include/Ppi/ReadOnlyVariable2.h | 117 + .../edk2/MdePkg/Include/Ppi/RecoveryModule.h | 87 + .../Include/Ppi/ReportStatusCodeHandler.h | 82 + .../edk2/MdePkg/Include/Ppi/Reset.h | 44 + .../edk2/MdePkg/Include/Ppi/Reset2.h | 38 + .../edk2/MdePkg/Include/Ppi/S3Resume2.h | 92 + .../edk2/MdePkg/Include/Ppi/SecHobData.h | 65 + .../Include/Ppi/SecPlatformInformation.h | 188 + .../Include/Ppi/SecPlatformInformation2.h | 85 + .../edk2/MdePkg/Include/Ppi/Security2.h | 101 + .../edk2/MdePkg/Include/Ppi/Smbus2.h | 203 + .../edk2/MdePkg/Include/Ppi/Stall.h | 62 + .../edk2/MdePkg/Include/Ppi/StatusCode.h | 41 + .../edk2/MdePkg/Include/Ppi/SuperIo.h | 189 + .../MdePkg/Include/Ppi/TemporaryRamDone.h | 52 + .../MdePkg/Include/Ppi/TemporaryRamSupport.h | 66 + .../MdePkg/Include/Ppi/VectorHandoffInfo.h | 75 + .../MdePkg/Include/Protocol/AbsolutePointer.h | 208 + .../Protocol/AcpiSystemDescriptionTable.h | 269 + .../edk2/MdePkg/Include/Protocol/AcpiTable.h | 130 + .../Include/Protocol/AdapterInformation.h | 260 + .../edk2/MdePkg/Include/Protocol/Arp.h | 385 + .../MdePkg/Include/Protocol/AtaPassThru.h | 474 + .../Include/Protocol/AuthenticationInfo.h | 237 + .../edk2/MdePkg/Include/Protocol/Bds.h | 72 + .../edk2/MdePkg/Include/Protocol/Bis.h | 451 + .../edk2/MdePkg/Include/Protocol/BlockIo.h | 241 + .../edk2/MdePkg/Include/Protocol/BlockIo2.h | 206 + .../MdePkg/Include/Protocol/BlockIoCrypto.h | 530 ++ .../Include/Protocol/BluetoothAttribute.h | 283 + .../MdePkg/Include/Protocol/BluetoothConfig.h | 529 ++ .../MdePkg/Include/Protocol/BluetoothHc.h | 424 + .../MdePkg/Include/Protocol/BluetoothIo.h | 417 + .../Include/Protocol/BluetoothLeConfig.h | 634 ++ .../Include/Protocol/BootManagerPolicy.h | 138 + .../Protocol/BusSpecificDriverOverride.h | 72 + .../edk2/MdePkg/Include/Protocol/Capsule.h | 35 + .../MdePkg/Include/Protocol/ComponentName.h | 129 + .../MdePkg/Include/Protocol/ComponentName2.h | 172 + .../edk2/MdePkg/Include/Protocol/Cpu.h | 300 + .../edk2/MdePkg/Include/Protocol/CpuIo2.h | 142 + .../edk2/MdePkg/Include/Protocol/DebugPort.h | 146 + .../MdePkg/Include/Protocol/DebugSupport.h | 778 ++ .../edk2/MdePkg/Include/Protocol/Decompress.h | 122 + .../Include/Protocol/DeferredImageLoad.h | 80 + .../edk2/MdePkg/Include/Protocol/DeviceIo.h | 268 + .../edk2/MdePkg/Include/Protocol/DevicePath.h | 1358 +++ .../Include/Protocol/DevicePathFromText.h | 72 + .../Include/Protocol/DevicePathToText.h | 85 + .../Include/Protocol/DevicePathUtilities.h | 192 + .../edk2/MdePkg/Include/Protocol/Dhcp4.h | 780 ++ .../edk2/MdePkg/Include/Protocol/Dhcp6.h | 786 ++ .../edk2/MdePkg/Include/Protocol/DiskInfo.h | 227 + .../edk2/MdePkg/Include/Protocol/DiskIo.h | 117 + .../edk2/MdePkg/Include/Protocol/DiskIo2.h | 172 + .../edk2/MdePkg/Include/Protocol/Dns4.h | 543 ++ .../edk2/MdePkg/Include/Protocol/Dns6.h | 539 ++ .../MdePkg/Include/Protocol/DriverBinding.h | 201 + .../Include/Protocol/DriverConfiguration.h | 167 + .../Include/Protocol/DriverConfiguration2.h | 190 + .../Include/Protocol/DriverDiagnostics.h | 131 + .../Include/Protocol/DriverDiagnostics2.h | 111 + .../Include/Protocol/DriverFamilyOverride.h | 66 + .../MdePkg/Include/Protocol/DriverHealth.h | 247 + .../Protocol/DriverSupportedEfiVersion.h | 46 + .../Include/Protocol/DxeMmReadyToLock.h | 25 + .../Include/Protocol/DxeSmmReadyToLock.h | 40 + .../edk2/MdePkg/Include/Protocol/Eap.h | 162 + .../Include/Protocol/EapConfiguration.h | 159 + .../MdePkg/Include/Protocol/EapManagement.h | 403 + .../MdePkg/Include/Protocol/EapManagement2.h | 87 + .../edk2/MdePkg/Include/Protocol/Ebc.h | 314 + .../edk2/MdePkg/Include/Protocol/EdidActive.h | 52 + .../MdePkg/Include/Protocol/EdidDiscovered.h | 50 + .../MdePkg/Include/Protocol/EdidOverride.h | 67 + .../edk2/MdePkg/Include/Protocol/EraseBlock.h | 105 + .../Include/Protocol/ExtendedSalBootService.h | 217 + .../Protocol/ExtendedSalServiceClasses.h | 278 + .../Include/Protocol/FirmwareManagement.h | 539 ++ .../MdePkg/Include/Protocol/FirmwareVolume2.h | 762 ++ .../Include/Protocol/FirmwareVolumeBlock.h | 366 + .../MdePkg/Include/Protocol/FormBrowser2.h | 180 + .../edk2/MdePkg/Include/Protocol/Ftp4.h | 524 ++ .../MdePkg/Include/Protocol/GraphicsOutput.h | 276 + .../Protocol/GuidedSectionExtraction.h | 141 + .../edk2/MdePkg/Include/Protocol/Hash.h | 175 + .../edk2/MdePkg/Include/Protocol/Hash2.h | 202 + .../MdePkg/Include/Protocol/HiiConfigAccess.h | 226 + .../Include/Protocol/HiiConfigKeyword.h | 205 + .../Include/Protocol/HiiConfigRouting.h | 423 + .../MdePkg/Include/Protocol/HiiDatabase.h | 534 ++ .../edk2/MdePkg/Include/Protocol/HiiFont.h | 475 + .../edk2/MdePkg/Include/Protocol/HiiImage.h | 359 + .../MdePkg/Include/Protocol/HiiImageDecoder.h | 206 + .../edk2/MdePkg/Include/Protocol/HiiImageEx.h | 254 + .../MdePkg/Include/Protocol/HiiPackageList.h | 33 + .../edk2/MdePkg/Include/Protocol/HiiPopup.h | 84 + .../edk2/MdePkg/Include/Protocol/HiiString.h | 244 + .../edk2/MdePkg/Include/Protocol/Http.h | 522 ++ .../Include/Protocol/HttpBootCallback.h | 100 + .../MdePkg/Include/Protocol/HttpUtilities.h | 124 + .../Protocol/I2cBusConfigurationManagement.h | 171 + .../MdePkg/Include/Protocol/I2cEnumerate.h | 110 + .../edk2/MdePkg/Include/Protocol/I2cHost.h | 152 + .../edk2/MdePkg/Include/Protocol/I2cIo.h | 172 + .../edk2/MdePkg/Include/Protocol/I2cMaster.h | 192 + .../Include/Protocol/IScsiInitiatorName.h | 87 + .../Include/Protocol/IdeControllerInit.h | 565 ++ .../Protocol/IncompatiblePciDeviceSupport.h | 173 + .../edk2/MdePkg/Include/Protocol/Ip4.h | 612 ++ .../edk2/MdePkg/Include/Protocol/Ip4Config.h | 182 + .../edk2/MdePkg/Include/Protocol/Ip4Config2.h | 323 + .../edk2/MdePkg/Include/Protocol/Ip6.h | 953 ++ .../edk2/MdePkg/Include/Protocol/Ip6Config.h | 374 + .../edk2/MdePkg/Include/Protocol/IpSec.h | 224 + .../MdePkg/Include/Protocol/IpSecConfig.h | 807 ++ .../edk2/MdePkg/Include/Protocol/IsaHc.h | 116 + .../edk2/MdePkg/Include/Protocol/Kms.h | 1343 +++ .../MdePkg/Include/Protocol/LegacyRegion2.h | 239 + .../Include/Protocol/LegacySpiController.h | 265 + .../MdePkg/Include/Protocol/LegacySpiFlash.h | 201 + .../Include/Protocol/LegacySpiSmmController.h | 36 + .../Include/Protocol/LegacySpiSmmFlash.h | 36 + .../edk2/MdePkg/Include/Protocol/LoadFile.h | 88 + .../edk2/MdePkg/Include/Protocol/LoadFile2.h | 85 + .../MdePkg/Include/Protocol/LoadedImage.h | 88 + .../MdePkg/Include/Protocol/ManagedNetwork.h | 372 + .../edk2/MdePkg/Include/Protocol/McaInitPmi.h | 207 + .../edk2/MdePkg/Include/Protocol/Metronome.h | 80 + .../edk2/MdePkg/Include/Protocol/MmAccess.h | 133 + .../edk2/MdePkg/Include/Protocol/MmBase.h | 87 + .../MdePkg/Include/Protocol/MmCommunication.h | 93 + .../MdePkg/Include/Protocol/MmConfiguration.h | 86 + .../edk2/MdePkg/Include/Protocol/MmControl.h | 106 + .../edk2/MdePkg/Include/Protocol/MmCpu.h | 247 + .../edk2/MdePkg/Include/Protocol/MmCpuIo.h | 96 + .../edk2/MdePkg/Include/Protocol/MmEndOfDxe.h | 30 + .../MdePkg/Include/Protocol/MmGpiDispatch.h | 125 + .../Include/Protocol/MmIoTrapDispatch.h | 136 + .../Include/Protocol/MmPciRootBridgeIo.h | 37 + .../Protocol/MmPeriodicTimerDispatch.h | 170 + .../Include/Protocol/MmPowerButtonDispatch.h | 117 + .../MdePkg/Include/Protocol/MmReadyToLock.h | 32 + .../Protocol/MmReportStatusCodeHandler.h | 84 + .../Protocol/MmStandbyButtonDispatch.h | 119 + .../MdePkg/Include/Protocol/MmStatusCode.h | 65 + .../MdePkg/Include/Protocol/MmSwDispatch.h | 136 + .../MdePkg/Include/Protocol/MmSxDispatch.h | 135 + .../MdePkg/Include/Protocol/MmUsbDispatch.h | 130 + .../Include/Protocol/MonotonicCounter.h | 28 + .../edk2/MdePkg/Include/Protocol/MpService.h | 632 ++ .../edk2/MdePkg/Include/Protocol/Mtftp4.h | 593 ++ .../edk2/MdePkg/Include/Protocol/Mtftp6.h | 826 ++ .../Protocol/NetworkInterfaceIdentifier.h | 118 + .../MdePkg/Include/Protocol/NvdimmLabel.h | 351 + .../Include/Protocol/NvmExpressPassthru.h | 289 + .../MdePkg/Include/Protocol/PartitionInfo.h | 74 + .../edk2/MdePkg/Include/Protocol/Pcd.h | 867 ++ .../edk2/MdePkg/Include/Protocol/PcdInfo.h | 108 + .../Include/Protocol/PciEnumerationComplete.h | 30 + .../PciHostBridgeResourceAllocation.h | 428 + .../MdePkg/Include/Protocol/PciHotPlugInit.h | 278 + .../Include/Protocol/PciHotPlugRequest.h | 170 + .../edk2/MdePkg/Include/Protocol/PciIo.h | 557 ++ .../MdePkg/Include/Protocol/PciOverride.h | 46 + .../MdePkg/Include/Protocol/PciPlatform.h | 344 + .../MdePkg/Include/Protocol/PciRootBridgeIo.h | 442 + .../edk2/MdePkg/Include/Protocol/PiPcd.h | 424 + .../edk2/MdePkg/Include/Protocol/PiPcdInfo.h | 83 + .../MdePkg/Include/Protocol/Pkcs7Verify.h | 229 + .../Include/Protocol/PlatformDriverOverride.h | 140 + .../Protocol/PlatformToDriverConfiguration.h | 355 + .../MdePkg/Include/Protocol/PxeBaseCode.h | 932 ++ .../Include/Protocol/PxeBaseCodeCallBack.h | 130 + .../edk2/MdePkg/Include/Protocol/RamDisk.h | 106 + .../MdePkg/Include/Protocol/RealTimeClock.h | 36 + .../Protocol/RegularExpressionProtocol.h | 181 + .../Protocol/ReportStatusCodeHandler.h | 97 + .../edk2/MdePkg/Include/Protocol/Reset.h | 31 + .../Include/Protocol/ResetNotification.h | 86 + .../edk2/MdePkg/Include/Protocol/Rest.h | 94 + .../edk2/MdePkg/Include/Protocol/Rng.h | 156 + .../edk2/MdePkg/Include/Protocol/Runtime.h | 128 + .../MdePkg/Include/Protocol/S3SaveState.h | 176 + .../MdePkg/Include/Protocol/S3SmmSaveState.h | 46 + .../edk2/MdePkg/Include/Protocol/ScsiIo.h | 317 + .../MdePkg/Include/Protocol/ScsiPassThru.h | 383 + .../MdePkg/Include/Protocol/ScsiPassThruExt.h | 394 + .../MdePkg/Include/Protocol/SdMmcPassThru.h | 264 + .../edk2/MdePkg/Include/Protocol/Security.h | 103 + .../edk2/MdePkg/Include/Protocol/Security2.h | 107 + .../MdePkg/Include/Protocol/SecurityPolicy.h | 26 + .../edk2/MdePkg/Include/Protocol/SerialIo.h | 300 + .../MdePkg/Include/Protocol/ServiceBinding.h | 94 + .../edk2/MdePkg/Include/Protocol/Shell.h | 1268 +++ .../Include/Protocol/ShellDynamicCommand.h | 85 + .../MdePkg/Include/Protocol/ShellParameters.h | 60 + .../Include/Protocol/SimpleFileSystem.h | 562 ++ .../MdePkg/Include/Protocol/SimpleNetwork.h | 681 ++ .../MdePkg/Include/Protocol/SimplePointer.h | 143 + .../MdePkg/Include/Protocol/SimpleTextIn.h | 133 + .../MdePkg/Include/Protocol/SimpleTextInEx.h | 323 + .../MdePkg/Include/Protocol/SimpleTextOut.h | 415 + .../MdePkg/Include/Protocol/SmartCardEdge.h | 742 ++ .../MdePkg/Include/Protocol/SmartCardReader.h | 325 + .../edk2/MdePkg/Include/Protocol/Smbios.h | 213 + .../edk2/MdePkg/Include/Protocol/SmbusHc.h | 295 + .../edk2/MdePkg/Include/Protocol/SmmAccess2.h | 44 + .../edk2/MdePkg/Include/Protocol/SmmBase2.h | 85 + .../Include/Protocol/SmmCommunication.h | 33 + .../Include/Protocol/SmmConfiguration.h | 84 + .../MdePkg/Include/Protocol/SmmControl2.h | 41 + .../edk2/MdePkg/Include/Protocol/SmmCpu.h | 136 + .../edk2/MdePkg/Include/Protocol/SmmCpuIo2.h | 41 + .../MdePkg/Include/Protocol/SmmEndOfDxe.h | 32 + .../MdePkg/Include/Protocol/SmmGpiDispatch2.h | 49 + .../Include/Protocol/SmmIoTrapDispatch2.h | 53 + .../Include/Protocol/SmmPciRootBridgeIo.h | 34 + .../Protocol/SmmPeriodicTimerDispatch2.h | 162 + .../Protocol/SmmPowerButtonDispatch2.h | 42 + .../MdePkg/Include/Protocol/SmmReadyToLock.h | 34 + .../Protocol/SmmReportStatusCodeHandler.h | 35 + .../Protocol/SmmStandbyButtonDispatch2.h | 42 + .../MdePkg/Include/Protocol/SmmStatusCode.h | 31 + .../MdePkg/Include/Protocol/SmmSwDispatch2.h | 134 + .../MdePkg/Include/Protocol/SmmSxDispatch2.h | 38 + .../MdePkg/Include/Protocol/SmmUsbDispatch2.h | 47 + .../Include/Protocol/SpiConfiguration.h | 293 + .../edk2/MdePkg/Include/Protocol/SpiHc.h | 194 + .../edk2/MdePkg/Include/Protocol/SpiIo.h | 292 + .../MdePkg/Include/Protocol/SpiNorFlash.h | 262 + .../Include/Protocol/SpiSmmConfiguration.h | 36 + .../edk2/MdePkg/Include/Protocol/SpiSmmHc.h | 36 + .../MdePkg/Include/Protocol/SpiSmmNorFlash.h | 36 + .../edk2/MdePkg/Include/Protocol/StatusCode.h | 59 + .../Include/Protocol/StorageSecurityCommand.h | 212 + .../edk2/MdePkg/Include/Protocol/SuperIo.h | 175 + .../MdePkg/Include/Protocol/SuperIoControl.h | 92 + .../edk2/MdePkg/Include/Protocol/Supplicant.h | 464 + .../edk2/MdePkg/Include/Protocol/TapeIo.h | 237 + .../MdePkg/Include/Protocol/Tcg2Protocol.h | 341 + .../edk2/MdePkg/Include/Protocol/TcgService.h | 201 + .../edk2/MdePkg/Include/Protocol/Tcp4.h | 577 ++ .../edk2/MdePkg/Include/Protocol/Tcp6.h | 864 ++ .../edk2/MdePkg/Include/Protocol/Timer.h | 180 + .../edk2/MdePkg/Include/Protocol/Timestamp.h | 101 + .../edk2/MdePkg/Include/Protocol/Tls.h | 471 + .../edk2/MdePkg/Include/Protocol/TlsConfig.h | 133 + .../MdePkg/Include/Protocol/TrEEProtocol.h | 249 + .../edk2/MdePkg/Include/Protocol/Udp4.h | 445 + .../edk2/MdePkg/Include/Protocol/Udp6.h | 580 ++ .../MdePkg/Include/Protocol/UfsDeviceConfig.h | 143 + .../edk2/MdePkg/Include/Protocol/UgaDraw.h | 166 + .../edk2/MdePkg/Include/Protocol/UgaIo.h | 197 + .../Include/Protocol/UnicodeCollation.h | 192 + .../Include/Protocol/Usb2HostController.h | 664 ++ .../MdePkg/Include/Protocol/UsbFunctionIo.h | 690 ++ .../Include/Protocol/UsbHostController.h | 508 ++ .../edk2/MdePkg/Include/Protocol/UsbIo.h | 512 ++ .../MdePkg/Include/Protocol/UserCredential.h | 292 + .../MdePkg/Include/Protocol/UserCredential2.h | 314 + .../MdePkg/Include/Protocol/UserManager.h | 624 ++ .../edk2/MdePkg/Include/Protocol/Variable.h | 45 + .../MdePkg/Include/Protocol/VariableWrite.h | 45 + .../edk2/MdePkg/Include/Protocol/VlanConfig.h | 143 + .../MdePkg/Include/Protocol/WatchdogTimer.h | 144 + .../edk2/MdePkg/Include/Protocol/WiFi.h | 1129 +++ .../edk2/MdePkg/Include/Protocol/WiFi2.h | 413 + .../edk2/MdePkg/Include/Uefi.h | 27 + .../MdePkg/Include/Uefi/UefiAcpiDataTable.h | 29 + .../edk2/MdePkg/Include/Uefi/UefiBaseType.h | 291 + .../edk2/MdePkg/Include/Uefi/UefiGpt.h | 145 + .../Uefi/UefiInternalFormRepresentation.h | 2135 +++++ .../edk2/MdePkg/Include/Uefi/UefiMultiPhase.h | 235 + .../edk2/MdePkg/Include/Uefi/UefiPxe.h | 1792 ++++ .../edk2/MdePkg/Include/Uefi/UefiSpec.h | 2213 +++++ .../edk2/MdePkg/Include/X64/Nasm.inc | 28 + .../edk2/MdePkg/Include/X64/ProcessorBind.h | 347 + .../BaseCacheMaintenanceLib/ArmCache.c | 247 + .../BaseCacheMaintenanceLib.inf | 55 + .../BaseCacheMaintenanceLib.uni | 23 + .../BaseCacheMaintenanceLib/EbcCache.c | 231 + .../BaseCacheMaintenanceLib/X86Cache.c | 278 + .../Library/BaseCpuLib/AArch64/CpuFlushTlb.S | 38 + .../BaseCpuLib/AArch64/CpuFlushTlb.asm | 39 + .../Library/BaseCpuLib/AArch64/CpuSleep.S | 39 + .../Library/BaseCpuLib/AArch64/CpuSleep.asm | 40 + .../Library/BaseCpuLib/Arm/CpuFlushTlb.S | 36 + .../Library/BaseCpuLib/Arm/CpuFlushTlb.asm | 37 + .../MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S | 43 + .../Library/BaseCpuLib/Arm/CpuSleep.asm | 44 + .../MdePkg/Library/BaseCpuLib/BaseCpuLib.inf | 74 + .../MdePkg/Library/BaseCpuLib/BaseCpuLib.uni | 24 + .../Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c | 46 + .../Library/BaseCpuLib/Ia32/CpuFlushTlb.c | 34 + .../Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm | 37 + .../Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c | 32 + .../MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c | 34 + .../Library/BaseCpuLib/Ia32/CpuSleep.nasm | 36 + .../Library/BaseCpuLib/Ia32/CpuSleepGcc.c | 33 + .../Library/BaseCpuLib/X64/CpuFlushTlb.S | 35 + .../Library/BaseCpuLib/X64/CpuFlushTlb.nasm | 38 + .../MdePkg/Library/BaseCpuLib/X64/CpuSleep.S | 34 + .../Library/BaseCpuLib/X64/CpuSleep.nasm | 37 + .../BaseDebugLibNull/BaseDebugLibNull.inf | 36 + .../BaseDebugLibNull/BaseDebugLibNull.uni | 21 + .../Library/BaseDebugLibNull/DebugLib.c | 198 + .../BaseDebugLibSerialPort.inf | 49 + .../BaseDebugLibSerialPort.uni | 21 + .../Library/BaseDebugLibSerialPort/DebugLib.c | 284 + .../BaseDebugPrintErrorLevelLib.c | 59 + .../BaseDebugPrintErrorLevelLib.inf | 40 + .../BaseDebugPrintErrorLevelLib.uni | 21 + .../BaseExtractGuidedSectionLib.c | 484 + .../BaseExtractGuidedSectionLib.inf | 54 + .../BaseExtractGuidedSectionLib.uni | 27 + .../BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S | 148 + .../AArch64/ArmVirtMmio.asm | 149 + .../BaseIoLibIntrinsic/Arm/ArmVirtMmio.S | 147 + .../BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm | 151 + .../BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf | 71 + .../BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni | 24 + .../BaseIoLibIntrinsicArmVirt.inf | 52 + .../BaseIoLibIntrinsicArmVirt.uni | 23 + .../BaseIoLibIntrinsicInternal.h | 26 + .../BaseIoLibIntrinsicSev.inf | 59 + .../BaseIoLibIntrinsic/Ia32/IoFifo.nasm | 137 + .../BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm | 299 + .../Library/BaseIoLibIntrinsic/IoHighLevel.c | 2356 +++++ .../MdePkg/Library/BaseIoLibIntrinsic/IoLib.c | 317 + .../Library/BaseIoLibIntrinsic/IoLibArm.c | 599 ++ .../Library/BaseIoLibIntrinsic/IoLibArmVirt.c | 733 ++ .../Library/BaseIoLibIntrinsic/IoLibEbc.c | 342 + .../Library/BaseIoLibIntrinsic/IoLibGcc.c | 196 + .../Library/BaseIoLibIntrinsic/IoLibIcc.c | 214 + .../BaseIoLibIntrinsic/IoLibMmioBuffer.c | 411 + .../Library/BaseIoLibIntrinsic/IoLibMsc.c | 228 + .../BaseIoLibIntrinsic/X64/IoFifo.nasm | 126 + .../BaseIoLibIntrinsic/X64/IoFifoSev.nasm | 288 + .../Library/BaseLib/AArch64/CpuBreakpoint.S | 37 + .../Library/BaseLib/AArch64/CpuBreakpoint.asm | 39 + .../BaseLib/AArch64/DisableInterrupts.S | 36 + .../BaseLib/AArch64/DisableInterrupts.asm | 37 + .../BaseLib/AArch64/EnableInterrupts.S | 36 + .../BaseLib/AArch64/EnableInterrupts.asm | 37 + .../BaseLib/AArch64/GetInterruptsState.S | 45 + .../BaseLib/AArch64/GetInterruptsState.asm | 49 + .../Library/BaseLib/AArch64/MemoryFence.S | 39 + .../Library/BaseLib/AArch64/MemoryFence.asm | 38 + .../Library/BaseLib/AArch64/SetJumpLongJump.S | 97 + .../BaseLib/AArch64/SetJumpLongJump.asm | 101 + .../BaseLib/AArch64/SpeculationBarrier.S | 39 + .../BaseLib/AArch64/SpeculationBarrier.asm | 38 + .../Library/BaseLib/AArch64/SwitchStack.S | 71 + .../Library/BaseLib/AArch64/SwitchStack.asm | 71 + .../edk2/MdePkg/Library/BaseLib/ARShiftU64.c | 41 + .../Library/BaseLib/Arm/CpuBreakpoint.S | 36 + .../Library/BaseLib/Arm/CpuBreakpoint.asm | 41 + .../MdePkg/Library/BaseLib/Arm/CpuPause.asm | 41 + .../Library/BaseLib/Arm/DisableInterrupts.S | 35 + .../Library/BaseLib/Arm/DisableInterrupts.asm | 37 + .../Library/BaseLib/Arm/EnableInterrupts.S | 36 + .../Library/BaseLib/Arm/EnableInterrupts.asm | 37 + .../Library/BaseLib/Arm/GetInterruptsState.S | 43 + .../BaseLib/Arm/GetInterruptsState.asm | 45 + .../Library/BaseLib/Arm/InternalSwitchStack.c | 79 + .../edk2/MdePkg/Library/BaseLib/Arm/Math64.S | 269 + .../MdePkg/Library/BaseLib/Arm/MemoryFence.S | 39 + .../Library/BaseLib/Arm/MemoryFence.asm | 39 + .../Library/BaseLib/Arm/SetJumpLongJump.S | 70 + .../Library/BaseLib/Arm/SetJumpLongJump.asm | 70 + .../Library/BaseLib/Arm/SpeculationBarrier.S | 39 + .../BaseLib/Arm/SpeculationBarrier.asm | 39 + .../MdePkg/Library/BaseLib/Arm/SwitchStack.S | 68 + .../Library/BaseLib/Arm/SwitchStack.asm | 45 + .../MdePkg/Library/BaseLib/Arm/Unaligned.c | 252 + .../edk2/MdePkg/Library/BaseLib/BaseLib.inf | 626 ++ .../edk2/MdePkg/Library/BaseLib/BaseLib.uni | 23 + .../MdePkg/Library/BaseLib/BaseLibInternals.h | 875 ++ .../edk2/MdePkg/Library/BaseLib/BitField.c | 1008 +++ .../edk2/MdePkg/Library/BaseLib/CheckSum.c | 632 ++ .../edk2/MdePkg/Library/BaseLib/ChkStkGcc.c | 24 + .../edk2/MdePkg/Library/BaseLib/Cpu.c | 65 + .../edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c | 38 + .../Library/BaseLib/DivS64x64Remainder.c | 53 + .../edk2/MdePkg/Library/BaseLib/DivU64x32.c | 45 + .../Library/BaseLib/DivU64x32Remainder.c | 49 + .../Library/BaseLib/DivU64x64Remainder.c | 49 + .../Library/BaseLib/Ebc/CpuBreakpoint.c | 129 + .../Library/BaseLib/Ebc/SetJumpLongJump.c | 68 + .../Library/BaseLib/Ebc/SpeculationBarrier.c | 30 + .../MdePkg/Library/BaseLib/Ebc/SwitchStack.c | 58 + .../edk2/MdePkg/Library/BaseLib/FilePaths.c | 121 + .../MdePkg/Library/BaseLib/GetPowerOfTwo32.c | 44 + .../MdePkg/Library/BaseLib/GetPowerOfTwo64.c | 44 + .../MdePkg/Library/BaseLib/HighBitSet32.c | 47 + .../MdePkg/Library/BaseLib/HighBitSet64.c | 55 + .../MdePkg/Library/BaseLib/Ia32/ARShiftU64.S | 43 + .../MdePkg/Library/BaseLib/Ia32/ARShiftU64.c | 51 + .../Library/BaseLib/Ia32/ARShiftU64.nasm | 45 + .../Library/BaseLib/Ia32/CpuBreakpoint.c | 41 + .../Library/BaseLib/Ia32/CpuBreakpoint.nasm | 36 + .../edk2/MdePkg/Library/BaseLib/Ia32/CpuId.S | 63 + .../edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c | 74 + .../MdePkg/Library/BaseLib/Ia32/CpuId.nasm | 65 + .../MdePkg/Library/BaseLib/Ia32/CpuIdEx.S | 67 + .../MdePkg/Library/BaseLib/Ia32/CpuIdEx.c | 82 + .../MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm | 67 + .../MdePkg/Library/BaseLib/Ia32/CpuPause.c | 35 + .../MdePkg/Library/BaseLib/Ia32/CpuPause.nasm | 36 + .../Library/BaseLib/Ia32/DisableCache.S | 39 + .../Library/BaseLib/Ia32/DisableCache.c | 36 + .../Library/BaseLib/Ia32/DisableCache.nasm | 42 + .../Library/BaseLib/Ia32/DisableInterrupts.c | 32 + .../BaseLib/Ia32/DisableInterrupts.nasm | 37 + .../Library/BaseLib/Ia32/DisablePaging32.S | 52 + .../Library/BaseLib/Ia32/DisablePaging32.c | 77 + .../Library/BaseLib/Ia32/DisablePaging32.nasm | 54 + .../Library/BaseLib/Ia32/DivS64x64Remainder.c | 53 + .../MdePkg/Library/BaseLib/Ia32/DivU64x32.S | 41 + .../MdePkg/Library/BaseLib/Ia32/DivU64x32.c | 50 + .../Library/BaseLib/Ia32/DivU64x32.nasm | 43 + .../Library/BaseLib/Ia32/DivU64x32Remainder.S | 46 + .../Library/BaseLib/Ia32/DivU64x32Remainder.c | 55 + .../BaseLib/Ia32/DivU64x32Remainder.nasm | 48 + .../Library/BaseLib/Ia32/DivU64x64Remainder.S | 89 + .../BaseLib/Ia32/DivU64x64Remainder.nasm | 94 + .../MdePkg/Library/BaseLib/Ia32/EnableCache.S | 39 + .../MdePkg/Library/BaseLib/Ia32/EnableCache.c | 36 + .../Library/BaseLib/Ia32/EnableCache.nasm | 42 + .../BaseLib/Ia32/EnableDisableInterrupts.S | 36 + .../BaseLib/Ia32/EnableDisableInterrupts.c | 36 + .../BaseLib/Ia32/EnableDisableInterrupts.nasm | 38 + .../Library/BaseLib/Ia32/EnableInterrupts.c | 32 + .../BaseLib/Ia32/EnableInterrupts.nasm | 37 + .../Library/BaseLib/Ia32/EnablePaging32.S | 52 + .../Library/BaseLib/Ia32/EnablePaging32.c | 81 + .../Library/BaseLib/Ia32/EnablePaging32.nasm | 54 + .../Library/BaseLib/Ia32/EnablePaging64.S | 63 + .../Library/BaseLib/Ia32/EnablePaging64.nasm | 65 + .../Library/BaseLib/Ia32/FlushCacheLine.c | 58 + .../Library/BaseLib/Ia32/FlushCacheLine.nasm | 51 + .../MdePkg/Library/BaseLib/Ia32/FxRestore.c | 40 + .../Library/BaseLib/Ia32/FxRestore.nasm | 38 + .../edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c | 40 + .../MdePkg/Library/BaseLib/Ia32/FxSave.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/GccInline.c | 1771 ++++ .../BaseLib/Ia32/InternalSwitchStack.S | 48 + .../BaseLib/Ia32/InternalSwitchStack.c | 60 + .../BaseLib/Ia32/InternalSwitchStack.nasm | 47 + .../edk2/MdePkg/Library/BaseLib/Ia32/Invd.c | 35 + .../MdePkg/Library/BaseLib/Ia32/Invd.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/LRotU64.S | 48 + .../MdePkg/Library/BaseLib/Ia32/LRotU64.c | 55 + .../MdePkg/Library/BaseLib/Ia32/LRotU64.nasm | 50 + .../MdePkg/Library/BaseLib/Ia32/LShiftU64.S | 43 + .../MdePkg/Library/BaseLib/Ia32/LShiftU64.c | 51 + .../Library/BaseLib/Ia32/LShiftU64.nasm | 45 + .../MdePkg/Library/BaseLib/Ia32/Lfence.nasm | 36 + .../MdePkg/Library/BaseLib/Ia32/LongJump.S | 41 + .../MdePkg/Library/BaseLib/Ia32/LongJump.c | 76 + .../MdePkg/Library/BaseLib/Ia32/LongJump.nasm | 66 + .../MdePkg/Library/BaseLib/Ia32/ModU64x32.S | 40 + .../MdePkg/Library/BaseLib/Ia32/ModU64x32.c | 48 + .../Library/BaseLib/Ia32/ModU64x32.nasm | 42 + .../MdePkg/Library/BaseLib/Ia32/Monitor.S | 40 + .../MdePkg/Library/BaseLib/Ia32/Monitor.c | 48 + .../MdePkg/Library/BaseLib/Ia32/Monitor.nasm | 42 + .../MdePkg/Library/BaseLib/Ia32/MultU64x32.S | 41 + .../MdePkg/Library/BaseLib/Ia32/MultU64x32.c | 47 + .../Library/BaseLib/Ia32/MultU64x32.nasm | 40 + .../MdePkg/Library/BaseLib/Ia32/MultU64x64.S | 44 + .../MdePkg/Library/BaseLib/Ia32/MultU64x64.c | 51 + .../Library/BaseLib/Ia32/MultU64x64.nasm | 46 + .../edk2/MdePkg/Library/BaseLib/Ia32/Mwait.S | 38 + .../edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c | 44 + .../MdePkg/Library/BaseLib/Ia32/Mwait.nasm | 40 + .../Library/BaseLib/Ia32/Non-existing.c | 57 + .../MdePkg/Library/BaseLib/Ia32/RRotU64.S | 48 + .../MdePkg/Library/BaseLib/Ia32/RRotU64.c | 55 + .../MdePkg/Library/BaseLib/Ia32/RRotU64.nasm | 50 + .../MdePkg/Library/BaseLib/Ia32/RShiftU64.S | 46 + .../MdePkg/Library/BaseLib/Ia32/RShiftU64.c | 51 + .../Library/BaseLib/Ia32/RShiftU64.nasm | 45 + .../edk2/MdePkg/Library/BaseLib/Ia32/RdRand.S | 80 + .../MdePkg/Library/BaseLib/Ia32/RdRand.nasm | 90 + .../MdePkg/Library/BaseLib/Ia32/ReadCr0.c | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadCr2.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadCr3.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadCr4.c | 40 + .../MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm | 37 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadCs.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadDr0.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadDr1.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadDr2.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadDr3.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadDr4.c | 40 + .../MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm | 44 + .../MdePkg/Library/BaseLib/Ia32/ReadDr5.c | 40 + .../MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm | 44 + .../MdePkg/Library/BaseLib/Ia32/ReadDr6.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadDr7.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm | 37 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadDs.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadEflags.c | 39 + .../Library/BaseLib/Ia32/ReadEflags.nasm | 38 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadEs.nasm | 37 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadFs.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadGdtr.c | 39 + .../MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm | 38 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadGs.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadIdtr.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadLdtr.c | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadMm0.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm1.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm2.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm3.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm4.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm5.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm6.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMm7.c | 42 + .../MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/ReadMsr64.c | 43 + .../Library/BaseLib/Ia32/ReadMsr64.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadPmc.c | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm | 38 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c | 38 + .../MdePkg/Library/BaseLib/Ia32/ReadSs.nasm | 37 + .../edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadTr.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadTsc.c | 37 + .../MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/SetJump.S | 44 + .../MdePkg/Library/BaseLib/Ia32/SetJump.c | 101 + .../MdePkg/Library/BaseLib/Ia32/SetJump.nasm | 69 + .../MdePkg/Library/BaseLib/Ia32/SwapBytes64.S | 38 + .../MdePkg/Library/BaseLib/Ia32/SwapBytes64.c | 43 + .../Library/BaseLib/Ia32/SwapBytes64.nasm | 40 + .../MdePkg/Library/BaseLib/Ia32/Thunk16.S | 222 + .../MdePkg/Library/BaseLib/Ia32/Thunk16.nasm | 263 + .../edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c | 35 + .../MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteCr0.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteCr2.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteCr3.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteCr4.c | 39 + .../MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteDr0.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteDr1.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteDr2.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteDr3.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteDr4.c | 39 + .../MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm | 45 + .../MdePkg/Library/BaseLib/Ia32/WriteDr5.c | 39 + .../MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm | 45 + .../MdePkg/Library/BaseLib/Ia32/WriteDr6.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteDr7.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteGdtr.c | 39 + .../Library/BaseLib/Ia32/WriteGdtr.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteIdtr.c | 41 + .../Library/BaseLib/Ia32/WriteIdtr.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/WriteLdtr.c | 39 + .../Library/BaseLib/Ia32/WriteLdtr.nasm | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm0.c | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm1.c | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm2.c | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm3.c | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm4.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm5.c | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm6.c | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMm7.c | 38 + .../MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm | 37 + .../MdePkg/Library/BaseLib/Ia32/WriteMsr64.c | 49 + .../Library/BaseLib/Ia32/WriteMsr64.nasm | 41 + .../MdePkg/Library/BaseLib/Ia32/WriteTr.nasm | 36 + .../edk2/MdePkg/Library/BaseLib/LRotU32.c | 42 + .../edk2/MdePkg/Library/BaseLib/LRotU64.c | 42 + .../edk2/MdePkg/Library/BaseLib/LShiftU64.c | 41 + .../edk2/MdePkg/Library/BaseLib/LinkedList.c | 605 ++ .../edk2/MdePkg/Library/BaseLib/LongJump.c | 47 + .../edk2/MdePkg/Library/BaseLib/LowBitSet32.c | 47 + .../edk2/MdePkg/Library/BaseLib/LowBitSet64.c | 50 + .../edk2/MdePkg/Library/BaseLib/Math64.c | 368 + .../edk2/MdePkg/Library/BaseLib/ModU64x32.c | 45 + .../edk2/MdePkg/Library/BaseLib/MultS64x64.c | 42 + .../edk2/MdePkg/Library/BaseLib/MultU64x32.c | 46 + .../edk2/MdePkg/Library/BaseLib/MultU64x64.c | 46 + .../edk2/MdePkg/Library/BaseLib/RRotU32.c | 42 + .../edk2/MdePkg/Library/BaseLib/RRotU64.c | 42 + .../edk2/MdePkg/Library/BaseLib/RShiftU64.c | 41 + .../edk2/MdePkg/Library/BaseLib/SafeString.c | 3650 ++++++++ .../edk2/MdePkg/Library/BaseLib/SetJump.c | 40 + .../edk2/MdePkg/Library/BaseLib/String.c | 2143 +++++ .../edk2/MdePkg/Library/BaseLib/SwapBytes16.c | 39 + .../edk2/MdePkg/Library/BaseLib/SwapBytes32.c | 45 + .../edk2/MdePkg/Library/BaseLib/SwapBytes64.c | 39 + .../edk2/MdePkg/Library/BaseLib/SwitchStack.c | 76 + .../edk2/MdePkg/Library/BaseLib/Unaligned.c | 222 + .../Library/BaseLib/X64/CpuBreakpoint.c | 39 + .../Library/BaseLib/X64/CpuBreakpoint.nasm | 37 + .../edk2/MdePkg/Library/BaseLib/X64/CpuId.S | 60 + .../MdePkg/Library/BaseLib/X64/CpuId.nasm | 64 + .../edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.S | 62 + .../MdePkg/Library/BaseLib/X64/CpuIdEx.nasm | 66 + .../MdePkg/Library/BaseLib/X64/CpuPause.nasm | 37 + .../MdePkg/Library/BaseLib/X64/DisableCache.S | 39 + .../Library/BaseLib/X64/DisableCache.nasm | 43 + .../BaseLib/X64/DisableInterrupts.nasm | 38 + .../Library/BaseLib/X64/DisablePaging64.S | 82 + .../Library/BaseLib/X64/DisablePaging64.nasm | 84 + .../MdePkg/Library/BaseLib/X64/EnableCache.S | 39 + .../Library/BaseLib/X64/EnableCache.nasm | 43 + .../BaseLib/X64/EnableDisableInterrupts.S | 36 + .../BaseLib/X64/EnableDisableInterrupts.nasm | 39 + .../Library/BaseLib/X64/EnableInterrupts.nasm | 38 + .../Library/BaseLib/X64/FlushCacheLine.nasm | 39 + .../MdePkg/Library/BaseLib/X64/FxRestore.nasm | 38 + .../MdePkg/Library/BaseLib/X64/FxSave.nasm | 38 + .../MdePkg/Library/BaseLib/X64/GccInline.c | 1806 ++++ .../edk2/MdePkg/Library/BaseLib/X64/Invd.nasm | 38 + .../MdePkg/Library/BaseLib/X64/Lfence.nasm | 37 + .../MdePkg/Library/BaseLib/X64/LongJump.S | 54 + .../MdePkg/Library/BaseLib/X64/LongJump.nasm | 83 + .../MdePkg/Library/BaseLib/X64/Monitor.nasm | 43 + .../MdePkg/Library/BaseLib/X64/Mwait.nasm | 41 + .../MdePkg/Library/BaseLib/X64/Non-existing.c | 153 + .../edk2/MdePkg/Library/BaseLib/X64/RdRand.S | 72 + .../MdePkg/Library/BaseLib/X64/RdRand.nasm | 83 + .../MdePkg/Library/BaseLib/X64/ReadCr0.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadCr2.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadCr3.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadCr4.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadCs.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDr0.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDr1.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDr2.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDr3.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDr4.nasm | 42 + .../MdePkg/Library/BaseLib/X64/ReadDr5.nasm | 42 + .../MdePkg/Library/BaseLib/X64/ReadDr6.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDr7.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadDs.nasm | 38 + .../Library/BaseLib/X64/ReadEflags.nasm | 39 + .../MdePkg/Library/BaseLib/X64/ReadEs.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadFs.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadGdtr.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadGs.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadIdtr.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadLdtr.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadMm0.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm1.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm2.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm3.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm4.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm5.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm6.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMm7.nasm | 41 + .../MdePkg/Library/BaseLib/X64/ReadMsr64.c | 39 + .../MdePkg/Library/BaseLib/X64/ReadMsr64.nasm | 40 + .../MdePkg/Library/BaseLib/X64/ReadPmc.nasm | 40 + .../MdePkg/Library/BaseLib/X64/ReadSs.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadTr.nasm | 38 + .../MdePkg/Library/BaseLib/X64/ReadTsc.nasm | 40 + .../edk2/MdePkg/Library/BaseLib/X64/SetJump.S | 53 + .../MdePkg/Library/BaseLib/X64/SetJump.nasm | 87 + .../MdePkg/Library/BaseLib/X64/SwitchStack.S | 52 + .../Library/BaseLib/X64/SwitchStack.nasm | 51 + .../edk2/MdePkg/Library/BaseLib/X64/Thunk16.S | 334 + .../MdePkg/Library/BaseLib/X64/Thunk16.nasm | 325 + .../MdePkg/Library/BaseLib/X64/Wbinvd.nasm | 38 + .../MdePkg/Library/BaseLib/X64/WriteCr0.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteCr2.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteCr3.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteCr4.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteDr0.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteDr1.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteDr2.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteDr3.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteDr4.nasm | 43 + .../MdePkg/Library/BaseLib/X64/WriteDr5.nasm | 43 + .../MdePkg/Library/BaseLib/X64/WriteDr6.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteDr7.nasm | 39 + .../MdePkg/Library/BaseLib/X64/WriteGdtr.nasm | 38 + .../MdePkg/Library/BaseLib/X64/WriteIdtr.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteLdtr.nasm | 38 + .../MdePkg/Library/BaseLib/X64/WriteMm0.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm1.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm2.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm3.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm4.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm5.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm6.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMm7.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteMsr64.c | 42 + .../Library/BaseLib/X64/WriteMsr64.nasm | 41 + .../MdePkg/Library/BaseLib/X64/WriteTr.nasm | 37 + .../Library/BaseLib/X86DisablePaging32.c | 66 + .../Library/BaseLib/X86DisablePaging64.c | 63 + .../Library/BaseLib/X86EnablePaging32.c | 69 + .../Library/BaseLib/X86EnablePaging64.c | 65 + .../MdePkg/Library/BaseLib/X86FxRestore.c | 49 + .../edk2/MdePkg/Library/BaseLib/X86FxSave.c | 48 + .../Library/BaseLib/X86GetInterruptState.c | 41 + .../MdePkg/Library/BaseLib/X86MemoryFence.c | 32 + .../edk2/MdePkg/Library/BaseLib/X86Msr.c | 660 ++ .../Library/BaseLib/X86PatchInstruction.c | 89 + .../edk2/MdePkg/Library/BaseLib/X86RdRand.c | 79 + .../edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c | 39 + .../edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c | 39 + .../Library/BaseLib/X86SpeculationBarrier.c | 32 + .../edk2/MdePkg/Library/BaseLib/X86Thunk.c | 268 + .../MdePkg/Library/BaseLib/X86WriteGdtr.c | 39 + .../MdePkg/Library/BaseLib/X86WriteIdtr.c | 39 + .../Library/BaseMemoryLib/BaseMemoryLib.inf | 57 + .../Library/BaseMemoryLib/BaseMemoryLib.uni | 21 + .../Library/BaseMemoryLib/CompareMemWrapper.c | 66 + .../MdePkg/Library/BaseMemoryLib/CopyMem.c | 154 + .../Library/BaseMemoryLib/CopyMemWrapper.c | 63 + .../BaseMemoryLib/IsZeroBufferWrapper.c | 54 + .../Library/BaseMemoryLib/MemLibGeneric.c | 293 + .../MdePkg/Library/BaseMemoryLib/MemLibGuid.c | 171 + .../Library/BaseMemoryLib/MemLibInternals.h | 251 + .../Library/BaseMemoryLib/ScanMem16Wrapper.c | 67 + .../Library/BaseMemoryLib/ScanMem32Wrapper.c | 66 + .../Library/BaseMemoryLib/ScanMem64Wrapper.c | 67 + .../Library/BaseMemoryLib/ScanMem8Wrapper.c | 99 + .../MdePkg/Library/BaseMemoryLib/SetMem.c | 87 + .../Library/BaseMemoryLib/SetMem16Wrapper.c | 64 + .../Library/BaseMemoryLib/SetMem32Wrapper.c | 64 + .../Library/BaseMemoryLib/SetMem64Wrapper.c | 64 + .../Library/BaseMemoryLib/SetMemWrapper.c | 91 + .../Library/BaseMemoryLib/ZeroMemWrapper.c | 56 + .../BaseMemoryLibMmx/BaseMemoryLibMmx.inf | 129 + .../BaseMemoryLibMmx/BaseMemoryLibMmx.uni | 22 + .../BaseMemoryLibMmx/CompareMemWrapper.c | 66 + .../Library/BaseMemoryLibMmx/CopyMemWrapper.c | 63 + .../BaseMemoryLibMmx/Ia32/CompareMem.S | 55 + .../BaseMemoryLibMmx/Ia32/CompareMem.nasm | 57 + .../Library/BaseMemoryLibMmx/Ia32/CopyMem.S | 86 + .../BaseMemoryLibMmx/Ia32/CopyMem.nasm | 77 + .../BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm | 55 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem16.S | 52 + .../BaseMemoryLibMmx/Ia32/ScanMem16.nasm | 54 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem32.S | 52 + .../BaseMemoryLibMmx/Ia32/ScanMem32.nasm | 54 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem64.S | 61 + .../BaseMemoryLibMmx/Ia32/ScanMem64.nasm | 63 + .../Library/BaseMemoryLibMmx/Ia32/ScanMem8.S | 52 + .../BaseMemoryLibMmx/Ia32/ScanMem8.nasm | 54 + .../Library/BaseMemoryLibMmx/Ia32/SetMem.S | 66 + .../Library/BaseMemoryLibMmx/Ia32/SetMem.nasm | 68 + .../Library/BaseMemoryLibMmx/Ia32/SetMem16.S | 59 + .../BaseMemoryLibMmx/Ia32/SetMem16.nasm | 61 + .../Library/BaseMemoryLibMmx/Ia32/SetMem32.S | 52 + .../BaseMemoryLibMmx/Ia32/SetMem32.nasm | 55 + .../Library/BaseMemoryLibMmx/Ia32/SetMem64.S | 43 + .../BaseMemoryLibMmx/Ia32/SetMem64.nasm | 46 + .../Library/BaseMemoryLibMmx/Ia32/ZeroMem.S | 54 + .../BaseMemoryLibMmx/Ia32/ZeroMem.nasm | 54 + .../BaseMemoryLibMmx/IsZeroBufferWrapper.c | 54 + .../Library/BaseMemoryLibMmx/MemLibGuid.c | 171 + .../BaseMemoryLibMmx/MemLibInternals.h | 251 + .../BaseMemoryLibMmx/ScanMem16Wrapper.c | 67 + .../BaseMemoryLibMmx/ScanMem32Wrapper.c | 66 + .../BaseMemoryLibMmx/ScanMem64Wrapper.c | 67 + .../BaseMemoryLibMmx/ScanMem8Wrapper.c | 99 + .../BaseMemoryLibMmx/SetMem16Wrapper.c | 64 + .../BaseMemoryLibMmx/SetMem32Wrapper.c | 64 + .../BaseMemoryLibMmx/SetMem64Wrapper.c | 64 + .../Library/BaseMemoryLibMmx/SetMemWrapper.c | 91 + .../Library/BaseMemoryLibMmx/X64/CompareMem.S | 59 + .../BaseMemoryLibMmx/X64/CompareMem.nasm | 58 + .../Library/BaseMemoryLibMmx/X64/CopyMem.S | 74 + .../Library/BaseMemoryLibMmx/X64/CopyMem.nasm | 74 + .../BaseMemoryLibMmx/X64/IsZeroBuffer.nasm | 55 + .../Library/BaseMemoryLibMmx/X64/ScanMem16.S | 56 + .../BaseMemoryLibMmx/X64/ScanMem16.nasm | 55 + .../Library/BaseMemoryLibMmx/X64/ScanMem32.S | 56 + .../BaseMemoryLibMmx/X64/ScanMem32.nasm | 55 + .../Library/BaseMemoryLibMmx/X64/ScanMem64.S | 55 + .../BaseMemoryLibMmx/X64/ScanMem64.nasm | 55 + .../Library/BaseMemoryLibMmx/X64/ScanMem8.S | 56 + .../BaseMemoryLibMmx/X64/ScanMem8.nasm | 55 + .../Library/BaseMemoryLibMmx/X64/SetMem.S | 61 + .../Library/BaseMemoryLibMmx/X64/SetMem.nasm | 60 + .../Library/BaseMemoryLibMmx/X64/SetMem16.S | 60 + .../BaseMemoryLibMmx/X64/SetMem16.nasm | 59 + .../Library/BaseMemoryLibMmx/X64/SetMem32.S | 55 + .../BaseMemoryLibMmx/X64/SetMem32.nasm | 53 + .../Library/BaseMemoryLibMmx/X64/SetMem64.S | 47 + .../BaseMemoryLibMmx/X64/SetMem64.nasm | 46 + .../Library/BaseMemoryLibMmx/X64/ZeroMem.S | 57 + .../Library/BaseMemoryLibMmx/X64/ZeroMem.nasm | 56 + .../Library/BaseMemoryLibMmx/ZeroMemWrapper.c | 56 + .../BaseMemoryLibOptDxe/AArch64/CompareGuid.S | 40 + .../BaseMemoryLibOptDxe/AArch64/CompareMem.S | 142 + .../BaseMemoryLibOptDxe/AArch64/CopyMem.S | 284 + .../BaseMemoryLibOptDxe/AArch64/ScanMem.S | 161 + .../BaseMemoryLibOptDxe/AArch64/SetMem.S | 247 + .../BaseMemoryLibOptDxe/Arm/CompareGuid.S | 66 + .../BaseMemoryLibOptDxe/Arm/CompareGuid.asm | 70 + .../BaseMemoryLibOptDxe/Arm/CompareMem.S | 139 + .../BaseMemoryLibOptDxe/Arm/CompareMem.asm | 140 + .../Library/BaseMemoryLibOptDxe/Arm/CopyMem.S | 176 + .../BaseMemoryLibOptDxe/Arm/CopyMem.asm | 147 + .../BaseMemoryLibOptDxe/Arm/MemLibGuid.c | 165 + .../Library/BaseMemoryLibOptDxe/Arm/ScanMem.S | 148 + .../BaseMemoryLibOptDxe/Arm/ScanMem.asm | 147 + .../BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c | 142 + .../Library/BaseMemoryLibOptDxe/Arm/SetMem.S | 94 + .../BaseMemoryLibOptDxe/Arm/SetMem.asm | 96 + .../BaseMemoryLibOptDxe.inf | 152 + .../BaseMemoryLibOptDxe.uni | 22 + .../BaseMemoryLibOptDxe/CompareMemWrapper.c | 66 + .../BaseMemoryLibOptDxe/CopyMemWrapper.c | 63 + .../BaseMemoryLibOptDxe/Ia32/CompareMem.S | 55 + .../BaseMemoryLibOptDxe/Ia32/CompareMem.nasm | 57 + .../BaseMemoryLibOptDxe/Ia32/CopyMem.S | 85 + .../BaseMemoryLibOptDxe/Ia32/CopyMem.nasm | 84 + .../Ia32/IsZeroBuffer.nasm | 55 + .../BaseMemoryLibOptDxe/Ia32/ScanMem16.S | 52 + .../BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm | 54 + .../BaseMemoryLibOptDxe/Ia32/ScanMem32.S | 52 + .../BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm | 54 + .../BaseMemoryLibOptDxe/Ia32/ScanMem64.S | 61 + .../BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm | 63 + .../BaseMemoryLibOptDxe/Ia32/ScanMem8.S | 52 + .../BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm | 54 + .../Library/BaseMemoryLibOptDxe/Ia32/SetMem.S | 50 + .../BaseMemoryLibOptDxe/Ia32/SetMem.nasm | 52 + .../BaseMemoryLibOptDxe/Ia32/SetMem16.S | 43 + .../BaseMemoryLibOptDxe/Ia32/SetMem16.nasm | 44 + .../BaseMemoryLibOptDxe/Ia32/SetMem32.S | 43 + .../BaseMemoryLibOptDxe/Ia32/SetMem32.nasm | 44 + .../BaseMemoryLibOptDxe/Ia32/SetMem64.S | 46 + .../BaseMemoryLibOptDxe/Ia32/SetMem64.nasm | 48 + .../BaseMemoryLibOptDxe/Ia32/ZeroMem.S | 49 + .../BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm | 49 + .../BaseMemoryLibOptDxe/IsZeroBufferWrapper.c | 54 + .../Library/BaseMemoryLibOptDxe/MemLibGuid.c | 171 + .../BaseMemoryLibOptDxe/MemLibInternals.h | 251 + .../BaseMemoryLibOptDxe/ScanMem16Wrapper.c | 67 + .../BaseMemoryLibOptDxe/ScanMem32Wrapper.c | 66 + .../BaseMemoryLibOptDxe/ScanMem64Wrapper.c | 67 + .../BaseMemoryLibOptDxe/ScanMem8Wrapper.c | 100 + .../BaseMemoryLibOptDxe/SetMem16Wrapper.c | 64 + .../BaseMemoryLibOptDxe/SetMem32Wrapper.c | 64 + .../BaseMemoryLibOptDxe/SetMem64Wrapper.c | 64 + .../BaseMemoryLibOptDxe/SetMemWrapper.c | 91 + .../BaseMemoryLibOptDxe/X64/CompareMem.S | 59 + .../BaseMemoryLibOptDxe/X64/CompareMem.nasm | 58 + .../Library/BaseMemoryLibOptDxe/X64/CopyMem.S | 82 + .../BaseMemoryLibOptDxe/X64/CopyMem.nasm | 83 + .../BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm | 55 + .../BaseMemoryLibOptDxe/X64/ScanMem16.S | 56 + .../BaseMemoryLibOptDxe/X64/ScanMem16.nasm | 55 + .../BaseMemoryLibOptDxe/X64/ScanMem32.S | 56 + .../BaseMemoryLibOptDxe/X64/ScanMem32.nasm | 55 + .../BaseMemoryLibOptDxe/X64/ScanMem64.S | 55 + .../BaseMemoryLibOptDxe/X64/ScanMem64.nasm | 55 + .../BaseMemoryLibOptDxe/X64/ScanMem8.S | 56 + .../BaseMemoryLibOptDxe/X64/ScanMem8.nasm | 55 + .../Library/BaseMemoryLibOptDxe/X64/SetMem.S | 57 + .../BaseMemoryLibOptDxe/X64/SetMem.nasm | 62 + .../BaseMemoryLibOptDxe/X64/SetMem16.S | 47 + .../BaseMemoryLibOptDxe/X64/SetMem16.nasm | 47 + .../BaseMemoryLibOptDxe/X64/SetMem32.S | 47 + .../BaseMemoryLibOptDxe/X64/SetMem32.nasm | 47 + .../BaseMemoryLibOptDxe/X64/SetMem64.S | 46 + .../BaseMemoryLibOptDxe/X64/SetMem64.nasm | 46 + .../Library/BaseMemoryLibOptDxe/X64/ZeroMem.S | 51 + .../BaseMemoryLibOptDxe/X64/ZeroMem.nasm | 50 + .../BaseMemoryLibOptDxe/ZeroMemWrapper.c | 56 + .../BaseMemoryLibOptPei.inf | 130 + .../BaseMemoryLibOptPei.uni | 22 + .../BaseMemoryLibOptPei/CompareMemWrapper.c | 66 + .../BaseMemoryLibOptPei/CopyMemWrapper.c | 63 + .../BaseMemoryLibOptPei/Ia32/CompareMem.S | 55 + .../BaseMemoryLibOptPei/Ia32/CompareMem.nasm | 57 + .../BaseMemoryLibOptPei/Ia32/CopyMem.S | 62 + .../BaseMemoryLibOptPei/Ia32/CopyMem.nasm | 62 + .../Ia32/IsZeroBuffer.nasm | 55 + .../BaseMemoryLibOptPei/Ia32/ScanMem16.S | 52 + .../BaseMemoryLibOptPei/Ia32/ScanMem16.nasm | 54 + .../BaseMemoryLibOptPei/Ia32/ScanMem32.S | 52 + .../BaseMemoryLibOptPei/Ia32/ScanMem32.nasm | 54 + .../BaseMemoryLibOptPei/Ia32/ScanMem64.S | 61 + .../BaseMemoryLibOptPei/Ia32/ScanMem64.nasm | 63 + .../BaseMemoryLibOptPei/Ia32/ScanMem8.S | 52 + .../BaseMemoryLibOptPei/Ia32/ScanMem8.nasm | 54 + .../Library/BaseMemoryLibOptPei/Ia32/SetMem.S | 50 + .../BaseMemoryLibOptPei/Ia32/SetMem.nasm | 52 + .../BaseMemoryLibOptPei/Ia32/SetMem16.S | 43 + .../BaseMemoryLibOptPei/Ia32/SetMem16.nasm | 44 + .../BaseMemoryLibOptPei/Ia32/SetMem32.S | 43 + .../BaseMemoryLibOptPei/Ia32/SetMem32.nasm | 44 + .../BaseMemoryLibOptPei/Ia32/SetMem64.S | 46 + .../BaseMemoryLibOptPei/Ia32/SetMem64.nasm | 48 + .../BaseMemoryLibOptPei/Ia32/ZeroMem.S | 49 + .../BaseMemoryLibOptPei/Ia32/ZeroMem.nasm | 49 + .../BaseMemoryLibOptPei/IsZeroBufferWrapper.c | 54 + .../Library/BaseMemoryLibOptPei/MemLibGuid.c | 171 + .../BaseMemoryLibOptPei/MemLibInternals.h | 251 + .../BaseMemoryLibOptPei/ScanMem16Wrapper.c | 67 + .../BaseMemoryLibOptPei/ScanMem32Wrapper.c | 66 + .../BaseMemoryLibOptPei/ScanMem64Wrapper.c | 67 + .../BaseMemoryLibOptPei/ScanMem8Wrapper.c | 99 + .../BaseMemoryLibOptPei/SetMem16Wrapper.c | 64 + .../BaseMemoryLibOptPei/SetMem32Wrapper.c | 64 + .../BaseMemoryLibOptPei/SetMem64Wrapper.c | 64 + .../BaseMemoryLibOptPei/SetMemWrapper.c | 91 + .../BaseMemoryLibOptPei/X64/CompareMem.S | 59 + .../BaseMemoryLibOptPei/X64/CompareMem.nasm | 58 + .../Library/BaseMemoryLibOptPei/X64/CopyMem.S | 66 + .../BaseMemoryLibOptPei/X64/CopyMem.nasm | 65 + .../BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm | 55 + .../BaseMemoryLibOptPei/X64/ScanMem16.S | 56 + .../BaseMemoryLibOptPei/X64/ScanMem16.nasm | 55 + .../BaseMemoryLibOptPei/X64/ScanMem32.S | 56 + .../BaseMemoryLibOptPei/X64/ScanMem32.nasm | 55 + .../BaseMemoryLibOptPei/X64/ScanMem64.S | 56 + .../BaseMemoryLibOptPei/X64/ScanMem64.nasm | 55 + .../BaseMemoryLibOptPei/X64/ScanMem8.S | 56 + .../BaseMemoryLibOptPei/X64/ScanMem8.nasm | 55 + .../Library/BaseMemoryLibOptPei/X64/SetMem.S | 47 + .../BaseMemoryLibOptPei/X64/SetMem.nasm | 47 + .../BaseMemoryLibOptPei/X64/SetMem16.S | 47 + .../BaseMemoryLibOptPei/X64/SetMem16.nasm | 46 + .../BaseMemoryLibOptPei/X64/SetMem32.S | 47 + .../BaseMemoryLibOptPei/X64/SetMem32.nasm | 46 + .../BaseMemoryLibOptPei/X64/SetMem64.S | 46 + .../BaseMemoryLibOptPei/X64/SetMem64.nasm | 45 + .../Library/BaseMemoryLibOptPei/X64/ZeroMem.S | 50 + .../BaseMemoryLibOptPei/X64/ZeroMem.nasm | 49 + .../BaseMemoryLibOptPei/ZeroMemWrapper.c | 56 + .../BaseMemoryLibRepStr.inf | 127 + .../BaseMemoryLibRepStr.uni | 22 + .../BaseMemoryLibRepStr/CompareMemWrapper.c | 66 + .../BaseMemoryLibRepStr/CopyMemWrapper.c | 63 + .../BaseMemoryLibRepStr/Ia32/CompareMem.S | 55 + .../BaseMemoryLibRepStr/Ia32/CompareMem.nasm | 57 + .../BaseMemoryLibRepStr/Ia32/CopyMem.S | 65 + .../BaseMemoryLibRepStr/Ia32/CopyMem.nasm | 64 + .../Ia32/IsZeroBuffer.nasm | 55 + .../BaseMemoryLibRepStr/Ia32/ScanMem16.S | 54 + .../BaseMemoryLibRepStr/Ia32/ScanMem16.nasm | 56 + .../BaseMemoryLibRepStr/Ia32/ScanMem32.S | 54 + .../BaseMemoryLibRepStr/Ia32/ScanMem32.nasm | 56 + .../BaseMemoryLibRepStr/Ia32/ScanMem64.S | 63 + .../BaseMemoryLibRepStr/Ia32/ScanMem64.nasm | 65 + .../BaseMemoryLibRepStr/Ia32/ScanMem8.S | 54 + .../BaseMemoryLibRepStr/Ia32/ScanMem8.nasm | 56 + .../Library/BaseMemoryLibRepStr/Ia32/SetMem.S | 46 + .../BaseMemoryLibRepStr/Ia32/SetMem.nasm | 44 + .../BaseMemoryLibRepStr/Ia32/SetMem16.S | 43 + .../BaseMemoryLibRepStr/Ia32/SetMem16.nasm | 44 + .../BaseMemoryLibRepStr/Ia32/SetMem32.S | 43 + .../BaseMemoryLibRepStr/Ia32/SetMem32.nasm | 44 + .../BaseMemoryLibRepStr/Ia32/SetMem64.S | 46 + .../BaseMemoryLibRepStr/Ia32/SetMem64.nasm | 48 + .../BaseMemoryLibRepStr/Ia32/ZeroMem.S | 49 + .../BaseMemoryLibRepStr/Ia32/ZeroMem.nasm | 49 + .../BaseMemoryLibRepStr/IsZeroBufferWrapper.c | 54 + .../Library/BaseMemoryLibRepStr/MemLibGuid.c | 171 + .../BaseMemoryLibRepStr/MemLibInternals.h | 251 + .../BaseMemoryLibRepStr/ScanMem16Wrapper.c | 67 + .../BaseMemoryLibRepStr/ScanMem32Wrapper.c | 66 + .../BaseMemoryLibRepStr/ScanMem64Wrapper.c | 67 + .../BaseMemoryLibRepStr/ScanMem8Wrapper.c | 99 + .../BaseMemoryLibRepStr/SetMem16Wrapper.c | 64 + .../BaseMemoryLibRepStr/SetMem32Wrapper.c | 64 + .../BaseMemoryLibRepStr/SetMem64Wrapper.c | 64 + .../BaseMemoryLibRepStr/SetMemWrapper.c | 91 + .../BaseMemoryLibRepStr/X64/CompareMem.S | 59 + .../BaseMemoryLibRepStr/X64/CompareMem.nasm | 58 + .../Library/BaseMemoryLibRepStr/X64/CopyMem.S | 66 + .../BaseMemoryLibRepStr/X64/CopyMem.nasm | 65 + .../BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm | 55 + .../BaseMemoryLibRepStr/X64/ScanMem16.S | 56 + .../BaseMemoryLibRepStr/X64/ScanMem16.nasm | 55 + .../BaseMemoryLibRepStr/X64/ScanMem32.S | 56 + .../BaseMemoryLibRepStr/X64/ScanMem32.nasm | 55 + .../BaseMemoryLibRepStr/X64/ScanMem64.S | 56 + .../BaseMemoryLibRepStr/X64/ScanMem64.nasm | 55 + .../BaseMemoryLibRepStr/X64/ScanMem8.S | 56 + .../BaseMemoryLibRepStr/X64/ScanMem8.nasm | 55 + .../Library/BaseMemoryLibRepStr/X64/SetMem.S | 47 + .../BaseMemoryLibRepStr/X64/SetMem.nasm | 46 + .../BaseMemoryLibRepStr/X64/SetMem16.S | 47 + .../BaseMemoryLibRepStr/X64/SetMem16.nasm | 46 + .../BaseMemoryLibRepStr/X64/SetMem32.S | 47 + .../BaseMemoryLibRepStr/X64/SetMem32.nasm | 46 + .../BaseMemoryLibRepStr/X64/SetMem64.S | 46 + .../BaseMemoryLibRepStr/X64/SetMem64.nasm | 45 + .../Library/BaseMemoryLibRepStr/X64/ZeroMem.S | 50 + .../BaseMemoryLibRepStr/X64/ZeroMem.nasm | 49 + .../BaseMemoryLibRepStr/ZeroMemWrapper.c | 56 + .../BaseMemoryLibSse2/BaseMemoryLibSse2.inf | 126 + .../BaseMemoryLibSse2/BaseMemoryLibSse2.uni | 21 + .../BaseMemoryLibSse2/CompareMemWrapper.c | 66 + .../BaseMemoryLibSse2/CopyMemWrapper.c | 63 + .../BaseMemoryLibSse2/Ia32/CompareMem.S | 55 + .../BaseMemoryLibSse2/Ia32/CompareMem.nasm | 57 + .../Library/BaseMemoryLibSse2/Ia32/CopyMem.S | 85 + .../BaseMemoryLibSse2/Ia32/CopyMem.nasm | 84 + .../BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm | 74 + .../BaseMemoryLibSse2/Ia32/ScanMem16.S | 52 + .../BaseMemoryLibSse2/Ia32/ScanMem16.nasm | 54 + .../BaseMemoryLibSse2/Ia32/ScanMem32.S | 52 + .../BaseMemoryLibSse2/Ia32/ScanMem32.nasm | 54 + .../BaseMemoryLibSse2/Ia32/ScanMem64.S | 61 + .../BaseMemoryLibSse2/Ia32/ScanMem64.nasm | 63 + .../Library/BaseMemoryLibSse2/Ia32/ScanMem8.S | 52 + .../BaseMemoryLibSse2/Ia32/ScanMem8.nasm | 54 + .../Library/BaseMemoryLibSse2/Ia32/SetMem.S | 76 + .../BaseMemoryLibSse2/Ia32/SetMem.nasm | 73 + .../Library/BaseMemoryLibSse2/Ia32/SetMem16.S | 69 + .../BaseMemoryLibSse2/Ia32/SetMem16.nasm | 69 + .../Library/BaseMemoryLibSse2/Ia32/SetMem32.S | 68 + .../BaseMemoryLibSse2/Ia32/SetMem32.nasm | 68 + .../Library/BaseMemoryLibSse2/Ia32/SetMem64.S | 58 + .../BaseMemoryLibSse2/Ia32/SetMem64.nasm | 60 + .../Library/BaseMemoryLibSse2/Ia32/ZeroMem.S | 65 + .../BaseMemoryLibSse2/Ia32/ZeroMem.nasm | 65 + .../BaseMemoryLibSse2/IsZeroBufferWrapper.c | 54 + .../Library/BaseMemoryLibSse2/MemLibGuid.c | 171 + .../BaseMemoryLibSse2/MemLibInternals.h | 251 + .../BaseMemoryLibSse2/ScanMem16Wrapper.c | 67 + .../BaseMemoryLibSse2/ScanMem32Wrapper.c | 66 + .../BaseMemoryLibSse2/ScanMem64Wrapper.c | 67 + .../BaseMemoryLibSse2/ScanMem8Wrapper.c | 99 + .../BaseMemoryLibSse2/SetMem16Wrapper.c | 64 + .../BaseMemoryLibSse2/SetMem32Wrapper.c | 64 + .../BaseMemoryLibSse2/SetMem64Wrapper.c | 64 + .../Library/BaseMemoryLibSse2/SetMemWrapper.c | 91 + .../BaseMemoryLibSse2/X64/CompareMem.S | 59 + .../BaseMemoryLibSse2/X64/CompareMem.nasm | 58 + .../Library/BaseMemoryLibSse2/X64/CopyMem.S | 83 + .../BaseMemoryLibSse2/X64/CopyMem.nasm | 83 + .../BaseMemoryLibSse2/X64/IsZeroBuffer.nasm | 76 + .../Library/BaseMemoryLibSse2/X64/ScanMem16.S | 56 + .../BaseMemoryLibSse2/X64/ScanMem16.nasm | 55 + .../Library/BaseMemoryLibSse2/X64/ScanMem32.S | 56 + .../BaseMemoryLibSse2/X64/ScanMem32.nasm | 55 + .../Library/BaseMemoryLibSse2/X64/ScanMem64.S | 56 + .../BaseMemoryLibSse2/X64/ScanMem64.nasm | 55 + .../Library/BaseMemoryLibSse2/X64/ScanMem8.S | 56 + .../BaseMemoryLibSse2/X64/ScanMem8.nasm | 55 + .../Library/BaseMemoryLibSse2/X64/SetMem.S | 72 + .../Library/BaseMemoryLibSse2/X64/SetMem.nasm | 71 + .../Library/BaseMemoryLibSse2/X64/SetMem16.S | 70 + .../BaseMemoryLibSse2/X64/SetMem16.nasm | 69 + .../Library/BaseMemoryLibSse2/X64/SetMem32.S | 69 + .../BaseMemoryLibSse2/X64/SetMem32.nasm | 68 + .../Library/BaseMemoryLibSse2/X64/SetMem64.S | 60 + .../BaseMemoryLibSse2/X64/SetMem64.nasm | 59 + .../Library/BaseMemoryLibSse2/X64/ZeroMem.S | 65 + .../BaseMemoryLibSse2/X64/ZeroMem.nasm | 65 + .../BaseMemoryLibSse2/ZeroMemWrapper.c | 56 + .../BaseOrderedCollectionRedBlackTreeLib.c | 1454 +++ .../BaseOrderedCollectionRedBlackTreeLib.inf | 51 + .../BaseOrderedCollectionRedBlackTreeLib.uni | 31 + .../Library/BasePcdLibNull/BasePcdLibNull.inf | 42 + .../Library/BasePcdLibNull/BasePcdLibNull.uni | 22 + .../MdePkg/Library/BasePcdLibNull/PcdLib.c | 1480 ++++ .../Library/BasePciCf8Lib/BasePciCf8Lib.inf | 42 + .../Library/BasePciCf8Lib/BasePciCf8Lib.uni | 22 + .../MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c | 1784 ++++ .../BasePciExpressLib/BasePciExpressLib.inf | 46 + .../BasePciExpressLib/BasePciExpressLib.uni | 22 + .../Library/BasePciExpressLib/PciExpressLib.c | 1419 +++ .../Library/BasePciLibCf8/BasePciLibCf8.inf | 40 + .../Library/BasePciLibCf8/BasePciLibCf8.uni | 22 + .../MdePkg/Library/BasePciLibCf8/PciLib.c | 1138 +++ .../BasePciLibPciExpress.inf | 41 + .../BasePciLibPciExpress.uni | 22 + .../Library/BasePciLibPciExpress/PciLib.c | 1138 +++ .../BasePciSegmentInfoLibNull.inf | 41 + .../BasePciSegmentInfoLibNull.uni | 20 + .../PciSegmentInfoLib.c | 38 + .../BasePciSegmentLibPci.inf | 43 + .../BasePciSegmentLibPci.uni | 21 + .../BasePciSegmentLibPci/PciSegmentLib.c | 1290 +++ .../BasePeCoffExtraActionLibNull.inf | 38 + .../PeCoffExtraActionLib.c | 54 + .../PeCoffExtraActionLibNull.uni | 21 + .../BasePeCoffGetEntryPointLib.inf | 40 + .../BasePeCoffGetEntryPointLib.uni | 21 + .../PeCoffGetEntryPoint.c | 388 + .../BasePeCoffLib/Arm/PeCoffLoaderEx.c | 250 + .../MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 1949 ++++ .../Library/BasePeCoffLib/BasePeCoffLib.inf | 56 + .../Library/BasePeCoffLib/BasePeCoffLib.uni | 29 + .../BasePeCoffLib/BasePeCoffLibInternals.h | 133 + .../Library/BasePeCoffLib/PeCoffLoaderEx.c | 90 + .../BasePerformanceLibNull.inf | 45 + .../BasePerformanceLibNull.uni | 21 + .../BasePerformanceLibNull/PerformanceLib.c | 361 + .../BasePostCodeLibDebug.inf | 50 + .../BasePostCodeLibDebug.uni | 22 + .../Library/BasePostCodeLibDebug/PostCode.c | 127 + .../BasePostCodeLibPort80.inf | 48 + .../BasePostCodeLibPort80.uni | 21 + .../Library/BasePostCodeLibPort80/PostCode.c | 145 + .../Library/BasePrintLib/BasePrintLib.inf | 50 + .../Library/BasePrintLib/BasePrintLib.uni | 21 + .../MdePkg/Library/BasePrintLib/PrintLib.c | 961 ++ .../Library/BasePrintLib/PrintLibInternal.c | 1269 +++ .../Library/BasePrintLib/PrintLibInternal.h | 277 + .../BaseReportStatusCodeLib.c | 392 + .../BaseReportStatusCodeLibNull.inf | 39 + .../BaseReportStatusCodeLibNull.uni | 21 + .../edk2/MdePkg/Library/BaseRngLib/BaseRng.c | 189 + .../MdePkg/Library/BaseRngLib/BaseRngLib.inf | 41 + .../MdePkg/Library/BaseRngLib/BaseRngLib.uni | 22 + .../BaseS3BootScriptLibNull.inf | 43 + .../BaseS3BootScriptLibNull.uni | 24 + .../BaseS3BootScriptLibNull/BootScriptLib.c | 568 ++ .../Library/BaseS3IoLib/BaseS3IoLib.inf | 46 + .../Library/BaseS3IoLib/BaseS3IoLib.uni | 23 + .../edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c | 3312 +++++++ .../Library/BaseS3PciLib/BaseS3PciLib.inf | 47 + .../Library/BaseS3PciLib/BaseS3PciLib.uni | 23 + .../MdePkg/Library/BaseS3PciLib/S3PciLib.c | 1269 +++ .../BaseS3PciSegmentLib.inf | 45 + .../BaseS3PciSegmentLib.uni | 23 + .../BaseS3PciSegmentLib/S3PciSegmentLib.c | 1249 +++ .../Library/BaseS3SmbusLib/BaseS3SmbusLib.inf | 47 + .../Library/BaseS3SmbusLib/BaseS3SmbusLib.uni | 23 + .../Library/BaseS3SmbusLib/S3SmbusLib.c | 502 ++ .../Library/BaseS3StallLib/BaseS3StallLib.inf | 45 + .../Library/BaseS3StallLib/BaseS3StallLib.uni | 23 + .../Library/BaseS3StallLib/S3StallLib.c | 52 + .../Library/BaseSafeIntLib/BaseSafeIntLib.inf | 62 + .../Library/BaseSafeIntLib/SafeIntLib.c | 4165 +++++++++ .../Library/BaseSafeIntLib/SafeIntLib32.c | 555 ++ .../Library/BaseSafeIntLib/SafeIntLib64.c | 508 ++ .../Library/BaseSafeIntLib/SafeIntLibEbc.c | 614 ++ .../BaseSerialPortLibNull.c | 197 + .../BaseSerialPortLibNull.inf | 36 + .../BaseSerialPortLibNull.uni | 21 + .../BaseSmbusLibNull/BaseSmbusLibNull.c | 544 ++ .../BaseSmbusLibNull/BaseSmbusLibNull.inf | 35 + .../BaseSmbusLibNull/BaseSmbusLibNull.uni | 21 + .../BaseStackCheckLib/BaseStackCheckGcc.c | 55 + .../BaseStackCheckLib/BaseStackCheckLib.inf | 45 + .../BaseStackCheckLib/BaseStackCheckLib.uni | 21 + .../BaseStackCheckLib/BaseStackCheckNull.c | 15 + .../AArch64/Synchronization.S | 205 + .../AArch64/Synchronization.asm | 205 + .../Arm/Synchronization.S | 213 + .../Arm/Synchronization.asm | 214 + .../BaseSynchronizationLib.inf | 97 + .../BaseSynchronizationLib.uni | 22 + .../BaseSynchronizationLibInternals.h | 151 + .../Ebc/Synchronization.c | 147 + .../BaseSynchronizationLib/Ia32/GccInline.c | 207 + .../Ia32/InterlockedCompareExchange16.c | 51 + .../Ia32/InterlockedCompareExchange16.nasm | 43 + .../Ia32/InterlockedCompareExchange32.c | 50 + .../Ia32/InterlockedCompareExchange32.nasm | 42 + .../Ia32/InterlockedCompareExchange64.c | 50 + .../Ia32/InterlockedCompareExchange64.nasm | 48 + .../Ia32/InterlockedDecrement.nasm | 39 + .../Ia32/InterlockedIncrement.nasm | 40 + .../Ia32/InternalGetSpinLockProperties.c | 64 + .../InterlockedDecrementMsc.c | 46 + .../InterlockedIncrementMsc.c | 46 + .../BaseSynchronizationLib/Synchronization.c | 416 + .../SynchronizationGcc.c | 432 + .../SynchronizationMsc.c | 434 + .../BaseSynchronizationLib/X64/GccInline.c | 206 + .../X64/InterlockedCompareExchange16.c | 54 + .../X64/InterlockedCompareExchange16.nasm | 42 + .../X64/InterlockedCompareExchange32.c | 54 + .../X64/InterlockedCompareExchange32.nasm | 41 + .../X64/InterlockedCompareExchange64.c | 53 + .../X64/InterlockedCompareExchange64.nasm | 41 + .../X64/InterlockedDecrement.nasm | 39 + .../X64/InterlockedIncrement.nasm | 40 + .../BaseTimerLibNullTemplate.inf | 45 + .../BaseTimerLibNullTemplate.uni | 24 + .../BaseTimerLibNullTemplate/TimerLibNull.c | 134 + .../BaseUefiDecompressLib.c | 822 ++ .../BaseUefiDecompressLib.inf | 43 + .../BaseUefiDecompressLib.uni | 21 + .../BaseUefiDecompressLibInternals.h | 211 + .../DxeCoreEntryPoint/DxeCoreEntryPoint.c | 79 + .../DxeCoreEntryPoint/DxeCoreEntryPoint.inf | 41 + .../DxeCoreEntryPoint/DxeCoreEntryPoint.uni | 21 + .../Library/DxeCoreHobLib/DxeCoreHobLib.inf | 44 + .../Library/DxeCoreHobLib/DxeCoreHobLib.uni | 22 + .../MdePkg/Library/DxeCoreHobLib/HobLib.c | 603 ++ .../DxeExtractGuidedSectionLib.c | 455 + .../DxeExtractGuidedSectionLib.inf | 47 + .../DxeExtractGuidedSectionLib.uni | 21 + .../MdePkg/Library/DxeHobLib/DxeHobLib.inf | 48 + .../MdePkg/Library/DxeHobLib/DxeHobLib.uni | 22 + .../edk2/MdePkg/Library/DxeHobLib/HobLib.c | 637 ++ .../MdePkg/Library/DxeHstiLib/DxeHstiLib.inf | 48 + .../MdePkg/Library/DxeHstiLib/DxeHstiLib.uni | 19 + .../edk2/MdePkg/Library/DxeHstiLib/HstiAip.c | 175 + .../edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c | 612 ++ .../edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h | 65 + .../DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h | 172 + .../Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf | 53 + .../Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni | 22 + .../Library/DxeIoLibCpuIo2/IoHighLevel.c | 2307 +++++ .../MdePkg/Library/DxeIoLibCpuIo2/IoLib.c | 869 ++ .../Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c | 413 + .../edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c | 1626 ++++ .../MdePkg/Library/DxePcdLib/DxePcdLib.inf | 68 + .../MdePkg/Library/DxePcdLib/DxePcdLib.uni | 31 + .../DxeRuntimeDebugLibSerialPort/DebugLib.c | 346 + .../DxeRuntimeDebugLibSerialPort.inf | 55 + .../DxeRuntimeDebugLibSerialPort.uni | 21 + .../DxeRuntimePciExpressLib.inf | 58 + .../DxeRuntimePciExpressLib.uni | 26 + .../DxeRuntimePciExpressLib/PciExpressLib.c | 1660 ++++ .../MdePkg/Library/DxeServicesLib/Allocate.c | 54 + .../Library/DxeServicesLib/DxeServicesLib.c | 1098 +++ .../Library/DxeServicesLib/DxeServicesLib.inf | 65 + .../Library/DxeServicesLib/DxeServicesLib.uni | 23 + .../Library/DxeServicesLib/X64/Allocate.c | 69 + .../DxeServicesTableLib/DxeServicesTableLib.c | 68 + .../DxeServicesTableLib.inf | 49 + .../DxeServicesTableLib.uni | 22 + .../MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c | 104 + .../Library/DxeSmbusLib/DxeSmbusLib.inf | 51 + .../Library/DxeSmbusLib/DxeSmbusLib.uni | 21 + .../Library/DxeSmbusLib/InternalSmbusLib.h | 85 + .../MdePkg/Library/DxeSmbusLib/SmbusLib.c | 592 ++ .../MmServicesTableLib/MmServicesTableLib.c | 63 + .../MmServicesTableLib/MmServicesTableLib.inf | 45 + .../MmServicesTableLib/MmServicesTableLib.uni | 23 + .../BasePciSegmentLib.c | 71 + .../BasePciSegmentLibSegmentInfo.inf | 46 + .../BasePciSegmentLibSegmentInfo.uni | 21 + .../DxeRuntimePciSegmentLib.c | 321 + .../DxeRuntimePciSegmentLibSegmentInfo.inf | 55 + .../DxeRuntimePciSegmentLibSegmentInfo.uni | 21 + .../PciSegmentLibCommon.c | 1375 +++ .../PciSegmentLibCommon.h | 57 + .../PeiCoreEntryPoint/PeiCoreEntryPoint.c | 101 + .../PeiCoreEntryPoint/PeiCoreEntryPoint.inf | 39 + .../PeiCoreEntryPoint/PeiCoreEntryPoint.uni | 21 + .../PeiDxePostCodeLibReportStatusCode.inf | 45 + .../PeiDxePostCodeLibReportStatusCode.uni | 21 + .../PostCode.c | 159 + .../PeiExtractGuidedSectionLib.c | 519 ++ .../PeiExtractGuidedSectionLib.inf | 48 + .../PeiExtractGuidedSectionLib.uni | 21 + .../edk2/MdePkg/Library/PeiHobLib/HobLib.c | 858 ++ .../MdePkg/Library/PeiHobLib/PeiHobLib.inf | 56 + .../MdePkg/Library/PeiHobLib/PeiHobLib.uni | 21 + .../Library/PeiIoLibCpuIo/IoHighLevel.c | 2356 +++++ .../edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c | 835 ++ .../Library/PeiIoLibCpuIo/IoLibMmioBuffer.c | 418 + .../Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf | 48 + .../Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni | 22 + .../MemoryAllocationLib.c | 848 ++ .../PeiMemoryAllocationLib.inf | 45 + .../PeiMemoryAllocationLib.uni | 22 + .../Library/PeiMemoryLib/CompareMemWrapper.c | 66 + .../Library/PeiMemoryLib/CopyMemWrapper.c | 63 + .../PeiMemoryLib/IsZeroBufferWrapper.c | 54 + .../edk2/MdePkg/Library/PeiMemoryLib/MemLib.c | 71 + .../Library/PeiMemoryLib/MemLibGeneric.c | 289 + .../MdePkg/Library/PeiMemoryLib/MemLibGuid.c | 171 + .../Library/PeiMemoryLib/MemLibInternals.h | 249 + .../Library/PeiMemoryLib/PeiMemoryLib.inf | 60 + .../Library/PeiMemoryLib/PeiMemoryLib.uni | 22 + .../Library/PeiMemoryLib/ScanMem16Wrapper.c | 67 + .../Library/PeiMemoryLib/ScanMem32Wrapper.c | 66 + .../Library/PeiMemoryLib/ScanMem64Wrapper.c | 67 + .../Library/PeiMemoryLib/ScanMem8Wrapper.c | 99 + .../Library/PeiMemoryLib/SetMem16Wrapper.c | 64 + .../Library/PeiMemoryLib/SetMem32Wrapper.c | 64 + .../Library/PeiMemoryLib/SetMem64Wrapper.c | 64 + .../Library/PeiMemoryLib/SetMemWrapper.c | 91 + .../Library/PeiMemoryLib/ZeroMemWrapper.c | 56 + .../edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c | 1625 ++++ .../MdePkg/Library/PeiPcdLib/PeiPcdLib.inf | 66 + .../MdePkg/Library/PeiPcdLib/PeiPcdLib.uni | 33 + .../MdePkg/Library/PeiPciLibPciCfg2/PciLib.c | 1422 +++ .../PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf | 56 + .../PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni | 25 + .../PeiPciSegmentLibPciCfg2/PciSegmentLib.c | 1414 +++ .../PeiPciSegmentLibPciCfg2.inf | 53 + .../PeiPciSegmentLibPciCfg2.uni | 24 + .../PeiResourcePublicationLib.c | 58 + .../PeiResourcePublicationLib.inf | 42 + .../PeiResourcePublicationLib.uni | 21 + .../Library/PeiServicesLib/PeiServicesLib.c | 817 ++ .../Library/PeiServicesLib/PeiServicesLib.inf | 48 + .../Library/PeiServicesLib/PeiServicesLib.uni | 21 + .../PeiServicesTablePointer.c | 116 + .../PeiServicesTablePointerLib.inf | 44 + .../PeiServicesTablePointerLib.uni | 23 + .../PeiServicesTablePointer.c | 131 + .../PeiServicesTablePointerLibIdt.inf | 43 + .../PeiServicesTablePointerLibIdt.uni | 22 + .../PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h | 80 + .../PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c | 95 + .../PeiSmbusLibSmbus2Ppi.inf | 50 + .../PeiSmbusLibSmbus2Ppi.uni | 21 + .../Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c | 584 ++ .../Library/PeimEntryPoint/PeimEntryPoint.c | 81 + .../Library/PeimEntryPoint/PeimEntryPoint.inf | 39 + .../Library/PeimEntryPoint/PeimEntryPoint.uni | 21 + .../SecPeiDxeTimerLibCpu.inf | 59 + .../SecPeiDxeTimerLibCpu.uni | 31 + .../SecPeiDxeTimerLibCpu/X86TimerLib.c | 375 + .../SmiHandlerProfileLibNull.c | 78 + .../SmiHandlerProfileLibNull.inf | 36 + .../SmiHandlerProfileLibNull.uni | 21 + .../edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c | 331 + .../edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf | 53 + .../edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni | 23 + .../Library/SmmIoLibSmmCpuIo2/IoHighLevel.c | 2312 +++++ .../MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c | 803 ++ .../SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c | 417 + .../SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h | 118 + .../SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf | 49 + .../SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni | 22 + .../MdePkg/Library/SmmLibNull/SmmLibNull.c | 103 + .../MdePkg/Library/SmmLibNull/SmmLibNull.inf | 37 + .../MdePkg/Library/SmmLibNull/SmmLibNull.uni | 21 + .../edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c | 658 ++ .../MdePkg/Library/SmmMemLib/SmmMemLib.inf | 62 + .../MdePkg/Library/SmmMemLib/SmmMemLib.uni | 24 + .../MemoryAllocationLib.c | 982 ++ .../SmmMemoryAllocationLib.inf | 50 + .../SmmMemoryAllocationLib.uni | 22 + .../Library/SmmPciExpressLib/PciExpressLib.c | 1430 +++ .../SmmPciExpressLib/SmmPciExpressLib.inf | 42 + .../Library/SmmPciLibPciRootBridgeIo/PciLib.c | 1434 +++ .../SmmPciLibPciRootBridgeIo.inf | 55 + .../SmmPciLibPciRootBridgeIo.uni | 25 + .../SmmPeriodicSmiLib/SmmPeriodicSmiLib.c | 1175 +++ .../SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf | 52 + .../SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni | 21 + .../SmmServicesTableLib/SmmServicesTableLib.c | 85 + .../SmmServicesTableLib.inf | 45 + .../SmmServicesTableLib.uni | 21 + .../StandaloneMmDriverEntryPoint.c | 87 + .../StandaloneMmDriverEntryPoint.inf | 43 + .../StandaloneMmDriverEntryPoint.uni | 22 + .../StandaloneMmServicesTableLib.c | 41 + .../StandaloneMmServicesTableLib.inf | 39 + .../StandaloneMmServicesTableLib.uni | 20 + .../ApplicationEntryPoint.c | 121 + .../UefiApplicationEntryPoint.inf | 40 + .../UefiApplicationEntryPoint.uni | 21 + .../UefiBootServicesTableLib.c | 66 + .../UefiBootServicesTableLib.inf | 40 + .../UefiBootServicesTableLib.uni | 21 + .../Library/UefiDebugLibConOut/DebugLib.c | 278 + .../UefiDebugLibConOut/UefiDebugLibConOut.inf | 54 + .../UefiDebugLibConOut/UefiDebugLibConOut.uni | 21 + .../UefiDebugLibDebugPortProtocol/DebugLib.c | 331 + .../UefiDebugLibDebugPortProtocol.inf | 57 + .../UefiDebugLibDebugPortProtocol.uni | 21 + .../Library/UefiDebugLibStdErr/DebugLib.c | 279 + .../UefiDebugLibStdErr/UefiDebugLibStdErr.inf | 52 + .../UefiDebugLibStdErr/UefiDebugLibStdErr.uni | 21 + .../UefiDevicePathLib/DevicePathFromText.c | 3672 ++++++++ .../UefiDevicePathLib/DevicePathToText.c | 2461 ++++++ .../UefiDevicePathLib/DevicePathUtilities.c | 903 ++ .../UefiDevicePathLib/UefiDevicePathLib.c | 360 + .../UefiDevicePathLib/UefiDevicePathLib.h | 457 + .../UefiDevicePathLib/UefiDevicePathLib.inf | 79 + .../UefiDevicePathLib/UefiDevicePathLib.uni | 21 + ...iDevicePathLibOptionalDevicePathProtocol.c | 484 + ...evicePathLibOptionalDevicePathProtocol.inf | 89 + ...evicePathLibOptionalDevicePathProtocol.uni | 23 + .../UefiDevicePathLib.c | 871 ++ .../UefiDevicePathLibDevicePathProtocol.inf | 61 + .../UefiDevicePathLibDevicePathProtocol.uni | 22 + .../UefiDriverEntryPoint/DriverEntryPoint.c | 173 + .../UefiDriverEntryPoint.inf | 67 + .../UefiDriverEntryPoint.uni | 21 + .../UefiFileHandleLib/UefiFileHandleLib.c | 1272 +++ .../UefiFileHandleLib/UefiFileHandleLib.inf | 48 + .../UefiFileHandleLib/UefiFileHandleLib.uni | 26 + .../edk2/MdePkg/Library/UefiLib/Acpi.c | 428 + .../edk2/MdePkg/Library/UefiLib/Console.c | 572 ++ .../MdePkg/Library/UefiLib/UefiDriverModel.c | 2026 +++++ .../edk2/MdePkg/Library/UefiLib/UefiLib.c | 2001 +++++ .../edk2/MdePkg/Library/UefiLib/UefiLib.inf | 93 + .../edk2/MdePkg/Library/UefiLib/UefiLib.uni | 25 + .../MdePkg/Library/UefiLib/UefiLibInternal.h | 44 + .../MdePkg/Library/UefiLib/UefiLibPrint.c | 822 ++ .../MdePkg/Library/UefiLib/UefiNotTiano.c | 336 + .../MemoryAllocationLib.c | 821 ++ .../UefiMemoryAllocationLib.inf | 42 + .../UefiMemoryAllocationLib.uni | 22 + .../Library/UefiMemoryLib/CompareMemWrapper.c | 66 + .../Library/UefiMemoryLib/CopyMemWrapper.c | 63 + .../UefiMemoryLib/IsZeroBufferWrapper.c | 54 + .../MdePkg/Library/UefiMemoryLib/MemLib.c | 63 + .../Library/UefiMemoryLib/MemLibGeneric.c | 289 + .../MdePkg/Library/UefiMemoryLib/MemLibGuid.c | 171 + .../Library/UefiMemoryLib/MemLibInternals.h | 249 + .../Library/UefiMemoryLib/ScanMem16Wrapper.c | 67 + .../Library/UefiMemoryLib/ScanMem32Wrapper.c | 66 + .../Library/UefiMemoryLib/ScanMem64Wrapper.c | 67 + .../Library/UefiMemoryLib/ScanMem8Wrapper.c | 99 + .../Library/UefiMemoryLib/SetMem16Wrapper.c | 64 + .../Library/UefiMemoryLib/SetMem32Wrapper.c | 64 + .../Library/UefiMemoryLib/SetMem64Wrapper.c | 64 + .../Library/UefiMemoryLib/SetMemWrapper.c | 91 + .../Library/UefiMemoryLib/UefiMemoryLib.inf | 60 + .../Library/UefiMemoryLib/UefiMemoryLib.uni | 22 + .../Library/UefiMemoryLib/ZeroMemWrapper.c | 56 + .../UefiPciLibPciRootBridgeIo/PciLib.c | 1434 +++ .../UefiPciLibPciRootBridgeIo.inf | 57 + .../UefiPciLibPciRootBridgeIo.uni | 25 + .../PciSegmentLib.c | 1491 ++++ .../PciSegmentLib.h | 58 + .../UefiPciSegmentLibPciRootBridgeIo.inf | 60 + .../UefiPciSegmentLibPciRootBridgeIo.uni | 25 + .../Library/UefiRuntimeLib/RuntimeLib.c | 843 ++ .../Library/UefiRuntimeLib/UefiRuntimeLib.inf | 51 + .../Library/UefiRuntimeLib/UefiRuntimeLib.uni | 23 + .../UefiRuntimeServicesTableLib.c | 49 + .../UefiRuntimeServicesTableLib.inf | 41 + .../UefiRuntimeServicesTableLib.uni | 21 + .../MdePkg/Library/UefiScsiLib/UefiScsiLib.c | 2067 +++++ .../Library/UefiScsiLib/UefiScsiLib.inf | 47 + .../Library/UefiScsiLib/UefiScsiLib.uni | 22 + .../edk2/MdePkg/Library/UefiUsbLib/Hid.c | 488 + .../MdePkg/Library/UefiUsbLib/UefiUsbLib.inf | 48 + .../MdePkg/Library/UefiUsbLib/UefiUsbLib.uni | 22 + .../Library/UefiUsbLib/UefiUsbLibInternal.h | 29 + .../MdePkg/Library/UefiUsbLib/UsbDxeLib.c | 672 ++ .../edk2/MdePkg/MdePkg.dec | 2307 +++++ .../edk2/MdePkg/MdePkg.dsc | 158 + .../edk2/MdePkg/MdePkg.uni | 413 + .../edk2/MdePkg/MdePkgExtra.uni | 20 + .../Voyager-2 (1703-1511)/edk2/OpensslLib.lib | Bin 0 -> 46687900 bytes .../Application/Shell/ConsoleLogger.c | 1243 +++ .../Application/Shell/ConsoleLogger.h | 323 + .../Application/Shell/ConsoleWrappers.c | 514 ++ .../Application/Shell/ConsoleWrappers.h | 80 + .../Application/Shell/FileHandleInternal.h | 65 + .../Application/Shell/FileHandleWrappers.c | 2153 +++++ .../Application/Shell/FileHandleWrappers.h | 93 + .../edk2/ShellPkg/Application/Shell/Shell.c | 3189 +++++++ .../edk2/ShellPkg/Application/Shell/Shell.h | 396 + .../edk2/ShellPkg/Application/Shell/Shell.inf | 110 + .../edk2/ShellPkg/Application/Shell/Shell.uni | 58 + .../ShellPkg/Application/Shell/ShellEnvVar.c | 578 ++ .../ShellPkg/Application/Shell/ShellEnvVar.h | 288 + .../Application/Shell/ShellManParser.c | 754 ++ .../Application/Shell/ShellManParser.h | 84 + .../Shell/ShellParametersProtocol.c | 1417 +++ .../Shell/ShellParametersProtocol.h | 215 + .../Application/Shell/ShellProtocol.c | 3835 ++++++++ .../Application/Shell/ShellProtocol.h | 944 ++ .../Application/ShellCTestApp/README.txt | 5 + .../Application/ShellCTestApp/ShellCTestApp.c | 51 + .../ShellCTestApp/ShellCTestApp.inf | 39 + .../Application/ShellCTestApp/TestArgv.log | Bin 0 -> 3320 bytes .../Application/ShellCTestApp/TestArgv.nsh | 64 + .../Application/ShellExecTestApp/SA.c | 38 + .../Application/ShellExecTestApp/SA.inf | 41 + .../ShellSortTestApp/ShellSortTestApp.c | 83 + .../ShellSortTestApp/ShellSortTestApp.inf | 42 + .../DynamicCommand/DpDynamicCommand/Dp.c | 972 ++ .../DynamicCommand/DpDynamicCommand/Dp.h | 146 + .../DynamicCommand/DpDynamicCommand/Dp.uni | 134 + .../DynamicCommand/DpDynamicCommand/DpApp.c | 53 + .../DynamicCommand/DpDynamicCommand/DpApp.inf | 69 + .../DpDynamicCommand/DpDynamicCommand.c | 131 + .../DpDynamicCommand/DpDynamicCommand.inf | 73 + .../DpDynamicCommand/DpInternal.h | 321 + .../DynamicCommand/DpDynamicCommand/DpTrace.c | 910 ++ .../DpDynamicCommand/DpUtilities.c | 428 + .../DpDynamicCommand/Literals.c | 28 + .../DpDynamicCommand/Literals.h | 32 + .../DynamicCommand/TftpDynamicCommand/Tftp.c | 1135 +++ .../DynamicCommand/TftpDynamicCommand/Tftp.h | 75 + .../TftpDynamicCommand/Tftp.uni | 100 + .../TftpDynamicCommand/TftpApp.c | 54 + .../TftpDynamicCommand/TftpApp.inf | 59 + .../TftpDynamicCommand/TftpDynamicCommand.c | 132 + .../TftpDynamicCommand/TftpDynamicCommand.inf | 64 + .../ShellPkg/Include/Guid/ShellAliasGuid.h | 25 + .../Include/Guid/ShellEnvironment2Ext.h | 25 + .../ShellPkg/Include/Guid/ShellLibHiiGuid.h | 86 + .../edk2/ShellPkg/Include/Guid/ShellMapGuid.h | 25 + .../Include/Guid/ShellPkgTokenSpace.h | 25 + .../ShellPkg/Include/Guid/ShellVariableGuid.h | 25 + .../ShellPkg/Include/Library/BcfgCommandLib.h | 52 + .../Include/Library/HandleParsingLib.h | 410 + .../ShellPkg/Include/Library/ShellCEntryLib.h | 40 + .../Include/Library/ShellCommandLib.h | 723 ++ .../edk2/ShellPkg/Include/Library/ShellLib.h | 1438 +++ .../Include/Protocol/EfiShellEnvironment2.h | 975 ++ .../Include/Protocol/EfiShellInterface.h | 94 + .../UefiHandleParsingLib.c | 3745 ++++++++ .../UefiHandleParsingLib.h | 300 + .../UefiHandleParsingLib.inf | 356 + .../UefiHandleParsingLib.uni | 529 ++ .../UefiShellAcpiViewCommandLib/AcpiParser.c | 692 ++ .../UefiShellAcpiViewCommandLib/AcpiParser.h | 815 ++ .../AcpiTableParser.c | 220 + .../AcpiTableParser.h | 133 + .../UefiShellAcpiViewCommandLib/AcpiView.c | 627 ++ .../UefiShellAcpiViewCommandLib/AcpiView.h | 116 + .../Parsers/Bgrt/BgrtParser.c | 71 + .../Parsers/Dbg2/Dbg2Parser.c | 250 + .../Parsers/Dsdt/DsdtParser.c | 48 + .../Parsers/Fadt/FadtParser.c | 289 + .../Parsers/Gtdt/GtdtParser.c | 306 + .../Parsers/Iort/IortParser.c | 723 ++ .../Parsers/Madt/MadtParser.c | 324 + .../Parsers/Mcfg/McfgParser.c | 96 + .../Parsers/Pptt/PpttParser.c | 362 + .../Parsers/Rsdp/RsdpParser.c | 181 + .../Parsers/Slit/SlitParser.c | 145 + .../Parsers/Spcr/SpcrParser.c | 180 + .../Parsers/Srat/SratParser.c | 350 + .../Parsers/Ssdt/SsdtParser.c | 48 + .../Parsers/Xsdt/XsdtParser.c | 156 + .../UefiShellAcpiViewCommandLib.c | 174 + .../UefiShellAcpiViewCommandLib.h | 32 + .../UefiShellAcpiViewCommandLib.inf | 78 + .../UefiShellAcpiViewCommandLib.uni | 134 + .../UefiShellBcfgCommandLib.c | 1906 ++++ .../UefiShellBcfgCommandLib.inf | 47 + .../UefiShellBcfgCommandLib.uni | 159 + .../UefiShellCEntryLib/UefiShellCEntryLib.c | 99 + .../UefiShellCEntryLib/UefiShellCEntryLib.inf | 44 + .../UefiShellCommandLib/ConsistMapping.c | 1698 ++++ .../UefiShellCommandLib/UefiShellCommandLib.c | 1905 ++++ .../UefiShellCommandLib/UefiShellCommandLib.h | 71 + .../UefiShellCommandLib.inf | 69 + .../Library/UefiShellDebug1CommandsLib/Comp.c | 378 + .../UefiShellDebug1CommandsLib/Compress.c | 1388 +++ .../UefiShellDebug1CommandsLib/Compress.h | 39 + .../Library/UefiShellDebug1CommandsLib/Dblk.c | 207 + .../Library/UefiShellDebug1CommandsLib/Dmem.c | 233 + .../UefiShellDebug1CommandsLib/DmpStore.c | 865 ++ .../UefiShellDebug1CommandsLib/Edit/Edit.c | 162 + .../Edit/FileBuffer.c | 3325 +++++++ .../Edit/FileBuffer.h | 246 + .../Edit/MainTextEditor.c | 1980 +++++ .../Edit/MainTextEditor.h | 72 + .../UefiShellDebug1CommandsLib/Edit/Misc.c | 90 + .../UefiShellDebug1CommandsLib/Edit/Misc.h | 50 + .../Edit/TextEditStrings.uni | 75 + .../Edit/TextEditor.h | 32 + .../Edit/TextEditorTypes.h | 103 + .../UefiShellDebug1CommandsLib/EditInputBar.c | 330 + .../UefiShellDebug1CommandsLib/EditInputBar.h | 87 + .../UefiShellDebug1CommandsLib/EditMenuBar.c | 216 + .../UefiShellDebug1CommandsLib/EditMenuBar.h | 119 + .../EditStatusBar.c | 230 + .../EditStatusBar.h | 102 + .../UefiShellDebug1CommandsLib/EditTitleBar.c | 207 + .../UefiShellDebug1CommandsLib/EditTitleBar.h | 74 + .../UefiShellDebug1CommandsLib/EfiCompress.c | 164 + .../EfiDecompress.c | 186 + .../HexEdit/BufferImage.c | 2475 ++++++ .../HexEdit/BufferImage.h | 273 + .../HexEdit/Clipboard.c | 112 + .../HexEdit/Clipboard.h | 69 + .../HexEdit/DiskImage.c | 417 + .../HexEdit/DiskImage.h | 95 + .../HexEdit/FileImage.c | 398 + .../HexEdit/FileImage.h | 83 + .../HexEdit/HexEdit.c | 277 + .../HexEdit/HexEditor.h | 41 + .../HexEdit/HexEditorTypes.h | 126 + .../HexEdit/HexeditStrings.uni | 76 + .../HexEdit/MainHexEditor.c | 2378 +++++ .../HexEdit/MainHexEditor.h | 75 + .../HexEdit/MemImage.c | 284 + .../HexEdit/MemImage.h | 92 + .../UefiShellDebug1CommandsLib/HexEdit/Misc.c | 262 + .../UefiShellDebug1CommandsLib/HexEdit/Misc.h | 93 + .../UefiShellDebug1CommandsLib/LoadPciRom.c | 409 + .../UefiShellDebug1CommandsLib/MemMap.c | 410 + .../Library/UefiShellDebug1CommandsLib/Mm.c | 637 ++ .../Library/UefiShellDebug1CommandsLib/Mode.c | 128 + .../Library/UefiShellDebug1CommandsLib/Pci.c | 5803 ++++++++++++ .../Library/UefiShellDebug1CommandsLib/Pci.h | 64 + .../UefiShellDebug1CommandsLib/SerMode.c | 371 + .../UefiShellDebug1CommandsLib/SetSize.c | 110 + .../UefiShellDebug1CommandsLib/SetVar.c | 475 + .../SmbiosView/EventLogInfo.c | 407 + .../SmbiosView/EventLogInfo.h | 112 + .../SmbiosView/LibSmbiosView.c | 373 + .../SmbiosView/LibSmbiosView.h | 159 + .../SmbiosView/PrintInfo.c | 3427 +++++++ .../SmbiosView/PrintInfo.h | 436 + .../SmbiosView/QueryTable.c | 4723 ++++++++++ .../SmbiosView/QueryTable.h | 818 ++ .../SmbiosView/SmbiosView.c | 1005 +++ .../SmbiosView/SmbiosView.h | 129 + .../SmbiosView/SmbiosViewStrings.uni | 506 ++ .../UefiShellDebug1CommandsLib.c | 427 + .../UefiShellDebug1CommandsLib.h | 383 + .../UefiShellDebug1CommandsLib.inf | 137 + .../UefiShellDebug1CommandsLib.uni | 1178 +++ .../UefiShellDriver1CommandsLib/Connect.c | 549 ++ .../UefiShellDriver1CommandsLib/DevTree.c | 277 + .../UefiShellDriver1CommandsLib/Devices.c | 269 + .../Library/UefiShellDriver1CommandsLib/Dh.c | 1197 +++ .../UefiShellDriver1CommandsLib/Disconnect.c | 204 + .../UefiShellDriver1CommandsLib/Drivers.c | 429 + .../UefiShellDriver1CommandsLib/DrvCfg.c | 1412 +++ .../UefiShellDriver1CommandsLib/DrvDiag.c | 463 + .../UefiShellDriver1CommandsLib/OpenInfo.c | 216 + .../UefiShellDriver1CommandsLib/Reconnect.c | 99 + .../UefiShellDriver1CommandsLib.c | 104 + .../UefiShellDriver1CommandsLib.h | 228 + .../UefiShellDriver1CommandsLib.inf | 73 + .../UefiShellDriver1CommandsLib.uni | 759 ++ .../UefiShellDriver1CommandsLib/Unload.c | 148 + .../UefiShellInstall1CommandsLib.c | 59 + .../UefiShellInstall1CommandsLib.inf | 51 + .../Library/UefiShellLevel1CommandsLib/Exit.c | 97 + .../Library/UefiShellLevel1CommandsLib/For.c | 751 ++ .../Library/UefiShellLevel1CommandsLib/Goto.c | 105 + .../Library/UefiShellLevel1CommandsLib/If.c | 1111 +++ .../UefiShellLevel1CommandsLib/Shift.c | 64 + .../UefiShellLevel1CommandsLib/Stall.c | 84 + .../UefiShellLevel1CommandsLib.c | 308 + .../UefiShellLevel1CommandsLib.h | 209 + .../UefiShellLevel1CommandsLib.inf | 58 + .../UefiShellLevel1CommandsLib.uni | 504 ++ .../UefiShellLevel2CommandsLib/Attrib.c | 277 + .../Library/UefiShellLevel2CommandsLib/Cd.c | 351 + .../Library/UefiShellLevel2CommandsLib/Cp.c | 779 ++ .../Library/UefiShellLevel2CommandsLib/Load.c | 279 + .../Library/UefiShellLevel2CommandsLib/Ls.c | 874 ++ .../Library/UefiShellLevel2CommandsLib/Map.c | 1302 +++ .../UefiShellLevel2CommandsLib/MkDir.c | 167 + .../Library/UefiShellLevel2CommandsLib/Mv.c | 863 ++ .../UefiShellLevel2CommandsLib/Parse.c | 317 + .../UefiShellLevel2CommandsLib/Reset.c | 170 + .../Library/UefiShellLevel2CommandsLib/Rm.c | 380 + .../Library/UefiShellLevel2CommandsLib/Set.c | 174 + .../UefiShellLevel2CommandsLib/TimeDate.c | 972 ++ .../UefiShellLevel2CommandsLib.c | 350 + .../UefiShellLevel2CommandsLib.h | 369 + .../UefiShellLevel2CommandsLib.inf | 84 + .../UefiShellLevel2CommandsLib.uni | 1085 +++ .../Library/UefiShellLevel2CommandsLib/Vol.c | 313 + .../UefiShellLevel3CommandsLib/Alias.c | 286 + .../Library/UefiShellLevel3CommandsLib/Cls.c | 230 + .../Library/UefiShellLevel3CommandsLib/Echo.c | 121 + .../UefiShellLevel3CommandsLib/GetMtc.c | 97 + .../Library/UefiShellLevel3CommandsLib/Help.c | 474 + .../UefiShellLevel3CommandsLib/Pause.c | 107 + .../UefiShellLevel3CommandsLib/Touch.c | 292 + .../Library/UefiShellLevel3CommandsLib/Type.c | 327 + .../UefiShellLevel3CommandsLib.c | 101 + .../UefiShellLevel3CommandsLib.h | 161 + .../UefiShellLevel3CommandsLib.inf | 74 + .../UefiShellLevel3CommandsLib.uni | 545 ++ .../Library/UefiShellLevel3CommandsLib/Ver.c | 153 + .../Library/UefiShellLib/UefiShellLib.c | 4375 +++++++++ .../Library/UefiShellLib/UefiShellLib.h | 96 + .../Library/UefiShellLib/UefiShellLib.inf | 70 + .../UefiShellNetwork1CommandsLib/Ifconfig.c | 1447 +++ .../UefiShellNetwork1CommandsLib/Ping.c | 1713 ++++ .../UefiShellNetwork1CommandsLib.c | 90 + .../UefiShellNetwork1CommandsLib.h | 76 + .../UefiShellNetwork1CommandsLib.inf | 68 + .../UefiShellNetwork1CommandsLib.uni | 182 + .../UefiShellNetwork2CommandsLib/Ifconfig6.c | 1912 ++++ .../UefiShellNetwork2CommandsLib/Ping6.c | 1373 +++ .../UefiShellNetwork2CommandsLib.c | 91 + .../UefiShellNetwork2CommandsLib.h | 72 + .../UefiShellNetwork2CommandsLib.inf | 64 + .../UefiShellNetwork2CommandsLib.uni | 167 + .../edk2/ShellPkg/ShellPkg.dec | 140 + .../edk2/ShellPkg/ShellPkg.dsc | 136 + .../edk2/UefiApplicationEntryPoint.lib | Bin 0 -> 7758 bytes .../edk2/UefiBootServicesTableLib.lib | Bin 0 -> 8616 bytes .../edk2/UefiDebugLibConOut.lib | Bin 0 -> 11316 bytes .../UefiDevicePathLibDevicePathProtocol.lib | Bin 0 -> 25448 bytes .../edk2/UefiDriverEntryPoint.lib | Bin 0 -> 9754 bytes .../edk2/UefiFileHandleLib.lib | Bin 0 -> 30844 bytes .../Voyager-2 (1703-1511)/edk2/UefiHiiLib.lib | Bin 0 -> 136052 bytes .../edk2/UefiHiiServicesLib.lib | Bin 0 -> 13228 bytes .../Voyager-2 (1703-1511)/edk2/UefiLib.lib | Bin 0 -> 179896 bytes .../edk2/UefiMemoryAllocationLib.lib | Bin 0 -> 21532 bytes .../edk2/UefiMemoryLib.lib | Bin 0 -> 63718 bytes .../edk2/UefiRuntimeLib.lib | Bin 0 -> 19480 bytes .../edk2/UefiRuntimeServicesTableLib.lib | Bin 0 -> 7630 bytes .../edk2/UefiShellLib.lib | Bin 0 -> 124928 bytes .../edk2/UefiSortLib.lib | Bin 0 -> 13586 bytes Voyager-2/Voyager-2 (2004-1709)/Hvax64.c | 32 +- Voyager-2/Voyager-2 (2004-1709)/Hvax64.h | 2 +- Voyager-2/Voyager-2 (2004-1709)/PayLoad.h | 2 +- Voyager-2/Voyager-2 (2004-1709)/WinLoad.c | 2 +- Voyager-2/Voyager-2.sln | 16 +- 2112 files changed, 494160 insertions(+), 26 deletions(-) create mode 100644 Voyager-2/Voyager-2 (1703-1511)/BootMgfw.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/BootMgfw.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/HvLoader.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/HvLoader.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Hvax64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Hvax64.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/PayLoad.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/PayLoad.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/ShitHook.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/ShitHook.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/UefiMain.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Utils.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Utils.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.filters create mode 100644 Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.user create mode 100644 Voyager-2/Voyager-2 (1703-1511)/WinLoad.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/WinLoad.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCacheMaintenanceLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCpuLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCryptLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseDebugPrintErrorLevelLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseMemoryLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BasePrintLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/BaseSynchronizationLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.dec create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.dsc create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkgExtra.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/BaseCryptLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/TlsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAes.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdes.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdesNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/InternalCryptLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticodeNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDh.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDhNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7SignNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyBase.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyRuntime.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExtNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTsNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandItc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/BaseMemAllocation.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/ConstantTimeClock.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/RuntimeMemAllocation.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/CrtLibSupport.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/assert.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/ctype.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/errno.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/internal/dso_conf.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/limits.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/memory.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/openssl/opensslconf.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdarg.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stddef.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdio.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdlib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/string.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/strings.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/time.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/types.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/syslog.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/time.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/unistd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/BaseIntrinsicLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/CopyMem.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/MemoryIntrinsics.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpenSSL-HOWTO.txt create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/buildinf.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/process_files.pl create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/InternalTlsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsConfig.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsInit.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsProcess.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/GlueLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/IntrinsicLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/AArch64/ProcessorBind.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Arm/ProcessorBind.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Base.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ebc/ProcessorBind.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Acpi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Apriori.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/AprioriFileName.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Btt.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/CapsuleReport.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Cper.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DebugImageInfoTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DxeServices.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventGroup.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventLegacyBios.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemVolumeLabelInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareContentsSigned.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem3.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FmpCapsule.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GlobalVariable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Gpt.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GraphicsInfoHob.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HardwareErrorVariable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiFormMapMethodGuid.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiKeyBoardLayout.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiPlatformSetupFormset.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HobList.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/ImageAuthentication.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MdePkgTokenSpace.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAllocationHob.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAttributesTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryOverwriteControl.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Mps.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PcAnsi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PropertiesTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SalSystemTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SmBios.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/StatusCodeDataTypeId.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SystemResourceTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/VectorHandoffTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/WinCertificate.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/Nasm.inc create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/ProcessorBind.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi10.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi20.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi30.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi40.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi50.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi51.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi60.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi61.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi62.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AcpiAml.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AlertStandardFormatTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Atapi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bluetooth.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bmp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPort2Table.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPortTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Dhcp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ElTorito.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Emmc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/HighPrecisionEventTimerTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Hsti.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Http11.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IScsiBootFirmwareTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IoRemappingTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Ipmi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiFruInformationStorage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnApp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnBridge.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnChassis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnFirmware.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnGroupExtension.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnStorage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnTransport.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LegacyBiosMpTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LowPowerIdleTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Mbr.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryOverwriteRequestControlLock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Nvme.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci22.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci23.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci30.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciCodeId.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress21.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress30.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress31.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress40.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PeImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Scsi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr3.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdLpDdr.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ServiceProcessorManagementInterfaceTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBios.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBus.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgPhysicalPresence.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageCore.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageOpal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcpaAcpi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tls1.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm12.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm20.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm2Acpi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmPtp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmTis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Udf.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Usb.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogActionTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogResourceTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsSmmSecurityMitigationTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsUxCapsule.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseMemoryLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CacheMaintenanceLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CpuLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugPrintErrorLevelLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DevicePathLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeCoreEntryPoint.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesTableLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtendedSalLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtractGuidedSectionLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/FileHandleLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HobLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HstiLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/IoLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MemoryAllocationLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MmServicesTableLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/OrderedCollectionLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PalLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PcdLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciCf8Lib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciExpressLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentInfoLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffExtraActionLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffGetEntryPointLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiCoreEntryPoint.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesTablePointerLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeimEntryPoint.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PerformanceLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PostCodeLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PrintLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ReportStatusCodeLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ResourcePublicationLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/RngLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3BootScriptLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3IoLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciSegmentLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3SmbusLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3StallLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SafeIntLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SalLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SerialPortLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmbusLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmiHandlerProfileLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmIoLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmMemLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmPeriodicSmiLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmServicesTableLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SynchronizationLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/TimerLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiApplicationEntryPoint.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiBootServicesTableLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDecompressLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDriverEntryPoint.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiScsiLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiUsbLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiBootMode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDependency.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDxeCis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareFile.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareVolume.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiHob.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiI2c.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMmCis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMultiPhase.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiPeiCis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiS3BootScript.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiSmmCis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiStatusCode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiDxe.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiMm.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiPei.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiSmm.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BootInRecoveryMode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Capsule.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/CpuIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Decompress.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DeviceRecoveryModule.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DxeIpl.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/EndOfPeiPhase.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolume.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Graphics.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/GuidedSectionExtraction.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/I2cMaster.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/IsaHc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadFile.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MasterBootMode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MemoryDiscovered.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MpServices.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Pcd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PcdInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PciCfg2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PeiCoreFvLocation.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcdInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReadOnlyVariable2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/RecoveryModule.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReportStatusCodeHandler.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/S3Resume2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecHobData.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Security2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Smbus2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Stall.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/StatusCode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SuperIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamDone.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamSupport.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/VectorHandoffInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AbsolutePointer.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiSystemDescriptionTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AdapterInformation.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Arp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AtaPassThru.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AuthenticationInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bds.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bis.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIoCrypto.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothAttribute.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothConfig.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothHc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothLeConfig.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BootManagerPolicy.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BusSpecificDriverOverride.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Capsule.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Cpu.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/CpuIo2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugPort.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugSupport.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Decompress.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeferredImageLoad.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeviceIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePath.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathFromText.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathToText.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathUtilities.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp6.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns6.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverBinding.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverFamilyOverride.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverHealth.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverSupportedEfiVersion.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeMmReadyToLock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeSmmReadyToLock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Eap.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ebc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidActive.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidDiscovered.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidOverride.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EraseBlock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalBootService.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalServiceClasses.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareManagement.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolume2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolumeBlock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FormBrowser2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ftp4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GraphicsOutput.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GuidedSectionExtraction.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigAccess.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigKeyword.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigRouting.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiDatabase.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiFont.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageDecoder.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageEx.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPackageList.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPopup.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiString.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Http.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpBootCallback.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpUtilities.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cBusConfigurationManagement.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cEnumerate.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cHost.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cMaster.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IScsiInitiatorName.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IdeControllerInit.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6Config.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSec.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSecConfig.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IsaHc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Kms.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacyRegion2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiController.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiFlash.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmController.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmFlash.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadedImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ManagedNetwork.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/McaInitPmi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Metronome.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmAccess.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmBase.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCommunication.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmControl.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpu.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpuIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmEndOfDxe.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmGpiDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmIoTrapDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPciRootBridgeIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPeriodicTimerDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPowerButtonDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReadyToLock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReportStatusCodeHandler.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStandbyButtonDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStatusCode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSwDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSxDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmUsbDispatch.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MonotonicCounter.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MpService.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp6.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NetworkInterfaceIdentifier.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvdimmLabel.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvmExpressPassthru.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PartitionInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pcd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PcdInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciEnumerationComplete.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugInit.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugRequest.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciOverride.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciPlatform.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciRootBridgeIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcd.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcdInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pkcs7Verify.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformDriverOverride.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformToDriverConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RamDisk.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RealTimeClock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RegularExpressionProtocol.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ReportStatusCodeHandler.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Reset.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ResetNotification.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rest.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rng.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Runtime.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SaveState.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SmmSaveState.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThru.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThruExt.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SdMmcPassThru.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SecurityPolicy.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SerialIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ServiceBinding.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Shell.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellDynamicCommand.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellParameters.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleFileSystem.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleNetwork.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimplePointer.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextIn.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextInEx.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextOut.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardEdge.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardReader.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Smbios.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmbusHc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmAccess2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmBase2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCommunication.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmControl2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpu.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpuIo2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmEndOfDxe.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmGpiDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmIoTrapDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPciRootBridgeIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPowerButtonDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReadyToLock.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReportStatusCodeHandler.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStandbyButtonDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStatusCode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSwDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSxDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmUsbDispatch2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiHc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiNorFlash.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmConfiguration.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmHc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmNorFlash.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StatusCode.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StorageSecurityCommand.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIoControl.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Supplicant.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TapeIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcg2Protocol.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TcgService.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp6.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timer.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timestamp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tls.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TlsConfig.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TrEEProtocol.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp4.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp6.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UfsDeviceConfig.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaDraw.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UnicodeCollation.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Usb2HostController.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbFunctionIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbHostController.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbIo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserManager.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Variable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VariableWrite.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VlanConfig.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WatchdogTimer.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiAcpiDataTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiBaseType.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiGpt.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiMultiPhase.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiPxe.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiSpec.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/Nasm.inc create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/ProcessorBind.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibIcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ARShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Math64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BitField.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CheckSum.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Cpu.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/FilePaths.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LinkedList.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LongJump.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Math64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ModU64x32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultS64x64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RShiftU64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SafeString.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SetJump.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/String.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes16.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwitchStack.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Unaligned.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/GccInline.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxRestore.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxSave.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Msr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86RdRand.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Thunk.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRng.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/HobLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/Allocate.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/HobLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Acpi.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Console.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/Hid.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dec create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dsc create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkgExtra.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/OpensslLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/README.txt create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/TestArgv.log create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/TestArgv.nsh create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellAliasGuid.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellEnvironment2Ext.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellLibHiiGuid.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellMapGuid.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellPkgTokenSpace.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellVariableGuid.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/BcfgCommandLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/HandleParsingLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCEntryLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCommandLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellEnvironment2.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellInterface.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dec create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dsc create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiApplicationEntryPoint.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiBootServicesTableLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiDebugLibConOut.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiDevicePathLibDevicePathProtocol.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiDriverEntryPoint.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiFileHandleLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiHiiLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiHiiServicesLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiMemoryAllocationLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiMemoryLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiRuntimeLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiRuntimeServicesTableLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiShellLib.lib create mode 100644 Voyager-2/Voyager-2 (1703-1511)/edk2/UefiSortLib.lib diff --git a/Voyager-2/PayLoad/types.h b/Voyager-2/PayLoad/types.h index 7d77fc4..4ce790a 100644 --- a/Voyager-2/PayLoad/types.h +++ b/Voyager-2/PayLoad/types.h @@ -5,7 +5,7 @@ #include #include -#define WINVER 1709 +#define WINVER 1511 #define VMEXIT_KEY 0xDEADBEEFDEADBEEF #define PORT_NUM 0x2F8 @@ -36,6 +36,18 @@ #define offset_vmcb_base 0x82F0 #define offset_vmcb_link 0x88 #define offset_vmcb 0xC80 +#elif WINVER == 1703 +#define offset_vmcb_base 0x82F0 +#define offset_vmcb_link 0x80 +#define offset_vmcb 0xBC0 +#elif WINVER == 1607 +#define offset_vmcb_base 0x82F0 +#define offset_vmcb_link 0x90 +#define offset_vmcb 0xBC0 +#elif WINVER == 1511 +#define offset_vmcb_base 0x82F0 +#define offset_vmcb_link 0x90 +#define offset_vmcb 0xC40 #endif using u8 = unsigned char; diff --git a/Voyager-2/Voyager-2 (1703-1511)/BootMgfw.c b/Voyager-2/Voyager-2 (1703-1511)/BootMgfw.c new file mode 100644 index 0000000..2fdb74b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/BootMgfw.c @@ -0,0 +1,178 @@ +#include "BootMgfw.h" + +SHITHOOK BootMgfwShitHook; +EFI_STATUS EFIAPI RestoreBootMgfw(VOID) +{ + UINTN HandleCount = NULL; + EFI_STATUS Result; + EFI_HANDLE* Handles = NULL; + EFI_FILE_HANDLE VolumeHandle; + EFI_FILE_HANDLE BootMgfwHandle; + EFI_FILE_IO_INTERFACE* FileSystem = NULL; + + if (EFI_ERROR((Result = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles)))) + { + DBG_PRINT("error getting file system handles -> 0x%p\n", Result); + return Result; + } + + for (UINT32 Idx = 0u; Idx < HandleCount; ++Idx) + { + if (EFI_ERROR((Result = gBS->OpenProtocol(Handles[Idx], &gEfiSimpleFileSystemProtocolGuid, (VOID**)&FileSystem, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)))) + { + DBG_PRINT("error opening protocol -> 0x%p\n", Result); + return Result; + } + + if (EFI_ERROR((Result = FileSystem->OpenVolume(FileSystem, &VolumeHandle)))) + { + DBG_PRINT("error opening file system -> 0x%p\n", Result); + return Result; + } + + if (!EFI_ERROR((Result = VolumeHandle->Open(VolumeHandle, &BootMgfwHandle, WINDOWS_BOOTMGFW_PATH, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY)))) + { + VolumeHandle->Close(VolumeHandle); + EFI_FILE_PROTOCOL* BootMgfwFile = NULL; + EFI_DEVICE_PATH* BootMgfwPathProtocol = FileDevicePath(Handles[Idx], WINDOWS_BOOTMGFW_PATH); + + // open bootmgfw as read/write then delete it... + if (EFI_ERROR((Result = EfiOpenFileByDevicePath(&BootMgfwPathProtocol, &BootMgfwFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, NULL)))) + { + DBG_PRINT("error opening bootmgfw... reason -> %r\n", Result); + return Result; + } + + if (EFI_ERROR((Result = BootMgfwFile->Delete(BootMgfwFile)))) + { + DBG_PRINT("error deleting bootmgfw... reason -> %r\n", Result); + return Result; + } + + // open bootmgfw.efi.backup + BootMgfwPathProtocol = FileDevicePath(Handles[Idx], WINDOWS_BOOTMGFW_BACKUP_PATH); + if (EFI_ERROR((Result = EfiOpenFileByDevicePath(&BootMgfwPathProtocol, &BootMgfwFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, NULL)))) + { + DBG_PRINT("failed to open backup file... reason -> %r\n", Result); + return Result; + } + + EFI_FILE_INFO* FileInfoPtr = NULL; + UINTN FileInfoSize = NULL; + + // get the size of bootmgfw.efi.backup... + if (EFI_ERROR((Result = BootMgfwFile->GetInfo(BootMgfwFile, &gEfiFileInfoGuid, &FileInfoSize, NULL)))) + { + if (Result == EFI_BUFFER_TOO_SMALL) + { + gBS->AllocatePool(EfiBootServicesData, FileInfoSize, &FileInfoPtr); + if (EFI_ERROR(Result = BootMgfwFile->GetInfo(BootMgfwFile, &gEfiFileInfoGuid, &FileInfoSize, FileInfoPtr))) + { + DBG_PRINT("get backup file information failed... reason -> %r\n", Result); + return Result; + } + } + else + { + DBG_PRINT("Failed to get file information... reason -> %r\n", Result); + return Result; + } + } + + VOID* BootMgfwBuffer = NULL; + UINTN BootMgfwSize = FileInfoPtr->FileSize; + gBS->AllocatePool(EfiBootServicesData, FileInfoPtr->FileSize, &BootMgfwBuffer); + + // read the backup file into an allocated pool... + if (EFI_ERROR((Result = BootMgfwFile->Read(BootMgfwFile, &BootMgfwSize, BootMgfwBuffer)))) + { + DBG_PRINT("Failed to read backup file into buffer... reason -> %r\n", Result); + return Result; + } + + // delete the backup file... + if (EFI_ERROR((Result = BootMgfwFile->Delete(BootMgfwFile)))) + { + DBG_PRINT("unable to delete backup file... reason -> %r\n", Result); + return Result; + } + + // create a new bootmgfw file... + BootMgfwPathProtocol = FileDevicePath(Handles[Idx], WINDOWS_BOOTMGFW_PATH); + if (EFI_ERROR((Result = EfiOpenFileByDevicePath(&BootMgfwPathProtocol, &BootMgfwFile, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, EFI_FILE_SYSTEM)))) + { + DBG_PRINT("unable to create new bootmgfw on disk... reason -> %r\n", Result); + return Result; + } + + // write the data from the backup file to the new bootmgfw file... + BootMgfwSize = FileInfoPtr->FileSize; + if (EFI_ERROR((Result = BootMgfwFile->Write(BootMgfwFile, &BootMgfwSize, BootMgfwBuffer)))) + { + DBG_PRINT("unable to write to newly created bootmgfw.efi... reason -> %r\n", Result); + return Result; + } + + BootMgfwFile->Close(BootMgfwFile); + gBS->FreePool(FileInfoPtr); + gBS->FreePool(BootMgfwBuffer); + return EFI_SUCCESS; + } + + if (EFI_ERROR((Result = gBS->CloseProtocol(Handles[Idx], &gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL)))) + { + DBG_PRINT("error closing protocol -> 0x%p\n", Result); + return Result; + } + } + + gBS->FreePool(Handles); + return EFI_ABORTED; +} + +EFI_STATUS EFIAPI InstallBootMgfwHooks(EFI_HANDLE ImageHandle) +{ + EFI_STATUS Result = EFI_SUCCESS; + EFI_LOADED_IMAGE* BootMgfw = NULL; + + if (EFI_ERROR(Result = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID**)&BootMgfw))) + return Result; + + DBG_PRINT("Module base -> 0x%p\n", BootMgfw->ImageBase); + DBG_PRINT("Module size -> 0x%x\n", BootMgfw->ImageSize); + + VOID* ArchStartBootApplication = + FindPattern( + BootMgfw->ImageBase, + BootMgfw->ImageSize, + START_BOOT_APPLICATION_SIG, + START_BOOT_APPLICATION_MASK + ); + + if (!ArchStartBootApplication) + return EFI_ABORTED; + + DBG_PRINT("ArchStartBootApplication -> 0x%p\n", RESOLVE_RVA(ArchStartBootApplication, 5, 1)); + MakeShitHook(&BootMgfwShitHook, RESOLVE_RVA(ArchStartBootApplication, 5, 1), &ArchStartBootApplicationHook, TRUE); + return EFI_SUCCESS; +} + +EFI_STATUS EFIAPI ArchStartBootApplicationHook(VOID* AppEntry, VOID* ImageBase, UINT32 ImageSize, UINT8 BootOption, VOID* ReturnArgs) +{ + DisableShitHook(&BootMgfwShitHook); + VOID* ImgLoadPEImageEx = + FindPattern( + ImageBase, + ImageSize, + LOAD_PE_IMG_SIG, + LOAD_PE_IMG_MASK + ); + + Print(L"PE PayLoad Size -> 0x%x\n", PayLoadSize()); + Print(L"winload base -> 0x%p\n", ImageBase); + Print(L"winload size -> 0x%x\n", ImageSize); + Print(L"winload.BlImgLoadPEImageEx -> 0x%p\n", RESOLVE_RVA(ImgLoadPEImageEx, 5, 1)); + + MakeShitHook(&WinLoadImageShitHook, RESOLVE_RVA(ImgLoadPEImageEx, 5, 1), &BlImgLoadPEImageEx, TRUE); + return ((IMG_ARCH_START_BOOT_APPLICATION)BootMgfwShitHook.Address)(AppEntry, ImageBase, ImageSize, BootOption, ReturnArgs); +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/BootMgfw.h b/Voyager-2/Voyager-2 (1703-1511)/BootMgfw.h new file mode 100644 index 0000000..03e1cb7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/BootMgfw.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "WinLoad.h" + +#define START_BOOT_APPLICATION_SIG "\xE8\x00\x00\x00\x00\x48\x8B\xCE\x8B\xD8\xE8\x00\x00\x00\x00\x41\x8B\xCF" +#define START_BOOT_APPLICATION_MASK "x????xxxxxx????xxx" + +static_assert(sizeof(START_BOOT_APPLICATION_SIG) == sizeof(START_BOOT_APPLICATION_MASK), "signature and mask size's dont match..."); +#define WINDOWS_BOOTMGFW_PATH L"\\efi\\microsoft\\boot\\bootmgfw.efi" +#define WINDOWS_BOOTMGFW_BACKUP_PATH L"\\efi\\microsoft\\boot\\bootmgfw.efi.backup" + +extern SHITHOOK BootMgfwShitHook; +typedef EFI_STATUS(EFIAPI* IMG_ARCH_START_BOOT_APPLICATION)(VOID*, VOID*, UINT32, UINT8, VOID*); +EFI_STATUS EFIAPI RestoreBootMgfw(VOID); +EFI_STATUS EFIAPI InstallBootMgfwHooks(EFI_HANDLE ImageHandle); +EFI_STATUS EFIAPI ArchStartBootApplicationHook(VOID* AppEntry, VOID* ImageBase, UINT32 ImageSize, UINT8 BootOption, VOID* ReturnArgs); diff --git a/Voyager-2/Voyager-2 (1703-1511)/HvLoader.c b/Voyager-2/Voyager-2 (1703-1511)/HvLoader.c new file mode 100644 index 0000000..0265aec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/HvLoader.c @@ -0,0 +1,151 @@ +#include "HvLoader.h" + +SHITHOOK HvLoadImageHook; +SHITHOOK HvLoadImageBufferHook; +SHITHOOK HvLoadAllocImageHook; +BOOLEAN ExtendedAllocation = FALSE; +BOOLEAN HookedHyperV = FALSE; + +EFI_STATUS EFIAPI HvBlImgLoadPEImageFromSourceBuffer(VOID* a1, VOID* a2, VOID* a3, VOID* a4, UINT64* ImageBase, + UINT32* ImageSize, VOID* a7, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13, VOID* a14, VOID* a15) +{ + DisableShitHook(&HvLoadImageBufferHook); + EFI_STATUS Result = ((HV_LDR_LOAD_IMAGE_BUFFER)HvLoadImageBufferHook.Address)(a1, a2, a3, a4, ImageBase, ImageSize, a7, a8, + a9, a10, a11, a12, a13, a14, a15); + if(!ExtendedAllocation && !HookedHyperV) + EnableShitHook(&HvLoadImageBufferHook); + + if (ExtendedAllocation && !HookedHyperV) + { + HookedHyperV = TRUE; + EFI_IMAGE_DOS_HEADER* HypervDosHeader = *ImageBase; + if (HypervDosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) + return NULL; + + EFI_IMAGE_NT_HEADERS64* HypervNtHeader = (UINT64)HypervDosHeader + HypervDosHeader->e_lfanew; + if (HypervNtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) + return NULL; + + EFI_IMAGE_SECTION_HEADER* pSection = ((UINT64)&HypervNtHeader->OptionalHeader) + + HypervNtHeader->FileHeader.SizeOfOptionalHeader; + + for (UINT16 i = 0; i < HypervNtHeader->FileHeader.NumberOfSections; i += 1, pSection += 1) + { + if (!AsciiStrCmp(&pSection->Name, ".reloc")) + { + VOYAGER_T VoyagerData; + MakeVoyagerData + ( + &VoyagerData, + *ImageBase, + *ImageSize, + *ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize, + PayLoadSize() + ); + + DBG_PRINT(".reloc section base address -> 0x%p\n", *ImageBase + pSection->VirtualAddress); + DBG_PRINT(".reloc section end (aka golden record base address) -> 0x%p\n", *ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize); + + VOID* VmExitHook = MapModule(&VoyagerData, PayLoad); + VOID* VmExitFunction = HookVmExit + ( + VoyagerData.HypervModuleBase, + VoyagerData.HypervModuleSize, + VmExitHook + ); + + pSection->Characteristics = SECTION_RWX; + pSection->Misc.VirtualSize += PayLoadSize(); + DBG_PRINT("VmExitHook (PayLoad Entry Point) -> 0x%p\n", VmExitHook); + } + } + + HypervNtHeader->OptionalHeader.SizeOfImage += PayLoadSize(); + *ImageSize += PayLoadSize(); + } + + DBG_PRINT("[HvLoader (Load Image)] ImageBase -> 0x%p, ImageSize -> 0x%p\n", *ImageBase, *ImageSize); + return Result; +} + +EFI_STATUS EFIAPI HvBlImgLoadPEImageEx(VOID* DeviceId, VOID* MemoryType, CHAR16* Path, UINT64* ImageBase, UINT32* ImageSize, + VOID* Hash, VOID* Flags, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13) +{ + DisableShitHook(&HvLoadImageHook); + EFI_STATUS Result = ((HV_LDR_LOAD_IMAGE)HvLoadImageHook.Address)(DeviceId, MemoryType, Path, ImageBase, ImageSize, Hash, Flags, a8, + a9, a10, a11, a12, a13); + if(!ExtendedAllocation && !HookedHyperV) + EnableShitHook(&HvLoadImageHook); + + if (ExtendedAllocation && !HookedHyperV) + { + HookedHyperV = TRUE; + EFI_IMAGE_DOS_HEADER* HypervDosHeader = *ImageBase; + if (HypervDosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) + return NULL; + + EFI_IMAGE_NT_HEADERS64* HypervNtHeader = (UINT64)HypervDosHeader + HypervDosHeader->e_lfanew; + if (HypervNtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) + return NULL; + + EFI_IMAGE_SECTION_HEADER* pSection = ((UINT64)&HypervNtHeader->OptionalHeader) + + HypervNtHeader->FileHeader.SizeOfOptionalHeader; + + for (UINT16 i = 0; i < HypervNtHeader->FileHeader.NumberOfSections; i += 1, pSection += 1) + { + if (!AsciiStrCmp(&pSection->Name, ".reloc")) + { + VOYAGER_T VoyagerData; + MakeVoyagerData + ( + &VoyagerData, + *ImageBase, + *ImageSize, + *ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize, + PayLoadSize() + ); + + DBG_PRINT(".reloc section base address -> 0x%p\n", *ImageBase + pSection->VirtualAddress); + DBG_PRINT(".reloc section end (aka golden record base address) -> 0x%p\n", *ImageBase + pSection->VirtualAddress + pSection->Misc.VirtualSize); + + VOID* VmExitHook = MapModule(&VoyagerData, PayLoad); + VOID* VmExitFunction = HookVmExit + ( + VoyagerData.HypervModuleBase, + VoyagerData.HypervModuleSize, + VmExitHook + ); + + pSection->Characteristics = SECTION_RWX; + pSection->Misc.VirtualSize += PayLoadSize(); + DBG_PRINT("VmExitHook (PayLoad Entry Point) -> 0x%p\n", VmExitHook); + } + } + + HypervNtHeader->OptionalHeader.SizeOfImage += PayLoadSize(); + *ImageSize += PayLoadSize(); + } + + DBG_PRINT("[HvLoader (Load Image)] ImageBase -> 0x%p, ImageSize -> 0x%p\n", *ImageBase, *ImageSize); + return Result; +} + +UINT64 EFIAPI HvLoaderBlImgAllocateImageBuffer(VOID** imageBuffer, UINTN imageSize, UINT32 memoryType, UINT32 attributes, VOID* unused, UINT32 flags) +{ + if (imageSize >= HV_ALLOC_SIZE && !ExtendedAllocation) + { + ExtendedAllocation = TRUE; + imageSize += PayLoadSize(); + + // allocate the entire hyper-v module as rwx... + memoryType = BL_MEMORY_ATTRIBUTE_RWX; + } + + DisableShitHook(&HvLoadAllocImageHook); + UINT64 Result = ((ALLOCATE_IMAGE_BUFFER)HvLoadAllocImageHook.Address)(imageBuffer, imageSize, memoryType, attributes, unused, flags); + if(!ExtendedAllocation) + EnableShitHook(&HvLoadAllocImageHook); + + DBG_PRINT("[HvLoader (Alloc Image Memory)] Allocated memory -> 0x%p, size -> 0x%x\n", *imageBuffer, imageSize); + return Result; +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/HvLoader.h b/Voyager-2/Voyager-2 (1703-1511)/HvLoader.h new file mode 100644 index 0000000..410375e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/HvLoader.h @@ -0,0 +1,38 @@ +#pragma once +#include "Utils.h" +#include "PayLoad.h" +#include "Hvax64.h" + +#if WINVER >= 1607 +#define ALLOCATE_IMAGE_BUFFER_SIG "\xE8\x00\x00\x00\x00\x4C\x8B\x65\x60" +#define ALLOCATE_IMAGE_BUFFER_MASK "x????xxxx" +#elif WINVER == 1511 +#define ALLOCATE_IMAGE_BUFFER_SIG "\xE8\x00\x00\x00\x00\x4C\x8B\x75\xC0" +#define ALLOCATE_IMAGE_BUFFER_MASK "x????xxxx" +#endif + +#if WINVER == 1703 +#define HV_LOAD_PE_IMG_SIG "\xE8\x00\x00\x00\x00\x44\x8B\xAD" +#define HV_LOAD_PE_IMG_MASK "x????xxx" +#elif WINVER <= 1607 // same for 1511 +#define HV_LOAD_PE_IMG_SIG "\xE8\x00\x00\x00\x00\x48\x8B\x7D\xF7" +#define HV_LOAD_PE_IMG_MASK "x????xxxx" +#endif + +static_assert(sizeof(HV_LOAD_PE_IMG_SIG) == sizeof(HV_LOAD_PE_IMG_MASK), "signature and mask do not match size..."); +static_assert(sizeof(ALLOCATE_IMAGE_BUFFER_SIG) == sizeof(ALLOCATE_IMAGE_BUFFER_MASK), "signature and mask do not match size!"); +typedef EFI_STATUS(EFIAPI* ALLOCATE_IMAGE_BUFFER)(VOID** imageBuffer, UINTN imageSize, UINT32 memoryType, UINT32 attributes, VOID* unused, UINT32 flags); +typedef EFI_STATUS(EFIAPI* HV_LDR_LOAD_IMAGE_BUFFER)(VOID* a1, VOID* a2, VOID* a3, VOID* a4, UINT64* ImageBase, + UINT32* ImageSize, VOID* a7, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13, VOID* a14, VOID* a15); +typedef EFI_STATUS(EFIAPI* HV_LDR_LOAD_IMAGE)(VOID* DeviceId, VOID* MemoryType, CHAR16* Path, VOID** ImageBase, UINT32* ImageSize, + VOID* Hash, VOID* Flags, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13); + +UINT64 EFIAPI HvLoaderBlImgAllocateImageBuffer(VOID** imageBuffer, UINTN imageSize, UINT32 memoryType, UINT32 attributes, VOID* unused, UINT32 flags); +EFI_STATUS EFIAPI HvBlImgLoadPEImageEx(VOID* DeviceId, VOID* MemoryType, CHAR16* Path, UINT64* ImageBase, UINT32* ImageSize, + VOID* Hash, VOID* Flags, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13); +EFI_STATUS EFIAPI HvBlImgLoadPEImageFromSourceBuffer(VOID* a1, VOID* a2, VOID* a3, VOID* a4, UINT64* ImageBase, + UINT32* ImageSize, VOID* a7, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13, VOID* a14, VOID* a15); + +extern SHITHOOK HvLoadImageHook; +extern SHITHOOK HvLoadAllocImageHook; +extern SHITHOOK HvLoadImageBufferHook; \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Hvax64.c b/Voyager-2/Voyager-2 (1703-1511)/Hvax64.c new file mode 100644 index 0000000..a6a8928 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Hvax64.c @@ -0,0 +1,122 @@ +#include "Hvax64.h" + +VOID* MapModule(PVOYAGER_T VoyagerData, UINT8* ImageBase) +{ + EFI_IMAGE_DOS_HEADER* dosHeaders = (EFI_IMAGE_DOS_HEADER*)ImageBase; + if (dosHeaders->e_magic != EFI_IMAGE_DOS_SIGNATURE) + return NULL; + + EFI_IMAGE_NT_HEADERS64* ntHeaders = (EFI_IMAGE_NT_HEADERS64*)(ImageBase + dosHeaders->e_lfanew); + + // Map headers + MemCopy(VoyagerData->ModuleBase, ImageBase, ntHeaders->OptionalHeader.SizeOfHeaders); + + // Map sections + EFI_IMAGE_SECTION_HEADER* sections = (EFI_IMAGE_SECTION_HEADER*)((UINT8*)&ntHeaders->OptionalHeader + ntHeaders->FileHeader.SizeOfOptionalHeader); + for (UINT32 i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i) + { + EFI_IMAGE_SECTION_HEADER* section = §ions[i]; + if (section->SizeOfRawData) + MemCopy(VoyagerData->ModuleBase + section->VirtualAddress, ImageBase + section->PointerToRawData, section->SizeOfRawData); + } + + // set exported pointer to voyager context... + EFI_IMAGE_EXPORT_DIRECTORY* ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)( + VoyagerData->ModuleBase + ntHeaders->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + + UINT32* Address = (UINT32*)(VoyagerData->ModuleBase + ExportDir->AddressOfFunctions); + UINT32* Name = (UINT32*)(VoyagerData->ModuleBase + ExportDir->AddressOfNames); + UINT16* Ordinal = (UINT16*)(VoyagerData->ModuleBase + ExportDir->AddressOfNameOrdinals); + + for (UINT16 i = 0; i < ExportDir->AddressOfFunctions; i++) + { + if (AsciiStrStr(VoyagerData->ModuleBase + Name[i], "voyager_context")) + { + *(VOYAGER_T*)(VoyagerData->ModuleBase + Address[Ordinal[i]]) = *VoyagerData; + break; + } + } + + // Resolve relocations + EFI_IMAGE_DATA_DIRECTORY* baseRelocDir = &ntHeaders->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if (baseRelocDir->VirtualAddress) + { + EFI_IMAGE_BASE_RELOCATION* reloc = (EFI_IMAGE_BASE_RELOCATION*)(VoyagerData->ModuleBase + baseRelocDir->VirtualAddress); + for (UINT32 currentSize = 0; currentSize < baseRelocDir->Size; ) + { + UINT32 relocCount = (reloc->SizeOfBlock - sizeof(EFI_IMAGE_BASE_RELOCATION)) / sizeof(UINT16); + UINT16* relocData = (UINT16*)((UINT8*)reloc + sizeof(EFI_IMAGE_BASE_RELOCATION)); + UINT8* relocBase = VoyagerData->ModuleBase + reloc->VirtualAddress; + + for (UINT32 i = 0; i < relocCount; ++i, ++relocData) + { + UINT16 data = *relocData; + UINT16 type = data >> 12; + UINT16 offset = data & 0xFFF; + + switch (type) + { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + case EFI_IMAGE_REL_BASED_DIR64: + { + UINT64* rva = (UINT64*)(relocBase + offset); + *rva = (UINT64)(VoyagerData->ModuleBase + (*rva - ntHeaders->OptionalHeader.ImageBase)); + break; + } + default: + return NULL; + } + } + + currentSize += reloc->SizeOfBlock; + reloc = (EFI_IMAGE_BASE_RELOCATION*)relocData; + } + } + + return VoyagerData->ModuleBase + ntHeaders->OptionalHeader.AddressOfEntryPoint; +} + +VOID MakeVoyagerData +( + PVOYAGER_T VoyagerData, + VOID* HypervAlloc, + UINT64 HypervAllocSize, + VOID* PayLoadBase, + UINT64 PayLoadSize +) +{ + VoyagerData->HypervModuleBase = HypervAlloc; + VoyagerData->HypervModuleSize = HypervAllocSize; + VoyagerData->ModuleBase = PayLoadBase; + VoyagerData->ModuleSize = PayLoadSize; + + VOID* VmExitHandlerCall = + FindPattern( + HypervAlloc, + HypervAllocSize, + VCPU_RUN_HANDLER_SIG, + VCPU_RUN_HANDLER_MASK + ); + + UINT64 VmExitHandlerCallRip = (UINT64)VmExitHandlerCall + 5; // + 5 bytes because "call vmexit_c_handler" is 5 bytes + UINT64 VmExitHandlerFunc = VmExitHandlerCallRip + *(INT32*)((UINT64)VmExitHandlerCall + 1); // + 1 to skip E8 (call) and read 4 bytes (RVA) + VoyagerData->VmExitHandlerRVA = ((UINT64)PayLoadEntry(PayLoadBase)) - VmExitHandlerFunc; +} + +VOID* HookVmExit(VOID* HypervBase, VOID* HypervSize, VOID* VmExitHook) +{ + VOID* VmExitHandlerCall = + FindPattern( + HypervBase, + HypervSize, + VCPU_RUN_HANDLER_SIG, + VCPU_RUN_HANDLER_MASK + ); + + UINT64 VmExitHandlerCallRip = ((UINT64)VmExitHandlerCall) + 5; // + 5 bytes to next instructions address... + UINT64 VmExitHandlerFunction = VmExitHandlerCallRip + *(INT32*)(((UINT64)VmExitHandlerCall) + 1); // + 1 to skip E8 (call) and read 4 bytes (RVA) + INT32 NewVmExitHandlerRVA = ((INT64)VmExitHook) - VmExitHandlerCallRip; + *(INT32*)((UINT64)VmExitHandlerCall + 1) = NewVmExitHandlerRVA; + return VmExitHandlerFunction; +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Hvax64.h b/Voyager-2/Voyager-2 (1703-1511)/Hvax64.h new file mode 100644 index 0000000..1067247 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Hvax64.h @@ -0,0 +1,34 @@ +#pragma once +#include "PayLoad.h" +#define HV_ALLOC_SIZE 0x1400000 + +#define VCPU_RUN_HANDLER_SIG "\xE8\x00\x00\x00\x00\x48\x89\x04\x24\xE9" +#define VCPU_RUN_HANDLER_MASK "x????xxxxx" + +static_assert(sizeof(VCPU_RUN_HANDLER_SIG) == sizeof(VCPU_RUN_HANDLER_MASK), "signature does not match mask size!"); + +// +// AllocBase is the base address of the extra memory allocated below where hyper-v is +// AllocSize is the size of the extra allocated memory... This size == module size... +// +VOID* MapModule(PVOYAGER_T VoyagerData, UINT8* ImageBase); + +// +// sig scan hv.exe for vmexit call and replace the relative call (RVA) with +// an RVA to the vmexit handler hook (which is the golden records entry point)... +// +// returns a pointer to the original vmexit function address... +// +VOID* HookVmExit(VOID* HypervBase, VOID* HypervSize, VOID* VmExitHook); + +// +// creates a structure with all the data needed to be passed to the golden record... +// +VOID MakeVoyagerData +( + PVOYAGER_T VoyagerData, + VOID* HypervAlloc, + UINT64 HypervAllocSize, + VOID* PayLoadBase, + UINT64 PayLoadSize +); \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/PayLoad.c b/Voyager-2/Voyager-2 (1703-1511)/PayLoad.c new file mode 100644 index 0000000..51caad9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/PayLoad.c @@ -0,0 +1,245 @@ +#include "PayLoad.h" + +UINT32 PayLoadSize(VOID) +{ + EFI_IMAGE_DOS_HEADER* RecordDosImageHeader = PayLoad; + if (RecordDosImageHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) + return NULL; + + EFI_IMAGE_NT_HEADERS64* RecordNtHeaders = (UINT64)RecordDosImageHeader + RecordDosImageHeader->e_lfanew; + if (RecordNtHeaders->Signature != EFI_IMAGE_NT_SIGNATURE) + return NULL; + + return RecordNtHeaders->OptionalHeader.SizeOfImage; +} + +VOID* PayLoadEntry(VOID* ModuleBase) +{ + EFI_IMAGE_DOS_HEADER* RecordDosImageHeader = PayLoad; + if (RecordDosImageHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) + return NULL; + + EFI_IMAGE_NT_HEADERS64* RecordNtHeaders = (UINT64)RecordDosImageHeader + RecordDosImageHeader->e_lfanew; + if (RecordNtHeaders->Signature != EFI_IMAGE_NT_SIGNATURE) + return NULL; + + return (UINT64)ModuleBase + RecordNtHeaders->OptionalHeader.AddressOfEntryPoint; +} + +unsigned char PayLoad[2560] = +{ + 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xB8, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, + 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, + 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, + 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0xBF, 0x31, 0xDD, + 0x6B, 0xDE, 0x5F, 0x8E, 0x6B, 0xDE, 0x5F, 0x8E, 0x6B, 0xDE, 0x5F, 0x8E, + 0xDC, 0xAF, 0x5A, 0x8F, 0x6A, 0xDE, 0x5F, 0x8E, 0xDC, 0xAF, 0x5F, 0x8F, + 0x6A, 0xDE, 0x5F, 0x8E, 0xDC, 0xAF, 0x5D, 0x8F, 0x6A, 0xDE, 0x5F, 0x8E, + 0x52, 0x69, 0x63, 0x68, 0x6B, 0xDE, 0x5F, 0x8E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x04, 0x00, + 0x56, 0xD5, 0x76, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x22, 0x20, 0x0B, 0x02, 0x0E, 0x1B, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x39, 0xEC, 0x00, 0x00, + 0x01, 0x00, 0x60, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, + 0x69, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, 0x2E, 0x72, 0x64, 0x61, + 0x74, 0x61, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, + 0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0xC8, 0x2E, 0x65, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x4C, 0x8B, 0x80, 0xF0, 0x82, 0x00, 0x00, 0x49, 0x8B, 0x80, 0x90, + 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x80, 0x40, 0x0C, 0x00, 0x00, 0x49, 0x83, + 0x78, 0x70, 0x72, 0x75, 0x33, 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, + 0xBE, 0xAD, 0xDE, 0x48, 0x39, 0x42, 0x08, 0x75, 0x23, 0x49, 0x8B, 0x80, + 0xC8, 0x00, 0x00, 0x00, 0x49, 0x89, 0x80, 0x78, 0x05, 0x00, 0x00, 0x49, + 0xC7, 0x80, 0xF8, 0x05, 0x00, 0x00, 0xEE, 0xFF, 0xC0, 0x00, 0x65, 0x48, + 0x8B, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x48, 0x8D, 0x05, 0xA1, + 0xFF, 0xFF, 0xFF, 0x48, 0x2B, 0x05, 0x9A, 0x1F, 0x00, 0x00, 0x48, 0xFF, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x56, 0xD5, 0x76, 0x5F, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x38, 0x20, 0x00, 0x00, + 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0xD5, 0x76, 0x5F, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x94, 0x20, 0x00, 0x00, 0x94, 0x06, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, + 0xE1, 0x7F, 0x6D, 0x89, 0xA5, 0x8B, 0x78, 0x48, 0x90, 0x94, 0x47, 0x89, + 0xD5, 0x64, 0xB3, 0x11, 0x03, 0x00, 0x00, 0x00, 0x43, 0x3A, 0x5C, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x5C, 0x78, 0x65, 0x72, 0x6F, 0x78, 0x5C, 0x44, + 0x65, 0x73, 0x6B, 0x74, 0x6F, 0x70, 0x5C, 0x76, 0x6F, 0x79, 0x61, 0x67, + 0x65, 0x72, 0x5C, 0x56, 0x6F, 0x79, 0x61, 0x67, 0x65, 0x72, 0x2D, 0x32, + 0x5C, 0x78, 0x36, 0x34, 0x5C, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, 0x65, + 0x5C, 0x50, 0x61, 0x79, 0x4C, 0x6F, 0x61, 0x64, 0x2E, 0x70, 0x64, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x69, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x38, 0x20, 0x00, 0x00, + 0xBC, 0x00, 0x00, 0x00, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7A, + 0x7A, 0x7A, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x2E, 0x65, 0x64, 0x61, + 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x32, 0x40, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x28, 0x40, 0x00, 0x00, 0x2C, 0x40, 0x00, 0x00, 0x30, 0x40, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x3E, 0x40, 0x00, 0x00, 0x00, 0x00, 0x50, 0x61, + 0x79, 0x4C, 0x6F, 0x61, 0x64, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x3F, 0x76, + 0x6F, 0x79, 0x61, 0x67, 0x65, 0x72, 0x5F, 0x63, 0x6F, 0x6E, 0x74, 0x65, + 0x78, 0x74, 0x40, 0x73, 0x76, 0x6D, 0x40, 0x40, 0x33, 0x55, 0x5F, 0x76, + 0x6F, 0x79, 0x61, 0x67, 0x65, 0x72, 0x5F, 0x74, 0x40, 0x31, 0x40, 0x41, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/PayLoad.h b/Voyager-2/Voyager-2 (1703-1511)/PayLoad.h new file mode 100644 index 0000000..cce752e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/PayLoad.h @@ -0,0 +1,17 @@ +#pragma once +#include "Utils.h" +extern unsigned char PayLoad[2560]; + +#pragma pack(push, 1) +typedef struct _VOYAGER_T +{ + UINT64 VmExitHandlerRVA; + UINT64 HypervModuleBase; + UINT64 HypervModuleSize; + UINT64 ModuleBase; + UINT64 ModuleSize; +} VOYAGER_T, *PVOYAGER_T; +#pragma pack(pop) + +UINT32 PayLoadSize(VOID); +VOID* PayLoadEntry(VOID* ModuleBase); \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/ShitHook.c b/Voyager-2/Voyager-2 (1703-1511)/ShitHook.c new file mode 100644 index 0000000..e76bd2e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/ShitHook.c @@ -0,0 +1,36 @@ +#include "ShitHook.h" + +VOID MakeShitHook(PSHITHOOK Hook, VOID* HookFrom, VOID* HookTo, BOOLEAN Install) +{ + if (!Hook || !HookFrom || !HookTo) + return; + + unsigned char JmpCode[14] = + { + 0xff, 0x25, 0x0, 0x0, 0x0, 0x0, // jmp QWORD PTR[rip + 0x0] + + // jmp address... + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0 + }; + + // save original bytes, and hook related addresses.... + Hook->Address = HookFrom; + Hook->HookAddress = HookTo; + gBS->CopyMem(Hook->Code, HookFrom, sizeof Hook->Code); + + // setup hook... + gBS->CopyMem(JmpCode + 6, &HookTo, sizeof HookTo); + gBS->CopyMem(Hook->JmpCode, JmpCode, sizeof JmpCode); + if (Install) EnableShitHook(Hook); +} + +VOID EnableShitHook(PSHITHOOK Hook) +{ + gBS->CopyMem(Hook->Address, Hook->JmpCode, sizeof Hook->JmpCode); +} + +VOID DisableShitHook(PSHITHOOK Hook) +{ + gBS->CopyMem(Hook->Address, Hook->Code, sizeof Hook->Code); +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/ShitHook.h b/Voyager-2/Voyager-2 (1703-1511)/ShitHook.h new file mode 100644 index 0000000..20fc34e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/ShitHook.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _SHITHOOK +{ + unsigned char Code[14]; + unsigned char JmpCode[14]; + + void* Address; + void* HookAddress; +} SHITHOOK, *PSHITHOOK; + +VOID MakeShitHook(PSHITHOOK Hook, VOID* HookFrom, VOID* HookTo, BOOLEAN Install); +VOID EnableShitHook(PSHITHOOK Hook); +VOID DisableShitHook(PSHITHOOK Hook); \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/UefiMain.c b/Voyager-2/Voyager-2 (1703-1511)/UefiMain.c new file mode 100644 index 0000000..dc2b2ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/UefiMain.c @@ -0,0 +1,31 @@ +#include "BootMgfw.h" + +CHAR8* gEfiCallerBaseName = "Voyager"; +const UINT32 _gUefiDriverRevision = 0x200; + +EFI_STATUS EFIAPI UefiUnload( + IN EFI_HANDLE ImageHandle +) +{ return EFI_SUCCESS; } + +EFI_STATUS EFIAPI UefiMain +( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable +) +{ + EFI_STATUS Result; + EFI_DEVICE_PATH_PROTOCOL* BootMgfwPath; + if (EFI_ERROR((Result = RestoreBootMgfw()))) + { + DBG_PRINT("unable to restore bootmgfw... reason -> %r\n", Result); + return Result; + } + + if (EFI_ERROR((Result = InstallBootMgfwHooks(ImageHandle)))) + { + DBG_PRINT("Failed to install bootmgfw hooks... reason -> %r\n", Result); + return Result; + } + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Utils.c b/Voyager-2/Voyager-2 (1703-1511)/Utils.c new file mode 100644 index 0000000..a054473 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Utils.c @@ -0,0 +1,51 @@ +#include "Utils.h" + +BOOLEAN CheckMask(CHAR8* base, CHAR8* pattern, CHAR8* mask) +{ + for (; *mask; ++base, ++pattern, ++mask) + if (*mask == 'x' && *base != *pattern) + return FALSE; + + return TRUE; +} + +VOID* FindPattern(CHAR8* base, UINTN size, CHAR8* pattern, CHAR8* mask) +{ + size -= AsciiStrLen(mask); + for (UINTN i = 0; i <= size; ++i) + { + VOID* addr = &base[i]; + if (CheckMask(addr, pattern, mask)) + return addr; + } + return NULL; +} + +VOID* GetExport(UINT8* ModuleBase, CHAR8* export) +{ + EFI_IMAGE_DOS_HEADER* dosHeaders = (EFI_IMAGE_DOS_HEADER*)ModuleBase; + if (dosHeaders->e_magic != EFI_IMAGE_DOS_SIGNATURE) + return NULL; + + EFI_IMAGE_NT_HEADERS64* ntHeaders = (EFI_IMAGE_NT_HEADERS64*)(ModuleBase + dosHeaders->e_lfanew); + UINT32 exportsRva = ntHeaders->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + EFI_IMAGE_EXPORT_DIRECTORY* exports = (EFI_IMAGE_EXPORT_DIRECTORY*)(ModuleBase + exportsRva); + UINT32* nameRva = (UINT32*)(ModuleBase + exports->AddressOfNames); + + for (UINT32 i = 0; i < exports->NumberOfNames; ++i) + { + CHAR8* func = (CHAR8*)(ModuleBase + nameRva[i]); + if (AsciiStrCmp(func, export) == 0) + { + UINT32* funcRva = (UINT32*)(ModuleBase + exports->AddressOfFunctions); + UINT16* ordinalRva = (UINT16*)(ModuleBase + exports->AddressOfNameOrdinals); + return (VOID*)(((UINT64)ModuleBase) + funcRva[ordinalRva[i]]); + } + } + return NULL; +} + +VOID MemCopy(VOID* dest, VOID* src, UINTN size) +{ + for (UINT8* d = dest, *s = src; size--; *d++ = *s++); +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Utils.h b/Voyager-2/Voyager-2 (1703-1511)/Utils.h new file mode 100644 index 0000000..28851f6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Utils.h @@ -0,0 +1,35 @@ +#pragma once +#include "ShitHook.h" +#define WINVER 1511 +#define PORT_NUM 0x2F8 +#define BL_MEMORY_ATTRIBUTE_RWX 0x424000 +#define SECTION_RWX (EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_EXECUTE) + +VOID __outbytestring(UINT16 Port, UINT8* Buffer, UINT32 Count); +void __outbyte(unsigned short Port, unsigned char Data); +#pragma intrinsic(__outbytestring) +#pragma intrinsic(__outbyte) + +static CHAR8 dbg_buffer[0x100]; +#define DBG_PRINT(...) \ + AsciiSPrint(dbg_buffer, sizeof dbg_buffer, __VA_ARGS__); \ + __outbytestring(PORT_NUM, dbg_buffer, AsciiStrLen(dbg_buffer)) + +#define RESOLVE_RVA(SIG_RESULT, RIP_OFFSET, RVA_OFFSET) \ + (*(INT32*)(((UINT64)SIG_RESULT) + RVA_OFFSET)) + ((UINT64)SIG_RESULT) + RIP_OFFSET + +typedef struct _LDR_DATA_TABLE_ENTRY +{ + LIST_ENTRY InLoadOrderLinks; // 16 + LIST_ENTRY InMemoryOrderLinks; // 32 + LIST_ENTRY InInitializationOrderLinks; // 48 + UINT64 ModuleBase; // 56 + UINT64 EntryPoint; // 64 + UINTN SizeOfImage; // 72 +} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY, **PPLDR_DATA_TABLE_ENTRY; + +// taken from umap (btbd) +BOOLEAN CheckMask(CHAR8* base, CHAR8* pattern, CHAR8* mask); +VOID* FindPattern(CHAR8* base, UINTN size, CHAR8* pattern, CHAR8* mask); +VOID* GetExport(UINT8* base, CHAR8* export); +VOID MemCopy(VOID* dest, VOID* src, UINTN size); \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj b/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj new file mode 100644 index 0000000..de610d6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj @@ -0,0 +1,198 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {C4B6B437-62DF-4166-9023-44CFC8A52258} + HyperMe + 10.0 + Voyager-2 (1703-1511) + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + false + v142 + Unicode + x86 + + + Application + false + v142 + true + Unicode + x86 + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + $(ProjectDir)edk2\CryptoPkg\Include;$(ProjectDir)edk2\ShellPkg\Include;$(ProjectDir)edk2\MdePkg\Include\X64;$(ProjectDir)edk2\MdePkg\Include + $(ProjectDir)edk2 + false + .efi + $(ProjectDir) + + + false + $(ProjectDir)edk2\CryptoPkg\Include;$(ProjectDir)edk2\ShellPkg\Include;$(ProjectDir)edk2\MdePkg\Include\X64;$(ProjectDir)edk2\MdePkg\Include;$(ProjectDir)edk2\StdLib\Include;$(ProjectDir) + $(ProjectDir)edk2 + false + .efi + $(ProjectDir) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + EFI Application + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + EFI Application + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + SyncCThrow + false + + + EFI Application + true + false + false + UefiHiiLib.lib;UefiHiiServicesLib.lib;UefiSortLib.lib;UefiShellLib.lib;GlueLib.lib;BaseLib.lib;BaseDebugPrintErrorLevelLib.lib;BasePrintLib.lib;UefiLib.lib;UefiBootServicesTableLib.lib;UefiRuntimeServicesTableLib.lib;UefiDevicePathLibDevicePathProtocol.lib;UefiDebugLibConOut.lib;UefiMemoryLib.lib;UefiMemoryAllocationLib.lib;BaseSynchronizationLib.lib;UefiFileHandleLib.lib;UefiApplicationEntryPoint.lib + true + EfiMain + + + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + true + SyncCThrow + false + + + EFI Application + true + true + true + false + false + UefiHiiLib.lib;UefiHiiServicesLib.lib;UefiSortLib.lib;UefiShellLib.lib;GlueLib.lib;BaseLib.lib;BaseDebugPrintErrorLevelLib.lib;BasePrintLib.lib;UefiLib.lib;UefiBootServicesTableLib.lib;UefiRuntimeServicesTableLib.lib;UefiDevicePathLibDevicePathProtocol.lib;UefiDebugLibConOut.lib;UefiMemoryLib.lib;UefiMemoryAllocationLib.lib;BaseSynchronizationLib.lib;UefiFileHandleLib.lib;UefiApplicationEntryPoint.lib + true + EfiMain + + + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.filters b/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.filters new file mode 100644 index 0000000..7a34236 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.user b/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/Voyager-1 (1703-1511).vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/WinLoad.c b/Voyager-2/Voyager-2 (1703-1511)/WinLoad.c new file mode 100644 index 0000000..a717e40 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/WinLoad.c @@ -0,0 +1,58 @@ +#include "WinLoad.h" + +SHITHOOK WinLoadImageShitHook; +CHAR8 ModulePathCStr[0x100]; +BOOLEAN InstalledHvLoaderHook = FALSE; + +EFI_STATUS EFIAPI BlImgLoadPEImageEx(VOID* a1, VOID* a2, CHAR16* ImagePath, UINT64* ImageBasePtr, UINT32* ImageSize, + VOID* a6, VOID* a7, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13, VOID* a14) +{ + UnicodeStrToAsciiStr(ImagePath, ModulePathCStr); + DBG_PRINT("LOADING FROM WINLOAD: "); + DBG_PRINT(ModulePathCStr); + + DisableShitHook(&WinLoadImageShitHook); + EFI_STATUS Result = ((LDR_LOAD_IMAGE)WinLoadImageShitHook.Address)(a1, a2, ImagePath, ImageBasePtr, ImageSize, a6, a7, a8, + a9, a10, a11, a12, a13, a14); + if(!InstalledHvLoaderHook) + EnableShitHook(&WinLoadImageShitHook); + + if (StrStr(ImagePath, L"hvloader.efi")) + { + VOID* LoadImage = + FindPattern( + *ImageBasePtr, + *ImageSize, + HV_LOAD_PE_IMG_SIG, + HV_LOAD_PE_IMG_MASK + ); + + VOID* AllocImage = + FindPattern( + *ImageBasePtr, + *ImageSize, + ALLOCATE_IMAGE_BUFFER_SIG, + ALLOCATE_IMAGE_BUFFER_MASK + ); + + if (!LoadImage || !AllocImage) + { + DBG_PRINT("Signatures FAILED!\n"); + return Result; + } + +#if WINVER == 1703 + MakeShitHook(&HvLoadImageBufferHook, RESOLVE_RVA(LoadImage, 5, 1), &HvBlImgLoadPEImageFromSourceBuffer, TRUE); +#elif WINVER <= 1607 // 1511 is the same... + MakeShitHook(&HvLoadImageHook, RESOLVE_RVA(LoadImage, 5, 1), &HvBlImgLoadPEImageEx, TRUE); +#endif + + MakeShitHook(&HvLoadAllocImageHook, RESOLVE_RVA(AllocImage, 5, 1), &HvLoaderBlImgAllocateImageBuffer, TRUE); + DBG_PRINT("LoadImageHook -> 0x%p\n", RESOLVE_RVA(LoadImage, 5, 1)); + DBG_PRINT("AllocImage -> 0x%p\n", RESOLVE_RVA(AllocImage, 5, 1)); + InstalledHvLoaderHook = TRUE; + } + + DBG_PRINT("[%s] Image Base -> 0x%p, Image Size -> 0x%p\n", __FUNCTION__, *ImageBasePtr, *ImageSize); + return Result; +} \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/WinLoad.h b/Voyager-2/Voyager-2 (1703-1511)/WinLoad.h new file mode 100644 index 0000000..54ac515 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/WinLoad.h @@ -0,0 +1,21 @@ +#pragma once +#include "Utils.h" +#include "HvLoader.h" +#include "PayLoad.h" + +extern SHITHOOK WinLoadImageShitHook; + +#if WINVER == 1703 +#define LOAD_PE_IMG_SIG "\xE8\x00\x00\x00\x00\x85\xC0\x79\x45" +#define LOAD_PE_IMG_MASK "x????xxxx" +#elif WINVER <= 1607 // works for 1511 +#define LOAD_PE_IMG_SIG "\xE8\x00\x00\x00\x00\x48\x8B\x7D\xF7" +#define LOAD_PE_IMG_MASK "x????xxxx" +#endif + +static_assert(sizeof(LOAD_PE_IMG_SIG) == sizeof(LOAD_PE_IMG_MASK), "signature and mask do not match size..."); +typedef EFI_STATUS (EFIAPI* LDR_LOAD_IMAGE)(VOID* a1, VOID* a2, CHAR16* ImagePath, UINT64* ImageBasePtr, UINT32* ImageSize, + VOID* a6, VOID* a7, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13, VOID* a14); + +EFI_STATUS EFIAPI BlImgLoadPEImageEx(VOID* a1, VOID* a2, CHAR16* ImagePath, UINT64* ImageBasePtr, UINT32* ImageSize, + VOID* a6, VOID* a7, VOID* a8, VOID* a9, VOID* a10, VOID* a11, VOID* a12, VOID* a13, VOID* a14); \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCacheMaintenanceLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCacheMaintenanceLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..7b3d65342d7db189965a92ad06321bee12f45f52 GIT binary patch literal 6300 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 RF;2gj0+F)wuf&V_@E<^EH0l5V literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCpuLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseCpuLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..57a7780c862d49abd0445e626183109e7e752b20 GIT binary patch literal 2114 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

A@_G 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�kyr5 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

hb1buo0`U_6<*`Uwrt7eieu0^v- z&}T-V&vBx^4Ej8x#kFW2a3waN;0a&ACmiYUgf9kmQD3!?WN|H86kLlIN{8TD^tu!K zO|X~uRd0|ju0_kS=}*_2esC>%BZ5O=86952??u;p|338-@INM8{4L^Rpq|sKJM3=} zTR7#&GEI3g@(Un8>#MesD*q1gS>K|Y##;>m$h_d~`Z$KR(*tSgu@fFUC?Wp_u>%u7 zTTgt+zd_9L&^U&^AsT6k-qSbI>wbzUdr3iBQhvYyzvlqO-yXil)Xve*ZP?!)_FJP4 z0(F2W@pp#<5m1M$QNIE8YhQJkH2F7&UxVdy*Z_;=bCk1-w4B|4;PF>q^#?uV-y8k{ z{RKV4!QUJHi0*ToK1fTSa;dnxk*ZG8NBpfJHZ@%5q@m+qxlc{yU5!**k2B#>F;!Ja z^>1p3zcW-cJSyN3xfFemO7uWl&c}K1IENDQZw%)cOtCa76OFV)R|C2#(em#LRimRX zBpPXnt_k#|sp?|V#orb#O)VHdUvF!{-xe-5bo^hZYgzLz2fsn8s+X$jP(l1%p+RcV z_FfNYd4|+6Wc;Pjh?9b}oRp@Jx+Ya!ovIY25Jw1??9yh_G10}@Y5jq%1 zf3bG5Ms)?M3sK^42wi|Gt^9Q3=#ZA9yA8-&iIjgoxYb}{p%vGG9z-K8(J4SDr>fqm zswV~H-wu-H_JF?~^u{9#^@b7r?Vx9L$-b0CT1wsx$@Em!kB0K^2I=q-y{xdGu_j&A7_L7n!dt^_2XP3k(S7DK<1^YF{H|VoEL0NV+;Yv zyzZ4$97Fl^Kw5efz+(a>WIvvO=V66j7bW}gn;sg+&_hHcEzuKGBlY8A$|O>dmXs$j zz{wn-=*N>WwQuU@Hmn~%X^ol+)D)sbKb{f+HO(6J0#MJTs%J=({rI_H`8;EQ#qycK z*+p8;?p%1xPF1t$A^Y)c&|lXx9Q5N^(S7F82Wjc^8hl<&Rj<%T^y60zomUJU|2n&v z9!N`%74TS=s@|Z7=*P`-XmS~;}5W{y`{IcpdY_y==hamlQsWy@VBL^PgB(=R1p1mTX24U z3bZ^!J~3qcCHVy>1!*}cyCC&Vs`@%reMKqRkH0Zoz79OUGOWa6*-bg5rQDB@`yo|* zPczYve=x+pH+1|-IzSJkrN^)EIGm~u(L?m(!-mJ92p&i1fwc7a10KIqLiFR`4Wz$V z|FlLO2kLL4L_hu;sM5;MzZ@OXa&$3iczCjY z($uMG{=Ey?k55k%+XMRXX?SF<-Y|lGd}>N9ed_*rR zJQqH)$-s7n*N<@wRizKI%sw}G{kQ>q>QP4Y<9Z;k*H`$ke%z2qq$TnyAg@eQjYyUK z_{y}R8w`yM0my9dN-B<_tLcHX^k@c;CX|rv0!<6mc!>4CKLxCX{s+hL_bb5Jo-lP=tmEvrN=;c44{PU#{&$eSQ`H$8fl3h z0`xsZ%YJ-Mbo6~hBQ4RHK#xdM8KjGTJObO=X1%Qi{W!zW@heA`HGeGl_ou1RX)1>b zq95NMoS&nCmS;$gA>%K}ahw#S<)l0UsfW_kgK6pkO38lwkm2%R;Q4@IB^Jx0ltWs| zJq5WZ($r*{iGKWqAvW32@h52tJ&=|j&%xuFG&PMLq8~qFcub4n@jN|{mL9XY;UO~Cd; zuOH(WT1OvbnSA#2>l)kG>&O4~!`t%o^M9QX{rKO01^J)rD|}c#KH1OzJqBrsEZ;vt zmFur!`}c_GD!v!F--7Bd$hED76dmt@6&V)xrO2~d(v46q%eR^G#?8iTN zXdFY8h(=nX&+Q+n9~V>3BL!(msfqzs;Q&QHu7aukK|i-){rCcFRCS;(Buez-3nQQ| zwnkkBRL%bCQqp8Ut{E(!OAWACKD9Z!NXyy193Bn&t9ta1{kQ?>+w}|w{kUFqpGNdS zTKY7BPvidTD*A|i+}O~$%FywzvrXxNwDbtUqeXw!oF1Ydw=g`KNAS3T9!N`%8{yH4 z60#q+GMHj%v>_U4iB14Io@m*RZIE7&`tW4Wd0yq6U|X{-s@?(_OFj-hGvL6+Iae|^R4@Oh0gq94Bo@~`>|AJ&hT5Q(%zz6s>= z{%R?yvL7!GHm0S90AzmiN-B<_LV6%AJ=VZu6(wXpUWMo3xLy|}`|-aX8pqIDqLG&9 zcOv%VV#)?mkd~D9F~E%+pyKg2!QcAT2$P!s7@fWIsM)FvZgN zooJ*b`fs5BBwF_4Kcl1nAsT6kj!nn=9rafyNEiM1B(}AadRq(n@d-o6uNb!Jy4y9y2 zu41^H7kHjySc%1Q0p*aEay1}#NxG^|GtrMPF~q7HI{qZpqzBT{qdq+9rmNcY5dFBW z;ZZw+M+15wEj_M;MO>!8nSJseFZ#FQPr>O43W<*V1n3hmKj9sD3b9BB z?6bg5Pghe(mOXiTut7~VBp_5!Pyf?&97E611?k}OB3x!rM0VvFcuro>YougXp5ftf z49y}Q>42Y`p5R|hjQ^fwF=-x2NC(m@80gC!sOZcuW145^=Q^x2FLc5!25u2?qBk#! zfP38uw*t6j>FNy{i~ z(+TO|^gf(6rmGEf5*>P@p|rtJ@~_1o&;{w>vIQ=i)72)rh#tM!aM={WKc%Z5sUdpxq2S#833z$t{AdXI%k&pc4$@(A{({&a>FW1%^&7=x zxBkQM`8{y`%`g*-=Whxk9RyAGpfIiLPB4xY9~g zRgMzrFv^R7twyZu+tmy%7GH6ls7^f60bd9B%Lb^L1JtFIke&Oo0b=_==dOuI=IRY4 zxF>ySbkVvLMLLKoh+Z*3T~15cyRU$g=y-*f8*2o{FX+~%kD;sRge;TOu3=qcYkIHS zI64e>Z-)7&iRj!%h85($teZjDed*ta`6npS68R61e+^TAkShE3U&D%ST>N1OK;{*% z@ZuOcP7kD|M@$A@f=>zAwf`H2>x^C-CA;==4~=6eHp8C+q$Rq1MnZ(1T}(NR6r?5P z3=Ht}3?C#q_URb~`OEcl8`iPUv__o+)LBG{etlL1)VbEE3xGO5LsceCcI)#qik44h z11y$LHO?;5a&~LLPHXJnbQrAei1wd(gSJfaW6auQ$qCR!3NS_ ztV66(89)ssN_6F+K$TX0hI4dC%h6>4Ig&`(lSdj%EVSY}kWDnw5sEv>fzOm@LUq zi)kX?vvdjQE42yUvvhHElVvnPTAHka$;u4%CQan~m98vd@@90C)igm`nyiP(+td*6 zRrRMu6;5|tXSaW{`_i%t(dLXYGuC66j-gmifc+oG;*BSzl+2UQoa14d$fwc5!4Ud+TkoR3$4lfx0g`W75 z_g%JoXdFW~5{S~SZ0aW+l>K4-EeV6XR^0~zTi{*1WXBTNXyM5r1G+gzfhrI8S1o{>|!@+%* zUeSG0=!3NMNrz9r;p$HMi2E-644pd-9slY)fF4Lok9*-Uc)0o>J;Z&N!G_2GB6tj; z2h!4GI6Q_?Lf&^7W-!Il7(q1B5j4Oe4G7x!KAu&wRT z+gfnnWsITY|0^TXA%G!yq-o;SpvHFW$*nn@3&rN=yY z%o(m;qKCNeGRN?EDT2p*dLS)5UWLailo0n_UNMmVVqIj7S_0H!qQrfd#Xyx-e%|2d zkd~uc0pv0w<$afB1``XdxDLEYG}02i4(PSR)#~BuEego{E^FoXfcq}1@yNG&!wBxX zycJz?JtdKrk{?0xgW>8u8p``FAB6X^!uO0d0oyOU`z|eC*b#XB%W!pqG}(_&2FvG!0T#>Wlo5RW%Lv=qtq6|_BUJej{x6rZ zA6FQm*D8oXKQ50)6^y5Z`j$b*hw&u40zxfE&Y=mk;1<{Y2k0`qR(F|yLhBPr` z{3UrkCk1IaDQzKj;|SGigo>k-?8i46F0BI3IKxUTmUfgwTFP~TT*nbAk!GSFcQnKj z4IO`yI@1Gb>Cqh?w~SC-=^^^@Erv(e2p+f518M2e3m$h+LiFQ145YtUdt0MYfJ!Dx z^y6fpN-IBoIXa}}=NtBeGkxsMyP=!)Bp;|emqES59r4O z@yHRqVFdknKy=A_DT%a{%!K5K5h{a*vLBCtkLYEE8OEA`?E$YJ;~2`K53)=?-{N(9 zeZ2d}uaCsPCm&hL{o~h07Uch~ukd00c*#h=SRgHtZvwe|q*_XAZ^YEj!T7@a@dwtZkAeD#DAA8Uih$Z|jrt6zts~VI(qup08Z4hJ23Rbg z&pEqD%h}xtj~ye`m-LYRcn9czh<^NKbf0hNgS7P72cPdosy*}({rEdWXOE%dUuS=y z2h!5xXLuYOsSeOX^y7nu$AJhQhv|W|^f(HSBb1Q+_=v$2OXGK zj{b*eq$N5w6TdxrmB#s%4hml7156? zW)^Ml6*9xmkn(s$?n?fWtd!|ragdgiQWa8FGSzvR>KsbReq60_u9eUN4L$(vL3@5vvAQvrp&w=U(-D*tRp`{EYbn{IIxdps);1ap8Qy_ zK}|FyAoRLdR&fkHK^LTh%T%~bp@{6tQ}CRu(`%&Uz2x;C9>>r$;*k#c=Q1Pp*qS`p7Jaw++5&h6DNA}>**qT^ajIaeFT^H=z?@`*#wslDI&Y{hXz+Hm5+%>I^eeg zzlC_&r?*7MZzCS*fZqZ9mznAd8i-E)CAPnJ_4XHZ>Msl>zovZczJ> z^DO^&G|{umWtD!VJIx7q25_enC%X3Oz?D{_&g3YO4x>B=*t3Y0efunfi^W%5C(b1v z>43io_-a|IYL==(3E8=;Wr^(rox3U?`9Ntykq)ADAbMGrs!2=PyDx*2 z=y-)SjWq(}bzbkrF;tgM$g(@lE9%|X!RcBGiQauJ=$mvq2XgulV8^YE2iUgG)SI+EPUJ?zVVNw&`_JvUh*x;c*PLCm!j5@0b;- zcNddxA_?h0x)}rQ%z=vD-5JyTnSQRrdUsbRTzBAZAx`w}TO#0YbHeoou4k6IokZEY zdj?DDb^|V!R1#+z=`hoG!X-6JrO-w8?o=3jtY7a2ZY)q=QQ~Trw#ldv~V66-#9l@kj^! z{lJeVUiR+M(eZi2BOUM$0{=jk%BO+o-49^<+pf32pm*mRN`CJyaB_GY4v%H2iCO9q zYKY$bSa9x61YVvwj~GJ!GJS%RgLIgjXCXE{OHIvEQz#~T_jJQ&YT!D>FcXXCISL{j z1ZP8VR+gGcJJGvm8FDiXC4aK!&;{w>vJfr{vebOKh~B-xaG4*$M9bA^cWidrW z?_O+R{RRAn6K(}?%ZL-bdl_)0m8ds4N~FUmR{^_{SlPQ*8eA;C;ySUKc%%b~bU`|}`~sJsDI$CK&v;G_=yg)EcmL$!aSZ)RJkkOGd&J&dOgcsq(t-3h z2KpxlDth;ynC74Ka~;;Z|8c_o2i(8JiQfHh1l&m{T={I=N2d4|*bbhv~OefL1 z&o`7R8%q8)x*A=O4lXs|a!IzTP8ZR;FEL!IM{uc07o>wrUAWYyi0s|94X#)!^@vA0 z;2Qzoka*d<8%D=pK|Im{-vs!^+3G49h~C{e8?Uj}+h5STuQHVU+S1g?Ar20qY}F!L zHK&H?-J#&zZ2`PIbDA4M{xWUJ$w4|yP6EW@vsK${btA=O?~XTo+6JyS8fIegBvKIR zAlMaxU9wdt+KJxX#gOY{DEX7sjV?$BmpkCnBU^Q+i|E}w443W^Tzb+4>EO}_E=d#- zy*tUk`U^P433n%OslYi*hh!V1Q50TpkdiOne)p>0i*&%w0(NG$dVyrwyJrTQ*9(RO zg#Pe~FOH#?=z?@`nGct_6p_7qE}oOI4Z?c&xCZ()**Jz?CLZa4e>FSO{qADYB9f2} zq$L>WVh&XF?!}nqaTsTK?|#Dxw*t6j#EIU$ECTLLC)^s~R%NS|B+A~sDp*o04Y*iR zYdOLWUd-u+Wm^Q7FX@7GaQOxUg&Ln_{wepD=um2d;k`W@7QgjNkjdiQCg!YAugJR-Mwf3hml1?ezZ=fdUeQK}MMMDIS^aH$l*o4GHPPmJKyNEc^yDtK+v=Vg*M~QS8Wi4Q95G#9k4TFotS6nA9BOd91 zZv=e9QL6qZRhJU7cQ+g*wh#2~`gr6ay`coXyKZ#RD=3O|5N!t0CZkkiTFTzt1Wuyk z6*e~32#m+-)~Ao5Yw3h6yVKW2z58Z3b*7N$-JL;yRClqk-rbd0qyx4Gu-!+gTS%6@ zyZfl3o0GQ~5)hi?6<-`fx6=jb;F1KFUKEkNyBD65sd}B1yx%>|!{ZoACLZa4PaPGh zcNde=NJ2W0`eUGXaiF4i--T(Orl0Gu``zhIxc>onH*unO-yH!r$O$(TxFMs|JtWHB zJtSCC_ZV=oq=s>(kq$GR4VTPOY6M+m@6Lq5Bt6@~{q7Obokr0K>EJXDPI;r$7&?jG zoo6VGF_ipkbUs~>4lWPFrC^krKo`-w3k;VD5nLXj3(~=5GF&E6ME34U23IVV$B9Qe z;GYKmDdJ`CekwYCD)C4M{0qQ8H%dK21JS#m!}j;A-u{B#{fwdH*OnPh4)ftKca)kv zO3k8%=-qRJb9XlI^30iK2>HwOWlj##VRDv0Z1E_yXp~w=G1cJPkq-E8 zfd6`w`f8NgP6^q&zn0qvdiPg&WQN{Qg5JG7y6CqQMLLM?hv>dh>N{G>-n}op;}w2q ztPvPb^?Emsp&#jlEW6XOqTYR04*nvZqJq zs4Gd7z5A+QNnL5c#ge*)GmUhZ=@xKlo}-%4MfUFIFqo}pJLuibqB~trC!~W@8#uMj zQ7!2tdUtC>simRhU!&X71?k|@5iW^2sy$sq?@lya+DCA?i7rS7m#%Q>LJ`@!yBJ)t zRJsw5binrjzB}=Nd z;u%Ikq=Von2xjG|k+c)NJIjz8X(;)Vl|vV#gUdL$Hf&u|$N!6lzANC%e! zxJ;mk=-m?xtiOOCa>7jn?h)cd?|uZh(n{1MjuPoG$|r!GOswqPlMOBwUvZsyl6a&8 z{yE^E$x+jC)YFuZz55xteV}(w!y_y8h7$Ddr=yELPf?_U=v;`-&QY^yDSP+q@QznF z%UB~YUgGs`97FTyge<$$e?`4}4V+d{Nc8Sips&{LAgp(A5cX0?ho*sysy_u$=>~ehsQCriFl*~eoMsOT}=9v zB%}lBa}0DF2P%5^Hcaye`neA4-CsE2b^!M!aiVvB83FgT6K)T1yK>YwB+A~sD_BzB z7;v$q_Hw3?4l{iKF8g!TKDx->y&nc^^=t>ddtY>?pXh{iaQY2SzvigJbP~P$S3~Kr zq2ynqkJ1I{;PMY#{>o8*&_(p_zYLc@BDfr<3(~j>{hz@VOC>hfzXO4E zz@G;Esk#1*581m<%?&>*1-=6DNC*7cz*ovuXV5_O?n=1@<2UK;FX-K87)pL^ImgN2 zLO5KItIp3=m8l_m_XW8{w_(l)UYbNp2tL-5v4B7QLYay*n|w=*<*GI*8r@(H^;~J1u4J z?g1y!@d~>eYXrvcd%YXSP)|A`%kES@HYUb3(-HX)H-d2hsx=Xg&ujdUrmid6#~!!+Q4wC)~rp6%Z$ScR>W)BTl%-fqN`h zO(aqF?#F^9HPL{JCG`Yn8tE|8)8R5TS52Xd?A=pg@VTDtpm$G+?(__ukPc3>;50K= zy+9|?yJs3oFBnSxHTosGARSy5z-4}}noAeayXPA&b0fICLKmci%VM}JqKNF>iwv$< zDz6idbigkMekt*?cQ1{OUqL+50lx;<4Mgu=h3#*z-u{B#z0y$fYs*?Ehxg&I zF;{KKRqLrCdiTcQ+}!}YJag6?LjE%SfRlrCn4GN;+mfp`=c-Ku>4J1{ zIRKaa6cN39zk&4^@J~*-!@wOPPW0|Wz?D{_e&HyQ4x>B@>=9yR?>=I1vG|JX#P7r- z9q=cBKc1`p&Q*U>LiX)kD!aB;weh!ed#6am-L3D*v| zHltN*5@qjh6D+CL23#zuc+ND^VWvC5rQ>LoNEg|=JHp_gp6#G_Cq{SbOeds+(`|6N zb+qb6C(*laHI%v;O8zyv2VIa3F3E7|JzDjoi|F0G4VRt~T>8)j>ELoFTv90_dv~hA z6-(tV;*k#cyMa$9UiR+v==g!eBOUPf0e|mkHJApXci)Tc?=QXm1-*N)q2$+=p-v8? z;E*+1jU26pQ$zIbtl-=o3A{XWh8sfuGR@)SARQ)WJjBM0R(Ye<7>dc>JEt>L>Huk%M`dgIa)nV7ty<)G+Z8!;PNzG zkPa@-!eu%|MDLz%VEqOBoD*&)a4!%idiM*!l~$r&`+&<8|U%?~)>J266-7iNMT})A=gJ>Z{SBzH6XeoR5 zitvtCxXf51F#g@^-8hC;(g|61r!_^r``j`3SIA>Zd42cUV+!(5>UI#;yU!cr*L|b| zwi>Wi$EYeK%idjeOi}NyVn{$}Y(xEqA~=RFqzlr)mmB%}kW0R~!+0~Niy9;SIR#u?tb8#>{x1g;TrqIWlnfKyJm zrode@MqN#!?A_M{OX_L^E|yd?&NR|trf-1D^<&g^bdkOLdKiq=vmNyA>!Lfw(Fy6` z6c4AiW7Lgw61}^vp>(660?wsYKY!_cW~~e124~hUl zitEJF#3LQ>Gk|}7jCyvAnobGXyPuca2YUCjcx0;HP=ek)J-X;jiXt6EUxw(sF=`Gi zW$&IB-th|O7;6N^kLlK@kD�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�O_O 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

_??{t89nhrG2pr`$d z4l>Wu!R9$S#5_-jniuFW^CBH?UZNw+%XFl9g=U+%^m8*{jxsx7#L2*z(-EUiC-V!l zGsd1S7=5~8{K>=!)Xkh|cE>o>!<=mP#AwtD<56#On)xY4r7UxX*#~3OXBeIOnqQgy zFh=#qC^Z1%)Ic)_W7}MFusIJS+utsSPv8%fTAy%j$<>-?|@<>P;3H<%|P)z zQ2YQCgGr9Llg!09InUfh=9@o}1sE|GV$57*?k0=PVPuIpoGdkeCd=mzsJ`OZ8-Hk!YXP3BRu**r$R zH-9BRAlqBa5p*kh!;gq=oB1Q%j*RaxkCUCq^e%k=$^4D%HcybB&4F}}d6MikPmz7* z0=nP)og6SvlY@{sWPV2vn`g)o^Izl_=pDtsWAO8_0r$o^&X0KI|?<|0dhGGomSWoDQe zWpYW!G6CAD%mv!HOb2?m@6JF+%oc8biqTJxrZoNf-3TK$*XIlOJ@saCQu?Fi%4Ol# zLmYXuY3t-B>F*`uhnPKrjTzdrEQEWwseve`(2ke7@U?-QZ*Aj+OTL&>s9_%{M#1vi%Qd z8g42n@XMStxiOHL;E;RDSMn)q-kIEB1oa$i0Lw?o$=tJ3%+w)AMwFb)Ka+dDn9p}u zCnwv0$(@GJsN31MypOUc+ku@~49EW{l_$f#F*)Sa&$??$i{#eTP0R_OZ=Kq#by7=G z2S?J#-`Yl1DVta?rAh15wA44#iI^Rd`sr<&rlclTC|AB(Vy)DcE!(`4lHM-yrCNy% zQd3)`CDyBtujMN}TA}Kr6{?jlUoNq6$~%d1scGpAqpI+EWRnVyHf_NiiST)x7iO?>{Q zscAm{D=9vIg0B+(H1zo~S#8}4XX2aTA5O+MuHf@O9fxn&vgeO&=kwP|Nsn**Rvq>T zy!_5?9q>K%51m5uXe3h1uVKIGA8Ow^U*}VFe{5RC3RSB_A=2lYrX)41*9LcSzH-)2 z`I?n{x74}s;vJQY%owy)1@yMt?g@PTuCG7(d#RU-V>B!E2piK%1+K%ZAyEFE|NVzJ zb|XJ_>yEn$9LY5{Y)Rw#uGd}8YEvaHw#~cQRm*0bDsjH558133RVg+(UEV^;+r8^< zL?{7*q2Y6aF9Fni5pSSc;!;qjE;_U?BMdP?pbSopA^36xwc@Iw|iYwNMWJ4vk4nV=h`Ga1XrP!JO=X#_d53*8gj?$kTZgI#Zd>EVNyq zEp+Z@UiL!gPOgJ%B%fSOW2#j!?guVFRphI5P|uaG=}dYilfD5l@thriqx*vj-Z`7W zv@$X51)hYK%G*OhEswm-WGVyDqJhy+;dwg-M~?(m+oeq0UYtr1T^7j_R0nQ&x!HZ+R*uH5xv-RBxS=kt}p z@uI$6ccp<{X_PMN5gWKVx~NsPDpEHRI!-eYys~LCzPkH|PvhLfEicI-i}}5p>u{v{5j)QV>|c-7b~T)6#LZG)hC-g7DE2 zzMEeamoC2kXFdgc3EX}0#@+1wLigcaMdz!Ew+zP{l)tX*M+scKZ7w$&VkUnZ5Br+; zHlBhxsvK`rV2&!o(WR<&{9!TjjY!pU!eT71L5eC8!(Vt*-SWDih!`kFv$syMFHc2o zh!$^3i$GgQZM=J^17Rp-6UM+V-@Cf+{AHEVFt>}z2`H;gwLFwhMF+Q6HfipBVE z3gS-8xe2(l)Z51Hh`|e;Y?0g^<134!%)o1wXiBgkUPm-IA8))7*)RCQxZ4npE%E%- zSHcS-%OcV~zKeIpHD*@j3zN9jCOlI1wXl(X9B;H^KtD#LHzLxzWBjFJ{C5U}4P>A% z*BVV$I*MyX8(1GpWYE8#=rN`Te$3jwkZv&-K2#j1tPSYR@=frtGda_Fp%>=j4$ z9**%pq*6B>$8#RCrmk8!ME@|3tMbUU;~>I>3>@rW%H?hS<|$;ZqNU%U&LQmdGPX+?gA9!AMI~}? zG+u$2&0fyPk|uER6bYle6A6bnI+Q#s-^~_PL%P}L(eAp-ND&L|dN+SQ!TqE#%;{Dk@j|6%Zc9$R>Q@yZ99dRFfWLXA>T(GY>2qtXk-7 zya;U|dmaT3g4L0Yhmeg%G5*(L{I9Bnyo^&huiCr!1i-@n~PgL4*z&ICz68 zzh=#5R0^`$$a00F&LJdu8EY(zK?cT}p%Qt_`pdxW@QYgb5cv~eHGN5dY|iYm?6GR0 zv)2jQz!N~hp|d)&_Xx7rBF6ugN?j(7=e%W2U9~odz6Flt{W7GZFX1RR)C~%jgucVW z?v8^Ud$Ygx=1i=0&p9r;9P0|jFOIbc>thx=1&3z1+;>ZmM@h69(nxOF4P5ir5x#xw4Q0 zoQ15yT7aF)Yk_bhH`=n`9)VZ>u~p+DF>Do?tr~{`38xfvOR{{myM)xco$G~%-NDK* zre7?Et#apQ!Z2>q`zVQD)Z$^>$Gz~u7WK5wcAYhHmw@lQPu|B8V#_}+5qn~ff*Oz)POW3cllDGUngDtN$VHojx zAC{I+lBsGgeWaiiE#F8J{cE1l8^)`8f3}u?M@E${J+@I%waBkA-nzPZwETxMoKDhs zXC6*?SQlCE%1hSrALQq(ttR&OJY%=C{GVf=gb~0FfxEFig6)n7kPg^a&_u3Ly$H*&7hySe9ejgb z2j5~Z!f5P8n2Nm!D`0me_99HfUW80|=!U%r-QlMPJoUt0gjMjj8XnhRFTz^*T?fzW zv4fy5{P)9Ng#JJ=05}F>FTx<88B9JW)3Fy}2s{kMUW6Igi!cm(5r$(g!c6Sy7(vF9 zS=ie#l1zm3B=QyZB76?)qkv{M-|aD-%z;)8q~}6%9wg@D%mVBKS%@=>aAq;iEWw$j zIMV}XmJznr#@<=_Z(M6*D?j#+bKz>SO-`3h9kcon>wY>le+WJvz zW0tkHNXXRJ$ywIgE+D(@94)2nS=QQmLN2X@)$4!PT3dz6RsJGtZ4Bw3aILMDeXR`} z2>u*vZK7dI8n4%16&bbfgY_v@p3E%Yx&Po2JNdd9PHWbW?!{0&oPfR$u&Y9>9qkV4 z*w&67fMhn4+ygHoQDeRQT zst(&G%N7?SrUlg+IaZ`@fy6Y9w4033vaBPc{EIH@?6fcIwEDxBb9RTgoHO1^^ohkF z3teF)`Xbm3^0hDLycBP|z&L@IKuPQeXzOy$D||VpXTg?pUbV0jB^aheFcW+^=k+`y z?`Cu<#=y4X+yPt0=}EvH^mHxbyuqwlmvNH#?LRY|cl%$kRkjb~jrUoEA0on|h|sx= z6YzmI@m|L1fK!&R*pi6BmwgbLSjOqfl-UxC%93^&C)3LqTLyx$2f5|ms6`V@h_1lkUiTn&Qu&P)H2RAC|D9&mWRz2 zgOCHUj58aR$ggA$*s6J9mvO#k)>!1sc%dWT1Z_mV4h4^#)zNRxB68<4&K8`~EaPm& zDNC4Qse>*1AWX50!xnn@GEQE<(JkY!A&?ipHCKD7&ZxAbeK&bQsRWcCt z$PmyWBSCkJ0U~ z-od!2?bDob84VA7m+t#;uvsYB`4+W#n)5BU!2{o;`yu4F3wbBoQWkI~FgToTc?TMN zhi*sg(0!lN5#^m^1Y1yJ{LEF@n23%-T~Q!xZ>lHV646RJa~@v zU+LlESCW`DE5Fj1M|ds#%17}=TNdF*h;Th3bn+`5a9L>hl?ws#f@75oaLMxwoawosSNE8jf!l)EWn1WwnlnTNW{0bvYIKPtDZ*=?$qf%VP*xp$f6a2~^ zR3bYD`4zsmSkJHUPBg&HuP`db|QkSVdgcTN0C`B2#v zje#Jy;&Hkty4fGdtT1yyX2rwXAIGcYWBfnCssz*cXJb{mx>%L2U>$ma|HuOG(H9Iy za68NhuoUdoA>&Eu#{zh@L^7fCLO<}k3_K##!Dg++| zFCd#zK|W}nKbx`)Ef8c=M*ab83VZakAZ*Gmq&<$cfaRlD5(k^|kd7sBuqjSLOWCuq zDMx|t*&mjBi6v|Ic$NqDe~{ zo&B#IoWG{^T^R#rytMe}(JxDks_MhJLNF;~xx&?mlvMB*6S(A6c$AuoN14vW^QBR; zky%coya)5MxqN;s%FVclIg8RB;tRNV{v=8Y6gY{Jan&s=5vkF>dbKON_oWDerAahS zx~UD14J$2}q@A$13ULyV!CkxPnTYlRlAAV}OuYB6FxrGuD(?wR$L1Br7co}lFG`?{ zvJ)tYfD2bdv5!MBPBJAS3`#EE7O+07Jz7{q@ z>vP7_5#g9<|EOqxb}&f3;Up*97S?1DQh;$KmPY!5MHA?Rg9r^Ws4!L}XOuNdQB#nm zG0}O?8Kchc#Ti%PGA5rhh762lK_c=!D}lo8@LUNWB3A;erauUfeHch~6U(ZF%~*gv zR}4JkQE=$2j!r!r*_$5ipQ=*F_>i2b*3?y-i|D80NZ!+AIp`xe$_+W5GoH!Amd_bO z4n7(G5!v2Kpa}bxXr+DR!u~Xwu$BV@JaSeobmW@nj29sCMbZ8R(f)ZVc*c_CEV6~V zN`}d}5=&Dr;gQMbj3I+C`E$neZ2e|6GPl6eZ&2qsb3A7(jLGMWAp>K3S{7EKtGV_XT7lLU%@!#R`ivXBED^_(#~m)8Q} zMmOuzWW7;gPm}eH4n9rR6TdY2w|nx(yaq|75nL%eY$PlB14RR(*`s7yeZ%Odu^znb z2j%buth0y6CQIv6P>M&1#zcERL^etsw>(59*pqCHGaGp_QwEbG-OW|OOpngz39_kI zv5i2M$Us&}%d2@H;bCiJeJwB9Lqv=6^Rz${^*qn0|BMe2T@!cmw@eZME7C#3kFdv( zdV?SN6#PgQSdl(pMLxR<;gkxr5y>1^Rgx>)#;uHZ*9!H;wUKhhoihP8tRow-7Sz^7WtVv56KhDTZ?!T~o=d?vb z@2@hm+vyUW8Ev3@o1WKBlT5Bq5PqZ=mn<+p(vOQ5oF5s?`nRG!MtD@R6CM$qf2icOU&V9Z$<+uF&dqqdU+$_r2xm|#IbO}iHlB#hC5+Xn zS3X5~l3``E69AF;lVEfY6XiXW-w&5u~$$Hu4){ysL&k33aa zendRL!;IwJkHkL^h$uyT@g#7?7hkdXo44M3WB5aXY3z5b#FATmH^+zVxC;;NSRUZ% z1<+Q0I_B2Y5o^N7Ms6*Tj!#9^lDFJQ_yb& zKf)N4oPzNqjt6*zG5G+G;75Ljv5@(ZJuqTv8sUa9FAjbr$fMZ!5y7KKeuOb7yzgBL zKT;{*{UulDM>P79AMrT*@8d^2oc&?^NItgz$B)SW7>yCYZV=}aI|bNV@@N38MF;Ha z$N+265xY7%VOK|2uojuv6VeTPLcI5tj0amX0c^=cuqBhgn@k38GUY0~342l}xUXc0 zg*O>0d6Qul-ekCiHyHshBjF_*Uf9c37;iF)Kc(|DW^DiCO>8eoVK?md59dw(AM~I( AIsgCw literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseDebugPrintErrorLevelLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseDebugPrintErrorLevelLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..5dfdf31ab8207d4764903b36e87cd3296a8140f8 GIT binary patch literal 2698 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 z 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 Co_uTo literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseMemoryLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseMemoryLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..405d96c8d1bd030dd5c0355f8cc019fd40b72ed0 GIT binary patch literal 65914 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 literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/BasePrintLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/BasePrintLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..b3e0ee8daa602ff517787bf8af5c54e29da00e9f GIT binary patch literal 57382 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 literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseSynchronizationLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/BaseSynchronizationLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..9fc3d943f65113bfdf68cfe45379fea0fdc590df GIT binary patch literal 21532 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 +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = CryptoPkg + PACKAGE_UNI_FILE = CryptoPkg.uni + PACKAGE_GUID = 36470E80-36F2-4ba0-8CC8-937C7D9FF888 + PACKAGE_VERSION = 0.98 + +[Includes] + Include + +[Includes.Common.Private] + Library/Include + Library/OpensslLib/openssl/include + Library/OpensslLib/openssl/crypto/include + +[LibraryClasses] + ## @libraryclass Provides basic library functions for cryptographic primitives. + ## + BaseCryptLib|Include/Library/BaseCryptLib.h + + ## @libraryclass Provides TLS library functions for EFI TLS protocol. + ## + TlsLib|Include/Library/TlsLib.h + +[UserExtensions.TianoCore."ExtraFiles"] + CryptoPkgExtra.uni diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.dsc b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.dsc new file mode 100644 index 0000000..0142f64 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.dsc @@ -0,0 +1,130 @@ +## @file +# Cryptographic Library Package for UEFI Security Implementation. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = CryptoPkg + PLATFORM_GUID = E1063286-6C8C-4c25-AEF0-67A9A5B6E6B6 + PLATFORM_VERSION = 0.98 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/CryptoPkg + SUPPORTED_ARCHITECTURES = IA32|X64|ARM|AARCH64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses] + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + +[LibraryClasses.ARM, LibraryClasses.AARCH64] + # + # It is not possible to prevent the ARM compiler for generic intrinsic functions. + # This library provides the instrinsic functions generate by a given compiler. + # [LibraryClasses.ARM, LibraryClasses.AARCH64] and NULL mean link this library + # into all ARM and AARCH64 images. + # + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + + # Add support for stack protector + NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf + +[LibraryClasses.ARM] + ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf + +[LibraryClasses.common.PEIM] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + +[LibraryClasses.common.DXE_DRIVER] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf + +[LibraryClasses.common.DXE_SMM_DRIVER] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +[LibraryClasses.common.UEFI_APPLICATION] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ +[PcdsFeatureFlag] + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + +[PcdsFixedAtBuild] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06 + +################################################################################################### +# +# Components Section - list of the modules and components that will be processed by compilation +# tools and the EDK II tools to generate PE32/PE32+/Coff image files. +# +# Note: The EDK II DSC file is not used to specify how compiled binary images get placed +# into firmware volume images. This section is just a list of modules to compile from +# source into UEFI-compliant binaries. +# It is the FDF file that contains information on combining binary files into firmware +# volume images, whose concept is beyond UEFI and is described in PI specification. +# Binary modules do not need to be listed in this section, as they should be +# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi), +# Logo (Logo.bmp), and etc. +# There may also be modules listed in this section that are not required in the FDF file, +# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be +# generated for it, but the binary will not be put into any firmware volume. +# +################################################################################################### +[Components] + CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf + CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf + CryptoPkg/Library/TlsLib/TlsLib.inf + CryptoPkg/Library/OpensslLib/OpensslLib.inf + +[Components.IA32, Components.X64] + CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.uni new file mode 100644 index 0000000..67bb1b4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkg.uni @@ -0,0 +1,25 @@ +// /** @file +// Package for cryptography modules. +// +// This Package provides cryptographic-related libraries for UEFI security modules. +// It also provides a test application to test libraries. +// +// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_PACKAGE_ABSTRACT #language en-US "Provides cryptographic-related libraries for UEFI security modules" + +#string STR_PACKAGE_DESCRIPTION #language en-US "This Package provides cryptographic-related libraries for UEFI security modules." + + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkgExtra.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkgExtra.uni new file mode 100644 index 0000000..30694d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/CryptoPkgExtra.uni @@ -0,0 +1,20 @@ +// /** @file +// Crypto Package Localized Strings and Content. +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_PROPERTIES_PACKAGE_NAME +#language en-US +"Crypto package" + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/BaseCryptLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/BaseCryptLib.h new file mode 100644 index 0000000..0a5a5ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/BaseCryptLib.h @@ -0,0 +1,2876 @@ +/** @file + Defines base cryptographic library APIs. + The Base Cryptographic Library provides implementations of basic cryptography + primitives (Hash Serials, HMAC, RSA, Diffie-Hellman, etc) for UEFI security + functionality enabling. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_CRYPT_LIB_H__ +#define __BASE_CRYPT_LIB_H__ + +#include + +/// +/// MD4 digest size in bytes +/// +#define MD4_DIGEST_SIZE 16 + +/// +/// MD5 digest size in bytes +/// +#define MD5_DIGEST_SIZE 16 + +/// +/// SHA-1 digest size in bytes. +/// +#define SHA1_DIGEST_SIZE 20 + +/// +/// SHA-256 digest size in bytes +/// +#define SHA256_DIGEST_SIZE 32 + +/// +/// SHA-384 digest size in bytes +/// +#define SHA384_DIGEST_SIZE 48 + +/// +/// SHA-512 digest size in bytes +/// +#define SHA512_DIGEST_SIZE 64 + +/// +/// TDES block size in bytes +/// +#define TDES_BLOCK_SIZE 8 + +/// +/// AES block size in bytes +/// +#define AES_BLOCK_SIZE 16 + +/// +/// RSA Key Tags Definition used in RsaSetKey() function for key component identification. +/// +typedef enum { + RsaKeyN, ///< RSA public Modulus (N) + RsaKeyE, ///< RSA Public exponent (e) + RsaKeyD, ///< RSA Private exponent (d) + RsaKeyP, ///< RSA secret prime factor of Modulus (p) + RsaKeyQ, ///< RSA secret prime factor of Modules (q) + RsaKeyDp, ///< p's CRT exponent (== d mod (p - 1)) + RsaKeyDq, ///< q's CRT exponent (== d mod (q - 1)) + RsaKeyQInv ///< The CRT coefficient (== 1/q mod p) +} RSA_KEY_TAG; + +//===================================================================================== +// One-Way Cryptographic Hash Primitives +//===================================================================================== + +/** + Retrieves the size, in bytes, of the context buffer required for MD4 hash operations. + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for MD4 hash operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Md4GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Md4Context as MD4 hash context for + subsequent use. + + If Md4Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] Md4Context Pointer to MD4 context being initialized. + + @retval TRUE MD4 context initialization succeeded. + @retval FALSE MD4 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Init ( + OUT VOID *Md4Context + ); + +/** + Makes a copy of an existing MD4 context. + + If Md4Context is NULL, then return FALSE. + If NewMd4Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Md4Context Pointer to MD4 context being copied. + @param[out] NewMd4Context Pointer to new MD4 context. + + @retval TRUE MD4 context copy succeeded. + @retval FALSE MD4 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Duplicate ( + IN CONST VOID *Md4Context, + OUT VOID *NewMd4Context + ); + +/** + Digests the input data and updates MD4 context. + + This function performs MD4 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + MD4 context should be already correctly initialized by Md4Init(), and should not be finalized + by Md4Final(). Behavior with invalid context is undefined. + + If Md4Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE MD4 data digest succeeded. + @retval FALSE MD4 data digest failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Update ( + IN OUT VOID *Md4Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the MD4 digest value. + + This function completes MD4 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the MD4 context cannot + be used again. + MD4 context should be already correctly initialized by Md4Init(), and should not be + finalized by Md4Final(). Behavior with invalid MD4 context is undefined. + + If Md4Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval TRUE MD4 digest computation succeeded. + @retval FALSE MD4 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Final ( + IN OUT VOID *Md4Context, + OUT UINT8 *HashValue + ); + +/** + Computes the MD4 message digest of a input data buffer. + + This function performs the MD4 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval TRUE MD4 digest computation succeeded. + @retval FALSE MD4 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for MD5 hash operations. + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for MD5 hash operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Md5GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Md5Context as MD5 hash context for + subsequent use. + + If Md5Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] Md5Context Pointer to MD5 context being initialized. + + @retval TRUE MD5 context initialization succeeded. + @retval FALSE MD5 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md5Init ( + OUT VOID *Md5Context + ); + +/** + Makes a copy of an existing MD5 context. + + If Md5Context is NULL, then return FALSE. + If NewMd5Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Md5Context Pointer to MD5 context being copied. + @param[out] NewMd5Context Pointer to new MD5 context. + + @retval TRUE MD5 context copy succeeded. + @retval FALSE MD5 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md5Duplicate ( + IN CONST VOID *Md5Context, + OUT VOID *NewMd5Context + ); + +/** + Digests the input data and updates MD5 context. + + This function performs MD5 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + MD5 context should be already correctly initialized by Md5Init(), and should not be finalized + by Md5Final(). Behavior with invalid context is undefined. + + If Md5Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Md5Context Pointer to the MD5 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE MD5 data digest succeeded. + @retval FALSE MD5 data digest failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md5Update ( + IN OUT VOID *Md5Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the MD5 digest value. + + This function completes MD5 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the MD5 context cannot + be used again. + MD5 context should be already correctly initialized by Md5Init(), and should not be + finalized by Md5Final(). Behavior with invalid MD5 context is undefined. + + If Md5Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Md5Context Pointer to the MD5 context. + @param[out] HashValue Pointer to a buffer that receives the MD5 digest + value (16 bytes). + + @retval TRUE MD5 digest computation succeeded. + @retval FALSE MD5 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md5Final ( + IN OUT VOID *Md5Context, + OUT UINT8 *HashValue + ); + +/** + Computes the MD5 message digest of a input data buffer. + + This function performs the MD5 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the MD5 digest + value (16 bytes). + + @retval TRUE MD5 digest computation succeeded. + @retval FALSE MD5 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md5HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations. + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for SHA-1 hash operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Sha1GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Sha1Context as SHA-1 hash context for + subsequent use. + + If Sha1Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] Sha1Context Pointer to SHA-1 context being initialized. + + @retval TRUE SHA-1 context initialization succeeded. + @retval FALSE SHA-1 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha1Init ( + OUT VOID *Sha1Context + ); + +/** + Makes a copy of an existing SHA-1 context. + + If Sha1Context is NULL, then return FALSE. + If NewSha1Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Sha1Context Pointer to SHA-1 context being copied. + @param[out] NewSha1Context Pointer to new SHA-1 context. + + @retval TRUE SHA-1 context copy succeeded. + @retval FALSE SHA-1 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha1Duplicate ( + IN CONST VOID *Sha1Context, + OUT VOID *NewSha1Context + ); + +/** + Digests the input data and updates SHA-1 context. + + This function performs SHA-1 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-1 context should be already correctly initialized by Sha1Init(), and should not be finalized + by Sha1Final(). Behavior with invalid context is undefined. + + If Sha1Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Sha1Context Pointer to the SHA-1 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-1 data digest succeeded. + @retval FALSE SHA-1 data digest failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha1Update ( + IN OUT VOID *Sha1Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the SHA-1 digest value. + + This function completes SHA-1 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-1 context cannot + be used again. + SHA-1 context should be already correctly initialized by Sha1Init(), and should not be + finalized by Sha1Final(). Behavior with invalid SHA-1 context is undefined. + + If Sha1Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Sha1Context Pointer to the SHA-1 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-1 digest + value (20 bytes). + + @retval TRUE SHA-1 digest computation succeeded. + @retval FALSE SHA-1 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha1Final ( + IN OUT VOID *Sha1Context, + OUT UINT8 *HashValue + ); + +/** + Computes the SHA-1 message digest of a input data buffer. + + This function performs the SHA-1 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-1 digest + value (20 bytes). + + @retval TRUE SHA-1 digest computation succeeded. + @retval FALSE SHA-1 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha1HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-256 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-256 hash operations. + +**/ +UINTN +EFIAPI +Sha256GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Sha256Context as SHA-256 hash context for + subsequent use. + + If Sha256Context is NULL, then return FALSE. + + @param[out] Sha256Context Pointer to SHA-256 context being initialized. + + @retval TRUE SHA-256 context initialization succeeded. + @retval FALSE SHA-256 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha256Init ( + OUT VOID *Sha256Context + ); + +/** + Makes a copy of an existing SHA-256 context. + + If Sha256Context is NULL, then return FALSE. + If NewSha256Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Sha256Context Pointer to SHA-256 context being copied. + @param[out] NewSha256Context Pointer to new SHA-256 context. + + @retval TRUE SHA-256 context copy succeeded. + @retval FALSE SHA-256 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha256Duplicate ( + IN CONST VOID *Sha256Context, + OUT VOID *NewSha256Context + ); + +/** + Digests the input data and updates SHA-256 context. + + This function performs SHA-256 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-256 context should be already correctly initialized by Sha256Init(), and should not be finalized + by Sha256Final(). Behavior with invalid context is undefined. + + If Sha256Context is NULL, then return FALSE. + + @param[in, out] Sha256Context Pointer to the SHA-256 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-256 data digest succeeded. + @retval FALSE SHA-256 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha256Update ( + IN OUT VOID *Sha256Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the SHA-256 digest value. + + This function completes SHA-256 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-256 context cannot + be used again. + SHA-256 context should be already correctly initialized by Sha256Init(), and should not be + finalized by Sha256Final(). Behavior with invalid SHA-256 context is undefined. + + If Sha256Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha256Context Pointer to the SHA-256 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-256 digest + value (32 bytes). + + @retval TRUE SHA-256 digest computation succeeded. + @retval FALSE SHA-256 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha256Final ( + IN OUT VOID *Sha256Context, + OUT UINT8 *HashValue + ); + +/** + Computes the SHA-256 message digest of a input data buffer. + + This function performs the SHA-256 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-256 digest + value (32 bytes). + + @retval TRUE SHA-256 digest computation succeeded. + @retval FALSE SHA-256 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha256HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-384 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-384 hash operations. + +**/ +UINTN +EFIAPI +Sha384GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Sha384Context as SHA-384 hash context for + subsequent use. + + If Sha384Context is NULL, then return FALSE. + + @param[out] Sha384Context Pointer to SHA-384 context being initialized. + + @retval TRUE SHA-384 context initialization succeeded. + @retval FALSE SHA-384 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha384Init ( + OUT VOID *Sha384Context + ); + +/** + Makes a copy of an existing SHA-384 context. + + If Sha384Context is NULL, then return FALSE. + If NewSha384Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Sha384Context Pointer to SHA-384 context being copied. + @param[out] NewSha384Context Pointer to new SHA-384 context. + + @retval TRUE SHA-384 context copy succeeded. + @retval FALSE SHA-384 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384Duplicate ( + IN CONST VOID *Sha384Context, + OUT VOID *NewSha384Context + ); + +/** + Digests the input data and updates SHA-384 context. + + This function performs SHA-384 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-384 context should be already correctly initialized by Sha384Init(), and should not be finalized + by Sha384Final(). Behavior with invalid context is undefined. + + If Sha384Context is NULL, then return FALSE. + + @param[in, out] Sha384Context Pointer to the SHA-384 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-384 data digest succeeded. + @retval FALSE SHA-384 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha384Update ( + IN OUT VOID *Sha384Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the SHA-384 digest value. + + This function completes SHA-384 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-384 context cannot + be used again. + SHA-384 context should be already correctly initialized by Sha384Init(), and should not be + finalized by Sha384Final(). Behavior with invalid SHA-384 context is undefined. + + If Sha384Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha384Context Pointer to the SHA-384 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-384 digest + value (48 bytes). + + @retval TRUE SHA-384 digest computation succeeded. + @retval FALSE SHA-384 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha384Final ( + IN OUT VOID *Sha384Context, + OUT UINT8 *HashValue + ); + +/** + Computes the SHA-384 message digest of a input data buffer. + + This function performs the SHA-384 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-384 digest + value (48 bytes). + + @retval TRUE SHA-384 digest computation succeeded. + @retval FALSE SHA-384 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-512 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-512 hash operations. + +**/ +UINTN +EFIAPI +Sha512GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory pointed by Sha512Context as SHA-512 hash context for + subsequent use. + + If Sha512Context is NULL, then return FALSE. + + @param[out] Sha512Context Pointer to SHA-512 context being initialized. + + @retval TRUE SHA-512 context initialization succeeded. + @retval FALSE SHA-512 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha512Init ( + OUT VOID *Sha512Context + ); + +/** + Makes a copy of an existing SHA-512 context. + + If Sha512Context is NULL, then return FALSE. + If NewSha512Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Sha512Context Pointer to SHA-512 context being copied. + @param[out] NewSha512Context Pointer to new SHA-512 context. + + @retval TRUE SHA-512 context copy succeeded. + @retval FALSE SHA-512 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512Duplicate ( + IN CONST VOID *Sha512Context, + OUT VOID *NewSha512Context + ); + +/** + Digests the input data and updates SHA-512 context. + + This function performs SHA-512 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-512 context should be already correctly initialized by Sha512Init(), and should not be finalized + by Sha512Final(). Behavior with invalid context is undefined. + + If Sha512Context is NULL, then return FALSE. + + @param[in, out] Sha512Context Pointer to the SHA-512 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-512 data digest succeeded. + @retval FALSE SHA-512 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha512Update ( + IN OUT VOID *Sha512Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the SHA-512 digest value. + + This function completes SHA-512 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-512 context cannot + be used again. + SHA-512 context should be already correctly initialized by Sha512Init(), and should not be + finalized by Sha512Final(). Behavior with invalid SHA-512 context is undefined. + + If Sha512Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha512Context Pointer to the SHA-512 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-512 digest + value (64 bytes). + + @retval TRUE SHA-512 digest computation succeeded. + @retval FALSE SHA-512 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha512Final ( + IN OUT VOID *Sha512Context, + OUT UINT8 *HashValue + ); + +/** + Computes the SHA-512 message digest of a input data buffer. + + This function performs the SHA-512 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-512 digest + value (64 bytes). + + @retval TRUE SHA-512 digest computation succeeded. + @retval FALSE SHA-512 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + +//===================================================================================== +// MAC (Message Authentication Code) Primitive +//===================================================================================== + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-MD5 operations. + (NOTE: This API is deprecated. + Use HmacMd5New() / HmacMd5Free() for HMAC-MD5 Context operations.) + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for HMAC-MD5 operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +HmacMd5GetContextSize ( + VOID + ); + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-MD5 use. + + If this interface is not supported, then return NULL. + + @return Pointer to the HMAC_CTX context that has been initialized. + If the allocations fails, HmacMd5New() returns NULL. + @retval NULL This interface is not supported. + +**/ +VOID * +EFIAPI +HmacMd5New ( + VOID + ); + +/** + Release the specified HMAC_CTX context. + + If this interface is not supported, then do nothing. + + @param[in] HmacMd5Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacMd5Free ( + IN VOID *HmacMd5Ctx + ); + +/** + Initializes user-supplied memory pointed by HmacMd5Context as HMAC-MD5 context for + subsequent use. + + If HmacMd5Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] HmacMd5Context Pointer to HMAC-MD5 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval TRUE HMAC-MD5 context initialization succeeded. + @retval FALSE HMAC-MD5 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Init ( + OUT VOID *HmacMd5Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ); + +/** + Makes a copy of an existing HMAC-MD5 context. + + If HmacMd5Context is NULL, then return FALSE. + If NewHmacMd5Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] HmacMd5Context Pointer to HMAC-MD5 context being copied. + @param[out] NewHmacMd5Context Pointer to new HMAC-MD5 context. + + @retval TRUE HMAC-MD5 context copy succeeded. + @retval FALSE HMAC-MD5 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Duplicate ( + IN CONST VOID *HmacMd5Context, + OUT VOID *NewHmacMd5Context + ); + +/** + Digests the input data and updates HMAC-MD5 context. + + This function performs HMAC-MD5 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + HMAC-MD5 context should be already correctly initialized by HmacMd5Init(), and should not be + finalized by HmacMd5Final(). Behavior with invalid context is undefined. + + If HmacMd5Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] HmacMd5Context Pointer to the HMAC-MD5 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE HMAC-MD5 data digest succeeded. + @retval FALSE HMAC-MD5 data digest failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Update ( + IN OUT VOID *HmacMd5Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the HMAC-MD5 digest value. + + This function completes HMAC-MD5 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the HMAC-MD5 context cannot + be used again. + HMAC-MD5 context should be already correctly initialized by HmacMd5Init(), and should not be + finalized by HmacMd5Final(). Behavior with invalid HMAC-MD5 context is undefined. + + If HmacMd5Context is NULL, then return FALSE. + If HmacValue is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] HmacMd5Context Pointer to the HMAC-MD5 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-MD5 digest + value (16 bytes). + + @retval TRUE HMAC-MD5 digest computation succeeded. + @retval FALSE HMAC-MD5 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Final ( + IN OUT VOID *HmacMd5Context, + OUT UINT8 *HmacValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-SHA1 operations. + (NOTE: This API is deprecated. + Use HmacSha1New() / HmacSha1Free() for HMAC-SHA1 Context operations.) + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for HMAC-SHA1 operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +HmacSha1GetContextSize ( + VOID + ); + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA1 use. + + If this interface is not supported, then return NULL. + + @return Pointer to the HMAC_CTX context that has been initialized. + If the allocations fails, HmacSha1New() returns NULL. + @return NULL This interface is not supported. + +**/ +VOID * +EFIAPI +HmacSha1New ( + VOID + ); + +/** + Release the specified HMAC_CTX context. + + If this interface is not supported, then do nothing. + + @param[in] HmacSha1Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacSha1Free ( + IN VOID *HmacSha1Ctx + ); + +/** + Initializes user-supplied memory pointed by HmacSha1Context as HMAC-SHA1 context for + subsequent use. + + If HmacSha1Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] HmacSha1Context Pointer to HMAC-SHA1 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval TRUE HMAC-SHA1 context initialization succeeded. + @retval FALSE HMAC-SHA1 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Init ( + OUT VOID *HmacSha1Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ); + +/** + Makes a copy of an existing HMAC-SHA1 context. + + If HmacSha1Context is NULL, then return FALSE. + If NewHmacSha1Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] HmacSha1Context Pointer to HMAC-SHA1 context being copied. + @param[out] NewHmacSha1Context Pointer to new HMAC-SHA1 context. + + @retval TRUE HMAC-SHA1 context copy succeeded. + @retval FALSE HMAC-SHA1 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Duplicate ( + IN CONST VOID *HmacSha1Context, + OUT VOID *NewHmacSha1Context + ); + +/** + Digests the input data and updates HMAC-SHA1 context. + + This function performs HMAC-SHA1 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + HMAC-SHA1 context should be already correctly initialized by HmacSha1Init(), and should not + be finalized by HmacSha1Final(). Behavior with invalid context is undefined. + + If HmacSha1Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] HmacSha1Context Pointer to the HMAC-SHA1 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE HMAC-SHA1 data digest succeeded. + @retval FALSE HMAC-SHA1 data digest failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Update ( + IN OUT VOID *HmacSha1Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the HMAC-SHA1 digest value. + + This function completes HMAC-SHA1 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the HMAC-SHA1 context cannot + be used again. + HMAC-SHA1 context should be already correctly initialized by HmacSha1Init(), and should + not be finalized by HmacSha1Final(). Behavior with invalid HMAC-SHA1 context is undefined. + + If HmacSha1Context is NULL, then return FALSE. + If HmacValue is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] HmacSha1Context Pointer to the HMAC-SHA1 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-SHA1 digest + value (20 bytes). + + @retval TRUE HMAC-SHA1 digest computation succeeded. + @retval FALSE HMAC-SHA1 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Final ( + IN OUT VOID *HmacSha1Context, + OUT UINT8 *HmacValue + ); + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-SHA256 operations. + (NOTE: This API is deprecated. + Use HmacSha256New() / HmacSha256Free() for HMAC-SHA256 Context operations.) + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for HMAC-SHA256 operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +HmacSha256GetContextSize ( + VOID + ); + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA256 use. + + @return Pointer to the HMAC_CTX context that has been initialized. + If the allocations fails, HmacSha256New() returns NULL. + +**/ +VOID * +EFIAPI +HmacSha256New ( + VOID + ); + +/** + Release the specified HMAC_CTX context. + + @param[in] HmacSha256Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacSha256Free ( + IN VOID *HmacSha256Ctx + ); + +/** + Initializes user-supplied memory pointed by HmacSha256Context as HMAC-SHA256 context for + subsequent use. + + If HmacSha256Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] HmacSha256Context Pointer to HMAC-SHA256 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval TRUE HMAC-SHA256 context initialization succeeded. + @retval FALSE HMAC-SHA256 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Init ( + OUT VOID *HmacSha256Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ); + +/** + Makes a copy of an existing HMAC-SHA256 context. + + If HmacSha256Context is NULL, then return FALSE. + If NewHmacSha256Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] HmacSha256Context Pointer to HMAC-SHA256 context being copied. + @param[out] NewHmacSha256Context Pointer to new HMAC-SHA256 context. + + @retval TRUE HMAC-SHA256 context copy succeeded. + @retval FALSE HMAC-SHA256 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Duplicate ( + IN CONST VOID *HmacSha256Context, + OUT VOID *NewHmacSha256Context + ); + +/** + Digests the input data and updates HMAC-SHA256 context. + + This function performs HMAC-SHA256 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + HMAC-SHA256 context should be already correctly initialized by HmacSha256Init(), and should not + be finalized by HmacSha256Final(). Behavior with invalid context is undefined. + + If HmacSha256Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] HmacSha256Context Pointer to the HMAC-SHA256 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE HMAC-SHA256 data digest succeeded. + @retval FALSE HMAC-SHA256 data digest failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Update ( + IN OUT VOID *HmacSha256Context, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the HMAC-SHA256 digest value. + + This function completes HMAC-SHA256 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the HMAC-SHA256 context cannot + be used again. + HMAC-SHA256 context should be already correctly initialized by HmacSha256Init(), and should + not be finalized by HmacSha256Final(). Behavior with invalid HMAC-SHA256 context is undefined. + + If HmacSha256Context is NULL, then return FALSE. + If HmacValue is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] HmacSha256Context Pointer to the HMAC-SHA256 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-SHA256 digest + value (32 bytes). + + @retval TRUE HMAC-SHA256 digest computation succeeded. + @retval FALSE HMAC-SHA256 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Final ( + IN OUT VOID *HmacSha256Context, + OUT UINT8 *HmacValue + ); + +//===================================================================================== +// Symmetric Cryptography Primitive +//===================================================================================== + +/** + Retrieves the size, in bytes, of the context buffer required for TDES operations. + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for TDES operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +TdesGetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory as TDES context for subsequent use. + + This function initializes user-supplied memory pointed by TdesContext as TDES context. + In addition, it sets up all TDES key materials for subsequent encryption and decryption + operations. + There are 3 key options as follows: + KeyLength = 64, Keying option 1: K1 == K2 == K3 (Backward compatibility with DES) + KeyLength = 128, Keying option 2: K1 != K2 and K3 = K1 (Less Security) + KeyLength = 192 Keying option 3: K1 != K2 != K3 (Strongest) + + If TdesContext is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeyLength is not valid, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] TdesContext Pointer to TDES context being initialized. + @param[in] Key Pointer to the user-supplied TDES key. + @param[in] KeyLength Length of TDES key in bits. + + @retval TRUE TDES context initialization succeeded. + @retval FALSE TDES context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesInit ( + OUT VOID *TdesContext, + IN CONST UINT8 *Key, + IN UINTN KeyLength + ); + +/** + Performs TDES encryption on a data buffer of the specified size in ECB mode. + + This function performs TDES encryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval TRUE TDES encryption succeeded. + @retval FALSE TDES encryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesEcbEncrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ); + +/** + Performs TDES decryption on a data buffer of the specified size in ECB mode. + + This function performs TDES decryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the TDES decryption output. + + @retval TRUE TDES decryption succeeded. + @retval FALSE TDES decryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesEcbDecrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ); + +/** + Performs TDES encryption on a data buffer of the specified size in CBC mode. + + This function performs TDES encryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (8 bytes). + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval TRUE TDES encryption succeeded. + @retval FALSE TDES encryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesCbcEncrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ); + +/** + Performs TDES decryption on a data buffer of the specified size in CBC mode. + + This function performs TDES decryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (8 bytes). + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval TRUE TDES decryption succeeded. + @retval FALSE TDES decryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesCbcDecrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ); + +/** + Retrieves the size, in bytes, of the context buffer required for AES operations. + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for AES operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +AesGetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory as AES context for subsequent use. + + This function initializes user-supplied memory pointed by AesContext as AES context. + In addition, it sets up all AES key materials for subsequent encryption and decryption + operations. + There are 3 options for key length, 128 bits, 192 bits, and 256 bits. + + If AesContext is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeyLength is not valid, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] AesContext Pointer to AES context being initialized. + @param[in] Key Pointer to the user-supplied AES key. + @param[in] KeyLength Length of AES key in bits. + + @retval TRUE AES context initialization succeeded. + @retval FALSE AES context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesInit ( + OUT VOID *AesContext, + IN CONST UINT8 *Key, + IN UINTN KeyLength + ); + +/** + Performs AES encryption on a data buffer of the specified size in ECB mode. + + This function performs AES encryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval TRUE AES encryption succeeded. + @retval FALSE AES encryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesEcbEncrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ); + +/** + Performs AES decryption on a data buffer of the specified size in ECB mode. + + This function performs AES decryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the AES decryption output. + + @retval TRUE AES decryption succeeded. + @retval FALSE AES decryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesEcbDecrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ); + +/** + Performs AES encryption on a data buffer of the specified size in CBC mode. + + This function performs AES encryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (16 bytes). + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval TRUE AES encryption succeeded. + @retval FALSE AES encryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesCbcEncrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ); + +/** + Performs AES decryption on a data buffer of the specified size in CBC mode. + + This function performs AES decryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (16 bytes). + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval TRUE AES decryption succeeded. + @retval FALSE AES decryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesCbcDecrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ); + +/** + Retrieves the size, in bytes, of the context buffer required for ARC4 operations. + + If this interface is not supported, then return zero. + + @return The size, in bytes, of the context buffer required for ARC4 operations. + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Arc4GetContextSize ( + VOID + ); + +/** + Initializes user-supplied memory as ARC4 context for subsequent use. + + This function initializes user-supplied memory pointed by Arc4Context as ARC4 context. + In addition, it sets up all ARC4 key materials for subsequent encryption and decryption + operations. + + If Arc4Context is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeySize does not in the range of [5, 256] bytes, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] Arc4Context Pointer to ARC4 context being initialized. + @param[in] Key Pointer to the user-supplied ARC4 key. + @param[in] KeySize Size of ARC4 key in bytes. + + @retval TRUE ARC4 context initialization succeeded. + @retval FALSE ARC4 context initialization failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Init ( + OUT VOID *Arc4Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ); + +/** + Performs ARC4 encryption on a data buffer of the specified size. + + This function performs ARC4 encryption on data buffer pointed by Input, of specified + size of InputSize. + Arc4Context should be already correctly initialized by Arc4Init(). Behavior with + invalid ARC4 context is undefined. + + If Arc4Context is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the ARC4 encryption output. + + @retval TRUE ARC4 encryption succeeded. + @retval FALSE ARC4 encryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Encrypt ( + IN OUT VOID *Arc4Context, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ); + +/** + Performs ARC4 decryption on a data buffer of the specified size. + + This function performs ARC4 decryption on data buffer pointed by Input, of specified + size of InputSize. + Arc4Context should be already correctly initialized by Arc4Init(). Behavior with + invalid ARC4 context is undefined. + + If Arc4Context is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the ARC4 decryption output. + + @retval TRUE ARC4 decryption succeeded. + @retval FALSE ARC4 decryption failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Decrypt ( + IN OUT VOID *Arc4Context, + IN UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ); + +/** + Resets the ARC4 context to the initial state. + + The function resets the ARC4 context to the state it had immediately after the + ARC4Init() function call. + Contrary to ARC4Init(), Arc4Reset() requires no secret key as input, but ARC4 context + should be already correctly initialized by ARC4Init(). + + If Arc4Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + + @retval TRUE ARC4 reset succeeded. + @retval FALSE ARC4 reset failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Reset ( + IN OUT VOID *Arc4Context + ); + +//===================================================================================== +// Asymmetric Cryptography Primitive +//===================================================================================== + +/** + Allocates and initializes one RSA context for subsequent use. + + @return Pointer to the RSA context that has been initialized. + If the allocations fails, RsaNew() returns NULL. + +**/ +VOID * +EFIAPI +RsaNew ( + VOID + ); + +/** + Release the specified RSA context. + + If RsaContext is NULL, then return FALSE. + + @param[in] RsaContext Pointer to the RSA context to be released. + +**/ +VOID +EFIAPI +RsaFree ( + IN VOID *RsaContext + ); + +/** + Sets the tag-designated key component into the established RSA context. + + This function sets the tag-designated RSA key component into the established + RSA context from the user-specified non-negative integer (octet string format + represented in RSA PKCS#1). + If BigNumber is NULL, then the specified key component in RSA context is cleared. + + If RsaContext is NULL, then return FALSE. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] KeyTag Tag of RSA key component being set. + @param[in] BigNumber Pointer to octet integer buffer. + If NULL, then the specified key component in RSA + context is cleared. + @param[in] BnSize Size of big number buffer in bytes. + If BigNumber is NULL, then it is ignored. + + @retval TRUE RSA key component was set successfully. + @retval FALSE Invalid RSA key component tag. + +**/ +BOOLEAN +EFIAPI +RsaSetKey ( + IN OUT VOID *RsaContext, + IN RSA_KEY_TAG KeyTag, + IN CONST UINT8 *BigNumber, + IN UINTN BnSize + ); + +/** + Gets the tag-designated RSA key component from the established RSA context. + + This function retrieves the tag-designated RSA key component from the + established RSA context as a non-negative integer (octet string format + represented in RSA PKCS#1). + If specified key component has not been set or has been cleared, then returned + BnSize is set to 0. + If the BigNumber buffer is too small to hold the contents of the key, FALSE + is returned and BnSize is set to the required buffer size to obtain the key. + + If RsaContext is NULL, then return FALSE. + If BnSize is NULL, then return FALSE. + If BnSize is large enough but BigNumber is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] KeyTag Tag of RSA key component being set. + @param[out] BigNumber Pointer to octet integer buffer. + @param[in, out] BnSize On input, the size of big number buffer in bytes. + On output, the size of data returned in big number buffer in bytes. + + @retval TRUE RSA key component was retrieved successfully. + @retval FALSE Invalid RSA key component tag. + @retval FALSE BnSize is too small. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetKey ( + IN OUT VOID *RsaContext, + IN RSA_KEY_TAG KeyTag, + OUT UINT8 *BigNumber, + IN OUT UINTN *BnSize + ); + +/** + Generates RSA key components. + + This function generates RSA key components. It takes RSA public exponent E and + length in bits of RSA modulus N as input, and generates all key components. + If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used. + + Before this function can be invoked, pseudorandom number generator must be correctly + initialized by RandomSeed(). + + If RsaContext is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] ModulusLength Length of RSA modulus N in bits. + @param[in] PublicExponent Pointer to RSA public exponent. + @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes. + + @retval TRUE RSA key component was generated successfully. + @retval FALSE Invalid RSA key component tag. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGenerateKey ( + IN OUT VOID *RsaContext, + IN UINTN ModulusLength, + IN CONST UINT8 *PublicExponent, + IN UINTN PublicExponentSize + ); + +/** + Validates key components of RSA context. + NOTE: This function performs integrity checks on all the RSA key material, so + the RSA key structure must contain all the private key data. + + This function validates key components of RSA context in following aspects: + - Whether p is a prime + - Whether q is a prime + - Whether n = p * q + - Whether d*e = 1 mod lcm(p-1,q-1) + + If RsaContext is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] RsaContext Pointer to RSA context to check. + + @retval TRUE RSA key components are valid. + @retval FALSE RSA key components are not valid. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaCheckKey ( + IN VOID *RsaContext + ); + +/** + Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme. + + This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in + RSA PKCS#1. + If the Signature buffer is too small to hold the contents of signature, FALSE + is returned and SigSize is set to the required buffer size to obtain the signature. + + If RsaContext is NULL, then return FALSE. + If MessageHash is NULL, then return FALSE. + If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE. + If SigSize is large enough but Signature is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] MessageHash Pointer to octet message hash to be signed. + @param[in] HashSize Size of the message hash in bytes. + @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature. + @param[in, out] SigSize On input, the size of Signature buffer in bytes. + On output, the size of data returned in Signature buffer in bytes. + + @retval TRUE Signature successfully generated in PKCS1-v1_5. + @retval FALSE Signature generation failed. + @retval FALSE SigSize is too small. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaPkcs1Sign ( + IN VOID *RsaContext, + IN CONST UINT8 *MessageHash, + IN UINTN HashSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ); + +/** + Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in + RSA PKCS#1. + + If RsaContext is NULL, then return FALSE. + If MessageHash is NULL, then return FALSE. + If Signature is NULL, then return FALSE. + If HashSize is not equal to the size of MD5, SHA-1, SHA-256 digest, then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] MessageHash Pointer to octet message hash to be checked. + @param[in] HashSize Size of the message hash in bytes. + @param[in] Signature Pointer to RSA PKCS1-v1_5 signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in PKCS1-v1_5. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPkcs1Verify ( + IN VOID *RsaContext, + IN CONST UINT8 *MessageHash, + IN UINTN HashSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ); + +/** + Retrieve the RSA Private Key from the password-protected PEM key data. + + If PemData is NULL, then return FALSE. + If RsaContext is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] PemData Pointer to the PEM-encoded key data to be retrieved. + @param[in] PemSize Size of the PEM key data in bytes. + @param[in] Password NULL-terminated passphrase used for encrypted PEM key data. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA private key component. Use RsaFree() function to free the + resource. + + @retval TRUE RSA Private Key was retrieved successfully. + @retval FALSE Invalid PEM key data or incorrect password. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetPrivateKeyFromPem ( + IN CONST UINT8 *PemData, + IN UINTN PemSize, + IN CONST CHAR8 *Password, + OUT VOID **RsaContext + ); + +/** + Retrieve the RSA Public Key from one DER-encoded X509 certificate. + + If Cert is NULL, then return FALSE. + If RsaContext is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA public key component. Use RsaFree() function to free the + resource. + + @retval TRUE RSA Public Key was retrieved successfully. + @retval FALSE Fail to retrieve RSA public key from X509 certificate. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetPublicKeyFromX509 ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT VOID **RsaContext + ); + +/** + Retrieve the subject bytes from one X.509 certificate. + + If Cert is NULL, then return FALSE. + If SubjectSize is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CertSubject Pointer to the retrieved certificate subject bytes. + @param[in, out] SubjectSize The size in bytes of the CertSubject buffer on input, + and the size of buffer returned CertSubject on output. + + @retval TRUE The certificate subject retrieved successfully. + @retval FALSE Invalid certificate, or the SubjectSize is too small for the result. + The SubjectSize will be updated with the required size. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetSubjectName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *CertSubject, + IN OUT UINTN *SubjectSize + ); + +/** + Retrieve the common name (CN) string from one X.509 certificate. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CommonName Buffer to contain the retrieved certificate common + name string (UTF8). At most CommonNameSize bytes will be + written and the string will be null terminated. May be + NULL in order to determine the size buffer needed. + @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input, + and the size of buffer returned CommonName on output. + If CommonName is NULL then the amount of space needed + in buffer (including the final null) is returned. + + @retval RETURN_SUCCESS The certificate CommonName retrieved successfully. + @retval RETURN_INVALID_PARAMETER If Cert is NULL. + If CommonNameSize is NULL. + If CommonName is not NULL and *CommonNameSize is 0. + If Certificate is invalid. + @retval RETURN_NOT_FOUND If no CommonName entry exists. + @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size + (including the final null) is returned in the + CommonNameSize parameter. + @retval RETURN_UNSUPPORTED The operation is not supported. + +**/ +RETURN_STATUS +EFIAPI +X509GetCommonName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT CHAR8 *CommonName, OPTIONAL + IN OUT UINTN *CommonNameSize + ); + +/** + Verify one X509 certificate was issued by the trusted CA. + + If Cert is NULL, then return FALSE. + If CACert is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Cert Pointer to the DER-encoded X509 certificate to be verified. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[in] CACert Pointer to the DER-encoded trusted CA certificate. + @param[in] CACertSize Size of the CA Certificate in bytes. + + @retval TRUE The certificate was issued by the trusted CA. + @retval FALSE Invalid certificate or the certificate was not issued by the given + trusted CA. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509VerifyCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST UINT8 *CACert, + IN UINTN CACertSize + ); + +/** + Construct a X509 object from DER-encoded certificate data. + + If Cert is NULL, then return FALSE. + If SingleX509Cert is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Cert Pointer to the DER-encoded certificate data. + @param[in] CertSize The size of certificate data in bytes. + @param[out] SingleX509Cert The generated X509 object. + + @retval TRUE The X509 object generation succeeded. + @retval FALSE The operation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509ConstructCertificate ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **SingleX509Cert + ); + +/** + Construct a X509 stack object from a list of DER-encoded certificate data. + + If X509Stack is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object. + On output, pointer to the X509 stack object with new + inserted X509 certificate. + @param ... A list of DER-encoded single certificate data followed + by certificate size. A NULL terminates the list. The + pairs are the arguments to X509ConstructCertificate(). + + @retval TRUE The X509 stack construction succeeded. + @retval FALSE The construction operation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509ConstructCertificateStack ( + IN OUT UINT8 **X509Stack, + ... + ); + +/** + Release the specified X509 object. + + If the interface is not supported, then ASSERT(). + + @param[in] X509Cert Pointer to the X509 object to be released. + +**/ +VOID +EFIAPI +X509Free ( + IN VOID *X509Cert + ); + +/** + Release the specified X509 stack object. + + If the interface is not supported, then ASSERT(). + + @param[in] X509Stack Pointer to the X509 stack object to be released. + +**/ +VOID +EFIAPI +X509StackFree ( + IN VOID *X509Stack + ); + +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + If Cert is NULL, then return FALSE. + If TBSCert is NULL, then return FALSE. + If TBSCertSize is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @retval TRUE The TBSCertificate was retrieved successfully. + @retval FALSE Invalid X.509 certificate. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ); + +/** + Derives a key from a password using a salt and iteration count, based on PKCS#5 v2.0 + password based encryption key derivation function PBKDF2, as specified in RFC 2898. + + If Password or Salt or OutKey is NULL, then return FALSE. + If the hash algorithm could not be determined, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] PasswordLength Length of input password in bytes. + @param[in] Password Pointer to the array for the password. + @param[in] SaltLength Size of the Salt in bytes. + @param[in] Salt Pointer to the Salt. + @param[in] IterationCount Number of iterations to perform. Its value should be + greater than or equal to 1. + @param[in] DigestSize Size of the message digest to be used (eg. SHA256_DIGEST_SIZE). + NOTE: DigestSize will be used to determine the hash algorithm. + Only SHA1_DIGEST_SIZE or SHA256_DIGEST_SIZE is supported. + @param[in] KeyLength Size of the derived key buffer in bytes. + @param[out] OutKey Pointer to the output derived key buffer. + + @retval TRUE A key was derived successfully. + @retval FALSE One of the pointers was NULL or one of the sizes was too large. + @retval FALSE The hash algorithm could not be determined from the digest size. + @retval FALSE The key derivation operation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs5HashPassword ( + IN UINTN PasswordLength, + IN CONST CHAR8 *Password, + IN UINTN SaltLength, + IN CONST UINT8 *Salt, + IN UINTN IterationCount, + IN UINTN DigestSize, + IN UINTN KeyLength, + OUT UINT8 *OutKey + ); + +/** + The 3rd parameter of Pkcs7GetSigners will return all embedded + X.509 certificate in one given PKCS7 signature. The format is: + // + // UINT8 CertNumber; + // UINT32 Cert1Length; + // UINT8 Cert1[]; + // UINT32 Cert2Length; + // UINT8 Cert2[]; + // ... + // UINT32 CertnLength; + // UINT8 Certn[]; + // + + The two following C-structure are used for parsing CertStack more clearly. +**/ +#pragma pack(1) + +typedef struct { + UINT32 CertDataLength; // The length in bytes of X.509 certificate. + UINT8 CertDataBuffer[0]; // The X.509 certificate content (DER). +} EFI_CERT_DATA; + +typedef struct { + UINT8 CertNumber; // Number of X.509 certificate. + //EFI_CERT_DATA CertArray[]; // An array of X.509 certificate. +} EFI_CERT_STACK; + +#pragma pack() + +/** + Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then + return FALSE. If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data. + It's caller's responsibility to free the buffer with + Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] StackLength Length of signer's certificates in bytes. + @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates. + It's caller's responsibility to free the buffer with + Pkcs7FreeSigners(). + @param[out] CertLength Length of the trusted certificate in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSigners ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **CertStack, + OUT UINTN *StackLength, + OUT UINT8 **TrustedCert, + OUT UINTN *CertLength + ); + +/** + Wrap function to use free() to free allocated memory for certificates. + + If this interface is not supported, then ASSERT(). + + @param[in] Certs Pointer to the certificates to be freed. + +**/ +VOID +EFIAPI +Pkcs7FreeSigners ( + IN UINT8 *Certs + ); + +/** + Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard", and outputs two certificate lists chained and + unchained to the signer's certificates. + The input signed data could be wrapped in a ContentInfo structure. + + @param[in] P7Data Pointer to the PKCS#7 message. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] SignerChainCerts Pointer to the certificates list chained to signer's + certificate. It's caller's responsibility to free the buffer + with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] ChainLength Length of the chained certificates list buffer in bytes. + @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's + responsibility to free the buffer with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] UnchainLength Length of the unchained certificates list buffer in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetCertificatesList ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **SignerChainCerts, + OUT UINTN *ChainLength, + OUT UINT8 **UnchainCerts, + OUT UINTN *UnchainLength + ); + +/** + Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message + Syntax Standard, version 1.5". This interface is only intended to be used for + application to perform PKCS#7 functionality validation. + + If this interface is not supported, then return FALSE. + + @param[in] PrivateKey Pointer to the PEM-formatted private key data for + data signing. + @param[in] PrivateKeySize Size of the PEM private key data in bytes. + @param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM + key data. + @param[in] InData Pointer to the content to be signed. + @param[in] InDataSize Size of InData in bytes. + @param[in] SignCert Pointer to signer's DER-encoded certificate to sign with. + @param[in] OtherCerts Pointer to an optional additional set of certificates to + include in the PKCS#7 signedData (e.g. any intermediate + CAs in the chain). + @param[out] SignedData Pointer to output PKCS#7 signedData. It's caller's + responsibility to free the buffer with FreePool(). + @param[out] SignedDataSize Size of SignedData in bytes. + + @retval TRUE PKCS#7 data signing succeeded. + @retval FALSE PKCS#7 data signing failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7Sign ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN CONST UINT8 *KeyPassword, + IN UINT8 *InData, + IN UINTN InDataSize, + IN UINT8 *SignCert, + IN UINT8 *OtherCerts OPTIONAL, + OUT UINT8 **SignedData, + OUT UINTN *SignedDataSize + ); + +/** + Verifies the validity of a PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, TrustedCert or InData is NULL, then return FALSE. + If P7Length, CertLength or DataLength overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertLength Length of the trusted certificate in bytes. + @param[in] InData Pointer to the content to be verified. + @param[in] DataLength Length of InData in bytes. + + @retval TRUE The specified PKCS#7 signed data is valid. + @retval FALSE Invalid PKCS#7 signed data. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7Verify ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + IN CONST UINT8 *TrustedCert, + IN UINTN CertLength, + IN CONST UINT8 *InData, + IN UINTN DataLength + ); + +/** + Extracts the attached content from a PKCS#7 signed data if existed. The input signed + data could be wrapped in a ContentInfo structure. + + If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow, + then return FALSE. If the P7Data is not correctly formatted, then return FALSE. + + Caution: This function may receive untrusted input. So this function will do + basic check for PKCS#7 data structure. + + @param[in] P7Data Pointer to the PKCS#7 signed data to process. + @param[in] P7Length Length of the PKCS#7 signed data in bytes. + @param[out] Content Pointer to the extracted content from the PKCS#7 signedData. + It's caller's responsibility to free the buffer with FreePool(). + @param[out] ContentSize The size of the extracted content in bytes. + + @retval TRUE The P7Data was correctly formatted for processing. + @retval FALSE The P7Data was not correctly formatted for processing. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetAttachedContent ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT VOID **Content, + OUT UINTN *ContentSize + ); + +/** + Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows + Authenticode Portable Executable Signature Format". + + If AuthData is NULL, then return FALSE. + If ImageHash is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[in] ImageHash Pointer to the original image file hash value. The procedure + for calculating the image hash value is described in Authenticode + specification. + @param[in] HashSize Size of Image hash value in bytes. + + @retval TRUE The specified Authenticode Signature is valid. + @retval FALSE Invalid Authenticode Signature. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AuthenticodeVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN CONST UINT8 *ImageHash, + IN UINTN HashSize + ); + +/** + Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode + signature. + + If AuthData is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which + is used for TSA certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[out] SigningTime Return the time of timestamp generation time if the timestamp + signature is valid. + + @retval TRUE The specified Authenticode includes a valid RFC3161 Timestamp CounterSignature. + @retval FALSE No valid RFC3161 Timestamp CounterSignature in the specified Authenticode data. + +**/ +BOOLEAN +EFIAPI +ImageTimestampVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TsaCert, + IN UINTN CertSize, + OUT EFI_TIME *SigningTime + ); + +//===================================================================================== +// DH Key Exchange Primitive +//===================================================================================== + +/** + Allocates and Initializes one Diffie-Hellman Context for subsequent use. + + @return Pointer to the Diffie-Hellman Context that has been initialized. + If the allocations fails, DhNew() returns NULL. + If the interface is not supported, DhNew() returns NULL. + +**/ +VOID * +EFIAPI +DhNew ( + VOID + ); + +/** + Release the specified DH context. + + If the interface is not supported, then ASSERT(). + + @param[in] DhContext Pointer to the DH context to be released. + +**/ +VOID +EFIAPI +DhFree ( + IN VOID *DhContext + ); + +/** + Generates DH parameter. + + Given generator g, and length of prime number p in bits, this function generates p, + and sets DH context according to value of g and p. + + Before this function can be invoked, pseudorandom number generator must be correctly + initialized by RandomSeed(). + + If DhContext is NULL, then return FALSE. + If Prime is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] Generator Value of generator. + @param[in] PrimeLength Length in bits of prime to be generated. + @param[out] Prime Pointer to the buffer to receive the generated prime number. + + @retval TRUE DH parameter generation succeeded. + @retval FALSE Value of Generator is not supported. + @retval FALSE PRNG fails to generate random prime number with PrimeLength. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhGenerateParameter ( + IN OUT VOID *DhContext, + IN UINTN Generator, + IN UINTN PrimeLength, + OUT UINT8 *Prime + ); + +/** + Sets generator and prime parameters for DH. + + Given generator g, and prime number p, this function and sets DH + context accordingly. + + If DhContext is NULL, then return FALSE. + If Prime is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] Generator Value of generator. + @param[in] PrimeLength Length in bits of prime to be generated. + @param[in] Prime Pointer to the prime number. + + @retval TRUE DH parameter setting succeeded. + @retval FALSE Value of Generator is not supported. + @retval FALSE Value of Generator is not suitable for the Prime. + @retval FALSE Value of Prime is not a prime number. + @retval FALSE Value of Prime is not a safe prime number. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhSetParameter ( + IN OUT VOID *DhContext, + IN UINTN Generator, + IN UINTN PrimeLength, + IN CONST UINT8 *Prime + ); + +/** + Generates DH public key. + + This function generates random secret exponent, and computes the public key, which is + returned via parameter PublicKey and PublicKeySize. DH context is updated accordingly. + If the PublicKey buffer is too small to hold the public key, FALSE is returned and + PublicKeySize is set to the required buffer size to obtain the public key. + + If DhContext is NULL, then return FALSE. + If PublicKeySize is NULL, then return FALSE. + If PublicKeySize is large enough but PublicKey is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[out] PublicKey Pointer to the buffer to receive generated public key. + @param[in, out] PublicKeySize On input, the size of PublicKey buffer in bytes. + On output, the size of data returned in PublicKey buffer in bytes. + + @retval TRUE DH public key generation succeeded. + @retval FALSE DH public key generation failed. + @retval FALSE PublicKeySize is not large enough. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhGenerateKey ( + IN OUT VOID *DhContext, + OUT UINT8 *PublicKey, + IN OUT UINTN *PublicKeySize + ); + +/** + Computes exchanged common key. + + Given peer's public key, this function computes the exchanged common key, based on its own + context including value of prime modulus and random secret exponent. + + If DhContext is NULL, then return FALSE. + If PeerPublicKey is NULL, then return FALSE. + If KeySize is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeySize is not large enough, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] PeerPublicKey Pointer to the peer's public key. + @param[in] PeerPublicKeySize Size of peer's public key in bytes. + @param[out] Key Pointer to the buffer to receive generated key. + @param[in, out] KeySize On input, the size of Key buffer in bytes. + On output, the size of data returned in Key buffer in bytes. + + @retval TRUE DH exchanged key generation succeeded. + @retval FALSE DH exchanged key generation failed. + @retval FALSE KeySize is not large enough. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhComputeKey ( + IN OUT VOID *DhContext, + IN CONST UINT8 *PeerPublicKey, + IN UINTN PeerPublicKeySize, + OUT UINT8 *Key, + IN OUT UINTN *KeySize + ); + +//===================================================================================== +// Pseudo-Random Generation Primitive +//===================================================================================== + +/** + Sets up the seed value for the pseudorandom number generator. + + This function sets up the seed value for the pseudorandom number generator. + If Seed is not NULL, then the seed passed in is used. + If Seed is NULL, then default seed is used. + If this interface is not supported, then return FALSE. + + @param[in] Seed Pointer to seed value. + If NULL, default seed is used. + @param[in] SeedSize Size of seed value. + If Seed is NULL, this parameter is ignored. + + @retval TRUE Pseudorandom number generator has enough entropy for random generation. + @retval FALSE Pseudorandom number generator does not have enough entropy for random generation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RandomSeed ( + IN CONST UINT8 *Seed OPTIONAL, + IN UINTN SeedSize + ); + +/** + Generates a pseudorandom byte stream of the specified size. + + If Output is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[out] Output Pointer to buffer to receive random value. + @param[in] Size Size of random bytes to generate. + + @retval TRUE Pseudorandom byte stream generated successfully. + @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RandomBytes ( + OUT UINT8 *Output, + IN UINTN Size + ); + +#endif // __BASE_CRYPT_LIB_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/TlsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/TlsLib.h new file mode 100644 index 0000000..59be651 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Include/Library/TlsLib.h @@ -0,0 +1,800 @@ +/** @file + Defines TLS Library APIs. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TLS_LIB_H__ +#define __TLS_LIB_H__ + +/** + Initializes the OpenSSL library. + + This function registers ciphers and digests used directly and indirectly + by SSL/TLS, and initializes the readable error messages. + This function must be called before any other action takes places. + + @retval TRUE The OpenSSL library has been initialized. + @retval FALSE Failed to initialize the OpenSSL library. + +**/ +BOOLEAN +EFIAPI +TlsInitialize ( + VOID + ); + +/** + Free an allocated SSL_CTX object. + + @param[in] TlsCtx Pointer to the SSL_CTX object to be released. + +**/ +VOID +EFIAPI +TlsCtxFree ( + IN VOID *TlsCtx + ); + +/** + Creates a new SSL_CTX object as framework to establish TLS/SSL enabled + connections. + + @param[in] MajorVer Major Version of TLS/SSL Protocol. + @param[in] MinorVer Minor Version of TLS/SSL Protocol. + + @return Pointer to an allocated SSL_CTX object. + If the creation failed, TlsCtxNew() returns NULL. + +**/ +VOID * +EFIAPI +TlsCtxNew ( + IN UINT8 MajorVer, + IN UINT8 MinorVer + ); + +/** + Free an allocated TLS object. + + This function removes the TLS object pointed to by Tls and frees up the + allocated memory. If Tls is NULL, nothing is done. + + @param[in] Tls Pointer to the TLS object to be freed. + +**/ +VOID +EFIAPI +TlsFree ( + IN VOID *Tls + ); + +/** + Create a new TLS object for a connection. + + This function creates a new TLS object for a connection. The new object + inherits the setting of the underlying context TlsCtx: connection method, + options, verification setting. + + @param[in] TlsCtx Pointer to the SSL_CTX object. + + @return Pointer to an allocated SSL object. + If the creation failed, TlsNew() returns NULL. + +**/ +VOID * +EFIAPI +TlsNew ( + IN VOID *TlsCtx + ); + +/** + Checks if the TLS handshake was done. + + This function will check if the specified TLS handshake was done. + + @param[in] Tls Pointer to the TLS object for handshake state checking. + + @retval TRUE The TLS handshake was done. + @retval FALSE The TLS handshake was not done. + +**/ +BOOLEAN +EFIAPI +TlsInHandshake ( + IN VOID *Tls + ); + +/** + Perform a TLS/SSL handshake. + + This function will perform a TLS/SSL handshake. + + @param[in] Tls Pointer to the TLS object for handshake operation. + @param[in] BufferIn Pointer to the most recently received TLS Handshake packet. + @param[in] BufferInSize Packet size in bytes for the most recently received TLS + Handshake packet. + @param[out] BufferOut Pointer to the buffer to hold the built packet. + @param[in, out] BufferOutSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Tls is NULL. + BufferIn is NULL but BufferInSize is NOT 0. + BufferInSize is 0 but BufferIn is NOT NULL. + BufferOutSize is NULL. + BufferOut is NULL if *BufferOutSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferOutSize is too small to hold the response packet. + @retval EFI_ABORTED Something wrong during handshake. + +**/ +EFI_STATUS +EFIAPI +TlsDoHandshake ( + IN VOID *Tls, + IN UINT8 *BufferIn, OPTIONAL + IN UINTN BufferInSize, OPTIONAL + OUT UINT8 *BufferOut, OPTIONAL + IN OUT UINTN *BufferOutSize + ); + +/** + Handle Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero, + TLS session has errors and the response packet needs to be Alert message based on error type. + + @param[in] Tls Pointer to the TLS object for state checking. + @param[in] BufferIn Pointer to the most recently received TLS Alert packet. + @param[in] BufferInSize Packet size in bytes for the most recently received TLS + Alert packet. + @param[out] BufferOut Pointer to the buffer to hold the built packet. + @param[in, out] BufferOutSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Tls is NULL. + BufferIn is NULL but BufferInSize is NOT 0. + BufferInSize is 0 but BufferIn is NOT NULL. + BufferOutSize is NULL. + BufferOut is NULL if *BufferOutSize is not zero. + @retval EFI_ABORTED An error occurred. + @retval EFI_BUFFER_TOO_SMALL BufferOutSize is too small to hold the response packet. + +**/ +EFI_STATUS +EFIAPI +TlsHandleAlert ( + IN VOID *Tls, + IN UINT8 *BufferIn, OPTIONAL + IN UINTN BufferInSize, OPTIONAL + OUT UINT8 *BufferOut, OPTIONAL + IN OUT UINTN *BufferOutSize + ); + +/** + Build the CloseNotify packet. + + @param[in] Tls Pointer to the TLS object for state checking. + @param[in, out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Tls is NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + +**/ +EFI_STATUS +EFIAPI +TlsCloseNotify ( + IN VOID *Tls, + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize + ); + +/** + Attempts to read bytes from one TLS object and places the data in Buffer. + + This function will attempt to read BufferSize bytes from the TLS object + and places the data in Buffer. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] Buffer Pointer to the buffer to store the data. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The amount of data successfully read from the TLS object. + @retval <=0 No data was successfully read. + +**/ +INTN +EFIAPI +TlsCtrlTrafficOut ( + IN VOID *Tls, + IN OUT VOID *Buffer, + IN UINTN BufferSize + ); + +/** + Attempts to write data from the buffer to TLS object. + + This function will attempt to write BufferSize bytes data from the Buffer + to the TLS object. + + @param[in] Tls Pointer to the TLS object. + @param[in] Buffer Pointer to the data buffer. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The amount of data successfully written to the TLS object. + @retval <=0 No data was successfully written. + +**/ +INTN +EFIAPI +TlsCtrlTrafficIn ( + IN VOID *Tls, + IN VOID *Buffer, + IN UINTN BufferSize + ); + +/** + Attempts to read bytes from the specified TLS connection into the buffer. + + This function tries to read BufferSize bytes data from the specified TLS + connection into the Buffer. + + @param[in] Tls Pointer to the TLS connection for data reading. + @param[in,out] Buffer Pointer to the data buffer. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The read operation was successful, and return value is the + number of bytes actually read from the TLS connection. + @retval <=0 The read operation was not successful. + +**/ +INTN +EFIAPI +TlsRead ( + IN VOID *Tls, + IN OUT VOID *Buffer, + IN UINTN BufferSize + ); + +/** + Attempts to write data to a TLS connection. + + This function tries to write BufferSize bytes data from the Buffer into the + specified TLS connection. + + @param[in] Tls Pointer to the TLS connection for data writing. + @param[in] Buffer Pointer to the data buffer. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The write operation was successful, and return value is the + number of bytes actually written to the TLS connection. + @retval <=0 The write operation was not successful. + +**/ +INTN +EFIAPI +TlsWrite ( + IN VOID *Tls, + IN VOID *Buffer, + IN UINTN BufferSize + ); + +/** + Set a new TLS/SSL method for a particular TLS object. + + This function sets a new TLS/SSL method for a particular TLS object. + + @param[in] Tls Pointer to a TLS object. + @param[in] MajorVer Major Version of TLS/SSL Protocol. + @param[in] MinorVer Minor Version of TLS/SSL Protocol. + + @retval EFI_SUCCESS The TLS/SSL method was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported TLS/SSL method. + +**/ +EFI_STATUS +EFIAPI +TlsSetVersion ( + IN VOID *Tls, + IN UINT8 MajorVer, + IN UINT8 MinorVer + ); + +/** + Set TLS object to work in client or server mode. + + This function prepares a TLS object to work in client or server mode. + + @param[in] Tls Pointer to a TLS object. + @param[in] IsServer Work in server mode. + + @retval EFI_SUCCESS The TLS/SSL work mode was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode. + +**/ +EFI_STATUS +EFIAPI +TlsSetConnectionEnd ( + IN VOID *Tls, + IN BOOLEAN IsServer + ); + +/** + Set the ciphers list to be used by the TLS object. + + This function sets the ciphers for use by a specified TLS object. + + @param[in] Tls Pointer to a TLS object. + @param[in] CipherId Array of UINT16 cipher identifiers. Each UINT16 + cipher identifier comes from the TLS Cipher Suite + Registry of the IANA, interpreting Byte1 and Byte2 + in network (big endian) byte order. + @param[in] CipherNum The number of cipher in the list. + + @retval EFI_SUCCESS The ciphers list was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED No supported TLS cipher was found in CipherId. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + +**/ +EFI_STATUS +EFIAPI +TlsSetCipherList ( + IN VOID *Tls, + IN UINT16 *CipherId, + IN UINTN CipherNum + ); + +/** + Set the compression method for TLS/SSL operations. + + This function handles TLS/SSL integrated compression methods. + + @param[in] CompMethod The compression method ID. + + @retval EFI_SUCCESS The compression method for the communication was + set successfully. + @retval EFI_UNSUPPORTED Unsupported compression method. + +**/ +EFI_STATUS +EFIAPI +TlsSetCompressionMethod ( + IN UINT8 CompMethod + ); + +/** + Set peer certificate verification mode for the TLS connection. + + This function sets the verification mode flags for the TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in] VerifyMode A set of logically or'ed verification mode flags. + +**/ +VOID +EFIAPI +TlsSetVerify ( + IN VOID *Tls, + IN UINT32 VerifyMode + ); + +/** + Sets a TLS/SSL session ID to be used during TLS/SSL connect. + + This function sets a session ID to be used when the TLS/SSL connection is + to be established. + + @param[in] Tls Pointer to the TLS object. + @param[in] SessionId Session ID data used for session resumption. + @param[in] SessionIdLen Length of Session ID in bytes. + + @retval EFI_SUCCESS Session ID was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED No available session for ID setting. + +**/ +EFI_STATUS +EFIAPI +TlsSetSessionId ( + IN VOID *Tls, + IN UINT8 *SessionId, + IN UINT16 SessionIdLen + ); + +/** + Adds the CA to the cert store when requesting Server or Client authentication. + + This function adds the CA certificate to the list of CAs when requesting + Server or Client authentication for the chosen TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in] Data Pointer to the data buffer of a DER-encoded binary + X.509 certificate or PEM-encoded X.509 certificate. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated. + @retval EFI_ABORTED Invalid X.509 certificate. + +**/ +EFI_STATUS +EFIAPI +TlsSetCaCertificate ( + IN VOID *Tls, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Loads the local public certificate into the specified TLS object. + + This function loads the X.509 certificate into the specified TLS object + for TLS negotiation. + + @param[in] Tls Pointer to the TLS object. + @param[in] Data Pointer to the data buffer of a DER-encoded binary + X.509 certificate or PEM-encoded X.509 certificate. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated. + @retval EFI_ABORTED Invalid X.509 certificate. + +**/ +EFI_STATUS +EFIAPI +TlsSetHostPublicCert ( + IN VOID *Tls, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Adds the local private key to the specified TLS object. + + This function adds the local private key (PEM-encoded RSA or PKCS#8 private + key) into the specified TLS object for TLS negotiation. + + @param[in] Tls Pointer to the TLS object. + @param[in] Data Pointer to the data buffer of a PEM-encoded RSA + or PKCS#8 private key. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_ABORTED Invalid private key data. + +**/ +EFI_STATUS +EFIAPI +TlsSetHostPrivateKey ( + IN VOID *Tls, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Adds the CA-supplied certificate revocation list for certificate validation. + + This function adds the CA-supplied certificate revocation list data for + certificate validity checking. + + @param[in] Data Pointer to the data buffer of a DER-encoded CRL data. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_ABORTED Invalid CRL data. + +**/ +EFI_STATUS +EFIAPI +TlsSetCertRevocationList ( + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Gets the protocol version used by the specified TLS connection. + + This function returns the protocol version used by the specified TLS + connection. + + If Tls is NULL, then ASSERT(). + + @param[in] Tls Pointer to the TLS object. + + @return The protocol version of the specified TLS connection. + +**/ +UINT16 +EFIAPI +TlsGetVersion ( + IN VOID *Tls + ); + +/** + Gets the connection end of the specified TLS connection. + + This function returns the connection end (as client or as server) used by + the specified TLS connection. + + If Tls is NULL, then ASSERT(). + + @param[in] Tls Pointer to the TLS object. + + @return The connection end used by the specified TLS connection. + +**/ +UINT8 +EFIAPI +TlsGetConnectionEnd ( + IN VOID *Tls + ); + +/** + Gets the cipher suite used by the specified TLS connection. + + This function returns current cipher suite used by the specified + TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] CipherId The cipher suite used by the TLS object. + + @retval EFI_SUCCESS The cipher suite was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported cipher suite. + +**/ +EFI_STATUS +EFIAPI +TlsGetCurrentCipher ( + IN VOID *Tls, + IN OUT UINT16 *CipherId + ); + +/** + Gets the compression methods used by the specified TLS connection. + + This function returns current integrated compression methods used by + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] CompressionId The current compression method used by + the TLS object. + + @retval EFI_SUCCESS The compression method was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_ABORTED Invalid Compression method. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +EFIAPI +TlsGetCurrentCompressionId ( + IN VOID *Tls, + IN OUT UINT8 *CompressionId + ); + +/** + Gets the verification mode currently set in the TLS connection. + + This function returns the peer verification mode currently set in the + specified TLS connection. + + If Tls is NULL, then ASSERT(). + + @param[in] Tls Pointer to the TLS object. + + @return The verification mode set in the specified TLS connection. + +**/ +UINT32 +EFIAPI +TlsGetVerify ( + IN VOID *Tls + ); + +/** + Gets the session ID used by the specified TLS connection. + + This function returns the TLS/SSL session ID currently used by the + specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] SessionId Buffer to contain the returned session ID. + @param[in,out] SessionIdLen The length of Session ID in bytes. + + @retval EFI_SUCCESS The Session ID was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Invalid TLS/SSL session. + +**/ +EFI_STATUS +EFIAPI +TlsGetSessionId ( + IN VOID *Tls, + IN OUT UINT8 *SessionId, + IN OUT UINT16 *SessionIdLen + ); + +/** + Gets the client random data used in the specified TLS connection. + + This function returns the TLS/SSL client random data currently used in + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] ClientRandom Buffer to contain the returned client + random data (32 bytes). + +**/ +VOID +EFIAPI +TlsGetClientRandom ( + IN VOID *Tls, + IN OUT UINT8 *ClientRandom + ); + +/** + Gets the server random data used in the specified TLS connection. + + This function returns the TLS/SSL server random data currently used in + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] ServerRandom Buffer to contain the returned server + random data (32 bytes). + +**/ +VOID +EFIAPI +TlsGetServerRandom ( + IN VOID *Tls, + IN OUT UINT8 *ServerRandom + ); + +/** + Gets the master key data used in the specified TLS connection. + + This function returns the TLS/SSL master key material currently used in + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] KeyMaterial Buffer to contain the returned key material. + + @retval EFI_SUCCESS Key material was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Invalid TLS/SSL session. + +**/ +EFI_STATUS +EFIAPI +TlsGetKeyMaterial ( + IN VOID *Tls, + IN OUT UINT8 *KeyMaterial + ); + +/** + Gets the CA Certificate from the cert store. + + This function returns the CA certificate for the chosen + TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[out] Data Pointer to the data buffer to receive the CA + certificate data sent to the client. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetCaCertificate ( + IN VOID *Tls, + OUT VOID *Data, + IN OUT UINTN *DataSize + ); + +/** + Gets the local public Certificate set in the specified TLS object. + + This function returns the local public certificate which was currently set + in the specified TLS object. + + @param[in] Tls Pointer to the TLS object. + @param[out] Data Pointer to the data buffer to receive the local + public certificate. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_NOT_FOUND The certificate is not found. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetHostPublicCert ( + IN VOID *Tls, + OUT VOID *Data, + IN OUT UINTN *DataSize + ); + +/** + Gets the local private key set in the specified TLS object. + + This function returns the local private key data which was currently set + in the specified TLS object. + + @param[in] Tls Pointer to the TLS object. + @param[out] Data Pointer to the data buffer to receive the local + private key data. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetHostPrivateKey ( + IN VOID *Tls, + OUT VOID *Data, + IN OUT UINTN *DataSize + ); + +/** + Gets the CA-supplied certificate revocation list data set in the specified + TLS object. + + This function returns the CA-supplied certificate revocation list data which + was currently set in the specified TLS object. + + @param[out] Data Pointer to the data buffer to receive the CRL data. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetCertRevocationList ( + OUT VOID *Data, + IN OUT UINTN *DataSize + ); + +#endif // __TLS_LIB_H__ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf new file mode 100644 index 0000000..45b94d0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf @@ -0,0 +1,102 @@ +## @file +# Cryptographic Library Instance for DXE_DRIVER. +# +# Caution: This module requires additional review when modified. +# This library will have external input - signature. +# This external input must be validated carefully to avoid security issues such as +# buffer overflow or integer overflow. +# +# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCryptLib + MODULE_UNI_FILE = BaseCryptLib.uni + FILE_GUID = be3bb803-91b6-4da0-bd91-a8b21c18ca5d + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseCryptLib|DXE_DRIVER DXE_CORE UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + InternalCryptLib.h + Hash/CryptMd4.c + Hash/CryptMd5.c + Hash/CryptSha1.c + Hash/CryptSha256.c + Hash/CryptSha512.c + Hmac/CryptHmacMd5.c + Hmac/CryptHmacSha1.c + Hmac/CryptHmacSha256.c + Cipher/CryptAes.c + Cipher/CryptTdes.c + Cipher/CryptArc4.c + Pk/CryptRsaBasic.c + Pk/CryptRsaExt.c + Pk/CryptPkcs5Pbkdf2.c + Pk/CryptPkcs7Sign.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + Pk/CryptDh.c + Pk/CryptX509.c + Pk/CryptAuthenticode.c + Pk/CryptTs.c + Pem/CryptPem.c + + SysCall/CrtWrapper.c + SysCall/TimerWrapper.c + SysCall/BaseMemAllocation.c + +[Sources.Ia32] + Rand/CryptRandTsc.c + +[Sources.X64] + Rand/CryptRandTsc.c + +[Sources.ARM] + Rand/CryptRand.c + +[Sources.AARCH64] + Rand/CryptRand.c + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiRuntimeServicesTableLib + DebugLib + OpensslLib + IntrinsicLib + PrintLib + +# +# Remove these [BuildOptions] after this library is cleaned up +# +[BuildOptions] + # + # suppress the following warnings so we do not break the build with warnings-as-errors: + # C4090: 'function' : different 'const' qualifiers + # + MSFT:*_*_*_CC_FLAGS = /wd4090 + + # -JCryptoPkg/Include : To disable the use of the system includes provided by RVCT + # --diag_remark=1 : Reduce severity of "#1-D: last line of file ends without a newline" + RVCT:*_*_ARM_CC_FLAGS = -JCryptoPkg/Include --diag_remark=1 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.uni new file mode 100644 index 0000000..33819b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.uni @@ -0,0 +1,25 @@ +// /** @file +// Cryptographic Library Instance for DXE_DRIVER. +// +// Caution: This module requires additional review when modified. +// This library will have external input - signature. +// This external input must be validated carefully to avoid security issues such as +// buffer overflow or integer overflow. +// +// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Cryptographic Library Instance for DXE_DRIVER" + +#string STR_MODULE_DESCRIPTION #language en-US "Caution: This module requires additional review when modified. This library will have external input - signature. This external input must be validated carefully to avoid security issues such as buffer overflow or integer overflow." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAes.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAes.c new file mode 100644 index 0000000..88eca0a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAes.c @@ -0,0 +1,323 @@ +/** @file + AES Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for AES operations. + + @return The size, in bytes, of the context buffer required for AES operations. + +**/ +UINTN +EFIAPI +AesGetContextSize ( + VOID + ) +{ + // + // AES uses different key contexts for encryption and decryption, so here memory + // for 2 copies of AES_KEY is allocated. + // + return (UINTN) (2 * sizeof (AES_KEY)); +} + +/** + Initializes user-supplied memory as AES context for subsequent use. + + This function initializes user-supplied memory pointed by AesContext as AES context. + In addition, it sets up all AES key materials for subsequent encryption and decryption + operations. + There are 3 options for key length, 128 bits, 192 bits, and 256 bits. + + If AesContext is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeyLength is not valid, then return FALSE. + + @param[out] AesContext Pointer to AES context being initialized. + @param[in] Key Pointer to the user-supplied AES key. + @param[in] KeyLength Length of AES key in bits. + + @retval TRUE AES context initialization succeeded. + @retval FALSE AES context initialization failed. + +**/ +BOOLEAN +EFIAPI +AesInit ( + OUT VOID *AesContext, + IN CONST UINT8 *Key, + IN UINTN KeyLength + ) +{ + AES_KEY *AesKey; + + // + // Check input parameters. + // + if (AesContext == NULL || Key == NULL || (KeyLength != 128 && KeyLength != 192 && KeyLength != 256)) { + return FALSE; + } + + // + // Initialize AES encryption & decryption key schedule. + // + AesKey = (AES_KEY *) AesContext; + if (AES_set_encrypt_key (Key, (UINT32) KeyLength, AesKey) != 0) { + return FALSE; + } + if (AES_set_decrypt_key (Key, (UINT32) KeyLength, AesKey + 1) != 0) { + return FALSE; + } + return TRUE; +} + +/** + Performs AES encryption on a data buffer of the specified size in ECB mode. + + This function performs AES encryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval TRUE AES encryption succeeded. + @retval FALSE AES encryption failed. + +**/ +BOOLEAN +EFIAPI +AesEcbEncrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + AES_KEY *AesKey; + + // + // Check input parameters. + // + if (AesContext == NULL || Input == NULL || (InputSize % AES_BLOCK_SIZE) != 0 || Output == NULL) { + return FALSE; + } + + AesKey = (AES_KEY *) AesContext; + + // + // Perform AES data encryption with ECB mode (block-by-block) + // + while (InputSize > 0) { + AES_ecb_encrypt (Input, Output, AesKey, AES_ENCRYPT); + Input += AES_BLOCK_SIZE; + Output += AES_BLOCK_SIZE; + InputSize -= AES_BLOCK_SIZE; + } + + return TRUE; +} + +/** + Performs AES decryption on a data buffer of the specified size in ECB mode. + + This function performs AES decryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the AES decryption output. + + @retval TRUE AES decryption succeeded. + @retval FALSE AES decryption failed. + +**/ +BOOLEAN +EFIAPI +AesEcbDecrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + AES_KEY *AesKey; + + // + // Check input parameters. + // + if (AesContext == NULL || Input == NULL || (InputSize % AES_BLOCK_SIZE) != 0 || Output == NULL) { + return FALSE; + } + + AesKey = (AES_KEY *) AesContext; + + // + // Perform AES data decryption with ECB mode (block-by-block) + // + while (InputSize > 0) { + AES_ecb_encrypt (Input, Output, AesKey + 1, AES_DECRYPT); + Input += AES_BLOCK_SIZE; + Output += AES_BLOCK_SIZE; + InputSize -= AES_BLOCK_SIZE; + } + + return TRUE; +} + +/** + Performs AES encryption on a data buffer of the specified size in CBC mode. + + This function performs AES encryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (16 bytes). + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval TRUE AES encryption succeeded. + @retval FALSE AES encryption failed. + +**/ +BOOLEAN +EFIAPI +AesCbcEncrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + AES_KEY *AesKey; + UINT8 IvecBuffer[AES_BLOCK_SIZE]; + + // + // Check input parameters. + // + if (AesContext == NULL || Input == NULL || (InputSize % AES_BLOCK_SIZE) != 0) { + return FALSE; + } + + if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) { + return FALSE; + } + + AesKey = (AES_KEY *) AesContext; + CopyMem (IvecBuffer, Ivec, AES_BLOCK_SIZE); + + // + // Perform AES data encryption with CBC mode + // + AES_cbc_encrypt (Input, Output, (UINT32) InputSize, AesKey, IvecBuffer, AES_ENCRYPT); + + return TRUE; +} + +/** + Performs AES decryption on a data buffer of the specified size in CBC mode. + + This function performs AES decryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (16 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (16 bytes). + AesContext should be already correctly initialized by AesInit(). Behavior with + invalid AES context is undefined. + + If AesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (16 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval TRUE AES decryption succeeded. + @retval FALSE AES decryption failed. + +**/ +BOOLEAN +EFIAPI +AesCbcDecrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + AES_KEY *AesKey; + UINT8 IvecBuffer[AES_BLOCK_SIZE]; + + // + // Check input parameters. + // + if (AesContext == NULL || Input == NULL || (InputSize % AES_BLOCK_SIZE) != 0) { + return FALSE; + } + + if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) { + return FALSE; + } + + AesKey = (AES_KEY *) AesContext; + CopyMem (IvecBuffer, Ivec, AES_BLOCK_SIZE); + + // + // Perform AES data decryption with CBC mode + // + AES_cbc_encrypt (Input, Output, (UINT32) InputSize, AesKey + 1, IvecBuffer, AES_DECRYPT); + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesNull.c new file mode 100644 index 0000000..66d014b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesNull.c @@ -0,0 +1,165 @@ +/** @file + AES Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for AES operations. + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +AesGetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Initializes user-supplied memory as AES context for subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] AesContext Pointer to AES context being initialized. + @param[in] Key Pointer to the user-supplied AES key. + @param[in] KeyLength Length of AES key in bits. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesInit ( + OUT VOID *AesContext, + IN CONST UINT8 *Key, + IN UINTN KeyLength + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs AES encryption on a data buffer of the specified size in ECB mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesEcbEncrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs AES decryption on a data buffer of the specified size in ECB mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the AES decryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesEcbDecrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs AES encryption on a data buffer of the specified size in CBC mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesCbcEncrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs AES decryption on a data buffer of the specified size in CBC mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] AesContext Pointer to the AES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the AES encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AesCbcDecrypt ( + IN VOID *AesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4.c new file mode 100644 index 0000000..cceede8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4.c @@ -0,0 +1,211 @@ +/** @file + ARC4 Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for ARC4 operations. + + @return The size, in bytes, of the context buffer required for ARC4 operations. + +**/ +UINTN +EFIAPI +Arc4GetContextSize ( + VOID + ) +{ + // + // Memory for 2 copies of RC4_KEY is allocated, one for working copy, and the other + // for backup copy. When Arc4Reset() is called, we can use the backup copy to restore + // the working copy to the initial state. + // + return (UINTN) (2 * sizeof (RC4_KEY)); +} + +/** + Initializes user-supplied memory as ARC4 context for subsequent use. + + This function initializes user-supplied memory pointed by Arc4Context as ARC4 context. + In addition, it sets up all ARC4 key materials for subsequent encryption and decryption + operations. + + If Arc4Context is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeySize does not in the range of [5, 256] bytes, then return FALSE. + + @param[out] Arc4Context Pointer to ARC4 context being initialized. + @param[in] Key Pointer to the user-supplied ARC4 key. + @param[in] KeySize Size of ARC4 key in bytes. + + @retval TRUE ARC4 context initialization succeeded. + @retval FALSE ARC4 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Arc4Init ( + OUT VOID *Arc4Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + RC4_KEY *Rc4Key; + + // + // Check input parameters. + // + if (Arc4Context == NULL || Key == NULL || (KeySize < 5 || KeySize > 256)) { + return FALSE; + } + + Rc4Key = (RC4_KEY *) Arc4Context; + + RC4_set_key (Rc4Key, (UINT32) KeySize, Key); + + CopyMem (Rc4Key + 1, Rc4Key, sizeof (RC4_KEY)); + + return TRUE; +} + +/** + Performs ARC4 encryption on a data buffer of the specified size. + + This function performs ARC4 encryption on data buffer pointed by Input, of specified + size of InputSize. + Arc4Context should be already correctly initialized by Arc4Init(). Behavior with + invalid ARC4 context is undefined. + + If Arc4Context is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If Output is NULL, then return FALSE. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the ARC4 encryption output. + + @retval TRUE ARC4 encryption succeeded. + @retval FALSE ARC4 encryption failed. + +**/ +BOOLEAN +EFIAPI +Arc4Encrypt ( + IN OUT VOID *Arc4Context, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + RC4_KEY *Rc4Key; + + // + // Check input parameters. + // + if (Arc4Context == NULL || Input == NULL || Output == NULL || InputSize > INT_MAX) { + return FALSE; + } + + Rc4Key = (RC4_KEY *) Arc4Context; + + RC4 (Rc4Key, (UINT32) InputSize, Input, Output); + + return TRUE; +} + +/** + Performs ARC4 decryption on a data buffer of the specified size. + + This function performs ARC4 decryption on data buffer pointed by Input, of specified + size of InputSize. + Arc4Context should be already correctly initialized by Arc4Init(). Behavior with + invalid ARC4 context is undefined. + + If Arc4Context is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If Output is NULL, then return FALSE. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the ARC4 decryption output. + + @retval TRUE ARC4 decryption succeeded. + @retval FALSE ARC4 decryption failed. + +**/ +BOOLEAN +EFIAPI +Arc4Decrypt ( + IN OUT VOID *Arc4Context, + IN UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + RC4_KEY *Rc4Key; + + // + // Check input parameters. + // + if (Arc4Context == NULL || Input == NULL || Output == NULL || InputSize > INT_MAX) { + return FALSE; + } + + Rc4Key = (RC4_KEY *) Arc4Context; + + RC4 (Rc4Key, (UINT32) InputSize, Input, Output); + + return TRUE; +} + +/** + Resets the ARC4 context to the initial state. + + The function resets the ARC4 context to the state it had immediately after the + ARC4Init() function call. + Contrary to ARC4Init(), Arc4Reset() requires no secret key as input, but ARC4 context + should be already correctly initialized by ARC4Init(). + + If Arc4Context is NULL, then return FALSE. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + + @retval TRUE ARC4 reset succeeded. + @retval FALSE ARC4 reset failed. + +**/ +BOOLEAN +EFIAPI +Arc4Reset ( + IN OUT VOID *Arc4Context + ) +{ + RC4_KEY *Rc4Key; + + // + // Check input parameters. + // + if (Arc4Context == NULL) { + return FALSE; + } + + Rc4Key = (RC4_KEY *) Arc4Context; + + CopyMem (Rc4Key, Rc4Key + 1, sizeof (RC4_KEY)); + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4Null.c new file mode 100644 index 0000000..6e100e2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptArc4Null.c @@ -0,0 +1,130 @@ +/** @file + ARC4 Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for ARC4 operations. + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + + +**/ +UINTN +EFIAPI +Arc4GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Initializes user-supplied memory as ARC4 context for subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] Arc4Context Pointer to ARC4 context being initialized. + @param[in] Key Pointer to the user-supplied ARC4 key. + @param[in] KeySize Size of ARC4 key in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Init ( + OUT VOID *Arc4Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs ARC4 encryption on a data buffer of the specified size. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the ARC4 encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Encrypt ( + IN OUT VOID *Arc4Context, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs ARC4 decryption on a data buffer of the specified size. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the ARC4 decryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Decrypt ( + IN OUT VOID *Arc4Context, + IN UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Resets the ARC4 context to the initial state. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Arc4Context Pointer to the ARC4 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Arc4Reset ( + IN OUT VOID *Arc4Context + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdes.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdes.c new file mode 100644 index 0000000..68c57d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdes.c @@ -0,0 +1,370 @@ +/** @file + TDES Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for TDES operations. + + @return The size, in bytes, of the context buffer required for TDES operations. + +**/ +UINTN +EFIAPI +TdesGetContextSize ( + VOID + ) +{ + // + // Memory for 3 copies of DES_key_schedule is allocated, for K1, K2 and K3 each. + // + return (UINTN) (3 * sizeof (DES_key_schedule)); +} + +/** + Initializes user-supplied memory as TDES context for subsequent use. + + This function initializes user-supplied memory pointed by TdesContext as TDES context. + In addition, it sets up all TDES key materials for subsequent encryption and decryption + operations. + There are 3 key options as follows: + KeyLength = 64, Keying option 1: K1 == K2 == K3 (Backward compatibility with DES) + KeyLength = 128, Keying option 2: K1 != K2 and K3 = K1 (Less Security) + KeyLength = 192 Keying option 3: K1 != K2 != K3 (Strongest) + + If TdesContext is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeyLength is not valid, then return FALSE. + + @param[out] TdesContext Pointer to TDES context being initialized. + @param[in] Key Pointer to the user-supplied TDES key. + @param[in] KeyLength Length of TDES key in bits. + + @retval TRUE TDES context initialization succeeded. + @retval FALSE TDES context initialization failed. + +**/ +BOOLEAN +EFIAPI +TdesInit ( + OUT VOID *TdesContext, + IN CONST UINT8 *Key, + IN UINTN KeyLength + ) +{ + DES_key_schedule *KeySchedule; + + // + // Check input parameters. + // + if (TdesContext == NULL || Key == NULL || (KeyLength != 64 && KeyLength != 128 && KeyLength != 192)) { + return FALSE; + } + + KeySchedule = (DES_key_schedule *) TdesContext; + + // + // If input Key is a weak key, return error. + // + if (DES_is_weak_key ((const_DES_cblock *) Key) == 1) { + return FALSE; + } + + DES_set_key_unchecked ((const_DES_cblock *) Key, KeySchedule); + + if (KeyLength == 64) { + CopyMem (KeySchedule + 1, KeySchedule, sizeof (DES_key_schedule)); + CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule)); + return TRUE; + } + + if (DES_is_weak_key ((const_DES_cblock *) (Key + 8)) == 1) { + return FALSE; + } + + DES_set_key_unchecked ((const_DES_cblock *) (Key + 8), KeySchedule + 1); + + if (KeyLength == 128) { + CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule)); + return TRUE; + } + + if (DES_is_weak_key ((const_DES_cblock *) (Key + 16)) == 1) { + return FALSE; + } + + DES_set_key_unchecked ((const_DES_cblock *) (Key + 16), KeySchedule + 2); + + return TRUE; +} + +/** + Performs TDES encryption on a data buffer of the specified size in ECB mode. + + This function performs TDES encryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval TRUE TDES encryption succeeded. + @retval FALSE TDES encryption failed. + +**/ +BOOLEAN +EFIAPI +TdesEcbEncrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + DES_key_schedule *KeySchedule; + + // + // Check input parameters. + // + if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0 || Output == NULL) { + return FALSE; + } + + KeySchedule = (DES_key_schedule *) TdesContext; + + while (InputSize > 0) { + DES_ecb3_encrypt ( + (const_DES_cblock *) Input, + (DES_cblock *) Output, + KeySchedule, + KeySchedule + 1, + KeySchedule + 2, + DES_ENCRYPT + ); + Input += TDES_BLOCK_SIZE; + Output += TDES_BLOCK_SIZE; + InputSize -= TDES_BLOCK_SIZE; + } + + return TRUE; +} + +/** + Performs TDES decryption on a data buffer of the specified size in ECB mode. + + This function performs TDES decryption on data buffer pointed by Input, of specified + size of InputSize, in ECB mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the TDES decryption output. + + @retval TRUE TDES decryption succeeded. + @retval FALSE TDES decryption failed. + +**/ +BOOLEAN +EFIAPI +TdesEcbDecrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + DES_key_schedule *KeySchedule; + + // + // Check input parameters. + // + if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0 || Output == NULL) { + return FALSE; + } + + KeySchedule = (DES_key_schedule *) TdesContext; + + while (InputSize > 0) { + DES_ecb3_encrypt ( + (const_DES_cblock *) Input, + (DES_cblock *) Output, + KeySchedule, + KeySchedule + 1, + KeySchedule + 2, + DES_DECRYPT + ); + Input += TDES_BLOCK_SIZE; + Output += TDES_BLOCK_SIZE; + InputSize -= TDES_BLOCK_SIZE; + } + + return TRUE; +} + +/** + Performs TDES encryption on a data buffer of the specified size in CBC mode. + + This function performs TDES encryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (8 bytes). + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval TRUE TDES encryption succeeded. + @retval FALSE TDES encryption failed. + +**/ +BOOLEAN +EFIAPI +TdesCbcEncrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + DES_key_schedule *KeySchedule; + UINT8 IvecBuffer[TDES_BLOCK_SIZE]; + + // + // Check input parameters. + // + if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0) { + return FALSE; + } + + if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) { + return FALSE; + } + + KeySchedule = (DES_key_schedule *) TdesContext; + CopyMem (IvecBuffer, Ivec, TDES_BLOCK_SIZE); + + DES_ede3_cbc_encrypt ( + Input, + Output, + (UINT32) InputSize, + KeySchedule, + KeySchedule + 1, + KeySchedule + 2, + (DES_cblock *) IvecBuffer, + DES_ENCRYPT + ); + + return TRUE; +} + +/** + Performs TDES decryption on a data buffer of the specified size in CBC mode. + + This function performs TDES decryption on data buffer pointed by Input, of specified + size of InputSize, in CBC mode. + InputSize must be multiple of block size (8 bytes). This function does not perform + padding. Caller must perform padding, if necessary, to ensure valid input data size. + Initialization vector should be one block size (8 bytes). + TdesContext should be already correctly initialized by TdesInit(). Behavior with + invalid TDES context is undefined. + + If TdesContext is NULL, then return FALSE. + If Input is NULL, then return FALSE. + If InputSize is not multiple of block size (8 bytes), then return FALSE. + If Ivec is NULL, then return FALSE. + If Output is NULL, then return FALSE. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval TRUE TDES decryption succeeded. + @retval FALSE TDES decryption failed. + +**/ +BOOLEAN +EFIAPI +TdesCbcDecrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + DES_key_schedule *KeySchedule; + UINT8 IvecBuffer[TDES_BLOCK_SIZE]; + + // + // Check input parameters. + // + if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0) { + return FALSE; + } + + if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) { + return FALSE; + } + + KeySchedule = (DES_key_schedule *) TdesContext; + CopyMem (IvecBuffer, Ivec, TDES_BLOCK_SIZE); + + DES_ede3_cbc_encrypt ( + Input, + Output, + (UINT32) InputSize, + KeySchedule, + KeySchedule + 1, + KeySchedule + 2, + (DES_cblock *) IvecBuffer, + DES_DECRYPT + ); + + return TRUE; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdesNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdesNull.c new file mode 100644 index 0000000..06ba4cf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Cipher/CryptTdesNull.c @@ -0,0 +1,166 @@ +/** @file + TDES Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for TDES operations. + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +TdesGetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Initializes user-supplied memory as TDES context for subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] TdesContext Pointer to TDES context being initialized. + @param[in] Key Pointer to the user-supplied TDES key. + @param[in] KeyLength Length of TDES key in bits. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesInit ( + OUT VOID *TdesContext, + IN CONST UINT8 *Key, + IN UINTN KeyLength + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs TDES encryption on a data buffer of the specified size in ECB mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesEcbEncrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs TDES decryption on a data buffer of the specified size in ECB mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be decrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[out] Output Pointer to a buffer that receives the TDES decryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesEcbDecrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs TDES encryption on a data buffer of the specified size in CBC mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesCbcEncrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Performs TDES decryption on a data buffer of the specified size in CBC mode. + + Return FALSE to indicate this interface is not supported. + + @param[in] TdesContext Pointer to the TDES context. + @param[in] Input Pointer to the buffer containing the data to be encrypted. + @param[in] InputSize Size of the Input buffer in bytes. + @param[in] Ivec Pointer to initialization vector. + @param[out] Output Pointer to a buffer that receives the TDES encryption output. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +TdesCbcDecrypt ( + IN VOID *TdesContext, + IN CONST UINT8 *Input, + IN UINTN InputSize, + IN CONST UINT8 *Ivec, + OUT UINT8 *Output + ) +{ + ASSERT (FALSE); + return FALSE; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c new file mode 100644 index 0000000..518bee4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4.c @@ -0,0 +1,229 @@ +/** @file + MD4 Digest Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for MD4 hash operations. + + @return The size, in bytes, of the context buffer required for MD4 hash operations. + +**/ +UINTN +EFIAPI +Md4GetContextSize ( + VOID + ) +{ + // + // Retrieves the OpenSSL MD4 Context Size + // + return (UINTN) (sizeof (MD4_CTX)); +} + +/** + Initializes user-supplied memory pointed by Md4Context as MD4 hash context for + subsequent use. + + If Md4Context is NULL, then return FALSE. + + @param[out] Md4Context Pointer to MD4 context being initialized. + + @retval TRUE MD4 context initialization succeeded. + @retval FALSE MD4 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Md4Init ( + OUT VOID *Md4Context + ) +{ + // + // Check input parameters. + // + if (Md4Context == NULL) { + return FALSE; + } + + // + // OpenSSL MD4 Context Initialization + // + return (BOOLEAN) (MD4_Init ((MD4_CTX *) Md4Context)); +} + +/** + Makes a copy of an existing MD4 context. + + If Md4Context is NULL, then return FALSE. + If NewMd4Context is NULL, then return FALSE. + + @param[in] Md4Context Pointer to MD4 context being copied. + @param[out] NewMd4Context Pointer to new MD4 context. + + @retval TRUE MD4 context copy succeeded. + @retval FALSE MD4 context copy failed. + +**/ +BOOLEAN +EFIAPI +Md4Duplicate ( + IN CONST VOID *Md4Context, + OUT VOID *NewMd4Context + ) +{ + // + // Check input parameters. + // + if (Md4Context == NULL || NewMd4Context == NULL) { + return FALSE; + } + + CopyMem (NewMd4Context, Md4Context, sizeof (MD4_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates MD4 context. + + This function performs MD4 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + MD4 context should be already correctly initialized by Md4Init(), and should not be finalized + by Md4Final(). Behavior with invalid context is undefined. + + If Md4Context is NULL, then return FALSE. + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE MD4 data digest succeeded. + @retval FALSE MD4 data digest failed. + +**/ +BOOLEAN +EFIAPI +Md4Update ( + IN OUT VOID *Md4Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Md4Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL MD4 Hash Update + // + return (BOOLEAN) (MD4_Update ((MD4_CTX *) Md4Context, Data, DataSize)); +} + +/** + Completes computation of the MD4 digest value. + + This function completes MD4 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the MD4 context cannot + be used again. + MD4 context should be already correctly initialized by Md4Init(), and should not be + finalized by Md4Final(). Behavior with invalid MD4 context is undefined. + + If Md4Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval TRUE MD4 digest computation succeeded. + @retval FALSE MD4 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Md4Final ( + IN OUT VOID *Md4Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Md4Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL MD4 Hash Finalization + // + return (BOOLEAN) (MD4_Final (HashValue, (MD4_CTX *) Md4Context)); +} + +/** + Computes the MD4 message digest of a input data buffer. + + This function performs the MD4 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval TRUE MD4 digest computation succeeded. + @retval FALSE MD4 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL MD4 Hash Computation. + // + if (MD4 (Data, DataSize, HashValue) == NULL) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4Null.c new file mode 100644 index 0000000..b8435b0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd4Null.c @@ -0,0 +1,149 @@ +/** @file + MD4 Digest Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for MD4 hash + operations. + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Md4GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Initializes user-supplied memory pointed by Md4Context as MD4 hash context for + subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] Md4Context Pointer to MD4 context being initialized. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Init ( + OUT VOID *Md4Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Makes a copy of an existing MD4 context. + + Return FALSE to indicate this interface is not supported. + + @param[in] Md4Context Pointer to MD4 context being copied. + @param[out] NewMd4Context Pointer to new MD4 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Duplicate ( + IN CONST VOID *Md4Context, + OUT VOID *NewMd4Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates MD4 context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Update ( + IN OUT VOID *Md4Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the MD4 digest value. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Md4Context Pointer to the MD4 context. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4Final ( + IN OUT VOID *Md4Context, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Computes the MD4 message digest of a input data buffer. + + Return FALSE to indicate this interface is not supported. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the MD4 digest + value (16 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md4HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c new file mode 100644 index 0000000..837ee3c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c @@ -0,0 +1,231 @@ +/** @file + MD5 Digest Wrapper Implementation over OpenSSL. + +Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + + +/** + Retrieves the size, in bytes, of the context buffer required for MD5 hash operations. + + @return The size, in bytes, of the context buffer required for MD5 hash operations. + +**/ +UINTN +EFIAPI +Md5GetContextSize ( + VOID + ) +{ + // + // Retrieves the OpenSSL MD5 Context Size + // + return (UINTN) (sizeof (MD5_CTX)); +} + + +/** + Initializes user-supplied memory pointed by Md5Context as MD5 hash context for + subsequent use. + + If Md5Context is NULL, then return FALSE. + + @param[out] Md5Context Pointer to MD5 context being initialized. + + @retval TRUE MD5 context initialization succeeded. + @retval FALSE MD5 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Md5Init ( + OUT VOID *Md5Context + ) +{ + // + // Check input parameters. + // + if (Md5Context == NULL) { + return FALSE; + } + + // + // OpenSSL MD5 Context Initialization + // + return (BOOLEAN) (MD5_Init ((MD5_CTX *) Md5Context)); +} + +/** + Makes a copy of an existing MD5 context. + + If Md5Context is NULL, then return FALSE. + If NewMd5Context is NULL, then return FALSE. + + @param[in] Md5Context Pointer to MD5 context being copied. + @param[out] NewMd5Context Pointer to new MD5 context. + + @retval TRUE MD5 context copy succeeded. + @retval FALSE MD5 context copy failed. + +**/ +BOOLEAN +EFIAPI +Md5Duplicate ( + IN CONST VOID *Md5Context, + OUT VOID *NewMd5Context + ) +{ + // + // Check input parameters. + // + if (Md5Context == NULL || NewMd5Context == NULL) { + return FALSE; + } + + CopyMem (NewMd5Context, Md5Context, sizeof (MD5_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates MD5 context. + + This function performs MD5 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + MD5 context should be already correctly initialized by Md5Init(), and should not be finalized + by Md5Final(). Behavior with invalid context is undefined. + + If Md5Context is NULL, then return FALSE. + + @param[in, out] Md5Context Pointer to the MD5 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE MD5 data digest succeeded. + @retval FALSE MD5 data digest failed. + +**/ +BOOLEAN +EFIAPI +Md5Update ( + IN OUT VOID *Md5Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Md5Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && (DataSize != 0)) { + return FALSE; + } + + // + // OpenSSL MD5 Hash Update + // + return (BOOLEAN) (MD5_Update ((MD5_CTX *) Md5Context, Data, DataSize)); +} + +/** + Completes computation of the MD5 digest value. + + This function completes MD5 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the MD5 context cannot + be used again. + MD5 context should be already correctly initialized by Md5Init(), and should not be + finalized by Md5Final(). Behavior with invalid MD5 context is undefined. + + If Md5Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Md5Context Pointer to the MD5 context. + @param[out] HashValue Pointer to a buffer that receives the MD5 digest + value (16 bytes). + + @retval TRUE MD5 digest computation succeeded. + @retval FALSE MD5 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Md5Final ( + IN OUT VOID *Md5Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Md5Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL MD5 Hash Finalization + // + return (BOOLEAN) (MD5_Final (HashValue, (MD5_CTX *) Md5Context)); +} + +/** + Computes the MD5 message digest of a input data buffer. + + This function performs the MD5 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the MD5 digest + value (16 bytes). + + @retval TRUE MD5 digest computation succeeded. + @retval FALSE MD5 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Md5HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && (DataSize != 0)) { + return FALSE; + } + + // + // OpenSSL MD5 Hash Computation. + // + if (MD5 (Data, DataSize, HashValue) == NULL) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c new file mode 100644 index 0000000..9fea08f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c @@ -0,0 +1,230 @@ +/** @file + SHA-1 Digest Wrapper Implementation over OpenSSL. + +Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-1 hash operations. + +**/ +UINTN +EFIAPI +Sha1GetContextSize ( + VOID + ) +{ + // + // Retrieves OpenSSL SHA Context Size + // + return (UINTN) (sizeof (SHA_CTX)); +} + +/** + Initializes user-supplied memory pointed by Sha1Context as SHA-1 hash context for + subsequent use. + + If Sha1Context is NULL, then return FALSE. + + @param[out] Sha1Context Pointer to SHA-1 context being initialized. + + @retval TRUE SHA-1 context initialization succeeded. + @retval FALSE SHA-1 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha1Init ( + OUT VOID *Sha1Context + ) +{ + // + // Check input parameters. + // + if (Sha1Context == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-1 Context Initialization + // + return (BOOLEAN) (SHA1_Init ((SHA_CTX *) Sha1Context)); +} + +/** + Makes a copy of an existing SHA-1 context. + + If Sha1Context is NULL, then return FALSE. + If NewSha1Context is NULL, then return FALSE. + + @param[in] Sha1Context Pointer to SHA-1 context being copied. + @param[out] NewSha1Context Pointer to new SHA-1 context. + + @retval TRUE SHA-1 context copy succeeded. + @retval FALSE SHA-1 context copy failed. + +**/ +BOOLEAN +EFIAPI +Sha1Duplicate ( + IN CONST VOID *Sha1Context, + OUT VOID *NewSha1Context + ) +{ + // + // Check input parameters. + // + if (Sha1Context == NULL || NewSha1Context == NULL) { + return FALSE; + } + + CopyMem (NewSha1Context, Sha1Context, sizeof (SHA_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates SHA-1 context. + + This function performs SHA-1 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-1 context should be already correctly initialized by Sha1Init(), and should not be finalized + by Sha1Final(). Behavior with invalid context is undefined. + + If Sha1Context is NULL, then return FALSE. + + @param[in, out] Sha1Context Pointer to the SHA-1 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-1 data digest succeeded. + @retval FALSE SHA-1 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha1Update ( + IN OUT VOID *Sha1Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Sha1Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-1 Hash Update + // + return (BOOLEAN) (SHA1_Update ((SHA_CTX *) Sha1Context, Data, DataSize)); +} + +/** + Completes computation of the SHA-1 digest value. + + This function completes SHA-1 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-1 context cannot + be used again. + SHA-1 context should be already correctly initialized by Sha1Init(), and should not be + finalized by Sha1Final(). Behavior with invalid SHA-1 context is undefined. + + If Sha1Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha1Context Pointer to the SHA-1 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-1 digest + value (20 bytes). + + @retval TRUE SHA-1 digest computation succeeded. + @retval FALSE SHA-1 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha1Final ( + IN OUT VOID *Sha1Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Sha1Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-1 Hash Finalization + // + return (BOOLEAN) (SHA1_Final (HashValue, (SHA_CTX *) Sha1Context)); +} + +/** + Computes the SHA-1 message digest of a input data buffer. + + This function performs the SHA-1 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-1 digest + value (20 bytes). + + @retval TRUE SHA-1 digest computation succeeded. + @retval FALSE SHA-1 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha1HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-1 Hash Computation. + // + if (SHA1 (Data, DataSize, HashValue) == NULL) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c new file mode 100644 index 0000000..3a04291 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha256.c @@ -0,0 +1,229 @@ +/** @file + SHA-256 Digest Wrapper Implementation over OpenSSL. + +Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-256 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-256 hash operations. + +**/ +UINTN +EFIAPI +Sha256GetContextSize ( + VOID + ) +{ + // + // Retrieves OpenSSL SHA-256 Context Size + // + return (UINTN) (sizeof (SHA256_CTX)); +} + +/** + Initializes user-supplied memory pointed by Sha256Context as SHA-256 hash context for + subsequent use. + + If Sha256Context is NULL, then return FALSE. + + @param[out] Sha256Context Pointer to SHA-256 context being initialized. + + @retval TRUE SHA-256 context initialization succeeded. + @retval FALSE SHA-256 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha256Init ( + OUT VOID *Sha256Context + ) +{ + // + // Check input parameters. + // + if (Sha256Context == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-256 Context Initialization + // + return (BOOLEAN) (SHA256_Init ((SHA256_CTX *) Sha256Context)); +} + +/** + Makes a copy of an existing SHA-256 context. + + If Sha256Context is NULL, then return FALSE. + If NewSha256Context is NULL, then return FALSE. + + @param[in] Sha256Context Pointer to SHA-256 context being copied. + @param[out] NewSha256Context Pointer to new SHA-256 context. + + @retval TRUE SHA-256 context copy succeeded. + @retval FALSE SHA-256 context copy failed. + +**/ +BOOLEAN +EFIAPI +Sha256Duplicate ( + IN CONST VOID *Sha256Context, + OUT VOID *NewSha256Context + ) +{ + // + // Check input parameters. + // + if (Sha256Context == NULL || NewSha256Context == NULL) { + return FALSE; + } + + CopyMem (NewSha256Context, Sha256Context, sizeof (SHA256_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates SHA-256 context. + + This function performs SHA-256 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-256 context should be already correctly initialized by Sha256Init(), and should not be finalized + by Sha256Final(). Behavior with invalid context is undefined. + + If Sha256Context is NULL, then return FALSE. + + @param[in, out] Sha256Context Pointer to the SHA-256 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-256 data digest succeeded. + @retval FALSE SHA-256 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha256Update ( + IN OUT VOID *Sha256Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Sha256Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-256 Hash Update + // + return (BOOLEAN) (SHA256_Update ((SHA256_CTX *) Sha256Context, Data, DataSize)); +} + +/** + Completes computation of the SHA-256 digest value. + + This function completes SHA-256 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-256 context cannot + be used again. + SHA-256 context should be already correctly initialized by Sha256Init(), and should not be + finalized by Sha256Final(). Behavior with invalid SHA-256 context is undefined. + + If Sha256Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha256Context Pointer to the SHA-256 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-256 digest + value (32 bytes). + + @retval TRUE SHA-256 digest computation succeeded. + @retval FALSE SHA-256 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha256Final ( + IN OUT VOID *Sha256Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Sha256Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-256 Hash Finalization + // + return (BOOLEAN) (SHA256_Final (HashValue, (SHA256_CTX *) Sha256Context)); +} + +/** + Computes the SHA-256 message digest of a input data buffer. + + This function performs the SHA-256 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-256 digest + value (32 bytes). + + @retval TRUE SHA-256 digest computation succeeded. + @retval FALSE SHA-256 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha256HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-256 Hash Computation. + // + if (SHA256 (Data, DataSize, HashValue) == NULL) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512.c new file mode 100644 index 0000000..b1843e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512.c @@ -0,0 +1,446 @@ +/** @file + SHA-384 and SHA-512 Digest Wrapper Implementations over OpenSSL. + +Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-384 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-384 hash operations. + +**/ +UINTN +EFIAPI +Sha384GetContextSize ( + VOID + ) +{ + // + // Retrieves OpenSSL SHA-384 Context Size + // + return (UINTN) (sizeof (SHA512_CTX)); +} + +/** + Initializes user-supplied memory pointed by Sha384Context as SHA-384 hash context for + subsequent use. + + If Sha384Context is NULL, then return FALSE. + + @param[out] Sha384Context Pointer to SHA-384 context being initialized. + + @retval TRUE SHA-384 context initialization succeeded. + @retval FALSE SHA-384 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha384Init ( + OUT VOID *Sha384Context + ) +{ + // + // Check input parameters. + // + if (Sha384Context == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-384 Context Initialization + // + return (BOOLEAN) (SHA384_Init ((SHA512_CTX *) Sha384Context)); +} + +/** + Makes a copy of an existing SHA-384 context. + + If Sha384Context is NULL, then return FALSE. + If NewSha384Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Sha384Context Pointer to SHA-384 context being copied. + @param[out] NewSha384Context Pointer to new SHA-384 context. + + @retval TRUE SHA-384 context copy succeeded. + @retval FALSE SHA-384 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384Duplicate ( + IN CONST VOID *Sha384Context, + OUT VOID *NewSha384Context + ) +{ + // + // Check input parameters. + // + if (Sha384Context == NULL || NewSha384Context == NULL) { + return FALSE; + } + + CopyMem (NewSha384Context, Sha384Context, sizeof (SHA512_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates SHA-384 context. + + This function performs SHA-384 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-384 context should be already correctly initialized by Sha384Init(), and should not be finalized + by Sha384Final(). Behavior with invalid context is undefined. + + If Sha384Context is NULL, then return FALSE. + + @param[in, out] Sha384Context Pointer to the SHA-384 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-384 data digest succeeded. + @retval FALSE SHA-384 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha384Update ( + IN OUT VOID *Sha384Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Sha384Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-384 Hash Update + // + return (BOOLEAN) (SHA384_Update ((SHA512_CTX *) Sha384Context, Data, DataSize)); +} + +/** + Completes computation of the SHA-384 digest value. + + This function completes SHA-384 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-384 context cannot + be used again. + SHA-384 context should be already correctly initialized by Sha384Init(), and should not be + finalized by Sha384Final(). Behavior with invalid SHA-384 context is undefined. + + If Sha384Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha384Context Pointer to the SHA-384 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-384 digest + value (48 bytes). + + @retval TRUE SHA-384 digest computation succeeded. + @retval FALSE SHA-384 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha384Final ( + IN OUT VOID *Sha384Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Sha384Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-384 Hash Finalization + // + return (BOOLEAN) (SHA384_Final (HashValue, (SHA512_CTX *) Sha384Context)); +} + +/** + Computes the SHA-384 message digest of a input data buffer. + + This function performs the SHA-384 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-384 digest + value (48 bytes). + + @retval TRUE SHA-384 digest computation succeeded. + @retval FALSE SHA-384 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-384 Hash Computation. + // + if (SHA384 (Data, DataSize, HashValue) == NULL) { + return FALSE; + } else { + return TRUE; + } +} + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-512 hash operations. + + @return The size, in bytes, of the context buffer required for SHA-512 hash operations. + +**/ +UINTN +EFIAPI +Sha512GetContextSize ( + VOID + ) +{ + // + // Retrieves OpenSSL SHA-512 Context Size + // + return (UINTN) (sizeof (SHA512_CTX)); +} + +/** + Initializes user-supplied memory pointed by Sha512Context as SHA-512 hash context for + subsequent use. + + If Sha512Context is NULL, then return FALSE. + + @param[out] Sha512Context Pointer to SHA-512 context being initialized. + + @retval TRUE SHA-512 context initialization succeeded. + @retval FALSE SHA-512 context initialization failed. + +**/ +BOOLEAN +EFIAPI +Sha512Init ( + OUT VOID *Sha512Context + ) +{ + // + // Check input parameters. + // + if (Sha512Context == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-512 Context Initialization + // + return (BOOLEAN) (SHA512_Init ((SHA512_CTX *) Sha512Context)); +} + +/** + Makes a copy of an existing SHA-512 context. + + If Sha512Context is NULL, then return FALSE. + If NewSha512Context is NULL, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] Sha512Context Pointer to SHA-512 context being copied. + @param[out] NewSha512Context Pointer to new SHA-512 context. + + @retval TRUE SHA-512 context copy succeeded. + @retval FALSE SHA-512 context copy failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512Duplicate ( + IN CONST VOID *Sha512Context, + OUT VOID *NewSha512Context + ) +{ + // + // Check input parameters. + // + if (Sha512Context == NULL || NewSha512Context == NULL) { + return FALSE; + } + + CopyMem (NewSha512Context, Sha512Context, sizeof (SHA512_CTX)); + + return TRUE; +} + +/** + Digests the input data and updates SHA-512 context. + + This function performs SHA-512 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + SHA-512 context should be already correctly initialized by Sha512Init(), and should not be finalized + by Sha512Final(). Behavior with invalid context is undefined. + + If Sha512Context is NULL, then return FALSE. + + @param[in, out] Sha512Context Pointer to the SHA-512 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE SHA-512 data digest succeeded. + @retval FALSE SHA-512 data digest failed. + +**/ +BOOLEAN +EFIAPI +Sha512Update ( + IN OUT VOID *Sha512Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (Sha512Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-512 Hash Update + // + return (BOOLEAN) (SHA512_Update ((SHA512_CTX *) Sha512Context, Data, DataSize)); +} + +/** + Completes computation of the SHA-512 digest value. + + This function completes SHA-512 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the SHA-512 context cannot + be used again. + SHA-512 context should be already correctly initialized by Sha512Init(), and should not be + finalized by Sha512Final(). Behavior with invalid SHA-512 context is undefined. + + If Sha512Context is NULL, then return FALSE. + If HashValue is NULL, then return FALSE. + + @param[in, out] Sha512Context Pointer to the SHA-512 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-512 digest + value (64 bytes). + + @retval TRUE SHA-512 digest computation succeeded. + @retval FALSE SHA-512 digest computation failed. + +**/ +BOOLEAN +EFIAPI +Sha512Final ( + IN OUT VOID *Sha512Context, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (Sha512Context == NULL || HashValue == NULL) { + return FALSE; + } + + // + // OpenSSL SHA-512 Hash Finalization + // + return (BOOLEAN) (SHA384_Final (HashValue, (SHA512_CTX *) Sha512Context)); +} + +/** + Computes the SHA-512 message digest of a input data buffer. + + This function performs the SHA-512 message digest of a given data buffer, and places + the digest value into the specified memory. + + If this interface is not supported, then return FALSE. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-512 digest + value (64 bytes). + + @retval TRUE SHA-512 digest computation succeeded. + @retval FALSE SHA-512 digest computation failed. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + // + // Check input parameters. + // + if (HashValue == NULL) { + return FALSE; + } + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL SHA-512 Hash Computation. + // + if (SHA512 (Data, DataSize, HashValue) == NULL) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512Null.c new file mode 100644 index 0000000..4a3bcfc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha512Null.c @@ -0,0 +1,281 @@ +/** @file + SHA-384 and SHA-512 Digest Wrapper Implementations which does not provide real capabilities. + +Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-384 hash operations. + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Sha384GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Initializes user-supplied memory pointed by Sha384Context as SHA-384 hash context for + subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] Sha384Context Pointer to SHA-384 context being initialized. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384Init ( + OUT VOID *Sha384Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Makes a copy of an existing SHA-384 context. + + Return FALSE to indicate this interface is not supported. + + @param[in] Sha384Context Pointer to SHA-384 context being copied. + @param[out] NewSha384Context Pointer to new SHA-384 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384Duplicate ( + IN CONST VOID *Sha384Context, + OUT VOID *NewSha384Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates SHA-384 context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Sha384Context Pointer to the SHA-384 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384Update ( + IN OUT VOID *Sha384Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the SHA-384 digest value. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Sha384Context Pointer to the SHA-384 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-384 digest + value (48 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384Final ( + IN OUT VOID *Sha384Context, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Computes the SHA-384 message digest of a input data buffer. + + Return FALSE to indicate this interface is not supported. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-384 digest + value (48 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha384HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Retrieves the size, in bytes, of the context buffer required for SHA-512 hash operations. + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +Sha512GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Initializes user-supplied memory pointed by Sha512Context as SHA-512 hash context for + subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] Sha512Context Pointer to SHA-512 context being initialized. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512Init ( + OUT VOID *Sha512Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Makes a copy of an existing SHA-512 context. + + Return FALSE to indicate this interface is not supported. + + @param[in] Sha512Context Pointer to SHA-512 context being copied. + @param[out] NewSha512Context Pointer to new SHA-512 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512Duplicate ( + IN CONST VOID *Sha512Context, + OUT VOID *NewSha512Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates SHA-512 context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Sha512Context Pointer to the SHA-512 context. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512Update ( + IN OUT VOID *Sha512Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the SHA-512 digest value. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] Sha512Context Pointer to the SHA-512 context. + @param[out] HashValue Pointer to a buffer that receives the SHA-512 digest + value (64 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512Final ( + IN OUT VOID *Sha512Context, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Computes the SHA-512 message digest of a input data buffer. + + Return FALSE to indicate this interface is not supported. + + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the SHA-512 digest + value (64 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Sha512HashAll ( + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c new file mode 100644 index 0000000..9688cd5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5.c @@ -0,0 +1,256 @@ +/** @file + HMAC-MD5 Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +#define HMAC_MD5_CTX_SIZE sizeof(void *) * 4 + sizeof(unsigned int) + \ + sizeof(unsigned char) * HMAC_MAX_MD_CBLOCK + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-MD5 operations. + (NOTE: This API is deprecated. + Use HmacMd5New() / HmacMd5Free() for HMAC-MD5 Context operations.) + + @return The size, in bytes, of the context buffer required for HMAC-MD5 operations. + +**/ +UINTN +EFIAPI +HmacMd5GetContextSize ( + VOID + ) +{ + // + // Retrieves the OpenSSL HMAC-MD5 Context Size + // NOTE: HMAC_CTX object was made opaque in openssl-1.1.x, here we just use the + // fixed size as a workaround to make this API work for compatibility. + // We should retire HmacMd5GetContextSize() in future, and use HmacMd5New() + // and HmacMd5Free() for context allocation and release. + // + return (UINTN) HMAC_MD5_CTX_SIZE; +} + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-MD5 use. + + @return Pointer to the HMAC_CTX context that has been initialized. + If the allocations fails, HmacMd5New() returns NULL. + +**/ +VOID * +EFIAPI +HmacMd5New ( + VOID + ) +{ + // + // Allocates & Initializes HMAC_CTX Context by OpenSSL HMAC_CTX_new() + // + return (VOID *) HMAC_CTX_new (); +} + +/** + Release the specified HMAC_CTX context. + + @param[in] HmacMd5Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacMd5Free ( + IN VOID *HmacMd5Ctx + ) +{ + // + // Free OpenSSL HMAC_CTX Context + // + HMAC_CTX_free ((HMAC_CTX *)HmacMd5Ctx); +} + +/** + Initializes user-supplied memory pointed by HmacMd5Context as HMAC-MD5 context for + subsequent use. + + If HmacMd5Context is NULL, then return FALSE. + + @param[out] HmacMd5Context Pointer to HMAC-MD5 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval TRUE HMAC-MD5 context initialization succeeded. + @retval FALSE HMAC-MD5 context initialization failed. + +**/ +BOOLEAN +EFIAPI +HmacMd5Init ( + OUT VOID *HmacMd5Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + // + // Check input parameters. + // + if (HmacMd5Context == NULL || KeySize > INT_MAX) { + return FALSE; + } + + // + // OpenSSL HMAC-MD5 Context Initialization + // + memset(HmacMd5Context, 0, HMAC_MD5_CTX_SIZE); + if (HMAC_CTX_reset ((HMAC_CTX *)HmacMd5Context) != 1) { + return FALSE; + } + if (HMAC_Init_ex ((HMAC_CTX *)HmacMd5Context, Key, (UINT32) KeySize, EVP_md5(), NULL) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Makes a copy of an existing HMAC-MD5 context. + + If HmacMd5Context is NULL, then return FALSE. + If NewHmacMd5Context is NULL, then return FALSE. + + @param[in] HmacMd5Context Pointer to HMAC-MD5 context being copied. + @param[out] NewHmacMd5Context Pointer to new HMAC-MD5 context. + + @retval TRUE HMAC-MD5 context copy succeeded. + @retval FALSE HMAC-MD5 context copy failed. + +**/ +BOOLEAN +EFIAPI +HmacMd5Duplicate ( + IN CONST VOID *HmacMd5Context, + OUT VOID *NewHmacMd5Context + ) +{ + // + // Check input parameters. + // + if (HmacMd5Context == NULL || NewHmacMd5Context == NULL) { + return FALSE; + } + + if (HMAC_CTX_copy ((HMAC_CTX *)NewHmacMd5Context, (HMAC_CTX *)HmacMd5Context) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Digests the input data and updates HMAC-MD5 context. + + This function performs HMAC-MD5 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + HMAC-MD5 context should be already correctly initialized by HmacMd5Init(), and should not be + finalized by HmacMd5Final(). Behavior with invalid context is undefined. + + If HmacMd5Context is NULL, then return FALSE. + + @param[in, out] HmacMd5Context Pointer to the HMAC-MD5 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE HMAC-MD5 data digest succeeded. + @retval FALSE HMAC-MD5 data digest failed. + +**/ +BOOLEAN +EFIAPI +HmacMd5Update ( + IN OUT VOID *HmacMd5Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (HmacMd5Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL HMAC-MD5 digest update + // + if (HMAC_Update ((HMAC_CTX *)HmacMd5Context, Data, DataSize) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Completes computation of the HMAC-MD5 digest value. + + This function completes HMAC-MD5 digest computation and retrieves the digest value into + the specified memory. After this function has been called, the HMAC-MD5 context cannot + be used again. + HMAC-MD5 context should be already correctly initialized by HmacMd5Init(), and should not be + finalized by HmacMd5Final(). Behavior with invalid HMAC-MD5 context is undefined. + + If HmacMd5Context is NULL, then return FALSE. + If HmacValue is NULL, then return FALSE. + + @param[in, out] HmacMd5Context Pointer to the HMAC-MD5 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-MD5 digest + value (16 bytes). + + @retval TRUE HMAC-MD5 digest computation succeeded. + @retval FALSE HMAC-MD5 digest computation failed. + +**/ +BOOLEAN +EFIAPI +HmacMd5Final ( + IN OUT VOID *HmacMd5Context, + OUT UINT8 *HmacValue + ) +{ + UINT32 Length; + + // + // Check input parameters. + // + if (HmacMd5Context == NULL || HmacValue == NULL) { + return FALSE; + } + + // + // OpenSSL HMAC-MD5 digest finalization + // + if (HMAC_Final ((HMAC_CTX *)HmacMd5Context, HmacValue, &Length) != 1) { + return FALSE; + } + if (HMAC_CTX_reset ((HMAC_CTX *)HmacMd5Context) != 1) { + return FALSE; + } + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5Null.c new file mode 100644 index 0000000..8e94e1a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacMd5Null.c @@ -0,0 +1,165 @@ +/** @file + HMAC-MD5 Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-MD5 operations. + (NOTE: This API is deprecated. + Use HmacMd5New() / HmacMd5Free() for HMAC-MD5 Context operations.) + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +HmacMd5GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-MD5 use. + + Return NULL to indicate this interface is not supported. + + @retval NULL This interface is not supported. + +**/ +VOID * +EFIAPI +HmacMd5New ( + VOID + ) +{ + ASSERT (FALSE); + return NULL; +} + +/** + Release the specified HMAC_CTX context. + + This function will do nothing. + + @param[in] HmacMd5Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacMd5Free ( + IN VOID *HmacMd5Ctx + ) +{ + ASSERT (FALSE); + return; +} + +/** + Initializes user-supplied memory pointed by HmacMd5Context as HMAC-MD5 context for + subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] HmacMd5Context Pointer to HMAC-MD5 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Init ( + OUT VOID *HmacMd5Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Makes a copy of an existing HMAC-MD5 context. + + Return FALSE to indicate this interface is not supported. + + @param[in] HmacMd5Context Pointer to HMAC-MD5 context being copied. + @param[out] NewHmacMd5Context Pointer to new HMAC-MD5 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Duplicate ( + IN CONST VOID *HmacMd5Context, + OUT VOID *NewHmacMd5Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates HMAC-MD5 context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] HmacMd5Context Pointer to the HMAC-MD5 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Update ( + IN OUT VOID *HmacMd5Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the HMAC-MD5 digest value. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] HmacMd5Context Pointer to the HMAC-MD5 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-MD5 digest + value (16 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacMd5Final ( + IN OUT VOID *HmacMd5Context, + OUT UINT8 *HmacValue + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c new file mode 100644 index 0000000..d82e648 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1.c @@ -0,0 +1,256 @@ +/** @file + HMAC-SHA1 Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +#define HMAC_SHA1_CTX_SIZE sizeof(void *) * 4 + sizeof(unsigned int) + \ + sizeof(unsigned char) * HMAC_MAX_MD_CBLOCK + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-SHA1 operations. + (NOTE: This API is deprecated. + Use HmacSha1New() / HmacSha1Free() for HMAC-SHA1 Context operations.) + + @return The size, in bytes, of the context buffer required for HMAC-SHA1 operations. + +**/ +UINTN +EFIAPI +HmacSha1GetContextSize ( + VOID + ) +{ + // + // Retrieves the OpenSSL HMAC-SHA1 Context Size + // NOTE: HMAC_CTX object was made opaque in openssl-1.1.x, here we just use the + // fixed size as a workaround to make this API work for compatibility. + // We should retire HmacSha15GetContextSize() in future, and use HmacSha1New() + // and HmacSha1Free() for context allocation and release. + // + return (UINTN) HMAC_SHA1_CTX_SIZE; +} + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA1 use. + + @return Pointer to the HMAC_CTX context that has been initialized. + If the allocations fails, HmacSha1New() returns NULL. + +**/ +VOID * +EFIAPI +HmacSha1New ( + VOID + ) +{ + // + // Allocates & Initializes HMAC_CTX Context by OpenSSL HMAC_CTX_new() + // + return (VOID *) HMAC_CTX_new (); +} + +/** + Release the specified HMAC_CTX context. + + @param[in] HmacSha1Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacSha1Free ( + IN VOID *HmacSha1Ctx + ) +{ + // + // Free OpenSSL HMAC_CTX Context + // + HMAC_CTX_free ((HMAC_CTX *)HmacSha1Ctx); +} + +/** + Initializes user-supplied memory pointed by HmacSha1Context as HMAC-SHA1 context for + subsequent use. + + If HmacSha1Context is NULL, then return FALSE. + + @param[out] HmacSha1Context Pointer to HMAC-SHA1 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval TRUE HMAC-SHA1 context initialization succeeded. + @retval FALSE HMAC-SHA1 context initialization failed. + +**/ +BOOLEAN +EFIAPI +HmacSha1Init ( + OUT VOID *HmacSha1Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + // + // Check input parameters. + // + if (HmacSha1Context == NULL || KeySize > INT_MAX) { + return FALSE; + } + + // + // OpenSSL HMAC-SHA1 Context Initialization + // + memset(HmacSha1Context, 0, HMAC_SHA1_CTX_SIZE); + if (HMAC_CTX_reset ((HMAC_CTX *)HmacSha1Context) != 1) { + return FALSE; + } + if (HMAC_Init_ex ((HMAC_CTX *)HmacSha1Context, Key, (UINT32) KeySize, EVP_sha1(), NULL) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Makes a copy of an existing HMAC-SHA1 context. + + If HmacSha1Context is NULL, then return FALSE. + If NewHmacSha1Context is NULL, then return FALSE. + + @param[in] HmacSha1Context Pointer to HMAC-SHA1 context being copied. + @param[out] NewHmacSha1Context Pointer to new HMAC-SHA1 context. + + @retval TRUE HMAC-SHA1 context copy succeeded. + @retval FALSE HMAC-SHA1 context copy failed. + +**/ +BOOLEAN +EFIAPI +HmacSha1Duplicate ( + IN CONST VOID *HmacSha1Context, + OUT VOID *NewHmacSha1Context + ) +{ + // + // Check input parameters. + // + if (HmacSha1Context == NULL || NewHmacSha1Context == NULL) { + return FALSE; + } + + if (HMAC_CTX_copy ((HMAC_CTX *)NewHmacSha1Context, (HMAC_CTX *)HmacSha1Context) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Digests the input data and updates HMAC-SHA1 context. + + This function performs HMAC-SHA1 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + HMAC-SHA1 context should be already correctly initialized by HmacSha1Init(), and should not + be finalized by HmacSha1Final(). Behavior with invalid context is undefined. + + If HmacSha1Context is NULL, then return FALSE. + + @param[in, out] HmacSha1Context Pointer to the HMAC-SHA1 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE HMAC-SHA1 data digest succeeded. + @retval FALSE HMAC-SHA1 data digest failed. + +**/ +BOOLEAN +EFIAPI +HmacSha1Update ( + IN OUT VOID *HmacSha1Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (HmacSha1Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL HMAC-SHA1 digest update + // + if (HMAC_Update ((HMAC_CTX *)HmacSha1Context, Data, DataSize) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Completes computation of the HMAC-SHA1 digest value. + + This function completes HMAC-SHA1 digest computation and retrieves the digest value into + the specified memory. After this function has been called, the HMAC-SHA1 context cannot + be used again. + HMAC-SHA1 context should be already correctly initialized by HmacSha1Init(), and should + not be finalized by HmacSha1Final(). Behavior with invalid HMAC-SHA1 context is undefined. + + If HmacSha1Context is NULL, then return FALSE. + If HmacValue is NULL, then return FALSE. + + @param[in, out] HmacSha1Context Pointer to the HMAC-SHA1 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-SHA1 digest + value (20 bytes). + + @retval TRUE HMAC-SHA1 digest computation succeeded. + @retval FALSE HMAC-SHA1 digest computation failed. + +**/ +BOOLEAN +EFIAPI +HmacSha1Final ( + IN OUT VOID *HmacSha1Context, + OUT UINT8 *HmacValue + ) +{ + UINT32 Length; + + // + // Check input parameters. + // + if (HmacSha1Context == NULL || HmacValue == NULL) { + return FALSE; + } + + // + // OpenSSL HMAC-SHA1 digest finalization + // + if (HMAC_Final ((HMAC_CTX *)HmacSha1Context, HmacValue, &Length) != 1) { + return FALSE; + } + if (HMAC_CTX_reset ((HMAC_CTX *)HmacSha1Context) != 1) { + return FALSE; + } + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1Null.c new file mode 100644 index 0000000..f3dcda4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha1Null.c @@ -0,0 +1,165 @@ +/** @file + HMAC-SHA1 Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-SHA1 operations. + (NOTE: This API is deprecated. + Use HmacSha1New() / HmacSha1Free() for HMAC-SHA1 Context operations.) + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +HmacSha1GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA1 use. + + Return NULL to indicate this interface is not supported. + + @return NULL This interface is not supported.. + +**/ +VOID * +EFIAPI +HmacSha1New ( + VOID + ) +{ + ASSERT (FALSE); + return NULL; +} + +/** + Release the specified HMAC_CTX context. + + This function will do nothing. + + @param[in] HmacSha1Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacSha1Free ( + IN VOID *HmacSha1Ctx + ) +{ + ASSERT (FALSE); + return; +} + +/** + Initializes user-supplied memory pointed by HmacSha1Context as HMAC-SHA1 context for + subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] HmacSha1Context Pointer to HMAC-SHA1 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Init ( + OUT VOID *HmacSha1Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Makes a copy of an existing HMAC-SHA1 context. + + Return FALSE to indicate this interface is not supported. + + @param[in] HmacSha1Context Pointer to HMAC-SHA1 context being copied. + @param[out] NewHmacSha1Context Pointer to new HMAC-SHA1 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Duplicate ( + IN CONST VOID *HmacSha1Context, + OUT VOID *NewHmacSha1Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates HMAC-SHA1 context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] HmacSha1Context Pointer to the HMAC-SHA1 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Update ( + IN OUT VOID *HmacSha1Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the HMAC-SHA1 digest value. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] HmacSha1Context Pointer to the HMAC-SHA1 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-SHA1 digest + value (20 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha1Final ( + IN OUT VOID *HmacSha1Context, + OUT UINT8 *HmacValue + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256.c new file mode 100644 index 0000000..03d550e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256.c @@ -0,0 +1,256 @@ +/** @file + HMAC-SHA256 Wrapper Implementation over OpenSSL. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +#define HMAC_SHA256_CTX_SIZE sizeof(void *) * 4 + sizeof(unsigned int) + \ + sizeof(unsigned char) * HMAC_MAX_MD_CBLOCK + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-SHA256 operations. + (NOTE: This API is deprecated. + Use HmacSha256New() / HmacSha256Free() for HMAC-SHA256 Context operations.) + + @return The size, in bytes, of the context buffer required for HMAC-SHA256 operations. + +**/ +UINTN +EFIAPI +HmacSha256GetContextSize ( + VOID + ) +{ + // + // Retrieves the OpenSSL HMAC-SHA256 Context Size + // NOTE: HMAC_CTX object was made opaque in openssl-1.1.x, here we just use the + // fixed size as a workaround to make this API work for compatibility. + // We should retire HmacSha256GetContextSize() in future, and use HmacSha256New() + // and HmacSha256Free() for context allocation and release. + // + return (UINTN)HMAC_SHA256_CTX_SIZE; +} + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA256 use. + + @return Pointer to the HMAC_CTX context that has been initialized. + If the allocations fails, HmacSha256New() returns NULL. + +**/ +VOID * +EFIAPI +HmacSha256New ( + VOID + ) +{ + // + // Allocates & Initializes HMAC_CTX Context by OpenSSL HMAC_CTX_new() + // + return (VOID *) HMAC_CTX_new (); +} + +/** + Release the specified HMAC_CTX context. + + @param[in] HmacSha256Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacSha256Free ( + IN VOID *HmacSha256Ctx + ) +{ + // + // Free OpenSSL HMAC_CTX Context + // + HMAC_CTX_free ((HMAC_CTX *)HmacSha256Ctx); +} + +/** + Initializes user-supplied memory pointed by HmacSha256Context as HMAC-SHA256 context for + subsequent use. + + If HmacSha256Context is NULL, then return FALSE. + + @param[out] HmacSha256Context Pointer to HMAC-SHA256 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval TRUE HMAC-SHA256 context initialization succeeded. + @retval FALSE HMAC-SHA256 context initialization failed. + +**/ +BOOLEAN +EFIAPI +HmacSha256Init ( + OUT VOID *HmacSha256Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + // + // Check input parameters. + // + if (HmacSha256Context == NULL || KeySize > INT_MAX) { + return FALSE; + } + + // + // OpenSSL HMAC-SHA256 Context Initialization + // + memset(HmacSha256Context, 0, HMAC_SHA256_CTX_SIZE); + if (HMAC_CTX_reset ((HMAC_CTX *)HmacSha256Context) != 1) { + return FALSE; + } + if (HMAC_Init_ex ((HMAC_CTX *)HmacSha256Context, Key, (UINT32) KeySize, EVP_sha256(), NULL) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Makes a copy of an existing HMAC-SHA256 context. + + If HmacSha256Context is NULL, then return FALSE. + If NewHmacSha256Context is NULL, then return FALSE. + + @param[in] HmacSha256Context Pointer to HMAC-SHA256 context being copied. + @param[out] NewHmacSha256Context Pointer to new HMAC-SHA256 context. + + @retval TRUE HMAC-SHA256 context copy succeeded. + @retval FALSE HMAC-SHA256 context copy failed. + +**/ +BOOLEAN +EFIAPI +HmacSha256Duplicate ( + IN CONST VOID *HmacSha256Context, + OUT VOID *NewHmacSha256Context + ) +{ + // + // Check input parameters. + // + if (HmacSha256Context == NULL || NewHmacSha256Context == NULL) { + return FALSE; + } + + if (HMAC_CTX_copy ((HMAC_CTX *)NewHmacSha256Context, (HMAC_CTX *)HmacSha256Context) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Digests the input data and updates HMAC-SHA256 context. + + This function performs HMAC-SHA256 digest on a data buffer of the specified size. + It can be called multiple times to compute the digest of long or discontinuous data streams. + HMAC-SHA256 context should be already correctly initialized by HmacSha256Init(), and should not + be finalized by HmacSha256Final(). Behavior with invalid context is undefined. + + If HmacSha256Context is NULL, then return FALSE. + + @param[in, out] HmacSha256Context Pointer to the HMAC-SHA256 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE HMAC-SHA256 data digest succeeded. + @retval FALSE HMAC-SHA256 data digest failed. + +**/ +BOOLEAN +EFIAPI +HmacSha256Update ( + IN OUT VOID *HmacSha256Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (HmacSha256Context == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case that only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL HMAC-SHA256 digest update + // + if (HMAC_Update ((HMAC_CTX *)HmacSha256Context, Data, DataSize) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Completes computation of the HMAC-SHA256 digest value. + + This function completes HMAC-SHA256 hash computation and retrieves the digest value into + the specified memory. After this function has been called, the HMAC-SHA256 context cannot + be used again. + HMAC-SHA256 context should be already correctly initialized by HmacSha256Init(), and should + not be finalized by HmacSha256Final(). Behavior with invalid HMAC-SHA256 context is undefined. + + If HmacSha256Context is NULL, then return FALSE. + If HmacValue is NULL, then return FALSE. + + @param[in, out] HmacSha256Context Pointer to the HMAC-SHA256 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-SHA256 digest + value (32 bytes). + + @retval TRUE HMAC-SHA256 digest computation succeeded. + @retval FALSE HMAC-SHA256 digest computation failed. + +**/ +BOOLEAN +EFIAPI +HmacSha256Final ( + IN OUT VOID *HmacSha256Context, + OUT UINT8 *HmacValue + ) +{ + UINT32 Length; + + // + // Check input parameters. + // + if (HmacSha256Context == NULL || HmacValue == NULL) { + return FALSE; + } + + // + // OpenSSL HMAC-SHA256 digest finalization + // + if (HMAC_Final ((HMAC_CTX *)HmacSha256Context, HmacValue, &Length) != 1) { + return FALSE; + } + if (HMAC_CTX_reset ((HMAC_CTX *)HmacSha256Context) != 1) { + return FALSE; + } + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256Null.c new file mode 100644 index 0000000..fcc45b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Hmac/CryptHmacSha256Null.c @@ -0,0 +1,165 @@ +/** @file + HMAC-SHA256 Wrapper Implementation which does not provide real capabilities. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieves the size, in bytes, of the context buffer required for HMAC-SHA256 operations. + (NOTE: This API is deprecated. + Use HmacSha256New() / HmacSha256Free() for HMAC-SHA256 Context operations.) + + Return zero to indicate this interface is not supported. + + @retval 0 This interface is not supported. + +**/ +UINTN +EFIAPI +HmacSha256GetContextSize ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA256 use. + + Return NULL to indicate this interface is not supported. + + @return NULL This interface is not supported.. + +**/ +VOID * +EFIAPI +HmacSha256New ( + VOID + ) +{ + ASSERT (FALSE); + return NULL; +} + +/** + Release the specified HMAC_CTX context. + + This function will do nothing. + + @param[in] HmacSha256Ctx Pointer to the HMAC_CTX context to be released. + +**/ +VOID +EFIAPI +HmacSha256Free ( + IN VOID *HmacSha256Ctx + ) +{ + ASSERT (FALSE); + return; +} + +/** + Initializes user-supplied memory pointed by HmacSha256Context as HMAC-SHA256 context for + subsequent use. + + Return FALSE to indicate this interface is not supported. + + @param[out] HmacSha256Context Pointer to HMAC-SHA256 context being initialized. + @param[in] Key Pointer to the user-supplied key. + @param[in] KeySize Key size in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Init ( + OUT VOID *HmacSha256Context, + IN CONST UINT8 *Key, + IN UINTN KeySize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Makes a copy of an existing HMAC-SHA256 context. + + Return FALSE to indicate this interface is not supported. + + @param[in] HmacSha256Context Pointer to HMAC-SHA256 context being copied. + @param[out] NewHmacSha256Context Pointer to new HMAC-SHA256 context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Duplicate ( + IN CONST VOID *HmacSha256Context, + OUT VOID *NewHmacSha256Context + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates HMAC-SHA256 context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] HmacSha256Context Pointer to the HMAC-SHA256 context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Update ( + IN OUT VOID *HmacSha256Context, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the HMAC-SHA256 digest value. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] HmacSha256Context Pointer to the HMAC-SHA256 context. + @param[out] HmacValue Pointer to a buffer that receives the HMAC-SHA256 digest + value (32 bytes). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +HmacSha256Final ( + IN OUT VOID *HmacSha256Context, + OUT UINT8 *HmacValue + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/InternalCryptLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/InternalCryptLib.h new file mode 100644 index 0000000..b34b052 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/InternalCryptLib.h @@ -0,0 +1,68 @@ +/** @file + Internal include file for BaseCryptLib. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __INTERNAL_CRYPT_LIB_H__ +#define __INTERNAL_CRYPT_LIB_H__ + +#undef _WIN32 +#undef _WIN64 + +#include +#include +#include +#include +#include + +#include "CrtLibSupport.h" + +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define OBJ_get0_data(o) ((o)->data) +#define OBJ_length(o) ((o)->length) +#endif + +/** + Check input P7Data is a wrapped ContentInfo structure or not. If not construct + a new structure to wrap P7Data. + + Caution: This function may receive untrusted input. + UEFI Authenticated Variable is external input, so this function will do basic + check for PKCS#7 data structure. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise + return FALSE. + @param[out] WrapData If return status of this function is TRUE: + 1) when WrapFlag is TRUE, pointer to P7Data. + 2) when WrapFlag is FALSE, pointer to a new ContentInfo + structure. It's caller's responsibility to free this + buffer. + @param[out] WrapDataSize Length of ContentInfo structure in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE The operation is failed due to lack of resources. + +**/ +BOOLEAN +WrapPkcs7Data ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT BOOLEAN *WrapFlag, + OUT UINT8 **WrapData, + OUT UINTN *WrapDataSize + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf new file mode 100644 index 0000000..e918fad --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf @@ -0,0 +1,99 @@ +## @file +# Cryptographic Library Instance for PEIM. +# +# Caution: This module requires additional review when modified. +# This library will have external input - signature. +# This external input must be validated carefully to avoid security issues such as +# buffer overflow or integer overflow. +# +# Note: MD4 Digest functions, +# HMAC-MD5 functions, HMAC-SHA1/SHA256 functions, AES/TDES/ARC4 functions, RSA external +# functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, X.509 +# certificate handler functions, authenticode signature verification functions, +# PEM handler functions, and pseudorandom number generator functions are not +# supported in this instance. +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiCryptLib + MODULE_UNI_FILE = PeiCryptLib.uni + FILE_GUID = 9a2a4375-194c-4e97-9f67-547ec98d96ca + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseCryptLib|PEIM PEI_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + Hash/CryptMd4Null.c + Hash/CryptMd5.c + Hash/CryptSha1.c + Hash/CryptSha256.c + Hash/CryptSha512.c + Hmac/CryptHmacMd5Null.c + Hmac/CryptHmacSha1Null.c + Hmac/CryptHmacSha256Null.c + Cipher/CryptAesNull.c + Cipher/CryptTdesNull.c + Cipher/CryptArc4Null.c + + Pk/CryptRsaBasic.c + Pk/CryptRsaExtNull.c + Pk/CryptPkcs5Pbkdf2Null.c + Pk/CryptPkcs7SignNull.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + + Pk/CryptDhNull.c + Pk/CryptX509Null.c + Pk/CryptAuthenticodeNull.c + Pk/CryptTsNull.c + Pem/CryptPemNull.c + + Rand/CryptRandNull.c + + SysCall/CrtWrapper.c + SysCall/ConstantTimeClock.c + SysCall/BaseMemAllocation.c + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + OpensslLib + IntrinsicLib + +# +# Remove these [BuildOptions] after this library is cleaned up +# +[BuildOptions] + # + # suppress the following warnings so we do not break the build with warnings-as-errors: + # C4090: 'function' : different 'const' qualifiers + # C4718: 'function call' : recursive call has no side effects, deleting + # + MSFT:*_*_*_CC_FLAGS = /wd4090 /wd4718 + + # -JCryptoPkg/Include : To disable the use of the system includes provided by RVCT + # --diag_remark=1 : Reduce severity of "#1-D: last line of file ends without a newline" + RVCT:*_*_ARM_CC_FLAGS = -JCryptoPkg/Include --diag_remark=1 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.uni new file mode 100644 index 0000000..b8b09b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.uni @@ -0,0 +1,31 @@ +// /** @file +// Cryptographic Library Instance for PEIM. +// +// Caution: This module requires additional review when modified. +// This library will have external input - signature. +// This external input must be validated carefully to avoid security issues such as +// buffer overflow or integer overflow. +// +// Note: MD4 Digest functions, HMAC-MD5 functions, HMAC-SHA1 functions, AES/ +// TDES/ARC4 functions, RSA external functions, PKCS#7 SignedData sign functions, +// Diffie-Hellman functions, X.509 certificate handler functions, authenticode +// signature verification functions, PEM handler functions, and pseudorandom number +// generator functions are not supported in this instance. +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Cryptographic Library Instance for PEIM" + +#string STR_MODULE_DESCRIPTION #language en-US "Caution: This module requires additional review when modified. This library will have external input - signature. This external input must be validated carefully to avoid security issues such as buffer overflow or integer overflow. Note: MD4 Digest functions, HMAC-MD5 functions, HMAC-SHA1 functions, AES/ TDES/ARC4 functions, RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, X.509 certificate handler functions, authenticode signature verification functions, PEM handler functions, and pseudorandom number generator functions are not supported in this instance." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c new file mode 100644 index 0000000..e3edc34 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c @@ -0,0 +1,135 @@ +/** @file + PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Callback function for password phrase conversion used for retrieving the encrypted PEM. + + @param[out] Buf Pointer to the buffer to write the passphrase to. + @param[in] Size Maximum length of the passphrase (i.e. the size of Buf). + @param[in] Flag A flag which is set to 0 when reading and 1 when writing. + @param[in] Key Key data to be passed to the callback routine. + + @retval The number of characters in the passphrase or 0 if an error occurred. + +**/ +INTN +PasswordCallback ( + OUT CHAR8 *Buf, + IN INTN Size, + IN INTN Flag, + IN VOID *Key + ) +{ + INTN KeyLength; + + ZeroMem ((VOID *) Buf, (UINTN) Size); + if (Key != NULL) { + // + // Duplicate key phrase directly. + // + KeyLength = (INTN) AsciiStrLen ((CHAR8 *)Key); + KeyLength = (KeyLength > Size ) ? Size : KeyLength; + CopyMem (Buf, Key, (UINTN) KeyLength); + return KeyLength; + } else { + return 0; + } +} + +/** + Retrieve the RSA Private Key from the password-protected PEM key data. + + @param[in] PemData Pointer to the PEM-encoded key data to be retrieved. + @param[in] PemSize Size of the PEM key data in bytes. + @param[in] Password NULL-terminated passphrase used for encrypted PEM key data. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA private key component. Use RsaFree() function to free the + resource. + + If PemData is NULL, then return FALSE. + If RsaContext is NULL, then return FALSE. + + @retval TRUE RSA Private Key was retrieved successfully. + @retval FALSE Invalid PEM key data or incorrect password. + +**/ +BOOLEAN +EFIAPI +RsaGetPrivateKeyFromPem ( + IN CONST UINT8 *PemData, + IN UINTN PemSize, + IN CONST CHAR8 *Password, + OUT VOID **RsaContext + ) +{ + BOOLEAN Status; + BIO *PemBio; + + // + // Check input parameters. + // + if (PemData == NULL || RsaContext == NULL || PemSize > INT_MAX) { + return FALSE; + } + + // + // Add possible block-cipher descriptor for PEM data decryption. + // NOTE: Only support most popular ciphers (3DES, AES) for the encrypted PEM. + // + if (EVP_add_cipher (EVP_des_ede3_cbc ()) == 0) { + return FALSE; + } + if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) { + return FALSE; + } + if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) { + return FALSE; + } + if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) { + return FALSE; + } + + Status = FALSE; + + // + // Read encrypted PEM Data. + // + PemBio = BIO_new (BIO_s_mem ()); + if (PemBio == NULL) { + goto _Exit; + } + + if (BIO_write (PemBio, PemData, (int) PemSize) <= 0) { + goto _Exit; + } + + // + // Retrieve RSA Private Key from encrypted PEM data. + // + *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *) &PasswordCallback, (void *) Password); + if (*RsaContext != NULL) { + Status = TRUE; + } + +_Exit: + // + // Release Resources. + // + BIO_free (PemBio); + + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c new file mode 100644 index 0000000..db8f43e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c @@ -0,0 +1,44 @@ +/** @file + PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation which does + not provide real capabilities. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Retrieve the RSA Private Key from the password-protected PEM key data. + + Return FALSE to indicate this interface is not supported. + + @param[in] PemData Pointer to the PEM-encoded key data to be retrieved. + @param[in] PemSize Size of the PEM key data in bytes. + @param[in] Password NULL-terminated passphrase used for encrypted PEM key data. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA private key component. Use RsaFree() function to free the + resource. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetPrivateKeyFromPem ( + IN CONST UINT8 *PemData, + IN UINTN PemSize, + IN CONST CHAR8 *Password, + OUT VOID **RsaContext + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c new file mode 100644 index 0000000..a451f32 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c @@ -0,0 +1,198 @@ +/** @file + Authenticode Portable Executable Signature Verification over OpenSSL. + + Caution: This module requires additional review when modified. + This library will have external input - signature (e.g. PE/COFF Authenticode). + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + AuthenticodeVerify() will get PE/COFF Authenticode and will do basic check for + data structure. + +Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include + +// +// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID +// +UINT8 mSpcIndirectOidValue[] = { + 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04 + }; + +/** + Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows + Authenticode Portable Executable Signature Format". + + If AuthData is NULL, then return FALSE. + If ImageHash is NULL, then return FALSE. + + Caution: This function may receive untrusted input. + PE/COFF Authenticode is external input, so this function will do basic check for + Authenticode data structure. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[in] ImageHash Pointer to the original image file hash value. The procedure + for calculating the image hash value is described in Authenticode + specification. + @param[in] HashSize Size of Image hash value in bytes. + + @retval TRUE The specified Authenticode Signature is valid. + @retval FALSE Invalid Authenticode Signature. + +**/ +BOOLEAN +EFIAPI +AuthenticodeVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN CONST UINT8 *ImageHash, + IN UINTN HashSize + ) +{ + BOOLEAN Status; + PKCS7 *Pkcs7; + CONST UINT8 *Temp; + CONST UINT8 *OrigAuthData; + UINT8 *SpcIndirectDataContent; + UINT8 Asn1Byte; + UINTN ContentSize; + CONST UINT8 *SpcIndirectDataOid; + + // + // Check input parameters. + // + if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) { + return FALSE; + } + + if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) { + return FALSE; + } + + Status = FALSE; + Pkcs7 = NULL; + OrigAuthData = AuthData; + + // + // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature + // + Temp = AuthData; + Pkcs7 = d2i_PKCS7 (NULL, &Temp, (int)DataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + // + // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to + // some authenticode-specific structure. Use opaque ASN.1 string to retrieve + // PKCS#7 ContentInfo here. + // + SpcIndirectDataOid = OBJ_get0_data(Pkcs7->d.sign->contents->type); + if (OBJ_length(Pkcs7->d.sign->contents->type) != sizeof(mSpcIndirectOidValue) || + CompareMem ( + SpcIndirectDataOid, + mSpcIndirectOidValue, + sizeof (mSpcIndirectOidValue) + ) != 0) { + // + // Un-matched SPC_INDIRECT_DATA_OBJID. + // + goto _Exit; + } + + + SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data); + + // + // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent. + // + Asn1Byte = *(SpcIndirectDataContent + 1); + + if ((Asn1Byte & 0x80) == 0) { + // + // Short Form of Length Encoding (Length < 128) + // + ContentSize = (UINTN) (Asn1Byte & 0x7F); + // + // Skip the SEQUENCE Tag; + // + SpcIndirectDataContent += 2; + + } else if ((Asn1Byte & 0x81) == 0x81) { + // + // Long Form of Length Encoding (128 <= Length < 255, Single Octet) + // + ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); + // + // Skip the SEQUENCE Tag; + // + SpcIndirectDataContent += 3; + + } else if ((Asn1Byte & 0x82) == 0x82) { + // + // Long Form of Length Encoding (Length > 255, Two Octet) + // + ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); + ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3)); + // + // Skip the SEQUENCE Tag; + // + SpcIndirectDataContent += 4; + + } else { + goto _Exit; + } + + // + // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent + // defined in Authenticode + // NOTE: Need to double-check HashLength here! + // + if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) { + // + // Un-matched PE/COFF Hash Value + // + goto _Exit; + } + + // + // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature + // + Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize); + +_Exit: + // + // Release Resources + // + PKCS7_free (Pkcs7); + + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticodeNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticodeNull.c new file mode 100644 index 0000000..d0f3440 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticodeNull.c @@ -0,0 +1,51 @@ +/** @file + Authenticode Portable Executable Signature Verification which does not provide + real capabilities. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows + Authenticode Portable Executable Signature Format". + + Return FALSE to indicate this interface is not supported. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[in] ImageHash Pointer to the original image file hash value. The procedure + for calculating the image hash value is described in Authenticode + specification. + @param[in] HashSize Size of Image hash value in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +AuthenticodeVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN CONST UINT8 *ImageHash, + IN UINTN HashSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDh.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDh.c new file mode 100644 index 0000000..7f17388 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDh.c @@ -0,0 +1,312 @@ +/** @file + Diffie-Hellman Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include + +/** + Allocates and Initializes one Diffie-Hellman Context for subsequent use. + + @return Pointer to the Diffie-Hellman Context that has been initialized. + If the allocations fails, DhNew() returns NULL. + +**/ +VOID * +EFIAPI +DhNew ( + VOID + ) +{ + // + // Allocates & Initializes DH Context by OpenSSL DH_new() + // + return (VOID *) DH_new (); +} + +/** + Release the specified DH context. + + If DhContext is NULL, then return FALSE. + + @param[in] DhContext Pointer to the DH context to be released. + +**/ +VOID +EFIAPI +DhFree ( + IN VOID *DhContext + ) +{ + // + // Free OpenSSL DH Context + // + DH_free ((DH *) DhContext); +} + +/** + Generates DH parameter. + + Given generator g, and length of prime number p in bits, this function generates p, + and sets DH context according to value of g and p. + + Before this function can be invoked, pseudorandom number generator must be correctly + initialized by RandomSeed(). + + If DhContext is NULL, then return FALSE. + If Prime is NULL, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] Generator Value of generator. + @param[in] PrimeLength Length in bits of prime to be generated. + @param[out] Prime Pointer to the buffer to receive the generated prime number. + + @retval TRUE DH parameter generation succeeded. + @retval FALSE Value of Generator is not supported. + @retval FALSE PRNG fails to generate random prime number with PrimeLength. + +**/ +BOOLEAN +EFIAPI +DhGenerateParameter ( + IN OUT VOID *DhContext, + IN UINTN Generator, + IN UINTN PrimeLength, + OUT UINT8 *Prime + ) +{ + BOOLEAN RetVal; + BIGNUM *BnP; + + // + // Check input parameters. + // + if (DhContext == NULL || Prime == NULL || PrimeLength > INT_MAX) { + return FALSE; + } + + if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) { + return FALSE; + } + + RetVal = (BOOLEAN) DH_generate_parameters_ex (DhContext, (UINT32) PrimeLength, (UINT32) Generator, NULL); + if (!RetVal) { + return FALSE; + } + + DH_get0_pqg (DhContext, (const BIGNUM **)&BnP, NULL, NULL); + BN_bn2bin (BnP, Prime); + + return TRUE; +} + +/** + Sets generator and prime parameters for DH. + + Given generator g, and prime number p, this function and sets DH + context accordingly. + + If DhContext is NULL, then return FALSE. + If Prime is NULL, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] Generator Value of generator. + @param[in] PrimeLength Length in bits of prime to be generated. + @param[in] Prime Pointer to the prime number. + + @retval TRUE DH parameter setting succeeded. + @retval FALSE Value of Generator is not supported. + @retval FALSE Value of Generator is not suitable for the Prime. + @retval FALSE Value of Prime is not a prime number. + @retval FALSE Value of Prime is not a safe prime number. + +**/ +BOOLEAN +EFIAPI +DhSetParameter ( + IN OUT VOID *DhContext, + IN UINTN Generator, + IN UINTN PrimeLength, + IN CONST UINT8 *Prime + ) +{ + DH *Dh; + BIGNUM *BnP; + BIGNUM *BnG; + + // + // Check input parameters. + // + if (DhContext == NULL || Prime == NULL || PrimeLength > INT_MAX) { + return FALSE; + } + + if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) { + return FALSE; + } + + // + // Set the generator and prime parameters for DH object. + // + Dh = (DH *)DhContext; + BnP = BN_bin2bn ((const unsigned char *)Prime, (int)(PrimeLength / 8), NULL); + BnG = BN_bin2bn ((const unsigned char *)&Generator, 1, NULL); + if ((BnP == NULL) || (BnG == NULL) || !DH_set0_pqg (Dh, BnP, NULL, BnG)) { + goto Error; + } + + return TRUE; + +Error: + BN_free (BnP); + BN_free (BnG); + + return FALSE; +} + +/** + Generates DH public key. + + This function generates random secret exponent, and computes the public key, which is + returned via parameter PublicKey and PublicKeySize. DH context is updated accordingly. + If the PublicKey buffer is too small to hold the public key, FALSE is returned and + PublicKeySize is set to the required buffer size to obtain the public key. + + If DhContext is NULL, then return FALSE. + If PublicKeySize is NULL, then return FALSE. + If PublicKeySize is large enough but PublicKey is NULL, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[out] PublicKey Pointer to the buffer to receive generated public key. + @param[in, out] PublicKeySize On input, the size of PublicKey buffer in bytes. + On output, the size of data returned in PublicKey buffer in bytes. + + @retval TRUE DH public key generation succeeded. + @retval FALSE DH public key generation failed. + @retval FALSE PublicKeySize is not large enough. + +**/ +BOOLEAN +EFIAPI +DhGenerateKey ( + IN OUT VOID *DhContext, + OUT UINT8 *PublicKey, + IN OUT UINTN *PublicKeySize + ) +{ + BOOLEAN RetVal; + DH *Dh; + BIGNUM *DhPubKey; + INTN Size; + + // + // Check input parameters. + // + if (DhContext == NULL || PublicKeySize == NULL) { + return FALSE; + } + + if (PublicKey == NULL && *PublicKeySize != 0) { + return FALSE; + } + + Dh = (DH *) DhContext; + + RetVal = (BOOLEAN) DH_generate_key (DhContext); + if (RetVal) { + DH_get0_key (Dh, (const BIGNUM **)&DhPubKey, NULL); + Size = BN_num_bytes (DhPubKey); + if ((Size > 0) && (*PublicKeySize < (UINTN) Size)) { + *PublicKeySize = Size; + return FALSE; + } + + if (PublicKey != NULL) { + BN_bn2bin (DhPubKey, PublicKey); + } + *PublicKeySize = Size; + } + + return RetVal; +} + +/** + Computes exchanged common key. + + Given peer's public key, this function computes the exchanged common key, based on its own + context including value of prime modulus and random secret exponent. + + If DhContext is NULL, then return FALSE. + If PeerPublicKey is NULL, then return FALSE. + If KeySize is NULL, then return FALSE. + If Key is NULL, then return FALSE. + If KeySize is not large enough, then return FALSE. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] PeerPublicKey Pointer to the peer's public key. + @param[in] PeerPublicKeySize Size of peer's public key in bytes. + @param[out] Key Pointer to the buffer to receive generated key. + @param[in, out] KeySize On input, the size of Key buffer in bytes. + On output, the size of data returned in Key buffer in bytes. + + @retval TRUE DH exchanged key generation succeeded. + @retval FALSE DH exchanged key generation failed. + @retval FALSE KeySize is not large enough. + +**/ +BOOLEAN +EFIAPI +DhComputeKey ( + IN OUT VOID *DhContext, + IN CONST UINT8 *PeerPublicKey, + IN UINTN PeerPublicKeySize, + OUT UINT8 *Key, + IN OUT UINTN *KeySize + ) +{ + BIGNUM *Bn; + INTN Size; + + // + // Check input parameters. + // + if (DhContext == NULL || PeerPublicKey == NULL || KeySize == NULL || Key == NULL) { + return FALSE; + } + + if (PeerPublicKeySize > INT_MAX) { + return FALSE; + } + + Bn = BN_bin2bn (PeerPublicKey, (UINT32) PeerPublicKeySize, NULL); + if (Bn == NULL) { + return FALSE; + } + + Size = DH_compute_key (Key, Bn, DhContext); + if (Size < 0) { + BN_free (Bn); + return FALSE; + } + + if (*KeySize < (UINTN) Size) { + *KeySize = Size; + BN_free (Bn); + return FALSE; + } + + *KeySize = Size; + BN_free (Bn); + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDhNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDhNull.c new file mode 100644 index 0000000..d577cca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptDhNull.c @@ -0,0 +1,156 @@ +/** @file + Diffie-Hellman Wrapper Implementation which does not provide + real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Allocates and Initializes one Diffie-Hellman Context for subsequent use. + + @return Pointer to the Diffie-Hellman Context that has been initialized. + If the interface is not supported, DhNew() returns NULL. + +**/ +VOID * +EFIAPI +DhNew ( + VOID + ) +{ + ASSERT (FALSE); + return NULL; +} + +/** + Release the specified DH context. + + If the interface is not supported, then ASSERT(). + + @param[in] DhContext Pointer to the DH context to be released. + +**/ +VOID +EFIAPI +DhFree ( + IN VOID *DhContext + ) +{ + ASSERT (FALSE); +} + +/** + Generates DH parameter. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] Generator Value of generator. + @param[in] PrimeLength Length in bits of prime to be generated. + @param[out] Prime Pointer to the buffer to receive the generated prime number. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhGenerateParameter ( + IN OUT VOID *DhContext, + IN UINTN Generator, + IN UINTN PrimeLength, + OUT UINT8 *Prime + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Sets generator and prime parameters for DH. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] Generator Value of generator. + @param[in] PrimeLength Length in bits of prime to be generated. + @param[in] Prime Pointer to the prime number. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhSetParameter ( + IN OUT VOID *DhContext, + IN UINTN Generator, + IN UINTN PrimeLength, + IN CONST UINT8 *Prime + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Generates DH public key. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] DhContext Pointer to the DH context. + @param[out] PublicKey Pointer to the buffer to receive generated public key. + @param[in, out] PublicKeySize On input, the size of PublicKey buffer in bytes. + On output, the size of data returned in PublicKey buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhGenerateKey ( + IN OUT VOID *DhContext, + OUT UINT8 *PublicKey, + IN OUT UINTN *PublicKeySize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Computes exchanged common key. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] DhContext Pointer to the DH context. + @param[in] PeerPublicKey Pointer to the peer's public key. + @param[in] PeerPublicKeySize Size of peer's public key in bytes. + @param[out] Key Pointer to the buffer to receive generated key. + @param[in, out] KeySize On input, the size of Key buffer in bytes. + On output, the size of data returned in Key buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +DhComputeKey ( + IN OUT VOID *DhContext, + IN CONST UINT8 *PeerPublicKey, + IN UINTN PeerPublicKeySize, + OUT UINT8 *Key, + IN OUT UINTN *KeySize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2.c new file mode 100644 index 0000000..ffe0cea --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2.c @@ -0,0 +1,101 @@ +/** @file + PBKDF2 Key Derivation Function Wrapper Implementation over OpenSSL. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include + +/** + Derives a key from a password using a salt and iteration count, based on PKCS#5 v2.0 + password based encryption key derivation function PBKDF2, as specified in RFC 2898. + + If Password or Salt or OutKey is NULL, then return FALSE. + If the hash algorithm could not be determined, then return FALSE. + + @param[in] PasswordLength Length of input password in bytes. + @param[in] Password Pointer to the array for the password. + @param[in] SaltLength Size of the Salt in bytes. + @param[in] Salt Pointer to the Salt. + @param[in] IterationCount Number of iterations to perform. Its value should be + greater than or equal to 1. + @param[in] DigestSize Size of the message digest to be used (eg. SHA256_DIGEST_SIZE). + NOTE: DigestSize will be used to determine the hash algorithm. + Only SHA1_DIGEST_SIZE or SHA256_DIGEST_SIZE is supported. + @param[in] KeyLength Size of the derived key buffer in bytes. + @param[out] OutKey Pointer to the output derived key buffer. + + @retval TRUE A key was derived successfully. + @retval FALSE One of the pointers was NULL or one of the sizes was too large. + @retval FALSE The hash algorithm could not be determined from the digest size. + @retval FALSE The key derivation operation failed. + +**/ +BOOLEAN +EFIAPI +Pkcs5HashPassword ( + IN UINTN PasswordLength, + IN CONST CHAR8 *Password, + IN UINTN SaltLength, + IN CONST UINT8 *Salt, + IN UINTN IterationCount, + IN UINTN DigestSize, + IN UINTN KeyLength, + OUT UINT8 *OutKey + ) +{ + CONST EVP_MD *HashAlg; + + HashAlg = NULL; + + // + // Parameter Checking. + // + if ((Password == NULL) || (Salt == NULL) || (OutKey == NULL)) { + return FALSE; + } + if ((PasswordLength == 0) || (PasswordLength > INT_MAX) || + (SaltLength == 0) || (SaltLength > INT_MAX) || + (KeyLength == 0) || (KeyLength > INT_MAX) || + (IterationCount < 1) || (IterationCount > INT_MAX)) { + return FALSE; + } + // + // Make sure the digest algorithm is supported. + // + switch (DigestSize) { + case SHA1_DIGEST_SIZE: + HashAlg = EVP_sha1(); + break; + case SHA256_DIGEST_SIZE: + HashAlg = EVP_sha256(); + break; + default: + return FALSE; + break; + } + + // + // Perform password-based key derivation routines. + // + return (BOOLEAN)PKCS5_PBKDF2_HMAC ( + (const char *)Password, + (int)PasswordLength, + (const unsigned char *)Salt, + (int)SaltLength, + (int)IterationCount, + HashAlg, + (int)KeyLength, + (unsigned char *)OutKey + ); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2Null.c new file mode 100644 index 0000000..502dd3c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs5Pbkdf2Null.c @@ -0,0 +1,56 @@ +/** @file + PBKDF2 Key Derivation Function Wrapper Implementation which does not provide real + capabilities. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include + +/** + Derives a key from a password using a salt and iteration count, based on PKCS#5 v2.0 + password based encryption key derivation function PBKDF2, as specified in RFC 2898. + + Return FALSE to indicate this interface is not supported. + + @param[in] PasswordLength Length of input password in bytes. + @param[in] Password Pointer to the array for the password. + @param[in] SaltLength Size of the Salt in bytes. + @param[in] Salt Pointer to the Salt. + @param[in] IterationCount Number of iterations to perform. Its value should be + greater than or equal to 1. + @param[in] DigestSize Size of the message digest to be used (eg. SHA256_DIGEST_SIZE). + NOTE: DigestSize will be used to determine the hash algorithm. + Only SHA1_DIGEST_SIZE or SHA256_DIGEST_SIZE is supported. + @param[in] KeyLength Size of the derived key buffer in bytes. + @param[out] OutKey Pointer to the output derived key buffer. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs5HashPassword ( + IN UINTN PasswordLength, + IN CONST CHAR8 *Password, + IN UINTN SaltLength, + IN CONST UINT8 *Salt, + IN UINTN IterationCount, + IN UINTN DigestSize, + IN UINTN KeyLength, + OUT UINT8 *OutKey + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c new file mode 100644 index 0000000..11becdd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c @@ -0,0 +1,200 @@ +/** @file + PKCS#7 SignedData Sign Wrapper Implementation over OpenSSL. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include + +/** + Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message + Syntax Standard, version 1.5". This interface is only intended to be used for + application to perform PKCS#7 functionality validation. + + @param[in] PrivateKey Pointer to the PEM-formatted private key data for + data signing. + @param[in] PrivateKeySize Size of the PEM private key data in bytes. + @param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM + key data. + @param[in] InData Pointer to the content to be signed. + @param[in] InDataSize Size of InData in bytes. + @param[in] SignCert Pointer to signer's DER-encoded certificate to sign with. + @param[in] OtherCerts Pointer to an optional additional set of certificates to + include in the PKCS#7 signedData (e.g. any intermediate + CAs in the chain). + @param[out] SignedData Pointer to output PKCS#7 signedData. It's caller's + responsibility to free the buffer with FreePool(). + @param[out] SignedDataSize Size of SignedData in bytes. + + @retval TRUE PKCS#7 data signing succeeded. + @retval FALSE PKCS#7 data signing failed. + +**/ +BOOLEAN +EFIAPI +Pkcs7Sign ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN CONST UINT8 *KeyPassword, + IN UINT8 *InData, + IN UINTN InDataSize, + IN UINT8 *SignCert, + IN UINT8 *OtherCerts OPTIONAL, + OUT UINT8 **SignedData, + OUT UINTN *SignedDataSize + ) +{ + BOOLEAN Status; + EVP_PKEY *Key; + BIO *DataBio; + PKCS7 *Pkcs7; + UINT8 *RsaContext; + UINT8 *P7Data; + UINTN P7DataSize; + UINT8 *Tmp; + + // + // Check input parameters. + // + if (PrivateKey == NULL || KeyPassword == NULL || InData == NULL || + SignCert == NULL || SignedData == NULL || SignedDataSize == NULL || InDataSize > INT_MAX) { + return FALSE; + } + + RsaContext = NULL; + Key = NULL; + Pkcs7 = NULL; + DataBio = NULL; + Status = FALSE; + + // + // Retrieve RSA private key from PEM data. + // + Status = RsaGetPrivateKeyFromPem ( + PrivateKey, + PrivateKeySize, + (CONST CHAR8 *) KeyPassword, + (VOID **) &RsaContext + ); + if (!Status) { + return Status; + } + + Status = FALSE; + + // + // Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling + // + if (EVP_add_digest (EVP_md5 ()) == 0) { + goto _Exit; + } + if (EVP_add_digest (EVP_sha1 ()) == 0) { + goto _Exit; + } + if (EVP_add_digest (EVP_sha256 ()) == 0) { + goto _Exit; + } + + RandomSeed (NULL, 0); + + // + // Construct OpenSSL EVP_PKEY for private key. + // + Key = EVP_PKEY_new (); + if (Key == NULL) { + goto _Exit; + } + if (EVP_PKEY_assign_RSA (Key, (RSA *) RsaContext) == 0) { + goto _Exit; + } + + // + // Convert the data to be signed to BIO format. + // + DataBio = BIO_new (BIO_s_mem ()); + if (DataBio == NULL) { + goto _Exit; + } + + if (BIO_write (DataBio, InData, (int) InDataSize) <= 0) { + goto _Exit; + } + + // + // Create the PKCS#7 signedData structure. + // + Pkcs7 = PKCS7_sign ( + (X509 *) SignCert, + Key, + (STACK_OF(X509) *) OtherCerts, + DataBio, + PKCS7_BINARY | PKCS7_NOATTR | PKCS7_DETACHED + ); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Convert PKCS#7 signedData structure into DER-encoded buffer. + // + P7DataSize = i2d_PKCS7 (Pkcs7, NULL); + if (P7DataSize <= 19) { + goto _Exit; + } + + P7Data = malloc (P7DataSize); + if (P7Data == NULL) { + goto _Exit; + } + + Tmp = P7Data; + P7DataSize = i2d_PKCS7 (Pkcs7, (unsigned char **) &Tmp); + ASSERT (P7DataSize > 19); + + // + // Strip ContentInfo to content only for signeddata. The data be trimmed off + // is totally 19 bytes. + // + *SignedDataSize = P7DataSize - 19; + *SignedData = AllocatePool (*SignedDataSize); + if (*SignedData == NULL) { + OPENSSL_free (P7Data); + goto _Exit; + } + + CopyMem (*SignedData, P7Data + 19, *SignedDataSize); + + OPENSSL_free (P7Data); + + Status = TRUE; + +_Exit: + // + // Release Resources + // + if (Key != NULL) { + EVP_PKEY_free (Key); + } + + if (DataBio != NULL) { + BIO_free (DataBio); + } + + if (Pkcs7 != NULL) { + PKCS7_free (Pkcs7); + } + + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7SignNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7SignNull.c new file mode 100644 index 0000000..830dbb4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7SignNull.c @@ -0,0 +1,60 @@ +/** @file + PKCS#7 SignedData Sign Wrapper Implementation which does not provide real + capabilities. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message + Syntax Standard, version 1.5". This interface is only intended to be used for + application to perform PKCS#7 functionality validation. + + Return FALSE to indicate this interface is not supported. + + @param[in] PrivateKey Pointer to the PEM-formatted private key data for + data signing. + @param[in] PrivateKeySize Size of the PEM private key data in bytes. + @param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM + key data. + @param[in] InData Pointer to the content to be signed. + @param[in] InDataSize Size of InData in bytes. + @param[in] SignCert Pointer to signer's DER-encoded certificate to sign with. + @param[in] OtherCerts Pointer to an optional additional set of certificates to + include in the PKCS#7 signedData (e.g. any intermediate + CAs in the chain). + @param[out] SignedData Pointer to output PKCS#7 signedData. It's caller's + responsibility to free the buffer with FreePool(). + @param[out] SignedDataSize Size of SignedData in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7Sign ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN CONST UINT8 *KeyPassword, + IN UINT8 *InData, + IN UINTN InDataSize, + IN UINT8 *SignCert, + IN UINT8 *OtherCerts OPTIONAL, + OUT UINT8 **SignedData, + OUT UINTN *SignedDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyBase.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyBase.c new file mode 100644 index 0000000..ce2b49f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyBase.c @@ -0,0 +1,131 @@ +/** @file + Non-runtime specific implementation of PKCS#7 SignedData Verification Wrapper. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include +#include + +/** + Extracts the attached content from a PKCS#7 signed data if existed. The input signed + data could be wrapped in a ContentInfo structure. + + If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow, + then return FALSE. If the P7Data is not correctly formatted, then return FALSE. + + Caution: This function may receive untrusted input. So this function will do + basic check for PKCS#7 data structure. + + @param[in] P7Data Pointer to the PKCS#7 signed data to process. + @param[in] P7Length Length of the PKCS#7 signed data in bytes. + @param[out] Content Pointer to the extracted content from the PKCS#7 signedData. + It's caller's responsibility to free the buffer with FreePool(). + @param[out] ContentSize The size of the extracted content in bytes. + + @retval TRUE The P7Data was correctly formatted for processing. + @retval FALSE The P7Data was not correctly formatted for processing. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetAttachedContent ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT VOID **Content, + OUT UINTN *ContentSize + ) +{ + BOOLEAN Status; + PKCS7 *Pkcs7; + UINT8 *SignedData; + UINTN SignedDataSize; + BOOLEAN Wrapped; + CONST UINT8 *Temp; + ASN1_OCTET_STRING *OctStr; + + // + // Check input parameter. + // + if ((P7Data == NULL) || (P7Length > INT_MAX) || (Content == NULL) || (ContentSize == NULL)) { + return FALSE; + } + + *Content = NULL; + Pkcs7 = NULL; + SignedData = NULL; + OctStr = NULL; + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status || (SignedDataSize > INT_MAX)) { + goto _Exit; + } + + Status = FALSE; + + // + // Decoding PKCS#7 SignedData + // + Temp = SignedData; + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (int)SignedDataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // The type of Pkcs7 must be signedData + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + // + // Check for detached or attached content + // + if (PKCS7_get_detached (Pkcs7)) { + // + // No Content supplied for PKCS7 detached signedData + // + *Content = NULL; + *ContentSize = 0; + } else { + // + // Retrieve the attached content in PKCS7 signedData + // + OctStr = Pkcs7->d.sign->contents->d.data; + if ((OctStr->length > 0) && (OctStr->data != NULL)) { + *ContentSize = OctStr->length; + *Content = AllocatePool (*ContentSize); + if (*Content == NULL) { + *ContentSize = 0; + goto _Exit; + } + CopyMem (*Content, OctStr->data, *ContentSize); + } + } + Status = TRUE; + +_Exit: + // + // Release Resources + // + PKCS7_free (Pkcs7); + + if (!Wrapped) { + OPENSSL_free (SignedData); + } + + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c new file mode 100644 index 0000000..0fb3107 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c @@ -0,0 +1,916 @@ +/** @file + PKCS#7 SignedData Verification Wrapper Implementation over OpenSSL. + + Caution: This module requires additional review when modified. + This library will have external input - signature (e.g. UEFI Authenticated + Variable). It may by input in SMM mode. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + WrapPkcs7Data(), Pkcs7GetSigners(), Pkcs7Verify() will get UEFI Authenticated + Variable and will do basic check for data structure. + +Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include +#include + +UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 }; + +/** + Check input P7Data is a wrapped ContentInfo structure or not. If not construct + a new structure to wrap P7Data. + + Caution: This function may receive untrusted input. + UEFI Authenticated Variable is external input, so this function will do basic + check for PKCS#7 data structure. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise + return FALSE. + @param[out] WrapData If return status of this function is TRUE: + 1) when WrapFlag is TRUE, pointer to P7Data. + 2) when WrapFlag is FALSE, pointer to a new ContentInfo + structure. It's caller's responsibility to free this + buffer. + @param[out] WrapDataSize Length of ContentInfo structure in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE The operation is failed due to lack of resources. + +**/ +BOOLEAN +WrapPkcs7Data ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT BOOLEAN *WrapFlag, + OUT UINT8 **WrapData, + OUT UINTN *WrapDataSize + ) +{ + BOOLEAN Wrapped; + UINT8 *SignedData; + + // + // Check whether input P7Data is a wrapped ContentInfo structure or not. + // + Wrapped = FALSE; + if ((P7Data[4] == 0x06) && (P7Data[5] == 0x09)) { + if (CompareMem (P7Data + 6, mOidValue, sizeof (mOidValue)) == 0) { + if ((P7Data[15] == 0xA0) && (P7Data[16] == 0x82)) { + Wrapped = TRUE; + } + } + } + + if (Wrapped) { + *WrapData = (UINT8 *) P7Data; + *WrapDataSize = P7Length; + } else { + // + // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes. + // + *WrapDataSize = P7Length + 19; + *WrapData = malloc (*WrapDataSize); + if (*WrapData == NULL) { + *WrapFlag = Wrapped; + return FALSE; + } + + SignedData = *WrapData; + + // + // Part1: 0x30, 0x82. + // + SignedData[0] = 0x30; + SignedData[1] = 0x82; + + // + // Part2: Length1 = P7Length + 19 - 4, in big endian. + // + SignedData[2] = (UINT8) (((UINT16) (*WrapDataSize - 4)) >> 8); + SignedData[3] = (UINT8) (((UINT16) (*WrapDataSize - 4)) & 0xff); + + // + // Part3: 0x06, 0x09. + // + SignedData[4] = 0x06; + SignedData[5] = 0x09; + + // + // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02. + // + CopyMem (SignedData + 6, mOidValue, sizeof (mOidValue)); + + // + // Part5: 0xA0, 0x82. + // + SignedData[15] = 0xA0; + SignedData[16] = 0x82; + + // + // Part6: Length2 = P7Length, in big endian. + // + SignedData[17] = (UINT8) (((UINT16) P7Length) >> 8); + SignedData[18] = (UINT8) (((UINT16) P7Length) & 0xff); + + // + // Part7: P7Data. + // + CopyMem (SignedData + 19, P7Data, P7Length); + } + + *WrapFlag = Wrapped; + return TRUE; +} + +/** + Pop single certificate from STACK_OF(X509). + + If X509Stack, Cert, or CertSize is NULL, then return FALSE. + + @param[in] X509Stack Pointer to a X509 stack object. + @param[out] Cert Pointer to a X509 certificate. + @param[out] CertSize Length of output X509 certificate in bytes. + + @retval TRUE The X509 stack pop succeeded. + @retval FALSE The pop operation failed. + +**/ +BOOLEAN +X509PopCertificate ( + IN VOID *X509Stack, + OUT UINT8 **Cert, + OUT UINTN *CertSize + ) +{ + BIO *CertBio; + X509 *X509Cert; + STACK_OF(X509) *CertStack; + BOOLEAN Status; + INT32 Result; + BUF_MEM *Ptr; + INT32 Length; + VOID *Buffer; + + Status = FALSE; + + if ((X509Stack == NULL) || (Cert == NULL) || (CertSize == NULL)) { + return Status; + } + + CertStack = (STACK_OF(X509) *) X509Stack; + + X509Cert = sk_X509_pop (CertStack); + + if (X509Cert == NULL) { + return Status; + } + + Buffer = NULL; + + CertBio = BIO_new (BIO_s_mem ()); + if (CertBio == NULL) { + return Status; + } + + Result = i2d_X509_bio (CertBio, X509Cert); + if (Result == 0) { + goto _Exit; + } + + BIO_get_mem_ptr (CertBio, &Ptr); + Length = (INT32)(Ptr->length); + if (Length <= 0) { + goto _Exit; + } + + Buffer = malloc (Length); + if (Buffer == NULL) { + goto _Exit; + } + + Result = BIO_read (CertBio, Buffer, Length); + if (Result != Length) { + goto _Exit; + } + + *Cert = Buffer; + *CertSize = Length; + + Status = TRUE; + +_Exit: + + BIO_free (CertBio); + + if (!Status && (Buffer != NULL)) { + free (Buffer); + } + + return Status; +} + +/** + Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then + return FALSE. If P7Length overflow, then return FALSE. + + Caution: This function may receive untrusted input. + UEFI Authenticated Variable is external input, so this function will do basic + check for PKCS#7 data structure. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data. + It's caller's responsibility to free the buffer with + Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] StackLength Length of signer's certificates in bytes. + @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates. + It's caller's responsibility to free the buffer with + Pkcs7FreeSigners(). + @param[out] CertLength Length of the trusted certificate in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSigners ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **CertStack, + OUT UINTN *StackLength, + OUT UINT8 **TrustedCert, + OUT UINTN *CertLength + ) +{ + PKCS7 *Pkcs7; + BOOLEAN Status; + UINT8 *SignedData; + CONST UINT8 *Temp; + UINTN SignedDataSize; + BOOLEAN Wrapped; + STACK_OF(X509) *Stack; + UINT8 Index; + UINT8 *CertBuf; + UINT8 *OldBuf; + UINTN BufferSize; + UINTN OldSize; + UINT8 *SingleCert; + UINTN SingleCertSize; + + if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) || + (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX)) { + return FALSE; + } + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status) { + return Status; + } + + Status = FALSE; + Pkcs7 = NULL; + Stack = NULL; + CertBuf = NULL; + OldBuf = NULL; + SingleCert = NULL; + + // + // Retrieve PKCS#7 Data (DER encoding) + // + if (SignedDataSize > INT_MAX) { + goto _Exit; + } + + Temp = SignedData; + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + Stack = PKCS7_get0_signers(Pkcs7, NULL, PKCS7_BINARY); + if (Stack == NULL) { + goto _Exit; + } + + // + // Convert CertStack to buffer in following format: + // UINT8 CertNumber; + // UINT32 Cert1Length; + // UINT8 Cert1[]; + // UINT32 Cert2Length; + // UINT8 Cert2[]; + // ... + // UINT32 CertnLength; + // UINT8 Certn[]; + // + BufferSize = sizeof (UINT8); + OldSize = BufferSize; + + for (Index = 0; ; Index++) { + Status = X509PopCertificate (Stack, &SingleCert, &SingleCertSize); + if (!Status) { + break; + } + + OldSize = BufferSize; + OldBuf = CertBuf; + BufferSize = OldSize + SingleCertSize + sizeof (UINT32); + CertBuf = malloc (BufferSize); + + if (CertBuf == NULL) { + goto _Exit; + } + + if (OldBuf != NULL) { + CopyMem (CertBuf, OldBuf, OldSize); + free (OldBuf); + OldBuf = NULL; + } + + WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) SingleCertSize); + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize); + + free (SingleCert); + SingleCert = NULL; + } + + if (CertBuf != NULL) { + // + // Update CertNumber. + // + CertBuf[0] = Index; + + *CertLength = BufferSize - OldSize - sizeof (UINT32); + *TrustedCert = malloc (*CertLength); + if (*TrustedCert == NULL) { + goto _Exit; + } + + CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength); + *CertStack = CertBuf; + *StackLength = BufferSize; + Status = TRUE; + } + +_Exit: + // + // Release Resources + // + if (!Wrapped) { + free (SignedData); + } + + if (Pkcs7 != NULL) { + PKCS7_free (Pkcs7); + } + + if (Stack != NULL) { + sk_X509_pop_free(Stack, X509_free); + } + + if (SingleCert != NULL) { + free (SingleCert); + } + + if (!Status && (CertBuf != NULL)) { + free (CertBuf); + *CertStack = NULL; + } + + if (OldBuf != NULL) { + free (OldBuf); + } + + return Status; +} + +/** + Wrap function to use free() to free allocated memory for certificates. + + @param[in] Certs Pointer to the certificates to be freed. + +**/ +VOID +EFIAPI +Pkcs7FreeSigners ( + IN UINT8 *Certs + ) +{ + if (Certs == NULL) { + return; + } + + free (Certs); +} + +/** + Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard", and outputs two certificate lists chained and + unchained to the signer's certificates. + The input signed data could be wrapped in a ContentInfo structure. + + @param[in] P7Data Pointer to the PKCS#7 message. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] SignerChainCerts Pointer to the certificates list chained to signer's + certificate. It's caller's responsibility to free the buffer + with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] ChainLength Length of the chained certificates list buffer in bytes. + @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's + responsibility to free the buffer with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] UnchainLength Length of the unchained certificates list buffer in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetCertificatesList ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **SignerChainCerts, + OUT UINTN *ChainLength, + OUT UINT8 **UnchainCerts, + OUT UINTN *UnchainLength + ) +{ + BOOLEAN Status; + UINT8 *NewP7Data; + UINTN NewP7Length; + BOOLEAN Wrapped; + UINT8 Index; + PKCS7 *Pkcs7; + X509_STORE_CTX *CertCtx; + STACK_OF(X509) *CtxChain; + STACK_OF(X509) *CtxUntrusted; + X509 *CtxCert; + STACK_OF(X509) *Signers; + X509 *Signer; + X509 *Cert; + X509 *Issuer; + X509_NAME *IssuerName; + UINT8 *CertBuf; + UINT8 *OldBuf; + UINTN BufferSize; + UINTN OldSize; + UINT8 *SingleCert; + UINTN CertSize; + + // + // Initializations + // + Status = FALSE; + NewP7Data = NULL; + Pkcs7 = NULL; + CertCtx = NULL; + CtxChain = NULL; + CtxCert = NULL; + CtxUntrusted = NULL; + Cert = NULL; + SingleCert = NULL; + CertBuf = NULL; + OldBuf = NULL; + Signers = NULL; + + ZeroMem (&CertCtx, sizeof (CertCtx)); + + // + // Parameter Checking + // + if ((P7Data == NULL) || (SignerChainCerts == NULL) || (ChainLength == NULL) || + (UnchainCerts == NULL) || (UnchainLength == NULL) || (P7Length > INT_MAX)) { + return Status; + } + + *SignerChainCerts = NULL; + *ChainLength = 0; + *UnchainCerts = NULL; + *UnchainLength = 0; + + // + // Construct a new PKCS#7 data wrapping with ContentInfo structure if needed. + // + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &NewP7Data, &NewP7Length); + if (!Status || (NewP7Length > INT_MAX)) { + goto _Error; + } + + // + // Decodes PKCS#7 SignedData + // + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &NewP7Data, (int) NewP7Length); + if ((Pkcs7 == NULL) || (!PKCS7_type_is_signed (Pkcs7))) { + goto _Error; + } + + // + // Obtains Signer's Certificate from PKCS#7 data + // NOTE: Only one signer case will be handled in this function, which means SignerInfos + // should include only one signer's certificate. + // + Signers = PKCS7_get0_signers (Pkcs7, NULL, PKCS7_BINARY); + if ((Signers == NULL) || (sk_X509_num (Signers) != 1)) { + goto _Error; + } + Signer = sk_X509_value (Signers, 0); + + CertCtx = X509_STORE_CTX_new (); + if (CertCtx == NULL) { + goto _Error; + } + if (!X509_STORE_CTX_init (CertCtx, NULL, Signer, Pkcs7->d.sign->cert)) { + goto _Error; + } + // + // Initialize Chained & Untrusted stack + // + CtxChain = X509_STORE_CTX_get0_chain (CertCtx); + CtxCert = X509_STORE_CTX_get0_cert (CertCtx); + if (CtxChain == NULL) { + if (((CtxChain = sk_X509_new_null ()) == NULL) || + (!sk_X509_push (CtxChain, CtxCert))) { + goto _Error; + } + } + CtxUntrusted = X509_STORE_CTX_get0_untrusted (CertCtx); + if (CtxUntrusted != NULL) { + (VOID)sk_X509_delete_ptr (CtxUntrusted, Signer); + } + + // + // Build certificates stack chained from Signer's certificate. + // + Cert = Signer; + for (; ;) { + // + // Self-Issue checking + // + Issuer = NULL; + if (X509_STORE_CTX_get1_issuer (&Issuer, CertCtx, Cert) == 1) { + if (X509_cmp (Issuer, Cert) == 0) { + break; + } + } + + // + // Found the issuer of the current certificate + // + if (CtxUntrusted != NULL) { + Issuer = NULL; + IssuerName = X509_get_issuer_name (Cert); + Issuer = X509_find_by_subject (CtxUntrusted, IssuerName); + if (Issuer != NULL) { + if (!sk_X509_push (CtxChain, Issuer)) { + goto _Error; + } + (VOID)sk_X509_delete_ptr (CtxUntrusted, Issuer); + + Cert = Issuer; + continue; + } + } + + break; + } + + // + // Converts Chained and Untrusted Certificate to Certificate Buffer in following format: + // UINT8 CertNumber; + // UINT32 Cert1Length; + // UINT8 Cert1[]; + // UINT32 Cert2Length; + // UINT8 Cert2[]; + // ... + // UINT32 CertnLength; + // UINT8 Certn[]; + // + + if (CtxChain != NULL) { + BufferSize = sizeof (UINT8); + CertBuf = NULL; + + for (Index = 0; ; Index++) { + Status = X509PopCertificate (CtxChain, &SingleCert, &CertSize); + if (!Status) { + break; + } + + OldSize = BufferSize; + OldBuf = CertBuf; + BufferSize = OldSize + CertSize + sizeof (UINT32); + CertBuf = malloc (BufferSize); + + if (CertBuf == NULL) { + Status = FALSE; + goto _Error; + } + if (OldBuf != NULL) { + CopyMem (CertBuf, OldBuf, OldSize); + free (OldBuf); + OldBuf = NULL; + } + + WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize); + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize); + + free (SingleCert); + SingleCert = NULL; + } + + if (CertBuf != NULL) { + // + // Update CertNumber. + // + CertBuf[0] = Index; + + *SignerChainCerts = CertBuf; + *ChainLength = BufferSize; + } + } + + if (CtxUntrusted != NULL) { + BufferSize = sizeof (UINT8); + CertBuf = NULL; + + for (Index = 0; ; Index++) { + Status = X509PopCertificate (CtxUntrusted, &SingleCert, &CertSize); + if (!Status) { + break; + } + + OldSize = BufferSize; + OldBuf = CertBuf; + BufferSize = OldSize + CertSize + sizeof (UINT32); + CertBuf = malloc (BufferSize); + + if (CertBuf == NULL) { + Status = FALSE; + goto _Error; + } + if (OldBuf != NULL) { + CopyMem (CertBuf, OldBuf, OldSize); + free (OldBuf); + OldBuf = NULL; + } + + WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize); + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize); + + free (SingleCert); + SingleCert = NULL; + } + + if (CertBuf != NULL) { + // + // Update CertNumber. + // + CertBuf[0] = Index; + + *UnchainCerts = CertBuf; + *UnchainLength = BufferSize; + } + } + + Status = TRUE; + +_Error: + // + // Release Resources. + // + if (!Wrapped && (NewP7Data != NULL)) { + free (NewP7Data); + } + + if (Pkcs7 != NULL) { + PKCS7_free (Pkcs7); + } + sk_X509_free (Signers); + + if (CertCtx != NULL) { + X509_STORE_CTX_cleanup (CertCtx); + X509_STORE_CTX_free (CertCtx); + } + + if (SingleCert != NULL) { + free (SingleCert); + } + + if (OldBuf != NULL) { + free (OldBuf); + } + + if (!Status && (CertBuf != NULL)) { + free (CertBuf); + *SignerChainCerts = NULL; + *UnchainCerts = NULL; + } + + return Status; +} + +/** + Verifies the validity of a PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, TrustedCert or InData is NULL, then return FALSE. + If P7Length, CertLength or DataLength overflow, then return FALSE. + + Caution: This function may receive untrusted input. + UEFI Authenticated Variable is external input, so this function will do basic + check for PKCS#7 data structure. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertLength Length of the trusted certificate in bytes. + @param[in] InData Pointer to the content to be verified. + @param[in] DataLength Length of InData in bytes. + + @retval TRUE The specified PKCS#7 signed data is valid. + @retval FALSE Invalid PKCS#7 signed data. + +**/ +BOOLEAN +EFIAPI +Pkcs7Verify ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + IN CONST UINT8 *TrustedCert, + IN UINTN CertLength, + IN CONST UINT8 *InData, + IN UINTN DataLength + ) +{ + PKCS7 *Pkcs7; + BIO *DataBio; + BOOLEAN Status; + X509 *Cert; + X509_STORE *CertStore; + UINT8 *SignedData; + CONST UINT8 *Temp; + UINTN SignedDataSize; + BOOLEAN Wrapped; + + // + // Check input parameters. + // + if (P7Data == NULL || TrustedCert == NULL || InData == NULL || + P7Length > INT_MAX || CertLength > INT_MAX || DataLength > INT_MAX) { + return FALSE; + } + + Pkcs7 = NULL; + DataBio = NULL; + Cert = NULL; + CertStore = NULL; + + // + // Register & Initialize necessary digest algorithms for PKCS#7 Handling + // + if (EVP_add_digest (EVP_md5 ()) == 0) { + return FALSE; + } + if (EVP_add_digest (EVP_sha1 ()) == 0) { + return FALSE; + } + if (EVP_add_digest (EVP_sha256 ()) == 0) { + return FALSE; + } + if (EVP_add_digest (EVP_sha384 ()) == 0) { + return FALSE; + } + if (EVP_add_digest (EVP_sha512 ()) == 0) { + return FALSE; + } + if (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA) == 0) { + return FALSE; + } + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status) { + return Status; + } + + Status = FALSE; + + // + // Retrieve PKCS#7 Data (DER encoding) + // + if (SignedDataSize > INT_MAX) { + goto _Exit; + } + + Temp = SignedData; + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + // + // Read DER-encoded root certificate and Construct X509 Certificate + // + Temp = TrustedCert; + Cert = d2i_X509 (NULL, &Temp, (long) CertLength); + if (Cert == NULL) { + goto _Exit; + } + + // + // Setup X509 Store for trusted certificate + // + CertStore = X509_STORE_new (); + if (CertStore == NULL) { + goto _Exit; + } + if (!(X509_STORE_add_cert (CertStore, Cert))) { + goto _Exit; + } + + // + // For generic PKCS#7 handling, InData may be NULL if the content is present + // in PKCS#7 structure. So ignore NULL checking here. + // + DataBio = BIO_new (BIO_s_mem ()); + if (DataBio == NULL) { + goto _Exit; + } + + if (BIO_write (DataBio, InData, (int) DataLength) <= 0) { + goto _Exit; + } + + // + // Allow partial certificate chains, terminated by a non-self-signed but + // still trusted intermediate certificate. Also disable time checks. + // + X509_STORE_set_flags (CertStore, + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME); + + // + // OpenSSL PKCS7 Verification by default checks for SMIME (email signing) and + // doesn't support the extended key usage for Authenticode Code Signing. + // Bypass the certificate purpose checking by enabling any purposes setting. + // + X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY); + + // + // Verifies the PKCS#7 signedData structure + // + Status = (BOOLEAN) PKCS7_verify (Pkcs7, NULL, CertStore, DataBio, NULL, PKCS7_BINARY); + +_Exit: + // + // Release Resources + // + BIO_free (DataBio); + X509_free (Cert); + X509_STORE_free (CertStore); + PKCS7_free (Pkcs7); + + if (!Wrapped) { + OPENSSL_free (SignedData); + } + + return Status; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c new file mode 100644 index 0000000..bb32131 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c @@ -0,0 +1,169 @@ +/** @file + PKCS#7 SignedData Verification Wrapper Implementation which does not provide + real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + Return FALSE to indicate this interface is not supported. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data. + It's caller's responsibility to free the buffer with + Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] StackLength Length of signer's certificates in bytes. + @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates. + It's caller's responsibility to free the buffer with + Pkcs7FreeSigners(). + @param[out] CertLength Length of the trusted certificate in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSigners ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **CertStack, + OUT UINTN *StackLength, + OUT UINT8 **TrustedCert, + OUT UINTN *CertLength + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Wrap function to use free() to free allocated memory for certificates. + + If the interface is not supported, then ASSERT(). + + @param[in] Certs Pointer to the certificates to be freed. + +**/ +VOID +EFIAPI +Pkcs7FreeSigners ( + IN UINT8 *Certs + ) +{ + ASSERT (FALSE); +} + +/** + Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard", and outputs two certificate lists chained and + unchained to the signer's certificates. + The input signed data could be wrapped in a ContentInfo structure. + + @param[in] P7Data Pointer to the PKCS#7 message. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] SignerChainCerts Pointer to the certificates list chained to signer's + certificate. It's caller's responsibility to free the buffer + with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] ChainLength Length of the chained certificates list buffer in bytes. + @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's + responsibility to free the buffer with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] UnchainLength Length of the unchained certificates list buffer in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetCertificatesList ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **SignerChainCerts, + OUT UINTN *ChainLength, + OUT UINT8 **UnchainCerts, + OUT UINTN *UnchainLength + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Verifies the validity of a PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + Return FALSE to indicate this interface is not supported. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertLength Length of the trusted certificate in bytes. + @param[in] InData Pointer to the content to be verified. + @param[in] DataLength Length of InData in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7Verify ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + IN CONST UINT8 *TrustedCert, + IN UINTN CertLength, + IN CONST UINT8 *InData, + IN UINTN DataLength + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Extracts the attached content from a PKCS#7 signed data if existed. The input signed + data could be wrapped in a ContentInfo structure. + + Return FALSE to indicate this interface is not supported. + + @param[in] P7Data Pointer to the PKCS#7 signed data to process. + @param[in] P7Length Length of the PKCS#7 signed data in bytes. + @param[out] Content Pointer to the extracted content from the PKCS#7 signedData. + It's caller's responsibility to free the buffer with FreePool(). + @param[out] ContentSize The size of the extracted content in bytes. + + @retval TRUE The P7Data was correctly formatted for processing. + @retval FALSE The P7Data was not correctly formatted for processing. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetAttachedContent ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT VOID **Content, + OUT UINTN *ContentSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyRuntime.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyRuntime.c new file mode 100644 index 0000000..857a40b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyRuntime.c @@ -0,0 +1,45 @@ +/** @file + Runtime specific implementation of PKCS#7 SignedData Verification Wrapper. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Extracts the attached content from a PKCS#7 signed data if existed. The input signed + data could be wrapped in a ContentInfo structure. + + Return FALSE to indicate this interface is not supported. + + @param[in] P7Data Pointer to the PKCS#7 signed data to process. + @param[in] P7Length Length of the PKCS#7 signed data in bytes. + @param[out] Content Pointer to the extracted content from the PKCS#7 signedData. + It's caller's responsibility to free the buffer with FreePool(). + @param[out] ContentSize The size of the extracted content in bytes. + + @retval TRUE The P7Data was correctly formatted for processing. + @retval FALSE The P7Data was not correctly formatted for processing. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetAttachedContent ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT VOID **Content, + OUT UINTN *ContentSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c new file mode 100644 index 0000000..f0d2bb5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c @@ -0,0 +1,325 @@ +/** @file + RSA Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file implements following APIs which provide basic capabilities for RSA: + 1) RsaNew + 2) RsaFree + 3) RsaSetKey + 4) RsaPkcs1Verify + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include + +/** + Allocates and initializes one RSA context for subsequent use. + + @return Pointer to the RSA context that has been initialized. + If the allocations fails, RsaNew() returns NULL. + +**/ +VOID * +EFIAPI +RsaNew ( + VOID + ) +{ + // + // Allocates & Initializes RSA Context by OpenSSL RSA_new() + // + return (VOID *) RSA_new (); +} + +/** + Release the specified RSA context. + + @param[in] RsaContext Pointer to the RSA context to be released. + +**/ +VOID +EFIAPI +RsaFree ( + IN VOID *RsaContext + ) +{ + // + // Free OpenSSL RSA Context + // + RSA_free ((RSA *) RsaContext); +} + +/** + Sets the tag-designated key component into the established RSA context. + + This function sets the tag-designated RSA key component into the established + RSA context from the user-specified non-negative integer (octet string format + represented in RSA PKCS#1). + If BigNumber is NULL, then the specified key component in RSA context is cleared. + + If RsaContext is NULL, then return FALSE. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] KeyTag Tag of RSA key component being set. + @param[in] BigNumber Pointer to octet integer buffer. + If NULL, then the specified key component in RSA + context is cleared. + @param[in] BnSize Size of big number buffer in bytes. + If BigNumber is NULL, then it is ignored. + + @retval TRUE RSA key component was set successfully. + @retval FALSE Invalid RSA key component tag. + +**/ +BOOLEAN +EFIAPI +RsaSetKey ( + IN OUT VOID *RsaContext, + IN RSA_KEY_TAG KeyTag, + IN CONST UINT8 *BigNumber, + IN UINTN BnSize + ) +{ + RSA *RsaKey; + BIGNUM *BnN; + BIGNUM *BnE; + BIGNUM *BnD; + BIGNUM *BnP; + BIGNUM *BnQ; + BIGNUM *BnDp; + BIGNUM *BnDq; + BIGNUM *BnQInv; + + // + // Check input parameters. + // + if (RsaContext == NULL || BnSize > INT_MAX) { + return FALSE; + } + + BnN = NULL; + BnE = NULL; + BnD = NULL; + BnP = NULL; + BnQ = NULL; + BnDp = NULL; + BnDq = NULL; + BnQInv = NULL; + + // + // Retrieve the components from RSA object. + // + RsaKey = (RSA *) RsaContext; + RSA_get0_key (RsaKey, (const BIGNUM **)&BnN, (const BIGNUM **)&BnE, (const BIGNUM **)&BnD); + RSA_get0_factors (RsaKey, (const BIGNUM **)&BnP, (const BIGNUM **)&BnQ); + RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnDp, (const BIGNUM **)&BnDq, (const BIGNUM **)&BnQInv); + + // + // Set RSA Key Components by converting octet string to OpenSSL BN representation. + // NOTE: For RSA public key (used in signature verification), only public components + // (N, e) are needed. + // + switch (KeyTag) { + + // + // RSA Public Modulus (N), Public Exponent (e) and Private Exponent (d) + // + case RsaKeyN: + case RsaKeyE: + case RsaKeyD: + if (BnN == NULL) { + BnN = BN_new (); + } + if (BnE == NULL) { + BnE = BN_new (); + } + if (BnD == NULL) { + BnD = BN_new (); + } + + if ((BnN == NULL) || (BnE == NULL) || (BnD == NULL)) { + return FALSE; + } + + switch (KeyTag) { + case RsaKeyN: + BnN = BN_bin2bn (BigNumber, (UINT32)BnSize, BnN); + break; + case RsaKeyE: + BnE = BN_bin2bn (BigNumber, (UINT32)BnSize, BnE); + break; + case RsaKeyD: + BnD = BN_bin2bn (BigNumber, (UINT32)BnSize, BnD); + break; + default: + return FALSE; + } + if (RSA_set0_key (RsaKey, BN_dup(BnN), BN_dup(BnE), BN_dup(BnD)) == 0) { + return FALSE; + } + + break; + + // + // RSA Secret Prime Factor of Modulus (p and q) + // + case RsaKeyP: + case RsaKeyQ: + if (BnP == NULL) { + BnP = BN_new (); + } + if (BnQ == NULL) { + BnQ = BN_new (); + } + if ((BnP == NULL) || (BnQ == NULL)) { + return FALSE; + } + + switch (KeyTag) { + case RsaKeyP: + BnP = BN_bin2bn (BigNumber, (UINT32)BnSize, BnP); + break; + case RsaKeyQ: + BnQ = BN_bin2bn (BigNumber, (UINT32)BnSize, BnQ); + break; + default: + return FALSE; + } + if (RSA_set0_factors (RsaKey, BN_dup(BnP), BN_dup(BnQ)) == 0) { + return FALSE; + } + + break; + + // + // p's CRT Exponent (== d mod (p - 1)), q's CRT Exponent (== d mod (q - 1)), + // and CRT Coefficient (== 1/q mod p) + // + case RsaKeyDp: + case RsaKeyDq: + case RsaKeyQInv: + if (BnDp == NULL) { + BnDp = BN_new (); + } + if (BnDq == NULL) { + BnDq = BN_new (); + } + if (BnQInv == NULL) { + BnQInv = BN_new (); + } + if ((BnDp == NULL) || (BnDq == NULL) || (BnQInv == NULL)) { + return FALSE; + } + + switch (KeyTag) { + case RsaKeyDp: + BnDp = BN_bin2bn (BigNumber, (UINT32)BnSize, BnDp); + break; + case RsaKeyDq: + BnDq = BN_bin2bn (BigNumber, (UINT32)BnSize, BnDq); + break; + case RsaKeyQInv: + BnQInv = BN_bin2bn (BigNumber, (UINT32)BnSize, BnQInv); + break; + default: + return FALSE; + } + if (RSA_set0_crt_params (RsaKey, BN_dup(BnDp), BN_dup(BnDq), BN_dup(BnQInv)) == 0) { + return FALSE; + } + + break; + + default: + return FALSE; + } + + return TRUE; +} + +/** + Verifies the RSA-SSA signature with EMSA-PKCS1-v1_5 encoding scheme defined in + RSA PKCS#1. + + If RsaContext is NULL, then return FALSE. + If MessageHash is NULL, then return FALSE. + If Signature is NULL, then return FALSE. + If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] MessageHash Pointer to octet message hash to be checked. + @param[in] HashSize Size of the message hash in bytes. + @param[in] Signature Pointer to RSA PKCS1-v1_5 signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in PKCS1-v1_5. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPkcs1Verify ( + IN VOID *RsaContext, + IN CONST UINT8 *MessageHash, + IN UINTN HashSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + INT32 DigestType; + UINT8 *SigBuf; + + // + // Check input parameters. + // + if (RsaContext == NULL || MessageHash == NULL || Signature == NULL) { + return FALSE; + } + + if (SigSize > INT_MAX || SigSize == 0) { + return FALSE; + } + + // + // Determine the message digest algorithm according to digest size. + // Only MD5, SHA-1 or SHA-256 algorithm is supported. + // + switch (HashSize) { + case MD5_DIGEST_SIZE: + DigestType = NID_md5; + break; + + case SHA1_DIGEST_SIZE: + DigestType = NID_sha1; + break; + + case SHA256_DIGEST_SIZE: + DigestType = NID_sha256; + break; + + default: + return FALSE; + } + + SigBuf = (UINT8 *) Signature; + return (BOOLEAN) RSA_verify ( + DigestType, + MessageHash, + (UINT32) HashSize, + SigBuf, + (UINT32) SigSize, + (RSA *) RsaContext + ); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c new file mode 100644 index 0000000..8bf0c01 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c @@ -0,0 +1,362 @@ +/** @file + RSA Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file implements following APIs which provide more capabilities for RSA: + 1) RsaGetKey + 2) RsaGenerateKey + 3) RsaCheckKey + 4) RsaPkcs1Sign + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include +#include + +/** + Gets the tag-designated RSA key component from the established RSA context. + + This function retrieves the tag-designated RSA key component from the + established RSA context as a non-negative integer (octet string format + represented in RSA PKCS#1). + If specified key component has not been set or has been cleared, then returned + BnSize is set to 0. + If the BigNumber buffer is too small to hold the contents of the key, FALSE + is returned and BnSize is set to the required buffer size to obtain the key. + + If RsaContext is NULL, then return FALSE. + If BnSize is NULL, then return FALSE. + If BnSize is large enough but BigNumber is NULL, then return FALSE. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] KeyTag Tag of RSA key component being set. + @param[out] BigNumber Pointer to octet integer buffer. + @param[in, out] BnSize On input, the size of big number buffer in bytes. + On output, the size of data returned in big number buffer in bytes. + + @retval TRUE RSA key component was retrieved successfully. + @retval FALSE Invalid RSA key component tag. + @retval FALSE BnSize is too small. + +**/ +BOOLEAN +EFIAPI +RsaGetKey ( + IN OUT VOID *RsaContext, + IN RSA_KEY_TAG KeyTag, + OUT UINT8 *BigNumber, + IN OUT UINTN *BnSize + ) +{ + RSA *RsaKey; + BIGNUM *BnKey; + UINTN Size; + + // + // Check input parameters. + // + if (RsaContext == NULL || BnSize == NULL) { + return FALSE; + } + + RsaKey = (RSA *) RsaContext; + Size = *BnSize; + *BnSize = 0; + BnKey = NULL; + + switch (KeyTag) { + + // + // RSA Public Modulus (N) + // + case RsaKeyN: + RSA_get0_key (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL); + break; + + // + // RSA Public Exponent (e) + // + case RsaKeyE: + RSA_get0_key (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL); + break; + + // + // RSA Private Exponent (d) + // + case RsaKeyD: + RSA_get0_key (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey); + break; + + // + // RSA Secret Prime Factor of Modulus (p) + // + case RsaKeyP: + RSA_get0_factors (RsaKey, (const BIGNUM **)&BnKey, NULL); + break; + + // + // RSA Secret Prime Factor of Modules (q) + // + case RsaKeyQ: + RSA_get0_factors (RsaKey, NULL, (const BIGNUM **)&BnKey); + break; + + // + // p's CRT Exponent (== d mod (p - 1)) + // + case RsaKeyDp: + RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL); + break; + + // + // q's CRT Exponent (== d mod (q - 1)) + // + case RsaKeyDq: + RSA_get0_crt_params (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL); + break; + + // + // The CRT Coefficient (== 1/q mod p) + // + case RsaKeyQInv: + RSA_get0_crt_params (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey); + break; + + default: + return FALSE; + } + + if (BnKey == NULL) { + return FALSE; + } + + *BnSize = Size; + Size = BN_num_bytes (BnKey); + + if (*BnSize < Size) { + *BnSize = Size; + return FALSE; + } + + if (BigNumber == NULL) { + *BnSize = Size; + return TRUE; + } + *BnSize = BN_bn2bin (BnKey, BigNumber) ; + + return TRUE; +} + +/** + Generates RSA key components. + + This function generates RSA key components. It takes RSA public exponent E and + length in bits of RSA modulus N as input, and generates all key components. + If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used. + + Before this function can be invoked, pseudorandom number generator must be correctly + initialized by RandomSeed(). + + If RsaContext is NULL, then return FALSE. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] ModulusLength Length of RSA modulus N in bits. + @param[in] PublicExponent Pointer to RSA public exponent. + @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes. + + @retval TRUE RSA key component was generated successfully. + @retval FALSE Invalid RSA key component tag. + +**/ +BOOLEAN +EFIAPI +RsaGenerateKey ( + IN OUT VOID *RsaContext, + IN UINTN ModulusLength, + IN CONST UINT8 *PublicExponent, + IN UINTN PublicExponentSize + ) +{ + BIGNUM *KeyE; + BOOLEAN RetVal; + + // + // Check input parameters. + // + if (RsaContext == NULL || ModulusLength > INT_MAX || PublicExponentSize > INT_MAX) { + return FALSE; + } + + KeyE = BN_new (); + if (KeyE == NULL) { + return FALSE; + } + + RetVal = FALSE; + + if (PublicExponent == NULL) { + if (BN_set_word (KeyE, 0x10001) == 0) { + goto _Exit; + } + } else { + if (BN_bin2bn (PublicExponent, (UINT32) PublicExponentSize, KeyE) == NULL) { + goto _Exit; + } + } + + if (RSA_generate_key_ex ((RSA *) RsaContext, (UINT32) ModulusLength, KeyE, NULL) == 1) { + RetVal = TRUE; + } + +_Exit: + BN_free (KeyE); + return RetVal; +} + +/** + Validates key components of RSA context. + NOTE: This function performs integrity checks on all the RSA key material, so + the RSA key structure must contain all the private key data. + + This function validates key components of RSA context in following aspects: + - Whether p is a prime + - Whether q is a prime + - Whether n = p * q + - Whether d*e = 1 mod lcm(p-1,q-1) + + If RsaContext is NULL, then return FALSE. + + @param[in] RsaContext Pointer to RSA context to check. + + @retval TRUE RSA key components are valid. + @retval FALSE RSA key components are not valid. + +**/ +BOOLEAN +EFIAPI +RsaCheckKey ( + IN VOID *RsaContext + ) +{ + UINTN Reason; + + // + // Check input parameters. + // + if (RsaContext == NULL) { + return FALSE; + } + + if (RSA_check_key ((RSA *) RsaContext) != 1) { + Reason = ERR_GET_REASON (ERR_peek_last_error ()); + if (Reason == RSA_R_P_NOT_PRIME || + Reason == RSA_R_Q_NOT_PRIME || + Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q || + Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1) { + return FALSE; + } + } + + return TRUE; +} + +/** + Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme. + + This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in + RSA PKCS#1. + If the Signature buffer is too small to hold the contents of signature, FALSE + is returned and SigSize is set to the required buffer size to obtain the signature. + + If RsaContext is NULL, then return FALSE. + If MessageHash is NULL, then return FALSE. + If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then return FALSE. + If SigSize is large enough but Signature is NULL, then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] MessageHash Pointer to octet message hash to be signed. + @param[in] HashSize Size of the message hash in bytes. + @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature. + @param[in, out] SigSize On input, the size of Signature buffer in bytes. + On output, the size of data returned in Signature buffer in bytes. + + @retval TRUE Signature successfully generated in PKCS1-v1_5. + @retval FALSE Signature generation failed. + @retval FALSE SigSize is too small. + +**/ +BOOLEAN +EFIAPI +RsaPkcs1Sign ( + IN VOID *RsaContext, + IN CONST UINT8 *MessageHash, + IN UINTN HashSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + RSA *Rsa; + UINTN Size; + INT32 DigestType; + + // + // Check input parameters. + // + if (RsaContext == NULL || MessageHash == NULL) { + return FALSE; + } + + Rsa = (RSA *) RsaContext; + Size = RSA_size (Rsa); + + if (*SigSize < Size) { + *SigSize = Size; + return FALSE; + } + + if (Signature == NULL) { + return FALSE; + } + + // + // Determine the message digest algorithm according to digest size. + // Only MD5, SHA-1 or SHA-256 algorithm is supported. + // + switch (HashSize) { + case MD5_DIGEST_SIZE: + DigestType = NID_md5; + break; + + case SHA1_DIGEST_SIZE: + DigestType = NID_sha1; + break; + + case SHA256_DIGEST_SIZE: + DigestType = NID_sha256; + break; + + default: + return FALSE; + } + + return (BOOLEAN) RSA_sign ( + DigestType, + MessageHash, + (UINT32) HashSize, + Signature, + (UINT32 *) SigSize, + (RSA *) RsaContext + ); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExtNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExtNull.c new file mode 100644 index 0000000..0d1b204 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaExtNull.c @@ -0,0 +1,125 @@ +/** @file + RSA Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file does not provide real capabilities for following APIs in RSA handling: + 1) RsaGetKey + 2) RsaGenerateKey + 3) RsaCheckKey + 4) RsaPkcs1Sign + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Gets the tag-designated RSA key component from the established RSA context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] KeyTag Tag of RSA key component being set. + @param[out] BigNumber Pointer to octet integer buffer. + @param[in, out] BnSize On input, the size of big number buffer in bytes. + On output, the size of data returned in big number buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetKey ( + IN OUT VOID *RsaContext, + IN RSA_KEY_TAG KeyTag, + OUT UINT8 *BigNumber, + IN OUT UINTN *BnSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Generates RSA key components. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] RsaContext Pointer to RSA context being set. + @param[in] ModulusLength Length of RSA modulus N in bits. + @param[in] PublicExponent Pointer to RSA public exponent. + @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGenerateKey ( + IN OUT VOID *RsaContext, + IN UINTN ModulusLength, + IN CONST UINT8 *PublicExponent, + IN UINTN PublicExponentSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Validates key components of RSA context. + + Return FALSE to indicate this interface is not supported. + + @param[in] RsaContext Pointer to RSA context to check. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaCheckKey ( + IN VOID *RsaContext + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme. + + Return FALSE to indicate this interface is not supported. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] MessageHash Pointer to octet message hash to be signed. + @param[in] HashSize Size of the message hash in bytes. + @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature. + @param[in, out] SigSize On input, the size of Signature buffer in bytes. + On output, the size of data returned in Signature buffer in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaPkcs1Sign ( + IN VOID *RsaContext, + IN CONST UINT8 *MessageHash, + IN UINTN HashSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c new file mode 100644 index 0000000..10715bd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c @@ -0,0 +1,665 @@ +/** @file + RFC3161 Timestamp Countersignature Verification over OpenSSL. + The timestamp is generated by a TimeStamping Authority (TSA) and asserts that a + publisher's signature existed before the specified time. The timestamp extends + the lifetime of the signature when a signing certificate expires or is later + revoked. + +Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include +#include +#include + +// +// OID ASN.1 Value for SPC_RFC3161_OBJID ("1.3.6.1.4.1.311.3.3.1") +// +UINT8 mSpcRFC3161OidValue[] = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01 + }; + +/// +/// The messageImprint field SHOULD contain the hash of the datum to be +/// time-stamped. The hash is represented as an OCTET STRING. Its +/// length MUST match the length of the hash value for that algorithm +/// (e.g., 20 bytes for SHA-1 or 16 bytes for MD5). +/// +/// MessageImprint ::= SEQUENCE { +/// hashAlgorithm AlgorithmIdentifier, +/// hashedMessage OCTET STRING } +/// +typedef struct { + X509_ALGOR *HashAlgorithm; + ASN1_OCTET_STRING *HashedMessage; +} TS_MESSAGE_IMPRINT; + +// +// ASN.1 Functions for TS_MESSAGE_IMPRINT +// +DECLARE_ASN1_FUNCTIONS (TS_MESSAGE_IMPRINT) +ASN1_SEQUENCE (TS_MESSAGE_IMPRINT) = { + ASN1_SIMPLE (TS_MESSAGE_IMPRINT, HashAlgorithm, X509_ALGOR), + ASN1_SIMPLE (TS_MESSAGE_IMPRINT, HashedMessage, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END (TS_MESSAGE_IMPRINT) +IMPLEMENT_ASN1_FUNCTIONS (TS_MESSAGE_IMPRINT) + +/// +/// Accuracy represents the time deviation around the UTC time contained +/// in GeneralizedTime of time-stamp token. +/// +/// Accuracy ::= SEQUENCE { +/// seconds INTEGER OPTIONAL, +/// millis [0] INTEGER (1..999) OPTIONAL, +/// micros [1] INTEGER (1..999) OPTIONAL } +/// +typedef struct { + ASN1_INTEGER *Seconds; + ASN1_INTEGER *Millis; + ASN1_INTEGER *Micros; +} TS_ACCURACY; + +// +// ASN.1 Functions for TS_ACCURACY +// +DECLARE_ASN1_FUNCTIONS (TS_ACCURACY) +ASN1_SEQUENCE (TS_ACCURACY) = { + ASN1_OPT (TS_ACCURACY, Seconds, ASN1_INTEGER), + ASN1_IMP_OPT (TS_ACCURACY, Millis, ASN1_INTEGER, 0), + ASN1_IMP_OPT (TS_ACCURACY, Micros, ASN1_INTEGER, 1) +} ASN1_SEQUENCE_END (TS_ACCURACY) +IMPLEMENT_ASN1_FUNCTIONS (TS_ACCURACY) + +/// +/// The timestamp token info resulting from a successful timestamp request, +/// as defined in RFC 3161. +/// +/// TSTInfo ::= SEQUENCE { +/// version INTEGER { v1(1) }, +/// policy TSAPolicyId, +/// messageImprint MessageImprint, +/// -- MUST have the same value as the similar field in +/// -- TimeStampReq +/// serialNumber INTEGER, +/// -- Time-Stamping users MUST be ready to accommodate integers +/// -- up to 160 bits. +/// genTime GeneralizedTime, +/// accuracy Accuracy OPTIONAL, +/// ordering BOOLEAN DEFAULT FALSE, +/// nonce INTEGER OPTIONAL, +/// -- MUST be present if the similar field was present +/// -- in TimeStampReq. In that case it MUST have the same value. +/// tsa [0] GeneralName OPTIONAL, +/// extensions [1] IMPLICIT Extensions OPTIONAL } +/// +typedef struct { + ASN1_INTEGER *Version; + ASN1_OBJECT *Policy; + TS_MESSAGE_IMPRINT *MessageImprint; + ASN1_INTEGER *SerialNumber; + ASN1_GENERALIZEDTIME *GenTime; + TS_ACCURACY *Accuracy; + ASN1_BOOLEAN Ordering; + ASN1_INTEGER *Nonce; + GENERAL_NAME *Tsa; + STACK_OF(X509_EXTENSION) *Extensions; +} TS_TST_INFO; + +// +// ASN.1 Functions for TS_TST_INFO +// +DECLARE_ASN1_FUNCTIONS (TS_TST_INFO) +ASN1_SEQUENCE (TS_TST_INFO) = { + ASN1_SIMPLE (TS_TST_INFO, Version, ASN1_INTEGER), + ASN1_SIMPLE (TS_TST_INFO, Policy, ASN1_OBJECT), + ASN1_SIMPLE (TS_TST_INFO, MessageImprint, TS_MESSAGE_IMPRINT), + ASN1_SIMPLE (TS_TST_INFO, SerialNumber, ASN1_INTEGER), + ASN1_SIMPLE (TS_TST_INFO, GenTime, ASN1_GENERALIZEDTIME), + ASN1_OPT (TS_TST_INFO, Accuracy, TS_ACCURACY), + ASN1_OPT (TS_TST_INFO, Ordering, ASN1_FBOOLEAN), + ASN1_OPT (TS_TST_INFO, Nonce, ASN1_INTEGER), + ASN1_EXP_OPT(TS_TST_INFO, Tsa, GENERAL_NAME, 0), + ASN1_IMP_SEQUENCE_OF_OPT (TS_TST_INFO, Extensions, X509_EXTENSION, 1) +} ASN1_SEQUENCE_END (TS_TST_INFO) +IMPLEMENT_ASN1_FUNCTIONS (TS_TST_INFO) + + +/** + Convert ASN.1 GeneralizedTime to EFI Time. + + @param[in] Asn1Time Pointer to the ASN.1 GeneralizedTime to be converted. + @param[out] SigningTime Return the corresponding EFI Time. + + @retval TRUE The time conversion succeeds. + @retval FALSE Invalid parameters. + +**/ +BOOLEAN +EFIAPI +ConvertAsn1TimeToEfiTime ( + IN ASN1_TIME *Asn1Time, + OUT EFI_TIME *EfiTime + ) +{ + CONST CHAR8 *Str; + UINTN Index; + + if ((Asn1Time == NULL) || (EfiTime == NULL)) { + return FALSE; + } + + Str = (CONST CHAR8*)Asn1Time->data; + SetMem (EfiTime, 0, sizeof (EFI_TIME)); + + Index = 0; + if (Asn1Time->type == V_ASN1_UTCTIME) { /* two digit year */ + EfiTime->Year = (Str[Index++] - '0') * 10; + EfiTime->Year += (Str[Index++] - '0'); + if (EfiTime->Year < 70) { + EfiTime->Year += 100; + } + } else if (Asn1Time->type == V_ASN1_GENERALIZEDTIME) { /* four digit year */ + EfiTime->Year = (Str[Index++] - '0') * 1000; + EfiTime->Year += (Str[Index++] - '0') * 100; + EfiTime->Year += (Str[Index++] - '0') * 10; + EfiTime->Year += (Str[Index++] - '0'); + if ((EfiTime->Year < 1900) || (EfiTime->Year > 9999)) { + return FALSE; + } + } + + EfiTime->Month = (Str[Index++] - '0') * 10; + EfiTime->Month += (Str[Index++] - '0'); + if ((EfiTime->Month < 1) || (EfiTime->Month > 12)) { + return FALSE; + } + + EfiTime->Day = (Str[Index++] - '0') * 10; + EfiTime->Day += (Str[Index++] - '0'); + if ((EfiTime->Day < 1) || (EfiTime->Day > 31)) { + return FALSE; + } + + EfiTime->Hour = (Str[Index++] - '0') * 10; + EfiTime->Hour += (Str[Index++] - '0'); + if (EfiTime->Hour > 23) { + return FALSE; + } + + EfiTime->Minute = (Str[Index++] - '0') * 10; + EfiTime->Minute += (Str[Index++] - '0'); + if (EfiTime->Minute > 59) { + return FALSE; + } + + EfiTime->Second = (Str[Index++] - '0') * 10; + EfiTime->Second += (Str[Index++] - '0'); + if (EfiTime->Second > 59) { + return FALSE; + } + + /* Note: we did not adjust the time based on time zone information */ + + return TRUE; +} + +/** + + Check the validity of TimeStamp Token Information. + + @param[in] TstInfo Pointer to the TS_TST_INFO structure. + @param[in] TimestampedData Pointer to the data to be time-stamped. + @param[in] DataSize Size of timestamped data in bytes. + + @retval TRUE The TimeStamp Token Information is valid. + @retval FALSE Invalid TimeStamp Token Information. + +**/ +BOOLEAN +EFIAPI +CheckTSTInfo ( + IN CONST TS_TST_INFO *TstInfo, + IN CONST UINT8 *TimestampedData, + IN UINTN DataSize + ) +{ + BOOLEAN Status; + TS_MESSAGE_IMPRINT *Imprint; + X509_ALGOR *HashAlgo; + CONST EVP_MD *Md; + EVP_MD_CTX *MdCtx; + UINTN MdSize; + UINT8 *HashedMsg; + + // + // Initialization + // + Status = FALSE; + HashAlgo = NULL; + HashedMsg = NULL; + MdCtx = NULL; + + // + // -- Check version number of Timestamp: + // The version field (currently v1) describes the version of the time-stamp token. + // Conforming time-stamping servers MUST be able to provide version 1 time-stamp tokens. + // + if ((ASN1_INTEGER_get (TstInfo->Version)) != 1) { + return FALSE; + } + + // + // -- Check Policies + // The policy field MUST indicate the TSA's policy under which the response was produced. + // + if (TstInfo->Policy == NULL) { + /// NOTE: Need to check if the requested and returned policies. + /// We have no information about the Requested TSA Policy. + return FALSE; + } + + // + // -- Compute & Check Message Imprint + // + Imprint = TstInfo->MessageImprint; + HashAlgo = X509_ALGOR_dup (Imprint->HashAlgorithm); + + Md = EVP_get_digestbyobj (HashAlgo->algorithm); + if (Md == NULL) { + goto _Exit; + } + + MdSize = EVP_MD_size (Md); + HashedMsg = AllocateZeroPool (MdSize); + if (HashedMsg == NULL) { + goto _Exit; + } + MdCtx = EVP_MD_CTX_new (); + if (MdCtx == NULL) { + goto _Exit; + } + if ((EVP_DigestInit_ex (MdCtx, Md, NULL) != 1) || + (EVP_DigestUpdate (MdCtx, TimestampedData, DataSize) != 1) || + (EVP_DigestFinal (MdCtx, HashedMsg, NULL) != 1)) { + goto _Exit; + } + if ((MdSize == (UINTN)ASN1_STRING_length (Imprint->HashedMessage)) && + (CompareMem (HashedMsg, ASN1_STRING_get0_data (Imprint->HashedMessage), MdSize) != 0)) { + goto _Exit; + } + + // + // -- Check Nonces + // + if (TstInfo->Nonce != NULL) { + // + // Nonces is optional, No error if no nonce is returned; + // + } + + // + // -- Check if the TSA name and signer certificate is matched. + // + if (TstInfo->Tsa != NULL) { + // + // Ignored the optional Tsa field checking. + // + } + + Status = TRUE; + +_Exit: + X509_ALGOR_free (HashAlgo); + EVP_MD_CTX_free (MdCtx); + if (HashedMsg != NULL) { + FreePool (HashedMsg); + } + + return Status; +} + +/** + Verifies the validity of a TimeStamp Token as described in RFC 3161 ("Internet + X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)"). + + If TSToken is NULL, then return FALSE. + If TimestampedData is NULL, then return FALSE. + + @param[in] TSToken Pointer to the RFC3161 TimeStamp Token, which is generated + by a TSA and located in the software publisher's SignerInfo + structure. + @param[in] TokenSize Size of the TimeStamp Token in bytes. + @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER. + @param[in] CertSize Size of the trusted TSA certificate in bytes. + @param[in] TimestampedData Pointer to the data to be time-stamped. + @param[in] DataSize Size of timestamped data in bytes. + @param[out] SigningTime Return the time of timestamp generation time if the timestamp + signature is valid. + + @retval TRUE The specified timestamp token is valid. + @retval FALSE Invalid timestamp token. + +**/ +BOOLEAN +EFIAPI +TimestampTokenVerify ( + IN CONST UINT8 *TSToken, + IN UINTN TokenSize, + IN CONST UINT8 *TsaCert, + IN UINTN CertSize, + IN CONST UINT8 *TimestampedData, + IN UINTN DataSize, + OUT EFI_TIME *SigningTime + ) +{ + BOOLEAN Status; + CONST UINT8 *TokenTemp; + PKCS7 *Pkcs7; + X509 *Cert; + CONST UINT8 *CertTemp; + X509_STORE *CertStore; + BIO *OutBio; + UINT8 *TstData; + UINTN TstSize; + CONST UINT8 *TstTemp; + TS_TST_INFO *TstInfo; + + Status = FALSE; + + // + // Check input parameters + // + if ((TSToken == NULL) || (TsaCert == NULL) || (TimestampedData == NULL) || + (TokenSize > INT_MAX) || (CertSize > INT_MAX) || (DataSize > INT_MAX)) { + return FALSE; + } + + // + // Initializations + // + if (SigningTime != NULL) { + SetMem (SigningTime, sizeof (EFI_TIME), 0); + } + Pkcs7 = NULL; + Cert = NULL; + CertStore = NULL; + OutBio = NULL; + TstData = NULL; + TstInfo = NULL; + + // + // TimeStamp Token should contain one valid DER-encoded ASN.1 PKCS#7 structure. + // + TokenTemp = TSToken; + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &TokenTemp, (int) TokenSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // The timestamp signature (TSA's response) will be one PKCS#7 signed data. + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + // + // Read the trusted TSA certificate (DER-encoded), and Construct X509 Certificate. + // + CertTemp = TsaCert; + Cert = d2i_X509 (NULL, &CertTemp, (long) CertSize); + if (Cert == NULL) { + goto _Exit; + } + + // + // Setup X509 Store for trusted certificate. + // + CertStore = X509_STORE_new (); + if ((CertStore == NULL) || !(X509_STORE_add_cert (CertStore, Cert))) { + goto _Exit; + } + + // + // Allow partial certificate chains, terminated by a non-self-signed but + // still trusted intermediate certificate. Also disable time checks. + // + X509_STORE_set_flags (CertStore, + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME); + + X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY); + + // + // Verifies the PKCS#7 signedData structure, and output the signed contents. + // + OutBio = BIO_new (BIO_s_mem ()); + if (OutBio == NULL) { + goto _Exit; + } + if (!PKCS7_verify (Pkcs7, NULL, CertStore, NULL, OutBio, PKCS7_BINARY)) { + goto _Exit; + } + + // + // Read the signed contents detached in timestamp signature. + // + TstData = AllocateZeroPool (2048); + if (TstData == NULL) { + goto _Exit; + } + TstSize = BIO_read (OutBio, (void *) TstData, 2048); + + // + // Construct TS_TST_INFO structure from the signed contents. + // + TstTemp = TstData; + TstInfo = d2i_TS_TST_INFO (NULL, (const unsigned char **) &TstTemp, + (int)TstSize); + if (TstInfo == NULL) { + goto _Exit; + } + + // + // Check TS_TST_INFO structure. + // + Status = CheckTSTInfo (TstInfo, TimestampedData, DataSize); + if (!Status) { + goto _Exit; + } + + // + // Retrieve the signing time from TS_TST_INFO structure. + // + if (SigningTime != NULL) { + SetMem (SigningTime, sizeof (EFI_TIME), 0); + Status = ConvertAsn1TimeToEfiTime (TstInfo->GenTime, SigningTime); + } + +_Exit: + // + // Release Resources + // + PKCS7_free (Pkcs7); + X509_free (Cert); + X509_STORE_free (CertStore); + BIO_free (OutBio); + TS_TST_INFO_free (TstInfo); + + if (TstData != NULL) { + FreePool (TstData); + } + + return Status; +} + +/** + Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode + signature. + + If AuthData is NULL, then return FALSE. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which + is used for TSA certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[out] SigningTime Return the time of timestamp generation time if the timestamp + signature is valid. + + @retval TRUE The specified Authenticode includes a valid RFC3161 Timestamp CounterSignature. + @retval FALSE No valid RFC3161 Timestamp CounterSignature in the specified Authenticode data. + +**/ +BOOLEAN +EFIAPI +ImageTimestampVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TsaCert, + IN UINTN CertSize, + OUT EFI_TIME *SigningTime + ) +{ + BOOLEAN Status; + PKCS7 *Pkcs7; + CONST UINT8 *Temp; + STACK_OF(PKCS7_SIGNER_INFO) *SignerInfos; + PKCS7_SIGNER_INFO *SignInfo; + UINTN Index; + STACK_OF(X509_ATTRIBUTE) *Sk; + X509_ATTRIBUTE *Xa; + ASN1_OBJECT *XaObj; + ASN1_TYPE *Asn1Type; + ASN1_OCTET_STRING *EncDigest; + UINT8 *TSToken; + UINTN TokenSize; + + // + // Input Parameters Checking. + // + if ((AuthData == NULL) || (TsaCert == NULL)) { + return FALSE; + } + + if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) { + return FALSE; + } + + // + // Register & Initialize necessary digest algorithms for PKCS#7 Handling. + // + if ((EVP_add_digest (EVP_md5 ()) == 0) || (EVP_add_digest (EVP_sha1 ()) == 0) || + (EVP_add_digest (EVP_sha256 ()) == 0) || (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0) { + return FALSE; + } + + // + // Initialization. + // + Status = FALSE; + Pkcs7 = NULL; + SignInfo = NULL; + + // + // Decode ASN.1-encoded Authenticode data into PKCS7 structure. + // + Temp = AuthData; + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) DataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Check if there is one and only one signer. + // + SignerInfos = PKCS7_get_signer_info (Pkcs7); + if (!SignerInfos || (sk_PKCS7_SIGNER_INFO_num (SignerInfos) != 1)) { + goto _Exit; + } + + // + // Locate the TimeStamp CounterSignature. + // + SignInfo = sk_PKCS7_SIGNER_INFO_value (SignerInfos, 0); + if (SignInfo == NULL) { + goto _Exit; + } + + // + // Locate Message Digest which will be the data to be time-stamped. + // + EncDigest = SignInfo->enc_digest; + if (EncDigest == NULL) { + goto _Exit; + } + + // + // The RFC3161 timestamp counterSignature is contained in unauthenticatedAttributes field + // of SignerInfo. + // + Sk = SignInfo->unauth_attr; + if (Sk == NULL) { // No timestamp counterSignature. + goto _Exit; + } + + Asn1Type = NULL; + for (Index = 0; Index < (UINTN) sk_X509_ATTRIBUTE_num (Sk); Index++) { + // + // Search valid RFC3161 timestamp counterSignature based on OBJID. + // + Xa = sk_X509_ATTRIBUTE_value (Sk, (int)Index); + if (Xa == NULL) { + continue; + } + XaObj = X509_ATTRIBUTE_get0_object(Xa); + if (XaObj == NULL) { + continue; + } + if ((OBJ_length(XaObj) != sizeof (mSpcRFC3161OidValue)) || + (CompareMem (OBJ_get0_data(XaObj), mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0)) { + continue; + } + Asn1Type = X509_ATTRIBUTE_get0_type(Xa, 0); + } + + if (Asn1Type == NULL) { + Status = FALSE; + goto _Exit; + } + TSToken = Asn1Type->value.octet_string->data; + TokenSize = Asn1Type->value.octet_string->length; + + // + // TimeStamp counterSignature (Token) verification. + // + Status = TimestampTokenVerify ( + TSToken, + TokenSize, + TsaCert, + CertSize, + EncDigest->data, + EncDigest->length, + SigningTime + ); + +_Exit: + // + // Release Resources + // + PKCS7_free (Pkcs7); + + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTsNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTsNull.c new file mode 100644 index 0000000..3a9b5f2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptTsNull.c @@ -0,0 +1,48 @@ +/** @file + RFC3161 Timestamp Countersignature Verification Wrapper Implementation which does + not provide real capabilities. + +Copyright (c) 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode + signature. + + Return FALSE to indicate this interface is not supported. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which + is used for TSA certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[out] SigningTime Return the time of timestamp generation time if the timestamp + signature is valid. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +ImageTimestampVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TsaCert, + IN UINTN CertSize, + OUT EFI_TIME *SigningTime + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c new file mode 100644 index 0000000..7424b80 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c @@ -0,0 +1,730 @@ +/** @file + X.509 Certificate Handler Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include + +/** + Construct a X509 object from DER-encoded certificate data. + + If Cert is NULL, then return FALSE. + If SingleX509Cert is NULL, then return FALSE. + + @param[in] Cert Pointer to the DER-encoded certificate data. + @param[in] CertSize The size of certificate data in bytes. + @param[out] SingleX509Cert The generated X509 object. + + @retval TRUE The X509 object generation succeeded. + @retval FALSE The operation failed. + +**/ +BOOLEAN +EFIAPI +X509ConstructCertificate ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **SingleX509Cert + ) +{ + X509 *X509Cert; + CONST UINT8 *Temp; + + // + // Check input parameters. + // + if (Cert == NULL || SingleX509Cert == NULL || CertSize > INT_MAX) { + return FALSE; + } + + // + // Read DER-encoded X509 Certificate and Construct X509 object. + // + Temp = Cert; + X509Cert = d2i_X509 (NULL, &Temp, (long) CertSize); + if (X509Cert == NULL) { + return FALSE; + } + + *SingleX509Cert = (UINT8 *) X509Cert; + + return TRUE; +} + +/** + Construct a X509 stack object from a list of DER-encoded certificate data. + + If X509Stack is NULL, then return FALSE. + + @param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object. + On output, pointer to the X509 stack object with new + inserted X509 certificate. + @param ... A list of DER-encoded single certificate data followed + by certificate size. A NULL terminates the list. The + pairs are the arguments to X509ConstructCertificate(). + + @retval TRUE The X509 stack construction succeeded. + @retval FALSE The construction operation failed. + +**/ +BOOLEAN +EFIAPI +X509ConstructCertificateStack ( + IN OUT UINT8 **X509Stack, + ... + ) +{ + UINT8 *Cert; + UINTN CertSize; + X509 *X509Cert; + STACK_OF(X509) *CertStack; + BOOLEAN Status; + VA_LIST Args; + UINTN Index; + + // + // Check input parameters. + // + if (X509Stack == NULL) { + return FALSE; + } + + Status = FALSE; + + // + // Initialize X509 stack object. + // + CertStack = (STACK_OF(X509) *) (*X509Stack); + if (CertStack == NULL) { + CertStack = sk_X509_new_null (); + if (CertStack == NULL) { + return Status; + } + } + + VA_START (Args, X509Stack); + + for (Index = 0; ; Index++) { + // + // If Cert is NULL, then it is the end of the list. + // + Cert = VA_ARG (Args, UINT8 *); + if (Cert == NULL) { + break; + } + + CertSize = VA_ARG (Args, UINTN); + if (CertSize == 0) { + break; + } + + // + // Construct X509 Object from the given DER-encoded certificate data. + // + X509Cert = NULL; + Status = X509ConstructCertificate ( + (CONST UINT8 *) Cert, + CertSize, + (UINT8 **) &X509Cert + ); + if (!Status) { + if (X509Cert != NULL) { + X509_free (X509Cert); + } + break; + } + + // + // Insert the new X509 object into X509 stack object. + // + sk_X509_push (CertStack, X509Cert); + } + + VA_END (Args); + + if (!Status) { + sk_X509_pop_free (CertStack, X509_free); + } else { + *X509Stack = (UINT8 *) CertStack; + } + + return Status; +} + +/** + Release the specified X509 object. + + If X509Cert is NULL, then return FALSE. + + @param[in] X509Cert Pointer to the X509 object to be released. + +**/ +VOID +EFIAPI +X509Free ( + IN VOID *X509Cert + ) +{ + // + // Check input parameters. + // + if (X509Cert == NULL) { + return; + } + + // + // Free OpenSSL X509 object. + // + X509_free ((X509 *) X509Cert); +} + +/** + Release the specified X509 stack object. + + If X509Stack is NULL, then return FALSE. + + @param[in] X509Stack Pointer to the X509 stack object to be released. + +**/ +VOID +EFIAPI +X509StackFree ( + IN VOID *X509Stack + ) +{ + // + // Check input parameters. + // + if (X509Stack == NULL) { + return; + } + + // + // Free OpenSSL X509 stack object. + // + sk_X509_pop_free ((STACK_OF(X509) *) X509Stack, X509_free); +} + +/** + Retrieve the subject bytes from one X.509 certificate. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CertSubject Pointer to the retrieved certificate subject bytes. + @param[in, out] SubjectSize The size in bytes of the CertSubject buffer on input, + and the size of buffer returned CertSubject on output. + + If Cert is NULL, then return FALSE. + If SubjectSize is NULL, then return FALSE. + + @retval TRUE The certificate subject retrieved successfully. + @retval FALSE Invalid certificate, or the SubjectSize is too small for the result. + The SubjectSize will be updated with the required size. + +**/ +BOOLEAN +EFIAPI +X509GetSubjectName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *CertSubject, + IN OUT UINTN *SubjectSize + ) +{ + BOOLEAN Status; + X509 *X509Cert; + X509_NAME *X509Name; + UINTN X509NameSize; + + // + // Check input parameters. + // + if (Cert == NULL || SubjectSize == NULL) { + return FALSE; + } + + X509Cert = NULL; + + // + // Read DER-encoded X509 Certificate and Construct X509 object. + // + Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert); + if ((X509Cert == NULL) || (!Status)) { + Status = FALSE; + goto _Exit; + } + + Status = FALSE; + + // + // Retrieve subject name from certificate object. + // + X509Name = X509_get_subject_name (X509Cert); + if (X509Name == NULL) { + goto _Exit; + } + + X509NameSize = i2d_X509_NAME(X509Name, NULL); + if (*SubjectSize < X509NameSize) { + *SubjectSize = X509NameSize; + goto _Exit; + } + *SubjectSize = X509NameSize; + if (CertSubject != NULL) { + i2d_X509_NAME(X509Name, &CertSubject); + Status = TRUE; + } + +_Exit: + // + // Release Resources. + // + if (X509Cert != NULL) { + X509_free (X509Cert); + } + + return Status; +} + +/** + Retrieve the common name (CN) string from one X.509 certificate. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CommonName Buffer to contain the retrieved certificate common + name string (UTF8). At most CommonNameSize bytes will be + written and the string will be null terminated. May be + NULL in order to determine the size buffer needed. + @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input, + and the size of buffer returned CommonName on output. + If CommonName is NULL then the amount of space needed + in buffer (including the final null) is returned. + + @retval RETURN_SUCCESS The certificate CommonName retrieved successfully. + @retval RETURN_INVALID_PARAMETER If Cert is NULL. + If CommonNameSize is NULL. + If CommonName is not NULL and *CommonNameSize is 0. + If Certificate is invalid. + @retval RETURN_NOT_FOUND If no CommonName entry exists. + @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size + (including the final null) is returned in the + CommonNameSize parameter. + @retval RETURN_UNSUPPORTED The operation is not supported. + +**/ +RETURN_STATUS +EFIAPI +X509GetCommonName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT CHAR8 *CommonName, OPTIONAL + IN OUT UINTN *CommonNameSize + ) +{ + RETURN_STATUS ReturnStatus; + BOOLEAN Status; + X509 *X509Cert; + X509_NAME *X509Name; + INT32 Index; + INTN Length; + X509_NAME_ENTRY *Entry; + ASN1_STRING *EntryData; + UINT8 *UTF8Name; + + ReturnStatus = RETURN_INVALID_PARAMETER; + UTF8Name = NULL; + + // + // Check input parameters. + // + if ((Cert == NULL) || (CertSize > INT_MAX) || (CommonNameSize == NULL)) { + return ReturnStatus; + } + if ((CommonName != NULL) && (*CommonNameSize == 0)) { + return ReturnStatus; + } + + X509Cert = NULL; + // + // Read DER-encoded X509 Certificate and Construct X509 object. + // + Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert); + if ((X509Cert == NULL) || (!Status)) { + // + // Invalid X.509 Certificate + // + goto _Exit; + } + + Status = FALSE; + + // + // Retrieve subject name from certificate object. + // + X509Name = X509_get_subject_name (X509Cert); + if (X509Name == NULL) { + // + // Fail to retrieve subject name content + // + goto _Exit; + } + + // + // Retrieve the CommonName information from X.509 Subject + // + Index = X509_NAME_get_index_by_NID (X509Name, NID_commonName, -1); + if (Index < 0) { + // + // No CommonName entry exists in X509_NAME object + // + *CommonNameSize = 0; + ReturnStatus = RETURN_NOT_FOUND; + goto _Exit; + } + + Entry = X509_NAME_get_entry (X509Name, Index); + if (Entry == NULL) { + // + // Fail to retrieve name entry data + // + *CommonNameSize = 0; + ReturnStatus = RETURN_NOT_FOUND; + goto _Exit; + } + + EntryData = X509_NAME_ENTRY_get_data (Entry); + + Length = ASN1_STRING_to_UTF8 (&UTF8Name, EntryData); + if (Length < 0) { + // + // Fail to convert the commonName string + // + *CommonNameSize = 0; + ReturnStatus = RETURN_INVALID_PARAMETER; + goto _Exit; + } + + if (CommonName == NULL) { + *CommonNameSize = Length + 1; + ReturnStatus = RETURN_BUFFER_TOO_SMALL; + } else { + *CommonNameSize = MIN ((UINTN)Length, *CommonNameSize - 1) + 1; + CopyMem (CommonName, UTF8Name, *CommonNameSize - 1); + CommonName[*CommonNameSize - 1] = '\0'; + ReturnStatus = RETURN_SUCCESS; + } + +_Exit: + // + // Release Resources. + // + if (X509Cert != NULL) { + X509_free (X509Cert); + } + if (UTF8Name != NULL) { + OPENSSL_free (UTF8Name); + } + + return ReturnStatus; +} + +/** + Retrieve the RSA Public Key from one DER-encoded X509 certificate. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA public key component. Use RsaFree() function to free the + resource. + + If Cert is NULL, then return FALSE. + If RsaContext is NULL, then return FALSE. + + @retval TRUE RSA Public Key was retrieved successfully. + @retval FALSE Fail to retrieve RSA public key from X509 certificate. + +**/ +BOOLEAN +EFIAPI +RsaGetPublicKeyFromX509 ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT VOID **RsaContext + ) +{ + BOOLEAN Status; + EVP_PKEY *Pkey; + X509 *X509Cert; + + // + // Check input parameters. + // + if (Cert == NULL || RsaContext == NULL) { + return FALSE; + } + + Pkey = NULL; + X509Cert = NULL; + + // + // Read DER-encoded X509 Certificate and Construct X509 object. + // + Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert); + if ((X509Cert == NULL) || (!Status)) { + Status = FALSE; + goto _Exit; + } + + Status = FALSE; + + // + // Retrieve and check EVP_PKEY data from X509 Certificate. + // + Pkey = X509_get_pubkey (X509Cert); + if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_RSA)) { + goto _Exit; + } + + // + // Duplicate RSA Context from the retrieved EVP_PKEY. + // + if ((*RsaContext = RSAPublicKey_dup (EVP_PKEY_get0_RSA (Pkey))) != NULL) { + Status = TRUE; + } + +_Exit: + // + // Release Resources. + // + if (X509Cert != NULL) { + X509_free (X509Cert); + } + + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); + } + + return Status; +} + +/** + Verify one X509 certificate was issued by the trusted CA. + + @param[in] Cert Pointer to the DER-encoded X509 certificate to be verified. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[in] CACert Pointer to the DER-encoded trusted CA certificate. + @param[in] CACertSize Size of the CA Certificate in bytes. + + If Cert is NULL, then return FALSE. + If CACert is NULL, then return FALSE. + + @retval TRUE The certificate was issued by the trusted CA. + @retval FALSE Invalid certificate or the certificate was not issued by the given + trusted CA. + +**/ +BOOLEAN +EFIAPI +X509VerifyCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST UINT8 *CACert, + IN UINTN CACertSize + ) +{ + BOOLEAN Status; + X509 *X509Cert; + X509 *X509CACert; + X509_STORE *CertStore; + X509_STORE_CTX *CertCtx; + + // + // Check input parameters. + // + if (Cert == NULL || CACert == NULL) { + return FALSE; + } + + Status = FALSE; + X509Cert = NULL; + X509CACert = NULL; + CertStore = NULL; + CertCtx = NULL; + + // + // Register & Initialize necessary digest algorithms for certificate verification. + // + if (EVP_add_digest (EVP_md5 ()) == 0) { + goto _Exit; + } + if (EVP_add_digest (EVP_sha1 ()) == 0) { + goto _Exit; + } + if (EVP_add_digest (EVP_sha256 ()) == 0) { + goto _Exit; + } + + // + // Read DER-encoded certificate to be verified and Construct X509 object. + // + Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert); + if ((X509Cert == NULL) || (!Status)) { + Status = FALSE; + goto _Exit; + } + + // + // Read DER-encoded root certificate and Construct X509 object. + // + Status = X509ConstructCertificate (CACert, CACertSize, (UINT8 **) &X509CACert); + if ((X509CACert == NULL) || (!Status)) { + Status = FALSE; + goto _Exit; + } + + Status = FALSE; + + // + // Set up X509 Store for trusted certificate. + // + CertStore = X509_STORE_new (); + if (CertStore == NULL) { + goto _Exit; + } + if (!(X509_STORE_add_cert (CertStore, X509CACert))) { + goto _Exit; + } + + // + // Allow partial certificate chains, terminated by a non-self-signed but + // still trusted intermediate certificate. Also disable time checks. + // + X509_STORE_set_flags (CertStore, + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME); + + // + // Set up X509_STORE_CTX for the subsequent verification operation. + // + CertCtx = X509_STORE_CTX_new (); + if (CertCtx == NULL) { + goto _Exit; + } + if (!X509_STORE_CTX_init (CertCtx, CertStore, X509Cert, NULL)) { + goto _Exit; + } + + // + // X509 Certificate Verification. + // + Status = (BOOLEAN) X509_verify_cert (CertCtx); + X509_STORE_CTX_cleanup (CertCtx); + +_Exit: + // + // Release Resources. + // + if (X509Cert != NULL) { + X509_free (X509Cert); + } + + if (X509CACert != NULL) { + X509_free (X509CACert); + } + + if (CertStore != NULL) { + X509_STORE_free (CertStore); + } + + X509_STORE_CTX_free (CertCtx); + + return Status; +} + +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + If Cert is NULL, then return FALSE. + If TBSCert is NULL, then return FALSE. + If TBSCertSize is NULL, then return FALSE. + + @retval TRUE The TBSCertificate was retrieved successfully. + @retval FALSE Invalid X.509 certificate. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ) +{ + CONST UINT8 *Temp; + UINT32 Asn1Tag; + UINT32 ObjClass; + UINTN Length; + + // + // Check input parameters. + // + if ((Cert == NULL) || (TBSCert == NULL) || + (TBSCertSize == NULL) || (CertSize > INT_MAX)) { + return FALSE; + } + + // + // An X.509 Certificate is: (defined in RFC3280) + // Certificate ::= SEQUENCE { + // tbsCertificate TBSCertificate, + // signatureAlgorithm AlgorithmIdentifier, + // signature BIT STRING } + // + // and + // + // TBSCertificate ::= SEQUENCE { + // version [0] Version DEFAULT v1, + // ... + // } + // + // So we can just ASN1-parse the x.509 DER-encoded data. If we strip + // the first SEQUENCE, the second SEQUENCE is the TBSCertificate. + // + Temp = Cert; + Length = 0; + ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)CertSize); + + if (Asn1Tag != V_ASN1_SEQUENCE) { + return FALSE; + } + + *TBSCert = (UINT8 *)Temp; + + ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length); + // + // Verify the parsed TBSCertificate is one correct SEQUENCE data. + // + if (Asn1Tag != V_ASN1_SEQUENCE) { + return FALSE; + } + + *TBSCertSize = Length + (Temp - *TBSCert); + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c new file mode 100644 index 0000000..86b56eb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c @@ -0,0 +1,238 @@ +/** @file + X.509 Certificate Handler Wrapper Implementation which does not provide + real capabilities. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + +/** + Construct a X509 object from DER-encoded certificate data. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the DER-encoded certificate data. + @param[in] CertSize The size of certificate data in bytes. + @param[out] SingleX509Cert The generated X509 object. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509ConstructCertificate ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **SingleX509Cert + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Construct a X509 stack object from a list of DER-encoded certificate data. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object. + On output, pointer to the X509 stack object with new + inserted X509 certificate. + @param ... A list of DER-encoded single certificate data followed + by certificate size. A NULL terminates the list. The + pairs are the arguments to X509ConstructCertificate(). + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509ConstructCertificateStack ( + IN OUT UINT8 **X509Stack, + ... + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Release the specified X509 object. + + If the interface is not supported, then ASSERT(). + + @param[in] X509Cert Pointer to the X509 object to be released. + +**/ +VOID +EFIAPI +X509Free ( + IN VOID *X509Cert + ) +{ + ASSERT (FALSE); +} + +/** + Release the specified X509 stack object. + + If the interface is not supported, then ASSERT(). + + @param[in] X509Stack Pointer to the X509 stack object to be released. + +**/ +VOID +EFIAPI +X509StackFree ( + IN VOID *X509Stack + ) +{ + ASSERT (FALSE); +} + +/** + Retrieve the subject bytes from one X.509 certificate. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CertSubject Pointer to the retrieved certificate subject bytes. + @param[in, out] SubjectSize The size in bytes of the CertSubject buffer on input, + and the size of buffer returned CertSubject on output. + + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetSubjectName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 *CertSubject, + IN OUT UINTN *SubjectSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Retrieve the common name (CN) string from one X.509 certificate. + + Return RETURN_UNSUPPORTED to indicate this interface is not supported. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] CommonName Buffer to contain the retrieved certificate common + name string (UTF8). At most CommonNameSize bytes will be + written and the string will be null terminated. May be + NULL in order to determine the size buffer needed. + @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input, + and the size of buffer returned CommonName on output. + If CommonName is NULL then the amount of space needed + in buffer (including the final null) is returned. + + @retval RETURN_UNSUPPORTED The operation is not supported. + +**/ +RETURN_STATUS +EFIAPI +X509GetCommonName ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT CHAR8 *CommonName, OPTIONAL + IN OUT UINTN *CommonNameSize + ) +{ + ASSERT (FALSE); + return RETURN_UNSUPPORTED; +} + +/** + Retrieve the RSA Public Key from one DER-encoded X509 certificate. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA public key component. Use RsaFree() function to free the + resource. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetPublicKeyFromX509 ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT VOID **RsaContext + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Verify one X509 certificate was issued by the trusted CA. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the DER-encoded X509 certificate to be verified. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[in] CACert Pointer to the DER-encoded trusted CA certificate. + @param[in] CACertSize Size of the CA Certificate in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509VerifyCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST UINT8 *CACert, + IN UINTN CACertSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Retrieve the TBSCertificate from one given X.509 certificate. + + Return FALSE to indicate this interface is not supported. + + @param[in] Cert Pointer to the given DER-encoded X509 certificate. + @param[in] CertSize Size of the X509 certificate in bytes. + @param[out] TBSCert DER-Encoded To-Be-Signed certificate. + @param[out] TBSCertSize Size of the TBS certificate in bytes. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +X509GetTBSCert ( + IN CONST UINT8 *Cert, + IN UINTN CertSize, + OUT UINT8 **TBSCert, + OUT UINTN *TBSCertSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c new file mode 100644 index 0000000..e1ee0d0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c @@ -0,0 +1,110 @@ +/** @file + Pseudorandom Number Generator Wrapper Implementation over OpenSSL. + +Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include + +// +// Default seed for UEFI Crypto Library +// +CONST UINT8 DefaultSeed[] = "UEFI Crypto Library default seed"; + +/** + Sets up the seed value for the pseudorandom number generator. + + This function sets up the seed value for the pseudorandom number generator. + If Seed is not NULL, then the seed passed in is used. + If Seed is NULL, then default seed is used. + + @param[in] Seed Pointer to seed value. + If NULL, default seed is used. + @param[in] SeedSize Size of seed value. + If Seed is NULL, this parameter is ignored. + + @retval TRUE Pseudorandom number generator has enough entropy for random generation. + @retval FALSE Pseudorandom number generator does not have enough entropy for random generation. + +**/ +BOOLEAN +EFIAPI +RandomSeed ( + IN CONST UINT8 *Seed OPTIONAL, + IN UINTN SeedSize + ) +{ + if (SeedSize > INT_MAX) { + return FALSE; + } + + // + // The software PRNG implementation built in OpenSSL depends on message digest algorithm. + // Make sure SHA-1 digest algorithm is available here. + // + if (EVP_add_digest (EVP_sha1 ()) == 0) { + return FALSE; + } + + // + // Seed the pseudorandom number generator with user-supplied value. + // NOTE: A cryptographic PRNG must be seeded with unpredictable data. + // + if (Seed != NULL) { + RAND_seed (Seed, (UINT32) SeedSize); + } else { + RAND_seed (DefaultSeed, sizeof (DefaultSeed)); + } + + if (RAND_status () == 1) { + return TRUE; + } + + return FALSE; +} + +/** + Generates a pseudorandom byte stream of the specified size. + + If Output is NULL, then return FALSE. + + @param[out] Output Pointer to buffer to receive random value. + @param[in] Size Size of random bytes to generate. + + @retval TRUE Pseudorandom byte stream generated successfully. + @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy. + +**/ +BOOLEAN +EFIAPI +RandomBytes ( + OUT UINT8 *Output, + IN UINTN Size + ) +{ + // + // Check input parameters. + // + if (Output == NULL || Size > INT_MAX) { + return FALSE; + } + + // + // Generate random data. + // + if (RAND_bytes (Output, (UINT32) Size) != 1) { + return FALSE; + } + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandItc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandItc.c new file mode 100644 index 0000000..01227dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandItc.c @@ -0,0 +1,118 @@ +/** @file + Pseudorandom Number Generator Wrapper Implementation over OpenSSL. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include +#include + +/** + Sets up the seed value for the pseudorandom number generator. + + This function sets up the seed value for the pseudorandom number generator. + If Seed is not NULL, then the seed passed in is used. + If Seed is NULL, then default seed is used. + + @param[in] Seed Pointer to seed value. + If NULL, default seed is used. + @param[in] SeedSize Size of seed value. + If Seed is NULL, this parameter is ignored. + + @retval TRUE Pseudorandom number generator has enough entropy for random generation. + @retval FALSE Pseudorandom number generator does not have enough entropy for random generation. + +**/ +BOOLEAN +EFIAPI +RandomSeed ( + IN CONST UINT8 *Seed OPTIONAL, + IN UINTN SeedSize + ) +{ + CHAR8 DefaultSeed[128]; + + if (SeedSize > INT_MAX) { + return FALSE; + } + + // + // The software PRNG implementation built in OpenSSL depends on message digest algorithm. + // Make sure SHA-1 digest algorithm is available here. + // + if (EVP_add_digest (EVP_sha1 ()) == 0) { + return FALSE; + } + + // + // Seed the pseudorandom number generator with user-supplied value. + // NOTE: A cryptographic PRNG must be seeded with unpredictable data. + // + if (Seed != NULL) { + RAND_seed (Seed, (UINT32) SeedSize); + } else { + // + // Retrieve current time. + // + AsciiSPrint ( + DefaultSeed, + sizeof (DefaultSeed), + "UEFI Crypto Library default seed (%ld)", + AsmReadItc () + ); + + RAND_seed (DefaultSeed, sizeof (DefaultSeed)); + } + + if (RAND_status () == 1) { + return TRUE; + } + + return FALSE; +} + +/** + Generates a pseudorandom byte stream of the specified size. + + If Output is NULL, then return FALSE. + + @param[out] Output Pointer to buffer to receive random value. + @param[in] Size Size of random bytes to generate. + + @retval TRUE Pseudorandom byte stream generated successfully. + @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy. + +**/ +BOOLEAN +EFIAPI +RandomBytes ( + OUT UINT8 *Output, + IN UINTN Size + ) +{ + // + // Check input parameters. + // + if (Output == NULL || Size > INT_MAX) { + return FALSE; + } + + // + // Generate random data. + // + if (RAND_bytes (Output, (UINT32) Size) != 1) { + return FALSE; + } + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandNull.c new file mode 100644 index 0000000..ef9c5bd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandNull.c @@ -0,0 +1,63 @@ +/** @file + Pseudorandom Number Generator Wrapper Implementation which does not provide + real capabilities. + +Copyright (c) 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" + + +/** + Sets up the seed value for the pseudorandom number generator. + + Return FALSE to indicate this interface is not supported. + + @param[in] Seed Pointer to seed value. + If NULL, default seed is used. + @param[in] SeedSize Size of seed value. + If Seed is NULL, this parameter is ignored. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RandomSeed ( + IN CONST UINT8 *Seed OPTIONAL, + IN UINTN SeedSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Generates a pseudorandom byte stream of the specified size. + + Return FALSE to indicate this interface is not supported. + + @param[out] Output Pointer to buffer to receive random value. + @param[in] Size Size of random bytes to generate. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RandomBytes ( + OUT UINT8 *Output, + IN UINTN Size + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c new file mode 100644 index 0000000..349d0a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c @@ -0,0 +1,118 @@ +/** @file + Pseudorandom Number Generator Wrapper Implementation over OpenSSL. + +Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalCryptLib.h" +#include +#include +#include + +/** + Sets up the seed value for the pseudorandom number generator. + + This function sets up the seed value for the pseudorandom number generator. + If Seed is not NULL, then the seed passed in is used. + If Seed is NULL, then default seed is used. + + @param[in] Seed Pointer to seed value. + If NULL, default seed is used. + @param[in] SeedSize Size of seed value. + If Seed is NULL, this parameter is ignored. + + @retval TRUE Pseudorandom number generator has enough entropy for random generation. + @retval FALSE Pseudorandom number generator does not have enough entropy for random generation. + +**/ +BOOLEAN +EFIAPI +RandomSeed ( + IN CONST UINT8 *Seed OPTIONAL, + IN UINTN SeedSize + ) +{ + CHAR8 DefaultSeed[128]; + + if (SeedSize > INT_MAX) { + return FALSE; + } + + // + // The software PRNG implementation built in OpenSSL depends on message digest algorithm. + // Make sure SHA-1 digest algorithm is available here. + // + if (EVP_add_digest (EVP_sha1 ()) == 0) { + return FALSE; + } + + // + // Seed the pseudorandom number generator with user-supplied value. + // NOTE: A cryptographic PRNG must be seeded with unpredictable data. + // + if (Seed != NULL) { + RAND_seed (Seed, (UINT32) SeedSize); + } else { + // + // Retrieve current time. + // + AsciiSPrint ( + DefaultSeed, + sizeof (DefaultSeed), + "UEFI Crypto Library default seed (%ld)", + AsmReadTsc () + ); + + RAND_seed (DefaultSeed, sizeof (DefaultSeed)); + } + + if (RAND_status () == 1) { + return TRUE; + } + + return FALSE; +} + +/** + Generates a pseudorandom byte stream of the specified size. + + If Output is NULL, then return FALSE. + + @param[out] Output Pointer to buffer to receive random value. + @param[in] Size Size of random bytes to generate. + + @retval TRUE Pseudorandom byte stream generated successfully. + @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy. + +**/ +BOOLEAN +EFIAPI +RandomBytes ( + OUT UINT8 *Output, + IN UINTN Size + ) +{ + // + // Check input parameters. + // + if (Output == NULL || Size > INT_MAX) { + return FALSE; + } + + // + // Generate random data. + // + if (RAND_bytes (Output, (UINT32) Size) != 1) { + return FALSE; + } + + return TRUE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf new file mode 100644 index 0000000..71ba8bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf @@ -0,0 +1,107 @@ +## @file +# Cryptographic Library Instance for DXE_RUNTIME_DRIVER. +# +# Caution: This module requires additional review when modified. +# This library will have external input - signature. +# This external input must be validated carefully to avoid security issues such as +# buffer overflow or integer overflow. +# +# Note: MD4 Digest functions, SHA-384 Digest functions, SHA-512 Digest functions, +# HMAC-MD5 functions, HMAC-SHA1/SHA256 functions, AES/TDES/ARC4 functions, RSA external +# functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and +# authenticode signature verification functions are not supported in this instance. +# +# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = RuntimeCryptLib + MODULE_UNI_FILE = RuntimeCryptLib.uni + FILE_GUID = 78189cc0-727d-46a4-84ea-f7dd860de64a + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseCryptLib|DXE_RUNTIME_DRIVER + CONSTRUCTOR = RuntimeCryptLibConstructor + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + Hash/CryptMd4Null.c + Hash/CryptMd5.c + Hash/CryptSha1.c + Hash/CryptSha256.c + Hash/CryptSha512Null.c + Hmac/CryptHmacMd5Null.c + Hmac/CryptHmacSha1Null.c + Hmac/CryptHmacSha256Null.c + Cipher/CryptAesNull.c + Cipher/CryptTdesNull.c + Cipher/CryptArc4Null.c + Pk/CryptRsaBasic.c + Pk/CryptRsaExtNull.c + Pk/CryptPkcs5Pbkdf2Null.c + Pk/CryptPkcs7SignNull.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyRuntime.c + Pk/CryptDhNull.c + Pk/CryptX509.c + Pk/CryptAuthenticodeNull.c + Pk/CryptTsNull.c + Pem/CryptPem.c + + SysCall/CrtWrapper.c + SysCall/TimerWrapper.c + SysCall/RuntimeMemAllocation.c + +[Sources.Ia32] + Rand/CryptRandTsc.c + +[Sources.X64] + Rand/CryptRandTsc.c + +[Sources.ARM] + Rand/CryptRand.c + +[Sources.AARCH64] + Rand/CryptRand.c + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DebugLib + OpensslLib + IntrinsicLib + PrintLib + +# +# Remove these [BuildOptions] after this library is cleaned up +# +[BuildOptions] + # + # suppress the following warnings so we do not break the build with warnings-as-errors: + # C4090: 'function' : different 'const' qualifiers + # + MSFT:*_*_*_CC_FLAGS = /wd4090 + + # -JCryptoPkg/Include : To disable the use of the system includes provided by RVCT + # --diag_remark=1 : Reduce severity of "#1-D: last line of file ends without a newline" + RVCT:*_*_ARM_CC_FLAGS = -JCryptoPkg/Include --diag_remark=1 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.uni new file mode 100644 index 0000000..601ed80 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.uni @@ -0,0 +1,30 @@ +// /** @file +// Cryptographic Library Instance for DXE_RUNTIME_DRIVER. +// +// Caution: This module requires additional review when modified. +// This library will have external input - signature. +// This external input must be validated carefully to avoid security issues such as +// buffer overflow or integer overflow. +// +// Note: MD4 Digest functions, HMAC-MD5 functions, HMAC-SHA1 functions, AES/ +// TDES/ARC4 functions, RSA external functions, PKCS#7 SignedData sign functions, +// Diffie-Hellman functions, and authenticode signature verification functions are +// not supported in this instance. +// +// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Cryptographic Library Instance for DXE_RUNTIME_DRIVER" + +#string STR_MODULE_DESCRIPTION #language en-US "Caution: This module requires additional review when modified. This library will have external input - signature. This external input must be validated carefully to avoid security issues such as buffer overflow or integer overflow. Note: MD4 Digest functions, HMAC-MD5 functions, HMAC-SHA1 functions, AES/ TDES/ARC4 functions, RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and authenticode signature verification functions are not supported in this instance." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf new file mode 100644 index 0000000..c1b39f9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf @@ -0,0 +1,104 @@ +## @file +# Cryptographic Library Instance for SMM driver. +# +# Caution: This module requires additional review when modified. +# This library will have external input - signature. +# This external input must be validated carefully to avoid security issues such as +# buffer overflow or integer overflow. +# +# Note: MD4 Digest functions, SHA-384 Digest functions, SHA-512 Digest functions, +# HMAC-MD5 functions, HMAC-SHA1 functions, TDES/ARC4 functions, RSA external +# functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and +# authenticode signature verification functions are not supported in this instance. +# +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmCryptLib + MODULE_UNI_FILE = SmmCryptLib.uni + FILE_GUID = 028080a3-8958-4a62-a1a8-0fa1da162007 + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + LIBRARY_CLASS = BaseCryptLib|DXE_SMM_DRIVER SMM_CORE MM_STANDALONE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + Hash/CryptMd4Null.c + Hash/CryptMd5.c + Hash/CryptSha1.c + Hash/CryptSha256.c + Hash/CryptSha512Null.c + Hmac/CryptHmacMd5Null.c + Hmac/CryptHmacSha1Null.c + Hmac/CryptHmacSha256.c + Cipher/CryptAes.c + Cipher/CryptTdesNull.c + Cipher/CryptArc4Null.c + Pk/CryptRsaBasic.c + Pk/CryptRsaExtNull.c + Pk/CryptPkcs5Pbkdf2.c + Pk/CryptPkcs7SignNull.c + Pk/CryptPkcs7VerifyCommon.c + Pk/CryptPkcs7VerifyBase.c + Pk/CryptDhNull.c + Pk/CryptX509.c + Pk/CryptAuthenticodeNull.c + Pk/CryptTsNull.c + Pem/CryptPem.c + + SysCall/CrtWrapper.c + SysCall/ConstantTimeClock.c + SysCall/BaseMemAllocation.c + +[Sources.Ia32] + Rand/CryptRandTsc.c + +[Sources.X64] + Rand/CryptRandTsc.c + +[Sources.ARM] + Rand/CryptRand.c + +[Sources.AARCH64] + Rand/CryptRand.c + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseLib + IoLib + BaseMemoryLib + MemoryAllocationLib + OpensslLib + IntrinsicLib + PrintLib + +# +# Remove these [BuildOptions] after this library is cleaned up +# +[BuildOptions] + # + # suppress the following warnings so we do not break the build with warnings-as-errors: + # C4090: 'function' : different 'const' qualifiers + # + MSFT:*_*_*_CC_FLAGS = /wd4090 + + XCODE:*_*_*_CC_FLAGS = -mmmx -msse diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.uni new file mode 100644 index 0000000..261d0fe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.uni @@ -0,0 +1,30 @@ +// /** @file +// Cryptographic Library Instance for SMM driver. +// +// Caution: This module requires additional review when modified. +// This library will have external input - signature. +// This external input must be validated carefully to avoid security issues such as +// buffer overflow or integer overflow. +// +// Note: MD4 Digest functions, HMAC-MD5 functions, HMAC-SHA1 functions, AES/ +// TDES/ARC4 functions, RSA external functions, PKCS#7 SignedData sign functions, +// Diffie-Hellman functions, and authenticode signature verification functions are +// not supported in this instance. +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Cryptographic Library Instance for SMM driver" + +#string STR_MODULE_DESCRIPTION #language en-US "Caution: This module requires additional review when modified. This library will have external input - signature. This external input must be validated carefully to avoid security issues such as buffer overflow or integer overflow. Note: MD4 Digest functions, HMAC-MD5 functions, HMAC-SHA1 functions, AES/ TDES/ARC4 functions, RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and authenticode signature verification functions are not supported in this instance." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/BaseMemAllocation.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/BaseMemAllocation.c new file mode 100644 index 0000000..e0c32ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/BaseMemAllocation.c @@ -0,0 +1,118 @@ +/** @file + Base Memory Allocation Routines Wrapper for Crypto library over OpenSSL + during PEI & DXE phases. + +Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +// +// Extra header to record the memory buffer size from malloc routine. +// +#define CRYPTMEM_HEAD_SIGNATURE SIGNATURE_32('c','m','h','d') +typedef struct { + UINT32 Signature; + UINT32 Reserved; + UINTN Size; +} CRYPTMEM_HEAD; + +#define CRYPTMEM_OVERHEAD sizeof(CRYPTMEM_HEAD) + +// +// -- Memory-Allocation Routines -- +// + +/* Allocates memory blocks */ +void *malloc (size_t size) +{ + CRYPTMEM_HEAD *PoolHdr; + UINTN NewSize; + VOID *Data; + + // + // Adjust the size by the buffer header overhead + // + NewSize = (UINTN)(size) + CRYPTMEM_OVERHEAD; + + Data = AllocatePool (NewSize); + if (Data != NULL) { + PoolHdr = (CRYPTMEM_HEAD *)Data; + // + // Record the memory brief information + // + PoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE; + PoolHdr->Size = size; + + return (VOID *)(PoolHdr + 1); + } else { + // + // The buffer allocation failed. + // + return NULL; + } +} + +/* Reallocate memory blocks */ +void *realloc (void *ptr, size_t size) +{ + CRYPTMEM_HEAD *OldPoolHdr; + CRYPTMEM_HEAD *NewPoolHdr; + UINTN OldSize; + UINTN NewSize; + VOID *Data; + + NewSize = (UINTN)size + CRYPTMEM_OVERHEAD; + Data = AllocatePool (NewSize); + if (Data != NULL) { + NewPoolHdr = (CRYPTMEM_HEAD *)Data; + NewPoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE; + NewPoolHdr->Size = size; + if (ptr != NULL) { + // + // Retrieve the original size from the buffer header. + // + OldPoolHdr = (CRYPTMEM_HEAD *)ptr - 1; + ASSERT (OldPoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE); + OldSize = OldPoolHdr->Size; + + // + // Duplicate the buffer content. + // + CopyMem ((VOID *)(NewPoolHdr + 1), ptr, MIN (OldSize, size)); + FreePool ((VOID *)OldPoolHdr); + } + + return (VOID *)(NewPoolHdr + 1); + } else { + // + // The buffer allocation failed. + // + return NULL; + } +} + +/* De-allocates or frees a memory block */ +void free (void *ptr) +{ + CRYPTMEM_HEAD *PoolHdr; + + // + // In Standard C, free() handles a null pointer argument transparently. This + // is not true of FreePool() below, so protect it. + // + if (ptr != NULL) { + PoolHdr = (CRYPTMEM_HEAD *)ptr - 1; + ASSERT (PoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE); + FreePool (PoolHdr); + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/ConstantTimeClock.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/ConstantTimeClock.c new file mode 100644 index 0000000..6904a19 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/ConstantTimeClock.c @@ -0,0 +1,43 @@ +/** @file + C Run-Time Libraries (CRT) Time Management Routines Wrapper Implementation + for OpenSSL-based Cryptographic Library. + + This C file implements constant time value for time() and NULL for gmtime() + thus should not be used in library instances which require functionality + of following APIs which need system time support: + 1) RsaGenerateKey + 2) RsaCheckKey + 3) RsaPkcs1Sign + 4) Pkcs7Sign + 5) DhGenerateParameter + 6) DhGenerateKey + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +// +// -- Time Management Routines -- +// + +time_t time (time_t *timer) +{ + if (timer != NULL) { + *timer = 0; + } + return 0; +} + +struct tm * gmtime (const time_t *timer) +{ + return NULL; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c new file mode 100644 index 0000000..c98a36e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c @@ -0,0 +1,474 @@ +/** @file + C Run-Time Libraries (CRT) Wrapper Implementation for OpenSSL-based + Cryptographic Library. + +Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +int errno = 0; + +FILE *stderr = NULL; +FILE *stdin = NULL; +FILE *stdout = NULL; + +typedef +int +(*SORT_COMPARE)( + IN VOID *Buffer1, + IN VOID *Buffer2 + ); + +// +// Duplicated from EDKII BaseSortLib for qsort() wrapper +// +STATIC +VOID +QuickSortWorker ( + IN OUT VOID *BufferToSort, + IN CONST UINTN Count, + IN CONST UINTN ElementSize, + IN SORT_COMPARE CompareFunction, + IN VOID *Buffer + ) +{ + VOID *Pivot; + UINTN LoopCount; + UINTN NextSwapLocation; + + ASSERT(BufferToSort != NULL); + ASSERT(CompareFunction != NULL); + ASSERT(Buffer != NULL); + + if (Count < 2 || ElementSize < 1) { + return; + } + + NextSwapLocation = 0; + + // + // Pick a pivot (we choose last element) + // + Pivot = ((UINT8 *)BufferToSort + ((Count - 1) * ElementSize)); + + // + // Now get the pivot such that all on "left" are below it + // and everything "right" are above it + // + for (LoopCount = 0; LoopCount < Count - 1; LoopCount++) + { + // + // If the element is less than the pivot + // + if (CompareFunction ((VOID *)((UINT8 *)BufferToSort + ((LoopCount) * ElementSize)), Pivot) <= 0) { + // + // Swap + // + CopyMem (Buffer, (UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), ElementSize); + CopyMem ((UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), (UINT8 *)BufferToSort + ((LoopCount) * ElementSize), ElementSize); + CopyMem ((UINT8 *)BufferToSort + ((LoopCount) * ElementSize), Buffer, ElementSize); + + // + // Increment NextSwapLocation + // + NextSwapLocation++; + } + } + // + // Swap pivot to its final position (NextSwapLocation) + // + CopyMem (Buffer, Pivot, ElementSize); + CopyMem (Pivot, (UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), ElementSize); + CopyMem ((UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), Buffer, ElementSize); + + // + // Now recurse on 2 partial lists. Neither of these will have the 'pivot' element. + // IE list is sorted left half, pivot element, sorted right half... + // + QuickSortWorker ( + BufferToSort, + NextSwapLocation, + ElementSize, + CompareFunction, + Buffer + ); + + QuickSortWorker ( + (UINT8 *)BufferToSort + (NextSwapLocation + 1) * ElementSize, + Count - NextSwapLocation - 1, + ElementSize, + CompareFunction, + Buffer + ); + + return; +} + +//--------------------------------------------------------- +// Standard C Run-time Library Interface Wrapper +//--------------------------------------------------------- + +// +// -- String Manipulation Routines -- +// + +/* Scan a string for the last occurrence of a character */ +char *strrchr (const char *str, int c) +{ + char * save; + + for (save = NULL; ; ++str) { + if (*str == c) { + save = (char *)str; + } + if (*str == 0) { + return (save); + } + } +} + +/* Compare first n bytes of string s1 with string s2, ignoring case */ +int strncasecmp (const char *s1, const char *s2, size_t n) +{ + int Val; + + ASSERT(s1 != NULL); + ASSERT(s2 != NULL); + + if (n != 0) { + do { + Val = tolower(*s1) - tolower(*s2); + if (Val != 0) { + return Val; + } + ++s1; + ++s2; + if (*s1 == '\0') { + break; + } + } while (--n != 0); + } + return 0; +} + +/* Read formatted data from a string */ +int sscanf (const char *buffer, const char *format, ...) +{ + // + // Null sscanf() function implementation to satisfy the linker, since + // no direct functionality logic dependency in present UEFI cases. + // + return 0; +} + +/* Maps errnum to an error-message string */ +char * strerror (int errnum) +{ + return NULL; +} + +/* Computes the length of the maximum initial segment of the string pointed to by s1 + which consists entirely of characters from the string pointed to by s2. */ +size_t strspn (const char *s1 , const char *s2) +{ + UINT8 Map[32]; + UINT32 Index; + size_t Count; + + for (Index = 0; Index < 32; Index++) { + Map[Index] = 0; + } + + while (*s2) { + Map[*s2 >> 3] |= (1 << (*s2 & 7)); + s2++; + } + + if (*s1) { + Count = 0; + while (Map[*s1 >> 3] & (1 << (*s1 & 7))) { + Count++; + s1++; + } + + return Count; + } + + return 0; +} + +/* Computes the length of the maximum initial segment of the string pointed to by s1 + which consists entirely of characters not from the string pointed to by s2. */ +size_t strcspn (const char *s1, const char *s2) +{ + UINT8 Map[32]; + UINT32 Index; + size_t Count; + + for (Index = 0; Index < 32; Index++) { + Map[Index] = 0; + } + + while (*s2) { + Map[*s2 >> 3] |= (1 << (*s2 & 7)); + s2++; + } + + Map[0] |= 1; + + Count = 0; + while (!(Map[*s1 >> 3] & (1 << (*s1 & 7)))) { + Count ++; + s1++; + } + + return Count; +} + +// +// -- Character Classification Routines -- +// + +/* Determines if a particular character is a decimal-digit character */ +int isdigit (int c) +{ + // + // ::= [0-9] + // + return (('0' <= (c)) && ((c) <= '9')); +} + +/* Determine if an integer represents character that is a hex digit */ +int isxdigit (int c) +{ + // + // ::= [0-9] | [a-f] | [A-F] + // + return ((('0' <= (c)) && ((c) <= '9')) || + (('a' <= (c)) && ((c) <= 'f')) || + (('A' <= (c)) && ((c) <= 'F'))); +} + +/* Determines if a particular character represents a space character */ +int isspace (int c) +{ + // + // ::= [ ] + // + return ((c) == ' '); +} + +/* Determine if a particular character is an alphanumeric character */ +int isalnum (int c) +{ + // + // ::= [0-9] | [a-z] | [A-Z] + // + return ((('0' <= (c)) && ((c) <= '9')) || + (('a' <= (c)) && ((c) <= 'z')) || + (('A' <= (c)) && ((c) <= 'Z'))); +} + +/* Determines if a particular character is in upper case */ +int isupper (int c) +{ + // + // := [A-Z] + // + return (('A' <= (c)) && ((c) <= 'Z')); +} + +// +// -- Data Conversion Routines -- +// + +/* Convert strings to a long-integer value */ +long strtol (const char *nptr, char **endptr, int base) +{ + // + // Null strtol() function implementation to satisfy the linker, since there is + // no direct functionality logic dependency in present UEFI cases. + // + return 0; +} + +/* Convert strings to an unsigned long-integer value */ +unsigned long strtoul (const char *nptr, char **endptr, int base) +{ + // + // Null strtoul() function implementation to satisfy the linker, since there is + // no direct functionality logic dependency in present UEFI cases. + // + return 0; +} + +/* Convert character to lowercase */ +int tolower (int c) +{ + if (('A' <= (c)) && ((c) <= 'Z')) { + return (c - ('A' - 'a')); + } + return (c); +} + +// +// -- Searching and Sorting Routines -- +// + +/* Performs a quick sort */ +void qsort (void *base, size_t num, size_t width, int (*compare)(const void *, const void *)) +{ + VOID *Buffer; + + ASSERT (base != NULL); + ASSERT (compare != NULL); + + // + // Use CRT-style malloc to cover BS and RT memory allocation. + // + Buffer = malloc (width); + ASSERT (Buffer != NULL); + + // + // Re-use PerformQuickSort() function Implementation in EDKII BaseSortLib. + // + QuickSortWorker (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare, Buffer); + + free (Buffer); + return; +} + +// +// -- Process and Environment Control Routines -- +// + +/* Get a value from the current environment */ +char *getenv (const char *varname) +{ + // + // Null getenv() function implementation to satisfy the linker, since there is + // no direct functionality logic dependency in present UEFI cases. + // + return NULL; +} + +/* Get a value from the current environment */ +char *secure_getenv (const char *varname) +{ + // + // Null secure_getenv() function implementation to satisfy the linker, since + // there is no direct functionality logic dependency in present UEFI cases. + // + // From the secure_getenv() manual: 'just like getenv() except that it + // returns NULL in cases where "secure execution" is required'. + // + return NULL; +} + +// +// -- Stream I/O Routines -- +// + +/* Write data to a stream */ +size_t fwrite (const void *buffer, size_t size, size_t count, FILE *stream) +{ + return 0; +} + +// +// -- Dummy OpenSSL Support Routines -- +// + +int BIO_printf (void *bio, const char *format, ...) +{ + return 0; +} + +int BIO_snprintf(char *buf, size_t n, const char *format, ...) +{ + return 0; +} + +#ifdef __GNUC__ + +typedef +VOID +(EFIAPI *NoReturnFuncPtr)( + VOID + ) __attribute__((__noreturn__)); + +STATIC +VOID +EFIAPI +NopFunction ( + VOID + ) +{ +} + +void abort (void) +{ + NoReturnFuncPtr NoReturnFunc; + + NoReturnFunc = (NoReturnFuncPtr) NopFunction; + + NoReturnFunc (); +} + +#else + +void abort (void) +{ + // Do nothing +} + +#endif + +int fclose (FILE *f) +{ + return 0; +} + +FILE *fopen (const char *c, const char *m) +{ + return NULL; +} + +size_t fread (void *b, size_t c, size_t i, FILE *f) +{ + return 0; +} + +uid_t getuid (void) +{ + return 0; +} + +uid_t geteuid (void) +{ + return 0; +} + +gid_t getgid (void) +{ + return 0; +} + +gid_t getegid (void) +{ + return 0; +} + +int printf (char const *fmt, ...) +{ + return 0; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/RuntimeMemAllocation.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/RuntimeMemAllocation.c new file mode 100644 index 0000000..b0142c2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/RuntimeMemAllocation.c @@ -0,0 +1,461 @@ +/** @file + Light-weight Memory Management Routines for OpenSSL-based Crypto + Library at Runtime Phase. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +//---------------------------------------------------------------- +// Initial version. Needs further optimizations. +//---------------------------------------------------------------- + +// +// Definitions for Runtime Memory Operations +// +#define RT_PAGE_SIZE 0x200 +#define RT_PAGE_MASK 0x1FF +#define RT_PAGE_SHIFT 9 + +#define RT_SIZE_TO_PAGES(a) (((a) >> RT_PAGE_SHIFT) + (((a) & RT_PAGE_MASK) ? 1 : 0)) +#define RT_PAGES_TO_SIZE(a) ((a) << RT_PAGE_SHIFT) + +// +// Page Flag Definitions +// +#define RT_PAGE_FREE 0x00000000 +#define RT_PAGE_USED 0x00000001 + +#define MIN_REQUIRED_BLOCKS 600 + +// +// Memory Page Table +// +typedef struct { + UINTN StartPageOffset; // Offset of the starting page allocated. + // Only available for USED pages. + UINT32 PageFlag; // Page Attributes. +} RT_MEMORY_PAGE_ENTRY; + +typedef struct { + UINTN PageCount; + UINTN LastEmptyPageOffset; + UINT8 *DataAreaBase; // Pointer to data Area. + RT_MEMORY_PAGE_ENTRY Pages[1]; // Page Table Entries. +} RT_MEMORY_PAGE_TABLE; + +// +// Global Page Table for Runtime Cryptographic Provider. +// +RT_MEMORY_PAGE_TABLE *mRTPageTable = NULL; + +// +// Event for Runtime Address Conversion. +// +STATIC EFI_EVENT mVirtualAddressChangeEvent; + + +/** + Initializes pre-allocated memory pointed by ScratchBuffer for subsequent + runtime use. + + @param[in, out] ScratchBuffer Pointer to user-supplied memory buffer. + @param[in] ScratchBufferSize Size of supplied buffer in bytes. + + @retval EFI_SUCCESS Successful initialization. + +**/ +EFI_STATUS +InitializeScratchMemory ( + IN OUT UINT8 *ScratchBuffer, + IN UINTN ScratchBufferSize + ) +{ + UINTN Index; + UINTN MemorySize; + + // + // Parameters Checking + // + if (ScratchBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (ScratchBufferSize < MIN_REQUIRED_BLOCKS * 1024) { + return EFI_BUFFER_TOO_SMALL; + } + + mRTPageTable = (RT_MEMORY_PAGE_TABLE *)ScratchBuffer; + + // + // Initialize Internal Page Table for Memory Management + // + SetMem (mRTPageTable, ScratchBufferSize, 0xFF); + MemorySize = ScratchBufferSize - sizeof (RT_MEMORY_PAGE_TABLE) + sizeof (RT_MEMORY_PAGE_ENTRY); + + mRTPageTable->PageCount = MemorySize / (RT_PAGE_SIZE + sizeof (RT_MEMORY_PAGE_ENTRY)); + mRTPageTable->LastEmptyPageOffset = 0x0; + + for (Index = 0; Index < mRTPageTable->PageCount; Index++) { + mRTPageTable->Pages[Index].PageFlag = RT_PAGE_FREE; + mRTPageTable->Pages[Index].StartPageOffset = 0; + } + + mRTPageTable->DataAreaBase = ScratchBuffer + sizeof (RT_MEMORY_PAGE_TABLE) + + (mRTPageTable->PageCount - 1) * sizeof (RT_MEMORY_PAGE_ENTRY); + + return EFI_SUCCESS; +} + + +/** + Look-up Free memory Region for object allocation. + + @param[in] AllocationSize Bytes to be allocated. + + @return Return available page offset for object allocation. + +**/ +UINTN +LookupFreeMemRegion ( + IN UINTN AllocationSize + ) +{ + UINTN StartPageIndex; + UINTN Index; + UINTN SubIndex; + UINTN ReqPages; + + StartPageIndex = RT_SIZE_TO_PAGES (mRTPageTable->LastEmptyPageOffset); + ReqPages = RT_SIZE_TO_PAGES (AllocationSize); + if (ReqPages > mRTPageTable->PageCount) { + // + // No enough region for object allocation. + // + return (UINTN)(-1); + } + + // + // Look up the free memory region with in current memory map table. + // + for (Index = StartPageIndex; Index <= (mRTPageTable->PageCount - ReqPages); ) { + // + // Check consecutive ReqPages pages. + // + for (SubIndex = 0; SubIndex < ReqPages; SubIndex++) { + if ((mRTPageTable->Pages[SubIndex + Index].PageFlag & RT_PAGE_USED) != 0) { + break; + } + } + + if (SubIndex == ReqPages) { + // + // Succeed! Return the Starting Offset. + // + return RT_PAGES_TO_SIZE (Index); + } + + // + // Failed! Skip current free memory pages and adjacent Used pages + // + while ((mRTPageTable->Pages[SubIndex + Index].PageFlag & RT_PAGE_USED) != 0) { + SubIndex++; + } + + Index += SubIndex; + } + + // + // Look up the free memory region from the beginning of the memory table + // until the StartCursorOffset + // + if (ReqPages > StartPageIndex) { + // + // No enough region for object allocation. + // + return (UINTN)(-1); + } + for (Index = 0; Index < (StartPageIndex - ReqPages); ) { + // + // Check Consecutive ReqPages Pages. + // + for (SubIndex = 0; SubIndex < ReqPages; SubIndex++) { + if ((mRTPageTable->Pages[SubIndex + Index].PageFlag & RT_PAGE_USED) != 0) { + break; + } + } + + if (SubIndex == ReqPages) { + // + // Succeed! Return the Starting Offset. + // + return RT_PAGES_TO_SIZE (Index); + } + + // + // Failed! Skip current adjacent Used pages + // + while ((SubIndex < (StartPageIndex - ReqPages)) && + ((mRTPageTable->Pages[SubIndex + Index].PageFlag & RT_PAGE_USED) != 0)) { + SubIndex++; + } + + Index += SubIndex; + } + + // + // No available region for object allocation! + // + return (UINTN)(-1); +} + + +/** + Allocates a buffer at runtime phase. + + @param[in] AllocationSize Bytes to be allocated. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +RuntimeAllocateMem ( + IN UINTN AllocationSize + ) +{ + UINT8 *AllocPtr; + UINTN ReqPages; + UINTN Index; + UINTN StartPage; + UINTN AllocOffset; + + AllocPtr = NULL; + ReqPages = 0; + + // + // Look for available consecutive memory region starting from LastEmptyPageOffset. + // If no proper memory region found, look up from the beginning. + // If still not found, return NULL to indicate failed allocation. + // + AllocOffset = LookupFreeMemRegion (AllocationSize); + if (AllocOffset == (UINTN)(-1)) { + return NULL; + } + + // + // Allocates consecutive memory pages with length of Size. Update the page + // table status. Returns the starting address. + // + ReqPages = RT_SIZE_TO_PAGES (AllocationSize); + AllocPtr = mRTPageTable->DataAreaBase + AllocOffset; + StartPage = RT_SIZE_TO_PAGES (AllocOffset); + Index = 0; + while (Index < ReqPages) { + mRTPageTable->Pages[StartPage + Index].PageFlag |= RT_PAGE_USED; + mRTPageTable->Pages[StartPage + Index].StartPageOffset = AllocOffset; + + Index++; + } + + mRTPageTable->LastEmptyPageOffset = AllocOffset + RT_PAGES_TO_SIZE (ReqPages); + + ZeroMem (AllocPtr, AllocationSize); + + // + // Returns a void pointer to the allocated space + // + return AllocPtr; +} + + +/** + Frees a buffer that was previously allocated at runtime phase. + + @param[in] Buffer Pointer to the buffer to free. + +**/ +VOID +RuntimeFreeMem ( + IN VOID *Buffer + ) +{ + UINTN StartOffset; + UINTN StartPageIndex; + + StartOffset = (UINTN)Buffer - (UINTN)mRTPageTable->DataAreaBase; + StartPageIndex = RT_SIZE_TO_PAGES (mRTPageTable->Pages[RT_SIZE_TO_PAGES(StartOffset)].StartPageOffset); + + while (StartPageIndex < mRTPageTable->PageCount) { + if (((mRTPageTable->Pages[StartPageIndex].PageFlag & RT_PAGE_USED) != 0) && + (mRTPageTable->Pages[StartPageIndex].StartPageOffset == StartOffset)) { + // + // Free this page + // + mRTPageTable->Pages[StartPageIndex].PageFlag &= ~RT_PAGE_USED; + mRTPageTable->Pages[StartPageIndex].PageFlag |= RT_PAGE_FREE; + mRTPageTable->Pages[StartPageIndex].StartPageOffset = 0; + + StartPageIndex++; + } else { + break; + } + } + + return; +} + + +/** + Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. + + This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE + event. It converts a pointer to a new virtual address. + + @param[in] Event The event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context. + +**/ +VOID +EFIAPI +RuntimeCryptLibAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Converts a pointer for runtime memory management to a new virtual address. + // + EfiConvertPointer (0x0, (VOID **) &mRTPageTable->DataAreaBase); + EfiConvertPointer (0x0, (VOID **) &mRTPageTable); +} + + +/** + Constructor routine for runtime crypt library instance. + + The constructor function pre-allocates space for runtime cryptographic operation. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The construction succeeded. + @retval EFI_OUT_OF_RESOURCE Failed to allocate memory. + +**/ +EFI_STATUS +EFIAPI +RuntimeCryptLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *Buffer; + + // + // Pre-allocates runtime space for possible cryptographic operations + // + Buffer = AllocateRuntimePool (MIN_REQUIRED_BLOCKS * 1024); + Status = InitializeScratchMemory (Buffer, MIN_REQUIRED_BLOCKS * 1024); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Create address change event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + RuntimeCryptLibAddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + + +// +// -- Memory-Allocation Routines Wrapper for UEFI-OpenSSL Library -- +// + +/* Allocates memory blocks */ +void *malloc (size_t size) +{ + return RuntimeAllocateMem ((UINTN) size); +} + +/* Reallocate memory blocks */ +void *realloc (void *ptr, size_t size) +{ + VOID *NewPtr; + UINTN StartOffset; + UINTN StartPageIndex; + UINTN PageCount; + + if (ptr == NULL) { + return malloc (size); + } + + // + // Get Original Size of ptr + // + StartOffset = (UINTN)ptr - (UINTN)mRTPageTable->DataAreaBase; + StartPageIndex = RT_SIZE_TO_PAGES (mRTPageTable->Pages[RT_SIZE_TO_PAGES (StartOffset)].StartPageOffset); + PageCount = 0; + while (StartPageIndex < mRTPageTable->PageCount) { + if (((mRTPageTable->Pages[StartPageIndex].PageFlag & RT_PAGE_USED) != 0) && + (mRTPageTable->Pages[StartPageIndex].StartPageOffset == StartOffset)) { + StartPageIndex++; + PageCount++; + } else { + break; + } + } + + if (size <= RT_PAGES_TO_SIZE (PageCount)) { + // + // Return the original pointer, if Caller try to reduce region size; + // + return ptr; + } + + NewPtr = RuntimeAllocateMem ((UINTN) size); + if (NewPtr == NULL) { + return NULL; + } + + CopyMem (NewPtr, ptr, RT_PAGES_TO_SIZE (PageCount)); + + RuntimeFreeMem (ptr); + + return NewPtr; +} + +/* Deallocates or frees a memory block */ +void free (void *ptr) +{ + // + // In Standard C, free() handles a null pointer argument transparently. This + // is not true of RuntimeFreeMem() below, so protect it. + // + if (ptr != NULL) { + RuntimeFreeMem (ptr); + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c new file mode 100644 index 0000000..dd544a3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/BaseCryptLib/SysCall/TimerWrapper.c @@ -0,0 +1,174 @@ +/** @file + C Run-Time Libraries (CRT) Time Management Routines Wrapper Implementation + for OpenSSL-based Cryptographic Library (used in DXE & RUNTIME). + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +// +// -- Time Management Routines -- +// + +#define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) +#define SECSPERMIN (60) +#define SECSPERHOUR (60 * 60) +#define SECSPERDAY (24 * SECSPERHOUR) + +// +// The arrays give the cumulative number of days up to the first of the +// month number used as the index (1 -> 12) for regular and leap years. +// The value at index 13 is for the whole year. +// +UINTN CumulativeDays[2][14] = { + { + 0, + 0, + 31, + 31 + 28, + 31 + 28 + 31, + 31 + 28 + 31 + 30, + 31 + 28 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + }, + { + 0, + 0, + 31, + 31 + 29, + 31 + 29 + 31, + 31 + 29 + 31 + 30, + 31 + 29 + 31 + 30 + 31, + 31 + 29 + 31 + 30 + 31 + 30, + 31 + 29 + 31 + 30 + 31 + 30 + 31, + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, + 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + } +}; + +/* Get the system time as seconds elapsed since midnight, January 1, 1970. */ +//INTN time( +// INTN *timer +// ) +time_t time (time_t *timer) +{ + EFI_STATUS Status; + EFI_TIME Time; + time_t CalTime; + UINTN Year; + + // + // Get the current time and date information + // + Status = gRT->GetTime (&Time, NULL); + if (EFI_ERROR (Status) || (Time.Year < 1970)) { + return 0; + } + + // + // Years Handling + // UTime should now be set to 00:00:00 on Jan 1 of the current year. + // + for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) { + CalTime = CalTime + (time_t)(CumulativeDays[IsLeap(Year)][13] * SECSPERDAY); + } + + // + // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment + // + CalTime = CalTime + + (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) + + (time_t)(CumulativeDays[IsLeap(Time.Year)][Time.Month] * SECSPERDAY) + + (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) + + (time_t)(Time.Hour * SECSPERHOUR) + + (time_t)(Time.Minute * 60) + + (time_t)Time.Second; + + if (timer != NULL) { + *timer = CalTime; + } + + return CalTime; +} + +// +// Convert a time value from type time_t to struct tm. +// +struct tm * gmtime (const time_t *timer) +{ + struct tm *GmTime; + UINT16 DayNo; + UINT16 DayRemainder; + time_t Year; + time_t YearNo; + UINT16 TotalDays; + UINT16 MonthNo; + + if (timer == NULL) { + return NULL; + } + + GmTime = malloc (sizeof (struct tm)); + if (GmTime == NULL) { + return NULL; + } + + ZeroMem ((VOID *) GmTime, (UINTN) sizeof (struct tm)); + + DayNo = (UINT16) (*timer / SECSPERDAY); + DayRemainder = (UINT16) (*timer % SECSPERDAY); + + GmTime->tm_sec = (int) (DayRemainder % SECSPERMIN); + GmTime->tm_min = (int) ((DayRemainder % SECSPERHOUR) / SECSPERMIN); + GmTime->tm_hour = (int) (DayRemainder / SECSPERHOUR); + GmTime->tm_wday = (int) ((DayNo + 4) % 7); + + for (Year = 1970, YearNo = 0; DayNo > 0; Year++) { + TotalDays = (UINT16) (IsLeap (Year) ? 366 : 365); + if (DayNo >= TotalDays) { + DayNo = (UINT16) (DayNo - TotalDays); + YearNo++; + } else { + break; + } + } + + GmTime->tm_year = (int) (YearNo + (1970 - 1900)); + GmTime->tm_yday = (int) DayNo; + + for (MonthNo = 12; MonthNo > 1; MonthNo--) { + if (DayNo >= CumulativeDays[IsLeap(Year)][MonthNo]) { + DayNo = (UINT16) (DayNo - (UINT16) (CumulativeDays[IsLeap(Year)][MonthNo])); + break; + } + } + + GmTime->tm_mon = (int) MonthNo - 1; + GmTime->tm_mday = (int) DayNo + 1; + + GmTime->tm_isdst = 0; + GmTime->tm_gmtoff = 0; + GmTime->tm_zone = NULL; + + return GmTime; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/CrtLibSupport.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/CrtLibSupport.h new file mode 100644 index 0000000..ab1168b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/CrtLibSupport.h @@ -0,0 +1,195 @@ +/** @file + Root include file of C runtime library to support building the third-party + cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __CRT_LIB_SUPPORT_H__ +#define __CRT_LIB_SUPPORT_H__ + +#include +#include +#include +#include + +#define OPENSSLDIR "" +#define ENGINESDIR "" + +#define MAX_STRING_SIZE 0x1000 + +// +// OpenSSL relies on explicit configuration for word size in crypto/bn, +// but we want it to be automatically inferred from the target. So we +// bypass what's in for OPENSSL_SYS_UEFI, and +// define our own here. +// +#ifdef CONFIG_HEADER_BN_H +#error CONFIG_HEADER_BN_H already defined +#endif + +#define CONFIG_HEADER_BN_H + +#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || defined(MDE_CPU_IA64) +// +// With GCC we would normally use SIXTY_FOUR_BIT_LONG, but MSVC needs +// SIXTY_FOUR_BIT, because 'long' is 32-bit and only 'long long' is +// 64-bit. Since using 'long long' works fine on GCC too, just do that. +// +#define SIXTY_FOUR_BIT +#elif defined(MDE_CPU_IA32) || defined(MDE_CPU_ARM) || defined(MDE_CPU_EBC) +#define THIRTY_TWO_BIT +#else +#error Unknown target architecture +#endif + +// +// Map all va_xxxx elements to VA_xxx defined in MdePkg/Include/Base.h +// +#if !defined(__CC_ARM) // if va_list is not already defined +#define va_list VA_LIST +#define va_arg VA_ARG +#define va_start VA_START +#define va_end VA_END +#else // __CC_ARM +#define va_start(Marker, Parameter) __va_start(Marker, Parameter) +#define va_arg(Marker, TYPE) __va_arg(Marker, TYPE) +#define va_end(Marker) ((void)0) +#endif + +// +// Definitions for global constants used by CRT library routines +// +#define EINVAL 22 /* Invalid argument */ +#define INT_MAX 0x7FFFFFFF /* Maximum (signed) int value */ +#define LONG_MAX 0X7FFFFFFFL /* max value for a long */ +#define LONG_MIN (-LONG_MAX-1) /* min value for a long */ +#define ULONG_MAX 0xFFFFFFFF /* Maximum unsigned long value */ +#define CHAR_BIT 8 /* Number of bits in a char */ + +// +// Basic types mapping +// +typedef UINTN size_t; +typedef INTN ssize_t; +typedef INT32 time_t; +typedef UINT8 __uint8_t; +typedef UINT8 sa_family_t; +typedef UINT32 uid_t; +typedef UINT32 gid_t; + +// +// File operations are not required for EFI building, +// so FILE is mapped to VOID * to pass build +// +typedef VOID *FILE; + +// +// Structures Definitions +// +struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Savings Time flag */ + long tm_gmtoff; /* offset from CUT in seconds */ + char *tm_zone; /* timezone abbreviation */ +}; + +struct timeval { + long tv_sec; /* time value, in seconds */ + long tv_usec; /* time value, in microseconds */ +}; + +struct sockaddr { + __uint8_t sa_len; /* total length */ + sa_family_t sa_family; /* address family */ + char sa_data[14]; /* actually longer; address value */ +}; + +// +// Global variables +// +extern int errno; +extern FILE *stderr; + +// +// Function prototypes of CRT Library routines +// +void *malloc (size_t); +void *realloc (void *, size_t); +void free (void *); +void *memset (void *, int, size_t); +int memcmp (const void *, const void *, size_t); +int isdigit (int); +int isspace (int); +int isxdigit (int); +int isalnum (int); +int isupper (int); +int tolower (int); +int strcmp (const char *, const char *); +int strncasecmp (const char *, const char *, size_t); +char *strrchr (const char *, int); +unsigned long strtoul (const char *, char **, int); +long strtol (const char *, char **, int); +char *strerror (int); +size_t strspn (const char *, const char *); +size_t strcspn (const char *, const char *); +int printf (const char *, ...); +int sscanf (const char *, const char *, ...); +FILE *fopen (const char *, const char *); +size_t fread (void *, size_t, size_t, FILE *); +size_t fwrite (const void *, size_t, size_t, FILE *); +int fclose (FILE *); +int fprintf (FILE *, const char *, ...); +time_t time (time_t *); +struct tm *gmtime (const time_t *); +uid_t getuid (void); +uid_t geteuid (void); +gid_t getgid (void); +gid_t getegid (void); +void qsort (void *, size_t, size_t, int (*)(const void *, const void *)); +char *getenv (const char *); +char *secure_getenv (const char *); +#if defined(__GNUC__) && (__GNUC__ >= 2) +void abort (void) __attribute__((__noreturn__)); +#else +void abort (void); +#endif + +// +// Macros that directly map functions to BaseLib, BaseMemoryLib, and DebugLib functions +// +#define memcpy(dest,source,count) CopyMem(dest,source,(UINTN)(count)) +#define memset(dest,ch,count) SetMem(dest,(UINTN)(count),(UINT8)(ch)) +#define memchr(buf,ch,count) ScanMem8(buf,(UINTN)(count),(UINT8)ch) +#define memcmp(buf1,buf2,count) (int)(CompareMem(buf1,buf2,(UINTN)(count))) +#define memmove(dest,source,count) CopyMem(dest,source,(UINTN)(count)) +#define strlen(str) (size_t)(AsciiStrnLenS(str,MAX_STRING_SIZE)) +#define strcpy(strDest,strSource) AsciiStrCpyS(strDest,MAX_STRING_SIZE,strSource) +#define strncpy(strDest,strSource,count) AsciiStrnCpyS(strDest,MAX_STRING_SIZE,strSource,(UINTN)count) +#define strcat(strDest,strSource) AsciiStrCatS(strDest,MAX_STRING_SIZE,strSource) +#define strchr(str,ch) ScanMem8((VOID *)(str),AsciiStrSize(str),(UINT8)ch) +#define strncmp(string1,string2,count) (int)(AsciiStrnCmp(string1,string2,(UINTN)(count))) +#define strcasecmp(str1,str2) (int)AsciiStriCmp(str1,str2) +#define sprintf(buf,...) AsciiSPrint(buf,MAX_STRING_SIZE,__VA_ARGS__) +#define localtime(timer) NULL +#define assert(expression) +#define offsetof(type,member) OFFSET_OF(type,member) +#define atoi(nptr) AsciiStrDecimalToUintn(nptr) +#define gettimeofday(tvp,tz) do { (tvp)->tv_sec = time(NULL); (tvp)->tv_usec = 0; } while (0) + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/assert.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/assert.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/assert.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/ctype.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/ctype.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/ctype.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/errno.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/errno.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/errno.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/internal/dso_conf.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/internal/dso_conf.h new file mode 100644 index 0000000..e69de29 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/limits.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/limits.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/limits.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/memory.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/memory.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/memory.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/openssl/opensslconf.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/openssl/opensslconf.h new file mode 100644 index 0000000..28dd9ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/openssl/opensslconf.h @@ -0,0 +1,314 @@ +/* + * WARNING: do not edit! + * Generated from include/openssl/opensslconf.h.in + * + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_ALGORITHM_DEFINES +# error OPENSSL_ALGORITHM_DEFINES no longer supported +#endif + +/* + * OpenSSL was configured with the following options: + */ + +#ifndef OPENSSL_SYS_UEFI +# define OPENSSL_SYS_UEFI 1 +#endif +#define OPENSSL_MIN_API 0x10100000L +#ifndef OPENSSL_NO_BF +# define OPENSSL_NO_BF +#endif +#ifndef OPENSSL_NO_BLAKE2 +# define OPENSSL_NO_BLAKE2 +#endif +#ifndef OPENSSL_NO_CAMELLIA +# define OPENSSL_NO_CAMELLIA +#endif +#ifndef OPENSSL_NO_CAST +# define OPENSSL_NO_CAST +#endif +#ifndef OPENSSL_NO_CHACHA +# define OPENSSL_NO_CHACHA +#endif +#ifndef OPENSSL_NO_CMS +# define OPENSSL_NO_CMS +#endif +#ifndef OPENSSL_NO_CT +# define OPENSSL_NO_CT +#endif +#ifndef OPENSSL_NO_DSA +# define OPENSSL_NO_DSA +#endif +#ifndef OPENSSL_NO_EC +# define OPENSSL_NO_EC +#endif +#ifndef OPENSSL_NO_IDEA +# define OPENSSL_NO_IDEA +#endif +#ifndef OPENSSL_NO_MD2 +# define OPENSSL_NO_MD2 +#endif +#ifndef OPENSSL_NO_MDC2 +# define OPENSSL_NO_MDC2 +#endif +#ifndef OPENSSL_NO_POLY1305 +# define OPENSSL_NO_POLY1305 +#endif +#ifndef OPENSSL_NO_RC2 +# define OPENSSL_NO_RC2 +#endif +#ifndef OPENSSL_NO_RC5 +# define OPENSSL_NO_RC5 +#endif +#ifndef OPENSSL_NO_RMD160 +# define OPENSSL_NO_RMD160 +#endif +#ifndef OPENSSL_NO_SEED +# define OPENSSL_NO_SEED +#endif +#ifndef OPENSSL_NO_SRP +# define OPENSSL_NO_SRP +#endif +#ifndef OPENSSL_NO_TS +# define OPENSSL_NO_TS +#endif +#ifndef OPENSSL_NO_UI +# define OPENSSL_NO_UI +#endif +#ifndef OPENSSL_NO_WHIRLPOOL +# define OPENSSL_NO_WHIRLPOOL +#endif +#ifndef OPENSSL_NO_AFALGENG +# define OPENSSL_NO_AFALGENG +#endif +#ifndef OPENSSL_NO_APPS +# define OPENSSL_NO_APPS +#endif +#ifndef OPENSSL_NO_ASAN +# define OPENSSL_NO_ASAN +#endif +#ifndef OPENSSL_NO_ASM +# define OPENSSL_NO_ASM +#endif +#ifndef OPENSSL_NO_ASYNC +# define OPENSSL_NO_ASYNC +#endif +#ifndef OPENSSL_NO_AUTOALGINIT +# define OPENSSL_NO_AUTOALGINIT +#endif +#ifndef OPENSSL_NO_AUTOERRINIT +# define OPENSSL_NO_AUTOERRINIT +#endif +#ifndef OPENSSL_NO_CAPIENG +# define OPENSSL_NO_CAPIENG +#endif +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +# define OPENSSL_NO_CRYPTO_MDEBUG +#endif +#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE +# define OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE +#endif +#ifndef OPENSSL_NO_DEPRECATED +# define OPENSSL_NO_DEPRECATED +#endif +#ifndef OPENSSL_NO_DGRAM +# define OPENSSL_NO_DGRAM +#endif +#ifndef OPENSSL_NO_DTLS +# define OPENSSL_NO_DTLS +#endif +#ifndef OPENSSL_NO_DTLS1 +# define OPENSSL_NO_DTLS1 +#endif +#ifndef OPENSSL_NO_DTLS1_2 +# define OPENSSL_NO_DTLS1_2 +#endif +#ifndef OPENSSL_NO_EC2M +# define OPENSSL_NO_EC2M +#endif +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# define OPENSSL_NO_EC_NISTP_64_GCC_128 +#endif +#ifndef OPENSSL_NO_ECDH +# define OPENSSL_NO_ECDH +#endif +#ifndef OPENSSL_NO_ECDSA +# define OPENSSL_NO_ECDSA +#endif +#ifndef OPENSSL_NO_EGD +# define OPENSSL_NO_EGD +#endif +#ifndef OPENSSL_NO_ENGINE +# define OPENSSL_NO_ENGINE +#endif +#ifndef OPENSSL_NO_ERR +# define OPENSSL_NO_ERR +#endif +#ifndef OPENSSL_NO_FILENAMES +# define OPENSSL_NO_FILENAMES +#endif +#ifndef OPENSSL_NO_FUZZ_AFL +# define OPENSSL_NO_FUZZ_AFL +#endif +#ifndef OPENSSL_NO_FUZZ_LIBFUZZER +# define OPENSSL_NO_FUZZ_LIBFUZZER +#endif +#ifndef OPENSSL_NO_GOST +# define OPENSSL_NO_GOST +#endif +#ifndef OPENSSL_NO_HEARTBEATS +# define OPENSSL_NO_HEARTBEATS +#endif +#ifndef OPENSSL_NO_HW +# define OPENSSL_NO_HW +#endif +#ifndef OPENSSL_NO_MSAN +# define OPENSSL_NO_MSAN +#endif +#ifndef OPENSSL_NO_OCB +# define OPENSSL_NO_OCB +#endif +#ifndef OPENSSL_NO_POSIX_IO +# define OPENSSL_NO_POSIX_IO +#endif +#ifndef OPENSSL_NO_RFC3779 +# define OPENSSL_NO_RFC3779 +#endif +#ifndef OPENSSL_NO_SCRYPT +# define OPENSSL_NO_SCRYPT +#endif +#ifndef OPENSSL_NO_SCTP +# define OPENSSL_NO_SCTP +#endif +#ifndef OPENSSL_NO_SOCK +# define OPENSSL_NO_SOCK +#endif +#ifndef OPENSSL_NO_SSL_TRACE +# define OPENSSL_NO_SSL_TRACE +#endif +#ifndef OPENSSL_NO_SSL3 +# define OPENSSL_NO_SSL3 +#endif +#ifndef OPENSSL_NO_SSL3_METHOD +# define OPENSSL_NO_SSL3_METHOD +#endif +#ifndef OPENSSL_NO_STDIO +# define OPENSSL_NO_STDIO +#endif +#ifndef OPENSSL_NO_TESTS +# define OPENSSL_NO_TESTS +#endif +#ifndef OPENSSL_NO_UBSAN +# define OPENSSL_NO_UBSAN +#endif +#ifndef OPENSSL_NO_UNIT_TEST +# define OPENSSL_NO_UNIT_TEST +#endif +#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS +# define OPENSSL_NO_WEAK_SSL_CIPHERS +#endif +#ifndef OPENSSL_NO_AFALGENG +# define OPENSSL_NO_AFALGENG +#endif + + +/* + * Sometimes OPENSSSL_NO_xxx ends up with an empty file and some compilers + * don't like that. This will hopefully silence them. + */ +#define NON_EMPTY_TRANSLATION_UNIT static void *dummy = &dummy; + +/* + * Applications should use -DOPENSSL_API_COMPAT= to suppress the + * declarations of functions deprecated in or before . Otherwise, they + * still won't see them if the library has been built to disable deprecated + * functions. + */ +#ifndef DECLARE_DEPRECATED +# if defined(OPENSSL_NO_DEPRECATED) +# define DECLARE_DEPRECATED(f) +# else +# define DECLARE_DEPRECATED(f) f; +# ifdef __GNUC__ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) +# undef DECLARE_DEPRECATED +# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated)); +# endif +# endif +# endif +#endif + +#ifndef OPENSSL_FILE +# ifdef OPENSSL_NO_FILENAMES +# define OPENSSL_FILE "" +# define OPENSSL_LINE 0 +# else +# define OPENSSL_FILE __FILE__ +# define OPENSSL_LINE __LINE__ +# endif +#endif + +#ifndef OPENSSL_MIN_API +# define OPENSSL_MIN_API 0 +#endif + +#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < OPENSSL_MIN_API +# undef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT OPENSSL_MIN_API +#endif + +#if OPENSSL_API_COMPAT < 0x10100000L +# define DEPRECATEDIN_1_1_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_1_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x10000000L +# define DEPRECATEDIN_1_0_0(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_1_0_0(f) +#endif + +#if OPENSSL_API_COMPAT < 0x00908000L +# define DEPRECATEDIN_0_9_8(f) DECLARE_DEPRECATED(f) +#else +# define DEPRECATEDIN_0_9_8(f) +#endif + + + +/* Generate 80386 code? */ +#undef I386_ONLY + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* + * The following are cipher-specific, but are part of the public API. + */ +#if !defined(OPENSSL_SYS_UEFI) +# undef BN_LLONG +/* Only one for the following should be defined */ +# undef SIXTY_FOUR_BIT_LONG +# undef SIXTY_FOUR_BIT +# define THIRTY_TWO_BIT +#endif + +#define RC4_INT unsigned int + +#ifdef __cplusplus +} +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdarg.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdarg.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdarg.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stddef.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stddef.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stddef.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdio.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdio.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdio.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdlib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdlib.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/stdlib.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/string.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/string.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/string.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/strings.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/strings.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/strings.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/time.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/time.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/time.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/types.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/types.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/sys/types.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/syslog.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/syslog.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/syslog.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/time.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/time.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/time.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/unistd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/unistd.h new file mode 100644 index 0000000..6f8b4f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/Include/unistd.h @@ -0,0 +1,15 @@ +/** @file + Include file to support building the third-party cryptographic library. + +Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/BaseIntrinsicLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/BaseIntrinsicLib.uni new file mode 100644 index 0000000..fbecd7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/BaseIntrinsicLib.uni @@ -0,0 +1,22 @@ +// /** @file +// Intrinsic Routines Wrapper Library Instance. +// +// This module is intrinsic routines wrapper library instance. +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Intrinsic Routines Wrapper Library Instance" + +#string STR_MODULE_DESCRIPTION #language en-US "This module is intrinsic routines wrapper library instance." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/CopyMem.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/CopyMem.c new file mode 100644 index 0000000..40aad7f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/CopyMem.c @@ -0,0 +1,23 @@ +/** @file + Intrinsic Memory Routines Wrapper Implementation for OpenSSL-based + Cryptographic Library. + +Copyright (c) 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/* Copies bytes between buffers */ +void * memcpy (void *dest, const void *src, unsigned int count) +{ + return CopyMem (dest, src, (UINTN)count); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.S new file mode 100644 index 0000000..a7342a4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.S @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# MathLShiftS64.S +# +# Abstract: +# +# 64-bit Math Worker Function. +# Shifts a 64-bit signed value left by a certain number of bits. +# +#------------------------------------------------------------------------------ + + .686: + .code: + +ASM_GLOBAL ASM_PFX(__ashldi3) + +#------------------------------------------------------------------------------ +# +# void __cdecl __ashldi3 (void) +# +#------------------------------------------------------------------------------ +ASM_PFX(__ashldi3): + # + # Handle shifting of 64 or more bits (return 0) + # + cmpb $64, %cl + jae ReturnZero + + # + # Handle shifting of between 0 and 31 bits + # + cmpb $32, %cl + jae More32 + shld %cl, %eax, %edx + shl %cl, %eax + ret + + # + # Handle shifting of between 32 and 63 bits + # +More32: + movl %eax, %edx + xor %eax, %eax + and $31, %cl + shl %cl, %edx + ret + +ReturnZero: + xor %eax, %eax + xor %edx, %edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.c new file mode 100644 index 0000000..f5baf0e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.c @@ -0,0 +1,54 @@ +/** @file + 64-bit Math Worker Function. + The 32-bit versions of C compiler generate calls to library routines + to handle 64-bit math. These functions use non-standard calling conventions. + +Copyright (c) 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +/* + * Shifts a 64-bit signed value left by a particular number of bits. + */ +__declspec(naked) void __cdecl _allshl (void) +{ + _asm { + ; + ; Handle shifting of 64 or more bits (return 0) + ; + cmp cl, 64 + jae short ReturnZero + + ; + ; Handle shifting of between 0 and 31 bits + ; + cmp cl, 32 + jae short More32 + shld edx, eax, cl + shl eax, cl + ret + + ; + ; Handle shifting of between 32 and 63 bits + ; +More32: + mov edx, eax + xor eax, eax + and cl, 31 + shl edx, cl + ret + +ReturnZero: + xor eax,eax + xor edx,edx + ret + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.nasm new file mode 100644 index 0000000..8855a3d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathLShiftS64.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; MathLShiftS64.nasm +; +; Abstract: +; +; 64-bit Math Worker Function. +; Shifts a 64-bit signed value left by a certain number of bits. +; +;------------------------------------------------------------------------------ + + SECTION .text + +global ASM_PFX(__ashldi3) +;------------------------------------------------------------------------------ +; +; void __cdecl __ashldi3 (void) +; +;------------------------------------------------------------------------------ +ASM_PFX(__ashldi3): + cmp cl,0x40 + jnc ReturnZero + cmp cl,0x20 + jnc More32 + shld edx,eax,cl + shl eax,cl + ret +More32: + mov edx,eax + xor eax,eax + and cl,0x1f + shl edx,cl + ret +ReturnZero: + xor eax,eax + xor edx,edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.S new file mode 100644 index 0000000..2e2d92e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.S @@ -0,0 +1,66 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# MathRShiftU64.S +# +# Abstract: +# +# 64-bit Math Worker Function. +# Shifts a 64-bit unsigned value right by a certain number of bits. +# +#------------------------------------------------------------------------------ + + + .686: + .code: + +ASM_GLOBAL ASM_PFX(__ashrdi3) + +#------------------------------------------------------------------------------ +# +# void __cdecl __ashrdi3 (void) +# +#------------------------------------------------------------------------------ +ASM_PFX(__ashrdi3): + # + # Checking: Only handle 64bit shifting or more + # + cmpb $64, %cl + jae _Exit + + # + # Handle shifting between 0 and 31 bits + # + cmpb $32, %cl + jae More32 + shrd %cl, %edx, %eax + shr %cl, %edx + ret + + # + # Handle shifting of 32-63 bits + # +More32: + movl %edx, %eax + xor %edx, %edx + and $31, %cl + shr %cl, %eax + ret + + # + # Invalid number (less then 32bits), return 0 + # +_Exit: + xor %eax, %eax + xor %edx, %edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.c new file mode 100644 index 0000000..2fe4deb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.c @@ -0,0 +1,57 @@ +/** @file + 64-bit Math Worker Function. + The 32-bit versions of C compiler generate calls to library routines + to handle 64-bit math. These functions use non-standard calling conventions. + +Copyright (c) 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +/* + * Shifts a 64-bit unsigned value right by a certain number of bits. + */ +__declspec(naked) void __cdecl _aullshr (void) +{ + _asm { + ; + ; Checking: Only handle 64bit shifting or more + ; + cmp cl, 64 + jae _Exit + + ; + ; Handle shifting between 0 and 31 bits + ; + cmp cl, 32 + jae More32 + shrd eax, edx, cl + shr edx, cl + ret + + ; + ; Handle shifting of 32-63 bits + ; +More32: + mov eax, edx + xor edx, edx + and cl, 31 + shr eax, cl + ret + + ; + ; Invalid number (less then 32bits), return 0 + ; +_Exit: + xor eax, eax + xor edx, edx + ret + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.nasm new file mode 100644 index 0000000..65a3684 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/Ia32/MathRShiftU64.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; MathRShiftU64.nasm +; +; Abstract: +; +; 64-bit Math Worker Function. +; Shifts a 64-bit unsigned value right by a certain number of bits. +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; +; void __cdecl __ashrdi3 (void) +; +;------------------------------------------------------------------------------ +global ASM_PFX(__ashrdi3) +ASM_PFX(__ashrdi3): + cmp cl,0x40 + jnc _Exit + cmp cl,0x20 + jnc More32 + shrd eax,edx,cl + shr edx,cl + ret +More32: + mov eax,edx + xor edx,edx + and cl,0x1f + shr eax,cl + ret +_Exit: + xor eax,eax + xor edx,edx + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf new file mode 100644 index 0000000..f43254b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf @@ -0,0 +1,73 @@ +## @file +# Intrinsic Routines Wrapper Library Instance. +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseIntrinsicLib + MODULE_UNI_FILE = BaseIntrinsicLib.uni + FILE_GUID = 63850097-3E97-4c4f-A52D-C811A0106105 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = IntrinsicLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MemoryIntrinsics.c + +[Sources.IA32] + CopyMem.c + + Ia32/MathLShiftS64.c | MSFT + Ia32/MathRShiftU64.c | MSFT + + Ia32/MathLShiftS64.c | INTEL + Ia32/MathRShiftU64.c | INTEL + + Ia32/MathLShiftS64.S | GCC + Ia32/MathRShiftU64.S | GCC + Ia32/MathLShiftS64.nasm | GCC + Ia32/MathRShiftU64.nasm | GCC + +[Sources.X64] + CopyMem.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + +[BuildOptions] + # + # Override MSFT build option to remove /Oi and /GL + # + MSFT:DEBUG_VS2003_IA32_CC_FLAGS == /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /GX- /Zi /Gm + MSFT:RELEASE_VS2003_IA32_CC_FLAGS == /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /GX- + MSFT:DEBUG_VS2003xASL_IA32_CC_FLAGS == /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /GX- /Zi /Gm + MSFT:RELEASE_VS2003xASL_IA32_CC_FLAGS == /nologo /c /WX /W4 /Gs32768 /Gy /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /GX- + MSFT:DEBUG_DDK3790_IA32_CC_FLAGS == /nologo /c /WX /Gy /Gs32768 /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm + MSFT:RELEASE_DDK3790_IA32_CC_FLAGS == /nologo /c /WX /Gy /Gs32768 /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF + MSFT:DEBUG_DDK3790xASL_IA32_CC_FLAGS == /nologo /c /WX /Gy /Gs32768 /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm + MSFT:RELEASE_DDK3790xASL_IA32_CC_FLAGS == /nologo /c /WX /Gy /Gs32768 /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF + MSFT:DEBUG_*_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm + MSFT:RELEASE_*_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /FIAutoGen.h /EHs-c- /GR- /GF + MSFT:DEBUG_*_X64_CC_FLAGS == /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1b2s /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm + MSFT:RELEASE_*_X64_CC_FLAGS == /nologo /c /WX /GS- /X /W4 /Gs32768 /D UNICODE /O1b2s /Gy /FIAutoGen.h /EHs-c- /GR- /GF + INTEL:*_*_*_CC_FLAGS = /Oi- diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/MemoryIntrinsics.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/MemoryIntrinsics.c new file mode 100644 index 0000000..9a66b37 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/IntrinsicLib/MemoryIntrinsics.c @@ -0,0 +1,60 @@ +/** @file + Intrinsic Memory Routines Wrapper Implementation for OpenSSL-based + Cryptographic Library. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +typedef UINTN size_t; + +/* OpenSSL will use floating point support, and C compiler produces the _fltused + symbol by default. Simply define this symbol here to satisfy the linker. */ +int _fltused = 1; + +/* Sets buffers to a specified character */ +void * memset (void *dest, int ch, size_t count) +{ + // + // NOTE: Here we use one base implementation for memset, instead of the direct + // optimized SetMem() wrapper. Because the IntrinsicLib has to be built + // without whole program optimization option, and there will be some + // potential register usage errors when calling other optimized codes. + // + + // + // 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 *Pointer; + + Pointer = (UINT8 *)dest; + while (count-- != 0) { + *(Pointer++) = (UINT8)ch; + } + + return dest; +} + +/* Compare bytes in two buffers. */ +int memcmp (const void *buf1, const void *buf2, size_t count) +{ + return (int)CompareMem(buf1, buf2, count); +} + +int strcmp (const char *s1, const char *s2) +{ + return (int)AsciiStrCmp(s1, s2); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpenSSL-HOWTO.txt b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpenSSL-HOWTO.txt new file mode 100644 index 0000000..a062b95 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpenSSL-HOWTO.txt @@ -0,0 +1,53 @@ + +============================================================================= + Introduction +============================================================================= + OpenSSL is a well-known open source implementation of SSL/TLS protocols. +The core library implements the cryptographic and SSL/TLS functions and +also provides various utility functions. The OpenSSL library is widely used +in variety of security products development as base crypto provider. +(See http://www.openssl.org/ for more information about OpenSSL). + UEFI (Unified Extensible Firmware Interface) is a specification detailing +the interfaces between OS and platform firmware. Several security features +were introduced (e.g. Authenticated Variable Service, Driver Signing, etc) +from UEFI 2.2 (http://www.uefi.org/). These security features highly depend +on the cryptography. + This HOWTO documents OpenSSL building under UEFI/EDKII environment. + +============================================================================= + OpenSSL-Version +============================================================================= + EDKII supports building with the latest release of OpenSSL. + NOTE: Only latest release version was fully validated. + And no guarantees on build & functionality if using other versions. + +============================================================================= + HOW to Install OpenSSL for UEFI Building +============================================================================= + OpenSSL repository was added as one submodule of EDKII project. + + The user can use the following commands to clone both main EDKII repo and +openssl submodule: + 1) Add the "--recursive" flag to the git clone command: + $ git clone --recursive https://github.com/tianocore/edk2 +or + 2) Manually initialize and update the submodules after the clone operation + on main project: + $ git clone https://github.com/tianocore/edk2 + $ git submodule update --init --recursive + + And use the following combined commands to pull the remote submodule updates +(e.g. Updating the new supported OpenSSL release tag): + $ git pull --recurse-submodules && \ + git submodule update --recursive + +============================================================================= + About process_files.pl +============================================================================= + "process_files.pl" is one Perl script which runs the OpenSSL Configure, +then processes the resulting file list into our local OpensslLib.inf and +OpensslLibCrypto.inf. + This only needs to be done once by the maintainer / developer when +updating to a new version of OpenSSL (or changing options, etc.). +Normal users do not need do this, since the results are already stored in +the EDKII git repository for them. diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.inf new file mode 100644 index 0000000..8a9265a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.inf @@ -0,0 +1,597 @@ +## @file +# This module provides OpenSSL Library implementation. +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OpensslLib + MODULE_UNI_FILE = OpensslLib.uni + FILE_GUID = C873A7D0-9824-409f-9B42-2C158B992E69 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = OpensslLib + DEFINE OPENSSL_PATH = openssl + DEFINE OPENSSL_FLAGS = -DL_ENDIAN -DOPENSSL_SMALL_FOOTPRINT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DNO_SYSLOG + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + $(OPENSSL_PATH)/e_os.h +# Autogenerated files list starts here + $(OPENSSL_PATH)/crypto/aes/aes_cbc.c + $(OPENSSL_PATH)/crypto/aes/aes_cfb.c + $(OPENSSL_PATH)/crypto/aes/aes_core.c + $(OPENSSL_PATH)/crypto/aes/aes_ecb.c + $(OPENSSL_PATH)/crypto/aes/aes_ige.c + $(OPENSSL_PATH)/crypto/aes/aes_misc.c + $(OPENSSL_PATH)/crypto/aes/aes_ofb.c + $(OPENSSL_PATH)/crypto/aes/aes_wrap.c + $(OPENSSL_PATH)/crypto/asn1/a_bitstr.c + $(OPENSSL_PATH)/crypto/asn1/a_d2i_fp.c + $(OPENSSL_PATH)/crypto/asn1/a_digest.c + $(OPENSSL_PATH)/crypto/asn1/a_dup.c + $(OPENSSL_PATH)/crypto/asn1/a_gentm.c + $(OPENSSL_PATH)/crypto/asn1/a_i2d_fp.c + $(OPENSSL_PATH)/crypto/asn1/a_int.c + $(OPENSSL_PATH)/crypto/asn1/a_mbstr.c + $(OPENSSL_PATH)/crypto/asn1/a_object.c + $(OPENSSL_PATH)/crypto/asn1/a_octet.c + $(OPENSSL_PATH)/crypto/asn1/a_print.c + $(OPENSSL_PATH)/crypto/asn1/a_sign.c + $(OPENSSL_PATH)/crypto/asn1/a_strex.c + $(OPENSSL_PATH)/crypto/asn1/a_strnid.c + $(OPENSSL_PATH)/crypto/asn1/a_time.c + $(OPENSSL_PATH)/crypto/asn1/a_type.c + $(OPENSSL_PATH)/crypto/asn1/a_utctm.c + $(OPENSSL_PATH)/crypto/asn1/a_utf8.c + $(OPENSSL_PATH)/crypto/asn1/a_verify.c + $(OPENSSL_PATH)/crypto/asn1/ameth_lib.c + $(OPENSSL_PATH)/crypto/asn1/asn1_err.c + $(OPENSSL_PATH)/crypto/asn1/asn1_gen.c + $(OPENSSL_PATH)/crypto/asn1/asn1_lib.c + $(OPENSSL_PATH)/crypto/asn1/asn1_par.c + $(OPENSSL_PATH)/crypto/asn1/asn_mime.c + $(OPENSSL_PATH)/crypto/asn1/asn_moid.c + $(OPENSSL_PATH)/crypto/asn1/asn_mstbl.c + $(OPENSSL_PATH)/crypto/asn1/asn_pack.c + $(OPENSSL_PATH)/crypto/asn1/bio_asn1.c + $(OPENSSL_PATH)/crypto/asn1/bio_ndef.c + $(OPENSSL_PATH)/crypto/asn1/d2i_pr.c + $(OPENSSL_PATH)/crypto/asn1/d2i_pu.c + $(OPENSSL_PATH)/crypto/asn1/evp_asn1.c + $(OPENSSL_PATH)/crypto/asn1/f_int.c + $(OPENSSL_PATH)/crypto/asn1/f_string.c + $(OPENSSL_PATH)/crypto/asn1/i2d_pr.c + $(OPENSSL_PATH)/crypto/asn1/i2d_pu.c + $(OPENSSL_PATH)/crypto/asn1/n_pkey.c + $(OPENSSL_PATH)/crypto/asn1/nsseq.c + $(OPENSSL_PATH)/crypto/asn1/p5_pbe.c + $(OPENSSL_PATH)/crypto/asn1/p5_pbev2.c + $(OPENSSL_PATH)/crypto/asn1/p5_scrypt.c + $(OPENSSL_PATH)/crypto/asn1/p8_pkey.c + $(OPENSSL_PATH)/crypto/asn1/t_bitst.c + $(OPENSSL_PATH)/crypto/asn1/t_pkey.c + $(OPENSSL_PATH)/crypto/asn1/t_spki.c + $(OPENSSL_PATH)/crypto/asn1/tasn_dec.c + $(OPENSSL_PATH)/crypto/asn1/tasn_enc.c + $(OPENSSL_PATH)/crypto/asn1/tasn_fre.c + $(OPENSSL_PATH)/crypto/asn1/tasn_new.c + $(OPENSSL_PATH)/crypto/asn1/tasn_prn.c + $(OPENSSL_PATH)/crypto/asn1/tasn_scn.c + $(OPENSSL_PATH)/crypto/asn1/tasn_typ.c + $(OPENSSL_PATH)/crypto/asn1/tasn_utl.c + $(OPENSSL_PATH)/crypto/asn1/x_algor.c + $(OPENSSL_PATH)/crypto/asn1/x_bignum.c + $(OPENSSL_PATH)/crypto/asn1/x_info.c + $(OPENSSL_PATH)/crypto/asn1/x_int64.c + $(OPENSSL_PATH)/crypto/asn1/x_long.c + $(OPENSSL_PATH)/crypto/asn1/x_pkey.c + $(OPENSSL_PATH)/crypto/asn1/x_sig.c + $(OPENSSL_PATH)/crypto/asn1/x_spki.c + $(OPENSSL_PATH)/crypto/asn1/x_val.c + $(OPENSSL_PATH)/crypto/async/arch/async_null.c + $(OPENSSL_PATH)/crypto/async/arch/async_posix.c + $(OPENSSL_PATH)/crypto/async/arch/async_win.c + $(OPENSSL_PATH)/crypto/async/async.c + $(OPENSSL_PATH)/crypto/async/async_err.c + $(OPENSSL_PATH)/crypto/async/async_wait.c + $(OPENSSL_PATH)/crypto/bio/b_addr.c + $(OPENSSL_PATH)/crypto/bio/b_dump.c + $(OPENSSL_PATH)/crypto/bio/b_sock.c + $(OPENSSL_PATH)/crypto/bio/b_sock2.c + $(OPENSSL_PATH)/crypto/bio/bf_buff.c + $(OPENSSL_PATH)/crypto/bio/bf_lbuf.c + $(OPENSSL_PATH)/crypto/bio/bf_nbio.c + $(OPENSSL_PATH)/crypto/bio/bf_null.c + $(OPENSSL_PATH)/crypto/bio/bio_cb.c + $(OPENSSL_PATH)/crypto/bio/bio_err.c + $(OPENSSL_PATH)/crypto/bio/bio_lib.c + $(OPENSSL_PATH)/crypto/bio/bio_meth.c + $(OPENSSL_PATH)/crypto/bio/bss_acpt.c + $(OPENSSL_PATH)/crypto/bio/bss_bio.c + $(OPENSSL_PATH)/crypto/bio/bss_conn.c + $(OPENSSL_PATH)/crypto/bio/bss_dgram.c + $(OPENSSL_PATH)/crypto/bio/bss_fd.c + $(OPENSSL_PATH)/crypto/bio/bss_file.c + $(OPENSSL_PATH)/crypto/bio/bss_log.c + $(OPENSSL_PATH)/crypto/bio/bss_mem.c + $(OPENSSL_PATH)/crypto/bio/bss_null.c + $(OPENSSL_PATH)/crypto/bio/bss_sock.c + $(OPENSSL_PATH)/crypto/bn/bn_add.c + $(OPENSSL_PATH)/crypto/bn/bn_asm.c + $(OPENSSL_PATH)/crypto/bn/bn_blind.c + $(OPENSSL_PATH)/crypto/bn/bn_const.c + $(OPENSSL_PATH)/crypto/bn/bn_ctx.c + $(OPENSSL_PATH)/crypto/bn/bn_depr.c + $(OPENSSL_PATH)/crypto/bn/bn_dh.c + $(OPENSSL_PATH)/crypto/bn/bn_div.c + $(OPENSSL_PATH)/crypto/bn/bn_err.c + $(OPENSSL_PATH)/crypto/bn/bn_exp.c + $(OPENSSL_PATH)/crypto/bn/bn_exp2.c + $(OPENSSL_PATH)/crypto/bn/bn_gcd.c + $(OPENSSL_PATH)/crypto/bn/bn_gf2m.c + $(OPENSSL_PATH)/crypto/bn/bn_intern.c + $(OPENSSL_PATH)/crypto/bn/bn_kron.c + $(OPENSSL_PATH)/crypto/bn/bn_lib.c + $(OPENSSL_PATH)/crypto/bn/bn_mod.c + $(OPENSSL_PATH)/crypto/bn/bn_mont.c + $(OPENSSL_PATH)/crypto/bn/bn_mpi.c + $(OPENSSL_PATH)/crypto/bn/bn_mul.c + $(OPENSSL_PATH)/crypto/bn/bn_nist.c + $(OPENSSL_PATH)/crypto/bn/bn_prime.c + $(OPENSSL_PATH)/crypto/bn/bn_print.c + $(OPENSSL_PATH)/crypto/bn/bn_rand.c + $(OPENSSL_PATH)/crypto/bn/bn_recp.c + $(OPENSSL_PATH)/crypto/bn/bn_shift.c + $(OPENSSL_PATH)/crypto/bn/bn_sqr.c + $(OPENSSL_PATH)/crypto/bn/bn_sqrt.c + $(OPENSSL_PATH)/crypto/bn/bn_srp.c + $(OPENSSL_PATH)/crypto/bn/bn_word.c + $(OPENSSL_PATH)/crypto/bn/bn_x931p.c + $(OPENSSL_PATH)/crypto/buffer/buf_err.c + $(OPENSSL_PATH)/crypto/buffer/buffer.c + $(OPENSSL_PATH)/crypto/cmac/cm_ameth.c + $(OPENSSL_PATH)/crypto/cmac/cm_pmeth.c + $(OPENSSL_PATH)/crypto/cmac/cmac.c + $(OPENSSL_PATH)/crypto/comp/c_zlib.c + $(OPENSSL_PATH)/crypto/comp/comp_err.c + $(OPENSSL_PATH)/crypto/comp/comp_lib.c + $(OPENSSL_PATH)/crypto/conf/conf_api.c + $(OPENSSL_PATH)/crypto/conf/conf_def.c + $(OPENSSL_PATH)/crypto/conf/conf_err.c + $(OPENSSL_PATH)/crypto/conf/conf_lib.c + $(OPENSSL_PATH)/crypto/conf/conf_mall.c + $(OPENSSL_PATH)/crypto/conf/conf_mod.c + $(OPENSSL_PATH)/crypto/conf/conf_sap.c + $(OPENSSL_PATH)/crypto/conf/conf_ssl.c + $(OPENSSL_PATH)/crypto/cpt_err.c + $(OPENSSL_PATH)/crypto/cryptlib.c + $(OPENSSL_PATH)/crypto/cversion.c + $(OPENSSL_PATH)/crypto/des/cbc_cksm.c + $(OPENSSL_PATH)/crypto/des/cbc_enc.c + $(OPENSSL_PATH)/crypto/des/cfb64ede.c + $(OPENSSL_PATH)/crypto/des/cfb64enc.c + $(OPENSSL_PATH)/crypto/des/cfb_enc.c + $(OPENSSL_PATH)/crypto/des/des_enc.c + $(OPENSSL_PATH)/crypto/des/ecb3_enc.c + $(OPENSSL_PATH)/crypto/des/ecb_enc.c + $(OPENSSL_PATH)/crypto/des/fcrypt.c + $(OPENSSL_PATH)/crypto/des/fcrypt_b.c + $(OPENSSL_PATH)/crypto/des/ofb64ede.c + $(OPENSSL_PATH)/crypto/des/ofb64enc.c + $(OPENSSL_PATH)/crypto/des/ofb_enc.c + $(OPENSSL_PATH)/crypto/des/pcbc_enc.c + $(OPENSSL_PATH)/crypto/des/qud_cksm.c + $(OPENSSL_PATH)/crypto/des/rand_key.c + $(OPENSSL_PATH)/crypto/des/rpc_enc.c + $(OPENSSL_PATH)/crypto/des/set_key.c + $(OPENSSL_PATH)/crypto/des/str2key.c + $(OPENSSL_PATH)/crypto/des/xcbc_enc.c + $(OPENSSL_PATH)/crypto/dh/dh_ameth.c + $(OPENSSL_PATH)/crypto/dh/dh_asn1.c + $(OPENSSL_PATH)/crypto/dh/dh_check.c + $(OPENSSL_PATH)/crypto/dh/dh_depr.c + $(OPENSSL_PATH)/crypto/dh/dh_err.c + $(OPENSSL_PATH)/crypto/dh/dh_gen.c + $(OPENSSL_PATH)/crypto/dh/dh_kdf.c + $(OPENSSL_PATH)/crypto/dh/dh_key.c + $(OPENSSL_PATH)/crypto/dh/dh_lib.c + $(OPENSSL_PATH)/crypto/dh/dh_meth.c + $(OPENSSL_PATH)/crypto/dh/dh_pmeth.c + $(OPENSSL_PATH)/crypto/dh/dh_prn.c + $(OPENSSL_PATH)/crypto/dh/dh_rfc5114.c + $(OPENSSL_PATH)/crypto/dso/dso_dl.c + $(OPENSSL_PATH)/crypto/dso/dso_dlfcn.c + $(OPENSSL_PATH)/crypto/dso/dso_err.c + $(OPENSSL_PATH)/crypto/dso/dso_lib.c + $(OPENSSL_PATH)/crypto/dso/dso_openssl.c + $(OPENSSL_PATH)/crypto/dso/dso_vms.c + $(OPENSSL_PATH)/crypto/dso/dso_win32.c + $(OPENSSL_PATH)/crypto/ebcdic.c + $(OPENSSL_PATH)/crypto/err/err.c + $(OPENSSL_PATH)/crypto/err/err_all.c + $(OPENSSL_PATH)/crypto/err/err_prn.c + $(OPENSSL_PATH)/crypto/evp/bio_b64.c + $(OPENSSL_PATH)/crypto/evp/bio_enc.c + $(OPENSSL_PATH)/crypto/evp/bio_md.c + $(OPENSSL_PATH)/crypto/evp/bio_ok.c + $(OPENSSL_PATH)/crypto/evp/c_allc.c + $(OPENSSL_PATH)/crypto/evp/c_alld.c + $(OPENSSL_PATH)/crypto/evp/cmeth_lib.c + $(OPENSSL_PATH)/crypto/evp/digest.c + $(OPENSSL_PATH)/crypto/evp/e_aes.c + $(OPENSSL_PATH)/crypto/evp/e_aes_cbc_hmac_sha1.c + $(OPENSSL_PATH)/crypto/evp/e_aes_cbc_hmac_sha256.c + $(OPENSSL_PATH)/crypto/evp/e_bf.c + $(OPENSSL_PATH)/crypto/evp/e_camellia.c + $(OPENSSL_PATH)/crypto/evp/e_cast.c + $(OPENSSL_PATH)/crypto/evp/e_chacha20_poly1305.c + $(OPENSSL_PATH)/crypto/evp/e_des.c + $(OPENSSL_PATH)/crypto/evp/e_des3.c + $(OPENSSL_PATH)/crypto/evp/e_idea.c + $(OPENSSL_PATH)/crypto/evp/e_null.c + $(OPENSSL_PATH)/crypto/evp/e_old.c + $(OPENSSL_PATH)/crypto/evp/e_rc2.c + $(OPENSSL_PATH)/crypto/evp/e_rc4.c + $(OPENSSL_PATH)/crypto/evp/e_rc4_hmac_md5.c + $(OPENSSL_PATH)/crypto/evp/e_rc5.c + $(OPENSSL_PATH)/crypto/evp/e_seed.c + $(OPENSSL_PATH)/crypto/evp/e_xcbc_d.c + $(OPENSSL_PATH)/crypto/evp/encode.c + $(OPENSSL_PATH)/crypto/evp/evp_cnf.c + $(OPENSSL_PATH)/crypto/evp/evp_enc.c + $(OPENSSL_PATH)/crypto/evp/evp_err.c + $(OPENSSL_PATH)/crypto/evp/evp_key.c + $(OPENSSL_PATH)/crypto/evp/evp_lib.c + $(OPENSSL_PATH)/crypto/evp/evp_pbe.c + $(OPENSSL_PATH)/crypto/evp/evp_pkey.c + $(OPENSSL_PATH)/crypto/evp/m_md2.c + $(OPENSSL_PATH)/crypto/evp/m_md4.c + $(OPENSSL_PATH)/crypto/evp/m_md5.c + $(OPENSSL_PATH)/crypto/evp/m_md5_sha1.c + $(OPENSSL_PATH)/crypto/evp/m_mdc2.c + $(OPENSSL_PATH)/crypto/evp/m_null.c + $(OPENSSL_PATH)/crypto/evp/m_ripemd.c + $(OPENSSL_PATH)/crypto/evp/m_sha1.c + $(OPENSSL_PATH)/crypto/evp/m_sigver.c + $(OPENSSL_PATH)/crypto/evp/m_wp.c + $(OPENSSL_PATH)/crypto/evp/names.c + $(OPENSSL_PATH)/crypto/evp/p5_crpt.c + $(OPENSSL_PATH)/crypto/evp/p5_crpt2.c + $(OPENSSL_PATH)/crypto/evp/p_dec.c + $(OPENSSL_PATH)/crypto/evp/p_enc.c + $(OPENSSL_PATH)/crypto/evp/p_lib.c + $(OPENSSL_PATH)/crypto/evp/p_open.c + $(OPENSSL_PATH)/crypto/evp/p_seal.c + $(OPENSSL_PATH)/crypto/evp/p_sign.c + $(OPENSSL_PATH)/crypto/evp/p_verify.c + $(OPENSSL_PATH)/crypto/evp/pmeth_fn.c + $(OPENSSL_PATH)/crypto/evp/pmeth_gn.c + $(OPENSSL_PATH)/crypto/evp/pmeth_lib.c + $(OPENSSL_PATH)/crypto/evp/scrypt.c + $(OPENSSL_PATH)/crypto/ex_data.c + $(OPENSSL_PATH)/crypto/getenv.c + $(OPENSSL_PATH)/crypto/hmac/hm_ameth.c + $(OPENSSL_PATH)/crypto/hmac/hm_pmeth.c + $(OPENSSL_PATH)/crypto/hmac/hmac.c + $(OPENSSL_PATH)/crypto/init.c + $(OPENSSL_PATH)/crypto/kdf/hkdf.c + $(OPENSSL_PATH)/crypto/kdf/kdf_err.c + $(OPENSSL_PATH)/crypto/kdf/tls1_prf.c + $(OPENSSL_PATH)/crypto/lhash/lh_stats.c + $(OPENSSL_PATH)/crypto/lhash/lhash.c + $(OPENSSL_PATH)/crypto/md4/md4_dgst.c + $(OPENSSL_PATH)/crypto/md4/md4_one.c + $(OPENSSL_PATH)/crypto/md5/md5_dgst.c + $(OPENSSL_PATH)/crypto/md5/md5_one.c + $(OPENSSL_PATH)/crypto/mem.c + $(OPENSSL_PATH)/crypto/mem_clr.c + $(OPENSSL_PATH)/crypto/mem_dbg.c + $(OPENSSL_PATH)/crypto/mem_sec.c + $(OPENSSL_PATH)/crypto/modes/cbc128.c + $(OPENSSL_PATH)/crypto/modes/ccm128.c + $(OPENSSL_PATH)/crypto/modes/cfb128.c + $(OPENSSL_PATH)/crypto/modes/ctr128.c + $(OPENSSL_PATH)/crypto/modes/cts128.c + $(OPENSSL_PATH)/crypto/modes/gcm128.c + $(OPENSSL_PATH)/crypto/modes/ocb128.c + $(OPENSSL_PATH)/crypto/modes/ofb128.c + $(OPENSSL_PATH)/crypto/modes/wrap128.c + $(OPENSSL_PATH)/crypto/modes/xts128.c + $(OPENSSL_PATH)/crypto/o_dir.c + $(OPENSSL_PATH)/crypto/o_fips.c + $(OPENSSL_PATH)/crypto/o_fopen.c + $(OPENSSL_PATH)/crypto/o_init.c + $(OPENSSL_PATH)/crypto/o_str.c + $(OPENSSL_PATH)/crypto/o_time.c + $(OPENSSL_PATH)/crypto/objects/o_names.c + $(OPENSSL_PATH)/crypto/objects/obj_dat.c + $(OPENSSL_PATH)/crypto/objects/obj_err.c + $(OPENSSL_PATH)/crypto/objects/obj_lib.c + $(OPENSSL_PATH)/crypto/objects/obj_xref.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_asn.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_cl.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_err.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_ext.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_ht.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_lib.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_prn.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_srv.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_vfy.c + $(OPENSSL_PATH)/crypto/ocsp/v3_ocsp.c + $(OPENSSL_PATH)/crypto/pem/pem_all.c + $(OPENSSL_PATH)/crypto/pem/pem_err.c + $(OPENSSL_PATH)/crypto/pem/pem_info.c + $(OPENSSL_PATH)/crypto/pem/pem_lib.c + $(OPENSSL_PATH)/crypto/pem/pem_oth.c + $(OPENSSL_PATH)/crypto/pem/pem_pk8.c + $(OPENSSL_PATH)/crypto/pem/pem_pkey.c + $(OPENSSL_PATH)/crypto/pem/pem_sign.c + $(OPENSSL_PATH)/crypto/pem/pem_x509.c + $(OPENSSL_PATH)/crypto/pem/pem_xaux.c + $(OPENSSL_PATH)/crypto/pem/pvkfmt.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_add.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_asn.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_attr.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_crpt.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_crt.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_decr.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_init.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_key.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_kiss.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_mutl.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_npas.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_p8d.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_p8e.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_sbag.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_utl.c + $(OPENSSL_PATH)/crypto/pkcs12/pk12err.c + $(OPENSSL_PATH)/crypto/pkcs7/bio_pk7.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_asn1.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_attr.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_doit.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_lib.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_mime.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_smime.c + $(OPENSSL_PATH)/crypto/pkcs7/pkcs7err.c + $(OPENSSL_PATH)/crypto/rand/md_rand.c + $(OPENSSL_PATH)/crypto/rand/rand_egd.c + $(OPENSSL_PATH)/crypto/rand/rand_err.c + $(OPENSSL_PATH)/crypto/rand/rand_lib.c + $(OPENSSL_PATH)/crypto/rand/rand_unix.c + $(OPENSSL_PATH)/crypto/rand/rand_vms.c + $(OPENSSL_PATH)/crypto/rand/rand_win.c + $(OPENSSL_PATH)/crypto/rand/randfile.c + $(OPENSSL_PATH)/crypto/rc4/rc4_enc.c + $(OPENSSL_PATH)/crypto/rc4/rc4_skey.c + $(OPENSSL_PATH)/crypto/rsa/rsa_ameth.c + $(OPENSSL_PATH)/crypto/rsa/rsa_asn1.c + $(OPENSSL_PATH)/crypto/rsa/rsa_chk.c + $(OPENSSL_PATH)/crypto/rsa/rsa_crpt.c + $(OPENSSL_PATH)/crypto/rsa/rsa_depr.c + $(OPENSSL_PATH)/crypto/rsa/rsa_err.c + $(OPENSSL_PATH)/crypto/rsa/rsa_gen.c + $(OPENSSL_PATH)/crypto/rsa/rsa_lib.c + $(OPENSSL_PATH)/crypto/rsa/rsa_meth.c + $(OPENSSL_PATH)/crypto/rsa/rsa_none.c + $(OPENSSL_PATH)/crypto/rsa/rsa_null.c + $(OPENSSL_PATH)/crypto/rsa/rsa_oaep.c + $(OPENSSL_PATH)/crypto/rsa/rsa_ossl.c + $(OPENSSL_PATH)/crypto/rsa/rsa_pk1.c + $(OPENSSL_PATH)/crypto/rsa/rsa_pmeth.c + $(OPENSSL_PATH)/crypto/rsa/rsa_prn.c + $(OPENSSL_PATH)/crypto/rsa/rsa_pss.c + $(OPENSSL_PATH)/crypto/rsa/rsa_saos.c + $(OPENSSL_PATH)/crypto/rsa/rsa_sign.c + $(OPENSSL_PATH)/crypto/rsa/rsa_ssl.c + $(OPENSSL_PATH)/crypto/rsa/rsa_x931.c + $(OPENSSL_PATH)/crypto/rsa/rsa_x931g.c + $(OPENSSL_PATH)/crypto/sha/sha1_one.c + $(OPENSSL_PATH)/crypto/sha/sha1dgst.c + $(OPENSSL_PATH)/crypto/sha/sha256.c + $(OPENSSL_PATH)/crypto/sha/sha512.c + $(OPENSSL_PATH)/crypto/stack/stack.c + $(OPENSSL_PATH)/crypto/threads_none.c + $(OPENSSL_PATH)/crypto/threads_pthread.c + $(OPENSSL_PATH)/crypto/threads_win.c + $(OPENSSL_PATH)/crypto/txt_db/txt_db.c + $(OPENSSL_PATH)/crypto/uid.c + $(OPENSSL_PATH)/crypto/x509/by_dir.c + $(OPENSSL_PATH)/crypto/x509/by_file.c + $(OPENSSL_PATH)/crypto/x509/t_crl.c + $(OPENSSL_PATH)/crypto/x509/t_req.c + $(OPENSSL_PATH)/crypto/x509/t_x509.c + $(OPENSSL_PATH)/crypto/x509/x509_att.c + $(OPENSSL_PATH)/crypto/x509/x509_cmp.c + $(OPENSSL_PATH)/crypto/x509/x509_d2.c + $(OPENSSL_PATH)/crypto/x509/x509_def.c + $(OPENSSL_PATH)/crypto/x509/x509_err.c + $(OPENSSL_PATH)/crypto/x509/x509_ext.c + $(OPENSSL_PATH)/crypto/x509/x509_lu.c + $(OPENSSL_PATH)/crypto/x509/x509_meth.c + $(OPENSSL_PATH)/crypto/x509/x509_obj.c + $(OPENSSL_PATH)/crypto/x509/x509_r2x.c + $(OPENSSL_PATH)/crypto/x509/x509_req.c + $(OPENSSL_PATH)/crypto/x509/x509_set.c + $(OPENSSL_PATH)/crypto/x509/x509_trs.c + $(OPENSSL_PATH)/crypto/x509/x509_txt.c + $(OPENSSL_PATH)/crypto/x509/x509_v3.c + $(OPENSSL_PATH)/crypto/x509/x509_vfy.c + $(OPENSSL_PATH)/crypto/x509/x509_vpm.c + $(OPENSSL_PATH)/crypto/x509/x509cset.c + $(OPENSSL_PATH)/crypto/x509/x509name.c + $(OPENSSL_PATH)/crypto/x509/x509rset.c + $(OPENSSL_PATH)/crypto/x509/x509spki.c + $(OPENSSL_PATH)/crypto/x509/x509type.c + $(OPENSSL_PATH)/crypto/x509/x_all.c + $(OPENSSL_PATH)/crypto/x509/x_attrib.c + $(OPENSSL_PATH)/crypto/x509/x_crl.c + $(OPENSSL_PATH)/crypto/x509/x_exten.c + $(OPENSSL_PATH)/crypto/x509/x_name.c + $(OPENSSL_PATH)/crypto/x509/x_pubkey.c + $(OPENSSL_PATH)/crypto/x509/x_req.c + $(OPENSSL_PATH)/crypto/x509/x_x509.c + $(OPENSSL_PATH)/crypto/x509/x_x509a.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_cache.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_data.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_lib.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_map.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_node.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_tree.c + $(OPENSSL_PATH)/crypto/x509v3/v3_addr.c + $(OPENSSL_PATH)/crypto/x509v3/v3_akey.c + $(OPENSSL_PATH)/crypto/x509v3/v3_akeya.c + $(OPENSSL_PATH)/crypto/x509v3/v3_alt.c + $(OPENSSL_PATH)/crypto/x509v3/v3_asid.c + $(OPENSSL_PATH)/crypto/x509v3/v3_bcons.c + $(OPENSSL_PATH)/crypto/x509v3/v3_bitst.c + $(OPENSSL_PATH)/crypto/x509v3/v3_conf.c + $(OPENSSL_PATH)/crypto/x509v3/v3_cpols.c + $(OPENSSL_PATH)/crypto/x509v3/v3_crld.c + $(OPENSSL_PATH)/crypto/x509v3/v3_enum.c + $(OPENSSL_PATH)/crypto/x509v3/v3_extku.c + $(OPENSSL_PATH)/crypto/x509v3/v3_genn.c + $(OPENSSL_PATH)/crypto/x509v3/v3_ia5.c + $(OPENSSL_PATH)/crypto/x509v3/v3_info.c + $(OPENSSL_PATH)/crypto/x509v3/v3_int.c + $(OPENSSL_PATH)/crypto/x509v3/v3_lib.c + $(OPENSSL_PATH)/crypto/x509v3/v3_ncons.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pci.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pcia.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pcons.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pku.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pmaps.c + $(OPENSSL_PATH)/crypto/x509v3/v3_prn.c + $(OPENSSL_PATH)/crypto/x509v3/v3_purp.c + $(OPENSSL_PATH)/crypto/x509v3/v3_skey.c + $(OPENSSL_PATH)/crypto/x509v3/v3_sxnet.c + $(OPENSSL_PATH)/crypto/x509v3/v3_tlsf.c + $(OPENSSL_PATH)/crypto/x509v3/v3_utl.c + $(OPENSSL_PATH)/crypto/x509v3/v3err.c + $(OPENSSL_PATH)/ssl/bio_ssl.c + $(OPENSSL_PATH)/ssl/d1_lib.c + $(OPENSSL_PATH)/ssl/d1_msg.c + $(OPENSSL_PATH)/ssl/d1_srtp.c + $(OPENSSL_PATH)/ssl/methods.c + $(OPENSSL_PATH)/ssl/pqueue.c + $(OPENSSL_PATH)/ssl/record/dtls1_bitmap.c + $(OPENSSL_PATH)/ssl/record/rec_layer_d1.c + $(OPENSSL_PATH)/ssl/record/rec_layer_s3.c + $(OPENSSL_PATH)/ssl/record/ssl3_buffer.c + $(OPENSSL_PATH)/ssl/record/ssl3_record.c + $(OPENSSL_PATH)/ssl/s3_cbc.c + $(OPENSSL_PATH)/ssl/s3_enc.c + $(OPENSSL_PATH)/ssl/s3_lib.c + $(OPENSSL_PATH)/ssl/s3_msg.c + $(OPENSSL_PATH)/ssl/ssl_asn1.c + $(OPENSSL_PATH)/ssl/ssl_cert.c + $(OPENSSL_PATH)/ssl/ssl_ciph.c + $(OPENSSL_PATH)/ssl/ssl_conf.c + $(OPENSSL_PATH)/ssl/ssl_err.c + $(OPENSSL_PATH)/ssl/ssl_init.c + $(OPENSSL_PATH)/ssl/ssl_lib.c + $(OPENSSL_PATH)/ssl/ssl_mcnf.c + $(OPENSSL_PATH)/ssl/ssl_rsa.c + $(OPENSSL_PATH)/ssl/ssl_sess.c + $(OPENSSL_PATH)/ssl/ssl_stat.c + $(OPENSSL_PATH)/ssl/ssl_txt.c + $(OPENSSL_PATH)/ssl/ssl_utst.c + $(OPENSSL_PATH)/ssl/statem/statem.c + $(OPENSSL_PATH)/ssl/statem/statem_clnt.c + $(OPENSSL_PATH)/ssl/statem/statem_dtls.c + $(OPENSSL_PATH)/ssl/statem/statem_lib.c + $(OPENSSL_PATH)/ssl/statem/statem_srvr.c + $(OPENSSL_PATH)/ssl/t1_enc.c + $(OPENSSL_PATH)/ssl/t1_ext.c + $(OPENSSL_PATH)/ssl/t1_lib.c + $(OPENSSL_PATH)/ssl/t1_reneg.c + $(OPENSSL_PATH)/ssl/t1_trce.c + $(OPENSSL_PATH)/ssl/tls_srp.c +# Autogenerated files list ends here + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + DebugLib + +[LibraryClasses.ARM] + ArmSoftFloatLib + +[BuildOptions] + # + # Disables the following Visual Studio compiler warnings brought by openssl source, + # so we do not break the build with /WX option: + # C4090: 'function' : different 'const' qualifiers + # C4244: conversion from type1 to type2, possible loss of data + # C4245: conversion from type1 to type2, signed/unsigned mismatch + # C4267: conversion from size_t to type, possible loss of data + # C4306: 'identifier' : conversion from 'type1' to 'type2' of greater size + # C4389: 'operator' : signed/unsigned mismatch (xxxx) + # C4702: unreachable code + # C4706: assignment within conditional expression + # C4819: The file contains a character that cannot be represented in the current code page + # + MSFT:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4090 /wd4244 /wd4245 /wd4267 /wd4389 /wd4702 /wd4706 /wd4819 + MSFT:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4090 /wd4244 /wd4245 /wd4267 /wd4306 /wd4389 /wd4702 /wd4706 /wd4819 + + INTEL:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w + INTEL:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w + + # + # Suppress the following build warnings in openssl so we don't break the build with -Werror + # -Werror=maybe-uninitialized: there exist some other paths for which the variable is not initialized. + # -Werror=format: Check calls to printf and scanf, etc., to make sure that the arguments supplied have + # types appropriate to the format string specified. + # + GCC:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized + GCC:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-error=format -Wno-format -DNO_MSABI_VA_FUNCS + GCC:*_*_ARM_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized + GCC:*_*_AARCH64_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-format + + # suppress the following warnings in openssl so we don't break the build with warnings-as-errors: + # 1295: Deprecated declaration - give arg types + # 550: was set but never used + # 1293: assignment in condition + # 111: statement is unreachable (invariably "break;" after "return X;" in case statement) + # 68: integer conversion resulted in a change of sign ("if (Status == -1)") + # 177: was declared but never referenced + # 223: function declared implicitly + # 144: a value of type cannot be used to initialize an entity of type + # 513: a value of type cannot be assigned to an entity of type + # 188: enumerated type mixed with another type (i.e. passing an integer as an enum without a cast) + # 1296: Extended constant initialiser used + # 128: loop is not reachable - may be emitted inappropriately if code follows a conditional return + # from the function that evaluates to true at compile time + # 546: transfer of control bypasses initialization - may be emitted inappropriately if the uninitialized + # variable is never referenced after the jump + # 1: ignore "#1-D: last line of file ends without a newline" + # 3017: may be used before being set (NOTE: This was fixed in OpenSSL 1.1 HEAD with + # commit d9b8b89bec4480de3a10bdaf9425db371c19145b, and can be dropped then.) + RVCT:*_*_ARM_CC_FLAGS = $(OPENSSL_FLAGS) --library_interface=aeabi_clib99 --diag_suppress=1296,1295,550,1293,111,68,177,223,144,513,188,128,546,1,3017 -JCryptoPkg/Include + XCODE:*_*_IA32_CC_FLAGS = -mmmx -msse -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -w + XCODE:*_*_X64_CC_FLAGS = -mmmx -msse -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -w + + # + # AARCH64 uses strict alignment and avoids SIMD registers for code that may execute + # with the MMU off. This involves SEC, PEI_CORE and PEIM modules as well as BASE + # libraries, given that they may be included into such modules. + # This library, even though of the BASE type, is never used in such cases, and + # avoiding the SIMD register file (which is shared with the FPU) prevents the + # compiler from successfully building some of the OpenSSL source files that + # use floating point types, so clear the flags here. + # + GCC:*_*_AARCH64_CC_XIPFLAGS == diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.uni new file mode 100644 index 0000000..f91f2ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLib.uni @@ -0,0 +1,22 @@ +// /** @file +// This module provides openSSL Library implementation. +// +// This module provides OpenSSL Library implementation. +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "OpenSSL Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "This module provides OpenSSL Library implementation." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf new file mode 100644 index 0000000..9a64c80 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf @@ -0,0 +1,558 @@ +## @file +# This module provides OpenSSL Library implementation. +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OpensslLibCrypto + MODULE_UNI_FILE = OpensslLibCrypto.uni + FILE_GUID = E29FC209-8B64-4500-BD20-AF4EAE47EA0E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = OpensslLib + DEFINE OPENSSL_PATH = openssl + DEFINE OPENSSL_FLAGS = -DL_ENDIAN -DOPENSSL_SMALL_FOOTPRINT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DNO_SYSLOG + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + $(OPENSSL_PATH)/e_os.h +# Autogenerated files list starts here + $(OPENSSL_PATH)/crypto/aes/aes_cbc.c + $(OPENSSL_PATH)/crypto/aes/aes_cfb.c + $(OPENSSL_PATH)/crypto/aes/aes_core.c + $(OPENSSL_PATH)/crypto/aes/aes_ecb.c + $(OPENSSL_PATH)/crypto/aes/aes_ige.c + $(OPENSSL_PATH)/crypto/aes/aes_misc.c + $(OPENSSL_PATH)/crypto/aes/aes_ofb.c + $(OPENSSL_PATH)/crypto/aes/aes_wrap.c + $(OPENSSL_PATH)/crypto/asn1/a_bitstr.c + $(OPENSSL_PATH)/crypto/asn1/a_d2i_fp.c + $(OPENSSL_PATH)/crypto/asn1/a_digest.c + $(OPENSSL_PATH)/crypto/asn1/a_dup.c + $(OPENSSL_PATH)/crypto/asn1/a_gentm.c + $(OPENSSL_PATH)/crypto/asn1/a_i2d_fp.c + $(OPENSSL_PATH)/crypto/asn1/a_int.c + $(OPENSSL_PATH)/crypto/asn1/a_mbstr.c + $(OPENSSL_PATH)/crypto/asn1/a_object.c + $(OPENSSL_PATH)/crypto/asn1/a_octet.c + $(OPENSSL_PATH)/crypto/asn1/a_print.c + $(OPENSSL_PATH)/crypto/asn1/a_sign.c + $(OPENSSL_PATH)/crypto/asn1/a_strex.c + $(OPENSSL_PATH)/crypto/asn1/a_strnid.c + $(OPENSSL_PATH)/crypto/asn1/a_time.c + $(OPENSSL_PATH)/crypto/asn1/a_type.c + $(OPENSSL_PATH)/crypto/asn1/a_utctm.c + $(OPENSSL_PATH)/crypto/asn1/a_utf8.c + $(OPENSSL_PATH)/crypto/asn1/a_verify.c + $(OPENSSL_PATH)/crypto/asn1/ameth_lib.c + $(OPENSSL_PATH)/crypto/asn1/asn1_err.c + $(OPENSSL_PATH)/crypto/asn1/asn1_gen.c + $(OPENSSL_PATH)/crypto/asn1/asn1_lib.c + $(OPENSSL_PATH)/crypto/asn1/asn1_par.c + $(OPENSSL_PATH)/crypto/asn1/asn_mime.c + $(OPENSSL_PATH)/crypto/asn1/asn_moid.c + $(OPENSSL_PATH)/crypto/asn1/asn_mstbl.c + $(OPENSSL_PATH)/crypto/asn1/asn_pack.c + $(OPENSSL_PATH)/crypto/asn1/bio_asn1.c + $(OPENSSL_PATH)/crypto/asn1/bio_ndef.c + $(OPENSSL_PATH)/crypto/asn1/d2i_pr.c + $(OPENSSL_PATH)/crypto/asn1/d2i_pu.c + $(OPENSSL_PATH)/crypto/asn1/evp_asn1.c + $(OPENSSL_PATH)/crypto/asn1/f_int.c + $(OPENSSL_PATH)/crypto/asn1/f_string.c + $(OPENSSL_PATH)/crypto/asn1/i2d_pr.c + $(OPENSSL_PATH)/crypto/asn1/i2d_pu.c + $(OPENSSL_PATH)/crypto/asn1/n_pkey.c + $(OPENSSL_PATH)/crypto/asn1/nsseq.c + $(OPENSSL_PATH)/crypto/asn1/p5_pbe.c + $(OPENSSL_PATH)/crypto/asn1/p5_pbev2.c + $(OPENSSL_PATH)/crypto/asn1/p5_scrypt.c + $(OPENSSL_PATH)/crypto/asn1/p8_pkey.c + $(OPENSSL_PATH)/crypto/asn1/t_bitst.c + $(OPENSSL_PATH)/crypto/asn1/t_pkey.c + $(OPENSSL_PATH)/crypto/asn1/t_spki.c + $(OPENSSL_PATH)/crypto/asn1/tasn_dec.c + $(OPENSSL_PATH)/crypto/asn1/tasn_enc.c + $(OPENSSL_PATH)/crypto/asn1/tasn_fre.c + $(OPENSSL_PATH)/crypto/asn1/tasn_new.c + $(OPENSSL_PATH)/crypto/asn1/tasn_prn.c + $(OPENSSL_PATH)/crypto/asn1/tasn_scn.c + $(OPENSSL_PATH)/crypto/asn1/tasn_typ.c + $(OPENSSL_PATH)/crypto/asn1/tasn_utl.c + $(OPENSSL_PATH)/crypto/asn1/x_algor.c + $(OPENSSL_PATH)/crypto/asn1/x_bignum.c + $(OPENSSL_PATH)/crypto/asn1/x_info.c + $(OPENSSL_PATH)/crypto/asn1/x_int64.c + $(OPENSSL_PATH)/crypto/asn1/x_long.c + $(OPENSSL_PATH)/crypto/asn1/x_pkey.c + $(OPENSSL_PATH)/crypto/asn1/x_sig.c + $(OPENSSL_PATH)/crypto/asn1/x_spki.c + $(OPENSSL_PATH)/crypto/asn1/x_val.c + $(OPENSSL_PATH)/crypto/async/arch/async_null.c + $(OPENSSL_PATH)/crypto/async/arch/async_posix.c + $(OPENSSL_PATH)/crypto/async/arch/async_win.c + $(OPENSSL_PATH)/crypto/async/async.c + $(OPENSSL_PATH)/crypto/async/async_err.c + $(OPENSSL_PATH)/crypto/async/async_wait.c + $(OPENSSL_PATH)/crypto/bio/b_addr.c + $(OPENSSL_PATH)/crypto/bio/b_dump.c + $(OPENSSL_PATH)/crypto/bio/b_sock.c + $(OPENSSL_PATH)/crypto/bio/b_sock2.c + $(OPENSSL_PATH)/crypto/bio/bf_buff.c + $(OPENSSL_PATH)/crypto/bio/bf_lbuf.c + $(OPENSSL_PATH)/crypto/bio/bf_nbio.c + $(OPENSSL_PATH)/crypto/bio/bf_null.c + $(OPENSSL_PATH)/crypto/bio/bio_cb.c + $(OPENSSL_PATH)/crypto/bio/bio_err.c + $(OPENSSL_PATH)/crypto/bio/bio_lib.c + $(OPENSSL_PATH)/crypto/bio/bio_meth.c + $(OPENSSL_PATH)/crypto/bio/bss_acpt.c + $(OPENSSL_PATH)/crypto/bio/bss_bio.c + $(OPENSSL_PATH)/crypto/bio/bss_conn.c + $(OPENSSL_PATH)/crypto/bio/bss_dgram.c + $(OPENSSL_PATH)/crypto/bio/bss_fd.c + $(OPENSSL_PATH)/crypto/bio/bss_file.c + $(OPENSSL_PATH)/crypto/bio/bss_log.c + $(OPENSSL_PATH)/crypto/bio/bss_mem.c + $(OPENSSL_PATH)/crypto/bio/bss_null.c + $(OPENSSL_PATH)/crypto/bio/bss_sock.c + $(OPENSSL_PATH)/crypto/bn/bn_add.c + $(OPENSSL_PATH)/crypto/bn/bn_asm.c + $(OPENSSL_PATH)/crypto/bn/bn_blind.c + $(OPENSSL_PATH)/crypto/bn/bn_const.c + $(OPENSSL_PATH)/crypto/bn/bn_ctx.c + $(OPENSSL_PATH)/crypto/bn/bn_depr.c + $(OPENSSL_PATH)/crypto/bn/bn_dh.c + $(OPENSSL_PATH)/crypto/bn/bn_div.c + $(OPENSSL_PATH)/crypto/bn/bn_err.c + $(OPENSSL_PATH)/crypto/bn/bn_exp.c + $(OPENSSL_PATH)/crypto/bn/bn_exp2.c + $(OPENSSL_PATH)/crypto/bn/bn_gcd.c + $(OPENSSL_PATH)/crypto/bn/bn_gf2m.c + $(OPENSSL_PATH)/crypto/bn/bn_intern.c + $(OPENSSL_PATH)/crypto/bn/bn_kron.c + $(OPENSSL_PATH)/crypto/bn/bn_lib.c + $(OPENSSL_PATH)/crypto/bn/bn_mod.c + $(OPENSSL_PATH)/crypto/bn/bn_mont.c + $(OPENSSL_PATH)/crypto/bn/bn_mpi.c + $(OPENSSL_PATH)/crypto/bn/bn_mul.c + $(OPENSSL_PATH)/crypto/bn/bn_nist.c + $(OPENSSL_PATH)/crypto/bn/bn_prime.c + $(OPENSSL_PATH)/crypto/bn/bn_print.c + $(OPENSSL_PATH)/crypto/bn/bn_rand.c + $(OPENSSL_PATH)/crypto/bn/bn_recp.c + $(OPENSSL_PATH)/crypto/bn/bn_shift.c + $(OPENSSL_PATH)/crypto/bn/bn_sqr.c + $(OPENSSL_PATH)/crypto/bn/bn_sqrt.c + $(OPENSSL_PATH)/crypto/bn/bn_srp.c + $(OPENSSL_PATH)/crypto/bn/bn_word.c + $(OPENSSL_PATH)/crypto/bn/bn_x931p.c + $(OPENSSL_PATH)/crypto/buffer/buf_err.c + $(OPENSSL_PATH)/crypto/buffer/buffer.c + $(OPENSSL_PATH)/crypto/cmac/cm_ameth.c + $(OPENSSL_PATH)/crypto/cmac/cm_pmeth.c + $(OPENSSL_PATH)/crypto/cmac/cmac.c + $(OPENSSL_PATH)/crypto/comp/c_zlib.c + $(OPENSSL_PATH)/crypto/comp/comp_err.c + $(OPENSSL_PATH)/crypto/comp/comp_lib.c + $(OPENSSL_PATH)/crypto/conf/conf_api.c + $(OPENSSL_PATH)/crypto/conf/conf_def.c + $(OPENSSL_PATH)/crypto/conf/conf_err.c + $(OPENSSL_PATH)/crypto/conf/conf_lib.c + $(OPENSSL_PATH)/crypto/conf/conf_mall.c + $(OPENSSL_PATH)/crypto/conf/conf_mod.c + $(OPENSSL_PATH)/crypto/conf/conf_sap.c + $(OPENSSL_PATH)/crypto/conf/conf_ssl.c + $(OPENSSL_PATH)/crypto/cpt_err.c + $(OPENSSL_PATH)/crypto/cryptlib.c + $(OPENSSL_PATH)/crypto/cversion.c + $(OPENSSL_PATH)/crypto/des/cbc_cksm.c + $(OPENSSL_PATH)/crypto/des/cbc_enc.c + $(OPENSSL_PATH)/crypto/des/cfb64ede.c + $(OPENSSL_PATH)/crypto/des/cfb64enc.c + $(OPENSSL_PATH)/crypto/des/cfb_enc.c + $(OPENSSL_PATH)/crypto/des/des_enc.c + $(OPENSSL_PATH)/crypto/des/ecb3_enc.c + $(OPENSSL_PATH)/crypto/des/ecb_enc.c + $(OPENSSL_PATH)/crypto/des/fcrypt.c + $(OPENSSL_PATH)/crypto/des/fcrypt_b.c + $(OPENSSL_PATH)/crypto/des/ofb64ede.c + $(OPENSSL_PATH)/crypto/des/ofb64enc.c + $(OPENSSL_PATH)/crypto/des/ofb_enc.c + $(OPENSSL_PATH)/crypto/des/pcbc_enc.c + $(OPENSSL_PATH)/crypto/des/qud_cksm.c + $(OPENSSL_PATH)/crypto/des/rand_key.c + $(OPENSSL_PATH)/crypto/des/rpc_enc.c + $(OPENSSL_PATH)/crypto/des/set_key.c + $(OPENSSL_PATH)/crypto/des/str2key.c + $(OPENSSL_PATH)/crypto/des/xcbc_enc.c + $(OPENSSL_PATH)/crypto/dh/dh_ameth.c + $(OPENSSL_PATH)/crypto/dh/dh_asn1.c + $(OPENSSL_PATH)/crypto/dh/dh_check.c + $(OPENSSL_PATH)/crypto/dh/dh_depr.c + $(OPENSSL_PATH)/crypto/dh/dh_err.c + $(OPENSSL_PATH)/crypto/dh/dh_gen.c + $(OPENSSL_PATH)/crypto/dh/dh_kdf.c + $(OPENSSL_PATH)/crypto/dh/dh_key.c + $(OPENSSL_PATH)/crypto/dh/dh_lib.c + $(OPENSSL_PATH)/crypto/dh/dh_meth.c + $(OPENSSL_PATH)/crypto/dh/dh_pmeth.c + $(OPENSSL_PATH)/crypto/dh/dh_prn.c + $(OPENSSL_PATH)/crypto/dh/dh_rfc5114.c + $(OPENSSL_PATH)/crypto/dso/dso_dl.c + $(OPENSSL_PATH)/crypto/dso/dso_dlfcn.c + $(OPENSSL_PATH)/crypto/dso/dso_err.c + $(OPENSSL_PATH)/crypto/dso/dso_lib.c + $(OPENSSL_PATH)/crypto/dso/dso_openssl.c + $(OPENSSL_PATH)/crypto/dso/dso_vms.c + $(OPENSSL_PATH)/crypto/dso/dso_win32.c + $(OPENSSL_PATH)/crypto/ebcdic.c + $(OPENSSL_PATH)/crypto/err/err.c + $(OPENSSL_PATH)/crypto/err/err_all.c + $(OPENSSL_PATH)/crypto/err/err_prn.c + $(OPENSSL_PATH)/crypto/evp/bio_b64.c + $(OPENSSL_PATH)/crypto/evp/bio_enc.c + $(OPENSSL_PATH)/crypto/evp/bio_md.c + $(OPENSSL_PATH)/crypto/evp/bio_ok.c + $(OPENSSL_PATH)/crypto/evp/c_allc.c + $(OPENSSL_PATH)/crypto/evp/c_alld.c + $(OPENSSL_PATH)/crypto/evp/cmeth_lib.c + $(OPENSSL_PATH)/crypto/evp/digest.c + $(OPENSSL_PATH)/crypto/evp/e_aes.c + $(OPENSSL_PATH)/crypto/evp/e_aes_cbc_hmac_sha1.c + $(OPENSSL_PATH)/crypto/evp/e_aes_cbc_hmac_sha256.c + $(OPENSSL_PATH)/crypto/evp/e_bf.c + $(OPENSSL_PATH)/crypto/evp/e_camellia.c + $(OPENSSL_PATH)/crypto/evp/e_cast.c + $(OPENSSL_PATH)/crypto/evp/e_chacha20_poly1305.c + $(OPENSSL_PATH)/crypto/evp/e_des.c + $(OPENSSL_PATH)/crypto/evp/e_des3.c + $(OPENSSL_PATH)/crypto/evp/e_idea.c + $(OPENSSL_PATH)/crypto/evp/e_null.c + $(OPENSSL_PATH)/crypto/evp/e_old.c + $(OPENSSL_PATH)/crypto/evp/e_rc2.c + $(OPENSSL_PATH)/crypto/evp/e_rc4.c + $(OPENSSL_PATH)/crypto/evp/e_rc4_hmac_md5.c + $(OPENSSL_PATH)/crypto/evp/e_rc5.c + $(OPENSSL_PATH)/crypto/evp/e_seed.c + $(OPENSSL_PATH)/crypto/evp/e_xcbc_d.c + $(OPENSSL_PATH)/crypto/evp/encode.c + $(OPENSSL_PATH)/crypto/evp/evp_cnf.c + $(OPENSSL_PATH)/crypto/evp/evp_enc.c + $(OPENSSL_PATH)/crypto/evp/evp_err.c + $(OPENSSL_PATH)/crypto/evp/evp_key.c + $(OPENSSL_PATH)/crypto/evp/evp_lib.c + $(OPENSSL_PATH)/crypto/evp/evp_pbe.c + $(OPENSSL_PATH)/crypto/evp/evp_pkey.c + $(OPENSSL_PATH)/crypto/evp/m_md2.c + $(OPENSSL_PATH)/crypto/evp/m_md4.c + $(OPENSSL_PATH)/crypto/evp/m_md5.c + $(OPENSSL_PATH)/crypto/evp/m_md5_sha1.c + $(OPENSSL_PATH)/crypto/evp/m_mdc2.c + $(OPENSSL_PATH)/crypto/evp/m_null.c + $(OPENSSL_PATH)/crypto/evp/m_ripemd.c + $(OPENSSL_PATH)/crypto/evp/m_sha1.c + $(OPENSSL_PATH)/crypto/evp/m_sigver.c + $(OPENSSL_PATH)/crypto/evp/m_wp.c + $(OPENSSL_PATH)/crypto/evp/names.c + $(OPENSSL_PATH)/crypto/evp/p5_crpt.c + $(OPENSSL_PATH)/crypto/evp/p5_crpt2.c + $(OPENSSL_PATH)/crypto/evp/p_dec.c + $(OPENSSL_PATH)/crypto/evp/p_enc.c + $(OPENSSL_PATH)/crypto/evp/p_lib.c + $(OPENSSL_PATH)/crypto/evp/p_open.c + $(OPENSSL_PATH)/crypto/evp/p_seal.c + $(OPENSSL_PATH)/crypto/evp/p_sign.c + $(OPENSSL_PATH)/crypto/evp/p_verify.c + $(OPENSSL_PATH)/crypto/evp/pmeth_fn.c + $(OPENSSL_PATH)/crypto/evp/pmeth_gn.c + $(OPENSSL_PATH)/crypto/evp/pmeth_lib.c + $(OPENSSL_PATH)/crypto/evp/scrypt.c + $(OPENSSL_PATH)/crypto/ex_data.c + $(OPENSSL_PATH)/crypto/getenv.c + $(OPENSSL_PATH)/crypto/hmac/hm_ameth.c + $(OPENSSL_PATH)/crypto/hmac/hm_pmeth.c + $(OPENSSL_PATH)/crypto/hmac/hmac.c + $(OPENSSL_PATH)/crypto/init.c + $(OPENSSL_PATH)/crypto/kdf/hkdf.c + $(OPENSSL_PATH)/crypto/kdf/kdf_err.c + $(OPENSSL_PATH)/crypto/kdf/tls1_prf.c + $(OPENSSL_PATH)/crypto/lhash/lh_stats.c + $(OPENSSL_PATH)/crypto/lhash/lhash.c + $(OPENSSL_PATH)/crypto/md4/md4_dgst.c + $(OPENSSL_PATH)/crypto/md4/md4_one.c + $(OPENSSL_PATH)/crypto/md5/md5_dgst.c + $(OPENSSL_PATH)/crypto/md5/md5_one.c + $(OPENSSL_PATH)/crypto/mem.c + $(OPENSSL_PATH)/crypto/mem_clr.c + $(OPENSSL_PATH)/crypto/mem_dbg.c + $(OPENSSL_PATH)/crypto/mem_sec.c + $(OPENSSL_PATH)/crypto/modes/cbc128.c + $(OPENSSL_PATH)/crypto/modes/ccm128.c + $(OPENSSL_PATH)/crypto/modes/cfb128.c + $(OPENSSL_PATH)/crypto/modes/ctr128.c + $(OPENSSL_PATH)/crypto/modes/cts128.c + $(OPENSSL_PATH)/crypto/modes/gcm128.c + $(OPENSSL_PATH)/crypto/modes/ocb128.c + $(OPENSSL_PATH)/crypto/modes/ofb128.c + $(OPENSSL_PATH)/crypto/modes/wrap128.c + $(OPENSSL_PATH)/crypto/modes/xts128.c + $(OPENSSL_PATH)/crypto/o_dir.c + $(OPENSSL_PATH)/crypto/o_fips.c + $(OPENSSL_PATH)/crypto/o_fopen.c + $(OPENSSL_PATH)/crypto/o_init.c + $(OPENSSL_PATH)/crypto/o_str.c + $(OPENSSL_PATH)/crypto/o_time.c + $(OPENSSL_PATH)/crypto/objects/o_names.c + $(OPENSSL_PATH)/crypto/objects/obj_dat.c + $(OPENSSL_PATH)/crypto/objects/obj_err.c + $(OPENSSL_PATH)/crypto/objects/obj_lib.c + $(OPENSSL_PATH)/crypto/objects/obj_xref.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_asn.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_cl.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_err.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_ext.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_ht.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_lib.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_prn.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_srv.c + $(OPENSSL_PATH)/crypto/ocsp/ocsp_vfy.c + $(OPENSSL_PATH)/crypto/ocsp/v3_ocsp.c + $(OPENSSL_PATH)/crypto/pem/pem_all.c + $(OPENSSL_PATH)/crypto/pem/pem_err.c + $(OPENSSL_PATH)/crypto/pem/pem_info.c + $(OPENSSL_PATH)/crypto/pem/pem_lib.c + $(OPENSSL_PATH)/crypto/pem/pem_oth.c + $(OPENSSL_PATH)/crypto/pem/pem_pk8.c + $(OPENSSL_PATH)/crypto/pem/pem_pkey.c + $(OPENSSL_PATH)/crypto/pem/pem_sign.c + $(OPENSSL_PATH)/crypto/pem/pem_x509.c + $(OPENSSL_PATH)/crypto/pem/pem_xaux.c + $(OPENSSL_PATH)/crypto/pem/pvkfmt.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_add.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_asn.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_attr.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_crpt.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_crt.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_decr.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_init.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_key.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_kiss.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_mutl.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_npas.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_p8d.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_p8e.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_sbag.c + $(OPENSSL_PATH)/crypto/pkcs12/p12_utl.c + $(OPENSSL_PATH)/crypto/pkcs12/pk12err.c + $(OPENSSL_PATH)/crypto/pkcs7/bio_pk7.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_asn1.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_attr.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_doit.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_lib.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_mime.c + $(OPENSSL_PATH)/crypto/pkcs7/pk7_smime.c + $(OPENSSL_PATH)/crypto/pkcs7/pkcs7err.c + $(OPENSSL_PATH)/crypto/rand/md_rand.c + $(OPENSSL_PATH)/crypto/rand/rand_egd.c + $(OPENSSL_PATH)/crypto/rand/rand_err.c + $(OPENSSL_PATH)/crypto/rand/rand_lib.c + $(OPENSSL_PATH)/crypto/rand/rand_unix.c + $(OPENSSL_PATH)/crypto/rand/rand_vms.c + $(OPENSSL_PATH)/crypto/rand/rand_win.c + $(OPENSSL_PATH)/crypto/rand/randfile.c + $(OPENSSL_PATH)/crypto/rc4/rc4_enc.c + $(OPENSSL_PATH)/crypto/rc4/rc4_skey.c + $(OPENSSL_PATH)/crypto/rsa/rsa_ameth.c + $(OPENSSL_PATH)/crypto/rsa/rsa_asn1.c + $(OPENSSL_PATH)/crypto/rsa/rsa_chk.c + $(OPENSSL_PATH)/crypto/rsa/rsa_crpt.c + $(OPENSSL_PATH)/crypto/rsa/rsa_depr.c + $(OPENSSL_PATH)/crypto/rsa/rsa_err.c + $(OPENSSL_PATH)/crypto/rsa/rsa_gen.c + $(OPENSSL_PATH)/crypto/rsa/rsa_lib.c + $(OPENSSL_PATH)/crypto/rsa/rsa_meth.c + $(OPENSSL_PATH)/crypto/rsa/rsa_none.c + $(OPENSSL_PATH)/crypto/rsa/rsa_null.c + $(OPENSSL_PATH)/crypto/rsa/rsa_oaep.c + $(OPENSSL_PATH)/crypto/rsa/rsa_ossl.c + $(OPENSSL_PATH)/crypto/rsa/rsa_pk1.c + $(OPENSSL_PATH)/crypto/rsa/rsa_pmeth.c + $(OPENSSL_PATH)/crypto/rsa/rsa_prn.c + $(OPENSSL_PATH)/crypto/rsa/rsa_pss.c + $(OPENSSL_PATH)/crypto/rsa/rsa_saos.c + $(OPENSSL_PATH)/crypto/rsa/rsa_sign.c + $(OPENSSL_PATH)/crypto/rsa/rsa_ssl.c + $(OPENSSL_PATH)/crypto/rsa/rsa_x931.c + $(OPENSSL_PATH)/crypto/rsa/rsa_x931g.c + $(OPENSSL_PATH)/crypto/sha/sha1_one.c + $(OPENSSL_PATH)/crypto/sha/sha1dgst.c + $(OPENSSL_PATH)/crypto/sha/sha256.c + $(OPENSSL_PATH)/crypto/sha/sha512.c + $(OPENSSL_PATH)/crypto/stack/stack.c + $(OPENSSL_PATH)/crypto/threads_none.c + $(OPENSSL_PATH)/crypto/threads_pthread.c + $(OPENSSL_PATH)/crypto/threads_win.c + $(OPENSSL_PATH)/crypto/txt_db/txt_db.c + $(OPENSSL_PATH)/crypto/uid.c + $(OPENSSL_PATH)/crypto/x509/by_dir.c + $(OPENSSL_PATH)/crypto/x509/by_file.c + $(OPENSSL_PATH)/crypto/x509/t_crl.c + $(OPENSSL_PATH)/crypto/x509/t_req.c + $(OPENSSL_PATH)/crypto/x509/t_x509.c + $(OPENSSL_PATH)/crypto/x509/x509_att.c + $(OPENSSL_PATH)/crypto/x509/x509_cmp.c + $(OPENSSL_PATH)/crypto/x509/x509_d2.c + $(OPENSSL_PATH)/crypto/x509/x509_def.c + $(OPENSSL_PATH)/crypto/x509/x509_err.c + $(OPENSSL_PATH)/crypto/x509/x509_ext.c + $(OPENSSL_PATH)/crypto/x509/x509_lu.c + $(OPENSSL_PATH)/crypto/x509/x509_meth.c + $(OPENSSL_PATH)/crypto/x509/x509_obj.c + $(OPENSSL_PATH)/crypto/x509/x509_r2x.c + $(OPENSSL_PATH)/crypto/x509/x509_req.c + $(OPENSSL_PATH)/crypto/x509/x509_set.c + $(OPENSSL_PATH)/crypto/x509/x509_trs.c + $(OPENSSL_PATH)/crypto/x509/x509_txt.c + $(OPENSSL_PATH)/crypto/x509/x509_v3.c + $(OPENSSL_PATH)/crypto/x509/x509_vfy.c + $(OPENSSL_PATH)/crypto/x509/x509_vpm.c + $(OPENSSL_PATH)/crypto/x509/x509cset.c + $(OPENSSL_PATH)/crypto/x509/x509name.c + $(OPENSSL_PATH)/crypto/x509/x509rset.c + $(OPENSSL_PATH)/crypto/x509/x509spki.c + $(OPENSSL_PATH)/crypto/x509/x509type.c + $(OPENSSL_PATH)/crypto/x509/x_all.c + $(OPENSSL_PATH)/crypto/x509/x_attrib.c + $(OPENSSL_PATH)/crypto/x509/x_crl.c + $(OPENSSL_PATH)/crypto/x509/x_exten.c + $(OPENSSL_PATH)/crypto/x509/x_name.c + $(OPENSSL_PATH)/crypto/x509/x_pubkey.c + $(OPENSSL_PATH)/crypto/x509/x_req.c + $(OPENSSL_PATH)/crypto/x509/x_x509.c + $(OPENSSL_PATH)/crypto/x509/x_x509a.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_cache.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_data.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_lib.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_map.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_node.c + $(OPENSSL_PATH)/crypto/x509v3/pcy_tree.c + $(OPENSSL_PATH)/crypto/x509v3/v3_addr.c + $(OPENSSL_PATH)/crypto/x509v3/v3_akey.c + $(OPENSSL_PATH)/crypto/x509v3/v3_akeya.c + $(OPENSSL_PATH)/crypto/x509v3/v3_alt.c + $(OPENSSL_PATH)/crypto/x509v3/v3_asid.c + $(OPENSSL_PATH)/crypto/x509v3/v3_bcons.c + $(OPENSSL_PATH)/crypto/x509v3/v3_bitst.c + $(OPENSSL_PATH)/crypto/x509v3/v3_conf.c + $(OPENSSL_PATH)/crypto/x509v3/v3_cpols.c + $(OPENSSL_PATH)/crypto/x509v3/v3_crld.c + $(OPENSSL_PATH)/crypto/x509v3/v3_enum.c + $(OPENSSL_PATH)/crypto/x509v3/v3_extku.c + $(OPENSSL_PATH)/crypto/x509v3/v3_genn.c + $(OPENSSL_PATH)/crypto/x509v3/v3_ia5.c + $(OPENSSL_PATH)/crypto/x509v3/v3_info.c + $(OPENSSL_PATH)/crypto/x509v3/v3_int.c + $(OPENSSL_PATH)/crypto/x509v3/v3_lib.c + $(OPENSSL_PATH)/crypto/x509v3/v3_ncons.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pci.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pcia.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pcons.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pku.c + $(OPENSSL_PATH)/crypto/x509v3/v3_pmaps.c + $(OPENSSL_PATH)/crypto/x509v3/v3_prn.c + $(OPENSSL_PATH)/crypto/x509v3/v3_purp.c + $(OPENSSL_PATH)/crypto/x509v3/v3_skey.c + $(OPENSSL_PATH)/crypto/x509v3/v3_sxnet.c + $(OPENSSL_PATH)/crypto/x509v3/v3_tlsf.c + $(OPENSSL_PATH)/crypto/x509v3/v3_utl.c + $(OPENSSL_PATH)/crypto/x509v3/v3err.c +# Autogenerated files list ends here + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + DebugLib + +[LibraryClasses.ARM] + ArmSoftFloatLib + +[BuildOptions] + # + # Disables the following Visual Studio compiler warnings brought by openssl source, + # so we do not break the build with /WX option: + # C4090: 'function' : different 'const' qualifiers + # C4244: conversion from type1 to type2, possible loss of data + # C4245: conversion from type1 to type2, signed/unsigned mismatch + # C4267: conversion from size_t to type, possible loss of data + # C4306: 'identifier' : conversion from 'type1' to 'type2' of greater size + # C4389: 'operator' : signed/unsigned mismatch (xxxx) + # C4702: unreachable code + # C4706: assignment within conditional expression + # C4819: The file contains a character that cannot be represented in the current code page + # + MSFT:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4090 /wd4244 /wd4245 /wd4267 /wd4389 /wd4702 /wd4706 /wd4819 + MSFT:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4090 /wd4244 /wd4245 /wd4267 /wd4306 /wd4389 /wd4702 /wd4706 /wd4819 + + INTEL:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w + INTEL:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w + + # + # Suppress the following build warnings in openssl so we don't break the build with -Werror + # -Werror=maybe-uninitialized: there exist some other paths for which the variable is not initialized. + # -Werror=format: Check calls to printf and scanf, etc., to make sure that the arguments supplied have + # types appropriate to the format string specified. + # + GCC:*_*_IA32_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized + GCC:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-error=format -Wno-format -DNO_MSABI_VA_FUNCS + GCC:*_*_ARM_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized + GCC:*_*_AARCH64_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-format + + # suppress the following warnings in openssl so we don't break the build with warnings-as-errors: + # 1295: Deprecated declaration - give arg types + # 550: was set but never used + # 1293: assignment in condition + # 111: statement is unreachable (invariably "break;" after "return X;" in case statement) + # 68: integer conversion resulted in a change of sign ("if (Status == -1)") + # 177: was declared but never referenced + # 223: function declared implicitly + # 144: a value of type cannot be used to initialize an entity of type + # 513: a value of type cannot be assigned to an entity of type + # 188: enumerated type mixed with another type (i.e. passing an integer as an enum without a cast) + # 1296: Extended constant initialiser used + # 128: loop is not reachable - may be emitted inappropriately if code follows a conditional return + # from the function that evaluates to true at compile time + # 546: transfer of control bypasses initialization - may be emitted inappropriately if the uninitialized + # variable is never referenced after the jump + # 1: ignore "#1-D: last line of file ends without a newline" + # 3017: may be used before being set (NOTE: This was fixed in OpenSSL 1.1 HEAD with + # commit d9b8b89bec4480de3a10bdaf9425db371c19145b, and can be dropped then.) + RVCT:*_*_ARM_CC_FLAGS = $(OPENSSL_FLAGS) --library_interface=aeabi_clib99 --diag_suppress=1296,1295,550,1293,111,68,177,223,144,513,188,128,546,1,3017 -JCryptoPkg/Include + XCODE:*_*_IA32_CC_FLAGS = -mmmx -msse -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -w + XCODE:*_*_X64_CC_FLAGS = -mmmx -msse -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -w + + # + # AARCH64 uses strict alignment and avoids SIMD registers for code that may execute + # with the MMU off. This involves SEC, PEI_CORE and PEIM modules as well as BASE + # libraries, given that they may be included into such modules. + # This library, even though of the BASE type, is never used in such cases, and + # avoiding the SIMD register file (which is shared with the FPU) prevents the + # compiler from successfully building some of the OpenSSL source files that + # use floating point types, so clear the flags here. + # + GCC:*_*_AARCH64_CC_XIPFLAGS == diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.uni new file mode 100644 index 0000000..4defa21 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.uni @@ -0,0 +1,22 @@ +// /** @file +// This module provides openSSL Library implementation (libcrypto only, no libssl). +// +// This module provides OpenSSL Library implementation (libcrypto only, no libssl). +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "OpenSSL Library implementation (libcrypto only, no libssl)" + +#string STR_MODULE_DESCRIPTION #language en-US "This module provides OpenSSL Library implementation (libcrypto only, no libssl)." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/buildinf.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/buildinf.h new file mode 100644 index 0000000..80781e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/buildinf.h @@ -0,0 +1,2 @@ +#define PLATFORM "UEFI" +#define DATE "Fri Dec 22 01:23:45 PDT 2017" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/process_files.pl b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/process_files.pl new file mode 100644 index 0000000..8f10c34 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/OpensslLib/process_files.pl @@ -0,0 +1,224 @@ +#!/usr/bin/perl -w +# +# This script runs the OpenSSL Configure script, then processes the +# resulting file list into our local OpensslLib[Crypto].inf and also +# takes a copy of opensslconf.h. +# +# This only needs to be done once by a developer when updating to a +# new version of OpenSSL (or changing options, etc.). Normal users +# do not need to do this, since the results are stored in the EDK2 +# git repository for them. +# +use strict; +use Cwd; +use File::Copy; + +# +# Find the openssl directory name for use lib. We have to do this +# inside of BEGIN. The variables we create here, however, don't seem +# to be available to the main script, so we have to repeat the +# exercise. +# +my $inf_file; +my $OPENSSL_PATH; +my @inf; + +BEGIN { + $inf_file = "OpensslLib.inf"; + + # Read the contents of the inf file + open( FD, "<" . $inf_file ) || + die "Cannot open \"" . $inf_file . "\"!"; + @inf = (); + close(FD) || + die "Cannot close \"" . $inf_file . "\"!"; + + foreach (@inf) { + if (/DEFINE\s+OPENSSL_PATH\s*=\s*([a-z]+)/) { + + # We need to run Configure before we can include its result... + $OPENSSL_PATH = $1; + + my $basedir = getcwd(); + + chdir($OPENSSL_PATH) || + die "Cannot change to OpenSSL directory \"" . $OPENSSL_PATH . "\""; + + # Configure UEFI + system( + "./Configure", + "UEFI", + "no-afalgeng", + "no-asm", + "no-async", + "no-autoalginit", + "no-autoerrinit", + "no-bf", + "no-blake2", + "no-camellia", + "no-capieng", + "no-cast", + "no-chacha", + "no-cms", + "no-ct", + "no-deprecated", + "no-dgram", + "no-dsa", + "no-dynamic-engine", + "no-ec", + "no-ec2m", + "no-engine", + "no-err", + "no-filenames", + "no-gost", + "no-hw", + "no-idea", + "no-mdc2", + "no-pic", + "no-ocb", + "no-poly1305", + "no-posix-io", + "no-rc2", + "no-rfc3779", + "no-rmd160", + "no-scrypt", + "no-seed", + "no-sock", + "no-srp", + "no-ssl", + "no-stdio", + "no-threads", + "no-ts", + "no-ui", + "no-whirlpool" + ) == 0 || + die "OpenSSL Configure failed!\n"; + + # Generate opensslconf.h per config data + system( + "perl -I. -Mconfigdata util/dofile.pl " . + "include/openssl/opensslconf.h.in " . + "> include/openssl/opensslconf.h" + ) == 0 || + die "Failed to generate opensslconf.h!\n"; + + chdir($basedir) || + die "Cannot change to base directory \"" . $basedir . "\""; + + push @INC, $1; + last; + } + } +} + +# +# Retrieve file lists from OpenSSL configdata +# +use configdata qw/%unified_info/; + +my @cryptofilelist = (); +my @sslfilelist = (); +foreach my $product ((@{$unified_info{libraries}}, + @{$unified_info{engines}})) { + foreach my $o (@{$unified_info{sources}->{$product}}) { + foreach my $s (@{$unified_info{sources}->{$o}}) { + next if ($unified_info{generate}->{$s}); + next if $s =~ "crypto/bio/b_print.c"; + if ($product =~ "libssl") { + push @sslfilelist, ' $(OPENSSL_PATH)/' . $s . "\r\n"; + next; + } + push @cryptofilelist, ' $(OPENSSL_PATH)/' . $s . "\r\n"; + } + } +} + +# +# Update OpensslLib.inf with autogenerated file list +# +my @new_inf = (); +my $subbing = 0; +print "\n--> Updating OpensslLib.inf ... "; +foreach (@inf) { + if ( $_ =~ "# Autogenerated files list starts here" ) { + push @new_inf, $_, @cryptofilelist, @sslfilelist; + $subbing = 1; + next; + } + if ( $_ =~ "# Autogenerated files list ends here" ) { + push @new_inf, $_; + $subbing = 0; + next; + } + + push @new_inf, $_ + unless ($subbing); +} + +my $new_inf_file = $inf_file . ".new"; +open( FD, ">" . $new_inf_file ) || + die $new_inf_file; +print( FD @new_inf ) || + die $new_inf_file; +close(FD) || + die $new_inf_file; +rename( $new_inf_file, $inf_file ) || + die "rename $inf_file"; +print "Done!"; + +# +# Update OpensslLibCrypto.inf with auto-generated file list (no libssl) +# +$inf_file = "OpensslLibCrypto.inf"; + +# Read the contents of the inf file +@inf = (); +@new_inf = (); +open( FD, "<" . $inf_file ) || + die "Cannot open \"" . $inf_file . "\"!"; +@inf = (); +close(FD) || + die "Cannot close \"" . $inf_file . "\"!"; + +$subbing = 0; +print "\n--> Updating OpensslLibCrypto.inf ... "; +foreach (@inf) { + if ( $_ =~ "# Autogenerated files list starts here" ) { + push @new_inf, $_, @cryptofilelist; + $subbing = 1; + next; + } + if ( $_ =~ "# Autogenerated files list ends here" ) { + push @new_inf, $_; + $subbing = 0; + next; + } + + push @new_inf, $_ + unless ($subbing); +} + +$new_inf_file = $inf_file . ".new"; +open( FD, ">" . $new_inf_file ) || + die $new_inf_file; +print( FD @new_inf ) || + die $new_inf_file; +close(FD) || + die $new_inf_file; +rename( $new_inf_file, $inf_file ) || + die "rename $inf_file"; +print "Done!"; + +# +# Copy opensslconf.h generated from OpenSSL Configuration +# +print "\n--> Duplicating opensslconf.h into Include/openssl ... "; +copy($OPENSSL_PATH . "/include/openssl/opensslconf.h", + $OPENSSL_PATH . "/../../Include/openssl/") || + die "Cannot copy opensslconf.h!"; +print "Done!\n"; + +print "\nProcessing Files Done!\n"; + +exit(0); + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/InternalTlsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/InternalTlsLib.h new file mode 100644 index 0000000..ffab14f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/InternalTlsLib.h @@ -0,0 +1,47 @@ +/** @file + Internal include file for TlsLib. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __INTERNAL_TLS_LIB_H__ +#define __INTERNAL_TLS_LIB_H__ + +#undef _WIN32 +#undef _WIN64 + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + // + // Main SSL Connection which is created by a server or a client + // per established connection. + // + SSL *Ssl; + // + // Memory BIO for the TLS/SSL Reading operations. + // + BIO *InBio; + // + // Memory BIO for the TLS/SSL Writing operations. + // + BIO *OutBio; +} TLS_CONNECTION; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsConfig.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsConfig.c new file mode 100644 index 0000000..502ce82 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsConfig.c @@ -0,0 +1,1217 @@ +/** @file + SSL/TLS Configuration Library Wrapper Implementation over OpenSSL. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalTlsLib.h" + +typedef struct { + // + // IANA/IETF defined Cipher Suite ID + // + UINT16 IanaCipher; + // + // OpenSSL-used Cipher Suite String + // + CONST CHAR8 *OpensslCipher; + // + // Length of OpensslCipher + // + UINTN OpensslCipherLength; +} TLS_CIPHER_MAPPING; + +// +// Create a TLS_CIPHER_MAPPING initializer from IanaCipher and OpensslCipher so +// that OpensslCipherLength is filled in automatically. IanaCipher must be an +// integer constant expression, and OpensslCipher must be a string literal. +// +#define MAP(IanaCipher, OpensslCipher) \ + { (IanaCipher), (OpensslCipher), sizeof (OpensslCipher) - 1 } + +// +// The mapping table between IANA/IETF Cipher Suite definitions and +// OpenSSL-used Cipher Suite name. +// +// Keep the table uniquely sorted by the IanaCipher field, in increasing order. +// +STATIC CONST TLS_CIPHER_MAPPING TlsCipherMappingTable[] = { + MAP ( 0x0001, "NULL-MD5" ), /// TLS_RSA_WITH_NULL_MD5 + MAP ( 0x0002, "NULL-SHA" ), /// TLS_RSA_WITH_NULL_SHA + MAP ( 0x0004, "RC4-MD5" ), /// TLS_RSA_WITH_RC4_128_MD5 + MAP ( 0x0005, "RC4-SHA" ), /// TLS_RSA_WITH_RC4_128_SHA + MAP ( 0x000A, "DES-CBC3-SHA" ), /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1 + MAP ( 0x0016, "DHE-RSA-DES-CBC3-SHA" ), /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + MAP ( 0x002F, "AES128-SHA" ), /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2 + MAP ( 0x0030, "DH-DSS-AES128-SHA" ), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA + MAP ( 0x0031, "DH-RSA-AES128-SHA" ), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA + MAP ( 0x0033, "DHE-RSA-AES128-SHA" ), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA + MAP ( 0x0035, "AES256-SHA" ), /// TLS_RSA_WITH_AES_256_CBC_SHA + MAP ( 0x0036, "DH-DSS-AES256-SHA" ), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA + MAP ( 0x0037, "DH-RSA-AES256-SHA" ), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA + MAP ( 0x0039, "DHE-RSA-AES256-SHA" ), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA + MAP ( 0x003B, "NULL-SHA256" ), /// TLS_RSA_WITH_NULL_SHA256 + MAP ( 0x003C, "AES128-SHA256" ), /// TLS_RSA_WITH_AES_128_CBC_SHA256 + MAP ( 0x003D, "AES256-SHA256" ), /// TLS_RSA_WITH_AES_256_CBC_SHA256 + MAP ( 0x003E, "DH-DSS-AES128-SHA256" ), /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256 + MAP ( 0x003F, "DH-RSA-AES128-SHA256" ), /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256 + MAP ( 0x0067, "DHE-RSA-AES128-SHA256" ), /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + MAP ( 0x0068, "DH-DSS-AES256-SHA256" ), /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256 + MAP ( 0x0069, "DH-RSA-AES256-SHA256" ), /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256 + MAP ( 0x006B, "DHE-RSA-AES256-SHA256" ), /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +}; + +/** + Gets the OpenSSL cipher suite mapping for the supplied IANA TLS cipher suite. + + @param[in] CipherId The supplied IANA TLS cipher suite ID. + + @return The corresponding OpenSSL cipher suite mapping if found, + NULL otherwise. + +**/ +STATIC +CONST TLS_CIPHER_MAPPING * +TlsGetCipherMapping ( + IN UINT16 CipherId + ) +{ + INTN Left; + INTN Right; + INTN Middle; + + // + // Binary Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation + // + Left = 0; + Right = ARRAY_SIZE (TlsCipherMappingTable) - 1; + + while (Right >= Left) { + Middle = (Left + Right) / 2; + + if (CipherId == TlsCipherMappingTable[Middle].IanaCipher) { + // + // Translate IANA cipher suite ID to OpenSSL name. + // + return &TlsCipherMappingTable[Middle]; + } + + if (CipherId < TlsCipherMappingTable[Middle].IanaCipher) { + Right = Middle - 1; + } else { + Left = Middle + 1; + } + } + + // + // No Cipher Mapping found, return NULL. + // + return NULL; +} + +/** + Set a new TLS/SSL method for a particular TLS object. + + This function sets a new TLS/SSL method for a particular TLS object. + + @param[in] Tls Pointer to a TLS object. + @param[in] MajorVer Major Version of TLS/SSL Protocol. + @param[in] MinorVer Minor Version of TLS/SSL Protocol. + + @retval EFI_SUCCESS The TLS/SSL method was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported TLS/SSL method. + +**/ +EFI_STATUS +EFIAPI +TlsSetVersion ( + IN VOID *Tls, + IN UINT8 MajorVer, + IN UINT8 MinorVer + ) +{ + TLS_CONNECTION *TlsConn; + UINT16 ProtoVersion; + + TlsConn = (TLS_CONNECTION *)Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL) { + return EFI_INVALID_PARAMETER; + } + + ProtoVersion = (MajorVer << 8) | MinorVer; + + // + // Bound TLS method to the particular specified version. + // + switch (ProtoVersion) { + case TLS1_VERSION: + // + // TLS 1.0 + // + SSL_set_min_proto_version (TlsConn->Ssl, TLS1_VERSION); + SSL_set_max_proto_version (TlsConn->Ssl, TLS1_VERSION); + break; + case TLS1_1_VERSION: + // + // TLS 1.1 + // + SSL_set_min_proto_version (TlsConn->Ssl, TLS1_1_VERSION); + SSL_set_max_proto_version (TlsConn->Ssl, TLS1_1_VERSION); + break; + case TLS1_2_VERSION: + // + // TLS 1.2 + // + SSL_set_min_proto_version (TlsConn->Ssl, TLS1_2_VERSION); + SSL_set_max_proto_version (TlsConn->Ssl, TLS1_2_VERSION); + break; + default: + // + // Unsupported Protocol Version + // + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS;; +} + +/** + Set TLS object to work in client or server mode. + + This function prepares a TLS object to work in client or server mode. + + @param[in] Tls Pointer to a TLS object. + @param[in] IsServer Work in server mode. + + @retval EFI_SUCCESS The TLS/SSL work mode was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported TLS/SSL work mode. + +**/ +EFI_STATUS +EFIAPI +TlsSetConnectionEnd ( + IN VOID *Tls, + IN BOOLEAN IsServer + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!IsServer) { + // + // Set TLS to work in Client mode. + // + SSL_set_connect_state (TlsConn->Ssl); + } else { + // + // Set TLS to work in Server mode. + // It is unsupported for UEFI version currently. + // + //SSL_set_accept_state (TlsConn->Ssl); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Set the ciphers list to be used by the TLS object. + + This function sets the ciphers for use by a specified TLS object. + + @param[in] Tls Pointer to a TLS object. + @param[in] CipherId Array of UINT16 cipher identifiers. Each UINT16 + cipher identifier comes from the TLS Cipher Suite + Registry of the IANA, interpreting Byte1 and Byte2 + in network (big endian) byte order. + @param[in] CipherNum The number of cipher in the list. + + @retval EFI_SUCCESS The ciphers list was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED No supported TLS cipher was found in CipherId. + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. + +**/ +EFI_STATUS +EFIAPI +TlsSetCipherList ( + IN VOID *Tls, + IN UINT16 *CipherId, + IN UINTN CipherNum + ) +{ + TLS_CONNECTION *TlsConn; + EFI_STATUS Status; + CONST TLS_CIPHER_MAPPING **MappedCipher; + UINTN MappedCipherBytes; + UINTN MappedCipherCount; + UINTN CipherStringSize; + UINTN Index; + CONST TLS_CIPHER_MAPPING *Mapping; + CHAR8 *CipherString; + CHAR8 *CipherStringPosition; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Allocate the MappedCipher array for recording the mappings that we find + // for the input IANA identifiers in CipherId. + // + Status = SafeUintnMult (CipherNum, sizeof (*MappedCipher), + &MappedCipherBytes); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + MappedCipher = AllocatePool (MappedCipherBytes); + if (MappedCipher == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Map the cipher IDs, and count the number of bytes for the full + // CipherString. + // + MappedCipherCount = 0; + CipherStringSize = 0; + for (Index = 0; Index < CipherNum; Index++) { + // + // Look up the IANA-to-OpenSSL mapping. + // + Mapping = TlsGetCipherMapping (CipherId[Index]); + if (Mapping == NULL) { + DEBUG ((DEBUG_VERBOSE, "%a:%a: skipping CipherId=0x%04x\n", + gEfiCallerBaseName, __FUNCTION__, CipherId[Index])); + // + // Skipping the cipher is valid because CipherId is an ordered + // preference list of ciphers, thus we can filter it as long as we + // don't change the relative order of elements on it. + // + continue; + } + // + // Accumulate Mapping->OpensslCipherLength into CipherStringSize. If this + // is not the first successful mapping, account for a colon (":") prefix + // too. + // + if (MappedCipherCount > 0) { + Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeMappedCipher; + } + } + Status = SafeUintnAdd (CipherStringSize, Mapping->OpensslCipherLength, + &CipherStringSize); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeMappedCipher; + } + // + // Record the mapping. + // + MappedCipher[MappedCipherCount++] = Mapping; + } + + // + // Verify that at least one IANA cipher ID could be mapped; account for the + // terminating NUL character in CipherStringSize; allocate CipherString. + // + if (MappedCipherCount == 0) { + DEBUG ((DEBUG_ERROR, "%a:%a: no CipherId could be mapped\n", + gEfiCallerBaseName, __FUNCTION__)); + Status = EFI_UNSUPPORTED; + goto FreeMappedCipher; + } + Status = SafeUintnAdd (CipherStringSize, 1, &CipherStringSize); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeMappedCipher; + } + CipherString = AllocatePool (CipherStringSize); + if (CipherString == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeMappedCipher; + } + + // + // Go over the collected mappings and populate CipherString. + // + CipherStringPosition = CipherString; + for (Index = 0; Index < MappedCipherCount; Index++) { + Mapping = MappedCipher[Index]; + // + // Append the colon (":") prefix except for the first mapping, then append + // Mapping->OpensslCipher. + // + if (Index > 0) { + *(CipherStringPosition++) = ':'; + } + CopyMem (CipherStringPosition, Mapping->OpensslCipher, + Mapping->OpensslCipherLength); + CipherStringPosition += Mapping->OpensslCipherLength; + } + + // + // NUL-terminate CipherString. + // + *(CipherStringPosition++) = '\0'; + ASSERT (CipherStringPosition == CipherString + CipherStringSize); + + // + // Log CipherString for debugging. CipherString can be very long if the + // caller provided a large CipherId array, so log CipherString in segments of + // 79 non-newline characters. (MAX_DEBUG_MESSAGE_LENGTH is usually 0x100 in + // DebugLib instances.) + // + DEBUG_CODE ( + UINTN FullLength; + UINTN SegmentLength; + + FullLength = CipherStringSize - 1; + DEBUG ((DEBUG_VERBOSE, "%a:%a: CipherString={\n", gEfiCallerBaseName, + __FUNCTION__)); + for (CipherStringPosition = CipherString; + CipherStringPosition < CipherString + FullLength; + CipherStringPosition += SegmentLength) { + SegmentLength = FullLength - (CipherStringPosition - CipherString); + if (SegmentLength > 79) { + SegmentLength = 79; + } + DEBUG ((DEBUG_VERBOSE, "%.*a\n", SegmentLength, CipherStringPosition)); + } + DEBUG ((DEBUG_VERBOSE, "}\n")); + // + // Restore the pre-debug value of CipherStringPosition by skipping over the + // trailing NUL. + // + CipherStringPosition++; + ASSERT (CipherStringPosition == CipherString + CipherStringSize); + ); + + // + // Sets the ciphers for use by the Tls object. + // + if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) { + Status = EFI_UNSUPPORTED; + goto FreeCipherString; + } + + Status = EFI_SUCCESS; + +FreeCipherString: + FreePool (CipherString); + +FreeMappedCipher: + FreePool (MappedCipher); + + return Status; +} + +/** + Set the compression method for TLS/SSL operations. + + This function handles TLS/SSL integrated compression methods. + + @param[in] CompMethod The compression method ID. + + @retval EFI_SUCCESS The compression method for the communication was + set successfully. + @retval EFI_UNSUPPORTED Unsupported compression method. + +**/ +EFI_STATUS +EFIAPI +TlsSetCompressionMethod ( + IN UINT8 CompMethod + ) +{ + COMP_METHOD *Cm; + INTN Ret; + + Cm = NULL; + Ret = 0; + + if (CompMethod == 0) { + // + // TLS defines one standard compression method, CompressionMethod.null (0), + // which specifies that data exchanged via the record protocol will not be compressed. + // So, return EFI_SUCCESS directly (RFC 3749). + // + return EFI_SUCCESS; + } else if (CompMethod == 1) { + Cm = COMP_zlib(); + } else { + return EFI_UNSUPPORTED; + } + + // + // Adds the compression method to the list of available + // compression methods. + // + Ret = SSL_COMP_add_compression_method (CompMethod, Cm); + if (Ret != 0) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Set peer certificate verification mode for the TLS connection. + + This function sets the verification mode flags for the TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in] VerifyMode A set of logically or'ed verification mode flags. + +**/ +VOID +EFIAPI +TlsSetVerify ( + IN VOID *Tls, + IN UINT32 VerifyMode + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL) { + return; + } + + // + // Set peer certificate verification parameters with NULL callback. + // + SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL); +} + +/** + Sets a TLS/SSL session ID to be used during TLS/SSL connect. + + This function sets a session ID to be used when the TLS/SSL connection is + to be established. + + @param[in] Tls Pointer to the TLS object. + @param[in] SessionId Session ID data used for session resumption. + @param[in] SessionIdLen Length of Session ID in bytes. + + @retval EFI_SUCCESS Session ID was set successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED No available session for ID setting. + +**/ +EFI_STATUS +EFIAPI +TlsSetSessionId ( + IN VOID *Tls, + IN UINT8 *SessionId, + IN UINT16 SessionIdLen + ) +{ + TLS_CONNECTION *TlsConn; + SSL_SESSION *Session; + + TlsConn = (TLS_CONNECTION *) Tls; + Session = NULL; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL) { + return EFI_INVALID_PARAMETER; + } + + Session = SSL_get_session (TlsConn->Ssl); + if (Session == NULL) { + return EFI_UNSUPPORTED; + } + + SSL_SESSION_set1_id (Session, (const unsigned char *)SessionId, SessionIdLen); + + return EFI_SUCCESS; +} + +/** + Adds the CA to the cert store when requesting Server or Client authentication. + + This function adds the CA certificate to the list of CAs when requesting + Server or Client authentication for the chosen TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in] Data Pointer to the data buffer of a DER-encoded binary + X.509 certificate or PEM-encoded X.509 certificate. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated. + @retval EFI_ABORTED Invalid X.509 certificate. + +**/ +EFI_STATUS +EFIAPI +TlsSetCaCertificate ( + IN VOID *Tls, + IN VOID *Data, + IN UINTN DataSize + ) +{ + BIO *BioCert; + X509 *Cert; + X509_STORE *X509Store; + EFI_STATUS Status; + TLS_CONNECTION *TlsConn; + SSL_CTX *SslCtx; + INTN Ret; + UINTN ErrorCode; + + BioCert = NULL; + Cert = NULL; + X509Store = NULL; + Status = EFI_SUCCESS; + TlsConn = (TLS_CONNECTION *) Tls; + Ret = 0; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate. + // Determine whether certificate is from DER encoding, if so, translate it to X509 structure. + // + Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize); + if (Cert == NULL) { + // + // Certificate is from PEM encoding. + // + BioCert = BIO_new (BIO_s_mem ()); + if (BioCert == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL); + if (Cert == NULL) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + } + + SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl); + X509Store = SSL_CTX_get_cert_store (SslCtx); + if (X509Store == NULL) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + // + // Add certificate to X509 store + // + Ret = X509_STORE_add_cert (X509Store, Cert); + if (Ret != 1) { + ErrorCode = ERR_peek_last_error (); + // + // Ignore "already in table" errors + // + if (!(ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT && + ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + } + +ON_EXIT: + if (BioCert != NULL) { + BIO_free (BioCert); + } + + if (Cert != NULL) { + X509_free (Cert); + } + + return Status; +} + +/** + Loads the local public certificate into the specified TLS object. + + This function loads the X.509 certificate into the specified TLS object + for TLS negotiation. + + @param[in] Tls Pointer to the TLS object. + @param[in] Data Pointer to the data buffer of a DER-encoded binary + X.509 certificate or PEM-encoded X.509 certificate. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated. + @retval EFI_ABORTED Invalid X.509 certificate. + +**/ +EFI_STATUS +EFIAPI +TlsSetHostPublicCert ( + IN VOID *Tls, + IN VOID *Data, + IN UINTN DataSize + ) +{ + BIO *BioCert; + X509 *Cert; + EFI_STATUS Status; + TLS_CONNECTION *TlsConn; + + BioCert = NULL; + Cert = NULL; + Status = EFI_SUCCESS; + TlsConn = (TLS_CONNECTION *) Tls; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate. + // Determine whether certificate is from DER encoding, if so, translate it to X509 structure. + // + Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize); + if (Cert == NULL) { + // + // Certificate is from PEM encoding. + // + BioCert = BIO_new (BIO_s_mem ()); + if (BioCert == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL); + if (Cert == NULL) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + } + + if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + +ON_EXIT: + if (BioCert != NULL) { + BIO_free (BioCert); + } + + if (Cert != NULL) { + X509_free (Cert); + } + + return Status; +} + +/** + Adds the local private key to the specified TLS object. + + This function adds the local private key (PEM-encoded RSA or PKCS#8 private + key) into the specified TLS object for TLS negotiation. + + @param[in] Tls Pointer to the TLS object. + @param[in] Data Pointer to the data buffer of a PEM-encoded RSA + or PKCS#8 private key. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_ABORTED Invalid private key data. + +**/ +EFI_STATUS +EFIAPI +TlsSetHostPrivateKey ( + IN VOID *Tls, + IN VOID *Data, + IN UINTN DataSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Adds the CA-supplied certificate revocation list for certificate validation. + + This function adds the CA-supplied certificate revocation list data for + certificate validity checking. + + @param[in] Data Pointer to the data buffer of a DER-encoded CRL data. + @param[in] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_ABORTED Invalid CRL data. + +**/ +EFI_STATUS +EFIAPI +TlsSetCertRevocationList ( + IN VOID *Data, + IN UINTN DataSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Gets the protocol version used by the specified TLS connection. + + This function returns the protocol version used by the specified TLS + connection. + + If Tls is NULL, then ASSERT(). + + @param[in] Tls Pointer to the TLS object. + + @return The protocol version of the specified TLS connection. + +**/ +UINT16 +EFIAPI +TlsGetVersion ( + IN VOID *Tls + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + + ASSERT (TlsConn != NULL); + + return (UINT16)(SSL_version (TlsConn->Ssl)); +} + +/** + Gets the connection end of the specified TLS connection. + + This function returns the connection end (as client or as server) used by + the specified TLS connection. + + If Tls is NULL, then ASSERT(). + + @param[in] Tls Pointer to the TLS object. + + @return The connection end used by the specified TLS connection. + +**/ +UINT8 +EFIAPI +TlsGetConnectionEnd ( + IN VOID *Tls + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + + ASSERT (TlsConn != NULL); + + return (UINT8)SSL_is_server (TlsConn->Ssl); +} + +/** + Gets the cipher suite used by the specified TLS connection. + + This function returns current cipher suite used by the specified + TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] CipherId The cipher suite used by the TLS object. + + @retval EFI_SUCCESS The cipher suite was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Unsupported cipher suite. + +**/ +EFI_STATUS +EFIAPI +TlsGetCurrentCipher ( + IN VOID *Tls, + IN OUT UINT16 *CipherId + ) +{ + TLS_CONNECTION *TlsConn; + CONST SSL_CIPHER *Cipher; + + TlsConn = (TLS_CONNECTION *) Tls; + Cipher = NULL; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) { + return EFI_INVALID_PARAMETER; + } + + Cipher = SSL_get_current_cipher (TlsConn->Ssl); + if (Cipher == NULL) { + return EFI_UNSUPPORTED; + } + + *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF; + + return EFI_SUCCESS; +} + +/** + Gets the compression methods used by the specified TLS connection. + + This function returns current integrated compression methods used by + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] CompressionId The current compression method used by + the TLS object. + + @retval EFI_SUCCESS The compression method was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_ABORTED Invalid Compression method. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +EFI_STATUS +EFIAPI +TlsGetCurrentCompressionId ( + IN VOID *Tls, + IN OUT UINT8 *CompressionId + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Gets the verification mode currently set in the TLS connection. + + This function returns the peer verification mode currently set in the + specified TLS connection. + + If Tls is NULL, then ASSERT(). + + @param[in] Tls Pointer to the TLS object. + + @return The verification mode set in the specified TLS connection. + +**/ +UINT32 +EFIAPI +TlsGetVerify ( + IN VOID *Tls + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + + ASSERT (TlsConn != NULL); + + return SSL_get_verify_mode (TlsConn->Ssl); +} + +/** + Gets the session ID used by the specified TLS connection. + + This function returns the TLS/SSL session ID currently used by the + specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] SessionId Buffer to contain the returned session ID. + @param[in,out] SessionIdLen The length of Session ID in bytes. + + @retval EFI_SUCCESS The Session ID was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Invalid TLS/SSL session. + +**/ +EFI_STATUS +EFIAPI +TlsGetSessionId ( + IN VOID *Tls, + IN OUT UINT8 *SessionId, + IN OUT UINT16 *SessionIdLen + ) +{ + TLS_CONNECTION *TlsConn; + SSL_SESSION *Session; + CONST UINT8 *SslSessionId; + + TlsConn = (TLS_CONNECTION *) Tls; + Session = NULL; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL || SessionIdLen == NULL) { + return EFI_INVALID_PARAMETER; + } + + Session = SSL_get_session (TlsConn->Ssl); + if (Session == NULL) { + return EFI_UNSUPPORTED; + } + + SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen); + CopyMem (SessionId, SslSessionId, *SessionIdLen); + + return EFI_SUCCESS; +} + +/** + Gets the client random data used in the specified TLS connection. + + This function returns the TLS/SSL client random data currently used in + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] ClientRandom Buffer to contain the returned client + random data (32 bytes). + +**/ +VOID +EFIAPI +TlsGetClientRandom ( + IN VOID *Tls, + IN OUT UINT8 *ClientRandom + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || ClientRandom == NULL) { + return; + } + + SSL_get_client_random (TlsConn->Ssl, ClientRandom, SSL3_RANDOM_SIZE); +} + +/** + Gets the server random data used in the specified TLS connection. + + This function returns the TLS/SSL server random data currently used in + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] ServerRandom Buffer to contain the returned server + random data (32 bytes). + +**/ +VOID +EFIAPI +TlsGetServerRandom ( + IN VOID *Tls, + IN OUT UINT8 *ServerRandom + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || ServerRandom == NULL) { + return; + } + + SSL_get_server_random (TlsConn->Ssl, ServerRandom, SSL3_RANDOM_SIZE); +} + +/** + Gets the master key data used in the specified TLS connection. + + This function returns the TLS/SSL master key material currently used in + the specified TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] KeyMaterial Buffer to contain the returned key material. + + @retval EFI_SUCCESS Key material was returned successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_UNSUPPORTED Invalid TLS/SSL session. + +**/ +EFI_STATUS +EFIAPI +TlsGetKeyMaterial ( + IN VOID *Tls, + IN OUT UINT8 *KeyMaterial + ) +{ + TLS_CONNECTION *TlsConn; + SSL_SESSION *Session; + + TlsConn = (TLS_CONNECTION *) Tls; + Session = NULL; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || KeyMaterial == NULL) { + return EFI_INVALID_PARAMETER; + } + + Session = SSL_get_session (TlsConn->Ssl); + + if (Session == NULL) { + return EFI_UNSUPPORTED; + } + + SSL_SESSION_get_master_key (Session, KeyMaterial, SSL3_MASTER_SECRET_SIZE); + + return EFI_SUCCESS; +} + +/** + Gets the CA Certificate from the cert store. + + This function returns the CA certificate for the chosen + TLS connection. + + @param[in] Tls Pointer to the TLS object. + @param[out] Data Pointer to the data buffer to receive the CA + certificate data sent to the client. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetCaCertificate ( + IN VOID *Tls, + OUT VOID *Data, + IN OUT UINTN *DataSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Gets the local public Certificate set in the specified TLS object. + + This function returns the local public certificate which was currently set + in the specified TLS object. + + @param[in] Tls Pointer to the TLS object. + @param[out] Data Pointer to the data buffer to receive the local + public certificate. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_NOT_FOUND The certificate is not found. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetHostPublicCert ( + IN VOID *Tls, + OUT VOID *Data, + IN OUT UINTN *DataSize + ) +{ + X509 *Cert; + TLS_CONNECTION *TlsConn; + + Cert = NULL; + TlsConn = (TLS_CONNECTION *) Tls; + + if (TlsConn == NULL || TlsConn->Ssl == NULL || DataSize == NULL || (*DataSize != 0 && Data == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Cert = SSL_get_certificate(TlsConn->Ssl); + if (Cert == NULL) { + return EFI_NOT_FOUND; + } + + // + // Only DER encoding is supported currently. + // + if (*DataSize < (UINTN) i2d_X509 (Cert, NULL)) { + *DataSize = (UINTN) i2d_X509 (Cert, NULL); + return EFI_BUFFER_TOO_SMALL; + } + + *DataSize = (UINTN) i2d_X509 (Cert, (unsigned char **) &Data); + + return EFI_SUCCESS; +} + +/** + Gets the local private key set in the specified TLS object. + + This function returns the local private key data which was currently set + in the specified TLS object. + + @param[in] Tls Pointer to the TLS object. + @param[out] Data Pointer to the data buffer to receive the local + private key data. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetHostPrivateKey ( + IN VOID *Tls, + OUT VOID *Data, + IN OUT UINTN *DataSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Gets the CA-supplied certificate revocation list data set in the specified + TLS object. + + This function returns the CA-supplied certificate revocation list data which + was currently set in the specified TLS object. + + @param[out] Data Pointer to the data buffer to receive the CRL data. + @param[in,out] DataSize The size of data buffer in bytes. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_BUFFER_TOO_SMALL The Data is too small to hold the data. + +**/ +EFI_STATUS +EFIAPI +TlsGetCertRevocationList ( + OUT VOID *Data, + IN OUT UINTN *DataSize + ) +{ + return EFI_UNSUPPORTED; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsInit.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsInit.c new file mode 100644 index 0000000..d9fe744 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsInit.c @@ -0,0 +1,269 @@ +/** @file + SSL/TLS Initialization Library Wrapper Implementation over OpenSSL. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalTlsLib.h" + +/** + Initializes the OpenSSL library. + + This function registers ciphers and digests used directly and indirectly + by SSL/TLS, and initializes the readable error messages. + This function must be called before any other action takes places. + + @retval TRUE The OpenSSL library has been initialized. + @retval FALSE Failed to initialize the OpenSSL library. + +**/ +BOOLEAN +EFIAPI +TlsInitialize ( + VOID + ) +{ + INTN Ret; + + // + // Performs initialization of crypto and ssl library, and loads required + // algorithms. + // + Ret = OPENSSL_init_ssl ( + OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, + NULL + ); + if (Ret != 1) { + return FALSE; + } + + // + // Initialize the pseudorandom number generator. + // + return RandomSeed (NULL, 0); +} + +/** + Free an allocated SSL_CTX object. + + @param[in] TlsCtx Pointer to the SSL_CTX object to be released. + +**/ +VOID +EFIAPI +TlsCtxFree ( + IN VOID *TlsCtx + ) +{ + if (TlsCtx == NULL) { + return; + } + + if (TlsCtx != NULL) { + SSL_CTX_free ((SSL_CTX *) (TlsCtx)); + } +} + +/** + Creates a new SSL_CTX object as framework to establish TLS/SSL enabled + connections. + + @param[in] MajorVer Major Version of TLS/SSL Protocol. + @param[in] MinorVer Minor Version of TLS/SSL Protocol. + + @return Pointer to an allocated SSL_CTX object. + If the creation failed, TlsCtxNew() returns NULL. + +**/ +VOID * +EFIAPI +TlsCtxNew ( + IN UINT8 MajorVer, + IN UINT8 MinorVer + ) +{ + SSL_CTX *TlsCtx; + UINT16 ProtoVersion; + + ProtoVersion = (MajorVer << 8) | MinorVer; + + TlsCtx = SSL_CTX_new (SSLv23_client_method ()); + if (TlsCtx == NULL) { + return NULL; + } + + // + // Ensure SSLv3 is disabled + // + SSL_CTX_set_options (TlsCtx, SSL_OP_NO_SSLv3); + + // + // Treat as minimum accepted versions by setting the minimal bound. + // Client can use higher TLS version if server supports it + // + SSL_CTX_set_min_proto_version (TlsCtx, ProtoVersion); + + return (VOID *) TlsCtx; +} + +/** + Free an allocated TLS object. + + This function removes the TLS object pointed to by Tls and frees up the + allocated memory. If Tls is NULL, nothing is done. + + @param[in] Tls Pointer to the TLS object to be freed. + +**/ +VOID +EFIAPI +TlsFree ( + IN VOID *Tls + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL) { + return; + } + + // + // Free the internal TLS and related BIO objects. + // + if (TlsConn->Ssl != NULL) { + SSL_free (TlsConn->Ssl); + } + + OPENSSL_free (Tls); +} + +/** + Create a new TLS object for a connection. + + This function creates a new TLS object for a connection. The new object + inherits the setting of the underlying context TlsCtx: connection method, + options, verification setting. + + @param[in] TlsCtx Pointer to the SSL_CTX object. + + @return Pointer to an allocated SSL object. + If the creation failed, TlsNew() returns NULL. + +**/ +VOID * +EFIAPI +TlsNew ( + IN VOID *TlsCtx + ) +{ + TLS_CONNECTION *TlsConn; + SSL_CTX *SslCtx; + X509_STORE *X509Store; + + TlsConn = NULL; + + // + // Allocate one new TLS_CONNECTION object + // + TlsConn = (TLS_CONNECTION *) OPENSSL_malloc (sizeof (TLS_CONNECTION)); + if (TlsConn == NULL) { + return NULL; + } + + TlsConn->Ssl = NULL; + + // + // Create a new SSL Object + // + TlsConn->Ssl = SSL_new ((SSL_CTX *) TlsCtx); + if (TlsConn->Ssl == NULL) { + TlsFree ((VOID *) TlsConn); + return NULL; + } + + // + // This retains compatibility with previous version of OpenSSL. + // + SSL_set_security_level (TlsConn->Ssl, 0); + + // + // Initialize the created SSL Object + // + SSL_set_info_callback (TlsConn->Ssl, NULL); + + TlsConn->InBio = NULL; + + // + // Set up Reading BIO for TLS connection + // + TlsConn->InBio = BIO_new (BIO_s_mem ()); + if (TlsConn->InBio == NULL) { + TlsFree ((VOID *) TlsConn); + return NULL; + } + + // + // Sets the behaviour of memory BIO when it is empty. It will set the + // read retry flag. + // + BIO_set_mem_eof_return (TlsConn->InBio, -1); + + TlsConn->OutBio = NULL; + + // + // Set up Writing BIO for TLS connection + // + TlsConn->OutBio = BIO_new (BIO_s_mem ()); + if (TlsConn->OutBio == NULL) { + TlsFree ((VOID *) TlsConn); + return NULL; + } + + // + // Sets the behaviour of memory BIO when it is empty. It will set the + // write retry flag. + // + BIO_set_mem_eof_return (TlsConn->OutBio, -1); + + ASSERT (TlsConn->Ssl != NULL && TlsConn->InBio != NULL && TlsConn->OutBio != NULL); + + // + // Connects the InBio and OutBio for the read and write operations. + // + SSL_set_bio (TlsConn->Ssl, TlsConn->InBio, TlsConn->OutBio); + + // + // Create new X509 store if needed + // + SslCtx = SSL_get_SSL_CTX (TlsConn->Ssl); + X509Store = SSL_CTX_get_cert_store (SslCtx); + if (X509Store == NULL) { + X509Store = X509_STORE_new (); + if (X509Store == NULL) { + TlsFree ((VOID *) TlsConn); + return NULL; + } + SSL_CTX_set1_verify_cert_store (SslCtx, X509Store); + X509_STORE_free (X509Store); + } + + // + // Set X509_STORE flags used in certificate validation + // + X509_STORE_set_flags ( + X509Store, + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME + ); + return (VOID *) TlsConn; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.inf new file mode 100644 index 0000000..4bc20ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.inf @@ -0,0 +1,56 @@ +## @file +# SSL/TLS Wrapper Library Instance based on OpenSSL. +# +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TlsLib + MODULE_UNI_FILE = TlsLib.uni + FILE_GUID = CC729DC5-4E21-0B36-1A00-3A8E1B86A155 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TlsLib|DXE_DRIVER DXE_CORE UEFI_APPLICATION UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + InternalTlsLib.h + TlsInit.c + TlsConfig.c + TlsProcess.c + +[Packages] + MdePkg/MdePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseCryptLib + BaseMemoryLib + DebugLib + IntrinsicLib + MemoryAllocationLib + OpensslLib + SafeIntLib + +[BuildOptions] + # + # suppress the following warnings so we do not break the build with warnings-as-errors: + # C4090: 'function' : different 'const' qualifiers + # + MSFT:*_*_*_CC_FLAGS = /wd4090 + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.uni new file mode 100644 index 0000000..b418cde --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsLib.uni @@ -0,0 +1,19 @@ +// /** @file +// SSL/TLS Wrapper Library Instance based on OpenSSL. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SSL/TLS Wrapper Library Instance" + +#string STR_MODULE_DESCRIPTION #language en-US "This module provides SSL/TLS Wrapper Library Instance." diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsProcess.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsProcess.c new file mode 100644 index 0000000..3a79fe4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/CryptoPkg/Library/TlsLib/TlsProcess.c @@ -0,0 +1,463 @@ +/** @file + SSL/TLS Process Library Wrapper Implementation over OpenSSL. + The process includes the TLS handshake and packet I/O. + +Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalTlsLib.h" + +#define MAX_BUFFER_SIZE 32768 + +/** + Checks if the TLS handshake was done. + + This function will check if the specified TLS handshake was done. + + @param[in] Tls Pointer to the TLS object for handshake state checking. + + @retval TRUE The TLS handshake was done. + @retval FALSE The TLS handshake was not done. + +**/ +BOOLEAN +EFIAPI +TlsInHandshake ( + IN VOID *Tls + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL) { + return FALSE; + } + + // + // Return the status which indicates if the TLS handshake was done. + // + return !SSL_is_init_finished (TlsConn->Ssl); +} + +/** + Perform a TLS/SSL handshake. + + This function will perform a TLS/SSL handshake. + + @param[in] Tls Pointer to the TLS object for handshake operation. + @param[in] BufferIn Pointer to the most recently received TLS Handshake packet. + @param[in] BufferInSize Packet size in bytes for the most recently received TLS + Handshake packet. + @param[out] BufferOut Pointer to the buffer to hold the built packet. + @param[in, out] BufferOutSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Tls is NULL. + BufferIn is NULL but BufferInSize is NOT 0. + BufferInSize is 0 but BufferIn is NOT NULL. + BufferOutSize is NULL. + BufferOut is NULL if *BufferOutSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferOutSize is too small to hold the response packet. + @retval EFI_ABORTED Something wrong during handshake. + +**/ +EFI_STATUS +EFIAPI +TlsDoHandshake ( + IN VOID *Tls, + IN UINT8 *BufferIn, OPTIONAL + IN UINTN BufferInSize, OPTIONAL + OUT UINT8 *BufferOut, OPTIONAL + IN OUT UINTN *BufferOutSize + ) +{ + TLS_CONNECTION *TlsConn; + UINTN PendingBufferSize; + INTN Ret; + UINTN ErrorCode; + + TlsConn = (TLS_CONNECTION *) Tls; + PendingBufferSize = 0; + Ret = 1; + + if (TlsConn == NULL || \ + TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \ + BufferOutSize == NULL || \ + (BufferIn == NULL && BufferInSize != 0) || \ + (BufferIn != NULL && BufferInSize == 0) || \ + (BufferOut == NULL && *BufferOutSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + if(BufferIn == NULL && BufferInSize == 0) { + // + // If RequestBuffer is NULL and RequestSize is 0, and TLS session + // status is EfiTlsSessionNotStarted, the TLS session will be initiated + // and the response packet needs to be ClientHello. + // + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + if (PendingBufferSize == 0) { + SSL_set_connect_state (TlsConn->Ssl); + Ret = SSL_do_handshake (TlsConn->Ssl); + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + } + } else { + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + if (PendingBufferSize == 0) { + BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize); + Ret = SSL_do_handshake (TlsConn->Ssl); + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + } + } + + if (Ret < 1) { + Ret = SSL_get_error (TlsConn->Ssl, (int) Ret); + if (Ret == SSL_ERROR_SSL || + Ret == SSL_ERROR_SYSCALL || + Ret == SSL_ERROR_ZERO_RETURN) { + DEBUG (( + DEBUG_ERROR, + "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n", + __FUNCTION__, + SSL_get_state (TlsConn->Ssl), + Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : "ZERO_RETURN" + )); + DEBUG_CODE_BEGIN (); + while (TRUE) { + ErrorCode = ERR_get_error (); + if (ErrorCode == 0) { + break; + } + DEBUG (( + DEBUG_ERROR, + "%a ERROR 0x%x=L%x:F%x:R%x\n", + __FUNCTION__, + ErrorCode, + ERR_GET_LIB (ErrorCode), + ERR_GET_FUNC (ErrorCode), + ERR_GET_REASON (ErrorCode) + )); + } + DEBUG_CODE_END (); + return EFI_ABORTED; + } + } + + if (PendingBufferSize > *BufferOutSize) { + *BufferOutSize = PendingBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + if (PendingBufferSize > 0) { + *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize); + } else { + *BufferOutSize = 0; + } + + return EFI_SUCCESS; +} + +/** + Handle Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero, + TLS session has errors and the response packet needs to be Alert message based on error type. + + @param[in] Tls Pointer to the TLS object for state checking. + @param[in] BufferIn Pointer to the most recently received TLS Alert packet. + @param[in] BufferInSize Packet size in bytes for the most recently received TLS + Alert packet. + @param[out] BufferOut Pointer to the buffer to hold the built packet. + @param[in, out] BufferOutSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Tls is NULL. + BufferIn is NULL but BufferInSize is NOT 0. + BufferInSize is 0 but BufferIn is NOT NULL. + BufferOutSize is NULL. + BufferOut is NULL if *BufferOutSize is not zero. + @retval EFI_ABORTED An error occurred. + @retval EFI_BUFFER_TOO_SMALL BufferOutSize is too small to hold the response packet. + +**/ +EFI_STATUS +EFIAPI +TlsHandleAlert ( + IN VOID *Tls, + IN UINT8 *BufferIn, OPTIONAL + IN UINTN BufferInSize, OPTIONAL + OUT UINT8 *BufferOut, OPTIONAL + IN OUT UINTN *BufferOutSize + ) +{ + TLS_CONNECTION *TlsConn; + UINTN PendingBufferSize; + UINT8 *TempBuffer; + INTN Ret; + + TlsConn = (TLS_CONNECTION *) Tls; + PendingBufferSize = 0; + TempBuffer = NULL; + Ret = 0; + + if (TlsConn == NULL || \ + TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \ + BufferOutSize == NULL || \ + (BufferIn == NULL && BufferInSize != 0) || \ + (BufferIn != NULL && BufferInSize == 0) || \ + (BufferOut == NULL && *BufferOutSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) { + Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize); + if (Ret != (INTN) BufferInSize) { + return EFI_ABORTED; + } + + TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE); + + // + // ssl3_send_alert() will be called in ssl3_read_bytes() function. + // TempBuffer is invalid since it's a Alert message, so just ignore it. + // + SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE); + + OPENSSL_free (TempBuffer); + + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + } + + if (PendingBufferSize > *BufferOutSize) { + *BufferOutSize = PendingBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + if (PendingBufferSize > 0) { + *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize); + } else { + *BufferOutSize = 0; + } + + return EFI_SUCCESS; +} + +/** + Build the CloseNotify packet. + + @param[in] Tls Pointer to the TLS object for state checking. + @param[in, out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Tls is NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + +**/ +EFI_STATUS +EFIAPI +TlsCloseNotify ( + IN VOID *Tls, + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize + ) +{ + TLS_CONNECTION *TlsConn; + UINTN PendingBufferSize; + + TlsConn = (TLS_CONNECTION *) Tls; + PendingBufferSize = 0; + + if (TlsConn == NULL || \ + TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \ + BufferSize == NULL || \ + (Buffer == NULL && *BufferSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + if (PendingBufferSize == 0) { + // + // ssl3_send_alert() and ssl3_dispatch_alert() function will be called. + // + SSL_shutdown (TlsConn->Ssl); + PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio); + } + + if (PendingBufferSize > *BufferSize) { + *BufferSize = PendingBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + if (PendingBufferSize > 0) { + *BufferSize = BIO_read (TlsConn->OutBio, Buffer, (UINT32) PendingBufferSize); + } else { + *BufferSize = 0; + } + + return EFI_SUCCESS; +} + +/** + Attempts to read bytes from one TLS object and places the data in Buffer. + + This function will attempt to read BufferSize bytes from the TLS object + and places the data in Buffer. + + @param[in] Tls Pointer to the TLS object. + @param[in,out] Buffer Pointer to the buffer to store the data. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The amount of data successfully read from the TLS object. + @retval <=0 No data was successfully read. + +**/ +INTN +EFIAPI +TlsCtrlTrafficOut ( + IN VOID *Tls, + IN OUT VOID *Buffer, + IN UINTN BufferSize + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->OutBio == 0) { + return -1; + } + + // + // Read and return the amount of data from the BIO. + // + return BIO_read (TlsConn->OutBio, Buffer, (UINT32) BufferSize); +} + +/** + Attempts to write data from the buffer to TLS object. + + This function will attempt to write BufferSize bytes data from the Buffer + to the TLS object. + + @param[in] Tls Pointer to the TLS object. + @param[in] Buffer Pointer to the data buffer. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The amount of data successfully written to the TLS object. + @retval <=0 No data was successfully written. + +**/ +INTN +EFIAPI +TlsCtrlTrafficIn ( + IN VOID *Tls, + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->InBio == 0) { + return -1; + } + + // + // Write and return the amount of data to the BIO. + // + return BIO_write (TlsConn->InBio, Buffer, (UINT32) BufferSize); +} +/** + Attempts to read bytes from the specified TLS connection into the buffer. + + This function tries to read BufferSize bytes data from the specified TLS + connection into the Buffer. + + @param[in] Tls Pointer to the TLS connection for data reading. + @param[in,out] Buffer Pointer to the data buffer. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The read operation was successful, and return value is the + number of bytes actually read from the TLS connection. + @retval <=0 The read operation was not successful. + +**/ +INTN +EFIAPI +TlsRead ( + IN VOID *Tls, + IN OUT VOID *Buffer, + IN UINTN BufferSize + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL) { + return -1; + } + + // + // Read bytes from the specified TLS connection. + // + return SSL_read (TlsConn->Ssl, Buffer, (UINT32) BufferSize); +} + +/** + Attempts to write data to a TLS connection. + + This function tries to write BufferSize bytes data from the Buffer into the + specified TLS connection. + + @param[in] Tls Pointer to the TLS connection for data writing. + @param[in] Buffer Pointer to the data buffer. + @param[in] BufferSize The size of Buffer in bytes. + + @retval >0 The write operation was successful, and return value is the + number of bytes actually written to the TLS connection. + @retval <=0 The write operation was not successful. + +**/ +INTN +EFIAPI +TlsWrite ( + IN VOID *Tls, + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + TLS_CONNECTION *TlsConn; + + TlsConn = (TLS_CONNECTION *) Tls; + if (TlsConn == NULL || TlsConn->Ssl == NULL) { + return -1; + } + + // + // Write bytes to the specified TLS connection. + // + return SSL_write (TlsConn->Ssl, Buffer, (UINT32) BufferSize); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/GlueLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/GlueLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..9ba27fa32ce96e103d480983dc0294fc535d91bd GIT binary patch literal 33434 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 E2hDDhw*UYD literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/IntrinsicLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/IntrinsicLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..41612c13d6b55d36829828cc084fc79595fbc396 GIT binary patch literal 5208 zcmc&&Yiv|S6h4>jW7)oTA&3a-0wqF}b{A-&Na~ih+DhAnK8TtP?RNLJUEA$0_uf`Y zNT@L?5nu5U6BPl2ub_q)6EK=sB0fk+#DpLGL4K%-Mok2j#Q3P^o4NP)?zWYx7*8{I z=6-YT%$aj$<~!TP8=_jQui8`Y&y-+ARn^+HYbvUOnRvi_t+eqj4-w@ODVK=cA!kXd z$yj=XI(r6;Azh6V-jiumx@wSaXn6bkGq1KR>hjFusV^x+A-6DrX7QgQo>NQ;Te9cQ zTK45u9bC88oV?3ZyFSvPtC}9!p=zlekvdiHH&W@y)`UJ39q3Sd5-XEY-B7hiech&& zjg65Vm1`oc>VO*6)kv!Q?nvXHp(O_OM64;%9jQ&FN1D}S8F$bX9he7AX(RSrx|qRJ zZiUfY&2;My1_G6pm41J)VojA)?efGQ$fMo+@9O*}hsewRhm^%NHD(N}@{OpR8#x@8 z4DonbPwgJ+Ep4;#IP0v=(hHGyqp8FwgiGYGargr1@9FiMky7R=j#=DLU$a)DrI zzcr ze&TX97r5A~Y&pL3Wc#jH-QHV_H{$O$%qRMh@jJN8e4%Q*e^sPb8%Z0f&HcR*J{DS3 z8=3l?#Dtv)cOEtQcxMrOJWTWERljzi^!JkDjr)&0zv+0#4_jd074@}!me|0ubiA7` zUZ~$Y_6<)XY$z1974eJwb`#wuA`T4*tcHj^YMme&<*NxdR1sDCTzT+oT-6OKrW)Vv zSc4EZ$D!J%@J9;iT1@nAa`YB+?+|M$6iW>a%CGzEei!fayL@=X2#aWrJ-Hm+eufnC zkwmdX^>F}>x8$SQ|(Af{`o*n)^ zc>NQv2Ohlj{LqR^$pt?*jy<`(`}FwxXI?qQg9r)5_*j%B;zzgVDC6UZSExsg8fAgN z<7}}+oEIM)>r!y_Ws39i!TMbauDwigUU=9SE(KR!rj$7@JM1r)0hk^`P5^Rf^Kk)P?(+B(<6*jASmzH@Z#w&Mox6EI{brt2R8uh`uJk63SBCs^Mtqsa>H9Ajamu{s-%%r& zaVM8~ROB=4_1lRi7;-Mdk}s#APd|5pP1o@)XREddW=(TfZ9`4#I-7R?!-m_)mo ztoy(p+lIH-KYi!<{4bmK)I7|w1?xt+%$)LO!n%{38N(Ft2et_q7{qXb+t}6x^oiN> zh-37Bu`;&0pk*|0u5yGqFdJ^nre*VBat~1t8m~nF|G04B}#0U*+qvVviGYp?2ttv6Y2hVY=`lbz@%&HnJW4X5c0KV8@;+$QL zqIo0Nu!%!Bic`9hYpgWDHT)Lj8sS~QMTQqG8D5DYyb{CjD~aJJg2W!Ru_tWoh>g8% zV~f}~@>{>z@=TmcB##rP@)*BmhuYeq+(ktbp*H_{fLH?MYH3A-maa$3Lt%bOtj%nBXu!tOHg?L! zPTQE3+;K5V=$5TjZ(041ym0WIV@=w3Jg|`eE(u1)hI?m1W|RcSC-O905iSK!h}!!eHV}(V z$=pWoEOKUT*ikM8Pd0$weCfop$*D6ARA%a&D>6OjI7p~migg5wzuU%H5k_>T;Mg}Z z-7n-8B!AL4NTx1l4`|h;{KQX;2$?O$LCab{5mI?biFo1x#Jm*+mTw{W&zq23ftbfh nAhQMH`~gtFxJyCimnqn*_}4*HQ#nJR8a940{;T&V9Wih| literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/AArch64/ProcessorBind.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/AArch64/ProcessorBind.h new file mode 100644 index 0000000..654cfe1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/AArch64/ProcessorBind.h @@ -0,0 +1,213 @@ +/** @file + Processor or Compiler specific defines and types for AArch64. + + Copyright (c) 2006 - 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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_AARCH64 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#if !defined(__GNUC__) && !defined(__ASSEMBLER__) +#pragma pack() +#endif + +#if defined(_MSC_EXTENSIONS) + +// +// Disable some level 4 compilation warnings (same as IA32 and X64) +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) source file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +// +// Disable 'potentially uninitialized local variable X used' warnings +// +#pragma warning ( disable : 4701 ) + +// +// Disable 'potentially uninitialized local pointer variable X used' warnings +// +#pragma warning ( disable : 4703 ) + + // + // use Microsoft* C compiler dependent integer width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; + +#else + + // + // Assume standard AARCH64 alignment. + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; + +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef UINT64 UINTN; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef INT64 INTN; + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x8000000000000000ULL + +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC000000000000000ULL + +/// +/// Maximum legal AARCH64 address +/// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL + +/// +/// Maximum usable address at boot time (48 bits using 4 KB pages) +/// +#define MAX_ALLOC_ADDRESS 0xFFFFFFFFFFFFULL + +/// +/// Maximum legal AArch64 INTN and UINTN values. +/// +#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL) +#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL) + +/// +/// Minimum legal AArch64 INTN value. +/// +#define MIN_INTN (((INTN)-9223372036854775807LL) - 1) + +/// +/// The stack alignment required for AARCH64 +/// +#define CPU_STACK_ALIGNMENT 16 + +/// +/// Page allocation granularity for AARCH64 +/// +#define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000) +#define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x10000) + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#define EFIAPI + +// When compiling with Clang, we still use GNU as for the assembler, so we still +// need to define the GCC_ASM* macros. +#if defined(__GNUC__) || defined(__clang__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl + + #define GCC_ASM_EXPORT(func__) \ + .global _CONCATENATE (__USER_LABEL_PREFIX__, func__) ;\ + .type ASM_PFX(func__), %function + + #define GCC_ASM_IMPORT(func__) \ + .extern _CONCATENATE (__USER_LABEL_PREFIX__, func__) + +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On ARM CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Arm/ProcessorBind.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Arm/ProcessorBind.h new file mode 100644 index 0000000..33b5a84 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Arm/ProcessorBind.h @@ -0,0 +1,246 @@ +/** @file + Processor or Compiler specific defines and types for ARM. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_ARM + +// +// Make sure we are using the correct packing rules per EFI specification +// +#if !defined(__GNUC__) && !defined(__ASSEMBLER__) +#pragma pack() +#endif + +#if defined(_MSC_EXTENSIONS) + +// +// Disable some level 4 compilation warnings (same as IA32 and X64) +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) source file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +// +// Disable 'potentially uninitialized local variable X used' warnings +// +#pragma warning ( disable : 4701 ) + +// +// Disable 'potentially uninitialized local pointer variable X used' warnings +// +#pragma warning ( disable : 4703 ) + +#endif + +// +// RVCT and MSFT don't support the __builtin_unreachable() macro +// +#if defined(__ARMCC_VERSION) || defined(_MSC_EXTENSIONS) +#define UNREACHABLE() +#endif + +#if defined(_MSC_EXTENSIONS) + // + // use Microsoft* C compiler dependent integer width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; +#else + // + // Assume standard ARM alignment. + // Need to check portability of long long + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef UINT32 UINTN; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef INT32 INTN; + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x80000000 + +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC0000000 + +/// +/// Maximum legal ARM address +/// +#define MAX_ADDRESS 0xFFFFFFFF + +/// +/// Maximum usable address at boot time +/// +#define MAX_ALLOC_ADDRESS MAX_ADDRESS + +/// +/// Maximum legal ARM INTN and UINTN values. +/// +#define MAX_INTN ((INTN)0x7FFFFFFF) +#define MAX_UINTN ((UINTN)0xFFFFFFFF) + +/// +/// Minimum legal ARM INTN value. +/// +#define MIN_INTN (((INTN)-2147483647) - 1) + +/// +/// The stack alignment required for ARM +/// +#define CPU_STACK_ALIGNMENT sizeof(UINT64) + +/// +/// Page allocation granularity for ARM +/// +#define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000) +#define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x1000) + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#define EFIAPI + +// When compiling with Clang, we still use GNU as for the assembler, so we still +// need to define the GCC_ASM* macros. +#if defined(__GNUC__) || defined(__clang__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl + + #if !defined(__APPLE__) + /// + /// ARM EABI defines that the linker should not manipulate call relocations + /// (do bl/blx conversion) unless the target symbol has function type. + /// CodeSourcery 2010.09 started requiring the .type to function properly + /// + #define INTERWORK_FUNC(func__) .type ASM_PFX(func__), %function + + #define GCC_ASM_EXPORT(func__) \ + .global _CONCATENATE (__USER_LABEL_PREFIX__, func__) ;\ + .type ASM_PFX(func__), %function + + #define GCC_ASM_IMPORT(func__) \ + .extern _CONCATENATE (__USER_LABEL_PREFIX__, func__) + + #else + // + // .type not supported by Apple Xcode tools + // + #define INTERWORK_FUNC(func__) + + #define GCC_ASM_EXPORT(func__) \ + .globl _CONCATENATE (__USER_LABEL_PREFIX__, func__) \ + + #define GCC_ASM_IMPORT(name) + + #endif +#elif defined(_MSC_EXTENSIONS) + // + // PRESERVE8 is not supported by the MSFT assembler. + // + #define PRESERVE8 +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On ARM CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Base.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Base.h new file mode 100644 index 0000000..0d7b381 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Base.h @@ -0,0 +1,1319 @@ +/** @file + Root include file for Mde Package Base type modules + + This is the include file for any module of type base. Base modules only use + types defined via this include file and can be ported easily to any + environment. There are a set of base libraries in the Mde Package that can + be used to implement base modules. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __BASE_H__ +#define __BASE_H__ + +// +// Include processor specific binding +// +#include + +#if defined(_MSC_EXTENSIONS) +// +// Disable warning when last field of data structure is a zero sized array. +// +#pragma warning ( disable : 4200 ) +#endif + +/** + Verifies the storage size of a given data type. + + This macro generates a divide by zero error or a zero size array declaration in + the preprocessor if the size is incorrect. These are declared as "extern" so + the space for these arrays will not be in the modules. + + @param TYPE The date type to determine the size of. + @param Size The expected size for the TYPE. + +**/ +#define VERIFY_SIZE_OF(TYPE, Size) extern UINT8 _VerifySizeof##TYPE[(sizeof(TYPE) == (Size)) / (sizeof(TYPE) == (Size))] + +// +// Verify that ProcessorBind.h produced UEFI Data Types that are compliant with +// Section 2.3.1 of the UEFI 2.3 Specification. +// +VERIFY_SIZE_OF (BOOLEAN, 1); +VERIFY_SIZE_OF (INT8, 1); +VERIFY_SIZE_OF (UINT8, 1); +VERIFY_SIZE_OF (INT16, 2); +VERIFY_SIZE_OF (UINT16, 2); +VERIFY_SIZE_OF (INT32, 4); +VERIFY_SIZE_OF (UINT32, 4); +VERIFY_SIZE_OF (INT64, 8); +VERIFY_SIZE_OF (UINT64, 8); +VERIFY_SIZE_OF (CHAR8, 1); +VERIFY_SIZE_OF (CHAR16, 2); + +// +// The following three enum types are used to verify that the compiler +// configuration for enum types is compliant with Section 2.3.1 of the +// UEFI 2.3 Specification. These enum types and enum values are not +// intended to be used. A prefix of '__' is used avoid conflicts with +// other types. +// +typedef enum { + __VerifyUint8EnumValue = 0xff +} __VERIFY_UINT8_ENUM_SIZE; + +typedef enum { + __VerifyUint16EnumValue = 0xffff +} __VERIFY_UINT16_ENUM_SIZE; + +typedef enum { + __VerifyUint32EnumValue = 0xffffffff +} __VERIFY_UINT32_ENUM_SIZE; + +VERIFY_SIZE_OF (__VERIFY_UINT8_ENUM_SIZE, 4); +VERIFY_SIZE_OF (__VERIFY_UINT16_ENUM_SIZE, 4); +VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4); + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if defined(_MSC_EXTENSIONS) && _MSC_VER < 1800 && !defined (MDE_CPU_EBC) + /// + /// Remove global variable from the linked image if there are no references to + /// it after all compiler and linker optimizations have been performed. + /// + /// + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + /// + /// Remove the global variable from the linked image if there are no references + /// to it after all compiler and linker optimizations have been performed. + /// + /// + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +// +// Should be used in combination with NORETURN to avoid 'noreturn' returns +// warnings. +// +#ifndef UNREACHABLE + #ifdef __GNUC__ + /// + /// Signal compilers and analyzers that this call is not reachable. It is + /// up to the compiler to remove any code past that point. + /// + #define UNREACHABLE() __builtin_unreachable () + #elif defined (__has_feature) + #if __has_builtin (__builtin_unreachable) + /// + /// Signal compilers and analyzers that this call is not reachable. It is + /// up to the compiler to remove any code past that point. + /// + #define UNREACHABLE() __builtin_unreachable () + #endif + #endif + + #ifndef UNREACHABLE + /// + /// Signal compilers and analyzers that this call is not reachable. It is + /// up to the compiler to remove any code past that point. + /// + #define UNREACHABLE() + #endif +#endif + +// +// Signaling compilers and analyzers that a certain function cannot return may +// remove all following code and thus lead to better optimization and less +// false positives. +// +#ifndef NORETURN + #if defined (__GNUC__) || defined (__clang__) + /// + /// Signal compilers and analyzers that the function cannot return. + /// It is up to the compiler to remove any code past a call to functions + /// flagged with this attribute. + /// + #define NORETURN __attribute__((noreturn)) + #elif defined(_MSC_EXTENSIONS) && !defined(MDE_CPU_EBC) + /// + /// Signal compilers and analyzers that the function cannot return. + /// It is up to the compiler to remove any code past a call to functions + /// flagged with this attribute. + /// + #define NORETURN __declspec(noreturn) + #else + /// + /// Signal compilers and analyzers that the function cannot return. + /// It is up to the compiler to remove any code past a call to functions + /// flagged with this attribute. + /// + #define NORETURN + #endif +#endif + +// +// Should be used in combination with ANALYZER_NORETURN to avoid 'noreturn' +// returns warnings. +// +#ifndef ANALYZER_UNREACHABLE + #ifdef __clang_analyzer__ + #if __has_builtin (__builtin_unreachable) + /// + /// Signal the analyzer that this call is not reachable. + /// This excludes compilers. + /// + #define ANALYZER_UNREACHABLE() __builtin_unreachable () + #endif + #endif + + #ifndef ANALYZER_UNREACHABLE + /// + /// Signal the analyzer that this call is not reachable. + /// This excludes compilers. + /// + #define ANALYZER_UNREACHABLE() + #endif +#endif + +// +// Static Analyzers may issue errors about potential NULL-dereferences when +// dereferencing a pointer, that has been checked before, outside of a +// NULL-check. This may lead to false positives, such as when using ASSERT() +// for verification. +// +#ifndef ANALYZER_NORETURN + #ifdef __has_feature + #if __has_feature (attribute_analyzer_noreturn) + /// + /// Signal analyzers that the function cannot return. + /// This excludes compilers. + /// + #define ANALYZER_NORETURN __attribute__((analyzer_noreturn)) + #endif + #endif + + #ifndef ANALYZER_NORETURN + /// + /// Signal the analyzer that the function cannot return. + /// This excludes compilers. + /// + #define ANALYZER_NORETURN + #endif +#endif + +/// +/// Tell the code optimizer that the function will return twice. +/// This prevents wrong optimizations which can cause bugs. +/// +#ifndef RETURNS_TWICE + #if defined (__GNUC__) || defined (__clang__) + /// + /// Tell the code optimizer that the function will return twice. + /// This prevents wrong optimizations which can cause bugs. + /// + #define RETURNS_TWICE __attribute__((returns_twice)) + #else + /// + /// Tell the code optimizer that the function will return twice. + /// This prevents wrong optimizations which can cause bugs. + /// + #define RETURNS_TWICE + #endif +#endif + +// +// For symbol name in assembly code, an extra "_" is sometimes necessary +// + +/// +/// Private worker functions for ASM_PFX() +/// +#define _CONCATENATE(a, b) __CONCATENATE(a, b) +#define __CONCATENATE(a, b) a ## b + +/// +/// The __USER_LABEL_PREFIX__ macro predefined by GNUC represents the prefix +/// on symbols in assembly language. +/// +#define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name) + +#if __APPLE__ + // + // Apple extension that is used by the linker to optimize code size + // with assembly functions. Put at the end of your .S files + // + #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED .subsections_via_symbols +#else + #define ASM_FUNCTION_REMOVE_IF_UNREFERENCED +#endif + +#ifdef __CC_ARM + // + // Older RVCT ARM compilers don't fully support #pragma pack and require __packed + // as a prefix for the structure. + // + #define PACKED __packed +#else + #define PACKED +#endif + +/// +/// 128 bit buffer containing a unique identifier value. +/// Unless otherwise specified, aligned on a 64 bit boundary. +/// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; + +/// +/// 4-byte buffer. An IPv4 internet protocol address. +/// +typedef struct { + UINT8 Addr[4]; +} IPv4_ADDRESS; + +/// +/// 16-byte buffer. An IPv6 internet protocol address. +/// +typedef struct { + UINT8 Addr[16]; +} IPv6_ADDRESS; + +// +// 8-bytes unsigned value that represents a physical system address. +// +typedef UINT64 PHYSICAL_ADDRESS; + +/// +/// LIST_ENTRY structure definition. +/// +typedef struct _LIST_ENTRY LIST_ENTRY; + +/// +/// _LIST_ENTRY structure definition. +/// +struct _LIST_ENTRY { + LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; +}; + +// +// Modifiers to abstract standard types to aid in debug of problems +// + +/// +/// Datum is read-only. +/// +#define CONST const + +/// +/// Datum is scoped to the current file or function. +/// +#define STATIC static + +/// +/// Undeclared type. +/// +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// + +/// +/// Datum is passed to the function. +/// +#define IN + +/// +/// Datum is returned from the function. +/// +#define OUT + +/// +/// Passing the datum to the function is optional, and a NULL +/// is passed if the value is not supplied. +/// +#define OPTIONAL + +// +// UEFI specification claims 1 and 0. We are concerned about the +// compiler portability so we did it this way. +// + +/// +/// Boolean true value. UEFI Specification defines this value to be 1, +/// but this form is more portable. +/// +#define TRUE ((BOOLEAN)(1==1)) + +/// +/// Boolean false value. UEFI Specification defines this value to be 0, +/// but this form is more portable. +/// +#define FALSE ((BOOLEAN)(0==1)) + +/// +/// NULL pointer (VOID *) +/// +#define NULL ((VOID *) 0) + +// +// Null character +// +#define CHAR_NULL 0x0000 + +/// +/// Maximum values for common UEFI Data Types +/// +#define MAX_INT8 ((INT8)0x7F) +#define MAX_UINT8 ((UINT8)0xFF) +#define MAX_INT16 ((INT16)0x7FFF) +#define MAX_UINT16 ((UINT16)0xFFFF) +#define MAX_INT32 ((INT32)0x7FFFFFFF) +#define MAX_UINT32 ((UINT32)0xFFFFFFFF) +#define MAX_INT64 ((INT64)0x7FFFFFFFFFFFFFFFULL) +#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL) + +/// +/// Minimum values for the signed UEFI Data Types +/// +#define MIN_INT8 (((INT8) -127) - 1) +#define MIN_INT16 (((INT16) -32767) - 1) +#define MIN_INT32 (((INT32) -2147483647) - 1) +#define MIN_INT64 (((INT64) -9223372036854775807LL) - 1) + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#define BIT32 0x0000000100000000ULL +#define BIT33 0x0000000200000000ULL +#define BIT34 0x0000000400000000ULL +#define BIT35 0x0000000800000000ULL +#define BIT36 0x0000001000000000ULL +#define BIT37 0x0000002000000000ULL +#define BIT38 0x0000004000000000ULL +#define BIT39 0x0000008000000000ULL +#define BIT40 0x0000010000000000ULL +#define BIT41 0x0000020000000000ULL +#define BIT42 0x0000040000000000ULL +#define BIT43 0x0000080000000000ULL +#define BIT44 0x0000100000000000ULL +#define BIT45 0x0000200000000000ULL +#define BIT46 0x0000400000000000ULL +#define BIT47 0x0000800000000000ULL +#define BIT48 0x0001000000000000ULL +#define BIT49 0x0002000000000000ULL +#define BIT50 0x0004000000000000ULL +#define BIT51 0x0008000000000000ULL +#define BIT52 0x0010000000000000ULL +#define BIT53 0x0020000000000000ULL +#define BIT54 0x0040000000000000ULL +#define BIT55 0x0080000000000000ULL +#define BIT56 0x0100000000000000ULL +#define BIT57 0x0200000000000000ULL +#define BIT58 0x0400000000000000ULL +#define BIT59 0x0800000000000000ULL +#define BIT60 0x1000000000000000ULL +#define BIT61 0x2000000000000000ULL +#define BIT62 0x4000000000000000ULL +#define BIT63 0x8000000000000000ULL + +#define SIZE_1KB 0x00000400 +#define SIZE_2KB 0x00000800 +#define SIZE_4KB 0x00001000 +#define SIZE_8KB 0x00002000 +#define SIZE_16KB 0x00004000 +#define SIZE_32KB 0x00008000 +#define SIZE_64KB 0x00010000 +#define SIZE_128KB 0x00020000 +#define SIZE_256KB 0x00040000 +#define SIZE_512KB 0x00080000 +#define SIZE_1MB 0x00100000 +#define SIZE_2MB 0x00200000 +#define SIZE_4MB 0x00400000 +#define SIZE_8MB 0x00800000 +#define SIZE_16MB 0x01000000 +#define SIZE_32MB 0x02000000 +#define SIZE_64MB 0x04000000 +#define SIZE_128MB 0x08000000 +#define SIZE_256MB 0x10000000 +#define SIZE_512MB 0x20000000 +#define SIZE_1GB 0x40000000 +#define SIZE_2GB 0x80000000 +#define SIZE_4GB 0x0000000100000000ULL +#define SIZE_8GB 0x0000000200000000ULL +#define SIZE_16GB 0x0000000400000000ULL +#define SIZE_32GB 0x0000000800000000ULL +#define SIZE_64GB 0x0000001000000000ULL +#define SIZE_128GB 0x0000002000000000ULL +#define SIZE_256GB 0x0000004000000000ULL +#define SIZE_512GB 0x0000008000000000ULL +#define SIZE_1TB 0x0000010000000000ULL +#define SIZE_2TB 0x0000020000000000ULL +#define SIZE_4TB 0x0000040000000000ULL +#define SIZE_8TB 0x0000080000000000ULL +#define SIZE_16TB 0x0000100000000000ULL +#define SIZE_32TB 0x0000200000000000ULL +#define SIZE_64TB 0x0000400000000000ULL +#define SIZE_128TB 0x0000800000000000ULL +#define SIZE_256TB 0x0001000000000000ULL +#define SIZE_512TB 0x0002000000000000ULL +#define SIZE_1PB 0x0004000000000000ULL +#define SIZE_2PB 0x0008000000000000ULL +#define SIZE_4PB 0x0010000000000000ULL +#define SIZE_8PB 0x0020000000000000ULL +#define SIZE_16PB 0x0040000000000000ULL +#define SIZE_32PB 0x0080000000000000ULL +#define SIZE_64PB 0x0100000000000000ULL +#define SIZE_128PB 0x0200000000000000ULL +#define SIZE_256PB 0x0400000000000000ULL +#define SIZE_512PB 0x0800000000000000ULL +#define SIZE_1EB 0x1000000000000000ULL +#define SIZE_2EB 0x2000000000000000ULL +#define SIZE_4EB 0x4000000000000000ULL +#define SIZE_8EB 0x8000000000000000ULL + +#define BASE_1KB 0x00000400 +#define BASE_2KB 0x00000800 +#define BASE_4KB 0x00001000 +#define BASE_8KB 0x00002000 +#define BASE_16KB 0x00004000 +#define BASE_32KB 0x00008000 +#define BASE_64KB 0x00010000 +#define BASE_128KB 0x00020000 +#define BASE_256KB 0x00040000 +#define BASE_512KB 0x00080000 +#define BASE_1MB 0x00100000 +#define BASE_2MB 0x00200000 +#define BASE_4MB 0x00400000 +#define BASE_8MB 0x00800000 +#define BASE_16MB 0x01000000 +#define BASE_32MB 0x02000000 +#define BASE_64MB 0x04000000 +#define BASE_128MB 0x08000000 +#define BASE_256MB 0x10000000 +#define BASE_512MB 0x20000000 +#define BASE_1GB 0x40000000 +#define BASE_2GB 0x80000000 +#define BASE_4GB 0x0000000100000000ULL +#define BASE_8GB 0x0000000200000000ULL +#define BASE_16GB 0x0000000400000000ULL +#define BASE_32GB 0x0000000800000000ULL +#define BASE_64GB 0x0000001000000000ULL +#define BASE_128GB 0x0000002000000000ULL +#define BASE_256GB 0x0000004000000000ULL +#define BASE_512GB 0x0000008000000000ULL +#define BASE_1TB 0x0000010000000000ULL +#define BASE_2TB 0x0000020000000000ULL +#define BASE_4TB 0x0000040000000000ULL +#define BASE_8TB 0x0000080000000000ULL +#define BASE_16TB 0x0000100000000000ULL +#define BASE_32TB 0x0000200000000000ULL +#define BASE_64TB 0x0000400000000000ULL +#define BASE_128TB 0x0000800000000000ULL +#define BASE_256TB 0x0001000000000000ULL +#define BASE_512TB 0x0002000000000000ULL +#define BASE_1PB 0x0004000000000000ULL +#define BASE_2PB 0x0008000000000000ULL +#define BASE_4PB 0x0010000000000000ULL +#define BASE_8PB 0x0020000000000000ULL +#define BASE_16PB 0x0040000000000000ULL +#define BASE_32PB 0x0080000000000000ULL +#define BASE_64PB 0x0100000000000000ULL +#define BASE_128PB 0x0200000000000000ULL +#define BASE_256PB 0x0400000000000000ULL +#define BASE_512PB 0x0800000000000000ULL +#define BASE_1EB 0x1000000000000000ULL +#define BASE_2EB 0x2000000000000000ULL +#define BASE_4EB 0x4000000000000000ULL +#define BASE_8EB 0x8000000000000000ULL + +// +// Support for variable argument lists in freestanding edk2 modules. +// +// For modules that use the ISO C library interfaces for variable +// argument lists, refer to "StdLib/Include/stdarg.h". +// +// VA_LIST - typedef for argument list. +// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use. +// VA_END (VA_LIST Marker) - Clear Marker +// VA_ARG (VA_LIST Marker, var arg type) - Use Marker to get an argument from +// the ... list. You must know the type and pass it in this macro. Type +// must be compatible with the type of the actual next argument (as promoted +// according to the default argument promotions.) +// VA_COPY (VA_LIST Dest, VA_LIST Start) - Initialize Dest as a copy of Start. +// +// Example: +// +// UINTN +// EFIAPI +// ExampleVarArg ( +// IN UINTN NumberOfArgs, +// ... +// ) +// { +// VA_LIST Marker; +// UINTN Index; +// UINTN Result; +// +// // +// // Initialize the Marker +// // +// VA_START (Marker, NumberOfArgs); +// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) { +// // +// // The ... list is a series of UINTN values, so sum them up. +// // +// Result += VA_ARG (Marker, UINTN); +// } +// +// VA_END (Marker); +// return Result; +// } +// +// Notes: +// - Functions that call VA_START() / VA_END() must have a variable +// argument list and must be declared EFIAPI. +// - Functions that call VA_COPY() / VA_END() must be declared EFIAPI. +// - Functions that only use VA_LIST and VA_ARG() need not be EFIAPI. +// + +/** + Return the size of argument that has been aligned to sizeof (UINTN). + + @param n The parameter size to be aligned. + + @return The aligned size. +**/ +#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) + +#if defined(__CC_ARM) +// +// RVCT ARM variable argument list support. +// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +#ifdef __APCS_ADSABI + typedef int *va_list[1]; + #define VA_LIST va_list +#else + typedef struct __va_list { void *__ap; } va_list; + #define VA_LIST va_list +#endif + +#define VA_START(Marker, Parameter) __va_start(Marker, Parameter) + +#define VA_ARG(Marker, TYPE) __va_arg(Marker, TYPE) + +#define VA_END(Marker) ((void)0) + +// For some ARM RVCT compilers, __va_copy is not defined +#ifndef __va_copy + #define __va_copy(dest, src) ((void)((dest) = (src))) +#endif + +#define VA_COPY(Dest, Start) __va_copy (Dest, Start) + +#elif defined(_M_ARM) || defined(_M_ARM64) +// +// MSFT ARM variable argument list support. +// + +typedef char* VA_LIST; + +#define VA_START(Marker, Parameter) __va_start (&Marker, &Parameter, _INT_SIZE_OF (Parameter), __alignof(Parameter), &Parameter) +#define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE) + ((-(INTN)Marker) & (sizeof(TYPE) - 1))) - _INT_SIZE_OF (TYPE))) +#define VA_END(Marker) (Marker = (VA_LIST) 0) +#define VA_COPY(Dest, Start) ((void)((Dest) = (Start))) + +#elif defined(__GNUC__) + +#if defined(MDE_CPU_X64) && !defined(NO_MSABI_VA_FUNCS) +// +// X64 only. Use MS ABI version of GCC built-in macros for variable argument lists. +// +/// +/// Both GCC and LLVM 3.8 for X64 support new variable argument intrinsics for Microsoft ABI +/// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef __builtin_ms_va_list VA_LIST; + +#define VA_START(Marker, Parameter) __builtin_ms_va_start (Marker, Parameter) + +#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE))) + +#define VA_END(Marker) __builtin_ms_va_end (Marker) + +#define VA_COPY(Dest, Start) __builtin_ms_va_copy (Dest, Start) + +#else +// +// Use GCC built-in macros for variable argument lists. +// + +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef __builtin_va_list VA_LIST; + +#define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter) + +#define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE))) + +#define VA_END(Marker) __builtin_va_end (Marker) + +#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start) + +#endif + +#else +/// +/// Variable used to traverse the list of arguments. This type can vary by +/// implementation and could be an array or structure. +/// +typedef CHAR8 *VA_LIST; + +/** + Retrieves a pointer to the beginning of a variable argument list, based on + the name of the parameter that immediately precedes the variable argument list. + + This function initializes Marker to point to the beginning of the variable + argument list that immediately follows Parameter. The method for computing the + pointer to the next argument in the argument list is CPU-specific following the + EFIAPI ABI. + + @param Marker The VA_LIST used to traverse the list of arguments. + @param Parameter The name of the parameter that immediately precedes + the variable argument list. + + @return A pointer to the beginning of a variable argument list. + +**/ +#define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter))) + +/** + Returns an argument of a specified type from a variable argument list and updates + the pointer to the variable argument list to point to the next argument. + + This function returns an argument of the type specified by TYPE from the beginning + of the variable argument list specified by Marker. Marker is then updated to point + to the next argument in the variable argument list. The method for computing the + pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI. + + @param Marker VA_LIST used to traverse the list of arguments. + @param TYPE The type of argument to retrieve from the beginning + of the variable argument list. + + @return An argument of the type specified by TYPE. + +**/ +#define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE))) + +/** + Terminates the use of a variable argument list. + + This function initializes Marker so it can no longer be used with VA_ARG(). + After this macro is used, the only way to access the variable argument list is + by using VA_START() again. + + @param Marker VA_LIST used to traverse the list of arguments. + +**/ +#define VA_END(Marker) (Marker = (VA_LIST) 0) + +/** + Initializes a VA_LIST as a copy of an existing VA_LIST. + + This macro initializes Dest as a copy of Start, as if the VA_START macro had been applied to Dest + followed by the same sequence of uses of the VA_ARG macro as had previously been used to reach + the present state of Start. + + @param Dest VA_LIST used to traverse the list of arguments. + @param Start VA_LIST used to traverse the list of arguments. + +**/ +#define VA_COPY(Dest, Start) ((void)((Dest) = (Start))) + +#endif + +/// +/// Pointer to the start of a variable argument list stored in a memory buffer. Same as UINT8 *. +/// +typedef UINTN *BASE_LIST; + +/** + Returns the size of a data type in sizeof(UINTN) units rounded up to the nearest UINTN boundary. + + @param TYPE The date type to determine the size of. + + @return The size of TYPE in sizeof (UINTN) units rounded up to the nearest UINTN boundary. +**/ +#define _BASE_INT_SIZE_OF(TYPE) ((sizeof (TYPE) + sizeof (UINTN) - 1) / sizeof (UINTN)) + +/** + Returns an argument of a specified type from a variable argument list and updates + the pointer to the variable argument list to point to the next argument. + + This function returns an argument of the type specified by TYPE from the beginning + of the variable argument list specified by Marker. Marker is then updated to point + to the next argument in the variable argument list. The method for computing the + pointer to the next argument in the argument list is CPU specific following the EFIAPI ABI. + + @param Marker The pointer to the beginning of a variable argument list. + @param TYPE The type of argument to retrieve from the beginning + of the variable argument list. + + @return An argument of the type specified by TYPE. + +**/ +#define BASE_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _BASE_INT_SIZE_OF (TYPE)) - _BASE_INT_SIZE_OF (TYPE))) + +/** + The macro that returns the byte offset of a field in a data structure. + + This function returns the offset, in bytes, of field specified by Field from the + beginning of the data structure specified by TYPE. If TYPE does not contain Field, + the module will not compile. + + @param TYPE The name of the data structure that contains the field specified by Field. + @param Field The name of the field in the data structure. + + @return Offset, in bytes, of field. + +**/ +#ifdef __GNUC__ +#if __GNUC__ >= 4 +#define OFFSET_OF(TYPE, Field) ((UINTN) __builtin_offsetof(TYPE, Field)) +#endif +#endif + +#ifndef OFFSET_OF +#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) +#endif + +/** + Macro that returns a pointer to the data structure that contains a specified field of + that data structure. This is a lightweight method to hide information by placing a + public data structure inside a larger private data structure and using a pointer to + the public data structure to retrieve a pointer to the private data structure. + + This function computes the offset, in bytes, of field specified by Field from the beginning + of the data structure specified by TYPE. This offset is subtracted from Record, and is + used to return a pointer to a data structure of the type specified by TYPE. If the data type + specified by TYPE does not contain the field specified by Field, then the module will not compile. + + @param Record Pointer to the field specified by Field within a data structure of type TYPE. + @param TYPE The name of the data structure type to return. This data structure must + contain the field specified by Field. + @param Field The name of the field in the data structure specified by TYPE to which Record points. + + @return A pointer to the structure from one of it's elements. + +**/ +#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - OFFSET_OF (TYPE, Field))) + +/** + Rounds a value up to the next boundary using a specified alignment. + + This function rounds Value up to the next boundary using the specified Alignment. + This aligned value is returned. + + @param Value The value to round up. + @param Alignment The alignment boundary used to return the aligned value. + + @return A value up to the next boundary. + +**/ +#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1))) + +/** + Adjust a pointer by adding the minimum offset required for it to be aligned on + a specified alignment boundary. + + This function rounds the pointer specified by Pointer to the next alignment boundary + specified by Alignment. The pointer to the aligned address is returned. + + @param Pointer The pointer to round up. + @param Alignment The alignment boundary to use to return an aligned pointer. + + @return Pointer to the aligned address. + +**/ +#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment)))) + +/** + Rounds a value up to the next natural boundary for the current CPU. + This is 4-bytes for 32-bit CPUs and 8-bytes for 64-bit CPUs. + + This function rounds the value specified by Value up to the next natural boundary for the + current CPU. This rounded value is returned. + + @param Value The value to round up. + + @return Rounded value specified by Value. + +**/ +#define ALIGN_VARIABLE(Value) ALIGN_VALUE ((Value), sizeof (UINTN)) + + +/** + Return the maximum of two operands. + + This macro returns the maximum of two operand specified by a and b. + Both a and b must be the same numerical types, signed or unsigned. + + @param a The first operand with any numerical type. + @param b The second operand. Can be any numerical type as long as is + the same type as a. + + @return Maximum of two operands. + +**/ +#define MAX(a, b) \ + (((a) > (b)) ? (a) : (b)) + +/** + Return the minimum of two operands. + + This macro returns the minimal of two operand specified by a and b. + Both a and b must be the same numerical types, signed or unsigned. + + @param a The first operand with any numerical type. + @param b The second operand. It should be the same any numerical type with a. + + @return Minimum of two operands. + +**/ +#define MIN(a, b) \ + (((a) < (b)) ? (a) : (b)) + +/** + Return the absolute value of a signed operand. + + This macro returns the absolute value of the signed operand specified by a. + + @param a The signed operand. + + @return The absolute value of the signed operand. + +**/ +#define ABS(a) \ + (((a) < 0) ? (-(a)) : (a)) + +// +// Status codes common to all execution phases +// +typedef UINTN RETURN_STATUS; + +/** + Produces a RETURN_STATUS code with the highest bit set. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit set. + +**/ +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) + +/** + Produces a RETURN_STATUS code with the highest bit clear. + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x7FFFFFFF. + + @return The value specified by StatusCode with the highest bit clear. + +**/ +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) + +/** + Returns TRUE if a specified RETURN_STATUS code is an error code. + + This function returns TRUE if StatusCode has the high bit set. Otherwise, FALSE is returned. + + @param StatusCode The status code value to evaluate. + + @retval TRUE The high bit of StatusCode is set. + @retval FALSE The high bit of StatusCode is clear. + +**/ +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) + +/// +/// The operation completed successfully. +/// +#define RETURN_SUCCESS 0 + +/// +/// The image failed to load. +/// +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) + +/// +/// The parameter was incorrect. +/// +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) + +/// +/// The operation is not supported. +/// +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) + +/// +/// The buffer was not the proper size for the request. +/// +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) + +/// +/// The buffer was not large enough to hold the requested data. +/// The required buffer size is returned in the appropriate +/// parameter when this error occurs. +/// +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) + +/// +/// There is no data pending upon return. +/// +#define RETURN_NOT_READY ENCODE_ERROR (6) + +/// +/// The physical device reported an error while attempting the +/// operation. +/// +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) + +/// +/// The device can not be written to. +/// +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) + +/// +/// The resource has run out. +/// +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) + +/// +/// An inconsistency was detected on the file system causing the +/// operation to fail. +/// +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) + +/// +/// There is no more space on the file system. +/// +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) + +/// +/// The device does not contain any medium to perform the +/// operation. +/// +#define RETURN_NO_MEDIA ENCODE_ERROR (12) + +/// +/// The medium in the device has changed since the last +/// access. +/// +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) + +/// +/// The item was not found. +/// +#define RETURN_NOT_FOUND ENCODE_ERROR (14) + +/// +/// Access was denied. +/// +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) + +/// +/// The server was not found or did not respond to the request. +/// +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) + +/// +/// A mapping to the device does not exist. +/// +#define RETURN_NO_MAPPING ENCODE_ERROR (17) + +/// +/// A timeout time expired. +/// +#define RETURN_TIMEOUT ENCODE_ERROR (18) + +/// +/// The protocol has not been started. +/// +#define RETURN_NOT_STARTED ENCODE_ERROR (19) + +/// +/// The protocol has already been started. +/// +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) + +/// +/// The operation was aborted. +/// +#define RETURN_ABORTED ENCODE_ERROR (21) + +/// +/// An ICMP error occurred during the network operation. +/// +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) + +/// +/// A TFTP error occurred during the network operation. +/// +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) + +/// +/// A protocol error occurred during the network operation. +/// +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) + +/// +/// A function encountered an internal version that was +/// incompatible with a version requested by the caller. +/// +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) + +/// +/// The function was not performed due to a security violation. +/// +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) + +/// +/// A CRC error was detected. +/// +#define RETURN_CRC_ERROR ENCODE_ERROR (27) + +/// +/// The beginning or end of media was reached. +/// +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) + +/// +/// The end of the file was reached. +/// +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +/// +/// The language specified was invalid. +/// +#define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) + +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) + +/// +/// A HTTP error occurred during the network operation. +/// +#define RETURN_HTTP_ERROR ENCODE_ERROR (35) + +/// +/// The string contained one or more characters that +/// the device could not render and were skipped. +/// +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) + +/// +/// The handle was closed, but the file was not deleted. +/// +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) + +/// +/// The handle was closed, but the data to the file was not +/// flushed properly. +/// +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) + +/// +/// The resulting buffer was too small, and the data was +/// truncated to the buffer size. +/// +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + +/// +/// The resulting buffer contains UEFI-compliant file system. +/// +#define RETURN_WARN_FILE_SYSTEM ENCODE_WARNING (6) + + +/** + Returns a 16-bit signature built from 2 ASCII characters. + + This macro returns a 16-bit value built from the two ASCII characters specified + by A and B. + + @param A The first ASCII character. + @param B The second ASCII character. + + @return A 16-bit value built from the two ASCII characters specified by A and B. + +**/ +#define SIGNATURE_16(A, B) ((A) | (B << 8)) + +/** + Returns a 32-bit signature built from 4 ASCII characters. + + This macro returns a 32-bit value built from the four ASCII characters specified + by A, B, C, and D. + + @param A The first ASCII character. + @param B The second ASCII character. + @param C The third ASCII character. + @param D The fourth ASCII character. + + @return A 32-bit value built from the two ASCII characters specified by A, B, + C and D. + +**/ +#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) + +/** + Returns a 64-bit signature built from 8 ASCII characters. + + This macro returns a 64-bit value built from the eight ASCII characters specified + by A, B, C, D, E, F, G,and H. + + @param A The first ASCII character. + @param B The second ASCII character. + @param C The third ASCII character. + @param D The fourth ASCII character. + @param E The fifth ASCII character. + @param F The sixth ASCII character. + @param G The seventh ASCII character. + @param H The eighth ASCII character. + + @return A 64-bit value built from the two ASCII characters specified by A, B, + C, D, E, F, G and H. + +**/ +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) + +#if defined(_MSC_EXTENSIONS) && !defined (__INTEL_COMPILER) && !defined (MDE_CPU_EBC) + void * _ReturnAddress(void); + #pragma intrinsic(_ReturnAddress) + /** + Get the return address of the calling function. + + Based on intrinsic function _ReturnAddress that provides the address of + the instruction in the calling function that will be executed after + control returns to the caller. + + @param L Return Level. + + @return The return address of the calling function or 0 if L != 0. + + **/ + #define RETURN_ADDRESS(L) ((L == 0) ? _ReturnAddress() : (VOID *) 0) +#elif defined(__GNUC__) + void * __builtin_return_address (unsigned int level); + /** + Get the return address of the calling function. + + Based on built-in Function __builtin_return_address that returns + the return address of the current function, or of one of its callers. + + @param L Return Level. + + @return The return address of the calling function. + + **/ + #define RETURN_ADDRESS(L) __builtin_return_address (L) +#else + /** + Get the return address of the calling function. + + @param L Return Level. + + @return 0 as compilers don't support this feature. + + **/ + #define RETURN_ADDRESS(L) ((VOID *) 0) +#endif + +/** + Return the number of elements in an array. + + @param Array An object of array type. Array is only used as an argument to + the sizeof operator, therefore Array is never evaluated. The + caller is responsible for ensuring that Array's type is not + incomplete; that is, Array must have known constant size. + + @return The number of elements in Array. The result has type UINTN. + +**/ +#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0])) + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ebc/ProcessorBind.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ebc/ProcessorBind.h new file mode 100644 index 0000000..4ccc4d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ebc/ProcessorBind.h @@ -0,0 +1,162 @@ +/** @file + Processor or compiler specific defines and types for EBC. + + We currently only have one EBC compiler so there may be some Intel compiler + specific functions in this file. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_EBC + +// +// Native integer types +// + +/// +/// 1-byte signed value +/// +typedef signed char INT8; +/// +/// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other +/// values are undefined. +/// +typedef unsigned char BOOLEAN; +/// +/// 1-byte unsigned value. +/// +typedef unsigned char UINT8; +/// +/// 1-byte Character. +/// +typedef char CHAR8; +/// +/// 2-byte signed value. +/// +typedef short INT16; +/// +/// 2-byte unsigned value. +/// +typedef unsigned short UINT16; +/// +/// 2-byte Character. Unless otherwise specified all strings are stored in the +/// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. +/// +typedef unsigned short CHAR16; +/// +/// 4-byte signed value. +/// +typedef int INT32; +/// +/// 4-byte unsigned value. +/// +typedef unsigned int UINT32; +/// +/// 8-byte signed value. +/// +typedef __int64 INT64; +/// +/// 8-byte unsigned value. +/// +typedef unsigned __int64 UINT64; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// "long" type scales to the processor native size with EBC compiler +/// +typedef long INTN; +/// +/// The unsigned value of native width. (4 bytes on supported 32-bit processor instructions; +/// 8 bytes on supported 64-bit processor instructions) +/// "long" type scales to the processor native size with the EBC compiler. +/// +typedef unsigned long UINTN; + +/// +/// A value of native width with the highest bit set. +/// Scalable macro to set the most significant bit in a natural number. +/// +#define MAX_BIT ((UINTN)((1ULL << (sizeof (INTN) * 8 - 1)))) +/// +/// A value of native width with the two highest bits set. +/// Scalable macro to set the most 2 significant bits in a natural number. +/// +#define MAX_2_BITS ((UINTN)(3ULL << (sizeof (INTN) * 8 - 2))) + +/// +/// Maximum legal EBC address +/// +#define MAX_ADDRESS ((UINTN)(~0ULL >> (64 - sizeof (INTN) * 8))) + +/// +/// Maximum usable address at boot time (48 bits using 4 KB pages) +/// +#define MAX_ALLOC_ADDRESS MAX_ADDRESS + +/// +/// Maximum legal EBC INTN and UINTN values. +/// +#define MAX_UINTN ((UINTN)(~0ULL >> (64 - sizeof (INTN) * 8))) +#define MAX_INTN ((INTN)(~0ULL >> (65 - sizeof (INTN) * 8))) + +/// +/// Minimum legal EBC INTN value. +/// +#define MIN_INTN (((INTN)-MAX_INTN) - 1) + +/// +/// The stack alignment required for EBC +/// +#define CPU_STACK_ALIGNMENT sizeof(UINTN) + +/// +/// Page allocation granularity for EBC +/// +#define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000) +#define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x1000) + +/// +/// Modifier to ensure that all protocol member functions and EFI intrinsics +/// use the correct C calling convention. All protocol member functions and +/// EFI intrinsics are required to modify their member functions with EFIAPI. +/// +#ifdef EFIAPI + /// + /// If EFIAPI is already defined, then we use that definition. + /// +#else +#define EFIAPI +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On EBC architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Acpi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Acpi.h new file mode 100644 index 0000000..06e3c32 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Acpi.h @@ -0,0 +1,46 @@ +/** @file + GUIDs used for ACPI entries in the EFI system table + + These GUIDs point the ACPI tables as defined in the ACPI specifications. + ACPI 2.0 specification defines the ACPI 2.0 GUID. UEFI 2.0 defines the + ACPI 2.0 Table GUID and ACPI Table GUID. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __ACPI_GUID_H__ +#define __ACPI_GUID_H__ + +#define ACPI_TABLE_GUID \ + { \ + 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_ACPI_TABLE_GUID \ + { \ + 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define ACPI_10_TABLE_GUID ACPI_TABLE_GUID + +// +// ACPI 2.0 or newer tables should use EFI_ACPI_TABLE_GUID. +// +#define EFI_ACPI_20_TABLE_GUID EFI_ACPI_TABLE_GUID + +extern EFI_GUID gEfiAcpiTableGuid; +extern EFI_GUID gEfiAcpi10TableGuid; +extern EFI_GUID gEfiAcpi20TableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Apriori.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Apriori.h new file mode 100644 index 0000000..b6eac82 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Apriori.h @@ -0,0 +1,30 @@ +/** @file + GUID used as an FV filename for A Priori file. The A Priori file contains a + list of FV filenames that the DXE dispatcher will schedule reguardless of + the dependency grammar. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID introduced in PI Version 1.0. + +**/ + +#ifndef __APRIORI_GUID_H__ +#define __APRIORI_GUID_H__ + +#define EFI_APRIORI_GUID \ + { \ + 0xfc510ee7, 0xffdc, 0x11d4, {0xbd, 0x41, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gAprioriGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/AprioriFileName.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/AprioriFileName.h new file mode 100644 index 0000000..af1873c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/AprioriFileName.h @@ -0,0 +1,44 @@ +/** @file + The GUID PEI_APRIORI_FILE_NAME_GUID definition is the file + name of the PEI a priori file that is stored in a firmware + volume. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID introduced in PI Version 1.0. + +**/ + +#ifndef __PEI_APRIORI_FILE_NAME_H__ +#define __PEI_APRIORI_FILE_NAME_H__ + +#define PEI_APRIORI_FILE_NAME_GUID \ + { 0x1b45cc0a, 0x156a, 0x428a, { 0x62, 0XAF, 0x49, 0x86, 0x4d, 0xa0, 0xe6, 0xe6 } } + + +/// +/// This file must be of type EFI_FV_FILETYPE_FREEFORM and must +/// contain a single section of type EFI_SECTION_RAW. For details on +/// firmware volumes, firmware file types, and firmware file section +/// types. +/// +typedef struct { + /// + /// An array of zero or more EFI_GUID type entries that match the file names of PEIM + /// modules in the same Firmware Volume. The maximum number of entries. + /// + EFI_GUID FileNamesWithinVolume[1]; +} PEI_APRIORI_FILE_CONTENTS; + +extern EFI_GUID gPeiAprioriFileNameGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Btt.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Btt.h new file mode 100644 index 0000000..e637614 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Btt.h @@ -0,0 +1,228 @@ +/** @file + Block Translation Table (BTT) metadata layout definition. + + BTT is a layout and set of rules for doing block I/O that provide powerfail + write atomicity of a single block. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This metadata layout definition was introduced in UEFI Specification 2.7. + +**/ + +#ifndef _BTT_H_ +#define _BTT_H_ + +/// +/// The BTT layout and behavior is described by the GUID as below. +/// +#define EFI_BTT_ABSTRACTION_GUID \ + { \ + 0x18633bfc, 0x1735, 0x4217, { 0x8a, 0xc9, 0x17, 0x23, 0x92, 0x82, 0xd3, 0xf8 } \ + } + +// +// Alignment of all BTT structures +// +#define EFI_BTT_ALIGNMENT 4096 + +#define EFI_BTT_INFO_UNUSED_LEN 3968 + +#define EFI_BTT_INFO_BLOCK_SIG_LEN 16 + +/// +/// Indicate inconsistent metadata or lost metadata due to unrecoverable media errors. +/// +#define EFI_BTT_INFO_BLOCK_FLAGS_ERROR 0x00000001 + +#define EFI_BTT_INFO_BLOCK_MAJOR_VERSION 2 +#define EFI_BTT_INFO_BLOCK_MINOR_VERSION 0 + +/// +/// Block Translation Table (BTT) Info Block +/// +typedef struct _EFI_BTT_INFO_BLOCK { + /// + /// Signature of the BTT Index Block data structure. + /// Shall be "BTT_ARENA_INFO\0\0". + /// + CHAR8 Sig[EFI_BTT_INFO_BLOCK_SIG_LEN]; + + /// + /// UUID identifying this BTT instance. + /// + GUID Uuid; + + /// + /// UUID of containing namespace. + /// + GUID ParentUuid; + + /// + /// Attributes of this BTT Info Block. + /// + UINT32 Flags; + + /// + /// Major version number. Currently at version 2. + /// + UINT16 Major; + + /// + /// Minor version number. Currently at version 0. + /// + UINT16 Minor; + + /// + /// Advertised LBA size in bytes. I/O requests shall be in this size chunk. + /// + UINT32 ExternalLbaSize; + + /// + /// Advertised number of LBAs in this arena. + /// + UINT32 ExternalNLba; + + /// + /// Internal LBA size shall be greater than or equal to ExternalLbaSize and shall not be smaller than 512 bytes. + /// + UINT32 InternalLbaSize; + + /// + /// Number of internal blocks in the arena data area. + /// + UINT32 InternalNLba; + + /// + /// Number of free blocks maintained for writes to this arena. + /// + UINT32 NFree; + + /// + /// The size of this info block in bytes. + /// + UINT32 InfoSize; + + /// + /// Offset of next arena, relative to the beginning of this arena. + /// + UINT64 NextOff; + + /// + /// Offset of the data area for this arena, relative to the beginning of this arena. + /// + UINT64 DataOff; + + /// + /// Offset of the map for this arena, relative to the beginning of this arena. + /// + UINT64 MapOff; + + /// + /// Offset of the flog for this arena, relative to the beginning of this arena. + /// + UINT64 FlogOff; + + /// + /// Offset of the backup copy of this arena's info block, relative to the beginning of this arena. + /// + UINT64 InfoOff; + + /// + /// Shall be zero. + /// + CHAR8 Unused[EFI_BTT_INFO_UNUSED_LEN]; + + /// + /// 64-bit Fletcher64 checksum of all fields. + /// + UINT64 Checksum; +} EFI_BTT_INFO_BLOCK; + +/// +/// BTT Map entry maps an LBA that indexes into the arena, to its actual location. +/// +typedef struct _EFI_BTT_MAP_ENTRY { + /// + /// Post-map LBA number (block number in this arena's data area) + /// + UINT32 PostMapLba : 30; + + /// + /// When set and Zero is not set, reads on this block return an error. + /// When set and Zero is set, indicate a map entry in its normal, non-error state. + /// + UINT32 Error : 1; + + /// + /// When set and Error is not set, reads on this block return a full block of zeros. + /// When set and Error is set, indicate a map entry in its normal, non-error state. + /// + UINT32 Zero : 1; +} EFI_BTT_MAP_ENTRY; + +/// +/// Alignment of each flog structure +/// +#define EFI_BTT_FLOG_ENTRY_ALIGNMENT 64 + +/// +/// The BTT Flog is both a free list and a log. +/// The Flog size is determined by the EFI_BTT_INFO_BLOCK.NFree which determines how many of these flog +/// entries there are. +/// The Flog location is the highest aligned address in the arena after space for the backup info block. +/// +typedef struct _EFI_BTT_FLOG { + /// + /// Last pre-map LBA written using this flog entry. + /// + UINT32 Lba0; + + /// + /// Old post-map LBA. + /// + UINT32 OldMap0; + + /// + /// New post-map LBA. + /// + UINT32 NewMap0; + + /// + /// The Seq0 field in each flog entry is used to determine which set of fields is newer between the two sets + /// (Lba0, OldMap0, NewMpa0, Seq0 vs Lba1, Oldmap1, NewMap1, Seq1). + /// + UINT32 Seq0; + + /// + /// Alternate lba entry. + /// + UINT32 Lba1; + + /// + /// Alternate old entry. + /// + UINT32 OldMap1; + + /// + /// Alternate new entry. + /// + UINT32 NewMap1; + + /// + /// Alternate Seq entry. + /// + UINT32 Seq1; +} EFI_BTT_FLOG; + +extern GUID gEfiBttAbstractionGuid; + +#endif //_BTT_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/CapsuleReport.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/CapsuleReport.h new file mode 100644 index 0000000..11b9b38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/CapsuleReport.h @@ -0,0 +1,105 @@ +/** @file + Guid & data structure used for Capsule process result variables + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.4 spec. + +**/ + + +#ifndef _CAPSULE_REPORT_GUID_H__ +#define _CAPSULE_REPORT_GUID_H__ + +// +// This is the GUID for capsule result variable. +// +#define EFI_CAPSULE_REPORT_GUID \ + { \ + 0x39b68c46, 0xf7fb, 0x441b, {0xb6, 0xec, 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3 } \ + } + + +typedef struct { + + /// + /// Size in bytes of the variable including any data beyond header as specified by CapsuleGuid + /// + UINT32 VariableTotalSize; + + /// + /// For alignment + /// + UINT32 Reserved; + + /// + /// Guid from EFI_CAPSULE_HEADER + /// + EFI_GUID CapsuleGuid; + + /// + /// Timestamp using system time when processing completed + /// + EFI_TIME CapsuleProcessed; + + /// + /// Result of the capsule processing. Exact interpretation of any error code may depend + /// upon type of capsule processed + /// + EFI_STATUS CapsuleStatus; +} EFI_CAPSULE_RESULT_VARIABLE_HEADER; + + +typedef struct { + + /// + /// Version of this structure, currently 0x00000001 + /// + UINT16 Version; + + /// + /// The index of the payload within the FMP capsule which was processed to generate this report + /// Starting from zero + /// + UINT8 PayloadIndex; + + /// + /// The UpdateImageIndex from EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER + /// (after unsigned conversion from UINT8 to UINT16). + /// + UINT8 UpdateImageIndex; + + /// + /// The UpdateImageTypeId Guid from EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER. + /// + EFI_GUID UpdateImageTypeId; + + /// + /// In case of capsule loaded from disk, the zero-terminated array containing file name of capsule that was processed. + /// In case of capsule submitted directly to UpdateCapsule() there is no file name, and this field is required to contain a single 16-bit zero character + /// which is included in VariableTotalSize. + /// + /// CHAR16 CapsuleFileName[]; + /// + + /// + /// This field will contain a zero-terminated CHAR16 string containing the text representation of the device path of device publishing Firmware Management Protocol + /// (if present). In case where device path is not present and the target is not otherwise known to firmware, or when payload was blocked by policy, or skipped, + /// this field is required to contain a single 16-bit zero character which is included in VariableTotalSize. + /// + /// CHAR16 CapsuleTarget[]; + /// +} EFI_CAPSULE_RESULT_VARIABLE_FMP; + + +extern EFI_GUID gEfiCapsuleReportGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Cper.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Cper.h new file mode 100644 index 0000000..ca919e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Cper.h @@ -0,0 +1,1243 @@ +/** @file + GUIDs and definitions used for Common Platform Error Record. + + Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.7 Specification. + +**/ + +#ifndef __CPER_GUID_H__ +#define __CPER_GUID_H__ + +#pragma pack(1) + +#define EFI_ERROR_RECORD_SIGNATURE_START SIGNATURE_32('C', 'P', 'E', 'R') +#define EFI_ERROR_RECORD_SIGNATURE_END 0xFFFFFFFF + +#define EFI_ERROR_RECORD_REVISION 0x0101 + +/// +/// Error Severity in Error Record Header and Error Section Descriptor +///@{ +#define EFI_GENERIC_ERROR_RECOVERABLE 0x00000000 +#define EFI_GENERIC_ERROR_FATAL 0x00000001 +#define EFI_GENERIC_ERROR_CORRECTED 0x00000002 +#define EFI_GENERIC_ERROR_INFO 0x00000003 +///@} + +/// +/// The validation bit mask indicates the validity of the following fields +/// in Error Record Header. +///@{ +#define EFI_ERROR_RECORD_HEADER_PLATFORM_ID_VALID BIT0 +#define EFI_ERROR_RECORD_HEADER_TIME_STAMP_VALID BIT1 +#define EFI_ERROR_RECORD_HEADER_PARTITION_ID_VALID BIT2 +///@} + +/// +/// Timestamp is precise if this bit is set and correlates to the time of the +/// error event. +/// +#define EFI_ERROR_TIME_STAMP_PRECISE BIT0 + +/// +/// The timestamp correlates to the time when the error information was collected +/// by the system software and may not necessarily represent the time of the error +/// event. The timestamp contains the local time in BCD format. +/// +typedef struct { + UINT8 Seconds; + UINT8 Minutes; + UINT8 Hours; + UINT8 Flag; + UINT8 Day; + UINT8 Month; + UINT8 Year; + UINT8 Century; +} EFI_ERROR_TIME_STAMP; + +/// +/// GUID value indicating the record association with an error event notification type. +///@{ +#define EFI_EVENT_NOTIFICATION_TYEP_CMC_GUID \ + { \ + 0x2DCE8BB1, 0xBDD7, 0x450e, { 0xB9, 0xAD, 0x9C, 0xF4, 0xEB, 0xD4, 0xF8, 0x90 } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_CPE_GUID \ + { \ + 0x4E292F96, 0xD843, 0x4a55, { 0xA8, 0xC2, 0xD4, 0x81, 0xF2, 0x7E, 0xBE, 0xEE } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_MCE_GUID \ + { \ + 0xE8F56FFE, 0x919C, 0x4cc5, { 0xBA, 0x88, 0x65, 0xAB, 0xE1, 0x49, 0x13, 0xBB } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_PCIE_GUID \ + { \ + 0xCF93C01F, 0x1A16, 0x4dfc, { 0xB8, 0xBC, 0x9C, 0x4D, 0xAF, 0x67, 0xC1, 0x04 } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_INIT_GUID \ + { \ + 0xCC5263E8, 0x9308, 0x454a, { 0x89, 0xD0, 0x34, 0x0B, 0xD3, 0x9B, 0xC9, 0x8E } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_NMI_GUID \ + { \ + 0x5BAD89FF, 0xB7E6, 0x42c9, { 0x81, 0x4A, 0xCF, 0x24, 0x85, 0xD6, 0xE9, 0x8A } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_BOOT_GUID \ + { \ + 0x3D61A466, 0xAB40, 0x409a, { 0xA6, 0x98, 0xF3, 0x62, 0xD4, 0x64, 0xB3, 0x8F } \ + } +#define EFI_EVENT_NOTIFICATION_TYEP_DMAR_GUID \ + { \ + 0x667DD791, 0xC6B3, 0x4c27, { 0x8A, 0x6B, 0x0F, 0x8E, 0x72, 0x2D, 0xEB, 0x41 } \ + } +///@} + +/// +/// Error Record Header Flags +///@{ +#define EFI_HW_ERROR_FLAGS_RECOVERED 0x00000001 +#define EFI_HW_ERROR_FLAGS_PREVERR 0x00000002 +#define EFI_HW_ERROR_FLAGS_SIMULATED 0x00000004 +///@} + +/// +/// Common error record header +/// +typedef struct { + UINT32 SignatureStart; + UINT16 Revision; + UINT32 SignatureEnd; + UINT16 SectionCount; + UINT32 ErrorSeverity; + UINT32 ValidationBits; + UINT32 RecordLength; + EFI_ERROR_TIME_STAMP TimeStamp; + EFI_GUID PlatformID; + EFI_GUID PartitionID; + EFI_GUID CreatorID; + EFI_GUID NotificationType; + UINT64 RecordID; + UINT32 Flags; + UINT64 PersistenceInfo; + UINT8 Resv1[12]; + /// + /// An array of SectionCount descriptors for the associated + /// sections. The number of valid sections is equivalent to the + /// SectionCount. The buffer size of the record may include + /// more space to dynamically add additional Section + /// Descriptors to the error record. + /// +} EFI_COMMON_ERROR_RECORD_HEADER; + +#define EFI_ERROR_SECTION_REVISION 0x0100 + +/// +/// Validity Fields in Error Section Descriptor. +/// +#define EFI_ERROR_SECTION_FRU_ID_VALID BIT0 +#define EFI_ERROR_SECTION_FRU_STRING_VALID BIT1 + +/// +/// Flag field contains information that describes the error section +/// in Error Section Descriptor. +/// +#define EFI_ERROR_SECTION_FLAGS_PRIMARY BIT0 +#define EFI_ERROR_SECTION_FLAGS_CONTAINMENT_WARNING BIT1 +#define EFI_ERROR_SECTION_FLAGS_RESET BIT2 +#define EFI_ERROR_SECTION_FLAGS_ERROR_THRESHOLD_EXCEEDED BIT3 +#define EFI_ERROR_SECTION_FLAGS_RESOURCE_NOT_ACCESSIBLE BIT4 +#define EFI_ERROR_SECTION_FLAGS_LATENT_ERROR BIT5 + +/// +/// Error Sectition Type GUIDs in Error Section Descriptor +///@{ +#define EFI_ERROR_SECTION_PROCESSOR_GENERIC_GUID \ + { \ + 0x9876ccad, 0x47b4, 0x4bdb, { 0xb6, 0x5e, 0x16, 0xf1, 0x93, 0xc4, 0xf3, 0xdb } \ + } +#define EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_GUID \ + { \ + 0xdc3ea0b0, 0xa144, 0x4797, { 0xb9, 0x5b, 0x53, 0xfa, 0x24, 0x2b, 0x6e, 0x1d } \ + } +#define EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_IA32X64_GUID \ + { \ + 0xdc3ea0b0, 0xa144, 0x4797, { 0xb9, 0x5b, 0x53, 0xfa, 0x24, 0x2b, 0x6e, 0x1d } \ + } +#define EFI_ERROR_SECTION_PROCESSOR_SPECIFIC_ARM_GUID \ + { \ + 0xe19e3d16, 0xbc11, 0x11e4, { 0x9c, 0xaa, 0xc2, 0x05, 0x1d, 0x5d, 0x46, 0xb0 } \ + } +#define EFI_ERROR_SECTION_PLATFORM_MEMORY_GUID \ + { \ + 0xa5bc1114, 0x6f64, 0x4ede, { 0xb8, 0x63, 0x3e, 0x83, 0xed, 0x7c, 0x83, 0xb1 } \ + } +#define EFI_ERROR_SECTION_PLATFORM_MEMORY2_GUID \ + { \ + 0x61EC04FC, 0x48E6, 0xD813, { 0x25, 0xC9, 0x8D, 0xAA, 0x44, 0x75, 0x0B, 0x12 } \ + } +#define EFI_ERROR_SECTION_PCIE_GUID \ + { \ + 0xd995e954, 0xbbc1, 0x430f, { 0xad, 0x91, 0xb4, 0x4d, 0xcb, 0x3c, 0x6f, 0x35 } \ + } +#define EFI_ERROR_SECTION_FW_ERROR_RECORD_GUID \ + { \ + 0x81212a96, 0x09ed, 0x4996, { 0x94, 0x71, 0x8d, 0x72, 0x9c, 0x8e, 0x69, 0xed } \ + } +#define EFI_ERROR_SECTION_PCI_PCIX_BUS_GUID \ + { \ + 0xc5753963, 0x3b84, 0x4095, { 0xbf, 0x78, 0xed, 0xda, 0xd3, 0xf9, 0xc9, 0xdd } \ + } +#define EFI_ERROR_SECTION_PCI_DEVICE_GUID \ + { \ + 0xeb5e4685, 0xca66, 0x4769, { 0xb6, 0xa2, 0x26, 0x06, 0x8b, 0x00, 0x13, 0x26 } \ + } +#define EFI_ERROR_SECTION_DMAR_GENERIC_GUID \ + { \ + 0x5b51fef7, 0xc79d, 0x4434, { 0x8f, 0x1b, 0xaa, 0x62, 0xde, 0x3e, 0x2c, 0x64 } \ + } +#define EFI_ERROR_SECTION_DIRECTED_IO_DMAR_GUID \ + { \ + 0x71761d37, 0x32b2, 0x45cd, { 0xa7, 0xd0, 0xb0, 0xfe, 0xdd, 0x93, 0xe8, 0xcf } \ + } +#define EFI_ERROR_SECTION_IOMMU_DMAR_GUID \ + { \ + 0x036f84e1, 0x7f37, 0x428c, { 0xa7, 0x9e, 0x57, 0x5f, 0xdf, 0xaa, 0x84, 0xec } \ + } +///@} + +/// +/// Error Section Descriptor +/// +typedef struct { + UINT32 SectionOffset; + UINT32 SectionLength; + UINT16 Revision; + UINT8 SecValidMask; + UINT8 Resv1; + UINT32 SectionFlags; + EFI_GUID SectionType; + EFI_GUID FruId; + UINT32 Severity; + CHAR8 FruString[20]; +} EFI_ERROR_SECTION_DESCRIPTOR; + +/// +/// The validation bit mask indicates whether or not each of the following fields are +/// valid in Proessor Generic Error section. +///@{ +#define EFI_GENERIC_ERROR_PROC_TYPE_VALID BIT0 +#define EFI_GENERIC_ERROR_PROC_ISA_VALID BIT1 +#define EFI_GENERIC_ERROR_PROC_ERROR_TYPE_VALID BIT2 +#define EFI_GENERIC_ERROR_PROC_OPERATION_VALID BIT3 +#define EFI_GENERIC_ERROR_PROC_FLAGS_VALID BIT4 +#define EFI_GENERIC_ERROR_PROC_LEVEL_VALID BIT5 +#define EFI_GENERIC_ERROR_PROC_VERSION_VALID BIT6 +#define EFI_GENERIC_ERROR_PROC_BRAND_VALID BIT7 +#define EFI_GENERIC_ERROR_PROC_ID_VALID BIT8 +#define EFI_GENERIC_ERROR_PROC_TARGET_ADDR_VALID BIT9 +#define EFI_GENERIC_ERROR_PROC_REQUESTER_ID_VALID BIT10 +#define EFI_GENERIC_ERROR_PROC_RESPONDER_ID_VALID BIT11 +#define EFI_GENERIC_ERROR_PROC_INST_IP_VALID BIT12 +///@} + +/// +/// The type of the processor architecture in Proessor Generic Error section. +///@{ +#define EFI_GENERIC_ERROR_PROC_TYPE_IA32_X64 0x00 +#define EFI_GENERIC_ERROR_PROC_TYPE_IA64 0x01 +#define EFI_GENERIC_ERROR_PROC_TYPE_ARM 0x02 +///@} + +/// +/// The type of the instruction set executing when the error occurred in Proessor +/// Generic Error section. +///@{ +#define EFI_GENERIC_ERROR_PROC_ISA_IA32 0x00 +#define EFI_GENERIC_ERROR_PROC_ISA_IA64 0x01 +#define EFI_GENERIC_ERROR_PROC_ISA_X64 0x02 +#define EFI_GENERIC_ERROR_PROC_ISA_ARM_A32_T32 0x03 +#define EFI_GENERIC_ERROR_PROC_ISA_ARM_A64 0x04 +///@} + +/// +/// The type of error that occurred in Proessor Generic Error section. +///@{ +#define EFI_GENERIC_ERROR_PROC_ERROR_TYPE_UNKNOWN 0x00 +#define EFI_GENERIC_ERROR_PROC_ERROR_TYPE_CACHE 0x01 +#define EFI_GENERIC_ERROR_PROC_ERROR_TYPE_TLB 0x02 +#define EFI_GENERIC_ERROR_PROC_ERROR_TYPE_BUS 0x04 +#define EFI_GENERIC_ERROR_PROC_ERROR_TYPE_MICRO_ARCH 0x08 +///@} + +/// +/// The type of operation in Proessor Generic Error section. +///@{ +#define EFI_GENERIC_ERROR_PROC_OPERATION_GENERIC 0x00 +#define EFI_GENERIC_ERROR_PROC_OPERATION_DATA_READ 0x01 +#define EFI_GENERIC_ERROR_PROC_OPERATION_DATA_WRITE 0x02 +#define EFI_GENERIC_ERROR_PROC_OPERATION_INSTRUCTION_EXEC 0x03 +///@} + +/// +/// Flags bit mask indicates additional information about the error in Proessor Generic +/// Error section +///@{ +#define EFI_GENERIC_ERROR_PROC_FLAGS_RESTARTABLE BIT0 +#define EFI_GENERIC_ERROR_PROC_FLAGS_PRECISE_IP BIT1 +#define EFI_GENERIC_ERROR_PROC_FLAGS_OVERFLOW BIT2 +#define EFI_GENERIC_ERROR_PROC_FLAGS_CORRECTED BIT3 +///@} + +/// +/// Processor Generic Error Section +/// describes processor reported hardware errors for logical processors in the system. +/// +typedef struct { + UINT64 ValidFields; + UINT8 Type; + UINT8 Isa; + UINT8 ErrorType; + UINT8 Operation; + UINT8 Flags; + UINT8 Level; + UINT16 Resv1; + UINT64 VersionInfo; + CHAR8 BrandString[128]; + UINT64 ApicId; + UINT64 TargetAddr; + UINT64 RequestorId; + UINT64 ResponderId; + UINT64 InstructionIP; +} EFI_PROCESSOR_GENERIC_ERROR_DATA; + + +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) +/// +/// IA32 and x64 Specific definitions. +/// + +/// +/// GUID value indicating the type of Processor Error Information structure +/// in IA32/X64 Processor Error Information Structure. +///@{ +#define EFI_IA32_X64_ERROR_TYPE_CACHE_CHECK_GUID \ + { \ + 0xA55701F5, 0xE3EF, 0x43de, {0xAC, 0x72, 0x24, 0x9B, 0x57, 0x3F, 0xAD, 0x2C } \ + } +#define EFI_IA32_X64_ERROR_TYPE_TLB_CHECK_GUID \ + { \ + 0xFC06B535, 0x5E1F, 0x4562, {0x9F, 0x25, 0x0A, 0x3B, 0x9A, 0xDB, 0x63, 0xC3 } \ + } +#define EFI_IA32_X64_ERROR_TYPE_BUS_CHECK_GUID \ + { \ + 0x1CF3F8B3, 0xC5B1, 0x49a2, {0xAA, 0x59, 0x5E, 0xEF, 0x92, 0xFF, 0xA6, 0x3C } \ + } +#define EFI_IA32_X64_ERROR_TYPE_MS_CHECK_GUID \ + { \ + 0x48AB7F57, 0xDC34, 0x4f6c, {0xA7, 0xD3, 0xB0, 0xB5, 0xB0, 0xA7, 0x43, 0x14 } \ + } +///@} + +/// +/// The validation bit mask indicates which fields in the IA32/X64 Processor +/// Error Record structure are valid. +///@{ +#define EFI_IA32_X64_PROCESSOR_ERROR_APIC_ID_VALID BIT0 +#define EFI_IA32_X64_PROCESSOR_ERROR_CPU_ID_INFO_VALID BIT1 +///@} + +/// +/// IA32/X64 Processor Error Record +/// +typedef struct { + UINT64 ValidFields; + UINT64 ApicId; + UINT8 CpuIdInfo[48]; +} EFI_IA32_X64_PROCESSOR_ERROR_RECORD; + +/// +/// The validation bit mask indicates which fields in the Cache Check structure +/// are valid. +///@{ +#define EFI_CACHE_CHECK_TRANSACTION_TYPE_VALID BIT0 +#define EFI_CACHE_CHECK_OPERATION_VALID BIT1 +#define EFI_CACHE_CHECK_LEVEL_VALID BIT2 +#define EFI_CACHE_CHECK_CONTEXT_CORRUPT_VALID BIT3 +#define EFI_CACHE_CHECK_UNCORRECTED_VALID BIT4 +#define EFI_CACHE_CHECK_PRECISE_IP_VALID BIT5 +#define EFI_CACHE_CHECK_RESTARTABLE_VALID BIT6 +#define EFI_CACHE_CHECK_OVERFLOW_VALID BIT7 +///@} + +/// +/// Type of cache error in the Cache Check structure +///@{ +#define EFI_CACHE_CHECK_ERROR_TYPE_INSTRUCTION 0 +#define EFI_CACHE_CHECK_ERROR_TYPE_DATA_ACCESS 1 +#define EFI_CACHE_CHECK_ERROR_TYPE_GENERIC 2 +///@} + +/// +/// Type of cache operation that caused the error in the Cache +/// Check structure +///@{ +#define EFI_CACHE_CHECK_OPERATION_TYPE_GENERIC 0 +#define EFI_CACHE_CHECK_OPERATION_TYPE_GENERIC_READ 1 +#define EFI_CACHE_CHECK_OPERATION_TYPE_GENERIC_WRITE 2 +#define EFI_CACHE_CHECK_OPERATION_TYPE_DATA_READ 3 +#define EFI_CACHE_CHECK_OPERATION_TYPE_DATA_WRITE 4 +#define EFI_CACHE_CHECK_OPERATION_TYPE_INSTRUCTION_FETCH 5 +#define EFI_CACHE_CHECK_OPERATION_TYPE_PREFETCH 6 +#define EFI_CACHE_CHECK_OPERATION_TYPE_EVICTION 7 +#define EFI_CACHE_CHECK_OPERATION_TYPE_SNOOP 8 +///@} + +/// +/// IA32/X64 Cache Check Structure +/// +typedef struct { + UINT64 ValidFields:16; + UINT64 TransactionType:2; + UINT64 Operation:4; + UINT64 Level:3; + UINT64 ContextCorrupt:1; + UINT64 ErrorUncorrected:1; + UINT64 PreciseIp:1; + UINT64 RestartableIp:1; + UINT64 Overflow:1; + UINT64 Resv1:34; +} EFI_IA32_X64_CACHE_CHECK_INFO; + +/// +/// The validation bit mask indicates which fields in the TLB Check structure +/// are valid. +///@{ +#define EFI_TLB_CHECK_TRANSACTION_TYPE_VALID BIT0 +#define EFI_TLB_CHECK_OPERATION_VALID BIT1 +#define EFI_TLB_CHECK_LEVEL_VALID BIT2 +#define EFI_TLB_CHECK_CONTEXT_CORRUPT_VALID BIT3 +#define EFI_TLB_CHECK_UNCORRECTED_VALID BIT4 +#define EFI_TLB_CHECK_PRECISE_IP_VALID BIT5 +#define EFI_TLB_CHECK_RESTARTABLE_VALID BIT6 +#define EFI_TLB_CHECK_OVERFLOW_VALID BIT7 +///@} + +/// +/// Type of cache error in the TLB Check structure +///@{ +#define EFI_TLB_CHECK_ERROR_TYPE_INSTRUCTION 0 +#define EFI_TLB_CHECK_ERROR_TYPE_DATA_ACCESS 1 +#define EFI_TLB_CHECK_ERROR_TYPE_GENERIC 2 +///@} + +/// +/// Type of cache operation that caused the error in the TLB +/// Check structure +///@{ +#define EFI_TLB_CHECK_OPERATION_TYPE_GENERIC 0 +#define EFI_TLB_CHECK_OPERATION_TYPE_GENERIC_READ 1 +#define EFI_TLB_CHECK_OPERATION_TYPE_GENERIC_WRITE 2 +#define EFI_TLB_CHECK_OPERATION_TYPE_DATA_READ 3 +#define EFI_TLB_CHECK_OPERATION_TYPE_DATA_WRITE 4 +#define EFI_TLB_CHECK_OPERATION_TYPE_INST_FETCH 5 +#define EFI_TLB_CHECK_OPERATION_TYPE_PREFETCH 6 +///@} + +/// +/// IA32/X64 TLB Check Structure +/// +typedef struct { + UINT64 ValidFields:16; + UINT64 TransactionType:2; + UINT64 Operation:4; + UINT64 Level:3; + UINT64 ContextCorrupt:1; + UINT64 ErrorUncorrected:1; + UINT64 PreciseIp:1; + UINT64 RestartableIp:1; + UINT64 Overflow:1; + UINT64 Resv1:34; +} EFI_IA32_X64_TLB_CHECK_INFO; + +/// +/// The validation bit mask indicates which fields in the MS Check structure +/// are valid. +///@{ +#define EFI_BUS_CHECK_TRANSACTION_TYPE_VALID BIT0 +#define EFI_BUS_CHECK_OPERATION_VALID BIT1 +#define EFI_BUS_CHECK_LEVEL_VALID BIT2 +#define EFI_BUS_CHECK_CONTEXT_CORRUPT_VALID BIT3 +#define EFI_BUS_CHECK_UNCORRECTED_VALID BIT4 +#define EFI_BUS_CHECK_PRECISE_IP_VALID BIT5 +#define EFI_BUS_CHECK_RESTARTABLE_VALID BIT6 +#define EFI_BUS_CHECK_OVERFLOW_VALID BIT7 +#define EFI_BUS_CHECK_PARTICIPATION_TYPE_VALID BIT8 +#define EFI_BUS_CHECK_TIME_OUT_VALID BIT9 +#define EFI_BUS_CHECK_ADDRESS_SPACE_VALID BIT10 +///@} + +/// +/// Type of cache error in the Bus Check structure +///@{ +#define EFI_BUS_CHECK_ERROR_TYPE_INSTRUCTION 0 +#define EFI_BUS_CHECK_ERROR_TYPE_DATA_ACCESS 1 +#define EFI_BUS_CHECK_ERROR_TYPE_GENERIC 2 +///@} + +/// +/// Type of cache operation that caused the error in the Bus +/// Check structure +///@{ +#define EFI_BUS_CHECK_OPERATION_TYPE_GENERIC 0 +#define EFI_BUS_CHECK_OPERATION_TYPE_GENERIC_READ 1 +#define EFI_BUS_CHECK_OPERATION_TYPE_GENERIC_WRITE 2 +#define EFI_BUS_CHECK_OPERATION_TYPE_DATA_READ 3 +#define EFI_BUS_CHECK_OPERATION_TYPE_DATA_WRITE 4 +#define EFI_BUS_CHECK_OPERATION_TYPE_INST_FETCH 5 +#define EFI_BUS_CHECK_OPERATION_TYPE_PREFETCH 6 +///@} + +/// +/// Type of Participation +///@{ +#define EFI_BUS_CHECK_PARTICIPATION_TYPE_REQUEST 0 +#define EFI_BUS_CHECK_PARTICIPATION_TYPE_RESPONDED 1 +#define EFI_BUS_CHECK_PARTICIPATION_TYPE_OBSERVED 2 +#define EFI_BUS_CHECK_PARTICIPATION_TYPE_GENERIC 3 +///@} + +/// +/// Type of Address Space +///@{ +#define EFI_BUS_CHECK_ADDRESS_SPACE_TYPE_MEMORY 0 +#define EFI_BUS_CHECK_ADDRESS_SPACE_TYPE_RESERVED 1 +#define EFI_BUS_CHECK_ADDRESS_SPACE_TYPE_IO 2 +#define EFI_BUS_CHECK_ADDRESS_SPACE_TYPE_OTHER 3 +///@} + +/// +/// IA32/X64 Bus Check Structure +/// +typedef struct { + UINT64 ValidFields:16; + UINT64 TransactionType:2; + UINT64 Operation:4; + UINT64 Level:3; + UINT64 ContextCorrupt:1; + UINT64 ErrorUncorrected:1; + UINT64 PreciseIp:1; + UINT64 RestartableIp:1; + UINT64 Overflow:1; + UINT64 ParticipationType:2; + UINT64 TimeOut:1; + UINT64 AddressSpace:2; + UINT64 Resv1:29; +} EFI_IA32_X64_BUS_CHECK_INFO; + +/// +/// The validation bit mask indicates which fields in the MS Check structure +/// are valid. +///@{ +#define EFI_MS_CHECK_ERROR_TYPE_VALID BIT0 +#define EFI_MS_CHECK_CONTEXT_CORRUPT_VALID BIT1 +#define EFI_MS_CHECK_UNCORRECTED_VALID BIT2 +#define EFI_MS_CHECK_PRECISE_IP_VALID BIT3 +#define EFI_MS_CHECK_RESTARTABLE_VALID BIT4 +#define EFI_MS_CHECK_OVERFLOW_VALID BIT5 +///@} + +/// +/// Error type identifies the operation that caused the error. +///@{ +#define EFI_MS_CHECK_ERROR_TYPE_NO 0 +#define EFI_MS_CHECK_ERROR_TYPE_UNCLASSIFIED 1 +#define EFI_MS_CHECK_ERROR_TYPE_MICROCODE_PARITY 2 +#define EFI_MS_CHECK_ERROR_TYPE_EXTERNAL 3 +#define EFI_MS_CHECK_ERROR_TYPE_FRC 4 +#define EFI_MS_CHECK_ERROR_TYPE_INTERNAL_UNCLASSIFIED 5 +///@} + +/// +/// IA32/X64 MS Check Field Description +/// +typedef struct { + UINT64 ValidFields:16; + UINT64 ErrorType:3; + UINT64 ContextCorrupt:1; + UINT64 ErrorUncorrected:1; + UINT64 PreciseIp:1; + UINT64 RestartableIp:1; + UINT64 Overflow:1; + UINT64 Resv1:40; +} EFI_IA32_X64_MS_CHECK_INFO; + +/// +/// IA32/X64 Check Information Item +/// +typedef union { + EFI_IA32_X64_CACHE_CHECK_INFO CacheCheck; + EFI_IA32_X64_TLB_CHECK_INFO TlbCheck; + EFI_IA32_X64_BUS_CHECK_INFO BusCheck; + EFI_IA32_X64_MS_CHECK_INFO MsCheck; + UINT64 Data64; +} EFI_IA32_X64_CHECK_INFO_ITEM; + +/// +/// The validation bit mask indicates which fields in the IA32/X64 Processor Error +/// Information Structure are valid. +///@{ +#define EFI_IA32_X64_ERROR_PROC_CHECK_INFO_VALID BIT0 +#define EFI_IA32_X64_ERROR_PROC_TARGET_ADDR_VALID BIT1 +#define EFI_IA32_X64_ERROR_PROC_REQUESTER_ID_VALID BIT2 +#define EFI_IA32_X64_ERROR_PROC_RESPONDER_ID_VALID BIT3 +#define EFI_IA32_X64_ERROR_PROC_INST_IP_VALID BIT4 +///@} + +/// +/// IA32/X64 Processor Error Information Structure +/// +typedef struct { + EFI_GUID ErrorType; + UINT64 ValidFields; + EFI_IA32_X64_CHECK_INFO_ITEM CheckInfo; + UINT64 TargetId; + UINT64 RequestorId; + UINT64 ResponderId; + UINT64 InstructionIP; +} EFI_IA32_X64_PROCESS_ERROR_INFO; + +/// +/// IA32/X64 Processor Context Information Structure +/// +typedef struct { + UINT16 RegisterType; + UINT16 ArraySize; + UINT32 MsrAddress; + UINT64 MmRegisterAddress; + // + // This field will provide the contents of the actual registers or raw data. + // The number of Registers or size of the raw data reported is determined + // by (Array Size / 8) or otherwise specified by the context structure type + // definition. + // +} EFI_IA32_X64_PROCESSOR_CONTEXT_INFO; + +/// +/// Register Context Type +///@{ +#define EFI_REG_CONTEXT_TYPE_UNCLASSIFIED 0x0000 +#define EFI_REG_CONTEXT_TYPE_MSR 0x0001 +#define EFI_REG_CONTEXT_TYPE_IA32 0x0002 +#define EFI_REG_CONTEXT_TYPE_X64 0x0003 +#define EFI_REG_CONTEXT_TYPE_FXSAVE 0x0004 +#define EFI_REG_CONTEXT_TYPE_DR_IA32 0x0005 +#define EFI_REG_CONTEXT_TYPE_DR_X64 0x0006 +#define EFI_REG_CONTEXT_TYPE_MEM_MAP 0x0007 +///@} + +/// +/// IA32 Register State +/// +typedef struct { + UINT32 Eax; + UINT32 Ebx; + UINT32 Ecx; + UINT32 Edx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT16 Cs; + UINT16 Ds; + UINT16 Ss; + UINT16 Es; + UINT16 Fs; + UINT16 Gs; + UINT32 Eflags; + UINT32 Eip; + UINT32 Cr0; + UINT32 Cr1; + UINT32 Cr2; + UINT32 Cr3; + UINT32 Cr4; + UINT32 Gdtr[2]; + UINT32 Idtr[2]; + UINT16 Ldtr; + UINT16 Tr; +} EFI_CONTEXT_IA32_REGISTER_STATE; + +/// +/// X64 Register State +/// +typedef struct { + UINT64 Rax; + UINT64 Rbx; + UINT64 Rcx; + UINT64 Rdx; + UINT64 Rsi; + UINT64 Rdi; + UINT64 Rbp; + UINT64 Rsp; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT16 Cs; + UINT16 Ds; + UINT16 Ss; + UINT16 Es; + UINT16 Fs; + UINT16 Gs; + UINT32 Resv1; + UINT64 Rflags; + UINT64 Rip; + UINT64 Cr0; + UINT64 Cr1; + UINT64 Cr2; + UINT64 Cr3; + UINT64 Cr4; + UINT64 Gdtr[2]; + UINT64 Idtr[2]; + UINT16 Ldtr; + UINT16 Tr; +} EFI_CONTEXT_X64_REGISTER_STATE; + +/// +/// The validation bit mask indicates each of the following field is in IA32/X64 +/// Processor Error Section. +/// +typedef struct { + UINT64 ApicIdValid:1; + UINT64 CpuIdInforValid:1; + UINT64 ErrorInfoNum:6; + UINT64 ContextNum:6; + UINT64 Resv1:50; +} EFI_IA32_X64_VALID_BITS; + +#endif + +/// +/// Error Status Fields +/// +typedef struct { + UINT64 Resv1:8; + UINT64 Type:8; + UINT64 AddressSignal:1; ///< Error in Address signals or in Address portion of transaction + UINT64 ControlSignal:1; ///< Error in Control signals or in Control portion of transaction + UINT64 DataSignal:1; ///< Error in Data signals or in Data portion of transaction + UINT64 DetectedByResponder:1; ///< Error detected by responder + UINT64 DetectedByRequester:1; ///< Error detected by requestor + UINT64 FirstError:1; ///< First Error in the sequence - option field + UINT64 OverflowNotLogged:1; ///< Additional errors were not logged due to lack of resources + UINT64 Resv2:41; +} EFI_GENERIC_ERROR_STATUS; + +/// +/// Error Type +/// +typedef enum { + /// + /// General Internal errors + /// + ErrorInternal = 1, + ErrorBus = 16, + /// + /// Component Internal errors + /// + ErrorMemStorage = 4, // Error in memory device + ErrorTlbStorage = 5, // TLB error in cache + ErrorCacheStorage = 6, + ErrorFunctionalUnit = 7, + ErrorSelftest = 8, + ErrorOverflow = 9, + /// + /// Bus internal errors + /// + ErrorVirtualMap = 17, + ErrorAccessInvalid = 18, // Improper access + ErrorUnimplAccess = 19, // Unimplemented memory access + ErrorLossOfLockstep = 20, + ErrorResponseInvalid= 21, // Response not associated with request + ErrorParity = 22, + ErrorProtocol = 23, + ErrorPath = 24, // Detected path error + ErrorTimeout = 25, // Bus timeout + ErrorPoisoned = 26 // Read data poisoned +} EFI_GENERIC_ERROR_STATUS_ERROR_TYPE; + +/// +/// Validation bit mask indicates which fields in the memory error record are valid +/// in Memory Error section +///@{ +#define EFI_PLATFORM_MEMORY_ERROR_STATUS_VALID BIT0 +#define EFI_PLATFORM_MEMORY_PHY_ADDRESS_VALID BIT1 +#define EFI_PLATFORM_MEMORY_PHY_ADDRESS_MASK_VALID BIT2 +#define EFI_PLATFORM_MEMORY_NODE_VALID BIT3 +#define EFI_PLATFORM_MEMORY_CARD_VALID BIT4 +#define EFI_PLATFORM_MEMORY_MODULE_VALID BIT5 +#define EFI_PLATFORM_MEMORY_BANK_VALID BIT6 +#define EFI_PLATFORM_MEMORY_DEVICE_VALID BIT7 +#define EFI_PLATFORM_MEMORY_ROW_VALID BIT8 +#define EFI_PLATFORM_MEMORY_COLUMN_VALID BIT9 +#define EFI_PLATFORM_MEMORY_BIT_POS_VALID BIT10 +#define EFI_PLATFORM_MEMORY_REQUESTOR_ID_VALID BIT11 +#define EFI_PLATFORM_MEMORY_RESPONDER_ID_VALID BIT12 +#define EFI_PLATFORM_MEMORY_TARGET_ID_VALID BIT13 +#define EFI_PLATFORM_MEMORY_ERROR_TYPE_VALID BIT14 +#define EFI_PLATFORM_MEMORY_ERROR_RANK_NUM_VALID BIT15 +#define EFI_PLATFORM_MEMORY_ERROR_CARD_HANDLE_VALID BIT16 +#define EFI_PLATFORM_MEMORY_ERROR_MODULE_HANDLE_VALID BIT17 +#define EFI_PLATFORM_MEMORY_ERROR_EXTENDED_ROW_BIT_16_17_VALID BIT18 +#define EFI_PLATFORM_MEMORY_ERROR_BANK_GROUP_VALID BIT19 +#define EFI_PLATFORM_MEMORY_ERROR_BANK_ADDRESS_VALID BIT20 +#define EFI_PLATFORM_MEMORY_ERROR_CHIP_IDENTIFICATION_VALID BIT21 +///@} + +/// +/// Memory Error Type identifies the type of error that occurred in Memory +/// Error section +///@{ +#define EFI_PLATFORM_MEMORY_ERROR_UNKNOWN 0x00 +#define EFI_PLATFORM_MEMORY_ERROR_NONE 0x01 +#define EFI_PLATFORM_MEMORY_ERROR_SINGLEBIT_ECC 0x02 +#define EFI_PLATFORM_MEMORY_ERROR_MLTIBIT_ECC 0x03 +#define EFI_PLATFORM_MEMORY_ERROR_SINGLESYMBOLS_CHIPKILL 0x04 +#define EFI_PLATFORM_MEMORY_ERROR_MULTISYMBOL_CHIPKILL 0x05 +#define EFI_PLATFORM_MEMORY_ERROR_MATER_ABORT 0x06 +#define EFI_PLATFORM_MEMORY_ERROR_TARGET_ABORT 0x07 +#define EFI_PLATFORM_MEMORY_ERROR_PARITY 0x08 +#define EFI_PLATFORM_MEMORY_ERROR_WDT 0x09 +#define EFI_PLATFORM_MEMORY_ERROR_INVALID_ADDRESS 0x0A +#define EFI_PLATFORM_MEMORY_ERROR_MIRROR_FAILED 0x0B +#define EFI_PLATFORM_MEMORY_ERROR_SPARING 0x0C +#define EFI_PLATFORM_MEMORY_ERROR_SCRUB_CORRECTED 0x0D +#define EFI_PLATFORM_MEMORY_ERROR_SCRUB_UNCORRECTED 0x0E +#define EFI_PLATFORM_MEMORY_ERROR_MEMORY_MAP_EVENT 0x0F +///@} + +/// +/// Memory Error Section +/// +typedef struct { + UINT64 ValidFields; + EFI_GENERIC_ERROR_STATUS ErrorStatus; + UINT64 PhysicalAddress; // Error physical address + UINT64 PhysicalAddressMask; // Grnaularity + UINT16 Node; // Node # + UINT16 Card; + UINT16 ModuleRank; // Module or Rank# + UINT16 Bank; + UINT16 Device; + UINT16 Row; + UINT16 Column; + UINT16 BitPosition; + UINT64 RequestorId; + UINT64 ResponderId; + UINT64 TargetId; + UINT8 ErrorType; + UINT8 Extended; + UINT16 RankNum; + UINT16 CardHandle; + UINT16 ModuleHandle; +} EFI_PLATFORM_MEMORY_ERROR_DATA; + +/// +/// Validation bit mask indicates which fields in the memory error record 2 are valid +/// in Memory Error section 2 +///@{ +#define EFI_PLATFORM_MEMORY2_ERROR_STATUS_VALID BIT0 +#define EFI_PLATFORM_MEMORY2_PHY_ADDRESS_VALID BIT1 +#define EFI_PLATFORM_MEMORY2_PHY_ADDRESS_MASK_VALID BIT2 +#define EFI_PLATFORM_MEMORY2_NODE_VALID BIT3 +#define EFI_PLATFORM_MEMORY2_CARD_VALID BIT4 +#define EFI_PLATFORM_MEMORY2_MODULE_VALID BIT5 +#define EFI_PLATFORM_MEMORY2_BANK_VALID BIT6 +#define EFI_PLATFORM_MEMORY2_DEVICE_VALID BIT7 +#define EFI_PLATFORM_MEMORY2_ROW_VALID BIT8 +#define EFI_PLATFORM_MEMORY2_COLUMN_VALID BIT9 +#define EFI_PLATFORM_MEMORY2_RANK_VALID BIT10 +#define EFI_PLATFORM_MEMORY2_BIT_POS_VALID BIT11 +#define EFI_PLATFORM_MEMORY2_CHIP_ID_VALID BIT12 +#define EFI_PLATFORM_MEMORY2_MEMORY_ERROR_TYPE_VALID BIT13 +#define EFI_PLATFORM_MEMORY2_STATUS_VALID BIT14 +#define EFI_PLATFORM_MEMORY2_REQUESTOR_ID_VALID BIT15 +#define EFI_PLATFORM_MEMORY2_RESPONDER_ID_VALID BIT16 +#define EFI_PLATFORM_MEMORY2_TARGET_ID_VALID BIT17 +#define EFI_PLATFORM_MEMORY2_CARD_HANDLE_VALID BIT18 +#define EFI_PLATFORM_MEMORY2_MODULE_HANDLE_VALID BIT19 +#define EFI_PLATFORM_MEMORY2_BANK_GROUP_VALID BIT20 +#define EFI_PLATFORM_MEMORY2_BANK_ADDRESS_VALID BIT21 +///@} + +/// +/// Memory Error Type identifies the type of error that occurred in Memory +/// Error section 2 +///@{ +#define EFI_PLATFORM_MEMORY2_ERROR_UNKNOWN 0x00 +#define EFI_PLATFORM_MEMORY2_ERROR_NONE 0x01 +#define EFI_PLATFORM_MEMORY2_ERROR_SINGLEBIT_ECC 0x02 +#define EFI_PLATFORM_MEMORY2_ERROR_MLTIBIT_ECC 0x03 +#define EFI_PLATFORM_MEMORY2_ERROR_SINGLESYMBOL_CHIPKILL 0x04 +#define EFI_PLATFORM_MEMORY2_ERROR_MULTISYMBOL_CHIPKILL 0x05 +#define EFI_PLATFORM_MEMORY2_ERROR_MASTER_ABORT 0x06 +#define EFI_PLATFORM_MEMORY2_ERROR_TARGET_ABORT 0x07 +#define EFI_PLATFORM_MEMORY2_ERROR_PARITY 0x08 +#define EFI_PLATFORM_MEMORY2_ERROR_WDT 0x09 +#define EFI_PLATFORM_MEMORY2_ERROR_INVALID_ADDRESS 0x0A +#define EFI_PLATFORM_MEMORY2_ERROR_MIRROR_BROKEN 0x0B +#define EFI_PLATFORM_MEMORY2_ERROR_MEMORY_SPARING 0x0C +#define EFI_PLATFORM_MEMORY2_ERROR_SCRUB_CORRECTED 0x0D +#define EFI_PLATFORM_MEMORY2_ERROR_SCRUB_UNCORRECTED 0x0E +#define EFI_PLATFORM_MEMORY2_ERROR_MEMORY_MAP_EVENT 0x0F +///@} + +/// +/// Memory Error Section 2 +/// +typedef struct { + UINT64 ValidFields; + EFI_GENERIC_ERROR_STATUS ErrorStatus; + UINT64 PhysicalAddress; // Error physical address + UINT64 PhysicalAddressMask; // Grnaularity + UINT16 Node; // Node # + UINT16 Card; + UINT16 Module; // Module or Rank# + UINT16 Bank; + UINT32 Device; + UINT32 Row; + UINT32 Column; + UINT32 Rank; + UINT32 BitPosition; + UINT8 ChipId; + UINT8 MemErrorType; + UINT8 Status; + UINT8 Reserved; + UINT64 RequestorId; + UINT64 ResponderId; + UINT64 TargetId; + UINT32 CardHandle; + UINT32 ModuleHandle; +} EFI_PLATFORM_MEMORY2_ERROR_DATA; + +/// +/// Validation bits mask indicates which of the following fields is valid +/// in PCI Express Error Record. +///@{ +#define EFI_PCIE_ERROR_PORT_TYPE_VALID BIT0 +#define EFI_PCIE_ERROR_VERSION_VALID BIT1 +#define EFI_PCIE_ERROR_COMMAND_STATUS_VALID BIT2 +#define EFI_PCIE_ERROR_DEVICE_ID_VALID BIT3 +#define EFI_PCIE_ERROR_SERIAL_NO_VALID BIT4 +#define EFI_PCIE_ERROR_BRIDGE_CRL_STS_VALID BIT5 +#define EFI_PCIE_ERROR_CAPABILITY_INFO_VALID BIT6 +#define EFI_PCIE_ERROR_AER_INFO_VALID BIT7 +///@} + +/// +/// PCIe Device/Port Type as defined in the PCI Express capabilities register +///@{ +#define EFI_PCIE_ERROR_PORT_PCIE_ENDPOINT 0x00000000 +#define EFI_PCIE_ERROR_PORT_PCI_ENDPOINT 0x00000001 +#define EFI_PCIE_ERROR_PORT_ROOT_PORT 0x00000004 +#define EFI_PCIE_ERROR_PORT_UPSWITCH_PORT 0x00000005 +#define EFI_PCIE_ERROR_PORT_DOWNSWITCH_PORT 0x00000006 +#define EFI_PCIE_ERROR_PORT_PCIE_TO_PCI_BRIDGE 0x00000007 +#define EFI_PCIE_ERROR_PORT_PCI_TO_PCIE_BRIDGE 0x00000008 +#define EFI_PCIE_ERROR_PORT_ROOT_INT_ENDPOINT 0x00000009 +#define EFI_PCIE_ERROR_PORT_ROOT_EVENT_COLLECTOR 0x0000000A +///@} + +/// +/// PCI Slot number +/// +typedef struct { + UINT16 Resv1:3; + UINT16 Number:13; +} EFI_GENERIC_ERROR_PCI_SLOT; + +/// +/// PCIe Root Port PCI/bridge PCI compatible device number and +/// bus number information to uniquely identify the root port or +/// bridge. Default values for both the bus numbers is zero. +/// +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT8 ClassCode[3]; + UINT8 Function; + UINT8 Device; + UINT16 Segment; + UINT8 PrimaryOrDeviceBus; + UINT8 SecondaryBus; + EFI_GENERIC_ERROR_PCI_SLOT Slot; + UINT8 Resv1; +} EFI_GENERIC_ERROR_PCIE_DEV_BRIDGE_ID; + +/// +/// PCIe Capability Structure +/// +typedef struct { + UINT8 PcieCap[60]; +} EFI_PCIE_ERROR_DATA_CAPABILITY; + +/// +/// PCIe Advanced Error Reporting Extended Capability Structure. +/// +typedef struct { + UINT8 PcieAer[96]; +} EFI_PCIE_ERROR_DATA_AER; + +/// +/// PCI Express Error Record +/// +typedef struct { + UINT64 ValidFields; + UINT32 PortType; + UINT32 Version; + UINT32 CommandStatus; + UINT32 Resv2; + EFI_GENERIC_ERROR_PCIE_DEV_BRIDGE_ID DevBridge; + UINT64 SerialNo; + UINT32 BridgeControlStatus; + EFI_PCIE_ERROR_DATA_CAPABILITY Capability; + EFI_PCIE_ERROR_DATA_AER AerInfo; +} EFI_PCIE_ERROR_DATA; + +/// +/// Validation bits Indicates which of the following fields is valid +/// in PCI/PCI-X Bus Error Section. +///@{ +#define EFI_PCI_PCIX_BUS_ERROR_STATUS_VALID BIT0 +#define EFI_PCI_PCIX_BUS_ERROR_TYPE_VALID BIT1 +#define EFI_PCI_PCIX_BUS_ERROR_BUS_ID_VALID BIT2 +#define EFI_PCI_PCIX_BUS_ERROR_BUS_ADDRESS_VALID BIT3 +#define EFI_PCI_PCIX_BUS_ERROR_BUS_DATA_VALID BIT4 +#define EFI_PCI_PCIX_BUS_ERROR_COMMAND_VALID BIT5 +#define EFI_PCI_PCIX_BUS_ERROR_REQUESTOR_ID_VALID BIT6 +#define EFI_PCI_PCIX_BUS_ERROR_COMPLETER_ID_VALID BIT7 +#define EFI_PCI_PCIX_BUS_ERROR_TARGET_ID_VALID BIT8 +///@} + +/// +/// PCI Bus Error Type in PCI/PCI-X Bus Error Section +///@{ +#define EFI_PCI_PCIX_BUS_ERROR_UNKNOWN 0x0000 +#define EFI_PCI_PCIX_BUS_ERROR_DATA_PARITY 0x0001 +#define EFI_PCI_PCIX_BUS_ERROR_SYSTEM 0x0002 +#define EFI_PCI_PCIX_BUS_ERROR_MASTER_ABORT 0x0003 +#define EFI_PCI_PCIX_BUS_ERROR_BUS_TIMEOUT 0x0004 +#define EFI_PCI_PCIX_BUS_ERROR_MASTER_DATA_PARITY 0x0005 +#define EFI_PCI_PCIX_BUS_ERROR_ADDRESS_PARITY 0x0006 +#define EFI_PCI_PCIX_BUS_ERROR_COMMAND_PARITY 0x0007 +///@} + +/// +/// PCI/PCI-X Bus Error Section +/// +typedef struct { + UINT64 ValidFields; + EFI_GENERIC_ERROR_STATUS ErrorStatus; + UINT16 Type; + UINT16 BusId; + UINT32 Resv2; + UINT64 BusAddress; + UINT64 BusData; + UINT64 BusCommand; + UINT64 RequestorId; + UINT64 ResponderId; + UINT64 TargetId; +} EFI_PCI_PCIX_BUS_ERROR_DATA; + +/// +/// Validation bits Indicates which of the following fields is valid +/// in PCI/PCI-X Component Error Section. +///@{ +#define EFI_PCI_PCIX_DEVICE_ERROR_STATUS_VALID BIT0 +#define EFI_PCI_PCIX_DEVICE_ERROR_ID_INFO_VALID BIT1 +#define EFI_PCI_PCIX_DEVICE_ERROR_MEM_NUM_VALID BIT2 +#define EFI_PCI_PCIX_DEVICE_ERROR_IO_NUM_VALID BIT3 +#define EFI_PCI_PCIX_DEVICE_ERROR_REG_DATA_PAIR_VALID BIT4 +///@} + +/// +/// PCI/PCI-X Device Identification Information +/// +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT8 ClassCode[3]; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Segment; + UINT8 Resv1; + UINT32 Resv2; +} EFI_GENERIC_ERROR_PCI_DEVICE_ID; + +/// +/// Identifies the type of firmware error record +///@{ +#define EFI_FIRMWARE_ERROR_TYPE_IPF_SAL 0x00 +#define EFI_FIRMWARE_ERROR_TYPE_SOC_TYPE1 0x01 +#define EFI_FIRMWARE_ERROR_TYPE_SOC_TYPE2 0x02 +///@} + +/// +/// Firmware Error Record Section +/// +typedef struct { + UINT8 ErrorType; + UINT8 Revision; + UINT8 Resv1[6]; + UINT64 RecordId; + EFI_GUID RecordIdGuid; +} EFI_FIRMWARE_ERROR_DATA; + +/// +/// Fault Reason in DMAr Generic Error Section +///@{ +#define EFI_DMA_FAULT_REASON_TABLE_ENTRY_NOT_PRESENT 0x01 +#define EFI_DMA_FAULT_REASON_TABLE_ENTRY_INVALID 0x02 +#define EFI_DMA_FAULT_REASON_ACCESS_MAPPING_TABLE_ERROR 0x03 +#define EFI_DMA_FAULT_REASON_RESV_BIT_ERROR_IN_MAPPING_TABLE 0x04 +#define EFI_DMA_FAULT_REASON_ACCESS_ADDR_OUT_OF_SPACE 0x05 +#define EFI_DMA_FAULT_REASON_INVALID_ACCESS 0x06 +#define EFI_DMA_FAULT_REASON_INVALID_REQUEST 0x07 +#define EFI_DMA_FAULT_REASON_ACCESS_TRANSLATE_TABLE_ERROR 0x08 +#define EFI_DMA_FAULT_REASON_RESV_BIT_ERROR_IN_TRANSLATE_TABLE 0x09 +#define EFI_DMA_FAULT_REASON_INVALID_COMMAOND 0x0A +#define EFI_DMA_FAULT_REASON_ACCESS_COMMAND_BUFFER_ERROR 0x0B +///@} + +/// +/// DMA access type in DMAr Generic Error Section +///@{ +#define EFI_DMA_ACCESS_TYPE_READ 0x00 +#define EFI_DMA_ACCESS_TYPE_WRITE 0x01 +///@} + +/// +/// DMA address type in DMAr Generic Error Section +///@{ +#define EFI_DMA_ADDRESS_UNTRANSLATED 0x00 +#define EFI_DMA_ADDRESS_TRANSLATION 0x01 +///@} + +/// +/// Architecture type in DMAr Generic Error Section +///@{ +#define EFI_DMA_ARCH_TYPE_VT 0x01 +#define EFI_DMA_ARCH_TYPE_IOMMU 0x02 +///@} + +/// +/// DMAr Generic Error Section +/// +typedef struct { + UINT16 RequesterId; + UINT16 SegmentNumber; + UINT8 FaultReason; + UINT8 AccessType; + UINT8 AddressType; + UINT8 ArchType; + UINT64 DeviceAddr; + UINT8 Resv1[16]; +} EFI_DMAR_GENERIC_ERROR_DATA; + +/// +/// Intel VT for Directed I/O specific DMAr Errors +/// +typedef struct { + UINT8 Version; + UINT8 Revision; + UINT8 OemId[6]; + UINT64 Capability; + UINT64 CapabilityEx; + UINT32 GlobalCommand; + UINT32 GlobalStatus; + UINT32 FaultStatus; + UINT8 Resv1[12]; + UINT64 FaultRecord[2]; + UINT64 RootEntry[2]; + UINT64 ContextEntry[2]; + UINT64 PteL6; + UINT64 PteL5; + UINT64 PteL4; + UINT64 PteL3; + UINT64 PteL2; + UINT64 PteL1; +} EFI_DIRECTED_IO_DMAR_ERROR_DATA; + +/// +/// IOMMU specific DMAr Errors +/// +typedef struct { + UINT8 Revision; + UINT8 Resv1[7]; + UINT64 Control; + UINT64 Status; + UINT8 Resv2[8]; + UINT64 EventLogEntry[2]; + UINT8 Resv3[16]; + UINT64 DeviceTableEntry[4]; + UINT64 PteL6; + UINT64 PteL5; + UINT64 PteL4; + UINT64 PteL3; + UINT64 PteL2; + UINT64 PteL1; +} EFI_IOMMU_DMAR_ERROR_DATA; + +#pragma pack() + +extern EFI_GUID gEfiEventNotificationTypeCmcGuid; +extern EFI_GUID gEfiEventNotificationTypeCpeGuid; +extern EFI_GUID gEfiEventNotificationTypeMceGuid; +extern EFI_GUID gEfiEventNotificationTypePcieGuid; +extern EFI_GUID gEfiEventNotificationTypeInitGuid; +extern EFI_GUID gEfiEventNotificationTypeNmiGuid; +extern EFI_GUID gEfiEventNotificationTypeBootGuid; +extern EFI_GUID gEfiEventNotificationTypeDmarGuid; + +extern EFI_GUID gEfiProcessorGenericErrorSectionGuid; +extern EFI_GUID gEfiProcessorSpecificErrorSectionGuid; +extern EFI_GUID gEfiIa32X64ProcessorErrorSectionGuid; +extern EFI_GUID gEfiArmProcessorErrorSectionGuid ; +extern EFI_GUID gEfiPlatformMemoryErrorSectionGuid; +extern EFI_GUID gEfiPlatformMemory2ErrorSectionGuid; +extern EFI_GUID gEfiPcieErrorSectionGuid; +extern EFI_GUID gEfiFirmwareErrorSectionGuid; +extern EFI_GUID gEfiPciBusErrorSectionGuid; +extern EFI_GUID gEfiPciDevErrorSectionGuid; +extern EFI_GUID gEfiDMArGenericErrorSectionGuid; +extern EFI_GUID gEfiDirectedIoDMArErrorSectionGuid; +extern EFI_GUID gEfiIommuDMArErrorSectionGuid; + +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) +/// +/// IA32 and x64 Specific definitions. +/// + +extern EFI_GUID gEfiIa32X64ErrorTypeCacheCheckGuid; +extern EFI_GUID gEfiIa32X64ErrorTypeTlbCheckGuid; +extern EFI_GUID gEfiIa32X64ErrorTypeBusCheckGuid; +extern EFI_GUID gEfiIa32X64ErrorTypeMsCheckGuid; + +#endif + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DebugImageInfoTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DebugImageInfoTable.h new file mode 100644 index 0000000..f97d2a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DebugImageInfoTable.h @@ -0,0 +1,80 @@ +/** @file + GUID and related data structures used with the Debug Image Info Table. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.0 spec. + +**/ + +#ifndef __DEBUG_IMAGE_INFO_GUID_H__ +#define __DEBUG_IMAGE_INFO_GUID_H__ + +#include + +/// +/// EFI_DEBUG_IMAGE_INFO_TABLE configuration table GUID declaration. +/// +#define EFI_DEBUG_IMAGE_INFO_TABLE_GUID \ + { \ + 0x49152e77, 0x1ada, 0x4764, {0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b } \ + } + +#define EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS 0x01 +#define EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED 0x02 + +#define EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL 0x01 + +typedef struct { + UINT64 Signature; ///< A constant UINT64 that has the value EFI_SYSTEM_TABLE_SIGNATURE + EFI_PHYSICAL_ADDRESS EfiSystemTableBase; ///< The physical address of the EFI system table. + UINT32 Crc32; ///< A 32-bit CRC value that is used to verify the EFI_SYSTEM_TABLE_POINTER structure is valid. +} EFI_SYSTEM_TABLE_POINTER; + +typedef struct { + /// + /// Indicates the type of image info structure. For PE32 EFI images, + /// this is set to EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL. + /// + UINT32 ImageInfoType; + /// + /// A pointer to an instance of the loaded image protocol for the associated image. + /// + EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocolInstance; + /// + /// Indicates the image handle of the associated image. + /// + EFI_HANDLE ImageHandle; +} EFI_DEBUG_IMAGE_INFO_NORMAL; + +typedef union { + UINT32 *ImageInfoType; + EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage; +} EFI_DEBUG_IMAGE_INFO; + +typedef struct { + /// + /// UpdateStatus is used by the system to indicate the state of the debug image info table. + /// + volatile UINT32 UpdateStatus; + /// + /// The number of EFI_DEBUG_IMAGE_INFO elements in the array pointed to by EfiDebugImageInfoTable. + /// + UINT32 TableSize; + /// + /// A pointer to the first element of an array of EFI_DEBUG_IMAGE_INFO structures. + /// + EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable; +} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER; + +extern EFI_GUID gEfiDebugImageInfoTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DxeServices.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DxeServices.h new file mode 100644 index 0000000..e55f72a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/DxeServices.h @@ -0,0 +1,28 @@ +/** @file + GUID used to identify the DXE Services Table + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID introduced in PI Version 1.0. + +**/ + +#ifndef __DXE_SERVICES_GUID_H__ +#define __DXE_SERVICES_GUID_H__ + +#define DXE_SERVICES_TABLE_GUID \ + { \ + 0x5ad34ba, 0x6f02, 0x4214, {0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 } \ + } + +extern EFI_GUID gEfiDxeServicesTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventGroup.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventGroup.h new file mode 100644 index 0000000..67269dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventGroup.h @@ -0,0 +1,52 @@ +/** @file + GUIDs for gBS->CreateEventEx Event Groups. Defined in UEFI spec 2.0 and PI 1.2.1. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EVENT_GROUP_GUID__ +#define __EVENT_GROUP_GUID__ + + +#define EFI_EVENT_GROUP_EXIT_BOOT_SERVICES \ + { 0x27abf055, 0xb1b8, 0x4c26, { 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf } } + +extern EFI_GUID gEfiEventExitBootServicesGuid; + + +#define EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE \ + { 0x13fa7698, 0xc831, 0x49c7, { 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96 } } + +extern EFI_GUID gEfiEventVirtualAddressChangeGuid; + + +#define EFI_EVENT_GROUP_MEMORY_MAP_CHANGE \ + { 0x78bee926, 0x692f, 0x48fd, { 0x9e, 0xdb, 0x1, 0x42, 0x2e, 0xf0, 0xd7, 0xab } } + +extern EFI_GUID gEfiEventMemoryMapChangeGuid; + + +#define EFI_EVENT_GROUP_READY_TO_BOOT \ + { 0x7ce88fb3, 0x4bd7, 0x4679, { 0x87, 0xa8, 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b } } + +extern EFI_GUID gEfiEventReadyToBootGuid; + +#define EFI_EVENT_GROUP_DXE_DISPATCH_GUID \ + { 0x7081e22f, 0xcac6, 0x4053, { 0x94, 0x68, 0x67, 0x57, 0x82, 0xcf, 0x88, 0xe5 }} + +extern EFI_GUID gEfiEventDxeDispatchGuid; + +#define EFI_END_OF_DXE_EVENT_GROUP_GUID \ + { 0x2ce967a, 0xdd7e, 0x4ffc, { 0x9e, 0xe7, 0x81, 0xc, 0xf0, 0x47, 0x8, 0x80 } } + +extern EFI_GUID gEfiEndOfDxeEventGroupGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventLegacyBios.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventLegacyBios.h new file mode 100644 index 0000000..3edac6a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/EventLegacyBios.h @@ -0,0 +1,28 @@ +/** @file + GUID is the name of events used with CreateEventEx in order to be notified + when the EFI boot manager is about to boot a legacy boot option. + Events of this type are notificated just before Int19h is invoked. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID introduced in PI Version 1.0. + +**/ + +#ifndef __EVENT_LEGACY_BIOS_GUID_H__ +#define __EVENT_LEGACY_BIOS_GUID_H__ + +#define EFI_EVENT_LEGACY_BOOT_GUID \ + { 0x2a571201, 0x4966, 0x47f6, {0x8b, 0x86, 0xf3, 0x1e, 0x41, 0xf3, 0x2f, 0x10 } } + +extern EFI_GUID gEfiEventLegacyBootGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileInfo.h new file mode 100644 index 0000000..e1f5233 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileInfo.h @@ -0,0 +1,71 @@ +/** @file + Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.SetInfo() + and EFI_FILE_PROTOCOL.GetInfo() to set or get generic file information. + This GUID is defined in UEFI specification. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FILE_INFO_H__ +#define __FILE_INFO_H__ + +#define EFI_FILE_INFO_ID \ + { \ + 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct { + /// + /// The size of the EFI_FILE_INFO structure, including the Null-terminated FileName string. + /// + UINT64 Size; + /// + /// The size of the file in bytes. + /// + UINT64 FileSize; + /// + /// PhysicalSize The amount of physical space the file consumes on the file system volume. + /// + UINT64 PhysicalSize; + /// + /// The time the file was created. + /// + EFI_TIME CreateTime; + /// + /// The time when the file was last accessed. + /// + EFI_TIME LastAccessTime; + /// + /// The time when the file's contents were last modified. + /// + EFI_TIME ModificationTime; + /// + /// The attribute bits for the file. + /// + UINT64 Attribute; + /// + /// The Null-terminated name of the file. + /// + CHAR16 FileName[1]; +} EFI_FILE_INFO; + +/// +/// The FileName field of the EFI_FILE_INFO data structure is variable length. +/// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to +/// be the size of the data structure without the FileName field. The following macro +/// computes this size correctly no matter how big the FileName array is declared. +/// This is required to make the EFI_FILE_INFO data structure ANSI compilant. +/// +#define SIZE_OF_EFI_FILE_INFO OFFSET_OF (EFI_FILE_INFO, FileName) + +extern EFI_GUID gEfiFileInfoGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemInfo.h new file mode 100644 index 0000000..4afcc99 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemInfo.h @@ -0,0 +1,63 @@ +/** @file + Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.GetInfo() + or EFI_FILE_PROTOCOL.SetInfo() to get or set information about the system's volume. + This GUID is defined in UEFI specification. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FILE_SYSTEM_INFO_H__ +#define __FILE_SYSTEM_INFO_H__ + +#define EFI_FILE_SYSTEM_INFO_ID \ + { \ + 0x9576e93, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct { + /// + /// The size of the EFI_FILE_SYSTEM_INFO structure, including the Null-terminated VolumeLabel string. + /// + UINT64 Size; + /// + /// TRUE if the volume only supports read access. + /// + BOOLEAN ReadOnly; + /// + /// The number of bytes managed by the file system. + /// + UINT64 VolumeSize; + /// + /// The number of available bytes for use by the file system. + /// + UINT64 FreeSpace; + /// + /// The nominal block size by which files are typically grown. + /// + UINT32 BlockSize; + /// + /// The Null-terminated string that is the volume's label. + /// + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_INFO; + +/// +/// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length. +/// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs +/// to be the size of the data structure without the VolumeLable field. The following macro +/// computes this size correctly no matter how big the VolumeLable array is declared. +/// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant. +/// +#define SIZE_OF_EFI_FILE_SYSTEM_INFO OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel) + +extern EFI_GUID gEfiFileSystemInfoGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemVolumeLabelInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemVolumeLabelInfo.h new file mode 100644 index 0000000..4fe21ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FileSystemVolumeLabelInfo.h @@ -0,0 +1,37 @@ +/** @file + Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.GetInfo() + or EFI_FILE_PROTOCOL.SetInfo() to get or set the system's volume label. + This GUID is defined in UEFI specification. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FILE_SYSTEM_VOLUME_LABEL_INFO_H__ +#define __FILE_SYSTEM_VOLUME_LABEL_INFO_H__ + +#define EFI_FILE_SYSTEM_VOLUME_LABEL_ID \ + { \ + 0xDB47D7D3, 0xFE81, 0x11d3, {0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } \ + } + +typedef struct { + /// + /// The Null-terminated string that is the volume's label. + /// + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_VOLUME_LABEL; + +#define SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL \ + OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL, VolumeLabel) + +extern EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareContentsSigned.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareContentsSigned.h new file mode 100644 index 0000000..cb78316 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareContentsSigned.h @@ -0,0 +1,26 @@ +/** @file + GUID is used to define the signed section. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID introduced in PI Version 1.2.1. + +**/ + +#ifndef __FIRMWARE_CONTENTS_SIGNED_GUID_H__ +#define __FIRMWARE_CONTENTS_SIGNED_GUID_H__ + +#define EFI_FIRMWARE_CONTENTS_SIGNED_GUID \ + { 0xf9d89e8, 0x9259, 0x4f76, {0xa5, 0xaf, 0xc, 0x89, 0xe3, 0x40, 0x23, 0xdf } } + +extern EFI_GUID gEfiFirmwareContentsSignedGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem2.h new file mode 100644 index 0000000..eb9a33d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem2.h @@ -0,0 +1,40 @@ +/** @file + Guid used to define the Firmware File System 2. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs introduced in PI Version 1.0. + +**/ + +#ifndef __FIRMWARE_FILE_SYSTEM2_GUID_H__ +#define __FIRMWARE_FILE_SYSTEM2_GUID_H__ + +/// +/// The firmware volume header contains a data field for +/// the file system GUID +/// +#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \ + { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } } + +/// +/// A Volume Top File (VTF) is a file that must be +/// located such that the last byte of the file is +/// also the last byte of the firmware volume +/// +#define EFI_FFS_VOLUME_TOP_FILE_GUID \ + { 0x1BA0062E, 0xC779, 0x4582, { 0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x9 } } + + +extern EFI_GUID gEfiFirmwareFileSystem2Guid; +extern EFI_GUID gEfiFirmwareVolumeTopFileGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem3.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem3.h new file mode 100644 index 0000000..351687f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FirmwareFileSystem3.h @@ -0,0 +1,30 @@ +/** @file + Guid used to define the Firmware File System 3. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs introduced in PI Version 1.0. + +**/ + +#ifndef __FIRMWARE_FILE_SYSTEM3_GUID_H__ +#define __FIRMWARE_FILE_SYSTEM3_GUID_H__ + +/// +/// The firmware volume header contains a data field for the file system GUID +/// {5473C07A-3DCB-4dca-BD6F-1E9689E7349A} +/// +#define EFI_FIRMWARE_FILE_SYSTEM3_GUID \ + { 0x5473c07a, 0x3dcb, 0x4dca, { 0xbd, 0x6f, 0x1e, 0x96, 0x89, 0xe7, 0x34, 0x9a }} + +extern EFI_GUID gEfiFirmwareFileSystem3Guid; + +#endif // __FIRMWARE_FILE_SYSTEM3_GUID_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FmpCapsule.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FmpCapsule.h new file mode 100644 index 0000000..2d97b10 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/FmpCapsule.h @@ -0,0 +1,98 @@ +/** @file + Guid & data structure used for Delivering Capsules Containing Updates to Firmware + Management Protocol + + Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.4 spec. + +**/ + + +#ifndef _FMP_CAPSULE_GUID_H__ +#define _FMP_CAPSULE_GUID_H__ + +// +// This is the GUID of the capsule for Firmware Management Protocol. +// +#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \ + { \ + 0x6dcbd5ed, 0xe82d, 0x4c44, {0xbd, 0xa1, 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a } \ + } + +#pragma pack(1) + +typedef struct { + UINT32 Version; + + /// + /// The number of drivers included in the capsule and the number of corresponding + /// offsets stored in ItemOffsetList array. + /// + UINT16 EmbeddedDriverCount; + + /// + /// The number of payload items included in the capsule and the number of + /// corresponding offsets stored in the ItemOffsetList array. + /// + UINT16 PayloadItemCount; + + /// + /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount] + /// containing offsets of each of the drivers and payload items contained within the capsule + /// + // UINT64 ItemOffsetList[]; +} EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER; + +typedef struct { + UINT32 Version; + + /// + /// Used to identify device firmware targeted by this update. This guid is matched by + /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR + /// + EFI_GUID UpdateImageTypeId; + + /// + /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage() + /// + UINT8 UpdateImageIndex; + UINT8 reserved_bytes[3]; + + /// + /// Size of the binary update image which immediately follows this structure + /// + UINT32 UpdateImageSize; + + /// + /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule + /// + UINT32 UpdateVendorCodeSize; + + /// + /// The HardwareInstance to target with this update. If value is zero it means match all + /// HardwareInstances. This field allows update software to target only a single device in + /// cases where there are more than one device with the same ImageTypeId GUID. + /// This header is outside the signed data of the Authentication Info structure and + /// therefore can be modified without changing the Auth data. + /// + UINT64 UpdateHardwareInstance; +} EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER; + +#pragma pack() + + +#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION 0x00000001 +#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002 + +extern EFI_GUID gEfiFmpCapsuleGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GlobalVariable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GlobalVariable.h new file mode 100644 index 0000000..eb8c091 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GlobalVariable.h @@ -0,0 +1,192 @@ +/** @file + GUID for EFI (NVRAM) Variables. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.1 +**/ + +#ifndef __GLOBAL_VARIABLE_GUID_H__ +#define __GLOBAL_VARIABLE_GUID_H__ + +#define EFI_GLOBAL_VARIABLE \ + { \ + 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } \ + } + +extern EFI_GUID gEfiGlobalVariableGuid; + +// +// Follow UEFI 2.4 spec: +// To prevent name collisions with possible future globally defined variables, +// other internal firmware data variables that are not defined here must be +// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or +// any other GUID defined by the UEFI Specification. Implementations must +// only permit the creation of variables with a UEFI Specification-defined +// VendorGuid when these variables are documented in the UEFI Specification. +// +// Note: except the globally defined variables defined below, the spec also defines +// L"Boot####" - A boot load option. +// L"Driver####" - A driver load option. +// L"SysPrep####" - A System Prep application load option. +// L"Key####" - Describes hot key relationship with a Boot#### load option. +// The attribute for them is NV+BS+RT, #### is a printed hex value, and no 0x or h +// is included in the hex value. They can not be expressed as a #define like other globally +// defined variables, it is because we can not list the Boot0000, Boot0001, etc one by one. +// + +/// +/// The language codes that the firmware supports. This value is deprecated. +/// Its attribute is BS+RT. +/// +#define EFI_LANG_CODES_VARIABLE_NAME L"LangCodes" +/// +/// The language code that the system is configured for. This value is deprecated. +/// Its attribute is NV+BS+RT. +/// +#define EFI_LANG_VARIABLE_NAME L"Lang" +/// +/// The firmware's boot managers timeout, in seconds, before initiating the default boot selection. +/// Its attribute is NV+BS+RT. +/// +#define EFI_TIME_OUT_VARIABLE_NAME L"Timeout" +/// +/// The language codes that the firmware supports. +/// Its attribute is BS+RT. +/// +#define EFI_PLATFORM_LANG_CODES_VARIABLE_NAME L"PlatformLangCodes" +/// +/// The language code that the system is configured for. +/// Its attribute is NV+BS+RT. +/// +#define EFI_PLATFORM_LANG_VARIABLE_NAME L"PlatformLang" +/// +/// The device path of the default input/output/error output console. +/// Its attribute is NV+BS+RT. +/// +#define EFI_CON_IN_VARIABLE_NAME L"ConIn" +#define EFI_CON_OUT_VARIABLE_NAME L"ConOut" +#define EFI_ERR_OUT_VARIABLE_NAME L"ErrOut" +/// +/// The device path of all possible input/output/error output devices. +/// Its attribute is BS+RT. +/// +#define EFI_CON_IN_DEV_VARIABLE_NAME L"ConInDev" +#define EFI_CON_OUT_DEV_VARIABLE_NAME L"ConOutDev" +#define EFI_ERR_OUT_DEV_VARIABLE_NAME L"ErrOutDev" +/// +/// The ordered boot option load list. +/// Its attribute is NV+BS+RT. +/// +#define EFI_BOOT_ORDER_VARIABLE_NAME L"BootOrder" +/// +/// The boot option for the next boot only. +/// Its attribute is NV+BS+RT. +/// +#define EFI_BOOT_NEXT_VARIABLE_NAME L"BootNext" +/// +/// The boot option that was selected for the current boot. +/// Its attribute is BS+RT. +/// +#define EFI_BOOT_CURRENT_VARIABLE_NAME L"BootCurrent" +/// +/// The types of boot options supported by the boot manager. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME L"BootOptionSupport" +/// +/// The ordered driver load option list. +/// Its attribute is NV+BS+RT. +/// +#define EFI_DRIVER_ORDER_VARIABLE_NAME L"DriverOrder" +/// +/// The ordered System Prep Application load option list. +/// Its attribute is NV+BS+RT. +/// +#define EFI_SYS_PREP_ORDER_VARIABLE_NAME L"SysPrepOrder" +/// +/// Identifies the level of hardware error record persistence +/// support implemented by the platform. This variable is +/// only modified by firmware and is read-only to the OS. +/// Its attribute is NV+BS+RT. +/// +#define EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME L"HwErrRecSupport" +/// +/// Whether the system is operating in setup mode (1) or not (0). +/// All other values are reserved. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_SETUP_MODE_NAME L"SetupMode" +/// +/// The Key Exchange Key Signature Database. +/// Its attribute is NV+BS+RT+AT. +/// +#define EFI_KEY_EXCHANGE_KEY_NAME L"KEK" +/// +/// The public Platform Key. +/// Its attribute is NV+BS+RT+AT. +/// +#define EFI_PLATFORM_KEY_NAME L"PK" +/// +/// Array of GUIDs representing the type of signatures supported +/// by the platform firmware. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_SIGNATURE_SUPPORT_NAME L"SignatureSupport" +/// +/// Whether the platform firmware is operating in Secure boot mode (1) or not (0). +/// All other values are reserved. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_SECURE_BOOT_MODE_NAME L"SecureBoot" +/// +/// The OEM's default Key Exchange Key Signature Database. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_KEK_DEFAULT_VARIABLE_NAME L"KEKDefault" +/// +/// The OEM's default public Platform Key. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_PK_DEFAULT_VARIABLE_NAME L"PKDefault" +/// +/// The OEM's default secure boot signature store. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_DB_DEFAULT_VARIABLE_NAME L"dbDefault" +/// +/// The OEM's default secure boot blacklist signature store. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_DBX_DEFAULT_VARIABLE_NAME L"dbxDefault" +/// +/// The OEM's default secure boot timestamp signature store. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_DBT_DEFAULT_VARIABLE_NAME L"dbtDefault" +/// +/// Allows the firmware to indicate supported features and actions to the OS. +/// Its attribute is BS+RT. +/// +#define EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME L"OsIndicationsSupported" +/// +/// Allows the OS to request the firmware to enable certain features and to take certain actions. +/// Its attribute is NV+BS+RT. +/// +#define EFI_OS_INDICATIONS_VARIABLE_NAME L"OsIndications" +/// +/// Whether the system is configured to use only vendor provided +/// keys or not. Should be treated as read-only. +/// Its attribute is BS+RT. +/// +#define EFI_VENDOR_KEYS_VARIABLE_NAME L"VendorKeys" + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Gpt.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Gpt.h new file mode 100644 index 0000000..aa008db --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Gpt.h @@ -0,0 +1,43 @@ +/** @file + Guids used for the GPT (GUID Partition Table) + + GPT defines a new disk partitioning scheme and also describes + usage of the legacy Master Boot Record (MBR) partitioning scheme. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.1 spec. + +**/ + +#ifndef __GPT_GUID_H__ +#define __GPT_GUID_H__ + +#define EFI_PART_TYPE_UNUSED_GUID \ + { \ + 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } \ + } + +#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \ + { \ + 0xc12a7328, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } \ + } + +#define EFI_PART_TYPE_LEGACY_MBR_GUID \ + { \ + 0x024dee41, 0x33e7, 0x11d3, {0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f } \ + } + +extern EFI_GUID gEfiPartTypeUnusedGuid; +extern EFI_GUID gEfiPartTypeSystemPartGuid; +extern EFI_GUID gEfiPartTypeLegacyMbrGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GraphicsInfoHob.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GraphicsInfoHob.h new file mode 100644 index 0000000..46dd29d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/GraphicsInfoHob.h @@ -0,0 +1,51 @@ +/** @file + Hob guid for Information about the graphics mode. + + Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This HOB is introduced in in PI Version 1.4. + +**/ + +#ifndef _GRAPHICS_INFO_HOB_GUID_H_ +#define _GRAPHICS_INFO_HOB_GUID_H_ + +#include + +#define EFI_PEI_GRAPHICS_INFO_HOB_GUID \ + { \ + 0x39f62cce, 0x6825, 0x4669, { 0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07 } \ + } + +#define EFI_PEI_GRAPHICS_DEVICE_INFO_HOB_GUID \ + { \ + 0xe5cb2ac9, 0xd35d, 0x4430, { 0x93, 0x6e, 0x1d, 0xe3, 0x32, 0x47, 0x8d, 0xe7 } \ + } + +typedef struct { + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINT32 FrameBufferSize; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION GraphicsMode; +} EFI_PEI_GRAPHICS_INFO_HOB; + +typedef struct { + UINT16 VendorId; ///< Ignore if the value is 0xFFFF. + UINT16 DeviceId; ///< Ignore if the value is 0xFFFF. + UINT16 SubsystemVendorId; ///< Ignore if the value is 0xFFFF. + UINT16 SubsystemId; ///< Ignore if the value is 0xFFFF. + UINT8 RevisionId; ///< Ignore if the value is 0xFF. + UINT8 BarIndex; ///< Ignore if the value is 0xFF. +} EFI_PEI_GRAPHICS_DEVICE_INFO_HOB; + +extern EFI_GUID gEfiGraphicsInfoHobGuid; +extern EFI_GUID gEfiGraphicsDeviceInfoHobGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HardwareErrorVariable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HardwareErrorVariable.h new file mode 100644 index 0000000..4f64415 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HardwareErrorVariable.h @@ -0,0 +1,28 @@ +/** @file + GUID for hardware error record variables. + + Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.1. + +**/ + +#ifndef _HARDWARE_ERROR_VARIABLE_GUID_H_ +#define _HARDWARE_ERROR_VARIABLE_GUID_H_ + +#define EFI_HARDWARE_ERROR_VARIABLE \ + { \ + 0x414E6BDD, 0xE47B, 0x47cc, {0xB2, 0x44, 0xBB, 0x61, 0x02, 0x0C, 0xF5, 0x16} \ + } + +extern EFI_GUID gEfiHardwareErrorVariableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiFormMapMethodGuid.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiFormMapMethodGuid.h new file mode 100644 index 0000000..55efbf2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiFormMapMethodGuid.h @@ -0,0 +1,25 @@ +/** @file + Guid used to identify HII FormMap configuration method. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.2 spec. +**/ + +#ifndef __EFI_HII_FORMMAP_GUID_H__ +#define __EFI_HII_FORMMAP_GUID_H__ + +#define EFI_HII_STANDARD_FORM_GUID \ + { 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 } } + +extern EFI_GUID gEfiHiiStandardFormGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiKeyBoardLayout.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiKeyBoardLayout.h new file mode 100644 index 0000000..3c7a31f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiKeyBoardLayout.h @@ -0,0 +1,27 @@ +/** @file + + HII keyboard layout GUID as defined in UEFI2.1 specification + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.1 spec. + +**/ + +#ifndef __HII_KEYBOARD_LAYOUT_GUID_H__ +#define __HII_KEYBOARD_LAYOUT_GUID_H__ + +#define EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID \ + { 0x14982a4f, 0xb0ed, 0x45b8, { 0xa8, 0x11, 0x5a, 0x7a, 0x9b, 0xc2, 0x32, 0xdf }} + +extern EFI_GUID gEfiHiiKeyBoardLayoutGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiPlatformSetupFormset.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiPlatformSetupFormset.h new file mode 100644 index 0000000..5741083 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HiiPlatformSetupFormset.h @@ -0,0 +1,35 @@ +/** @file + GUID indicates that the form set contains forms designed to be used + for platform configuration and this form set will be displayed. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.1. + +**/ + +#ifndef __HII_PLATFORM_SETUP_FORMSET_GUID_H__ +#define __HII_PLATFORM_SETUP_FORMSET_GUID_H__ + +#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \ + { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } } + +#define EFI_HII_DRIVER_HEALTH_FORMSET_GUID \ + { 0xf22fc20c, 0x8cf4, 0x45eb, { 0x8e, 0x6, 0xad, 0x4e, 0x50, 0xb9, 0x5d, 0xd3 } } + +#define EFI_HII_USER_CREDENTIAL_FORMSET_GUID \ + { 0x337f4407, 0x5aee, 0x4b83, { 0xb2, 0xa7, 0x4e, 0xad, 0xca, 0x30, 0x88, 0xcd } } + +extern EFI_GUID gEfiHiiPlatformSetupFormsetGuid; +extern EFI_GUID gEfiHiiDriverHealthFormsetGuid; +extern EFI_GUID gEfiHiiUserCredentialFormsetGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HobList.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HobList.h new file mode 100644 index 0000000..c190740 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/HobList.h @@ -0,0 +1,30 @@ +/** @file + GUIDs used for HOB List entries + + These GUIDs point the HOB List passed from PEI to DXE. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID introduced in PI Version 1.0. + +**/ + +#ifndef __HOB_LIST_GUID_H__ +#define __HOB_LIST_GUID_H__ + +#define HOB_LIST_GUID \ + { \ + 0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +extern EFI_GUID gEfiHobListGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/ImageAuthentication.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/ImageAuthentication.h new file mode 100644 index 0000000..fd5c72f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/ImageAuthentication.h @@ -0,0 +1,352 @@ +/** @file + Image signature database are defined for the signed image validation. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.5 spec. +**/ + +#ifndef __IMAGE_AUTHTICATION_H__ +#define __IMAGE_AUTHTICATION_H__ + +#include +#include + +#define EFI_IMAGE_SECURITY_DATABASE_GUID \ + { \ + 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f } \ + } + +/// +/// Varialbe name with guid EFI_IMAGE_SECURITY_DATABASE_GUID +/// for the authorized signature database. +/// +#define EFI_IMAGE_SECURITY_DATABASE L"db" +/// +/// Varialbe name with guid EFI_IMAGE_SECURITY_DATABASE_GUID +/// for the forbidden signature database. +/// +#define EFI_IMAGE_SECURITY_DATABASE1 L"dbx" +/// +/// Variable name with guid EFI_IMAGE_SECURITY_DATABASE_GUID +/// for the timestamp signature database. +/// +#define EFI_IMAGE_SECURITY_DATABASE2 L"dbt" + +#define SECURE_BOOT_MODE_ENABLE 1 +#define SECURE_BOOT_MODE_DISABLE 0 + +#define SETUP_MODE 1 +#define USER_MODE 0 + +//*********************************************************************** +// Signature Database +//*********************************************************************** +/// +/// The format of a signature database. +/// +#pragma pack(1) + +typedef struct { + /// + /// An identifier which identifies the agent which added the signature to the list. + /// + EFI_GUID SignatureOwner; + /// + /// The format of the signature is defined by the SignatureType. + /// + UINT8 SignatureData[1]; +} EFI_SIGNATURE_DATA; + +typedef struct { + /// + /// Type of the signature. GUID signature types are defined in below. + /// + EFI_GUID SignatureType; + /// + /// Total size of the signature list, including this header. + /// + UINT32 SignatureListSize; + /// + /// Size of the signature header which precedes the array of signatures. + /// + UINT32 SignatureHeaderSize; + /// + /// Size of each signature. + /// + UINT32 SignatureSize; + /// + /// Header before the array of signatures. The format of this header is specified + /// by the SignatureType. + /// UINT8 SignatureHeader[SignatureHeaderSize]; + /// + /// An array of signatures. Each signature is SignatureSize bytes in length. + /// EFI_SIGNATURE_DATA Signatures[][SignatureSize]; + /// +} EFI_SIGNATURE_LIST; + +typedef struct { + /// + /// The SHA256 hash of an X.509 certificate's To-Be-Signed contents. + /// + EFI_SHA256_HASH ToBeSignedHash; + /// + /// The time that the certificate shall be considered to be revoked. + /// + EFI_TIME TimeOfRevocation; +} EFI_CERT_X509_SHA256; + +typedef struct { + /// + /// The SHA384 hash of an X.509 certificate's To-Be-Signed contents. + /// + EFI_SHA384_HASH ToBeSignedHash; + /// + /// The time that the certificate shall be considered to be revoked. + /// + EFI_TIME TimeOfRevocation; +} EFI_CERT_X509_SHA384; + +typedef struct { + /// + /// The SHA512 hash of an X.509 certificate's To-Be-Signed contents. + /// + EFI_SHA512_HASH ToBeSignedHash; + /// + /// The time that the certificate shall be considered to be revoked. + /// + EFI_TIME TimeOfRevocation; +} EFI_CERT_X509_SHA512; + +#pragma pack() + +/// +/// This identifies a signature containing a SHA-256 hash. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) + +/// 32 bytes. +/// +#define EFI_CERT_SHA256_GUID \ + { \ + 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28} \ + } + +/// +/// This identifies a signature containing an RSA-2048 key. The key (only the modulus +/// since the public key exponent is known to be 0x10001) shall be stored in big-endian +/// order. +/// The SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size +/// of SignatureOwner component) + 256 bytes. +/// +#define EFI_CERT_RSA2048_GUID \ + { \ + 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} \ + } + +/// +/// This identifies a signature containing a RSA-2048 signature of a SHA-256 hash. The +/// SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size of +/// SignatureOwner component) + 256 bytes. +/// +#define EFI_CERT_RSA2048_SHA256_GUID \ + { \ + 0xe2b36190, 0x879b, 0x4a3d, {0xad, 0x8d, 0xf2, 0xe7, 0xbb, 0xa3, 0x27, 0x84} \ + } + +/// +/// This identifies a signature containing a SHA-1 hash. The SignatureSize shall always +/// be 16 (size of SignatureOwner component) + 20 bytes. +/// +#define EFI_CERT_SHA1_GUID \ + { \ + 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd} \ + } + +/// +/// TThis identifies a signature containing a RSA-2048 signature of a SHA-1 hash. The +/// SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size of +/// SignatureOwner component) + 256 bytes. +/// +#define EFI_CERT_RSA2048_SHA1_GUID \ + { \ + 0x67f8444f, 0x8743, 0x48f1, {0xa3, 0x28, 0x1e, 0xaa, 0xb8, 0x73, 0x60, 0x80} \ + } + +/// +/// This identifies a signature based on an X.509 certificate. If the signature is an X.509 +/// certificate then verification of the signature of an image should validate the public +/// key certificate in the image using certificate path verification, up to this X.509 +/// certificate as a trusted root. The SignatureHeader size shall always be 0. The +/// SignatureSize may vary but shall always be 16 (size of the SignatureOwner component) + +/// the size of the certificate itself. +/// Note: This means that each certificate will normally be in a separate EFI_SIGNATURE_LIST. +/// +#define EFI_CERT_X509_GUID \ + { \ + 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} \ + } + +/// +/// This identifies a signature containing a SHA-224 hash. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) + +/// 28 bytes. +/// +#define EFI_CERT_SHA224_GUID \ + { \ + 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} \ + } + +/// +/// This identifies a signature containing a SHA-384 hash. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) + +/// 48 bytes. +/// +#define EFI_CERT_SHA384_GUID \ + { \ + 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} \ + } + +/// +/// This identifies a signature containing a SHA-512 hash. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of SignatureOwner component) + +/// 64 bytes. +/// +#define EFI_CERT_SHA512_GUID \ + { \ + 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} \ + } + +/// +/// This identifies a signature containing the SHA256 hash of an X.509 certificate's +/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component) +/// + 48 bytes for an EFI_CERT_X509_SHA256 structure. If the TimeOfRevocation is non-zero, +/// the certificate should be considered to be revoked from that time and onwards, and +/// otherwise the certificate shall be considered to always be revoked. +/// +#define EFI_CERT_X509_SHA256_GUID \ + { \ + 0x3bd2a492, 0x96c0, 0x4079, {0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed } \ + } + +/// +/// This identifies a signature containing the SHA384 hash of an X.509 certificate's +/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component) +/// + 64 bytes for an EFI_CERT_X509_SHA384 structure. If the TimeOfRevocation is non-zero, +/// the certificate should be considered to be revoked from that time and onwards, and +/// otherwise the certificate shall be considered to always be revoked. +/// +#define EFI_CERT_X509_SHA384_GUID \ + { \ + 0x7076876e, 0x80c2, 0x4ee6, {0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b } \ + } + +/// +/// This identifies a signature containing the SHA512 hash of an X.509 certificate's +/// To-Be-Signed contents, and a time of revocation. The SignatureHeader size shall +/// always be 0. The SignatureSize shall always be 16 (size of the SignatureOwner component) +/// + 80 bytes for an EFI_CERT_X509_SHA512 structure. If the TimeOfRevocation is non-zero, +/// the certificate should be considered to be revoked from that time and onwards, and +/// otherwise the certificate shall be considered to always be revoked. +/// +#define EFI_CERT_X509_SHA512_GUID \ + { \ + 0x446dbf63, 0x2502, 0x4cda, {0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d } \ + } + +/// +/// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315] +/// SignedData value. +/// +#define EFI_CERT_TYPE_PKCS7_GUID \ + { \ + 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \ + } + +//*********************************************************************** +// Image Execution Information Table Definition +//*********************************************************************** +typedef UINT32 EFI_IMAGE_EXECUTION_ACTION; + +#define EFI_IMAGE_EXECUTION_AUTHENTICATION 0x00000007 +#define EFI_IMAGE_EXECUTION_AUTH_UNTESTED 0x00000000 +#define EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED 0x00000001 +#define EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED 0x00000002 +#define EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND 0x00000003 +#define EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND 0x00000004 +#define EFI_IMAGE_EXECUTION_POLICY_FAILED 0x00000005 +#define EFI_IMAGE_EXECUTION_INITIALIZED 0x00000008 + +// +// EFI_IMAGE_EXECUTION_INFO is added to EFI System Configuration Table +// and assigned the GUID EFI_IMAGE_SECURITY_DATABASE_GUID. +// +typedef struct { + /// + /// Describes the action taken by the firmware regarding this image. + /// + EFI_IMAGE_EXECUTION_ACTION Action; + /// + /// Size of all of the entire structure. + /// + UINT32 InfoSize; + /// + /// If this image was a UEFI device driver (for option ROM, for example) this is the + /// null-terminated, user-friendly name for the device. If the image was for an application, + /// then this is the name of the application. If this cannot be determined, then a simple + /// NULL character should be put in this position. + /// CHAR16 Name[]; + /// + + /// + /// For device drivers, this is the device path of the device for which this device driver + /// was intended. In some cases, the driver itself may be stored as part of the system + /// firmware, but this field should record the device's path, not the firmware path. For + /// applications, this is the device path of the application. If this cannot be determined, + /// a simple end-of-path device node should be put in this position. + /// EFI_DEVICE_PATH_PROTOCOL DevicePath; + /// + + /// + /// Zero or more image signatures. If the image contained no signatures, + /// then this field is empty. + /// EFI_SIGNATURE_LIST Signature; + /// +} EFI_IMAGE_EXECUTION_INFO; + + +typedef struct { + /// + /// Number of EFI_IMAGE_EXECUTION_INFO structures. + /// + UINTN NumberOfImages; + /// + /// Number of image instances of EFI_IMAGE_EXECUTION_INFO structures. + /// + // EFI_IMAGE_EXECUTION_INFO InformationInfo[] +} EFI_IMAGE_EXECUTION_INFO_TABLE; + +extern EFI_GUID gEfiImageSecurityDatabaseGuid; +extern EFI_GUID gEfiCertSha256Guid; +extern EFI_GUID gEfiCertRsa2048Guid; +extern EFI_GUID gEfiCertRsa2048Sha256Guid; +extern EFI_GUID gEfiCertSha1Guid; +extern EFI_GUID gEfiCertRsa2048Sha1Guid; +extern EFI_GUID gEfiCertX509Guid; +extern EFI_GUID gEfiCertSha224Guid; +extern EFI_GUID gEfiCertSha384Guid; +extern EFI_GUID gEfiCertSha512Guid; +extern EFI_GUID gEfiCertX509Sha256Guid; +extern EFI_GUID gEfiCertX509Sha384Guid; +extern EFI_GUID gEfiCertX509Sha512Guid; +extern EFI_GUID gEfiCertPkcs7Guid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MdePkgTokenSpace.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MdePkgTokenSpace.h new file mode 100644 index 0000000..ee42aea --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MdePkgTokenSpace.h @@ -0,0 +1,25 @@ +/** @file + GUID for MdePkg PCD Token Space + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MDEPKG_TOKEN_SPACE_GUID_H_ +#define _MDEPKG_TOKEN_SPACE_GUID_H_ + +#define MDEPKG_TOKEN_SPACE_GUID \ + { \ + 0x914AEBE7, 0x4635, 0x459b, { 0xAA, 0x1C, 0x11, 0xE2, 0x19, 0xB0, 0x3A, 0x10 } \ + } + +extern EFI_GUID gEfiMdePkgTokenSpaceGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAllocationHob.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAllocationHob.h new file mode 100644 index 0000000..98a7395 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAllocationHob.h @@ -0,0 +1,34 @@ +/** @file + GUIDs for HOBs used in memory allcation + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs introduced in PI Version 1.0. + +**/ + +#ifndef __MEMORY_ALLOCATION_GUID_H__ +#define __MEMORY_ALLOCATION_GUID_H__ + +#define EFI_HOB_MEMORY_ALLOC_BSP_STORE_GUID \ + {0x564b33cd, 0xc92a, 0x4593, {0x90, 0xbf, 0x24, 0x73, 0xe4, 0x3c, 0x63, 0x22} }; + +#define EFI_HOB_MEMORY_ALLOC_STACK_GUID \ + {0x4ed4bf27, 0x4092, 0x42e9, {0x80, 0x7d, 0x52, 0x7b, 0x1d, 0x0, 0xc9, 0xbd} } + +#define EFI_HOB_MEMORY_ALLOC_MODULE_GUID \ + {0xf8e21975, 0x899, 0x4f58, {0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a} } + +extern EFI_GUID gEfiHobMemoryAllocBspStoreGuid; +extern EFI_GUID gEfiHobMemoryAllocStackGuid; +extern EFI_GUID gEfiHobMemoryAllocModuleGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAttributesTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAttributesTable.h new file mode 100644 index 0000000..1292771 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryAttributesTable.h @@ -0,0 +1,34 @@ +/** @file + GUIDs used for UEFI Memory Attributes Table in the UEFI 2.6 specification. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_MEMORY_ATTRIBUTES_TABLE_H__ +#define __UEFI_MEMORY_ATTRIBUTES_TABLE_H__ + +#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID {\ + 0xdcfa911d, 0x26eb, 0x469f, {0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20} \ +} + +typedef struct { + UINT32 Version; + UINT32 NumberOfEntries; + UINT32 DescriptorSize; + UINT32 Reserved; +//EFI_MEMORY_DESCRIPTOR Entry[1]; +} EFI_MEMORY_ATTRIBUTES_TABLE; + +#define EFI_MEMORY_ATTRIBUTES_TABLE_VERSION 0x00000001 + +extern EFI_GUID gEfiMemoryAttributesTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryOverwriteControl.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryOverwriteControl.h new file mode 100644 index 0000000..f119062 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/MemoryOverwriteControl.h @@ -0,0 +1,76 @@ +/** @file + GUID used for MemoryOverwriteRequestControl UEFI variable defined in + TCG Platform Reset Attack Mitigation Specification 1.00. + See http://trustedcomputinggroup.org for the latest specification + + The purpose of the MemoryOverwriteRequestControl UEFI variable is to give users (e.g., OS, loader) the ability to + indicate to the platform that secrets are present in memory and that the platform firmware must clear memory upon + a restart. The OS loader should not create the variable. Rather, the firmware is required to create it. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MEMORY_OVERWRITE_CONTROL_DATA_GUID_H_ +#define _MEMORY_OVERWRITE_CONTROL_DATA_GUID_H_ + +#define MEMORY_ONLY_RESET_CONTROL_GUID \ + { \ + 0xe20939be, 0x32d4, 0x41be, {0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29} \ + } + +/// +/// Variable name is "MemoryOverwriteRequestControl" and it is a 1 byte unsigned value. +/// The attributes should be: +/// EFI_VARIABLE_NON_VOLATILE | +/// EFI_VARIABLE_BOOTSERVICE_ACCESS | +/// EFI_VARIABLE_RUNTIME_ACCESS +/// +#define MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME L"MemoryOverwriteRequestControl" + +/// +/// 0 = Firmware MUST clear the MOR bit +/// 1 = Firmware MUST set the MOR bit +/// +#define MOR_CLEAR_MEMORY_BIT_MASK 0x01 + +/// +/// 0 = Firmware MAY autodetect a clean shutdown of the Static RTM OS. +/// 1 = Firmware MUST NOT autodetect a clean shutdown of the Static RTM OS. +/// +#define MOR_DISABLEAUTODETECT_BIT_MASK 0x10 + +/// +/// MOR field bit offset +/// +#define MOR_CLEAR_MEMORY_BIT_OFFSET 0 +#define MOR_DISABLEAUTODETECT_BIT_OFFSET 4 + +/** + Return the ClearMemory bit value 0 or 1. + + @param mor 1 byte value that contains ClearMemory and DisableAutoDetect bit. + + @return ClearMemory bit value +**/ +#define MOR_CLEAR_MEMORY_VALUE(mor) (((UINT8)(mor) & MOR_CLEAR_MEMORY_BIT_MASK) >> MOR_CLEAR_MEMORY_BIT_OFFSET) + +/** + Return the DisableAutoDetect bit value 0 or 1. + + @param mor 1 byte value that contains ClearMemory and DisableAutoDetect bit. + + @return DisableAutoDetect bit value +**/ +#define MOR_DISABLE_AUTO_DETECT_VALUE(mor) (((UINT8)(mor) & MOR_DISABLEAUTODETECT_BIT_MASK) >> MOR_DISABLEAUTODETECT_BIT_OFFSET) + +extern EFI_GUID gEfiMemoryOverwriteControlDataGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Mps.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Mps.h new file mode 100644 index 0000000..a24a9f2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/Mps.h @@ -0,0 +1,35 @@ +/** @file + GUIDs used for MPS entries in the UEFI 2.0 system table + ACPI is the primary means of exporting MPS information to the OS. MPS only was + included to support Itanium-based platform power on. So don't use it if you don't have too. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __MPS_GUID_H__ +#define __MPS_GUID_H__ + +#define EFI_MPS_TABLE_GUID \ + { \ + 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +// +// GUID name defined in spec. +// +#define MPS_TABLE_GUID EFI_MPS_TABLE_GUID + +extern EFI_GUID gEfiMpsTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PcAnsi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PcAnsi.h new file mode 100644 index 0000000..d49d08a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PcAnsi.h @@ -0,0 +1,58 @@ +/** @file + Terminal Device Path Vendor Guid. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __PC_ANSI_H__ +#define __PC_ANSI_H__ + +#define EFI_PC_ANSI_GUID \ + { \ + 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_GUID \ + { \ + 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_PLUS_GUID \ + { \ + 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \ + } + +#define EFI_VT_UTF8_GUID \ + { \ + 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \ + } + +#define DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL \ + { \ + 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \ + } + +#define EFI_SAS_DEVICE_PATH_GUID \ + { \ + 0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +extern EFI_GUID gEfiPcAnsiGuid; +extern EFI_GUID gEfiVT100Guid; +extern EFI_GUID gEfiVT100PlusGuid; +extern EFI_GUID gEfiVTUTF8Guid; +extern EFI_GUID gEfiUartDevicePathGuid; +extern EFI_GUID gEfiSasDevicePathGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PropertiesTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PropertiesTable.h new file mode 100644 index 0000000..7fa3826 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/PropertiesTable.h @@ -0,0 +1,37 @@ +/** @file + GUIDs used for UEFI Properties Table in the UEFI 2.5 specification. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_PROPERTIES_TABLE_H__ +#define __EFI_PROPERTIES_TABLE_H__ + +#define EFI_PROPERTIES_TABLE_GUID {\ + 0x880aaca3, 0x4adc, 0x4a04, {0x90, 0x79, 0xb7, 0x47, 0x34, 0x8, 0x25, 0xe5} \ +} + +typedef struct { + UINT32 Version; + UINT32 Length; + UINT64 MemoryProtectionAttribute; +} EFI_PROPERTIES_TABLE; + +#define EFI_PROPERTIES_TABLE_VERSION 0x00010000 + +// +// Memory attribute (Not defined bit is reserved) +// +#define EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA 0x1 + +extern EFI_GUID gEfiPropertiesTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SalSystemTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SalSystemTable.h new file mode 100644 index 0000000..59156a8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SalSystemTable.h @@ -0,0 +1,31 @@ +/** @file + GUIDs used for SAL system table entries in the EFI system table. + + SAL System Table contains Itanium-based processor centric information about + the system. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __SAL_SYSTEM_TABLE_GUID_H__ +#define __SAL_SYSTEM_TABLE_GUID_H__ + +#define SAL_SYSTEM_TABLE_GUID \ + { \ + 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +extern EFI_GUID gEfiSalSystemTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SmBios.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SmBios.h new file mode 100644 index 0000000..c7af90e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SmBios.h @@ -0,0 +1,38 @@ +/** @file + GUIDs used to locate the SMBIOS tables in the UEFI 2.5 system table. + + These GUIDs in the system table are the only legal ways to search for and + locate the SMBIOS tables. Do not search the 0xF0000 segment to find SMBIOS + tables. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.5 spec. + +**/ + +#ifndef __SMBIOS_GUID_H__ +#define __SMBIOS_GUID_H__ + +#define SMBIOS_TABLE_GUID \ + { \ + 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define SMBIOS3_TABLE_GUID \ + { \ + 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 } \ + } + +extern EFI_GUID gEfiSmbiosTableGuid; +extern EFI_GUID gEfiSmbios3TableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/StatusCodeDataTypeId.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/StatusCodeDataTypeId.h new file mode 100644 index 0000000..f6e4ecb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/StatusCodeDataTypeId.h @@ -0,0 +1,809 @@ +/** @file + GUID used to identify id for the caller who is initiating the Status Code. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + These GUIDs and structures are defined in UEFI Platform Initialization Specification 1.2 + Volume 3: Shared Architectural Elements + +**/ + +#ifndef __PI_STATUS_CODE_DATA_TYPE_ID_GUID_H__ +#define __PI_STATUS_CODE_DATA_TYPE_ID_GUID_H__ + +#include +#include + +/// +/// Global ID for the EFI_STATUS_CODE_STRING structure +/// +#define EFI_STATUS_CODE_DATA_TYPE_STRING_GUID \ + { 0x92D11080, 0x496F, 0x4D95, { 0xBE, 0x7E, 0x03, 0x74, 0x88, 0x38, 0x2B, 0x0A } } + +typedef enum { + /// + /// A NULL-terminated ASCII string. + /// + EfiStringAscii, + /// + /// A double NULL-terminated Unicode string. + /// + EfiStringUnicode, + /// + /// An EFI_STATUS_CODE_STRING_TOKEN representing the string. The actual + /// string can be obtained by querying the HII Database + /// + EfiStringToken +} EFI_STRING_TYPE; + +/// +/// Specifies the format of the data in EFI_STATUS_CODE_STRING_DATA.String. +/// +typedef struct { + /// + /// The HII package list which contains the string. Handle is a dynamic value that may + /// not be the same for different boots. Type EFI_HII_HANDLE is defined in + /// EFI_HII_DATABASE_PROTOCOL.NewPackageList() in the UEFI Specification. + /// + EFI_HII_HANDLE Handle; + /// + /// When combined with Handle, the string token can be used to retrieve the string. + /// Type EFI_STRING_ID is defined in EFI_IFR_OP_HEADER in the UEFI Specification. + /// + EFI_STRING_ID Token; +} EFI_STATUS_CODE_STRING_TOKEN; + +typedef union { + /// + /// ASCII formatted string. + /// + CHAR8 *Ascii; + /// + /// Unicode formatted string. + /// + CHAR16 *Unicode; + /// + /// HII handle/token pair. + /// + EFI_STATUS_CODE_STRING_TOKEN Hii; +} EFI_STATUS_CODE_STRING; + +/// +/// This data type defines a string type of extended data. A string can accompany +/// any status code. The string can provide additional information about the +/// status code. The string can be ASCII, Unicode, or a Human Interface Infrastructure +/// (HII) token/GUID pair. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_STATUS_CODE_STRING_DATA) - HeaderSize, and + /// DataHeader.Type should be + /// EFI_STATUS_CODE_DATA_TYPE_STRING_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// Specifies the format of the data in String. + /// + EFI_STRING_TYPE StringType; + /// + /// A pointer to the extended data. The data follows the format specified by + /// StringType. + /// + EFI_STATUS_CODE_STRING String; +} EFI_STATUS_CODE_STRING_DATA; + +extern EFI_GUID gEfiStatusCodeDataTypeStringGuid; + +/// +/// Global ID for the following structures: +/// - EFI_DEVICE_PATH_EXTENDED_DATA +/// - EFI_DEVICE_HANDLE_EXTENDED_DATA +/// - EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA +/// - EFI_COMPUTING_UNIT_VOLTAGE_ERROR_DATA +/// - EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA +/// - EFI_COMPUTING_UNIT_TIMER_EXPIRED_ERROR_DATA +/// - EFI_HOST_PROCESSOR_MISMATCH_ERROR_DATA +/// - EFI_MEMORY_RANGE_EXTENDED_DATA +/// - EFI_DEBUG_ASSERT_DATA +/// - EFI_STATUS_CODE_EXCEP_EXTENDED_DATA +/// - EFI_STATUS_CODE_START_EXTENDED_DATA +/// - EFI_LEGACY_OPROM_EXTENDED_DATA +/// - EFI_RETURN_STATUS_EXTENDED_DATA +/// +#define EFI_STATUS_CODE_SPECIFIC_DATA_GUID \ + { 0x335984bd, 0xe805, 0x409a, { 0xb8, 0xf8, 0xd2, 0x7e, 0xce, 0x5f, 0xf7, 0xa6 } } + +/// +/// Extended data about the device path, which is used for many errors and +/// progress codes to point to the device. +/// +/// The device path is used to point to the physical device in case there is more than one device +/// belonging to the same subclass. For example, the system may contain two USB keyboards and one +/// PS/2* keyboard. The driver that parses the status code can use the device path extended data to +/// differentiate between the three. The index field is not useful in this case because there is no standard +/// numbering convention. Device paths are preferred over using device handles because device handles +/// for a given device can change from one boot to another and do not mean anything beyond Boot +/// Services time. In certain cases, the bus driver may not create a device handle for a given device if it +/// detects a critical error. In these cases, the device path extended data can be used to refer to the +/// device, but there may not be any device handles with an instance of +/// EFI_DEVICE_PATH_PROTOCOL that matches DevicePath. The variable device path structure +/// is included in this structure to make it self sufficient. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA). DataHeader.Size should be the size + /// of variable-length DevicePath, and DataHeader.Size is zero for a virtual + /// device that does not have a device path. DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The device path to the controller or the hardware device. Note that this parameter is a + /// variable-length device path structure and not a pointer to such a structure. This structure is + /// populated only if it is a physical device. For virtual devices, the Size field in DataHeader + /// is set to zero and this field is not populated. + /// + // EFI_DEVICE_PATH_PROTOCOL DevicePath; +} EFI_DEVICE_PATH_EXTENDED_DATA; + +/// +/// Device handle Extended Data. Used for many +/// errors and progress codes to point to the device. +/// +/// The handle of the device with which the progress or error code is associated. The handle is +/// guaranteed to be accurate only at the time the status code is reported. Handles are dynamic entities +/// between boots, so handles cannot be considered to be valid if the system has reset subsequent to the +/// status code being reported. Handles may be used to determine a wide variety of useful information +/// about the source of the status code. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - HeaderSize, and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The device handle. + /// + EFI_HANDLE Handle; +} EFI_DEVICE_HANDLE_EXTENDED_DATA; + +/// +/// This structure defines extended data describing a PCI resource allocation error. +/// +/// @par Note: +/// The following structure contains variable-length fields and cannot be defined as a C-style +/// structure. +/// +/// This extended data conveys details for a PCI resource allocation failure error. See the PCI +/// specification and the ACPI specification for details on PCI resource allocations and the format for +/// resource descriptors. This error does not detail why the resource allocation failed. It may be due to a +/// bad resource request or a lack of available resources to satisfy a valid request. The variable device +/// path structure and the resource structures are included in this structure to make it self sufficient. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be sizeof + /// (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// (DevicePathSize + DevicePathSize + DevicePathSize + + /// sizeof(UINT32) + 3 * sizeof (UINT16) ), and DataHeader.Type + /// should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The PCI BAR. Applicable only for PCI devices. Ignored for all other devices. + /// + UINT32 Bar; + /// + /// DevicePathSize should be zero if it is a virtual device that is not associated with + /// a device path. Otherwise, this parameter is the length of the variable-length + /// DevicePath. + /// + UINT16 DevicePathSize; + /// + /// Represents the size the ReqRes parameter. ReqResSize should be zero if the + /// requested resources are not provided as a part of extended data. + /// + UINT16 ReqResSize; + /// + /// Represents the size the AllocRes parameter. AllocResSize should be zero if the + /// allocated resources are not provided as a part of extended data. + /// + UINT16 AllocResSize; + /// + /// The device path to the controller or the hardware device that did not get the requested + /// resources. Note that this parameter is the variable-length device path structure and not + /// a pointer to this structure. + /// + // EFI_DEVICE_PATH_PROTOCOL DevicePath; + /// + /// The requested resources in the format of an ACPI 2.0 resource descriptor. This + /// parameter is not a pointer; it is the complete resource descriptor. + /// + // UINT8 ReqRes[]; + /// + /// The allocated resources in the format of an ACPI 2.0 resource descriptor. This + /// parameter is not a pointer; it is the complete resource descriptor. + /// + // UINT8 AllocRes[]; +} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA; + +/// +/// This structure provides a calculation for base-10 representations. +/// +/// Not consistent with PI 1.2 Specification. +/// This data type is not defined in the PI 1.2 Specification, but is +/// required by several of the other data structures in this file. +/// +typedef struct { + /// + /// The INT16 number by which to multiply the base-2 representation. + /// + INT16 Value; + /// + /// The INT16 number by which to raise the base-2 calculation. + /// + INT16 Exponent; +} EFI_EXP_BASE10_DATA; + +/// +/// This structure provides the voltage at the time of error. It also provides +/// the threshold value indicating the minimum or maximum voltage that is considered +/// an error. If the voltage is less then the threshold, the error indicates that the +/// voltage fell below the minimum acceptable value. If the voltage is greater then the threshold, +/// the error indicates that the voltage rose above the maximum acceptable value. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_COMPUTING_UNIT_VOLTAGE_ERROR_DATA) - + /// HeaderSize, and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The voltage value at the time of the error. + /// + EFI_EXP_BASE10_DATA Voltage; + /// + /// The voltage threshold. + /// + EFI_EXP_BASE10_DATA Threshold; +} EFI_COMPUTING_UNIT_VOLTAGE_ERROR_DATA; + +/// +/// Microcode Update Extended Error Data +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA) - + /// HeaderSize, and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The version of the microcode update from the header. + /// + UINT32 Version; +} EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA; + +/// +/// This structure provides details about the computing unit timer expiration error. +/// The timer limit provides the timeout value of the timer prior to expiration. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_COMPUTING_UNIT_TIMER_EXPIRED_ERROR_DATA) - + /// HeaderSize, and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The number of seconds that the computing unit timer was configured to expire. + /// + EFI_EXP_BASE10_DATA TimerLimit; +} EFI_COMPUTING_UNIT_TIMER_EXPIRED_ERROR_DATA; + +/// +/// Attribute bits for EFI_HOST_PROCESSOR_MISMATCH_ERROR_DATA.Attributes +/// All other attributes are reserved for future use and must be initialized to 0. +/// +///@{ +#define EFI_COMPUTING_UNIT_MISMATCH_SPEED 0x0001 +#define EFI_COMPUTING_UNIT_MISMATCH_FSB_SPEED 0x0002 +#define EFI_COMPUTING_UNIT_MISMATCH_FAMILY 0x0004 +#define EFI_COMPUTING_UNIT_MISMATCH_MODEL 0x0008 +#define EFI_COMPUTING_UNIT_MISMATCH_STEPPING 0x0010 +#define EFI_COMPUTING_UNIT_MISMATCH_CACHE_SIZE 0x0020 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM1 0x1000 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM2 0x2000 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM3 0x4000 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM4 0x8000 +///@} + +/// +/// This structure defines extended data for processor mismatch errors. +/// +/// This provides information to indicate which processors mismatch, and how they mismatch. The +/// status code contains the instance number of the processor that is in error. This structure's +/// Instance indicates the second processor that does not match. This differentiation allows the +/// consumer to determine which two processors do not match. The Attributes indicate what +/// mismatch is being reported. Because Attributes is a bit field, more than one mismatch can be +/// reported with one error code. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_ HOST_PROCESSOR_MISMATCH_ERROR_DATA) - + /// HeaderSize , and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The unit number of the computing unit that does not match. + /// + UINT32 Instance; + /// + /// The attributes describing the failure. + /// + UINT16 Attributes; +} EFI_HOST_PROCESSOR_MISMATCH_ERROR_DATA; + +/// +/// This structure provides details about the computing unit thermal failure. +/// +/// This structure provides the temperature at the time of error. It also provides the threshold value +/// indicating the minimum temperature that is considered an error. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_COMPUTING_UNIT_THERMAL_ERROR_DATA) - + /// HeaderSize , and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The thermal value at the time of the error. + /// + EFI_EXP_BASE10_DATA Temperature; + /// + /// The thermal threshold. + /// + EFI_EXP_BASE10_DATA Threshold; +} EFI_COMPUTING_UNIT_THERMAL_ERROR_DATA; + +/// +/// Enumeration of valid cache types +/// +typedef enum { + EfiInitCacheDataOnly, + EfiInitCacheInstrOnly, + EfiInitCacheBoth, + EfiInitCacheUnspecified +} EFI_INIT_CACHE_TYPE; + +/// +/// Embedded cache init extended data +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_CACHE_INIT_DATA) - HeaderSize , and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The cache level. Starts with 1 for level 1 cache. + /// + UINT32 Level; + /// + /// The type of cache. + /// + EFI_INIT_CACHE_TYPE Type; +} EFI_CACHE_INIT_DATA; + +/// +/// +/// +typedef UINT32 EFI_CPU_STATE_CHANGE_CAUSE; + +/// +/// The reasons that the processor is disabled. +/// Used to fill in EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA.Cause. +/// +///@{ +#define EFI_CPU_CAUSE_INTERNAL_ERROR 0x0001 +#define EFI_CPU_CAUSE_THERMAL_ERROR 0x0002 +#define EFI_CPU_CAUSE_SELFTEST_FAILURE 0x0004 +#define EFI_CPU_CAUSE_PREBOOT_TIMEOUT 0x0008 +#define EFI_CPU_CAUSE_FAILED_TO_START 0x0010 +#define EFI_CPU_CAUSE_CONFIG_ERROR 0x0020 +#define EFI_CPU_CAUSE_USER_SELECTION 0x0080 +#define EFI_CPU_CAUSE_BY_ASSOCIATION 0x0100 +#define EFI_CPU_CAUSE_UNSPECIFIED 0x8000 +///@} + +/// +/// This structure provides information about the disabled computing unit. +/// +/// This structure provides details as to why and how the computing unit was disabled. The causes +/// should cover the typical reasons a processor would be disabled. How the processor was disabled is +/// important because there are distinct differences between hardware and software disabling. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA) - + /// HeaderSize, and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The reason for disabling the processor. + /// + UINT32 Cause; + /// + /// TRUE if the processor is disabled via software means such as not listing it in the ACPI tables. + /// Such a processor will respond to Interprocessor Interrupts (IPIs). FALSE if the processor is hardware + /// disabled, which means it is invisible to software and will not respond to IPIs. + /// + BOOLEAN SoftwareDisabled; +} EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA; + +/// +/// Memory Error Granularity Definition +/// +typedef UINT8 EFI_MEMORY_ERROR_GRANULARITY; + +/// +/// Memory Error Granularities. Used to fill in EFI_MEMORY_EXTENDED_ERROR_DATA.Granularity. +/// +///@{ +#define EFI_MEMORY_ERROR_OTHER 0x01 +#define EFI_MEMORY_ERROR_UNKNOWN 0x02 +#define EFI_MEMORY_ERROR_DEVICE 0x03 +#define EFI_MEMORY_ERROR_PARTITION 0x04 +///@} + +/// +/// Memory Error Operation Definition +/// +typedef UINT8 EFI_MEMORY_ERROR_OPERATION; + +/// +/// Memory Error Operations. Used to fill in EFI_MEMORY_EXTENDED_ERROR_DATA.Operation. +/// +///@{ +#define EFI_MEMORY_OPERATION_OTHER 0x01 +#define EFI_MEMORY_OPERATION_UNKNOWN 0x02 +#define EFI_MEMORY_OPERATION_READ 0x03 +#define EFI_MEMORY_OPERATION_WRITE 0x04 +#define EFI_MEMORY_OPERATION_PARTIAL_WRITE 0x05 +///@} + +/// +/// This structure provides specific details about the memory error that was detected. It provides +/// enough information so that consumers can identify the exact failure and provides enough +/// information to enable corrective action if necessary. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA) - HeaderSize, and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The error granularity type. + /// + EFI_MEMORY_ERROR_GRANULARITY Granularity; + /// + /// The operation that resulted in the error being detected. + /// + EFI_MEMORY_ERROR_OPERATION Operation; + /// + /// The error syndrome, vendor-specific ECC syndrome, or CRC data associated with + /// the error. If unknown, should be initialized to 0. + /// Inconsistent with specification here: + /// This field in StatusCodes spec0.9 is defined as UINT32, keep code unchanged. + /// + UINTN Syndrome; + /// + /// The physical address of the error. + /// + EFI_PHYSICAL_ADDRESS Address; + /// + /// The range, in bytes, within which the error address can be determined. + /// + UINTN Resolution; +} EFI_MEMORY_EXTENDED_ERROR_DATA; + +/// +/// A definition to describe that the operation is performed on multiple devices within the array. +/// May be used for EFI_STATUS_CODE_DIMM_NUMBER.Array and EFI_STATUS_CODE_DIMM_NUMBER.Device. +/// +#define EFI_MULTIPLE_MEMORY_DEVICE_OPERATION 0xfffe + +/// +/// A definition to describe that the operation is performed on all devices within the array. +/// May be used for EFI_STATUS_CODE_DIMM_NUMBER.Array and EFI_STATUS_CODE_DIMM_NUMBER.Device. +/// +#define EFI_ALL_MEMORY_DEVICE_OPERATION 0xffff + +/// +/// A definition to describe that the operation is performed on multiple arrays. +/// May be used for EFI_STATUS_CODE_DIMM_NUMBER.Array and EFI_STATUS_CODE_DIMM_NUMBER.Device. +/// +#define EFI_MULTIPLE_MEMORY_ARRAY_OPERATION 0xfffe + +/// +/// A definition to describe that the operation is performed on all the arrays. +/// May be used for EFI_STATUS_CODE_DIMM_NUMBER.Array and EFI_STATUS_CODE_DIMM_NUMBER.Device. +/// +#define EFI_ALL_MEMORY_ARRAY_OPERATION 0xffff + +/// +/// This extended data provides some context that consumers can use to locate a DIMM within the +/// overall memory scheme. +/// +/// This extended data provides some context that consumers can use to locate a DIMM within the +/// overall memory scheme. The Array and Device numbers may indicate a specific DIMM, or they +/// may be populated with the group definitions in "Related Definitions" below. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_STATUS_CODE_DIMM_NUMBER) - HeaderSize, and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The memory array number. + /// + UINT16 Array; + /// + /// The device number within that Array. + /// + UINT16 Device; +} EFI_STATUS_CODE_DIMM_NUMBER; + +/// +/// This structure defines extended data describing memory modules that do not match. +/// +/// This extended data may be used to convey the specifics of memory modules that do not match. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_MEMORY_MODULE_MISMATCH_ERROR_DATA) - + /// HeaderSize, and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The instance number of the memory module that does not match. + /// + EFI_STATUS_CODE_DIMM_NUMBER Instance; +} EFI_MEMORY_MODULE_MISMATCH_ERROR_DATA; + +/// +/// This structure defines extended data describing a memory range. +/// +/// This extended data may be used to convey the specifics of a memory range. Ranges are specified +/// with a start address and a length. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA) - HeaderSize, and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The starting address of the memory range. + /// + EFI_PHYSICAL_ADDRESS Start; + /// + /// The length in bytes of the memory range. + /// + EFI_PHYSICAL_ADDRESS Length; +} EFI_MEMORY_RANGE_EXTENDED_DATA; + +/// +/// This structure provides the assert information that is typically associated with a debug assertion failing. +/// +/// The data indicates the location of the assertion that failed in the source code. This information +/// includes the file name and line number that are necessary to find the failing assertion in source code. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_DEBUG_ASSERT_DATA) - HeaderSize , and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The line number of the source file where the fault was generated. + /// + UINT32 LineNumber; + /// + /// The size in bytes of FileName. + /// + UINT32 FileNameSize; + /// + /// A pointer to a NULL-terminated ASCII or Unicode string that represents + /// the file name of the source file where the fault was generated. + /// + EFI_STATUS_CODE_STRING_DATA *FileName; +} EFI_DEBUG_ASSERT_DATA; + +/// +/// System Context Data EBC/IA32/IPF +/// +typedef union { + /// + /// The context of the EBC virtual machine when the exception was generated. Type + /// EFI_SYSTEM_CONTEXT_EBC is defined in EFI_DEBUG_SUPPORT_PROTOCOL + /// in the UEFI Specification. + /// + EFI_SYSTEM_CONTEXT_EBC SystemContextEbc; + /// + /// The context of the IA-32 processor when the exception was generated. Type + /// EFI_SYSTEM_CONTEXT_IA32 is defined in the + /// EFI_DEBUG_SUPPORT_PROTOCOL in the UEFI Specification. + /// + EFI_SYSTEM_CONTEXT_IA32 SystemContextIa32; + /// + /// The context of the Itanium(R) processor when the exception was generated. Type + /// EFI_SYSTEM_CONTEXT_IPF is defined in the + /// EFI_DEBUG_SUPPORT_PROTOCOL in the UEFI Specification. + /// + EFI_SYSTEM_CONTEXT_IPF SystemContextIpf; + /// + /// The context of the X64 processor when the exception was generated. Type + /// EFI_SYSTEM_CONTEXT_X64 is defined in the + /// EFI_DEBUG_SUPPORT_PROTOCOL in the UEFI Specification. + /// + EFI_SYSTEM_CONTEXT_X64 SystemContextX64; + /// + /// The context of the ARM processor when the exception was generated. Type + /// EFI_SYSTEM_CONTEXT_ARM is defined in the + /// EFI_DEBUG_SUPPORT_PROTOCOL in the UEFI Specification. + /// + EFI_SYSTEM_CONTEXT_ARM SystemContextArm; +} EFI_STATUS_CODE_EXCEP_SYSTEM_CONTEXT; + +/// +/// This structure defines extended data describing a processor exception error. +/// +/// This extended data allows the processor context that is present at the time of the exception to be +/// reported with the exception. The format and contents of the context data varies depending on the +/// processor architecture. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_STATUS_CODE_EXCEP_EXTENDED_DATA) - HeaderSize, + /// and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The system context. + /// + EFI_STATUS_CODE_EXCEP_SYSTEM_CONTEXT Context; +} EFI_STATUS_CODE_EXCEP_EXTENDED_DATA; + +/// +/// This structure defines extended data describing a call to a driver binding protocol start function. +/// +/// This extended data records information about a Start() function call. Start() is a member of +/// the UEFI Driver Binding Protocol. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_STATUS_CODE_START_EXTENDED_DATA) - HeaderSize, + /// and DataHeader.Type should be + /// EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The controller handle. + /// + EFI_HANDLE ControllerHandle; + /// + /// The driver binding handle. + /// + EFI_HANDLE DriverBindingHandle; + /// + /// The size of the RemainingDevicePath. It is zero if the Start() function is + /// called with RemainingDevicePath = NULL. The UEFI Specification allows + /// that the Start() function of bus drivers can be called in this way. + /// + UINT16 DevicePathSize; + /// + /// Matches the RemainingDevicePath parameter being passed to the Start() function. + /// Note that this parameter is the variable-length device path and not a pointer + /// to the device path. + /// + // EFI_DEVICE_PATH_PROTOCOL RemainingDevicePath; +} EFI_STATUS_CODE_START_EXTENDED_DATA; + +/// +/// This structure defines extended data describing a legacy option ROM (OpROM). +/// +/// The device handle and ROM image base can be used by consumers to determine which option ROM +/// failed. Due to the black-box nature of legacy option ROMs, the amount of information that can be +/// obtained may be limited. +/// +typedef struct { + /// + /// The data header identifying the data. DataHeader.HeaderSize should be + /// sizeof (EFI_STATUS_CODE_DATA), DataHeader.Size should be + /// sizeof (EFI_LEGACY_OPROM_EXTENDED_DATA) - HeaderSize, and + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The handle corresponding to the device that this legacy option ROM is being invoked. + /// + EFI_HANDLE DeviceHandle; + /// + /// The base address of the shadowed legacy ROM image. May or may not point to the shadow RAM area. + /// + EFI_PHYSICAL_ADDRESS RomImageBase; +} EFI_LEGACY_OPROM_EXTENDED_DATA; + +/// +/// This structure defines extended data describing an EFI_STATUS return value that stands for a +/// failed function call (such as a UEFI boot service). +/// +typedef struct { + /// + /// The data header identifying the data: + /// DataHeader.HeaderSize should be sizeof(EFI_STATUS_CODE_DATA), + /// DataHeader.Size should be sizeof(EFI_RETURN_STATUS_EXTENDED_DATA) - HeaderSize, + /// DataHeader.Type should be EFI_STATUS_CODE_SPECIFIC_DATA_GUID. + /// + EFI_STATUS_CODE_DATA DataHeader; + /// + /// The EFI_STATUS return value of the service or function whose failure triggered the + /// reporting of the status code (generally an error code or a debug code). + /// + EFI_STATUS ReturnStatus; +} EFI_RETURN_STATUS_EXTENDED_DATA; + +extern EFI_GUID gEfiStatusCodeSpecificDataGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SystemResourceTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SystemResourceTable.h new file mode 100644 index 0000000..dc7e16b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/SystemResourceTable.h @@ -0,0 +1,125 @@ +/** @file + Guid & data structure used for EFI System Resource Table (ESRT) + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUIDs defined in UEFI 2.5 spec. + +**/ + + +#ifndef _SYSTEM_RESOURCE_TABLE_H__ +#define _SYSTEM_RESOURCE_TABLE_H__ + +#define EFI_SYSTEM_RESOURCE_TABLE_GUID \ + { \ + 0xb122a263, 0x3661, 0x4f68, {0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } \ + } + +/// +/// Current Entry Version +/// +#define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION 1 + +/// +/// Firmware Type Definitions +/// +#define ESRT_FW_TYPE_UNKNOWN 0x00000000 +#define ESRT_FW_TYPE_SYSTEMFIRMWARE 0x00000001 +#define ESRT_FW_TYPE_DEVICEFIRMWARE 0x00000002 +#define ESRT_FW_TYPE_UEFIDRIVER 0x00000003 + +/// +/// Last Attempt Status Values +/// +#define LAST_ATTEMPT_STATUS_SUCCESS 0x00000000 +#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL 0x00000001 +#define LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES 0x00000002 +#define LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION 0x00000003 +#define LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT 0x00000004 +#define LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR 0x00000005 +#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_AC 0x00000006 +#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT 0x00000007 + +typedef struct { + /// + /// The firmware class field contains a GUID that identifies a firmware component + /// that can be updated via UpdateCapsule(). This GUID must be unique within all + /// entries of the ESRT. + /// + EFI_GUID FwClass; + /// + /// Identifies the type of firmware resource. + /// + UINT32 FwType; + /// + /// The firmware version field represents the current version of the firmware + /// resource, value must always increase as a larger number represents a newer + /// version. + /// + UINT32 FwVersion; + /// + /// The lowest firmware resource version to which a firmware resource can be + /// rolled back for the given system/device. Generally this is used to protect + /// against known and fixed security issues. + /// + UINT32 LowestSupportedFwVersion; + /// + /// The capsule flags field contains the CapsuleGuid flags (bits 0- 15) as defined + /// in the EFI_CAPSULE_HEADER that will be set in the capsule header. + /// + UINT32 CapsuleFlags; + /// + /// The last attempt version field describes the last firmware version for which + /// an update was attempted (uses the same format as Firmware Version). + /// Last Attempt Version is updated each time an UpdateCapsule() is attempted for + /// an ESRT entry and is preserved across reboots (non-volatile). However, in + /// cases where the attempt version is not recorded due to limitations in the + /// update process, the field shall set to zero after a failed update. Similarly, + /// in the case of a removable device, this value is set to 0 in cases where the + /// device has not been updated since being added to the system. + /// + UINT32 LastAttemptVersion; + /// + /// The last attempt status field describes the result of the last firmware update + /// attempt for the firmware resource entry. + /// LastAttemptStatus is updated each time an UpdateCapsule() is attempted for an + /// ESRT entry and is preserved across reboots (non-volatile). + /// If a firmware update has never been attempted or is unknown, for example after + /// fresh insertion of a removable device, LastAttemptStatus must be set to Success. + /// + UINT32 LastAttemptStatus; +} EFI_SYSTEM_RESOURCE_ENTRY; + +typedef struct { + /// + /// The number of firmware resources in the table, must not be zero. + /// + UINT32 FwResourceCount; + /// + /// The maximum number of resource array entries that can be within the table + /// without reallocating the table, must not be zero. + /// + UINT32 FwResourceCountMax; + /// + /// The version of the EFI_SYSTEM_RESOURCE_ENTRY entities used in this table. + /// This field should be set to 1. + /// + UINT64 FwResourceVersion; + /// + /// Array of EFI_SYSTEM_RESOURCE_ENTRY + /// + //EFI_SYSTEM_RESOURCE_ENTRY Entries[]; +} EFI_SYSTEM_RESOURCE_TABLE; + +extern EFI_GUID gEfiSystemResourceTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/VectorHandoffTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/VectorHandoffTable.h new file mode 100644 index 0000000..fc5a18f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/VectorHandoffTable.h @@ -0,0 +1,33 @@ +/** @file + GUID for system configuration table entry that points to the table + in case an entity in DXE wishes to update/change the vector table contents. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in PI 1.2.1 spec. +**/ + +#ifndef __EFI_VECTOR_HANDOFF_TABLE_H__ +#define __EFI_VECTOR_HANDOFF_TABLE_H__ + +#include + +// +// System configuration table entry that points to the table +// in case an entity in DXE wishes to update/change the vector +// table contents. +// +#define EFI_VECTOR_HANDOF_TABLE_GUID \ + { 0x996ec11c, 0x5397, 0x4e73, { 0xb5, 0x8f, 0x82, 0x7e, 0x52, 0x90, 0x6d, 0xef }} + +extern EFI_GUID gEfiVectorHandoffTableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/WinCertificate.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/WinCertificate.h new file mode 100644 index 0000000..6dea446 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Guid/WinCertificate.h @@ -0,0 +1,128 @@ +/** @file + GUID for UEFI WIN_CERTIFICATE structure. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + GUID defined in UEFI 2.0 spec. +**/ + +#ifndef __EFI_WIN_CERTIFICATE_H__ +#define __EFI_WIN_CERTIFICATE_H__ + +// +// _WIN_CERTIFICATE.wCertificateType +// +#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 +#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +/// +/// The WIN_CERTIFICATE structure is part of the PE/COFF specification. +/// +typedef struct { + /// + /// The length of the entire certificate, + /// including the length of the header, in bytes. + /// + UINT32 dwLength; + /// + /// The revision level of the WIN_CERTIFICATE + /// structure. The current revision level is 0x0200. + /// + UINT16 wRevision; + /// + /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI + /// certificate types. The UEFI specification reserves the range of + /// certificate type values from 0x0EF0 to 0x0EFF. + /// + UINT16 wCertificateType; + /// + /// The following is the actual certificate. The format of + /// the certificate depends on wCertificateType. + /// + /// UINT8 bCertificate[ANYSIZE_ARRAY]; + /// +} WIN_CERTIFICATE; + +/// +/// WIN_CERTIFICATE_UEFI_GUID.CertType +/// +#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \ + {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } } + +/// +/// WIN_CERTIFICATE_UEFI_GUID.CertData +/// +typedef struct { + EFI_GUID HashType; + UINT8 PublicKey[256]; + UINT8 Signature[256]; +} EFI_CERT_BLOCK_RSA_2048_SHA256; + + +/// +/// Certificate which encapsulates a GUID-specific digital signature +/// +typedef struct { + /// + /// This is the standard WIN_CERTIFICATE header, where + /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID. + /// + WIN_CERTIFICATE Hdr; + /// + /// This is the unique id which determines the + /// format of the CertData. . + /// + EFI_GUID CertType; + /// + /// The following is the certificate data. The format of + /// the data is determined by the CertType. + /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID, + /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure. + /// + UINT8 CertData[1]; +} WIN_CERTIFICATE_UEFI_GUID; + + +/// +/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature. +/// +/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from +/// WIN_CERTIFICATE and encapsulate the information needed to +/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as +/// specified in RFC2437. +/// +typedef struct { + /// + /// This is the standard WIN_CERTIFICATE header, where + /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15. + /// + WIN_CERTIFICATE Hdr; + /// + /// This is the hashing algorithm which was performed on the + /// UEFI executable when creating the digital signature. + /// + EFI_GUID HashAlgorithm; + /// + /// The following is the actual digital signature. The + /// size of the signature is the same size as the key + /// (1024-bit key is 128 bytes) and can be determined by + /// subtracting the length of the other parts of this header + /// from the total length of the certificate as found in + /// Hdr.dwLength. + /// + /// UINT8 Signature[]; + /// +} WIN_CERTIFICATE_EFI_PKCS1_15; + +extern EFI_GUID gEfiCertTypeRsa2048Sha256Guid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/Nasm.inc b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/Nasm.inc new file mode 100644 index 0000000..ba78d83 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/Nasm.inc @@ -0,0 +1,28 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2019, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Abstract: +; +; This file provides macro definitions for NASM files. +; +;------------------------------------------------------------------------------ + +%macro SETSSBSY 0 + DB 0xF3, 0x0F, 0x01, 0xE8 +%endmacro + +%macro READSSP_EAX 0 + DB 0xF3, 0x0F, 0x1E, 0xC8 +%endmacro + +%macro INCSSP_EAX 0 + DB 0xF3, 0x0F, 0xAE, 0xE8 +%endmacro diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/ProcessorBind.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/ProcessorBind.h new file mode 100644 index 0000000..96c09b1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ia32/ProcessorBind.h @@ -0,0 +1,328 @@ +/** @file + Processor or Compiler specific defines and types for IA-32 architecture. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices. +/// +#define MDE_CPU_IA32 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#if !defined(__GNUC__) +#pragma pack() +#endif + +#if defined(__INTEL_COMPILER) +// +// Disable ICC's remark #869: "Parameter" was never referenced warning. +// This is legal ANSI C code so we disable the remark that is turned on with -Wall +// +#pragma warning ( disable : 869 ) + +// +// Disable ICC's remark #1418: external function definition with no prior declaration. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1418 ) + +// +// Disable ICC's remark #1419: external declaration in primary source file +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1419 ) + +// +// Disable ICC's remark #593: "Variable" was set but never used. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 593 ) + +#endif + + +#if defined(_MSC_EXTENSIONS) + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) source file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +#if _MSC_VER == 1800 || _MSC_VER == 1900 || _MSC_VER >= 1910 + +// +// Disable these warnings for VS2013. +// + +// +// This warning is for potentially uninitialized local variable, and it may cause false +// positive issues in VS2013 and VS2015 build +// +#pragma warning ( disable : 4701 ) + +// +// This warning is for potentially uninitialized local pointer variable, and it may cause +// false positive issues in VS2013 and VS2015 build +// +#pragma warning ( disable : 4703 ) + +#endif + +#endif + + +#if defined(_MSC_EXTENSIONS) + + // + // use Microsoft C compiler dependent integer width types + // + + /// + /// 8-byte unsigned value. + /// + typedef unsigned __int64 UINT64; + /// + /// 8-byte signed value. + /// + typedef __int64 INT64; + /// + /// 4-byte unsigned value. + /// + typedef unsigned __int32 UINT32; + /// + /// 4-byte signed value. + /// + typedef __int32 INT32; + /// + /// 2-byte unsigned value. + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value. + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value. + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character. + /// + typedef char CHAR8; + /// + /// 1-byte signed value. + /// + typedef signed char INT8; +#else + /// + /// 8-byte unsigned value. + /// + typedef unsigned long long UINT64; + /// + /// 8-byte signed value. + /// + typedef long long INT64; + /// + /// 4-byte unsigned value. + /// + typedef unsigned int UINT32; + /// + /// 4-byte signed value. + /// + typedef int INT32; + /// + /// 2-byte unsigned value. + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value. + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value. + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character + /// + typedef char CHAR8; + /// + /// 1-byte signed value + /// + typedef signed char INT8; +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions; +/// 8 bytes on supported 64-bit processor instructions.) +/// +typedef UINT32 UINTN; +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions; +/// 8 bytes on supported 64-bit processor instructions.) +/// +typedef INT32 INTN; + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x80000000 +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC0000000 + +/// +/// Maximum legal IA-32 address. +/// +#define MAX_ADDRESS 0xFFFFFFFF + +/// +/// Maximum usable address at boot time +/// +#define MAX_ALLOC_ADDRESS MAX_ADDRESS + +/// +/// Maximum legal IA-32 INTN and UINTN values. +/// +#define MAX_INTN ((INTN)0x7FFFFFFF) +#define MAX_UINTN ((UINTN)0xFFFFFFFF) + +/// +/// Minimum legal IA-32 INTN value. +/// +#define MIN_INTN (((INTN)-2147483647) - 1) + +/// +/// The stack alignment required for IA-32. +/// +#define CPU_STACK_ALIGNMENT sizeof(UINTN) + +/// +/// Page allocation granularity for IA-32. +/// +#define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000) +#define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x1000) + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#ifdef EFIAPI + /// + /// If EFIAPI is already defined, then we use that definition. + /// +#elif defined(_MSC_EXTENSIONS) + /// + /// Microsoft* compiler specific method for EFIAPI calling convention. + /// + #define EFIAPI __cdecl +#elif defined(__GNUC__) + /// + /// GCC specific method for EFIAPI calling convention. + /// + #define EFIAPI __attribute__((cdecl)) +#else + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI +#endif + +#if defined(__GNUC__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On IA-32 CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi.h new file mode 100644 index 0000000..1710ad5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi.h @@ -0,0 +1,21 @@ +/** @file + This file contains the latest ACPI definitions that are + consumed by drivers that do not care about ACPI versions. + + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ACPI_H_ +#define _ACPI_H_ + +#include + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi10.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi10.h new file mode 100644 index 0000000..e292227 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi10.h @@ -0,0 +1,661 @@ +/** @file + ACPI 1.0b definitions from the ACPI Specification, revision 1.0b + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_1_0_H_ +#define _ACPI_1_0_H_ + +#include + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure. +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_COMMON_HEADER; + +#pragma pack(1) +/// +/// The common ACPI description table header. This structure prefaces most ACPI tables. +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + UINT8 OemId[6]; + UINT64 OemTableId; + UINT32 OemRevision; + UINT32 CreatorId; + UINT32 CreatorRevision; +} EFI_ACPI_DESCRIPTION_HEADER; +#pragma pack() + +// +// Define for Desriptor +// +#define ACPI_SMALL_ITEM_FLAG 0x00 +#define ACPI_LARGE_ITEM_FLAG 0x01 + +// +// Small Item Descriptor Name +// +#define ACPI_SMALL_IRQ_DESCRIPTOR_NAME 0x04 +#define ACPI_SMALL_DMA_DESCRIPTOR_NAME 0x05 +#define ACPI_SMALL_START_DEPENDENT_DESCRIPTOR_NAME 0x06 +#define ACPI_SMALL_END_DEPENDENT_DESCRIPTOR_NAME 0x07 +#define ACPI_SMALL_IO_PORT_DESCRIPTOR_NAME 0x08 +#define ACPI_SMALL_FIXED_IO_PORT_DESCRIPTOR_NAME 0x09 +#define ACPI_SMALL_VENDOR_DEFINED_DESCRIPTOR_NAME 0x0E +#define ACPI_SMALL_END_TAG_DESCRIPTOR_NAME 0x0F + +// +// Large Item Descriptor Name +// +#define ACPI_LARGE_24_BIT_MEMORY_RANGE_DESCRIPTOR_NAME 0x01 +#define ACPI_LARGE_VENDOR_DEFINED_DESCRIPTOR_NAME 0x04 +#define ACPI_LARGE_32_BIT_MEMORY_RANGE_DESCRIPTOR_NAME 0x05 +#define ACPI_LARGE_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR_NAME 0x06 +#define ACPI_LARGE_DWORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x07 +#define ACPI_LARGE_WORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x08 +#define ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME 0x09 +#define ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x0A + +// +// Small Item Descriptor Value +// +#define ACPI_IRQ_NOFLAG_DESCRIPTOR 0x22 +#define ACPI_IRQ_DESCRIPTOR 0x23 +#define ACPI_DMA_DESCRIPTOR 0x2A +#define ACPI_START_DEPENDENT_DESCRIPTOR 0x30 +#define ACPI_START_DEPENDENT_EX_DESCRIPTOR 0x31 +#define ACPI_END_DEPENDENT_DESCRIPTOR 0x38 +#define ACPI_IO_PORT_DESCRIPTOR 0x47 +#define ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR 0x4B +#define ACPI_END_TAG_DESCRIPTOR 0x79 + +// +// Large Item Descriptor Value +// +#define ACPI_24_BIT_MEMORY_RANGE_DESCRIPTOR 0x81 +#define ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR 0x85 +#define ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR 0x86 +#define ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR 0x87 +#define ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR 0x88 +#define ACPI_EXTENDED_INTERRUPT_DESCRIPTOR 0x89 +#define ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR 0x8A +#define ACPI_ADDRESS_SPACE_DESCRIPTOR 0x8A + +// +// Resource Type +// +#define ACPI_ADDRESS_SPACE_TYPE_MEM 0x00 +#define ACPI_ADDRESS_SPACE_TYPE_IO 0x01 +#define ACPI_ADDRESS_SPACE_TYPE_BUS 0x02 + +/// +/// Power Management Timer frequency is fixed at 3.579545MHz. +/// +#define ACPI_TIMER_FREQUENCY 3579545 + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// The commond definition of QWORD, DWORD, and WORD +/// Address Space Descriptors. +/// +typedef PACKED struct { + UINT8 Desc; + UINT16 Len; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT64 AddrSpaceGranularity; + UINT64 AddrRangeMin; + UINT64 AddrRangeMax; + UINT64 AddrTranslationOffset; + UINT64 AddrLen; +} EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR; + +typedef PACKED union { + UINT8 Byte; + PACKED struct { + UINT8 Length : 3; + UINT8 Name : 4; + UINT8 Type : 1; + } Bits; +} ACPI_SMALL_RESOURCE_HEADER; + +typedef PACKED struct { + PACKED union { + UINT8 Byte; + PACKED struct { + UINT8 Name : 7; + UINT8 Type : 1; + }Bits; + } Header; + UINT16 Length; +} ACPI_LARGE_RESOURCE_HEADER; + +/// +/// IRQ Descriptor. +/// +typedef PACKED struct { + ACPI_SMALL_RESOURCE_HEADER Header; + UINT16 Mask; +} EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR; + +/// +/// IRQ Descriptor. +/// +typedef PACKED struct { + ACPI_SMALL_RESOURCE_HEADER Header; + UINT16 Mask; + UINT8 Information; +} EFI_ACPI_IRQ_DESCRIPTOR; + +/// +/// DMA Descriptor. +/// +typedef PACKED struct { + ACPI_SMALL_RESOURCE_HEADER Header; + UINT8 ChannelMask; + UINT8 Information; +} EFI_ACPI_DMA_DESCRIPTOR; + +/// +/// I/O Port Descriptor +/// +typedef PACKED struct { + ACPI_SMALL_RESOURCE_HEADER Header; + UINT8 Information; + UINT16 BaseAddressMin; + UINT16 BaseAddressMax; + UINT8 Alignment; + UINT8 Length; +} EFI_ACPI_IO_PORT_DESCRIPTOR; + +/// +/// Fixed Location I/O Port Descriptor. +/// +typedef PACKED struct { + ACPI_SMALL_RESOURCE_HEADER Header; + UINT16 BaseAddress; + UINT8 Length; +} EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR; + +/// +/// 24-Bit Memory Range Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 Information; + UINT16 BaseAddressMin; + UINT16 BaseAddressMax; + UINT16 Alignment; + UINT16 Length; +} EFI_ACPI_24_BIT_MEMORY_RANGE_DESCRIPTOR; + +/// +/// 32-Bit Memory Range Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 Information; + UINT32 BaseAddressMin; + UINT32 BaseAddressMax; + UINT32 Alignment; + UINT32 Length; +} EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR; + +/// +/// Fixed 32-Bit Fixed Memory Range Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 Information; + UINT32 BaseAddress; + UINT32 Length; +} EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR; + +/// +/// QWORD Address Space Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT64 AddrSpaceGranularity; + UINT64 AddrRangeMin; + UINT64 AddrRangeMax; + UINT64 AddrTranslationOffset; + UINT64 AddrLen; +} EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR; + +/// +/// DWORD Address Space Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT32 AddrSpaceGranularity; + UINT32 AddrRangeMin; + UINT32 AddrRangeMax; + UINT32 AddrTranslationOffset; + UINT32 AddrLen; +} EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR; + +/// +/// WORD Address Space Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT16 AddrSpaceGranularity; + UINT16 AddrRangeMin; + UINT16 AddrRangeMax; + UINT16 AddrTranslationOffset; + UINT16 AddrLen; +} EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR; + +/// +/// Extended Interrupt Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 InterruptVectorFlags; + UINT8 InterruptTableLength; + UINT32 InterruptNumber[1]; +} EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR; + +#pragma pack() + +/// +/// The End tag identifies an end of resource data. +/// +typedef struct { + UINT8 Desc; + UINT8 Checksum; +} EFI_ACPI_END_TAG_DESCRIPTOR; + +// +// General use definitions +// +#define EFI_ACPI_RESERVED_BYTE 0x00 +#define EFI_ACPI_RESERVED_WORD 0x0000 +#define EFI_ACPI_RESERVED_DWORD 0x00000000 +#define EFI_ACPI_RESERVED_QWORD 0x0000000000000000 + +// +// Resource Type Specific Flags +// Ref ACPI specification 6.4.3.5.5 +// +// Bit [0] : Write Status, _RW +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_WRITE (1 << 0) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_ONLY (0 << 0) +// +// Bit [2:1] : Memory Attributes, _MEM +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_NON_CACHEABLE (0 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE (1 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_WRITE_COMBINING (2 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE (3 << 1) +// +// Bit [4:3] : Memory Attributes, _MTP +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_MEMORY (0 << 3) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_RESERVED (1 << 3) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_ACPI (2 << 3) +#define EFI_APCI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_NVS (3 << 3) +// +// Bit [5] : Memory to I/O Translation, _TTP +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_TRANSLATION (1 << 5) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_STATIC (0 << 5) + +// +// IRQ Information +// Ref ACPI specification 6.4.2.1 +// +#define EFI_ACPI_IRQ_SHARABLE_MASK 0x10 +#define EFI_ACPI_IRQ_SHARABLE 0x10 + +#define EFI_ACPI_IRQ_POLARITY_MASK 0x08 +#define EFI_ACPI_IRQ_HIGH_TRUE 0x00 +#define EFI_ACPI_IRQ_LOW_FALSE 0x08 + +#define EFI_ACPI_IRQ_MODE 0x01 +#define EFI_ACPI_IRQ_LEVEL_TRIGGERED 0x00 +#define EFI_ACPI_IRQ_EDGE_TRIGGERED 0x01 + +// +// DMA Information +// Ref ACPI specification 6.4.2.2 +// +#define EFI_ACPI_DMA_SPEED_TYPE_MASK 0x60 +#define EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY 0x00 +#define EFI_ACPI_DMA_SPEED_TYPE_A 0x20 +#define EFI_ACPI_DMA_SPEED_TYPE_B 0x40 +#define EFI_ACPI_DMA_SPEED_TYPE_F 0x60 + +#define EFI_ACPI_DMA_BUS_MASTER_MASK 0x04 +#define EFI_ACPI_DMA_BUS_MASTER 0x04 + +#define EFI_ACPI_DMA_TRANSFER_TYPE_MASK 0x03 +#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x00 +#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x01 +#define EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x10 + +// +// IO Information +// Ref ACPI specification 6.4.2.5 +// +#define EFI_ACPI_IO_DECODE_MASK 0x01 +#define EFI_ACPI_IO_DECODE_16_BIT 0x01 +#define EFI_ACPI_IO_DECODE_10_BIT 0x00 + +// +// Memory Information +// Ref ACPI specification 6.4.3.4 +// +#define EFI_ACPI_MEMORY_WRITE_STATUS_MASK 0x01 +#define EFI_ACPI_MEMORY_WRITABLE 0x01 +#define EFI_ACPI_MEMORY_NON_WRITABLE 0x00 + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI 1.0b table structures +// + +/// +/// Root System Description Pointer Structure. +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Reserved; + UINT32 RsdtAddress; +} EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 1.0b specification). +/// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT). +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 IntModel; + UINT8 Reserved1; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 Reserved2; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 Reserved3; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT8 Reserved4; + UINT8 Reserved5; + UINT8 Reserved6; + UINT32 Flags; +} EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 1.0b specification). +/// +#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x01 + +#define EFI_ACPI_1_0_INT_MODE_DUAL_PIC 0 +#define EFI_ACPI_1_0_INT_MODE_MULTIPLE_APIC 1 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_WBINVD BIT0 +#define EFI_ACPI_1_0_WBINVD_FLUSH BIT1 +#define EFI_ACPI_1_0_PROC_C1 BIT2 +#define EFI_ACPI_1_0_P_LVL2_UP BIT3 +#define EFI_ACPI_1_0_PWR_BUTTON BIT4 +#define EFI_ACPI_1_0_SLP_BUTTON BIT5 +#define EFI_ACPI_1_0_FIX_RTC BIT6 +#define EFI_ACPI_1_0_RTC_S4 BIT7 +#define EFI_ACPI_1_0_TMR_VAL_EXT BIT8 +#define EFI_ACPI_1_0_DCK_CAP BIT9 + +/// +/// Firmware ACPI Control Structure. +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT8 Reserved[40]; +} EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// Firmware Control Structure Feature Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_1_0_S4BIOS_F BIT0 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform-specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 1.0b specification). +/// +#define EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_1_0_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x05 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_1_0_IO_APIC 0x01 +#define EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_1_0_LOCAL_APIC_NMI 0x04 + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition. +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_1_0_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 SystemVectorBase; +} EFI_ACPI_1_0_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterruptVector; + UINT16 Flags; +} EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Non-Maskable Interrupt Source Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterruptVector; +} EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicInti; +} EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_1_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer. +/// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table. +/// +#define EFI_ACPI_1_0_APIC_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "DSDT" Differentiated System Description Table. +/// +#define EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "FACS" Firmware ACPI Control Structure. +/// +#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FACP" Fixed ACPI Description Table. +/// +#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "PSDT" Persistent System Description Table. +/// +#define EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RSDT" Root System Description Table. +/// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table. +/// +#define EFI_ACPI_1_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SSDT" Secondary System Description Table. +/// +#define EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi20.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi20.h new file mode 100644 index 0000000..8ee1f7f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi20.h @@ -0,0 +1,545 @@ +/** @file + ACPI 2.0 definitions from the ACPI Specification, revision 2.0 + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_2_0_H_ +#define _ACPI_2_0_H_ + +#include + +// +// Define for Desriptor +// +#define ACPI_LARGE_GENERIC_REGISTER_DESCRIPTOR_NAME 0x02 + +#define ACPI_GENERIC_REGISTER_DESCRIPTOR 0x82 + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// Generic Register Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AddressSize; + UINT64 RegisterAddress; +} EFI_ACPI_GENERIC_REGISTER_DESCRIPTOR; + +#pragma pack() + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 2.0 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 Reserved; + UINT64 Address; +} EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_2_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_2_0_SYSTEM_IO 1 +#define EFI_ACPI_2_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_2_0_SMBUS 4 +#define EFI_ACPI_2_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// ACPI 2.0 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_2_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x03 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_2_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_2_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_2_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_2_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_2_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_2_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_2_0_PM_PROFILE_APPLIANCE_PC 6 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_LEGACY_DEVICES BIT0 +#define EFI_ACPI_2_0_8042 BIT1 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_WBINVD BIT0 +#define EFI_ACPI_2_0_WBINVD_FLUSH BIT1 +#define EFI_ACPI_2_0_PROC_C1 BIT2 +#define EFI_ACPI_2_0_P_LVL2_UP BIT3 +#define EFI_ACPI_2_0_PWR_BUTTON BIT4 +#define EFI_ACPI_2_0_SLP_BUTTON BIT5 +#define EFI_ACPI_2_0_FIX_RTC BIT6 +#define EFI_ACPI_2_0_RTC_S4 BIT7 +#define EFI_ACPI_2_0_TMR_VAL_EXT BIT8 +#define EFI_ACPI_2_0_DCK_CAP BIT9 +#define EFI_ACPI_2_0_RESET_REG_SUP BIT10 +#define EFI_ACPI_2_0_SEALED_CASE BIT11 +#define EFI_ACPI_2_0_HEADLESS BIT12 +#define EFI_ACPI_2_0_CPU_SW_SLP BIT13 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved[31]; +} EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x01 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_2_0_S4BIOS_F BIT0 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_2_0_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_2_0_IO_APIC 0x01 +#define EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_2_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_2_0_IO_SAPIC 0x06 +#define EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC 0x07 +#define EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES 0x08 + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_2_0_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_2_0_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_2_0_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; +} EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 Reserved; +} EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_2_0_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 2.0 spec.) +/// +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "SPIC" Multiple SAPIC Description Table +/// +/// BUGBUG: Don't know where this came from except SR870BN4 uses it. +/// #define EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE 0x43495053 +/// +#define EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_2_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "DBGP" MS Bebug Port Spec +/// +#define EFI_ACPI_2_0_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_2_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_2_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_2_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_2_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SRAT" Static Resource Affinity Table +/// +#define EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_2_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_2_0_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi30.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi30.h new file mode 100644 index 0000000..608968d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi30.h @@ -0,0 +1,729 @@ +/** @file + ACPI 3.0 definitions from the ACPI Specification Revision 3.0b October 10, 2006 + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_3_0_H_ +#define _ACPI_3_0_H_ + +#include + +// +// Define for Desriptor +// +#define ACPI_LARGE_EXTENDED_ADDRESS_SPACE_DESCRIPTOR_NAME 0x0B + +#define ACPI_EXTENDED_ADDRESS_SPACE_DESCRIPTOR 0x8B + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// Extended Address Space Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT8 RevisionId; + UINT8 Reserved; + UINT64 AddrSpaceGranularity; + UINT64 AddrRangeMin; + UINT64 AddrRangeMax; + UINT64 AddrTranslationOffset; + UINT64 AddrLen; + UINT64 TypeSpecificAttribute; +} EFI_ACPI_EXTENDED_ADDRESS_SPACE_DESCRIPTOR; + +#pragma pack() + +// +// Memory Type Specific Flags +// +#define EFI_ACPI_MEMORY_TYPE_SPECIFIC_ATTRIBUTES_UC 0x0000000000000001 +#define EFI_ACPI_MEMORY_TYPE_SPECIFIC_ATTRIBUTES_WC 0x0000000000000002 +#define EFI_ACPI_MEMORY_TYPE_SPECIFIC_ATTRIBUTES_WT 0x0000000000000004 +#define EFI_ACPI_MEMORY_TYPE_SPECIFIC_ATTRIBUTES_WB 0x0000000000000008 +#define EFI_ACPI_MEMORY_TYPE_SPECIFIC_ATTRIBUTES_UCE 0x0000000000000010 +#define EFI_ACPI_MEMORY_TYPE_SPECIFIC_ATTRIBUTES_NV 0x0000000000008000 + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 3.0 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_3_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_3_0_SYSTEM_IO 1 +#define EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_3_0_SMBUS 4 +#define EFI_ACPI_3_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_3_0_UNDEFINED 0 +#define EFI_ACPI_3_0_BYTE 1 +#define EFI_ACPI_3_0_WORD 2 +#define EFI_ACPI_3_0_DWORD 3 +#define EFI_ACPI_3_0_QWORD 4 + +// +// ACPI 3.0 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 3.0b spec.) +/// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 3.0b) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_3_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x04 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_3_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_3_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_3_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_3_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_3_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_3_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_3_0_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_3_0_PM_PROFILE_PERFORMANCE_SERVER 7 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_LEGACY_DEVICES BIT0 +#define EFI_ACPI_3_0_8042 BIT1 +#define EFI_ACPI_3_0_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_3_0_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_3_0_PCIE_ASPM_CONTROLS BIT4 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_WBINVD BIT0 +#define EFI_ACPI_3_0_WBINVD_FLUSH BIT1 +#define EFI_ACPI_3_0_PROC_C1 BIT2 +#define EFI_ACPI_3_0_P_LVL2_UP BIT3 +#define EFI_ACPI_3_0_PWR_BUTTON BIT4 +#define EFI_ACPI_3_0_SLP_BUTTON BIT5 +#define EFI_ACPI_3_0_FIX_RTC BIT6 +#define EFI_ACPI_3_0_RTC_S4 BIT7 +#define EFI_ACPI_3_0_TMR_VAL_EXT BIT8 +#define EFI_ACPI_3_0_DCK_CAP BIT9 +#define EFI_ACPI_3_0_RESET_REG_SUP BIT10 +#define EFI_ACPI_3_0_SEALED_CASE BIT11 +#define EFI_ACPI_3_0_HEADLESS BIT12 +#define EFI_ACPI_3_0_CPU_SW_SLP BIT13 +#define EFI_ACPI_3_0_PCI_EXP_WAK BIT14 +#define EFI_ACPI_3_0_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_3_0_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_3_0_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_3_0_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_3_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved[31]; +} EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x01 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_3_0_S4BIOS_F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_3_0_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_3_0_IO_APIC 0x01 +#define EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_3_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_3_0_IO_SAPIC 0x06 +#define EFI_ACPI_3_0_LOCAL_SAPIC 0x07 +#define EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES 0x08 + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_3_0_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_3_0_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_3_0_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_POLARITY (3 << 0) +#define EFI_ACPI_3_0_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_3_0_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_3_0_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_3_0_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x02 + +// +// SRAT structure types. +// All other values between 0x02 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_3_0_MEMORY_AFFINITY 0x01 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT8 Reserved[4]; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_3_0_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_3_0_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_3_0_MEMORY_NONVOLATILE (1 << 2) + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_3_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 3.0 spec.) +/// +#define EFI_ACPI_3_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_3_0_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_3_0_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WSPT" Windows Specific Properties Table +/// +#define EFI_ACPI_3_0_WINDOWS_SPECIFIC_PROPERTIES_TABLE_SIGNATURE SIGNATURE_32('W', 'S', 'P', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi40.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi40.h new file mode 100644 index 0000000..fafafa4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi40.h @@ -0,0 +1,1309 @@ +/** @file + ACPI 4.0 definitions from the ACPI Specification Revision 4.0a April 5, 2010 + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_4_0_H_ +#define _ACPI_4_0_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 4.0 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_4_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_4_0_SYSTEM_IO 1 +#define EFI_ACPI_4_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_4_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_4_0_SMBUS 4 +#define EFI_ACPI_4_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_4_0_UNDEFINED 0 +#define EFI_ACPI_4_0_BYTE 1 +#define EFI_ACPI_4_0_WORD 2 +#define EFI_ACPI_4_0_DWORD 3 +#define EFI_ACPI_4_0_QWORD 4 + +// +// ACPI 4.0 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 4.0b spec.) +/// +#define EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 4.0a) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_4_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_4_0_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x04 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_4_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_4_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_4_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_4_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_4_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_4_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_4_0_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_4_0_PM_PROFILE_PERFORMANCE_SERVER 7 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_4_0_LEGACY_DEVICES BIT0 +#define EFI_ACPI_4_0_8042 BIT1 +#define EFI_ACPI_4_0_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_4_0_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_4_0_PCIE_ASPM_CONTROLS BIT4 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_4_0_WBINVD BIT0 +#define EFI_ACPI_4_0_WBINVD_FLUSH BIT1 +#define EFI_ACPI_4_0_PROC_C1 BIT2 +#define EFI_ACPI_4_0_P_LVL2_UP BIT3 +#define EFI_ACPI_4_0_PWR_BUTTON BIT4 +#define EFI_ACPI_4_0_SLP_BUTTON BIT5 +#define EFI_ACPI_4_0_FIX_RTC BIT6 +#define EFI_ACPI_4_0_RTC_S4 BIT7 +#define EFI_ACPI_4_0_TMR_VAL_EXT BIT8 +#define EFI_ACPI_4_0_DCK_CAP BIT9 +#define EFI_ACPI_4_0_RESET_REG_SUP BIT10 +#define EFI_ACPI_4_0_SEALED_CASE BIT11 +#define EFI_ACPI_4_0_HEADLESS BIT12 +#define EFI_ACPI_4_0_CPU_SW_SLP BIT13 +#define EFI_ACPI_4_0_PCI_EXP_WAK BIT14 +#define EFI_ACPI_4_0_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_4_0_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_4_0_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_4_0_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_4_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved0[3]; + UINT32 OspmFlags; + UINT8 Reserved1[24]; +} EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x02 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_4_0_S4BIOS_F BIT0 +#define EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F BIT1 + +/// +/// OSPM Enabled Firmware Control Structure Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_4_0_OSPM_64BIT_WAKE__F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_4_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_4_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x03 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_4_0_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x0B an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_4_0_IO_APIC 0x01 +#define EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_4_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_4_0_IO_SAPIC 0x06 +#define EFI_ACPI_4_0_LOCAL_SAPIC 0x07 +#define EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES 0x08 +#define EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC 0x09 +#define EFI_ACPI_4_0_LOCAL_X2APIC_NMI 0x0A + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_4_0_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_4_0_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_4_0_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_4_0_POLARITY (3 << 0) +#define EFI_ACPI_4_0_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_4_0_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_4_0_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Processor Local x2APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 AcpiProcessorUid; +} EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE; + +/// +/// Local x2APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 AcpiProcessorUid; + UINT8 LocalX2ApicLint; + UINT8 Reserved[3]; +} EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_4_0_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_4_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_4_0_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x03 + +// +// SRAT structure types. +// All other values between 0x03 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_4_0_MEMORY_AFFINITY 0x01 +#define EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_AFFINITY 0x02 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT32 ClockDomain; +} EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_4_0_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_4_0_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_4_0_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_4_0_MEMORY_NONVOLATILE (1 << 2) + +/// +/// Processor Local x2APIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved1[2]; + UINT32 ProximityDomain; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT8 Reserved2[4]; +} EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE; + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_4_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +/// +/// Corrected Platform Error Polling Table (CPEP) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[8]; +} EFI_ACPI_4_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_HEADER; + +/// +/// CPEP Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_REVISION 0x01 + +// +// CPEP processor structure types. +// +#define EFI_ACPI_4_0_CPEP_PROCESSOR_APIC_SAPIC 0x00 + +/// +/// Corrected Platform Error Polling Processor Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT32 PollingInterval; +} EFI_ACPI_4_0_CPEP_PROCESSOR_APIC_SAPIC_STRUCTURE; + +/// +/// Maximum System Characteristics Table (MSCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetProxDomInfo; + UINT32 MaximumNumberOfProximityDomains; + UINT32 MaximumNumberOfClockDomains; + UINT64 MaximumPhysicalAddress; +} EFI_ACPI_4_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_HEADER; + +/// +/// MSCT Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_REVISION 0x01 + +/// +/// Maximum Proximity Domain Information Structure Definition +/// +typedef struct { + UINT8 Revision; + UINT8 Length; + UINT32 ProximityDomainRangeLow; + UINT32 ProximityDomainRangeHigh; + UINT32 MaximumProcessorCapacity; + UINT64 MaximumMemoryCapacity; +} EFI_ACPI_4_0_MAXIMUM_PROXIMITY_DOMAIN_INFORMATION_STRUCTURE; + +/// +/// Boot Error Record Table (BERT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 BootErrorRegionLength; + UINT64 BootErrorRegion; +} EFI_ACPI_4_0_BOOT_ERROR_RECORD_TABLE_HEADER; + +/// +/// BERT Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_BOOT_ERROR_RECORD_TABLE_REVISION 0x01 + +/// +/// Boot Error Region Block Status Definition +/// +typedef struct { + UINT32 UncorrectableErrorValid:1; + UINT32 CorrectableErrorValid:1; + UINT32 MultipleUncorrectableErrors:1; + UINT32 MultipleCorrectableErrors:1; + UINT32 ErrorDataEntryCount:10; + UINT32 Reserved:18; +} EFI_ACPI_4_0_ERROR_BLOCK_STATUS; + +/// +/// Boot Error Region Definition +/// +typedef struct { + EFI_ACPI_4_0_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_4_0_BOOT_ERROR_REGION_STRUCTURE; + +// +// Boot Error Severity types +// +#define EFI_ACPI_4_0_ERROR_SEVERITY_CORRECTABLE 0x00 +#define EFI_ACPI_4_0_ERROR_SEVERITY_FATAL 0x01 +#define EFI_ACPI_4_0_ERROR_SEVERITY_CORRECTED 0x02 +#define EFI_ACPI_4_0_ERROR_SEVERITY_NONE 0x03 + +/// +/// Generic Error Data Entry Definition +/// +typedef struct { + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; +} EFI_ACPI_4_0_GENERIC_ERROR_DATA_ENTRY_STRUCTURE; + +/// +/// Generic Error Data Entry Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_GENERIC_ERROR_DATA_ENTRY_REVISION 0x0201 + +/// +/// HEST - Hardware Error Source Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ErrorSourceCount; +} EFI_ACPI_4_0_HARDWARE_ERROR_SOURCE_TABLE_HEADER; + +/// +/// HEST Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_HARDWARE_ERROR_SOURCE_TABLE_REVISION 0x01 + +// +// Error Source structure types. +// +#define EFI_ACPI_4_0_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION 0x00 +#define EFI_ACPI_4_0_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK 0x01 +#define EFI_ACPI_4_0_IA32_ARCHITECTURE_NMI_ERROR 0x02 +#define EFI_ACPI_4_0_PCI_EXPRESS_ROOT_PORT_AER 0x06 +#define EFI_ACPI_4_0_PCI_EXPRESS_DEVICE_AER 0x07 +#define EFI_ACPI_4_0_PCI_EXPRESS_BRIDGE_AER 0x08 +#define EFI_ACPI_4_0_GENERIC_HARDWARE_ERROR 0x09 + +// +// Error Source structure flags. +// +#define EFI_ACPI_4_0_ERROR_SOURCE_FLAG_FIRMWARE_FIRST (1 << 0) +#define EFI_ACPI_4_0_ERROR_SOURCE_FLAG_GLOBAL (1 << 1) + +/// +/// IA-32 Architecture Machine Check Exception Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityInitData; + UINT64 GlobalControlInitData; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[7]; +} EFI_ACPI_4_0_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure Definition +/// +typedef struct { + UINT8 BankNumber; + UINT8 ClearStatusOnInitialization; + UINT8 StatusDataFormat; + UINT8 Reserved0; + UINT32 ControlRegisterMsrAddress; + UINT64 ControlInitData; + UINT32 StatusRegisterMsrAddress; + UINT32 AddressRegisterMsrAddress; + UINT32 MiscRegisterMsrAddress; +} EFI_ACPI_4_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure MCA data format +/// +#define EFI_ACPI_4_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_IA32 0x00 +#define EFI_ACPI_4_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_INTEL64 0x01 +#define EFI_ACPI_4_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_AMD64 0x02 + +// +// Hardware Error Notification types. All other values are reserved +// +#define EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_POLLED 0x00 +#define EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_EXTERNAL_INTERRUPT 0x01 +#define EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_LOCAL_INTERRUPT 0x02 +#define EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_SCI 0x03 +#define EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_NMI 0x04 + +/// +/// Hardware Error Notification Configuration Write Enable Structure Definition +/// +typedef struct { + UINT16 Type:1; + UINT16 PollInterval:1; + UINT16 SwitchToPollingThresholdValue:1; + UINT16 SwitchToPollingThresholdWindow:1; + UINT16 ErrorThresholdValue:1; + UINT16 ErrorThresholdWindow:1; + UINT16 Reserved:10; +} EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE; + +/// +/// Hardware Error Notification Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE ConfigurationWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 SwitchToPollingThresholdValue; + UINT32 SwitchToPollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; +} EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE; + +/// +/// IA-32 Architecture Corrected Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_4_0_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE; + +/// +/// IA-32 Architecture NMI Error Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; +} EFI_ACPI_4_0_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE; + +/// +/// PCI Express Root Port AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 RootErrorCommand; +} EFI_ACPI_4_0_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE; + +/// +/// PCI Express Device AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_4_0_PCI_EXPRESS_DEVICE_AER_STRUCTURE; + +/// +/// PCI Express Bridge AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 SecondaryUncorrectableErrorMask; + UINT32 SecondaryUncorrectableErrorSeverity; + UINT32 SecondaryAdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_4_0_PCI_EXPRESS_BRIDGE_AER_STRUCTURE; + +/// +/// Generic Hardware Error Source Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_4_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; +} EFI_ACPI_4_0_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE; + +/// +/// Generic Error Status Definition +/// +typedef struct { + EFI_ACPI_4_0_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_4_0_GENERIC_ERROR_STATUS_STRUCTURE; + +/// +/// ERST - Error Record Serialization Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 SerializationHeaderSize; + UINT8 Reserved0[4]; + UINT32 InstructionEntryCount; +} EFI_ACPI_4_0_ERROR_RECORD_SERIALIZATION_TABLE_HEADER; + +/// +/// ERST Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_ERROR_RECORD_SERIALIZATION_TABLE_REVISION 0x01 + +/// +/// ERST Serialization Actions +/// +#define EFI_ACPI_4_0_ERST_BEGIN_WRITE_OPERATION 0x00 +#define EFI_ACPI_4_0_ERST_BEGIN_READ_OPERATION 0x01 +#define EFI_ACPI_4_0_ERST_BEGIN_CLEAR_OPERATION 0x02 +#define EFI_ACPI_4_0_ERST_END_OPERATION 0x03 +#define EFI_ACPI_4_0_ERST_SET_RECORD_OFFSET 0x04 +#define EFI_ACPI_4_0_ERST_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_4_0_ERST_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_4_0_ERST_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_4_0_ERST_GET_RECORD_IDENTIFIER 0x08 +#define EFI_ACPI_4_0_ERST_SET_RECORD_IDENTIFIER 0x09 +#define EFI_ACPI_4_0_ERST_GET_RECORD_COUNT 0x0A +#define EFI_ACPI_4_0_ERST_BEGIN_DUMMY_WRITE_OPERATION 0x0B +#define EFI_ACPI_4_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE 0x0D +#define EFI_ACPI_4_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE_LENGTH 0x0E +#define EFI_ACPI_4_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0x0F + +/// +/// ERST Action Command Status +/// +#define EFI_ACPI_4_0_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_4_0_EINJ_STATUS_NOT_ENOUGH_SPACE 0x01 +#define EFI_ACPI_4_0_EINJ_STATUS_HARDWARE_NOT_AVAILABLE 0x02 +#define EFI_ACPI_4_0_EINJ_STATUS_FAILED 0x03 +#define EFI_ACPI_4_0_EINJ_STATUS_RECORD_STORE_EMPTY 0x04 +#define EFI_ACPI_4_0_EINJ_STATUS_RECORD_NOT_FOUND 0x05 + +/// +/// ERST Serialization Instructions +/// +#define EFI_ACPI_4_0_ERST_READ_REGISTER 0x00 +#define EFI_ACPI_4_0_ERST_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_4_0_ERST_WRITE_REGISTER 0x02 +#define EFI_ACPI_4_0_ERST_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_4_0_ERST_NOOP 0x04 +#define EFI_ACPI_4_0_ERST_LOAD_VAR1 0x05 +#define EFI_ACPI_4_0_ERST_LOAD_VAR2 0x06 +#define EFI_ACPI_4_0_ERST_STORE_VAR1 0x07 +#define EFI_ACPI_4_0_ERST_ADD 0x08 +#define EFI_ACPI_4_0_ERST_SUBTRACT 0x09 +#define EFI_ACPI_4_0_ERST_ADD_VALUE 0x0A +#define EFI_ACPI_4_0_ERST_SUBTRACT_VALUE 0x0B +#define EFI_ACPI_4_0_ERST_STALL 0x0C +#define EFI_ACPI_4_0_ERST_STALL_WHILE_TRUE 0x0D +#define EFI_ACPI_4_0_ERST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E +#define EFI_ACPI_4_0_ERST_GOTO 0x0F +#define EFI_ACPI_4_0_ERST_SET_SRC_ADDRESS_BASE 0x10 +#define EFI_ACPI_4_0_ERST_SET_DST_ADDRESS_BASE 0x11 +#define EFI_ACPI_4_0_ERST_MOVE_DATA 0x12 + +/// +/// ERST Instruction Flags +/// +#define EFI_ACPI_4_0_ERST_PRESERVE_REGISTER 0x01 + +/// +/// ERST Serialization Instruction Entry +/// +typedef struct { + UINT8 SerializationAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_4_0_ERST_SERIALIZATION_INSTRUCTION_ENTRY; + +/// +/// EINJ - Error Injection Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 InjectionHeaderSize; + UINT8 InjectionFlags; + UINT8 Reserved0[3]; + UINT32 InjectionEntryCount; +} EFI_ACPI_4_0_ERROR_INJECTION_TABLE_HEADER; + +/// +/// EINJ Version (as defined in ACPI 4.0 spec.) +/// +#define EFI_ACPI_4_0_ERROR_INJECTION_TABLE_REVISION 0x01 + +/// +/// EINJ Error Injection Actions +/// +#define EFI_ACPI_4_0_EINJ_BEGIN_INJECTION_OPERATION 0x00 +#define EFI_ACPI_4_0_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE 0x01 +#define EFI_ACPI_4_0_EINJ_SET_ERROR_TYPE 0x02 +#define EFI_ACPI_4_0_EINJ_GET_ERROR_TYPE 0x03 +#define EFI_ACPI_4_0_EINJ_END_OPERATION 0x04 +#define EFI_ACPI_4_0_EINJ_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_4_0_EINJ_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_4_0_EINJ_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_4_0_EINJ_TRIGGER_ERROR 0xFF + +/// +/// EINJ Action Command Status +/// +#define EFI_ACPI_4_0_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_4_0_EINJ_STATUS_UNKNOWN_FAILURE 0x01 +#define EFI_ACPI_4_0_EINJ_STATUS_INVALID_ACCESS 0x02 + +/// +/// EINJ Error Type Definition +/// +#define EFI_ACPI_4_0_EINJ_ERROR_PROCESSOR_CORRECTABLE (1 << 0) +#define EFI_ACPI_4_0_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_NONFATAL (1 << 1) +#define EFI_ACPI_4_0_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_FATAL (1 << 2) +#define EFI_ACPI_4_0_EINJ_ERROR_MEMORY_CORRECTABLE (1 << 3) +#define EFI_ACPI_4_0_EINJ_ERROR_MEMORY_UNCORRECTABLE_NONFATAL (1 << 4) +#define EFI_ACPI_4_0_EINJ_ERROR_MEMORY_UNCORRECTABLE_FATAL (1 << 5) +#define EFI_ACPI_4_0_EINJ_ERROR_PCI_EXPRESS_CORRECTABLE (1 << 6) +#define EFI_ACPI_4_0_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_NONFATAL (1 << 7) +#define EFI_ACPI_4_0_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_FATAL (1 << 8) +#define EFI_ACPI_4_0_EINJ_ERROR_PLATFORM_CORRECTABLE (1 << 9) +#define EFI_ACPI_4_0_EINJ_ERROR_PLATFORM_UNCORRECTABLE_NONFATAL (1 << 10) +#define EFI_ACPI_4_0_EINJ_ERROR_PLATFORM_UNCORRECTABLE_FATAL (1 << 11) + +/// +/// EINJ Injection Instructions +/// +#define EFI_ACPI_4_0_EINJ_READ_REGISTER 0x00 +#define EFI_ACPI_4_0_EINJ_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_4_0_EINJ_WRITE_REGISTER 0x02 +#define EFI_ACPI_4_0_EINJ_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_4_0_EINJ_NOOP 0x04 + +/// +/// EINJ Instruction Flags +/// +#define EFI_ACPI_4_0_EINJ_PRESERVE_REGISTER 0x01 + +/// +/// EINJ Injection Instruction Entry +/// +typedef struct { + UINT8 InjectionAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_4_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_4_0_EINJ_INJECTION_INSTRUCTION_ENTRY; + +/// +/// EINJ Trigger Action Table +/// +typedef struct { + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; +} EFI_ACPI_4_0_EINJ_TRIGGER_ACTION_TABLE; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BERT" Boot Error Record Table +/// +#define EFI_ACPI_4_0_BOOT_ERROR_RECORD_TABLE_SIGNATURE SIGNATURE_32('B', 'E', 'R', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_4_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_4_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_4_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "EINJ" Error Injection Table +/// +#define EFI_ACPI_4_0_ERROR_INJECTION_TABLE_SIGNATURE SIGNATURE_32('E', 'I', 'N', 'J') + +/// +/// "ERST" Error Record Serialization Table +/// +#define EFI_ACPI_4_0_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE SIGNATURE_32('E', 'R', 'S', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_4_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "HEST" Hardware Error Source Table +/// +#define EFI_ACPI_4_0_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('H', 'E', 'S', 'T') + +/// +/// "MSCT" Maximum System Characteristics Table +/// +#define EFI_ACPI_4_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'C', 'T') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_4_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_4_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_4_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_4_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_4_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_4_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_4_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_4_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_4_0_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DMAR" DMA Remapping Table +/// +#define EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('D', 'M', 'A', 'R') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_4_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_4_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_4_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +/// +/// "IVRS" I/O Virtualization Reporting Structure +/// +#define EFI_ACPI_4_0_IO_VIRTUALIZATION_REPORTING_STRUCTURE_SIGNATURE SIGNATURE_32('I', 'V', 'R', 'S') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_4_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "MCHI" Management Controller Host Interface Table +/// +#define EFI_ACPI_4_0_MANAGEMENT_CONTROLLER_HOST_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'H', 'I') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_4_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_4_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_4_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "UEFI" UEFI ACPI Data Table +/// +#define EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE SIGNATURE_32('U', 'E', 'F', 'I') + +/// +/// "WAET" Windows ACPI Enlightenment Table +/// +#define EFI_ACPI_4_0_WINDOWS_ACPI_ENLIGHTENMENT_TABLE_SIGNATURE SIGNATURE_32('W', 'A', 'E', 'T') + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_4_0_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_4_0_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi50.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi50.h new file mode 100644 index 0000000..23f5f3f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi50.h @@ -0,0 +1,2119 @@ +/** @file + ACPI 5.0 definitions from the ACPI Specification Revision 5.0a November 13, 2013. + + Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_5_0_H_ +#define _ACPI_5_0_H_ + +#include + +// +// Define for Desriptor +// +#define ACPI_SMALL_FIXED_DMA_DESCRIPTOR_NAME 0x0A +#define ACPI_LARGE_GPIO_CONNECTION_DESCRIPTOR_NAME 0x0C +#define ACPI_LARGE_GENERIC_SERIAL_BUS_CONNECTION_DESCRIPTOR_NAME 0x0E + +#define ACPI_FIXED_DMA_DESCRIPTOR 0x55 +#define ACPI_GPIO_CONNECTION_DESCRIPTOR 0x8C +#define ACPI_GENERIC_SERIAL_BUS_CONNECTION_DESCRIPTOR 0x8E + +#pragma pack(1) + +/// +/// Generic DMA Descriptor. +/// +typedef PACKED struct { + ACPI_SMALL_RESOURCE_HEADER Header; + UINT16 DmaRequestLine; + UINT16 DmaChannel; + UINT8 DmaTransferWidth; +} EFI_ACPI_FIXED_DMA_DESCRIPTOR; + +/// +/// GPIO Connection Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT8 ConnectionType; + UINT16 GeneralFlags; + UINT16 InterruptFlags; + UINT8 PinConfiguration; + UINT16 OutputDriveStrength; + UINT16 DebounceTimeout; + UINT16 PinTableOffset; + UINT8 ResourceSourceIndex; + UINT16 ResourceSourceNameOffset; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; +} EFI_ACPI_GPIO_CONNECTION_DESCRIPTOR; + +#define EFI_ACPI_GPIO_CONNECTION_TYPE_INTERRUPT 0x0 +#define EFI_ACPI_GPIO_CONNECTION_TYPE_IO 0x1 + +/// +/// Serial Bus Resource Descriptor (Generic) +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT8 ResourceSourceIndex; + UINT8 SerialBusType; + UINT8 GeneralFlags; + UINT16 TypeSpecificFlags; + UINT8 TypeSpecificRevisionId; + UINT16 TypeDataLength; +// Type specific data +} EFI_ACPI_SERIAL_BUS_RESOURCE_DESCRIPTOR; + +#define EFI_ACPI_SERIAL_BUS_RESOURCE_TYPE_I2C 0x1 +#define EFI_ACPI_SERIAL_BUS_RESOURCE_TYPE_SPI 0x2 +#define EFI_ACPI_SERIAL_BUS_RESOURCE_TYPE_UART 0x3 + +/// +/// Serial Bus Resource Descriptor (I2C) +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT8 ResourceSourceIndex; + UINT8 SerialBusType; + UINT8 GeneralFlags; + UINT16 TypeSpecificFlags; + UINT8 TypeSpecificRevisionId; + UINT16 TypeDataLength; + UINT32 ConnectionSpeed; + UINT16 SlaveAddress; +} EFI_ACPI_SERIAL_BUS_RESOURCE_I2C_DESCRIPTOR; + +/// +/// Serial Bus Resource Descriptor (SPI) +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT8 ResourceSourceIndex; + UINT8 SerialBusType; + UINT8 GeneralFlags; + UINT16 TypeSpecificFlags; + UINT8 TypeSpecificRevisionId; + UINT16 TypeDataLength; + UINT32 ConnectionSpeed; + UINT8 DataBitLength; + UINT8 Phase; + UINT8 Polarity; + UINT16 DeviceSelection; +} EFI_ACPI_SERIAL_BUS_RESOURCE_SPI_DESCRIPTOR; + +/// +/// Serial Bus Resource Descriptor (UART) +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT8 ResourceSourceIndex; + UINT8 SerialBusType; + UINT8 GeneralFlags; + UINT16 TypeSpecificFlags; + UINT8 TypeSpecificRevisionId; + UINT16 TypeDataLength; + UINT32 DefaultBaudRate; + UINT16 RxFIFO; + UINT16 TxFIFO; + UINT8 Parity; + UINT8 SerialLinesEnabled; +} EFI_ACPI_SERIAL_BUS_RESOURCE_UART_DESCRIPTOR; + +#pragma pack() + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 5.0 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_5_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_5_0_SYSTEM_IO 1 +#define EFI_ACPI_5_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_5_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_5_0_SMBUS 4 +#define EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL 0x0A +#define EFI_ACPI_5_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_5_0_UNDEFINED 0 +#define EFI_ACPI_5_0_BYTE 1 +#define EFI_ACPI_5_0_WORD 2 +#define EFI_ACPI_5_0_DWORD 3 +#define EFI_ACPI_5_0_QWORD 4 + +// +// ACPI 5.0 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 5.0) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_5_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE SleepControlReg; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE SleepStatusReg; +} EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x05 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_5_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_5_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_5_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_5_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_5_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_5_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_5_0_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_5_0_PM_PROFILE_PERFORMANCE_SERVER 7 +#define EFI_ACPI_5_0_PM_PROFILE_TABLET 8 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_0_LEGACY_DEVICES BIT0 +#define EFI_ACPI_5_0_8042 BIT1 +#define EFI_ACPI_5_0_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_5_0_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_5_0_PCIE_ASPM_CONTROLS BIT4 +#define EFI_ACPI_5_0_CMOS_RTC_NOT_PRESENT BIT5 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_0_WBINVD BIT0 +#define EFI_ACPI_5_0_WBINVD_FLUSH BIT1 +#define EFI_ACPI_5_0_PROC_C1 BIT2 +#define EFI_ACPI_5_0_P_LVL2_UP BIT3 +#define EFI_ACPI_5_0_PWR_BUTTON BIT4 +#define EFI_ACPI_5_0_SLP_BUTTON BIT5 +#define EFI_ACPI_5_0_FIX_RTC BIT6 +#define EFI_ACPI_5_0_RTC_S4 BIT7 +#define EFI_ACPI_5_0_TMR_VAL_EXT BIT8 +#define EFI_ACPI_5_0_DCK_CAP BIT9 +#define EFI_ACPI_5_0_RESET_REG_SUP BIT10 +#define EFI_ACPI_5_0_SEALED_CASE BIT11 +#define EFI_ACPI_5_0_HEADLESS BIT12 +#define EFI_ACPI_5_0_CPU_SW_SLP BIT13 +#define EFI_ACPI_5_0_PCI_EXP_WAK BIT14 +#define EFI_ACPI_5_0_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_5_0_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_5_0_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_5_0_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_5_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 +#define EFI_ACPI_5_0_HW_REDUCED_ACPI BIT20 +#define EFI_ACPI_5_0_LOW_POWER_S0_IDLE_CAPABLE BIT21 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved0[3]; + UINT32 OspmFlags; + UINT8 Reserved1[24]; +} EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x02 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_0_S4BIOS_F BIT0 +#define EFI_ACPI_5_0_64BIT_WAKE_SUPPORTED_F BIT1 + +/// +/// OSPM Enabled Firmware Control Structure Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_0_OSPM_64BIT_WAKE_F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_5_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x03 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_0_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x0D and 0x7F are reserved and +// will be ignored by OSPM. 0x80 ~ 0xFF are reserved for OEM. +// +#define EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_5_0_IO_APIC 0x01 +#define EFI_ACPI_5_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_5_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_5_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_5_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_5_0_IO_SAPIC 0x06 +#define EFI_ACPI_5_0_LOCAL_SAPIC 0x07 +#define EFI_ACPI_5_0_PLATFORM_INTERRUPT_SOURCES 0x08 +#define EFI_ACPI_5_0_PROCESSOR_LOCAL_X2APIC 0x09 +#define EFI_ACPI_5_0_LOCAL_X2APIC_NMI 0x0A +#define EFI_ACPI_5_0_GIC 0x0B +#define EFI_ACPI_5_0_GICD 0x0C + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_0_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_5_0_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_5_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_5_0_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_0_POLARITY (3 << 0) +#define EFI_ACPI_5_0_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_5_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_5_0_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_5_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_5_0_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_5_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_5_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_0_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Processor Local x2APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 AcpiProcessorUid; +} EFI_ACPI_5_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE; + +/// +/// Local x2APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 AcpiProcessorUid; + UINT8 LocalX2ApicLint; + UINT8 Reserved[3]; +} EFI_ACPI_5_0_LOCAL_X2APIC_NMI_STRUCTURE; + +/// +/// GIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 GicId; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ParkingProtocolVersion; + UINT32 PerformanceInterruptGsiv; + UINT64 ParkedAddress; + UINT64 PhysicalBaseAddress; +} EFI_ACPI_5_0_GIC_STRUCTURE; + +/// +/// GIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_0_GIC_ENABLED BIT0 +#define EFI_ACPI_5_0_PERFORMANCE_INTERRUPT_MODEL BIT1 + +/// +/// GIC Distributor Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicId; + UINT64 PhysicalBaseAddress; + UINT32 SystemVectorBase; + UINT32 Reserved2; +} EFI_ACPI_5_0_GIC_DISTRIBUTOR_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_5_0_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_5_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT). The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_5_0_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x03 + +// +// SRAT structure types. +// All other values between 0x03 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_5_0_MEMORY_AFFINITY 0x01 +#define EFI_ACPI_5_0_PROCESSOR_LOCAL_X2APIC_AFFINITY 0x02 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT32 ClockDomain; +} EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_5_0_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_5_0_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_5_0_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_5_0_MEMORY_NONVOLATILE (1 << 2) + +/// +/// Processor Local x2APIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved1[2]; + UINT32 ProximityDomain; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT8 Reserved2[4]; +} EFI_ACPI_5_0_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE; + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_5_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +/// +/// Corrected Platform Error Polling Table (CPEP) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[8]; +} EFI_ACPI_5_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_HEADER; + +/// +/// CPEP Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_REVISION 0x01 + +// +// CPEP processor structure types. +// +#define EFI_ACPI_5_0_CPEP_PROCESSOR_APIC_SAPIC 0x00 + +/// +/// Corrected Platform Error Polling Processor Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT32 PollingInterval; +} EFI_ACPI_5_0_CPEP_PROCESSOR_APIC_SAPIC_STRUCTURE; + +/// +/// Maximum System Characteristics Table (MSCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetProxDomInfo; + UINT32 MaximumNumberOfProximityDomains; + UINT32 MaximumNumberOfClockDomains; + UINT64 MaximumPhysicalAddress; +} EFI_ACPI_5_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_HEADER; + +/// +/// MSCT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_REVISION 0x01 + +/// +/// Maximum Proximity Domain Information Structure Definition +/// +typedef struct { + UINT8 Revision; + UINT8 Length; + UINT32 ProximityDomainRangeLow; + UINT32 ProximityDomainRangeHigh; + UINT32 MaximumProcessorCapacity; + UINT64 MaximumMemoryCapacity; +} EFI_ACPI_5_0_MAXIMUM_PROXIMITY_DOMAIN_INFORMATION_STRUCTURE; + +/// +/// ACPI RAS Feature Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier[12]; +} EFI_ACPI_5_0_RAS_FEATURE_TABLE; + +/// +/// RASF Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_RAS_FEATURE_TABLE_REVISION 0x01 + +/// +/// ACPI RASF Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT16 Version; + UINT8 RASCapabilities[16]; + UINT8 SetRASCapabilities[16]; + UINT16 NumberOfRASFParameterBlocks; + UINT32 SetRASCapabilitiesStatus; +} EFI_ACPI_5_0_RASF_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI RASF PCC command code +/// +#define EFI_ACPI_5_0_RASF_PCC_COMMAND_CODE_EXECUTE_RASF_COMMAND 0x01 + +/// +/// ACPI RASF Platform RAS Capabilities +/// +#define EFI_ACPI_5_0_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED 0x01 +#define EFI_ACPI_5_0_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED_AND_EXPOSED_TO_SOFTWARE 0x02 + +/// +/// ACPI RASF Parameter Block structure for PATROL_SCRUB +/// +typedef struct { + UINT16 Type; + UINT16 Version; + UINT16 Length; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; +} EFI_ACPI_5_0_RASF_PATROL_SCRUB_PLATFORM_BLOCK_STRUCTURE; + +/// +/// ACPI RASF Patrol Scrub command +/// +#define EFI_ACPI_5_0_RASF_PATROL_SCRUB_COMMAND_GET_PATROL_PARAMETERS 0x01 +#define EFI_ACPI_5_0_RASF_PATROL_SCRUB_COMMAND_START_PATROL_SCRUBBER 0x02 +#define EFI_ACPI_5_0_RASF_PATROL_SCRUB_COMMAND_STOP_PATROL_SCRUBBER 0x03 + +/// +/// Memory Power State Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier; + UINT8 Reserved[3]; +// Memory Power Node Structure +// Memory Power State Characteristics +} EFI_ACPI_5_0_MEMORY_POWER_STATUS_TABLE; + +/// +/// MPST Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_MEMORY_POWER_STATE_TABLE_REVISION 0x01 + +/// +/// MPST Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT32 MemoryPowerCommandRegister; + UINT32 MemoryPowerStatusRegister; + UINT32 PowerStateId; + UINT32 MemoryPowerNodeId; + UINT64 MemoryEnergyConsumed; + UINT64 ExpectedAveragePowerComsuned; +} EFI_ACPI_5_0_MPST_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI MPST PCC command code +/// +#define EFI_ACPI_5_0_MPST_PCC_COMMAND_CODE_EXECUTE_MPST_COMMAND 0x03 + +/// +/// ACPI MPST Memory Power command +/// +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_POWER_STATE 0x01 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_COMMAND_SET_MEMORY_POWER_STATE 0x02 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_COMMAND_GET_AVERAGE_POWER_CONSUMED 0x03 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_ENERGY_CONSUMED 0x04 + +/// +/// MPST Memory Power Node Table +/// +typedef struct { + UINT8 PowerStateValue; + UINT8 PowerStateInformationIndex; +} EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE; + +typedef struct { + UINT8 Flag; + UINT8 Reserved; + UINT16 MemoryPowerNodeId; + UINT32 Length; + UINT64 AddressBase; + UINT64 AddressLength; + UINT32 NumberOfPowerStates; + UINT32 NumberOfPhysicalComponents; +//EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE MemoryPowerState[NumberOfPowerStates]; +//UINT16 PhysicalComponentIdentifier[NumberOfPhysicalComponents]; +} EFI_ACPI_5_0_MPST_MEMORY_POWER_STRUCTURE; + +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_STRUCTURE_FLAG_ENABLE 0x01 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_STRUCTURE_FLAG_POWER_MANAGED 0x02 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_STRUCTURE_FLAG_HOT_PLUGGABLE 0x04 + +typedef struct { + UINT16 MemoryPowerNodeCount; + UINT8 Reserved[2]; +} EFI_ACPI_5_0_MPST_MEMORY_POWER_NODE_TABLE; + +/// +/// MPST Memory Power State Characteristics Table +/// +typedef struct { + UINT8 PowerStateStructureID; + UINT8 Flag; + UINT16 Reserved; + UINT32 AveragePowerConsumedInMPS0; + UINT32 RelativePowerSavingToMPS0; + UINT64 ExitLatencyToMPS0; +} EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE; + +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_MEMORY_CONTENT_PRESERVED 0x01 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_ENTRY 0x02 +#define EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_EXIT 0x04 + +typedef struct { + UINT16 MemoryPowerStateCharacteristicsCount; + UINT8 Reserved[2]; +} EFI_ACPI_5_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_TABLE; + +/// +/// Memory Topology Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_5_0_MEMORY_TOPOLOGY_TABLE; + +/// +/// PMTT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_MEMORY_TOPOLOGY_TABLE_REVISION 0x01 + +/// +/// Common Memory Aggregator Device Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + UINT16 Flags; + UINT16 Reserved1; +} EFI_ACPI_5_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Memory Aggregator Device Type +/// +#define EFI_ACPI_5_0_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_SOCKET 0x1 +#define EFI_ACPI_5_0_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_MEMORY_CONTROLLER 0x2 +#define EFI_ACPI_5_0_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_DIMM 0x3 + +/// +/// Socket Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_5_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 SocketIdentifier; + UINT16 Reserved; +//EFI_ACPI_5_0_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE MemoryController[]; +} EFI_ACPI_5_0_PMMT_SOCKET_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// MemoryController Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_5_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT32 ReadLatency; + UINT32 WriteLatency; + UINT32 ReadBandwidth; + UINT32 WriteBandwidth; + UINT16 OptimalAccessUnit; + UINT16 OptimalAccessAlignment; + UINT16 Reserved; + UINT16 NumberOfProximityDomains; +//UINT32 ProximityDomain[NumberOfProximityDomains]; +//EFI_ACPI_5_0_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE PhysicalComponent[]; +} EFI_ACPI_5_0_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// DIMM Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_5_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 PhysicalComponentIdentifier; + UINT16 Reserved; + UINT32 SizeOfDimm; + UINT32 SmbiosHandle; +} EFI_ACPI_5_0_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Boot Graphics Resource Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /// + /// 2-bytes (16 bit) version ID. This value must be 1. + /// + UINT16 Version; + /// + /// 1-byte status field indicating current status about the table. + /// Bits[7:1] = Reserved (must be zero) + /// Bit [0] = Valid. A one indicates the boot image graphic is valid. + /// + UINT8 Status; + /// + /// 1-byte enumerated type field indicating format of the image. + /// 0 = Bitmap + /// 1 - 255 Reserved (for future use) + /// + UINT8 ImageType; + /// + /// 8-byte (64 bit) physical address pointing to the firmware's in-memory copy + /// of the image bitmap. + /// + UINT64 ImageAddress; + /// + /// A 4-byte (32-bit) unsigned long describing the display X-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetX; + /// + /// A 4-byte (32-bit) unsigned long describing the display Y-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetY; +} EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE; + +/// +/// BGRT Revision +/// +#define EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION 1 + +/// +/// BGRT Version +/// +#define EFI_ACPI_5_0_BGRT_VERSION 0x01 + +/// +/// BGRT Status +/// +#define EFI_ACPI_5_0_BGRT_STATUS_NOT_DISPLAYED 0x00 +#define EFI_ACPI_5_0_BGRT_STATUS_DISPLAYED 0x01 +#define EFI_ACPI_5_0_BGRT_STATUS_INVALID EFI_ACPI_5_0_BGRT_STATUS_NOT_DISPLAYED +#define EFI_ACPI_5_0_BGRT_STATUS_VALID EFI_ACPI_5_0_BGRT_STATUS_DISPLAYED + +/// +/// BGRT Image Type +/// +#define EFI_ACPI_5_0_BGRT_IMAGE_TYPE_BMP 0x00 + +/// +/// FPDT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION 0x01 + +/// +/// FPDT Performance Record Types +/// +#define EFI_ACPI_5_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER 0x0000 +#define EFI_ACPI_5_0_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER 0x0001 + +/// +/// FPDT Performance Record Revision +/// +#define EFI_ACPI_5_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER 0x01 +#define EFI_ACPI_5_0_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER 0x01 + +/// +/// FPDT Runtime Performance Record Types +/// +#define EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME 0x0000 +#define EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND 0x0001 +#define EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT 0x0002 + +/// +/// FPDT Runtime Performance Record Revision +/// +#define EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME 0x01 +#define EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND 0x01 +#define EFI_ACPI_5_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT 0x02 + +/// +/// FPDT Performance Record header +/// +typedef struct { + UINT16 Type; + UINT8 Length; + UINT8 Revision; +} EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER; + +/// +/// FPDT Performance Table header +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_5_0_FPDT_PERFORMANCE_TABLE_HEADER; + +/// +/// FPDT Firmware Basic Boot Performance Pointer Record Structure +/// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the Basic Boot Performance Table. + /// + UINT64 BootPerformanceTablePointer; +} EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT S3 Performance Table Pointer Record Structure +/// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the S3 Performance Table. + /// + UINT64 S3PerformanceTablePointer; +} EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Record Structure +/// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// Timer value logged at the beginning of firmware image execution. + /// This may not always be zero or near zero. + /// + UINT64 ResetEnd; + /// + /// Timer value logged just prior to loading the OS boot loader into memory. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 OsLoaderLoadImageStart; + /// + /// Timer value logged just prior to launching the previously loaded OS boot loader image. + /// For non-UEFI compatible boots, the timer value logged will be just prior + /// to the INT 19h handler invocation. + /// + UINT64 OsLoaderStartImageStart; + /// + /// Timer value logged at the point when the OS loader calls the + /// ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesEntry; + /// + /// Timer value logged at the point just prior towhen the OS loader gaining + /// control back from calls the ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesExit; +} EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Table signature +/// +#define EFI_ACPI_5_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('F', 'B', 'P', 'T') + +// +// FPDT Firmware Basic Boot Performance Table +// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_5_0_FPDT_FIRMWARE_BASIC_BOOT_TABLE; + +/// +/// FPDT "S3PT" S3 Performance Table +/// +#define EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('S', '3', 'P', 'T') + +// +// FPDT Firmware S3 Boot Performance Table +// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_5_0_FPDT_FIRMWARE_S3_BOOT_TABLE; + +/// +/// FPDT Basic S3 Resume Performance Record +/// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// A count of the number of S3 resume cycles since the last full boot sequence. + /// + UINT32 ResumeCount; + /// + /// Timer recorded at the end of BIOS S3 resume, just prior to handoff to the + /// OS waking vector. Only the most recent resume cycle's time is retained. + /// + UINT64 FullResume; + /// + /// Average timer value of all resume cycles logged since the last full boot + /// sequence, including the most recent resume. Note that the entire log of + /// timer values does not need to be retained in order to calculate this average. + /// + UINT64 AverageResume; +} EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD; + +/// +/// FPDT Basic S3 Suspend Performance Record +/// +typedef struct { + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// Timer value recorded at the OS write to SLP_TYP upon entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendStart; + /// + /// Timer value recorded at the final firmware write to SLP_TYP (or other + /// mechanism) used to trigger hardware entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendEnd; +} EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD; + +/// +/// Firmware Performance Record Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_RECORD_TABLE; + +/// +/// Generic Timer Description Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 PhysicalAddress; + UINT32 GlobalFlags; + UINT32 SecurePL1TimerGSIV; + UINT32 SecurePL1TimerFlags; + UINT32 NonSecurePL1TimerGSIV; + UINT32 NonSecurePL1TimerFlags; + UINT32 VirtualTimerGSIV; + UINT32 VirtualTimerFlags; + UINT32 NonSecurePL2TimerGSIV; + UINT32 NonSecurePL2TimerFlags; +} EFI_ACPI_5_0_GENERIC_TIMER_DESCRIPTION_TABLE; + +/// +/// GTDT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Global Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_0_GTDT_GLOBAL_FLAG_MEMORY_MAPPED_BLOCK_PRESENT BIT0 +#define EFI_ACPI_5_0_GTDT_GLOBAL_FLAG_INTERRUPT_MODE BIT1 + +/// +/// Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_0_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_5_0_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 + +/// +/// Boot Error Record Table (BERT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 BootErrorRegionLength; + UINT64 BootErrorRegion; +} EFI_ACPI_5_0_BOOT_ERROR_RECORD_TABLE_HEADER; + +/// +/// BERT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_BOOT_ERROR_RECORD_TABLE_REVISION 0x01 + +/// +/// Boot Error Region Block Status Definition +/// +typedef struct { + UINT32 UncorrectableErrorValid:1; + UINT32 CorrectableErrorValid:1; + UINT32 MultipleUncorrectableErrors:1; + UINT32 MultipleCorrectableErrors:1; + UINT32 ErrorDataEntryCount:10; + UINT32 Reserved:18; +} EFI_ACPI_5_0_ERROR_BLOCK_STATUS; + +/// +/// Boot Error Region Definition +/// +typedef struct { + EFI_ACPI_5_0_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_5_0_BOOT_ERROR_REGION_STRUCTURE; + +// +// Boot Error Severity types +// +#define EFI_ACPI_5_0_ERROR_SEVERITY_CORRECTABLE 0x00 +#define EFI_ACPI_5_0_ERROR_SEVERITY_FATAL 0x01 +#define EFI_ACPI_5_0_ERROR_SEVERITY_CORRECTED 0x02 +#define EFI_ACPI_5_0_ERROR_SEVERITY_NONE 0x03 + +/// +/// Generic Error Data Entry Definition +/// +typedef struct { + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; +} EFI_ACPI_5_0_GENERIC_ERROR_DATA_ENTRY_STRUCTURE; + +/// +/// Generic Error Data Entry Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_GENERIC_ERROR_DATA_ENTRY_REVISION 0x0201 + +/// +/// HEST - Hardware Error Source Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ErrorSourceCount; +} EFI_ACPI_5_0_HARDWARE_ERROR_SOURCE_TABLE_HEADER; + +/// +/// HEST Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_HARDWARE_ERROR_SOURCE_TABLE_REVISION 0x01 + +// +// Error Source structure types. +// +#define EFI_ACPI_5_0_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION 0x00 +#define EFI_ACPI_5_0_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK 0x01 +#define EFI_ACPI_5_0_IA32_ARCHITECTURE_NMI_ERROR 0x02 +#define EFI_ACPI_5_0_PCI_EXPRESS_ROOT_PORT_AER 0x06 +#define EFI_ACPI_5_0_PCI_EXPRESS_DEVICE_AER 0x07 +#define EFI_ACPI_5_0_PCI_EXPRESS_BRIDGE_AER 0x08 +#define EFI_ACPI_5_0_GENERIC_HARDWARE_ERROR 0x09 + +// +// Error Source structure flags. +// +#define EFI_ACPI_5_0_ERROR_SOURCE_FLAG_FIRMWARE_FIRST (1 << 0) +#define EFI_ACPI_5_0_ERROR_SOURCE_FLAG_GLOBAL (1 << 1) + +/// +/// IA-32 Architecture Machine Check Exception Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityInitData; + UINT64 GlobalControlInitData; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[7]; +} EFI_ACPI_5_0_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure Definition +/// +typedef struct { + UINT8 BankNumber; + UINT8 ClearStatusOnInitialization; + UINT8 StatusDataFormat; + UINT8 Reserved0; + UINT32 ControlRegisterMsrAddress; + UINT64 ControlInitData; + UINT32 StatusRegisterMsrAddress; + UINT32 AddressRegisterMsrAddress; + UINT32 MiscRegisterMsrAddress; +} EFI_ACPI_5_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure MCA data format +/// +#define EFI_ACPI_5_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_IA32 0x00 +#define EFI_ACPI_5_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_INTEL64 0x01 +#define EFI_ACPI_5_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_AMD64 0x02 + +// +// Hardware Error Notification types. All other values are reserved +// +#define EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_POLLED 0x00 +#define EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_EXTERNAL_INTERRUPT 0x01 +#define EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_LOCAL_INTERRUPT 0x02 +#define EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_SCI 0x03 +#define EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_NMI 0x04 + +/// +/// Hardware Error Notification Configuration Write Enable Structure Definition +/// +typedef struct { + UINT16 Type:1; + UINT16 PollInterval:1; + UINT16 SwitchToPollingThresholdValue:1; + UINT16 SwitchToPollingThresholdWindow:1; + UINT16 ErrorThresholdValue:1; + UINT16 ErrorThresholdWindow:1; + UINT16 Reserved:10; +} EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE; + +/// +/// Hardware Error Notification Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE ConfigurationWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 SwitchToPollingThresholdValue; + UINT32 SwitchToPollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; +} EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE; + +/// +/// IA-32 Architecture Corrected Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_5_0_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE; + +/// +/// IA-32 Architecture NMI Error Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; +} EFI_ACPI_5_0_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE; + +/// +/// PCI Express Root Port AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 RootErrorCommand; +} EFI_ACPI_5_0_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE; + +/// +/// PCI Express Device AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_5_0_PCI_EXPRESS_DEVICE_AER_STRUCTURE; + +/// +/// PCI Express Bridge AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 SecondaryUncorrectableErrorMask; + UINT32 SecondaryUncorrectableErrorSeverity; + UINT32 SecondaryAdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_5_0_PCI_EXPRESS_BRIDGE_AER_STRUCTURE; + +/// +/// Generic Hardware Error Source Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_5_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; +} EFI_ACPI_5_0_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE; + +/// +/// Generic Error Status Definition +/// +typedef struct { + EFI_ACPI_5_0_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_5_0_GENERIC_ERROR_STATUS_STRUCTURE; + +/// +/// ERST - Error Record Serialization Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 SerializationHeaderSize; + UINT8 Reserved0[4]; + UINT32 InstructionEntryCount; +} EFI_ACPI_5_0_ERROR_RECORD_SERIALIZATION_TABLE_HEADER; + +/// +/// ERST Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_ERROR_RECORD_SERIALIZATION_TABLE_REVISION 0x01 + +/// +/// ERST Serialization Actions +/// +#define EFI_ACPI_5_0_ERST_BEGIN_WRITE_OPERATION 0x00 +#define EFI_ACPI_5_0_ERST_BEGIN_READ_OPERATION 0x01 +#define EFI_ACPI_5_0_ERST_BEGIN_CLEAR_OPERATION 0x02 +#define EFI_ACPI_5_0_ERST_END_OPERATION 0x03 +#define EFI_ACPI_5_0_ERST_SET_RECORD_OFFSET 0x04 +#define EFI_ACPI_5_0_ERST_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_5_0_ERST_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_5_0_ERST_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_5_0_ERST_GET_RECORD_IDENTIFIER 0x08 +#define EFI_ACPI_5_0_ERST_SET_RECORD_IDENTIFIER 0x09 +#define EFI_ACPI_5_0_ERST_GET_RECORD_COUNT 0x0A +#define EFI_ACPI_5_0_ERST_BEGIN_DUMMY_WRITE_OPERATION 0x0B +#define EFI_ACPI_5_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE 0x0D +#define EFI_ACPI_5_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE_LENGTH 0x0E +#define EFI_ACPI_5_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0x0F + +/// +/// ERST Action Command Status +/// +#define EFI_ACPI_5_0_ERST_STATUS_SUCCESS 0x00 +#define EFI_ACPI_5_0_ERST_STATUS_NOT_ENOUGH_SPACE 0x01 +#define EFI_ACPI_5_0_ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x02 +#define EFI_ACPI_5_0_ERST_STATUS_FAILED 0x03 +#define EFI_ACPI_5_0_ERST_STATUS_RECORD_STORE_EMPTY 0x04 +#define EFI_ACPI_5_0_ERST_STATUS_RECORD_NOT_FOUND 0x05 + +/// +/// ERST Serialization Instructions +/// +#define EFI_ACPI_5_0_ERST_READ_REGISTER 0x00 +#define EFI_ACPI_5_0_ERST_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_5_0_ERST_WRITE_REGISTER 0x02 +#define EFI_ACPI_5_0_ERST_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_5_0_ERST_NOOP 0x04 +#define EFI_ACPI_5_0_ERST_LOAD_VAR1 0x05 +#define EFI_ACPI_5_0_ERST_LOAD_VAR2 0x06 +#define EFI_ACPI_5_0_ERST_STORE_VAR1 0x07 +#define EFI_ACPI_5_0_ERST_ADD 0x08 +#define EFI_ACPI_5_0_ERST_SUBTRACT 0x09 +#define EFI_ACPI_5_0_ERST_ADD_VALUE 0x0A +#define EFI_ACPI_5_0_ERST_SUBTRACT_VALUE 0x0B +#define EFI_ACPI_5_0_ERST_STALL 0x0C +#define EFI_ACPI_5_0_ERST_STALL_WHILE_TRUE 0x0D +#define EFI_ACPI_5_0_ERST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E +#define EFI_ACPI_5_0_ERST_GOTO 0x0F +#define EFI_ACPI_5_0_ERST_SET_SRC_ADDRESS_BASE 0x10 +#define EFI_ACPI_5_0_ERST_SET_DST_ADDRESS_BASE 0x11 +#define EFI_ACPI_5_0_ERST_MOVE_DATA 0x12 + +/// +/// ERST Instruction Flags +/// +#define EFI_ACPI_5_0_ERST_PRESERVE_REGISTER 0x01 + +/// +/// ERST Serialization Instruction Entry +/// +typedef struct { + UINT8 SerializationAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_5_0_ERST_SERIALIZATION_INSTRUCTION_ENTRY; + +/// +/// EINJ - Error Injection Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 InjectionHeaderSize; + UINT8 InjectionFlags; + UINT8 Reserved0[3]; + UINT32 InjectionEntryCount; +} EFI_ACPI_5_0_ERROR_INJECTION_TABLE_HEADER; + +/// +/// EINJ Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_ERROR_INJECTION_TABLE_REVISION 0x01 + +/// +/// EINJ Error Injection Actions +/// +#define EFI_ACPI_5_0_EINJ_BEGIN_INJECTION_OPERATION 0x00 +#define EFI_ACPI_5_0_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE 0x01 +#define EFI_ACPI_5_0_EINJ_SET_ERROR_TYPE 0x02 +#define EFI_ACPI_5_0_EINJ_GET_ERROR_TYPE 0x03 +#define EFI_ACPI_5_0_EINJ_END_OPERATION 0x04 +#define EFI_ACPI_5_0_EINJ_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_5_0_EINJ_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_5_0_EINJ_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_5_0_EINJ_TRIGGER_ERROR 0xFF + +/// +/// EINJ Action Command Status +/// +#define EFI_ACPI_5_0_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_5_0_EINJ_STATUS_UNKNOWN_FAILURE 0x01 +#define EFI_ACPI_5_0_EINJ_STATUS_INVALID_ACCESS 0x02 + +/// +/// EINJ Error Type Definition +/// +#define EFI_ACPI_5_0_EINJ_ERROR_PROCESSOR_CORRECTABLE (1 << 0) +#define EFI_ACPI_5_0_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_NONFATAL (1 << 1) +#define EFI_ACPI_5_0_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_FATAL (1 << 2) +#define EFI_ACPI_5_0_EINJ_ERROR_MEMORY_CORRECTABLE (1 << 3) +#define EFI_ACPI_5_0_EINJ_ERROR_MEMORY_UNCORRECTABLE_NONFATAL (1 << 4) +#define EFI_ACPI_5_0_EINJ_ERROR_MEMORY_UNCORRECTABLE_FATAL (1 << 5) +#define EFI_ACPI_5_0_EINJ_ERROR_PCI_EXPRESS_CORRECTABLE (1 << 6) +#define EFI_ACPI_5_0_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_NONFATAL (1 << 7) +#define EFI_ACPI_5_0_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_FATAL (1 << 8) +#define EFI_ACPI_5_0_EINJ_ERROR_PLATFORM_CORRECTABLE (1 << 9) +#define EFI_ACPI_5_0_EINJ_ERROR_PLATFORM_UNCORRECTABLE_NONFATAL (1 << 10) +#define EFI_ACPI_5_0_EINJ_ERROR_PLATFORM_UNCORRECTABLE_FATAL (1 << 11) + +/// +/// EINJ Injection Instructions +/// +#define EFI_ACPI_5_0_EINJ_READ_REGISTER 0x00 +#define EFI_ACPI_5_0_EINJ_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_5_0_EINJ_WRITE_REGISTER 0x02 +#define EFI_ACPI_5_0_EINJ_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_5_0_EINJ_NOOP 0x04 + +/// +/// EINJ Instruction Flags +/// +#define EFI_ACPI_5_0_EINJ_PRESERVE_REGISTER 0x01 + +/// +/// EINJ Injection Instruction Entry +/// +typedef struct { + UINT8 InjectionAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_5_0_EINJ_INJECTION_INSTRUCTION_ENTRY; + +/// +/// EINJ Trigger Action Table +/// +typedef struct { + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; +} EFI_ACPI_5_0_EINJ_TRIGGER_ACTION_TABLE; + +/// +/// Platform Communications Channel Table (PCCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Flags; + UINT64 Reserved; +} EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER; + +/// +/// PCCT Version (as defined in ACPI 5.0 spec.) +/// +#define EFI_ACPI_5_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION 0x01 + +/// +/// PCCT Global Flags +/// +#define EFI_ACPI_5_0_PCCT_FLAGS_SCI_DOORBELL BIT0 + +// +// PCCT Subspace type +// +#define EFI_ACPI_5_0_PCCT_SUBSPACE_TYPE_GENERIC 0x00 + +/// +/// PCC Subspace Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Length; +} EFI_ACPI_5_0_PCCT_SUBSPACE_HEADER; + +/// +/// Generic Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_5_0_PCCT_SUBSPACE_GENERIC; + +/// +/// Generic Communications Channel Shared Memory Region +/// + +typedef struct { + UINT8 Command; + UINT8 Reserved:7; + UINT8 GenerateSci:1; +} EFI_ACPI_5_0_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND; + +typedef struct { + UINT8 CommandComplete:1; + UINT8 SciDoorbell:1; + UINT8 Error:1; + UINT8 PlatformNotification:1; + UINT8 Reserved:4; + UINT8 Reserved1; +} EFI_ACPI_5_0_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS; + +typedef struct { + UINT32 Signature; + EFI_ACPI_5_0_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND Command; + EFI_ACPI_5_0_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS Status; +} EFI_ACPI_5_0_PCCT_GENERIC_SHARED_MEMORY_REGION_HEADER; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BERT" Boot Error Record Table +/// +#define EFI_ACPI_5_0_BOOT_ERROR_RECORD_TABLE_SIGNATURE SIGNATURE_32('B', 'E', 'R', 'T') + +/// +/// "BGRT" Boot Graphics Resource Table +/// +#define EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('B', 'G', 'R', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_5_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_5_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "EINJ" Error Injection Table +/// +#define EFI_ACPI_5_0_ERROR_INJECTION_TABLE_SIGNATURE SIGNATURE_32('E', 'I', 'N', 'J') + +/// +/// "ERST" Error Record Serialization Table +/// +#define EFI_ACPI_5_0_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE SIGNATURE_32('E', 'R', 'S', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FPDT" Firmware Performance Data Table +/// +#define EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE SIGNATURE_32('F', 'P', 'D', 'T') + +/// +/// "GTDT" Generic Timer Description Table +/// +#define EFI_ACPI_5_0_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('G', 'T', 'D', 'T') + +/// +/// "HEST" Hardware Error Source Table +/// +#define EFI_ACPI_5_0_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('H', 'E', 'S', 'T') + +/// +/// "MPST" Memory Power State Table +/// +#define EFI_ACPI_5_0_MEMORY_POWER_STATE_TABLE_SIGNATURE SIGNATURE_32('M', 'P', 'S', 'T') + +/// +/// "MSCT" Maximum System Characteristics Table +/// +#define EFI_ACPI_5_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'C', 'T') + +/// +/// "PMTT" Platform Memory Topology Table +/// +#define EFI_ACPI_5_0_PLATFORM_MEMORY_TOPOLOGY_TABLE_SIGNATURE SIGNATURE_32('P', 'M', 'T', 'T') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_5_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RASF" ACPI RAS Feature Table +/// +#define EFI_ACPI_5_0_ACPI_RAS_FEATURE_TABLE_SIGNATURE SIGNATURE_32('R', 'A', 'S', 'F') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_5_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_5_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_5_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_5_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_5_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "CSRT" MS Core System Resource Table +/// +#define EFI_ACPI_5_0_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('C', 'S', 'R', 'T') + +/// +/// "DBG2" MS Debug Port 2 Spec +/// +#define EFI_ACPI_5_0_DEBUG_PORT_2_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', '2') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_5_0_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DMAR" DMA Remapping Table +/// +#define EFI_ACPI_5_0_DMA_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('D', 'M', 'A', 'R') + +/// +/// "DRTM" Dynamic Root of Trust for Measurement Table +/// +#define EFI_ACPI_5_0_DYNAMIC_ROOT_OF_TRUST_FOR_MEASUREMENT_TABLE_SIGNATURE SIGNATURE_32('D', 'R', 'T', 'M') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_5_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_5_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_5_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +/// +/// "IVRS" I/O Virtualization Reporting Structure +/// +#define EFI_ACPI_5_0_IO_VIRTUALIZATION_REPORTING_STRUCTURE_SIGNATURE SIGNATURE_32('I', 'V', 'R', 'S') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "MCHI" Management Controller Host Interface Table +/// +#define EFI_ACPI_5_0_MANAGEMENT_CONTROLLER_HOST_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'H', 'I') + +/// +/// "MSDM" MS Data Management Table +/// +#define EFI_ACPI_5_0_DATA_MANAGEMENT_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'D', 'M') + +/// +/// "SLIC" MS Software Licensing Table Specification +/// +#define EFI_ACPI_5_0_SOFTWARE_LICENSING_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'C') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_5_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_5_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "TPM2" Trusted Computing Platform 1 Table +/// +#define EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE SIGNATURE_32('T', 'P', 'M', '2') + +/// +/// "UEFI" UEFI ACPI Data Table +/// +#define EFI_ACPI_5_0_UEFI_ACPI_DATA_TABLE_SIGNATURE SIGNATURE_32('U', 'E', 'F', 'I') + +/// +/// "WAET" Windows ACPI Emulated Devices Table +/// +#define EFI_ACPI_5_0_WINDOWS_ACPI_EMULATED_DEVICES_TABLE_SIGNATURE SIGNATURE_32('W', 'A', 'E', 'T') +#define EFI_ACPI_5_0_WINDOWS_ACPI_ENLIGHTENMENT_TABLE_SIGNATURE EFI_ACPI_5_0_WINDOWS_ACPI_EMULATED_DEVICES_TABLE_SIGNATURE + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_5_0_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_5_0_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +/// +/// "WPBT" MS Platform Binary Table +/// +#define EFI_ACPI_5_0_PLATFORM_BINARY_TABLE_SIGNATURE SIGNATURE_32('W', 'P', 'B', 'T') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi51.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi51.h new file mode 100644 index 0000000..90f0d98 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi51.h @@ -0,0 +1,2139 @@ +/** @file + ACPI 5.1 definitions from the ACPI Specification Revision 5.1 Errata B January, 2016. + + Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_5_1_H_ +#define _ACPI_5_1_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 5.1 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_5_1_SYSTEM_MEMORY 0 +#define EFI_ACPI_5_1_SYSTEM_IO 1 +#define EFI_ACPI_5_1_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_5_1_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_5_1_SMBUS 4 +#define EFI_ACPI_5_1_PLATFORM_COMMUNICATION_CHANNEL 0x0A +#define EFI_ACPI_5_1_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_5_1_UNDEFINED 0 +#define EFI_ACPI_5_1_BYTE 1 +#define EFI_ACPI_5_1_WORD 2 +#define EFI_ACPI_5_1_DWORD 3 +#define EFI_ACPI_5_1_QWORD 4 + +// +// ACPI 5.1 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_5_1_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 5.1) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_5_1_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT16 ArmBootArch; + UINT8 MinorVersion; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE SleepControlReg; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE SleepStatusReg; +} EFI_ACPI_5_1_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x05 +#define EFI_ACPI_5_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION 0x01 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_5_1_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_5_1_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_5_1_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_5_1_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_5_1_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_5_1_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_5_1_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_5_1_PM_PROFILE_PERFORMANCE_SERVER 7 +#define EFI_ACPI_5_1_PM_PROFILE_TABLET 8 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_1_LEGACY_DEVICES BIT0 +#define EFI_ACPI_5_1_8042 BIT1 +#define EFI_ACPI_5_1_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_5_1_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_5_1_PCIE_ASPM_CONTROLS BIT4 +#define EFI_ACPI_5_1_CMOS_RTC_NOT_PRESENT BIT5 + +// +// Fixed ACPI Description Table Arm Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_1_ARM_PSCI_COMPLIANT BIT0 +#define EFI_ACPI_5_1_ARM_PSCI_USE_HVC BIT1 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_1_WBINVD BIT0 +#define EFI_ACPI_5_1_WBINVD_FLUSH BIT1 +#define EFI_ACPI_5_1_PROC_C1 BIT2 +#define EFI_ACPI_5_1_P_LVL2_UP BIT3 +#define EFI_ACPI_5_1_PWR_BUTTON BIT4 +#define EFI_ACPI_5_1_SLP_BUTTON BIT5 +#define EFI_ACPI_5_1_FIX_RTC BIT6 +#define EFI_ACPI_5_1_RTC_S4 BIT7 +#define EFI_ACPI_5_1_TMR_VAL_EXT BIT8 +#define EFI_ACPI_5_1_DCK_CAP BIT9 +#define EFI_ACPI_5_1_RESET_REG_SUP BIT10 +#define EFI_ACPI_5_1_SEALED_CASE BIT11 +#define EFI_ACPI_5_1_HEADLESS BIT12 +#define EFI_ACPI_5_1_CPU_SW_SLP BIT13 +#define EFI_ACPI_5_1_PCI_EXP_WAK BIT14 +#define EFI_ACPI_5_1_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_5_1_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_5_1_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_5_1_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_5_1_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 +#define EFI_ACPI_5_1_HW_REDUCED_ACPI BIT20 +#define EFI_ACPI_5_1_LOW_POWER_S0_IDLE_CAPABLE BIT21 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved0[3]; + UINT32 OspmFlags; + UINT8 Reserved1[24]; +} EFI_ACPI_5_1_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x02 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_1_S4BIOS_F BIT0 +#define EFI_ACPI_5_1_64BIT_WAKE_SUPPORTED_F BIT1 + +/// +/// OSPM Enabled Firmware Control Structure Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_1_OSPM_64BIT_WAKE_F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_5_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_5_1_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x03 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_1_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x0D and 0x7F are reserved and +// will be ignored by OSPM. 0x80 ~ 0xFF are reserved for OEM. +// +#define EFI_ACPI_5_1_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_5_1_IO_APIC 0x01 +#define EFI_ACPI_5_1_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_5_1_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_5_1_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_5_1_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_5_1_IO_SAPIC 0x06 +#define EFI_ACPI_5_1_LOCAL_SAPIC 0x07 +#define EFI_ACPI_5_1_PLATFORM_INTERRUPT_SOURCES 0x08 +#define EFI_ACPI_5_1_PROCESSOR_LOCAL_X2APIC 0x09 +#define EFI_ACPI_5_1_LOCAL_X2APIC_NMI 0x0A +#define EFI_ACPI_5_1_GIC 0x0B +#define EFI_ACPI_5_1_GICD 0x0C +#define EFI_ACPI_5_1_GIC_MSI_FRAME 0x0D +#define EFI_ACPI_5_1_GICR 0x0E + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_5_1_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_5_1_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_5_1_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_5_1_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_5_1_POLARITY (3 << 0) +#define EFI_ACPI_5_1_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_5_1_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_5_1_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_5_1_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_5_1_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_5_1_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_5_1_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_5_1_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Processor Local x2APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 AcpiProcessorUid; +} EFI_ACPI_5_1_PROCESSOR_LOCAL_X2APIC_STRUCTURE; + +/// +/// Local x2APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 AcpiProcessorUid; + UINT8 LocalX2ApicLint; + UINT8 Reserved[3]; +} EFI_ACPI_5_1_LOCAL_X2APIC_NMI_STRUCTURE; + +/// +/// GIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 CPUInterfaceNumber; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ParkingProtocolVersion; + UINT32 PerformanceInterruptGsiv; + UINT64 ParkedAddress; + UINT64 PhysicalBaseAddress; + UINT64 GICV; + UINT64 GICH; + UINT32 VGICMaintenanceInterrupt; + UINT64 GICRBaseAddress; + UINT64 MPIDR; +} EFI_ACPI_5_1_GIC_STRUCTURE; + +/// +/// GIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_GIC_ENABLED BIT0 +#define EFI_ACPI_5_1_PERFORMANCE_INTERRUPT_MODEL BIT1 +#define EFI_ACPI_5_1_VGIC_MAINTENANCE_INTERRUPT_MODE_FLAGS BIT2 + +/// +/// GIC Distributor Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicId; + UINT64 PhysicalBaseAddress; + UINT32 SystemVectorBase; + UINT8 GicVersion; + UINT8 Reserved2[3]; +} EFI_ACPI_5_1_GIC_DISTRIBUTOR_STRUCTURE; + +/// +/// GIC Version +/// +#define EFI_ACPI_5_1_GIC_V1 0x01 +#define EFI_ACPI_5_1_GIC_V2 0x02 +#define EFI_ACPI_5_1_GIC_V3 0x03 +#define EFI_ACPI_5_1_GIC_V4 0x04 + +/// +/// GIC MSI Frame Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicMsiFrameId; + UINT64 PhysicalBaseAddress; + UINT32 Flags; + UINT16 SPICount; + UINT16 SPIBase; +} EFI_ACPI_5_1_GIC_MSI_FRAME_STRUCTURE; + +/// +/// GIC MSI Frame Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_SPI_COUNT_BASE_SELECT BIT0 + +/// +/// GICR Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 DiscoveryRangeBaseAddress; + UINT32 DiscoveryRangeLength; +} EFI_ACPI_5_1_GICR_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_5_1_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_5_1_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT). The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_5_1_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x03 + +// +// SRAT structure types. +// All other values between 0x04 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_5_1_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_5_1_MEMORY_AFFINITY 0x01 +#define EFI_ACPI_5_1_PROCESSOR_LOCAL_X2APIC_AFFINITY 0x02 +#define EFI_ACPI_5_1_GICC_AFFINITY 0x03 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT32 ClockDomain; +} EFI_ACPI_5_1_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_5_1_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_5_1_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_5_1_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_5_1_MEMORY_NONVOLATILE (1 << 2) + +/// +/// Processor Local x2APIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved1[2]; + UINT32 ProximityDomain; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT8 Reserved2[4]; +} EFI_ACPI_5_1_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE; + +/// +/// GICC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ClockDomain; +} EFI_ACPI_5_1_GICC_AFFINITY_STRUCTURE; + +/// +/// GICC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_GICC_ENABLED (1 << 0) + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_5_1_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +/// +/// Corrected Platform Error Polling Table (CPEP) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[8]; +} EFI_ACPI_5_1_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_HEADER; + +/// +/// CPEP Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_REVISION 0x01 + +// +// CPEP processor structure types. +// +#define EFI_ACPI_5_1_CPEP_PROCESSOR_APIC_SAPIC 0x00 + +/// +/// Corrected Platform Error Polling Processor Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT32 PollingInterval; +} EFI_ACPI_5_1_CPEP_PROCESSOR_APIC_SAPIC_STRUCTURE; + +/// +/// Maximum System Characteristics Table (MSCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetProxDomInfo; + UINT32 MaximumNumberOfProximityDomains; + UINT32 MaximumNumberOfClockDomains; + UINT64 MaximumPhysicalAddress; +} EFI_ACPI_5_1_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_HEADER; + +/// +/// MSCT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_REVISION 0x01 + +/// +/// Maximum Proximity Domain Information Structure Definition +/// +typedef struct { + UINT8 Revision; + UINT8 Length; + UINT32 ProximityDomainRangeLow; + UINT32 ProximityDomainRangeHigh; + UINT32 MaximumProcessorCapacity; + UINT64 MaximumMemoryCapacity; +} EFI_ACPI_5_1_MAXIMUM_PROXIMITY_DOMAIN_INFORMATION_STRUCTURE; + +/// +/// ACPI RAS Feature Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier[12]; +} EFI_ACPI_5_1_RAS_FEATURE_TABLE; + +/// +/// RASF Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_RAS_FEATURE_TABLE_REVISION 0x01 + +/// +/// ACPI RASF Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT16 Version; + UINT8 RASCapabilities[16]; + UINT8 SetRASCapabilities[16]; + UINT16 NumberOfRASFParameterBlocks; + UINT32 SetRASCapabilitiesStatus; +} EFI_ACPI_5_1_RASF_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI RASF PCC command code +/// +#define EFI_ACPI_5_1_RASF_PCC_COMMAND_CODE_EXECUTE_RASF_COMMAND 0x01 + +/// +/// ACPI RASF Platform RAS Capabilities +/// +#define EFI_ACPI_5_1_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED 0x01 +#define EFI_ACPI_5_1_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED_AND_EXPOSED_TO_SOFTWARE 0x02 + +/// +/// ACPI RASF Parameter Block structure for PATROL_SCRUB +/// +typedef struct { + UINT16 Type; + UINT16 Version; + UINT16 Length; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; +} EFI_ACPI_5_1_RASF_PATROL_SCRUB_PLATFORM_BLOCK_STRUCTURE; + +/// +/// ACPI RASF Patrol Scrub command +/// +#define EFI_ACPI_5_1_RASF_PATROL_SCRUB_COMMAND_GET_PATROL_PARAMETERS 0x01 +#define EFI_ACPI_5_1_RASF_PATROL_SCRUB_COMMAND_START_PATROL_SCRUBBER 0x02 +#define EFI_ACPI_5_1_RASF_PATROL_SCRUB_COMMAND_STOP_PATROL_SCRUBBER 0x03 + +/// +/// Memory Power State Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier; + UINT8 Reserved[3]; +// Memory Power Node Structure +// Memory Power State Characteristics +} EFI_ACPI_5_1_MEMORY_POWER_STATUS_TABLE; + +/// +/// MPST Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_MEMORY_POWER_STATE_TABLE_REVISION 0x01 + +/// +/// MPST Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT32 MemoryPowerCommandRegister; + UINT32 MemoryPowerStatusRegister; + UINT32 PowerStateId; + UINT32 MemoryPowerNodeId; + UINT64 MemoryEnergyConsumed; + UINT64 ExpectedAveragePowerComsuned; +} EFI_ACPI_5_1_MPST_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI MPST PCC command code +/// +#define EFI_ACPI_5_1_MPST_PCC_COMMAND_CODE_EXECUTE_MPST_COMMAND 0x03 + +/// +/// ACPI MPST Memory Power command +/// +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_POWER_STATE 0x01 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_COMMAND_SET_MEMORY_POWER_STATE 0x02 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_COMMAND_GET_AVERAGE_POWER_CONSUMED 0x03 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_ENERGY_CONSUMED 0x04 + +/// +/// MPST Memory Power Node Table +/// +typedef struct { + UINT8 PowerStateValue; + UINT8 PowerStateInformationIndex; +} EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE; + +typedef struct { + UINT8 Flag; + UINT8 Reserved; + UINT16 MemoryPowerNodeId; + UINT32 Length; + UINT64 AddressBase; + UINT64 AddressLength; + UINT32 NumberOfPowerStates; + UINT32 NumberOfPhysicalComponents; +//EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE MemoryPowerState[NumberOfPowerStates]; +//UINT16 PhysicalComponentIdentifier[NumberOfPhysicalComponents]; +} EFI_ACPI_5_1_MPST_MEMORY_POWER_STRUCTURE; + +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_STRUCTURE_FLAG_ENABLE 0x01 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_STRUCTURE_FLAG_POWER_MANAGED 0x02 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_STRUCTURE_FLAG_HOT_PLUGGABLE 0x04 + +typedef struct { + UINT16 MemoryPowerNodeCount; + UINT8 Reserved[2]; +} EFI_ACPI_5_1_MPST_MEMORY_POWER_NODE_TABLE; + +/// +/// MPST Memory Power State Characteristics Table +/// +typedef struct { + UINT8 PowerStateStructureID; + UINT8 Flag; + UINT16 Reserved; + UINT32 AveragePowerConsumedInMPS0; + UINT32 RelativePowerSavingToMPS0; + UINT64 ExitLatencyToMPS0; +} EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE; + +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_MEMORY_CONTENT_PRESERVED 0x01 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_ENTRY 0x02 +#define EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_EXIT 0x04 + +typedef struct { + UINT16 MemoryPowerStateCharacteristicsCount; + UINT8 Reserved[2]; +} EFI_ACPI_5_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_TABLE; + +/// +/// Memory Topology Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_5_1_MEMORY_TOPOLOGY_TABLE; + +/// +/// PMTT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_MEMORY_TOPOLOGY_TABLE_REVISION 0x01 + +/// +/// Common Memory Aggregator Device Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + UINT16 Flags; + UINT16 Reserved1; +} EFI_ACPI_5_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Memory Aggregator Device Type +/// +#define EFI_ACPI_5_1_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_SOCKET 0x1 +#define EFI_ACPI_5_1_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_MEMORY_CONTROLLER 0x2 +#define EFI_ACPI_5_1_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_DIMM 0x3 + +/// +/// Socket Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_5_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 SocketIdentifier; + UINT16 Reserved; +//EFI_ACPI_5_1_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE MemoryController[]; +} EFI_ACPI_5_1_PMMT_SOCKET_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// MemoryController Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_5_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT32 ReadLatency; + UINT32 WriteLatency; + UINT32 ReadBandwidth; + UINT32 WriteBandwidth; + UINT16 OptimalAccessUnit; + UINT16 OptimalAccessAlignment; + UINT16 Reserved; + UINT16 NumberOfProximityDomains; +//UINT32 ProximityDomain[NumberOfProximityDomains]; +//EFI_ACPI_5_1_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE PhysicalComponent[]; +} EFI_ACPI_5_1_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// DIMM Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_5_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 PhysicalComponentIdentifier; + UINT16 Reserved; + UINT32 SizeOfDimm; + UINT32 SmbiosHandle; +} EFI_ACPI_5_1_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Boot Graphics Resource Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /// + /// 2-bytes (16 bit) version ID. This value must be 1. + /// + UINT16 Version; + /// + /// 1-byte status field indicating current status about the table. + /// Bits[7:1] = Reserved (must be zero) + /// Bit [0] = Valid. A one indicates the boot image graphic is valid. + /// + UINT8 Status; + /// + /// 1-byte enumerated type field indicating format of the image. + /// 0 = Bitmap + /// 1 - 255 Reserved (for future use) + /// + UINT8 ImageType; + /// + /// 8-byte (64 bit) physical address pointing to the firmware's in-memory copy + /// of the image bitmap. + /// + UINT64 ImageAddress; + /// + /// A 4-byte (32-bit) unsigned long describing the display X-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetX; + /// + /// A 4-byte (32-bit) unsigned long describing the display Y-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetY; +} EFI_ACPI_5_1_BOOT_GRAPHICS_RESOURCE_TABLE; + +/// +/// BGRT Revision +/// +#define EFI_ACPI_5_1_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION 1 + +/// +/// BGRT Version +/// +#define EFI_ACPI_5_1_BGRT_VERSION 0x01 + +/// +/// BGRT Status +/// +#define EFI_ACPI_5_1_BGRT_STATUS_NOT_DISPLAYED 0x00 +#define EFI_ACPI_5_1_BGRT_STATUS_DISPLAYED 0x01 + +/// +/// BGRT Image Type +/// +#define EFI_ACPI_5_1_BGRT_IMAGE_TYPE_BMP 0x00 + +/// +/// FPDT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION 0x01 + +/// +/// FPDT Performance Record Types +/// +#define EFI_ACPI_5_1_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER 0x0000 +#define EFI_ACPI_5_1_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER 0x0001 + +/// +/// FPDT Performance Record Revision +/// +#define EFI_ACPI_5_1_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER 0x01 +#define EFI_ACPI_5_1_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER 0x01 + +/// +/// FPDT Runtime Performance Record Types +/// +#define EFI_ACPI_5_1_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME 0x0000 +#define EFI_ACPI_5_1_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND 0x0001 +#define EFI_ACPI_5_1_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT 0x0002 + +/// +/// FPDT Runtime Performance Record Revision +/// +#define EFI_ACPI_5_1_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME 0x01 +#define EFI_ACPI_5_1_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND 0x01 +#define EFI_ACPI_5_1_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT 0x02 + +/// +/// FPDT Performance Record header +/// +typedef struct { + UINT16 Type; + UINT8 Length; + UINT8 Revision; +} EFI_ACPI_5_1_FPDT_PERFORMANCE_RECORD_HEADER; + +/// +/// FPDT Performance Table header +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_5_1_FPDT_PERFORMANCE_TABLE_HEADER; + +/// +/// FPDT Firmware Basic Boot Performance Pointer Record Structure +/// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the Basic Boot Performance Table. + /// + UINT64 BootPerformanceTablePointer; +} EFI_ACPI_5_1_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT S3 Performance Table Pointer Record Structure +/// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the S3 Performance Table. + /// + UINT64 S3PerformanceTablePointer; +} EFI_ACPI_5_1_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Record Structure +/// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// Timer value logged at the beginning of firmware image execution. + /// This may not always be zero or near zero. + /// + UINT64 ResetEnd; + /// + /// Timer value logged just prior to loading the OS boot loader into memory. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 OsLoaderLoadImageStart; + /// + /// Timer value logged just prior to launching the previously loaded OS boot loader image. + /// For non-UEFI compatible boots, the timer value logged will be just prior + /// to the INT 19h handler invocation. + /// + UINT64 OsLoaderStartImageStart; + /// + /// Timer value logged at the point when the OS loader calls the + /// ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesEntry; + /// + /// Timer value logged at the point just prior towhen the OS loader gaining + /// control back from calls the ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesExit; +} EFI_ACPI_5_1_FPDT_FIRMWARE_BASIC_BOOT_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Table signature +/// +#define EFI_ACPI_5_1_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('F', 'B', 'P', 'T') + +// +// FPDT Firmware Basic Boot Performance Table +// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_5_1_FPDT_FIRMWARE_BASIC_BOOT_TABLE; + +/// +/// FPDT "S3PT" S3 Performance Table +/// +#define EFI_ACPI_5_1_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('S', '3', 'P', 'T') + +// +// FPDT Firmware S3 Boot Performance Table +// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_5_1_FPDT_FIRMWARE_S3_BOOT_TABLE; + +/// +/// FPDT Basic S3 Resume Performance Record +/// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// A count of the number of S3 resume cycles since the last full boot sequence. + /// + UINT32 ResumeCount; + /// + /// Timer recorded at the end of BIOS S3 resume, just prior to handoff to the + /// OS waking vector. Only the most recent resume cycle's time is retained. + /// + UINT64 FullResume; + /// + /// Average timer value of all resume cycles logged since the last full boot + /// sequence, including the most recent resume. Note that the entire log of + /// timer values does not need to be retained in order to calculate this average. + /// + UINT64 AverageResume; +} EFI_ACPI_5_1_FPDT_S3_RESUME_RECORD; + +/// +/// FPDT Basic S3 Suspend Performance Record +/// +typedef struct { + EFI_ACPI_5_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// Timer value recorded at the OS write to SLP_TYP upon entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendStart; + /// + /// Timer value recorded at the final firmware write to SLP_TYP (or other + /// mechanism) used to trigger hardware entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendEnd; +} EFI_ACPI_5_1_FPDT_S3_SUSPEND_RECORD; + +/// +/// Firmware Performance Record Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_5_1_FIRMWARE_PERFORMANCE_RECORD_TABLE; + +/// +/// Generic Timer Description Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 CntControlBasePhysicalAddress; + UINT32 Reserved; + UINT32 SecurePL1TimerGSIV; + UINT32 SecurePL1TimerFlags; + UINT32 NonSecurePL1TimerGSIV; + UINT32 NonSecurePL1TimerFlags; + UINT32 VirtualTimerGSIV; + UINT32 VirtualTimerFlags; + UINT32 NonSecurePL2TimerGSIV; + UINT32 NonSecurePL2TimerFlags; + UINT64 CntReadBasePhysicalAddress; + UINT32 PlatformTimerCount; + UINT32 PlatformTimerOffset; +} EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE; + +/// +/// GTDT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_5_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_5_1_GTDT_TIMER_FLAG_ALWAYS_ON_CAPABILITY BIT2 + +/// +/// Platform Timer Type +/// +#define EFI_ACPI_5_1_GTDT_GT_BLOCK 0 +#define EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG 1 + +/// +/// GT Block Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 CntCtlBase; + UINT32 GTBlockTimerCount; + UINT32 GTBlockTimerOffset; +} EFI_ACPI_5_1_GTDT_GT_BLOCK_STRUCTURE; + +/// +/// GT Block Timer Structure +/// +typedef struct { + UINT8 GTFrameNumber; + UINT8 Reserved[3]; + UINT64 CntBaseX; + UINT64 CntEL0BaseX; + UINT32 GTxPhysicalTimerGSIV; + UINT32 GTxPhysicalTimerFlags; + UINT32 GTxVirtualTimerGSIV; + UINT32 GTxVirtualTimerFlags; + UINT32 GTxCommonFlags; +} EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_STRUCTURE; + +/// +/// GT Block Physical Timers and Virtual Timers Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_5_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 + +/// +/// Common Flags Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_GTDT_GT_BLOCK_COMMON_FLAG_SECURE_TIMER BIT0 +#define EFI_ACPI_5_1_GTDT_GT_BLOCK_COMMON_FLAG_ALWAYS_ON_CAPABILITY BIT1 + +/// +/// SBSA Generic Watchdog Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 RefreshFramePhysicalAddress; + UINT64 WatchdogControlFramePhysicalAddress; + UINT32 WatchdogTimerGSIV; + UINT32 WatchdogTimerFlags; +} EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE; + +/// +/// SBSA Generic Watchdog Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_5_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_SECURE_TIMER BIT2 + +/// +/// Boot Error Record Table (BERT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 BootErrorRegionLength; + UINT64 BootErrorRegion; +} EFI_ACPI_5_1_BOOT_ERROR_RECORD_TABLE_HEADER; + +/// +/// BERT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_BOOT_ERROR_RECORD_TABLE_REVISION 0x01 + +/// +/// Boot Error Region Block Status Definition +/// +typedef struct { + UINT32 UncorrectableErrorValid:1; + UINT32 CorrectableErrorValid:1; + UINT32 MultipleUncorrectableErrors:1; + UINT32 MultipleCorrectableErrors:1; + UINT32 ErrorDataEntryCount:10; + UINT32 Reserved:18; +} EFI_ACPI_5_1_ERROR_BLOCK_STATUS; + +/// +/// Boot Error Region Definition +/// +typedef struct { + EFI_ACPI_5_1_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_5_1_BOOT_ERROR_REGION_STRUCTURE; + +// +// Boot Error Severity types +// +#define EFI_ACPI_5_1_ERROR_SEVERITY_CORRECTABLE 0x00 +#define EFI_ACPI_5_1_ERROR_SEVERITY_FATAL 0x01 +#define EFI_ACPI_5_1_ERROR_SEVERITY_CORRECTED 0x02 +#define EFI_ACPI_5_1_ERROR_SEVERITY_NONE 0x03 + +/// +/// Generic Error Data Entry Definition +/// +typedef struct { + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; +} EFI_ACPI_5_1_GENERIC_ERROR_DATA_ENTRY_STRUCTURE; + +/// +/// Generic Error Data Entry Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_GENERIC_ERROR_DATA_ENTRY_REVISION 0x0201 + +/// +/// HEST - Hardware Error Source Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ErrorSourceCount; +} EFI_ACPI_5_1_HARDWARE_ERROR_SOURCE_TABLE_HEADER; + +/// +/// HEST Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_HARDWARE_ERROR_SOURCE_TABLE_REVISION 0x01 + +// +// Error Source structure types. +// +#define EFI_ACPI_5_1_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION 0x00 +#define EFI_ACPI_5_1_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK 0x01 +#define EFI_ACPI_5_1_IA32_ARCHITECTURE_NMI_ERROR 0x02 +#define EFI_ACPI_5_1_PCI_EXPRESS_ROOT_PORT_AER 0x06 +#define EFI_ACPI_5_1_PCI_EXPRESS_DEVICE_AER 0x07 +#define EFI_ACPI_5_1_PCI_EXPRESS_BRIDGE_AER 0x08 +#define EFI_ACPI_5_1_GENERIC_HARDWARE_ERROR 0x09 + +// +// Error Source structure flags. +// +#define EFI_ACPI_5_1_ERROR_SOURCE_FLAG_FIRMWARE_FIRST (1 << 0) +#define EFI_ACPI_5_1_ERROR_SOURCE_FLAG_GLOBAL (1 << 1) + +/// +/// IA-32 Architecture Machine Check Exception Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityInitData; + UINT64 GlobalControlInitData; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[7]; +} EFI_ACPI_5_1_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure Definition +/// +typedef struct { + UINT8 BankNumber; + UINT8 ClearStatusOnInitialization; + UINT8 StatusDataFormat; + UINT8 Reserved0; + UINT32 ControlRegisterMsrAddress; + UINT64 ControlInitData; + UINT32 StatusRegisterMsrAddress; + UINT32 AddressRegisterMsrAddress; + UINT32 MiscRegisterMsrAddress; +} EFI_ACPI_5_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure MCA data format +/// +#define EFI_ACPI_5_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_IA32 0x00 +#define EFI_ACPI_5_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_INTEL64 0x01 +#define EFI_ACPI_5_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_AMD64 0x02 + +// +// Hardware Error Notification types. All other values are reserved +// +#define EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_POLLED 0x00 +#define EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_EXTERNAL_INTERRUPT 0x01 +#define EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_LOCAL_INTERRUPT 0x02 +#define EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_SCI 0x03 +#define EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_NMI 0x04 + +/// +/// Hardware Error Notification Configuration Write Enable Structure Definition +/// +typedef struct { + UINT16 Type:1; + UINT16 PollInterval:1; + UINT16 SwitchToPollingThresholdValue:1; + UINT16 SwitchToPollingThresholdWindow:1; + UINT16 ErrorThresholdValue:1; + UINT16 ErrorThresholdWindow:1; + UINT16 Reserved:10; +} EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE; + +/// +/// Hardware Error Notification Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE ConfigurationWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 SwitchToPollingThresholdValue; + UINT32 SwitchToPollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; +} EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE; + +/// +/// IA-32 Architecture Corrected Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_5_1_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE; + +/// +/// IA-32 Architecture NMI Error Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; +} EFI_ACPI_5_1_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE; + +/// +/// PCI Express Root Port AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 RootErrorCommand; +} EFI_ACPI_5_1_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE; + +/// +/// PCI Express Device AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_5_1_PCI_EXPRESS_DEVICE_AER_STRUCTURE; + +/// +/// PCI Express Bridge AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 SecondaryUncorrectableErrorMask; + UINT32 SecondaryUncorrectableErrorSeverity; + UINT32 SecondaryAdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_5_1_PCI_EXPRESS_BRIDGE_AER_STRUCTURE; + +/// +/// Generic Hardware Error Source Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_5_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; +} EFI_ACPI_5_1_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE; + +/// +/// Generic Error Status Definition +/// +typedef struct { + EFI_ACPI_5_1_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_5_1_GENERIC_ERROR_STATUS_STRUCTURE; + +/// +/// ERST - Error Record Serialization Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 SerializationHeaderSize; + UINT8 Reserved0[4]; + UINT32 InstructionEntryCount; +} EFI_ACPI_5_1_ERROR_RECORD_SERIALIZATION_TABLE_HEADER; + +/// +/// ERST Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_ERROR_RECORD_SERIALIZATION_TABLE_REVISION 0x01 + +/// +/// ERST Serialization Actions +/// +#define EFI_ACPI_5_1_ERST_BEGIN_WRITE_OPERATION 0x00 +#define EFI_ACPI_5_1_ERST_BEGIN_READ_OPERATION 0x01 +#define EFI_ACPI_5_1_ERST_BEGIN_CLEAR_OPERATION 0x02 +#define EFI_ACPI_5_1_ERST_END_OPERATION 0x03 +#define EFI_ACPI_5_1_ERST_SET_RECORD_OFFSET 0x04 +#define EFI_ACPI_5_1_ERST_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_5_1_ERST_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_5_1_ERST_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_5_1_ERST_GET_RECORD_IDENTIFIER 0x08 +#define EFI_ACPI_5_1_ERST_SET_RECORD_IDENTIFIER 0x09 +#define EFI_ACPI_5_1_ERST_GET_RECORD_COUNT 0x0A +#define EFI_ACPI_5_1_ERST_BEGIN_DUMMY_WRITE_OPERATION 0x0B +#define EFI_ACPI_5_1_ERST_GET_ERROR_LOG_ADDRESS_RANGE 0x0D +#define EFI_ACPI_5_1_ERST_GET_ERROR_LOG_ADDRESS_RANGE_LENGTH 0x0E +#define EFI_ACPI_5_1_ERST_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0x0F + +/// +/// ERST Action Command Status +/// +#define EFI_ACPI_5_1_ERST_STATUS_SUCCESS 0x00 +#define EFI_ACPI_5_1_ERST_STATUS_NOT_ENOUGH_SPACE 0x01 +#define EFI_ACPI_5_1_ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x02 +#define EFI_ACPI_5_1_ERST_STATUS_FAILED 0x03 +#define EFI_ACPI_5_1_ERST_STATUS_RECORD_STORE_EMPTY 0x04 +#define EFI_ACPI_5_1_ERST_STATUS_RECORD_NOT_FOUND 0x05 + +/// +/// ERST Serialization Instructions +/// +#define EFI_ACPI_5_1_ERST_READ_REGISTER 0x00 +#define EFI_ACPI_5_1_ERST_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_5_1_ERST_WRITE_REGISTER 0x02 +#define EFI_ACPI_5_1_ERST_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_5_1_ERST_NOOP 0x04 +#define EFI_ACPI_5_1_ERST_LOAD_VAR1 0x05 +#define EFI_ACPI_5_1_ERST_LOAD_VAR2 0x06 +#define EFI_ACPI_5_1_ERST_STORE_VAR1 0x07 +#define EFI_ACPI_5_1_ERST_ADD 0x08 +#define EFI_ACPI_5_1_ERST_SUBTRACT 0x09 +#define EFI_ACPI_5_1_ERST_ADD_VALUE 0x0A +#define EFI_ACPI_5_1_ERST_SUBTRACT_VALUE 0x0B +#define EFI_ACPI_5_1_ERST_STALL 0x0C +#define EFI_ACPI_5_1_ERST_STALL_WHILE_TRUE 0x0D +#define EFI_ACPI_5_1_ERST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E +#define EFI_ACPI_5_1_ERST_GOTO 0x0F +#define EFI_ACPI_5_1_ERST_SET_SRC_ADDRESS_BASE 0x10 +#define EFI_ACPI_5_1_ERST_SET_DST_ADDRESS_BASE 0x11 +#define EFI_ACPI_5_1_ERST_MOVE_DATA 0x12 + +/// +/// ERST Instruction Flags +/// +#define EFI_ACPI_5_1_ERST_PRESERVE_REGISTER 0x01 + +/// +/// ERST Serialization Instruction Entry +/// +typedef struct { + UINT8 SerializationAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_5_1_ERST_SERIALIZATION_INSTRUCTION_ENTRY; + +/// +/// EINJ - Error Injection Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 InjectionHeaderSize; + UINT8 InjectionFlags; + UINT8 Reserved0[3]; + UINT32 InjectionEntryCount; +} EFI_ACPI_5_1_ERROR_INJECTION_TABLE_HEADER; + +/// +/// EINJ Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_ERROR_INJECTION_TABLE_REVISION 0x01 + +/// +/// EINJ Error Injection Actions +/// +#define EFI_ACPI_5_1_EINJ_BEGIN_INJECTION_OPERATION 0x00 +#define EFI_ACPI_5_1_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE 0x01 +#define EFI_ACPI_5_1_EINJ_SET_ERROR_TYPE 0x02 +#define EFI_ACPI_5_1_EINJ_GET_ERROR_TYPE 0x03 +#define EFI_ACPI_5_1_EINJ_END_OPERATION 0x04 +#define EFI_ACPI_5_1_EINJ_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_5_1_EINJ_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_5_1_EINJ_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_5_1_EINJ_TRIGGER_ERROR 0xFF + +/// +/// EINJ Action Command Status +/// +#define EFI_ACPI_5_1_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_5_1_EINJ_STATUS_UNKNOWN_FAILURE 0x01 +#define EFI_ACPI_5_1_EINJ_STATUS_INVALID_ACCESS 0x02 + +/// +/// EINJ Error Type Definition +/// +#define EFI_ACPI_5_1_EINJ_ERROR_PROCESSOR_CORRECTABLE (1 << 0) +#define EFI_ACPI_5_1_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_NONFATAL (1 << 1) +#define EFI_ACPI_5_1_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_FATAL (1 << 2) +#define EFI_ACPI_5_1_EINJ_ERROR_MEMORY_CORRECTABLE (1 << 3) +#define EFI_ACPI_5_1_EINJ_ERROR_MEMORY_UNCORRECTABLE_NONFATAL (1 << 4) +#define EFI_ACPI_5_1_EINJ_ERROR_MEMORY_UNCORRECTABLE_FATAL (1 << 5) +#define EFI_ACPI_5_1_EINJ_ERROR_PCI_EXPRESS_CORRECTABLE (1 << 6) +#define EFI_ACPI_5_1_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_NONFATAL (1 << 7) +#define EFI_ACPI_5_1_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_FATAL (1 << 8) +#define EFI_ACPI_5_1_EINJ_ERROR_PLATFORM_CORRECTABLE (1 << 9) +#define EFI_ACPI_5_1_EINJ_ERROR_PLATFORM_UNCORRECTABLE_NONFATAL (1 << 10) +#define EFI_ACPI_5_1_EINJ_ERROR_PLATFORM_UNCORRECTABLE_FATAL (1 << 11) + +/// +/// EINJ Injection Instructions +/// +#define EFI_ACPI_5_1_EINJ_READ_REGISTER 0x00 +#define EFI_ACPI_5_1_EINJ_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_5_1_EINJ_WRITE_REGISTER 0x02 +#define EFI_ACPI_5_1_EINJ_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_5_1_EINJ_NOOP 0x04 + +/// +/// EINJ Instruction Flags +/// +#define EFI_ACPI_5_1_EINJ_PRESERVE_REGISTER 0x01 + +/// +/// EINJ Injection Instruction Entry +/// +typedef struct { + UINT8 InjectionAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_5_1_EINJ_INJECTION_INSTRUCTION_ENTRY; + +/// +/// EINJ Trigger Action Table +/// +typedef struct { + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; +} EFI_ACPI_5_1_EINJ_TRIGGER_ACTION_TABLE; + +/// +/// Platform Communications Channel Table (PCCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Flags; + UINT64 Reserved; +} EFI_ACPI_5_1_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER; + +/// +/// PCCT Version (as defined in ACPI 5.1 spec.) +/// +#define EFI_ACPI_5_1_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION 0x01 + +/// +/// PCCT Global Flags +/// +#define EFI_ACPI_5_1_PCCT_FLAGS_SCI_DOORBELL BIT0 + +// +// PCCT Subspace type +// +#define EFI_ACPI_5_1_PCCT_SUBSPACE_TYPE_GENERIC 0x00 + +/// +/// PCC Subspace Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Length; +} EFI_ACPI_5_1_PCCT_SUBSPACE_HEADER; + +/// +/// Generic Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_5_1_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_5_1_PCCT_SUBSPACE_GENERIC; + +/// +/// Generic Communications Channel Shared Memory Region +/// + +typedef struct { + UINT8 Command; + UINT8 Reserved:7; + UINT8 GenerateSci:1; +} EFI_ACPI_5_1_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND; + +typedef struct { + UINT8 CommandComplete:1; + UINT8 SciDoorbell:1; + UINT8 Error:1; + UINT8 PlatformNotification:1; + UINT8 Reserved:4; + UINT8 Reserved1; +} EFI_ACPI_5_1_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS; + +typedef struct { + UINT32 Signature; + EFI_ACPI_5_1_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND Command; + EFI_ACPI_5_1_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS Status; +} EFI_ACPI_5_1_PCCT_GENERIC_SHARED_MEMORY_REGION_HEADER; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_5_1_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_5_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BERT" Boot Error Record Table +/// +#define EFI_ACPI_5_1_BOOT_ERROR_RECORD_TABLE_SIGNATURE SIGNATURE_32('B', 'E', 'R', 'T') + +/// +/// "BGRT" Boot Graphics Resource Table +/// +#define EFI_ACPI_5_1_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('B', 'G', 'R', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_5_1_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_5_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_5_1_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "EINJ" Error Injection Table +/// +#define EFI_ACPI_5_1_ERROR_INJECTION_TABLE_SIGNATURE SIGNATURE_32('E', 'I', 'N', 'J') + +/// +/// "ERST" Error Record Serialization Table +/// +#define EFI_ACPI_5_1_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE SIGNATURE_32('E', 'R', 'S', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_5_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_5_1_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FPDT" Firmware Performance Data Table +/// +#define EFI_ACPI_5_1_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE SIGNATURE_32('F', 'P', 'D', 'T') + +/// +/// "GTDT" Generic Timer Description Table +/// +#define EFI_ACPI_5_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('G', 'T', 'D', 'T') + +/// +/// "HEST" Hardware Error Source Table +/// +#define EFI_ACPI_5_1_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('H', 'E', 'S', 'T') + +/// +/// "MPST" Memory Power State Table +/// +#define EFI_ACPI_5_1_MEMORY_POWER_STATE_TABLE_SIGNATURE SIGNATURE_32('M', 'P', 'S', 'T') + +/// +/// "MSCT" Maximum System Characteristics Table +/// +#define EFI_ACPI_5_1_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'C', 'T') + +/// +/// "PMTT" Platform Memory Topology Table +/// +#define EFI_ACPI_5_1_PLATFORM_MEMORY_TOPOLOGY_TABLE_SIGNATURE SIGNATURE_32('P', 'M', 'T', 'T') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_5_1_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RASF" ACPI RAS Feature Table +/// +#define EFI_ACPI_5_1_ACPI_RAS_FEATURE_TABLE_SIGNATURE SIGNATURE_32('R', 'A', 'S', 'F') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_5_1_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_5_1_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_5_1_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_5_1_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_5_1_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_5_1_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_5_1_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "CSRT" MS Core System Resource Table +/// +#define EFI_ACPI_5_1_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('C', 'S', 'R', 'T') + +/// +/// "DBG2" MS Debug Port 2 Spec +/// +#define EFI_ACPI_5_1_DEBUG_PORT_2_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', '2') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_5_1_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DMAR" DMA Remapping Table +/// +#define EFI_ACPI_5_1_DMA_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('D', 'M', 'A', 'R') + +/// +/// "DRTM" Dynamic Root of Trust for Measurement Table +/// +#define EFI_ACPI_5_1_DYNAMIC_ROOT_OF_TRUST_FOR_MEASUREMENT_TABLE_SIGNATURE SIGNATURE_32('D', 'R', 'T', 'M') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_5_1_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_5_1_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_5_1_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +/// +/// "IVRS" I/O Virtualization Reporting Structure +/// +#define EFI_ACPI_5_1_IO_VIRTUALIZATION_REPORTING_STRUCTURE_SIGNATURE SIGNATURE_32('I', 'V', 'R', 'S') + +/// +/// "LPIT" Low Power Idle Table +/// +#define EFI_ACPI_5_1_IO_LOW_POWER_IDLE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('L', 'P', 'I', 'T') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_5_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "MCHI" Management Controller Host Interface Table +/// +#define EFI_ACPI_5_1_MANAGEMENT_CONTROLLER_HOST_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'H', 'I') + +/// +/// "MSDM" MS Data Management Table +/// +#define EFI_ACPI_5_1_DATA_MANAGEMENT_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'D', 'M') + +/// +/// "SLIC" MS Software Licensing Table Specification +/// +#define EFI_ACPI_5_1_SOFTWARE_LICENSING_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'C') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_5_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_5_1_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_5_1_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "TPM2" Trusted Computing Platform 1 Table +/// +#define EFI_ACPI_5_1_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE SIGNATURE_32('T', 'P', 'M', '2') + +/// +/// "UEFI" UEFI ACPI Data Table +/// +#define EFI_ACPI_5_1_UEFI_ACPI_DATA_TABLE_SIGNATURE SIGNATURE_32('U', 'E', 'F', 'I') + +/// +/// "WAET" Windows ACPI Emulated Devices Table +/// +#define EFI_ACPI_5_1_WINDOWS_ACPI_EMULATED_DEVICES_TABLE_SIGNATURE SIGNATURE_32('W', 'A', 'E', 'T') + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_5_1_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_5_1_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +/// +/// "WPBT" MS Platform Binary Table +/// +#define EFI_ACPI_5_1_PLATFORM_BINARY_TABLE_SIGNATURE SIGNATURE_32('W', 'P', 'B', 'T') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi60.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi60.h new file mode 100644 index 0000000..30f1c01 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi60.h @@ -0,0 +1,2392 @@ +/** @file + ACPI 6.0 definitions from the ACPI Specification Revision 6.0 Errata A January, 2016. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_6_0_H_ +#define _ACPI_6_0_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 6.0 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_6_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_6_0_SYSTEM_IO 1 +#define EFI_ACPI_6_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_6_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_6_0_SMBUS 4 +#define EFI_ACPI_6_0_PLATFORM_COMMUNICATION_CHANNEL 0x0A +#define EFI_ACPI_6_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_6_0_UNDEFINED 0 +#define EFI_ACPI_6_0_BYTE 1 +#define EFI_ACPI_6_0_WORD 2 +#define EFI_ACPI_6_0_DWORD 3 +#define EFI_ACPI_6_0_QWORD 4 + +// +// ACPI 6.0 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 6.0) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_6_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT16 ArmBootArch; + UINT8 MinorVersion; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE SleepControlReg; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE SleepStatusReg; + UINT64 HypervisorVendorIdentity; +} EFI_ACPI_6_0_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x06 +#define EFI_ACPI_6_0_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION 0x00 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_6_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_6_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_6_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_6_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_6_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_6_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_6_0_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_6_0_PM_PROFILE_PERFORMANCE_SERVER 7 +#define EFI_ACPI_6_0_PM_PROFILE_TABLET 8 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_0_LEGACY_DEVICES BIT0 +#define EFI_ACPI_6_0_8042 BIT1 +#define EFI_ACPI_6_0_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_6_0_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_6_0_PCIE_ASPM_CONTROLS BIT4 +#define EFI_ACPI_6_0_CMOS_RTC_NOT_PRESENT BIT5 + +// +// Fixed ACPI Description Table Arm Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_0_ARM_PSCI_COMPLIANT BIT0 +#define EFI_ACPI_6_0_ARM_PSCI_USE_HVC BIT1 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_0_WBINVD BIT0 +#define EFI_ACPI_6_0_WBINVD_FLUSH BIT1 +#define EFI_ACPI_6_0_PROC_C1 BIT2 +#define EFI_ACPI_6_0_P_LVL2_UP BIT3 +#define EFI_ACPI_6_0_PWR_BUTTON BIT4 +#define EFI_ACPI_6_0_SLP_BUTTON BIT5 +#define EFI_ACPI_6_0_FIX_RTC BIT6 +#define EFI_ACPI_6_0_RTC_S4 BIT7 +#define EFI_ACPI_6_0_TMR_VAL_EXT BIT8 +#define EFI_ACPI_6_0_DCK_CAP BIT9 +#define EFI_ACPI_6_0_RESET_REG_SUP BIT10 +#define EFI_ACPI_6_0_SEALED_CASE BIT11 +#define EFI_ACPI_6_0_HEADLESS BIT12 +#define EFI_ACPI_6_0_CPU_SW_SLP BIT13 +#define EFI_ACPI_6_0_PCI_EXP_WAK BIT14 +#define EFI_ACPI_6_0_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_6_0_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_6_0_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_6_0_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_6_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 +#define EFI_ACPI_6_0_HW_REDUCED_ACPI BIT20 +#define EFI_ACPI_6_0_LOW_POWER_S0_IDLE_CAPABLE BIT21 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved0[3]; + UINT32 OspmFlags; + UINT8 Reserved1[24]; +} EFI_ACPI_6_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x02 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_0_S4BIOS_F BIT0 +#define EFI_ACPI_6_0_64BIT_WAKE_SUPPORTED_F BIT1 + +/// +/// OSPM Enabled Firmware Control Structure Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_0_OSPM_64BIT_WAKE_F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_6_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_6_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 6.0 Errata A spec.) +/// +#define EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x04 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_0_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x0D and 0x7F are reserved and +// will be ignored by OSPM. 0x80 ~ 0xFF are reserved for OEM. +// +#define EFI_ACPI_6_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_6_0_IO_APIC 0x01 +#define EFI_ACPI_6_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_6_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_6_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_6_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_6_0_IO_SAPIC 0x06 +#define EFI_ACPI_6_0_LOCAL_SAPIC 0x07 +#define EFI_ACPI_6_0_PLATFORM_INTERRUPT_SOURCES 0x08 +#define EFI_ACPI_6_0_PROCESSOR_LOCAL_X2APIC 0x09 +#define EFI_ACPI_6_0_LOCAL_X2APIC_NMI 0x0A +#define EFI_ACPI_6_0_GIC 0x0B +#define EFI_ACPI_6_0_GICD 0x0C +#define EFI_ACPI_6_0_GIC_MSI_FRAME 0x0D +#define EFI_ACPI_6_0_GICR 0x0E +#define EFI_ACPI_6_0_GIC_ITS 0x0F + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorUid; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_6_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_6_0_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_6_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_6_0_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_0_POLARITY (3 << 0) +#define EFI_ACPI_6_0_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_6_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorUid; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_6_0_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_6_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_6_0_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_6_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_6_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_0_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Processor Local x2APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 AcpiProcessorUid; +} EFI_ACPI_6_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE; + +/// +/// Local x2APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 AcpiProcessorUid; + UINT8 LocalX2ApicLint; + UINT8 Reserved[3]; +} EFI_ACPI_6_0_LOCAL_X2APIC_NMI_STRUCTURE; + +/// +/// GIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 CPUInterfaceNumber; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ParkingProtocolVersion; + UINT32 PerformanceInterruptGsiv; + UINT64 ParkedAddress; + UINT64 PhysicalBaseAddress; + UINT64 GICV; + UINT64 GICH; + UINT32 VGICMaintenanceInterrupt; + UINT64 GICRBaseAddress; + UINT64 MPIDR; + UINT8 ProcessorPowerEfficiencyClass; + UINT8 Reserved2[3]; +} EFI_ACPI_6_0_GIC_STRUCTURE; + +/// +/// GIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_GIC_ENABLED BIT0 +#define EFI_ACPI_6_0_PERFORMANCE_INTERRUPT_MODEL BIT1 +#define EFI_ACPI_6_0_VGIC_MAINTENANCE_INTERRUPT_MODE_FLAGS BIT2 + +/// +/// GIC Distributor Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicId; + UINT64 PhysicalBaseAddress; + UINT32 SystemVectorBase; + UINT8 GicVersion; + UINT8 Reserved2[3]; +} EFI_ACPI_6_0_GIC_DISTRIBUTOR_STRUCTURE; + +/// +/// GIC Version +/// +#define EFI_ACPI_6_0_GIC_V1 0x01 +#define EFI_ACPI_6_0_GIC_V2 0x02 +#define EFI_ACPI_6_0_GIC_V3 0x03 +#define EFI_ACPI_6_0_GIC_V4 0x04 + +/// +/// GIC MSI Frame Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicMsiFrameId; + UINT64 PhysicalBaseAddress; + UINT32 Flags; + UINT16 SPICount; + UINT16 SPIBase; +} EFI_ACPI_6_0_GIC_MSI_FRAME_STRUCTURE; + +/// +/// GIC MSI Frame Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_SPI_COUNT_BASE_SELECT BIT0 + +/// +/// GICR Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 DiscoveryRangeBaseAddress; + UINT32 DiscoveryRangeLength; +} EFI_ACPI_6_0_GICR_STRUCTURE; + +/// +/// GIC Interrupt Translation Service Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 GicItsId; + UINT64 PhysicalBaseAddress; + UINT32 Reserved2; +} EFI_ACPI_6_0_GIC_ITS_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_6_0_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_6_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT). The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x03 + +// +// SRAT structure types. +// All other values between 0x04 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_6_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_6_0_MEMORY_AFFINITY 0x01 +#define EFI_ACPI_6_0_PROCESSOR_LOCAL_X2APIC_AFFINITY 0x02 +#define EFI_ACPI_6_0_GICC_AFFINITY 0x03 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT32 ClockDomain; +} EFI_ACPI_6_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_6_0_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_6_0_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_6_0_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_6_0_MEMORY_NONVOLATILE (1 << 2) + +/// +/// Processor Local x2APIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved1[2]; + UINT32 ProximityDomain; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT8 Reserved2[4]; +} EFI_ACPI_6_0_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE; + +/// +/// GICC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ClockDomain; +} EFI_ACPI_6_0_GICC_AFFINITY_STRUCTURE; + +/// +/// GICC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_GICC_ENABLED (1 << 0) + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_6_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +/// +/// Corrected Platform Error Polling Table (CPEP) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[8]; +} EFI_ACPI_6_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_HEADER; + +/// +/// CPEP Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_REVISION 0x01 + +// +// CPEP processor structure types. +// +#define EFI_ACPI_6_0_CPEP_PROCESSOR_APIC_SAPIC 0x00 + +/// +/// Corrected Platform Error Polling Processor Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT32 PollingInterval; +} EFI_ACPI_6_0_CPEP_PROCESSOR_APIC_SAPIC_STRUCTURE; + +/// +/// Maximum System Characteristics Table (MSCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetProxDomInfo; + UINT32 MaximumNumberOfProximityDomains; + UINT32 MaximumNumberOfClockDomains; + UINT64 MaximumPhysicalAddress; +} EFI_ACPI_6_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_HEADER; + +/// +/// MSCT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_REVISION 0x01 + +/// +/// Maximum Proximity Domain Information Structure Definition +/// +typedef struct { + UINT8 Revision; + UINT8 Length; + UINT32 ProximityDomainRangeLow; + UINT32 ProximityDomainRangeHigh; + UINT32 MaximumProcessorCapacity; + UINT64 MaximumMemoryCapacity; +} EFI_ACPI_6_0_MAXIMUM_PROXIMITY_DOMAIN_INFORMATION_STRUCTURE; + +/// +/// ACPI RAS Feature Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier[12]; +} EFI_ACPI_6_0_RAS_FEATURE_TABLE; + +/// +/// RASF Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_RAS_FEATURE_TABLE_REVISION 0x01 + +/// +/// ACPI RASF Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT16 Version; + UINT8 RASCapabilities[16]; + UINT8 SetRASCapabilities[16]; + UINT16 NumberOfRASFParameterBlocks; + UINT32 SetRASCapabilitiesStatus; +} EFI_ACPI_6_0_RASF_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI RASF PCC command code +/// +#define EFI_ACPI_6_0_RASF_PCC_COMMAND_CODE_EXECUTE_RASF_COMMAND 0x01 + +/// +/// ACPI RASF Platform RAS Capabilities +/// +#define EFI_ACPI_6_0_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED 0x01 +#define EFI_ACPI_6_0_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED_AND_EXPOSED_TO_SOFTWARE 0x02 + +/// +/// ACPI RASF Parameter Block structure for PATROL_SCRUB +/// +typedef struct { + UINT16 Type; + UINT16 Version; + UINT16 Length; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; +} EFI_ACPI_6_0_RASF_PATROL_SCRUB_PLATFORM_BLOCK_STRUCTURE; + +/// +/// ACPI RASF Patrol Scrub command +/// +#define EFI_ACPI_6_0_RASF_PATROL_SCRUB_COMMAND_GET_PATROL_PARAMETERS 0x01 +#define EFI_ACPI_6_0_RASF_PATROL_SCRUB_COMMAND_START_PATROL_SCRUBBER 0x02 +#define EFI_ACPI_6_0_RASF_PATROL_SCRUB_COMMAND_STOP_PATROL_SCRUBBER 0x03 + +/// +/// Memory Power State Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier; + UINT8 Reserved[3]; +// Memory Power Node Structure +// Memory Power State Characteristics +} EFI_ACPI_6_0_MEMORY_POWER_STATUS_TABLE; + +/// +/// MPST Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_MEMORY_POWER_STATE_TABLE_REVISION 0x01 + +/// +/// MPST Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT32 MemoryPowerCommandRegister; + UINT32 MemoryPowerStatusRegister; + UINT32 PowerStateId; + UINT32 MemoryPowerNodeId; + UINT64 MemoryEnergyConsumed; + UINT64 ExpectedAveragePowerComsuned; +} EFI_ACPI_6_0_MPST_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI MPST PCC command code +/// +#define EFI_ACPI_6_0_MPST_PCC_COMMAND_CODE_EXECUTE_MPST_COMMAND 0x03 + +/// +/// ACPI MPST Memory Power command +/// +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_POWER_STATE 0x01 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_COMMAND_SET_MEMORY_POWER_STATE 0x02 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_COMMAND_GET_AVERAGE_POWER_CONSUMED 0x03 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_ENERGY_CONSUMED 0x04 + +/// +/// MPST Memory Power Node Table +/// +typedef struct { + UINT8 PowerStateValue; + UINT8 PowerStateInformationIndex; +} EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE; + +typedef struct { + UINT8 Flag; + UINT8 Reserved; + UINT16 MemoryPowerNodeId; + UINT32 Length; + UINT64 AddressBase; + UINT64 AddressLength; + UINT32 NumberOfPowerStates; + UINT32 NumberOfPhysicalComponents; +//EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE MemoryPowerState[NumberOfPowerStates]; +//UINT16 PhysicalComponentIdentifier[NumberOfPhysicalComponents]; +} EFI_ACPI_6_0_MPST_MEMORY_POWER_STRUCTURE; + +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_STRUCTURE_FLAG_ENABLE 0x01 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_STRUCTURE_FLAG_POWER_MANAGED 0x02 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_STRUCTURE_FLAG_HOT_PLUGGABLE 0x04 + +typedef struct { + UINT16 MemoryPowerNodeCount; + UINT8 Reserved[2]; +} EFI_ACPI_6_0_MPST_MEMORY_POWER_NODE_TABLE; + +/// +/// MPST Memory Power State Characteristics Table +/// +typedef struct { + UINT8 PowerStateStructureID; + UINT8 Flag; + UINT16 Reserved; + UINT32 AveragePowerConsumedInMPS0; + UINT32 RelativePowerSavingToMPS0; + UINT64 ExitLatencyToMPS0; +} EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE; + +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_MEMORY_CONTENT_PRESERVED 0x01 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_ENTRY 0x02 +#define EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_EXIT 0x04 + +typedef struct { + UINT16 MemoryPowerStateCharacteristicsCount; + UINT8 Reserved[2]; +} EFI_ACPI_6_0_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_TABLE; + +/// +/// Memory Topology Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_6_0_MEMORY_TOPOLOGY_TABLE; + +/// +/// PMTT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_MEMORY_TOPOLOGY_TABLE_REVISION 0x01 + +/// +/// Common Memory Aggregator Device Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + UINT16 Flags; + UINT16 Reserved1; +} EFI_ACPI_6_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Memory Aggregator Device Type +/// +#define EFI_ACPI_6_0_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_SOCKET 0x1 +#define EFI_ACPI_6_0_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_MEMORY_CONTROLLER 0x2 +#define EFI_ACPI_6_0_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_DIMM 0x3 + +/// +/// Socket Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 SocketIdentifier; + UINT16 Reserved; +//EFI_ACPI_6_0_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE MemoryController[]; +} EFI_ACPI_6_0_PMMT_SOCKET_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// MemoryController Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT32 ReadLatency; + UINT32 WriteLatency; + UINT32 ReadBandwidth; + UINT32 WriteBandwidth; + UINT16 OptimalAccessUnit; + UINT16 OptimalAccessAlignment; + UINT16 Reserved; + UINT16 NumberOfProximityDomains; +//UINT32 ProximityDomain[NumberOfProximityDomains]; +//EFI_ACPI_6_0_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE PhysicalComponent[]; +} EFI_ACPI_6_0_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// DIMM Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_0_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 PhysicalComponentIdentifier; + UINT16 Reserved; + UINT32 SizeOfDimm; + UINT32 SmbiosHandle; +} EFI_ACPI_6_0_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Boot Graphics Resource Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /// + /// 2-bytes (16 bit) version ID. This value must be 1. + /// + UINT16 Version; + /// + /// 1-byte status field indicating current status about the table. + /// Bits[7:1] = Reserved (must be zero) + /// Bit [0] = Valid. A one indicates the boot image graphic is valid. + /// + UINT8 Status; + /// + /// 1-byte enumerated type field indicating format of the image. + /// 0 = Bitmap + /// 1 - 255 Reserved (for future use) + /// + UINT8 ImageType; + /// + /// 8-byte (64 bit) physical address pointing to the firmware's in-memory copy + /// of the image bitmap. + /// + UINT64 ImageAddress; + /// + /// A 4-byte (32-bit) unsigned long describing the display X-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetX; + /// + /// A 4-byte (32-bit) unsigned long describing the display Y-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetY; +} EFI_ACPI_6_0_BOOT_GRAPHICS_RESOURCE_TABLE; + +/// +/// BGRT Revision +/// +#define EFI_ACPI_6_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION 1 + +/// +/// BGRT Version +/// +#define EFI_ACPI_6_0_BGRT_VERSION 0x01 + +/// +/// BGRT Status +/// +#define EFI_ACPI_6_0_BGRT_STATUS_NOT_DISPLAYED 0x00 +#define EFI_ACPI_6_0_BGRT_STATUS_DISPLAYED 0x01 + +/// +/// BGRT Image Type +/// +#define EFI_ACPI_6_0_BGRT_IMAGE_TYPE_BMP 0x00 + +/// +/// FPDT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION 0x01 + +/// +/// FPDT Performance Record Types +/// +#define EFI_ACPI_6_0_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER 0x0000 +#define EFI_ACPI_6_0_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER 0x0001 + +/// +/// FPDT Performance Record Revision +/// +#define EFI_ACPI_6_0_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER 0x01 +#define EFI_ACPI_6_0_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER 0x01 + +/// +/// FPDT Runtime Performance Record Types +/// +#define EFI_ACPI_6_0_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME 0x0000 +#define EFI_ACPI_6_0_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND 0x0001 +#define EFI_ACPI_6_0_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT 0x0002 + +/// +/// FPDT Runtime Performance Record Revision +/// +#define EFI_ACPI_6_0_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME 0x01 +#define EFI_ACPI_6_0_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND 0x01 +#define EFI_ACPI_6_0_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT 0x02 + +/// +/// FPDT Performance Record header +/// +typedef struct { + UINT16 Type; + UINT8 Length; + UINT8 Revision; +} EFI_ACPI_6_0_FPDT_PERFORMANCE_RECORD_HEADER; + +/// +/// FPDT Performance Table header +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_6_0_FPDT_PERFORMANCE_TABLE_HEADER; + +/// +/// FPDT Firmware Basic Boot Performance Pointer Record Structure +/// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the Basic Boot Performance Table. + /// + UINT64 BootPerformanceTablePointer; +} EFI_ACPI_6_0_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT S3 Performance Table Pointer Record Structure +/// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the S3 Performance Table. + /// + UINT64 S3PerformanceTablePointer; +} EFI_ACPI_6_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Record Structure +/// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// Timer value logged at the beginning of firmware image execution. + /// This may not always be zero or near zero. + /// + UINT64 ResetEnd; + /// + /// Timer value logged just prior to loading the OS boot loader into memory. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 OsLoaderLoadImageStart; + /// + /// Timer value logged just prior to launching the previously loaded OS boot loader image. + /// For non-UEFI compatible boots, the timer value logged will be just prior + /// to the INT 19h handler invocation. + /// + UINT64 OsLoaderStartImageStart; + /// + /// Timer value logged at the point when the OS loader calls the + /// ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesEntry; + /// + /// Timer value logged at the point just prior towhen the OS loader gaining + /// control back from calls the ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesExit; +} EFI_ACPI_6_0_FPDT_FIRMWARE_BASIC_BOOT_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Table signature +/// +#define EFI_ACPI_6_0_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('F', 'B', 'P', 'T') + +// +// FPDT Firmware Basic Boot Performance Table +// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_6_0_FPDT_FIRMWARE_BASIC_BOOT_TABLE; + +/// +/// FPDT "S3PT" S3 Performance Table +/// +#define EFI_ACPI_6_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('S', '3', 'P', 'T') + +// +// FPDT Firmware S3 Boot Performance Table +// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_6_0_FPDT_FIRMWARE_S3_BOOT_TABLE; + +/// +/// FPDT Basic S3 Resume Performance Record +/// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// A count of the number of S3 resume cycles since the last full boot sequence. + /// + UINT32 ResumeCount; + /// + /// Timer recorded at the end of BIOS S3 resume, just prior to handoff to the + /// OS waking vector. Only the most recent resume cycle's time is retained. + /// + UINT64 FullResume; + /// + /// Average timer value of all resume cycles logged since the last full boot + /// sequence, including the most recent resume. Note that the entire log of + /// timer values does not need to be retained in order to calculate this average. + /// + UINT64 AverageResume; +} EFI_ACPI_6_0_FPDT_S3_RESUME_RECORD; + +/// +/// FPDT Basic S3 Suspend Performance Record +/// +typedef struct { + EFI_ACPI_6_0_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// Timer value recorded at the OS write to SLP_TYP upon entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendStart; + /// + /// Timer value recorded at the final firmware write to SLP_TYP (or other + /// mechanism) used to trigger hardware entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendEnd; +} EFI_ACPI_6_0_FPDT_S3_SUSPEND_RECORD; + +/// +/// Firmware Performance Record Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_6_0_FIRMWARE_PERFORMANCE_RECORD_TABLE; + +/// +/// Generic Timer Description Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 CntControlBasePhysicalAddress; + UINT32 Reserved; + UINT32 SecurePL1TimerGSIV; + UINT32 SecurePL1TimerFlags; + UINT32 NonSecurePL1TimerGSIV; + UINT32 NonSecurePL1TimerFlags; + UINT32 VirtualTimerGSIV; + UINT32 VirtualTimerFlags; + UINT32 NonSecurePL2TimerGSIV; + UINT32 NonSecurePL2TimerFlags; + UINT64 CntReadBasePhysicalAddress; + UINT32 PlatformTimerCount; + UINT32 PlatformTimerOffset; +} EFI_ACPI_6_0_GENERIC_TIMER_DESCRIPTION_TABLE; + +/// +/// GTDT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_0_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_6_0_GTDT_TIMER_FLAG_ALWAYS_ON_CAPABILITY BIT2 + +/// +/// Platform Timer Type +/// +#define EFI_ACPI_6_0_GTDT_GT_BLOCK 0 +#define EFI_ACPI_6_0_GTDT_SBSA_GENERIC_WATCHDOG 1 + +/// +/// GT Block Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 CntCtlBase; + UINT32 GTBlockTimerCount; + UINT32 GTBlockTimerOffset; +} EFI_ACPI_6_0_GTDT_GT_BLOCK_STRUCTURE; + +/// +/// GT Block Timer Structure +/// +typedef struct { + UINT8 GTFrameNumber; + UINT8 Reserved[3]; + UINT64 CntBaseX; + UINT64 CntEL0BaseX; + UINT32 GTxPhysicalTimerGSIV; + UINT32 GTxPhysicalTimerFlags; + UINT32 GTxVirtualTimerGSIV; + UINT32 GTxVirtualTimerFlags; + UINT32 GTxCommonFlags; +} EFI_ACPI_6_0_GTDT_GT_BLOCK_TIMER_STRUCTURE; + +/// +/// GT Block Physical Timers and Virtual Timers Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_0_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 + +/// +/// Common Flags Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_GTDT_GT_BLOCK_COMMON_FLAG_SECURE_TIMER BIT0 +#define EFI_ACPI_6_0_GTDT_GT_BLOCK_COMMON_FLAG_ALWAYS_ON_CAPABILITY BIT1 + +/// +/// SBSA Generic Watchdog Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 RefreshFramePhysicalAddress; + UINT64 WatchdogControlFramePhysicalAddress; + UINT32 WatchdogTimerGSIV; + UINT32 WatchdogTimerFlags; +} EFI_ACPI_6_0_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE; + +/// +/// SBSA Generic Watchdog Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_0_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_0_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_6_0_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_SECURE_TIMER BIT2 + +// +// NVDIMM Firmware Interface Table definition. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_6_0_NVDIMM_FIRMWARE_INTERFACE_TABLE; + +// +// NFIT Version (as defined in ACPI 6.0 spec.) +// +#define EFI_ACPI_6_0_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION 0x1 + +// +// Definition for NFIT Table Structure Types +// +#define EFI_ACPI_6_0_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE 0 +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_TO_SYSTEM_ADDRESS_RANGE_MAP_STRUCTURE_TYPE 1 +#define EFI_ACPI_6_0_NFIT_INTERLEAVE_STRUCTURE_TYPE 2 +#define EFI_ACPI_6_0_NFIT_SMBIOS_MANAGEMENT_INFORMATION_STRUCTURE_TYPE 3 +#define EFI_ACPI_6_0_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE_TYPE 4 +#define EFI_ACPI_6_0_NFIT_NVDIMM_BLOCK_DATA_WINDOW_REGION_STRUCTURE_TYPE 5 +#define EFI_ACPI_6_0_NFIT_FLUSH_HINT_ADDRESS_STRUCTURE_TYPE 6 + +// +// Definition for NFIT Structure Header +// +typedef struct { + UINT16 Type; + UINT16 Length; +} EFI_ACPI_6_0_NFIT_STRUCTURE_HEADER; + +// +// Definition for System Physical Address Range Structure +// +#define EFI_ACPI_6_0_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_FLAGS_CONTROL_REGION_FOR_MANAGEMENT BIT0 +#define EFI_ACPI_6_0_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_FLAGS_PROXIMITY_DOMAIN_VALID BIT1 +#define EFI_ACPI_6_0_NFIT_GUID_VOLATILE_MEMORY_REGION { 0x7305944F, 0xFDDA, 0x44E3, { 0xB1, 0x6C, 0x3F, 0x22, 0xD2, 0x52, 0xE5, 0xD0 }} +#define EFI_ACPI_6_0_NFIT_GUID_BYTE_ADDRESSABLE_PERSISTENT_MEMORY_REGION { 0x66F0D379, 0xB4F3, 0x4074, { 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C, 0xDB }} +#define EFI_ACPI_6_0_NFIT_GUID_NVDIMM_CONTROL_REGION { 0x92F701F6, 0x13B4, 0x405D, { 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }} +#define EFI_ACPI_6_0_NFIT_GUID_NVDIMM_BLOCK_DATA_WINDOW_REGION { 0x91AF0530, 0x5D86, 0x470E, { 0xA6, 0xB0, 0x0A, 0x2D, 0xB9, 0x40, 0x82, 0x49 }} +#define EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_VOLATILE { 0x77AB535A, 0x45FC, 0x624B, { 0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }} +#define EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_VOLATILE { 0x3D5ABD30, 0x4175, 0x87CE, { 0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }} +#define EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_PERSISTENT { 0x5CEA02C9, 0x4D07, 0x69D3, { 0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }} +#define EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_PERSISTENT { 0x08018188, 0x42CD, 0xBB48, { 0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }} +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 SPARangeStructureIndex; + UINT16 Flags; + UINT32 Reserved_8; + UINT32 ProximityDomain; + GUID AddressRangeTypeGUID; + UINT64 SystemPhysicalAddressRangeBase; + UINT64 SystemPhysicalAddressRangeLength; + UINT64 AddressRangeMemoryMappingAttribute; +} EFI_ACPI_6_0_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE; + +// +// Definition for Memory Device to System Physical Address Range Mapping Structure +// +typedef struct { + UINT32 DIMMNumber:4; + UINT32 MemoryChannelNumber:4; + UINT32 MemoryControllerID:4; + UINT32 SocketID:4; + UINT32 NodeControllerID:12; + UINT32 Reserved_28:4; +} EFI_ACPI_6_0_NFIT_DEVICE_HANDLE; + +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_STATE_FLAGS_PREVIOUS_SAVE_FAIL BIT0 +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_STATE_FLAGS_LAST_RESTORE_FAIL BIT1 +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_STATE_FLAGS_PLATFORM_FLUSH_FAIL BIT2 +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_STATE_FLAGS_NOT_ARMED_PRIOR_TO_OSPM_HAND_OFF BIT3 +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_STATE_FLAGS_SMART_HEALTH_EVENTS_PRIOR_OSPM_HAND_OFF BIT4 +#define EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_STATE_FLAGS_FIRMWARE_ENABLED_TO_NOTIFY_OSPM_ON_SMART_HEALTH_EVENTS BIT5 +typedef struct { + UINT16 Type; + UINT16 Length; + EFI_ACPI_6_0_NFIT_DEVICE_HANDLE NFITDeviceHandle; + UINT16 MemoryDevicePhysicalID; + UINT16 MemoryDeviceRegionID; + UINT16 SPARangeStructureIndex ; + UINT16 NVDIMMControlRegionStructureIndex; + UINT64 MemoryDeviceRegionSize; + UINT64 RegionOffset; + UINT64 MemoryDevicePhysicalAddressRegionBase; + UINT16 InterleaveStructureIndex; + UINT16 InterleaveWays; + UINT16 MemoryDeviceStateFlags; + UINT16 Reserved_46; +} EFI_ACPI_6_0_NFIT_MEMORY_DEVICE_TO_SYSTEM_ADDRESS_RANGE_MAP_STRUCTURE; + +// +// Definition for Interleave Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 InterleaveStructureIndex; + UINT16 Reserved_6; + UINT32 NumberOfLines; + UINT32 LineSize; +//UINT32 LineOffset[NumberOfLines]; +} EFI_ACPI_6_0_NFIT_INTERLEAVE_STRUCTURE; + +// +// Definition for SMBIOS Management Information Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT32 Reserved_4; +//UINT8 Data[]; +} EFI_ACPI_6_0_NFIT_SMBIOS_MANAGEMENT_INFORMATION_STRUCTURE; + +// +// Definition for NVDIMM Control Region Structure +// +#define EFI_ACPI_6_0_NFIT_NVDIMM_CONTROL_REGION_FLAGS_BLOCK_DATA_WINDOWS_BUFFERED BIT0 +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 NVDIMMControlRegionStructureIndex; + UINT16 VendorID; + UINT16 DeviceID; + UINT16 RevisionID; + UINT16 SubsystemVendorID; + UINT16 SubsystemDeviceID; + UINT16 SubsystemRevisionID; + UINT8 Reserved_18[6]; + UINT32 SerialNumber; + UINT16 RegionFormatInterfaceCode; + UINT16 NumberOfBlockControlWindows; + UINT64 SizeOfBlockControlWindow; + UINT64 CommandRegisterOffsetInBlockControlWindow; + UINT64 SizeOfCommandRegisterInBlockControlWindows; + UINT64 StatusRegisterOffsetInBlockControlWindow; + UINT64 SizeOfStatusRegisterInBlockControlWindows; + UINT16 NVDIMMControlRegionFlag; + UINT8 Reserved_74[6]; +} EFI_ACPI_6_0_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE; + +// +// Definition for NVDIMM Block Data Window Region Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 NVDIMMControlRegionStructureIndex; + UINT16 NumberOfBlockDataWindows; + UINT64 BlockDataWindowStartOffset; + UINT64 SizeOfBlockDataWindow; + UINT64 BlockAccessibleMemoryCapacity; + UINT64 BeginningAddressOfFirstBlockInBlockAccessibleMemory; +} EFI_ACPI_6_0_NFIT_NVDIMM_BLOCK_DATA_WINDOW_REGION_STRUCTURE; + +// +// Definition for Flush Hint Address Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + EFI_ACPI_6_0_NFIT_DEVICE_HANDLE NFITDeviceHandle; + UINT16 NumberOfFlushHintAddresses; + UINT8 Reserved_10[6]; +//UINT64 FlushHintAddress[NumberOfFlushHintAddresses]; +} EFI_ACPI_6_0_NFIT_FLUSH_HINT_ADDRESS_STRUCTURE; + +/// +/// Boot Error Record Table (BERT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 BootErrorRegionLength; + UINT64 BootErrorRegion; +} EFI_ACPI_6_0_BOOT_ERROR_RECORD_TABLE_HEADER; + +/// +/// BERT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_BOOT_ERROR_RECORD_TABLE_REVISION 0x01 + +/// +/// Boot Error Region Block Status Definition +/// +typedef struct { + UINT32 UncorrectableErrorValid:1; + UINT32 CorrectableErrorValid:1; + UINT32 MultipleUncorrectableErrors:1; + UINT32 MultipleCorrectableErrors:1; + UINT32 ErrorDataEntryCount:10; + UINT32 Reserved:18; +} EFI_ACPI_6_0_ERROR_BLOCK_STATUS; + +/// +/// Boot Error Region Definition +/// +typedef struct { + EFI_ACPI_6_0_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_6_0_BOOT_ERROR_REGION_STRUCTURE; + +// +// Boot Error Severity types +// +#define EFI_ACPI_6_0_ERROR_SEVERITY_CORRECTABLE 0x00 +#define EFI_ACPI_6_0_ERROR_SEVERITY_FATAL 0x01 +#define EFI_ACPI_6_0_ERROR_SEVERITY_CORRECTED 0x02 +#define EFI_ACPI_6_0_ERROR_SEVERITY_NONE 0x03 + +/// +/// Generic Error Data Entry Definition +/// +typedef struct { + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; +} EFI_ACPI_6_0_GENERIC_ERROR_DATA_ENTRY_STRUCTURE; + +/// +/// Generic Error Data Entry Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_GENERIC_ERROR_DATA_ENTRY_REVISION 0x0201 + +/// +/// HEST - Hardware Error Source Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ErrorSourceCount; +} EFI_ACPI_6_0_HARDWARE_ERROR_SOURCE_TABLE_HEADER; + +/// +/// HEST Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_HARDWARE_ERROR_SOURCE_TABLE_REVISION 0x01 + +// +// Error Source structure types. +// +#define EFI_ACPI_6_0_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION 0x00 +#define EFI_ACPI_6_0_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK 0x01 +#define EFI_ACPI_6_0_IA32_ARCHITECTURE_NMI_ERROR 0x02 +#define EFI_ACPI_6_0_PCI_EXPRESS_ROOT_PORT_AER 0x06 +#define EFI_ACPI_6_0_PCI_EXPRESS_DEVICE_AER 0x07 +#define EFI_ACPI_6_0_PCI_EXPRESS_BRIDGE_AER 0x08 +#define EFI_ACPI_6_0_GENERIC_HARDWARE_ERROR 0x09 + +// +// Error Source structure flags. +// +#define EFI_ACPI_6_0_ERROR_SOURCE_FLAG_FIRMWARE_FIRST (1 << 0) +#define EFI_ACPI_6_0_ERROR_SOURCE_FLAG_GLOBAL (1 << 1) + +/// +/// IA-32 Architecture Machine Check Exception Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityInitData; + UINT64 GlobalControlInitData; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[7]; +} EFI_ACPI_6_0_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure Definition +/// +typedef struct { + UINT8 BankNumber; + UINT8 ClearStatusOnInitialization; + UINT8 StatusDataFormat; + UINT8 Reserved0; + UINT32 ControlRegisterMsrAddress; + UINT64 ControlInitData; + UINT32 StatusRegisterMsrAddress; + UINT32 AddressRegisterMsrAddress; + UINT32 MiscRegisterMsrAddress; +} EFI_ACPI_6_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure MCA data format +/// +#define EFI_ACPI_6_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_IA32 0x00 +#define EFI_ACPI_6_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_INTEL64 0x01 +#define EFI_ACPI_6_0_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_AMD64 0x02 + +// +// Hardware Error Notification types. All other values are reserved +// +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_POLLED 0x00 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_EXTERNAL_INTERRUPT 0x01 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_LOCAL_INTERRUPT 0x02 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_SCI 0x03 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_NMI 0x04 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_CMCI 0x05 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_MCE 0x06 +#define EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_GPIO_SIGNAL 0x07 + +/// +/// Hardware Error Notification Configuration Write Enable Structure Definition +/// +typedef struct { + UINT16 Type:1; + UINT16 PollInterval:1; + UINT16 SwitchToPollingThresholdValue:1; + UINT16 SwitchToPollingThresholdWindow:1; + UINT16 ErrorThresholdValue:1; + UINT16 ErrorThresholdWindow:1; + UINT16 Reserved:10; +} EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE; + +/// +/// Hardware Error Notification Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE ConfigurationWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 SwitchToPollingThresholdValue; + UINT32 SwitchToPollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; +} EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE; + +/// +/// IA-32 Architecture Corrected Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_6_0_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE; + +/// +/// IA-32 Architecture NMI Error Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; +} EFI_ACPI_6_0_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE; + +/// +/// PCI Express Root Port AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 RootErrorCommand; +} EFI_ACPI_6_0_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE; + +/// +/// PCI Express Device AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_6_0_PCI_EXPRESS_DEVICE_AER_STRUCTURE; + +/// +/// PCI Express Bridge AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 SecondaryUncorrectableErrorMask; + UINT32 SecondaryUncorrectableErrorSeverity; + UINT32 SecondaryAdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_6_0_PCI_EXPRESS_BRIDGE_AER_STRUCTURE; + +/// +/// Generic Hardware Error Source Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_6_0_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; +} EFI_ACPI_6_0_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE; + +/// +/// Generic Error Status Definition +/// +typedef struct { + EFI_ACPI_6_0_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_6_0_GENERIC_ERROR_STATUS_STRUCTURE; + +/// +/// ERST - Error Record Serialization Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 SerializationHeaderSize; + UINT8 Reserved0[4]; + UINT32 InstructionEntryCount; +} EFI_ACPI_6_0_ERROR_RECORD_SERIALIZATION_TABLE_HEADER; + +/// +/// ERST Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_ERROR_RECORD_SERIALIZATION_TABLE_REVISION 0x01 + +/// +/// ERST Serialization Actions +/// +#define EFI_ACPI_6_0_ERST_BEGIN_WRITE_OPERATION 0x00 +#define EFI_ACPI_6_0_ERST_BEGIN_READ_OPERATION 0x01 +#define EFI_ACPI_6_0_ERST_BEGIN_CLEAR_OPERATION 0x02 +#define EFI_ACPI_6_0_ERST_END_OPERATION 0x03 +#define EFI_ACPI_6_0_ERST_SET_RECORD_OFFSET 0x04 +#define EFI_ACPI_6_0_ERST_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_6_0_ERST_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_6_0_ERST_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_6_0_ERST_GET_RECORD_IDENTIFIER 0x08 +#define EFI_ACPI_6_0_ERST_SET_RECORD_IDENTIFIER 0x09 +#define EFI_ACPI_6_0_ERST_GET_RECORD_COUNT 0x0A +#define EFI_ACPI_6_0_ERST_BEGIN_DUMMY_WRITE_OPERATION 0x0B +#define EFI_ACPI_6_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE 0x0D +#define EFI_ACPI_6_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE_LENGTH 0x0E +#define EFI_ACPI_6_0_ERST_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0x0F + +/// +/// ERST Action Command Status +/// +#define EFI_ACPI_6_0_ERST_STATUS_SUCCESS 0x00 +#define EFI_ACPI_6_0_ERST_STATUS_NOT_ENOUGH_SPACE 0x01 +#define EFI_ACPI_6_0_ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x02 +#define EFI_ACPI_6_0_ERST_STATUS_FAILED 0x03 +#define EFI_ACPI_6_0_ERST_STATUS_RECORD_STORE_EMPTY 0x04 +#define EFI_ACPI_6_0_ERST_STATUS_RECORD_NOT_FOUND 0x05 + +/// +/// ERST Serialization Instructions +/// +#define EFI_ACPI_6_0_ERST_READ_REGISTER 0x00 +#define EFI_ACPI_6_0_ERST_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_6_0_ERST_WRITE_REGISTER 0x02 +#define EFI_ACPI_6_0_ERST_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_6_0_ERST_NOOP 0x04 +#define EFI_ACPI_6_0_ERST_LOAD_VAR1 0x05 +#define EFI_ACPI_6_0_ERST_LOAD_VAR2 0x06 +#define EFI_ACPI_6_0_ERST_STORE_VAR1 0x07 +#define EFI_ACPI_6_0_ERST_ADD 0x08 +#define EFI_ACPI_6_0_ERST_SUBTRACT 0x09 +#define EFI_ACPI_6_0_ERST_ADD_VALUE 0x0A +#define EFI_ACPI_6_0_ERST_SUBTRACT_VALUE 0x0B +#define EFI_ACPI_6_0_ERST_STALL 0x0C +#define EFI_ACPI_6_0_ERST_STALL_WHILE_TRUE 0x0D +#define EFI_ACPI_6_0_ERST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E +#define EFI_ACPI_6_0_ERST_GOTO 0x0F +#define EFI_ACPI_6_0_ERST_SET_SRC_ADDRESS_BASE 0x10 +#define EFI_ACPI_6_0_ERST_SET_DST_ADDRESS_BASE 0x11 +#define EFI_ACPI_6_0_ERST_MOVE_DATA 0x12 + +/// +/// ERST Instruction Flags +/// +#define EFI_ACPI_6_0_ERST_PRESERVE_REGISTER 0x01 + +/// +/// ERST Serialization Instruction Entry +/// +typedef struct { + UINT8 SerializationAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_6_0_ERST_SERIALIZATION_INSTRUCTION_ENTRY; + +/// +/// EINJ - Error Injection Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 InjectionHeaderSize; + UINT8 InjectionFlags; + UINT8 Reserved0[3]; + UINT32 InjectionEntryCount; +} EFI_ACPI_6_0_ERROR_INJECTION_TABLE_HEADER; + +/// +/// EINJ Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_ERROR_INJECTION_TABLE_REVISION 0x01 + +/// +/// EINJ Error Injection Actions +/// +#define EFI_ACPI_6_0_EINJ_BEGIN_INJECTION_OPERATION 0x00 +#define EFI_ACPI_6_0_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE 0x01 +#define EFI_ACPI_6_0_EINJ_SET_ERROR_TYPE 0x02 +#define EFI_ACPI_6_0_EINJ_GET_ERROR_TYPE 0x03 +#define EFI_ACPI_6_0_EINJ_END_OPERATION 0x04 +#define EFI_ACPI_6_0_EINJ_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_6_0_EINJ_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_6_0_EINJ_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_6_0_EINJ_TRIGGER_ERROR 0xFF + +/// +/// EINJ Action Command Status +/// +#define EFI_ACPI_6_0_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_6_0_EINJ_STATUS_UNKNOWN_FAILURE 0x01 +#define EFI_ACPI_6_0_EINJ_STATUS_INVALID_ACCESS 0x02 + +/// +/// EINJ Error Type Definition +/// +#define EFI_ACPI_6_0_EINJ_ERROR_PROCESSOR_CORRECTABLE (1 << 0) +#define EFI_ACPI_6_0_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_NONFATAL (1 << 1) +#define EFI_ACPI_6_0_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_FATAL (1 << 2) +#define EFI_ACPI_6_0_EINJ_ERROR_MEMORY_CORRECTABLE (1 << 3) +#define EFI_ACPI_6_0_EINJ_ERROR_MEMORY_UNCORRECTABLE_NONFATAL (1 << 4) +#define EFI_ACPI_6_0_EINJ_ERROR_MEMORY_UNCORRECTABLE_FATAL (1 << 5) +#define EFI_ACPI_6_0_EINJ_ERROR_PCI_EXPRESS_CORRECTABLE (1 << 6) +#define EFI_ACPI_6_0_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_NONFATAL (1 << 7) +#define EFI_ACPI_6_0_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_FATAL (1 << 8) +#define EFI_ACPI_6_0_EINJ_ERROR_PLATFORM_CORRECTABLE (1 << 9) +#define EFI_ACPI_6_0_EINJ_ERROR_PLATFORM_UNCORRECTABLE_NONFATAL (1 << 10) +#define EFI_ACPI_6_0_EINJ_ERROR_PLATFORM_UNCORRECTABLE_FATAL (1 << 11) + +/// +/// EINJ Injection Instructions +/// +#define EFI_ACPI_6_0_EINJ_READ_REGISTER 0x00 +#define EFI_ACPI_6_0_EINJ_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_6_0_EINJ_WRITE_REGISTER 0x02 +#define EFI_ACPI_6_0_EINJ_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_6_0_EINJ_NOOP 0x04 + +/// +/// EINJ Instruction Flags +/// +#define EFI_ACPI_6_0_EINJ_PRESERVE_REGISTER 0x01 + +/// +/// EINJ Injection Instruction Entry +/// +typedef struct { + UINT8 InjectionAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_6_0_EINJ_INJECTION_INSTRUCTION_ENTRY; + +/// +/// EINJ Trigger Action Table +/// +typedef struct { + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; +} EFI_ACPI_6_0_EINJ_TRIGGER_ACTION_TABLE; + +/// +/// Platform Communications Channel Table (PCCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Flags; + UINT64 Reserved; +} EFI_ACPI_6_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER; + +/// +/// PCCT Version (as defined in ACPI 6.0 spec.) +/// +#define EFI_ACPI_6_0_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION 0x01 + +/// +/// PCCT Global Flags +/// +#define EFI_ACPI_6_0_PCCT_FLAGS_SCI_DOORBELL BIT0 + +// +// PCCT Subspace type +// +#define EFI_ACPI_6_0_PCCT_SUBSPACE_TYPE_GENERIC 0x00 +#define EFI_ACPI_6_0_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS 0x01 +#define EFI_ACPI_6_0_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS 0x02 + +/// +/// PCC Subspace Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Length; +} EFI_ACPI_6_0_PCCT_SUBSPACE_HEADER; + +/// +/// Generic Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_6_0_PCCT_SUBSPACE_GENERIC; + +/// +/// Generic Communications Channel Shared Memory Region +/// + +typedef struct { + UINT8 Command; + UINT8 Reserved:7; + UINT8 GenerateSci:1; +} EFI_ACPI_6_0_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND; + +typedef struct { + UINT8 CommandComplete:1; + UINT8 SciDoorbell:1; + UINT8 Error:1; + UINT8 PlatformNotification:1; + UINT8 Reserved:4; + UINT8 Reserved1; +} EFI_ACPI_6_0_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS; + +typedef struct { + UINT32 Signature; + EFI_ACPI_6_0_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND Command; + EFI_ACPI_6_0_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS Status; +} EFI_ACPI_6_0_PCCT_GENERIC_SHARED_MEMORY_REGION_HEADER; + +#define EFI_ACPI_6_0_PCCT_SUBSPACE_DOORBELL_INTERRUPT_FLAGS_POLARITY BIT0 +#define EFI_ACPI_6_0_PCCT_SUBSPACE_DOORBELL_INTERRUPT_FLAGS_MODE BIT1 + +/// +/// Type 1 HW-Reduced Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 DoorbellInterrupt; + UINT8 DoorbellInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_6_0_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS; + +/// +/// Type 2 HW-Reduced Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 DoorbellInterrupt; + UINT8 DoorbellInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; + EFI_ACPI_6_0_GENERIC_ADDRESS_STRUCTURE DoorbellAckRegister; + UINT64 DoorbellAckPreserve; + UINT64 DoorbellAckWrite; +} EFI_ACPI_6_0_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_6_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BERT" Boot Error Record Table +/// +#define EFI_ACPI_6_0_BOOT_ERROR_RECORD_TABLE_SIGNATURE SIGNATURE_32('B', 'E', 'R', 'T') + +/// +/// "BGRT" Boot Graphics Resource Table +/// +#define EFI_ACPI_6_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('B', 'G', 'R', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_6_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_6_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_6_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "EINJ" Error Injection Table +/// +#define EFI_ACPI_6_0_ERROR_INJECTION_TABLE_SIGNATURE SIGNATURE_32('E', 'I', 'N', 'J') + +/// +/// "ERST" Error Record Serialization Table +/// +#define EFI_ACPI_6_0_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE SIGNATURE_32('E', 'R', 'S', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_6_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_6_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FPDT" Firmware Performance Data Table +/// +#define EFI_ACPI_6_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE SIGNATURE_32('F', 'P', 'D', 'T') + +/// +/// "GTDT" Generic Timer Description Table +/// +#define EFI_ACPI_6_0_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('G', 'T', 'D', 'T') + +/// +/// "HEST" Hardware Error Source Table +/// +#define EFI_ACPI_6_0_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('H', 'E', 'S', 'T') + +/// +/// "MPST" Memory Power State Table +/// +#define EFI_ACPI_6_0_MEMORY_POWER_STATE_TABLE_SIGNATURE SIGNATURE_32('M', 'P', 'S', 'T') + +/// +/// "MSCT" Maximum System Characteristics Table +/// +#define EFI_ACPI_6_0_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'C', 'T') + +/// +/// "NFIT" NVDIMM Firmware Interface Table +/// +#define EFI_ACPI_6_0_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('N', 'F', 'I', 'T') + +/// +/// "PMTT" Platform Memory Topology Table +/// +#define EFI_ACPI_6_0_PLATFORM_MEMORY_TOPOLOGY_TABLE_SIGNATURE SIGNATURE_32('P', 'M', 'T', 'T') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_6_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RASF" ACPI RAS Feature Table +/// +#define EFI_ACPI_6_0_ACPI_RAS_FEATURE_TABLE_SIGNATURE SIGNATURE_32('R', 'A', 'S', 'F') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_6_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_6_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_6_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_6_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_6_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_6_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_6_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "CSRT" MS Core System Resource Table +/// +#define EFI_ACPI_6_0_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('C', 'S', 'R', 'T') + +/// +/// "DBG2" MS Debug Port 2 Spec +/// +#define EFI_ACPI_6_0_DEBUG_PORT_2_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', '2') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_6_0_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DMAR" DMA Remapping Table +/// +#define EFI_ACPI_6_0_DMA_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('D', 'M', 'A', 'R') + +/// +/// "DRTM" Dynamic Root of Trust for Measurement Table +/// +#define EFI_ACPI_6_0_DYNAMIC_ROOT_OF_TRUST_FOR_MEASUREMENT_TABLE_SIGNATURE SIGNATURE_32('D', 'R', 'T', 'M') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_6_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_6_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_6_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +/// +/// "IORT" I/O Remapping Table +/// +#define EFI_ACPI_6_0_IO_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('I', 'O', 'R', 'T') + +/// +/// "IVRS" I/O Virtualization Reporting Structure +/// +#define EFI_ACPI_6_0_IO_VIRTUALIZATION_REPORTING_STRUCTURE_SIGNATURE SIGNATURE_32('I', 'V', 'R', 'S') + +/// +/// "LPIT" Low Power Idle Table +/// +#define EFI_ACPI_6_0_LOW_POWER_IDLE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('L', 'P', 'I', 'T') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_6_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "MCHI" Management Controller Host Interface Table +/// +#define EFI_ACPI_6_0_MANAGEMENT_CONTROLLER_HOST_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'H', 'I') + +/// +/// "MSDM" MS Data Management Table +/// +#define EFI_ACPI_6_0_DATA_MANAGEMENT_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'D', 'M') + +/// +/// "SLIC" MS Software Licensing Table Specification +/// +#define EFI_ACPI_6_0_SOFTWARE_LICENSING_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'C') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_6_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_6_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "STAO" _STA Override Table +/// +#define EFI_ACPI_6_0_STA_OVERRIDE_TABLE_SIGNATURE SIGNATURE_32('S', 'T', 'A', 'O') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_6_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "TPM2" Trusted Computing Platform 1 Table +/// +#define EFI_ACPI_6_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE SIGNATURE_32('T', 'P', 'M', '2') + +/// +/// "UEFI" UEFI ACPI Data Table +/// +#define EFI_ACPI_6_0_UEFI_ACPI_DATA_TABLE_SIGNATURE SIGNATURE_32('U', 'E', 'F', 'I') + +/// +/// "WAET" Windows ACPI Emulated Devices Table +/// +#define EFI_ACPI_6_0_WINDOWS_ACPI_EMULATED_DEVICES_TABLE_SIGNATURE SIGNATURE_32('W', 'A', 'E', 'T') + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_6_0_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_6_0_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +/// +/// "WPBT" MS Platform Binary Table +/// +#define EFI_ACPI_6_0_PLATFORM_BINARY_TABLE_SIGNATURE SIGNATURE_32('W', 'P', 'B', 'T') + +/// +/// "XENV" Xen Project Table +/// +#define EFI_ACPI_6_0_XEN_PROJECT_TABLE_SIGNATURE SIGNATURE_32('X', 'E', 'N', 'V') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi61.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi61.h new file mode 100644 index 0000000..3cebc68 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi61.h @@ -0,0 +1,2424 @@ +/** @file + ACPI 6.1 definitions from the ACPI Specification Revision 6.1 January, 2016. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_6_1_H_ +#define _ACPI_6_1_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 6.1 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_6_1_SYSTEM_MEMORY 0 +#define EFI_ACPI_6_1_SYSTEM_IO 1 +#define EFI_ACPI_6_1_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_6_1_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_6_1_SMBUS 4 +#define EFI_ACPI_6_1_PLATFORM_COMMUNICATION_CHANNEL 0x0A +#define EFI_ACPI_6_1_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_6_1_UNDEFINED 0 +#define EFI_ACPI_6_1_BYTE 1 +#define EFI_ACPI_6_1_WORD 2 +#define EFI_ACPI_6_1_DWORD 3 +#define EFI_ACPI_6_1_QWORD 4 + +// +// ACPI 6.1 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 6.1) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_6_1_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT16 ArmBootArch; + UINT8 MinorVersion; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE SleepControlReg; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE SleepStatusReg; + UINT64 HypervisorVendorIdentity; +} EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x06 +#define EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION 0x01 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_6_1_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_6_1_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_6_1_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_6_1_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_6_1_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_6_1_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_6_1_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_6_1_PM_PROFILE_PERFORMANCE_SERVER 7 +#define EFI_ACPI_6_1_PM_PROFILE_TABLET 8 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_1_LEGACY_DEVICES BIT0 +#define EFI_ACPI_6_1_8042 BIT1 +#define EFI_ACPI_6_1_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_6_1_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_6_1_PCIE_ASPM_CONTROLS BIT4 +#define EFI_ACPI_6_1_CMOS_RTC_NOT_PRESENT BIT5 + +// +// Fixed ACPI Description Table Arm Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_1_ARM_PSCI_COMPLIANT BIT0 +#define EFI_ACPI_6_1_ARM_PSCI_USE_HVC BIT1 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_1_WBINVD BIT0 +#define EFI_ACPI_6_1_WBINVD_FLUSH BIT1 +#define EFI_ACPI_6_1_PROC_C1 BIT2 +#define EFI_ACPI_6_1_P_LVL2_UP BIT3 +#define EFI_ACPI_6_1_PWR_BUTTON BIT4 +#define EFI_ACPI_6_1_SLP_BUTTON BIT5 +#define EFI_ACPI_6_1_FIX_RTC BIT6 +#define EFI_ACPI_6_1_RTC_S4 BIT7 +#define EFI_ACPI_6_1_TMR_VAL_EXT BIT8 +#define EFI_ACPI_6_1_DCK_CAP BIT9 +#define EFI_ACPI_6_1_RESET_REG_SUP BIT10 +#define EFI_ACPI_6_1_SEALED_CASE BIT11 +#define EFI_ACPI_6_1_HEADLESS BIT12 +#define EFI_ACPI_6_1_CPU_SW_SLP BIT13 +#define EFI_ACPI_6_1_PCI_EXP_WAK BIT14 +#define EFI_ACPI_6_1_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_6_1_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_6_1_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_6_1_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_6_1_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 +#define EFI_ACPI_6_1_HW_REDUCED_ACPI BIT20 +#define EFI_ACPI_6_1_LOW_POWER_S0_IDLE_CAPABLE BIT21 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved0[3]; + UINT32 OspmFlags; + UINT8 Reserved1[24]; +} EFI_ACPI_6_1_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x02 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_1_S4BIOS_F BIT0 +#define EFI_ACPI_6_1_64BIT_WAKE_SUPPORTED_F BIT1 + +/// +/// OSPM Enabled Firmware Control Structure Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_1_OSPM_64BIT_WAKE_F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_6_1_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x04 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_1_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x0D and 0x7F are reserved and +// will be ignored by OSPM. 0x80 ~ 0xFF are reserved for OEM. +// +#define EFI_ACPI_6_1_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_6_1_IO_APIC 0x01 +#define EFI_ACPI_6_1_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_6_1_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_6_1_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_6_1_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_6_1_IO_SAPIC 0x06 +#define EFI_ACPI_6_1_LOCAL_SAPIC 0x07 +#define EFI_ACPI_6_1_PLATFORM_INTERRUPT_SOURCES 0x08 +#define EFI_ACPI_6_1_PROCESSOR_LOCAL_X2APIC 0x09 +#define EFI_ACPI_6_1_LOCAL_X2APIC_NMI 0x0A +#define EFI_ACPI_6_1_GIC 0x0B +#define EFI_ACPI_6_1_GICD 0x0C +#define EFI_ACPI_6_1_GIC_MSI_FRAME 0x0D +#define EFI_ACPI_6_1_GICR 0x0E +#define EFI_ACPI_6_1_GIC_ITS 0x0F + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorUid; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_6_1_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_6_1_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_6_1_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_6_1_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_1_POLARITY (3 << 0) +#define EFI_ACPI_6_1_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_6_1_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorUid; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_6_1_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_6_1_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_6_1_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_6_1_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_6_1_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_1_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Processor Local x2APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 AcpiProcessorUid; +} EFI_ACPI_6_1_PROCESSOR_LOCAL_X2APIC_STRUCTURE; + +/// +/// Local x2APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 AcpiProcessorUid; + UINT8 LocalX2ApicLint; + UINT8 Reserved[3]; +} EFI_ACPI_6_1_LOCAL_X2APIC_NMI_STRUCTURE; + +/// +/// GIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 CPUInterfaceNumber; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ParkingProtocolVersion; + UINT32 PerformanceInterruptGsiv; + UINT64 ParkedAddress; + UINT64 PhysicalBaseAddress; + UINT64 GICV; + UINT64 GICH; + UINT32 VGICMaintenanceInterrupt; + UINT64 GICRBaseAddress; + UINT64 MPIDR; + UINT8 ProcessorPowerEfficiencyClass; + UINT8 Reserved2[3]; +} EFI_ACPI_6_1_GIC_STRUCTURE; + +/// +/// GIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_GIC_ENABLED BIT0 +#define EFI_ACPI_6_1_PERFORMANCE_INTERRUPT_MODEL BIT1 +#define EFI_ACPI_6_1_VGIC_MAINTENANCE_INTERRUPT_MODE_FLAGS BIT2 + +/// +/// GIC Distributor Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicId; + UINT64 PhysicalBaseAddress; + UINT32 SystemVectorBase; + UINT8 GicVersion; + UINT8 Reserved2[3]; +} EFI_ACPI_6_1_GIC_DISTRIBUTOR_STRUCTURE; + +/// +/// GIC Version +/// +#define EFI_ACPI_6_1_GIC_V1 0x01 +#define EFI_ACPI_6_1_GIC_V2 0x02 +#define EFI_ACPI_6_1_GIC_V3 0x03 +#define EFI_ACPI_6_1_GIC_V4 0x04 + +/// +/// GIC MSI Frame Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicMsiFrameId; + UINT64 PhysicalBaseAddress; + UINT32 Flags; + UINT16 SPICount; + UINT16 SPIBase; +} EFI_ACPI_6_1_GIC_MSI_FRAME_STRUCTURE; + +/// +/// GIC MSI Frame Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_SPI_COUNT_BASE_SELECT BIT0 + +/// +/// GICR Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 DiscoveryRangeBaseAddress; + UINT32 DiscoveryRangeLength; +} EFI_ACPI_6_1_GICR_STRUCTURE; + +/// +/// GIC Interrupt Translation Service Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 GicItsId; + UINT64 PhysicalBaseAddress; + UINT32 Reserved2; +} EFI_ACPI_6_1_GIC_ITS_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_6_1_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_6_1_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT). The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_6_1_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x03 + +// +// SRAT structure types. +// All other values between 0x04 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_6_1_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_6_1_MEMORY_AFFINITY 0x01 +#define EFI_ACPI_6_1_PROCESSOR_LOCAL_X2APIC_AFFINITY 0x02 +#define EFI_ACPI_6_1_GICC_AFFINITY 0x03 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT32 ClockDomain; +} EFI_ACPI_6_1_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_6_1_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_6_1_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_6_1_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_6_1_MEMORY_NONVOLATILE (1 << 2) + +/// +/// Processor Local x2APIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved1[2]; + UINT32 ProximityDomain; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT8 Reserved2[4]; +} EFI_ACPI_6_1_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE; + +/// +/// GICC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ClockDomain; +} EFI_ACPI_6_1_GICC_AFFINITY_STRUCTURE; + +/// +/// GICC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_GICC_ENABLED (1 << 0) + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_6_1_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +/// +/// Corrected Platform Error Polling Table (CPEP) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[8]; +} EFI_ACPI_6_1_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_HEADER; + +/// +/// CPEP Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_REVISION 0x01 + +// +// CPEP processor structure types. +// +#define EFI_ACPI_6_1_CPEP_PROCESSOR_APIC_SAPIC 0x00 + +/// +/// Corrected Platform Error Polling Processor Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT32 PollingInterval; +} EFI_ACPI_6_1_CPEP_PROCESSOR_APIC_SAPIC_STRUCTURE; + +/// +/// Maximum System Characteristics Table (MSCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetProxDomInfo; + UINT32 MaximumNumberOfProximityDomains; + UINT32 MaximumNumberOfClockDomains; + UINT64 MaximumPhysicalAddress; +} EFI_ACPI_6_1_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_HEADER; + +/// +/// MSCT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_REVISION 0x01 + +/// +/// Maximum Proximity Domain Information Structure Definition +/// +typedef struct { + UINT8 Revision; + UINT8 Length; + UINT32 ProximityDomainRangeLow; + UINT32 ProximityDomainRangeHigh; + UINT32 MaximumProcessorCapacity; + UINT64 MaximumMemoryCapacity; +} EFI_ACPI_6_1_MAXIMUM_PROXIMITY_DOMAIN_INFORMATION_STRUCTURE; + +/// +/// ACPI RAS Feature Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier[12]; +} EFI_ACPI_6_1_RAS_FEATURE_TABLE; + +/// +/// RASF Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_RAS_FEATURE_TABLE_REVISION 0x01 + +/// +/// ACPI RASF Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT16 Version; + UINT8 RASCapabilities[16]; + UINT8 SetRASCapabilities[16]; + UINT16 NumberOfRASFParameterBlocks; + UINT32 SetRASCapabilitiesStatus; +} EFI_ACPI_6_1_RASF_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI RASF PCC command code +/// +#define EFI_ACPI_6_1_RASF_PCC_COMMAND_CODE_EXECUTE_RASF_COMMAND 0x01 + +/// +/// ACPI RASF Platform RAS Capabilities +/// +#define EFI_ACPI_6_1_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED 0x01 +#define EFI_ACPI_6_1_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPOTED_AND_EXPOSED_TO_SOFTWARE 0x02 + +/// +/// ACPI RASF Parameter Block structure for PATROL_SCRUB +/// +typedef struct { + UINT16 Type; + UINT16 Version; + UINT16 Length; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; +} EFI_ACPI_6_1_RASF_PATROL_SCRUB_PLATFORM_BLOCK_STRUCTURE; + +/// +/// ACPI RASF Patrol Scrub command +/// +#define EFI_ACPI_6_1_RASF_PATROL_SCRUB_COMMAND_GET_PATROL_PARAMETERS 0x01 +#define EFI_ACPI_6_1_RASF_PATROL_SCRUB_COMMAND_START_PATROL_SCRUBBER 0x02 +#define EFI_ACPI_6_1_RASF_PATROL_SCRUB_COMMAND_STOP_PATROL_SCRUBBER 0x03 + +/// +/// Memory Power State Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier; + UINT8 Reserved[3]; +// Memory Power Node Structure +// Memory Power State Characteristics +} EFI_ACPI_6_1_MEMORY_POWER_STATUS_TABLE; + +/// +/// MPST Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_MEMORY_POWER_STATE_TABLE_REVISION 0x01 + +/// +/// MPST Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT32 MemoryPowerCommandRegister; + UINT32 MemoryPowerStatusRegister; + UINT32 PowerStateId; + UINT32 MemoryPowerNodeId; + UINT64 MemoryEnergyConsumed; + UINT64 ExpectedAveragePowerComsuned; +} EFI_ACPI_6_1_MPST_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI MPST PCC command code +/// +#define EFI_ACPI_6_1_MPST_PCC_COMMAND_CODE_EXECUTE_MPST_COMMAND 0x03 + +/// +/// ACPI MPST Memory Power command +/// +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_POWER_STATE 0x01 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_COMMAND_SET_MEMORY_POWER_STATE 0x02 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_COMMAND_GET_AVERAGE_POWER_CONSUMED 0x03 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_ENERGY_CONSUMED 0x04 + +/// +/// MPST Memory Power Node Table +/// +typedef struct { + UINT8 PowerStateValue; + UINT8 PowerStateInformationIndex; +} EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE; + +typedef struct { + UINT8 Flag; + UINT8 Reserved; + UINT16 MemoryPowerNodeId; + UINT32 Length; + UINT64 AddressBase; + UINT64 AddressLength; + UINT32 NumberOfPowerStates; + UINT32 NumberOfPhysicalComponents; +//EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE MemoryPowerState[NumberOfPowerStates]; +//UINT16 PhysicalComponentIdentifier[NumberOfPhysicalComponents]; +} EFI_ACPI_6_1_MPST_MEMORY_POWER_STRUCTURE; + +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_STRUCTURE_FLAG_ENABLE 0x01 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_STRUCTURE_FLAG_POWER_MANAGED 0x02 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_STRUCTURE_FLAG_HOT_PLUGGABLE 0x04 + +typedef struct { + UINT16 MemoryPowerNodeCount; + UINT8 Reserved[2]; +} EFI_ACPI_6_1_MPST_MEMORY_POWER_NODE_TABLE; + +/// +/// MPST Memory Power State Characteristics Table +/// +typedef struct { + UINT8 PowerStateStructureID; + UINT8 Flag; + UINT16 Reserved; + UINT32 AveragePowerConsumedInMPS0; + UINT32 RelativePowerSavingToMPS0; + UINT64 ExitLatencyToMPS0; +} EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE; + +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_MEMORY_CONTENT_PRESERVED 0x01 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_ENTRY 0x02 +#define EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_EXIT 0x04 + +typedef struct { + UINT16 MemoryPowerStateCharacteristicsCount; + UINT8 Reserved[2]; +} EFI_ACPI_6_1_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_TABLE; + +/// +/// Memory Topology Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_6_1_MEMORY_TOPOLOGY_TABLE; + +/// +/// PMTT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_MEMORY_TOPOLOGY_TABLE_REVISION 0x01 + +/// +/// Common Memory Aggregator Device Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + UINT16 Flags; + UINT16 Reserved1; +} EFI_ACPI_6_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Memory Aggregator Device Type +/// +#define EFI_ACPI_6_1_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_SOCKET 0x1 +#define EFI_ACPI_6_1_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_MEMORY_CONTROLLER 0x2 +#define EFI_ACPI_6_1_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_DIMM 0x3 + +/// +/// Socket Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 SocketIdentifier; + UINT16 Reserved; +//EFI_ACPI_6_1_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE MemoryController[]; +} EFI_ACPI_6_1_PMMT_SOCKET_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// MemoryController Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT32 ReadLatency; + UINT32 WriteLatency; + UINT32 ReadBandwidth; + UINT32 WriteBandwidth; + UINT16 OptimalAccessUnit; + UINT16 OptimalAccessAlignment; + UINT16 Reserved; + UINT16 NumberOfProximityDomains; +//UINT32 ProximityDomain[NumberOfProximityDomains]; +//EFI_ACPI_6_1_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE PhysicalComponent[]; +} EFI_ACPI_6_1_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// DIMM Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_1_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 PhysicalComponentIdentifier; + UINT16 Reserved; + UINT32 SizeOfDimm; + UINT32 SmbiosHandle; +} EFI_ACPI_6_1_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Boot Graphics Resource Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /// + /// 2-bytes (16 bit) version ID. This value must be 1. + /// + UINT16 Version; + /// + /// 1-byte status field indicating current status about the table. + /// Bits[7:1] = Reserved (must be zero) + /// Bit [0] = Valid. A one indicates the boot image graphic is valid. + /// + UINT8 Status; + /// + /// 1-byte enumerated type field indicating format of the image. + /// 0 = Bitmap + /// 1 - 255 Reserved (for future use) + /// + UINT8 ImageType; + /// + /// 8-byte (64 bit) physical address pointing to the firmware's in-memory copy + /// of the image bitmap. + /// + UINT64 ImageAddress; + /// + /// A 4-byte (32-bit) unsigned long describing the display X-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetX; + /// + /// A 4-byte (32-bit) unsigned long describing the display Y-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetY; +} EFI_ACPI_6_1_BOOT_GRAPHICS_RESOURCE_TABLE; + +/// +/// BGRT Revision +/// +#define EFI_ACPI_6_1_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION 1 + +/// +/// BGRT Version +/// +#define EFI_ACPI_6_1_BGRT_VERSION 0x01 + +/// +/// BGRT Status +/// +#define EFI_ACPI_6_1_BGRT_STATUS_NOT_DISPLAYED 0x00 +#define EFI_ACPI_6_1_BGRT_STATUS_DISPLAYED 0x01 + +/// +/// BGRT Image Type +/// +#define EFI_ACPI_6_1_BGRT_IMAGE_TYPE_BMP 0x00 + +/// +/// FPDT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION 0x01 + +/// +/// FPDT Performance Record Types +/// +#define EFI_ACPI_6_1_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER 0x0000 +#define EFI_ACPI_6_1_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER 0x0001 + +/// +/// FPDT Performance Record Revision +/// +#define EFI_ACPI_6_1_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER 0x01 +#define EFI_ACPI_6_1_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER 0x01 + +/// +/// FPDT Runtime Performance Record Types +/// +#define EFI_ACPI_6_1_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME 0x0000 +#define EFI_ACPI_6_1_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND 0x0001 +#define EFI_ACPI_6_1_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT 0x0002 + +/// +/// FPDT Runtime Performance Record Revision +/// +#define EFI_ACPI_6_1_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME 0x01 +#define EFI_ACPI_6_1_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND 0x01 +#define EFI_ACPI_6_1_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT 0x02 + +/// +/// FPDT Performance Record header +/// +typedef struct { + UINT16 Type; + UINT8 Length; + UINT8 Revision; +} EFI_ACPI_6_1_FPDT_PERFORMANCE_RECORD_HEADER; + +/// +/// FPDT Performance Table header +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_6_1_FPDT_PERFORMANCE_TABLE_HEADER; + +/// +/// FPDT Firmware Basic Boot Performance Pointer Record Structure +/// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the Basic Boot Performance Table. + /// + UINT64 BootPerformanceTablePointer; +} EFI_ACPI_6_1_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT S3 Performance Table Pointer Record Structure +/// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the S3 Performance Table. + /// + UINT64 S3PerformanceTablePointer; +} EFI_ACPI_6_1_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Record Structure +/// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// Timer value logged at the beginning of firmware image execution. + /// This may not always be zero or near zero. + /// + UINT64 ResetEnd; + /// + /// Timer value logged just prior to loading the OS boot loader into memory. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 OsLoaderLoadImageStart; + /// + /// Timer value logged just prior to launching the previously loaded OS boot loader image. + /// For non-UEFI compatible boots, the timer value logged will be just prior + /// to the INT 19h handler invocation. + /// + UINT64 OsLoaderStartImageStart; + /// + /// Timer value logged at the point when the OS loader calls the + /// ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesEntry; + /// + /// Timer value logged at the point just prior towhen the OS loader gaining + /// control back from calls the ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesExit; +} EFI_ACPI_6_1_FPDT_FIRMWARE_BASIC_BOOT_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Table signature +/// +#define EFI_ACPI_6_1_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('F', 'B', 'P', 'T') + +// +// FPDT Firmware Basic Boot Performance Table +// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_6_1_FPDT_FIRMWARE_BASIC_BOOT_TABLE; + +/// +/// FPDT "S3PT" S3 Performance Table +/// +#define EFI_ACPI_6_1_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('S', '3', 'P', 'T') + +// +// FPDT Firmware S3 Boot Performance Table +// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_6_1_FPDT_FIRMWARE_S3_BOOT_TABLE; + +/// +/// FPDT Basic S3 Resume Performance Record +/// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// A count of the number of S3 resume cycles since the last full boot sequence. + /// + UINT32 ResumeCount; + /// + /// Timer recorded at the end of BIOS S3 resume, just prior to handoff to the + /// OS waking vector. Only the most recent resume cycle's time is retained. + /// + UINT64 FullResume; + /// + /// Average timer value of all resume cycles logged since the last full boot + /// sequence, including the most recent resume. Note that the entire log of + /// timer values does not need to be retained in order to calculate this average. + /// + UINT64 AverageResume; +} EFI_ACPI_6_1_FPDT_S3_RESUME_RECORD; + +/// +/// FPDT Basic S3 Suspend Performance Record +/// +typedef struct { + EFI_ACPI_6_1_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// Timer value recorded at the OS write to SLP_TYP upon entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendStart; + /// + /// Timer value recorded at the final firmware write to SLP_TYP (or other + /// mechanism) used to trigger hardware entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendEnd; +} EFI_ACPI_6_1_FPDT_S3_SUSPEND_RECORD; + +/// +/// Firmware Performance Record Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_6_1_FIRMWARE_PERFORMANCE_RECORD_TABLE; + +/// +/// Generic Timer Description Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 CntControlBasePhysicalAddress; + UINT32 Reserved; + UINT32 SecurePL1TimerGSIV; + UINT32 SecurePL1TimerFlags; + UINT32 NonSecurePL1TimerGSIV; + UINT32 NonSecurePL1TimerFlags; + UINT32 VirtualTimerGSIV; + UINT32 VirtualTimerFlags; + UINT32 NonSecurePL2TimerGSIV; + UINT32 NonSecurePL2TimerFlags; + UINT64 CntReadBasePhysicalAddress; + UINT32 PlatformTimerCount; + UINT32 PlatformTimerOffset; +} EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE; + +/// +/// GTDT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_1_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_6_1_GTDT_TIMER_FLAG_ALWAYS_ON_CAPABILITY BIT2 + +/// +/// Platform Timer Type +/// +#define EFI_ACPI_6_1_GTDT_GT_BLOCK 0 +#define EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG 1 + +/// +/// GT Block Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 CntCtlBase; + UINT32 GTBlockTimerCount; + UINT32 GTBlockTimerOffset; +} EFI_ACPI_6_1_GTDT_GT_BLOCK_STRUCTURE; + +/// +/// GT Block Timer Structure +/// +typedef struct { + UINT8 GTFrameNumber; + UINT8 Reserved[3]; + UINT64 CntBaseX; + UINT64 CntEL0BaseX; + UINT32 GTxPhysicalTimerGSIV; + UINT32 GTxPhysicalTimerFlags; + UINT32 GTxVirtualTimerGSIV; + UINT32 GTxVirtualTimerFlags; + UINT32 GTxCommonFlags; +} EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_STRUCTURE; + +/// +/// GT Block Physical Timers and Virtual Timers Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_1_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 + +/// +/// Common Flags Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_GTDT_GT_BLOCK_COMMON_FLAG_SECURE_TIMER BIT0 +#define EFI_ACPI_6_1_GTDT_GT_BLOCK_COMMON_FLAG_ALWAYS_ON_CAPABILITY BIT1 + +/// +/// SBSA Generic Watchdog Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 RefreshFramePhysicalAddress; + UINT64 WatchdogControlFramePhysicalAddress; + UINT32 WatchdogTimerGSIV; + UINT32 WatchdogTimerFlags; +} EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE; + +/// +/// SBSA Generic Watchdog Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_6_1_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_SECURE_TIMER BIT2 + +// +// NVDIMM Firmware Interface Table definition. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE; + +// +// NFIT Version (as defined in ACPI 6.1 spec.) +// +#define EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION 0x1 + +// +// Definition for NFIT Table Structure Types +// +#define EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE 0 +#define EFI_ACPI_6_1_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE_TYPE 1 +#define EFI_ACPI_6_1_NFIT_INTERLEAVE_STRUCTURE_TYPE 2 +#define EFI_ACPI_6_1_NFIT_SMBIOS_MANAGEMENT_INFORMATION_STRUCTURE_TYPE 3 +#define EFI_ACPI_6_1_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE_TYPE 4 +#define EFI_ACPI_6_1_NFIT_NVDIMM_BLOCK_DATA_WINDOW_REGION_STRUCTURE_TYPE 5 +#define EFI_ACPI_6_1_NFIT_FLUSH_HINT_ADDRESS_STRUCTURE_TYPE 6 + +// +// Definition for NFIT Structure Header +// +typedef struct { + UINT16 Type; + UINT16 Length; +} EFI_ACPI_6_1_NFIT_STRUCTURE_HEADER; + +// +// Definition for System Physical Address Range Structure +// +#define EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_FLAGS_CONTROL_REGION_FOR_MANAGEMENT BIT0 +#define EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_FLAGS_PROXIMITY_DOMAIN_VALID BIT1 +#define EFI_ACPI_6_1_NFIT_GUID_VOLATILE_MEMORY_REGION { 0x7305944F, 0xFDDA, 0x44E3, { 0xB1, 0x6C, 0x3F, 0x22, 0xD2, 0x52, 0xE5, 0xD0 }} +#define EFI_ACPI_6_1_NFIT_GUID_BYTE_ADDRESSABLE_PERSISTENT_MEMORY_REGION { 0x66F0D379, 0xB4F3, 0x4074, { 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C, 0xDB }} +#define EFI_ACPI_6_1_NFIT_GUID_NVDIMM_CONTROL_REGION { 0x92F701F6, 0x13B4, 0x405D, { 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }} +#define EFI_ACPI_6_1_NFIT_GUID_NVDIMM_BLOCK_DATA_WINDOW_REGION { 0x91AF0530, 0x5D86, 0x470E, { 0xA6, 0xB0, 0x0A, 0x2D, 0xB9, 0x40, 0x82, 0x49 }} +#define EFI_ACPI_6_1_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_VOLATILE { 0x77AB535A, 0x45FC, 0x624B, { 0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }} +#define EFI_ACPI_6_1_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_VOLATILE { 0x3D5ABD30, 0x4175, 0x87CE, { 0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }} +#define EFI_ACPI_6_1_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_PERSISTENT { 0x5CEA02C9, 0x4D07, 0x69D3, { 0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }} +#define EFI_ACPI_6_1_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_PERSISTENT { 0x08018188, 0x42CD, 0xBB48, { 0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }} +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 SPARangeStructureIndex; + UINT16 Flags; + UINT32 Reserved_8; + UINT32 ProximityDomain; + GUID AddressRangeTypeGUID; + UINT64 SystemPhysicalAddressRangeBase; + UINT64 SystemPhysicalAddressRangeLength; + UINT64 AddressRangeMemoryMappingAttribute; +} EFI_ACPI_6_1_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE; + +// +// Definition for Memory Device to System Physical Address Range Mapping Structure +// +typedef struct { + UINT32 DIMMNumber:4; + UINT32 MemoryChannelNumber:4; + UINT32 MemoryControllerID:4; + UINT32 SocketID:4; + UINT32 NodeControllerID:12; + UINT32 Reserved_28:4; +} EFI_ACPI_6_1_NFIT_DEVICE_HANDLE; + +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_PREVIOUS_SAVE_FAIL BIT0 +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_LAST_RESTORE_FAIL BIT1 +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_PLATFORM_FLUSH_FAIL BIT2 +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_NOT_ARMED_PRIOR_TO_OSPM_HAND_OFF BIT3 +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_SMART_HEALTH_EVENTS_PRIOR_OSPM_HAND_OFF BIT4 +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_FIRMWARE_ENABLED_TO_NOTIFY_OSPM_ON_SMART_HEALTH_EVENTS BIT5 +#define EFI_ACPI_6_1_NFIT_MEMORY_DEVICE_STATE_FLAGS_FIRMWARE_NOT_MAP_NVDIMM_TO_SPA BIT6 +typedef struct { + UINT16 Type; + UINT16 Length; + EFI_ACPI_6_1_NFIT_DEVICE_HANDLE NFITDeviceHandle; + UINT16 NVDIMMPhysicalID; + UINT16 NVDIMMRegionID; + UINT16 SPARangeStructureIndex ; + UINT16 NVDIMMControlRegionStructureIndex; + UINT64 NVDIMMRegionSize; + UINT64 RegionOffset; + UINT64 NVDIMMPhysicalAddressRegionBase; + UINT16 InterleaveStructureIndex; + UINT16 InterleaveWays; + UINT16 NVDIMMStateFlags; + UINT16 Reserved_46; +} EFI_ACPI_6_1_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE; + +// +// Definition for Interleave Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 InterleaveStructureIndex; + UINT16 Reserved_6; + UINT32 NumberOfLines; + UINT32 LineSize; +//UINT32 LineOffset[NumberOfLines]; +} EFI_ACPI_6_1_NFIT_INTERLEAVE_STRUCTURE; + +// +// Definition for SMBIOS Management Information Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT32 Reserved_4; +//UINT8 Data[]; +} EFI_ACPI_6_1_NFIT_SMBIOS_MANAGEMENT_INFORMATION_STRUCTURE; + +// +// Definition for NVDIMM Control Region Structure +// +#define EFI_ACPI_6_1_NFIT_NVDIMM_CONTROL_REGION_VALID_FIELDS_MANUFACTURING BIT0 + +#define EFI_ACPI_6_1_NFIT_NVDIMM_CONTROL_REGION_FLAGS_BLOCK_DATA_WINDOWS_BUFFERED BIT0 +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 NVDIMMControlRegionStructureIndex; + UINT16 VendorID; + UINT16 DeviceID; + UINT16 RevisionID; + UINT16 SubsystemVendorID; + UINT16 SubsystemDeviceID; + UINT16 SubsystemRevisionID; + UINT8 ValidFields; + UINT8 ManufacturingLocation; + UINT16 ManufacturingDate; + UINT8 Reserved_22[2]; + UINT32 SerialNumber; + UINT16 RegionFormatInterfaceCode; + UINT16 NumberOfBlockControlWindows; + UINT64 SizeOfBlockControlWindow; + UINT64 CommandRegisterOffsetInBlockControlWindow; + UINT64 SizeOfCommandRegisterInBlockControlWindows; + UINT64 StatusRegisterOffsetInBlockControlWindow; + UINT64 SizeOfStatusRegisterInBlockControlWindows; + UINT16 NVDIMMControlRegionFlag; + UINT8 Reserved_74[6]; +} EFI_ACPI_6_1_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE; + +// +// Definition for NVDIMM Block Data Window Region Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 NVDIMMControlRegionStructureIndex; + UINT16 NumberOfBlockDataWindows; + UINT64 BlockDataWindowStartOffset; + UINT64 SizeOfBlockDataWindow; + UINT64 BlockAccessibleMemoryCapacity; + UINT64 BeginningAddressOfFirstBlockInBlockAccessibleMemory; +} EFI_ACPI_6_1_NFIT_NVDIMM_BLOCK_DATA_WINDOW_REGION_STRUCTURE; + +// +// Definition for Flush Hint Address Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + EFI_ACPI_6_1_NFIT_DEVICE_HANDLE NFITDeviceHandle; + UINT16 NumberOfFlushHintAddresses; + UINT8 Reserved_10[6]; +//UINT64 FlushHintAddress[NumberOfFlushHintAddresses]; +} EFI_ACPI_6_1_NFIT_FLUSH_HINT_ADDRESS_STRUCTURE; + +/// +/// Boot Error Record Table (BERT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 BootErrorRegionLength; + UINT64 BootErrorRegion; +} EFI_ACPI_6_1_BOOT_ERROR_RECORD_TABLE_HEADER; + +/// +/// BERT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_BOOT_ERROR_RECORD_TABLE_REVISION 0x01 + +/// +/// Boot Error Region Block Status Definition +/// +typedef struct { + UINT32 UncorrectableErrorValid:1; + UINT32 CorrectableErrorValid:1; + UINT32 MultipleUncorrectableErrors:1; + UINT32 MultipleCorrectableErrors:1; + UINT32 ErrorDataEntryCount:10; + UINT32 Reserved:18; +} EFI_ACPI_6_1_ERROR_BLOCK_STATUS; + +/// +/// Boot Error Region Definition +/// +typedef struct { + EFI_ACPI_6_1_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_6_1_BOOT_ERROR_REGION_STRUCTURE; + +// +// Boot Error Severity types +// +#define EFI_ACPI_6_1_ERROR_SEVERITY_CORRECTABLE 0x00 +#define EFI_ACPI_6_1_ERROR_SEVERITY_FATAL 0x01 +#define EFI_ACPI_6_1_ERROR_SEVERITY_CORRECTED 0x02 +#define EFI_ACPI_6_1_ERROR_SEVERITY_NONE 0x03 + +/// +/// Generic Error Data Entry Definition +/// +typedef struct { + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; + UINT8 Timestamp[8]; +} EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_STRUCTURE; + +/// +/// Generic Error Data Entry Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_GENERIC_ERROR_DATA_ENTRY_REVISION 0x0300 + +/// +/// HEST - Hardware Error Source Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ErrorSourceCount; +} EFI_ACPI_6_1_HARDWARE_ERROR_SOURCE_TABLE_HEADER; + +/// +/// HEST Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_HARDWARE_ERROR_SOURCE_TABLE_REVISION 0x01 + +// +// Error Source structure types. +// +#define EFI_ACPI_6_1_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION 0x00 +#define EFI_ACPI_6_1_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK 0x01 +#define EFI_ACPI_6_1_IA32_ARCHITECTURE_NMI_ERROR 0x02 +#define EFI_ACPI_6_1_PCI_EXPRESS_ROOT_PORT_AER 0x06 +#define EFI_ACPI_6_1_PCI_EXPRESS_DEVICE_AER 0x07 +#define EFI_ACPI_6_1_PCI_EXPRESS_BRIDGE_AER 0x08 +#define EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR 0x09 +#define EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_VERSION_2 0x0A + +// +// Error Source structure flags. +// +#define EFI_ACPI_6_1_ERROR_SOURCE_FLAG_FIRMWARE_FIRST (1 << 0) +#define EFI_ACPI_6_1_ERROR_SOURCE_FLAG_GLOBAL (1 << 1) + +/// +/// IA-32 Architecture Machine Check Exception Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityInitData; + UINT64 GlobalControlInitData; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[7]; +} EFI_ACPI_6_1_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure Definition +/// +typedef struct { + UINT8 BankNumber; + UINT8 ClearStatusOnInitialization; + UINT8 StatusDataFormat; + UINT8 Reserved0; + UINT32 ControlRegisterMsrAddress; + UINT64 ControlInitData; + UINT32 StatusRegisterMsrAddress; + UINT32 AddressRegisterMsrAddress; + UINT32 MiscRegisterMsrAddress; +} EFI_ACPI_6_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure MCA data format +/// +#define EFI_ACPI_6_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_IA32 0x00 +#define EFI_ACPI_6_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_INTEL64 0x01 +#define EFI_ACPI_6_1_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_AMD64 0x02 + +// +// Hardware Error Notification types. All other values are reserved +// +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_POLLED 0x00 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_EXTERNAL_INTERRUPT 0x01 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_LOCAL_INTERRUPT 0x02 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_SCI 0x03 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_NMI 0x04 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_CMCI 0x05 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_MCE 0x06 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_GPIO_SIGNAL 0x07 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_ARMV8_SEA 0x08 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_ARMV8_SEI 0x09 +#define EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_GSIV 0x0A + +/// +/// Hardware Error Notification Configuration Write Enable Structure Definition +/// +typedef struct { + UINT16 Type:1; + UINT16 PollInterval:1; + UINT16 SwitchToPollingThresholdValue:1; + UINT16 SwitchToPollingThresholdWindow:1; + UINT16 ErrorThresholdValue:1; + UINT16 ErrorThresholdWindow:1; + UINT16 Reserved:10; +} EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE; + +/// +/// Hardware Error Notification Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE ConfigurationWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 SwitchToPollingThresholdValue; + UINT32 SwitchToPollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; +} EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE; + +/// +/// IA-32 Architecture Corrected Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_6_1_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE; + +/// +/// IA-32 Architecture NMI Error Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; +} EFI_ACPI_6_1_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE; + +/// +/// PCI Express Root Port AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 RootErrorCommand; +} EFI_ACPI_6_1_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE; + +/// +/// PCI Express Device AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_6_1_PCI_EXPRESS_DEVICE_AER_STRUCTURE; + +/// +/// PCI Express Bridge AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 SecondaryUncorrectableErrorMask; + UINT32 SecondaryUncorrectableErrorSeverity; + UINT32 SecondaryAdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_6_1_PCI_EXPRESS_BRIDGE_AER_STRUCTURE; + +/// +/// Generic Hardware Error Source Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; +} EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE; + +/// +/// Generic Hardware Error Source Version 2 Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE ReadAckRegister; + UINT64 ReadAckPreserve; + UINT64 ReadAckWrite; +} EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE; + +/// +/// Generic Error Status Definition +/// +typedef struct { + EFI_ACPI_6_1_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_6_1_GENERIC_ERROR_STATUS_STRUCTURE; + +/// +/// ERST - Error Record Serialization Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 SerializationHeaderSize; + UINT8 Reserved0[4]; + UINT32 InstructionEntryCount; +} EFI_ACPI_6_1_ERROR_RECORD_SERIALIZATION_TABLE_HEADER; + +/// +/// ERST Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_ERROR_RECORD_SERIALIZATION_TABLE_REVISION 0x01 + +/// +/// ERST Serialization Actions +/// +#define EFI_ACPI_6_1_ERST_BEGIN_WRITE_OPERATION 0x00 +#define EFI_ACPI_6_1_ERST_BEGIN_READ_OPERATION 0x01 +#define EFI_ACPI_6_1_ERST_BEGIN_CLEAR_OPERATION 0x02 +#define EFI_ACPI_6_1_ERST_END_OPERATION 0x03 +#define EFI_ACPI_6_1_ERST_SET_RECORD_OFFSET 0x04 +#define EFI_ACPI_6_1_ERST_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_6_1_ERST_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_6_1_ERST_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_6_1_ERST_GET_RECORD_IDENTIFIER 0x08 +#define EFI_ACPI_6_1_ERST_SET_RECORD_IDENTIFIER 0x09 +#define EFI_ACPI_6_1_ERST_GET_RECORD_COUNT 0x0A +#define EFI_ACPI_6_1_ERST_BEGIN_DUMMY_WRITE_OPERATION 0x0B +#define EFI_ACPI_6_1_ERST_GET_ERROR_LOG_ADDRESS_RANGE 0x0D +#define EFI_ACPI_6_1_ERST_GET_ERROR_LOG_ADDRESS_RANGE_LENGTH 0x0E +#define EFI_ACPI_6_1_ERST_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0x0F +#define EFI_ACPI_6_1_ERST_GET_EXECUTE_OPERATION_TIMINGS 0x10 + +/// +/// ERST Action Command Status +/// +#define EFI_ACPI_6_1_ERST_STATUS_SUCCESS 0x00 +#define EFI_ACPI_6_1_ERST_STATUS_NOT_ENOUGH_SPACE 0x01 +#define EFI_ACPI_6_1_ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x02 +#define EFI_ACPI_6_1_ERST_STATUS_FAILED 0x03 +#define EFI_ACPI_6_1_ERST_STATUS_RECORD_STORE_EMPTY 0x04 +#define EFI_ACPI_6_1_ERST_STATUS_RECORD_NOT_FOUND 0x05 + +/// +/// ERST Serialization Instructions +/// +#define EFI_ACPI_6_1_ERST_READ_REGISTER 0x00 +#define EFI_ACPI_6_1_ERST_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_6_1_ERST_WRITE_REGISTER 0x02 +#define EFI_ACPI_6_1_ERST_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_6_1_ERST_NOOP 0x04 +#define EFI_ACPI_6_1_ERST_LOAD_VAR1 0x05 +#define EFI_ACPI_6_1_ERST_LOAD_VAR2 0x06 +#define EFI_ACPI_6_1_ERST_STORE_VAR1 0x07 +#define EFI_ACPI_6_1_ERST_ADD 0x08 +#define EFI_ACPI_6_1_ERST_SUBTRACT 0x09 +#define EFI_ACPI_6_1_ERST_ADD_VALUE 0x0A +#define EFI_ACPI_6_1_ERST_SUBTRACT_VALUE 0x0B +#define EFI_ACPI_6_1_ERST_STALL 0x0C +#define EFI_ACPI_6_1_ERST_STALL_WHILE_TRUE 0x0D +#define EFI_ACPI_6_1_ERST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E +#define EFI_ACPI_6_1_ERST_GOTO 0x0F +#define EFI_ACPI_6_1_ERST_SET_SRC_ADDRESS_BASE 0x10 +#define EFI_ACPI_6_1_ERST_SET_DST_ADDRESS_BASE 0x11 +#define EFI_ACPI_6_1_ERST_MOVE_DATA 0x12 + +/// +/// ERST Instruction Flags +/// +#define EFI_ACPI_6_1_ERST_PRESERVE_REGISTER 0x01 + +/// +/// ERST Serialization Instruction Entry +/// +typedef struct { + UINT8 SerializationAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_6_1_ERST_SERIALIZATION_INSTRUCTION_ENTRY; + +/// +/// EINJ - Error Injection Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 InjectionHeaderSize; + UINT8 InjectionFlags; + UINT8 Reserved0[3]; + UINT32 InjectionEntryCount; +} EFI_ACPI_6_1_ERROR_INJECTION_TABLE_HEADER; + +/// +/// EINJ Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_ERROR_INJECTION_TABLE_REVISION 0x01 + +/// +/// EINJ Error Injection Actions +/// +#define EFI_ACPI_6_1_EINJ_BEGIN_INJECTION_OPERATION 0x00 +#define EFI_ACPI_6_1_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE 0x01 +#define EFI_ACPI_6_1_EINJ_SET_ERROR_TYPE 0x02 +#define EFI_ACPI_6_1_EINJ_GET_ERROR_TYPE 0x03 +#define EFI_ACPI_6_1_EINJ_END_OPERATION 0x04 +#define EFI_ACPI_6_1_EINJ_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_6_1_EINJ_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_6_1_EINJ_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_6_1_EINJ_TRIGGER_ERROR 0xFF + +/// +/// EINJ Action Command Status +/// +#define EFI_ACPI_6_1_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_6_1_EINJ_STATUS_UNKNOWN_FAILURE 0x01 +#define EFI_ACPI_6_1_EINJ_STATUS_INVALID_ACCESS 0x02 + +/// +/// EINJ Error Type Definition +/// +#define EFI_ACPI_6_1_EINJ_ERROR_PROCESSOR_CORRECTABLE (1 << 0) +#define EFI_ACPI_6_1_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_NONFATAL (1 << 1) +#define EFI_ACPI_6_1_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_FATAL (1 << 2) +#define EFI_ACPI_6_1_EINJ_ERROR_MEMORY_CORRECTABLE (1 << 3) +#define EFI_ACPI_6_1_EINJ_ERROR_MEMORY_UNCORRECTABLE_NONFATAL (1 << 4) +#define EFI_ACPI_6_1_EINJ_ERROR_MEMORY_UNCORRECTABLE_FATAL (1 << 5) +#define EFI_ACPI_6_1_EINJ_ERROR_PCI_EXPRESS_CORRECTABLE (1 << 6) +#define EFI_ACPI_6_1_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_NONFATAL (1 << 7) +#define EFI_ACPI_6_1_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_FATAL (1 << 8) +#define EFI_ACPI_6_1_EINJ_ERROR_PLATFORM_CORRECTABLE (1 << 9) +#define EFI_ACPI_6_1_EINJ_ERROR_PLATFORM_UNCORRECTABLE_NONFATAL (1 << 10) +#define EFI_ACPI_6_1_EINJ_ERROR_PLATFORM_UNCORRECTABLE_FATAL (1 << 11) + +/// +/// EINJ Injection Instructions +/// +#define EFI_ACPI_6_1_EINJ_READ_REGISTER 0x00 +#define EFI_ACPI_6_1_EINJ_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_6_1_EINJ_WRITE_REGISTER 0x02 +#define EFI_ACPI_6_1_EINJ_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_6_1_EINJ_NOOP 0x04 + +/// +/// EINJ Instruction Flags +/// +#define EFI_ACPI_6_1_EINJ_PRESERVE_REGISTER 0x01 + +/// +/// EINJ Injection Instruction Entry +/// +typedef struct { + UINT8 InjectionAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_6_1_EINJ_INJECTION_INSTRUCTION_ENTRY; + +/// +/// EINJ Trigger Action Table +/// +typedef struct { + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; +} EFI_ACPI_6_1_EINJ_TRIGGER_ACTION_TABLE; + +/// +/// Platform Communications Channel Table (PCCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Flags; + UINT64 Reserved; +} EFI_ACPI_6_1_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER; + +/// +/// PCCT Version (as defined in ACPI 6.1 spec.) +/// +#define EFI_ACPI_6_1_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION 0x01 + +/// +/// PCCT Global Flags +/// +#define EFI_ACPI_6_1_PCCT_FLAGS_SCI_DOORBELL BIT0 + +// +// PCCT Subspace type +// +#define EFI_ACPI_6_1_PCCT_SUBSPACE_TYPE_GENERIC 0x00 +#define EFI_ACPI_6_1_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS 0x01 +#define EFI_ACPI_6_1_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS 0x02 + +/// +/// PCC Subspace Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Length; +} EFI_ACPI_6_1_PCCT_SUBSPACE_HEADER; + +/// +/// Generic Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_6_1_PCCT_SUBSPACE_GENERIC; + +/// +/// Generic Communications Channel Shared Memory Region +/// + +typedef struct { + UINT8 Command; + UINT8 Reserved:7; + UINT8 GenerateSci:1; +} EFI_ACPI_6_1_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND; + +typedef struct { + UINT8 CommandComplete:1; + UINT8 SciDoorbell:1; + UINT8 Error:1; + UINT8 PlatformNotification:1; + UINT8 Reserved:4; + UINT8 Reserved1; +} EFI_ACPI_6_1_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS; + +typedef struct { + UINT32 Signature; + EFI_ACPI_6_1_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND Command; + EFI_ACPI_6_1_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS Status; +} EFI_ACPI_6_1_PCCT_GENERIC_SHARED_MEMORY_REGION_HEADER; + +#define EFI_ACPI_6_1_PCCT_SUBSPACE_DOORBELL_INTERRUPT_FLAGS_POLARITY BIT0 +#define EFI_ACPI_6_1_PCCT_SUBSPACE_DOORBELL_INTERRUPT_FLAGS_MODE BIT1 + +/// +/// Type 1 HW-Reduced Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 DoorbellInterrupt; + UINT8 DoorbellInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_6_1_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS; + +/// +/// Type 2 HW-Reduced Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 DoorbellInterrupt; + UINT8 DoorbellInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE DoorbellAckRegister; + UINT64 DoorbellAckPreserve; + UINT64 DoorbellAckWrite; +} EFI_ACPI_6_1_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_6_1_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BERT" Boot Error Record Table +/// +#define EFI_ACPI_6_1_BOOT_ERROR_RECORD_TABLE_SIGNATURE SIGNATURE_32('B', 'E', 'R', 'T') + +/// +/// "BGRT" Boot Graphics Resource Table +/// +#define EFI_ACPI_6_1_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('B', 'G', 'R', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_6_1_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_6_1_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_6_1_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "EINJ" Error Injection Table +/// +#define EFI_ACPI_6_1_ERROR_INJECTION_TABLE_SIGNATURE SIGNATURE_32('E', 'I', 'N', 'J') + +/// +/// "ERST" Error Record Serialization Table +/// +#define EFI_ACPI_6_1_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE SIGNATURE_32('E', 'R', 'S', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_6_1_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_6_1_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FPDT" Firmware Performance Data Table +/// +#define EFI_ACPI_6_1_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE SIGNATURE_32('F', 'P', 'D', 'T') + +/// +/// "GTDT" Generic Timer Description Table +/// +#define EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('G', 'T', 'D', 'T') + +/// +/// "HEST" Hardware Error Source Table +/// +#define EFI_ACPI_6_1_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('H', 'E', 'S', 'T') + +/// +/// "MPST" Memory Power State Table +/// +#define EFI_ACPI_6_1_MEMORY_POWER_STATE_TABLE_SIGNATURE SIGNATURE_32('M', 'P', 'S', 'T') + +/// +/// "MSCT" Maximum System Characteristics Table +/// +#define EFI_ACPI_6_1_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'C', 'T') + +/// +/// "NFIT" NVDIMM Firmware Interface Table +/// +#define EFI_ACPI_6_1_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('N', 'F', 'I', 'T') + +/// +/// "PMTT" Platform Memory Topology Table +/// +#define EFI_ACPI_6_1_PLATFORM_MEMORY_TOPOLOGY_TABLE_SIGNATURE SIGNATURE_32('P', 'M', 'T', 'T') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_6_1_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RASF" ACPI RAS Feature Table +/// +#define EFI_ACPI_6_1_ACPI_RAS_FEATURE_TABLE_SIGNATURE SIGNATURE_32('R', 'A', 'S', 'F') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_6_1_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_6_1_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_6_1_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_6_1_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_6_1_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_6_1_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_6_1_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "CSRT" MS Core System Resource Table +/// +#define EFI_ACPI_6_1_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('C', 'S', 'R', 'T') + +/// +/// "DBG2" MS Debug Port 2 Spec +/// +#define EFI_ACPI_6_1_DEBUG_PORT_2_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', '2') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_6_1_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DMAR" DMA Remapping Table +/// +#define EFI_ACPI_6_1_DMA_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('D', 'M', 'A', 'R') + +/// +/// "DRTM" Dynamic Root of Trust for Measurement Table +/// +#define EFI_ACPI_6_1_DYNAMIC_ROOT_OF_TRUST_FOR_MEASUREMENT_TABLE_SIGNATURE SIGNATURE_32('D', 'R', 'T', 'M') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_6_1_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_6_1_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_6_1_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +/// +/// "IORT" I/O Remapping Table +/// +#define EFI_ACPI_6_1_IO_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('I', 'O', 'R', 'T') + +/// +/// "IVRS" I/O Virtualization Reporting Structure +/// +#define EFI_ACPI_6_1_IO_VIRTUALIZATION_REPORTING_STRUCTURE_SIGNATURE SIGNATURE_32('I', 'V', 'R', 'S') + +/// +/// "LPIT" Low Power Idle Table +/// +#define EFI_ACPI_6_1_LOW_POWER_IDLE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('L', 'P', 'I', 'T') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_6_1_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "MCHI" Management Controller Host Interface Table +/// +#define EFI_ACPI_6_1_MANAGEMENT_CONTROLLER_HOST_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'H', 'I') + +/// +/// "MSDM" MS Data Management Table +/// +#define EFI_ACPI_6_1_DATA_MANAGEMENT_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'D', 'M') + +/// +/// "SLIC" MS Software Licensing Table Specification +/// +#define EFI_ACPI_6_1_SOFTWARE_LICENSING_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'C') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_6_1_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_6_1_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "STAO" _STA Override Table +/// +#define EFI_ACPI_6_1_STA_OVERRIDE_TABLE_SIGNATURE SIGNATURE_32('S', 'T', 'A', 'O') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_6_1_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "TPM2" Trusted Computing Platform 1 Table +/// +#define EFI_ACPI_6_1_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE SIGNATURE_32('T', 'P', 'M', '2') + +/// +/// "UEFI" UEFI ACPI Data Table +/// +#define EFI_ACPI_6_1_UEFI_ACPI_DATA_TABLE_SIGNATURE SIGNATURE_32('U', 'E', 'F', 'I') + +/// +/// "WAET" Windows ACPI Emulated Devices Table +/// +#define EFI_ACPI_6_1_WINDOWS_ACPI_EMULATED_DEVICES_TABLE_SIGNATURE SIGNATURE_32('W', 'A', 'E', 'T') + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_6_1_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_6_1_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +/// +/// "WPBT" MS Platform Binary Table +/// +#define EFI_ACPI_6_1_PLATFORM_BINARY_TABLE_SIGNATURE SIGNATURE_32('W', 'P', 'B', 'T') + +/// +/// "XENV" Xen Project Table +/// +#define EFI_ACPI_6_1_XEN_PROJECT_TABLE_SIGNATURE SIGNATURE_32('X', 'E', 'N', 'V') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi62.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi62.h new file mode 100644 index 0000000..7dcd9ff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Acpi62.h @@ -0,0 +1,2960 @@ +/** @file + ACPI 6.2 definitions from the ACPI Specification Revision 6.2 May, 2017. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ACPI_6_2_H_ +#define _ACPI_6_2_H_ + +#include + +// +// Large Item Descriptor Name +// +#define ACPI_LARGE_PIN_FUNCTION_DESCRIPTOR_NAME 0x0D +#define ACPI_LARGE_PIN_CONFIGURATION_DESCRIPTOR_NAME 0x0F +#define ACPI_LARGE_PIN_GROUP_DESCRIPTOR_NAME 0x10 +#define ACPI_LARGE_PIN_GROUP_FUNCTION_DESCRIPTOR_NAME 0x11 +#define ACPI_LARGE_PIN_GROUP_CONFIGURATION_DESCRIPTOR_NAME 0x12 + +// +// Large Item Descriptor Value +// +#define ACPI_PIN_FUNCTION_DESCRIPTOR 0x8D +#define ACPI_PIN_CONFIGURATION_DESCRIPTOR 0x8F +#define ACPI_PIN_GROUP_DESCRIPTOR 0x90 +#define ACPI_PIN_GROUP_FUNCTION_DESCRIPTOR 0x91 +#define ACPI_PIN_GROUP_CONFIGURATION_DESCRIPTOR 0x92 + +#pragma pack(1) + +/// +/// Pin Function Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT16 Flags; + UINT8 PinPullConfiguration; + UINT16 FunctionNumber; + UINT16 PinTableOffset; + UINT8 ResourceSourceIndex; + UINT16 ResourceSourceNameOffset; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; +} EFI_ACPI_PIN_FUNCTION_DESCRIPTOR; + +/// +/// Pin Configuration Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT16 Flags; + UINT8 PinConfigurationType; + UINT32 PinConfigurationValue; + UINT16 PinTableOffset; + UINT8 ResourceSourceIndex; + UINT16 ResourceSourceNameOffset; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; +} EFI_ACPI_PIN_CONFIGURATION_DESCRIPTOR; + +/// +/// Pin Group Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT16 Flags; + UINT16 PinTableOffset; + UINT16 ResourceLabelOffset; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; +} EFI_ACPI_PIN_GROUP_DESCRIPTOR; + +/// +/// Pin Group Function Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT16 Flags; + UINT16 FunctionNumber; + UINT8 ResourceSourceIndex; + UINT16 ResourceSourceNameOffset; + UINT16 ResourceSourceLabelOffset; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; +} EFI_ACPI_PIN_GROUP_FUNCTION_DESCRIPTOR; + +/// +/// Pin Group Configuration Descriptor +/// +typedef PACKED struct { + ACPI_LARGE_RESOURCE_HEADER Header; + UINT8 RevisionId; + UINT16 Flags; + UINT8 PinConfigurationType; + UINT32 PinConfigurationValue; + UINT8 ResourceSourceIndex; + UINT16 ResourceSourceNameOffset; + UINT16 ResourceSourceLabelOffset; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; +} EFI_ACPI_PIN_GROUP_CONFIGURATION_DESCRIPTOR; + +#pragma pack() + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// ACPI 6.2 Generic Address Space definition +/// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_6_2_SYSTEM_MEMORY 0 +#define EFI_ACPI_6_2_SYSTEM_IO 1 +#define EFI_ACPI_6_2_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_6_2_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_6_2_SMBUS 4 +#define EFI_ACPI_6_2_PLATFORM_COMMUNICATION_CHANNEL 0x0A +#define EFI_ACPI_6_2_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_6_2_UNDEFINED 0 +#define EFI_ACPI_6_2_BYTE 1 +#define EFI_ACPI_6_2_WORD 2 +#define EFI_ACPI_6_2_DWORD 3 +#define EFI_ACPI_6_2_QWORD 4 + +// +// ACPI 6.2 table structures +// + +/// +/// Root System Description Pointer Structure +/// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER; + +/// +/// RSD_PTR Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 ///< ACPISpec (Revision 6.2) says current value is 2 + +/// +/// Common table header, this prefaces all ACPI tables, including FACS, but +/// excluding the RSD PTR structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_6_2_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers. +// + +/// +/// RSDT Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT64 table pointers. +// + +/// +/// XSDT Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Fixed ACPI Description Table Structure (FADT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT16 ArmBootArch; + UINT8 MinorVersion; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE SleepControlReg; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE SleepStatusReg; + UINT64 HypervisorVendorIdentity; +} EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE; + +/// +/// FADT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x06 +#define EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_MINOR_REVISION 0x02 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_6_2_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_6_2_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_6_2_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_6_2_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_6_2_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_6_2_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_6_2_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_6_2_PM_PROFILE_PERFORMANCE_SERVER 7 +#define EFI_ACPI_6_2_PM_PROFILE_TABLET 8 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_2_LEGACY_DEVICES BIT0 +#define EFI_ACPI_6_2_8042 BIT1 +#define EFI_ACPI_6_2_VGA_NOT_PRESENT BIT2 +#define EFI_ACPI_6_2_MSI_NOT_SUPPORTED BIT3 +#define EFI_ACPI_6_2_PCIE_ASPM_CONTROLS BIT4 +#define EFI_ACPI_6_2_CMOS_RTC_NOT_PRESENT BIT5 + +// +// Fixed ACPI Description Table Arm Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_2_ARM_PSCI_COMPLIANT BIT0 +#define EFI_ACPI_6_2_ARM_PSCI_USE_HVC BIT1 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_2_WBINVD BIT0 +#define EFI_ACPI_6_2_WBINVD_FLUSH BIT1 +#define EFI_ACPI_6_2_PROC_C1 BIT2 +#define EFI_ACPI_6_2_P_LVL2_UP BIT3 +#define EFI_ACPI_6_2_PWR_BUTTON BIT4 +#define EFI_ACPI_6_2_SLP_BUTTON BIT5 +#define EFI_ACPI_6_2_FIX_RTC BIT6 +#define EFI_ACPI_6_2_RTC_S4 BIT7 +#define EFI_ACPI_6_2_TMR_VAL_EXT BIT8 +#define EFI_ACPI_6_2_DCK_CAP BIT9 +#define EFI_ACPI_6_2_RESET_REG_SUP BIT10 +#define EFI_ACPI_6_2_SEALED_CASE BIT11 +#define EFI_ACPI_6_2_HEADLESS BIT12 +#define EFI_ACPI_6_2_CPU_SW_SLP BIT13 +#define EFI_ACPI_6_2_PCI_EXP_WAK BIT14 +#define EFI_ACPI_6_2_USE_PLATFORM_CLOCK BIT15 +#define EFI_ACPI_6_2_S4_RTC_STS_VALID BIT16 +#define EFI_ACPI_6_2_REMOTE_POWER_ON_CAPABLE BIT17 +#define EFI_ACPI_6_2_FORCE_APIC_CLUSTER_MODEL BIT18 +#define EFI_ACPI_6_2_FORCE_APIC_PHYSICAL_DESTINATION_MODE BIT19 +#define EFI_ACPI_6_2_HW_REDUCED_ACPI BIT20 +#define EFI_ACPI_6_2_LOW_POWER_S0_IDLE_CAPABLE BIT21 + +/// +/// Firmware ACPI Control Structure +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved0[3]; + UINT32 OspmFlags; + UINT8 Reserved1[24]; +} EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +/// +/// FACS Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x02 + +/// +/// Firmware Control Structure Feature Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_2_S4BIOS_F BIT0 +#define EFI_ACPI_6_2_64BIT_WAKE_SUPPORTED_F BIT1 + +/// +/// OSPM Enabled Firmware Control Structure Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_2_OSPM_64BIT_WAKE_F BIT0 + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header, the same with +// EFI_ACPI_DESCRIPTION_HEADER, followed by a definition block. +// +#define EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Multiple APIC Description Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +/// +/// MADT Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x04 + +/// +/// Multiple APIC Flags +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_2_PCAT_COMPAT BIT0 + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x0D and 0x7F are reserved and +// will be ignored by OSPM. 0x80 ~ 0xFF are reserved for OEM. +// +#define EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_6_2_IO_APIC 0x01 +#define EFI_ACPI_6_2_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_6_2_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_6_2_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_6_2_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_6_2_IO_SAPIC 0x06 +#define EFI_ACPI_6_2_LOCAL_SAPIC 0x07 +#define EFI_ACPI_6_2_PLATFORM_INTERRUPT_SOURCES 0x08 +#define EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC 0x09 +#define EFI_ACPI_6_2_LOCAL_X2APIC_NMI 0x0A +#define EFI_ACPI_6_2_GIC 0x0B +#define EFI_ACPI_6_2_GICD 0x0C +#define EFI_ACPI_6_2_GIC_MSI_FRAME 0x0D +#define EFI_ACPI_6_2_GICR 0x0E +#define EFI_ACPI_6_2_GIC_ITS 0x0F + +// +// APIC Structure Definitions +// + +/// +/// Processor Local APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorUid; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_STRUCTURE; + +/// +/// Local APIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_LOCAL_APIC_ENABLED BIT0 + +/// +/// IO APIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_6_2_IO_APIC_STRUCTURE; + +/// +/// Interrupt Source Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_6_2_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_6_2_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_6_2_POLARITY (3 << 0) +#define EFI_ACPI_6_2_TRIGGER_MODE (3 << 2) + +/// +/// Non-Maskable Interrupt Source Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_6_2_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +/// +/// Local APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorUid; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_6_2_LOCAL_APIC_NMI_STRUCTURE; + +/// +/// Local APIC Address Override Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_6_2_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +/// +/// IO SAPIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_6_2_IO_SAPIC_STRUCTURE; + +/// +/// Local SAPIC Structure +/// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_6_2_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +/// +/// Platform Interrupt Sources Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_6_2_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +/// +/// Platform Interrupt Source Flags. +/// All other bits are reserved and must be set to 0. +/// +#define EFI_ACPI_6_2_CPEI_PROCESSOR_OVERRIDE BIT0 + +/// +/// Processor Local x2APIC Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 AcpiProcessorUid; +} EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_STRUCTURE; + +/// +/// Local x2APIC NMI Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 AcpiProcessorUid; + UINT8 LocalX2ApicLint; + UINT8 Reserved[3]; +} EFI_ACPI_6_2_LOCAL_X2APIC_NMI_STRUCTURE; + +/// +/// GIC Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 CPUInterfaceNumber; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ParkingProtocolVersion; + UINT32 PerformanceInterruptGsiv; + UINT64 ParkedAddress; + UINT64 PhysicalBaseAddress; + UINT64 GICV; + UINT64 GICH; + UINT32 VGICMaintenanceInterrupt; + UINT64 GICRBaseAddress; + UINT64 MPIDR; + UINT8 ProcessorPowerEfficiencyClass; + UINT8 Reserved2[3]; +} EFI_ACPI_6_2_GIC_STRUCTURE; + +/// +/// GIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_GIC_ENABLED BIT0 +#define EFI_ACPI_6_2_PERFORMANCE_INTERRUPT_MODEL BIT1 +#define EFI_ACPI_6_2_VGIC_MAINTENANCE_INTERRUPT_MODE_FLAGS BIT2 + +/// +/// GIC Distributor Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicId; + UINT64 PhysicalBaseAddress; + UINT32 SystemVectorBase; + UINT8 GicVersion; + UINT8 Reserved2[3]; +} EFI_ACPI_6_2_GIC_DISTRIBUTOR_STRUCTURE; + +/// +/// GIC Version +/// +#define EFI_ACPI_6_2_GIC_V1 0x01 +#define EFI_ACPI_6_2_GIC_V2 0x02 +#define EFI_ACPI_6_2_GIC_V3 0x03 +#define EFI_ACPI_6_2_GIC_V4 0x04 + +/// +/// GIC MSI Frame Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved1; + UINT32 GicMsiFrameId; + UINT64 PhysicalBaseAddress; + UINT32 Flags; + UINT16 SPICount; + UINT16 SPIBase; +} EFI_ACPI_6_2_GIC_MSI_FRAME_STRUCTURE; + +/// +/// GIC MSI Frame Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_SPI_COUNT_BASE_SELECT BIT0 + +/// +/// GICR Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 DiscoveryRangeBaseAddress; + UINT32 DiscoveryRangeLength; +} EFI_ACPI_6_2_GICR_STRUCTURE; + +/// +/// GIC Interrupt Translation Service Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT32 GicItsId; + UINT64 PhysicalBaseAddress; + UINT32 Reserved2; +} EFI_ACPI_6_2_GIC_ITS_STRUCTURE; + +/// +/// Smart Battery Description Table (SBST) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_6_2_SMART_BATTERY_DESCRIPTION_TABLE; + +/// +/// SBST Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +/// +/// Embedded Controller Boot Resources Table (ECDT) +/// The table is followed by a null terminated ASCII string that contains +/// a fully qualified reference to the name space object. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_6_2_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +/// +/// ECDT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +/// +/// System Resource Affinity Table (SRAT). The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; ///< Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +/// +/// SRAT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x03 + +// +// SRAT structure types. +// All other values between 0x05 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_6_2_MEMORY_AFFINITY 0x01 +#define EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY 0x02 +#define EFI_ACPI_6_2_GICC_AFFINITY 0x03 +#define EFI_ACPI_6_2_GIC_ITS_AFFINITY 0x04 + +/// +/// Processor Local APIC/SAPIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT32 ClockDomain; +} EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +/// +/// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +/// +/// Memory Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_6_2_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_6_2_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_6_2_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_6_2_MEMORY_NONVOLATILE (1 << 2) + +/// +/// Processor Local x2APIC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved1[2]; + UINT32 ProximityDomain; + UINT32 X2ApicId; + UINT32 Flags; + UINT32 ClockDomain; + UINT8 Reserved2[4]; +} EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY_STRUCTURE; + +/// +/// GICC Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ClockDomain; +} EFI_ACPI_6_2_GICC_AFFINITY_STRUCTURE; + +/// +/// GICC Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_GICC_ENABLED (1 << 0) + +/// +/// GIC Interrupt Translation Service (ITS) Affinity Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT8 Reserved[2]; + UINT32 ItsId; +} EFI_ACPI_6_2_GIC_ITS_AFFINITY_STRUCTURE; + +/// +/// System Locality Distance Information Table (SLIT). +/// The rest of the table is a matrix. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_6_2_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +/// +/// SLIT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +/// +/// Corrected Platform Error Polling Table (CPEP) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[8]; +} EFI_ACPI_6_2_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_HEADER; + +/// +/// CPEP Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_REVISION 0x01 + +// +// CPEP processor structure types. +// +#define EFI_ACPI_6_2_CPEP_PROCESSOR_APIC_SAPIC 0x00 + +/// +/// Corrected Platform Error Polling Processor Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT32 PollingInterval; +} EFI_ACPI_6_2_CPEP_PROCESSOR_APIC_SAPIC_STRUCTURE; + +/// +/// Maximum System Characteristics Table (MSCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetProxDomInfo; + UINT32 MaximumNumberOfProximityDomains; + UINT32 MaximumNumberOfClockDomains; + UINT64 MaximumPhysicalAddress; +} EFI_ACPI_6_2_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_HEADER; + +/// +/// MSCT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_REVISION 0x01 + +/// +/// Maximum Proximity Domain Information Structure Definition +/// +typedef struct { + UINT8 Revision; + UINT8 Length; + UINT32 ProximityDomainRangeLow; + UINT32 ProximityDomainRangeHigh; + UINT32 MaximumProcessorCapacity; + UINT64 MaximumMemoryCapacity; +} EFI_ACPI_6_2_MAXIMUM_PROXIMITY_DOMAIN_INFORMATION_STRUCTURE; + +/// +/// ACPI RAS Feature Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier[12]; +} EFI_ACPI_6_2_RAS_FEATURE_TABLE; + +/// +/// RASF Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_RAS_FEATURE_TABLE_REVISION 0x01 + +/// +/// ACPI RASF Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT16 Version; + UINT8 RASCapabilities[16]; + UINT8 SetRASCapabilities[16]; + UINT16 NumberOfRASFParameterBlocks; + UINT32 SetRASCapabilitiesStatus; +} EFI_ACPI_6_2_RASF_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI RASF PCC command code +/// +#define EFI_ACPI_6_2_RASF_PCC_COMMAND_CODE_EXECUTE_RASF_COMMAND 0x01 + +/// +/// ACPI RASF Platform RAS Capabilities +/// +#define EFI_ACPI_6_2_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPORTED BIT0 +#define EFI_ACPI_6_2_RASF_PLATFORM_RAS_CAPABILITY_HARDWARE_BASED_PATROL_SCRUB_SUPPORTED_AND_EXPOSED_TO_SOFTWARE BIT1 +#define EFI_ACPI_6_2_RASF_PLATFORM_RAS_CAPABILITY_CPU_CACHE_FLUSH_TO_NVDIMM_DURABILITY_ON_POWER_LOSS BIT2 +#define EFI_ACPI_6_2_RASF_PLATFORM_RAS_CAPABILITY_MEMORY_CONTROLLER_FLUSH_TO_NVDIMM_DURABILITY_ON_POWER_LOSS BIT3 +#define EFI_ACPI_6_2_RASF_PLATFORM_RAS_CAPABILITY_BYTE_ADDRESSABLE_PERSISTENT_MEMORY_HARDWARE_MIRRORING BIT4 + +/// +/// ACPI RASF Parameter Block structure for PATROL_SCRUB +/// +typedef struct { + UINT16 Type; + UINT16 Version; + UINT16 Length; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; +} EFI_ACPI_6_2_RASF_PATROL_SCRUB_PLATFORM_BLOCK_STRUCTURE; + +/// +/// ACPI RASF Patrol Scrub command +/// +#define EFI_ACPI_6_2_RASF_PATROL_SCRUB_COMMAND_GET_PATROL_PARAMETERS 0x01 +#define EFI_ACPI_6_2_RASF_PATROL_SCRUB_COMMAND_START_PATROL_SCRUBBER 0x02 +#define EFI_ACPI_6_2_RASF_PATROL_SCRUB_COMMAND_STOP_PATROL_SCRUBBER 0x03 + +/// +/// Memory Power State Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 PlatformCommunicationChannelIdentifier; + UINT8 Reserved[3]; +// Memory Power Node Structure +// Memory Power State Characteristics +} EFI_ACPI_6_2_MEMORY_POWER_STATUS_TABLE; + +/// +/// MPST Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_MEMORY_POWER_STATE_TABLE_REVISION 0x01 + +/// +/// MPST Platform Communication Channel Shared Memory Region definition. +/// +typedef struct { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT32 MemoryPowerCommandRegister; + UINT32 MemoryPowerStatusRegister; + UINT32 PowerStateId; + UINT32 MemoryPowerNodeId; + UINT64 MemoryEnergyConsumed; + UINT64 ExpectedAveragePowerComsuned; +} EFI_ACPI_6_2_MPST_PLATFORM_COMMUNICATION_CHANNEL_SHARED_MEMORY_REGION; + +/// +/// ACPI MPST PCC command code +/// +#define EFI_ACPI_6_2_MPST_PCC_COMMAND_CODE_EXECUTE_MPST_COMMAND 0x03 + +/// +/// ACPI MPST Memory Power command +/// +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_POWER_STATE 0x01 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_COMMAND_SET_MEMORY_POWER_STATE 0x02 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_COMMAND_GET_AVERAGE_POWER_CONSUMED 0x03 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_COMMAND_GET_MEMORY_ENERGY_CONSUMED 0x04 + +/// +/// MPST Memory Power Node Table +/// +typedef struct { + UINT8 PowerStateValue; + UINT8 PowerStateInformationIndex; +} EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE; + +typedef struct { + UINT8 Flag; + UINT8 Reserved; + UINT16 MemoryPowerNodeId; + UINT32 Length; + UINT64 AddressBase; + UINT64 AddressLength; + UINT32 NumberOfPowerStates; + UINT32 NumberOfPhysicalComponents; +//EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE MemoryPowerState[NumberOfPowerStates]; +//UINT16 PhysicalComponentIdentifier[NumberOfPhysicalComponents]; +} EFI_ACPI_6_2_MPST_MEMORY_POWER_STRUCTURE; + +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_STRUCTURE_FLAG_ENABLE 0x01 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_STRUCTURE_FLAG_POWER_MANAGED 0x02 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_STRUCTURE_FLAG_HOT_PLUGGABLE 0x04 + +typedef struct { + UINT16 MemoryPowerNodeCount; + UINT8 Reserved[2]; +} EFI_ACPI_6_2_MPST_MEMORY_POWER_NODE_TABLE; + +/// +/// MPST Memory Power State Characteristics Table +/// +typedef struct { + UINT8 PowerStateStructureID; + UINT8 Flag; + UINT16 Reserved; + UINT32 AveragePowerConsumedInMPS0; + UINT32 RelativePowerSavingToMPS0; + UINT64 ExitLatencyToMPS0; +} EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE; + +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_MEMORY_CONTENT_PRESERVED 0x01 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_ENTRY 0x02 +#define EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_STRUCTURE_FLAG_AUTONOMOUS_MEMORY_POWER_STATE_EXIT 0x04 + +typedef struct { + UINT16 MemoryPowerStateCharacteristicsCount; + UINT8 Reserved[2]; +} EFI_ACPI_6_2_MPST_MEMORY_POWER_STATE_CHARACTERISTICS_TABLE; + +/// +/// Memory Topology Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_6_2_MEMORY_TOPOLOGY_TABLE; + +/// +/// PMTT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_MEMORY_TOPOLOGY_TABLE_REVISION 0x01 + +/// +/// Common Memory Aggregator Device Structure. +/// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + UINT16 Flags; + UINT16 Reserved1; +} EFI_ACPI_6_2_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Memory Aggregator Device Type +/// +#define EFI_ACPI_6_2_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_SOCKET 0x1 +#define EFI_ACPI_6_2_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_MEMORY_CONTROLLER 0x2 +#define EFI_ACPI_6_2_PMMT_MEMORY_AGGREGATOR_DEVICE_TYPE_DIMM 0x3 + +/// +/// Socket Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_2_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 SocketIdentifier; + UINT16 Reserved; +//EFI_ACPI_6_2_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE MemoryController[]; +} EFI_ACPI_6_2_PMMT_SOCKET_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// MemoryController Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_2_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT32 ReadLatency; + UINT32 WriteLatency; + UINT32 ReadBandwidth; + UINT32 WriteBandwidth; + UINT16 OptimalAccessUnit; + UINT16 OptimalAccessAlignment; + UINT16 Reserved; + UINT16 NumberOfProximityDomains; +//UINT32 ProximityDomain[NumberOfProximityDomains]; +//EFI_ACPI_6_2_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE PhysicalComponent[]; +} EFI_ACPI_6_2_PMMT_MEMORY_CONTROLLER_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// DIMM Memory Aggregator Device Structure. +/// +typedef struct { + EFI_ACPI_6_2_PMMT_COMMON_MEMORY_AGGREGATOR_DEVICE_STRUCTURE Header; + UINT16 PhysicalComponentIdentifier; + UINT16 Reserved; + UINT32 SizeOfDimm; + UINT32 SmbiosHandle; +} EFI_ACPI_6_2_PMMT_DIMM_MEMORY_AGGREGATOR_DEVICE_STRUCTURE; + +/// +/// Boot Graphics Resource Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /// + /// 2-bytes (16 bit) version ID. This value must be 1. + /// + UINT16 Version; + /// + /// 1-byte status field indicating current status about the table. + /// Bits[7:1] = Reserved (must be zero) + /// Bit [0] = Valid. A one indicates the boot image graphic is valid. + /// + UINT8 Status; + /// + /// 1-byte enumerated type field indicating format of the image. + /// 0 = Bitmap + /// 1 - 255 Reserved (for future use) + /// + UINT8 ImageType; + /// + /// 8-byte (64 bit) physical address pointing to the firmware's in-memory copy + /// of the image bitmap. + /// + UINT64 ImageAddress; + /// + /// A 4-byte (32-bit) unsigned long describing the display X-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetX; + /// + /// A 4-byte (32-bit) unsigned long describing the display Y-offset of the boot image. + /// (X, Y) display offset of the top left corner of the boot image. + /// The top left corner of the display is at offset (0, 0). + /// + UINT32 ImageOffsetY; +} EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE; + +/// +/// BGRT Revision +/// +#define EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION 1 + +/// +/// BGRT Version +/// +#define EFI_ACPI_6_2_BGRT_VERSION 0x01 + +/// +/// BGRT Status +/// +#define EFI_ACPI_6_2_BGRT_STATUS_NOT_DISPLAYED 0x00 +#define EFI_ACPI_6_2_BGRT_STATUS_DISPLAYED 0x01 + +/// +/// BGRT Image Type +/// +#define EFI_ACPI_6_2_BGRT_IMAGE_TYPE_BMP 0x00 + +/// +/// FPDT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_FIRMWARE_PERFORMANCE_DATA_TABLE_REVISION 0x01 + +/// +/// FPDT Performance Record Types +/// +#define EFI_ACPI_6_2_FPDT_RECORD_TYPE_FIRMWARE_BASIC_BOOT_POINTER 0x0000 +#define EFI_ACPI_6_2_FPDT_RECORD_TYPE_S3_PERFORMANCE_TABLE_POINTER 0x0001 + +/// +/// FPDT Performance Record Revision +/// +#define EFI_ACPI_6_2_FPDT_RECORD_REVISION_FIRMWARE_BASIC_BOOT_POINTER 0x01 +#define EFI_ACPI_6_2_FPDT_RECORD_REVISION_S3_PERFORMANCE_TABLE_POINTER 0x01 + +/// +/// FPDT Runtime Performance Record Types +/// +#define EFI_ACPI_6_2_FPDT_RUNTIME_RECORD_TYPE_S3_RESUME 0x0000 +#define EFI_ACPI_6_2_FPDT_RUNTIME_RECORD_TYPE_S3_SUSPEND 0x0001 +#define EFI_ACPI_6_2_FPDT_RUNTIME_RECORD_TYPE_FIRMWARE_BASIC_BOOT 0x0002 + +/// +/// FPDT Runtime Performance Record Revision +/// +#define EFI_ACPI_6_2_FPDT_RUNTIME_RECORD_REVISION_S3_RESUME 0x01 +#define EFI_ACPI_6_2_FPDT_RUNTIME_RECORD_REVISION_S3_SUSPEND 0x01 +#define EFI_ACPI_6_2_FPDT_RUNTIME_RECORD_REVISION_FIRMWARE_BASIC_BOOT 0x02 + +/// +/// FPDT Performance Record header +/// +typedef struct { + UINT16 Type; + UINT8 Length; + UINT8 Revision; +} EFI_ACPI_6_2_FPDT_PERFORMANCE_RECORD_HEADER; + +/// +/// FPDT Performance Table header +/// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_6_2_FPDT_PERFORMANCE_TABLE_HEADER; + +/// +/// FPDT Firmware Basic Boot Performance Pointer Record Structure +/// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the Basic Boot Performance Table. + /// + UINT64 BootPerformanceTablePointer; +} EFI_ACPI_6_2_FPDT_BOOT_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT S3 Performance Table Pointer Record Structure +/// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// 64-bit processor-relative physical address of the S3 Performance Table. + /// + UINT64 S3PerformanceTablePointer; +} EFI_ACPI_6_2_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Record Structure +/// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_RECORD_HEADER Header; + UINT32 Reserved; + /// + /// Timer value logged at the beginning of firmware image execution. + /// This may not always be zero or near zero. + /// + UINT64 ResetEnd; + /// + /// Timer value logged just prior to loading the OS boot loader into memory. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 OsLoaderLoadImageStart; + /// + /// Timer value logged just prior to launching the previously loaded OS boot loader image. + /// For non-UEFI compatible boots, the timer value logged will be just prior + /// to the INT 19h handler invocation. + /// + UINT64 OsLoaderStartImageStart; + /// + /// Timer value logged at the point when the OS loader calls the + /// ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesEntry; + /// + /// Timer value logged at the point just prior towhen the OS loader gaining + /// control back from calls the ExitBootServices function for UEFI compatible firmware. + /// For non-UEFI compatible boots, this field must be zero. + /// + UINT64 ExitBootServicesExit; +} EFI_ACPI_6_2_FPDT_FIRMWARE_BASIC_BOOT_RECORD; + +/// +/// FPDT Firmware Basic Boot Performance Table signature +/// +#define EFI_ACPI_6_2_FPDT_BOOT_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('F', 'B', 'P', 'T') + +// +// FPDT Firmware Basic Boot Performance Table +// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_6_2_FPDT_FIRMWARE_BASIC_BOOT_TABLE; + +/// +/// FPDT "S3PT" S3 Performance Table +/// +#define EFI_ACPI_6_2_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE SIGNATURE_32('S', '3', 'P', 'T') + +// +// FPDT Firmware S3 Boot Performance Table +// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_TABLE_HEADER Header; + // + // one or more Performance Records. + // +} EFI_ACPI_6_2_FPDT_FIRMWARE_S3_BOOT_TABLE; + +/// +/// FPDT Basic S3 Resume Performance Record +/// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// A count of the number of S3 resume cycles since the last full boot sequence. + /// + UINT32 ResumeCount; + /// + /// Timer recorded at the end of BIOS S3 resume, just prior to handoff to the + /// OS waking vector. Only the most recent resume cycle's time is retained. + /// + UINT64 FullResume; + /// + /// Average timer value of all resume cycles logged since the last full boot + /// sequence, including the most recent resume. Note that the entire log of + /// timer values does not need to be retained in order to calculate this average. + /// + UINT64 AverageResume; +} EFI_ACPI_6_2_FPDT_S3_RESUME_RECORD; + +/// +/// FPDT Basic S3 Suspend Performance Record +/// +typedef struct { + EFI_ACPI_6_2_FPDT_PERFORMANCE_RECORD_HEADER Header; + /// + /// Timer value recorded at the OS write to SLP_TYP upon entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendStart; + /// + /// Timer value recorded at the final firmware write to SLP_TYP (or other + /// mechanism) used to trigger hardware entry to S3. + /// Only the most recent suspend cycle's timer value is retained. + /// + UINT64 SuspendEnd; +} EFI_ACPI_6_2_FPDT_S3_SUSPEND_RECORD; + +/// +/// Firmware Performance Record Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_6_2_FIRMWARE_PERFORMANCE_RECORD_TABLE; + +/// +/// Generic Timer Description Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 CntControlBasePhysicalAddress; + UINT32 Reserved; + UINT32 SecurePL1TimerGSIV; + UINT32 SecurePL1TimerFlags; + UINT32 NonSecurePL1TimerGSIV; + UINT32 NonSecurePL1TimerFlags; + UINT32 VirtualTimerGSIV; + UINT32 VirtualTimerFlags; + UINT32 NonSecurePL2TimerGSIV; + UINT32 NonSecurePL2TimerFlags; + UINT64 CntReadBasePhysicalAddress; + UINT32 PlatformTimerCount; + UINT32 PlatformTimerOffset; +} EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE; + +/// +/// GTDT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION 0x02 + +/// +/// Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_GTDT_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_2_GTDT_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_6_2_GTDT_TIMER_FLAG_ALWAYS_ON_CAPABILITY BIT2 + +/// +/// Platform Timer Type +/// +#define EFI_ACPI_6_2_GTDT_GT_BLOCK 0 +#define EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG 1 + +/// +/// GT Block Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 CntCtlBase; + UINT32 GTBlockTimerCount; + UINT32 GTBlockTimerOffset; +} EFI_ACPI_6_2_GTDT_GT_BLOCK_STRUCTURE; + +/// +/// GT Block Timer Structure +/// +typedef struct { + UINT8 GTFrameNumber; + UINT8 Reserved[3]; + UINT64 CntBaseX; + UINT64 CntEL0BaseX; + UINT32 GTxPhysicalTimerGSIV; + UINT32 GTxPhysicalTimerFlags; + UINT32 GTxVirtualTimerGSIV; + UINT32 GTxVirtualTimerFlags; + UINT32 GTxCommonFlags; +} EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_STRUCTURE; + +/// +/// GT Block Physical Timers and Virtual Timers Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_2_GTDT_GT_BLOCK_TIMER_FLAG_TIMER_INTERRUPT_POLARITY BIT1 + +/// +/// Common Flags Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_GTDT_GT_BLOCK_COMMON_FLAG_SECURE_TIMER BIT0 +#define EFI_ACPI_6_2_GTDT_GT_BLOCK_COMMON_FLAG_ALWAYS_ON_CAPABILITY BIT1 + +/// +/// SBSA Generic Watchdog Structure +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT64 RefreshFramePhysicalAddress; + UINT64 WatchdogControlFramePhysicalAddress; + UINT32 WatchdogTimerGSIV; + UINT32 WatchdogTimerFlags; +} EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE; + +/// +/// SBSA Generic Watchdog Timer Flags. All other bits are reserved and must be 0. +/// +#define EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_MODE BIT0 +#define EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_TIMER_INTERRUPT_POLARITY BIT1 +#define EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG_FLAG_SECURE_TIMER BIT2 + +// +// NVDIMM Firmware Interface Table definition. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved; +} EFI_ACPI_6_2_NVDIMM_FIRMWARE_INTERFACE_TABLE; + +// +// NFIT Version (as defined in ACPI 6.2 spec.) +// +#define EFI_ACPI_6_2_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION 0x1 + +// +// Definition for NFIT Table Structure Types +// +#define EFI_ACPI_6_2_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE 0 +#define EFI_ACPI_6_2_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE_TYPE 1 +#define EFI_ACPI_6_2_NFIT_INTERLEAVE_STRUCTURE_TYPE 2 +#define EFI_ACPI_6_2_NFIT_SMBIOS_MANAGEMENT_INFORMATION_STRUCTURE_TYPE 3 +#define EFI_ACPI_6_2_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE_TYPE 4 +#define EFI_ACPI_6_2_NFIT_NVDIMM_BLOCK_DATA_WINDOW_REGION_STRUCTURE_TYPE 5 +#define EFI_ACPI_6_2_NFIT_FLUSH_HINT_ADDRESS_STRUCTURE_TYPE 6 + +// +// Definition for NFIT Structure Header +// +typedef struct { + UINT16 Type; + UINT16 Length; +} EFI_ACPI_6_2_NFIT_STRUCTURE_HEADER; + +// +// Definition for System Physical Address Range Structure +// +#define EFI_ACPI_6_2_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_FLAGS_CONTROL_REGION_FOR_MANAGEMENT BIT0 +#define EFI_ACPI_6_2_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_FLAGS_PROXIMITY_DOMAIN_VALID BIT1 +#define EFI_ACPI_6_2_NFIT_GUID_VOLATILE_MEMORY_REGION { 0x7305944F, 0xFDDA, 0x44E3, { 0xB1, 0x6C, 0x3F, 0x22, 0xD2, 0x52, 0xE5, 0xD0 }} +#define EFI_ACPI_6_2_NFIT_GUID_BYTE_ADDRESSABLE_PERSISTENT_MEMORY_REGION { 0x66F0D379, 0xB4F3, 0x4074, { 0xAC, 0x43, 0x0D, 0x33, 0x18, 0xB7, 0x8C, 0xDB }} +#define EFI_ACPI_6_2_NFIT_GUID_NVDIMM_CONTROL_REGION { 0x92F701F6, 0x13B4, 0x405D, { 0x91, 0x0B, 0x29, 0x93, 0x67, 0xE8, 0x23, 0x4C }} +#define EFI_ACPI_6_2_NFIT_GUID_NVDIMM_BLOCK_DATA_WINDOW_REGION { 0x91AF0530, 0x5D86, 0x470E, { 0xA6, 0xB0, 0x0A, 0x2D, 0xB9, 0x40, 0x82, 0x49 }} +#define EFI_ACPI_6_2_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_VOLATILE { 0x77AB535A, 0x45FC, 0x624B, { 0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }} +#define EFI_ACPI_6_2_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_VOLATILE { 0x3D5ABD30, 0x4175, 0x87CE, { 0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }} +#define EFI_ACPI_6_2_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_PERSISTENT { 0x5CEA02C9, 0x4D07, 0x69D3, { 0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }} +#define EFI_ACPI_6_2_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_PERSISTENT { 0x08018188, 0x42CD, 0xBB48, { 0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }} +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 SPARangeStructureIndex; + UINT16 Flags; + UINT32 Reserved_8; + UINT32 ProximityDomain; + GUID AddressRangeTypeGUID; + UINT64 SystemPhysicalAddressRangeBase; + UINT64 SystemPhysicalAddressRangeLength; + UINT64 AddressRangeMemoryMappingAttribute; +} EFI_ACPI_6_2_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE; + +// +// Definition for Memory Device to System Physical Address Range Mapping Structure +// +typedef struct { + UINT32 DIMMNumber:4; + UINT32 MemoryChannelNumber:4; + UINT32 MemoryControllerID:4; + UINT32 SocketID:4; + UINT32 NodeControllerID:12; + UINT32 Reserved_28:4; +} EFI_ACPI_6_2_NFIT_DEVICE_HANDLE; + +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_PREVIOUS_SAVE_FAIL BIT0 +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_LAST_RESTORE_FAIL BIT1 +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_PLATFORM_FLUSH_FAIL BIT2 +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_NOT_ARMED_PRIOR_TO_OSPM_HAND_OFF BIT3 +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_SMART_HEALTH_EVENTS_PRIOR_OSPM_HAND_OFF BIT4 +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_FIRMWARE_ENABLED_TO_NOTIFY_OSPM_ON_SMART_HEALTH_EVENTS BIT5 +#define EFI_ACPI_6_2_NFIT_MEMORY_DEVICE_STATE_FLAGS_FIRMWARE_NOT_MAP_NVDIMM_TO_SPA BIT6 +typedef struct { + UINT16 Type; + UINT16 Length; + EFI_ACPI_6_2_NFIT_DEVICE_HANDLE NFITDeviceHandle; + UINT16 NVDIMMPhysicalID; + UINT16 NVDIMMRegionID; + UINT16 SPARangeStructureIndex ; + UINT16 NVDIMMControlRegionStructureIndex; + UINT64 NVDIMMRegionSize; + UINT64 RegionOffset; + UINT64 NVDIMMPhysicalAddressRegionBase; + UINT16 InterleaveStructureIndex; + UINT16 InterleaveWays; + UINT16 NVDIMMStateFlags; + UINT16 Reserved_46; +} EFI_ACPI_6_2_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE; + +// +// Definition for Interleave Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 InterleaveStructureIndex; + UINT16 Reserved_6; + UINT32 NumberOfLines; + UINT32 LineSize; +//UINT32 LineOffset[NumberOfLines]; +} EFI_ACPI_6_2_NFIT_INTERLEAVE_STRUCTURE; + +// +// Definition for SMBIOS Management Information Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT32 Reserved_4; +//UINT8 Data[]; +} EFI_ACPI_6_2_NFIT_SMBIOS_MANAGEMENT_INFORMATION_STRUCTURE; + +// +// Definition for NVDIMM Control Region Structure +// +#define EFI_ACPI_6_2_NFIT_NVDIMM_CONTROL_REGION_VALID_FIELDS_MANUFACTURING BIT0 + +#define EFI_ACPI_6_2_NFIT_NVDIMM_CONTROL_REGION_FLAGS_BLOCK_DATA_WINDOWS_BUFFERED BIT0 +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 NVDIMMControlRegionStructureIndex; + UINT16 VendorID; + UINT16 DeviceID; + UINT16 RevisionID; + UINT16 SubsystemVendorID; + UINT16 SubsystemDeviceID; + UINT16 SubsystemRevisionID; + UINT8 ValidFields; + UINT8 ManufacturingLocation; + UINT16 ManufacturingDate; + UINT8 Reserved_22[2]; + UINT32 SerialNumber; + UINT16 RegionFormatInterfaceCode; + UINT16 NumberOfBlockControlWindows; + UINT64 SizeOfBlockControlWindow; + UINT64 CommandRegisterOffsetInBlockControlWindow; + UINT64 SizeOfCommandRegisterInBlockControlWindows; + UINT64 StatusRegisterOffsetInBlockControlWindow; + UINT64 SizeOfStatusRegisterInBlockControlWindows; + UINT16 NVDIMMControlRegionFlag; + UINT8 Reserved_74[6]; +} EFI_ACPI_6_2_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE; + +// +// Definition for NVDIMM Block Data Window Region Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + UINT16 NVDIMMControlRegionStructureIndex; + UINT16 NumberOfBlockDataWindows; + UINT64 BlockDataWindowStartOffset; + UINT64 SizeOfBlockDataWindow; + UINT64 BlockAccessibleMemoryCapacity; + UINT64 BeginningAddressOfFirstBlockInBlockAccessibleMemory; +} EFI_ACPI_6_2_NFIT_NVDIMM_BLOCK_DATA_WINDOW_REGION_STRUCTURE; + +// +// Definition for Flush Hint Address Structure +// +typedef struct { + UINT16 Type; + UINT16 Length; + EFI_ACPI_6_2_NFIT_DEVICE_HANDLE NFITDeviceHandle; + UINT16 NumberOfFlushHintAddresses; + UINT8 Reserved_10[6]; +//UINT64 FlushHintAddress[NumberOfFlushHintAddresses]; +} EFI_ACPI_6_2_NFIT_FLUSH_HINT_ADDRESS_STRUCTURE; + +/// +/// Secure DEVices Table (SDEV) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_6_2_SECURE_DEVICES_TABLE_HEADER; + +/// +/// SDEV Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_SECURE_DEVICES_TABLE_REVISION 0x01 + +/// +/// Secure Devcice types +/// +#define EFI_ACPI_6_2_SDEV_TYPE_PCIE_ENDPOINT_DEVICE 0x01 +#define EFI_ACPI_6_2_SDEV_TYPE_ACPI_NAMESPACE_DEVICE 0x00 + +/// +/// Secure Devcice flags +/// +#define EFI_ACPI_6_2_SDEV_FLAG_ALLOW_HANDOFF BIT0 + +/// +/// SDEV Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Flags; + UINT16 Length; +} EFI_ACPI_6_2_SDEV_STRUCTURE_HEADER; + +/// +/// PCIe Endpoint Device based Secure Device Structure +/// +typedef struct { + UINT8 Type; + UINT8 Flags; + UINT16 Length; + UINT16 PciSegmentNumber; + UINT16 StartBusNumber; + UINT16 PciPathOffset; + UINT16 PciPathLength; + UINT16 VendorSpecificDataOffset; + UINT16 VendorSpecificDataLength; +} EFI_ACPI_6_2_SDEV_STRUCTURE_PCIE_ENDPOINT_DEVICE; + +/// +/// ACPI_NAMESPACE_DEVICE based Secure Device Structure +/// +typedef struct { + UINT8 Type; + UINT8 Flags; + UINT16 Length; + UINT16 DeviceIdentifierOffset; + UINT16 DeviceIdentifierLength; + UINT16 VendorSpecificDataOffset; + UINT16 VendorSpecificDataLength; +} EFI_ACPI_6_2_SDEV_STRUCTURE_ACPI_NAMESPACE_DEVICE; + +/// +/// Boot Error Record Table (BERT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 BootErrorRegionLength; + UINT64 BootErrorRegion; +} EFI_ACPI_6_2_BOOT_ERROR_RECORD_TABLE_HEADER; + +/// +/// BERT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_BOOT_ERROR_RECORD_TABLE_REVISION 0x01 + +/// +/// Boot Error Region Block Status Definition +/// +typedef struct { + UINT32 UncorrectableErrorValid:1; + UINT32 CorrectableErrorValid:1; + UINT32 MultipleUncorrectableErrors:1; + UINT32 MultipleCorrectableErrors:1; + UINT32 ErrorDataEntryCount:10; + UINT32 Reserved:18; +} EFI_ACPI_6_2_ERROR_BLOCK_STATUS; + +/// +/// Boot Error Region Definition +/// +typedef struct { + EFI_ACPI_6_2_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_6_2_BOOT_ERROR_REGION_STRUCTURE; + +// +// Boot Error Severity types +// +#define EFI_ACPI_6_2_ERROR_SEVERITY_CORRECTABLE 0x00 +#define EFI_ACPI_6_2_ERROR_SEVERITY_FATAL 0x01 +#define EFI_ACPI_6_2_ERROR_SEVERITY_CORRECTED 0x02 +#define EFI_ACPI_6_2_ERROR_SEVERITY_NONE 0x03 + +/// +/// Generic Error Data Entry Definition +/// +typedef struct { + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; + UINT8 Timestamp[8]; +} EFI_ACPI_6_2_GENERIC_ERROR_DATA_ENTRY_STRUCTURE; + +/// +/// Generic Error Data Entry Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_GENERIC_ERROR_DATA_ENTRY_REVISION 0x0300 + +/// +/// HEST - Hardware Error Source Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ErrorSourceCount; +} EFI_ACPI_6_2_HARDWARE_ERROR_SOURCE_TABLE_HEADER; + +/// +/// HEST Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_HARDWARE_ERROR_SOURCE_TABLE_REVISION 0x01 + +// +// Error Source structure types. +// +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION 0x00 +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK 0x01 +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_NMI_ERROR 0x02 +#define EFI_ACPI_6_2_PCI_EXPRESS_ROOT_PORT_AER 0x06 +#define EFI_ACPI_6_2_PCI_EXPRESS_DEVICE_AER 0x07 +#define EFI_ACPI_6_2_PCI_EXPRESS_BRIDGE_AER 0x08 +#define EFI_ACPI_6_2_GENERIC_HARDWARE_ERROR 0x09 +#define EFI_ACPI_6_2_GENERIC_HARDWARE_ERROR_VERSION_2 0x0A +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_DEFERRED_MACHINE_CHECK 0x0B + +// +// Error Source structure flags. +// +#define EFI_ACPI_6_2_ERROR_SOURCE_FLAG_FIRMWARE_FIRST (1 << 0) +#define EFI_ACPI_6_2_ERROR_SOURCE_FLAG_GLOBAL (1 << 1) +#define EFI_ACPI_6_2_ERROR_SOURCE_FLAG_GHES_ASSIST (1 << 2) + +/// +/// IA-32 Architecture Machine Check Exception Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT64 GlobalCapabilityInitData; + UINT64 GlobalControlInitData; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[7]; +} EFI_ACPI_6_2_IA32_ARCHITECTURE_MACHINE_CHECK_EXCEPTION_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure Definition +/// +typedef struct { + UINT8 BankNumber; + UINT8 ClearStatusOnInitialization; + UINT8 StatusDataFormat; + UINT8 Reserved0; + UINT32 ControlRegisterMsrAddress; + UINT64 ControlInitData; + UINT32 StatusRegisterMsrAddress; + UINT32 AddressRegisterMsrAddress; + UINT32 MiscRegisterMsrAddress; +} EFI_ACPI_6_2_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_BANK_STRUCTURE; + +/// +/// IA-32 Architecture Machine Check Bank Structure MCA data format +/// +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_IA32 0x00 +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_INTEL64 0x01 +#define EFI_ACPI_6_2_IA32_ARCHITECTURE_MACHINE_CHECK_ERROR_DATA_FORMAT_AMD64 0x02 + +// +// Hardware Error Notification types. All other values are reserved +// +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_POLLED 0x00 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_EXTERNAL_INTERRUPT 0x01 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_LOCAL_INTERRUPT 0x02 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_SCI 0x03 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_NMI 0x04 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_CMCI 0x05 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_MCE 0x06 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_GPIO_SIGNAL 0x07 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_ARMV8_SEA 0x08 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_ARMV8_SEI 0x09 +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_GSIV 0x0A +#define EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCEPTION 0x0B + +/// +/// Hardware Error Notification Configuration Write Enable Structure Definition +/// +typedef struct { + UINT16 Type:1; + UINT16 PollInterval:1; + UINT16 SwitchToPollingThresholdValue:1; + UINT16 SwitchToPollingThresholdWindow:1; + UINT16 ErrorThresholdValue:1; + UINT16 ErrorThresholdWindow:1; + UINT16 Reserved:10; +} EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE; + +/// +/// Hardware Error Notification Structure Definition +/// +typedef struct { + UINT8 Type; + UINT8 Length; + EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_CONFIGURATION_WRITE_ENABLE_STRUCTURE ConfigurationWriteEnable; + UINT32 PollInterval; + UINT32 Vector; + UINT32 SwitchToPollingThresholdValue; + UINT32 SwitchToPollingThresholdWindow; + UINT32 ErrorThresholdValue; + UINT32 ErrorThresholdWindow; +} EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_STRUCTURE; + +/// +/// IA-32 Architecture Corrected Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_6_2_IA32_ARCHITECTURE_CORRECTED_MACHINE_CHECK_STRUCTURE; + +/// +/// IA-32 Architecture NMI Error Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; +} EFI_ACPI_6_2_IA32_ARCHITECTURE_NMI_ERROR_STRUCTURE; + +/// +/// PCI Express Root Port AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 RootErrorCommand; +} EFI_ACPI_6_2_PCI_EXPRESS_ROOT_PORT_AER_STRUCTURE; + +/// +/// PCI Express Device AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_6_2_PCI_EXPRESS_DEVICE_AER_STRUCTURE; + +/// +/// PCI Express Bridge AER Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 Bus; + UINT16 Device; + UINT16 Function; + UINT16 DeviceControl; + UINT8 Reserved1[2]; + UINT32 UncorrectableErrorMask; + UINT32 UncorrectableErrorSeverity; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 SecondaryUncorrectableErrorMask; + UINT32 SecondaryUncorrectableErrorSeverity; + UINT32 SecondaryAdvancedErrorCapabilitiesAndControl; +} EFI_ACPI_6_2_PCI_EXPRESS_BRIDGE_AER_STRUCTURE; + +/// +/// Generic Hardware Error Source Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; +} EFI_ACPI_6_2_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE; + +/// +/// Generic Hardware Error Source Version 2 Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT16 RelatedSourceId; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + UINT32 MaxRawDataLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE ErrorStatusAddress; + EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT32 ErrorStatusBlockLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE ReadAckRegister; + UINT64 ReadAckPreserve; + UINT64 ReadAckWrite; +} EFI_ACPI_6_2_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE; + +/// +/// Generic Error Status Definition +/// +typedef struct { + EFI_ACPI_6_2_ERROR_BLOCK_STATUS BlockStatus; + UINT32 RawDataOffset; + UINT32 RawDataLength; + UINT32 DataLength; + UINT32 ErrorSeverity; +} EFI_ACPI_6_2_GENERIC_ERROR_STATUS_STRUCTURE; + +/// +/// IA-32 Architecture Deferred Machine Check Structure Definition +/// +typedef struct { + UINT16 Type; + UINT16 SourceId; + UINT8 Reserved0[2]; + UINT8 Flags; + UINT8 Enabled; + UINT32 NumberOfRecordsToPreAllocate; + UINT32 MaxSectionsPerRecord; + EFI_ACPI_6_2_HARDWARE_ERROR_NOTIFICATION_STRUCTURE NotificationStructure; + UINT8 NumberOfHardwareBanks; + UINT8 Reserved1[3]; +} EFI_ACPI_6_2_IA32_ARCHITECTURE_DEFERRED_MACHINE_CHECK_STRUCTURE;; + +/// +/// HMAT - Heterogeneous Memory Attribute Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 Reserved[4]; +} EFI_ACPI_6_2_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_HEADER; + +/// +/// HMAT Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_REVISION 0x01 + +/// +/// HMAT types +/// +#define EFI_ACPI_6_2_HMAT_TYPE_MEMORY_SUBSYSTEM_ADDRESS_RANGE 0x00 +#define EFI_ACPI_6_2_HMAT_TYPE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO 0x01 +#define EFI_ACPI_6_2_HMAT_TYPE_MEMORY_SIDE_CACHE_INFO 0x02 + +/// +/// HMAT Structure Header +/// +typedef struct { + UINT16 Type; + UINT8 Reserved[2]; + UINT32 Length; +} EFI_ACPI_6_2_HMAT_STRUCTURE_HEADER; + +/// +/// Memory Subsystem Address Range Structure flags +/// +typedef struct { + UINT16 ProcessorProximityDomainValid:1; + UINT16 MemoryProximityDomainValid:1; + UINT16 ReservationHint:1; + UINT16 Reserved:13; +} EFI_ACPI_6_2_HMAT_STRUCTURE_MEMORY_SUBSYSTEM_ADDRESS_RANGE_FLAGS; + +/// +/// Memory Subsystem Address Range Structure +/// +typedef struct { + UINT16 Type; + UINT8 Reserved[2]; + UINT32 Length; + EFI_ACPI_6_2_HMAT_STRUCTURE_MEMORY_SUBSYSTEM_ADDRESS_RANGE_FLAGS Flags; + UINT8 Reserved1[2]; + UINT32 ProcessorProximityDomain; + UINT32 MemoryProximityDomain; + UINT8 Reserved2[4]; + UINT64 SystemPhysicalAddressRangeBase; + UINT64 SystemPhysicalAddressRangeLength; +} EFI_ACPI_6_2_HMAT_STRUCTURE_MEMORY_SUBSYSTEM_ADDRESS_RANGE; + +/// +/// System Locality Latency and Bandwidth Information Structure flags +/// +typedef struct { + UINT8 MemoryHierarchy:5; + UINT8 Reserved:3; +} EFI_ACPI_6_2_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO_FLAGS; + +/// +/// System Locality Latency and Bandwidth Information Structure +/// +typedef struct { + UINT16 Type; + UINT8 Reserved[2]; + UINT32 Length; + EFI_ACPI_6_2_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO_FLAGS Flags; + UINT8 DataType; + UINT8 Reserved1[2]; + UINT32 NumberOfInitiatorProximityDomains; + UINT32 NumberOfTargetProximityDomains; + UINT8 Reserved2[4]; + UINT64 EntryBaseUnit; +} EFI_ACPI_6_2_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO; + +/// +/// Memory Side Cache Information Structure cache attributes +/// +typedef struct { + UINT32 TotalCacheLevels:4; + UINT32 CacheLevel:4; + UINT32 CacheAssociativity:4; + UINT32 WritePolicy:4; + UINT32 CacheLineSize:16; +} EFI_ACPI_6_2_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES; + +/// +/// Memory Side Cache Information Structure +/// +typedef struct { + UINT16 Type; + UINT8 Reserved[2]; + UINT32 Length; + UINT32 MemoryProximityDomain; + UINT8 Reserved1[4]; + UINT64 MemorySideCacheSize; + EFI_ACPI_6_2_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES CacheAttributes; + UINT8 Reserved2[2]; + UINT16 NumberOfSmbiosHandles; +} EFI_ACPI_6_2_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO; + +/// +/// ERST - Error Record Serialization Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 SerializationHeaderSize; + UINT8 Reserved0[4]; + UINT32 InstructionEntryCount; +} EFI_ACPI_6_2_ERROR_RECORD_SERIALIZATION_TABLE_HEADER; + +/// +/// ERST Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_ERROR_RECORD_SERIALIZATION_TABLE_REVISION 0x01 + +/// +/// ERST Serialization Actions +/// +#define EFI_ACPI_6_2_ERST_BEGIN_WRITE_OPERATION 0x00 +#define EFI_ACPI_6_2_ERST_BEGIN_READ_OPERATION 0x01 +#define EFI_ACPI_6_2_ERST_BEGIN_CLEAR_OPERATION 0x02 +#define EFI_ACPI_6_2_ERST_END_OPERATION 0x03 +#define EFI_ACPI_6_2_ERST_SET_RECORD_OFFSET 0x04 +#define EFI_ACPI_6_2_ERST_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_6_2_ERST_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_6_2_ERST_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_6_2_ERST_GET_RECORD_IDENTIFIER 0x08 +#define EFI_ACPI_6_2_ERST_SET_RECORD_IDENTIFIER 0x09 +#define EFI_ACPI_6_2_ERST_GET_RECORD_COUNT 0x0A +#define EFI_ACPI_6_2_ERST_BEGIN_DUMMY_WRITE_OPERATION 0x0B +#define EFI_ACPI_6_2_ERST_GET_ERROR_LOG_ADDRESS_RANGE 0x0D +#define EFI_ACPI_6_2_ERST_GET_ERROR_LOG_ADDRESS_RANGE_LENGTH 0x0E +#define EFI_ACPI_6_2_ERST_GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES 0x0F +#define EFI_ACPI_6_2_ERST_GET_EXECUTE_OPERATION_TIMINGS 0x10 + +/// +/// ERST Action Command Status +/// +#define EFI_ACPI_6_2_ERST_STATUS_SUCCESS 0x00 +#define EFI_ACPI_6_2_ERST_STATUS_NOT_ENOUGH_SPACE 0x01 +#define EFI_ACPI_6_2_ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x02 +#define EFI_ACPI_6_2_ERST_STATUS_FAILED 0x03 +#define EFI_ACPI_6_2_ERST_STATUS_RECORD_STORE_EMPTY 0x04 +#define EFI_ACPI_6_2_ERST_STATUS_RECORD_NOT_FOUND 0x05 + +/// +/// ERST Serialization Instructions +/// +#define EFI_ACPI_6_2_ERST_READ_REGISTER 0x00 +#define EFI_ACPI_6_2_ERST_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_6_2_ERST_WRITE_REGISTER 0x02 +#define EFI_ACPI_6_2_ERST_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_6_2_ERST_NOOP 0x04 +#define EFI_ACPI_6_2_ERST_LOAD_VAR1 0x05 +#define EFI_ACPI_6_2_ERST_LOAD_VAR2 0x06 +#define EFI_ACPI_6_2_ERST_STORE_VAR1 0x07 +#define EFI_ACPI_6_2_ERST_ADD 0x08 +#define EFI_ACPI_6_2_ERST_SUBTRACT 0x09 +#define EFI_ACPI_6_2_ERST_ADD_VALUE 0x0A +#define EFI_ACPI_6_2_ERST_SUBTRACT_VALUE 0x0B +#define EFI_ACPI_6_2_ERST_STALL 0x0C +#define EFI_ACPI_6_2_ERST_STALL_WHILE_TRUE 0x0D +#define EFI_ACPI_6_2_ERST_SKIP_NEXT_INSTRUCTION_IF_TRUE 0x0E +#define EFI_ACPI_6_2_ERST_GOTO 0x0F +#define EFI_ACPI_6_2_ERST_SET_SRC_ADDRESS_BASE 0x10 +#define EFI_ACPI_6_2_ERST_SET_DST_ADDRESS_BASE 0x11 +#define EFI_ACPI_6_2_ERST_MOVE_DATA 0x12 + +/// +/// ERST Instruction Flags +/// +#define EFI_ACPI_6_2_ERST_PRESERVE_REGISTER 0x01 + +/// +/// ERST Serialization Instruction Entry +/// +typedef struct { + UINT8 SerializationAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_6_2_ERST_SERIALIZATION_INSTRUCTION_ENTRY; + +/// +/// EINJ - Error Injection Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 InjectionHeaderSize; + UINT8 InjectionFlags; + UINT8 Reserved0[3]; + UINT32 InjectionEntryCount; +} EFI_ACPI_6_2_ERROR_INJECTION_TABLE_HEADER; + +/// +/// EINJ Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_ERROR_INJECTION_TABLE_REVISION 0x01 + +/// +/// EINJ Error Injection Actions +/// +#define EFI_ACPI_6_2_EINJ_BEGIN_INJECTION_OPERATION 0x00 +#define EFI_ACPI_6_2_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE 0x01 +#define EFI_ACPI_6_2_EINJ_SET_ERROR_TYPE 0x02 +#define EFI_ACPI_6_2_EINJ_GET_ERROR_TYPE 0x03 +#define EFI_ACPI_6_2_EINJ_END_OPERATION 0x04 +#define EFI_ACPI_6_2_EINJ_EXECUTE_OPERATION 0x05 +#define EFI_ACPI_6_2_EINJ_CHECK_BUSY_STATUS 0x06 +#define EFI_ACPI_6_2_EINJ_GET_COMMAND_STATUS 0x07 +#define EFI_ACPI_6_2_EINJ_TRIGGER_ERROR 0xFF + +/// +/// EINJ Action Command Status +/// +#define EFI_ACPI_6_2_EINJ_STATUS_SUCCESS 0x00 +#define EFI_ACPI_6_2_EINJ_STATUS_UNKNOWN_FAILURE 0x01 +#define EFI_ACPI_6_2_EINJ_STATUS_INVALID_ACCESS 0x02 + +/// +/// EINJ Error Type Definition +/// +#define EFI_ACPI_6_2_EINJ_ERROR_PROCESSOR_CORRECTABLE (1 << 0) +#define EFI_ACPI_6_2_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_NONFATAL (1 << 1) +#define EFI_ACPI_6_2_EINJ_ERROR_PROCESSOR_UNCORRECTABLE_FATAL (1 << 2) +#define EFI_ACPI_6_2_EINJ_ERROR_MEMORY_CORRECTABLE (1 << 3) +#define EFI_ACPI_6_2_EINJ_ERROR_MEMORY_UNCORRECTABLE_NONFATAL (1 << 4) +#define EFI_ACPI_6_2_EINJ_ERROR_MEMORY_UNCORRECTABLE_FATAL (1 << 5) +#define EFI_ACPI_6_2_EINJ_ERROR_PCI_EXPRESS_CORRECTABLE (1 << 6) +#define EFI_ACPI_6_2_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_NONFATAL (1 << 7) +#define EFI_ACPI_6_2_EINJ_ERROR_PCI_EXPRESS_UNCORRECTABLE_FATAL (1 << 8) +#define EFI_ACPI_6_2_EINJ_ERROR_PLATFORM_CORRECTABLE (1 << 9) +#define EFI_ACPI_6_2_EINJ_ERROR_PLATFORM_UNCORRECTABLE_NONFATAL (1 << 10) +#define EFI_ACPI_6_2_EINJ_ERROR_PLATFORM_UNCORRECTABLE_FATAL (1 << 11) + +/// +/// EINJ Injection Instructions +/// +#define EFI_ACPI_6_2_EINJ_READ_REGISTER 0x00 +#define EFI_ACPI_6_2_EINJ_READ_REGISTER_VALUE 0x01 +#define EFI_ACPI_6_2_EINJ_WRITE_REGISTER 0x02 +#define EFI_ACPI_6_2_EINJ_WRITE_REGISTER_VALUE 0x03 +#define EFI_ACPI_6_2_EINJ_NOOP 0x04 + +/// +/// EINJ Instruction Flags +/// +#define EFI_ACPI_6_2_EINJ_PRESERVE_REGISTER 0x01 + +/// +/// EINJ Injection Instruction Entry +/// +typedef struct { + UINT8 InjectionAction; + UINT8 Instruction; + UINT8 Flags; + UINT8 Reserved0; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT64 Value; + UINT64 Mask; +} EFI_ACPI_6_2_EINJ_INJECTION_INSTRUCTION_ENTRY; + +/// +/// EINJ Trigger Action Table +/// +typedef struct { + UINT32 HeaderSize; + UINT32 Revision; + UINT32 TableSize; + UINT32 EntryCount; +} EFI_ACPI_6_2_EINJ_TRIGGER_ACTION_TABLE; + +/// +/// Platform Communications Channel Table (PCCT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Flags; + UINT64 Reserved; +} EFI_ACPI_6_2_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER; + +/// +/// PCCT Version (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION 0x02 + +/// +/// PCCT Global Flags +/// +#define EFI_ACPI_6_2_PCCT_FLAGS_PLATFORM_INTERRUPT BIT0 + +// +// PCCT Subspace type +// +#define EFI_ACPI_6_2_PCCT_SUBSPACE_TYPE_GENERIC 0x00 +#define EFI_ACPI_6_2_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS 0x01 +#define EFI_ACPI_6_2_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS 0x02 +#define EFI_ACPI_6_2_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC 0x03 +#define EFI_ACPI_6_2_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC 0x04 + +/// +/// PCC Subspace Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Length; +} EFI_ACPI_6_2_PCCT_SUBSPACE_HEADER; + +/// +/// Generic Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[6]; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_6_2_PCCT_SUBSPACE_GENERIC; + +/// +/// Generic Communications Channel Shared Memory Region +/// + +typedef struct { + UINT8 Command; + UINT8 Reserved:7; + UINT8 NotifyOnCompletion:1; +} EFI_ACPI_6_2_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND; + +typedef struct { + UINT8 CommandComplete:1; + UINT8 PlatformInterrupt:1; + UINT8 Error:1; + UINT8 PlatformNotification:1; + UINT8 Reserved:4; + UINT8 Reserved1; +} EFI_ACPI_6_2_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS; + +typedef struct { + UINT32 Signature; + EFI_ACPI_6_2_PCCT_GENERIC_SHARED_MEMORY_REGION_COMMAND Command; + EFI_ACPI_6_2_PCCT_GENERIC_SHARED_MEMORY_REGION_STATUS Status; +} EFI_ACPI_6_2_PCCT_GENERIC_SHARED_MEMORY_REGION_HEADER; + +#define EFI_ACPI_6_2_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_POLARITY BIT0 +#define EFI_ACPI_6_2_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE BIT1 + +/// +/// Type 1 HW-Reduced Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 PlatformInterrupt; + UINT8 PlatformInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; +} EFI_ACPI_6_2_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS; + +/// +/// Type 2 HW-Reduced Communications Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 PlatformInterrupt; + UINT8 PlatformInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 AddressLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT16 MinimumRequestTurnaroundTime; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE PlatformInterruptAckRegister; + UINT64 PlatformInterruptAckPreserve; + UINT64 PlatformInterruptAckWrite; +} EFI_ACPI_6_2_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS; + +/// +/// Type 3 Extended PCC Subspace Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 PlatformInterrupt; + UINT8 PlatformInterruptFlags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT32 AddressLength; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + UINT32 NominalLatency; + UINT32 MaximumPeriodicAccessRate; + UINT32 MinimumRequestTurnaroundTime; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE PlatformInterruptAckRegister; + UINT64 PlatformInterruptAckPreserve; + UINT64 PlatformInterruptAckSet; + UINT8 Reserved1[8]; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE CommandCompleteCheckRegister; + UINT64 CommandCompleteCheckMask; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE CommandCompleteUpdateRegister; + UINT64 CommandCompleteUpdatePreserve; + UINT64 CommandCompleteUpdateSet; + EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE ErrorStatusRegister; + UINT64 ErrorStatusMask; +} EFI_ACPI_6_2_PCCT_SUBSPACE_3_EXTENDED_PCC; + +/// +/// Type 4 Extended PCC Subspace Structure +/// +typedef EFI_ACPI_6_2_PCCT_SUBSPACE_3_EXTENDED_PCC EFI_ACPI_6_2_PCCT_SUBSPACE_4_EXTENDED_PCC; + +#define EFI_ACPI_6_2_PCCT_MASTER_SLAVE_COMMUNICATIONS_CHANNEL_FLAGS_NOTIFY_ON_COMPLETION BIT0 + +typedef struct { + UINT32 Signature; + UINT32 Flags; + UINT32 Length; + UINT32 Command; +} EFI_ACPI_6_2_PCCT_EXTENDED_PCC_SHARED_MEMORY_REGION_HEADER; + +/// +/// Platform Debug Trigger Table (PDTT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 TriggerCount; + UINT8 Reserved[3]; + UINT32 TriggerIdentifierArrayOffset; +} EFI_ACPI_6_2_PLATFORM_DEBUG_TRIGGER_TABLE_HEADER; + +/// +/// PDTT Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_PLATFORM_DEBUG_TRIGGER_TABLE_REVISION 0x00 + +/// +/// PDTT Platform Communication Channel Identifier Structure +/// +typedef struct { + UINT16 SubChannelIdentifer:8; + UINT16 Runtime:1; + UINT16 WaitForCompletion:1; + UINT16 Reserved:6; +} EFI_ACPI_6_2_PDTT_PCC_IDENTIFIER; + +/// +/// PCC Commands Codes used by Platform Debug Trigger Table +/// +#define EFI_ACPI_6_2_PDTT_PCC_COMMAND_DOORBELL_ONLY 0x00 +#define EFI_ACPI_6_2_PDTT_PCC_COMMAND_VENDOR_SPECIFIC 0x01 + +/// +/// PPTT Platform Communication Channel +/// +typedef EFI_ACPI_6_2_PCCT_GENERIC_SHARED_MEMORY_REGION_HEADER EFI_ACPI_6_2_PDTT_PCC; + +/// +/// Processor Properties Topology Table (PPTT) +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; +} EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER; + +/// +/// PPTT Revision (as defined in ACPI 6.2 spec.) +/// +#define EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION 0x01 + +/// +/// PPTT types +/// +#define EFI_ACPI_6_2_PPTT_TYPE_PROCESSOR 0x00 +#define EFI_ACPI_6_2_PPTT_TYPE_CACHE 0x01 +#define EFI_ACPI_6_2_PPTT_TYPE_ID 0x02 + +/// +/// PPTT Structure Header +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; +} EFI_ACPI_6_2_PPTT_STRUCTURE_HEADER; + +/// +/// For PPTT struct processor flags +/// +#define EFI_ACPI_6_2_PPTT_PROCESSOR_ID_INVALID 0x0 +#define EFI_ACPI_6_2_PPTT_PROCESSOR_ID_VALID 0x1 + +/// +/// Processor hierarchy node structure flags +/// +typedef struct { + UINT32 PhysicalPackage:1; + UINT32 AcpiProcessorIdValid:1; + UINT32 Reserved:30; +} EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR_FLAGS; + +/// +/// Processor hierarchy node structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR_FLAGS Flags; + UINT32 Parent; + UINT32 AcpiProcessorId; + UINT32 NumberOfPrivateResources; +} EFI_ACPI_6_2_PPTT_STRUCTURE_PROCESSOR; + +/// +/// Cache Type Structure flags +/// +typedef struct { + UINT32 SizePropertyValid:1; + UINT32 NumberOfSetsValid:1; + UINT32 AssociativityValid:1; + UINT32 AllocationTypeValid:1; + UINT32 CacheTypeValid:1; + UINT32 WritePolicyValid:1; + UINT32 LineSizeValid:1; + UINT32 Reserved:25; +} EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_FLAGS; + +/// +/// For cache attributes +/// +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_ALLOCATION_READ 0x0 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_ALLOCATION_WRITE 0x1 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_ALLOCATION_READ_WRITE 0x2 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_CACHE_TYPE_DATA 0x0 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_CACHE_TYPE_INSTRUCTION 0x1 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_CACHE_TYPE_UNIFIED 0x2 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_WRITE_POLICY_WRITE_BACK 0x0 +#define EFI_ACPI_6_2_CACHE_ATTRIBUTES_WRITE_POLICY_WRITE_THROUGH 0x1 + +/// +/// Cache Type Structure cache attributes +/// +typedef struct { + UINT8 AllocationType:2; + UINT8 CacheType:2; + UINT8 WritePolicy:1; + UINT8 Reserved:3; +} EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_ATTRIBUTES; + +/// +/// Cache Type Structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_FLAGS Flags; + UINT32 NextLevelOfCache; + UINT32 Size; + UINT32 NumberOfSets; + UINT8 Associativity; + EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE_ATTRIBUTES Attributes; + UINT16 LineSize; +} EFI_ACPI_6_2_PPTT_STRUCTURE_CACHE; + +/// +/// ID structure +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Reserved[2]; + UINT32 VendorId; + UINT64 Level1Id; + UINT64 Level2Id; + UINT16 MajorRev; + UINT16 MinorRev; + UINT16 SpinRev; +} EFI_ACPI_6_2_PPTT_STRUCTURE_ID; + +// +// Known table signatures +// + +/// +/// "RSD PTR " Root System Description Pointer +/// +#define EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ') + +/// +/// "APIC" Multiple APIC Description Table +/// +#define EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C') + +/// +/// "BERT" Boot Error Record Table +/// +#define EFI_ACPI_6_2_BOOT_ERROR_RECORD_TABLE_SIGNATURE SIGNATURE_32('B', 'E', 'R', 'T') + +/// +/// "BGRT" Boot Graphics Resource Table +/// +#define EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('B', 'G', 'R', 'T') + +/// +/// "CPEP" Corrected Platform Error Polling Table +/// +#define EFI_ACPI_6_2_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE SIGNATURE_32('C', 'P', 'E', 'P') + +/// +/// "DSDT" Differentiated System Description Table +/// +#define EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T') + +/// +/// "ECDT" Embedded Controller Boot Resources Table +/// +#define EFI_ACPI_6_2_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE SIGNATURE_32('E', 'C', 'D', 'T') + +/// +/// "EINJ" Error Injection Table +/// +#define EFI_ACPI_6_2_ERROR_INJECTION_TABLE_SIGNATURE SIGNATURE_32('E', 'I', 'N', 'J') + +/// +/// "ERST" Error Record Serialization Table +/// +#define EFI_ACPI_6_2_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE SIGNATURE_32('E', 'R', 'S', 'T') + +/// +/// "FACP" Fixed ACPI Description Table +/// +#define EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P') + +/// +/// "FACS" Firmware ACPI Control Structure +/// +#define EFI_ACPI_6_2_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S') + +/// +/// "FPDT" Firmware Performance Data Table +/// +#define EFI_ACPI_6_2_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE SIGNATURE_32('F', 'P', 'D', 'T') + +/// +/// "GTDT" Generic Timer Description Table +/// +#define EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('G', 'T', 'D', 'T') + +/// +/// "HEST" Hardware Error Source Table +/// +#define EFI_ACPI_6_2_HARDWARE_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('H', 'E', 'S', 'T') + +/// +/// "HMAT" Heterogeneous Memory Attribute Table +/// +#define EFI_ACPI_6_2_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE SIGNATURE_32('H', 'M', 'A', 'T') + +/// +/// "MPST" Memory Power State Table +/// +#define EFI_ACPI_6_2_MEMORY_POWER_STATE_TABLE_SIGNATURE SIGNATURE_32('M', 'P', 'S', 'T') + +/// +/// "MSCT" Maximum System Characteristics Table +/// +#define EFI_ACPI_6_2_MAXIMUM_SYSTEM_CHARACTERISTICS_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'C', 'T') + +/// +/// "NFIT" NVDIMM Firmware Interface Table +/// +#define EFI_ACPI_6_2_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('N', 'F', 'I', 'T') + +/// +/// "PDTT" Platform Debug Trigger Table +/// +#define EFI_ACPI_6_2_PLATFORM_DEBUG_TRIGGER_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('P', 'D', 'T', 'T') + +/// +/// "PMTT" Platform Memory Topology Table +/// +#define EFI_ACPI_6_2_PLATFORM_MEMORY_TOPOLOGY_TABLE_SIGNATURE SIGNATURE_32('P', 'M', 'T', 'T') + +/// +/// "PPTT" Processor Properties Topology Table +/// +#define EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('P', 'P', 'T', 'T') + +/// +/// "PSDT" Persistent System Description Table +/// +#define EFI_ACPI_6_2_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T') + +/// +/// "RASF" ACPI RAS Feature Table +/// +#define EFI_ACPI_6_2_ACPI_RAS_FEATURE_TABLE_SIGNATURE SIGNATURE_32('R', 'A', 'S', 'F') + +/// +/// "RSDT" Root System Description Table +/// +#define EFI_ACPI_6_2_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T') + +/// +/// "SBST" Smart Battery Specification Table +/// +#define EFI_ACPI_6_2_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T') + +/// +/// "SDEV" Secure DEVices Table +/// +#define EFI_ACPI_6_2_SECURE_DEVICES_TABLE_SIGNATURE SIGNATURE_32('S', 'D', 'E', 'V') + +/// +/// "SLIT" System Locality Information Table +/// +#define EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T') + +/// +/// "SRAT" System Resource Affinity Table +/// +#define EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE SIGNATURE_32('S', 'R', 'A', 'T') + +/// +/// "SSDT" Secondary System Description Table +/// +#define EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T') + +/// +/// "XSDT" Extended System Description Table +/// +#define EFI_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('X', 'S', 'D', 'T') + +/// +/// "BOOT" MS Simple Boot Spec +/// +#define EFI_ACPI_6_2_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE SIGNATURE_32('B', 'O', 'O', 'T') + +/// +/// "CSRT" MS Core System Resource Table +/// +#define EFI_ACPI_6_2_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('C', 'S', 'R', 'T') + +/// +/// "DBG2" MS Debug Port 2 Spec +/// +#define EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', '2') + +/// +/// "DBGP" MS Debug Port Spec +/// +#define EFI_ACPI_6_2_DEBUG_PORT_TABLE_SIGNATURE SIGNATURE_32('D', 'B', 'G', 'P') + +/// +/// "DMAR" DMA Remapping Table +/// +#define EFI_ACPI_6_2_DMA_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('D', 'M', 'A', 'R') + +/// +/// "DPPT" DMA Protection Policy Table +/// +#define EFI_ACPI_6_2_DMA_PROTECTION_POLICY_TABLE_SIGNATURE SIGNATURE_32('D', 'P', 'P', 'T') + +/// +/// "DRTM" Dynamic Root of Trust for Measurement Table +/// +#define EFI_ACPI_6_2_DYNAMIC_ROOT_OF_TRUST_FOR_MEASUREMENT_TABLE_SIGNATURE SIGNATURE_32('D', 'R', 'T', 'M') + +/// +/// "ETDT" Event Timer Description Table +/// +#define EFI_ACPI_6_2_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('E', 'T', 'D', 'T') + +/// +/// "HPET" IA-PC High Precision Event Timer Table +/// +#define EFI_ACPI_6_2_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T') + +/// +/// "iBFT" iSCSI Boot Firmware Table +/// +#define EFI_ACPI_6_2_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE SIGNATURE_32('i', 'B', 'F', 'T') + +/// +/// "IORT" I/O Remapping Table +/// +#define EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE SIGNATURE_32('I', 'O', 'R', 'T') + +/// +/// "IVRS" I/O Virtualization Reporting Structure +/// +#define EFI_ACPI_6_2_IO_VIRTUALIZATION_REPORTING_STRUCTURE_SIGNATURE SIGNATURE_32('I', 'V', 'R', 'S') + +/// +/// "LPIT" Low Power Idle Table +/// +#define EFI_ACPI_6_2_LOW_POWER_IDLE_TABLE_STRUCTURE_SIGNATURE SIGNATURE_32('L', 'P', 'I', 'T') + +/// +/// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +/// +#define EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'F', 'G') + +/// +/// "MCHI" Management Controller Host Interface Table +/// +#define EFI_ACPI_6_2_MANAGEMENT_CONTROLLER_HOST_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('M', 'C', 'H', 'I') + +/// +/// "MSDM" MS Data Management Table +/// +#define EFI_ACPI_6_2_DATA_MANAGEMENT_TABLE_SIGNATURE SIGNATURE_32('M', 'S', 'D', 'M') + +/// +/// "SDEI" Software Delegated Exceptions Interface Table +/// +#define EFI_ACPI_6_2_SOFTWARE_DELEGATED_EXCEPTIONS_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'D', 'E', 'I') + +/// +/// "SLIC" MS Software Licensing Table Specification +/// +#define EFI_ACPI_6_2_SOFTWARE_LICENSING_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'C') + +/// +/// "SPCR" Serial Port Concole Redirection Table +/// +#define EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R') + +/// +/// "SPMI" Server Platform Management Interface Table +/// +#define EFI_ACPI_6_2_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'M', 'I') + +/// +/// "STAO" _STA Override Table +/// +#define EFI_ACPI_6_2_STA_OVERRIDE_TABLE_SIGNATURE SIGNATURE_32('S', 'T', 'A', 'O') + +/// +/// "TCPA" Trusted Computing Platform Alliance Capabilities Table +/// +#define EFI_ACPI_6_2_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE SIGNATURE_32('T', 'C', 'P', 'A') + +/// +/// "TPM2" Trusted Computing Platform 1 Table +/// +#define EFI_ACPI_6_2_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE SIGNATURE_32('T', 'P', 'M', '2') + +/// +/// "UEFI" UEFI ACPI Data Table +/// +#define EFI_ACPI_6_2_UEFI_ACPI_DATA_TABLE_SIGNATURE SIGNATURE_32('U', 'E', 'F', 'I') + +/// +/// "WAET" Windows ACPI Emulated Devices Table +/// +#define EFI_ACPI_6_2_WINDOWS_ACPI_EMULATED_DEVICES_TABLE_SIGNATURE SIGNATURE_32('W', 'A', 'E', 'T') + +/// +/// "WDAT" Watchdog Action Table +/// +#define EFI_ACPI_6_2_WATCHDOG_ACTION_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'A', 'T') + +/// +/// "WDRT" Watchdog Resource Table +/// +#define EFI_ACPI_6_2_WATCHDOG_RESOURCE_TABLE_SIGNATURE SIGNATURE_32('W', 'D', 'R', 'T') + +/// +/// "WPBT" MS Platform Binary Table +/// +#define EFI_ACPI_6_2_PLATFORM_BINARY_TABLE_SIGNATURE SIGNATURE_32('W', 'P', 'B', 'T') + +/// +/// "WSMT" Windows SMM Security Mitigation Table +/// +#define EFI_ACPI_6_2_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE SIGNATURE_32('W', 'S', 'M', 'T') + +/// +/// "XENV" Xen Project Table +/// +#define EFI_ACPI_6_2_XEN_PROJECT_TABLE_SIGNATURE SIGNATURE_32('X', 'E', 'N', 'V') + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AcpiAml.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AcpiAml.h new file mode 100644 index 0000000..19d9684 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AcpiAml.h @@ -0,0 +1,175 @@ +/** @file + This file contains AML code definition in the latest ACPI spec. + + Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ACPI_AML_H_ +#define _ACPI_AML_H_ + +// +// ACPI AML definition +// + +// +// Primary OpCode +// +#define AML_ZERO_OP 0x00 +#define AML_ONE_OP 0x01 +#define AML_ALIAS_OP 0x06 +#define AML_NAME_OP 0x08 +#define AML_BYTE_PREFIX 0x0a +#define AML_WORD_PREFIX 0x0b +#define AML_DWORD_PREFIX 0x0c +#define AML_STRING_PREFIX 0x0d +#define AML_QWORD_PREFIX 0x0e +#define AML_SCOPE_OP 0x10 +#define AML_BUFFER_OP 0x11 +#define AML_PACKAGE_OP 0x12 +#define AML_VAR_PACKAGE_OP 0x13 +#define AML_METHOD_OP 0x14 +#define AML_DUAL_NAME_PREFIX 0x2e +#define AML_MULTI_NAME_PREFIX 0x2f +#define AML_NAME_CHAR_A 0x41 +#define AML_NAME_CHAR_B 0x42 +#define AML_NAME_CHAR_C 0x43 +#define AML_NAME_CHAR_D 0x44 +#define AML_NAME_CHAR_E 0x45 +#define AML_NAME_CHAR_F 0x46 +#define AML_NAME_CHAR_G 0x47 +#define AML_NAME_CHAR_H 0x48 +#define AML_NAME_CHAR_I 0x49 +#define AML_NAME_CHAR_J 0x4a +#define AML_NAME_CHAR_K 0x4b +#define AML_NAME_CHAR_L 0x4c +#define AML_NAME_CHAR_M 0x4d +#define AML_NAME_CHAR_N 0x4e +#define AML_NAME_CHAR_O 0x4f +#define AML_NAME_CHAR_P 0x50 +#define AML_NAME_CHAR_Q 0x51 +#define AML_NAME_CHAR_R 0x52 +#define AML_NAME_CHAR_S 0x53 +#define AML_NAME_CHAR_T 0x54 +#define AML_NAME_CHAR_U 0x55 +#define AML_NAME_CHAR_V 0x56 +#define AML_NAME_CHAR_W 0x57 +#define AML_NAME_CHAR_X 0x58 +#define AML_NAME_CHAR_Y 0x59 +#define AML_NAME_CHAR_Z 0x5a +#define AML_ROOT_CHAR 0x5c +#define AML_PARENT_PREFIX_CHAR 0x5e +#define AML_NAME_CHAR__ 0x5f +#define AML_LOCAL0 0x60 +#define AML_LOCAL1 0x61 +#define AML_LOCAL2 0x62 +#define AML_LOCAL3 0x63 +#define AML_LOCAL4 0x64 +#define AML_LOCAL5 0x65 +#define AML_LOCAL6 0x66 +#define AML_LOCAL7 0x67 +#define AML_ARG0 0x68 +#define AML_ARG1 0x69 +#define AML_ARG2 0x6a +#define AML_ARG3 0x6b +#define AML_ARG4 0x6c +#define AML_ARG5 0x6d +#define AML_ARG6 0x6e +#define AML_STORE_OP 0x70 +#define AML_REF_OF_OP 0x71 +#define AML_ADD_OP 0x72 +#define AML_CONCAT_OP 0x73 +#define AML_SUBTRACT_OP 0x74 +#define AML_INCREMENT_OP 0x75 +#define AML_DECREMENT_OP 0x76 +#define AML_MULTIPLY_OP 0x77 +#define AML_DIVIDE_OP 0x78 +#define AML_SHIFT_LEFT_OP 0x79 +#define AML_SHIFT_RIGHT_OP 0x7a +#define AML_AND_OP 0x7b +#define AML_NAND_OP 0x7c +#define AML_OR_OP 0x7d +#define AML_NOR_OP 0x7e +#define AML_XOR_OP 0x7f +#define AML_NOT_OP 0x80 +#define AML_FIND_SET_LEFT_BIT_OP 0x81 +#define AML_FIND_SET_RIGHT_BIT_OP 0x82 +#define AML_DEREF_OF_OP 0x83 +#define AML_CONCAT_RES_OP 0x84 +#define AML_MOD_OP 0x85 +#define AML_NOTIFY_OP 0x86 +#define AML_SIZE_OF_OP 0x87 +#define AML_INDEX_OP 0x88 +#define AML_MATCH_OP 0x89 +#define AML_CREATE_DWORD_FIELD_OP 0x8a +#define AML_CREATE_WORD_FIELD_OP 0x8b +#define AML_CREATE_BYTE_FIELD_OP 0x8c +#define AML_CREATE_BIT_FIELD_OP 0x8d +#define AML_OBJECT_TYPE_OP 0x8e +#define AML_CREATE_QWORD_FIELD_OP 0x8f +#define AML_LAND_OP 0x90 +#define AML_LOR_OP 0x91 +#define AML_LNOT_OP 0x92 +#define AML_LEQUAL_OP 0x93 +#define AML_LGREATER_OP 0x94 +#define AML_LLESS_OP 0x95 +#define AML_TO_BUFFER_OP 0x96 +#define AML_TO_DEC_STRING_OP 0x97 +#define AML_TO_HEX_STRING_OP 0x98 +#define AML_TO_INTEGER_OP 0x99 +#define AML_TO_STRING_OP 0x9c +#define AML_COPY_OBJECT_OP 0x9d +#define AML_MID_OP 0x9e +#define AML_CONTINUE_OP 0x9f +#define AML_IF_OP 0xa0 +#define AML_ELSE_OP 0xa1 +#define AML_WHILE_OP 0xa2 +#define AML_NOOP_OP 0xa3 +#define AML_RETURN_OP 0xa4 +#define AML_BREAK_OP 0xa5 +#define AML_BREAK_POINT_OP 0xcc +#define AML_ONES_OP 0xff + +// +// Extended OpCode +// +#define AML_EXT_OP 0x5b + +#define AML_EXT_MUTEX_OP 0x01 +#define AML_EXT_EVENT_OP 0x02 +#define AML_EXT_COND_REF_OF_OP 0x12 +#define AML_EXT_CREATE_FIELD_OP 0x13 +#define AML_EXT_LOAD_TABLE_OP 0x1f +#define AML_EXT_LOAD_OP 0x20 +#define AML_EXT_STALL_OP 0x21 +#define AML_EXT_SLEEP_OP 0x22 +#define AML_EXT_ACQUIRE_OP 0x23 +#define AML_EXT_SIGNAL_OP 0x24 +#define AML_EXT_WAIT_OP 0x25 +#define AML_EXT_RESET_OP 0x26 +#define AML_EXT_RELEASE_OP 0x27 +#define AML_EXT_FROM_BCD_OP 0x28 +#define AML_EXT_TO_BCD_OP 0x29 +#define AML_EXT_UNLOAD_OP 0x2a +#define AML_EXT_REVISION_OP 0x30 +#define AML_EXT_DEBUG_OP 0x31 +#define AML_EXT_FATAL_OP 0x32 +#define AML_EXT_TIMER_OP 0x33 +#define AML_EXT_REGION_OP 0x80 +#define AML_EXT_FIELD_OP 0x81 +#define AML_EXT_DEVICE_OP 0x82 +#define AML_EXT_PROCESSOR_OP 0x83 +#define AML_EXT_POWER_RES_OP 0x84 +#define AML_EXT_THERMAL_ZONE_OP 0x85 +#define AML_EXT_INDEX_FIELD_OP 0x86 +#define AML_EXT_BANK_FIELD_OP 0x87 +#define AML_EXT_DATA_REGION_OP 0x88 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AlertStandardFormatTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AlertStandardFormatTable.h new file mode 100644 index 0000000..758fbea --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/AlertStandardFormatTable.h @@ -0,0 +1,146 @@ +/** @file + ACPI Alert Standard Format Description Table ASF! as described in the ASF2.0 Specification + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _ALERT_STANDARD_FORMAT_TABLE_H_ +#define _ALERT_STANDARD_FORMAT_TABLE_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack (1) + +/// +/// Information Record header that appears at the beginning of each record +/// +typedef struct { + UINT8 Type; + UINT8 Reserved; + UINT16 RecordLength; +} EFI_ACPI_ASF_RECORD_HEADER; + +/// +/// This structure contains information that identifies the system's type +/// and configuration +/// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 MinWatchDogResetValue; + UINT8 MinPollingInterval; + UINT16 SystemID; + UINT32 IANAManufactureID; + UINT8 FeatureFlags; + UINT8 Reserved[3]; +} EFI_ACPI_ASF_INFO; + +/// +/// ASF Alert Data +/// +typedef struct { + UINT8 DeviceAddress; + UINT8 Command; + UINT8 DataMask; + UINT8 CompareValue; + UINT8 EventSenseType; + UINT8 EventType; + UINT8 EventOffset; + UINT8 EventSourceType; + UINT8 EventSeverity; + UINT8 SensorNumber; + UINT8 Entity; + UINT8 EntityInstance; +} EFI_ACPI_ASF_ALERTDATA; + +/// +/// Alert sensors definition +/// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 AssertionEventBitMask; + UINT8 DeassertionEventBitMask; + UINT8 NumberOfAlerts; + UINT8 ArrayElementLength; ///< For ASF version 1.0 and later, this filed is set to 0x0C + /// + /// EFI_ACPI_ASF_ALERTDATA DeviceArray[ANYSIZE_ARRAY]; + /// +} EFI_ACPI_ASF_ALRT; + +/// +/// Alert Control Data +/// +typedef struct { + UINT8 Function; + UINT8 DeviceAddress; + UINT8 Command; + UINT8 DataValue; +} EFI_ACPI_ASF_CONTROLDATA; + +/// +/// Alert Remote Control System Actions +/// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 NumberOfControls; + UINT8 ArrayElementLength; ///< For ASF version 1.0 and later, this filed is set to 0x4 + UINT16 RctlReserved; + /// + /// EFI_ACPI_ASF_CONTROLDATA; DeviceArray[ANYSIZE_ARRAY]; + /// +} EFI_ACPI_ASF_RCTL; + + +/// +/// Remote Control Capabilities +/// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 RemoteControlCapabilities[7]; + UINT8 RMCPCompletionCode; + UINT32 RMCPIANA; + UINT8 RMCPSpecialCommand; + UINT8 RMCPSpecialCommandParameter[2]; + UINT8 RMCPBootOptions[2]; + UINT8 RMCPOEMParameters[2]; +} EFI_ACPI_ASF_RMCP; + +/// +/// SMBus Devices with fixed addresses +/// +typedef struct { + EFI_ACPI_ASF_RECORD_HEADER RecordHeader; + UINT8 SEEPROMAddress; + UINT8 NumberOfDevices; + /// + /// UINT8 FixedSmbusAddresses[ANYSIZE_ARRAY]; + /// +} EFI_ACPI_ASF_ADDR; + +/// +/// ASF! Description Table Header +/// +typedef EFI_ACPI_DESCRIPTION_HEADER EFI_ACPI_ASF_DESCRIPTION_HEADER; + +/// +/// The revision stored in ASF! DESCRIPTION TABLE as BCD value +/// +#define EFI_ACPI_2_0_ASF_DESCRIPTION_TABLE_REVISION 0x20 + +/// +/// "ASF!" ASF Description Table Signature +/// +#define EFI_ACPI_ASF_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32 ('A', 'S', 'F', '!') + +#pragma pack () + +#endif // _ALERT_STANDARD_FORMAT_TABLE_H diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Atapi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Atapi.h new file mode 100644 index 0000000..c1a0d90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Atapi.h @@ -0,0 +1,857 @@ +/** @file + This file contains just some basic definitions that are needed by drivers + that dealing with ATA/ATAPI interface. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ATAPI_H_ +#define _ATAPI_H_ + +#pragma pack(1) + +/// +/// ATA5_IDENTIFY_DATA is defined in ATA-5. +/// (This structure is provided mainly for backward-compatibility support. +/// Old drivers may reference fields that are marked "obsolete" in +/// ATA_IDENTIFY_DATA, which currently conforms to ATA-8.) +/// +typedef struct { + UINT16 config; ///< General Configuration. + UINT16 cylinders; ///< Number of Cylinders. + UINT16 reserved_2; + UINT16 heads; ///< Number of logical heads. + UINT16 vendor_data1; + UINT16 vendor_data2; + UINT16 sectors_per_track; + UINT16 vendor_specific_7_9[3]; + CHAR8 SerialNo[20]; ///< ASCII + UINT16 vendor_specific_20_21[2]; + UINT16 ecc_bytes_available; + CHAR8 FirmwareVer[8]; ///< ASCII + CHAR8 ModelName[40]; ///< ASCII + UINT16 multi_sector_cmd_max_sct_cnt; + UINT16 reserved_48; + UINT16 capabilities; + UINT16 reserved_50; + UINT16 pio_cycle_timing; + UINT16 reserved_52; + UINT16 field_validity; + UINT16 current_cylinders; + UINT16 current_heads; + UINT16 current_sectors; + UINT16 CurrentCapacityLsb; + UINT16 CurrentCapacityMsb; + UINT16 reserved_59; + UINT16 user_addressable_sectors_lo; + UINT16 user_addressable_sectors_hi; + UINT16 reserved_62; + UINT16 multi_word_dma_mode; + UINT16 advanced_pio_modes; + UINT16 min_multi_word_dma_cycle_time; + UINT16 rec_multi_word_dma_cycle_time; + UINT16 min_pio_cycle_time_without_flow_control; + UINT16 min_pio_cycle_time_with_flow_control; + UINT16 reserved_69_79[11]; + UINT16 major_version_no; + UINT16 minor_version_no; + UINT16 command_set_supported_82; ///< word 82 + UINT16 command_set_supported_83; ///< word 83 + UINT16 command_set_feature_extn; ///< word 84 + UINT16 command_set_feature_enb_85; ///< word 85 + UINT16 command_set_feature_enb_86; ///< word 86 + UINT16 command_set_feature_default; ///< word 87 + UINT16 ultra_dma_mode; ///< word 88 + UINT16 reserved_89_127[39]; + UINT16 security_status; + UINT16 vendor_data_129_159[31]; + UINT16 reserved_160_255[96]; +} ATA5_IDENTIFY_DATA; + +/// +/// ATA_IDENTIFY_DATA strictly complies with ATA/ATAPI-8 Spec +/// to define the data returned by an ATA device upon successful +/// completion of the ATA IDENTIFY_DEVICE command. +/// +typedef struct { + UINT16 config; ///< General Configuration. + UINT16 obsolete_1; + UINT16 specific_config; ///< Specific Configuration. + UINT16 obsolete_3; + UINT16 retired_4_5[2]; + UINT16 obsolete_6; + UINT16 cfa_reserved_7_8[2]; + UINT16 retired_9; + CHAR8 SerialNo[20]; ///< word 10~19 + UINT16 retired_20_21[2]; + UINT16 obsolete_22; + CHAR8 FirmwareVer[8]; ///< word 23~26 + CHAR8 ModelName[40]; ///< word 27~46 + UINT16 multi_sector_cmd_max_sct_cnt; + UINT16 trusted_computing_support; + UINT16 capabilities_49; + UINT16 capabilities_50; + UINT16 obsolete_51_52[2]; + UINT16 field_validity; + UINT16 obsolete_54_58[5]; + UINT16 multi_sector_setting; + UINT16 user_addressable_sectors_lo; + UINT16 user_addressable_sectors_hi; + UINT16 obsolete_62; + UINT16 multi_word_dma_mode; + UINT16 advanced_pio_modes; + UINT16 min_multi_word_dma_cycle_time; + UINT16 rec_multi_word_dma_cycle_time; + UINT16 min_pio_cycle_time_without_flow_control; + UINT16 min_pio_cycle_time_with_flow_control; + UINT16 additional_supported; ///< word 69 + UINT16 reserved_70; + UINT16 reserved_71_74[4]; ///< Reserved for IDENTIFY PACKET DEVICE cmd. + UINT16 queue_depth; + UINT16 serial_ata_capabilities; + UINT16 reserved_77; ///< Reserved for Serial ATA + UINT16 serial_ata_features_supported; + UINT16 serial_ata_features_enabled; + UINT16 major_version_no; + UINT16 minor_version_no; + UINT16 command_set_supported_82; ///< word 82 + UINT16 command_set_supported_83; ///< word 83 + UINT16 command_set_feature_extn; ///< word 84 + UINT16 command_set_feature_enb_85; ///< word 85 + UINT16 command_set_feature_enb_86; ///< word 86 + UINT16 command_set_feature_default; ///< word 87 + UINT16 ultra_dma_mode; ///< word 88 + UINT16 time_for_security_erase_unit; + UINT16 time_for_enhanced_security_erase_unit; + UINT16 advanced_power_management_level; + UINT16 master_password_identifier; + UINT16 hardware_configuration_test_result; + UINT16 obsolete_94; + UINT16 stream_minimum_request_size; + UINT16 streaming_transfer_time_for_dma; + UINT16 streaming_access_latency_for_dma_and_pio; + UINT16 streaming_performance_granularity[2]; ///< word 98~99 + UINT16 maximum_lba_for_48bit_addressing[4]; ///< word 100~103 + UINT16 streaming_transfer_time_for_pio; + UINT16 max_no_of_512byte_blocks_per_data_set_cmd; + UINT16 phy_logic_sector_support; ///< word 106 + UINT16 interseek_delay_for_iso7779; + UINT16 world_wide_name[4]; ///< word 108~111 + UINT16 reserved_for_128bit_wwn_112_115[4]; + UINT16 reserved_for_technical_report; + UINT16 logic_sector_size_lo; ///< word 117 + UINT16 logic_sector_size_hi; ///< word 118 + UINT16 features_and_command_sets_supported_ext; ///< word 119 + UINT16 features_and_command_sets_enabled_ext; ///< word 120 + UINT16 reserved_121_126[6]; + UINT16 obsolete_127; + UINT16 security_status; ///< word 128 + UINT16 vendor_specific_129_159[31]; + UINT16 cfa_power_mode; ///< word 160 + UINT16 reserved_for_compactflash_161_167[7]; + UINT16 device_nominal_form_factor; + UINT16 is_data_set_cmd_supported; + CHAR8 additional_product_identifier[8]; + UINT16 reserved_174_175[2]; + CHAR8 media_serial_number[60]; ///< word 176~205 + UINT16 sct_command_transport; ///< word 206 + UINT16 reserved_207_208[2]; + UINT16 alignment_logic_in_phy_blocks; ///< word 209 + UINT16 write_read_verify_sector_count_mode3[2]; ///< word 210~211 + UINT16 verify_sector_count_mode2[2]; + UINT16 nv_cache_capabilities; + UINT16 nv_cache_size_in_logical_block_lsw; ///< word 215 + UINT16 nv_cache_size_in_logical_block_msw; ///< word 216 + UINT16 nominal_media_rotation_rate; + UINT16 reserved_218; + UINT16 nv_cache_options; ///< word 219 + UINT16 write_read_verify_mode; ///< word 220 + UINT16 reserved_221; + UINT16 transport_major_revision_number; + UINT16 transport_minor_revision_number; + UINT16 reserved_224_229[6]; + UINT64 extended_no_of_addressable_sectors; + UINT16 min_number_per_download_microcode_mode3; ///< word 234 + UINT16 max_number_per_download_microcode_mode3; ///< word 235 + UINT16 reserved_236_254[19]; + UINT16 integrity_word; +} ATA_IDENTIFY_DATA; + +/// +/// ATAPI_IDENTIFY_DATA strictly complies with ATA/ATAPI-8 Spec +/// to define the data returned by an ATAPI device upon successful +/// completion of the ATA IDENTIFY_PACKET_DEVICE command. +/// +typedef struct { + UINT16 config; ///< General Configuration. + UINT16 reserved_1; + UINT16 specific_config; ///< Specific Configuration. + UINT16 reserved_3_9[7]; + CHAR8 SerialNo[20]; ///< word 10~19 + UINT16 reserved_20_22[3]; + CHAR8 FirmwareVer[8]; ///< word 23~26 + CHAR8 ModelName[40]; ///< word 27~46 + UINT16 reserved_47_48[2]; + UINT16 capabilities_49; + UINT16 capabilities_50; + UINT16 obsolete_51; + UINT16 reserved_52; + UINT16 field_validity; ///< word 53 + UINT16 reserved_54_61[8]; + UINT16 dma_dir; + UINT16 multi_word_dma_mode; ///< word 63 + UINT16 advanced_pio_modes; ///< word 64 + UINT16 min_multi_word_dma_cycle_time; + UINT16 rec_multi_word_dma_cycle_time; + UINT16 min_pio_cycle_time_without_flow_control; + UINT16 min_pio_cycle_time_with_flow_control; + UINT16 reserved_69_70[2]; + UINT16 obsolete_71_72[2]; + UINT16 reserved_73_74[2]; + UINT16 obsolete_75; + UINT16 serial_ata_capabilities; + UINT16 reserved_77; ///< Reserved for Serial ATA + UINT16 serial_ata_features_supported; + UINT16 serial_ata_features_enabled; + UINT16 major_version_no; ///< word 80 + UINT16 minor_version_no; ///< word 81 + UINT16 cmd_set_support_82; + UINT16 cmd_set_support_83; + UINT16 cmd_feature_support; + UINT16 cmd_feature_enable_85; + UINT16 cmd_feature_enable_86; + UINT16 cmd_feature_default; + UINT16 ultra_dma_select; + UINT16 time_required_for_sec_erase; ///< word 89 + UINT16 time_required_for_enhanced_sec_erase; ///< word 90 + UINT16 advanced_power_management_level; + UINT16 master_pwd_revison_code; + UINT16 hardware_reset_result; ///< word 93 + UINT16 obsolete_94; + UINT16 reserved_95_107[13]; + UINT16 world_wide_name[4]; ///< word 108~111 + UINT16 reserved_for_128bit_wwn_112_115[4]; + UINT16 reserved_116_118[3]; + UINT16 command_and_feature_sets_supported; ///< word 119 + UINT16 command_and_feature_sets_supported_enabled; + UINT16 reserved_121_124[4]; + UINT16 atapi_byte_count_0_behavior; ///< word 125 + UINT16 obsolete_126_127[2]; + UINT16 security_status; + UINT16 reserved_129_159[31]; + UINT16 cfa_reserved_160_175[16]; + UINT16 reserved_176_221[46]; + UINT16 transport_major_version; + UINT16 transport_minor_version; + UINT16 reserved_224_254[31]; + UINT16 integrity_word; +} ATAPI_IDENTIFY_DATA; + + +/// +/// Standard Quiry Data format, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 peripheral_type; + UINT8 RMB; + UINT8 version; + UINT8 response_data_format; + UINT8 addnl_length; ///< n - 4, Numbers of bytes following this one. + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 vendor_info[8]; + UINT8 product_id[16]; + UINT8 product_revision_level[4]; + UINT8 vendor_specific_36_55[55 - 36 + 1]; + UINT8 reserved_56_95[95 - 56 + 1]; + /// + /// Vendor-specific parameters fields. The sizeof (ATAPI_INQUIRY_DATA) is 254 + /// since allocation_length is one byte in ATAPI_INQUIRY_CMD. + /// + UINT8 vendor_specific_96_253[253 - 96 + 1]; +} ATAPI_INQUIRY_DATA; + +/// +/// Request Sense Standard Data, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 error_code : 7; + UINT8 valid : 1; + UINT8 reserved_1; + UINT8 sense_key : 4; + UINT8 reserved_2 : 1; + UINT8 Vendor_specifc_1 : 3; + UINT8 vendor_specific_3; + UINT8 vendor_specific_4; + UINT8 vendor_specific_5; + UINT8 vendor_specific_6; + UINT8 addnl_sense_length; ///< n - 7 + UINT8 vendor_specific_8; + UINT8 vendor_specific_9; + UINT8 vendor_specific_10; + UINT8 vendor_specific_11; + UINT8 addnl_sense_code; ///< mandatory + UINT8 addnl_sense_code_qualifier; ///< mandatory + UINT8 field_replaceable_unit_code; ///< optional + UINT8 sense_key_specific_15 : 7; + UINT8 SKSV : 1; + UINT8 sense_key_specific_16; + UINT8 sense_key_specific_17; +} ATAPI_REQUEST_SENSE_DATA; + +/// +/// READ CAPACITY Data, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 BlockSize3; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} ATAPI_READ_CAPACITY_DATA; + +/// +/// Capacity List Header + Current/Maximum Capacity Descriptor, +/// defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 reserved_0; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 Capacity_Length; + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 DesCode : 2; + UINT8 reserved_9 : 6; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} ATAPI_READ_FORMAT_CAPACITY_DATA; + +/// +/// Test Unit Ready Command, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 opcode; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} ATAPI_TEST_UNIT_READY_CMD; + +/// +/// INQUIRY Command, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 page_code; ///< defined in SFF8090i, V6 + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} ATAPI_INQUIRY_CMD; + +/// +/// REQUEST SENSE Command, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} ATAPI_REQUEST_SENSE_CMD; + +/// +/// READ (10) Command, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 reserved_6; + UINT8 TranLen0; + UINT8 TranLen1; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} ATAPI_READ10_CMD; + +/// +/// READ Format Capacity Command, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 allocation_length_hi; + UINT8 allocation_length_lo; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} ATAPI_READ_FORMAT_CAP_CMD; + +/// +/// MODE SENSE Command, defined in SFF-8070i(ATAPI Removable Rewritable Specification). +/// +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 page_code : 6; + UINT8 page_control : 2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 parameter_list_length_hi; + UINT8 parameter_list_length_lo; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} ATAPI_MODE_SENSE_CMD; + +/// +/// ATAPI_PACKET_COMMAND is not defined in the ATA specification. +/// We add it here for the convenience of ATA/ATAPI module writers. +/// +typedef union { + UINT16 Data16[6]; + ATAPI_TEST_UNIT_READY_CMD TestUnitReady; + ATAPI_READ10_CMD Read10; + ATAPI_REQUEST_SENSE_CMD RequestSence; + ATAPI_INQUIRY_CMD Inquiry; + ATAPI_MODE_SENSE_CMD ModeSense; + ATAPI_READ_FORMAT_CAP_CMD ReadFormatCapacity; +} ATAPI_PACKET_COMMAND; + +#pragma pack() + + +#define ATAPI_MAX_DMA_EXT_CMD_SECTORS 0x10000 +#define ATAPI_MAX_DMA_CMD_SECTORS 0x100 + +// ATA/ATAPI Signature equates +#define ATA_SIGNATURE 0x0101 ///< defined in ACS-3 +#define ATAPI_SIGNATURE 0xeb14 ///< defined in ACS-3 +#define ATAPI_SIGNATURE_32 0xeb140101 ///< defined in ACS-3 + +// Spin Up Configuration definitions +#define ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE 0x37c8 ///< defined in ACS-3 +#define ATA_SPINUP_CFG_REQUIRED_IDD_COMPLETE 0x738c ///< defined in ACS-3 +#define ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE 0x8c73 ///< defined in ACS-3 +#define ATA_SPINUP_CFG_NOT_REQUIRED_IDD_COMPLETE 0xc837 ///< defined in ACS-3 + +// +// ATA Packet Command Code +// +#define ATA_CMD_FORMAT_UNIT 0x04 ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_SOFT_RESET 0x08 ///< defined from ATA-3 +#define ATA_CMD_PACKET 0xA0 ///< defined from ATA-3 +#define ATA_CMD_IDENTIFY_DEVICE 0xA1 ///< defined from ATA-3 +#define ATA_CMD_SERVICE 0xA2 ///< defined from ATA-3 +#define ATA_CMD_TEST_UNIT_READY 0x00 ///< defined from ATA-1 +#define ATA_CMD_REQUEST_SENSE 0x03 ///< defined from ATA-4 +#define ATA_CMD_INQUIRY 0x12 ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_READ_FORMAT_CAPACITY 0x23 ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_READ_CAPACITY 0x25 ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_READ_10 0x28 ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_WRITE_10 0x2A ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_ATAPI_SEEK 0x2B ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_WRITE_AND_VERIFY 0x2E ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_VERIFY 0x2F ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_READ_12 0xA8 ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_WRITE_12 0xAA ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_START_STOP_UNIT 0x1B ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_PREVENT_ALLOW_MEDIA_REMOVAL 0x1E ///< defined in ATAPI Removable Rewritable Media Devcies +#define ATA_CMD_MODE_SELECT 0x55 ///< defined in ATAPI Removable Rewritable Media Devcies + +#define ATA_CMD_MODE_SENSE 0x5A ///< defined in ATAPI Removable Rewritable Media Devcies + #define ATA_PAGE_CODE_READ_WRITE_ERROR 0x01 ///< defined in ATAPI Removable Rewritable Media Devcies + #define ATA_PAGE_CODE_CACHING_PAGE 0x08 ///< defined in ATAPI Removable Rewritable Media Devcies + #define ATA_PAGE_CODE_REMOVABLE_BLOCK_CAPABILITIES 0x1B ///< defined in ATAPI Removable Rewritable Media Devcies + #define ATA_PAGE_CODE_TIMER_PROTECT_PAGE 0x1C ///< defined in ATAPI Removable Rewritable Media Devcies + #define ATA_PAGE_CODE_RETURN_ALL_PAGES 0x3F ///< defined in ATAPI Removable Rewritable Media Devcies + +#define ATA_CMD_GET_CONFIGURATION 0x46 ///< defined in ATAPI Multimedia Devices + #define ATA_GCCD_RT_FIELD_VALUE_ALL 0x00 ///< defined in ATAPI Multimedia Devices + #define ATA_GCCD_RT_FIELD_VALUE_CURRENT 0x01 ///< defined in ATAPI Multimedia Devices + #define ATA_GCCD_RT_FIELD_VALUE_SINGLE 0x02 ///< defined in ATAPI Multimedia Devices + #define ATA_GCCD_RT_FIELD_VALUE_RESERVED 0x03 ///< defined in ATAPI Multimedia Devices + + #define ATA_FEATURE_LIST_PROFILE_LIST 0x0000 ///< defined in ATAPI Multimedia Devices + #define ATA_FEATURE_LIST_CORE 0x0001 ///< defined in ATAPI Multimedia Devices + #define ATA_FEATURE_LIST_MORPHING 0x0002 ///< defined in ATAPI Multimedia Devices + #define ATA_FEATURE_LIST_REMOVEABLE_MEDIUM 0x0003 ///< defined in ATAPI Multimedia Devices + #define ATA_FEATURE_LIST_WRITE_PROTECT 0x0004 ///< defined in ATAPI Multimedia Devices + +/// +/// Start/Stop and Eject Operations +/// +///@{ +#define ATA_CMD_SUBOP_STOP_DISC 0x00 ///< Stop the Disc +#define ATA_CMD_SUBOP_START_DISC 0x01 ///< Start the Disc and acquire the format type +#define ATA_CMD_SUBOP_EJECT_DISC 0x02 ///< Eject the Disc if possible +#define ATA_CMD_SUBOP_CLOSE_TRAY 0x03 ///< Load the Disc (Close Tray) +///@} + +// +// ATA Commands Code +// + +// +// Class 1: PIO Data-In Commands +// +#define ATA_CMD_IDENTIFY_DRIVE 0xec ///< defined from ATA-3 +#define ATA_CMD_READ_BUFFER 0xe4 ///< defined from ATA-1 +#define ATA_CMD_READ_SECTORS 0x20 ///< defined from ATA-1 +#define ATA_CMD_READ_SECTORS_WITH_RETRY 0x21 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_READ_LONG 0x22 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_READ_LONG_WITH_RETRY 0x23 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_READ_SECTORS_EXT 0x24 ///< defined from ATA-6 +#define ATA_CMD_READ_MULTIPLE 0xc4 ///< defined in ACS-3 +#define ATA_CMD_READ_MULTIPLE_EXT 0x29 ///< defined in ACS-3 +#define ATA_CMD_READ_LOG_EXT 0x2f ///< defined in ACS-3 + +// +// Class 2: PIO Data-Out Commands +// +#define ATA_CMD_FORMAT_TRACK 0x50 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_WRITE_BUFFER 0xe8 ///< defined from ATA-1 +#define ATA_CMD_WRITE_SECTORS 0x30 ///< defined from ATA-1 +#define ATA_CMD_WRITE_SECTORS_WITH_RETRY 0x31 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_WRITE_LONG 0x32 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_WRITE_LONG_WITH_RETRY 0x33 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_WRITE_VERIFY 0x3c ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_WRITE_SECTORS_EXT 0x34 ///< defined from ATA-6 +#define ATA_CMD_WRITE_MULTIPLE 0xc5 ///< defined in ACS-3 +#define ATA_CMD_WRITE_MULTIPLE_EXT 0x39 ///< defined in ACS-3 + +// +// Class 3 No Data Command +// +#define ATA_CMD_ACK_MEDIA_CHANGE 0xdb ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_BOOT_POST_BOOT 0xdc ///< defined from ATA-1, obsoleted from ATA-3 +#define ATA_CMD_BOOT_PRE_BOOT 0xdd ///< defined from ATA-1, obsoleted from ATA-3 +#define ATA_CMD_CHECK_POWER_MODE 0x98 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_CHECK_POWER_MODE_ALIAS 0xe5 ///< defined from ATA-1 +#define ATA_CMD_DOOR_LOCK 0xde ///< defined from ATA-1 +#define ATA_CMD_DOOR_UNLOCK 0xdf ///< defined from ATA-1 +#define ATA_CMD_EXEC_DRIVE_DIAG 0x90 ///< defined from ATA-1 +#define ATA_CMD_IDLE_ALIAS 0x97 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_IDLE 0xe3 ///< defined from ATA-1 +#define ATA_CMD_IDLE_IMMEDIATE 0x95 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_IDLE_IMMEDIATE_ALIAS 0xe1 ///< defined from ATA-1 +#define ATA_CMD_INIT_DRIVE_PARAM 0x91 ///< defined from ATA-1, obsoleted from ATA-6 +#define ATA_CMD_RECALIBRATE 0x10 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_READ_DRIVE_STATE 0xe9 ///< defined from ATA-1, obsoleted from ATA-3 +#define ATA_CMD_SET_MULTIPLE_MODE 0xC6 ///< defined from ATA-2 +#define ATA_CMD_READ_VERIFY 0x40 ///< defined from ATA-1 +#define ATA_CMD_READ_VERIFY_WITH_RETRY 0x41 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_SEEK 0x70 ///< defined from ATA-1 +#define ATA_CMD_SET_FEATURES 0xef ///< defined from ATA-1 +#define ATA_CMD_STANDBY 0x96 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_STANDBY_ALIAS 0xe2 ///< defined from ATA-1 +#define ATA_CMD_STANDBY_IMMEDIATE 0x94 ///< defined from ATA-1, obsoleted from ATA-4 +#define ATA_CMD_STANDBY_IMMEDIATE_ALIAS 0xe0 ///< defined from ATA-1 +#define ATA_CMD_SLEEP 0xe6 ///< defined in ACS-3 +#define ATA_CMD_READ_NATIVE_MAX_ADDRESS 0xf8 ///< defined in ATA-6 +#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT 0x27 ///< defined in ATA-6 + +// +// Set Features Sub Command +// +#define ATA_SUB_CMD_ENABLE_VOLATILE_WRITE_CACHE 0x02 ///< defined in ACS-3 +#define ATA_SUB_CMD_SET_TRANSFER_MODE 0x03 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_APM 0x05 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_PUIS 0x06 ///< defined in ACS-3 +#define ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP 0x07 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_WRITE_READ_VERIFY 0x0b ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_SATA_FEATURE 0x10 ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_MEDIA_STATUS_NOTIFICATION 0x31 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_FREE_FALL_CONTROL 0x41 ///< defined in ACS-3 +#define ATA_SUB_CMD_ACOUSTIC_MANAGEMENT_ENABLE 0x42 ///< defined in ACS-3 +#define ATA_SUB_CMD_SET_MAX_HOST_INTERFACE_SECTOR_TIMES 0x43 ///< defined in ACS-3 +#define ATA_SUB_CMD_EXTENDED_POWER_CONDITIONS 0x4a ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_READ_LOOK_AHEAD 0x55 ///< defined in ACS-3 +#define ATA_SUB_CMD_EN_DIS_DSN_FEATURE 0x63 ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_REVERT_TO_POWER_ON_DEFAULTS 0x66 ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_VOLATILE_WRITE_CACHE 0x82 ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_APM 0x85 ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_PUIS 0x86 ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_WRITE_READ_VERIFY 0x8b ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_SATA_FEATURE 0x90 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_MEDIA_STATUS_NOTIFICATION 0x95 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_READ_LOOK_AHEAD 0xaa ///< defined in ACS-3 +#define ATA_SUB_CMD_DISABLE_FREE_FALL_CONTROL 0xc1 ///< defined in ACS-3 +#define ATA_SUB_CMD_ACOUSTIC_MANAGEMENT_DISABLE 0xc2 ///< defined in ACS-3 +#define ATA_SUB_CMD_EN_DIS_SENSE_DATA_REPORTING 0xc3 ///< defined in ACS-3 +#define ATA_SUB_CMD_ENABLE_REVERT_TO_POWER_ON_DEFAULTS 0xcc ///< defined in ACS-3 + +// +// S.M.A.R.T +// +#define ATA_CMD_SMART 0xb0 ///< defined from ATA-3 +#define ATA_CONSTANT_C2 0xc2 ///< reserved +#define ATA_CONSTANT_4F 0x4f ///< reserved + +#define ATA_SMART_READ_DATA 0xd0 ///< defined in ACS-3 + +#define ATA_SMART_AUTOSAVE 0xd2 ///< defined in ACS-3 + #define ATA_AUTOSAVE_DISABLE_ATTR 0x00 + #define ATA_AUTOSAVE_ENABLE_ATTR 0xf1 + +#define ATA_SMART_EXECUTE_OFFLINE_IMMEDIATE 0xd4 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_OFFLINE_ROUTINE 0x00 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_OFFLINE_SHORT_SELFTEST 0x01 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_OFFLINE_EXTENDED_SELFTEST 0x02 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_OFFLINE_CONVEYANCE_SELFTEST 0x03 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_OFFLINE_SELECTIVE_SELFTEST 0x04 ///< defined in ACS-3 + #define ATA_SMART_ABORT_SELF_TEST_SUBROUTINE 0x7f ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_CAPTIVE_SHORT_SELFTEST 0x81 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_CAPTIVE_EXTENDED_SELFTEST 0x82 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_CAPTIVE_CONVEYANCE_SELFTEST 0x83 ///< defined in ACS-3 + #define ATA_EXECUTE_SMART_CAPTIVE_SELECTIVE_SELFTEST 0x84 ///< defined in ACS-3 + +#define ATA_SMART_READLOG 0xd5 ///< defined in ACS-3 +#define ATA_SMART_WRITELOG 0xd6 ///< defined in ACS-3 +#define ATA_SMART_ENABLE_OPERATION 0xd8 ///< reserved +#define ATA_SMART_DISABLE_OPERATION 0xd9 ///< defined in ACS-3 +#define ATA_SMART_RETURN_STATUS 0xda ///< defined from ATA-3 + +#define ATA_SMART_THRESHOLD_NOT_EXCEEDED_VALUE 0xc24f ///< defined in ACS-3 +#define ATA_SMART_THRESHOLD_EXCEEDED_VALUE 0x2cf4 ///< defined in ACS-3 + +// SMART Log Definitions +#define ATA_SMART_LOG_DIRECTORY 0x00 ///< defined in ACS-3 +#define ATA_SMART_SUM_SMART_ERROR_LOG 0x01 ///< defined in ACS-3 +#define ATA_SMART_COMP_SMART_ERROR_LOG 0x02 ///< defined in ACS-3 +#define ATA_SMART_EXT_COMP_SMART_ERROR_LOG 0x03 ///< defined in ACS-3 +#define ATA_SMART_SMART_SELFTEST_LOG 0x06 ///< defined in ACS-3 +#define ATA_SMART_EXT_SMART_SELFTEST_LOG 0x07 ///< defined in ACS-3 +#define ATA_SMART_SELECTIVE_SELFTEST_LOG 0x09 ///< defined in ACS-3 +#define ATA_SMART_HOST_VENDOR_SPECIFIC 0x80 ///< defined in ACS-3 +#define ATA_SMART_DEVICE_VENDOR_SPECIFIC 0xa0 ///< defined in ACS-3 + +// +// Class 4: DMA Command +// +#define ATA_CMD_READ_DMA 0xc8 ///< defined from ATA-1 +#define ATA_CMD_READ_DMA_WITH_RETRY 0xc9 ///< defined from ATA-1, obsoleted from ATA-5 +#define ATA_CMD_READ_DMA_EXT 0x25 ///< defined from ATA-6 +#define ATA_CMD_WRITE_DMA 0xca ///< defined from ATA-1 +#define ATA_CMD_WRITE_DMA_WITH_RETRY 0xcb ///< defined from ATA-1, obsoleted from ATA- +#define ATA_CMD_WRITE_DMA_EXT 0x35 ///< defined from ATA-6 + +// +// ATA Security commands +// +#define ATA_CMD_SECURITY_SET_PASSWORD 0xf1 ///< defined in ACS-3 +#define ATA_CMD_SECURITY_UNLOCK 0xf2 ///< defined in ACS-3 +#define ATA_CMD_SECURITY_ERASE_PREPARE 0xf3 ///< defined in ACS-3 +#define ATA_CMD_SECURITY_ERASE_UNIT 0xf4 ///< defined in ACS-3 +#define ATA_CMD_SECURITY_FREEZE_LOCK 0xf5 ///< defined in ACS-3 +#define ATA_CMD_SECURITY_DISABLE_PASSWORD 0xf6 ///< defined in ACS-3 + +#define ATA_SECURITY_BUFFER_LENGTH 512 ///< defined in ACS-3 + +// +// ATA Device Config Overlay +// +#define ATA_CMD_DEV_CONFIG_OVERLAY 0xb1 ///< defined from ATA-6 + #define ATA_CMD_DEV_CONFIG_RESTORE_FEATURE 0xc0 ///< defined from ATA-6 + #define ATA_CMD_DEV_CONFIG_FREEZELOCK_FEATURE 0xc1 ///< defined from ATA-6 + #define ATA_CMD_DEV_CONFIG_IDENTIFY_FEATURE 0xc2 ///< defined from ATA-6 + #define ATA_CMD_DEV_CONFIG_SET_FEATURE 0xc3 ///< defined from ATA-6 + +// +// ATA Trusted Computing Feature Set Commands +// +#define ATA_CMD_TRUSTED_NON_DATA 0x5b ///< defined in ACS-3 +#define ATA_CMD_TRUSTED_RECEIVE 0x5c ///< defined in ACS-3 +#define ATA_CMD_TRUSTED_RECEIVE_DMA 0x5d ///< defined in ACS-3 +#define ATA_CMD_TRUSTED_SEND 0x5e ///< defined in ACS-3 +#define ATA_CMD_TRUSTED_SEND_DMA 0x5f ///< defined in ACS-3 + +// +// ATA Trusted Receive Fields +// +#define ATA_TR_RETURN_SECURITY_PROTOCOL_INFORMATION 0x00 ///< defined in ACS-3 +#define ATA_TR_SECURITY_PROTOCOL_JEDEC_RESERVED 0xec ///< defined in ACS-3 +#define ATA_TR_SECURITY_PROTOCOL_SDCARD_RESERVED 0xed ///< defined in ACS-3 +#define ATA_TR_SECURITY_PROTOCOL_IEEE1667_RESERVED 0xee ///< defined in ACS-3 + +// +// Equates used for Acoustic Flags +// +#define ATA_ACOUSTIC_LEVEL_BYPASS 0xff ///< defined from ATA-6 +#define ATA_ACOUSTIC_LEVEL_MAXIMUM_PERFORMANCE 0xfe ///< defined from ATA-6 +#define ATA_ACOUSTIC_LEVEL_QUIET 0x80 ///< defined from ATA-6 + +// +// Equates used for DiPM Support +// +#define ATA_CMD_DIPM_SUB 0x03 // defined in ACS-3 : Count value in SetFeature identification : 03h Device-initiated interface power state transitions + #define ATA_DIPM_ENABLE 0x10 // defined in ACS-3 + #define ATA_DIPM_DISABLE 0x90 // defined in ACS-3 + +// +// Equates used for DevSleep Support +// +#define ATA_CMD_DEVSLEEP_SUB 0x09 // defined in SATA 3.2 Gold Spec : Count value in SetFeature identification : 09h Device Sleep + #define ATA_DEVSLEEP_ENABLE 0x10 // defined in SATA 3.2 Gold Spec + #define ATA_DEVSLEEP_DISABLE 0x90 // defined in SATA 3.2 Gold Spec + +#define ATA_DEVSLP_EXIT_TIMEOUT 20 // MDAT - 20 ms +#define ATA_DEVSLP_MINIMUM_DETECTION_TIME 10 // DMDT - 10 us +#define ATA_DEVSLP_MINIMUM_ASSERTION_TIME 10 // DETO - 10 ms + +// +// Set MAX Commands +// +#define ATA_CMD_SET_MAX_ADDRESS_EXT 0x37 ///< defined from ATA-6 +#define ATA_CMD_SET_MAX_ADDRESS 0xf9 ///< defined from ATA-6 + #define ATA_SET_MAX_SET_PASSWORD 0x01 ///< defined from ATA-6 + #define ATA_SET_MAX_LOCK 0x02 ///< defined from ATA-6 + #define ATA_SET_MAX_UNLOCK 0x03 ///< defined from ATA-6 + #define ATA_SET_MAX_FREEZE_LOCK 0x04 ///< defined from ATA-6 + +/// +/// Default content of device control register, disable INT, +/// Bit3 is set to 1 according ATA-1 +/// +#define ATA_DEFAULT_CTL (0x0a) +/// +/// Default context of Device/Head Register, +/// Bit7 and Bit5 are set to 1 for back-compatibilities. +/// +#define ATA_DEFAULT_CMD (0xa0) + +#define ATAPI_MAX_BYTE_COUNT (0xfffe) + +#define ATA_REQUEST_SENSE_ERROR (0x70) ///< defined in SFF-8070i + +// +// Sense Key, Additional Sense Codes and Additional Sense Code Qualifier +// defined in MultiMedia Commands (MMC, MMC-2) +// +// Sense Key +// +#define ATA_SK_NO_SENSE (0x0) +#define ATA_SK_RECOVERY_ERROR (0x1) +#define ATA_SK_NOT_READY (0x2) +#define ATA_SK_MEDIUM_ERROR (0x3) +#define ATA_SK_HARDWARE_ERROR (0x4) +#define ATA_SK_ILLEGAL_REQUEST (0x5) +#define ATA_SK_UNIT_ATTENTION (0x6) +#define ATA_SK_DATA_PROTECT (0x7) +#define ATA_SK_BLANK_CHECK (0x8) +#define ATA_SK_VENDOR_SPECIFIC (0x9) +#define ATA_SK_RESERVED_A (0xA) +#define ATA_SK_ABORT (0xB) +#define ATA_SK_RESERVED_C (0xC) +#define ATA_SK_OVERFLOW (0xD) +#define ATA_SK_MISCOMPARE (0xE) +#define ATA_SK_RESERVED_F (0xF) + +// +// Additional Sense Codes +// +#define ATA_ASC_NOT_READY (0x04) +#define ATA_ASC_MEDIA_ERR1 (0x10) +#define ATA_ASC_MEDIA_ERR2 (0x11) +#define ATA_ASC_MEDIA_ERR3 (0x14) +#define ATA_ASC_MEDIA_ERR4 (0x30) +#define ATA_ASC_MEDIA_UPSIDE_DOWN (0x06) +#define ATA_ASC_INVALID_CMD (0x20) +#define ATA_ASC_LBA_OUT_OF_RANGE (0x21) +#define ATA_ASC_INVALID_FIELD (0x24) +#define ATA_ASC_WRITE_PROTECTED (0x27) +#define ATA_ASC_MEDIA_CHANGE (0x28) +#define ATA_ASC_RESET (0x29) ///< Power On Reset or Bus Reset occurred. +#define ATA_ASC_ILLEGAL_FIELD (0x26) +#define ATA_ASC_NO_MEDIA (0x3A) +#define ATA_ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64) + +// +// Additional Sense Code Qualifier +// +#define ATA_ASCQ_IN_PROGRESS (0x01) + +// +// Error Register +// +#define ATA_ERRREG_BBK BIT7 ///< Bad block detected defined from ATA-1, obsoleted from ATA-2 +#define ATA_ERRREG_UNC BIT6 ///< Uncorrectable Data defined from ATA-1, obsoleted from ATA-4 +#define ATA_ERRREG_MC BIT5 ///< Media Change defined from ATA-1, obsoleted from ATA-4 +#define ATA_ERRREG_IDNF BIT4 ///< ID Not Found defined from ATA-1, obsoleted from ATA-4 +#define ATA_ERRREG_MCR BIT3 ///< Media Change Requested defined from ATA-1, obsoleted from ATA-4 +#define ATA_ERRREG_ABRT BIT2 ///< Aborted Command defined from ATA-1 +#define ATA_ERRREG_TK0NF BIT1 ///< Track 0 Not Found defined from ATA-1, obsoleted from ATA-4 +#define ATA_ERRREG_AMNF BIT0 ///< Address Mark Not Found defined from ATA-1, obsoleted from ATA-4 + +// +// Status Register +// +#define ATA_STSREG_BSY BIT7 ///< Controller Busy defined from ATA-1 +#define ATA_STSREG_DRDY BIT6 ///< Drive Ready defined from ATA-1 +#define ATA_STSREG_DWF BIT5 ///< Drive Write Fault defined from ATA-1, obsoleted from ATA-4 +#define ATA_STSREG_DF BIT5 ///< Drive Fault defined from ATA-6 +#define ATA_STSREG_DSC BIT4 ///< Disk Seek Complete defined from ATA-1, obsoleted from ATA-4 +#define ATA_STSREG_DRQ BIT3 ///< Data Request defined from ATA-1 +#define ATA_STSREG_CORR BIT2 ///< Corrected Data defined from ATA-1, obsoleted from ATA-4 +#define ATA_STSREG_IDX BIT1 ///< Index defined from ATA-1, obsoleted from ATA-4 +#define ATA_STSREG_ERR BIT0 ///< Error defined from ATA-1 + +// +// Device Control Register +// +#define ATA_CTLREG_SRST BIT2 ///< Software Reset. +#define ATA_CTLREG_IEN_L BIT1 ///< Interrupt Enable #. + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bluetooth.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bluetooth.h new file mode 100644 index 0000000..f0b6db1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bluetooth.h @@ -0,0 +1,62 @@ +/** @file + This file contains the Bluetooth definitions that are consumed by drivers. + These definitions are from Bluetooth Core Specification Version 4.0 June, 2010 + + Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BLUETOOTH_H_ +#define _BLUETOOTH_H_ + +#pragma pack(1) + +/// +/// BLUETOOTH_ADDRESS +/// +typedef struct { + /// + /// 48bit Bluetooth device address. + /// + UINT8 Address[6]; +} BLUETOOTH_ADDRESS; + +/// +/// BLUETOOTH_CLASS_OF_DEVICE. See Bluetooth specification for detail. +/// +typedef struct { + UINT8 FormatType:2; + UINT8 MinorDeviceClass: 6; + UINT16 MajorDeviceClass: 5; + UINT16 MajorServiceClass:11; +} BLUETOOTH_CLASS_OF_DEVICE; + +/// +/// BLUETOOTH_LE_ADDRESS +/// +typedef struct { + /// + /// 48-bit Bluetooth device address + /// + UINT8 Address[6]; + /// + /// 0x00 - Public Device Address + /// 0x01 - Random Device Address + /// + UINT8 Type; +} BLUETOOTH_LE_ADDRESS; + +#pragma pack() + +#define BLUETOOTH_HCI_COMMAND_LOCAL_READABLE_NAME_MAX_SIZE 248 + +#define BLUETOOTH_HCI_LINK_KEY_SIZE 16 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bmp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bmp.h new file mode 100644 index 0000000..2539391 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Bmp.h @@ -0,0 +1,48 @@ +/** @file + This file defines BMP file header data structures. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BMP_H_ +#define _BMP_H_ + +#pragma pack(1) + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} BMP_COLOR_MAP; + +typedef struct { + CHAR8 CharB; + CHAR8 CharM; + UINT32 Size; + UINT16 Reserved[2]; + UINT32 ImageOffset; + UINT32 HeaderSize; + UINT32 PixelWidth; + UINT32 PixelHeight; + UINT16 Planes; ///< Must be 1 + UINT16 BitPerPixel; ///< 1, 4, 8, or 24 + UINT32 CompressionType; + UINT32 ImageSize; ///< Compressed image size in bytes + UINT32 XPixelsPerMeter; + UINT32 YPixelsPerMeter; + UINT32 NumberOfColors; + UINT32 ImportantColors; +} BMP_IMAGE_HEADER; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPort2Table.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPort2Table.h new file mode 100644 index 0000000..cfd1238 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPort2Table.h @@ -0,0 +1,79 @@ +/** @file + ACPI debug port 2 table definition, defined at + Microsoft DebugPort2Specification. + + Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2016, ARM Limited. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _DEBUG_PORT_2_TABLE_H_ +#define _DEBUG_PORT_2_TABLE_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +// +// Debug Device Information structure. +// +typedef struct { + UINT8 Revision; + UINT16 Length; + UINT8 NumberofGenericAddressRegisters; + UINT16 NameSpaceStringLength; + UINT16 NameSpaceStringOffset; + UINT16 OemDataLength; + UINT16 OemDataOffset; + UINT16 PortType; + UINT16 PortSubtype; + UINT8 Reserved[2]; + UINT16 BaseAddressRegisterOffset; + UINT16 AddressSizeOffset; +} EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT; + +#define EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION 0x00 + +#define EFI_ACPI_DBG2_PORT_TYPE_SERIAL 0x8000 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550 0x0000 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_16550_SUBSET_COMPATIBLE_WITH_MS_DBGP_SPEC 0x0001 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART 0x0003 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X 0x000d +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART 0x000e +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC 0x000f +#define EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_BCM2835_UART 0x0010 +#define EFI_ACPI_DBG2_PORT_TYPE_1394 0x8001 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_1394_STANDARD 0x0000 +#define EFI_ACPI_DBG2_PORT_TYPE_USB 0x8002 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_USB_XHCI 0x0000 +#define EFI_ACPI_DBG2_PORT_SUBTYPE_USB_EHCI 0x0001 +#define EFI_ACPI_DBG2_PORT_TYPE_NET 0x8003 + +// +// Debug Port 2 Table definition. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 OffsetDbgDeviceInfo; + UINT32 NumberDbgDeviceInfo; +} EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE; + +#pragma pack() + +// +// DBG2 Revision (defined in spec) +// +#define EFI_ACPI_DEBUG_PORT_2_TABLE_REVISION 0x00 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPortTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPortTable.h new file mode 100644 index 0000000..1393a78 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DebugPortTable.h @@ -0,0 +1,50 @@ +/** @file + ACPI debug port table definition, defined at + Microsoft DebugPortSpecification. + + Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _DEBUG_PORT_TABLE_H_ +#define _DEBUG_PORT_TABLE_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +// +// Debug Port Table definition. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 InterfaceType; + UINT8 Reserved_37[3]; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE BaseAddress; +} EFI_ACPI_DEBUG_PORT_DESCRIPTION_TABLE; + +#pragma pack() + +// +// DBGP Revision (defined in spec) +// +#define EFI_ACPI_DEBUG_PORT_TABLE_REVISION 0x01 + +// +// Interface Type +// +#define EFI_ACPI_DBGP_INTERFACE_TYPE_FULL_16550 0 +#define EFI_ACPI_DBGP_INTERFACE_TYPE_16550_SUBSET_COMPATIBLE_WITH_MS_DBGP_SPEC 1 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Dhcp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Dhcp.h new file mode 100644 index 0000000..9f09753 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Dhcp.h @@ -0,0 +1,282 @@ +/** @file + This file contains the DHCPv4 and DHCPv6 option definitions and other configuration. + They are used to carry additional information and parameters in DHCP messages. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _DHCP_H_ +#define _DHCP_H_ + +/// +/// Dynamic Host Configuration Protocol for IPv4 (DHCPv4) +/// +/// Dhcpv4 Options, definitions from RFC 2132 +/// +#define DHCP4_TAG_PAD 0 /// Pad Option +#define DHCP4_TAG_EOP 255 /// End Option +#define DHCP4_TAG_NETMASK 1 /// Subnet Mask +#define DHCP4_TAG_TIME_OFFSET 2 /// Time Offset from UTC +#define DHCP4_TAG_ROUTER 3 /// Router option, +#define DHCP4_TAG_TIME_SERVER 4 /// Time Server +#define DHCP4_TAG_NAME_SERVER 5 /// Name Server +#define DHCP4_TAG_DNS_SERVER 6 /// Domain Name Server +#define DHCP4_TAG_LOG_SERVER 7 /// Log Server +#define DHCP4_TAG_COOKIE_SERVER 8 /// Cookie Server +#define DHCP4_TAG_LPR_SERVER 9 /// LPR Print Server +#define DHCP4_TAG_IMPRESS_SERVER 10 /// Impress Server +#define DHCP4_TAG_RL_SERVER 11 /// Resource Location Server +#define DHCP4_TAG_HOSTNAME 12 /// Host Name +#define DHCP4_TAG_BOOTFILE_LEN 13 /// Boot File Size +#define DHCP4_TAG_DUMP 14 /// Merit Dump File +#define DHCP4_TAG_DOMAINNAME 15 /// Domain Name +#define DHCP4_TAG_SWAP_SERVER 16 /// Swap Server +#define DHCP4_TAG_ROOTPATH 17 /// Root path +#define DHCP4_TAG_EXTEND_PATH 18 /// Extensions Path +#define DHCP4_TAG_IPFORWARD 19 /// IP Forwarding Enable/Disable +#define DHCP4_TAG_NONLOCAL_SRR 20 /// on-Local Source Routing Enable/Disable +#define DHCP4_TAG_POLICY_SRR 21 /// Policy Filter +#define DHCP4_TAG_EMTU 22 /// Maximum Datagram Reassembly Size +#define DHCP4_TAG_TTL 23 /// Default IP Time-to-live +#define DHCP4_TAG_PATHMTU_AGE 24 /// Path MTU Aging Timeout +#define DHCP4_TAG_PATHMTU_PLATEAU 25 /// Path MTU Plateau Table +#define DHCP4_TAG_IFMTU 26 /// Interface MTU +#define DHCP4_TAG_SUBNET_LOCAL 27 /// All Subnets are Local +#define DHCP4_TAG_BROADCAST 28 /// Broadcast Address +#define DHCP4_TAG_DISCOVER_MASK 29 /// Perform Mask Discovery +#define DHCP4_TAG_SUPPLY_MASK 30 /// Mask Supplier +#define DHCP4_TAG_DISCOVER_ROUTE 31 /// Perform Router Discovery +#define DHCP4_TAG_ROUTER_SOLICIT 32 /// Router Solicitation Address +#define DHCP4_TAG_STATIC_ROUTE 33 /// Static Route +#define DHCP4_TAG_TRAILER 34 /// Trailer Encapsulation +#define DHCP4_TAG_ARPAGE 35 /// ARP Cache Timeout +#define DHCP4_TAG_ETHER_ENCAP 36 /// Ethernet Encapsulation +#define DHCP4_TAG_TCP_TTL 37 /// TCP Default TTL +#define DHCP4_TAG_KEEP_INTERVAL 38 /// TCP Keepalive Interval +#define DHCP4_TAG_KEEP_GARBAGE 39 /// TCP Keepalive Garbage +#define DHCP4_TAG_NIS_DOMAIN 40 /// Network Information Service Domain +#define DHCP4_TAG_NIS_SERVER 41 /// Network Information Servers +#define DHCP4_TAG_NTP_SERVER 42 /// Network Time Protocol Servers +#define DHCP4_TAG_VENDOR 43 /// Vendor Specific Information +#define DHCP4_TAG_NBNS 44 /// NetBIOS over TCP/IP Name Server +#define DHCP4_TAG_NBDD 45 /// NetBIOS Datagram Distribution Server +#define DHCP4_TAG_NBTYPE 46 /// NetBIOS over TCP/IP Node Type +#define DHCP4_TAG_NBSCOPE 47 /// NetBIOS over TCP/IP Scope +#define DHCP4_TAG_XFONT 48 /// X Window System Font Server +#define DHCP4_TAG_XDM 49 /// X Window System Display Manager +#define DHCP4_TAG_REQUEST_IP 50 /// Requested IP Address +#define DHCP4_TAG_LEASE 51 /// IP Address Lease Time +#define DHCP4_TAG_OVERLOAD 52 /// Option Overload +#define DHCP4_TAG_MSG_TYPE 53 /// DHCP Message Type +#define DHCP4_TAG_SERVER_ID 54 /// Server Identifier +#define DHCP4_TAG_PARA_LIST 55 /// Parameter Request List +#define DHCP4_TAG_MESSAGE 56 /// Message +#define DHCP4_TAG_MAXMSG 57 /// Maximum DHCP Message Size +#define DHCP4_TAG_T1 58 /// Renewal (T1) Time Value +#define DHCP4_TAG_T2 59 /// Rebinding (T2) Time Value +#define DHCP4_TAG_VENDOR_CLASS_ID 60 /// Vendor class identifier +#define DHCP4_TAG_CLIENT_ID 61 /// Client-identifier +#define DHCP4_TAG_NISPLUS 64 /// Network Information Service+ Domain +#define DHCP4_TAG_NISPLUS_SERVER 65 /// Network Information Service+ Servers +#define DHCP4_TAG_TFTP 66 /// TFTP server name +#define DHCP4_TAG_BOOTFILE 67 /// Bootfile name +#define DHCP4_TAG_MOBILEIP 68 /// Mobile IP Home Agent +#define DHCP4_TAG_SMTP 69 /// Simple Mail Transport Protocol Server +#define DHCP4_TAG_POP3 70 /// Post Office Protocol (POP3) Server +#define DHCP4_TAG_NNTP 71 /// Network News Transport Protocol Server +#define DHCP4_TAG_WWW 72 /// Default World Wide Web (WWW) Server +#define DHCP4_TAG_FINGER 73 /// Default Finger Server +#define DHCP4_TAG_IRC 74 /// Default Internet Relay Chat (IRC) Server +#define DHCP4_TAG_STTALK 75 /// StreetTalk Server +#define DHCP4_TAG_STDA 76 /// StreetTalk Directory Assistance Server +#define DHCP4_TAG_USER_CLASS_ID 77 /// User class identifier +#define DHCP4_TAG_ARCH 93 /// Client System Architecture Type, RFC 4578 +#define DHCP4_TAG_UNDI 94 /// Client Network Interface Identifier, RFC 4578 +#define DHCP4_TAG_UUID 97 /// Client Machine Identifier, RFC 4578 +#define DHCP4_TAG_CLASSLESS_ROUTE 121 /// Classless Route + + +/// +/// Dynamic Host Configuration Protocol for IPv6 (DHCPv6) +/// +/// Enumeration of Dhcp6 message type, refers to section-5.3 of rfc-3315. +/// +typedef enum { + Dhcp6MsgSolicit = 1, + Dhcp6MsgAdvertise = 2, + Dhcp6MsgRequest = 3, + Dhcp6MsgConfirm = 4, + Dhcp6MsgRenew = 5, + Dhcp6MsgRebind = 6, + Dhcp6MsgReply = 7, + Dhcp6MsgRelease = 8, + Dhcp6MsgDecline = 9, + Dhcp6MsgReconfigure = 10, + Dhcp6MsgInfoRequest = 11 +} DHCP6_MSG_TYPE; + +/// +/// Enumeration of option code in Dhcp6 packet, refers to section-24.3 of rfc-3315. +/// +typedef enum { + Dhcp6OptClientId = 1, + Dhcp6OptServerId = 2, + Dhcp6OptIana = 3, + Dhcp6OptIata = 4, + Dhcp6OptIaAddr = 5, + Dhcp6OptRequestOption = 6, + Dhcp6OptPreference = 7, + Dhcp6OptElapsedTime = 8, + Dhcp6OptReplayMessage = 9, + Dhcp6OptAuthentication = 11, + Dhcp6OptServerUnicast = 12, + Dhcp6OptStatusCode = 13, + Dhcp6OptRapidCommit = 14, + Dhcp6OptUserClass = 15, + Dhcp6OptVendorClass = 16, + Dhcp6OptVendorInfo = 17, + Dhcp6OptInterfaceId = 18, + Dhcp6OptReconfigMessage = 19, + Dhcp6OptReconfigureAccept = 20 +} DHCP6_OPT_CODE; + +/// +/// Enumeration of status code recorded by IANA, refers to section-24.4 of rfc-3315. +/// +typedef enum { + Dhcp6StsSuccess = 0, + Dhcp6StsUnspecFail = 1, + Dhcp6StsNoAddrsAvail = 2, + Dhcp6StsNoBinding = 3, + Dhcp6StsNotOnLink = 4, + Dhcp6StsUseMulticast = 5 +} DHCP6_STS_CODE; + +/// +/// Enumeration of Duid type recorded by IANA, refers to section-24.5 of rfc-3315. +/// +typedef enum { + Dhcp6DuidTypeLlt = 1, + Dhcp6DuidTypeEn = 2, + Dhcp6DuidTypeLl = 3, + Dhcp6DuidTypeUuid = 4 +} DHCP6_DUID_TYPE; + +/// Transmission and Retransmission Parameters +/// This section presents a table of values used to describe the message +/// transmission behavior of clients and servers. +/// +/// Transmit parameters of solicit message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_SOL_MAX_DELAY 1 +#define DHCP6_SOL_IRT 1 +#define DHCP6_SOL_MRC 0 +#define DHCP6_SOL_MRT 120 +#define DHCP6_SOL_MRD 0 +/// +/// Transmit parameters of request message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_REQ_IRT 1 +#define DHCP6_REQ_MRC 10 +#define DHCP6_REQ_MRT 30 +#define DHCP6_REQ_MRD 0 +/// +/// Transmit parameters of confirm message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_CNF_MAX_DELAY 1 +#define DHCP6_CNF_IRT 1 +#define DHCP6_CNF_MRC 0 +#define DHCP6_CNF_MRT 4 +#define DHCP6_CNF_MRD 10 +/// +/// Transmit parameters of renew message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_REN_IRT 10 +#define DHCP6_REN_MRC 0 +#define DHCP6_REN_MRT 600 +#define DHCP6_REN_MRD 0 +/// +/// Transmit parameters of rebind message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_REB_IRT 10 +#define DHCP6_REB_MRC 0 +#define DHCP6_REB_MRT 600 +#define DHCP6_REB_MRD 0 +/// +/// Transmit parameters of information request message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_INF_MAX_DELAY 1 +#define DHCP6_INF_IRT 1 +#define DHCP6_INF_MRC 0 +#define DHCP6_INF_MRT 120 +#define DHCP6_INF_MRD 0 +/// +/// Transmit parameters of release message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_REL_IRT 1 +#define DHCP6_REL_MRC 5 +#define DHCP6_REL_MRT 0 +#define DHCP6_REL_MRD 0 +/// +/// Transmit parameters of decline message, refers to section-5.5 of rfc-3315. +/// +#define DHCP6_DEC_IRT 1 +#define DHCP6_DEC_MRC 5 +#define DHCP6_DEC_MRT 0 +#define DHCP6_DEC_MRD 0 + +//// +//// DHCPv6 Options, definitions from RFC 3315,RFC 5970 and RFC 3646. +//// +#define DHCP6_OPT_CLIENT_ID 1 /// Client Identifier Option +#define DHCP6_OPT_SERVER_ID 2 /// Server Identifier Option +#define DHCP6_OPT_IA_NA 3 /// The Identity Association for Non-temporary Addresses option +#define DHCP6_OPT_IA_TA 4 /// The Identity Association for the Temporary Addresses +#define DHCP6_OPT_IAADDR 5 /// IA Address option +#define DHCP6_OPT_ORO 6 /// Request option +#define DHCP6_OPT_PREFERENCE 7 /// Preference option +#define DHCP6_OPT_ELAPSED_TIME 8 /// Elapsed Time Option +#define DHCP6_OPT_REPLAY_MSG 9 /// Relay Message option +#define DHCP6_OPT_AUTH 11 /// Authentication option +#define DHCP6_OPT_UNICAST 12 /// Server Unicast Option +#define DHCP6_OPT_STATUS_CODE 13 /// Status Code Option +#define DHCP6_OPT_RAPID_COMMIT 14 /// Rapid Commit option +#define DHCP6_OPT_USER_CLASS 15 /// User Class option +#define DHCP6_OPT_VENDOR_CLASS 16 /// Vendor Class Option +#define DHCP6_OPT_VENDOR_OPTS 17 /// Vendor-specific Information Option +#define DHCP6_OPT_INTERFACE_ID 18 /// Interface-Id Option +#define DHCP6_OPT_RECONFIG_MSG 19 /// Reconfigure Message Option +#define DHCP6_OPT_RECONFIG_ACCEPT 20 /// Reconfigure Accept Option +#define DHCP6_OPT_DNS_SERVERS 23 /// DNS Configuration options, RFC 3646 +#define DHCP6_OPT_BOOT_FILE_URL 59 /// Assigned by IANA, RFC 5970 +#define DHCP6_OPT_BOOT_FILE_PARAM 60 /// Assigned by IANA, RFC 5970 +#define DHCP6_OPT_ARCH 61 /// Assigned by IANA, RFC 5970 +#define DHCP6_OPT_UNDI 62 /// Assigned by IANA, RFC 5970 + +/// +/// Processor Architecture Types +/// These identifiers are defined by IETF: +/// http://www.ietf.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml +/// +#define PXE_CLIENT_ARCH_X86_BIOS 0x0000 /// x86 BIOS for PXE +#define PXE_CLIENT_ARCH_IPF 0x0002 /// Itanium for PXE +#define PXE_CLIENT_ARCH_IA32 0x0006 /// x86 uefi for PXE +#define PXE_CLIENT_ARCH_X64 0x0007 /// x64 uefi for PXE +#define PXE_CLIENT_ARCH_EBC 0x0009 /// EBC for PXE +#define PXE_CLIENT_ARCH_ARM 0x000A /// Arm uefi 32 for PXE +#define PXE_CLIENT_ARCH_AARCH64 0x000B /// Arm uefi 64 for PXE + +#define HTTP_CLIENT_ARCH_IA32 0x000F /// x86 uefi boot from http +#define HTTP_CLIENT_ARCH_X64 0x0010 /// x64 uefi boot from http +#define HTTP_CLIENT_ARCH_EBC 0x0011 /// EBC boot from http +#define HTTP_CLIENT_ARCH_ARM 0x0012 /// Arm uefi 32 boot from http +#define HTTP_CLIENT_ARCH_AARCH64 0x0013 /// Arm uefi 64 boot from http + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h new file mode 100644 index 0000000..0b87ad2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h @@ -0,0 +1,269 @@ +/** @file + DMA Remapping Reporting (DMAR) ACPI table definition from Intel(R) + Virtualization Technology for Directed I/O (VT-D) Architecture Specification. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - Intel(R) Virtualization Technology for Directed I/O (VT-D) Architecture + Specification v2.5, Dated November 2017. + http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/vt-directed-io-spec.pdf + + @par Glossary: + - HPET - High Precision Event Timer + - NUMA - Non-uniform Memory Access +**/ +#ifndef _DMA_REMAPPING_REPORTING_TABLE_H_ +#define _DMA_REMAPPING_REPORTING_TABLE_H_ + +#include + +#pragma pack(1) + +/// +/// DMA-Remapping Reporting Structure definitions from section 8.1 +///@{ +#define EFI_ACPI_DMAR_REVISION 0x01 + +#define EFI_ACPI_DMAR_FLAGS_INTR_REMAP BIT0 +#define EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT BIT1 +#define EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG BIT2 +///@} + +/// +/// Remapping Structure Types definitions from section 8.2 +///@{ +#define EFI_ACPI_DMAR_TYPE_DRHD 0x00 +#define EFI_ACPI_DMAR_TYPE_RMRR 0x01 +#define EFI_ACPI_DMAR_TYPE_ATSR 0x02 +#define EFI_ACPI_DMAR_TYPE_RHSA 0x03 +#define EFI_ACPI_DMAR_TYPE_ANDD 0x04 +///@} + +/// +/// DMA-Remapping Hardware Unit definitions from section 8.3 +/// +#define EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL BIT0 + +/// +/// DMA-Remapping Device Scope Entry Structure definitions from section 8.3.1 +///@{ +#define EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT 0x01 +#define EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE 0x02 +#define EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC 0x03 +#define EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET 0x04 +#define EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE 0x05 +///@} + +/// +/// Root Port ATS Capability Reporting Structure definitions from section 8.5 +/// +#define EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS BIT0 + +/// +/// Definition for DMA Remapping Structure Header +/// +typedef struct { + UINT16 Type; + UINT16 Length; +} EFI_ACPI_DMAR_STRUCTURE_HEADER; + +/// +/// Definition for DMA-Remapping PCI Path +/// +typedef struct { + UINT8 Device; + UINT8 Function; +} EFI_ACPI_DMAR_PCI_PATH; + +/// +/// Device Scope Structure is defined in section 8.3.1 +/// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved2; + UINT8 EnumerationId; + UINT8 StartBusNumber; +} EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER; + +/** + DMA-remapping hardware unit definition (DRHD) structure is defined in + section 8.3. This uniquely represents a remapping hardware unit present + in the platform. There must be at least one instance of this structure + for each PCI segment in the platform. +**/ +typedef struct { + EFI_ACPI_DMAR_STRUCTURE_HEADER Header; + /** + - Bit[0]: INCLUDE_PCI_ALL + - If Set, this remapping hardware unit has under its scope all + PCI compatible devices in the specified Segment, except devices + reported under the scope of other remapping hardware units for + the same Segment. + - If Clear, this remapping hardware unit has under its scope only + devices in the specified Segment that are explicitly identified + through the DeviceScope field. + - Bits[7:1] Reserved. + **/ + UINT8 Flags; + UINT8 Reserved; + /// + /// The PCI Segment associated with this unit. + /// + UINT16 SegmentNumber; + /// + /// Base address of remapping hardware register-set for this unit. + /// + UINT64 RegisterBaseAddress; +} EFI_ACPI_DMAR_DRHD_HEADER; + +/** + Reserved Memory Region Reporting Structure (RMRR) is described in section 8.4 + Reserved memory ranges that may be DMA targets may be reported through the + RMRR structures, along with the devices that requires access to the specified + reserved memory region. +**/ +typedef struct { + EFI_ACPI_DMAR_STRUCTURE_HEADER Header; + UINT8 Reserved[2]; + /// + /// PCI Segment Number associated with devices identified through + /// the Device Scope field. + /// + UINT16 SegmentNumber; + /// + /// Base address of 4KB-aligned reserved memory region + /// + UINT64 ReservedMemoryRegionBaseAddress; + /** + Last address of the reserved memory region. Value in this field must be + greater than the value in Reserved Memory Region Base Address field. + The reserved memory region size (Limit - Base + 1) must be an integer + multiple of 4KB. + **/ + UINT64 ReservedMemoryRegionLimitAddress; +} EFI_ACPI_DMAR_RMRR_HEADER; + +/** + Root Port ATS Capability Reporting (ATSR) structure is defined in section 8.5. + This structure is applicable only for platforms supporting Device-TLBs as + reported through the Extended Capability Register. For each PCI Segment in + the platform that supports Device-TLBs, BIOS provides an ATSR structure. The + ATSR structures identifies PCI-Express Root-Ports supporting Address + Translation Services (ATS) transactions. Software must enable ATS on endpoint + devices behind a Root Port only if the Root Port is reported as supporting + ATS transactions. +**/ +typedef struct { + EFI_ACPI_DMAR_STRUCTURE_HEADER Header; + /** + - Bit[0]: ALL_PORTS: + - If Set, indicates all PCI Express Root Ports in the specified + PCI Segment supports ATS transactions. + - If Clear, indicates ATS transactions are supported only on + Root Ports identified through the Device Scope field. + - Bits[7:1] Reserved. + **/ + UINT8 Flags; + UINT8 Reserved; + /// + /// The PCI Segment associated with this ATSR structure + /// + UINT16 SegmentNumber; +} EFI_ACPI_DMAR_ATSR_HEADER; + +/** + Remapping Hardware Static Affinity (RHSA) is an optional structure defined + in section 8.6. This is intended to be used only on NUMA platforms with + Remapping hardware units and memory spanned across multiple nodes. + When used, there must be a RHSA structure for each Remapping hardware unit + reported through DRHD structure. +**/ +typedef struct { + EFI_ACPI_DMAR_STRUCTURE_HEADER Header; + UINT8 Reserved[4]; + /// + /// Register Base Address of this Remap hardware unit reported in the + /// corresponding DRHD structure. + /// + UINT64 RegisterBaseAddress; + /// + /// Proximity Domain to which the Remap hardware unit identified by the + /// Register Base Address field belongs. + /// + UINT32 ProximityDomain; +} EFI_ACPI_DMAR_RHSA_HEADER; + +/** + An ACPI Name-space Device Declaration (ANDD) structure is defined in section + 8.7 and uniquely represents an ACPI name-space enumerated device capable of + issuing DMA requests in the platform. ANDD structures are used in conjunction + with Device-Scope entries of type ACPI_NAMESPACE_DEVICE. +**/ +typedef struct { + EFI_ACPI_DMAR_STRUCTURE_HEADER Header; + UINT8 Reserved[3]; + /** + Each ACPI device enumerated through an ANDD structure must have a unique + value for this field. To report an ACPI device with ACPI Device Number + value of X, under the scope of a DRHD unit, a Device-Scope entry of type + ACPI_NAMESPACE_DEVICE is used with value of X in the Enumeration ID field. + The Start Bus Number and Path fields in the Device-Scope together + provides the 16-bit source-id allocated by platform for the ACPI device. + **/ + UINT8 AcpiDeviceNumber; +} EFI_ACPI_DMAR_ANDD_HEADER; + +/** + DMA Remapping Reporting Structure Header as defined in section 8.1 + This header will be followed by list of Remapping Structures listed below + - DMA Remapping Hardware Unit Definition (DRHD) + - Reserved Memory Region Reporting (RMRR) + - Root Port ATS Capability Reporting (ATSR) + - Remapping Hardware Static Affinity (RHSA) + - ACPI Name-space Device Declaration (ANDD) + These structure types must by reported in numerical order. + i.e., All remapping structures of type 0 (DRHD) enumerated before remapping + structures of type 1 (RMRR), and so forth. +**/ +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /** + This field indicates the maximum DMA physical addressability supported by + this platform. The system address map reported by the BIOS indicates what + portions of this addresses are populated. The Host Address Width (HAW) of + the platform is computed as (N+1), where N is the value reported in this + field. + For example, for a platform supporting 40 bits of physical addressability, + the value of 100111b is reported in this field. + **/ + UINT8 HostAddressWidth; + /** + - Bit[0]: INTR_REMAP - If Clear, the platform does not support interrupt + remapping. If Set, the platform supports interrupt remapping. + - Bit[1]: X2APIC_OPT_OUT - For firmware compatibility reasons, platform + firmware may Set this field to request system software to opt + out of enabling Extended xAPIC (X2APIC) mode. This field is + valid only when the INTR_REMAP field (bit 0) is Set. + - Bit[2]: DMA_CTRL_PLATFORM_OPT_IN_FLAG - Platform firmware is + recommended to Set this field to report any platform initiated + DMA is restricted to only reserved memory regions (reported in + RMRR structures) when transferring control to system software + such as on ExitBootServices(). + - Bits[7:3] Reserved. + **/ + UINT8 Flags; + UINT8 Reserved[10]; +} EFI_ACPI_DMAR_HEADER; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ElTorito.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ElTorito.h new file mode 100644 index 0000000..b213d31 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ElTorito.h @@ -0,0 +1,147 @@ +/** @file + ElTorito Partitions Format Definition. + This file includes some defintions from + 1. "El Torito" Bootable CD-ROM Format Specification, Version 1.0. + 2. Volume and File Structure of CDROM for Information Interchange, + Standard ECMA-119. (IS0 9660) + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ELTORITO_H_ +#define _ELTORITO_H_ + +// +// CDROM_VOLUME_DESCRIPTOR.Types, defined in ISO 9660 +// +#define CDVOL_TYPE_STANDARD 0x0 +#define CDVOL_TYPE_CODED 0x1 +#define CDVOL_TYPE_END 0xFF + +/// +/// CDROM_VOLUME_DESCRIPTOR.Id +/// +#define CDVOL_ID "CD001" + +/// +/// CDROM_VOLUME_DESCRIPTOR.SystemId +/// +#define CDVOL_ELTORITO_ID "EL TORITO SPECIFICATION" + +// +// Indicator types +// +#define ELTORITO_ID_CATALOG 0x01 +#define ELTORITO_ID_SECTION_BOOTABLE 0x88 +#define ELTORITO_ID_SECTION_NOT_BOOTABLE 0x00 +#define ELTORITO_ID_SECTION_HEADER 0x90 +#define ELTORITO_ID_SECTION_HEADER_FINAL 0x91 + +// +// ELTORITO_CATALOG.Boot.MediaTypes +// +#define ELTORITO_NO_EMULATION 0x00 +#define ELTORITO_12_DISKETTE 0x01 +#define ELTORITO_14_DISKETTE 0x02 +#define ELTORITO_28_DISKETTE 0x03 +#define ELTORITO_HARD_DISK 0x04 + + +#pragma pack(1) + +/// +/// CD-ROM Volume Descriptor +/// +typedef union { + struct { + UINT8 Type; + CHAR8 Id[5]; ///< "CD001" + CHAR8 Reserved[82]; + } Unknown; + + /// + /// Boot Record Volume Descriptor, defined in "El Torito" Specification. + /// + struct { + UINT8 Type; ///< Must be 0 + CHAR8 Id[5]; ///< "CD001" + UINT8 Version; ///< Must be 1 + CHAR8 SystemId[32]; ///< "EL TORITO SPECIFICATION" + CHAR8 Unused[32]; ///< Must be 0 + UINT8 EltCatalog[4]; ///< Absolute pointer to first sector of Boot Catalog + CHAR8 Unused2[13]; ///< Must be 0 + } BootRecordVolume; + + /// + /// Primary Volumn Descriptor, defined in ISO 9660. + /// + struct { + UINT8 Type; + CHAR8 Id[5]; ///< "CD001" + UINT8 Version; + UINT8 Unused; ///< Must be 0 + CHAR8 SystemId[32]; + CHAR8 VolumeId[32]; + UINT8 Unused2[8]; ///< Must be 0 + UINT32 VolSpaceSize[2]; ///< the number of Logical Blocks + } PrimaryVolume; + +} CDROM_VOLUME_DESCRIPTOR; + +/// +/// Catalog Entry +/// +typedef union { + struct { + CHAR8 Reserved[0x20]; + } Unknown; + + /// + /// Catalog validation entry (Catalog header) + /// + struct { + UINT8 Indicator; ///< Must be 01 + UINT8 PlatformId; + UINT16 Reserved; + CHAR8 ManufacId[24]; + UINT16 Checksum; + UINT16 Id55AA; + } Catalog; + + /// + /// Initial/Default Entry or Section Entry + /// + struct { + UINT8 Indicator; ///< 88 = Bootable, 00 = Not Bootable + UINT8 MediaType : 4; + UINT8 Reserved1 : 4; ///< Must be 0 + UINT16 LoadSegment; + UINT8 SystemType; + UINT8 Reserved2; ///< Must be 0 + UINT16 SectorCount; + UINT32 Lba; + } Boot; + + /// + /// Section Header Entry + /// + struct { + UINT8 Indicator; ///< 90 - Header, more header follw, 91 - Final Header + UINT8 PlatformId; + UINT16 SectionEntries; ///< Number of section entries following this header + CHAR8 Id[28]; + } Section; + +} ELTORITO_CATALOG; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Emmc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Emmc.h new file mode 100644 index 0000000..ad0ca55 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Emmc.h @@ -0,0 +1,297 @@ +/** @file + Header file for eMMC support. + + This header file contains some definitions defined in EMMC4.5/EMMC5.0 spec. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EMMC_H__ +#define __EMMC_H__ + +// +// EMMC command index +// +#define EMMC_GO_IDLE_STATE 0 +#define EMMC_SEND_OP_COND 1 +#define EMMC_ALL_SEND_CID 2 +#define EMMC_SET_RELATIVE_ADDR 3 +#define EMMC_SET_DSR 4 +#define EMMC_SLEEP_AWAKE 5 +#define EMMC_SWITCH 6 +#define EMMC_SELECT_DESELECT_CARD 7 +#define EMMC_SEND_EXT_CSD 8 +#define EMMC_SEND_CSD 9 +#define EMMC_SEND_CID 10 +#define EMMC_STOP_TRANSMISSION 12 +#define EMMC_SEND_STATUS 13 +#define EMMC_BUSTEST_R 14 +#define EMMC_GO_INACTIVE_STATE 15 +#define EMMC_SET_BLOCKLEN 16 +#define EMMC_READ_SINGLE_BLOCK 17 +#define EMMC_READ_MULTIPLE_BLOCK 18 +#define EMMC_BUSTEST_W 19 +#define EMMC_SEND_TUNING_BLOCK 21 +#define EMMC_SET_BLOCK_COUNT 23 +#define EMMC_WRITE_BLOCK 24 +#define EMMC_WRITE_MULTIPLE_BLOCK 25 +#define EMMC_PROGRAM_CID 26 +#define EMMC_PROGRAM_CSD 27 +#define EMMC_SET_WRITE_PROT 28 +#define EMMC_CLR_WRITE_PROT 29 +#define EMMC_SEND_WRITE_PROT 30 +#define EMMC_SEND_WRITE_PROT_TYPE 31 +#define EMMC_ERASE_GROUP_START 35 +#define EMMC_ERASE_GROUP_END 36 +#define EMMC_ERASE 38 +#define EMMC_FAST_IO 39 +#define EMMC_GO_IRQ_STATE 40 +#define EMMC_LOCK_UNLOCK 42 +#define EMMC_SET_TIME 49 +#define EMMC_PROTOCOL_RD 53 +#define EMMC_PROTOCOL_WR 54 +#define EMMC_APP_CMD 55 +#define EMMC_GEN_CMD 56 + +typedef enum { + EmmcPartitionUserData = 0, + EmmcPartitionBoot1 = 1, + EmmcPartitionBoot2 = 2, + EmmcPartitionRPMB = 3, + EmmcPartitionGP1 = 4, + EmmcPartitionGP2 = 5, + EmmcPartitionGP3 = 6, + EmmcPartitionGP4 = 7, + EmmcPartitionUnknown +} EMMC_PARTITION_TYPE; + +#pragma pack(1) +typedef struct { + UINT8 NotUsed:1; // Not used [0:0] + UINT8 Crc:7; // CRC [7:1] + UINT8 ManufacturingDate; // Manufacturing date [15:8] + UINT8 ProductSerialNumber[4]; // Product serial number [47:16] + UINT8 ProductRevision; // Product revision [55:48] + UINT8 ProductName[6]; // Product name [103:56] + UINT8 OemId; // OEM/Application ID [111:104] + UINT8 DeviceType:2; // Device/BGA [113:112] + UINT8 Reserved:6; // Reserved [119:114] + UINT8 ManufacturerId; // Manufacturer ID [127:120] +} EMMC_CID; + +typedef struct { + UINT32 NotUsed:1; // Not used [0:0] + UINT32 Crc:7; // CRC [7:1] + UINT32 Ecc:2; // ECC code [9:8] + UINT32 FileFormat:2; // File format [11:10] + UINT32 TmpWriteProtect:1; // Temporary write protection [12:12] + UINT32 PermWriteProtect:1; // Permanent write protection [13:13] + UINT32 Copy:1; // Copy flag (OTP) [14:14] + UINT32 FileFormatGrp:1; // File format group [15:15] + UINT32 ContentProtApp:1; // Content protection application [16:16] + UINT32 Reserved:4; // Reserved [20:17] + UINT32 WriteBlPartial:1; // Partial blocks for write allowed [21:21] + UINT32 WriteBlLen:4; // Max. write data block length [25:22] + UINT32 R2WFactor:3; // Write speed factor [28:26] + UINT32 DefaultEcc:2; // Manufacturer default ECC [30:29] + UINT32 WpGrpEnable:1; // Write protect group enable [31:31] + + UINT32 WpGrpSize:5; // Write protect group size [36:32] + UINT32 EraseGrpMult:5; // Erase group size multiplier [41:37] + UINT32 EraseGrpSize:5; // Erase group size [46:42] + UINT32 CSizeMult:3; // Device size multiplier [49:47] + UINT32 VddWCurrMax:3; // Max. write current @ VDD max [52:50] + UINT32 VddWCurrMin:3; // Max. write current @ VDD min [55:53] + UINT32 VddRCurrMax:3; // Max. read current @ VDD max [58:56] + UINT32 VddRCurrMin:3; // Max. read current @ VDD min [61:59] + UINT32 CSizeLow:2; // Device size low two bits [63:62] + + UINT32 CSizeHigh:10; // Device size high eight bits [73:64] + UINT32 Reserved1:2; // Reserved [75:74] + UINT32 DsrImp:1; // DSR implemented [76:76] + UINT32 ReadBlkMisalign:1; // Read block misalignment [77:77] + UINT32 WriteBlkMisalign:1; // Write block misalignment [78:78] + UINT32 ReadBlPartial:1; // Partial blocks for read allowed [79:79] + UINT32 ReadBlLen:4; // Max. read data block length [83:80] + UINT32 Ccc:12; // Device command classes [95:84] + + UINT32 TranSpeed:8; // Max. bus clock frequency [103:96] + UINT32 Nsac:8; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104] + UINT32 Taac:8; // Data read access-time 1 [119:112] + UINT32 Reserved2:2; // Reserved [121:120] + UINT32 SpecVers:4; // System specification version [125:122] + UINT32 CsdStructure:2; // CSD structure [127:126] +} EMMC_CSD; + +typedef struct { + // + // Modes Segment + // + UINT8 Reserved[16]; // Reserved [15:0] + UINT8 SecureRemovalType; // Secure Removal Type R/W & R [16] + UINT8 ProductStateAwarenessEnablement; // Product state awareness enablement R/W/E & R [17] + UINT8 MaxPreLoadingDataSize[4]; // Max pre loading data size R [21:18] + UINT8 PreLoadingDataSize[4]; // Pre loading data size R/W/EP [25:22] + UINT8 FfuStatus; // FFU status R [26] + UINT8 Reserved1[2]; // Reserved [28:27] + UINT8 ModeOperationCodes; // Mode operation codes W/EP [29] + UINT8 ModeConfig; // Mode config R/W/EP [30] + UINT8 Reserved2; // Reserved [31] + UINT8 FlushCache; // Flushing of the cache W/EP [32] + UINT8 CacheCtrl; // Control to turn the Cache ON/OFF R/W/EP [33] + UINT8 PowerOffNotification; // Power Off Notification R/W/EP [34] + UINT8 PackedFailureIndex; // Packed command failure index R [35] + UINT8 PackedCommandStatus; // Packed command status R [36] + UINT8 ContextConf[15]; // Context configuration R/W/EP [51:37] + UINT8 ExtPartitionsAttribute[2]; // Extended Partitions Attribute R/W [53:52] + UINT8 ExceptionEventsStatus[2]; // Exception events status R [55:54] + UINT8 ExceptionEventsCtrl[2]; // Exception events control R/W/EP [57:56] + UINT8 DyncapNeeded; // Number of addressed group to be Released R [58] + UINT8 Class6Ctrl; // Class 6 commands control R/W/EP [59] + UINT8 IniTimeoutEmu; // 1st initialization after disabling sector size emulation R [60] + UINT8 DataSectorSize; // Sector size R [61] + UINT8 UseNativeSector; // Sector size emulation R/W [62] + UINT8 NativeSectorSize; // Native sector size R [63] + UINT8 VendorSpecificField[64]; // Vendor Specific Fields [127:64] + UINT8 Reserved3[2]; // Reserved [129:128] + UINT8 ProgramCidCsdDdrSupport; // Program CID/CSD in DDR mode support R [130] + UINT8 PeriodicWakeup; // Periodic Wake-up R/W/E [131] + UINT8 TcaseSupport; // Package Case Temperature is controlled W/EP [132] + UINT8 ProductionStateAwareness; // Production state awareness R/W/E [133] + UINT8 SecBadBlkMgmnt; // Bad Block Management mode R/W [134] + UINT8 Reserved4; // Reserved [135] + UINT8 EnhStartAddr[4]; // Enhanced User Data Start Address R/W [139:136] + UINT8 EnhSizeMult[3]; // Enhanced User Data Area Size R/W [142:140] + UINT8 GpSizeMult[12]; // General Purpose Partition Size R/W [154:143] + UINT8 PartitionSettingCompleted; // Partitioning Setting R/W [155] + UINT8 PartitionsAttribute; // Partitions attribute R/W [156] + UINT8 MaxEnhSizeMult[3]; // Max Enhanced Area Size R [159:157] + UINT8 PartitioningSupport; // Partitioning Support R [160] + UINT8 HpiMgmt; // HPI management R/W/EP [161] + UINT8 RstFunction; // H/W reset function R/W [162] + UINT8 BkopsEn; // Enable background operations handshake R/W [163] + UINT8 BkopsStart; // Manually start background operations W/EP [164] + UINT8 SanitizeStart; // Start Sanitize operation W/EP [165] + UINT8 WrRelParam; // Write reliability parameter register R [166] + UINT8 WrRelSet; // Write reliability setting register R/W [167] + UINT8 RpmbSizeMult; // RPMB Size R [168] + UINT8 FwConfig; // FW configuration R/W [169] + UINT8 Reserved5; // Reserved [170] + UINT8 UserWp; // User area write protection register R/W,R/W/CP&R/W/EP [171] + UINT8 Reserved6; // Reserved [172] + UINT8 BootWp; // Boot area write protection register R/W&R/W/CP[173] + UINT8 BootWpStatus; // Boot write protection status registers R [174] + UINT8 EraseGroupDef; // High-density erase group definition R/W/EP [175] + UINT8 Reserved7; // Reserved [176] + UINT8 BootBusConditions; // Boot bus Conditions R/W/E [177] + UINT8 BootConfigProt; // Boot config protection R/W&R/W/CP[178] + UINT8 PartitionConfig; // Partition configuration R/W/E&R/W/EP[179] + UINT8 Reserved8; // Reserved [180] + UINT8 ErasedMemCont; // Erased memory content R [181] + UINT8 Reserved9; // Reserved [182] + UINT8 BusWidth; // Bus width mode W/EP [183] + UINT8 Reserved10; // Reserved [184] + UINT8 HsTiming; // High-speed interface timing R/W/EP [185] + UINT8 Reserved11; // Reserved [186] + UINT8 PowerClass; // Power class R/W/EP [187] + UINT8 Reserved12; // Reserved [188] + UINT8 CmdSetRev; // Command set revision R [189] + UINT8 Reserved13; // Reserved [190] + UINT8 CmdSet; // Command set R/W/EP [191] + // + // Properties Segment + // + UINT8 ExtCsdRev; // Extended CSD revision [192] + UINT8 Reserved14; // Reserved [193] + UINT8 CsdStructure; // CSD STRUCTURE [194] + UINT8 Reserved15; // Reserved [195] + UINT8 DeviceType; // Device type [196] + UINT8 DriverStrength; // I/O Driver Strength [197] + UINT8 OutOfInterruptTime; // Out-of-interrupt busy timing[198] + UINT8 PartitionSwitchTime; // Partition switching timing [199] + UINT8 PwrCl52M195V; // Power class for 52MHz at 1.95V [200] + UINT8 PwrCl26M195V; // Power class for 26MHz at 1.95V [201] + UINT8 PwrCl52M360V; // Power class for 52MHz at 3.6V [202] + UINT8 PwrCl26M360V; // Power class for 26MHz at 3.6V [203] + UINT8 Reserved16; // Reserved [204] + UINT8 MinPerfR4B26M; // Minimum Read Performance for 4bit at 26MHz [205] + UINT8 MinPerfW4B26M; // Minimum Write Performance for 4bit at 26MHz [206] + UINT8 MinPerfR8B26M4B52M; // Minimum Read Performance for 8bit at 26MHz, for 4bit at 52MHz [207] + UINT8 MinPerfW8B26M4B52M; // Minimum Write Performance for 8bit at 26MHz, for 4bit at 52MHz [208] + UINT8 MinPerfR8B52M; // Minimum Read Performance for 8bit at 52MHz [209] + UINT8 MinPerfW8B52M; // Minimum Write Performance for 8bit at 52MHz [210] + UINT8 Reserved17; // Reserved [211] + UINT8 SecCount[4]; // Sector Count [215:212] + UINT8 SleepNotificationTime; // Sleep Notification Timout [216] + UINT8 SATimeout; // Sleep/awake timeout [217] + UINT8 ProductionStateAwarenessTimeout; // Production state awareness timeout [218] + UINT8 SCVccq; // Sleep current (VCCQ) [219] + UINT8 SCVcc; // Sleep current (VCC) [220] + UINT8 HcWpGrpSize; // High-capacity write protect group size [221] + UINT8 RelWrSecC; // Reliable write sector count [222] + UINT8 EraseTimeoutMult; // High-capacity erase timeout [223] + UINT8 HcEraseGrpSize; // High-capacity erase unit size [224] + UINT8 AccSize; // Access size [225] + UINT8 BootSizeMult; // Boot partition size [226] + UINT8 Reserved18; // Reserved [227] + UINT8 BootInfo; // Boot information [228] + UINT8 SecTrimMult; // Secure TRIM Multiplier [229] + UINT8 SecEraseMult; // Secure Erase Multiplier [230] + UINT8 SecFeatureSupport; // Secure Feature support [231] + UINT8 TrimMult; // TRIM Multiplier [232] + UINT8 Reserved19; // Reserved [233] + UINT8 MinPerfDdrR8b52M; // Minimum Read Performance for 8bit at 52MHz in DDR mode [234] + UINT8 MinPerfDdrW8b52M; // Minimum Write Performance for 8bit at 52MHz in DDR mode [235] + UINT8 PwrCl200M130V; // Power class for 200MHz, at VCCQ=1.3V, VCC = 3.6V [236] + UINT8 PwrCl200M195V; // Power class for 200MHz at VCCQ=1.95V, VCC = 3.6V [237] + UINT8 PwrClDdr52M195V; // Power class for 52MHz, DDR at VCC= 1.95V [238] + UINT8 PwrClDdr52M360V; // Power class for 52MHz, DDR at VCC= 3.6V [239] + UINT8 Reserved20; // Reserved [240] + UINT8 IniTimeoutAp; // 1st initialization time after partitioning [241] + UINT8 CorrectlyPrgSectorsNum[4]; // Number of correctly programmed sectors [245:242] + UINT8 BkopsStatus; // Background operations status [246] + UINT8 PowerOffLongTime; // Power off notification(long) timeout [247] + UINT8 GenericCmd6Time; // Generic CMD6 timeout [248] + UINT8 CacheSize[4]; // Cache size [252:249] + UINT8 PwrClDdr200M360V; // Power class for 200MHz, DDR at VCC= 3.6V [253] + UINT8 FirmwareVersion[8]; // Firmware version [261:254] + UINT8 DeviceVersion[2]; // Device version [263:262] + UINT8 OptimalTrimUnitSize; // Optimal trim unit size[264] + UINT8 OptimalWriteSize; // Optimal write size [265] + UINT8 OptimalReadSize; // Optimal read size [266] + UINT8 PreEolInfo; // Pre EOL information [267] + UINT8 DeviceLifeTimeEstTypA; // Device life time estimation type A [268] + UINT8 DeviceLifeTimeEstTypB; // Device life time estimation type B [269] + UINT8 VendorProprietaryHealthReport[32]; // Vendor proprietary health report [301:270] + UINT8 NumOfFwSectorsProgrammed[4]; // Number of FW sectors correctly programmed [305:302] + UINT8 Reserved21[181]; // Reserved [486:306] + UINT8 FfuArg[4]; // FFU Argument [490:487] + UINT8 OperationCodeTimeout; // Operation codes timeout [491] + UINT8 FfuFeatures; // FFU features [492] + UINT8 SupportedModes; // Supported modes [493] + UINT8 ExtSupport; // Extended partitions attribute support [494] + UINT8 LargeUnitSizeM1; // Large Unit size [495] + UINT8 ContextCapabilities; // Context management capabilities [496] + UINT8 TagResSize; // Tag Resources Size [497] + UINT8 TagUnitSize; // Tag Unit Size [498] + UINT8 DataTagSupport; // Data Tag Support [499] + UINT8 MaxPackedWrites; // Max packed write commands [500] + UINT8 MaxPackedReads; // Max packed read commands[501] + UINT8 BkOpsSupport; // Background operations support [502] + UINT8 HpiFeatures; // HPI features [503] + UINT8 SupportedCmdSet; // Supported Command Sets [504] + UINT8 ExtSecurityErr; // Extended Security Commands Error [505] + UINT8 Reserved22[6]; // Reserved [511:506] +} EMMC_EXT_CSD; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/HighPrecisionEventTimerTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/HighPrecisionEventTimerTable.h new file mode 100644 index 0000000..26f2743 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/HighPrecisionEventTimerTable.h @@ -0,0 +1,68 @@ +/** @file + ACPI high precision event timer table definition, at www.intel.com + Specification name is IA-PC HPET (High Precision Event Timers) Specification. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _HIGH_PRECISION_EVENT_TIMER_TABLE_H_ +#define _HIGH_PRECISION_EVENT_TIMER_TABLE_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// HPET Event Timer Block ID described in IA-PC HPET Specification, 3.2.4. +/// +typedef union { + struct { + UINT32 Revision : 8; + UINT32 NumberOfTimers : 5; + UINT32 CounterSize : 1; + UINT32 Reserved : 1; + UINT32 LegacyRoute : 1; + UINT32 VendorId : 16; + } Bits; + UINT32 Uint32; +} EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID; + + +/// +/// High Precision Event Timer Table header definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 EventTimerBlockId; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE BaseAddressLower32Bit; + UINT8 HpetNumber; + UINT16 MainCounterMinimumClockTickInPeriodicMode; + UINT8 PageProtectionAndOemAttribute; +} EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER; + +/// +/// HPET Revision (defined in spec) +/// +#define EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION 0x01 + +// +// Page protection setting +// Values 3 through 15 are reserved for use by the specification +// +#define EFI_ACPI_NO_PAGE_PROTECTION 0 +#define EFI_ACPI_4KB_PAGE_PROTECTION 1 +#define EFI_ACPI_64KB_PAGE_PROTECTION 2 + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Hsti.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Hsti.h new file mode 100644 index 0000000..e018b53 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Hsti.h @@ -0,0 +1,82 @@ +/** @file + Support for HSTI 1.1a specification, defined at + Microsoft Hardware Security Testability Specification. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HSTI_H__ +#define __HSTI_H__ + +#pragma pack(1) + +#define ADAPTER_INFO_PLATFORM_SECURITY_GUID \ + {0x6be272c7, 0x1320, 0x4ccd, { 0x90, 0x17, 0xd4, 0x61, 0x2c, 0x01, 0x2b, 0x25 }} + +#define PLATFORM_SECURITY_VERSION_VNEXTCS 0x00000003 + +#define PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE 0x00000001 // IHV +#define PLATFORM_SECURITY_ROLE_PLATFORM_IBV 0x00000002 +#define PLATFORM_SECURITY_ROLE_IMPLEMENTOR_OEM 0x00000003 +#define PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM 0x00000004 + +typedef struct { + // + // Return PLATFORM_SECURITY_VERSION_VNEXTCS + // + UINT32 Version; + // + // The role of the publisher of this interface. Reference platform designers + // such as IHVs and IBVs are expected to return PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE + // and PLATFORM_SECURITY_ROLE_PLATFORM_IBV respectively. + // If the test modules from the designers are unable to fully verify all + // security features, then the platform implementers, OEMs and ODMs, will + // need to publish this interface with a role of Implementer. + // + UINT32 Role; + // + // Human readable vendor, model, & version of this implementation. + // + CHAR16 ImplementationID[256]; + // + // The size in bytes of the SecurityFeaturesRequired and SecurityFeaturesEnabled arrays. + // The arrays must be the same size. + // + UINT32 SecurityFeaturesSize; + // + // IHV-defined bitfield corresponding to all security features which must be + // implemented to meet the security requirements defined by PLATFORM_SECURITY_VERSION Version. + // +//UINT8 SecurityFeaturesRequired[]; //Ignored for non-IHV + // + // Publisher-defined bitfield corresponding to all security features which + // have implemented programmatic tests in this module. + // +//UINT8 SecurityFeaturesImplemented[]; + // + // Publisher-defined bitfield corresponding to all security features which + // have been verified implemented by this implementation. + // +//UINT8 SecurityFeaturesVerified[]; + // + // A Null-terminated string, one failure per line (CR/LF terminated), with a + // unique identifier that the OEM/ODM can use to locate the documentation + // which will describe the steps to remediate the failure - a URL to the + // documentation is recommended. + // +//CHAR16 ErrorString[]; +} ADAPTER_INFO_PLATFORM_SECURITY; + +#pragma pack() + +extern EFI_GUID gAdapterInfoPlatformSecurityGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Http11.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Http11.h new file mode 100644 index 0000000..9b91afe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Http11.h @@ -0,0 +1,254 @@ +/** @file + Hypertext Transfer Protocol -- HTTP/1.1 Standard definitions, from RFC 2616 + + This file contains common HTTP 1.1 definitions from RFC 2616 + + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __HTTP_11_H__ +#define __HTTP_11_H__ + +#pragma pack(1) + +/// +/// HTTP Version (currently HTTP 1.1) +/// +/// The version of an HTTP message is indicated by an HTTP-Version field +/// in the first line of the message. +/// +#define HTTP_VERSION "HTTP/1.1" + +/// +/// HTTP Request Method definitions +/// +/// The Method token indicates the method to be performed on the +/// resource identified by the Request-URI. The method is case-sensitive. +/// +#define HTTP_METHOD_OPTIONS "OPTIONS" +#define HTTP_METHOD_GET "GET" +#define HTTP_METHOD_HEAD "HEAD" +#define HTTP_METHOD_POST "POST" +#define HTTP_METHOD_PUT "PUT" +#define HTTP_METHOD_DELETE "DELETE" +#define HTTP_METHOD_TRACE "TRACE" +#define HTTP_METHOD_CONNECT "CONNECT" +#define HTTP_METHOD_PATCH "PATCH" + +/// +/// Connect method has maximum length according to EFI_HTTP_METHOD defined in +/// UEFI2.5 spec so use this. +/// +#define HTTP_METHOD_MAXIMUM_LEN sizeof (HTTP_METHOD_CONNECT) + +/// +/// Accept Request Header +/// The Accept request-header field can be used to specify certain media types which are +/// acceptable for the response. Accept headers can be used to indicate that the request +/// is specifically limited to a small set of desired types, as in the case of a request +/// for an in-line image. +/// +#define HTTP_HEADER_ACCEPT "Accept" + + +/// +/// Accept-Charset Request Header +/// The Accept-Charset request-header field can be used to indicate what character sets +/// are acceptable for the response. This field allows clients capable of understanding +/// more comprehensive or special-purpose character sets to signal that capability to a +/// server which is capable of representing documents in those character sets. +/// +#define HTTP_HEADER_ACCEPT_CHARSET "Accept-Charset" + +/// +/// Accept-Language Request Header +/// The Accept-Language request-header field is similar to Accept, +/// but restricts the set of natural languages that are preferred +/// as a response to the request. +/// +#define HTTP_HEADER_ACCEPT_LANGUAGE "Accept-Language" + +/// +/// Accept-Ranges Request Header +/// The Accept-Ranges response-header field allows the server to +/// indicate its acceptance of range requests for a resource: +/// +#define HTTP_HEADER_ACCEPT_RANGES "Accept-Ranges" + + +/// +/// Accept-Encoding Request Header +/// The Accept-Encoding request-header field is similar to Accept, +/// but restricts the content-codings that are acceptable in the response. +/// +#define HTTP_HEADER_ACCEPT_ENCODING "Accept-Encoding" + +/// +/// Content-Encoding Header +/// The Content-Encoding entity-header field is used as a modifier to the media-type. +/// When present, its value indicates what additional content codings have been applied +/// to the entity-body, and thus what decoding mechanisms must be applied in order to +/// obtain the media-type referenced by the Content-Type header field. Content-Encoding +/// is primarily used to allow a document to be compressed without losing the identity +/// of its underlying media type. +/// +#define HTTP_HEADER_CONTENT_ENCODING "Content-Encoding" + +/// +/// HTTP Content-Encoding Compression types +/// + +#define HTTP_CONTENT_ENCODING_IDENTITY "identity" /// No transformation is used. This is the default value for content coding. +#define HTTP_CONTENT_ENCODING_GZIP "gzip" /// Content-Encoding: GNU zip format (described in RFC 1952). +#define HTTP_CONTENT_ENCODING_COMPRESS "compress" /// encoding format produced by the common UNIX file compression program "compress". +#define HTTP_CONTENT_ENCODING_DEFLATE "deflate" /// The "zlib" format defined in RFC 1950 in combination with the "deflate" + /// compression mechanism described in RFC 1951. + + +/// +/// Content-Type Header +/// The Content-Type entity-header field indicates the media type of the entity-body sent to +/// the recipient or, in the case of the HEAD method, the media type that would have been sent +/// had the request been a GET. +/// +#define HTTP_HEADER_CONTENT_TYPE "Content-Type" +// +// Common Media Types defined in http://www.iana.org/assignments/media-types/media-types.xhtml +// +#define HTTP_CONTENT_TYPE_APP_JSON "application/json" +#define HTTP_CONTENT_TYPE_APP_OCTET_STREAM "application/octet-stream" + +#define HTTP_CONTENT_TYPE_TEXT_HTML "text/html" +#define HTTP_CONTENT_TYPE_TEXT_PLAIN "text/plain" +#define HTTP_CONTENT_TYPE_TEXT_CSS "text/css" +#define HTTP_CONTENT_TYPE_TEXT_XML "text/xml" + +#define HTTP_CONTENT_TYPE_IMAGE_GIF "image/gif" +#define HTTP_CONTENT_TYPE_IMAGE_JPEG "image/jpeg" +#define HTTP_CONTENT_TYPE_IMAGE_PNG "image/png" +#define HTTP_CONTENT_TYPE_IMAGE_SVG_XML "image/svg+xml" + + +/// +/// Content-Length Header +/// The Content-Length entity-header field indicates the size of the entity-body, +/// in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD +/// method, the size of the entity-body that would have been sent had the request been a GET. +/// +#define HTTP_HEADER_CONTENT_LENGTH "Content-Length" + +/// +/// Transfer-Encoding Header +/// The Transfer-Encoding general-header field indicates what (if any) type of transformation +/// has been applied to the message body in order to safely transfer it between the sender +/// and the recipient. This differs from the content-coding in that the transfer-coding +/// is a property of the message, not of the entity. +/// +#define HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding" + + +/// +/// User Agent Request Header +/// +/// The User-Agent request-header field contains information about the user agent originating +/// the request. This is for statistical purposes, the tracing of protocol violations, and +/// automated recognition of user agents for the sake of tailoring responses to avoid +/// particular user agent limitations. User agents SHOULD include this field with requests. +/// The field can contain multiple product tokens and comments identifying the agent and any +/// subproducts which form a significant part of the user agent. +/// By convention, the product tokens are listed in order of their significance for +/// identifying the application. +/// +#define HTTP_HEADER_USER_AGENT "User-Agent" + +/// +/// Host Request Header +/// +/// The Host request-header field specifies the Internet host and port number of the resource +/// being requested, as obtained from the original URI given by the user or referring resource +/// +#define HTTP_HEADER_HOST "Host" + +/// +/// Location Response Header +/// +/// The Location response-header field is used to redirect the recipient to a location other than +/// the Request-URI for completion of the request or identification of a new resource. +/// For 201 (Created) responses, the Location is that of the new resource which was created by +/// the request. For 3xx responses, the location SHOULD indicate the server's preferred URI for +/// automatic redirection to the resource. The field value consists of a single absolute URI. +/// +#define HTTP_HEADER_LOCATION "Location" + +/// +/// The If-Match request-header field is used with a method to make it conditional. +/// A client that has one or more entities previously obtained from the resource +/// can verify that one of those entities is current by including a list of their +/// associated entity tags in the If-Match header field. +/// The purpose of this feature is to allow efficient updates of cached information +/// with a minimum amount of transaction overhead. It is also used, on updating requests, +/// to prevent inadvertent modification of the wrong version of a resource. +/// As a special case, the value "*" matches any current entity of the resource. +/// +#define HTTP_HEADER_IF_MATCH "If-Match" + + +/// +/// The If-None-Match request-header field is used with a method to make it conditional. +/// A client that has one or more entities previously obtained from the resource can verify +/// that none of those entities is current by including a list of their associated entity +/// tags in the If-None-Match header field. The purpose of this feature is to allow efficient +/// updates of cached information with a minimum amount of transaction overhead. It is also used +/// to prevent a method (e.g. PUT) from inadvertently modifying an existing resource when the +/// client believes that the resource does not exist. +/// +#define HTTP_HEADER_IF_NONE_MATCH "If-None-Match" + + + +/// +/// Authorization Request Header +/// The Authorization field value consists of credentials +/// containing the authentication information of the user agent for +/// the realm of the resource being requested. +/// +#define HTTP_HEADER_AUTHORIZATION "Authorization" + +/// +/// ETAG Response Header +/// The ETag response-header field provides the current value of the entity tag +/// for the requested variant. +/// +#define HTTP_HEADER_ETAG "ETag" + +/// +/// Custom header field checked by the iLO web server to +/// specify a client session key. +/// Example: X-Auth-Token: 24de6b1f8fa147ad59f6452def628798 +/// +#define HTTP_HEADER_X_AUTH_TOKEN "X-Auth-Token" + +/// +/// Expect Header +/// The "Expect" header field in a request indicates a certain set of +/// behaviors (expectations) that need to be supported by the server in +/// order to properly handle this request. The only such expectation +/// defined by this specification is 100-continue. +/// +#define HTTP_HEADER_EXPECT "Expect" + +/// +/// Expect Header Value +/// +#define HTTP_EXPECT_100_CONTINUE "100-continue" + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IScsiBootFirmwareTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IScsiBootFirmwareTable.h new file mode 100644 index 0000000..b12c02b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IScsiBootFirmwareTable.h @@ -0,0 +1,167 @@ +/** @file + The definition for iSCSI Boot Firmware Table, it's defined in Microsoft's + iSCSI Boot Firmware Table(iBFT) as Defined in ACPI 3.0b Specification. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _ISCSI_BOOT_FIRMWARE_TABLE_H_ +#define _ISCSI_BOOT_FIRMWARE_TABLE_H_ + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION 0x01 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_ALIGNMENT 8 + +/// +/// Structure Type/ID +/// +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_RESERVED_STRUCTURE_ID 0 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID 1 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID 2 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID 3 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID 4 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_EXTERNSIONS_STRUCTURE_ID 5 + +/// +/// from the definition of IP_PREFIX_ORIGIN Enumeration in MSDN, +/// not defined in Microsoft iBFT document. +/// +typedef enum { + IpPrefixOriginOther = 0, + IpPrefixOriginManual, + IpPrefixOriginWellKnown, + IpPrefixOriginDhcp, + IpPrefixOriginRouterAdvertisement, + IpPrefixOriginUnchanged = 16 +} IP_PREFIX_VALUE; + +#pragma pack(1) + +/// +/// iBF Table Header +/// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + UINT8 OemId[6]; + UINT64 OemTableId; + UINT8 Reserved[24]; +} EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER; + +/// +/// Common Header of Boot Firmware Table Structure +/// +typedef struct { + UINT8 StructureId; + UINT8 Version; + UINT16 Length; + UINT8 Index; + UINT8 Flags; +} EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_HEADER; + +/// +/// Control Structure +/// +typedef struct { + EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_HEADER Header; + UINT16 Extensions; + UINT16 InitiatorOffset; + UINT16 NIC0Offset; + UINT16 Target0Offset; + UINT16 NIC1Offset; + UINT16 Target1Offset; +} EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE; + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION 0x1 + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_FLAG_BOOT_FAILOVER BIT0 + +/// +/// Initiator Structure +/// +typedef struct { + EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_HEADER Header; + EFI_IPv6_ADDRESS ISnsServer; + EFI_IPv6_ADDRESS SlpServer; + EFI_IPv6_ADDRESS PrimaryRadiusServer; + EFI_IPv6_ADDRESS SecondaryRadiusServer; + UINT16 IScsiNameLength; + UINT16 IScsiNameOffset; +} EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE; + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION 0x1 + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID BIT0 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED BIT1 + +/// +/// NIC Structure +/// +typedef struct { + EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_HEADER Header; + EFI_IPv6_ADDRESS Ip; + UINT8 SubnetMaskPrefixLength; + UINT8 Origin; + EFI_IPv6_ADDRESS Gateway; + EFI_IPv6_ADDRESS PrimaryDns; + EFI_IPv6_ADDRESS SecondaryDns; + EFI_IPv6_ADDRESS DhcpServer; + UINT16 VLanTag; + UINT8 Mac[6]; + UINT16 PciLocation; + UINT16 HostNameLength; + UINT16 HostNameOffset; +} EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE; + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION 0x1 + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID BIT0 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED BIT1 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL BIT2 + +/// +/// Target Structure +/// +typedef struct { + EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_HEADER Header; + EFI_IPv6_ADDRESS Ip; + UINT16 Port; + UINT8 BootLun[8]; + UINT8 CHAPType; + UINT8 NicIndex; + UINT16 IScsiNameLength; + UINT16 IScsiNameOffset; + UINT16 CHAPNameLength; + UINT16 CHAPNameOffset; + UINT16 CHAPSecretLength; + UINT16 CHAPSecretOffset; + UINT16 ReverseCHAPNameLength; + UINT16 ReverseCHAPNameOffset; + UINT16 ReverseCHAPSecretLength; + UINT16 ReverseCHAPSecretOffset; +} EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE; + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION 0x1 + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID BIT0 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED BIT1 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_RADIUS_CHAP BIT2 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_RADIUS_RCHAP BIT3 + +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP 0 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_CHAP 1 +#define EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP 2 + +#pragma pack() + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IoRemappingTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IoRemappingTable.h new file mode 100644 index 0000000..71a0159 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IoRemappingTable.h @@ -0,0 +1,209 @@ +/** @file + ACPI IO Remapping Table (IORT) as specified in ARM spec DEN0049D + + http://infocenter.arm.com/help/topic/com.arm.doc.den0049d/DEN0049D_IO_Remapping_Table.pdf + + Copyright (c) 2017, Linaro Limited. All rights reserved.
+ Copyright (c) 2018, ARM Limited. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __IO_REMAPPING_TABLE_H__ +#define __IO_REMAPPING_TABLE_H__ + +#include + +#define EFI_ACPI_IO_REMAPPING_TABLE_REVISION 0x0 + +#define EFI_ACPI_IORT_TYPE_ITS_GROUP 0x0 +#define EFI_ACPI_IORT_TYPE_NAMED_COMP 0x1 +#define EFI_ACPI_IORT_TYPE_ROOT_COMPLEX 0x2 +#define EFI_ACPI_IORT_TYPE_SMMUv1v2 0x3 +#define EFI_ACPI_IORT_TYPE_SMMUv3 0x4 +#define EFI_ACPI_IORT_TYPE_PMCG 0x5 + +#define EFI_ACPI_IORT_MEM_ACCESS_PROP_CCA BIT0 + +#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_TR BIT0 +#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_WA BIT1 +#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_RA BIT2 +#define EFI_ACPI_IORT_MEM_ACCESS_PROP_AH_AHO BIT3 + +#define EFI_ACPI_IORT_MEM_ACCESS_FLAGS_CPM BIT0 +#define EFI_ACPI_IORT_MEM_ACCESS_FLAGS_DACS BIT1 + +#define EFI_ACPI_IORT_SMMUv1v2_MODEL_v1 0x0 +#define EFI_ACPI_IORT_SMMUv1v2_MODEL_v2 0x1 +#define EFI_ACPI_IORT_SMMUv1v2_MODEL_MMU400 0x2 +#define EFI_ACPI_IORT_SMMUv1v2_MODEL_MMU500 0x3 +#define EFI_ACPI_IORT_SMMUv1v2_MODEL_MMU401 0x4 +#define EFI_ACPI_IORT_SMMUv1v2_MODEL_CAVIUM_THX_v2 0x5 + +#define EFI_ACPI_IORT_SMMUv1v2_FLAG_DVM BIT0 +#define EFI_ACPI_IORT_SMMUv1v2_FLAG_COH_WALK BIT1 + +#define EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_LEVEL 0x0 +#define EFI_ACPI_IORT_SMMUv1v2_INT_FLAG_EDGE 0x1 + +#define EFI_ACPI_IORT_SMMUv3_FLAG_COHAC_OVERRIDE BIT0 +#define EFI_ACPI_IORT_SMMUv3_FLAG_HTTU_OVERRIDE BIT1 +#define EFI_ACPI_IORT_SMMUv3_FLAG_PROXIMITY_DOMAIN BIT3 + +#define EFI_ACPI_IORT_SMMUv3_MODEL_GENERIC 0x0 +#define EFI_ACPI_IORT_SMMUv3_MODEL_HISILICON_HI161X 0x1 +#define EFI_ACPI_IORT_SMMUv3_MODEL_CAVIUM_CN99XX 0x2 + +#define EFI_ACPI_IORT_ROOT_COMPLEX_ATS_UNSUPPORTED 0x0 +#define EFI_ACPI_IORT_ROOT_COMPLEX_ATS_SUPPORTED 0x1 + +#define EFI_ACPI_IORT_ID_MAPPING_FLAGS_SINGLE BIT0 + +#pragma pack(1) + +/// +/// Table header +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 NumNodes; + UINT32 NodeOffset; + UINT32 Reserved; +} EFI_ACPI_6_0_IO_REMAPPING_TABLE; + +/// +/// Definition for ID mapping table shared by all node types +/// +typedef struct { + UINT32 InputBase; + UINT32 NumIds; + UINT32 OutputBase; + UINT32 OutputReference; + UINT32 Flags; +} EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE; + +/// +/// Node header definition shared by all node types +/// +typedef struct { + UINT8 Type; + UINT16 Length; + UINT8 Revision; + UINT32 Reserved; + UINT32 NumIdMappings; + UINT32 IdReference; +} EFI_ACPI_6_0_IO_REMAPPING_NODE; + +/// +/// Node type 0: ITS node +/// +typedef struct { + EFI_ACPI_6_0_IO_REMAPPING_NODE Node; + + UINT32 NumItsIdentifiers; +//UINT32 ItsIdentifiers[NumItsIdentifiers]; +} EFI_ACPI_6_0_IO_REMAPPING_ITS_NODE; + +/// +/// Node type 1: root complex node +/// +typedef struct { + EFI_ACPI_6_0_IO_REMAPPING_NODE Node; + + UINT32 CacheCoherent; + UINT8 AllocationHints; + UINT16 Reserved; + UINT8 MemoryAccessFlags; + + UINT32 AtsAttribute; + UINT32 PciSegmentNumber; + UINT8 MemoryAddressSize; + UINT8 Reserved1[3]; +} EFI_ACPI_6_0_IO_REMAPPING_RC_NODE; + +/// +/// Node type 2: named component node +/// +typedef struct { + EFI_ACPI_6_0_IO_REMAPPING_NODE Node; + + UINT32 Flags; + UINT32 CacheCoherent; + UINT8 AllocationHints; + UINT16 Reserved; + UINT8 MemoryAccessFlags; + UINT8 AddressSizeLimit; +//UINT8 ObjectName[]; +} EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE; + +/// +/// Node type 3: SMMUv1 or SMMUv2 node +/// +typedef struct { + UINT32 Interrupt; + UINT32 InterruptFlags; +} EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT; + +typedef struct { + EFI_ACPI_6_0_IO_REMAPPING_NODE Node; + + UINT64 Base; + UINT64 Span; + UINT32 Model; + UINT32 Flags; + UINT32 GlobalInterruptArrayRef; + UINT32 NumContextInterrupts; + UINT32 ContextInterruptArrayRef; + UINT32 NumPmuInterrupts; + UINT32 PmuInterruptArrayRef; + + UINT32 SMMU_NSgIrpt; + UINT32 SMMU_NSgIrptFlags; + UINT32 SMMU_NSgCfgIrpt; + UINT32 SMMU_NSgCfgIrptFlags; + +//EFI_ACPI_6_0_IO_REMAPPING_SMMU_CTX_INT ContextInterrupt[NumContextInterrupts]; +//EFI_ACPI_6_0_IO_REMAPPING_SMMU_CTX_INT PmuInterrupt[NumPmuInterrupts]; +} EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE; + +/// +/// Node type 4: SMMUv3 node +/// +typedef struct { + EFI_ACPI_6_0_IO_REMAPPING_NODE Node; + + UINT64 Base; + UINT32 Flags; + UINT32 Reserved; + UINT64 VatosAddress; + UINT32 Model; + UINT32 Event; + UINT32 Pri; + UINT32 Gerr; + UINT32 Sync; + UINT32 ProximityDomain; + UINT32 DeviceIdMappingIndex; +} EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE; + +/// +/// Node type 5: PMCG node +/// +typedef struct { + EFI_ACPI_6_0_IO_REMAPPING_NODE Node; + + UINT64 Base; + UINT32 OverflowInterruptGsiv; + UINT32 NodeReference; + UINT64 Page1Base; +//EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE OverflowInterruptMsiMapping[1]; +} EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Ipmi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Ipmi.h new file mode 100644 index 0000000..e6ec242 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Ipmi.h @@ -0,0 +1,61 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + IPMI Platform Management FRU Information Storage Definition v1.0 Revision 1.3. + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_H_ +#define _IPMI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// Generic Completion Codes definitions +// +#define IPMI_COMP_CODE_NORMAL 0x00 +#define IPMI_COMP_CODE_NODE_BUSY 0xC0 +#define IPMI_COMP_CODE_INVALID_COMMAND 0xC1 +#define IPMI_COMP_CODE_INVALID_FOR_GIVEN_LUN 0xC2 +#define IPMI_COMP_CODE_TIMEOUT 0xC3 +#define IPMI_COMP_CODE_OUT_OF_SPACE 0xC4 +#define IPMI_COMP_CODE_RESERVATION_CANCELED_OR_INVALID 0xC5 +#define IPMI_COMP_CODE_REQUEST_DATA_TRUNCATED 0xC6 +#define IPMI_COMP_CODE_INVALID_REQUEST_DATA_LENGTH 0xC7 +#define IPMI_COMP_CODE_REQUEST_EXCEED_LIMIT 0xC8 +#define IPMI_COMP_CODE_OUT_OF_RANGE 0xC9 +#define IPMI_COMP_CODE_CANNOT_RETURN 0xCA +#define IPMI_COMP_CODE_NOT_PRESENT 0xCB +#define IPMI_COMP_CODE_INVALID_DATA_FIELD 0xCC +#define IPMI_COMP_CODE_COMMAND_ILLEGAL 0xCD +#define IPMI_COMP_CODE_CMD_RESP_NOT_PROVIDED 0xCE +#define IPMI_COMP_CODE_FAIL_DUP_REQUEST 0xCF +#define IPMI_COMP_CODE_SDR_REP_IN_UPDATE_MODE 0xD0 +#define IPMI_COMP_CODE_DEV_IN_FW_UPDATE_MODE 0xD1 +#define IPMI_COMP_CODE_BMC_INIT_IN_PROGRESS 0xD2 +#define IPMI_COMP_CODE_DEST_UNAVAILABLE 0xD3 +#define IPMI_COMP_CODE_INSUFFICIENT_PRIVILEGE 0xD4 +#define IPMI_COMP_CODE_UNSUPPORTED_IN_PRESENT_STATE 0xD5 +#define IPMI_COMP_CODE_SUBFUNCTION_DISABLED 0xD6 +#define IPMI_COMP_CODE_UNSPECIFIED 0xFF + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiFruInformationStorage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiFruInformationStorage.h new file mode 100644 index 0000000..033ef6f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiFruInformationStorage.h @@ -0,0 +1,92 @@ +/** @file + IPMI Platform Management FRU Information Storage Definitions + + This file contains the definitions for: + Common Header Format (Chapter 8) + MultiRecord Header (Section 16.1) + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - IPMI Platform Management FRU Information Storage Definition v1.0 Revision + 1.3, Dated March 24, 2015. + https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-platform-mgt-fru-info-storage-def-v1-0-rev-1-3-spec-update.pdf +**/ + +#ifndef _IPMI_FRU_INFORMATION_STORAGE_H_ +#define _IPMI_FRU_INFORMATION_STORAGE_H_ + +#pragma pack(1) + +// +// Structure definitions for FRU Common Header +// +typedef union { + /// + /// Individual bit fields + /// + struct { + UINT8 FormatVersionNumber:4; + UINT8 Reserved:4; + } Bits; + /// + /// All bit fields as a 8-bit value + /// + UINT8 Uint8; +} IPMI_FRU_COMMON_HEADER_FORMAT_VERSION; + +typedef struct { + IPMI_FRU_COMMON_HEADER_FORMAT_VERSION FormatVersion; + UINT8 InternalUseStartingOffset; + UINT8 ChassisInfoStartingOffset; + UINT8 BoardAreaStartingOffset; + UINT8 ProductInfoStartingOffset; + UINT8 MultiRecInfoStartingOffset; + UINT8 Pad; + UINT8 Checksum; +} IPMI_FRU_COMMON_HEADER; + +// +// Structure definition for FRU MultiRecord Header +// +typedef union { + /// + /// Individual bit fields + /// + struct { + UINT8 RecordFormatVersion:4; + UINT8 Reserved:3; + UINT8 EndofList:1; + } Bits; + /// + /// All bit fields as a 8-bit value + /// + UINT8 Uint8; +} IPMI_FRU_MULTI_RECORD_HEADER_FORMAT_VERSION; + +typedef struct { + UINT8 RecordTypeId; + IPMI_FRU_MULTI_RECORD_HEADER_FORMAT_VERSION FormatVersion; + UINT8 RecordLength; + UINT8 RecordChecksum; + UINT8 HeaderChecksum; +} IPMI_FRU_MULTI_RECORD_HEADER; + +// +// Structure definition for System UUID Subrecord with checksum. +// +typedef struct { + UINT8 RecordCheckSum; + UINT8 SubRecordId; + EFI_GUID Uuid; +} IPMI_SYSTEM_UUID_SUB_RECORD_WITH_CHECKSUM; + +#pragma pack() +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnApp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnApp.h new file mode 100644 index 0000000..61f5040 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnApp.h @@ -0,0 +1,1035 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + This file contains all NetFn App commands, including: + IPM Device "Global" Commands (Chapter 20) + Firmware Firewall & Command Discovery Commands (Chapter 21) + BMC Watchdog Timer Commands (Chapter 27) + IPMI Messaging Support Commands (Chapter 22) + RMCP+ Support and Payload Commands (Chapter 24) + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_APP_H_ +#define _IPMI_NET_FN_APP_H_ + +#pragma pack(1) +// +// Net function definition for App command +// +#define IPMI_NETFN_APP 0x06 + +// +// Below is Definitions for IPM Device "Global" Commands (Chapter 20) +// + +// +// Definitions for Get Device ID command +// +#define IPMI_APP_GET_DEVICE_ID 0x1 + +// +// Constants and Structure definitions for "Get Device ID" command to follow here +// +typedef union { + struct { + UINT8 DeviceRevision : 4; + UINT8 Reserved : 3; + UINT8 DeviceSdr : 1; + } Bits; + UINT8 Uint8; +} IPMI_GET_DEVICE_ID_DEVICE_REV; + +typedef union { + struct { + UINT8 MajorFirmwareRev : 7; + UINT8 UpdateMode : 1; + } Bits; + UINT8 Uint8; +} IPMI_GET_DEVICE_ID_FIRMWARE_REV_1; + +typedef union { + struct { + UINT8 SensorDeviceSupport : 1; + UINT8 SdrRepositorySupport : 1; + UINT8 SelDeviceSupport : 1; + UINT8 FruInventorySupport : 1; + UINT8 IpmbMessageReceiver : 1; + UINT8 IpmbMessageGenerator : 1; + UINT8 BridgeSupport : 1; + UINT8 ChassisSupport : 1; + } Bits; + UINT8 Uint8; +} IPMI_GET_DEVICE_ID_DEVICE_SUPPORT; + +typedef struct { + UINT8 CompletionCode; + UINT8 DeviceId; + IPMI_GET_DEVICE_ID_DEVICE_REV DeviceRevision; + IPMI_GET_DEVICE_ID_FIRMWARE_REV_1 FirmwareRev1; + UINT8 MinorFirmwareRev; + UINT8 SpecificationVersion; + IPMI_GET_DEVICE_ID_DEVICE_SUPPORT DeviceSupport; + UINT8 ManufacturerId[3]; + UINT16 ProductId; + UINT32 AuxFirmwareRevInfo; +} IPMI_GET_DEVICE_ID_RESPONSE; + + +// +// Definitions for Cold Reset command +// +#define IPMI_APP_COLD_RESET 0x2 + +// +// Constants and Structure definitions for "Cold Reset" command to follow here +// + +// +// Definitions for Warm Reset command +// +#define IPMI_APP_WARM_RESET 0x3 + +// +// Constants and Structure definitions for "Warm Reset" command to follow here +// + +// +// Definitions for Get Self Results command +// +#define IPMI_APP_GET_SELFTEST_RESULTS 0x4 + +// +// Constants and Structure definitions for "Get Self Test Results" command to follow here +// +typedef struct { + UINT8 CompletionCode; + UINT8 Result; + UINT8 Param; +} IPMI_SELF_TEST_RESULT_RESPONSE; + +#define IPMI_APP_SELFTEST_NO_ERROR 0x55 +#define IPMI_APP_SELFTEST_NOT_IMPLEMENTED 0x56 +#define IPMI_APP_SELFTEST_ERROR 0x57 +#define IPMI_APP_SELFTEST_FATAL_HW_ERROR 0x58 +#define IPMI_APP_SELFTEST_INACCESSIBLE_SEL 0x80 +#define IPMI_APP_SELFTEST_INACCESSIBLE_SDR 0x40 +#define IPMI_APP_SELFTEST_INACCESSIBLE_FRU 0x20 +#define IPMI_APP_SELFTEST_IPMB_SIGNAL_FAIL 0x10 +#define IPMI_APP_SELFTEST_SDR_REPOSITORY_EMPTY 0x08 +#define IPMI_APP_SELFTEST_FRU_CORRUPT 0x04 +#define IPMI_APP_SELFTEST_FW_BOOTBLOCK_CORRUPT 0x02 +#define IPMI_APP_SELFTEST_FW_CORRUPT 0x01 + +// +// Definitions for Manufacturing Test ON command +// +#define IPMI_APP_MANUFACTURING_TEST_ON 0x5 + +// +// Constants and Structure definitions for "Manufacturing Test ON" command to follow here +// + +// +// Definitions for Set ACPI Power State command +// +#define IPMI_APP_SET_ACPI_POWERSTATE 0x6 + +// +// Constants and Structure definitions for "Set ACPI Power State" command to follow here +// + +// +// Definitions for System Power State +// +// Working +#define IPMI_SYSTEM_POWER_STATE_S0_G0 0x0 +#define IPMI_SYSTEM_POWER_STATE_S1 0x1 +#define IPMI_SYSTEM_POWER_STATE_S2 0x2 +#define IPMI_SYSTEM_POWER_STATE_S3 0x3 +#define IPMI_SYSTEM_POWER_STATE_S4 0x4 +// Soft off +#define IPMI_SYSTEM_POWER_STATE_S5_G2 0x5 +// Sent when message source cannot differentiate between S4 and S5 +#define IPMI_SYSTEM_POWER_STATE_S4_S5 0x6 +// Mechanical off +#define IPMI_SYSTEM_POWER_STATE_G3 0x7 +// Sleeping - cannot differentiate between S1-S3 +#define IPMI_SYSTEM_POWER_STATE_SLEEPING 0x8 +// Sleeping - cannot differentiate between S1-S4 +#define IPMI_SYSTEM_POWER_STATE_G1_SLEEPING 0x9 +// S5 entered by override +#define IPMI_SYSTEM_POWER_STATE_OVERRIDE 0xA +#define IPMI_SYSTEM_POWER_STATE_LEGACY_ON 0x20 +#define IPMI_SYSTEM_POWER_STATE_LEGACY_OFF 0x21 +#define IPMI_SYSTEM_POWER_STATE_UNKNOWN 0x2A +#define IPMI_SYSTEM_POWER_STATE_NO_CHANGE 0x7F + +// +// Definitions for Device Power State +// +#define IPMI_DEVICE_POWER_STATE_D0 0x0 +#define IPMI_DEVICE_POWER_STATE_D1 0x1 +#define IPMI_DEVICE_POWER_STATE_D2 0x2 +#define IPMI_DEVICE_POWER_STATE_D3 0x3 +#define IPMI_DEVICE_POWER_STATE_UNKNOWN 0x2A +#define IPMI_DEVICE_POWER_STATE_NO_CHANGE 0x7F + +typedef union { + struct { + UINT8 PowerState : 7; + UINT8 StateChange : 1; + } Bits; + UINT8 Uint8; +} IPMI_ACPI_POWER_STATE; + +typedef struct { + IPMI_ACPI_POWER_STATE SystemPowerState; + IPMI_ACPI_POWER_STATE DevicePowerState; +} IPMI_SET_ACPI_POWER_STATE_REQUEST; + +// +// Definitions for Get ACPI Power State command +// +#define IPMI_APP_GET_ACPI_POWERSTATE 0x7 + +// +// Constants and Structure definitions for "Get ACPI Power State" command to follow here +// + +// +// Definitions for Get Device GUID command +// +#define IPMI_APP_GET_DEVICE_GUID 0x8 + +// +// Constants and Structure definitions for "Get Device GUID" command to follow here +// +// +// Message structure definition for "Get Device Guid" IPMI command +// +typedef struct { + UINT8 CompletionCode; + UINT8 Guid[16]; +} IPMI_GET_DEVICE_GUID_RESPONSE; + +// +// Below is Definitions for BMC Watchdog Timer Commands (Chapter 27) +// + +// +// Definitions for Reset WatchDog Timer command +// +#define IPMI_APP_RESET_WATCHDOG_TIMER 0x22 + +// +// Definitions for Set WatchDog Timer command +// +#define IPMI_APP_SET_WATCHDOG_TIMER 0x24 + +// +// Constants and Structure definitions for "Set WatchDog Timer" command to follow here +// + +// +// Definitions for watchdog timer use +// +#define IPMI_WATCHDOG_TIMER_BIOS_FRB2 0x1 +#define IPMI_WATCHDOG_TIMER_BIOS_POST 0x2 +#define IPMI_WATCHDOG_TIMER_OS_LOADER 0x3 +#define IPMI_WATCHDOG_TIMER_SMS 0x4 +#define IPMI_WATCHDOG_TIMER_OEM 0x5 + +// +// Structure definition for timer Use +// +typedef union { + struct { + UINT8 TimerUse : 3; + UINT8 Reserved : 3; + UINT8 TimerRunning : 1; + UINT8 TimerUseExpirationFlagLog : 1; + } Bits; + UINT8 Uint8; +} IPMI_WATCHDOG_TIMER_USE; + +// +// Definitions for watchdog timeout action +// +#define IPMI_WATCHDOG_TIMER_ACTION_NO_ACTION 0x0 +#define IPMI_WATCHDOG_TIMER_ACTION_HARD_RESET 0x1 +#define IPMI_WATCHDOG_TIMER_ACTION_POWER_DONW 0x2 +#define IPMI_WATCHDOG_TIMER_ACTION_POWER_CYCLE 0x3 + +// +// Definitions for watchdog pre-timeout interrupt +// +#define IPMI_WATCHDOG_PRE_TIMEOUT_INTERRUPT_NONE 0x0 +#define IPMI_WATCHDOG_PRE_TIMEOUT_INTERRUPT_SMI 0x1 +#define IPMI_WATCHDOG_PRE_TIMEOUT_INTERRUPT_NMI 0x2 +#define IPMI_WATCHDOG_PRE_TIMEOUT_INTERRUPT_MESSAGING 0x3 + +// +// Structure definitions for Timer Actions +// +typedef union { + struct { + UINT8 TimeoutAction : 3; + UINT8 Reserved1 : 1; + UINT8 PreTimeoutInterrupt : 3; + UINT8 Reserved2 : 1; + } Bits; + UINT8 Uint8; +} IPMI_WATCHDOG_TIMER_ACTIONS; + +// +// Bit definitions for Timer use expiration flags +// +#define IPMI_WATCHDOG_TIMER_EXPIRATION_FLAG_BIOS_FRB2 BIT1 +#define IPMI_WATCHDOG_TIMER_EXPIRATION_FLAG_BIOS_POST BIT2 +#define IPMI_WATCHDOG_TIMER_EXPIRATION_FLAG_OS_LOAD BIT3 +#define IPMI_WATCHDOG_TIMER_EXPIRATION_FLAG_SMS_OS BIT4 +#define IPMI_WATCHDOG_TIMER_EXPIRATION_FLAG_OEM BIT5 + +typedef struct { + IPMI_WATCHDOG_TIMER_USE TimerUse; + IPMI_WATCHDOG_TIMER_ACTIONS TimerActions; + UINT8 PretimeoutInterval; + UINT8 TimerUseExpirationFlagsClear; + UINT16 InitialCountdownValue; +} IPMI_SET_WATCHDOG_TIMER_REQUEST; + +// +// Definitions for Get WatchDog Timer command +// +#define IPMI_APP_GET_WATCHDOG_TIMER 0x25 + +// +// Constants and Structure definitions for "Get WatchDog Timer" command to follow here +// +typedef struct { + UINT8 CompletionCode; + IPMI_WATCHDOG_TIMER_USE TimerUse; + IPMI_WATCHDOG_TIMER_ACTIONS TimerActions; + UINT8 PretimeoutInterval; + UINT8 TimerUseExpirationFlagsClear; + UINT16 InitialCountdownValue; + UINT16 PresentCountdownValue; +} IPMI_GET_WATCHDOG_TIMER_RESPONSE; + +// +// Below is Definitions for IPMI Messaging Support Commands (Chapter 22) +// + +// +// Definitions for Set BMC Global Enables command +// +#define IPMI_APP_SET_BMC_GLOBAL_ENABLES 0x2E + +// +// Constants and Structure definitions for "Set BMC Global Enables " command to follow here +// +typedef union { + struct { + UINT8 ReceiveMessageQueueInterrupt : 1; + UINT8 EventMessageBufferFullInterrupt : 1; + UINT8 EventMessageBuffer : 1; + UINT8 SystemEventLogging : 1; + UINT8 Reserved : 1; + UINT8 Oem0Enable : 1; + UINT8 Oem1Enable : 1; + UINT8 Oem2Enable : 1; + } Bits; + UINT8 Uint8; +} IPMI_BMC_GLOBAL_ENABLES; + +typedef struct { + IPMI_BMC_GLOBAL_ENABLES SetEnables; +} IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST; + +// +// Definitions for Get BMC Global Enables command +// +#define IPMI_APP_GET_BMC_GLOBAL_ENABLES 0x2F + +// +// Constants and Structure definitions for "Get BMC Global Enables " command to follow here +// +typedef struct { + UINT8 CompletionCode; + IPMI_BMC_GLOBAL_ENABLES GetEnables; +} IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE; + +// +// Definitions for Clear Message Flags command +// +#define IPMI_APP_CLEAR_MESSAGE_FLAGS 0x30 + +// +// Constants and Structure definitions for "Clear Message Flags" command to follow here +// +typedef union { + struct { + UINT8 ReceiveMessageQueue : 1; + UINT8 EventMessageBuffer : 1; + UINT8 Reserved1 : 1; + UINT8 WatchdogPerTimeoutInterrupt : 1; + UINT8 Reserved2 : 1; + UINT8 Oem0 : 1; + UINT8 Oem1 : 1; + UINT8 Oem2 : 1; + } Bits; + UINT8 Uint8; +} IPMI_MESSAGE_FLAGS; + +typedef struct { + IPMI_MESSAGE_FLAGS ClearFlags; +} IPMI_CLEAR_MESSAGE_FLAGS_REQUEST; + +// +// Definitions for Get Message Flags command +// +#define IPMI_APP_GET_MESSAGE_FLAGS 0x31 + +// +// Constants and Structure definitions for "Get Message Flags" command to follow here +// +typedef struct { + UINT8 CompletionCode; + IPMI_MESSAGE_FLAGS GetFlags; +} IPMI_GET_MESSAGE_FLAGS_RESPONSE; + +// +// Definitions for Enable Message Channel Receive command +// +#define IPMI_APP_ENABLE_MESSAGE_CHANNEL_RECEIVE 0x32 + +// +// Constants and Structure definitions for "Enable Message Channel Receive" command to follow here +// + +// +// Definitions for Get Message command +// +#define IPMI_APP_GET_MESSAGE 0x33 + +// +// Constants and Structure definitions for "Get Message" command to follow here +// +typedef union { + struct { + UINT8 ChannelNumber : 4; + UINT8 InferredPrivilegeLevel : 4; + } Bits; + UINT8 Uint8; +} IPMI_GET_MESSAGE_CHANNEL_NUMBER; + +typedef struct { + UINT8 CompletionCode; + IPMI_GET_MESSAGE_CHANNEL_NUMBER ChannelNumber; + UINT8 MessageData[0]; +} IPMI_GET_MESSAGE_RESPONSE; + +// +// Definitions for Send Message command +// +#define IPMI_APP_SEND_MESSAGE 0x34 + +// +// Constants and Structure definitions for "Send Message" command to follow here +// +typedef union { + struct { + UINT8 ChannelNumber : 4; + UINT8 Authentication : 1; + UINT8 Encryption : 1; + UINT8 Tracking : 2; + } Bits; + UINT8 Uint8; +} IPMI_SEND_MESSAGE_CHANNEL_NUMBER; + +typedef struct { + UINT8 CompletionCode; + IPMI_SEND_MESSAGE_CHANNEL_NUMBER ChannelNumber; + UINT8 MessageData[0]; +} IPMI_SEND_MESSAGE_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 ResponseData[0]; +} IPMI_SEND_MESSAGE_RESPONSE; + +// +// Definitions for Read Event Message Buffer command +// +#define IPMI_APP_READ_EVENT_MSG_BUFFER 0x35 + +// +// Constants and Structure definitions for "Read Event Message Buffer" command to follow here +// + +// +// Definitions for Get BT Interface Capabilities command +// +#define IPMI_APP_GET_BT_INTERFACE_CAPABILITY 0x36 + +// +// Constants and Structure definitions for "Get BT Interface Capabilities" command to follow here +// + +// +// Definitions for Get System GUID command +// +#define IPMI_APP_GET_SYSTEM_GUID 0x37 + +// +// Constants and Structure definitions for "Get System GUID" command to follow here +// + +// +// Definitions for Get Channel Authentication Capabilities command +// +#define IPMI_APP_GET_CHANNEL_AUTHENTICATION_CAPABILITIES 0x38 + +// +// Constants and Structure definitions for "Get Channel Authentication Capabilities" command to follow here +// + +// +// Definitions for Get Session Challenge command +// +#define IPMI_APP_GET_SESSION_CHALLENGE 0x39 + +// +// Constants and Structure definitions for "Get Session Challenge" command to follow here +// + +// +// Definitions for Activate Session command +// +#define IPMI_APP_ACTIVATE_SESSION 0x3A + +// +// Constants and Structure definitions for "Activate Session" command to follow here +// + +// +// Definitions for Set Session Privelege Level command +// +#define IPMI_APP_SET_SESSION_PRIVELEGE_LEVEL 0x3B + +// +// Constants and Structure definitions for "Set Session Privelege Level" command to follow here +// + +// +// Definitions for Close Session command +// +#define IPMI_APP_CLOSE_SESSION 0x3C + +// +// Constants and Structure definitions for "Close Session" command to follow here +// + +// +// Definitions for Get Session Info command +// +#define IPMI_APP_GET_SESSION_INFO 0x3D + +// +// Constants and Structure definitions for "Get Session Info" command to follow here +// + +// +// Definitions for Get Auth Code command +// +#define IPMI_APP_GET_AUTHCODE 0x3F + +// +// Constants and Structure definitions for "Get AuthCode" command to follow here +// + +// +// Definitions for Set Channel Access command +// +#define IPMI_APP_SET_CHANNEL_ACCESS 0x40 + +// +// Constants and Structure definitions for "Set Channel Access" command to follow here +// + +// +// Definitions for Get Channel Access command +// +#define IPMI_APP_GET_CHANNEL_ACCESS 0x41 + +// +// Constants and Structure definitions for "Get Channel Access" command to follow here +// + +// +// Definitions for channel access memory type in Get Channel Access command request +// +#define IPMI_CHANNEL_ACCESS_MEMORY_TYPE_NON_VOLATILE 0x1 +#define IPMI_CHANNEL_ACCESS_MEMORY_TYPE_PRESENT_VOLATILE_SETTING 0x2 + +// +// Definitions for channel access modes in Get Channel Access command response +// +#define IPMI_CHANNEL_ACCESS_MODES_DISABLED 0x0 +#define IPMI_CHANNEL_ACCESS_MODES_PRE_BOOT_ONLY 0x1 +#define IPMI_CHANNEL_ACCESS_MODES_ALWAYS_AVAILABLE 0x2 +#define IPMI_CHANNEL_ACCESS_MODES_SHARED 0x3 + +typedef union { + struct { + UINT8 ChannelNo : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_GET_CHANNEL_ACCESS_CHANNEL_NUMBER; + +typedef union { + struct { + UINT8 Reserved : 6; + UINT8 MemoryType : 2; + } Bits; + UINT8 Uint8; +} IPMI_GET_CHANNEL_ACCESS_TYPE; + +typedef struct { + IPMI_GET_CHANNEL_ACCESS_CHANNEL_NUMBER ChannelNumber; + IPMI_GET_CHANNEL_ACCESS_TYPE AccessType; +} IPMI_GET_CHANNEL_ACCESS_REQUEST; + +typedef union { + struct { + UINT8 AccessMode : 3; + UINT8 UserLevelAuthEnabled : 1; + UINT8 MessageAuthEnable : 1; + UINT8 Alert : 1; + UINT8 Reserved : 2; + } Bits; + UINT8 Uint8; +} IPMI_GET_CHANNEL_ACCESS_CHANNEL_ACCESS; + +typedef union { + struct { + UINT8 ChannelPriviledgeLimit : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_GET_CHANNEL_ACCESS_PRIVILEGE_LIMIT; + +typedef struct { + UINT8 CompletionCode; + IPMI_GET_CHANNEL_ACCESS_CHANNEL_ACCESS ChannelAccess; + IPMI_GET_CHANNEL_ACCESS_PRIVILEGE_LIMIT PrivilegeLimit; +} IPMI_GET_CHANNEL_ACCESS_RESPONSE; + +// +// Definitions for Get Channel Info command +// +#define IPMI_APP_GET_CHANNEL_INFO 0x42 + +// +// Constants and Structure definitions for "Get Channel Info" command to follow here +// + +// +// Definitions for channel media type +// +// IPMB (I2C) +#define IPMI_CHANNEL_MEDIA_TYPE_IPMB 0x1 +// ICMB v1.0 +#define IPMI_CHANNEL_MEDIA_TYPE_ICMB_1_0 0x2 +// ICMB v0.9 +#define IPMI_CHANNEL_MEDIA_TYPE_ICMB_0_9 0x3 +// 802.3 LAN +#define IPMI_CHANNEL_MEDIA_TYPE_802_3_LAN 0x4 +// Asynch. Serial/Modem (RS-232) +#define IPMI_CHANNEL_MEDIA_TYPE_RS_232 0x5 +// Other LAN +#define IPMI_CHANNEL_MEDIA_TYPE_OTHER_LAN 0x6 +// PCI SMBus +#define IPMI_CHANNEL_MEDIA_TYPE_PCI_SM_BUS 0x7 +// SMBus v1.0/1.1 +#define IPMI_CHANNEL_MEDIA_TYPE_SM_BUS_V1 0x8 +// SMBus v2.0 +#define IPMI_CHANNEL_MEDIA_TYPE_SM_BUS_V2 0x9 +// USB 1.x +#define IPMI_CHANNEL_MEDIA_TYPE_USB1 0xA +// USB 2.x +#define IPMI_CHANNEL_MEDIA_TYPE_USB2 0xB +// System Interface (KCS, SMIC, or BT) +#define IPMI_CHANNEL_MEDIA_TYPE_SYSTEM_INTERFACE 0xC +// OEM +#define IPMI_CHANNEL_MEDIA_TYPE_OEM_START 0x60 +#define IPMI_CHANNEL_MEDIA_TYPE_OEM_END 0x7F + +typedef union { + struct { + UINT8 ChannelNo : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_CHANNEL_INFO_CHANNEL_NUMBER; + +typedef union { + struct { + UINT8 ChannelMediumType : 7; + UINT8 Reserved : 1; + } Bits; + UINT8 Uint8; +} IPMI_CHANNEL_INFO_MEDIUM_TYPE; + +typedef union { + struct { + UINT8 ChannelProtocolType : 5; + UINT8 Reserved : 3; + } Bits; + UINT8 Uint8; +} IPMI_CHANNEL_INFO_PROTOCOL_TYPE; + +typedef union { + struct { + UINT8 ActiveSessionCount : 6; + UINT8 SessionSupport : 2; + } Bits; + UINT8 Uint8; +} IPMI_CHANNEL_INFO_SESSION_SUPPORT; + +typedef struct { + UINT8 CompletionCode; + IPMI_CHANNEL_INFO_CHANNEL_NUMBER ChannelNumber; + IPMI_CHANNEL_INFO_MEDIUM_TYPE MediumType; + IPMI_CHANNEL_INFO_PROTOCOL_TYPE ProtocolType; + IPMI_CHANNEL_INFO_SESSION_SUPPORT SessionSupport; + UINT8 VendorId[3]; + UINT16 AuxChannelInfo; +} IPMI_GET_CHANNEL_INFO_RESPONSE; + +// +// Definitions for Get Channel Info command +// +#define IPMI_APP_GET_CHANNEL_INFO 0x42 + +// +// Constants and Structure definitions for "Get Channel Info" command to follow here +// + +// +// Definitions for Set User Access command +// +#define IPMI_APP_SET_USER_ACCESS 0x43 + +// +// Constants and Structure definitions for "Set User Access" command to follow here +// + +// +// Definitions for Get User Access command +// +#define IPMI_APP_GET_USER_ACCESS 0x44 + +// +// Constants and Structure definitions for "Get User Access" command to follow here +// +typedef union { + struct { + UINT8 ChannelNo : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_GET_USER_ACCESS_CHANNEL_NUMBER; + +typedef union { + struct { + UINT8 UserId : 6; + UINT8 Reserved : 2; + } Bits; + UINT8 Uint8; +} IPMI_USER_ID; + +typedef struct { + IPMI_GET_USER_ACCESS_CHANNEL_NUMBER ChannelNumber; + IPMI_USER_ID UserId; +} IPMI_GET_USER_ACCESS_REQUEST; + +typedef union { + struct { + UINT8 MaxUserId : 6; + UINT8 Reserved : 2; + } Bits; + UINT8 Uint8; +} IPMI_GET_USER_ACCESS_MAX_USER_ID; + +typedef union { + struct { + UINT8 CurrentUserId : 6; + UINT8 UserIdEnableStatus : 2; + } Bits; + UINT8 Uint8; +} IPMI_GET_USER_ACCESS_CURRENT_USER; + +typedef union { + struct { + UINT8 FixedUserId : 6; + UINT8 Reserved : 2; + } Bits; + UINT8 Uint8; +} IPMI_GET_USER_ACCESS_FIXED_NAME_USER; + +typedef union { + struct { + UINT8 UserPrivilegeLimit : 4; + UINT8 EnableIpmiMessaging : 1; + UINT8 EnableUserLinkAuthetication : 1; + UINT8 UserAccessAvailable : 1; + UINT8 Reserved : 1; + } Bits; + UINT8 Uint8; +} IPMI_GET_USER_ACCESS_CHANNEL_ACCESS; + +typedef struct { + UINT8 CompletionCode; + IPMI_GET_USER_ACCESS_MAX_USER_ID MaxUserId; + IPMI_GET_USER_ACCESS_CURRENT_USER CurrentUser; + IPMI_GET_USER_ACCESS_FIXED_NAME_USER FixedNameUser; + IPMI_GET_USER_ACCESS_CHANNEL_ACCESS ChannelAccess; +} IPMI_GET_USER_ACCESS_RESPONSE; + +// +// Definitions for Set User Name command +// +#define IPMI_APP_SET_USER_NAME 0x45 + +// +// Constants and Structure definitions for "Set User Name" command to follow here +// +typedef struct { + IPMI_USER_ID UserId; + UINT8 UserName[16]; +} IPMI_SET_USER_NAME_REQUEST; + +// +// Definitions for Get User Name command +// +#define IPMI_APP_GET_USER_NAME 0x46 + +// +// Constants and Structure definitions for "Get User Name" command to follow here +// +typedef struct { + IPMI_USER_ID UserId; +} IPMI_GET_USER_NAME_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 UserName[16]; +} IPMI_GET_USER_NAME_RESPONSE; + +// +// Definitions for Set User Password command +// +#define IPMI_APP_SET_USER_PASSWORD 0x47 + +// +// Constants and Structure definitions for "Set User Password" command to follow here +// + +// +// Definitions for Set User password command operation type +// +#define IPMI_SET_USER_PASSWORD_OPERATION_TYPE_DISABLE_USER 0x0 +#define IPMI_SET_USER_PASSWORD_OPERATION_TYPE_ENABLE_USER 0x1 +#define IPMI_SET_USER_PASSWORD_OPERATION_TYPE_SET_PASSWORD 0x2 +#define IPMI_SET_USER_PASSWORD_OPERATION_TYPE_TEST_PASSWORD 0x3 + +// +// Definitions for Set user password command password size +// +#define IPMI_SET_USER_PASSWORD_PASSWORD_SIZE_16 0x0 +#define IPMI_SET_USER_PASSWORD_PASSWORD_SIZE_20 0x1 + +typedef union { + struct { + UINT8 UserId : 6; + UINT8 Reserved : 1; + UINT8 PasswordSize : 1; + } Bits; + UINT8 Uint8; +} IPMI_SET_USER_PASSWORD_USER_ID; + +typedef union { + struct { + UINT8 Operation : 2; + UINT8 Reserved : 6; + } Bits; + UINT8 Uint8; +} IPMI_SET_USER_PASSWORD_OPERATION; + +typedef struct { + IPMI_SET_USER_PASSWORD_USER_ID UserId; + IPMI_SET_USER_PASSWORD_OPERATION Operation; + UINT8 PasswordData[0]; // 16 or 20 bytes, depending on the 'PasswordSize' field +} IPMI_SET_USER_PASSWORD_REQUEST; + +// +// Below is Definitions for RMCP+ Support and Payload Commands (Chapter 24) +// + +// +// Definitions for Activate Payload command +// +#define IPMI_APP_ACTIVATE_PAYLOAD 0x48 + +// +// Constants and Structure definitions for "Activate Payload" command to follow here +// + +// +// Definitions for De-Activate Payload command +// +#define IPMI_APP_DEACTIVATE_PAYLOAD 0x49 + +// +// Constants and Structure definitions for "DeActivate Payload" command to follow here +// + +// +// Definitions for Get Payload activation Status command +// +#define IPMI_APP_GET_PAYLOAD_ACTIVATION_STATUS 0x4a + +// +// Constants and Structure definitions for "Get Payload activation Status" command to follow here +// + +// +// Definitions for Get Payload Instance Info command +// +#define IPMI_APP_GET_PAYLOAD_INSTANCE_INFO 0x4b + +// +// Constants and Structure definitions for "Get Payload Instance Info" command to follow here +// + +// +// Definitions for Set User Payload Access command +// +#define IPMI_APP_SET_USER_PAYLOAD_ACCESS 0x4C + +// +// Constants and Structure definitions for "Set User Payload Access" command to follow here +// + +// +// Definitions for Get User Payload Access command +// +#define IPMI_APP_GET_USER_PAYLOAD_ACCESS 0x4D + +// +// Constants and Structure definitions for "Get User Payload Access" command to follow here +// + +// +// Definitions for Get Channel Payload Support command +// +#define IPMI_APP_GET_CHANNEL_PAYLOAD_SUPPORT 0x4E + +// +// Constants and Structure definitions for "Get Channel Payload Support" command to follow here +// + +// +// Definitions for Get Channel Payload Version command +// +#define IPMI_APP_GET_CHANNEL_PAYLOAD_VERSION 0x4F + +// +// Constants and Structure definitions for "Get Channel Payload Version" command to follow here +// + +// +// Definitions for Get Channel OEM Payload Info command +// +#define IPMI_APP_GET_CHANNEL_OEM_PAYLOAD_INFO 0x50 + +// +// Constants and Structure definitions for "Get Channel OEM Payload Info" command to follow here +// + +// +// Definitions for Master Write-Read command +// +#define IPMI_APP_MASTER_WRITE_READ 0x52 + +// +// Constants and Structure definitions for "Master Write Read" command to follow here +// + +// +// Definitions for Get Channel Cipher Suites command +// +#define IPMI_APP_GET_CHANNEL_CIPHER_SUITES 0x54 + +// +// Constants and Structure definitions for "Get Channel Cipher Suites" command to follow here +// + +// +// Below is Definitions for RMCP+ Support and Payload Commands (Chapter 24, Section 3) +// + +// +// Definitions for Suspend-Resume Payload Encryption command +// +#define IPMI_APP_SUSPEND_RESUME_PAYLOAD_ENCRYPTION 0x55 + +// +// Constants and Structure definitions for "Suspend-Resume Payload Encryption" command to follow here +// + +// +// Below is Definitions for IPMI Messaging Support Commands (Chapter 22, Section 25 and 9) +// + +// +// Definitions for Set Channel Security Keys command +// +#define IPMI_APP_SET_CHANNEL_SECURITY_KEYS 0x56 + +// +// Constants and Structure definitions for "Set Channel Security Keys" command to follow here +// + +// +// Definitions for Get System Interface Capabilities command +// +#define IPMI_APP_GET_SYSTEM_INTERFACE_CAPABILITIES 0x57 + +// +// Constants and Structure definitions for "Get System Interface Capabilities" command to follow here +// + +// +// Definitions for Get System Interface Capabilities command SSIF transaction support +// +#define IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_SSIF_TRANSACTION_SUPPORT_SINGLE_PARTITION_RW 0x0 +#define IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_SSIF_TRANSACTION_SUPPORT_MULTI_PARTITION_RW 0x1 +#define IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_SSIF_TRANSACTION_SUPPORT_MULTI_PARTITION_RW_WITH_MIDDLE 0x2 + +#pragma pack() +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnBridge.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnBridge.h new file mode 100644 index 0000000..7f174fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnBridge.h @@ -0,0 +1,243 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + IPMI Intelligent Chassis Management Bus Bridge Specification Version 1.0, + Revision 1.3. + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_BRIDGE_H_ +#define _IPMI_NET_FN_BRIDGE_H_ + +// +// Net function definition for Bridge command +// +#define IPMI_NETFN_BRIDGE 0x02 + +// +// Definitions for Get Bridge State command +// +#define IPMI_BRIDGE_GET_STATE 0x00 + +// +// Constants and Structure definitions for "Get Bridge State" command to follow here +// + +// +// Definitions for Set Bridge State command +// +#define IPMI_BRIDGE_SET_STATE 0x01 + +// +// Constants and Structure definitions for "Set Bridge State" command to follow here +// + +// +// Definitions for Get ICMB Address command +// +#define IPMI_BRIDGE_GET_ICMB_ADDRESS 0x02 + +// +// Constants and Structure definitions for "Get ICMB Address" command to follow here +// + +// +// Definitions for Set ICMB Address command +// +#define IPMI_BRIDGE_SET_ICMB_ADDRESS 0x03 + +// +// Constants and Structure definitions for "Set ICMB Address" command to follow here +// + +// +// Definitions for Set Bridge Proxy Address command +// +#define IPMI_BRIDGE_SET_PROXY_ADDRESS 0x04 + +// +// Constants and Structure definitions for "Set Bridge Proxy Address" command to follow here +// + +// +// Definitions for Get Bridge Statistics command +// +#define IPMI_BRIDGE_GET_BRIDGE_STATISTICS 0x05 + +// +// Constants and Structure definitions for "Get Bridge Statistics" command to follow here +// + +// +// Definitions for Get ICMB Capabilities command +// +#define IPMI_BRIDGE_GET_ICMB_CAPABILITIES 0x06 + +// +// Constants and Structure definitions for "Get ICMB Capabilities" command to follow here +// + +// +// Definitions for Clear Bridge Statistics command +// +#define IPMI_BRIDGE_CLEAR_STATISTICS 0x08 + +// +// Constants and Structure definitions for "Clear Bridge Statistics" command to follow here +// + +// +// Definitions for Get Bridge Proxy Address command +// +#define IPMI_BRIDGE_GET_PROXY_ADDRESS 0x09 + +// +// Constants and Structure definitions for "Get Bridge Proxy Address" command to follow here +// + +// +// Definitions for Get ICMB Connector Info command +// +#define IPMI_BRIDGE_GET_ICMB_CONNECTOR_INFO 0x0A + +// +// Constants and Structure definitions for "Get ICMB Connector Info " command to follow here +// + +// +// Definitions for Get ICMB Connection ID command +// +#define IPMI_BRIDGE_GET_ICMB_CONNECTION_ID 0x0B + +// +// Constants and Structure definitions for "Get ICMB Connection ID" command to follow here +// + +// +// Definitions for Get ICMB Connection ID command +// +#define IPMI_BRIDGE_SEND_ICMB_CONNECTION_ID 0x0C + +// +// Constants and Structure definitions for "Send ICMB Connection ID" command to follow here +// + +// +// Definitions for Prepare for Discoveery command +// +#define IPMI_BRIDGE_PREPARE_FOR_DISCOVERY 0x10 + +// +// Constants and Structure definitions for "Prepare for Discoveery" command to follow here +// + +// +// Definitions for Get Addresses command +// +#define IPMI_BRIDGE_GET_ADDRESSES 0x11 + +// +// Constants and Structure definitions for "Get Addresses" command to follow here +// + +// +// Definitions for Set Discovered command +// +#define IPMI_BRIDGE_SET_DISCOVERED 0x12 + +// +// Constants and Structure definitions for "Set Discovered" command to follow here +// + +// +// Definitions for Get Chassis Device ID command +// +#define IPMI_BRIDGE_GET_CHASSIS_DEVICEID 0x13 + +// +// Constants and Structure definitions for "Get Chassis Device ID" command to follow here +// + +// +// Definitions for Set Chassis Device ID command +// +#define IPMI_BRIDGE_SET_CHASSIS_DEVICEID 0x14 + +// +// Constants and Structure definitions for "Set Chassis Device ID" command to follow here +// + +// +// Definitions for Bridge Request command +// +#define IPMI_BRIDGE_REQUEST 0x20 + +// +// Constants and Structure definitions for "Bridge Request" command to follow here +// + +// +// Definitions for Bridge Message command +// +#define IPMI_BRIDGE_MESSAGE 0x21 + +// +// Constants and Structure definitions for "Bridge Message" command to follow here +// + +// +// Definitions for Get Event Count command +// +#define IPMI_BRIDGE_GET_EVENT_COUNT 0x30 + +// +// Constants and Structure definitions for "Get Event Count" command to follow here +// + +// +// Definitions for Set Event Destination command +// +#define IPMI_BRIDGE_SET_EVENT_DESTINATION 0x31 + +// +// Constants and Structure definitions for "Set Event Destination" command to follow here +// + +// +// Definitions for Set Event Reception State command +// +#define IPMI_BRIDGE_SET_EVENT_RECEPTION_STATE 0x32 + +// +// Constants and Structure definitions for "Set Event Reception State" command to follow here +// + +// +// Definitions for Set Event Reception State command +// +#define IPMI_BRIDGE_SET_EVENT_RECEPTION_STATE 0x32 + +// +// Constants and Structure definitions for "Set Event Reception State" command to follow here +// + +// +// Definitions for Send ICMB Event Message command +// +#define IPMI_BRIDGE_SEND_ICMB_EVENT_MESSAGE 0x33 + +// +// Constants and Structure definitions for "Send ICMB Event Message" command to follow here +// + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnChassis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnChassis.h new file mode 100644 index 0000000..f70fc74 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnChassis.h @@ -0,0 +1,464 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + This file contains all NetFn Chassis commands, including: + Chassis Commands (Chapter 28) + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_CHASSIS_H_ +#define _IPMI_NET_FN_CHASSIS_H_ + +#pragma pack (1) +// +// Net function definition for Chassis command +// +#define IPMI_NETFN_CHASSIS 0x00 + +// +// Below is Definitions for Chassis commands (Chapter 28) +// + +// +// Definitions for Get Chassis Capabilities command +// +#define IPMI_CHASSIS_GET_CAPABILITIES 0x00 + +// +// Constants and Structure definitions for "Get Chassis Capabilities" command to follow here +// +typedef struct { + UINT8 CompletionCode; + UINT8 CapabilitiesFlags; + UINT8 ChassisFruInfoDeviceAddress; + UINT8 ChassisSDRDeviceAddress; + UINT8 ChassisSELDeviceAddress; + UINT8 ChassisSystemManagementDeviceAddress; + UINT8 ChassisBridgeDeviceAddress; +} IPMI_GET_CHASSIS_CAPABILITIES_RESPONSE; + +// +// Definitions for Get Chassis Status command +// +#define IPMI_CHASSIS_GET_STATUS 0x01 + +// +// Constants and Structure definitions for "Get Chassis Status" command to follow here +// +typedef struct { + UINT8 CompletionCode; + UINT8 CurrentPowerState; + UINT8 LastPowerEvent; + UINT8 MiscChassisState; + UINT8 FrontPanelButtonCapabilities; +} IPMI_GET_CHASSIS_STATUS_RESPONSE; + +// +// Definitions for Chassis Control command +// +#define IPMI_CHASSIS_CONTROL 0x02 + +// +// Constants and Structure definitions for "Chassis Control" command to follow here +// +typedef union { + struct { + UINT8 ChassisControl:4; + UINT8 Reserved:4; + } Bits; + UINT8 Uint8; +} IPMI_CHASSIS_CONTROL_CHASSIS_CONTROL; + +typedef struct { + IPMI_CHASSIS_CONTROL_CHASSIS_CONTROL ChassisControl; +} IPMI_CHASSIS_CONTROL_REQUEST; + +// +// Definitions for Chassis Reset command +// +#define IPMI_CHASSIS_RESET 0x03 + +// +// Constants and Structure definitions for "Chassis Reset" command to follow here +// + +// +// Definitions for Chassis Identify command +// +#define IPMI_CHASSIS_IDENTIFY 0x04 + +// +// Constants and Structure definitions for "Chassis Identify" command to follow here +// + +// +// Definitions for Set Chassis Capabilities command +// +#define IPMI_CHASSIS_SET_CAPABILITIES 0x05 + +// +// Constants and Structure definitions for "Set Chassis Capabilities" command to follow here +// + +// +// Definitions for Set Power Restore Policy command +// +#define IPMI_CHASSIS_SET_POWER_RESTORE_POLICY 0x06 + +// +// Constants and Structure definitions for "Set Power Restore Policy" command to follow here +// +typedef union { + struct { + UINT8 PowerRestorePolicy : 3; + UINT8 Reserved : 5; + } Bits; + UINT8 Uint8; +} IPMI_POWER_RESTORE_POLICY; + +typedef struct { + IPMI_POWER_RESTORE_POLICY PowerRestorePolicy; +} IPMI_SET_POWER_RESTORE_POLICY_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 PowerRestorePolicySupport; +} IPMI_SET_POWER_RESTORE_POLICY_RESPONSE; + +// +// Definitions for Get System Restart Cause command +// +#define IPMI_CHASSIS_GET_SYSTEM_RESTART_CAUSE 0x07 + +// +// Constants and Structure definitions for "Get System Restart Cause" command to follow here +// +#define IPMI_SYSTEM_RESTART_CAUSE_UNKNOWN 0x0 +#define IPMI_SYSTEM_RESTART_CAUSE_CHASSIS_CONTROL_COMMAND 0x1 +#define IPMI_SYSTEM_RESTART_CAUSE_PUSHBUTTON_RESET 0x2 +#define IPMI_SYSTEM_RESTART_CAUSE_PUSHBUTTON_POWERUP 0x3 +#define IPMI_SYSTEM_RESTART_CAUSE_WATCHDOG_EXPIRE 0x4 +#define IPMI_SYSTEM_RESTART_CAUSE_OEM 0x5 +#define IPMI_SYSTEM_RESTART_CAUSE_AUTO_POWER_ALWAYS_RESTORE 0x6 +#define IPMI_SYSTEM_RESTART_CAUSE_AUTO_POWER_RESTORE_PREV 0x7 +#define IPMI_SYSTEM_RESTART_CAUSE_PEF_RESET 0x8 +#define IPMI_SYSTEM_RESTART_CAUSE_PEF_POWERCYCLE 0x9 +#define IPMI_SYSTEM_RESTART_CAUSE_SOFT_RESET 0xA +#define IPMI_SYSTEM_RESTART_CAUSE_RTC_POWERUP 0xB + +typedef union { + struct { + UINT8 Cause:4; + UINT8 Reserved:4; + } Bits; + UINT8 Uint8; +} IPMI_SYSTEM_RESTART_CAUSE; + +typedef struct { + UINT8 CompletionCode; + IPMI_SYSTEM_RESTART_CAUSE RestartCause; + UINT8 ChannelNumber; +} IPMI_GET_SYSTEM_RESTART_CAUSE_RESPONSE; + +// +// Definitions for Set System BOOT options command +// +#define IPMI_CHASSIS_SET_SYSTEM_BOOT_OPTIONS 0x08 + +// +// Constants and Structure definitions for "Set System boot options" command to follow here +// +typedef union { + struct { + UINT8 ParameterSelector:7; + UINT8 MarkParameterInvalid:1; + } Bits; + UINT8 Uint8; +} IPMI_SET_BOOT_OPTIONS_PARAMETER_VALID; + +typedef struct { + IPMI_SET_BOOT_OPTIONS_PARAMETER_VALID ParameterValid; + UINT8 ParameterData[0]; +} IPMI_SET_BOOT_OPTIONS_REQUEST; + +// +// Definitions for Get System Boot options command +// +#define IPMI_CHASSIS_GET_SYSTEM_BOOT_OPTIONS 0x09 + +// +// Constants and Structure definitions for "Get System boot options" command to follow here +// +typedef union { + struct { + UINT8 ParameterSelector:7; + UINT8 Reserved:1; + } Bits; + UINT8 Uint8; +} IPMI_GET_BOOT_OPTIONS_PARAMETER_SELECTOR; + +typedef struct { + IPMI_GET_BOOT_OPTIONS_PARAMETER_SELECTOR ParameterSelector; + UINT8 SetSelector; + UINT8 BlockSelector; +} IPMI_GET_BOOT_OPTIONS_REQUEST; + +typedef struct { + UINT8 Parameter; + UINT8 Valid; + UINT8 Data1; + UINT8 Data2; + UINT8 Data3; + UINT8 Data4; + UINT8 Data5; +} IPMI_GET_THE_SYSTEM_BOOT_OPTIONS; + +typedef struct { + UINT8 ParameterVersion; + UINT8 ParameterValid; + UINT8 ChannelNumber; + UINT32 SessionId; + UINT32 TimeStamp; + UINT8 Reserved[3]; +} IPMI_BOOT_INITIATOR; + +// +// Definitions for boot option parameter selector +// +#define IPMI_BOOT_OPTIONS_PARAMETER_SELECTOR_SET_IN_PROGRESS 0x0 +#define IPMI_BOOT_OPTIONS_PARAMETER_SELECTOR_SERVICE_PARTITION_SELECTOR 0x1 +#define IPMI_BOOT_OPTIONS_PARAMETER_SELECTOR_SERVICE_PARTITION_SCAN 0x2 +#define IPMI_BOOT_OPTIONS_PARAMETER_SELECTOR_BMC_BOOT_FLAG 0x3 +#define IPMI_BOOT_OPTIONS_PARAMETER_BOOT_INFO_ACK 0x4 +#define IPMI_BOOT_OPTIONS_PARAMETER_BOOT_FLAGS 0x5 +#define IPMI_BOOT_OPTIONS_PARAMETER_BOOT_INITIATOR_INFO 0x6 +#define IPMI_BOOT_OPTIONS_PARAMETER_BOOT_INITIATOR_MAILBOX 0x7 +#define IPMI_BOOT_OPTIONS_PARAMETER_OEM_BEGIN 0x60 +#define IPMI_BOOT_OPTIONS_PARAMETER_OEM_END 0x7F + +// +// Response Parameters for IPMI Get Boot Options +// +typedef union { + struct { + UINT8 SetInProgress : 2; + UINT8 Reserved : 6; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_0; + +typedef struct { + UINT8 ServicePartitionSelector; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_1; + +typedef union { + struct { + UINT8 ServicePartitionDiscovered : 1; + UINT8 ServicePartitionScanRequest : 1; + UINT8 Reserved: 6; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_2; + +typedef union { + struct { + UINT8 BmcBootFlagValid : 5; + UINT8 Reserved : 3; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_3; + +typedef struct { + UINT8 WriteMask; + UINT8 BootInitiatorAcknowledgeData; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_4; + +// +// Definitions for the 'Boot device selector' field of Boot Option Parameters #5 +// +#define IPMI_BOOT_DEVICE_SELECTOR_NO_OVERRIDE 0x0 +#define IPMI_BOOT_DEVICE_SELECTOR_PXE 0x1 +#define IPMI_BOOT_DEVICE_SELECTOR_HARDDRIVE 0x2 +#define IPMI_BOOT_DEVICE_SELECTOR_HARDDRIVE_SAFE_MODE 0x3 +#define IPMI_BOOT_DEVICE_SELECTOR_DIAGNOSTIC_PARTITION 0x4 +#define IPMI_BOOT_DEVICE_SELECTOR_CD_DVD 0x5 +#define IPMI_BOOT_DEVICE_SELECTOR_BIOS_SETUP 0x6 +#define IPMI_BOOT_DEVICE_SELECTOR_REMOTE_FLOPPY 0x7 +#define IPMI_BOOT_DEVICE_SELECTOR_REMOTE_CD_DVD 0x8 +#define IPMI_BOOT_DEVICE_SELECTOR_PRIMARY_REMOTE_MEDIA 0x9 +#define IPMI_BOOT_DEVICE_SELECTOR_REMOTE_HARDDRIVE 0xB +#define IPMI_BOOT_DEVICE_SELECTOR_FLOPPY 0xF + +#define BOOT_OPTION_HANDLED_BY_BIOS 0x01 + +// +// Constant definitions for the 'BIOS Mux Control Override' field of Boot Option Parameters #5 +// +#define BIOS_MUX_CONTROL_OVERRIDE_RECOMMEND_SETTING 0x00 +#define BIOS_MUX_CONTROL_OVERRIDE_FORCE_TO_BMC 0x01 +#define BIOS_MUX_CONTROL_OVERRIDE_FORCE_TO_SYSTEM 0x02 + +typedef union { + struct { + UINT8 Reserved:5; + UINT8 BiosBootType:1; + UINT8 PersistentOptions:1; + UINT8 BootFlagValid:1; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_1; + +typedef union { + struct { + UINT8 LockReset:1; + UINT8 ScreenBlank:1; + UINT8 BootDeviceSelector:4; + UINT8 LockKeyboard:1; + UINT8 CmosClear:1; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_2; + +typedef union { + struct { + UINT8 ConsoleRedirection:2; + UINT8 LockSleep:1; + UINT8 UserPasswordBypass:1; + UINT8 ForceProgressEventTrap:1; + UINT8 BiosVerbosity:2; + UINT8 LockPower:1; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_3; + +typedef union { + struct { + UINT8 BiosMuxControlOverride:3; + UINT8 BiosSharedModeOverride:1; + UINT8 Reserved:4; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_4; + +typedef union { + struct { + UINT8 DeviceInstanceSelector:5; + UINT8 Reserved:3; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_5; + +typedef struct { + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_1 Data1; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_2 Data2; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_3 Data3; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_4 Data4; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5_DATA_5 Data5; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5; + +typedef union { + struct { + UINT8 ChannelNumber:4; + UINT8 Reserved:4; + } Bits; + UINT8 Uint8; +} IPMI_BOOT_OPTIONS_CHANNEL_NUMBER; + +typedef struct { + IPMI_BOOT_OPTIONS_CHANNEL_NUMBER ChannelNumber; + UINT8 SessionId[4]; + UINT8 BootInfoTimeStamp[4]; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_6; + +typedef struct { + UINT8 SetSelector; + UINT8 BlockData[16]; +} IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_7; + +typedef union { + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_0 Parm0; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_1 Parm1; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_2 Parm2; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_3 Parm3; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_4 Parm4; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_5 Parm5; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_6 Parm6; + IPMI_BOOT_OPTIONS_RESPONSE_PARAMETER_7 Parm7; +} IPMI_BOOT_OPTIONS_PARAMETERS; + +typedef union { + struct { + UINT8 ParameterVersion:4; + UINT8 Reserved:4; + } Bits; + UINT8 Uint8; +} IPMI_GET_BOOT_OPTIONS_PARAMETER_VERSION; + +typedef union { + struct { + UINT8 ParameterSelector:7; + UINT8 ParameterValid:1; + } Bits; + UINT8 Uint8; +} IPMI_GET_BOOT_OPTIONS_PARAMETER_VALID; + +typedef struct { + UINT8 CompletionCode; + IPMI_GET_BOOT_OPTIONS_PARAMETER_VERSION ParameterVersion; + IPMI_GET_BOOT_OPTIONS_PARAMETER_VALID ParameterValid; + UINT8 ParameterData[0]; +} IPMI_GET_BOOT_OPTIONS_RESPONSE; + +// +// Definitions for Set front panel button enables command +// +#define IPMI_CHASSIS_SET_FRONT_PANEL_BUTTON_ENABLES 0x0A + +// +// Constants and Structure definitions for "Set front panel button enables" command to follow here +// +typedef union { + struct { + UINT8 DisablePoweroffButton:1; + UINT8 DisableResetButton:1; + UINT8 DisableDiagnosticInterruptButton:1; + UINT8 DisableStandbyButton:1; + UINT8 Reserved:4; + } Bits; + UINT8 Uint8; +} IPMI_FRONT_PANEL_BUTTON_ENABLES; + +typedef struct { + IPMI_FRONT_PANEL_BUTTON_ENABLES FrontPanelButtonEnables; +} IPMI_CHASSIS_SET_FRONT_PANEL_BUTTON_ENABLES_REQUEST; + +// +// Definitions for Set Power Cycle Interval command +// +#define IPMI_CHASSIS_SET_POWER_CYCLE_INTERVALS 0x0B + +// +// Constants and Structure definitions for "Set Power Cycle Interval" command to follow here +// + +// +// Definitions for Get POH Counter command +// +#define IPMI_CHASSIS_GET_POH_COUNTER 0x0F + +// +// Constants and Structure definitions for "Get POH Counter" command to follow here +// +#pragma pack() +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnFirmware.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnFirmware.h new file mode 100644 index 0000000..aba3c41 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnFirmware.h @@ -0,0 +1,26 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_FIRMWARE_H_ +#define _IPMI_NET_FN_FIRMWARE_H_ + +// +// Net function definition for Firmware command +// +#define IPMI_NETFN_FIRMWARE 0x08 + +// +// All Firmware commands and their structure definitions to follow here +// + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnGroupExtension.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnGroupExtension.h new file mode 100644 index 0000000..2a8ec69 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnGroupExtension.h @@ -0,0 +1,26 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_GROUP_EXTENSION_H_ +#define _IPMI_NET_FN_GROUP_EXTENSION_H_ + +// +// Net function definition for Group Extension command +// +#define IPMI_NETFN_GROUP_EXT 0x2C + +// +// All Group Extension commands and their structure definitions to follow here +// + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h new file mode 100644 index 0000000..f9d851e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h @@ -0,0 +1,52 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + This file contains all NetFn Sensor/Event commands, including: + Event Commands (Chapter 29) + PEF and Alerting Commands (Chapter 30) + Sensor Device Commands (Chapter 35) + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_SENSOR_EVENT_H_ +#define _IPMI_NET_FN_SENSOR_EVENT_H_ + +#pragma pack(1) +// +// Net function definition for Sensor command +// +#define IPMI_NETFN_SENSOR_EVENT 0x04 + +// +// All Sensor commands and their structure definitions to follow here +// + +// +// Definitions for Send Platform Event Message command +// +#define IPMI_SENSOR_PLATFORM_EVENT_MESSAGE 0x02 + +typedef struct { + UINT8 GeneratorId; + UINT8 EvMRevision; + UINT8 SensorType; + UINT8 SensorNumber; + UINT8 EventDirType; + UINT8 OEMEvData1; + UINT8 OEMEvData2; + UINT8 OEMEvData3; +} IPMI_PLATFORM_EVENT_MESSAGE_DATA_REQUEST; + +#pragma pack() +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnStorage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnStorage.h new file mode 100644 index 0000000..f176f34 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnStorage.h @@ -0,0 +1,789 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + This file contains all NetFn Storage commands, including: + FRU Inventory Commands (Chapter 34) + SDR Repository (Chapter 33) + System Event Log(SEL) Commands (Chapter 31) + SEL Record Formats (Chapter 32) + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_STORAGE_H_ +#define _IPMI_NET_FN_STORAGE_H_ + +#pragma pack(1) +// +// Net function definition for Storage command +// +#define IPMI_NETFN_STORAGE 0x0A + +// +// All Storage commands and their structure definitions to follow here +// + +// +// Below is Definitions for FRU Inventory Commands (Chapter 34) +// + +// +// Definitions for Get Fru Inventory Area Info command +// +#define IPMI_STORAGE_GET_FRU_INVENTORY_AREAINFO 0x10 + +// +// Constants and Structure definitions for "Get Fru Inventory Area Info" command to follow here +// +typedef struct { + UINT8 DeviceId; +} IPMI_GET_FRU_INVENTORY_AREA_INFO_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT16 InventoryAreaSize; + UINT8 AccessType; +} IPMI_GET_FRU_INVENTORY_AREA_INFO_RESPONSE; + +// +// Definitions for Read Fru Data command +// +#define IPMI_STORAGE_READ_FRU_DATA 0x11 + +// +// Constants and Structure definitions for "Read Fru Data" command to follow here +// +typedef struct { + UINT8 FruDeviceId; + UINT16 FruOffset; +} IPMI_FRU_COMMON_DATA; + +typedef struct { + IPMI_FRU_COMMON_DATA Data; + UINT8 Count; +} IPMI_FRU_READ_COMMAND; + +typedef struct { + UINT8 DeviceId; + UINT16 InventoryOffset; + UINT8 CountToRead; +} IPMI_READ_FRU_DATA_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 CountReturned; + UINT8 Data[0]; +} IPMI_READ_FRU_DATA_RESPONSE; + +// +// Definitions for Write Fru Data command +// +#define IPMI_STORAGE_WRITE_FRU_DATA 0x12 + +// +// Constants and Structure definitions for "Write Fru Data" command to follow here +// +typedef struct { + IPMI_FRU_COMMON_DATA Data; + UINT8 FruData[16]; +} IPMI_FRU_WRITE_COMMAND; + +typedef struct { + UINT8 DeviceId; + UINT16 InventoryOffset; + UINT8 Data[0]; +} IPMI_WRITE_FRU_DATA_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 CountWritten; +} IPMI_WRITE_FRU_DATA_RESPONSE; + +// +// Below is Definitions for SDR Repository (Chapter 33) +// + +// +// Definitions for Get SDR Repository Info command +// +#define IPMI_STORAGE_GET_SDR_REPOSITORY_INFO 0x20 + +// +// Constants and Structure definitions for "Get SDR Repository Info" command to follow here +// +typedef union { + struct { + UINT8 SdrRepAllocInfoCmd : 1; + UINT8 SdrRepReserveCmd : 1; + UINT8 PartialAddSdrCmd : 1; + UINT8 DeleteSdrRepCmd : 1; + UINT8 Reserved : 1; + UINT8 SdrRepUpdateOp : 2; + UINT8 Overflow : 1; + } Bits; + UINT8 Uint8; +} IPMI_SDR_OPERATION_SUPPORT; + +typedef struct { + UINT8 CompletionCode; + UINT8 Version; + UINT16 RecordCount; + UINT16 FreeSpace; + UINT32 RecentAdditionTimeStamp; + UINT32 RecentEraseTimeStamp; + IPMI_SDR_OPERATION_SUPPORT OperationSupport; +} IPMI_GET_SDR_REPOSITORY_INFO_RESPONSE; + +// +// Definitions for Get SDR Repository Allocateion Info command +// +#define IPMI_STORAGE_GET_SDR_REPOSITORY_ALLOCATION_INFO 0x21 + +// +// Constants and Structure definitions for "Get SDR Repository Allocateion Info" command to follow here +// + +// +// Definitions for Reserve SDR Repository command +// +#define IPMI_STORAGE_RESERVE_SDR_REPOSITORY 0x22 + +// +// Constants and Structure definitions for "Reserve SDR Repository" command to follow here +// +typedef struct { + UINT8 CompletionCode; + UINT8 ReservationId[2]; // Reservation ID. LS byte first. +} IPMI_RESERVE_SDR_REPOSITORY_RESPONSE; + +// +// Definitions for Get SDR command +// +#define IPMI_STORAGE_GET_SDR 0x23 + +// +// Constants and Structure definitions for "Get SDR" command to follow here +// +typedef union { + struct { + UINT8 EventScanningEnabled : 1; + UINT8 EventScanningDisabled : 1; + UINT8 InitSensorType : 1; + UINT8 InitHysteresis : 1; + UINT8 InitThresholds : 1; + UINT8 InitEvent : 1; + UINT8 InitScanning : 1; + UINT8 SettableSensor : 1; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_SENSOR_INIT; + +typedef union { + struct { + UINT8 EventMessageControl : 2; + UINT8 ThresholdAccessSupport : 2; + UINT8 HysteresisSupport : 2; + UINT8 ReArmSupport : 1; + UINT8 IgnoreSensor : 1; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_SENSOR_CAP; + +typedef union { + struct { + UINT8 Linearization : 7; + UINT8 Reserved : 1; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_LINEARIZATION; + +typedef union { + struct { + UINT8 Toleremce : 6; + UINT8 MHi : 2; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_M_TOLERANCE; + +typedef union { + struct { + UINT8 AccuracyLow : 6; + UINT8 BHi : 2; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_B_ACCURACY; + +typedef union { + struct { + UINT8 Reserved : 2; + UINT8 AccuracyExp : 2; + UINT8 AccuracyHi : 4; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_ACCURACY_SENSOR_DIR; + +typedef union { + struct { + UINT8 BExp : 4; + UINT8 RExp : 4; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_R_EXP_B_EXP; + +typedef union { + struct { + UINT8 NominalReadingSpscified : 1; + UINT8 NominalMaxSpscified : 1; + UINT8 NominalMinSpscified : 1; + UINT8 Reserved : 5; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_ANALOG_FLAGS; + +typedef struct { + UINT16 RecordId; // 1 + UINT8 Version; // 3 + UINT8 RecordType; // 4 + UINT8 RecordLength; // 5 + UINT8 OwnerId; // 6 + UINT8 OwnerLun; // 7 + UINT8 SensorNumber; // 8 + UINT8 EntityId; // 9 + UINT8 EntityInstance; // 10 + IPMI_SDR_RECORD_SENSOR_INIT SensorInitialization; // 11 + IPMI_SDR_RECORD_SENSOR_CAP SensorCapabilities; // 12 + UINT8 SensorType; // 13 + UINT8 EventType; // 14 + UINT8 Reserved1[7]; // 15 + UINT8 UnitType; // 22 + UINT8 Reserved2; // 23 + IPMI_SDR_RECORD_LINEARIZATION Linearization; // 24 + UINT8 MLo; // 25 + IPMI_SDR_RECORD_M_TOLERANCE MHiTolerance; // 26 + UINT8 BLo; // 27 + IPMI_SDR_RECORD_B_ACCURACY BHiAccuracyLo; // 28 + IPMI_SDR_RECORD_ACCURACY_SENSOR_DIR AccuracySensorDirection; // 29 + IPMI_SDR_RECORD_R_EXP_B_EXP RExpBExp; // 30 + IPMI_SDR_RECORD_ANALOG_FLAGS AnalogFlags; // 31 + UINT8 NominalReading; // 32 + UINT8 Reserved3[4]; // 33 + UINT8 UpperNonRecoverThreshold; // 37 + UINT8 UpperCriticalThreshold; // 38 + UINT8 UpperNonCriticalThreshold; // 39 + UINT8 LowerNonRecoverThreshold; // 40 + UINT8 LowerCriticalThreshold; // 41 + UINT8 LowerNonCriticalThreshold; // 42 + UINT8 Reserved4[5]; // 43 + UINT8 IdStringLength; // 48 + UINT8 AsciiIdString[16]; // 49 - 64 +} IPMI_SDR_RECORD_STRUCT_1; + +typedef struct { + UINT16 RecordId; // 1 + UINT8 Version; // 3 + UINT8 RecordType; // 4 + UINT8 RecordLength; // 5 + UINT8 OwnerId; // 6 + UINT8 OwnerLun; // 7 + UINT8 SensorNumber; // 8 + UINT8 EntityId; // 9 + UINT8 EntityInstance; // 10 + IPMI_SDR_RECORD_SENSOR_INIT SensorInitialization; // 11 + IPMI_SDR_RECORD_SENSOR_CAP SensorCapabilities; // 12 + UINT8 SensorType; // 13 + UINT8 EventType; // 14 + UINT8 Reserved1[7]; // 15 + UINT8 UnitType; // 22 + UINT8 Reserved2[9]; // 23 + UINT8 IdStringLength; // 32 + UINT8 AsciiIdString[16]; // 33 - 48 +} IPMI_SDR_RECORD_STRUCT_2; + +typedef union { + struct { + UINT8 Reserved1 : 1; + UINT8 ControllerSlaveAddress : 7; + UINT8 FruDeviceId; + UINT8 BusId : 3; + UINT8 Lun : 2; + UINT8 Reserved2 : 2; + UINT8 LogicalFruDevice : 1; + UINT8 Reserved3 : 4; + UINT8 ChannelNumber : 4; + } Bits; + UINT32 Uint32; +} IPMI_FRU_DATA_INFO; + +typedef union { + struct { + UINT8 Length : 4; + UINT8 Reserved : 1; + UINT8 StringType : 3; + } Bits; + UINT8 Uint8; +} IPMI_SDR_RECORD_DEV_ID_STR_TYPE_LENGTH; + +typedef struct { + UINT16 RecordId; // 1 + UINT8 Version; // 3 + UINT8 RecordType; // 4 + UINT8 RecordLength; // 5 + IPMI_FRU_DATA_INFO FruDeviceData; // 6 + UINT8 Reserved; // 10 + UINT8 DeviceType; // 11 + UINT8 DeviceTypeModifier; // 12 + UINT8 FruEntityId; // 13 + UINT8 FruEntityInstance; // 14 + UINT8 OemReserved; // 15 + IPMI_SDR_RECORD_DEV_ID_STR_TYPE_LENGTH StringTypeLength; // 16 + UINT8 String[16]; // 17 +} IPMI_SDR_RECORD_STRUCT_11; + +typedef struct { + UINT16 RecordId; //1 + UINT8 Version; //3 + UINT8 RecordType; //4 + UINT8 RecordLength; //5 + UINT8 ManufacturerId[3]; //6 + UINT8 StringChars[20]; +} IPMI_SDR_RECORD_STRUCT_C0; + +typedef struct { + UINT16 RecordId; //1 + UINT8 Version; //3 + UINT8 RecordType; //4 + UINT8 RecordLength; //5 +} IPMI_SDR_RECORD_STRUCT_HEADER; + +typedef union { + IPMI_SDR_RECORD_STRUCT_1 SensorType1; + IPMI_SDR_RECORD_STRUCT_2 SensorType2; + IPMI_SDR_RECORD_STRUCT_11 SensorType11; + IPMI_SDR_RECORD_STRUCT_C0 SensorTypeC0; + IPMI_SDR_RECORD_STRUCT_HEADER SensorHeader; +} IPMI_SENSOR_RECORD_STRUCT; + +typedef struct { + UINT16 ReservationId; + UINT16 RecordId; + UINT8 RecordOffset; + UINT8 BytesToRead; +} IPMI_GET_SDR_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT16 NextRecordId; + IPMI_SENSOR_RECORD_STRUCT RecordData; +} IPMI_GET_SDR_RESPONSE; + +// +// Definitions for Add SDR command +// +#define IPMI_STORAGE_ADD_SDR 0x24 + +// +// Constants and Structure definitions for "Add SDR" command to follow here +// + +// +// Definitions for Partial Add SDR command +// +#define IPMI_STORAGE_PARTIAL_ADD_SDR 0x25 + +// +// Constants and Structure definitions for "Partial Add SDR" command to follow here +// + +// +// Definitions for Delete SDR command +// +#define IPMI_STORAGE_DELETE_SDR 0x26 + +// +// Constants and Structure definitions for "Delete SDR" command to follow here +// + +// +// Definitions for Clear SDR Repository command +// +#define IPMI_STORAGE_CLEAR_SDR 0x27 + +// +// Constants and Structure definitions for "Clear SDR Repository" command to follow here +// + +// +// Definitions for Get SDR Repository Time command +// +#define IPMI_STORAGE_GET_SDR_REPOSITORY_TIME 0x28 + +// +// Constants and Structure definitions for "Get SDR Repository Time" command to follow here +// + +// +// Definitions for Set SDR Repository Time command +// +#define IPMI_STORAGE_SET_SDR_REPOSITORY_TIME 0x29 + +// +// Constants and Structure definitions for "Set SDR Repository Time" command to follow here +// + +// +// Definitions for Enter SDR Repository Update Mode command +// +#define IPMI_STORAGE_ENTER_SDR_UPDATE_MODE 0x2A + +// +// Constants and Structure definitions for "Enter SDR Repository Update Mode" command to follow here +// + +// +// Definitions for Exit SDR Repository Update Mode command +// +#define IPMI_STORAGE_EXIT_SDR_UPDATE_MODE 0x2B + +// +// Constants and Structure definitions for "Exit SDR Repository Update Mode" command to follow here +// + +// +// Definitions for Run Initialize Agent command +// +#define IPMI_STORAGE_RUN_INIT_AGENT 0x2C + +// +// Constants and Structure definitions for "Run Initialize Agent" command to follow here +// + +// +// Below is Definitions for System Event Log(SEL) Commands (Chapter 31) +// + +// +// Definitions for Get SEL Info command +// +#define IPMI_STORAGE_GET_SEL_INFO 0x40 + +// +// Constants and Structure definitions for "Get SEL Info" command to follow here +// +#define IPMI_GET_SEL_INFO_OPERATION_SUPPORT_GET_SEL_ALLOCATION_INFO_CMD BIT0 +#define IPMI_GET_SEL_INFO_OPERATION_SUPPORT_RESERVE_SEL_CMD BIT1 +#define IPMI_GET_SEL_INFO_OPERATION_SUPPORT_PARTIAL_ADD_SEL_ENTRY_CMD BIT2 +#define IPMI_GET_SEL_INFO_OPERATION_SUPPORT_DELETE_SEL_CMD BIT3 +#define IPMI_GET_SEL_INFO_OPERATION_SUPPORT_OVERFLOW_FLAG BIT7 + +typedef struct { + UINT8 CompletionCode; + UINT8 Version; // Version of SEL + UINT16 NoOfEntries; // No of Entries in the SEL + UINT16 FreeSpace; // Free space in Bytes + UINT32 RecentAddTimeStamp; // Most Recent Addition of Time Stamp + UINT32 RecentEraseTimeStamp; // Most Recent Erasure of Time Stamp + UINT8 OperationSupport; // Operation Support +} IPMI_GET_SEL_INFO_RESPONSE; + +// +// Definitions for Get SEL Allocation Info command +// +#define IPMI_STORAGE_GET_SEL_ALLOCATION_INFO 0x41 + +// +// Constants and Structure definitions for "Get SEL Allocation Info" command to follow here +// + +// +// Definitions for Reserve SEL command +// +#define IPMI_STORAGE_RESERVE_SEL 0x42 + +// +// Constants and Structure definitions for "Reserve SEL" command to follow here +// +typedef struct { + UINT8 CompletionCode; + UINT8 ReservationId[2]; // Reservation ID. LS byte first. +} IPMI_RESERVE_SEL_RESPONSE; + +// +// Definitions for Get SEL Entry command +// +#define IPMI_STORAGE_GET_SEL_ENTRY 0x43 + +// +// Constants and Structure definitions for "Get SEL Entry" command to follow here +// + +// +// Below is Definitions for SEL Record Formats (Chapter 32) +// +typedef struct { + UINT16 RecordId; + UINT8 RecordType; + UINT32 TimeStamp; + UINT16 GeneratorId; + UINT8 EvMRevision; + UINT8 SensorType; + UINT8 SensorNumber; + UINT8 EventDirType; + UINT8 OEMEvData1; + UINT8 OEMEvData2; + UINT8 OEMEvData3; +} IPMI_SEL_EVENT_RECORD_DATA; + +typedef struct { + UINT16 RecordId; + UINT8 RecordType; // C0h-DFh = OEM system event record + UINT32 TimeStamp; + UINT8 ManufacturerId[3]; + UINT8 OEMDefined[6]; +} IPMI_TIMESTAMPED_OEM_SEL_RECORD_DATA; + +typedef struct { + UINT16 RecordId; + UINT8 RecordType; // E0h-FFh = OEM system event record + UINT8 OEMDefined[13]; +} IPMI_NON_TIMESTAMPED_OEM_SEL_RECORD_DATA; + +typedef struct { + UINT8 ReserveId[2]; // Reservation ID, LS Byte First + UINT8 SelRecID[2]; // Sel Record ID, LS Byte First + UINT8 Offset; // Offset Into Record + UINT8 BytesToRead; // Bytes to be Read, 0xFF for entire record +} IPMI_GET_SEL_ENTRY_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT16 NextSelRecordId; // Next SEL Record ID, LS Byte first + IPMI_SEL_EVENT_RECORD_DATA RecordData; +} IPMI_GET_SEL_ENTRY_RESPONSE; + +// +// Definitions for Add SEL Entry command +// +#define IPMI_STORAGE_ADD_SEL_ENTRY 0x44 + +// +// Constants and Structure definitions for "Add SEL Entry" command to follow here +// +typedef struct { + IPMI_SEL_EVENT_RECORD_DATA RecordData; +} IPMI_ADD_SEL_ENTRY_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT16 RecordId; // Record ID for added record, LS Byte first +} IPMI_ADD_SEL_ENTRY_RESPONSE; + +// +// Definitions for Partial Add SEL Entry command +// +#define IPMI_STORAGE_PARTIAL_ADD_SEL_ENTRY 0x45 + +// +// Constants and Structure definitions for "Partial Add SEL Entry" command to follow here +// +typedef struct { + UINT16 ReservationId; + UINT16 RecordId; + UINT8 OffsetIntoRecord; + UINT8 InProgress; + UINT8 RecordData[0]; +} IPMI_PARTIAL_ADD_SEL_ENTRY_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT16 RecordId; +} IPMI_PARTIAL_ADD_SEL_ENTRY_RESPONSE; + +// +// Definitions for Delete SEL Entry command +// +#define IPMI_STORAGE_DELETE_SEL_ENTRY 0x46 + +// +// Constants and Structure definitions for "Delete SEL Entry" command to follow here +// +typedef struct { + UINT8 ReserveId[2]; // Reservation ID, LS byte first + UINT8 RecordToDelete[2]; // Record to Delete, LS Byte First +} IPMI_DELETE_SEL_ENTRY_REQUEST; + +#define IPMI_DELETE_SEL_ENTRY_RESPONSE_TYPE_UNSUPPORTED 0x80 +#define IPMI_DELETE_SEL_ENTRY_RESPONSE_ERASE_IN_PROGRESS 0x81 + +typedef struct { + UINT8 CompletionCode; + UINT16 RecordId; // Record ID added. LS byte first +} IPMI_DELETE_SEL_ENTRY_RESPONSE; + +// +// Definitions for Clear SEL command +// +#define IPMI_STORAGE_CLEAR_SEL 0x47 + +// +// Constants and Structure definitions for "Clear SEL" command to follow here +// +#define IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII 0x43 +#define IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII 0x4C +#define IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII 0x52 +#define IPMI_CLEAR_SEL_REQUEST_INITIALIZE_ERASE 0xAA +#define IPMI_CLEAR_SEL_REQUEST_GET_ERASE_STATUS 0x00 + +typedef struct { + UINT8 Reserve[2]; // Reserve ID, LSB first + UINT8 AscC; // Ascii for 'C' (0x43) + UINT8 AscL; // Ascii for 'L' (0x4c) + UINT8 AscR; // Ascii for 'R' (0x52) + UINT8 Erase; // 0xAA, Initiate Erase, 0x00 Get Erase Status +} IPMI_CLEAR_SEL_REQUEST; + +#define IPMI_CLEAR_SEL_RESPONSE_ERASURE_IN_PROGRESS 0x00 +#define IPMI_CLEAR_SEL_RESPONSE_ERASURE_COMPLETED 0x01 + +typedef struct { + UINT8 CompletionCode; + UINT8 ErasureProgress; +} IPMI_CLEAR_SEL_RESPONSE; + +// +// Definitions for Get SEL Time command +// +#define IPMI_STORAGE_GET_SEL_TIME 0x48 + +// +// Constants and Structure definitions for "Get SEL Time" command to follow here +// +typedef struct { + UINT8 CompletionCode; + UINT32 Timestamp; // Present Timestamp clock reading. LS byte first. +} IPMI_GET_SEL_TIME_RESPONSE; + +// +// Definitions for Set SEL Time command +// +#define IPMI_STORAGE_SET_SEL_TIME 0x49 + +// +// Constants and Structure definitions for "Set SEL Time" command to follow here +// +typedef struct { + UINT32 Timestamp; +} IPMI_SET_SEL_TIME_REQUEST; + +// +// Definitions for Get Auxillary Log Status command +// +#define IPMI_STORAGE_GET_AUXILLARY_LOG_STATUS 0x5A + +// +// Constants and Structure definitions for "Get Auxillary Log Status" command to follow here +// + +// +// Definitions for Set Auxillary Log Status command +// +#define IPMI_STORAGE_SET_AUXILLARY_LOG_STATUS 0x5B + +// +// Constants and Structure definitions for "Set Auxillary Log Status" command to follow here +// + +// +// Definitions for Get SEL Time UTC Offset command +// +#define IPMI_STORAGE_GET_SEL_TIME_UTC_OFFSET 0x5C + +// +// Constants and Structure definitions for "Get SEL Time UTC Offset" command to follow here +// +typedef struct { + UINT8 CompletionCode; + // + // 16-bit, 2s-complement signed integer for the offset in minutes from UTC to SEL Time. + // LS-byte first. (ranges from -1440 to 1440) + // + INT16 UtcOffset; +} IPMI_GET_SEL_TIME_UTC_OFFSET_RESPONSE; + +// +// Definitions for Set SEL Time UTC Offset command +// +#define IPMI_STORAGE_SET_SEL_TIME_UTC_OFFSET 0x5D + +// +// Constants and Structure definitions for "Set SEL Time UTC Offset" command to follow here +// + +#define IPMI_COMPLETE_SEL_RECORD 0xFF + +#define IPMI_SEL_SYSTEM_RECORD 0x02 +#define IPMI_SEL_OEM_TIME_STAMP_RECORD_START 0xC0 +#define IPMI_SEL_OEM_TIME_STAMP_RECORD_END 0xDF +#define IPMI_SEL_OEM_NO_TIME_STAMP_RECORD_START 0xE0 +#define IPMI_SEL_OEM_NO_TIME_STAMP_RECORD_END 0xFF + +#define IPMI_SEL_EVENT_DIR(EventDirType) (EventDirType >> 7) +#define IPMI_SEL_EVENT_DIR_ASSERTION_EVENT 0x00 +#define IPMI_SEL_EVENT_DIR_DEASSERTION_EVENT 0x01 + +#define IPMI_SEL_EVENT_TYPE(EventDirType) (EventDirType & 0x7F) +// +// Event/Reading Type Code Ranges (Chapter 42) +// +#define IPMI_SEL_EVENT_TYPE_UNSPECIFIED 0x00 +#define IPMI_SEL_EVENT_TYPE_THRESHOLD 0x01 +#define IPMI_SEL_EVENT_TYPE_GENERIC_START 0x02 +#define IPMI_SEL_EVENT_TYPE_GENERIC_END 0x0C +#define IPMI_SEL_EVENT_TYPE_SENSOR_SPECIFIC 0x6F +#define IPMI_SEL_EVENT_TYPE_OEM_START 0x70 +#define IPMI_SEL_EVENT_TYPE_OEM_END 0x7F + +#define SOFTWARE_ID_FROM_GENERATOR_ID(GeneratorId) ((GeneratorId & 0xFF) >> 1) +// +// System Software IDs definitions (Section 5.5) +// +#define IPMI_SWID_BIOS_RANGE_START 0x00 +#define IPMI_SWID_BIOS_RANGE_END 0x0F +#define IPMI_SWID_SMI_HANDLER_RANGE_START 0x10 +#define IPMI_SWID_SMI_HANDLER_RANGE_END 0x1F +#define IPMI_SWID_SMS_RANGE_START 0x20 +#define IPMI_SWID_SMS_RANGE_END 0x2F +#define IPMI_SWID_OEM_RANGE_START 0x30 +#define IPMI_SWID_OEM_RANGE_END 0x3F +#define IPMI_SWID_REMOTE_CONSOLE_RANGE_START 0x40 +#define IPMI_SWID_REMOTE_CONSOLE_RANGE_END 0x46 +#define IPMI_SWID_TERMINAL_REMOTE_CONSOLE_ID 0x47 + +#define SLAVE_ADDRESS_FROM_GENERATOR_ID(GeneratorId) ((GeneratorId & 0xFF) >> 1) +#define LUN_FROM_GENERATOR_ID(GeneratorId) ((GeneratorId >> 8) & 0x03) +#define CHANNEL_NUMBER_FROM_GENERATOR_ID(GeneratorId) ((GeneratorId >> 12) & 0x0F) + +#define IPMI_EVM_REVISION 0x04 +#define IPMI_BIOS_ID 0x18 +#define IPMI_FORMAT_REV 0x00 +#define IPMI_FORMAT_REV1 0x01 +#define IPMI_SOFTWARE_ID 0x01 +#define IPMI_PLATFORM_VAL_ID 0x01 +#define IPMI_GENERATOR_ID(i,f) ((i << 1) | (f << 1) | IPMI_SOFTWARE_ID) + +#define IPMI_SENSOR_TYPE_EVENT_CODE_DISCRETE 0x6F + +#define IPMI_OEM_SPECIFIC_DATA 0x02 +#define IPMI_SENSOR_SPECIFIC_DATA 0x03 + +#pragma pack() +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnTransport.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnTransport.h new file mode 100644 index 0000000..44ee36d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/IpmiNetFnTransport.h @@ -0,0 +1,891 @@ +/** @file + IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1. + + This file contains all NetFn Transport commands, including: + IPM LAN Commands (Chapter 23) + IPMI Serial/Modem Commands (Chapter 25) + SOL Commands (Chapter 26) + Command Forwarding Commands (Chapter 35b) + + See IPMI specification, Appendix G, Command Assignments + and Appendix H, Sub-function Assignments. + + Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _IPMI_NET_FN_TRANSPORT_H_ +#define _IPMI_NET_FN_TRANSPORT_H_ + +#pragma pack(1) +// +// Net function definition for Transport command +// +#define IPMI_NETFN_TRANSPORT 0x0C + +// +// Below is Definitions for IPM LAN Commands (Chapter 23) +// + +// +// Definitions for Set Lan Configuration Parameters command +// +#define IPMI_TRANSPORT_SET_LAN_CONFIG_PARAMETERS 0x01 + +// +// Constants and Structure definitions for "Set Lan Configuration Parameters" command to follow here +// + +// +// LAN Management Structure +// +typedef enum { + IpmiLanReserved1, + IpmiLanReserved2, + IpmiLanAuthType, + IpmiLanIpAddress, + IpmiLanIpAddressSource, + IpmiLanMacAddress, + IpmiLanSubnetMask, + IpmiLanIpv4HeaderParam, + IpmiLanPrimaryRcmpPort, + IpmiLanSecondaryRcmpPort, + IpmiLanBmcGeneratedArpCtrl, + IpmiLanArpInterval, + IpmiLanDefaultGateway, + IpmiLanDefaultGatewayMac, + IpmiLanBackupGateway, + IpmiLanBackupGatewayMac, + IpmiLanCommunityString, + IpmiLanReserved3, + IpmiLanDestinationType, + IpmiLanDestinationAddress, + IpmiIpv4OrIpv6Support = 0x32, + IpmiIpv4OrIpv6AddressEnable, + IpmiIpv6HdrStatTrafficClass, + IpmiIpv6HdrStatHopLimit, + IpmiIpv6HdrFlowLabel, + IpmiIpv6Status, + IpmiIpv6StaticAddress, + IpmiIpv6DhcpStaticDuidLen, + IpmiIpv6DhcpStaticDuid, + IpmiIpv6DhcpAddress, + IpmiIpv6DhcpDynamicDuidLen, + IpmiIpv6DhcpDynamicDuid, + IpmiIpv6RouterConfig = 0x40, + IpmiIpv6StaticRouter1IpAddr, + IpmiIpv6DynamicRouterIpAddr = 0x4a +} IPMI_LAN_OPTION_TYPE; + +// +// IP Address Source +// +typedef enum { + IpmiUnspecified, + IpmiStaticAddrsss, + IpmiDynamicAddressBmcDhcp, + IpmiDynamicAddressBiosDhcp, + IpmiDynamicAddressBmcNonDhcp +} IPMI_IP_ADDRESS_SRC; + +// +// Destination Type +// +typedef enum { + IpmiPetTrapDestination, + IpmiDirectedEventDestination, + IpmiReserved1, + IpmiReserved2, + IpmiReserved3, + IpmiReserved4, + IpmiReserved5, + IpmiOem1, + IpmiOem2 +} IPMI_LAN_DEST_TYPE_DEST_TYPE; + +typedef union { + struct { + UINT8 NoAuth : 1; + UINT8 MD2Auth : 1; + UINT8 MD5Auth : 1; + UINT8 Reserved1 : 1; + UINT8 StraightPswd : 1; + UINT8 OemType : 1; + UINT8 Reserved2 : 2; + } Bits; + UINT8 Uint8; +} IPMI_LAN_AUTH_TYPE; + +typedef struct { + UINT8 IpAddress[4]; +} IPMI_LAN_IP_ADDRESS; + +typedef union { + struct { + UINT8 AddressSrc : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_LAN_IP_ADDRESS_SRC; + +typedef struct { + UINT8 MacAddress[6]; +} IPMI_LAN_MAC_ADDRESS; + +typedef struct { + UINT8 IpAddress[4]; +} IPMI_LAN_SUBNET_MASK; + +typedef union { + struct { + UINT8 IpFlag : 3; + UINT8 Reserved : 5; + } Bits; + UINT8 Uint8; +} IPMI_LAN_IPV4_HDR_PARAM_DATA_2; + +typedef union { + struct { + UINT8 Precedence : 3; + UINT8 Reserved : 1; + UINT8 ServiceType : 4; + } Bits; + UINT8 Uint8; +} IPMI_LAN_IPV4_HDR_PARAM_DATA_3; + +typedef struct { + UINT8 TimeToLive; + IPMI_LAN_IPV4_HDR_PARAM_DATA_2 Data2; + IPMI_LAN_IPV4_HDR_PARAM_DATA_3 Data3; +} IPMI_LAN_IPV4_HDR_PARAM; + +typedef struct { + UINT8 RcmpPortMsb; + UINT8 RcmpPortLsb; +} IPMI_LAN_RCMP_PORT; + +typedef union { + struct { + UINT8 EnableBmcArpResponse : 1; + UINT8 EnableBmcGratuitousArp : 1; + UINT8 Reserved : 6; + } Bits; + UINT8 Uint8; +} IPMI_LAN_BMC_GENERATED_ARP_CONTROL; + +typedef struct { + UINT8 ArpInterval; +} IPMI_LAN_ARP_INTERVAL; + +typedef struct { + UINT8 Data[18]; +} IPMI_LAN_COMMUNITY_STRING; + +typedef union { + struct { + UINT8 DestinationSelector : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_LAN_SET_SELECTOR; + +typedef union { + struct { + UINT8 DestinationType : 3; + UINT8 Reserved : 4; + UINT8 AlertAcknowledged : 1; + } Bits; + UINT8 Uint8; +} IPMI_LAN_DEST_TYPE_DESTINATION_TYPE; + +typedef struct { + IPMI_LAN_SET_SELECTOR SetSelector; + IPMI_LAN_DEST_TYPE_DESTINATION_TYPE DestinationType; +} IPMI_LAN_DEST_TYPE; + +typedef union { + struct { + UINT8 AlertingIpAddressSelector : 4; + UINT8 AddressFormat : 4; + } Bits; + UINT8 Uint8; +} IPMI_LAN_ADDRESS_FORMAT; + +typedef union { + struct { + UINT8 UseDefaultGateway : 1; + UINT8 Reserved2 : 7; + } Bits; + UINT8 Uint8; +} IPMI_LAN_GATEWAY_SELECTOR; + +typedef struct { + IPMI_LAN_SET_SELECTOR SetSelector; + IPMI_LAN_ADDRESS_FORMAT AddressFormat; + IPMI_LAN_GATEWAY_SELECTOR GatewaySelector; + IPMI_LAN_IP_ADDRESS AlertingIpAddress; + IPMI_LAN_MAC_ADDRESS AlertingMacAddress; +} IPMI_LAN_DEST_ADDRESS; + +typedef union { + IPMI_LAN_AUTH_TYPE IpmiLanAuthType; + IPMI_LAN_IP_ADDRESS IpmiLanIpAddress; + IPMI_LAN_IP_ADDRESS_SRC IpmiLanIpAddressSrc; + IPMI_LAN_MAC_ADDRESS IpmiLanMacAddress; + IPMI_LAN_SUBNET_MASK IpmiLanSubnetMask; + IPMI_LAN_IPV4_HDR_PARAM IpmiLanIpv4HdrParam; + IPMI_LAN_RCMP_PORT IpmiLanPrimaryRcmpPort; + IPMI_LAN_BMC_GENERATED_ARP_CONTROL IpmiLanArpControl; + IPMI_LAN_ARP_INTERVAL IpmiLanArpInterval; + IPMI_LAN_COMMUNITY_STRING IpmiLanCommunityString; + IPMI_LAN_DEST_TYPE IpmiLanDestType; + IPMI_LAN_DEST_ADDRESS IpmiLanDestAddress; +} IPMI_LAN_OPTIONS; + +typedef union { + struct { + UINT8 AddressSourceType : 4; + UINT8 Reserved : 3; + UINT8 EnableStatus : 1; + } Bits; + UINT8 Uint8; +} IPMI_LAN_IPV6_ADDRESS_SOURCE_TYPE; + +typedef struct { + UINT8 SetSelector; + IPMI_LAN_IPV6_ADDRESS_SOURCE_TYPE AddressSourceType; + UINT8 Ipv6Address[16]; + UINT8 AddressPrefixLen; + UINT8 AddressStatus; +} IPMI_LAN_IPV6_STATIC_ADDRESS; + +// +// Set in progress parameter +// +typedef union { + struct { + UINT8 SetInProgress:2; + UINT8 Reserved:6; + } Bits; + UINT8 Uint8; +} IPMI_LAN_SET_IN_PROGRESS; + +typedef union { + struct { + UINT8 ChannelNo : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_SET_LAN_CONFIG_CHANNEL_NUM; + +typedef struct { + IPMI_SET_LAN_CONFIG_CHANNEL_NUM ChannelNumber; + UINT8 ParameterSelector; + UINT8 ParameterData[0]; +} IPMI_SET_LAN_CONFIGURATION_PARAMETERS_COMMAND_REQUEST; + +// +// Definitions for Get Lan Configuration Parameters command +// +#define IPMI_TRANSPORT_GET_LAN_CONFIG_PARAMETERS 0x02 + +// +// Constants and Structure definitions for "Get Lan Configuration Parameters" command to follow here +// +typedef union { + struct { + UINT8 ChannelNo : 4; + UINT8 Reserved : 3; + UINT8 GetParameter : 1; + } Bits; + UINT8 Uint8; +} IPMI_GET_LAN_CONFIG_CHANNEL_NUM; + +typedef struct { + IPMI_GET_LAN_CONFIG_CHANNEL_NUM ChannelNumber; + UINT8 ParameterSelector; + UINT8 SetSelector; + UINT8 BlockSelector; +} IPMI_GET_LAN_CONFIGURATION_PARAMETERS_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 ParameterRevision; + UINT8 ParameterData[0]; +} IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE; + +// +// Definitions for Suspend BMC ARPs command +// +#define IPMI_TRANSPORT_SUSPEND_BMC_ARPS 0x03 + +// +// Constants and Structure definitions for "Suspend BMC ARPs" command to follow here +// + +// +// Definitions for Get IP-UDP-RMCP Statistics command +// +#define IPMI_TRANSPORT_GET_PACKET_STATISTICS 0x04 + +// +// Constants and Structure definitions for "Get IP-UDP-RMCP Statistics" command to follow here +// + +// +// Below is Definitions for IPMI Serial/Modem Commands (Chapter 25) +// + +// +// Definitions for Set Serial/Modem Configuration command +// +#define IPMI_TRANSPORT_SET_SERIAL_CONFIGURATION 0x10 + +// +// Constants and Structure definitions for "Set Serial/Modem Configuration" command to follow here +// + +// +// EMP OPTION DATA +// +typedef union { + struct { + UINT8 NoAuthentication : 1; + UINT8 MD2Authentication : 1; + UINT8 MD5Authentication : 1; + UINT8 Reserved1 : 1; + UINT8 StraightPassword : 1; + UINT8 OemProprietary : 1; + UINT8 Reservd2 : 2; + } Bits; + UINT8 Uint8; +} IPMI_EMP_AUTH_TYPE; + +typedef union { + struct { + UINT8 EnableBasicMode : 1; + UINT8 EnablePPPMode : 1; + UINT8 EnableTerminalMode : 1; + UINT8 Reserved1 : 2; + UINT8 SnoopOsPPPNegotiation : 1; + UINT8 Reserved2 : 1; + UINT8 DirectConnect : 1; + } Bits; + UINT8 Uint8; +} IPMI_EMP_CONNECTION_TYPE; + +typedef union { + struct { + UINT8 InactivityTimeout : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_EMP_INACTIVITY_TIMEOUT; + +typedef union { + struct { + UINT8 IpmiCallback : 1; + UINT8 CBCPCallback : 1; + UINT8 Reserved : 6; + } Bits; + UINT8 Uint8; +} IPMI_CHANNEL_CALLBACK_CONTROL_ENABLE; + +typedef union { + struct { + UINT8 CbcpEnableNoCallback : 1; + UINT8 CbcpEnablePreSpecifiedNumber : 1; + UINT8 CbcpEnableUserSpecifiedNumber : 1; + UINT8 CbcpEnableCallbackFromList : 1; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_CHANNEL_CALLBACK_CONTROL_CBCP; + +typedef struct { + IPMI_CHANNEL_CALLBACK_CONTROL_ENABLE CallbackEnable; + IPMI_CHANNEL_CALLBACK_CONTROL_CBCP CBCPNegotiation; + UINT8 CallbackDestination1; + UINT8 CallbackDestination2; + UINT8 CallbackDestination3; +} IPMI_EMP_CHANNEL_CALLBACK_CONTROL; + +typedef union { + struct { + UINT8 CloseSessionOnDCDLoss : 1; + UINT8 EnableSessionInactivityTimeout : 1; + UINT8 Reserved : 6; + } Bits; + UINT8 Uint8; +} IPMI_EMP_SESSION_TERMINATION; + +typedef union { + struct { + UINT8 Reserved1 : 5; + UINT8 EnableDtrHangup : 1; + UINT8 FlowControl : 2; + UINT8 BitRate : 4; + UINT8 Reserved2 : 4; + UINT8 SaveSetting : 1; + UINT8 SetComPort : 1; + UINT8 Reserved3 : 6; + } Bits; + UINT8 Uint8; + UINT16 Uint16; +} IPMI_EMP_MESSAGING_COM_SETTING; + +typedef union { + struct { + UINT8 RingDurationInterval : 6; + UINT8 Reserved1 : 2; + UINT8 RingDeadTime : 4; + UINT8 Reserved2 : 4; + } Bits; + UINT8 Uint8; +} IPMI_EMP_MODEM_RING_TIME; + +typedef struct { + UINT8 Reserved; + UINT8 InitString[48]; +} IPMI_EMP_MODEM_INIT_STRING; + +typedef struct { + UINT8 EscapeSequence[5]; +} IPMI_EMP_MODEM_ESC_SEQUENCE; + +typedef struct { + UINT8 HangupSequence[8]; +} IPMI_EMP_MODEM_HANGUP_SEQUENCE; + +typedef struct { + UINT8 ModelDialCommend[8]; +} IPMI_MODEM_DIALUP_COMMAND; + +typedef struct { + UINT8 PageBlackoutInterval; +} IPMI_PAGE_BLACKOUT_INTERVAL; + +typedef struct { + UINT8 CommunityString[18]; +} IPMI_EMP_COMMUNITY_STRING; + +typedef union { + struct { + UINT8 Reserved : 4; + UINT8 DialStringSelector : 4; + } Bits; + UINT8 Uint8; +} IPMI_DIAL_PAGE_DESTINATION; + +typedef union { + struct { + UINT8 TapAccountSelector : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_TAP_PAGE_DESTINATION; + +typedef struct { + UINT8 PPPAccountSetSelector; + UINT8 DialStringSelector; +} IPMI_PPP_ALERT_DESTINATION; + +typedef union { + IPMI_DIAL_PAGE_DESTINATION DialPageDestination; + IPMI_TAP_PAGE_DESTINATION TapPageDestination; + IPMI_PPP_ALERT_DESTINATION PppAlertDestination; +} IPMI_DEST_TYPE_SPECIFIC; + +typedef union { + struct { + UINT8 DestinationSelector : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_EMP_DESTINATION_SELECTOR; + +typedef union { + struct { + UINT8 DestinationType : 4; + UINT8 Reserved : 3; + UINT8 AlertAckRequired : 1; + } Bits; + UINT8 Uint8; +} IPMI_EMP_DESTINATION_TYPE; + +typedef union { + struct { + UINT8 NumRetriesCall : 3; + UINT8 Reserved1 : 1; + UINT8 NumRetryAlert : 3; + UINT8 Reserved2 : 1; + } Bits; + UINT8 Uint8; +} IPMI_EMP_RETRIES; + +typedef struct { + IPMI_EMP_DESTINATION_SELECTOR DestinationSelector; + IPMI_EMP_DESTINATION_TYPE DestinationType; + UINT8 AlertAckTimeoutSeconds; + IPMI_EMP_RETRIES Retries; + IPMI_DEST_TYPE_SPECIFIC DestinationTypeSpecific; +} IPMI_EMP_DESTINATION_INFO; + +typedef union { + struct { + UINT8 Parity : 3; + UINT8 CharacterSize : 1; + UINT8 StopBit : 1; + UINT8 DtrHangup : 1; + UINT8 FlowControl : 2; + } Bits; + UINT8 Uint8; +} IPMI_EMP_DESTINATION_COM_SETTING_DATA_2; + +typedef union { + struct { + UINT8 BitRate : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_EMP_BIT_RATE; + +typedef struct { + IPMI_EMP_DESTINATION_SELECTOR DestinationSelector; + IPMI_EMP_DESTINATION_COM_SETTING_DATA_2 Data2; + IPMI_EMP_BIT_RATE BitRate; +} IPMI_EMP_DESTINATION_COM_SETTING; + +typedef union { + struct { + UINT8 DialStringSelector : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_DIAL_STRING_SELECTOR; + +typedef struct { + IPMI_DIAL_STRING_SELECTOR DestinationSelector; + UINT8 Reserved; + UINT8 DialString[48]; +} IPMI_DESTINATION_DIAL_STRING; + +typedef union { + UINT32 IpAddressLong; + UINT8 IpAddress[4]; +} IPMI_PPP_IP_ADDRESS; + +typedef union { + struct { + UINT8 IpAddressSelector : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_DESTINATION_IP_ADDRESS_SELECTOR; + +typedef struct { + IPMI_DESTINATION_IP_ADDRESS_SELECTOR DestinationSelector; + IPMI_PPP_IP_ADDRESS PppIpAddress; +} IPMI_DESTINATION_IP_ADDRESS; + +typedef union { + struct { + UINT8 TapServiceSelector : 4; + UINT8 TapDialStringSelector : 4; + } Bits; + UINT8 Uint8; +} IPMI_TAP_DIAL_STRING_SERVICE_SELECTOR; + + +typedef struct { + UINT8 TapSelector; + IPMI_TAP_DIAL_STRING_SERVICE_SELECTOR TapDialStringServiceSelector; +} IPMI_DESTINATION_TAP_ACCOUNT; + +typedef struct { + UINT8 TapSelector; + UINT8 PagerIdString[16]; +} IPMI_TAP_PAGER_ID_STRING; + +typedef union { + UINT8 OptionData; + IPMI_EMP_AUTH_TYPE EmpAuthType; + IPMI_EMP_CONNECTION_TYPE EmpConnectionType; + IPMI_EMP_INACTIVITY_TIMEOUT EmpInactivityTimeout; + IPMI_EMP_CHANNEL_CALLBACK_CONTROL EmpCallbackControl; + IPMI_EMP_SESSION_TERMINATION EmpSessionTermination; + IPMI_EMP_MESSAGING_COM_SETTING EmpMessagingComSetting; + IPMI_EMP_MODEM_RING_TIME EmpModemRingTime; + IPMI_EMP_MODEM_INIT_STRING EmpModemInitString; + IPMI_EMP_MODEM_ESC_SEQUENCE EmpModemEscSequence; + IPMI_EMP_MODEM_HANGUP_SEQUENCE EmpModemHangupSequence; + IPMI_MODEM_DIALUP_COMMAND EmpModemDialupCommand; + IPMI_PAGE_BLACKOUT_INTERVAL EmpPageBlackoutInterval; + IPMI_EMP_COMMUNITY_STRING EmpCommunityString; + IPMI_EMP_DESTINATION_INFO EmpDestinationInfo; + IPMI_EMP_DESTINATION_COM_SETTING EmpDestinationComSetting; + UINT8 CallRetryBusySignalInterval; + IPMI_DESTINATION_DIAL_STRING DestinationDialString; + IPMI_DESTINATION_IP_ADDRESS DestinationIpAddress; + IPMI_DESTINATION_TAP_ACCOUNT DestinationTapAccount; + IPMI_TAP_PAGER_ID_STRING TapPagerIdString; +} IPMI_EMP_OPTIONS; + +// +// Definitions for Get Serial/Modem Configuration command +// +#define IPMI_TRANSPORT_GET_SERIAL_CONFIGURATION 0x11 + +// +// Constants and Structure definitions for "Get Serial/Modem Configuration" command to follow here +// + +// +// Definitions for Set Serial/Modem Mux command +// +#define IPMI_TRANSPORT_SET_SERIAL_MUX 0x12 + +// +// Constants and Structure definitions for "Set Serial/Modem Mux" command to follow here +// + +// +// Set Serial/Modem Mux command request return status +// +#define IPMI_MUX_SETTING_REQUEST_REJECTED 0x00 +#define IPMI_MUX_SETTING_REQUEST_ACCEPTED 0x01 + +// +// Definitions for serial multiplex settings +// +#define IPMI_MUX_SETTING_GET_MUX_SETTING 0x0 +#define IPMI_MUX_SETTING_REQUEST_MUX_TO_SYSTEM 0x1 +#define IPMI_MUX_SETTING_REQUEST_MUX_TO_BMC 0x2 +#define IPMI_MUX_SETTING_FORCE_MUX_TO_SYSTEM 0x3 +#define IPMI_MUX_SETTING_FORCE_MUX_TO_BMC 0x4 +#define IPMI_MUX_SETTING_BLOCK_REQUEST_MUX_TO_SYSTEM 0x5 +#define IPMI_MUX_SETTING_ALLOW_REQUEST_MUX_TO_SYSTEM 0x6 +#define IPMI_MUX_SETTING_BLOCK_REQUEST_MUX_TO_BMC 0x7 +#define IPMI_MUX_SETTING_ALLOW_REQUEST_MUX_TO_BMC 0x8 + +typedef union { + struct { + UINT8 ChannelNo : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_MUX_CHANNEL_NUM; + +typedef union { + struct { + UINT8 MuxSetting : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_MUX_SETTING_REQUEST; + +typedef struct { + IPMI_MUX_CHANNEL_NUM ChannelNumber; + IPMI_MUX_SETTING_REQUEST MuxSetting; +} IPMI_SET_SERIAL_MODEM_MUX_COMMAND_REQUEST; + +typedef union { + struct { + UINT8 MuxSetToBmc : 1; + UINT8 CommandStatus : 1; + UINT8 MessagingSessionActive : 1; + UINT8 AlertInProgress : 1; + UINT8 Reserved : 2; + UINT8 MuxToBmcAllowed : 1; + UINT8 MuxToSystemBlocked : 1; + } Bits; + UINT8 Uint8; +} IPMI_MUX_SETTING_PRESENT_STATE; + +typedef struct { + UINT8 CompletionCode; + IPMI_MUX_SETTING_PRESENT_STATE MuxSetting; +} IPMI_SET_SERIAL_MODEM_MUX_COMMAND_RESPONSE; + +// +// Definitions for Get TAP Response Code command +// +#define IPMI_TRANSPORT_GET_TAP_RESPONSE_CODE 0x13 + +// +// Constants and Structure definitions for "Get TAP Response Code" command to follow here +// + +// +// Definitions for Set PPP UDP Proxy Transmit Data command +// +#define IPMI_TRANSPORT_SET_PPP_UDP_PROXY_TXDATA 0x14 + +// +// Constants and Structure definitions for "Set PPP UDP Proxy Transmit Data" command to follow here +// + +// +// Definitions for Get PPP UDP Proxy Transmit Data command +// +#define IPMI_TRANSPORT_GET_PPP_UDP_PROXY_TXDATA 0x15 + +// +// Constants and Structure definitions for "Get PPP UDP Proxy Transmit Data" command to follow here +// + +// +// Definitions for Send PPP UDP Proxy Packet command +// +#define IPMI_TRANSPORT_SEND_PPP_UDP_PROXY_PACKET 0x16 + +// +// Constants and Structure definitions for "Send PPP UDP Proxy Packet" command to follow here +// + +// +// Definitions for Get PPP UDP Proxy Receive Data command +// +#define IPMI_TRANSPORT_GET_PPP_UDP_PROXY_RX 0x17 + +// +// Constants and Structure definitions for "Get PPP UDP Proxy Receive Data" command to follow here +// + +// +// Definitions for Serial/Modem connection active command +// +#define IPMI_TRANSPORT_SERIAL_CONNECTION_ACTIVE 0x18 + +// +// Constants and Structure definitions for "Serial/Modem connection active" command to follow here +// + +// +// Definitions for Callback command +// +#define IPMI_TRANSPORT_CALLBACK 0x19 + +// +// Constants and Structure definitions for "Callback" command to follow here +// + +// +// Definitions for Set user Callback Options command +// +#define IPMI_TRANSPORT_SET_USER_CALLBACK_OPTIONS 0x1A + +// +// Constants and Structure definitions for "Set user Callback Options" command to follow here +// + +// +// Definitions for Get user Callback Options command +// +#define IPMI_TRANSPORT_GET_USER_CALLBACK_OPTIONS 0x1B + +// +// Constants and Structure definitions for "Get user Callback Options" command to follow here +// + +// +// Below is Definitions for SOL Commands (Chapter 26) +// + +// +// Definitions for SOL activating command +// +#define IPMI_TRANSPORT_SOL_ACTIVATING 0x20 + +// +// Constants and Structure definitions for "SOL activating" command to follow here +// +typedef union { + struct { + UINT8 SessionState : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_SOL_SESSION_STATE; + +typedef struct { + IPMI_SOL_SESSION_STATE SessionState; + UINT8 PayloadInstance; + UINT8 FormatVersionMajor; // 1 + UINT8 FormatVersionMinor; // 0 +} IPMI_SOL_ACTIVATING_REQUEST; + +// +// Definitions for Set SOL Configuration Parameters command +// +#define IPMI_TRANSPORT_SET_SOL_CONFIG_PARAM 0x21 + +// +// Constants and Structure definitions for "Set SOL Configuration Parameters" command to follow here +// + +// +// SOL Configuration Parameters selector +// +#define IPMI_SOL_CONFIGURATION_PARAMETER_SET_IN_PROGRESS 0 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_ENABLE 1 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_AUTHENTICATION 2 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_CHARACTER_PARAM 3 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_RETRY 4 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_NV_BIT_RATE 5 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_VOLATILE_BIT_RATE 6 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_PAYLOAD_CHANNEL 7 +#define IPMI_SOL_CONFIGURATION_PARAMETER_SOL_PAYLOAD_PORT 8 + +typedef union { + struct { + UINT8 ChannelNumber : 4; + UINT8 Reserved : 4; + } Bits; + UINT8 Uint8; +} IPMI_SET_SOL_CONFIG_PARAM_CHANNEL_NUM; + +typedef struct { + IPMI_SET_SOL_CONFIG_PARAM_CHANNEL_NUM ChannelNumber; + UINT8 ParameterSelector; + UINT8 ParameterData[0]; +} IPMI_SET_SOL_CONFIGURATION_PARAMETERS_REQUEST; + +// +// Definitions for Get SOL Configuration Parameters command +// +#define IPMI_TRANSPORT_GET_SOL_CONFIG_PARAM 0x22 + +// +// Constants and Structure definitions for "Get SOL Configuration Parameters" command to follow here +// +typedef union { + struct { + UINT8 ChannelNumber : 4; + UINT8 Reserved : 3; + UINT8 GetParameter : 1; + } Bits; + UINT8 Uint8; +} IPMI_GET_SOL_CONFIG_PARAM_CHANNEL_NUM; + +typedef struct { + IPMI_GET_SOL_CONFIG_PARAM_CHANNEL_NUM ChannelNumber; + UINT8 ParameterSelector; + UINT8 SetSelector; + UINT8 BlockSelector; +} IPMI_GET_SOL_CONFIGURATION_PARAMETERS_REQUEST; + +typedef struct { + UINT8 CompletionCode; + UINT8 ParameterRevision; + UINT8 ParameterData[0]; +} IPMI_GET_SOL_CONFIGURATION_PARAMETERS_RESPONSE; + +#pragma pack() +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LegacyBiosMpTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LegacyBiosMpTable.h new file mode 100644 index 0000000..61a6e9e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LegacyBiosMpTable.h @@ -0,0 +1,294 @@ +/** @file + Defives data structures per MultiProcessor Specification Ver 1.4. + + The MultiProcessor Specification defines an enhancement to the standard + to which PC manufacturers design DOS-compatible systems. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LEGACY_BIOS_MPTABLE_H_ +#define _LEGACY_BIOS_MPTABLE_H_ + +#define EFI_LEGACY_MP_TABLE_REV_1_4 0x04 + +// +// Define MP table structures. All are packed. +// +#pragma pack(1) + +#define EFI_LEGACY_MP_TABLE_FLOATING_POINTER_SIGNATURE SIGNATURE_32 ('_', 'M', 'P', '_') +typedef struct { + UINT32 Reserved1 : 6; + UINT32 MutipleClk : 1; + UINT32 Imcr : 1; + UINT32 Reserved2 : 24; +} FEATUREBYTE2_5; + +typedef struct { + UINT32 Signature; + UINT32 PhysicalAddress; + UINT8 Length; + UINT8 SpecRev; + UINT8 Checksum; + UINT8 FeatureByte1; + FEATUREBYTE2_5 FeatureByte2_5; +} EFI_LEGACY_MP_TABLE_FLOATING_POINTER; + +#define EFI_LEGACY_MP_TABLE_HEADER_SIGNATURE SIGNATURE_32 ('P', 'C', 'M', 'P') +typedef struct { + UINT32 Signature; + UINT16 BaseTableLength; + UINT8 SpecRev; + UINT8 Checksum; + CHAR8 OemId[8]; + CHAR8 OemProductId[12]; + UINT32 OemTablePointer; + UINT16 OemTableSize; + UINT16 EntryCount; + UINT32 LocalApicAddress; + UINT16 ExtendedTableLength; + UINT8 ExtendedChecksum; + UINT8 Reserved; +} EFI_LEGACY_MP_TABLE_HEADER; + +typedef struct { + UINT8 EntryType; +} EFI_LEGACY_MP_TABLE_ENTRY_TYPE; + +// +// Entry Type 0: Processor. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_PROCESSOR 0x00 +typedef struct { + UINT8 Enabled : 1; + UINT8 Bsp : 1; + UINT8 Reserved : 6; +} EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR_FLAGS; + +typedef struct { + UINT32 Stepping : 4; + UINT32 Model : 4; + UINT32 Family : 4; + UINT32 Reserved : 20; +} EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR_SIGNATURE; + +typedef struct { + UINT32 Fpu : 1; + UINT32 Reserved1 : 6; + UINT32 Mce : 1; + UINT32 Cx8 : 1; + UINT32 Apic : 1; + UINT32 Reserved2 : 22; +} EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR_FEATURES; + +typedef struct { + UINT8 EntryType; + UINT8 Id; + UINT8 Ver; + EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR_FLAGS Flags; + EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR_SIGNATURE Signature; + EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR_FEATURES Features; + UINT32 Reserved1; + UINT32 Reserved2; +} EFI_LEGACY_MP_TABLE_ENTRY_PROCESSOR; + +// +// Entry Type 1: Bus. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_BUS 0x01 +typedef struct { + UINT8 EntryType; + UINT8 Id; + CHAR8 TypeString[6]; +} EFI_LEGACY_MP_TABLE_ENTRY_BUS; + +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_CBUS "CBUS " // Corollary CBus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_CBUSII "CBUSII" // Corollary CBUS II +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_EISA "EISA " // Extended ISA +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_FUTURE "FUTURE" // IEEE FutureBus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_INTERN "INTERN" // Internal bus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_ISA "ISA " // Industry Standard Architecture +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MBI "MBI " // Multibus I +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MBII "MBII " // Multibus II +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MCA "MCA " // Micro Channel Architecture +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MPI "MPI " // MPI +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_MPSA "MPSA " // MPSA +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_NUBUS "NUBUS " // Apple Macintosh NuBus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_PCI "PCI " // Peripheral Component Interconnect +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_PCMCIA "PCMCIA" // PC Memory Card International Assoc. +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_TC "TC " // DEC TurboChannel +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_VL "VL " // VESA Local Bus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_VME "VME " // VMEbus +#define EFI_LEGACY_MP_TABLE_ENTRY_BUS_STRING_XPRESS "XPRESS" // Express System Bus +// +// Entry Type 2: I/O APIC. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_IOAPIC 0x02 +typedef struct { + UINT8 Enabled : 1; + UINT8 Reserved : 7; +} EFI_LEGACY_MP_TABLE_ENTRY_IOAPIC_FLAGS; + +typedef struct { + UINT8 EntryType; + UINT8 Id; + UINT8 Ver; + EFI_LEGACY_MP_TABLE_ENTRY_IOAPIC_FLAGS Flags; + UINT32 Address; +} EFI_LEGACY_MP_TABLE_ENTRY_IOAPIC; + +// +// Entry Type 3: I/O Interrupt Assignment. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_IO_INT 0x03 +typedef struct { + UINT16 Polarity : 2; + UINT16 Trigger : 2; + UINT16 Reserved : 12; +} EFI_LEGACY_MP_TABLE_ENTRY_INT_FLAGS; + +typedef struct { + UINT8 IntNo : 2; + UINT8 Dev : 5; + UINT8 Reserved : 1; +} EFI_LEGACY_MP_TABLE_ENTRY_INT_FIELDS; + +typedef union { + EFI_LEGACY_MP_TABLE_ENTRY_INT_FIELDS fields; + UINT8 byte; +} EFI_LEGACY_MP_TABLE_ENTRY_INT_SOURCE_BUS_IRQ; + +typedef struct { + UINT8 EntryType; + UINT8 IntType; + EFI_LEGACY_MP_TABLE_ENTRY_INT_FLAGS Flags; + UINT8 SourceBusId; + EFI_LEGACY_MP_TABLE_ENTRY_INT_SOURCE_BUS_IRQ SourceBusIrq; + UINT8 DestApicId; + UINT8 DestApicIntIn; +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT; + +typedef enum { + EfiLegacyMpTableEntryIoIntTypeInt = 0, + EfiLegacyMpTableEntryIoIntTypeNmi = 1, + EfiLegacyMpTableEntryIoIntTypeSmi = 2, + EfiLegacyMpTableEntryIoIntTypeExtInt= 3, +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT_TYPE; + +typedef enum { + EfiLegacyMpTableEntryIoIntFlagsPolaritySpec = 0x0, + EfiLegacyMpTableEntryIoIntFlagsPolarityActiveHigh = 0x1, + EfiLegacyMpTableEntryIoIntFlagsPolarityReserved = 0x2, + EfiLegacyMpTableEntryIoIntFlagsPolarityActiveLow = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT_FLAGS_POLARITY; + +typedef enum { + EfiLegacyMpTableEntryIoIntFlagsTriggerSpec = 0x0, + EfiLegacyMpTableEntryIoIntFlagsTriggerEdge = 0x1, + EfiLegacyMpTableEntryIoIntFlagsTriggerReserved = 0x2, + EfiLegacyMpTableEntryIoIntFlagsTriggerLevel = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_IO_INT_FLAGS_TRIGGER; + +// +// Entry Type 4: Local Interrupt Assignment. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_TYPE_LOCAL_INT 0x04 +typedef struct { + UINT8 EntryType; + UINT8 IntType; + EFI_LEGACY_MP_TABLE_ENTRY_INT_FLAGS Flags; + UINT8 SourceBusId; + EFI_LEGACY_MP_TABLE_ENTRY_INT_SOURCE_BUS_IRQ SourceBusIrq; + UINT8 DestApicId; + UINT8 DestApicIntIn; +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT; + +typedef enum { + EfiLegacyMpTableEntryLocalIntTypeInt = 0, + EfiLegacyMpTableEntryLocalIntTypeNmi = 1, + EfiLegacyMpTableEntryLocalIntTypeSmi = 2, + EfiLegacyMpTableEntryLocalIntTypeExtInt = 3, +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT_TYPE; + +typedef enum { + EfiLegacyMpTableEntryLocalIntFlagsPolaritySpec = 0x0, + EfiLegacyMpTableEntryLocalIntFlagsPolarityActiveHigh= 0x1, + EfiLegacyMpTableEntryLocalIntFlagsPolarityReserved = 0x2, + EfiLegacyMpTableEntryLocalIntFlagsPolarityActiveLow = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT_FLAGS_POLARITY; + +typedef enum { + EfiLegacyMpTableEntryLocalIntFlagsTriggerSpec = 0x0, + EfiLegacyMpTableEntryLocalIntFlagsTriggerEdge = 0x1, + EfiLegacyMpTableEntryLocalIntFlagsTriggerReserved = 0x2, + EfiLegacyMpTableEntryLocalIntFlagsTriggerLevel = 0x3, +} EFI_LEGACY_MP_TABLE_ENTRY_LOCAL_INT_FLAGS_TRIGGER; + +// +// Entry Type 128: System Address Space Mapping. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_EXT_TYPE_SYS_ADDR_SPACE_MAPPING 0x80 +typedef struct { + UINT8 EntryType; + UINT8 Length; + UINT8 BusId; + UINT8 AddressType; + UINT64 AddressBase; + UINT64 AddressLength; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_SYS_ADDR_SPACE_MAPPING; + +typedef enum { + EfiLegacyMpTableEntryExtSysAddrSpaceMappingIo = 0, + EfiLegacyMpTableEntryExtSysAddrSpaceMappingMemory = 1, + EfiLegacyMpTableEntryExtSysAddrSpaceMappingPrefetch = 2, +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_SYS_ADDR_SPACE_MAPPING_TYPE; + +// +// Entry Type 129: Bus Hierarchy. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_EXT_TYPE_BUS_HIERARCHY 0x81 +typedef struct { + UINT8 SubtractiveDecode : 1; + UINT8 Reserved : 7; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_BUS_HIERARCHY_BUSINFO; + +typedef struct { + UINT8 EntryType; + UINT8 Length; + UINT8 BusId; + EFI_LEGACY_MP_TABLE_ENTRY_EXT_BUS_HIERARCHY_BUSINFO BusInfo; + UINT8 ParentBus; + UINT8 Reserved1; + UINT8 Reserved2; + UINT8 Reserved3; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_BUS_HIERARCHY; + +// +// Entry Type 130: Compatibility Bus Address Space Modifier. +// +#define EFI_LEGACY_MP_TABLE_ENTRY_EXT_TYPE_COMPAT_BUS_ADDR_SPACE_MODIFIER 0x82 +typedef struct { + UINT8 RangeMode : 1; + UINT8 Reserved : 7; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_COMPAT_BUS_ADDR_SPACE_MODIFIER_ADDR_MODE; + +typedef struct { + UINT8 EntryType; + UINT8 Length; + UINT8 BusId; + EFI_LEGACY_MP_TABLE_ENTRY_EXT_COMPAT_BUS_ADDR_SPACE_MODIFIER_ADDR_MODE AddrMode; + UINT32 PredefinedRangeList; +} EFI_LEGACY_MP_TABLE_ENTRY_EXT_COMPAT_BUS_ADDR_SPACE_MODIFIER; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LowPowerIdleTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LowPowerIdleTable.h new file mode 100644 index 0000000..2b361ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/LowPowerIdleTable.h @@ -0,0 +1,82 @@ +/** @file + ACPI Low Power Idle Table (LPIT) definitions + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - ACPI Low Power Idle Table (LPIT) Revision 001, dated July 2014 + http://www.uefi.org/sites/default/files/resources/ACPI_Low_Power_Idle_Table.pdf + + @par Glossary: + - GAS - Generic Address Structure + - LPI - Low Power Idle +**/ +#ifndef _LOW_POWER_IDLE_TABLE_H_ +#define _LOW_POWER_IDLE_TABLE_H_ + +#include + +#pragma pack(1) + +/// +/// LPI Structure Types +/// +#define ACPI_LPI_STRUCTURE_TYPE_NATIVE_CSTATE 0x00 + +/// +/// Low Power Idle (LPI) State Flags +/// +typedef union { + struct { + UINT32 Disabled : 1; ///< If set, LPI state is not used + /** + If set, Residency counter is not available for this LPI state and + Residency Counter Frequency is invalid + **/ + UINT32 CounterUnavailable : 1; + UINT32 Reserved : 30; ///< Reserved for future use. Must be zero + } Bits; + UINT32 Data32; +} ACPI_LPI_STATE_FLAGS; + +/// +/// Low Power Idle (LPI) structure with Native C-state instruction entry trigger descriptor +/// +typedef struct { + UINT32 Type; ///< LPI State descriptor Type 0 + UINT32 Length; ///< Length of LPI state Descriptor Structure + /// + /// Unique LPI state identifier: zero based, monotonically increasing identifier + /// + UINT16 UniqueId; + UINT8 Reserved[2]; ///< Must be Zero + ACPI_LPI_STATE_FLAGS Flags; ///< LPI state flags + /** + The LPI entry trigger, matching an existing _CST.Register object, represented as a + Generic Address Structure. All processors must request this state or deeper to trigger. + **/ + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE EntryTrigger; + UINT32 Residency; ///< Minimum residency or break-even in uSec + UINT32 Latency; ///< Worst case exit latency in uSec + /** + [optional] Residency counter, represented as a Generic Address Structure. + If not present, Flags[1] bit should be set. + **/ + EFI_ACPI_6_1_GENERIC_ADDRESS_STRUCTURE ResidencyCounter; + /** + [optional] Residency counter frequency in cycles per second. Value 0 indicates that + counter runs at TSC frequency. Valid only if Residency Counter is present. + **/ + UINT64 ResidencyCounterFrequency; +} ACPI_LPI_NATIVE_CSTATE_DESCRIPTOR; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Mbr.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Mbr.h new file mode 100644 index 0000000..bf6f843 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Mbr.h @@ -0,0 +1,60 @@ +/** @file + Legacy Master Boot Record Format Definition. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MBR_H_ +#define _MBR_H_ + +#define MBR_SIGNATURE 0xaa55 + +#define EXTENDED_DOS_PARTITION 0x05 +#define EXTENDED_WINDOWS_PARTITION 0x0F + +#define MAX_MBR_PARTITIONS 4 + +#define PMBR_GPT_PARTITION 0xEE +#define EFI_PARTITION 0xEF + +#define MBR_SIZE 512 + +#pragma pack(1) +/// +/// MBR Partition Entry +/// +typedef struct { + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSIndicator; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT8 StartingLBA[4]; + UINT8 SizeInLBA[4]; +} MBR_PARTITION_RECORD; + +/// +/// MBR Partition Table +/// +typedef struct { + UINT8 BootStrapCode[440]; + UINT8 UniqueMbrSignature[4]; + UINT8 Unknown[2]; + MBR_PARTITION_RECORD Partition[MAX_MBR_PARTITIONS]; + UINT16 Signature; +} MASTER_BOOT_RECORD; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h new file mode 100644 index 0000000..cdcc345 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h @@ -0,0 +1,53 @@ +/** @file + ACPI memory mapped configuration space access table definition, defined at + in the PCI Firmware Specification, version 3.0. + Specification is available at http://www.pcisig.com. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_ +#define _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_ + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// Memory Mapped Configuration Space Access Table (MCFG) +/// This table is a basic description table header followed by +/// a number of base address allocation structures. +/// +typedef struct { + UINT64 BaseAddress; + UINT16 PciSegmentGroupNumber; + UINT8 StartBusNumber; + UINT8 EndBusNumber; + UINT32 Reserved; +} EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE; + +/// +/// MCFG Table header definition. The rest of the table +/// must be defined in a platform specific manner. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 Reserved; +} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER; + +/// +/// MCFG Revision (defined in spec) +/// +#define EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION 0x01 + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryOverwriteRequestControlLock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryOverwriteRequestControlLock.h new file mode 100644 index 0000000..91ee477 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/MemoryOverwriteRequestControlLock.h @@ -0,0 +1,43 @@ +/** @file + Support for Microsoft Secure MOR implementation, defined at + Microsoft Secure MOR implementation. + https://msdn.microsoft.com/en-us/library/windows/hardware/mt270973(v=vs.85).aspx + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_H__ +#define __MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_H__ + +#define MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_GUID \ + { \ + 0xBB983CCF, 0x151D, 0x40E1, {0xA0, 0x7B, 0x4A, 0x17, 0xBE, 0x16, 0x82, 0x92} \ + } + +#define MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME L"MemoryOverwriteRequestControlLock" + +// +// VendorGuid: {BB983CCF-151D-40E1-A07B-4A17BE168292} +// Name: MemoryOverwriteRequestControlLock +// Attributes: NV+BS+RT +// GetVariable value in Data parameter: 0x0 (unlocked); 0x1 (locked without key); 0x2 (locked with key) +// SetVariable value in Data parameter: 0x0 (unlocked); 0x1 (locked); +// Revision 2 additionally accepts an 8-byte value that represents a shared secret key. +// + +// +// Note: Setting MemoryOverwriteRequestControlLock does not commit to flash (just changes the internal lock state). +// Getting the variable returns the internal state and never exposes the key. +// + +extern EFI_GUID gEfiMemoryOverwriteRequestControlLockGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Nvme.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Nvme.h new file mode 100644 index 0000000..49ce876 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Nvme.h @@ -0,0 +1,939 @@ +/** @file + Definitions based on NVMe spec. version 1.1. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Specification Reference: + NVMe Specification 1.1 + +**/ + +#ifndef __NVM_E_H__ +#define __NVM_E_H__ + +#pragma pack(1) + +// +// controller register offsets +// +#define NVME_CAP_OFFSET 0x0000 // Controller Capabilities +#define NVME_VER_OFFSET 0x0008 // Version +#define NVME_INTMS_OFFSET 0x000c // Interrupt Mask Set +#define NVME_INTMC_OFFSET 0x0010 // Interrupt Mask Clear +#define NVME_CC_OFFSET 0x0014 // Controller Configuration +#define NVME_CSTS_OFFSET 0x001c // Controller Status +#define NVME_NSSR_OFFSET 0x0020 // NVM Subsystem Reset +#define NVME_AQA_OFFSET 0x0024 // Admin Queue Attributes +#define NVME_ASQ_OFFSET 0x0028 // Admin Submission Queue Base Address +#define NVME_ACQ_OFFSET 0x0030 // Admin Completion Queue Base Address +#define NVME_SQ0_OFFSET 0x1000 // Submission Queue 0 (admin) Tail Doorbell +#define NVME_CQ0_OFFSET 0x1004 // Completion Queue 0 (admin) Head Doorbell + +// +// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD)) +// Get the doorbell stride bit shift value from the controller capabilities. +// +#define NVME_SQTDBL_OFFSET(QID, DSTRD) 0x1000 + ((2 * (QID)) * (4 << (DSTRD))) // Submission Queue y (NVM) Tail Doorbell +#define NVME_CQHDBL_OFFSET(QID, DSTRD) 0x1000 + (((2 * (QID)) + 1) * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell + + +#pragma pack(1) + +// +// 3.1.1 Offset 00h: CAP - Controller Capabilities +// +typedef struct { + UINT16 Mqes; // Maximum Queue Entries Supported + UINT8 Cqr:1; // Contiguous Queues Required + UINT8 Ams:2; // Arbitration Mechanism Supported + UINT8 Rsvd1:5; + UINT8 To; // Timeout + UINT16 Dstrd:4; + UINT16 Nssrs:1; // NVM Subsystem Reset Supported NSSRS + UINT16 Css:4; // Command Sets Supported - Bit 37 + UINT16 Rsvd3:7; + UINT8 Mpsmin:4; + UINT8 Mpsmax:4; + UINT8 Rsvd4; +} NVME_CAP; + +// +// 3.1.2 Offset 08h: VS - Version +// +typedef struct { + UINT16 Mnr; // Minor version number + UINT16 Mjr; // Major version number +} NVME_VER; + +// +// 3.1.5 Offset 14h: CC - Controller Configuration +// +typedef struct { + UINT16 En:1; // Enable + UINT16 Rsvd1:3; + UINT16 Css:3; // I/O Command Set Selected + UINT16 Mps:4; // Memory Page Size + UINT16 Ams:3; // Arbitration Mechanism Selected + UINT16 Shn:2; // Shutdown Notification + UINT8 Iosqes:4; // I/O Submission Queue Entry Size + UINT8 Iocqes:4; // I/O Completion Queue Entry Size + UINT8 Rsvd2; +} NVME_CC; +#define NVME_CC_SHN_NORMAL_SHUTDOWN 1 +#define NVME_CC_SHN_ABRUPT_SHUTDOWN 2 + +// +// 3.1.6 Offset 1Ch: CSTS - Controller Status +// +typedef struct { + UINT32 Rdy:1; // Ready + UINT32 Cfs:1; // Controller Fatal Status + UINT32 Shst:2; // Shutdown Status + UINT32 Nssro:1; // NVM Subsystem Reset Occurred + UINT32 Rsvd1:27; +} NVME_CSTS; +#define NVME_CSTS_SHST_SHUTDOWN_OCCURRING 1 +#define NVME_CSTS_SHST_SHUTDOWN_COMPLETED 2 +// +// 3.1.8 Offset 24h: AQA - Admin Queue Attributes +// +typedef struct { + UINT16 Asqs:12; // Submission Queue Size + UINT16 Rsvd1:4; + UINT16 Acqs:12; // Completion Queue Size + UINT16 Rsvd2:4; +} NVME_AQA; + +// +// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address +// +#define NVME_ASQ UINT64 +// +// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address +// +#define NVME_ACQ UINT64 + +// +// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission Queue y Tail Doorbell +// +typedef struct { + UINT16 Sqt; + UINT16 Rsvd1; +} NVME_SQTDBL; + +// +// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL - Completion Queue y Head Doorbell +// +typedef struct { + UINT16 Cqh; + UINT16 Rsvd1; +} NVME_CQHDBL; + +// +// NVM command set structures +// +// Read Command +// +typedef struct { + // + // CDW 10, 11 + // + UINT64 Slba; /* Starting Sector Address */ + // + // CDW 12 + // + UINT16 Nlb; /* Number of Sectors */ + UINT16 Rsvd1:10; + UINT16 Prinfo:4; /* Protection Info Check */ + UINT16 Fua:1; /* Force Unit Access */ + UINT16 Lr:1; /* Limited Retry */ + // + // CDW 13 + // + UINT32 Af:4; /* Access Frequency */ + UINT32 Al:2; /* Access Latency */ + UINT32 Sr:1; /* Sequential Request */ + UINT32 In:1; /* Incompressible */ + UINT32 Rsvd2:24; + // + // CDW 14 + // + UINT32 Eilbrt; /* Expected Initial Logical Block Reference Tag */ + // + // CDW 15 + // + UINT16 Elbat; /* Expected Logical Block Application Tag */ + UINT16 Elbatm; /* Expected Logical Block Application Tag Mask */ +} NVME_READ; + +// +// Write Command +// +typedef struct { + // + // CDW 10, 11 + // + UINT64 Slba; /* Starting Sector Address */ + // + // CDW 12 + // + UINT16 Nlb; /* Number of Sectors */ + UINT16 Rsvd1:10; + UINT16 Prinfo:4; /* Protection Info Check */ + UINT16 Fua:1; /* Force Unit Access */ + UINT16 Lr:1; /* Limited Retry */ + // + // CDW 13 + // + UINT32 Af:4; /* Access Frequency */ + UINT32 Al:2; /* Access Latency */ + UINT32 Sr:1; /* Sequential Request */ + UINT32 In:1; /* Incompressible */ + UINT32 Rsvd2:24; + // + // CDW 14 + // + UINT32 Ilbrt; /* Initial Logical Block Reference Tag */ + // + // CDW 15 + // + UINT16 Lbat; /* Logical Block Application Tag */ + UINT16 Lbatm; /* Logical Block Application Tag Mask */ +} NVME_WRITE; + +// +// Flush +// +typedef struct { + // + // CDW 10 + // + UINT32 Flush; /* Flush */ +} NVME_FLUSH; + +// +// Write Uncorrectable command +// +typedef struct { + // + // CDW 10, 11 + // + UINT64 Slba; /* Starting LBA */ + // + // CDW 12 + // + UINT32 Nlb:16; /* Number of Logical Blocks */ + UINT32 Rsvd1:16; +} NVME_WRITE_UNCORRECTABLE; + +// +// Write Zeroes command +// +typedef struct { + // + // CDW 10, 11 + // + UINT64 Slba; /* Starting LBA */ + // + // CDW 12 + // + UINT16 Nlb; /* Number of Logical Blocks */ + UINT16 Rsvd1:10; + UINT16 Prinfo:4; /* Protection Info Check */ + UINT16 Fua:1; /* Force Unit Access */ + UINT16 Lr:1; /* Limited Retry */ + // + // CDW 13 + // + UINT32 Rsvd2; + // + // CDW 14 + // + UINT32 Ilbrt; /* Initial Logical Block Reference Tag */ + // + // CDW 15 + // + UINT16 Lbat; /* Logical Block Application Tag */ + UINT16 Lbatm; /* Logical Block Application Tag Mask */ +} NVME_WRITE_ZEROES; + +// +// Compare command +// +typedef struct { + // + // CDW 10, 11 + // + UINT64 Slba; /* Starting LBA */ + // + // CDW 12 + // + UINT16 Nlb; /* Number of Logical Blocks */ + UINT16 Rsvd1:10; + UINT16 Prinfo:4; /* Protection Info Check */ + UINT16 Fua:1; /* Force Unit Access */ + UINT16 Lr:1; /* Limited Retry */ + // + // CDW 13 + // + UINT32 Rsvd2; + // + // CDW 14 + // + UINT32 Eilbrt; /* Expected Initial Logical Block Reference Tag */ + // + // CDW 15 + // + UINT16 Elbat; /* Expected Logical Block Application Tag */ + UINT16 Elbatm; /* Expected Logical Block Application Tag Mask */ +} NVME_COMPARE; + +typedef union { + NVME_READ Read; + NVME_WRITE Write; + NVME_FLUSH Flush; + NVME_WRITE_UNCORRECTABLE WriteUncorrectable; + NVME_WRITE_ZEROES WriteZeros; + NVME_COMPARE Compare; +} NVME_CMD; + +typedef struct { + UINT16 Mp; /* Maximum Power */ + UINT8 Rsvd1; /* Reserved as of Nvm Express 1.1 Spec */ + UINT8 Mps:1; /* Max Power Scale */ + UINT8 Nops:1; /* Non-Operational State */ + UINT8 Rsvd2:6; /* Reserved as of Nvm Express 1.1 Spec */ + UINT32 Enlat; /* Entry Latency */ + UINT32 Exlat; /* Exit Latency */ + UINT8 Rrt:5; /* Relative Read Throughput */ + UINT8 Rsvd3:3; /* Reserved as of Nvm Express 1.1 Spec */ + UINT8 Rrl:5; /* Relative Read Leatency */ + UINT8 Rsvd4:3; /* Reserved as of Nvm Express 1.1 Spec */ + UINT8 Rwt:5; /* Relative Write Throughput */ + UINT8 Rsvd5:3; /* Reserved as of Nvm Express 1.1 Spec */ + UINT8 Rwl:5; /* Relative Write Leatency */ + UINT8 Rsvd6:3; /* Reserved as of Nvm Express 1.1 Spec */ + UINT8 Rsvd7[16]; /* Reserved as of Nvm Express 1.1 Spec */ +} NVME_PSDESCRIPTOR; + +// +// Identify Controller Data +// +typedef struct { + // + // Controller Capabilities and Features 0-255 + // + UINT16 Vid; /* PCI Vendor ID */ + UINT16 Ssvid; /* PCI sub-system vendor ID */ + UINT8 Sn[20]; /* Product serial number */ + + UINT8 Mn[40]; /* Proeduct model number */ + UINT8 Fr[8]; /* Firmware Revision */ + UINT8 Rab; /* Recommended Arbitration Burst */ + UINT8 Ieee_oui[3]; /* Organization Unique Identifier */ + UINT8 Cmic; /* Multi-interface Capabilities */ + UINT8 Mdts; /* Maximum Data Transfer Size */ + UINT8 Cntlid[2]; /* Controller ID */ + UINT8 Rsvd1[176]; /* Reserved as of Nvm Express 1.1 Spec */ + // + // Admin Command Set Attributes + // + UINT16 Oacs; /* Optional Admin Command Support */ + #define NAMESPACE_MANAGEMENT_SUPPORTED BIT3 + #define FW_DOWNLOAD_ACTIVATE_SUPPORTED BIT2 + #define FORMAT_NVM_SUPPORTED BIT1 + #define SECURITY_SEND_RECEIVE_SUPPORTED BIT0 + UINT8 Acl; /* Abort Command Limit */ + UINT8 Aerl; /* Async Event Request Limit */ + UINT8 Frmw; /* Firmware updates */ + UINT8 Lpa; /* Log Page Attributes */ + UINT8 Elpe; /* Error Log Page Entries */ + UINT8 Npss; /* Number of Power States Support */ + UINT8 Avscc; /* Admin Vendor Specific Command Configuration */ + UINT8 Apsta; /* Autonomous Power State Transition Attributes */ + UINT8 Rsvd2[246]; /* Reserved as of Nvm Express 1.1 Spec */ + // + // NVM Command Set Attributes + // + UINT8 Sqes; /* Submission Queue Entry Size */ + UINT8 Cqes; /* Completion Queue Entry Size */ + UINT16 Rsvd3; /* Reserved as of Nvm Express 1.1 Spec */ + UINT32 Nn; /* Number of Namespaces */ + UINT16 Oncs; /* Optional NVM Command Support */ + UINT16 Fuses; /* Fused Operation Support */ + UINT8 Fna; /* Format NVM Attributes */ + UINT8 Vwc; /* Volatile Write Cache */ + UINT16 Awun; /* Atomic Write Unit Normal */ + UINT16 Awupf; /* Atomic Write Unit Power Fail */ + UINT8 Nvscc; /* NVM Vendor Specific Command Configuration */ + UINT8 Rsvd4; /* Reserved as of Nvm Express 1.1 Spec */ + UINT16 Acwu; /* Atomic Compare & Write Unit */ + UINT16 Rsvd5; /* Reserved as of Nvm Express 1.1 Spec */ + UINT32 Sgls; /* SGL Support */ + UINT8 Rsvd6[164]; /* Reserved as of Nvm Express 1.1 Spec */ + // + // I/O Command set Attributes + // + UINT8 Rsvd7[1344]; /* Reserved as of Nvm Express 1.1 Spec */ + // + // Power State Descriptors + // + NVME_PSDESCRIPTOR PsDescriptor[32]; + + UINT8 VendorData[1024]; /* Vendor specific data */ +} NVME_ADMIN_CONTROLLER_DATA; + +typedef struct { + UINT16 Ms; /* Metadata Size */ + UINT8 Lbads; /* LBA Data Size */ + UINT8 Rp:2; /* Relative Performance */ + #define LBAF_RP_BEST 00b + #define LBAF_RP_BETTER 01b + #define LBAF_RP_GOOD 10b + #define LBAF_RP_DEGRADED 11b + UINT8 Rsvd1:6; /* Reserved as of Nvm Express 1.1 Spec */ +} NVME_LBAFORMAT; + +// +// Identify Namespace Data +// +typedef struct { + // + // NVM Command Set Specific + // + UINT64 Nsze; /* Namespace Size (total number of blocks in formatted namespace) */ + UINT64 Ncap; /* Namespace Capacity (max number of logical blocks) */ + UINT64 Nuse; /* Namespace Utilization */ + UINT8 Nsfeat; /* Namespace Features */ + UINT8 Nlbaf; /* Number of LBA Formats */ + UINT8 Flbas; /* Formatted LBA size */ + UINT8 Mc; /* Metadata Capabilities */ + UINT8 Dpc; /* End-to-end Data Protection capabilities */ + UINT8 Dps; /* End-to-end Data Protection Type Settings */ + UINT8 Nmic; /* Namespace Multi-path I/O and Namespace Sharing Capabilities */ + UINT8 Rescap; /* Reservation Capabilities */ + UINT8 Rsvd1[88]; /* Reserved as of Nvm Express 1.1 Spec */ + UINT64 Eui64; /* IEEE Extended Unique Identifier */ + // + // LBA Format + // + NVME_LBAFORMAT LbaFormat[16]; + + UINT8 Rsvd2[192]; /* Reserved as of Nvm Express 1.1 Spec */ + UINT8 VendorData[3712]; /* Vendor specific data */ +} NVME_ADMIN_NAMESPACE_DATA; + +// +// NvmExpress Admin Identify Cmd +// +typedef struct { + // + // CDW 10 + // + UINT32 Cns:2; + UINT32 Rsvd1:30; +} NVME_ADMIN_IDENTIFY; + +// +// NvmExpress Admin Create I/O Completion Queue +// +typedef struct { + // + // CDW 10 + // + UINT32 Qid:16; /* Queue Identifier */ + UINT32 Qsize:16; /* Queue Size */ + + // + // CDW 11 + // + UINT32 Pc:1; /* Physically Contiguous */ + UINT32 Ien:1; /* Interrupts Enabled */ + UINT32 Rsvd1:14; /* reserved as of Nvm Express 1.1 Spec */ + UINT32 Iv:16; /* Interrupt Vector for MSI-X or MSI*/ +} NVME_ADMIN_CRIOCQ; + +// +// NvmExpress Admin Create I/O Submission Queue +// +typedef struct { + // + // CDW 10 + // + UINT32 Qid:16; /* Queue Identifier */ + UINT32 Qsize:16; /* Queue Size */ + + // + // CDW 11 + // + UINT32 Pc:1; /* Physically Contiguous */ + UINT32 Qprio:2; /* Queue Priority */ + UINT32 Rsvd1:13; /* Reserved as of Nvm Express 1.1 Spec */ + UINT32 Cqid:16; /* Completion Queue ID */ +} NVME_ADMIN_CRIOSQ; + +// +// NvmExpress Admin Delete I/O Completion Queue +// +typedef struct { + // + // CDW 10 + // + UINT16 Qid; + UINT16 Rsvd1; +} NVME_ADMIN_DEIOCQ; + +// +// NvmExpress Admin Delete I/O Submission Queue +// +typedef struct { + // + // CDW 10 + // + UINT16 Qid; + UINT16 Rsvd1; +} NVME_ADMIN_DEIOSQ; + +// +// NvmExpress Admin Abort Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Sqid:16; /* Submission Queue identifier */ + UINT32 Cid:16; /* Command Identifier */ +} NVME_ADMIN_ABORT; + +// +// NvmExpress Admin Firmware Activate Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Fs:3; /* Submission Queue identifier */ + UINT32 Aa:2; /* Command Identifier */ + UINT32 Rsvd1:27; +} NVME_ADMIN_FIRMWARE_ACTIVATE; + +// +// NvmExpress Admin Firmware Image Download Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Numd; /* Number of Dwords */ + // + // CDW 11 + // + UINT32 Ofst; /* Offset */ +} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD; + +// +// NvmExpress Admin Get Features Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Fid:8; /* Feature Identifier */ + UINT32 Sel:3; /* Select */ + UINT32 Rsvd1:21; +} NVME_ADMIN_GET_FEATURES; + +// +// NvmExpress Admin Get Log Page Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Lid:8; /* Log Page Identifier */ + #define LID_ERROR_INFO 0x1 + #define LID_SMART_INFO 0x2 + #define LID_FW_SLOT_INFO 0x3 + UINT32 Rsvd1:8; + UINT32 Numd:12; /* Number of Dwords */ + UINT32 Rsvd2:4; /* Reserved as of Nvm Express 1.1 Spec */ +} NVME_ADMIN_GET_LOG_PAGE; + +// +// NvmExpress Admin Set Features Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Fid:8; /* Feature Identifier */ + UINT32 Rsvd1:23; + UINT32 Sv:1; /* Save */ +} NVME_ADMIN_SET_FEATURES; + +// +// NvmExpress Admin Format NVM Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Lbaf:4; /* LBA Format */ + UINT32 Ms:1; /* Metadata Settings */ + UINT32 Pi:3; /* Protection Information */ + UINT32 Pil:1; /* Protection Information Location */ + UINT32 Ses:3; /* Secure Erase Settings */ + UINT32 Rsvd1:20; +} NVME_ADMIN_FORMAT_NVM; + +// +// NvmExpress Admin Security Receive Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Rsvd1:8; + UINT32 Spsp:16; /* SP Specific */ + UINT32 Secp:8; /* Security Protocol */ + // + // CDW 11 + // + UINT32 Al; /* Allocation Length */ +} NVME_ADMIN_SECURITY_RECEIVE; + +// +// NvmExpress Admin Security Send Command +// +typedef struct { + // + // CDW 10 + // + UINT32 Rsvd1:8; + UINT32 Spsp:16; /* SP Specific */ + UINT32 Secp:8; /* Security Protocol */ + // + // CDW 11 + // + UINT32 Tl; /* Transfer Length */ +} NVME_ADMIN_SECURITY_SEND; + +typedef union { + NVME_ADMIN_IDENTIFY Identify; + NVME_ADMIN_CRIOCQ CrIoCq; + NVME_ADMIN_CRIOSQ CrIoSq; + NVME_ADMIN_DEIOCQ DeIoCq; + NVME_ADMIN_DEIOSQ DeIoSq; + NVME_ADMIN_ABORT Abort; + NVME_ADMIN_FIRMWARE_ACTIVATE Activate; + NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD FirmwareImageDownload; + NVME_ADMIN_GET_FEATURES GetFeatures; + NVME_ADMIN_GET_LOG_PAGE GetLogPage; + NVME_ADMIN_SET_FEATURES SetFeatures; + NVME_ADMIN_FORMAT_NVM FormatNvm; + NVME_ADMIN_SECURITY_RECEIVE SecurityReceive; + NVME_ADMIN_SECURITY_SEND SecuritySend; +} NVME_ADMIN_CMD; + +typedef struct { + UINT32 Cdw10; + UINT32 Cdw11; + UINT32 Cdw12; + UINT32 Cdw13; + UINT32 Cdw14; + UINT32 Cdw15; +} NVME_RAW; + +typedef union { + NVME_ADMIN_CMD Admin; // Union of Admin commands + NVME_CMD Nvm; // Union of Nvm commands + NVME_RAW Raw; +} NVME_PAYLOAD; + +// +// Submission Queue +// +typedef struct { + // + // CDW 0, Common to all comnmands + // + UINT8 Opc; // Opcode + UINT8 Fuse:2; // Fused Operation + UINT8 Rsvd1:5; + UINT8 Psdt:1; // PRP or SGL for Data Transfer + UINT16 Cid; // Command Identifier + + // + // CDW 1 + // + UINT32 Nsid; // Namespace Identifier + + // + // CDW 2,3 + // + UINT64 Rsvd2; + + // + // CDW 4,5 + // + UINT64 Mptr; // Metadata Pointer + + // + // CDW 6-9 + // + UINT64 Prp[2]; // First and second PRP entries + + NVME_PAYLOAD Payload; + +} NVME_SQ; + +// +// Completion Queue +// +typedef struct { + // + // CDW 0 + // + UINT32 Dword0; + // + // CDW 1 + // + UINT32 Rsvd1; + // + // CDW 2 + // + UINT16 Sqhd; // Submission Queue Head Pointer + UINT16 Sqid; // Submission Queue Identifier + // + // CDW 3 + // + UINT16 Cid; // Command Identifier + UINT16 Pt:1; // Phase Tag + UINT16 Sc:8; // Status Code + UINT16 Sct:3; // Status Code Type + UINT16 Rsvd2:2; + UINT16 Mo:1; // More + UINT16 Dnr:1; // Do Not Retry +} NVME_CQ; + +// +// Nvm Express Admin cmd opcodes +// +#define NVME_ADMIN_DEIOSQ_CMD 0x00 +#define NVME_ADMIN_CRIOSQ_CMD 0x01 +#define NVME_ADMIN_GET_LOG_PAGE_CMD 0x02 +#define NVME_ADMIN_DEIOCQ_CMD 0x04 +#define NVME_ADMIN_CRIOCQ_CMD 0x05 +#define NVME_ADMIN_IDENTIFY_CMD 0x06 +#define NVME_ADMIN_ABORT_CMD 0x08 +#define NVME_ADMIN_SET_FEATURES_CMD 0x09 +#define NVME_ADMIN_GET_FEATURES_CMD 0x0A +#define NVME_ADMIN_ASYNC_EVENT_REQUEST_CMD 0x0C +#define NVME_ADMIN_NAMESACE_MANAGEMENT_CMD 0x0D +#define NVME_ADMIN_FW_COMMIT_CMD 0x10 +#define NVME_ADMIN_FW_IAMGE_DOWNLOAD_CMD 0x11 +#define NVME_ADMIN_NAMESACE_ATTACHMENT_CMD 0x15 +#define NVME_ADMIN_FORMAT_NVM_CMD 0x80 +#define NVME_ADMIN_SECURITY_SEND_CMD 0x81 +#define NVME_ADMIN_SECURITY_RECEIVE_CMD 0x82 + +#define NVME_IO_FLUSH_OPC 0 +#define NVME_IO_WRITE_OPC 1 +#define NVME_IO_READ_OPC 2 + +typedef enum { + DeleteIOSubmissionQueueOpcode = NVME_ADMIN_DEIOSQ_CMD, + CreateIOSubmissionQueueOpcode = NVME_ADMIN_CRIOSQ_CMD, + GetLogPageOpcode = NVME_ADMIN_GET_LOG_PAGE_CMD, + DeleteIOCompletionQueueOpcode = NVME_ADMIN_DEIOCQ_CMD, + CreateIOCompletionQueueOpcode = NVME_ADMIN_CRIOCQ_CMD, + IdentifyOpcode = NVME_ADMIN_IDENTIFY_CMD, + AbortOpcode = NVME_ADMIN_ABORT_CMD, + SetFeaturesOpcode = NVME_ADMIN_SET_FEATURES_CMD, + GetFeaturesOpcode = NVME_ADMIN_GET_FEATURES_CMD, + AsyncEventRequestOpcode = NVME_ADMIN_ASYNC_EVENT_REQUEST_CMD, + NamespaceManagementOpcode = NVME_ADMIN_NAMESACE_MANAGEMENT_CMD, + FirmwareCommitOpcode = NVME_ADMIN_FW_COMMIT_CMD, + FirmwareImageDownloadOpcode = NVME_ADMIN_FW_IAMGE_DOWNLOAD_CMD, + NamespaceAttachmentOpcode = NVME_ADMIN_NAMESACE_ATTACHMENT_CMD, + FormatNvmOpcode = NVME_ADMIN_FORMAT_NVM_CMD, + SecuritySendOpcode = NVME_ADMIN_SECURITY_SEND_CMD, + SecurityReceiveOpcode = NVME_ADMIN_SECURITY_RECEIVE_CMD +} NVME_ADMIN_COMMAND_OPCODE; + +// +// Controller or Namespace Structure (CNS) field +// (ref. spec. v1.1 figure 82). +// +typedef enum { +IdentifyNamespaceCns = 0x0, +IdentifyControllerCns = 0x1, +IdentifyActiveNsListCns = 0x2 +} NVME_ADMIN_IDENTIFY_CNS; + +// +// Commit Action +// (ref. spec. 1.1 figure 60). +// +typedef enum { + ActivateActionReplace = 0x0, + ActivateActionReplaceActivate = 0x1, + ActivateActionActivate = 0x2 +} NVME_FW_ACTIVATE_ACTION; + +// +// Firmware Slot +// (ref. spec. 1.1 Figure 60). +// +typedef enum { + FirmwareSlotCtrlChooses = 0x0, + FirmwareSlot1 = 0x1, + FirmwareSlot2 = 0x2, + FirmwareSlot3 = 0x3, + FirmwareSlot4 = 0x4, + FirmwareSlot5 = 0x5, + FirmwareSlot6 = 0x6, + FirmwareSlot7 = 0x7 +} NVME_FW_ACTIVATE_SLOT; + +// +// Get Log Page ? Log Page Identifiers +// (ref. spec. v1.1 Figure 73). +// +typedef enum { + ErrorInfoLogID = LID_ERROR_INFO, + SmartHealthInfoLogID = LID_SMART_INFO, + FirmwareSlotInfoLogID = LID_FW_SLOT_INFO +} NVME_LOG_ID; + +// +// Get Log Page ? Firmware Slot Information Log +// (ref. spec. v1.1 Figure 77). +// +typedef struct { + // + // Indicates the firmware slot from which the actively running firmware revision was loaded. + // + UINT8 ActivelyRunningFwSlot:3; + UINT8 :1; + // + // Indicates the firmware slot that is going to be activated at the next controller reset. If this field is 0h, then the controller does not indicate the firmware slot that is going to be activated at the next controller reset. + // + UINT8 NextActiveFwSlot:3; + UINT8 :1; +} NVME_ACTIVE_FW_INFO; + +// +// Get Log Page ? Firmware Slot Information Log +// (ref. spec. v1.1 Figure 77). +// +typedef struct { + // + // Specifies information about the active firmware revision. + //s + NVME_ACTIVE_FW_INFO ActiveFwInfo; + UINT8 Reserved1[7]; + // + // Contains the revision of the firmware downloaded to firmware slot 1/7. If no valid firmware revision is present or if this slot is unsupported, all zeros shall be returned. + // + CHAR8 FwRevisionSlot[7][8]; + UINT8 Reserved2[448]; +} NVME_FW_SLOT_INFO_LOG; + +// +// SMART / Health Information (Log Identifier 02h) +// (ref. spec. v1.1 5.10.1.2) +// +typedef struct { + // + // This field indicates critical warnings for the state of the controller. + // + UINT8 CriticalWarningAvailableSpare:1; + UINT8 CriticalWarningTemperature:1; + UINT8 CriticalWarningReliability:1; + UINT8 CriticalWarningMediaReadOnly:1; + UINT8 CriticalWarningVolatileBackup:1; + UINT8 CriticalWarningReserved:3; + // + // Contains a value corresponding to a temperature in degrees Kelvin that represents the current composite temperature of the controller and namespace(s) associated with that controller. The manner in which this value is computed is implementation specific and may not represent the actual temperature of any physical point in the NVM subsystem. + // + UINT16 CompositeTemp; + // + // Contains a normalized percentage (0 to 100%) of the remaining spare capacity available. + // + UINT8 AvailableSpare; + // + // When the Available Spare falls below the threshold indicated in this field, an asynchronous event completion may occur. The value is indicated as a normalized percentage (0 to 100%). + // + UINT8 AvailableSpareThreshold; + // + // Contains a vendor specific estimate of the percentage of NVM subsystem life used based on the actual usage and the manufacturer?s prediction of NVM life. A value of 100 indicates that the estimated endurance of the NVM in the NVM subsystem has been consumed, but may not indicate an NVM subsystem failure. The value is allowed to exceed 100. Percentages greater than 254 shall be represented as 255. This value shall be updated once per power-on hour (when the controller is not in a sleep state). + // + UINT8 PercentageUsed; + UINT8 Reserved1[26]; + // + // Contains the number of 512 byte data units the host has read from the controller; this value does not include metadata. + // + UINT8 DataUnitsRead[16]; + // + // Contains the number of 512 byte data units the host has written to the controller; this value does not include metadata. + // + UINT8 DataUnitsWritten[16]; + // + // Contains the number of read commands completed by the controller. + // + UINT8 HostReadCommands[16]; + // + // Contains the number of write commands completed by the controller. + // + UINT8 HostWriteCommands[16]; + // + // Contains the amount of time the controller is busy with I/O commands. This value is reported in minutes. + // + UINT8 ControllerBusyTime[16]; + // + // Contains the number of power cycles. + // + UINT8 PowerCycles[16]; + // + // Contains the number of power-on hours. + // + UINT8 PowerOnHours[16]; + // + // Contains the number of unsafe shutdowns. + // + UINT8 UnsafeShutdowns[16]; + // + // Contains the number of occurrences where the controller detected an unrecovered data integrity error. + // + UINT8 MediaAndDataIntegrityErrors[16]; + // + // Contains the number of Error Information log entries over the life of the controller. + // + UINT8 NumberErrorInformationLogEntries[16]; + // + // Contains the amount of time in minutes that the controller is operational and the Composite Temperature is greater than or equal to the Warning Composite Temperature Threshold (WCTEMP) field and less than the Critical Composite Temperature Threshold (CCTEMP) field in the Identify Controller data structure in Figure 90. + // + UINT32 WarningCompositeTemperatureTime; + // + // Contains the amount of time in minutes that the controller is operational and the Composite Temperature is greater the Critical Composite Temperature Threshold (CCTEMP) field in the Identify Controller data structure in Figure 90. + // + UINT32 CriticalCompositeTemperatureTime; + // + // Contains the current temperature in degrees Kelvin reported by the temperature sensor. An implementation that does not implement the temperature sensor reports a temperature of zero degrees Kelvin. + // + UINT16 TemperatureSensor[8]; + UINT8 Reserved2[296]; +} NVME_SMART_HEALTH_INFO_LOG; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pal.h new file mode 100644 index 0000000..4a76f26 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pal.h @@ -0,0 +1,3302 @@ +/** @file + Main PAL API's defined in Intel Itanium Architecture Software Developer's Manual. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PAL_API_H__ +#define __PAL_API_H__ + +#define PAL_SUCCESS 0x0 + +/// +/// CacheType of PAL_CACHE_FLUSH. +/// +#define PAL_CACHE_FLUSH_INSTRUCTION_ALL 1 +#define PAL_CACHE_FLUSH_DATA_ALL 2 +#define PAL_CACHE_FLUSH_ALL 3 +#define PAL_CACHE_FLUSH_SYNC_TO_DATA 4 + + +/// +/// Bitmask of Opearation of PAL_CACHE_FLUSH. +/// +#define PAL_CACHE_FLUSH_INVALIDATE_LINES BIT0 +#define PAL_CACHE_FLUSH_NO_INVALIDATE_LINES 0 +#define PAL_CACHE_FLUSH_POLL_INTERRUPT BIT1 +#define PAL_CACHE_FLUSH_NO_INTERRUPT 0 + +/** + PAL Procedure - PAL_CACHE_FLUSH. + + Flush the instruction or data caches. It is required by Itanium processors. + The PAL procedure supports the Static Registers calling + convention. It could be called at virtual mode and physical + mode. + + @param Index Index of PAL_CACHE_FLUSH within the + list of PAL procedures. + @param CacheType Unsigned 64-bit integer indicating + which cache to flush. + @param Operation Formatted bit vector indicating the + operation of this call. + @param ProgressIndicator Unsigned 64-bit integer specifying + the starting position of the flush + operation. + + @retval 2 Call completed without error, but a PMI + was taken during the execution of this + procedure. + @retval 1 Call has not completed flushing due to + a pending interrupt. + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error + + @return R9 Unsigned 64-bit integer specifying the vector + number of the pending interrupt. + @return R10 Unsigned 64-bit integer specifying the + starting position of the flush operation. + @return R11 Unsigned 64-bit integer specifying the vector + number of the pending interrupt. + +**/ +#define PAL_CACHE_FLUSH 1 + + +/// +/// Attributes of PAL_CACHE_CONFIG_INFO1 +/// +#define PAL_CACHE_ATTR_WT 0 +#define PAL_CACHE_ATTR_WB 1 + +/// +/// PAL_CACHE_CONFIG_INFO1.StoreHint +/// +#define PAL_CACHE_STORE_TEMPORAL 0 +#define PAL_CACHE_STORE_NONE_TEMPORAL 3 + +/// +/// PAL_CACHE_CONFIG_INFO1.StoreHint +/// +#define PAL_CACHE_STORE_TEMPORAL_LVL_1 0 +#define PAL_CACHE_STORE_NONE_TEMPORAL_LVL_ALL 3 + +/// +/// PAL_CACHE_CONFIG_INFO1.StoreHint +/// +#define PAL_CACHE_LOAD_TEMPORAL_LVL_1 0 +#define PAL_CACHE_LOAD_NONE_TEMPORAL_LVL_1 1 +#define PAL_CACHE_LOAD_NONE_TEMPORAL_LVL_ALL 3 + +/// +/// Detail the characteristics of a given processor controlled +/// cache in the cache hierarchy. +/// +typedef struct { + UINT64 IsUnified : 1; + UINT64 Attributes : 2; + UINT64 Associativity:8; + UINT64 LineSize:8; + UINT64 Stride:8; + UINT64 StoreLatency:8; + UINT64 StoreHint:8; + UINT64 LoadHint:8; +} PAL_CACHE_INFO_RETURN1; + +/// +/// Detail the characteristics of a given processor controlled +/// cache in the cache hierarchy. +/// +typedef struct { + UINT64 CacheSize:32; + UINT64 AliasBoundary:8; + UINT64 TagLsBits:8; + UINT64 TagMsBits:8; +} PAL_CACHE_INFO_RETURN2; + +/** + PAL Procedure - PAL_CACHE_INFO. + + Return detailed instruction or data cache information. It is + required by Itanium processors. The PAL procedure supports the Static + Registers calling convention. It could be called at virtual + mode and physical mode. + + @param Index Index of PAL_CACHE_INFO within the list of + PAL procedures. + @param CacheLevel Unsigned 64-bit integer specifying the + level in the cache hierarchy for which + information is requested. This value must + be between 0 and one less than the value + returned in the cache_levels return value + from PAL_CACHE_SUMMARY. + @param CacheType Unsigned 64-bit integer with a value of 1 + for instruction cache and 2 for data or + unified cache. All other values are + reserved. + @param Reserved Should be 0. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error + + @return R9 Detail the characteristics of a given + processor controlled cache in the cache + hierarchy. See PAL_CACHE_INFO_RETURN1. + @return R10 Detail the characteristics of a given + processor controlled cache in the cache + hierarchy. See PAL_CACHE_INFO_RETURN2. + @return R11 Reserved with 0. + +**/ +#define PAL_CACHE_INFO 2 + + + +/// +/// Level of PAL_CACHE_INIT. +/// +#define PAL_CACHE_INIT_ALL 0xffffffffffffffffULL + +/// +/// CacheType +/// +#define PAL_CACHE_INIT_TYPE_INSTRUCTION 0x1 +#define PAL_CACHE_INIT_TYPE_DATA 0x2 +#define PAL_CACHE_INIT_TYPE_INSTRUCTION_AND_DATA 0x3 + +/// +/// Restrict of PAL_CACHE_INIT. +/// +#define PAL_CACHE_INIT_NO_RESTRICT 0 +#define PAL_CACHE_INIT_RESTRICTED 1 + +/** + PAL Procedure - PAL_CACHE_INIT. + + Initialize the instruction or data caches. It is required by + Itanium processors. The PAL procedure supports the Static Registers calling + convention. It could be called at physical mode. + + @param Index Index of PAL_CACHE_INIT within the list of PAL + procedures. + @param Level Unsigned 64-bit integer containing the level of + cache to initialize. If the cache level can be + initialized independently, only that level will + be initialized. Otherwise + implementation-dependent side-effects will + occur. + @param CacheType Unsigned 64-bit integer with a value of 1 to + initialize the instruction cache, 2 to + initialize the data cache, or 3 to + initialize both. All other values are + reserved. + @param Restrict Unsigned 64-bit integer with a value of 0 or + 1. All other values are reserved. If + restrict is 1 and initializing the specified + level and cache_type of the cache would + cause side-effects, PAL_CACHE_INIT will + return -4 instead of initializing the cache. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -4 Call could not initialize the specified + level and cache_type of the cache without + side-effects and restrict was 1. + +**/ +#define PAL_CACHE_INIT 3 + + +/// +/// PAL_CACHE_PROTECTION.Method. +/// +#define PAL_CACHE_PROTECTION_NONE_PROTECT 0 +#define PAL_CACHE_PROTECTION_ODD_PROTECT 1 +#define PAL_CACHE_PROTECTION_EVEN_PROTECT 2 +#define PAL_CACHE_PROTECTION_ECC_PROTECT 3 + + + +/// +/// PAL_CACHE_PROTECTION.TagOrData. +/// +#define PAL_CACHE_PROTECTION_PROTECT_DATA 0 +#define PAL_CACHE_PROTECTION_PROTECT_TAG 1 +#define PAL_CACHE_PROTECTION_PROTECT_TAG_ANDTHEN_DATA 2 +#define PAL_CACHE_PROTECTION_PROTECT_DATA_ANDTHEN_TAG 3 + +/// +/// 32-bit protection information structures. +/// +typedef struct { + UINT32 DataBits:8; + UINT32 TagProtLsb:6; + UINT32 TagProtMsb:6; + UINT32 ProtBits:6; + UINT32 Method:4; + UINT32 TagOrData:2; +} PAL_CACHE_PROTECTION; + +/** + PAL Procedure - PAL_CACHE_PROT_INFO. + + Return instruction or data cache protection information. It is + required by Itanium processors. The PAL procedure supports the Static + Registers calling convention. It could be called at physical + mode and Virtual mode. + + @param Index Index of PAL_CACHE_PROT_INFO within the list of + PAL procedures. + @param CacheLevel Unsigned 64-bit integer specifying the level + in the cache hierarchy for which information + is requested. This value must be between 0 + and one less than the value returned in the + cache_levels return value from + PAL_CACHE_SUMMARY. + @param CacheType Unsigned 64-bit integer with a value of 1 + for instruction cache and 2 for data or + unified cache. All other values are + reserved. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Detail the characteristics of a given + processor controlled cache in the cache + hierarchy. See PAL_CACHE_PROTECTION[0..1]. + @return R10 Detail the characteristics of a given + processor controlled cache in the cache + hierarchy. See PAL_CACHE_PROTECTION[2..3]. + @return R11 Detail the characteristics of a given + processor controlled cache in the cache + hierarchy. See PAL_CACHE_PROTECTION[4..5]. + +**/ +#define PAL_CACHE_PROT_INFO 38 + +typedef struct { + UINT64 ThreadId : 16; ///< The thread identifier of the logical + ///< processor for which information is being + ///< returned. This value will be unique on a per core basis. + UINT64 Reserved1: 16; + UINT64 CoreId: 16; ///< The core identifier of the logical processor + ///< for which information is being returned. + ///< This value will be unique on a per physical + ///< processor package basis. + UINT64 Reserved2: 16; +} PAL_PCOC_N_CACHE_INFO1; + + +typedef struct { + UINT64 LogicalAddress : 16; ///< Logical address: geographical address + ///< of the logical processor for which + ///< information is being returned. This is + ///< the same value that is returned by the + ///< PAL_FIXED_ADDR procedure when it is + ///< called on the logical processor. + UINT64 Reserved1: 16; + UINT64 Reserved2: 32; +} PAL_PCOC_N_CACHE_INFO2; + +/** + PAL Procedure - PAL_CACHE_SHARED_INFO. + + Returns information on which logical processors share caches. + It is optional. The PAL procedure supports the Static + Registers calling convention. It could be called at physical + mode and Virtual mode. + + @param Index Index of PAL_CACHE_SHARED_INFO within the list + of PAL procedures. + @param CacheLevel Unsigned 64-bit integer specifying the + level in the cache hierarchy for which + information is requested. This value must + be between 0 and one less than the value + returned in the cache_levels return value + from PAL_CACHE_SUMMARY. + @param CacheType Unsigned 64-bit integer with a value of 1 + for instruction cache and 2 for data or + unified cache. All other values are + reserved. + @param ProcNumber Unsigned 64-bit integer that specifies for + which logical processor information is + being requested. This input argument must + be zero for the first call to this + procedure and can be a maximum value of + one less than the number of logical + processors sharing this cache, which is + returned by the num_shared return value. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned integer that returns the number of + logical processors that share the processor + cache level and type, for which information was + requested. + @return R10 The format of PAL_PCOC_N_CACHE_INFO1. + @return R11 The format of PAL_PCOC_N_CACHE_INFO2. + +**/ +#define PAL_CACHE_SHARED_INFO 43 + + +/** + PAL Procedure - PAL_CACHE_SUMMARY. + + Return a summary of the cache hierarchy. It is required by + Itanium processors. The PAL procedure supports the Static Registers calling + convention. It could be called at physical mode and Virtual + mode. + + @param Index Index of PAL_CACHE_SUMMARY within the list of + PAL procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 CacheLevels Unsigned 64-bit integer denoting the + number of levels of cache + implemented by the processor. + Strictly, this is the number of + levels for which the cache + controller is integrated into the + processor (the cache SRAMs may be + external to the processor). + @return R10 UniqueCaches Unsigned 64-bit integer denoting the + number of unique caches implemented + by the processor. This has a maximum + of 2*cache_levels, but may be less + if any of the levels in the cache + hierarchy are unified caches or do + not have both instruction and data + caches. + +**/ +#define PAL_CACHE_SUMMARY 4 + + +// +// Virtual Memory Attributes implemented by processor. +// +#define PAL_MEMORY_ATTR_WB 0 +#define PAL_MEMORY_ATTR_WC 6 +#define PAL_MEMORY_ATTR_UC 4 +#define PAL_MEMORY_ATTR_UCE 5 +#define PAL_MEMORY_ATTR_NATPAGE 7 + +/** + PAL Procedure - PAL_MEM_ATTRIB. + + Return a list of supported memory attributes.. It is required + by Itanium processors. The PAL procedure supports the Static Registers calling + convention. It could be called at physical mode and Virtual + mode. + + @param Index Index of PAL_MEM_ATTRIB within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Attributes 8-bit vector of memory attributes + implemented by processor. See Virtual + Memory Attributes above. + +**/ + +#define PAL_MEM_ATTRIB 5 + +/** + PAL Procedure - PAL_PREFETCH_VISIBILITY. + + Used in architected sequence to transition pages from a + cacheable, speculative attribute to an uncacheable attribute. + It is required by Itanium processors. The PAL procedure supports the Static + Registers calling convention. It could be called at physical + mode and Virtual mode. + + @param Index Index of PAL_PREFETCH_VISIBILITY within the list + of PAL procedures. + @param TransitionType Unsigned integer specifying the type + of memory attribute transition that is + being performed. + + @retval 1 Call completed without error; this + call is not necessary on remote + processors. + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_PREFETCH_VISIBILITY 41 + +/** + PAL Procedure - PAL_PTCE_INFO. + + Return information needed for ptc.e instruction to purge + entire TC. It is required by Itanium processors. The PAL procedure supports + the Static Registers calling convention. It could be called at + physical mode and Virtual mode. + + @param Index Index of PAL_PTCE_INFO within the list + of PAL procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned 64-bit integer denoting the beginning + address to be used by the first PTCE instruction + in the purge loop. + @return R10 Two unsigned 32-bit integers denoting the loop + counts of the outer (loop 1) and inner (loop 2) + purge loops. count1 (loop 1) is contained in bits + 63:32 of the parameter, and count2 (loop 2) is + contained in bits 31:0 of the parameter. + @return R11 Two unsigned 32-bit integers denoting the loop + strides of the outer (loop 1) and inner (loop 2) + purge loops. stride1 (loop 1) is contained in bits + 63:32 of the parameter, and stride2 (loop 2) is + contained in bits 31:0 of the parameter. + +**/ +#define PAL_PTCE_INFO 6 + +typedef struct { + UINT64 NumberSets:8; ///< Unsigned 8-bit integer denoting the number + ///< of hash sets for the specified level + ///< (1=fully associative) + UINT64 NumberWays:8; ///< Unsigned 8-bit integer denoting the + ///< associativity of the specified level + ///< (1=direct). + UINT64 NumberEntries:16; ///< Unsigned 16-bit integer denoting the + ///< number of entries in the specified TC. + UINT64 PageSizeIsOptimized:1; ///< Flag denoting whether the + ///< specified level is optimized for + ///< the region's preferred page size + ///< (1=optimized) tc_pages indicates + ///< which page sizes are usable by + ///< this translation cache. + UINT64 TcIsUnified:1; ///< Flag denoting whether the specified TC is + ///< unified (1=unified). + UINT64 EntriesReduction:1; ///< Flag denoting whether installed + ///< translation registers will reduce + ///< the number of entries within the + ///< specified TC. +} PAL_TC_INFO; + +/** + PAL Procedure - PAL_VM_INFO. + + Return detailed information about virtual memory features + supported in the processor. It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and Virtual mode. + + @param Index Index of PAL_VM_INFO within the list + of PAL procedures. + @param TcLevel Unsigned 64-bit integer specifying the level + in the TLB hierarchy for which information is + required. This value must be between 0 and one + less than the value returned in the + vm_info_1.num_tc_levels return value from + PAL_VM_SUMMARY. + @param TcType Unsigned 64-bit integer with a value of 1 for + instruction translation cache and 2 for data + or unified translation cache. All other values + are reserved. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 8-byte formatted value returning information + about the specified TC. See PAL_TC_INFO above. + @return R10 64-bit vector containing a bit for each page + size supported in the specified TC, where bit + position n indicates a page size of 2**n. + +**/ +#define PAL_VM_INFO 7 + + +/** + PAL Procedure - PAL_VM_PAGE_SIZE. + + Return virtual memory TC and hardware walker page sizes + supported in the processor. It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and Virtual mode. + + @param Index Index of PAL_VM_PAGE_SIZE within the list + of PAL procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 64-bit vector containing a bit for each + architected page size that is supported for + TLB insertions and region registers. + @return R10 64-bit vector containing a bit for each + architected page size supported for TLB purge + operations. + +**/ +#define PAL_VM_PAGE_SIZE 34 + +typedef struct { + UINT64 WalkerPresent:1; ///< 1-bit flag indicating whether a hardware + ///< TLB walker is implemented (1 = walker + ///< present). + UINT64 WidthOfPhysicalAddress: 7; ///< Unsigned 7-bit integer + ///< denoting the number of bits of + ///< physical address implemented. + UINT64 WidthOfKey:8; ///< Unsigned 8-bit integer denoting the number + ///< of bits mplemented in the PKR.key field. + UINT64 MaxPkrIndex:8; ///< Unsigned 8-bit integer denoting the + ///< maximum PKR index (number of PKRs-1). + UINT64 HashTagId:8; ///< Unsigned 8-bit integer which uniquely + ///< identifies the processor hash and tag + ///< algorithm. + UINT64 MaxDtrIndex:8; ///< Unsigned 8 bit integer denoting the + ///< maximum data translation register index + ///< (number of dtr entries - 1). + UINT64 MaxItrIndex:8; ///< Unsigned 8 bit integer denoting the + ///< maximum instruction translation register + ///< index (number of itr entries - 1). + UINT64 NumberOfUniqueTc:8; ///< Unsigned 8-bit integer denoting the + ///< number of unique TCs implemented. + ///< This is a maximum of + ///< 2*num_tc_levels. + UINT64 NumberOfTcLevels:8; ///< Unsigned 8-bit integer denoting the + ///< number of TC levels. +} PAL_VM_INFO1; + +typedef struct { + UINT64 WidthOfVirtualAddress:8; ///< Unsigned 8-bit integer denoting + ///< is the total number of virtual + ///< address bits - 1. + UINT64 WidthOfRid:8; ///< Unsigned 8-bit integer denoting the number + ///< of bits implemented in the RR.rid field. + UINT64 MaxPurgedTlbs:16; ///< Unsigned 16 bit integer denoting the + ///< maximum number of concurrent outstanding + ///< TLB purges allowed by the processor. A + ///< value of 0 indicates one outstanding + ///< purge allowed. A value of 216-1 + ///< indicates no limit on outstanding + ///< purges. All other values indicate the + ///< actual number of concurrent outstanding + ///< purges allowed. + UINT64 Reserved:32; +} PAL_VM_INFO2; + +/** + PAL Procedure - PAL_VM_SUMMARY. + + Return summary information about virtual memory features + supported in the processor. It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and Virtual mode. + + @param Index Index of PAL_VM_SUMMARY within the list + of PAL procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 8-byte formatted value returning global virtual + memory information. See PAL_VM_INFO1 above. + @return R10 8-byte formatted value returning global virtual + memory information. See PAL_VM_INFO2 above. + +**/ +#define PAL_VM_SUMMARY 8 + + +// +// Bit mask of TR_valid flag. +// +#define PAL_TR_ACCESS_RIGHT_IS_VALID BIT0 +#define PAL_TR_PRIVILEGE_LEVEL_IS_VALID BIT1 +#define PAL_TR_DIRTY_IS_VALID BIT2 +#define PAL_TR_MEMORY_ATTR_IS_VALID BIT3 + + +/** + PAL Procedure - PAL_VM_TR_READ. + + Read contents of a translation register. It is required by + Itanium processors. The PAL procedure supports the Stacked Register calling + convention. It could be called at physical mode. + + @param Index Index of PAL_VM_TR_READ within the list + of PAL procedures. + @param RegNumber Unsigned 64-bit number denoting which TR to + read. + @param TrType Unsigned 64-bit number denoting whether to + read an ITR (0) or DTR (1). All other values + are reserved. + @param TrBuffer 64-bit pointer to the 32-byte memory buffer in + which translation data is returned. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Formatted bit vector denoting which fields are + valid. See TR_valid above. + +**/ +#define PAL_VM_TR_READ 261 + + + + +// +// Bit Mask of Processor Bus Fesatures . +// + +/** + + When 0, bus data errors are detected and single bit errors are + corrected. When 1, no error detection or correction is done. + +**/ +#define PAL_BUS_DISABLE_DATA_ERROR_SIGNALLING BIT63 + + +/** + + When 0, bus address errors are signalled on the bus. When 1, + no bus errors are signalled on the bus. If Disable Bus Address + Error Checking is 1, this bit is ignored. + +**/ +#define PAL_BUS_DISABLE_ADDRESS_ERROR_SIGNALLING BIT62 + + + + +/** + + When 0, bus errors are detected, single bit errors are + corrected., and a CMCI or MCA is generated internally to the + processor. When 1, no bus address errors are detected or + corrected. + +**/ +#define PAL_BUS_DISABLE_ADDRESS_ERROR_CHECK BIT61 + + +/** + + When 0, bus protocol errors (BINIT#) are signaled by the + processor on the bus. When 1, bus protocol errors (BINIT#) are + not signaled on the bus. If Disable Bus Initialization Event + Checking is 1, this bit is ignored. + +**/ +#define PAL_BUS_DISABLE_INITIALIZATION_EVENT_SIGNALLING BIT60 + + +/** + + When 0, bus protocol errors (BINIT#) are detected and sampled + and an MCA is generated internally to the processor. When 1, + the processor will ignore bus protocol error conditions + (BINIT#). + +**/ +#define PAL_BUS_DISABLE_INITIALIZATION_EVENT_CHECK BIT59 + + + +/** + + When 0, BERR# is signalled if a bus error is detected. When 1, + bus errors are not signalled on the bus. + +**/ +#define PAL_BUS_DISABLE_ERROR_SIGNALLING BIT58 + + + + +/** + + When 0, BERR# is signalled when internal processor requestor + initiated bus errors are detected. When 1, internal requester + bus errors are not signalled on the bus. + +**/ +#define PAL_BUS_DISABLE__INTERNAL_ERROR_SIGNALLING BIT57 + + +/** + + When 0, the processor takes an MCA if BERR# is asserted. When + 1, the processor ignores the BERR# signal. + +**/ +#define PAL_BUS_DISABLE_ERROR_CHECK BIT56 + + +/** + + When 0, the processor asserts BINIT# if it detects a parity + error on the signals which identify the transactions to which + this is a response. When 1, the processor ignores parity on + these signals. + +**/ +#define PAL_BUS_DISABLE_RSP_ERROR_CHECK BIT55 + + +/** + + When 0, the in-order transaction queue is limited only by the + number of hardware entries. When 1, the processor's in-order + transactions queue is limited to one entry. + +**/ +#define PAL_BUS_DISABLE_TRANSACTION_QUEUE BIT54 + +/** + + Enable a bus cache line replacement transaction when a cache + line in the exclusive state is replaced from the highest level + processor cache and is not present in the lower level processor + caches. When 0, no bus cache line replacement transaction will + be seen on the bus. When 1, bus cache line replacement + transactions will be seen on the bus when the above condition is + detected. + +**/ +#define PAL_BUS_ENABLE_EXCLUSIVE_CACHE_LINE_REPLACEMENT BIT53 + + +/** + + Enable a bus cache line replacement transaction when a cache + line in the shared or exclusive state is replaced from the + highest level processor cache and is not present in the lower + level processor caches. + When 0, no bus cache line replacement transaction will be seen + on the bus. When 1, bus cache line replacement transactions + will be seen on the bus when the above condition is detected. + +**/ +#define PAL_BUS_ENABLE_SHARED_CACHE_LINE_REPLACEMENT BIT52 + + + +/** + + When 0, the data bus is configured at the 2x data transfer + rate.When 1, the data bus is configured at the 1x data + transfer rate, 30 Opt. Req. Disable Bus Lock Mask. When 0, the + processor executes locked transactions atomically. When 1, the + processor masks the bus lock signal and executes locked + transactions as a non-atomic series of transactions. + +**/ +#define PAL_BUS_ENABLE_HALF_TRANSFER BIT30 + +/** + + When 0, the processor will deassert bus request when finished + with each transaction. When 1, the processor will continue to + assert bus request after it has finished, if it was the last + agent to own the bus and if there are no other pending + requests. + +**/ +#define PAL_BUS_REQUEST_BUS_PARKING BIT29 + + +/** + PAL Procedure - PAL_BUS_GET_FEATURES. + + Return configurable processor bus interface features and their + current settings. It is required by Itanium processors. The PAL procedure + supports the Stacked Register calling convention. It could be + called at physical mode. + + @param Index Index of PAL_BUS_GET_FEATURES within the list + of PAL procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 64-bit vector of features implemented. + (1=implemented, 0=not implemented) + @return R10 64-bit vector of current feature settings. + @return R11 64-bit vector of features controllable by + software. (1=controllable, 0= not controllable) + +**/ +#define PAL_BUS_GET_FEATURES 9 + +/** + PAL Procedure - PAL_BUS_SET_FEATURES. + + Enable or disable configurable features in processor bus + interface. It is required by Itanium processors. The PAL procedure + supports the Static Registers calling convention. It could be + called at physical mode. + + @param Index Index of PAL_BUS_SET_FEATURES within the list + of PAL procedures. + @param FeatureSelect 64-bit vector denoting desired state of + each feature (1=select, 0=non-select). + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_BUS_SET_FEATURES 10 + + +/** + PAL Procedure - PAL_DEBUG_INFO. + + Return the number of instruction and data breakpoint + registers. It is required by Itanium processors. The + PAL procedure supports the Static Registers calling + convention. It could be called at physical mode and virtual + mode. + + @param Index Index of PAL_DEBUG_INFO within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned 64-bit integer denoting the number of + pairs of instruction debug registers implemented + by the processor. + @return R10 Unsigned 64-bit integer denoting the number of + pairs of data debug registers implemented by the + processor. + +**/ +#define PAL_DEBUG_INFO 11 + +/** + PAL Procedure - PAL_FIXED_ADDR. + + Return the fixed component of a processor's directed address. + It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and virtual mode. + + @param Index Index of PAL_FIXED_ADDR within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Fixed geographical address of this processor. + +**/ +#define PAL_FIXED_ADDR 12 + +/** + PAL Procedure - PAL_FREQ_BASE. + + Return the frequency of the output clock for use by the + platform, if generated by the processor. It is optinal. The + PAL procedure supports the Static Registers calling + convention. It could be called at physical mode and virtual + mode. + + @param Index Index of PAL_FREQ_BASE within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Base frequency of the platform if generated by the + processor chip. + +**/ +#define PAL_FREQ_BASE 13 + + +/** + PAL Procedure - PAL_FREQ_RATIOS. + + Return ratio of processor, bus, and interval time counter to + processor input clock or output clock for platform use, if + generated by the processor. It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and virtual mode. + + @param Index Index of PAL_FREQ_RATIOS within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Ratio of the processor frequency to the input + clock of the processor, if the platform clock is + generated externally or to the output clock to the + platform, if the platform clock is generated by + the processor. + @return R10 Ratio of the bus frequency to the input clock of + the processor, if the platform clock is generated + externally or to the output clock to the platform, + if the platform clock is generated by the + processor. + @return R11 Ratio of the interval timer counter rate to input + clock of the processor, if the platform clock is + generated externally or to the output clock to the + platform, if the platform clock is generated by + the processor. + +**/ +#define PAL_FREQ_RATIOS 14 + +typedef struct { + UINT64 NumberOfLogicalProcessors:16; ///< Total number of logical + ///< processors on this physical + ///< processor package that are + ///< enabled. + UINT64 ThreadsPerCore:8; ///< Number of threads per core. + UINT64 Reserved1:8; + UINT64 CoresPerProcessor:8; ///< Total number of cores on this + ///< physical processor package. + UINT64 Reserved2:8; + UINT64 PhysicalProcessorPackageId:8; ///< Physical processor package + ///< identifier which was + ///< assigned at reset by the + ///< platform or bus + ///< controller. This value may + ///< or may not be unique + ///< across the entire platform + ///< since it depends on the + ///< platform vendor's policy. + UINT64 Reserved3:8; +} PAL_LOGICAL_PROCESSPR_OVERVIEW; + +typedef struct { + UINT64 ThreadId:16; ///< The thread identifier of the logical + ///< processor for which information is being + ///< returned. This value will be unique on a per + ///< core basis. + UINT64 Reserved1:16; + UINT64 CoreId:16; ///< The core identifier of the logical processor + ///< for which information is being returned. + ///< This value will be unique on a per physical + ///< processor package basis. + UINT64 Reserved2:16; +} PAL_LOGICAL_PROCESSORN_INFO1; + +typedef struct { + UINT64 LogicalAddress:16; ///< Geographical address of the logical + ///< processor for which information is being + ///< returned. This is the same value that is + ///< returned by the PAL_FIXED_ADDR procedure + ///< when it is called on the logical processor. + UINT64 Reserved:48; +} PAL_LOGICAL_PROCESSORN_INFO2; + +/** + PAL Procedure - PAL_LOGICAL_TO_PHYSICAL. + + Return information on which logical processors map to a + physical processor die. It is optinal. The PAL procedure + supports the Static Registers calling convention. It could be + called at physical mode and virtual mode. + + @param Index Index of PAL_LOGICAL_TO_PHYSICAL within the list of PAL + procedures. + @param ProcessorNumber Signed 64-bit integer that specifies + for which logical processor + information is being requested. When + this input argument is -1, information + is returned about the logical + processor on which the procedure call + is made. This input argument must be + in the range of 1 up to one less than + the number of logical processors + returned by num_log in the + log_overview return value. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 The format of PAL_LOGICAL_PROCESSPR_OVERVIEW. + @return R10 The format of PAL_LOGICAL_PROCESSORN_INFO1. + @return R11 The format of PAL_LOGICAL_PROCESSORN_INFO2. + +**/ +#define PAL_LOGICAL_TO_PHYSICAL 42 + +typedef struct { + UINT64 NumberOfPmcPairs:8; ///< Unsigned 8-bit number defining the + ///< number of generic PMC/PMD pairs. + UINT64 WidthOfCounter:8; ///< Unsigned 8-bit number in the range + ///< 0:60 defining the number of + ///< implemented counter bits. + UINT64 TypeOfCycleCounting:8; ///< Unsigned 8-bit number defining the + ///< event type for counting processor cycles. + UINT64 TypeOfRetiredInstructionBundle:8; ///< Retired Unsigned 8-bit + ///< number defining the + ///< event type for retired + ///< instruction bundles. + UINT64 Reserved:32; +} PAL_PERFORMANCE_INFO; + +/** + PAL Procedure - PAL_PERF_MON_INFO. + + Return the number and type of performance monitors. It is + required by Itanium processors. The PAL procedure supports the Static + Registers calling convention. It could be called at physical + mode and virtual mode. + + @param Index Index of PAL_PERF_MON_INFO within the list of + PAL procedures. + @param PerformanceBuffer An address to an 8-byte aligned + 128-byte memory buffer. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Information about the performance monitors + implemented. See PAL_PERFORMANCE_INFO; + +**/ +#define PAL_PERF_MON_INFO 15 + +#define PAL_PLATFORM_ADDR_INTERRUPT_BLOCK_TOKEN 0x0 +#define PAL_PLATFORM_ADDR_IO_BLOCK_TOKEN 0x1 + +/** + PAL Procedure - PAL_PLATFORM_ADDR. + + Specify processor interrupt block address and I/O port space + address. It is required by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode and virtual mode. + + @param Index Index of PAL_PLATFORM_ADDR within the list of + PAL procedures. + @param Type Unsigned 64-bit integer specifying the type of + block. 0 indicates that the processor interrupt + block pointer should be initialized. 1 indicates + that the processor I/O block pointer should be + initialized. + @param Address Unsigned 64-bit integer specifying the address + to which the processor I/O block or interrupt + block shall be set. The address must specify + an implemented physical address on the + processor model, bit 63 is ignored. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure. + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_PLATFORM_ADDR 16 + +typedef struct { + UINT64 Reserved1:36; + UINT64 FaultInUndefinedIns:1; ///< Bit36, No Unimplemented + ///< instruction address reported as + ///< fault. Denotes how the processor + ///< reports the detection of + ///< unimplemented instruction + ///< addresses. When 1, the processor + ///< reports an Unimplemented + ///< Instruction Address fault on the + ///< unimplemented address; when 0, it + ///< reports an Unimplemented + ///< Instruction Address trap on the + ///< previous instruction in program + ///< order. This feature may only be + ///< interrogated by + ///< PAL_PROC_GET_FEATURES. It may not + ///< be enabled or disabled by + ///< PAL_PROC_SET_FEATURES. The + ///< corresponding argument is ignored. + + UINT64 NoPresentPmi:1; ///< Bit37, No INIT, PMI, and LINT pins + ///< present. Denotes the absence of INIT, + ///< PMI, LINT0 and LINT1 pins on the + ///< processor. When 1, the pins are absent. + ///< When 0, the pins are present. This + ///< feature may only be interrogated by + ///< PAL_PROC_GET_FEATURES. It may not be + ///< enabled or disabled by + ///< PAL_PROC_SET_FEATURES. The corresponding + ///< argument is ignored. + + UINT64 NoSimpleImpInUndefinedIns:1; ///< Bit38, No Simple + ///< implementation of + ///< unimplemented instruction + ///< addresses. Denotes how an + ///< unimplemented instruction + ///< address is recorded in IIP + ///< on an Unimplemented + ///< Instruction Address trap or + ///< fault. When 1, the full + ///< unimplemented address is + ///< recorded in IIP; when 0, the + ///< address is sign extended + ///< (virtual addresses) or zero + ///< extended (physical + ///< addresses). This feature may + ///< only be interrogated by + ///< PAL_PROC_GET_FEATURES. It + ///< may not be enabled or + ///< disabled by + ///< PAL_PROC_SET_FEATURES. The + ///< corresponding argument is + ///< ignored. + + UINT64 NoVariablePState:1; ///< Bit39, No Variable P-state + ///< performance: A value of 1, indicates + ///< that a processor implements + ///< techniques to optimize performance + ///< for the given P-state power budget + ///< by dynamically varying the + ///< frequency, such that maximum + ///< performance is achieved for the + ///< power budget. A value of 0, + ///< indicates that P-states have no + ///< frequency variation or very small + ///< frequency variations for their given + ///< power budget. This feature may only + ///< be interrogated by + ///< PAL_PROC_GET_FEATURES. it may not be + ///< enabled or disabled by + ///< PAL_PROC_SET_FEATURES. The + ///< corresponding argument is ignored. + + UINT64 NoVM:1; ///< Bit40, No Virtual Machine features implemented. + ///< Denotes whether PSR.vm is implemented. This + ///< feature may only be interrogated by + ///< PAL_PROC_GET_FEATURES. It may not be enabled or + ///< disabled by PAL_PROC_SET_FEATURES. The + ///< corresponding argument is ignored. + + UINT64 NoXipXpsrXfs:1; ///< Bit41, No XIP, XPSR, and XFS + ///< implemented. Denotes whether XIP, XPSR, + ///< and XFS are implemented for machine + ///< check recovery. This feature may only be + ///< interrogated by PAL_PROC_GET_FEATURES. + ///< It may not be enabled or disabled by + ///< PAL_PROC_SET_FEATURES. The corresponding + ///< argument is ignored. + + UINT64 NoXr1ThroughXr3:1; ///< Bit42, No XR1 through XR3 implemented. + ///< Denotes whether XR1 XR3 are + ///< implemented for machine check + ///< recovery. This feature may only be + ///< interrogated by PAL_PROC_GET_FEATURES. + ///< It may not be enabled or disabled by + ///< PAL_PROC_SET_FEATURES. The + ///< corresponding argument is ignored. + + UINT64 DisableDynamicPrediction:1; ///< Bit43, Disable Dynamic + ///< Predicate Prediction. When + ///< 0, the processor may predict + ///< predicate results and + ///< execute speculatively, but + ///< may not commit results until + ///< the actual predicates are + ///< known. When 1, the processor + ///< shall not execute predicated + ///< instructions until the + ///< actual predicates are known. + + UINT64 DisableSpontaneousDeferral:1; ///< Bit44, Disable Spontaneous + ///< Deferral. When 1, the + ///< processor may optionally + ///< defer speculative loads + ///< that do not encounter any + ///< exception conditions, but + ///< that trigger other + ///< implementation-dependent + ///< conditions (e.g., cache + ///< miss). When 0, spontaneous + ///< deferral is disabled. + + UINT64 DisableDynamicDataCachePrefetch:1; ///< Bit45, Disable Dynamic + ///< Data Cache Prefetch. + ///< When 0, the processor + ///< may prefetch into the + ///< caches any data which + ///< has not been accessed + ///< by instruction + ///< execution, but which + ///< is likely to be + ///< accessed. When 1, no + ///< data may be fetched + ///< until it is needed for + ///< instruction execution + ///< or is fetched by an + ///< lfetch instruction. + + UINT64 DisableDynamicInsCachePrefetch:1; ///< Bit46, Disable + ///< DynamicInstruction Cache + ///< Prefetch. When 0, the + ///< processor may prefetch + ///< into the caches any + ///< instruction which has + ///< not been executed, but + ///< whose execution is + ///< likely. When 1, + ///< instructions may not be + ///< fetched until needed or + ///< hinted for execution. + ///< (Prefetch for a hinted + ///< branch is allowed even + ///< when dynamic instruction + ///< cache prefetch is + ///< disabled.) + + UINT64 DisableBranchPrediction:1; ///< Bit47, Disable Dynamic branch + ///< prediction. When 0, the + ///< processor may predict branch + ///< targets and speculatively + ///< execute, but may not commit + ///< results. When 1, the processor + ///< must wait until branch targets + ///< are known to execute. + UINT64 Reserved2:4; + UINT64 DisablePState:1; ///< Bit52, Disable P-states. When 1, the PAL + ///< P-state procedures (PAL_PSTATE_INFO, + ///< PAL_SET_PSTATE, PAL_GET_PSTATE) will + ///< return with a status of -1 + ///< (Unimplemented procedure). + + UINT64 EnableMcaOnDataPoisoning:1; ///< Bit53, Enable MCA signaling + ///< on data-poisoning event + ///< detection. When 0, a CMCI + ///< will be signaled on error + ///< detection. When 1, an MCA + ///< will be signaled on error + ///< detection. If this feature + ///< is not supported, then the + ///< corresponding argument is + ///< ignored when calling + ///< PAL_PROC_SET_FEATURES. Note + ///< that the functionality of + ///< this bit is independent of + ///< the setting in bit 60 + ///< (Enable CMCI promotion), and + ///< that the bit 60 setting does + ///< not affect CMCI signaling + ///< for data-poisoning related + ///< events. Volume 2: Processor + ///< Abstraction Layer 2:431 + ///< PAL_PROC_GET_FEATURES + + UINT64 EnableVmsw:1; ///< Bit54, Enable the use of the vmsw + ///< instruction. When 0, the vmsw instruction + ///< causes a Virtualization fault when + ///< executed at the most privileged level. + ///< When 1, this bit will enable normal + ///< operation of the vmsw instruction. + + UINT64 EnableEnvNotification:1; ///< Bit55, Enable external + ///< notification when the processor + ///< detects hardware errors caused + ///< by environmental factors that + ///< could cause loss of + ///< deterministic behavior of the + ///< processor. When 1, this bit will + ///< enable external notification, + ///< when 0 external notification is + ///< not provided. The type of + ///< external notification of these + ///< errors is processor-dependent. A + ///< loss of processor deterministic + ///< behavior is considered to have + ///< occurred if these + ///< environmentally induced errors + ///< cause the processor to deviate + ///< from its normal execution and + ///< eventually causes different + ///< behavior which can be observed + ///< at the processor bus pins. + ///< Processor errors that do not + ///< have this effects (i.e., + ///< software induced machine checks) + ///< may or may not be promoted + ///< depending on the processor + ///< implementation. + + UINT64 DisableBinitWithTimeout:1; ///< Bit56, Disable a BINIT on + ///< internal processor time-out. + ///< When 0, the processor may + ///< generate a BINIT on an + ///< internal processor time-out. + ///< When 1, the processor will not + ///< generate a BINIT on an + ///< internal processor time-out. + ///< The event is silently ignored. + + UINT64 DisableDPM:1; ///< Bit57, Disable Dynamic Power Management + ///< (DPM). When 0, the hardware may reduce + ///< power consumption by removing the clock + ///< input from idle functional units. When 1, + ///< all functional units will receive clock + ///< input, even when idle. + + UINT64 DisableCoherency:1; ///< Bit58, Disable Coherency. When 0, + ///< the processor uses normal coherency + ///< requests and responses. When 1, the + ///< processor answers all requests as if + ///< the line were not present. + + UINT64 DisableCache:1; ///< Bit59, Disable Cache. When 0, the + ///< processor performs cast outs on + ///< cacheable pages and issues and responds + ///< to coherency requests normally. When 1, + ///< the processor performs a memory access + ///< for each reference regardless of cache + ///< contents and issues no coherence + ///< requests and responds as if the line + ///< were not present. Cache contents cannot + ///< be relied upon when the cache is + ///< disabled. WARNING: Semaphore + ///< instructions may not be atomic or may + ///< cause Unsupported Data Reference faults + ///< if caches are disabled. + + UINT64 EnableCmciPromotion:1; ///< Bit60, Enable CMCI promotion When + ///< 1, Corrected Machine Check + ///< Interrupts (CMCI) are promoted to + ///< MCAs. They are also further + ///< promoted to BERR if bit 39, Enable + ///< MCA promotion, is also set and + ///< they are promoted to BINIT if bit + ///< 38, Enable MCA to BINIT promotion, + ///< is also set. This bit has no + ///< effect if MCA signalling is + ///< disabled (see + ///< PAL_BUS_GET/SET_FEATURES) + + UINT64 EnableMcaToBinitPromotion:1; ///< Bit61, Enable MCA to BINIT + ///< promotion. When 1, machine + ///< check aborts (MCAs) are + ///< promoted to the Bus + ///< Initialization signal, and + ///< the BINIT pin is assert on + ///< each occurrence of an MCA. + ///< Setting this bit has no + ///< effect if BINIT signalling + ///< is disabled. (See + ///< PAL_BUS_GET/SET_FEATURES) + + UINT64 EnableMcaPromotion:1; ///< Bit62, Enable MCA promotion. When + ///< 1, machine check aborts (MCAs) are + ///< promoted to the Bus Error signal, + ///< and the BERR pin is assert on each + ///< occurrence of an MCA. Setting this + ///< bit has no effect if BERR + ///< signalling is disabled. (See + ///< PAL_BUS_GET/SET_FEATURES) + + UINT64 EnableBerrPromotion:1; ///< Bit63. Enable BERR promotion. When + ///< 1, the Bus Error (BERR) signal is + ///< promoted to the Bus Initialization + ///< (BINIT) signal, and the BINIT pin + ///< is asserted on the occurrence of + ///< each Bus Error. Setting this bit + ///< has no effect if BINIT signalling + ///< is disabled. (See + ///< PAL_BUS_GET/SET_FEATURES) +} PAL_PROCESSOR_FEATURES; + +/** + PAL Procedure - PAL_PROC_GET_FEATURES. + + Return configurable processor features and their current + setting. It is required by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode and virtual mode. + + @param Index Index of PAL_PROC_GET_FEATURES within the list of + PAL procedures. + @param Reserved Reserved parameter. + @param FeatureSet Feature set information is being requested + for. + + @retval 1 Call completed without error; The + feature_set passed is not supported but a + feature_set of a larger value is supported. + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -8 feature_set passed is beyond the maximum + feature_set supported + + @return R9 64-bit vector of features implemented. See + PAL_PROCESSOR_FEATURES. + @return R10 64-bit vector of current feature settings. See + PAL_PROCESSOR_FEATURES. + @return R11 64-bit vector of features controllable by + software. + +**/ +#define PAL_PROC_GET_FEATURES 17 + + +/** + PAL Procedure - PAL_PROC_SET_FEATURES. + + Enable or disable configurable processor features. It is + required by Itanium processors. The PAL procedure supports the Static + Registers calling convention. It could be called at physical + mode. + + @param Index Index of PAL_PROC_SET_FEATURES within the list of + PAL procedures. + @param FeatureSelect 64-bit vector denoting desired state of + each feature (1=select, 0=non-select). + @param FeatureSet Feature set to apply changes to. See + PAL_PROC_GET_FEATURES for more information + on feature sets. + + @retval 1 Call completed without error; The + feature_set passed is not supported but a + feature_set of a larger value is supported + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -8 feature_set passed is beyond the maximum + feature_set supported + +**/ +#define PAL_PROC_SET_FEATURES 18 + + +// +// Value of PAL_REGISTER_INFO.InfoRequest. +// +#define PAL_APPLICATION_REGISTER_IMPLEMENTED 0 +#define PAL_APPLICATION_REGISTER_READABLE 1 +#define PAL_CONTROL_REGISTER_IMPLEMENTED 2 +#define PAL_CONTROL_REGISTER_READABLE 3 + + +/** + PAL Procedure - PAL_REGISTER_INFO. + + Return AR and CR register information. It is required by Itanium processors. + The PAL procedure supports the Static Registers calling + convention. It could be called at physical mode and virtual + mode. + + @param Index Index of PAL_REGISTER_INFO within the list of + PAL procedures. + @param InfoRequest Unsigned 64-bit integer denoting what + register information is requested. See + PAL_REGISTER_INFO.InfoRequest above. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 64-bit vector denoting information for registers + 0-63. Bit 0 is register 0, bit 63 is register 63. + @return R10 64-bit vector denoting information for registers + 64-127. Bit 0 is register 64, bit 63 is register + 127. + +**/ +#define PAL_REGISTER_INFO 39 + +/** + PAL Procedure - PAL_RSE_INFO. + + Return RSE information. It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and virtual mode. + + @param Index Index of PAL_RSE_INFO within the list of + PAL procedures. + @param InfoRequest Unsigned 64-bit integer denoting what + register information is requested. See + PAL_REGISTER_INFO.InfoRequest above. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Number of physical stacked general registers. + @return R10 RSE hints supported by processor. + +**/ +#define PAL_RSE_INFO 19 + +typedef struct { + UINT64 VersionOfPalB:16; ///< Is a 16-bit binary coded decimal (BCD) + ///< number that provides identification + ///< information about the PAL_B firmware. + UINT64 Reserved1:8; + UINT64 PalVendor:8; ///< Is an unsigned 8-bit integer indicating the + ///< vendor of the PAL code. + UINT64 VersionOfPalA:16; ///< Is a 16-bit binary coded decimal (BCD) + ///< number that provides identification + ///< information about the PAL_A firmware. In + ///< the split PAL_A model, this return value + ///< is the version number of the + ///< processor-specific PAL_A. The generic + ///< PAL_A version is not returned by this + ///< procedure in the split PAL_A model. + UINT64 Reserved2:16; +} PAL_VERSION_INFO; + +/** + PAL Procedure - PAL_VERSION. + + Return version of PAL code. It is required by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode and virtual mode. + + @param Index Index of PAL_VERSION within the list of + PAL procedures. + @param InfoRequest Unsigned 64-bit integer denoting what + register information is requested. See + PAL_REGISTER_INFO.InfoRequest above. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 8-byte formatted value returning the minimum PAL + version needed for proper operation of the + processor. See PAL_VERSION_INFO above. + @return R10 8-byte formatted value returning the current PAL + version running on the processor. See + PAL_VERSION_INFO above. + +**/ +#define PAL_VERSION 20 + + + +// +// Vectors of PAL_MC_CLEAR_LOG.pending +// +#define PAL_MC_PENDING BIT0 +#define PAL_INIT_PENDING BIT1 + +/** + PAL Procedure - PAL_MC_CLEAR_LOG. + + Clear all error information from processor error logging + registers. It is required by Itanium processors. The PAL procedure supports + the Static Registers calling convention. It could be called at + physical mode and virtual mode. + + @param Index Index of PAL_MC_CLEAR_LOG within the list of + PAL procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 64-bit vector denoting whether an event is + pending. See PAL_MC_CLEAR_LOG.pending above. + +**/ +#define PAL_MC_CLEAR_LOG 21 + +/** + PAL Procedure - PAL_MC_DRAIN. + + Ensure that all operations that could cause an MCA have + completed. It is required by Itanium processors. The PAL procedure supports + the Static Registers calling convention. It could be called at + physical mode and virtual mode. + + @param Index Index of PAL_MC_DRAIN within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_MC_DRAIN 22 + + +/** + PAL Procedure - PAL_MC_DYNAMIC_STATE. + + Return Processor Dynamic State for logging by SAL. It is + optional. The PAL procedure supports the Static Registers + calling convention. It could be called at physical mode. + + @param Index Index of PAL_MC_DYNAMIC_STATE within the list of PAL + procedures. + @param Offset Offset of the next 8 bytes of Dynamic Processor + State to return. (multiple of 8). + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure. + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned 64-bit integer denoting bytes of Dynamic + Processor State returned. + @return R10 Next 8 bytes of Dynamic Processor State. + +**/ +#define PAL_MC_DYNAMIC_STATE 24 + + + +// +// Values of PAL_MC_ERROR_INFO.InfoIndex. +// +#define PAL_PROCESSOR_ERROR_MAP 0 +#define PAL_PROCESSOR_STATE_PARAM 1 +#define PAL_STRUCTURE_SPECIFIC_ERROR 2 + +typedef struct { + UINT64 CoreId:4; ///< Bit3:0, Processor core ID (default is 0 for + ///< processors with a single core) + + UINT64 ThreadId:4; ///< Bit7:4, Logical thread ID (default is 0 for + ///< processors that execute a single thread) + + UINT64 InfoOfInsCache:4; ///< Bit11:8, Error information is + ///< available for 1st, 2nd, 3rd, and 4th + ///< level instruction caches. + + UINT64 InfoOfDataCache:4; ///< Bit15:12, Error information is + ///< available for 1st, 2nd, 3rd, and 4th + ///< level data/unified caches. + + UINT64 InfoOfInsTlb:4; ///< Bit19:16 Error information is available + ///< for 1st, 2nd, 3rd, and 4th level + ///< instruction TLB. + + UINT64 InfoOfDataTlb:4; ///< Bit23:20, Error information is available + ///< for 1st, 2nd, 3rd, and 4th level + ///< data/unified TLB + + UINT64 InfoOfProcessorBus:4; ///< Bit27:24 Error information is + ///< available for the 1st, 2nd, 3rd, + ///< and 4th level processor bus + ///< hierarchy. + UINT64 InfoOfRegisterFile:4; ///< Bit31:28 Error information is + ///< available on register file + ///< structures. + UINT64 InfoOfMicroArch:4; ///< Bit47:32, Error information is + ///< available on micro-architectural + ///< structures. + UINT64 Reserved:16; +} PAL_MC_ERROR_INFO_LEVEL_INDEX; + +// +// Value of PAL_MC_ERROR_INFO.ErrorTypeIndex +// +#define PAL_ERR_INFO_BY_LEVEL_INDEX 0 +#define PAL_ERR_INFO_TARGET_ADDRESS 1 +#define PAL_ERR_INFO_REQUESTER_IDENTIFIER 2 +#define PAL_ERR_INFO_REPONSER_INDENTIFIER 3 +#define PAL_ERR_INFO_PRECISE_INSTRUCTION_POINTER 4 + +typedef struct { + UINT64 Operation:4; ///< Bit3:0, Type of cache operation that caused + ///< the machine check: 0 - unknown or internal + ///< error 1 - load 2 - store 3 - instruction + ///< fetch or instruction prefetch 4 - data + ///< prefetch (both hardware and software) 5 - + ///< snoop (coherency check) 6 - cast out + ///< (explicit or implicit write-back of a cache + ///< line) 7 - move in (cache line fill) + + UINT64 FailedCacheLevel:2; ///< Bit5:4 Level of cache where the + ///< error occurred. A value of 0 + ///< indicates the first level of cache. + UINT64 Reserved1:2; + UINT64 FailedInDataPart:1; ///< Bit8, Failure located in the data part of the cache line. + UINT64 FailedInTagPart:1; ///< Bit9, Failure located in the tag part of the cache line. + UINT64 FailedInDataCache:1; ///< Bit10, Failure located in the data cache + + UINT64 FailedInInsCache:1; ///< Bit11, Failure located in the + ///< instruction cache. + + UINT64 Mesi:3; ///< Bit14:12, 0 - cache line is invalid. 1 - cache + ///< line is held shared. 2 - cache line is held + ///< exclusive. 3 - cache line is modified. All other + ///< values are reserved. + + UINT64 MesiIsValid:1; ///< Bit15, The mesi field in the cache_check + ///< parameter is valid. + + UINT64 FailedWay:5; ///< Bit20:16, Failure located in the way of + ///< the cache indicated by this value. + + UINT64 WayIndexIsValid:1; ///< Bit21, The way and index field in the + ///< cache_check parameter is valid. + + UINT64 Reserved2:1; + UINT64 MultipleBitsError:1; ///< Bit23, A multiple-bit error was + ///< detected, and data was poisoned for + ///< the corresponding cache line during + ///< castout. + UINT64 Reserved3:8; + UINT64 IndexOfCacheLineError:20; ///< Bit51:32, Index of the cache + ///< line where the error occurred. + UINT64 Reserved4:2; + + UINT64 InstructionSet:1; ///< Bit54, Instruction set. If this value + ///< is set to zero, the instruction that + ///< generated the machine check was an + ///< Intel Itanium instruction. If this bit + ///< is set to one, the instruction that + ///< generated the machine check was IA-32 + ///< instruction. + + UINT64 InstructionSetIsValid:1; ///< Bit55, The is field in the + ///< cache_check parameter is valid. + + UINT64 PrivilegeLevel:2; ///< Bit57:56, Privilege level. The + ///< privilege level of the instruction + ///< bundle responsible for generating the + ///< machine check. + + UINT64 PrivilegeLevelIsValide:1; ///< Bit58, The pl field of the + ///< cache_check parameter is + ///< valid. + + UINT64 McCorrected:1; ///< Bit59, Machine check corrected: This bit + ///< is set to one to indicate that the machine + ///< check has been corrected. + + UINT64 TargetAddressIsValid:1; ///< Bit60, Target address is valid: + ///< This bit is set to one to + ///< indicate that a valid target + ///< address has been logged. + + UINT64 RequesterIdentifier:1; ///< Bit61, Requester identifier: This + ///< bit is set to one to indicate that + ///< a valid requester identifier has + ///< been logged. + + UINT64 ResponserIdentifier:1; ///< Bit62, Responder identifier: This + ///< bit is set to one to indicate that + ///< a valid responder identifier has + ///< been logged. + + UINT64 PreciseInsPointer:1; ///< Bit63, Precise instruction pointer. + ///< This bit is set to one to indicate + ///< that a valid precise instruction + ///< pointer has been logged. + +} PAL_CACHE_CHECK_INFO; + + +typedef struct { + UINT64 FailedSlot:8; ///< Bit7:0, Slot number of the translation + ///< register where the failure occurred. + UINT64 FailedSlotIsValid:1; ///< Bit8, The tr_slot field in the + ///< TLB_check parameter is valid. + UINT64 Reserved1 :1; + UINT64 TlbLevel:2; ///< Bit11:10, The level of the TLB where the + ///< error occurred. A value of 0 indicates the + ///< first level of TLB + UINT64 Reserved2 :4; + + UINT64 FailedInDataTr:1; ///< Bit16, Error occurred in the data + ///< translation registers. + + UINT64 FailedInInsTr:1; ///< Bit17, Error occurred in the instruction + ///< translation registers + + UINT64 FailedInDataTc:1; ///< Bit18, Error occurred in data + ///< translation cache. + + UINT64 FailedInInsTc:1; ///< Bit19, Error occurred in the instruction + ///< translation cache. + + UINT64 FailedOperation:4; ///< Bit23:20, Type of cache operation that + ///< caused the machine check: 0 - unknown + ///< 1 - TLB access due to load instruction + ///< 2 - TLB access due to store + ///< instruction 3 - TLB access due to + ///< instruction fetch or instruction + ///< prefetch 4 - TLB access due to data + ///< prefetch (both hardware and software) + ///< 5 - TLB shoot down access 6 - TLB + ///< probe instruction (probe, tpa) 7 - + ///< move in (VHPT fill) 8 - purge (insert + ///< operation that purges entries or a TLB + ///< purge instruction) All other values + ///< are reserved. + + UINT64 Reserved3:30; + UINT64 InstructionSet:1; ///< Bit54, Instruction set. If this value + ///< is set to zero, the instruction that + ///< generated the machine check was an + ///< Intel Itanium instruction. If this bit + ///< is set to one, the instruction that + ///< generated the machine check was IA-32 + ///< instruction. + + UINT64 InstructionSetIsValid:1; ///< Bit55, The is field in the + ///< TLB_check parameter is valid. + + UINT64 PrivelegeLevel:2; ///< Bit57:56, Privilege level. The + ///< privilege level of the instruction + ///< bundle responsible for generating the + ///< machine check. + + UINT64 PrivelegeLevelIsValid:1; ///< Bit58, The pl field of the + ///< TLB_check parameter is valid. + + UINT64 McCorrected:1; ///< Bit59, Machine check corrected: This bit + ///< is set to one to indicate that the machine + ///< check has been corrected. + + UINT64 TargetAddressIsValid:1; ///< Bit60, Target address is valid: + ///< This bit is set to one to + ///< indicate that a valid target + ///< address has been logged. + + UINT64 RequesterIdentifier:1; ///< Bit61 Requester identifier: This + ///< bit is set to one to indicate that + ///< a valid requester identifier has + ///< been logged. + + UINT64 ResponserIdentifier:1; ///< Bit62, Responder identifier: This + ///< bit is set to one to indicate that + ///< a valid responder identifier has + ///< been logged. + + UINT64 PreciseInsPointer:1; ///< Bit63 Precise instruction pointer. + ///< This bit is set to one to indicate + ///< that a valid precise instruction + ///< pointer has been logged. +} PAL_TLB_CHECK_INFO; + +/** + PAL Procedure - PAL_MC_ERROR_INFO. + + Return Processor Machine Check Information and Processor + Static State for logging by SAL. It is required by Itanium processors. The + PAL procedure supports the Static Registers calling + convention. It could be called at physical and virtual mode. + + @param Index Index of PAL_MC_ERROR_INFO within the list of PAL + procedures. + @param InfoIndex Unsigned 64-bit integer identifying the + error information that is being requested. + See PAL_MC_ERROR_INFO.InfoIndex. + @param LevelIndex 8-byte formatted value identifying the + structure to return error information + on. See PAL_MC_ERROR_INFO_LEVEL_INDEX. + @param ErrorTypeIndex Unsigned 64-bit integer denoting the + type of error information that is + being requested for the structure + identified in LevelIndex. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -6 Argument was valid, but no error + information was available + + @return R9 Error information returned. The format of this + value is dependant on the input values passed. + @return R10 If this value is zero, all the error information + specified by err_type_index has been returned. If + this value is one, more structure-specific error + information is available and the caller needs to + make this procedure call again with level_index + unchanged and err_type_index, incremented. + +**/ +#define PAL_MC_ERROR_INFO 25 + +/** + PAL Procedure - PAL_MC_EXPECTED. + + Set/Reset Expected Machine Check Indicator. It is required by + Itanium processors. The PAL procedure supports the Static Registers calling + convention. It could be called at physical mode. + + @param Index Index of PAL_MC_EXPECTED within the list of PAL + procedures. + @param Expected Unsigned integer with a value of 0 or 1 to + set or reset the hardware resource + PALE_CHECK examines for expected machine + checks. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned integer denoting whether a machine check + was previously expected. + +**/ +#define PAL_MC_EXPECTED 23 + +/** + PAL Procedure - PAL_MC_REGISTER_MEM. + + Register min-state save area with PAL for machine checks and + inits. It is required by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode. + + @param Index Index of PAL_MC_REGISTER_MEM within the list of PAL + procedures. + @param Address Physical address of the buffer to be + registered with PAL. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_MC_REGISTER_MEM 27 + +/** + PAL Procedure - PAL_MC_RESUME. + + Restore minimal architected state and return to interrupted + process. It is required by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode. + + @param Index Index of PAL_MC_RESUME within the list of PAL + procedures. + @param SetCmci Unsigned 64 bit integer denoting whether to + set the CMC interrupt. A value of 0 indicates + not to set the interrupt, a value of 1 + indicated to set the interrupt, and all other + values are reserved. + @param SavePtr Physical address of min-state save area used + to used to restore processor state. + @param NewContext Unsigned 64-bit integer denoting whether + the caller is returning to a new context. + A value of 0 indicates the caller is + returning to the interrupted context, a + value of 1 indicates that the caller is + returning to a new context. + + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_MC_RESUME 26 + +/** + PAL Procedure - PAL_HALT. + + Enter the low-power HALT state or an implementation-dependent + low-power state. It is optinal. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode. + + @param Index Index of PAL_HALT within the list of PAL + procedures. + @param HaltState Unsigned 64-bit integer denoting low power + state requested. + @param IoDetailPtr 8-byte aligned physical address pointer to + information on the type of I/O + (load/store) requested. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Value returned if a load instruction is requested + in the io_detail_ptr + +**/ +#define PAL_HALT 28 + + +/** + PAL Procedure - PAL_HALT_INFO. + + Return the low power capabilities of the processor. It is + required by Itanium processors. The PAL procedure supports the + Stacked Registers calling convention. It could be called at + physical and virtual mode. + + @param Index Index of PAL_HALT_INFO within the list of PAL + procedures. + @param PowerBuffer 64-bit pointer to a 64-byte buffer aligned + on an 8-byte boundary. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_HALT_INFO 257 + + +/** + PAL Procedure - PAL_HALT_LIGHT. + + Enter the low power LIGHT HALT state. It is required by + Itanium processors. The PAL procedure supports the Static Registers calling + convention. It could be called at physical and virtual mode. + + @param Index Index of PAL_HALT_LIGHT within the list of PAL + procedures. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_HALT_LIGHT 29 + +/** + PAL Procedure - PAL_CACHE_LINE_INIT. + + Initialize tags and data of a cache line for processor + testing. It is required by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical and virtual mode. + + @param Index Index of PAL_CACHE_LINE_INIT within the list of PAL + procedures. + @param Address Unsigned 64-bit integer value denoting the + physical address from which the physical page + number is to be generated. The address must be + an implemented physical address, bit 63 must + be zero. + @param DataValue 64-bit data value which is used to + initialize the cache line. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_CACHE_LINE_INIT 31 + +/** + PAL Procedure - PAL_CACHE_READ. + + Read tag and data of a cache line for diagnostic testing. It + is optional. The PAL procedure supports the + Satcked Registers calling convention. It could be called at + physical mode. + + @param Index Index of PAL_CACHE_READ within the list of PAL + procedures. + @param LineId 8-byte formatted value describing where in the + cache to read the data. + @param Address 64-bit 8-byte aligned physical address from + which to read the data. The address must be an + implemented physical address on the processor + model with bit 63 set to zero. + + @retval 1 The word at address was found in the + cache, but the line was invalid. + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -5 The word at address was not found in the + cache. + @retval -7 The operation requested is not supported + for this cache_type and level. + + @return R9 Right-justified value returned from the cache + line. + @return R10 The number of bits returned in data. + @return R11 The status of the cache line. + +**/ +#define PAL_CACHE_READ 259 + + +/** + PAL Procedure - PAL_CACHE_WRITE. + + Write tag and data of a cache for diagnostic testing. It is + optional. The PAL procedure supports the Satcked Registers + calling convention. It could be called at physical mode. + + @param Index Index of PAL_CACHE_WRITE within the list of PAL + procedures. + @param LineId 8-byte formatted value describing where in the + cache to write the data. + @param Address 64-bit 8-byte aligned physical address at + which the data should be written. The address + must be an implemented physical address on the + processor model with bit 63 set to 0. + @param Data Unsigned 64-bit integer value to write into + the specified part of the cache. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -7 The operation requested is not supported + for this cache_type and level. + +**/ +#define PAL_CACHE_WRITE 260 + +/** + PAL Procedure - PAL_TEST_INFO. + + Returns alignment and size requirements needed for the memory + buffer passed to the PAL_TEST_PROC procedure as well as + information on self-test control words for the processor self + tests. It is required by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode. + + @param Index Index of PAL_TEST_INFO within the list of PAL + procedures. + @param TestPhase Unsigned integer that specifies which phase + of the processor self-test information is + being requested on. A value of 0 indicates + the phase two of the processor self-test and + a value of 1 indicates phase one of the + processor self-test. All other values are + reserved. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned 64-bit integer denoting the number of + bytes of main memory needed to perform the second + phase of processor self-test. + @return R10 Unsigned 64-bit integer denoting the alignment + required for the memory buffer. + @return R11 48-bit wide bit-field indicating if control of + the processor self-tests is supported and which + bits of the test_control field are defined for + use. + +**/ +#define PAL_TEST_INFO 37 + +typedef struct { + UINT64 BufferSize:56; ///< Indicates the size in bytes of the memory + ///< buffer that is passed to this procedure. + ///< BufferSize must be greater than or equal in + ///< size to the bytes_needed return value from + ///< PAL_TEST_INFO, otherwise this procedure will + ///< return with an invalid argument return + ///< value. + + UINT64 TestPhase:8; ///< Defines which phase of the processor + ///< self-tests are requested to be run. A value + ///< of zero indicates to run phase two of the + ///< processor self-tests. Phase two of the + ///< processor self-tests are ones that require + ///< external memory to execute correctly. A + ///< value of one indicates to run phase one of + ///< the processor self-tests. Phase one of the + ///< processor self-tests are tests run during + ///< PALE_RESET and do not depend on external + ///< memory to run correctly. When the caller + ///< requests to have phase one of the processor + ///< self-test run via this procedure call, a + ///< memory buffer may be needed to save and + ///< restore state as required by the PAL calling + ///< conventions. The procedure PAL_TEST_INFO + ///< informs the caller about the requirements of + ///< the memory buffer. +} PAL_TEST_INFO_INFO; + +typedef struct { + UINT64 TestControl:47; ///< This is an ordered implementation-specific + ///< control word that allows the user control + ///< over the length and runtime of the + ///< processor self-tests. This control word is + ///< ordered from the longest running tests up + ///< to the shortest running tests with bit 0 + ///< controlling the longest running test. PAL + ///< may not implement all 47-bits of the + ///< test_control word. PAL communicates if a + ///< bit provides control by placing a zero in + ///< that bit. If a bit provides no control, + ///< PAL will place a one in it. PAL will have + ///< two sets of test_control bits for the two + ///< phases of the processor self-test. PAL + ///< provides information about implemented + ///< test_control bits at the hand-off from PAL + ///< to SAL for the firmware recovery check. + ///< These test_control bits provide control + ///< for phase one of processor self-test. It + ///< also provides this information via the PAL + ///< procedure call PAL_TEST_INFO for both the + ///< phase one and phase two processor tests + ///< depending on which information the caller + ///< is requesting. PAL interprets these bits + ///< as input parameters on two occasions. The + ///< first time is when SAL passes control back + ///< to PAL after the firmware recovery check. + ///< The second time is when a call to + ///< PAL_TEST_PROC is made. When PAL interprets + ///< these bits it will only interpret + ///< implemented test_control bits and will + ///< ignore the values located in the + ///< unimplemented test_control bits. PAL + ///< interprets the implemented bits such that + ///< if a bit contains a zero, this indicates + ///< to run the test. If a bit contains a one, + ///< this indicates to PAL to skip the test. If + ///< the cs bit indicates that control is not + ///< available, the test_control bits will be + ///< ignored or generate an illegal argument in + ///< procedure calls if the caller sets these + ///< bits. + + UINT64 ControlSupport:1; ///< This bit defines if an implementation + ///< supports control of the PAL self-tests + ///< via the self-test control word. If + ///< this bit is 0, the implementation does + ///< not support control of the processor + ///< self-tests via the self-test control + ///< word. If this bit is 1, the + ///< implementation does support control of + ///< the processor self-tests via the + ///< self-test control word. If control is + ///< not supported, GR37 will be ignored at + ///< the hand-off between SAL and PAL after + ///< the firmware recovery check and the + ///< PAL procedures related to the + ///< processor self-tests may return + ///< illegal arguments if a user tries to + ///< use the self-test control features. + UINT64 Reserved:16; +} PAL_SELF_TEST_CONTROL; + +typedef struct { + UINT64 Attributes:8; ///< Specifies the memory attributes that are + ///< allowed to be used with the memory buffer + ///< passed to this procedure. The attributes + ///< parameter is a vector where each bit + ///< represents one of the virtual memory + ///< attributes defined by the architecture.See + ///< MEMORY_AATRIBUTES. The caller is required + ///< to support the cacheable attribute for the + ///< memory buffer, otherwise an invalid + ///< argument will be returned. + UINT64 Reserved:8; + UINT64 TestControl:48; ///< Is the self-test control word + ///< corresponding to the test_phase passed. + ///< This test_control directs the coverage and + ///< runtime of the processor self-tests + ///< specified by the test_phase input + ///< argument. Information on if this + ///< feature is implemented and the number of + ///< bits supported can be obtained by the + ///< PAL_TEST_INFO procedure call. If this + ///< feature is implemented by the processor, + ///< the caller can selectively skip parts of + ///< the processor self-test by setting + ///< test_control bits to a one. If a bit has a + ///< zero, this test will be run. The values in + ///< the unimplemented bits are ignored. If + ///< PAL_TEST_INFO indicated that the self-test + ///< control word is not implemented, this + ///< procedure will return with an invalid + ///< argument status if the caller sets any of + ///< the test_control bits. See + ///< PAL_SELF_TEST_CONTROL. +} PAL_TEST_CONTROL; + +/** + PAL Procedure - PAL_TEST_PROC. + + Perform late processor self test. It is required by Itanium processors. The + PAL procedure supports the Static Registers calling + convention. It could be called at physical mode. + + @param Index Index of PAL_TEST_PROC within the list of PAL + procedures. + @param TestAddress 64-bit physical address of main memory + area to be used by processor self-test. + The memory region passed must be + cacheable, bit 63 must be zero. + @param TestInfo Input argument specifying the size of the + memory buffer passed and the phase of the + processor self-test that should be run. See + PAL_TEST_INFO. + @param TestParam Input argument specifying the self-test + control word and the allowable memory + attributes that can be used with the memory + buffer. See PAL_TEST_CONTROL. + + @retval 1 Call completed without error, but hardware + failures occurred during self-test. + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Formatted 8-byte value denoting the state of the + processor after self-test + +**/ +#define PAL_TEST_PROC 258 + +typedef struct { + UINT32 NumberOfInterruptControllers; ///< Number of interrupt + ///< controllers currently + ///< enabled on the system. + + UINT32 NumberOfProcessors; ///< Number of processors currently + ///< enabled on the system. +} PAL_PLATFORM_INFO; + +/** + PAL Procedure - PAL_COPY_INFO. + + Return information needed to relocate PAL procedures and PAL + PMI code to memory. It is required by Itanium processors. The PAL procedure + supports the Static Registers calling convention. It could be + called at physical mode. + + @param Index Index of PAL_COPY_INFO within the list of PAL + procedures. + @param CopyType Unsigned integer denoting type of procedures + for which copy information is requested. + @param PlatformInfo 8-byte formatted value describing the + number of processors and the number of + interrupt controllers currently enabled + on the system. See PAL_PLATFORM_INFO. + @param McaProcStateInfo Unsigned integer denoting the number + of bytes that SAL needs for the + min-state save area for each + processor. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned integer denoting the number of bytes of + PAL information that must be copied to main + memory. + @return R10 Unsigned integer denoting the starting alignment + of the data to be copied. + +**/ +#define PAL_COPY_INFO 30 + +/** + PAL Procedure - PAL_COPY_PAL. + + Relocate PAL procedures and PAL PMI code to memory. It is + required by Itanium processors. The PAL procedure supports the Stacked + Registers calling convention. It could be called at physical + mode. + + @param Index Index of PAL_COPY_PAL within the list of PAL + procedures. + @param TargetAddress Physical address of a memory buffer to + copy relocatable PAL procedures and PAL + PMI code. + @param AllocSize Unsigned integer denoting the size of the + buffer passed by SAL for the copy operation. + @param CopyOption Unsigned integer indicating whether + relocatable PAL code and PAL PMI code + should be copied from firmware address + space to main memory. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned integer denoting the offset of PAL_PROC + in the relocatable segment copied. + +**/ +#define PAL_COPY_PAL 256 + +/** + PAL Procedure - PAL_ENTER_IA_32_ENV. + + Enter IA-32 System environment. It is optional. The PAL + procedure supports the Static Registers calling convention. + It could be called at physical mode. + + Note: Since this is a special call, it does not follow the PAL + static register calling convention. GR28 contains the index of + PAL_ENTER_IA_32_ENV within the list of PAL procedures. All other + input arguments including GR29-GR31 are setup by SAL to values + as required by the IA-32 operating system defined in Table + 11-67. The registers that are designated as preserved, scratch, + input arguments and procedure return values by the static + procedure calling convention are not followed by this call. For + instance, GR5 and GR6 need not be preserved since these are + regarded as scratch by the IA-32 operating system. Note: In an + MP system, this call must be COMPLETED on the first CPU to enter + the IA-32 System Environment (may or may not be the BSP) prior + to being called on the remaining processors in the MP system. + + @param Index GR28 contains the index of the + PAL_ENTER_IA_32_ENV call within the list of PAL + procedures. + + + @retval The status is returned in GR4. + -1 - Un-implemented procedure 0 JMPE detected + at privilege level + + 0 - 1 SAL allocated buffer for IA-32 System + Environment operation is too small + + 2 - IA-32 Firmware Checksum Error + + 3 - SAL allocated buffer for IA-32 System + Environment operation is not properly aligned + + 4 - Error in SAL MP Info Table + + 5 - Error in SAL Memory Descriptor Table + + 6 - Error in SAL System Table + + 7 - Inconsistent IA-32 state + + 8 - IA-32 Firmware Internal Error + + 9 - IA-32 Soft Reset (Note: remaining register + state is undefined for this termination + reason) + + 10 - Machine Check Error + + 11 - Error in SAL I/O Intercept Table + + 12 - Processor exit due to other processor in + MP system terminating the IA32 system + environment. (Note: remaining register state + is undefined for this termination reason.) + + 13 - Itanium architecture-based state + corruption by either SAL PMI handler or I/O + Intercept callback function. + + +**/ +#define PAL_ENTER_IA_32_ENV 33 + +/** + PAL Procedure - PAL_PMI_ENTRYPOINT. + + Register PMI memory entrypoints with processor. It is required + by Itanium processors. The PAL procedure supports the Stacked Registers + calling convention. It could be called at physical mode. + + @param Index Index of PAL_PMI_ENTRYPOINT within the list of + PAL procedures. + @param SalPmiEntry 256-byte aligned physical address of SAL + PMI entrypoint in memory. + + @retval 0 Call completed without error + @retval -2 Invalid argument + @retval -3 Call completed with error. + +**/ +#define PAL_PMI_ENTRYPOINT 32 + + +/** + + The ASCII brand identification string will be copied to the + address specified in the address input argument. The processor + brand identification string is defined to be a maximum of 128 + characters long; 127 bytes will contain characters and the 128th + byte is defined to be NULL (0). A processor may return less than + the 127 ASCII characters as long as the string is null + terminated. The string length will be placed in the brand_info + return argument. + +**/ +#define PAL_BRAND_INFO_ID_REQUEST 0 + +/** + PAL Procedure - PAL_BRAND_INFO. + + Provides processor branding information. It is optional by + Itanium processors. The PAL procedure supports the Stacked Registers calling + convention. It could be called at physical and Virtual mode. + + @param Index Index of PAL_BRAND_INFO within the list of PAL + procedures. + @param InfoRequest Unsigned 64-bit integer specifying the + information that is being requested. (See + PAL_BRAND_INFO_ID_REQUEST) + @param Address Unsigned 64-bit integer specifying the + address of the 128-byte block to which the + processor brand string shall be written. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -6 Input argument is not implemented. + + @return R9 Brand information returned. The format of this + value is dependent on the input values passed. + +**/ +#define PAL_BRAND_INFO 274 + +/** + PAL Procedure - PAL_GET_HW_POLICY. + + Returns the current hardware resource sharing policy of the + processor. It is optional by Itanium processors. The PAL procedure supports + the Static Registers calling convention. It could be called at + physical and Virtual mode. + + + @param Index Index of PAL_GET_HW_POLICY within the list of PAL + procedures. + @param ProcessorNumber Unsigned 64-bit integer that specifies + for which logical processor + information is being requested. This + input argument must be zero for the + first call to this procedure and can + be a maximum value of one less than + the number of logical processors + impacted by the hardware resource + sharing policy, which is returned by + the R10 return value. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + + @return R9 Unsigned 64-bit integer representing the current + hardware resource sharing policy. + @return R10 Unsigned 64-bit integer that returns the number + of logical processors impacted by the policy + input argument. + @return R11 Unsigned 64-bit integer containing the logical + address of one of the logical processors + impacted by policy modification. + +**/ +#define PAL_GET_HW_POLICY 48 + + +// +// Value of PAL_SET_HW_POLICY.Policy +// +#define PAL_SET_HW_POLICY_PERFORMANCE 0 +#define PAL_SET_HW_POLICY_FAIRNESS 1 +#define PAL_SET_HW_POLICY_HIGH_PRIORITY 2 +#define PAL_SET_HW_POLICY_EXCLUSIVE_HIGH_PRIORITY 3 + +/** + PAL Procedure - PAL_SET_HW_POLICY. + + Sets the current hardware resource sharing policy of the + processor. It is optional by Itanium processors. The PAL procedure supports + the Static Registers calling convention. It could be called at + physical and Virtual mode. + + @param Index Index of PAL_SET_HW_POLICY within the list of PAL + procedures. + @param Policy Unsigned 64-bit integer specifying the hardware + resource sharing policy the caller is setting. + See Value of PAL_SET_HW_POLICY.Policy above. + + @retval 1 Call completed successfully but could not + change the hardware policy since a + competing logical processor is set in + exclusive high priority. + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_SET_HW_POLICY 49 + +typedef struct { + UINT64 Mode:3; ///< Bit2:0, Indicates the mode of operation for this + ///< procedure: 0 - Query mode 1 - Error inject mode + ///< (err_inj should also be specified) 2 - Cancel + ///< outstanding trigger. All other fields in + ///< PAL_MC_ERROR_TYPE_INFO, + ///< PAL_MC_ERROR_STRUCTURE_INFO and + ///< PAL_MC_ERROR_DATA_BUFFER are ignored. All other + ///< values are reserved. + + UINT64 ErrorInjection:3; ///< Bit5:3, indicates the mode of error + ///< injection: 0 - Error inject only (no + ///< error consumption) 1 - Error inject + ///< and consume All other values are + ///< reserved. + + UINT64 ErrorSeverity:2; ///< Bit7:6, indicates the severity desired + ///< for error injection/query. Definitions + ///< of the different error severity types + ///< 0 - Corrected error 1 - Recoverable + ///< error 2 - Fatal error 3 - Reserved + + UINT64 ErrorStructure:5; ///< Bit12:8, Indicates the structure + ///< identification for error + ///< injection/query: 0 - Any structure + ///< (cannot be used during query mode). + ///< When selected, the structure type used + ///< for error injection is determined by + ///< PAL. 1 - Cache 2 - TLB 3 - Register + ///< file 4 - Bus/System interconnect 5-15 + ///< - Reserved 16-31 - Processor + ///< specific error injection + ///< capabilities.ErrorDataBuffer is used + ///< to specify error types. Please refer + ///< to the processor specific + ///< documentation for additional details. + + UINT64 StructureHierarchy:3; ///< Bit15:13, Indicates the structure + ///< hierarchy for error + ///< injection/query: 0 - Any level of + ///< hierarchy (cannot be used during + ///< query mode). When selected, the + ///< structure hierarchy used for error + ///< injection is determined by PAL. 1 + ///< - Error structure hierarchy + ///< level-1 2 - Error structure + ///< hierarchy level-2 3 - Error + ///< structure hierarchy level-3 4 - + ///< Error structure hierarchy level-4 + ///< All other values are reserved. + + UINT64 Reserved:32; ///< Reserved 47:16 Reserved + + UINT64 ImplSpec:16; ///< Bit63:48, Processor specific error injection capabilities. +} PAL_MC_ERROR_TYPE_INFO; + +typedef struct { + UINT64 StructInfoIsValid:1; ///< Bit0 When 1, indicates that the + ///< structure information fields + ///< (c_t,cl_p,cl_id) are valid and + ///< should be used for error injection. + ///< When 0, the structure information + ///< fields are ignored, and the values + ///< of these fields used for error + ///< injection are + ///< implementation-specific. + + UINT64 CacheType:2; ///< Bit2:1 Indicates which cache should be used + ///< for error injection: 0 - Reserved 1 - + ///< Instruction cache 2 - Data or unified cache + ///< 3 - Reserved + + UINT64 PortionOfCacheLine:3; ///< Bit5:3 Indicates the portion of the + ///< cache line where the error should + ///< be injected: 0 - Reserved 1 - Tag + ///< 2 - Data 3 - mesi All other + ///< values are reserved. + + UINT64 Mechanism:3; ///< Bit8:6 Indicates which mechanism is used to + ///< identify the cache line to be used for error + ///< injection: 0 - Reserved 1 - Virtual address + ///< provided in the inj_addr field of the buffer + ///< pointed to by err_data_buffer should be used + ///< to identify the cache line for error + ///< injection. 2 - Physical address provided in + ///< the inj_addr field of the buffer pointed to + ///< by err_data_buffershould be used to identify + ///< the cache line for error injection. 3 - way + ///< and index fields provided in err_data_buffer + ///< should be used to identify the cache line + ///< for error injection. All other values are + ///< reserved. + + UINT64 DataPoisonOfCacheLine:1; ///< Bit9 When 1, indicates that a + ///< multiple bit, non-correctable + ///< error should be injected in the + ///< cache line specified by cl_id. + ///< If this injected error is not + ///< consumed, it may eventually + ///< cause a data-poisoning event + ///< resulting in a corrected error + ///< signal, when the associated + ///< cache line is cast out (implicit + ///< or explicit write-back of the + ///< cache line). The error severity + ///< specified by err_sev in + ///< err_type_info must be set to 0 + ///< (corrected error) when this bit + ///< is set. + + UINT64 Reserved1:22; + + UINT64 TrigerInfoIsValid:1; ///< Bit32 When 1, indicates that the + ///< trigger information fields (trigger, + ///< trigger_pl) are valid and should be + ///< used for error injection. When 0, + ///< the trigger information fields are + ///< ignored and error injection is + ///< performed immediately. + + UINT64 Triger:4; ///< Bit36:33 Indicates the operation type to be + ///< used as the error trigger condition. The + ///< address corresponding to the trigger is + ///< specified in the trigger_addr field of the + ///< buffer pointed to by err_data_buffer: 0 - + ///< Instruction memory access. The trigger match + ///< conditions for this operation type are similar + ///< to the IBR address breakpoint match conditions + ///< 1 - Data memory access. The trigger match + ///< conditions for this operation type are similar + ///< to the DBR address breakpoint match conditions + ///< All other values are reserved. + + UINT64 PrivilegeOfTriger:3; ///< Bit39:37 Indicates the privilege + ///< level of the context during which + ///< the error should be injected: 0 - + ///< privilege level 0 1 - privilege + ///< level 1 2 - privilege level 2 3 - + ///< privilege level 3 All other values + ///< are reserved. If the implementation + ///< does not support privilege level + ///< qualifier for triggers (i.e. if + ///< trigger_pl is 0 in the capabilities + ///< vector), this field is ignored and + ///< triggers can be taken at any + ///< privilege level. + + UINT64 Reserved2:24; +} PAL_MC_ERROR_STRUCT_INFO; + +/** + + Buffer Pointed to by err_data_buffer - TLB + +**/ +typedef struct { + UINT64 TrigerAddress; + UINT64 VirtualPageNumber:52; + UINT64 Reserved1:8; + UINT64 RegionId:24; + UINT64 Reserved2:40; +} PAL_MC_ERROR_DATA_BUFFER_TLB; + +/** + PAL Procedure - PAL_MC_ERROR_INJECT. + + Injects the requested processor error or returns information + on the supported injection capabilities for this particular + processor implementation. It is optional by Itanium processors. The PAL + procedure supports the Stacked Registers calling convention. + It could be called at physical and Virtual mode. + + @param Index Index of PAL_MC_ERROR_INJECT within the list of PAL + procedures. + @param ErrorTypeInfo Unsigned 64-bit integer specifying the + first level error information which + identifies the error structure and + corresponding structure hierarchy, and + the error severity. + @param ErrorStructInfo Unsigned 64-bit integer identifying + the optional structure specific + information that provides the second + level details for the requested error. + @param ErrorDataBuffer 64-bit physical address of a buffer + providing additional parameters for + the requested error. The address of + this buffer must be 8-byte aligned. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -4 Call completed with error; the requested + error could not be injected due to failure in + locating the target location in the specified + structure. + @retval -5 Argument was valid, but requested error + injection capability is not supported. + @retval -9 Call requires PAL memory buffer. + + @return R9 64-bit vector specifying the supported error + injection capabilities for the input argument + combination of struct_hier, err_struct and + err_sev fields in ErrorTypeInfo. + @return R10 64-bit vector specifying the architectural + resources that are used by the procedure. + +**/ +#define PAL_MC_ERROR_INJECT 276 + + +// +// Types of PAL_GET_PSTATE.Type +// +#define PAL_GET_PSTATE_RECENT 0 +#define PAL_GET_PSTATE_AVERAGE_NEW_START 1 +#define PAL_GET_PSTATE_AVERAGE 2 +#define PAL_GET_PSTATE_NOW 3 + +/** + PAL Procedure - PAL_GET_PSTATE. + + Returns the performance index of the processor. It is optional + by Itanium processors. The PAL procedure supports the Stacked Registers + calling convention. It could be called at physical and Virtual + mode. + + @param Index Index of PAL_GET_PSTATE within the list of PAL + procedures. + @param Type Type of performance_index value to be returned + by this procedure.See PAL_GET_PSTATE.Type above. + + @retval 1 Call completed without error, but accuracy + of performance index has been impacted by a + thermal throttling event, or a + hardware-initiated event. + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + + @return R9 Unsigned integer denoting the processor + performance for the time duration since the last + PAL_GET_PSTATE procedure call was made. The + value returned is between 0 and 100, and is + relative to the performance index of the highest + available P-state. + +**/ +#define PAL_GET_PSTATE 262 + +/** + + Layout of PAL_PSTATE_INFO.PStateBuffer + +**/ +typedef struct { + UINT32 PerformanceIndex:7; + UINT32 Reserved1:5; + UINT32 TypicalPowerDissipation:20; + UINT32 TransitionLatency1; + UINT32 TransitionLatency2; + UINT32 Reserved2; +} PAL_PSTATE_INFO_BUFFER; + + +/** + PAL Procedure - PAL_PSTATE_INFO. + + Returns information about the P-states supported by the + processor. It is optional by Itanium processors. The PAL procedure supports + the Static Registers calling convention. It could be called + at physical and Virtual mode. + + @param Index Index of PAL_PSTATE_INFO within the list of PAL + procedures. + @param PStateBuffer 64-bit pointer to a 256-byte buffer + aligned on an 8-byte boundary. See + PAL_PSTATE_INFO_BUFFER above. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + + @return R9 Unsigned integer denoting the number of P-states + supported. The maximum value of this field is 16. + @return R10 Dependency domain information + +**/ +#define PAL_PSTATE_INFO 44 + + +/** + PAL Procedure - PAL_SET_PSTATE. + + To request a processor transition to a given P-state. It is + optional by Itanium processors. The PAL procedure supports the Stacked + Registers calling convention. It could be called at physical + and Virtual mode. + + @param Index Index of PAL_SET_PSTATE within the list of PAL + procedures. + @param PState Unsigned integer denoting the processor + P-state being requested. + @param ForcePState Unsigned integer denoting whether the + P-state change should be forced for the + logical processor. + + @retval 1 Call completed without error, but + transition request was not accepted + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_SET_PSTATE 263 + +/** + PAL Procedure - PAL_SHUTDOWN. + + Put the logical processor into a low power state which can be + exited only by a reset event. It is optional by Itanium processors. The PAL + procedure supports the Static Registers calling convention. It + could be called at physical mode. + + @param Index Index of PAL_SHUTDOWN within the list of PAL + procedures. + @param NotifyPlatform 8-byte aligned physical address + pointer providing details on how to + optionally notify the platform that + the processor is entering a shutdown + state. + + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_SHUTDOWN 45 + +/** + + Layout of PAL_MEMORY_BUFFER.ControlWord + +**/ +typedef struct { + UINT64 Registration:1; + UINT64 ProbeInterrupt:1; + UINT64 Reserved:62; +} PAL_MEMORY_CONTROL_WORD; + +/** + PAL Procedure - PAL_MEMORY_BUFFER. + + Provides cacheable memory to PAL for exclusive use during + runtime. It is optional by Itanium processors. The PAL procedure supports the + Static Registers calling convention. It could be called at + physical mode. + + @param Index Index of PAL_MEMORY_BUFFER within the list of PAL + procedures. + @param BaseAddress Physical address of the memory buffer + allocated for PAL use. + @param AllocSize Unsigned integer denoting the size of the + memory buffer. + @param ControlWord Formatted bit vector that provides control + options for this procedure. See + PAL_MEMORY_CONTROL_WORD above. + + @retval 1 Call has not completed a buffer relocation + due to a pending interrupt + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + + @return R9 Returns the minimum size of the memory buffer + required if the alloc_size input argument was + not large enough. + +**/ +#define PAL_MEMORY_BUFFER 277 + + +/** + PAL Procedure - PAL_VP_CREATE. + + Initializes a new vpd for the operation of a new virtual + processor in the virtual environment. It is optional by Itanium processors. + The PAL procedure supports the Stacked Registers calling + convention. It could be called at Virtual mode. + + @param Index Index of PAL_VP_CREATE within the list of PAL + procedures. + @param Vpd 64-bit host virtual pointer to the Virtual + Processor Descriptor (VPD). + @param HostIva 64-bit host virtual pointer to the host IVT + for the virtual processor + @param OptionalHandler 64-bit non-zero host-virtual pointer + to an optional handler for + virtualization intercepts. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_VP_CREATE 265 + +/** + + Virtual Environment Information Parameter + +**/ +typedef struct { + UINT64 Reserved1:8; + UINT64 Opcode:1; + UINT64 Reserved:53; +} PAL_VP_ENV_INFO_RETURN; + +/** + PAL Procedure - PAL_VP_ENV_INFO. + + Returns the parameters needed to enter a virtual environment. + It is optional by Itanium processors. The PAL procedure supports the Stacked + Registers calling convention. It could be called at Virtual + mode. + + @param Index Index of PAL_VP_ENV_INFO within the list of PAL + procedures. + @param Vpd 64-bit host virtual pointer to the Virtual + Processor Descriptor (VPD). + @param HostIva 64-bit host virtual pointer to the host IVT + for the virtual processor + @param OptionalHandler 64-bit non-zero host-virtual pointer + to an optional handler for + virtualization intercepts. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + + @return R9 Unsigned integer denoting the number of bytes + required by the PAL virtual environment buffer + during PAL_VP_INIT_ENV + @return R10 64-bit vector of virtual environment + information. See PAL_VP_ENV_INFO_RETURN. + + +**/ +#define PAL_VP_ENV_INFO 266 + +/** + PAL Procedure - PAL_VP_EXIT_ENV. + + Allows a logical processor to exit a virtual environment. + It is optional by Itanium processors. The PAL procedure supports the Stacked + Registers calling convention. It could be called at Virtual + mode. + + @param Index Index of PAL_VP_EXIT_ENV within the list of PAL + procedures. + @param Iva Optional 64-bit host virtual pointer to the IVT + when this procedure is done + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_VP_EXIT_ENV 267 + + + +/** + PAL Procedure - PAL_VP_INIT_ENV. + + Allows a logical processor to enter a virtual environment. It + is optional by Itanium processors. The PAL procedure supports the Stacked + Registers calling convention. It could be called at Virtual + mode. + + @param Index Index of PAL_VP_INIT_ENV within the list of PAL + procedures. + @param ConfigOptions 64-bit vector of global configuration + settings. + @param PhysicalBase Host physical base address of a block of + contiguous physical memory for the PAL + virtual environment buffer 1) This + memory area must be allocated by the VMM + and be 4K aligned. The first logical + processor to enter the environment will + initialize the physical block for + virtualization operations. + @param VirtualBase Host virtual base address of the + corresponding physical memory block for + the PAL virtual environment buffer : The + VMM must maintain the host virtual to host + physical data and instruction translations + in TRs for addresses within the allocated + address space. Logical processors in this + virtual environment will use this address + when transitioning to virtual mode + operations. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + + @return R9 Virtualization Service Address - VSA specifies + the virtual base address of the PAL + virtualization services in this virtual + environment. + + +**/ +#define PAL_VP_INIT_ENV 268 + + +/** + PAL Procedure - PAL_VP_REGISTER. + + Register a different host IVT and/or a different optional + virtualization intercept handler for the virtual processor + specified by vpd. It is optional by Itanium processors. The PAL procedure + supports the Stacked Registers calling convention. It could be + called at Virtual mode. + + @param Index Index of PAL_VP_REGISTER within the list of PAL + procedures. + @param Vpd 64-bit host virtual pointer to the Virtual + Processor Descriptor (VPD) host_iva 64-bit host + virtual pointer to the host IVT for the virtual + processor + @param OptionalHandler 64-bit non-zero host-virtual pointer + to an optional handler for + virtualization intercepts. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_VP_REGISTER 269 + + +/** + PAL Procedure - PAL_VP_RESTORE. + + Restores virtual processor state for the specified vpd on the + logical processor. It is optional by Itanium processors. The PAL procedure + supports the Stacked Registers calling convention. It could be + called at Virtual mode. + + @param Index Index of PAL_VP_RESTORE within the list of PAL + procedures. + @param Vpd 64-bit host virtual pointer to the Virtual + Processor Descriptor (VPD) host_iva 64-bit host + virtual pointer to the host IVT for the virtual + processor + @param PalVector Vector specifies PAL procedure + implementation-specific state to be + restored. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_VP_RESTORE 270 + +/** + PAL Procedure - PAL_VP_SAVE. + + Saves virtual processor state for the specified vpd on the + logical processor. It is optional by Itanium processors. The PAL procedure + supports the Stacked Registers calling convention. It could be + called at Virtual mode. + + @param Index Index of PAL_VP_SAVE within the list of PAL + procedures. + @param Vpd 64-bit host virtual pointer to the Virtual + Processor Descriptor (VPD) host_iva 64-bit host + virtual pointer to the host IVT for the virtual + processor + @param PalVector Vector specifies PAL procedure + implementation-specific state to be + restored. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_VP_SAVE 271 + + +/** + PAL Procedure - PAL_VP_TERMINATE. + + Terminates operation for the specified virtual processor. It + is optional by Itanium processors. The PAL procedure supports the Stacked + Registers calling convention. It could be called at Virtual + mode. + + @param Index Index of PAL_VP_TERMINATE within the list of PAL + procedures. + @param Vpd 64-bit host virtual pointer to the Virtual + Processor Descriptor (VPD) + @param Iva Optional 64-bit host virtual pointer to the IVT + when this procedure is done. + + @retval 0 Call completed without error + @retval -1 Unimplemented procedure + @retval -2 Invalid argument + @retval -3 Call completed with error. + @retval -9 Call requires PAL memory buffer. + +**/ +#define PAL_VP_TERMINATE 272 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci.h new file mode 100644 index 0000000..b5916bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci.h @@ -0,0 +1,23 @@ +/** @file + Support for the latest PCI standard. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCI_H_ +#define _PCI_H_ + +#include +#include +#include +#include + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci22.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci22.h new file mode 100644 index 0000000..9f2817c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci22.h @@ -0,0 +1,867 @@ +/** @file + Support for PCI 2.2 standard. + + This file includes the definitions in the following specifications, + PCI Local Bus Specification, 2.2 + PCI-to-PCI Bridge Architecture Specification, Revision 1.2 + PC Card Standard, 8.0 + PCI Power Management Interface Specifiction, Revision 1.2 + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2014 - 2015, Hewlett-Packard Development Company, L.P.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCI22_H_ +#define _PCI22_H_ + +#define PCI_MAX_BUS 255 +#define PCI_MAX_DEVICE 31 +#define PCI_MAX_FUNC 7 + +#pragma pack(1) + +/// +/// Common header region in PCI Configuration Space +/// Section 6.1, PCI Local Bus Specification, 2.2 +/// +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionID; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 LatencyTimer; + UINT8 HeaderType; + UINT8 BIST; +} PCI_DEVICE_INDEPENDENT_REGION; + +/// +/// PCI Device header region in PCI Configuration Space +/// Section 6.1, PCI Local Bus Specification, 2.2 +/// +typedef struct { + UINT32 Bar[6]; + UINT32 CISPtr; + UINT16 SubsystemVendorID; + UINT16 SubsystemID; + UINT32 ExpansionRomBar; + UINT8 CapabilityPtr; + UINT8 Reserved1[3]; + UINT32 Reserved2; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT8 MinGnt; + UINT8 MaxLat; +} PCI_DEVICE_HEADER_TYPE_REGION; + +/// +/// PCI Device Configuration Space +/// Section 6.1, PCI Local Bus Specification, 2.2 +/// +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; +} PCI_TYPE00; + +/// +/// PCI-PCI Bridge header region in PCI Configuration Space +/// Section 3.2, PCI-PCI Bridge Architecture, Version 1.2 +/// +typedef struct { + UINT32 Bar[2]; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32; + UINT32 PrefetchableLimitUpper32; + UINT16 IoBaseUpper16; + UINT16 IoLimitUpper16; + UINT8 CapabilityPtr; + UINT8 Reserved[3]; + UINT32 ExpansionRomBAR; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; +} PCI_BRIDGE_CONTROL_REGISTER; + +/// +/// PCI-to-PCI Bridge Configuration Space +/// Section 3.2, PCI-PCI Bridge Architecture, Version 1.2 +/// +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_BRIDGE_CONTROL_REGISTER Bridge; +} PCI_TYPE01; + +typedef union { + PCI_TYPE00 Device; + PCI_TYPE01 Bridge; +} PCI_TYPE_GENERIC; + +/// +/// CardBus Conroller Configuration Space, +/// Section 4.5.1, PC Card Standard. 8.0 +/// +typedef struct { + UINT32 CardBusSocketReg; ///< Cardus Socket/ExCA Base + UINT8 Cap_Ptr; + UINT8 Reserved; + UINT16 SecondaryStatus; ///< Secondary Status + UINT8 PciBusNumber; ///< PCI Bus Number + UINT8 CardBusBusNumber; ///< CardBus Bus Number + UINT8 SubordinateBusNumber; ///< Subordinate Bus Number + UINT8 CardBusLatencyTimer; ///< CardBus Latency Timer + UINT32 MemoryBase0; ///< Memory Base Register 0 + UINT32 MemoryLimit0; ///< Memory Limit Register 0 + UINT32 MemoryBase1; + UINT32 MemoryLimit1; + UINT32 IoBase0; + UINT32 IoLimit0; ///< I/O Base Register 0 + UINT32 IoBase1; ///< I/O Limit Register 0 + UINT32 IoLimit1; + UINT8 InterruptLine; ///< Interrupt Line + UINT8 InterruptPin; ///< Interrupt Pin + UINT16 BridgeControl; ///< Bridge Control +} PCI_CARDBUS_CONTROL_REGISTER; + +// +// Definitions of PCI class bytes and manipulation macros. +// +#define PCI_CLASS_OLD 0x00 +#define PCI_CLASS_OLD_OTHER 0x00 +#define PCI_CLASS_OLD_VGA 0x01 + +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_MASS_STORAGE_SCSI 0x00 +#define PCI_CLASS_MASS_STORAGE_IDE 0x01 +#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02 +#define PCI_CLASS_MASS_STORAGE_IPI 0x03 +#define PCI_CLASS_MASS_STORAGE_RAID 0x04 +#define PCI_CLASS_MASS_STORAGE_OTHER 0x80 + +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x00 +#define PCI_CLASS_NETWORK_TOKENRING 0x01 +#define PCI_CLASS_NETWORK_FDDI 0x02 +#define PCI_CLASS_NETWORK_ATM 0x03 +#define PCI_CLASS_NETWORK_ISDN 0x04 +#define PCI_CLASS_NETWORK_OTHER 0x80 + +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_VGA 0x00 +#define PCI_IF_VGA_VGA 0x00 +#define PCI_IF_VGA_8514 0x01 +#define PCI_CLASS_DISPLAY_XGA 0x01 +#define PCI_CLASS_DISPLAY_3D 0x02 +#define PCI_CLASS_DISPLAY_OTHER 0x80 + +#define PCI_CLASS_MEDIA 0x04 +#define PCI_CLASS_MEDIA_VIDEO 0x00 +#define PCI_CLASS_MEDIA_AUDIO 0x01 +#define PCI_CLASS_MEDIA_TELEPHONE 0x02 +#define PCI_CLASS_MEDIA_OTHER 0x80 + +#define PCI_CLASS_MEMORY_CONTROLLER 0x05 +#define PCI_CLASS_MEMORY_RAM 0x00 +#define PCI_CLASS_MEMORY_FLASH 0x01 +#define PCI_CLASS_MEMORY_OTHER 0x80 + +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x00 +#define PCI_CLASS_BRIDGE_ISA 0x01 +#define PCI_CLASS_BRIDGE_EISA 0x02 +#define PCI_CLASS_BRIDGE_MCA 0x03 +#define PCI_CLASS_BRIDGE_P2P 0x04 +#define PCI_IF_BRIDGE_P2P 0x00 +#define PCI_IF_BRIDGE_P2P_SUBTRACTIVE 0x01 +#define PCI_CLASS_BRIDGE_PCMCIA 0x05 +#define PCI_CLASS_BRIDGE_NUBUS 0x06 +#define PCI_CLASS_BRIDGE_CARDBUS 0x07 +#define PCI_CLASS_BRIDGE_RACEWAY 0x08 +#define PCI_CLASS_BRIDGE_OTHER 0x80 +#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80 + +#define PCI_CLASS_SCC 0x07 ///< Simple communications controllers +#define PCI_SUBCLASS_SERIAL 0x00 +#define PCI_IF_GENERIC_XT 0x00 +#define PCI_IF_16450 0x01 +#define PCI_IF_16550 0x02 +#define PCI_IF_16650 0x03 +#define PCI_IF_16750 0x04 +#define PCI_IF_16850 0x05 +#define PCI_IF_16950 0x06 +#define PCI_SUBCLASS_PARALLEL 0x01 +#define PCI_IF_PARALLEL_PORT 0x00 +#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01 +#define PCI_IF_ECP_PARALLEL_PORT 0x02 +#define PCI_IF_1284_CONTROLLER 0x03 +#define PCI_IF_1284_DEVICE 0xFE +#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02 +#define PCI_SUBCLASS_MODEM 0x03 +#define PCI_IF_GENERIC_MODEM 0x00 +#define PCI_IF_16450_MODEM 0x01 +#define PCI_IF_16550_MODEM 0x02 +#define PCI_IF_16650_MODEM 0x03 +#define PCI_IF_16750_MODEM 0x04 +#define PCI_SUBCLASS_SCC_OTHER 0x80 + +#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 +#define PCI_SUBCLASS_PIC 0x00 +#define PCI_IF_8259_PIC 0x00 +#define PCI_IF_ISA_PIC 0x01 +#define PCI_IF_EISA_PIC 0x02 +#define PCI_IF_APIC_CONTROLLER 0x10 ///< I/O APIC interrupt controller , 32 bye none-prefectable memory. +#define PCI_IF_APIC_CONTROLLER2 0x20 +#define PCI_SUBCLASS_DMA 0x01 +#define PCI_IF_8237_DMA 0x00 +#define PCI_IF_ISA_DMA 0x01 +#define PCI_IF_EISA_DMA 0x02 +#define PCI_SUBCLASS_TIMER 0x02 +#define PCI_IF_8254_TIMER 0x00 +#define PCI_IF_ISA_TIMER 0x01 +#define PCI_IF_EISA_TIMER 0x02 +#define PCI_SUBCLASS_RTC 0x03 +#define PCI_IF_GENERIC_RTC 0x00 +#define PCI_IF_ISA_RTC 0x01 +#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 ///< HotPlug Controller +#define PCI_SUBCLASS_PERIPHERAL_OTHER 0x80 + +#define PCI_CLASS_INPUT_DEVICE 0x09 +#define PCI_SUBCLASS_KEYBOARD 0x00 +#define PCI_SUBCLASS_PEN 0x01 +#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02 +#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03 +#define PCI_SUBCLASS_GAMEPORT 0x04 +#define PCI_IF_GAMEPORT 0x00 +#define PCI_IF_GAMEPORT1 0x10 +#define PCI_SUBCLASS_INPUT_OTHER 0x80 + +#define PCI_CLASS_DOCKING_STATION 0x0A +#define PCI_SUBCLASS_DOCKING_GENERIC 0x00 +#define PCI_SUBCLASS_DOCKING_OTHER 0x80 + +#define PCI_CLASS_PROCESSOR 0x0B +#define PCI_SUBCLASS_PROC_386 0x00 +#define PCI_SUBCLASS_PROC_486 0x01 +#define PCI_SUBCLASS_PROC_PENTIUM 0x02 +#define PCI_SUBCLASS_PROC_ALPHA 0x10 +#define PCI_SUBCLASS_PROC_POWERPC 0x20 +#define PCI_SUBCLASS_PROC_MIPS 0x30 +#define PCI_SUBCLASS_PROC_CO_PORC 0x40 ///< Co-Processor + +#define PCI_CLASS_SERIAL 0x0C +#define PCI_CLASS_SERIAL_FIREWIRE 0x00 +#define PCI_IF_1394 0x00 +#define PCI_IF_1394_OPEN_HCI 0x10 +#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01 +#define PCI_CLASS_SERIAL_SSA 0x02 +#define PCI_CLASS_SERIAL_USB 0x03 +#define PCI_IF_UHCI 0x00 +#define PCI_IF_OHCI 0x10 +#define PCI_IF_USB_OTHER 0x80 +#define PCI_IF_USB_DEVICE 0xFE +#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04 +#define PCI_CLASS_SERIAL_SMB 0x05 + +#define PCI_CLASS_WIRELESS 0x0D +#define PCI_SUBCLASS_IRDA 0x00 +#define PCI_SUBCLASS_IR 0x01 +#define PCI_SUBCLASS_RF 0x10 +#define PCI_SUBCLASS_WIRELESS_OTHER 0x80 + +#define PCI_CLASS_INTELLIGENT_IO 0x0E + +#define PCI_CLASS_SATELLITE 0x0F +#define PCI_SUBCLASS_TV 0x01 +#define PCI_SUBCLASS_AUDIO 0x02 +#define PCI_SUBCLASS_VOICE 0x03 +#define PCI_SUBCLASS_DATA 0x04 + +#define PCI_SECURITY_CONTROLLER 0x10 ///< Encryption and decryption controller +#define PCI_SUBCLASS_NET_COMPUT 0x00 +#define PCI_SUBCLASS_ENTERTAINMENT 0x10 +#define PCI_SUBCLASS_SECURITY_OTHER 0x80 + +#define PCI_CLASS_DPIO 0x11 +#define PCI_SUBCLASS_DPIO 0x00 +#define PCI_SUBCLASS_DPIO_OTHER 0x80 + +/** + Macro that checks whether the Base Class code of device matched. + + @param _p Specified device. + @param c Base Class code needs matching. + + @retval TRUE Base Class code matches the specified device. + @retval FALSE Base Class code doesn't match the specified device. + +**/ +#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c)) +/** + Macro that checks whether the Base Class code and Sub-Class code of device matched. + + @param _p Specified device. + @param c Base Class code needs matching. + @param s Sub-Class code needs matching. + + @retval TRUE Base Class code and Sub-Class code match the specified device. + @retval FALSE Base Class code and Sub-Class code don't match the specified device. + +**/ +#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s))) +/** + Macro that checks whether the Base Class code, Sub-Class code and Interface code of device matched. + + @param _p Specified device. + @param c Base Class code needs matching. + @param s Sub-Class code needs matching. + @param p Interface code needs matching. + + @retval TRUE Base Class code, Sub-Class code and Interface code match the specified device. + @retval FALSE Base Class code, Sub-Class code and Interface code don't match the specified device. + +**/ +#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p))) + +/** + Macro that checks whether device is a display controller. + + @param _p Specified device. + + @retval TRUE Device is a display controller. + @retval FALSE Device is not a display controller. + +**/ +#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY) +/** + Macro that checks whether device is a VGA-compatible controller. + + @param _p Specified device. + + @retval TRUE Device is a VGA-compatible controller. + @retval FALSE Device is not a VGA-compatible controller. + +**/ +#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, PCI_IF_VGA_VGA) +/** + Macro that checks whether device is an 8514-compatible controller. + + @param _p Specified device. + + @retval TRUE Device is an 8514-compatible controller. + @retval FALSE Device is not an 8514-compatible controller. + +**/ +#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, PCI_IF_VGA_8514) +/** + Macro that checks whether device is built before the Class Code field was defined. + + @param _p Specified device. + + @retval TRUE Device is an old device. + @retval FALSE Device is not an old device. + +**/ +#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD) +/** + Macro that checks whether device is a VGA-compatible device built before the Class Code field was defined. + + @param _p Specified device. + + @retval TRUE Device is an old VGA-compatible device. + @retval FALSE Device is not an old VGA-compatible device. + +**/ +#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) +/** + Macro that checks whether device is an IDE controller. + + @param _p Specified device. + + @retval TRUE Device is an IDE controller. + @retval FALSE Device is not an IDE controller. + +**/ +#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE) +/** + Macro that checks whether device is a SCSI bus controller. + + @param _p Specified device. + + @retval TRUE Device is a SCSI bus controller. + @retval FALSE Device is not a SCSI bus controller. + +**/ +#define IS_PCI_SCSI(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI) +/** + Macro that checks whether device is a RAID controller. + + @param _p Specified device. + + @retval TRUE Device is a RAID controller. + @retval FALSE Device is not a RAID controller. + +**/ +#define IS_PCI_RAID(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID) +/** + Macro that checks whether device is an ISA bridge. + + @param _p Specified device. + + @retval TRUE Device is an ISA bridge. + @retval FALSE Device is not an ISA bridge. + +**/ +#define IS_PCI_LPC(_p) IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA) +/** + Macro that checks whether device is a PCI-to-PCI bridge. + + @param _p Specified device. + + @retval TRUE Device is a PCI-to-PCI bridge. + @retval FALSE Device is not a PCI-to-PCI bridge. + +**/ +#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, PCI_IF_BRIDGE_P2P) +/** + Macro that checks whether device is a Subtractive Decode PCI-to-PCI bridge. + + @param _p Specified device. + + @retval TRUE Device is a Subtractive Decode PCI-to-PCI bridge. + @retval FALSE Device is not a Subtractive Decode PCI-to-PCI bridge. + +**/ +#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, PCI_IF_BRIDGE_P2P_SUBTRACTIVE) +/** + Macro that checks whether device is a 16550-compatible serial controller. + + @param _p Specified device. + + @retval TRUE Device is a 16550-compatible serial controller. + @retval FALSE Device is not a 16550-compatible serial controller. + +**/ +#define IS_PCI_16550_SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550) +/** + Macro that checks whether device is a Universal Serial Bus controller. + + @param _p Specified device. + + @retval TRUE Device is a Universal Serial Bus controller. + @retval FALSE Device is not a Universal Serial Bus controller. + +**/ +#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB) + +// +// the definition of Header Type +// +#define HEADER_TYPE_DEVICE 0x00 +#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 +#define HEADER_TYPE_CARDBUS_BRIDGE 0x02 +#define HEADER_TYPE_MULTI_FUNCTION 0x80 +// +// Mask of Header type +// +#define HEADER_LAYOUT_CODE 0x7f +/** + Macro that checks whether device is a PCI-PCI bridge. + + @param _p Specified device. + + @retval TRUE Device is a PCI-PCI bridge. + @retval FALSE Device is not a PCI-PCI bridge. + +**/ +#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE)) +/** + Macro that checks whether device is a CardBus bridge. + + @param _p Specified device. + + @retval TRUE Device is a CardBus bridge. + @retval FALSE Device is not a CardBus bridge. + +**/ +#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) +/** + Macro that checks whether device is a multiple functions device. + + @param _p Specified device. + + @retval TRUE Device is a multiple functions device. + @retval FALSE Device is not a multiple functions device. + +**/ +#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) + +/// +/// Rom Base Address in Bridge, defined in PCI-to-PCI Bridge Architecure Specification, +/// +#define PCI_BRIDGE_ROMBAR 0x38 + +#define PCI_MAX_BAR 0x0006 +#define PCI_MAX_CONFIG_OFFSET 0x0100 + +#define PCI_VENDOR_ID_OFFSET 0x00 +#define PCI_DEVICE_ID_OFFSET 0x02 +#define PCI_COMMAND_OFFSET 0x04 +#define PCI_PRIMARY_STATUS_OFFSET 0x06 +#define PCI_REVISION_ID_OFFSET 0x08 +#define PCI_CLASSCODE_OFFSET 0x09 +#define PCI_CACHELINE_SIZE_OFFSET 0x0C +#define PCI_LATENCY_TIMER_OFFSET 0x0D +#define PCI_HEADER_TYPE_OFFSET 0x0E +#define PCI_BIST_OFFSET 0x0F +#define PCI_BASE_ADDRESSREG_OFFSET 0x10 +#define PCI_CARDBUS_CIS_OFFSET 0x28 +#define PCI_SVID_OFFSET 0x2C ///< SubSystem Vendor id +#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C +#define PCI_SID_OFFSET 0x2E ///< SubSystem ID +#define PCI_SUBSYSTEM_ID_OFFSET 0x2E +#define PCI_EXPANSION_ROM_BASE 0x30 +#define PCI_CAPBILITY_POINTER_OFFSET 0x34 +#define PCI_INT_LINE_OFFSET 0x3C ///< Interrupt Line Register +#define PCI_INT_PIN_OFFSET 0x3D ///< Interrupt Pin Register +#define PCI_MAXGNT_OFFSET 0x3E ///< Max Grant Register +#define PCI_MAXLAT_OFFSET 0x3F ///< Max Latency Register + +// +// defined in PCI-to-PCI Bridge Architecture Specification +// +#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18 +#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19 +#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a +#define PCI_BRIDGE_SECONDARY_LATENCY_TIMER_OFFSET 0x1b +#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E +#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E + +/// +/// Interrupt Line "Unknown" or "No connection" value defined for x86 based system +/// +#define PCI_INT_LINE_UNKNOWN 0xFF + +/// +/// PCI Access Data Format +/// +typedef union { + struct { + UINT32 Reg : 8; + UINT32 Func : 3; + UINT32 Dev : 5; + UINT32 Bus : 8; + UINT32 Reserved : 7; + UINT32 Enable : 1; + } Bits; + UINT32 Uint32; +} PCI_CONFIG_ACCESS_CF8; + +#pragma pack() + +#define EFI_PCI_COMMAND_IO_SPACE BIT0 ///< 0x0001 +#define EFI_PCI_COMMAND_MEMORY_SPACE BIT1 ///< 0x0002 +#define EFI_PCI_COMMAND_BUS_MASTER BIT2 ///< 0x0004 +#define EFI_PCI_COMMAND_SPECIAL_CYCLE BIT3 ///< 0x0008 +#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE BIT4 ///< 0x0010 +#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP BIT5 ///< 0x0020 +#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND BIT6 ///< 0x0040 +#define EFI_PCI_COMMAND_STEPPING_CONTROL BIT7 ///< 0x0080 +#define EFI_PCI_COMMAND_SERR BIT8 ///< 0x0100 +#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK BIT9 ///< 0x0200 + +// +// defined in PCI-to-PCI Bridge Architecture Specification +// +#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE BIT0 ///< 0x0001 +#define EFI_PCI_BRIDGE_CONTROL_SERR BIT1 ///< 0x0002 +#define EFI_PCI_BRIDGE_CONTROL_ISA BIT2 ///< 0x0004 +#define EFI_PCI_BRIDGE_CONTROL_VGA BIT3 ///< 0x0008 +#define EFI_PCI_BRIDGE_CONTROL_VGA_16 BIT4 ///< 0x0010 +#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT BIT5 ///< 0x0020 +#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS BIT6 ///< 0x0040 +#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK BIT7 ///< 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER BIT8 ///< 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER BIT9 ///< 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS BIT10 ///< 0x0400 +#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR BIT11 ///< 0x0800 + +// +// Following are the PCI-CARDBUS bridge control bit, defined in PC Card Standard +// +#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE BIT7 ///< 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE BIT8 ///< 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE BIT9 ///< 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE BIT10 ///< 0x0400 + +// +// Following are the PCI status control bit +// +#define EFI_PCI_STATUS_CAPABILITY BIT4 ///< 0x0010 +#define EFI_PCI_STATUS_66MZ_CAPABLE BIT5 ///< 0x0020 +#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE BIT7 ///< 0x0080 +#define EFI_PCI_MASTER_DATA_PARITY_ERROR BIT8 ///< 0x0100 + +/// +/// defined in PC Card Standard +/// +#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14 + +#pragma pack(1) +// +// PCI Capability List IDs and records +// +#define EFI_PCI_CAPABILITY_ID_PMI 0x01 +#define EFI_PCI_CAPABILITY_ID_AGP 0x02 +#define EFI_PCI_CAPABILITY_ID_VPD 0x03 +#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04 +#define EFI_PCI_CAPABILITY_ID_MSI 0x05 +#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06 +#define EFI_PCI_CAPABILITY_ID_SHPC 0x0C + +/// +/// Capabilities List Header +/// Section 6.7, PCI Local Bus Specification, 2.2 +/// +typedef struct { + UINT8 CapabilityID; + UINT8 NextItemPtr; +} EFI_PCI_CAPABILITY_HDR; + +/// +/// PMC - Power Management Capabilities +/// Section 3.2.3, PCI Power Management Interface Specifiction, Revision 1.2 +/// +typedef union { + struct { + UINT16 Version : 3; + UINT16 PmeClock : 1; + UINT16 Reserved : 1; + UINT16 DeviceSpecificInitialization : 1; + UINT16 AuxCurrent : 3; + UINT16 D1Support : 1; + UINT16 D2Support : 1; + UINT16 PmeSupport : 5; + } Bits; + UINT16 Data; +} EFI_PCI_PMC; + +#define EFI_PCI_PMC_D3_COLD_MASK (BIT15) + +/// +/// PMCSR - Power Management Control/Status +/// Section 3.2.4, PCI Power Management Interface Specifiction, Revision 1.2 +/// +typedef union { + struct { + UINT16 PowerState : 2; + UINT16 ReservedForPciExpress : 1; + UINT16 NoSoftReset : 1; + UINT16 Reserved : 4; + UINT16 PmeEnable : 1; + UINT16 DataSelect : 4; + UINT16 DataScale : 2; + UINT16 PmeStatus : 1; + } Bits; + UINT16 Data; +} EFI_PCI_PMCSR; + +#define PCI_POWER_STATE_D0 0 +#define PCI_POWER_STATE_D1 1 +#define PCI_POWER_STATE_D2 2 +#define PCI_POWER_STATE_D3_HOT 3 + +/// +/// PMCSR_BSE - PMCSR PCI-to-PCI Bridge Support Extensions +/// Section 3.2.5, PCI Power Management Interface Specifiction, Revision 1.2 +/// +typedef union { + struct { + UINT8 Reserved : 6; + UINT8 B2B3 : 1; + UINT8 BusPowerClockControl : 1; + } Bits; + UINT8 Uint8; +} EFI_PCI_PMCSR_BSE; + +/// +/// Power Management Register Block Definition +/// Section 3.2, PCI Power Management Interface Specifiction, Revision 1.2 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + EFI_PCI_PMC PMC; + EFI_PCI_PMCSR PMCSR; + EFI_PCI_PMCSR_BSE BridgeExtention; + UINT8 Data; +} EFI_PCI_CAPABILITY_PMI; + +/// +/// A.G.P Capability +/// Section 6.1.4, Accelerated Graphics Port Interface Specification, Revision 1.0 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 Rev; + UINT8 Reserved; + UINT32 Status; + UINT32 Command; +} EFI_PCI_CAPABILITY_AGP; + +/// +/// VPD Capability Structure +/// Appendix I, PCI Local Bus Specification, 2.2 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 AddrReg; + UINT32 DataReg; +} EFI_PCI_CAPABILITY_VPD; + +/// +/// Slot Numbering Capabilities Register +/// Section 3.2.6, PCI-to-PCI Bridge Architeture Specification, Revision 1.2 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 ExpnsSlotReg; + UINT8 ChassisNo; +} EFI_PCI_CAPABILITY_SLOTID; + +/// +/// Message Capability Structure for 32-bit Message Address +/// Section 6.8.1, PCI Local Bus Specification, 2.2 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrReg; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI32; + +/// +/// Message Capability Structure for 64-bit Message Address +/// Section 6.8.1, PCI Local Bus Specification, 2.2 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrRegLsdw; + UINT32 MsgAddrRegMsdw; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI64; + +/// +/// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG, +/// CompactPCI Hot Swap Specification PICMG 2.1, R1.0 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + /// + /// not finished - fields need to go here + /// +} EFI_PCI_CAPABILITY_HOTPLUG; + +#define PCI_BAR_IDX0 0x00 +#define PCI_BAR_IDX1 0x01 +#define PCI_BAR_IDX2 0x02 +#define PCI_BAR_IDX3 0x03 +#define PCI_BAR_IDX4 0x04 +#define PCI_BAR_IDX5 0x05 + +/// +/// EFI PCI Option ROM definitions +/// +#define EFI_ROOT_BRIDGE_LIST 'eprb' +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 ///< defined in UEFI Spec. + +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#define PCI_DATA_STRUCTURE_SIGNATURE SIGNATURE_32 ('P', 'C', 'I', 'R') +#define PCI_CODE_TYPE_PCAT_IMAGE 0x00 +#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001 ///< defined in UEFI spec. + +/// +/// Standard PCI Expansion ROM Header +/// Section 13.4.2, Unified Extensible Firmware Interface Specification, Version 2.1 +/// +typedef struct { + UINT16 Signature; ///< 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; + +/// +/// Legacy ROM Header Extensions +/// Section 6.3.3.1, PCI Local Bus Specification, 2.2 +/// +typedef struct { + UINT16 Signature; ///< 0xaa55 + UINT8 Size512; + UINT8 InitEntryPoint[3]; + UINT8 Reserved[0x12]; + UINT16 PcirOffset; +} EFI_LEGACY_EXPANSION_ROM_HEADER; + +/// +/// PCI Data Structure Format +/// Section 6.3.1.2, PCI Local Bus Specification, 2.2 +/// +typedef struct { + UINT32 Signature; ///< "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} PCI_DATA_STRUCTURE; + +/// +/// EFI PCI Expansion ROM Header +/// Section 13.4.2, Unified Extensible Firmware Interface Specification, Version 2.1 +/// +typedef struct { + UINT16 Signature; ///< 0xaa55 + UINT16 InitializationSize; + UINT32 EfiSignature; ///< 0x0EF1 + UINT16 EfiSubsystem; + UINT16 EfiMachineType; + UINT16 CompressionType; + UINT8 Reserved[8]; + UINT16 EfiImageHeaderOffset; + UINT16 PcirOffset; +} EFI_PCI_EXPANSION_ROM_HEADER; + +typedef union { + UINT8 *Raw; + PCI_EXPANSION_ROM_HEADER *Generic; + EFI_PCI_EXPANSION_ROM_HEADER *Efi; + EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt; +} EFI_PCI_ROM_HEADER; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci23.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci23.h new file mode 100644 index 0000000..fa19e92 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci23.h @@ -0,0 +1,133 @@ +/** @file + Support for PCI 2.3 standard. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCI23_H_ +#define _PCI23_H_ + +#include + +/// +/// PCI_CLASS_MASS_STORAGE, Base Class 01h. +/// +///@{ +#define PCI_CLASS_MASS_STORAGE_ATA 0x05 +#define PCI_IF_MASS_STORAGE_SINGLE_DMA 0x20 +#define PCI_IF_MASS_STORAGE_CHAINED_DMA 0x30 +///@} + +/// +/// PCI_CLASS_NETWORK, Base Class 02h. +/// +///@{ +#define PCI_CLASS_NETWORK_WORLDFIP 0x05 +#define PCI_CLASS_NETWORK_PICMG_MULTI_COMPUTING 0x06 +///@} + +/// +/// PCI_CLASS_BRIDGE, Base Class 06h. +/// +///@{ +#define PCI_CLASS_BRIDGE_SEMI_TRANSPARENT_P2P 0x09 +#define PCI_IF_BRIDGE_SEMI_TRANSPARENT_P2P_PRIMARY 0x40 +#define PCI_IF_BRIDGE_SEMI_TRANSPARENT_P2P_SECONDARY 0x80 +#define PCI_CLASS_BRIDGE_INFINIBAND_TO_PCI 0x0A +///@} + +/// +/// PCI_CLASS_SCC, Base Class 07h. +/// +///@{ +#define PCI_SUBCLASS_GPIB 0x04 +#define PCI_SUBCLASS_SMART_CARD 0x05 +///@} + +/// +/// PCI_CLASS_SERIAL, Base Class 0Ch. +/// +///@{ +#define PCI_IF_EHCI 0x20 +#define PCI_CLASS_SERIAL_IB 0x06 +#define PCI_CLASS_SERIAL_IPMI 0x07 +#define PCI_IF_IPMI_SMIC 0x00 +#define PCI_IF_IPMI_KCS 0x01 ///< Keyboard Controller Style +#define PCI_IF_IPMI_BT 0x02 ///< Block Transfer +#define PCI_CLASS_SERIAL_SERCOS 0x08 +#define PCI_CLASS_SERIAL_CANBUS 0x09 +///@} + +/// +/// PCI_CLASS_WIRELESS, Base Class 0Dh. +/// +///@{ +#define PCI_SUBCLASS_BLUETOOTH 0x11 +#define PCI_SUBCLASS_BROADBAND 0x12 +///@} + +/// +/// PCI_CLASS_DPIO, Base Class 11h. +/// +///@{ +#define PCI_SUBCLASS_PERFORMANCE_COUNTERS 0x01 +#define PCI_SUBCLASS_COMMUNICATION_SYNCHRONIZATION 0x10 +#define PCI_SUBCLASS_MANAGEMENT_CARD 0x20 +///@} + +/// +/// defined in PCI Express Spec. +/// +#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000 + +/// +/// PCI Capability List IDs and records. +/// +#define EFI_PCI_CAPABILITY_ID_PCIX 0x07 +#define EFI_PCI_CAPABILITY_ID_VENDOR 0x09 + +#pragma pack(1) +/// +/// PCI-X Capabilities List, +/// Section 7.2, PCI-X Addendum to the PCI Local Bus Specification, Revision 1.0b. +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 CommandReg; + UINT32 StatusReg; +} EFI_PCI_CAPABILITY_PCIX; + +/// +/// PCI-X Bridge Capabilities List, +/// Section 8.6.2, PCI-X Addendum to the PCI Local Bus Specification, Revision 1.0b. +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 SecStatusReg; + UINT32 StatusReg; + UINT32 SplitTransCtrlRegUp; + UINT32 SplitTransCtrlRegDn; +} EFI_PCI_CAPABILITY_PCIX_BRDG; + +/// +/// Vendor Specific Capability Header +/// Table H-1: Capability IDs, PCI Local Bus Specification, 2.3 +/// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 Length; +} EFI_PCI_CAPABILITY_VENDOR_HDR; + +#pragma pack() + +#define PCI_CODE_TYPE_EFI_IMAGE 0x03 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci30.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci30.h new file mode 100644 index 0000000..63c36b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Pci30.h @@ -0,0 +1,79 @@ +/** @file + Support for PCI 3.0 standard. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI30_H__ +#define __PCI30_H__ + + +#include + +/// +/// PCI_CLASS_MASS_STORAGE, Base Class 01h. +/// +///@{ +#define PCI_CLASS_MASS_STORAGE_SATADPA 0x06 +#define PCI_IF_MASS_STORAGE_SATA 0x00 +#define PCI_IF_MASS_STORAGE_AHCI 0x01 +///@} + +/// +/// PCI_CLASS_WIRELESS, Base Class 0Dh. +/// +///@{ +#define PCI_SUBCLASS_ETHERNET_80211A 0x20 +#define PCI_SUBCLASS_ETHERNET_80211B 0x21 +///@} + +/** + Macro that checks whether device is a SATA controller. + + @param _p Specified device. + + @retval TRUE Device is a SATA controller. + @retval FALSE Device is not a SATA controller. + +**/ +#define IS_PCI_SATADPA(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SATADPA) + +/// +/// PCI Capability List IDs and records +/// +#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 + +#pragma pack(1) + +/// +/// PCI Data Structure Format +/// Section 5.1.2, PCI Firmware Specification, Revision 3.0 +/// +typedef struct { + UINT32 Signature; ///< "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 DeviceListOffset; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 MaxRuntimeImageLength; + UINT16 ConfigUtilityCodeHeaderOffset; + UINT16 DMTFCLPEntryPointOffset; +} PCI_3_0_DATA_STRUCTURE; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciCodeId.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciCodeId.h new file mode 100644 index 0000000..3b506f0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciCodeId.h @@ -0,0 +1,100 @@ +/** @file + The file lists the PCI class codes only defined in PCI code and ID assignment specification + revision 1.3. + + Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_CODE_ID_H__ +#define __PCI_CODE_ID_H__ + + +/// +/// PCI_CLASS_MASS_STORAGE, Base Class 01h. +/// +///@{ +#define PCI_IF_MASS_STORAGE_SCSI_VENDOR_SPECIFIC 0x00 +#define PCI_IF_MASS_STORAGE_SCSI_DEVICE_PQI 0x11 +#define PCI_IF_MASS_STORAGE_SCSI_CONTROLLER_PQI 0x12 +#define PCI_IF_MASS_STORAGE_SCSI_DEVICE_CONTROLLER_PQI 0x13 +#define PCI_IF_MASS_STORAGE_SCSI_DEVICE_NVM_EXPRESS 0x21 +#define PCI_IF_MASS_STORAGE_SATA_SERIAL_BUS 0x02 +#define PCI_CLASS_MASS_STORAGE_SAS 0x07 +#define PCI_IF_MASS_STORAGE_SAS 0x00 +#define PCI_IF_MASS_STORAGE_SAS_SERIAL_BUS 0x01 +#define PCI_CLASS_MASS_STORAGE_SOLID_STATE 0x08 +#define PCI_IF_MASS_STORAGE_SOLID_STATE 0x00 +#define PCI_IF_MASS_STORAGE_SOLID_STATE_NVMHCI 0x01 +#define PCI_IF_MASS_STORAGE_SOLID_STATE_ENTERPRISE_NVMHCI 0x02 +///@} + +/// +/// PCI_CLASS_NETWORK, Base Class 02h. +/// +///@{ +#define PCI_CLASS_NETWORK_INFINIBAND 0x07 +///@} + +/// +/// PCI_CLASS_MEDIA, Base Class 04h. +/// +///@{ +#define PCI_CLASS_MEDIA_MIXED_MODE 0x03 +///@} + +/// +/// PCI_CLASS_BRIDGE, Base Class 06h. +/// +///@{ +#define PCI_CLASS_BRIDGE_ADVANCED_SWITCHING_TO_PCI 0x0B +#define PCI_IF_BRIDGE_ADVANCED_SWITCHING_TO_PCI_CUSTOM 0x00 +#define PCI_IF_BRIDGE_ADVANCED_SWITCHING_TO_PCI_ASI_SIG 0x01 +///@} + +/// +/// PCI_CLASS_SYSTEM_PERIPHERAL, Base Class 08h. +/// +///@{ +#define PCI_IF_HPET 0x03 +#define PCI_SUBCLASS_SD_HOST_CONTROLLER 0x05 +#define PCI_SUBCLASS_IOMMU 0x06 +///@} + +/// +/// PCI_CLASS_PROCESSOR, Base Class 0Bh. +/// +///@{ +#define PCI_SUBCLASS_PROC_OTHER 0x80 +///@} + +/// +/// PCI_CLASS_SERIAL, Base Class 0Ch. +/// +///@{ +#define PCI_IF_XHCI 0x30 +#define PCI_CLASS_SERIAL_OTHER 0x80 +///@} + +/// +/// PCI_CLASS_SATELLITE, Base Class 0Fh. +/// +///@{ +#define PCI_SUBCLASS_SATELLITE_OTHER 0x80 +///@} + +/// +/// PCI_CLASS_PROCESSING_ACCELERATOR, Base Class 12h. +/// +///@{ +#define PCI_CLASS_PROCESSING_ACCELERATOR 0x12 +///@} + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress21.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress21.h new file mode 100644 index 0000000..ef4b85d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress21.h @@ -0,0 +1,668 @@ +/** @file + Support for the latest PCI standard. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCIEXPRESS21_H_ +#define _PCIEXPRESS21_H_ + +#include + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + ECAM (Enhanced Configuration Access Mechanism) address. The unused upper bits + of Bus, Device, Function and Register are stripped prior to the generation of + the address. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..4095. + + @return The encode ECAM address. + +**/ +#define PCI_ECAM_ADDRESS(Bus,Device,Function,Offset) \ + (((Offset) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + +#pragma pack(1) +/// +/// PCI Express Capability Structure +/// +typedef union { + struct { + UINT16 Version : 4; + UINT16 DevicePortType : 4; + UINT16 SlotImplemented : 1; + UINT16 InterruptMessageNumber : 5; + UINT16 Undefined : 1; + UINT16 Reserved : 1; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_CAPABILITY; + +#define PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT 0 +#define PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT 1 +#define PCIE_DEVICE_PORT_TYPE_ROOT_PORT 4 +#define PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT 5 +#define PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT 6 +#define PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE 7 +#define PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE 8 +#define PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT 9 +#define PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR 10 + +typedef union { + struct { + UINT32 MaxPayloadSize : 3; + UINT32 PhantomFunctions : 2; + UINT32 ExtendedTagField : 1; + UINT32 EndpointL0sAcceptableLatency : 3; + UINT32 EndpointL1AcceptableLatency : 3; + UINT32 Undefined : 3; + UINT32 RoleBasedErrorReporting : 1; + UINT32 Reserved : 2; + UINT32 CapturedSlotPowerLimitValue : 8; + UINT32 CapturedSlotPowerLimitScale : 2; + UINT32 FunctionLevelReset : 1; + UINT32 Reserved2 : 3; + } Bits; + UINT32 Uint32; +} PCI_REG_PCIE_DEVICE_CAPABILITY; + +typedef union { + struct { + UINT16 CorrectableError : 1; + UINT16 NonFatalError : 1; + UINT16 FatalError : 1; + UINT16 UnsupportedRequest : 1; + UINT16 RelaxedOrdering : 1; + UINT16 MaxPayloadSize : 3; + UINT16 ExtendedTagField : 1; + UINT16 PhantomFunctions : 1; + UINT16 AuxPower : 1; + UINT16 NoSnoop : 1; + UINT16 MaxReadRequestSize : 3; + UINT16 BridgeConfigurationRetryOrFunctionLevelReset : 1; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_DEVICE_CONTROL; + +typedef union { + struct { + UINT16 CorrectableError : 1; + UINT16 NonFatalError : 1; + UINT16 FatalError : 1; + UINT16 UnsupportedRequest : 1; + UINT16 AuxPower : 1; + UINT16 TransactionsPending : 1; + UINT16 Reserved : 10; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_DEVICE_STATUS; + +typedef union { + struct { + UINT32 MaxLinkSpeed : 4; + UINT32 MaxLinkWidth : 6; + UINT32 Aspm : 2; + UINT32 L0sExitLatency : 3; + UINT32 L1ExitLatency : 3; + UINT32 ClockPowerManagement : 1; + UINT32 SurpriseDownError : 1; + UINT32 DataLinkLayerLinkActive : 1; + UINT32 LinkBandwidthNotification : 1; + UINT32 AspmOptionalityCompliance : 1; + UINT32 Reserved : 1; + UINT32 PortNumber : 8; + } Bits; + UINT32 Uint32; +} PCI_REG_PCIE_LINK_CAPABILITY; + +#define PCIE_LINK_ASPM_L0S BIT0 +#define PCIE_LINK_ASPM_L1 BIT1 + +typedef union { + struct { + UINT16 AspmControl : 2; + UINT16 Reserved : 1; + UINT16 ReadCompletionBoundary : 1; + UINT16 LinkDisable : 1; + UINT16 RetrainLink : 1; + UINT16 CommonClockConfiguration : 1; + UINT16 ExtendedSynch : 1; + UINT16 ClockPowerManagement : 1; + UINT16 HardwareAutonomousWidthDisable : 1; + UINT16 LinkBandwidthManagementInterrupt : 1; + UINT16 LinkAutonomousBandwidthInterrupt : 1; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_LINK_CONTROL; + +typedef union { + struct { + UINT16 CurrentLinkSpeed : 4; + UINT16 NegotiatedLinkWidth : 6; + UINT16 Undefined : 1; + UINT16 LinkTraining : 1; + UINT16 SlotClockConfiguration : 1; + UINT16 DataLinkLayerLinkActive : 1; + UINT16 LinkBandwidthManagement : 1; + UINT16 LinkAutonomousBandwidth : 1; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_LINK_STATUS; + +typedef union { + struct { + UINT32 AttentionButton : 1; + UINT32 PowerController : 1; + UINT32 MrlSensor : 1; + UINT32 AttentionIndicator : 1; + UINT32 PowerIndicator : 1; + UINT32 HotPlugSurprise : 1; + UINT32 HotPlugCapable : 1; + UINT32 SlotPowerLimitValue : 8; + UINT32 SlotPowerLimitScale : 2; + UINT32 ElectromechanicalInterlock : 1; + UINT32 NoCommandCompleted : 1; + UINT32 PhysicalSlotNumber : 13; + } Bits; + UINT32 Uint32; +} PCI_REG_PCIE_SLOT_CAPABILITY; + +typedef union { + struct { + UINT16 AttentionButtonPressed : 1; + UINT16 PowerFaultDetected : 1; + UINT16 MrlSensorChanged : 1; + UINT16 PresenceDetectChanged : 1; + UINT16 CommandCompletedInterrupt : 1; + UINT16 HotPlugInterrupt : 1; + UINT16 AttentionIndicator : 2; + UINT16 PowerIndicator : 2; + UINT16 PowerController : 1; + UINT16 ElectromechanicalInterlock : 1; + UINT16 DataLinkLayerStateChanged : 1; + UINT16 Reserved : 3; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_SLOT_CONTROL; + +typedef union { + struct { + UINT16 AttentionButtonPressed : 1; + UINT16 PowerFaultDetected : 1; + UINT16 MrlSensorChanged : 1; + UINT16 PresenceDetectChanged : 1; + UINT16 CommandCompleted : 1; + UINT16 MrlSensor : 1; + UINT16 PresenceDetect : 1; + UINT16 ElectromechanicalInterlock : 1; + UINT16 DataLinkLayerStateChanged : 1; + UINT16 Reserved : 7; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_SLOT_STATUS; + +typedef union { + struct { + UINT16 SystemErrorOnCorrectableError : 1; + UINT16 SystemErrorOnNonFatalError : 1; + UINT16 SystemErrorOnFatalError : 1; + UINT16 PmeInterrupt : 1; + UINT16 CrsSoftwareVisibility : 1; + UINT16 Reserved : 11; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_ROOT_CONTROL; + +typedef union { + struct { + UINT16 CrsSoftwareVisibility : 1; + UINT16 Reserved : 15; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_ROOT_CAPABILITY; + +typedef union { + struct { + UINT32 PmeRequesterId : 16; + UINT32 PmeStatus : 1; + UINT32 PmePending : 1; + UINT32 Reserved : 14; + } Bits; + UINT32 Uint32; +} PCI_REG_PCIE_ROOT_STATUS; + +typedef union { + struct { + UINT32 CompletionTimeoutRanges : 4; + UINT32 CompletionTimeoutDisable : 1; + UINT32 AriForwarding : 1; + UINT32 AtomicOpRouting : 1; + UINT32 AtomicOp32Completer : 1; + UINT32 AtomicOp64Completer : 1; + UINT32 Cas128Completer : 1; + UINT32 NoRoEnabledPrPrPassing : 1; + UINT32 LtrMechanism : 1; + UINT32 TphCompleter : 2; + UINT32 Reserved : 4; + UINT32 Obff : 2; + UINT32 ExtendedFmtField : 1; + UINT32 EndEndTlpPrefix : 1; + UINT32 MaxEndEndTlpPrefixes : 2; + UINT32 Reserved2 : 8; + } Bits; + UINT32 Uint32; +} PCI_REG_PCIE_DEVICE_CAPABILITY2; + +#define PCIE_DEVICE_CAPABILITY_OBFF_MESSAGE BIT0 +#define PCIE_DEVICE_CAPABILITY_OBFF_WAKE BIT1 + +typedef union { + struct { + UINT16 CompletionTimeoutValue : 4; + UINT16 CompletionTimeoutDisable : 1; + UINT16 AriForwarding : 1; + UINT16 AtomicOpRequester : 1; + UINT16 AtomicOpEgressBlocking : 1; + UINT16 IdoRequest : 1; + UINT16 IdoCompletion : 1; + UINT16 LtrMechanism : 2; + UINT16 Reserved : 2; + UINT16 Obff : 2; + UINT16 EndEndTlpPrefixBlocking : 1; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_DEVICE_CONTROL2; + +#define PCIE_COMPLETION_TIMEOUT_50US_50MS 0 +#define PCIE_COMPLETION_TIMEOUT_50US_100US 1 +#define PCIE_COMPLETION_TIMEOUT_1MS_10MS 2 +#define PCIE_COMPLETION_TIMEOUT_16MS_55MS 5 +#define PCIE_COMPLETION_TIMEOUT_65MS_210MS 6 +#define PCIE_COMPLETION_TIMEOUT_260MS_900MS 9 +#define PCIE_COMPLETION_TIMEOUT_1S_3_5S 10 +#define PCIE_COMPLETION_TIMEOUT_4S_13S 13 +#define PCIE_COMPLETION_TIMEOUT_17S_64S 14 + +#define PCIE_DEVICE_CONTROL_OBFF_DISABLED 0 +#define PCIE_DEVICE_CONTROL_OBFF_MESSAGE_A 1 +#define PCIE_DEVICE_CONTROL_OBFF_MESSAGE_B 2 +#define PCIE_DEVICE_CONTROL_OBFF_WAKE 3 + +typedef union { + struct { + UINT32 Reserved : 1; + UINT32 LinkSpeedsVector : 7; + UINT32 Crosslink : 1; + UINT32 Reserved2 : 23; + } Bits; + UINT32 Uint32; +} PCI_REG_PCIE_LINK_CAPABILITY2; + +typedef union { + struct { + UINT16 TargetLinkSpeed : 4; + UINT16 EnterCompliance : 1; + UINT16 HardwareAutonomousSpeedDisable : 1; + UINT16 SelectableDeemphasis : 1; + UINT16 TransmitMargin : 3; + UINT16 EnterModifiedCompliance : 1; + UINT16 ComplianceSos : 1; + UINT16 CompliancePresetDeemphasis : 4; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_LINK_CONTROL2; + +typedef union { + struct { + UINT16 CurrentDeemphasisLevel : 1; + UINT16 EqualizationComplete : 1; + UINT16 EqualizationPhase1Successful : 1; + UINT16 EqualizationPhase2Successful : 1; + UINT16 EqualizationPhase3Successful : 1; + UINT16 LinkEqualizationRequest : 1; + UINT16 Reserved : 10; + } Bits; + UINT16 Uint16; +} PCI_REG_PCIE_LINK_STATUS2; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + PCI_REG_PCIE_CAPABILITY Capability; + PCI_REG_PCIE_DEVICE_CAPABILITY DeviceCapability; + PCI_REG_PCIE_DEVICE_CONTROL DeviceControl; + PCI_REG_PCIE_DEVICE_STATUS DeviceStatus; + PCI_REG_PCIE_LINK_CAPABILITY LinkCapability; + PCI_REG_PCIE_LINK_CONTROL LinkControl; + PCI_REG_PCIE_LINK_STATUS LinkStatus; + PCI_REG_PCIE_SLOT_CAPABILITY SlotCapability; + PCI_REG_PCIE_SLOT_CONTROL SlotControl; + PCI_REG_PCIE_SLOT_STATUS SlotStatus; + PCI_REG_PCIE_ROOT_CONTROL RootControl; + PCI_REG_PCIE_ROOT_CAPABILITY RootCapability; + PCI_REG_PCIE_ROOT_STATUS RootStatus; + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCapability2; + PCI_REG_PCIE_DEVICE_CONTROL2 DeviceControl2; + UINT16 DeviceStatus2; + PCI_REG_PCIE_LINK_CAPABILITY2 LinkCapability2; + PCI_REG_PCIE_LINK_CONTROL2 LinkControl2; + PCI_REG_PCIE_LINK_STATUS2 LinkStatus2; + UINT32 SlotCapability2; + UINT16 SlotControl2; + UINT16 SlotStatus2; +} PCI_CAPABILITY_PCIEXP; + +#define EFI_PCIE_CAPABILITY_BASE_OFFSET 0x100 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY 0x10 +#define EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET 0x24 +#define EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING 0x20 +#define EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET 0x28 +#define EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING 0x20 + +// +// for SR-IOV +// +#define EFI_PCIE_CAPABILITY_ID_ARI 0x0E +#define EFI_PCIE_CAPABILITY_ID_ATS 0x0F +#define EFI_PCIE_CAPABILITY_ID_SRIOV 0x10 +#define EFI_PCIE_CAPABILITY_ID_MRIOV 0x11 + +typedef struct { + UINT32 CapabilityHeader; + UINT32 Capability; + UINT16 Control; + UINT16 Status; + UINT16 InitialVFs; + UINT16 TotalVFs; + UINT16 NumVFs; + UINT8 FunctionDependencyLink; + UINT8 Reserved0; + UINT16 FirstVFOffset; + UINT16 VFStride; + UINT16 Reserved1; + UINT16 VFDeviceID; + UINT32 SupportedPageSize; + UINT32 SystemPageSize; + UINT32 VFBar[6]; + UINT32 VFMigrationStateArrayOffset; +} SR_IOV_CAPABILITY_REGISTER; + +#define EFI_PCIE_CAPABILITY_ID_SRIOV_CAPABILITIES 0x04 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL 0x08 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_STATUS 0x0A +#define EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS 0x0C +#define EFI_PCIE_CAPABILITY_ID_SRIOV_TOTALVFS 0x0E +#define EFI_PCIE_CAPABILITY_ID_SRIOV_NUMVFS 0x10 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_FUNCTION_DEPENDENCY_LINK 0x12 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF 0x14 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE 0x16 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_VFDEVICEID 0x1A +#define EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE 0x1C +#define EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE 0x20 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0 0x24 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR1 0x28 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR2 0x2C +#define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR3 0x30 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR4 0x34 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5 0x38 +#define EFI_PCIE_CAPABILITY_ID_SRIOV_VF_MIGRATION_STATE 0x3C + +typedef struct { + UINT32 CapabilityId:16; + UINT32 CapabilityVersion:4; + UINT32 NextCapabilityOffset:12; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER; + +#define PCI_EXP_EXT_HDR PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ADVANCED_ERROR_REPORTING_ID 0x0001 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ADVANCED_ERROR_REPORTING_VER1 0x1 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ADVANCED_ERROR_REPORTING_VER2 0x2 + +typedef union { + struct { + UINT32 Undefined : 1; + UINT32 Reserved : 3; + UINT32 DataLinkProtocolError : 1; + UINT32 SurpriseDownError : 1; + UINT32 Reserved2 : 6; + UINT32 PoisonedTlp : 1; + UINT32 FlowControlProtocolError : 1; + UINT32 CompletionTimeout : 1; + UINT32 CompleterAbort : 1; + UINT32 UnexpectedCompletion : 1; + UINT32 ReceiverOverflow : 1; + UINT32 MalformedTlp : 1; + UINT32 EcrcError : 1; + UINT32 UnsupportedRequestError : 1; + UINT32 AcsVoilation : 1; + UINT32 UncorrectableInternalError : 1; + UINT32 McBlockedTlp : 1; + UINT32 AtomicOpEgressBlocked : 1; + UINT32 TlpPrefixBlockedError : 1; + UINT32 Reserved3 : 6; + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_UNCORRECTABLE_ERROR; + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + PCI_EXPRESS_REG_UNCORRECTABLE_ERROR UncorrectableErrorStatus; + PCI_EXPRESS_REG_UNCORRECTABLE_ERROR UncorrectableErrorMask; + PCI_EXPRESS_REG_UNCORRECTABLE_ERROR UncorrectableErrorSeverity; + UINT32 CorrectableErrorStatus; + UINT32 CorrectableErrorMask; + UINT32 AdvancedErrorCapabilitiesAndControl; + UINT32 HeaderLog[4]; + UINT32 RootErrorCommand; + UINT32 RootErrorStatus; + UINT16 ErrorSourceIdentification; + UINT16 CorrectableErrorSourceIdentification; + UINT32 TlpPrefixLog[4]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_VIRTUAL_CHANNEL_ID 0x0002 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_VIRTUAL_CHANNEL_MFVC 0x0009 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_VIRTUAL_CHANNEL_VER1 0x1 + +typedef struct { + UINT32 VcResourceCapability:24; + UINT32 PortArbTableOffset:8; + UINT32 VcResourceControl; + UINT16 Reserved1; + UINT16 VcResourceStatus; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC; + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 ExtendedVcCount:3; + UINT32 PortVcCapability1:29; + UINT32 PortVcCapability2:24; + UINT32 VcArbTableOffset:8; + UINT16 PortVcControl; + UINT16 PortVcStatus; + PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC Capability[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_SERIAL_NUMBER_ID 0x0003 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_SERIAL_NUMBER_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT64 SerialNumber; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_ID 0x0005 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 ElementSelfDescription; + UINT32 Reserved; + UINT32 LinkEntry[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(LINK_DECLARATION) (UINT8)(((LINK_DECLARATION->ElementSelfDescription)&0x0000ff00)>>8) + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_CONTROL_ID 0x0006 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_CONTROL_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 RootComplexLinkCapabilities; + UINT16 RootComplexLinkControl; + UINT16 RootComplexLinkStatus; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_POWER_BUDGETING_ID 0x0004 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_POWER_BUDGETING_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 DataSelect:8; + UINT32 Reserved:24; + UINT32 Data; + UINT32 PowerBudgetCapability:1; + UINT32 Reserved2:7; + UINT32 Reserved3:24; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_ID 0x000D +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT16 AcsCapability; + UINT16 AcsControl; + UINT8 EgressControlVectorArray[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_CONTROL(ACS_EXTENDED) (UINT8)(((ACS_EXTENDED->AcsCapability)&0x00000020)) +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_VECTOR_SIZE(ACS_EXTENDED) (UINT8)(((ACS_EXTENDED->AcsCapability)&0x0000FF00)) + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION_ID 0x0007 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 AssociationBitmap; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_MULTI_FUNCTION_VIRTUAL_CHANNEL_ID 0x0008 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_MULTI_FUNCTION_VIRTUAL_CHANNEL_VER1 0x1 + +typedef PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTI_FUNCTION_VIRTUAL_CHANNEL_CAPABILITY; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID 0x000B +#define PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 VendorSpecificHeader; + UINT8 VendorSpecific[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_GET_SIZE(VENDOR) (UINT16)(((VENDOR->VendorSpecificHeader)&0xFFF00000)>>20) + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_RCRB_HEADER_ID 0x000A +#define PCI_EXPRESS_EXTENDED_CAPABILITY_RCRB_HEADER_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT16 VendorId; + UINT16 DeviceId; + UINT32 RcrbCapabilities; + UINT32 RcrbControl; + UINT32 Reserved; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_MULTICAST_ID 0x0012 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_MULTICAST_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT16 MultiCastCapability; + UINT16 MulticastControl; + UINT64 McBaseAddress; + UINT64 McReceiveAddress; + UINT64 McBlockAll; + UINT64 McBlockUntranslated; + UINT64 McOverlayBar; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID 0x0015 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_VER1 0x1 + +typedef struct { + UINT32 ResizableBarCapability; + UINT16 ResizableBarControl; + UINT16 Reserved; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY; + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Capability[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR; + +#define GET_NUMBER_RESIZABLE_BARS(x) (((x->Capability[0].ResizableBarControl) & 0xE0) >> 5) + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_ID 0x000E +#define PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT16 AriCapability; + UINT16 AriControl; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_ID 0x0016 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 DpaCapability; + UINT32 DpaLatencyIndicator; + UINT16 DpaStatus; + UINT16 DpaControl; + UINT8 DpaPowerAllocationArray[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(POWER) (UINT16)(((POWER->DpaCapability)&0x0000000F)) + + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LATENCE_TOLERANCE_REPORTING_ID 0x0018 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_LATENCE_TOLERANCE_REPORTING_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT16 MaxSnoopLatency; + UINT16 MaxNoSnoopLatency; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING; + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_TPH_ID 0x0017 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_TPH_VER1 0x1 + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + UINT32 TphRequesterCapability; + UINT32 TphRequesterControl; + UINT16 TphStTable[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH; + +#define GET_TPH_TABLE_SIZE(x) ((x->TphRequesterCapability & 0x7FF0000)>>16) * sizeof(UINT16) + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress30.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress30.h new file mode 100644 index 0000000..742028a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress30.h @@ -0,0 +1,57 @@ +/** @file + Support for the PCI Express 3.0 standard. + + This header file may not define all structures. Please extend as required. + + Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCIEXPRESS30_H_ +#define _PCIEXPRESS30_H_ + +#include + +#pragma pack(1) + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_SECONDARY_PCIE_ID 0x0019 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_SECONDARY_PCIE_VER1 0x1 + +typedef union { + struct { + UINT32 PerformEqualization : 1; + UINT32 LinkEqualizationRequestInterruptEnable : 1; + UINT32 Reserved : 30; + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_LINK_CONTROL3; + +typedef union { + struct { + UINT16 DownstreamPortTransmitterPreset : 4; + UINT16 DownstreamPortReceiverPresetHint : 3; + UINT16 Reserved : 1; + UINT16 UpstreamPortTransmitterPreset : 4; + UINT16 UpstreamPortReceiverPresetHint : 3; + UINT16 Reserved2 : 1; + } Bits; + UINT16 Uint16; +} PCI_EXPRESS_REG_LANE_EQUALIZATION_CONTROL; + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + PCI_EXPRESS_REG_LINK_CONTROL3 LinkControl3; + UINT32 LaneErrorStatus; + PCI_EXPRESS_REG_LANE_EQUALIZATION_CONTROL EqualizationControl[2]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress31.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress31.h new file mode 100644 index 0000000..72a3ccd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress31.h @@ -0,0 +1,78 @@ +/** @file +Support for the PCI Express 3.1 standard. + +This header file may not define all structures. Please extend as required. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCIEXPRESS31_H_ +#define _PCIEXPRESS31_H_ + +#include + +#pragma pack(1) + +#define PCI_EXPRESS_EXTENDED_CAPABILITY_L1_PM_SUBSTATES_ID 0x001E +#define PCI_EXPRESS_EXTENDED_CAPABILITY_L1_PM_SUBSTATES_VER1 0x1 + +typedef union { + struct { + UINT32 PciPmL12 : 1; + UINT32 PciPmL11 : 1; + UINT32 AspmL12 : 1; + UINT32 AspmL11 : 1; + UINT32 L1PmSubstates : 1; + UINT32 Reserved : 3; + UINT32 CommonModeRestoreTime : 8; + UINT32 TPowerOnScale : 2; + UINT32 Reserved2 : 1; + UINT32 TPowerOnValue : 5; + UINT32 Reserved3 : 8; + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_L1_PM_SUBSTATES_CAPABILITY; + +typedef union { + struct { + UINT32 PciPmL12 : 1; + UINT32 PciPmL11 : 1; + UINT32 AspmL12 : 1; + UINT32 AspmL11 : 1; + UINT32 Reserved : 4; + UINT32 CommonModeRestoreTime : 8; + UINT32 LtrL12ThresholdValue : 10; + UINT32 Reserved2 : 3; + UINT32 LtrL12ThresholdScale : 3; + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_L1_PM_SUBSTATES_CONTROL1; + +typedef union { + struct { + UINT32 TPowerOnScale : 2; + UINT32 Reserved : 1; + UINT32 TPowerOnValue : 5; + UINT32 Reserved2 : 24; + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_L1_PM_SUBSTATES_CONTROL2; + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + PCI_EXPRESS_REG_L1_PM_SUBSTATES_CAPABILITY Capability; + PCI_EXPRESS_REG_L1_PM_SUBSTATES_CONTROL1 Control1; + PCI_EXPRESS_REG_L1_PM_SUBSTATES_CONTROL2 Control2; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_L1_PM_SUBSTATES; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress40.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress40.h new file mode 100644 index 0000000..41d0883 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PciExpress40.h @@ -0,0 +1,89 @@ +/** @file +Support for the PCI Express 4.0 standard. + +This header file may not define all structures. Please extend as required. + +Copyright (c) 2018, American Megatrends, Inc. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PCIEXPRESS40_H_ +#define _PCIEXPRESS40_H_ + +#include + +#pragma pack(1) + +/// The Physical Layer PCI Express Extended Capability definitions. +/// +/// Based on section 7.7.5 of PCI Express Base Specification 4.0. +///@{ +#define PCI_EXPRESS_EXTENDED_CAPABILITY_PHYSICAL_LAYER_16_0_ID 0x0026 +#define PCI_EXPRESS_EXTENDED_CAPABILITY_PHYSICAL_LAYER_16_0_VER1 0x1 + +// Register offsets from Physical Layer PCI-E Ext Cap Header +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_CAPABILITIES_OFFSET 0x04 +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_CONTROL_OFFSET 0x08 +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_STATUS_OFFSET 0x0C +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_LOCAL_DATA_PARITY_STATUS_OFFSET 0x10 +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_FIRST_RETIMER_DATA_PARITY_STATUS_OFFSET 0x14 +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_SECOND_RETIMER_DATA_PARITY_STATUS_OFFSET 0x18 +#define PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_LANE_EQUALIZATION_CONTROL_OFFSET 0x20 + +typedef union { + struct { + UINT32 Reserved : 32; // Reserved bit 0:31 + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_CAPABILITIES; + +typedef union { + struct { + UINT32 Reserved : 32; // Reserved bit 0:31 + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_CONTROL; + +typedef union { + struct { + UINT32 EqualizationComplete : 1; // bit 0 + UINT32 EqualizationPhase1Success : 1; // bit 1 + UINT32 EqualizationPhase2Success : 1; // bit 2 + UINT32 EqualizationPhase3Success : 1; // bit 3 + UINT32 LinkEqualizationRequest : 1; // bit 4 + UINT32 Reserved : 27; // Reserved bit 5:31 + } Bits; + UINT32 Uint32; +} PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_STATUS; + +typedef union { + struct { + UINT8 DownstreamPortTransmitterPreset : 4; //bit 0..3 + UINT8 UpstreamPortTransmitterPreset : 4; //bit 4..7 + } Bits; + UINT8 Uint8; +} PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_LANE_EQUALIZATION_CONTROL; + +typedef struct { + PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; + PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_CAPABILITIES Capablities; + PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_CONTROL Control; + PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_STATUS Status; + UINT32 LocalDataParityMismatchStatus; + UINT32 FirstRetimerDataParityMismatchStatus; + UINT32 SecondRetimerDataParityMismatchStatus; + UINT32 Reserved; + PCI_EXPRESS_REG_PHYSICAL_LAYER_16_0_LANE_EQUALIZATION_CONTROL LaneEqualizationControl[1]; +} PCI_EXPRESS_EXTENDED_CAPABILITIES_PHYSICAL_LAYER_16_0; +///@} + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PeImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PeImage.h new file mode 100644 index 0000000..7c55317 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/PeImage.h @@ -0,0 +1,756 @@ +/** @file + EFI image format for PE32, PE32+ and TE. Please note some data structures are + different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and + EFI_IMAGE_NT_HEADERS64 is for PE32+. + + This file is coded to the Visual Studio, Microsoft Portable Executable and + Common Object File Format Specification, Revision 8.3 - February 6, 2013. + This file also includes some definitions in PI Specification, Revision 1.0. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PE_IMAGE_H__ +#define __PE_IMAGE_H__ + +// +// PE32+ Subsystem type for EFI images +// +#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0 + + +// +// PE32+ Machine type for EFI images +// +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_EBC 0x0EBC +#define IMAGE_FILE_MACHINE_X64 0x8664 +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2 +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 + +// +// EXE file formats +// +#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z') +#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E') +#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E') +#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0') + +/// +/// PE images can start with an optional DOS header, so if an image is run +/// under DOS it can print an error message. +/// +typedef struct { + UINT16 e_magic; ///< Magic number. + UINT16 e_cblp; ///< Bytes on last page of file. + UINT16 e_cp; ///< Pages in file. + UINT16 e_crlc; ///< Relocations. + UINT16 e_cparhdr; ///< Size of header in paragraphs. + UINT16 e_minalloc; ///< Minimum extra paragraphs needed. + UINT16 e_maxalloc; ///< Maximum extra paragraphs needed. + UINT16 e_ss; ///< Initial (relative) SS value. + UINT16 e_sp; ///< Initial SP value. + UINT16 e_csum; ///< Checksum. + UINT16 e_ip; ///< Initial IP value. + UINT16 e_cs; ///< Initial (relative) CS value. + UINT16 e_lfarlc; ///< File address of relocation table. + UINT16 e_ovno; ///< Overlay number. + UINT16 e_res[4]; ///< Reserved words. + UINT16 e_oemid; ///< OEM identifier (for e_oeminfo). + UINT16 e_oeminfo; ///< OEM information; e_oemid specific. + UINT16 e_res2[10]; ///< Reserved words. + UINT32 e_lfanew; ///< File address of new exe header. +} EFI_IMAGE_DOS_HEADER; + +/// +/// COFF File Header (Object and Image). +/// +typedef struct { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} EFI_IMAGE_FILE_HEADER; + +/// +/// Size of EFI_IMAGE_FILE_HEADER. +/// +#define EFI_IMAGE_SIZEOF_FILE_HEADER 20 + +// +// Characteristics +// +#define EFI_IMAGE_FILE_RELOCS_STRIPPED BIT0 ///< 0x0001 Relocation info stripped from file. +#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE BIT1 ///< 0x0002 File is executable (i.e. no unresolved externel references). +#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED BIT2 ///< 0x0004 Line nunbers stripped from file. +#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED BIT3 ///< 0x0008 Local symbols stripped from file. +#define EFI_IMAGE_FILE_BYTES_REVERSED_LO BIT7 ///< 0x0080 Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_32BIT_MACHINE BIT8 ///< 0x0100 32 bit word machine. +#define EFI_IMAGE_FILE_DEBUG_STRIPPED BIT9 ///< 0x0200 Debugging info stripped from file in .DBG file. +#define EFI_IMAGE_FILE_SYSTEM BIT12 ///< 0x1000 System File. +#define EFI_IMAGE_FILE_DLL BIT13 ///< 0x2000 File is a DLL. +#define EFI_IMAGE_FILE_BYTES_REVERSED_HI BIT15 ///< 0x8000 Bytes of machine word are reversed. + +/// +/// Header Data Directories. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 Size; +} EFI_IMAGE_DATA_DIRECTORY; + +// +// Directory Entries +// +#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 +#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 + +#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 + +/// +/// @attention +/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and +/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary +/// after NT additional fields. +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b + +/// +/// Optional Header Standard Fields for PE32. +/// +typedef struct { + /// + /// Standard fields. + /// + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+. + /// + /// Optional Header Windows-Specific Fields. + /// + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER32; + +/// +/// @attention +/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and +/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary +/// after NT additional fields. +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b + +/// +/// Optional Header Standard Fields for PE32+. +/// +typedef struct { + /// + /// Standard fields. + /// + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + /// + /// Optional Header Windows-Specific Fields. + /// + UINT64 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT64 SizeOfStackReserve; + UINT64 SizeOfStackCommit; + UINT64 SizeOfHeapReserve; + UINT64 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER64; + + +/// +/// @attention +/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools. +/// +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} EFI_IMAGE_NT_HEADERS32; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) + +/// +/// @attention +/// EFI_IMAGE_HEADERS64 is for use ONLY by tools. +/// +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} EFI_IMAGE_NT_HEADERS64; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) + +// +// Other Windows Subsystem Values +// +#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 +#define EFI_IMAGE_SUBSYSTEM_NATIVE 1 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 +#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 + +/// +/// Length of ShortName. +/// +#define EFI_IMAGE_SIZEOF_SHORT_NAME 8 + +/// +/// Section Table. This table immediately follows the optional header. +/// +typedef struct { + UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} EFI_IMAGE_SECTION_HEADER; + +/// +/// Size of EFI_IMAGE_SECTION_HEADER. +/// +#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 + +// +// Section Flags Values +// +#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved. +#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020 +#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040 +#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080 + +#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved. +#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information. +#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image. +#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000 + +#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000 +#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000 +#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000 +#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000 +#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000 +#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000 +#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000 + +#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000 +#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000 +#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000 +#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000 +#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000 +#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000 +#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000 + +/// +/// Size of a Symbol Table Record. +/// +#define EFI_IMAGE_SIZEOF_SYMBOL 18 + +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// +#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common. +#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value. +#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item. + +// +// Symbol Type (fundamental) values. +// +#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type. +#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type. +#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character. +#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer. +#define EFI_IMAGE_SYM_TYPE_INT 4 +#define EFI_IMAGE_SYM_TYPE_LONG 5 +#define EFI_IMAGE_SYM_TYPE_FLOAT 6 +#define EFI_IMAGE_SYM_TYPE_DOUBLE 7 +#define EFI_IMAGE_SYM_TYPE_STRUCT 8 +#define EFI_IMAGE_SYM_TYPE_UNION 9 +#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration. +#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration. +#define EFI_IMAGE_SYM_TYPE_BYTE 12 +#define EFI_IMAGE_SYM_TYPE_WORD 13 +#define EFI_IMAGE_SYM_TYPE_UINT 14 +#define EFI_IMAGE_SYM_TYPE_DWORD 15 + +// +// Symbol Type (derived) values. +// +#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type. +#define EFI_IMAGE_SYM_DTYPE_POINTER 1 +#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 +#define EFI_IMAGE_SYM_DTYPE_ARRAY 3 + +// +// Storage classes. +// +#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1) +#define EFI_IMAGE_SYM_CLASS_NULL 0 +#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 +#define EFI_IMAGE_SYM_CLASS_STATIC 3 +#define EFI_IMAGE_SYM_CLASS_REGISTER 4 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define EFI_IMAGE_SYM_CLASS_LABEL 6 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 +#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 +#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 +#define EFI_IMAGE_SYM_CLASS_BLOCK 100 +#define EFI_IMAGE_SYM_CLASS_FUNCTION 101 +#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define EFI_IMAGE_SYM_CLASS_FILE 103 +#define EFI_IMAGE_SYM_CLASS_SECTION 104 +#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// +// type packing constants +// +#define EFI_IMAGE_N_BTMASK 017 +#define EFI_IMAGE_N_TMASK 060 +#define EFI_IMAGE_N_TMASK1 0300 +#define EFI_IMAGE_N_TMASK2 0360 +#define EFI_IMAGE_N_BTSHFT 4 +#define EFI_IMAGE_N_TSHIFT 2 + +// +// Communal selection types. +// +#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define EFI_IMAGE_COMDAT_SELECT_ANY 2 +#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +// +// the following values only be referred in PeCoff, not defined in PECOFF. +// +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +/// +/// Relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} EFI_IMAGE_RELOCATION; + +/// +/// Size of EFI_IMAGE_RELOCATION +/// +#define EFI_IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// +#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary. +#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address. +#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address. +#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address. +#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included. +#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address. +#define EFI_IMAGE_REL_I386_SECTION 0x000A +#define EFI_IMAGE_REL_I386_SECREL 0x000B +#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address. + +// +// x64 processor relocation types. +// +#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32 0x0002 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_1 0x0005 +#define IMAGE_REL_AMD64_REL32_2 0x0006 +#define IMAGE_REL_AMD64_REL32_3 0x0007 +#define IMAGE_REL_AMD64_REL32_4 0x0008 +#define IMAGE_REL_AMD64_REL32_5 0x0009 +#define IMAGE_REL_AMD64_SECTION 0x000A +#define IMAGE_REL_AMD64_SECREL 0x000B +#define IMAGE_REL_AMD64_SECREL7 0x000C +#define IMAGE_REL_AMD64_TOKEN 0x000D +#define IMAGE_REL_AMD64_SREL32 0x000E +#define IMAGE_REL_AMD64_PAIR 0x000F +#define IMAGE_REL_AMD64_SSPAN32 0x0010 + +/// +/// Based relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +} EFI_IMAGE_BASE_RELOCATION; + +/// +/// Size of EFI_IMAGE_BASE_RELOCATION. +/// +#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// +#define EFI_IMAGE_REL_BASED_ABSOLUTE 0 +#define EFI_IMAGE_REL_BASED_HIGH 1 +#define EFI_IMAGE_REL_BASED_LOW 2 +#define EFI_IMAGE_REL_BASED_HIGHLOW 3 +#define EFI_IMAGE_REL_BASED_HIGHADJ 4 +#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5 +#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7 +#define EFI_IMAGE_REL_BASED_IA64_IMM64 9 +#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9 +#define EFI_IMAGE_REL_BASED_DIR64 10 + +/// +/// Line number format. +/// +typedef struct { + union { + UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; ///< Virtual address of line number. + } Type; + UINT16 Linenumber; ///< Line number. +} EFI_IMAGE_LINENUMBER; + +/// +/// Size of EFI_IMAGE_LINENUMBER. +/// +#define EFI_IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// +#define EFI_IMAGE_ARCHIVE_START_SIZE 8 +#define EFI_IMAGE_ARCHIVE_START "!\n" +#define EFI_IMAGE_ARCHIVE_END "`\n" +#define EFI_IMAGE_ARCHIVE_PAD "\n" +#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +/// +/// Archive Member Headers +/// +typedef struct { + UINT8 Name[16]; ///< File member name - `/' terminated. + UINT8 Date[12]; ///< File member date - decimal. + UINT8 UserID[6]; ///< File member user id - decimal. + UINT8 GroupID[6]; ///< File member group id - decimal. + UINT8 Mode[8]; ///< File member mode - octal. + UINT8 Size[10]; ///< File member size - decimal. + UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A). +} EFI_IMAGE_ARCHIVE_MEMBER_HEADER; + +/// +/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER. +/// +#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + + +// +// DLL Support +// + +/// +/// Export Directory Table. +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; + UINT32 AddressOfNames; + UINT32 AddressOfNameOrdinals; +} EFI_IMAGE_EXPORT_DIRECTORY; + +/// +/// Hint/Name Table. +/// +typedef struct { + UINT16 Hint; + UINT8 Name[1]; +} EFI_IMAGE_IMPORT_BY_NAME; + +/// +/// Import Address Table RVA (Thunk Table). +/// +typedef struct { + union { + UINT32 Function; + UINT32 Ordinal; + EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; + } u1; +} EFI_IMAGE_THUNK_DATA; + +#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32. +#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) +#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +/// +/// Import Directory Table +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + EFI_IMAGE_THUNK_DATA *FirstThunk; +} EFI_IMAGE_IMPORT_DESCRIPTOR; + + +/// +/// Debug Directory Format. +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Type; + UINT32 SizeOfData; + UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base. + UINT32 FileOffset; ///< The file pointer to the debug data. +} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; + +#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information. + +/// +/// Debug Data Structure defined in Microsoft C++. +/// +#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0') +typedef struct { + UINT32 Signature; ///< "NB10" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; + +/// +/// Debug Data Structure defined in Microsoft C++. +/// +#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S') +typedef struct { + UINT32 Signature; ///< "RSDS". + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + UINT32 Unknown4; + UINT32 Unknown5; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; + + +/// +/// Debug Data Structure defined by Apple Mach-O to Coff utility. +/// +#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C') +typedef struct { + UINT32 Signature; ///< "MTOC". + GUID MachOUuid; + // + // Filename of .DLL (Mach-O with debug info) goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; + +/// +/// Resource format. +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT16 NumberOfNamedEntries; + UINT16 NumberOfIdEntries; + // + // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here. + // +} EFI_IMAGE_RESOURCE_DIRECTORY; + +/// +/// Resource directory entry format. +/// +typedef struct { + union { + struct { + UINT32 NameOffset:31; + UINT32 NameIsString:1; + } s; + UINT32 Id; + } u1; + union { + UINT32 OffsetToData; + struct { + UINT32 OffsetToDirectory:31; + UINT32 DataIsDirectory:1; + } s; + } u2; +} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY; + +/// +/// Resource directory entry for string. +/// +typedef struct { + UINT16 Length; + CHAR16 String[1]; +} EFI_IMAGE_RESOURCE_DIRECTORY_STRING; + +/// +/// Resource directory entry for data array. +/// +typedef struct { + UINT32 OffsetToData; + UINT32 Size; + UINT32 CodePage; + UINT32 Reserved; +} EFI_IMAGE_RESOURCE_DATA_ENTRY; + +/// +/// Header format for TE images, defined in the PI Specification, 1.0. +/// +typedef struct { + UINT16 Signature; ///< The signature for TE format = "VZ". + UINT16 Machine; ///< From the original file header. + UINT8 NumberOfSections; ///< From the original file header. + UINT8 Subsystem; ///< From original optional header. + UINT16 StrippedSize; ///< Number of bytes we removed from the header. + UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header. + UINT32 BaseOfCode; ///< From original image -- required for ITP debug. + UINT64 ImageBase; ///< From original file header. + EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory. +} EFI_TE_IMAGE_HEADER; + + +#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z') + +// +// Data directory indexes in our TE image header +// +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 + + +/// +/// Union of PE32, PE32+, and TE headers. +/// +typedef union { + EFI_IMAGE_NT_HEADERS32 Pe32; + EFI_IMAGE_NT_HEADERS64 Pe32Plus; + EFI_TE_IMAGE_HEADER Te; +} EFI_IMAGE_OPTIONAL_HEADER_UNION; + +typedef union { + EFI_IMAGE_NT_HEADERS32 *Pe32; + EFI_IMAGE_NT_HEADERS64 *Pe32Plus; + EFI_TE_IMAGE_HEADER *Te; + EFI_IMAGE_OPTIONAL_HEADER_UNION *Union; +} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sal.h new file mode 100644 index 0000000..a22eee3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sal.h @@ -0,0 +1,915 @@ +/** @file + Main SAL API's defined in Intel Itanium Processor Family System Abstraction + Layer Specification Revision 3.2 (December 2003) + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SAL_API_H__ +#define __SAL_API_H__ + +/// +/// SAL return status type +/// +typedef INTN EFI_SAL_STATUS; + +/// +/// Call completed without error. +/// +#define EFI_SAL_SUCCESS ((EFI_SAL_STATUS) 0) +/// +/// Call completed without error, but some information was lost due to overflow. +/// +#define EFI_SAL_OVERFLOW ((EFI_SAL_STATUS) 1) +/// +/// Call completed without error; effect a warm boot of the system to complete the update. +/// +#define EFI_SAL_WARM_BOOT_NEEDED ((EFI_SAL_STATUS) 2) +/// +/// More information is available for retrieval. +/// +#define EFI_SAL_MORE_RECORDS ((EFI_SAL_STATUS) 3) +/// +/// Not implemented. +/// +#define EFI_SAL_NOT_IMPLEMENTED ((EFI_SAL_STATUS) - 1) +/// +/// Invalid Argument. +/// +#define EFI_SAL_INVALID_ARGUMENT ((EFI_SAL_STATUS) - 2) +/// +/// Call completed without error. +/// +#define EFI_SAL_ERROR ((EFI_SAL_STATUS) - 3) +/// +/// Virtual address not registered. +/// +#define EFI_SAL_VIRTUAL_ADDRESS_ERROR ((EFI_SAL_STATUS) - 4) +/// +/// No information available. +/// +#define EFI_SAL_NO_INFORMATION ((EFI_SAL_STATUS) - 5) +/// +/// Scratch buffer required. +/// +#define EFI_SAL_NOT_ENOUGH_SCRATCH ((EFI_SAL_STATUS) - 9) + +/// +/// Return registers from SAL. +/// +typedef struct { + /// + /// SAL return status value in r8. + /// + EFI_SAL_STATUS Status; + /// + /// SAL returned value in r9. + /// + UINTN r9; + /// + /// SAL returned value in r10. + /// + UINTN r10; + /// + /// SAL returned value in r11. + /// + UINTN r11; +} SAL_RETURN_REGS; + +/** + Prototype of SAL procedures. + + @param FunctionId Functional identifier. + The upper 32 bits are ignored and only the lower 32 bits + are used. The following functional identifiers are defined: + 0x01XXXXXX - Architected SAL functional group. + 0x02XXXXXX to 0x03XXXXXX - OEM SAL functional group. Each OEM is + allowed to use the entire range in the 0x02XXXXXX to 0x03XXXXXX range. + 0x04XXXXXX to 0xFFFFFFFF - Reserved. + @param Arg1 The first parameter of the architected/OEM specific SAL functions. + @param Arg2 The second parameter of the architected/OEM specific SAL functions. + @param Arg3 The third parameter passed to the ESAL function based. + @param Arg4 The fourth parameter passed to the ESAL function based. + @param Arg5 The fifth parameter passed to the ESAL function based. + @param Arg6 The sixth parameter passed to the ESAL function. + @param Arg7 The seventh parameter passed to the ESAL function based. + + @return r8 Return status: positive number indicates successful, + negative number indicates failure. + r9 Other return parameter in r9. + r10 Other return parameter in r10. + r11 Other return parameter in r11. + +**/ +typedef +SAL_RETURN_REGS +(EFIAPI *SAL_PROC)( + IN UINT64 FunctionId, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7 + ); + +// +// SAL Procedure FunctionId definition +// + +/// +/// Register software code locations with SAL. +/// +#define EFI_SAL_SET_VECTORS 0x01000000 +/// +/// Return Machine State information obtained by SAL. +/// +#define EFI_SAL_GET_STATE_INFO 0x01000001 +/// +/// Obtain size of Machine State information. +/// +#define EFI_SAL_GET_STATE_INFO_SIZE 0x01000002 +/// +/// Clear Machine State information. +/// +#define EFI_SAL_CLEAR_STATE_INFO 0x01000003 +/// +/// Cause the processor to go into a spin loop within SAL. +/// +#define EFI_SAL_MC_RENDEZ 0x01000004 +/// +/// Register the machine check interface layer with SAL. +/// +#define EFI_SAL_MC_SET_PARAMS 0x01000005 +/// +/// Register the physical addresses of locations needed by SAL. +/// +#define EFI_SAL_REGISTER_PHYSICAL_ADDR 0x01000006 +/// +/// Flush the instruction or data caches. +/// +#define EFI_SAL_CACHE_FLUSH 0x01000008 +/// +/// Initialize the instruction and data caches. +/// +#define EFI_SAL_CACHE_INIT 0x01000009 +/// +/// Read from the PCI configuration space. +/// +#define EFI_SAL_PCI_CONFIG_READ 0x01000010 +/// +/// Write to the PCI configuration space. +/// +#define EFI_SAL_PCI_CONFIG_WRITE 0x01000011 +/// +/// Return the base frequency of the platform. +/// +#define EFI_SAL_FREQ_BASE 0x01000012 +/// +/// Returns information on the physical processor mapping within the platform. +/// +#define EFI_SAL_PHYSICAL_ID_INFO 0x01000013 +/// +/// Update the contents of firmware blocks. +/// +#define EFI_SAL_UPDATE_PAL 0x01000020 + +#define EFI_SAL_FUNCTION_ID_MASK 0x0000ffff +#define EFI_SAL_MAX_SAL_FUNCTION_ID 0x00000021 + +// +// SAL Procedure parameter definitions +// Not much point in using typedefs or enums because all params +// are UINT64 and the entry point is common +// + +// +// Parameter of EFI_SAL_SET_VECTORS +// +// Vector type +// +#define EFI_SAL_SET_MCA_VECTOR 0x0 +#define EFI_SAL_SET_INIT_VECTOR 0x1 +#define EFI_SAL_SET_BOOT_RENDEZ_VECTOR 0x2 +/// +/// The format of a length_cs_n argument. +/// +typedef struct { + UINT64 Length : 32; + UINT64 ChecksumValid : 1; + UINT64 Reserved1 : 7; + UINT64 ByteChecksum : 8; + UINT64 Reserved2 : 16; +} SAL_SET_VECTORS_CS_N; + +// +// Parameter of EFI_SAL_GET_STATE_INFO, EFI_SAL_GET_STATE_INFO_SIZE, and EFI_SAL_CLEAR_STATE_INFO +// +// Type of information +// +#define EFI_SAL_MCA_STATE_INFO 0x0 +#define EFI_SAL_INIT_STATE_INFO 0x1 +#define EFI_SAL_CMC_STATE_INFO 0x2 +#define EFI_SAL_CP_STATE_INFO 0x3 + +// +// Parameter of EFI_SAL_MC_SET_PARAMS +// +// Unsigned 64-bit integer value for the parameter type of the machine check interface +// +#define EFI_SAL_MC_SET_RENDEZ_PARAM 0x1 +#define EFI_SAL_MC_SET_WAKEUP_PARAM 0x2 +#define EFI_SAL_MC_SET_CPE_PARAM 0x3 +// +// Unsigned 64-bit integer value indicating whether interrupt vector or +// memory address is specified +// +#define EFI_SAL_MC_SET_INTR_PARAM 0x1 +#define EFI_SAL_MC_SET_MEM_PARAM 0x2 + +// +// Parameter of EFI_SAL_REGISTER_PAL_PHYSICAL_ADDR +// +// The encoded value of the entity whose physical address is registered +// +#define EFI_SAL_REGISTER_PAL_ADDR 0x0 + +// +// Parameter of EFI_SAL_CACHE_FLUSH +// +// Unsigned 64-bit integer denoting type of cache flush operation +// +#define EFI_SAL_FLUSH_I_CACHE 0x01 +#define EFI_SAL_FLUSH_D_CACHE 0x02 +#define EFI_SAL_FLUSH_BOTH_CACHE 0x03 +#define EFI_SAL_FLUSH_MAKE_COHERENT 0x04 + +// +// Parameter of EFI_SAL_PCI_CONFIG_READ and EFI_SAL_PCI_CONFIG_WRITE +// +// PCI config size +// +#define EFI_SAL_PCI_CONFIG_ONE_BYTE 0x1 +#define EFI_SAL_PCI_CONFIG_TWO_BYTES 0x2 +#define EFI_SAL_PCI_CONFIG_FOUR_BYTES 0x4 +// +// The type of PCI configuration address +// +#define EFI_SAL_PCI_COMPATIBLE_ADDRESS 0x0 +#define EFI_SAL_PCI_EXTENDED_REGISTER_ADDRESS 0x1 +/// +/// The format of PCI Compatible Address. +/// +typedef struct { + UINT64 Register : 8; + UINT64 Function : 3; + UINT64 Device : 5; + UINT64 Bus : 8; + UINT64 Segment : 8; + UINT64 Reserved : 32; +} SAL_PCI_ADDRESS; +/// +/// The format of Extended Register Address. +/// +typedef struct { + UINT64 Register : 8; + UINT64 ExtendedRegister : 4; + UINT64 Function : 3; + UINT64 Device : 5; + UINT64 Bus : 8; + UINT64 Segment : 16; + UINT64 Reserved : 20; +} SAL_PCI_EXTENDED_REGISTER_ADDRESS; + +// +// Parameter of EFI_SAL_FREQ_BASE +// +// Unsigned 64-bit integer specifying the type of clock source +// +#define EFI_SAL_CPU_INPUT_FREQ_BASE 0x0 +#define EFI_SAL_PLATFORM_IT_FREQ_BASE 0x1 +#define EFI_SAL_PLATFORM_RTC_FREQ_BASE 0x2 + +// +// Parameter and return value of EFI_SAL_UPDATE_PAL +// +// Return parameter provides additional information on the +// failure when the status field contains a value of -3, +// returned in r9. +// +#define EFI_SAL_UPDATE_BAD_PAL_VERSION ((UINT64) -1) +#define EFI_SAL_UPDATE_PAL_AUTH_FAIL ((UINT64) -2) +#define EFI_SAL_UPDATE_PAL_BAD_TYPE ((UINT64) -3) +#define EFI_SAL_UPDATE_PAL_READONLY ((UINT64) -4) +#define EFI_SAL_UPDATE_PAL_WRITE_FAIL ((UINT64) -10) +#define EFI_SAL_UPDATE_PAL_ERASE_FAIL ((UINT64) -11) +#define EFI_SAL_UPDATE_PAL_READ_FAIL ((UINT64) -12) +#define EFI_SAL_UPDATE_PAL_CANT_FIT ((UINT64) -13) +/// +/// 64-byte header of update data block. +/// +typedef struct { + UINT32 Size; + UINT32 MmddyyyyDate; + UINT16 Version; + UINT8 Type; + UINT8 Reserved[5]; + UINT64 FwVendorId; + UINT8 Reserved2[40]; +} SAL_UPDATE_PAL_DATA_BLOCK; +/// +/// Data structure pointed by the parameter param_buf. +/// It is a 16-byte aligned data structure in memory with a length of 32 bytes +/// that describes the new firmware. This information is organized in the form +/// of a linked list with each element describing one firmware component. +/// +typedef struct _SAL_UPDATE_PAL_INFO_BLOCK { + struct _SAL_UPDATE_PAL_INFO_BLOCK *Next; + struct SAL_UPDATE_PAL_DATA_BLOCK *DataBlock; + UINT8 StoreChecksum; + UINT8 Reserved[15]; +} SAL_UPDATE_PAL_INFO_BLOCK; + +/// +/// SAL System Table Definitions. +/// +#pragma pack(1) +typedef struct { + /// + /// The ASCII string representation of "SST_" that confirms the presence of the table. + /// + UINT32 Signature; + /// + /// The length of the entire table in bytes, starting from offset zero and including the + /// header and all entries indicated by the EntryCount field. + /// + UINT32 Length; + /// + /// The revision number of the Itanium Processor Family System Abstraction Layer + /// Specification supported by the SAL implementation, in binary coded decimal (BCD) format. + /// + UINT16 SalRevision; + /// + /// The number of entries in the variable portion of the table. + /// + UINT16 EntryCount; + /// + /// A modulo checksum of the entire table and the entries following this table. + /// + UINT8 CheckSum; + /// + /// Unused, must be zero. + /// + UINT8 Reserved[7]; + /// + /// Version Number of the SAL_A firmware implementation in BCD format. + /// + UINT16 SalAVersion; + /// + /// Version Number of the SAL_B firmware implementation in BCD format. + /// + UINT16 SalBVersion; + /// + /// An ASCII identification string which uniquely identifies the manufacturer + /// of the system hardware. + /// + UINT8 OemId[32]; + /// + /// An ASCII identification string which uniquely identifies a family of + /// compatible products from the manufacturer. + /// + UINT8 ProductId[32]; + /// + /// Unused, must be zero. + /// + UINT8 Reserved2[8]; +} SAL_SYSTEM_TABLE_HEADER; + +#define EFI_SAL_ST_HEADER_SIGNATURE "SST_" +#define EFI_SAL_REVISION 0x0320 +// +// SAL System Types +// +#define EFI_SAL_ST_ENTRY_POINT 0 +#define EFI_SAL_ST_MEMORY_DESCRIPTOR 1 +#define EFI_SAL_ST_PLATFORM_FEATURES 2 +#define EFI_SAL_ST_TR_USAGE 3 +#define EFI_SAL_ST_PTC 4 +#define EFI_SAL_ST_AP_WAKEUP 5 + +// +// SAL System Type Sizes +// +#define EFI_SAL_ST_ENTRY_POINT_SIZE 48 +#define EFI_SAL_ST_MEMORY_DESCRIPTOR_SIZE 32 +#define EFI_SAL_ST_PLATFORM_FEATURES_SIZE 16 +#define EFI_SAL_ST_TR_USAGE_SIZE 32 +#define EFI_SAL_ST_PTC_SIZE 16 +#define EFI_SAL_ST_AP_WAKEUP_SIZE 16 + +/// +/// Format of Entrypoint Descriptor Entry. +/// +typedef struct { + UINT8 Type; ///< Type here should be 0. + UINT8 Reserved[7]; + UINT64 PalProcEntry; + UINT64 SalProcEntry; + UINT64 SalGlobalDataPointer; + UINT64 Reserved2[2]; +} SAL_ST_ENTRY_POINT_DESCRIPTOR; + +/// +/// Format of Platform Features Descriptor Entry. +/// +typedef struct { + UINT8 Type; ///< Type here should be 2. + UINT8 PlatformFeatures; + UINT8 Reserved[14]; +} SAL_ST_PLATFORM_FEATURES; + +// +// Value of Platform Feature List +// +#define SAL_PLAT_FEAT_BUS_LOCK 0x01 +#define SAL_PLAT_FEAT_PLAT_IPI_HINT 0x02 +#define SAL_PLAT_FEAT_PROC_IPI_HINT 0x04 + +/// +/// Format of Translation Register Descriptor Entry. +/// +typedef struct { + UINT8 Type; ///< Type here should be 3. + UINT8 TRType; + UINT8 TRNumber; + UINT8 Reserved[5]; + UINT64 VirtualAddress; + UINT64 EncodedPageSize; + UINT64 Reserved1; +} SAL_ST_TR_DECRIPTOR; + +// +// Type of Translation Register +// +#define EFI_SAL_ST_TR_USAGE_INSTRUCTION 00 +#define EFI_SAL_ST_TR_USAGE_DATA 01 + +/// +/// Definition of Coherence Domain Information. +/// +typedef struct { + UINT64 NumberOfProcessors; + UINT64 LocalIDRegister; +} SAL_COHERENCE_DOMAIN_INFO; + +/// +/// Format of Purge Translation Cache Coherence Domain Entry. +/// +typedef struct { + UINT8 Type; ///< Type here should be 4. + UINT8 Reserved[3]; + UINT32 NumberOfDomains; + SAL_COHERENCE_DOMAIN_INFO *DomainInformation; +} SAL_ST_CACHE_COHERENCE_DECRIPTOR; + +/// +/// Format of Application Processor Wake-Up Descriptor Entry. +/// +typedef struct { + UINT8 Type; ///< Type here should be 5. + UINT8 WakeUpType; + UINT8 Reserved[6]; + UINT64 ExternalInterruptVector; +} SAL_ST_AP_WAKEUP_DECRIPTOR; + +/// +/// Format of Firmware Interface Table (FIT) Entry. +/// +typedef struct { + UINT64 Address; + UINT8 Size[3]; + UINT8 Reserved; + UINT16 Revision; + UINT8 Type : 7; + UINT8 CheckSumValid : 1; + UINT8 CheckSum; +} EFI_SAL_FIT_ENTRY; +// +// FIT Types +// +#define EFI_SAL_FIT_FIT_HEADER_TYPE 0x00 +#define EFI_SAL_FIT_PAL_B_TYPE 0x01 +// +// Type from 0x02 to 0x0D is reserved. +// +#define EFI_SAL_FIT_PROCESSOR_SPECIFIC_PAL_A_TYPE 0x0E +#define EFI_SAL_FIT_PAL_A_TYPE 0x0F +// +// OEM-defined type range is from 0x10 to 0x7E. +// Here we defined the PEI_CORE type as 0x10 +// +#define EFI_SAL_FIT_PEI_CORE_TYPE 0x10 +#define EFI_SAL_FIT_UNUSED_TYPE 0x7F + +// +// FIT Entry +// +#define EFI_SAL_FIT_ENTRY_PTR (0x100000000 - 32) // 4GB - 24 +#define EFI_SAL_FIT_PALA_ENTRY (0x100000000 - 48) // 4GB - 32 +#define EFI_SAL_FIT_PALB_TYPE 01 + +// +// Following definitions are for Error Record Structure +// + +/// +/// Format of TimeStamp field in Record Header. +/// +typedef struct { + UINT8 Seconds; + UINT8 Minutes; + UINT8 Hours; + UINT8 Reserved; + UINT8 Day; + UINT8 Month; + UINT8 Year; + UINT8 Century; +} SAL_TIME_STAMP; +/// +/// Definition of Record Header. +/// +typedef struct { + UINT64 RecordId; + UINT16 Revision; + UINT8 ErrorSeverity; + UINT8 ValidationBits; + UINT32 RecordLength; + SAL_TIME_STAMP TimeStamp; + UINT8 OemPlatformId[16]; +} SAL_RECORD_HEADER; +/// +/// Definition of Section Header. +/// +typedef struct { + GUID Guid; + UINT16 Revision; + UINT8 ErrorRecoveryInfo; + UINT8 Reserved; + UINT32 SectionLength; +} SAL_SEC_HEADER; + +/// +/// GUID of Processor Machine Check Errors. +/// +#define SAL_PROCESSOR_ERROR_RECORD_INFO \ + { \ + 0xe429faf1, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for valid bits of MOD_ERROR_INFO +// +#define CHECK_INFO_VALID_BIT_MASK 0x1 +#define REQUESTOR_ID_VALID_BIT_MASK 0x2 +#define RESPONDER_ID_VALID_BIT_MASK 0x4 +#define TARGER_ID_VALID_BIT_MASK 0x8 +#define PRECISE_IP_VALID_BIT_MASK 0x10 +/// +/// Definition of MOD_ERROR_INFO_STRUCT. +/// +typedef struct { + UINT64 InfoValid : 1; + UINT64 ReqValid : 1; + UINT64 RespValid : 1; + UINT64 TargetValid : 1; + UINT64 IpValid : 1; + UINT64 Reserved : 59; + UINT64 Info; + UINT64 Req; + UINT64 Resp; + UINT64 Target; + UINT64 Ip; +} MOD_ERROR_INFO; +/// +/// Definition of CPUID_INFO_STRUCT. +/// +typedef struct { + UINT8 CpuidInfo[40]; + UINT8 Reserved; +} CPUID_INFO; + +typedef struct { + UINT64 FrLow; + UINT64 FrHigh; +} FR_STRUCT; +// +// Bit masks for PSI_STATIC_STRUCT.ValidFieldBits +// +#define MIN_STATE_VALID_BIT_MASK 0x1 +#define BR_VALID_BIT_MASK 0x2 +#define CR_VALID_BIT_MASK 0x4 +#define AR_VALID_BIT_MASK 0x8 +#define RR_VALID_BIT_MASK 0x10 +#define FR_VALID_BIT_MASK 0x20 +/// +/// Definition of PSI_STATIC_STRUCT. +/// +typedef struct { + UINT64 ValidFieldBits; + UINT8 MinStateInfo[1024]; + UINT64 Br[8]; + UINT64 Cr[128]; + UINT64 Ar[128]; + UINT64 Rr[8]; + FR_STRUCT Fr[128]; +} PSI_STATIC_STRUCT; +// +// Bit masks for SAL_PROCESSOR_ERROR_RECORD.ValidationBits +// +#define PROC_ERROR_MAP_VALID_BIT_MASK 0x1 +#define PROC_STATE_PARAMETER_VALID_BIT_MASK 0x2 +#define PROC_CR_LID_VALID_BIT_MASK 0x4 +#define PROC_STATIC_STRUCT_VALID_BIT_MASK 0x8 +#define CPU_INFO_VALID_BIT_MASK 0x1000000 +/// +/// Definition of Processor Machine Check Error Record. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 ProcErrorMap; + UINT64 ProcStateParameter; + UINT64 ProcCrLid; + MOD_ERROR_INFO CacheError[15]; + MOD_ERROR_INFO TlbError[15]; + MOD_ERROR_INFO BusError[15]; + MOD_ERROR_INFO RegFileCheck[15]; + MOD_ERROR_INFO MsCheck[15]; + CPUID_INFO CpuInfo; + PSI_STATIC_STRUCT PsiValidData; +} SAL_PROCESSOR_ERROR_RECORD; + +/// +/// GUID of Platform Memory Device Error Info. +/// +#define SAL_MEMORY_ERROR_RECORD_INFO \ + { \ + 0xe429faf2, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for SAL_MEMORY_ERROR_RECORD.ValidationBits +// +#define MEMORY_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define MEMORY_PHYSICAL_ADDRESS_VALID_BIT_MASK 0x2 +#define MEMORY_ADDR_BIT_MASK 0x4 +#define MEMORY_NODE_VALID_BIT_MASK 0x8 +#define MEMORY_CARD_VALID_BIT_MASK 0x10 +#define MEMORY_MODULE_VALID_BIT_MASK 0x20 +#define MEMORY_BANK_VALID_BIT_MASK 0x40 +#define MEMORY_DEVICE_VALID_BIT_MASK 0x80 +#define MEMORY_ROW_VALID_BIT_MASK 0x100 +#define MEMORY_COLUMN_VALID_BIT_MASK 0x200 +#define MEMORY_BIT_POSITION_VALID_BIT_MASK 0x400 +#define MEMORY_PLATFORM_REQUESTOR_ID_VALID_BIT_MASK 0x800 +#define MEMORY_PLATFORM_RESPONDER_ID_VALID_BIT_MASK 0x1000 +#define MEMORY_PLATFORM_TARGET_VALID_BIT_MASK 0x2000 +#define MEMORY_PLATFORM_BUS_SPECIFIC_DATA_VALID_BIT_MASK 0x4000 +#define MEMORY_PLATFORM_OEM_ID_VALID_BIT_MASK 0x8000 +#define MEMORY_PLATFORM_OEM_DATA_STRUCT_VALID_BIT_MASK 0x10000 +/// +/// Definition of Platform Memory Device Error Info Record. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 MemErrorStatus; + UINT64 MemPhysicalAddress; + UINT64 MemPhysicalAddressMask; + UINT16 MemNode; + UINT16 MemCard; + UINT16 MemModule; + UINT16 MemBank; + UINT16 MemDevice; + UINT16 MemRow; + UINT16 MemColumn; + UINT16 MemBitPosition; + UINT64 ModRequestorId; + UINT64 ModResponderId; + UINT64 ModTargetId; + UINT64 BusSpecificData; + UINT8 MemPlatformOemId[16]; +} SAL_MEMORY_ERROR_RECORD; + +/// +/// GUID of Platform PCI Bus Error Info. +/// +#define SAL_PCI_BUS_ERROR_RECORD_INFO \ + { \ + 0xe429faf4, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for SAL_PCI_BUS_ERROR_RECORD.ValidationBits +// +#define PCI_BUS_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define PCI_BUS_ERROR_TYPE_VALID_BIT_MASK 0x2 +#define PCI_BUS_ID_VALID_BIT_MASK 0x4 +#define PCI_BUS_ADDRESS_VALID_BIT_MASK 0x8 +#define PCI_BUS_DATA_VALID_BIT_MASK 0x10 +#define PCI_BUS_CMD_VALID_BIT_MASK 0x20 +#define PCI_BUS_REQUESTOR_ID_VALID_BIT_MASK 0x40 +#define PCI_BUS_RESPONDER_ID_VALID_BIT_MASK 0x80 +#define PCI_BUS_TARGET_VALID_BIT_MASK 0x100 +#define PCI_BUS_OEM_ID_VALID_BIT_MASK 0x200 +#define PCI_BUS_OEM_DATA_STRUCT_VALID_BIT_MASK 0x400 + +/// +/// Designated PCI Bus identifier. +/// +typedef struct { + UINT8 BusNumber; + UINT8 SegmentNumber; +} PCI_BUS_ID; + +/// +/// Definition of Platform PCI Bus Error Info Record. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 PciBusErrorStatus; + UINT16 PciBusErrorType; + PCI_BUS_ID PciBusId; + UINT32 Reserved; + UINT64 PciBusAddress; + UINT64 PciBusData; + UINT64 PciBusCommand; + UINT64 PciBusRequestorId; + UINT64 PciBusResponderId; + UINT64 PciBusTargetId; + UINT8 PciBusOemId[16]; +} SAL_PCI_BUS_ERROR_RECORD; + +/// +/// GUID of Platform PCI Component Error Info. +/// +#define SAL_PCI_COMP_ERROR_RECORD_INFO \ + { \ + 0xe429faf6, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for SAL_PCI_COMPONENT_ERROR_RECORD.ValidationBits +// +#define PCI_COMP_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define PCI_COMP_INFO_VALID_BIT_MASK 0x2 +#define PCI_COMP_MEM_NUM_VALID_BIT_MASK 0x4 +#define PCI_COMP_IO_NUM_VALID_BIT_MASK 0x8 +#define PCI_COMP_REG_DATA_PAIR_VALID_BIT_MASK 0x10 +#define PCI_COMP_OEM_DATA_STRUCT_VALID_BIT_MASK 0x20 +/// +/// Format of PCI Component Information to identify the device. +/// +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT8 ClassCode[3]; + UINT8 FunctionNumber; + UINT8 DeviceNumber; + UINT8 BusNumber; + UINT8 SegmentNumber; + UINT8 Reserved[5]; +} PCI_COMP_INFO; +/// +/// Definition of Platform PCI Component Error Info. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 PciComponentErrorStatus; + PCI_COMP_INFO PciComponentInfo; + UINT32 PciComponentMemNum; + UINT32 PciComponentIoNum; + UINT8 PciBusOemId[16]; +} SAL_PCI_COMPONENT_ERROR_RECORD; + +/// +/// Platform SEL Device Error Info. +/// +#define SAL_SEL_DEVICE_ERROR_RECORD_INFO \ + { \ + 0xe429faf3, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for SAL_SEL_DEVICE_ERROR_RECORD.ValidationBits +// +#define SEL_RECORD_ID_VALID_BIT_MASK 0x1; +#define SEL_RECORD_TYPE_VALID_BIT_MASK 0x2; +#define SEL_GENERATOR_ID_VALID_BIT_MASK 0x4; +#define SEL_EVM_REV_VALID_BIT_MASK 0x8; +#define SEL_SENSOR_TYPE_VALID_BIT_MASK 0x10; +#define SEL_SENSOR_NUM_VALID_BIT_MASK 0x20; +#define SEL_EVENT_DIR_TYPE_VALID_BIT_MASK 0x40; +#define SEL_EVENT_DATA1_VALID_BIT_MASK 0x80; +#define SEL_EVENT_DATA2_VALID_BIT_MASK 0x100; +#define SEL_EVENT_DATA3_VALID_BIT_MASK 0x200; +/// +/// Definition of Platform SEL Device Error Info Record. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT16 SelRecordId; + UINT8 SelRecordType; + UINT32 TimeStamp; + UINT16 GeneratorId; + UINT8 EvmRevision; + UINT8 SensorType; + UINT8 SensorNum; + UINT8 EventDirType; + UINT8 Data1; + UINT8 Data2; + UINT8 Data3; +} SAL_SEL_DEVICE_ERROR_RECORD; + +/// +/// GUID of Platform SMBIOS Device Error Info. +/// +#define SAL_SMBIOS_ERROR_RECORD_INFO \ + { \ + 0xe429faf5, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for SAL_SMBIOS_DEVICE_ERROR_RECORD.ValidationBits +// +#define SMBIOS_EVENT_TYPE_VALID_BIT_MASK 0x1 +#define SMBIOS_LENGTH_VALID_BIT_MASK 0x2 +#define SMBIOS_TIME_STAMP_VALID_BIT_MASK 0x4 +#define SMBIOS_DATA_VALID_BIT_MASK 0x8 +/// +/// Definition of Platform SMBIOS Device Error Info Record. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT8 SmbiosEventType; + UINT8 SmbiosLength; + UINT8 SmbiosBcdTimeStamp[6]; +} SAL_SMBIOS_DEVICE_ERROR_RECORD; + +/// +/// GUID of Platform Specific Error Info. +/// +#define SAL_PLATFORM_ERROR_RECORD_INFO \ + { \ + 0xe429faf7, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +// +// Bit masks for SAL_PLATFORM_SPECIFIC_ERROR_RECORD.ValidationBits +// +#define PLATFORM_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define PLATFORM_REQUESTOR_ID_VALID_BIT_MASK 0x2 +#define PLATFORM_RESPONDER_ID_VALID_BIT_MASK 0x4 +#define PLATFORM_TARGET_VALID_BIT_MASK 0x8 +#define PLATFORM_SPECIFIC_DATA_VALID_BIT_MASK 0x10 +#define PLATFORM_OEM_ID_VALID_BIT_MASK 0x20 +#define PLATFORM_OEM_DATA_STRUCT_VALID_BIT_MASK 0x40 +#define PLATFORM_OEM_DEVICE_PATH_VALID_BIT_MASK 0x80 +/// +/// Definition of Platform Specific Error Info Record. +/// +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 PlatformErrorStatus; + UINT64 PlatformRequestorId; + UINT64 PlatformResponderId; + UINT64 PlatformTargetId; + UINT64 PlatformBusSpecificData; + UINT8 OemComponentId[16]; +} SAL_PLATFORM_SPECIFIC_ERROR_RECORD; + +/// +/// Union of all the possible SAL Error Record Types. +/// +typedef union { + SAL_RECORD_HEADER *RecordHeader; + SAL_PROCESSOR_ERROR_RECORD *SalProcessorRecord; + SAL_PCI_BUS_ERROR_RECORD *SalPciBusRecord; + SAL_PCI_COMPONENT_ERROR_RECORD *SalPciComponentRecord; + SAL_SEL_DEVICE_ERROR_RECORD *ImpiRecord; + SAL_SMBIOS_DEVICE_ERROR_RECORD *SmbiosRecord; + SAL_PLATFORM_SPECIFIC_ERROR_RECORD *PlatformRecord; + SAL_MEMORY_ERROR_RECORD *MemoryRecord; + UINT8 *Raw; +} SAL_ERROR_RECORDS_POINTERS; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Scsi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Scsi.h new file mode 100644 index 0000000..5706f3a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Scsi.h @@ -0,0 +1,412 @@ +/** @file + Support for SCSI-2 standard + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SCSI_H__ +#define __SCSI_H__ + +// +// SCSI command OP Code +// +// +// Commands for all device types +// +#define EFI_SCSI_OP_CHANGE_DEFINITION 0x40 +#define EFI_SCSI_OP_COMPARE 0x39 +#define EFI_SCSI_OP_COPY 0x18 +#define EFI_SCSI_OP_COPY_VERIFY 0x3a +#define EFI_SCSI_OP_INQUIRY 0x12 +#define EFI_SCSI_OP_LOG_SELECT 0x4c +#define EFI_SCSI_OP_LOG_SENSE 0x4d +#define EFI_SCSI_OP_MODE_SEL6 0x15 +#define EFI_SCSI_OP_MODE_SEL10 0x55 +#define EFI_SCSI_OP_MODE_SEN6 0x1a +#define EFI_SCSI_OP_MODE_SEN10 0x5a +#define EFI_SCSI_OP_READ_BUFFER 0x3c +#define EFI_SCSI_OP_RECEIVE_DIAG 0x1c +#define EFI_SCSI_OP_REQUEST_SENSE 0x03 +#define EFI_SCSI_OP_SEND_DIAG 0x1d +#define EFI_SCSI_OP_TEST_UNIT_READY 0x00 +#define EFI_SCSI_OP_WRITE_BUFF 0x3b + +// +// Additional commands for Direct Access Devices +// +#define EFI_SCSI_OP_FORMAT 0x04 +#define EFI_SCSI_OP_LOCK_UN_CACHE 0x36 +#define EFI_SCSI_OP_PREFETCH 0x34 +#define EFI_SCSI_OP_MEDIA_REMOVAL 0x1e +#define EFI_SCSI_OP_READ6 0x08 +#define EFI_SCSI_OP_READ10 0x28 +#define EFI_SCSI_OP_READ16 0x88 +#define EFI_SCSI_OP_READ_CAPACITY 0x25 +#define EFI_SCSI_OP_READ_CAPACITY16 0x9e +#define EFI_SCSI_OP_READ_DEFECT 0x37 +#define EFI_SCSI_OP_READ_LONG 0x3e +#define EFI_SCSI_OP_REASSIGN_BLK 0x07 +#define EFI_SCSI_OP_RELEASE 0x17 +#define EFI_SCSI_OP_REZERO 0x01 +#define EFI_SCSI_OP_SEARCH_DATA_E 0x31 +#define EFI_SCSI_OP_SEARCH_DATA_H 0x30 +#define EFI_SCSI_OP_SEARCH_DATA_L 0x32 +#define EFI_SCSI_OP_SEEK6 0x0b +#define EFI_SCSI_OP_SEEK10 0x2b +#define EFI_SCSI_OP_SEND_DIAG 0x1d +#define EFI_SCSI_OP_SET_LIMIT 0x33 +#define EFI_SCSI_OP_START_STOP_UNIT 0x1b +#define EFI_SCSI_OP_SYNC_CACHE 0x35 +#define EFI_SCSI_OP_VERIFY 0x2f +#define EFI_SCSI_OP_WRITE6 0x0a +#define EFI_SCSI_OP_WRITE10 0x2a +#define EFI_SCSI_OP_WRITE16 0x8a +#define EFI_SCSI_OP_WRITE_VERIFY 0x2e +#define EFI_SCSI_OP_WRITE_LONG 0x3f +#define EFI_SCSI_OP_WRITE_SAME 0x41 +#define EFI_SCSI_OP_UNMAP 0x42 + +// +// Additional commands for Sequential Access Devices +// +#define EFI_SCSI_OP_ERASE 0x19 +#define EFI_SCSI_OP_LOAD_UNLOAD 0x1b +#define EFI_SCSI_OP_LOCATE 0x2b +#define EFI_SCSI_OP_READ_BLOCK_LIMIT 0x05 +#define EFI_SCSI_OP_READ_POS 0x34 +#define EFI_SCSI_OP_READ_REVERSE 0x0f +#define EFI_SCSI_OP_RECOVER_BUF_DATA 0x14 +#define EFI_SCSI_OP_RESERVE_UNIT 0x16 +#define EFI_SCSI_OP_REWIND 0x01 +#define EFI_SCSI_OP_SPACE 0x11 +#define EFI_SCSI_OP_VERIFY_TAPE 0x13 +#define EFI_SCSI_OP_WRITE_FILEMARK 0x10 + +// +// Additional commands for Printer Devices +// +#define EFI_SCSI_OP_PRINT 0x0a +#define EFI_SCSI_OP_SLEW_PRINT 0x0b +#define EFI_SCSI_OP_STOP_PRINT 0x1b +#define EFI_SCSI_OP_SYNC_BUFF 0x10 + +// +// Additional commands for Processor Devices +// +#define EFI_SCSI_OP_RECEIVE 0x08 +#define EFI_SCSI_OP_SEND 0x0a + +// +// Additional commands for Write-Once Devices +// +#define EFI_SCSI_OP_MEDIUM_SCAN 0x38 +#define EFI_SCSI_OP_SEARCH_DAT_E10 0x31 +#define EFI_SCSI_OP_SEARCH_DAT_E12 0xb1 +#define EFI_SCSI_OP_SEARCH_DAT_H10 0x30 +#define EFI_SCSI_OP_SEARCH_DAT_H12 0xb0 +#define EFI_SCSI_OP_SEARCH_DAT_L10 0x32 +#define EFI_SCSI_OP_SEARCH_DAT_L12 0xb2 +#define EFI_SCSI_OP_SET_LIMIT10 0x33 +#define EFI_SCSI_OP_SET_LIMIT12 0xb3 +#define EFI_SCSI_OP_VERIFY10 0x2f +#define EFI_SCSI_OP_VERIFY12 0xaf +#define EFI_SCSI_OP_WRITE12 0xaa +#define EFI_SCSI_OP_WRITE_VERIFY10 0x2e +#define EFI_SCSI_OP_WRITE_VERIFY12 0xae + +// +// Additional commands for CD-ROM Devices +// +#define EFI_SCSI_OP_PLAY_AUD_10 0x45 +#define EFI_SCSI_OP_PLAY_AUD_12 0xa5 +#define EFI_SCSI_OP_PLAY_AUD_MSF 0x47 +#define EFI_SCSI_OP_PLAY_AUD_TKIN 0x48 +#define EFI_SCSI_OP_PLAY_TK_REL10 0x49 +#define EFI_SCSI_OP_PLAY_TK_REL12 0xa9 +#define EFI_SCSI_OP_READ_CD_CAPACITY 0x25 +#define EFI_SCSI_OP_READ_HEADER 0x44 +#define EFI_SCSI_OP_READ_SUB_CHANNEL 0x42 +#define EFI_SCSI_OP_READ_TOC 0x43 + +// +// Additional commands for Scanner Devices +// +#define EFI_SCSI_OP_GET_DATABUFF_STAT 0x34 +#define EFI_SCSI_OP_GET_WINDOW 0x25 +#define EFI_SCSI_OP_OBJECT_POS 0x31 +#define EFI_SCSI_OP_SCAN 0x1b +#define EFI_SCSI_OP_SET_WINDOW 0x24 + +// +// Additional commands for Optical Memory Devices +// +#define EFI_SCSI_OP_UPDATE_BLOCK 0x3d + +// +// Additional commands for Medium Changer Devices +// +#define EFI_SCSI_OP_EXCHANGE_MEDIUM 0xa6 +#define EFI_SCSI_OP_INIT_ELEMENT_STAT 0x07 +#define EFI_SCSI_OP_POS_TO_ELEMENT 0x2b +#define EFI_SCSI_OP_REQUEST_VE_ADDR 0xb5 +#define EFI_SCSI_OP_SEND_VOL_TAG 0xb6 + +// +// Additional commands for Communition Devices +// +#define EFI_SCSI_OP_GET_MESSAGE6 0x08 +#define EFI_SCSI_OP_GET_MESSAGE10 0x28 +#define EFI_SCSI_OP_GET_MESSAGE12 0xa8 +#define EFI_SCSI_OP_SEND_MESSAGE6 0x0a +#define EFI_SCSI_OP_SEND_MESSAGE10 0x2a +#define EFI_SCSI_OP_SEND_MESSAGE12 0xaa + +// +// SCSI Data Transfer Direction +// +#define EFI_SCSI_DATA_IN 0 +#define EFI_SCSI_DATA_OUT 1 + +// +// Peripheral Device Type Definitions +// +#define EFI_SCSI_TYPE_DISK 0x00 ///< Direct-access device (e.g. magnetic disk) +#define EFI_SCSI_TYPE_TAPE 0x01 ///< Sequential-access device (e.g. magnetic tape) +#define EFI_SCSI_TYPE_PRINTER 0x02 ///< Printer device +#define EFI_SCSI_TYPE_PROCESSOR 0x03 ///< Processor device +#define EFI_SCSI_TYPE_WORM 0x04 ///< Write-once device (e.g. some optical disks) +#define EFI_SCSI_TYPE_CDROM 0x05 ///< CD-ROM device +#define EFI_SCSI_TYPE_SCANNER 0x06 ///< Scanner device +#define EFI_SCSI_TYPE_OPTICAL 0x07 ///< Optical memory device (e.g. some optical disks) +#define EFI_SCSI_TYPE_MEDIUMCHANGER 0x08 ///< Medium changer device (e.g. jukeboxes) +#define EFI_SCSI_TYPE_COMMUNICATION 0x09 ///< Communications device +#define EFI_SCSI_TYPE_ASCIT8_1 0x0A ///< Defined by ASC IT8 (Graphic arts pre-press devices) +#define EFI_SCSI_TYPE_ASCIT8_2 0x0B ///< Defined by ASC IT8 (Graphic arts pre-press devices) +// +// 0Ch - 1Eh are reserved +// +#define EFI_SCSI_TYPE_UNKNOWN 0x1F ///< Unknown or no device type + +// +// Page Codes for INQUIRY command +// +#define EFI_SCSI_PAGE_CODE_SUPPORTED_VPD 0x00 +#define EFI_SCSI_PAGE_CODE_BLOCK_LIMITS_VPD 0xB0 + +#pragma pack(1) +/// +/// Standard INQUIRY data format +/// +typedef struct { + UINT8 Peripheral_Type : 5; + UINT8 Peripheral_Qualifier : 3; + UINT8 DeviceType_Modifier : 7; + UINT8 Rmb : 1; + UINT8 Version; + UINT8 Response_Data_Format; + UINT8 Addnl_Length; + UINT8 Reserved_5_95[95 - 5 + 1]; +} EFI_SCSI_INQUIRY_DATA; + +/// +/// Supported VPD Pages VPD page +/// +typedef struct { + UINT8 Peripheral_Type : 5; + UINT8 Peripheral_Qualifier : 3; + UINT8 PageCode; + UINT8 PageLength2; + UINT8 PageLength1; + UINT8 SupportedVpdPageList[0x100]; +} EFI_SCSI_SUPPORTED_VPD_PAGES_VPD_PAGE; + +/// +/// Block Limits VPD page +/// +typedef struct { + UINT8 Peripheral_Type : 5; + UINT8 Peripheral_Qualifier : 3; + UINT8 PageCode; + UINT8 PageLength2; + UINT8 PageLength1; + UINT8 WriteSameNonZero : 1; + UINT8 Reserved_4 : 7; + UINT8 MaximumCompareAndWriteLength; + UINT8 OptimalTransferLengthGranularity2; + UINT8 OptimalTransferLengthGranularity1; + UINT8 MaximumTransferLength4; + UINT8 MaximumTransferLength3; + UINT8 MaximumTransferLength2; + UINT8 MaximumTransferLength1; + UINT8 OptimalTransferLength4; + UINT8 OptimalTransferLength3; + UINT8 OptimalTransferLength2; + UINT8 OptimalTransferLength1; + UINT8 MaximumPrefetchXdreadXdwriteTransferLength4; + UINT8 MaximumPrefetchXdreadXdwriteTransferLength3; + UINT8 MaximumPrefetchXdreadXdwriteTransferLength2; + UINT8 MaximumPrefetchXdreadXdwriteTransferLength1; + UINT8 MaximumUnmapLbaCount4; + UINT8 MaximumUnmapLbaCount3; + UINT8 MaximumUnmapLbaCount2; + UINT8 MaximumUnmapLbaCount1; + UINT8 MaximumUnmapBlockDescriptorCount4; + UINT8 MaximumUnmapBlockDescriptorCount3; + UINT8 MaximumUnmapBlockDescriptorCount2; + UINT8 MaximumUnmapBlockDescriptorCount1; + UINT8 OptimalUnmapGranularity4; + UINT8 OptimalUnmapGranularity3; + UINT8 OptimalUnmapGranularity2; + UINT8 OptimalUnmapGranularity1; + UINT8 UnmapGranularityAlignment4 : 7; + UINT8 UnmapGranularityAlignmentValid : 1; + UINT8 UnmapGranularityAlignment3; + UINT8 UnmapGranularityAlignment2; + UINT8 UnmapGranularityAlignment1; + UINT8 MaximumWriteSameLength4; + UINT8 MaximumWriteSameLength3; + UINT8 MaximumWriteSameLength2; + UINT8 MaximumWriteSameLength1; + UINT8 MaximumAtomicTransferLength4; + UINT8 MaximumAtomicTransferLength3; + UINT8 MaximumAtomicTransferLength2; + UINT8 MaximumAtomicTransferLength1; + UINT8 AtomicAlignment4; + UINT8 AtomicAlignment3; + UINT8 AtomicAlignment2; + UINT8 AtomicAlignment1; + UINT8 AtomicTransferLengthGranularity4; + UINT8 AtomicTransferLengthGranularity3; + UINT8 AtomicTransferLengthGranularity2; + UINT8 AtomicTransferLengthGranularity1; + UINT8 MaximumAtomicTransferLengthWithAtomicBoundary4; + UINT8 MaximumAtomicTransferLengthWithAtomicBoundary3; + UINT8 MaximumAtomicTransferLengthWithAtomicBoundary2; + UINT8 MaximumAtomicTransferLengthWithAtomicBoundary1; + UINT8 MaximumAtomicBoundarySize4; + UINT8 MaximumAtomicBoundarySize3; + UINT8 MaximumAtomicBoundarySize2; + UINT8 MaximumAtomicBoundarySize1; +} EFI_SCSI_BLOCK_LIMITS_VPD_PAGE; + +/// +/// Error codes 70h and 71h sense data format +/// +typedef struct { + UINT8 Error_Code : 7; + UINT8 Valid : 1; + UINT8 Segment_Number; + UINT8 Sense_Key : 4; + UINT8 Reserved_21 : 1; + UINT8 Ili : 1; + UINT8 Reserved_22 : 2; + UINT8 Information_3_6[4]; + UINT8 Addnl_Sense_Length; ///< Additional sense length (n-7) + UINT8 Vendor_Specific_8_11[4]; + UINT8 Addnl_Sense_Code; ///< Additional sense code + UINT8 Addnl_Sense_Code_Qualifier; ///< Additional sense code qualifier + UINT8 Field_Replaceable_Unit_Code; ///< Field replaceable unit code + UINT8 Reserved_15_17[3]; +} EFI_SCSI_SENSE_DATA; + +/// +/// SCSI Disk READ CAPACITY Data +/// +typedef struct { + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 BlockSize3; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} EFI_SCSI_DISK_CAPACITY_DATA; + +typedef struct { + UINT8 LastLba7; + UINT8 LastLba6; + UINT8 LastLba5; + UINT8 LastLba4; + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 BlockSize3; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; + UINT8 Protection; + UINT8 LogicPerPhysical; + UINT8 LowestAlignLogic2; + UINT8 LowestAlignLogic1; + UINT8 Reserved[16]; +} EFI_SCSI_DISK_CAPACITY_DATA16; + +typedef struct { + UINT16 DataLen; + UINT16 BlkDespDataLen; + UINT8 Reserved[4]; +} EFI_SCSI_DISK_UNMAP_PARAM_LIST_HEADER; + +typedef struct { + UINT64 Lba; + UINT32 BlockNum; + UINT8 Reserved[4]; +} EFI_SCSI_DISK_UNMAP_BLOCK_DESP; + + +#pragma pack() + +// +// Sense Key +// +#define EFI_SCSI_SK_NO_SENSE (0x0) +#define EFI_SCSI_SK_RECOVERY_ERROR (0x1) +#define EFI_SCSI_SK_NOT_READY (0x2) +#define EFI_SCSI_SK_MEDIUM_ERROR (0x3) +#define EFI_SCSI_SK_HARDWARE_ERROR (0x4) +#define EFI_SCSI_SK_ILLEGAL_REQUEST (0x5) +#define EFI_SCSI_SK_UNIT_ATTENTION (0x6) +#define EFI_SCSI_SK_DATA_PROTECT (0x7) +#define EFI_SCSI_SK_BLANK_CHECK (0x8) +#define EFI_SCSI_SK_VENDOR_SPECIFIC (0x9) +#define EFI_SCSI_SK_RESERVED_A (0xA) +#define EFI_SCSI_SK_ABORT (0xB) +#define EFI_SCSI_SK_RESERVED_C (0xC) +#define EFI_SCSI_SK_OVERFLOW (0xD) +#define EFI_SCSI_SK_MISCOMPARE (0xE) +#define EFI_SCSI_SK_RESERVED_F (0xF) + +// +// Additional Sense Codes and Sense Code Qualifiers. +// Only some frequently used additional sense codes and qualifiers are +// defined here. Please refer to SCSI standard for full value definition. +// +#define EFI_SCSI_ASC_NOT_READY (0x04) +#define EFI_SCSI_ASCQ_IN_PROGRESS (0x01) + +#define EFI_SCSI_ASC_MEDIA_ERR1 (0x10) +#define EFI_SCSI_ASC_MEDIA_ERR2 (0x11) +#define EFI_SCSI_ASC_MEDIA_ERR3 (0x14) +#define EFI_SCSI_ASC_MEDIA_ERR4 (0x30) +#define EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN (0x06) +#define EFI_SCSI_ASC_INVALID_CMD (0x20) +#define EFI_SCSI_ASC_LBA_OUT_OF_RANGE (0x21) +#define EFI_SCSI_ASC_INVALID_FIELD (0x24) +#define EFI_SCSI_ASC_WRITE_PROTECTED (0x27) +#define EFI_SCSI_ASC_MEDIA_CHANGE (0x28) +#define EFI_SCSI_ASC_RESET (0x29) ///< Power On Reset or Bus Reset occurred +#define EFI_SCSI_ASC_ILLEGAL_FIELD (0x26) +#define EFI_SCSI_ASC_NO_MEDIA (0x3A) +#define EFI_SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64) + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sd.h new file mode 100644 index 0000000..693dfcf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Sd.h @@ -0,0 +1,181 @@ +/** @file + Header file for SD memory card support. + + This header file contains some definitions defined in SD Physical Layer Simplified + Specification Version 4.10 spec. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SD_H__ +#define __SD_H__ + +// +// SD command index +// +#define SD_GO_IDLE_STATE 0 +#define SD_ALL_SEND_CID 2 +#define SD_SET_RELATIVE_ADDR 3 +#define SD_SET_DSR 4 +#define SDIO_SEND_OP_COND 5 +#define SD_SWITCH_FUNC 6 +#define SD_SELECT_DESELECT_CARD 7 +#define SD_SEND_IF_COND 8 +#define SD_SEND_CSD 9 +#define SD_SEND_CID 10 +#define SD_VOLTAGE_SWITCH 11 +#define SD_STOP_TRANSMISSION 12 +#define SD_SEND_STATUS 13 +#define SD_GO_INACTIVE_STATE 15 +#define SD_SET_BLOCKLEN 16 +#define SD_READ_SINGLE_BLOCK 17 +#define SD_READ_MULTIPLE_BLOCK 18 +#define SD_SEND_TUNING_BLOCK 19 +#define SD_SPEED_CLASS_CONTROL 20 +#define SD_SET_BLOCK_COUNT 23 +#define SD_WRITE_SINGLE_BLOCK 24 +#define SD_WRITE_MULTIPLE_BLOCK 25 +#define SD_PROGRAM_CSD 27 +#define SD_SET_WRITE_PROT 28 +#define SD_CLR_WRITE_PROT 29 +#define SD_SEND_WRITE_PROT 30 +#define SD_ERASE_WR_BLK_START 32 +#define SD_ERASE_WR_BLK_END 33 +#define SD_ERASE 38 +#define SD_LOCK_UNLOCK 42 +#define SD_READ_EXTR_SINGLE 48 +#define SD_WRITE_EXTR_SINGLE 49 +#define SDIO_RW_DIRECT 52 +#define SDIO_RW_EXTENDED 53 +#define SD_APP_CMD 55 +#define SD_GEN_CMD 56 +#define SD_READ_EXTR_MULTI 58 +#define SD_WRITE_EXTR_MULTI 59 + +#define SD_SET_BUS_WIDTH 6 // ACMD6 +#define SD_STATUS 13 // ACMD13 +#define SD_SEND_NUM_WR_BLOCKS 22 // ACMD22 +#define SD_SET_WR_BLK_ERASE_COUNT 23 // ACMD23 +#define SD_SEND_OP_COND 41 // ACMD41 +#define SD_SET_CLR_CARD_DETECT 42 // ACMD42 +#define SD_SEND_SCR 51 // ACMD51 + +#pragma pack(1) +typedef struct { + UINT8 NotUsed:1; // Not used [0:0] + UINT8 Crc:7; // CRC [7:1] + UINT16 ManufacturingDate:12; // Manufacturing date [19:8] + UINT16 Reserved:4; // Reserved [23:20] + UINT8 ProductSerialNumber[4]; // Product serial number [55:24] + UINT8 ProductRevision; // Product revision [63:56] + UINT8 ProductName[5]; // Product name [103:64] + UINT8 OemId[2]; // OEM/Application ID [119:104] + UINT8 ManufacturerId; // Manufacturer ID [127:120] +} SD_CID; + +typedef struct { + UINT32 NotUsed:1; // Not used [0:0] + UINT32 Crc:7; // CRC [7:1] + UINT32 Reserved:2; // Reserved [9:8] + UINT32 FileFormat:2; // File format [11:10] + UINT32 TmpWriteProtect:1; // Temporary write protection [12:12] + UINT32 PermWriteProtect:1; // Permanent write protection [13:13] + UINT32 Copy:1; // Copy flag (OTP) [14:14] + UINT32 FileFormatGrp:1; // File format group [15:15] + UINT32 Reserved1:5; // Reserved [20:16] + UINT32 WriteBlPartial:1; // Partial blocks for write allowed [21:21] + UINT32 WriteBlLen:4; // Max. write data block length [25:22] + UINT32 R2WFactor:3; // Write speed factor [28:26] + UINT32 Reserved2:2; // Manufacturer default ECC [30:29] + UINT32 WpGrpEnable:1; // Write protect group enable [31:31] + + UINT32 WpGrpSize:7; // Write protect group size [38:32] + UINT32 SectorSize:7; // Erase sector size [45:39] + UINT32 EraseBlkEn:1; // Erase single block enable [46:46] + UINT32 CSizeMul:3; // device size multiplier [49:47] + UINT32 VddWCurrMax:3; // max. write current @VDD max [52:50] + UINT32 VddWCurrMin:3; // max. write current @VDD min [55:53] + UINT32 VddRCurrMax:3; // max. read current @VDD max [58:56] + UINT32 VddRCurrMin:3; // max. read current @VDD min [61:59] + UINT32 CSizeLow:2; // Device size low 2 bits [63:62] + + UINT32 CSizeHigh:10; // Device size high 10 bits [73:64] + UINT32 Reserved4:2; // Reserved [75:74] + UINT32 DsrImp:1; // DSR implemented [76:76] + UINT32 ReadBlkMisalign:1; // Read block misalignment [77:77] + UINT32 WriteBlkMisalign:1; // Write block misalignment [78:78] + UINT32 ReadBlPartial:1; // Partial blocks for read allowed [79:79] + UINT32 ReadBlLen:4; // Max. read data block length [83:80] + UINT32 Ccc:12; // Card command classes [95:84] + + UINT32 TranSpeed:8; // Max. data transfer rate [103:96] + UINT32 Nsac:8; // Data read access-time in CLK cycles (NSAC*100) [111:104] + UINT32 Taac:8; // Data read access-time [119:112] + UINT32 Reserved5:6; // Reserved [125:120] + UINT32 CsdStructure:2; // CSD structure [127:126] +} SD_CSD; + +typedef struct { + UINT32 NotUsed:1; // Not used [0:0] + UINT32 Crc:7; // CRC [7:1] + UINT32 Reserved:2; // Reserved [9:8] + UINT32 FileFormat:2; // File format [11:10] + UINT32 TmpWriteProtect:1; // Temporary write protection [12:12] + UINT32 PermWriteProtect:1; // Permanent write protection [13:13] + UINT32 Copy:1; // Copy flag (OTP) [14:14] + UINT32 FileFormatGrp:1; // File format group [15:15] + UINT32 Reserved1:5; // Reserved [20:16] + UINT32 WriteBlPartial:1; // Partial blocks for write allowed [21:21] + UINT32 WriteBlLen:4; // Max. write data block length [25:22] + UINT32 R2WFactor:3; // Write speed factor [28:26] + UINT32 Reserved2:2; // Manufacturer default ECC [30:29] + UINT32 WpGrpEnable:1; // Write protect group enable [31:31] + + UINT32 WpGrpSize:7; // Write protect group size [38:32] + UINT32 SectorSize:7; // Erase sector size [45:39] + UINT32 EraseBlkEn:1; // Erase single block enable [46:46] + UINT32 Reserved3:1; // Reserved [47:47] + UINT32 CSizeLow:16; // Device size low 16 bits [63:48] + + UINT32 CSizeHigh:6; // Device size high 6 bits [69:64] + UINT32 Reserved4:6; // Reserved [75:70] + UINT32 DsrImp:1; // DSR implemented [76:76] + UINT32 ReadBlkMisalign:1; // Read block misalignment [77:77] + UINT32 WriteBlkMisalign:1; // Write block misalignment [78:78] + UINT32 ReadBlPartial:1; // Partial blocks for read allowed [79:79] + UINT32 ReadBlLen:4; // Max. read data block length [83:80] + UINT32 Ccc:12; // Card command classes [95:84] + + UINT32 TranSpeed:8; // Max. data transfer rate [103:96] + UINT32 Nsac:8; // Data read access-time in CLK cycles (NSAC*100) [111:104] + UINT32 Taac:8; // Data read access-time [119:112] + UINT32 Reserved5:6; // Reserved [125:120] + UINT32 CsdStructure:2; // CSD structure [127:126] +} SD_CSD2; + +typedef struct { + UINT32 Reserved; // Reserved [31:0] + + UINT32 CmdSupport:4; // Command Support bits [35:32] + UINT32 Reserved1:6; // Reserved [41:36] + UINT32 SdSpec4:1; // Spec. Version 4.00 or higher [42:42] + UINT32 ExSecurity:4; // Extended Security Support [46:43] + UINT32 SdSpec3:1; // Spec. Version 3.00 or higher [47:47] + UINT32 SdBusWidths:4; // DAT Bus widths supported [51:48] + UINT32 SdSecurity:3; // CPRM security support [54:52] + UINT32 DataStatAfterErase:1; // Data status after erases [55] + UINT32 SdSpec:4; // SD Memory Card Spec. Version [59:56] + UINT32 ScrStructure:4; // SCR Structure [63:60] +} SD_SCR; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpd.h new file mode 100644 index 0000000..0a4d894 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpd.h @@ -0,0 +1,74 @@ +/** @file + This file contains definitions for the SPD fields on an SDRAM. + + Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _SDRAM_SPD_H_ +#define _SDRAM_SPD_H_ + +#include +#include +#include + +// +// SDRAM SPD field definitions +// +#define SPD_MEMORY_TYPE 2 +#define SPD_SDRAM_ROW_ADDR 3 +#define SPD_SDRAM_COL_ADDR 4 +#define SPD_SDRAM_MODULE_ROWS 5 +#define SPD_SDRAM_MODULE_DATA_WIDTH_LSB 6 +#define SPD_SDRAM_MODULE_DATA_WIDTH_MSB 7 +#define SPD_SDRAM_ECC_SUPPORT 11 +#define SPD_SDRAM_REFRESH 12 +#define SPD_SDRAM_WIDTH 13 +#define SPD_SDRAM_ERROR_WIDTH 14 +#define SPD_SDRAM_BURST_LENGTH 16 +#define SPD_SDRAM_NO_OF_BANKS 17 +#define SPD_SDRAM_CAS_LATENCY 18 +#define SPD_SDRAM_MODULE_ATTR 21 + +#define SPD_SDRAM_TCLK1_PULSE 9 ///< cycle time for highest cas latency +#define SPD_SDRAM_TAC1_PULSE 10 ///< access time for highest cas latency +#define SPD_SDRAM_TCLK2_PULSE 23 ///< cycle time for 2nd highest cas latency +#define SPD_SDRAM_TAC2_PULSE 24 ///< access time for 2nd highest cas latency +#define SPD_SDRAM_TCLK3_PULSE 25 ///< cycle time for 3rd highest cas latency +#define SPD_SDRAM_TAC3_PULSE 26 ///< access time for 3rd highest cas latency +#define SPD_SDRAM_MIN_PRECHARGE 27 +#define SPD_SDRAM_ACTIVE_MIN 28 +#define SPD_SDRAM_RAS_CAS 29 +#define SPD_SDRAM_RAS_PULSE 30 +#define SPD_SDRAM_DENSITY 31 + +// +// Memory Type Definitions +// +#define SPD_VAL_SDR_TYPE 4 ///< SDR SDRAM memory +#define SPD_VAL_DDR_TYPE 7 ///< DDR SDRAM memory +#define SPD_VAL_DDR2_TYPE 8 ///< DDR2 SDRAM memory +#define SPD_VAL_DDR3_TYPE 11 ///< DDR3 SDRAM memory +#define SPD_VAL_DDR4_TYPE 12 ///< DDR4 SDRAM memory +#define SPD_VAL_LPDDR3_TYPE 15 ///< LPDDR3 SDRAM memory +#define SPD_VAL_LPDDR4_TYPE 16 ///< LPDDR4 SDRAM memory + +// +// ECC Type Definitions +// +#define SPD_ECC_TYPE_NONE 0x00 ///< No error checking +#define SPD_ECC_TYPE_PARITY 0x01 ///< No error checking +#define SPD_ECC_TYPE_ECC 0x02 ///< Error checking only +// +// Module Attributes (Bit positions) +// +#define SPD_BUFFERED 0x01 +#define SPD_REGISTERED 0x02 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr3.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr3.h new file mode 100644 index 0000000..4bcf706 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr3.h @@ -0,0 +1,769 @@ +/** @file + This file contains definitions for SPD DDR3. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - Serial Presence Detect (SPD) for DDR3 SDRAM Modules Document Release 6 + http://www.jedec.org/sites/default/files/docs/4_01_02_11R21A.pdf +**/ + +#ifndef _SDRAM_SPD_DDR3_H_ +#define _SDRAM_SPD_DDR3_H_ + +#pragma pack (push, 1) + +typedef union { + struct { + UINT8 BytesUsed : 4; ///< Bits 3:0 + UINT8 BytesTotal : 3; ///< Bits 6:4 + UINT8 CrcCoverage : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_DEVICE_DESCRIPTION_STRUCT; + +typedef union { + struct { + UINT8 Minor : 4; ///< Bits 3:0 + UINT8 Major : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_REVISION_STRUCT; + +typedef union { + struct { + UINT8 Type : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_DRAM_DEVICE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 ModuleType : 4; ///< Bits 3:0 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_MODULE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 Density : 4; ///< Bits 3:0 + UINT8 BankAddress : 3; ///< Bits 6:4 + UINT8 Reserved : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_SDRAM_DENSITY_BANKS_STRUCT; + +typedef union { + struct { + UINT8 ColumnAddress : 3; ///< Bits 2:0 + UINT8 RowAddress : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_SDRAM_ADDRESSING_STRUCT; + +typedef union { + struct { + UINT8 OperationAt1_50 : 1; ///< Bits 0:0 + UINT8 OperationAt1_35 : 1; ///< Bits 1:1 + UINT8 OperationAt1_25 : 1; ///< Bits 2:2 + UINT8 Reserved : 5; ///< Bits 7:3 + } Bits; + UINT8 Data; +} SPD3_MODULE_NOMINAL_VOLTAGE_STRUCT; + +typedef union { + struct { + UINT8 SdramDeviceWidth : 3; ///< Bits 2:0 + UINT8 RankCount : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_MODULE_ORGANIZATION_STRUCT; + +typedef union { + struct { + UINT8 PrimaryBusWidth : 3; ///< Bits 2:0 + UINT8 BusWidthExtension : 2; ///< Bits 4:3 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD3_MODULE_MEMORY_BUS_WIDTH_STRUCT; + +typedef union { + struct { + UINT8 Divisor : 4; ///< Bits 3:0 + UINT8 Dividend : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_FINE_TIMEBASE_STRUCT; + +typedef union { + struct { + UINT8 Dividend : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_MEDIUM_TIMEBASE_DIVIDEND_STRUCT; + +typedef union { + struct { + UINT8 Divisor : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_MEDIUM_TIMEBASE_DIVISOR_STRUCT; + +typedef struct { + SPD3_MEDIUM_TIMEBASE_DIVIDEND_STRUCT Dividend; ///< Medium Timebase (MTB) Dividend + SPD3_MEDIUM_TIMEBASE_DIVISOR_STRUCT Divisor; ///< Medium Timebase (MTB) Divisor +} SPD3_MEDIUM_TIMEBASE; + +typedef union { + struct { + UINT8 tCKmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TCK_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT16 Cl4 : 1; ///< Bits 0:0 + UINT16 Cl5 : 1; ///< Bits 1:1 + UINT16 Cl6 : 1; ///< Bits 2:2 + UINT16 Cl7 : 1; ///< Bits 3:3 + UINT16 Cl8 : 1; ///< Bits 4:4 + UINT16 Cl9 : 1; ///< Bits 5:5 + UINT16 Cl10 : 1; ///< Bits 6:6 + UINT16 Cl11 : 1; ///< Bits 7:7 + UINT16 Cl12 : 1; ///< Bits 8:8 + UINT16 Cl13 : 1; ///< Bits 9:9 + UINT16 Cl14 : 1; ///< Bits 10:10 + UINT16 Cl15 : 1; ///< Bits 11:11 + UINT16 Cl16 : 1; ///< Bits 12:12 + UINT16 Cl17 : 1; ///< Bits 13:13 + UINT16 Cl18 : 1; ///< Bits 14:14 + UINT16 Reserved : 1; ///< Bits 15:15 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD3_CAS_LATENCIES_SUPPORTED_STRUCT; + +typedef union { + struct { + UINT8 tAAmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TAA_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tWRmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TWR_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRCDmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TRCD_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRRDmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TRRD_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRPmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TRP_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRASminUpper : 4; ///< Bits 3:0 + UINT8 tRCminUpper : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_TRAS_TRC_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRASmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TRAS_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRCmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TRC_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT16 tRFCmin : 16; ///< Bits 15:0 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD3_TRFC_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tWTRmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TWTR_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRTPmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TRTP_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tFAWminUpper : 4; ///< Bits 3:0 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_TFAW_MIN_MTB_UPPER_STRUCT; + +typedef union { + struct { + UINT8 tFAWmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_TFAW_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 Rzq6 : 1; ///< Bits 0:0 + UINT8 Rzq7 : 1; ///< Bits 1:1 + UINT8 Reserved : 5; ///< Bits 6:2 + UINT8 DllOff : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_SDRAM_OPTIONAL_FEATURES_STRUCT; + +typedef union { + struct { + UINT8 ExtendedTemperatureRange : 1; ///< Bits 0:0 + UINT8 ExtendedTemperatureRefreshRate : 1; ///< Bits 1:1 + UINT8 AutoSelfRefresh : 1; ///< Bits 2:2 + UINT8 OnDieThermalSensor : 1; ///< Bits 3:3 + UINT8 Reserved : 3; ///< Bits 6:4 + UINT8 PartialArraySelfRefresh : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_SDRAM_THERMAL_REFRESH_STRUCT; + +typedef union { + struct { + UINT8 ThermalSensorAccuracy : 7; ///< Bits 6:0 + UINT8 ThermalSensorPresence : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_MODULE_THERMAL_SENSOR_STRUCT; + +typedef union { + struct { + UINT8 SignalLoading : 2; ///< Bits 1:0 + UINT8 Reserved : 2; ///< Bits 3:2 + UINT8 DieCount : 3; ///< Bits 6:4 + UINT8 SdramDeviceType : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_SDRAM_DEVICE_TYPE_STRUCT; + +typedef union { + struct { + INT8 tCKminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD3_TCK_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tAAminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD3_TAA_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRCDminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD3_TRCD_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRPminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD3_TRP_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRCminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD3_TRC_MIN_FTB_STRUCT; + +typedef union { + struct { + UINT8 MaximumActivateCount : 4; ///< Bits 3:0 + UINT8 MaximumActivateWindow : 2; ///< Bits 5:4 + UINT8 VendorSpecific : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_MAXIMUM_ACTIVE_COUNT_STRUCT; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 RawCardExtension : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD3_UNBUF_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_UNBUF_MODULE_NOMINAL_THICKNESS; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_UNBUF_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 MappingRank1 : 1; ///< Bits 0:0 + UINT8 Reserved : 7; ///< Bits 7:1 + } Bits; + UINT8 Data; +} SPD3_UNBUF_ADDRESS_MAPPING; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD3_RDIMM_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_RDIMM_MODULE_NOMINAL_THICKNESS; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_RDIMM_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 RegisterCount : 2; ///< Bits 1:0 + UINT8 DramRowCount : 2; ///< Bits 3:2 + UINT8 RegisterType : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_RDIMM_MODULE_ATTRIBUTES; + +typedef union { + struct { + UINT8 HeatSpreaderThermalCharacteristics : 7; ///< Bits 6:0 + UINT8 HeatSpreaderSolution : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_RDIMM_THERMAL_HEAT_SPREADER_SOLUTION; + +typedef union { + struct { + UINT16 ContinuationCount : 7; ///< Bits 6:0 + UINT16 ContinuationParity : 1; ///< Bits 7:7 + UINT16 LastNonZeroByte : 8; ///< Bits 15:8 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD3_MANUFACTURER_ID_CODE; + +typedef union { + struct { + UINT8 RegisterRevisionNumber; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD3_RDIMM_REGISTER_REVISION_NUMBER; + +typedef union { + struct { + UINT8 Bit0 : 1; ///< Bits 0:0 + UINT8 Bit1 : 1; ///< Bits 1:1 + UINT8 Bit2 : 1; ///< Bits 2:2 + UINT8 Reserved : 5; ///< Bits 7:3 + } Bits; + UINT8 Data; +} SPD3_RDIMM_REGISTER_TYPE; + +typedef union { + struct { + UINT8 Reserved : 4; ///< Bits 0:3 + UINT8 CommandAddressAOutputs : 2; ///< Bits 5:4 + UINT8 CommandAddressBOutputs : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_RDIMM_REGISTER_CONTROL_COMMAND_ADDRESS; + +typedef union { + struct { + UINT8 ControlSignalsAOutputs : 2; ///< Bits 0:1 + UINT8 ControlSignalsBOutputs : 2; ///< Bits 3:2 + UINT8 Y1Y3ClockOutputs : 2; ///< Bits 5:4 + UINT8 Y0Y2ClockOutputs : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_RDIMM_REGISTER_CONTROL_CONTROL_CLOCK; + +typedef union { + struct { + UINT8 Reserved0 : 4; ///< Bits 0:3 + UINT8 Reserved1 : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_RDIMM_REGISTER_CONTROL_RESERVED; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_MODULE_NOMINAL_THICKNESS; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 RegisterCount : 2; ///< Bits 1:0 + UINT8 DramRowCount : 2; ///< Bits 3:2 + UINT8 RegisterType : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_MODULE_ATTRIBUTES; + +typedef union { + struct { + UINT8 AddressCommandPrelaunch : 1; ///< Bits 0:0 + UINT8 Rank1Rank5Swap : 1; ///< Bits 1:1 + UINT8 Reserved0 : 1; ///< Bits 2:2 + UINT8 Reserved1 : 1; ///< Bits 3:3 + UINT8 AddressCommandOutputs : 2; ///< Bits 5:4 + UINT8 QxCS_nOutputs : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_TIMING_CONTROL_DRIVE_STRENGTH; + +typedef union { + struct { + UINT8 QxOdtOutputs : 2; ///< Bits 1:0 + UINT8 QxCkeOutputs : 2; ///< Bits 3:2 + UINT8 Y1Y3ClockOutputs : 2; ///< Bits 5:4 + UINT8 Y0Y2ClockOutputs : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_TIMING_DRIVE_STRENGTH; + +typedef union { + struct { + UINT8 YExtendedDelay : 2; ///< Bits 1:0 + UINT8 QxCS_n : 2; ///< Bits 3:2 + UINT8 QxOdt : 2; ///< Bits 5:4 + UINT8 QxCke : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_EXTENDED_DELAY; + +typedef union { + struct { + UINT8 DelayY : 3; ///< Bits 2:0 + UINT8 Reserved : 1; ///< Bits 3:3 + UINT8 QxCS_n : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_ADDITIVE_DELAY_FOR_QXCS_N_QXCA; + +typedef union { + struct { + UINT8 QxCS_n : 4; ///< Bits 3:0 + UINT8 QxOdt : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_ADDITIVE_DELAY_FOR_QXODT_QXCKE; + +typedef union { + struct { + UINT8 RC8MdqOdtStrength : 3; ///< Bits 2:0 + UINT8 RC8Reserved : 1; ///< Bits 3:3 + UINT8 RC9MdqOdtStrength : 3; ///< Bits 6:4 + UINT8 RC9Reserved : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_MDQ_TERMINATION_DRIVE_STRENGTH; + +typedef union { + struct { + UINT8 RC10DA3ValueR0 : 1; ///< Bits 0:0 + UINT8 RC10DA4ValueR0 : 1; ///< Bits 1:1 + UINT8 RC10DA3ValueR1 : 1; ///< Bits 2:2 + UINT8 RC10DA4ValueR1 : 1; ///< Bits 3:3 + UINT8 RC11DA3ValueR0 : 1; ///< Bits 4:4 + UINT8 RC11DA4ValueR0 : 1; ///< Bits 5:5 + UINT8 RC11DA3ValueR1 : 1; ///< Bits 6:6 + UINT8 RC11DA4ValueR1 : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL; + +typedef union { + struct { + UINT8 Driver_Impedance : 2; ///< Bits 1:0 + UINT8 Rtt_Nom : 3; ///< Bits 4:2 + UINT8 Reserved : 1; ///< Bits 5:5 + UINT8 Rtt_WR : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_MR_1_2; + +typedef union { + struct { + UINT8 MinimumDelayTime : 7; ///< Bits 0:6 + UINT8 Reserved : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD3_LRDIMM_MODULE_DELAY_TIME; + +typedef struct { + UINT8 Year; ///< Year represented in BCD (00h = 2000) + UINT8 Week; ///< Year represented in BCD (47h = week 47) +} SPD3_MANUFACTURING_DATE; + +typedef union { + UINT32 Data; + UINT16 SerialNumber16[2]; + UINT8 SerialNumber8[4]; +} SPD3_MANUFACTURER_SERIAL_NUMBER; + +typedef struct { + UINT8 Location; ///< Module Manufacturing Location +} SPD3_MANUFACTURING_LOCATION; + +typedef struct { + SPD3_MANUFACTURER_ID_CODE IdCode; ///< Module Manufacturer ID Code + SPD3_MANUFACTURING_LOCATION Location; ///< Module Manufacturing Location + SPD3_MANUFACTURING_DATE Date; ///< Module Manufacturing Year, in BCD (range: 2000-2255) + SPD3_MANUFACTURER_SERIAL_NUMBER SerialNumber; ///< Module Serial Number +} SPD3_UNIQUE_MODULE_ID; + +typedef union { + UINT16 Crc[1]; + UINT8 Data8[2]; +} SPD3_CYCLIC_REDUNDANCY_CODE; + +typedef struct { + SPD3_DEVICE_DESCRIPTION_STRUCT Description; ///< 0 Number of Serial PD Bytes Written / SPD Device Size / CRC Coverage 1, 2 + SPD3_REVISION_STRUCT Revision; ///< 1 SPD Revision + SPD3_DRAM_DEVICE_TYPE_STRUCT DramDeviceType; ///< 2 DRAM Device Type + SPD3_MODULE_TYPE_STRUCT ModuleType; ///< 3 Module Type + SPD3_SDRAM_DENSITY_BANKS_STRUCT SdramDensityAndBanks; ///< 4 SDRAM Density and Banks + SPD3_SDRAM_ADDRESSING_STRUCT SdramAddressing; ///< 5 SDRAM Addressing + SPD3_MODULE_NOMINAL_VOLTAGE_STRUCT ModuleNominalVoltage; ///< 6 Module Nominal Voltage, VDD + SPD3_MODULE_ORGANIZATION_STRUCT ModuleOrganization; ///< 7 Module Organization + SPD3_MODULE_MEMORY_BUS_WIDTH_STRUCT ModuleMemoryBusWidth; ///< 8 Module Memory Bus Width + SPD3_FINE_TIMEBASE_STRUCT FineTimebase; ///< 9 Fine Timebase (FTB) Dividend / Divisor + SPD3_MEDIUM_TIMEBASE MediumTimebase; ///< 10-11 Medium Timebase (MTB) Dividend + SPD3_TCK_MIN_MTB_STRUCT tCKmin; ///< 12 SDRAM Minimum Cycle Time (tCKmin) + UINT8 Reserved0; ///< 13 Reserved + SPD3_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 14-15 CAS Latencies Supported + SPD3_TAA_MIN_MTB_STRUCT tAAmin; ///< 16 Minimum CAS Latency Time (tAAmin) + SPD3_TWR_MIN_MTB_STRUCT tWRmin; ///< 17 Minimum Write Recovery Time (tWRmin) + SPD3_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 18 Minimum RAS# to CAS# Delay Time (tRCDmin) + SPD3_TRRD_MIN_MTB_STRUCT tRRDmin; ///< 19 Minimum Row Active to Row Active Delay Time (tRRDmin) + SPD3_TRP_MIN_MTB_STRUCT tRPmin; ///< 20 Minimum Row Precharge Delay Time (tRPmin) + SPD3_TRAS_TRC_MIN_MTB_STRUCT tRASMintRCMinUpper; ///< 21 Upper Nibbles for tRAS and tRC + SPD3_TRAS_MIN_MTB_STRUCT tRASmin; ///< 22 Minimum Active to Precharge Delay Time (tRASmin), Least Significant Byte + SPD3_TRC_MIN_MTB_STRUCT tRCmin; ///< 23 Minimum Active to Active/Refresh Delay Time (tRCmin), Least Significant Byte + SPD3_TRFC_MIN_MTB_STRUCT tRFCmin; ///< 24-25 Minimum Refresh Recovery Delay Time (tRFCmin) + SPD3_TWTR_MIN_MTB_STRUCT tWTRmin; ///< 26 Minimum Internal Write to Read Command Delay Time (tWTRmin) + SPD3_TRTP_MIN_MTB_STRUCT tRTPmin; ///< 27 Minimum Internal Read to Precharge Command Delay Time (tRTPmin) + SPD3_TFAW_MIN_MTB_UPPER_STRUCT tFAWMinUpper; ///< 28 Upper Nibble for tFAW + SPD3_TFAW_MIN_MTB_STRUCT tFAWmin; ///< 29 Minimum Four Activate Window Delay Time (tFAWmin) + SPD3_SDRAM_OPTIONAL_FEATURES_STRUCT SdramOptionalFeatures; ///< 30 SDRAM Optional Features + SPD3_SDRAM_THERMAL_REFRESH_STRUCT ThermalAndRefreshOptions; ///< 31 SDRAM Thermal And Refresh Options + SPD3_MODULE_THERMAL_SENSOR_STRUCT ModuleThermalSensor; ///< 32 Module Thermal Sensor + SPD3_SDRAM_DEVICE_TYPE_STRUCT SdramDeviceType; ///< 33 SDRAM Device Type + SPD3_TCK_MIN_FTB_STRUCT tCKminFine; ///< 34 Fine Offset for SDRAM Minimum Cycle Time (tCKmin) + SPD3_TAA_MIN_FTB_STRUCT tAAminFine; ///< 35 Fine Offset for Minimum CAS Latency Time (tAAmin) + SPD3_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 36 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin) + SPD3_TRP_MIN_FTB_STRUCT tRPminFine; ///< 37 Minimum Row Precharge Delay Time (tRPmin) + SPD3_TRC_MIN_FTB_STRUCT tRCminFine; ///< 38 Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin) + UINT8 Reserved1[40 - 39 + 1]; ///< 39 - 40 Reserved + SPD3_MAXIMUM_ACTIVE_COUNT_STRUCT MacValue; ///< 41 SDRAM Maximum Active Count (MAC) Value + UINT8 Reserved2[59 - 42 + 1]; ///< 42 - 59 Reserved +} SPD3_BASE_SECTION; + +typedef struct { + SPD3_UNBUF_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 60 Module Nominal Height + SPD3_UNBUF_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 61 Module Maximum Thickness + SPD3_UNBUF_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 62 Reference Raw Card Used + SPD3_UNBUF_ADDRESS_MAPPING AddressMappingEdgeConn; ///< 63 Address Mapping from Edge Connector to DRAM + UINT8 Reserved[116 - 64 + 1]; ///< 64-116 Reserved +} SPD3_MODULE_UNBUFFERED; + +typedef struct { + SPD3_RDIMM_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 60 Module Nominal Height + SPD3_RDIMM_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 61 Module Maximum Thickness + SPD3_RDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 62 Reference Raw Card Used + SPD3_RDIMM_MODULE_ATTRIBUTES DimmModuleAttributes; ///< 63 DIMM Module Attributes + SPD3_RDIMM_THERMAL_HEAT_SPREADER_SOLUTION ThermalHeatSpreaderSolution; ///< 64 RDIMM Thermal Heat Spreader Solution + SPD3_MANUFACTURER_ID_CODE RegisterManufacturerIdCode; ///< 65-66 Register Manufacturer ID Code + SPD3_RDIMM_REGISTER_REVISION_NUMBER RegisterRevisionNumber; ///< 67 Register Revision Number + SPD3_RDIMM_REGISTER_TYPE RegisterType; ///< 68 Register Type + SPD3_RDIMM_REGISTER_CONTROL_RESERVED Rc1Rc0; ///< 69 RC1 (MS Nibble) / RC0 (LS Nibble) - Reserved + SPD3_RDIMM_REGISTER_CONTROL_COMMAND_ADDRESS Rc3Rc2; ///< 70 RC3 (MS Nibble) / RC2 (LS Nibble) - Drive Strength, Command/Address + SPD3_RDIMM_REGISTER_CONTROL_CONTROL_CLOCK Rc5Rc4; ///< 71 RC5 (MS Nibble) / RC4 (LS Nibble) - Drive Strength, Control and Clock + SPD3_RDIMM_REGISTER_CONTROL_RESERVED Rc7Rc6; ///< 72 RC7 (MS Nibble) / RC6 (LS Nibble) - Reserved for Register Vendor + SPD3_RDIMM_REGISTER_CONTROL_RESERVED Rc9Rc8; ///< 73 RC9 (MS Nibble) / RC8 (LS Nibble) - Reserved + SPD3_RDIMM_REGISTER_CONTROL_RESERVED Rc11Rc10; ///< 74 RC11 (MS Nibble) / RC10 (LS Nibble) - Reserved + SPD3_RDIMM_REGISTER_CONTROL_RESERVED Rc13Rc12; ///< 75 RC12 (MS Nibble) / RC12 (LS Nibble) - Reserved + SPD3_RDIMM_REGISTER_CONTROL_RESERVED Rc15Rc14; ///< 76 RC15 (MS Nibble) / RC14 (LS Nibble) - Reserved + UINT8 Reserved[116 - 77 + 1]; ///< 77-116 Reserved +} SPD3_MODULE_REGISTERED; + +typedef struct { + SPD3_UNBUF_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 60 Module Nominal Height + SPD3_UNBUF_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 61 Module Maximum Thickness + SPD3_UNBUF_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 62 Reference Raw Card Used + UINT8 Reserved[116 - 63 + 1]; ///< 63-116 Reserved +} SPD3_MODULE_CLOCKED; + +typedef struct { + SPD3_LRDIMM_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 60 Module Nominal Height + SPD3_LRDIMM_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 61 Module Maximum Thickness + SPD3_LRDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 62 Reference Raw Card Used + SPD3_LRDIMM_MODULE_ATTRIBUTES DimmModuleAttributes; ///< 63 Module Attributes + UINT8 MemoryBufferRevisionNumber; ///< 64 Memory Buffer Revision Number + SPD3_MANUFACTURER_ID_CODE ManufacturerIdCode; ///< 65-66 Memory Buffer Manufacturer ID Code + SPD3_LRDIMM_TIMING_CONTROL_DRIVE_STRENGTH TimingControlDriveStrengthCaCs; ///< 67 F0RC3 / F0RC2 - Timing Control & Drive Strength, CA & CS + SPD3_LRDIMM_TIMING_DRIVE_STRENGTH DriveStrength; ///< 68 F0RC5 / F0RC4 - Drive Strength, ODT & CKE and Y + SPD3_LRDIMM_EXTENDED_DELAY ExtendedDelay; ///< 69 F1RC11 / F1RC8 - Extended Delay for Y, CS and ODT & CKE + SPD3_LRDIMM_ADDITIVE_DELAY_FOR_QXCS_N_QXCA AdditiveDelayForCsCa; ///< 70 F1RC13 / F1RC12 - Additive Delay for CS and CA + SPD3_LRDIMM_ADDITIVE_DELAY_FOR_QXODT_QXCKE AdditiveDelayForOdtCke; ///< 71 F1RC15 / F1RC14 - Additive Delay for ODT & CKE + SPD3_LRDIMM_MDQ_TERMINATION_DRIVE_STRENGTH MdqTerminationDriveStrengthFor800_1066; ///< 72 F1RC15 / F1RC14 - Additive Delay for ODT & CKE + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_0_1QxOdtControlFor800_1066; ///< 73 F[3,4]RC11 / F[3,4]RC10 - Rank 0 & 1 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_2_3QxOdtControlFor800_1066; ///< 74 F[5,6]RC11 / F[5,6]RC10 - Rank 2 & 3 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_4_5QxOdtControlFor800_1066; ///< 75 F[7,8]RC11 / F[7,8]RC10 - Rank 4 & 5 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_6_7QxOdtControlFor800_1066; ///< 76 F[9,10]RC11 / F[9,10]RC10 - Rank 6 & 7 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_MR_1_2 MR_1_2RegistersFor800_1066; ///< 77 MR1,2 Registers for 800 & 1066 + SPD3_LRDIMM_MDQ_TERMINATION_DRIVE_STRENGTH MdqTerminationDriveStrengthFor1333_1600; ///< 78 F1RC15 / F1RC14 - Additive Delay for ODT & CKE + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_0_1QxOdtControlFor1333_1600; ///< 79 F[3,4]RC11 / F[3,4]RC10 - Rank 0 & 1 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_2_3QxOdtControlFor1333_1600; ///< 80 F[5,6]RC11 / F[5,6]RC10 - Rank 2 & 3 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_4_5QxOdtControlFor1333_1600; ///< 81 F[7,8]RC11 / F[7,8]RC10 - Rank 4 & 5 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_6_7QxOdtControlFor1333_1600; ///< 82 F[9,10]RC11 / F[9,10]RC10 - Rank 6 & 7 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_MR_1_2 MR_1_2RegistersFor1333_1600; ///< 83 MR1,2 Registers for 800 & 1066 + SPD3_LRDIMM_MDQ_TERMINATION_DRIVE_STRENGTH MdqTerminationDriveStrengthFor1866_2133; ///< 84 F1RC15 / F1RC14 - Additive Delay for ODT & CKE + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_0_1QxOdtControlFor1866_2133; ///< 85 F[3,4]RC11 / F[3,4]RC10 - Rank 0 & 1 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_2_3QxOdtControlFor1866_2133; ///< 86 F[5,6]RC11 / F[5,6]RC10 - Rank 2 & 3 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_4_5QxOdtControlFor1866_2133; ///< 87 F[7,8]RC11 / F[7,8]RC10 - Rank 4 & 5 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_RANK_READ_WRITE_QXODT_CONTROL Rank_6_7QxOdtControlFor1866_2133; ///< 88 F[9,10]RC11 / F[9,10]RC10 - Rank 6 & 7 RD & WR QxODT Control for 800 & 1066 + SPD3_LRDIMM_MR_1_2 MR_1_2RegistersFor1866_2133; ///< 89 MR1,2 Registers for 800 & 1066 + SPD3_LRDIMM_MODULE_DELAY_TIME MinimumModuleDelayTimeFor1_5V; ///< 90 Minimum Module Delay Time for 1.5 V + SPD3_LRDIMM_MODULE_DELAY_TIME MaximumModuleDelayTimeFor1_5V; ///< 91 Maximum Module Delay Time for 1.5 V + SPD3_LRDIMM_MODULE_DELAY_TIME MinimumModuleDelayTimeFor1_35V; ///< 92 Minimum Module Delay Time for 1.35 V + SPD3_LRDIMM_MODULE_DELAY_TIME MaximumModuleDelayTimeFor1_35V; ///< 93 Maximum Module Delay Time for 1.35 V + SPD3_LRDIMM_MODULE_DELAY_TIME MinimumModuleDelayTimeFor1_25V; ///< 94 Minimum Module Delay Time for 1.25 V + SPD3_LRDIMM_MODULE_DELAY_TIME MaximumModuleDelayTimeFor1_25V; ///< 95 Maximum Module Delay Time for 1.25 V + UINT8 Reserved[101 - 96 + 1]; ///< 96-101 Reserved + UINT8 PersonalityByte[116 - 102 + 1]; ///< 102-116 Memory Buffer Personality Bytes +} SPD3_MODULE_LOADREDUCED; + +typedef union { + SPD3_MODULE_UNBUFFERED Unbuffered; ///< 128-255 Unbuffered Memory Module Types + SPD3_MODULE_REGISTERED Registered; ///< 128-255 Registered Memory Module Types + SPD3_MODULE_CLOCKED Clocked; ///< 128-255 Registered Memory Module Types + SPD3_MODULE_LOADREDUCED LoadReduced; ///< 128-255 Load Reduced Memory Module Types +} SPD3_MODULE_SPECIFIC; + +typedef struct { + UINT8 ModulePartNumber[145 - 128 + 1]; ///< 128-145 Module Part Number +} SPD3_MODULE_PART_NUMBER; + +typedef struct { + UINT8 ModuleRevisionCode[147 - 146 + 1]; ///< 146-147 Module Revision Code +} SPD3_MODULE_REVISION_CODE; + +typedef struct { + UINT8 ManufacturerSpecificData[175 - 150 + 1];///< 150-175 Manufacturer's Specific Data +} SPD3_MANUFACTURER_SPECIFIC; + +/// +/// DDR3 Serial Presence Detect structure +/// +typedef struct { + SPD3_BASE_SECTION General; ///< 0-59 General Section + SPD3_MODULE_SPECIFIC Module; ///< 60-116 Module-Specific Section + SPD3_UNIQUE_MODULE_ID ModuleId; ///< 117-125 Unique Module ID + SPD3_CYCLIC_REDUNDANCY_CODE Crc; ///< 126-127 Cyclical Redundancy Code (CRC) + SPD3_MODULE_PART_NUMBER ModulePartNumber; ///< 128-145 Module Part Number + SPD3_MODULE_REVISION_CODE ModuleRevisionCode; ///< 146-147 Module Revision Code + SPD3_MANUFACTURER_ID_CODE DramIdCode; ///< 148-149 Dram Manufacturer ID Code + SPD3_MANUFACTURER_SPECIFIC ManufacturerSpecificData; ///< 150-175 Manufacturer's Specific Data + UINT8 Reserved[255 - 176 + 1]; ///< 176-255 Open for Customer Use +} SPD_DDR3; + +#pragma pack (pop) +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr4.h new file mode 100644 index 0000000..d6bc76f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdDdr4.h @@ -0,0 +1,958 @@ +/** @file + This file contains definitions for SPD DDR4. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - Serial Presence Detect (SPD) for DDR4 SDRAM Modules Document Release 4 + http://www.jedec.org/standards-documents/docs/spd412l-4 +**/ + +#ifndef _SDRAM_SPD_DDR4_H_ +#define _SDRAM_SPD_DDR4_H_ + +#pragma pack (push, 1) + +typedef union { + struct { + UINT8 BytesUsed : 4; ///< Bits 3:0 + UINT8 BytesTotal : 3; ///< Bits 6:4 + UINT8 CrcCoverage : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_DEVICE_DESCRIPTION_STRUCT; + +typedef union { + struct { + UINT8 Minor : 4; ///< Bits 3:0 + UINT8 Major : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_REVISION_STRUCT; + +typedef union { + struct { + UINT8 Type : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_DRAM_DEVICE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 ModuleType : 4; ///< Bits 3:0 + UINT8 HybridMedia : 3; ///< Bits 6:4 + UINT8 Hybrid : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_MODULE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 Density : 4; ///< Bits 3:0 + UINT8 BankAddress : 2; ///< Bits 5:4 + UINT8 BankGroup : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_SDRAM_DENSITY_BANKS_STRUCT; + +typedef union { + struct { + UINT8 ColumnAddress : 3; ///< Bits 2:0 + UINT8 RowAddress : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_SDRAM_ADDRESSING_STRUCT; + +typedef union { + struct { + UINT8 SignalLoading : 2; ///< Bits 1:0 + UINT8 Reserved : 2; ///< Bits 3:2 + UINT8 DieCount : 3; ///< Bits 6:4 + UINT8 SdramPackageType : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_PRIMARY_SDRAM_PACKAGE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 MaximumActivateCount : 4; ///< Bits 3:0 + UINT8 MaximumActivateWindow : 2; ///< Bits 5:4 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_SDRAM_OPTIONAL_FEATURES_STRUCT; + +typedef union { + struct { + UINT8 Reserved : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_SDRAM_THERMAL_REFRESH_STRUCT; + +typedef union { + struct { + UINT8 Reserved : 5; ///< Bits 4:0 + UINT8 SoftPPR : 1; ///< Bits 5:5 + UINT8 PostPackageRepair : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_OTHER_SDRAM_OPTIONAL_FEATURES_STRUCT; + +typedef union { + struct { + UINT8 SignalLoading : 2; ///< Bits 1:0 + UINT8 DRAMDensityRatio : 2; ///< Bits 3:2 + UINT8 DieCount : 3; ///< Bits 6:4 + UINT8 SdramPackageType : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_SECONDARY_SDRAM_PACKAGE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 OperationAt1_20 : 1; ///< Bits 0:0 + UINT8 EndurantAt1_20 : 1; ///< Bits 1:1 + UINT8 Reserved : 6; ///< Bits 7:2 + } Bits; + UINT8 Data; +} SPD4_MODULE_NOMINAL_VOLTAGE_STRUCT; + +typedef union { + struct { + UINT8 SdramDeviceWidth : 3; ///< Bits 2:0 + UINT8 RankCount : 3; ///< Bits 5:3 + UINT8 RankMix : 1; ///< Bits 6:6 + UINT8 Reserved : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_MODULE_ORGANIZATION_STRUCT; + +typedef union { + struct { + UINT8 PrimaryBusWidth : 3; ///< Bits 2:0 + UINT8 BusWidthExtension : 2; ///< Bits 4:3 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD4_MODULE_MEMORY_BUS_WIDTH_STRUCT; + +typedef union { + struct { + UINT8 Reserved : 7; ///< Bits 6:0 + UINT8 ThermalSensorPresence : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_MODULE_THERMAL_SENSOR_STRUCT; + +typedef union { + struct { + UINT8 ExtendedBaseModuleType : 4; ///< Bits 3:0 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_EXTENDED_MODULE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 Fine : 2; ///< Bits 1:0 + UINT8 Medium : 2; ///< Bits 3:2 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_TIMEBASE_STRUCT; + +typedef union { + struct { + UINT8 tCKmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TCK_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tCKmax : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TCK_MAX_MTB_STRUCT; + +typedef union { + struct { + UINT32 Cl7 : 1; ///< Bits 0:0 + UINT32 Cl8 : 1; ///< Bits 1:1 + UINT32 Cl9 : 1; ///< Bits 2:2 + UINT32 Cl10 : 1; ///< Bits 3:3 + UINT32 Cl11 : 1; ///< Bits 4:4 + UINT32 Cl12 : 1; ///< Bits 5:5 + UINT32 Cl13 : 1; ///< Bits 6:6 + UINT32 Cl14 : 1; ///< Bits 7:7 + UINT32 Cl15 : 1; ///< Bits 8:8 + UINT32 Cl16 : 1; ///< Bits 9:9 + UINT32 Cl17 : 1; ///< Bits 10:10 + UINT32 Cl18 : 1; ///< Bits 11:11 + UINT32 Cl19 : 1; ///< Bits 12:12 + UINT32 Cl20 : 1; ///< Bits 13:13 + UINT32 Cl21 : 1; ///< Bits 14:14 + UINT32 Cl22 : 1; ///< Bits 15:15 + UINT32 Cl23 : 1; ///< Bits 16:16 + UINT32 Cl24 : 1; ///< Bits 17:17 + UINT32 Cl25 : 1; ///< Bits 18:18 + UINT32 Cl26 : 1; ///< Bits 19:19 + UINT32 Cl27 : 1; ///< Bits 20:20 + UINT32 Cl28 : 1; ///< Bits 21:21 + UINT32 Cl29 : 1; ///< Bits 22:22 + UINT32 Cl30 : 1; ///< Bits 23:23 + UINT32 Cl31 : 1; ///< Bits 24:24 + UINT32 Cl32 : 1; ///< Bits 25:25 + UINT32 Cl33 : 1; ///< Bits 26:26 + UINT32 Cl34 : 1; ///< Bits 27:27 + UINT32 Cl35 : 1; ///< Bits 28:28 + UINT32 Cl36 : 1; ///< Bits 29:29 + UINT32 Reserved : 1; ///< Bits 30:30 + UINT32 ClRange : 1; ///< Bits 31:31 + } Bits; + struct { + UINT32 Cl23 : 1; ///< Bits 0:0 + UINT32 Cl24 : 1; ///< Bits 1:1 + UINT32 Cl25 : 1; ///< Bits 2:2 + UINT32 Cl26 : 1; ///< Bits 3:3 + UINT32 Cl27 : 1; ///< Bits 4:4 + UINT32 Cl28 : 1; ///< Bits 5:5 + UINT32 Cl29 : 1; ///< Bits 6:6 + UINT32 Cl30 : 1; ///< Bits 7:7 + UINT32 Cl31 : 1; ///< Bits 8:8 + UINT32 Cl32 : 1; ///< Bits 9:9 + UINT32 Cl33 : 1; ///< Bits 10:10 + UINT32 Cl34 : 1; ///< Bits 11:11 + UINT32 Cl35 : 1; ///< Bits 12:12 + UINT32 Cl36 : 1; ///< Bits 13:13 + UINT32 Cl37 : 1; ///< Bits 14:14 + UINT32 Cl38 : 1; ///< Bits 15:15 + UINT32 Cl39 : 1; ///< Bits 16:16 + UINT32 Cl40 : 1; ///< Bits 17:17 + UINT32 Cl41 : 1; ///< Bits 18:18 + UINT32 Cl42 : 1; ///< Bits 19:19 + UINT32 Cl43 : 1; ///< Bits 20:20 + UINT32 Cl44 : 1; ///< Bits 21:21 + UINT32 Cl45 : 1; ///< Bits 22:22 + UINT32 Cl46 : 1; ///< Bits 23:23 + UINT32 Cl47 : 1; ///< Bits 24:24 + UINT32 Cl48 : 1; ///< Bits 25:25 + UINT32 Cl49 : 1; ///< Bits 26:26 + UINT32 Cl50 : 1; ///< Bits 27:27 + UINT32 Cl51 : 1; ///< Bits 28:28 + UINT32 Cl52 : 1; ///< Bits 29:29 + UINT32 Reserved : 1; ///< Bits 30:30 + UINT32 ClRange : 1; ///< Bits 31:31 + } HighRangeBits; + UINT32 Data; + UINT16 Data16[2]; + UINT8 Data8[4]; +} SPD4_CAS_LATENCIES_SUPPORTED_STRUCT; + +typedef union { + struct { + UINT8 tAAmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TAA_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRCDmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TRCD_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRPmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TRP_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRASminUpper : 4; ///< Bits 3:0 + UINT8 tRCminUpper : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_TRAS_TRC_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRASmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TRAS_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRCmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TRC_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT16 tRFCmin : 16; ///< Bits 15:0 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD4_TRFC_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tFAWminUpper : 4; ///< Bits 3:0 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_TFAW_MIN_MTB_UPPER_STRUCT; + +typedef union { + struct { + UINT8 tFAWmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TFAW_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRRDmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TRRD_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tCCDmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TCCD_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tWRminMostSignificantNibble : 4; ///< Bits 3:0 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_TWR_UPPER_NIBBLE_STRUCT; + +typedef union { + struct { + UINT8 tWRmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TWR_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tWTR_SminMostSignificantNibble : 4; ///< Bits 3:0 + UINT8 tWTR_LminMostSignificantNibble : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_TWTR_UPPER_NIBBLE_STRUCT; + +typedef union { + struct { + UINT8 tWTRmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_TWTR_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 BitOrderatSDRAM : 5; ///< Bits 4:0 + UINT8 WiredtoUpperLowerNibble : 1; ///< Bits 5:5 + UINT8 PackageRankMap : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_CONNECTOR_BIT_MAPPING_BYTE_STRUCT; + +typedef union { + struct { + INT8 tCCDminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TCCD_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRRDminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TRRD_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRCminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TRC_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRPminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TRP_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tRCDminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TRCD_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tAAminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TAA_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tCKmaxFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TCK_MAX_FTB_STRUCT; + +typedef union { + struct { + INT8 tCKminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD4_TCK_MIN_FTB_STRUCT; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 RawCardExtension : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD4_UNBUF_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_UNBUF_MODULE_NOMINAL_THICKNESS; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_UNBUF_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 MappingRank1 : 1; ///< Bits 0:0 + UINT8 Reserved : 7; ///< Bits 7:1 + } Bits; + UINT8 Data; +} SPD4_UNBUF_ADDRESS_MAPPING; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD4_RDIMM_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_RDIMM_MODULE_NOMINAL_THICKNESS; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_RDIMM_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 RegisterCount : 2; ///< Bits 1:0 + UINT8 DramRowCount : 2; ///< Bits 3:2 + UINT8 RegisterType : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_RDIMM_MODULE_ATTRIBUTES; + +typedef union { + struct { + UINT8 HeatSpreaderThermalCharacteristics : 7; ///< Bits 6:0 + UINT8 HeatSpreaderSolution : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_RDIMM_THERMAL_HEAT_SPREADER_SOLUTION; + +typedef union { + struct { + UINT16 ContinuationCount : 7; ///< Bits 6:0 + UINT16 ContinuationParity : 1; ///< Bits 7:7 + UINT16 LastNonZeroByte : 8; ///< Bits 15:8 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD4_MANUFACTURER_ID_CODE; + +typedef union { + struct { + UINT8 RegisterRevisionNumber; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_RDIMM_REGISTER_REVISION_NUMBER; + +typedef union { + struct { + UINT8 Rank1Mapping : 1; ///< Bits 0:0 + UINT8 Reserved : 7; ///< Bits 7:1 + } Bits; + UINT8 Data; +} SPD4_RDIMM_ADDRESS_MAPPING_FROM_REGISTER_TO_DRAM; + +typedef union { + struct { + UINT8 Cke : 2; ///< Bits 1:0 + UINT8 Odt : 2; ///< Bits 3:2 + UINT8 CommandAddress : 2; ///< Bits 5:4 + UINT8 ChipSelect : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_RDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CONTROL_COMMAND_ADDRESS; + +typedef union { + struct { + UINT8 Y0Y2 : 2; ///< Bits 1:0 + UINT8 Y1Y3 : 2; ///< Bits 3:2 + UINT8 Reserved0 : 2; ///< Bits 5:4 + UINT8 RcdOutputSlewRateControl : 1; ///< Bits 6:6 + UINT8 Reserved1 : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_RDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CLOCK; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_MODULE_NOMINAL_THICKNESS; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 RegisterCount : 2; ///< Bits 1:0 + UINT8 DramRowCount : 2; ///< Bits 3:2 + UINT8 RegisterType : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_MODULE_ATTRIBUTES; + +typedef union { + struct { + UINT8 HeatSpreaderThermalCharacteristics : 7; ///< Bits 6:0 + UINT8 HeatSpreaderSolution : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_THERMAL_HEAT_SPREADER_SOLUTION; + +typedef union { + struct { + UINT8 RegisterRevisionNumber; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_REGISTER_REVISION_NUMBER; + +typedef union { + struct { + UINT8 Rank1Mapping : 1; ///< Bits 0:0 + UINT8 Reserved : 7; ///< Bits 7:1 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_ADDRESS_MAPPING_FROM_REGISTER_TO_DRAM; + +typedef union { + struct { + UINT8 Cke : 2; ///< Bits 1:0 + UINT8 Odt : 2; ///< Bits 3:2 + UINT8 CommandAddress : 2; ///< Bits 5:4 + UINT8 ChipSelect : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CONTROL_COMMAND_ADDRESS; + +typedef union { + struct { + UINT8 Y0Y2 : 2; ///< Bits 1:0 + UINT8 Y1Y3 : 2; ///< Bits 3:2 + UINT8 Reserved0 : 2; ///< Bits 5:4 + UINT8 RcdOutputSlewRateControl : 1; ///< Bits 6:6 + UINT8 Reserved1 : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CLOCK; + +typedef struct { + UINT8 DataBufferRevisionNumber; +} SPD4_LRDIMM_DATA_BUFFER_REVISION_NUMBER; + +typedef union { + struct { + UINT8 DramVrefDQForPackageRank0 : 6; ///< Bits 5:0 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DRAM_VREFDQ_FOR_PACKAGE_RANK; + +typedef struct { + UINT8 DataBufferVrefDQforDramInterface; +} SPD4_LRDIMM_DATA_BUFFER_VREFDQ_FOR_DRAM_INTERFACE; + +typedef union { + struct { + UINT8 DramInterfaceMdqDriveStrength : 4; ///< Bits 3:0 + UINT8 DramInterfaceMdqReadTerminationStrength : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DATA_BUFFER_MDQ_DRIVE_STRENGTH_RTT_FOR_DATA_RATE; + +typedef union { + struct { + UINT8 DataRateLe1866 : 2; ///< Bits 1:0 + UINT8 DataRateLe2400 : 2; ///< Bits 3:2 + UINT8 DataRateLe3200 : 2; ///< Bits 5:4 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DRAM_DRIVE_STRENGTH; + +typedef union { + struct { + UINT8 Rtt_Nom : 3; ///< Bits 2:0 + UINT8 Rtt_WR : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DRAM_ODT_RTT_WR_RTT_NOM_FOR_DATA_RATE; + +typedef union { + struct { + UINT8 PackageRanks0_1 : 3; ///< Bits 2:0 + UINT8 PackageRanks2_3 : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DRAM_ODT_RTT_PARK_FOR_DATA_RATE; + +typedef union { + struct { + UINT8 Rank0 : 1; ///< Bits 0:0 + UINT8 Rank1 : 1; ///< Bits 1:1 + UINT8 Rank2 : 1; ///< Bits 2:2 + UINT8 Rank3 : 1; ///< Bits 3:3 + UINT8 DataBuffer : 1; ///< Bits 4:4 + UINT8 Reserved : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DATA_BUFFER_VREFDQ_FOR_DRAM_INTERFACE_RANGE; + +typedef union { + struct { + UINT8 DataBufferGainAdjustment : 1; ///< Bits 0:0 + UINT8 DataBufferDfe : 1; ///< Bits 1:1 + UINT8 Reserved : 6; ///< Bits 7:2 + } Bits; + UINT8 Data; +} SPD4_LRDIMM_DATA_BUFFER_DQ_DECISION_FEEDBACK_EQUALIZATION; + +typedef UINT16 SPD4_NVDIMM_MODULE_PRODUCT_IDENTIFIER; + +typedef union { + struct { + UINT16 ContinuationCount : 7; ///< Bits 6:0 + UINT16 ContinuationParity : 1; ///< Bits 7:7 + UINT16 LastNonZeroByte : 8; ///< Bits 15:8 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD4_NVDIMM_SUBSYSTEM_CONTROLLER_MANUFACTURER_ID_CODE; + +typedef UINT16 SPD4_NVDIMM_SUBSYSTEM_CONTROLLER_IDENTIFIER; + +typedef UINT8 SPD4_NVDIMM_SUBSYSTEM_CONTROLLER_REVISION_CODE; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD4_NVDIMM_REFERENCE_RAW_CARD; + +typedef union { + struct { + UINT8 Reserved : 4; ///< Bits 3:0 + UINT8 Extension : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD4_NVDIMM_MODULE_CHARACTERISTICS; + +typedef struct { + UINT8 Reserved; + UINT8 MediaType; +} SPD4_NVDIMM_HYBRID_MODULE_MEDIA_TYPES; + +typedef UINT8 SPD4_NVDIMM_MAXIMUM_NONVOLATILE_MEMORY_INITIALIZATION_TIME; + +typedef union { + struct { + UINT16 FunctionInterface : 5; ///< Bits 4:0 + UINT16 FunctionClass : 5; ///< Bits 9:5 + UINT16 BlockOffset : 4; ///< Bits 13:10 + UINT16 Reserved : 1; ///< Bits 14:14 + UINT16 Implemented : 1; ///< Bits 15:15 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD4_NVDIMM_FUNCTION_INTERFACE_DESCRIPTOR; + +typedef struct { + UINT8 Year; ///< Year represented in BCD (00h = 2000) + UINT8 Week; ///< Year represented in BCD (47h = week 47) +} SPD4_MANUFACTURING_DATE; + +typedef union { + UINT32 Data; + UINT16 SerialNumber16[2]; + UINT8 SerialNumber8[4]; +} SPD4_MANUFACTURER_SERIAL_NUMBER; + +typedef struct { + UINT8 Location; ///< Module Manufacturing Location +} SPD4_MANUFACTURING_LOCATION; + +typedef struct { + SPD4_MANUFACTURER_ID_CODE IdCode; ///< Module Manufacturer ID Code + SPD4_MANUFACTURING_LOCATION Location; ///< Module Manufacturing Location + SPD4_MANUFACTURING_DATE Date; ///< Module Manufacturing Year, in BCD (range: 2000-2255) + SPD4_MANUFACTURER_SERIAL_NUMBER SerialNumber; ///< Module Serial Number +} SPD4_UNIQUE_MODULE_ID; + +typedef union { + UINT16 Crc[1]; + UINT8 Data8[2]; +} SPD4_CYCLIC_REDUNDANCY_CODE; + +typedef struct { + SPD4_DEVICE_DESCRIPTION_STRUCT Description; ///< 0 Number of Serial PD Bytes Written / SPD Device Size / CRC Coverage 1, 2 + SPD4_REVISION_STRUCT Revision; ///< 1 SPD Revision + SPD4_DRAM_DEVICE_TYPE_STRUCT DramDeviceType; ///< 2 DRAM Device Type + SPD4_MODULE_TYPE_STRUCT ModuleType; ///< 3 Module Type + SPD4_SDRAM_DENSITY_BANKS_STRUCT SdramDensityAndBanks; ///< 4 SDRAM Density and Banks + SPD4_SDRAM_ADDRESSING_STRUCT SdramAddressing; ///< 5 SDRAM Addressing + SPD4_PRIMARY_SDRAM_PACKAGE_TYPE_STRUCT PrimarySdramPackageType; ///< 6 Primary SDRAM Package Type + SPD4_SDRAM_OPTIONAL_FEATURES_STRUCT SdramOptionalFeatures; ///< 7 SDRAM Optional Features + SPD4_SDRAM_THERMAL_REFRESH_STRUCT ThermalAndRefreshOptions; ///< 8 SDRAM Thermal and Refresh Options + SPD4_OTHER_SDRAM_OPTIONAL_FEATURES_STRUCT OtherOptionalFeatures; ///< 9 Other SDRAM Optional Features + SPD4_SECONDARY_SDRAM_PACKAGE_TYPE_STRUCT SecondarySdramPackageType;///< 10 Secondary SDRAM Package Type + SPD4_MODULE_NOMINAL_VOLTAGE_STRUCT ModuleNominalVoltage; ///< 11 Module Nominal Voltage, VDD + SPD4_MODULE_ORGANIZATION_STRUCT ModuleOrganization; ///< 12 Module Organization + SPD4_MODULE_MEMORY_BUS_WIDTH_STRUCT ModuleMemoryBusWidth; ///< 13 Module Memory Bus Width + SPD4_MODULE_THERMAL_SENSOR_STRUCT ModuleThermalSensor; ///< 14 Module Thermal Sensor + SPD4_EXTENDED_MODULE_TYPE_STRUCT ExtendedModuleType; ///< 15 Extended Module Type + UINT8 Reserved0; ///< 16 Reserved + SPD4_TIMEBASE_STRUCT Timebase; ///< 17 Timebases + SPD4_TCK_MIN_MTB_STRUCT tCKmin; ///< 18 SDRAM Minimum Cycle Time (tCKmin) + SPD4_TCK_MAX_MTB_STRUCT tCKmax; ///< 19 SDRAM Maximum Cycle Time (tCKmax) + SPD4_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 20-23 CAS Latencies Supported + SPD4_TAA_MIN_MTB_STRUCT tAAmin; ///< 24 Minimum CAS Latency Time (tAAmin) + SPD4_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 25 Minimum RAS# to CAS# Delay Time (tRCDmin) + SPD4_TRP_MIN_MTB_STRUCT tRPmin; ///< 26 Minimum Row Precharge Delay Time (tRPmin) + SPD4_TRAS_TRC_MIN_MTB_STRUCT tRASMintRCMinUpper; ///< 27 Upper Nibbles for tRAS and tRC + SPD4_TRAS_MIN_MTB_STRUCT tRASmin; ///< 28 Minimum Active to Precharge Delay Time (tRASmin), Least Significant Byte + SPD4_TRC_MIN_MTB_STRUCT tRCmin; ///< 29 Minimum Active to Active/Refresh Delay Time (tRCmin), Least Significant Byte + SPD4_TRFC_MIN_MTB_STRUCT tRFC1min; ///< 30-31 Minimum Refresh Recovery Delay Time (tRFC1min) + SPD4_TRFC_MIN_MTB_STRUCT tRFC2min; ///< 32-33 Minimum Refresh Recovery Delay Time (tRFC2min) + SPD4_TRFC_MIN_MTB_STRUCT tRFC4min; ///< 34-35 Minimum Refresh Recovery Delay Time (tRFC4min) + SPD4_TFAW_MIN_MTB_UPPER_STRUCT tFAWMinUpper; ///< 36 Upper Nibble for tFAW + SPD4_TFAW_MIN_MTB_STRUCT tFAWmin; ///< 37 Minimum Four Activate Window Delay Time (tFAWmin) + SPD4_TRRD_MIN_MTB_STRUCT tRRD_Smin; ///< 38 Minimum Activate to Activate Delay Time (tRRD_Smin), different bank group + SPD4_TRRD_MIN_MTB_STRUCT tRRD_Lmin; ///< 39 Minimum Activate to Activate Delay Time (tRRD_Lmin), same bank group + SPD4_TCCD_MIN_MTB_STRUCT tCCD_Lmin; ///< 40 Minimum CAS to CAS Delay Time (tCCD_Lmin), Same Bank Group + SPD4_TWR_UPPER_NIBBLE_STRUCT tWRUpperNibble; ///< 41 Upper Nibble for tWRmin + SPD4_TWR_MIN_MTB_STRUCT tWRmin; ///< 42 Minimum Write Recovery Time (tWRmin) + SPD4_TWTR_UPPER_NIBBLE_STRUCT tWTRUpperNibble; ///< 43 Upper Nibbles for tWTRmin + SPD4_TWTR_MIN_MTB_STRUCT tWTR_Smin; ///< 44 Minimum Write to Read Time (tWTR_Smin), Different Bank Group + SPD4_TWTR_MIN_MTB_STRUCT tWTR_Lmin; ///< 45 Minimum Write to Read Time (tWTR_Lmin), Same Bank Group + UINT8 Reserved1[59 - 46 + 1]; ///< 46-59 Reserved + SPD4_CONNECTOR_BIT_MAPPING_BYTE_STRUCT BitMapping[77 - 60 + 1]; ///< 60-77 Connector to SDRAM Bit Mapping + UINT8 Reserved2[116 - 78 + 1]; ///< 78-116 Reserved + SPD4_TCCD_MIN_FTB_STRUCT tCCD_LminFine; ///< 117 Fine Offset for Minimum CAS to CAS Delay Time (tCCD_Lmin), same bank group + SPD4_TRRD_MIN_FTB_STRUCT tRRD_LminFine; ///< 118 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Lmin), different bank group + SPD4_TRRD_MIN_FTB_STRUCT tRRD_SminFine; ///< 119 Fine Offset for Minimum Activate to Activate Delay Time (tRRD_Smin), same bank group + SPD4_TRC_MIN_FTB_STRUCT tRCminFine; ///< 120 Fine Offset for Minimum Active to Active/Refresh Delay Time (tRCmin) + SPD4_TRP_MIN_FTB_STRUCT tRPminFine; ///< 121 Fine Offset for Minimum Row Precharge Delay Time (tRPabmin) + SPD4_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 122 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin) + SPD4_TAA_MIN_FTB_STRUCT tAAminFine; ///< 123 Fine Offset for Minimum CAS Latency Time (tAAmin) + SPD4_TCK_MAX_FTB_STRUCT tCKmaxFine; ///< 124 Fine Offset for SDRAM Minimum Cycle Time (tCKmax) + SPD4_TCK_MIN_FTB_STRUCT tCKminFine; ///< 125 Fine Offset for SDRAM Maximum Cycle Time (tCKmin) + SPD4_CYCLIC_REDUNDANCY_CODE Crc; ///< 126-127 Cyclical Redundancy Code (CRC) +} SPD4_BASE_SECTION; + +typedef struct { + SPD4_UNBUF_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height + SPD4_UNBUF_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness + SPD4_UNBUF_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used + SPD4_UNBUF_ADDRESS_MAPPING AddressMappingEdgeConn; ///< 131 Address Mapping from Edge Connector to DRAM + UINT8 Reserved[253 - 132 + 1]; ///< 132-253 Reserved + SPD4_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC) +} SPD4_MODULE_UNBUFFERED; + +typedef struct { + SPD4_RDIMM_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height + SPD4_RDIMM_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness + SPD4_RDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used + SPD4_RDIMM_MODULE_ATTRIBUTES DimmModuleAttributes; ///< 131 DIMM Module Attributes + SPD4_RDIMM_THERMAL_HEAT_SPREADER_SOLUTION DimmThermalHeatSpreaderSolution; ///< 132 RDIMM Thermal Heat Spreader Solution + SPD4_MANUFACTURER_ID_CODE RegisterManufacturerIdCode; ///< 133-134 Register Manufacturer ID Code + SPD4_RDIMM_REGISTER_REVISION_NUMBER RegisterRevisionNumber; ///< 135 Register Revision Number + SPD4_RDIMM_ADDRESS_MAPPING_FROM_REGISTER_TO_DRAM AddressMappingFromRegisterToDRAM; ///< 136 Address Mapping from Register to DRAM + SPD4_RDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CONTROL_COMMAND_ADDRESS RegisterOutputDriveStrengthForControlCommandAddress; ///< 137 Register Output Drive Strength for Control and Command Address + SPD4_RDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CLOCK RegisterOutputDriveStrengthForClock; ///< 138 Register Output Drive Strength for Clock + UINT8 Reserved[253 - 139 + 1]; ///< 253-139 Reserved + SPD4_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC) +} SPD4_MODULE_REGISTERED; + +typedef struct { + SPD4_LRDIMM_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height + SPD4_LRDIMM_MODULE_NOMINAL_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness + SPD4_LRDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used + SPD4_LRDIMM_MODULE_ATTRIBUTES DimmModuleAttributes; ///< 131 DIMM Module Attributes + SPD4_LRDIMM_THERMAL_HEAT_SPREADER_SOLUTION ThermalHeatSpreaderSolution; ///< 132 RDIMM Thermal Heat Spreader Solution + SPD4_MANUFACTURER_ID_CODE RegisterManufacturerIdCode; ///< 133-134 Register Manufacturer ID Code + SPD4_LRDIMM_REGISTER_REVISION_NUMBER RegisterRevisionNumber; ///< 135 Register Revision Number + SPD4_LRDIMM_ADDRESS_MAPPING_FROM_REGISTER_TO_DRAM AddressMappingFromRegisterToDram; ///< 136 Address Mapping from Register to DRAM + SPD4_LRDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CONTROL_COMMAND_ADDRESS RegisterOutputDriveStrengthForControlCommandAddress; ///< 137 Register Output Drive Strength for Control and Command Address + SPD4_LRDIMM_REGISTER_OUTPUT_DRIVE_STRENGTH_FOR_CLOCK RegisterOutputDriveStrengthForClock; ///< 138 Register Output Drive Strength for Clock + SPD4_LRDIMM_DATA_BUFFER_REVISION_NUMBER DataBufferRevisionNumber; ///< 139 Data Buffer Revision Number + SPD4_LRDIMM_DRAM_VREFDQ_FOR_PACKAGE_RANK DramVrefDQForPackageRank0; ///< 140 DRAM VrefDQ for Package Rank 0 + SPD4_LRDIMM_DRAM_VREFDQ_FOR_PACKAGE_RANK DramVrefDQForPackageRank1; ///< 141 DRAM VrefDQ for Package Rank 1 + SPD4_LRDIMM_DRAM_VREFDQ_FOR_PACKAGE_RANK DramVrefDQForPackageRank2; ///< 142 DRAM VrefDQ for Package Rank 2 + SPD4_LRDIMM_DRAM_VREFDQ_FOR_PACKAGE_RANK DramVrefDQForPackageRank3; ///< 143 DRAM VrefDQ for Package Rank 3 + SPD4_LRDIMM_DATA_BUFFER_VREFDQ_FOR_DRAM_INTERFACE DataBufferVrefDQForDramInterface; ///< 144 Data Buffer VrefDQ for DRAM Interface + SPD4_LRDIMM_DATA_BUFFER_MDQ_DRIVE_STRENGTH_RTT_FOR_DATA_RATE DataBufferMdqDriveStrengthRttForDataRateLe1866; ///< 145 Data Buffer MDQ Drive Strength and RTT for data rate <= 1866 + SPD4_LRDIMM_DATA_BUFFER_MDQ_DRIVE_STRENGTH_RTT_FOR_DATA_RATE DataBufferMdqDriveStrengthRttForDataRateLe2400; ///< 146 Data Buffer MDQ Drive Strength and RTT for data rate <=2400 + SPD4_LRDIMM_DATA_BUFFER_MDQ_DRIVE_STRENGTH_RTT_FOR_DATA_RATE DataBufferMdqDriveStrengthRttForDataRateLe3200; ///< 147 Data Buffer MDQ Drive Strength and RTT for data rate <=3200 + SPD4_LRDIMM_DRAM_DRIVE_STRENGTH DramDriveStrength; ///< 148 DRAM Drive Strength + SPD4_LRDIMM_DRAM_ODT_RTT_WR_RTT_NOM_FOR_DATA_RATE DramOdtRttWrRttNomForDataRateLe1866; ///< 149 DRAM ODT (RTT_WR and RTT_NOM) for data rate <= 1866 + SPD4_LRDIMM_DRAM_ODT_RTT_WR_RTT_NOM_FOR_DATA_RATE DramOdtRttWrRttNomForDataRateLe2400; ///< 150 DRAM ODT (RTT_WR and RTT_NOM) for data rate <= 2400 + SPD4_LRDIMM_DRAM_ODT_RTT_WR_RTT_NOM_FOR_DATA_RATE DramOdtRttWrRttNomForDataRateLe3200; ///< 151 DRAM ODT (RTT_WR and RTT_NOM) for data rate <= 3200 + SPD4_LRDIMM_DRAM_ODT_RTT_PARK_FOR_DATA_RATE DramOdtRttParkForDataRateLe1866; ///< 152 DRAM ODT (RTT_PARK) for data rate <= 1866 + SPD4_LRDIMM_DRAM_ODT_RTT_PARK_FOR_DATA_RATE DramOdtRttParkForDataRateLe2400; ///< 153 DRAM ODT (RTT_PARK) for data rate <= 2400 + SPD4_LRDIMM_DRAM_ODT_RTT_PARK_FOR_DATA_RATE DramOdtRttParkForDataRateLe3200; ///< 154 DRAM ODT (RTT_PARK) for data rate <= 3200 + SPD4_LRDIMM_DATA_BUFFER_VREFDQ_FOR_DRAM_INTERFACE_RANGE DataBufferVrefDQForDramInterfaceRange; ///< 155 Data Buffer VrefDQ for DRAM Interface Range + SPD4_LRDIMM_DATA_BUFFER_DQ_DECISION_FEEDBACK_EQUALIZATION DataBufferDqDecisionFeedbackEqualization; ///< 156 Data Buffer DQ Decision Feedback Equalization + UINT8 Reserved[253 - 157 + 1]; ///< 253-132 Reserved + SPD4_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC) +} SPD4_MODULE_LOADREDUCED; + +typedef struct { + UINT8 Reserved0[191 - 128 + 1]; ///< 128-191 Reserved + SPD4_NVDIMM_MODULE_PRODUCT_IDENTIFIER ModuleProductIdentifier; ///< 192-193 Module Product Identifier + SPD4_NVDIMM_SUBSYSTEM_CONTROLLER_MANUFACTURER_ID_CODE SubsystemControllerManufacturerIdCode; ///< 194-195 Subsystem Controller Manufacturer's ID Code + SPD4_NVDIMM_SUBSYSTEM_CONTROLLER_IDENTIFIER SubsystemControllerIdentifier; ///< 196-197 Subsystem Controller Identifier + SPD4_NVDIMM_SUBSYSTEM_CONTROLLER_REVISION_CODE SubsystemControllerRevisionCode; ///< 198 Subsystem Controller Revision Code + SPD4_NVDIMM_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 199 Reference Raw Card Used + SPD4_NVDIMM_MODULE_CHARACTERISTICS ModuleCharacteristics; ///< 200 Module Characteristics + SPD4_NVDIMM_HYBRID_MODULE_MEDIA_TYPES HybridModuleMediaTypes; ///< 201-202 Hybrid Module Media Types + SPD4_NVDIMM_MAXIMUM_NONVOLATILE_MEMORY_INITIALIZATION_TIME MaximumNonVolatileMemoryInitializationTime; ///< 203 Maximum Non-Volatile Memory Initialization Time + SPD4_NVDIMM_FUNCTION_INTERFACE_DESCRIPTOR FunctionInterfaceDescriptors[8]; ///< 204-219 Function Interface Descriptors + UINT8 Reserved[253 - 220 + 1]; ///< 220-253 Reserved + SPD4_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC) +} SPD4_MODULE_NVDIMM; + +typedef union { + SPD4_MODULE_UNBUFFERED Unbuffered; ///< 128-255 Unbuffered Memory Module Types + SPD4_MODULE_REGISTERED Registered; ///< 128-255 Registered Memory Module Types + SPD4_MODULE_LOADREDUCED LoadReduced; ///< 128-255 Load Reduced Memory Module Types + SPD4_MODULE_NVDIMM NonVolatile; ///< 128-255 Non-Volatile (NVDIMM-N) Hybrid Memory Parameters +} SPD4_MODULE_SPECIFIC; + +typedef struct { + UINT8 ModulePartNumber[348 - 329 + 1]; ///< 329-348 Module Part Number +} SPD4_MODULE_PART_NUMBER; + +typedef struct { + UINT8 ManufacturerSpecificData[381 - 353 + 1]; ///< 353-381 Manufacturer's Specific Data +} SPD4_MANUFACTURER_SPECIFIC; + +typedef UINT8 SPD4_MODULE_REVISION_CODE;///< 349 Module Revision Code +typedef UINT8 SPD4_DRAM_STEPPING; ///< 352 Dram Stepping + +typedef struct { + SPD4_UNIQUE_MODULE_ID ModuleId; ///< 320-328 Unique Module ID + SPD4_MODULE_PART_NUMBER ModulePartNumber; ///< 329-348 Module Part Number + SPD4_MODULE_REVISION_CODE ModuleRevisionCode; ///< 349 Module Revision Code + SPD4_MANUFACTURER_ID_CODE DramIdCode; ///< 350-351 Dram Manufacturer ID Code + SPD4_DRAM_STEPPING DramStepping; ///< 352 Dram Stepping + SPD4_MANUFACTURER_SPECIFIC ManufacturerSpecificData; ///< 353-381 Manufacturer's Specific Data + UINT8 Reserved[2]; ///< 382-383 Reserved +} SPD4_MANUFACTURING_DATA; + +typedef struct { + UINT8 Reserved[511 - 384 + 1]; ///< 384-511 Unbuffered Memory Module Types +} SPD4_END_USER_SECTION; + +/// +/// DDR4 Serial Presence Detect structure +/// +typedef struct { + SPD4_BASE_SECTION Base; ///< 0-127 Base Configuration and DRAM Parameters + SPD4_MODULE_SPECIFIC Module; ///< 128-255 Module-Specific Section + UINT8 Reserved[319 - 256 + 1]; ///< 256-319 Reserved + SPD4_MANUFACTURING_DATA ManufactureInfo; ///< 320-383 Manufacturing Information + SPD4_END_USER_SECTION EndUser; ///< 384-511 End User Programmable +} SPD_DDR4; + +#pragma pack (pop) +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdLpDdr.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdLpDdr.h new file mode 100644 index 0000000..1f2302b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SdramSpdLpDdr.h @@ -0,0 +1,474 @@ +/** @file + This file contains definitions for SPD LPDDR. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - Serial Presence Detect (SPD) for LPDDR3 and LPDDR4 SDRAM Modules Document Release 2 + http://www.jedec.org/standards-documents/docs/spd412m-2 +**/ + +#ifndef _SDRAM_SPD_LPDDR_H_ +#define _SDRAM_SPD_LPDDR_H_ + +#pragma pack (push, 1) + +typedef union { + struct { + UINT8 BytesUsed : 4; ///< Bits 3:0 + UINT8 BytesTotal : 3; ///< Bits 6:4 + UINT8 CrcCoverage : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD_LPDDR_DEVICE_DESCRIPTION_STRUCT; + +typedef union { + struct { + UINT8 Minor : 4; ///< Bits 3:0 + UINT8 Major : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD_LPDDR_REVISION_STRUCT; + +typedef union { + struct { + UINT8 Type : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_DRAM_DEVICE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 ModuleType : 4; ///< Bits 3:0 + UINT8 HybridMedia : 3; ///< Bits 6:4 + UINT8 Hybrid : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 Density : 4; ///< Bits 3:0 + UINT8 BankAddress : 2; ///< Bits 5:4 + UINT8 BankGroup : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_SDRAM_DENSITY_BANKS_STRUCT; + +typedef union { + struct { + UINT8 ColumnAddress : 3; ///< Bits 2:0 + UINT8 RowAddress : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_SDRAM_ADDRESSING_STRUCT; + +typedef union { + struct { + UINT8 SignalLoading : 2; ///< Bits 1:0 + UINT8 ChannelsPerDie : 2; ///< Bits 3:2 + UINT8 DieCount : 3; ///< Bits 6:4 + UINT8 SdramPackageType : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD_LPDDR_SDRAM_PACKAGE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 MaximumActivateCount : 4; ///< Bits 3:0 + UINT8 MaximumActivateWindow : 2; ///< Bits 5:4 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_SDRAM_OPTIONAL_FEATURES_STRUCT; + +typedef union { + struct { + UINT8 Reserved : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_SDRAM_THERMAL_REFRESH_STRUCT; + +typedef union { + struct { + UINT8 Reserved : 5; ///< Bits 4:0 + UINT8 SoftPPR : 1; ///< Bits 5:5 + UINT8 PostPackageRepair : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_OTHER_SDRAM_OPTIONAL_FEATURES_STRUCT; + +typedef union { + struct { + UINT8 OperationAt1_20 : 1; ///< Bits 0:0 + UINT8 EndurantAt1_20 : 1; ///< Bits 1:1 + UINT8 OperationAt1_10 : 1; ///< Bits 2:2 + UINT8 EndurantAt1_10 : 1; ///< Bits 3:3 + UINT8 OperationAtTBD2V : 1; ///< Bits 4:4 + UINT8 EndurantAtTBD2V : 1; ///< Bits 5:5 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_NOMINAL_VOLTAGE_STRUCT; + +typedef union { + struct { + UINT8 SdramDeviceWidth : 3; ///< Bits 2:0 + UINT8 RankCount : 3; ///< Bits 5:3 + UINT8 Reserved : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_ORGANIZATION_STRUCT; + +typedef union { + struct { + UINT8 PrimaryBusWidth : 3; ///< Bits 2:0 + UINT8 BusWidthExtension : 2; ///< Bits 4:3 + UINT8 NumberofChannels : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_MEMORY_BUS_WIDTH_STRUCT; + +typedef union { + struct { + UINT8 Reserved : 7; ///< Bits 6:0 + UINT8 ThermalSensorPresence : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_THERMAL_SENSOR_STRUCT; + +typedef union { + struct { + UINT8 ExtendedBaseModuleType : 4; ///< Bits 3:0 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD_LPDDR_EXTENDED_MODULE_TYPE_STRUCT; + +typedef union { + struct { + UINT8 ChipSelectLoading : 3; ///< Bits 2:0 + UINT8 CommandAddressControlClockLoading : 3; ///< Bits 5:3 + UINT8 DataStrobeMaskLoading : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_SIGNAL_LOADING_STRUCT; + +typedef union { + struct { + UINT8 Fine : 2; ///< Bits 1:0 + UINT8 Medium : 2; ///< Bits 3:2 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD_LPDDR_TIMEBASE_STRUCT; + +typedef union { + struct { + UINT8 tCKmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_TCK_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tCKmax : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_TCK_MAX_MTB_STRUCT; + +typedef union { + struct { + UINT32 Cl3 : 1; ///< Bits 0:0 + UINT32 Cl6 : 1; ///< Bits 1:1 + UINT32 Cl8 : 1; ///< Bits 2:2 + UINT32 Cl9 : 1; ///< Bits 3:3 + UINT32 Cl10 : 1; ///< Bits 4:4 + UINT32 Cl11 : 1; ///< Bits 5:5 + UINT32 Cl12 : 1; ///< Bits 6:6 + UINT32 Cl14 : 1; ///< Bits 7:7 + UINT32 Cl16 : 1; ///< Bits 8:8 + UINT32 Reserved0 : 1; ///< Bits 9:9 + UINT32 Cl20 : 1; ///< Bits 10:10 + UINT32 Cl22 : 1; ///< Bits 11:11 + UINT32 Cl24 : 1; ///< Bits 12:12 + UINT32 Reserved1 : 1; ///< Bits 13:13 + UINT32 Cl28 : 1; ///< Bits 14:14 + UINT32 Reserved2 : 1; ///< Bits 15:15 + UINT32 Cl32 : 1; ///< Bits 16:16 + UINT32 Reserved3 : 1; ///< Bits 17:17 + UINT32 Cl36 : 1; ///< Bits 18:18 + UINT32 Reserved4 : 1; ///< Bits 19:19 + UINT32 Cl40 : 1; ///< Bits 20:20 + UINT32 Reserved5 : 11; ///< Bits 31:21 + } Bits; + UINT32 Data; + UINT16 Data16[2]; + UINT8 Data8[4]; +} SPD_LPDDR_CAS_LATENCIES_SUPPORTED_STRUCT; + +typedef union { + struct { + UINT8 tAAmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_TAA_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 ReadLatencyMode : 2; ///< Bits 1:0 + UINT8 WriteLatencySet : 2; ///< Bits 3:2 + UINT8 Reserved : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD_LPDDR_RW_LATENCY_OPTION_STRUCT; + +typedef union { + struct { + UINT8 tRCDmin : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_TRCD_MIN_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRPab : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_TRP_AB_MTB_STRUCT; + +typedef union { + struct { + UINT8 tRPpb : 8; ///< Bits 7:0 + } Bits; + UINT8 Data; +} SPD_LPDDR_TRP_PB_MTB_STRUCT; + +typedef union { + struct { + UINT16 tRFCab : 16; ///< Bits 15:0 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD_LPDDR_TRFC_AB_MTB_STRUCT; + +typedef union { +struct { + UINT16 tRFCpb : 16; ///< Bits 15:0 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD_LPDDR_TRFC_PB_MTB_STRUCT; + +typedef union { + struct { + UINT8 BitOrderatSDRAM : 5; ///< Bits 4:0 + UINT8 WiredtoUpperLowerNibble : 1; ///< Bits 5:5 + UINT8 PackageRankMap : 2; ///< Bits 7:6 + } Bits; + UINT8 Data; +} SPD_LPDDR_CONNECTOR_BIT_MAPPING_BYTE_STRUCT; + +typedef union { + struct { + INT8 tRPpbFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD_LPDDR_TRP_PB_FTB_STRUCT; + +typedef union { + struct { + INT8 tRPabFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD_LPDDR_TRP_AB_FTB_STRUCT; + +typedef union { + struct { + INT8 tRCDminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD_LPDDR_TRCD_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tAAminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD_LPDDR_TAA_MIN_FTB_STRUCT; + +typedef union { + struct { + INT8 tCKmaxFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD_LPDDR_TCK_MAX_FTB_STRUCT; + +typedef union { + struct { + INT8 tCKminFine : 8; ///< Bits 7:0 + } Bits; + INT8 Data; +} SPD_LPDDR_TCK_MIN_FTB_STRUCT; + +typedef union { + struct { + UINT16 ContinuationCount : 7; ///< Bits 6:0 + UINT16 ContinuationParity : 1; ///< Bits 7:7 + UINT16 LastNonZeroByte : 8; ///< Bits 15:8 + } Bits; + UINT16 Data; + UINT8 Data8[2]; +} SPD_LPDDR_MANUFACTURER_ID_CODE; + +typedef struct { + UINT8 Location; ///< Module Manufacturing Location +} SPD_LPDDR_MANUFACTURING_LOCATION; + +typedef struct { + UINT8 Year; ///< Year represented in BCD (00h = 2000) + UINT8 Week; ///< Year represented in BCD (47h = week 47) +} SPD_LPDDR_MANUFACTURING_DATE; + +typedef union { + UINT32 Data; + UINT16 SerialNumber16[2]; + UINT8 SerialNumber8[4]; +} SPD_LPDDR_MANUFACTURER_SERIAL_NUMBER; + +typedef struct { + SPD_LPDDR_MANUFACTURER_ID_CODE IdCode; ///< Module Manufacturer ID Code + SPD_LPDDR_MANUFACTURING_LOCATION Location; ///< Module Manufacturing Location + SPD_LPDDR_MANUFACTURING_DATE Date; ///< Module Manufacturing Year, in BCD (range: 2000-2255) + SPD_LPDDR_MANUFACTURER_SERIAL_NUMBER SerialNumber; ///< Module Serial Number +} SPD_LPDDR_UNIQUE_MODULE_ID; + +typedef union { + struct { + UINT8 FrontThickness : 4; ///< Bits 3:0 + UINT8 BackThickness : 4; ///< Bits 7:4 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_MAXIMUM_THICKNESS; + +typedef union { + struct { + UINT8 Height : 5; ///< Bits 4:0 + UINT8 RawCardExtension : 3; ///< Bits 7:5 + } Bits; + UINT8 Data; +} SPD_LPDDR_MODULE_NOMINAL_HEIGHT; + +typedef union { + struct { + UINT8 Card : 5; ///< Bits 4:0 + UINT8 Revision : 2; ///< Bits 6:5 + UINT8 Extension : 1; ///< Bits 7:7 + } Bits; + UINT8 Data; +} SPD_LPDDR_REFERENCE_RAW_CARD; + +typedef union { + UINT16 Crc[1]; + UINT8 Data8[2]; +} SPD_LPDDR_CYCLIC_REDUNDANCY_CODE; + +typedef struct { + SPD_LPDDR_DEVICE_DESCRIPTION_STRUCT Description; ///< 0 Number of Serial PD Bytes Written / SPD Device Size / CRC Coverage 1, 2 + SPD_LPDDR_REVISION_STRUCT Revision; ///< 1 SPD Revision + SPD_LPDDR_DRAM_DEVICE_TYPE_STRUCT DramDeviceType; ///< 2 DRAM Device Type + SPD_LPDDR_MODULE_TYPE_STRUCT ModuleType; ///< 3 Module Type + SPD_LPDDR_SDRAM_DENSITY_BANKS_STRUCT SdramDensityAndBanks; ///< 4 SDRAM Density and Banks + SPD_LPDDR_SDRAM_ADDRESSING_STRUCT SdramAddressing; ///< 5 SDRAM Addressing + SPD_LPDDR_SDRAM_PACKAGE_TYPE_STRUCT SdramPackageType; ///< 6 SDRAM Package Type + SPD_LPDDR_SDRAM_OPTIONAL_FEATURES_STRUCT SdramOptionalFeatures; ///< 7 SDRAM Optional Features + SPD_LPDDR_SDRAM_THERMAL_REFRESH_STRUCT ThermalAndRefreshOptions; ///< 8 SDRAM Thermal and Refresh Options + SPD_LPDDR_OTHER_SDRAM_OPTIONAL_FEATURES_STRUCT OtherOptionalFeatures; ///< 9 Other SDRAM Optional Features + UINT8 Reserved0; ///< 10 Reserved + SPD_LPDDR_MODULE_NOMINAL_VOLTAGE_STRUCT ModuleNominalVoltage; ///< 11 Module Nominal Voltage, VDD + SPD_LPDDR_MODULE_ORGANIZATION_STRUCT ModuleOrganization; ///< 12 Module Organization + SPD_LPDDR_MODULE_MEMORY_BUS_WIDTH_STRUCT ModuleMemoryBusWidth; ///< 13 Module Memory Bus Width + SPD_LPDDR_MODULE_THERMAL_SENSOR_STRUCT ModuleThermalSensor; ///< 14 Module Thermal Sensor + SPD_LPDDR_EXTENDED_MODULE_TYPE_STRUCT ExtendedModuleType; ///< 15 Extended Module Type + SPD_LPDDR_SIGNAL_LOADING_STRUCT SignalLoading; ///< 16 Signal Loading + SPD_LPDDR_TIMEBASE_STRUCT Timebase; ///< 17 Timebases + SPD_LPDDR_TCK_MIN_MTB_STRUCT tCKmin; ///< 18 SDRAM Minimum Cycle Time (tCKmin) + SPD_LPDDR_TCK_MAX_MTB_STRUCT tCKmax; ///< 19 SDRAM Maximum Cycle Time (tCKmax) + SPD_LPDDR_CAS_LATENCIES_SUPPORTED_STRUCT CasLatencies; ///< 20-23 CAS Latencies Supported + SPD_LPDDR_TAA_MIN_MTB_STRUCT tAAmin; ///< 24 Minimum CAS Latency Time (tAAmin) + SPD_LPDDR_RW_LATENCY_OPTION_STRUCT LatencySetOptions; ///< 25 Read and Write Latency Set Options + SPD_LPDDR_TRCD_MIN_MTB_STRUCT tRCDmin; ///< 26 Minimum RAS# to CAS# Delay Time (tRCDmin) + SPD_LPDDR_TRP_AB_MTB_STRUCT tRPab; ///< 27 Minimum Row Precharge Delay Time (tRPab), all banks + SPD_LPDDR_TRP_PB_MTB_STRUCT tRPpb; ///< 28 Minimum Row Precharge Delay Time (tRPpb), per bank + SPD_LPDDR_TRFC_AB_MTB_STRUCT tRFCab; ///< 29-30 Minimum Refresh Recovery Delay Time (tRFCab), all banks + SPD_LPDDR_TRFC_PB_MTB_STRUCT tRFCpb; ///< 31-32 Minimum Refresh Recovery Delay Time (tRFCpb), per bank + UINT8 Reserved1[59 - 33 + 1]; ///< 33-59 Reserved + SPD_LPDDR_CONNECTOR_BIT_MAPPING_BYTE_STRUCT BitMapping[77 - 60 + 1]; ///< 60-77 Connector to SDRAM Bit Mapping + UINT8 Reserved2[119 - 78 + 1]; ///< 78-119 Reserved + SPD_LPDDR_TRP_PB_FTB_STRUCT tRPpbFine; ///< 120 Fine Offset for Minimum Row Precharge Delay Time (tRPpbFine), per bank + SPD_LPDDR_TRP_AB_FTB_STRUCT tRPabFine; ///< 121 Fine Offset for Minimum Row Precharge Delay Time (tRPabFine), all ranks + SPD_LPDDR_TRCD_MIN_FTB_STRUCT tRCDminFine; ///< 122 Fine Offset for Minimum RAS# to CAS# Delay Time (tRCDmin) + SPD_LPDDR_TAA_MIN_FTB_STRUCT tAAminFine; ///< 123 Fine Offset for Minimum CAS Latency Time (tAAmin) + SPD_LPDDR_TCK_MAX_FTB_STRUCT tCKmaxFine; ///< 124 Fine Offset for SDRAM Maximum Cycle Time (tCKmax) + SPD_LPDDR_TCK_MIN_FTB_STRUCT tCKminFine; ///< 125 Fine Offset for SDRAM Minimum Cycle Time (tCKmin) + SPD_LPDDR_CYCLIC_REDUNDANCY_CODE Crc; ///< 126-127 Cyclical Redundancy Code (CRC) +} SPD_LPDDR_BASE_SECTION; + +typedef struct { + SPD_LPDDR_MODULE_NOMINAL_HEIGHT ModuleNominalHeight; ///< 128 Module Nominal Height + SPD_LPDDR_MODULE_MAXIMUM_THICKNESS ModuleMaximumThickness; ///< 129 Module Maximum Thickness + SPD_LPDDR_REFERENCE_RAW_CARD ReferenceRawCardUsed; ///< 130 Reference Raw Card Used + UINT8 Reserved[253 - 131 + 1]; ///< 131-253 Reserved + SPD_LPDDR_CYCLIC_REDUNDANCY_CODE Crc; ///< 254-255 Cyclical Redundancy Code (CRC) +} SPD_LPDDR_MODULE_LPDIMM; + +typedef struct { + SPD_LPDDR_MODULE_LPDIMM LpDimm; ///< 128-255 Unbuffered Memory Module Types +} SPD_LPDDR_MODULE_SPECIFIC; + +typedef struct { + UINT8 ModulePartNumber[348 - 329 + 1]; ///< 329-348 Module Part Number +} SPD_LPDDR_MODULE_PART_NUMBER; + +typedef struct { + UINT8 ManufacturerSpecificData[381 - 353 + 1]; ///< 353-381 Manufacturer's Specific Data +} SPD_LPDDR_MANUFACTURER_SPECIFIC; + +typedef UINT8 SPD_LPDDR_MODULE_REVISION_CODE;///< 349 Module Revision Code +typedef UINT8 SPD_LPDDR_DRAM_STEPPING; ///< 352 Dram Stepping + +typedef struct { + SPD_LPDDR_UNIQUE_MODULE_ID ModuleId; ///< 320-328 Unique Module ID + SPD_LPDDR_MODULE_PART_NUMBER ModulePartNumber; ///< 329-348 Module Part Number + SPD_LPDDR_MODULE_REVISION_CODE ModuleRevisionCode; ///< 349 Module Revision Code + SPD_LPDDR_MANUFACTURER_ID_CODE DramIdCode; ///< 350-351 Dram Manufacturer ID Code + SPD_LPDDR_DRAM_STEPPING DramStepping; ///< 352 Dram Stepping + SPD_LPDDR_MANUFACTURER_SPECIFIC ManufacturerSpecificData; ///< 353-381 Manufacturer's Specific Data + UINT8 Reserved[383 - 382 + 1]; ///< 382-383 Reserved +} SPD_LPDDR_MANUFACTURING_DATA; + +typedef struct { + UINT8 Reserved[511 - 384 + 1]; ///< 384-511 End User Programmable +} SPD_LPDDR_END_USER_SECTION; + +/// +/// LPDDR Serial Presence Detect structure +/// +typedef struct { + SPD_LPDDR_BASE_SECTION Base; ///< 0-127 Base Configuration and DRAM Parameters + SPD_LPDDR_MODULE_SPECIFIC Module; ///< 128-255 Module-Specific Section + UINT8 Reserved[319 - 256 + 1]; ///< 256-319 Hybrid Memory Parameters + SPD_LPDDR_MANUFACTURING_DATA ManufactureInfo; ///< 320-383 Manufacturing Information + SPD_LPDDR_END_USER_SECTION EndUser; ///< 384-511 End User Programmable +} SPD_LPDDR; + +#pragma pack (pop) +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h new file mode 100644 index 0000000..5db6367 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h @@ -0,0 +1,163 @@ +/** @file + ACPI Serial Port Console Redirection Table as defined by Microsoft in + http://www.microsoft.com/whdc/system/platform/server/spcr.mspx + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2014 - 2016, ARM Limited. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_H_ +#define _SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_H_ + + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// SPCR Revision (defined in spec) +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION 0x02 + +/// +/// Serial Port Console Redirection Table Format +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT8 InterfaceType; + UINT8 Reserved1[3]; + EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddress; + UINT8 InterruptType; + UINT8 Irq; + UINT32 GlobalSystemInterrupt; + UINT8 BaudRate; + UINT8 Parity; + UINT8 StopBits; + UINT8 FlowControl; + UINT8 TerminalType; + UINT8 Reserved2; + UINT16 PciDeviceId; + UINT16 PciVendorId; + UINT8 PciBusNumber; + UINT8 PciDeviceNumber; + UINT8 PciFunctionNumber; + UINT32 PciFlags; + UINT8 PciSegment; + UINT32 Reserved3; +} EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE; + +#pragma pack() + +// +// SPCR Definitions +// + +// +// Interface Type +// + +/// +/// Full 16550 interface +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16550 0 +/// +/// Full 16450 interface +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16450 1 + + +// +// The Serial Port Subtypes for ARM are documented in Table 3 of the DBG2 Specification +// + +/// +/// ARM PL011 UART +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART 0x03 + +/// +/// ARM SBSA Generic UART (2.x) supporting 32-bit only accesses [deprecated] +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_SBSA_GENERIC_UART_2X 0x0d + +/// +/// ARM SBSA Generic UART +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_SBSA_GENERIC_UART 0x0e + +// +// Interrupt Type +// + +/// +/// PC-AT-compatible dual-8259 IRQ interrupt +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_8259 0x1 +/// +/// I/O APIC interrupt (Global System Interrupt) +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_APIC 0x2 +/// +/// I/O SAPIC interrupt (Global System Interrupt) +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_SAPIC 0x4 +/// +/// ARMH GIC interrupt (Global System Interrupt) +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC 0x8 + +// +// Baud Rate +// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600 3 +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200 4 +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600 6 +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200 7 + +// +// Parity +// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY 0 + +// +// Stop Bits +// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1 1 + +// +// Flow Control +// + +/// +/// DCD required for transmit +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_FLOW_CONTROL_DCD 0x1 +/// +/// RTS/CTS hardware flow control +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_FLOW_CONTROL_RTS_CTS 0x2 +/// +/// XON/XOFF software control +/// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_FLOW_CONTROL_XON_XOFF 0x4 + +// +// Terminal Type +// +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT100 0 +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT100_PLUS 1 +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT_UTF8 2 +#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI 3 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ServiceProcessorManagementInterfaceTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ServiceProcessorManagementInterfaceTable.h new file mode 100644 index 0000000..ea50e43 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/ServiceProcessorManagementInterfaceTable.h @@ -0,0 +1,104 @@ +/** @file + Service Processor Management Interface (SPMI) ACPI table definition from + Intelligent Platform Management Interface Specification Second Generation. + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + - Intelligent Platform Management Interface Specification Second Generation + v2.0 Revision 1.1, Dated October 2013. + https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/ipmi-intelligent-platform-mgt-interface-spec-2nd-gen-v2-0-spec-update.pdf +**/ +#ifndef _SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE_H_ +#define _SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE_H_ + +#include + +#pragma pack(1) + +/// +/// Definition for the device identification information used by the Service +/// Processor Management Interface Description Table +/// +typedef union { + /// + /// For PCI IPMI device + /// + struct { + UINT8 SegmentGroup; + UINT8 Bus; + UINT8 Device; + UINT8 Function; + } Pci; + /// + /// For non-PCI IPMI device, the ACPI _UID value of the device + /// + UINT32 Uid; +} EFI_ACPI_SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE_DEVICE_ID; + + +/// +/// Definition for Service Processor Management Interface Description Table +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + /// + /// Indicates the type of IPMI interface. + /// + UINT8 InterfaceType; + /// + /// This field must always be 01h to be compatible with any software that + /// implements previous versions of this spec. + /// + UINT8 Reserved1; + /// + /// Identifies the IPMI specification revision, in BCD format. + /// + UINT16 SpecificationRevision; + /// + /// Interrupt type(s) used by the interface. + /// + UINT8 InterruptType; + /// + /// The bit assignment of the SCI interrupt within the GPEx_STS register of a + /// GPE described if the FADT that the interface triggers. + /// + UINT8 Gpe; + /// + /// Reserved, must be 00h. + /// + UINT8 Reserved2; + /// + /// PCI Device Flag. + /// + UINT8 PciDeviceFlag; + /// + /// The I/O APIC or I/O SAPIC Global System Interrupt used by the interface. + /// + UINT32 GlobalSystemInterrupt; + /// + /// The base address of the interface register set described using the + /// Generic Address Structure (GAS, See [ACPI 2.0] for the definition). + /// + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE BaseAddress; + /// + /// Device identification information. + /// + EFI_ACPI_SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE_DEVICE_ID DeviceId; + /// + /// This field must always be null (0x00) to be compatible with any software + /// that implements previous versions of this spec. + /// + UINT8 Reserved3; +} EFI_ACPI_SERVICE_PROCESSOR_MANAGEMENT_INTERFACE_TABLE; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBios.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBios.h new file mode 100644 index 0000000..8d0f65b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBios.h @@ -0,0 +1,2602 @@ +/** @file + Industry Standard Definitions of SMBIOS Table Specification v3.2.0. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMBIOS_STANDARD_H__ +#define __SMBIOS_STANDARD_H__ + +/// +/// Reference SMBIOS 2.6, chapter 3.1.2. +/// For v2.1 and later, handle values in the range 0FF00h to 0FFFFh are reserved for +/// use by this specification. +/// +#define SMBIOS_HANDLE_RESERVED_BEGIN 0xFF00 + +/// +/// Reference SMBIOS 2.7, chapter 6.1.2. +/// The UEFI Platform Initialization Specification reserves handle number FFFEh for its +/// EFI_SMBIOS_PROTOCOL.Add() function to mean "assign an unused handle number automatically." +/// This number is not used for any other purpose by the SMBIOS specification. +/// +#define SMBIOS_HANDLE_PI_RESERVED 0xFFFE + +/// +/// Reference SMBIOS 2.6, chapter 3.1.3. +/// Each text string is limited to 64 significant characters due to system MIF limitations. +/// Reference SMBIOS 2.7, chapter 6.1.3. +/// It will have no limit on the length of each individual text string. +/// +#define SMBIOS_STRING_MAX_LENGTH 64 + +// +// The length of the entire structure table (including all strings) must be reported +// in the Structure Table Length field of the SMBIOS Structure Table Entry Point, +// which is a WORD field limited to 65,535 bytes. +// +#define SMBIOS_TABLE_MAX_LENGTH 0xFFFF + +// +// For SMBIOS 3.0, Structure table maximum size in Entry Point structure is DWORD field limited to 0xFFFFFFFF bytes. +// +#define SMBIOS_3_0_TABLE_MAX_LENGTH 0xFFFFFFFF + +// +// SMBIOS type macros which is according to SMBIOS 2.7 specification. +// +#define SMBIOS_TYPE_BIOS_INFORMATION 0 +#define SMBIOS_TYPE_SYSTEM_INFORMATION 1 +#define SMBIOS_TYPE_BASEBOARD_INFORMATION 2 +#define SMBIOS_TYPE_SYSTEM_ENCLOSURE 3 +#define SMBIOS_TYPE_PROCESSOR_INFORMATION 4 +#define SMBIOS_TYPE_MEMORY_CONTROLLER_INFORMATION 5 +#define SMBIOS_TYPE_MEMORY_MODULE_INFORMATON 6 +#define SMBIOS_TYPE_CACHE_INFORMATION 7 +#define SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION 8 +#define SMBIOS_TYPE_SYSTEM_SLOTS 9 +#define SMBIOS_TYPE_ONBOARD_DEVICE_INFORMATION 10 +#define SMBIOS_TYPE_OEM_STRINGS 11 +#define SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS 12 +#define SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION 13 +#define SMBIOS_TYPE_GROUP_ASSOCIATIONS 14 +#define SMBIOS_TYPE_SYSTEM_EVENT_LOG 15 +#define SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY 16 +#define SMBIOS_TYPE_MEMORY_DEVICE 17 +#define SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION 18 +#define SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS 19 +#define SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS 20 +#define SMBIOS_TYPE_BUILT_IN_POINTING_DEVICE 21 +#define SMBIOS_TYPE_PORTABLE_BATTERY 22 +#define SMBIOS_TYPE_SYSTEM_RESET 23 +#define SMBIOS_TYPE_HARDWARE_SECURITY 24 +#define SMBIOS_TYPE_SYSTEM_POWER_CONTROLS 25 +#define SMBIOS_TYPE_VOLTAGE_PROBE 26 +#define SMBIOS_TYPE_COOLING_DEVICE 27 +#define SMBIOS_TYPE_TEMPERATURE_PROBE 28 +#define SMBIOS_TYPE_ELECTRICAL_CURRENT_PROBE 29 +#define SMBIOS_TYPE_OUT_OF_BAND_REMOTE_ACCESS 30 +#define SMBIOS_TYPE_BOOT_INTEGRITY_SERVICE 31 +#define SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION 32 +#define SMBIOS_TYPE_64BIT_MEMORY_ERROR_INFORMATION 33 +#define SMBIOS_TYPE_MANAGEMENT_DEVICE 34 +#define SMBIOS_TYPE_MANAGEMENT_DEVICE_COMPONENT 35 +#define SMBIOS_TYPE_MANAGEMENT_DEVICE_THRESHOLD_DATA 36 +#define SMBIOS_TYPE_MEMORY_CHANNEL 37 +#define SMBIOS_TYPE_IPMI_DEVICE_INFORMATION 38 +#define SMBIOS_TYPE_SYSTEM_POWER_SUPPLY 39 +#define SMBIOS_TYPE_ADDITIONAL_INFORMATION 40 +#define SMBIOS_TYPE_ONBOARD_DEVICES_EXTENDED_INFORMATION 41 +#define SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE 42 +#define SMBIOS_TYPE_TPM_DEVICE 43 + +/// +/// Inactive type is added from SMBIOS 2.2. Reference SMBIOS 2.6, chapter 3.3.43. +/// Upper-level software that interprets the SMBIOS structure-table should bypass an +/// Inactive structure just like a structure type that the software does not recognize. +/// +#define SMBIOS_TYPE_INACTIVE 0x007E + +/// +/// End-of-table type is added from SMBIOS 2.2. Reference SMBIOS 2.6, chapter 3.3.44. +/// The end-of-table indicator is used in the last physical structure in a table +/// +#define SMBIOS_TYPE_END_OF_TABLE 0x007F + +#define SMBIOS_OEM_BEGIN 128 +#define SMBIOS_OEM_END 255 + +/// +/// Types 0 through 127 (7Fh) are reserved for and defined by this +/// specification. Types 128 through 256 (80h to FFh) are available for system- and OEM-specific information. +/// +typedef UINT8 SMBIOS_TYPE; + +/// +/// Specifies the structure's handle, a unique 16-bit number in the range 0 to 0FFFEh (for version +/// 2.0) or 0 to 0FEFFh (for version 2.1 and later). The handle can be used with the Get SMBIOS +/// Structure function to retrieve a specific structure; the handle numbers are not required to be +/// contiguous. For v2.1 and later, handle values in the range 0FF00h to 0FFFFh are reserved for +/// use by this specification. +/// If the system configuration changes, a previously assigned handle might no longer exist. +/// However once a handle has been assigned by the BIOS, the BIOS cannot re-assign that handle +/// number to another structure. +/// +typedef UINT16 SMBIOS_HANDLE; + +/// +/// Smbios Table Entry Point Structure. +/// +#pragma pack(1) +typedef struct { + UINT8 AnchorString[4]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT16 MaxStructureSize; + UINT8 EntryPointRevision; + UINT8 FormattedArea[5]; + UINT8 IntermediateAnchorString[5]; + UINT8 IntermediateChecksum; + UINT16 TableLength; + UINT32 TableAddress; + UINT16 NumberOfSmbiosStructures; + UINT8 SmbiosBcdRevision; +} SMBIOS_TABLE_ENTRY_POINT; + +typedef struct { + UINT8 AnchorString[5]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT8 DocRev; + UINT8 EntryPointRevision; + UINT8 Reserved; + UINT32 TableMaximumSize; + UINT64 TableAddress; +} SMBIOS_TABLE_3_0_ENTRY_POINT; + +/// +/// The Smbios structure header. +/// +typedef struct { + SMBIOS_TYPE Type; + UINT8 Length; + SMBIOS_HANDLE Handle; +} SMBIOS_STRUCTURE; + +/// +/// Text strings associated with a given SMBIOS structure are returned in the dmiStrucBuffer, appended directly after +/// the formatted portion of the structure. This method of returning string information eliminates the need for +/// application software to deal with pointers embedded in the SMBIOS structure. Each string is terminated with a null +/// (00h) BYTE and the set of strings is terminated with an additional null (00h) BYTE. When the formatted portion of +/// a SMBIOS structure references a string, it does so by specifying a non-zero string number within the structure's +/// string-set. For example, if a string field contains 02h, it references the second string following the formatted portion +/// of the SMBIOS structure. If a string field references no string, a null (0) is placed in that string field. If the +/// formatted portion of the structure contains string-reference fields and all the string fields are set to 0 (no string +/// references), the formatted section of the structure is followed by two null (00h) BYTES. +/// +typedef UINT8 SMBIOS_TABLE_STRING; + +/// +/// BIOS Characteristics +/// Defines which functions the BIOS supports. PCI, PCMCIA, Flash, etc. +/// +typedef struct { + UINT32 Reserved :2; ///< Bits 0-1. + UINT32 Unknown :1; + UINT32 BiosCharacteristicsNotSupported :1; + UINT32 IsaIsSupported :1; + UINT32 McaIsSupported :1; + UINT32 EisaIsSupported :1; + UINT32 PciIsSupported :1; + UINT32 PcmciaIsSupported :1; + UINT32 PlugAndPlayIsSupported :1; + UINT32 ApmIsSupported :1; + UINT32 BiosIsUpgradable :1; + UINT32 BiosShadowingAllowed :1; + UINT32 VlVesaIsSupported :1; + UINT32 EscdSupportIsAvailable :1; + UINT32 BootFromCdIsSupported :1; + UINT32 SelectableBootIsSupported :1; + UINT32 RomBiosIsSocketed :1; + UINT32 BootFromPcmciaIsSupported :1; + UINT32 EDDSpecificationIsSupported :1; + UINT32 JapaneseNecFloppyIsSupported :1; + UINT32 JapaneseToshibaFloppyIsSupported :1; + UINT32 Floppy525_360IsSupported :1; + UINT32 Floppy525_12IsSupported :1; + UINT32 Floppy35_720IsSupported :1; + UINT32 Floppy35_288IsSupported :1; + UINT32 PrintScreenIsSupported :1; + UINT32 Keyboard8042IsSupported :1; + UINT32 SerialIsSupported :1; + UINT32 PrinterIsSupported :1; + UINT32 CgaMonoIsSupported :1; + UINT32 NecPc98 :1; + UINT32 ReservedForVendor :32; ///< Bits 32-63. Bits 32-47 reserved for BIOS vendor + ///< and bits 48-63 reserved for System Vendor. +} MISC_BIOS_CHARACTERISTICS; + +/// +/// BIOS Characteristics Extension Byte 1. +/// This information, available for SMBIOS version 2.1 and later, appears at offset 12h +/// within the BIOS Information structure. +/// +typedef struct { + UINT8 AcpiIsSupported :1; + UINT8 UsbLegacyIsSupported :1; + UINT8 AgpIsSupported :1; + UINT8 I2OBootIsSupported :1; + UINT8 Ls120BootIsSupported :1; + UINT8 AtapiZipDriveBootIsSupported :1; + UINT8 Boot1394IsSupported :1; + UINT8 SmartBatteryIsSupported :1; +} MBCE_BIOS_RESERVED; + +/// +/// BIOS Characteristics Extension Byte 2. +/// This information, available for SMBIOS version 2.3 and later, appears at offset 13h +/// within the BIOS Information structure. +/// +typedef struct { + UINT8 BiosBootSpecIsSupported :1; + UINT8 FunctionKeyNetworkBootIsSupported :1; + UINT8 TargetContentDistributionEnabled :1; + UINT8 UefiSpecificationSupported :1; + UINT8 VirtualMachineSupported :1; + UINT8 ExtensionByte2Reserved :3; +} MBCE_SYSTEM_RESERVED; + +/// +/// BIOS Characteristics Extension Bytes. +/// +typedef struct { + MBCE_BIOS_RESERVED BiosReserved; + MBCE_SYSTEM_RESERVED SystemReserved; +} MISC_BIOS_CHARACTERISTICS_EXTENSION; + +/// +/// Extended BIOS ROM size. +/// +typedef struct { + UINT16 Size :14; + UINT16 Unit :2; +} EXTENDED_BIOS_ROM_SIZE; + +/// +/// BIOS Information (Type 0). +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Vendor; + SMBIOS_TABLE_STRING BiosVersion; + UINT16 BiosSegment; + SMBIOS_TABLE_STRING BiosReleaseDate; + UINT8 BiosSize; + MISC_BIOS_CHARACTERISTICS BiosCharacteristics; + UINT8 BIOSCharacteristicsExtensionBytes[2]; + UINT8 SystemBiosMajorRelease; + UINT8 SystemBiosMinorRelease; + UINT8 EmbeddedControllerFirmwareMajorRelease; + UINT8 EmbeddedControllerFirmwareMinorRelease; + // + // Add for smbios 3.1.0 + // + EXTENDED_BIOS_ROM_SIZE ExtendedBiosSize; +} SMBIOS_TABLE_TYPE0; + +/// +/// System Wake-up Type. +/// +typedef enum { + SystemWakeupTypeReserved = 0x00, + SystemWakeupTypeOther = 0x01, + SystemWakeupTypeUnknown = 0x02, + SystemWakeupTypeApmTimer = 0x03, + SystemWakeupTypeModemRing = 0x04, + SystemWakeupTypeLanRemote = 0x05, + SystemWakeupTypePowerSwitch = 0x06, + SystemWakeupTypePciPme = 0x07, + SystemWakeupTypeAcPowerRestored = 0x08 +} MISC_SYSTEM_WAKEUP_TYPE; + +/// +/// System Information (Type 1). +/// +/// The information in this structure defines attributes of the overall system and is +/// intended to be associated with the Component ID group of the system's MIF. +/// An SMBIOS implementation is associated with a single system instance and contains +/// one and only one System Information (Type 1) structure. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Manufacturer; + SMBIOS_TABLE_STRING ProductName; + SMBIOS_TABLE_STRING Version; + SMBIOS_TABLE_STRING SerialNumber; + GUID Uuid; + UINT8 WakeUpType; ///< The enumeration value from MISC_SYSTEM_WAKEUP_TYPE. + SMBIOS_TABLE_STRING SKUNumber; + SMBIOS_TABLE_STRING Family; +} SMBIOS_TABLE_TYPE1; + +/// +/// Base Board - Feature Flags. +/// +typedef struct { + UINT8 Motherboard :1; + UINT8 RequiresDaughterCard :1; + UINT8 Removable :1; + UINT8 Replaceable :1; + UINT8 HotSwappable :1; + UINT8 Reserved :3; +} BASE_BOARD_FEATURE_FLAGS; + +/// +/// Base Board - Board Type. +/// +typedef enum { + BaseBoardTypeUnknown = 0x1, + BaseBoardTypeOther = 0x2, + BaseBoardTypeServerBlade = 0x3, + BaseBoardTypeConnectivitySwitch = 0x4, + BaseBoardTypeSystemManagementModule = 0x5, + BaseBoardTypeProcessorModule = 0x6, + BaseBoardTypeIOModule = 0x7, + BaseBoardTypeMemoryModule = 0x8, + BaseBoardTypeDaughterBoard = 0x9, + BaseBoardTypeMotherBoard = 0xA, + BaseBoardTypeProcessorMemoryModule = 0xB, + BaseBoardTypeProcessorIOModule = 0xC, + BaseBoardTypeInterconnectBoard = 0xD +} BASE_BOARD_TYPE; + +/// +/// Base Board (or Module) Information (Type 2). +/// +/// The information in this structure defines attributes of a system baseboard - +/// for example a motherboard, planar, or server blade or other standard system module. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Manufacturer; + SMBIOS_TABLE_STRING ProductName; + SMBIOS_TABLE_STRING Version; + SMBIOS_TABLE_STRING SerialNumber; + SMBIOS_TABLE_STRING AssetTag; + BASE_BOARD_FEATURE_FLAGS FeatureFlag; + SMBIOS_TABLE_STRING LocationInChassis; + UINT16 ChassisHandle; + UINT8 BoardType; ///< The enumeration value from BASE_BOARD_TYPE. + UINT8 NumberOfContainedObjectHandles; + UINT16 ContainedObjectHandles[1]; +} SMBIOS_TABLE_TYPE2; + +/// +/// System Enclosure or Chassis Types +/// +typedef enum { + MiscChassisTypeOther = 0x01, + MiscChassisTypeUnknown = 0x02, + MiscChassisTypeDeskTop = 0x03, + MiscChassisTypeLowProfileDesktop = 0x04, + MiscChassisTypePizzaBox = 0x05, + MiscChassisTypeMiniTower = 0x06, + MiscChassisTypeTower = 0x07, + MiscChassisTypePortable = 0x08, + MiscChassisTypeLapTop = 0x09, + MiscChassisTypeNotebook = 0x0A, + MiscChassisTypeHandHeld = 0x0B, + MiscChassisTypeDockingStation = 0x0C, + MiscChassisTypeAllInOne = 0x0D, + MiscChassisTypeSubNotebook = 0x0E, + MiscChassisTypeSpaceSaving = 0x0F, + MiscChassisTypeLunchBox = 0x10, + MiscChassisTypeMainServerChassis = 0x11, + MiscChassisTypeExpansionChassis = 0x12, + MiscChassisTypeSubChassis = 0x13, + MiscChassisTypeBusExpansionChassis = 0x14, + MiscChassisTypePeripheralChassis = 0x15, + MiscChassisTypeRaidChassis = 0x16, + MiscChassisTypeRackMountChassis = 0x17, + MiscChassisTypeSealedCasePc = 0x18, + MiscChassisMultiSystemChassis = 0x19, + MiscChassisCompactPCI = 0x1A, + MiscChassisAdvancedTCA = 0x1B, + MiscChassisBlade = 0x1C, + MiscChassisBladeEnclosure = 0x1D, + MiscChassisTablet = 0x1E, + MiscChassisConvertible = 0x1F, + MiscChassisDetachable = 0x20, + MiscChassisIoTGateway = 0x21, + MiscChassisEmbeddedPc = 0x22, + MiscChassisMiniPc = 0x23, + MiscChassisStickPc = 0x24 +} MISC_CHASSIS_TYPE; + +/// +/// System Enclosure or Chassis States . +/// +typedef enum { + ChassisStateOther = 0x01, + ChassisStateUnknown = 0x02, + ChassisStateSafe = 0x03, + ChassisStateWarning = 0x04, + ChassisStateCritical = 0x05, + ChassisStateNonRecoverable = 0x06 +} MISC_CHASSIS_STATE; + +/// +/// System Enclosure or Chassis Security Status. +/// +typedef enum { + ChassisSecurityStatusOther = 0x01, + ChassisSecurityStatusUnknown = 0x02, + ChassisSecurityStatusNone = 0x03, + ChassisSecurityStatusExternalInterfaceLockedOut = 0x04, + ChassisSecurityStatusExternalInterfaceLockedEnabled = 0x05 +} MISC_CHASSIS_SECURITY_STATE; + +/// +/// Contained Element record +/// +typedef struct { + UINT8 ContainedElementType; + UINT8 ContainedElementMinimum; + UINT8 ContainedElementMaximum; +} CONTAINED_ELEMENT; + + +/// +/// System Enclosure or Chassis (Type 3). +/// +/// The information in this structure defines attributes of the system's mechanical enclosure(s). +/// For example, if a system included a separate enclosure for its peripheral devices, +/// two structures would be returned: one for the main, system enclosure and the second for +/// the peripheral device enclosure. The additions to this structure in v2.1 of this specification +/// support the population of the CIM_Chassis class. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Manufacturer; + UINT8 Type; + SMBIOS_TABLE_STRING Version; + SMBIOS_TABLE_STRING SerialNumber; + SMBIOS_TABLE_STRING AssetTag; + UINT8 BootupState; ///< The enumeration value from MISC_CHASSIS_STATE. + UINT8 PowerSupplyState; ///< The enumeration value from MISC_CHASSIS_STATE. + UINT8 ThermalState; ///< The enumeration value from MISC_CHASSIS_STATE. + UINT8 SecurityStatus; ///< The enumeration value from MISC_CHASSIS_SECURITY_STATE. + UINT8 OemDefined[4]; + UINT8 Height; + UINT8 NumberofPowerCords; + UINT8 ContainedElementCount; + UINT8 ContainedElementRecordLength; + // + // Can have 0 to (ContainedElementCount * ContainedElementRecordLength) contained elements + // + CONTAINED_ELEMENT ContainedElements[1]; + // + // Add for smbios 2.7 + // + // Since ContainedElements has a variable number of entries, must not define SKUNumber in + // the structure. Need to reference it by starting at offset 0x15 and adding + // (ContainedElementCount * ContainedElementRecordLength) bytes. + // + // SMBIOS_TABLE_STRING SKUNumber; +} SMBIOS_TABLE_TYPE3; + +/// +/// Processor Information - Processor Type. +/// +typedef enum { + ProcessorOther = 0x01, + ProcessorUnknown = 0x02, + CentralProcessor = 0x03, + MathProcessor = 0x04, + DspProcessor = 0x05, + VideoProcessor = 0x06 +} PROCESSOR_TYPE_DATA; + +/// +/// Processor Information - Processor Family. +/// +typedef enum { + ProcessorFamilyOther = 0x01, + ProcessorFamilyUnknown = 0x02, + ProcessorFamily8086 = 0x03, + ProcessorFamily80286 = 0x04, + ProcessorFamilyIntel386 = 0x05, + ProcessorFamilyIntel486 = 0x06, + ProcessorFamily8087 = 0x07, + ProcessorFamily80287 = 0x08, + ProcessorFamily80387 = 0x09, + ProcessorFamily80487 = 0x0A, + ProcessorFamilyPentium = 0x0B, + ProcessorFamilyPentiumPro = 0x0C, + ProcessorFamilyPentiumII = 0x0D, + ProcessorFamilyPentiumMMX = 0x0E, + ProcessorFamilyCeleron = 0x0F, + ProcessorFamilyPentiumIIXeon = 0x10, + ProcessorFamilyPentiumIII = 0x11, + ProcessorFamilyM1 = 0x12, + ProcessorFamilyM2 = 0x13, + ProcessorFamilyIntelCeleronM = 0x14, + ProcessorFamilyIntelPentium4Ht = 0x15, + ProcessorFamilyAmdDuron = 0x18, + ProcessorFamilyK5 = 0x19, + ProcessorFamilyK6 = 0x1A, + ProcessorFamilyK6_2 = 0x1B, + ProcessorFamilyK6_3 = 0x1C, + ProcessorFamilyAmdAthlon = 0x1D, + ProcessorFamilyAmd29000 = 0x1E, + ProcessorFamilyK6_2Plus = 0x1F, + ProcessorFamilyPowerPC = 0x20, + ProcessorFamilyPowerPC601 = 0x21, + ProcessorFamilyPowerPC603 = 0x22, + ProcessorFamilyPowerPC603Plus = 0x23, + ProcessorFamilyPowerPC604 = 0x24, + ProcessorFamilyPowerPC620 = 0x25, + ProcessorFamilyPowerPCx704 = 0x26, + ProcessorFamilyPowerPC750 = 0x27, + ProcessorFamilyIntelCoreDuo = 0x28, + ProcessorFamilyIntelCoreDuoMobile = 0x29, + ProcessorFamilyIntelCoreSoloMobile = 0x2A, + ProcessorFamilyIntelAtom = 0x2B, + ProcessorFamilyIntelCoreM = 0x2C, + ProcessorFamilyIntelCorem3 = 0x2D, + ProcessorFamilyIntelCorem5 = 0x2E, + ProcessorFamilyIntelCorem7 = 0x2F, + ProcessorFamilyAlpha = 0x30, + ProcessorFamilyAlpha21064 = 0x31, + ProcessorFamilyAlpha21066 = 0x32, + ProcessorFamilyAlpha21164 = 0x33, + ProcessorFamilyAlpha21164PC = 0x34, + ProcessorFamilyAlpha21164a = 0x35, + ProcessorFamilyAlpha21264 = 0x36, + ProcessorFamilyAlpha21364 = 0x37, + ProcessorFamilyAmdTurionIIUltraDualCoreMobileM = 0x38, + ProcessorFamilyAmdTurionIIDualCoreMobileM = 0x39, + ProcessorFamilyAmdAthlonIIDualCoreM = 0x3A, + ProcessorFamilyAmdOpteron6100Series = 0x3B, + ProcessorFamilyAmdOpteron4100Series = 0x3C, + ProcessorFamilyAmdOpteron6200Series = 0x3D, + ProcessorFamilyAmdOpteron4200Series = 0x3E, + ProcessorFamilyAmdFxSeries = 0x3F, + ProcessorFamilyMips = 0x40, + ProcessorFamilyMIPSR4000 = 0x41, + ProcessorFamilyMIPSR4200 = 0x42, + ProcessorFamilyMIPSR4400 = 0x43, + ProcessorFamilyMIPSR4600 = 0x44, + ProcessorFamilyMIPSR10000 = 0x45, + ProcessorFamilyAmdCSeries = 0x46, + ProcessorFamilyAmdESeries = 0x47, + ProcessorFamilyAmdASeries = 0x48, ///< SMBIOS spec 2.8.0 updated the name + ProcessorFamilyAmdGSeries = 0x49, + ProcessorFamilyAmdZSeries = 0x4A, + ProcessorFamilyAmdRSeries = 0x4B, + ProcessorFamilyAmdOpteron4300 = 0x4C, + ProcessorFamilyAmdOpteron6300 = 0x4D, + ProcessorFamilyAmdOpteron3300 = 0x4E, + ProcessorFamilyAmdFireProSeries = 0x4F, + ProcessorFamilySparc = 0x50, + ProcessorFamilySuperSparc = 0x51, + ProcessorFamilymicroSparcII = 0x52, + ProcessorFamilymicroSparcIIep = 0x53, + ProcessorFamilyUltraSparc = 0x54, + ProcessorFamilyUltraSparcII = 0x55, + ProcessorFamilyUltraSparcIii = 0x56, + ProcessorFamilyUltraSparcIII = 0x57, + ProcessorFamilyUltraSparcIIIi = 0x58, + ProcessorFamily68040 = 0x60, + ProcessorFamily68xxx = 0x61, + ProcessorFamily68000 = 0x62, + ProcessorFamily68010 = 0x63, + ProcessorFamily68020 = 0x64, + ProcessorFamily68030 = 0x65, + ProcessorFamilyAmdAthlonX4QuadCore = 0x66, + ProcessorFamilyAmdOpteronX1000Series = 0x67, + ProcessorFamilyAmdOpteronX2000Series = 0x68, + ProcessorFamilyAmdOpteronASeries = 0x69, + ProcessorFamilyAmdOpteronX3000Series = 0x6A, + ProcessorFamilyAmdZen = 0x6B, + ProcessorFamilyHobbit = 0x70, + ProcessorFamilyCrusoeTM5000 = 0x78, + ProcessorFamilyCrusoeTM3000 = 0x79, + ProcessorFamilyEfficeonTM8000 = 0x7A, + ProcessorFamilyWeitek = 0x80, + ProcessorFamilyItanium = 0x82, + ProcessorFamilyAmdAthlon64 = 0x83, + ProcessorFamilyAmdOpteron = 0x84, + ProcessorFamilyAmdSempron = 0x85, + ProcessorFamilyAmdTurion64Mobile = 0x86, + ProcessorFamilyDualCoreAmdOpteron = 0x87, + ProcessorFamilyAmdAthlon64X2DualCore = 0x88, + ProcessorFamilyAmdTurion64X2Mobile = 0x89, + ProcessorFamilyQuadCoreAmdOpteron = 0x8A, + ProcessorFamilyThirdGenerationAmdOpteron = 0x8B, + ProcessorFamilyAmdPhenomFxQuadCore = 0x8C, + ProcessorFamilyAmdPhenomX4QuadCore = 0x8D, + ProcessorFamilyAmdPhenomX2DualCore = 0x8E, + ProcessorFamilyAmdAthlonX2DualCore = 0x8F, + ProcessorFamilyPARISC = 0x90, + ProcessorFamilyPaRisc8500 = 0x91, + ProcessorFamilyPaRisc8000 = 0x92, + ProcessorFamilyPaRisc7300LC = 0x93, + ProcessorFamilyPaRisc7200 = 0x94, + ProcessorFamilyPaRisc7100LC = 0x95, + ProcessorFamilyPaRisc7100 = 0x96, + ProcessorFamilyV30 = 0xA0, + ProcessorFamilyQuadCoreIntelXeon3200Series = 0xA1, + ProcessorFamilyDualCoreIntelXeon3000Series = 0xA2, + ProcessorFamilyQuadCoreIntelXeon5300Series = 0xA3, + ProcessorFamilyDualCoreIntelXeon5100Series = 0xA4, + ProcessorFamilyDualCoreIntelXeon5000Series = 0xA5, + ProcessorFamilyDualCoreIntelXeonLV = 0xA6, + ProcessorFamilyDualCoreIntelXeonULV = 0xA7, + ProcessorFamilyDualCoreIntelXeon7100Series = 0xA8, + ProcessorFamilyQuadCoreIntelXeon5400Series = 0xA9, + ProcessorFamilyQuadCoreIntelXeon = 0xAA, + ProcessorFamilyDualCoreIntelXeon5200Series = 0xAB, + ProcessorFamilyDualCoreIntelXeon7200Series = 0xAC, + ProcessorFamilyQuadCoreIntelXeon7300Series = 0xAD, + ProcessorFamilyQuadCoreIntelXeon7400Series = 0xAE, + ProcessorFamilyMultiCoreIntelXeon7400Series = 0xAF, + ProcessorFamilyPentiumIIIXeon = 0xB0, + ProcessorFamilyPentiumIIISpeedStep = 0xB1, + ProcessorFamilyPentium4 = 0xB2, + ProcessorFamilyIntelXeon = 0xB3, + ProcessorFamilyAS400 = 0xB4, + ProcessorFamilyIntelXeonMP = 0xB5, + ProcessorFamilyAMDAthlonXP = 0xB6, + ProcessorFamilyAMDAthlonMP = 0xB7, + ProcessorFamilyIntelItanium2 = 0xB8, + ProcessorFamilyIntelPentiumM = 0xB9, + ProcessorFamilyIntelCeleronD = 0xBA, + ProcessorFamilyIntelPentiumD = 0xBB, + ProcessorFamilyIntelPentiumEx = 0xBC, + ProcessorFamilyIntelCoreSolo = 0xBD, ///< SMBIOS spec 2.6 updated this value + ProcessorFamilyReserved = 0xBE, + ProcessorFamilyIntelCore2 = 0xBF, + ProcessorFamilyIntelCore2Solo = 0xC0, + ProcessorFamilyIntelCore2Extreme = 0xC1, + ProcessorFamilyIntelCore2Quad = 0xC2, + ProcessorFamilyIntelCore2ExtremeMobile = 0xC3, + ProcessorFamilyIntelCore2DuoMobile = 0xC4, + ProcessorFamilyIntelCore2SoloMobile = 0xC5, + ProcessorFamilyIntelCoreI7 = 0xC6, + ProcessorFamilyDualCoreIntelCeleron = 0xC7, + ProcessorFamilyIBM390 = 0xC8, + ProcessorFamilyG4 = 0xC9, + ProcessorFamilyG5 = 0xCA, + ProcessorFamilyG6 = 0xCB, + ProcessorFamilyzArchitecture = 0xCC, + ProcessorFamilyIntelCoreI5 = 0xCD, + ProcessorFamilyIntelCoreI3 = 0xCE, + ProcessorFamilyIntelCoreI9 = 0xCF, + ProcessorFamilyViaC7M = 0xD2, + ProcessorFamilyViaC7D = 0xD3, + ProcessorFamilyViaC7 = 0xD4, + ProcessorFamilyViaEden = 0xD5, + ProcessorFamilyMultiCoreIntelXeon = 0xD6, + ProcessorFamilyDualCoreIntelXeon3Series = 0xD7, + ProcessorFamilyQuadCoreIntelXeon3Series = 0xD8, + ProcessorFamilyViaNano = 0xD9, + ProcessorFamilyDualCoreIntelXeon5Series = 0xDA, + ProcessorFamilyQuadCoreIntelXeon5Series = 0xDB, + ProcessorFamilyDualCoreIntelXeon7Series = 0xDD, + ProcessorFamilyQuadCoreIntelXeon7Series = 0xDE, + ProcessorFamilyMultiCoreIntelXeon7Series = 0xDF, + ProcessorFamilyMultiCoreIntelXeon3400Series = 0xE0, + ProcessorFamilyAmdOpteron3000Series = 0xE4, + ProcessorFamilyAmdSempronII = 0xE5, + ProcessorFamilyEmbeddedAmdOpteronQuadCore = 0xE6, + ProcessorFamilyAmdPhenomTripleCore = 0xE7, + ProcessorFamilyAmdTurionUltraDualCoreMobile = 0xE8, + ProcessorFamilyAmdTurionDualCoreMobile = 0xE9, + ProcessorFamilyAmdAthlonDualCore = 0xEA, + ProcessorFamilyAmdSempronSI = 0xEB, + ProcessorFamilyAmdPhenomII = 0xEC, + ProcessorFamilyAmdAthlonII = 0xED, + ProcessorFamilySixCoreAmdOpteron = 0xEE, + ProcessorFamilyAmdSempronM = 0xEF, + ProcessorFamilyi860 = 0xFA, + ProcessorFamilyi960 = 0xFB, + ProcessorFamilyIndicatorFamily2 = 0xFE, + ProcessorFamilyReserved1 = 0xFF +} PROCESSOR_FAMILY_DATA; + +/// +/// Processor Information2 - Processor Family2. +/// +typedef enum { + ProcessorFamilyARMv7 = 0x0100, + ProcessorFamilyARMv8 = 0x0101, + ProcessorFamilySH3 = 0x0104, + ProcessorFamilySH4 = 0x0105, + ProcessorFamilyARM = 0x0118, + ProcessorFamilyStrongARM = 0x0119, + ProcessorFamily6x86 = 0x012C, + ProcessorFamilyMediaGX = 0x012D, + ProcessorFamilyMII = 0x012E, + ProcessorFamilyWinChip = 0x0140, + ProcessorFamilyDSP = 0x015E, + ProcessorFamilyVideoProcessor = 0x01F4 +} PROCESSOR_FAMILY2_DATA; + +/// +/// Processor Information - Voltage. +/// +typedef struct { + UINT8 ProcessorVoltageCapability5V :1; + UINT8 ProcessorVoltageCapability3_3V :1; + UINT8 ProcessorVoltageCapability2_9V :1; + UINT8 ProcessorVoltageCapabilityReserved :1; ///< Bit 3, must be zero. + UINT8 ProcessorVoltageReserved :3; ///< Bits 4-6, must be zero. + UINT8 ProcessorVoltageIndicateLegacy :1; +} PROCESSOR_VOLTAGE; + +/// +/// Processor Information - Processor Upgrade. +/// +typedef enum { + ProcessorUpgradeOther = 0x01, + ProcessorUpgradeUnknown = 0x02, + ProcessorUpgradeDaughterBoard = 0x03, + ProcessorUpgradeZIFSocket = 0x04, + ProcessorUpgradePiggyBack = 0x05, ///< Replaceable. + ProcessorUpgradeNone = 0x06, + ProcessorUpgradeLIFSocket = 0x07, + ProcessorUpgradeSlot1 = 0x08, + ProcessorUpgradeSlot2 = 0x09, + ProcessorUpgrade370PinSocket = 0x0A, + ProcessorUpgradeSlotA = 0x0B, + ProcessorUpgradeSlotM = 0x0C, + ProcessorUpgradeSocket423 = 0x0D, + ProcessorUpgradeSocketA = 0x0E, ///< Socket 462. + ProcessorUpgradeSocket478 = 0x0F, + ProcessorUpgradeSocket754 = 0x10, + ProcessorUpgradeSocket940 = 0x11, + ProcessorUpgradeSocket939 = 0x12, + ProcessorUpgradeSocketmPGA604 = 0x13, + ProcessorUpgradeSocketLGA771 = 0x14, + ProcessorUpgradeSocketLGA775 = 0x15, + ProcessorUpgradeSocketS1 = 0x16, + ProcessorUpgradeAM2 = 0x17, + ProcessorUpgradeF1207 = 0x18, + ProcessorSocketLGA1366 = 0x19, + ProcessorUpgradeSocketG34 = 0x1A, + ProcessorUpgradeSocketAM3 = 0x1B, + ProcessorUpgradeSocketC32 = 0x1C, + ProcessorUpgradeSocketLGA1156 = 0x1D, + ProcessorUpgradeSocketLGA1567 = 0x1E, + ProcessorUpgradeSocketPGA988A = 0x1F, + ProcessorUpgradeSocketBGA1288 = 0x20, + ProcessorUpgradeSocketrPGA988B = 0x21, + ProcessorUpgradeSocketBGA1023 = 0x22, + ProcessorUpgradeSocketBGA1224 = 0x23, + ProcessorUpgradeSocketLGA1155 = 0x24, ///< SMBIOS spec 2.8.0 updated the name + ProcessorUpgradeSocketLGA1356 = 0x25, + ProcessorUpgradeSocketLGA2011 = 0x26, + ProcessorUpgradeSocketFS1 = 0x27, + ProcessorUpgradeSocketFS2 = 0x28, + ProcessorUpgradeSocketFM1 = 0x29, + ProcessorUpgradeSocketFM2 = 0x2A, + ProcessorUpgradeSocketLGA2011_3 = 0x2B, + ProcessorUpgradeSocketLGA1356_3 = 0x2C, + ProcessorUpgradeSocketLGA1150 = 0x2D, + ProcessorUpgradeSocketBGA1168 = 0x2E, + ProcessorUpgradeSocketBGA1234 = 0x2F, + ProcessorUpgradeSocketBGA1364 = 0x30, + ProcessorUpgradeSocketAM4 = 0x31, + ProcessorUpgradeSocketLGA1151 = 0x32, + ProcessorUpgradeSocketBGA1356 = 0x33, + ProcessorUpgradeSocketBGA1440 = 0x34, + ProcessorUpgradeSocketBGA1515 = 0x35, + ProcessorUpgradeSocketLGA3647_1 = 0x36, + ProcessorUpgradeSocketSP3 = 0x37, + ProcessorUpgradeSocketSP3r2 = 0x38, + ProcessorUpgradeSocketLGA2066 = 0x39, + ProcessorUpgradeSocketBGA1392 = 0x3A, + ProcessorUpgradeSocketBGA1510 = 0x3B, + ProcessorUpgradeSocketBGA1528 = 0x3C +} PROCESSOR_UPGRADE; + +/// +/// Processor ID Field Description +/// +typedef struct { + UINT32 ProcessorSteppingId:4; + UINT32 ProcessorModel: 4; + UINT32 ProcessorFamily: 4; + UINT32 ProcessorType: 2; + UINT32 ProcessorReserved1: 2; + UINT32 ProcessorXModel: 4; + UINT32 ProcessorXFamily: 8; + UINT32 ProcessorReserved2: 4; +} PROCESSOR_SIGNATURE; + +typedef struct { + UINT32 ProcessorFpu :1; + UINT32 ProcessorVme :1; + UINT32 ProcessorDe :1; + UINT32 ProcessorPse :1; + UINT32 ProcessorTsc :1; + UINT32 ProcessorMsr :1; + UINT32 ProcessorPae :1; + UINT32 ProcessorMce :1; + UINT32 ProcessorCx8 :1; + UINT32 ProcessorApic :1; + UINT32 ProcessorReserved1 :1; + UINT32 ProcessorSep :1; + UINT32 ProcessorMtrr :1; + UINT32 ProcessorPge :1; + UINT32 ProcessorMca :1; + UINT32 ProcessorCmov :1; + UINT32 ProcessorPat :1; + UINT32 ProcessorPse36 :1; + UINT32 ProcessorPsn :1; + UINT32 ProcessorClfsh :1; + UINT32 ProcessorReserved2 :1; + UINT32 ProcessorDs :1; + UINT32 ProcessorAcpi :1; + UINT32 ProcessorMmx :1; + UINT32 ProcessorFxsr :1; + UINT32 ProcessorSse :1; + UINT32 ProcessorSse2 :1; + UINT32 ProcessorSs :1; + UINT32 ProcessorReserved3 :1; + UINT32 ProcessorTm :1; + UINT32 ProcessorReserved4 :2; +} PROCESSOR_FEATURE_FLAGS; + +typedef struct { + PROCESSOR_SIGNATURE Signature; + PROCESSOR_FEATURE_FLAGS FeatureFlags; +} PROCESSOR_ID_DATA; + +/// +/// Processor Information (Type 4). +/// +/// The information in this structure defines the attributes of a single processor; +/// a separate structure instance is provided for each system processor socket/slot. +/// For example, a system with an IntelDX2 processor would have a single +/// structure instance, while a system with an IntelSX2 processor would have a structure +/// to describe the main CPU, and a second structure to describe the 80487 co-processor. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Socket; + UINT8 ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA. + UINT8 ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY_DATA. + SMBIOS_TABLE_STRING ProcessorManufacture; + PROCESSOR_ID_DATA ProcessorId; + SMBIOS_TABLE_STRING ProcessorVersion; + PROCESSOR_VOLTAGE Voltage; + UINT16 ExternalClock; + UINT16 MaxSpeed; + UINT16 CurrentSpeed; + UINT8 Status; + UINT8 ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE. + UINT16 L1CacheHandle; + UINT16 L2CacheHandle; + UINT16 L3CacheHandle; + SMBIOS_TABLE_STRING SerialNumber; + SMBIOS_TABLE_STRING AssetTag; + SMBIOS_TABLE_STRING PartNumber; + // + // Add for smbios 2.5 + // + UINT8 CoreCount; + UINT8 EnabledCoreCount; + UINT8 ThreadCount; + UINT16 ProcessorCharacteristics; + // + // Add for smbios 2.6 + // + UINT16 ProcessorFamily2; + // + // Add for smbios 3.0 + // + UINT16 CoreCount2; + UINT16 EnabledCoreCount2; + UINT16 ThreadCount2; +} SMBIOS_TABLE_TYPE4; + +/// +/// Memory Controller Error Detecting Method. +/// +typedef enum { + ErrorDetectingMethodOther = 0x01, + ErrorDetectingMethodUnknown = 0x02, + ErrorDetectingMethodNone = 0x03, + ErrorDetectingMethodParity = 0x04, + ErrorDetectingMethod32Ecc = 0x05, + ErrorDetectingMethod64Ecc = 0x06, + ErrorDetectingMethod128Ecc = 0x07, + ErrorDetectingMethodCrc = 0x08 +} MEMORY_ERROR_DETECT_METHOD; + +/// +/// Memory Controller Error Correcting Capability. +/// +typedef struct { + UINT8 Other :1; + UINT8 Unknown :1; + UINT8 None :1; + UINT8 SingleBitErrorCorrect :1; + UINT8 DoubleBitErrorCorrect :1; + UINT8 ErrorScrubbing :1; + UINT8 Reserved :2; +} MEMORY_ERROR_CORRECT_CAPABILITY; + +/// +/// Memory Controller Information - Interleave Support. +/// +typedef enum { + MemoryInterleaveOther = 0x01, + MemoryInterleaveUnknown = 0x02, + MemoryInterleaveOneWay = 0x03, + MemoryInterleaveTwoWay = 0x04, + MemoryInterleaveFourWay = 0x05, + MemoryInterleaveEightWay = 0x06, + MemoryInterleaveSixteenWay = 0x07 +} MEMORY_SUPPORT_INTERLEAVE_TYPE; + +/// +/// Memory Controller Information - Memory Speeds. +/// +typedef struct { + UINT16 Other :1; + UINT16 Unknown :1; + UINT16 SeventyNs:1; + UINT16 SixtyNs :1; + UINT16 FiftyNs :1; + UINT16 Reserved :11; +} MEMORY_SPEED_TYPE; + +/// +/// Memory Controller Information (Type 5, Obsolete). +/// +/// The information in this structure defines the attributes of the system's memory controller(s) +/// and the supported attributes of any memory-modules present in the sockets controlled by +/// this controller. +/// Note: This structure, and its companion Memory Module Information (Type 6, Obsolete), +/// are obsolete starting with version 2.1 of this specification. The Physical Memory Array (Type 16) +/// and Memory Device (Type 17) structures should be used instead. BIOS providers might +/// choose to implement both memory description types to allow existing DMI browsers +/// to properly display the system's memory attributes. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 ErrDetectMethod; ///< The enumeration value from MEMORY_ERROR_DETECT_METHOD. + MEMORY_ERROR_CORRECT_CAPABILITY ErrCorrectCapability; + UINT8 SupportInterleave; ///< The enumeration value from MEMORY_SUPPORT_INTERLEAVE_TYPE. + UINT8 CurrentInterleave; ///< The enumeration value from MEMORY_SUPPORT_INTERLEAVE_TYPE . + UINT8 MaxMemoryModuleSize; + MEMORY_SPEED_TYPE SupportSpeed; + UINT16 SupportMemoryType; + UINT8 MemoryModuleVoltage; + UINT8 AssociatedMemorySlotNum; + UINT16 MemoryModuleConfigHandles[1]; +} SMBIOS_TABLE_TYPE5; + +/// +/// Memory Module Information - Memory Types +/// +typedef struct { + UINT16 Other :1; + UINT16 Unknown :1; + UINT16 Standard :1; + UINT16 FastPageMode:1; + UINT16 Edo :1; + UINT16 Parity :1; + UINT16 Ecc :1; + UINT16 Simm :1; + UINT16 Dimm :1; + UINT16 BurstEdo :1; + UINT16 Sdram :1; + UINT16 Reserved :5; +} MEMORY_CURRENT_TYPE; + +/// +/// Memory Module Information - Memory Size. +/// +typedef struct { + UINT8 InstalledOrEnabledSize :7; ///< Size (n), where 2**n is the size in MB. + UINT8 SingleOrDoubleBank :1; +} MEMORY_INSTALLED_ENABLED_SIZE; + +/// +/// Memory Module Information (Type 6, Obsolete) +/// +/// One Memory Module Information structure is included for each memory-module socket +/// in the system. The structure describes the speed, type, size, and error status +/// of each system memory module. The supported attributes of each module are described +/// by the "owning" Memory Controller Information structure. +/// Note: This structure, and its companion Memory Controller Information (Type 5, Obsolete), +/// are obsolete starting with version 2.1 of this specification. The Physical Memory Array (Type 16) +/// and Memory Device (Type 17) structures should be used instead. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING SocketDesignation; + UINT8 BankConnections; + UINT8 CurrentSpeed; + MEMORY_CURRENT_TYPE CurrentMemoryType; + MEMORY_INSTALLED_ENABLED_SIZE InstalledSize; + MEMORY_INSTALLED_ENABLED_SIZE EnabledSize; + UINT8 ErrorStatus; +} SMBIOS_TABLE_TYPE6; + +/// +/// Cache Information - SRAM Type. +/// +typedef struct { + UINT16 Other :1; + UINT16 Unknown :1; + UINT16 NonBurst :1; + UINT16 Burst :1; + UINT16 PipelineBurst :1; + UINT16 Synchronous :1; + UINT16 Asynchronous :1; + UINT16 Reserved :9; +} CACHE_SRAM_TYPE_DATA; + +/// +/// Cache Information - Error Correction Type. +/// +typedef enum { + CacheErrorOther = 0x01, + CacheErrorUnknown = 0x02, + CacheErrorNone = 0x03, + CacheErrorParity = 0x04, + CacheErrorSingleBit = 0x05, ///< ECC + CacheErrorMultiBit = 0x06 ///< ECC +} CACHE_ERROR_TYPE_DATA; + +/// +/// Cache Information - System Cache Type. +/// +typedef enum { + CacheTypeOther = 0x01, + CacheTypeUnknown = 0x02, + CacheTypeInstruction = 0x03, + CacheTypeData = 0x04, + CacheTypeUnified = 0x05 +} CACHE_TYPE_DATA; + +/// +/// Cache Information - Associativity. +/// +typedef enum { + CacheAssociativityOther = 0x01, + CacheAssociativityUnknown = 0x02, + CacheAssociativityDirectMapped = 0x03, + CacheAssociativity2Way = 0x04, + CacheAssociativity4Way = 0x05, + CacheAssociativityFully = 0x06, + CacheAssociativity8Way = 0x07, + CacheAssociativity16Way = 0x08, + CacheAssociativity12Way = 0x09, + CacheAssociativity24Way = 0x0A, + CacheAssociativity32Way = 0x0B, + CacheAssociativity48Way = 0x0C, + CacheAssociativity64Way = 0x0D, + CacheAssociativity20Way = 0x0E +} CACHE_ASSOCIATIVITY_DATA; + +/// +/// Cache Information (Type 7). +/// +/// The information in this structure defines the attributes of CPU cache device in the system. +/// One structure is specified for each such device, whether the device is internal to +/// or external to the CPU module. Cache modules can be associated with a processor structure +/// in one or two ways, depending on the SMBIOS version. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING SocketDesignation; + UINT16 CacheConfiguration; + UINT16 MaximumCacheSize; + UINT16 InstalledSize; + CACHE_SRAM_TYPE_DATA SupportedSRAMType; + CACHE_SRAM_TYPE_DATA CurrentSRAMType; + UINT8 CacheSpeed; + UINT8 ErrorCorrectionType; ///< The enumeration value from CACHE_ERROR_TYPE_DATA. + UINT8 SystemCacheType; ///< The enumeration value from CACHE_TYPE_DATA. + UINT8 Associativity; ///< The enumeration value from CACHE_ASSOCIATIVITY_DATA. + // + // Add for smbios 3.1.0 + // + UINT32 MaximumCacheSize2; + UINT32 InstalledSize2; +} SMBIOS_TABLE_TYPE7; + +/// +/// Port Connector Information - Connector Types. +/// +typedef enum { + PortConnectorTypeNone = 0x00, + PortConnectorTypeCentronics = 0x01, + PortConnectorTypeMiniCentronics = 0x02, + PortConnectorTypeProprietary = 0x03, + PortConnectorTypeDB25Male = 0x04, + PortConnectorTypeDB25Female = 0x05, + PortConnectorTypeDB15Male = 0x06, + PortConnectorTypeDB15Female = 0x07, + PortConnectorTypeDB9Male = 0x08, + PortConnectorTypeDB9Female = 0x09, + PortConnectorTypeRJ11 = 0x0A, + PortConnectorTypeRJ45 = 0x0B, + PortConnectorType50PinMiniScsi = 0x0C, + PortConnectorTypeMiniDin = 0x0D, + PortConnectorTypeMicroDin = 0x0E, + PortConnectorTypePS2 = 0x0F, + PortConnectorTypeInfrared = 0x10, + PortConnectorTypeHpHil = 0x11, + PortConnectorTypeUsb = 0x12, + PortConnectorTypeSsaScsi = 0x13, + PortConnectorTypeCircularDin8Male = 0x14, + PortConnectorTypeCircularDin8Female = 0x15, + PortConnectorTypeOnboardIde = 0x16, + PortConnectorTypeOnboardFloppy = 0x17, + PortConnectorType9PinDualInline = 0x18, + PortConnectorType25PinDualInline = 0x19, + PortConnectorType50PinDualInline = 0x1A, + PortConnectorType68PinDualInline = 0x1B, + PortConnectorTypeOnboardSoundInput = 0x1C, + PortConnectorTypeMiniCentronicsType14 = 0x1D, + PortConnectorTypeMiniCentronicsType26 = 0x1E, + PortConnectorTypeHeadPhoneMiniJack = 0x1F, + PortConnectorTypeBNC = 0x20, + PortConnectorType1394 = 0x21, + PortConnectorTypeSasSata = 0x22, + PortConnectorTypeUsbTypeC = 0x23, + PortConnectorTypePC98 = 0xA0, + PortConnectorTypePC98Hireso = 0xA1, + PortConnectorTypePCH98 = 0xA2, + PortConnectorTypePC98Note = 0xA3, + PortConnectorTypePC98Full = 0xA4, + PortConnectorTypeOther = 0xFF +} MISC_PORT_CONNECTOR_TYPE; + +/// +/// Port Connector Information - Port Types +/// +typedef enum { + PortTypeNone = 0x00, + PortTypeParallelXtAtCompatible = 0x01, + PortTypeParallelPortPs2 = 0x02, + PortTypeParallelPortEcp = 0x03, + PortTypeParallelPortEpp = 0x04, + PortTypeParallelPortEcpEpp = 0x05, + PortTypeSerialXtAtCompatible = 0x06, + PortTypeSerial16450Compatible = 0x07, + PortTypeSerial16550Compatible = 0x08, + PortTypeSerial16550ACompatible = 0x09, + PortTypeScsi = 0x0A, + PortTypeMidi = 0x0B, + PortTypeJoyStick = 0x0C, + PortTypeKeyboard = 0x0D, + PortTypeMouse = 0x0E, + PortTypeSsaScsi = 0x0F, + PortTypeUsb = 0x10, + PortTypeFireWire = 0x11, + PortTypePcmciaTypeI = 0x12, + PortTypePcmciaTypeII = 0x13, + PortTypePcmciaTypeIII = 0x14, + PortTypeCardBus = 0x15, + PortTypeAccessBusPort = 0x16, + PortTypeScsiII = 0x17, + PortTypeScsiWide = 0x18, + PortTypePC98 = 0x19, + PortTypePC98Hireso = 0x1A, + PortTypePCH98 = 0x1B, + PortTypeVideoPort = 0x1C, + PortTypeAudioPort = 0x1D, + PortTypeModemPort = 0x1E, + PortTypeNetworkPort = 0x1F, + PortTypeSata = 0x20, + PortTypeSas = 0x21, + PortTypeMfdp = 0x22, ///< Multi-Function Display Port + PortTypeThunderbolt = 0x23, + PortType8251Compatible = 0xA0, + PortType8251FifoCompatible = 0xA1, + PortTypeOther = 0xFF +} MISC_PORT_TYPE; + +/// +/// Port Connector Information (Type 8). +/// +/// The information in this structure defines the attributes of a system port connector, +/// e.g. parallel, serial, keyboard, or mouse ports. The port's type and connector information +/// are provided. One structure is present for each port provided by the system. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING InternalReferenceDesignator; + UINT8 InternalConnectorType; ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE. + SMBIOS_TABLE_STRING ExternalReferenceDesignator; + UINT8 ExternalConnectorType; ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE. + UINT8 PortType; ///< The enumeration value from MISC_PORT_TYPE. +} SMBIOS_TABLE_TYPE8; + +/// +/// System Slots - Slot Type +/// +typedef enum { + SlotTypeOther = 0x01, + SlotTypeUnknown = 0x02, + SlotTypeIsa = 0x03, + SlotTypeMca = 0x04, + SlotTypeEisa = 0x05, + SlotTypePci = 0x06, + SlotTypePcmcia = 0x07, + SlotTypeVlVesa = 0x08, + SlotTypeProprietary = 0x09, + SlotTypeProcessorCardSlot = 0x0A, + SlotTypeProprietaryMemoryCardSlot = 0x0B, + SlotTypeIORiserCardSlot = 0x0C, + SlotTypeNuBus = 0x0D, + SlotTypePci66MhzCapable = 0x0E, + SlotTypeAgp = 0x0F, + SlotTypeApg2X = 0x10, + SlotTypeAgp4X = 0x11, + SlotTypePciX = 0x12, + SlotTypeAgp8X = 0x13, + SlotTypeM2Socket1_DP = 0x14, + SlotTypeM2Socket1_SD = 0x15, + SlotTypeM2Socket2 = 0x16, + SlotTypeM2Socket3 = 0x17, + SlotTypeMxmTypeI = 0x18, + SlotTypeMxmTypeII = 0x19, + SlotTypeMxmTypeIIIStandard = 0x1A, + SlotTypeMxmTypeIIIHe = 0x1B, + SlotTypeMxmTypeIV = 0x1C, + SlotTypeMxm30TypeA = 0x1D, + SlotTypeMxm30TypeB = 0x1E, + SlotTypePciExpressGen2Sff_8639 = 0x1F, + SlotTypePciExpressGen3Sff_8639 = 0x20, + SlotTypePciExpressMini52pinWithBSKO = 0x21, ///< PCI Express Mini 52-pin (CEM spec. 2.0) with bottom-side keep-outs. + SlotTypePciExpressMini52pinWithoutBSKO = 0x22, ///< PCI Express Mini 52-pin (CEM spec. 2.0) without bottom-side keep-outs. + SlotTypePciExpressMini76pin = 0x23, ///< PCI Express Mini 76-pin (CEM spec. 2.0) Corresponds to Display-Mini card. + SlotTypePC98C20 = 0xA0, + SlotTypePC98C24 = 0xA1, + SlotTypePC98E = 0xA2, + SlotTypePC98LocalBus = 0xA3, + SlotTypePC98Card = 0xA4, + SlotTypePciExpress = 0xA5, + SlotTypePciExpressX1 = 0xA6, + SlotTypePciExpressX2 = 0xA7, + SlotTypePciExpressX4 = 0xA8, + SlotTypePciExpressX8 = 0xA9, + SlotTypePciExpressX16 = 0xAA, + SlotTypePciExpressGen2 = 0xAB, + SlotTypePciExpressGen2X1 = 0xAC, + SlotTypePciExpressGen2X2 = 0xAD, + SlotTypePciExpressGen2X4 = 0xAE, + SlotTypePciExpressGen2X8 = 0xAF, + SlotTypePciExpressGen2X16 = 0xB0, + SlotTypePciExpressGen3 = 0xB1, + SlotTypePciExpressGen3X1 = 0xB2, + SlotTypePciExpressGen3X2 = 0xB3, + SlotTypePciExpressGen3X4 = 0xB4, + SlotTypePciExpressGen3X8 = 0xB5, + SlotTypePciExpressGen3X16 = 0xB6 +} MISC_SLOT_TYPE; + +/// +/// System Slots - Slot Data Bus Width. +/// +typedef enum { + SlotDataBusWidthOther = 0x01, + SlotDataBusWidthUnknown = 0x02, + SlotDataBusWidth8Bit = 0x03, + SlotDataBusWidth16Bit = 0x04, + SlotDataBusWidth32Bit = 0x05, + SlotDataBusWidth64Bit = 0x06, + SlotDataBusWidth128Bit = 0x07, + SlotDataBusWidth1X = 0x08, ///< Or X1 + SlotDataBusWidth2X = 0x09, ///< Or X2 + SlotDataBusWidth4X = 0x0A, ///< Or X4 + SlotDataBusWidth8X = 0x0B, ///< Or X8 + SlotDataBusWidth12X = 0x0C, ///< Or X12 + SlotDataBusWidth16X = 0x0D, ///< Or X16 + SlotDataBusWidth32X = 0x0E ///< Or X32 +} MISC_SLOT_DATA_BUS_WIDTH; + +/// +/// System Slots - Current Usage. +/// +typedef enum { + SlotUsageOther = 0x01, + SlotUsageUnknown = 0x02, + SlotUsageAvailable = 0x03, + SlotUsageInUse = 0x04, + SlotUsageUnavailable = 0x05 +} MISC_SLOT_USAGE; + +/// +/// System Slots - Slot Length. +/// +typedef enum { + SlotLengthOther = 0x01, + SlotLengthUnknown = 0x02, + SlotLengthShort = 0x03, + SlotLengthLong = 0x04 +} MISC_SLOT_LENGTH; + +/// +/// System Slots - Slot Characteristics 1. +/// +typedef struct { + UINT8 CharacteristicsUnknown :1; + UINT8 Provides50Volts :1; + UINT8 Provides33Volts :1; + UINT8 SharedSlot :1; + UINT8 PcCard16Supported :1; + UINT8 CardBusSupported :1; + UINT8 ZoomVideoSupported :1; + UINT8 ModemRingResumeSupported:1; +} MISC_SLOT_CHARACTERISTICS1; +/// +/// System Slots - Slot Characteristics 2. +/// +typedef struct { + UINT8 PmeSignalSupported :1; + UINT8 HotPlugDevicesSupported :1; + UINT8 SmbusSignalSupported :1; + UINT8 BifurcationSupported :1; + UINT8 Reserved :4; ///< Set to 0. +} MISC_SLOT_CHARACTERISTICS2; + +/// +/// System Slots - Peer Segment/Bus/Device/Function/Width Groups +/// +typedef struct { + UINT16 SegmentGroupNum; + UINT8 BusNum; + UINT8 DevFuncNum; + UINT8 DataBusWidth; +} MISC_SLOT_PEER_GROUP; + +/// +/// System Slots (Type 9) +/// +/// The information in this structure defines the attributes of a system slot. +/// One structure is provided for each slot in the system. +/// +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING SlotDesignation; + UINT8 SlotType; ///< The enumeration value from MISC_SLOT_TYPE. + UINT8 SlotDataBusWidth; ///< The enumeration value from MISC_SLOT_DATA_BUS_WIDTH. + UINT8 CurrentUsage; ///< The enumeration value from MISC_SLOT_USAGE. + UINT8 SlotLength; ///< The enumeration value from MISC_SLOT_LENGTH. + UINT16 SlotID; + MISC_SLOT_CHARACTERISTICS1 SlotCharacteristics1; + MISC_SLOT_CHARACTERISTICS2 SlotCharacteristics2; + // + // Add for smbios 2.6 + // + UINT16 SegmentGroupNum; + UINT8 BusNum; + UINT8 DevFuncNum; + // + // Add for smbios 3.2 + // + UINT8 DataBusWidth; + UINT8 PeerGroupingCount; + MISC_SLOT_PEER_GROUP PeerGroups[1]; +} SMBIOS_TABLE_TYPE9; + +/// +/// On Board Devices Information - Device Types. +/// +typedef enum { + OnBoardDeviceTypeOther = 0x01, + OnBoardDeviceTypeUnknown = 0x02, + OnBoardDeviceTypeVideo = 0x03, + OnBoardDeviceTypeScsiController = 0x04, + OnBoardDeviceTypeEthernet = 0x05, + OnBoardDeviceTypeTokenRing = 0x06, + OnBoardDeviceTypeSound = 0x07, + OnBoardDeviceTypePATAController = 0x08, + OnBoardDeviceTypeSATAController = 0x09, + OnBoardDeviceTypeSASController = 0x0A +} MISC_ONBOARD_DEVICE_TYPE; + +/// +/// Device Item Entry +/// +typedef struct { + UINT8 DeviceType; ///< Bit [6:0] - enumeration type of device from MISC_ONBOARD_DEVICE_TYPE. + ///< Bit 7 - 1 : device enabled, 0 : device disabled. + SMBIOS_TABLE_STRING DescriptionString; +} DEVICE_STRUCT; + +/// +/// On Board Devices Information (Type 10, obsolete). +/// +/// Note: This structure is obsolete starting with version 2.6 specification; the Onboard Devices Extended +/// Information (Type 41) structure should be used instead . BIOS providers can choose to implement both +/// types to allow existing SMBIOS browsers to properly display the system's onboard devices information. +/// The information in this structure defines the attributes of devices that are onboard (soldered onto) +/// a system element, usually the baseboard. In general, an entry in this table implies that the BIOS +/// has some level of control over the enabling of the associated device for use by the system. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + DEVICE_STRUCT Device[1]; +} SMBIOS_TABLE_TYPE10; + +/// +/// OEM Strings (Type 11). +/// This structure contains free form strings defined by the OEM. Examples of this are: +/// Part Numbers for Reference Documents for the system, contact information for the manufacturer, etc. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 StringCount; +} SMBIOS_TABLE_TYPE11; + +/// +/// System Configuration Options (Type 12). +/// +/// This structure contains information required to configure the base board's Jumpers and Switches. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 StringCount; +} SMBIOS_TABLE_TYPE12; + + +/// +/// BIOS Language Information (Type 13). +/// +/// The information in this structure defines the installable language attributes of the BIOS. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 InstallableLanguages; + UINT8 Flags; + UINT8 Reserved[15]; + SMBIOS_TABLE_STRING CurrentLanguages; +} SMBIOS_TABLE_TYPE13; + +/// +/// Group Item Entry +/// +typedef struct { + UINT8 ItemType; + UINT16 ItemHandle; +} GROUP_STRUCT; + +/// +/// Group Associations (Type 14). +/// +/// The Group Associations structure is provided for OEMs who want to specify +/// the arrangement or hierarchy of certain components (including other Group Associations) +/// within the system. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING GroupName; + GROUP_STRUCT Group[1]; +} SMBIOS_TABLE_TYPE14; + +/// +/// System Event Log - Event Log Types. +/// +typedef enum { + EventLogTypeReserved = 0x00, + EventLogTypeSingleBitECC = 0x01, + EventLogTypeMultiBitECC = 0x02, + EventLogTypeParityMemErr = 0x03, + EventLogTypeBusTimeOut = 0x04, + EventLogTypeIOChannelCheck = 0x05, + EventLogTypeSoftwareNMI = 0x06, + EventLogTypePOSTMemResize = 0x07, + EventLogTypePOSTErr = 0x08, + EventLogTypePCIParityErr = 0x09, + EventLogTypePCISystemErr = 0x0A, + EventLogTypeCPUFailure = 0x0B, + EventLogTypeEISATimeOut = 0x0C, + EventLogTypeMemLogDisabled = 0x0D, + EventLogTypeLoggingDisabled = 0x0E, + EventLogTypeSysLimitExce = 0x10, + EventLogTypeAsyncHWTimer = 0x11, + EventLogTypeSysConfigInfo = 0x12, + EventLogTypeHDInfo = 0x13, + EventLogTypeSysReconfig = 0x14, + EventLogTypeUncorrectCPUErr = 0x15, + EventLogTypeAreaResetAndClr = 0x16, + EventLogTypeSystemBoot = 0x17, + EventLogTypeUnused = 0x18, ///< 0x18 - 0x7F + EventLogTypeAvailForSys = 0x80, ///< 0x80 - 0xFE + EventLogTypeEndOfLog = 0xFF +} EVENT_LOG_TYPE_DATA; + +/// +/// System Event Log - Variable Data Format Types. +/// +typedef enum { + EventLogVariableNone = 0x00, + EventLogVariableHandle = 0x01, + EventLogVariableMutilEvent = 0x02, + EventLogVariableMutilEventHandle = 0x03, + EventLogVariablePOSTResultBitmap = 0x04, + EventLogVariableSysManagementType = 0x05, + EventLogVariableMutliEventSysManagmentType = 0x06, + EventLogVariableUnused = 0x07, + EventLogVariableOEMAssigned = 0x80 +} EVENT_LOG_VARIABLE_DATA; + +/// +/// Event Log Type Descriptors +/// +typedef struct { + UINT8 LogType; ///< The enumeration value from EVENT_LOG_TYPE_DATA. + UINT8 DataFormatType; +} EVENT_LOG_TYPE; + +/// +/// System Event Log (Type 15). +/// +/// The presence of this structure within the SMBIOS data returned for a system indicates +/// that the system supports an event log. An event log is a fixed-length area within a +/// non-volatile storage element, starting with a fixed-length (and vendor-specific) header +/// record, followed by one or more variable-length log records. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT16 LogAreaLength; + UINT16 LogHeaderStartOffset; + UINT16 LogDataStartOffset; + UINT8 AccessMethod; + UINT8 LogStatus; + UINT32 LogChangeToken; + UINT32 AccessMethodAddress; + UINT8 LogHeaderFormat; + UINT8 NumberOfSupportedLogTypeDescriptors; + UINT8 LengthOfLogTypeDescriptor; + EVENT_LOG_TYPE EventLogTypeDescriptors[1]; +} SMBIOS_TABLE_TYPE15; + +/// +/// Physical Memory Array - Location. +/// +typedef enum { + MemoryArrayLocationOther = 0x01, + MemoryArrayLocationUnknown = 0x02, + MemoryArrayLocationSystemBoard = 0x03, + MemoryArrayLocationIsaAddonCard = 0x04, + MemoryArrayLocationEisaAddonCard = 0x05, + MemoryArrayLocationPciAddonCard = 0x06, + MemoryArrayLocationMcaAddonCard = 0x07, + MemoryArrayLocationPcmciaAddonCard = 0x08, + MemoryArrayLocationProprietaryAddonCard = 0x09, + MemoryArrayLocationNuBus = 0x0A, + MemoryArrayLocationPc98C20AddonCard = 0xA0, + MemoryArrayLocationPc98C24AddonCard = 0xA1, + MemoryArrayLocationPc98EAddonCard = 0xA2, + MemoryArrayLocationPc98LocalBusAddonCard = 0xA3 +} MEMORY_ARRAY_LOCATION; + +/// +/// Physical Memory Array - Use. +/// +typedef enum { + MemoryArrayUseOther = 0x01, + MemoryArrayUseUnknown = 0x02, + MemoryArrayUseSystemMemory = 0x03, + MemoryArrayUseVideoMemory = 0x04, + MemoryArrayUseFlashMemory = 0x05, + MemoryArrayUseNonVolatileRam = 0x06, + MemoryArrayUseCacheMemory = 0x07 +} MEMORY_ARRAY_USE; + +/// +/// Physical Memory Array - Error Correction Types. +/// +typedef enum { + MemoryErrorCorrectionOther = 0x01, + MemoryErrorCorrectionUnknown = 0x02, + MemoryErrorCorrectionNone = 0x03, + MemoryErrorCorrectionParity = 0x04, + MemoryErrorCorrectionSingleBitEcc = 0x05, + MemoryErrorCorrectionMultiBitEcc = 0x06, + MemoryErrorCorrectionCrc = 0x07 +} MEMORY_ERROR_CORRECTION; + +/// +/// Physical Memory Array (Type 16). +/// +/// This structure describes a collection of memory devices that operate +/// together to form a memory address space. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 Location; ///< The enumeration value from MEMORY_ARRAY_LOCATION. + UINT8 Use; ///< The enumeration value from MEMORY_ARRAY_USE. + UINT8 MemoryErrorCorrection; ///< The enumeration value from MEMORY_ERROR_CORRECTION. + UINT32 MaximumCapacity; + UINT16 MemoryErrorInformationHandle; + UINT16 NumberOfMemoryDevices; + // + // Add for smbios 2.7 + // + UINT64 ExtendedMaximumCapacity; +} SMBIOS_TABLE_TYPE16; + +/// +/// Memory Device - Form Factor. +/// +typedef enum { + MemoryFormFactorOther = 0x01, + MemoryFormFactorUnknown = 0x02, + MemoryFormFactorSimm = 0x03, + MemoryFormFactorSip = 0x04, + MemoryFormFactorChip = 0x05, + MemoryFormFactorDip = 0x06, + MemoryFormFactorZip = 0x07, + MemoryFormFactorProprietaryCard = 0x08, + MemoryFormFactorDimm = 0x09, + MemoryFormFactorTsop = 0x0A, + MemoryFormFactorRowOfChips = 0x0B, + MemoryFormFactorRimm = 0x0C, + MemoryFormFactorSodimm = 0x0D, + MemoryFormFactorSrimm = 0x0E, + MemoryFormFactorFbDimm = 0x0F +} MEMORY_FORM_FACTOR; + +/// +/// Memory Device - Type +/// +typedef enum { + MemoryTypeOther = 0x01, + MemoryTypeUnknown = 0x02, + MemoryTypeDram = 0x03, + MemoryTypeEdram = 0x04, + MemoryTypeVram = 0x05, + MemoryTypeSram = 0x06, + MemoryTypeRam = 0x07, + MemoryTypeRom = 0x08, + MemoryTypeFlash = 0x09, + MemoryTypeEeprom = 0x0A, + MemoryTypeFeprom = 0x0B, + MemoryTypeEprom = 0x0C, + MemoryTypeCdram = 0x0D, + MemoryType3Dram = 0x0E, + MemoryTypeSdram = 0x0F, + MemoryTypeSgram = 0x10, + MemoryTypeRdram = 0x11, + MemoryTypeDdr = 0x12, + MemoryTypeDdr2 = 0x13, + MemoryTypeDdr2FbDimm = 0x14, + MemoryTypeDdr3 = 0x18, + MemoryTypeFbd2 = 0x19, + MemoryTypeDdr4 = 0x1A, + MemoryTypeLpddr = 0x1B, + MemoryTypeLpddr2 = 0x1C, + MemoryTypeLpddr3 = 0x1D, + MemoryTypeLpddr4 = 0x1E, + MemoryTypeLogicalNonVolatileDevice = 0x1F +} MEMORY_DEVICE_TYPE; + +/// +/// Memory Device - Type Detail +/// +typedef struct { + UINT16 Reserved :1; + UINT16 Other :1; + UINT16 Unknown :1; + UINT16 FastPaged :1; + UINT16 StaticColumn :1; + UINT16 PseudoStatic :1; + UINT16 Rambus :1; + UINT16 Synchronous :1; + UINT16 Cmos :1; + UINT16 Edo :1; + UINT16 WindowDram :1; + UINT16 CacheDram :1; + UINT16 Nonvolatile :1; + UINT16 Registered :1; + UINT16 Unbuffered :1; + UINT16 LrDimm :1; +} MEMORY_DEVICE_TYPE_DETAIL; + +/// +/// Memory Device - Memory Technology +/// +typedef enum { + MemoryTechnologyOther = 0x01, + MemoryTechnologyUnknown = 0x02, + MemoryTechnologyDram = 0x03, + MemoryTechnologyNvdimmN = 0x04, + MemoryTechnologyNvdimmF = 0x05, + MemoryTechnologyNvdimmP = 0x06, + MemoryTechnologyIntelPersistentMemory = 0x07 +} MEMORY_DEVICE_TECHNOLOGY; + +/// +/// Memory Device - Memory Operating Mode Capability +/// +typedef union { + /// + /// Individual bit fields + /// + struct { + UINT16 Reserved :1; ///< Set to 0. + UINT16 Other :1; + UINT16 Unknown :1; + UINT16 VolatileMemory :1; + UINT16 ByteAccessiblePersistentMemory :1; + UINT16 BlockAccessiblePersistentMemory :1; + UINT16 Reserved2 :10; ///< Set to 0. + } Bits; + /// + /// All bit fields as a 16-bit value + /// + UINT16 Uint16; +} MEMORY_DEVICE_OPERATING_MODE_CAPABILITY; + +/// +/// Memory Device (Type 17). +/// +/// This structure describes a single memory device that is part of +/// a larger Physical Memory Array (Type 16). +/// Note: If a system includes memory-device sockets, the SMBIOS implementation +/// includes a Memory Device structure instance for each slot, whether or not the +/// socket is currently populated. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT16 MemoryArrayHandle; + UINT16 MemoryErrorInformationHandle; + UINT16 TotalWidth; + UINT16 DataWidth; + UINT16 Size; + UINT8 FormFactor; ///< The enumeration value from MEMORY_FORM_FACTOR. + UINT8 DeviceSet; + SMBIOS_TABLE_STRING DeviceLocator; + SMBIOS_TABLE_STRING BankLocator; + UINT8 MemoryType; ///< The enumeration value from MEMORY_DEVICE_TYPE. + MEMORY_DEVICE_TYPE_DETAIL TypeDetail; + UINT16 Speed; + SMBIOS_TABLE_STRING Manufacturer; + SMBIOS_TABLE_STRING SerialNumber; + SMBIOS_TABLE_STRING AssetTag; + SMBIOS_TABLE_STRING PartNumber; + // + // Add for smbios 2.6 + // + UINT8 Attributes; + // + // Add for smbios 2.7 + // + UINT32 ExtendedSize; + // + // Keep using name "ConfiguredMemoryClockSpeed" for compatibility + // although this field is renamed from "Configured Memory Clock Speed" + // to "Configured Memory Speed" in smbios 3.2.0. + // + UINT16 ConfiguredMemoryClockSpeed; + // + // Add for smbios 2.8.0 + // + UINT16 MinimumVoltage; + UINT16 MaximumVoltage; + UINT16 ConfiguredVoltage; + // + // Add for smbios 3.2.0 + // + UINT8 MemoryTechnology; ///< The enumeration value from MEMORY_DEVICE_TECHNOLOGY + MEMORY_DEVICE_OPERATING_MODE_CAPABILITY MemoryOperatingModeCapability; + SMBIOS_TABLE_STRING FirwareVersion; + UINT16 ModuleManufacturerID; + UINT16 ModuleProductID; + UINT16 MemorySubsystemControllerManufacturerID; + UINT16 MemorySubsystemControllerProductID; + UINT64 NonVolatileSize; + UINT64 VolatileSize; + UINT64 CacheSize; + UINT64 LogicalSize; +} SMBIOS_TABLE_TYPE17; + +/// +/// 32-bit Memory Error Information - Error Type. +/// +typedef enum { + MemoryErrorOther = 0x01, + MemoryErrorUnknown = 0x02, + MemoryErrorOk = 0x03, + MemoryErrorBadRead = 0x04, + MemoryErrorParity = 0x05, + MemoryErrorSigleBit = 0x06, + MemoryErrorDoubleBit = 0x07, + MemoryErrorMultiBit = 0x08, + MemoryErrorNibble = 0x09, + MemoryErrorChecksum = 0x0A, + MemoryErrorCrc = 0x0B, + MemoryErrorCorrectSingleBit = 0x0C, + MemoryErrorCorrected = 0x0D, + MemoryErrorUnCorrectable = 0x0E +} MEMORY_ERROR_TYPE; + +/// +/// 32-bit Memory Error Information - Error Granularity. +/// +typedef enum { + MemoryGranularityOther = 0x01, + MemoryGranularityOtherUnknown = 0x02, + MemoryGranularityDeviceLevel = 0x03, + MemoryGranularityMemPartitionLevel = 0x04 +} MEMORY_ERROR_GRANULARITY; + +/// +/// 32-bit Memory Error Information - Error Operation. +/// +typedef enum { + MemoryErrorOperationOther = 0x01, + MemoryErrorOperationUnknown = 0x02, + MemoryErrorOperationRead = 0x03, + MemoryErrorOperationWrite = 0x04, + MemoryErrorOperationPartialWrite = 0x05 +} MEMORY_ERROR_OPERATION; + +/// +/// 32-bit Memory Error Information (Type 18). +/// +/// This structure identifies the specifics of an error that might be detected +/// within a Physical Memory Array. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 ErrorType; ///< The enumeration value from MEMORY_ERROR_TYPE. + UINT8 ErrorGranularity; ///< The enumeration value from MEMORY_ERROR_GRANULARITY. + UINT8 ErrorOperation; ///< The enumeration value from MEMORY_ERROR_OPERATION. + UINT32 VendorSyndrome; + UINT32 MemoryArrayErrorAddress; + UINT32 DeviceErrorAddress; + UINT32 ErrorResolution; +} SMBIOS_TABLE_TYPE18; + +/// +/// Memory Array Mapped Address (Type 19). +/// +/// This structure provides the address mapping for a Physical Memory Array. +/// One structure is present for each contiguous address range described. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT32 StartingAddress; + UINT32 EndingAddress; + UINT16 MemoryArrayHandle; + UINT8 PartitionWidth; + // + // Add for smbios 2.7 + // + UINT64 ExtendedStartingAddress; + UINT64 ExtendedEndingAddress; +} SMBIOS_TABLE_TYPE19; + +/// +/// Memory Device Mapped Address (Type 20). +/// +/// This structure maps memory address space usually to a device-level granularity. +/// One structure is present for each contiguous address range described. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT32 StartingAddress; + UINT32 EndingAddress; + UINT16 MemoryDeviceHandle; + UINT16 MemoryArrayMappedAddressHandle; + UINT8 PartitionRowPosition; + UINT8 InterleavePosition; + UINT8 InterleavedDataDepth; + // + // Add for smbios 2.7 + // + UINT64 ExtendedStartingAddress; + UINT64 ExtendedEndingAddress; +} SMBIOS_TABLE_TYPE20; + +/// +/// Built-in Pointing Device - Type +/// +typedef enum { + PointingDeviceTypeOther = 0x01, + PointingDeviceTypeUnknown = 0x02, + PointingDeviceTypeMouse = 0x03, + PointingDeviceTypeTrackBall = 0x04, + PointingDeviceTypeTrackPoint = 0x05, + PointingDeviceTypeGlidePoint = 0x06, + PointingDeviceTouchPad = 0x07, + PointingDeviceTouchScreen = 0x08, + PointingDeviceOpticalSensor = 0x09 +} BUILTIN_POINTING_DEVICE_TYPE; + +/// +/// Built-in Pointing Device - Interface. +/// +typedef enum { + PointingDeviceInterfaceOther = 0x01, + PointingDeviceInterfaceUnknown = 0x02, + PointingDeviceInterfaceSerial = 0x03, + PointingDeviceInterfacePs2 = 0x04, + PointingDeviceInterfaceInfrared = 0x05, + PointingDeviceInterfaceHpHil = 0x06, + PointingDeviceInterfaceBusMouse = 0x07, + PointingDeviceInterfaceADB = 0x08, + PointingDeviceInterfaceBusMouseDB9 = 0xA0, + PointingDeviceInterfaceBusMouseMicroDin = 0xA1, + PointingDeviceInterfaceUsb = 0xA2 +} BUILTIN_POINTING_DEVICE_INTERFACE; + +/// +/// Built-in Pointing Device (Type 21). +/// +/// This structure describes the attributes of the built-in pointing device for the +/// system. The presence of this structure does not imply that the built-in +/// pointing device is active for the system's use! +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 Type; ///< The enumeration value from BUILTIN_POINTING_DEVICE_TYPE. + UINT8 Interface; ///< The enumeration value from BUILTIN_POINTING_DEVICE_INTERFACE. + UINT8 NumberOfButtons; +} SMBIOS_TABLE_TYPE21; + +/// +/// Portable Battery - Device Chemistry +/// +typedef enum { + PortableBatteryDeviceChemistryOther = 0x01, + PortableBatteryDeviceChemistryUnknown = 0x02, + PortableBatteryDeviceChemistryLeadAcid = 0x03, + PortableBatteryDeviceChemistryNickelCadmium = 0x04, + PortableBatteryDeviceChemistryNickelMetalHydride = 0x05, + PortableBatteryDeviceChemistryLithiumIon = 0x06, + PortableBatteryDeviceChemistryZincAir = 0x07, + PortableBatteryDeviceChemistryLithiumPolymer = 0x08 +} PORTABLE_BATTERY_DEVICE_CHEMISTRY; + +/// +/// Portable Battery (Type 22). +/// +/// This structure describes the attributes of the portable battery(s) for the system. +/// The structure contains the static attributes for the group. Each structure describes +/// a single battery pack's attributes. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Location; + SMBIOS_TABLE_STRING Manufacturer; + SMBIOS_TABLE_STRING ManufactureDate; + SMBIOS_TABLE_STRING SerialNumber; + SMBIOS_TABLE_STRING DeviceName; + UINT8 DeviceChemistry; ///< The enumeration value from PORTABLE_BATTERY_DEVICE_CHEMISTRY. + UINT16 DeviceCapacity; + UINT16 DesignVoltage; + SMBIOS_TABLE_STRING SBDSVersionNumber; + UINT8 MaximumErrorInBatteryData; + UINT16 SBDSSerialNumber; + UINT16 SBDSManufactureDate; + SMBIOS_TABLE_STRING SBDSDeviceChemistry; + UINT8 DesignCapacityMultiplier; + UINT32 OEMSpecific; +} SMBIOS_TABLE_TYPE22; + +/// +/// System Reset (Type 23) +/// +/// This structure describes whether Automatic System Reset functions enabled (Status). +/// If the system has a watchdog Timer and the timer is not reset (Timer Reset) +/// before the Interval elapses, an automatic system reset will occur. The system will re-boot +/// according to the Boot Option. This function may repeat until the Limit is reached, at which time +/// the system will re-boot according to the Boot Option at Limit. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 Capabilities; + UINT16 ResetCount; + UINT16 ResetLimit; + UINT16 TimerInterval; + UINT16 Timeout; +} SMBIOS_TABLE_TYPE23; + +/// +/// Hardware Security (Type 24). +/// +/// This structure describes the system-wide hardware security settings. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 HardwareSecuritySettings; +} SMBIOS_TABLE_TYPE24; + +/// +/// System Power Controls (Type 25). +/// +/// This structure describes the attributes for controlling the main power supply to the system. +/// Software that interprets this structure uses the month, day, hour, minute, and second values +/// to determine the number of seconds until the next power-on of the system. The presence of +/// this structure implies that a timed power-on facility is available for the system. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 NextScheduledPowerOnMonth; + UINT8 NextScheduledPowerOnDayOfMonth; + UINT8 NextScheduledPowerOnHour; + UINT8 NextScheduledPowerOnMinute; + UINT8 NextScheduledPowerOnSecond; +} SMBIOS_TABLE_TYPE25; + +/// +/// Voltage Probe - Location and Status. +/// +typedef struct { + UINT8 VoltageProbeSite :5; + UINT8 VoltageProbeStatus :3; +} MISC_VOLTAGE_PROBE_LOCATION; + +/// +/// Voltage Probe (Type 26) +/// +/// This describes the attributes for a voltage probe in the system. +/// Each structure describes a single voltage probe. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Description; + MISC_VOLTAGE_PROBE_LOCATION LocationAndStatus; + UINT16 MaximumValue; + UINT16 MinimumValue; + UINT16 Resolution; + UINT16 Tolerance; + UINT16 Accuracy; + UINT32 OEMDefined; + UINT16 NominalValue; +} SMBIOS_TABLE_TYPE26; + +/// +/// Cooling Device - Device Type and Status. +/// +typedef struct { + UINT8 CoolingDevice :5; + UINT8 CoolingDeviceStatus :3; +} MISC_COOLING_DEVICE_TYPE; + +/// +/// Cooling Device (Type 27) +/// +/// This structure describes the attributes for a cooling device in the system. +/// Each structure describes a single cooling device. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT16 TemperatureProbeHandle; + MISC_COOLING_DEVICE_TYPE DeviceTypeAndStatus; + UINT8 CoolingUnitGroup; + UINT32 OEMDefined; + UINT16 NominalSpeed; + // + // Add for smbios 2.7 + // + SMBIOS_TABLE_STRING Description; +} SMBIOS_TABLE_TYPE27; + +/// +/// Temperature Probe - Location and Status. +/// +typedef struct { + UINT8 TemperatureProbeSite :5; + UINT8 TemperatureProbeStatus :3; +} MISC_TEMPERATURE_PROBE_LOCATION; + +/// +/// Temperature Probe (Type 28). +/// +/// This structure describes the attributes for a temperature probe in the system. +/// Each structure describes a single temperature probe. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Description; + MISC_TEMPERATURE_PROBE_LOCATION LocationAndStatus; + UINT16 MaximumValue; + UINT16 MinimumValue; + UINT16 Resolution; + UINT16 Tolerance; + UINT16 Accuracy; + UINT32 OEMDefined; + UINT16 NominalValue; +} SMBIOS_TABLE_TYPE28; + +/// +/// Electrical Current Probe - Location and Status. +/// +typedef struct { + UINT8 ElectricalCurrentProbeSite :5; + UINT8 ElectricalCurrentProbeStatus :3; +} MISC_ELECTRICAL_CURRENT_PROBE_LOCATION; + +/// +/// Electrical Current Probe (Type 29). +/// +/// This structure describes the attributes for an electrical current probe in the system. +/// Each structure describes a single electrical current probe. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Description; + MISC_ELECTRICAL_CURRENT_PROBE_LOCATION LocationAndStatus; + UINT16 MaximumValue; + UINT16 MinimumValue; + UINT16 Resolution; + UINT16 Tolerance; + UINT16 Accuracy; + UINT32 OEMDefined; + UINT16 NominalValue; +} SMBIOS_TABLE_TYPE29; + +/// +/// Out-of-Band Remote Access (Type 30). +/// +/// This structure describes the attributes and policy settings of a hardware facility +/// that may be used to gain remote access to a hardware system when the operating system +/// is not available due to power-down status, hardware failures, or boot failures. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING ManufacturerName; + UINT8 Connections; +} SMBIOS_TABLE_TYPE30; + +/// +/// Boot Integrity Services (BIS) Entry Point (Type 31). +/// +/// Structure type 31 (decimal) is reserved for use by the Boot Integrity Services (BIS). +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 Checksum; + UINT8 Reserved1; + UINT16 Reserved2; + UINT32 BisEntry16; + UINT32 BisEntry32; + UINT64 Reserved3; + UINT32 Reserved4; +} SMBIOS_TABLE_TYPE31; + +/// +/// System Boot Information - System Boot Status. +/// +typedef enum { + BootInformationStatusNoError = 0x00, + BootInformationStatusNoBootableMedia = 0x01, + BootInformationStatusNormalOSFailedLoading = 0x02, + BootInformationStatusFirmwareDetectedFailure = 0x03, + BootInformationStatusOSDetectedFailure = 0x04, + BootInformationStatusUserRequestedBoot = 0x05, + BootInformationStatusSystemSecurityViolation = 0x06, + BootInformationStatusPreviousRequestedImage = 0x07, + BootInformationStatusWatchdogTimerExpired = 0x08, + BootInformationStatusStartReserved = 0x09, + BootInformationStatusStartOemSpecific = 0x80, + BootInformationStatusStartProductSpecific = 0xC0 +} MISC_BOOT_INFORMATION_STATUS_DATA_TYPE; + +/// +/// System Boot Information (Type 32). +/// +/// The client system firmware, e.g. BIOS, communicates the System Boot Status to the +/// client's Pre-boot Execution Environment (PXE) boot image or OS-present management +/// application via this structure. When used in the PXE environment, for example, +/// this code identifies the reason the PXE was initiated and can be used by boot-image +/// software to further automate an enterprise's PXE sessions. For example, an enterprise +/// could choose to automatically download a hardware-diagnostic image to a client whose +/// reason code indicated either a firmware- or operating system-detected hardware failure. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 Reserved[6]; + UINT8 BootStatus; ///< The enumeration value from MISC_BOOT_INFORMATION_STATUS_DATA_TYPE. +} SMBIOS_TABLE_TYPE32; + +/// +/// 64-bit Memory Error Information (Type 33). +/// +/// This structure describes an error within a Physical Memory Array, +/// when the error address is above 4G (0xFFFFFFFF). +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 ErrorType; ///< The enumeration value from MEMORY_ERROR_TYPE. + UINT8 ErrorGranularity; ///< The enumeration value from MEMORY_ERROR_GRANULARITY. + UINT8 ErrorOperation; ///< The enumeration value from MEMORY_ERROR_OPERATION. + UINT32 VendorSyndrome; + UINT64 MemoryArrayErrorAddress; + UINT64 DeviceErrorAddress; + UINT32 ErrorResolution; +} SMBIOS_TABLE_TYPE33; + +/// +/// Management Device - Type. +/// +typedef enum { + ManagementDeviceTypeOther = 0x01, + ManagementDeviceTypeUnknown = 0x02, + ManagementDeviceTypeLm75 = 0x03, + ManagementDeviceTypeLm78 = 0x04, + ManagementDeviceTypeLm79 = 0x05, + ManagementDeviceTypeLm80 = 0x06, + ManagementDeviceTypeLm81 = 0x07, + ManagementDeviceTypeAdm9240 = 0x08, + ManagementDeviceTypeDs1780 = 0x09, + ManagementDeviceTypeMaxim1617 = 0x0A, + ManagementDeviceTypeGl518Sm = 0x0B, + ManagementDeviceTypeW83781D = 0x0C, + ManagementDeviceTypeHt82H791 = 0x0D +} MISC_MANAGEMENT_DEVICE_TYPE; + +/// +/// Management Device - Address Type. +/// +typedef enum { + ManagementDeviceAddressTypeOther = 0x01, + ManagementDeviceAddressTypeUnknown = 0x02, + ManagementDeviceAddressTypeIOPort = 0x03, + ManagementDeviceAddressTypeMemory = 0x04, + ManagementDeviceAddressTypeSmbus = 0x05 +} MISC_MANAGEMENT_DEVICE_ADDRESS_TYPE; + +/// +/// Management Device (Type 34). +/// +/// The information in this structure defines the attributes of a Management Device. +/// A Management Device might control one or more fans or voltage, current, or temperature +/// probes as defined by one or more Management Device Component structures. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Description; + UINT8 Type; ///< The enumeration value from MISC_MANAGEMENT_DEVICE_TYPE. + UINT32 Address; + UINT8 AddressType; ///< The enumeration value from MISC_MANAGEMENT_DEVICE_ADDRESS_TYPE. +} SMBIOS_TABLE_TYPE34; + +/// +/// Management Device Component (Type 35) +/// +/// This structure associates a cooling device or environmental probe with structures +/// that define the controlling hardware device and (optionally) the component's thresholds. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING Description; + UINT16 ManagementDeviceHandle; + UINT16 ComponentHandle; + UINT16 ThresholdHandle; +} SMBIOS_TABLE_TYPE35; + +/// +/// Management Device Threshold Data (Type 36). +/// +/// The information in this structure defines threshold information for +/// a component (probe or cooling-unit) contained within a Management Device. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT16 LowerThresholdNonCritical; + UINT16 UpperThresholdNonCritical; + UINT16 LowerThresholdCritical; + UINT16 UpperThresholdCritical; + UINT16 LowerThresholdNonRecoverable; + UINT16 UpperThresholdNonRecoverable; +} SMBIOS_TABLE_TYPE36; + +/// +/// Memory Channel Entry. +/// +typedef struct { + UINT8 DeviceLoad; + UINT16 DeviceHandle; +} MEMORY_DEVICE; + +/// +/// Memory Channel - Channel Type. +/// +typedef enum { + MemoryChannelTypeOther = 0x01, + MemoryChannelTypeUnknown = 0x02, + MemoryChannelTypeRambus = 0x03, + MemoryChannelTypeSyncLink = 0x04 +} MEMORY_CHANNEL_TYPE; + +/// +/// Memory Channel (Type 37) +/// +/// The information in this structure provides the correlation between a Memory Channel +/// and its associated Memory Devices. Each device presents one or more loads to the channel. +/// The sum of all device loads cannot exceed the channel's defined maximum. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 ChannelType; + UINT8 MaximumChannelLoad; + UINT8 MemoryDeviceCount; + MEMORY_DEVICE MemoryDevice[1]; +} SMBIOS_TABLE_TYPE37; + +/// +/// IPMI Device Information - BMC Interface Type +/// +typedef enum { + IPMIDeviceInfoInterfaceTypeUnknown = 0x00, + IPMIDeviceInfoInterfaceTypeKCS = 0x01, ///< The Keyboard Controller Style. + IPMIDeviceInfoInterfaceTypeSMIC = 0x02, ///< The Server Management Interface Chip. + IPMIDeviceInfoInterfaceTypeBT = 0x03, ///< The Block Transfer + IPMIDeviceInfoInterfaceTypeSSIF = 0x04 ///< SMBus System Interface +} BMC_INTERFACE_TYPE; + +/// +/// IPMI Device Information (Type 38). +/// +/// The information in this structure defines the attributes of an +/// Intelligent Platform Management Interface (IPMI) Baseboard Management Controller (BMC). +/// +/// The Type 42 structure can also be used to describe a physical management controller +/// host interface and one or more protocols that share that interface. If IPMI is not +/// shared with other protocols, either the Type 38 or Type 42 structures can be used. +/// Providing Type 38 is recommended for backward compatibility. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 InterfaceType; ///< The enumeration value from BMC_INTERFACE_TYPE. + UINT8 IPMISpecificationRevision; + UINT8 I2CSlaveAddress; + UINT8 NVStorageDeviceAddress; + UINT64 BaseAddress; + UINT8 BaseAddressModifier_InterruptInfo; + UINT8 InterruptNumber; +} SMBIOS_TABLE_TYPE38; + +/// +/// System Power Supply - Power Supply Characteristics. +/// +typedef struct { + UINT16 PowerSupplyHotReplaceable:1; + UINT16 PowerSupplyPresent :1; + UINT16 PowerSupplyUnplugged :1; + UINT16 InputVoltageRangeSwitch :4; + UINT16 PowerSupplyStatus :3; + UINT16 PowerSupplyType :4; + UINT16 Reserved :2; +} SYS_POWER_SUPPLY_CHARACTERISTICS; + +/// +/// System Power Supply (Type 39). +/// +/// This structure identifies attributes of a system power supply. One instance +/// of this record is present for each possible power supply in a system. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 PowerUnitGroup; + SMBIOS_TABLE_STRING Location; + SMBIOS_TABLE_STRING DeviceName; + SMBIOS_TABLE_STRING Manufacturer; + SMBIOS_TABLE_STRING SerialNumber; + SMBIOS_TABLE_STRING AssetTagNumber; + SMBIOS_TABLE_STRING ModelPartNumber; + SMBIOS_TABLE_STRING RevisionLevel; + UINT16 MaxPowerCapacity; + SYS_POWER_SUPPLY_CHARACTERISTICS PowerSupplyCharacteristics; + UINT16 InputVoltageProbeHandle; + UINT16 CoolingDeviceHandle; + UINT16 InputCurrentProbeHandle; +} SMBIOS_TABLE_TYPE39; + +/// +/// Additional Information Entry Format. +/// +typedef struct { + UINT8 EntryLength; + UINT16 ReferencedHandle; + UINT8 ReferencedOffset; + SMBIOS_TABLE_STRING EntryString; + UINT8 Value[1]; +} ADDITIONAL_INFORMATION_ENTRY; + +/// +/// Additional Information (Type 40). +/// +/// This structure is intended to provide additional information for handling unspecified +/// enumerated values and interim field updates in another structure. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 NumberOfAdditionalInformationEntries; + ADDITIONAL_INFORMATION_ENTRY AdditionalInfoEntries[1]; +} SMBIOS_TABLE_TYPE40; + +/// +/// Onboard Devices Extended Information - Onboard Device Types. +/// +typedef enum{ + OnBoardDeviceExtendedTypeOther = 0x01, + OnBoardDeviceExtendedTypeUnknown = 0x02, + OnBoardDeviceExtendedTypeVideo = 0x03, + OnBoardDeviceExtendedTypeScsiController = 0x04, + OnBoardDeviceExtendedTypeEthernet = 0x05, + OnBoardDeviceExtendedTypeTokenRing = 0x06, + OnBoardDeviceExtendedTypeSound = 0x07, + OnBoardDeviceExtendedTypePATAController = 0x08, + OnBoardDeviceExtendedTypeSATAController = 0x09, + OnBoardDeviceExtendedTypeSASController = 0x0A +} ONBOARD_DEVICE_EXTENDED_INFO_TYPE; + +/// +/// Onboard Devices Extended Information (Type 41). +/// +/// The information in this structure defines the attributes of devices that +/// are onboard (soldered onto) a system element, usually the baseboard. +/// In general, an entry in this table implies that the BIOS has some level of +/// control over the enabling of the associated device for use by the system. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + SMBIOS_TABLE_STRING ReferenceDesignation; + UINT8 DeviceType; ///< The enumeration value from ONBOARD_DEVICE_EXTENDED_INFO_TYPE + UINT8 DeviceTypeInstance; + UINT16 SegmentGroupNum; + UINT8 BusNum; + UINT8 DevFuncNum; +} SMBIOS_TABLE_TYPE41; + +/// +/// Management Controller Host Interface - Interface Types. +/// 00h - 3Fh: MCTP Host Interfaces +/// +typedef enum{ + MCHostInterfaceTypeNetworkHostInterface = 0x40, + MCHostInterfaceTypeOemDefined = 0xF0 +} MC_HOST_INTERFACE_TYPE; + +/// +/// Management Controller Host Interface - Protocol Types. +/// +typedef enum{ + MCHostInterfaceProtocolTypeIPMI = 0x02, + MCHostInterfaceProtocolTypeMCTP = 0x03, + MCHostInterfaceProtocolTypeRedfishOverIP = 0x04, + MCHostInterfaceProtocolTypeOemDefined = 0xF0 +} MC_HOST_INTERFACE_PROTOCOL_TYPE; + +/// +/// Management Controller Host Interface (Type 42). +/// +/// The information in this structure defines the attributes of a Management +/// Controller Host Interface that is not discoverable by "Plug and Play" mechanisms. +/// +/// Type 42 should be used for management controller host interfaces that use protocols +/// other than IPMI or that use multiple protocols on a single host interface type. +/// +/// This structure should also be provided if IPMI is shared with other protocols +/// over the same interface hardware. If IPMI is not shared with other protocols, +/// either the Type 38 or Type 42 structures can be used. Providing Type 38 is +/// recommended for backward compatibility. The structures are not required to +/// be mutually exclusive. Type 38 and Type 42 structures may be implemented +/// simultaneously to provide backward compatibility with IPMI applications or drivers +/// that do not yet recognize the Type 42 structure. +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 InterfaceType; ///< The enumeration value from MC_HOST_INTERFACE_TYPE + UINT8 InterfaceTypeSpecificDataLength; + UINT8 InterfaceTypeSpecificData[4]; ///< This field has a minimum of four bytes +} SMBIOS_TABLE_TYPE42; + +/// +/// TPM Device (Type 43). +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; + UINT8 VendorID[4]; + UINT8 MajorSpecVersion; + UINT8 MinorSpecVersion; + UINT32 FirmwareVersion1; + UINT32 FirmwareVersion2; + SMBIOS_TABLE_STRING Description; + UINT64 Characteristics; + UINT32 OemDefined; +} SMBIOS_TABLE_TYPE43; + +/// +/// Inactive (Type 126) +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; +} SMBIOS_TABLE_TYPE126; + +/// +/// End-of-Table (Type 127) +/// +typedef struct { + SMBIOS_STRUCTURE Hdr; +} SMBIOS_TABLE_TYPE127; + +/// +/// Union of all the possible SMBIOS record types. +/// +typedef union { + SMBIOS_STRUCTURE *Hdr; + SMBIOS_TABLE_TYPE0 *Type0; + SMBIOS_TABLE_TYPE1 *Type1; + SMBIOS_TABLE_TYPE2 *Type2; + SMBIOS_TABLE_TYPE3 *Type3; + SMBIOS_TABLE_TYPE4 *Type4; + SMBIOS_TABLE_TYPE5 *Type5; + SMBIOS_TABLE_TYPE6 *Type6; + SMBIOS_TABLE_TYPE7 *Type7; + SMBIOS_TABLE_TYPE8 *Type8; + SMBIOS_TABLE_TYPE9 *Type9; + SMBIOS_TABLE_TYPE10 *Type10; + SMBIOS_TABLE_TYPE11 *Type11; + SMBIOS_TABLE_TYPE12 *Type12; + SMBIOS_TABLE_TYPE13 *Type13; + SMBIOS_TABLE_TYPE14 *Type14; + SMBIOS_TABLE_TYPE15 *Type15; + SMBIOS_TABLE_TYPE16 *Type16; + SMBIOS_TABLE_TYPE17 *Type17; + SMBIOS_TABLE_TYPE18 *Type18; + SMBIOS_TABLE_TYPE19 *Type19; + SMBIOS_TABLE_TYPE20 *Type20; + SMBIOS_TABLE_TYPE21 *Type21; + SMBIOS_TABLE_TYPE22 *Type22; + SMBIOS_TABLE_TYPE23 *Type23; + SMBIOS_TABLE_TYPE24 *Type24; + SMBIOS_TABLE_TYPE25 *Type25; + SMBIOS_TABLE_TYPE26 *Type26; + SMBIOS_TABLE_TYPE27 *Type27; + SMBIOS_TABLE_TYPE28 *Type28; + SMBIOS_TABLE_TYPE29 *Type29; + SMBIOS_TABLE_TYPE30 *Type30; + SMBIOS_TABLE_TYPE31 *Type31; + SMBIOS_TABLE_TYPE32 *Type32; + SMBIOS_TABLE_TYPE33 *Type33; + SMBIOS_TABLE_TYPE34 *Type34; + SMBIOS_TABLE_TYPE35 *Type35; + SMBIOS_TABLE_TYPE36 *Type36; + SMBIOS_TABLE_TYPE37 *Type37; + SMBIOS_TABLE_TYPE38 *Type38; + SMBIOS_TABLE_TYPE39 *Type39; + SMBIOS_TABLE_TYPE40 *Type40; + SMBIOS_TABLE_TYPE41 *Type41; + SMBIOS_TABLE_TYPE42 *Type42; + SMBIOS_TABLE_TYPE43 *Type43; + SMBIOS_TABLE_TYPE126 *Type126; + SMBIOS_TABLE_TYPE127 *Type127; + UINT8 *Raw; +} SMBIOS_STRUCTURE_POINTER; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBus.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBus.h new file mode 100644 index 0000000..950c40f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/SmBus.h @@ -0,0 +1,81 @@ +/** @file + This file declares the SMBus definitions defined in SmBus Specifciation V2.0 + and defined in PI1.0 specification volume 5. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMBUS_H_ +#define _SMBUS_H_ + + +/// +/// UDID of SMBUS device. +/// +typedef struct { + UINT32 VendorSpecificId; + UINT16 SubsystemDeviceId; + UINT16 SubsystemVendorId; + UINT16 Interface; + UINT16 DeviceId; + UINT16 VendorId; + UINT8 VendorRevision; + UINT8 DeviceCapabilities; +} EFI_SMBUS_UDID; + +/// +/// Smbus Device Address +/// +typedef struct { + /// + /// The SMBUS hardware address to which the SMBUS device is preassigned or allocated. + /// + UINTN SmbusDeviceAddress : 7; +} EFI_SMBUS_DEVICE_ADDRESS; + +typedef struct { + /// + /// The SMBUS hardware address to which the SMBUS device is preassigned or + /// allocated. Type EFI_SMBUS_DEVICE_ADDRESS is defined in EFI_PEI_SMBUS2_PPI.Execute(). + /// + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + /// + /// The SMBUS Unique Device Identifier (UDID) as defined in EFI_SMBUS_UDID. + /// Type EFI_SMBUS_UDID is defined in EFI_PEI_SMBUS2_PPI.ArpDevice(). + /// + EFI_SMBUS_UDID SmbusDeviceUdid; +} EFI_SMBUS_DEVICE_MAP; + +/// +/// Smbus Operations +/// +typedef enum _EFI_SMBUS_OPERATION { + EfiSmbusQuickRead, + EfiSmbusQuickWrite, + EfiSmbusReceiveByte, + EfiSmbusSendByte, + EfiSmbusReadByte, + EfiSmbusWriteByte, + EfiSmbusReadWord, + EfiSmbusWriteWord, + EfiSmbusReadBlock, + EfiSmbusWriteBlock, + EfiSmbusProcessCall, + EfiSmbusBWBRProcessCall +} EFI_SMBUS_OPERATION; + +/// +/// EFI_SMBUS_DEVICE_COMMAND +/// +typedef UINTN EFI_SMBUS_DEVICE_COMMAND; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgPhysicalPresence.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgPhysicalPresence.h new file mode 100644 index 0000000..192e5ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgPhysicalPresence.h @@ -0,0 +1,129 @@ +/** @file + TCG Physical Presence definition. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG_PHYSICAL_PRESENCE_H_ +#define _TCG_PHYSICAL_PRESENCE_H_ + +// +// TCG PP definition for physical presence ACPI function +// +#define TCG_ACPI_FUNCTION_GET_PHYSICAL_PRESENCE_INTERFACE_VERSION 1 +#define TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS 2 +#define TCG_ACPI_FUNCTION_GET_PENDING_REQUEST_BY_OS 3 +#define TCG_ACPI_FUNCTION_GET_PLATFORM_ACTION_TO_TRANSITION_TO_BIOS 4 +#define TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS 5 +#define TCG_ACPI_FUNCTION_SUBMIT_PREFERRED_USER_LANGUAGE 6 +#define TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2 7 +#define TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST 8 + +// +// TCG PP definition for TPM Operation Response to OS Environment +// +#define TCG_PP_OPERATION_RESPONSE_SUCCESS 0x0 +#define TCG_PP_OPERATION_RESPONSE_USER_ABORT 0xFFFFFFF0 +#define TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE 0xFFFFFFF1 + +// +// TCG PP definition of return code for Return TPM Operation Response to OS Environment +// +#define TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS 0 +#define TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE 1 + +// +// TCG PP definition of return code for Submit TPM Request to Pre-OS Environment +// and Submit TPM Request to Pre-OS Environment 2 +// +#define TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS 0 +#define TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED 1 +#define TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE 2 +#define TCG_PP_SUBMIT_REQUEST_TO_PREOS_BLOCKED_BY_BIOS_SETTINGS 3 + +// +// TCG PP definition of return code for Get User Confirmation Status for Operation +// +#define TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED 0 +#define TCG_PP_GET_USER_CONFIRMATION_BIOS_ONLY 1 +#define TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION 2 +#define TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED 3 +#define TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED 4 + +// +// TCG PP definition of physical presence operation actions for TPM12 +// +#define TCG_PHYSICAL_PRESENCE_NO_ACTION 0 +#define TCG_PHYSICAL_PRESENCE_ENABLE 1 +#define TCG_PHYSICAL_PRESENCE_DISABLE 2 +#define TCG_PHYSICAL_PRESENCE_ACTIVATE 3 +#define TCG_PHYSICAL_PRESENCE_DEACTIVATE 4 +#define TCG_PHYSICAL_PRESENCE_CLEAR 5 +#define TCG_PHYSICAL_PRESENCE_ENABLE_ACTIVATE 6 +#define TCG_PHYSICAL_PRESENCE_DEACTIVATE_DISABLE 7 +#define TCG_PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE 8 +#define TCG_PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE 9 +#define TCG_PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE 10 +#define TCG_PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE 11 +#define TCG_PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE 12 +#define TCG_PHYSICAL_PRESENCE_SET_OPERATOR_AUTH 13 +#define TCG_PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE 14 +#define TCG_PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE 15 +#define TCG_PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE 16 +#define TCG_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE 17 +#define TCG_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE 18 +#define TCG_PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE 19 +#define TCG_PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE 20 +#define TCG_PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR 21 +#define TCG_PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE 22 + +#define TCG_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION 128 + +// +// TCG PP definition of physical presence operation actions for TPM2 +// +#define TCG2_PHYSICAL_PRESENCE_NO_ACTION 0 +#define TCG2_PHYSICAL_PRESENCE_ENABLE 1 +#define TCG2_PHYSICAL_PRESENCE_DISABLE 2 +#define TCG2_PHYSICAL_PRESENCE_CLEAR 5 +#define TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR 14 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE 17 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE 18 +#define TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2 21 +#define TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3 22 +#define TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS 23 +#define TCG2_PHYSICAL_PRESENCE_CHANGE_EPS 24 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CHANGE_PCRS_FALSE 25 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CHANGE_PCRS_TRUE 26 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_TURN_ON_FALSE 27 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_TURN_ON_TRUE 28 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_TURN_OFF_FALSE 29 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_TURN_OFF_TRUE 30 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CHANGE_EPS_FALSE 31 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CHANGE_EPS_TRUE 32 +#define TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS 33 +#define TCG2_PHYSICAL_PRESENCE_DISABLE_ENDORSEMENT_ENABLE_STORAGE_HIERARCHY 34 +#define TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX 34 + +// +// TCG PP definition of physical presence operation actions for storage management +// +#define TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN 96 +#define TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID 96 +#define TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID 97 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE 98 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE 99 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE 100 +#define TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE 101 + +#define TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION 128 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageCore.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageCore.h new file mode 100644 index 0000000..2e083c8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageCore.h @@ -0,0 +1,401 @@ +/** @file + TCG defined values and structures. + + (TCG Storage Architecture Core Specification, Version 2.01, Revision 1.00, + https://trustedcomputinggroup.org/tcg-storage-architecture-core-specification/) + + Check http://trustedcomputinggroup.org for latest specification updates. + +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG_STORAGE_CORE_H_ +#define _TCG_STORAGE_CORE_H_ + +#include + +#pragma pack(1) + +/// UID in host native byte order +typedef UINT64 TCG_UID; + +#define TCG_TO_UID(b0, b1, b2, b3, b4, b5, b6, b7) (TCG_UID)( \ + (UINT64)(b0) | \ + ((UINT64)(b1) << 8) | \ + ((UINT64)(b2) << 16) | \ + ((UINT64)(b3) << 24) | \ + ((UINT64)(b4) << 32) | \ + ((UINT64)(b5) << 40) | \ + ((UINT64)(b6) << 48) | \ + ((UINT64)(b7) << 56)) + +typedef struct { + UINT32 ReservedBE; + UINT16 ComIDBE; + UINT16 ComIDExtensionBE; + UINT32 OutstandingDataBE; + UINT32 MinTransferBE; + UINT32 LengthBE; + UINT8 Payload[0]; +} TCG_COM_PACKET; + +typedef struct { + UINT32 TperSessionNumberBE; + UINT32 HostSessionNumberBE; + UINT32 SequenceNumberBE; + UINT16 ReservedBE; + UINT16 AckTypeBE; + UINT32 AcknowledgementBE; + UINT32 LengthBE; + UINT8 Payload[0]; +} TCG_PACKET; + +#define TCG_SUBPACKET_ALIGNMENT 4 // 4-byte alignment per spec + +typedef struct { + UINT8 ReservedBE[6]; + UINT16 KindBE; + UINT32 LengthBE; + UINT8 Payload[0]; +} TCG_SUB_PACKET; + +#define SUBPACKET_KIND_DATA 0x0000 +#define SUBPACKET_KIND_CREDIT_CONTROL 0x8001 + +#define TCG_ATOM_TYPE_INTEGER 0x0 +#define TCG_ATOM_TYPE_BYTE 0x1 +typedef struct { + UINT8 Data : 6; + UINT8 Sign : 1; + UINT8 IsZero : 1; +} TCG_TINY_ATOM_BITS; + +typedef union { + UINT8 Raw; + TCG_TINY_ATOM_BITS TinyAtomBits; +} TCG_SIMPLE_TOKEN_TINY_ATOM; + + +typedef struct { + UINT8 Length : 4; + UINT8 SignOrCont : 1; + UINT8 ByteOrInt : 1; + UINT8 IsZero : 1; + UINT8 IsOne : 1; +} TCG_SHORT_ATOM_BITS; + +typedef union { + UINT8 RawHeader; + TCG_SHORT_ATOM_BITS ShortAtomBits; +} TCG_SIMPLE_TOKEN_SHORT_ATOM; + + +#define TCG_MEDIUM_ATOM_LENGTH_HIGH_SHIFT 0x8 +#define TCG_MEDIUM_ATOM_LENGTH_HIGH_MASK 0x7 + +typedef struct { + UINT8 LengthHigh : 3; + UINT8 SignOrCont : 1; + UINT8 ByteOrInt : 1; + UINT8 IsZero : 1; + UINT8 IsOne1 : 1; + UINT8 IsOne2 : 1; + UINT8 LengthLow; +} TCG_MEDIUM_ATOM_BITS; + +typedef union { + UINT16 RawHeader; + TCG_MEDIUM_ATOM_BITS MediumAtomBits; +} TCG_SIMPLE_TOKEN_MEDIUM_ATOM; + + +#define TCG_LONG_ATOM_LENGTH_HIGH_SHIFT 16 +#define TCG_LONG_ATOM_LENGTH_MID_SHIFT 8 + +typedef struct { + UINT8 SignOrCont : 1; + UINT8 ByteOrInt : 1; + UINT8 Reserved : 2; + UINT8 IsZero : 1; + UINT8 IsOne1 : 1; + UINT8 IsOne2 : 1; + UINT8 IsOne3 : 1; + UINT8 LengthHigh; + UINT8 LengthMid; + UINT8 LengthLow; +} TCG_LONG_ATOM_BITS; + +typedef union { + UINT32 RawHeader; + TCG_LONG_ATOM_BITS LongAtomBits; +} TCG_SIMPLE_TOKEN_LONG_ATOM; + + +// TCG Core Spec v2 - Table 04 - Token Types +typedef enum { + TcgTokenTypeReserved, + TcgTokenTypeTinyAtom, + TcgTokenTypeShortAtom, + TcgTokenTypeMediumAtom, + TcgTokenTypeLongAtom, + TcgTokenTypeStartList, + TcgTokenTypeEndList, + TcgTokenTypeStartName, + TcgTokenTypeEndName, + TcgTokenTypeCall, + TcgTokenTypeEndOfData, + TcgTokenTypeEndOfSession, + TcgTokenTypeStartTransaction, + TcgTokenTypeEndTransaction, + TcgTokenTypeEmptyAtom, +} TCG_TOKEN_TYPE; + +#pragma pack() + +#define TCG_TOKEN_SHORTATOM_MAX_BYTE_SIZE 0x0F +#define TCG_TOKEN_MEDIUMATOM_MAX_BYTE_SIZE 0x7FF +#define TCG_TOKEN_LONGATOM_MAX_BYTE_SIZE 0xFFFFFF + +#define TCG_TOKEN_TINYATOM_UNSIGNED_MAX_VALUE 0x3F +#define TCG_TOKEN_TINYATOM_SIGNED_MAX_VALUE 0x1F +#define TCG_TOKEN_TINYATOM_SIGNED_MIN_VALUE -32 + +// TOKEN TYPES +#define TCG_TOKEN_TINYATOM 0x00 +#define TCG_TOKEN_TINYSIGNEDATOM 0x40 +#define TCG_TOKEN_SHORTATOM 0x80 +#define TCG_TOKEN_SHORTSIGNEDATOM 0x90 +#define TCG_TOKEN_SHORTBYTESATOM 0xA0 +#define TCG_TOKEN_MEDIUMATOM 0xC0 +#define TCG_TOKEN_MEDIUMSIGNEDATOM 0xC8 +#define TCG_TOKEN_MEDIUMBYTESATOM 0xD0 +#define TCG_TOKEN_LONGATOM 0xE0 +#define TCG_TOKEN_LONGSIGNEDATOM 0xE1 +#define TCG_TOKEN_LONGBYTESATOM 0xE2 +#define TCG_TOKEN_STARTLIST 0xF0 +#define TCG_TOKEN_ENDLIST 0xF1 +#define TCG_TOKEN_STARTNAME 0xF2 +#define TCG_TOKEN_ENDNAME 0xF3 +// 0xF4 - 0xF7 TCG Reserved +#define TCG_TOKEN_CALL 0xF8 +#define TCG_TOKEN_ENDDATA 0xF9 +#define TCG_TOKEN_ENDSESSION 0xFA +#define TCG_TOKEN_STARTTRANSACTION 0xFB +#define TCG_TOKEN_ENDTRANSACTION 0xFC +// 0xFD - 0xFE TCG Reserved +#define TCG_TOKEN_EMPTY 0xFF + +// CELLBLOCK reserved Names +#define TCG_CELL_BLOCK_TABLE_NAME (UINT8)0x00 +#define TCG_CELL_BLOCK_START_ROW_NAME (UINT8)0x01 +#define TCG_CELL_BLOCK_END_ROW_NAME (UINT8)0x02 +#define TCG_CELL_BLOCK_START_COLUMN_NAME (UINT8)0x03 +#define TCG_CELL_BLOCK_END_COLUMN_NAME (UINT8)0x04 + +// METHOD STATUS CODES +#define TCG_METHOD_STATUS_CODE_SUCCESS 0x00 +#define TCG_METHOD_STATUS_CODE_NOT_AUTHORIZED 0x01 +#define TCG_METHOD_STATUS_CODE_OBSOLETE 0x02 +#define TCG_METHOD_STATUS_CODE_SP_BUSY 0x03 +#define TCG_METHOD_STATUS_CODE_SP_FAILED 0x04 +#define TCG_METHOD_STATUS_CODE_SP_DISABLED 0x05 +#define TCG_METHOD_STATUS_CODE_SP_FROZEN 0x06 +#define TCG_METHOD_STATUS_CODE_NO_SESSIONS_AVAILABLE 0x07 +#define TCG_METHOD_STATUS_CODE_UNIQUENESS_CONFLICT 0x08 +#define TCG_METHOD_STATUS_CODE_INSUFFICIENT_SPACE 0x09 +#define TCG_METHOD_STATUS_CODE_INSUFFICIENT_ROWS 0x0A +#define TCG_METHOD_STATUS_CODE_INVALID_PARAMETER 0x0C +#define TCG_METHOD_STATUS_CODE_OBSOLETE2 0x0D +#define TCG_METHOD_STATUS_CODE_OBSOLETE3 0x0E +#define TCG_METHOD_STATUS_CODE_TPER_MALFUNCTION 0x0F +#define TCG_METHOD_STATUS_CODE_TRANSACTION_FAILURE 0x10 +#define TCG_METHOD_STATUS_CODE_RESPONSE_OVERFLOW 0x11 +#define TCG_METHOD_STATUS_CODE_AUTHORITY_LOCKED_OUT 0x12 +#define TCG_METHOD_STATUS_CODE_FAIL 0x3F + + +// Feature Codes +#define TCG_FEATURE_INVALID (UINT16)0x0000 +#define TCG_FEATURE_TPER (UINT16)0x0001 +#define TCG_FEATURE_LOCKING (UINT16)0x0002 +#define TCG_FEATURE_GEOMETRY_REPORTING (UINT16)0x0003 +#define TCG_FEATURE_SINGLE_USER_MODE (UINT16)0x0201 +#define TCG_FEATURE_DATASTORE_TABLE (UINT16)0x0202 +#define TCG_FEATURE_OPAL_SSC_V1_0_0 (UINT16)0x0200 +#define TCG_FEATURE_OPAL_SSC_V2_0_0 (UINT16)0x0203 +#define TCG_FEATURE_OPAL_SSC_LITE (UINT16)0x0301 +#define TCG_FEATURE_PYRITE_SSC (UINT16)0x0302 +#define TCG_FEATURE_PYRITE_SSC_V2_0_0 (UINT16)0x0303 +#define TCG_FEATURE_BLOCK_SID (UINT16)0x0402 +#define TCG_FEATURE_DATA_REMOVAL (UINT16)0x0404 + +// ACE Expression values +#define TCG_ACE_EXPRESSION_AND 0x0 +#define TCG_ACE_EXPRESSION_OR 0x1 + +/**************************************************************************** +TRUSTED RECEIVE - supported security protocols list (SP_Specific = 0000h) +ATA 8 Rev6a Table 68 7.57.6.2 +****************************************************************************/ +// Security Protocol IDs +#define TCG_SECURITY_PROTOCOL_INFO 0x00 +#define TCG_OPAL_SECURITY_PROTOCOL_1 0x01 +#define TCG_OPAL_SECURITY_PROTOCOL_2 0x02 +#define TCG_SECURITY_PROTOCOL_TCG3 0x03 +#define TCG_SECURITY_PROTOCOL_TCG4 0x04 +#define TCG_SECURITY_PROTOCOL_TCG5 0x05 +#define TCG_SECURITY_PROTOCOL_TCG6 0x06 +#define TCG_SECURITY_PROTOCOL_CBCS 0x07 +#define TCG_SECURITY_PROTOCOL_TAPE_DATA 0x20 +#define TCG_SECURITY_PROTOCOL_DATA_ENCRYPT_CONFIG 0x21 +#define TCG_SECURITY_PROTOCOL_SA_CREATION_CAPS 0x40 +#define TCG_SECURITY_PROTOCOL_IKEV2_SCSI 0x41 +#define TCG_SECURITY_PROTOCOL_JEDEC_UFS 0xEC +#define TCG_SECURITY_PROTOCOL_SDCARD_SECURITY 0xED +#define TCG_SECURITY_PROTOCOL_IEEE_1667 0xEE +#define TCG_SECURITY_PROTOCOL_ATA_DEVICE_SERVER_PASS 0xEF + +// Security Protocol Specific IDs +#define TCG_SP_SPECIFIC_PROTOCOL_LIST 0x0000 +#define TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY 0x0001 + +#define TCG_RESERVED_COMID 0x0000 + +// Defined in TCG Storage Feature Set:Block SID Authentication spec, +// ComId used for BlockSid command is hardcode 0x0005. +#define TCG_BLOCKSID_COMID 0x0005 + +#pragma pack(1) +typedef struct { + UINT8 Reserved[6]; + UINT16 ListLength_BE; // 6 - 7 + UINT8 List[504]; // 8... +} TCG_SUPPORTED_SECURITY_PROTOCOLS; + + +// Level 0 Discovery +typedef struct { + UINT32 LengthBE; // number of valid bytes in discovery response, not including length field + UINT16 VerMajorBE; + UINT16 VerMinorBE; + UINT8 Reserved[8]; + UINT8 VendorUnique[32]; +} TCG_LEVEL0_DISCOVERY_HEADER; + +typedef struct _TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER { + UINT16 FeatureCode_BE; + UINT8 Reserved : 4; + UINT8 Version : 4; + UINT8 Length; // length of feature dependent data in bytes +} TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER; + + +typedef struct { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT8 LockingSupported : 1; + UINT8 LockingEnabled : 1; // means the locking security provider (SP) is enabled + UINT8 Locked : 1; // means at least 1 locking range is enabled + UINT8 MediaEncryption : 1; + UINT8 MbrEnabled : 1; + UINT8 MbrDone : 1; + UINT8 Reserved : 2; + UINT8 Reserved515[11]; +} TCG_LOCKING_FEATURE_DESCRIPTOR; + +typedef struct { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT8 SIDValueState : 1; + UINT8 SIDBlockedState : 1; + UINT8 Reserved4 : 6; + UINT8 HardwareReset : 1; + UINT8 Reserved5 : 7; + UINT8 Reserved615[10]; +} TCG_BLOCK_SID_FEATURE_DESCRIPTOR; + + +typedef struct { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT8 SyncSupported : 1; + UINT8 AsyncSupported : 1; + UINT8 AckNakSupported : 1; + UINT8 BufferMgmtSupported : 1; + UINT8 StreamingSupported : 1; + UINT8 Reserved4b5 : 1; + UINT8 ComIdMgmtSupported : 1; + UINT8 Reserved4b7 : 1; + UINT8 Reserved515[11]; +} TCG_TPER_FEATURE_DESCRIPTOR; + +#pragma pack() + +// Special Purpose UIDs +#define TCG_UID_NULL TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) +#define TCG_UID_THIS_SP TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01) +#define TCG_UID_SMUID TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF) + +// Session Manager Method UIDS +#define TCG_UID_SM_PROPERTIES TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01) +#define TCG_UID_SM_START_SESSION TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x02) +#define TCG_UID_SM_SYNC_SESSION TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03) +#define TCG_UID_SM_START_TRUSTED_SESSION TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x04) +#define TCG_UID_SM_SYNC_TRUSTED_SESSION TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x05) +#define TCG_UID_SM_CLOSE_SESSION TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x06) + +// MethodID UIDs +#define TCG_UID_METHOD_DELETE_SP TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01) +#define TCG_UID_METHOD_CREATE_TABLE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02) +#define TCG_UID_METHOD_DELETE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03) +#define TCG_UID_METHOD_CREATE_ROW TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04) +#define TCG_UID_METHOD_DELETE_ROW TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05) +#define TCG_UID_METHOD_NEXT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08) +#define TCG_UID_METHOD_GET_FREE_SPACE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09) +#define TCG_UID_METHOD_GET_FREE_ROWS TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A) +#define TCG_UID_METHOD_DELETE_METHOD TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0B) +#define TCG_UID_METHOD_GET_ACL TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0D) +#define TCG_UID_METHOD_ADD_ACE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E) +#define TCG_UID_METHOD_REMOVE_ACE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0F) +#define TCG_UID_METHOD_GEN_KEY TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10) +#define TCG_UID_METHOD_GET_PACKAGE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12) +#define TCG_UID_METHOD_SET_PACKAGE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13) +#define TCG_UID_METHOD_GET TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16) +#define TCG_UID_METHOD_SET TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17) +#define TCG_UID_METHOD_AUTHENTICATE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1C) +#define TCG_UID_METHOD_ISSUE_SP TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01) +#define TCG_UID_METHOD_GET_CLOCK TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x01) +#define TCG_UID_METHOD_RESET_CLOCK TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x02) +#define TCG_UID_METHOD_SET_CLOCK_HIGH TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x03) +#define TCG_UID_METHOD_SET_LAG_HIGH TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x04) +#define TCG_UID_METHOD_SET_CLOCK_LOW TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x05) +#define TCG_UID_METHOD_SET_LAG_LOW TCG_TO_UID(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x06) +#define TCG_UID_METHOD_INCREMENT_COUNTER TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x07) +#define TCG_UID_METHOD_RANDOM TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01) +#define TCG_UID_METHOD_SALT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x02) +#define TCG_UID_METHOD_DECRYPT_INIT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x03) +#define TCG_UID_METHOD_DECRYPT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x04) +#define TCG_UID_METHOD_DECRYPT_FINALIZE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x05) +#define TCG_UID_METHOD_ENCRYPT_INIT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x06) +#define TCG_UID_METHOD_ENCRYPT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x07) +#define TCG_UID_METHOD_ENCRYPT_FINALIZE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x08) +#define TCG_UID_METHOD_HMAC_INIT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x09) +#define TCG_UID_METHOD_HMAC TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x0A) +#define TCG_UID_METHOD_HMAC_FINALIZE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x0B) +#define TCG_UID_METHOD_HASH_INIT TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x0C) +#define TCG_UID_METHOD_HASH TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x0D) +#define TCG_UID_METHOD_HASH_FINALIZE TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x0E) +#define TCG_UID_METHOD_SIGN TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x0F) +#define TCG_UID_METHOD_VERIFY TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x10) +#define TCG_UID_METHOD_XOR TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x11) +#define TCG_UID_METHOD_ADD_LOG TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0A, 0x01) +#define TCG_UID_METHOD_CREATE_LOG TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0A, 0x02) +#define TCG_UID_METHOD_CLEAR_LOG TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0A, 0x03) +#define TCG_UID_METHOD_FLUSH_LOG TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0A, 0x04) + +#endif // TCG_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageOpal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageOpal.h new file mode 100644 index 0000000..e8a5281 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcgStorageOpal.h @@ -0,0 +1,249 @@ +/** @file + Opal Specification defined values and structures. + + (TCG Storage Architecture Core Specification, Version 2.01, Revision 1.00, + https://trustedcomputinggroup.org/tcg-storage-architecture-core-specification/ + + Storage Work Group Storage Security Subsystem Class: Pyrite, Version 1.00 Final, Revision 1.00, + https://trustedcomputinggroup.org/tcg-storage-security-subsystem-class-pyrite/ + + Storage Work Group Storage Security Subsystem Class: Opal, Version 2.01 Final, Revision 1.00, + https://trustedcomputinggroup.org/storage-work-group-storage-security-subsystem-class-opal/ + + TCG Storage Security Subsystem Class: Opalite Version 1.00 Revision 1.00, + https://trustedcomputinggroup.org/tcg-storage-security-subsystem-class-opalite/) + + Check http://trustedcomputinggroup.org for latest specification updates. + +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG_STORAGE_OPAL_H_ +#define _TCG_STORAGE_OPAL_H_ + +#include + +#define OPAL_UID_ADMIN_SP TCG_TO_UID(0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x01) +#define OPAL_UID_ADMIN_SP_C_PIN_MSID TCG_TO_UID(0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x84, 0x02) +#define OPAL_UID_ADMIN_SP_C_PIN_SID TCG_TO_UID(0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01) +#define OPAL_UID_LOCKING_SP TCG_TO_UID(0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x02) + +// ADMIN_SP +// Authorities +#define OPAL_ADMIN_SP_ANYBODY_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01) +#define OPAL_ADMIN_SP_ADMINS_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02) +#define OPAL_ADMIN_SP_MAKERS_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03) +#define OPAL_ADMIN_SP_SID_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06) +#define OPAL_ADMIN_SP_ADMIN1_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x01) +#define OPAL_ADMIN_SP_PSID_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0xFF, 0x01) + +#define OPAL_ADMIN_SP_ACTIVATE_METHOD TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x03) +#define OPAL_ADMIN_SP_REVERT_METHOD TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x02) + +// ADMIN_SP +// Data Removal mechanism +#define OPAL_UID_ADMIN_SP_DATA_REMOVAL_MECHANISM TCG_TO_UID(0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x00, 0x01) + +// LOCKING SP +// Authorities +#define OPAL_LOCKING_SP_ANYBODY_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01) +#define OPAL_LOCKING_SP_ADMINS_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02) +#define OPAL_LOCKING_SP_ADMIN1_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01) +#define OPAL_LOCKING_SP_USERS_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x00) +#define OPAL_LOCKING_SP_USER1_AUTHORITY TCG_TO_UID(0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x01) + +#define OPAL_LOCKING_SP_REVERTSP_METHOD TCG_TO_UID(0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11) + +// C_PIN Table Rows +#define OPAL_LOCKING_SP_C_PIN_ADMIN1 TCG_TO_UID( 0x00, 0x00, 0x00, 0x0B, 0x00, 0x01, 0x00, 0x01 ) +#define OPAL_LOCKING_SP_C_PIN_USER1 TCG_TO_UID( 0x00, 0x00, 0x00, 0x0B, 0x00, 0x03, 0x00, 0x01 ) + +// Locking Table +#define OPAL_LOCKING_SP_LOCKING_GLOBALRANGE TCG_TO_UID( 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 ) +#define OPAL_LOCKING_SP_LOCKING_RANGE1 TCG_TO_UID( 0x00, 0x00, 0x08, 0x02, 0x00, 0x03, 0x00, 0x01 ) + + +// LOCKING SP ACE Table Preconfiguration +#define OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL TCG_TO_UID( 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xD0, 0x00 ) +#define OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_RDLOCKED TCG_TO_UID( 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE0, 0x00 ) +#define OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_WRLOCKED TCG_TO_UID( 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xE8, 0x00 ) + +#define OPAL_LOCKING_SP_ACE_K_AES_256_GLOBALRANGE_GENKEY TCG_TO_UID( 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xB8, 0x00 ) +#define OPAL_LOCKING_SP_ACE_K_AES_128_GLOBALRANGE_GENKEY TCG_TO_UID( 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0xB0, 0x00 ) + + +// LOCKING SP LockingInfo Table Preconfiguration +#define OPAL_LOCKING_SP_LOCKING_INFO TCG_TO_UID( 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x01 ) + +#define OPAL_LOCKING_SP_LOCKINGINFO_ALIGNMENTREQUIRED_COL 0x7 +#define OPAL_LOCKING_SP_LOCKINGINFO_LOGICALBLOCKSIZE_COL 0x8 +#define OPAL_LOCKING_SP_LOCKINGINFO_ALIGNMENTGRANULARITY_COL 0x9 +#define OPAL_LOCKING_SP_LOCKINGINFO_LOWESTALIGNEDLBA_COL 0xA + +// K_AES_256 Table Preconfiguration +#define OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY TCG_TO_UID( 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x01 ) + +// K_AES_128 Table Preconfiguration +#define OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY TCG_TO_UID( 0x00, 0x00, 0x08, 0x05, 0x00, 0x00, 0x00, 0x01 ) + +// Minimum Properties that an Opal Compliant SD Shall support +#define OPAL_MIN_MAX_COM_PACKET_SIZE 2048 +#define OPAL_MIN_MAX_REPONSE_COM_PACKET_SIZE 2048 +#define OPAL_MIN_MAX_PACKET_SIZE 2028 +#define OPAL_MIN_MAX_IND_TOKEN_SIZE 1992 +#define OPAL_MIN_MAX_PACKETS 1 +#define OPAL_MIN_MAX_SUBPACKETS 1 +#define OPAL_MIN_MAX_METHODS 1 +#define OPAL_MIN_MAX_SESSIONS 1 +#define OPAL_MIN_MAX_AUTHENTICATIONS 2 +#define OPAL_MIN_MAX_TRANSACTION_LIMIT 1 + +#define OPAL_ADMIN_SP_PIN_COL 3 +#define OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL 5 +#define OPAL_RANDOM_METHOD_MAX_COUNT_SIZE 32 + +// Data Removal Mechanism column. +#define OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL 1 + +// +// Supported Data Removal Mechanism. +// Detail see Pyrite SSC v2 spec. +// +typedef enum { + OverwriteDataErase = 0, + BlockErase, + CryptoErase, + Unmap, + ResetWritePointers, + VendorSpecificErase, + ResearvedMechanism +} SUPPORTED_DATA_REMOVAL_MECHANISM; + +#pragma pack(1) + +typedef struct _OPAL_GEOMETRY_REPORTING_FEATURE { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT8 Reserved[8]; + UINT32 LogicalBlockSizeBE; + UINT64 AlignmentGranularityBE; + UINT64 LowestAlignedLBABE; +} OPAL_GEOMETRY_REPORTING_FEATURE; + +typedef struct _OPAL_SINGLE_USER_MODE_FEATURE { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT32 NumLockingObjectsSupportedBE; + UINT8 Any : 1; + UINT8 All : 1; + UINT8 Policy : 1; + UINT8 Reserved : 5; + UINT8 Reserved2[7]; +} OPAL_SINGLE_USER_MODE_FEATURE; + +typedef struct _OPAL_DATASTORE_TABLE_FEATURE { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT16 Reserved; + UINT16 MaxNumTablesBE; + UINT32 MaxTotalSizeBE; + UINT32 SizeAlignmentBE; +} OPAL_DATASTORE_TABLE_FEATURE; + +typedef struct _OPAL_SSCV1_FEATURE_DESCRIPTOR { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT16 BaseComdIdBE; + UINT16 NumComIdsBE; + UINT8 RangeCrossing : 1; + UINT8 Reserved : 7; + UINT8 Future[11]; +} OPAL_SSCV1_FEATURE_DESCRIPTOR; + +typedef struct _OPAL_SSCV2_FEATURE_DESCRIPTOR { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT16 BaseComdIdBE; + UINT16 NumComIdsBE; + UINT8 Reserved; + UINT16 NumLockingSpAdminAuthoritiesSupportedBE; + UINT16 NumLockingSpUserAuthoritiesSupportedBE; + UINT8 InitialCPINSIDPIN; + UINT8 CPINSIDPINRevertBehavior; + UINT8 Future[5]; +} OPAL_SSCV2_FEATURE_DESCRIPTOR; + +typedef struct _OPAL_SSCLITE_FEATURE_DESCRIPTOR { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT16 BaseComdIdBE; + UINT16 NumComIdsBE; + UINT8 Reserved[5]; + UINT8 InitialCPINSIDPIN; + UINT8 CPINSIDPINRevertBehavior; + UINT8 Future[5]; +} OPAL_SSCLITE_FEATURE_DESCRIPTOR; + +typedef struct _PYRITE_SSC_FEATURE_DESCRIPTOR { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT16 BaseComdIdBE; + UINT16 NumComIdsBE; + UINT8 Reserved[5]; + UINT8 InitialCPINSIDPIN; + UINT8 CPINSIDPINRevertBehavior; + UINT8 Future[5]; +} PYRITE_SSC_FEATURE_DESCRIPTOR; + +typedef struct _PYRITE_SSCV2_FEATURE_DESCRIPTOR { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT16 BaseComdIdBE; + UINT16 NumComIdsBE; + UINT8 Reserved[5]; + UINT8 InitialCPINSIDPIN; + UINT8 CPINSIDPINRevertBehavior; + UINT8 Future[5]; +} PYRITE_SSCV2_FEATURE_DESCRIPTOR; + +typedef struct _DATA_REMOVAL_FEATURE_DESCRIPTOR { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER Header; + UINT8 Reserved; + UINT8 OperationProcessing : 1; + UINT8 Reserved2 : 7; + UINT8 RemovalMechanism; + UINT8 FormatBit0 : 1; // Data Removal Time Format for Bit 0 + UINT8 FormatBit1 : 1; // Data Removal Time Format for Bit 1 + UINT8 FormatBit2 : 1; // Data Removal Time Format for Bit 2 + UINT8 FormatBit3 : 1; // Data Removal Time Format for Bit 3 + UINT8 FormatBit4 : 1; // Data Removal Time Format for Bit 4 + UINT8 FormatBit5 : 1; // Data Removal Time Format for Bit 5 + UINT8 Reserved3 : 2; + UINT16 TimeBit0; // Data Removal Time for Supported Data Removal Mechanism Bit 0 + UINT16 TimeBit1; // Data Removal Time for Supported Data Removal Mechanism Bit 1 + UINT16 TimeBit2; // Data Removal Time for Supported Data Removal Mechanism Bit 2 + UINT16 TimeBit3; // Data Removal Time for Supported Data Removal Mechanism Bit 3 + UINT16 TimeBit4; // Data Removal Time for Supported Data Removal Mechanism Bit 4 + UINT16 TimeBit5; // Data Removal Time for Supported Data Removal Mechanism Bit 5 + UINT8 Future[16]; +} DATA_REMOVAL_FEATURE_DESCRIPTOR; + +typedef union { + TCG_LEVEL0_FEATURE_DESCRIPTOR_HEADER CommonHeader; + TCG_TPER_FEATURE_DESCRIPTOR Tper; + TCG_LOCKING_FEATURE_DESCRIPTOR Locking; + OPAL_GEOMETRY_REPORTING_FEATURE Geometry; + OPAL_SINGLE_USER_MODE_FEATURE SingleUser; + OPAL_DATASTORE_TABLE_FEATURE DataStore; + OPAL_SSCV1_FEATURE_DESCRIPTOR OpalSscV1; + OPAL_SSCV2_FEATURE_DESCRIPTOR OpalSscV2; + OPAL_SSCLITE_FEATURE_DESCRIPTOR OpalSscLite; + PYRITE_SSC_FEATURE_DESCRIPTOR PyriteSsc; + PYRITE_SSCV2_FEATURE_DESCRIPTOR PyriteSscV2; + TCG_BLOCK_SID_FEATURE_DESCRIPTOR BlockSid; + DATA_REMOVAL_FEATURE_DESCRIPTOR DataRemoval; +} OPAL_LEVEL0_FEATURE_DESCRIPTOR; + +#pragma pack() + +#endif // _OPAL_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcpaAcpi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcpaAcpi.h new file mode 100644 index 0000000..fde31ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TcpaAcpi.h @@ -0,0 +1,58 @@ +/** @file + TCPA ACPI table definition. + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCPA_ACPI_H_ +#define _TCPA_ACPI_H_ + +#include + +#pragma pack (1) + +typedef struct _EFI_TCG_CLIENT_ACPI_TABLE { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT16 PlatformClass; + UINT32 Laml; + UINT64 Lasa; +} EFI_TCG_CLIENT_ACPI_TABLE; + +typedef struct _EFI_TCG_SERVER_ACPI_TABLE { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT16 PlatformClass; + UINT16 Reserved0; + UINT64 Laml; + UINT64 Lasa; + UINT16 SpecRev; + UINT8 DeviceFlags; + UINT8 InterruptFlags; + UINT8 Gpe; + UINT8 Reserved1[3]; + UINT32 GlobalSysInt; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE BaseAddress; + UINT32 Reserved2; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE ConfigAddress; + UINT8 PciSegNum; + UINT8 PciBusNum; + UINT8 PciDevNum; + UINT8 PciFuncNum; +} EFI_TCG_SERVER_ACPI_TABLE; + +// +// TCG Platform Type based on TCG ACPI Specification Version 1.00 +// +#define TCG_PLATFORM_TYPE_CLIENT 0 +#define TCG_PLATFORM_TYPE_SERVER 1 + +#pragma pack () + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tls1.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tls1.h new file mode 100644 index 0000000..5f55e0b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tls1.h @@ -0,0 +1,107 @@ +/** @file + Transport Layer Security -- TLS 1.0/1.1/1.2 Standard definitions, from RFC 2246/4346/5246 + + This file contains common TLS 1.0/1.1/1.2 definitions from RFC 2246/4346/5246 + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __TLS_1_H__ +#define __TLS_1_H__ + +#pragma pack(1) + +/// +/// TLS Cipher Suite, refers to A.5 of rfc-2246, rfc-4346 and rfc-5246. +/// +#define TLS_RSA_WITH_NULL_MD5 {0x00, 0x01} +#define TLS_RSA_WITH_NULL_SHA {0x00, 0x02} +#define TLS_RSA_WITH_RC4_128_MD5 {0x00, 0x04} +#define TLS_RSA_WITH_RC4_128_SHA {0x00, 0x05} +#define TLS_RSA_WITH_IDEA_CBC_SHA {0x00, 0x07} +#define TLS_RSA_WITH_DES_CBC_SHA {0x00, 0x09} +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA {0x00, 0x0A} +#define TLS_DH_DSS_WITH_DES_CBC_SHA {0x00, 0x0C} +#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA {0x00, 0x0D} +#define TLS_DH_RSA_WITH_DES_CBC_SHA {0x00, 0x0F} +#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA {0x00, 0x10} +#define TLS_DHE_DSS_WITH_DES_CBC_SHA {0x00, 0x12} +#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA {0x00, 0x13} +#define TLS_DHE_RSA_WITH_DES_CBC_SHA {0x00, 0x15} +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA {0x00, 0x16} +#define TLS_RSA_WITH_AES_128_CBC_SHA {0x00, 0x2F} +#define TLS_DH_DSS_WITH_AES_128_CBC_SHA {0x00, 0x30} +#define TLS_DH_RSA_WITH_AES_128_CBC_SHA {0x00, 0x31} +#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA {0x00, 0x32} +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA {0x00, 0x33} +#define TLS_RSA_WITH_AES_256_CBC_SHA {0x00, 0x35} +#define TLS_DH_DSS_WITH_AES_256_CBC_SHA {0x00, 0x36} +#define TLS_DH_RSA_WITH_AES_256_CBC_SHA {0x00, 0x37} +#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA {0x00, 0x38} +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA {0x00, 0x39} +#define TLS_RSA_WITH_NULL_SHA256 {0x00, 0x3B} +#define TLS_RSA_WITH_AES_128_CBC_SHA256 {0x00, 0x3C} +#define TLS_RSA_WITH_AES_256_CBC_SHA256 {0x00, 0x3D} +#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256 {0x00, 0x3E} +#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256 {0x00, 0x3F} +#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 {0x00, 0x40} +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 {0x00, 0x67} +#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256 {0x00, 0x68} +#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256 {0x00, 0x69} +#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 {0x00, 0x6A} +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 {0x00, 0x6B} + +/// +/// TLS Version, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246. +/// +#define TLS10_PROTOCOL_VERSION_MAJOR 0x03 +#define TLS10_PROTOCOL_VERSION_MINOR 0x01 +#define TLS11_PROTOCOL_VERSION_MAJOR 0x03 +#define TLS11_PROTOCOL_VERSION_MINOR 0x02 +#define TLS12_PROTOCOL_VERSION_MAJOR 0x03 +#define TLS12_PROTOCOL_VERSION_MINOR 0x03 + +/// +/// TLS Content Type, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246. +/// +typedef enum { + TlsContentTypeChangeCipherSpec = 20, + TlsContentTypeAlert = 21, + TlsContentTypeHandshake = 22, + TlsContentTypeApplicationData = 23, +} TLS_CONTENT_TYPE; + +/// +/// TLS Record Header, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246. +/// +typedef struct { + UINT8 ContentType; + EFI_TLS_VERSION Version; + UINT16 Length; +} TLS_RECORD_HEADER; + +#define TLS_RECORD_HEADER_LENGTH 5 + +// +// The length (in bytes) of the TLSPlaintext records payload MUST NOT exceed 2^14. +// Refers to section 6.2 of RFC5246. +// +#define TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH 16384 + +// +// The length (in bytes) of the TLSCiphertext records payload MUST NOT exceed 2^14 + 2048. +// Refers to section 6.2 of RFC5246. +// +#define TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH 18432 + +#pragma pack() + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm12.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm12.h new file mode 100644 index 0000000..2aee799 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm12.h @@ -0,0 +1,2173 @@ +/** @file + TPM Specification data structures (TCG TPM Specification Version 1.2 Revision 103) + See http://trustedcomputinggroup.org for latest specification updates + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + + +#ifndef _TPM12_H_ +#define _TPM12_H_ + +/// +/// The start of TPM return codes +/// +#define TPM_BASE 0 + +// +// All structures MUST be packed on a byte boundary. +// + +#pragma pack (1) + +// +// Part 2, section 2.2.3: Helper redefinitions +// +/// +/// Indicates the conditions where it is required that authorization be presented +/// +typedef UINT8 TPM_AUTH_DATA_USAGE; +/// +/// The information as to what the payload is in an encrypted structure +/// +typedef UINT8 TPM_PAYLOAD_TYPE; +/// +/// The version info breakdown +/// +typedef UINT8 TPM_VERSION_BYTE; +/// +/// The state of the dictionary attack mitigation logic +/// +typedef UINT8 TPM_DA_STATE; +/// +/// The request or response authorization type +/// +typedef UINT16 TPM_TAG; +/// +/// The protocol in use +/// +typedef UINT16 TPM_PROTOCOL_ID; +/// +/// Indicates the start state +/// +typedef UINT16 TPM_STARTUP_TYPE; +/// +/// The definition of the encryption scheme +/// +typedef UINT16 TPM_ENC_SCHEME; +/// +/// The definition of the signature scheme +/// +typedef UINT16 TPM_SIG_SCHEME; +/// +/// The definition of the migration scheme +/// +typedef UINT16 TPM_MIGRATE_SCHEME; +/// +/// Sets the state of the physical presence mechanism +/// +typedef UINT16 TPM_PHYSICAL_PRESENCE; +/// +/// Indicates the types of entity that are supported by the TPM +/// +typedef UINT16 TPM_ENTITY_TYPE; +/// +/// Indicates the permitted usage of the key +/// +typedef UINT16 TPM_KEY_USAGE; +/// +/// The type of asymmetric encrypted structure in use by the endorsement key +/// +typedef UINT16 TPM_EK_TYPE; +/// +/// The tag for the structure +/// +typedef UINT16 TPM_STRUCTURE_TAG; +/// +/// The platform specific spec to which the information relates to +/// +typedef UINT16 TPM_PLATFORM_SPECIFIC; +/// +/// The command ordinal +/// +typedef UINT32 TPM_COMMAND_CODE; +/// +/// Identifies a TPM capability area +/// +typedef UINT32 TPM_CAPABILITY_AREA; +/// +/// Indicates information regarding a key +/// +typedef UINT32 TPM_KEY_FLAGS; +/// +/// Indicates the type of algorithm +/// +typedef UINT32 TPM_ALGORITHM_ID; +/// +/// The locality modifier +/// +typedef UINT32 TPM_MODIFIER_INDICATOR; +/// +/// The actual number of a counter +/// +typedef UINT32 TPM_ACTUAL_COUNT; +/// +/// Attributes that define what options are in use for a transport session +/// +typedef UINT32 TPM_TRANSPORT_ATTRIBUTES; +/// +/// Handle to an authorization session +/// +typedef UINT32 TPM_AUTHHANDLE; +/// +/// Index to a DIR register +/// +typedef UINT32 TPM_DIRINDEX; +/// +/// The area where a key is held assigned by the TPM +/// +typedef UINT32 TPM_KEY_HANDLE; +/// +/// Index to a PCR register +/// +typedef UINT32 TPM_PCRINDEX; +/// +/// The return code from a function +/// +typedef UINT32 TPM_RESULT; +/// +/// The types of resources that a TPM may have using internal resources +/// +typedef UINT32 TPM_RESOURCE_TYPE; +/// +/// Allows for controlling of the key when loaded and how to handle TPM_Startup issues +/// +typedef UINT32 TPM_KEY_CONTROL; +/// +/// The index into the NV storage area +/// +typedef UINT32 TPM_NV_INDEX; +/// +/// The family ID. Family IDs are automatically assigned a sequence number by the TPM. +/// A trusted process can set the FamilyID value in an individual row to NULL, which +/// invalidates that row. The family ID resets to NULL on each change of TPM Owner. +/// +typedef UINT32 TPM_FAMILY_ID; +/// +/// IA value used as a label for the most recent verification of this family. Set to zero when not in use. +/// +typedef UINT32 TPM_FAMILY_VERIFICATION; +/// +/// How the TPM handles var +/// +typedef UINT32 TPM_STARTUP_EFFECTS; +/// +/// The mode of a symmetric encryption +/// +typedef UINT32 TPM_SYM_MODE; +/// +/// The family flags +/// +typedef UINT32 TPM_FAMILY_FLAGS; +/// +/// The index value for the delegate NV table +/// +typedef UINT32 TPM_DELEGATE_INDEX; +/// +/// The restrictions placed on delegation of CMK commands +/// +typedef UINT32 TPM_CMK_DELEGATE; +/// +/// The ID value of a monotonic counter +/// +typedef UINT32 TPM_COUNT_ID; +/// +/// A command to execute +/// +typedef UINT32 TPM_REDIT_COMMAND; +/// +/// A transport session handle +/// +typedef UINT32 TPM_TRANSHANDLE; +/// +/// A generic handle could be key, transport etc +/// +typedef UINT32 TPM_HANDLE; +/// +/// What operation is happening +/// +typedef UINT32 TPM_FAMILY_OPERATION; + +// +// Part 2, section 2.2.4: Vendor specific +// The following defines allow for the quick specification of a +// vendor specific item. +// +#define TPM_Vendor_Specific32 ((UINT32) 0x00000400) +#define TPM_Vendor_Specific8 ((UINT8) 0x80) + +// +// Part 2, section 3.1: TPM_STRUCTURE_TAG +// +#define TPM_TAG_CONTEXTBLOB ((TPM_STRUCTURE_TAG) 0x0001) +#define TPM_TAG_CONTEXT_SENSITIVE ((TPM_STRUCTURE_TAG) 0x0002) +#define TPM_TAG_CONTEXTPOINTER ((TPM_STRUCTURE_TAG) 0x0003) +#define TPM_TAG_CONTEXTLIST ((TPM_STRUCTURE_TAG) 0x0004) +#define TPM_TAG_SIGNINFO ((TPM_STRUCTURE_TAG) 0x0005) +#define TPM_TAG_PCR_INFO_LONG ((TPM_STRUCTURE_TAG) 0x0006) +#define TPM_TAG_PERSISTENT_FLAGS ((TPM_STRUCTURE_TAG) 0x0007) +#define TPM_TAG_VOLATILE_FLAGS ((TPM_STRUCTURE_TAG) 0x0008) +#define TPM_TAG_PERSISTENT_DATA ((TPM_STRUCTURE_TAG) 0x0009) +#define TPM_TAG_VOLATILE_DATA ((TPM_STRUCTURE_TAG) 0x000A) +#define TPM_TAG_SV_DATA ((TPM_STRUCTURE_TAG) 0x000B) +#define TPM_TAG_EK_BLOB ((TPM_STRUCTURE_TAG) 0x000C) +#define TPM_TAG_EK_BLOB_AUTH ((TPM_STRUCTURE_TAG) 0x000D) +#define TPM_TAG_COUNTER_VALUE ((TPM_STRUCTURE_TAG) 0x000E) +#define TPM_TAG_TRANSPORT_INTERNAL ((TPM_STRUCTURE_TAG) 0x000F) +#define TPM_TAG_TRANSPORT_LOG_IN ((TPM_STRUCTURE_TAG) 0x0010) +#define TPM_TAG_TRANSPORT_LOG_OUT ((TPM_STRUCTURE_TAG) 0x0011) +#define TPM_TAG_AUDIT_EVENT_IN ((TPM_STRUCTURE_TAG) 0x0012) +#define TPM_TAG_AUDIT_EVENT_OUT ((TPM_STRUCTURE_TAG) 0x0013) +#define TPM_TAG_CURRENT_TICKS ((TPM_STRUCTURE_TAG) 0x0014) +#define TPM_TAG_KEY ((TPM_STRUCTURE_TAG) 0x0015) +#define TPM_TAG_STORED_DATA12 ((TPM_STRUCTURE_TAG) 0x0016) +#define TPM_TAG_NV_ATTRIBUTES ((TPM_STRUCTURE_TAG) 0x0017) +#define TPM_TAG_NV_DATA_PUBLIC ((TPM_STRUCTURE_TAG) 0x0018) +#define TPM_TAG_NV_DATA_SENSITIVE ((TPM_STRUCTURE_TAG) 0x0019) +#define TPM_TAG_DELEGATIONS ((TPM_STRUCTURE_TAG) 0x001A) +#define TPM_TAG_DELEGATE_PUBLIC ((TPM_STRUCTURE_TAG) 0x001B) +#define TPM_TAG_DELEGATE_TABLE_ROW ((TPM_STRUCTURE_TAG) 0x001C) +#define TPM_TAG_TRANSPORT_AUTH ((TPM_STRUCTURE_TAG) 0x001D) +#define TPM_TAG_TRANSPORT_PUBLIC ((TPM_STRUCTURE_TAG) 0x001E) +#define TPM_TAG_PERMANENT_FLAGS ((TPM_STRUCTURE_TAG) 0x001F) +#define TPM_TAG_STCLEAR_FLAGS ((TPM_STRUCTURE_TAG) 0x0020) +#define TPM_TAG_STANY_FLAGS ((TPM_STRUCTURE_TAG) 0x0021) +#define TPM_TAG_PERMANENT_DATA ((TPM_STRUCTURE_TAG) 0x0022) +#define TPM_TAG_STCLEAR_DATA ((TPM_STRUCTURE_TAG) 0x0023) +#define TPM_TAG_STANY_DATA ((TPM_STRUCTURE_TAG) 0x0024) +#define TPM_TAG_FAMILY_TABLE_ENTRY ((TPM_STRUCTURE_TAG) 0x0025) +#define TPM_TAG_DELEGATE_SENSITIVE ((TPM_STRUCTURE_TAG) 0x0026) +#define TPM_TAG_DELG_KEY_BLOB ((TPM_STRUCTURE_TAG) 0x0027) +#define TPM_TAG_KEY12 ((TPM_STRUCTURE_TAG) 0x0028) +#define TPM_TAG_CERTIFY_INFO2 ((TPM_STRUCTURE_TAG) 0x0029) +#define TPM_TAG_DELEGATE_OWNER_BLOB ((TPM_STRUCTURE_TAG) 0x002A) +#define TPM_TAG_EK_BLOB_ACTIVATE ((TPM_STRUCTURE_TAG) 0x002B) +#define TPM_TAG_DAA_BLOB ((TPM_STRUCTURE_TAG) 0x002C) +#define TPM_TAG_DAA_CONTEXT ((TPM_STRUCTURE_TAG) 0x002D) +#define TPM_TAG_DAA_ENFORCE ((TPM_STRUCTURE_TAG) 0x002E) +#define TPM_TAG_DAA_ISSUER ((TPM_STRUCTURE_TAG) 0x002F) +#define TPM_TAG_CAP_VERSION_INFO ((TPM_STRUCTURE_TAG) 0x0030) +#define TPM_TAG_DAA_SENSITIVE ((TPM_STRUCTURE_TAG) 0x0031) +#define TPM_TAG_DAA_TPM ((TPM_STRUCTURE_TAG) 0x0032) +#define TPM_TAG_CMK_MIGAUTH ((TPM_STRUCTURE_TAG) 0x0033) +#define TPM_TAG_CMK_SIGTICKET ((TPM_STRUCTURE_TAG) 0x0034) +#define TPM_TAG_CMK_MA_APPROVAL ((TPM_STRUCTURE_TAG) 0x0035) +#define TPM_TAG_QUOTE_INFO2 ((TPM_STRUCTURE_TAG) 0x0036) +#define TPM_TAG_DA_INFO ((TPM_STRUCTURE_TAG) 0x0037) +#define TPM_TAG_DA_LIMITED ((TPM_STRUCTURE_TAG) 0x0038) +#define TPM_TAG_DA_ACTION_TYPE ((TPM_STRUCTURE_TAG) 0x0039) + +// +// Part 2, section 4: TPM Types +// + +// +// Part 2, section 4.1: TPM_RESOURCE_TYPE +// +#define TPM_RT_KEY ((TPM_RESOURCE_TYPE) 0x00000001) ///< The handle is a key handle and is the result of a LoadKey type operation +#define TPM_RT_AUTH ((TPM_RESOURCE_TYPE) 0x00000002) ///< The handle is an authorization handle. Auth handles come from TPM_OIAP, TPM_OSAP and TPM_DSAP +#define TPM_RT_HASH ((TPM_RESOURCE_TYPE) 0x00000003) ///< Reserved for hashes +#define TPM_RT_TRANS ((TPM_RESOURCE_TYPE) 0x00000004) ///< The handle is for a transport session. Transport handles come from TPM_EstablishTransport +#define TPM_RT_CONTEXT ((TPM_RESOURCE_TYPE) 0x00000005) ///< Resource wrapped and held outside the TPM using the context save/restore commands +#define TPM_RT_COUNTER ((TPM_RESOURCE_TYPE) 0x00000006) ///< Reserved for counters +#define TPM_RT_DELEGATE ((TPM_RESOURCE_TYPE) 0x00000007) ///< The handle is for a delegate row. These are the internal rows held in NV storage by the TPM +#define TPM_RT_DAA_TPM ((TPM_RESOURCE_TYPE) 0x00000008) ///< The value is a DAA TPM specific blob +#define TPM_RT_DAA_V0 ((TPM_RESOURCE_TYPE) 0x00000009) ///< The value is a DAA V0 parameter +#define TPM_RT_DAA_V1 ((TPM_RESOURCE_TYPE) 0x0000000A) ///< The value is a DAA V1 parameter + +// +// Part 2, section 4.2: TPM_PAYLOAD_TYPE +// +#define TPM_PT_ASYM ((TPM_PAYLOAD_TYPE) 0x01) ///< The entity is an asymmetric key +#define TPM_PT_BIND ((TPM_PAYLOAD_TYPE) 0x02) ///< The entity is bound data +#define TPM_PT_MIGRATE ((TPM_PAYLOAD_TYPE) 0x03) ///< The entity is a migration blob +#define TPM_PT_MAINT ((TPM_PAYLOAD_TYPE) 0x04) ///< The entity is a maintenance blob +#define TPM_PT_SEAL ((TPM_PAYLOAD_TYPE) 0x05) ///< The entity is sealed data +#define TPM_PT_MIGRATE_RESTRICTED ((TPM_PAYLOAD_TYPE) 0x06) ///< The entity is a restricted-migration asymmetric key +#define TPM_PT_MIGRATE_EXTERNAL ((TPM_PAYLOAD_TYPE) 0x07) ///< The entity is a external migratable key +#define TPM_PT_CMK_MIGRATE ((TPM_PAYLOAD_TYPE) 0x08) ///< The entity is a CMK migratable blob +#define TPM_PT_VENDOR_SPECIFIC ((TPM_PAYLOAD_TYPE) 0x80) ///< 0x80 - 0xFF Vendor specific payloads + +// +// Part 2, section 4.3: TPM_ENTITY_TYPE +// +#define TPM_ET_KEYHANDLE ((UINT16) 0x0001) ///< The entity is a keyHandle or key +#define TPM_ET_OWNER ((UINT16) 0x0002) ///< The entity is the TPM Owner +#define TPM_ET_DATA ((UINT16) 0x0003) ///< The entity is some data +#define TPM_ET_SRK ((UINT16) 0x0004) ///< The entity is the SRK +#define TPM_ET_KEY ((UINT16) 0x0005) ///< The entity is a key or keyHandle +#define TPM_ET_REVOKE ((UINT16) 0x0006) ///< The entity is the RevokeTrust value +#define TPM_ET_DEL_OWNER_BLOB ((UINT16) 0x0007) ///< The entity is a delegate owner blob +#define TPM_ET_DEL_ROW ((UINT16) 0x0008) ///< The entity is a delegate row +#define TPM_ET_DEL_KEY_BLOB ((UINT16) 0x0009) ///< The entity is a delegate key blob +#define TPM_ET_COUNTER ((UINT16) 0x000A) ///< The entity is a counter +#define TPM_ET_NV ((UINT16) 0x000B) ///< The entity is a NV index +#define TPM_ET_OPERATOR ((UINT16) 0x000C) ///< The entity is the operator +#define TPM_ET_RESERVED_HANDLE ((UINT16) 0x0040) ///< Reserved. This value avoids collisions with the handle MSB setting. +// +// TPM_ENTITY_TYPE MSB Values: The MSB is used to indicate the ADIP encryption sheme when applicable +// +#define TPM_ET_XOR ((UINT16) 0x0000) ///< ADIP encryption scheme: XOR +#define TPM_ET_AES128 ((UINT16) 0x0006) ///< ADIP encryption scheme: AES 128 bits + +// +// Part 2, section 4.4.1: Reserved Key Handles +// +#define TPM_KH_SRK ((TPM_KEY_HANDLE) 0x40000000) ///< The handle points to the SRK +#define TPM_KH_OWNER ((TPM_KEY_HANDLE) 0x40000001) ///< The handle points to the TPM Owner +#define TPM_KH_REVOKE ((TPM_KEY_HANDLE) 0x40000002) ///< The handle points to the RevokeTrust value +#define TPM_KH_TRANSPORT ((TPM_KEY_HANDLE) 0x40000003) ///< The handle points to the EstablishTransport static authorization +#define TPM_KH_OPERATOR ((TPM_KEY_HANDLE) 0x40000004) ///< The handle points to the Operator auth +#define TPM_KH_ADMIN ((TPM_KEY_HANDLE) 0x40000005) ///< The handle points to the delegation administration auth +#define TPM_KH_EK ((TPM_KEY_HANDLE) 0x40000006) ///< The handle points to the PUBEK, only usable with TPM_OwnerReadInternalPub + +// +// Part 2, section 4.5: TPM_STARTUP_TYPE +// +#define TPM_ST_CLEAR ((TPM_STARTUP_TYPE) 0x0001) ///< The TPM is starting up from a clean state +#define TPM_ST_STATE ((TPM_STARTUP_TYPE) 0x0002) ///< The TPM is starting up from a saved state +#define TPM_ST_DEACTIVATED ((TPM_STARTUP_TYPE) 0x0003) ///< The TPM is to startup and set the deactivated flag to TRUE + +// +// Part 2, section 4.6: TPM_STATUP_EFFECTS +// The table makeup is still an open issue. +// + +// +// Part 2, section 4.7: TPM_PROTOCOL_ID +// +#define TPM_PID_OIAP ((TPM_PROTOCOL_ID) 0x0001) ///< The OIAP protocol. +#define TPM_PID_OSAP ((TPM_PROTOCOL_ID) 0x0002) ///< The OSAP protocol. +#define TPM_PID_ADIP ((TPM_PROTOCOL_ID) 0x0003) ///< The ADIP protocol. +#define TPM_PID_ADCP ((TPM_PROTOCOL_ID) 0x0004) ///< The ADCP protocol. +#define TPM_PID_OWNER ((TPM_PROTOCOL_ID) 0x0005) ///< The protocol for taking ownership of a TPM. +#define TPM_PID_DSAP ((TPM_PROTOCOL_ID) 0x0006) ///< The DSAP protocol +#define TPM_PID_TRANSPORT ((TPM_PROTOCOL_ID) 0x0007) ///< The transport protocol + +// +// Part 2, section 4.8: TPM_ALGORITHM_ID +// The TPM MUST support the algorithms TPM_ALG_RSA, TPM_ALG_SHA, TPM_ALG_HMAC, +// TPM_ALG_MGF1 +// +#define TPM_ALG_RSA ((TPM_ALGORITHM_ID) 0x00000001) ///< The RSA algorithm. +#define TPM_ALG_DES ((TPM_ALGORITHM_ID) 0x00000002) ///< The DES algorithm +#define TPM_ALG_3DES ((TPM_ALGORITHM_ID) 0x00000003) ///< The 3DES algorithm in EDE mode +#define TPM_ALG_SHA ((TPM_ALGORITHM_ID) 0x00000004) ///< The SHA1 algorithm +#define TPM_ALG_HMAC ((TPM_ALGORITHM_ID) 0x00000005) ///< The RFC 2104 HMAC algorithm +#define TPM_ALG_AES128 ((TPM_ALGORITHM_ID) 0x00000006) ///< The AES algorithm, key size 128 +#define TPM_ALG_MGF1 ((TPM_ALGORITHM_ID) 0x00000007) ///< The XOR algorithm using MGF1 to create a string the size of the encrypted block +#define TPM_ALG_AES192 ((TPM_ALGORITHM_ID) 0x00000008) ///< AES, key size 192 +#define TPM_ALG_AES256 ((TPM_ALGORITHM_ID) 0x00000009) ///< AES, key size 256 +#define TPM_ALG_XOR ((TPM_ALGORITHM_ID) 0x0000000A) ///< XOR using the rolling nonces + +// +// Part 2, section 4.9: TPM_PHYSICAL_PRESENCE +// +#define TPM_PHYSICAL_PRESENCE_HW_DISABLE ((TPM_PHYSICAL_PRESENCE) 0x0200) ///< Sets the physicalPresenceHWEnable to FALSE +#define TPM_PHYSICAL_PRESENCE_CMD_DISABLE ((TPM_PHYSICAL_PRESENCE) 0x0100) ///< Sets the physicalPresenceCMDEnable to FALSE +#define TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK ((TPM_PHYSICAL_PRESENCE) 0x0080) ///< Sets the physicalPresenceLifetimeLock to TRUE +#define TPM_PHYSICAL_PRESENCE_HW_ENABLE ((TPM_PHYSICAL_PRESENCE) 0x0040) ///< Sets the physicalPresenceHWEnable to TRUE +#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE ((TPM_PHYSICAL_PRESENCE) 0x0020) ///< Sets the physicalPresenceCMDEnable to TRUE +#define TPM_PHYSICAL_PRESENCE_NOTPRESENT ((TPM_PHYSICAL_PRESENCE) 0x0010) ///< Sets PhysicalPresence = FALSE +#define TPM_PHYSICAL_PRESENCE_PRESENT ((TPM_PHYSICAL_PRESENCE) 0x0008) ///< Sets PhysicalPresence = TRUE +#define TPM_PHYSICAL_PRESENCE_LOCK ((TPM_PHYSICAL_PRESENCE) 0x0004) ///< Sets PhysicalPresenceLock = TRUE + +// +// Part 2, section 4.10: TPM_MIGRATE_SCHEME +// +#define TPM_MS_MIGRATE ((TPM_MIGRATE_SCHEME) 0x0001) ///< A public key that can be used with all TPM migration commands other than 'ReWrap' mode. +#define TPM_MS_REWRAP ((TPM_MIGRATE_SCHEME) 0x0002) ///< A public key that can be used for the ReWrap mode of TPM_CreateMigrationBlob. +#define TPM_MS_MAINT ((TPM_MIGRATE_SCHEME) 0x0003) ///< A public key that can be used for the Maintenance commands +#define TPM_MS_RESTRICT_MIGRATE ((TPM_MIGRATE_SCHEME) 0x0004) ///< The key is to be migrated to a Migration Authority. +#define TPM_MS_RESTRICT_APPROVE_DOUBLE ((TPM_MIGRATE_SCHEME) 0x0005) ///< The key is to be migrated to an entity approved by a Migration Authority using double wrapping + +// +// Part 2, section 4.11: TPM_EK_TYPE +// +#define TPM_EK_TYPE_ACTIVATE ((TPM_EK_TYPE) 0x0001) ///< The blob MUST be TPM_EK_BLOB_ACTIVATE +#define TPM_EK_TYPE_AUTH ((TPM_EK_TYPE) 0x0002) ///< The blob MUST be TPM_EK_BLOB_AUTH + +// +// Part 2, section 4.12: TPM_PLATFORM_SPECIFIC +// +#define TPM_PS_PC_11 ((TPM_PLATFORM_SPECIFIC) 0x0001) ///< PC Specific version 1.1 +#define TPM_PS_PC_12 ((TPM_PLATFORM_SPECIFIC) 0x0002) ///< PC Specific version 1.2 +#define TPM_PS_PDA_12 ((TPM_PLATFORM_SPECIFIC) 0x0003) ///< PDA Specific version 1.2 +#define TPM_PS_Server_12 ((TPM_PLATFORM_SPECIFIC) 0x0004) ///< Server Specific version 1.2 +#define TPM_PS_Mobile_12 ((TPM_PLATFORM_SPECIFIC) 0x0005) ///< Mobil Specific version 1.2 + +// +// Part 2, section 5: Basic Structures +// + +/// +/// Part 2, section 5.1: TPM_STRUCT_VER +/// +typedef struct tdTPM_STRUCT_VER { + UINT8 major; + UINT8 minor; + UINT8 revMajor; + UINT8 revMinor; +} TPM_STRUCT_VER; + +/// +/// Part 2, section 5.3: TPM_VERSION +/// +typedef struct tdTPM_VERSION { + TPM_VERSION_BYTE major; + TPM_VERSION_BYTE minor; + UINT8 revMajor; + UINT8 revMinor; +} TPM_VERSION; + + +#define TPM_SHA1_160_HASH_LEN 0x14 +#define TPM_SHA1BASED_NONCE_LEN TPM_SHA1_160_HASH_LEN + +/// +/// Part 2, section 5.4: TPM_DIGEST +/// +typedef struct tdTPM_DIGEST{ + UINT8 digest[TPM_SHA1_160_HASH_LEN]; +} TPM_DIGEST; + +/// +/// This SHALL be the digest of the chosen identityLabel and privacyCA for a new TPM identity +/// +typedef TPM_DIGEST TPM_CHOSENID_HASH; +/// +/// This SHALL be the hash of a list of PCR indexes and PCR values that a key or data is bound to +/// +typedef TPM_DIGEST TPM_COMPOSITE_HASH; +/// +/// This SHALL be the value of a DIR register +/// +typedef TPM_DIGEST TPM_DIRVALUE; + +typedef TPM_DIGEST TPM_HMAC; +/// +/// The value inside of the PCR +/// +typedef TPM_DIGEST TPM_PCRVALUE; +/// +/// This SHALL be the value of the current internal audit state +/// +typedef TPM_DIGEST TPM_AUDITDIGEST; + +/// +/// Part 2, section 5.5: TPM_NONCE +/// +typedef struct tdTPM_NONCE{ + UINT8 nonce[20]; +} TPM_NONCE; + +/// +/// This SHALL be a random value generated by a TPM immediately after the EK is installed +/// in that TPM, whenever an EK is installed in that TPM +/// +typedef TPM_NONCE TPM_DAA_TPM_SEED; +/// +/// This SHALL be a random value +/// +typedef TPM_NONCE TPM_DAA_CONTEXT_SEED; + +// +// Part 2, section 5.6: TPM_AUTHDATA +// +/// +/// The AuthData data is the information that is saved or passed to provide proof of ownership +/// 296 of an entity +/// +typedef UINT8 tdTPM_AUTHDATA[20]; + +typedef tdTPM_AUTHDATA TPM_AUTHDATA; +/// +/// A secret plaintext value used in the authorization process +/// +typedef TPM_AUTHDATA TPM_SECRET; +/// +/// A ciphertext (encrypted) version of AuthData data. The encryption mechanism depends on the context +/// +typedef TPM_AUTHDATA TPM_ENCAUTH; + +/// +/// Part 2, section 5.7: TPM_KEY_HANDLE_LIST +/// Size of handle is loaded * sizeof(TPM_KEY_HANDLE) +/// +typedef struct tdTPM_KEY_HANDLE_LIST { + UINT16 loaded; + TPM_KEY_HANDLE handle[1]; +} TPM_KEY_HANDLE_LIST; + +// +// Part 2, section 5.8: TPM_KEY_USAGE values +// +/// +/// TPM_KEY_SIGNING SHALL indicate a signing key. The [private] key SHALL be +/// used for signing operations, only. This means that it MUST be a leaf of the +/// Protected Storage key hierarchy. +/// +#define TPM_KEY_SIGNING ((UINT16) 0x0010) +/// +/// TPM_KEY_STORAGE SHALL indicate a storage key. The key SHALL be used to wrap +/// and unwrap other keys in the Protected Storage hierarchy +/// +#define TPM_KEY_STORAGE ((UINT16) 0x0011) +/// +/// TPM_KEY_IDENTITY SHALL indicate an identity key. The key SHALL be used for +/// operations that require a TPM identity, only. +/// +#define TPM_KEY_IDENTITY ((UINT16) 0x0012) +/// +/// TPM_KEY_AUTHCHANGE SHALL indicate an ephemeral key that is in use during +/// the ChangeAuthAsym process, only. +/// +#define TPM_KEY_AUTHCHANGE ((UINT16) 0x0013) +/// +/// TPM_KEY_BIND SHALL indicate a key that can be used for TPM_Bind and +/// TPM_Unbind operations only. +/// +#define TPM_KEY_BIND ((UINT16) 0x0014) +/// +/// TPM_KEY_LEGACY SHALL indicate a key that can perform signing and binding +/// operations. The key MAY be used for both signing and binding operations. +/// The TPM_KEY_LEGACY key type is to allow for use by applications where both +/// signing and encryption operations occur with the same key. The use of this +/// key type is not recommended TPM_KEY_MIGRATE 0x0016 This SHALL indicate a +/// key in use for TPM_MigrateKey +/// +#define TPM_KEY_LEGACY ((UINT16) 0x0015) +/// +/// TPM_KEY_MIGRAGE SHALL indicate a key in use for TPM_MigrateKey +/// +#define TPM_KEY_MIGRATE ((UINT16) 0x0016) + +// +// Part 2, section 5.8.1: Mandatory Key Usage Schemes +// + +#define TPM_ES_NONE ((TPM_ENC_SCHEME) 0x0001) +#define TPM_ES_RSAESPKCSv15 ((TPM_ENC_SCHEME) 0x0002) +#define TPM_ES_RSAESOAEP_SHA1_MGF1 ((TPM_ENC_SCHEME) 0x0003) +#define TPM_ES_SYM_CNT ((TPM_ENC_SCHEME) 0x0004) ///< rev94 defined +#define TPM_ES_SYM_CTR ((TPM_ENC_SCHEME) 0x0004) +#define TPM_ES_SYM_OFB ((TPM_ENC_SCHEME) 0x0005) + +#define TPM_SS_NONE ((TPM_SIG_SCHEME) 0x0001) +#define TPM_SS_RSASSAPKCS1v15_SHA1 ((TPM_SIG_SCHEME) 0x0002) +#define TPM_SS_RSASSAPKCS1v15_DER ((TPM_SIG_SCHEME) 0x0003) +#define TPM_SS_RSASSAPKCS1v15_INFO ((TPM_SIG_SCHEME) 0x0004) + +// +// Part 2, section 5.9: TPM_AUTH_DATA_USAGE values +// +#define TPM_AUTH_NEVER ((TPM_AUTH_DATA_USAGE) 0x00) +#define TPM_AUTH_ALWAYS ((TPM_AUTH_DATA_USAGE) 0x01) +#define TPM_AUTH_PRIV_USE_ONLY ((TPM_AUTH_DATA_USAGE) 0x03) + +/// +/// Part 2, section 5.10: TPM_KEY_FLAGS +/// +typedef enum tdTPM_KEY_FLAGS { + redirection = 0x00000001, + migratable = 0x00000002, + isVolatile = 0x00000004, + pcrIgnoredOnRead = 0x00000008, + migrateAuthority = 0x00000010 +} TPM_KEY_FLAGS_BITS; + +/// +/// Part 2, section 5.11: TPM_CHANGEAUTH_VALIDATE +/// +typedef struct tdTPM_CHANGEAUTH_VALIDATE { + TPM_SECRET newAuthSecret; + TPM_NONCE n1; +} TPM_CHANGEAUTH_VALIDATE; + +/// +/// Part 2, section 5.12: TPM_MIGRATIONKEYAUTH +/// decalared after section 10 to catch declaration of TPM_PUBKEY +/// +/// Part 2 section 10.1: TPM_KEY_PARMS +/// [size_is(parmSize)] BYTE* parms; +/// +typedef struct tdTPM_KEY_PARMS { + TPM_ALGORITHM_ID algorithmID; + TPM_ENC_SCHEME encScheme; + TPM_SIG_SCHEME sigScheme; + UINT32 parmSize; + UINT8 *parms; +} TPM_KEY_PARMS; + +/// +/// Part 2, section 10.4: TPM_STORE_PUBKEY +/// +typedef struct tdTPM_STORE_PUBKEY { + UINT32 keyLength; + UINT8 key[1]; +} TPM_STORE_PUBKEY; + +/// +/// Part 2, section 10.5: TPM_PUBKEY +/// +typedef struct tdTPM_PUBKEY{ + TPM_KEY_PARMS algorithmParms; + TPM_STORE_PUBKEY pubKey; +} TPM_PUBKEY; + +/// +/// Part 2, section 5.12: TPM_MIGRATIONKEYAUTH +/// +typedef struct tdTPM_MIGRATIONKEYAUTH{ + TPM_PUBKEY migrationKey; + TPM_MIGRATE_SCHEME migrationScheme; + TPM_DIGEST digest; +} TPM_MIGRATIONKEYAUTH; + +/// +/// Part 2, section 5.13: TPM_COUNTER_VALUE +/// +typedef struct tdTPM_COUNTER_VALUE{ + TPM_STRUCTURE_TAG tag; + UINT8 label[4]; + TPM_ACTUAL_COUNT counter; +} TPM_COUNTER_VALUE; + +/// +/// Part 2, section 5.14: TPM_SIGN_INFO +/// Size of data indicated by dataLen +/// +typedef struct tdTPM_SIGN_INFO { + TPM_STRUCTURE_TAG tag; + UINT8 fixed[4]; + TPM_NONCE replay; + UINT32 dataLen; + UINT8 *data; +} TPM_SIGN_INFO; + +/// +/// Part 2, section 5.15: TPM_MSA_COMPOSITE +/// Number of migAuthDigest indicated by MSAlist +/// +typedef struct tdTPM_MSA_COMPOSITE { + UINT32 MSAlist; + TPM_DIGEST migAuthDigest[1]; +} TPM_MSA_COMPOSITE; + +/// +/// Part 2, section 5.16: TPM_CMK_AUTH +/// +typedef struct tdTPM_CMK_AUTH{ + TPM_DIGEST migrationAuthorityDigest; + TPM_DIGEST destinationKeyDigest; + TPM_DIGEST sourceKeyDigest; +} TPM_CMK_AUTH; + +// +// Part 2, section 5.17: TPM_CMK_DELEGATE +// +#define TPM_CMK_DELEGATE_SIGNING ((TPM_CMK_DELEGATE) BIT31) +#define TPM_CMK_DELEGATE_STORAGE ((TPM_CMK_DELEGATE) BIT30) +#define TPM_CMK_DELEGATE_BIND ((TPM_CMK_DELEGATE) BIT29) +#define TPM_CMK_DELEGATE_LEGACY ((TPM_CMK_DELEGATE) BIT28) +#define TPM_CMK_DELEGATE_MIGRATE ((TPM_CMK_DELEGATE) BIT27) + +/// +/// Part 2, section 5.18: TPM_SELECT_SIZE +/// +typedef struct tdTPM_SELECT_SIZE { + UINT8 major; + UINT8 minor; + UINT16 reqSize; +} TPM_SELECT_SIZE; + +/// +/// Part 2, section 5,19: TPM_CMK_MIGAUTH +/// +typedef struct tdTPM_CMK_MIGAUTH{ + TPM_STRUCTURE_TAG tag; + TPM_DIGEST msaDigest; + TPM_DIGEST pubKeyDigest; +} TPM_CMK_MIGAUTH; + +/// +/// Part 2, section 5.20: TPM_CMK_SIGTICKET +/// +typedef struct tdTPM_CMK_SIGTICKET{ + TPM_STRUCTURE_TAG tag; + TPM_DIGEST verKeyDigest; + TPM_DIGEST signedData; +} TPM_CMK_SIGTICKET; + +/// +/// Part 2, section 5.21: TPM_CMK_MA_APPROVAL +/// +typedef struct tdTPM_CMK_MA_APPROVAL{ + TPM_STRUCTURE_TAG tag; + TPM_DIGEST migrationAuthorityDigest; +} TPM_CMK_MA_APPROVAL; + +// +// Part 2, section 6: Command Tags +// +#define TPM_TAG_RQU_COMMAND ((TPM_STRUCTURE_TAG) 0x00C1) +#define TPM_TAG_RQU_AUTH1_COMMAND ((TPM_STRUCTURE_TAG) 0x00C2) +#define TPM_TAG_RQU_AUTH2_COMMAND ((TPM_STRUCTURE_TAG) 0x00C3) +#define TPM_TAG_RSP_COMMAND ((TPM_STRUCTURE_TAG) 0x00C4) +#define TPM_TAG_RSP_AUTH1_COMMAND ((TPM_STRUCTURE_TAG) 0x00C5) +#define TPM_TAG_RSP_AUTH2_COMMAND ((TPM_STRUCTURE_TAG) 0x00C6) + +/// +/// Part 2, section 7.1: TPM_PERMANENT_FLAGS +/// +typedef struct tdTPM_PERMANENT_FLAGS{ + TPM_STRUCTURE_TAG tag; + BOOLEAN disable; + BOOLEAN ownership; + BOOLEAN deactivated; + BOOLEAN readPubek; + BOOLEAN disableOwnerClear; + BOOLEAN allowMaintenance; + BOOLEAN physicalPresenceLifetimeLock; + BOOLEAN physicalPresenceHWEnable; + BOOLEAN physicalPresenceCMDEnable; + BOOLEAN CEKPUsed; + BOOLEAN TPMpost; + BOOLEAN TPMpostLock; + BOOLEAN FIPS; + BOOLEAN operator; + BOOLEAN enableRevokeEK; + BOOLEAN nvLocked; + BOOLEAN readSRKPub; + BOOLEAN tpmEstablished; + BOOLEAN maintenanceDone; + BOOLEAN disableFullDALogicInfo; +} TPM_PERMANENT_FLAGS; + +// +// Part 2, section 7.1.1: Flag Restrictions (of TPM_PERMANENT_FLAGS) +// +#define TPM_PF_DISABLE ((TPM_CAPABILITY_AREA) 1) +#define TPM_PF_OWNERSHIP ((TPM_CAPABILITY_AREA) 2) +#define TPM_PF_DEACTIVATED ((TPM_CAPABILITY_AREA) 3) +#define TPM_PF_READPUBEK ((TPM_CAPABILITY_AREA) 4) +#define TPM_PF_DISABLEOWNERCLEAR ((TPM_CAPABILITY_AREA) 5) +#define TPM_PF_ALLOWMAINTENANCE ((TPM_CAPABILITY_AREA) 6) +#define TPM_PF_PHYSICALPRESENCELIFETIMELOCK ((TPM_CAPABILITY_AREA) 7) +#define TPM_PF_PHYSICALPRESENCEHWENABLE ((TPM_CAPABILITY_AREA) 8) +#define TPM_PF_PHYSICALPRESENCECMDENABLE ((TPM_CAPABILITY_AREA) 9) +#define TPM_PF_CEKPUSED ((TPM_CAPABILITY_AREA) 10) +#define TPM_PF_TPMPOST ((TPM_CAPABILITY_AREA) 11) +#define TPM_PF_TPMPOSTLOCK ((TPM_CAPABILITY_AREA) 12) +#define TPM_PF_FIPS ((TPM_CAPABILITY_AREA) 13) +#define TPM_PF_OPERATOR ((TPM_CAPABILITY_AREA) 14) +#define TPM_PF_ENABLEREVOKEEK ((TPM_CAPABILITY_AREA) 15) +#define TPM_PF_NV_LOCKED ((TPM_CAPABILITY_AREA) 16) +#define TPM_PF_READSRKPUB ((TPM_CAPABILITY_AREA) 17) +#define TPM_PF_TPMESTABLISHED ((TPM_CAPABILITY_AREA) 18) +#define TPM_PF_MAINTENANCEDONE ((TPM_CAPABILITY_AREA) 19) +#define TPM_PF_DISABLEFULLDALOGICINFO ((TPM_CAPABILITY_AREA) 20) + +/// +/// Part 2, section 7.2: TPM_STCLEAR_FLAGS +/// +typedef struct tdTPM_STCLEAR_FLAGS{ + TPM_STRUCTURE_TAG tag; + BOOLEAN deactivated; + BOOLEAN disableForceClear; + BOOLEAN physicalPresence; + BOOLEAN physicalPresenceLock; + BOOLEAN bGlobalLock; +} TPM_STCLEAR_FLAGS; + +// +// Part 2, section 7.2.1: Flag Restrictions (of TPM_STCLEAR_FLAGS) +// +#define TPM_SF_DEACTIVATED ((TPM_CAPABILITY_AREA) 1) +#define TPM_SF_DISABLEFORCECLEAR ((TPM_CAPABILITY_AREA) 2) +#define TPM_SF_PHYSICALPRESENCE ((TPM_CAPABILITY_AREA) 3) +#define TPM_SF_PHYSICALPRESENCELOCK ((TPM_CAPABILITY_AREA) 4) +#define TPM_SF_BGLOBALLOCK ((TPM_CAPABILITY_AREA) 5) + +/// +/// Part 2, section 7.3: TPM_STANY_FLAGS +/// +typedef struct tdTPM_STANY_FLAGS{ + TPM_STRUCTURE_TAG tag; + BOOLEAN postInitialise; + TPM_MODIFIER_INDICATOR localityModifier; + BOOLEAN transportExclusive; + BOOLEAN TOSPresent; +} TPM_STANY_FLAGS; + +// +// Part 2, section 7.3.1: Flag Restrictions (of TPM_STANY_FLAGS) +// +#define TPM_AF_POSTINITIALISE ((TPM_CAPABILITY_AREA) 1) +#define TPM_AF_LOCALITYMODIFIER ((TPM_CAPABILITY_AREA) 2) +#define TPM_AF_TRANSPORTEXCLUSIVE ((TPM_CAPABILITY_AREA) 3) +#define TPM_AF_TOSPRESENT ((TPM_CAPABILITY_AREA) 4) + +// +// All those structures defined in section 7.4, 7.5, 7.6 are not normative and +// thus no definitions here +// +// Part 2, section 7.4: TPM_PERMANENT_DATA +// +#define TPM_MIN_COUNTERS 4 ///< the minimum number of counters is 4 +#define TPM_DELEGATE_KEY TPM_KEY +#define TPM_NUM_PCR 16 +#define TPM_MAX_NV_WRITE_NOOWNER 64 + +// +// Part 2, section 7.4.1: PERMANENT_DATA Subcap for SetCapability +// +#define TPM_PD_REVMAJOR ((TPM_CAPABILITY_AREA) 1) +#define TPM_PD_REVMINOR ((TPM_CAPABILITY_AREA) 2) +#define TPM_PD_TPMPROOF ((TPM_CAPABILITY_AREA) 3) +#define TPM_PD_OWNERAUTH ((TPM_CAPABILITY_AREA) 4) +#define TPM_PD_OPERATORAUTH ((TPM_CAPABILITY_AREA) 5) +#define TPM_PD_MANUMAINTPUB ((TPM_CAPABILITY_AREA) 6) +#define TPM_PD_ENDORSEMENTKEY ((TPM_CAPABILITY_AREA) 7) +#define TPM_PD_SRK ((TPM_CAPABILITY_AREA) 8) +#define TPM_PD_DELEGATEKEY ((TPM_CAPABILITY_AREA) 9) +#define TPM_PD_CONTEXTKEY ((TPM_CAPABILITY_AREA) 10) +#define TPM_PD_AUDITMONOTONICCOUNTER ((TPM_CAPABILITY_AREA) 11) +#define TPM_PD_MONOTONICCOUNTER ((TPM_CAPABILITY_AREA) 12) +#define TPM_PD_PCRATTRIB ((TPM_CAPABILITY_AREA) 13) +#define TPM_PD_ORDINALAUDITSTATUS ((TPM_CAPABILITY_AREA) 14) +#define TPM_PD_AUTHDIR ((TPM_CAPABILITY_AREA) 15) +#define TPM_PD_RNGSTATE ((TPM_CAPABILITY_AREA) 16) +#define TPM_PD_FAMILYTABLE ((TPM_CAPABILITY_AREA) 17) +#define TPM_DELEGATETABLE ((TPM_CAPABILITY_AREA) 18) +#define TPM_PD_EKRESET ((TPM_CAPABILITY_AREA) 19) +#define TPM_PD_MAXNVBUFSIZE ((TPM_CAPABILITY_AREA) 20) +#define TPM_PD_LASTFAMILYID ((TPM_CAPABILITY_AREA) 21) +#define TPM_PD_NOOWNERNVWRITE ((TPM_CAPABILITY_AREA) 22) +#define TPM_PD_RESTRICTDELEGATE ((TPM_CAPABILITY_AREA) 23) +#define TPM_PD_TPMDAASEED ((TPM_CAPABILITY_AREA) 24) +#define TPM_PD_DAAPROOF ((TPM_CAPABILITY_AREA) 25) + +/// +/// Part 2, section 7.5: TPM_STCLEAR_DATA +/// available inside TPM only +/// + typedef struct tdTPM_STCLEAR_DATA{ + TPM_STRUCTURE_TAG tag; + TPM_NONCE contextNonceKey; + TPM_COUNT_ID countID; + UINT32 ownerReference; + BOOLEAN disableResetLock; + TPM_PCRVALUE PCR[TPM_NUM_PCR]; + UINT32 deferredPhysicalPresence; + }TPM_STCLEAR_DATA; + +// +// Part 2, section 7.5.1: STCLEAR_DATA Subcap for SetCapability +// +#define TPM_SD_CONTEXTNONCEKEY ((TPM_CAPABILITY_AREA)0x00000001) +#define TPM_SD_COUNTID ((TPM_CAPABILITY_AREA)0x00000002) +#define TPM_SD_OWNERREFERENCE ((TPM_CAPABILITY_AREA)0x00000003) +#define TPM_SD_DISABLERESETLOCK ((TPM_CAPABILITY_AREA)0x00000004) +#define TPM_SD_PCR ((TPM_CAPABILITY_AREA)0x00000005) +#define TPM_SD_DEFERREDPHYSICALPRESENCE ((TPM_CAPABILITY_AREA)0x00000006) + +// +// Part 2, section 7.6.1: STANY_DATA Subcap for SetCapability +// +#define TPM_AD_CONTEXTNONCESESSION ((TPM_CAPABILITY_AREA) 1) +#define TPM_AD_AUDITDIGEST ((TPM_CAPABILITY_AREA) 2) +#define TPM_AD_CURRENTTICKS ((TPM_CAPABILITY_AREA) 3) +#define TPM_AD_CONTEXTCOUNT ((TPM_CAPABILITY_AREA) 4) +#define TPM_AD_CONTEXTLIST ((TPM_CAPABILITY_AREA) 5) +#define TPM_AD_SESSIONS ((TPM_CAPABILITY_AREA) 6) + +// +// Part 2, section 8: PCR Structures +// + +/// +/// Part 2, section 8.1: TPM_PCR_SELECTION +/// Size of pcrSelect[] indicated by sizeOfSelect +/// +typedef struct tdTPM_PCR_SELECTION { + UINT16 sizeOfSelect; + UINT8 pcrSelect[1]; +} TPM_PCR_SELECTION; + +/// +/// Part 2, section 8.2: TPM_PCR_COMPOSITE +/// Size of pcrValue[] indicated by valueSize +/// +typedef struct tdTPM_PCR_COMPOSITE { + TPM_PCR_SELECTION select; + UINT32 valueSize; + TPM_PCRVALUE pcrValue[1]; +} TPM_PCR_COMPOSITE; + +/// +/// Part 2, section 8.3: TPM_PCR_INFO +/// +typedef struct tdTPM_PCR_INFO { + TPM_PCR_SELECTION pcrSelection; + TPM_COMPOSITE_HASH digestAtRelease; + TPM_COMPOSITE_HASH digestAtCreation; +} TPM_PCR_INFO; + +/// +/// Part 2, section 8.6: TPM_LOCALITY_SELECTION +/// +typedef UINT8 TPM_LOCALITY_SELECTION; + +#define TPM_LOC_FOUR ((UINT8) 0x10) +#define TPM_LOC_THREE ((UINT8) 0x08) +#define TPM_LOC_TWO ((UINT8) 0x04) +#define TPM_LOC_ONE ((UINT8) 0x02) +#define TPM_LOC_ZERO ((UINT8) 0x01) + +/// +/// Part 2, section 8.4: TPM_PCR_INFO_LONG +/// +typedef struct tdTPM_PCR_INFO_LONG { + TPM_STRUCTURE_TAG tag; + TPM_LOCALITY_SELECTION localityAtCreation; + TPM_LOCALITY_SELECTION localityAtRelease; + TPM_PCR_SELECTION creationPCRSelection; + TPM_PCR_SELECTION releasePCRSelection; + TPM_COMPOSITE_HASH digestAtCreation; + TPM_COMPOSITE_HASH digestAtRelease; +} TPM_PCR_INFO_LONG; + +/// +/// Part 2, section 8.5: TPM_PCR_INFO_SHORT +/// +typedef struct tdTPM_PCR_INFO_SHORT{ + TPM_PCR_SELECTION pcrSelection; + TPM_LOCALITY_SELECTION localityAtRelease; + TPM_COMPOSITE_HASH digestAtRelease; +} TPM_PCR_INFO_SHORT; + +/// +/// Part 2, section 8.8: TPM_PCR_ATTRIBUTES +/// +typedef struct tdTPM_PCR_ATTRIBUTES{ + BOOLEAN pcrReset; + TPM_LOCALITY_SELECTION pcrExtendLocal; + TPM_LOCALITY_SELECTION pcrResetLocal; +} TPM_PCR_ATTRIBUTES; + +// +// Part 2, section 9: Storage Structures +// + +/// +/// Part 2, section 9.1: TPM_STORED_DATA +/// [size_is(sealInfoSize)] BYTE* sealInfo; +/// [size_is(encDataSize)] BYTE* encData; +/// +typedef struct tdTPM_STORED_DATA { + TPM_STRUCT_VER ver; + UINT32 sealInfoSize; + UINT8 *sealInfo; + UINT32 encDataSize; + UINT8 *encData; +} TPM_STORED_DATA; + +/// +/// Part 2, section 9.2: TPM_STORED_DATA12 +/// [size_is(sealInfoSize)] BYTE* sealInfo; +/// [size_is(encDataSize)] BYTE* encData; +/// +typedef struct tdTPM_STORED_DATA12 { + TPM_STRUCTURE_TAG tag; + TPM_ENTITY_TYPE et; + UINT32 sealInfoSize; + UINT8 *sealInfo; + UINT32 encDataSize; + UINT8 *encData; +} TPM_STORED_DATA12; + +/// +/// Part 2, section 9.3: TPM_SEALED_DATA +/// [size_is(dataSize)] BYTE* data; +/// +typedef struct tdTPM_SEALED_DATA { + TPM_PAYLOAD_TYPE payload; + TPM_SECRET authData; + TPM_NONCE tpmProof; + TPM_DIGEST storedDigest; + UINT32 dataSize; + UINT8 *data; +} TPM_SEALED_DATA; + +/// +/// Part 2, section 9.4: TPM_SYMMETRIC_KEY +/// [size_is(size)] BYTE* data; +/// +typedef struct tdTPM_SYMMETRIC_KEY { + TPM_ALGORITHM_ID algId; + TPM_ENC_SCHEME encScheme; + UINT16 dataSize; + UINT8 *data; +} TPM_SYMMETRIC_KEY; + +/// +/// Part 2, section 9.5: TPM_BOUND_DATA +/// +typedef struct tdTPM_BOUND_DATA { + TPM_STRUCT_VER ver; + TPM_PAYLOAD_TYPE payload; + UINT8 payloadData[1]; +} TPM_BOUND_DATA; + +// +// Part 2 section 10: TPM_KEY complex +// + +// +// Section 10.1, 10.4, and 10.5 have been defined previously +// + +/// +/// Part 2, section 10.2: TPM_KEY +/// [size_is(encDataSize)] BYTE* encData; +/// +typedef struct tdTPM_KEY{ + TPM_STRUCT_VER ver; + TPM_KEY_USAGE keyUsage; + TPM_KEY_FLAGS keyFlags; + TPM_AUTH_DATA_USAGE authDataUsage; + TPM_KEY_PARMS algorithmParms; + UINT32 PCRInfoSize; + UINT8 *PCRInfo; + TPM_STORE_PUBKEY pubKey; + UINT32 encDataSize; + UINT8 *encData; +} TPM_KEY; + +/// +/// Part 2, section 10.3: TPM_KEY12 +/// [size_is(encDataSize)] BYTE* encData; +/// +typedef struct tdTPM_KEY12{ + TPM_STRUCTURE_TAG tag; + UINT16 fill; + TPM_KEY_USAGE keyUsage; + TPM_KEY_FLAGS keyFlags; + TPM_AUTH_DATA_USAGE authDataUsage; + TPM_KEY_PARMS algorithmParms; + UINT32 PCRInfoSize; + UINT8 *PCRInfo; + TPM_STORE_PUBKEY pubKey; + UINT32 encDataSize; + UINT8 *encData; +} TPM_KEY12; + +/// +/// Part 2, section 10.7: TPM_STORE_PRIVKEY +/// [size_is(keyLength)] BYTE* key; +/// +typedef struct tdTPM_STORE_PRIVKEY { + UINT32 keyLength; + UINT8 *key; +} TPM_STORE_PRIVKEY; + +/// +/// Part 2, section 10.6: TPM_STORE_ASYMKEY +/// +typedef struct tdTPM_STORE_ASYMKEY { // pos len total + TPM_PAYLOAD_TYPE payload; // 0 1 1 + TPM_SECRET usageAuth; // 1 20 21 + TPM_SECRET migrationAuth; // 21 20 41 + TPM_DIGEST pubDataDigest; // 41 20 61 + TPM_STORE_PRIVKEY privKey; // 61 132-151 193-214 +} TPM_STORE_ASYMKEY; + +/// +/// Part 2, section 10.8: TPM_MIGRATE_ASYMKEY +/// [size_is(partPrivKeyLen)] BYTE* partPrivKey; +/// +typedef struct tdTPM_MIGRATE_ASYMKEY { // pos len total + TPM_PAYLOAD_TYPE payload; // 0 1 1 + TPM_SECRET usageAuth; // 1 20 21 + TPM_DIGEST pubDataDigest; // 21 20 41 + UINT32 partPrivKeyLen; // 41 4 45 + UINT8 *partPrivKey; // 45 112-127 157-172 +} TPM_MIGRATE_ASYMKEY; + +/// +/// Part 2, section 10.9: TPM_KEY_CONTROL +/// +#define TPM_KEY_CONTROL_OWNER_EVICT ((UINT32) 0x00000001) + +// +// Part 2, section 11: Signed Structures +// + +/// +/// Part 2, section 11.1: TPM_CERTIFY_INFO Structure +/// +typedef struct tdTPM_CERTIFY_INFO { + TPM_STRUCT_VER version; + TPM_KEY_USAGE keyUsage; + TPM_KEY_FLAGS keyFlags; + TPM_AUTH_DATA_USAGE authDataUsage; + TPM_KEY_PARMS algorithmParms; + TPM_DIGEST pubkeyDigest; + TPM_NONCE data; + BOOLEAN parentPCRStatus; + UINT32 PCRInfoSize; + UINT8 *PCRInfo; +} TPM_CERTIFY_INFO; + +/// +/// Part 2, section 11.2: TPM_CERTIFY_INFO2 Structure +/// +typedef struct tdTPM_CERTIFY_INFO2 { + TPM_STRUCTURE_TAG tag; + UINT8 fill; + TPM_PAYLOAD_TYPE payloadType; + TPM_KEY_USAGE keyUsage; + TPM_KEY_FLAGS keyFlags; + TPM_AUTH_DATA_USAGE authDataUsage; + TPM_KEY_PARMS algorithmParms; + TPM_DIGEST pubkeyDigest; + TPM_NONCE data; + BOOLEAN parentPCRStatus; + UINT32 PCRInfoSize; + UINT8 *PCRInfo; + UINT32 migrationAuthoritySize; + UINT8 *migrationAuthority; +} TPM_CERTIFY_INFO2; + +/// +/// Part 2, section 11.3 TPM_QUOTE_INFO Structure +/// +typedef struct tdTPM_QUOTE_INFO { + TPM_STRUCT_VER version; + UINT8 fixed[4]; + TPM_COMPOSITE_HASH digestValue; + TPM_NONCE externalData; +} TPM_QUOTE_INFO; + +/// +/// Part 2, section 11.4 TPM_QUOTE_INFO2 Structure +/// +typedef struct tdTPM_QUOTE_INFO2 { + TPM_STRUCTURE_TAG tag; + UINT8 fixed[4]; + TPM_NONCE externalData; + TPM_PCR_INFO_SHORT infoShort; +} TPM_QUOTE_INFO2; + +// +// Part 2, section 12: Identity Structures +// + +/// +/// Part 2, section 12.1 TPM_EK_BLOB +/// +typedef struct tdTPM_EK_BLOB { + TPM_STRUCTURE_TAG tag; + TPM_EK_TYPE ekType; + UINT32 blobSize; + UINT8 *blob; +} TPM_EK_BLOB; + +/// +/// Part 2, section 12.2 TPM_EK_BLOB_ACTIVATE +/// +typedef struct tdTPM_EK_BLOB_ACTIVATE { + TPM_STRUCTURE_TAG tag; + TPM_SYMMETRIC_KEY sessionKey; + TPM_DIGEST idDigest; + TPM_PCR_INFO_SHORT pcrInfo; +} TPM_EK_BLOB_ACTIVATE; + +/// +/// Part 2, section 12.3 TPM_EK_BLOB_AUTH +/// +typedef struct tdTPM_EK_BLOB_AUTH { + TPM_STRUCTURE_TAG tag; + TPM_SECRET authValue; +} TPM_EK_BLOB_AUTH; + + +/// +/// Part 2, section 12.5 TPM_IDENTITY_CONTENTS +/// +typedef struct tdTPM_IDENTITY_CONTENTS { + TPM_STRUCT_VER ver; + UINT32 ordinal; + TPM_CHOSENID_HASH labelPrivCADigest; + TPM_PUBKEY identityPubKey; +} TPM_IDENTITY_CONTENTS; + +/// +/// Part 2, section 12.6 TPM_IDENTITY_REQ +/// +typedef struct tdTPM_IDENTITY_REQ { + UINT32 asymSize; + UINT32 symSize; + TPM_KEY_PARMS asymAlgorithm; + TPM_KEY_PARMS symAlgorithm; + UINT8 *asymBlob; + UINT8 *symBlob; +} TPM_IDENTITY_REQ; + +/// +/// Part 2, section 12.7 TPM_IDENTITY_PROOF +/// +typedef struct tdTPM_IDENTITY_PROOF { + TPM_STRUCT_VER ver; + UINT32 labelSize; + UINT32 identityBindingSize; + UINT32 endorsementSize; + UINT32 platformSize; + UINT32 conformanceSize; + TPM_PUBKEY identityKey; + UINT8 *labelArea; + UINT8 *identityBinding; + UINT8 *endorsementCredential; + UINT8 *platformCredential; + UINT8 *conformanceCredential; +} TPM_IDENTITY_PROOF; + +/// +/// Part 2, section 12.8 TPM_ASYM_CA_CONTENTS +/// +typedef struct tdTPM_ASYM_CA_CONTENTS { + TPM_SYMMETRIC_KEY sessionKey; + TPM_DIGEST idDigest; +} TPM_ASYM_CA_CONTENTS; + +/// +/// Part 2, section 12.9 TPM_SYM_CA_ATTESTATION +/// +typedef struct tdTPM_SYM_CA_ATTESTATION { + UINT32 credSize; + TPM_KEY_PARMS algorithm; + UINT8 *credential; +} TPM_SYM_CA_ATTESTATION; + +/// +/// Part 2, section 15: Tick Structures +/// Placed here out of order because definitions are used in section 13. +/// +typedef struct tdTPM_CURRENT_TICKS { + TPM_STRUCTURE_TAG tag; + UINT64 currentTicks; + UINT16 tickRate; + TPM_NONCE tickNonce; +} TPM_CURRENT_TICKS; + +/// +/// Part 2, section 13: Transport structures +/// + +/// +/// Part 2, section 13.1: TPM _TRANSPORT_PUBLIC +/// +typedef struct tdTPM_TRANSPORT_PUBLIC { + TPM_STRUCTURE_TAG tag; + TPM_TRANSPORT_ATTRIBUTES transAttributes; + TPM_ALGORITHM_ID algId; + TPM_ENC_SCHEME encScheme; +} TPM_TRANSPORT_PUBLIC; + +// +// Part 2, section 13.1.1 TPM_TRANSPORT_ATTRIBUTES Definitions +// +#define TPM_TRANSPORT_ENCRYPT ((UINT32)BIT0) +#define TPM_TRANSPORT_LOG ((UINT32)BIT1) +#define TPM_TRANSPORT_EXCLUSIVE ((UINT32)BIT2) + +/// +/// Part 2, section 13.2 TPM_TRANSPORT_INTERNAL +/// +typedef struct tdTPM_TRANSPORT_INTERNAL { + TPM_STRUCTURE_TAG tag; + TPM_AUTHDATA authData; + TPM_TRANSPORT_PUBLIC transPublic; + TPM_TRANSHANDLE transHandle; + TPM_NONCE transNonceEven; + TPM_DIGEST transDigest; +} TPM_TRANSPORT_INTERNAL; + +/// +/// Part 2, section 13.3 TPM_TRANSPORT_LOG_IN structure +/// +typedef struct tdTPM_TRANSPORT_LOG_IN { + TPM_STRUCTURE_TAG tag; + TPM_DIGEST parameters; + TPM_DIGEST pubKeyHash; +} TPM_TRANSPORT_LOG_IN; + +/// +/// Part 2, section 13.4 TPM_TRANSPORT_LOG_OUT structure +/// +typedef struct tdTPM_TRANSPORT_LOG_OUT { + TPM_STRUCTURE_TAG tag; + TPM_CURRENT_TICKS currentTicks; + TPM_DIGEST parameters; + TPM_MODIFIER_INDICATOR locality; +} TPM_TRANSPORT_LOG_OUT; + +/// +/// Part 2, section 13.5 TPM_TRANSPORT_AUTH structure +/// +typedef struct tdTPM_TRANSPORT_AUTH { + TPM_STRUCTURE_TAG tag; + TPM_AUTHDATA authData; +} TPM_TRANSPORT_AUTH; + +// +// Part 2, section 14: Audit Structures +// + +/// +/// Part 2, section 14.1 TPM_AUDIT_EVENT_IN structure +/// +typedef struct tdTPM_AUDIT_EVENT_IN { + TPM_STRUCTURE_TAG tag; + TPM_DIGEST inputParms; + TPM_COUNTER_VALUE auditCount; +} TPM_AUDIT_EVENT_IN; + +/// +/// Part 2, section 14.2 TPM_AUDIT_EVENT_OUT structure +/// +typedef struct tdTPM_AUDIT_EVENT_OUT { + TPM_STRUCTURE_TAG tag; + TPM_COMMAND_CODE ordinal; + TPM_DIGEST outputParms; + TPM_COUNTER_VALUE auditCount; + TPM_RESULT returnCode; +} TPM_AUDIT_EVENT_OUT; + +// +// Part 2, section 16: Return Codes +// + +#define TPM_VENDOR_ERROR TPM_Vendor_Specific32 +#define TPM_NON_FATAL 0x00000800 + +#define TPM_SUCCESS ((TPM_RESULT) TPM_BASE) +#define TPM_AUTHFAIL ((TPM_RESULT) (TPM_BASE + 1)) +#define TPM_BADINDEX ((TPM_RESULT) (TPM_BASE + 2)) +#define TPM_BAD_PARAMETER ((TPM_RESULT) (TPM_BASE + 3)) +#define TPM_AUDITFAILURE ((TPM_RESULT) (TPM_BASE + 4)) +#define TPM_CLEAR_DISABLED ((TPM_RESULT) (TPM_BASE + 5)) +#define TPM_DEACTIVATED ((TPM_RESULT) (TPM_BASE + 6)) +#define TPM_DISABLED ((TPM_RESULT) (TPM_BASE + 7)) +#define TPM_DISABLED_CMD ((TPM_RESULT) (TPM_BASE + 8)) +#define TPM_FAIL ((TPM_RESULT) (TPM_BASE + 9)) +#define TPM_BAD_ORDINAL ((TPM_RESULT) (TPM_BASE + 10)) +#define TPM_INSTALL_DISABLED ((TPM_RESULT) (TPM_BASE + 11)) +#define TPM_INVALID_KEYHANDLE ((TPM_RESULT) (TPM_BASE + 12)) +#define TPM_KEYNOTFOUND ((TPM_RESULT) (TPM_BASE + 13)) +#define TPM_INAPPROPRIATE_ENC ((TPM_RESULT) (TPM_BASE + 14)) +#define TPM_MIGRATEFAIL ((TPM_RESULT) (TPM_BASE + 15)) +#define TPM_INVALID_PCR_INFO ((TPM_RESULT) (TPM_BASE + 16)) +#define TPM_NOSPACE ((TPM_RESULT) (TPM_BASE + 17)) +#define TPM_NOSRK ((TPM_RESULT) (TPM_BASE + 18)) +#define TPM_NOTSEALED_BLOB ((TPM_RESULT) (TPM_BASE + 19)) +#define TPM_OWNER_SET ((TPM_RESULT) (TPM_BASE + 20)) +#define TPM_RESOURCES ((TPM_RESULT) (TPM_BASE + 21)) +#define TPM_SHORTRANDOM ((TPM_RESULT) (TPM_BASE + 22)) +#define TPM_SIZE ((TPM_RESULT) (TPM_BASE + 23)) +#define TPM_WRONGPCRVAL ((TPM_RESULT) (TPM_BASE + 24)) +#define TPM_BAD_PARAM_SIZE ((TPM_RESULT) (TPM_BASE + 25)) +#define TPM_SHA_THREAD ((TPM_RESULT) (TPM_BASE + 26)) +#define TPM_SHA_ERROR ((TPM_RESULT) (TPM_BASE + 27)) +#define TPM_FAILEDSELFTEST ((TPM_RESULT) (TPM_BASE + 28)) +#define TPM_AUTH2FAIL ((TPM_RESULT) (TPM_BASE + 29)) +#define TPM_BADTAG ((TPM_RESULT) (TPM_BASE + 30)) +#define TPM_IOERROR ((TPM_RESULT) (TPM_BASE + 31)) +#define TPM_ENCRYPT_ERROR ((TPM_RESULT) (TPM_BASE + 32)) +#define TPM_DECRYPT_ERROR ((TPM_RESULT) (TPM_BASE + 33)) +#define TPM_INVALID_AUTHHANDLE ((TPM_RESULT) (TPM_BASE + 34)) +#define TPM_NO_ENDORSEMENT ((TPM_RESULT) (TPM_BASE + 35)) +#define TPM_INVALID_KEYUSAGE ((TPM_RESULT) (TPM_BASE + 36)) +#define TPM_WRONG_ENTITYTYPE ((TPM_RESULT) (TPM_BASE + 37)) +#define TPM_INVALID_POSTINIT ((TPM_RESULT) (TPM_BASE + 38)) +#define TPM_INAPPROPRIATE_SIG ((TPM_RESULT) (TPM_BASE + 39)) +#define TPM_BAD_KEY_PROPERTY ((TPM_RESULT) (TPM_BASE + 40)) +#define TPM_BAD_MIGRATION ((TPM_RESULT) (TPM_BASE + 41)) +#define TPM_BAD_SCHEME ((TPM_RESULT) (TPM_BASE + 42)) +#define TPM_BAD_DATASIZE ((TPM_RESULT) (TPM_BASE + 43)) +#define TPM_BAD_MODE ((TPM_RESULT) (TPM_BASE + 44)) +#define TPM_BAD_PRESENCE ((TPM_RESULT) (TPM_BASE + 45)) +#define TPM_BAD_VERSION ((TPM_RESULT) (TPM_BASE + 46)) +#define TPM_NO_WRAP_TRANSPORT ((TPM_RESULT) (TPM_BASE + 47)) +#define TPM_AUDITFAIL_UNSUCCESSFUL ((TPM_RESULT) (TPM_BASE + 48)) +#define TPM_AUDITFAIL_SUCCESSFUL ((TPM_RESULT) (TPM_BASE + 49)) +#define TPM_NOTRESETABLE ((TPM_RESULT) (TPM_BASE + 50)) +#define TPM_NOTLOCAL ((TPM_RESULT) (TPM_BASE + 51)) +#define TPM_BAD_TYPE ((TPM_RESULT) (TPM_BASE + 52)) +#define TPM_INVALID_RESOURCE ((TPM_RESULT) (TPM_BASE + 53)) +#define TPM_NOTFIPS ((TPM_RESULT) (TPM_BASE + 54)) +#define TPM_INVALID_FAMILY ((TPM_RESULT) (TPM_BASE + 55)) +#define TPM_NO_NV_PERMISSION ((TPM_RESULT) (TPM_BASE + 56)) +#define TPM_REQUIRES_SIGN ((TPM_RESULT) (TPM_BASE + 57)) +#define TPM_KEY_NOTSUPPORTED ((TPM_RESULT) (TPM_BASE + 58)) +#define TPM_AUTH_CONFLICT ((TPM_RESULT) (TPM_BASE + 59)) +#define TPM_AREA_LOCKED ((TPM_RESULT) (TPM_BASE + 60)) +#define TPM_BAD_LOCALITY ((TPM_RESULT) (TPM_BASE + 61)) +#define TPM_READ_ONLY ((TPM_RESULT) (TPM_BASE + 62)) +#define TPM_PER_NOWRITE ((TPM_RESULT) (TPM_BASE + 63)) +#define TPM_FAMILYCOUNT ((TPM_RESULT) (TPM_BASE + 64)) +#define TPM_WRITE_LOCKED ((TPM_RESULT) (TPM_BASE + 65)) +#define TPM_BAD_ATTRIBUTES ((TPM_RESULT) (TPM_BASE + 66)) +#define TPM_INVALID_STRUCTURE ((TPM_RESULT) (TPM_BASE + 67)) +#define TPM_KEY_OWNER_CONTROL ((TPM_RESULT) (TPM_BASE + 68)) +#define TPM_BAD_COUNTER ((TPM_RESULT) (TPM_BASE + 69)) +#define TPM_NOT_FULLWRITE ((TPM_RESULT) (TPM_BASE + 70)) +#define TPM_CONTEXT_GAP ((TPM_RESULT) (TPM_BASE + 71)) +#define TPM_MAXNVWRITES ((TPM_RESULT) (TPM_BASE + 72)) +#define TPM_NOOPERATOR ((TPM_RESULT) (TPM_BASE + 73)) +#define TPM_RESOURCEMISSING ((TPM_RESULT) (TPM_BASE + 74)) +#define TPM_DELEGATE_LOCK ((TPM_RESULT) (TPM_BASE + 75)) +#define TPM_DELEGATE_FAMILY ((TPM_RESULT) (TPM_BASE + 76)) +#define TPM_DELEGATE_ADMIN ((TPM_RESULT) (TPM_BASE + 77)) +#define TPM_TRANSPORT_NOTEXCLUSIVE ((TPM_RESULT) (TPM_BASE + 78)) +#define TPM_OWNER_CONTROL ((TPM_RESULT) (TPM_BASE + 79)) +#define TPM_DAA_RESOURCES ((TPM_RESULT) (TPM_BASE + 80)) +#define TPM_DAA_INPUT_DATA0 ((TPM_RESULT) (TPM_BASE + 81)) +#define TPM_DAA_INPUT_DATA1 ((TPM_RESULT) (TPM_BASE + 82)) +#define TPM_DAA_ISSUER_SETTINGS ((TPM_RESULT) (TPM_BASE + 83)) +#define TPM_DAA_TPM_SETTINGS ((TPM_RESULT) (TPM_BASE + 84)) +#define TPM_DAA_STAGE ((TPM_RESULT) (TPM_BASE + 85)) +#define TPM_DAA_ISSUER_VALIDITY ((TPM_RESULT) (TPM_BASE + 86)) +#define TPM_DAA_WRONG_W ((TPM_RESULT) (TPM_BASE + 87)) +#define TPM_BAD_HANDLE ((TPM_RESULT) (TPM_BASE + 88)) +#define TPM_BAD_DELEGATE ((TPM_RESULT) (TPM_BASE + 89)) +#define TPM_BADCONTEXT ((TPM_RESULT) (TPM_BASE + 90)) +#define TPM_TOOMANYCONTEXTS ((TPM_RESULT) (TPM_BASE + 91)) +#define TPM_MA_TICKET_SIGNATURE ((TPM_RESULT) (TPM_BASE + 92)) +#define TPM_MA_DESTINATION ((TPM_RESULT) (TPM_BASE + 93)) +#define TPM_MA_SOURCE ((TPM_RESULT) (TPM_BASE + 94)) +#define TPM_MA_AUTHORITY ((TPM_RESULT) (TPM_BASE + 95)) +#define TPM_PERMANENTEK ((TPM_RESULT) (TPM_BASE + 97)) +#define TPM_BAD_SIGNATURE ((TPM_RESULT) (TPM_BASE + 98)) +#define TPM_NOCONTEXTSPACE ((TPM_RESULT) (TPM_BASE + 99)) + +#define TPM_RETRY ((TPM_RESULT) (TPM_BASE + TPM_NON_FATAL)) +#define TPM_NEEDS_SELFTEST ((TPM_RESULT) (TPM_BASE + TPM_NON_FATAL + 1)) +#define TPM_DOING_SELFTEST ((TPM_RESULT) (TPM_BASE + TPM_NON_FATAL + 2)) +#define TPM_DEFEND_LOCK_RUNNING ((TPM_RESULT) (TPM_BASE + TPM_NON_FATAL + 3)) + +// +// Part 2, section 17: Ordinals +// +// Ordinals are 32 bit values. The upper byte contains values that serve as +// flag indicators, the next byte contains values indicating what committee +// designated the ordinal, and the final two bytes contain the Command +// Ordinal Index. +// 3 2 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |P|C|V| Reserved| Purview | Command Ordinal Index | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Where: +// +// * P is Protected/Unprotected command. When 0 the command is a Protected +// command, when 1 the command is an Unprotected command. +// +// * C is Non-Connection/Connection related command. When 0 this command +// passes through to either the protected (TPM) or unprotected (TSS) +// components. +// +// * V is TPM/Vendor command. When 0 the command is TPM defined, when 1 the +// command is vendor defined. +// +// * All reserved area bits are set to 0. +// + +#define TPM_ORD_ActivateIdentity ((TPM_COMMAND_CODE) 0x0000007A) +#define TPM_ORD_AuthorizeMigrationKey ((TPM_COMMAND_CODE) 0x0000002B) +#define TPM_ORD_CertifyKey ((TPM_COMMAND_CODE) 0x00000032) +#define TPM_ORD_CertifyKey2 ((TPM_COMMAND_CODE) 0x00000033) +#define TPM_ORD_CertifySelfTest ((TPM_COMMAND_CODE) 0x00000052) +#define TPM_ORD_ChangeAuth ((TPM_COMMAND_CODE) 0x0000000C) +#define TPM_ORD_ChangeAuthAsymFinish ((TPM_COMMAND_CODE) 0x0000000F) +#define TPM_ORD_ChangeAuthAsymStart ((TPM_COMMAND_CODE) 0x0000000E) +#define TPM_ORD_ChangeAuthOwner ((TPM_COMMAND_CODE) 0x00000010) +#define TPM_ORD_CMK_ApproveMA ((TPM_COMMAND_CODE) 0x0000001D) +#define TPM_ORD_CMK_ConvertMigration ((TPM_COMMAND_CODE) 0x00000024) +#define TPM_ORD_CMK_CreateBlob ((TPM_COMMAND_CODE) 0x0000001B) +#define TPM_ORD_CMK_CreateKey ((TPM_COMMAND_CODE) 0x00000013) +#define TPM_ORD_CMK_CreateTicket ((TPM_COMMAND_CODE) 0x00000012) +#define TPM_ORD_CMK_SetRestrictions ((TPM_COMMAND_CODE) 0x0000001C) +#define TPM_ORD_ContinueSelfTest ((TPM_COMMAND_CODE) 0x00000053) +#define TPM_ORD_ConvertMigrationBlob ((TPM_COMMAND_CODE) 0x0000002A) +#define TPM_ORD_CreateCounter ((TPM_COMMAND_CODE) 0x000000DC) +#define TPM_ORD_CreateEndorsementKeyPair ((TPM_COMMAND_CODE) 0x00000078) +#define TPM_ORD_CreateMaintenanceArchive ((TPM_COMMAND_CODE) 0x0000002C) +#define TPM_ORD_CreateMigrationBlob ((TPM_COMMAND_CODE) 0x00000028) +#define TPM_ORD_CreateRevocableEK ((TPM_COMMAND_CODE) 0x0000007F) +#define TPM_ORD_CreateWrapKey ((TPM_COMMAND_CODE) 0x0000001F) +#define TPM_ORD_DAA_JOIN ((TPM_COMMAND_CODE) 0x00000029) +#define TPM_ORD_DAA_SIGN ((TPM_COMMAND_CODE) 0x00000031) +#define TPM_ORD_Delegate_CreateKeyDelegation ((TPM_COMMAND_CODE) 0x000000D4) +#define TPM_ORD_Delegate_CreateOwnerDelegation ((TPM_COMMAND_CODE) 0x000000D5) +#define TPM_ORD_Delegate_LoadOwnerDelegation ((TPM_COMMAND_CODE) 0x000000D8) +#define TPM_ORD_Delegate_Manage ((TPM_COMMAND_CODE) 0x000000D2) +#define TPM_ORD_Delegate_ReadTable ((TPM_COMMAND_CODE) 0x000000DB) +#define TPM_ORD_Delegate_UpdateVerification ((TPM_COMMAND_CODE) 0x000000D1) +#define TPM_ORD_Delegate_VerifyDelegation ((TPM_COMMAND_CODE) 0x000000D6) +#define TPM_ORD_DirRead ((TPM_COMMAND_CODE) 0x0000001A) +#define TPM_ORD_DirWriteAuth ((TPM_COMMAND_CODE) 0x00000019) +#define TPM_ORD_DisableForceClear ((TPM_COMMAND_CODE) 0x0000005E) +#define TPM_ORD_DisableOwnerClear ((TPM_COMMAND_CODE) 0x0000005C) +#define TPM_ORD_DisablePubekRead ((TPM_COMMAND_CODE) 0x0000007E) +#define TPM_ORD_DSAP ((TPM_COMMAND_CODE) 0x00000011) +#define TPM_ORD_EstablishTransport ((TPM_COMMAND_CODE) 0x000000E6) +#define TPM_ORD_EvictKey ((TPM_COMMAND_CODE) 0x00000022) +#define TPM_ORD_ExecuteTransport ((TPM_COMMAND_CODE) 0x000000E7) +#define TPM_ORD_Extend ((TPM_COMMAND_CODE) 0x00000014) +#define TPM_ORD_FieldUpgrade ((TPM_COMMAND_CODE) 0x000000AA) +#define TPM_ORD_FlushSpecific ((TPM_COMMAND_CODE) 0x000000BA) +#define TPM_ORD_ForceClear ((TPM_COMMAND_CODE) 0x0000005D) +#define TPM_ORD_GetAuditDigest ((TPM_COMMAND_CODE) 0x00000085) +#define TPM_ORD_GetAuditDigestSigned ((TPM_COMMAND_CODE) 0x00000086) +#define TPM_ORD_GetAuditEvent ((TPM_COMMAND_CODE) 0x00000082) +#define TPM_ORD_GetAuditEventSigned ((TPM_COMMAND_CODE) 0x00000083) +#define TPM_ORD_GetCapability ((TPM_COMMAND_CODE) 0x00000065) +#define TPM_ORD_GetCapabilityOwner ((TPM_COMMAND_CODE) 0x00000066) +#define TPM_ORD_GetCapabilitySigned ((TPM_COMMAND_CODE) 0x00000064) +#define TPM_ORD_GetOrdinalAuditStatus ((TPM_COMMAND_CODE) 0x0000008C) +#define TPM_ORD_GetPubKey ((TPM_COMMAND_CODE) 0x00000021) +#define TPM_ORD_GetRandom ((TPM_COMMAND_CODE) 0x00000046) +#define TPM_ORD_GetTestResult ((TPM_COMMAND_CODE) 0x00000054) +#define TPM_ORD_GetTicks ((TPM_COMMAND_CODE) 0x000000F1) +#define TPM_ORD_IncrementCounter ((TPM_COMMAND_CODE) 0x000000DD) +#define TPM_ORD_Init ((TPM_COMMAND_CODE) 0x00000097) +#define TPM_ORD_KeyControlOwner ((TPM_COMMAND_CODE) 0x00000023) +#define TPM_ORD_KillMaintenanceFeature ((TPM_COMMAND_CODE) 0x0000002E) +#define TPM_ORD_LoadAuthContext ((TPM_COMMAND_CODE) 0x000000B7) +#define TPM_ORD_LoadContext ((TPM_COMMAND_CODE) 0x000000B9) +#define TPM_ORD_LoadKey ((TPM_COMMAND_CODE) 0x00000020) +#define TPM_ORD_LoadKey2 ((TPM_COMMAND_CODE) 0x00000041) +#define TPM_ORD_LoadKeyContext ((TPM_COMMAND_CODE) 0x000000B5) +#define TPM_ORD_LoadMaintenanceArchive ((TPM_COMMAND_CODE) 0x0000002D) +#define TPM_ORD_LoadManuMaintPub ((TPM_COMMAND_CODE) 0x0000002F) +#define TPM_ORD_MakeIdentity ((TPM_COMMAND_CODE) 0x00000079) +#define TPM_ORD_MigrateKey ((TPM_COMMAND_CODE) 0x00000025) +#define TPM_ORD_NV_DefineSpace ((TPM_COMMAND_CODE) 0x000000CC) +#define TPM_ORD_NV_ReadValue ((TPM_COMMAND_CODE) 0x000000CF) +#define TPM_ORD_NV_ReadValueAuth ((TPM_COMMAND_CODE) 0x000000D0) +#define TPM_ORD_NV_WriteValue ((TPM_COMMAND_CODE) 0x000000CD) +#define TPM_ORD_NV_WriteValueAuth ((TPM_COMMAND_CODE) 0x000000CE) +#define TPM_ORD_OIAP ((TPM_COMMAND_CODE) 0x0000000A) +#define TPM_ORD_OSAP ((TPM_COMMAND_CODE) 0x0000000B) +#define TPM_ORD_OwnerClear ((TPM_COMMAND_CODE) 0x0000005B) +#define TPM_ORD_OwnerReadInternalPub ((TPM_COMMAND_CODE) 0x00000081) +#define TPM_ORD_OwnerReadPubek ((TPM_COMMAND_CODE) 0x0000007D) +#define TPM_ORD_OwnerSetDisable ((TPM_COMMAND_CODE) 0x0000006E) +#define TPM_ORD_PCR_Reset ((TPM_COMMAND_CODE) 0x000000C8) +#define TPM_ORD_PcrRead ((TPM_COMMAND_CODE) 0x00000015) +#define TPM_ORD_PhysicalDisable ((TPM_COMMAND_CODE) 0x00000070) +#define TPM_ORD_PhysicalEnable ((TPM_COMMAND_CODE) 0x0000006F) +#define TPM_ORD_PhysicalSetDeactivated ((TPM_COMMAND_CODE) 0x00000072) +#define TPM_ORD_Quote ((TPM_COMMAND_CODE) 0x00000016) +#define TPM_ORD_Quote2 ((TPM_COMMAND_CODE) 0x0000003E) +#define TPM_ORD_ReadCounter ((TPM_COMMAND_CODE) 0x000000DE) +#define TPM_ORD_ReadManuMaintPub ((TPM_COMMAND_CODE) 0x00000030) +#define TPM_ORD_ReadPubek ((TPM_COMMAND_CODE) 0x0000007C) +#define TPM_ORD_ReleaseCounter ((TPM_COMMAND_CODE) 0x000000DF) +#define TPM_ORD_ReleaseCounterOwner ((TPM_COMMAND_CODE) 0x000000E0) +#define TPM_ORD_ReleaseTransportSigned ((TPM_COMMAND_CODE) 0x000000E8) +#define TPM_ORD_Reset ((TPM_COMMAND_CODE) 0x0000005A) +#define TPM_ORD_ResetLockValue ((TPM_COMMAND_CODE) 0x00000040) +#define TPM_ORD_RevokeTrust ((TPM_COMMAND_CODE) 0x00000080) +#define TPM_ORD_SaveAuthContext ((TPM_COMMAND_CODE) 0x000000B6) +#define TPM_ORD_SaveContext ((TPM_COMMAND_CODE) 0x000000B8) +#define TPM_ORD_SaveKeyContext ((TPM_COMMAND_CODE) 0x000000B4) +#define TPM_ORD_SaveState ((TPM_COMMAND_CODE) 0x00000098) +#define TPM_ORD_Seal ((TPM_COMMAND_CODE) 0x00000017) +#define TPM_ORD_Sealx ((TPM_COMMAND_CODE) 0x0000003D) +#define TPM_ORD_SelfTestFull ((TPM_COMMAND_CODE) 0x00000050) +#define TPM_ORD_SetCapability ((TPM_COMMAND_CODE) 0x0000003F) +#define TPM_ORD_SetOperatorAuth ((TPM_COMMAND_CODE) 0x00000074) +#define TPM_ORD_SetOrdinalAuditStatus ((TPM_COMMAND_CODE) 0x0000008D) +#define TPM_ORD_SetOwnerInstall ((TPM_COMMAND_CODE) 0x00000071) +#define TPM_ORD_SetOwnerPointer ((TPM_COMMAND_CODE) 0x00000075) +#define TPM_ORD_SetRedirection ((TPM_COMMAND_CODE) 0x0000009A) +#define TPM_ORD_SetTempDeactivated ((TPM_COMMAND_CODE) 0x00000073) +#define TPM_ORD_SHA1Complete ((TPM_COMMAND_CODE) 0x000000A2) +#define TPM_ORD_SHA1CompleteExtend ((TPM_COMMAND_CODE) 0x000000A3) +#define TPM_ORD_SHA1Start ((TPM_COMMAND_CODE) 0x000000A0) +#define TPM_ORD_SHA1Update ((TPM_COMMAND_CODE) 0x000000A1) +#define TPM_ORD_Sign ((TPM_COMMAND_CODE) 0x0000003C) +#define TPM_ORD_Startup ((TPM_COMMAND_CODE) 0x00000099) +#define TPM_ORD_StirRandom ((TPM_COMMAND_CODE) 0x00000047) +#define TPM_ORD_TakeOwnership ((TPM_COMMAND_CODE) 0x0000000D) +#define TPM_ORD_Terminate_Handle ((TPM_COMMAND_CODE) 0x00000096) +#define TPM_ORD_TickStampBlob ((TPM_COMMAND_CODE) 0x000000F2) +#define TPM_ORD_UnBind ((TPM_COMMAND_CODE) 0x0000001E) +#define TPM_ORD_Unseal ((TPM_COMMAND_CODE) 0x00000018) +#define TSC_ORD_PhysicalPresence ((TPM_COMMAND_CODE) 0x4000000A) +#define TSC_ORD_ResetEstablishmentBit ((TPM_COMMAND_CODE) 0x4000000B) + +// +// Part 2, section 18: Context structures +// + +/// +/// Part 2, section 18.1: TPM_CONTEXT_BLOB +/// +typedef struct tdTPM_CONTEXT_BLOB { + TPM_STRUCTURE_TAG tag; + TPM_RESOURCE_TYPE resourceType; + TPM_HANDLE handle; + UINT8 label[16]; + UINT32 contextCount; + TPM_DIGEST integrityDigest; + UINT32 additionalSize; + UINT8 *additionalData; + UINT32 sensitiveSize; + UINT8 *sensitiveData; +} TPM_CONTEXT_BLOB; + +/// +/// Part 2, section 18.2 TPM_CONTEXT_SENSITIVE +/// +typedef struct tdTPM_CONTEXT_SENSITIVE { + TPM_STRUCTURE_TAG tag; + TPM_NONCE contextNonce; + UINT32 internalSize; + UINT8 *internalData; +} TPM_CONTEXT_SENSITIVE; + +// +// Part 2, section 19: NV Structures +// + +// +// Part 2, section 19.1.1: Required TPM_NV_INDEX values +// +#define TPM_NV_INDEX_LOCK ((UINT32)0xffffffff) +#define TPM_NV_INDEX0 ((UINT32)0x00000000) +#define TPM_NV_INDEX_DIR ((UINT32)0x10000001) +#define TPM_NV_INDEX_EKCert ((UINT32)0x0000f000) +#define TPM_NV_INDEX_TPM_CC ((UINT32)0x0000f001) +#define TPM_NV_INDEX_PlatformCert ((UINT32)0x0000f002) +#define TPM_NV_INDEX_Platform_CC ((UINT32)0x0000f003) +// +// Part 2, section 19.1.2: Reserved Index values +// +#define TPM_NV_INDEX_TSS_BASE ((UINT32)0x00011100) +#define TPM_NV_INDEX_PC_BASE ((UINT32)0x00011200) +#define TPM_NV_INDEX_SERVER_BASE ((UINT32)0x00011300) +#define TPM_NV_INDEX_MOBILE_BASE ((UINT32)0x00011400) +#define TPM_NV_INDEX_PERIPHERAL_BASE ((UINT32)0x00011500) +#define TPM_NV_INDEX_GROUP_RESV_BASE ((UINT32)0x00010000) + +/// +/// Part 2, section 19.2: TPM_NV_ATTRIBUTES +/// +typedef struct tdTPM_NV_ATTRIBUTES { + TPM_STRUCTURE_TAG tag; + UINT32 attributes; +} TPM_NV_ATTRIBUTES; + +#define TPM_NV_PER_READ_STCLEAR (BIT31) +#define TPM_NV_PER_AUTHREAD (BIT18) +#define TPM_NV_PER_OWNERREAD (BIT17) +#define TPM_NV_PER_PPREAD (BIT16) +#define TPM_NV_PER_GLOBALLOCK (BIT15) +#define TPM_NV_PER_WRITE_STCLEAR (BIT14) +#define TPM_NV_PER_WRITEDEFINE (BIT13) +#define TPM_NV_PER_WRITEALL (BIT12) +#define TPM_NV_PER_AUTHWRITE (BIT2) +#define TPM_NV_PER_OWNERWRITE (BIT1) +#define TPM_NV_PER_PPWRITE (BIT0) + +/// +/// Part 2, section 19.3: TPM_NV_DATA_PUBLIC +/// +typedef struct tdTPM_NV_DATA_PUBLIC { + TPM_STRUCTURE_TAG tag; + TPM_NV_INDEX nvIndex; + TPM_PCR_INFO_SHORT pcrInfoRead; + TPM_PCR_INFO_SHORT pcrInfoWrite; + TPM_NV_ATTRIBUTES permission; + BOOLEAN bReadSTClear; + BOOLEAN bWriteSTClear; + BOOLEAN bWriteDefine; + UINT32 dataSize; +} TPM_NV_DATA_PUBLIC; + +// +// Part 2, section 20: Delegate Structures +// + +#define TPM_DEL_OWNER_BITS ((UINT32)0x00000001) +#define TPM_DEL_KEY_BITS ((UINT32)0x00000002) +/// +/// Part 2, section 20.2: Delegate Definitions +/// +typedef struct tdTPM_DELEGATIONS { + TPM_STRUCTURE_TAG tag; + UINT32 delegateType; + UINT32 per1; + UINT32 per2; +} TPM_DELEGATIONS; + +// +// Part 2, section 20.2.1: Owner Permission Settings +// +#define TPM_DELEGATE_SetOrdinalAuditStatus (BIT30) +#define TPM_DELEGATE_DirWriteAuth (BIT29) +#define TPM_DELEGATE_CMK_ApproveMA (BIT28) +#define TPM_DELEGATE_NV_WriteValue (BIT27) +#define TPM_DELEGATE_CMK_CreateTicket (BIT26) +#define TPM_DELEGATE_NV_ReadValue (BIT25) +#define TPM_DELEGATE_Delegate_LoadOwnerDelegation (BIT24) +#define TPM_DELEGATE_DAA_Join (BIT23) +#define TPM_DELEGATE_AuthorizeMigrationKey (BIT22) +#define TPM_DELEGATE_CreateMaintenanceArchive (BIT21) +#define TPM_DELEGATE_LoadMaintenanceArchive (BIT20) +#define TPM_DELEGATE_KillMaintenanceFeature (BIT19) +#define TPM_DELEGATE_OwnerReadInteralPub (BIT18) +#define TPM_DELEGATE_ResetLockValue (BIT17) +#define TPM_DELEGATE_OwnerClear (BIT16) +#define TPM_DELEGATE_DisableOwnerClear (BIT15) +#define TPM_DELEGATE_NV_DefineSpace (BIT14) +#define TPM_DELEGATE_OwnerSetDisable (BIT13) +#define TPM_DELEGATE_SetCapability (BIT12) +#define TPM_DELEGATE_MakeIdentity (BIT11) +#define TPM_DELEGATE_ActivateIdentity (BIT10) +#define TPM_DELEGATE_OwnerReadPubek (BIT9) +#define TPM_DELEGATE_DisablePubekRead (BIT8) +#define TPM_DELEGATE_SetRedirection (BIT7) +#define TPM_DELEGATE_FieldUpgrade (BIT6) +#define TPM_DELEGATE_Delegate_UpdateVerification (BIT5) +#define TPM_DELEGATE_CreateCounter (BIT4) +#define TPM_DELEGATE_ReleaseCounterOwner (BIT3) +#define TPM_DELEGATE_DelegateManage (BIT2) +#define TPM_DELEGATE_Delegate_CreateOwnerDelegation (BIT1) +#define TPM_DELEGATE_DAA_Sign (BIT0) + +// +// Part 2, section 20.2.3: Key Permission settings +// +#define TPM_KEY_DELEGATE_CMK_ConvertMigration (BIT28) +#define TPM_KEY_DELEGATE_TickStampBlob (BIT27) +#define TPM_KEY_DELEGATE_ChangeAuthAsymStart (BIT26) +#define TPM_KEY_DELEGATE_ChangeAuthAsymFinish (BIT25) +#define TPM_KEY_DELEGATE_CMK_CreateKey (BIT24) +#define TPM_KEY_DELEGATE_MigrateKey (BIT23) +#define TPM_KEY_DELEGATE_LoadKey2 (BIT22) +#define TPM_KEY_DELEGATE_EstablishTransport (BIT21) +#define TPM_KEY_DELEGATE_ReleaseTransportSigned (BIT20) +#define TPM_KEY_DELEGATE_Quote2 (BIT19) +#define TPM_KEY_DELEGATE_Sealx (BIT18) +#define TPM_KEY_DELEGATE_MakeIdentity (BIT17) +#define TPM_KEY_DELEGATE_ActivateIdentity (BIT16) +#define TPM_KEY_DELEGATE_GetAuditDigestSigned (BIT15) +#define TPM_KEY_DELEGATE_Sign (BIT14) +#define TPM_KEY_DELEGATE_CertifyKey2 (BIT13) +#define TPM_KEY_DELEGATE_CertifyKey (BIT12) +#define TPM_KEY_DELEGATE_CreateWrapKey (BIT11) +#define TPM_KEY_DELEGATE_CMK_CreateBlob (BIT10) +#define TPM_KEY_DELEGATE_CreateMigrationBlob (BIT9) +#define TPM_KEY_DELEGATE_ConvertMigrationBlob (BIT8) +#define TPM_KEY_DELEGATE_CreateKeyDelegation (BIT7) +#define TPM_KEY_DELEGATE_ChangeAuth (BIT6) +#define TPM_KEY_DELEGATE_GetPubKey (BIT5) +#define TPM_KEY_DELEGATE_UnBind (BIT4) +#define TPM_KEY_DELEGATE_Quote (BIT3) +#define TPM_KEY_DELEGATE_Unseal (BIT2) +#define TPM_KEY_DELEGATE_Seal (BIT1) +#define TPM_KEY_DELEGATE_LoadKey (BIT0) + +// +// Part 2, section 20.3: TPM_FAMILY_FLAGS +// +#define TPM_DELEGATE_ADMIN_LOCK (BIT1) +#define TPM_FAMFLAG_ENABLE (BIT0) + +/// +/// Part 2, section 20.4: TPM_FAMILY_LABEL +/// +typedef struct tdTPM_FAMILY_LABEL { + UINT8 label; +} TPM_FAMILY_LABEL; + +/// +/// Part 2, section 20.5: TPM_FAMILY_TABLE_ENTRY +/// +typedef struct tdTPM_FAMILY_TABLE_ENTRY { + TPM_STRUCTURE_TAG tag; + TPM_FAMILY_LABEL label; + TPM_FAMILY_ID familyID; + TPM_FAMILY_VERIFICATION verificationCount; + TPM_FAMILY_FLAGS flags; +} TPM_FAMILY_TABLE_ENTRY; + +// +// Part 2, section 20.6: TPM_FAMILY_TABLE +// +#define TPM_NUM_FAMILY_TABLE_ENTRY_MIN 8 + +typedef struct tdTPM_FAMILY_TABLE{ + TPM_FAMILY_TABLE_ENTRY famTableRow[TPM_NUM_FAMILY_TABLE_ENTRY_MIN]; +} TPM_FAMILY_TABLE; + +/// +/// Part 2, section 20.7: TPM_DELEGATE_LABEL +/// +typedef struct tdTPM_DELEGATE_LABEL { + UINT8 label; +} TPM_DELEGATE_LABEL; + +/// +/// Part 2, section 20.8: TPM_DELEGATE_PUBLIC +/// +typedef struct tdTPM_DELEGATE_PUBLIC { + TPM_STRUCTURE_TAG tag; + TPM_DELEGATE_LABEL label; + TPM_PCR_INFO_SHORT pcrInfo; + TPM_DELEGATIONS permissions; + TPM_FAMILY_ID familyID; + TPM_FAMILY_VERIFICATION verificationCount; +} TPM_DELEGATE_PUBLIC; + +/// +/// Part 2, section 20.9: TPM_DELEGATE_TABLE_ROW +/// +typedef struct tdTPM_DELEGATE_TABLE_ROW { + TPM_STRUCTURE_TAG tag; + TPM_DELEGATE_PUBLIC pub; + TPM_SECRET authValue; +} TPM_DELEGATE_TABLE_ROW; + +// +// Part 2, section 20.10: TPM_DELEGATE_TABLE +// +#define TPM_NUM_DELEGATE_TABLE_ENTRY_MIN 2 + +typedef struct tdTPM_DELEGATE_TABLE{ + TPM_DELEGATE_TABLE_ROW delRow[TPM_NUM_DELEGATE_TABLE_ENTRY_MIN]; +} TPM_DELEGATE_TABLE; + +/// +/// Part 2, section 20.11: TPM_DELEGATE_SENSITIVE +/// +typedef struct tdTPM_DELEGATE_SENSITIVE { + TPM_STRUCTURE_TAG tag; + TPM_SECRET authValue; +} TPM_DELEGATE_SENSITIVE; + +/// +/// Part 2, section 20.12: TPM_DELEGATE_OWNER_BLOB +/// +typedef struct tdTPM_DELEGATE_OWNER_BLOB { + TPM_STRUCTURE_TAG tag; + TPM_DELEGATE_PUBLIC pub; + TPM_DIGEST integrityDigest; + UINT32 additionalSize; + UINT8 *additionalArea; + UINT32 sensitiveSize; + UINT8 *sensitiveArea; +} TPM_DELEGATE_OWNER_BLOB; + +/// +/// Part 2, section 20.13: TTPM_DELEGATE_KEY_BLOB +/// +typedef struct tdTPM_DELEGATE_KEY_BLOB { + TPM_STRUCTURE_TAG tag; + TPM_DELEGATE_PUBLIC pub; + TPM_DIGEST integrityDigest; + TPM_DIGEST pubKeyDigest; + UINT32 additionalSize; + UINT8 *additionalArea; + UINT32 sensitiveSize; + UINT8 *sensitiveArea; +} TPM_DELEGATE_KEY_BLOB; + +// +// Part 2, section 20.14: TPM_FAMILY_OPERATION Values +// +#define TPM_FAMILY_CREATE ((UINT32)0x00000001) +#define TPM_FAMILY_ENABLE ((UINT32)0x00000002) +#define TPM_FAMILY_ADMIN ((UINT32)0x00000003) +#define TPM_FAMILY_INVALIDATE ((UINT32)0x00000004) + +// +// Part 2, section 21.1: TPM_CAPABILITY_AREA for GetCapability +// +#define TPM_CAP_ORD ((TPM_CAPABILITY_AREA) 0x00000001) +#define TPM_CAP_ALG ((TPM_CAPABILITY_AREA) 0x00000002) +#define TPM_CAP_PID ((TPM_CAPABILITY_AREA) 0x00000003) +#define TPM_CAP_FLAG ((TPM_CAPABILITY_AREA) 0x00000004) +#define TPM_CAP_PROPERTY ((TPM_CAPABILITY_AREA) 0x00000005) +#define TPM_CAP_VERSION ((TPM_CAPABILITY_AREA) 0x00000006) +#define TPM_CAP_KEY_HANDLE ((TPM_CAPABILITY_AREA) 0x00000007) +#define TPM_CAP_CHECK_LOADED ((TPM_CAPABILITY_AREA) 0x00000008) +#define TPM_CAP_SYM_MODE ((TPM_CAPABILITY_AREA) 0x00000009) +#define TPM_CAP_KEY_STATUS ((TPM_CAPABILITY_AREA) 0x0000000C) +#define TPM_CAP_NV_LIST ((TPM_CAPABILITY_AREA) 0x0000000D) +#define TPM_CAP_MFR ((TPM_CAPABILITY_AREA) 0x00000010) +#define TPM_CAP_NV_INDEX ((TPM_CAPABILITY_AREA) 0x00000011) +#define TPM_CAP_TRANS_ALG ((TPM_CAPABILITY_AREA) 0x00000012) +#define TPM_CAP_HANDLE ((TPM_CAPABILITY_AREA) 0x00000014) +#define TPM_CAP_TRANS_ES ((TPM_CAPABILITY_AREA) 0x00000015) +#define TPM_CAP_AUTH_ENCRYPT ((TPM_CAPABILITY_AREA) 0x00000017) +#define TPM_CAP_SELECT_SIZE ((TPM_CAPABILITY_AREA) 0x00000018) +#define TPM_CAP_VERSION_VAL ((TPM_CAPABILITY_AREA) 0x0000001A) + +#define TPM_CAP_FLAG_PERMANENT ((TPM_CAPABILITY_AREA) 0x00000108) +#define TPM_CAP_FLAG_VOLATILE ((TPM_CAPABILITY_AREA) 0x00000109) + +// +// Part 2, section 21.2: CAP_PROPERTY Subcap values for GetCapability +// +#define TPM_CAP_PROP_PCR ((TPM_CAPABILITY_AREA) 0x00000101) +#define TPM_CAP_PROP_DIR ((TPM_CAPABILITY_AREA) 0x00000102) +#define TPM_CAP_PROP_MANUFACTURER ((TPM_CAPABILITY_AREA) 0x00000103) +#define TPM_CAP_PROP_KEYS ((TPM_CAPABILITY_AREA) 0x00000104) +#define TPM_CAP_PROP_MIN_COUNTER ((TPM_CAPABILITY_AREA) 0x00000107) +#define TPM_CAP_PROP_AUTHSESS ((TPM_CAPABILITY_AREA) 0x0000010A) +#define TPM_CAP_PROP_TRANSESS ((TPM_CAPABILITY_AREA) 0x0000010B) +#define TPM_CAP_PROP_COUNTERS ((TPM_CAPABILITY_AREA) 0x0000010C) +#define TPM_CAP_PROP_MAX_AUTHSESS ((TPM_CAPABILITY_AREA) 0x0000010D) +#define TPM_CAP_PROP_MAX_TRANSESS ((TPM_CAPABILITY_AREA) 0x0000010E) +#define TPM_CAP_PROP_MAX_COUNTERS ((TPM_CAPABILITY_AREA) 0x0000010F) +#define TPM_CAP_PROP_MAX_KEYS ((TPM_CAPABILITY_AREA) 0x00000110) +#define TPM_CAP_PROP_OWNER ((TPM_CAPABILITY_AREA) 0x00000111) +#define TPM_CAP_PROP_CONTEXT ((TPM_CAPABILITY_AREA) 0x00000112) +#define TPM_CAP_PROP_MAX_CONTEXT ((TPM_CAPABILITY_AREA) 0x00000113) +#define TPM_CAP_PROP_FAMILYROWS ((TPM_CAPABILITY_AREA) 0x00000114) +#define TPM_CAP_PROP_TIS_TIMEOUT ((TPM_CAPABILITY_AREA) 0x00000115) +#define TPM_CAP_PROP_STARTUP_EFFECT ((TPM_CAPABILITY_AREA) 0x00000116) +#define TPM_CAP_PROP_DELEGATE_ROW ((TPM_CAPABILITY_AREA) 0x00000117) +#define TPM_CAP_PROP_DAA_MAX ((TPM_CAPABILITY_AREA) 0x00000119) +#define CAP_PROP_SESSION_DAA ((TPM_CAPABILITY_AREA) 0x0000011A) +#define TPM_CAP_PROP_CONTEXT_DIST ((TPM_CAPABILITY_AREA) 0x0000011B) +#define TPM_CAP_PROP_DAA_INTERRUPT ((TPM_CAPABILITY_AREA) 0x0000011C) +#define TPM_CAP_PROP_SESSIONS ((TPM_CAPABILITY_AREA) 0x0000011D) +#define TPM_CAP_PROP_MAX_SESSIONS ((TPM_CAPABILITY_AREA) 0x0000011E) +#define TPM_CAP_PROP_CMK_RESTRICTION ((TPM_CAPABILITY_AREA) 0x0000011F) +#define TPM_CAP_PROP_DURATION ((TPM_CAPABILITY_AREA) 0x00000120) +#define TPM_CAP_PROP_ACTIVE_COUNTER ((TPM_CAPABILITY_AREA) 0x00000122) +#define TPM_CAP_PROP_MAX_NV_AVAILABLE ((TPM_CAPABILITY_AREA) 0x00000123) +#define TPM_CAP_PROP_INPUT_BUFFER ((TPM_CAPABILITY_AREA) 0x00000124) + +// +// Part 2, section 21.4: TPM_CAPABILITY_AREA for SetCapability +// +#define TPM_SET_PERM_FLAGS ((TPM_CAPABILITY_AREA) 0x00000001) +#define TPM_SET_PERM_DATA ((TPM_CAPABILITY_AREA) 0x00000002) +#define TPM_SET_STCLEAR_FLAGS ((TPM_CAPABILITY_AREA) 0x00000003) +#define TPM_SET_STCLEAR_DATA ((TPM_CAPABILITY_AREA) 0x00000004) +#define TPM_SET_STANY_FLAGS ((TPM_CAPABILITY_AREA) 0x00000005) +#define TPM_SET_STANY_DATA ((TPM_CAPABILITY_AREA) 0x00000006) + +/// +/// Part 2, section 21.6: TPM_CAP_VERSION_INFO +/// [size_is(vendorSpecificSize)] BYTE* vendorSpecific; +/// +typedef struct tdTPM_CAP_VERSION_INFO { + TPM_STRUCTURE_TAG tag; + TPM_VERSION version; + UINT16 specLevel; + UINT8 errataRev; + UINT8 tpmVendorID[4]; + UINT16 vendorSpecificSize; + UINT8 *vendorSpecific; +} TPM_CAP_VERSION_INFO; + +/// +/// Part 2, section 21.10: TPM_DA_ACTION_TYPE +/// +typedef struct tdTPM_DA_ACTION_TYPE { + TPM_STRUCTURE_TAG tag; + UINT32 actions; +} TPM_DA_ACTION_TYPE; + +#define TPM_DA_ACTION_FAILURE_MODE (((UINT32)1)<<3) +#define TPM_DA_ACTION_DEACTIVATE (((UINT32)1)<<2) +#define TPM_DA_ACTION_DISABLE (((UINT32)1)<<1) +#define TPM_DA_ACTION_TIMEOUT (((UINT32)1)<<0) + +/// +/// Part 2, section 21.7: TPM_DA_INFO +/// +typedef struct tdTPM_DA_INFO { + TPM_STRUCTURE_TAG tag; + TPM_DA_STATE state; + UINT16 currentCount; + UINT16 thresholdCount; + TPM_DA_ACTION_TYPE actionAtThreshold; + UINT32 actionDependValue; + UINT32 vendorDataSize; + UINT8 *vendorData; +} TPM_DA_INFO; + +/// +/// Part 2, section 21.8: TPM_DA_INFO_LIMITED +/// +typedef struct tdTPM_DA_INFO_LIMITED { + TPM_STRUCTURE_TAG tag; + TPM_DA_STATE state; + TPM_DA_ACTION_TYPE actionAtThreshold; + UINT32 vendorDataSize; + UINT8 *vendorData; +} TPM_DA_INFO_LIMITED; + +// +// Part 2, section 21.9: CAP_PROPERTY Subcap values for GetCapability +// +#define TPM_DA_STATE_INACTIVE ((UINT8)0x00) +#define TPM_DA_STATE_ACTIVE ((UINT8)0x01) + +// +// Part 2, section 22: DAA Structures +// + +// +// Part 2, section 22.1: Size definitions +// +#define TPM_DAA_SIZE_r0 (43) +#define TPM_DAA_SIZE_r1 (43) +#define TPM_DAA_SIZE_r2 (128) +#define TPM_DAA_SIZE_r3 (168) +#define TPM_DAA_SIZE_r4 (219) +#define TPM_DAA_SIZE_NT (20) +#define TPM_DAA_SIZE_v0 (128) +#define TPM_DAA_SIZE_v1 (192) +#define TPM_DAA_SIZE_NE (256) +#define TPM_DAA_SIZE_w (256) +#define TPM_DAA_SIZE_issuerModulus (256) +// +// Part 2, section 22.2: Constant definitions +// +#define TPM_DAA_power0 (104) +#define TPM_DAA_power1 (1024) + +/// +/// Part 2, section 22.3: TPM_DAA_ISSUER +/// +typedef struct tdTPM_DAA_ISSUER { + TPM_STRUCTURE_TAG tag; + TPM_DIGEST DAA_digest_R0; + TPM_DIGEST DAA_digest_R1; + TPM_DIGEST DAA_digest_S0; + TPM_DIGEST DAA_digest_S1; + TPM_DIGEST DAA_digest_n; + TPM_DIGEST DAA_digest_gamma; + UINT8 DAA_generic_q[26]; +} TPM_DAA_ISSUER; + +/// +/// Part 2, section 22.4: TPM_DAA_TPM +/// +typedef struct tdTPM_DAA_TPM { + TPM_STRUCTURE_TAG tag; + TPM_DIGEST DAA_digestIssuer; + TPM_DIGEST DAA_digest_v0; + TPM_DIGEST DAA_digest_v1; + TPM_DIGEST DAA_rekey; + UINT32 DAA_count; +} TPM_DAA_TPM; + +/// +/// Part 2, section 22.5: TPM_DAA_CONTEXT +/// +typedef struct tdTPM_DAA_CONTEXT { + TPM_STRUCTURE_TAG tag; + TPM_DIGEST DAA_digestContext; + TPM_DIGEST DAA_digest; + TPM_DAA_CONTEXT_SEED DAA_contextSeed; + UINT8 DAA_scratch[256]; + UINT8 DAA_stage; +} TPM_DAA_CONTEXT; + +/// +/// Part 2, section 22.6: TPM_DAA_JOINDATA +/// +typedef struct tdTPM_DAA_JOINDATA { + UINT8 DAA_join_u0[128]; + UINT8 DAA_join_u1[138]; + TPM_DIGEST DAA_digest_n0; +} TPM_DAA_JOINDATA; + +/// +/// Part 2, section 22.8: TPM_DAA_BLOB +/// +typedef struct tdTPM_DAA_BLOB { + TPM_STRUCTURE_TAG tag; + TPM_RESOURCE_TYPE resourceType; + UINT8 label[16]; + TPM_DIGEST blobIntegrity; + UINT32 additionalSize; + UINT8 *additionalData; + UINT32 sensitiveSize; + UINT8 *sensitiveData; +} TPM_DAA_BLOB; + +/// +/// Part 2, section 22.9: TPM_DAA_SENSITIVE +/// +typedef struct tdTPM_DAA_SENSITIVE { + TPM_STRUCTURE_TAG tag; + UINT32 internalSize; + UINT8 *internalData; +} TPM_DAA_SENSITIVE; + + +// +// Part 2, section 23: Redirection +// + +/// +/// Part 2 section 23.1: TPM_REDIR_COMMAND +/// This section defines exactly one value but does not +/// give it a name. The definition of TPM_SetRedirection in Part3 +/// refers to exactly one name but does not give its value. We join +/// them here. +/// +#define TPM_REDIR_GPIO (0x00000001) + +/// +/// TPM Command Headers defined in Part 3 +/// +typedef struct tdTPM_RQU_COMMAND_HDR { + TPM_STRUCTURE_TAG tag; + UINT32 paramSize; + TPM_COMMAND_CODE ordinal; +} TPM_RQU_COMMAND_HDR; + +/// +/// TPM Response Headers defined in Part 3 +/// +typedef struct tdTPM_RSP_COMMAND_HDR { + TPM_STRUCTURE_TAG tag; + UINT32 paramSize; + TPM_RESULT returnCode; +} TPM_RSP_COMMAND_HDR; + +#pragma pack () + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm20.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm20.h new file mode 100644 index 0000000..697a2d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm20.h @@ -0,0 +1,1820 @@ +/** @file + TPM2.0 Specification data structures + (Trusted Platform Module Library Specification, Family "2.0", Level 00, Revision 00.96, + @http://www.trustedcomputinggroup.org/resources/tpm_library_specification) + + Check http://trustedcomputinggroup.org for latest specification updates. + +Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _TPM20_H_ +#define _TPM20_H_ + +#include + +#pragma pack (1) + +// Annex A Algorithm Constants + +// Table 205 - Defines for SHA1 Hash Values +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +// Table 206 - Defines for SHA256 Hash Values +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +// Table 207 - Defines for SHA384 Hash Values +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 + +// Table 208 - Defines for SHA512 Hash Values +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 + +// Table 209 - Defines for SM3_256 Hash Values +#define SM3_256_DIGEST_SIZE 32 +#define SM3_256_BLOCK_SIZE 64 + +// Table 210 - Defines for Architectural Limits Values +#define MAX_SESSION_NUMBER 3 + +// Annex B Implementation Definitions + +// Table 211 - Defines for Logic Values +#define YES 1 +#define NO 0 +#define SET 1 +#define CLEAR 0 + +// Table 215 - Defines for RSA Algorithm Constants +#define MAX_RSA_KEY_BITS 2048 +#define MAX_RSA_KEY_BYTES ((MAX_RSA_KEY_BITS + 7) / 8) + +// Table 216 - Defines for ECC Algorithm Constants +#define MAX_ECC_KEY_BITS 256 +#define MAX_ECC_KEY_BYTES ((MAX_ECC_KEY_BITS + 7) / 8) + +// Table 217 - Defines for AES Algorithm Constants +#define MAX_AES_KEY_BITS 128 +#define MAX_AES_BLOCK_SIZE_BYTES 16 +#define MAX_AES_KEY_BYTES ((MAX_AES_KEY_BITS + 7) / 8) + +// Table 218 - Defines for SM4 Algorithm Constants +#define MAX_SM4_KEY_BITS 128 +#define MAX_SM4_BLOCK_SIZE_BYTES 16 +#define MAX_SM4_KEY_BYTES ((MAX_SM4_KEY_BITS + 7) / 8) + +// Table 219 - Defines for Symmetric Algorithm Constants +#define MAX_SYM_KEY_BITS MAX_AES_KEY_BITS +#define MAX_SYM_KEY_BYTES MAX_AES_KEY_BYTES +#define MAX_SYM_BLOCK_SIZE MAX_AES_BLOCK_SIZE_BYTES + +// Table 220 - Defines for Implementation Values +typedef UINT16 BSIZE; +#define BUFFER_ALIGNMENT 4 +#define IMPLEMENTATION_PCR 24 +#define PLATFORM_PCR 24 +#define DRTM_PCR 17 +#define NUM_LOCALITIES 5 +#define MAX_HANDLE_NUM 3 +#define MAX_ACTIVE_SESSIONS 64 +typedef UINT16 CONTEXT_SLOT; +typedef UINT64 CONTEXT_COUNTER; +#define MAX_LOADED_SESSIONS 3 +#define MAX_SESSION_NUM 3 +#define MAX_LOADED_OBJECTS 3 +#define MIN_EVICT_OBJECTS 2 +#define PCR_SELECT_MIN ((PLATFORM_PCR + 7) / 8) +#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR + 7) / 8) +#define NUM_POLICY_PCR_GROUP 1 +#define NUM_AUTHVALUE_PCR_GROUP 1 +#define MAX_CONTEXT_SIZE 4000 +#define MAX_DIGEST_BUFFER 1024 +#define MAX_NV_INDEX_SIZE 1024 +#define MAX_CAP_BUFFER 1024 +#define NV_MEMORY_SIZE 16384 +#define NUM_STATIC_PCR 16 +#define MAX_ALG_LIST_SIZE 64 +#define TIMER_PRESCALE 100000 +#define PRIMARY_SEED_SIZE 32 +#define CONTEXT_ENCRYPT_ALG TPM_ALG_AES +#define CONTEXT_ENCRYPT_KEY_BITS MAX_SYM_KEY_BITS +#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS + 7) / 8) +#define CONTEXT_INTEGRITY_HASH_ALG TPM_ALG_SHA256 +#define CONTEXT_INTEGRITY_HASH_SIZE SHA256_DIGEST_SIZE +#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE +#define NV_CLOCK_UPDATE_INTERVAL 12 +#define NUM_POLICY_PCR 1 +#define MAX_COMMAND_SIZE 4096 +#define MAX_RESPONSE_SIZE 4096 +#define ORDERLY_BITS 8 +#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1) +#define ALG_ID_FIRST TPM_ALG_FIRST +#define ALG_ID_LAST TPM_ALG_LAST +#define MAX_SYM_DATA 128 +#define MAX_RNG_ENTROPY_SIZE 64 +#define RAM_INDEX_SPACE 512 +#define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 +#define CRT_FORMAT_RSA YES +#define PRIVATE_VENDOR_SPECIFIC_BYTES ((MAX_RSA_KEY_BYTES / 2) * ( 3 + CRT_FORMAT_RSA * 2)) + +// Capability related MAX_ value +#define MAX_CAP_DATA (MAX_CAP_BUFFER - sizeof(TPM_CAP) - sizeof(UINT32)) +#define MAX_CAP_ALGS (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY)) +#define MAX_CAP_HANDLES (MAX_CAP_DATA / sizeof(TPM_HANDLE)) +#define MAX_CAP_CC (MAX_CAP_DATA / sizeof(TPM_CC)) +#define MAX_TPM_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PROPERTY)) +#define MAX_PCR_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT)) +#define MAX_ECC_CURVES (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE)) + +// +// Always set 5 here, because we want to support all hash algo in BIOS. +// +#define HASH_COUNT 5 + +// 5 Base Types + +// Table 3 - Definition of Base Types +typedef UINT8 BYTE; + +// Table 4 - Definition of Types for Documentation Clarity +// +// NOTE: Comment because it has same name as TPM1.2 (value is same, so not runtime issue) +// +//typedef UINT32 TPM_ALGORITHM_ID; +//typedef UINT32 TPM_MODIFIER_INDICATOR; +typedef UINT32 TPM_AUTHORIZATION_SIZE; +typedef UINT32 TPM_PARAMETER_SIZE; +typedef UINT16 TPM_KEY_SIZE; +typedef UINT16 TPM_KEY_BITS; + +// 6 Constants + +// Table 6 - TPM_GENERATED Constants +typedef UINT32 TPM_GENERATED; +#define TPM_GENERATED_VALUE (TPM_GENERATED)(0xff544347) + +// Table 7 - TPM_ALG_ID Constants +typedef UINT16 TPM_ALG_ID; +// +// NOTE: Comment some algo which has same name as TPM1.2 (value is same, so not runtime issue) +// +#define TPM_ALG_ERROR (TPM_ALG_ID)(0x0000) +#define TPM_ALG_FIRST (TPM_ALG_ID)(0x0001) +//#define TPM_ALG_RSA (TPM_ALG_ID)(0x0001) +//#define TPM_ALG_SHA (TPM_ALG_ID)(0x0004) +#define TPM_ALG_SHA1 (TPM_ALG_ID)(0x0004) +//#define TPM_ALG_HMAC (TPM_ALG_ID)(0x0005) +#define TPM_ALG_AES (TPM_ALG_ID)(0x0006) +//#define TPM_ALG_MGF1 (TPM_ALG_ID)(0x0007) +#define TPM_ALG_KEYEDHASH (TPM_ALG_ID)(0x0008) +//#define TPM_ALG_XOR (TPM_ALG_ID)(0x000A) +#define TPM_ALG_SHA256 (TPM_ALG_ID)(0x000B) +#define TPM_ALG_SHA384 (TPM_ALG_ID)(0x000C) +#define TPM_ALG_SHA512 (TPM_ALG_ID)(0x000D) +#define TPM_ALG_NULL (TPM_ALG_ID)(0x0010) +#define TPM_ALG_SM3_256 (TPM_ALG_ID)(0x0012) +#define TPM_ALG_SM4 (TPM_ALG_ID)(0x0013) +#define TPM_ALG_RSASSA (TPM_ALG_ID)(0x0014) +#define TPM_ALG_RSAES (TPM_ALG_ID)(0x0015) +#define TPM_ALG_RSAPSS (TPM_ALG_ID)(0x0016) +#define TPM_ALG_OAEP (TPM_ALG_ID)(0x0017) +#define TPM_ALG_ECDSA (TPM_ALG_ID)(0x0018) +#define TPM_ALG_ECDH (TPM_ALG_ID)(0x0019) +#define TPM_ALG_ECDAA (TPM_ALG_ID)(0x001A) +#define TPM_ALG_SM2 (TPM_ALG_ID)(0x001B) +#define TPM_ALG_ECSCHNORR (TPM_ALG_ID)(0x001C) +#define TPM_ALG_ECMQV (TPM_ALG_ID)(0x001D) +#define TPM_ALG_KDF1_SP800_56a (TPM_ALG_ID)(0x0020) +#define TPM_ALG_KDF2 (TPM_ALG_ID)(0x0021) +#define TPM_ALG_KDF1_SP800_108 (TPM_ALG_ID)(0x0022) +#define TPM_ALG_ECC (TPM_ALG_ID)(0x0023) +#define TPM_ALG_SYMCIPHER (TPM_ALG_ID)(0x0025) +#define TPM_ALG_CTR (TPM_ALG_ID)(0x0040) +#define TPM_ALG_OFB (TPM_ALG_ID)(0x0041) +#define TPM_ALG_CBC (TPM_ALG_ID)(0x0042) +#define TPM_ALG_CFB (TPM_ALG_ID)(0x0043) +#define TPM_ALG_ECB (TPM_ALG_ID)(0x0044) +#define TPM_ALG_LAST (TPM_ALG_ID)(0x0044) + +// Table 8 - TPM_ECC_CURVE Constants +typedef UINT16 TPM_ECC_CURVE; +#define TPM_ECC_NONE (TPM_ECC_CURVE)(0x0000) +#define TPM_ECC_NIST_P192 (TPM_ECC_CURVE)(0x0001) +#define TPM_ECC_NIST_P224 (TPM_ECC_CURVE)(0x0002) +#define TPM_ECC_NIST_P256 (TPM_ECC_CURVE)(0x0003) +#define TPM_ECC_NIST_P384 (TPM_ECC_CURVE)(0x0004) +#define TPM_ECC_NIST_P521 (TPM_ECC_CURVE)(0x0005) +#define TPM_ECC_BN_P256 (TPM_ECC_CURVE)(0x0010) +#define TPM_ECC_BN_P638 (TPM_ECC_CURVE)(0x0011) +#define TPM_ECC_SM2_P256 (TPM_ECC_CURVE)(0x0020) + +// Table 11 - TPM_CC Constants (Numeric Order) +typedef UINT32 TPM_CC; +#define TPM_CC_FIRST (TPM_CC)(0x0000011F) +#define TPM_CC_PP_FIRST (TPM_CC)(0x0000011F) +#define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F) +#define TPM_CC_EvictControl (TPM_CC)(0x00000120) +#define TPM_CC_HierarchyControl (TPM_CC)(0x00000121) +#define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122) +#define TPM_CC_ChangeEPS (TPM_CC)(0x00000124) +#define TPM_CC_ChangePPS (TPM_CC)(0x00000125) +#define TPM_CC_Clear (TPM_CC)(0x00000126) +#define TPM_CC_ClearControl (TPM_CC)(0x00000127) +#define TPM_CC_ClockSet (TPM_CC)(0x00000128) +#define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129) +#define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A) +#define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B) +#define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C) +#define TPM_CC_PP_Commands (TPM_CC)(0x0000012D) +#define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E) +#define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F) +#define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130) +#define TPM_CC_CreatePrimary (TPM_CC)(0x00000131) +#define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132) +#define TPM_CC_PP_LAST (TPM_CC)(0x00000132) +#define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133) +#define TPM_CC_NV_Increment (TPM_CC)(0x00000134) +#define TPM_CC_NV_SetBits (TPM_CC)(0x00000135) +#define TPM_CC_NV_Extend (TPM_CC)(0x00000136) +#define TPM_CC_NV_Write (TPM_CC)(0x00000137) +#define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138) +#define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139) +#define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A) +#define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B) +#define TPM_CC_PCR_Event (TPM_CC)(0x0000013C) +#define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D) +#define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E) +#define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F) +#define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140) +#define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141) +#define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142) +#define TPM_CC_SelfTest (TPM_CC)(0x00000143) +#define TPM_CC_Startup (TPM_CC)(0x00000144) +#define TPM_CC_Shutdown (TPM_CC)(0x00000145) +#define TPM_CC_StirRandom (TPM_CC)(0x00000146) +#define TPM_CC_ActivateCredential (TPM_CC)(0x00000147) +#define TPM_CC_Certify (TPM_CC)(0x00000148) +#define TPM_CC_PolicyNV (TPM_CC)(0x00000149) +#define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A) +#define TPM_CC_Duplicate (TPM_CC)(0x0000014B) +#define TPM_CC_GetTime (TPM_CC)(0x0000014C) +#define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D) +#define TPM_CC_NV_Read (TPM_CC)(0x0000014E) +#define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F) +#define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150) +#define TPM_CC_PolicySecret (TPM_CC)(0x00000151) +#define TPM_CC_Rewrap (TPM_CC)(0x00000152) +#define TPM_CC_Create (TPM_CC)(0x00000153) +#define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154) +#define TPM_CC_HMAC (TPM_CC)(0x00000155) +#define TPM_CC_Import (TPM_CC)(0x00000156) +#define TPM_CC_Load (TPM_CC)(0x00000157) +#define TPM_CC_Quote (TPM_CC)(0x00000158) +#define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159) +#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B) +#define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C) +#define TPM_CC_Sign (TPM_CC)(0x0000015D) +#define TPM_CC_Unseal (TPM_CC)(0x0000015E) +#define TPM_CC_PolicySigned (TPM_CC)(0x00000160) +#define TPM_CC_ContextLoad (TPM_CC)(0x00000161) +#define TPM_CC_ContextSave (TPM_CC)(0x00000162) +#define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163) +#define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164) +#define TPM_CC_FlushContext (TPM_CC)(0x00000165) +#define TPM_CC_LoadExternal (TPM_CC)(0x00000167) +#define TPM_CC_MakeCredential (TPM_CC)(0x00000168) +#define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169) +#define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A) +#define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B) +#define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C) +#define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D) +#define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E) +#define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F) +#define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170) +#define TPM_CC_PolicyOR (TPM_CC)(0x00000171) +#define TPM_CC_PolicyTicket (TPM_CC)(0x00000172) +#define TPM_CC_ReadPublic (TPM_CC)(0x00000173) +#define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174) +#define TPM_CC_StartAuthSession (TPM_CC)(0x00000176) +#define TPM_CC_VerifySignature (TPM_CC)(0x00000177) +#define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178) +#define TPM_CC_FirmwareRead (TPM_CC)(0x00000179) +#define TPM_CC_GetCapability (TPM_CC)(0x0000017A) +#define TPM_CC_GetRandom (TPM_CC)(0x0000017B) +#define TPM_CC_GetTestResult (TPM_CC)(0x0000017C) +#define TPM_CC_Hash (TPM_CC)(0x0000017D) +#define TPM_CC_PCR_Read (TPM_CC)(0x0000017E) +#define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F) +#define TPM_CC_PolicyRestart (TPM_CC)(0x00000180) +#define TPM_CC_ReadClock (TPM_CC)(0x00000181) +#define TPM_CC_PCR_Extend (TPM_CC)(0x00000182) +#define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183) +#define TPM_CC_NV_Certify (TPM_CC)(0x00000184) +#define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185) +#define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186) +#define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187) +#define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188) +#define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189) +#define TPM_CC_TestParms (TPM_CC)(0x0000018A) +#define TPM_CC_Commit (TPM_CC)(0x0000018B) +#define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C) +#define TPM_CC_ZGen_2Phase (TPM_CC)(0x0000018D) +#define TPM_CC_EC_Ephemeral (TPM_CC)(0x0000018E) +#define TPM_CC_LAST (TPM_CC)(0x0000018E) + +// Table 15 - TPM_RC Constants (Actions) +typedef UINT32 TPM_RC; +#define TPM_RC_SUCCESS (TPM_RC)(0x000) +#define TPM_RC_BAD_TAG (TPM_RC)(0x030) +#define RC_VER1 (TPM_RC)(0x100) +#define TPM_RC_INITIALIZE (TPM_RC)(RC_VER1 + 0x000) +#define TPM_RC_FAILURE (TPM_RC)(RC_VER1 + 0x001) +#define TPM_RC_SEQUENCE (TPM_RC)(RC_VER1 + 0x003) +#define TPM_RC_PRIVATE (TPM_RC)(RC_VER1 + 0x00B) +#define TPM_RC_HMAC (TPM_RC)(RC_VER1 + 0x019) +#define TPM_RC_DISABLED (TPM_RC)(RC_VER1 + 0x020) +#define TPM_RC_EXCLUSIVE (TPM_RC)(RC_VER1 + 0x021) +#define TPM_RC_AUTH_TYPE (TPM_RC)(RC_VER1 + 0x024) +#define TPM_RC_AUTH_MISSING (TPM_RC)(RC_VER1 + 0x025) +#define TPM_RC_POLICY (TPM_RC)(RC_VER1 + 0x026) +#define TPM_RC_PCR (TPM_RC)(RC_VER1 + 0x027) +#define TPM_RC_PCR_CHANGED (TPM_RC)(RC_VER1 + 0x028) +#define TPM_RC_UPGRADE (TPM_RC)(RC_VER1 + 0x02D) +#define TPM_RC_TOO_MANY_CONTEXTS (TPM_RC)(RC_VER1 + 0x02E) +#define TPM_RC_AUTH_UNAVAILABLE (TPM_RC)(RC_VER1 + 0x02F) +#define TPM_RC_REBOOT (TPM_RC)(RC_VER1 + 0x030) +#define TPM_RC_UNBALANCED (TPM_RC)(RC_VER1 + 0x031) +#define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1 + 0x042) +#define TPM_RC_COMMAND_CODE (TPM_RC)(RC_VER1 + 0x043) +#define TPM_RC_AUTHSIZE (TPM_RC)(RC_VER1 + 0x044) +#define TPM_RC_AUTH_CONTEXT (TPM_RC)(RC_VER1 + 0x045) +#define TPM_RC_NV_RANGE (TPM_RC)(RC_VER1 + 0x046) +#define TPM_RC_NV_SIZE (TPM_RC)(RC_VER1 + 0x047) +#define TPM_RC_NV_LOCKED (TPM_RC)(RC_VER1 + 0x048) +#define TPM_RC_NV_AUTHORIZATION (TPM_RC)(RC_VER1 + 0x049) +#define TPM_RC_NV_UNINITIALIZED (TPM_RC)(RC_VER1 + 0x04A) +#define TPM_RC_NV_SPACE (TPM_RC)(RC_VER1 + 0x04B) +#define TPM_RC_NV_DEFINED (TPM_RC)(RC_VER1 + 0x04C) +#define TPM_RC_BAD_CONTEXT (TPM_RC)(RC_VER1 + 0x050) +#define TPM_RC_CPHASH (TPM_RC)(RC_VER1 + 0x051) +#define TPM_RC_PARENT (TPM_RC)(RC_VER1 + 0x052) +#define TPM_RC_NEEDS_TEST (TPM_RC)(RC_VER1 + 0x053) +#define TPM_RC_NO_RESULT (TPM_RC)(RC_VER1 + 0x054) +#define TPM_RC_SENSITIVE (TPM_RC)(RC_VER1 + 0x055) +#define RC_MAX_FM0 (TPM_RC)(RC_VER1 + 0x07F) +#define RC_FMT1 (TPM_RC)(0x080) +#define TPM_RC_ASYMMETRIC (TPM_RC)(RC_FMT1 + 0x001) +#define TPM_RC_ATTRIBUTES (TPM_RC)(RC_FMT1 + 0x002) +#define TPM_RC_HASH (TPM_RC)(RC_FMT1 + 0x003) +#define TPM_RC_VALUE (TPM_RC)(RC_FMT1 + 0x004) +#define TPM_RC_HIERARCHY (TPM_RC)(RC_FMT1 + 0x005) +#define TPM_RC_KEY_SIZE (TPM_RC)(RC_FMT1 + 0x007) +#define TPM_RC_MGF (TPM_RC)(RC_FMT1 + 0x008) +#define TPM_RC_MODE (TPM_RC)(RC_FMT1 + 0x009) +#define TPM_RC_TYPE (TPM_RC)(RC_FMT1 + 0x00A) +#define TPM_RC_HANDLE (TPM_RC)(RC_FMT1 + 0x00B) +#define TPM_RC_KDF (TPM_RC)(RC_FMT1 + 0x00C) +#define TPM_RC_RANGE (TPM_RC)(RC_FMT1 + 0x00D) +#define TPM_RC_AUTH_FAIL (TPM_RC)(RC_FMT1 + 0x00E) +#define TPM_RC_NONCE (TPM_RC)(RC_FMT1 + 0x00F) +#define TPM_RC_PP (TPM_RC)(RC_FMT1 + 0x010) +#define TPM_RC_SCHEME (TPM_RC)(RC_FMT1 + 0x012) +#define TPM_RC_SIZE (TPM_RC)(RC_FMT1 + 0x015) +#define TPM_RC_SYMMETRIC (TPM_RC)(RC_FMT1 + 0x016) +#define TPM_RC_TAG (TPM_RC)(RC_FMT1 + 0x017) +#define TPM_RC_SELECTOR (TPM_RC)(RC_FMT1 + 0x018) +#define TPM_RC_INSUFFICIENT (TPM_RC)(RC_FMT1 + 0x01A) +#define TPM_RC_SIGNATURE (TPM_RC)(RC_FMT1 + 0x01B) +#define TPM_RC_KEY (TPM_RC)(RC_FMT1 + 0x01C) +#define TPM_RC_POLICY_FAIL (TPM_RC)(RC_FMT1 + 0x01D) +#define TPM_RC_INTEGRITY (TPM_RC)(RC_FMT1 + 0x01F) +#define TPM_RC_TICKET (TPM_RC)(RC_FMT1 + 0x020) +#define TPM_RC_RESERVED_BITS (TPM_RC)(RC_FMT1 + 0x021) +#define TPM_RC_BAD_AUTH (TPM_RC)(RC_FMT1 + 0x022) +#define TPM_RC_EXPIRED (TPM_RC)(RC_FMT1 + 0x023) +#define TPM_RC_POLICY_CC (TPM_RC)(RC_FMT1 + 0x024 ) +#define TPM_RC_BINDING (TPM_RC)(RC_FMT1 + 0x025) +#define TPM_RC_CURVE (TPM_RC)(RC_FMT1 + 0x026) +#define TPM_RC_ECC_POINT (TPM_RC)(RC_FMT1 + 0x027) +#define RC_WARN (TPM_RC)(0x900) +#define TPM_RC_CONTEXT_GAP (TPM_RC)(RC_WARN + 0x001) +#define TPM_RC_OBJECT_MEMORY (TPM_RC)(RC_WARN + 0x002) +#define TPM_RC_SESSION_MEMORY (TPM_RC)(RC_WARN + 0x003) +#define TPM_RC_MEMORY (TPM_RC)(RC_WARN + 0x004) +#define TPM_RC_SESSION_HANDLES (TPM_RC)(RC_WARN + 0x005) +#define TPM_RC_OBJECT_HANDLES (TPM_RC)(RC_WARN + 0x006) +#define TPM_RC_LOCALITY (TPM_RC)(RC_WARN + 0x007) +#define TPM_RC_YIELDED (TPM_RC)(RC_WARN + 0x008) +#define TPM_RC_CANCELED (TPM_RC)(RC_WARN + 0x009) +#define TPM_RC_TESTING (TPM_RC)(RC_WARN + 0x00A) +#define TPM_RC_REFERENCE_H0 (TPM_RC)(RC_WARN + 0x010) +#define TPM_RC_REFERENCE_H1 (TPM_RC)(RC_WARN + 0x011) +#define TPM_RC_REFERENCE_H2 (TPM_RC)(RC_WARN + 0x012) +#define TPM_RC_REFERENCE_H3 (TPM_RC)(RC_WARN + 0x013) +#define TPM_RC_REFERENCE_H4 (TPM_RC)(RC_WARN + 0x014) +#define TPM_RC_REFERENCE_H5 (TPM_RC)(RC_WARN + 0x015) +#define TPM_RC_REFERENCE_H6 (TPM_RC)(RC_WARN + 0x016) +#define TPM_RC_REFERENCE_S0 (TPM_RC)(RC_WARN + 0x018) +#define TPM_RC_REFERENCE_S1 (TPM_RC)(RC_WARN + 0x019) +#define TPM_RC_REFERENCE_S2 (TPM_RC)(RC_WARN + 0x01A) +#define TPM_RC_REFERENCE_S3 (TPM_RC)(RC_WARN + 0x01B) +#define TPM_RC_REFERENCE_S4 (TPM_RC)(RC_WARN + 0x01C) +#define TPM_RC_REFERENCE_S5 (TPM_RC)(RC_WARN + 0x01D) +#define TPM_RC_REFERENCE_S6 (TPM_RC)(RC_WARN + 0x01E) +#define TPM_RC_NV_RATE (TPM_RC)(RC_WARN + 0x020) +#define TPM_RC_LOCKOUT (TPM_RC)(RC_WARN + 0x021) +#define TPM_RC_RETRY (TPM_RC)(RC_WARN + 0x022) +#define TPM_RC_NV_UNAVAILABLE (TPM_RC)(RC_WARN + 0x023) +#define TPM_RC_NOT_USED (TPM_RC)(RC_WARN + 0x7F) +#define TPM_RC_H (TPM_RC)(0x000) +#define TPM_RC_P (TPM_RC)(0x040) +#define TPM_RC_S (TPM_RC)(0x800) +#define TPM_RC_1 (TPM_RC)(0x100) +#define TPM_RC_2 (TPM_RC)(0x200) +#define TPM_RC_3 (TPM_RC)(0x300) +#define TPM_RC_4 (TPM_RC)(0x400) +#define TPM_RC_5 (TPM_RC)(0x500) +#define TPM_RC_6 (TPM_RC)(0x600) +#define TPM_RC_7 (TPM_RC)(0x700) +#define TPM_RC_8 (TPM_RC)(0x800) +#define TPM_RC_9 (TPM_RC)(0x900) +#define TPM_RC_A (TPM_RC)(0xA00) +#define TPM_RC_B (TPM_RC)(0xB00) +#define TPM_RC_C (TPM_RC)(0xC00) +#define TPM_RC_D (TPM_RC)(0xD00) +#define TPM_RC_E (TPM_RC)(0xE00) +#define TPM_RC_F (TPM_RC)(0xF00) +#define TPM_RC_N_MASK (TPM_RC)(0xF00) + +// Table 16 - TPM_CLOCK_ADJUST Constants +typedef INT8 TPM_CLOCK_ADJUST; +#define TPM_CLOCK_COARSE_SLOWER (TPM_CLOCK_ADJUST)(-3) +#define TPM_CLOCK_MEDIUM_SLOWER (TPM_CLOCK_ADJUST)(-2) +#define TPM_CLOCK_FINE_SLOWER (TPM_CLOCK_ADJUST)(-1) +#define TPM_CLOCK_NO_CHANGE (TPM_CLOCK_ADJUST)(0) +#define TPM_CLOCK_FINE_FASTER (TPM_CLOCK_ADJUST)(1) +#define TPM_CLOCK_MEDIUM_FASTER (TPM_CLOCK_ADJUST)(2) +#define TPM_CLOCK_COARSE_FASTER (TPM_CLOCK_ADJUST)(3) + +// Table 17 - TPM_EO Constants +typedef UINT16 TPM_EO; +#define TPM_EO_EQ (TPM_EO)(0x0000) +#define TPM_EO_NEQ (TPM_EO)(0x0001) +#define TPM_EO_SIGNED_GT (TPM_EO)(0x0002) +#define TPM_EO_UNSIGNED_GT (TPM_EO)(0x0003) +#define TPM_EO_SIGNED_LT (TPM_EO)(0x0004) +#define TPM_EO_UNSIGNED_LT (TPM_EO)(0x0005) +#define TPM_EO_SIGNED_GE (TPM_EO)(0x0006) +#define TPM_EO_UNSIGNED_GE (TPM_EO)(0x0007) +#define TPM_EO_SIGNED_LE (TPM_EO)(0x0008) +#define TPM_EO_UNSIGNED_LE (TPM_EO)(0x0009) +#define TPM_EO_BITSET (TPM_EO)(0x000A) +#define TPM_EO_BITCLEAR (TPM_EO)(0x000B) + +// Table 18 - TPM_ST Constants +typedef UINT16 TPM_ST; +#define TPM_ST_RSP_COMMAND (TPM_ST)(0x00C4) +#define TPM_ST_NULL (TPM_ST)(0X8000) +#define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001) +#define TPM_ST_SESSIONS (TPM_ST)(0x8002) +#define TPM_ST_ATTEST_NV (TPM_ST)(0x8014) +#define TPM_ST_ATTEST_COMMAND_AUDIT (TPM_ST)(0x8015) +#define TPM_ST_ATTEST_SESSION_AUDIT (TPM_ST)(0x8016) +#define TPM_ST_ATTEST_CERTIFY (TPM_ST)(0x8017) +#define TPM_ST_ATTEST_QUOTE (TPM_ST)(0x8018) +#define TPM_ST_ATTEST_TIME (TPM_ST)(0x8019) +#define TPM_ST_ATTEST_CREATION (TPM_ST)(0x801A) +#define TPM_ST_CREATION (TPM_ST)(0x8021) +#define TPM_ST_VERIFIED (TPM_ST)(0x8022) +#define TPM_ST_AUTH_SECRET (TPM_ST)(0x8023) +#define TPM_ST_HASHCHECK (TPM_ST)(0x8024) +#define TPM_ST_AUTH_SIGNED (TPM_ST)(0x8025) +#define TPM_ST_FU_MANIFEST (TPM_ST)(0x8029) + +// Table 19 - TPM_SU Constants +typedef UINT16 TPM_SU; +#define TPM_SU_CLEAR (TPM_SU)(0x0000) +#define TPM_SU_STATE (TPM_SU)(0x0001) + +// Table 20 - TPM_SE Constants +typedef UINT8 TPM_SE; +#define TPM_SE_HMAC (TPM_SE)(0x00) +#define TPM_SE_POLICY (TPM_SE)(0x01) +#define TPM_SE_TRIAL (TPM_SE)(0x03) + +// Table 21 - TPM_CAP Constants +typedef UINT32 TPM_CAP; +#define TPM_CAP_FIRST (TPM_CAP)(0x00000000) +#define TPM_CAP_ALGS (TPM_CAP)(0x00000000) +#define TPM_CAP_HANDLES (TPM_CAP)(0x00000001) +#define TPM_CAP_COMMANDS (TPM_CAP)(0x00000002) +#define TPM_CAP_PP_COMMANDS (TPM_CAP)(0x00000003) +#define TPM_CAP_AUDIT_COMMANDS (TPM_CAP)(0x00000004) +#define TPM_CAP_PCRS (TPM_CAP)(0x00000005) +#define TPM_CAP_TPM_PROPERTIES (TPM_CAP)(0x00000006) +#define TPM_CAP_PCR_PROPERTIES (TPM_CAP)(0x00000007) +#define TPM_CAP_ECC_CURVES (TPM_CAP)(0x00000008) +#define TPM_CAP_LAST (TPM_CAP)(0x00000008) +#define TPM_CAP_VENDOR_PROPERTY (TPM_CAP)(0x00000100) + +// Table 22 - TPM_PT Constants +typedef UINT32 TPM_PT; +#define TPM_PT_NONE (TPM_PT)(0x00000000) +#define PT_GROUP (TPM_PT)(0x00000100) +#define PT_FIXED (TPM_PT)(PT_GROUP * 1) +#define TPM_PT_FAMILY_INDICATOR (TPM_PT)(PT_FIXED + 0) +#define TPM_PT_LEVEL (TPM_PT)(PT_FIXED + 1) +#define TPM_PT_REVISION (TPM_PT)(PT_FIXED + 2) +#define TPM_PT_DAY_OF_YEAR (TPM_PT)(PT_FIXED + 3) +#define TPM_PT_YEAR (TPM_PT)(PT_FIXED + 4) +#define TPM_PT_MANUFACTURER (TPM_PT)(PT_FIXED + 5) +#define TPM_PT_VENDOR_STRING_1 (TPM_PT)(PT_FIXED + 6) +#define TPM_PT_VENDOR_STRING_2 (TPM_PT)(PT_FIXED + 7) +#define TPM_PT_VENDOR_STRING_3 (TPM_PT)(PT_FIXED + 8) +#define TPM_PT_VENDOR_STRING_4 (TPM_PT)(PT_FIXED + 9) +#define TPM_PT_VENDOR_TPM_TYPE (TPM_PT)(PT_FIXED + 10) +#define TPM_PT_FIRMWARE_VERSION_1 (TPM_PT)(PT_FIXED + 11) +#define TPM_PT_FIRMWARE_VERSION_2 (TPM_PT)(PT_FIXED + 12) +#define TPM_PT_INPUT_BUFFER (TPM_PT)(PT_FIXED + 13) +#define TPM_PT_HR_TRANSIENT_MIN (TPM_PT)(PT_FIXED + 14) +#define TPM_PT_HR_PERSISTENT_MIN (TPM_PT)(PT_FIXED + 15) +#define TPM_PT_HR_LOADED_MIN (TPM_PT)(PT_FIXED + 16) +#define TPM_PT_ACTIVE_SESSIONS_MAX (TPM_PT)(PT_FIXED + 17) +#define TPM_PT_PCR_COUNT (TPM_PT)(PT_FIXED + 18) +#define TPM_PT_PCR_SELECT_MIN (TPM_PT)(PT_FIXED + 19) +#define TPM_PT_CONTEXT_GAP_MAX (TPM_PT)(PT_FIXED + 20) +#define TPM_PT_NV_COUNTERS_MAX (TPM_PT)(PT_FIXED + 22) +#define TPM_PT_NV_INDEX_MAX (TPM_PT)(PT_FIXED + 23) +#define TPM_PT_MEMORY (TPM_PT)(PT_FIXED + 24) +#define TPM_PT_CLOCK_UPDATE (TPM_PT)(PT_FIXED + 25) +#define TPM_PT_CONTEXT_HASH (TPM_PT)(PT_FIXED + 26) +#define TPM_PT_CONTEXT_SYM (TPM_PT)(PT_FIXED + 27) +#define TPM_PT_CONTEXT_SYM_SIZE (TPM_PT)(PT_FIXED + 28) +#define TPM_PT_ORDERLY_COUNT (TPM_PT)(PT_FIXED + 29) +#define TPM_PT_MAX_COMMAND_SIZE (TPM_PT)(PT_FIXED + 30) +#define TPM_PT_MAX_RESPONSE_SIZE (TPM_PT)(PT_FIXED + 31) +#define TPM_PT_MAX_DIGEST (TPM_PT)(PT_FIXED + 32) +#define TPM_PT_MAX_OBJECT_CONTEXT (TPM_PT)(PT_FIXED + 33) +#define TPM_PT_MAX_SESSION_CONTEXT (TPM_PT)(PT_FIXED + 34) +#define TPM_PT_PS_FAMILY_INDICATOR (TPM_PT)(PT_FIXED + 35) +#define TPM_PT_PS_LEVEL (TPM_PT)(PT_FIXED + 36) +#define TPM_PT_PS_REVISION (TPM_PT)(PT_FIXED + 37) +#define TPM_PT_PS_DAY_OF_YEAR (TPM_PT)(PT_FIXED + 38) +#define TPM_PT_PS_YEAR (TPM_PT)(PT_FIXED + 39) +#define TPM_PT_SPLIT_MAX (TPM_PT)(PT_FIXED + 40) +#define TPM_PT_TOTAL_COMMANDS (TPM_PT)(PT_FIXED + 41) +#define TPM_PT_LIBRARY_COMMANDS (TPM_PT)(PT_FIXED + 42) +#define TPM_PT_VENDOR_COMMANDS (TPM_PT)(PT_FIXED + 43) +#define PT_VAR (TPM_PT)(PT_GROUP * 2) +#define TPM_PT_PERMANENT (TPM_PT)(PT_VAR + 0) +#define TPM_PT_STARTUP_CLEAR (TPM_PT)(PT_VAR + 1) +#define TPM_PT_HR_NV_INDEX (TPM_PT)(PT_VAR + 2) +#define TPM_PT_HR_LOADED (TPM_PT)(PT_VAR + 3) +#define TPM_PT_HR_LOADED_AVAIL (TPM_PT)(PT_VAR + 4) +#define TPM_PT_HR_ACTIVE (TPM_PT)(PT_VAR + 5) +#define TPM_PT_HR_ACTIVE_AVAIL (TPM_PT)(PT_VAR + 6) +#define TPM_PT_HR_TRANSIENT_AVAIL (TPM_PT)(PT_VAR + 7) +#define TPM_PT_HR_PERSISTENT (TPM_PT)(PT_VAR + 8) +#define TPM_PT_HR_PERSISTENT_AVAIL (TPM_PT)(PT_VAR + 9) +#define TPM_PT_NV_COUNTERS (TPM_PT)(PT_VAR + 10) +#define TPM_PT_NV_COUNTERS_AVAIL (TPM_PT)(PT_VAR + 11) +#define TPM_PT_ALGORITHM_SET (TPM_PT)(PT_VAR + 12) +#define TPM_PT_LOADED_CURVES (TPM_PT)(PT_VAR + 13) +#define TPM_PT_LOCKOUT_COUNTER (TPM_PT)(PT_VAR + 14) +#define TPM_PT_MAX_AUTH_FAIL (TPM_PT)(PT_VAR + 15) +#define TPM_PT_LOCKOUT_INTERVAL (TPM_PT)(PT_VAR + 16) +#define TPM_PT_LOCKOUT_RECOVERY (TPM_PT)(PT_VAR + 17) +#define TPM_PT_NV_WRITE_RECOVERY (TPM_PT)(PT_VAR + 18) +#define TPM_PT_AUDIT_COUNTER_0 (TPM_PT)(PT_VAR + 19) +#define TPM_PT_AUDIT_COUNTER_1 (TPM_PT)(PT_VAR + 20) + +// Table 23 - TPM_PT_PCR Constants +typedef UINT32 TPM_PT_PCR; +#define TPM_PT_PCR_FIRST (TPM_PT_PCR)(0x00000000) +#define TPM_PT_PCR_SAVE (TPM_PT_PCR)(0x00000000) +#define TPM_PT_PCR_EXTEND_L0 (TPM_PT_PCR)(0x00000001) +#define TPM_PT_PCR_RESET_L0 (TPM_PT_PCR)(0x00000002) +#define TPM_PT_PCR_EXTEND_L1 (TPM_PT_PCR)(0x00000003) +#define TPM_PT_PCR_RESET_L1 (TPM_PT_PCR)(0x00000004) +#define TPM_PT_PCR_EXTEND_L2 (TPM_PT_PCR)(0x00000005) +#define TPM_PT_PCR_RESET_L2 (TPM_PT_PCR)(0x00000006) +#define TPM_PT_PCR_EXTEND_L3 (TPM_PT_PCR)(0x00000007) +#define TPM_PT_PCR_RESET_L3 (TPM_PT_PCR)(0x00000008) +#define TPM_PT_PCR_EXTEND_L4 (TPM_PT_PCR)(0x00000009) +#define TPM_PT_PCR_RESET_L4 (TPM_PT_PCR)(0x0000000A) +#define TPM_PT_PCR_NO_INCREMENT (TPM_PT_PCR)(0x00000011) +#define TPM_PT_PCR_DRTM_RESET (TPM_PT_PCR)(0x00000012) +#define TPM_PT_PCR_POLICY (TPM_PT_PCR)(0x00000013) +#define TPM_PT_PCR_AUTH (TPM_PT_PCR)(0x00000014) +#define TPM_PT_PCR_LAST (TPM_PT_PCR)(0x00000014) + +// Table 24 - TPM_PS Constants +typedef UINT32 TPM_PS; +#define TPM_PS_MAIN (TPM_PS)(0x00000000) +#define TPM_PS_PC (TPM_PS)(0x00000001) +#define TPM_PS_PDA (TPM_PS)(0x00000002) +#define TPM_PS_CELL_PHONE (TPM_PS)(0x00000003) +#define TPM_PS_SERVER (TPM_PS)(0x00000004) +#define TPM_PS_PERIPHERAL (TPM_PS)(0x00000005) +#define TPM_PS_TSS (TPM_PS)(0x00000006) +#define TPM_PS_STORAGE (TPM_PS)(0x00000007) +#define TPM_PS_AUTHENTICATION (TPM_PS)(0x00000008) +#define TPM_PS_EMBEDDED (TPM_PS)(0x00000009) +#define TPM_PS_HARDCOPY (TPM_PS)(0x0000000A) +#define TPM_PS_INFRASTRUCTURE (TPM_PS)(0x0000000B) +#define TPM_PS_VIRTUALIZATION (TPM_PS)(0x0000000C) +#define TPM_PS_TNC (TPM_PS)(0x0000000D) +#define TPM_PS_MULTI_TENANT (TPM_PS)(0x0000000E) +#define TPM_PS_TC (TPM_PS)(0x0000000F) + +// 7 Handles + +// Table 25 - Handles Types +// +// NOTE: Comment because it has same name as TPM1.2 (value is same, so not runtime issue) +// +//typedef UINT32 TPM_HANDLE; + +// Table 26 - TPM_HT Constants +typedef UINT8 TPM_HT; +#define TPM_HT_PCR (TPM_HT)(0x00) +#define TPM_HT_NV_INDEX (TPM_HT)(0x01) +#define TPM_HT_HMAC_SESSION (TPM_HT)(0x02) +#define TPM_HT_LOADED_SESSION (TPM_HT)(0x02) +#define TPM_HT_POLICY_SESSION (TPM_HT)(0x03) +#define TPM_HT_ACTIVE_SESSION (TPM_HT)(0x03) +#define TPM_HT_PERMANENT (TPM_HT)(0x40) +#define TPM_HT_TRANSIENT (TPM_HT)(0x80) +#define TPM_HT_PERSISTENT (TPM_HT)(0x81) + +// Table 27 - TPM_RH Constants +typedef UINT32 TPM_RH; +#define TPM_RH_FIRST (TPM_RH)(0x40000000) +#define TPM_RH_SRK (TPM_RH)(0x40000000) +#define TPM_RH_OWNER (TPM_RH)(0x40000001) +#define TPM_RH_REVOKE (TPM_RH)(0x40000002) +#define TPM_RH_TRANSPORT (TPM_RH)(0x40000003) +#define TPM_RH_OPERATOR (TPM_RH)(0x40000004) +#define TPM_RH_ADMIN (TPM_RH)(0x40000005) +#define TPM_RH_EK (TPM_RH)(0x40000006) +#define TPM_RH_NULL (TPM_RH)(0x40000007) +#define TPM_RH_UNASSIGNED (TPM_RH)(0x40000008) +#define TPM_RS_PW (TPM_RH)(0x40000009) +#define TPM_RH_LOCKOUT (TPM_RH)(0x4000000A) +#define TPM_RH_ENDORSEMENT (TPM_RH)(0x4000000B) +#define TPM_RH_PLATFORM (TPM_RH)(0x4000000C) +#define TPM_RH_PLATFORM_NV (TPM_RH)(0x4000000D) +#define TPM_RH_AUTH_00 (TPM_RH)(0x40000010) +#define TPM_RH_AUTH_FF (TPM_RH)(0x4000010F) +#define TPM_RH_LAST (TPM_RH)(0x4000010F) + +// Table 28 - TPM_HC Constants +typedef TPM_HANDLE TPM_HC; +#define HR_HANDLE_MASK (TPM_HC)(0x00FFFFFF) +#define HR_RANGE_MASK (TPM_HC)(0xFF000000) +#define HR_SHIFT (TPM_HC)(24) +#define HR_PCR (TPM_HC)((TPM_HC)TPM_HT_PCR << HR_SHIFT) +#define HR_HMAC_SESSION (TPM_HC)((TPM_HC)TPM_HT_HMAC_SESSION << HR_SHIFT) +#define HR_POLICY_SESSION (TPM_HC)((TPM_HC)TPM_HT_POLICY_SESSION << HR_SHIFT) +#define HR_TRANSIENT (TPM_HC)((TPM_HC)TPM_HT_TRANSIENT << HR_SHIFT) +#define HR_PERSISTENT (TPM_HC)((TPM_HC)TPM_HT_PERSISTENT << HR_SHIFT) +#define HR_NV_INDEX (TPM_HC)((TPM_HC)TPM_HT_NV_INDEX << HR_SHIFT) +#define HR_PERMANENT (TPM_HC)((TPM_HC)TPM_HT_PERMANENT << HR_SHIFT) +#define PCR_FIRST (TPM_HC)(HR_PCR + 0) +#define PCR_LAST (TPM_HC)(PCR_FIRST + IMPLEMENTATION_PCR - 1) +#define HMAC_SESSION_FIRST (TPM_HC)(HR_HMAC_SESSION + 0) +#define HMAC_SESSION_LAST (TPM_HC)(HMAC_SESSION_FIRST + MAX_ACTIVE_SESSIONS - 1) +#define LOADED_SESSION_FIRST (TPM_HC)(HMAC_SESSION_FIRST) +#define LOADED_SESSION_LAST (TPM_HC)(HMAC_SESSION_LAST) +#define POLICY_SESSION_FIRST (TPM_HC)(HR_POLICY_SESSION + 0) +#define POLICY_SESSION_LAST (TPM_HC)(POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS - 1) +#define TRANSIENT_FIRST (TPM_HC)(HR_TRANSIENT + 0) +#define ACTIVE_SESSION_FIRST (TPM_HC)(POLICY_SESSION_FIRST) +#define ACTIVE_SESSION_LAST (TPM_HC)(POLICY_SESSION_LAST) +#define TRANSIENT_LAST (TPM_HC)(TRANSIENT_FIRST+MAX_LOADED_OBJECTS - 1) +#define PERSISTENT_FIRST (TPM_HC)(HR_PERSISTENT + 0) +#define PERSISTENT_LAST (TPM_HC)(PERSISTENT_FIRST + 0x00FFFFFF) +#define PLATFORM_PERSISTENT (TPM_HC)(PERSISTENT_FIRST + 0x00800000) +#define NV_INDEX_FIRST (TPM_HC)(HR_NV_INDEX + 0) +#define NV_INDEX_LAST (TPM_HC)(NV_INDEX_FIRST + 0x00FFFFFF) +#define PERMANENT_FIRST (TPM_HC)(TPM_RH_FIRST) +#define PERMANENT_LAST (TPM_HC)(TPM_RH_LAST) + +// 8 Attribute Structures + +// Table 29 - TPMA_ALGORITHM Bits +typedef struct { + UINT32 asymmetric : 1; + UINT32 symmetric : 1; + UINT32 hash : 1; + UINT32 object : 1; + UINT32 reserved4_7 : 4; + UINT32 signing : 1; + UINT32 encrypting : 1; + UINT32 method : 1; + UINT32 reserved11_31 : 21; +} TPMA_ALGORITHM; + +// Table 30 - TPMA_OBJECT Bits +typedef struct { + UINT32 reserved1 : 1; + UINT32 fixedTPM : 1; + UINT32 stClear : 1; + UINT32 reserved4 : 1; + UINT32 fixedParent : 1; + UINT32 sensitiveDataOrigin : 1; + UINT32 userWithAuth : 1; + UINT32 adminWithPolicy : 1; + UINT32 reserved8_9 : 2; + UINT32 noDA : 1; + UINT32 encryptedDuplication : 1; + UINT32 reserved12_15 : 4; + UINT32 restricted : 1; + UINT32 decrypt : 1; + UINT32 sign : 1; + UINT32 reserved19_31 : 13; +} TPMA_OBJECT; + +// Table 31 - TPMA_SESSION Bits +typedef struct { + UINT8 continueSession : 1; + UINT8 auditExclusive : 1; + UINT8 auditReset : 1; + UINT8 reserved3_4 : 2; + UINT8 decrypt : 1; + UINT8 encrypt : 1; + UINT8 audit : 1; +} TPMA_SESSION; + +// Table 32 - TPMA_LOCALITY Bits +// +// NOTE: Use low case here to resolve conflict +// +typedef struct { + UINT8 locZero : 1; + UINT8 locOne : 1; + UINT8 locTwo : 1; + UINT8 locThree : 1; + UINT8 locFour : 1; + UINT8 Extended : 3; +} TPMA_LOCALITY; + +// Table 33 - TPMA_PERMANENT Bits +typedef struct { + UINT32 ownerAuthSet : 1; + UINT32 endorsementAuthSet : 1; + UINT32 lockoutAuthSet : 1; + UINT32 reserved3_7 : 5; + UINT32 disableClear : 1; + UINT32 inLockout : 1; + UINT32 tpmGeneratedEPS : 1; + UINT32 reserved11_31 : 21; +} TPMA_PERMANENT; + +// Table 34 - TPMA_STARTUP_CLEAR Bits +typedef struct { + UINT32 phEnable : 1; + UINT32 shEnable : 1; + UINT32 ehEnable : 1; + UINT32 reserved3_30 : 28; + UINT32 orderly : 1; +} TPMA_STARTUP_CLEAR; + +// Table 35 - TPMA_MEMORY Bits +typedef struct { + UINT32 sharedRAM : 1; + UINT32 sharedNV : 1; + UINT32 objectCopiedToRam : 1; + UINT32 reserved3_31 : 29; +} TPMA_MEMORY; + +// Table 36 - TPMA_CC Bits +typedef struct { + UINT32 commandIndex : 16; + UINT32 reserved16_21 : 6; + UINT32 nv : 1; + UINT32 extensive : 1; + UINT32 flushed : 1; + UINT32 cHandles : 3; + UINT32 rHandle : 1; + UINT32 V : 1; + UINT32 Res : 2; +} TPMA_CC; + +// 9 Interface Types + +// Table 37 - TPMI_YES_NO Type +typedef BYTE TPMI_YES_NO; + +// Table 38 - TPMI_DH_OBJECT Type +typedef TPM_HANDLE TPMI_DH_OBJECT; + +// Table 39 - TPMI_DH_PERSISTENT Type +typedef TPM_HANDLE TPMI_DH_PERSISTENT; + +// Table 40 - TPMI_DH_ENTITY Type +typedef TPM_HANDLE TPMI_DH_ENTITY; + +// Table 41 - TPMI_DH_PCR Type +typedef TPM_HANDLE TPMI_DH_PCR; + +// Table 42 - TPMI_SH_AUTH_SESSION Type +typedef TPM_HANDLE TPMI_SH_AUTH_SESSION; + +// Table 43 - TPMI_SH_HMAC Type +typedef TPM_HANDLE TPMI_SH_HMAC; + +// Table 44 - TPMI_SH_POLICY Type +typedef TPM_HANDLE TPMI_SH_POLICY; + +// Table 45 - TPMI_DH_CONTEXT Type +typedef TPM_HANDLE TPMI_DH_CONTEXT; + +// Table 46 - TPMI_RH_HIERARCHY Type +typedef TPM_HANDLE TPMI_RH_HIERARCHY; + +// Table 47 - TPMI_RH_HIERARCHY_AUTH Type +typedef TPM_HANDLE TPMI_RH_HIERARCHY_AUTH; + +// Table 48 - TPMI_RH_PLATFORM Type +typedef TPM_HANDLE TPMI_RH_PLATFORM; + +// Table 49 - TPMI_RH_OWNER Type +typedef TPM_HANDLE TPMI_RH_OWNER; + +// Table 50 - TPMI_RH_ENDORSEMENT Type +typedef TPM_HANDLE TPMI_RH_ENDORSEMENT; + +// Table 51 - TPMI_RH_PROVISION Type +typedef TPM_HANDLE TPMI_RH_PROVISION; + +// Table 52 - TPMI_RH_CLEAR Type +typedef TPM_HANDLE TPMI_RH_CLEAR; + +// Table 53 - TPMI_RH_NV_AUTH Type +typedef TPM_HANDLE TPMI_RH_NV_AUTH; + +// Table 54 - TPMI_RH_LOCKOUT Type +typedef TPM_HANDLE TPMI_RH_LOCKOUT; + +// Table 55 - TPMI_RH_NV_INDEX Type +typedef TPM_HANDLE TPMI_RH_NV_INDEX; + +// Table 56 - TPMI_ALG_HASH Type +typedef TPM_ALG_ID TPMI_ALG_HASH; + +// Table 57 - TPMI_ALG_ASYM Type +typedef TPM_ALG_ID TPMI_ALG_ASYM; + +// Table 58 - TPMI_ALG_SYM Type +typedef TPM_ALG_ID TPMI_ALG_SYM; + +// Table 59 - TPMI_ALG_SYM_OBJECT Type +typedef TPM_ALG_ID TPMI_ALG_SYM_OBJECT; + +// Table 60 - TPMI_ALG_SYM_MODE Type +typedef TPM_ALG_ID TPMI_ALG_SYM_MODE; + +// Table 61 - TPMI_ALG_KDF Type +typedef TPM_ALG_ID TPMI_ALG_KDF; + +// Table 62 - TPMI_ALG_SIG_SCHEME Type +typedef TPM_ALG_ID TPMI_ALG_SIG_SCHEME; + +// Table 63 - TPMI_ECC_KEY_EXCHANGE Type +typedef TPM_ALG_ID TPMI_ECC_KEY_EXCHANGE; + +// Table 64 - TPMI_ST_COMMAND_TAG Type +typedef TPM_ST TPMI_ST_COMMAND_TAG; + +// 10 Structure Definitions + +// Table 65 - TPMS_ALGORITHM_DESCRIPTION Structure +typedef struct { + TPM_ALG_ID alg; + TPMA_ALGORITHM attributes; +} TPMS_ALGORITHM_DESCRIPTION; + +// Table 66 - TPMU_HA Union +typedef union { + BYTE sha1[SHA1_DIGEST_SIZE]; + BYTE sha256[SHA256_DIGEST_SIZE]; + BYTE sm3_256[SM3_256_DIGEST_SIZE]; + BYTE sha384[SHA384_DIGEST_SIZE]; + BYTE sha512[SHA512_DIGEST_SIZE]; +} TPMU_HA; + +// Table 67 - TPMT_HA Structure +typedef struct { + TPMI_ALG_HASH hashAlg; + TPMU_HA digest; +} TPMT_HA; + +// Table 68 - TPM2B_DIGEST Structure +typedef struct { + UINT16 size; + BYTE buffer[sizeof(TPMU_HA)]; +} TPM2B_DIGEST; + +// Table 69 - TPM2B_DATA Structure +typedef struct { + UINT16 size; + BYTE buffer[sizeof(TPMT_HA)]; +} TPM2B_DATA; + +// Table 70 - TPM2B_NONCE Types +typedef TPM2B_DIGEST TPM2B_NONCE; + +// Table 71 - TPM2B_AUTH Types +typedef TPM2B_DIGEST TPM2B_AUTH; + +// Table 72 - TPM2B_OPERAND Types +typedef TPM2B_DIGEST TPM2B_OPERAND; + +// Table 73 - TPM2B_EVENT Structure +typedef struct { + UINT16 size; + BYTE buffer[1024]; +} TPM2B_EVENT; + +// Table 74 - TPM2B_MAX_BUFFER Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_DIGEST_BUFFER]; +} TPM2B_MAX_BUFFER; + +// Table 75 - TPM2B_MAX_NV_BUFFER Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_NV_INDEX_SIZE]; +} TPM2B_MAX_NV_BUFFER; + +// Table 76 - TPM2B_TIMEOUT Structure +typedef struct { + UINT16 size; + BYTE buffer[sizeof(UINT64)]; +} TPM2B_TIMEOUT; + +// Table 77 -- TPM2B_IV Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_SYM_BLOCK_SIZE]; +} TPM2B_IV; + +// Table 78 - TPMU_NAME Union +typedef union { + TPMT_HA digest; + TPM_HANDLE handle; +} TPMU_NAME; + +// Table 79 - TPM2B_NAME Structure +typedef struct { + UINT16 size; + BYTE name[sizeof(TPMU_NAME)]; +} TPM2B_NAME; + +// Table 80 - TPMS_PCR_SELECT Structure +typedef struct { + UINT8 sizeofSelect; + BYTE pcrSelect[PCR_SELECT_MAX]; +} TPMS_PCR_SELECT; + +// Table 81 - TPMS_PCR_SELECTION Structure +typedef struct { + TPMI_ALG_HASH hash; + UINT8 sizeofSelect; + BYTE pcrSelect[PCR_SELECT_MAX]; +} TPMS_PCR_SELECTION; + +// Table 84 - TPMT_TK_CREATION Structure +typedef struct { + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_CREATION; + +// Table 85 - TPMT_TK_VERIFIED Structure +typedef struct { + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_VERIFIED; + +// Table 86 - TPMT_TK_AUTH Structure +typedef struct { + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_AUTH; + +// Table 87 - TPMT_TK_HASHCHECK Structure +typedef struct { + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_HASHCHECK; + +// Table 88 - TPMS_ALG_PROPERTY Structure +typedef struct { + TPM_ALG_ID alg; + TPMA_ALGORITHM algProperties; +} TPMS_ALG_PROPERTY; + +// Table 89 - TPMS_TAGGED_PROPERTY Structure +typedef struct { + TPM_PT property; + UINT32 value; +} TPMS_TAGGED_PROPERTY; + +// Table 90 - TPMS_TAGGED_PCR_SELECT Structure +typedef struct { + TPM_PT tag; + UINT8 sizeofSelect; + BYTE pcrSelect[PCR_SELECT_MAX]; +} TPMS_TAGGED_PCR_SELECT; + +// Table 91 - TPML_CC Structure +typedef struct { + UINT32 count; + TPM_CC commandCodes[MAX_CAP_CC]; +} TPML_CC; + +// Table 92 - TPML_CCA Structure +typedef struct { + UINT32 count; + TPMA_CC commandAttributes[MAX_CAP_CC]; +} TPML_CCA; + +// Table 93 - TPML_ALG Structure +typedef struct { + UINT32 count; + TPM_ALG_ID algorithms[MAX_ALG_LIST_SIZE]; +} TPML_ALG; + +// Table 94 - TPML_HANDLE Structure +typedef struct { + UINT32 count; + TPM_HANDLE handle[MAX_CAP_HANDLES]; +} TPML_HANDLE; + +// Table 95 - TPML_DIGEST Structure +typedef struct { + UINT32 count; + TPM2B_DIGEST digests[8]; +} TPML_DIGEST; + +// Table 96 -- TPML_DIGEST_VALUES Structure +typedef struct { + UINT32 count; + TPMT_HA digests[HASH_COUNT]; +} TPML_DIGEST_VALUES; + +// Table 97 - TPM2B_DIGEST_VALUES Structure +typedef struct { + UINT16 size; + BYTE buffer[sizeof(TPML_DIGEST_VALUES)]; +} TPM2B_DIGEST_VALUES; + +// Table 98 - TPML_PCR_SELECTION Structure +typedef struct { + UINT32 count; + TPMS_PCR_SELECTION pcrSelections[HASH_COUNT]; +} TPML_PCR_SELECTION; + +// Table 99 - TPML_ALG_PROPERTY Structure +typedef struct { + UINT32 count; + TPMS_ALG_PROPERTY algProperties[MAX_CAP_ALGS]; +} TPML_ALG_PROPERTY; + +// Table 100 - TPML_TAGGED_TPM_PROPERTY Structure +typedef struct { + UINT32 count; + TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; +} TPML_TAGGED_TPM_PROPERTY; + +// Table 101 - TPML_TAGGED_PCR_PROPERTY Structure +typedef struct { + UINT32 count; + TPMS_TAGGED_PCR_SELECT pcrProperty[MAX_PCR_PROPERTIES]; +} TPML_TAGGED_PCR_PROPERTY; + +// Table 102 - TPML_ECC_CURVE Structure +typedef struct { + UINT32 count; + TPM_ECC_CURVE eccCurves[MAX_ECC_CURVES]; +} TPML_ECC_CURVE; + +// Table 103 - TPMU_CAPABILITIES Union +typedef union { + TPML_ALG_PROPERTY algorithms; + TPML_HANDLE handles; + TPML_CCA command; + TPML_CC ppCommands; + TPML_CC auditCommands; + TPML_PCR_SELECTION assignedPCR; + TPML_TAGGED_TPM_PROPERTY tpmProperties; + TPML_TAGGED_PCR_PROPERTY pcrProperties; + TPML_ECC_CURVE eccCurves; +} TPMU_CAPABILITIES; + +// Table 104 - TPMS_CAPABILITY_DATA Structure +typedef struct { + TPM_CAP capability; + TPMU_CAPABILITIES data; +} TPMS_CAPABILITY_DATA; + +// Table 105 - TPMS_CLOCK_INFO Structure +typedef struct { + UINT64 clock; + UINT32 resetCount; + UINT32 restartCount; + TPMI_YES_NO safe; +} TPMS_CLOCK_INFO; + +// Table 106 - TPMS_TIME_INFO Structure +typedef struct { + UINT64 time; + TPMS_CLOCK_INFO clockInfo; +} TPMS_TIME_INFO; + +// Table 107 - TPMS_TIME_ATTEST_INFO Structure +typedef struct { + TPMS_TIME_INFO time; + UINT64 firmwareVersion; +} TPMS_TIME_ATTEST_INFO; + +// Table 108 - TPMS_CERTIFY_INFO Structure +typedef struct { + TPM2B_NAME name; + TPM2B_NAME qualifiedName; +} TPMS_CERTIFY_INFO; + +// Table 109 - TPMS_QUOTE_INFO Structure +typedef struct { + TPML_PCR_SELECTION pcrSelect; + TPM2B_DIGEST pcrDigest; +} TPMS_QUOTE_INFO; + +// Table 110 - TPMS_COMMAND_AUDIT_INFO Structure +typedef struct { + UINT64 auditCounter; + TPM_ALG_ID digestAlg; + TPM2B_DIGEST auditDigest; + TPM2B_DIGEST commandDigest; +} TPMS_COMMAND_AUDIT_INFO; + +// Table 111 - TPMS_SESSION_AUDIT_INFO Structure +typedef struct { + TPMI_YES_NO exclusiveSession; + TPM2B_DIGEST sessionDigest; +} TPMS_SESSION_AUDIT_INFO; + +// Table 112 - TPMS_CREATION_INFO Structure +typedef struct { + TPM2B_NAME objectName; + TPM2B_DIGEST creationHash; +} TPMS_CREATION_INFO; + +// Table 113 - TPMS_NV_CERTIFY_INFO Structure +typedef struct { + TPM2B_NAME indexName; + UINT16 offset; + TPM2B_MAX_NV_BUFFER nvContents; +} TPMS_NV_CERTIFY_INFO; + +// Table 114 - TPMI_ST_ATTEST Type +typedef TPM_ST TPMI_ST_ATTEST; + +// Table 115 - TPMU_ATTEST Union +typedef union { + TPMS_CERTIFY_INFO certify; + TPMS_CREATION_INFO creation; + TPMS_QUOTE_INFO quote; + TPMS_COMMAND_AUDIT_INFO commandAudit; + TPMS_SESSION_AUDIT_INFO sessionAudit; + TPMS_TIME_ATTEST_INFO time; + TPMS_NV_CERTIFY_INFO nv; +} TPMU_ATTEST; + +// Table 116 - TPMS_ATTEST Structure +typedef struct { + TPM_GENERATED magic; + TPMI_ST_ATTEST type; + TPM2B_NAME qualifiedSigner; + TPM2B_DATA extraData; + TPMS_CLOCK_INFO clockInfo; + UINT64 firmwareVersion; + TPMU_ATTEST attested; +} TPMS_ATTEST; + +// Table 117 - TPM2B_ATTEST Structure +typedef struct { + UINT16 size; + BYTE attestationData[sizeof(TPMS_ATTEST)]; +} TPM2B_ATTEST; + +// Table 118 - TPMS_AUTH_COMMAND Structure +typedef struct { + TPMI_SH_AUTH_SESSION sessionHandle; + TPM2B_NONCE nonce; + TPMA_SESSION sessionAttributes; + TPM2B_AUTH hmac; +} TPMS_AUTH_COMMAND; + +// Table 119 - TPMS_AUTH_RESPONSE Structure +typedef struct { + TPM2B_NONCE nonce; + TPMA_SESSION sessionAttributes; + TPM2B_AUTH hmac; +} TPMS_AUTH_RESPONSE; + +// 11 Algorithm Parameters and Structures + +// Table 120 - TPMI_AES_KEY_BITS Type +typedef TPM_KEY_BITS TPMI_AES_KEY_BITS; + +// Table 121 - TPMI_SM4_KEY_BITS Type +typedef TPM_KEY_BITS TPMI_SM4_KEY_BITS; + +// Table 122 - TPMU_SYM_KEY_BITS Union +typedef union { + TPMI_AES_KEY_BITS aes; + TPMI_SM4_KEY_BITS SM4; + TPM_KEY_BITS sym; + TPMI_ALG_HASH xor; +} TPMU_SYM_KEY_BITS; + +// Table 123 - TPMU_SYM_MODE Union +typedef union { + TPMI_ALG_SYM_MODE aes; + TPMI_ALG_SYM_MODE SM4; + TPMI_ALG_SYM_MODE sym; +} TPMU_SYM_MODE; + +// Table 125 - TPMT_SYM_DEF Structure +typedef struct { + TPMI_ALG_SYM algorithm; + TPMU_SYM_KEY_BITS keyBits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF; + +// Table 126 - TPMT_SYM_DEF_OBJECT Structure +typedef struct { + TPMI_ALG_SYM_OBJECT algorithm; + TPMU_SYM_KEY_BITS keyBits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF_OBJECT; + +// Table 127 - TPM2B_SYM_KEY Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_SYM_KEY_BYTES]; +} TPM2B_SYM_KEY; + +// Table 128 - TPMS_SYMCIPHER_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT sym; +} TPMS_SYMCIPHER_PARMS; + +// Table 129 - TPM2B_SENSITIVE_DATA Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_SYM_DATA]; +} TPM2B_SENSITIVE_DATA; + +// Table 130 - TPMS_SENSITIVE_CREATE Structure +typedef struct { + TPM2B_AUTH userAuth; + TPM2B_SENSITIVE_DATA data; +} TPMS_SENSITIVE_CREATE; + +// Table 131 - TPM2B_SENSITIVE_CREATE Structure +typedef struct { + UINT16 size; + TPMS_SENSITIVE_CREATE sensitive; +} TPM2B_SENSITIVE_CREATE; + +// Table 132 - TPMS_SCHEME_SIGHASH Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_SIGHASH; + +// Table 133 - TPMI_ALG_KEYEDHASH_SCHEME Type +typedef TPM_ALG_ID TPMI_ALG_KEYEDHASH_SCHEME; + +// Table 134 - HMAC_SIG_SCHEME Types +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_HMAC; + +// Table 135 - TPMS_SCHEME_XOR Structure +typedef struct { + TPMI_ALG_HASH hashAlg; + TPMI_ALG_KDF kdf; +} TPMS_SCHEME_XOR; + +// Table 136 - TPMU_SCHEME_KEYEDHASH Union +typedef union { + TPMS_SCHEME_HMAC hmac; + TPMS_SCHEME_XOR xor; +} TPMU_SCHEME_KEYEDHASH; + +// Table 137 - TPMT_KEYEDHASH_SCHEME Structure +typedef struct { + TPMI_ALG_KEYEDHASH_SCHEME scheme; + TPMU_SCHEME_KEYEDHASH details; +} TPMT_KEYEDHASH_SCHEME; + +// Table 138 - RSA_SIG_SCHEMES Types +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSASSA; +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSAPSS; + +// Table 139 - ECC_SIG_SCHEMES Types +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECDSA; +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_SM2; +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECSCHNORR; + +// Table 140 - TPMS_SCHEME_ECDAA Structure +typedef struct { + TPMI_ALG_HASH hashAlg; + UINT16 count; +} TPMS_SCHEME_ECDAA; + +// Table 141 - TPMU_SIG_SCHEME Union +typedef union { + TPMS_SCHEME_RSASSA rsassa; + TPMS_SCHEME_RSAPSS rsapss; + TPMS_SCHEME_ECDSA ecdsa; + TPMS_SCHEME_ECDAA ecdaa; + TPMS_SCHEME_ECSCHNORR ecSchnorr; + TPMS_SCHEME_HMAC hmac; + TPMS_SCHEME_SIGHASH any; +} TPMU_SIG_SCHEME; + +// Table 142 - TPMT_SIG_SCHEME Structure +typedef struct { + TPMI_ALG_SIG_SCHEME scheme; + TPMU_SIG_SCHEME details; +} TPMT_SIG_SCHEME; + +// Table 143 - TPMS_SCHEME_OAEP Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_OAEP; + +// Table 144 - TPMS_SCHEME_ECDH Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_ECDH; + +// Table 145 - TPMS_SCHEME_MGF1 Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_MGF1; + +// Table 146 - TPMS_SCHEME_KDF1_SP800_56a Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_KDF1_SP800_56a; + +// Table 147 - TPMS_SCHEME_KDF2 Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_KDF2; + +// Table 148 - TPMS_SCHEME_KDF1_SP800_108 Structure +typedef struct { + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_KDF1_SP800_108; + +// Table 149 - TPMU_KDF_SCHEME Union +typedef union { + TPMS_SCHEME_MGF1 mgf1; + TPMS_SCHEME_KDF1_SP800_56a kdf1_SP800_56a; + TPMS_SCHEME_KDF2 kdf2; + TPMS_SCHEME_KDF1_SP800_108 kdf1_sp800_108; +} TPMU_KDF_SCHEME; + +// Table 150 - TPMT_KDF_SCHEME Structure +typedef struct { + TPMI_ALG_KDF scheme; + TPMU_KDF_SCHEME details; +} TPMT_KDF_SCHEME; + +// Table 151 - TPMI_ALG_ASYM_SCHEME Type +typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME; + +// Table 152 - TPMU_ASYM_SCHEME Union +typedef union { + TPMS_SCHEME_RSASSA rsassa; + TPMS_SCHEME_RSAPSS rsapss; + TPMS_SCHEME_OAEP oaep; + TPMS_SCHEME_ECDSA ecdsa; + TPMS_SCHEME_ECDAA ecdaa; + TPMS_SCHEME_ECSCHNORR ecSchnorr; + TPMS_SCHEME_SIGHASH anySig; +} TPMU_ASYM_SCHEME; + +// Table 153 - TPMT_ASYM_SCHEME Structure +typedef struct { + TPMI_ALG_ASYM_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_ASYM_SCHEME; + +// Table 154 - TPMI_ALG_RSA_SCHEME Type +typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME; + +// Table 155 - TPMT_RSA_SCHEME Structure +typedef struct { + TPMI_ALG_RSA_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_SCHEME; + +// Table 156 - TPMI_ALG_RSA_DECRYPT Type +typedef TPM_ALG_ID TPMI_ALG_RSA_DECRYPT; + +// Table 157 - TPMT_RSA_DECRYPT Structure +typedef struct { + TPMI_ALG_RSA_DECRYPT scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_DECRYPT; + +// Table 158 - TPM2B_PUBLIC_KEY_RSA Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_RSA_KEY_BYTES]; +} TPM2B_PUBLIC_KEY_RSA; + +// Table 159 - TPMI_RSA_KEY_BITS Type +typedef TPM_KEY_BITS TPMI_RSA_KEY_BITS; + +// Table 160 - TPM2B_PRIVATE_KEY_RSA Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_RSA_KEY_BYTES/2]; +} TPM2B_PRIVATE_KEY_RSA; + +// Table 161 - TPM2B_ECC_PARAMETER Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_ECC_KEY_BYTES]; +} TPM2B_ECC_PARAMETER; + +// Table 162 - TPMS_ECC_POINT Structure +typedef struct { + TPM2B_ECC_PARAMETER x; + TPM2B_ECC_PARAMETER y; +} TPMS_ECC_POINT; + +// Table 163 -- TPM2B_ECC_POINT Structure +typedef struct { + UINT16 size; + TPMS_ECC_POINT point; +} TPM2B_ECC_POINT; + +// Table 164 - TPMI_ALG_ECC_SCHEME Type +typedef TPM_ALG_ID TPMI_ALG_ECC_SCHEME; + +// Table 165 - TPMI_ECC_CURVE Type +typedef TPM_ECC_CURVE TPMI_ECC_CURVE; + +// Table 166 - TPMT_ECC_SCHEME Structure +typedef struct { + TPMI_ALG_ECC_SCHEME scheme; + TPMU_SIG_SCHEME details; +} TPMT_ECC_SCHEME; + +// Table 167 - TPMS_ALGORITHM_DETAIL_ECC Structure +typedef struct { + TPM_ECC_CURVE curveID; + UINT16 keySize; + TPMT_KDF_SCHEME kdf; + TPMT_ECC_SCHEME sign; + TPM2B_ECC_PARAMETER p; + TPM2B_ECC_PARAMETER a; + TPM2B_ECC_PARAMETER b; + TPM2B_ECC_PARAMETER gX; + TPM2B_ECC_PARAMETER gY; + TPM2B_ECC_PARAMETER n; + TPM2B_ECC_PARAMETER h; +} TPMS_ALGORITHM_DETAIL_ECC; + +// Table 168 - TPMS_SIGNATURE_RSASSA Structure +typedef struct { + TPMI_ALG_HASH hash; + TPM2B_PUBLIC_KEY_RSA sig; +} TPMS_SIGNATURE_RSASSA; + +// Table 169 - TPMS_SIGNATURE_RSAPSS Structure +typedef struct { + TPMI_ALG_HASH hash; + TPM2B_PUBLIC_KEY_RSA sig; +} TPMS_SIGNATURE_RSAPSS; + +// Table 170 - TPMS_SIGNATURE_ECDSA Structure +typedef struct { + TPMI_ALG_HASH hash; + TPM2B_ECC_PARAMETER signatureR; + TPM2B_ECC_PARAMETER signatureS; +} TPMS_SIGNATURE_ECDSA; + +// Table 171 - TPMU_SIGNATURE Union +typedef union { + TPMS_SIGNATURE_RSASSA rsassa; + TPMS_SIGNATURE_RSAPSS rsapss; + TPMS_SIGNATURE_ECDSA ecdsa; + TPMS_SIGNATURE_ECDSA sm2; + TPMS_SIGNATURE_ECDSA ecdaa; + TPMS_SIGNATURE_ECDSA ecschnorr; + TPMT_HA hmac; + TPMS_SCHEME_SIGHASH any; +} TPMU_SIGNATURE; + +// Table 172 - TPMT_SIGNATURE Structure +typedef struct { + TPMI_ALG_SIG_SCHEME sigAlg; + TPMU_SIGNATURE signature; +} TPMT_SIGNATURE; + +// Table 173 - TPMU_ENCRYPTED_SECRET Union +typedef union { + BYTE ecc[sizeof(TPMS_ECC_POINT)]; + BYTE rsa[MAX_RSA_KEY_BYTES]; + BYTE symmetric[sizeof(TPM2B_DIGEST)]; + BYTE keyedHash[sizeof(TPM2B_DIGEST)]; +} TPMU_ENCRYPTED_SECRET; + +// Table 174 - TPM2B_ENCRYPTED_SECRET Structure +typedef struct { + UINT16 size; + BYTE secret[sizeof(TPMU_ENCRYPTED_SECRET)]; +} TPM2B_ENCRYPTED_SECRET; + +// 12 Key/Object Complex + +// Table 175 - TPMI_ALG_PUBLIC Type +typedef TPM_ALG_ID TPMI_ALG_PUBLIC; + +// Table 176 - TPMU_PUBLIC_ID Union +typedef union { + TPM2B_DIGEST keyedHash; + TPM2B_DIGEST sym; + TPM2B_PUBLIC_KEY_RSA rsa; + TPMS_ECC_POINT ecc; +} TPMU_PUBLIC_ID; + +// Table 177 - TPMS_KEYEDHASH_PARMS Structure +typedef struct { + TPMT_KEYEDHASH_SCHEME scheme; +} TPMS_KEYEDHASH_PARMS; + +// Table 178 - TPMS_ASYM_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ASYM_SCHEME scheme; +} TPMS_ASYM_PARMS; + +// Table 179 - TPMS_RSA_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_RSA_SCHEME scheme; + TPMI_RSA_KEY_BITS keyBits; + UINT32 exponent; +} TPMS_RSA_PARMS; + +// Table 180 - TPMS_ECC_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ECC_SCHEME scheme; + TPMI_ECC_CURVE curveID; + TPMT_KDF_SCHEME kdf; +} TPMS_ECC_PARMS; + +// Table 181 - TPMU_PUBLIC_PARMS Union +typedef union { + TPMS_KEYEDHASH_PARMS keyedHashDetail; + TPMT_SYM_DEF_OBJECT symDetail; + TPMS_RSA_PARMS rsaDetail; + TPMS_ECC_PARMS eccDetail; + TPMS_ASYM_PARMS asymDetail; +} TPMU_PUBLIC_PARMS; + +// Table 182 - TPMT_PUBLIC_PARMS Structure +typedef struct { + TPMI_ALG_PUBLIC type; + TPMU_PUBLIC_PARMS parameters; +} TPMT_PUBLIC_PARMS; + +// Table 183 - TPMT_PUBLIC Structure +typedef struct { + TPMI_ALG_PUBLIC type; + TPMI_ALG_HASH nameAlg; + TPMA_OBJECT objectAttributes; + TPM2B_DIGEST authPolicy; + TPMU_PUBLIC_PARMS parameters; + TPMU_PUBLIC_ID unique; +} TPMT_PUBLIC; + +// Table 184 - TPM2B_PUBLIC Structure +typedef struct { + UINT16 size; + TPMT_PUBLIC publicArea; +} TPM2B_PUBLIC; + +// Table 185 - TPM2B_PRIVATE_VENDOR_SPECIFIC Structure +typedef struct { + UINT16 size; + BYTE buffer[PRIVATE_VENDOR_SPECIFIC_BYTES]; +} TPM2B_PRIVATE_VENDOR_SPECIFIC; + +// Table 186 - TPMU_SENSITIVE_COMPOSITE Union +typedef union { + TPM2B_PRIVATE_KEY_RSA rsa; + TPM2B_ECC_PARAMETER ecc; + TPM2B_SENSITIVE_DATA bits; + TPM2B_SYM_KEY sym; + TPM2B_PRIVATE_VENDOR_SPECIFIC any; +} TPMU_SENSITIVE_COMPOSITE; + +// Table 187 - TPMT_SENSITIVE Structure +typedef struct { + TPMI_ALG_PUBLIC sensitiveType; + TPM2B_AUTH authValue; + TPM2B_DIGEST seedValue; + TPMU_SENSITIVE_COMPOSITE sensitive; +} TPMT_SENSITIVE; + +// Table 188 - TPM2B_SENSITIVE Structure +typedef struct { + UINT16 size; + TPMT_SENSITIVE sensitiveArea; +} TPM2B_SENSITIVE; + +// Table 189 - _PRIVATE Structure +typedef struct { + TPM2B_DIGEST integrityOuter; + TPM2B_DIGEST integrityInner; + TPMT_SENSITIVE sensitive; +} _PRIVATE; + +// Table 190 - TPM2B_PRIVATE Structure +typedef struct { + UINT16 size; + BYTE buffer[sizeof(_PRIVATE)]; +} TPM2B_PRIVATE; + +// Table 191 - _ID_OBJECT Structure +typedef struct { + TPM2B_DIGEST integrityHMAC; + TPM2B_DIGEST encIdentity; +} _ID_OBJECT; + +// Table 192 - TPM2B_ID_OBJECT Structure +typedef struct { + UINT16 size; + BYTE credential[sizeof(_ID_OBJECT)]; +} TPM2B_ID_OBJECT; + +// 13 NV Storage Structures + +// Table 193 - TPM_NV_INDEX Bits +// +// NOTE: Comment here to resolve conflict +// +//typedef struct { +// UINT32 index : 22; +// UINT32 space : 2; +// UINT32 RH_NV : 8; +//} TPM_NV_INDEX; + +// Table 195 - TPMA_NV Bits +typedef struct { + UINT32 TPMA_NV_PPWRITE : 1; + UINT32 TPMA_NV_OWNERWRITE : 1; + UINT32 TPMA_NV_AUTHWRITE : 1; + UINT32 TPMA_NV_POLICYWRITE : 1; + UINT32 TPMA_NV_COUNTER : 1; + UINT32 TPMA_NV_BITS : 1; + UINT32 TPMA_NV_EXTEND : 1; + UINT32 reserved7_9 : 3; + UINT32 TPMA_NV_POLICY_DELETE : 1; + UINT32 TPMA_NV_WRITELOCKED : 1; + UINT32 TPMA_NV_WRITEALL : 1; + UINT32 TPMA_NV_WRITEDEFINE : 1; + UINT32 TPMA_NV_WRITE_STCLEAR : 1; + UINT32 TPMA_NV_GLOBALLOCK : 1; + UINT32 TPMA_NV_PPREAD : 1; + UINT32 TPMA_NV_OWNERREAD : 1; + UINT32 TPMA_NV_AUTHREAD : 1; + UINT32 TPMA_NV_POLICYREAD : 1; + UINT32 reserved20_24 : 5; + UINT32 TPMA_NV_NO_DA : 1; + UINT32 TPMA_NV_ORDERLY : 1; + UINT32 TPMA_NV_CLEAR_STCLEAR : 1; + UINT32 TPMA_NV_READLOCKED : 1; + UINT32 TPMA_NV_WRITTEN : 1; + UINT32 TPMA_NV_PLATFORMCREATE : 1; + UINT32 TPMA_NV_READ_STCLEAR : 1; +} TPMA_NV; + +// Table 196 - TPMS_NV_PUBLIC Structure +typedef struct { + TPMI_RH_NV_INDEX nvIndex; + TPMI_ALG_HASH nameAlg; + TPMA_NV attributes; + TPM2B_DIGEST authPolicy; + UINT16 dataSize; +} TPMS_NV_PUBLIC; + +// Table 197 - TPM2B_NV_PUBLIC Structure +typedef struct { + UINT16 size; + TPMS_NV_PUBLIC nvPublic; +} TPM2B_NV_PUBLIC; + +// 14 Context Data + +// Table 198 - TPM2B_CONTEXT_SENSITIVE Structure +typedef struct { + UINT16 size; + BYTE buffer[MAX_CONTEXT_SIZE]; +} TPM2B_CONTEXT_SENSITIVE; + +// Table 199 - TPMS_CONTEXT_DATA Structure +typedef struct { + TPM2B_DIGEST integrity; + TPM2B_CONTEXT_SENSITIVE encrypted; +} TPMS_CONTEXT_DATA; + +// Table 200 - TPM2B_CONTEXT_DATA Structure +typedef struct { + UINT16 size; + BYTE buffer[sizeof(TPMS_CONTEXT_DATA)]; +} TPM2B_CONTEXT_DATA; + +// Table 201 - TPMS_CONTEXT Structure +typedef struct { + UINT64 sequence; + TPMI_DH_CONTEXT savedHandle; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_CONTEXT_DATA contextBlob; +} TPMS_CONTEXT; + +// 15 Creation Data + +// Table 203 - TPMS_CREATION_DATA Structure +typedef struct { + TPML_PCR_SELECTION pcrSelect; + TPM2B_DIGEST pcrDigest; + TPMA_LOCALITY locality; + TPM_ALG_ID parentNameAlg; + TPM2B_NAME parentName; + TPM2B_NAME parentQualifiedName; + TPM2B_DATA outsideInfo; +} TPMS_CREATION_DATA; + +// Table 204 - TPM2B_CREATION_DATA Structure +typedef struct { + UINT16 size; + TPMS_CREATION_DATA creationData; +} TPM2B_CREATION_DATA; + + +// +// Command Header +// +typedef struct { + TPM_ST tag; + UINT32 paramSize; + TPM_CC commandCode; +} TPM2_COMMAND_HEADER; + +typedef struct { + TPM_ST tag; + UINT32 paramSize; + TPM_RC responseCode; +} TPM2_RESPONSE_HEADER; + +#pragma pack () + +// +// TCG Algorithm Registry +// +#define HASH_ALG_SHA1 0x00000001 +#define HASH_ALG_SHA256 0x00000002 +#define HASH_ALG_SHA384 0x00000004 +#define HASH_ALG_SHA512 0x00000008 +#define HASH_ALG_SM3_256 0x00000010 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm2Acpi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm2Acpi.h new file mode 100644 index 0000000..0d477da --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Tpm2Acpi.h @@ -0,0 +1,59 @@ +/** @file + TPM2 ACPI table definition. + +Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TPM2_ACPI_H_ +#define _TPM2_ACPI_H_ + +#include + +#pragma pack (1) + +#define EFI_TPM2_ACPI_TABLE_REVISION_3 3 +#define EFI_TPM2_ACPI_TABLE_REVISION_4 4 +#define EFI_TPM2_ACPI_TABLE_REVISION EFI_TPM2_ACPI_TABLE_REVISION_4 + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + // Flags field is replaced in version 4 and above + // BIT0~15: PlatformClass This field is only valid for version 4 and above + // BIT16~31: Reserved + UINT32 Flags; + UINT64 AddressOfControlArea; + UINT32 StartMethod; +//UINT8 PlatformSpecificParameters[]; // size up to 12 +//UINT32 Laml; // Optional +//UINT32 Lasa; // Optional +} EFI_TPM2_ACPI_TABLE; + +#define EFI_TPM2_ACPI_TABLE_START_METHOD_ACPI 2 +#define EFI_TPM2_ACPI_TABLE_START_METHOD_TIS 6 +#define EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE 7 +#define EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_ACPI 8 +#define EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE_WITH_SMC 11 + +typedef struct { + UINT32 Reserved; + UINT32 Error; + UINT32 Cancel; + UINT32 Start; + UINT64 InterruptControl; + UINT32 CommandSize; + UINT64 Command; + UINT32 ResponseSize; + UINT64 Response; +} EFI_TPM2_ACPI_CONTROL_AREA; + +#pragma pack () + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmPtp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmPtp.h new file mode 100644 index 0000000..1e15bf8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmPtp.h @@ -0,0 +1,523 @@ +/** @file + Platform TPM Profile Specification definition for TPM2.0. + It covers both FIFO and CRB interface. + +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TPM_PTP_H_ +#define _TPM_PTP_H_ + +// +// PTP FIFO definition +// + +// +// Set structure alignment to 1-byte +// +#pragma pack (1) + +// +// Register set map as specified in PTP specification Chapter 5 +// +typedef struct { + /// + /// Used to gain ownership for this particular port. + /// + UINT8 Access; // 0 + UINT8 Reserved1[7]; // 1 + /// + /// Controls interrupts. + /// + UINT32 IntEnable; // 8 + /// + /// SIRQ vector to be used by the TPM. + /// + UINT8 IntVector; // 0ch + UINT8 Reserved2[3]; // 0dh + /// + /// What caused interrupt. + /// + UINT32 IntSts; // 10h + /// + /// Shows which interrupts are supported by that particular TPM. + /// + UINT32 InterfaceCapability;// 14h + /// + /// Status Register. Provides status of the TPM. + /// + UINT8 Status; // 18h + /// + /// Number of consecutive writes that can be done to the TPM. + /// + UINT16 BurstCount; // 19h + /// + /// Additional Status Register. + /// + UINT8 StatusEx; // 1Bh + UINT8 Reserved3[8]; + /// + /// Read or write FIFO, depending on transaction. + /// + UINT32 DataFifo; // 24h + UINT8 Reserved4[8]; // 28h + /// + /// Used to identify the Interface types supported by the TPM. + /// + UINT32 InterfaceId; // 30h + UINT8 Reserved5[0x4c]; // 34h + /// + /// Extended ReadFIFO or WriteFIFO, depending on the current bus cycle (read or write) + /// + UINT32 XDataFifo; // 80h + UINT8 Reserved6[0xe7c]; // 84h + /// + /// Vendor ID + /// + UINT16 Vid; // 0f00h + /// + /// Device ID + /// + UINT16 Did; // 0f02h + /// + /// Revision ID + /// + UINT8 Rid; // 0f04h + UINT8 Reserved[0xfb]; // 0f05h +} PTP_FIFO_REGISTERS; + +// +// Restore original structure alignment +// +#pragma pack () + +// +// Define pointer types used to access TIS registers on PC +// +typedef PTP_FIFO_REGISTERS *PTP_FIFO_REGISTERS_PTR; + +// +// Define bits of FIFO Interface Identifier Register +// +typedef union { + struct { + UINT32 InterfaceType:4; + UINT32 InterfaceVersion:4; + UINT32 CapLocality:1; + UINT32 Reserved1:2; + UINT32 CapDataXferSizeSupport:2; + UINT32 CapFIFO:1; + UINT32 CapCRB:1; + UINT32 CapIFRes:2; + UINT32 InterfaceSelector:2; + UINT32 IntfSelLock:1; + UINT32 Reserved2:4; + UINT32 Reserved3:8; + } Bits; + UINT32 Uint32; +} PTP_FIFO_INTERFACE_IDENTIFIER; + +// +// Define bits of FIFO Interface Capability Register +// +typedef union { + struct { + UINT32 DataAvailIntSupport:1; + UINT32 StsValidIntSupport:1; + UINT32 LocalityChangeIntSupport:1; + UINT32 InterruptLevelHigh:1; + UINT32 InterruptLevelLow:1; + UINT32 InterruptEdgeRising:1; + UINT32 InterruptEdgeFalling:1; + UINT32 CommandReadyIntSupport:1; + UINT32 BurstCountStatic:1; + UINT32 DataTransferSizeSupport:2; + UINT32 Reserved:17; + UINT32 InterfaceVersion:3; + UINT32 Reserved2:1; + } Bits; + UINT32 Uint32; +} PTP_FIFO_INTERFACE_CAPABILITY; + +/// +/// InterfaceVersion +/// +#define INTERFACE_CAPABILITY_INTERFACE_VERSION_TIS_12 0x0 +#define INTERFACE_CAPABILITY_INTERFACE_VERSION_TIS_13 0x2 +#define INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP 0x3 + + +// +// Define bits of ACCESS and STATUS registers +// + +/// +/// This bit is a 1 to indicate that the other bits in this register are valid. +/// +#define PTP_FIFO_VALID BIT7 +/// +/// Indicate that this locality is active. +/// +#define PTP_FIFO_ACC_ACTIVE BIT5 +/// +/// Set to 1 to indicate that this locality had the TPM taken away while +/// this locality had the TIS_PC_ACC_ACTIVE bit set. +/// +#define PTP_FIFO_ACC_SEIZED BIT4 +/// +/// Set to 1 to indicate that TPM MUST reset the +/// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the +/// locality that is writing this bit. +/// +#define PTP_FIFO_ACC_SEIZE BIT3 +/// +/// When this bit is 1, another locality is requesting usage of the TPM. +/// +#define PTP_FIFO_ACC_PENDIND BIT2 +/// +/// Set to 1 to indicate that this locality is requesting to use TPM. +/// +#define PTP_FIFO_ACC_RQUUSE BIT1 +/// +/// A value of 1 indicates that a T/OS has not been established on the platform +/// +#define PTP_FIFO_ACC_ESTABLISH BIT0 + +/// +/// This field indicates that STS_DATA and STS_EXPECT are valid +/// +#define PTP_FIFO_STS_VALID BIT7 +/// +/// When this bit is 1, TPM is in the Ready state, +/// indicating it is ready to receive a new command. +/// +#define PTP_FIFO_STS_READY BIT6 +/// +/// Write a 1 to this bit to cause the TPM to execute that command. +/// +#define PTP_FIFO_STS_GO BIT5 +/// +/// This bit indicates that the TPM has data available as a response. +/// +#define PTP_FIFO_STS_DATA BIT4 +/// +/// The TPM sets this bit to a value of 1 when it expects another byte of data for a command. +/// +#define PTP_FIFO_STS_EXPECT BIT3 +/// +/// Indicates that the TPM has completed all self-test actions following a TPM_ContinueSelfTest command. +/// +#define PTP_FIFO_STS_SELFTEST_DONE BIT2 +/// +/// Writes a 1 to this bit to force the TPM to re-send the response. +/// +#define PTP_FIFO_STS_RETRY BIT1 + +/// +/// TPM Family Identifier. +/// 00: TPM 1.2 Family +/// 01: TPM 2.0 Family +/// +#define PTP_FIFO_STS_EX_TPM_FAMILY (BIT2 | BIT3) +#define PTP_FIFO_STS_EX_TPM_FAMILY_OFFSET (2) +#define PTP_FIFO_STS_EX_TPM_FAMILY_TPM12 (0) +#define PTP_FIFO_STS_EX_TPM_FAMILY_TPM20 (BIT2) +/// +/// A write of 1 after tpmGo and before dataAvail aborts the currently executing command, resulting in a response of TPM_RC_CANCELLED. +/// A write of 1 after dataAvail and before tpmGo is ignored by the TPM. +/// +#define PTP_FIFO_STS_EX_CANCEL BIT0 + + +// +// PTP CRB definition +// + +// +// Set structure alignment to 1-byte +// +#pragma pack (1) + +// +// Register set map as specified in PTP specification Chapter 5 +// +typedef struct { + /// + /// Used to determine current state of Locality of the TPM. + /// + UINT32 LocalityState; // 0 + UINT8 Reserved1[4]; // 4 + /// + /// Used to gain control of the TPM by this Locality. + /// + UINT32 LocalityControl; // 8 + /// + /// Used to determine whether Locality has been granted or Seized. + /// + UINT32 LocalityStatus; // 0ch + UINT8 Reserved2[0x20]; // 10h + /// + /// Used to identify the Interface types supported by the TPM. + /// + UINT32 InterfaceId; // 30h + /// + /// Vendor ID + /// + UINT16 Vid; // 34h + /// + /// Device ID + /// + UINT16 Did; // 36h + /// + /// Optional Register used in low memory environments prior to CRB_DATA_BUFFER availability. + /// + UINT64 CrbControlExtension; // 38h + /// + /// Register used to initiate transactions for the CRB interface. + /// + UINT32 CrbControlRequest; // 40h + /// + /// Register used by the TPM to provide status of the CRB interface. + /// + UINT32 CrbControlStatus; // 44h + /// + /// Register used by software to cancel command processing. + /// + UINT32 CrbControlCancel; // 48h + /// + /// Register used to indicate presence of command or response data in the CRB buffer. + /// + UINT32 CrbControlStart; // 4Ch + /// + /// Register used to configure and respond to interrupts. + /// + UINT32 CrbInterruptEnable; // 50h + UINT32 CrbInterruptStatus; // 54h + /// + /// Size of the Command buffer. + /// + UINT32 CrbControlCommandSize; // 58h + /// + /// Command buffer start address + /// + UINT32 CrbControlCommandAddressLow; // 5Ch + UINT32 CrbControlCommandAddressHigh; // 60h + /// + /// Size of the Response buffer + /// + UINT32 CrbControlResponseSize; // 64h + /// + /// Address of the start of the Response buffer + /// + UINT64 CrbControlResponseAddrss; // 68h + UINT8 Reserved4[0x10]; // 70h + /// + /// Command/Response Data may be defined as large as 3968 (0xF80). + /// + UINT8 CrbDataBuffer[0xF80]; // 80h +} PTP_CRB_REGISTERS; + +// +// Define pointer types used to access CRB registers on PTP +// +typedef PTP_CRB_REGISTERS *PTP_CRB_REGISTERS_PTR; + +// +// Define bits of CRB Interface Identifier Register +// +typedef union { + struct { + UINT32 InterfaceType:4; + UINT32 InterfaceVersion:4; + UINT32 CapLocality:1; + UINT32 CapCRBIdleBypass:1; + UINT32 Reserved1:1; + UINT32 CapDataXferSizeSupport:2; + UINT32 CapFIFO:1; + UINT32 CapCRB:1; + UINT32 CapIFRes:2; + UINT32 InterfaceSelector:2; + UINT32 IntfSelLock:1; + UINT32 Reserved2:4; + UINT32 Rid:8; + } Bits; + UINT32 Uint32; +} PTP_CRB_INTERFACE_IDENTIFIER; + +/// +/// InterfaceType +/// +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO 0x0 +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB 0x1 +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS 0xF + +/// +/// InterfaceVersion +/// +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO 0x0 +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB 0x1 + +/// +/// InterfaceSelector +/// +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_SELECTOR_FIFO 0x0 +#define PTP_INTERFACE_IDENTIFIER_INTERFACE_SELECTOR_CRB 0x1 + +// +// Define bits of Locality State Register +// + +/// +/// This bit indicates whether all other bits of this register contain valid values, if it is a 1. +/// +#define PTP_CRB_LOCALITY_STATE_TPM_REG_VALID_STATUS BIT7 + +/// +/// 000 - Locality 0 +/// 001 - Locality 1 +/// 010 - Locality 2 +/// 011 - Locality 3 +/// 100 - Locality 4 +/// +#define PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_MASK (BIT2 | BIT3 | BIT4) +#define PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_0 (0) +#define PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_1 (BIT2) +#define PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_2 (BIT3) +#define PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_3 (BIT2 | BIT3) +#define PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_4 (BIT4) + +/// +/// A 0 indicates to the host that no locality is assigned. +/// A 1 indicates a locality has been assigned. +/// +#define PTP_CRB_LOCALITY_STATE_LOCALITY_ASSIGNED BIT1 + +/// +/// The TPM clears this bit to 0 upon receipt of _TPM_Hash_End +/// The TPM sets this bit to a 1 when the TPM_LOC_CTRL_x.resetEstablishment field is set to 1. +/// +#define PTP_CRB_LOCALITY_STATE_TPM_ESTABLISHED BIT0 + +// +// Define bits of Locality Control Register +// + +/// +/// Writes (1): Reset TPM_LOC_STATE_x.tpmEstablished bit if the write occurs from Locality 3 or 4. +/// +#define PTP_CRB_LOCALITY_CONTROL_RESET_ESTABLISHMENT_BIT BIT3 + +/// +/// Writes (1): The TPM gives control of the TPM to the locality setting this bit if it is the higher priority locality. +/// +#define PTP_CRB_LOCALITY_CONTROL_SEIZE BIT2 + +/// +/// Writes (1): The active Locality is done with the TPM. +/// +#define PTP_CRB_LOCALITY_CONTROL_RELINQUISH BIT1 + +/// +/// Writes (1): Interrupt the TPM and generate a locality arbitration algorithm. +/// +#define PTP_CRB_LOCALITY_CONTROL_REQUEST_ACCESS BIT0 + +// +// Define bits of Locality Status Register +// + +/// +/// 0: A higher locality has not initiated a Seize arbitration process. +/// 1: A higher locality has Seized the TPM from this locality. +/// +#define PTP_CRB_LOCALITY_STATUS_BEEN_SEIZED BIT1 + +/// +/// 0: Locality has not been granted to the TPM. +/// 1: Locality has been granted access to the TPM +/// +#define PTP_CRB_LOCALITY_STATUS_GRANTED BIT0 + +// +// Define bits of CRB Control Area Request Register +// + +/// +/// Used by Software to indicate transition the TPM to and from the Idle state +/// 1: Set by Software to indicate response has been read from the response buffer and TPM can transition to Idle +/// 0: Cleared to 0 by TPM to acknowledge the request when TPM enters Idle state. +/// TPM SHALL complete this transition within TIMEOUT_C. +/// +#define PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE BIT1 + +/// +/// Used by Software to request the TPM transition to the Ready State. +/// 1: Set to 1 by Software to indicate the TPM should be ready to receive a command. +/// 0: Cleared to 0 by TPM to acknowledge the request. +/// TPM SHALL complete this transition within TIMEOUT_C. +/// +#define PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY BIT0 + +// +// Define bits of CRB Control Area Status Register +// + +/// +/// Used by TPM to indicate it is in the Idle State +/// 1: Set by TPM when in the Idle State +/// 0: Cleared by TPM on receipt of TPM_CRB_CTRL_REQ_x.cmdReady when TPM transitions to the Ready State. +/// SHALL be cleared by TIMEOUT_C. +/// +#define PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE BIT1 + +/// +/// Used by the TPM to indicate current status. +/// 1: Set by TPM to indicate a FATAL Error +/// 0: Indicates TPM is operational +/// +#define PTP_CRB_CONTROL_AREA_STATUS_TPM_STATUS BIT0 + +// +// Define bits of CRB Control Cancel Register +// + +/// +/// Used by software to cancel command processing Reads return correct value +/// Writes (0000 0001h): Cancel a command +/// Writes (0000 0000h): Clears field when command has been cancelled +/// +#define PTP_CRB_CONTROL_CANCEL BIT0 + +// +// Define bits of CRB Control Start Register +// + +/// +/// When set by software, indicates a command is ready for processing. +/// Writes (0000 0001h): TPM transitions to Command Execution +/// Writes (0000 0000h): TPM clears this field and transitions to Command Completion +/// +#define PTP_CRB_CONTROL_START BIT0 + +// +// Restore original structure alignment +// +#pragma pack () + +// +// Default TimeOut value +// +#define PTP_TIMEOUT_A (750 * 1000) // 750ms +#define PTP_TIMEOUT_B (2000 * 1000) // 2s +#define PTP_TIMEOUT_C (200 * 1000) // 200ms +#define PTP_TIMEOUT_D (30 * 1000) // 30ms + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmTis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmTis.h new file mode 100644 index 0000000..19399a0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/TpmTis.h @@ -0,0 +1,187 @@ +/** @file + TPM Interface Specification definition. + It covers both TPM1.2 and TPM2.0. + +Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TPM_TIS_H_ +#define _TPM_TIS_H_ + +// +// Set structure alignment to 1-byte +// +#pragma pack (1) + +// +// Register set map as specified in TIS specification Chapter 10 +// +typedef struct { + /// + /// Used to gain ownership for this particular port. + /// + UINT8 Access; // 0 + UINT8 Reserved1[7]; // 1 + /// + /// Controls interrupts. + /// + UINT32 IntEnable; // 8 + /// + /// SIRQ vector to be used by the TPM. + /// + UINT8 IntVector; // 0ch + UINT8 Reserved2[3]; // 0dh + /// + /// What caused interrupt. + /// + UINT32 IntSts; // 10h + /// + /// Shows which interrupts are supported by that particular TPM. + /// + UINT32 IntfCapability; // 14h + /// + /// Status Register. Provides status of the TPM. + /// + UINT8 Status; // 18h + /// + /// Number of consecutive writes that can be done to the TPM. + /// + UINT16 BurstCount; // 19h + UINT8 Reserved3[9]; + /// + /// Read or write FIFO, depending on transaction. + /// + UINT32 DataFifo; // 24h + UINT8 Reserved4[0xed8]; // 28h + /// + /// Vendor ID + /// + UINT16 Vid; // 0f00h + /// + /// Device ID + /// + UINT16 Did; // 0f02h + /// + /// Revision ID + /// + UINT8 Rid; // 0f04h + UINT8 Reserved[0x7b]; // 0f05h + /// + /// Alias to I/O legacy space. + /// + UINT32 LegacyAddress1; // 0f80h + /// + /// Additional 8 bits for I/O legacy space extension. + /// + UINT32 LegacyAddress1Ex; // 0f84h + /// + /// Alias to second I/O legacy space. + /// + UINT32 LegacyAddress2; // 0f88h + /// + /// Additional 8 bits for second I/O legacy space extension. + /// + UINT32 LegacyAddress2Ex; // 0f8ch + /// + /// Vendor-defined configuration registers. + /// + UINT8 VendorDefined[0x70];// 0f90h +} TIS_PC_REGISTERS; + +// +// Restore original structure alignment +// +#pragma pack () + +// +// Define pointer types used to access TIS registers on PC +// +typedef TIS_PC_REGISTERS *TIS_PC_REGISTERS_PTR; + +// +// Define bits of ACCESS and STATUS registers +// + +/// +/// This bit is a 1 to indicate that the other bits in this register are valid. +/// +#define TIS_PC_VALID BIT7 +/// +/// Indicate that this locality is active. +/// +#define TIS_PC_ACC_ACTIVE BIT5 +/// +/// Set to 1 to indicate that this locality had the TPM taken away while +/// this locality had the TIS_PC_ACC_ACTIVE bit set. +/// +#define TIS_PC_ACC_SEIZED BIT4 +/// +/// Set to 1 to indicate that TPM MUST reset the +/// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the +/// locality that is writing this bit. +/// +#define TIS_PC_ACC_SEIZE BIT3 +/// +/// When this bit is 1, another locality is requesting usage of the TPM. +/// +#define TIS_PC_ACC_PENDIND BIT2 +/// +/// Set to 1 to indicate that this locality is requesting to use TPM. +/// +#define TIS_PC_ACC_RQUUSE BIT1 +/// +/// A value of 1 indicates that a T/OS has not been established on the platform +/// +#define TIS_PC_ACC_ESTABLISH BIT0 + +/// +/// Write a 1 to this bit to notify TPM to cancel currently executing command +/// +#define TIS_PC_STS_CANCEL BIT24 +/// +/// This field indicates that STS_DATA and STS_EXPECT are valid +/// +#define TIS_PC_STS_VALID BIT7 +/// +/// When this bit is 1, TPM is in the Ready state, +/// indicating it is ready to receive a new command. +/// +#define TIS_PC_STS_READY BIT6 +/// +/// Write a 1 to this bit to cause the TPM to execute that command. +/// +#define TIS_PC_STS_GO BIT5 +/// +/// This bit indicates that the TPM has data available as a response. +/// +#define TIS_PC_STS_DATA BIT4 +/// +/// The TPM sets this bit to a value of 1 when it expects another byte of data for a command. +/// +#define TIS_PC_STS_EXPECT BIT3 +/// +/// Indicates that the TPM has completed all self-test actions following a TPM_ContinueSelfTest command. +/// +#define TIS_PC_STS_SELFTEST_DONE BIT2 +/// +/// Writes a 1 to this bit to force the TPM to re-send the response. +/// +#define TIS_PC_STS_RETRY BIT1 + +// +// Default TimeOut value +// +#define TIS_TIMEOUT_A (750 * 1000) // 750ms +#define TIS_TIMEOUT_B (2000 * 1000) // 2s +#define TIS_TIMEOUT_C (750 * 1000) // 750ms +#define TIS_TIMEOUT_D (750 * 1000) // 750ms + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Udf.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Udf.h new file mode 100644 index 0000000..c277a0f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Udf.h @@ -0,0 +1,147 @@ +/** @file + OSTA Universal Disk Format (UDF) definitions. + + Copyright (C) 2014-2017 Paulo Alcantara + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __UDF_H__ +#define __UDF_H__ + +#define UDF_BEA_IDENTIFIER "BEA01" +#define UDF_NSR2_IDENTIFIER "NSR02" +#define UDF_NSR3_IDENTIFIER "NSR03" +#define UDF_TEA_IDENTIFIER "TEA01" + +#define UDF_LOGICAL_SECTOR_SHIFT 11 +#define UDF_LOGICAL_SECTOR_SIZE ((UINT64)(1ULL << UDF_LOGICAL_SECTOR_SHIFT)) +#define UDF_VRS_START_OFFSET ((UINT64)(16ULL << UDF_LOGICAL_SECTOR_SHIFT)) + +typedef enum { + UdfPrimaryVolumeDescriptor = 1, + UdfAnchorVolumeDescriptorPointer = 2, + UdfVolumeDescriptorPointer = 3, + UdfImplemenationUseVolumeDescriptor = 4, + UdfPartitionDescriptor = 5, + UdfLogicalVolumeDescriptor = 6, + UdfUnallocatedSpaceDescriptor = 7, + UdfTerminatingDescriptor = 8, + UdfLogicalVolumeIntegrityDescriptor = 9, + UdfFileSetDescriptor = 256, + UdfFileIdentifierDescriptor = 257, + UdfAllocationExtentDescriptor = 258, + UdfFileEntry = 261, + UdfExtendedFileEntry = 266, +} UDF_VOLUME_DESCRIPTOR_ID; + +#pragma pack(1) + +typedef struct { + UINT16 TagIdentifier; + UINT16 DescriptorVersion; + UINT8 TagChecksum; + UINT8 Reserved; + UINT16 TagSerialNumber; + UINT16 DescriptorCRC; + UINT16 DescriptorCRCLength; + UINT32 TagLocation; +} UDF_DESCRIPTOR_TAG; + +typedef struct { + UINT32 ExtentLength; + UINT32 ExtentLocation; +} UDF_EXTENT_AD; + +typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + union { + // + // Domain Entity Identifier + // + struct { + UINT16 UdfRevision; + UINT8 DomainFlags; + UINT8 Reserved[5]; + } Domain; + // + // UDF Entity Identifier + // + struct { + UINT16 UdfRevision; + UINT8 OSClass; + UINT8 OSIdentifier; + UINT8 Reserved[4]; + } Entity; + // + // Implementation Entity Identifier + // + struct { + UINT8 OSClass; + UINT8 OSIdentifier; + UINT8 ImplementationUseArea[6]; + } ImplementationEntity; + // + // Application Entity Identifier + // + struct { + UINT8 ApplicationUseArea[8]; + } ApplicationEntity; + // + // Raw Identifier Suffix + // + struct { + UINT8 Data[8]; + } Raw; + } Suffix; +} UDF_ENTITY_ID; + +typedef struct { + UINT32 LogicalBlockNumber; + UINT16 PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8 ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UDF_EXTENT_AD MainVolumeDescriptorSequenceExtent; + UDF_EXTENT_AD ReserveVolumeDescriptorSequenceExtent; + UINT8 Reserved[480]; +} UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h new file mode 100644 index 0000000..a00aa2d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h @@ -0,0 +1,342 @@ +/** @file + TCG EFI Platform Definition in TCG_EFI_Platform_1_20_Final + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_TCG_PLATFORM_H__ +#define __UEFI_TCG_PLATFORM_H__ + +#include +#include +#include + +// +// Standard event types +// +#define EV_PREBOOT_CERT ((TCG_EVENTTYPE) 0x00000000) +#define EV_POST_CODE ((TCG_EVENTTYPE) 0x00000001) +#define EV_NO_ACTION ((TCG_EVENTTYPE) 0x00000003) +#define EV_SEPARATOR ((TCG_EVENTTYPE) 0x00000004) +#define EV_ACTION ((TCG_EVENTTYPE) 0x00000005) +#define EV_S_CRTM_CONTENTS ((TCG_EVENTTYPE) 0x00000007) +#define EV_S_CRTM_VERSION ((TCG_EVENTTYPE) 0x00000008) +#define EV_CPU_MICROCODE ((TCG_EVENTTYPE) 0x00000009) +#define EV_PLATFORM_CONFIG_FLAGS ((TCG_EVENTTYPE) 0x0000000A) +#define EV_TABLE_OF_DEVICES ((TCG_EVENTTYPE) 0x0000000B) +#define EV_COMPACT_HASH ((TCG_EVENTTYPE) 0x0000000C) +#define EV_NONHOST_CODE ((TCG_EVENTTYPE) 0x0000000F) +#define EV_NONHOST_CONFIG ((TCG_EVENTTYPE) 0x00000010) +#define EV_NONHOST_INFO ((TCG_EVENTTYPE) 0x00000011) +#define EV_OMIT_BOOT_DEVICE_EVENTS ((TCG_EVENTTYPE) 0x00000012) + +// +// EFI specific event types +// +#define EV_EFI_EVENT_BASE ((TCG_EVENTTYPE) 0x80000000) +#define EV_EFI_VARIABLE_DRIVER_CONFIG (EV_EFI_EVENT_BASE + 1) +#define EV_EFI_VARIABLE_BOOT (EV_EFI_EVENT_BASE + 2) +#define EV_EFI_BOOT_SERVICES_APPLICATION (EV_EFI_EVENT_BASE + 3) +#define EV_EFI_BOOT_SERVICES_DRIVER (EV_EFI_EVENT_BASE + 4) +#define EV_EFI_RUNTIME_SERVICES_DRIVER (EV_EFI_EVENT_BASE + 5) +#define EV_EFI_GPT_EVENT (EV_EFI_EVENT_BASE + 6) +#define EV_EFI_ACTION (EV_EFI_EVENT_BASE + 7) +#define EV_EFI_PLATFORM_FIRMWARE_BLOB (EV_EFI_EVENT_BASE + 8) +#define EV_EFI_HANDOFF_TABLES (EV_EFI_EVENT_BASE + 9) +#define EV_EFI_HCRTM_EVENT (EV_EFI_EVENT_BASE + 0x10) +#define EV_EFI_VARIABLE_AUTHORITY (EV_EFI_EVENT_BASE + 0xE0) + +#define EFI_CALLING_EFI_APPLICATION \ + "Calling EFI Application from Boot Option" +#define EFI_RETURNING_FROM_EFI_APPLICATION \ + "Returning from EFI Application from Boot Option" +#define EFI_EXIT_BOOT_SERVICES_INVOCATION \ + "Exit Boot Services Invocation" +#define EFI_EXIT_BOOT_SERVICES_FAILED \ + "Exit Boot Services Returned with Failure" +#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED \ + "Exit Boot Services Returned with Success" + + +#define EV_POSTCODE_INFO_POST_CODE "POST CODE" +#define POST_CODE_STR_LEN (sizeof(EV_POSTCODE_INFO_POST_CODE) - 1) + +#define EV_POSTCODE_INFO_SMM_CODE "SMM CODE" +#define SMM_CODE_STR_LEN (sizeof(EV_POSTCODE_INFO_SMM_CODE) - 1) + +#define EV_POSTCODE_INFO_ACPI_DATA "ACPI DATA" +#define ACPI_DATA_LEN (sizeof(EV_POSTCODE_INFO_ACPI_DATA) - 1) + +#define EV_POSTCODE_INFO_BIS_CODE "BIS CODE" +#define BIS_CODE_LEN (sizeof(EV_POSTCODE_INFO_BIS_CODE) - 1) + +#define EV_POSTCODE_INFO_UEFI_PI "UEFI PI" +#define UEFI_PI_LEN (sizeof(EV_POSTCODE_INFO_UEFI_PI) - 1) + +#define EV_POSTCODE_INFO_OPROM "Embedded Option ROM" +#define OPROM_LEN (sizeof(EV_POSTCODE_INFO_OPROM) - 1) + +#define FIRMWARE_DEBUGGER_EVENT_STRING "UEFI Debug Mode" +#define FIRMWARE_DEBUGGER_EVENT_STRING_LEN (sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1) + +// +// Set structure alignment to 1-byte +// +#pragma pack (1) + +typedef UINT32 TCG_EVENTTYPE; +typedef TPM_PCRINDEX TCG_PCRINDEX; +typedef TPM_DIGEST TCG_DIGEST; +/// +/// Event Log Entry Structure Definition +/// +typedef struct tdTCG_PCR_EVENT { + TCG_PCRINDEX PCRIndex; ///< PCRIndex event extended to + TCG_EVENTTYPE EventType; ///< TCG EFI event type + TCG_DIGEST Digest; ///< Value extended into PCRIndex + UINT32 EventSize; ///< Size of the event data + UINT8 Event[1]; ///< The event data +} TCG_PCR_EVENT; + +#define TSS_EVENT_DATA_MAX_SIZE 256 + +/// +/// TCG_PCR_EVENT_HDR +/// +typedef struct tdTCG_PCR_EVENT_HDR { + TCG_PCRINDEX PCRIndex; + TCG_EVENTTYPE EventType; + TCG_DIGEST Digest; + UINT32 EventSize; +} TCG_PCR_EVENT_HDR; + +/// +/// EFI_PLATFORM_FIRMWARE_BLOB +/// +/// BlobLength should be of type UINTN but we use UINT64 here +/// because PEI is 32-bit while DXE is 64-bit on x64 platforms +/// +typedef struct tdEFI_PLATFORM_FIRMWARE_BLOB { + EFI_PHYSICAL_ADDRESS BlobBase; + UINT64 BlobLength; +} EFI_PLATFORM_FIRMWARE_BLOB; + +/// +/// EFI_IMAGE_LOAD_EVENT +/// +/// This structure is used in EV_EFI_BOOT_SERVICES_APPLICATION, +/// EV_EFI_BOOT_SERVICES_DRIVER and EV_EFI_RUNTIME_SERVICES_DRIVER +/// +typedef struct tdEFI_IMAGE_LOAD_EVENT { + EFI_PHYSICAL_ADDRESS ImageLocationInMemory; + UINTN ImageLengthInMemory; + UINTN ImageLinkTimeAddress; + UINTN LengthOfDevicePath; + EFI_DEVICE_PATH_PROTOCOL DevicePath[1]; +} EFI_IMAGE_LOAD_EVENT; + +/// +/// EFI_HANDOFF_TABLE_POINTERS +/// +/// This structure is used in EV_EFI_HANDOFF_TABLES event to facilitate +/// the measurement of given configuration tables. +/// +typedef struct tdEFI_HANDOFF_TABLE_POINTERS { + UINTN NumberOfTables; + EFI_CONFIGURATION_TABLE TableEntry[1]; +} EFI_HANDOFF_TABLE_POINTERS; + +/// +/// EFI_VARIABLE_DATA +/// +/// This structure serves as the header for measuring variables. The name of the +/// variable (in Unicode format) should immediately follow, then the variable +/// data. +/// This is defined in TCG EFI Platform Spec for TPM1.1 or 1.2 V1.22 +/// +typedef struct tdEFI_VARIABLE_DATA { + EFI_GUID VariableName; + UINTN UnicodeNameLength; + UINTN VariableDataLength; + CHAR16 UnicodeName[1]; + INT8 VariableData[1]; ///< Driver or platform-specific data +} EFI_VARIABLE_DATA; + +/// +/// UEFI_VARIABLE_DATA +/// +/// This structure serves as the header for measuring variables. The name of the +/// variable (in Unicode format) should immediately follow, then the variable +/// data. +/// This is defined in TCG PC Client Firmware Profile Spec 00.21 +/// +typedef struct tdUEFI_VARIABLE_DATA { + EFI_GUID VariableName; + UINT64 UnicodeNameLength; + UINT64 VariableDataLength; + CHAR16 UnicodeName[1]; + INT8 VariableData[1]; ///< Driver or platform-specific data +} UEFI_VARIABLE_DATA; + +// +// For TrEE1.0 compatibility +// +typedef struct { + EFI_GUID VariableName; + UINT64 UnicodeNameLength; // The TCG Definition used UINTN + UINT64 VariableDataLength; // The TCG Definition used UINTN + CHAR16 UnicodeName[1]; + INT8 VariableData[1]; +} EFI_VARIABLE_DATA_TREE; + +typedef struct tdEFI_GPT_DATA { + EFI_PARTITION_TABLE_HEADER EfiPartitionHeader; + UINTN NumberOfPartitions; + EFI_PARTITION_ENTRY Partitions[1]; +} EFI_GPT_DATA; + +// +// Crypto Agile Log Entry Format +// +typedef struct tdTCG_PCR_EVENT2 { + TCG_PCRINDEX PCRIndex; + TCG_EVENTTYPE EventType; + TPML_DIGEST_VALUES Digest; + UINT32 EventSize; + UINT8 Event[1]; +} TCG_PCR_EVENT2; + +// +// TCG PCR Event2 Header +// Follow TCG EFI Protocol Spec 5.2 Crypto Agile Log Entry Format +// +typedef struct tdTCG_PCR_EVENT2_HDR{ + TCG_PCRINDEX PCRIndex; + TCG_EVENTTYPE EventType; + TPML_DIGEST_VALUES Digests; + UINT32 EventSize; +} TCG_PCR_EVENT2_HDR; + +// +// Log Header Entry Data +// +typedef struct { + // + // TCG defined hashing algorithm ID. + // + UINT16 algorithmId; + // + // The size of the digest for the respective hashing algorithm. + // + UINT16 digestSize; +} TCG_EfiSpecIdEventAlgorithmSize; + +#define TCG_EfiSpecIDEventStruct_SIGNATURE_02 "Spec ID Event02" +#define TCG_EfiSpecIDEventStruct_SIGNATURE_03 "Spec ID Event03" + +#define TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM12 1 +#define TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM12 2 +#define TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM12 2 + +#define TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2 0 + +typedef struct { + UINT8 signature[16]; + // + // The value for the Platform Class. + // The enumeration is defined in the TCG ACPI Specification Client Common Header. + // + UINT32 platformClass; + // + // The TCG EFI Platform Specification minor version number this BIOS supports. + // Any BIOS supporting version (1.22) MUST set this value to 02h. + // Any BIOS supporting version (2.0) SHALL set this value to 0x00. + // + UINT8 specVersionMinor; + // + // The TCG EFI Platform Specification major version number this BIOS supports. + // Any BIOS supporting version (1.22) MUST set this value to 01h. + // Any BIOS supporting version (2.0) SHALL set this value to 0x02. + // + UINT8 specVersionMajor; + // + // The TCG EFI Platform Specification errata for this specification this BIOS supports. + // Any BIOS supporting version and errata (1.22) MUST set this value to 02h. + // Any BIOS supporting version and errata (2.0) SHALL set this value to 0x00. + // + UINT8 specErrata; + // + // Specifies the size of the UINTN fields used in various data structures used in this specification. + // 0x01 indicates UINT32 and 0x02 indicates UINT64. + // + UINT8 uintnSize; + // + // This field is added in "Spec ID Event03". + // The number of hashing algorithms used in this event log (except the first event). + // All events in this event log use all hashing algorithms defined here. + // +//UINT32 numberOfAlgorithms; + // + // This field is added in "Spec ID Event03". + // An array of size numberOfAlgorithms of value pairs. + // +//TCG_EfiSpecIdEventAlgorithmSize digestSize[numberOfAlgorithms]; + // + // Size in bytes of the VendorInfo field. + // Maximum value SHALL be FFh bytes. + // +//UINT8 vendorInfoSize; + // + // Provided for use by the BIOS implementer. + // The value might be used, for example, to provide more detailed information about the specific BIOS such as BIOS revision numbers, etc. + // The values within this field are not standardized and are implementer-specific. + // Platform-specific or -unique information SHALL NOT be provided in this field. + // +//UINT8 vendorInfo[vendorInfoSize]; +} TCG_EfiSpecIDEventStruct; + + + +#define TCG_EfiStartupLocalityEvent_SIGNATURE "StartupLocality" + + +// +// PC Client PTP spec Table 8 Relationship between Locality and Locality Attribute +// +#define LOCALITY_0_INDICATOR 0x01 +#define LOCALITY_1_INDICATOR 0x02 +#define LOCALITY_2_INDICATOR 0x03 +#define LOCALITY_3_INDICATOR 0x04 +#define LOCALITY_4_INDICATOR 0x05 + + +// +// Startup Locality Event +// +typedef struct tdTCG_EfiStartupLocalityEvent{ + UINT8 Signature[16]; + // + // The Locality Indicator which sent the TPM2_Startup command + // + UINT8 StartupLocality; +} TCG_EfiStartupLocalityEvent; + + +// +// Restore original structure alignment +// +#pragma pack () + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Usb.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Usb.h new file mode 100644 index 0000000..38c4d85 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/Usb.h @@ -0,0 +1,386 @@ +/** @file + Support for USB 2.0 standard. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __USB_H__ +#define __USB_H__ + +// +// Subset of Class and Subclass definitions from USB Specs +// + +// +// Usb mass storage class code +// +#define USB_MASS_STORE_CLASS 0x08 + +// +// Usb mass storage subclass code, specify the command set used. +// +#define USB_MASS_STORE_RBC 0x01 ///< Reduced Block Commands +#define USB_MASS_STORE_8020I 0x02 ///< SFF-8020i, typically a CD/DVD device +#define USB_MASS_STORE_QIC 0x03 ///< Typically a tape device +#define USB_MASS_STORE_UFI 0x04 ///< Typically a floppy disk driver device +#define USB_MASS_STORE_8070I 0x05 ///< SFF-8070i, typically a floppy disk driver device. +#define USB_MASS_STORE_SCSI 0x06 ///< SCSI transparent command set + +// +// Usb mass storage protocol code, specify the transport protocol +// +#define USB_MASS_STORE_CBI0 0x00 ///< CBI protocol with command completion interrupt +#define USB_MASS_STORE_CBI1 0x01 ///< CBI protocol without command completion interrupt +#define USB_MASS_STORE_BOT 0x50 ///< Bulk-Only Transport + +// +// Standard device request and request type +// USB 2.0 spec, Section 9.4 +// +#define USB_DEV_GET_STATUS 0x00 +#define USB_DEV_GET_STATUS_REQ_TYPE_D 0x80 // Receiver : Device +#define USB_DEV_GET_STATUS_REQ_TYPE_I 0x81 // Receiver : Interface +#define USB_DEV_GET_STATUS_REQ_TYPE_E 0x82 // Receiver : Endpoint + +#define USB_DEV_CLEAR_FEATURE 0x01 +#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device +#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface +#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint + +#define USB_DEV_SET_FEATURE 0x03 +#define USB_DEV_SET_FEATURE_REQ_TYPE_D 0x00 // Receiver : Device +#define USB_DEV_SET_FEATURE_REQ_TYPE_I 0x01 // Receiver : Interface +#define USB_DEV_SET_FEATURE_REQ_TYPE_E 0x02 // Receiver : Endpoint + +#define USB_DEV_SET_ADDRESS 0x05 +#define USB_DEV_SET_ADDRESS_REQ_TYPE 0x00 + +#define USB_DEV_GET_DESCRIPTOR 0x06 +#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE 0x80 + +#define USB_DEV_SET_DESCRIPTOR 0x07 +#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE 0x00 + +#define USB_DEV_GET_CONFIGURATION 0x08 +#define USB_DEV_GET_CONFIGURATION_REQ_TYPE 0x80 + +#define USB_DEV_SET_CONFIGURATION 0x09 +#define USB_DEV_SET_CONFIGURATION_REQ_TYPE 0x00 + +#define USB_DEV_GET_INTERFACE 0x0A +#define USB_DEV_GET_INTERFACE_REQ_TYPE 0x81 + +#define USB_DEV_SET_INTERFACE 0x0B +#define USB_DEV_SET_INTERFACE_REQ_TYPE 0x01 + +#define USB_DEV_SYNCH_FRAME 0x0C +#define USB_DEV_SYNCH_FRAME_REQ_TYPE 0x82 + + +// +// USB standard descriptors and reqeust +// +#pragma pack(1) + +/// +/// Format of Setup Data for USB Device Requests +/// USB 2.0 spec, Section 9.3 +/// +typedef struct { + UINT8 RequestType; + UINT8 Request; + UINT16 Value; + UINT16 Index; + UINT16 Length; +} USB_DEVICE_REQUEST; + +/// +/// Standard Device Descriptor +/// USB 2.0 spec, Section 9.6.1 +/// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT16 BcdUSB; + UINT8 DeviceClass; + UINT8 DeviceSubClass; + UINT8 DeviceProtocol; + UINT8 MaxPacketSize0; + UINT16 IdVendor; + UINT16 IdProduct; + UINT16 BcdDevice; + UINT8 StrManufacturer; + UINT8 StrProduct; + UINT8 StrSerialNumber; + UINT8 NumConfigurations; +} USB_DEVICE_DESCRIPTOR; + +/// +/// Standard Configuration Descriptor +/// USB 2.0 spec, Section 9.6.3 +/// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT16 TotalLength; + UINT8 NumInterfaces; + UINT8 ConfigurationValue; + UINT8 Configuration; + UINT8 Attributes; + UINT8 MaxPower; +} USB_CONFIG_DESCRIPTOR; + +/// +/// Standard Interface Descriptor +/// USB 2.0 spec, Section 9.6.5 +/// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT8 InterfaceNumber; + UINT8 AlternateSetting; + UINT8 NumEndpoints; + UINT8 InterfaceClass; + UINT8 InterfaceSubClass; + UINT8 InterfaceProtocol; + UINT8 Interface; +} USB_INTERFACE_DESCRIPTOR; + +/// +/// Standard Endpoint Descriptor +/// USB 2.0 spec, Section 9.6.6 +/// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT8 EndpointAddress; + UINT8 Attributes; + UINT16 MaxPacketSize; + UINT8 Interval; +} USB_ENDPOINT_DESCRIPTOR; + +/// +/// UNICODE String Descriptor +/// USB 2.0 spec, Section 9.6.7 +/// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[1]; +} EFI_USB_STRING_DESCRIPTOR; + +#pragma pack() + + +typedef enum { + // + // USB request type + // + USB_REQ_TYPE_STANDARD = (0x00 << 5), + USB_REQ_TYPE_CLASS = (0x01 << 5), + USB_REQ_TYPE_VENDOR = (0x02 << 5), + + // + // Standard control transfer request type, or the value + // to fill in EFI_USB_DEVICE_REQUEST.Request + // + USB_REQ_GET_STATUS = 0x00, + USB_REQ_CLEAR_FEATURE = 0x01, + USB_REQ_SET_FEATURE = 0x03, + USB_REQ_SET_ADDRESS = 0x05, + USB_REQ_GET_DESCRIPTOR = 0x06, + USB_REQ_SET_DESCRIPTOR = 0x07, + USB_REQ_GET_CONFIG = 0x08, + USB_REQ_SET_CONFIG = 0x09, + USB_REQ_GET_INTERFACE = 0x0A, + USB_REQ_SET_INTERFACE = 0x0B, + USB_REQ_SYNCH_FRAME = 0x0C, + + // + // Usb control transfer target + // + USB_TARGET_DEVICE = 0, + USB_TARGET_INTERFACE = 0x01, + USB_TARGET_ENDPOINT = 0x02, + USB_TARGET_OTHER = 0x03, + + // + // USB Descriptor types + // + USB_DESC_TYPE_DEVICE = 0x01, + USB_DESC_TYPE_CONFIG = 0x02, + USB_DESC_TYPE_STRING = 0x03, + USB_DESC_TYPE_INTERFACE = 0x04, + USB_DESC_TYPE_ENDPOINT = 0x05, + USB_DESC_TYPE_HID = 0x21, + USB_DESC_TYPE_REPORT = 0x22, + + // + // Features to be cleared by CLEAR_FEATURE requests + // + USB_FEATURE_ENDPOINT_HALT = 0, + + // + // USB endpoint types: 00: control, 01: isochronous, 10: bulk, 11: interrupt + // + USB_ENDPOINT_CONTROL = 0x00, + USB_ENDPOINT_ISO = 0x01, + USB_ENDPOINT_BULK = 0x02, + USB_ENDPOINT_INTERRUPT = 0x03, + + USB_ENDPOINT_TYPE_MASK = 0x03, + USB_ENDPOINT_DIR_IN = 0x80, + + // + //Use 200 ms to increase the error handling response time + // + EFI_USB_INTERRUPT_DELAY = 2000000 +} USB_TYPES_DEFINITION; + + +// +// HID constants definition, see Device Class Definition +// for Human Interface Devices (HID) rev1.11 +// + +// +// HID standard GET_DESCRIPTOR request. +// +#define USB_HID_GET_DESCRIPTOR_REQ_TYPE 0x81 + +// +// HID specific requests. +// +#define USB_HID_CLASS_GET_REQ_TYPE 0xa1 +#define USB_HID_CLASS_SET_REQ_TYPE 0x21 + +// +// HID report item format +// +#define HID_ITEM_FORMAT_SHORT 0 +#define HID_ITEM_FORMAT_LONG 1 + +// +// Special tag indicating long items +// +#define HID_ITEM_TAG_LONG 15 + +// +// HID report descriptor item type (prefix bit 2,3) +// +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +// +// HID report descriptor main item tags +// +#define HID_MAIN_ITEM_TAG_INPUT 8 +#define HID_MAIN_ITEM_TAG_OUTPUT 9 +#define HID_MAIN_ITEM_TAG_FEATURE 11 +#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 +#define HID_MAIN_ITEM_TAG_END_COLLECTION 12 + +// +// HID report descriptor main item contents +// +#define HID_MAIN_ITEM_CONSTANT 0x001 +#define HID_MAIN_ITEM_VARIABLE 0x002 +#define HID_MAIN_ITEM_RELATIVE 0x004 +#define HID_MAIN_ITEM_WRAP 0x008 +#define HID_MAIN_ITEM_NONLINEAR 0x010 +#define HID_MAIN_ITEM_NO_PREFERRED 0x020 +#define HID_MAIN_ITEM_NULL_STATE 0x040 +#define HID_MAIN_ITEM_VOLATILE 0x080 +#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 + +// +// HID report descriptor collection item types +// +#define HID_COLLECTION_PHYSICAL 0 +#define HID_COLLECTION_APPLICATION 1 +#define HID_COLLECTION_LOGICAL 2 + +// +// HID report descriptor global item tags +// +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 +#define HID_GLOBAL_ITEM_TAG_UNIT 6 +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 +#define HID_GLOBAL_ITEM_TAG_PUSH 10 +#define HID_GLOBAL_ITEM_TAG_POP 11 + +// +// HID report descriptor local item tags +// +#define HID_LOCAL_ITEM_TAG_USAGE 0 +#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 +#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 +#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 +#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 +#define HID_LOCAL_ITEM_TAG_DELIMITER 10 + +// +// HID report types +// +#define HID_INPUT_REPORT 1 +#define HID_OUTPUT_REPORT 2 +#define HID_FEATURE_REPORT 3 + +// +// HID class protocol request +// +#define EFI_USB_GET_REPORT_REQUEST 0x01 +#define EFI_USB_GET_IDLE_REQUEST 0x02 +#define EFI_USB_GET_PROTOCOL_REQUEST 0x03 +#define EFI_USB_SET_REPORT_REQUEST 0x09 +#define EFI_USB_SET_IDLE_REQUEST 0x0a +#define EFI_USB_SET_PROTOCOL_REQUEST 0x0b + +#pragma pack(1) +/// +/// Descriptor header for Report/Physical Descriptors +/// HID 1.1, section 6.2.1 +/// +typedef struct hid_class_descriptor { + UINT8 DescriptorType; + UINT16 DescriptorLength; +} EFI_USB_HID_CLASS_DESCRIPTOR; + +/// +/// The HID descriptor identifies the length and type +/// of subordinate descriptors for a device. +/// HID 1.1, section 6.2.1 +/// +typedef struct hid_descriptor { + UINT8 Length; + UINT8 DescriptorType; + UINT16 BcdHID; + UINT8 CountryCode; + UINT8 NumDescriptors; + EFI_USB_HID_CLASS_DESCRIPTOR HidClassDesc[1]; +} EFI_USB_HID_DESCRIPTOR; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogActionTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogActionTable.h new file mode 100644 index 0000000..9cf699a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogActionTable.h @@ -0,0 +1,96 @@ +/** @file + ACPI Watchdog Action Table (WADT) as defined at + Microsoft Hardware Watchdog Timers Design Specification. + + Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + + +#ifndef _WATCHDOG_ACTION_TABLE_H_ +#define _WATCHDOG_ACTION_TABLE_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) +/// +/// Watchdog Action Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WatchdogHeaderLength; + UINT16 PCISegment; + UINT8 PCIBusNumber; + UINT8 PCIDeviceNumber; + UINT8 PCIFunctionNumber; + UINT8 Reserved_45[3]; + UINT32 TimerPeriod; + UINT32 MaxCount; + UINT32 MinCount; + UINT8 WatchdogFlags; + UINT8 Reserved_61[3]; + UINT32 NumberWatchdogInstructionEntries; +} EFI_ACPI_WATCHDOG_ACTION_1_0_TABLE; + +/// +/// Watchdog Instruction Entries +/// +typedef struct { + UINT8 WatchdogAction; + UINT8 InstructionFlags; + UINT8 Reserved_2[2]; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE RegisterRegion; + UINT32 Value; + UINT32 Mask; +} EFI_ACPI_WATCHDOG_ACTION_1_0_WATCHDOG_ACTION_INSTRUCTION_ENTRY; + +#pragma pack() + +/// +/// WDAT Revision (defined in spec) +/// +#define EFI_ACPI_WATCHDOG_ACTION_1_0_TABLE_REVISION 0x01 + +// +// WDAT 1.0 Flags +// +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ENABLED 0x1 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_STOPPED_IN_SLEEP_STATE 0x80 + +// +// WDAT 1.0 Watchdog Actions +// +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_RESET 0x1 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_CURRENT_COUNTDOWN_PERIOD 0x4 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_COUNTDOWN_PERIOD 0x5 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_SET_COUNTDOWN_PERIOD 0x6 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_RUNNING_STATE 0x8 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_SET_RUNNING_STATE 0x9 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_STOPPED_STATE 0xA +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_SET_STOPPED_STATE 0xB +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_REBOOT 0x10 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_SET_REBOOT 0x11 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_SHUTDOWN 0x12 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_SET_SHUTDOWN 0x13 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_QUERY_WATCHDOG_STATUS 0x20 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_ACTION_SET_WATCHDOG_STATUS 0x21 + +// +// WDAT 1.0 Watchdog Action Entry Instruction Flags +// +#define EFI_ACPI_WDAT_1_0_WATCHDOG_INSTRUCTION_READ_VALUE 0x0 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_INSTRUCTION_READ_COUNTDOWN 0x1 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_INSTRUCTION_WRITE_VALUE 0x2 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_INSTRUCTION_WRITE_COUNTDOWN 0x3 +#define EFI_ACPI_WDAT_1_0_WATCHDOG_INSTRUCTION_PRESERVE_REGISTER 0x80 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogResourceTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogResourceTable.h new file mode 100644 index 0000000..9caad7f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WatchdogResourceTable.h @@ -0,0 +1,56 @@ +/** @file + ACPI Watchdog Resource Table (WDRT) as defined at + Microsoft Windows Hardware Developer Central. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _WATCHDOG_RESOURCE_TABLE_H_ +#define _WATCHDOG_RESOURCE_TABLE_H_ + +#include + +// +// Ensure proper structure formats +// +#pragma pack(1) + +/// +/// Watchdog Resource Table definition. +/// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE ControlRegisterAddress; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE CountRegisterAddress; + UINT16 PCIDeviceID; + UINT16 PCIVendorID; + UINT8 PCIBusNumber; + UINT8 PCIDeviceNumber; + UINT8 PCIFunctionNumber; + UINT8 PCISegment; + UINT16 MaxCount; + UINT8 Units; +} EFI_ACPI_WATCHDOG_RESOURCE_1_0_TABLE; + +#pragma pack() + +// +// WDRT Revision (defined in spec) +// +#define EFI_ACPI_WATCHDOG_RESOURCE_1_0_TABLE_REVISION 0x01 + +// +// WDRT 1.0 Count Unit +// +#define EFI_ACPI_WDRT_1_0_COUNT_UNIT_1_SEC_PER_COUNT 1 +#define EFI_ACPI_WDRT_1_0_COUNT_UNIT_100_MILLISEC_PER_COUNT 2 +#define EFI_ACPI_WDRT_1_0_COUNT_UNIT_10_MILLISEC_PER_COUNT 3 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsSmmSecurityMitigationTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsSmmSecurityMitigationTable.h new file mode 100644 index 0000000..ec5c359 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsSmmSecurityMitigationTable.h @@ -0,0 +1,39 @@ +/** @file + Defines Windows SMM Security Mitigation Table + @ https://msdn.microsoft.com/windows/hardware/drivers/bringup/acpi-system-description-tables#wsmt + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _WINDOWS_SMM_SECURITY_MITIGATION_TABLE_H_ +#define _WINDOWS_SMM_SECURITY_MITIGATION_TABLE_H_ + +#include + +#define EFI_ACPI_WINDOWS_SMM_SECURITY_MITIGATION_TABLE_SIGNATURE SIGNATURE_32('W', 'S', 'M', 'T') + +#pragma pack(1) + +#define EFI_WSMT_TABLE_REVISION 1 + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 ProtectionFlags; +} EFI_ACPI_WSMT_TABLE; + +#define EFI_WSMT_PROTECTION_FLAGS_FIXED_COMM_BUFFERS 0x1 +#define EFI_WSMT_PROTECTION_FLAGS_COMM_BUFFER_NESTED_PTR_PROTECTION 0x2 +#define EFI_WSMT_PROTECTION_FLAGS_SYSTEM_RESOURCE_PROTECTION 0x4 + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsUxCapsule.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsUxCapsule.h new file mode 100644 index 0000000..b11dc26 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/IndustryStandard/WindowsUxCapsule.h @@ -0,0 +1,47 @@ +/** @file + Defines Windows UX Capsule GUID and layout defined at Microsoft + Windows UEFI Firmware Update Platform specification + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _WINDOWS_UX_CAPSULE_GUID_H_ +#define _WINDOWS_UX_CAPSULE_GUID_H_ + +#pragma pack(1) + +typedef struct { + UINT8 Version; + UINT8 Checksum; + UINT8 ImageType; + UINT8 Reserved; + UINT32 Mode; + UINT32 OffsetX; + UINT32 OffsetY; + //UINT8 Image[]; +} DISPLAY_DISPLAY_PAYLOAD; + +typedef struct { + EFI_CAPSULE_HEADER CapsuleHeader; + DISPLAY_DISPLAY_PAYLOAD ImagePayload; +} EFI_DISPLAY_CAPSULE; + +#pragma pack() + +#define WINDOWS_UX_CAPSULE_GUID \ + { \ + 0x3b8c8162, 0x188c, 0x46a4, { 0xae, 0xc9, 0xbe, 0x43, 0xf1, 0xd6, 0x56, 0x97} \ + } + +extern EFI_GUID gWindowsUxCapsuleGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseLib.h new file mode 100644 index 0000000..020328b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseLib.h @@ -0,0 +1,7868 @@ +/** @file + Provides string functions, linked list functions, math functions, synchronization + functions, file path functions, and CPU architecture-specific functions. + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_LIB__ +#define __BASE_LIB__ + +// +// Definitions for architecture-specific types +// +#if defined (MDE_CPU_IA32) +/// +/// The IA-32 architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT32 Ebx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Eip; + UINT32 Ssp; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 + +#endif // defined (MDE_CPU_IA32) + +#if defined (MDE_CPU_X64) +/// +/// The x64 architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + UINT64 Rdi; + UINT64 Rsi; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT64 MxCsr; + UINT8 XmmBuffer[160]; ///< XMM6-XMM15. + UINT64 Ssp; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_X64) + +#if defined (MDE_CPU_EBC) +/// +/// The EBC context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 IP; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_EBC) + +#if defined (MDE_CPU_ARM) + +typedef struct { + UINT32 R3; ///< A copy of R13. + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 R14; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 + +#endif // defined (MDE_CPU_ARM) + +#if defined (MDE_CPU_AARCH64) +typedef struct { + // GP regs + UINT64 X19; + UINT64 X20; + UINT64 X21; + UINT64 X22; + UINT64 X23; + UINT64 X24; + UINT64 X25; + UINT64 X26; + UINT64 X27; + UINT64 X28; + UINT64 FP; + UINT64 LR; + UINT64 IP0; + + // FP regs + UINT64 D8; + UINT64 D9; + UINT64 D10; + UINT64 D11; + UINT64 D12; + UINT64 D13; + UINT64 D14; + UINT64 D15; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_AARCH64) + + +// +// String Services +// + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 + ); + +/** + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 + ); + +/** + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 + ); + +/** + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 would be returned, then the function will also ASSERT(). + + 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 + ); + +/** + 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 would be returned, then the function will also ASSERT(). + + 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 + ); + +/** + 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 would be returned, then the function will also ASSERT(). + + 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 + ); + +/** + 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 would be returned, then the function will also ASSERT(). + + 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 + ); + +/** + 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 + ); + +/** + 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 + ); + +/** + 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 + ); + +/** + 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 + ); + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated Unicode string. + @param Source The 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 + ); +#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES) + +/** + 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 Pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ); + + +/** + 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 The pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *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 The pointer to a Null-terminated Unicode string. + @param SecondString The 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 + ); + + +/** + 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 The pointer to a Null-terminated Unicode string. + @param SecondString The 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 + ); + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated Unicode string. + @param Source The 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 + ); +#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES) + +/** + 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 The pointer to a Null-terminated Unicode string. + @param SearchString The 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 + ); + +/** + 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 The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrDecimalToUintn ( + IN CONST CHAR16 *String + ); + +/** + 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 The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrDecimalToUint64 ( + IN CONST CHAR16 *String + ); + + +/** + 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 The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrHexToUintn ( + IN CONST CHAR16 *String + ); + + +/** + 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 The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrHexToUint64 ( + IN CONST CHAR16 *String + ); + +/** + 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 NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If String is not aligned in 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(). + + 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 + ); + +/** + 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 NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If String is not aligned in 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(). + + 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 + ); + +#define GUID_STRING_LENGTH 36 + +/** + 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 NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + 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 + ); + +/** + 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(). + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), 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 + ); + +#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 The pointer to a Null-terminated Unicode string. + @param Destination The pointer to a Null-terminated ASCII string. + + @return Destination. + +**/ +CHAR8 * +EFIAPI +UnicodeStrToAsciiStr ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination + ); + +#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES) + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 + 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 would be returned, then the function will also ASSERT(). + + If an error is returned, then the Destination is 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 + ); + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated ASCII string. + @param Source The 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 + ); +#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES) + +/** + 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 The pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *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 The pointer to a Null-terminated ASCII string. + @param SecondString The 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 + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + @param SecondString The 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 + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + @param SecondString The 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 + ); + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + + +/** + [ATTENTION] This function is 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 The pointer to a Null-terminated ASCII string. + @param Source The 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 + ); +#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES) + +/** + 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 The pointer to a Null-terminated ASCII string. + @param SearchString The 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 + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + + @retval The value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrDecimalToUintn ( + IN CONST CHAR8 *String + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrDecimalToUint64 ( + IN CONST CHAR8 *String + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrHexToUintn ( + IN CONST CHAR8 *String + ); + + +/** + 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 The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrHexToUint64 ( + IN CONST CHAR8 *String + ); + +/** + 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 String is NULL, then ASSERT(). + + If Address is NULL, 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 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 + ); + +/** + 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 String is NULL, then ASSERT(). + + If Address is NULL, 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 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 + ); + +/** + 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] + + If String is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @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 + ); + +/** + 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. + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), then ASSERT(). + + @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 + ); + +#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 The pointer to a Null-terminated ASCII string. + @param Destination The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +AsciiStrToUnicodeStr ( + IN CONST CHAR8 *Source, + OUT CHAR16 *Destination + ); + +#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES) + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 would be returned, then the function will also 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Convert Base64 ascii string to binary data based on RFC4648. + + Produce Null-terminated binary data in the output buffer specified by Destination and DestinationSize. + The binary data is produced by converting the Base64 ascii string specified by Source and SourceLength. + + @param Source Input ASCII characters + @param SourceLength Number of ASCII characters + @param Destination Pointer to output buffer + @param DestinationSize Caller is responsible for passing in buffer of at least DestinationSize. + Set 0 to get the size needed. Set to bytes stored on return. + + @retval RETURN_SUCCESS When binary 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_INVALID_PARAMETER If there is any invalid character in input stream. + @retval RETURN_BUFFER_TOO_SMALL If buffer length is smaller than required buffer size. + + **/ +RETURN_STATUS +EFIAPI +Base64Decode ( + IN CONST CHAR8 *Source, + IN UINTN SourceLength, + OUT UINT8 *Destination OPTIONAL, + IN OUT UINTN *DestinationSize + ); + +/** + 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 + ); + + +/** + 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 + ); + +// +// File Path Manipulation Functions +// + +/** + Removes the last directory or file entry in a path. + + @param[in, out] Path The 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 + ); + +/** + 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 + ); + +// +// Linked List Functions and Macros +// + +/** + Initializes the head node of a doubly linked list that is declared as a + global variable in a module. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this macro, the other linked list functions + may be used to add and remove nodes from the linked list. This macro results + in smaller executables by initializing the linked list in the data section, + instead if calling the InitializeListHead() function to perform the + equivalent operation. + + @param ListHead The head note of a list to initialize. + +**/ +#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead) {&(ListHead), &(ListHead)} + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 The 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 + ); + + +/** + 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 The 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 + ); + + +/** + 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 + ); + + +/** + 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 the 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +// +// Math Services +// + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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. + + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + Switches the endianness 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 + ); + + +/** + Switches the endianness 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 + ); + + +/** + Switches the endianness 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 + ); + + +/** + 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 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + + +/** + Multiples 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 +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + + +/** + Multiples a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiples 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +// +// Bit Field Functions +// + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// Base Library Checksum Functions +// + +/** + 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 + ); + + +/** + 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 two's complement checksum of Buffer. + +**/ +UINT8 +EFIAPI +CalculateCheckSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ); + + +/** + 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 + ); + + +/** + 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 two's complement checksum of Buffer. + +**/ +UINT16 +EFIAPI +CalculateCheckSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ); + + +/** + 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 + ); + + +/** + 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 two's complement checksum of Buffer. + +**/ +UINT32 +EFIAPI +CalculateCheckSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ); + + +/** + 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 + ); + + +/** + 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 two's complement checksum of Buffer. + +**/ +UINT64 +EFIAPI +CalculateCheckSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ); + +/** + 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 + ); + +// +// Base Library CPU Functions +// + +/** + Function entry point used when a stack switch is requested with SwitchStack() + + @param Context1 Context1 parameter passed into SwitchStack(). + @param Context2 Context2 parameter passed into SwitchStack(). + +**/ +typedef +VOID +(EFIAPI *SWITCH_STACK_ENTRY_POINT)( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ); + + +/** + 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 + ); + + +/** + 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 Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + NOTE: The structure BASE_LIBRARY_JUMP_BUFFER is CPU architecture specific. + The same structure must never be used for more than one CPU architecture context. + For example, a BASE_LIBRARY_JUMP_BUFFER allocated by an IA-32 module must never be used from an x64 module. + SetJump()/LongJump() is not currently supported for the EBC processor type. + + @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 + ); + + +/** + 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 Itanium processors, 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 + ); + + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ); + + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ); + + +/** + 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 + ); + + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ); + + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE if interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + 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 +SetInterruptState ( + IN BOOLEAN InterruptState + ); + + +/** + 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 + ); + + +/** + 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 architectures. + Itanium processors 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 IA-32, x64, and + EBC architectures. For Itanium processors, 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, + ... + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) +/// +/// IA32 and x64 Specific Functions. +/// Byte packed structure for 16-bit Real Mode EFLAGS. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + } Bits; + UINT16 Uint16; +} IA32_FLAGS16; + +/// +/// Byte packed structure for EFLAGS/RFLAGS. +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + UINT32 RF:1; ///< Resume Flag. + UINT32 VM:1; ///< Virtual 8086 Mode. + UINT32 AC:1; ///< Alignment Check. + UINT32 VIF:1; ///< Virtual Interrupt Flag. + UINT32 VIP:1; ///< Virtual Interrupt Pending. + UINT32 ID:1; ///< ID Flag. + UINT32 Reserved_4:10; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_EFLAGS32; + +/// +/// Byte packed structure for Control Register 0 (CR0). +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 PE:1; ///< Protection Enable. + UINT32 MP:1; ///< Monitor Coprocessor. + UINT32 EM:1; ///< Emulation. + UINT32 TS:1; ///< Task Switched. + UINT32 ET:1; ///< Extension Type. + UINT32 NE:1; ///< Numeric Error. + UINT32 Reserved_0:10; ///< Reserved. + UINT32 WP:1; ///< Write Protect. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AM:1; ///< Alignment Mask. + UINT32 Reserved_2:10; ///< Reserved. + UINT32 NW:1; ///< Mot Write-through. + UINT32 CD:1; ///< Cache Disable. + UINT32 PG:1; ///< Paging. + } Bits; + UINTN UintN; +} IA32_CR0; + +/// +/// Byte packed structure for Control Register 4 (CR4). +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 VME:1; ///< Virtual-8086 Mode Extensions. + UINT32 PVI:1; ///< Protected-Mode Virtual Interrupts. + UINT32 TSD:1; ///< Time Stamp Disable. + UINT32 DE:1; ///< Debugging Extensions. + UINT32 PSE:1; ///< Page Size Extensions. + UINT32 PAE:1; ///< Physical Address Extension. + UINT32 MCE:1; ///< Machine Check Enable. + UINT32 PGE:1; ///< Page Global Enable. + UINT32 PCE:1; ///< Performance Monitoring Counter + ///< Enable. + UINT32 OSFXSR:1; ///< Operating System Support for + ///< FXSAVE and FXRSTOR instructions + UINT32 OSXMMEXCPT:1; ///< Operating System Support for + ///< Unmasked SIMD Floating Point + ///< Exceptions. + UINT32 Reserved_0:2; ///< Reserved. + UINT32 VMXE:1; ///< VMX Enable + UINT32 Reserved_1:18; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_CR4; + +/// +/// Byte packed structure for a segment descriptor in a GDT/LDT. +/// +typedef union { + struct { + UINT32 LimitLow:16; + UINT32 BaseLow:16; + UINT32 BaseMid:8; + UINT32 Type:4; + UINT32 S:1; + UINT32 DPL:2; + UINT32 P:1; + UINT32 LimitHigh:4; + UINT32 AVL:1; + UINT32 L:1; + UINT32 DB:1; + UINT32 G:1; + UINT32 BaseHigh:8; + } Bits; + UINT64 Uint64; +} IA32_SEGMENT_DESCRIPTOR; + +/// +/// Byte packed structure for an IDTR, GDTR, LDTR descriptor. +/// +#pragma pack (1) +typedef struct { + UINT16 Limit; + UINTN Base; +} IA32_DESCRIPTOR; +#pragma pack () + +#define IA32_IDT_GATE_TYPE_TASK 0x85 +#define IA32_IDT_GATE_TYPE_INTERRUPT_16 0x86 +#define IA32_IDT_GATE_TYPE_TRAP_16 0x87 +#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0x8E +#define IA32_IDT_GATE_TYPE_TRAP_32 0x8F + +#define IA32_GDT_TYPE_TSS 0x9 +#define IA32_GDT_ALIGNMENT 8 + +#if defined (MDE_CPU_IA32) +/// +/// Byte packed structure for an IA-32 Interrupt Gate Descriptor. +/// +typedef union { + struct { + UINT32 OffsetLow:16; ///< Offset bits 15..0. + UINT32 Selector:16; ///< Selector. + UINT32 Reserved_0:8; ///< Reserved. + UINT32 GateType:8; ///< Gate Type. See #defines above. + UINT32 OffsetHigh:16; ///< Offset bits 31..16. + } Bits; + UINT64 Uint64; +} IA32_IDT_GATE_DESCRIPTOR; + +#pragma pack (1) +// +// IA32 Task-State Segment Definition +// +typedef struct { + UINT16 PreviousTaskLink; + UINT16 Reserved_2; + UINT32 ESP0; + UINT16 SS0; + UINT16 Reserved_10; + UINT32 ESP1; + UINT16 SS1; + UINT16 Reserved_18; + UINT32 ESP2; + UINT16 SS2; + UINT16 Reserved_26; + UINT32 CR3; + UINT32 EIP; + UINT32 EFLAGS; + UINT32 EAX; + UINT32 ECX; + UINT32 EDX; + UINT32 EBX; + UINT32 ESP; + UINT32 EBP; + UINT32 ESI; + UINT32 EDI; + UINT16 ES; + UINT16 Reserved_74; + UINT16 CS; + UINT16 Reserved_78; + UINT16 SS; + UINT16 Reserved_82; + UINT16 DS; + UINT16 Reserved_86; + UINT16 FS; + UINT16 Reserved_90; + UINT16 GS; + UINT16 Reserved_94; + UINT16 LDTSegmentSelector; + UINT16 Reserved_98; + UINT16 T; + UINT16 IOMapBaseAddress; +} IA32_TASK_STATE_SEGMENT; + +typedef union { + struct { + UINT32 LimitLow:16; ///< Segment Limit 15..00 + UINT32 BaseLow:16; ///< Base Address 15..00 + UINT32 BaseMid:8; ///< Base Address 23..16 + UINT32 Type:4; ///< Type (1 0 B 1) + UINT32 Reserved_43:1; ///< 0 + UINT32 DPL:2; ///< Descriptor Privilege Level + UINT32 P:1; ///< Segment Present + UINT32 LimitHigh:4; ///< Segment Limit 19..16 + UINT32 AVL:1; ///< Available for use by system software + UINT32 Reserved_52:2; ///< 0 0 + UINT32 G:1; ///< Granularity + UINT32 BaseHigh:8; ///< Base Address 31..24 + } Bits; + UINT64 Uint64; +} IA32_TSS_DESCRIPTOR; +#pragma pack () + +#endif // defined (MDE_CPU_IA32) + +#if defined (MDE_CPU_X64) +/// +/// Byte packed structure for an x64 Interrupt Gate Descriptor. +/// +typedef union { + struct { + UINT32 OffsetLow:16; ///< Offset bits 15..0. + UINT32 Selector:16; ///< Selector. + UINT32 Reserved_0:8; ///< Reserved. + UINT32 GateType:8; ///< Gate Type. See #defines above. + UINT32 OffsetHigh:16; ///< Offset bits 31..16. + UINT32 OffsetUpper:32; ///< Offset bits 63..32. + UINT32 Reserved_1:32; ///< Reserved. + } Bits; + struct { + UINT64 Uint64; + UINT64 Uint64_1; + } Uint128; +} IA32_IDT_GATE_DESCRIPTOR; + +#pragma pack (1) +// +// IA32 Task-State Segment Definition +// +typedef struct { + UINT32 Reserved_0; + UINT64 RSP0; + UINT64 RSP1; + UINT64 RSP2; + UINT64 Reserved_28; + UINT64 IST[7]; + UINT64 Reserved_92; + UINT16 Reserved_100; + UINT16 IOMapBaseAddress; +} IA32_TASK_STATE_SEGMENT; + +typedef union { + struct { + UINT32 LimitLow:16; ///< Segment Limit 15..00 + UINT32 BaseLow:16; ///< Base Address 15..00 + UINT32 BaseMidl:8; ///< Base Address 23..16 + UINT32 Type:4; ///< Type (1 0 B 1) + UINT32 Reserved_43:1; ///< 0 + UINT32 DPL:2; ///< Descriptor Privilege Level + UINT32 P:1; ///< Segment Present + UINT32 LimitHigh:4; ///< Segment Limit 19..16 + UINT32 AVL:1; ///< Available for use by system software + UINT32 Reserved_52:2; ///< 0 0 + UINT32 G:1; ///< Granularity + UINT32 BaseMidh:8; ///< Base Address 31..24 + UINT32 BaseHigh:32; ///< Base Address 63..32 + UINT32 Reserved_96:32; ///< Reserved + } Bits; + struct { + UINT64 Uint64; + UINT64 Uint64_1; + } Uint128; +} IA32_TSS_DESCRIPTOR; +#pragma pack () + +#endif // defined (MDE_CPU_X64) + +/// +/// Byte packed structure for an FP/SSE/SSE2 context. +/// +typedef struct { + UINT8 Buffer[512]; +} IA32_FX_BUFFER; + +/// +/// Structures for the 16-bit real mode thunks. +/// +typedef struct { + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT8 BL; + UINT8 BH; + UINT16 Reserved5; + UINT8 DL; + UINT8 DH; + UINT16 Reserved6; + UINT8 CL; + UINT8 CH; + UINT16 Reserved7; + UINT8 AL; + UINT8 AH; + UINT16 Reserved8; +} IA32_BYTE_REGS; + +typedef struct { + UINT16 DI; + UINT16 Reserved1; + UINT16 SI; + UINT16 Reserved2; + UINT16 BP; + UINT16 Reserved3; + UINT16 SP; + UINT16 Reserved4; + UINT16 BX; + UINT16 Reserved5; + UINT16 DX; + UINT16 Reserved6; + UINT16 CX; + UINT16 Reserved7; + UINT16 AX; + UINT16 Reserved8; +} IA32_WORD_REGS; + +typedef struct { + UINT32 EDI; + UINT32 ESI; + UINT32 EBP; + UINT32 ESP; + UINT32 EBX; + UINT32 EDX; + UINT32 ECX; + UINT32 EAX; + UINT16 DS; + UINT16 ES; + UINT16 FS; + UINT16 GS; + IA32_EFLAGS32 EFLAGS; + UINT32 Eip; + UINT16 CS; + UINT16 SS; +} IA32_DWORD_REGS; + +typedef union { + IA32_DWORD_REGS E; + IA32_WORD_REGS X; + IA32_BYTE_REGS H; +} IA32_REGISTER_SET; + +/// +/// Byte packed structure for an 16-bit real mode thunks. +/// +typedef struct { + IA32_REGISTER_SET *RealModeState; + VOID *RealModeBuffer; + UINT32 RealModeBufferSize; + UINT32 ThunkAttributes; +} THUNK_CONTEXT; + +#define THUNK_ATTRIBUTE_BIG_REAL_MODE 0x00000001 +#define THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 0x00000002 +#define THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL 0x00000004 + +/// +/// Type definition for representing labels in NASM source code that allow for +/// the patching of immediate operands of IA32 and X64 instructions. +/// +/// While the type is technically defined as a function type (note: not a +/// pointer-to-function type), such labels in NASM source code never stand for +/// actual functions, and identifiers declared with this function type should +/// never be called. This is also why the EFIAPI calling convention specifier +/// is missing from the typedef, and why the typedef does not follow the usual +/// edk2 coding style for function (or pointer-to-function) typedefs. The VOID +/// return type and the VOID argument list are merely artifacts. +/// +typedef VOID (X86_ASSEMBLY_PATCH_LABEL) (VOID); + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxSave ( + 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. + + 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 The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ); + + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmInvd ( + 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 +AsmFlushCacheLine ( + IN VOID *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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +// +// 16-bit thunking services +// + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Load given selector into TR register. + + @param[in] Selector Task segment selector +**/ +VOID +EFIAPI +AsmWriteTr ( + IN UINT16 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 + ); + +/** + 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 + ); + +#endif // defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) +#endif // !defined (__BASE_LIB__) diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseMemoryLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseMemoryLib.h new file mode 100644 index 0000000..5199143 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/BaseMemoryLib.h @@ -0,0 +1,489 @@ +/** @file + Provides copy memory, fill memory, zero memory, and GUID functions. + + The Base Memory Library provides optimized implementations for common memory-based operations. + These functions should be used in place of coding your own loops to do equivalent common functions. + This allows optimized library implementations to help increase performance. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_MEMORY_LIB__ +#define __BASE_MEMORY_LIB__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 target the 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, otherwise NULL. + +**/ +VOID * +EFIAPI +ScanMem8 ( + 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. + + This function searches target the 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, otherwise NULL. + +**/ +VOID * +EFIAPI +ScanMem16 ( + 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. + + This function searches target the 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, otherwise NULL. + +**/ +VOID * +EFIAPI +ScanMem32 ( + 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. + + This function searches target the 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, otherwise NULL. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 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 target the 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, otherwise NULL. + +**/ +VOID * +EFIAPI +ScanMemN ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINTN Value + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the 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, otherwise NULL. + +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CacheMaintenanceLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CacheMaintenanceLib.h new file mode 100644 index 0000000..7101bef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CacheMaintenanceLib.h @@ -0,0 +1,212 @@ +/** @file + Provides services to maintain instruction and data caches. + + The Cache Maintenance Library provides abstractions for basic processor cache operations. + It removes the need to use assembly in C code. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __CACHE_MAINTENANCE_LIB__ +#define __CACHE_MAINTENANCE_LIB__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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, the 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CpuLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CpuLib.h new file mode 100644 index 0000000..6b4e4da --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/CpuLib.h @@ -0,0 +1,51 @@ +/** @file + Provides CPU architecture specific functions that can not be defined + in the Base Library due to dependencies on the PAL Library + + The CPU Library provides services to flush CPU TLBs and place the CPU in a sleep state. + The implementation of these services on Itanium processors requires the use of PAL Calls. + PAL Calls require PEI and DXE specific mechanisms to look up PAL Entry Point. + As a result, these services could not be defined in the Base Library. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __CPU_LIB_H__ +#define __CPU_LIB_H__ + +/** + 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 + ); + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugLib.h new file mode 100644 index 0000000..d744025 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugLib.h @@ -0,0 +1,529 @@ +/** @file + Provides services to print debug and assert messages to a debug output device. + + The Debug library supports debug print and asserts based on a combination of macros and code. + The debug library can be turned on and off so that the debug code does not increase the size of an image. + + Note that a reserved macro named MDEPKG_NDEBUG is introduced for the intention + of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is + defined, then debug and assert related macros wrapped by it are the NULL implementations. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEBUG_LIB_H__ +#define __DEBUG_LIB_H__ + +// +// Declare bits for PcdDebugPropertyMask +// +#define DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED 0x01 +#define DEBUG_PROPERTY_DEBUG_PRINT_ENABLED 0x02 +#define DEBUG_PROPERTY_DEBUG_CODE_ENABLED 0x04 +#define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED 0x08 +#define DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED 0x10 +#define DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED 0x20 + +// +// Declare bits for PcdDebugPrintErrorLevel and the ErrorLevel parameter of DebugPrint() +// +#define DEBUG_INIT 0x00000001 // Initialization +#define DEBUG_WARN 0x00000002 // Warnings +#define DEBUG_LOAD 0x00000004 // Load events +#define DEBUG_FS 0x00000008 // EFI File system +#define DEBUG_POOL 0x00000010 // Alloc & Free (pool) +#define DEBUG_PAGE 0x00000020 // Alloc & Free (page) +#define DEBUG_INFO 0x00000040 // Informational debug messages +#define DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers +#define DEBUG_VARIABLE 0x00000100 // Variable +#define DEBUG_BM 0x00000400 // Boot Manager +#define DEBUG_BLKIO 0x00001000 // BlkIo Driver +#define DEBUG_NET 0x00004000 // Network Io Driver +#define DEBUG_UNDI 0x00010000 // UNDI Driver +#define DEBUG_LOADFILE 0x00020000 // LoadFile +#define DEBUG_EVENT 0x00080000 // Event messages +#define DEBUG_GCD 0x00100000 // Global Coherency Database changes +#define DEBUG_CACHE 0x00200000 // Memory range cachability changes +#define DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + // significantly impact boot performance +#define DEBUG_ERROR 0x80000000 // Error + +// +// Aliases of debug message mask bits +// +#define EFI_D_INIT DEBUG_INIT +#define EFI_D_WARN DEBUG_WARN +#define EFI_D_LOAD DEBUG_LOAD +#define EFI_D_FS DEBUG_FS +#define EFI_D_POOL DEBUG_POOL +#define EFI_D_PAGE DEBUG_PAGE +#define EFI_D_INFO DEBUG_INFO +#define EFI_D_DISPATCH DEBUG_DISPATCH +#define EFI_D_VARIABLE DEBUG_VARIABLE +#define EFI_D_BM DEBUG_BM +#define EFI_D_BLKIO DEBUG_BLKIO +#define EFI_D_NET DEBUG_NET +#define EFI_D_UNDI DEBUG_UNDI +#define EFI_D_LOADFILE DEBUG_LOADFILE +#define EFI_D_EVENT DEBUG_EVENT +#define EFI_D_VERBOSE DEBUG_VERBOSE +#define EFI_D_ERROR DEBUG_ERROR + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format The format string for the debug message to print. + @param ... The variable argument list whose contents are accessed + based on the format string specified by Format. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ); + + +/** + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT (): \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 + ); + + +/** + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise, FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ); + + +/** + Returns TRUE if DEBUG() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise, FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ); + + +/** + Returns TRUE if DEBUG_CODE() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise, FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ); + + +/** + Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise, FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ); + +/** + 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 + ); + +/** + Internal worker macro that calls DebugAssert(). + + This macro calls DebugAssert(), passing in the filename, line number, and an + expression that evaluated to FALSE. + + @param Expression Boolean expression that evaluated to FALSE + +**/ +#define _ASSERT(Expression) DebugAssert (__FILE__, __LINE__, #Expression) + + +/** + Internal worker macro that calls DebugPrint(). + + This macro calls DebugPrint() passing in the debug error level, a format + string, and a variable argument list. + __VA_ARGS__ is not supported by EBC compiler, Microsoft Visual Studio .NET 2003 + and Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830. + + @param Expression Expression containing an error level, a format string, + and a variable argument list based on the format string. + +**/ + +#if !defined(MDE_CPU_EBC) && (!defined (_MSC_VER) || _MSC_VER > 1400) + #define _DEBUG_PRINT(PrintLevel, ...) \ + do { \ + if (DebugPrintLevelEnabled (PrintLevel)) { \ + DebugPrint (PrintLevel, ##__VA_ARGS__); \ + } \ + } while (FALSE) + #define _DEBUG(Expression) _DEBUG_PRINT Expression +#else +#define _DEBUG(Expression) DebugPrint Expression +#endif + +/** + Macro that calls DebugAssert() if an expression evaluates to FALSE. + + If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED + bit of PcdDebugProperyMask is set, then this macro evaluates the Boolean + expression specified by Expression. If Expression evaluates to FALSE, then + DebugAssert() is called passing in the source filename, source line number, + and Expression. + + @param Expression Boolean expression. + +**/ +#if !defined(MDEPKG_NDEBUG) + #define ASSERT(Expression) \ + do { \ + if (DebugAssertEnabled ()) { \ + if (!(Expression)) { \ + _ASSERT (Expression); \ + ANALYZER_UNREACHABLE (); \ + } \ + } \ + } while (FALSE) +#else + #define ASSERT(Expression) +#endif + +/** + Macro that calls DebugPrint(). + + If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED + bit of PcdDebugProperyMask is set, then this macro passes Expression to + DebugPrint(). + + @param Expression Expression containing an error level, a format string, + and a variable argument list based on the format string. + + +**/ +#if !defined(MDEPKG_NDEBUG) + #define DEBUG(Expression) \ + do { \ + if (DebugPrintEnabled ()) { \ + _DEBUG (Expression); \ + } \ + } while (FALSE) +#else + #define DEBUG(Expression) +#endif + +/** + Macro that calls DebugAssert() if an EFI_STATUS evaluates to an error code. + + If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED + bit of PcdDebugProperyMask is set, then this macro evaluates the EFI_STATUS + value specified by StatusParameter. If StatusParameter is an error code, + then DebugAssert() is called passing in the source filename, source line + number, and StatusParameter. + + @param StatusParameter EFI_STATUS value to evaluate. + +**/ +#if !defined(MDEPKG_NDEBUG) + #define ASSERT_EFI_ERROR(StatusParameter) \ + do { \ + if (DebugAssertEnabled ()) { \ + if (EFI_ERROR (StatusParameter)) { \ + DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", StatusParameter)); \ + _ASSERT (!EFI_ERROR (StatusParameter)); \ + } \ + } \ + } while (FALSE) +#else + #define ASSERT_EFI_ERROR(StatusParameter) +#endif + +/** + Macro that calls DebugAssert() if a RETURN_STATUS evaluates to an error code. + + If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED + bit of PcdDebugProperyMask is set, then this macro evaluates the + RETURN_STATUS value specified by StatusParameter. If StatusParameter is an + error code, then DebugAssert() is called passing in the source filename, + source line number, and StatusParameter. + + @param StatusParameter RETURN_STATUS value to evaluate. + +**/ +#if !defined(MDEPKG_NDEBUG) + #define ASSERT_RETURN_ERROR(StatusParameter) \ + do { \ + if (DebugAssertEnabled ()) { \ + if (RETURN_ERROR (StatusParameter)) { \ + DEBUG ((DEBUG_ERROR, "\nASSERT_RETURN_ERROR (Status = %r)\n", \ + StatusParameter)); \ + _ASSERT (!RETURN_ERROR (StatusParameter)); \ + } \ + } \ + } while (FALSE) +#else + #define ASSERT_RETURN_ERROR(StatusParameter) +#endif + +/** + Macro that calls DebugAssert() if a protocol is already installed in the + handle database. + + If MDEPKG_NDEBUG is defined or the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit + of PcdDebugProperyMask is clear, then return. + + If Handle is NULL, then a check is made to see if the protocol specified by Guid + is present on any handle in the handle database. If Handle is not NULL, then + a check is made to see if the protocol specified by Guid is present on the + handle specified by Handle. If the check finds the protocol, then DebugAssert() + is called passing in the source filename, source line number, and Guid. + + If Guid is NULL, then ASSERT(). + + @param Handle The handle to check for the protocol. This is an optional + parameter that may be NULL. If it is NULL, then the entire + handle database is searched. + + @param Guid The pointer to a protocol GUID. + +**/ +#if !defined(MDEPKG_NDEBUG) + #define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid) \ + do { \ + if (DebugAssertEnabled ()) { \ + VOID *Instance; \ + ASSERT (Guid != NULL); \ + if (Handle == NULL) { \ + if (!EFI_ERROR (gBS->LocateProtocol ((EFI_GUID *)Guid, NULL, &Instance))) { \ + _ASSERT (Guid already installed in database); \ + } \ + } else { \ + if (!EFI_ERROR (gBS->HandleProtocol (Handle, (EFI_GUID *)Guid, &Instance))) { \ + _ASSERT (Guid already installed on Handle); \ + } \ + } \ + } \ + } while (FALSE) +#else + #define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid) +#endif + +/** + Macro that marks the beginning of debug source code. + + If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set, + then this macro marks the beginning of source code that is included in a module. + Otherwise, the source lines between DEBUG_CODE_BEGIN() and DEBUG_CODE_END() + are not included in a module. + +**/ +#define DEBUG_CODE_BEGIN() do { if (DebugCodeEnabled ()) { UINT8 __DebugCodeLocal + + +/** + The macro that marks the end of debug source code. + + If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set, + then this macro marks the end of source code that is included in a module. + Otherwise, the source lines between DEBUG_CODE_BEGIN() and DEBUG_CODE_END() + are not included in a module. + +**/ +#define DEBUG_CODE_END() __DebugCodeLocal = 0; __DebugCodeLocal++; } } while (FALSE) + + +/** + The macro that declares a section of debug source code. + + If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set, + then the source code specified by Expression is included in a module. + Otherwise, the source specified by Expression is not included in a module. + +**/ +#define DEBUG_CODE(Expression) \ + DEBUG_CODE_BEGIN (); \ + Expression \ + DEBUG_CODE_END () + + +/** + The macro that calls DebugClearMemory() to clear a buffer to a default value. + + If the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set, + then this macro calls DebugClearMemory() passing in Address and Length. + + @param Address The pointer to a buffer. + @param Length The number of bytes in the buffer to set. + +**/ +#define DEBUG_CLEAR_MEMORY(Address, Length) \ + do { \ + if (DebugClearMemoryEnabled ()) { \ + DebugClearMemory (Address, Length); \ + } \ + } while (FALSE) + + +/** + Macro that calls DebugAssert() if the containing record does not have a + matching signature. If the signatures matches, then a pointer to the data + structure that contains a specified field of that data structure is returned. + This is a lightweight method hide information by placing a public data + structure inside a larger private data structure and using a pointer to the + public data structure to retrieve a pointer to the private data structure. + + If MDEPKG_NDEBUG is defined or the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit + of PcdDebugProperyMask is clear, then this macro computes the offset, in bytes, + of the field specified by Field from the beginning of the data structure specified + by TYPE. This offset is subtracted from Record, and is used to return a pointer + to a data structure of the type specified by TYPE. + + If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit + of PcdDebugProperyMask is set, then this macro computes the offset, in bytes, + of field specified by Field from the beginning of the data structure specified + by TYPE. This offset is subtracted from Record, and is used to compute a pointer + to a data structure of the type specified by TYPE. The Signature field of the + data structure specified by TYPE is compared to TestSignature. If the signatures + match, then a pointer to the pointer to a data structure of the type specified by + TYPE is returned. If the signatures do not match, then DebugAssert() is called + with a description of "CR has a bad signature" and Record is returned. + + If the data type specified by TYPE does not contain the field specified by Field, + then the module will not compile. + + If TYPE does not contain a field called Signature, then the module will not + compile. + + @param Record The pointer to the field specified by Field within a data + structure of type TYPE. + + @param TYPE The name of the data structure type to return This + data structure must contain the field specified by Field. + + @param Field The name of the field in the data structure specified + by TYPE to which Record points. + + @param TestSignature The 32-bit signature value to match. + +**/ +#if !defined(MDEPKG_NDEBUG) + #define CR(Record, TYPE, Field, TestSignature) \ + (DebugAssertEnabled () && (BASE_CR (Record, TYPE, Field)->Signature != TestSignature)) ? \ + (TYPE *) (_ASSERT (CR has Bad Signature), Record) : \ + BASE_CR (Record, TYPE, Field) +#else + #define CR(Record, TYPE, Field, TestSignature) \ + BASE_CR (Record, TYPE, Field) +#endif + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugPrintErrorLevelLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugPrintErrorLevelLib.h new file mode 100644 index 0000000..000d162 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DebugPrintErrorLevelLib.h @@ -0,0 +1,43 @@ +/** @file + Debug Print Error Level Library class + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#ifndef _DEBUG_PRINT_ERROR_LEVEL_LIB_H_ +#define _DEBUG_PRINT_ERROR_LEVEL_LIB_H_ + +/** + 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 + ); + +/** + 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 successfully set. + @retval FALSE The debug print error level mask could not be set. + +**/ +BOOLEAN +EFIAPI +SetDebugPrintErrorLevel ( + UINT32 ErrorLevel + ); +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DevicePathLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DevicePathLib.h new file mode 100644 index 0000000..c338f73 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DevicePathLib.h @@ -0,0 +1,567 @@ +/** @file + Provides library functions to construct and parse UEFI Device Paths. + + This library provides defines, macros, and functions to help create and parse + EFI_DEVICE_PATH_PROTOCOL structures. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEVICE_PATH_LIB_H__ +#define __DEVICE_PATH_LIB_H__ + +#define END_DEVICE_PATH_LENGTH (sizeof (EFI_DEVICE_PATH_PROTOCOL)) + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 >= 0x10000, 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 secified 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeCoreEntryPoint.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeCoreEntryPoint.h new file mode 100644 index 0000000..5e9f7a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeCoreEntryPoint.h @@ -0,0 +1,99 @@ +/** @file + Module entry point library for DXE core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +/// +/// Global variable that contains a pointer to the Hob List passed into the DXE Core entry point. +/// +extern VOID *gHobList; + + +/** + 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 Pointer to the beginning of the HOB List passed in from the PEI Phase. + +**/ +VOID +EFIAPI +_ModuleEntryPoint ( + IN VOID *HobStart + ); + + +/** + Required by the EBC compiler and identical in functionality to _ModuleEntryPoint(). + + This function is required to call _ModuleEntryPoint() passing in HobStart. + + @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase. + +**/ +VOID +EFIAPI +EfiMain ( + IN VOID *HobStart + ); + + +/** + Autogenerated function that calls the library constructors for all of the module's dependent libraries. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of library constructors for the set of library instances + that a module depends on. This includes library instances that a module depends on + directly and library instances that a module depends on indirectly through other + libraries. This function is autogenerated by build tools and those build tools are + responsible for collecting the set of library instances, determine which ones have + constructors, and calling the library constructors in the proper order based upon + each of the library instances own dependencies. + + @param ImageHandle The image handle of the DXE Core. + @param SystemTable A pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Autogenerated function that calls a set of module entry points. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of module entry points. + This function is autogenerated by build tools and those build tools are responsible + for collecting the module entry points and calling them in a specified order. + + @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase. + +**/ +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN VOID *HobStart + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesLib.h new file mode 100644 index 0000000..187d42d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesLib.h @@ -0,0 +1,330 @@ +/** @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) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DXE_SERVICES_LIB_H__ +#define __DXE_SERVICES_LIB_H__ + +/** + 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 + ); + +/** + Searches all the available 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 in which the firmware volumes are 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. + It is 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 + ); + +/** + 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. + It is 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 + ); + + +/** + Searches the FFS file the 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. + It is 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 + ); + + +/** + 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 The 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 Pointer to the device path of the file that is abstracted to + the file buffer. + @param[out] FileSize Pointer to the size of the abstracted file buffer. + @param[out] AuthenticationStatus Pointer to 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesTableLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesTableLib.h new file mode 100644 index 0000000..e0edde3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/DxeServicesTableLib.h @@ -0,0 +1,34 @@ +/** @file + Provides a service to retrieve a pointer to the DXE Services Table. + Only available to DXE module types. + + This library does not contain any functions or macros. It simply exports a global + pointer to the DXE Services Table as defined in the Platform Initialization Driver + Execution Environment Core Interface Specification. The library constructor must + initialize this global pointer to the DX Services Table, so it is available at the + module's entry point. Since there is overhead in looking up the pointer to the DXE + Services Table, only those modules that actually require access to the DXE Services + Table should use this library. This will typically be DXE Drivers that require GCD + or Dispatcher services. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DXE_SERVICES_TABLE_LIB_H__ +#define __DXE_SERVICES_TABLE_LIB_H__ + +/// +/// Cache copy of the DXE Services Table +/// +extern EFI_DXE_SERVICES *gDS; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtendedSalLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtendedSalLib.h new file mode 100644 index 0000000..dcee128 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtendedSalLib.h @@ -0,0 +1,494 @@ +/** @file + Library class definition of Extended SAL Library. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EXTENDED_SAL_LIB_H__ +#define _EXTENDED_SAL_LIB_H__ + +#include + +/** + Register ESAL Class and its associated global. + + This function Registers one or more Extended SAL services in a given + class along with the associated global context. + This function is only available prior to ExitBootServices(). + + @param ClassGuidLo GUID of function class, lower 64-bits + @param ClassGuidHi GUID of function class, upper 64-bits + @param ModuleGlobal Module global for Function. + @param ... List of Function/FunctionId pairs, ended by NULL + + @retval EFI_SUCCESS The Extended SAL services were registered. + @retval EFI_UNSUPPORTED This function was called after ExitBootServices(). + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to register one or more of the specified services. + @retval Other ClassGuid could not be installed onto a new handle. + +**/ +EFI_STATUS +EFIAPI +RegisterEsalClass ( + IN CONST UINT64 ClassGuidLo, + IN CONST UINT64 ClassGuidHi, + IN VOID *ModuleGlobal, OPTIONAL + ... + ); + +/** + Calls an Extended SAL Class service that was previously registered with RegisterEsalClass(). + + This function calls an Extended SAL Class service that was previously registered with RegisterEsalClass(). + + @param ClassGuidLo GUID of function, lower 64-bits + @param ClassGuidHi GUID of function, upper 64-bits + @param FunctionId Function in ClassGuid to call + @param Arg2 Argument 2 ClassGuid/FunctionId defined + @param Arg3 Argument 3 ClassGuid/FunctionId defined + @param Arg4 Argument 4 ClassGuid/FunctionId defined + @param Arg5 Argument 5 ClassGuid/FunctionId defined + @param Arg6 Argument 6 ClassGuid/FunctionId defined + @param Arg7 Argument 7 ClassGuid/FunctionId defined + @param Arg8 Argument 8 ClassGuid/FunctionId defined + + @retval EFI_SAL_ERROR The address of ExtendedSalProc() can not be determined + for the current CPU execution mode. + @retval Other See the return status from ExtendedSalProc() in the + EXTENDED_SAL_BOOT_SERVICE_PROTOCOL. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalCall ( + IN UINT64 ClassGuidLo, + IN UINT64 ClassGuidHi, + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +/** + Wrapper for the EsalStallFunctionId service of Extended SAL Stall Services Class. + + This function is a wrapper for the EsalStallFunctionId service of Extended SAL + Stall Services Class. See EsalStallFunctionId of Extended SAL Specification. + + @param Microseconds The number of microseconds to delay. + + @retval EFI_SAL_SUCCESS Call completed without error. + @retval EFI_SAL_INVALID_ARGUMENT Invalid argument. + @retval EFI_SAL_VIRTUAL_ADDRESS_ERROR Virtual address not registered + +**/ +SAL_RETURN_REGS +EFIAPI +EsalStall ( + IN UINTN Microseconds + ); + +/** + Wrapper for the EsalSetNewPalEntryFunctionId service of Extended SAL PAL Services Services Class. + + This function is a wrapper for the EsalSetNewPalEntryFunctionId service of Extended SAL + PAL Services Services Class. See EsalSetNewPalEntryFunctionId of Extended SAL Specification. + + @param PhysicalAddress If TRUE, then PalEntryPoint is a physical address. + If FALSE, then PalEntryPoint is a virtual address. + @param PalEntryPoint The PAL Entry Point being set. + + @retval EFI_SAL_SUCCESS The PAL Entry Point was set. + @retval EFI_SAL_VIRTUAL_ADDRESS_ERROR This function was called in virtual mode before + virtual mappings for the specified Extended SAL + Procedure are available. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalSetNewPalEntry ( + IN BOOLEAN PhysicalAddress, + IN UINT64 PalEntryPoint + ); + +/** + Wrapper for the EsalGetNewPalEntryFunctionId service of Extended SAL PAL Services Services Class. + + This function is a wrapper for the EsalGetNewPalEntryFunctionId service of Extended SAL + PAL Services Services Class. See EsalGetNewPalEntryFunctionId of Extended SAL Specification. + + @param PhysicalAddress If TRUE, then PalEntryPoint is a physical address. + If FALSE, then PalEntryPoint is a virtual address. + + @retval EFI_SAL_SUCCESS The PAL Entry Point was retrieved and returned in + SAL_RETURN_REGS.r9. + @retval EFI_SAL_VIRTUAL_ADDRESS_ERROR This function was called in virtual mode before + virtual mappings for the specified Extended SAL + Procedure are available. + @return r9 PAL entry point retrieved. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetNewPalEntry ( + IN BOOLEAN PhysicalAddress + ); + +/** + Wrapper for the EsalGetStateBufferFunctionId service of Extended SAL MCA Log Services Class. + + This function is a wrapper for the EsalGetStateBufferFunctionId service of Extended SAL + MCA Log Services Class. See EsalGetStateBufferFunctionId of Extended SAL Specification. + + @param McaType See type parameter of SAL Procedure SAL_GET_STATE_INFO. + @param McaBuffer A pointer to the base address of the returned buffer. + Copied from SAL_RETURN_REGS.r9. + @param BufferSize A pointer to the size, in bytes, of the returned buffer. + Copied from SAL_RETURN_REGS.r10. + + @retval EFI_SAL_SUCCESS The memory buffer to store error records was returned in r9 and r10. + @retval EFI_OUT_OF_RESOURCES A memory buffer for string error records in not available + @return r9 Base address of the returned buffer + @return r10 Size of the returned buffer in bytes + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetStateBuffer ( + IN UINT64 McaType, + OUT UINT8 **McaBuffer, + OUT UINTN *BufferSize + ); + +/** + Wrapper for the EsalSaveStateBufferFunctionId service of Extended SAL MCA Log Services Class. + + This function is a wrapper for the EsalSaveStateBufferFunctionId service of Extended SAL + MCA Log Services Class. See EsalSaveStateBufferFunctionId of Extended SAL Specification. + + @param McaType See type parameter of SAL Procedure SAL_GET_STATE_INFO. + + @retval EFI_SUCCESS The memory buffer containing the error record was written to nonvolatile storage. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalSaveStateBuffer ( + IN UINT64 McaType + ); + +/** + Wrapper for the EsalGetVectorsFunctionId service of Extended SAL Base Services Class. + + This function is a wrapper for the EsalGetVectorsFunctionId service of Extended SAL + Base Services Class. See EsalGetVectorsFunctionId of Extended SAL Specification. + + @param VectorType The vector type to retrieve. + 0 - MCA, 1 - BSP INIT, 2 - BOOT_RENDEZ, 3 - AP INIT. + + @retval EFI_SAL_SUCCESS Call completed without error. + @retval EFI_SAL_INVALID_ARGUMENT Invalid argument. + @retval EFI_SAL_NO_INFORMATION The requested vector has not been registered + with the SAL Procedure SAL_SET_VECTORS. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetVectors ( + IN UINT64 VectorType + ); + +/** + Wrapper for the EsalMcGetParamsFunctionId service of Extended SAL Base Services Class. + + This function is a wrapper for the EsalMcGetParamsFunctionId service of Extended SAL + Base Services Class. See EsalMcGetParamsFunctionId of Extended SAL Specification. + + @param ParamInfoType The parameter type to retrieve. + 1 - rendezvous interrupt + 2 - wake up + 3 - Corrected Platform Error Vector. + + @retval EFI_SAL_SUCCESS Call completed without error. + @retval EFI_SAL_INVALID_ARGUMENT Invalid argument. + @retval EFI_SAL_NO_INFORMATION The requested vector has not been registered + with the SAL Procedure SAL_MC_SET_PARAMS. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalMcGetParams ( + IN UINT64 ParamInfoType + ); + +/** + Wrapper for the EsalMcGetParamsFunctionId service of Extended SAL Base Services Class. + + This function is a wrapper for the EsalMcGetParamsFunctionId service of Extended SAL + Base Services Class. See EsalMcGetParamsFunctionId of Extended SAL Specification. + + @retval EFI_SAL_SUCCESS Call completed without error. + @retval EFI_SAL_NO_INFORMATION The requested vector has not been registered + with the SAL Procedure SAL_MC_SET_PARAMS. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalMcGetMcParams ( + VOID + ); + +/** + Wrapper for the EsalGetMcCheckinFlagsFunctionId service of Extended SAL Base Services Class. + + This function is a wrapper for the EsalGetMcCheckinFlagsFunctionId service of Extended SAL + Base Services Class. See EsalGetMcCheckinFlagsFunctionId of Extended SAL Specification. + + @param CpuIndex The index of the CPU of set of enabled CPUs to check. + + @retval EFI_SAL_SUCCESS The checkin status of the requested CPU was returned. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetMcCheckinFlags ( + IN UINT64 CpuIndex + ); + +/** + Wrapper for the EsalAddCpuDataFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalAddCpuDataFunctionId service of Extended SAL + MP Services Class. See EsalAddCpuDataFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU being added. + @param Enabled The enable flag for the CPU being added. + TRUE means the CPU is enabled. + FALSE means the CPU is disabled. + @param PalCompatibility The PAL Compatibility value for the CPU being added. + + @retval EFI_SAL_SUCCESS The CPU was added to the database. + @retval EFI_SAL_NOT_ENOUGH_SCRATCH There are not enough resource available to add the CPU. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalAddCpuData ( + IN UINT64 CpuGlobalId, + IN BOOLEAN Enabled, + IN UINT64 PalCompatibility + ); + +/** + Wrapper for the EsalRemoveCpuDataFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalRemoveCpuDataFunctionId service of Extended SAL + MP Services Class. See EsalRemoveCpuDataFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU being removed. + + @retval EFI_SAL_SUCCESS The CPU was removed from the database. + @retval EFI_SAL_NO_INFORMATION The specified CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalRemoveCpuData ( + IN UINT64 CpuGlobalId + ); + +/** + Wrapper for the EsalModifyCpuDataFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalModifyCpuDataFunctionId service of Extended SAL + MP Services Class. See EsalModifyCpuDataFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU being modified. + @param Enabled The enable flag for the CPU being modified. + TRUE means the CPU is enabled. + FALSE means the CPU is disabled. + @param PalCompatibility The PAL Compatibility value for the CPU being modified. + + @retval EFI_SAL_SUCCESS The CPU database was updated. + @retval EFI_SAL_NO_INFORMATION The specified CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalModifyCpuData ( + IN UINT64 CpuGlobalId, + IN BOOLEAN Enabled, + IN UINT64 PalCompatibility + ); + +/** + Wrapper for the EsalGetCpuDataByIdFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalGetCpuDataByIdFunctionId service of Extended SAL + MP Services Class. See EsalGetCpuDataByIdFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU being looked up. + @param IndexByEnabledCpu If TRUE, then the index of set of enabled CPUs of database is returned. + If FALSE, then the index of set of all CPUs of database is returned. + + @retval EFI_SAL_SUCCESS The information on the specified CPU was returned. + @retval EFI_SAL_NO_INFORMATION The specified CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetCpuDataById ( + IN UINT64 CpuGlobalId, + IN BOOLEAN IndexByEnabledCpu + ); + +/** + Wrapper for the EsalGetCpuDataByIndexFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalGetCpuDataByIndexFunctionId service of Extended SAL + MP Services Class. See EsalGetCpuDataByIndexFunctionId of Extended SAL Specification. + + @param Index The Global ID for the CPU being modified. + @param IndexByEnabledCpu If TRUE, then the index of set of enabled CPUs of database is returned. + If FALSE, then the index of set of all CPUs of database is returned. + + @retval EFI_SAL_SUCCESS The information on the specified CPU was returned. + @retval EFI_SAL_NO_INFORMATION The specified CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetCpuDataByIndex ( + IN UINT64 Index, + IN BOOLEAN IndexByEnabledCpu + ); + +/** + Wrapper for the EsalWhoAmIFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalWhoAmIFunctionId service of Extended SAL + MP Services Class. See EsalWhoAmIFunctionId of Extended SAL Specification. + + @param IndexByEnabledCpu If TRUE, then the index of set of enabled CPUs of database is returned. + If FALSE, then the index of set of all CPUs of database is returned. + + @retval EFI_SAL_SUCCESS The Global ID for the calling CPU was returned. + @retval EFI_SAL_NO_INFORMATION The calling CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalWhoAmI ( + IN BOOLEAN IndexByEnabledCpu + ); + +/** + Wrapper for the EsalNumProcessors service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalNumProcessors service of Extended SAL + MP Services Class. See EsalNumProcessors of Extended SAL Specification. + + @retval EFI_SAL_SUCCESS The information on the number of CPUs in the platform + was returned. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalNumProcessors ( + VOID + ); + +/** + Wrapper for the EsalSetMinStateFnctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalSetMinStateFnctionId service of Extended SAL + MP Services Class. See EsalSetMinStateFnctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU whose MINSTATE pointer is being set. + @param MinStatePointer The physical address of the MINSTATE buffer for the CPU + specified by CpuGlobalId. + + @retval EFI_SAL_SUCCESS The MINSTATE pointer was set for the specified CPU. + @retval EFI_SAL_NO_INFORMATION The specified CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalSetMinState ( + IN UINT64 CpuGlobalId, + IN EFI_PHYSICAL_ADDRESS MinStatePointer + ); + +/** + Wrapper for the EsalGetMinStateFunctionId service of Extended SAL MP Services Class. + + This function is a wrapper for the EsalGetMinStateFunctionId service of Extended SAL + MP Services Class. See EsalGetMinStateFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU whose MINSTATE pointer is being retrieved. + + @retval EFI_SAL_SUCCESS The MINSTATE pointer for the specified CPU was retrieved. + @retval EFI_SAL_NO_INFORMATION The specified CPU is not in the database. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalGetMinState ( + IN UINT64 CpuGlobalId + ); + +/** + Wrapper for the EsalMcsGetStateInfoFunctionId service of Extended SAL MCA Services Class. + + This function is a wrapper for the EsalMcsGetStateInfoFunctionId service of Extended SAL + MCA Services Class. See EsalMcsGetStateInfoFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU whose MCA state buffer is being retrieved. + @param StateBufferPointer A pointer to the returned MCA state buffer. + @param RequiredStateBufferSize A pointer to the size, in bytes, of the returned MCA state buffer. + + @retval EFI_SUCCESS MINSTATE successfully got and size calculated. + @retval EFI_SAL_NO_INFORMATION Fail to get MINSTATE. + +**/ +SAL_RETURN_REGS +EFIAPI +EsalMcaGetStateInfo ( + IN UINT64 CpuGlobalId, + OUT EFI_PHYSICAL_ADDRESS *StateBufferPointer, + OUT UINT64 *RequiredStateBufferSize + ); + +/** + Wrapper for the EsalMcaRegisterCpuFunctionId service of Extended SAL MCA Services Class. + + This function is a wrapper for the EsalMcaRegisterCpuFunctionId service of Extended SAL + MCA Services Class. See EsalMcaRegisterCpuFunctionId of Extended SAL Specification. + + @param CpuGlobalId The Global ID for the CPU whose MCA state buffer is being set. + @param StateBufferPointer A pointer to the MCA state buffer. + + @retval EFI_SAL_NO_INFORMATION Cannot get the processor info with the CpuId + @retval EFI_SUCCESS Save the processor's state info successfully + +**/ +SAL_RETURN_REGS +EFIAPI +EsalMcaRegisterCpu ( + IN UINT64 CpuGlobalId, + IN EFI_PHYSICAL_ADDRESS StateBufferPointer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtractGuidedSectionLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtractGuidedSectionLib.h new file mode 100644 index 0000000..d26e7ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ExtractGuidedSectionLib.h @@ -0,0 +1,284 @@ +/** @file + This library provides common functions to process the different guided section data. + + This library provides functions to process GUIDed sections of FFS files. Handlers may + be registered to decode GUIDed sections of FFS files. Services are provided to determine + the set of supported section GUIDs, collection information about a specific GUIDed section, + and decode a specific GUIDed section. + + A library instance that produces this library class may be used to produce a + EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI or a EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL + providing a simple method to extend the number of GUIDed sections types a platform supports. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#ifndef __EXTRACT_GUIDED_SECTION_H__ +#define __EXTRACT_GUIDED_SECTION_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. + +**/ +typedef +RETURN_STATUS +(EFIAPI *EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER)( + IN CONST VOID *InputSection, + OUT UINT32 *OutputBufferSize, + OUT UINT32 *ScratchBufferSize, + OUT UINT16 *SectionAttribute + ); + +/** + Decodes a GUIDed section into a caller allocated output buffer. + + Decodes the GUIDed section specified by InputSection. + If GUID for InputSection does not match the GUID that this handler supports, then RETURN_UNSUPPORTED is returned. + If the data in InputSection can not be decoded, then RETURN_INVALID_PARAMETER is returned. + If the GUID of InputSection does match the GUID that this handler supports, then InputSection + is decoded into the buffer specified by OutputBuffer and the authentication status of this + decode operation is returned in AuthenticationStatus. If the decoded buffer is identical to the + data in InputSection, then OutputBuffer is set to point at the data in InputSection. Otherwise, + the decoded data will be placed in caller allocated buffer specified by OutputBuffer. + + If InputSection is NULL, then ASSERT(). + If OutputBuffer is NULL, then ASSERT(). + If ScratchBuffer is NULL and this decode operation requires a scratch buffer, then ASSERT(). + If AuthenticationStatus is NULL, then ASSERT(). + + + @param[in] InputSection A pointer to a GUIDed section of an FFS formatted file. + @param[out] OutputBuffer A pointer to a buffer that contains the result of a decode operation. + @param[out] ScratchBuffer A caller allocated buffer that may be required by this function + as a scratch buffer to perform the decode operation. + @param[out] AuthenticationStatus + A pointer to the authentication status of the decoded output buffer. + See the definition of authentication status in the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI + section of the PI Specification. EFI_AUTH_STATUS_PLATFORM_OVERRIDE must + never be set by this handler. + + @retval RETURN_SUCCESS The buffer specified by InputSection was decoded. + @retval RETURN_UNSUPPORTED The section specified by InputSection does not match the GUID this handler supports. + @retval RETURN_INVALID_PARAMETER The section specified by InputSection can not be decoded. + +**/ +typedef +RETURN_STATUS +(EFIAPI *EXTRACT_GUIDED_SECTION_DECODE_HANDLER)( + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + IN VOID *ScratchBuffer, OPTIONAL + OUT UINT32 *AuthenticationStatus + ); + +/** + 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 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/FileHandleLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/FileHandleLib.h new file mode 100644 index 0000000..521690b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/FileHandleLib.h @@ -0,0 +1,507 @@ +/** @file + Provides interface to EFI_FILE_HANDLE functionality. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _FILE_HANDLE_LIBRARY_HEADER_ +#define _FILE_HANDLE_LIBRARY_HEADER_ + +#include +#include + +/// The tag for use in identifying UNICODE files. +/// If the file is UNICODE, the first 16 bits of the file will equal this value. +extern CONST UINT16 gUnicodeFileTag; + +/** + This function retrieves information about the file for the handle + specified and stores it in the allocated pool memory. + + This function allocates a buffer to store the file's information. It is the + caller's responsibility to free the buffer. + + @param[in] FileHandle The file handle of the file for which information is + being requested. + + @retval NULL Information could not be retrieved. + @retval !NULL The information about the file. +**/ +EFI_FILE_INFO* +EFIAPI +FileHandleGetInfo ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + This function sets the information about the file for the opened handle + specified. + + @param[in] FileHandle The file handle of the file for which information + is being set. + + @param[in] FileInfo The information to set. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid. + @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileHandleSetInfo ( + IN EFI_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO *FileInfo + ); + +/** + This function reads information from an opened file. + + If FileHandle is not a directory, the function reads the requested number of + bytes from the file at the file's current position and returns them in Buffer. + If the read goes beyond the end of the file, the read length is truncated to the + end of the file. The file's current position is increased by the number of bytes + returned. If FileHandle is a directory, the function reads the directory entry + at the file's current position and returns the entry in Buffer. If the Buffer + is not large enough to hold the current directory entry, then + EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. + BufferSize is set to be the size of the buffer needed to read the entry. On + success, the current position is updated to the next directory entry. If there + are no more directory entries, the read returns a zero-length buffer. + EFI_FILE_INFO is the structure returned as the directory entry. + + @param[in] FileHandle The opened file handle. + @param[in, out] BufferSize On input, the size of buffer in bytes. On return, + the number of bytes written. + @param[out] Buffer The buffer to put read data into. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required + size. + +**/ +EFI_STATUS +EFIAPI +FileHandleRead( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Write data to a file. + + This function writes the specified number of bytes to the file at the current + file position. The current file position is advanced the actual number of bytes + written, which is returned in BufferSize. Partial writes only occur when there + has been a data error during the write attempt (such as "volume space full"). + The file is automatically grown to hold the data if required. Direct writes to + opened directories are not supported. + + @param[in] FileHandle The opened file for writing. + @param[in, out] BufferSize On input, the number of bytes in Buffer. On output, + the number of bytes written. + @param[in] Buffer The buffer containing data to write is stored. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to an open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write-protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileHandleWrite( + IN EFI_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Close an open file handle. + + This function closes a specified file handle. All "dirty" cached file data is + flushed to the device, and the file is closed. In all cases the handle is + closed. + + @param[in] FileHandle The file handle to close. + + @retval EFI_SUCCESS The file handle was closed successfully. +**/ +EFI_STATUS +EFIAPI +FileHandleClose ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + Delete a file and close the handle. + + This function closes and deletes a file. In all cases the file handle is closed. + If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is + returned, but the handle is still closed. + + @param[in] FileHandle The file handle to delete. + + @retval EFI_SUCCESS The file was closed successfully. + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not + deleted. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +FileHandleDelete ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + Set the current position in a file. + + This function sets the current file position for the handle to the position + supplied. With the exception of moving to position 0xFFFFFFFFFFFFFFFF, only + absolute positioning is supported, and moving past the end of the file is + allowed (a subsequent write would grow the file). Moving to position + 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file. + If FileHandle is a directory, the only position that may be set is zero. This + has the effect of starting the read process of the directory entries over again. + + @param[in] FileHandle The file handle on which the position is being set. + @param[in] Position The byte position from the beginning of the file. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED The request for non-zero is not valid on + directories. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +FileHandleSetPosition ( + IN EFI_FILE_HANDLE FileHandle, + IN UINT64 Position + ); + +/** + Gets a file's current position. + + This function retrieves the current file position for the file handle. For + directories, the current file position has no meaning outside of the file + system driver. As such, the operation is not supported. An error is returned + if FileHandle is a directory. + + @param[in] FileHandle The open file handle on which to get the position. + @param[out] Position The byte position from 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 + ); +/** + Flushes data on a file. + + This function flushes all modified data associated with a file to a device. + + @param[in] FileHandle The file handle on which to flush data. + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. +**/ +EFI_STATUS +EFIAPI +FileHandleFlush ( + IN EFI_FILE_HANDLE FileHandle + ); + +/** + Function to determine if a given handle is a directory handle. + + 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 + ); + +/** Retrieve first entry from a directory. + + This function takes an open directory handle and gets information from the + first entry in the directory. A buffer is allocated to contain + the information and a pointer to the buffer is returned in *Buffer. The + caller can use FileHandleFindNextFile() to get subsequent directory entries. + + The buffer will be freed by FileHandleFindNextFile() when the last directory + entry is read. Otherwise, the caller must free the buffer, using FreePool, + when finished with it. + + @param[in] DirHandle The file handle of the directory to search. + @param[out] Buffer The pointer to pointer to buffer for file's information. + + @retval EFI_SUCCESS Found the first file. + @retval EFI_NOT_FOUND Cannot find the directory. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @return Others The status of FileHandleGetInfo, FileHandleSetPosition, + or FileHandleRead. +**/ +EFI_STATUS +EFIAPI +FileHandleFindFirstFile ( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ); + +/** Retrieve next entries from a directory. + + To use this function, the caller must first call the FileHandleFindFirstFile() + function to get the first directory entry. Subsequent directory entries are + retrieved by using the FileHandleFindNextFile() function. This function can + be called several times to get each entry from the directory. If the call of + FileHandleFindNextFile() retrieved the last directory entry, the next call of + this function will set *NoFile to TRUE and free the buffer. + + @param[in] DirHandle The file handle of the directory. + @param[out] Buffer The pointer to buffer for file's information. + @param[out] NoFile The pointer to boolean when last file is found. + + @retval EFI_SUCCESS Found the next file, or reached last file. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. +**/ +EFI_STATUS +EFIAPI +FileHandleFindNextFile( + IN EFI_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *NoFile + ); + +/** + Retrieve the size of a file. + + 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 + ); + +/** + 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 + ); + +/** + 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. + + @param[in] Handle Handle to the Directory or File to create path to. + @param[out] FullFileName Pointer to pointer to generated full file name. It + is the responsibility of the caller to free this memory + with a call to FreePool(). + @retval EFI_SUCCESS The operation was successful and FullFileName is valid. + @retval EFI_INVALID_PARAMETER Handle was NULL. + @retval EFI_INVALID_PARAMETER FullFileName was NULL. + @retval EFI_OUT_OF_MEMORY A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileHandleGetFileName ( + IN CONST EFI_FILE_HANDLE Handle, + OUT CHAR16 **FullFileName + ); + +/** + Function to read a single line (up to but not including the \n) from a file. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + 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 + ); + +/** + Function to read a single line from a file. The \n is not included in the returned + buffer. The returned buffer must be callee freed. + + If the position upon start is 0, then the Ascii Boolean will be set. This should be + maintained and not changed for all operations with the same file. + + @param[in] Handle FileHandle to read from. + @param[in, out] Ascii Boolean value for indicating whether the file is + Ascii (TRUE) or UCS2 (FALSE). + + @return The line of text from the file. + + @sa FileHandleReadLine +**/ +CHAR16* +EFIAPI +FileHandleReturnLine( + IN EFI_FILE_HANDLE Handle, + IN OUT BOOLEAN *Ascii + ); + +/** + Function to write a line of 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 + ); + +/** + Function to take a formatted argument and print it to a file. + + @param[in] Handle The file handle for the file to write to. + @param[in] Format The format argument (see printlib for the format specifier). + @param[in] ... The variable arguments for the format. + + @retval EFI_SUCCESS The operation was successful. + @retval other A return value from FileHandleWriteLine. + + @sa FileHandleWriteLine +**/ +EFI_STATUS +EFIAPI +FileHandlePrintLine( + IN EFI_FILE_HANDLE Handle, + IN CONST CHAR16 *Format, + ... + ); + +/** + Function to determine if a FILE_HANDLE is at the end of the file. + + This will NOT work on directories. + + If Handle is NULL, then ASSERT(). + + @param[in] Handle The file handle. + + @retval TRUE The position is at the end of the file. + @retval FALSE The position is not at the end of the file. +**/ +BOOLEAN +EFIAPI +FileHandleEof( + IN EFI_FILE_HANDLE Handle + ); + +#endif //_FILE_HANDLE_LIBRARY_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HobLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HobLib.h new file mode 100644 index 0000000..0d9fc0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HobLib.h @@ -0,0 +1,566 @@ +/** @file + Provides services to create and parse HOBs. Only available for PEI + and DXE module types. + + The HOB Library supports the efficient creation and searching of HOBs + defined in the PI Specification. + A HOB is a Hand-Off Block, defined in the Framework architecture, that + allows the PEI phase to pass information to the DXE phase. HOBs are position + independent and can be relocated easily to different memory locations. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HOB_LIB_H__ +#define __HOB_LIB_H__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 info 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 + ); + +/** + 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 info 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Returns the type of a HOB. + + This macro returns the HobType field from the HOB header for the + HOB specified by HobStart. + + @param HobStart A pointer to a HOB. + + @return HobType. + +**/ +#define GET_HOB_TYPE(HobStart) \ + ((*(EFI_HOB_GENERIC_HEADER **)&(HobStart))->HobType) + +/** + Returns the length, in bytes, of a HOB. + + This macro returns the HobLength field from the HOB header for the + HOB specified by HobStart. + + @param HobStart A pointer to a HOB. + + @return HobLength. + +**/ +#define GET_HOB_LENGTH(HobStart) \ + ((*(EFI_HOB_GENERIC_HEADER **)&(HobStart))->HobLength) + +/** + Returns a pointer to the next HOB in the HOB list. + + This macro returns a pointer to HOB that follows the + HOB specified by HobStart in the HOB List. + + @param HobStart A pointer to a HOB. + + @return A pointer to the next HOB in the HOB list. + +**/ +#define GET_NEXT_HOB(HobStart) \ + (VOID *)(*(UINT8 **)&(HobStart) + GET_HOB_LENGTH (HobStart)) + +/** + Determines if a HOB is the last HOB in the HOB list. + + This macro determine if the HOB specified by HobStart is the + last HOB in the HOB list. If HobStart is last HOB in the HOB list, + then TRUE is returned. Otherwise, FALSE is returned. + + @param HobStart A pointer to a HOB. + + @retval TRUE The HOB specified by HobStart is the last HOB in the HOB list. + @retval FALSE The HOB specified by HobStart is not the last HOB in the HOB list. + +**/ +#define END_OF_HOB_LIST(HobStart) (GET_HOB_TYPE (HobStart) == (UINT16)EFI_HOB_TYPE_END_OF_HOB_LIST) + +/** + Returns a pointer to data buffer from a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + This macro returns a pointer to the data buffer in a HOB specified by HobStart. + HobStart is assumed to be a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + @param GuidHob A pointer to a HOB. + + @return A pointer to the data buffer in a HOB. + +**/ +#define GET_GUID_HOB_DATA(HobStart) \ + (VOID *)(*(UINT8 **)&(HobStart) + sizeof (EFI_HOB_GUID_TYPE)) + +/** + Returns the size of the data buffer from a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + This macro returns the size, in bytes, of the data buffer in a HOB specified by HobStart. + HobStart is assumed to be a HOB of type EFI_HOB_TYPE_GUID_EXTENSION. + + @param GuidHob A pointer to a HOB. + + @return The size of the data buffer. +**/ +#define GET_GUID_HOB_DATA_SIZE(HobStart) \ + (UINT16)(GET_HOB_LENGTH (HobStart) - sizeof (EFI_HOB_GUID_TYPE)) + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HstiLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HstiLib.h new file mode 100644 index 0000000..2ae87f6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/HstiLib.h @@ -0,0 +1,158 @@ +/** @file + Provides services to create, get and update HSTI table in AIP protocol. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HSTI_LIB_H__ +#define __HSTI_LIB_H__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/IoLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/IoLib.h new file mode 100644 index 0000000..b42e243 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/IoLib.h @@ -0,0 +1,2815 @@ +/** @file + Provide services to access I/O Ports and MMIO registers. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __IO_LIB_H__ +#define __IO_LIB_H__ + +/** + Macro that converts PCI Segment and I/O Port to an address that can be + passed to the I/O Library functions. + + Computes an address that is compatible with the I/O Library functions. + The unused upper bits of Segment, and Port are stripped prior to the + generation of the address. + + @param Segment PCI Segment number. Range 0..65535. + @param Port I/O Port number. Range 0..65535. + + @return An address that the I/o Library functions need. + +**/ + +#define IO_LIB_ADDRESS(Segment,Port) \ + ( ((Port) & 0xffff) | (((Segment) & 0xffff) << 16) ) + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 Starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT8 * +EFIAPI +MmioReadBuffer8 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT8 *Buffer + ); + +/** + 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 Starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT16 * +EFIAPI +MmioReadBuffer16 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT16 *Buffer + ); + +/** + 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 Starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT32 * +EFIAPI +MmioReadBuffer32 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT32 *Buffer + ); + +/** + 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 Starting address for the MMIO region to be copied from. + @param Length The size, in bytes, of Buffer. + @param Buffer Pointer to a system memory buffer receiving the data read. + + @return Buffer + +**/ +UINT64 * +EFIAPI +MmioReadBuffer64 ( + IN UINTN StartAddress, + IN UINTN Length, + OUT UINT64 *Buffer + ); + +/** + 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 Starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer 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 + ); + +/** + 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 Starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer 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 + ); + +/** + 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 Starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer 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 + ); + +/** + 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 Starting address for the MMIO region to be copied to. + @param Length The size, in bytes, of Buffer. + @param Buffer 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 + ); + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MemoryAllocationLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MemoryAllocationLib.h new file mode 100644 index 0000000..acdf54b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MemoryAllocationLib.h @@ -0,0 +1,493 @@ +/** @file + Provides services to allocate and free memory buffers of various memory types and alignments. + + The Memory Allocation Library abstracts various common memory allocation operations. This library + allows code to be written in a phase-independent manner because the allocation of memory in PEI, DXE, + and SMM (for example) is done via a different mechanism. Using a common library interface makes it + much easier to port algorithms from phase to phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MEMORY_ALLOCATION_LIB_H__ +#define __MEMORY_ALLOCATION_LIB_H__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MmServicesTableLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MmServicesTableLib.h new file mode 100644 index 0000000..ba34030 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/MmServicesTableLib.h @@ -0,0 +1,25 @@ +/** @file + Provides a service to retrieve a pointer to the Standalone MM Services Table. + Only available to MM_STANDALONE, SMM/DXE Combined and SMM module types. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MM_SERVICES_TABLE_LIB_H__ +#define __MM_SERVICES_TABLE_LIB_H__ + +#include + +extern EFI_MM_SYSTEM_TABLE *gMmst; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/OrderedCollectionLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/OrderedCollectionLib.h new file mode 100644 index 0000000..e4191b8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/OrderedCollectionLib.h @@ -0,0 +1,425 @@ +/** @file + An ordered collection library interface. + + The library class provides a set of APIs to manage an ordered collection of + items. + + Copyright (C) 2014, Red Hat, Inc. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License that accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __ORDERED_COLLECTION_LIB__ +#define __ORDERED_COLLECTION_LIB__ + +#include + +// +// Opaque structure for a collection. +// +typedef struct ORDERED_COLLECTION ORDERED_COLLECTION; + +// +// Opaque structure for collection entries. +// +// Collection entries do not take ownership of the associated user structures, +// they only link them. This makes it easy to link the same user structure into +// several collections. If reference counting is required, the caller is +// responsible for implementing it, as part of the user structure. +// +// A pointer-to-ORDERED_COLLECTION_ENTRY is considered an "iterator". Multiple, +// simultaneous iterations are supported. +// +typedef struct ORDERED_COLLECTION_ENTRY ORDERED_COLLECTION_ENTRY; + +// +// Altering the key field of an in-collection user structure (ie. the portion +// of the user structure that ORDERED_COLLECTION_USER_COMPARE and +// ORDERED_COLLECTION_KEY_COMPARE, below, read) is not allowed in-place. The +// caller is responsible for bracketing the key change with the deletion and +// the reinsertion of the user structure, so that the changed key value is +// reflected in the collection. +// + +/** + Comparator function type for two user structures. + + @param[in] UserStruct1 Pointer to the first user structure. + + @param[in] UserStruct2 Pointer to the second user structure. + + @retval <0 If UserStruct1 compares less than UserStruct2. + + @retval 0 If UserStruct1 compares equal to UserStruct2. + + @retval >0 If UserStruct1 compares greater than UserStruct2. +**/ +typedef +INTN +(EFIAPI *ORDERED_COLLECTION_USER_COMPARE)( + IN CONST VOID *UserStruct1, + IN CONST VOID *UserStruct2 + ); + +/** + Compare a standalone key against a user structure containing an embedded key. + + @param[in] StandaloneKey Pointer to the bare key. + + @param[in] UserStruct Pointer to the user structure with the embedded + key. + + @retval <0 If StandaloneKey compares less than UserStruct's key. + + @retval 0 If StandaloneKey compares equal to UserStruct's key. + + @retval >0 If StandaloneKey compares greater than UserStruct's key. +**/ +typedef +INTN +(EFIAPI *ORDERED_COLLECTION_KEY_COMPARE)( + IN CONST VOID *StandaloneKey, + IN CONST VOID *UserStruct + ); + + +// +// Some functions below are read-only, while others are read-write. If any +// write operation is expected to run concurrently with any other operation on +// the same collection, then the caller is responsible for implementing locking +// for the whole collection. +// + +/** + Retrieve the user structure linked by the specified collection entry. + + Read-only operation. + + @param[in] Entry Pointer to the collection entry 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 Entry. +**/ +VOID * +EFIAPI +OrderedCollectionUserStruct ( + IN CONST ORDERED_COLLECTION_ENTRY *Entry + ); + + +/** + Allocate and initialize the ORDERED_COLLECTION structure. + + @param[in] UserStructCompare This caller-provided function will be used to + order two user structures linked into the + collection, 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 collection, during + the lookup procedure. + + @retval NULL If allocation failed. + + @return Pointer to the allocated, initialized ORDERED_COLLECTION + structure, otherwise. +**/ +ORDERED_COLLECTION * +EFIAPI +OrderedCollectionInit ( + IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare, + IN ORDERED_COLLECTION_KEY_COMPARE KeyCompare + ); + + +/** + Check whether the collection is empty (has no entries). + + Read-only operation. + + @param[in] Collection The collection to check for emptiness. + + @retval TRUE The collection is empty. + + @retval FALSE The collection is not empty. +**/ +BOOLEAN +EFIAPI +OrderedCollectionIsEmpty ( + IN CONST ORDERED_COLLECTION *Collection + ); + + +/** + Uninitialize and release an empty ORDERED_COLLECTION structure. + + Read-write operation. + + It is the caller's responsibility to delete all entries from the collection + before calling this function. + + @param[in] Collection The empty collection to uninitialize and release. +**/ +VOID +EFIAPI +OrderedCollectionUninit ( + IN ORDERED_COLLECTION *Collection + ); + + +/** + Look up the collection entry that links the user structure that matches the + specified standalone key. + + Read-only operation. + + @param[in] Collection The collection to search for StandaloneKey. + + @param[in] StandaloneKey The key to locate among the user structures linked + into Collection. StandaloneKey will be passed to + ORDERED_COLLECTION_KEY_COMPARE. + + @retval NULL StandaloneKey could not be found. + + @return The collection entry that links to the user structure matching + StandaloneKey, otherwise. +**/ +ORDERED_COLLECTION_ENTRY * +EFIAPI +OrderedCollectionFind ( + IN CONST ORDERED_COLLECTION *Collection, + IN CONST VOID *StandaloneKey + ); + + +/** + Find the collection entry of the minimum user structure stored in the + collection. + + Read-only operation. + + @param[in] Collection The collection to return the minimum entry of. The + user structure linked by the minimum entry compares + less than all other user structures in the collection. + + @retval NULL If Collection is empty. + + @return The collection entry that links the minimum user structure, + otherwise. +**/ +ORDERED_COLLECTION_ENTRY * +EFIAPI +OrderedCollectionMin ( + IN CONST ORDERED_COLLECTION *Collection + ); + + +/** + Find the collection entry of the maximum user structure stored in the + collection. + + Read-only operation. + + @param[in] Collection The collection to return the maximum entry of. The + user structure linked by the maximum entry compares + greater than all other user structures in the + collection. + + @retval NULL If Collection is empty. + + @return The collection entry that links the maximum user structure, + otherwise. +**/ +ORDERED_COLLECTION_ENTRY * +EFIAPI +OrderedCollectionMax ( + IN CONST ORDERED_COLLECTION *Collection + ); + + +/** + Get the collection entry of the least user structure that is greater than the + one linked by Entry. + + Read-only operation. + + @param[in] Entry The entry to get the successor entry of. + + @retval NULL If Entry is NULL, or Entry is the maximum entry of its + containing collection (ie. Entry has no successor entry). + + @return The collection entry linking the least user structure that is + greater than the one linked by Entry, otherwise. +**/ +ORDERED_COLLECTION_ENTRY * +EFIAPI +OrderedCollectionNext ( + IN CONST ORDERED_COLLECTION_ENTRY *Entry + ); + + +/** + Get the collection entry of the greatest user structure that is less than the + one linked by Entry. + + Read-only operation. + + @param[in] Entry The entry to get the predecessor entry of. + + @retval NULL If Entry is NULL, or Entry is the minimum entry of its + containing collection (ie. Entry has no predecessor entry). + + @return The collection entry linking the greatest user structure that + is less than the one linked by Entry, otherwise. +**/ +ORDERED_COLLECTION_ENTRY * +EFIAPI +OrderedCollectionPrev ( + IN CONST ORDERED_COLLECTION_ENTRY *Entry + ); + + +/** + Insert (link) a user structure into the collection, allocating a new + collection entry. + + Read-write operation. + + @param[in,out] Collection The collection to insert UserStruct into. + + @param[out] Entry The meaning of this optional, output-only + parameter depends on the return value of the + function. + + When insertion is successful (RETURN_SUCCESS), + Entry is set on output to the new collection entry + that now links UserStruct. + + When insertion fails due to lack of memory + (RETURN_OUT_OF_RESOURCES), Entry is not changed. + + When insertion fails due to key collision (ie. + another user structure is already in the + collection that compares equal to UserStruct), + with return value RETURN_ALREADY_STARTED, then + Entry is set on output to the entry 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 collection. + UserStruct is ordered against in-collection user + structures with the + ORDERED_COLLECTION_USER_COMPARE function. + + @retval RETURN_SUCCESS Insertion successful. A new collection entry + has been allocated, linking UserStruct. The + new collection entry is reported back in + Entry (if the caller requested it). + + Existing ORDERED_COLLECTION_ENTRY pointers + into Collection remain valid. For example, + on-going iterations in the caller can + continue with OrderedCollectionNext() / + OrderedCollectionPrev(), and they will + return the new entry at some point if user + structure order dictates it. + + @retval RETURN_OUT_OF_RESOURCES The function failed to allocate memory for + the new collection entry. The collection has + not been changed. Existing + ORDERED_COLLECTION_ENTRY pointers into + Collection remain valid. + + @retval RETURN_ALREADY_STARTED A user structure has been found in the + collection that compares equal to + UserStruct. The entry linking the colliding + user structure is reported back in Entry (if + the caller requested it). The collection has + not been changed. Existing + ORDERED_COLLECTION_ENTRY pointers into + Collection remain valid. +**/ +RETURN_STATUS +EFIAPI +OrderedCollectionInsert ( + IN OUT ORDERED_COLLECTION *Collection, + OUT ORDERED_COLLECTION_ENTRY **Entry OPTIONAL, + IN VOID *UserStruct + ); + + +/** + Delete an entry from the collection, unlinking the associated user structure. + + Read-write operation. + + @param[in,out] Collection The collection to delete Entry from. + + @param[in] Entry The collection entry to delete from Collection. + The caller is responsible for ensuring that Entry + belongs to Collection, and that Entry is non-NULL + and valid. Entry is typically an earlier return + value, or output parameter, of: + + - OrderedCollectionFind(), for deleting an entry + by user structure key, + + - OrderedCollectionMin() / OrderedCollectionMax(), + for deleting the minimum / maximum entry, + + - OrderedCollectionNext() / + OrderedCollectionPrev(), for deleting an entry + found during an iteration, + + - OrderedCollectionInsert() with return value + RETURN_ALREADY_STARTED, for deleting an entry + whose linked user structure caused collision + during insertion. + + Existing ORDERED_COLLECTION_ENTRY pointers (ie. + iterators) *different* from Entry remain valid. + For example: + + - OrderedCollectionNext() / + OrderedCollectionPrev() iterations in the caller + can be continued from Entry, if + OrderedCollectionNext() or + OrderedCollectionPrev() is called on Entry + *before* OrderedCollectionDelete() is. That is, + fetch the successor / predecessor entry first, + then delete Entry. + + - On-going iterations in the caller that would + have otherwise returned Entry at some point, as + dictated by user structure order, will correctly + reflect the absence of Entry 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 Entry (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 ORDERED_COLLECTION *Collection, + IN ORDERED_COLLECTION_ENTRY *Entry, + OUT VOID **UserStruct OPTIONAL + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PalLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PalLib.h new file mode 100644 index 0000000..57f5195 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PalLib.h @@ -0,0 +1,63 @@ +/** @file + Provides library services to make PAL Calls. + + The PAL Library provides a service to make a PAL CALL. This service is identical + in functionality to AsmPalCall() in the functions of the Base Library specific to Intel Itanium architecture. + The only difference is that the PAL Entry Point is not passed in. Implementations + of this library class must manage PAL Entry Point on their own. For example, a PEI + implementation can use a PPI to lookup the PAL Entry Point, and a DXE implementation + can contain a constructor to look up the PAL Entry Point from a HOB. This library class + is only available on Intel Itanium-based platforms. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PAL_CALL_LIB_H__ +#define __PAL_CALL_LIB_H__ + +#include + +/** + Makes a PAL procedure call. + + This is a wrapper function to make a PAL procedure call. Based on the Index value, + this API will make static or stacked PAL call. Architected procedures may be designated + as required or optional. If a PAL procedure is specified as optional, a unique return + code of 0xFFFFFFFFFFFFFFFF is returned in the Status field of the PAL_CALL_RETURN structure. + This indicates that the procedure is not present in this PAL implementation. It is the + caller's responsibility to check for this return code after calling any optional PAL + procedure. No parameter checking is performed on the 4 input parameters, but there are + some common rules that the caller should follow when making a PAL call. Any address + passed to PAL as buffers for return parameters must be 8-byte aligned. Unaligned addresses + may cause undefined results. For those parameters defined as reserved or some fields + defined as reserved must be zero filled or the invalid argument return value may be + returned or undefined result may occur during the execution of the procedure. + This function is only available on Intel Itanium-based platforms. + + @param Index The PAL procedure Index number. + @param Arg2 The 2nd parameter for PAL procedure calls. + @param Arg3 The 3rd parameter for PAL procedure calls. + @param Arg4 The 4th parameter for PAL procedure calls. + + @return Structure returned from the PAL Call procedure, including the status and return value. + +**/ +PAL_CALL_RETURN +EFIAPI +PalCall ( + IN UINT64 Index, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PcdLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PcdLib.h new file mode 100644 index 0000000..9ea2217 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PcdLib.h @@ -0,0 +1,2260 @@ +/** @file + Provides library services to get and set Platform Configuration Database entries. + + PCD Library Class provides a PCD usage macro interface for all PCD types. + It should be included in any module that uses PCD. If a module uses dynamic/dynamicex + PCD, module should be linked to a PEIM/DXE library instance to access that PCD. + If a module uses PatchableInModule type PCD, it also needs the library instance to produce + LibPatchPcdSetPtr() interface. For FeatureFlag/Fixed PCD, the macro interface is + translated to a variable or macro that is auto-generated by build tool in + module's autogen.h/autogen.c. + The PcdGetXX(), PcdSetXX(), PcdToken(), and PcdGetNextTokenSpace() operations are + only available prior to ExitBootServices(). If access to PCD values are required + at runtime, then their values must be collected prior to ExitBootServices(). + There are no restrictions on the use of FeaturePcd(), FixedPcdGetXX(), + PatchPcdGetXX(), and PatchPcdSetXX(). + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCD_LIB_H__ +#define __PCD_LIB_H__ + + +/** + Retrieves a token number based on a token name. + + Returns the token number associated with the PCD token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve the token number for. + + @return The token number associated with the PCD. + +**/ +#define PcdToken(TokenName) _PCD_TOKEN_##TokenName + + +/** + Retrieves a Boolean PCD feature flag based on a token name. + + Returns the Boolean value for the PCD feature flag specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a feature flag PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return Boolean value for the PCD feature flag. + +**/ +#define FeaturePcdGet(TokenName) _PCD_GET_MODE_BOOL_##TokenName + + +/** + Retrieves an 8-bit fixed PCD token value based on a token name. + + Returns the 8-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a fixed at build PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 8-bit value for the token specified by TokenName. + +**/ +#define FixedPcdGet8(TokenName) _PCD_VALUE_##TokenName + + +/** + Retrieves a 16-bit fixed PCD token value based on a token name. + + Returns the 16-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a fixed at build PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 16-bit value for the token specified by TokenName. + +**/ +#define FixedPcdGet16(TokenName) _PCD_VALUE_##TokenName + + +/** + Retrieves a 32-bit fixed PCD token value based on a token name. + + Returns the 32-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a fixed at build PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 32-bit value for the token specified by TokenName. + +**/ +#define FixedPcdGet32(TokenName) _PCD_VALUE_##TokenName + + +/** + Retrieves a 64-bit fixed PCD token value based on a token name. + + Returns the 64-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a fixed at build PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 64-bit value for the token specified by TokenName. + +**/ +#define FixedPcdGet64(TokenName) _PCD_VALUE_##TokenName + + +/** + Retrieves a Boolean fixed PCD token value based on a token name. + + Returns the Boolean value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a fixed at build PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return The Boolean value for the token. + +**/ +#define FixedPcdGetBool(TokenName) _PCD_VALUE_##TokenName + + +/** + Retrieves a pointer to a fixed PCD token buffer based on a token name. + + Returns a pointer to the buffer for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a fixed at build PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A pointer to the buffer. + +**/ +#define FixedPcdGetPtr(TokenName) ((VOID *)_PCD_VALUE_##TokenName) + + +/** + Retrieves an 8-bit binary patchable PCD token value based on a token name. + + Returns the 8-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return An 8-bit binary patchable PCD token value. + +**/ +#define PatchPcdGet8(TokenName) _gPcd_BinaryPatch_##TokenName + +/** + Retrieves a 16-bit binary patchable PCD token value based on a token name. + + Returns the 16-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A 16-bit binary patchable PCD token value. + +**/ +#define PatchPcdGet16(TokenName) _gPcd_BinaryPatch_##TokenName + + +/** + Retrieves a 32-bit binary patchable PCD token value based on a token name. + + Returns the 32-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A 32-bit binary patchable PCD token value. + +**/ +#define PatchPcdGet32(TokenName) _gPcd_BinaryPatch_##TokenName + + +/** + Retrieves a 64-bit binary patchable PCD token value based on a token name. + + Returns the 64-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A 64-bit binary patchable PCD token value. + +**/ +#define PatchPcdGet64(TokenName) _gPcd_BinaryPatch_##TokenName + + +/** + Retrieves a Boolean binary patchable PCD token value based on a token name. + + Returns the Boolean value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return The Boolean value for the token. + +**/ +#define PatchPcdGetBool(TokenName) _gPcd_BinaryPatch_##TokenName + + +/** + Retrieves a pointer to a binary patchable PCD token buffer based on a token name. + + Returns a pointer to the buffer for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A pointer to the buffer for the token. + +**/ +#define PatchPcdGetPtr(TokenName) ((VOID *)_gPcd_BinaryPatch_##TokenName) + + +/** + Sets an 8-bit binary patchable PCD token value based on a token name. + + Sets the 8-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the binary patchable PCD token to set the current value for. + @param Value The 8-bit value to set. + + @return Return the Value that was set. + +**/ +#define PatchPcdSet8(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value)) + + +/** + Sets a 16-bit binary patchable PCD token value based on a token name. + + Sets the 16-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the binary patchable PCD token to set the current value for. + @param Value The 16-bit value to set. + + @return Return the Value that was set. + +**/ +#define PatchPcdSet16(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value)) + + +/** + Sets a 32-bit binary patchable PCD token value based on a token name. + + Sets the 32-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the binary patchable PCD token to set the current value for. + @param Value The 32-bit value to set. + + @return Return the Value that was set. + +**/ +#define PatchPcdSet32(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value)) + + +/** + Sets a 64-bit binary patchable PCD token value based on a token name. + + Sets the 64-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the binary patchable PCD token to set the current value for. + @param Value The 64-bit value to set. + + @return Return the Value that was set. + +**/ +#define PatchPcdSet64(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value)) + + +/** + Sets a Boolean binary patchable PCD token value based on a token name. + + Sets the Boolean value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + @param TokenName The name of the binary patchable PCD token to set the current value for. + @param Value The boolean value to set. + + @return Return the Value that was set. + +**/ +#define PatchPcdSetBool(TokenName, Value) (_gPcd_BinaryPatch_##TokenName = (Value)) + + +/** + Sets a pointer to a binary patchable PCD token buffer based on a token name. + + Sets the buffer for the token specified by TokenName. Buffer is returned. + If SizeOfBuffer is greater than the maximum size supported by TokenName, then set SizeOfBuffer + to the maximum size supported by TokenName 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 TokenName is not a valid token in the token space, then the module will not build. + If TokenName is not a patchable in module PCD, then the module will not build. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param TokenName The name of the binary patchable PCD token to set the current value for. + @param SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param Buffer Pointer to the value to set. + + @return Return the pointer to the Buffer that was set. + +**/ +#define PatchPcdSetPtr(TokenName, Size, Buffer) \ + LibPatchPcdSetPtrAndSize ( \ + (VOID *)_gPcd_BinaryPatch_##TokenName, \ + &_gPcd_BinaryPatch_Size_##TokenName, \ + (UINTN)_PCD_PATCHABLE_##TokenName##_SIZE, \ + (Size), \ + (Buffer) \ + ) +/** + Retrieves an 8-bit PCD token value based on a token name. + + Returns the 8-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 8-bit value for the token specified by TokenName. + +**/ +#define PcdGet8(TokenName) _PCD_GET_MODE_8_##TokenName + + +/** + Retrieves a 16-bit PCD token value based on a token name. + + Returns the 16-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 16-bit value for the token specified by TokenName. + +**/ +#define PcdGet16(TokenName) _PCD_GET_MODE_16_##TokenName + + +/** + Retrieves a 32-bit PCD token value based on a token name. + + Returns the 32-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 32-bit value for the token specified by TokenName. + +**/ +#define PcdGet32(TokenName) _PCD_GET_MODE_32_##TokenName + + +/** + Retrieves a 64-bit PCD token value based on a token name. + + Returns the 64-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return 64-bit value for the token specified by TokenName. + +**/ +#define PcdGet64(TokenName) _PCD_GET_MODE_64_##TokenName + + +/** + Retrieves a pointer to a PCD token buffer based on a token name. + + Returns a pointer to the buffer for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A pointer to the buffer. + +**/ +#define PcdGetPtr(TokenName) _PCD_GET_MODE_PTR_##TokenName + + +/** + Retrieves a Boolean PCD token value based on a token name. + + Returns the Boolean value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A Boolean PCD token value. + +**/ +#define PcdGetBool(TokenName) _PCD_GET_MODE_BOOL_##TokenName + + +/** + Retrieves the size of a fixed PCD token based on a token name. + + Returns the size of the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param[in] TokenName The name of the PCD token to retrieve a current value size for. + + @return Return the size + +**/ +#define FixedPcdGetSize(TokenName) _PCD_SIZE_##TokenName + + +/** + Retrieves the size of a binary patchable PCD token based on a token name. + + Returns the size of the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param[in] TokenName The name of the PCD token to retrieve a current value size for. + + @return Return the size + +**/ +#define PatchPcdGetSize(TokenName) _gPcd_BinaryPatch_Size_##TokenName + + +/** + Retrieves the size of the PCD token based on a token name. + + Returns the size of the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param[in] TokenName The name of the PCD token to retrieve a current value size for. + + @return Return the size + +**/ +#define PcdGetSize(TokenName) _PCD_GET_MODE_SIZE_##TokenName + + +/** + 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 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 size for. + + @return Return the size. + +**/ +#define PcdGetExSize(Guid, TokenName) LibPcdGetExSize ((Guid), PcdTokenEx(Guid,TokenName)) + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES +/** + Sets an 8-bit PCD token value based on a token name. + + Sets the 8-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 8-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSet8(TokenName, Value) _PCD_SET_MODE_8_##TokenName ((Value)) + + +/** + Sets a 16-bit PCD token value based on a token name. + + Sets the 16-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 16-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSet16(TokenName, Value) _PCD_SET_MODE_16_##TokenName ((Value)) + + +/** + Sets a 32-bit PCD token value based on a token name. + + Sets the 32-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 32-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSet32(TokenName, Value) _PCD_SET_MODE_32_##TokenName ((Value)) + + +/** + Sets a 64-bit PCD token value based on a token name. + + Sets the 64-bit value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 64-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSet64(TokenName, Value) _PCD_SET_MODE_64_##TokenName ((Value)) + + +/** + Sets a pointer to a PCD token buffer based on a token name. + + Sets the buffer for the token specified by TokenName. Buffer is returned. + If SizeOfBuffer is greater than the maximum size supported by TokenName, + then set SizeOfBuffer to the maximum size supported by TokenName 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 TokenName is not a valid token in the token space, then the module will not build. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param TokenName The name of the PCD token to set the current value for. + @param SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param Buffer A pointer to the buffer to set. + + @return Return the pointer to the Buffer that was set. + +**/ +#define PcdSetPtr(TokenName, SizeOfBuffer, Buffer) \ + _PCD_SET_MODE_PTR_##TokenName ((SizeOfBuffer), (Buffer)) + +/** + Sets a Boolean PCD token value based on a token name. + + Sets the Boolean value for the token specified by TokenName. Value is returned. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to set the current value for. + @param Buffer The Boolean value to set. + + @return Return the Value that was set. + +**/ +#define PcdSetBool(TokenName, Value) _PCD_SET_MODE_BOOL_##TokenName ((Value)) +#endif + +/** + Sets a 8-bit PCD token value based on a token name. + + Sets the 8-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSet8S(TokenName, Value) _PCD_SET_MODE_8_S_##TokenName ((Value)) + +/** + Sets a 16-bit PCD token value based on a token name. + + Sets the 16-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSet16S(TokenName, Value) _PCD_SET_MODE_16_S_##TokenName ((Value)) + +/** + Sets a 32-bit PCD token value based on a token name. + + Sets the 32-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSet32S(TokenName, Value) _PCD_SET_MODE_32_S_##TokenName ((Value)) + +/** + Sets a 64-bit PCD token value based on a token name. + + Sets the 64-bit value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSet64S(TokenName, Value) _PCD_SET_MODE_64_S_##TokenName ((Value)) + +/** + Sets a pointer to a PCD token buffer based on a token name. + + Sets the buffer for the token specified by TokenName. + If SizeOfBuffer is greater than the maximum size supported by TokenName, + then set SizeOfBuffer to the maximum size supported by TokenName 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 the maximum size + supported by TokenName and RETURN_INVALID_PARAMETER must be returned. + If TokenName is not a valid token in the token space, then the module will not build. + + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param TokenName The name of the PCD token to set the current value for. + @param SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param Buffer A pointer to the buffer to set. + + @return The status of the set operation. + +**/ +#define PcdSetPtrS(TokenName, SizeOfBuffer, Buffer) \ + _PCD_SET_MODE_PTR_S_##TokenName ((SizeOfBuffer), (Buffer)) + + + +/** + Sets a boolean PCD token value based on a token name. + + Sets the boolean value for the token specified by TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param TokenName The name of the PCD token to retrieve a current value for. + @param Value The boolean value to set. + + @return The status of the set operation. + +**/ +#define PcdSetBoolS(TokenName, Value) _PCD_SET_MODE_BOOL_S_##TokenName ((Value)) + +/** + Retrieves a token number based on a GUID and a token name. + + Returns the token number for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space, then the module will not build. + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return Return the token number. + +**/ +#define PcdTokenEx(Guid,TokenName) _PCD_TOKEN_EX_##TokenName(Guid) + +/** + Retrieves an 8-bit PCD token value based on a GUID and a token name. + + Returns the 8-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return An 8-bit PCD token value. + +**/ +#define PcdGetEx8(Guid, TokenName) LibPcdGetEx8 ((Guid), PcdTokenEx(Guid,TokenName)) + +/** + Retrieves a 16-bit PCD token value based on a GUID and a token name. + + Returns the 16-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A 16-bit PCD token value. + +**/ +#define PcdGetEx16(Guid, TokenName) LibPcdGetEx16 ((Guid), PcdTokenEx(Guid,TokenName)) + + +/** + Retrieves a 32-bit PCD token value based on a GUID and a token name. + + Returns the 32-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A 32-bit PCD token value. + +**/ +#define PcdGetEx32(Guid, TokenName) LibPcdGetEx32 ((Guid), PcdTokenEx(Guid,TokenName)) + + +/** + Retrieves a 64-bit PCD token value based on a GUID and a token name. + + Returns the 64-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A 64-bit PCD token value. + +**/ +#define PcdGetEx64(Guid, TokenName) LibPcdGetEx64 ((Guid), PcdTokenEx(Guid,TokenName)) + + +/** + Retrieves a pointer to a PCD token buffer based on a GUID and a token name. + + Returns a pointer to the buffer for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A pointer to a PCD token buffer. + +**/ +#define PcdGetExPtr(Guid, TokenName) LibPcdGetExPtr ((Guid), PcdTokenEx(Guid,TokenName)) + + +/** + Retrieves a Boolean PCD token value based on a GUID and a token name. + + Returns the Boolean value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to retrieve a current value for. + + @return A Boolean PCD token value. + +**/ +#define PcdGetExBool(Guid, TokenName) LibPcdGetExBool ((Guid), PcdTokenEx(Guid,TokenName)) + + + +#ifndef DISABLE_NEW_DEPRECATED_INTERFACES +/** + Sets an 8-bit PCD token value based on a GUID and a token name. + + Sets the 8-bit value for the token specified by Guid and TokenName. Value is returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 8-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSetEx8(Guid, TokenName, Value) LibPcdSetEx8 ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + + +/** + Sets a 16-bit PCD token value based on a GUID and a token name. + + Sets the 16-bit value for the token specified by Guid and TokenName. Value is returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 16-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSetEx16(Guid, TokenName, Value) LibPcdSetEx16 ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + + +/** + Sets a 32-bit PCD token value based on a GUID and a token name. + + Sets the 32-bit value for the token specified by Guid and TokenName. Value is returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 32-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSetEx32(Guid, TokenName, Value) LibPcdSetEx32 ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + + +/** + Sets a 64-bit PCD token value based on a GUID and a token name. + + Sets the 64-bit value for the token specified by Guid and TokenName. Value is returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 64-bit value to set. + + @return Return the Value that was set. + +**/ +#define PcdSetEx64(Guid, TokenName, Value) LibPcdSetEx64 ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + + +/** + Sets a pointer to a PCD token buffer based on a GUID and a token name. + + Sets the buffer for the token specified by Guid and TokenName. Buffer is returned. + If SizeOfBuffer is greater than the maximum size supported by Guid and TokenName, + then set SizeOfBuffer to the maximum size supported by Guid and TokenName 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 + Guid and TokenName and NULL must be returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param Buffer Pointer to the buffer to set. + + @return Return the pointer to the Buffer that was set. + +**/ +#define PcdSetExPtr(Guid, TokenName, SizeOfBuffer, Buffer) \ + LibPcdSetExPtr ((Guid), PcdTokenEx(Guid,TokenName), (SizeOfBuffer), (Buffer)) + + +/** + Sets a Boolean PCD token value based on a GUID and a token name. + + Sets the Boolean value for the token specified by Guid and TokenName. Value is returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The Boolean value to set. + + @return Return the Value that was set. + +**/ +#define PcdSetExBool(Guid, TokenName, Value) \ + LibPcdSetExBool((Guid), PcdTokenEx(Guid,TokenName), (Value)) +#endif + +/** + Sets an 8-bit PCD token value based on a GUID and a token name. + + Sets the 8-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 8-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSetEx8S(Guid, TokenName, Value) LibPcdSetEx8S ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + +/** + Sets an 16-bit PCD token value based on a GUID and a token name. + + Sets the 16-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 16-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSetEx16S(Guid, TokenName, Value) LibPcdSetEx16S ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + +/** + Sets an 32-bit PCD token value based on a GUID and a token name. + + Sets the 32-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 32-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSetEx32S(Guid, TokenName, Value) LibPcdSetEx32S ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + +/** + Sets an 64-bit PCD token value based on a GUID and a token name. + + Sets the 64-bit value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The 64-bit value to set. + + @return The status of the set operation. + +**/ +#define PcdSetEx64S(Guid, TokenName, Value) LibPcdSetEx64S ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + +/** + Sets a pointer to a PCD token buffer based on a GUID and a token name. + + Sets the buffer for the token specified by Guid and TokenName. + If SizeOfBuffer is greater than the maximum size supported by Guid and TokenName, + then set SizeOfBuffer to the maximum size supported by Guid and TokenName 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 the maximum size + supported by Guid and TokenName and RETURN_INVALID_PARAMETER must be returned. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + If SizeOfBuffer is NULL, then ASSERT(). + If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param SizeOfBuffer A pointer to the size, in bytes, of Buffer. + @param Buffer Pointer to the buffer to set. + + @return The status of the set operation. + +**/ +#define PcdSetExPtrS(Guid, TokenName, SizeOfBuffer, Buffer) \ + LibPcdSetExPtrS ((Guid), PcdTokenEx(Guid,TokenName), (SizeOfBuffer), (Buffer)) + + +/** + Sets an boolean PCD token value based on a GUID and a token name. + + Sets the boolean value for the token specified by Guid and TokenName. + If TokenName is not a valid token in the token space specified by Guid, + then the module will not build. + + If Guid is NULL, then ASSERT(). + + @param Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param TokenName The name of the PCD token to set the current value for. + @param Value The boolean value to set. + + @return The status of the set operation. + +**/ +#define PcdSetExBoolS(Guid, TokenName, Value) \ + LibPcdSetExBoolS ((Guid), PcdTokenEx(Guid,TokenName), (Value)) + +/** + 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 was set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +#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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 that was set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN CONST 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 that was set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN 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 and + Guid to the value specified by Value. Value is returned. + + If Guid 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] 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 + ); +#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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 the + maximum size supported by TokenName and RETURN_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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 RETURN_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 + ); + +/** + 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 + ); + +/** + This notification function serves two purposes. + + Firstly, it notifies the module that did the registration that the value of this + PCD token has been set. + Secondly, it provides a mechanism for the module that did the registration to intercept + the set operation and override the value been set if necessary. After the invocation of + the callback function, TokenData will be used by PCD service PEIM or driver to modify th + internal data in PCD database. + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in, out] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + +**/ +typedef +VOID +(EFIAPI *PCD_CALLBACK)( + IN CONST GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN OUT VOID *TokenData, + IN UINTN TokenDataSize + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + + +/** + 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 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 + ); + + + +/** + 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 Pointer to the a PCD token space GUID + + @return The next valid token namespace. + +**/ +GUID * +EFIAPI +LibPcdGetNextTokenSpace ( + IN CONST 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 that was set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtr ( + OUT VOID *PatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST 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 + ); + +/** + 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 that was set. + +**/ +VOID * +EFIAPI +LibPatchPcdSetPtrAndSize ( + OUT VOID *PatchVariable, + OUT UINTN *SizeOfPatchVariable, + IN UINTN MaximumDatumSize, + IN OUT UINTN *SizeOfBuffer, + IN CONST 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 + ); + +typedef enum { + PCD_TYPE_8, + PCD_TYPE_16, + PCD_TYPE_32, + PCD_TYPE_64, + PCD_TYPE_BOOL, + PCD_TYPE_PTR +} PCD_TYPE; + +typedef struct { + /// + /// The returned information associated with the requested TokenNumber. If + /// TokenNumber is 0, then PcdType is set to PCD_TYPE_8. + /// + PCD_TYPE PcdType; + /// + /// The size of the data in bytes associated with the TokenNumber specified. If + /// TokenNumber is 0, then PcdSize is set 0. + /// + UINTN PcdSize; + /// + /// The null-terminated ASCII string associated with a given token. If the + /// TokenNumber specified was 0, then this field corresponds to the null-terminated + /// ASCII string associated with the token's namespace Guid. If NULL, there is no + /// name associated with this request. + /// + CHAR8 *PcdName; +} PCD_INFO; + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciCf8Lib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciCf8Lib.h new file mode 100644 index 0000000..2c74e7c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciCf8Lib.h @@ -0,0 +1,1094 @@ +/** @file + Provides services to access PCI Configuration Space using the I/O ports 0xCF8 and 0xCFC. + + This library is identical to the PCI Library, except the access method for performing PCI + configuration cycles must be through I/O ports 0xCF8 and 0xCFC. This library only allows + access to PCI Segment #0. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_CF8_LIB_H__ +#define __PCI_CF8_LIB_H__ + + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + Computes an address that is compatible with the PCI Library functions. The + unused upper bits of Bus, Device, Function and Register are stripped prior to + the generation of the address. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255. + + @return The encode PCI address. + +**/ +#define PCI_CF8_LIB_ADDRESS(Bus,Device,Function,Offset) \ + (((Offset) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciCf8BitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 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 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciCf8BitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 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 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciCf8BitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 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 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 read from StartAddress. + +**/ +UINTN +EFIAPI +PciCf8ReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *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 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 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 written to StartAddress. + +**/ +UINTN +EFIAPI +PciCf8WriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciExpressLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciExpressLib.h new file mode 100644 index 0000000..7fa5e76 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciExpressLib.h @@ -0,0 +1,1062 @@ +/** @file + Provides services to access PCI Configuration Space using the MMIO PCI Express window. + + This library is identical to the PCI Library, except the access method for performing PCI + configuration cycles must be through the 256 MB PCI Express MMIO window whose base address + is defined by PcdPciExpressBaseAddress. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_EXPRESS_LIB_H__ +#define __PCI_EXPRESS_LIB_H__ + +#include + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + Computes an address that is compatible with the PCI Library functions. The + unused upper bits of Bus, Device, Function and Register are stripped prior to + the generation of the address. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..4095. + + @return The encode PCI address. + +**/ +#define PCI_EXPRESS_LIB_ADDRESS(Bus,Device,Function,Offset) PCI_ECAM_ADDRESS ((Bus), (Device), (Function), (Offset)) + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 read data from StartAddress. + +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *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 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 written to StartAddress. + +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciLib.h new file mode 100644 index 0000000..0594824 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciLib.h @@ -0,0 +1,1062 @@ +/** @file + Provides services to access PCI Configuration Space. + + These functions perform PCI configuration cycles using the default PCI configuration + access method. This may use I/O ports 0xCF8 and 0xCFC to perform PCI configuration accesses, + or it may use MMIO registers relative to the PcdPciExpressBaseAddress, or it may use some + alternate access method. Modules will typically use the PCI Library for its PCI configuration + accesses. However, if a module requires a mix of PCI access methods, the PCI CF8 Library or + PCI Express Library may be used in conjunction with the PCI Library. The functionality of + these three libraries is identical. The PCI CF8 Library and PCI Express Library simply use + explicit access methods. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_LIB_H__ +#define __PCI_LIB_H__ + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 + for PCI Express. + + @return The encoded PCI address. + +**/ +#define PCI_LIB_ADDRESS(Bus,Device,Function,Register) \ + (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed by 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +/** + 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 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 +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *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 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 written to StartAddress. + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentInfoLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentInfoLib.h new file mode 100644 index 0000000..8d1738b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentInfoLib.h @@ -0,0 +1,41 @@ +/** @file + Provides services to return segment information on a platform with multiple PCI segments. + + This library is consumed by PciSegmentLib to support multiple segment PCI configuration access. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_SEGMENT_INFO_LIB__ +#define __PCI_SEGMENT_INFO_LIB__ + +typedef struct { + UINT16 SegmentNumber; ///< Segment number. + UINT64 BaseAddress; ///< ECAM Base address. + UINT8 StartBusNumber; ///< Start BUS number, for verifying the PCI Segment address. + UINT8 EndBusNumber; ///< End BUS number, for verifying the PCI Segment address. +} PCI_SEGMENT_INFO; + +/** + 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 * +GetPciSegmentInfo ( + UINTN *Count + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentLib.h new file mode 100644 index 0000000..aa6e253 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PciSegmentLib.h @@ -0,0 +1,1049 @@ +/** @file + Provides services to access PCI Configuration Space on a platform with multiple PCI segments. + + The PCI Segment Library function provide services to read, write, and modify the PCI configuration + registers on PCI root bridges on any supported PCI segment. These library services take a single + address parameter that encodes the PCI Segment, PCI Bus, PCI Device, PCI Function, and PCI Register. + The layout of this address parameter is as follows: + + PCI Register: Bits 0..11 + PCI Function Bits 12..14 + PCI Device Bits 15..19 + PCI Bus Bits 20..27 + Reserved Bits 28..31. Must be 0. + PCI Segment Bits 32..47 + Reserved Bits 48..63. Must be 0. + + | Reserved (MBZ) | Segment | Reserved (MBZ) | Bus | Device | Function | Register | + 63 48 47 32 31 28 27 20 19 15 14 12 11 0 + + These functions perform PCI configuration cycles using the default PCI configuration access + method. This may use I/O ports 0xCF8 and 0xCFC to perform PCI configuration accesses, or it + may use MMIO registers relative to the PcdPciExpressBaseAddress, or it may use some alternate + access method. Modules will typically use the PCI Segment Library for its PCI configuration + accesses when PCI Segments other than Segment #0 must be accessed. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_SEGMENT_LIB__ +#define __PCI_SEGMENT_LIB__ + + +/** + Macro that converts PCI Segment, PCI Bus, PCI Device, PCI Function, + and PCI Register to an address that can be passed to the PCI Segment Library functions. + + Computes an address that is compatible with the PCI Segment Library functions. + The unused upper bits of Segment, Bus, Device, Function, + and Register are stripped prior to the generation of the address. + + @param Segment PCI Segment number. Range 0..65535. + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 for PCI Express. + + @return The address that is compatible with the PCI Segment Library functions. + +**/ +#define PCI_SEGMENT_LIB_ADDRESS(Segment,Bus,Device,Function,Register) \ + ((Segment != 0) ? \ + ( ((Register) & 0xfff) | \ + (((Function) & 0x07) << 12) | \ + (((Device) & 0x1f) << 15) | \ + (((Bus) & 0xff) << 20) | \ + (LShiftU64 ((Segment) & 0xffff, 32)) \ + ) : \ + ( ((Register) & 0xfff) | \ + (((Function) & 0x07) << 12) | \ + (((Device) & 0x1f) << 15) | \ + (((Bus) & 0xff) << 20) \ + ) \ + ) + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffExtraActionLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffExtraActionLib.h new file mode 100644 index 0000000..a16f81e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffExtraActionLib.h @@ -0,0 +1,53 @@ +/** @file + Provides services to perform additional actions when a PE/COFF image is loaded + or unloaded. This is useful for environment where symbols need to be loaded + and unloaded to support source level debugging. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PE_COFF_EXTRA_ACTION_LIB_H__ +#define __PE_COFF_EXTRA_ACTION_LIB_H__ + +#include + +/** + Performs additional actions after a PE/COFF image has been loaded and relocated. + + If ImageContext is NULL, then ASSERT(). + + @param ImageContext 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 + ); + +/** + 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 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffGetEntryPointLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffGetEntryPointLib.h new file mode 100644 index 0000000..c07d3e1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffGetEntryPointLib.h @@ -0,0 +1,122 @@ +/** @file + Provides a service to retrieve the PE/COFF entry point from a PE/COFF image. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PE_COFF_GET_ENTRY_POINT_LIB_H__ +#define __PE_COFF_GET_ENTRY_POINT_LIB_H__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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 + ); + +/** + Returns PE/COFF image base specified by the address in this PE/COFF image. + + On DEBUG build, searches the PE/COFF image base forward the address in this + PE/COFF image 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffLib.h new file mode 100644 index 0000000..1c53a36 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeCoffLib.h @@ -0,0 +1,392 @@ +/** @file + Provides services to load and relocate a PE/COFF image. + + The PE/COFF Loader Library abstracts the implementation of a PE/COFF loader for + IA-32, x86, IPF, and EBC processor types. The library functions are memory-based + and can be ported easily to any environment. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_PE_COFF_LIB_H__ +#define __BASE_PE_COFF_LIB_H__ + +#include +// +// Return status codes from the PE/COFF Loader services +// +#define IMAGE_ERROR_SUCCESS 0 +#define IMAGE_ERROR_IMAGE_READ 1 +#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2 +#define IMAGE_ERROR_INVALID_MACHINE_TYPE 3 +#define IMAGE_ERROR_INVALID_SUBSYSTEM 4 +#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5 +#define IMAGE_ERROR_INVALID_IMAGE_SIZE 6 +#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7 +#define IMAGE_ERROR_SECTION_NOT_LOADED 8 +#define IMAGE_ERROR_FAILED_RELOCATION 9 +#define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10 +#define IMAGE_ERROR_UNSUPPORTED 11 + +/** + Reads contents of a PE/COFF image. + + A function of this type reads contents of the PE/COFF image 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. + If FileOffset specifies an offset past the end of the PE/COFF image, a ReadSize of 0 is returned. + A function of this type must be registered in the ImageRead field of a PE_COFF_LOADER_IMAGE_CONTEXT + structure for the PE/COFF Loader Library service to function correctly. This function abstracts access + to a PE/COFF image so it can be implemented in an environment specific manner. For example, SEC and PEI + environments may access memory directly to read the contents of a PE/COFF image, and DXE or UEFI + environments may require protocol services to read the contents of PE/COFF image + stored on FLASH, disk, or network devices. + + If FileHandle is not a valid handle, then ASSERT(). + If ReadSize is NULL, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param FileHandle Pointer to the file handle to read the PE/COFF image. + @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 The specified portion of the PE/COFF image was + read and the size return in ReadSize. + @retval RETURN_DEVICE_ERROR The specified portion of the PE/COFF image + could not be read due to a device error. + +**/ +typedef +RETURN_STATUS +(EFIAPI *PE_COFF_LOADER_READ_FILE)( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ); + +/// +/// The context structure used while PE/COFF image is being loaded and relocated. +/// +typedef struct { + /// + /// Set by PeCoffLoaderGetImageInfo() to the ImageBase in the PE/COFF header. + /// + PHYSICAL_ADDRESS ImageAddress; + /// + /// Set by PeCoffLoaderGetImageInfo() to the SizeOfImage in the PE/COFF header. + /// Image size includes the size of Debug Entry if it is present. + /// + UINT64 ImageSize; + /// + /// Is set to zero by PeCoffLoaderGetImageInfo(). If DestinationAddress is non-zero, + /// PeCoffLoaderRelocateImage() will relocate the image using this base address. + /// If the DestinationAddress is zero, the ImageAddress will be used as the base + /// address of relocation. + /// + PHYSICAL_ADDRESS DestinationAddress; + /// + /// PeCoffLoaderLoadImage() sets EntryPoint to to the entry point of the PE/COFF image. + /// + PHYSICAL_ADDRESS EntryPoint; + /// + /// Passed in by the caller to PeCoffLoaderGetImageInfo() and PeCoffLoaderLoadImage() + /// to abstract accessing the image from the library. + /// + PE_COFF_LOADER_READ_FILE ImageRead; + /// + /// Used as the FileHandle passed into the ImageRead function when it's called. + /// + VOID *Handle; + /// + /// Caller allocated buffer of size FixupDataSize that can be optionally allocated + /// prior to calling PeCoffLoaderRelocateImage(). + /// This buffer is filled with the information used to fix up the image. + /// The fixups have been applied to the image and this entry is just for information. + /// + VOID *FixupData; + /// + /// Set by PeCoffLoaderGetImageInfo() to the Section Alignment in the PE/COFF header. + /// If the image is a TE image, then this field is set to 0. + /// + UINT32 SectionAlignment; + /// + /// Set by PeCoffLoaderGetImageInfo() to offset to the PE/COFF header. + /// If the PE/COFF image does not start with a DOS header, this value is zero. + /// Otherwise, it's the offset to the PE/COFF header. + /// + UINT32 PeCoffHeaderOffset; + /// + /// Set by PeCoffLoaderGetImageInfo() to the Relative Virtual Address of the debug directory, + /// if it exists in the image + /// + UINT32 DebugDirectoryEntryRva; + /// + /// Set by PeCoffLoaderLoadImage() to CodeView area of the PE/COFF Debug directory. + /// + VOID *CodeView; + /// + /// Set by PeCoffLoaderLoadImage() to point to the PDB entry contained in the CodeView area. + /// The PdbPointer points to the filename of the PDB file used for source-level debug of + /// the image by a debugger. + /// + CHAR8 *PdbPointer; + /// + /// Is set by PeCoffLoaderGetImageInfo() to the Section Alignment in the PE/COFF header. + /// + UINTN SizeOfHeaders; + /// + /// Not used by this library class. Other library classes that layer on top of this library + /// class fill in this value as part of their GetImageInfo call. + /// This allows the caller of the library to know what type of memory needs to be allocated + /// to load and relocate the image. + /// + UINT32 ImageCodeMemoryType; + /// + /// Not used by this library class. Other library classes that layer on top of this library + /// class fill in this value as part of their GetImageInfo call. + /// This allows the caller of the library to know what type of memory needs to be allocated + /// to load and relocate the image. + /// + UINT32 ImageDataMemoryType; + /// + /// Set by any of the library functions if they encounter an error. + /// + UINT32 ImageError; + /// + /// Set by PeCoffLoaderLoadImage() to indicate the size of FixupData that the caller must + /// allocate before calling PeCoffLoaderRelocateImage(). + /// + UINTN FixupDataSize; + /// + /// Set by PeCoffLoaderGetImageInfo() to the machine type stored in the PE/COFF header. + /// + UINT16 Machine; + /// + /// Set by PeCoffLoaderGetImageInfo() to the subsystem type stored in the PE/COFF header. + /// + UINT16 ImageType; + /// + /// Set by PeCoffLoaderGetImageInfo() to TRUE if the PE/COFF image does not contain + /// relocation information. + /// + BOOLEAN RelocationsStripped; + /// + /// Set by PeCoffLoaderGetImageInfo() to TRUE if the image is a TE image. + /// For a definition of the TE Image format, see the Platform Initialization Pre-EFI + /// Initialization Core Interface Specification. + /// + BOOLEAN IsTeImage; + /// + /// Set by PeCoffLoaderLoadImage() to the HII resource offset + /// if the image contains a custom PE/COFF resource with the type 'HII'. + /// Otherwise, the entry remains to be 0. + /// + PHYSICAL_ADDRESS HiiResourceData; + /// + /// Private storage for implementation specific data. + /// + UINT64 Context; +} PE_COFF_LOADER_IMAGE_CONTEXT; + +/** + 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. + + @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 + ); + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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. + + 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 The 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 + ); + + +/** + Reapply fixups on a fixed up PE32/PE32+ image to allow virtual 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 + ); + +/** + 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 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 + ); +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiCoreEntryPoint.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiCoreEntryPoint.h new file mode 100644 index 0000000..a80a99d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiCoreEntryPoint.h @@ -0,0 +1,138 @@ +/** @file + Module entry point library for PEI core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +/** + 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 + ); + +/** + 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 Foundation + and 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 + ); + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. + + This function must be called by the PEI Core once an initial PEI Services Table has been established. + This function calls the set of library constructors for the set of library instances that a + module depends on. This include library instances that a module depends on directly and library + instances that a module depends on indirectly through other libraries. + This function is autogenerated by build tools and those build tools are responsible for collecting + the set of library instances, determining which ones have constructors, and calling the library + constructors in the proper order based upon the dependencies of each of the library instances. + The PEI Core must call this function with a NULL FileHandle value as soon as the initial PEI + Services Table has been established. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + + +/** + Autogenerated function that calls a set of module entry points. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of module entry points. + This function is autogenerated by build tools and those build tools are responsible + for collecting the module entry points and calling them in a specified order. + + @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. + @param Context A pointer to a private context structure defined by the PEI Core + implementation. The implementation of _ModuleEntryPoint() must set + this parameter is NULL to indicate that this is the first PEI phase. + +**/ +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, + IN VOID *Context + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesLib.h new file mode 100644 index 0000000..c5cc3b1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesLib.h @@ -0,0 +1,567 @@ +/** @file + Provides library functions for all PEI Services. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PEI_SERVICES_LIB_H__ +#define __PEI_SERVICES_LIB_H__ + +/** + 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 + ); + +/** + This service enables PEIMs to replace an entry in the PPI database with an alternate entry. + + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + This service enables PEIMs to discover additional firmware files. + + @param SearchType A filter to find files only of this type. + @param VolumeHandle 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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; undefined otherwise. + + @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 + ); + +/** + 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 + ); + + +/** + 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 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 + ); + + +/** + 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 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 If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsGetFileInfo ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *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 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 If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiServicesFfsGetFileInfo2 ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ); + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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(). + + + @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 + ); + +/** + 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(). + + @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 + ); + +/** + 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. ResetData is only valid if ResetStatus is something + other than EFI_SUCCESS unless the ResetType is EfiResetPlatformSpecific + where a minimum amount of ResetData is always required. + +**/ +VOID +EFIAPI +PeiServicesResetSystem2 ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesTablePointerLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesTablePointerLib.h new file mode 100644 index 0000000..42fe987 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeiServicesTablePointerLib.h @@ -0,0 +1,74 @@ +/** @file + Provides a service to retrieve a pointer to the PEI Services Table. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PEI_SERVICES_TABLE_POINTER_LIB_H__ +#define __PEI_SERVICES_TABLE_POINTER_LIB_H__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeimEntryPoint.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeimEntryPoint.h new file mode 100644 index 0000000..adc98d9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PeimEntryPoint.h @@ -0,0 +1,109 @@ +/** @file + Module entry point library for PEIM. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +/// +/// Declare the EFI/UEFI Specification Revision to which this driver is implemented +/// +extern CONST UINT32 _gPeimRevision; + + +/** + 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 + ); + + +/** + 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 + ); + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of library constructors for the set of library instances that a + module depends on. This includes library instances that a module depends on directly and library + instances that a module depends on indirectly through other libraries. + This function is autogenerated by build tools and those build tools are responsible for collecting + the set of library instances, determine which ones have constructors, and calling the library + constructors in the proper order based upon each of the library instances own dependencies. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + Autogenerated function that calls a set of module entry points. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of module entry points. + This function is autogenerated by build tools and those build tools are responsible + for collecting the module entry points and calling them in a specified order. + + @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 +ProcessModuleEntryPointList ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PerformanceLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PerformanceLib.h new file mode 100644 index 0000000..1f2f1f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PerformanceLib.h @@ -0,0 +1,772 @@ +/** @file + Provides services to log the execution times and retrieve them later. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PERFORMANCE_LIB_H__ +#define __PERFORMANCE_LIB_H__ + +/// +/// Performance library propery mask bits +/// +#define PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED 0x00000001 + +// +// Public Progress Identifiers for Event Records. +// +#define PERF_EVENT_ID 0x00 + +#define MODULE_START_ID 0x01 +#define MODULE_END_ID 0x02 +#define MODULE_LOADIMAGE_START_ID 0x03 +#define MODULE_LOADIMAGE_END_ID 0x04 +#define MODULE_DB_START_ID 0x05 +#define MODULE_DB_END_ID 0x06 +#define MODULE_DB_SUPPORT_START_ID 0x07 +#define MODULE_DB_SUPPORT_END_ID 0x08 +#define MODULE_DB_STOP_START_ID 0x09 +#define MODULE_DB_STOP_END_ID 0x0A + +#define PERF_EVENTSIGNAL_START_ID 0x10 +#define PERF_EVENTSIGNAL_END_ID 0x11 +#define PERF_CALLBACK_START_ID 0x20 +#define PERF_CALLBACK_END_ID 0x21 +#define PERF_FUNCTION_START_ID 0x30 +#define PERF_FUNCTION_END_ID 0x31 +#define PERF_INMODULE_START_ID 0x40 +#define PERF_INMODULE_END_ID 0x41 +#define PERF_CROSSMODULE_START_ID 0x50 +#define PERF_CROSSMODULE_END_ID 0x51 + +// +// Declare bits for PcdPerformanceLibraryPropertyMask and +// also used as the Type parameter of LogPerformanceMeasurementEnabled(). +// +#define PERF_CORE_START_IMAGE 0x0002 +#define PERF_CORE_LOAD_IMAGE 0x0004 +#define PERF_CORE_DB_SUPPORT 0x0008 +#define PERF_CORE_DB_START 0x0010 +#define PERF_CORE_DB_STOP 0x0020 + +#define PERF_GENERAL_TYPE 0x0040 + +/** + 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 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. + + @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 + ); + +/** + 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 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. + + @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 + ); + +/** + 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 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. + + @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 + ); + +/** + 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 + ); + +/** + 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 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 + ); + +/** + 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 of 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 + ); + +/** + 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 + ); + + +/** + 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 + ); + +/** + Create performance record with event description. + + @param CallerIdentifier - Image handle or pointer to caller ID GUID + @param Guid - Pointer to a GUID. + Used for event signal perf and callback perf to cache the event 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 Identifier. + +**/ +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 + ); + +/** + Begin Macro to measure the performance of StartImage in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT1(dsiable PERF_CORE_START_IMAGE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_START_IMAGE_BEGIN(ModuleHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_START_IMAGE)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the performance of StartImage in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT1 (dsiable PERF_CORE_START_IMAGE)of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_START_IMAGE_END(ModuleHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_START_IMAGE)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_END_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the performance of LoadImage in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT2 (dsiable PERF_CORE_LOAD_IAMGE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_LOAD_IMAGE_BEGIN(ModuleHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_LOAD_IMAGE)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_LOADIMAGE_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the performance of LoadImage in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT2 (dsiable PERF_CORE_LOAD_IAMGE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_LOAD_IMAGE_END(ModuleHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_LOAD_IMAGE)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, 0, MODULE_LOADIMAGE_END_ID); \ + } \ + } while (FALSE) + +/** + Start Macro to measure the performance of DriverBinding Support in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT3 (dsiable PERF_CORE_DB_SUPPORT) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_DRIVER_BINDING_SUPPORT_BEGIN(ModuleHandle, ControllerHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_SUPPORT)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_SUPPORT_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the performance of DriverBinding Support in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT3 (dsiable PERF_CORE_DB_SUPPORT) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_DRIVER_BINDING_SUPPORT_END(ModuleHandle, ControllerHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_SUPPORT)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_SUPPORT_END_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the performance of DriverBinding Start in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT4 (dsiable PERF_CORE_DB_START) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_DRIVER_BINDING_START_BEGIN(ModuleHandle, ControllerHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_START)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the performance of DriverBinding Start in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT4 (dsiable PERF_CORE_DB_START) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_DRIVER_BINDING_START_END(ModuleHandle, ControllerHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_START)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_END_ID); \ + } \ + } while (FALSE) + +/** + Start Macro to measure the performance of DriverBinding Stop in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT5 (dsiable PERF_CORE_DB_STOP) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_DRIVER_BINDING_STOP_BEGIN(ModuleHandle, ControllerHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_STOP)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_STOP_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the performance of DriverBinding Stop in core. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT5 (dsiable PERF_CORE_DB_STOP) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_DRIVER_BINDING_STOP_END(ModuleHandle, ControllerHandle) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_CORE_DB_STOP)) { \ + LogPerformanceMeasurement (ModuleHandle, NULL, NULL, (UINT64)(UINTN)ControllerHandle, MODULE_DB_STOP_END_ID); \ + } \ + } while (FALSE) + +/** + Macro to measure the time from power-on to this macro execution. + It can be used to log a meaningful thing which happens at a time point. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_EVENT(EventString) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, EventString , 0, PERF_EVENT_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the perofrmance of evnent signal behavior in any module. + The event guid will be passed with this macro. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_EVENT_SIGNAL_BEGIN(EventGuid) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, EventGuid, __FUNCTION__ , 0, PERF_EVENTSIGNAL_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the perofrmance of evnent signal behavior in any module. + The event guid will be passed with this macro. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_EVENT_SIGNAL_END(EventGuid) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, EventGuid, __FUNCTION__ , 0, PERF_EVENTSIGNAL_END_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the perofrmance of a callback function in any module. + The event guid which trigger the callback function will be passed with this macro. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_CALLBACK_BEGIN(TriggerGuid) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, TriggerGuid, __FUNCTION__ , 0, PERF_CALLBACK_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the perofrmance of a callback function in any module. + The event guid which trigger the callback function will be passed with this macro. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_CALLBACK_END(TriggerGuid) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, TriggerGuid, __FUNCTION__ , 0, PERF_CALLBACK_END_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the perofrmance of a general function in any module. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_FUNCTION_BEGIN() \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, __FUNCTION__ , 0, PERF_FUNCTION_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the perofrmance of a general function in any module. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_FUNCTION_END() \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, __FUNCTION__ , 0, PERF_FUNCTION_END_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the perofrmance of a behavior within one module. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_INMODULE_BEGIN(MeasurementString) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_INMODULE_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the perofrmance of a behavior within one module. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_INMODULE_END(MeasurementString) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_INMODULE_END_ID); \ + } \ + } while (FALSE) + +/** + Begin Macro to measure the perofrmance of a behavior in different modules. + Such as the performance of PEI phase, DXE phase, BDS phase. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_CROSSMODULE_BEGIN(MeasurementString) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_CROSSMODULE_START_ID); \ + } \ + } while (FALSE) + +/** + End Macro to measure the perofrmance of a behavior in different modules. + Such as the performance of PEI phase, DXE phase, BDS phase. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + and the BIT6 (dsiable PERF_GENERAL_TYPE) of PcdPerformanceLibraryPropertyMask is not set. + then LogPerformanceMeasurement() is called. + +**/ +#define PERF_CROSSMODULE_END(MeasurementString) \ + do { \ + if (LogPerformanceMeasurementEnabled (PERF_GENERAL_TYPE)) { \ + LogPerformanceMeasurement (&gEfiCallerIdGuid, NULL, MeasurementString, 0, PERF_CROSSMODULE_END_ID); \ + } \ + } while (FALSE) + +/** + Macro that calls EndPerformanceMeasurement(). + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then EndPerformanceMeasurement() is called. + +**/ +#define PERF_END(Handle, Token, Module, TimeStamp) \ + do { \ + if (PerformanceMeasurementEnabled ()) { \ + EndPerformanceMeasurement (Handle, Token, Module, TimeStamp); \ + } \ + } while (FALSE) + +/** + Macro that calls StartPerformanceMeasurement(). + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then StartPerformanceMeasurement() is called. + +**/ +#define PERF_START(Handle, Token, Module, TimeStamp) \ + do { \ + if (PerformanceMeasurementEnabled ()) { \ + StartPerformanceMeasurement (Handle, Token, Module, TimeStamp); \ + } \ + } while (FALSE) + +/** + Macro that calls EndPerformanceMeasurementEx(). + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then EndPerformanceMeasurementEx() is called. + +**/ +#define PERF_END_EX(Handle, Token, Module, TimeStamp, Identifier) \ + do { \ + if (PerformanceMeasurementEnabled ()) { \ + EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, Identifier); \ + } \ + } while (FALSE) + +/** + Macro that calls StartPerformanceMeasurementEx(). + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then StartPerformanceMeasurementEx() is called. + +**/ +#define PERF_START_EX(Handle, Token, Module, TimeStamp, Identifier) \ + do { \ + if (PerformanceMeasurementEnabled ()) { \ + StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, Identifier); \ + } \ + } while (FALSE) + +/** + Macro that marks the beginning of performance measurement source code. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then this macro marks the beginning of source code that is included in a module. + Otherwise, the source lines between PERF_CODE_BEGIN() and PERF_CODE_END() are not included in a module. + +**/ +#define PERF_CODE_BEGIN() do { if (PerformanceMeasurementEnabled ()) { UINT8 __PerformanceCodeLocal + +/** + Macro that marks the end of performance measurement source code. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then this macro marks the end of source code that is included in a module. + Otherwise, the source lines between PERF_CODE_BEGIN() and PERF_CODE_END() are not included in a module. + +**/ +#define PERF_CODE_END() __PerformanceCodeLocal = 0; __PerformanceCodeLocal++; } } while (FALSE) + +/** + Macro that declares a section of performance measurement source code. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then the source code specified by Expression is included in a module. + Otherwise, the source specified by Expression is not included in a module. + + @param Expression Performance measurement source code to include in a module. + +**/ +#define PERF_CODE(Expression) \ + PERF_CODE_BEGIN (); \ + Expression \ + PERF_CODE_END () + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PostCodeLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PostCodeLib.h new file mode 100644 index 0000000..c487469 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PostCodeLib.h @@ -0,0 +1,150 @@ +/** @file + Provides services to send progress/error codes to a POST card. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __POST_CODE_LIB_H__ +#define __POST_CODE_LIB_H__ + +#define POST_CODE_PROPERTY_POST_CODE_ENABLED 0x00000008 +#define POST_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED 0x00000010 + +/** + Sends a 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 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 + ); + + +/** + Sends a 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 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + Sends a 32-bit value to a POST card. + + If POST codes are enabled in PcdPostCodeProperyMask, then call PostCode() + passing in Value. Value is returned. + + @param Value The 32-bit value to write to the POST card. + + @return Value The 32-bit value to write to the POST card. + +**/ +#define POST_CODE(Value) PostCodeEnabled() ? PostCode(Value) : Value + +/** + Sends a 32-bit value to a POST and associated ASCII string. + + If POST codes and POST code descriptions are enabled in + PcdPostCodeProperyMask, then call PostCodeWithDescription() passing in + Value and Description. If only POST codes are enabled, then call PostCode() + passing in Value. Value is returned. + + @param Value The 32-bit value to write to the POST card. + @param Description Pointer to an ASCII string that is a description of the + POST code value. + + @return Value The 32-bit value to write to the POST card. +**/ +#define POST_CODE_WITH_DESCRIPTION(Value,Description) \ + PostCodeEnabled() ? \ + (PostCodeDescriptionEnabled() ? \ + PostCodeWithDescription(Value,Description) : \ + PostCode(Value)) : \ + Value + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PrintLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PrintLib.h new file mode 100644 index 0000000..cd4c6a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/PrintLib.h @@ -0,0 +1,1051 @@ +/** @file + Provides services to print a formatted string to a buffer. All combinations of + Unicode and ASCII strings are supported. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + The Print Library functions provide a simple means to produce formatted output + strings. Many of the output functions use a format string to describe how to + format the output of variable arguments. The format string consists of normal + text and argument descriptors. There are no restrictions for how the normal + text and argument descriptors can be mixed. The following end of line(EOL) + translations must be performed on the contents of the format string: + + - '\\r' is translated to '\\r' + - '\\r\\n' is translated to '\\r\\n' + - '\\n' is translated to '\\r\\n' + - '\\n\\r' is translated to '\\r\\n' + + This does not follow the ANSI C standard for sprint(). The format of argument + descriptors is described below. The ANSI C standard for sprint() has been + followed for some of the format types, and has not been followed for others. + The exceptions are noted below. + + %[flags][width][.precision]type + + [flags]: + - - + - The field is left justified. If not flag is not specified, then the + field is right justified. + - space + - Prefix a space character to a number. Only valid for types X, x, and d. + - + + - Prefix a plus character to a number. Only valid for types X, x, and d. + If both space and + are specified, then space is ignored. + - 0 + - Pad with 0 characters to the left of a number. Only valid for types + X, x, and d. + - , + - Place a comma every 3rd digit of the number. Only valid for type d. + If 0 is also specified, then 0 is ignored. + - L, l + - The number being printed is size UINT64. Only valid for types X, x, and d. + If this flag is not specified, then the number being printed is size int. + - NOTE: All invalid flags are ignored. + + [width]: + + - * + - The width of the field is specified by a UINTN argument in the + argument list. + - number + - The number specified as a decimal value represents the width of + the field. + - NOTE: If [width] is not specified, then a field width of 0 is assumed. + + [.precision]: + + - * + - The precision of the field is specified by a UINTN argument in the + argument list. + - number + - The number specified as a decimal value represents the precision of + the field. + - NOTE: If [.precision] is not specified, then a precision of 0 is assumed. + + type: + + - % + - Print a %%. + - c + - The argument is a Unicode character. ASCII characters can be printed + using this type too by making sure bits 8..15 of the argument are set to 0. + - x + - The argument is an unsigned hexadecimal number. The characters used are 0..9 and + A..F. If the flag 'L' is not specified, then the argument is assumed + to be size int. This does not follow ANSI C. + - X + - The argument is an unsigned hexadecimal number and the number is padded with + zeros. This is equivalent to a format string of "0x". If the flag + 'L' is not specified, then the argument is assumed to be size int. + This does not follow ANSI C. + - d + - The argument is a signed decimal number. If the flag 'L' is not specified, + then the argument is assumed to be size int. + - u + - The argument is a unsigned decimal number. If the flag 'L' is not specified, + then the argument is assumed to be size int. + - p + - The argument is a pointer that is a (VOID *), and it is printed as an + unsigned hexadecimal number The characters used are 0..9 and A..F. + - a + - The argument is a pointer to an ASCII string. + This does not follow ANSI C. + - S, s + - The argument is a pointer to a Unicode string. + This does not follow ANSI C. + - g + - The argument is a pointer to a GUID structure. The GUID is printed + in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. + This does not follow ANSI C. + - t + - The argument is a pointer to an EFI_TIME structure. The time and + date are printed in the format "mm/dd/yyyy hh:mm" where mm is the + month zero padded, dd is the day zero padded, yyyy is the year zero + padded, hh is the hour zero padded, and mm is minutes zero padded. + This does not follow ANSI C. + - r + - The argument is a RETURN_STATUS value. This value is converted to + a string following the table below. This does not follow ANSI C. + - RETURN_SUCCESS + - "Success" + - RETURN_LOAD_ERROR + - "Load Error" + - RETURN_INVALID_PARAMETER + - "Invalid Parameter" + - RETURN_UNSUPPORTED + - "Unsupported" + - RETURN_BAD_BUFFER_SIZE + - "Bad Buffer Size" + - RETURN_BUFFER_TOO_SMALL + - "Buffer Too Small" + - RETURN_NOT_READY + - "Not Ready" + - RETURN_DEVICE_ERROR + - "Device Error" + - RETURN_WRITE_PROTECTED + - "Write Protected" + - RETURN_OUT_OF_RESOURCES + - "Out of Resources" + - RETURN_VOLUME_CORRUPTED + - "Volume Corrupt" + - RETURN_VOLUME_FULL + - "Volume Full" + - RETURN_NO_MEDIA + - "No Media" + - RETURN_MEDIA_CHANGED + - "Media changed" + - RETURN_NOT_FOUND + - "Not Found" + - RETURN_ACCESS_DENIED + - "Access Denied" + - RETURN_NO_RESPONSE + - "No Response" + - RETURN_NO_MAPPING + - "No mapping" + - RETURN_TIMEOUT + - "Time out" + - RETURN_NOT_STARTED + - "Not started" + - RETURN_ALREADY_STARTED + - "Already started" + - RETURN_ABORTED + - "Aborted" + - RETURN_ICMP_ERROR + - "ICMP Error" + - RETURN_TFTP_ERROR + - "TFTP Error" + - RETURN_PROTOCOL_ERROR + - "Protocol Error" + - RETURN_WARN_UNKNOWN_GLYPH + - "Warning Unknown Glyph" + - RETURN_WARN_DELETE_FAILURE + - "Warning Delete Failure" + - RETURN_WARN_WRITE_FAILURE + - "Warning Write Failure" + - RETURN_WARN_BUFFER_TOO_SMALL + - "Warning Buffer Too Small" + +**/ + +#ifndef __PRINT_LIB_H__ +#define __PRINT_LIB_H__ + +/// +/// Define the maximum number of characters that are required to +/// encode with a NULL terminator a decimal, hexadecimal, GUID, +/// or TIME value. +/// +/// Maximum Length Decimal String = 28 +/// "-9,223,372,036,854,775,808" +/// Maximum Length Hexadecimal String = 17 +/// "FFFFFFFFFFFFFFFF" +/// Maximum Length GUID = 37 +/// "00000000-0000-0000-0000-000000000000" +/// Maximum Length TIME = 18 +/// "12/12/2006 12:12" +/// +#define MAXIMUM_VALUE_CHARACTERS 38 + +/// +/// Flags bitmask values use in UnicodeValueToString() and +/// AsciiValueToString() +/// +#define LEFT_JUSTIFY 0x01 +#define COMMA_TYPE 0x08 +#define PREFIX_ZERO 0x20 +#define RADIX_HEX 0x80 + +/** + 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 + ); + +/** + 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 + ); + +/** + 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, + ... + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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, + ... + ); + +#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 + ); + +#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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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, + ... + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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, + ... + ); + +#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 A 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 + ); + +#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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ReportStatusCodeLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ReportStatusCodeLib.h new file mode 100644 index 0000000..a20764b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ReportStatusCodeLib.h @@ -0,0 +1,492 @@ +/** @file + Provides services to log status code records. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __REPORT_STATUS_CODE_LIB_H__ +#define __REPORT_STATUS_CODE_LIB_H__ + +#include +#include +#include + +// +// Declare bits for PcdReportStatusCodePropertyMask +// +#define REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED 0x00000001 +#define REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED 0x00000002 +#define REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED 0x00000004 + +/** + 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 + ); + + +/** + 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 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 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 + ); + + +/** + 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 status code data buffer. + @param ErrorLevel The pointer to 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 + ); + + +/** + 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 Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED The report status code is not supported. + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ); + + +/** + 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 an implementation dependent GUID. + 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 The status code type. + @param Value The 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. + @retval EFI_DEVICE_ERROR A call to a Report Status Code Library function + is already in progress. + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with an implementation dependent GUID. 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 The status code type. + @param Value The 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. + @retval EFI_DEVICE_ERROR A call to a Report Status Code Library function + is already in progress. + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN CONST VOID *ExtendedData, + IN UINTN ExtendedDataSize + ); + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDataGuid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() + is called while processing another any other Report Status Code Library function, + then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type The status code type. + @param Value The status code value. + @param Instance The 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 an implementation dependent GUID. + @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. + @retval EFI_DEVICE_ERROR A call to a Report Status Code Library function + is already in progress. + +**/ +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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + Reports a status code with minimal parameters if the status code type is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCode() passing in Type + and Value. + + @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 Report status code is not supported. + +**/ +#define REPORT_STATUS_CODE(Type,Value) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCode(Type,Value) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCode(Type,Value) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCode(Type,Value) : \ + EFI_UNSUPPORTED + + +/** + Reports a status code with a Device Path Protocol as the extended data if the + status code type is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCodeWithDevicePath() + passing in Type, Value, and DevicePath. + + @param Type The status code type. + @param Value The status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED The report status code is not supported. + @retval EFI_DEVICE_ERROR A call to a Report Status Code Library function + is already in progress. + +**/ +#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type,Value,DevicePathParameter) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCodeWithDevicePath(Type,Value,DevicePathParameter) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCodeWithDevicePath(Type,Value,DevicePathParameter) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCodeWithDevicePath(Type,Value,DevicePathParameter) : \ + EFI_UNSUPPORTED + + +/** + Reports a status code with an extended data buffer if the status code type + is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCodeWithExtendedData() + passing in Type, Value, ExtendedData, and ExtendedDataSize. + + @param Type The status code type. + @param Value The 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. + @retval EFI_DEVICE_ERROR A call to a Report Status Code Library function + is already in progress. + +**/ +#define REPORT_STATUS_CODE_WITH_EXTENDED_DATA(Type,Value,ExtendedData,ExtendedDataSize) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCodeWithExtendedData(Type,Value,ExtendedData,ExtendedDataSize) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCodeWithExtendedData(Type,Value,ExtendedData,ExtendedDataSize) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCodeWithExtendedData(Type,Value,ExtendedData,ExtendedDataSize) : \ + EFI_UNSUPPORTED + +/** + Reports a status code specifying all parameters if the status code type is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCodeEx() passing in Type, + Value, Instance, CallerId, ExtendedDataGuid, ExtendedData, and ExtendedDataSize. + + @param Type The status code type. + @param Value The status code value. + @param Instance The 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 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 an implementation dependent GUID. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section if it was specified. + @retval EFI_UNSUPPORTED The report status code is not supported. + @retval EFI_DEVICE_ERROR A call to a Report Status Code Library function + is already in progress. + +**/ +#define REPORT_STATUS_CODE_EX(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) : \ + EFI_UNSUPPORTED + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ResourcePublicationLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ResourcePublicationLib.h new file mode 100644 index 0000000..9e2e014 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/ResourcePublicationLib.h @@ -0,0 +1,42 @@ +/** @file + Provides a service to publish discovered system resources. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __RESOURCE_PUBLICATION_LIB__ +#define __RESOURCE_PUBLICATION_LIB__ + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/RngLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/RngLib.h new file mode 100644 index 0000000..4b0b90c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/RngLib.h @@ -0,0 +1,86 @@ +/** @file + Provides random number generator services. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __RNG_LIB_H__ +#define __RNG_LIB_H__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif // __RNG_LIB_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3BootScriptLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3BootScriptLib.h new file mode 100644 index 0000000..585cef0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3BootScriptLib.h @@ -0,0 +1,602 @@ +/** @file + Defines library APIs used by modules to save EFI Boot Script Opcodes. + These OpCode will be restored by S3 related modules. + Note that some of the API defined in the Library class may not + be provided in the Framework version library instance, which means some of these + APIs cannot be used if the underlying firmware is Framework and not PI. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _S3_BOOT_SCRIPT_LIB_H_ +#define _S3_BOOT_SCRIPT_LIB_H_ + +#include +#include + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the S3 Boot Script Library PCI functions. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 + for PCI Express. + + @return The encoded PCI address. + +**/ +#define S3_BOOT_SCRIPT_LIB_PCI_ADDRESS(Bus,Device,Function,Register) \ + (UINT64) ( \ + (((UINTN) Bus) << 24) | \ + (((UINTN) Device) << 16) | \ + (((UINTN) Function) << 8) | \ + (((UINTN) (Register)) < 256 ? ((UINTN) (Register)) : (UINT64) (LShiftU64 ((UINT64) (Register), 32)))) + +/// +/// S3 Boot Script Width. +/// +typedef enum { + S3BootScriptWidthUint8, ///< 8-bit operation. + S3BootScriptWidthUint16, ///< 16-bit operation. + S3BootScriptWidthUint32, ///< 32-bit operation. + S3BootScriptWidthUint64, ///< 64-bit operation. + S3BootScriptWidthFifoUint8, ///< 8-bit FIFO operation. + S3BootScriptWidthFifoUint16, ///< 16-bit FIFO operation. + S3BootScriptWidthFifoUint32, ///< 32-bit FIFO operation. + S3BootScriptWidthFifoUint64, ///< 64-bit FIFO operation. + S3BootScriptWidthFillUint8, ///< 8-bit Fill operation. + S3BootScriptWidthFillUint16, ///< 16-bit Fill operation. + S3BootScriptWidthFillUint32, ///< 32-bit Fill operation. + S3BootScriptWidthFillUint64, ///< 64-bit Fill operation. + S3BootScriptWidthMaximum +} S3_BOOT_SCRIPT_LIB_WIDTH; + +/** + Save I/O write to boot script. + + @param[in] Width The width of the I/O operations. + @param[in] Address The base address of the I/O operations. + @param[in] Count The number of I/O operations to perform. + @param[in] Buffer The source buffer from which to write data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveIoWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Adds a record for an I/O modify operation into a S3 boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Address The base address of the I/O operations. + @param[in] Data A pointer to the data to be OR-ed. + @param[in] 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 to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveIoReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ); + +/** + Adds a record for a memory write operation into a specified boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Address The base address of the memory operations + @param[in] Count The number of memory operations to perform. + @param[in] Buffer The source buffer from which to write the data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveMemWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Adds a record for a memory modify operation into a specified boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Address The base address of the memory operations. Address needs + alignment, if required + @param[in] Data A pointer to the data to be OR-ed. + @param[in] 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 to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveMemReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ); + +/** + Adds a record for a PCI configuration space write operation into a specified boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Address The address within the PCI configuration space. + @param[in] Count The number of PCI operations to perform. + @param[in] Buffer The source buffer from which to write the data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfgWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Adds a record for a PCI configuration space modify operation into a specified boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Address The address within the PCI configuration space. + @param[in] Data A pointer to the data to be OR-ed.The size depends on Width. + @param[in] DataMask A pointer to the data mask to be AND-ed. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN__SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfgReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ); + +/** + Adds a record for a PCI configuration space modify operation into a specified boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Segment The PCI segment number for Address. + @param[in] Address The address within the PCI configuration space. + @param[in] Count The number of PCI operations to perform. + @param[in] Buffer The source buffer from which to write the data. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfg2Write ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT16 Segment, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Adds a record for a PCI configuration space modify operation into a specified boot script table. + + @param[in] Width The width of the I/O operations. + @param[in] Segment The PCI segment number for Address. + @param[in] Address The address within the PCI configuration space. + @param[in] Data A pointer to the data to be OR-ed. The size depends on Width. + @param[in] DataMask A pointer to the data mask to be AND-ed. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciCfg2ReadWrite ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT16 Segment, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask + ); + +/** + Adds a record for an SMBus command execution into a specified boot script table. + + @param[in] SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS + Command, SMBUS Data Length, and PEC. + @param[in] Operation Indicates which particular SMBus protocol it will use + to execute the SMBus transactions. + @param[in] Length A pointer to signify the number of bytes that this + operation will do. + @param[in] Buffer Contains the value of data to execute to the SMBUS + slave device. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveSmbusExecute ( + IN UINTN SmBusAddress, + IN EFI_SMBUS_OPERATION Operation, + IN UINTN *Length, + IN VOID *Buffer + ); + +/** + Adds a record for an execution stall on the processor into a specified boot script table. + + @param[in] Duration The duration in microseconds of the stall. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveStall ( + IN UINTN Duration + ); + +/** + Adds a record for dispatching specified arbitrary code into a specified boot script table. + + @param[in] EntryPoint The entry point of the code to be dispatched. + @param[in] Context The argument to be passed into the EntryPoint of the code + to be dispatched. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveDispatch2 ( + IN VOID *EntryPoint, + IN VOID *Context + ); + +/** + Adds a record for dispatching specified arbitrary code into a specified boot script table. + + @param[in] EntryPoint The entry point of the code to be dispatched. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveDispatch ( + IN VOID *EntryPoint + ); + +/** + 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[in] Width The width of the memory operations. + @param[in] Address The base address of the memory operations. + @param[in] BitMask A pointer to the bit mask to be AND-ed with the data read + from the register. + @param[in] BitValue A pointer to the data value after to be Masked. + @param[in] Duration The duration in microseconds of the stall. + @param[in] LoopTimes The times of the register polling. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was 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 + ); + +/** + 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[in] InformationLength Length of the data in bytes + @param[in] Information Information to be logged in the boot scrpit + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveInformation ( + IN UINT32 InformationLength, + IN VOID *Information + ); +/** + 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 The 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 insufficient granularity, so the + delay may be longer. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform the + operation. + @retval RETURN_SUCCESS The opcode was added. + @note The FRAMEWORK version implementation does not support this API +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveIoPoll ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask, + IN UINT64 Delay + ); + +/** + 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 insufficient granularity, so the + delay may be longer. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform the + operation. + @retval RETURN_SUCCESS The opcode was added. + @note The FRAMEWORK version implementation does not support this API +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSavePciPoll ( + IN S3_BOOT_SCRIPT_LIB_WIDTH Width, + IN UINT64 Address, + IN VOID *Data, + IN VOID *DataMask, + IN UINT64 Delay + ); +/** + 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 insufficient granularity so the delay + may be longer. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform the + operation. + @retval RETURN_SUCCESS The opcode was 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. + The FRAMEWORK version implementation does not support this API. + +**/ +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 + ); +/** + Save ASCII string information specified by Buffer to boot script with opcode + EFI_BOOT_SCRIPT_INFORMATION_OPCODE. + + @param[in] String The Null-terminated ASCII string to store into the S3 boot + script table. + + @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table to perform + the operation. + @retval RETURN_SUCCESS The opcode was added. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptSaveInformationAsciiString ( + IN CONST CHAR8 *String + ); + +/** + 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. This + API is supplied here to meet the requirements of the 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 + ); + +/** + Executes the S3 boot script table. + + @retval RETURN_SUCCESS The boot script table was executed successfully. + @retval RETURN_UNSUPPORTED Invalid script table or opcode. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptExecute ( + VOID + ); +/** + Move the last boot script entry to the position + + @param BeforeOrAfter Specifies whether the opcode is stored before + (TRUE) or after (FALSE) the positionin 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 The opcode was inserted. + @note The FRAMEWORK version implementation does not support this API. +**/ +RETURN_STATUS +EFIAPI +S3BootScriptMoveLastOpcode ( + IN BOOLEAN BeforeOrAfter, + IN OUT VOID **Position OPTIONAL + ); +/** + 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 positionof 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. + @note The FRAMEWORK version implementation does not support this API + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptLabel ( + IN BOOLEAN BeforeOrAfter, + IN BOOLEAN CreateIfNotFound, + IN OUT VOID **Position OPTIONAL, + IN CONST CHAR8 *Label + ); +/** + 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 s + upported because of the PCD Feature Flags. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. + @note The FRAMEWORK version implementation does not support this API +**/ +RETURN_STATUS +EFIAPI +S3BootScriptCompare ( + IN UINT8 *Position1, + IN UINT8 *Position2, + OUT UINTN *RelativePosition + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3IoLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3IoLib.h new file mode 100644 index 0000000..17682fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3IoLib.h @@ -0,0 +1,2677 @@ +/** @file + I/O and MMIO Library Services that do I/O and also enable the I/O operation + to be replayed during an S3 resume. This library class maps directly on top + of the IoLib class. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __S3_IO_LIB_H__ +#define __S3_IO_LIB_H__ + +/** + 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[in] Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +S3IoRead8 ( + IN UINTN 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads an 8-bit I/O port, performs a bitwise OR, 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads an 8-bit I/O port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Port The I/O port to write. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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. + Remaining 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + Reads a bit field in an 8-bit port, 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 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +S3IoRead16 ( + IN UINTN 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 16-bit I/O port, performs a bitwise OR, 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 16-bit I/O port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Port The I/O port to write. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + Reads a bit field in a 16-bit port, 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 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +S3IoRead32 ( + IN UINTN 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 32-bit I/O port, performs a bitwise OR, 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 32-bit I/O port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Port The I/O port to write. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + Reads a bit field in a 32-bit port, 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 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +S3IoRead64 ( + IN UINTN 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[in] Port The I/O port to write. + @param[in] Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT64 +EFIAPI +S3IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ); + +/** + Reads a 64-bit I/O port, performs a bitwise OR, 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 64-bit I/O port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] 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 + ); + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Port The I/O port to write. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + Reads a bit field in a 64-bit port, performs a bitwise 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise OR, 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[in] Port The I/O port to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] AndData The value to AND with the read value from the I/O port. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +S3MmioRead8 ( + IN UINTN 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads an 8-bit MMIO register, performs a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads an 8-bit MMIO register, performs a bitwise 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Address The MMIO register to write. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address MMIO register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +S3MmioRead16 ( + IN UINTN 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 16-bit MMIO register, performs a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 16-bit MMIO register, performs a bitwise 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Address The MMIO register to write. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address MMIO register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +S3MmioRead32 ( + IN UINTN 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 32-bit MMIO register, performs a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 32-bit MMIO register, performs a bitwise 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Address The MMIO register to write. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address MMIO register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +S3MmioRead64 ( + IN UINTN 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 64-bit MMIO register, performs a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 64-bit MMIO register, performs a bitwise 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[in] Address The MMIO register to write. + @param[in] 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 + ); + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, 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[in] Address The MMIO register to write. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + 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[in] Address MMIO register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] 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 + ); + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise OR, 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[in] Address The MMIO register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param[in] AndData The value to AND with the read value from the MMIO register. + @param[in] 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 + ); + +/** + Copies 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 bytes 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[in] StartAddress Starting address for the MMIO region to be copied from. + @param[in] Length Size in bytes of the copy. + @param[out] 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 + ); + +/** + Copies 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 bytes 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[in] StartAddress Starting address for the MMIO region to be copied from. + @param[in] Length Size in bytes of the copy. + @param[out] 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 + ); + +/** + Copies 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[in] StartAddress Starting address for the MMIO region to be copied from. + @param[in] Length Size in bytes of the copy. + @param[out] 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 + ); + +/** + Copies 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[in] StartAddress Starting address for the MMIO region to be copied from. + @param[in] Length Size in bytes of the copy. + @param[out] 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 + ); + +/** + Copies 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[in] StartAddress Starting address for the MMIO region to be copied to. + @param[in] Length Size in bytes of the copy. + @param[in] 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 + ); + +/** + Copies 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 bytes 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[in] StartAddress Starting address for the MMIO region to be copied to. + @param[in] Length Size in bytes of the copy. + @param[in] 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 + ); + +/** + Copies 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 bytes 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[in] StartAddress Starting address for the MMIO region to be copied to. + @param[in] Length Size in bytes of the copy. + @param[in] 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 + ); + +/** + Copies 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 bytes 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[in] StartAddress Starting address for the MMIO region to be copied to. + @param[in] Length Size in bytes of the copy. + @param[in] 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciLib.h new file mode 100644 index 0000000..d074adf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciLib.h @@ -0,0 +1,1052 @@ +/** @file + The 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 PciLib class. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __S3_PCI_LIB_H__ +#define __S3_PCI_LIB_H__ + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the S3 PCI Library functions. + + @param Bus The PCI Bus number. Range 0..255. + @param Device The PCI Device number. Range 0..31. + @param Function The PCI Function number. Range 0..7. + @param Register The PCI Register number. Range 0..255 for PCI. Range 0..4095 + for PCI Express. + + @return The encoded PCI address. + +**/ +#define S3_PCI_LIB_ADDRESS(Bus,Device,Function,Register) \ + (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + +/** + + Reads and returns the 8-bit PCI configuration register specified by Address, + and saves the value in the S3 script to be replayed on S3 resume. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + + @return The value read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciRead8 ( + IN UINTN 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +S3PciWrite8 ( + IN UINTN Address, + IN UINT8 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] 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 + ); + +/** + 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[in] Address The 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +S3PciWrite16 ( + IN UINTN Address, + IN UINT16 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] 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 + ); + +/** + 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[in] Address The 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +S3PciWrite32 ( + IN UINTN Address, + IN UINT32 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] 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 + ); + +/** + 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[in] Address The address that encodes the PCI Bus, Device, Function and + Register. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to read. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] 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 + ); + +/** + 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[in] Address The PCI configuration register to write. + @param[in] StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param[in] EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param[in] AndData The value to AND with the PCI configuration register. + @param[in] 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 + ); + +/** + 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[in] StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param[in] Size Size in bytes of the transfer. + @param[out] Buffer The pointer to a buffer receiving the data read. + + @return Size. + +**/ +UINTN +EFIAPI +S3PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ); + +/** + 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[in] StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param[in] Size Size in bytes of the transfer. + @param[in] Buffer The pointer to a buffer containing the data to write. + + @return Size. + +**/ +UINTN +EFIAPI +S3PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciSegmentLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciSegmentLib.h new file mode 100644 index 0000000..e42e678 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3PciSegmentLib.h @@ -0,0 +1,1037 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __S3_PCI_SEGMENT_LIB__ +#define __S3_PCI_SEGMENT_LIB__ + + +/** + Macro that converts PCI Segment, PCI Bus, PCI Device, PCI Function, + and PCI Register to an address that can be passed to the S3 PCI Segment Library functions. + + Computes an address that is compatible with the PCI Segment Library functions. + The unused upper bits of Segment, Bus, Device, Function, + and Register are stripped prior to the generation of the address. + + @param Segment PCI Segment number. Range 0..65535. + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 for PCI Express. + + @return The address that is compatible with the PCI Segment Library functions. + +**/ +#define S3_PCI_SEGMENT_LIB_ADDRESS(Segment,Bus,Device,Function,Register) \ + ((Segment != 0) ? \ + ( ((Register) & 0xfff) | \ + (((Function) & 0x07) << 12) | \ + (((Device) & 0x1f) << 15) | \ + (((Bus) & 0xff) << 20) | \ + (LShiftU64 ((Segment) & 0xffff, 32)) \ + ) : \ + ( ((Register) & 0xfff) | \ + (((Function) & 0x07) << 12) | \ + (((Device) & 0x1f) << 15) | \ + (((Bus) & 0xff) << 20) \ + ) \ + ) + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3SmbusLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3SmbusLib.h new file mode 100644 index 0000000..186b78c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3SmbusLib.h @@ -0,0 +1,455 @@ +/** @file + Smbus Library Services that conduct SMBus transactions and 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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __S3_SMBUS_LIB_H__ +#define __S3_SMBUS_LIB_H__ + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + RETURN_UNSUPPORTED The SMBus operation is not supported. + +**/ +VOID +EFIAPI +S3SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + RETURN_UNSUPPORTED The SMBus operation is not supported. + +**/ +VOID +EFIAPI +S3SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[in] Value The 8-bit value to send. + @param[out] Status The 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 + was recorded 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 +S3SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[in] Value The 8-bit value to write. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[in] Value The 16-bit value to write. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[in] Value The 16-bit value to write. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Buffer The pointer to the buffer to store the bytes read from the SMBUS. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[out] Buffer The pointer to the buffer to store the bytes read from the SMBUS. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + 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[in] SmBusAddress The address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param[in] WriteBuffer The pointer to the buffer of bytes to write to the SMBUS. + @param[out] ReadBuffer The pointer to the buffer of bytes to read from the SMBUS. + @param[out] Status The 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 + was recorded in the Host Status Register bit. Device errors are a result + of a transaction collision, illegal command field, unclaimed cycle + (host initiated), or bus error (collision). + 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 +S3SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *WriteBuffer, + OUT VOID *ReadBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3StallLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3StallLib.h new file mode 100644 index 0000000..fee77c4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/S3StallLib.h @@ -0,0 +1,39 @@ +/** @file + Stall Services that perform stalls 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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __S3_STALL_LIB_H__ +#define __S3_STALL_LIB_H__ + +/** + Stalls the CPU for at least the given number of microseconds 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[in] MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds. + +**/ +UINTN +EFIAPI +S3Stall ( + IN UINTN MicroSeconds + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SafeIntLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SafeIntLib.h new file mode 100644 index 0000000..7fc17aa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SafeIntLib.h @@ -0,0 +1,3030 @@ +/** @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. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ +#ifndef __INT_SAFE_LIB_H__ +#define __INT_SAFE_LIB_H__ + +// +// It is common for -1 to be used as an error value +// +#define INT8_ERROR ((INT8) -1) +#define UINT8_ERROR MAX_UINT8 +#define CHAR8_ERROR ((CHAR8)(MAX_INT8)) +#define INT16_ERROR ((INT16) -1) +#define UINT16_ERROR MAX_UINT16 +#define CHAR16_ERROR MAX_UINT16 +#define INT32_ERROR ((INT32) -1) +#define UINT32_ERROR MAX_UINT32 +#define INT64_ERROR ((INT64) -1) +#define UINT64_ERROR MAX_UINT64 +#define INTN_ERROR ((INTN) -1) +#define UINTN_ERROR MAX_UINTN + +// +// CHAR16 is defined to be the same as UINT16, so for CHAR16 +// operations redirect to the UINT16 ones: +// +#define SafeInt8ToChar16 SafeInt8ToUint16 +#define SafeInt16ToChar16 SafeInt16ToUint16 +#define SafeInt32ToChar16 SafeInt32ToUint16 +#define SafeUint32ToChar16 SafeUint32ToUint16 +#define SafeInt64ToChar16 SafeInt64ToUint16 +#define SafeUint64ToChar16 SafeUint64ToUint16 +#define SafeIntnToChar16 SafeIntnToUint16 +#define SafeUintnToChar16 SafeUintnToUint16 + +#define SafeChar16ToInt8 SafeUint16ToInt8 +#define SafeChar16ToUint8 SafeUint16ToUint8 +#define SafeChar16ToChar8 SafeUint16ToChar8 +#define SafeChar16ToInt16 SafeUint16ToInt16 + +#define SafeChar16Mult SafeUint16Mult +#define SafeChar16Sub SafeUint16Sub +#define SafeChar16Add SafeUint16Add + +// +// 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// 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 + ); + +/** + 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 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 + ); + +/** + 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 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 + ); + +// +// 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif // __INT_SAFE_LIB_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SalLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SalLib.h new file mode 100644 index 0000000..3b5c0c3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SalLib.h @@ -0,0 +1,59 @@ +/** @file + Provides library services to make SAL Calls. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SAL_LIB__ +#define __SAL_LIB__ + +#include + +/** + Makes a SAL procedure call. + + This is a wrapper function to make a SAL procedure call. + No parameter checking is performed on the 8 input parameters, + but there are some common rules that the caller should follow + when making a SAL call. Any address passed to SAL as buffers + for return parameters must be 8-byte aligned. Unaligned + addresses may cause undefined results. For those parameters + defined as reserved or some fields defined as reserved must be + zero filled or the invalid argument return value may be returned + or undefined result may occur during the execution of the procedure. + This function is only available on Intel Itanium-based platforms. + + @param Index The SAL procedure Index number + @param Arg2 The 2nd parameter for SAL procedure calls + @param Arg3 The 3rd parameter for SAL procedure calls + @param Arg4 The 4th parameter for SAL procedure calls + @param Arg5 The 5th parameter for SAL procedure calls + @param Arg6 The 6th parameter for SAL procedure calls + @param Arg7 The 7th parameter for SAL procedure calls + @param Arg8 The 8th parameter for SAL procedure calls + + @return SAL returned registers. + +**/ +SAL_RETURN_REGS +EFIAPI +SalCall ( + IN UINT64 Index, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SerialPortLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SerialPortLib.h new file mode 100644 index 0000000..e10b0d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SerialPortLib.h @@ -0,0 +1,180 @@ +/** @file + This library class provides common serial I/O port functions. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2014, ARM Ltd. All rights reserved. +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SERIAL_PORT_LIB__ +#define __SERIAL_PORT_LIB__ + +#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 + ); + +/** + 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 Pointer to the data buffer to be written. + @param NumberOfBytes 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 + ); + + +/** + 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 Pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes Number of bytes which will be read. + + @retval 0 Read data failed, no data is to be read. + @retval >0 Actual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmbusLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmbusLib.h new file mode 100644 index 0000000..e8c8333 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmbusLib.h @@ -0,0 +1,497 @@ +/** @file + Provides library functions to access SMBUS devices. Libraries of this class + must be ported to a specific SMBUS controller. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMBUS_LIB__ +#define __SMBUS_LIB__ + +/** + Macro that converts SMBUS slave address, SMBUS command, SMBUS data length, + and PEC to a value that can be passed to the SMBUS Library functions. + + Computes an address that is compatible with the SMBUS Library functions. + The unused upper bits of SlaveAddress, Command, and Length are stripped + prior to the generation of the address. + + @param SlaveAddress SMBUS Slave Address. Range 0..127. + @param Command SMBUS Command. Range 0..255. + @param Length SMBUS Data Length. Range 0..32. + @param Pec TRUE if Packet Error Checking is enabled. Otherwise FALSE. + +**/ +#define SMBUS_LIB_ADDRESS(SlaveAddress,Command,Length,Pec) \ + ( ((Pec) ? BIT22: 0) | \ + (((SlaveAddress) & 0x7f) << 1) | \ + (((Command) & 0xff) << 8) | \ + (((Length) & 0x3f) << 16) \ + ) + +/** + Macro that returns the SMBUS Slave Address value from an SmBusAddress Parameter value. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC +**/ +#define SMBUS_LIB_SLAVE_ADDRESS(SmBusAddress) (((SmBusAddress) >> 1) & 0x7f) + +/** + Macro that returns the SMBUS Command value from an SmBusAddress Parameter value. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC +**/ +#define SMBUS_LIB_COMMAND(SmBusAddress) (((SmBusAddress) >> 8) & 0xff) + +/** + Macro that returns the SMBUS Data Length value from an SmBusAddress Parameter value. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC +**/ +#define SMBUS_LIB_LENGTH(SmBusAddress) (((SmBusAddress) >> 16) & 0x3f) + +/** + Macro that returns the SMBUS PEC value from an SmBusAddress Parameter value. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC +**/ +#define SMBUS_LIB_PEC(SmBusAddress) ((BOOLEAN) (((SmBusAddress) & BIT22) != 0)) + +/** + Macro that returns the set of reserved bits from an SmBusAddress Parameter value. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC +**/ +#define SMBUS_LIB_RESERVED(SmBusAddress) ((SmBusAddress) & ~(BIT23 - 2)) + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmiHandlerProfileLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmiHandlerProfileLib.h new file mode 100644 index 0000000..91abd64 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmiHandlerProfileLib.h @@ -0,0 +1,87 @@ +/** @file + Provides services to log the SMI handler registration. + + This API provides services for the SMM Child Dispatch Protocols provider, + to register SMI handler information to SmmCore. + + NOTE: + There is no need to update the consumers of SMST->SmiHandlerRegister() or + the consumers of SMM Child Dispatch Protocols. + The SmmCore (who produces SMST) should have ability to register such + information directly. + The SmmChildDispatcher (who produces SMM Child Dispatch Protocols) should + be responsible to call the services to register information to SMM Core. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMI_HANDLER_PROFILE_LIB_H__ +#define __SMI_HANDLER_PROFILE_LIB_H__ + +#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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmIoLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmIoLib.h new file mode 100644 index 0000000..9fa587f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmIoLib.h @@ -0,0 +1,42 @@ +/** @file + Provides services for SMM IO Operation. + + The SMM IO Library provides function for checking if IO resource is accessible inside of SMM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_IO_LIB_H_ +#define _SMM_IO_LIB_H_ + +/** + 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 + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmLib.h new file mode 100644 index 0000000..d42127a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmLib.h @@ -0,0 +1,89 @@ +/** @file + Library class name: SmmLib + + SMM Library Services that abstracts both S/W SMI generation and detection. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMM_LIB_H__ +#define __SMM_LIB_H__ + + +/** + Triggers an SMI at boot time. + + This function triggers a software SMM interrupt at boot time. + +**/ +VOID +EFIAPI +TriggerBootServiceSoftwareSmi ( + VOID + ); + + +/** + Triggers an SMI at run time. + + This function triggers a software SMM interrupt at run time. + +**/ +VOID +EFIAPI +TriggerRuntimeSoftwareSmi ( + VOID + ); + + +/** + Test if a boot time software SMI happened. + + This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and + it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE. + + @retval TRUE A software SMI triggered at boot time happened. + @retval FLASE No software SMI happened, or the software SMI was triggered at run time. + +**/ +BOOLEAN +EFIAPI +IsBootServiceSoftwareSmi ( + VOID + ); + + +/** + Test if a run time software SMI happened. + + This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and + it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE. + + @retval TRUE A software SMI triggered at run time happened. + @retval FLASE No software SMI happened or the software SMI was triggered at boot time. + +**/ +BOOLEAN +EFIAPI +IsRuntimeSoftwareSmi ( + VOID + ); + +/** + Clear APM SMI Status Bit; Set the EOS bit. + +**/ +VOID +EFIAPI +ClearSmi ( + VOID + ); +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmMemLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmMemLib.h new file mode 100644 index 0000000..13e9fc7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmMemLib.h @@ -0,0 +1,138 @@ +/** @file + Provides services for SMM Memory Operation. + + The SMM Mem Library provides function for checking if buffer is outside SMRAM and valid. + It also provides functions for copy data from SMRAM to non-SMRAM, from non-SMRAM to SMRAM, + from non-SMRAM to non-SMRAM, or set data in non-SMRAM. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_MEM_LIB_H_ +#define _SMM_MEM_LIB_H_ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 DesinationBuffer 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 + ); + +/** + 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 DesinationBuffer 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmPeriodicSmiLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmPeriodicSmiLib.h new file mode 100644 index 0000000..f7b9f31 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmPeriodicSmiLib.h @@ -0,0 +1,184 @@ +/** @file + Provides services to enable and disable periodic SMI handlers. + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PERIODIC_SMI_LIB_H__ +#define __PERIODIC_SMI_LIB_H__ + +#define PERIODIC_SMI_LIBRARY_ANY_CPU 0xffffffff + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 seperate 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 + ); + +/** + This function is a prototype for a periodic SMI handler function + that may be enabled with PeriodicSmiEnable() and disabled with + PeriodicSmiDisable(). + + @param[in] Context Content registered with PeriodicSmiEnable(). + @param[in] ElapsedTime The actual time in 100ns units elapsed since + this function was called. A value of 0 indicates + an unknown amount of time. + +**/ +typedef +VOID +(EFIAPI *PERIODIC_SMI_LIBRARY_HANDLER) ( + IN CONST VOID *Context OPTIONAL, + IN UINT64 ElapsedTime + ); + +/** + 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 givien 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 speficied 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmServicesTableLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmServicesTableLib.h new file mode 100644 index 0000000..c475a39 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SmmServicesTableLib.h @@ -0,0 +1,43 @@ +/** @file + Provides a service to retrieve a pointer to the SMM Services Table. + Only available to SMM module types. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMM_SERVICES_TABLE_LIB_H__ +#define __SMM_SERVICES_TABLE_LIB_H__ + +#include + +/// +/// Cache pointer to the SMM Services Table +/// +extern EFI_SMM_SYSTEM_TABLE2 *gSmst; + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h new file mode 100644 index 0000000..cb6db90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h @@ -0,0 +1,131 @@ +/** @file + Module entry point library for Standalone MM Drivers. + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+Copyright (c) 2018, Linaro, Limited. All rights reserved.
+ +This program and the accompanying materials are licensed and made available +under the terms and conditions of the BSD License which accompanies this +distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +/// +/// Declare the PI Specification Revision that this driver requires to execute +/// correctly. +/// +extern CONST UINT32 _gMmRevision; + +/** + 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 MmSystemTable->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 EFI_MM_SYSTEM_TABLE *MmSystemTable + ); + + +/** + Auto generated function that calls the library constructors for all of the + module's dependent libraries. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of library constructors for the set of library + instances that a module depends on. This includes library instances that a + module depends on directly and library instances that a module depends on + indirectly through other libraries. This function is auto generated by build + tools and those build tools are responsible for collecting the set of library + instances, determine which ones have constructors, and calling the library + constructors in the proper order based upon each of the library instances own + dependencies. + + @param ImageHandle The image handle of the Standalone MM Driver. + @param MmSystemTable A pointer to the MM System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ); + + +/** + Auto generated function that calls the library descructors for all of the + module's dependent libraries. + + This function may be called by _ModuleEntryPoint(). + This function calls the set of library destructors for the set of library + instances that a module depends on. This includes library instances that a + module depends on directly and library instances that a module depends on + indirectly through other libraries. + This function is auto generated by build tools and those build tools are + responsible for collecting the set of library instances, determine which ones + have destructors, and calling the library destructors in the proper order + based upon each of the library instances own dependencies. + + @param ImageHandle The image handle of the Standalone MM Driver. + @param MmSystemTable A pointer to the MM System Table. + +**/ +VOID +EFIAPI +ProcessLibraryDestructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ); + + +/** + Auto generated function that calls a set of module entry points. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of module entry points. + This function is auto generated by build tools and those build tools are + responsible for collecting the module entry points and calling them in a + specified order. + + @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 executed normally. + @retval !EFI_SUCCESS The Standalone MM Driver failed to execute normally. +**/ +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SynchronizationLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SynchronizationLib.h new file mode 100644 index 0000000..915f448 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/SynchronizationLib.h @@ -0,0 +1,293 @@ +/** @file + Provides synchronization functions. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SYNCHRONIZATION_LIB__ +#define __SYNCHRONIZATION_LIB__ + +/// +/// Definitions for SPIN_LOCK +/// +typedef volatile UINTN SPIN_LOCK; + + +/** + 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 + ); + + +/** + 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 in release state. + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *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 lock. + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *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 + ); + + +/** + 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 + ); + + +/** + Performs an atomic increment of a 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 + ); + + +/** + Performs an atomic decrement of a 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/TimerLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/TimerLib.h new file mode 100644 index 0000000..f0d898a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/TimerLib.h @@ -0,0 +1,114 @@ +/** @file + Provides calibrated delay and performance counter services. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TIMER_LIB__ +#define __TIMER_LIB__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiApplicationEntryPoint.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiApplicationEntryPoint.h new file mode 100644 index 0000000..c245d98 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiApplicationEntryPoint.h @@ -0,0 +1,154 @@ +/** @file + Module entry point library for UEFI Applications. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_APPLICATION_ENTRY_POINT_H__ +#define __UEFI_APPLICATION_ENTRY_POINT_H__ + +/// +/// Declare the EFI/UEFI Specification Revision to which this driver is implemented +/// +extern CONST UINT32 _gUefiDriverRevision; + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of library constructors for the set of library instances + that a module depends on. This includes library instances that a module depends on + directly and library instances that a module depends on indirectly through other libraries. + This function is autogenerated by build tools and those build tools are responsible for + collecting the set of library instances, determine which ones have constructors, and + calling the library constructors in the proper order based upon each of the library + instances own dependencies. + + @param ImageHandle The image handle of the UEFI Application. + @param SystemTable A pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Autogenerated function that calls the library descructors for all of the module's + dependent libraries. + + This function may be called by _ModuleEntryPoint()or Exit(). + This function calls the set of library destructors for the set of library instances + that a module depends on. This includes library instances that a module depends on + directly and library instances that a module depends on indirectly through other libraries. + This function is autogenerated by build tools and those build tools are responsible + for collecting the set of library instances, determine which ones have destructors, + and calling the library destructors in the proper order based upon each of the library + instances own dependencies. + + @param ImageHandle The image handle of the UEFI Application. + @param SystemTable A pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryDestructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + This function calls the set of module entry points. It must be called by _ModuleEntryPoint(). + + This function is autogenerated by build tools and those build tools are + responsible for collecting the module entry points and calling them in a specified order. + + @param ImageHandle The image handle of the UEFI Application. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The UEFI Application executed normally. + @retval !EFI_SUCCESS The UEFI Application failed to execute normally. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiBootServicesTableLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiBootServicesTableLib.h new file mode 100644 index 0000000..b382a8d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiBootServicesTableLib.h @@ -0,0 +1,34 @@ +/** @file + Provides a service to retrieve a pointer to the EFI Boot Services Table. + Only available to DXE and UEFI module types. + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_BOOT_SERVICES_TABLE_LIB_H__ +#define __UEFI_BOOT_SERVICES_TABLE_LIB_H__ + +/// +/// Cache the Image Handle +/// +extern EFI_HANDLE gImageHandle; + +/// +/// Cache pointer to the EFI System Table +/// +extern EFI_SYSTEM_TABLE *gST; + +/// +/// Cache pointer to the EFI Boot Services Table +/// +extern EFI_BOOT_SERVICES *gBS; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDecompressLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDecompressLib.h new file mode 100644 index 0000000..391c0c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDecompressLib.h @@ -0,0 +1,108 @@ +/** @file + Provides services to decompress a buffer using the UEFI Decompress algorithm. + + The UEFI Decompress Library enables the decompression of objects that + were compressed using the UEFI compression scheme. The UEFI Decompress + Library is independent of environment and requires the caller to allocate + all required memory buffers. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_DECPOMPRESS_LIB_H__ +#define __UEFI_DECPOMPRESS_LIB_H__ + +/** + 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 + ); + +/** + 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. + + @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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDriverEntryPoint.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDriverEntryPoint.h new file mode 100644 index 0000000..bbb48a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiDriverEntryPoint.h @@ -0,0 +1,195 @@ +/** @file + Module entry point library for UEFI drivers, DXE Drivers, DXE Runtime Drivers, + and DXE SMM Drivers. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +/// +///Declare the PI Specification Revision that this driver requires to execute correctly. +/// +extern CONST UINT32 _gDxeRevision; + +/// +/// Declare the EFI/UEFI Specification Revision to which this driver is implemented +/// +extern CONST UINT32 _gUefiDriverRevision; + +/// +/// Declare the number of unload handler in the image. +/// +extern CONST UINT8 _gDriverUnloadImageCount; + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + Invokes the library destructors for all dependent libraries and terminates the + DXE Driver, DXE Runtime Driver, DXE SMM Driver, or UEFI Driver. + + This function calls ProcessLibraryDestructorList() and the EFI Boot Service Exit() + with a status specified by Status. + + @param Status Status returned by the driver that is exiting. + +**/ +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ); + + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of library constructors for the set of library instances + that a module depends on. This includes library instances that a module depends on + directly and library instances that a module depends on indirectly through other libraries. + This function is autogenerated by build tools and those build tools are responsible + for collecting the set of library instances, determine which ones have constructors, + and calling the library constructors in the proper order based upon each of the library + instances own dependencies. + + @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. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Autogenerated function that calls the library descructors for all of the module's + dependent libraries. + + This function may be called by _ModuleEntryPoint() or ExitDriver(). + This function calls the set of library destructors for the set of library instances + that a module depends on. This includes library instances that a module depends on + directly and library instances that a module depends on indirectly through other libraries. + This function is autogenerated by build tools and those build tools are responsible for + collecting the set of library instances, determine which ones have destructors, and calling + the library destructors in the proper order based upon each of the library instances own dependencies. + + @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. + +**/ +VOID +EFIAPI +ProcessLibraryDestructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Autogenerated function that calls a set of module entry points. + + This function must be called by _ModuleEntryPoint(). + This function calls the set of module entry points. + This function is autogenerated by build tools and those build tools are responsible + for collecting the module entry points and calling them in a specified order. + + @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 executed normally. + @retval !EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM Driver, or UEFI Driver failed to execute normally. +**/ +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Autogenerated function that calls a set of module unload handlers. + + This function must be called from the unload handler registered by _ModuleEntryPoint(). + This function calls the set of module unload handlers. + This function is autogenerated by build tools and those build tools are responsible + for collecting the module unload handlers and calling them in a specified order. + + @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, DXE SMM Driver, or UEFI Driver. + + @retval EFI_SUCCESS The unload handlers executed normally. + @retval !EFI_SUCCESS The unload handlers failed to execute normally. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiLib.h new file mode 100644 index 0000000..5998ee0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiLib.h @@ -0,0 +1,1802 @@ +/** @file + Provides library functions for common UEFI operations. Only available to DXE + and UEFI module types. + + 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. + + Note that a reserved macro named MDEPKG_NDEBUG is introduced for the intention + of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is + defined, then debug and assert related macros wrapped by it are the NULL implementations. + +Copyright (c) 2019, NVIDIA Corporation. All rights reserved. +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_LIB_H__ +#define __UEFI_LIB_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/// +/// Unicode String Table +/// +typedef struct { + CHAR8 *Language; + CHAR16 *UnicodeString; +} EFI_UNICODE_STRING_TABLE; + +/// +/// EFI Lock Status +/// +typedef enum { + EfiLockUninitialized = 0, + EfiLockReleased = 1, + EfiLockAcquired = 2 +} EFI_LOCK_STATE; + +/// +/// EFI Lock +/// +typedef struct { + EFI_TPL Tpl; + EFI_TPL OwnerTpl; + EFI_LOCK_STATE Lock; +} EFI_LOCK; + +/** + Macro that returns the number of 100 ns units for a specified number of microseconds. + This is useful for managing EFI timer events. + + @param Microseconds The number of microseconds. + + @return The number of 100 ns units equivalent to the number of microseconds specified + by Microseconds. + +**/ +#define EFI_TIMER_PERIOD_MICROSECONDS(Microseconds) MultU64x32((UINT64)(Microseconds), 10) + +/** + Macro that returns the number of 100 ns units for a specified number of milliseconds. + This is useful for managing EFI timer events. + + @param Milliseconds The number of milliseconds. + + @return The number of 100 ns units equivalent to the number of milliseconds specified + by Milliseconds. + +**/ +#define EFI_TIMER_PERIOD_MILLISECONDS(Milliseconds) MultU64x32((UINT64)(Milliseconds), 10000) + +/** + Macro that returns the number of 100 ns units for a specified number of seconds. + This is useful for managing EFI timer events. + + @param Seconds The number of seconds. + + @return The number of 100 ns units equivalent to the number of seconds specified + by Seconds. + +**/ +#define EFI_TIMER_PERIOD_SECONDS(Seconds) MultU64x32((UINT64)(Seconds), 10000000) + +/** + Macro that returns the a pointer to the next EFI_MEMORY_DESCRIPTOR in an array + returned from GetMemoryMap(). + + @param MemoryDescriptor A pointer to an EFI_MEMORY_DESCRIPTOR. + + @param Size The size, in bytes, of the current EFI_MEMORY_DESCRIPTOR. + + @return A pointer to the next EFI_MEMORY_DESCRIPTOR. + +**/ +#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ + ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size))) + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 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 resources 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 + ); + +/** + 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 resources to signal the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventSignal ( + IN CONST EFI_GUID *Name + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 The EFI TPL associated with the lock. + + @return The lock. + +**/ +EFI_LOCK * +EFIAPI +EfiInitializeLock ( + IN OUT EFI_LOCK *Lock, + IN EFI_TPL Priority + ); + +/** + Initializes a basic mutual exclusion lock. + + This macro initializes the contents of a basic mutual exclusion lock to the + released state. 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. + + @param Priority The task priority level of the lock. + + @return The lock. + +**/ +#define EFI_INITIALIZE_LOCK_VARIABLE(Priority) \ + {Priority, TPL_APPLICATION, EfiLockReleased } + + +/** + Macro that calls DebugAssert() if an EFI_LOCK structure is not in the locked state. + + If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED + bit of PcdDebugProperyMask is set, then this macro evaluates the EFI_LOCK + structure specified by Lock. If Lock is not in the locked state, then + DebugAssert() is called passing in the source filename, source line number, + and Lock. + + If Lock is NULL, then ASSERT(). + + @param LockParameter A pointer to the lock to acquire. + +**/ +#if !defined(MDEPKG_NDEBUG) + #define ASSERT_LOCKED(LockParameter) \ + do { \ + if (DebugAssertEnabled ()) { \ + ASSERT (LockParameter != NULL); \ + if ((LockParameter)->Lock != EfiLockAcquired) { \ + _ASSERT (LockParameter not locked); \ + } \ + } \ + } while (FALSE) +#else + #define ASSERT_LOCKED(LockParameter) +#endif + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 the 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#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 + ); + +/** + [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 + ); +#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. + + @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 +GetVariable2 ( + IN CONST CHAR16 *Name, + IN CONST EFI_GUID *Guid, + OUT VOID **Value, + OUT UINTN *Size OPTIONAL + ); + +/** + 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. + + @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 +GetEfiGlobalVariable2 ( + IN CONST CHAR16 *Name, + OUT VOID **Value, + OUT UINTN *Size OPTIONAL + ); + +/** 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 + ); + +/** + 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, + ... + ); + +/** + 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 + ... + ); + +/** + 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 + ); + +/** + 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 + ); + +// +// Functions that abstract early Framework contamination of UEFI. +// +/** + 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 + ); + +/** + 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 + ); + +/** + 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 The event was created. + @retval Other The event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventLegacyBoot ( + OUT EFI_EVENT *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 The event was created. + @retval Other The 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 + ); + +/** + 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 The event was created. + @retval Other The event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventReadyToBoot ( + OUT EFI_EVENT *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 The event was created. + @retval Other The 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 + ); + +/** + 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 + ); + +/** + 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 backward + 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 + ); + +/** + 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 ... The variable argument list whose contents are accessed based + on the format string specified by Format. + + @return Number of Unicode characters printed to ConOut. + +**/ +UINTN +EFIAPI +Print ( + IN CONST CHAR16 *Format, + ... + ); + +/** + 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 ... The variable argument list whose contents are accessed based + on the format string specified by Format. + + @return Number of Unicode characters printed to StdErr. + +**/ +UINTN +EFIAPI +ErrorPrint ( + IN CONST CHAR16 *Format, + ... + ); + +/** + 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 ... The variable argument list whose contents are accessed based + on the format string specified by Format. + + @return Number of ASCII characters printed to ConOut. + +**/ +UINTN +EFIAPI +AsciiPrint ( + IN CONST CHAR8 *Format, + ... + ); + +/** + 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 ... The variable argument list whose contents are accessed based + on the format string specified by Format. + + @return Number of ASCII characters printed to ConErr. + +**/ +UINTN +EFIAPI +AsciiErrorPrint ( + IN CONST CHAR8 *Format, + ... + ); + + +/** + 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 + 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. + 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 X coordinate to print the string. + @param PointY 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 ... 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, + ... + ); + +/** + 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 + 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. + If Format is NULL, then ASSERT(). + If gST->ConsoleOutputHandle is NULL, then ASSERT(). + + @param PointX X coordinate to print the string. + @param PointY 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 ... The 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, + ... + ); + + +/** + 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 completed successfully. + @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 + ); + + +/** + 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 + ); + + +/** + 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 completed successfully. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in the 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 + ); + + +/** + 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 + ); + + +/** + 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 completed successfully. + @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 + ); + + +/** + 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 + ); + + +/** + 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 completed successfully. + @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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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, + ... + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeLib.h new file mode 100644 index 0000000..4d72d55 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeLib.h @@ -0,0 +1,587 @@ +/** @file + Provides library functions for each of the UEFI Runtime Services. + Only available to DXE and UEFI module types. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __UEFI_RUNTIME_LIB__ +#define __UEFI_RUNTIME_LIB__ + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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, as 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 The size in bytes of Data-Buffer. + @param Data Point 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_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 + ); + +/** + 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 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 + ); + +/** + 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 EfiResetPlatformSpecific the data buffer also starts with a Null-terminated + string that is followed by an EFI_GUID that describes the specific type of reset to perform. +**/ +VOID +EFIAPI +EfiResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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 Successfully executed the function. + @retval !EFI_SUCCESS Failed to execute the function. + +**/ +EFI_STATUS +EFIAPI +EfiConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ); + +/** + 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 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 A 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 is NULL, or an incompatible set of flags were + set in the capsule header. + @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 + ); + + +/** + 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 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 + ); + + +/** + 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 + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h new file mode 100644 index 0000000..609f2ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h @@ -0,0 +1,32 @@ +/** @file + Provides a service to retrieve a pointer to the EFI Runtime Services Table. + + This library does not contain any functions or macros. It simply exports the + global variable gRT that is a pointer to the EFI Runtime Services Table as defined + in the UEFI Specification. The global variable gRT must be preinitialized to NULL. + The library constructor must set gRT to point at the EFI Runtime Services Table so + it is available at the module's entry point. Since there is overhead in initializing + this global variable, only those modules that actually require access to the EFI + Runtime Services Table should use this library. + Only available to DXE and UEFI module types. + +Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_RUNTIME_SERVICES_TABLE_LIB_H__ +#define __UEFI_RUNTIME_SERVICES_TABLE_LIB_H__ + +/// +/// Cached copy of the EFI Runtime Services Table +/// +extern EFI_RUNTIME_SERVICES *gRT; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiScsiLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiScsiLib.h new file mode 100644 index 0000000..c849b40 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiScsiLib.h @@ -0,0 +1,1181 @@ +/** @file + Provides the functions to submit Scsi commands defined in SCSI-2 specification for SCSI devices. + + This library class provides the functions to submit SCSI commands defined in SCSI-2 specification + for hard drive, CD and DVD devices that are the most common SCSI boot targets used by UEFI platforms. + This library class depends on SCSI I/O Protocol defined in UEFI Specification and SCSI-2 industry standard. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SCSI_LIB_H__ +#define __SCSI_LIB_H__ + +#include + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiUsbLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiUsbLib.h new file mode 100644 index 0000000..a2eab69 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Library/UefiUsbLib.h @@ -0,0 +1,563 @@ +/** @file + 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 - 2008, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef __USB_DXE_LIB_H__ +#define __USB_DXE_LIB_H__ + +#include + +/** + Get the descriptor of the specified USB HID interface. + + Submit a UsbGetHidDescriptor() 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 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 + ); + + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiBootMode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiBootMode.h new file mode 100644 index 0000000..793833b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiBootMode.h @@ -0,0 +1,42 @@ +/** @file + Present the boot mode values in PI. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2.1A + +**/ + +#ifndef __PI_BOOT_MODE_H__ +#define __PI_BOOT_MODE_H__ + +/// +/// EFI boot mode +/// +typedef UINT32 EFI_BOOT_MODE; + +// +// 0x21 - 0xf..f are reserved. +// +#define BOOT_WITH_FULL_CONFIGURATION 0x00 +#define BOOT_WITH_MINIMAL_CONFIGURATION 0x01 +#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02 +#define BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03 +#define BOOT_WITH_DEFAULT_SETTINGS 0x04 +#define BOOT_ON_S4_RESUME 0x05 +#define BOOT_ON_S5_RESUME 0x06 +#define BOOT_WITH_MFG_MODE_SETTINGS 0x07 +#define BOOT_ON_S2_RESUME 0x10 +#define BOOT_ON_S3_RESUME 0x11 +#define BOOT_ON_FLASH_UPDATE 0x12 +#define BOOT_IN_RECOVERY_MODE 0x20 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDependency.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDependency.h new file mode 100644 index 0000000..c8daac1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDependency.h @@ -0,0 +1,47 @@ +/** @file + Present the dependency expression values in PI. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.0 + +**/ +#ifndef __PI_DEPENDENCY_H__ +#define __PI_DEPENDENCY_H__ + +/// +/// If present, this must be the first and only opcode, +/// EFI_DEP_BEFORE may be used by DXE and SMM drivers. +/// +#define EFI_DEP_BEFORE 0x00 + +/// +/// If present, this must be the first and only opcode, +/// EFI_DEP_AFTER may be used by DXE and SMM drivers. +/// +#define EFI_DEP_AFTER 0x01 + +#define EFI_DEP_PUSH 0x02 +#define EFI_DEP_AND 0x03 +#define EFI_DEP_OR 0x04 +#define EFI_DEP_NOT 0x05 +#define EFI_DEP_TRUE 0x06 +#define EFI_DEP_FALSE 0x07 +#define EFI_DEP_END 0x08 + + +/// +/// If present, this must be the first opcode, +/// EFI_DEP_SOR is only used by DXE driver. +/// +#define EFI_DEP_SOR 0x09 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDxeCis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDxeCis.h new file mode 100644 index 0000000..cd79eff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiDxeCis.h @@ -0,0 +1,744 @@ +/** @file + Include file matches things in PI. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.6 + +**/ + +#ifndef __PI_DXECIS_H__ +#define __PI_DXECIS_H__ + +#include +#include + +/// +/// Global Coherencey Domain types - Memory type. +/// +typedef enum { + /// + /// A memory region that is visible to the boot processor. However, there are no system + /// components that are currently decoding this memory region. + /// + EfiGcdMemoryTypeNonExistent, + /// + /// A memory region that is visible to the boot processor. This memory region is being + /// decoded by a system component, but the memory region is not considered to be either + /// system memory or memory-mapped I/O. + /// + EfiGcdMemoryTypeReserved, + /// + /// A memory region that is visible to the boot processor. A memory controller is + /// currently decoding this memory region and the memory controller is producing a + /// tested system memory region that is available to the memory services. + /// + EfiGcdMemoryTypeSystemMemory, + /// + /// A memory region that is visible to the boot processor. This memory region is + /// currently being decoded by a component as memory-mapped I/O that can be used to + /// access I/O devices in the platform. + /// + EfiGcdMemoryTypeMemoryMappedIo, + /// + /// A memory region that is visible to the boot processor. + /// This memory supports byte-addressable non-volatility. + /// + EfiGcdMemoryTypePersistent, + // + // Keep original one for the compatibility. + // + EfiGcdMemoryTypePersistentMemory = EfiGcdMemoryTypePersistent, + /// + /// A memory region that provides higher reliability relative to other memory in the + /// system. If all memory has the same reliability, then this bit is not used. + /// + EfiGcdMemoryTypeMoreReliable, + EfiGcdMemoryTypeMaximum +} EFI_GCD_MEMORY_TYPE; + +/// +/// Global Coherencey Domain types - IO type. +/// +typedef enum { + /// + /// An I/O region that is visible to the boot processor. However, there are no system + /// components that are currently decoding this I/O region. + /// + EfiGcdIoTypeNonExistent, + /// + /// An I/O region that is visible to the boot processor. This I/O region is currently being + /// decoded by a system component, but the I/O region cannot be used to access I/O devices. + /// + EfiGcdIoTypeReserved, + /// + /// An I/O region that is visible to the boot processor. This I/O region is currently being + /// decoded by a system component that is producing I/O ports that can be used to access I/O devices. + /// + EfiGcdIoTypeIo, + EfiGcdIoTypeMaximum +} EFI_GCD_IO_TYPE; + +/// +/// The type of allocation to perform. +/// +typedef enum { + /// + /// The GCD memory space map is searched from the lowest address up to the highest address + /// looking for unallocated memory ranges. + /// + EfiGcdAllocateAnySearchBottomUp, + /// + /// The GCD memory space map is searched from the lowest address up + /// to the specified MaxAddress looking for unallocated memory ranges. + /// + EfiGcdAllocateMaxAddressSearchBottomUp, + /// + /// The GCD memory space map is checked to see if the memory range starting + /// at the specified Address is available. + /// + EfiGcdAllocateAddress, + /// + /// The GCD memory space map is searched from the highest address down to the lowest address + /// looking for unallocated memory ranges. + /// + EfiGcdAllocateAnySearchTopDown, + /// + /// The GCD memory space map is searched from the specified MaxAddress + /// down to the lowest address looking for unallocated memory ranges. + /// + EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdMaxAllocateType +} EFI_GCD_ALLOCATE_TYPE; + +/// +/// EFI_GCD_MEMORY_SPACE_DESCRIPTOR. +/// +typedef struct { + /// + /// The physical address of the first byte in the memory region. Type + /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function + /// description in the UEFI 2.0 specification. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + + /// + /// The number of bytes in the memory region. + /// + UINT64 Length; + + /// + /// The bit mask of attributes that the memory region is capable of supporting. The bit + /// mask of available attributes is defined in the GetMemoryMap() function description + /// in the UEFI 2.0 specification. + /// + UINT64 Capabilities; + /// + /// The bit mask of attributes that the memory region is currently using. The bit mask of + /// available attributes is defined in GetMemoryMap(). + /// + UINT64 Attributes; + /// + /// Type of the memory region. Type EFI_GCD_MEMORY_TYPE is defined in the + /// AddMemorySpace() function description. + /// + EFI_GCD_MEMORY_TYPE GcdMemoryType; + + /// + /// The image handle of the agent that allocated the memory resource described by + /// PhysicalStart and NumberOfBytes. If this field is NULL, then the memory + /// resource is not currently allocated. Type EFI_HANDLE is defined in + /// InstallProtocolInterface() in the UEFI 2.0 specification. + /// + EFI_HANDLE ImageHandle; + + /// + /// The device handle for which the memory resource has been allocated. If + /// ImageHandle is NULL, then the memory resource is not currently allocated. If this + /// field is NULL, then the memory resource is not associated with a device that is + /// described by a device handle. Type EFI_HANDLE is defined in + /// InstallProtocolInterface() in the UEFI 2.0 specification. + /// + EFI_HANDLE DeviceHandle; +} EFI_GCD_MEMORY_SPACE_DESCRIPTOR; + +/// +/// EFI_GCD_IO_SPACE_DESCRIPTOR. +/// +typedef struct { + /// + /// Physical address of the first byte in the I/O region. Type + /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function + /// description in the UEFI 2.0 specification. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + + /// + /// Number of bytes in the I/O region. + /// + UINT64 Length; + + /// + /// Type of the I/O region. Type EFI_GCD_IO_TYPE is defined in the + /// AddIoSpace() function description. + /// + EFI_GCD_IO_TYPE GcdIoType; + + /// + /// The image handle of the agent that allocated the I/O resource described by + /// PhysicalStart and NumberOfBytes. If this field is NULL, then the I/O + /// resource is not currently allocated. Type EFI_HANDLE is defined in + /// InstallProtocolInterface() in the UEFI 2.0 specification. + /// + EFI_HANDLE ImageHandle; + + /// + /// The device handle for which the I/O resource has been allocated. If ImageHandle + /// is NULL, then the I/O resource is not currently allocated. If this field is NULL, then + /// the I/O resource is not associated with a device that is described by a device handle. + /// Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI + /// 2.0 specification. + /// + EFI_HANDLE DeviceHandle; +} EFI_GCD_IO_SPACE_DESCRIPTOR; + + +/** + Adds reserved memory, system memory, or memory-mapped I/O resources to the + global coherency domain of the processor. + + @param GcdMemoryType The type of memory resource being added. + @param BaseAddress The physical address that is the start address + of the memory resource being added. + @param Length The size, in bytes, of the memory resource that + is being added. + @param Capabilities The bit mask of attributes that the memory + resource region supports. + + @retval EFI_SUCCESS The memory resource was added to the global + coherency domain of the processor. + @retval EFI_INVALID_PARAMETER GcdMemoryType is invalid. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to add + the memory resource to the global coherency + domain of the processor. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes + of the memory resource range specified by + BaseAddress and Length. + @retval EFI_ACCESS_DENIED One or more bytes of the memory resource range + specified by BaseAddress and Length conflicts + with a memory resource range that was previously + added to the global coherency domain of the processor. + @retval EFI_ACCESS_DENIED One or more bytes of the memory resource range + specified by BaseAddress and Length was allocated + in a prior call to AllocateMemorySpace(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADD_MEMORY_SPACE)( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ); + +/** + Allocates nonexistent memory, reserved memory, system memory, or memorymapped + I/O resources from the global coherency domain of the processor. + + @param GcdAllocateType The type of allocation to perform. + @param GcdMemoryType The type of memory resource being allocated. + @param Alignment The log base 2 of the boundary that BaseAddress must + be aligned on output. Align with 2^Alignment. + @param Length The size in bytes of the memory resource range that + is being allocated. + @param BaseAddress A pointer to a physical address to allocate. + @param Imagehandle The image handle of the agent that is allocating + the memory resource. + @param DeviceHandle The device handle for which the memory resource + is being allocated. + + @retval EFI_INVALID_PARAMETER GcdAllocateType is invalid. + @retval EFI_INVALID_PARAMETER GcdMemoryType is invalid. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_INVALID_PARAMETER BaseAddress is NULL. + @retval EFI_INVALID_PARAMETER ImageHandle is NULL. + @retval EFI_NOT_FOUND The memory resource request could not be satisfied. + No descriptor contains the desired space. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to allocate the memory + resource from the global coherency domain of the processor. + @retval EFI_SUCCESS The memory resource was allocated from the global coherency + domain of the processor. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_MEMORY_SPACE)( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ); + +/** + Frees nonexistent memory, reserved memory, system memory, or memory-mapped + I/O resources from the global coherency domain of the processor. + + @param BaseAddress The physical address that is the start address of the memory resource being freed. + @param Length The size in bytes of the memory resource range that is being freed. + + @retval EFI_SUCCESS The memory resource was freed from the global coherency domain of + the processor. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + @retval EFI_NOT_FOUND The memory resource range specified by BaseAddress and + Length was not allocated with previous calls to AllocateMemorySpace(). + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to free the memory resource + from the global coherency domain of the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_MEMORY_SPACE)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Removes reserved memory, system memory, or memory-mapped I/O resources from + the global coherency domain of the processor. + + @param BaseAddress The physical address that is the start address of the memory resource being removed. + @param Length The size in bytes of the memory resource that is being removed. + + @retval EFI_SUCCESS The memory resource was removed from the global coherency + domain of the processor. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + @retval EFI_NOT_FOUND One or more bytes of the memory resource range specified by + BaseAddress and Length was not added with previous calls to + AddMemorySpace(). + @retval EFI_ACCESS_DEFINED One or more bytes of the memory resource range specified by + BaseAddress and Length has been allocated with AllocateMemorySpace(). + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to remove the memory + resource from the global coherency domain of the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REMOVE_MEMORY_SPACE)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Retrieves the descriptor for a memory region containing a specified address. + + @param BaseAddress The physical address that is the start address of a memory region. + @param Descriptor A pointer to a caller allocated descriptor. + + @retval EFI_SUCCESS The descriptor for the memory resource region containing + BaseAddress was returned in Descriptor. + @retval EFI_INVALID_PARAMETER Descriptor is NULL. + @retval EFI_NOT_FOUND A memory resource range containing BaseAddress was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_SPACE_DESCRIPTOR)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ); + +/** + Modifies the attributes for a memory region in the global coherency domain of the + processor. + + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memory region. + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is + not available yet. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_MEMORY_SPACE_ATTRIBUTES)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +/** + Modifies the capabilities for a memory region in the global coherency domain of the + processor. + + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Capabilities The bit mask of capabilities that the memory region supports. + + @retval EFI_SUCCESS The capabilities were set for the memory region. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the + memory region attributes currently in use. + @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities + of the memory resource range. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_MEMORY_SPACE_CAPABILITIES) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ); + +/** + Returns a map of the memory resources in the global coherency domain of the + processor. + + @param NumberOfDescriptors A pointer to number of descriptors returned in the MemorySpaceMap buffer. + @param MemorySpaceMap A pointer to the array of EFI_GCD_MEMORY_SPACE_DESCRIPTORs. + + @retval EFI_SUCCESS The memory space map was returned in the MemorySpaceMap + buffer, and the number of descriptors in MemorySpaceMap was + returned in NumberOfDescriptors. + @retval EFI_INVALID_PARAMETER NumberOfDescriptors is NULL. + @retval EFI_INVALID_PARAMETER MemorySpaceMap is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate MemorySpaceMap. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_SPACE_MAP)( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ); + +/** + Adds reserved I/O or I/O resources to the global coherency domain of the processor. + + @param GcdIoType The type of I/O resource being added. + @param BaseAddress The physical address that is the start address of the I/O resource being added. + @param Length The size in bytes of the I/O resource that is being added. + + @retval EFI_SUCCESS The I/O resource was added to the global coherency domain of + the processor. + @retval EFI_INVALID_PARAMETER GcdIoType is invalid. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to add the I/O resource to + the global coherency domain of the processor. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the I/O + resource range specified by BaseAddress and Length. + @retval EFI_ACCESS_DENIED One or more bytes of the I/O resource range specified by + BaseAddress and Length conflicts with an I/O resource + range that was previously added to the global coherency domain + of the processor. + @retval EFI_ACCESS_DENIED One or more bytes of the I/O resource range specified by + BaseAddress and Length was allocated in a prior call to + AllocateIoSpace(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADD_IO_SPACE)( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param GcdAllocateType The type of allocation to perform. + @param GcdIoType The type of I/O resource being allocated. + @param Alignment The log base 2 of the boundary that BaseAddress must be aligned on output. + @param Length The size in bytes of the I/O resource range that is being allocated. + @param BaseAddress A pointer to a physical address. + @param Imagehandle The image handle of the agent that is allocating the I/O resource. + @param DeviceHandle The device handle for which the I/O resource is being allocated. + + @retval EFI_SUCCESS The I/O resource was allocated from the global coherency domain + of the processor. + @retval EFI_INVALID_PARAMETER GcdAllocateType is invalid. + @retval EFI_INVALID_PARAMETER GcdIoType is invalid. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_INVALID_PARAMETER BaseAddress is NULL. + @retval EFI_INVALID_PARAMETER ImageHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to allocate the I/O + resource from the global coherency domain of the processor. + @retval EFI_NOT_FOUND The I/O resource request could not be satisfied. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_IO_SPACE)( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ); + +/** + Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param BaseAddress The physical address that is the start address of the I/O resource being freed. + @param Length The size in bytes of the I/O resource range that is being freed. + + @retval EFI_SUCCESS The I/O resource was freed from the global coherency domain of the + processor. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the I/O resource + range specified by BaseAddress and Length. + @retval EFI_NOT_FOUND The I/O resource range specified by BaseAddress and Length + was not allocated with previous calls to AllocateIoSpace(). + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to free the I/O resource from + the global coherency domain of the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_IO_SPACE)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Removes reserved I/O or I/O resources from the global coherency domain of the + processor. + + @param BaseAddress A pointer to a physical address that is the start address of the I/O resource being + removed. + @param Length The size in bytes of the I/O resource that is being removed. + + @retval EFI_SUCCESS The I/O resource was removed from the global coherency domain + of the processor. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the I/O + resource range specified by BaseAddress and Length. + @retval EFI_NOT_FOUND One or more bytes of the I/O resource range specified by + BaseAddress and Length was not added with previous + calls to AddIoSpace(). + @retval EFI_ACCESS_DENIED One or more bytes of the I/O resource range specified by + BaseAddress and Length has been allocated with + AllocateIoSpace(). + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to remove the I/O + resource from the global coherency domain of the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REMOVE_IO_SPACE)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Retrieves the descriptor for an I/O region containing a specified address. + + @param BaseAddress The physical address that is the start address of an I/O region. + @param Descriptor A pointer to a caller allocated descriptor. + + @retval EFI_SUCCESS The descriptor for the I/O resource region containing + BaseAddress was returned in Descriptor. + @retval EFI_INVALID_PARAMETER Descriptor is NULL. + @retval EFI_NOT_FOUND An I/O resource range containing BaseAddress was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_IO_SPACE_DESCRIPTOR)( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ); + +/** + Returns a map of the I/O resources in the global coherency domain of the processor. + + @param NumberOfDescriptors A pointer to number of descriptors returned in the IoSpaceMap buffer. + @param MemorySpaceMap A pointer to the array of EFI_GCD_IO_SPACE_DESCRIPTORs. + + @retval EFI_SUCCESS The I/O space map was returned in the IoSpaceMap buffer, and + the number of descriptors in IoSpaceMap was returned in + NumberOfDescriptors. + @retval EFI_INVALID_PARAMETER NumberOfDescriptors is NULL. + @retval EFI_INVALID_PARAMETER IoSpaceMap is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate IoSpaceMap. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_IO_SPACE_MAP)( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ); + + + +/** + Loads and executed DXE drivers from firmware volumes. + + The Dispatch() function searches for DXE drivers in firmware volumes that have been + installed since the last time the Dispatch() service was called. It then evaluates + the dependency expressions of all the DXE drivers and loads and executes those DXE + drivers whose dependency expression evaluate to TRUE. This service must interact with + the Security Architectural Protocol to authenticate DXE drivers before they are executed. + This process is continued until no more DXE drivers can be executed. + + @retval EFI_SUCCESS One or more DXE driver were dispatched. + @retval EFI_NOT_FOUND No DXE drivers were dispatched. + @retval EFI_ALREADY_STARTED An attempt is being made to start the DXE Dispatcher recursively. + Thus, no action was taken. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISPATCH)( + VOID + ); + +/** + Clears the Schedule on Request (SOR) flag for a component that is stored in a firmware volume. + + @param FirmwareVolumeHandle The handle of the firmware volume that contains the file specified by FileName. + @param FileName A pointer to the name of the file in a firmware volume. + + @retval EFI_SUCCESS The DXE driver was found and its SOR bit was cleared. + @retval EFI_NOT_FOUND The DXE driver does not exist, or the DXE driver exists and its SOR + bit is not set. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCHEDULE)( + IN EFI_HANDLE FirmwareVolumeHandle, + IN CONST EFI_GUID *FileName + ); + +/** + Promotes a file stored in a firmware volume from the untrusted to the trusted state. + + @param FirmwareVolumeHandle The handle of the firmware volume that contains the file specified by FileName. + @param DriverName A pointer to the name of the file in a firmware volume. + + @return Status of promoting FFS from untrusted to trusted + state. + @retval EFI_NOT_FOUND The file was not found in the untrusted state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TRUST)( + IN EFI_HANDLE FirmwareVolumeHandle, + IN CONST EFI_GUID *FileName + ); + +/** + Creates a firmware volume handle for a firmware volume that is present in system memory. + + @param FirmwareVolumeHeader A pointer to the header of the firmware volume. + @param Size The size, in bytes, of the firmware volume. + @param FirmwareVolumeHandle On output, a pointer to the created handle. + + @retval EFI_SUCCESS The EFI_FIRMWARE_VOLUME_PROTOCOL and + EFI_DEVICE_PATH_PROTOCOL were installed onto + FirmwareVolumeHandle for the firmware volume described + by FirmwareVolumeHeader and Size. + @retval EFI_VOLUME_CORRUPTED The firmware volume described by FirmwareVolumeHeader + and Size is corrupted. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources available to produce the + EFI_FIRMWARE_VOLUME_PROTOCOL and EFI_DEVICE_PATH_PROTOCOL + for the firmware volume described by FirmwareVolumeHeader and Size. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PROCESS_FIRMWARE_VOLUME)( + IN CONST VOID *FirmwareVolumeHeader, + IN UINTN Size, + OUT EFI_HANDLE *FirmwareVolumeHandle + ); + +// +// DXE Services Table +// +#define DXE_SERVICES_SIGNATURE 0x565245535f455844ULL +#define DXE_SPECIFICATION_MAJOR_REVISION 1 +#define DXE_SPECIFICATION_MINOR_REVISION 60 +#define DXE_SERVICES_REVISION ((DXE_SPECIFICATION_MAJOR_REVISION<<16) | (DXE_SPECIFICATION_MINOR_REVISION)) + +typedef struct { + /// + /// The table header for the DXE Services Table. + /// This header contains the DXE_SERVICES_SIGNATURE and DXE_SERVICES_REVISION values. + /// + EFI_TABLE_HEADER Hdr; + + // + // Global Coherency Domain Services + // + EFI_ADD_MEMORY_SPACE AddMemorySpace; + EFI_ALLOCATE_MEMORY_SPACE AllocateMemorySpace; + EFI_FREE_MEMORY_SPACE FreeMemorySpace; + EFI_REMOVE_MEMORY_SPACE RemoveMemorySpace; + EFI_GET_MEMORY_SPACE_DESCRIPTOR GetMemorySpaceDescriptor; + EFI_SET_MEMORY_SPACE_ATTRIBUTES SetMemorySpaceAttributes; + EFI_GET_MEMORY_SPACE_MAP GetMemorySpaceMap; + EFI_ADD_IO_SPACE AddIoSpace; + EFI_ALLOCATE_IO_SPACE AllocateIoSpace; + EFI_FREE_IO_SPACE FreeIoSpace; + EFI_REMOVE_IO_SPACE RemoveIoSpace; + EFI_GET_IO_SPACE_DESCRIPTOR GetIoSpaceDescriptor; + EFI_GET_IO_SPACE_MAP GetIoSpaceMap; + + // + // Dispatcher Services + // + EFI_DISPATCH Dispatch; + EFI_SCHEDULE Schedule; + EFI_TRUST Trust; + // + // Service to process a single firmware volume found in a capsule + // + EFI_PROCESS_FIRMWARE_VOLUME ProcessFirmwareVolume; + // + // Extensions to Global Coherency Domain Services + // + EFI_SET_MEMORY_SPACE_CAPABILITIES SetMemorySpaceCapabilities; +} DXE_SERVICES; + +typedef DXE_SERVICES EFI_DXE_SERVICES; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareFile.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareFile.h new file mode 100644 index 0000000..8192c0c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareFile.h @@ -0,0 +1,501 @@ +/** @file + The firmware file related definitions in PI. + +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.6. + +**/ + + +#ifndef __PI_FIRMWARE_FILE_H__ +#define __PI_FIRMWARE_FILE_H__ + +#pragma pack(1) +/// +/// Used to verify the integrity of the file. +/// +typedef union { + struct { + /// + /// The IntegrityCheck.Checksum.Header field is an 8-bit checksum of the file + /// header. The State and IntegrityCheck.Checksum.File fields are assumed + /// to be zero and the checksum is calculated such that the entire header sums to zero. + /// + UINT8 Header; + /// + /// If the FFS_ATTRIB_CHECKSUM (see definition below) bit of the Attributes + /// field is set to one, the IntegrityCheck.Checksum.File field is an 8-bit + /// checksum of the file data. + /// If the FFS_ATTRIB_CHECKSUM bit of the Attributes field is cleared to zero, + /// the IntegrityCheck.Checksum.File field must be initialized with a value of + /// 0xAA. The IntegrityCheck.Checksum.File field is valid any time the + /// EFI_FILE_DATA_VALID bit is set in the State field. + /// + UINT8 File; + } Checksum; + /// + /// This is the full 16 bits of the IntegrityCheck field. + /// + UINT16 Checksum16; +} EFI_FFS_INTEGRITY_CHECK; + +/// +/// FFS_FIXED_CHECKSUM is the checksum value used when the +/// FFS_ATTRIB_CHECKSUM attribute bit is clear. +/// +#define FFS_FIXED_CHECKSUM 0xAA + +typedef UINT8 EFI_FV_FILETYPE; +typedef UINT8 EFI_FFS_FILE_ATTRIBUTES; +typedef UINT8 EFI_FFS_FILE_STATE; + +/// +/// File Types Definitions +/// +#define EFI_FV_FILETYPE_ALL 0x00 +#define EFI_FV_FILETYPE_RAW 0x01 +#define EFI_FV_FILETYPE_FREEFORM 0x02 +#define EFI_FV_FILETYPE_SECURITY_CORE 0x03 +#define EFI_FV_FILETYPE_PEI_CORE 0x04 +#define EFI_FV_FILETYPE_DXE_CORE 0x05 +#define EFI_FV_FILETYPE_PEIM 0x06 +#define EFI_FV_FILETYPE_DRIVER 0x07 +#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08 +#define EFI_FV_FILETYPE_APPLICATION 0x09 +#define EFI_FV_FILETYPE_MM 0x0A +#define EFI_FV_FILETYPE_SMM EFI_FV_FILETYPE_MM +#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B +#define EFI_FV_FILETYPE_COMBINED_MM_DXE 0x0C +#define EFI_FV_FILETYPE_COMBINED_SMM_DXE EFI_FV_FILETYPE_COMBINED_MM_DXE +#define EFI_FV_FILETYPE_MM_CORE 0x0D +#define EFI_FV_FILETYPE_SMM_CORE EFI_FV_FILETYPE_MM_CORE +#define EFI_FV_FILETYPE_MM_STANDALONE 0x0E +#define EFI_FV_FILETYPE_MM_CORE_STANDALONE 0x0F +#define EFI_FV_FILETYPE_OEM_MIN 0xc0 +#define EFI_FV_FILETYPE_OEM_MAX 0xdf +#define EFI_FV_FILETYPE_DEBUG_MIN 0xe0 +#define EFI_FV_FILETYPE_DEBUG_MAX 0xef +#define EFI_FV_FILETYPE_FFS_MIN 0xf0 +#define EFI_FV_FILETYPE_FFS_MAX 0xff +#define EFI_FV_FILETYPE_FFS_PAD 0xf0 +/// +/// FFS File Attributes. +/// +#define FFS_ATTRIB_LARGE_FILE 0x01 +#define FFS_ATTRIB_DATA_ALIGNMENT_2 0x02 +#define FFS_ATTRIB_FIXED 0x04 +#define FFS_ATTRIB_DATA_ALIGNMENT 0x38 +#define FFS_ATTRIB_CHECKSUM 0x40 + +/// +/// FFS File State Bits. +/// +#define EFI_FILE_HEADER_CONSTRUCTION 0x01 +#define EFI_FILE_HEADER_VALID 0x02 +#define EFI_FILE_DATA_VALID 0x04 +#define EFI_FILE_MARKED_FOR_UPDATE 0x08 +#define EFI_FILE_DELETED 0x10 +#define EFI_FILE_HEADER_INVALID 0x20 + + +/// +/// Each file begins with the header that describe the +/// contents and state of the files. +/// +typedef struct { + /// + /// This GUID is the file name. It is used to uniquely identify the file. + /// + EFI_GUID Name; + /// + /// Used to verify the integrity of the file. + /// + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + /// + /// Identifies the type of file. + /// + EFI_FV_FILETYPE Type; + /// + /// Declares various file attribute bits. + /// + EFI_FFS_FILE_ATTRIBUTES Attributes; + /// + /// The length of the file in bytes, including the FFS header. + /// + UINT8 Size[3]; + /// + /// Used to track the state of the file throughout the life of the file from creation to deletion. + /// + EFI_FFS_FILE_STATE State; +} EFI_FFS_FILE_HEADER; + +typedef struct { + /// + /// This GUID is the file name. It is used to uniquely identify the file. There may be only + /// one instance of a file with the file name GUID of Name in any given firmware + /// volume, except if the file type is EFI_FV_FILETYPE_FFS_PAD. + /// + EFI_GUID Name; + + /// + /// Used to verify the integrity of the file. + /// + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + + /// + /// Identifies the type of file. + /// + EFI_FV_FILETYPE Type; + + /// + /// Declares various file attribute bits. + /// + EFI_FFS_FILE_ATTRIBUTES Attributes; + + /// + /// The length of the file in bytes, including the FFS header. + /// The length of the file data is either (Size - sizeof(EFI_FFS_FILE_HEADER)). This calculation means a + /// zero-length file has a Size of 24 bytes, which is sizeof(EFI_FFS_FILE_HEADER). + /// Size is not required to be a multiple of 8 bytes. Given a file F, the next file header is + /// located at the next 8-byte aligned firmware volume offset following the last byte of the file F. + /// + UINT8 Size[3]; + + /// + /// Used to track the state of the file throughout the life of the file from creation to deletion. + /// + EFI_FFS_FILE_STATE State; + + /// + /// If FFS_ATTRIB_LARGE_FILE is set in Attributes, then ExtendedSize exists and Size must be set to zero. + /// If FFS_ATTRIB_LARGE_FILE is not set then EFI_FFS_FILE_HEADER is used. + /// + UINT64 ExtendedSize; +} EFI_FFS_FILE_HEADER2; + +#define IS_FFS_FILE2(FfsFileHeaderPtr) \ + (((((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Attributes) & FFS_ATTRIB_LARGE_FILE) == FFS_ATTRIB_LARGE_FILE) + +#define FFS_FILE_SIZE(FfsFileHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Size) & 0x00ffffff)) + +#define FFS_FILE2_SIZE(FfsFileHeaderPtr) \ + ((UINT32) (((EFI_FFS_FILE_HEADER2 *) (UINTN) FfsFileHeaderPtr)->ExtendedSize)) + +typedef UINT8 EFI_SECTION_TYPE; + +/// +/// Pseudo type. It is used as a wild card when retrieving sections. +/// The section type EFI_SECTION_ALL matches all section types. +/// +#define EFI_SECTION_ALL 0x00 + +/// +/// Encapsulation section Type values. +/// +#define EFI_SECTION_COMPRESSION 0x01 + +#define EFI_SECTION_GUID_DEFINED 0x02 + +#define EFI_SECTION_DISPOSABLE 0x03 + +/// +/// Leaf section Type values. +/// +#define EFI_SECTION_PE32 0x10 +#define EFI_SECTION_PIC 0x11 +#define EFI_SECTION_TE 0x12 +#define EFI_SECTION_DXE_DEPEX 0x13 +#define EFI_SECTION_VERSION 0x14 +#define EFI_SECTION_USER_INTERFACE 0x15 +#define EFI_SECTION_COMPATIBILITY16 0x16 +#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define EFI_SECTION_RAW 0x19 +#define EFI_SECTION_PEI_DEPEX 0x1B +#define EFI_SECTION_MM_DEPEX 0x1C +#define EFI_SECTION_SMM_DEPEX EFI_SECTION_MM_DEPEX + +/// +/// Common section header. +/// +typedef struct { + /// + /// A 24-bit unsigned integer that contains the total size of the section in bytes, + /// including the EFI_COMMON_SECTION_HEADER. + /// + UINT8 Size[3]; + EFI_SECTION_TYPE Type; + /// + /// Declares the section type. + /// +} EFI_COMMON_SECTION_HEADER; + +typedef struct { + /// + /// A 24-bit unsigned integer that contains the total size of the section in bytes, + /// including the EFI_COMMON_SECTION_HEADER. + /// + UINT8 Size[3]; + + EFI_SECTION_TYPE Type; + + /// + /// If Size is 0xFFFFFF, then ExtendedSize contains the size of the section. If + /// Size is not equal to 0xFFFFFF, then this field does not exist. + /// + UINT32 ExtendedSize; +} EFI_COMMON_SECTION_HEADER2; + +/// +/// Leaf section type that contains an +/// IA-32 16-bit executable image. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2; + +/// +/// CompressionType of EFI_COMPRESSION_SECTION. +/// +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +/// +/// An encapsulation section type in which the +/// section data is compressed. +/// +typedef struct { + /// + /// Usual common section header. CommonHeader.Type = EFI_SECTION_COMPRESSION. + /// + EFI_COMMON_SECTION_HEADER CommonHeader; + /// + /// The UINT32 that indicates the size of the section data after decompression. + /// + UINT32 UncompressedLength; + /// + /// Indicates which compression algorithm is used. + /// + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION; + +typedef struct { + /// + /// Usual common section header. CommonHeader.Type = EFI_SECTION_COMPRESSION. + /// + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// UINT32 that indicates the size of the section data after decompression. + /// + UINT32 UncompressedLength; + /// + /// Indicates which compression algorithm is used. + /// + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION2; + +/// +/// An encapsulation section type in which the section data is disposable. +/// A disposable section is an encapsulation section in which the section data may be disposed of during +/// the process of creating or updating a firmware image without significant impact on the usefulness of +/// the file. The Type field in the section header is set to EFI_SECTION_DISPOSABLE. This +/// allows optional or descriptive data to be included with the firmware file which can be removed in +/// order to conserve space. The contents of this section are implementation specific, but might contain +/// debug data or detailed integration instructions. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_DISPOSABLE_SECTION2; + +/// +/// The leaf section which could be used to determine the dispatch order of DXEs. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2; + +/// +/// The leaf section which contains a PI FV. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2; + +/// +/// The leaf section which contains a single GUID. +/// +typedef struct { + /// + /// Common section header. CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID. + /// + EFI_COMMON_SECTION_HEADER CommonHeader; + /// + /// This GUID is defined by the creator of the file. It is a vendor-defined file type. + /// + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION; + +typedef struct { + /// + /// The common section header. CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID. + /// + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// This GUID is defined by the creator of the file. It is a vendor-defined file type. + /// + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION2; + +/// +/// Attributes of EFI_GUID_DEFINED_SECTION. +/// +#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 +/// +/// The leaf section which is encapsulation defined by specific GUID. +/// +typedef struct { + /// + /// The common section header. CommonHeader.Type = EFI_SECTION_GUID_DEFINED. + /// + EFI_COMMON_SECTION_HEADER CommonHeader; + /// + /// The GUID that defines the format of the data that follows. It is a vendor-defined section type. + /// + EFI_GUID SectionDefinitionGuid; + /// + /// Contains the offset in bytes from the beginning of the common header to the first byte of the data. + /// + UINT16 DataOffset; + /// + /// The bit field that declares some specific characteristics of the section contents. + /// + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION; + +typedef struct { + /// + /// The common section header. CommonHeader.Type = EFI_SECTION_GUID_DEFINED. + /// + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// The GUID that defines the format of the data that follows. It is a vendor-defined section type. + /// + EFI_GUID SectionDefinitionGuid; + /// + /// Contains the offset in bytes from the beginning of the common header to the first byte of the data. + /// + UINT16 DataOffset; + /// + /// The bit field that declares some specific characteristics of the section contents. + /// + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION2; + +/// +/// The leaf section which contains PE32+ image. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2; + +/// +/// The leaf section used to determine the dispatch order of PEIMs. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2; + +/// +/// A leaf section type that contains a position-independent-code (PIC) image. +/// A PIC image section is a leaf section that contains a position-independent-code (PIC) image. +/// In addition to normal PE32+ images that contain relocation information, PEIM executables may be +/// PIC and are referred to as PIC images. A PIC image is the same as a PE32+ image except that all +/// relocation information has been stripped from the image and the image can be moved and will +/// execute correctly without performing any relocation or other fix-ups. EFI_PIC_SECTION2 must +/// be used if the section is 16MB or larger. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2; + +/// +/// The leaf section which constains the position-independent-code image. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2; + +/// +/// The leaf section which contains an array of zero or more bytes. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2; + +/// +/// The SMM dependency expression section is a leaf section that contains a dependency expression that +/// is used to determine the dispatch order for SMM drivers. Before the SMRAM invocation of the +/// SMM driver's entry point, this dependency expression must evaluate to TRUE. See the Platform +/// Initialization Specification, Volume 2, for details regarding the format of the dependency expression. +/// The dependency expression may refer to protocols installed in either the UEFI or the SMM protocol +/// database. EFI_SMM_DEPEX_SECTION2 must be used if the section is 16MB or larger. +/// +typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_SMM_DEPEX_SECTION2; + +/// +/// The leaf section which contains a unicode string that +/// is human readable file name. +/// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + + /// + /// Array of unicode string. + /// + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION2; + +/// +/// The leaf section which contains a numeric build number and +/// an optional unicode string that represents the file revision. +/// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT16 BuildNumber; + + /// + /// Array of unicode string. + /// + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + /// + /// A UINT16 that represents a particular build. Subsequent builds have monotonically + /// increasing build numbers relative to earlier builds. + /// + UINT16 BuildNumber; + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION2; + +#define IS_SECTION2(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff) == 0x00ffffff) + +#define SECTION_SIZE(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff)) + +#define SECTION2_SIZE(SectionHeaderPtr) \ + (((EFI_COMMON_SECTION_HEADER2 *) (UINTN) SectionHeaderPtr)->ExtendedSize) + +#pragma pack() + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareVolume.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareVolume.h new file mode 100644 index 0000000..96bc909 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiFirmwareVolume.h @@ -0,0 +1,253 @@ +/** @file + The firmware volume related definitions in PI. + + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.6 + +**/ + +#ifndef __PI_FIRMWAREVOLUME_H__ +#define __PI_FIRMWAREVOLUME_H__ + +/// +/// EFI_FV_FILE_ATTRIBUTES +/// +typedef UINT32 EFI_FV_FILE_ATTRIBUTES; + +// +// Value of EFI_FV_FILE_ATTRIBUTES. +// +#define EFI_FV_FILE_ATTRIB_ALIGNMENT 0x0000001F +#define EFI_FV_FILE_ATTRIB_FIXED 0x00000100 +#define EFI_FV_FILE_ATTRIB_MEMORY_MAPPED 0x00000200 + +/// +/// type of EFI FVB attribute +/// +typedef UINT32 EFI_FVB_ATTRIBUTES_2; + +// +// Attributes bit definitions +// +#define EFI_FVB2_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB2_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB2_READ_STATUS 0x00000004 +#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB2_WRITE_STATUS 0x00000020 +#define EFI_FVB2_LOCK_CAP 0x00000040 +#define EFI_FVB2_LOCK_STATUS 0x00000080 +#define EFI_FVB2_STICKY_WRITE 0x00000200 +#define EFI_FVB2_MEMORY_MAPPED 0x00000400 +#define EFI_FVB2_ERASE_POLARITY 0x00000800 +#define EFI_FVB2_READ_LOCK_CAP 0x00001000 +#define EFI_FVB2_READ_LOCK_STATUS 0x00002000 +#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000 +#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000 +#define EFI_FVB2_ALIGNMENT 0x001F0000 +#define EFI_FVB2_ALIGNMENT_1 0x00000000 +#define EFI_FVB2_ALIGNMENT_2 0x00010000 +#define EFI_FVB2_ALIGNMENT_4 0x00020000 +#define EFI_FVB2_ALIGNMENT_8 0x00030000 +#define EFI_FVB2_ALIGNMENT_16 0x00040000 +#define EFI_FVB2_ALIGNMENT_32 0x00050000 +#define EFI_FVB2_ALIGNMENT_64 0x00060000 +#define EFI_FVB2_ALIGNMENT_128 0x00070000 +#define EFI_FVB2_ALIGNMENT_256 0x00080000 +#define EFI_FVB2_ALIGNMENT_512 0x00090000 +#define EFI_FVB2_ALIGNMENT_1K 0x000A0000 +#define EFI_FVB2_ALIGNMENT_2K 0x000B0000 +#define EFI_FVB2_ALIGNMENT_4K 0x000C0000 +#define EFI_FVB2_ALIGNMENT_8K 0x000D0000 +#define EFI_FVB2_ALIGNMENT_16K 0x000E0000 +#define EFI_FVB2_ALIGNMENT_32K 0x000F0000 +#define EFI_FVB2_ALIGNMENT_64K 0x00100000 +#define EFI_FVB2_ALIGNMENT_128K 0x00110000 +#define EFI_FVB2_ALIGNMENT_256K 0x00120000 +#define EFI_FVB2_ALIGNMENT_512K 0x00130000 +#define EFI_FVB2_ALIGNMENT_1M 0x00140000 +#define EFI_FVB2_ALIGNMENT_2M 0x00150000 +#define EFI_FVB2_ALIGNMENT_4M 0x00160000 +#define EFI_FVB2_ALIGNMENT_8M 0x00170000 +#define EFI_FVB2_ALIGNMENT_16M 0x00180000 +#define EFI_FVB2_ALIGNMENT_32M 0x00190000 +#define EFI_FVB2_ALIGNMENT_64M 0x001A0000 +#define EFI_FVB2_ALIGNMENT_128M 0x001B0000 +#define EFI_FVB2_ALIGNMENT_256M 0x001C0000 +#define EFI_FVB2_ALIGNMENT_512M 0x001D0000 +#define EFI_FVB2_ALIGNMENT_1G 0x001E0000 +#define EFI_FVB2_ALIGNMENT_2G 0x001F0000 +#define EFI_FVB2_WEAK_ALIGNMENT 0x80000000 + +typedef struct { + /// + /// The number of sequential blocks which are of the same size. + /// + UINT32 NumBlocks; + /// + /// The size of the blocks. + /// + UINT32 Length; +} EFI_FV_BLOCK_MAP_ENTRY; + +/// +/// Describes the features and layout of the firmware volume. +/// +typedef struct { + /// + /// The first 16 bytes are reserved to allow for the reset vector of + /// processors whose reset vector is at address 0. + /// + UINT8 ZeroVector[16]; + /// + /// Declares the file system with which the firmware volume is formatted. + /// + EFI_GUID FileSystemGuid; + /// + /// Length in bytes of the complete firmware volume, including the header. + /// + UINT64 FvLength; + /// + /// Set to EFI_FVH_SIGNATURE + /// + UINT32 Signature; + /// + /// Declares capabilities and power-on defaults for the firmware volume. + /// + EFI_FVB_ATTRIBUTES_2 Attributes; + /// + /// Length in bytes of the complete firmware volume header. + /// + UINT16 HeaderLength; + /// + /// A 16-bit checksum of the firmware volume header. A valid header sums to zero. + /// + UINT16 Checksum; + /// + /// Offset, relative to the start of the header, of the extended header + /// (EFI_FIRMWARE_VOLUME_EXT_HEADER) or zero if there is no extended header. + /// + UINT16 ExtHeaderOffset; + /// + /// This field must always be set to zero. + /// + UINT8 Reserved[1]; + /// + /// Set to 2. Future versions of this specification may define new header fields and will + /// increment the Revision field accordingly. + /// + UINT8 Revision; + /// + /// An array of run-length encoded FvBlockMapEntry structures. The array is + /// terminated with an entry of {0,0}. + /// + EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]; +} EFI_FIRMWARE_VOLUME_HEADER; + +#define EFI_FVH_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', 'H') + +/// +/// Firmware Volume Header Revision definition +/// +#define EFI_FVH_REVISION 0x02 + +/// +/// Extension header pointed by ExtHeaderOffset of volume header. +/// +typedef struct { + /// + /// Firmware volume name. + /// + EFI_GUID FvName; + /// + /// Size of the rest of the extension header, including this structure. + /// + UINT32 ExtHeaderSize; +} EFI_FIRMWARE_VOLUME_EXT_HEADER; + +/// +/// Entry struture for describing FV extension header +/// +typedef struct { + /// + /// Size of this header extension. + /// + UINT16 ExtEntrySize; + /// + /// Type of the header. + /// + UINT16 ExtEntryType; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY; + +#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01 +/// +/// This extension header provides a mapping between a GUID and an OEM file type. +/// +typedef struct { + /// + /// Standard extension entry, with the type EFI_FV_EXT_TYPE_OEM_TYPE. + /// + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + /// + /// A bit mask, one bit for each file type between 0xC0 (bit 0) and 0xDF (bit 31). If a bit + /// is '1', then the GUID entry exists in Types. If a bit is '0' then no GUID entry exists in Types. + /// + UINT32 TypeMask; + /// + /// An array of GUIDs, each GUID representing an OEM file type. + /// + /// EFI_GUID Types[1]; + /// +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_OEM_TYPE; + +#define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002 + +/// +/// This extension header EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE provides a vendor specific +/// GUID FormatType type which includes a length and a successive series of data bytes. +/// +typedef struct { + /// + /// Standard extension entry, with the type EFI_FV_EXT_TYPE_OEM_TYPE. + /// + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + /// + /// Vendor-specific GUID. + /// + EFI_GUID FormatType; + /// + /// An arry of bytes of length Length. + /// + /// UINT8 Data[1]; + /// +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE; + +#define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03 + +/// +/// The EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE can be used to find +/// out how many EFI_FVB2_ERASE_POLARITY bytes are at the end of the FV. +/// +typedef struct { + /// + /// Standard extension entry, with the type EFI_FV_EXT_TYPE_USED_SIZE_TYPE. + /// + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + /// + /// The number of bytes of the FV that are in uses. The remaining + /// EFI_FIRMWARE_VOLUME_HEADER FvLength minus UsedSize bytes in + /// the FV must contain the value implied by EFI_FVB2_ERASE_POLARITY. + /// + UINT32 UsedSize; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiHob.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiHob.h new file mode 100644 index 0000000..c63c3ff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiHob.h @@ -0,0 +1,518 @@ +/** @file + HOB related definitions in PI. + +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.6 + +**/ + +#ifndef __PI_HOB_H__ +#define __PI_HOB_H__ + +// +// HobType of EFI_HOB_GENERIC_HEADER. +// +#define EFI_HOB_TYPE_HANDOFF 0x0001 +#define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002 +#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003 +#define EFI_HOB_TYPE_GUID_EXTENSION 0x0004 +#define EFI_HOB_TYPE_FV 0x0005 +#define EFI_HOB_TYPE_CPU 0x0006 +#define EFI_HOB_TYPE_MEMORY_POOL 0x0007 +#define EFI_HOB_TYPE_FV2 0x0009 +#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED 0x000A +#define EFI_HOB_TYPE_UEFI_CAPSULE 0x000B +#define EFI_HOB_TYPE_FV3 0x000C +#define EFI_HOB_TYPE_UNUSED 0xFFFE +#define EFI_HOB_TYPE_END_OF_HOB_LIST 0xFFFF + +/// +/// Describes the format and size of the data inside the HOB. +/// All HOBs must contain this generic HOB header. +/// +typedef struct { + /// + /// Identifies the HOB data structure type. + /// + UINT16 HobType; + /// + /// The length in bytes of the HOB. + /// + UINT16 HobLength; + /// + /// This field must always be set to zero. + /// + UINT32 Reserved; +} EFI_HOB_GENERIC_HEADER; + + +/// +/// Value of version in EFI_HOB_HANDOFF_INFO_TABLE. +/// +#define EFI_HOB_HANDOFF_TABLE_VERSION 0x0009 + +/// +/// Contains general state information used by the HOB producer phase. +/// This HOB must be the first one in the HOB list. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_HANDOFF. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The version number pertaining to the PHIT HOB definition. + /// This value is four bytes in length to provide an 8-byte aligned entry + /// when it is combined with the 4-byte BootMode. + /// + UINT32 Version; + /// + /// The system boot mode as determined during the HOB producer phase. + /// + EFI_BOOT_MODE BootMode; + /// + /// The highest address location of memory that is allocated for use by the HOB producer + /// phase. This address must be 4-KB aligned to meet page restrictions of UEFI. + /// + EFI_PHYSICAL_ADDRESS EfiMemoryTop; + /// + /// The lowest address location of memory that is allocated for use by the HOB producer phase. + /// + EFI_PHYSICAL_ADDRESS EfiMemoryBottom; + /// + /// The highest address location of free memory that is currently available + /// for use by the HOB producer phase. + /// + EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop; + /// + /// The lowest address location of free memory that is available for use by the HOB producer phase. + /// + EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom; + /// + /// The end of the HOB list. + /// + EFI_PHYSICAL_ADDRESS EfiEndOfHobList; +} EFI_HOB_HANDOFF_INFO_TABLE; + +/// +/// EFI_HOB_MEMORY_ALLOCATION_HEADER describes the +/// various attributes of the logical memory allocation. The type field will be used for +/// subsequent inclusion in the UEFI memory map. +/// +typedef struct { + /// + /// A GUID that defines the memory allocation region's type and purpose, as well as + /// other fields within the memory allocation HOB. This GUID is used to define the + /// additional data within the HOB that may be present for the memory allocation HOB. + /// Type EFI_GUID is defined in InstallProtocolInterface() in the UEFI 2.0 + /// specification. + /// + EFI_GUID Name; + + /// + /// The base address of memory allocated by this HOB. Type + /// EFI_PHYSICAL_ADDRESS is defined in AllocatePages() in the UEFI 2.0 + /// specification. + /// + EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + + /// + /// The length in bytes of memory allocated by this HOB. + /// + UINT64 MemoryLength; + + /// + /// Defines the type of memory allocated by this HOB. The memory type definition + /// follows the EFI_MEMORY_TYPE definition. Type EFI_MEMORY_TYPE is defined + /// in AllocatePages() in the UEFI 2.0 specification. + /// + EFI_MEMORY_TYPE MemoryType; + + /// + /// Padding for Itanium processor family + /// + UINT8 Reserved[4]; +} EFI_HOB_MEMORY_ALLOCATION_HEADER; + +/// +/// Describes all memory ranges used during the HOB producer +/// phase that exist outside the HOB list. This HOB type +/// describes how memory is used, not the physical attributes of memory. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; + // + // Additional data pertaining to the "Name" Guid memory + // may go here. + // +} EFI_HOB_MEMORY_ALLOCATION; + + +/// +/// Describes the memory stack that is produced by the HOB producer +/// phase and upon which all post-memory-installed executable +/// content in the HOB producer phase is executing. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; +} EFI_HOB_MEMORY_ALLOCATION_STACK; + +/// +/// Defines the location of the boot-strap +/// processor (BSP) BSPStore ("Backing Store Pointer Store"). +/// This HOB is valid for the Itanium processor family only +/// register overflow store. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; +} EFI_HOB_MEMORY_ALLOCATION_BSP_STORE; + +/// +/// Defines the location and entry point of the HOB consumer phase. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// An instance of the EFI_HOB_MEMORY_ALLOCATION_HEADER that describes the + /// various attributes of the logical memory allocation. + /// + EFI_HOB_MEMORY_ALLOCATION_HEADER MemoryAllocationHeader; + /// + /// The GUID specifying the values of the firmware file system name + /// that contains the HOB consumer phase component. + /// + EFI_GUID ModuleName; + /// + /// The address of the memory-mapped firmware volume + /// that contains the HOB consumer phase firmware file. + /// + EFI_PHYSICAL_ADDRESS EntryPoint; +} EFI_HOB_MEMORY_ALLOCATION_MODULE; + +/// +/// The resource type. +/// +typedef UINT32 EFI_RESOURCE_TYPE; + +// +// Value of ResourceType in EFI_HOB_RESOURCE_DESCRIPTOR. +// +#define EFI_RESOURCE_SYSTEM_MEMORY 0x00000000 +#define EFI_RESOURCE_MEMORY_MAPPED_IO 0x00000001 +#define EFI_RESOURCE_IO 0x00000002 +#define EFI_RESOURCE_FIRMWARE_DEVICE 0x00000003 +#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004 +#define EFI_RESOURCE_MEMORY_RESERVED 0x00000005 +#define EFI_RESOURCE_IO_RESERVED 0x00000006 +#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000007 + +/// +/// A type of recount attribute type. +/// +typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; + +// +// These types can be ORed together as needed. +// +// The following attributes are used to describe settings +// +#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 +// +// This is typically used as memory cacheability attribute today. +// NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED +// as Physical write protected attribute, and EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED +// means Memory cacheability attribute: The memory supports being programmed with +// a writeprotected cacheable attribute. +// +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 +#define EFI_RESOURCE_ATTRIBUTE_PERSISTENT 0x00800000 +// +// The rest of the attributes are used to describe capabilities +// +#define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008 +#define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000 +#define EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000 +#define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 +#define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE 0x00100000 +// +// This is typically used as memory cacheability attribute today. +// NOTE: Since PI spec 1.4, please use EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE +// as Memory capability attribute: The memory supports being protected from processor +// writes, and EFI_RESOURCE_ATTRIBUTE_WRITE_PROTEC TABLE means Memory cacheability attribute: +// The memory supports being programmed with a writeprotected cacheable attribute. +// +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE 0x00200000 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE 0x00400000 +#define EFI_RESOURCE_ATTRIBUTE_PERSISTABLE 0x01000000 + +#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED 0x00040000 +#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE 0x00080000 + +// +// Physical memory relative reliability attribute. This +// memory provides higher reliability relative to other +// memory in the system. If all memory has the same +// reliability, then this bit is not used. +// +#define EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE 0x02000000 + +/// +/// Describes the resource properties of all fixed, +/// nonrelocatable resource ranges found on the processor +/// host bus during the HOB producer phase. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_RESOURCE_DESCRIPTOR. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// A GUID representing the owner of the resource. This GUID is used by HOB + /// consumer phase components to correlate device ownership of a resource. + /// + EFI_GUID Owner; + /// + /// The resource type enumeration as defined by EFI_RESOURCE_TYPE. + /// + EFI_RESOURCE_TYPE ResourceType; + /// + /// Resource attributes as defined by EFI_RESOURCE_ATTRIBUTE_TYPE. + /// + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + /// + /// The physical start address of the resource region. + /// + EFI_PHYSICAL_ADDRESS PhysicalStart; + /// + /// The number of bytes of the resource region. + /// + UINT64 ResourceLength; +} EFI_HOB_RESOURCE_DESCRIPTOR; + +/// +/// Allows writers of executable content in the HOB producer phase to +/// maintain and manage HOBs with specific GUID. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_GUID_EXTENSION. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// A GUID that defines the contents of this HOB. + /// + EFI_GUID Name; + // + // Guid specific data goes here + // +} EFI_HOB_GUID_TYPE; + +/// +/// Details the location of firmware volumes that contain firmware files. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The physical memory-mapped base address of the firmware volume. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + /// + /// The length in bytes of the firmware volume. + /// + UINT64 Length; +} EFI_HOB_FIRMWARE_VOLUME; + +/// +/// Details the location of a firmware volume that was extracted +/// from a file within another firmware volume. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV2. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The physical memory-mapped base address of the firmware volume. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + /// + /// The length in bytes of the firmware volume. + /// + UINT64 Length; + /// + /// The name of the firmware volume. + /// + EFI_GUID FvName; + /// + /// The name of the firmware file that contained this firmware volume. + /// + EFI_GUID FileName; +} EFI_HOB_FIRMWARE_VOLUME2; + +/// +/// Details the location of a firmware volume that was extracted +/// from a file within another firmware volume. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_FV3. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// The physical memory-mapped base address of the firmware volume. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + /// + /// The length in bytes of the firmware volume. + /// + UINT64 Length; + /// + /// The authentication status. + /// + UINT32 AuthenticationStatus; + /// + /// TRUE if the FV was extracted as a file within another firmware volume. + /// FALSE otherwise. + /// + BOOLEAN ExtractedFv; + /// + /// The name of the firmware volume. + /// Valid only if IsExtractedFv is TRUE. + /// + EFI_GUID FvName; + /// + /// The name of the firmware file that contained this firmware volume. + /// Valid only if IsExtractedFv is TRUE. + /// + EFI_GUID FileName; +} EFI_HOB_FIRMWARE_VOLUME3; + +/// +/// Describes processor information, such as address space and I/O space capabilities. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_CPU. + /// + EFI_HOB_GENERIC_HEADER Header; + /// + /// Identifies the maximum physical memory addressability of the processor. + /// + UINT8 SizeOfMemorySpace; + /// + /// Identifies the maximum physical I/O addressability of the processor. + /// + UINT8 SizeOfIoSpace; + /// + /// This field will always be set to zero. + /// + UINT8 Reserved[6]; +} EFI_HOB_CPU; + + +/// +/// Describes pool memory allocations. +/// +typedef struct { + /// + /// The HOB generic header. Header.HobType = EFI_HOB_TYPE_MEMORY_POOL. + /// + EFI_HOB_GENERIC_HEADER Header; +} EFI_HOB_MEMORY_POOL; + +/// +/// Each UEFI capsule HOB details the location of a UEFI capsule. It includes a base address and length +/// which is based upon memory blocks with a EFI_CAPSULE_HEADER and the associated +/// CapsuleImageSize-based payloads. These HOB's shall be created by the PEI PI firmware +/// sometime after the UEFI UpdateCapsule service invocation with the +/// CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag set in the EFI_CAPSULE_HEADER. +/// +typedef struct { + /// + /// The HOB generic header where Header.HobType = EFI_HOB_TYPE_UEFI_CAPSULE. + /// + EFI_HOB_GENERIC_HEADER Header; + + /// + /// The physical memory-mapped base address of an UEFI capsule. This value is set to + /// point to the base of the contiguous memory of the UEFI capsule. + /// The length of the contiguous memory in bytes. + /// + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; +} EFI_HOB_UEFI_CAPSULE; + +/// +/// Union of all the possible HOB Types. +/// +typedef union { + EFI_HOB_GENERIC_HEADER *Header; + EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocation; + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *MemoryAllocationBspStore; + EFI_HOB_MEMORY_ALLOCATION_STACK *MemoryAllocationStack; + EFI_HOB_MEMORY_ALLOCATION_MODULE *MemoryAllocationModule; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor; + EFI_HOB_GUID_TYPE *Guid; + EFI_HOB_FIRMWARE_VOLUME *FirmwareVolume; + EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2; + EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3; + EFI_HOB_CPU *Cpu; + EFI_HOB_MEMORY_POOL *Pool; + EFI_HOB_UEFI_CAPSULE *Capsule; + UINT8 *Raw; +} EFI_PEI_HOB_POINTERS; + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiI2c.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiI2c.h new file mode 100644 index 0000000..49745b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiI2c.h @@ -0,0 +1,307 @@ +/** @file + Include file matches things in PI. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.3 + +**/ + +#ifndef __PI_I2C_H__ +#define __PI_I2C_H__ + +/// +/// A 10-bit slave address is or'ed with the following value enabling the +/// I2C protocol stack to address the duplicated address space between 0 +// and 127 in 10-bit mode. +/// +#define I2C_ADDRESSING_10_BIT 0x80000000 + +/// +/// I2C controller capabilities +/// +/// The EFI_I2C_CONTROLLER_CAPABILITIES specifies the capabilities of the +/// I2C host controller. The StructureSizeInBytes enables variations of +/// this structure to be identified if there is need to extend this +/// structure in the future. +/// +typedef struct { + /// + /// Length of this data structure in bytes + /// + UINT32 StructureSizeInBytes; + + /// + /// The maximum number of bytes the I2C host controller is able to + /// receive from the I2C bus. + /// + UINT32 MaximumReceiveBytes; + + /// + /// The maximum number of bytes the I2C host controller is able to send + /// on the I2C bus. + /// + UINT32 MaximumTransmitBytes; + + /// + /// The maximum number of bytes in the I2C bus transaction. + /// + UINT32 MaximumTotalBytes; +} EFI_I2C_CONTROLLER_CAPABILITIES; + +/// +/// I2C device description +/// +/// The EFI_I2C_ENUMERATE_PROTOCOL uses the EFI_I2C_DEVICE to describe +/// the platform specific details associated with an I2C device. This +/// description is passed to the I2C bus driver during enumeration where +/// it is made available to the third party I2C device driver via the +/// EFI_I2C_IO_PROTOCOL. +/// +typedef struct { + /// + /// Unique value assigned by the silicon manufacture or the third + /// party I2C driver writer for the I2C part. This value logically + /// combines both the manufacture name and the I2C part number into + /// a single value specified as a GUID. + /// + CONST EFI_GUID *DeviceGuid; + + /// + /// Unique ID of the I2C part within the system + /// + UINT32 DeviceIndex; + + /// + /// Hardware revision - ACPI _HRV value. See the Advanced + /// Configuration and Power Interface Specification, Revision 5.0 + /// for the field format and the Plug and play support for I2C + /// web-page for restriction on values. + /// + /// http://www.acpi.info/spec.htm + /// http://msdn.microsoft.com/en-us/library/windows/hardware/jj131711(v=vs.85).aspx + /// + UINT32 HardwareRevision; + + /// + /// I2C bus configuration for the I2C device + /// + UINT32 I2cBusConfiguration; + + /// + /// Number of slave addresses for the I2C device. + /// + UINT32 SlaveAddressCount; + + /// + /// Pointer to the array of slave addresses for the I2C device. + /// + CONST UINT32 *SlaveAddressArray; +} EFI_I2C_DEVICE; + +/// +/// Define the I2C flags +/// +/// I2C read operation when set +#define I2C_FLAG_READ 0x00000001 + +/// +/// Define the flags for SMBus operation +/// +/// The following flags are also present in only the first I2C operation +/// and are ignored when present in other operations. These flags +/// describe a particular SMB transaction as shown in the following table. +/// + +/// SMBus operation +#define I2C_FLAG_SMBUS_OPERATION 0x00010000 + +/// SMBus block operation +/// The flag I2C_FLAG_SMBUS_BLOCK causes the I2C master protocol to update +/// the LengthInBytes field of the operation in the request packet with +/// the actual number of bytes read or written. These values are only +/// valid when the entire I2C transaction is successful. +/// This flag also changes the LengthInBytes meaning to be: A maximum +/// of LengthInBytes is to be read from the device. The first byte +/// read contains the number of bytes remaining to be read, plus an +/// optional PEC value. +#define I2C_FLAG_SMBUS_BLOCK 0x00020000 + +/// SMBus process call operation +#define I2C_FLAG_SMBUS_PROCESS_CALL 0x00040000 + +/// SMBus use packet error code (PEC) +/// Note that the I2C master protocol may clear the I2C_FLAG_SMBUS_PEC bit +/// to indicate that the PEC value was checked by the hardware and is +/// not appended to the returned read data. +/// +#define I2C_FLAG_SMBUS_PEC 0x00080000 + +//---------------------------------------------------------------------- +/// +/// QuickRead: OperationCount=1, +/// LengthInBytes=0, Flags=I2C_FLAG_READ +/// QuickWrite: OperationCount=1, +/// LengthInBytes=0, Flags=0 +/// +/// +/// ReceiveByte: OperationCount=1, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_READ +/// ReceiveByte+PEC: OperationCount=1, +/// LengthInBytes=2, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_READ +/// | I2C_FLAG_SMBUS_PEC +/// +/// +/// SendByte: OperationCount=1, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// SendByte+PEC: OperationCount=1, +/// LengthInBytes=2, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PEC +/// +/// +/// ReadDataByte: OperationCount=2, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// LengthInBytes=1, Flags=I2C_FLAG_READ +/// ReadDataByte+PEC: OperationCount=2, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PEC +/// LengthInBytes=2, Flags=I2C_FLAG_READ +/// +/// +/// WriteDataByte: OperationCount=1, +/// LengthInBytes=2, Flags=I2C_FLAG_SMBUS_OPERATION +/// WriteDataByte+PEC: OperationCount=1, +/// LengthInBytes=3, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PEC +/// +/// +/// ReadDataWord: OperationCount=2, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// LengthInBytes=2, Flags=I2C_FLAG_READ +/// ReadDataWord+PEC: OperationCount=2, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PEC +/// LengthInBytes=3, Flags=I2C_FLAG_READ +/// +/// +/// WriteDataWord: OperationCount=1, +/// LengthInBytes=3, Flags=I2C_FLAG_SMBUS_OPERATION +/// WriteDataWord+PEC: OperationCount=1, +/// LengthInBytes=4, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PEC +/// +/// +/// ReadBlock: OperationCount=2, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_BLOCK +/// LengthInBytes=33, Flags=I2C_FLAG_READ +/// ReadBlock+PEC: OperationCount=2, +/// LengthInBytes=1, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_BLOCK +/// | I2C_FLAG_SMBUS_PEC +/// LengthInBytes=34, Flags=I2C_FLAG_READ +/// +/// +/// WriteBlock: OperationCount=1, +/// LengthInBytes=N+2, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_BLOCK +/// WriteBlock+PEC: OperationCount=1, +/// LengthInBytes=N+3, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_BLOCK +/// | I2C_FLAG_SMBUS_PEC +/// +/// +/// ProcessCall: OperationCount=2, +/// LengthInBytes=3, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PROCESS_CALL +/// LengthInBytes=2, Flags=I2C_FLAG_READ +/// ProcessCall+PEC: OperationCount=2, +/// LengthInBytes=3, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PROCESS_CALL +/// | I2C_FLAG_SMBUS_PEC +/// LengthInBytes=3, Flags=I2C_FLAG_READ +/// +/// +/// BlkProcessCall: OperationCount=2, +/// LengthInBytes=N+2, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PROCESS_CALL +/// | I2C_FLAG_SMBUS_BLOCK +/// LengthInBytes=33, Flags=I2C_FLAG_READ +/// BlkProcessCall+PEC: OperationCount=2, +/// LengthInBytes=N+2, Flags=I2C_FLAG_SMBUS_OPERATION +/// | I2C_FLAG_SMBUS_PROCESS_CALL +/// | I2C_FLAG_SMBUS_BLOCK +/// | I2C_FLAG_SMBUS_PEC +/// LengthInBytes=34, Flags=I2C_FLAG_READ +/// +//---------------------------------------------------------------------- + +/// +/// I2C device operation +/// +/// The EFI_I2C_OPERATION describes a subset of an I2C transaction in which +/// the I2C controller is either sending or receiving bytes from the bus. +/// Some transactions will consist of a single operation while others will +/// be two or more. +/// +/// Note: Some I2C controllers do not support read or write ping (address +/// only) operation and will return EFI_UNSUPPORTED status when these +/// operations are requested. +/// +/// Note: I2C controllers which do not support complex transactions requiring +/// multiple repeated start bits return EFI_UNSUPPORTED without processing +/// any of the transaction. +/// +typedef struct { + /// + /// Flags to qualify the I2C operation. + /// + UINT32 Flags; + + /// + /// Number of bytes to send to or receive from the I2C device. A ping + /// (address only byte/bytes) is indicated by setting the LengthInBytes + /// to zero. + /// + UINT32 LengthInBytes; + + /// + /// Pointer to a buffer containing the data to send or to receive from + /// the I2C device. The Buffer must be at least LengthInBytes in size. + /// + UINT8 *Buffer; +} EFI_I2C_OPERATION; + +/// +/// I2C device request +/// +/// The EFI_I2C_REQUEST_PACKET describes a single I2C transaction. The +/// transaction starts with a start bit followed by the first operation +/// in the operation array. Subsequent operations are separated with +/// repeated start bits and the last operation is followed by a stop bit +/// which concludes the transaction. Each operation is described by one +/// of the elements in the Operation array. +/// +typedef struct { + /// + /// Number of elements in the operation array + /// + UINTN OperationCount; + + /// + /// Description of the I2C operation + /// + EFI_I2C_OPERATION Operation [1]; +} EFI_I2C_REQUEST_PACKET; + +#endif // __PI_I2C_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMmCis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMmCis.h new file mode 100644 index 0000000..036a9f2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMmCis.h @@ -0,0 +1,351 @@ +/** @file + Common definitions in the Platform Initialization Specification version 1.5 + VOLUME 4 Management Mode Core Interface version. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PI_MMCIS_H_ +#define _PI_MMCIS_H_ + +#include +#include + +typedef struct _EFI_MM_SYSTEM_TABLE EFI_MM_SYSTEM_TABLE; + +/// +/// The Management Mode System Table (MMST) signature +/// +#define MM_MMST_SIGNATURE SIGNATURE_32 ('S', 'M', 'S', 'T') +/// +/// The Management Mode System Table (MMST) revision is 1.6 +/// +#define MM_SPECIFICATION_MAJOR_REVISION 1 +#define MM_SPECIFICATION_MINOR_REVISION 60 +#define EFI_MM_SYSTEM_TABLE_REVISION ((MM_SPECIFICATION_MAJOR_REVISION<<16) | (MM_SPECIFICATION_MINOR_REVISION)) + +/** + Adds, updates, or removes a configuration table entry from the Management Mode System Table. + + The MmInstallConfigurationTable() function is used to maintain the list + of configuration tables that are stored in the Management Mode System + Table. The list is stored as an array of (GUID, Pointer) pairs. The list + must be allocated from pool memory with PoolType set to EfiRuntimeServicesData. + + @param[in] SystemTable A pointer to the MM System Table (MMST). + @param[in] Guid A pointer to the GUID for the entry to add, update, or remove. + @param[in] Table A pointer to the buffer of the table to add. + @param[in] TableSize The size of the table to install. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_INSTALL_CONFIGURATION_TABLE)( + IN CONST EFI_MM_SYSTEM_TABLE *SystemTable, + IN CONST EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ); + +/** + This service lets the caller to get one distinct application processor (AP) to execute + a caller-provided code stream while in MM. + + @param[in] Procedure A pointer to the code stream to be run on the designated + AP of the system. + @param[in] CpuNumber The zero-based index of the processor number of the AP + on which the code stream is supposed to run. + @param[in,out] ProcArguments Allows the caller to pass a list of parameters to the code + that is run by the AP. + + @retval EFI_SUCCESS The call was successful and the return parameters are valid. + @retval EFI_INVALID_PARAMETER The input arguments are out of range. + @retval EFI_INVALID_PARAMETER The CPU requested is not available on this SMI invocation. + @retval EFI_INVALID_PARAMETER The CPU cannot support an additional service invocation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_STARTUP_THIS_AP)( + IN EFI_AP_PROCEDURE Procedure, + IN UINTN CpuNumber, + IN OUT VOID *ProcArguments OPTIONAL + ); + +/** + Function prototype for protocol install notification. + + @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. + + @return Status Code +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_NOTIFY_FN)( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ); + +/** + Register a callback function be called when a particular protocol interface is installed. + + The MmRegisterProtocolNotify() function creates a registration Function that is to be + called whenever a protocol interface is installed for Protocol by + MmInstallProtocolInterface(). + If Function == NULL and Registration is an existing registration, then the callback is unhooked. + + @param[in] Protocol The unique ID of the protocol for which the event is to be registered. + @param[in] Function Points to the notification function. + @param[out] Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS Successfully returned the registration record + that has been added or unhooked. + @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL. + @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request. + @retval EFI_NOT_FOUND If the registration is not found when Function == NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_REGISTER_PROTOCOL_NOTIFY)( + IN CONST EFI_GUID *Protocol, + IN EFI_MM_NOTIFY_FN Function, + OUT VOID **Registration + ); + +/** + Manage MMI of a particular type. + + @param[in] HandlerType Points to the handler type or NULL for root MMI handlers. + @param[in] Context Points to an optional context buffer. + @param[in,out] CommBuffer Points to the optional communication buffer. + @param[in,out] CommBufferSize Points to the size of the optional communication buffer. + + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING Interrupt source was processed successfully but not quiesced. + @retval EFI_INTERRUPT_PENDING One or more SMI sources could not be quiesced. + @retval EFI_NOT_FOUND Interrupt source was not handled or quiesced. + @retval EFI_SUCCESS Interrupt source was handled and quiesced. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_INTERRUPT_MANAGE)( + IN CONST EFI_GUID *HandlerType, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + Main entry point for an MM handler dispatch or communicate-based callback. + + @param[in] DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister(). + @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-MM environment into an MM 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. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_HANDLER_ENTRY_POINT)( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ); + +/** + Registers a handler to execute within MM. + + @param[in] Handler Handler service function pointer. + @param[in] HandlerType Points to the handler type or NULL for root MMI handlers. + @param[out] DispatchHandle On return, contains a unique handle which can be used to later + unregister the handler function. + + @retval EFI_SUCCESS MMI handler added successfully. + @retval EFI_INVALID_PARAMETER Handler is NULL or DispatchHandle is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_INTERRUPT_REGISTER)( + IN EFI_MM_HANDLER_ENTRY_POINT Handler, + IN CONST EFI_GUID *HandlerType OPTIONAL, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a handler in MM. + + @param[in] DispatchHandle The handle that was specified when the handler was registered. + + @retval EFI_SUCCESS Handler function was successfully unregistered. + @retval EFI_INVALID_PARAMETER DispatchHandle does not refer to a valid handle. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_INTERRUPT_UNREGISTER)( + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Processor information and functionality needed by MM Foundation. +/// +typedef struct _EFI_MM_ENTRY_CONTEXT { + EFI_MM_STARTUP_THIS_AP MmStartupThisAp; + /// + /// A number between zero and the NumberOfCpus field. This field designates which + /// processor is executing the MM Foundation. + /// + UINTN CurrentlyExecutingCpu; + /// + /// The number of possible processors in the platform. This is a 1 based + /// counter. This does not indicate the number of processors that entered MM. + /// + UINTN NumberOfCpus; + /// + /// Points to an array, where each element describes the number of bytes in the + /// corresponding save state specified by CpuSaveState. There are always + /// NumberOfCpus entries in the array. + /// + UINTN *CpuSaveStateSize; + /// + /// Points to an array, where each element is a pointer to a CPU save state. The + /// corresponding element in CpuSaveStateSize specifies the number of bytes in the + /// save state area. There are always NumberOfCpus entries in the array. + /// + VOID **CpuSaveState; +} EFI_MM_ENTRY_CONTEXT; + +/** + This function is the main entry point to the MM Foundation. + + @param[in] MmEntryContext Processor information and functionality needed by MM Foundation. +**/ +typedef +VOID +(EFIAPI *EFI_MM_ENTRY_POINT)( + IN CONST EFI_MM_ENTRY_CONTEXT *MmEntryContext + ); + +/// +/// Management Mode System Table (MMST) +/// +/// The Management Mode System Table (MMST) is a table that contains a collection of common +/// services for managing MMRAM allocation and providing basic I/O services. These services are +/// intended for both preboot and runtime usage. +/// +struct _EFI_MM_SYSTEM_TABLE { + /// + /// The table header for the SMST. + /// + EFI_TABLE_HEADER Hdr; + /// + /// A pointer to a NULL-terminated Unicode string containing the vendor name. + /// It is permissible for this pointer to be NULL. + /// + CHAR16 *MmFirmwareVendor; + /// + /// The particular revision of the firmware. + /// + UINT32 MmFirmwareRevision; + + EFI_MM_INSTALL_CONFIGURATION_TABLE MmInstallConfigurationTable; + + /// + /// I/O Service + /// + EFI_MM_CPU_IO_PROTOCOL MmIo; + + /// + /// Runtime memory services + /// + EFI_ALLOCATE_POOL MmAllocatePool; + EFI_FREE_POOL MmFreePool; + EFI_ALLOCATE_PAGES MmAllocatePages; + EFI_FREE_PAGES MmFreePages; + + /// + /// MP service + /// + EFI_MM_STARTUP_THIS_AP MmStartupThisAp; + + /// + /// CPU information records + /// + + /// + /// A number between zero and and the NumberOfCpus field. This field designates + /// which processor is executing the MM infrastructure. + /// + UINTN CurrentlyExecutingCpu; + /// + /// The number of possible processors in the platform. This is a 1 based counter. + /// + UINTN NumberOfCpus; + /// + /// Points to an array, where each element describes the number of bytes in the + /// corresponding save state specified by CpuSaveState. There are always + /// NumberOfCpus entries in the array. + /// + UINTN *CpuSaveStateSize; + /// + /// Points to an array, where each element is a pointer to a CPU save state. The + /// corresponding element in CpuSaveStateSize specifies the number of bytes in the + /// save state area. There are always NumberOfCpus entries in the array. + /// + VOID **CpuSaveState; + + /// + /// Extensibility table + /// + + /// + /// The number of UEFI Configuration Tables in the buffer MmConfigurationTable. + /// + UINTN NumberOfTableEntries; + /// + /// A pointer to the UEFI Configuration Tables. The number of entries in the table is + /// NumberOfTableEntries. + /// + EFI_CONFIGURATION_TABLE *MmConfigurationTable; + + /// + /// Protocol services + /// + EFI_INSTALL_PROTOCOL_INTERFACE MmInstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE MmUninstallProtocolInterface; + EFI_HANDLE_PROTOCOL MmHandleProtocol; + EFI_MM_REGISTER_PROTOCOL_NOTIFY MmRegisterProtocolNotify; + EFI_LOCATE_HANDLE MmLocateHandle; + EFI_LOCATE_PROTOCOL MmLocateProtocol; + + /// + /// MMI Management functions + /// + EFI_MM_INTERRUPT_MANAGE MmiManage; + EFI_MM_INTERRUPT_REGISTER MmiHandlerRegister; + EFI_MM_INTERRUPT_UNREGISTER MmiHandlerUnRegister; +}; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMultiPhase.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMultiPhase.h new file mode 100644 index 0000000..a878986 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiMultiPhase.h @@ -0,0 +1,185 @@ +/** @file + Include file matches things in PI for multiple module types. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + These elements are defined in UEFI Platform Initialization Specification 1.2. + +**/ + +#ifndef __PI_MULTIPHASE_H__ +#define __PI_MULTIPHASE_H__ + +#include +#include +#include +#include +#include +#include +#include + +/** + Produces an error code in the range reserved for use by the Platform Initialization + Architecture Specification. + + The supported 32-bit range is 0xA0000000-0xBFFFFFFF + The supported 64-bit range is 0xA000000000000000-0xBFFFFFFFFFFFFFFF + + @param StatusCode The status code value to convert into a warning code. + StatusCode must be in the range 0x00000000..0x1FFFFFFF. + + @return The value specified by StatusCode in the PI reserved range. + +**/ +#define DXE_ERROR(StatusCode) (MAX_BIT | (MAX_BIT >> 2) | StatusCode) + +/// +/// If this value is returned by an EFI image, then the image should be unloaded. +/// +#define EFI_REQUEST_UNLOAD_IMAGE DXE_ERROR (1) + +/// +/// If this value is returned by an API, it means the capability is not yet +/// installed/available/ready to use. +/// +#define EFI_NOT_AVAILABLE_YET DXE_ERROR (2) + +/// +/// Success and warning codes reserved for use by PI. +/// Supported 32-bit range is 0x20000000-0x3fffffff. +/// Supported 64-bit range is 0x2000000000000000-0x3fffffffffffffff. +/// +#define PI_ENCODE_WARNING(a) ((MAX_BIT >> 2) | (a)) + +/// +/// Error codes reserved for use by PI. +/// Supported 32-bit range is 0xa0000000-0xbfffffff. +/// Supported 64-bit range is 0xa000000000000000-0xbfffffffffffffff. +/// +#define PI_ENCODE_ERROR(a) (MAX_BIT | (MAX_BIT >> 2) | (a)) + +/// +/// Return status codes defined in SMM CIS. +/// +#define EFI_INTERRUPT_PENDING PI_ENCODE_ERROR (0) + +#define EFI_WARN_INTERRUPT_SOURCE_PENDING PI_ENCODE_WARNING (0) +#define EFI_WARN_INTERRUPT_SOURCE_QUIESCED PI_ENCODE_WARNING (1) + +/// +/// Bitmask of values for Authentication Status. +/// Authentication Status is returned from EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL +/// and the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI +/// +/// xx00 Image was not signed. +/// xxx1 Platform security policy override. Assumes the same meaning as 0010 (the image was signed, the +/// signature was tested, and the signature passed authentication test). +/// 0010 Image was signed, the signature was tested, and the signature passed authentication test. +/// 0110 Image was signed and the signature was not tested. +/// 1010 Image was signed, the signature was tested, and the signature failed the authentication test. +/// +///@{ +#define EFI_AUTH_STATUS_PLATFORM_OVERRIDE 0x01 +#define EFI_AUTH_STATUS_IMAGE_SIGNED 0x02 +#define EFI_AUTH_STATUS_NOT_TESTED 0x04 +#define EFI_AUTH_STATUS_TEST_FAILED 0x08 +#define EFI_AUTH_STATUS_ALL 0x0f +///@} + +/// +/// MMRAM states and capabilities +/// +#define EFI_MMRAM_OPEN 0x00000001 +#define EFI_MMRAM_CLOSED 0x00000002 +#define EFI_MMRAM_LOCKED 0x00000004 +#define EFI_CACHEABLE 0x00000008 +#define EFI_ALLOCATED 0x00000010 +#define EFI_NEEDS_TESTING 0x00000020 +#define EFI_NEEDS_ECC_INITIALIZATION 0x00000040 + +#define EFI_SMRAM_OPEN EFI_MMRAM_OPEN +#define EFI_SMRAM_CLOSED EFI_MMRAM_CLOSED +#define EFI_SMRAM_LOCKED EFI_MMRAM_LOCKED + +/// +/// Structure describing a MMRAM region and its accessibility attributes. +/// +typedef struct { + /// + /// Designates the physical address of the MMRAM in memory. This view of memory is + /// the same as seen by I/O-based agents, for example, but it may not be the address seen + /// by the processors. + /// + EFI_PHYSICAL_ADDRESS PhysicalStart; + /// + /// Designates the address of the MMRAM, as seen by software executing on the + /// processors. This address may or may not match PhysicalStart. + /// + EFI_PHYSICAL_ADDRESS CpuStart; + /// + /// Describes the number of bytes in the MMRAM region. + /// + UINT64 PhysicalSize; + /// + /// Describes the accessibility attributes of the MMRAM. These attributes include the + /// hardware state (e.g., Open/Closed/Locked), capability (e.g., cacheable), logical + /// allocation (e.g., allocated), and pre-use initialization (e.g., needs testing/ECC + /// initialization). + /// + UINT64 RegionState; +} EFI_MMRAM_DESCRIPTOR; + +typedef EFI_MMRAM_DESCRIPTOR EFI_SMRAM_DESCRIPTOR; + +typedef enum { + EFI_PCD_TYPE_8, + EFI_PCD_TYPE_16, + EFI_PCD_TYPE_32, + EFI_PCD_TYPE_64, + EFI_PCD_TYPE_BOOL, + EFI_PCD_TYPE_PTR +} EFI_PCD_TYPE; + +typedef struct { + /// + /// The returned information associated with the requested TokenNumber. If + /// TokenNumber is 0, then PcdType is set to EFI_PCD_TYPE_8. + /// + EFI_PCD_TYPE PcdType; + /// + /// The size of the data in bytes associated with the TokenNumber specified. If + /// TokenNumber is 0, then PcdSize is set 0. + /// + UINTN PcdSize; + /// + /// The null-terminated ASCII string associated with a given token. If the + /// TokenNumber specified was 0, then this field corresponds to the null-terminated + /// ASCII string associated with the token's namespace Guid. If NULL, there is no + /// name associated with this request. + /// + CHAR8 *PcdName; +} EFI_PCD_INFO; + +/** + The function prototype for invoking a function on an Application Processor. + + This definition is used by the UEFI MP Serices Protocol, and the + PI SMM System Table. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +typedef +VOID +(EFIAPI *EFI_AP_PROCEDURE)( + IN OUT VOID *Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiPeiCis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiPeiCis.h new file mode 100644 index 0000000..16f0e2f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiPeiCis.h @@ -0,0 +1,1070 @@ +/** @file + PI PEI master include file. This file should match the PI spec. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.6. + +**/ + +#ifndef __PI_PEICIS_H__ +#define __PI_PEICIS_H__ + +#include +#include + +/// +/// The handles of EFI FV. +/// +typedef VOID *EFI_PEI_FV_HANDLE; + +/// +/// The handles of EFI FFS. +/// +typedef VOID *EFI_PEI_FILE_HANDLE; + +/// +/// Declare the forward reference data structure for EFI_PEI_SERVICE. +/// +typedef struct _EFI_PEI_SERVICES EFI_PEI_SERVICES; + +/// +/// Declare the forward reference data structure for EFI_PEI_NOTIFY_DESCRIPTOR. +/// +typedef struct _EFI_PEI_NOTIFY_DESCRIPTOR EFI_PEI_NOTIFY_DESCRIPTOR; + + +#include +#include + + +/** + The PEI Dispatcher will invoke each PEIM one time. During this pass, the PEI + Dispatcher will pass control to the PEIM at the AddressOfEntryPoint in the PE Header. + + @param FileHandle Pointer to the FFS file header. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The PEI completed successfully. + @retval !EFI_SUCCESS There is error in PEIM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEIM_ENTRY_POINT2)( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + Entry point of the notification callback function itself within the PEIM. + + @param PeiServices Indirect reference to the PEI Services Table. + @param NotifyDescriptor Address of the notification descriptor data structure. + @param Ppi Address of the PPI that was installed. + + @return Status of the notification. + The status code returned from this function is ignored. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEIM_NOTIFY_ENTRY_POINT)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +// +// PEI Ppi Services List Descriptors +// +#define EFI_PEI_PPI_DESCRIPTOR_PIC 0x00000001 +#define EFI_PEI_PPI_DESCRIPTOR_PPI 0x00000010 +#define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK 0x00000020 +#define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH 0x00000040 +#define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES 0x00000060 +#define EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST 0x80000000 + +/// +/// The data structure through which a PEIM describes available services to the PEI Foundation. +/// +typedef struct { + /// + /// This field is a set of flags describing the characteristics of this imported table entry. + /// All flags are defined as EFI_PEI_PPI_DESCRIPTOR_***, which can also be combined into one. + /// + UINTN Flags; + /// + /// The address of the EFI_GUID that names the interface. + /// + EFI_GUID *Guid; + /// + /// A pointer to the PPI. It contains the information necessary to install a service. + /// + VOID *Ppi; +} EFI_PEI_PPI_DESCRIPTOR; + +/// +/// The data structure in a given PEIM that tells the PEI +/// Foundation where to invoke the notification service. +/// +struct _EFI_PEI_NOTIFY_DESCRIPTOR { + /// + /// Details if the type of notification are callback or dispatch. + /// + UINTN Flags; + /// + /// The address of the EFI_GUID that names the interface. + /// + EFI_GUID *Guid; + /// + /// Address of the notification callback function itself within the PEIM. + /// + EFI_PEIM_NOTIFY_ENTRY_POINT Notify; +}; + +/// +/// This data structure is the means by which callable services are installed and +/// notifications are registered in the PEI phase. +/// +typedef union { + /// + /// The typedef structure of the notification descriptor. + /// + EFI_PEI_NOTIFY_DESCRIPTOR Notify; + /// + /// The typedef structure of the PPI descriptor. + /// + EFI_PEI_PPI_DESCRIPTOR Ppi; +} EFI_PEI_DESCRIPTOR; + +/** + This service is the first one provided by the PEI Foundation. This function + installs an interface in the PEI PPI database by GUID. The purpose of the + service is to publish an interface that other parties can use to call + additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table + published by 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 or 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_INSTALL_PPI)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +/** + This function reinstalls an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to replace a same-named interface in the protocol database + with a different interface. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table + published by the PEI Foundation. + @param OldPpi A pointer to the former PPI in the database. + @param NewPpi A pointer to the new interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL or 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_REINSTALL_PPI)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN CONST EFI_PEI_PPI_DESCRIPTOR *NewPpi + ); + +/** + This function locates an interface in the PEI PPI database by GUID. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES published by the PEI Foundation. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOCATE_PPI)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor OPTIONAL, + IN OUT VOID **Ppi + ); + +/** + This function installs a notification service to be called back when a + given interface is installed or reinstalled. The purpose of the service + is to publish an interface that other parties can use to call additional PPIs + that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @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 PpiList pointer is NULL, or any of the PEI PPI 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_NOTIFY_PPI)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ); + +/** + This function returns the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode returned successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_BOOT_MODE)( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ); + +/** + This function sets the value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The boot mode returned successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SET_BOOT_MODE)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +/** + This function returns the pointer to the list of Hand-Off Blocks (HOBs) in memory. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_HOB_LIST)( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT VOID **HobList + ); + +/** + This service, published by the PEI Foundation, abstracts the creation of a Hand-Off Block's (HOB's) headers. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CREATE_HOB)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ); + +/** + The purpose of the service is to abstract the capability of the PEI + Foundation to discover instances of firmware volumes in the system. + + This service enables PEIMs to discover additional firmware volumes. The PEI Foundation uses this + service to abstract the locations and formats of various firmware volumes. These volumes include + the Boot Firmware Volume and any other volumes exposed by EFI_PEI_FV_PPI. The service + returns a volume handle of type EFI_PEI_FV_HANDLE, which must be unique within the system. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Instance This instance of the firmware volume to find. + The value 0 is the Boot Firmware Volume (BFV). + @param VolumeHandle On exit, points to the next volumn handle or NULL if it does not exist. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_INVALID_PARAMETER VolumeHandle is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_NEXT_VOLUME2)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + OUT EFI_PEI_FV_HANDLE *VolumeHandle + ); + +/** + Searches for the next matching file in the firmware volume. + + This service enables PEIMs to discover firmware files within a specified volume. + To find the first instance of a firmware file, pass a FileHandle value of NULL into the service. + The service returns a file handle of type EFI_PEI_FILE_HANDLE, which must be unique within + the system. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SearchType A filter to find files only of this type. + @param FvHandle Handle of firmware volume in which to search. + @param FileHandle On entry, points to the current handle from which to begin searching + or NULL to start at the beginning of the firmware volume. + On exit, points the file handle of the next file in the volume or NULL + if there are no more files. + + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_NEXT_FILE2)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN CONST EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/** + Searches for the next matching section within the specified file. + + This service enables PEI modules to discover the first section of a given type within a valid file. + This service will search within encapsulation sections (compression and GUIDed) as well. It will + search inside of a GUIDed section or a compressed section, but may not, for example, search a + GUIDed section inside a GUIDes section. + This service will not search within compression sections or GUIDed sections that require + extraction if memory is not present. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType The value of the section type to find. + @param FileHandle Handle of the firmware file to search. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_SECTION_DATA2)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + +/** + Searches for the next matching section within the specified file. + + This service enables PEI modules to discover the section of a given type within a valid file. + This service will search within encapsulation sections (compression and GUIDed) as well. It will + search inside of a GUIDed section or a compressed section, but may not, for example, search a + GUIDed section inside a GUIDes section. + This service will not search within compression sections or GUIDed sections that require + extraction if memory is not present. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param SectionType The value of the section type to find. + @param SectionInstance Section instance to find. + @param FileHandle Handle of the firmware file to search. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_SECTION_DATA3)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus + ); + +/** + This function registers the found memory configuration with the PEI Foundation. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_INSTALL_PEI_MEMORY)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap. + After InstallPeiMemory() is called, PEI will allocate pages within the region + of memory provided by InstallPeiMemory() service in a best-effort fashion. + Location-specific allocations are not managed by the PEI foundation code. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory A pointer to a physical address. On output, the address is set to the base + of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_INVALID_PARAMETER The type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode, + EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData, + EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_ALLOCATE_PAGES)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param[in] Memory The base physical address of the pages to be freed. + @param[in] Pages The number of contiguous 4 KB 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(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FREE_PAGES) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +/** + The purpose of this service is to publish an interface that + allows PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Size The number of bytes to allocate from the pool. + @param Buffer If the call succeeds, a pointer to a pointer to the allocated buffer; undefined otherwise. + + @retval EFI_SUCCESS The allocation was successful. + @retval EFI_OUT_OF_RESOURCES There is not enough heap to allocate the requested size. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_ALLOCATE_POOL)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + This service copies the contents of one buffer to another buffer. + + @param Destination The pointer to the destination buffer of the memory copy. + @param Source The pointer to the source buffer of the memory copy. + @param Length The number of bytes to copy from Source to Destination. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_COPY_MEM)( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +/** + The service fills a buffer with a specified value. + + @param Buffer The pointer to the buffer to fill. + @param Size The number of bytes in Buffer to fill. + @param Value The value to fill Buffer with. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_SET_MEM)( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +/** + This service publishes an interface that allows PEIMs to report status codes. + + ReportStatusCode() is called by PEIMs that wish to report status information on their + progress. The principal use model is for a PEIM to emit one of the standard 32-bit error codes. This + will allow a platform owner to ascertain the state of the system, especially under conditions where + the full consoles might not have been installed. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + @param Type Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_AVAILABLE_YET No progress code provider has installed an interface in the system. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_REPORT_STATUS_CODE)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId OPTIONAL, + IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + Resets the entire platform. + + This service resets the entire platform, including all processors + and devices, and reboots the system. + This service will never return EFI_SUCCESS. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES + table published by the PEI Foundation. + + @retval EFI_NOT_AVAILABLE_YET The service has not been installed yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_RESET_SYSTEM)( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + 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. ResetData is only valid if ResetStatus is something + other than EFI_SUCCESS unless the ResetType is EfiResetPlatformSpecific + where a minimum amount of ResetData is always required. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_RESET2_SYSTEM) ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + Find a file within a volume by its name. + + This service searches for files with a specific name, within + either the specified firmware volume or all firmware volumes. + The service returns a file handle of type EFI_PEI_FILE_HANDLE, + which must be unique within the system. + + @param FileName A pointer to the name of the file to + find within the firmware volume. + @param VolumeHandle The firmware volume to search. + @param FileHandle Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or + FileName was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_BY_NAME)( + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + +/// +/// The information of the FV file. +/// +typedef struct { + /// + /// Name of the file. + /// + EFI_GUID FileName; + /// + /// File type. + /// + EFI_FV_FILETYPE FileType; + /// + /// Attributes of the file. + /// + EFI_FV_FILE_ATTRIBUTES FileAttributes; + /// + /// Points to the file's data (not the header). + /// Not valid if EFI_FV_FILE_ATTRIB_MEMORY_MAPPED + /// is zero. + /// + VOID *Buffer; + /// + /// Size of the file's data. + /// + UINT32 BufferSize; +} EFI_FV_FILE_INFO; + +/// +/// The information with authentication status of the FV file. +/// +typedef struct { + /// + /// Name of the file. + /// + EFI_GUID FileName; + /// + /// File type. + /// + EFI_FV_FILETYPE FileType; + /// + /// Attributes of the file. + /// + EFI_FV_FILE_ATTRIBUTES FileAttributes; + /// + /// Points to the file's data (not the header). + /// Not valid if EFI_FV_FILE_ATTRIB_MEMORY_MAPPED + /// is zero. + /// + VOID *Buffer; + /// + /// Size of the file's data. + /// + UINT32 BufferSize; + /// + /// Authentication status for this file. + /// + UINT32 AuthenticationStatus; +} EFI_FV_FILE_INFO2; + +/** + Returns information about a specific file. + + This function returns information about a specific file, + including its file name, type, attributes, starting address and + size. If the firmware volume is not memory mapped, then the + Buffer member will be NULL. + + @param FileHandle The handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information was returned. + @retval EFI_INVALID_PARAMETER FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER FileInfo is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_GET_FILE_INFO)( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + +/** + Returns information about a specific file. + + This function returns information about a specific file, + including its file name, type, attributes, starting address, size and authentication status. + If the firmware volume is not memory mapped, then the Buffer member will be NULL. + + @param FileHandle The handle of the file. + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information was returned. + @retval EFI_INVALID_PARAMETER FileHandle does not + represent a valid file. + @retval EFI_INVALID_PARAMETER FileInfo is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_GET_FILE_INFO2)( + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo + ); + +/// +/// The information of the FV volume. +/// +typedef struct { + /// + /// Attributes of the firmware volume. + /// + EFI_FVB_ATTRIBUTES_2 FvAttributes; + /// + /// Format of the firmware volume. + /// + EFI_GUID FvFormat; + /// + /// Name of the firmware volume. + /// + EFI_GUID FvName; + /// + /// Points to the first byte of the firmware + /// volume, if bit EFI_FVB_MEMORY_MAPPED is + /// set in FvAttributes. + /// + VOID *FvStart; + /// + /// Size of the firmware volume. + /// + UINT64 FvSize; +} EFI_FV_INFO; + +/** + Returns information about the specified volume. + + This function returns information about a specific firmware + volume, including its name, type, attributes, starting address + and size. + + @param VolumeHandle Handle of the volume. + @param VolumeInfo Upon exit, points to the volume's information. + + @retval EFI_SUCCESS The volume information returned. + @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume. + @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL. + @retval EFI_SUCCESS Information was successfully returned. + @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_GET_VOLUME_INFO)( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + +/** + Register a PEIM so that it will be shadowed and called again. + + This service registers a file handle so that after memory is + available, the PEIM will be re-loaded into permanent memory and + re-initialized. The PEIM registered this way will always be + initialized twice. The first time, this function call will + return EFI_SUCCESS. The second time, this function call will + return EFI_ALREADY_STARTED. Depending on the order in which + PEIMs are dispatched, the PEIM making this call may be + initialized after permanent memory is installed, even the first + time. + + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_REGISTER_FOR_SHADOW)( + IN EFI_PEI_FILE_HANDLE FileHandle + ); + + +// +// PEI Specification Revision information +// +#define PEI_SPECIFICATION_MAJOR_REVISION 1 +#define PEI_SPECIFICATION_MINOR_REVISION 60 +/// +/// Specification inconsistency here: +/// In the PI1.0 spec, PEI_SERVICES_SIGNATURE is defined as 0x5652455320494550. But +/// to pass a multiple tool chain, it appends an ULL. +/// +// +// PEI Services Table +// +#define PEI_SERVICES_SIGNATURE 0x5652455320494550ULL +/// +/// Specification inconsistency here: +/// In the PI1.0 specification, there is a typo error in PEI_SERVICES_REVISION. In the specification the defintion is +/// #define ((PEI_SPECIFICATION_MAJOR_REVISION<<16) |(PEI_SPECIFICATION_MINOR_REVISION)) +/// and it should be as follows: +/// +#define PEI_SERVICES_REVISION ((PEI_SPECIFICATION_MAJOR_REVISION<<16) | (PEI_SPECIFICATION_MINOR_REVISION)) + +/// +/// EFI_PEI_SERVICES is a collection of functions whose implementation is provided by the PEI +/// Foundation. These services fall into various classes, including the following: +/// - Managing the boot mode +/// - Allocating both early and permanent memory +/// - Supporting the Firmware File System (FFS) +/// - Abstracting the PPI database abstraction +/// - Creating Hand-Off Blocks (HOBs). +/// +struct _EFI_PEI_SERVICES { + /// + /// The table header for the PEI Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // PPI Functions + // + EFI_PEI_INSTALL_PPI InstallPpi; + EFI_PEI_REINSTALL_PPI ReInstallPpi; + EFI_PEI_LOCATE_PPI LocatePpi; + EFI_PEI_NOTIFY_PPI NotifyPpi; + + // + // Boot Mode Functions + // + EFI_PEI_GET_BOOT_MODE GetBootMode; + EFI_PEI_SET_BOOT_MODE SetBootMode; + + // + // HOB Functions + // + EFI_PEI_GET_HOB_LIST GetHobList; + EFI_PEI_CREATE_HOB CreateHob; + + // + // Firmware Volume Functions + // + EFI_PEI_FFS_FIND_NEXT_VOLUME2 FfsFindNextVolume; + EFI_PEI_FFS_FIND_NEXT_FILE2 FfsFindNextFile; + EFI_PEI_FFS_FIND_SECTION_DATA2 FfsFindSectionData; + + // + // PEI Memory Functions + // + EFI_PEI_INSTALL_PEI_MEMORY InstallPeiMemory; + EFI_PEI_ALLOCATE_PAGES AllocatePages; + EFI_PEI_ALLOCATE_POOL AllocatePool; + EFI_PEI_COPY_MEM CopyMem; + EFI_PEI_SET_MEM SetMem; + + // + // Status Code + // + EFI_PEI_REPORT_STATUS_CODE ReportStatusCode; + + // + // Reset + // + EFI_PEI_RESET_SYSTEM ResetSystem; + + // + // (the following interfaces are installed by publishing PEIM) + // I/O Abstractions + // + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_PEI_PCI_CFG2_PPI *PciCfg; + + // + // Future Installed Services + // + EFI_PEI_FFS_FIND_BY_NAME FfsFindFileByName; + EFI_PEI_FFS_GET_FILE_INFO FfsGetFileInfo; + EFI_PEI_FFS_GET_VOLUME_INFO FfsGetVolumeInfo; + EFI_PEI_REGISTER_FOR_SHADOW RegisterForShadow; + EFI_PEI_FFS_FIND_SECTION_DATA3 FindSectionData3; + EFI_PEI_FFS_GET_FILE_INFO2 FfsGetFileInfo2; + EFI_PEI_RESET2_SYSTEM ResetSystem2; + EFI_PEI_FREE_PAGES FreePages; +}; + + +/// +/// EFI_SEC_PEI_HAND_OFF structure holds information about +/// PEI core's operating environment, such as the size of location of +/// temporary RAM, the stack location and BFV location. +/// +typedef struct _EFI_SEC_PEI_HAND_OFF { + /// + /// Size of the data structure. + /// + UINT16 DataSize; + + /// + /// Points to the first byte of the boot firmware volume, + /// which the PEI Dispatcher should search for + /// PEI modules. + /// + VOID *BootFirmwareVolumeBase; + + /// + /// Size of the boot firmware volume, in bytes. + /// + UINTN BootFirmwareVolumeSize; + + /// + /// Points to the first byte of the temporary RAM. + /// + VOID *TemporaryRamBase; + + /// + /// Size of the temporary RAM, in bytes. + /// + UINTN TemporaryRamSize; + + /// + /// Points to the first byte of the temporary RAM + /// available for use by the PEI Foundation. The area + /// described by PeiTemporaryRamBase and PeiTemporaryRamSize + /// must not extend outside beyond the area described by + /// TemporaryRamBase & TemporaryRamSize. This area should not + /// overlap with the area reported by StackBase and + /// StackSize. + /// + VOID *PeiTemporaryRamBase; + + /// + /// The size of the available temporary RAM available for + /// use by the PEI Foundation, in bytes. + /// + UINTN PeiTemporaryRamSize; + + /// + /// Points to the first byte of the stack. + /// This are may be part of the memory described by + /// TemporaryRamBase and TemporaryRamSize + /// or may be an entirely separate area. + /// + VOID *StackBase; + + /// + /// Size of the stack, in bytes. + /// + UINTN StackSize; +} EFI_SEC_PEI_HAND_OFF; + + +/** + The entry point of PEI Foundation. + + 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. These PPI's + will be installed and/or immediately signaled if they are + notification type. 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. + + @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. + + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CORE_ENTRY_POINT)( + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList +); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiS3BootScript.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiS3BootScript.h new file mode 100644 index 0000000..378736b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiS3BootScript.h @@ -0,0 +1,59 @@ +/** @file + This file contains the boot script defintions that are shared between the + Boot Script Executor PPI and the Boot Script Save Protocol. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PI_S3_BOOT_SCRIPT_H_ +#define _PI_S3_BOOT_SCRIPT_H_ + +//******************************************* +// EFI Boot Script Opcode definitions +//******************************************* +#define EFI_BOOT_SCRIPT_IO_WRITE_OPCODE 0x00 +#define EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE 0x01 +#define EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE 0x02 +#define EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE 0x03 +#define EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE 0x04 +#define EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE 0x05 +#define EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE 0x06 +#define EFI_BOOT_SCRIPT_STALL_OPCODE 0x07 +#define EFI_BOOT_SCRIPT_DISPATCH_OPCODE 0x08 +#define EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE 0x09 +#define EFI_BOOT_SCRIPT_INFORMATION_OPCODE 0x0A +#define EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE 0x0B +#define EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE 0x0C +#define EFI_BOOT_SCRIPT_IO_POLL_OPCODE 0x0D +#define EFI_BOOT_SCRIPT_MEM_POLL_OPCODE 0x0E +#define EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE 0x0F +#define EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE 0x10 + +//******************************************* +// EFI_BOOT_SCRIPT_WIDTH +//******************************************* +typedef enum { + EfiBootScriptWidthUint8, + EfiBootScriptWidthUint16, + EfiBootScriptWidthUint32, + EfiBootScriptWidthUint64, + EfiBootScriptWidthFifoUint8, + EfiBootScriptWidthFifoUint16, + EfiBootScriptWidthFifoUint32, + EfiBootScriptWidthFifoUint64, + EfiBootScriptWidthFillUint8, + EfiBootScriptWidthFillUint16, + EfiBootScriptWidthFillUint32, + EfiBootScriptWidthFillUint64, + EfiBootScriptWidthMaximum +} EFI_BOOT_SCRIPT_WIDTH; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiSmmCis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiSmmCis.h new file mode 100644 index 0000000..c3941ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiSmmCis.h @@ -0,0 +1,206 @@ +/** @file + Common definitions in the Platform Initialization Specification version 1.4a + VOLUME 4 System Management Mode Core Interface version. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PI_SMMCIS_H_ +#define _PI_SMMCIS_H_ + +#include +#include + +typedef struct _EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2; +// +// Define new MM related definition introduced by PI 1.5. +// +#define SMM_SMST_SIGNATURE MM_MMST_SIGNATURE +#define SMM_SPECIFICATION_MAJOR_REVISION MM_SPECIFICATION_MAJOR_REVISION +#define SMM_SPECIFICATION_MINOR_REVISION MM_SPECIFICATION_MINOR_REVISION +#define EFI_SMM_SYSTEM_TABLE2_REVISION EFI_MM_SYSTEM_TABLE_REVISION + +/** + Adds, updates, or removes a configuration table entry from the System Management System Table. + + The SmmInstallConfigurationTable() function is used to maintain the list + of configuration tables that are stored in the System Management System + Table. The list is stored as an array of (GUID, Pointer) pairs. The list + must be allocated from pool memory with PoolType set to EfiRuntimeServicesData. + + @param[in] SystemTable A pointer to the SMM System Table (SMST). + @param[in] Guid A pointer to the GUID for the entry to add, update, or remove. + @param[in] Table A pointer to the buffer of the table to add. + @param[in] TableSize The size of the table to install. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_INSTALL_CONFIGURATION_TABLE2)( + IN CONST EFI_SMM_SYSTEM_TABLE2 *SystemTable, + IN CONST EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ); + +typedef EFI_MM_STARTUP_THIS_AP EFI_SMM_STARTUP_THIS_AP; +typedef EFI_MM_NOTIFY_FN EFI_SMM_NOTIFY_FN; +typedef EFI_MM_REGISTER_PROTOCOL_NOTIFY EFI_SMM_REGISTER_PROTOCOL_NOTIFY; +typedef EFI_MM_INTERRUPT_MANAGE EFI_SMM_INTERRUPT_MANAGE; +typedef EFI_MM_HANDLER_ENTRY_POINT EFI_SMM_HANDLER_ENTRY_POINT2; +typedef EFI_MM_INTERRUPT_REGISTER EFI_SMM_INTERRUPT_REGISTER; +typedef EFI_MM_INTERRUPT_UNREGISTER EFI_SMM_INTERRUPT_UNREGISTER; + +/// +/// Processor information and functionality needed by SMM Foundation. +/// +typedef struct _EFI_SMM_ENTRY_CONTEXT { + EFI_SMM_STARTUP_THIS_AP SmmStartupThisAp; + /// + /// A number between zero and the NumberOfCpus field. This field designates which + /// processor is executing the SMM Foundation. + /// + UINTN CurrentlyExecutingCpu; + /// + /// The number of possible processors in the platform. This is a 1 based + /// counter. This does not indicate the number of processors that entered SMM. + /// + UINTN NumberOfCpus; + /// + /// Points to an array, where each element describes the number of bytes in the + /// corresponding save state specified by CpuSaveState. There are always + /// NumberOfCpus entries in the array. + /// + UINTN *CpuSaveStateSize; + /// + /// Points to an array, where each element is a pointer to a CPU save state. The + /// corresponding element in CpuSaveStateSize specifies the number of bytes in the + /// save state area. There are always NumberOfCpus entries in the array. + /// + VOID **CpuSaveState; +} EFI_SMM_ENTRY_CONTEXT; + +/** + This function is the main entry point to the SMM Foundation. + + @param[in] SmmEntryContext Processor information and functionality needed by SMM Foundation. +**/ +typedef +VOID +(EFIAPI *EFI_SMM_ENTRY_POINT)( + IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext + ); + +/// +/// System Management System Table (SMST) +/// +/// The System Management System Table (SMST) is a table that contains a collection of common +/// services for managing SMRAM allocation and providing basic I/O services. These services are +/// intended for both preboot and runtime usage. +/// +struct _EFI_SMM_SYSTEM_TABLE2 { + /// + /// The table header for the SMST. + /// + EFI_TABLE_HEADER Hdr; + /// + /// A pointer to a NULL-terminated Unicode string containing the vendor name. + /// It is permissible for this pointer to be NULL. + /// + CHAR16 *SmmFirmwareVendor; + /// + /// The particular revision of the firmware. + /// + UINT32 SmmFirmwareRevision; + + EFI_SMM_INSTALL_CONFIGURATION_TABLE2 SmmInstallConfigurationTable; + + /// + /// I/O Service + /// + EFI_SMM_CPU_IO2_PROTOCOL SmmIo; + + /// + /// Runtime memory services + /// + EFI_ALLOCATE_POOL SmmAllocatePool; + EFI_FREE_POOL SmmFreePool; + EFI_ALLOCATE_PAGES SmmAllocatePages; + EFI_FREE_PAGES SmmFreePages; + + /// + /// MP service + /// + EFI_SMM_STARTUP_THIS_AP SmmStartupThisAp; + + /// + /// CPU information records + /// + + /// + /// A number between zero and and the NumberOfCpus field. This field designates + /// which processor is executing the SMM infrastructure. + /// + UINTN CurrentlyExecutingCpu; + /// + /// The number of possible processors in the platform. This is a 1 based counter. + /// + UINTN NumberOfCpus; + /// + /// Points to an array, where each element describes the number of bytes in the + /// corresponding save state specified by CpuSaveState. There are always + /// NumberOfCpus entries in the array. + /// + UINTN *CpuSaveStateSize; + /// + /// Points to an array, where each element is a pointer to a CPU save state. The + /// corresponding element in CpuSaveStateSize specifies the number of bytes in the + /// save state area. There are always NumberOfCpus entries in the array. + /// + VOID **CpuSaveState; + + /// + /// Extensibility table + /// + + /// + /// The number of UEFI Configuration Tables in the buffer SmmConfigurationTable. + /// + UINTN NumberOfTableEntries; + /// + /// A pointer to the UEFI Configuration Tables. The number of entries in the table is + /// NumberOfTableEntries. + /// + EFI_CONFIGURATION_TABLE *SmmConfigurationTable; + + /// + /// Protocol services + /// + EFI_INSTALL_PROTOCOL_INTERFACE SmmInstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE SmmUninstallProtocolInterface; + EFI_HANDLE_PROTOCOL SmmHandleProtocol; + EFI_SMM_REGISTER_PROTOCOL_NOTIFY SmmRegisterProtocolNotify; + EFI_LOCATE_HANDLE SmmLocateHandle; + EFI_LOCATE_PROTOCOL SmmLocateProtocol; + + /// + /// SMI Management functions + /// + EFI_SMM_INTERRUPT_MANAGE SmiManage; + EFI_SMM_INTERRUPT_REGISTER SmiHandlerRegister; + EFI_SMM_INTERRUPT_UNREGISTER SmiHandlerUnRegister; +}; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiStatusCode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiStatusCode.h new file mode 100644 index 0000000..b63fee8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Pi/PiStatusCode.h @@ -0,0 +1,1200 @@ +/** @file + StatusCode related definitions in PI. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + These status codes are defined in UEFI Platform Initialization Specification 1.2, + Volume 3: Shared Architectural Elements. + +**/ + +#ifndef __PI_STATUS_CODE_H__ +#define __PI_STATUS_CODE_H__ + +// +// Required for IA32, X64, IPF, ARM and EBC defines for CPU exception types +// +#include + +/// +/// Status Code Type Definition. +/// +typedef UINT32 EFI_STATUS_CODE_TYPE; + +/// +/// A Status Code Type is made up of the code type and severity. +/// All values masked by EFI_STATUS_CODE_RESERVED_MASK are +/// reserved for use by this specification. +/// +///@{ +#define EFI_STATUS_CODE_TYPE_MASK 0x000000FF +#define EFI_STATUS_CODE_SEVERITY_MASK 0xFF000000 +#define EFI_STATUS_CODE_RESERVED_MASK 0x00FFFF00 +///@} + +/// +/// Definition of code types. All other values masked by +/// EFI_STATUS_CODE_TYPE_MASK are reserved for use by +/// this specification. +/// +///@{ +#define EFI_PROGRESS_CODE 0x00000001 +#define EFI_ERROR_CODE 0x00000002 +#define EFI_DEBUG_CODE 0x00000003 +///@} + +/// +/// Definitions of severities, all other values masked by +/// EFI_STATUS_CODE_SEVERITY_MASK are reserved for use by +/// this specification. +/// Uncontained errors are major errors that could not contained +/// to the specific component that is reporting the error. +/// For example, if a memory error was not detected early enough, +/// the bad data could be consumed by other drivers. +/// +///@{ +#define EFI_ERROR_MINOR 0x40000000 +#define EFI_ERROR_MAJOR 0x80000000 +#define EFI_ERROR_UNRECOVERED 0x90000000 +#define EFI_ERROR_UNCONTAINED 0xa0000000 +///@} + +/// +/// Status Code Value Definition. +/// +typedef UINT32 EFI_STATUS_CODE_VALUE; + +/// +/// A Status Code Value is made up of the class, subclass, and +/// an operation. +/// +///@{ +#define EFI_STATUS_CODE_CLASS_MASK 0xFF000000 +#define EFI_STATUS_CODE_SUBCLASS_MASK 0x00FF0000 +#define EFI_STATUS_CODE_OPERATION_MASK 0x0000FFFF +///@} + +/// +/// Definition of Status Code extended data header. +/// The data will follow HeaderSize bytes from the beginning of +/// the structure and is Size bytes long. +/// +typedef struct { + /// + /// The size of the structure. This is specified to enable future expansion. + /// + UINT16 HeaderSize; + /// + /// The size of the data in bytes. This does not include the size of the header structure. + /// + UINT16 Size; + /// + /// The GUID defining the type of the data. + /// + EFI_GUID Type; +} EFI_STATUS_CODE_DATA; + +/// +/// General partitioning scheme for Progress and Error Codes are: +/// - 0x0000-0x0FFF Shared by all sub-classes in a given class. +/// - 0x1000-0x7FFF Subclass Specific. +/// - 0x8000-0xFFFF OEM specific. +///@{ +#define EFI_SUBCLASS_SPECIFIC 0x1000 +#define EFI_OEM_SPECIFIC 0x8000 +///@} + +/// +/// Debug Code definitions for all classes and subclass. +/// Only one debug code is defined at this point and should +/// be used for anything that is sent to the debug stream. +/// +///@{ +#define EFI_DC_UNSPECIFIED 0x0 +///@} + +/// +/// Class definitions. +/// Values of 4-127 are reserved for future use by this specification. +/// Values in the range 127-255 are reserved for OEM use. +/// +///@{ +#define EFI_COMPUTING_UNIT 0x00000000 +#define EFI_PERIPHERAL 0x01000000 +#define EFI_IO_BUS 0x02000000 +#define EFI_SOFTWARE 0x03000000 +///@} + +/// +/// Computing Unit Subclass definitions. +/// Values of 8-127 are reserved for future use by this specification. +/// Values of 128-255 are reserved for OEM use. +/// +///@{ +#define EFI_COMPUTING_UNIT_UNSPECIFIED (EFI_COMPUTING_UNIT | 0x00000000) +#define EFI_COMPUTING_UNIT_HOST_PROCESSOR (EFI_COMPUTING_UNIT | 0x00010000) +#define EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR (EFI_COMPUTING_UNIT | 0x00020000) +#define EFI_COMPUTING_UNIT_IO_PROCESSOR (EFI_COMPUTING_UNIT | 0x00030000) +#define EFI_COMPUTING_UNIT_CACHE (EFI_COMPUTING_UNIT | 0x00040000) +#define EFI_COMPUTING_UNIT_MEMORY (EFI_COMPUTING_UNIT | 0x00050000) +#define EFI_COMPUTING_UNIT_CHIPSET (EFI_COMPUTING_UNIT | 0x00060000) +///@} + +/// +/// Computing Unit Class Progress Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_CU_PC_INIT_BEGIN 0x00000000 +#define EFI_CU_PC_INIT_END 0x00000001 +///@} + +// +// Computing Unit Unspecified Subclass Progress Code definitions. +// + +/// +/// Computing Unit Host Processor Subclass Progress Code definitions. +///@{ +#define EFI_CU_HP_PC_POWER_ON_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_HP_PC_CACHE_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_HP_PC_RAM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_HP_PC_MEMORY_CONTROLLER_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_HP_PC_IO_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_HP_PC_BSP_SELECT (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_HP_PC_BSP_RESELECT (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_HP_PC_AP_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_HP_PC_SMM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000008) +///@} + +// +// Computing Unit Firmware Processor Subclass Progress Code definitions. +// + +// +// Computing Unit IO Processor Subclass Progress Code definitions. +// + +/// +/// Computing Unit Cache Subclass Progress Code definitions. +/// +///@{ +#define EFI_CU_CACHE_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_CACHE_PC_CONFIGURATION (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +/// +/// Computing Unit Memory Subclass Progress Code definitions. +/// +///@{ +#define EFI_CU_MEMORY_PC_SPD_READ (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_MEMORY_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_MEMORY_PC_TIMING (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_MEMORY_PC_CONFIGURING (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_MEMORY_PC_OPTIMIZING (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_MEMORY_PC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_MEMORY_PC_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000006) +///@} + +// +// Computing Unit Chipset Subclass Progress Code definitions. +// + +/// +/// South Bridge initialization prior to memory detection. +/// +#define EFI_CHIPSET_PC_PEI_CAR_SB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000000) + +/// +/// North Bridge initialization prior to memory detection. +/// +#define EFI_CHIPSET_PC_PEI_CAR_NB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000001) + +/// +/// South Bridge initialization after memory detection. +/// +#define EFI_CHIPSET_PC_PEI_MEM_SB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000002) + +/// +/// North Bridge initialization after memory detection. +/// +#define EFI_CHIPSET_PC_PEI_MEM_NB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000003) + +/// +/// PCI Host Bridge DXE initialization. +/// +#define EFI_CHIPSET_PC_DXE_HB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000004) + +/// +/// North Bridge DXE initialization. +/// +#define EFI_CHIPSET_PC_DXE_NB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000005) + +/// +/// North Bridge specific SMM initialization in DXE. +/// +#define EFI_CHIPSET_PC_DXE_NB_SMM_INIT (EFI_SUBCLASS_SPECIFIC|0x00000006) + +/// +/// Initialization of the South Bridge specific UEFI Runtime Services. +/// +#define EFI_CHIPSET_PC_DXE_SB_RT_INIT (EFI_SUBCLASS_SPECIFIC|0x00000007) + +/// +/// South Bridge DXE initialization +/// +#define EFI_CHIPSET_PC_DXE_SB_INIT (EFI_SUBCLASS_SPECIFIC|0x00000008) + +/// +/// South Bridge specific SMM initialization in DXE. +/// +#define EFI_CHIPSET_PC_DXE_SB_SMM_INIT (EFI_SUBCLASS_SPECIFIC|0x00000009) + +/// +/// Initialization of the South Bridge devices. +/// +#define EFI_CHIPSET_PC_DXE_SB_DEVICES_INIT (EFI_SUBCLASS_SPECIFIC|0x0000000a) + +/// +/// Computing Unit Class Error Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_CU_EC_NON_SPECIFIC 0x00000000 +#define EFI_CU_EC_DISABLED 0x00000001 +#define EFI_CU_EC_NOT_SUPPORTED 0x00000002 +#define EFI_CU_EC_NOT_DETECTED 0x00000003 +#define EFI_CU_EC_NOT_CONFIGURED 0x00000004 +///@} + +// +// Computing Unit Unspecified Subclass Error Code definitions. +// + +/// +/// Computing Unit Host Processor Subclass Error Code definitions. +/// +///@{ +#define EFI_CU_HP_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_HP_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_HP_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_HP_EC_TIMER_EXPIRED (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_HP_EC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_HP_EC_INTERNAL (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_HP_EC_THERMAL (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_HP_EC_LOW_VOLTAGE (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_HP_EC_HIGH_VOLTAGE (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_CU_HP_EC_CACHE (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_CU_HP_EC_MICROCODE_UPDATE (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_CU_HP_EC_CORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_CU_HP_EC_UNCORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_CU_HP_EC_NO_MICROCODE_UPDATE (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +///@} + +/// +/// Computing Unit Firmware Processor Subclass Error Code definitions. +/// +///@{ +#define EFI_CU_FP_EC_HARD_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_FP_EC_SOFT_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_FP_EC_COMM_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002) +///@} + +// +// Computing Unit IO Processor Subclass Error Code definitions. +// + +/// +/// Computing Unit Cache Subclass Error Code definitions. +/// +///@{ +#define EFI_CU_CACHE_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_CACHE_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_CACHE_EC_INVALID_SIZE (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_CACHE_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000003) +///@} + +/// +/// Computing Unit Memory Subclass Error Code definitions. +/// +///@{ +#define EFI_CU_MEMORY_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_MEMORY_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_MEMORY_EC_CORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_MEMORY_EC_UNCORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_MEMORY_EC_SPD_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_MEMORY_EC_INVALID_SIZE (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_MEMORY_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_MEMORY_EC_S3_RESUME_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_MEMORY_EC_UPDATE_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_CU_MEMORY_EC_NONE_DETECTED (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_CU_MEMORY_EC_NONE_USEFUL (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +///@} + +/// +/// Computing Unit Chipset Subclass Error Code definitions. +/// +///@{ +#define EFI_CHIPSET_EC_BAD_BATTERY (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CHIPSET_EC_DXE_NB_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CHIPSET_EC_DXE_SB_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002) +///@} + +/// +/// Peripheral Subclass definitions. +/// Values of 12-127 are reserved for future use by this specification. +/// Values of 128-255 are reserved for OEM use. +/// +///@{ +#define EFI_PERIPHERAL_UNSPECIFIED (EFI_PERIPHERAL | 0x00000000) +#define EFI_PERIPHERAL_KEYBOARD (EFI_PERIPHERAL | 0x00010000) +#define EFI_PERIPHERAL_MOUSE (EFI_PERIPHERAL | 0x00020000) +#define EFI_PERIPHERAL_LOCAL_CONSOLE (EFI_PERIPHERAL | 0x00030000) +#define EFI_PERIPHERAL_REMOTE_CONSOLE (EFI_PERIPHERAL | 0x00040000) +#define EFI_PERIPHERAL_SERIAL_PORT (EFI_PERIPHERAL | 0x00050000) +#define EFI_PERIPHERAL_PARALLEL_PORT (EFI_PERIPHERAL | 0x00060000) +#define EFI_PERIPHERAL_FIXED_MEDIA (EFI_PERIPHERAL | 0x00070000) +#define EFI_PERIPHERAL_REMOVABLE_MEDIA (EFI_PERIPHERAL | 0x00080000) +#define EFI_PERIPHERAL_AUDIO_INPUT (EFI_PERIPHERAL | 0x00090000) +#define EFI_PERIPHERAL_AUDIO_OUTPUT (EFI_PERIPHERAL | 0x000A0000) +#define EFI_PERIPHERAL_LCD_DEVICE (EFI_PERIPHERAL | 0x000B0000) +#define EFI_PERIPHERAL_NETWORK (EFI_PERIPHERAL | 0x000C0000) +///@} + +/// +/// Peripheral Class Progress Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_P_PC_INIT 0x00000000 +#define EFI_P_PC_RESET 0x00000001 +#define EFI_P_PC_DISABLE 0x00000002 +#define EFI_P_PC_PRESENCE_DETECT 0x00000003 +#define EFI_P_PC_ENABLE 0x00000004 +#define EFI_P_PC_RECONFIG 0x00000005 +#define EFI_P_PC_DETECTED 0x00000006 +///@} + +// +// Peripheral Class Unspecified Subclass Progress Code definitions. +// + +/// +/// Peripheral Class Keyboard Subclass Progress Code definitions. +/// +///@{ +#define EFI_P_KEYBOARD_PC_CLEAR_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_P_KEYBOARD_PC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +/// +/// Peripheral Class Mouse Subclass Progress Code definitions. +/// +///@{ +#define EFI_P_MOUSE_PC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000000) +///@} + +// +// Peripheral Class Local Console Subclass Progress Code definitions. +// + +// +// Peripheral Class Remote Console Subclass Progress Code definitions. +// + +/// +/// Peripheral Class Serial Port Subclass Progress Code definitions. +/// +///@{ +#define EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000000) +///@} + +// +// Peripheral Class Parallel Port Subclass Progress Code definitions. +// + +// +// Peripheral Class Fixed Media Subclass Progress Code definitions. +// + +// +// Peripheral Class Removable Media Subclass Progress Code definitions. +// + +// +// Peripheral Class Audio Input Subclass Progress Code definitions. +// + +// +// Peripheral Class Audio Output Subclass Progress Code definitions. +// + +// +// Peripheral Class LCD Device Subclass Progress Code definitions. +// + +// +// Peripheral Class Network Subclass Progress Code definitions. +// + +/// +/// Peripheral Class Error Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_P_EC_NON_SPECIFIC 0x00000000 +#define EFI_P_EC_DISABLED 0x00000001 +#define EFI_P_EC_NOT_SUPPORTED 0x00000002 +#define EFI_P_EC_NOT_DETECTED 0x00000003 +#define EFI_P_EC_NOT_CONFIGURED 0x00000004 +#define EFI_P_EC_INTERFACE_ERROR 0x00000005 +#define EFI_P_EC_CONTROLLER_ERROR 0x00000006 +#define EFI_P_EC_INPUT_ERROR 0x00000007 +#define EFI_P_EC_OUTPUT_ERROR 0x00000008 +#define EFI_P_EC_RESOURCE_CONFLICT 0x00000009 +///@} + +// +// Peripheral Class Unspecified Subclass Error Code definitions. +// + +/// +/// Peripheral Class Keyboard Subclass Error Code definitions. +/// +///@{ +#define EFI_P_KEYBOARD_EC_LOCKED (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_P_KEYBOARD_EC_STUCK_KEY (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +/// +/// Peripheral Class Mouse Subclass Error Code definitions. +/// +///@{ +#define EFI_P_MOUSE_EC_LOCKED (EFI_SUBCLASS_SPECIFIC | 0x00000000) +///@} + +// +// Peripheral Class Local Console Subclass Error Code definitions. +// + +// +// Peripheral Class Remote Console Subclass Error Code definitions. +// + +// +// Peripheral Class Serial Port Subclass Error Code definitions. +// + +// +// Peripheral Class Parallel Port Subclass Error Code definitions. +// + +// +// Peripheral Class Fixed Media Subclass Error Code definitions. +// + +// +// Peripheral Class Removable Media Subclass Error Code definitions. +// + +// +// Peripheral Class Audio Input Subclass Error Code definitions. +// + +// +// Peripheral Class Audio Output Subclass Error Code definitions. +// + +// +// Peripheral Class LCD Device Subclass Error Code definitions. +// + +// +// Peripheral Class Network Subclass Error Code definitions. +// + +/// +/// IO Bus Subclass definitions. +/// Values of 14-127 are reserved for future use by this specification. +/// Values of 128-255 are reserved for OEM use. +/// +///@{ +#define EFI_IO_BUS_UNSPECIFIED (EFI_IO_BUS | 0x00000000) +#define EFI_IO_BUS_PCI (EFI_IO_BUS | 0x00010000) +#define EFI_IO_BUS_USB (EFI_IO_BUS | 0x00020000) +#define EFI_IO_BUS_IBA (EFI_IO_BUS | 0x00030000) +#define EFI_IO_BUS_AGP (EFI_IO_BUS | 0x00040000) +#define EFI_IO_BUS_PC_CARD (EFI_IO_BUS | 0x00050000) +#define EFI_IO_BUS_LPC (EFI_IO_BUS | 0x00060000) +#define EFI_IO_BUS_SCSI (EFI_IO_BUS | 0x00070000) +#define EFI_IO_BUS_ATA_ATAPI (EFI_IO_BUS | 0x00080000) +#define EFI_IO_BUS_FC (EFI_IO_BUS | 0x00090000) +#define EFI_IO_BUS_IP_NETWORK (EFI_IO_BUS | 0x000A0000) +#define EFI_IO_BUS_SMBUS (EFI_IO_BUS | 0x000B0000) +#define EFI_IO_BUS_I2C (EFI_IO_BUS | 0x000C0000) +///@} + +/// +/// IO Bus Class Progress Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_IOB_PC_INIT 0x00000000 +#define EFI_IOB_PC_RESET 0x00000001 +#define EFI_IOB_PC_DISABLE 0x00000002 +#define EFI_IOB_PC_DETECT 0x00000003 +#define EFI_IOB_PC_ENABLE 0x00000004 +#define EFI_IOB_PC_RECONFIG 0x00000005 +#define EFI_IOB_PC_HOTPLUG 0x00000006 +///@} + +// +// IO Bus Class Unspecified Subclass Progress Code definitions. +// + +/// +/// IO Bus Class PCI Subclass Progress Code definitions. +/// +///@{ +#define EFI_IOB_PCI_BUS_ENUM (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_PCI_RES_ALLOC (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_IOB_PCI_HPC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000002) +///@} + +// +// IO Bus Class USB Subclass Progress Code definitions. +// + +// +// IO Bus Class IBA Subclass Progress Code definitions. +// + +// +// IO Bus Class AGP Subclass Progress Code definitions. +// + +// +// IO Bus Class PC Card Subclass Progress Code definitions. +// + +// +// IO Bus Class LPC Subclass Progress Code definitions. +// + +// +// IO Bus Class SCSI Subclass Progress Code definitions. +// + +// +// IO Bus Class ATA/ATAPI Subclass Progress Code definitions. +// +#define EFI_IOB_ATA_BUS_SMART_ENABLE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_ATA_BUS_SMART_DISABLE (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD (EFI_SUBCLASS_SPECIFIC | 0x00000003) +// +// IO Bus Class FC Subclass Progress Code definitions. +// + +// +// IO Bus Class IP Network Subclass Progress Code definitions. +// + +// +// IO Bus Class SMBUS Subclass Progress Code definitions. +// + +// +// IO Bus Class I2C Subclass Progress Code definitions. +// + +/// +/// IO Bus Class Error Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_IOB_EC_NON_SPECIFIC 0x00000000 +#define EFI_IOB_EC_DISABLED 0x00000001 +#define EFI_IOB_EC_NOT_SUPPORTED 0x00000002 +#define EFI_IOB_EC_NOT_DETECTED 0x00000003 +#define EFI_IOB_EC_NOT_CONFIGURED 0x00000004 +#define EFI_IOB_EC_INTERFACE_ERROR 0x00000005 +#define EFI_IOB_EC_CONTROLLER_ERROR 0x00000006 +#define EFI_IOB_EC_READ_ERROR 0x00000007 +#define EFI_IOB_EC_WRITE_ERROR 0x00000008 +#define EFI_IOB_EC_RESOURCE_CONFLICT 0x00000009 +///@} + +// +// IO Bus Class Unspecified Subclass Error Code definitions. +// + +/// +/// IO Bus Class PCI Subclass Error Code definitions. +/// +///@{ +#define EFI_IOB_PCI_EC_PERR (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_PCI_EC_SERR (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +// +// IO Bus Class USB Subclass Error Code definitions. +// + +// +// IO Bus Class IBA Subclass Error Code definitions. +// + +// +// IO Bus Class AGP Subclass Error Code definitions. +// + +// +// IO Bus Class PC Card Subclass Error Code definitions. +// + +// +// IO Bus Class LPC Subclass Error Code definitions. +// + +// +// IO Bus Class SCSI Subclass Error Code definitions. +// + +// +// IO Bus Class ATA/ATAPI Subclass Error Code definitions. +// +#define EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_ATA_BUS_SMART_DISABLED (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// IO Bus Class FC Subclass Error Code definitions. +// + +// +// IO Bus Class IP Network Subclass Error Code definitions. +// + +// +// IO Bus Class SMBUS Subclass Error Code definitions. +// + +// +// IO Bus Class I2C Subclass Error Code definitions. +// + +/// +/// Software Subclass definitions. +/// Values of 14-127 are reserved for future use by this specification. +/// Values of 128-255 are reserved for OEM use. +/// +///@{ +#define EFI_SOFTWARE_UNSPECIFIED (EFI_SOFTWARE | 0x00000000) +#define EFI_SOFTWARE_SEC (EFI_SOFTWARE | 0x00010000) +#define EFI_SOFTWARE_PEI_CORE (EFI_SOFTWARE | 0x00020000) +#define EFI_SOFTWARE_PEI_MODULE (EFI_SOFTWARE | 0x00030000) +#define EFI_SOFTWARE_DXE_CORE (EFI_SOFTWARE | 0x00040000) +#define EFI_SOFTWARE_DXE_BS_DRIVER (EFI_SOFTWARE | 0x00050000) +#define EFI_SOFTWARE_DXE_RT_DRIVER (EFI_SOFTWARE | 0x00060000) +#define EFI_SOFTWARE_SMM_DRIVER (EFI_SOFTWARE | 0x00070000) +#define EFI_SOFTWARE_EFI_APPLICATION (EFI_SOFTWARE | 0x00080000) +#define EFI_SOFTWARE_EFI_OS_LOADER (EFI_SOFTWARE | 0x00090000) +#define EFI_SOFTWARE_RT (EFI_SOFTWARE | 0x000A0000) +#define EFI_SOFTWARE_AL (EFI_SOFTWARE | 0x000B0000) +#define EFI_SOFTWARE_EBC_EXCEPTION (EFI_SOFTWARE | 0x000C0000) +#define EFI_SOFTWARE_IA32_EXCEPTION (EFI_SOFTWARE | 0x000D0000) +#define EFI_SOFTWARE_IPF_EXCEPTION (EFI_SOFTWARE | 0x000E0000) +#define EFI_SOFTWARE_PEI_SERVICE (EFI_SOFTWARE | 0x000F0000) +#define EFI_SOFTWARE_EFI_BOOT_SERVICE (EFI_SOFTWARE | 0x00100000) +#define EFI_SOFTWARE_EFI_RUNTIME_SERVICE (EFI_SOFTWARE | 0x00110000) +#define EFI_SOFTWARE_EFI_DXE_SERVICE (EFI_SOFTWARE | 0x00120000) +#define EFI_SOFTWARE_X64_EXCEPTION (EFI_SOFTWARE | 0x00130000) +#define EFI_SOFTWARE_ARM_EXCEPTION (EFI_SOFTWARE | 0x00140000) + +///@} + +/// +/// Software Class Progress Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_SW_PC_INIT 0x00000000 +#define EFI_SW_PC_LOAD 0x00000001 +#define EFI_SW_PC_INIT_BEGIN 0x00000002 +#define EFI_SW_PC_INIT_END 0x00000003 +#define EFI_SW_PC_AUTHENTICATE_BEGIN 0x00000004 +#define EFI_SW_PC_AUTHENTICATE_END 0x00000005 +#define EFI_SW_PC_INPUT_WAIT 0x00000006 +#define EFI_SW_PC_USER_SETUP 0x00000007 +///@} + +// +// Software Class Unspecified Subclass Progress Code definitions. +// + +/// +/// Software Class SEC Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_SEC_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_SEC_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +/// +/// Software Class PEI Core Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_PEI_CORE_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEI_CORE_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) +///@} + +/// +/// Software Class PEI Module Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_PEI_PC_RECOVERY_BEGIN (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEI_PC_CAPSULE_LOAD (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEI_PC_CAPSULE_START (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_PEI_PC_RECOVERY_USER (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_PEI_PC_RECOVERY_AUTO (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_PEI_PC_S3_BOOT_SCRIPT (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_PEI_PC_OS_WAKE (EFI_SUBCLASS_SPECIFIC | 0x00000006) +///@} + +/// +/// Software Class DXE Core Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_DXE_CORE_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_CORE_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_CORE_PC_START_DRIVER (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_CORE_PC_ARCH_READY (EFI_SUBCLASS_SPECIFIC | 0x00000004) +///@} + +/// +/// Software Class DXE BS Driver Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_DXE_BS_PC_LEGACY_OPROM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_BS_PC_EXIT_BOOT_SERVICES_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_BS_PC_VIRTUAL_ADDRESS_CHANGE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_BS_PC_ATTEMPT_BOOT_ORDER_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000007) +///@} + +// +// Software Class SMM Driver Subclass Progress Code definitions. +// + +// +// Software Class EFI Application Subclass Progress Code definitions. +// + +// +// Software Class EFI OS Loader Subclass Progress Code definitions. +// + +/// +/// Software Class EFI RT Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_RT_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_RT_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_RT_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) +///@} + +// +// Software Class X64 Exception Subclass Progress Code definitions. +// + +// +// Software Class ARM Exception Subclass Progress Code definitions. +// + +// +// Software Class EBC Exception Subclass Progress Code definitions. +// + +// +// Software Class IA32 Exception Subclass Progress Code definitions. +// + +// +// Software Class X64 Exception Subclass Progress Code definitions. +// + +// +// Software Class IPF Exception Subclass Progress Code definitions. +// + +/// +/// Software Class PEI Services Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_PS_PC_INSTALL_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PS_PC_REINSTALL_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PS_PC_LOCATE_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_PS_PC_NOTIFY_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_PS_PC_GET_BOOT_MODE (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_PS_PC_SET_BOOT_MODE (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_PS_PC_GET_HOB_LIST (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_PS_PC_CREATE_HOB (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_PS_PC_FFS_FIND_NEXT_VOLUME (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_PS_PC_FFS_FIND_NEXT_FILE (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_PS_PC_FFS_FIND_SECTION_DATA (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_PS_PC_INSTALL_PEI_MEMORY (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_PS_PC_ALLOCATE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_PS_PC_ALLOCATE_POOL (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +#define EFI_SW_PS_PC_COPY_MEM (EFI_SUBCLASS_SPECIFIC | 0x0000000E) +#define EFI_SW_PS_PC_SET_MEM (EFI_SUBCLASS_SPECIFIC | 0x0000000F) +#define EFI_SW_PS_PC_RESET_SYSTEM (EFI_SUBCLASS_SPECIFIC | 0x00000010) +#define EFI_SW_PS_PC_FFS_FIND_FILE_BY_NAME (EFI_SUBCLASS_SPECIFIC | 0x00000013) +#define EFI_SW_PS_PC_FFS_GET_FILE_INFO (EFI_SUBCLASS_SPECIFIC | 0x00000014) +#define EFI_SW_PS_PC_FFS_GET_VOLUME_INFO (EFI_SUBCLASS_SPECIFIC | 0x00000015) +#define EFI_SW_PS_PC_FFS_REGISTER_FOR_SHADOW (EFI_SUBCLASS_SPECIFIC | 0x00000016) +///@} + +/// +/// Software Class EFI Boot Services Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_BS_PC_RAISE_TPL (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_BS_PC_RESTORE_TPL (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_BS_PC_ALLOCATE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_BS_PC_FREE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_BS_PC_GET_MEMORY_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_BS_PC_ALLOCATE_POOL (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_BS_PC_FREE_POOL (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_BS_PC_CREATE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_BS_PC_SET_TIMER (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_BS_PC_WAIT_FOR_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_BS_PC_SIGNAL_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_BS_PC_CLOSE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_BS_PC_CHECK_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_BS_PC_INSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +#define EFI_SW_BS_PC_REINSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000E) +#define EFI_SW_BS_PC_UNINSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000F) +#define EFI_SW_BS_PC_HANDLE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000010) +#define EFI_SW_BS_PC_PC_HANDLE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000011) +#define EFI_SW_BS_PC_REGISTER_PROTOCOL_NOTIFY (EFI_SUBCLASS_SPECIFIC | 0x00000012) +#define EFI_SW_BS_PC_LOCATE_HANDLE (EFI_SUBCLASS_SPECIFIC | 0x00000013) +#define EFI_SW_BS_PC_INSTALL_CONFIGURATION_TABLE (EFI_SUBCLASS_SPECIFIC | 0x00000014) +#define EFI_SW_BS_PC_LOAD_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000015) +#define EFI_SW_BS_PC_START_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000016) +#define EFI_SW_BS_PC_EXIT (EFI_SUBCLASS_SPECIFIC | 0x00000017) +#define EFI_SW_BS_PC_UNLOAD_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000018) +#define EFI_SW_BS_PC_EXIT_BOOT_SERVICES (EFI_SUBCLASS_SPECIFIC | 0x00000019) +#define EFI_SW_BS_PC_GET_NEXT_MONOTONIC_COUNT (EFI_SUBCLASS_SPECIFIC | 0x0000001A) +#define EFI_SW_BS_PC_STALL (EFI_SUBCLASS_SPECIFIC | 0x0000001B) +#define EFI_SW_BS_PC_SET_WATCHDOG_TIMER (EFI_SUBCLASS_SPECIFIC | 0x0000001C) +#define EFI_SW_BS_PC_CONNECT_CONTROLLER (EFI_SUBCLASS_SPECIFIC | 0x0000001D) +#define EFI_SW_BS_PC_DISCONNECT_CONTROLLER (EFI_SUBCLASS_SPECIFIC | 0x0000001E) +#define EFI_SW_BS_PC_OPEN_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x0000001F) +#define EFI_SW_BS_PC_CLOSE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000020) +#define EFI_SW_BS_PC_OPEN_PROTOCOL_INFORMATION (EFI_SUBCLASS_SPECIFIC | 0x00000021) +#define EFI_SW_BS_PC_PROTOCOLS_PER_HANDLE (EFI_SUBCLASS_SPECIFIC | 0x00000022) +#define EFI_SW_BS_PC_LOCATE_HANDLE_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000023) +#define EFI_SW_BS_PC_LOCATE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000024) +#define EFI_SW_BS_PC_INSTALL_MULTIPLE_INTERFACES (EFI_SUBCLASS_SPECIFIC | 0x00000025) +#define EFI_SW_BS_PC_UNINSTALL_MULTIPLE_INTERFACES (EFI_SUBCLASS_SPECIFIC | 0x00000026) +#define EFI_SW_BS_PC_CALCULATE_CRC_32 (EFI_SUBCLASS_SPECIFIC | 0x00000027) +#define EFI_SW_BS_PC_COPY_MEM (EFI_SUBCLASS_SPECIFIC | 0x00000028) +#define EFI_SW_BS_PC_SET_MEM (EFI_SUBCLASS_SPECIFIC | 0x00000029) +#define EFI_SW_BS_PC_CREATE_EVENT_EX (EFI_SUBCLASS_SPECIFIC | 0x0000002A) +///@} + +/// +/// Software Class EFI Runtime Services Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_RS_PC_GET_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_RS_PC_SET_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_RS_PC_GET_WAKEUP_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_RS_PC_SET_WAKEUP_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_RS_PC_CONVERT_POINTER (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_RS_PC_GET_VARIABLE (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_RS_PC_GET_NEXT_VARIABLE_NAME (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_RS_PC_SET_VARIABLE (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_RS_PC_GET_NEXT_HIGH_MONOTONIC_COUNT (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_RS_PC_RESET_SYSTEM (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_RS_PC_UPDATE_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_RS_PC_QUERY_CAPSULE_CAPABILITIES (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_RS_PC_QUERY_VARIABLE_INFO (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +///@} + +/// +/// Software Class EFI DXE Services Subclass Progress Code definitions +/// +///@{ +#define EFI_SW_DS_PC_ADD_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DS_PC_ALLOCATE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DS_PC_FREE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DS_PC_REMOVE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DS_PC_GET_MEMORY_SPACE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DS_PC_SET_MEMORY_SPACE_ATTRIBUTES (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_DS_PC_GET_MEMORY_SPACE_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_DS_PC_ADD_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_DS_PC_ALLOCATE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_DS_PC_FREE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_DS_PC_REMOVE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_DS_PC_GET_IO_SPACE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_DS_PC_GET_IO_SPACE_MAP (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_DS_PC_DISPATCH (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +#define EFI_SW_DS_PC_SCHEDULE (EFI_SUBCLASS_SPECIFIC | 0x0000000E) +#define EFI_SW_DS_PC_TRUST (EFI_SUBCLASS_SPECIFIC | 0x0000000F) +#define EFI_SW_DS_PC_PROCESS_FIRMWARE_VOLUME (EFI_SUBCLASS_SPECIFIC | 0x00000010) +///@} + +/// +/// Software Class Error Code definitions. +/// These are shared by all subclasses. +/// +///@{ +#define EFI_SW_EC_NON_SPECIFIC 0x00000000 +#define EFI_SW_EC_LOAD_ERROR 0x00000001 +#define EFI_SW_EC_INVALID_PARAMETER 0x00000002 +#define EFI_SW_EC_UNSUPPORTED 0x00000003 +#define EFI_SW_EC_INVALID_BUFFER 0x00000004 +#define EFI_SW_EC_OUT_OF_RESOURCES 0x00000005 +#define EFI_SW_EC_ABORTED 0x00000006 +#define EFI_SW_EC_ILLEGAL_SOFTWARE_STATE 0x00000007 +#define EFI_SW_EC_ILLEGAL_HARDWARE_STATE 0x00000008 +#define EFI_SW_EC_START_ERROR 0x00000009 +#define EFI_SW_EC_BAD_DATE_TIME 0x0000000A +#define EFI_SW_EC_CFG_INVALID 0x0000000B +#define EFI_SW_EC_CFG_CLR_REQUEST 0x0000000C +#define EFI_SW_EC_CFG_DEFAULT 0x0000000D +#define EFI_SW_EC_PWD_INVALID 0x0000000E +#define EFI_SW_EC_PWD_CLR_REQUEST 0x0000000F +#define EFI_SW_EC_PWD_CLEARED 0x00000010 +#define EFI_SW_EC_EVENT_LOG_FULL 0x00000011 +///@} + +// +// Software Class Unspecified Subclass Error Code definitions. +// + +// +// Software Class SEC Subclass Error Code definitions. +// + +/// +/// Software Class PEI Core Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_PEI_CORE_EC_DXE_CORRUPT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEI_CORE_EC_DXEIPL_NOT_FOUND (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEI_CORE_EC_MEMORY_NOT_INSTALLED (EFI_SUBCLASS_SPECIFIC | 0x00000002) +///@} + +/// +/// Software Class PEI Module Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_PEI_EC_S3_BOOT_SCRIPT_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_PEI_EC_S3_OS_WAKE_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_PEI_EC_S3_RESUME_FAILED (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_PEI_EC_RECOVERY_FAILED (EFI_SUBCLASS_SPECIFIC | 0x00000007) +///@} + +/// +/// Software Class DXE Foundation Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_DXE_CORE_EC_NO_ARCH (EFI_SUBCLASS_SPECIFIC | 0x00000000) +///@} + + +/// +/// Software Class DXE Boot Service Driver Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_BS_EC_INVALID_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_BS_EC_INVALID_IDE_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000004) +///@} + +// +// Software Class DXE Runtime Service Driver Subclass Error Code definitions. +// + +// +// Software Class SMM Driver Subclass Error Code definitions. +// + +// +// Software Class EFI Application Subclass Error Code definitions. +// + +// +// Software Class EFI OS Loader Subclass Error Code definitions. +// + +// +// Software Class EFI RT Subclass Error Code definitions. +// + +// +// Software Class EFI AL Subclass Error Code definitions. +// + +/// +/// Software Class EBC Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol definitions in the EFI +/// specification. +/// +///@{ +#define EFI_SW_EC_EBC_UNDEFINED 0x00000000 +#define EFI_SW_EC_EBC_DIVIDE_ERROR EXCEPT_EBC_DIVIDE_ERROR +#define EFI_SW_EC_EBC_DEBUG EXCEPT_EBC_DEBUG +#define EFI_SW_EC_EBC_BREAKPOINT EXCEPT_EBC_BREAKPOINT +#define EFI_SW_EC_EBC_OVERFLOW EXCEPT_EBC_OVERFLOW +#define EFI_SW_EC_EBC_INVALID_OPCODE EXCEPT_EBC_INVALID_OPCODE +#define EFI_SW_EC_EBC_STACK_FAULT EXCEPT_EBC_STACK_FAULT +#define EFI_SW_EC_EBC_ALIGNMENT_CHECK EXCEPT_EBC_ALIGNMENT_CHECK +#define EFI_SW_EC_EBC_INSTRUCTION_ENCODING EXCEPT_EBC_INSTRUCTION_ENCODING +#define EFI_SW_EC_EBC_BAD_BREAK EXCEPT_EBC_BAD_BREAK +#define EFI_SW_EC_EBC_STEP EXCEPT_EBC_STEP +///@} + +/// +/// Software Class IA32 Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol definitions in the EFI +/// specification. +/// +///@{ +#define EFI_SW_EC_IA32_DIVIDE_ERROR EXCEPT_IA32_DIVIDE_ERROR +#define EFI_SW_EC_IA32_DEBUG EXCEPT_IA32_DEBUG +#define EFI_SW_EC_IA32_NMI EXCEPT_IA32_NMI +#define EFI_SW_EC_IA32_BREAKPOINT EXCEPT_IA32_BREAKPOINT +#define EFI_SW_EC_IA32_OVERFLOW EXCEPT_IA32_OVERFLOW +#define EFI_SW_EC_IA32_BOUND EXCEPT_IA32_BOUND +#define EFI_SW_EC_IA32_INVALID_OPCODE EXCEPT_IA32_INVALID_OPCODE +#define EFI_SW_EC_IA32_DOUBLE_FAULT EXCEPT_IA32_DOUBLE_FAULT +#define EFI_SW_EC_IA32_INVALID_TSS EXCEPT_IA32_INVALID_TSS +#define EFI_SW_EC_IA32_SEG_NOT_PRESENT EXCEPT_IA32_SEG_NOT_PRESENT +#define EFI_SW_EC_IA32_STACK_FAULT EXCEPT_IA32_STACK_FAULT +#define EFI_SW_EC_IA32_GP_FAULT EXCEPT_IA32_GP_FAULT +#define EFI_SW_EC_IA32_PAGE_FAULT EXCEPT_IA32_PAGE_FAULT +#define EFI_SW_EC_IA32_FP_ERROR EXCEPT_IA32_FP_ERROR +#define EFI_SW_EC_IA32_ALIGNMENT_CHECK EXCEPT_IA32_ALIGNMENT_CHECK +#define EFI_SW_EC_IA32_MACHINE_CHECK EXCEPT_IA32_MACHINE_CHECK +#define EFI_SW_EC_IA32_SIMD EXCEPT_IA32_SIMD +///@} + +/// +/// Software Class IPF Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol definitions in the EFI +/// specification. +/// +///@{ +#define EFI_SW_EC_IPF_ALT_DTLB EXCEPT_IPF_ALT_DTLB +#define EFI_SW_EC_IPF_DNESTED_TLB EXCEPT_IPF_DNESTED_TLB +#define EFI_SW_EC_IPF_BREAKPOINT EXCEPT_IPF_BREAKPOINT +#define EFI_SW_EC_IPF_EXTERNAL_INTERRUPT EXCEPT_IPF_EXTERNAL_INTERRUPT +#define EFI_SW_EC_IPF_GEN_EXCEPT EXCEPT_IPF_GEN_EXCEPT +#define EFI_SW_EC_IPF_NAT_CONSUMPTION EXCEPT_IPF_NAT_CONSUMPTION +#define EFI_SW_EC_IPF_DEBUG_EXCEPT EXCEPT_IPF_DEBUG_EXCEPT +#define EFI_SW_EC_IPF_UNALIGNED_ACCESS EXCEPT_IPF_UNALIGNED_ACCESS +#define EFI_SW_EC_IPF_FP_FAULT EXCEPT_IPF_FP_FAULT +#define EFI_SW_EC_IPF_FP_TRAP EXCEPT_IPF_FP_TRAP +#define EFI_SW_EC_IPF_TAKEN_BRANCH EXCEPT_IPF_TAKEN_BRANCH +#define EFI_SW_EC_IPF_SINGLE_STEP EXCEPT_IPF_SINGLE_STEP +///@} + +/// +/// Software Class PEI Service Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_PS_EC_RESET_NOT_AVAILABLE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PS_EC_MEMORY_INSTALLED_TWICE (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +// +// Software Class EFI Boot Service Subclass Error Code definitions. +// + +// +// Software Class EFI Runtime Service Subclass Error Code definitions. +// + +/// +/// Software Class EFI DXE Service Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_DXE_BS_PC_VERIFYING_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000006) +///@} + +/// +/// Software Class DXE RT Driver Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_DXE_RT_PC_S0 (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_RT_PC_S1 (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_RT_PC_S2 (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_RT_PC_S3 (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_RT_PC_S4 (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_RT_PC_S5 (EFI_SUBCLASS_SPECIFIC | 0x00000005) +///@} + +/// +/// Software Class X64 Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol +/// definitions in the EFI specification. +/// +///@{ +#define EFI_SW_EC_X64_DIVIDE_ERROR EXCEPT_X64_DIVIDE_ERROR +#define EFI_SW_EC_X64_DEBUG EXCEPT_X64_DEBUG +#define EFI_SW_EC_X64_NMI EXCEPT_X64_NMI +#define EFI_SW_EC_X64_BREAKPOINT EXCEPT_X64_BREAKPOINT +#define EFI_SW_EC_X64_OVERFLOW EXCEPT_X64_OVERFLOW +#define EFI_SW_EC_X64_BOUND EXCEPT_X64_BOUND +#define EFI_SW_EC_X64_INVALID_OPCODE EXCEPT_X64_INVALID_OPCODE +#define EFI_SW_EC_X64_DOUBLE_FAULT EXCEPT_X64_DOUBLE_FAULT +#define EFI_SW_EC_X64_INVALID_TSS EXCEPT_X64_INVALID_TSS +#define EFI_SW_EC_X64_SEG_NOT_PRESENT EXCEPT_X64_SEG_NOT_PRESENT +#define EFI_SW_EC_X64_STACK_FAULT EXCEPT_X64_STACK_FAULT +#define EFI_SW_EC_X64_GP_FAULT EXCEPT_X64_GP_FAULT +#define EFI_SW_EC_X64_PAGE_FAULT EXCEPT_X64_PAGE_FAULT +#define EFI_SW_EC_X64_FP_ERROR EXCEPT_X64_FP_ERROR +#define EFI_SW_EC_X64_ALIGNMENT_CHECK EXCEPT_X64_ALIGNMENT_CHECK +#define EFI_SW_EC_X64_MACHINE_CHECK EXCEPT_X64_MACHINE_CHECK +#define EFI_SW_EC_X64_SIMD EXCEPT_X64_SIMD +///@} + +/// +/// Software Class ARM Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol +/// definitions in the EFI specification. +/// +///@{ +#define EFI_SW_EC_ARM_RESET EXCEPT_ARM_RESET +#define EFI_SW_EC_ARM_UNDEFINED_INSTRUCTION EXCEPT_ARM_UNDEFINED_INSTRUCTION +#define EFI_SW_EC_ARM_SOFTWARE_INTERRUPT EXCEPT_ARM_SOFTWARE_INTERRUPT +#define EFI_SW_EC_ARM_PREFETCH_ABORT EXCEPT_ARM_PREFETCH_ABORT +#define EFI_SW_EC_ARM_DATA_ABORT EXCEPT_ARM_DATA_ABORT +#define EFI_SW_EC_ARM_RESERVED EXCEPT_ARM_RESERVED +#define EFI_SW_EC_ARM_IRQ EXCEPT_ARM_IRQ +#define EFI_SW_EC_ARM_FIQ EXCEPT_ARM_FIQ +///@} + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiDxe.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiDxe.h new file mode 100644 index 0000000..68812cb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiDxe.h @@ -0,0 +1,25 @@ +/** @file + + Root include file for Mde Package DXE_CORE, DXE, RUNTIME, SMM, SAL type modules. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PI_DXE_H__ +#define __PI_DXE_H__ + +#include +#include + +#include + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiMm.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiMm.h new file mode 100644 index 0000000..c296fb4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiMm.h @@ -0,0 +1,25 @@ +/** @file + + Root include file for Mde Package MM modules. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PI_MM_H__ +#define __PI_MM_H__ + +#include +#include + +#include + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiPei.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiPei.h new file mode 100644 index 0000000..804d995 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiPei.h @@ -0,0 +1,27 @@ +/** @file + + Root include file for Mde Package SEC, PEIM, PEI_CORE type modules. + + This is the include file for any module of type PEIM. PEIM + modules only use types defined via this include file and can + be ported easily to any environment. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PI_PEI_H__ +#define __PI_PEI_H__ + +#include +#include + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiSmm.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiSmm.h new file mode 100644 index 0000000..7e3b7ce --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/PiSmm.h @@ -0,0 +1,25 @@ +/** @file + + Root include file for Mde Package SMM modules. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PI_SMM_H__ +#define __PI_SMM_H__ + +#include +#include + +#include + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo.h new file mode 100644 index 0000000..3a26957 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo.h @@ -0,0 +1,238 @@ +/** @file + Provides the services required to access a block I/O device during PEI recovery + boot mode. + + The Recovery Module PPI and the Device Recovery Module PPI are device neutral. + This PPI is device specific and addresses the most common form of recovery + media-block I/O devices such as legacy floppy, CD-ROM, or IDE devices. + + The Recovery Block I/O PPI is used to access block devices. Because the Recovery + Block I/O PPIs that are provided by the PEI ATAPI driver and PEI legacy floppy + driver are the same, here we define a set of general PPIs for both drivers to use. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.2 Volume 1: + Pre-EFI Initalization Core Interface. + +**/ + +#ifndef _PEI_BLOCK_IO_H_ +#define _PEI_BLOCK_IO_H_ + +/// +/// Global ID for EFI_PEI_RECOVERY_BLOCK_IO_PPI +/// +#define EFI_PEI_RECOVERY_BLOCK_IO_PPI_GUID \ + { \ + 0x695d8aa1, 0x42ee, 0x4c46, { 0x80, 0x5c, 0x6e, 0xa6, 0xbc, 0xe7, 0x99, 0xe3 } \ + } + +/// +/// The forward declaration for EFI_PEI_RECOVERY_BLOCK_IO_PPI. +/// +typedef struct _EFI_PEI_RECOVERY_BLOCK_IO_PPI EFI_PEI_RECOVERY_BLOCK_IO_PPI; + +/// +/// All blocks on the recovery device are addressed with a 64-bit Logical Block Address (LBA). +/// +typedef UINT64 EFI_PEI_LBA; + +/// +/// EFI_PEI_BLOCK_DEVICE_TYPE +/// +typedef enum { + LegacyFloppy = 0, ///< The recovery device is a floppy. + IdeCDROM = 1, ///< The recovery device is an IDE CD-ROM + IdeLS120 = 2, ///< The recovery device is an IDE LS-120 + UsbMassStorage= 3, ///< The recovery device is a USB Mass Storage device + SD = 4, ///< The recovery device is a Secure Digital device + EMMC = 5, ///< The recovery device is a eMMC device + UfsDevice = 6, ///< The recovery device is a Universal Flash Storage device + MaxDeviceType +} EFI_PEI_BLOCK_DEVICE_TYPE; + +/// +/// Specification inconsistency here: +/// PEI_BLOCK_IO_MEDIA has been changed to EFI_PEI_BLOCK_IO_MEDIA. +/// Inconsistency exists in UEFI Platform Initialization Specification 1.2 +/// Volume 1: Pre-EFI Initalization Core Interface, where all referrences to +/// this structure name are with the "EFI_" prefix, except for the definition +/// which is without "EFI_". So the name of PEI_BLOCK_IO_MEDIA is taken as the +/// exception, and EFI_PEI_BLOCK_IO_MEDIA is used to comply with most of +/// the specification. +/// +typedef struct { + /// + /// The type of media device being referenced by DeviceIndex. + /// + EFI_PEI_BLOCK_DEVICE_TYPE DeviceType; + /// + /// A flag that indicates if media is present. This flag is always set for + /// nonremovable media devices. + /// + BOOLEAN MediaPresent; + /// + /// The last logical block that the device supports. + /// + UINTN LastBlock; + /// + /// The size of a logical block in bytes. + /// + UINTN BlockSize; +} EFI_PEI_BLOCK_IO_MEDIA; + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. To the PEI ATAPI driver, it returns the number + of all the detected ATAPI devices it detects during the enumeration process. + To the PEI legacy floppy driver, it returns the number of all the legacy + devices it finds during its enumeration process. If no device is detected, + then the function will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_NUMBER_BLOCK_DEVICES)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + OUT UINTN *NumberBlockDevices + ); + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @par Note: + The MediaInfo structure describes an enumeration of possible block device + types. This enumeration exists because no device paths are actually passed + across interfaces that describe the type or class of hardware that is publishing + the block I/O interface. This enumeration will allow for policy decisions + in the Recovery PEIM, such as "Try to recover from legacy floppy first, + LS-120 second, CD-ROM third." If there are multiple partitions abstracted + by a given device type, they should be reported in ascending order; this + order also applies to nested partitions, such as legacy MBR, where the + outermost partitions would have precedence in the reporting order. The + same logic applies to systems such as IDE that have precedence relationships + like "Master/Slave" or "Primary/Secondary". The master device should be + reported first, the slave second. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_DEVICE_MEDIA_INFORMATION)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ); + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the + buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_READ_BLOCKS)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/// +/// EFI_PEI_RECOVERY_BLOCK_IO_PPI provides the services that are required +/// to access a block I/O device during PEI recovery boot mode. +/// +struct _EFI_PEI_RECOVERY_BLOCK_IO_PPI { + /// + /// Gets the number of block I/O devices that the specific block driver manages. + /// + EFI_PEI_GET_NUMBER_BLOCK_DEVICES GetNumberOfBlockDevices; + + /// + /// Gets the specified media information. + /// + EFI_PEI_GET_DEVICE_MEDIA_INFORMATION GetBlockDeviceMediaInfo; + + /// + /// Reads the requested number of blocks from the specified block device. + /// + EFI_PEI_READ_BLOCKS ReadBlocks; +}; + +extern EFI_GUID gEfiPeiVirtualBlockIoPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo2.h new file mode 100644 index 0000000..c76b703 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BlockIo2.h @@ -0,0 +1,223 @@ +/** @file + Provides the services required to access a block I/O 2 device during PEI recovery + boot mode. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.4 Volume 1: + Pre-EFI Initalization Core Interface. + +**/ + +#ifndef _PEI_BLOCK_IO2_H_ +#define _PEI_BLOCK_IO2_H_ + +#include +#include + +/// +/// Global ID for EFI_PEI_RECOVERY_BLOCK_IO2_PPI +/// +#define EFI_PEI_RECOVERY_BLOCK_IO2_PPI_GUID \ + { \ + 0x26cc0fad, 0xbeb3, 0x478a, { 0x91, 0xb2, 0xc, 0x18, 0x8f, 0x72, 0x61, 0x98 } \ + } + +/// +/// The forward declaration for EFI_PEI_RECOVERY_BLOCK_IO_PPI. +/// +typedef struct _EFI_PEI_RECOVERY_BLOCK_IO2_PPI EFI_PEI_RECOVERY_BLOCK_IO2_PPI; + +#define EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION 0x00010000 + +typedef struct { + /// + /// A type of interface that the device being referenced by DeviceIndex is + /// attached to. This field re-uses Messaging Device Path Node sub-type values + /// as defined by Section 9.3.5 Messaging Device Path of UEFI Specification. + /// When more than one sub-type is associated with the interface, sub-type with + /// the smallest number must be used. + /// + UINT8 InterfaceType; + /// + /// A flag that indicates if media is removable. + /// + BOOLEAN RemovableMedia; + /// + /// A flag that indicates if media is present. This flag is always set for + /// non-removable media devices. + /// + BOOLEAN MediaPresent; + /// + /// A flag that indicates if media is read-only. + /// + BOOLEAN ReadOnly; + /// + /// The size of a logical block in bytes. + /// + UINT32 BlockSize; + /// + /// The last logical block that the device supports. + /// + EFI_PEI_LBA LastBlock; +} EFI_PEI_BLOCK_IO2_MEDIA; + +/** + Gets the count of block I/O devices that one specific block driver detects. + + This function is used for getting the count of block I/O devices that one + specific block driver detects. To the PEI ATAPI driver, it returns the number + of all the detected ATAPI devices it detects during the enumeration process. + To the PEI legacy floppy driver, it returns the number of all the legacy + devices it finds during its enumeration process. If no device is detected, + then the function will return zero. + + @param[in] PeiServices General-purpose services that are available + to every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI + instance. + @param[out] NumberBlockDevices The number of block I/O devices discovered. + + @retval EFI_SUCCESS The operation performed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_NUMBER_BLOCK_DEVICES2)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + OUT UINTN *NumberBlockDevices + ); + +/** + Gets a block device's media information. + + This function will provide the caller with the specified block device's media + information. If the media changes, calling this function will update the media + information accordingly. + + @param[in] PeiServices General-purpose services that are available to every + PEIM + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, the PPIs that + want to talk to a single device must specify the + device index that was assigned during the enumeration + process. This index is a number from one to + NumberBlockDevices. + @param[out] MediaInfo The media information of the specified block media. + The caller is responsible for the ownership of this + data structure. + + @par Note: + The MediaInfo structure describes an enumeration of possible block device + types. This enumeration exists because no device paths are actually passed + across interfaces that describe the type or class of hardware that is publishing + the block I/O interface. This enumeration will allow for policy decisions + in the Recovery PEIM, such as "Try to recover from legacy floppy first, + LS-120 second, CD-ROM third." If there are multiple partitions abstracted + by a given device type, they should be reported in ascending order; this + order also applies to nested partitions, such as legacy MBR, where the + outermost partitions would have precedence in the reporting order. The + same logic applies to systems such as IDE that have precedence relationships + like "Master/Slave" or "Primary/Secondary". The master device should be + reported first, the slave second. + + @retval EFI_SUCCESS Media information about the specified block device + was obtained successfully. + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_DEVICE_MEDIA_INFORMATION2)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo + ); + +/** + Reads the requested number of blocks from the specified block device. + + The function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. If there is no media in the device, + the function returns EFI_NO_MEDIA. + + @param[in] PeiServices General-purpose services that are available to + every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance. + @param[in] DeviceIndex Specifies the block device to which the function wants + to talk. Because the driver that implements Block I/O + PPIs will manage multiple block devices, PPIs that + want to talk to a single device must specify the device + index that was assigned during the enumeration process. + This index is a number from one to NumberBlockDevices. + @param[in] StartLBA The starting logical block address (LBA) to read from + on the device + @param[in] BufferSize The size of the Buffer in bytes. This number must be + a multiple of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the + buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the read operation. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not + valid, or the buffer is not properly aligned. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_READ_BLOCKS2)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/// +/// EFI_PEI_RECOVERY_BLOCK_IO_PPI provides the services that are required +/// to access a block I/O device during PEI recovery boot mode. +/// +struct _EFI_PEI_RECOVERY_BLOCK_IO2_PPI { + /// + /// The revision to which the interface adheres. + /// All future revisions must be backwards compatible. + /// + UINT64 Revision; + /// + /// Gets the number of block I/O devices that the specific block driver manages. + /// + EFI_PEI_GET_NUMBER_BLOCK_DEVICES2 GetNumberOfBlockDevices; + + /// + /// Gets the specified media information. + /// + EFI_PEI_GET_DEVICE_MEDIA_INFORMATION2 GetBlockDeviceMediaInfo; + + /// + /// Reads the requested number of blocks from the specified block device. + /// + EFI_PEI_READ_BLOCKS2 ReadBlocks; +}; + +extern EFI_GUID gEfiPeiVirtualBlockIo2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BootInRecoveryMode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BootInRecoveryMode.h new file mode 100644 index 0000000..2b017cd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/BootInRecoveryMode.h @@ -0,0 +1,30 @@ +/** @file + This PPI is installed by the platform PEIM to designate that a recovery boot + is in progress. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __BOOT_IN_RECOVERY_MODE_PPI_H__ +#define __BOOT_IN_RECOVERY_MODE_PPI_H__ + +#define EFI_PEI_BOOT_IN_RECOVERY_MODE_PPI \ + { \ + 0x17ee496a, 0xd8e4, 0x4b9a, {0x94, 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } \ + } + + +extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Capsule.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Capsule.h new file mode 100644 index 0000000..1c86532 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Capsule.h @@ -0,0 +1,136 @@ +/** @file + Defines the APIs that enable PEI services to work with + the underlying capsule capabilities of the platform. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.4. + +**/ + +#ifndef _PEI_CAPSULE_PPI_H_ +#define _PEI_CAPSULE_PPI_H_ + +/// +/// Global ID for the EFI_PEI_CAPSULE_PPI. +/// +#define EFI_PEI_CAPSULE_PPI_GUID \ + { \ + 0x3acf33ee, 0xd892, 0x40f4, {0xa2, 0xfc, 0x38, 0x54, 0xd2, 0xe1, 0x32, 0x3d } \ + } + +/// +/// Forward declaration for the EFI_PEI_CAPSULE_PPI. +/// +typedef struct _EFI_PEI_CAPSULE_PPI EFI_PEI_CAPSULE_PPI; + +/// +/// Keep name backwards compatible before PI Version 1.4 +/// +typedef struct _EFI_PEI_CAPSULE_PPI PEI_CAPSULE_PPI; + +/** + Upon determining that there is a capsule to operate on, this service + will use a series of EFI_CAPSULE_BLOCK_DESCRIPTOR entries to determine + the current location of the various capsule fragments and coalesce them + into a contiguous region of system memory. + + @param[in] PeiServices Pointer to the PEI Services Table. + @param[out] MemoryBase Pointer to the base of a block of memory into which the buffers will be coalesced. + On output, this variable will hold the base address + of a coalesced capsule. + @param[out] MemorySize Size of the memory region pointed to by MemoryBase. + On output, this variable will contain the size of the + coalesced capsule. + + @retval EFI_NOT_FOUND If: boot modecould not be determined, or the + boot mode is not flash-update, or the capsule descriptors were not found. + @retval EFI_BUFFER_TOO_SMALL The capsule could not be coalesced in the provided memory region. + @retval EFI_SUCCESS There was no capsule, or the capsule was processed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CAPSULE_COALESCE)( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **MemoryBase, + IN OUT UINTN *MemSize + ); + +/** + Determine if a capsule needs to be processed. + The means by which the presence of a capsule is determined is platform + specific. For example, an implementation could be driven by the presence + of a Capsule EFI Variable containing a list of EFI_CAPSULE_BLOCK_DESCRIPTOR + entries. If present, return EFI_SUCCESS, otherwise return EFI_NOT_FOUND. + + @param[in] PeiServices Pointer to the PEI Services Table. + + @retval EFI_SUCCESS If a capsule is available. + @retval EFI_NOT_FOUND No capsule detected. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CAPSULE_CHECK_CAPSULE_UPDATE)( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + The Capsule PPI service that gets called after memory is available. The + capsule coalesce function, which must be called first, returns a base + address and size. Once the memory init PEIM has discovered memory, + it should call this function and pass in the base address and size + returned by the Coalesce() function. Then this function can create a + capsule HOB and return. + + @par Notes: + This function assumes it will not be called until the + actual capsule update. + + @param[in] PeiServices Pointer to the PEI Services Table. + @param[in] CapsuleBase Address returned by the capsule coalesce function. + @param[in] CapsuleSize Value returned by the capsule coalesce function. + + @retval EFI_VOLUME_CORRUPTED CapsuleBase does not appear to point to a + coalesced capsule. + @retval EFI_SUCCESS Capsule HOB was created successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CAPSULE_CREATE_STATE)( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CapsuleBase, + IN UINTN CapsuleSize + ); + +/// +/// This PPI provides several services in PEI to work with the underlying +/// capsule capabilities of the platform. These services include the ability +/// for PEI to coalesce a capsule from a scattered set of memory locations +/// into a contiguous space in memory, detect if a capsule is present for +/// processing, and once memory is available, create a HOB for the capsule. +/// +struct _EFI_PEI_CAPSULE_PPI { + EFI_PEI_CAPSULE_COALESCE Coalesce; + EFI_PEI_CAPSULE_CHECK_CAPSULE_UPDATE CheckCapsuleUpdate; + EFI_PEI_CAPSULE_CREATE_STATE CreateState; +}; + +/// +/// Keep name backwards compatible before PI Version 1.4 +/// +extern EFI_GUID gPeiCapsulePpiGuid; + +extern EFI_GUID gEfiPeiCapsulePpiGuid; + +#endif // #ifndef _PEI_CAPSULE_PPI_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/CpuIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/CpuIo.h new file mode 100644 index 0000000..aa307a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/CpuIo.h @@ -0,0 +1,428 @@ +/** @file + This PPI provides a set of memory and I/O-based services. + The perspective of the services is that of the processor, not the bus or system. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __PEI_CPUIO_PPI_H__ +#define __PEI_CPUIO_PPI_H__ + +#define EFI_PEI_CPU_IO_PPI_INSTALLED_GUID \ + { 0xe6af1f7b, 0xfc3f, 0x46da, {0xa8, 0x28, 0xa3, 0xb4, 0x57, 0xa4, 0x42, 0x82 } } + +typedef struct _EFI_PEI_CPU_IO_PPI EFI_PEI_CPU_IO_PPI; + +/// +/// EFI_PEI_CPU_IO_PPI_WIDTH. +/// +typedef enum { + EfiPeiCpuIoWidthUint8, + EfiPeiCpuIoWidthUint16, + EfiPeiCpuIoWidthUint32, + EfiPeiCpuIoWidthUint64, + EfiPeiCpuIoWidthFifoUint8, + EfiPeiCpuIoWidthFifoUint16, + EfiPeiCpuIoWidthFifoUint32, + EfiPeiCpuIoWidthFifoUint64, + EfiPeiCpuIoWidthFillUint8, + EfiPeiCpuIoWidthFillUint16, + EfiPeiCpuIoWidthFillUint32, + EfiPeiCpuIoWidthFillUint64, + EfiPeiCpuIoWidthMaximum +} EFI_PEI_CPU_IO_PPI_WIDTH; + +/** + Memory-based access services and I/O-based access services. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Width The width of the access. Enumerated in bytes. + @param[in] Address The physical address of the access. + @param[in] Count The number of accesses to perform. + @param[in, out] Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_MEM)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/// +/// EFI_PEI_CPU_IO_PPI_ACCESS +/// +typedef struct { + /// + /// This service provides the various modalities of memory and I/O read. + /// + EFI_PEI_CPU_IO_PPI_IO_MEM Read; + /// + /// This service provides the various modalities of memory and I/O write. + /// + EFI_PEI_CPU_IO_PPI_IO_MEM Write; +} EFI_PEI_CPU_IO_PPI_ACCESS; + +/** + 8-bit I/O read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return An 8-bit value returned from the I/O space. + +**/ +typedef +UINT8 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ8)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 16-bit I/O read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return A 16-bit value returned from the I/O space. + +**/ +typedef +UINT16 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ16)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 32-bit I/O read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return A 32-bit value returned from the I/O space. + +**/ +typedef +UINT32 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ32)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 64-bit I/O read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return A 64-bit value returned from the I/O space. + +**/ +typedef +UINT64 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ64)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit I/O write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE8)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit I/O write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE16)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit I/O write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE32)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit I/O write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE64)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +/** + 8-bit memory read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return An 8-bit value returned from the memory space. + +**/ +typedef +UINT8 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ8)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 16-bit memory read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return A 16-bit value returned from the memory space. + +**/ +typedef +UINT16 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ16)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 32-bit memory read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return A 32-bit value returned from the memory space. + +**/ +typedef +UINT32 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ32)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 64-bit memory read operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + + @return A 64-bit value returned from the memory space. + +**/ +typedef +UINT64 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ64)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit memory write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE8)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit memory write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE16)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit memory write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE32)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit memory write operations. + + @param[in] PeiServices An indirect pointer to the PEI Services Table published + by the PEI Foundation. + @param[in] This The pointer to local data for the interface. + @param[in] Address The physical address of the access. + @param[in] Data The data to write. + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE64)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +/// +/// EFI_PEI_CPU_IO_PPI provides a set of memory and I/O-based services. +/// The perspective of the services is that of the processor, not that of the +/// bus or system. +/// +struct _EFI_PEI_CPU_IO_PPI { + /// + /// Collection of memory-access services. + /// + EFI_PEI_CPU_IO_PPI_ACCESS Mem; + /// + /// Collection of I/O-access services. + /// + EFI_PEI_CPU_IO_PPI_ACCESS Io; + + EFI_PEI_CPU_IO_PPI_IO_READ8 IoRead8; + EFI_PEI_CPU_IO_PPI_IO_READ16 IoRead16; + EFI_PEI_CPU_IO_PPI_IO_READ32 IoRead32; + EFI_PEI_CPU_IO_PPI_IO_READ64 IoRead64; + + EFI_PEI_CPU_IO_PPI_IO_WRITE8 IoWrite8; + EFI_PEI_CPU_IO_PPI_IO_WRITE16 IoWrite16; + EFI_PEI_CPU_IO_PPI_IO_WRITE32 IoWrite32; + EFI_PEI_CPU_IO_PPI_IO_WRITE64 IoWrite64; + + EFI_PEI_CPU_IO_PPI_MEM_READ8 MemRead8; + EFI_PEI_CPU_IO_PPI_MEM_READ16 MemRead16; + EFI_PEI_CPU_IO_PPI_MEM_READ32 MemRead32; + EFI_PEI_CPU_IO_PPI_MEM_READ64 MemRead64; + + EFI_PEI_CPU_IO_PPI_MEM_WRITE8 MemWrite8; + EFI_PEI_CPU_IO_PPI_MEM_WRITE16 MemWrite16; + EFI_PEI_CPU_IO_PPI_MEM_WRITE32 MemWrite32; + EFI_PEI_CPU_IO_PPI_MEM_WRITE64 MemWrite64; +}; + +extern EFI_GUID gEfiPeiCpuIoPpiInstalledGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Decompress.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Decompress.h new file mode 100644 index 0000000..26fae7a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Decompress.h @@ -0,0 +1,74 @@ +/** @file + Provides decompression services to the PEI Foundatoin. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __DECOMPRESS_PPI_H__ +#define __DECOMPRESS_PPI_H__ + +#define EFI_PEI_DECOMPRESS_PPI_GUID \ + { 0x1a36e4e7, 0xfab6, 0x476a, { 0x8e, 0x75, 0x69, 0x5a, 0x5, 0x76, 0xfd, 0xd7 } } + +typedef struct _EFI_PEI_DECOMPRESS_PPI EFI_PEI_DECOMPRESS_PPI; + +/** + Decompress a single compression section in a firmware file. + + Decompresses the data in a compressed section and returns it + as a series of standard PI Firmware File Sections. The + required memory is allocated from permanent memory. + + @param This Points to this instance of the + EFI_PEI_DECOMPRESS_PEI PPI. + @param InputSection Points to the compressed section. + @param OutputBuffer Holds the returned pointer to the + decompressed sections. + @param OutputSize Holds the returned size of the decompress + section streams. + + @retval EFI_SUCCESS The section was decompressed + successfully. OutputBuffer contains the + resulting data and OutputSize contains + the resulting size. + @retval EFI_OUT_OF_RESOURCES Unable to allocate sufficient + memory to hold the decompressed data. + @retval EFI_UNSUPPORTED The compression type specified + in the compression header is unsupported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DECOMPRESS_DECOMPRESS)( + IN CONST EFI_PEI_DECOMPRESS_PPI *This, + IN CONST EFI_COMPRESSION_SECTION *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize +); + + +/// +/// This PPI's single member function decompresses a compression +/// encapsulated section. It is used by the PEI Foundation to +/// process sectioned files. Prior to the installation of this PPI, +/// compression sections will be ignored. +/// +struct _EFI_PEI_DECOMPRESS_PPI { + EFI_PEI_DECOMPRESS_DECOMPRESS Decompress; +}; + + +extern EFI_GUID gEfiPeiDecompressPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DeviceRecoveryModule.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DeviceRecoveryModule.h new file mode 100644 index 0000000..a4f6cba --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DeviceRecoveryModule.h @@ -0,0 +1,144 @@ +/** @file + This file declares the Device Recovery Module PPI. + + The interface of this PPI does the following: + - Reports the number of recovery DXE capsules that exist on the associated device(s) + - Finds the requested firmware binary capsule + - Loads that capsule into memory + + A device can be either a group of devices, such as a block device, or an individual device. + The module determines the internal search order, with capsule number 1 as the highest load + priority and number N as the lowest priority. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.2 Volume 1: + Pre-EFI Initalization Core Interface + +**/ + +#ifndef _PEI_DEVICE_RECOVERY_MODULE_PPI_H_ +#define _PEI_DEVICE_RECOVERY_MODULE_PPI_H_ + +#define EFI_PEI_DEVICE_RECOVERY_MODULE_PPI_GUID \ + { \ + 0x0DE2CE25, 0x446A, 0x45a7, {0xBF, 0xC9, 0x37, 0xDA, 0x26, 0x34, 0x4B, 0x37 } \ + } + +typedef struct _EFI_PEI_DEVICE_RECOVERY_MODULE_PPI EFI_PEI_DEVICE_RECOVERY_MODULE_PPI; + +/** + Returns the number of DXE capsules residing on the device. + + This function searches for DXE capsules from the associated device and returns + the number and maximum size in bytes of the capsules discovered. Entry 1 is + assumed to be the highest load priority and entry N is assumed to be the lowest + priority. + + @param[in] PeiServices General-purpose services that are available + to every PEIM + @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI + instance. + @param[out] NumberRecoveryCapsules Pointer to a caller-allocated UINTN. On + output, *NumberRecoveryCapsules contains + the number of recovery capsule images + available for retrieval from this PEIM + instance. + + @retval EFI_SUCCESS One or more capsules were discovered. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DEVICE_GET_NUMBER_RECOVERY_CAPSULE)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This, + OUT UINTN *NumberRecoveryCapsules + ); + +/** + Returns the size and type of the requested recovery capsule. + + This function gets the size and type of the capsule specified by CapsuleInstance. + + @param[in] PeiServices General-purpose services that are available to every PEIM + @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI + instance. + @param[in] CapsuleInstance Specifies for which capsule instance to retrieve + the information. This parameter must be between + one and the value returned by GetNumberRecoveryCapsules() + in NumberRecoveryCapsules. + @param[out] Size A pointer to a caller-allocated UINTN in which + the size of the requested recovery module is + returned. + @param[out] CapsuleType A pointer to a caller-allocated EFI_GUID in which + the type of the requested recovery capsule is + returned. The semantic meaning of the value + returned is defined by the implementation. + + @retval EFI_SUCCESS One or more capsules were discovered. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DEVICE_GET_RECOVERY_CAPSULE_INFO)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This, + IN UINTN CapsuleInstance, + OUT UINTN *Size, + OUT EFI_GUID *CapsuleType + ); + +/** + Loads a DXE capsule from some media into memory. + + This function, by whatever mechanism, retrieves a DXE capsule from some device + and loads it into memory. Note that the published interface is device neutral. + + @param[in] PeiServices General-purpose services that are available + to every PEIM + @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI + instance. + @param[in] CapsuleInstance Specifies which capsule instance to retrieve. + @param[out] Buffer Specifies a caller-allocated buffer in which + the requested recovery capsule will be returned. + + @retval EFI_SUCCESS The capsule was loaded correctly. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A requested recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DEVICE_LOAD_RECOVERY_CAPSULE)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This, + IN UINTN CapsuleInstance, + OUT VOID *Buffer + ); + +/// +/// Presents a standard interface to EFI_PEI_DEVICE_RECOVERY_MODULE_PPI, +/// regardless of the underlying device(s). +/// +struct _EFI_PEI_DEVICE_RECOVERY_MODULE_PPI { + EFI_PEI_DEVICE_GET_NUMBER_RECOVERY_CAPSULE GetNumberRecoveryCapsules; ///< Returns the number of DXE capsules residing on the device. + EFI_PEI_DEVICE_GET_RECOVERY_CAPSULE_INFO GetRecoveryCapsuleInfo; ///< Returns the size and type of the requested recovery capsule. + EFI_PEI_DEVICE_LOAD_RECOVERY_CAPSULE LoadRecoveryCapsule; ///< Loads a DXE capsule from some media into memory. +}; + +extern EFI_GUID gEfiPeiDeviceRecoveryModulePpiGuid; + +#endif /* _PEI_DEVICE_RECOVERY_MODULE_PPI_H_ */ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DxeIpl.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DxeIpl.h new file mode 100644 index 0000000..e7146a9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/DxeIpl.h @@ -0,0 +1,72 @@ +/** @file + This file declares DXE Initial Program Load PPI. + When the PEI core is done it calls the DXE IPL PPI to load the DXE Foundation. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __DXE_IPL_H__ +#define __DXE_IPL_H__ + +#define EFI_DXE_IPL_PPI_GUID \ + { \ + 0xae8ce5d, 0xe448, 0x4437, {0xa8, 0xd7, 0xeb, 0xf5, 0xf1, 0x94, 0xf7, 0x31 } \ + } + +typedef struct _EFI_DXE_IPL_PPI EFI_DXE_IPL_PPI; + +/** + The architectural PPI that the PEI Foundation invokes when + there are no additional PEIMs to invoke. + + This function is invoked by the PEI Foundation. + The PEI Foundation will invoke this service when there are + no additional PEIMs to invoke in the system. + If this PPI does not exist, it is an error condition and + an ill-formed firmware set. The DXE IPL PPI should never + return after having been invoked by the PEI Foundation. + The DXE IPL PPI can do many things internally, including the following: + - Invoke the DXE entry point from a firmware volume + - Invoke the recovery processing modules + - Invoke the S3 resume modules + + @param This Pointer to the DXE IPL PPI instance + @param PeiServices Pointer to the PEI Services Table. + @param HobList Pointer to the list of Hand-Off Block (HOB) entries. + + @retval EFI_SUCCESS Upon this return code, the PEI Foundation should enter + some exception handling.Under normal circumstances, + the DXE IPL PPI should not return. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DXE_IPL_ENTRY)( + IN CONST EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ); + +/// +/// Final service to be invoked by the PEI Foundation. +/// The DXE IPL PPI is responsible for locating and loading the DXE Foundation. +/// The DXE IPL PPI may use PEI services to locate and load the DXE Foundation. +/// +struct _EFI_DXE_IPL_PPI { + EFI_DXE_IPL_ENTRY Entry; +}; + +extern EFI_GUID gEfiDxeIplPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/EndOfPeiPhase.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/EndOfPeiPhase.h new file mode 100644 index 0000000..07a4d05 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/EndOfPeiPhase.h @@ -0,0 +1,31 @@ +/** @file + This PPI will be installed at the end of PEI for all boot paths, including + normal, recovery, and S3. It allows for PEIMs to possibly quiesce hardware, + build handoff information for the next phase of execution, + or provide some terminal processing behavior. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __END_OF_PEI_PHASE_PPI_H__ +#define __END_OF_PEI_PHASE_PPI_H__ + +#define EFI_PEI_END_OF_PEI_PHASE_PPI_GUID \ + { \ + 0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } \ + } + +extern EFI_GUID gEfiEndOfPeiSignalPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolume.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolume.h new file mode 100644 index 0000000..c9d3391 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolume.h @@ -0,0 +1,294 @@ +/** @file + This file provides functions for accessing a memory-mapped firmware volume of a specific format. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is from PI Version 1.0 errata. + +**/ + +#ifndef __FIRMWARE_VOLUME_PPI_H__ +#define __FIRMWARE_VOLUME_PPI_H__ + +/// +/// The GUID for this PPI is the same as the firmware volume format GUID. +/// The FV format can be EFI_FIRMWARE_FILE_SYSTEM2_GUID or the GUID for a user-defined +/// format. The EFI_FIRMWARE_FILE_SYSTEM2_GUID is the PI Firmware Volume format. +/// +typedef struct _EFI_PEI_FIRMWARE_VOLUME_PPI EFI_PEI_FIRMWARE_VOLUME_PPI; + + +/** + Process a firmware volume and create a volume handle. + + Create a volume handle from the information in the buffer. For + memory-mapped firmware volumes, Buffer and BufferSize refer to + the start of the firmware volume and the firmware volume size. + For non memory-mapped firmware volumes, this points to a + buffer which contains the necessary information for creating + the firmware volume handle. Normally, these values are derived + from the EFI_FIRMWARE_VOLUME_INFO_PPI. + + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param Buffer Points to the start of the buffer. + @param BufferSize Size of the buffer. + @param FvHandle Points to the returned firmware volume + handle. The firmware volume handle must + be unique within the system. + + @retval EFI_SUCCESS Firmware volume handle created. + @retval EFI_VOLUME_CORRUPTED Volume was corrupt. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_PROCESS_FV)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN VOID *Buffer, + IN UINTN BufferSize, + OUT EFI_PEI_FV_HANDLE *FvHandle +); + +/** + Finds the next file of the specified type. + + This service enables PEI modules to discover additional firmware files. + The FileHandle must be unique within the system. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only files of this type. Type + EFI_FV_FILETYPE_ALL causes no filtering to be + done. + @param FvHandle Handle of firmware volume in which to + search. + @param FileHandle Points to the current handle from which to + begin searching or NULL to start at the + beginning of the firmware volume. Updated + upon return to reflect the file found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_FIND_FILE_TYPE)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE FvHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle +); + + +/** + Find a file within a volume by its name. + + This service searches for files with a specific name, within + either the specified firmware volume or all firmware volumes. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileName A pointer to the name of the file to find + within the firmware volume. + @param FvHandle Upon entry, the pointer to the firmware + volume to search or NULL if all firmware + volumes should be searched. Upon exit, the + actual firmware volume in which the file was + found. + @param FileHandle Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + @retval EFI_NOT_FOUND File was not found. + @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or + FileName was NULL. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_FIND_FILE_NAME)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN CONST EFI_GUID *FileName, + IN EFI_PEI_FV_HANDLE *FvHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle +); + + +/** + Returns information about a specific file. + + This function returns information about a specific + file, including its file name, type, attributes, starting + address and size. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileHandle 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 If FileInfo is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_GET_FILE_INFO)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo +); + +/** + Returns information about a specific file. + + This function returns information about a specific + file, including its file name, type, attributes, starting + address, size and authentication status. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FileHandle 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 If FileInfo is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_GET_FILE_INFO2)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO2 *FileInfo +); + +/** + This function returns information about the firmware volume. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param FvHandle Handle to the firmware handle. + @param VolumeInfo Points to the returned firmware volume + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid + firmware volume or VolumeInfo is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_GET_INFO)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_PEI_FV_HANDLE FvHandle, + OUT EFI_FV_INFO *VolumeInfo +); + +/** + Find the next matching section in the firmware file. + + This service enables PEI modules to discover sections + of a given type within a valid file. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only sections of this + type. + @param FileHandle Handle of firmware file in which to + search. + @param SectionData Updated upon return to point to the + section found. + + @retval EFI_SUCCESS Section was found. + @retval EFI_NOT_FOUND Section of the specified type was not + found. SectionData contains NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_FIND_SECTION)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_SECTION_TYPE SearchType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData +); + +/** + Find the next matching section in the firmware file. + + This service enables PEI modules to discover sections + of a given instance and type within a valid file. + + @param This Points to this instance of the + EFI_PEI_FIRMWARE_VOLUME_PPI. + @param SearchType A filter to find only sections of this + type. + @param SearchInstance A filter to find the specific instance + of sections. + @param FileHandle Handle of firmware file in which to + search. + @param SectionData Updated upon return to point to the + section found. + @param AuthenticationStatus Updated upon return to point to the + authentication status for this section. + + @retval EFI_SUCCESS Section was found. + @retval EFI_NOT_FOUND Section of the specified type was not + found. SectionData contains NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_FIND_SECTION2)( + IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This, + IN EFI_SECTION_TYPE SearchType, + IN UINTN SearchInstance, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData, + OUT UINT32 *AuthenticationStatus +); + +#define EFI_PEI_FIRMWARE_VOLUME_PPI_SIGNATURE SIGNATURE_32 ('P', 'F', 'V', 'P') +#define EFI_PEI_FIRMWARE_VOLUME_PPI_REVISION 0x00010030 + +/// +/// This PPI provides functions for accessing a memory-mapped firmware volume of a specific format. +/// +struct _EFI_PEI_FIRMWARE_VOLUME_PPI { + EFI_PEI_FV_PROCESS_FV ProcessVolume; + EFI_PEI_FV_FIND_FILE_TYPE FindFileByType; + EFI_PEI_FV_FIND_FILE_NAME FindFileByName; + EFI_PEI_FV_GET_FILE_INFO GetFileInfo; + EFI_PEI_FV_GET_INFO GetVolumeInfo; + EFI_PEI_FV_FIND_SECTION FindSectionByType; + EFI_PEI_FV_GET_FILE_INFO2 GetFileInfo2; + EFI_PEI_FV_FIND_SECTION2 FindSectionByType2; + /// + /// Signature is used to keep backward-compatibility, set to {'P','F','V','P'}. + /// + UINT32 Signature; + /// + /// Revision for further extension. + /// + UINT32 Revision; +}; + +extern EFI_GUID gEfiPeiFirmwareVolumePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo.h new file mode 100644 index 0000000..e8457e9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo.h @@ -0,0 +1,68 @@ +/** @file + This file provides location and format of a firmware volume. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __EFI_PEI_FIRMWARE_VOLUME_INFO_H__ +#define __EFI_PEI_FIRMWARE_VOLUME_INFO_H__ + + + +#define EFI_PEI_FIRMWARE_VOLUME_INFO_PPI_GUID \ +{ 0x49edb1c1, 0xbf21, 0x4761, { 0xbb, 0x12, 0xeb, 0x0, 0x31, 0xaa, 0xbb, 0x39 } } + +typedef struct _EFI_PEI_FIRMWARE_VOLUME_INFO_PPI EFI_PEI_FIRMWARE_VOLUME_INFO_PPI; + +/// +/// This PPI describes the location and format of a firmware volume. +/// The FvFormat can be EFI_FIRMWARE_FILE_SYSTEM2_GUID or the GUID for +/// a user-defined format. The EFI_FIRMWARE_FILE_SYSTEM2_GUID is +/// the PI Firmware Volume format. +/// +struct _EFI_PEI_FIRMWARE_VOLUME_INFO_PPI { + /// + /// Unique identifier of the format of the memory-mapped firmware volume. + /// + EFI_GUID FvFormat; + /// + /// 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. + /// + VOID *FvInfo; + /// + /// Size of the data provided by FvInfo. For memory-mapped firmware volumes, + /// this is typically the size of the firmware volume. + /// + UINT32 FvInfoSize; + /// + /// If the firmware volume originally came from a firmware file, then these + /// point to the parent firmware volume name and firmware volume file. + /// If it did not originally come from a firmware file, these should be NULL. + /// + EFI_GUID *ParentFvName; + /// + /// If the firmware volume originally came from a firmware file, then these + /// point to the parent firmware volume name and firmware volume file. + /// If it did not originally come from a firmware file, these should be NULL. + /// + EFI_GUID *ParentFileName; +}; + +extern EFI_GUID gEfiPeiFirmwareVolumeInfoPpiGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo2.h new file mode 100644 index 0000000..f4cf631 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/FirmwareVolumeInfo2.h @@ -0,0 +1,72 @@ +/** @file + This file provides location, format and authentication status of a firmware volume. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.3 errata. + +**/ + +#ifndef __EFI_PEI_FIRMWARE_VOLUME_INFO2_H__ +#define __EFI_PEI_FIRMWARE_VOLUME_INFO2_H__ + + + +#define EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI_GUID \ +{ 0xea7ca24b, 0xded5, 0x4dad, { 0xa3, 0x89, 0xbf, 0x82, 0x7e, 0x8f, 0x9b, 0x38 } } + +typedef struct _EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI; + +/// +/// This PPI describes the location and format of a firmware volume. +/// The FvFormat can be EFI_FIRMWARE_FILE_SYSTEM2_GUID or the GUID for +/// a user-defined format. The EFI_FIRMWARE_FILE_SYSTEM2_GUID is +/// the PI Firmware Volume format. +/// +struct _EFI_PEI_FIRMWARE_VOLUME_INFO2_PPI { + /// + /// Unique identifier of the format of the memory-mapped firmware volume. + /// + EFI_GUID FvFormat; + /// + /// 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. + /// + VOID *FvInfo; + /// + /// Size of the data provided by FvInfo. For memory-mapped firmware volumes, + /// this is typically the size of the firmware volume. + /// + UINT32 FvInfoSize; + /// + /// If the firmware volume originally came from a firmware file, then these + /// point to the parent firmware volume name and firmware volume file. + /// If it did not originally come from a firmware file, these should be NULL. + /// + EFI_GUID *ParentFvName; + /// + /// If the firmware volume originally came from a firmware file, then these + /// point to the parent firmware volume name and firmware volume file. + /// If it did not originally come from a firmware file, these should be NULL. + /// + EFI_GUID *ParentFileName; + /// + /// Authentication Status. + /// + UINT32 AuthenticationStatus; +}; + +extern EFI_GUID gEfiPeiFirmwareVolumeInfo2PpiGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Graphics.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Graphics.h new file mode 100644 index 0000000..3ae6bef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Graphics.h @@ -0,0 +1,85 @@ +/** @file + This file declares Graphics PPI. + This PPI is the main interface exposed by the Graphics PEIM to be used by the + other firmware modules. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.4. + +**/ + +#ifndef __PEI_GRAPHICS_PPI_H__ +#define __PEI_GRAPHICS_PPI_H__ + +#include + +#define EFI_PEI_GRAPHICS_PPI_GUID \ + { \ + 0x6ecd1463, 0x4a4a, 0x461b, { 0xaf, 0x5f, 0x5a, 0x33, 0xe3, 0xb2, 0x16, 0x2b } \ + } + +typedef struct _EFI_PEI_GRAPHICS_PPI EFI_PEI_GRAPHICS_PPI; + +/** + The GraphicsPpiInit initializes the graphics subsystem in phases. + + @param[in] GraphicsPolicyPtr GraphicsPolicyPtr points to a configuration data + block of policy settings required by Graphics PEIM. + + @retval EFI_SUCCESS The invocation was successful. + @retval EFI_INVALID_PARAMETER The phase parameter is not valid. + @retval EFI_NOT_ABORTED The stages was not called in the proper order. + @retval EFI_NOT_FOUND The PeiGraphicsPlatformPolicyPpi is not located. + @retval EFI_DEVICE_ERROR The initialization failed due to device error. + @retval EFI_NOT_READY The previous init stage is still in progress and not + ready for the current initialization phase yet. The + platform code should call this again sometime later. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GRAPHICS_INIT) ( + IN VOID *GraphicsPolicyPtr + ); + +/** + The GraphicsPpiGetMode returns the mode information supported by the Graphics PEI + Module. + + @param[in, out] Mode Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE data. + + @retval EFI_SUCCESS Valid mode information was returned. + @retval EFI_INVALID_PARAMETER The Mode parameter is not valid. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video + mode. + @retval EFI_NOT_READY The Graphics Initialization is not competed and Mode + information is not yet available.The platform code + should call this again after the Graphics + initialization is done. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GRAPHICS_GET_MODE) ( + IN OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode + ); + +/// +/// This PPI is the main interface exposed by the Graphics PEIM to be used by the other +/// firmware modules. +/// +struct _EFI_PEI_GRAPHICS_PPI { + EFI_PEI_GRAPHICS_INIT GraphicsPpiInit; + EFI_PEI_GRAPHICS_GET_MODE GraphicsPpiGetMode; +}; + +extern EFI_GUID gEfiPeiGraphicsPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/GuidedSectionExtraction.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/GuidedSectionExtraction.h new file mode 100644 index 0000000..3b0f185 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/GuidedSectionExtraction.h @@ -0,0 +1,104 @@ +/** @file + If a GUID-defined section is encountered when doing section extraction, + the PEI Foundation or the EFI_PEI_FILE_LOADER_PPI instance + calls the appropriate instance of the GUIDed Section Extraction PPI + to extract the section stream contained therein. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __EFI_GUIDED_SECTION_EXTRACTION_PPI_H__ +#define __EFI_GUIDED_SECTION_EXTRACTION_PPI_H__ + +// +// Typically, protocol interface structures are identified +// by associating them with a GUID. Each instance of +// a protocol with a given GUID must have +// the same interface structure. While all instances of +// the GUIDed Section Extraction PPI must have +// the same interface structure, they do not all have +// te same GUID. The GUID that is associated with +// an instance of the GUIDed Section Extraction Protocol +// is used to correlate it with the GUIDed section type +// that it is intended to process. +// + + +typedef struct _EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI; + + +/** + Processes the input section and returns the data contained therein + along with the authentication status. + + The ExtractSection() function processes the input section and + returns a pointer to the section contents. If the section being + extracted does not require processing (if the section + GuidedSectionHeader.Attributes has the + EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then + OutputBuffer is just updated to point to the start of the + section's contents. Otherwise, *Buffer must be allocated + from PEI permanent memory. + + @param This Indicates the EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI + instance. + @param InputSection Buffer containing the input GUIDed section to be + processed. + @param OutputBuffer *OutputBuffer is allocated from PEI permanent memory + and contains the new section stream. + @param OutputSize A pointer to a caller-allocated UINTN in which + the size of *OutputBuffer allocation is stored. + If the function returns anything other than + EFI_SUCCESS, the value of *OutputSize is undefined. + @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates + the authentication status of the output buffer. + If the input section's + GuidedSectionHeader.Attributes field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit as clear, + *AuthenticationStatus must return zero. These bits + reflect the status of the extraction operation. + If the function returns anything other than EFI_SUCCESS, + the value of *AuthenticationStatus is undefined. + + @retval EFI_SUCCESS The InputSection was successfully processed and the + section contents were returned. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process the request. + @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match this instance of the + GUIDed Section Extraction PPI. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_EXTRACT_GUIDED_SECTION)( + IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This, + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus +); + +/// +/// If a GUID-defined section is encountered when doing section extraction, +/// the PEI Foundation or the EFI_PEI_FILE_LOADER_PPI instance +/// calls the appropriate instance of the GUIDed Section +/// Extraction PPI to extract the section stream contained +/// therein. +/// +struct _EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI { + EFI_PEI_EXTRACT_GUIDED_SECTION ExtractSection; +}; + + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/I2cMaster.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/I2cMaster.h new file mode 100644 index 0000000..638ee4b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/I2cMaster.h @@ -0,0 +1,108 @@ +/** @file + This PPI manipulates the I2C host controller to perform transactions as a master + on the I2C bus using the current state of any switches or multiplexers in the I2C bus. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.3. + +**/ + +#ifndef __I2C_MASTER_PPI_H__ +#define __I2C_MASTER_PPI_H__ + +#include + +#define EFI_PEI_I2C_MASTER_PPI_GUID \ + { 0xb3bfab9b, 0x9f9c, 0x4e8b, { 0xad, 0x37, 0x7f, 0x8c, 0x51, 0xfc, 0x62, 0x80 }} + +typedef struct _EFI_PEI_I2C_MASTER_PPI EFI_PEI_I2C_MASTER_PPI; + +/** + Set the frequency for the I2C clock line. + + @param This Pointer to an EFI_PEI_I2C_MASTER_PPI structure. + @param BusClockHertz Pointer to the requested I2C bus clock frequency in Hertz. + Upon return this value contains the actual frequency + in use by the I2C controller. + + @retval EFI_SUCCESS The bus frequency was set successfully. + @retval EFI_INVALID_PARAMETER BusClockHertz is NULL + @retval EFI_UNSUPPORTED The controller does not support this frequency. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_I2C_MASTER_PPI_SET_BUS_FREQUENCY) ( + IN EFI_PEI_I2C_MASTER_PPI *This, + IN UINTN *BusClockHertz + ); + +/** + Reset the I2C controller and configure it for use. + + @param This Pointer to an EFI_PEI_I2C_MASTER_PPI structure. + + @retval EFI_SUCCESS The reset completed successfully. + @retval EFI_DEVICE_ERROR The reset operation failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_I2C_MASTER_PPI_RESET) ( + IN CONST EFI_PEI_I2C_MASTER_PPI *This + ); + +/** + Start an I2C transaction on the host controller. + + @param This Pointer to an EFI_PEI_I2C_MASTER_PPI structure. + @param SlaveAddress Address of the device on the I2C bus. + Set the I2C_ADDRESSING_10_BIT when using 10-bit addresses, + clear this bit for 7-bit addressing. + Bits 0-6 are used for 7-bit I2C slave addresses and + bits 0-9 are used for 10-bit I2C slave addresses. + @param RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET structure describing the I2C transaction. + + @retval EFI_SUCCESS The transaction completed successfully. + @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the transaction. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_NO_RESPONSE The I2C device is not responding to the slave address. + EFI_DEVICE_ERROR will be returned if the controller cannot distinguish when the NACK occurred. + @retval EFI_NOT_FOUND Reserved bit set in the SlaveAddress parameter + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction + @retval EFI_UNSUPPORTED The controller does not support the requested transaction. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_I2C_MASTER_PPI_START_REQUEST) ( + IN CONST EFI_PEI_I2C_MASTER_PPI *This, + IN UINTN SlaveAddress, + IN EFI_I2C_REQUEST_PACKET *RequestPacket + ); + +/// +/// This PPI manipulates the I2C host controller to perform transactions as a master on the I2C bus +/// using the current state of any switches or multiplexers in the I2C bus. +/// +struct _EFI_PEI_I2C_MASTER_PPI { + EFI_PEI_I2C_MASTER_PPI_SET_BUS_FREQUENCY SetBusFrequency; + EFI_PEI_I2C_MASTER_PPI_RESET Reset; + EFI_PEI_I2C_MASTER_PPI_START_REQUEST StartRequest; + CONST EFI_I2C_CONTROLLER_CAPABILITIES *I2cControllerCapabilities; + EFI_GUID Identifier; +}; + +extern EFI_GUID gEfiPeiI2cMasterPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/IsaHc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/IsaHc.h new file mode 100644 index 0000000..0af9a0c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/IsaHc.h @@ -0,0 +1,119 @@ +/** @file + This PPI opens or closes an I/O aperture in a ISA HOST controller. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is from PI Version 1.2.1. + +**/ + +#ifndef __ISA_HC_PPI_H__ +#define __ISA_HC_PPI_H__ + +#define EFI_ISA_HC_PPI_GUID \ + { \ + 0x8d48bd70, 0xc8a3, 0x4c06, {0x90, 0x1b, 0x74, 0x79, 0x46, 0xaa, 0xc3, 0x58} \ + } + +typedef struct _EFI_ISA_HC_PPI EFI_ISA_HC_PPI; +typedef struct _EFI_ISA_HC_PPI *PEFI_ISA_HC_PPI; + +/** + Open I/O aperture. + + This function opens an I/O aperture in a ISA Host Controller for the I/O + addresses specified by IoAddress to IoAddress + IoLength - 1. It is possible + that more than one caller may be assigned to the same aperture. + It may be possible that a single hardware aperture may be used for more than + one device. This function tracks the number of times that each aperture is + referenced, and doesa not close the hardware aperture (via CloseIoAperture()) + until there are no more references to it. + + @param This A pointer to this instance of the EFI_ISA_HC_PPI. + @param IoAddress An unsigned integer that specifies the first byte of + the I/O space required. + @param IoLength An unsigned integer that specifies the number of + bytes of the I/O space required. + @param IoApertureHandle A pointer to the returned I/O aperture handle. + This value can be used on subsequent calls to CloseIoAperture(). + + @retval EFI_SUCCESS The I/O aperture was opened successfully. + @retval EFI_UNSUPPORTED The ISA Host Controller is a subtractive-decode controller. + @retval EFI_OUT_OF_RESOURCES There is no available I/O aperture. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_ISA_HC_OPEN_IO) ( + IN CONST EFI_ISA_HC_PPI *This, + IN UINT16 IoAddress, + IN UINT16 IoLength, + OUT UINT64 *IoApertureHandle + ); + +/** + Close I/O aperture. + + This function closes a previously opened I/O aperture handle. If there are no + more I/O aperture handles that refer to the hardware I/O aperture resource, + then the hardware I/O aperture is closed. + It may be possible that a single hardware aperture may be used for more than + one device. This function tracks the number of times that each aperture is + referenced, and does not close the hardware aperture (via CloseIoAperture()) + until there are no more references to it. + + @param This A pointer to this instance of the EFI_ISA_HC_PPI. + @param IoApertureHandle The I/O aperture handle previously returned from a + call to OpenIoAperture(). + + @retval EFI_SUCCESS The I/O aperture was closed successfully. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_ISA_HC_CLOSE_IO) ( + IN CONST EFI_ISA_HC_PPI *This, + IN UINT64 IoApertureHandle + ); + +/// +/// This PPI provides functions for opening or closing an I/O aperture. +/// +struct _EFI_ISA_HC_PPI { + /// + /// An unsigned integer that specifies the version of the PPI structure. + /// + UINT32 Version; + /// + /// The address of the ISA/LPC Bridge device. + /// For PCI, this is the segment, bus, device and function of the a ISA/LPC + /// Bridge device. + /// + /// If bits 24-31 are 0, then the definition is: + /// Bits 0:2 - Function + /// Bits 3-7 - Device + /// Bits 8:15 - Bus + /// Bits 16-23 - Segment + /// Bits 24-31 - Bus Type + /// If bits 24-31 are 0xff, then the definition is platform-specific. + /// + UINT32 Address; + /// + /// Opens an aperture on a positive-decode ISA Host Controller. + /// + EFI_PEI_ISA_HC_OPEN_IO OpenIoAperture; + /// + /// Closes an aperture on a positive-decode ISA Host Controller. + /// + EFI_PEI_ISA_HC_CLOSE_IO CloseIoAperture; +}; + +extern EFI_GUID gEfiIsaHcPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadFile.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadFile.h new file mode 100644 index 0000000..3215e9b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadFile.h @@ -0,0 +1,77 @@ +/** @file + Load image file from fv to memory. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __LOAD_FILE_PPI_H__ +#define __LOAD_FILE_PPI_H__ + +#define EFI_PEI_LOAD_FILE_PPI_GUID \ + { 0xb9e0abfe, 0x5979, 0x4914, { 0x97, 0x7f, 0x6d, 0xee, 0x78, 0xc2, 0x78, 0xa6 } } + + +typedef struct _EFI_PEI_LOAD_FILE_PPI EFI_PEI_LOAD_FILE_PPI; + +/** + Loads a PEIM into memory for subsequent execution. + + This service is the single member function of EFI_LOAD_FILE_PPI. + This service separates image loading and relocating from the PEI Foundation. + + @param This Interface pointer that implements + the Load File PPI instance. + @param FileHandle File handle of the file to load. + @param ImageAddress Pointer to the address of the loaded image. + @param ImageSize Pointer to the size of the loaded image. + @param EntryPoint Pointer to the entry point of the image. + @param AuthenticationState On exit, points to the attestation + authentication state of the image + or 0 if no attestation was performed. + + @retval EFI_SUCCESS The image was loaded successfully. + @retval EFI_OUT_OF_RESOURCES There was not enough memory. + @retval EFI_LOAD_ERROR There was no supported image in the file. + @retval EFI_INVALID_PARAMETER FileHandle was not a valid firmware file handle. + @retval EFI_INVALID_PARAMETER EntryPoint was NULL. + @retval EFI_UNSUPPORTED An image requires relocations or is not + memory mapped. + @retval EFI_WARN_BUFFER_TOO_SMALL + There is not enough heap to allocate the requested size. + This will not prevent the XIP image from being invoked. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOAD_FILE)( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState +); + +/// +/// This PPI is a pointer to the Load File service. +/// This service will be published by a PEIM. The PEI Foundation +/// will use this service to launch the known PEI module images. +/// +struct _EFI_PEI_LOAD_FILE_PPI { + EFI_PEI_LOAD_FILE LoadFile; +}; + +extern EFI_GUID gEfiPeiLoadFilePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadImage.h new file mode 100644 index 0000000..6455187 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/LoadImage.h @@ -0,0 +1,52 @@ +/** @file + The file describes the PPI which notifies other drivers + of the PEIM being initialized by the PEI Dispatcher. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __LOADED_IMAGE_PPI_H__ +#define __LOADED_IMAGE_PPI_H__ + +#define EFI_PEI_LOADED_IMAGE_PPI_GUID \ + { 0xc1fcd448, 0x6300, 0x4458, { 0xb8, 0x64, 0x28, 0xdf, 0x1, 0x53, 0x64, 0xbc } } + + +typedef struct _EFI_PEI_LOADED_IMAGE_PPI EFI_PEI_LOADED_IMAGE_PPI; + +/// +/// This interface is installed by the PEI Dispatcher after the image has been +/// loaded and after all security checks have been performed, +/// to notify other PEIMs of the files which are being loaded. +/// +struct _EFI_PEI_LOADED_IMAGE_PPI { + /// + /// Address of the image at the address where it will be executed. + /// + EFI_PHYSICAL_ADDRESS ImageAddress; + /// + /// Size of the image as it will be executed. + /// + UINT64 ImageSize; + /// + /// File handle from which the image was loaded. + /// Can be NULL, indicating the image was not loaded from a handle. + /// + EFI_PEI_FILE_HANDLE FileHandle; +}; + + +extern EFI_GUID gEfiPeiLoadedImagePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MasterBootMode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MasterBootMode.h new file mode 100644 index 0000000..f34ca60 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MasterBootMode.h @@ -0,0 +1,32 @@ +/** @file + This file declares Boot Mode PPI. + + The Master Boot Mode PPI is installed by a PEIM to signal that a final + boot has been determined and set. This signal is useful in that PEIMs + with boot-mode-specific behavior can put this PPI in their dependency expression. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __MASTER_BOOT_MODE_PPI_H__ +#define __MASTER_BOOT_MODE_PPI_H__ + +#define EFI_PEI_MASTER_BOOT_MODE_PEIM_PPI \ + { \ + 0x7408d748, 0xfc8c, 0x4ee6, {0x92, 0x88, 0xc4, 0xbe, 0xc0, 0x92, 0xa4, 0x10 } \ + } + +extern EFI_GUID gEfiPeiMasterBootModePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MemoryDiscovered.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MemoryDiscovered.h new file mode 100644 index 0000000..1fd1919 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MemoryDiscovered.h @@ -0,0 +1,32 @@ +/** @file + This file declares Memory Discovered PPI. + + This PPI is published by the PEI Foundation when the main memory is installed. + It is essentially a PPI with no associated interface. Its purpose is to be used + as a signal for other PEIMs who can register for a notification on its installation. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __PEI_MEMORY_DISCOVERED_PPI_H__ +#define __PEI_MEMORY_DISCOVERED_PPI_H__ + +#define EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID \ + { \ + 0xf894643d, 0xc449, 0x42d1, {0x8e, 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } \ + } + +extern EFI_GUID gEfiPeiMemoryDiscoveredPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MpServices.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MpServices.h new file mode 100644 index 0000000..888bed9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/MpServices.h @@ -0,0 +1,283 @@ +/** @file + This file declares UEFI PI Multi-processor PPI. + This PPI is installed by some platform or chipset-specific PEIM that abstracts + handling multiprocessor support. + + Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.4. + +**/ + +#ifndef __PEI_MP_SERVICES_PPI_H__ +#define __PEI_MP_SERVICES_PPI_H__ + +#include + +#define EFI_PEI_MP_SERVICES_PPI_GUID \ + { \ + 0xee16160a, 0xe8be, 0x47a6, { 0x82, 0xa, 0xc6, 0x90, 0xd, 0xb0, 0x25, 0xa } \ + } + +typedef struct _EFI_PEI_MP_SERVICES_PPI EFI_PEI_MP_SERVICES_PPI ; + +/** + Get the number of CPU's. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This Pointer to this instance of the PPI. + @param[out] NumberOfProcessors Pointer to the total number of logical processors in + the system, including the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors + Number of processors in the system that are enabled. + + @retval EFI_SUCCESS The number of logical processors and enabled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL. + NumberOfEnabledProcessors is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ); + +/** + Get information on a specific CPU. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This Pointer to this instance of the PPI. + @param[in] ProcessorNumber Pointer to the total number of logical processors in + the system, including the BSP and disabled APs. + @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist in the platform. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_GET_PROCESSOR_INFO) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ); + +/** + Activate all of the application proessors. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[in] Procedure A pointer to the function to be run on enabled APs of + the system. + @param[in] SingleThread If TRUE, then all the enabled APs execute the function + specified by Procedure one by one, in ascending order + of processor handle number. If FALSE, then all the + enabled APs execute the function specified by Procedure + simultaneously. + @param[in] TimeoutInMicroSeconds + Indicates the time limit in microseconds for APs to + return from Procedure, for blocking mode only. Zero + means infinity. If the timeout expires before all APs + return from Procedure, then Procedure on the failed APs + is terminated. All enabled APs are available for next + function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() + or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the + timeout expires in blocking mode, BSP returns + EFI_TIMEOUT. + @param[in] ProcedureArgument The parameter passed into Procedure for all APs. + + @retval EFI_SUCCESS In blocking mode, all APs have finished before the + timeout expired. + @retval EFI_DEVICE_ERROR Caller processor is AP. + @retval EFI_NOT_STARTED No enabled APs exist in the system. + @retval EFI_NOT_READY Any enabled APs are busy. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before all + enabled APs have finished. + @retval EFI_INVALID_PARAMETER Procedure is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_STARTUP_ALL_APS) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument OPTIONAL + ); + +/** + Activate a specific application processor. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[in] Procedure A pointer to the function to be run on enabled APs of + the system. + @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the + total number of logical processors minus 1. The total + number of logical processors can be retrieved by + EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + @param[in] TimeoutInMicroSeconds + Indicates the time limit in microseconds for APs to + return from Procedure, for blocking mode only. Zero + means infinity. If the timeout expires before all APs + return from Procedure, then Procedure on the failed APs + is terminated. All enabled APs are available for next + function assigned by EFI_PEI_MP_SERVICES_PPI.StartupAllAPs() + or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the + timeout expires in blocking mode, BSP returns + EFI_TIMEOUT. + @param[in] ProcedureArgument The parameter passed into Procedure for all APs. + + @retval EFI_SUCCESS In blocking mode, specified AP finished before the + timeout expires. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before the + specified AP has finished. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. + @retval EFI_INVALID_PARAMETER Procedure is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_STARTUP_THIS_AP) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL + ); + +/** + Switch the boot strap processor. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the + total number of logical processors minus 1. The total + number of logical processors can be retrieved by + EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled + AP. Otherwise, it will be disabled. + + @retval EFI_SUCCESS BSP successfully switched. + @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this + service returning. + @retval EFI_UNSUPPORTED Switching the BSP is not supported. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled + AP. + @retval EFI_NOT_READY The specified AP is busy. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_SWITCH_BSP) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ); + +/** + Enable or disable an application processor. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the + total number of logical processors minus 1. The total + number of logical processors can be retrieved by + EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + @param[in] EnableAP Specifies the new state for the processor for enabled, + FALSE for disabled. + @param[in] HealthFlag If not NULL, a pointer to a value that specifies the + new health status of the AP. This flag corresponds to + StatusFlag defined in EFI_PEI_MP_SERVICES_PPI.GetProcessorInfo(). + Only the PROCESSOR_HEALTH_STATUS_BIT is used. All other + bits are ignored. If it is NULL, this parameter is + ignored. + + @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. + @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed prior + to this service returning. + @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber + does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_ENABLEDISABLEAP) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag OPTIONAL + ); + +/** + Identify the currently executing processor. + + @param[in] PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the + total number of logical processors minus 1. The total + number of logical processors can be retrieved by + EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + + @retval EFI_SUCCESS The current processor handle number was returned in + ProcessorNumber. + @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_MP_SERVICES_WHOAMI) ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_MP_SERVICES_PPI *This, + OUT UINTN *ProcessorNumber + ); + +/// +/// This PPI is installed by some platform or chipset-specific PEIM that abstracts +/// handling multiprocessor support. +/// +struct _EFI_PEI_MP_SERVICES_PPI { + EFI_PEI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors; + EFI_PEI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo; + EFI_PEI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs; + EFI_PEI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP; + EFI_PEI_MP_SERVICES_SWITCH_BSP SwitchBSP; + EFI_PEI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP; + EFI_PEI_MP_SERVICES_WHOAMI WhoAmI; +}; + +extern EFI_GUID gEfiPeiMpServicesPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Pcd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Pcd.h new file mode 100644 index 0000000..29c8150 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Pcd.h @@ -0,0 +1,860 @@ +/** @file + Native Platform Configuration Database (PCD) PPI + + Different with the EFI_PCD_PPI defined in PI 1.2 specification, the native + PCD PPI provide interfaces for dynamic and dynamic-ex type PCD. + The interfaces for dynamic type PCD do not require the token space guid as parameter, + but interfaces for dynamic-ex type PCD require token space guid as parameter. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCD_PPI_H__ +#define __PCD_PPI_H__ + +#define PCD_PPI_GUID \ + { 0x6e81c58, 0x4ad7, 0x44bc, { 0x83, 0x90, 0xf1, 0x2, 0x65, 0xf7, 0x24, 0x80 } } + +#define PCD_INVALID_TOKEN_NUMBER ((UINTN) 0) + + +/** + Sets the SKU value for subsequent calls to set or get PCD token values. + + SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values. + SetSku() is normally called only once by the system. + + For each item (token), the database can hold a single value that applies to all SKUs, + or multiple values, where each value is associated with a specific SKU Id. Items with multiple, + SKU-specific values are called SKU enabled. + + The SKU Id of zero is reserved as a default. The valid SkuId range is 1 to 255. + For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the + single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the + last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token, + the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been + set for that Id, the results are unpredictable. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @retval VOID + +**/ +typedef +VOID +(EFIAPI *PCD_PPI_SET_SKU)( + IN UINTN SkuId + ); + + + +/** + Retrieves an 8-bit value for a given PCD token. + + Retrieves the current byte-sized value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT8 value. + +**/ +typedef +UINT8 +(EFIAPI *PCD_PPI_GET8)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 16-bit value for a given PCD token. + + Retrieves the current 16-bit value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT16 value. + +**/ +typedef +UINT16 +(EFIAPI *PCD_PPI_GET16)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 32-bit value for a given PCD token. + + Retrieves the current 32-bit value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT32 value. + +**/ +typedef +UINT32 +(EFIAPI *PCD_PPI_GET32)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 64-bit value for a given PCD token. + + Retrieves the current 64-bit value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT64 value. + +**/ +typedef +UINT64 +(EFIAPI *PCD_PPI_GET64)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a pointer to a value for a given PCD token. + + Retrieves the current pointer to the buffer for a PCD token number. + Do not make any assumptions about the alignment of the pointer that + is returned by this function call. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The pointer to the buffer to be retrived. + +**/ +typedef +VOID * +(EFIAPI *PCD_PPI_GET_POINTER)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a Boolean value for a given PCD token. + + Retrieves the current boolean value for a PCD token number. + Do not make any assumptions about the alignment of the pointer that + is returned by this function call. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The Boolean value. + +**/ +typedef +BOOLEAN +(EFIAPI *PCD_PPI_GET_BOOLEAN)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves the size of the value for a given PCD token. + + Retrieves the current size of a particular PCD token. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The size of the value for the PCD token. + +**/ +typedef +UINTN +(EFIAPI *PCD_PPI_GET_SIZE)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves an 8-bit value for a given PCD token and token space. + + Retrieves the 8-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 8-bit value for the PCD token. + +**/ +typedef +UINT8 +(EFIAPI *PCD_PPI_GET_EX_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 16-bit value for a given PCD token and token space. + + Retrieves the 16-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 16-bit value for the PCD token. + +**/ +typedef +UINT16 +(EFIAPI *PCD_PPI_GET_EX_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 32-bit value for a given PCD token and token space. + + Retrieves the 32-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 32-bit value for the PCD token. + +**/ +typedef +UINT32 +(EFIAPI *PCD_PPI_GET_EX_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 64-bit value for a given PCD token and token space. + + Retrieves the 64-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 64-bit value for the PCD token. + +**/ +typedef +UINT64 +(EFIAPI *PCD_PPI_GET_EX_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a pointer to a value for a given PCD token and token space. + + Retrieves the current pointer to the buffer for a PCD token number. + Do not make any assumptions about the alignment of the pointer that + is returned by this function call. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The pointer to the buffer to be retrived. + +**/ +typedef +VOID * +(EFIAPI *PCD_PPI_GET_EX_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves an Boolean value for a given PCD token and token space. + + Retrieves the Boolean value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size Boolean value for the PCD token. + +**/ +typedef +BOOLEAN +(EFIAPI *PCD_PPI_GET_EX_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves the size of the value for a given PCD token and token space. + + Retrieves the current size of a particular PCD token. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size of the value for the PCD token. + +**/ +typedef +UINTN +(EFIAPI *PCD_PPI_GET_EX_SIZE)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Sets an 8-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET8)( + IN UINTN TokenNumber, + IN UINT8 Value + ); + + + +/** + Sets a 16-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET16)( + IN UINTN TokenNumber, + IN UINT16 Value + ); + + + +/** + Sets a 32-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET32)( + IN UINTN TokenNumber, + IN UINT32 Value + ); + + + +/** + Sets a 64-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET64)( + IN UINTN TokenNumber, + IN UINT64 Value + ); + +/** + Sets a value of a specified size for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in, out] SizeOfValue A pointer to the length of the value being set for the PCD token. + On input, if the SizeOfValue is greater than the maximum size supported + for this TokenNumber then the output value of SizeOfValue will reflect + the maximum size supported for this TokenNumber. + @param[in] Buffer The buffer to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_POINTER)( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfValue, + IN VOID *Buffer + ); + +/** + Sets an Boolean value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_BOOLEAN)( + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + + + +/** + Sets an 8-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ); + + + +/** + Sets a 16-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ); + + + +/** + Sets a 32-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ); + + + +/** + Sets a 64-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ); + + + +/** + Sets a value of a specified size for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in, out] SizeOfValue A pointer to the length of the value being set for the PCD token. + On input, if the SizeOfValue is greater than the maximum size supported + for this TokenNumber then the output value of SizeOfValue will reflect + the maximum size supported for this TokenNumber. + @param[in] Buffer The buffer to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfValue, + IN VOID *Buffer + ); + +/** + Sets an Boolean value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + + + +/** + Callback on SET function prototype definition. + + This notification function serves two purposes. Firstly, it notifies the module + which did the registration that the value of this PCD token has been set. Secondly, + it provides a mechanism for the module which did the registration to intercept the set + operation and override the value been set if necessary. After the invocation of the + callback function, TokenData will be used by PCD service PEIM to modify the internal data + in PCD database. + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in, out] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + + @retval VOID + +**/ +typedef +VOID +(EFIAPI *PCD_PPI_CALLBACK)( + IN CONST EFI_GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN OUT VOID *TokenData, + IN UINTN TokenDataSize + ); + + + +/** + Specifies a function to be called anytime the value of a designated token is changed. + + @param[in] TokenNumber The PCD token number. + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event + for the CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_CALLBACK_ONSET)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_PPI_CALLBACK CallBackFunction + ); + + + +/** + Cancels a previously set callback function for a particular PCD token number. + + @param[in] TokenNumber The PCD token number. + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event + for the CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_CANCEL_CALLBACK)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_PPI_CALLBACK CallBackFunction + ); + + + +/** + Retrieves the next valid token number in a given namespace. + + This is useful since the PCD infrastructure contains a sparse list of token numbers, + and one cannot a priori know what token numbers are valid in the database. + + If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned. + If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned. + If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned. + If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned. + The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid. + If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned. + If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned. + If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned. + + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + This is an optional parameter that may be NULL. If this parameter is NULL, then a request + is being made to retrieve tokens from the default token space. + @param[in, out] TokenNumber A pointer to the PCD token number to use to find the subsequent token number. + + @retval EFI_SUCCESS The PCD service has retrieved the next valid token number. + @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_GET_NEXT_TOKEN)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ); + + + +/** + Retrieves the next valid PCD token namespace for a given namespace. + + Gets the next valid token namespace for a given namespace. This is useful to traverse the valid + token namespaces on a platform. + + @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token + namespace from which the search will start. On output, it designates the next valid + token namespace on the platform. If *Guid is NULL, then the GUID of the first token + space of the current platform is returned. If the search cannot locate the next valid + token namespace, an error is returned and the value of *Guid is undefined. + + @retval EFI_SUCCESS The PCD service retrieved the value requested. + @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_GET_NEXT_TOKENSPACE)( + IN OUT CONST EFI_GUID **Guid + ); + + + +/// +/// This service abstracts the ability to set/get Platform Configuration Database (PCD). +/// +typedef struct { + PCD_PPI_SET_SKU SetSku; + + PCD_PPI_GET8 Get8; + PCD_PPI_GET16 Get16; + PCD_PPI_GET32 Get32; + PCD_PPI_GET64 Get64; + PCD_PPI_GET_POINTER GetPtr; + PCD_PPI_GET_BOOLEAN GetBool; + PCD_PPI_GET_SIZE GetSize; + + PCD_PPI_GET_EX_8 Get8Ex; + PCD_PPI_GET_EX_16 Get16Ex; + PCD_PPI_GET_EX_32 Get32Ex; + PCD_PPI_GET_EX_64 Get64Ex; + PCD_PPI_GET_EX_POINTER GetPtrEx; + PCD_PPI_GET_EX_BOOLEAN GetBoolEx; + PCD_PPI_GET_EX_SIZE GetSizeEx; + + PCD_PPI_SET8 Set8; + PCD_PPI_SET16 Set16; + PCD_PPI_SET32 Set32; + PCD_PPI_SET64 Set64; + PCD_PPI_SET_POINTER SetPtr; + PCD_PPI_SET_BOOLEAN SetBool; + + PCD_PPI_SET_EX_8 Set8Ex; + PCD_PPI_SET_EX_16 Set16Ex; + PCD_PPI_SET_EX_32 Set32Ex; + PCD_PPI_SET_EX_64 Set64Ex; + PCD_PPI_SET_EX_POINTER SetPtrEx; + PCD_PPI_SET_EX_BOOLEAN SetBoolEx; + + PCD_PPI_CALLBACK_ONSET CallbackOnSet; + PCD_PPI_CANCEL_CALLBACK CancelCallback; + PCD_PPI_GET_NEXT_TOKEN GetNextToken; + PCD_PPI_GET_NEXT_TOKENSPACE GetNextTokenSpace; +} PCD_PPI; + + +extern EFI_GUID gPcdPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PcdInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PcdInfo.h new file mode 100644 index 0000000..8608bd2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PcdInfo.h @@ -0,0 +1,105 @@ +/** @file + Native Platform Configuration Database (PCD) INFO PPI + + The PPI that provides additional information about items that reside in the PCD database. + + Different with the EFI_GET_PCD_INFO_PPI defined in PI 1.2.1 specification, + the native PCD INFO PPI provide interfaces for dynamic and dynamic-ex type PCD. + The interfaces for dynamic type PCD do not require the token space guid as parameter, + but interfaces for dynamic-ex type PCD require token space guid as parameter. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCD_INFO_PPI_H__ +#define __PCD_INFO_PPI_H__ + +extern EFI_GUID gGetPcdInfoPpiGuid; + +#define GET_PCD_INFO_PPI_GUID \ + { 0x4d8b155b, 0xc059, 0x4c8f, { 0x89, 0x26, 0x6, 0xfd, 0x43, 0x31, 0xdb, 0x8a } } + +/// +/// The forward declaration for GET_PCD_INFO_PPI. +/// +typedef struct _GET_PCD_INFO_PPI GET_PCD_INFO_PPI; + +/** + Retrieve additional information associated with a PCD token in the default token space. + + 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. + + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + + @retval EFI_SUCCESS The PCD information was returned successfully + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_PCD_INFO_PPI_GET_INFO) ( + IN UINTN TokenNumber, + OUT EFI_PCD_INFO *PcdInfo +); + +/** + 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. + + @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. + + @retval EFI_SUCCESS The PCD information was returned successfully + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_PCD_INFO_PPI_GET_INFO_EX) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + OUT EFI_PCD_INFO *PcdInfo +); + +/** + 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. +**/ +typedef +UINTN +(EFIAPI *GET_PCD_INFO_PPI_GET_SKU) ( + VOID +); + +/// +/// This is the PCD service to use when querying for some additional data that can be contained in the +/// PCD database. +/// +struct _GET_PCD_INFO_PPI { + /// + /// Retrieve additional information associated with a PCD. + /// + GET_PCD_INFO_PPI_GET_INFO GetInfo; + GET_PCD_INFO_PPI_GET_INFO_EX GetInfoEx; + /// + /// Retrieve the currently set SKU Id. + /// + GET_PCD_INFO_PPI_GET_SKU GetSku; +}; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PciCfg2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PciCfg2.h new file mode 100644 index 0000000..ea11485 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PciCfg2.h @@ -0,0 +1,184 @@ +/** @file + This file declares PciCfg2 PPI. + + This ppi Provides platform or chipset-specific access to + the PCI configuration space for a specific PCI segment. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __PEI_PCI_CFG2_H__ +#define __PEI_PCI_CFG2_H__ + +#include + +#define EFI_PEI_PCI_CFG2_PPI_GUID \ + { 0x57a449a, 0x1fdc, 0x4c06, { 0xbf, 0xc9, 0xf5, 0x3f, 0x6a, 0x99, 0xbb, 0x92 } } + +typedef struct _EFI_PEI_PCI_CFG2_PPI EFI_PEI_PCI_CFG2_PPI; + +#define EFI_PEI_PCI_CFG_ADDRESS(bus,dev,func,reg) \ + (UINT64) ( \ + (((UINTN) bus) << 24) | \ + (((UINTN) dev) << 16) | \ + (((UINTN) func) << 8) | \ + (((UINTN) (reg)) < 256 ? ((UINTN) (reg)) : (UINT64) (LShiftU64 ((UINT64) (reg), 32)))) + +/// +/// EFI_PEI_PCI_CFG_PPI_WIDTH +/// +typedef enum { + /// + /// 8-bit access + /// + EfiPeiPciCfgWidthUint8 = 0, + /// + /// 16-bit access + /// + EfiPeiPciCfgWidthUint16 = 1, + /// + /// 32-bit access + /// + EfiPeiPciCfgWidthUint32 = 2, + /// + /// 64-bit access + /// + EfiPeiPciCfgWidthUint64 = 3, + EfiPeiPciCfgWidthMaximum +} EFI_PEI_PCI_CFG_PPI_WIDTH; + +/// +/// EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS +/// +typedef struct { + /// + /// 8-bit register offset within the PCI configuration space for a given device's function + /// space. + /// + UINT8 Register; + /// + /// Only the 3 least-significant bits are used to encode one of 8 possible functions within a + /// given device. + /// + UINT8 Function; + /// + /// Only the 5 least-significant bits are used to encode one of 32 possible devices. + /// + UINT8 Device; + /// + /// 8-bit value to encode between 0 and 255 buses. + /// + UINT8 Bus; + /// + /// Register number in PCI configuration space. If this field is zero, then Register is used + /// for the register number. If this field is non-zero, then Register is ignored and this field + /// is used for the register number. + /// + UINT32 ExtendedRegister; +} EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS; + +/** + Reads from or write to a given location in the PCI configuration space. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Width The width of the access. Enumerated in bytes. + See EFI_PEI_PCI_CFG_PPI_WIDTH above. + + @param Address The physical address of the access. The format of + the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. + + @param Buffer A pointer to the buffer of data.. + + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_DEVICE_ERROR There was a problem with the transaction. + + @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this + time. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCI_CFG2_PPI_IO)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer +); + + +/** + Performs a read-modify-write operation on the contents + from a given location in the PCI configuration space. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Width The width of the access. Enumerated in bytes. Type + EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). + + @param Address The physical address of the access. + + @param SetBits Points to value to bitwise-OR with the read configuration value. + + The size of the value is determined by Width. + + @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value. + The size of the value is determined by Width. + + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_DEVICE_ERROR There was a problem with the transaction. + + @retval EFI_DEVICE_NOT_READY The device is not capable of supporting + the operation at this time. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCI_CFG2_PPI_RW)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_PCI_CFG2_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN VOID *SetBits, + IN VOID *ClearBits +); + +/// +/// The EFI_PEI_PCI_CFG_PPI interfaces are used to abstract accesses to PCI +/// controllers behind a PCI root bridge controller. +/// +struct _EFI_PEI_PCI_CFG2_PPI { + EFI_PEI_PCI_CFG2_PPI_IO Read; + EFI_PEI_PCI_CFG2_PPI_IO Write; + EFI_PEI_PCI_CFG2_PPI_RW Modify; + /// + /// The PCI bus segment which the specified functions will access. + /// + UINT16 Segment; +}; + + +extern EFI_GUID gEfiPciCfg2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PeiCoreFvLocation.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PeiCoreFvLocation.h new file mode 100644 index 0000000..65be4af --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PeiCoreFvLocation.h @@ -0,0 +1,48 @@ +/** @file + Header file for Pei Core FV Location PPI. + + This PPI contains a pointer to the firmware volume which contains the PEI Foundation. + If the PEI Foundation does not reside in the BFV, then SEC must pass this PPI as a part + of the PPI list provided to the PEI Foundation Entry Point, otherwise the PEI Foundation + shall assume that it resides within the BFV. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.7 Volume 1: + Standards + +**/ + + +#ifndef _EFI_PEI_CORE_FV_LOCATION_H_ +#define _EFI_PEI_CORE_FV_LOCATION_H_ + +/// +/// Global ID for EFI_PEI_CORE_FV_LOCATION_PPI +/// +#define EFI_PEI_CORE_FV_LOCATION_GUID \ + { \ + 0x52888eae, 0x5b10, 0x47d0, {0xa8, 0x7f, 0xb8, 0x22, 0xab, 0xa0, 0xca, 0xf4 } \ + } + +/// +/// This PPI provides location of EFI PeiCoreFv. +/// +typedef struct { + /// + /// Pointer to the first byte of the firmware volume which contains the PEI Foundation. + /// + VOID *PeiCoreFvLocation; +} EFI_PEI_CORE_FV_LOCATION_PPI; + +extern EFI_GUID gEfiPeiCoreFvLocationPpiGuid; + +#endif // _EFI_PEI_CORE_FV_LOCATION_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcd.h new file mode 100644 index 0000000..41b0c2e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcd.h @@ -0,0 +1,432 @@ +/** @file + Platform Configuration Database (PCD) PPI defined in PI 1.2 Vol3 + + A platform database that contains a variety of current platform settings or + directives that can be accessed by a driver or application. + PI PCD ppi only provide the accessing interfaces for Dynamic-Ex type PCD. + + This is the base PCD service API that provides an abstraction for accessing configuration content in + the platform. It a seamless mechanism for extracting information regardless of where the + information is stored (such as in Read-only data, or an EFI Variable). + This protocol allows access to data through size-granular APIs and provides a mechanism for a + firmware component to monitor specific settings and be alerted when a setting is changed. + + Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2 Vol 3. +**/ + +#ifndef __PI_PCD_PPI_H__ +#define __PI_PCD_PPI_H__ + +extern EFI_GUID gEfiPeiPcdPpiGuid; + +#define EFI_PEI_PCD_PPI_GUID \ + { 0x1f34d25, 0x4de2, 0x23ad, { 0x3f, 0xf3, 0x36, 0x35, 0x3f, 0xf3, 0x23, 0xf1 } } + +#define EFI_PCD_INVALID_TOKEN_NUMBER ((UINTN) 0) + +/** + SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values. SetSku() is + normally called only once by the system. + For each item (token), the database can hold a single value that applies to all SKUs, or multiple + values, where each value is associated with a specific SKU Id. Items with multiple, SKU-specific + values are called SKU enabled. + The SKU Id of zero is reserved as a default. The valid SkuId range is 1 to 255. For tokens that are + not SKU enabled, the system ignores any set SKU Id and works with the single value for that token. + For SKU-enabled tokens, the system will use the SKU Id set by the last call to SetSku(). If no + SKU Id is set or the currently set SKU Id isn't valid for the specified token, the system uses the + default SKU Id. If the system attempts to use the default SKU Id and no value has been set for that + Id, the results are unpredictable. + + @param[in] SkuId The SKU value to set. +**/ +typedef +VOID +(EFIAPI *EFI_PEI_PCD_PPI_SET_SKU)( + IN UINTN SkuId +); + +/** + Retrieves the current byte-sized value for a PCD token number. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + + @return 8-bit value for a given PCD token. +**/ +typedef +UINT8 +(EFIAPI *EFI_PEI_PCD_PPI_GET_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current word-sized value for a PCD token number. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + + @return 16-bit value for a given PCD token. +**/ +typedef +UINT16 +(EFIAPI *EFI_PEI_PCD_PPI_GET_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current 32-bit value for a PCD token number. If the TokenNumber is invalid, the + results are unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + + @return 32-bit value for a given PCD token. +**/ +typedef +UINT32 +(EFIAPI *EFI_PEI_PCD_PPI_GET_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current 64-bit value for a PCD token number. If the TokenNumber is invalid, the + results are unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + + @return 64-bit value for a given PCD token. +**/ +typedef +UINT64 +(EFIAPI *EFI_PEI_PCD_PPI_GET_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current pointer to the value for a PCD token number. There should not be any + alignment assumptions about the pointer that is returned by this function call. If the TokenNumber + is invalid, the results are unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. +**/ +typedef +VOID * +(EFIAPI *EFI_PEI_PCD_PPI_GET_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current Boolean-sized value for a PCD token number. If the TokenNumber is + invalid, the results are unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + + @return Boolean value for a given PCD token. +**/ +typedef +BOOLEAN +(EFIAPI *EFI_PEI_PCD_PPI_GET_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current size of a particular PCD token. If the TokenNumber is invalid, the results are + unpredictable. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + + @return the size of the value for a given PCD token. +**/ +typedef +UINTN +(EFIAPI *EFI_PEI_PCD_PPI_GET_SIZE)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Sets an 8-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_SET_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value +); + +/** + Sets an 16-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_SET_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value +); + +/** + Sets an 32-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_SET_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value +); + +/** + Sets an 64-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_SET_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value +); + +/** + Sets a value of the specified size for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + @param[in] SizeOfValue The length of the value being set for the PCD token. If too large of a length is + specified, upon return from this function the value of SizeOfValue will reflect the + maximum size for the PCD token. + @param[in] Buffer A pointer to the buffer containing the value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_SET_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfValue, + IN VOID *Buffer +); + +/** + Sets a Boolean value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_SET_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value +); + +typedef +VOID +(EFIAPI *EFI_PEI_PCD_PPI_CALLBACK)( + IN EFI_GUID *Guid OPTIONAL, + IN UINTN CallBackToken, + IN OUT VOID *TokenData, + IN UINTN TokenDatSize +); + +/** + Specifies a function to be called anytime the value of a designated token is changed. + + @param[in] Guid The 128-bit unique value that designates which namespace to monitor. If NULL, use + the standard platform namespace. + @param[in] CallBackToken The PCD token number to monitor. + @param[in] CallBackFunction The function prototype that will be called when the value associated with the + CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event for the + CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_CALLBACK_ON_SET)( + IN CONST EFI_GUID *Guid OPTIONAL, + IN UINTN CallBackToken, + IN EFI_PEI_PCD_PPI_CALLBACK CallBackFunction +); + +/** + Cancels a previously set callback function for a particular PCD token number. + + @param[in] Guid The 128-bit unique value that designates which namespace to monitor. If NULL, use + the standard platform namespace. + @param[in] CallBackToken The PCD token number to cancel monitoring. + @param[in] CallBackFunction The function prototype that was originally passed to the CallBackOnSet function. + + @retval EFI_SUCCESS The PCD service has cancelled the call event associated with the + CallBackToken. + @retval EFI_INVALID_PARAMETER The PCD service did not match the CallBackFunction to one + that is currently being monitored. + @retval EFI_NOT_FOUND The PCD service could not find data the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_CANCEL_CALLBACK)( + IN CONST EFI_GUID *Guid OPTIONAL, + IN UINTN CallBackToken, + IN EFI_PEI_PCD_PPI_CALLBACK CallBackFunction +); + +/** + Retrieves the next valid PCD token for a given namespace. + + This provides a means by which to get the next valid token number in a given namespace. This is + useful since the PCD infrastructure has a sparse list of token numbers in it, and one cannot a priori + know what token numbers are valid in the database. + + @param[in] Guid The 128-bit unique value that designates which namespace to extract the value from. + @param[in] TokenNumber A pointer to the PCD token number to use to find the subsequent token number. To + retrieve the "first" token, have the pointer reference a TokenNumber value of 0. + + @retval EFI_SUCCESS The PCD service has retrieved the value requested. + @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_GET_NEXT_TOKEN)( + IN CONST EFI_GUID *Guid OPTIONAL, + IN UINTN *TokenNumber +); + +/** + Retrieves the next valid PCD token namespace for a given namespace. + + Gets the next valid token namespace for a given namespace. This is useful to traverse the valid + token namespaces on a platform. + + @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token + namespace from which the search will start. On output, it designates the next valid + token namespace on the platform. If *Guid is NULL, then the GUID of the first token + space of the current platform is returned. If the search cannot locate the next valid + token namespace, an error is returned and the value of *Guid is undefined. + + @retval EFI_SUCCESS The PCD service retrieved the value requested. + @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCD_PPI_GET_NEXT_TOKEN_SPACE)( + IN OUT CONST EFI_GUID **Guid +); + +typedef struct { + EFI_PEI_PCD_PPI_SET_SKU SetSku; + EFI_PEI_PCD_PPI_GET_8 Get8; + EFI_PEI_PCD_PPI_GET_16 Get16; + EFI_PEI_PCD_PPI_GET_32 Get32; + EFI_PEI_PCD_PPI_GET_64 Get64; + EFI_PEI_PCD_PPI_GET_POINTER GetPtr; + EFI_PEI_PCD_PPI_GET_BOOLEAN GetBool; + EFI_PEI_PCD_PPI_GET_SIZE GetSize; + EFI_PEI_PCD_PPI_SET_8 Set8; + EFI_PEI_PCD_PPI_SET_16 Set16; + EFI_PEI_PCD_PPI_SET_32 Set32; + EFI_PEI_PCD_PPI_SET_64 Set64; + EFI_PEI_PCD_PPI_SET_POINTER SetPtr; + EFI_PEI_PCD_PPI_SET_BOOLEAN SetBool; + EFI_PEI_PCD_PPI_CALLBACK_ON_SET CallbackOnSet; + EFI_PEI_PCD_PPI_CANCEL_CALLBACK CancelCallback; + EFI_PEI_PCD_PPI_GET_NEXT_TOKEN GetNextToken; + EFI_PEI_PCD_PPI_GET_NEXT_TOKEN_SPACE GetNextTokenSpace; +} EFI_PEI_PCD_PPI; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcdInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcdInfo.h new file mode 100644 index 0000000..20571f8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/PiPcdInfo.h @@ -0,0 +1,82 @@ +/** @file + Platform Configuration Database (PCD) Info Ppi defined in PI 1.2.1 Vol3. + + The PPI that provides additional information about items that reside in the PCD database. + + Copyright (c) 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2.1 Vol 3. +**/ + +#ifndef __PI_PCD_INFO_PPI_H__ +#define __PI_PCD_INFO_PPI_H__ + +extern EFI_GUID gEfiGetPcdInfoPpiGuid; + +#define EFI_GET_PCD_INFO_PPI_GUID \ + { 0xa60c6b59, 0xe459, 0x425d, { 0x9c, 0x69, 0xb, 0xcc, 0x9c, 0xb2, 0x7d, 0x81 } } + +/// +/// The forward declaration for EFI_GET_PCD_INFO_PPI. +/// +typedef struct _EFI_GET_PCD_INFO_PPI EFI_GET_PCD_INFO_PPI; + +/** + 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. + + @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. + + @retval EFI_SUCCESS The PCD information was returned successfully + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_PCD_INFO_PPI_GET_INFO) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + OUT EFI_PCD_INFO *PcdInfo +); + +/** + 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. +**/ +typedef +UINTN +(EFIAPI *EFI_GET_PCD_INFO_PPI_GET_SKU) ( + VOID +); + +/// +/// This is the PCD service to use when querying for some additional data that can be contained in the +/// PCD database. +/// +struct _EFI_GET_PCD_INFO_PPI { + /// + /// Retrieve additional information associated with a PCD. + /// + EFI_GET_PCD_INFO_PPI_GET_INFO GetInfo; + /// + /// Retrieve the currently set SKU Id. + /// + EFI_GET_PCD_INFO_PPI_GET_SKU GetSku; +}; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReadOnlyVariable2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReadOnlyVariable2.h new file mode 100644 index 0000000..98f559a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReadOnlyVariable2.h @@ -0,0 +1,117 @@ +/** @file + This file declares Read-only Variable Service2 PPI. + This ppi permits read-only access to the UEFI variable store during the PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __PEI_READ_ONLY_VARIABLE2_PPI_H__ +#define __PEI_READ_ONLY_VARIABLE2_PPI_H__ + +#define EFI_PEI_READ_ONLY_VARIABLE2_PPI_GUID \ + { 0x2ab86ef5, 0xecb5, 0x4134, { 0xb5, 0x56, 0x38, 0x54, 0xca, 0x1f, 0xe1, 0xb4 } } + + +typedef struct _EFI_PEI_READ_ONLY_VARIABLE2_PPI EFI_PEI_READ_ONLY_VARIABLE2_PPI; + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. 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 This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI. + @param VariableName A pointer to a null-terminated string that is the variable's name. + @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of + VariableGuid and VariableName must be unique. + @param Attributes If non-NULL, on return, points to the variable's attributes. + @param DataSize On entry, points to the size in bytes of the Data buffer. + On return, points to the size of the data returned in Data. + @param Data Points to the buffer which will hold the returned variable value. + May be NULL with a zero DataSize in order to determine the size of the buffer needed. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data. + DataSize is updated with the size required for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_VARIABLE2)( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param This A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI. + + @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName. + On return, the size of the variable name buffer. + @param VariableName On entry, a pointer to a null-terminated string that is the variable's name. + On return, points to the next variable's null-terminated name string. + + @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_NEXT_VARIABLE_NAME2)( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ); + +/// +/// This PPI provides a lightweight, read-only variant of the full EFI +/// variable services. +/// +struct _EFI_PEI_READ_ONLY_VARIABLE2_PPI { + EFI_PEI_GET_VARIABLE2 GetVariable; + EFI_PEI_GET_NEXT_VARIABLE_NAME2 NextVariableName; +}; + +extern EFI_GUID gEfiPeiReadOnlyVariable2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/RecoveryModule.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/RecoveryModule.h new file mode 100644 index 0000000..70aa40b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/RecoveryModule.h @@ -0,0 +1,87 @@ +/** @file + This file declares Recovery Module PPI. This PPI is used to find and load the + recovery files. + + A module that produces this PPI has many roles and is responsible for the following: + -# Calling the driver recovery PPI EFI_PEI_DEVICE_RECOVERY_MODULE_PPI. + GetNumberRecoveryCapsules() to determine if one or more DXE recovery + entities exist. + -# If no capsules exist, then performing appropriate error handling. + -# Allocating a buffer of MaxRecoveryCapsuleSize as determined by + EFI_PEI_DEVICE_RECOVERY_MODULE_PPI.GetRecoveryCapsuleInfo() or + larger. + -# Determining the policy in which DXE recovery capsules are loaded. + -# Calling the driver recovery PPI EFI_PEI_DEVICE_RECOVERY_MODULE_PPI. + LoadRecoveryCapsule() for capsule number x. + -# If the load failed, performing appropriate error handling. + -# Performing security checks for a loaded DXE recovery capsule. + -# If the security checks failed, then logging the failure in a data HOB. + -# If the security checks failed, then determining the next + EFI_PEI_DEVICE_RECOVERY_MODULE_PPI.LoadRecoveryCapsule()capsule number; + otherwise, go to step 11. + -# If more DXE recovery capsules exist, then go to step 5; otherwise, perform + error handling. + -# Decomposing the capsule loaded by EFI_PEI_DEVICE_RECOVERY_MODULE_PPI. + LoadRecoveryCapsule() into its components. It is assumed that the path + parameters are redundant for recovery and Setup parameters are either + redundant or canned. + -# Invalidating all HOB entries for updateable firmware volume entries. + This invalidation prevents possible errant drivers from being executed. + -# Updating the HOB table with the recovery DXE firmware volume information + generated from the capsule decomposition. + -# Returning to the PEI Dispatcher. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.2 Errata B Volume 1: + Pre-EFI Initalization Core Interface + +**/ + +#ifndef __PEI_RECOVERY_MODULE_PPI_H__ +#define __PEI_RECOVERY_MODULE_PPI_H__ + +#define EFI_PEI_RECOVERY_MODULE_PPI_GUID \ + { \ + 0xFB6D9542, 0x612D, 0x4f45, {0x87, 0x2F, 0x5C, 0xFF, 0x52, 0xE9, 0x3D, 0xCF } \ + } + +typedef struct _EFI_PEI_RECOVERY_MODULE_PPI EFI_PEI_RECOVERY_MODULE_PPI; + +/** + Loads a DXE capsule from some media into memory and updates the HOB table + with the DXE firmware volume information. + + @param PeiServices General-purpose services that are available to every PEIM. + @param This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance. + + @retval EFI_SUCCESS The capsule was loaded correctly. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOAD_RECOVERY_CAPSULE)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_MODULE_PPI *This + ); + +/// +/// Finds and loads the recovery files. +/// +struct _EFI_PEI_RECOVERY_MODULE_PPI { + EFI_PEI_LOAD_RECOVERY_CAPSULE LoadRecoveryCapsule; ///< Loads a DXE binary capsule into memory. +}; + +extern EFI_GUID gEfiPeiRecoveryModulePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReportStatusCodeHandler.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReportStatusCodeHandler.h new file mode 100644 index 0000000..437bd79 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/ReportStatusCodeHandler.h @@ -0,0 +1,82 @@ +/** @file + This PPI provides registering and unregistering services to status code consumers. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __REPORT_STATUS_CODE_HANDLER_PPI_H__ +#define __REPORT_STATUS_CODE_HANDLER_PPI_H__ + +#define EFI_PEI_RSC_HANDLER_PPI_GUID \ + { \ + 0x65d394, 0x9951, 0x4144, {0x82, 0xa3, 0xa, 0xfc, 0x85, 0x79, 0xc2, 0x51} \ + } + +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_RSC_HANDLER_CALLBACK)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN CONST EFI_STATUS_CODE_DATA *Data +); + +/** + Register the callback function for ReportStatusCode() notification. + + When this function is called the function pointer is added to an internal list and any future calls to + ReportStatusCode() will be forwarded to the Callback function. + + @param[in] Callback A pointer to a function of type EFI_PEI_RSC_HANDLER_CALLBACK that is called + when a call to ReportStatusCode() occurs. + + @retval EFI_SUCCESS Function was successfully registered. + @retval EFI_INVALID_PARAMETER The callback function was NULL. + @retval EFI_OUT_OF_RESOURCES The internal buffer ran out of space. No more functions can be + registered. + @retval EFI_ALREADY_STARTED The function was already registered. It can't be registered again. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_RSC_HANDLER_REGISTER)( + IN EFI_PEI_RSC_HANDLER_CALLBACK Callback +); + +/** + Remove a previously registered callback function from the notification list. + + ReportStatusCode() messages will no longer be forwarded to the Callback function. + + @param[in] Callback A pointer to a function of type EFI_PEI_RSC_HANDLER_CALLBACK that is to be + unregistered. + + @retval EFI_SUCCESS The function was successfully unregistered. + @retval EFI_INVALID_PARAMETER The callback function was NULL. + @retval EFI_NOT_FOUND The callback function was not found to be unregistered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_RSC_HANDLER_UNREGISTER)( + IN EFI_PEI_RSC_HANDLER_CALLBACK Callback +); + +typedef struct _EFI_PEI_RSC_HANDLER_PPI { + EFI_PEI_RSC_HANDLER_REGISTER Register; + EFI_PEI_RSC_HANDLER_UNREGISTER Unregister; +} EFI_PEI_RSC_HANDLER_PPI; + +extern EFI_GUID gEfiPeiRscHandlerPpiGuid; + +#endif // __REPORT_STATUS_CODE_HANDLER_PPI_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset.h new file mode 100644 index 0000000..cbc5de3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset.h @@ -0,0 +1,44 @@ +/** @file + This file declares Reset PPI used to reset the platform. + + This PPI is installed by some platform- or chipset-specific PEIM that + abstracts the Reset Service to other agents. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __RESET_PPI_H__ +#define __RESET_PPI_H__ + +#define EFI_PEI_RESET_PPI_GUID \ + { \ + 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78, 0xc6, 0xf4, 0xfe, 0x71, 0x2f } \ + } + +// +// EFI_PEI_RESET_PPI.ResetSystem() is equivalent to the +// PEI Service ResetSystem(). +// It is introduced in PIPeiCis.h. +// + +/// +/// This PPI provides provide a simple reset service. +/// +typedef struct { + EFI_PEI_RESET_SYSTEM ResetSystem; +} EFI_PEI_RESET_PPI; + +extern EFI_GUID gEfiPeiResetPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset2.h new file mode 100644 index 0000000..8834ba8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Reset2.h @@ -0,0 +1,38 @@ +/** @file + This file declares Reset2 PPI used to reset the platform. + + This PPI is installed by some platform- or chipset-specific PEIM that + abstracts the Reset Service to other agents. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.4. + +**/ + +#ifndef __RESET2_PPI_H__ +#define __RESET2_PPI_H__ + +#define EFI_PEI_RESET2_PPI_GUID \ + { \ + 0x6cc45765, 0xcce4, 0x42fd, {0xbc, 0x56, 0x1, 0x1a, 0xaa, 0xc6, 0xc9, 0xa8 } \ + } + +/// +/// This PPI provides provide a simple reset service. +/// +typedef struct _EFI_PEI_RESET2_PPI { + EFI_PEI_RESET2_SYSTEM ResetSystem; +} EFI_PEI_RESET2_PPI; + +extern EFI_GUID gEfiPeiReset2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/S3Resume2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/S3Resume2.h new file mode 100644 index 0000000..bb18ef8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/S3Resume2.h @@ -0,0 +1,92 @@ +/** @file + This PPI produces functions to interpret and execute the PI boot script table. + + This PPI is published by a PEIM and provides for the restoration of the platform's + configuration when resuming from the ACPI S3 power state. The ability to execute + the boot script may depend on the availability of other PPIs. For example, if + the boot script includes an SMBus command, this PEIM looks for the relevant PPI + that is able to execute that command. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.2 Volume 5: + Standards + +**/ + +#ifndef __PEI_S3_RESUME_PPI_H__ +#define __PEI_S3_RESUME_PPI_H__ + +/// +/// Global ID for EFI_PEI_S3_RESUME2_PPI +/// +#define EFI_PEI_S3_RESUME2_PPI_GUID \ + { \ + 0x6D582DBC, 0xDB85, 0x4514, {0x8F, 0xCC, 0x5A, 0xDF, 0x62, 0x27, 0xB1, 0x47 } \ + } + +/// +/// Forward declaration for EFI_PEI_S3_RESUME_PPI +/// +typedef struct _EFI_PEI_S3_RESUME2_PPI EFI_PEI_S3_RESUME2_PPI; + +/** + Restores the platform to its preboot configuration for an S3 resume and + jumps to the OS waking vector. + + This function will restore the platform to its pre-boot configuration that was + pre-stored in the boot script table and transfer control to OS waking vector. + Upon invocation, this function is responsible for locating the following + information before jumping to OS waking vector: + - ACPI tables + - boot script table + - any other information that it needs + + The S3RestoreConfig() function then executes the pre-stored boot script table + and transitions the platform to the pre-boot state. The boot script is recorded + during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and + EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions. Finally, this function + transfers control to the OS waking vector. If the OS supports only a real-mode + waking vector, this function will switch from flat mode to real mode before + jumping to the waking vector. If all platform pre-boot configurations are + successfully restored and all other necessary information is ready, this + function will never return and instead will directly jump to the OS waking + vector. If this function returns, it indicates that the attempt to resume + from the ACPI S3 sleep state failed. + + @param[in] This Pointer to this instance of the PEI_S3_RESUME_PPI + + @retval EFI_ABORTED Execution of the S3 resume boot script table failed. + @retval EFI_NOT_FOUND Some necessary information that is used for the S3 + resume boot path could not be located. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_S3_RESUME_PPI_RESTORE_CONFIG2)( + IN EFI_PEI_S3_RESUME2_PPI *This + ); + +/** + EFI_PEI_S3_RESUME2_PPI accomplishes the firmware S3 resume boot + path and transfers control to OS. +**/ +struct _EFI_PEI_S3_RESUME2_PPI { + /// + /// Restores the platform to its preboot configuration for an S3 resume and + /// jumps to the OS waking vector. + /// + EFI_PEI_S3_RESUME_PPI_RESTORE_CONFIG2 S3RestoreConfig2; +}; + +extern EFI_GUID gEfiPeiS3Resume2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecHobData.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecHobData.h new file mode 100644 index 0000000..73a1c96 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecHobData.h @@ -0,0 +1,65 @@ +/** @file + This file declares Sec Hob Data PPI. + + This PPI provides a way for the SEC code to pass zero or more HOBs in a HOB list. + +Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.5. + +**/ + +#ifndef __SEC_HOB_DATA_PPI_H__ +#define __SEC_HOB_DATA_PPI_H__ + +#include + +#define EFI_SEC_HOB_DATA_PPI_GUID \ + { \ + 0x3ebdaf20, 0x6667, 0x40d8, {0xb4, 0xee, 0xf5, 0x99, 0x9a, 0xc1, 0xb7, 0x1f } \ + } + +typedef struct _EFI_SEC_HOB_DATA_PPI EFI_SEC_HOB_DATA_PPI; + +/** + Return a pointer to a buffer containing zero or more HOBs that + will be installed into the PEI HOB List. + + This function returns a pointer to a pointer to zero or more HOBs, + terminated with a HOB of type EFI_HOB_TYPE_END_OF_HOB_LIST. + Note: The HobList must not contain a EFI_HOB_HANDOFF_INFO_TABLE HOB (PHIT) HOB. + + @param[in] This Pointer to this PPI structure. + @param[out] HobList A pointer to a returned pointer to zero or more HOBs. + If no HOBs are to be returned, then the returned pointer + is a pointer to a HOB of type EFI_HOB_TYPE_END_OF_HOB_LIST. + + @retval EFI_SUCCESS This function completed successfully. + @retval EFI_NOT_FOUND No HOBS are available. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SEC_HOB_DATA_GET) ( + IN CONST EFI_SEC_HOB_DATA_PPI *This, + OUT EFI_HOB_GENERIC_HEADER **HobList +); + +/// +/// This PPI provides a way for the SEC code to pass zero or more HOBs in a HOB list. +/// +struct _EFI_SEC_HOB_DATA_PPI { + EFI_SEC_HOB_DATA_GET GetHobs; +}; + +extern EFI_GUID gEfiSecHobDataPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation.h new file mode 100644 index 0000000..eaf73ce --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation.h @@ -0,0 +1,188 @@ +/** @file + This file declares Sec Platform Information PPI. + + This service is the primary handoff state into the PEI Foundation. + The Security (SEC) component creates the early, transitory memory + environment and also encapsulates knowledge of at least the + location of the Boot Firmware Volume (BFV). + +Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __SEC_PLATFORM_INFORMATION_PPI_H__ +#define __SEC_PLATFORM_INFORMATION_PPI_H__ + +#include + +#define EFI_SEC_PLATFORM_INFORMATION_GUID \ + { \ + 0x6f8c2b35, 0xfef4, 0x448d, {0x82, 0x56, 0xe1, 0x1b, 0x19, 0xd6, 0x10, 0x77 } \ + } + +typedef struct _EFI_SEC_PLATFORM_INFORMATION_PPI EFI_SEC_PLATFORM_INFORMATION_PPI; + + +/// +/// EFI_HEALTH_FLAGS +/// Contains information generated by microcode, hardware, and/or the Itanium +/// processor PAL code about the state of the processor upon reset. +/// +typedef union { + struct { + /// + /// A 2-bit field indicating self-test state after reset. + /// + UINT32 Status : 2; + /// + /// A 1-bit field indicating whether testing has occurred. + /// If this field is zero, the processor has not been tested, + /// and no further fields in the self-test State parameter are valid. + /// + UINT32 Tested : 1; + /// + /// Reserved 13 bits. + /// + UINT32 Reserved1 :13; + /// + /// A 1-bit field. If set to 1, this indicates that virtual + /// memory features are not available. + /// + UINT32 VirtualMemoryUnavailable : 1; + /// + /// A 1-bit field. If set to 1, this indicates that IA-32 execution + /// is not available. + /// + UINT32 Ia32ExecutionUnavailable : 1; + /// + /// A 1-bit field. If set to 1, this indicates that the floating + /// point unit is not available. + /// + UINT32 FloatingPointUnavailable : 1; + /// + /// A 1-bit field. If set to 1, this indicates miscellaneous + /// functional failure other than vm, ia, or fp. + /// The test status field provides additional information on + /// test failures when the State field returns a value of + /// performance restricted or functionally restricted. + /// The value returned is implementation dependent. + /// + UINT32 MiscFeaturesUnavailable : 1; + /// + /// Reserved 12 bits. + /// + UINT32 Reserved2 :12; + } Bits; + UINT32 Uint32; +} EFI_HEALTH_FLAGS; + +#define NORMAL_BOOT_CALL 0x0 +#define RECOVERY_CHECK_CALL 0x3 + +typedef EFI_HEALTH_FLAGS X64_HANDOFF_STATUS; +typedef EFI_HEALTH_FLAGS IA32_HANDOFF_STATUS; +/// +/// The hand-off status structure for Itanium architecture. +/// +typedef struct { + /// + /// SALE_ENTRY state : 3 = Recovery_Check + /// and 0 = RESET or Normal_Boot phase. + /// + UINT8 BootPhase; + /// + /// Firmware status on entry to SALE. + /// + UINT8 FWStatus; + UINT16 Reserved1; + UINT32 Reserved2; + /// + /// Geographically significant unique processor ID assigned by PAL. + /// + UINT16 ProcId; + UINT16 Reserved3; + UINT8 IdMask; + UINT8 EidMask; + UINT16 Reserved4; + /// + /// Address to make PAL calls. + /// + UINT64 PalCallAddress; + /// + /// If the entry state is RECOVERY_CHECK, this contains the PAL_RESET + /// return address, and if entry state is RESET, this contains + /// address for PAL_authentication call. + /// + UINT64 PalSpecialAddress; + /// + /// GR35 from PALE_EXIT state. + /// + UINT64 SelfTestStatus; + /// + /// GR37 from PALE_EXIT state. + /// + UINT64 SelfTestControl; + UINT64 MemoryBufferRequired; +} ITANIUM_HANDOFF_STATUS; + +/// +/// EFI_SEC_PLATFORM_INFORMATION_RECORD. +/// +typedef union { + IA32_HANDOFF_STATUS IA32HealthFlags; + X64_HANDOFF_STATUS x64HealthFlags; + ITANIUM_HANDOFF_STATUS ItaniumHealthFlags; +} EFI_SEC_PLATFORM_INFORMATION_RECORD; + +/** + This interface conveys state information out of the Security (SEC) phase into PEI. + + This service is published by the SEC phase. The SEC phase handoff has an optional + EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the + PEI Foundation. As such, if the platform supports the built-in self test (BIST) on IA-32 Intel + architecture or the PAL-A handoff state for Itanium architecture, this information is encapsulated + into the data structure abstracted by this service. This information is collected for the boot-strap + processor (BSP) on IA-32. For Itanium architecture, it is available on all processors that execute + the PEI Foundation. + + @param PeiServices The pointer to the PEI Services Table. + @param StructureSize The pointer to the variable describing size of the input buffer. + @param PlatformInformationRecord The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to + hold the record is returned in StructureSize. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SEC_PLATFORM_INFORMATION)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord +); + + +/// +/// This service abstracts platform-specific information. It is necessary +/// to convey this information to the PEI Foundation so that it can +/// discover where to begin dispatching PEIMs. +/// +struct _EFI_SEC_PLATFORM_INFORMATION_PPI { + EFI_SEC_PLATFORM_INFORMATION PlatformInformation; +}; + + +extern EFI_GUID gEfiSecPlatformInformationPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation2.h new file mode 100644 index 0000000..1a6a776 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SecPlatformInformation2.h @@ -0,0 +1,85 @@ +/** @file + This file declares Sec Platform Information2 PPI. + + This service is the primary handoff state into the PEI Foundation. + This service abstracts platform-specific information for many CPU's. + +Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced from PI Version 1.4. + +**/ + +#ifndef __SEC_PLATFORM_INFORMATION2_PPI_H__ +#define __SEC_PLATFORM_INFORMATION2_PPI_H__ + +#include + +#define EFI_SEC_PLATFORM_INFORMATION2_GUID \ + { \ + 0x9e9f374b, 0x8f16, 0x4230, {0x98, 0x24, 0x58, 0x46, 0xee, 0x76, 0x6a, 0x97 } \ + } + +typedef struct _EFI_SEC_PLATFORM_INFORMATION2_PPI EFI_SEC_PLATFORM_INFORMATION2_PPI; + +/// +/// EFI_SEC_PLATFORM_INFORMATION_CPU. +/// +typedef struct { + UINT32 CpuLocation; + EFI_SEC_PLATFORM_INFORMATION_RECORD InfoRecord; +} EFI_SEC_PLATFORM_INFORMATION_CPU; + +/// +/// EFI_SEC_PLATFORM_INFORMATION_RECORD2. +/// +typedef struct { + /// + /// The CPU location would be the local APIC ID + /// + UINT32 NumberOfCpus; + EFI_SEC_PLATFORM_INFORMATION_CPU CpuInstance[1]; +} EFI_SEC_PLATFORM_INFORMATION_RECORD2; + +/** + This interface conveys state information out of the Security (SEC) phase into PEI. + + This service is published by the SEC phase. + + @param PeiServices The pointer to the PEI Services Table. + @param StructureSize The pointer to the variable describing size of the input buffer. + @param PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_BUFFER_TOO_SMALL The buffer was too small. The current buffer size needed to + hold the record is returned in StructureSize. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SEC_PLATFORM_INFORMATION2)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2 +); + +/// +/// This service abstracts platform-specific information for many CPU's. +/// It is the multi-processor equivalent of PlatformInformation for +/// implementations that synchronize some, if not all CPU's in the SEC phase. +/// +struct _EFI_SEC_PLATFORM_INFORMATION2_PPI { + EFI_SEC_PLATFORM_INFORMATION2 PlatformInformation2; +}; + +extern EFI_GUID gEfiSecPlatformInformation2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Security2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Security2.h new file mode 100644 index 0000000..4dc9a77 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Security2.h @@ -0,0 +1,101 @@ +/** @file + This file declares Pei Security2 PPI. + + This PPI is installed by some platform PEIM that abstracts the security + policy to the PEI Foundation, namely the case of a PEIM's authentication + state being returned during the PEI section extraction process. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __SECURITY2_PPI_H__ +#define __SECURITY2_PPI_H__ + +#define EFI_PEI_SECURITY2_PPI_GUID \ + { 0xdcd0be23, 0x9586, 0x40f4, { 0xb6, 0x43, 0x6, 0x52, 0x2c, 0xed, 0x4e, 0xde } } + + +typedef struct _EFI_PEI_SECURITY2_PPI EFI_PEI_SECURITY2_PPI; + +/** + Allows the platform builder to implement a security policy + in response to varying file authentication states. + + This service is published by some platform PEIM. The purpose of + this service is to expose a given platform's policy-based + response to the PEI Foundation. For example, if there is a PEIM + in a GUIDed encapsulation section and the extraction of the PEI + file section yields an authentication failure, there is no a + priori policy in the PEI Foundation. Specifically, this + situation leads to the question whether PEIMs that are either + not in GUIDed sections or are in sections whose authentication + fails should still be executed. + + @param PeiServices An indirect pointer to the PEI Services + Table published by the PEI Foundation. + @param This Interface pointer that implements the + particular EFI_PEI_SECURITY2_PPI instance. + @param AuthenticationStatus Authentication status of the file. + xx00 Image was not signed. + xxx1 Platform security policy override. + Assumes same meaning as 0010 (the image was signed, the + signature was tested, and the signature passed authentication test). + 0010 Image was signed, the signature was tested, + and the signature passed authentication test. + 0110 Image was signed and the signature was not tested. + 1010 Image was signed, the signature was tested, + and the signature failed the authentication test. + @param FvHandle Handle of the volume in which the file + resides. This allows different policies + depending on different firmware volumes. + @param FileHandle Handle of the file under review. + @param DeferExecution Pointer to a variable that alerts the + PEI Foundation to defer execution of a + PEIM. + + @retval EFI_SUCCESS The service performed its action successfully. + @retval EFI_SECURITY_VIOLATION The object cannot be trusted. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SECURITY_AUTHENTICATION_STATE)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_SECURITY2_PPI *This, + IN UINT32 AuthenticationStatus, + IN EFI_PEI_FV_HANDLE FvHandle, + IN EFI_PEI_FILE_HANDLE FileHandle, + IN OUT BOOLEAN *DeferExecution +); + +/// +/// This PPI is a means by which the platform builder can indicate +/// a response to a PEIM's authentication state. This can be in +/// the form of a requirement for the PEI Foundation to skip a +/// module using the DeferExecution Boolean output in the +/// AuthenticationState() member function. Alternately, the +/// Security PPI can invoke something like a cryptographic PPI +/// that hashes the PEIM contents to log attestations, for which +/// the FileHandle parameter in AuthenticationState() will be +/// useful. If this PPI does not exist, PEIMs will be considered +/// trusted. +/// +struct _EFI_PEI_SECURITY2_PPI { + EFI_PEI_SECURITY_AUTHENTICATION_STATE AuthenticationState; +}; + + +extern EFI_GUID gEfiPeiSecurity2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Smbus2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Smbus2.h new file mode 100644 index 0000000..b90c318 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Smbus2.h @@ -0,0 +1,203 @@ +/** @file + This file declares Smbus2 PPI. + This PPI provides the basic I/O interfaces that a PEIM uses to access its + SMBus controller and the slave devices attached to it. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __PEI_SMBUS2_PPI_H__ +#define __PEI_SMBUS2_PPI_H__ + +#include + +#define EFI_PEI_SMBUS2_PPI_GUID \ + { 0x9ca93627, 0xb65b, 0x4324, { 0xa2, 0x2, 0xc0, 0xb4, 0x61, 0x76, 0x45, 0x43 } } + + +typedef struct _EFI_PEI_SMBUS2_PPI EFI_PEI_SMBUS2_PPI; + +/** + Executes an SMBus operation to an SMBus controller. Returns when either + the command has been executed or an error is encountered in doing the operation. + + @param This A pointer to the EFI_PEI_SMBUS2_PPI instance. + @param SlaveAddress The SMBUS hardware address to which the SMBUS device is preassigned or + allocated. + @param Command This command is transmitted by the SMBus host controller to the SMBus slave + device and the interpretation is SMBus slave device specific. + It can mean the offset to a list of functions inside + an SMBus slave device. Not all operations or slave devices support + this command's registers. + @param Operation Signifies which particular SMBus hardware protocol instance that it + will use to execute the SMBus transactions. + This SMBus hardware protocol is defined by the System Management Bus (SMBus) + Specification and is not related to UEFI. + @param PecCheck Defines if Packet Error Code (PEC) checking is required for this operation. + @param Length Signifies the number of bytes that this operation will do. + The maximum number of bytes can be revision specific and operation specific. + This parameter will contain the actual number of bytes that are executed + for this operation. Not all operations require this argument. + @param Buffer Contains the value of data to execute to the SMBus slave device. + Not all operations require this argument. + The length of this buffer is identified by Length. + + + @retval EFI_SUCCESS The last data that was returned from the access + matched the poll exit criteria. + @retval EFI_CRC_ERROR The checksum is not correct (PEC is incorrect) + @retval EFI_TIMEOUT Timeout expired before the operation was completed. + Timeout is determined by the SMBus host controller device. + @retval EFI_OUT_OF_RESOURCES The request could not be completed + due to a lack of resources. + @retval EFI_DEVICE_ERROR The request was not completed because + a failure reflected in the Host Status Register bit. + @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION. + Or Length/Buffer is NULL for operations except for EfiSmbusQuickRead and + EfiSmbusQuickWrite. Or Length is outside the range of valid values. + @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported. + @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS2_PPI_EXECUTE_OPERATION)( + IN CONST EFI_PEI_SMBUS2_PPI *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer +); + +/** + The ArpDevice() function enumerates the entire bus or enumerates a specific + device that is identified by SmbusUdid. + + @param This A pointer to the EFI_PEI_SMBUS2_PPI instance. + @param ArpAll A Boolean expression that indicates if the host drivers need + to enumerate all the devices or enumerate only the device that is identified + by SmbusUdid. If ArpAll is TRUE, SmbusUdid and SlaveAddress are optional. + If ArpAll is FALSE, ArpDevice will enumerate SmbusUdid and the address + will be at SlaveAddress. + @param SmbusUdid The targeted SMBus Unique Device Identifier (UDID). + The UDID may not exist for SMBus devices with fixed addresses. + @param SlaveAddress The new SMBus address for the slave device for + which the operation is targeted. + + @retval EFI_SUCCESS The SMBus slave device address was set. + @retval EFI_INVALID_PARAMETER SlaveAddress is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed + due to a lack of resources. + @retval EFI_TIMEOUT The SMBus slave device did not respond. + @retval EFI_DEVICE_ERROR The request was not completed because the transaction failed. + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are not implemented by this PEIM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS2_PPI_ARP_DEVICE)( + IN CONST EFI_PEI_SMBUS2_PPI *This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID *SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL +); + +/** + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param This A pointer to the EFI_PEI_SMBUS2_PPI instance. + @param Length Size of the buffer that contains the SMBus device map. + @param SmbusDeviceMap The pointer to the device map as enumerated + by the SMBus controller driver. + + @retval EFI_SUCCESS The device map was returned correctly in the buffer. + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are not implemented by this PEIM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS2_PPI_GET_ARP_MAP)( + IN CONST EFI_PEI_SMBUS2_PPI *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap +); + +/** + CallBack function can be registered in EFI_PEI_SMBUS2_PPI_NOTIFY. + + @param This A pointer to the EFI_PEI_SMBUS2_PPI instance. + @param SlaveAddress The SMBUS hardware address to which the SMBUS + device is preassigned or allocated. + @param Data Data of the SMBus host notify command that + the caller wants to be called. + + @retval EFI_SUCCESS NotifyFunction has been registered. + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are not + implemented by this PEIM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS_NOTIFY2_FUNCTION)( + IN CONST EFI_PEI_SMBUS2_PPI *SmbusPpi, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data +); + +/** + The Notify() function registers all the callback functions to allow the + bus driver to call these functions when the SlaveAddress/Data pair happens. + + @param This A pointer to the EFI_PEI_SMBUS2_PPI instance. + @param SlaveAddress Address that the host controller detects as + sending a message and calls all the registered functions. + @param Data Data that the host controller detects as sending a message + and calls all the registered functions. + @param NotifyFunction The function to call when the bus driver + detects the SlaveAddress and Data pair. + + @retval EFI_SUCCESS NotifyFunction has been registered. + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are not + implemented by this PEIM. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS2_PPI_NOTIFY)( + IN CONST EFI_PEI_SMBUS2_PPI *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_PEI_SMBUS_NOTIFY2_FUNCTION NotifyFunction +); + +/// +/// Provides the basic I/O interfaces that a PEIM uses to access +/// its SMBus controller and the slave devices attached to it. +/// +struct _EFI_PEI_SMBUS2_PPI { + EFI_PEI_SMBUS2_PPI_EXECUTE_OPERATION Execute; + EFI_PEI_SMBUS2_PPI_ARP_DEVICE ArpDevice; + EFI_PEI_SMBUS2_PPI_GET_ARP_MAP GetArpMap; + EFI_PEI_SMBUS2_PPI_NOTIFY Notify; + /// + /// Identifier which uniquely identifies this SMBus controller in a system. + /// + EFI_GUID Identifier; +}; + +extern EFI_GUID gEfiPeiSmbus2PpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Stall.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Stall.h new file mode 100644 index 0000000..83b1a36 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/Stall.h @@ -0,0 +1,62 @@ +/** @file + This file declares Stall PPI. + + This ppi abstracts the blocking stall service to other agents. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __STALL_PPI_H__ +#define __STALL_PPI_H__ + +#define EFI_PEI_STALL_PPI_GUID \ + { 0x1f4c6f90, 0xb06b, 0x48d8, {0xa2, 0x01, 0xba, 0xe5, 0xf1, 0xcd, 0x7d, 0x56 } } + +typedef struct _EFI_PEI_STALL_PPI EFI_PEI_STALL_PPI; + +/** + The Stall() function provides a blocking stall for at least the number + of microseconds stipulated in the final argument of the API. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + @param This Pointer to the local data for the interface. + @param Microseconds Number of microseconds for which to stall. + + @retval EFI_SUCCESS The service provided at least the required delay. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_STALL)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +/// +/// This service provides a simple, blocking stall with platform-specific resolution. +/// +struct _EFI_PEI_STALL_PPI { + /// + /// The resolution in microseconds of the stall services. + /// + UINTN Resolution; + + EFI_PEI_STALL Stall; +}; + +extern EFI_GUID gEfiPeiStallPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/StatusCode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/StatusCode.h new file mode 100644 index 0000000..b47ec55 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/StatusCode.h @@ -0,0 +1,41 @@ +/** @file + This file declares Status Code PPI. + This ppi provides a service that allows PEIMs to report status codes. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __STATUS_CODE_PPI_H__ +#define __STATUS_CODE_PPI_H__ + +#define EFI_PEI_REPORT_PROGRESS_CODE_PPI_GUID \ + { 0x229832d3, 0x7a30, 0x4b36, {0xb8, 0x27, 0xf4, 0xc, 0xb7, 0xd4, 0x54, 0x36 } } + +// +// EFI_PEI_PROGRESS_CODE_PPI.ReportStatusCode() is equivalent to the +// PEI Service ReportStatusCode(). +// It is introduced in PIPeiCis.h. +// + +/// +/// This PPI provides the service to report status code. +/// There can be only one instance of this service in the system. +/// +typedef struct { + EFI_PEI_REPORT_STATUS_CODE ReportStatusCode; +} EFI_PEI_PROGRESS_CODE_PPI; + +extern EFI_GUID gEfiPeiStatusCodePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SuperIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SuperIo.h new file mode 100644 index 0000000..6fcfb49 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/SuperIo.h @@ -0,0 +1,189 @@ +/** @file + This PPI provides the super I/O register access functionality. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is from PI Version 1.2.1. + +**/ + +#ifndef __EFI_SUPER_IO_PPI_H__ +#define __EFI_SUPER_IO_PPI_H__ + +#include + +#define EFI_SIO_PPI_GUID \ + { \ + 0x23a464ad, 0xcb83, 0x48b8, {0x94, 0xab, 0x1a, 0x6f, 0xef, 0xcf, 0xe5, 0x22} \ + } + +typedef struct _EFI_SIO_PPI EFI_SIO_PPI; +typedef struct _EFI_SIO_PPI *PEFI_SIO_PPI; + +typedef UINT16 EFI_SIO_REGISTER; +#define EFI_SIO_REG(ldn,reg) (EFI_SIO_REGISTER) (((ldn) << 8) | reg) +#define EFI_SIO_LDN_GLOBAL 0xFF + +/** + Read a Super I/O register. + + The register is specified as an 8-bit logical device number and an 8-bit + register value. The logical device numbers for specific SIO devices can be + determined using the Info member of the PPI structure. + + @param PeiServices A pointer to a pointer to the PEI Services. + @param This A pointer to this instance of the EFI_SIO_PPI. + @param ExitCfgMode A boolean specifying whether the driver should turn on + configuration mode (FALSE) or turn off configuration mode + (TRUE) after completing the read operation. The driver must + track the current state of the configuration mode (if any) + and turn on configuration mode (if necessary) prior to + register access. + @param Register A value specifying the logical device number (bits 15:8) + and the register to read (bits 7:0). The logical device + number of EFI_SIO_LDN_GLOBAL indicates that global + registers will be used. + @param IoData A pointer to the returned register value. + + @retval EFI_SUCCESS Success. + @retval EFI_TIMEOUT The register could not be read in the a reasonable + amount of time. The exact time is device-specific. + @retval EFI_INVALID_PARAMETERS Register was out of range for this device. + @retval EFI_INVALID_PARAMETERS IoData was NULL + @retval EFI_DEVICE_ERROR There was a device fault or the device was not present. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SIO_REGISTER_READ)( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_SIO_PPI *This, + IN BOOLEAN ExitCfgMode, + IN EFI_SIO_REGISTER Register, + OUT UINT8 *IoData + ); + +/** + Write a Super I/O register. + + The register is specified as an 8-bit logical device number and an 8-bit register + value. The logical device numbers for specific SIO devices can be determined + using the Info member of the PPI structure. + + @param PeiServices A pointer to a pointer to the PEI Services. + @param This A pointer to this instance of the EFI_SIO_PPI. + @param ExitCfgMode A boolean specifying whether the driver should turn on + configuration mode (FALSE) or turn off configuration mode + (TRUE) after completing the read operation. The driver must + track the current state of the configuration mode (if any) + and turn on configuration mode (if necessary) prior to + register access. + @param Register A value specifying the logical device number (bits 15:8) + and the register to read (bits 7:0). The logical device + number of EFI_SIO_LDN_GLOBAL indicates that global + registers will be used. + @param IoData A pointer to the returned register value. + + @retval EFI_SUCCESS Success. + @retval EFI_TIMEOUT The register could not be read in the a reasonable + amount of time. The exact time is device-specific. + @retval EFI_INVALID_PARAMETERS Register was out of range for this device. + @retval EFI_INVALID_PARAMETERS IoData was NULL + @retval EFI_DEVICE_ERROR There was a device fault or the device was not present. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SIO_REGISTER_WRITE)( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_SIO_PPI *This, + IN BOOLEAN ExitCfgMode, + IN EFI_SIO_REGISTER Register, + IN UINT8 IoData + ); + +/** + Provides an interface for a table based programming of the Super I/O registers. + + The Modify() function provides an interface for table based programming of the + Super I/O registers. This function can be used to perform programming of + multiple Super I/O registers with a single function call. For each table entry, + the Register is read, its content is bitwise ANDed with AndMask, and then ORed + with OrMask before being written back to the Register. The Super I/O driver + must track the current state of the Super I/O and enable the configuration mode + of Super I/O if necessary prior to table processing. Once the table is processed, + the Super I/O device must be returned to the original state. + + @param PeiServices A pointer to a pointer to the PEI Services. + @param This A pointer to this instance of the EFI_SIO_PPI. + @param Command A pointer to an array of NumberOfCommands EFI_SIO_REGISTER_MODIFY + structures. Each structure specifies a single Super I/O register + modify operation. + @param NumberOfCommands The number of elements in the Command array. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETERS Command is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SIO_REGISTER_MODIFY)( + IN EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_SIO_PPI *This, + IN CONST EFI_SIO_REGISTER_MODIFY *Command, + IN UINTN NumberOfCommands + ); + +/// +/// Specifies the end of the information list. +/// +#define EFI_ACPI_PNP_HID_END EFI_PNP_ID (0x0000) + +typedef UINT32 EFI_ACPI_HID; +typedef UINT32 EFI_ACPI_UID; +#pragma pack(1) +typedef struct _EFI_SIO_INFO { + EFI_ACPI_HID Hid; + EFI_ACPI_UID Uid; + UINT8 Ldn; +} EFI_SIO_INFO, *PEFI_SIO_INFO; +#pragma pack() + +/// +/// This PPI provides low-level access to Super I/O registers using Read() and +/// Write(). It also uniquely identifies this Super I/O controller using a GUID +/// and provides mappings between ACPI style PNP IDs and the logical device numbers. +/// There is one instance of this PPI per Super I/O device. +/// +struct _EFI_SIO_PPI { + /// + /// This function reads a register's value from the Super I/O controller. + /// + EFI_PEI_SIO_REGISTER_READ Read; + /// + /// This function writes a value to a register in the Super I/O controller. + /// + EFI_PEI_SIO_REGISTER_WRITE Write; + /// + /// This function modifies zero or more registers in the Super I/O controller + /// using a table. + /// + EFI_PEI_SIO_REGISTER_MODIFY Modify; + /// + /// This GUID uniquely identifies the Super I/O controller. + /// + EFI_GUID SioGuid; + /// + /// This pointer is to an array which maps EISA identifiers to logical devices numbers. + /// + PEFI_SIO_INFO Info; +}; + +extern EFI_GUID gEfiSioPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamDone.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamDone.h new file mode 100644 index 0000000..65af8c0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamDone.h @@ -0,0 +1,52 @@ +/** @file + This file declares Temporary RAM Done PPI. + The PPI that provides a service to disable the use of Temporary RAM. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.2.1. + +**/ + +#ifndef __TEMPORARY_RAM_DONE_H__ +#define __TEMPORARY_RAM_DONE_H__ + +#define EFI_PEI_TEMPORARY_RAM_DONE_PPI_GUID \ + { 0xceab683c, 0xec56, 0x4a2d, { 0xa9, 0x6, 0x40, 0x53, 0xfa, 0x4e, 0x9c, 0x16 } } + +/** + TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked + by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed. + + @retval EFI_SUCCESS Use of Temporary RAM was disabled. + @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_PEI_TEMPORARY_RAM_DONE) ( + VOID + ); + +/// +/// This is an optional PPI that may be produced by SEC or a PEIM. If present, it provide a service to +/// disable the use of Temporary RAM. This service may only be called by the PEI Foundation after the +/// transition from Temporary RAM to Permanent RAM is complete. This PPI provides an alternative +/// to the Temporary RAM Migration PPI for system architectures that allow Temporary RAM and +/// Permanent RAM to be enabled and accessed at the same time with no side effects. +/// +typedef struct _EFI_PEI_TEMPORARY_RAM_DONE_PPI { + EFI_PEI_TEMPORARY_RAM_DONE TemporaryRamDone; +} EFI_PEI_TEMPORARY_RAM_DONE_PPI; + +extern EFI_GUID gEfiTemporaryRamDonePpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamSupport.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamSupport.h new file mode 100644 index 0000000..bbf5fd8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/TemporaryRamSupport.h @@ -0,0 +1,66 @@ +/** @file + This file declares Temporary RAM Support PPI. + This Ppi provides the service that migrates temporary RAM into permanent memory. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.0. + +**/ + +#ifndef __TEMPORARY_RAM_SUPPORT_H__ +#define __TEMPORARY_RAM_SUPPORT_H__ + +/// +/// Note: The GUID name EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI_GUID is different from the current +/// PI 1.2 spec. +/// +#define EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI_GUID \ + { 0xdbe23aa9, 0xa345, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} } + + +/** + This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param PeiServices Pointer to the PEI Services Table. + @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +typedef +EFI_STATUS +(EFIAPI * TEMPORARY_RAM_MIGRATION)( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize +); + +/// +/// This service abstracts the ability to migrate contents of the platform early memory store. +/// Note: The name EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI is different from the current PI 1.2 spec. +/// This PPI was optional. +/// +typedef struct { + TEMPORARY_RAM_MIGRATION TemporaryRamMigration; +} EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI; + +extern EFI_GUID gEfiTemporaryRamSupportPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/VectorHandoffInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/VectorHandoffInfo.h new file mode 100644 index 0000000..76ccc5e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Ppi/VectorHandoffInfo.h @@ -0,0 +1,75 @@ +/** @file + This file declares Vector Handoff Info PPI that describes an array of + interrupt and/or exception vectors that are in use and need to persist. + + This is an optional PPI that may be produced by SEC. If present, it provides + a description of the interrupt and/or exception vectors that were established + in the SEC Phase and need to persist into PEI and DXE. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is introduced in PI Version 1.2.1. + +**/ + +#ifndef __VECTOR_HANDOFF_INFO_H__ +#define __VECTOR_HANDOFF_INFO_H__ + +/// +/// NOTE: EFI_PEI_VECTOR_HANDOFF_INFO_PPI_GUID can also be used in the PEI Phase +/// to build a GUIDed HOB that contains an array of EFI_VECTOR_HANDOFF_INFO. +/// +#define EFI_PEI_VECTOR_HANDOFF_INFO_PPI_GUID \ + { 0x3cd652b4, 0x6d33, 0x4dce, { 0x89, 0xdb, 0x83, 0xdf, 0x97, 0x66, 0xfc, 0xca }} + +/// +/// Vector Handoff Info Attributes +///@{ +#define EFI_VECTOR_HANDOFF_DO_NOT_HOOK 0x00000000 +#define EFI_VECTOR_HANDOFF_HOOK_BEFORE 0x00000001 +#define EFI_VECTOR_HANDOFF_HOOK_AFTER 0x00000002 +#define EFI_VECTOR_HANDOFF_LAST_ENTRY 0x80000000 +///@} + +/// +/// EFI_VECTOR_HANDOFF_INFO entries that describes the interrupt and/or +/// exception vectors in use in the PEI Phase. +/// +typedef struct { + // + // The interrupt or exception vector that is in use and must be preserved. + // + UINT32 VectorNumber; + // + // A bitmask that describes the attributes ofthe interrupt or exception vector. + // + UINT32 Attribute; + // + // The GUID identifies the party who created the entry. For the + // EFI_VECTOR_HANDOFF_DO_NOT_HOOK case, this establishes the single owner. + // + EFI_GUID Owner; +} EFI_VECTOR_HANDOFF_INFO; + +/// +/// Provides a description of the interrupt and/or exception vectors that +/// were established in the SEC Phase and need to persist into PEI and DXE. +/// +typedef struct _EFI_PEI_VECTOR_HANDOFF_INFO_PPI { + // + // Pointer to an array of interrupt and /or exception vectors. + // + EFI_VECTOR_HANDOFF_INFO *Info; +} EFI_PEI_VECTOR_HANDOFF_INFO_PPI; + +extern EFI_GUID gEfiVectorHandoffInfoPpiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AbsolutePointer.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AbsolutePointer.h new file mode 100644 index 0000000..01b8d90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AbsolutePointer.h @@ -0,0 +1,208 @@ +/** @file + The file provides services that allow information about an + absolute pointer device to be retrieved. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.3. + +**/ + +#ifndef __ABSOLUTE_POINTER_H__ +#define __ABSOLUTE_POINTER_H__ + + +#define EFI_ABSOLUTE_POINTER_PROTOCOL_GUID \ + { 0x8D59D32B, 0xC655, 0x4AE9, { 0x9B, 0x15, 0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43 } } + + +typedef struct _EFI_ABSOLUTE_POINTER_PROTOCOL EFI_ABSOLUTE_POINTER_PROTOCOL; + + +//******************************************************* +// EFI_ABSOLUTE_POINTER_MODE +//******************************************************* + + +/** + The following data values in the EFI_ABSOLUTE_POINTER_MODE + interface are read-only and are changed by using the appropriate + interface functions. +**/ +typedef struct { + UINT64 AbsoluteMinX; ///< The Absolute Minimum of the device on the x-axis + UINT64 AbsoluteMinY; ///< The Absolute Minimum of the device on the y axis. + UINT64 AbsoluteMinZ; ///< The Absolute Minimum of the device on the z-axis + UINT64 AbsoluteMaxX; ///< The Absolute Maximum of the device on the x-axis. If 0, and the + ///< AbsoluteMinX is 0, then the pointer device does not support a xaxis + UINT64 AbsoluteMaxY; ///< The Absolute Maximum of the device on the y -axis. If 0, and the + ///< AbsoluteMinX is 0, then the pointer device does not support a yaxis. + UINT64 AbsoluteMaxZ; ///< The Absolute Maximum of the device on the z-axis. If 0 , and the + ///< AbsoluteMinX is 0, then the pointer device does not support a zaxis + UINT32 Attributes; ///< The following bits are set as needed (or'd together) to indicate the + ///< capabilities of the device supported. The remaining bits are undefined + ///< and should be 0 +} EFI_ABSOLUTE_POINTER_MODE; + +/// +/// If set, indicates this device supports an alternate button input. +/// +#define EFI_ABSP_SupportsAltActive 0x00000001 + +/// +/// If set, indicates this device returns pressure data in parameter CurrentZ. +/// +#define EFI_ABSP_SupportsPressureAsZ 0x00000002 + + +/** + This function resets the pointer device hardware. As part of + initialization process, the firmware/device will make a quick + but reasonable attempt to verify that the device is + functioning. If the ExtendedVerification flag is TRUE the + firmware may take an extended amount of time to verify the + device is operating on reset. Otherwise the reset operation is + to occur as quickly as possible. The hardware verification + process is not defined by this specification and is left up to + the platform firmware or driver to implement. + + @param This A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL + instance. + + @param ExtendedVerification Indicates that the driver may + perform a more exhaustive + verification operation of the + device during reset. + + @retval EFI_SUCCESS The device was reset. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ABSOLUTE_POINTER_RESET)( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + +/// +/// This bit is set if the touch sensor is active. +/// +#define EFI_ABSP_TouchActive 0x00000001 + +/// +/// This bit is set if the alt sensor, such as pen-side button, is active +/// +#define EFI_ABS_AltActive 0x00000002 + + +/** + Definition of EFI_ABSOLUTE_POINTER_STATE. +**/ +typedef struct { + /// + /// The unsigned position of the activation on the x axis. If the AboluteMinX + /// and the AboluteMaxX fields of the EFI_ABSOLUTE_POINTER_MODE structure are + /// both 0, then this pointer device does not support an x-axis, and this field + /// must be ignored. + /// + UINT64 CurrentX; + + /// + /// The unsigned position of the activation on the y axis. If the AboluteMinY + /// and the AboluteMaxY fields of the EFI_ABSOLUTE_POINTER_MODE structure are + /// both 0, then this pointer device does not support an y-axis, and this field + /// must be ignored. + /// + UINT64 CurrentY; + + /// + /// The unsigned position of the activation on the z axis, or the pressure + /// measurement. If the AboluteMinZ and the AboluteMaxZ fields of the + /// EFI_ABSOLUTE_POINTER_MODE structure are both 0, then this pointer device + /// does not support an z-axis, and this field must be ignored. + /// + UINT64 CurrentZ; + + /// + /// Bits are set to 1 in this structure item to indicate that device buttons are + /// active. + /// + UINT32 ActiveButtons; +} EFI_ABSOLUTE_POINTER_STATE; + +/** + The GetState() function retrieves the current state of a pointer + device. This includes information on the active state associated + with the pointer device and the current position of the axes + associated with the pointer device. If the state of the pointer + device has not changed since the last call to GetState(), then + EFI_NOT_READY is returned. If the state of the pointer device + has changed since the last call to GetState(), then the state + information is placed in State, and EFI_SUCCESS is returned. If + a device error occurs while attempting to retrieve the state + information, then EFI_DEVICE_ERROR is returned. + + + @param This A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL + instance. + + @param State A pointer to the state information on the + pointer device. + + @retval EFI_SUCCESS The state of the pointer device was + returned in State. + + @retval EFI_NOT_READY The state of the pointer device has not + changed since the last call to GetState(). + + @retval EFI_DEVICE_ERROR A device error occurred while + attempting to retrieve the pointer + device's current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ABSOLUTE_POINTER_GET_STATE)( + IN EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN OUT EFI_ABSOLUTE_POINTER_STATE *State +); + + +/// +/// The EFI_ABSOLUTE_POINTER_PROTOCOL provides a set of services +/// for a pointer device that can be used as an input device from an +/// application written to this specification. The services include +/// the ability to: reset the pointer device, retrieve the state of +/// the pointer device, and retrieve the capabilities of the pointer +/// device. The service also provides certain data items describing the device. +/// +struct _EFI_ABSOLUTE_POINTER_PROTOCOL { + EFI_ABSOLUTE_POINTER_RESET Reset; + EFI_ABSOLUTE_POINTER_GET_STATE GetState; + /// + /// Event to use with WaitForEvent() to wait for input from the pointer device. + /// + EFI_EVENT WaitForInput; + /// + /// Pointer to EFI_ABSOLUTE_POINTER_MODE data. + /// + EFI_ABSOLUTE_POINTER_MODE *Mode; +}; + + +extern EFI_GUID gEfiAbsolutePointerProtocolGuid; + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiSystemDescriptionTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiSystemDescriptionTable.h new file mode 100644 index 0000000..ad8668f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiSystemDescriptionTable.h @@ -0,0 +1,269 @@ +/** @file + This protocol provides services for creating ACPI system description tables. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.2. + +**/ + +#ifndef __ACPI_SYSTEM_DESCRIPTION_TABLE_H___ +#define __ACPI_SYSTEM_DESCRIPTION_TABLE_H___ + +#define EFI_ACPI_SDT_PROTOCOL_GUID \ + { 0xeb97088e, 0xcfdf, 0x49c6, { 0xbe, 0x4b, 0xd9, 0x6, 0xa5, 0xb2, 0xe, 0x86 }} + +typedef UINT32 EFI_ACPI_TABLE_VERSION; +typedef VOID *EFI_ACPI_HANDLE; + +#define EFI_ACPI_TABLE_VERSION_NONE (1 << 0) +#define EFI_ACPI_TABLE_VERSION_1_0B (1 << 1) +#define EFI_ACPI_TABLE_VERSION_2_0 (1 << 2) +#define EFI_ACPI_TABLE_VERSION_3_0 (1 << 3) +#define EFI_ACPI_TABLE_VERSION_4_0 (1 << 4) +#define EFI_ACPI_TABLE_VERSION_5_0 (1 << 5) + +typedef UINT32 EFI_ACPI_DATA_TYPE; +#define EFI_ACPI_DATA_TYPE_NONE 0 +#define EFI_ACPI_DATA_TYPE_OPCODE 1 +#define EFI_ACPI_DATA_TYPE_NAME_STRING 2 +#define EFI_ACPI_DATA_TYPE_OP 3 +#define EFI_ACPI_DATA_TYPE_UINT 4 +#define EFI_ACPI_DATA_TYPE_STRING 5 +#define EFI_ACPI_DATA_TYPE_CHILD 6 + +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + CHAR8 OemId[6]; + CHAR8 OemTableId[8]; + UINT32 OemRevision; + UINT32 CreatorId; + UINT32 CreatorRevision; +} EFI_ACPI_SDT_HEADER; + +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_NOTIFICATION_FN)( + IN EFI_ACPI_SDT_HEADER *Table, ///< A pointer to the ACPI table header. + IN EFI_ACPI_TABLE_VERSION Version, ///< The ACPI table's version. + IN UINTN TableKey ///< The table key for this ACPI table. +); + +/** + Returns a requested ACPI table. + + The GetAcpiTable() function returns a pointer to a buffer containing the ACPI table associated + with the Index that was input. The following structures are not considered elements in the list of + ACPI tables: + - Root System Description Pointer (RSD_PTR) + - Root System Description Table (RSDT) + - Extended System Description Table (XSDT) + Version is updated with a bit map containing all the versions of ACPI of which the table is a + member. For tables installed via the EFI_ACPI_TABLE_PROTOCOL.InstallAcpiTable() interface, + the function returns the value of EFI_ACPI_STD_PROTOCOL.AcpiVersion. + + @param[in] Index The zero-based index of the table to retrieve. + @param[out] Table Pointer for returning the table buffer. + @param[out] Version On return, updated with the ACPI versions to which this table belongs. Type + EFI_ACPI_TABLE_VERSION is defined in "Related Definitions" in the + EFI_ACPI_SDT_PROTOCOL. + @param[out] TableKey On return, points to the table key for the specified ACPI system definition table. + This is identical to the table key used in the EFI_ACPI_TABLE_PROTOCOL. + The TableKey can be passed to EFI_ACPI_TABLE_PROTOCOL.UninstallAcpiTable() + to uninstall the table. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The requested index is too large and a table was not found. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_GET_ACPI_TABLE2)( + IN UINTN Index, + OUT EFI_ACPI_SDT_HEADER **Table, + OUT EFI_ACPI_TABLE_VERSION *Version, + OUT UINTN *TableKey +); + +/** + Register or unregister a callback when an ACPI table is installed. + + This function registers or unregisters a function which will be called whenever a new ACPI table is + installed. + + @param[in] Register If TRUE, then the specified function will be registered. If FALSE, then the specified + function will be unregistered. + @param[in] Notification Points to the callback function to be registered or unregistered. + + @retval EFI_SUCCESS Callback successfully registered or unregistered. + @retval EFI_INVALID_PARAMETER Notification is NULL + @retval EFI_INVALID_PARAMETER Register is FALSE and Notification does not match a known registration function. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_REGISTER_NOTIFY)( + IN BOOLEAN Register, + IN EFI_ACPI_NOTIFICATION_FN Notification +); + +/** + Create a handle from an ACPI opcode + + @param[in] Buffer Points to the ACPI opcode. + @param[out] Handle Upon return, holds the handle. + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER Buffer is NULL or Handle is NULL or Buffer points to an + invalid opcode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_OPEN)( + IN VOID *Buffer, + OUT EFI_ACPI_HANDLE *Handle +); + +/** + Create a handle for the first ACPI opcode in an ACPI system description table. + + @param[in] TableKey The table key for the ACPI table, as returned by GetTable(). + @param[out] Handle On return, points to the newly created ACPI handle. + + @retval EFI_SUCCESS Handle created successfully. + @retval EFI_NOT_FOUND TableKey does not refer to a valid ACPI table. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_OPEN_SDT)( + IN UINTN TableKey, + OUT EFI_ACPI_HANDLE *Handle +); + +/** + Close an ACPI handle. + + @param[in] Handle Returns the handle. + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_CLOSE)( + IN EFI_ACPI_HANDLE Handle +); + +/** + Return the child ACPI objects. + + @param[in] ParentHandle Parent handle. + @param[in, out] Handle On entry, points to the previously returned handle or NULL to start with the first + handle. On return, points to the next returned ACPI handle or NULL if there are no + child objects. + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER ParentHandle is NULL or does not refer to a valid ACPI object. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_GET_CHILD)( + IN EFI_ACPI_HANDLE ParentHandle, + IN OUT EFI_ACPI_HANDLE *Handle +); + +/** + Retrieve information about an ACPI object. + + @param[in] Handle ACPI object handle. + @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right + in the ACPI encoding, with index 0 always being the ACPI opcode. + @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists + for the specified index. + @param[out] Data Upon return, points to the pointer to the data. + @param[out] DataSize Upon return, points to the size of Data. + + @retval +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_GET_OPTION)( + IN EFI_ACPI_HANDLE Handle, + IN UINTN Index, + OUT EFI_ACPI_DATA_TYPE *DataType, + OUT CONST VOID **Data, + OUT UINTN *DataSize +); + +/** + Change information about an ACPI object. + + @param[in] Handle ACPI object handle. + @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right + in the ACPI encoding, with index 0 always being the ACPI opcode. + @param[in] Data Points to the data. + @param[in] DataSize The size of the Data. + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER Handle is NULL or does not refer to a valid ACPI object. + @retval EFI_BAD_BUFFER_SIZE Data cannot be accommodated in the space occupied by + the option. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_SET_OPTION)( + IN EFI_ACPI_HANDLE Handle, + IN UINTN Index, + IN CONST VOID *Data, + IN UINTN DataSize +); + +/** + Returns the handle of the ACPI object representing the specified ACPI path + + @param[in] HandleIn Points to the handle of the object representing the starting point for the path search. + @param[in] AcpiPath Points to the ACPI path, which conforms to the ACPI encoded path format. + @param[out] HandleOut On return, points to the ACPI object which represents AcpiPath, relative to + HandleIn. + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER HandleIn is NULL or does not refer to a valid ACPI object. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_FIND_PATH)( + IN EFI_ACPI_HANDLE HandleIn, + IN VOID *AcpiPath, + OUT EFI_ACPI_HANDLE *HandleOut +); + +typedef struct _EFI_ACPI_SDT_PROTOCOL { + /// + /// A bit map containing all the ACPI versions supported by this protocol. + /// + EFI_ACPI_TABLE_VERSION AcpiVersion; + EFI_ACPI_GET_ACPI_TABLE2 GetAcpiTable; + EFI_ACPI_REGISTER_NOTIFY RegisterNotify; + EFI_ACPI_OPEN Open; + EFI_ACPI_OPEN_SDT OpenSdt; + EFI_ACPI_CLOSE Close; + EFI_ACPI_GET_CHILD GetChild; + EFI_ACPI_GET_OPTION GetOption; + EFI_ACPI_SET_OPTION SetOption; + EFI_ACPI_FIND_PATH FindPath; +} EFI_ACPI_SDT_PROTOCOL; + +extern EFI_GUID gEfiAcpiSdtProtocolGuid; + +#endif // __ACPI_SYSTEM_DESCRIPTION_TABLE_H___ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiTable.h new file mode 100644 index 0000000..d174439 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AcpiTable.h @@ -0,0 +1,130 @@ +/** @file + The file provides the protocol to install or remove an ACPI + table from a platform. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.3. + +**/ + +#ifndef __ACPI_TABLE_H___ +#define __ACPI_TABLE_H___ + +#define EFI_ACPI_TABLE_PROTOCOL_GUID \ + { 0xffe06bdd, 0x6107, 0x46a6, { 0x7b, 0xb2, 0x5a, 0x9c, 0x7e, 0xc5, 0x27, 0x5c }} + + +typedef struct _EFI_ACPI_TABLE_PROTOCOL EFI_ACPI_TABLE_PROTOCOL; + +/** + + The InstallAcpiTable() function allows a caller to install an + ACPI table. When successful, the table will be linked by the + RSDT/XSDT. AcpiTableBuffer specifies the table to be installed. + InstallAcpiTable() will make a copy of the table and insert the + copy into the RSDT/XSDT. InstallAcpiTable() must insert the new + table at the end of the RSDT/XSDT. To prevent namespace + collision, ACPI tables may be created using UEFI ACPI table + format. If this protocol is used to install a table with a + signature already present in the system, the new table will not + replace the existing table. It is a platform implementation + decision to add a new table with a signature matching an + existing table or disallow duplicate table signatures and + return EFI_ACCESS_DENIED. On successful output, TableKey is + initialized with a unique key. Its value may be used in a + subsequent call to UninstallAcpiTable to remove an ACPI table. + If an EFI application is running at the time of this call, the + relevant EFI_CONFIGURATION_TABLE pointer to the RSDT is no + longer considered valid. + + + @param This A pointer to a EFI_ACPI_TABLE_PROTOCOL. + + @param AcpiTableBuffer A pointer to a buffer containing the + ACPI table to be installed. + + @param AcpiTableBufferSize Specifies the size, in bytes, of + the AcpiTableBuffer buffer. + + + @param TableKey Returns a key to refer to the ACPI table. + + @retval EFI_SUCCESS The table was successfully inserted + + @retval EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, + TableKey is NULL, or + AcpiTableBufferSize and the size + field embedded in the ACPI table + pointed to by AcpiTableBuffer + are not in sync. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources exist to + complete the request. + @retval EFI_ACCESS_DENIED The table signature matches a table already + present in the system and platform policy + does not allow duplicate tables of this type. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_TABLE_INSTALL_ACPI_TABLE)( + IN EFI_ACPI_TABLE_PROTOCOL *This, + IN VOID *AcpiTableBuffer, + IN UINTN AcpiTableBufferSize, + OUT UINTN *TableKey +); + + +/** + + The UninstallAcpiTable() function allows a caller to remove an + ACPI table. The routine will remove its reference from the + RSDT/XSDT. A table is referenced by the TableKey parameter + returned from a prior call to InstallAcpiTable(). If an EFI + application is running at the time of this call, the relevant + EFI_CONFIGURATION_TABLE pointer to the RSDT is no longer + considered valid. + + @param This A pointer to a EFI_ACPI_TABLE_PROTOCOL. + + @param TableKey Specifies the table to uninstall. The key was + returned from InstallAcpiTable(). + + @retval EFI_SUCCESS The table was successfully inserted + + @retval EFI_NOT_FOUND TableKey does not refer to a valid key + for a table entry. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources exist to + complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE)( + IN EFI_ACPI_TABLE_PROTOCOL *This, + IN UINTN TableKey +); + +/// +/// The EFI_ACPI_TABLE_PROTOCOL provides the ability for a component +/// to install and uninstall ACPI tables from a platform. +/// +struct _EFI_ACPI_TABLE_PROTOCOL { + EFI_ACPI_TABLE_INSTALL_ACPI_TABLE InstallAcpiTable; + EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE UninstallAcpiTable; +}; + +extern EFI_GUID gEfiAcpiTableProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AdapterInformation.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AdapterInformation.h new file mode 100644 index 0000000..636c775 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AdapterInformation.h @@ -0,0 +1,260 @@ +/** @file + EFI Adapter Information Protocol definition. + The EFI Adapter Information Protocol is used to dynamically and quickly discover + or set device information for an adapter. + + Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.4 + +**/ + +#ifndef __EFI_ADAPTER_INFORMATION_PROTOCOL_H__ +#define __EFI_ADAPTER_INFORMATION_PROTOCOL_H__ + + +#define EFI_ADAPTER_INFORMATION_PROTOCOL_GUID \ + { \ + 0xE5DD1403, 0xD622, 0xC24E, {0x84, 0x88, 0xC7, 0x1B, 0x17, 0xF5, 0xE8, 0x02 } \ + } + +#define EFI_ADAPTER_INFO_MEDIA_STATE_GUID \ + { \ + 0xD7C74207, 0xA831, 0x4A26, {0xB1, 0xF5, 0xD1, 0x93, 0x06, 0x5C, 0xE8, 0xB6 } \ + } + +#define EFI_ADAPTER_INFO_NETWORK_BOOT_GUID \ + { \ + 0x1FBD2960, 0x4130, 0x41E5, {0x94, 0xAC, 0xD2, 0xCF, 0x03, 0x7F, 0xB3, 0x7C } \ + } + +#define EFI_ADAPTER_INFO_SAN_MAC_ADDRESS_GUID \ + { \ + 0x114da5ef, 0x2cf1, 0x4e12, {0x9b, 0xbb, 0xc4, 0x70, 0xb5, 0x52, 0x5, 0xd9 } \ + } + +#define EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT_GUID \ + { \ + 0x4bd56be3, 0x4975, 0x4d8a, {0xa0, 0xad, 0xc4, 0x91, 0x20, 0x4b, 0x5d, 0x4d} \ + } + +#define EFI_ADAPTER_INFO_MEDIA_TYPE_GUID \ + { \ + 0x8484472f, 0x71ec, 0x411a, { 0xb3, 0x9c, 0x62, 0xcd, 0x94, 0xd9, 0x91, 0x6e } \ + } + + +typedef struct _EFI_ADAPTER_INFORMATION_PROTOCOL EFI_ADAPTER_INFORMATION_PROTOCOL; + +/// +/// EFI_ADAPTER_INFO_MEDIA_STATE +/// +typedef struct { + /// + /// Returns the current media state status. MediaState can have any of the following values: + /// EFI_SUCCESS: There is media attached to the network adapter. EFI_NOT_READY: This detects a bounced state. + /// There was media attached to the network adapter, but it was removed and reattached. EFI_NO_MEDIA: There is + /// not any media attached to the network. + /// + EFI_STATUS MediaState; +} EFI_ADAPTER_INFO_MEDIA_STATE; + +/// +/// EFI_ADAPTER_INFO_MEDIA_TYPE +/// +typedef struct { + /// + /// Indicates the current media type. MediaType can have any of the following values: + /// 1: Ethernet Network Adapter + /// 2: Ethernet Wireless Network Adapter + /// 3~255: Reserved + /// + UINT8 MediaType; +} EFI_ADAPTER_INFO_MEDIA_TYPE; + +/// +/// EFI_ADAPTER_INFO_NETWORK_BOOT +/// +typedef struct { + /// + /// TRUE if the adapter supports booting from iSCSI IPv4 targets. + /// + BOOLEAN iScsiIpv4BootCapablity; + /// + /// TRUE if the adapter supports booting from iSCSI IPv6 targets. + /// + BOOLEAN iScsiIpv6BootCapablity; + /// + /// TRUE if the adapter supports booting from FCoE targets. + /// + BOOLEAN FCoeBootCapablity; + /// + /// TRUE if the adapter supports an offload engine (such as TCP + /// Offload Engine (TOE)) for its iSCSI or FCoE boot operations. + /// + BOOLEAN OffloadCapability; + /// + /// TRUE if the adapter supports multipath I/O (MPIO) for its iSCSI + /// boot operations. + /// + BOOLEAN iScsiMpioCapability; + /// + /// TRUE if the adapter is currently configured to boot from iSCSI + /// IPv4 targets. + /// + BOOLEAN iScsiIpv4Boot; + /// + /// TRUE if the adapter is currently configured to boot from iSCSI + /// IPv6 targets. + /// + BOOLEAN iScsiIpv6Boot; + /// + /// TRUE if the adapter is currently configured to boot from FCoE targets. + /// + BOOLEAN FCoeBoot; +} EFI_ADAPTER_INFO_NETWORK_BOOT; + +/// +/// EFI_ADAPTER_INFO_SAN_MAC_ADDRESS +/// +typedef struct { + /// + /// Returns the SAN MAC address for the adapter.For adapters that support today's 802.3 ethernet + /// networking and Fibre-Channel Over Ethernet (FCOE), this conveys the FCOE SAN MAC address from the adapter. + /// + EFI_MAC_ADDRESS SanMacAddress; +} EFI_ADAPTER_INFO_SAN_MAC_ADDRESS; + +/// +/// EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT +/// +typedef struct { + /// + /// Returns capability of UNDI to support IPv6 traffic. + /// + BOOLEAN Ipv6Support; +} EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT; + +/** + 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] InforamtionBlock The service returns a pointer to the buffer with the InformationBlock + structure which contains details about the data specific to InformationType. + @param[out] InforamtionBlockSize 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADAPTER_INFO_GET_INFO)( + IN EFI_ADAPTER_INFORMATION_PROTOCOL *This, + IN EFI_GUID *InformationType, + OUT VOID **InformationBlock, + OUT UINTN *InformationBlockSize + ); + +/** + 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] InforamtionBlock A pointer to the InformationBlock structure which contains details + about the data specific to InformationType. + @param[in] InforamtionBlockSize 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(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADAPTER_INFO_SET_INFO)( + IN EFI_ADAPTER_INFORMATION_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN VOID *InformationBlock, + IN UINTN InformationBlockSize + ); + +/** + 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADAPTER_INFO_GET_SUPPORTED_TYPES)( + IN EFI_ADAPTER_INFORMATION_PROTOCOL *This, + OUT EFI_GUID **InfoTypesBuffer, + OUT UINTN *InfoTypesBufferCount + ); + +/// +/// EFI_ADAPTER_INFORMATION_PROTOCOL +/// The protocol for adapter provides the following services. +/// - Gets device state information from adapter. +/// - Sets device information for adapter. +/// - Gets a list of supported information types for this instance of the protocol. +/// +struct _EFI_ADAPTER_INFORMATION_PROTOCOL { + EFI_ADAPTER_INFO_GET_INFO GetInformation; + EFI_ADAPTER_INFO_SET_INFO SetInformation; + EFI_ADAPTER_INFO_GET_SUPPORTED_TYPES GetSupportedTypes; +}; + +extern EFI_GUID gEfiAdapterInformationProtocolGuid; + +extern EFI_GUID gEfiAdapterInfoMediaStateGuid; + +extern EFI_GUID gEfiAdapterInfoNetworkBootGuid; + +extern EFI_GUID gEfiAdapterInfoSanMacAddressGuid; + +extern EFI_GUID gEfiAdapterInfoUndiIpv6SupportGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Arp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Arp.h new file mode 100644 index 0000000..cc53bc6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Arp.h @@ -0,0 +1,385 @@ +/** @file + EFI ARP Protocol Definition + + The EFI ARP Service Binding Protocol is used to locate EFI + ARP Protocol drivers to create and destroy child of the + driver to communicate with other host using ARP protocol. + The EFI ARP Protocol provides services to map IP network + address to hardware address used by a data link protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.0. + +**/ + +#ifndef __EFI_ARP_PROTOCOL_H__ +#define __EFI_ARP_PROTOCOL_H__ + +#define EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xf44c00ee, 0x1f2c, 0x4a00, {0xaa, 0x9, 0x1c, 0x9f, 0x3e, 0x8, 0x0, 0xa3 } \ + } + +#define EFI_ARP_PROTOCOL_GUID \ + { \ + 0xf4b427bb, 0xba21, 0x4f16, {0xbc, 0x4e, 0x43, 0xe4, 0x16, 0xab, 0x61, 0x9c } \ + } + +typedef struct _EFI_ARP_PROTOCOL EFI_ARP_PROTOCOL; + +typedef struct { + /// + /// Length in bytes of this entry. + /// + UINT32 Size; + + /// + /// Set to TRUE if this entry is a "deny" entry. + /// Set to FALSE if this entry is a "normal" entry. + /// + BOOLEAN DenyFlag; + + /// + /// Set to TRUE if this entry will not time out. + /// Set to FALSE if this entry will time out. + /// + BOOLEAN StaticFlag; + + /// + /// 16-bit ARP hardware identifier number. + /// + UINT16 HwAddressType; + + /// + /// 16-bit protocol type number. + /// + UINT16 SwAddressType; + + /// + /// The length of the hardware address. + /// + UINT8 HwAddressLength; + + /// + /// The length of the protocol address. + /// + UINT8 SwAddressLength; +} EFI_ARP_FIND_DATA; + +typedef struct { + /// + /// 16-bit protocol type number in host byte order. + /// + UINT16 SwAddressType; + + /// + /// The length in bytes of the station's protocol address to register. + /// + UINT8 SwAddressLength; + + /// + /// The pointer to the first byte of the protocol address to register. For + /// example, if SwAddressType is 0x0800 (IP), then + /// StationAddress points to the first byte of this station's IP + /// address stored in network byte order. + /// + VOID *StationAddress; + + /// + /// The timeout value in 100-ns units that is associated with each + /// new dynamic ARP cache entry. If it is set to zero, the value is + /// implementation-specific. + /// + UINT32 EntryTimeOut; + + /// + /// The number of retries before a MAC address is resolved. If it is + /// set to zero, the value is implementation-specific. + /// + UINT32 RetryCount; + + /// + /// The timeout value in 100-ns units that is used to wait for the ARP + /// reply packet or the timeout value between two retries. Set to zero + /// to use implementation-specific value. + /// + UINT32 RetryTimeOut; +} EFI_ARP_CONFIG_DATA; + + +/** + This function is used to assign a station address to the ARP cache for this instance + of the ARP driver. + + Each ARP instance has one station address. The EFI_ARP_PROTOCOL driver will + respond to ARP requests that match this registered station address. A call to + this function with the ConfigData field set to NULL will reset this ARP instance. + + Once a protocol type and station address have been assigned to this ARP instance, + all the following ARP functions will use this information. Attempting to change + the protocol type or station address to a configured ARP instance will result in errors. + + @param This The pointer to the EFI_ARP_PROTOCOL instance. + @param ConfigData The pointer to the EFI_ARP_CONFIG_DATA structure. + + @retval EFI_SUCCESS The new station address was successfully + registered. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + * This is NULL. + * SwAddressLength is zero when ConfigData is not NULL. + * StationAddress is NULL when ConfigData is not NULL. + @retval EFI_ACCESS_DENIED The SwAddressType, SwAddressLength, or + StationAddress is different from the one that is + already registered. + @retval EFI_OUT_OF_RESOURCES Storage for the new StationAddress could not be + allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_CONFIGURE)( + IN EFI_ARP_PROTOCOL *This, + IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL + ); + +/** + This function is used to insert entries into the ARP cache. + + ARP cache entries are typically inserted and updated by network protocol drivers + as network traffic is processed. Most ARP cache entries will time out and be + deleted if the network traffic stops. ARP cache entries that were inserted + by the Add() function may be static (will not time out) or dynamic (will time out). + Default ARP cache timeout values are not covered in most network protocol + specifications (although RFC 1122 comes pretty close) and will only be + discussed in general terms in this specification. The timeout values that are + used in the EFI Sample Implementation should be used only as a guideline. + Final product implementations of the EFI network stack should be tuned for + their expected network environments. + + @param This Pointer to the EFI_ARP_PROTOCOL instance. + @param DenyFlag Set to TRUE if this entry is a deny entry. Set to + FALSE if this entry is a normal entry. + @param TargetSwAddress Pointer to a protocol address to add (or deny). + May be set to NULL if DenyFlag is TRUE. + @param TargetHwAddress Pointer to a hardware address to add (or deny). + May be set to NULL if DenyFlag is TRUE. + @param TimeoutValue Time in 100-ns units that this entry will remain + in the ARP cache. A value of zero means that the + entry is permanent. A nonzero value will override + the one given by Configure() if the entry to be + added is a dynamic entry. + @param Overwrite If TRUE, the matching cache entry will be + overwritten with the supplied parameters. If + FALSE, EFI_ACCESS_DENIED is returned if the + corresponding cache entry already exists. + + @retval EFI_SUCCESS The entry has been added or updated. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + * This is NULL. + * DenyFlag is FALSE and TargetHwAddress is NULL. + * DenyFlag is FALSE and TargetSwAddress is NULL. + * TargetHwAddress is NULL and TargetSwAddress is NULL. + * Neither TargetSwAddress nor TargetHwAddress are NULL when DenyFlag is + TRUE. + @retval EFI_OUT_OF_RESOURCES The new ARP cache entry could not be allocated. + @retval EFI_ACCESS_DENIED The ARP cache entry already exists and Overwrite + is not true. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_ADD)( + IN EFI_ARP_PROTOCOL *This, + IN BOOLEAN DenyFlag, + IN VOID *TargetSwAddress OPTIONAL, + IN VOID *TargetHwAddress OPTIONAL, + IN UINT32 TimeoutValue, + IN BOOLEAN Overwrite + ); + +/** + This function searches the ARP cache for matching entries and allocates a buffer into + which those entries are copied. + + The first part of the allocated buffer is EFI_ARP_FIND_DATA, following which + are protocol address pairs and hardware address pairs. + When finding a specific protocol address (BySwAddress is TRUE and AddressBuffer + is not NULL), the ARP cache timeout for the found entry is reset if Refresh is + set to TRUE. If the found ARP cache entry is a permanent entry, it is not + affected by Refresh. + + @param This The pointer to the EFI_ARP_PROTOCOL instance. + @param BySwAddress Set to TRUE to look for matching software protocol + addresses. Set to FALSE to look for matching + hardware protocol addresses. + @param AddressBuffer The pointer to the address buffer. Set to NULL + to match all addresses. + @param EntryLength The size of an entry in the entries buffer. + @param EntryCount The number of ARP cache entries that are found by + the specified criteria. + @param Entries The pointer to the buffer that will receive the ARP + cache entries. + @param Refresh Set to TRUE to refresh the timeout value of the + matching ARP cache entry. + + @retval EFI_SUCCESS The requested ARP cache entries were copied into + the buffer. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. Both EntryCount and EntryLength are + NULL, when Refresh is FALSE. + @retval EFI_NOT_FOUND No matching entries were found. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_FIND)( + IN EFI_ARP_PROTOCOL *This, + IN BOOLEAN BySwAddress, + IN VOID *AddressBuffer OPTIONAL, + OUT UINT32 *EntryLength OPTIONAL, + OUT UINT32 *EntryCount OPTIONAL, + OUT EFI_ARP_FIND_DATA **Entries OPTIONAL, + IN BOOLEAN Refresh + ); + + +/** + This function removes specified ARP cache entries. + + @param This The pointer to the EFI_ARP_PROTOCOL instance. + @param BySwAddress Set to TRUE to delete matching protocol addresses. + Set to FALSE to delete matching hardware + addresses. + @param AddressBuffer The pointer to the address buffer that is used as a + key to look for the cache entry. Set to NULL to + delete all entries. + + @retval EFI_SUCCESS The entry was removed from the ARP cache. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND The specified deletion key was not found. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_DELETE)( + IN EFI_ARP_PROTOCOL *This, + IN BOOLEAN BySwAddress, + IN VOID *AddressBuffer OPTIONAL + ); + +/** + This function delete all dynamic entries from the ARP cache that match the specified + software protocol type. + + @param This The pointer to the EFI_ARP_PROTOCOL instance. + + @retval EFI_SUCCESS The cache has been flushed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND There are no matching dynamic cache entries. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_FLUSH)( + IN EFI_ARP_PROTOCOL *This + ); + +/** + This function tries to resolve the TargetSwAddress and optionally returns a + TargetHwAddress if it already exists in the ARP cache. + + @param This The pointer to the EFI_ARP_PROTOCOL instance. + @param TargetSwAddress The pointer to the protocol address to resolve. + @param ResolvedEvent The pointer to the event that will be signaled when + the address is resolved or some error occurs. + @param TargetHwAddress The pointer to the buffer for the resolved hardware + address in network byte order. + + @retval EFI_SUCCESS The data is copied from the ARP cache into the + TargetHwAddress buffer. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. TargetHwAddress is NULL. + @retval EFI_ACCESS_DENIED The requested address is not present in the normal + ARP cache but is present in the deny address list. + Outgoing traffic to that address is forbidden. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + @retval EFI_NOT_READY The request has been started and is not finished. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_REQUEST)( + IN EFI_ARP_PROTOCOL *This, + IN VOID *TargetSwAddress OPTIONAL, + IN EFI_EVENT ResolvedEvent OPTIONAL, + OUT VOID *TargetHwAddress + ); + +/** + This function aborts the previous ARP request (identified by This, TargetSwAddress + and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request(). + + If the request is in the internal ARP request queue, the request is aborted + immediately and its ResolvedEvent is signaled. Only an asynchronous address + request needs to be canceled. If TargeSwAddress and ResolveEvent are both + NULL, all the pending asynchronous requests that have been issued by This + instance will be cancelled and their corresponding events will be signaled. + + @param This The pointer to the EFI_ARP_PROTOCOL instance. + @param TargetSwAddress The pointer to the protocol address in previous + request session. + @param ResolvedEvent Pointer to the event that is used as the + notification event in previous request session. + + @retval EFI_SUCCESS The pending request session(s) is/are aborted and + corresponding event(s) is/are signaled. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. TargetSwAddress is not NULL and + ResolvedEvent is NULL. TargetSwAddress is NULL and + ResolvedEvent is not NULL. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + @retval EFI_NOT_FOUND The request is not issued by + EFI_ARP_PROTOCOL.Request(). + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_CANCEL)( + IN EFI_ARP_PROTOCOL *This, + IN VOID *TargetSwAddress OPTIONAL, + IN EFI_EVENT ResolvedEvent OPTIONAL + ); + +/// +/// ARP is used to resolve local network protocol addresses into +/// network hardware addresses. +/// +struct _EFI_ARP_PROTOCOL { + EFI_ARP_CONFIGURE Configure; + EFI_ARP_ADD Add; + EFI_ARP_FIND Find; + EFI_ARP_DELETE Delete; + EFI_ARP_FLUSH Flush; + EFI_ARP_REQUEST Request; + EFI_ARP_CANCEL Cancel; +}; + + +extern EFI_GUID gEfiArpServiceBindingProtocolGuid; +extern EFI_GUID gEfiArpProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AtaPassThru.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AtaPassThru.h new file mode 100644 index 0000000..b3be920 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AtaPassThru.h @@ -0,0 +1,474 @@ +/** @file + The EFI_ATA_PASS_THRU_PROTOCOL provides information about an ATA controller and the ability + to send ATA Command Blocks to any ATA device attached to that ATA controller. The information + includes the attributes of the ATA controller. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.3. + +**/ + +#ifndef __ATA_PASS_THROUGH_H__ +#define __ATA_PASS_THROUGH_H__ + +#define EFI_ATA_PASS_THRU_PROTOCOL_GUID \ + { \ + 0x1d3de7f0, 0x807, 0x424f, {0xaa, 0x69, 0x11, 0xa5, 0x4e, 0x19, 0xa4, 0x6f } \ + } + +typedef struct _EFI_ATA_PASS_THRU_PROTOCOL EFI_ATA_PASS_THRU_PROTOCOL; + +typedef struct { + UINT32 Attributes; + UINT32 IoAlign; +} EFI_ATA_PASS_THRU_MODE; + +/// +/// If this bit is set, then the EFI_ATA_PASS_THRU_PROTOCOL interface is for physical +/// devices on the ATA controller. +/// +#define EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001 +/// +/// If this bit is set, then the EFI_ATA_PASS_THRU_PROTOCOL interface is for logical +/// devices on the ATA controller. +/// +#define EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002 +/// +/// If this bit is set, then the EFI_ATA_PASS_THRU_PROTOCOL interface supports non blocking +/// I/O. Every EFI_ATA_PASS_THRU_PROTOCOL must support blocking I/O. The support of non-blocking +/// I/O is optional. +/// +#define EFI_ATA_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004 + +typedef struct _EFI_ATA_COMMAND_BLOCK { + UINT8 Reserved1[2]; + UINT8 AtaCommand; + UINT8 AtaFeatures; + UINT8 AtaSectorNumber; + UINT8 AtaCylinderLow; + UINT8 AtaCylinderHigh; + UINT8 AtaDeviceHead; + UINT8 AtaSectorNumberExp; + UINT8 AtaCylinderLowExp; + UINT8 AtaCylinderHighExp; + UINT8 AtaFeaturesExp; + UINT8 AtaSectorCount; + UINT8 AtaSectorCountExp; + UINT8 Reserved2[6]; +} EFI_ATA_COMMAND_BLOCK; + +typedef struct _EFI_ATA_STATUS_BLOCK { + UINT8 Reserved1[2]; + UINT8 AtaStatus; + UINT8 AtaError; + UINT8 AtaSectorNumber; + UINT8 AtaCylinderLow; + UINT8 AtaCylinderHigh; + UINT8 AtaDeviceHead; + UINT8 AtaSectorNumberExp; + UINT8 AtaCylinderLowExp; + UINT8 AtaCylinderHighExp; + UINT8 Reserved2; + UINT8 AtaSectorCount; + UINT8 AtaSectorCountExp; + UINT8 Reserved3[6]; +} EFI_ATA_STATUS_BLOCK; + +typedef UINT8 EFI_ATA_PASS_THRU_CMD_PROTOCOL; + +#define EFI_ATA_PASS_THRU_PROTOCOL_ATA_HARDWARE_RESET 0x00 +#define EFI_ATA_PASS_THRU_PROTOCOL_ATA_SOFTWARE_RESET 0x01 +#define EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA 0x02 +#define EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN 0x04 +#define EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT 0x05 +#define EFI_ATA_PASS_THRU_PROTOCOL_DMA 0x06 +#define EFI_ATA_PASS_THRU_PROTOCOL_DMA_QUEUED 0x07 +#define EFI_ATA_PASS_THRU_PROTOCOL_DEVICE_DIAGNOSTIC 0x08 +#define EFI_ATA_PASS_THRU_PROTOCOL_DEVICE_RESET 0x09 +#define EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN 0x0A +#define EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT 0x0B +#define EFI_ATA_PASS_THRU_PROTOCOL_FPDMA 0x0C +#define EFI_ATA_PASS_THRU_PROTOCOL_RETURN_RESPONSE 0xFF + +typedef UINT8 EFI_ATA_PASS_THRU_LENGTH; + +#define EFI_ATA_PASS_THRU_LENGTH_BYTES 0x80 + + +#define EFI_ATA_PASS_THRU_LENGTH_MASK 0x70 +#define EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER 0x00 +#define EFI_ATA_PASS_THRU_LENGTH_FEATURES 0x10 +#define EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT 0x20 +#define EFI_ATA_PASS_THRU_LENGTH_TPSIU 0x30 + +#define EFI_ATA_PASS_THRU_LENGTH_COUNT 0x0F + +typedef struct { + /// + /// A pointer to the sense data that was generated by the execution of the ATA + /// command. It must be aligned to the boundary specified in the IoAlign field + /// in the EFI_ATA_PASS_THRU_MODE structure. + /// + EFI_ATA_STATUS_BLOCK *Asb; + /// + /// A pointer to buffer that contains the Command Data Block to send to the ATA + /// device specified by Port and PortMultiplierPort. + /// + EFI_ATA_COMMAND_BLOCK *Acb; + /// + /// The timeout, in 100 ns units, to use for the execution of this ATA command. + /// A Timeout value of 0 means that this function will wait indefinitely for the + /// ATA command to execute. If Timeout is greater than zero, then this function + /// will return EFI_TIMEOUT if the time required to execute the ATA command is + /// greater than Timeout. + /// + UINT64 Timeout; + /// + /// A pointer to the data buffer to transfer between the ATA controller and the + /// ATA device for read and bidirectional commands. For all write and non data + /// commands where InTransferLength is 0 this field is optional and may be NULL. + /// If this field is not NULL, then it must be aligned on the boundary specified + /// by the IoAlign field in the EFI_ATA_PASS_THRU_MODE structure. + /// + VOID *InDataBuffer; + /// + /// A pointer to the data buffer to transfer between the ATA controller and the + /// ATA device for write or bidirectional commands. For all read and non data + /// commands where OutTransferLength is 0 this field is optional and may be NULL. + /// If this field is not NULL, then it must be aligned on the boundary specified + /// by the IoAlign field in the EFI_ATA_PASS_THRU_MODE structure. + /// + VOID *OutDataBuffer; + /// + /// On input, the size, in bytes, of InDataBuffer. On output, the number of bytes + /// transferred between the ATA controller and the ATA device. If InTransferLength + /// is larger than the ATA controller can handle, no data will be transferred, + /// InTransferLength will be updated to contain the number of bytes that the ATA + /// controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned. + /// + UINT32 InTransferLength; + /// + /// On Input, the size, in bytes of OutDataBuffer. On Output, the Number of bytes + /// transferred between ATA Controller and the ATA device. If OutTransferLength is + /// larger than the ATA controller can handle, no data will be transferred, + /// OutTransferLength will be updated to contain the number of bytes that the ATA + /// controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned. + /// + UINT32 OutTransferLength; + /// + /// Specifies the protocol used when the ATA device executes the command. + /// + EFI_ATA_PASS_THRU_CMD_PROTOCOL Protocol; + /// + /// Specifies the way in which the ATA command length is encoded. + /// + EFI_ATA_PASS_THRU_LENGTH Length; +} EFI_ATA_PASS_THRU_COMMAND_PACKET; + + +/** + Sends an ATA command to an ATA device that is attached to the ATA controller. This function + supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, + and the non-blocking I/O functionality is optional. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in] Port The port number of the ATA device to send the command. + @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command. + If there is no port multiplier, then specify 0xFFFF. + @param[in,out] Packet A pointer to the ATA command to send to the ATA device specified by Port + and PortMultiplierPort. + @param[in] Event If non-blocking I/O is not supported 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 ATA command completes. + + @retval EFI_SUCCESS The ATA command was sent by the host. For bi-directional commands, + InTransferLength bytes were transferred from InDataBuffer. For write and + bi-directional commands, OutTransferLength bytes were transferred by OutDataBuffer. + @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number of bytes that could be transferred + is returned in InTransferLength. For write and bi-directional commands, + OutTransferLength bytes were transferred by OutDataBuffer. + @retval EFI_NOT_READY The ATA command could not be sent because there are too many ATA commands + already queued. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the ATA command. + @retval EFI_INVALID_PARAMETER Port, PortMultiplierPort, or the contents of Acb are invalid. The ATA + command was not sent, so no additional status information is available. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_PASSTHRU)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ); + +/** + Used to retrieve the list of legal port numbers for ATA devices on an ATA controller. + These can either be the list of ports where ATA devices are actually present or the + list of legal port numbers for the ATA controller. Regardless, the caller of this + function must probe the port number returned to see if an ATA device is actually + present at that location on the ATA controller. + + The GetNextPort() function retrieves the port number on an ATA controller. If on input + Port is 0xFFFF, then the port number of the first port on the ATA controller is returned + in Port and EFI_SUCCESS is returned. + + If Port is a port number that was returned on a previous call to GetNextPort(), then the + port number of the next port on the ATA controller is returned in Port, and EFI_SUCCESS + is returned. If Port is not 0xFFFF and Port was not returned on a previous call to + GetNextPort(), then EFI_INVALID_PARAMETER is returned. + + If Port is the port number of the last port on the ATA controller, then EFI_NOT_FOUND is + returned. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in,out] Port On input, a pointer to the port number on the ATA controller. + On output, a pointer to the next port number on the ATA + controller. An input value of 0xFFFF retrieves the first port + number on the ATA controller. + + @retval EFI_SUCCESS The next port number on the ATA controller was returned in Port. + @retval EFI_NOT_FOUND There are no more ports on this ATA controller. + @retval EFI_INVALID_PARAMETER Port is not 0xFFFF and Port was not returned on a previous call + to GetNextPort(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_GET_NEXT_PORT)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN OUT UINT16 *Port + ); + +/** + Used to retrieve the list of legal port multiplier port numbers for ATA devices on a port of an ATA + controller. These can either be the list of port multiplier ports where ATA devices are actually + present on port or the list of legal port multiplier ports on that port. Regardless, the caller of this + function must probe the port number and port multiplier port number returned to see if an ATA + device is actually present. + + The GetNextDevice() function retrieves the port multiplier port number of an ATA device + present on a port of an ATA controller. + + If PortMultiplierPort points to a port multiplier port number value that was returned on a + previous call to GetNextDevice(), then the port multiplier port number of the next ATA device + on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is + returned. + + If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first + ATA device on port of the ATA controller is returned in PortMultiplierPort and + EFI_SUCCESS is returned. + + If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort + was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER + is returned. + + If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of + the ATA controller, then EFI_NOT_FOUND is returned. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in] Port The port number present on the ATA controller. + @param[in,out] PortMultiplierPort On input, a pointer to the port multiplier port number of an + ATA device present on the ATA controller. + If on input a PortMultiplierPort of 0xFFFF is specified, + then the port multiplier port number of the first ATA device + is returned. On output, a pointer to the port multiplier port + number of the next ATA device present on an ATA controller. + + @retval EFI_SUCCESS The port multiplier port number of the next ATA device on the port + of the ATA controller was returned in PortMultiplierPort. + @retval EFI_NOT_FOUND There are no more ATA devices on this port of the ATA controller. + @retval EFI_INVALID_PARAMETER PortMultiplierPort is not 0xFFFF, and PortMultiplierPort was not + returned on a previous call to GetNextDevice(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_GET_NEXT_DEVICE)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN UINT16 Port, + IN OUT UINT16 *PortMultiplierPort + ); + +/** + Used to allocate and build a device path node for an ATA device on an ATA controller. + + The BuildDevicePath() function allocates and builds a single device node for the ATA + device specified by Port and PortMultiplierPort. If the ATA device specified by Port and + PortMultiplierPort is not present on the ATA controller, then EFI_NOT_FOUND is returned. + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. If there are not enough + resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned. + + Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of + DevicePath are initialized to describe the ATA device specified by Port and PortMultiplierPort, + and EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in] Port Port specifies the port number of the ATA device for which a + device path node is to be allocated and built. + @param[in] PortMultiplierPort The port multiplier port number of the ATA device for which a + device path node is to be allocated and built. If there is no + port multiplier, then specify 0xFFFF. + @param[in,out] DevicePath A pointer to a single device path node that describes the ATA + device specified by Port and PortMultiplierPort. This function + is responsible for allocating the buffer DevicePath with the + boot service AllocatePool(). It is the caller's responsibility + to free DevicePath when the caller is finished with DevicePath. + @retval EFI_SUCCESS The device path node that describes the ATA device specified by + Port and PortMultiplierPort was allocated and returned in DevicePath. + @retval EFI_NOT_FOUND The ATA device specified by Port and PortMultiplierPort does not + exist on the ATA controller. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_BUILD_DEVICE_PATH)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN UINT16 Port, + IN UINT16 PortMultiplierPort, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Used to translate a device path node to a port number and port multiplier port number. + + The GetDevice() function determines the port and port multiplier port number associated with + the ATA device described by DevicePath. If DevicePath is a device path node type that the + ATA Pass Thru driver supports, then the ATA Pass Thru driver will attempt to translate the contents + DevicePath into a port number and port multiplier port number. + + If this translation is successful, then that port number and port multiplier port number are returned + in Port and PortMultiplierPort, and EFI_SUCCESS is returned. + + If DevicePath, Port, or PortMultiplierPort are NULL, then EFI_INVALID_PARAMETER is returned. + + If DevicePath is not a device path node type that the ATA Pass Thru driver supports, then + EFI_UNSUPPORTED is returned. + + If DevicePath is a device path node type that the ATA Pass Thru driver supports, but there is not + a valid translation from DevicePath to a port number and port multiplier port number, then + EFI_NOT_FOUND is returned. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in] DevicePath A pointer to the device path node that describes an ATA device on the + ATA controller. + @param[out] Port On return, points to the port number of an ATA device on the ATA controller. + @param[out] PortMultiplierPort On return, points to the port multiplier port number of an ATA device + on the ATA controller. + + @retval EFI_SUCCESS DevicePath was successfully translated to a port number and port multiplier + port number, and they were returned in Port and PortMultiplierPort. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER Port is NULL. + @retval EFI_INVALID_PARAMETER PortMultiplierPort is NULL. + @retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath. + @retval EFI_NOT_FOUND A valid translation from DevicePath to a port number and port multiplier + port number does not exist. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_GET_DEVICE)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT16 *Port, + OUT UINT16 *PortMultiplierPort + ); + +/** + Resets a specific port on the ATA controller. This operation also resets all the ATA devices + connected to the port. + + The ResetChannel() function resets an a specific port on an ATA controller. This operation + resets all the ATA devices connected to that port. If this ATA controller does not support + a reset port operation, then EFI_UNSUPPORTED is returned. + + If a device error occurs while executing that port reset operation, then EFI_DEVICE_ERROR is + returned. + + If a timeout occurs during the execution of the port reset operation, then EFI_TIMEOUT is returned. + + If the port reset operation is completed, then EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in] Port The port number on the ATA controller. + + @retval EFI_SUCCESS The ATA controller port was reset. + @retval EFI_UNSUPPORTED The ATA controller does not support a port reset operation. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the ATA port. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset the ATA port. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_RESET_PORT)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN UINT16 Port + ); + +/** + Resets an ATA device that is connected to an ATA controller. + + The ResetDevice() function resets the ATA device specified by Port and PortMultiplierPort. + If this ATA controller does not support a device reset operation, then EFI_UNSUPPORTED is + returned. + + If Port or PortMultiplierPort are not in a valid range for this ATA controller, then + EFI_INVALID_PARAMETER is returned. + + If a device error occurs while executing that device reset operation, then EFI_DEVICE_ERROR + is returned. + + If a timeout occurs during the execution of the device reset operation, then EFI_TIMEOUT is + returned. + + If the device reset operation is completed, then EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance. + @param[in] Port Port represents the port number of the ATA device to be reset. + @param[in] PortMultiplierPort The port multiplier port number of the ATA device to reset. + If there is no port multiplier, then specify 0xFFFF. + @retval EFI_SUCCESS The ATA device specified by Port and PortMultiplierPort was reset. + @retval EFI_UNSUPPORTED The ATA controller does not support a device reset operation. + @retval EFI_INVALID_PARAMETER Port or PortMultiplierPort are invalid. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the ATA device + specified by Port and PortMultiplierPort. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset the ATA device + specified by Port and PortMultiplierPort. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ATA_PASS_THRU_RESET_DEVICE)( + IN EFI_ATA_PASS_THRU_PROTOCOL *This, + IN UINT16 Port, + IN UINT16 PortMultiplierPort + ); + +struct _EFI_ATA_PASS_THRU_PROTOCOL { + EFI_ATA_PASS_THRU_MODE *Mode; + EFI_ATA_PASS_THRU_PASSTHRU PassThru; + EFI_ATA_PASS_THRU_GET_NEXT_PORT GetNextPort; + EFI_ATA_PASS_THRU_GET_NEXT_DEVICE GetNextDevice; + EFI_ATA_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_ATA_PASS_THRU_GET_DEVICE GetDevice; + EFI_ATA_PASS_THRU_RESET_PORT ResetPort; + EFI_ATA_PASS_THRU_RESET_DEVICE ResetDevice; +}; + +extern EFI_GUID gEfiAtaPassThruProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AuthenticationInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AuthenticationInfo.h new file mode 100644 index 0000000..72fc6d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/AuthenticationInfo.h @@ -0,0 +1,237 @@ +/** @file + EFI_AUTHENTICATION_INFO_PROTOCOL as defined in UEFI 2.0. + This protocol is used on any device handle to obtain authentication information + associated with the physical or logical device. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __AUTHENTICATION_INFO_H__ +#define __AUTHENTICATION_INFO_H__ + +#define EFI_AUTHENTICATION_INFO_PROTOCOL_GUID \ + { \ + 0x7671d9d0, 0x53db, 0x4173, {0xaa, 0x69, 0x23, 0x27, 0xf2, 0x1f, 0x0b, 0xc7 } \ + } + +#define EFI_AUTHENTICATION_CHAP_RADIUS_GUID \ + { \ + 0xd6062b50, 0x15ca, 0x11da, {0x92, 0x19, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +#define EFI_AUTHENTICATION_CHAP_LOCAL_GUID \ + { \ + 0xc280c73e, 0x15ca, 0x11da, {0xb0, 0xca, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +typedef struct _EFI_AUTHENTICATION_INFO_PROTOCOL EFI_AUTHENTICATION_INFO_PROTOCOL; + +#pragma pack(1) +typedef struct { + /// + /// Authentication Type GUID. + /// + EFI_GUID Guid; + + /// + /// Length of this structure in bytes. + /// + UINT16 Length; +} AUTH_NODE_HEADER; + +typedef struct { + AUTH_NODE_HEADER Header; + + /// + /// RADIUS Server IPv4 or IPv6 Address. + /// + UINT8 RadiusIpAddr[16]; ///< IPv4 or IPv6 address. + + /// + /// Reserved for future use. + /// + UINT16 Reserved; + + /// + /// Network Access Server IPv4 or IPv6 Address (OPTIONAL). + /// + UINT8 NasIpAddr[16]; ///< IPv4 or IPv6 address. + + /// + /// Network Access Server Secret Length in bytes (OPTIONAL). + /// + UINT16 NasSecretLength; + + /// + /// Network Access Server Secret (OPTIONAL). + /// + UINT8 NasSecret[1]; + + /// + /// CHAP Initiator Secret Length in bytes on offset NasSecret + NasSecretLength. + /// + /// UINT16 ChapSecretLength; + /// + /// CHAP Initiator Secret. + /// + /// UINT8 ChapSecret[]; + /// + /// CHAP Initiator Name Length in bytes on offset ChapSecret + ChapSecretLength. + /// + /// UINT16 ChapNameLength; + /// + /// CHAP Initiator Name. + /// + /// UINT8 ChapName[]; + /// + /// Reverse CHAP Name Length in bytes on offset ChapName + ChapNameLength. + /// + /// UINT16 ReverseChapNameLength; + /// + /// Reverse CHAP Name. + /// + /// UINT8 ReverseChapName[]; + /// + /// Reverse CHAP Secret Length in bytes on offseet ReverseChapName + ReverseChapNameLength. + /// + /// UINT16 ReverseChapSecretLength; + /// + /// Reverse CHAP Secret. + /// + /// UINT8 ReverseChapSecret[]; + /// +} CHAP_RADIUS_AUTH_NODE; + +typedef struct { + AUTH_NODE_HEADER Header; + + /// + /// Reserved for future use. + /// + UINT16 Reserved; + + /// + /// User Secret Length in bytes. + /// + UINT16 UserSecretLength; + + /// + /// User Secret. + /// + UINT8 UserSecret[1]; + + /// + /// User Name Length in bytes on offset UserSecret + UserSecretLength. + /// + /// UINT16 UserNameLength; + /// + /// User Name. + /// + /// UINT8 UserName[]; + /// + /// CHAP Initiator Secret Length in bytes on offset UserName + UserNameLength. + /// + /// UINT16 ChapSecretLength; + /// + /// CHAP Initiator Secret. + /// + /// UINT8 ChapSecret[]; + /// + /// CHAP Initiator Name Length in bytes on offset ChapSecret + ChapSecretLength. + /// + /// UINT16 ChapNameLength; + /// + /// CHAP Initiator Name. + /// + /// UINT8 ChapName[]; + /// + /// Reverse CHAP Name Length in bytes on offset ChapName + ChapNameLength. + /// + /// UINT16 ReverseChapNameLength; + /// + /// Reverse CHAP Name. + /// + /// UINT8 ReverseChapName[]; + /// + /// Reverse CHAP Secret Length in bytes on offset ReverseChapName + ReverseChapNameLength. + /// + /// UINT16 ReverseChapSecretLength; + /// + /// Reverse CHAP Secret. + /// + /// UINT8 ReverseChapSecret[]; + /// +} CHAP_LOCAL_AUTH_NODE; +#pragma pack() + +/** + Retrieves the authentication information associated with a particular controller handle. + + @param[in] This The pointer to the EFI_AUTHENTICATION_INFO_PROTOCOL. + @param[in] ControllerHandle The handle to the Controller. + @param[out] Buffer The pointer to the authentication information. This function is + responsible for allocating the buffer and it is the caller's + responsibility to free buffer when the caller is finished with buffer. + + @retval EFI_SUCCESS Successfully retrieved authentication information + for the given ControllerHandle. + @retval EFI_INVALID_PARAMETER No matching authentication information found for + the given ControllerHandle. + @retval EFI_DEVICE_ERROR The authentication information could not be retrieved + due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_AUTHENTICATION_INFO_PROTOCOL_GET)( + IN EFI_AUTHENTICATION_INFO_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + OUT VOID **Buffer + ); + +/** + Set the authentication information for a given controller handle. + + @param[in] This The pointer to the EFI_AUTHENTICATION_INFO_PROTOCOL. + @param[in] ControllerHandle The handle to the Controller. + @param[in] Buffer The pointer to the authentication information. + + @retval EFI_SUCCESS Successfully set authentication information for the + given ControllerHandle. + @retval EFI_UNSUPPORTED If the platform policies do not allow setting of + the authentication information. + @retval EFI_DEVICE_ERROR The authentication information could not be configured + due to a hardware error. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_AUTHENTICATION_INFO_PROTOCOL_SET)( + IN EFI_AUTHENTICATION_INFO_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN VOID *Buffer + ); + +/// +/// This protocol is used on any device handle to obtain authentication +/// information associated with the physical or logical device. +/// +struct _EFI_AUTHENTICATION_INFO_PROTOCOL { + EFI_AUTHENTICATION_INFO_PROTOCOL_GET Get; + EFI_AUTHENTICATION_INFO_PROTOCOL_SET Set; +}; + +extern EFI_GUID gEfiAuthenticationInfoProtocolGuid; +extern EFI_GUID gEfiAuthenticationChapRadiusGuid; +extern EFI_GUID gEfiAuthenticationChapLocalGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bds.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bds.h new file mode 100644 index 0000000..57966b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bds.h @@ -0,0 +1,72 @@ +/** @file + Boot Device Selection Architectural Protocol as defined in PI spec Volume 2 DXE + + When the DXE core is done it calls the BDS via this protocol. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_BDS_H__ +#define __ARCH_PROTOCOL_BDS_H__ + +/// +/// Global ID for the BDS Architectural Protocol +/// +#define EFI_BDS_ARCH_PROTOCOL_GUID \ + { 0x665E3FF6, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +/// +/// Declare forward reference for the BDS Architectural Protocol +/// +typedef struct _EFI_BDS_ARCH_PROTOCOL EFI_BDS_ARCH_PROTOCOL; + +/** + This function uses policy data from the platform to determine what operating + system or system utility should be loaded and invoked. This function call + also optionally make the use of user input to determine the operating system + or system utility to be loaded and invoked. When the DXE Core has dispatched + all the drivers on the dispatch queue, this function is called. This + function will attempt to connect the boot devices required to load and invoke + the selected operating system or system utility. During this process, + additional firmware volumes may be discovered that may contain addition DXE + drivers that can be dispatched by the DXE Core. If a boot device cannot be + fully connected, this function calls the DXE Service Dispatch() to allow the + DXE drivers from any newly discovered firmware volumes to be dispatched. + Then the boot device connection can be attempted again. If the same boot + device connection operation fails twice in a row, then that boot device has + failed, and should be skipped. This function should never return. + + @param This The EFI_BDS_ARCH_PROTOCOL instance. + + @return None. + +**/ +typedef +VOID +(EFIAPI *EFI_BDS_ENTRY)( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +/// +/// The EFI_BDS_ARCH_PROTOCOL transfers control from DXE to an operating +/// system or a system utility. If there are not enough drivers initialized +/// when this protocol is used to access the required boot device(s), then +/// this protocol should add drivers to the dispatch queue and return control +/// back to the dispatcher. Once the required boot devices are available, then +/// the boot device can be used to load and invoke an OS or a system utility. +/// +struct _EFI_BDS_ARCH_PROTOCOL { + EFI_BDS_ENTRY Entry; +}; + +extern EFI_GUID gEfiBdsArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bis.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bis.h new file mode 100644 index 0000000..a3f073d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Bis.h @@ -0,0 +1,451 @@ +/** @file + The EFI_BIS_PROTOCOL is used to check a digital signature of a data block + against a digital certificate for the purpose of an integrity and authorization check. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in EFI Specification 1.10. + +**/ + +#ifndef __BIS_H__ +#define __BIS_H__ + +#define EFI_BIS_PROTOCOL_GUID \ + { \ + 0x0b64aab0, 0x5429, 0x11d4, {0x98, 0x16, 0x00, 0xa0, 0xc9, 0x1f, 0xad, 0xcf } \ + } + +// +// X-Intel-BIS-ParameterSet +// Attribute value +// Binary Value of X-Intel-BIS-ParameterSet Attribute. +// (Value is Base-64 encoded in actual signed manifest). +// +#define BOOT_OBJECT_AUTHORIZATION_PARMSET_GUID \ + { \ + 0xedd35e31, 0x7b9, 0x11d2, { 0x83,0xa3,0x0,0xa0,0xc9,0x1f,0xad,0xcf } \ + } + + + +typedef struct _EFI_BIS_PROTOCOL EFI_BIS_PROTOCOL; + + +// +// Basic types +// +typedef VOID *BIS_APPLICATION_HANDLE; +typedef UINT16 BIS_ALG_ID; +typedef UINT32 BIS_CERT_ID; + +/// +/// EFI_BIS_DATA instances obtained from BIS must be freed by calling Free( ). +/// +typedef struct { + UINT32 Length; ///< The length of Data in 8 bit bytes. + UINT8 *Data; ///< 32 Bit Flat Address of data. +} EFI_BIS_DATA; + +/// +/// EFI_BIS_VERSION type. +/// +typedef struct { + UINT32 Major; ///< The major BIS version number. + UINT32 Minor; ///< A minor BIS version number. +} EFI_BIS_VERSION; + +// +// ----------------------------------------------------// +// Use these values to initialize EFI_BIS_VERSION.Major +// and to interpret results of Initialize. +// ----------------------------------------------------// +// +#define BIS_CURRENT_VERSION_MAJOR BIS_VERSION_1 +#define BIS_VERSION_1 1 + +/// +/// EFI_BIS_SIGNATURE_INFO type. +/// +typedef struct { + BIS_CERT_ID CertificateID; ///< Truncated hash of platform Boot Object + BIS_ALG_ID AlgorithmID; ///< A signature algorithm number. + UINT16 KeyLength; ///< The length of alg. keys in bits. +} EFI_BIS_SIGNATURE_INFO; + +/// +/// values for EFI_BIS_SIGNATURE_INFO.AlgorithmID. +/// The exact numeric values come from the +/// "Common Data Security Architecture (CDSA) Specification". +/// +#define BIS_ALG_DSA (41) // CSSM_ALGID_DSA +#define BIS_ALG_RSA_MD5 (42) // CSSM_ALGID_MD5_WITH_RSA +/// +/// values for EFI_BIS_SIGNATURE_INFO.CertificateId. +/// +#define BIS_CERT_ID_DSA BIS_ALG_DSA // CSSM_ALGID_DSA +#define BIS_CERT_ID_RSA_MD5 BIS_ALG_RSA_MD5 // CSSM_ALGID_MD5_WITH_RSA +/// +/// The mask value that gets applied to the truncated hash of a +/// platform Boot Object Authorization Certificate to create the certificateID. +/// A certificateID must not have any bits set to the value 1 other than bits in +/// this mask. +/// +#define BIS_CERT_ID_MASK (0xFF7F7FFF) + +/// +/// Macros for dealing with the EFI_BIS_DATA object obtained +/// from BIS_GetSignatureInfo(). +/// BIS_GET_SIGINFO_COUNT - tells how many EFI_BIS_SIGNATURE_INFO +/// elements are contained in a EFI_BIS_DATA struct pointed to +/// by the provided EFI_BIS_DATA*. +/// +#define BIS_GET_SIGINFO_COUNT(BisDataPtr) ((BisDataPtr)->Length / sizeof (EFI_BIS_SIGNATURE_INFO)) + +/// +/// BIS_GET_SIGINFO_ARRAY - produces a EFI_BIS_SIGNATURE_INFO* +/// from a given EFI_BIS_DATA*. +/// +#define BIS_GET_SIGINFO_ARRAY(BisDataPtr) ((EFI_BIS_SIGNATURE_INFO *) (BisDataPtr)->Data) + +/// +/// Support an old name for backward compatibility. +/// +#define BOOT_OBJECT_AUTHORIZATION_PARMSET_GUIDVALUE \ + BOOT_OBJECT_AUTHORIZATION_PARMSET_GUID + +/** + Initializes the BIS service, checking that it is compatible with the version requested by the caller. + After this call, other BIS functions may be invoked. + + @param This A pointer to the EFI_BIS_PROTOCOL object. + @param AppHandle The function writes the new BIS_APPLICATION_HANDLE if + successful, otherwise it writes NULL. The caller must eventually + destroy this handle by calling Shutdown(). + @param InterfaceVersion On input, the caller supplies the major version number of the + interface version desired. + On output, both the major and minor + version numbers are updated with the major and minor version + numbers of the interface. This update is done whether or not the + initialization was successful. + @param TargetAddress Indicates a network or device address of the BIS platform to connect to. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INCOMPATIBLE_VERSION The InterfaceVersion.Major requested by the + caller was not compatible with the interface version of the + implementation. The InterfaceVersion.Major has + been updated with the current interface version. + @retval EFI_UNSUPPORTED This is a local-platform implementation and + TargetAddress.Data was not NULL, or + TargetAddress.Data was any other value that was not + supported by the implementation. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_DEVICE_ERROR One of the following device errors: + * The function encountered an unexpected internal failure while initializing a cryptographic software module + * No cryptographic software module with compatible version was found + found + * A resource limitation was encountered while using a cryptographic software module. + @retval EFI_INVALID_PARAMETER The This parameter supplied by the caller is NULL or does not + reference a valid EFI_BIS_PROTOCOL object. Or, + the AppHandle parameter supplied by the caller is NULL or + an invalid memory reference. Or, + the InterfaceVersion parameter supplied by the caller + is NULL or an invalid memory reference. Or, + the TargetAddress parameter supplied by the caller is + NULL or an invalid memory reference. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_INITIALIZE)( + IN EFI_BIS_PROTOCOL *This, + OUT BIS_APPLICATION_HANDLE *AppHandle, + IN OUT EFI_BIS_VERSION *InterfaceVersion, + IN EFI_BIS_DATA *TargetAddress + ); + +/** + Frees memory structures allocated and returned by other functions in the EFI_BIS protocol. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + @param ToFree An EFI_BIS_DATA* and associated memory block to be freed. + This EFI_BIS_DATA* must have been allocated by one of the other BIS functions. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The ToFree parameter is not or is no longer a memory resource + associated with this AppHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_FREE)( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *ToFree + ); + +/** + Shuts down an application's instance of the BIS service, invalidating the application handle. After + this call, other BIS functions may no longer be invoked using the application handle value. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not, or is no longer, a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_DEVICE_ERROR The function encountered an unexpected internal failure while + returning resources associated with a cryptographic software module, or + while trying to shut down a cryptographic software module. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_SHUTDOWN)( + IN BIS_APPLICATION_HANDLE AppHandle + ); + +/** + Retrieves the certificate that has been configured as the identity of the organization designated as + the source of authorization for signatures of boot objects. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + @param Certificate The function writes an allocated EFI_BIS_DATA* containing the Boot + Object Authorization Certificate object. The caller must + eventually free the memory allocated by this function using the function Free(). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_NOT_FOUND There is no Boot Object Authorization Certificate currently installed. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The Certificate parameter supplied by the caller is NULL or + an invalid memory reference. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CERTIFICATE)( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT EFI_BIS_DATA **Certificate + ); + +/** + Verifies the integrity and authorization of the indicated data object according to the + indicated credentials. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + @param Credentials A Signed Manifest containing verification information for the indicated + data object. + @param DataObject An in-memory copy of the raw data object to be verified. + @param IsVerified The function writes TRUE if the verification succeeded, otherwise + FALSE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_SECURITY_VIOLATION The signed manifest supplied as the Credentials parameter + was invalid (could not be parsed) or Platform-specific authorization failed, etc. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_VERIFY_BOOT_OBJECT)( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *Credentials, + IN EFI_BIS_DATA *DataObject, + OUT BOOLEAN *IsVerified + ); + +/** + Retrieves the current status of the Boot Authorization Check Flag. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + @param CheckIsRequired The function writes the value TRUE if a Boot Authorization Check is + currently required on this platform, otherwise the function writes + FALSE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The CheckIsRequired parameter supplied by the caller is + NULL or an invalid memory reference. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CHECKFLAG)( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT BOOLEAN *CheckIsRequired + ); + +/** + Retrieves a unique token value to be included in the request credential for the next update of any + parameter in the Boot Object Authorization set + + @param AppHandle An opaque handle that identifies the caller's + instance of initialization of the BIS service. + @param UpdateToken The function writes an allocated EFI_BIS_DATA* + containing the newunique update token value. + The caller musteventually free the memory allocated + by this function using the function Free(). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The UpdateToken parameter supplied by the caller is NULL or + an invalid memory reference. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_UPDATE_TOKEN)( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT EFI_BIS_DATA **UpdateToken + ); + +/** + Updates one of the configurable parameters of the Boot Object Authorization set. + + @param AppHandle An opaque handle that identifies the caller's + instance of initialization of the BIS service. + @param RequestCredential This is a Signed Manifest with embedded attributes + that carry the details of the requested update. + @param NewUpdateToken The function writes an allocated EFI_BIS_DATA* + containing the new unique update token value. + The caller must eventually free the memory allocated + by this function using the function Free(). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_SECURITY_VIOLATION The signed manifest supplied as the RequestCredential parameter + was invalid (could not be parsed) or Platform-specific authorization failed, etc. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred while analyzing the new + certificate's key algorithm, or while attempting to retrieve + the public key algorithm of the manifest's signer's certificate, + or An unexpected internal error occurred in a cryptographic software module. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_UPDATE_BOOT_OBJECT_AUTHORIZATION)( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *RequestCredential, + OUT EFI_BIS_DATA **NewUpdateToken + ); + +/** + Verifies the integrity and authorization of the indicated data object according to the indicated + credentials and authority certificate. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + @param Credentials A Signed Manifest containing verification information for the + indicated data object. + @param DataObject An in-memory copy of the raw data object to be verified. + @param SectionName An ASCII string giving the section name in the + manifest holding the verification information (in other words, + hash value) that corresponds to DataObject. + @param AuthorityCertificate A digital certificate whose public key must match the signer's + public key which is found in the credentials. + @param IsVerified The function writes TRUE if the verification was successful. + Otherwise, the function writes FALSE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_SECURITY_VIOLATION The Credentials.Data supplied by the caller is NULL, + or the AuthorityCertificate supplied by the caller was + invalid (could not be parsed), + or Platform-specific authorization failed, etc. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred while attempting to retrieve + the public key algorithm of the manifest's signer's certificate, + or An unexpected internal error occurred in a cryptographic software module. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_VERIFY_OBJECT_WITH_CREDENTIAL)( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *Credentials, + IN EFI_BIS_DATA *DataObject, + IN EFI_BIS_DATA *SectionName, + IN EFI_BIS_DATA *AuthorityCertificate, + OUT BOOLEAN *IsVerified + ); + +/** + Retrieves a list of digital certificate identifier, digital signature algorithm, hash algorithm, and keylength + combinations that the platform supports. + + @param AppHandle An opaque handle that identifies the caller's instance of initialization + of the BIS service. + @param SignatureInfo The function writes an allocated EFI_BIS_DATA* containing the array + of EFI_BIS_SIGNATURE_INFO structures representing the supported + digital certificate identifier, algorithm, and key length combinations. + The caller must eventually free the memory allocated by this function using the function Free(). + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The SignatureInfo parameter supplied by the caller is NULL + or an invalid memory reference. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred in a + cryptographic software module, or + The function encountered an unexpected internal consistency check + failure (possible corruption of stored Boot Object Authorization Certificate). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_SIGNATURE_INFO)( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT EFI_BIS_DATA **SignatureInfo + ); + +/// +/// The EFI_BIS_PROTOCOL is used to check a digital signature of a data block against a digital +/// certificate for the purpose of an integrity and authorization check. +/// +struct _EFI_BIS_PROTOCOL { + EFI_BIS_INITIALIZE Initialize; + EFI_BIS_SHUTDOWN Shutdown; + EFI_BIS_FREE Free; + EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CERTIFICATE GetBootObjectAuthorizationCertificate; + EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CHECKFLAG GetBootObjectAuthorizationCheckFlag; + EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_UPDATE_TOKEN GetBootObjectAuthorizationUpdateToken; + EFI_BIS_GET_SIGNATURE_INFO GetSignatureInfo; + EFI_BIS_UPDATE_BOOT_OBJECT_AUTHORIZATION UpdateBootObjectAuthorization; + EFI_BIS_VERIFY_BOOT_OBJECT VerifyBootObject; + EFI_BIS_VERIFY_OBJECT_WITH_CREDENTIAL VerifyObjectWithCredential; +}; + +extern EFI_GUID gEfiBisProtocolGuid; +extern EFI_GUID gBootObjectAuthorizationParmsetGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo.h new file mode 100644 index 0000000..2bcbe23 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo.h @@ -0,0 +1,241 @@ +/** @file + Block IO protocol as defined in the UEFI 2.0 specification. + + The Block IO protocol is used to abstract block devices like hard drives, + DVD-ROMs and floppy drives. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BLOCK_IO_H__ +#define __BLOCK_IO_H__ + +#define EFI_BLOCK_IO_PROTOCOL_GUID \ + { \ + 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL; + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO; + +/** + Reset the Block Device. + + @param This Indicates a pointer to the calling context. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_RESET)( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId Id of the media, changes every time the media is replaced. + @param Lba The starting Logical Block Address to read from + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the destination buffer for the data. The caller is + responsible for either having implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_READ)( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId The media ID that the write request is for. + @param Lba The starting logical block address to be written. The caller is + responsible for writing to only legitimate locations. + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_WRITE)( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flush the Block Device. + + @param This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data was written to the device + @retval EFI_DEVICE_ERROR The device reported an error while writting back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_FLUSH)( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +/** + Block IO read only mode data and updated only via members of BlockIO +**/ +typedef struct { + /// + /// The curent media Id. If the media changes, this value is changed. + /// + UINT32 MediaId; + + /// + /// TRUE if the media is removable; otherwise, FALSE. + /// + BOOLEAN RemovableMedia; + + /// + /// TRUE if there is a media currently present in the device; + /// othersise, FALSE. THis field shows the media present status + /// as of the most recent ReadBlocks() or WriteBlocks() call. + /// + BOOLEAN MediaPresent; + + /// + /// TRUE if LBA 0 is the first block of a partition; otherwise + /// FALSE. For media with only one partition this would be TRUE. + /// + BOOLEAN LogicalPartition; + + /// + /// TRUE if the media is marked read-only otherwise, FALSE. + /// This field shows the read-only status as of the most recent WriteBlocks () call. + /// + BOOLEAN ReadOnly; + + /// + /// TRUE if the WriteBlock () function caches write data. + /// + BOOLEAN WriteCaching; + + /// + /// The intrinsic block size of the device. If the media changes, then + /// this field is updated. + /// + UINT32 BlockSize; + + /// + /// Supplies the alignment requirement for any buffer to read or write block(s). + /// + UINT32 IoAlign; + + /// + /// The last logical block address on the device. + /// If the media changes, then this field is updated. + /// + EFI_LBA LastBlock; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the first LBA is aligned to + /// a physical block boundary. + /// + EFI_LBA LowestAlignedLba; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the number of logical blocks + /// per physical block. + /// + UINT32 LogicalBlocksPerPhysicalBlock; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION3. Returns the optimal transfer length + /// granularity as a number of logical blocks. + /// + UINT32 OptimalTransferLengthGranularity; +} EFI_BLOCK_IO_MEDIA; + +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031 + +/// +/// Revision defined in EFI1.1. +/// +#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION + +/// +/// This protocol provides control over block devices. +/// +struct _EFI_BLOCK_IO_PROTOCOL { + /// + /// The revision to which the block IO interface adheres. All future + /// revisions must be backwards compatible. If a future version is not + /// back wards compatible, it is not the same GUID. + /// + UINT64 Revision; + /// + /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device. + /// + EFI_BLOCK_IO_MEDIA *Media; + + EFI_BLOCK_RESET Reset; + EFI_BLOCK_READ ReadBlocks; + EFI_BLOCK_WRITE WriteBlocks; + EFI_BLOCK_FLUSH FlushBlocks; + +}; + +extern EFI_GUID gEfiBlockIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo2.h new file mode 100644 index 0000000..2e6ec1c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIo2.h @@ -0,0 +1,206 @@ +/** @file + Block IO2 protocol as defined in the UEFI 2.3.1 specification. + + The Block IO2 protocol defines an extension to the Block IO protocol which + enables the ability to read and write data at a block level in a non-blocking + manner. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BLOCK_IO2_H__ +#define __BLOCK_IO2_H__ + +#include + +#define EFI_BLOCK_IO2_PROTOCOL_GUID \ + { \ + 0xa77b2472, 0xe282, 0x4e9f, {0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1} \ + } + +typedef struct _EFI_BLOCK_IO2_PROTOCOL EFI_BLOCK_IO2_PROTOCOL; + +/** + The struct of Block IO2 Token. +**/ +typedef struct { + + /// + /// 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 read request is completed. + /// + EFI_EVENT Event; + + /// + /// Defines whether or not the signaled event encountered an error. + /// + EFI_STATUS TransactionStatus; +} EFI_BLOCK_IO2_TOKEN; + + +/** + Reset the block device hardware. + + @param[in] This Indicates a pointer to the calling context. + @param[in] ExtendedVerification Indicates that the driver may perform a more + exhausive verification operation of the device + during reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_RESET_EX) ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read BufferSize bytes from Lba into Buffer. + + This function reads the requested number of blocks from the device. All the + blocks are read, or an error is returned. + If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and + non-blocking I/O is being used, the Event associated with this request will + not be signaled. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId Id of the media, changes every time the media is + replaced. + @param[in] Lba The starting Logical Block Address to read from. + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize Size of Buffer, must be a multiple of device block size. + @param[out] Buffer A pointer to the destination buffer for the data. The + caller is responsible for either having implicit or + explicit ownership of the buffer. + + @retval EFI_SUCCESS The read request was queued if Token->Event is + not NULL.The data was read correctly from the + device if the Token->Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_READ_EX) ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write BufferSize bytes from Lba into Buffer. + + This function writes the requested number of blocks to the device. All blocks + are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA, + EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is + being used, the Event associated with this request will not be signaled. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the write request is for. + @param[in] Lba The starting logical block address to be written. The + caller is responsible for writing to only legitimate + locations. + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize Size of Buffer, must be a multiple of device block size. + @param[in] Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The write request was queued if Event is not NULL. + The data was written correctly to the device if + the Event is NULL. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_WRITE_EX) ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flush the Block Device. + + If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED + is returned and non-blocking I/O is being used, the Event associated with + this request will not be signaled. + + @param[in] This Indicates a pointer to the calling context. + @param[in,out] Token A pointer to the token associated with the transaction + + @retval EFI_SUCCESS The flush request was queued if Event is not NULL. + All outstanding data was written correctly to the + device if the Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while writting back + the data. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_FLUSH_EX) ( + IN EFI_BLOCK_IO2_PROTOCOL *This, + IN OUT EFI_BLOCK_IO2_TOKEN *Token + ); + +/// +/// The Block I/O2 protocol defines an extension to the Block I/O protocol which +/// enables the ability to read and write data at a block level in a non-blocking +// manner. +/// +struct _EFI_BLOCK_IO2_PROTOCOL { + /// + /// A pointer to the EFI_BLOCK_IO_MEDIA data for this device. + /// Type EFI_BLOCK_IO_MEDIA is defined in BlockIo.h. + /// + EFI_BLOCK_IO_MEDIA *Media; + + EFI_BLOCK_RESET_EX Reset; + EFI_BLOCK_READ_EX ReadBlocksEx; + EFI_BLOCK_WRITE_EX WriteBlocksEx; + EFI_BLOCK_FLUSH_EX FlushBlocksEx; +}; + +extern EFI_GUID gEfiBlockIo2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIoCrypto.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIoCrypto.h new file mode 100644 index 0000000..631ebfd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BlockIoCrypto.h @@ -0,0 +1,530 @@ +/** @file + The UEFI Inline Cryptographic Interface protocol provides services to abstract + access to inline cryptographic capabilities. + + Copyright (c) 2015-2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.5. + +**/ + +#ifndef __BLOCK_IO_CRYPTO_H__ +#define __BLOCK_IO_CRYPTO_H__ + +#include + +#define EFI_BLOCK_IO_CRYPTO_PROTOCOL_GUID \ + { \ + 0xa00490ba, 0x3f1a, 0x4b4c, {0xab, 0x90, 0x4f, 0xa9, 0x97, 0x26, 0xa1, 0xe8} \ + } + +typedef struct _EFI_BLOCK_IO_CRYPTO_PROTOCOL EFI_BLOCK_IO_CRYPTO_PROTOCOL; + +/// +/// The struct of Block I/O Crypto Token. +/// +typedef struct { + // + // 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 read request is completed and data was + // decrypted (when Index was specified). + // + EFI_EVENT Event; + // + // Defines whether or not the signaled event encountered an error. + // + EFI_STATUS TransactionStatus; +} EFI_BLOCK_IO_CRYPTO_TOKEN; + +typedef struct { + // + // GUID of the algorithm. + // + EFI_GUID Algorithm; + // + // Specifies KeySizein bits used with this Algorithm. + // + UINT64 KeySize; + // + // Specifies bitmask of block sizes supported by this algorithm. + // Bit j being set means that 2^j bytes crypto block size is supported. + // + UINT64 CryptoBlockSizeBitMask; +} EFI_BLOCK_IO_CRYPTO_CAPABILITY; + +/// +/// EFI_BLOCK_IO_CRYPTO_IV_INPUT structure is used as a common header in CryptoIvInput +/// parameters passed to the ReadExtended and WriteExtended methods for Inline +/// Cryptographic Interface. +/// Its purpose is to pass size of the entire CryptoIvInputparameter memory buffer to +/// the Inline Cryptographic Interface. +/// +typedef struct { + UINT64 InputSize; +} EFI_BLOCK_IO_CRYPTO_IV_INPUT; + +#define EFI_BLOCK_IO_CRYPTO_ALGO_GUID_AES_XTS \ + { \ + 0x2f87ba6a, 0x5c04, 0x4385, {0xa7, 0x80, 0xf3, 0xbf, 0x78, 0xa9, 0x7b, 0xec} \ + } + +extern EFI_GUID gEfiBlockIoCryptoAlgoAesXtsGuid; + +typedef struct { + EFI_BLOCK_IO_CRYPTO_IV_INPUT Header; + UINT64 CryptoBlockNumber; + UINT64 CryptoBlockByteSize; +} EFI_BLOCK_IO_CRYPTO_IV_INPUT_AES_XTS; + +#define EFI_BLOCK_IO_CRYPTO_ALGO_GUID_AES_CBC_MICROSOFT_BITLOCKER \ + { \ + 0x689e4c62, 0x70bf, 0x4cf3, {0x88, 0xbb, 0x33, 0xb3, 0x18, 0x26, 0x86, 0x70} \ + } + +extern EFI_GUID gEfiBlockIoCryptoAlgoAesCbcMsBitlockerGuid; + +typedef struct { + EFI_BLOCK_IO_CRYPTO_IV_INPUT Header; + UINT64 CryptoBlockByteOffset; + UINT64 CryptoBlockByteSize; +} EFI_BLOCK_IO_CRYPTO_IV_INPUT_AES_CBC_MICROSOFT_BITLOCKER; + +#define EFI_BLOCK_IO_CRYPTO_INDEX_ANY 0xFFFFFFFFFFFFFFFF + +typedef struct { + // + // Is inline cryptographic capability supported on this device. + // + BOOLEAN Supported; + // + // Maximum number of keys that can be configured at the same time. + // + UINT64 KeyCount; + // + // Number of supported capabilities. + // + UINT64 CapabilityCount; + // + // Array of supported capabilities. + // + EFI_BLOCK_IO_CRYPTO_CAPABILITY Capabilities[1]; +} EFI_BLOCK_IO_CRYPTO_CAPABILITIES; + +typedef struct { + // + // Configuration table index. A special Index EFI_BLOCK_IO_CRYPTO_INDEX_ANY can be + // used to set any available entry in the configuration table. + // + UINT64 Index; + // + // Identifies the owner of the configuration table entry. Entry can also be used + // with the Nil value to clear key from the configuration table index. + // + EFI_GUID KeyOwnerGuid; + // + // A supported capability to be used. The CryptoBlockSizeBitMask field of the + // structure should have only one bit set from the supported mask. + // + EFI_BLOCK_IO_CRYPTO_CAPABILITY Capability; + // + // Pointer to the key. The size of the key is defined by the KeySize field of + // the capability specified by the Capability parameter. + // + VOID *CryptoKey; +} EFI_BLOCK_IO_CRYPTO_CONFIGURATION_TABLE_ENTRY; + +typedef struct { + // + // Configuration table index. + // + UINT64 Index; + // + // Identifies the current owner of the entry. + // + EFI_GUID KeyOwnerGuid; + // + // The capability to be used. The CryptoBlockSizeBitMask field of the structure + // has only one bit set from the supported mask. + // + EFI_BLOCK_IO_CRYPTO_CAPABILITY Capability; +} EFI_BLOCK_IO_CRYPTO_RESPONSE_CONFIGURATION_ENTRY; + +/** + Reset the block device hardware. + + The Reset() function resets the block device hardware. + + As part of the initialization process, the firmware/device will make a quick but + reasonable attempt to verify that the device is functioning. + + If the ExtendedVerificationflag is TRUE the firmware may take an extended amount + of time to verify the device is operating on reset. Otherwise the reset operation + is to occur as quickly as possible. + + The hardware verification process is not defined by this specification and is left + up to the platform firmware or driver to implement. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[in] ExtendedVerification Indicates that the driver may perform a more exhausive + verification operation of the device during reset. + + @retval EFI_SUCCESS The block device was reset. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could + not be reset. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_RESET) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Get the capabilities of the underlying inline cryptographic interface. + + The GetCapabilities() function determines whether pre-OS controllable inline crypto + is supported by the system for the current disk and, if so, returns the capabilities + of the crypto engine. + + The caller is responsible for providing the Capabilities structure with a sufficient + number of entries. + + If the structure is too small, the EFI_BUFFER_TOO_SMALL error code is returned and the + CapabilityCount field contains the number of entries needed to contain the capabilities. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[out] Capabilities Pointer to the EFI_BLOCK_IO_CRYPTO_CAPABILITIES structure. + + @retval EFI_SUCCESS The ICI is ready for use. + @retval EFI_BUFFER_TOO_SMALL The Capabilities structure was too small. The number of + entries needed is returned in the CapabilityCount field + of the structure. + @retval EFI_NO_RESPONSE No response was received from the ICI. + @retval EFI_DEVICE_ERROR An error occurred when attempting to access the ICI. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER Capabilities is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_GET_CAPABILITIES) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + OUT EFI_BLOCK_IO_CRYPTO_CAPABILITIES *Capabilities + ); + +/** + Set the configuration of the underlying inline cryptographic interface. + + The SetConfiguration() function allows the user to set the current configuration of the + inline cryptographic interface and should be called before attempting any crypto operations. + + This configures the configuration table entries with algorithms, key sizes and keys. Each + configured entry can later be referred to by index at the time of storage transaction. + + The configuration table index will refer to the combination ofKeyOwnerGuid, Algorithm, and + CryptoKey. + + KeyOwnerGuid identifies the component taking ownership of the entry. It helps components to + identify their own entries, cooperate with other owner components, and avoid conflicts. This + Guid identifier is there to help coordination between cooperating components and not a security + or synchronization feature. The Nil GUID can be used by a component to release use of entry + owned. It is also used to identify potentially available entries (see GetConfiguration). + + CryptoKey specifies algorithm-specific key material to use within parameters of selected crypto + capability. + + This function is called infrequently typically once, on device start, before IO starts. It + can be called at later times in cases the number of keysused on the drive is higher than what + can be configured at a time or a new key has to be added. + + Components setting or changing an entry or entries for a given index or indices must ensure + that IO referencing affected indices is temporarily blocked (run-down) at the time of change. + + Indices parameters in each parameter table entry allow to set only a portion of the available + table entries in the crypto module anywhere from single entry to entire table supported. + + If corresponding table entry or entries being set are already in use by another owner the call + should be failed and none of the entries should be modified. The interface implementation must + enforce atomicity of this operation (should either succeed fully or fail completely without + modifying state). + + Note that components using GetConfiguration command to discover available entries should be + prepared that by the time of calling SetConfiguration the previously available entry may have + become occupied. Such components should be prepared to re-try the sequence of operations. + + Alternatively EFI_BLOCK_IO_CRYPTO_INDEX_ANY can be used to have the implementation discover + and allocate available,if any, indices atomically. + + An optional ResultingTable pointer can be provided by the caller to receive the newly configured + entries. The array provided by the caller must have at least ConfigurationCount of entries. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[in] ConfigurationCount Number of entries being configured with this call. + @param[in] ConfigurationTable Pointer to a table used to populate the configuration table. + @param[out] ResultingTable Optional pointer to a table that receives the newly configured + entries. + + @retval EFI_SUCCESS The ICI is ready for use. + @retval EFI_NO_RESPONSE No response was received from the ICI. + @retval EFI_DEVICE_ERROR An error occurred when attempting to access the ICI. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER ConfigurationTable is NULL. + @retval EFI_INVALID_PARAMETER ConfigurationCount is 0. + @retval EFI_OUT_OF_RESOURCES Could not find the requested number of available entries in the + configuration table. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_SET_CONFIGURATION) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + IN UINT64 ConfigurationCount, + IN EFI_BLOCK_IO_CRYPTO_CONFIGURATION_TABLE_ENTRY *ConfigurationTable, + OUT EFI_BLOCK_IO_CRYPTO_RESPONSE_CONFIGURATION_ENTRY *ResultingTable OPTIONAL + ); + +/** + Get the configuration of the underlying inline cryptographic interface. + + The GetConfiguration() function allows the user to get the configuration of the inline + cryptographic interface. + + Retrieves, entirely or partially, the currently configured key table. Note that the keys + themselves are not retrieved, but rather just indices, owner GUIDs and capabilities. + + If fewer entries than specified by ConfigurationCount are returned, the Index field of the + unused entries is set to EFI_BLOCK_IO_CRYPTO_INDEX_ANY. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[in] StartIndex Configuration table index at which to start the configuration + query. + @param[in] ConfigurationCount Number of entries to return in the response table. + @param[in] KeyOwnerGuid Optional parameter to filter response down to entries with a + given owner. A pointer to the Nil value can be used to return + available entries. Set to NULL when no owner filtering is required. + @param[out] ConfigurationTable Table of configured configuration table entries (with no CryptoKey + returned): configuration table index, KeyOwnerGuid, Capability. + Should have sufficient space to store up to ConfigurationCount + entries. + + @retval EFI_SUCCESS The ICI is ready for use. + @retval EFI_NO_RESPONSE No response was received from the ICI. + @retval EFI_DEVICE_ERROR An error occurred when attempting to access the ICI. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER Configuration table is NULL. + @retval EFI_INVALID_PARAMETER StartIndex is out of bounds. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_GET_CONFIGURATION) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + IN UINT64 StartIndex, + IN UINT64 ConfigurationCount, + IN EFI_GUID *KeyOwnerGuid OPTIONAL, + OUT EFI_BLOCK_IO_CRYPTO_RESPONSE_CONFIGURATION_ENTRY *ConfigurationTable +); + +/** + Reads the requested number of blocks from the device and optionally decrypts + them inline. + + TheReadExtended() function allows the caller to perform a storage device read + operation. The function reads the requested number of blocks from the device + and then if Index is specified decrypts them inline. All the blocks are read + and decrypted (if decryption requested), or an error is returned. + + If there is no media in the device, the function returns EFI_NO_MEDIA. If the + MediaId is not the ID for the current media in the device, the function returns + EFI_MEDIA_CHANGED. + + If EFI_DEVICE_ERROR, EFI_NO_MEDIA, or EFI_MEDIA_CHANGED is returned and nonblocking + I/O is being used, the Event associated with this request will not be signaled. + + In addition to standard storage transaction parameters (LBA, IO size, and buffer), + this command will also specify a configuration table Index and CryptoIvInput + when data has to be decrypted inline by the controller after being read from + the storage device. If an Index parameter is not specified, no decryption is + performed. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[in] MediaId The media ID that the read request is for. + @param[in] LBA The starting logical block address to read from on + the device. + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param[out] Buffer A pointer to the destination buffer for the data. The + caller is responsible for either having implicit or + explicit ownership of the buffer. + @param[in] Index A pointer to the configuration table index. This is + optional. + @param[in] CryptoIvInput A pointer to a buffer that contains additional + cryptographic parameters as required by the capability + referenced by the configuration table index, such as + cryptographic initialization vector. + + @retval EFI_SUCCESS The read request was queued if Token-> Event is not NULL. + The data was read correctly from the device if the + Token->Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform + the read operation and/or decryption operation. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic + block size of the device. + @retval EFI_INVALID_PARAMETER This is NULL, or the read request contains LBAs that are + not valid, or the buffer is not on proper alignment. + @retval EFI_INVALID_PARAMETER CryptoIvInput is incorrect. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of + resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_READ_EXTENDED) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO_CRYPTO_TOKEN *Token, + IN UINT64 BufferSize, + OUT VOID *Buffer, + IN UINT64 *Index OPTIONAL, + IN VOID *CryptoIvInput OPTIONAL + ); + +/** + Optionally encrypts a specified number of blocks inline and then writes to the + device. + + The WriteExtended() function allows the caller to perform a storage device write + operation. The function encrypts the requested number of blocks inline if Index + is specified and then writes them to the device. All the blocks are encrypted + (if encryption requested) and written, or an error is returned. + + If there is no media in the device, the function returns EFI_NO_MEDIA. If the + MediaId is not the ID for the current media in the device, the function returns + EFI_MEDIA_CHANGED. + + If EFI_DEVICE_ERROR, EFI_NO_MEDIA, or EFI_MEDIA_CHANGED is returned and nonblocking + I/O is being used, the Event associated with this request will not be signaled. + + In addition to standard storage transaction parameters (LBA, IO size, and buffer), + this command will also specify a configuration table Index and a CryptoIvInput + when data has to be decrypted inline by the controller before being written to + the storage device. If no Index parameter is specified, no encryption is performed. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[in] MediaId The media ID that the read request is for. + @param[in] LBA The starting logical block address to read from on + the device. + @param[in, out] Token A pointer to the token associated with the transaction. + @param[in] BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param[in] Buffer A pointer to the source buffer for the data. + @param[in] Index A pointer to the configuration table index. This is + optional. + @param[in] CryptoIvInput A pointer to a buffer that contains additional + cryptographic parameters as required by the capability + referenced by the configuration table index, such as + cryptographic initialization vector. + + @retval EFI_SUCCESS The request to encrypt (optionally) and write was queued + if Event is not NULL. The data was encrypted (optionally) + and written correctly to the device if the Event is NULL. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to encrypt + blocks or to perform the write operation. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic + block size of the device. + @retval EFI_INVALID_PARAMETER This is NULL, or the write request contains LBAs that are + not valid, or the buffer is not on proper alignment. + @retval EFI_INVALID_PARAMETER CryptoIvInput is incorrect. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of + resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_WRITE_EXTENDED) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO_CRYPTO_TOKEN *Token, + IN UINT64 BufferSize, + IN VOID *Buffer, + IN UINT64 *Index OPTIONAL, + IN VOID *CryptoIvInput OPTIONAL + ); + +/** + Flushes all modified data toa physical block device. + + The FlushBlocks() function flushes all modified data to the physical block device. + Any modified data that has to be encrypted must have been already encrypted as a + part of WriteExtended() operation - inline crypto operation cannot be a part of + flush operation. + + All data written to the device prior to the flush must be physically written before + returning EFI_SUCCESS from this function. This would include any cached data the + driver may have cached, and cached data the device may have cached. A flush may + cause a read request following the flush to force a device access. + + If EFI_DEVICE_ERROR, EFI_NO_MEDIA, EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is + returned and non-blocking I/O is being used, the Event associated with this request + will not be signaled. + + @param[in] This Pointer to the EFI_BLOCK_IO_CRYPTO_PROTOCOL instance. + @param[in, out] Token A pointer to the token associated with the transaction. + + @retval EFI_SUCCESS The flush request was queued if Event is not NULL. All + outstanding data was written correctly to the device if + the Event is NULL. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of + resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_IO_CRYPTO_FLUSH) ( + IN EFI_BLOCK_IO_CRYPTO_PROTOCOL *This, + IN OUT EFI_BLOCK_IO_CRYPTO_TOKEN *Token + ); + +/// +/// The EFI_BLOCK_IO_CRYPTO_PROTOCOL defines a UEFI protocol that can be used by UEFI +/// drivers and applications to perform block encryption on a storage device, such as UFS. +/// +struct _EFI_BLOCK_IO_CRYPTO_PROTOCOL { + EFI_BLOCK_IO_MEDIA *Media; + EFI_BLOCK_IO_CRYPTO_RESET Reset; + EFI_BLOCK_IO_CRYPTO_GET_CAPABILITIES GetCapabilities; + EFI_BLOCK_IO_CRYPTO_SET_CONFIGURATION SetConfiguration; + EFI_BLOCK_IO_CRYPTO_GET_CONFIGURATION GetConfiguration; + EFI_BLOCK_IO_CRYPTO_READ_EXTENDED ReadExtended; + EFI_BLOCK_IO_CRYPTO_WRITE_EXTENDED WriteExtended; + EFI_BLOCK_IO_CRYPTO_FLUSH FlushBlocks; +}; + +extern EFI_GUID gEfiBlockIoCryptoProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothAttribute.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothAttribute.h new file mode 100644 index 0000000..71df2b9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothAttribute.h @@ -0,0 +1,283 @@ +/** @file + EFI Bluetooth Attribute Protocol as defined in UEFI 2.7. + This protocol provides service for Bluetooth ATT (Attribute Protocol) and GATT (Generic + Attribute Profile) based protocol interfaces. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __EFI_BLUETOOTH_ATTRIBUTE_H__ +#define __EFI_BLUETOOTH_ATTRIBUTE_H__ + +#define EFI_BLUETOOTH_ATTRIBUTE_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x5639867a, 0x8c8e, 0x408d, { 0xac, 0x2f, 0x4b, 0x61, 0xbd, 0xc0, 0xbb, 0xbb } \ + } + +#define EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL_GUID \ + { \ + 0x898890e9, 0x84b2, 0x4f3a, { 0x8c, 0x58, 0xd8, 0x57, 0x78, 0x13, 0xe0, 0xac } \ + } + +typedef struct _EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL; + +#pragma pack(1) + +// +// Bluetooth UUID +// +typedef struct { + UINT8 Length; + union { + UINT16 Uuid16; + UINT32 Uuid32; + UINT8 Uuid128[16]; + } Data; +} EFI_BLUETOOTH_UUID; + + +#define UUID_16BIT_TYPE_LEN 2 +#define UUID_32BIT_TYPE_LEN 4 +#define UUID_128BIT_TYPE_LEN 16 + +#define BLUETOOTH_IS_ATTRIBUTE_OF_TYPE(a,t) ((a)->Type.Length == UUID_16BIT_TYPE_LEN && (a)->Type.Data.Uuid16 == (t)) + +// +// Bluetooth Attribute Permission +// +typedef union { + struct { + UINT16 Readable : 1; + UINT16 ReadEncryption : 1; + UINT16 ReadAuthentication : 1; + UINT16 ReadAuthorization : 1; + UINT16 ReadKeySize : 5; + UINT16 Reserved1 : 7; + UINT16 Writeable : 1; + UINT16 WriteEncryption : 1; + UINT16 WriteAuthentication : 1; + UINT16 WriteAuthorization : 1; + UINT16 WriteKeySize : 5; + UINT16 Reserved2 : 7; + } Permission; + UINT32 Data32; +} EFI_BLUETOOTH_ATTRIBUTE_PERMISSION; + +typedef struct { + EFI_BLUETOOTH_UUID Type; + UINT16 Length; + UINT16 AttributeHandle; + EFI_BLUETOOTH_ATTRIBUTE_PERMISSION AttributePermission; +} EFI_BLUETOOTH_ATTRIBUTE_HEADER; + +typedef struct { + EFI_BLUETOOTH_ATTRIBUTE_HEADER Header; + UINT16 EndGroupHandle; + EFI_BLUETOOTH_UUID ServiceUuid; +} EFI_BLUETOOTH_GATT_PRIMARY_SERVICE_INFO; + +typedef struct { + EFI_BLUETOOTH_ATTRIBUTE_HEADER Header; + UINT16 StartGroupHandle; + UINT16 EndGroupHandle; + EFI_BLUETOOTH_UUID ServiceUuid; +} EFI_BLUETOOTH_GATT_INCLUDE_SERVICE_INFO; + +typedef struct { + EFI_BLUETOOTH_ATTRIBUTE_HEADER Header; + UINT8 CharacteristicProperties; + UINT16 CharacteristicValueHandle; + EFI_BLUETOOTH_UUID CharacteristicUuid; +} EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO; + +typedef struct { + EFI_BLUETOOTH_ATTRIBUTE_HEADER Header; + EFI_BLUETOOTH_UUID CharacteristicDescriptorUuid; +} EFI_BLUETOOTH_GATT_CHARACTERISTIC_DESCRIPTOR_INFO; + +#pragma pack() + +typedef struct { + UINT16 AttributeHandle; +} EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER_NOTIFICATION; + +typedef struct { + UINT16 AttributeHandle; +} EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER_INDICATION; + +typedef struct { + UINT32 Version; + UINT8 AttributeOpCode; + union { + EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER_NOTIFICATION Notification; + EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER_INDICATION Indication; + } Parameter; +} EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER; + +typedef struct { + UINT32 Version; + BLUETOOTH_LE_ADDRESS BD_ADDR; + BLUETOOTH_LE_ADDRESS DirectAddress; + UINT8 RSSI; + UINTN AdvertisementDataSize; + VOID *AdvertisementData; +} EFI_BLUETOOTH_LE_DEVICE_INFO; + +/** + The callback function to send request. + + @param[in] This Pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL instance. + @param[in] Data Data received. The first byte is the attribute opcode, followed by opcode specific + fields. See Bluetooth specification, Vol 3, Part F, Attribute Protocol. It might be a + normal RESPONSE message, or ERROR RESPONSE messag + @param[in] DataLength The length of Data in bytes. + @param[in] Context The context passed from the callback registration request. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_FUNCTION) ( + IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This, + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context + ); + +/** + Send a "REQUEST" or "COMMAND" message to remote server and receive a "RESPONSE" message + for "REQUEST" from remote server according to Bluetooth attribute protocol data unit(PDU). + + @param[in] This Pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL instance. + @param[in] Data Data of a REQUEST or COMMAND message. The first byte is the attribute PDU + related opcode, followed by opcode specific fields. See Bluetooth specification, + Vol 3, Part F, Attribute Protocol. + @param[in] DataLength The length of Data in bytes. + @param[in] Callback Callback function to notify the RESPONSE is received to the caller, with the + response buffer. Caller must check the response buffer content to know if the + request action is success or fail. It may be NULL if the data is a COMMAND. + @param[in] Context Data passed into Callback function. It is optional parameter and may be NULL. + + @retval EFI_SUCCESS The request is sent successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid due to following conditions: + - The Buffer is NULL. + - The BufferLength is 0. + - The opcode in Buffer is not a valid OPCODE according to Bluetooth specification. + - The Callback is NULL. + @retval EFI_DEVICE_ERROR Sending the request failed due to the host controller or the device error. + @retval EFI_NOT_READY A GATT operation is already underway for this device. + @retval EFI_UNSUPPORTED The attribute does not support the corresponding operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_ATTRIBUTE_SEND_REQUEST) ( + IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This, + IN VOID *Data, + IN UINTN DataLength, + IN EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/** + Register or unregister a server initiated message, such as NOTIFICATION or INDICATION, on a + characteristic value on remote server. + + @param[in] This Pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL instance. + @param[in] CallbackParameter The parameter of the callback. + @param[in] Callback Callback function for server initiated attribute protocol. NULL callback + function means unregister the server initiated callback. + @param[in] Context Data passed into Callback function. It is optional parameter and may be NULL. + + @retval EFI_SUCCESS The callback function is registered or unregistered successfully + @retval EFI_INVALID_PARAMETER The attribute opcode is not server initiated message opcode. See + Bluetooth specification, Vol 3, Part F, Attribute Protocol. + @retval EFI_ALREADY_STARTED A callback function is already registered on the same attribute + opcode and attribute handle, when the Callback is not NULL. + @retval EFI_NOT_STARTED A callback function is not registered on the same attribute opcode + and attribute handle, when the Callback is NULL. + @retval EFI_NOT_READY A GATT operation is already underway for this device. + @retval EFI_UNSUPPORTED The attribute does not support notification. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_ATTRIBUTE_REGISTER_FOR_SERVER_NOTIFICATION)( + IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This, + IN EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER *CallbackParameter, + IN EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/** + Get Bluetooth discovered service information. + + @param[in] This Pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL instance. + @param[out] ServiceInfoSize A pointer to the size, in bytes, of the ServiceInfo buffer. + @param[out] ServiceInfo A pointer to a callee allocated buffer that returns Bluetooth + discovered service information. Callee allocates this buffer by + using EFI Boot Service AllocatePool(). + + @retval EFI_SUCCESS The Bluetooth discovered service information is returned successfully. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the Bluetooth discovered + service information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_ATTRIBUTE_GET_SERVICE_INFO)( + IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This, + OUT UINTN *ServiceInfoSize, + OUT VOID **ServiceInfo + ); + +/** + Get Bluetooth device information. + + @param[in] This Pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL instance. + @param[out] DeviceInfoSize A pointer to the size, in bytes, of the DeviceInfo buffer. + @param[out] DeviceInfo A pointer to a callee allocated buffer that returns Bluetooth + device information. Callee allocates this buffer by using EFI Boot + Service AllocatePool(). If this device is Bluetooth classic + device, EFI_BLUETOOTH_DEVICE_INFO should be used. If + this device is Bluetooth LE device, EFI_BLUETOOTH_LE_DEVICE_INFO + should be used. + + @retval EFI_SUCCESS The Bluetooth device information is returned successfully. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the Bluetooth device + information + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_ATTRIBUTE_GET_DEVICE_INFO)( + IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This, + OUT UINTN *DeviceInfoSize, + OUT VOID **DeviceInfo + ); + +struct _EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL { + EFI_BLUETOOTH_ATTRIBUTE_SEND_REQUEST SendRequest; + EFI_BLUETOOTH_ATTRIBUTE_REGISTER_FOR_SERVER_NOTIFICATION RegisterForServerNotification; + EFI_BLUETOOTH_ATTRIBUTE_GET_SERVICE_INFO GetServiceInfo; + EFI_BLUETOOTH_ATTRIBUTE_GET_DEVICE_INFO GetDeviceInfo; +}; + + +extern EFI_GUID gEfiBluetoothAttributeProtocolGuid; +extern EFI_GUID gEfiBluetoothAttributeServiceBindingProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothConfig.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothConfig.h new file mode 100644 index 0000000..07dfd2c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothConfig.h @@ -0,0 +1,529 @@ +/** @file + EFI Bluetooth Configuration Protocol as defined in UEFI 2.7. + This protocol abstracts user interface configuration for Bluetooth device. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __EFI_BLUETOOTH_CONFIG_PROTOCOL_H__ +#define __EFI_BLUETOOTH_CONFIG_PROTOCOL_H__ + +#include + +#define EFI_BLUETOOTH_CONFIG_PROTOCOL_GUID \ + { \ + 0x62960cf3, 0x40ff, 0x4263, { 0xa7, 0x7c, 0xdf, 0xde, 0xbd, 0x19, 0x1b, 0x4b } \ + } + +typedef struct _EFI_BLUETOOTH_CONFIG_PROTOCOL EFI_BLUETOOTH_CONFIG_PROTOCOL; + +typedef UINT32 EFI_BLUETOOTH_CONFIG_REMOTE_DEVICE_STATE_TYPE; +#define EFI_BLUETOOTH_CONFIG_REMOTE_DEVICE_STATE_CONNECTED 0x1 +#define EFI_BLUETOOTH_CONFIG_REMOTE_DEVICE_STATE_PAIRED 0x2 + +/// +/// EFI_BLUETOOTH_SCAN_CALLBACK_INFORMATION +/// +typedef struct { + /// + /// 48bit Bluetooth device address. + /// + BLUETOOTH_ADDRESS BDAddr; + /// + /// State of the remote deive + /// + UINT8 RemoteDeviceState; + /// + /// Bluetooth ClassOfDevice. See Bluetooth specification for detail. + /// + BLUETOOTH_CLASS_OF_DEVICE ClassOfDevice; + /// + /// Remote device name + /// + UINT8 RemoteDeviceName[BLUETOOTH_HCI_COMMAND_LOCAL_READABLE_NAME_MAX_SIZE]; +} EFI_BLUETOOTH_SCAN_CALLBACK_INFORMATION; + +/// +/// EFI_BLUETOOTH_CONFIG_DATA_TYPE +/// +typedef enum { + /// + /// Local/Remote Bluetooth device name. Data structure is zero terminated CHAR8[]. + /// + EfiBluetoothConfigDataTypeDeviceName, + /// + /// Local/Remote Bluetooth device ClassOfDevice. Data structure is BLUETOOTH_CLASS_OF_DEVICE. + /// + EfiBluetoothConfigDataTypeClassOfDevice, + /// + /// Remote Bluetooth device state. Data structure is EFI_BLUETOOTH_CONFIG_REMOTE_DEVICE_STATE_TYPE. + /// + EfiBluetoothConfigDataTypeRemoteDeviceState, /* Relevant for LE*/ + /// + /// Local/Remote Bluetooth device SDP information. Data structure is UINT8[]. + /// + EfiBluetoothConfigDataTypeSdpInfo, + /// + /// Local Bluetooth device address. Data structure is BLUETOOTH_ADDRESS. + /// + EfiBluetoothConfigDataTypeBDADDR, /* Relevant for LE*/ + /// + /// Local Bluetooth discoverable state. Data structure is UINT8. (Page scan and/or Inquiry scan) + /// + EfiBluetoothConfigDataTypeDiscoverable, /* Relevant for LE*/ + /// + /// Local Bluetooth controller stored paired device list. Data structure is BLUETOOTH_ADDRESS[]. + /// + EfiBluetoothConfigDataTypeControllerStoredPairedDeviceList, + /// + /// Local available device list. Data structure is BLUETOOTH_ADDRESS[]. + /// + EfiBluetoothConfigDataTypeAvailableDeviceList, + EfiBluetoothConfigDataTypeRandomAddress, /* Relevant for LE*/ + EfiBluetoothConfigDataTypeRSSI, /* Relevant for LE*/ + /// + /// Advertisement report. Data structure is UNIT8[]. + /// + EfiBluetoothConfigDataTypeAdvertisementData, /* Relevant for LE*/ + EfiBluetoothConfigDataTypeIoCapability, /* Relevant for LE*/ + EfiBluetoothConfigDataTypeOOBDataFlag, /* Relevant for LE*/ + /// + /// KeyType of Authentication Requirements flag of local + /// device as UINT8, indicating requested security properties. + /// See Bluetooth specification 3.H.3.5.1. BIT0: MITM, BIT1:SC. + /// + EfiBluetoothConfigDataTypeKeyType, /* Relevant for LE*/ + EfiBluetoothConfigDataTypeEncKeySize, /* Relevant for LE*/ + EfiBluetoothConfigDataTypeMax, +} EFI_BLUETOOTH_CONFIG_DATA_TYPE; + +/// +/// EFI_BLUETOOTH_PIN_CALLBACK_TYPE. +/// +typedef enum { + /// + /// For SSP - passkey entry. Input buffer is Passkey (4 bytes). No output buffer. + /// See Bluetooth HCI command for detail. + /// + EfiBluetoothCallbackTypeUserPasskeyNotification, + /// + /// For SSP - just work and numeric comparison. Input buffer is numeric value (4 bytes). + /// Output buffer is BOOLEAN (1 byte). See Bluetooth HCI command for detail. + /// + EfiBluetoothCallbackTypeUserConfirmationRequest, + /// + /// For SSP - OOB. See Bluetooth HCI command for detail. + /// + EfiBluetoothCallbackTypeOOBDataRequest, + /// + /// For legacy paring. No input buffer. Output buffer is PIN code( <= 16 bytes). + /// See Bluetooth HCI command for detail. + /// + EfiBluetoothCallbackTypePinCodeRequest, + EfiBluetoothCallbackTypeMax +} EFI_BLUETOOTH_PIN_CALLBACK_TYPE; + +/// +/// EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE. +/// +typedef enum { + /// + /// This callback is called when Bluetooth receive Disconnection_Complete event. Input buffer is Event + /// Parameters of Disconnection_Complete Event defined in Bluetooth specification. + /// + EfiBluetoothConnCallbackTypeDisconnected, + /// + /// This callback is called when Bluetooth receive Connection_Complete event. Input buffer is Event + /// Parameters of Connection_Complete Event defined in Bluetooth specification. + /// + EfiBluetoothConnCallbackTypeConnected, + /// + /// This callback is called when Bluetooth receive Authentication_Complete event. Input buffer is Event + /// Parameters of Authentication_Complete Event defined in Bluetooth specification. + /// + EfiBluetoothConnCallbackTypeAuthenticated, + /// + /// This callback is called when Bluetooth receive Encryption_Change event. Input buffer is Event + /// Parameters of Encryption_Change Event defined in Bluetooth specification. + /// + EfiBluetoothConnCallbackTypeEncrypted +} EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE; + + +/** + Initialize Bluetooth host controller and local device. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + + @retval EFI_SUCCESS The Bluetooth host controller and local device is initialized successfully. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to initialize the Bluetooth host controller + and local device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_INIT)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This + ); + +/** + Callback function, it is called if a Bluetooth device is found during scan process. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Context Context passed from scan request. + @param CallbackInfo Data related to scan result. NULL CallbackInfo means scan complete. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_SCAN_CALLBACK_FUNCTION) ( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN EFI_BLUETOOTH_SCAN_CALLBACK_INFORMATION *CallbackInfo + ); + +/** + Scan Bluetooth device. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param ReScan If TRUE, a new scan request is submitted no matter there is scan result before. + If FALSE and there is scan result, the previous scan result is returned and no scan request + is submitted. + @param ScanType Bluetooth scan type, Inquiry and/or Page. See Bluetooth specification for detail. + @param Callback The callback function. This function is called if a Bluetooth device is found during scan + process. + @param Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The Bluetooth scan request is submitted. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to scan the Bluetooth device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_SCAN)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN BOOLEAN ReScan, + IN UINT8 ScanType, + IN EFI_BLUETOOTH_CONFIG_SCAN_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/** + Connect a Bluetooth device. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param BD_ADDR The address of Bluetooth device to be connected. + + @retval EFI_SUCCESS The Bluetooth device is connected successfully. + @retval EFI_ALREADY_STARTED The Bluetooth device is already connected. + @retval EFI_NOT_FOUND The Bluetooth device is not found. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to connect the Bluetooth device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_CONNECT)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN BLUETOOTH_ADDRESS *BD_ADDR + ); + +/** + Disconnect a Bluetooth device. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param BD_ADDR The address of Bluetooth device to be connected. + @param Reason Bluetooth disconnect reason. See Bluetooth specification for detail. + + @retval EFI_SUCCESS The Bluetooth device is disconnected successfully. + @retval EFI_NOT_STARTED The Bluetooth device is not connected. + @retval EFI_NOT_FOUND The Bluetooth device is not found. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to disconnect the Bluetooth device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_DISCONNECT)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN BLUETOOTH_ADDRESS *BD_ADDR, + IN UINT8 Reason + ); + +/** + Get Bluetooth configuration data. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param DataType Configuration data type. + @param DataSize On input, indicates the size, in bytes, of the data buffer specified by Data. + On output, indicates the amount of data actually returned. + @param Data A pointer to the buffer of data that will be returned. + + @retval EFI_SUCCESS The Bluetooth configuration data is returned successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataSize is NULL. + - *DataSize is not 0 and Data is NULL. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The DataType is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the buffer. + *DataSize has been updated with the size needed to complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_GET_DATA)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_DATA_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT VOID *Data + ); + +/** + Set Bluetooth configuration data. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param DataType Configuration data type. + @param DataSize Indicates the size, in bytes, of the data buffer specified by Data. + @param Data A pointer to the buffer of data that will be set. + + @retval EFI_SUCCESS The Bluetooth configuration data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataSize is 0. + - Data is NULL. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_BUFFER_TOO_SMALL Cannot set configuration data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_SET_DATA)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_DATA_TYPE DataType, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Get remove Bluetooth device configuration data. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param DataType Configuration data type. + @param BDAddr Remote Bluetooth device address. + @param DataSize On input, indicates the size, in bytes, of the data buffer specified by Data. + On output, indicates the amount of data actually returned. + @param Data A pointer to the buffer of data that will be returned. + + @retval EFI_SUCCESS The remote Bluetooth device configuration data is returned successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataSize is NULL. + - *DataSize is not 0 and Data is NULL. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The DataType is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the buffer. + *DataSize has been updated with the size needed to complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_GET_REMOTE_DATA)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_DATA_TYPE DataType, + IN BLUETOOTH_ADDRESS *BDAddr, + IN OUT UINTN *DataSize, + IN OUT VOID *Data + ); + +/** + The callback function for PIN code. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Context Context passed from registration. + @param CallbackType Callback type in EFI_BLUETOOTH_PIN_CALLBACK_TYPE. + @param InputBuffer A pointer to the buffer of data that is input from callback caller. + @param InputBufferSize Indicates the size, in bytes, of the data buffer specified by InputBuffer. + @param OutputBuffer A pointer to the buffer of data that will be output from callback callee. + Callee allocates this buffer by using EFI Boot Service AllocatePool(). + @param OutputBufferSize Indicates the size, in bytes, of the data buffer specified by OutputBuffer. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_PIN_CALLBACK_FUNCTION)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN EFI_BLUETOOTH_PIN_CALLBACK_TYPE CallbackType, + IN VOID *InputBuffer, + IN UINTN InputBufferSize, + OUT VOID **OutputBuffer, + OUT UINTN *OutputBufferSize + ); + +/** + Register PIN callback function. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Callback The callback function. NULL means unregister. + @param Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The PIN callback function is registered successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_PIN_CALLBACK)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_REGISTER_PIN_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/** + The callback function to get link key. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Context Context passed from registration. + @param BDAddr A pointer to Bluetooth device address. + @param LinkKey A pointer to the buffer of link key. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_GET_LINK_KEY_CALLBACK_FUNCTION)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN BLUETOOTH_ADDRESS *BDAddr, + OUT UINT8 LinkKey[BLUETOOTH_HCI_LINK_KEY_SIZE] + ); + +/** + Register get link key callback function. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Callback The callback function. NULL means unregister. + @param Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The link key callback function is registered successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_GET_LINK_KEY_CALLBACK)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_REGISTER_GET_LINK_KEY_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/** + The callback function to set link key. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Context Context passed from registration. + @param BDAddr A pointer to Bluetooth device address. + @param LinkKey A pointer to the buffer of link key. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_SET_LINK_KEY_CALLBACK_FUNCTION)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN BLUETOOTH_ADDRESS *BDAddr, + IN UINT8 LinkKey[BLUETOOTH_HCI_LINK_KEY_SIZE] + ); + +/** + Register set link key callback function. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Callback The callback function. NULL means unregister. + @param Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The link key callback function is registered successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_SET_LINK_KEY_CALLBACK)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_REGISTER_SET_LINK_KEY_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/** + The callback function. It is called after connect completed. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Context Context passed from registration. + @param CallbackType Callback type in EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE. + @param BDAddr A pointer to Bluetooth device address. + @param InputBuffer A pointer to the buffer of data that is input from callback caller. + @param InputBufferSize Indicates the size, in bytes, of the data buffer specified by InputBuffer. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_CONNECT_COMPLETE_CALLBACK_FUNCTION)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE CallbackType, + IN BLUETOOTH_ADDRESS *BDAddr, + IN VOID *InputBuffer, + IN UINTN InputBufferSize + ); + +/** + Register link connect complete callback function. + + @param This Pointer to the EFI_BLUETOOTH_CONFIG_PROTOCOL instance. + @param Callback The callback function. NULL means unregister. + @param Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The link connect complete callback function is registered successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_CONFIG_REGISTER_CONNECT_COMPLETE_CALLBACK)( + IN EFI_BLUETOOTH_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_REGISTER_CONNECT_COMPLETE_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +/// +/// This protocol abstracts user interface configuration for Bluetooth device. +/// +struct _EFI_BLUETOOTH_CONFIG_PROTOCOL { + EFI_BLUETOOTH_CONFIG_INIT Init; + EFI_BLUETOOTH_CONFIG_SCAN Scan; + EFI_BLUETOOTH_CONFIG_CONNECT Connect; + EFI_BLUETOOTH_CONFIG_DISCONNECT Disconnect; + EFI_BLUETOOTH_CONFIG_GET_DATA GetData; + EFI_BLUETOOTH_CONFIG_SET_DATA SetData; + EFI_BLUETOOTH_CONFIG_GET_REMOTE_DATA GetRemoteData; + EFI_BLUETOOTH_CONFIG_REGISTER_PIN_CALLBACK RegisterPinCallback; + EFI_BLUETOOTH_CONFIG_REGISTER_GET_LINK_KEY_CALLBACK RegisterGetLinkKeyCallback; + EFI_BLUETOOTH_CONFIG_REGISTER_SET_LINK_KEY_CALLBACK RegisterSetLinkKeyCallback; + EFI_BLUETOOTH_CONFIG_REGISTER_CONNECT_COMPLETE_CALLBACK RegisterLinkConnectCompleteCallback; +}; + +extern EFI_GUID gEfiBluetoothConfigProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothHc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothHc.h new file mode 100644 index 0000000..72ce89a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothHc.h @@ -0,0 +1,424 @@ +/** @file + EFI Bluetooth Host Controller Protocol as defined in UEFI 2.5. + This protocol abstracts the Bluetooth host controller layer message transmit and receive. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_BLUETOOTH_HC_PROTOCOL_H__ +#define __EFI_BLUETOOTH_HC_PROTOCOL_H__ + +#define EFI_BLUETOOTH_HC_PROTOCOL_GUID \ + { \ + 0xb3930571, 0xbeba, 0x4fc5, { 0x92, 0x3, 0x94, 0x27, 0x24, 0x2e, 0x6a, 0x43 } \ + } + +typedef struct _EFI_BLUETOOTH_HC_PROTOCOL EFI_BLUETOOTH_HC_PROTOCOL; + +/** + Send HCI command packet. + + The SendCommand() function sends HCI command packet. Buffer holds the whole HCI + command packet, including OpCode, OCF, OGF, parameter length, and parameters. When + this function is returned, it just means the HCI command packet is sent, it does not mean + the command is success or complete. Caller might need to wait a command status event + to know the command status, or wait a command complete event to know if the + command is completed. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in,out] BufferSize On input, indicates the size, in bytes, of the data buffer + specified by Buffer. On output, indicates the amount of + data actually transferred. + @param[in] Buffer A pointer to the buffer of data that will be transmitted to + Bluetooth host controller. + @param[in] Timeout Indicating the transfer should be completed within this + time frame. The units are in milliseconds. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The HCI command packet is sent successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is 0. + Buffer is NULL. + @retval EFI_TIMEOUT Sending HCI command packet fail due to timeout. + @retval EFI_DEVICE_ERROR Sending HCI command packet fail due to host controller or device + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_SEND_COMMAND)( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive HCI event packet. + + The ReceiveEvent() function receives HCI event packet. Buffer holds the whole HCI event + packet, including EventCode, parameter length, and parameters. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in,out] BufferSize On input, indicates the size, in bytes, of the data buffer + specified by Buffer. On output, indicates the amount of + data actually transferred. + @param[out] Buffer A pointer to the buffer of data that will be received from + Bluetooth host controller. + @param[in] Timeout Indicating the transfer should be completed within this + time frame. The units are in milliseconds. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The HCI event packet is received successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is 0. + Buffer is NULL. + @retval EFI_TIMEOUT Receiving HCI event packet fail due to timeout. + @retval EFI_DEVICE_ERROR Receiving HCI event packet fail due to host controller or device + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_RECEIVE_EVENT)( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + IN UINTN Timeout + ); + +/** + The async callback of AsyncReceiveEvent(). + + @param[in] Data Data received via asynchronous transfer. + @param[in] DataLength The length of Data in bytes, received via asynchronous + transfer. + @param[in] Context Context passed from asynchronous transfer request. + + @retval EFI_SUCCESS The callback does execute successfully. + @retval Others The callback doesn't execute successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_ASYNC_FUNC_CALLBACK) ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context + ); + +/** + Receive HCI event packet in non-blocking way. + + The AsyncReceiveEvent() function receives HCI event packet in non-blocking way. Data + in Callback function holds the whole HCI event packet, including EventCode, parameter + length, and parameters. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted. If FALSE, the + request is deleted. + @param[in] PollingInterval Indicates the periodic rate, in milliseconds, that the + transfer is to be executed. + @param[in] DataLength Specifies the length, in bytes, of the data to be received. + @param[in] Callback The callback function. This function is called if the + asynchronous transfer is completed. + @param[in] Context Data passed into Callback function. This is optional + parameter and may be NULL. + + @retval EFI_SUCCESS The HCI asynchronous receive request is submitted successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + DataLength is 0. + If IsNewTransfer is TRUE, and an asynchronous receive + request already exists. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_ASYNC_RECEIVE_EVENT) ( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_BLUETOOTH_HC_ASYNC_FUNC_CALLBACK Callback, + IN VOID *Context + ); + +/** + Send HCI ACL data packet. + + The SendACLData() function sends HCI ACL data packet. Buffer holds the whole HCI ACL + data packet, including Handle, PB flag, BC flag, data length, and data. + + The SendACLData() function and ReceiveACLData() function just send and receive data + payload from application layer. In order to protect the payload data, the Bluetooth bus is + required to call HCI_Set_Connection_Encryption command to enable hardware based + encryption after authentication completed, according to pairing mode and host + capability. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in, out] BufferSize On input, indicates the size, in bytes, of the data buffer + specified by Buffer. On output, indicates the amount of + data actually transferred. + @param[in] Buffer A pointer to the buffer of data that will be transmitted to + Bluetooth host controller. + @param[in] Timeout Indicating the transfer should be completed within this + time frame. The units are in milliseconds. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The HCI ACL data packet is sent successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is 0. + Buffer is NULL. + @retval EFI_TIMEOUT Sending HCI ACL data packet fail due to timeout. + @retval EFI_DEVICE_ERROR Sending HCI ACL data packet fail due to host controller or device + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_SEND_ACL_DATA)( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive HCI ACL data packet. + + The ReceiveACLData() function receives HCI ACL data packet. Buffer holds the whole HCI + ACL data packet, including Handle, PB flag, BC flag, data length, and data. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in, out] BufferSize On input, indicates the size, in bytes, of the data buffer + specified by Buffer. On output, indicates the amount of + data actually transferred. + @param[out] Buffer A pointer to the buffer of data that will be received from + Bluetooth host controller. + @param[in] Timeout Indicating the transfer should be completed within this + time frame. The units are in milliseconds. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The HCI ACL data packet is received successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is 0. + Buffer is NULL. + @retval EFI_TIMEOUT Receiving HCI ACL data packet fail due to timeout. + @retval EFI_DEVICE_ERROR Receiving HCI ACL data packet fail due to host controller or device + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_RECEIVE_ACL_DATA)( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive HCI ACL data packet in non-blocking way. + + The AsyncReceiveACLData() function receives HCI ACL data packet in non-blocking way. + Data in Callback holds the whole HCI ACL data packet, including Handle, PB flag, BC flag, + data length, and data. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted. If FALSE, the + request is deleted. + @param[in] PollingInterval Indicates the periodic rate, in milliseconds, that the + transfer is to be executed. + @param[in] DataLength Specifies the length, in bytes, of the data to be received. + @param[in] Callback The callback function. This function is called if the + asynchronous transfer is completed. + @param[in] Context Data passed into Callback function. This is optional + parameter and may be NULL. + + @retval EFI_SUCCESS The HCI asynchronous receive request is submitted successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + DataLength is 0. + If IsNewTransfer is TRUE, and an asynchronous receive + request already exists. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_ASYNC_RECEIVE_ACL_DATA) ( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_BLUETOOTH_HC_ASYNC_FUNC_CALLBACK Callback, + IN VOID *Context + ); + +/** + Send HCI SCO data packet. + + The SendSCOData() function sends HCI SCO data packet. Buffer holds the whole HCI SCO + data packet, including ConnectionHandle, PacketStatus flag, data length, and data. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in,out] BufferSize On input, indicates the size, in bytes, of the data buffer + specified by Buffer. On output, indicates the amount of + data actually transferred. + @param[in] Buffer A pointer to the buffer of data that will be transmitted to + Bluetooth host controller. + @param[in] Timeout Indicating the transfer should be completed within this + time frame. The units are in milliseconds. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The HCI SCO data packet is sent successfully. + @retval EFI_UNSUPPORTED The implementation does not support HCI SCO transfer. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is 0. + Buffer is NULL. + @retval EFI_TIMEOUT Sending HCI SCO data packet fail due to timeout. + @retval EFI_DEVICE_ERROR Sending HCI SCO data packet fail due to host controller or device + error. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_SEND_SCO_DATA)( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive HCI SCO data packet. + + The ReceiveSCOData() function receives HCI SCO data packet. Buffer holds the whole HCI + SCO data packet, including ConnectionHandle, PacketStatus flag, data length, and data. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in,out] BufferSize On input, indicates the size, in bytes, of the data buffer + specified by Buffer. On output, indicates the amount of + data actually transferred. + @param[out] Buffer A pointer to the buffer of data that will be received from + Bluetooth host controller. + @param[in] Timeout Indicating the transfer should be completed within this + time frame. The units are in milliseconds. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The HCI SCO data packet is received successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is 0. + Buffer is NULL. + @retval EFI_TIMEOUT Receiving HCI SCO data packet fail due to timeout. + @retval EFI_DEVICE_ERROR Receiving HCI SCO data packet fail due to host controller or device + error. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_RECEIVE_SCO_DATA)( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive HCI SCO data packet in non-blocking way. + + The AsyncReceiveSCOData() function receives HCI SCO data packet in non-blocking way. + Data in Callback holds the whole HCI SCO data packet, including ConnectionHandle, + PacketStatus flag, data length, and data. + + @param[in] This Pointer to the EFI_BLUETOOTH_HC_PROTOCOL instance. + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted. If FALSE, the + request is deleted. + @param[in] PollingInterval Indicates the periodic rate, in milliseconds, that the + transfer is to be executed. + @param[in] DataLength Specifies the length, in bytes, of the data to be received. + @param[in] Callback The callback function. This function is called if the + asynchronous transfer is completed. + @param[in] Context Data passed into Callback function. This is optional + parameter and may be NULL. + + @retval EFI_SUCCESS The HCI asynchronous receive request is submitted successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + DataLength is 0. + If IsNewTransfer is TRUE, and an asynchronous receive + request already exists. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_HC_ASYNC_RECEIVE_SCO_DATA) ( + IN EFI_BLUETOOTH_HC_PROTOCOL *This, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_BLUETOOTH_HC_ASYNC_FUNC_CALLBACK Callback, + IN VOID *Context + ); + +// +// The EFI_BLUETOOTH_HC_PROTOCOL is used to transmit or receive HCI layer data packets. +// +struct _EFI_BLUETOOTH_HC_PROTOCOL { + // + // Send HCI command packet. + // + EFI_BLUETOOTH_HC_SEND_COMMAND SendCommand; + // + // Receive HCI event packets. + // + EFI_BLUETOOTH_HC_RECEIVE_EVENT ReceiveEvent; + // + // Non-blocking receive HCI event packets. + // + EFI_BLUETOOTH_HC_ASYNC_RECEIVE_EVENT AsyncReceiveEvent; + // + // Send HCI ACL (asynchronous connection-oriented) data packets. + // + EFI_BLUETOOTH_HC_SEND_ACL_DATA SendACLData; + // + // Receive HCI ACL data packets. + // + EFI_BLUETOOTH_HC_RECEIVE_ACL_DATA ReceiveACLData; + // + // Non-blocking receive HCI ACL data packets. + // + EFI_BLUETOOTH_HC_ASYNC_RECEIVE_ACL_DATA AsyncReceiveACLData; + // + // Send HCI synchronous (SCO and eSCO) data packets. + // + EFI_BLUETOOTH_HC_SEND_SCO_DATA SendSCOData; + // + // Receive HCI synchronous data packets. + // + EFI_BLUETOOTH_HC_RECEIVE_SCO_DATA ReceiveSCOData; + // + // Non-blocking receive HCI synchronous data packets. + // + EFI_BLUETOOTH_HC_ASYNC_RECEIVE_SCO_DATA AsyncReceiveSCOData; +}; + +extern EFI_GUID gEfiBluetoothHcProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothIo.h new file mode 100644 index 0000000..a0463ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothIo.h @@ -0,0 +1,417 @@ +/** @file + EFI Bluetooth IO Service Binding Protocol as defined in UEFI 2.5. + EFI Bluetooth IO Protocol as defined in UEFI 2.5. + The EFI Bluetooth IO Service Binding Protocol is used to locate EFI Bluetooth IO Protocol drivers to + create and destroy child of the driver to communicate with other Bluetooth device by using Bluetooth IO protocol. + + Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_BLUETOOTH_IO_PROTOCOL_H__ +#define __EFI_BLUETOOTH_IO_PROTOCOL_H__ + +#include + +#define EFI_BLUETOOTH_IO_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x388278d3, 0x7b85, 0x42f0, { 0xab, 0xa9, 0xfb, 0x4b, 0xfd, 0x69, 0xf5, 0xab } \ + } + +#define EFI_BLUETOOTH_IO_PROTOCOL_GUID \ + { \ + 0x467313de, 0x4e30, 0x43f1, { 0x94, 0x3e, 0x32, 0x3f, 0x89, 0x84, 0x5d, 0xb5 } \ + } + +typedef struct _EFI_BLUETOOTH_IO_PROTOCOL EFI_BLUETOOTH_IO_PROTOCOL; + +/// +/// EFI_BLUETOOTH_DEVICE_INFO +/// +typedef struct { + /// + /// The version of the structure + /// + UINT32 Version; + /// + /// 48bit Bluetooth device address. + /// + BLUETOOTH_ADDRESS BD_ADDR; + /// + /// Bluetooth PageScanRepetitionMode. See Bluetooth specification for detail. + /// + UINT8 PageScanRepetitionMode; + /// + /// Bluetooth ClassOfDevice. See Bluetooth specification for detail. + /// + BLUETOOTH_CLASS_OF_DEVICE ClassOfDevice; + /// + /// Bluetooth CloseOffset. See Bluetooth specification for detail. + /// + UINT16 ClockOffset; + /// + /// Bluetooth RSSI. See Bluetooth specification for detail. + /// + UINT8 RSSI; + /// + /// Bluetooth ExtendedInquiryResponse. See Bluetooth specification for detail. + /// + UINT8 ExtendedInquiryResponse[240]; +} EFI_BLUETOOTH_DEVICE_INFO; + +/** + Get Bluetooth device information. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[out] DeviceInfoSize A pointer to the size, in bytes, of the DeviceInfo buffer. + @param[out] DeviceInfo A pointer to a callee allocated buffer that returns Bluetooth device information. + + @retval EFI_SUCCESS The Bluetooth device information is returned successfully. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the Bluetooth device information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_GET_DEVICE_INFO)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + OUT UINTN *DeviceInfoSize, + OUT VOID **DeviceInfo + ); + +/** + Get Bluetooth SDP information. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[out] SdpInfoSize A pointer to the size, in bytes, of the SdpInfo buffer. + @param[out] SdpInfo A pointer to a callee allocated buffer that returns Bluetooth SDP information. + + @retval EFI_SUCCESS The Bluetooth device information is returned successfully. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the Bluetooth SDP information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_GET_SDP_INFO)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + OUT UINTN *SdpInfoSize, + OUT VOID **SdpInfo + ); + +/** + Send L2CAP message (including L2CAP header). + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in, out] BufferSize On input, indicates the size, in bytes, of the data buffer specified by Buffer. + On output, indicates the amount of data actually transferred. + @param[in] Buffer A pointer to the buffer of data that will be transmitted to Bluetooth L2CAP layer. + @param[in] Timeout Indicating the transfer should be completed within this time frame. The units are in + milliseconds. If Timeout is 0, then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The L2CAP message is sent successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - BufferSize is NULL. + - *BufferSize is 0. + - Buffer is NULL. + @retval EFI_TIMEOUT Sending L2CAP message fail due to timeout. + @retval EFI_DEVICE_ERROR Sending L2CAP message fail due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_RAW_SEND)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive L2CAP message (including L2CAP header). + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in] BufferSize On input, indicates the size, in bytes, of the data buffer specified by Buffer. + On output, indicates the amount of data actually transferred. + @param[out] Buffer A pointer to the buffer of data that will be received from Bluetooth L2CAP layer. + @param[in] Timeout Indicating the transfer should be completed within this time frame. The units are in + milliseconds. If Timeout is 0, then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The L2CAP message is received successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - BufferSize is NULL. + - *BufferSize is 0. + - Buffer is NULL. + @retval EFI_TIMEOUT Receiving L2CAP message fail due to timeout. + @retval EFI_DEVICE_ERROR Receiving L2CAP message fail due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_RAW_RECEIVE)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + IN UINTN Timeout + ); + +/** + Callback function, it is called when asynchronous transfer is completed. + + @param[in] ChannelID Bluetooth L2CAP message channel ID. + @param[in] Data Data received via asynchronous transfer. + @param[in] DataLength The length of Data in bytes, received via asynchronous transfer. + @param[in] Context Context passed from asynchronous transfer request. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_ASYNC_FUNC_CALLBACK) ( + IN UINT16 ChannelID, + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context + ); + +/** + Receive L2CAP message (including L2CAP header) in non-blocking way. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted. If FALSE, the request is deleted. + @param[in] PollingInterval Indicates the periodic rate, in milliseconds, that the transfer is to be executed. + @param[in] DataLength Specifies the length, in bytes, of the data to be received. + @param[in] Callback The callback function. This function is called if the asynchronous transfer is + completed. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The L2CAP asynchronous receive request is submitted successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataLength is 0. + - If IsNewTransfer is TRUE, and an asynchronous receive request already exists. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_RAW_ASYNC_RECEIVE)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_BLUETOOTH_IO_ASYNC_FUNC_CALLBACK Callback, + IN VOID *Context + ); + +/** + Send L2CAP message (excluding L2CAP header) to a specific channel. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in] Handle A handle created by EFI_BLUETOOTH_IO_PROTOCOL.L2CapConnect indicates which channel to send. + @param[in, out] BufferSize On input, indicates the size, in bytes, of the data buffer specified by Buffer. + On output, indicates the amount of data actually transferred. + @param[in] Buffer A pointer to the buffer of data that will be transmitted to Bluetooth L2CAP layer. + @param[in] Timeout Indicating the transfer should be completed within this time frame. The units are in + milliseconds. If Timeout is 0, then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The L2CAP message is sent successfully. + @retval EFI_NOT_FOUND Handle is invalid or not found. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - BufferSize is NULL. + - *BufferSize is 0. + - Buffer is NULL. + @retval EFI_TIMEOUT Sending L2CAP message fail due to timeout. + @retval EFI_DEVICE_ERROR Sending L2CAP message fail due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_SEND)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer, + IN UINTN Timeout + ); + +/** + Receive L2CAP message (excluding L2CAP header) from a specific channel. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in] Handle A handle created by EFI_BLUETOOTH_IO_PROTOCOL.L2CapConnect indicates which channel to receive. + @param[out] BufferSize Indicates the size, in bytes, of the data buffer specified by Buffer. + @param[out] Buffer A pointer to the buffer of data that will be received from Bluetooth L2CAP layer. + @param[in] Timeout Indicating the transfer should be completed within this time frame. The units are in + milliseconds. If Timeout is 0, then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + + @retval EFI_SUCCESS The L2CAP message is received successfully. + @retval EFI_NOT_FOUND Handle is invalid or not found. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - BufferSize is NULL. + - *BufferSize is 0. + - Buffer is NULL. + @retval EFI_TIMEOUT Receiving L2CAP message fail due to timeout. + @retval EFI_DEVICE_ERROR Receiving L2CAP message fail due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_RECEIVE)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN EFI_HANDLE Handle, + OUT UINTN *BufferSize, + OUT VOID **Buffer, + IN UINTN Timeout + ); + +/** + Callback function, it is called when asynchronous transfer is completed. + + @param[in] Data Data received via asynchronous transfer. + @param[in] DataLength The length of Data in bytes, received via asynchronous transfer. + @param[in] Context Context passed from asynchronous transfer request. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_CHANNEL_SERVICE_CALLBACK) ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context + ); + +/** + Receive L2CAP message (excluding L2CAP header) in non-blocking way from a specific channel. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in] Handel A handle created by EFI_BLUETOOTH_IO_PROTOCOL.L2CapConnect indicates which channel + to receive. + @param[in] Callback The callback function. This function is called if the asynchronous transfer is + completed. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The L2CAP asynchronous receive request is submitted successfully. + @retval EFI_NOT_FOUND Handle is invalid or not found. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataLength is 0. + - If an asynchronous receive request already exists on same Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_ASYNC_RECEIVE)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_BLUETOOTH_IO_CHANNEL_SERVICE_CALLBACK Callback, + IN VOID* Context + ); + +/** + Do L2CAP connection. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[out] Handel A handle to indicate this L2CAP connection. + @param[in] Psm Bluetooth PSM. See Bluetooth specification for detail. + @param[in] Mtu Bluetooth MTU. See Bluetooth specification for detail. + @param[in] Callback The callback function. This function is called whenever there is message received + in this channel. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The Bluetooth L2CAP layer connection is created successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - Handle is NULL. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to do Bluetooth L2CAP connection. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_CONNECT)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + OUT EFI_HANDLE *Handle, + IN UINT16 Psm, + IN UINT16 Mtu, + IN EFI_BLUETOOTH_IO_CHANNEL_SERVICE_CALLBACK Callback, + IN VOID *Context + ); + +/** + Do L2CAP disconnection. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[in] Handel A handle to indicate this L2CAP connection. + + @retval EFI_SUCCESS The Bluetooth L2CAP layer is disconnected successfully. + @retval EFI_NOT_FOUND Handle is invalid or not found. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to do Bluetooth L2CAP disconnection. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_DISCONNECT)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + IN EFI_HANDLE Handle + ); + +/** + Register L2CAP callback function for special channel. + + @param[in] This Pointer to the EFI_BLUETOOTH_IO_PROTOCOL instance. + @param[out] Handel A handle to indicate this L2CAP connection. + @param[in] Psm Bluetooth PSM. See Bluetooth specification for detail. + @param[in] Mtu Bluetooth MTU. See Bluetooth specification for detail. + @param[in] Callback The callback function. This function is called whenever there is message received + in this channel. NULL means unregister. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The Bluetooth L2CAP callback function is registered successfully. + @retval EFI_ALREADY_STARTED The callback function already exists when register. + @retval EFI_NOT_FOUND The callback function does not exist when unregister. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_IO_L2CAP_REGISTER_SERVICE)( + IN EFI_BLUETOOTH_IO_PROTOCOL *This, + OUT EFI_HANDLE *Handle, + IN UINT16 Psm, + IN UINT16 Mtu, + IN EFI_BLUETOOTH_IO_CHANNEL_SERVICE_CALLBACK Callback, + IN VOID *Context + ); + +/// +/// This protocol provides service for Bluetooth L2CAP (Logical Link Control and Adaptation Protocol) +/// and SDP (Service Discovery Protocol). +/// +struct _EFI_BLUETOOTH_IO_PROTOCOL { + EFI_BLUETOOTH_IO_GET_DEVICE_INFO GetDeviceInfo; + EFI_BLUETOOTH_IO_GET_SDP_INFO GetSdpInfo; + EFI_BLUETOOTH_IO_L2CAP_RAW_SEND L2CapRawSend; + EFI_BLUETOOTH_IO_L2CAP_RAW_RECEIVE L2CapRawReceive; + EFI_BLUETOOTH_IO_L2CAP_RAW_ASYNC_RECEIVE L2CapRawAsyncReceive; + EFI_BLUETOOTH_IO_L2CAP_SEND L2CapSend; + EFI_BLUETOOTH_IO_L2CAP_RECEIVE L2CapReceive; + EFI_BLUETOOTH_IO_L2CAP_ASYNC_RECEIVE L2CapAsyncReceive; + EFI_BLUETOOTH_IO_L2CAP_CONNECT L2CapConnect; + EFI_BLUETOOTH_IO_L2CAP_DISCONNECT L2CapDisconnect; + EFI_BLUETOOTH_IO_L2CAP_REGISTER_SERVICE L2CapRegisterService; +}; + +extern EFI_GUID gEfiBluetoothIoServiceBindingProtocolGuid; +extern EFI_GUID gEfiBluetoothIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothLeConfig.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothLeConfig.h new file mode 100644 index 0000000..b4f1e9b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BluetoothLeConfig.h @@ -0,0 +1,634 @@ +/** @file + EFI Bluetooth LE Config Protocol as defined in UEFI 2.7. + This protocol abstracts user interface configuration for BluetoothLe device. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __EFI_BLUETOOTH_LE_CONFIG_H__ +#define __EFI_BLUETOOTH_LE_CONFIG_H__ + +#include +#include + +#define EFI_BLUETOOTH_LE_CONFIG_PROTOCOL_GUID \ + { \ + 0x8f76da58, 0x1f99, 0x4275, { 0xa4, 0xec, 0x47, 0x56, 0x51, 0x5b, 0x1c, 0xe8 } \ + } + +typedef struct _EFI_BLUETOOTH_LE_CONFIG_PROTOCOL EFI_BLUETOOTH_LE_CONFIG_PROTOCOL; + +/** + Initialize BluetoothLE host controller and local device. + + The Init() function initializes BluetoothLE host controller and local device. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + + @retval EFI_SUCCESS The BluetoothLE host controller and local device is initialized successfully. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to initialize the BluetoothLE host controller + and local device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_INIT)( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This + ); + +typedef struct { + /// + /// The version of the structure. A value of zero represents the EFI_BLUETOOTH_LE_CONFIG_SCAN_PARAMETER + /// structure as defined here. Future version of this specification may extend this data structure in a + /// backward compatible way and increase the value of Version. + /// + UINT32 Version; + /// + /// Passive scanning or active scanning. See Bluetooth specification. + /// + UINT8 ScanType; + /// + /// Recommended scan interval to be used while performing scan. + /// + UINT16 ScanInterval; + /// + /// Recommended scan window to be used while performing a scan. + /// + UINT16 ScanWindow; + /// + /// Recommended scanning filter policy to be used while performing a scan. + /// + UINT8 ScanningFilterPolicy; + /// + /// This is one byte flag to serve as a filter to remove unneeded scan + /// result. For example, set BIT0 means scan in LE Limited Discoverable + /// Mode. Set BIT1 means scan in LE General Discoverable Mode. + /// + UINT8 AdvertisementFlagFilter; +} EFI_BLUETOOTH_LE_CONFIG_SCAN_PARAMETER; + +typedef struct{ + BLUETOOTH_LE_ADDRESS BDAddr; + BLUETOOTH_LE_ADDRESS DirectAddress; + UINT8 RemoteDeviceState; + INT8 RSSI; + UINTN AdvertisementDataSize; + VOID *AdvertisementData; +} EFI_BLUETOOTH_LE_SCAN_CALLBACK_INFORMATION; + +/** + Callback function, it is called if a BluetoothLE device is found during scan process. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Context Context passed from scan request. + @param[in] CallbackInfo Data related to scan result. NULL CallbackInfo means scan complete. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_SCAN_CALLBACK_FUNCTION) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN EFI_BLUETOOTH_LE_SCAN_CALLBACK_INFORMATION *CallbackInfo + ); + +/** + Scan BluetoothLE device. + + The Scan() function scans BluetoothLE device. When this function is returned, it just means scan + request is submitted. It does not mean scan process is started or finished. Whenever there is a + BluetoothLE device is found, the Callback function will be called. Callback function might be + called before this function returns or after this function returns + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] ReScan If TRUE, a new scan request is submitted no matter there is scan result before. + If FALSE and there is scan result, the previous scan result is returned and no scan request + is submitted. + @param[in] Timeout Duration in milliseconds for which to scan. + @param[in] ScanParameter If it is not NULL, the ScanParameter is used to perform a scan by the BluetoothLE bus driver. + If it is NULL, the default parameter is used. + @param[in] Callback The callback function. This function is called if a BluetoothLE device is found during + scan process. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The Bluetooth scan request is submitted. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to scan the BluetoothLE device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_SCAN)( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN BOOLEAN ReScan, + IN UINT32 Timeout, + IN EFI_BLUETOOTH_LE_CONFIG_SCAN_PARAMETER *ScanParameter, OPTIONAL + IN EFI_BLUETOOTH_LE_CONFIG_SCAN_CALLBACK_FUNCTION Callback, + IN VOID *Context + ); + +typedef struct { + /// + /// The version of the structure. A value of zero represents the + /// EFI_BLUETOOTH_LE_CONFIG_CONNECT_PARAMETER + /// structure as defined here. Future version of this specification may + /// extend this data structure in a backward compatible way and + /// increase the value of Version. + /// + UINT32 Version; + /// + /// Recommended scan interval to be used while performing scan before connect. + /// + UINT16 ScanInterval; + /// + /// Recommended scan window to be used while performing a connection + /// + UINT16 ScanWindow; + /// + /// Minimum allowed connection interval. Shall be less than or equal to ConnIntervalMax. + /// + UINT16 ConnIntervalMin; + /// + /// Maximum allowed connection interval. Shall be greater than or equal to ConnIntervalMin. + /// + UINT16 ConnIntervalMax; + /// + /// Slave latency for the connection in number of connection events. + /// + UINT16 ConnLatency; + /// + /// Link supervision timeout for the connection. + /// + UINT16 SupervisionTimeout; +} EFI_BLUETOOTH_LE_CONFIG_CONNECT_PARAMETER; + +/** + Connect a BluetoothLE device. + + The Connect() function connects a Bluetooth device. When this function is returned successfully, + a new EFI_BLUETOOTH_IO_PROTOCOL is created. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] AutoReconnect If TRUE, the BluetoothLE host controller needs to do an auto + reconnect. If FALSE, the BluetoothLE host controller does not do + an auto reconnect. + @param[in] DoBonding If TRUE, the BluetoothLE host controller needs to do a bonding. + If FALSE, the BluetoothLE host controller does not do a bonding. + @param[in] ConnectParameter If it is not NULL, the ConnectParameter is used to perform a + scan by the BluetoothLE bus driver. If it is NULL, the default + parameter is used. + @param[in] BD_ADDR The address of the BluetoothLE device to be connected. + + @retval EFI_SUCCESS The BluetoothLE device is connected successfully. + @retval EFI_ALREADY_STARTED The BluetoothLE device is already connected. + @retval EFI_NOT_FOUND The BluetoothLE device is not found. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to connect the BluetoothLE device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_CONNECT)( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN BOOLEAN AutoReconnect, + IN BOOLEAN DoBonding, + IN EFI_BLUETOOTH_LE_CONFIG_CONNECT_PARAMETER *ConnectParameter, OPTIONAL + IN BLUETOOTH_LE_ADDRESS *BD_ADDR + ); + +/** + Disconnect a BluetoothLE device. + + The Disconnect() function disconnects a BluetoothLE device. When this function is returned + successfully, the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL associated with this device is + destroyed and all services associated are stopped. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] BD_ADDR The address of BluetoothLE device to be connected. + @param[in] Reason Bluetooth disconnect reason. See Bluetooth specification for detail. + + @retval EFI_SUCCESS The BluetoothLE device is disconnected successfully. + @retval EFI_NOT_STARTED The BluetoothLE device is not connected. + @retval EFI_NOT_FOUND The BluetoothLE device is not found. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to disconnect the BluetoothLE device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_DISCONNECT)( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN BLUETOOTH_LE_ADDRESS *BD_ADDR, + IN UINT8 Reason + ); + +/** + Get BluetoothLE configuration data. + + The GetData() function returns BluetoothLE configuration data. For remote BluetoothLE device + configuration data, please use GetRemoteData() function with valid BD_ADDR. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] DataType Configuration data type. + @param[in, out] DataSize On input, indicates the size, in bytes, of the data buffer specified by Data. + On output, indicates the amount of data actually returned. + @param[in, out] Data A pointer to the buffer of data that will be returned. + + @retval EFI_SUCCESS The BluetoothLE configuration data is returned successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataSize is NULL. + - *DataSize is 0. + - Data is NULL. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The DataType is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_GET_DATA) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_DATA_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT VOID *Data OPTIONAL + ); + +/** + Set BluetoothLE configuration data. + + The SetData() function sets local BluetoothLE device configuration data. Not all DataType can be + set. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] DataType Configuration data type. + @param[in] DataSize Indicates the size, in bytes, of the data buffer specified by Data. + @param[in] Data A pointer to the buffer of data that will be set. + + @retval EFI_SUCCESS The BluetoothLE configuration data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataSize is 0. + - Data is NULL. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_WRITE_PROTECTED Cannot set configuration data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_SET_DATA) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_DATA_TYPE DataType, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Get remove BluetoothLE device configuration data. + + The GetRemoteData() function returns remote BluetoothLE device configuration data. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] DataType Configuration data type. + @param[in] BDAddr Remote BluetoothLE device address. + @param[in, out] DataSize On input, indicates the size, in bytes, of the data buffer specified by Data. + On output, indicates the amount of data actually returned. + @param[in, out] Data A pointer to the buffer of data that will be returned. + + @retval EFI_SUCCESS The remote BluetoothLE device configuration data is returned successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - DataSize is NULL. + - *DataSize is 0. + - Data is NULL. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The DataType is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_GET_REMOTE_DATA) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_CONFIG_DATA_TYPE DataType, + IN BLUETOOTH_LE_ADDRESS *BDAddr, + IN OUT UINTN *DataSize, + IN OUT VOID *Data + ); + +typedef enum { + /// + /// It indicates an authorization request. No data is associated with the callback + /// input. In the output data, the application should return the authorization value. + /// The data structure is BOOLEAN. TRUE means YES. FALSE means NO. + /// + EfiBluetoothSmpAuthorizationRequestEvent, + /// + /// It indicates that a passkey has been generated locally by the driver, and the same + /// passkey should be entered at the remote device. The callback input data is the + /// passkey of type UINT32, to be displayed by the application. No output data + /// should be returned. + /// + EfiBluetoothSmpPasskeyReadyEvent, + /// + /// It indicates that the driver is requesting for the passkey has been generated at + /// the remote device. No data is associated with the callback input. The output data + /// is the passkey of type UINT32, to be entered by the user. + /// + EfiBluetoothSmpPasskeyRequestEvent, + /// + /// It indicates that the driver is requesting for the passkey that has been pre-shared + /// out-of-band with the remote device. No data is associated with the callback + /// input. The output data is the stored OOB data of type UINT8[16]. + /// + EfiBluetoothSmpOOBDataRequestEvent, + /// + /// In indicates that a number have been generated locally by the bus driver, and + /// also at the remote device, and the bus driver wants to know if the two numbers + /// match. The callback input data is the number of type UINT32. The output data + /// is confirmation value of type BOOLEAN. TRUE means comparison pass. FALSE + /// means comparison fail. + /// + EfiBluetoothSmpNumericComparisonEvent, +} EFI_BLUETOOTH_LE_SMP_EVENT_DATA_TYPE; + +/** + The callback function for SMP. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Context Data passed into callback function. This is optional parameter + and may be NULL. + @param[in] BDAddr Remote BluetoothLE device address. + @param[in] EventDataType Event data type in EFI_BLUETOOTH_LE_SMP_EVENT_DATA_TYPE. + @param[in] DataSize Indicates the size, in bytes, of the data buffer specified by Data. + @param[in] Data A pointer to the buffer of data. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_SMP_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN BLUETOOTH_LE_ADDRESS *BDAddr, + IN EFI_BLUETOOTH_LE_SMP_EVENT_DATA_TYPE EventDataType, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Register Security Manager Protocol callback function for user authentication/authorization. + + The RegisterSmpAuthCallback() function register Security Manager Protocol callback + function for user authentication/authorization. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Callback Callback function for user authentication/authorization. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The SMP callback function is registered successfully. + @retval EFI_ALREADY_STARTED A callback function is already registered on the same attribute + opcode and attribute handle, when the Callback is not NULL. + @retval EFI_NOT_STARTED A callback function is not registered on the same attribute opcode + and attribute handle, when the Callback is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_REGISTER_SMP_AUTH_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_LE_SMP_CALLBACK Callback, + IN VOID *Context + ); + +/** + Send user authentication/authorization to remote device. + + The SendSmpAuthData() function sends user authentication/authorization to remote device. It + should be used to send these information after the caller gets the request data from the callback + function by RegisterSmpAuthCallback(). + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] BDAddr Remote BluetoothLE device address. + @param[in] EventDataType Event data type in EFI_BLUETOOTH_LE_SMP_EVENT_DATA_TYPE. + @param[in] DataSize The size of Data in bytes, of the data buffer specified by Data. + @param[in] Data A pointer to the buffer of data that will be sent. The data format + depends on the type of SMP event data being responded to. + + @retval EFI_SUCCESS The SMP authorization data is sent successfully. + @retval EFI_NOT_READY SMP is not in the correct state to receive the auth data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_SEND_SMP_AUTH_DATA) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN BLUETOOTH_LE_ADDRESS *BDAddr, + IN EFI_BLUETOOTH_LE_SMP_EVENT_DATA_TYPE EventDataType, + IN UINTN DataSize, + IN VOID *Data + ); + +typedef enum { + // For local device only + EfiBluetoothSmpLocalIR, /* If Key hierarchy is supported */ + EfiBluetoothSmpLocalER, /* If Key hierarchy is supported */ + EfiBluetoothSmpLocalDHK, /* If Key hierarchy is supported. OPTIONAL */ + // For peer specific + EfiBluetoothSmpKeysDistributed = 0x1000, + EfiBluetoothSmpKeySize, + EfiBluetoothSmpKeyType, + EfiBluetoothSmpPeerLTK, + EfiBluetoothSmpPeerIRK, + EfiBluetoothSmpPeerCSRK, + EfiBluetoothSmpPeerRand, + EfiBluetoothSmpPeerEDIV, + EfiBluetoothSmpPeerSignCounter, + EfiBluetoothSmpLocalLTK, /* If Key hierarchy not supported */ + EfiBluetoothSmpLocalIRK, /* If Key hierarchy not supported */ + EfiBluetoothSmpLocalCSRK, /* If Key hierarchy not supported */ + EfiBluetoothSmpLocalSignCounter, + EfiBluetoothSmpLocalDIV, +} EFI_BLUETOOTH_LE_SMP_DATA_TYPE; + +/** + The callback function to get SMP data. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Context Data passed into callback function. This is optional parameter + and may be NULL. + @param[in] BDAddr Remote BluetoothLE device address. For Local device setting, it + should be NULL. + @param[in] DataType Data type in EFI_BLUETOOTH_LE_SMP_DATA_TYPE. + @param[in, out] DataSize On input, indicates the size, in bytes, of the data buffer specified + by Data. On output, indicates the amount of data actually returned. + @param[out] Data A pointer to the buffer of data that will be returned. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_BLUETOOTH_LE_CONFIG_SMP_GET_DATA_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN BLUETOOTH_LE_ADDRESS *BDAddr, + IN EFI_BLUETOOTH_LE_SMP_DATA_TYPE DataType, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + Register a callback function to get SMP related data. + + The RegisterSmpGetDataCallback() function registers a callback function to get SMP related data. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Callback Callback function for SMP get data. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The SMP get data callback function is registered successfully. + @retval EFI_ALREADY_STARTED A callback function is already registered on the same attribute + opcode and attribute handle, when the Callback is not NULL. + @retval EFI_NOT_STARTED A callback function is not registered on the same attribute opcode + and attribute handle, when the Callback is NULL +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_BLUETOOTH_LE_CONFIG_REGISTER_SMP_GET_DATA_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_LE_CONFIG_SMP_GET_DATA_CALLBACK Callback, + IN VOID *Context + ); + +/** + The callback function to set SMP data. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Context Data passed into callback function. This is optional parameter + and may be NULL. + @param[in] BDAddr Remote BluetoothLE device address. + @param[in] DataType Data type in EFI_BLUETOOTH_LE_SMP_DATA_TYPE. + @param[in] DataSize Indicates the size, in bytes, of the data buffer specified by Data. + @param[in] Data A pointer to the buffer of data. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_BLUETOOTH_LE_CONFIG_SMP_SET_DATA_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN BLUETOOTH_LE_ADDRESS *BDAddr, + IN EFI_BLUETOOTH_LE_SMP_DATA_TYPE Type, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Register a callback function to set SMP related data. + + The RegisterSmpSetDataCallback() function registers a callback function to set SMP related data. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Callback Callback function for SMP set data. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The SMP set data callback function is registered successfully. + @retval EFI_ALREADY_STARTED A callback function is already registered on the same attribute + opcode and attribute handle, when the Callback is not NULL. + @retval EFI_NOT_STARTED A callback function is not registered on the same attribute opcode + and attribute handle, when the Callback is NULL +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_BLUETOOTH_LE_CONFIG_REGISTER_SMP_SET_DATA_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_LE_CONFIG_SMP_SET_DATA_CALLBACK Callback, + IN VOID *Context + ); + +/** + The callback function to hook connect complete event. + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Context Data passed into callback function. This is optional parameter + and may be NULL. + @param[in] CallbackType The value defined in EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE. + @param[in] BDAddr Remote BluetoothLE device address. + @param[in] InputBuffer A pointer to the buffer of data that is input from callback caller. + @param[in] InputBufferSize Indicates the size, in bytes, of the data buffer specified by InputBuffer. + + @retval EFI_SUCCESS The callback function complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_CONNECT_COMPLETE_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN VOID *Context, + IN EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE CallbackType, + IN BLUETOOTH_LE_ADDRESS *BDAddr, + IN VOID *InputBuffer, + IN UINTN InputBufferSize + ); + +/** + Register link connect complete callback function. + + The RegisterLinkConnectCompleteCallback() function registers Bluetooth link connect + complete callback function. The Bluetooth Configuration driver may call + RegisterLinkConnectCompleteCallback() to register a callback function. During pairing, + Bluetooth bus driver must trigger this callback function to report device state, if it is registered. + Then Bluetooth Configuration driver will get information on device connection, according to + CallbackType defined by EFI_BLUETOOTH_CONNECT_COMPLETE_CALLBACK_TYPE + + @param[in] This Pointer to the EFI_BLUETOOTH_LE_CONFIG_PROTOCOL instance. + @param[in] Callback The callback function. NULL means unregister. + @param[in] Context Data passed into Callback function. This is optional parameter and may be NULL. + + @retval EFI_SUCCESS The link connect complete callback function is registered successfully. + @retval EFI_ALREADY_STARTED A callback function is already registered on the same attribute + opcode and attribute handle, when the Callback is not NULL. + @retval EFI_NOT_STARTED A callback function is not registered on the same attribute opcode + and attribute handle, when the Callback is NULL +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLUETOOTH_LE_CONFIG_REGISTER_CONNECT_COMPLETE_CALLBACK) ( + IN EFI_BLUETOOTH_LE_CONFIG_PROTOCOL *This, + IN EFI_BLUETOOTH_LE_CONFIG_CONNECT_COMPLETE_CALLBACK Callback, + IN VOID *Context + ); + +/// +/// This protocol abstracts user interface configuration for BluetoothLe device. +/// +struct _EFI_BLUETOOTH_LE_CONFIG_PROTOCOL { + EFI_BLUETOOTH_LE_CONFIG_INIT Init; + EFI_BLUETOOTH_LE_CONFIG_SCAN Scan; + EFI_BLUETOOTH_LE_CONFIG_CONNECT Connect; + EFI_BLUETOOTH_LE_CONFIG_DISCONNECT Disconnect; + EFI_BLUETOOTH_LE_CONFIG_GET_DATA GetData; + EFI_BLUETOOTH_LE_CONFIG_SET_DATA SetData; + EFI_BLUETOOTH_LE_CONFIG_GET_REMOTE_DATA GetRemoteData; + EFI_BLUETOOTH_LE_REGISTER_SMP_AUTH_CALLBACK RegisterSmpAuthCallback; + EFI_BLUETOOTH_LE_SEND_SMP_AUTH_DATA SendSmpAuthData; + EFI_BLUETOOTH_LE_CONFIG_REGISTER_SMP_GET_DATA_CALLBACK RegisterSmpGetDataCallback; + EFI_BLUETOOTH_LE_CONFIG_REGISTER_SMP_SET_DATA_CALLBACK RegisterSmpSetDataCallback; + EFI_BLUETOOTH_LE_CONFIG_REGISTER_CONNECT_COMPLETE_CALLBACK RegisterLinkConnectCompleteCallback; +}; + +extern EFI_GUID gEfiBluetoothLeConfigProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BootManagerPolicy.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BootManagerPolicy.h new file mode 100644 index 0000000..a368b69 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BootManagerPolicy.h @@ -0,0 +1,138 @@ +/** @file + Boot Manager Policy Protocol as defined in UEFI Specification. + + This protocol is used by EFI Applications to request the UEFI Boot Manager + to connect devices using platform policy. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __BOOT_MANAGER_POLICY_H__ +#define __BOOT_MANAGER_POLICY_H__ + +#define EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID \ + { \ + 0xFEDF8E0C, 0xE147, 0x11E3, { 0x99, 0x03, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } \ + } + +#define EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID \ + { \ + 0xCAB0E94C, 0xE15F, 0x11E3, { 0x91, 0x8D, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } \ + } + +#define EFI_BOOT_MANAGER_POLICY_NETWORK_GUID \ + { \ + 0xD04159DC, 0xE15F, 0x11E3, { 0xB2, 0x61, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } \ + } + +#define EFI_BOOT_MANAGER_POLICY_CONNECT_ALL_GUID \ + { \ + 0x113B2126, 0xFC8A, 0x11E3, { 0xBD, 0x6C, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } \ + } + +typedef struct _EFI_BOOT_MANAGER_POLICY_PROTOCOL EFI_BOOT_MANAGER_POLICY_PROTOCOL; + +#define EFI_BOOT_MANAGER_POLICY_PROTOCOL_REVISION 0x00010000 + +/** + Connect a device path following the platforms EFI Boot Manager policy. + + The ConnectDevicePath() function allows the caller to connect a DevicePath using the + same policy as the EFI Boot Manger. + + @param[in] This A pointer to the EFI_BOOT_MANAGER_POLICY_PROTOCOL instance. + @param[in] DevicePath Points to the start of the EFI device path to connect. + If DevicePath is NULL then all the controllers in the + system will be connected using the platforms EFI Boot + Manager policy. + @param[in] Recursive If TRUE, then ConnectController() is called recursively + until the entire tree of controllers below the + controller specified by DevicePath have been created. + If FALSE, then the tree of controllers is only expanded + one level. If DevicePath is NULL then Recursive is ignored. + + @retval EFI_SUCCESS The DevicePath was connected. + @retval EFI_NOT_FOUND The DevicePath was not found. + @retval EFI_NOT_FOUND No driver was connected to DevicePath. + @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device + drivers on the DevicePath. + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BOOT_MANAGER_POLICY_CONNECT_DEVICE_PATH)( + IN EFI_BOOT_MANAGER_POLICY_PROTOCOL *This, + IN EFI_DEVICE_PATH *DevicePath, + IN BOOLEAN Recursive + ); + +/** + Connect a class of devices using the platform Boot Manager policy. + + The ConnectDeviceClass() function allows the caller to request that the Boot + Manager connect a class of devices. + + If Class is EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID then the Boot Manager will + use platform policy to connect consoles. Some platforms may restrict the + number of consoles connected as they attempt to fast boot, and calling + ConnectDeviceClass() with a Class value of EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID + must connect the set of consoles that follow the Boot Manager platform policy, + and the EFI_SIMPLE_TEXT_INPUT_PROTOCOL, EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL, and + the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL are produced on the connected handles. + The Boot Manager may restrict which consoles get connect due to platform policy, + for example a security policy may require that a given console is not connected. + + If Class is EFI_BOOT_MANAGER_POLICY_NETWORK_GUID then the Boot Manager will + connect the protocols the platforms supports for UEFI general purpose network + applications on one or more handles. If more than one network controller is + available a platform will connect, one, many, or all of the networks based + on platform policy. Connecting UEFI networking protocols, like EFI_DHCP4_PROTOCOL, + does not establish connections on the network. The UEFI general purpose network + application that called ConnectDeviceClass() may need to use the published + protocols to establish the network connection. The Boot Manager can optionally + have a policy to establish a network connection. + + If Class is EFI_BOOT_MANAGER_POLICY_CONNECT_ALL_GUID then the Boot Manager + will connect all UEFI drivers using the UEFI Boot Service + EFI_BOOT_SERVICES.ConnectController(). If the Boot Manager has policy + associated with connect all UEFI drivers this policy will be used. + + A platform can also define platform specific Class values as a properly generated + EFI_GUID would never conflict with this specification. + + @param[in] This A pointer to the EFI_BOOT_MANAGER_POLICY_PROTOCOL instance. + @param[in] Class A pointer to an EFI_GUID that represents a class of devices + that will be connected using the Boot Mangers platform policy. + + @retval EFI_SUCCESS At least one devices of the Class was connected. + @retval EFI_DEVICE_ERROR Devices were not connected due to an error. + @retval EFI_NOT_FOUND The Class is not supported by the platform. + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BOOT_MANAGER_POLICY_CONNECT_DEVICE_CLASS)( + IN EFI_BOOT_MANAGER_POLICY_PROTOCOL *This, + IN EFI_GUID *Class + ); + +struct _EFI_BOOT_MANAGER_POLICY_PROTOCOL { + UINT64 Revision; + EFI_BOOT_MANAGER_POLICY_CONNECT_DEVICE_PATH ConnectDevicePath; + EFI_BOOT_MANAGER_POLICY_CONNECT_DEVICE_CLASS ConnectDeviceClass; +}; + +extern EFI_GUID gEfiBootManagerPolicyProtocolGuid; + +extern EFI_GUID gEfiBootManagerPolicyConsoleGuid; +extern EFI_GUID gEfiBootManagerPolicyNetworkGuid; +extern EFI_GUID gEfiBootManagerPolicyConnectAllGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BusSpecificDriverOverride.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BusSpecificDriverOverride.h new file mode 100644 index 0000000..3ec474c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/BusSpecificDriverOverride.h @@ -0,0 +1,72 @@ +/** @file + Bus Specific Driver Override protocol as defined in the UEFI 2.0 specification. + + Bus drivers that have a bus specific algorithm for matching drivers to controllers are + required to produce this protocol for each controller. For example, a PCI Bus Driver will produce an + instance of this protocol for every PCI controller that has a PCI option ROM that contains one or + more UEFI drivers. The protocol instance is attached to the handle of the PCI controller. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_H_ +#define _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_H_ + +/// +/// Global ID for the Bus Specific Driver Override Protocol +/// +#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { \ + 0x3bc1b285, 0x8a15, 0x4a82, {0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65 } \ + } + +typedef struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL; + +// +// Prototypes for the Bus Specific Driver Override Protocol +// + +/** + Uses a bus specific algorithm to retrieve a driver image handle for a controller. + + @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_ + OVERRIDE_PROTOCOL instance. + @param DriverImageHandle On input, a pointer to the previous driver image handle returned + by GetDriver(). On output, a pointer to the next driver + image handle. Passing in a NULL, will return the first driver + image handle. + + @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle. + @retval EFI_NOT_FOUND The end of the list of override drivers was reached. + A bus specific override driver is not returned in DriverImageHandle. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a + previous call to GetDriver(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER)( + IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, + IN OUT EFI_HANDLE *DriverImageHandle + ); + +/// +/// This protocol matches one or more drivers to a controller. This protocol is produced by a bus driver, +/// and it is installed on the child handles of buses that require a bus specific algorithm for matching +/// drivers to controllers. +/// +struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL { + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER GetDriver; +}; + +extern EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Capsule.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Capsule.h new file mode 100644 index 0000000..11f9f52 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Capsule.h @@ -0,0 +1,35 @@ +/** @file + Capsule Architectural Protocol as defined in PI1.0a Specification VOLUME 2 DXE + + The DXE Driver that produces this protocol must be a runtime driver. + The driver is responsible for initializing the CapsuleUpdate() and + QueryCapsuleCapabilities() fields of the UEFI Runtime Services Table. + After the two fields of the UEFI Runtime Services Table have been initialized, + the driver must install the EFI_CAPSULE_ARCH_PROTOCOL_GUID on a new handle + with a NULL interface pointer. The installation of this protocol informs + the DXE Foundation that the Capsule related services are now available and + that the DXE Foundation must update the 32-bit CRC of the UEFI Runtime Services Table. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_CAPSULE_ARCH_H__ +#define __ARCH_PROTOCOL_CAPSULE_ARCH_H__ + +// +// Global ID for the Capsule Architectural Protocol +// +#define EFI_CAPSULE_ARCH_PROTOCOL_GUID \ + { 0x5053697e, 0x2cbc, 0x4819, {0x90, 0xd9, 0x05, 0x80, 0xde, 0xee, 0x57, 0x54 }} + +extern EFI_GUID gEfiCapsuleArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName.h new file mode 100644 index 0000000..25b1dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName.h @@ -0,0 +1,129 @@ +/** @file + EFI Component Name Protocol as defined in the EFI 1.1 specification. + This protocol is used to retrieve user readable names of EFI Drivers + and controllers managed by EFI Drivers. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_COMPONENT_NAME_H__ +#define __EFI_COMPONENT_NAME_H__ + +/// +/// The global ID for the Component Name Protocol. +/// +#define EFI_COMPONENT_NAME_PROTOCOL_GUID \ + { \ + 0x107a772c, 0xd5e1, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL; + + +/** + Retrieves a Unicode string that is the user-readable name of the EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a three-character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME_GET_DRIVER_NAME)( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language, from the point of view of the driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/// +/// This protocol is used to retrieve user readable names of drivers +/// and controllers managed by UEFI Drivers. +/// +struct _EFI_COMPONENT_NAME_PROTOCOL { + EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName; + /// + /// A Null-terminated ASCII string that contains one or more + /// ISO 639-2 language codes. This is the list of language codes + /// that this protocol supports. + /// + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiComponentNameProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName2.h new file mode 100644 index 0000000..f4e98be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ComponentName2.h @@ -0,0 +1,172 @@ +/** @file + UEFI Component Name 2 Protocol as defined in the UEFI 2.1 specification. + This protocol is used to retrieve user readable names of drivers + and controllers managed by UEFI Drivers. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_COMPONENT_NAME2_H__ +#define __EFI_COMPONENT_NAME2_H__ + +/// +/// Global ID for the Component Name Protocol +/// +#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \ + {0x6a7a5cff, 0xe8d9, 0x4f70, { 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14 } } + +typedef struct _EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL; + + +/** + Retrieves a string that is the user readable name of + the EFI Driver. + + @param This A pointer to the + EFI_COMPONENT_NAME2_PROTOCOL instance. + + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller + is requesting, and it must match one of the + languages specified in SupportedLanguages. + The number of languages supported by a + driver is up to the driver writer. Language + is specified in RFC 4646 language code + format. + + @param DriverName A pointer to the string to return. + This string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The string for the + Driver specified by This and the + language specified by Language + was returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This + does not support the language + specified by Language. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME2_GET_DRIVER_NAME)( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a string that is the user readable name of + the controller that is being managed by an EFI Driver. + + @param This A pointer to the + EFI_COMPONENT_NAME2_PROTOCOL instance. + + @param ControllerHandle The handle of a controller that the + driver specified by This is managing. + This handle specifies the controller + whose name is to be returned. + + @param ChildHandle The handle of the child controller to + retrieve the name of. This is an + optional parameter that may be NULL. + It will be NULL for device drivers. + It will also be NULL for bus + drivers that wish to retrieve the + name of the bus controller. It will + not be NULL for a bus driver that + wishes to retrieve the name of a + child controller. + + @param Language A pointer to a Null-terminated ASCII + string array indicating the language. + This is the language of the driver + name that the caller is requesting, + and it must match one of the + languages specified in + SupportedLanguages. The number of + languages supported by a driver is up + to the driver writer. Language is + specified in RFC 4646 language code + format. + + @param ControllerName A pointer to the string to return. + This string is the name of the controller + specified by ControllerHandle and ChildHandle + in the language specified by Language + from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The string for the user + readable name in the language + specified by Language for the + driver specified by This was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it + is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is + not currently managing the + controller specified by + ControllerHandle and + ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This + does not support the language + specified by Language. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/// +/// This protocol is used to retrieve user readable names of drivers +/// and controllers managed by UEFI Drivers. +/// +struct _EFI_COMPONENT_NAME2_PROTOCOL { + EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName; + + /// + /// A Null-terminated ASCII string array that contains one or more + /// supported language codes. This is the list of language codes that + /// this protocol supports. The number of languages supported by a + /// driver is up to the driver writer. SupportedLanguages is + /// specified in RFC 4646 format. + /// + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiComponentName2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Cpu.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Cpu.h new file mode 100644 index 0000000..9ab3d4e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Cpu.h @@ -0,0 +1,300 @@ +/** @file + CPU Architectural Protocol as defined in PI spec Volume 2 DXE + + This code abstracts the DXE core from processor implementation details. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_CPU_H__ +#define __ARCH_PROTOCOL_CPU_H__ + +#include + +#define EFI_CPU_ARCH_PROTOCOL_GUID \ + { 0x26baccb1, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +typedef struct _EFI_CPU_ARCH_PROTOCOL EFI_CPU_ARCH_PROTOCOL; + +/// +/// The type of flush operation +/// +typedef enum { + EfiCpuFlushTypeWriteBackInvalidate, + EfiCpuFlushTypeWriteBack, + EfiCpuFlushTypeInvalidate, + EfiCpuMaxFlushType +} EFI_CPU_FLUSH_TYPE; + +/// +/// The type of processor INIT. +/// +typedef enum { + EfiCpuInit, + EfiCpuMaxInitType +} EFI_CPU_INIT_TYPE; + +/** + EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs. + + @param InterruptType Defines the type of interrupt or exception that + occurred on the processor.This parameter is processor architecture specific. + @param SystemContext A pointer to the processor context when + the interrupt occurred on the processor. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_CPU_INTERRUPT_HANDLER)( + IN CONST EFI_EXCEPTION_TYPE InterruptType, + IN CONST EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_FLUSH_DATA_CACHE)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ); + + +/** + This function enables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are enabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_ENABLE_INTERRUPT)( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + + +/** + This function disables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are disabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_DISABLE_INTERRUPT)( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + + +/** + This function retrieves the processor's current interrupt state a returns it in + State. If interrupts are currently enabled, then TRUE is returned. If interrupts + are currently disabled, then FALSE is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param State A pointer to the processor's current interrupt state. Set to TRUE if + interrupts are enabled and FALSE if interrupts are disabled. + + @retval EFI_SUCCESS The processor's current interrupt state was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_GET_INTERRUPT_STATE)( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ); + + +/** + This function generates an INIT on the processor. If this function succeeds, then the + processor will be reset, and control will not be returned to the caller. If InitType is + not supported by this processor, or the processor cannot programmatically generate an + INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error + occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InitType The type of processor INIT to perform. + + @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen. + @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported + by this processor. + @retval EFI_DEVICE_ERROR The processor INIT failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_INIT)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ); + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_REGISTER_INTERRUPT_HANDLER)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. If TimerValue does not increment at a predictable rate, then 0 is + returned. This parameter is optional and may be NULL. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_GET_TIMER_VALUE)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ); + + +/** + This function modifies the attributes for the memory region specified by BaseAddress and + Length from their current attributes to the attributes specified by Attributes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memory region. + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combination of attributes that + cannot be set together. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_SET_MEMORY_ATTRIBUTES)( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + + +/// +/// The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE +/// Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt +/// vectors and exception vectors, reading internal processor timers, resetting the processor, and +/// determining the processor frequency. +/// +struct _EFI_CPU_ARCH_PROTOCOL { + EFI_CPU_FLUSH_DATA_CACHE FlushDataCache; + EFI_CPU_ENABLE_INTERRUPT EnableInterrupt; + EFI_CPU_DISABLE_INTERRUPT DisableInterrupt; + EFI_CPU_GET_INTERRUPT_STATE GetInterruptState; + EFI_CPU_INIT Init; + EFI_CPU_REGISTER_INTERRUPT_HANDLER RegisterInterruptHandler; + EFI_CPU_GET_TIMER_VALUE GetTimerValue; + EFI_CPU_SET_MEMORY_ATTRIBUTES SetMemoryAttributes; + /// + /// The number of timers that are available in a processor. The value in this + /// field is a constant that must not be modified after the CPU Architectural + /// Protocol is installed. All consumers must treat this as a read-only field. + /// + UINT32 NumberOfTimers; + /// + /// The size, in bytes, of the alignment required for DMA buffer allocations. + /// This is typically the size of the largest data cache line in the platform. + /// The value in this field is a constant that must not be modified after the + /// CPU Architectural Protocol is installed. All consumers must treat this as + /// a read-only field. + /// + UINT32 DmaBufferAlignment; +}; + +extern EFI_GUID gEfiCpuArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/CpuIo2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/CpuIo2.h new file mode 100644 index 0000000..e159d35 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/CpuIo2.h @@ -0,0 +1,142 @@ +/** @file + This files describes the CPU I/O 2 Protocol. + + This protocol provides an I/O abstraction for a system processor. This protocol + is used by a PCI root bridge I/O driver to perform memory-mapped I/O and I/O transactions. + The I/O or memory primitives can be used by the consumer of the protocol to materialize + bus-specific configuration cycles, such as the transitional configuration address and data + ports for PCI. Only drivers that require direct access to the entire system should use this + protocol. + + Note: This is a boot-services only protocol and it may not be used by runtime drivers after + ExitBootServices(). It is different from the Framework CPU I/O Protocol, which is a runtime + protocol and can be used by runtime drivers after ExitBootServices(). + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef __CPU_IO2_H__ +#define __CPU_IO2_H__ + +#define EFI_CPU_IO2_PROTOCOL_GUID \ + { \ + 0xad61f191, 0xae5f, 0x4c0e, {0xb9, 0xfa, 0xe8, 0x69, 0xd2, 0x88, 0xc6, 0x4f} \ + } + +typedef struct _EFI_CPU_IO2_PROTOCOL EFI_CPU_IO2_PROTOCOL; + +/// +/// Enumeration that defines the width of the I/O operation. +/// +typedef enum { + EfiCpuIoWidthUint8, + EfiCpuIoWidthUint16, + EfiCpuIoWidthUint32, + EfiCpuIoWidthUint64, + EfiCpuIoWidthFifoUint8, + EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, + EfiCpuIoWidthFifoUint64, + EfiCpuIoWidthFillUint8, + EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, + EfiCpuIoWidthFillUint64, + EfiCpuIoWidthMaximum +} EFI_CPU_IO_PROTOCOL_WIDTH; + +/** + Enables a driver to access registers in the PI CPU I/O space. + + The Io.Read() and Io.Write() functions enable a driver to access PCI controller + registers in the PI CPU I/O space. + + The I/O operations are carried out exactly as requested. The caller is responsible + for satisfying any alignment and I/O width restrictions that a PI System on a + platform might require. For example on some platforms, width requests of + EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will + be handled by the driver. + + If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, + or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for + each of the Count operations that is performed. + + If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times on the same Address. + + If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is + incremented for each of the Count operations that is performed. The read or + write operation is performed Count times from the first element of Buffer. + + @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O or Memory operation. + @param[in] Address The base address of the I/O operation. + @param[in] Count The number of I/O operations to perform. The number + of bytes moved is Width size * Count, starting at Address. + @param[in, out] Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the PI system. + @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + @retval EFI_UNSUPPORTED The address range specified by Address, Width, + and Count is not valid for this PI system. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM)( + IN EFI_CPU_IO2_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/// +/// Service for read and write accesses. +/// +typedef struct { + /// + /// This service provides the various modalities of memory and I/O read. + /// + EFI_CPU_IO_PROTOCOL_IO_MEM Read; + /// + /// This service provides the various modalities of memory and I/O write. + /// + EFI_CPU_IO_PROTOCOL_IO_MEM Write; +} EFI_CPU_IO_PROTOCOL_ACCESS; + +/// +/// Provides the basic memory and I/O interfaces that are used to abstract +/// accesses to devices in a system. +/// +struct _EFI_CPU_IO2_PROTOCOL { + /// + /// Enables a driver to access memory-mapped registers in the EFI system memory space. + /// + EFI_CPU_IO_PROTOCOL_ACCESS Mem; + /// + /// Enables a driver to access registers in the EFI CPU I/O space. + /// + EFI_CPU_IO_PROTOCOL_ACCESS Io; +}; + +extern EFI_GUID gEfiCpuIo2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugPort.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugPort.h new file mode 100644 index 0000000..d0c280f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugPort.h @@ -0,0 +1,146 @@ +/** @file + + The file defines the EFI Debugport protocol. + This protocol is used by debug agent to communicate with the + remote debug host. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEBUG_PORT_H__ +#define __DEBUG_PORT_H__ + + +/// +/// DebugPortIo protocol {EBA4E8D2-3858-41EC-A281-2647BA9660D0} +/// +#define EFI_DEBUGPORT_PROTOCOL_GUID \ + { \ + 0xEBA4E8D2, 0x3858, 0x41EC, {0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 } \ + } + +extern EFI_GUID gEfiDebugPortProtocolGuid; + +typedef struct _EFI_DEBUGPORT_PROTOCOL EFI_DEBUGPORT_PROTOCOL; + +// +// DebugPort member functions +// + +/** + Resets the debugport. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + + @retval EFI_SUCCESS The debugport device was reset and is in usable state. + @retval EFI_DEVICE_ERROR The debugport device could not be reset and is unusable. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_RESET)( + IN EFI_DEBUGPORT_PROTOCOL *This + ); + +/** + Writes data to the debugport. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + @param Timeout The number of microseconds to wait before timing out a write operation. + @param BufferSize On input, the requested number of bytes of data to write. On output, the + number of bytes of data actually written. + @param Buffer A pointer to a buffer containing the data to write. + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_WRITE)( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Reads data from the debugport. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + @param Timeout The number of microseconds to wait before timing out a read operation. + @param BufferSize On input, the requested number of bytes of data to read. On output, the + number of bytes of data actually number of bytes + of data read and returned in Buffer. + @param Buffer A pointer to a buffer into which the data read will be saved. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The operation was stopped due to a timeout or overrun. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_READ)( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Checks to see if any data is available to be read from the debugport device. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + + @retval EFI_SUCCESS At least one byte of data is available to be read. + @retval EFI_DEVICE_ERROR The debugport device is not functioning correctly. + @retval EFI_NOT_READY No data is available to be read. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_POLL)( + IN EFI_DEBUGPORT_PROTOCOL *This + ); + +/// +/// This protocol provides the communication link between the debug agent and the remote host. +/// +struct _EFI_DEBUGPORT_PROTOCOL { + EFI_DEBUGPORT_RESET Reset; + EFI_DEBUGPORT_WRITE Write; + EFI_DEBUGPORT_READ Read; + EFI_DEBUGPORT_POLL Poll; +}; + +// +// DEBUGPORT variable definitions... +// +#define EFI_DEBUGPORT_VARIABLE_NAME L"DEBUGPORT" +#define EFI_DEBUGPORT_VARIABLE_GUID EFI_DEBUGPORT_PROTOCOL_GUID + +extern EFI_GUID gEfiDebugPortVariableGuid; + +// +// DebugPort device path definitions... +// +#define DEVICE_PATH_MESSAGING_DEBUGPORT EFI_DEBUGPORT_PROTOCOL_GUID + +extern EFI_GUID gEfiDebugPortDevicePathGuid; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} DEBUGPORT_DEVICE_PATH; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugSupport.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugSupport.h new file mode 100644 index 0000000..f97610d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DebugSupport.h @@ -0,0 +1,778 @@ +/** @file + DebugSupport protocol and supporting definitions as defined in the UEFI2.4 + specification. + + The DebugSupport protocol is used by source level debuggers to abstract the + processor and handle context save and restore operations. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+ +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEBUG_SUPPORT_H__ +#define __DEBUG_SUPPORT_H__ + +#include + +typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL EFI_DEBUG_SUPPORT_PROTOCOL; + +/// +/// Debug Support protocol {2755590C-6F3C-42FA-9EA4-A3BA543CDA25}. +/// +#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \ + { \ + 0x2755590C, 0x6F3C, 0x42FA, {0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } \ + } + +/// +/// Processor exception to be hooked. +/// All exception types for IA32, X64, Itanium and EBC processors are defined. +/// +typedef INTN EFI_EXCEPTION_TYPE; + +/// +/// IA-32 processor exception types. +/// +#define EXCEPT_IA32_DIVIDE_ERROR 0 +#define EXCEPT_IA32_DEBUG 1 +#define EXCEPT_IA32_NMI 2 +#define EXCEPT_IA32_BREAKPOINT 3 +#define EXCEPT_IA32_OVERFLOW 4 +#define EXCEPT_IA32_BOUND 5 +#define EXCEPT_IA32_INVALID_OPCODE 6 +#define EXCEPT_IA32_DOUBLE_FAULT 8 +#define EXCEPT_IA32_INVALID_TSS 10 +#define EXCEPT_IA32_SEG_NOT_PRESENT 11 +#define EXCEPT_IA32_STACK_FAULT 12 +#define EXCEPT_IA32_GP_FAULT 13 +#define EXCEPT_IA32_PAGE_FAULT 14 +#define EXCEPT_IA32_FP_ERROR 16 +#define EXCEPT_IA32_ALIGNMENT_CHECK 17 +#define EXCEPT_IA32_MACHINE_CHECK 18 +#define EXCEPT_IA32_SIMD 19 + +/// +/// FXSAVE_STATE. +/// FP / MMX / XMM registers (see fxrstor instruction definition). +/// +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT32 Eip; + UINT16 Cs; + UINT16 Reserved1; + UINT32 DataOffset; + UINT16 Ds; + UINT8 Reserved2[10]; + UINT8 St0Mm0[10], Reserved3[6]; + UINT8 St1Mm1[10], Reserved4[6]; + UINT8 St2Mm2[10], Reserved5[6]; + UINT8 St3Mm3[10], Reserved6[6]; + UINT8 St4Mm4[10], Reserved7[6]; + UINT8 St5Mm5[10], Reserved8[6]; + UINT8 St6Mm6[10], Reserved9[6]; + UINT8 St7Mm7[10], Reserved10[6]; + UINT8 Xmm0[16]; + UINT8 Xmm1[16]; + UINT8 Xmm2[16]; + UINT8 Xmm3[16]; + UINT8 Xmm4[16]; + UINT8 Xmm5[16]; + UINT8 Xmm6[16]; + UINT8 Xmm7[16]; + UINT8 Reserved11[14 * 16]; +} EFI_FX_SAVE_STATE_IA32; + +/// +/// IA-32 processor context definition. +/// +typedef struct { + UINT32 ExceptionData; + EFI_FX_SAVE_STATE_IA32 FxSaveState; + UINT32 Dr0; + UINT32 Dr1; + UINT32 Dr2; + UINT32 Dr3; + UINT32 Dr6; + UINT32 Dr7; + UINT32 Cr0; + UINT32 Cr1; /* Reserved */ + UINT32 Cr2; + UINT32 Cr3; + UINT32 Cr4; + UINT32 Eflags; + UINT32 Ldtr; + UINT32 Tr; + UINT32 Gdtr[2]; + UINT32 Idtr[2]; + UINT32 Eip; + UINT32 Gs; + UINT32 Fs; + UINT32 Es; + UINT32 Ds; + UINT32 Cs; + UINT32 Ss; + UINT32 Edi; + UINT32 Esi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; +} EFI_SYSTEM_CONTEXT_IA32; + +/// +/// x64 processor exception types. +/// +#define EXCEPT_X64_DIVIDE_ERROR 0 +#define EXCEPT_X64_DEBUG 1 +#define EXCEPT_X64_NMI 2 +#define EXCEPT_X64_BREAKPOINT 3 +#define EXCEPT_X64_OVERFLOW 4 +#define EXCEPT_X64_BOUND 5 +#define EXCEPT_X64_INVALID_OPCODE 6 +#define EXCEPT_X64_DOUBLE_FAULT 8 +#define EXCEPT_X64_INVALID_TSS 10 +#define EXCEPT_X64_SEG_NOT_PRESENT 11 +#define EXCEPT_X64_STACK_FAULT 12 +#define EXCEPT_X64_GP_FAULT 13 +#define EXCEPT_X64_PAGE_FAULT 14 +#define EXCEPT_X64_FP_ERROR 16 +#define EXCEPT_X64_ALIGNMENT_CHECK 17 +#define EXCEPT_X64_MACHINE_CHECK 18 +#define EXCEPT_X64_SIMD 19 + +/// +/// FXSAVE_STATE. +/// FP / MMX / XMM registers (see fxrstor instruction definition). +/// +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT64 Rip; + UINT64 DataOffset; + UINT8 Reserved1[8]; + UINT8 St0Mm0[10], Reserved2[6]; + UINT8 St1Mm1[10], Reserved3[6]; + UINT8 St2Mm2[10], Reserved4[6]; + UINT8 St3Mm3[10], Reserved5[6]; + UINT8 St4Mm4[10], Reserved6[6]; + UINT8 St5Mm5[10], Reserved7[6]; + UINT8 St6Mm6[10], Reserved8[6]; + UINT8 St7Mm7[10], Reserved9[6]; + UINT8 Xmm0[16]; + UINT8 Xmm1[16]; + UINT8 Xmm2[16]; + UINT8 Xmm3[16]; + UINT8 Xmm4[16]; + UINT8 Xmm5[16]; + UINT8 Xmm6[16]; + UINT8 Xmm7[16]; + // + // NOTE: UEFI 2.0 spec definition as follows. + // + UINT8 Reserved11[14 * 16]; +} EFI_FX_SAVE_STATE_X64; + +/// +/// x64 processor context definition. +/// +typedef struct { + UINT64 ExceptionData; + EFI_FX_SAVE_STATE_X64 FxSaveState; + UINT64 Dr0; + UINT64 Dr1; + UINT64 Dr2; + UINT64 Dr3; + UINT64 Dr6; + UINT64 Dr7; + UINT64 Cr0; + UINT64 Cr1; /* Reserved */ + UINT64 Cr2; + UINT64 Cr3; + UINT64 Cr4; + UINT64 Cr8; + UINT64 Rflags; + UINT64 Ldtr; + UINT64 Tr; + UINT64 Gdtr[2]; + UINT64 Idtr[2]; + UINT64 Rip; + UINT64 Gs; + UINT64 Fs; + UINT64 Es; + UINT64 Ds; + UINT64 Cs; + UINT64 Ss; + UINT64 Rdi; + UINT64 Rsi; + UINT64 Rbp; + UINT64 Rsp; + UINT64 Rbx; + UINT64 Rdx; + UINT64 Rcx; + UINT64 Rax; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; +} EFI_SYSTEM_CONTEXT_X64; + +/// +/// Itanium Processor Family Exception types. +/// +#define EXCEPT_IPF_VHTP_TRANSLATION 0 +#define EXCEPT_IPF_INSTRUCTION_TLB 1 +#define EXCEPT_IPF_DATA_TLB 2 +#define EXCEPT_IPF_ALT_INSTRUCTION_TLB 3 +#define EXCEPT_IPF_ALT_DATA_TLB 4 +#define EXCEPT_IPF_DATA_NESTED_TLB 5 +#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6 +#define EXCEPT_IPF_DATA_KEY_MISSED 7 +#define EXCEPT_IPF_DIRTY_BIT 8 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9 +#define EXCEPT_IPF_DATA_ACCESS_BIT 10 +#define EXCEPT_IPF_BREAKPOINT 11 +#define EXCEPT_IPF_EXTERNAL_INTERRUPT 12 +// +// 13 - 19 reserved +// +#define EXCEPT_IPF_PAGE_NOT_PRESENT 20 +#define EXCEPT_IPF_KEY_PERMISSION 21 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS 22 +#define EXCEPT_IPF_DATA_ACCESS_RIGHTS 23 +#define EXCEPT_IPF_GENERAL_EXCEPTION 24 +#define EXCEPT_IPF_DISABLED_FP_REGISTER 25 +#define EXCEPT_IPF_NAT_CONSUMPTION 26 +#define EXCEPT_IPF_SPECULATION 27 +// +// 28 reserved +// +#define EXCEPT_IPF_DEBUG 29 +#define EXCEPT_IPF_UNALIGNED_REFERENCE 30 +#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE 31 +#define EXCEPT_IPF_FP_FAULT 32 +#define EXCEPT_IPF_FP_TRAP 33 +#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP 34 +#define EXCEPT_IPF_TAKEN_BRANCH 35 +#define EXCEPT_IPF_SINGLE_STEP 36 +// +// 37 - 44 reserved +// +#define EXCEPT_IPF_IA32_EXCEPTION 45 +#define EXCEPT_IPF_IA32_INTERCEPT 46 +#define EXCEPT_IPF_IA32_INTERRUPT 47 + +/// +/// IPF processor context definition. +/// +typedef struct { + // + // The first reserved field is necessary to preserve alignment for the correct + // bits in UNAT and to insure F2 is 16 byte aligned. + // + UINT64 Reserved; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 R16; + UINT64 R17; + UINT64 R18; + UINT64 R19; + UINT64 R20; + UINT64 R21; + UINT64 R22; + UINT64 R23; + UINT64 R24; + UINT64 R25; + UINT64 R26; + UINT64 R27; + UINT64 R28; + UINT64 R29; + UINT64 R30; + UINT64 R31; + + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F6[2]; + UINT64 F7[2]; + UINT64 F8[2]; + UINT64 F9[2]; + UINT64 F10[2]; + UINT64 F11[2]; + UINT64 F12[2]; + UINT64 F13[2]; + UINT64 F14[2]; + UINT64 F15[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + + UINT64 Pr; + + UINT64 B0; + UINT64 B1; + UINT64 B2; + UINT64 B3; + UINT64 B4; + UINT64 B5; + UINT64 B6; + UINT64 B7; + + // + // application registers + // + UINT64 ArRsc; + UINT64 ArBsp; + UINT64 ArBspstore; + UINT64 ArRnat; + + UINT64 ArFcr; + + UINT64 ArEflag; + UINT64 ArCsd; + UINT64 ArSsd; + UINT64 ArCflg; + UINT64 ArFsr; + UINT64 ArFir; + UINT64 ArFdr; + + UINT64 ArCcv; + + UINT64 ArUnat; + + UINT64 ArFpsr; + + UINT64 ArPfs; + UINT64 ArLc; + UINT64 ArEc; + + // + // control registers + // + UINT64 CrDcr; + UINT64 CrItm; + UINT64 CrIva; + UINT64 CrPta; + UINT64 CrIpsr; + UINT64 CrIsr; + UINT64 CrIip; + UINT64 CrIfa; + UINT64 CrItir; + UINT64 CrIipa; + UINT64 CrIfs; + UINT64 CrIim; + UINT64 CrIha; + + // + // debug registers + // + UINT64 Dbr0; + UINT64 Dbr1; + UINT64 Dbr2; + UINT64 Dbr3; + UINT64 Dbr4; + UINT64 Dbr5; + UINT64 Dbr6; + UINT64 Dbr7; + + UINT64 Ibr0; + UINT64 Ibr1; + UINT64 Ibr2; + UINT64 Ibr3; + UINT64 Ibr4; + UINT64 Ibr5; + UINT64 Ibr6; + UINT64 Ibr7; + + // + // virtual registers - nat bits for R1-R31 + // + UINT64 IntNat; + +} EFI_SYSTEM_CONTEXT_IPF; + +/// +/// EBC processor exception types. +/// +#define EXCEPT_EBC_UNDEFINED 0 +#define EXCEPT_EBC_DIVIDE_ERROR 1 +#define EXCEPT_EBC_DEBUG 2 +#define EXCEPT_EBC_BREAKPOINT 3 +#define EXCEPT_EBC_OVERFLOW 4 +#define EXCEPT_EBC_INVALID_OPCODE 5 ///< Opcode out of range. +#define EXCEPT_EBC_STACK_FAULT 6 +#define EXCEPT_EBC_ALIGNMENT_CHECK 7 +#define EXCEPT_EBC_INSTRUCTION_ENCODING 8 ///< Malformed instruction. +#define EXCEPT_EBC_BAD_BREAK 9 ///< BREAK 0 or undefined BREAK. +#define EXCEPT_EBC_STEP 10 ///< To support debug stepping. +/// +/// For coding convenience, define the maximum valid EBC exception. +/// +#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP + +/// +/// EBC processor context definition. +/// +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 Flags; + UINT64 ControlFlags; + UINT64 Ip; +} EFI_SYSTEM_CONTEXT_EBC; + + + +/// +/// ARM processor exception types. +/// +#define EXCEPT_ARM_RESET 0 +#define EXCEPT_ARM_UNDEFINED_INSTRUCTION 1 +#define EXCEPT_ARM_SOFTWARE_INTERRUPT 2 +#define EXCEPT_ARM_PREFETCH_ABORT 3 +#define EXCEPT_ARM_DATA_ABORT 4 +#define EXCEPT_ARM_RESERVED 5 +#define EXCEPT_ARM_IRQ 6 +#define EXCEPT_ARM_FIQ 7 + +/// +/// For coding convenience, define the maximum valid ARM exception. +/// +#define MAX_ARM_EXCEPTION EXCEPT_ARM_FIQ + +/// +/// ARM processor context definition. +/// +typedef struct { + UINT32 R0; + UINT32 R1; + UINT32 R2; + UINT32 R3; + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 SP; + UINT32 LR; + UINT32 PC; + UINT32 CPSR; + UINT32 DFSR; + UINT32 DFAR; + UINT32 IFSR; + UINT32 IFAR; +} EFI_SYSTEM_CONTEXT_ARM; + + +/// +/// AARCH64 processor exception types. +/// +#define EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS 0 +#define EXCEPT_AARCH64_IRQ 1 +#define EXCEPT_AARCH64_FIQ 2 +#define EXCEPT_AARCH64_SERROR 3 + +/// +/// For coding convenience, define the maximum valid ARM exception. +/// +#define MAX_AARCH64_EXCEPTION EXCEPT_AARCH64_SERROR + +typedef struct { + // General Purpose Registers + UINT64 X0; + UINT64 X1; + UINT64 X2; + UINT64 X3; + UINT64 X4; + UINT64 X5; + UINT64 X6; + UINT64 X7; + UINT64 X8; + UINT64 X9; + UINT64 X10; + UINT64 X11; + UINT64 X12; + UINT64 X13; + UINT64 X14; + UINT64 X15; + UINT64 X16; + UINT64 X17; + UINT64 X18; + UINT64 X19; + UINT64 X20; + UINT64 X21; + UINT64 X22; + UINT64 X23; + UINT64 X24; + UINT64 X25; + UINT64 X26; + UINT64 X27; + UINT64 X28; + UINT64 FP; // x29 - Frame pointer + UINT64 LR; // x30 - Link Register + UINT64 SP; // x31 - Stack pointer + + // FP/SIMD Registers + UINT64 V0[2]; + UINT64 V1[2]; + UINT64 V2[2]; + UINT64 V3[2]; + UINT64 V4[2]; + UINT64 V5[2]; + UINT64 V6[2]; + UINT64 V7[2]; + UINT64 V8[2]; + UINT64 V9[2]; + UINT64 V10[2]; + UINT64 V11[2]; + UINT64 V12[2]; + UINT64 V13[2]; + UINT64 V14[2]; + UINT64 V15[2]; + UINT64 V16[2]; + UINT64 V17[2]; + UINT64 V18[2]; + UINT64 V19[2]; + UINT64 V20[2]; + UINT64 V21[2]; + UINT64 V22[2]; + UINT64 V23[2]; + UINT64 V24[2]; + UINT64 V25[2]; + UINT64 V26[2]; + UINT64 V27[2]; + UINT64 V28[2]; + UINT64 V29[2]; + UINT64 V30[2]; + UINT64 V31[2]; + + UINT64 ELR; // Exception Link Register + UINT64 SPSR; // Saved Processor Status Register + UINT64 FPSR; // Floating Point Status Register + UINT64 ESR; // Exception syndrome register + UINT64 FAR; // Fault Address Register +} EFI_SYSTEM_CONTEXT_AARCH64; + + +/// +/// Universal EFI_SYSTEM_CONTEXT definition. +/// +typedef union { + EFI_SYSTEM_CONTEXT_EBC *SystemContextEbc; + EFI_SYSTEM_CONTEXT_IA32 *SystemContextIa32; + EFI_SYSTEM_CONTEXT_X64 *SystemContextX64; + EFI_SYSTEM_CONTEXT_IPF *SystemContextIpf; + EFI_SYSTEM_CONTEXT_ARM *SystemContextArm; + EFI_SYSTEM_CONTEXT_AARCH64 *SystemContextAArch64; +} EFI_SYSTEM_CONTEXT; + +// +// DebugSupport callback function prototypes +// + +/** + Registers and enables an exception callback function for the specified exception. + + @param ExceptionType Exception types in EBC, IA-32, x64, or IPF. + @param SystemContext Exception content. + +**/ +typedef +VOID +(EFIAPI *EFI_EXCEPTION_CALLBACK)( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Registers and enables the on-target debug agent's periodic entry point. + + @param SystemContext Exception content. + +**/ +typedef +VOID +(EFIAPI *EFI_PERIODIC_CALLBACK)( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +/// +/// Machine type definition +/// +typedef enum { + IsaIa32 = IMAGE_FILE_MACHINE_I386, ///< 0x014C + IsaX64 = IMAGE_FILE_MACHINE_X64, ///< 0x8664 + IsaIpf = IMAGE_FILE_MACHINE_IA64, ///< 0x0200 + IsaEbc = IMAGE_FILE_MACHINE_EBC, ///< 0x0EBC + IsaArm = IMAGE_FILE_MACHINE_ARMTHUMB_MIXED, ///< 0x01c2 + IsaAArch64 = IMAGE_FILE_MACHINE_ARM64 ///< 0xAA64 +} EFI_INSTRUCTION_SET_ARCHITECTURE; + + +// +// DebugSupport member function definitions +// + +/** + Returns the maximum value that may be used for the ProcessorIndex parameter in + RegisterPeriodicCallback() and RegisterExceptionCallback(). + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported + processor index is returned. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MAXIMUM_PROCESSOR_INDEX)( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ); + +/** + Registers a function to be called back periodically in interrupt context. + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param ProcessorIndex Specifies which processor the callback function applies to. + @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main + periodic entry point of the debug agent. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback + function was previously registered. + @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback + function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PERIODIC_CALLBACK)( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ); + +/** + Registers a function to be called when a given processor exception occurs. + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param ProcessorIndex Specifies which processor the callback function applies to. + @param ExceptionCallback A pointer to a function of type EXCEPTION_CALLBACK that is called + when the processor exception specified by ExceptionType occurs. + @param ExceptionType Specifies which processor exception to hook. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback + function was previously registered. + @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback + function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_EXCEPTION_CALLBACK)( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ); + +/** + Invalidates processor instruction cache for a memory range. Subsequent execution in this range + causes a fresh memory fetch to retrieve code to be executed. + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param ProcessorIndex Specifies which processor's instruction cache is to be invalidated. + @param Start Specifies the physical base of the memory range to be invalidated. + @param Length Specifies the minimum number of bytes in the processor's instruction + cache to invalidate. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INVALIDATE_INSTRUCTION_CACHE)( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ); + +/// +/// This protocol provides the services to allow the debug agent to register +/// callback functions that are called either periodically or when specific +/// processor exceptions occur. +/// +struct _EFI_DEBUG_SUPPORT_PROTOCOL { + /// + /// Declares the processor architecture for this instance of the EFI Debug Support protocol. + /// + EFI_INSTRUCTION_SET_ARCHITECTURE Isa; + EFI_GET_MAXIMUM_PROCESSOR_INDEX GetMaximumProcessorIndex; + EFI_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback; + EFI_REGISTER_EXCEPTION_CALLBACK RegisterExceptionCallback; + EFI_INVALIDATE_INSTRUCTION_CACHE InvalidateInstructionCache; +}; + +extern EFI_GUID gEfiDebugSupportProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Decompress.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Decompress.h new file mode 100644 index 0000000..a66e991 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Decompress.h @@ -0,0 +1,122 @@ +/** @file + The Decompress Protocol Interface as defined in UEFI spec + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DECOMPRESS_H__ +#define __DECOMPRESS_H__ + +#define EFI_DECOMPRESS_PROTOCOL_GUID \ + { \ + 0xd8117cfe, 0x94a6, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_DECOMPRESS_PROTOCOL EFI_DECOMPRESS_PROTOCOL; + +/** + The GetInfo() function 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 + EFI_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 EFI_SUCCESS is returned. + + The GetInfo() function does not have a 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. + + @param This A pointer to the EFI_DECOMPRESS_PROTOCOL instance. + @param Source The source buffer containing the compressed data. + @param SourceSize The size, in bytes, of 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 EFI_SUCCESS The size of the uncompressed data was returned in DestinationSize + and the size of the scratch buffer was returned in ScratchSize. + @retval EFI_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 SourceData. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DECOMPRESS_GET_INFO)( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +/** + The Decompress() function extracts decompressed data to its original form. + + This protocol is designed so that the decompression algorithm can be + implemented without using any memory services. As a result, the + Decompress() function is not allowed to call AllocatePool() or + AllocatePages() 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 and SourceSize is + successfully decompressed into Destination, then EFI_SUCCESS is returned. + If the compressed source data specified by Source and SourceSize is not in + a valid compressed data format, then EFI_INVALID_PARAMETER is returned. + + @param This A pointer to the EFI_DECOMPRESS_PROTOCOL instance. + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source data. + @param Destination On output, the destination buffer that contains + the uncompressed data. + @param DestinationSize The size of destination buffer. The size of destination + buffer needed is obtained from GetInfo(). + @param Scratch A temporary scratch buffer that is used to perform the + decompression. + @param ScratchSize The size of scratch buffer. The size of scratch buffer needed + is obtained from GetInfo(). + + @retval EFI_SUCCESS Decompression completed successfully, and the uncompressed + buffer is returned in Destination. + @retval EFI_INVALID_PARAMETER The source buffer specified by Source and SourceSize is + corrupted (not in a valid compressed format). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DECOMPRESS_DECOMPRESS)( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +/// +/// Provides a decompression service. +/// +struct _EFI_DECOMPRESS_PROTOCOL { + EFI_DECOMPRESS_GET_INFO GetInfo; + EFI_DECOMPRESS_DECOMPRESS Decompress; +}; + +extern EFI_GUID gEfiDecompressProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeferredImageLoad.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeferredImageLoad.h new file mode 100644 index 0000000..ddf3aca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeferredImageLoad.h @@ -0,0 +1,80 @@ +/** @file + UEFI 2.2 Deferred Image Load Protocol definition. + + This protocol returns information about images whose load was denied because of security + considerations. This information can be used by the Boot Manager or another agent to reevaluate the + images when the current security profile has been changed, such as when the current user profile + changes. There can be more than one instance of this protocol installed. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEFERRED_IMAGE_LOAD_H__ +#define __DEFERRED_IMAGE_LOAD_H__ + +/// +/// Global ID for the Deferred Image Load Protocol +/// +#define EFI_DEFERRED_IMAGE_LOAD_PROTOCOL_GUID \ + { \ + 0x15853d7c, 0x3ddf, 0x43e0, { 0xa1, 0xcb, 0xeb, 0xf8, 0x5b, 0x8f, 0x87, 0x2c } \ + }; + +typedef struct _EFI_DEFERRED_IMAGE_LOAD_PROTOCOL EFI_DEFERRED_IMAGE_LOAD_PROTOCOL; + +/** + Returns information about a deferred image. + + This function returns information about a single deferred image. The deferred images are numbered + consecutively, starting with 0. If there is no image which corresponds to ImageIndex, then + EFI_NOT_FOUND is returned. All deferred images may be returned by iteratively calling this + function until EFI_NOT_FOUND is returned. + Image may be NULL and ImageSize set to 0 if the decision to defer execution was made because + of the location of the executable image rather than its actual contents. record handle until + there are no more, at which point UserInfo will point to NULL. + + @param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL. + @param[in] ImageIndex Zero-based index of the deferred index. + @param[out] ImageDevicePath On return, points to a pointer to the device path of the image. + The device path should not be freed by the caller. + @param[out] Image On return, points to the first byte of the image or NULL if the + image is not available. The image should not be freed by the caller + unless LoadImage() has been called successfully. + @param[out] ImageSize On return, the size of the image, or 0 if the image is not available. + @param[out] BootOption On return, points to TRUE if the image was intended as a boot option + or FALSE if it was not intended as a boot option. + + @retval EFI_SUCCESS Image information returned successfully. + @retval EFI_NOT_FOUND ImageIndex does not refer to a valid image. + @retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or + BootOption is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEFERRED_IMAGE_INFO)( + IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This, + IN UINTN ImageIndex, + OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath, + OUT VOID **Image, + OUT UINTN *ImageSize, + OUT BOOLEAN *BootOption + ); + +/// +/// This protocol returns information about a deferred image. +/// +struct _EFI_DEFERRED_IMAGE_LOAD_PROTOCOL { + EFI_DEFERRED_IMAGE_INFO GetImageInfo; +}; + +extern EFI_GUID gEfiDeferredImageLoadProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeviceIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeviceIo.h new file mode 100644 index 0000000..88dd325 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DeviceIo.h @@ -0,0 +1,268 @@ +/** @file + Device IO protocol as defined in the EFI 1.10 specification. + + Device IO is used to abstract hardware access to devices. It includes + memory mapped IO, IO, PCI Config space, and DMA. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEVICE_IO_H__ +#define __DEVICE_IO_H__ + +#define EFI_DEVICE_IO_PROTOCOL_GUID \ + { \ + 0xaf6ac311, 0x84c3, 0x11d2, {0x8e, 0x3c, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_DEVICE_IO_PROTOCOL EFI_DEVICE_IO_PROTOCOL; + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define DEVICE_IO_PROTOCOL EFI_DEVICE_IO_PROTOCOL_GUID + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_DEVICE_IO_PROTOCOL EFI_DEVICE_IO_INTERFACE; + +/// +/// Device IO Access Width +/// +typedef enum { + IO_UINT8 = 0, + IO_UINT16 = 1, + IO_UINT32 = 2, + IO_UINT64 = 3, + // + // Below enumerations are added in "Extensible Firmware Interface Specification, + // Version 1.10, Specification Update, Version 001". + // + MMIO_COPY_UINT8 = 4, + MMIO_COPY_UINT16 = 5, + MMIO_COPY_UINT32 = 6, + MMIO_COPY_UINT64 = 7 +} EFI_IO_WIDTH; + +/** + Enables a driver to access device registers in the appropriate memory or I/O space. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Width Signifies the width of the I/O operations. + @param Address The base address of the I/O operations. + @param Count The number of I/O operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. If + Width is MMIO_COPY_UINT8, MMIO_COPY_UINT16, + MMIO_COPY_UINT32, or MMIO_COPY_UINT64, then + Buffer is interpreted as a base address of an I/O operation such as Address. + + @retval EFI_SUCCESS The data was read from or written to the device. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Width is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEVICE_IO)( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_DEVICE_IO Read; + EFI_DEVICE_IO Write; +} EFI_IO_ACCESS; + +/** + Provides an EFI Device Path for a PCI device with the given PCI configuration space address. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param PciAddress The PCI configuration space address of the device whose Device Path + is going to be returned. + @param PciDevicePath A pointer to the pointer for the EFI Device Path for PciAddress. + Memory for the Device Path is allocated from the pool. + + @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI Device Path. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device Path. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_DEVICE_PATH)( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINT64 PciAddress, + IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath + ); + +typedef enum { + /// + /// A read operation from system memory by a bus master. + /// + EfiBusMasterRead, + + /// + /// A write operation to system memory by a bus master. + /// + EfiBusMasterWrite, + + /// + /// Provides both read and write access to system memory + /// by both the processor and a bus master. The buffer is + /// coherent from both the processor's and the bus master's + /// point of view. + /// + EfiBusMasterCommonBuffer +} EFI_IO_OPERATION_TYPE; + +/** + Provides the device-specific addresses needed to access system memory. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the device. + @param NumberOfBytes On input, the number of bytes to map. + On output, the number of bytes that were mapped. + @param DeviceAddress The resulting map address for the bus master device to use to access the + hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_MAP)( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_OPERATION_TYPE Operation, + IN EFI_PHYSICAL_ADDRESS *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_UNMAP)( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Type The type allocation to perform. + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + @retval EFI_INVALID_PARAMETER The requested memory type is invalid. + @retval EFI_UNSUPPORTED The requested HostAddress is not supported on + this platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_ALLOCATE_BUFFER)( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *HostAddress + ); + +/** + Flushes any posted write data to the device. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_FLUSH)( + IN EFI_DEVICE_IO_PROTOCOL *This + ); + +/** + Frees pages that were allocated with AllocateBuffer(). + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Pages The number of pages to free. + @param HostAddress The base address of the range to free. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocateBuffer(). + @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_FREE_BUFFER)( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINTN Pages, + IN EFI_PHYSICAL_ADDRESS HostAddress + ); + +/// +/// This protocol provides the basic Memory, I/O, and PCI interfaces that +/// are used to abstract accesses to devices. +/// +struct _EFI_DEVICE_IO_PROTOCOL { + /// + /// Allows reads and writes to memory mapped I/O space. + /// + EFI_IO_ACCESS Mem; + /// + /// Allows reads and writes to I/O space. + /// + EFI_IO_ACCESS Io; + /// + /// Allows reads and writes to PCI configuration space. + /// + EFI_IO_ACCESS Pci; + EFI_IO_MAP Map; + EFI_PCI_DEVICE_PATH PciDevicePath; + EFI_IO_UNMAP Unmap; + EFI_IO_ALLOCATE_BUFFER AllocateBuffer; + EFI_IO_FLUSH Flush; + EFI_IO_FREE_BUFFER FreeBuffer; +}; + +extern EFI_GUID gEfiDeviceIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePath.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePath.h new file mode 100644 index 0000000..b68bfa2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePath.h @@ -0,0 +1,1358 @@ +/** @file + The device path protocol as defined in UEFI 2.0. + + The device path represents a programmatic path to a device, + from a software point of view. The path must persist from boot to boot, so + it can not contain things like PCI bus numbers that change from boot to boot. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DEVICE_PATH_PROTOCOL_H__ +#define __EFI_DEVICE_PATH_PROTOCOL_H__ + +#include +#include +#include + +/// +/// Device Path protocol. +/// +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +/// +/// Device Path guid definition for backward-compatible with EFI1.1. +/// +#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID + +#pragma pack(1) + +/** + This protocol can be used on any device handle to obtain generic path/location + information concerning the physical device or logical device. If the handle does + not logically map to a physical device, the handle may not necessarily support + the device path protocol. The device path describes the location of the device + the handle is for. The size of the Device Path can be determined from the structures + that make up the Device Path. +**/ +typedef struct { + UINT8 Type; ///< 0x01 Hardware Device Path. + ///< 0x02 ACPI Device Path. + ///< 0x03 Messaging Device Path. + ///< 0x04 Media Device Path. + ///< 0x05 BIOS Boot Specification Device Path. + ///< 0x7F End of Hardware Device Path. + + UINT8 SubType; ///< Varies by Type + ///< 0xFF End Entire Device Path, or + ///< 0x01 End This Instance of a Device Path and start a new + ///< Device Path. + + UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define + ///< type of data. Size of data is included in Length. + +} EFI_DEVICE_PATH_PROTOCOL; + +/// +/// Device Path protocol definition for backward-compatible with EFI1.1. +/// +typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH; + +/// +/// Hardware Device Paths. +/// +#define HARDWARE_DEVICE_PATH 0x01 + +/// +/// PCI Device Path SubType. +/// +#define HW_PCI_DP 0x01 + +/// +/// PCI Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// PCI Function Number. + /// + UINT8 Function; + /// + /// PCI Device Number. + /// + UINT8 Device; +} PCI_DEVICE_PATH; + +/// +/// PCCARD Device Path SubType. +/// +#define HW_PCCARD_DP 0x02 + +/// +/// PCCARD Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Function Number (0 = First Function). + /// + UINT8 FunctionNumber; +} PCCARD_DEVICE_PATH; + +/// +/// Memory Mapped Device Path SubType. +/// +#define HW_MEMMAP_DP 0x03 + +/// +/// Memory Mapped Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// EFI_MEMORY_TYPE + /// + UINT32 MemoryType; + /// + /// Starting Memory Address. + /// + EFI_PHYSICAL_ADDRESS StartingAddress; + /// + /// Ending Memory Address. + /// + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +/// +/// Hardware Vendor Device Path SubType. +/// +#define HW_VENDOR_DP 0x04 + +/// +/// The Vendor Device Path allows the creation of vendor-defined Device Paths. A vendor must +/// allocate a Vendor GUID for a Device Path. The Vendor GUID can then be used to define the +/// contents on the n bytes that follow in the Vendor Device Path node. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Vendor-assigned GUID that defines the data that follows. + /// + EFI_GUID Guid; + /// + /// Vendor-defined variable size data. + /// +} VENDOR_DEVICE_PATH; + +/// +/// Controller Device Path SubType. +/// +#define HW_CONTROLLER_DP 0x05 + +/// +/// Controller Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Controller number. + /// + UINT32 ControllerNumber; +} CONTROLLER_DEVICE_PATH; + +/// +/// BMC Device Path SubType. +/// +#define HW_BMC_DP 0x06 + +/// +/// BMC Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Interface Type. + /// + UINT8 InterfaceType; + /// + /// Base Address. + /// + UINT8 BaseAddress[8]; +} BMC_DEVICE_PATH; + +/// +/// ACPI Device Paths. +/// +#define ACPI_DEVICE_PATH 0x02 + +/// +/// ACPI Device Path SubType. +/// +#define ACPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device's PnP hardware ID stored in a numeric 32-bit + /// compressed EISA-type ID. This value must match the + /// corresponding _HID in the ACPI name space. + /// + UINT32 HID; + /// + /// Unique ID that is required by ACPI if two devices have the + /// same _HID. This value must also match the corresponding + /// _UID/_HID pair in the ACPI name space. Only the 32-bit + /// numeric value type of _UID is supported. Thus, strings must + /// not be used for the _UID in the ACPI name space. + /// + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +/// +/// Expanded ACPI Device Path SubType. +/// +#define ACPI_EXTENDED_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device's PnP hardware ID stored in a numeric 32-bit + /// compressed EISA-type ID. This value must match the + /// corresponding _HID in the ACPI name space. + /// + UINT32 HID; + /// + /// Unique ID that is required by ACPI if two devices have the + /// same _HID. This value must also match the corresponding + /// _UID/_HID pair in the ACPI name space. + /// + UINT32 UID; + /// + /// Device's compatible PnP hardware ID stored in a numeric + /// 32-bit compressed EISA-type ID. This value must match at + /// least one of the compatible device IDs returned by the + /// corresponding _CID in the ACPI name space. + /// + UINT32 CID; + /// + /// Optional variable length _HIDSTR. + /// Optional variable length _UIDSTR. + /// Optional variable length _CIDSTR. + /// +} ACPI_EXTENDED_HID_DEVICE_PATH; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32)((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) +#define EFI_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + +/// +/// ACPI _ADR Device Path SubType. +/// +#define ACPI_ADR_DP 0x03 + +/// +/// The _ADR device path is used to contain video output device attributes to support the Graphics +/// Output Protocol. The device path can contain multiple _ADR entries if multiple video output +/// devices are displaying the same output. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// _ADR value. For video output devices the value of this + /// field comes from Table B-2 of the ACPI 3.0 specification. At + /// least one _ADR value is required. + /// + UINT32 ADR; + // + // This device path may optionally contain more than one _ADR entry. + // +} ACPI_ADR_DEVICE_PATH; + +#define ACPI_ADR_DISPLAY_TYPE_OTHER 0 +#define ACPI_ADR_DISPLAY_TYPE_VGA 1 +#define ACPI_ADR_DISPLAY_TYPE_TV 2 +#define ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL 3 +#define ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL 4 + +#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \ + ((UINT32)( ((UINT32)((_DeviceIdScheme) & 0x1) << 31) | \ + (((_HeadId) & 0x7) << 18) | \ + (((_NonVgaOutput) & 0x1) << 17) | \ + (((_BiosCanDetect) & 0x1) << 16) | \ + (((_VendorInfo) & 0xf) << 12) | \ + (((_Type) & 0xf) << 8) | \ + (((_Port) & 0xf) << 4) | \ + ((_Index) & 0xf) )) + +/// +/// Messaging Device Paths. +/// This Device Path is used to describe the connection of devices outside the resource domain of the +/// system. This Device Path can describe physical messaging information like SCSI ID, or abstract +/// information like networking protocol IP addresses. +/// +#define MESSAGING_DEVICE_PATH 0x03 + +/// +/// ATAPI Device Path SubType +/// +#define MSG_ATAPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Set to zero for primary, or one for secondary. + /// + UINT8 PrimarySecondary; + /// + /// Set to zero for master, or one for slave mode. + /// + UINT8 SlaveMaster; + /// + /// Logical Unit Number. + /// + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +/// +/// SCSI Device Path SubType. +/// +#define MSG_SCSI_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID on the SCSI bus (PUN). + /// + UINT16 Pun; + /// + /// Logical Unit Number (LUN). + /// + UINT16 Lun; +} SCSI_DEVICE_PATH; + +/// +/// Fibre Channel SubType. +/// +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// Fibre Channel World Wide Number. + /// + UINT64 WWN; + /// + /// Fibre Channel Logical Unit Number. + /// + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +/// +/// Fibre Channel Ex SubType. +/// +#define MSG_FIBRECHANNELEX_DP 0x15 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 8 byte array containing Fibre Channel End Device Port Name. + /// + UINT8 WWN[8]; + /// + /// 8 byte array containing Fibre Channel Logical Unit Number. + /// + UINT8 Lun[8]; +} FIBRECHANNELEX_DEVICE_PATH; + +/// +/// 1394 Device Path SubType +/// +#define MSG_1394_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 1394 Global Unique ID (GUID). + /// + UINT64 Guid; +} F1394_DEVICE_PATH; + +/// +/// USB Device Path SubType. +/// +#define MSG_USB_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// USB Parent Port Number. + /// + UINT8 ParentPortNumber; + /// + /// USB Interface Number. + /// + UINT8 InterfaceNumber; +} USB_DEVICE_PATH; + +/// +/// USB Class Device Path SubType. +/// +#define MSG_USB_CLASS_DP 0x0f +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Vendor ID assigned by USB-IF. A value of 0xFFFF will + /// match any Vendor ID. + /// + UINT16 VendorId; + /// + /// Product ID assigned by USB-IF. A value of 0xFFFF will + /// match any Product ID. + /// + UINT16 ProductId; + /// + /// The class code assigned by the USB-IF. A value of 0xFF + /// will match any class code. + /// + UINT8 DeviceClass; + /// + /// The subclass code assigned by the USB-IF. A value of + /// 0xFF will match any subclass code. + /// + UINT8 DeviceSubClass; + /// + /// The protocol code assigned by the USB-IF. A value of + /// 0xFF will match any protocol code. + /// + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +/// +/// USB WWID Device Path SubType. +/// +#define MSG_USB_WWID_DP 0x10 + +/// +/// This device path describes a USB device using its serial number. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// USB interface number. + /// + UINT16 InterfaceNumber; + /// + /// USB vendor id of the device. + /// + UINT16 VendorId; + /// + /// USB product id of the device. + /// + UINT16 ProductId; + /// + /// Last 64-or-fewer UTF-16 characters of the USB + /// serial number. The length of the string is + /// determined by the Length field less the offset of the + /// Serial Number field (10) + /// + /// CHAR16 SerialNumber[...]; +} USB_WWID_DEVICE_PATH; + +/// +/// Device Logical Unit SubType. +/// +#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Logical Unit Number for the interface. + /// + UINT8 Lun; +} DEVICE_LOGICAL_UNIT_DEVICE_PATH; + +/// +/// SATA Device Path SubType. +/// +#define MSG_SATA_DP 0x12 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The HBA port number that facilitates the connection to the + /// device or a port multiplier. The value 0xFFFF is reserved. + /// + UINT16 HBAPortNumber; + /// + /// The Port multiplier port number that facilitates the connection + /// to the device. Must be set to 0xFFFF if the device is directly + /// connected to the HBA. + /// + UINT16 PortMultiplierPortNumber; + /// + /// Logical Unit Number. + /// + UINT16 Lun; +} SATA_DEVICE_PATH; + +/// +/// Flag for if the device is directly connected to the HBA. +/// +#define SATA_HBA_DIRECT_CONNECT_FLAG 0x8000 + +/// +/// I2O Device Path SubType. +/// +#define MSG_I2O_DP 0x06 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID (TID) for a device. + /// + UINT32 Tid; +} I2O_DEVICE_PATH; + +/// +/// MAC Address Device Path SubType. +/// +#define MSG_MAC_ADDR_DP 0x0b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The MAC address for a network interface padded with 0s. + /// + EFI_MAC_ADDRESS MacAddress; + /// + /// Network interface type(i.e. 802.3, FDDI). + /// + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +/// +/// IPv4 Device Path SubType +/// +#define MSG_IPv4_DP 0x0c +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The local IPv4 address. + /// + EFI_IPv4_ADDRESS LocalIpAddress; + /// + /// The remote IPv4 address. + /// + EFI_IPv4_ADDRESS RemoteIpAddress; + /// + /// The local port number. + /// + UINT16 LocalPort; + /// + /// The remote port number. + /// + UINT16 RemotePort; + /// + /// The network protocol(i.e. UDP, TCP). + /// + UINT16 Protocol; + /// + /// 0x00 - The Source IP Address was assigned though DHCP. + /// 0x01 - The Source IP Address is statically bound. + /// + BOOLEAN StaticIpAddress; + /// + /// The gateway IP address + /// + EFI_IPv4_ADDRESS GatewayIpAddress; + /// + /// The subnet mask + /// + EFI_IPv4_ADDRESS SubnetMask; +} IPv4_DEVICE_PATH; + +/// +/// IPv6 Device Path SubType. +/// +#define MSG_IPv6_DP 0x0d +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The local IPv6 address. + /// + EFI_IPv6_ADDRESS LocalIpAddress; + /// + /// The remote IPv6 address. + /// + EFI_IPv6_ADDRESS RemoteIpAddress; + /// + /// The local port number. + /// + UINT16 LocalPort; + /// + /// The remote port number. + /// + UINT16 RemotePort; + /// + /// The network protocol(i.e. UDP, TCP). + /// + UINT16 Protocol; + /// + /// 0x00 - The Local IP Address was manually configured. + /// 0x01 - The Local IP Address is assigned through IPv6 + /// stateless auto-configuration. + /// 0x02 - The Local IP Address is assigned through IPv6 + /// stateful configuration. + /// + UINT8 IpAddressOrigin; + /// + /// The prefix length + /// + UINT8 PrefixLength; + /// + /// The gateway IP address + /// + EFI_IPv6_ADDRESS GatewayIpAddress; +} IPv6_DEVICE_PATH; + +/// +/// InfiniBand Device Path SubType. +/// +#define MSG_INFINIBAND_DP 0x09 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Flags to help identify/manage InfiniBand device path elements: + /// Bit 0 - IOC/Service (0b = IOC, 1b = Service). + /// Bit 1 - Extend Boot Environment. + /// Bit 2 - Console Protocol. + /// Bit 3 - Storage Protocol. + /// Bit 4 - Network Protocol. + /// All other bits are reserved. + /// + UINT32 ResourceFlags; + /// + /// 128-bit Global Identifier for remote fabric port. + /// + UINT8 PortGid[16]; + /// + /// 64-bit unique identifier to remote IOC or server process. + /// Interpretation of field specified by Resource Flags (bit 0). + /// + UINT64 ServiceId; + /// + /// 64-bit persistent ID of remote IOC port. + /// + UINT64 TargetPortId; + /// + /// 64-bit persistent ID of remote device. + /// + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE 0x01 +#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT 0x02 +#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL 0x04 +#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL 0x08 +#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL 0x10 + +/// +/// UART Device Path SubType. +/// +#define MSG_UART_DP 0x0e +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved. + /// + UINT32 Reserved; + /// + /// The baud rate setting for the UART style device. A value of 0 + /// means that the device's default baud rate will be used. + /// + UINT64 BaudRate; + /// + /// The number of data bits for the UART style device. A value + /// of 0 means that the device's default number of data bits will be used. + /// + UINT8 DataBits; + /// + /// The parity setting for the UART style device. + /// Parity 0x00 - Default Parity. + /// Parity 0x01 - No Parity. + /// Parity 0x02 - Even Parity. + /// Parity 0x03 - Odd Parity. + /// Parity 0x04 - Mark Parity. + /// Parity 0x05 - Space Parity. + /// + UINT8 Parity; + /// + /// The number of stop bits for the UART style device. + /// Stop Bits 0x00 - Default Stop Bits. + /// Stop Bits 0x01 - 1 Stop Bit. + /// Stop Bits 0x02 - 1.5 Stop Bits. + /// Stop Bits 0x03 - 2 Stop Bits. + /// + UINT8 StopBits; +} UART_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MSG_VENDOR_DP 0x0a +typedef VENDOR_DEVICE_PATH VENDOR_DEFINED_DEVICE_PATH; + +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID + +/// +/// A new device path node is defined to declare flow control characteristics. +/// UART Flow Control Messaging Device Path +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL GUID. + /// + EFI_GUID Guid; + /// + /// Bitmap of supported flow control types. + /// Bit 0 set indicates hardware flow control. + /// Bit 1 set indicates Xon/Xoff flow control. + /// All other bits are reserved and are clear. + /// + UINT32 FlowControlMap; +} UART_FLOW_CONTROL_DEVICE_PATH; + +#define UART_FLOW_CONTROL_HARDWARE 0x00000001 +#define UART_FLOW_CONTROL_XON_XOFF 0x00000010 + +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID +/// +/// Serial Attached SCSI (SAS) Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// DEVICE_PATH_MESSAGING_SAS GUID. + /// + EFI_GUID Guid; + /// + /// Reserved for future use. + /// + UINT32 Reserved; + /// + /// SAS Address for Serial Attached SCSI Target. + /// + UINT64 SasAddress; + /// + /// SAS Logical Unit Number. + /// + UINT64 Lun; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SAS_DEVICE_PATH; + +/// +/// Serial Attached SCSI (SAS) Ex Device Path SubType +/// +#define MSG_SASEX_DP 0x16 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port. + /// + UINT8 SasAddress[8]; + /// + /// 8-byte array of the SAS Logical Unit Number. + /// + UINT8 Lun[8]; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SASEX_DEVICE_PATH; + +/// +/// NvmExpress Namespace Device Path SubType. +/// +#define MSG_NVME_NAMESPACE_DP 0x17 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 NamespaceId; + UINT64 NamespaceUuid; +} NVME_NAMESPACE_DEVICE_PATH; + +/// +/// DNS Device Path SubType +/// +#define MSG_DNS_DP 0x1F +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Indicates the DNS server address is IPv4 or IPv6 address. + /// + UINT8 IsIPv6; + /// + /// Instance of the DNS server address. + /// + EFI_IP_ADDRESS DnsServerIp[]; +} DNS_DEVICE_PATH; + +/// +/// Uniform Resource Identifiers (URI) Device Path SubType +/// +#define MSG_URI_DP 0x18 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Instance of the URI pursuant to RFC 3986. + /// + CHAR8 Uri[]; +} URI_DEVICE_PATH; + +/// +/// Universal Flash Storage (UFS) Device Path SubType. +/// +#define MSG_UFS_DP 0x19 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID on the UFS bus (PUN). + /// + UINT8 Pun; + /// + /// Logical Unit Number (LUN). + /// + UINT8 Lun; +} UFS_DEVICE_PATH; + +/// +/// SD (Secure Digital) Device Path SubType. +/// +#define MSG_SD_DP 0x1A +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 SlotNumber; +} SD_DEVICE_PATH; + +/// +/// EMMC (Embedded MMC) Device Path SubType. +/// +#define MSG_EMMC_DP 0x1D +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 SlotNumber; +} EMMC_DEVICE_PATH; + +/// +/// iSCSI Device Path SubType +/// +#define MSG_ISCSI_DP 0x13 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Network Protocol (0 = TCP, 1+ = reserved). + /// + UINT16 NetworkProtocol; + /// + /// iSCSI Login Options. + /// + UINT16 LoginOption; + /// + /// iSCSI Logical Unit Number. + /// + UINT64 Lun; + /// + /// iSCSI Target Portal group tag the initiator intends + /// to establish a session with. + /// + UINT16 TargetPortalGroupTag; + /// + /// iSCSI NodeTarget Name. The length of the name + /// is determined by subtracting the offset of this field from Length. + /// + /// CHAR8 iSCSI Target Name. +} ISCSI_DEVICE_PATH; + +#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C 0x0002 +#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C 0x0008 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP 0x0000 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON 0x1000 +#define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000 +#define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000 + +/// +/// VLAN Device Path SubType. +/// +#define MSG_VLAN_DP 0x14 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// VLAN identifier (0-4094). + /// + UINT16 VlanId; +} VLAN_DEVICE_PATH; + +/// +/// Bluetooth Device Path SubType. +/// +#define MSG_BLUETOOTH_DP 0x1b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 48bit Bluetooth device address. + /// + BLUETOOTH_ADDRESS BD_ADDR; +} BLUETOOTH_DEVICE_PATH; + +/// +/// Wi-Fi Device Path SubType. +/// +#define MSG_WIFI_DP 0x1C +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Service set identifier. A 32-byte octets string. + /// + UINT8 SSId[32]; +} WIFI_DEVICE_PATH; + +/// +/// Bluetooth LE Device Path SubType. +/// +#define MSG_BLUETOOTH_LE_DP 0x1E +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + BLUETOOTH_LE_ADDRESS Address; +} BLUETOOTH_LE_DEVICE_PATH; + +// +// Media Device Path +// +#define MEDIA_DEVICE_PATH 0x04 + +/// +/// Hard Drive Media Device Path SubType. +/// +#define MEDIA_HARDDRIVE_DP 0x01 + +/// +/// The Hard Drive Media Device Path is used to represent a partition on a hard drive. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Describes the entry in a partition table, starting with entry 1. + /// Partition number zero represents the entire device. Valid + /// partition numbers for a MBR partition are [1, 4]. Valid + /// partition numbers for a GPT partition are [1, NumberOfPartitionEntries]. + /// + UINT32 PartitionNumber; + /// + /// Starting LBA of the partition on the hard drive. + /// + UINT64 PartitionStart; + /// + /// Size of the partition in units of Logical Blocks. + /// + UINT64 PartitionSize; + /// + /// Signature unique to this partition: + /// If SignatureType is 0, this field has to be initialized with 16 zeros. + /// If SignatureType is 1, the MBR signature is stored in the first 4 bytes of this field. + /// The other 12 bytes are initialized with zeros. + /// If SignatureType is 2, this field contains a 16 byte signature. + /// + UINT8 Signature[16]; + /// + /// Partition Format: (Unused values reserved). + /// 0x01 - PC-AT compatible legacy MBR. + /// 0x02 - GUID Partition Table. + /// + UINT8 MBRType; + /// + /// Type of Disk Signature: (Unused values reserved). + /// 0x00 - No Disk Signature. + /// 0x01 - 32-bit signature from address 0x1b8 of the type 0x01 MBR. + /// 0x02 - GUID signature. + /// + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define NO_DISK_SIGNATURE 0x00 +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +/// +/// CD-ROM Media Device Path SubType. +/// +#define MEDIA_CDROM_DP 0x02 + +/// +/// The CD-ROM Media Device Path is used to define a system partition that exists on a CD-ROM. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Boot Entry number from the Boot Catalog. The Initial/Default entry is defined as zero. + /// + UINT32 BootEntry; + /// + /// Starting RBA of the partition on the medium. CD-ROMs use Relative logical Block Addressing. + /// + UINT64 PartitionStart; + /// + /// Size of the partition in units of Blocks, also called Sectors. + /// + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MEDIA_VENDOR_DP 0x03 ///< Media vendor device path subtype. + +/// +/// File Path Media Device Path SubType +/// +#define MEDIA_FILEPATH_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// A NULL-terminated Path string including directory and file names. + /// + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH OFFSET_OF(FILEPATH_DEVICE_PATH,PathName) + +/// +/// Media Protocol Device Path SubType. +/// +#define MEDIA_PROTOCOL_DP 0x05 + +/// +/// The Media Protocol Device Path is used to denote the protocol that is being +/// used in a device path at the location of the path specified. +/// Many protocols are inherent to the style of device path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The ID of the protocol. + /// + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + +/// +/// PIWG Firmware File SubType. +/// +#define MEDIA_PIWG_FW_FILE_DP 0x06 + +/// +/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware file. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Firmware file name + /// + EFI_GUID FvFileName; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; + +/// +/// PIWG Firmware Volume Device Path SubType. +/// +#define MEDIA_PIWG_FW_VOL_DP 0x07 + +/// +/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware volume. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Firmware volume name. + /// + EFI_GUID FvName; +} MEDIA_FW_VOL_DEVICE_PATH; + +/// +/// Media relative offset range device path. +/// +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08 + +/// +/// Used to describe the offset range of media relative. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 StartingOffset; + UINT64 EndingOffset; +} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH; + +/// +/// This GUID defines a RAM Disk supporting a raw disk format in volatile memory. +/// +#define EFI_VIRTUAL_DISK_GUID EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_VOLATILE + +extern EFI_GUID gEfiVirtualDiskGuid; + +/// +/// This GUID defines a RAM Disk supporting an ISO image in volatile memory. +/// +#define EFI_VIRTUAL_CD_GUID EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_VOLATILE + +extern EFI_GUID gEfiVirtualCdGuid; + +/// +/// This GUID defines a RAM Disk supporting a raw disk format in persistent memory. +/// +#define EFI_PERSISTENT_VIRTUAL_DISK_GUID EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_DISK_REGION_PERSISTENT + +extern EFI_GUID gEfiPersistentVirtualDiskGuid; + +/// +/// This GUID defines a RAM Disk supporting an ISO image in persistent memory. +/// +#define EFI_PERSISTENT_VIRTUAL_CD_GUID EFI_ACPI_6_0_NFIT_GUID_RAM_DISK_SUPPORTING_VIRTUAL_CD_REGION_PERSISTENT + +extern EFI_GUID gEfiPersistentVirtualCdGuid; + +/// +/// Media ram disk device path. +/// +#define MEDIA_RAM_DISK_DP 0x09 + +/// +/// Used to describe the ram disk device path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Starting Memory Address. + /// + UINT32 StartingAddr[2]; + /// + /// Ending Memory Address. + /// + UINT32 EndingAddr[2]; + /// + /// GUID that defines the type of the RAM Disk. + /// + EFI_GUID TypeGuid; + /// + /// RAM Diskinstance number, if supported. The default value is zero. + /// + UINT16 Instance; +} MEDIA_RAM_DISK_DEVICE_PATH; + +/// +/// BIOS Boot Specification Device Path. +/// +#define BBS_DEVICE_PATH 0x05 + +/// +/// BIOS Boot Specification Device Path SubType. +/// +#define BBS_BBS_DP 0x01 + +/// +/// This Device Path is used to describe the booting of non-EFI-aware operating systems. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device Type as defined by the BIOS Boot Specification. + /// + UINT16 DeviceType; + /// + /// Status Flags as defined by the BIOS Boot Specification. + /// + UINT16 StatusFlag; + /// + /// Null-terminated ASCII string that describes the boot device to a user. + /// + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +// +// DeviceType definitions - from BBS specification +// +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_BEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + + +/// +/// Union of all possible Device Paths and pointers to Device Paths. +/// +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + + CONTROLLER_DEVICE_PATH Controller; + BMC_DEVICE_PATH Bmc; + ACPI_HID_DEVICE_PATH Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH ExtendedAcpi; + ACPI_ADR_DEVICE_PATH AcpiAdr; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + ISCSI_DEVICE_PATH Iscsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + FIBRECHANNELEX_DEVICE_PATH FibreChannelEx; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + SATA_DEVICE_PATH Sata; + USB_CLASS_DEVICE_PATH UsbClass; + USB_WWID_DEVICE_PATH UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicUnit; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + VLAN_DEVICE_PATH Vlan; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + UART_FLOW_CONTROL_DEVICE_PATH UartFlowControl; + SAS_DEVICE_PATH Sas; + SASEX_DEVICE_PATH SasEx; + NVME_NAMESPACE_DEVICE_PATH NvmeNamespace; + DNS_DEVICE_PATH Dns; + URI_DEVICE_PATH Uri; + BLUETOOTH_DEVICE_PATH Bluetooth; + WIFI_DEVICE_PATH WiFi; + UFS_DEVICE_PATH Ufs; + SD_DEVICE_PATH Sd; + EMMC_DEVICE_PATH Emmc; + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH Offset; + MEDIA_RAM_DISK_DEVICE_PATH RamDisk; + BBS_BBS_DEVICE_PATH Bbs; +} EFI_DEV_PATH; + + + +typedef union { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; + + CONTROLLER_DEVICE_PATH *Controller; + BMC_DEVICE_PATH *Bmc; + ACPI_HID_DEVICE_PATH *Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + ACPI_ADR_DEVICE_PATH *AcpiAdr; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + ISCSI_DEVICE_PATH *Iscsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + FIBRECHANNELEX_DEVICE_PATH *FibreChannelEx; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + SATA_DEVICE_PATH *Sata; + USB_CLASS_DEVICE_PATH *UsbClass; + USB_WWID_DEVICE_PATH *UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicUnit; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + VLAN_DEVICE_PATH *Vlan; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + SAS_DEVICE_PATH *Sas; + SASEX_DEVICE_PATH *SasEx; + NVME_NAMESPACE_DEVICE_PATH *NvmeNamespace; + DNS_DEVICE_PATH *Dns; + URI_DEVICE_PATH *Uri; + BLUETOOTH_DEVICE_PATH *Bluetooth; + WIFI_DEVICE_PATH *WiFi; + UFS_DEVICE_PATH *Ufs; + SD_DEVICE_PATH *Sd; + EMMC_DEVICE_PATH *Emmc; + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH *FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; +} EFI_DEV_PATH_PTR; + +#pragma pack() + +#define END_DEVICE_PATH_TYPE 0x7f +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xFF +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 + +extern EFI_GUID gEfiDevicePathProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathFromText.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathFromText.h new file mode 100644 index 0000000..6a2e238 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathFromText.h @@ -0,0 +1,72 @@ +/** @file + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL as defined in UEFI 2.0. + This protocol provides service to convert text to device paths and device nodes. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__ +#define __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__ + +/// +/// Device Path From Text protocol +/// +#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \ + { \ + 0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e } \ + } + +/** + 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. + + @retval a_pointer Pointer to the EFI device node. + @retval NULL if TextDeviceNode is NULL or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_NODE)( + IN CONST CHAR16 *TextDeviceNode + ); + + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device path character. + + @retval a_pointer Pointer to the allocated device path. + @retval NULL if TextDeviceNode is NULL or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_PATH)( + IN CONST CHAR16 *TextDevicePath + ); + +/// +/// This protocol converts text to device paths and device nodes. +/// +typedef struct { + EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode; + EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath; +} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; + +extern EFI_GUID gEfiDevicePathFromTextProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathToText.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathToText.h new file mode 100644 index 0000000..34fe4f3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathToText.h @@ -0,0 +1,85 @@ +/** @file + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL as defined in UEFI 2.0. + This protocol provides service to convert device nodes and paths to text. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEVICE_PATH_TO_TEXT_PROTOCOL_H__ +#define __DEVICE_PATH_TO_TEXT_PROTOCOL_H__ + +/// +/// Device Path To Text protocol +/// +#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + { \ + 0x8b843e20, 0x8132, 0x4852, {0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c } \ + } + +/** + Convert a device node to its text representation. + + @param DeviceNode Points 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. + + @retval a_pointer a pointer to the allocated text representation of the device node data + @retval NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_NODE)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/** + Convert a device path to its text representation. + + @param DevicePath Points to the device path 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 The AllowShortcuts is FALSE, then the shortcut forms of + text representation for a device node cannot be used. + + @retval a_pointer a pointer to the allocated text representation of the device node. + @retval NULL if DevicePath is NULL or there was insufficient memory. + +**/ +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_PATH)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/// +/// This protocol converts device paths and device nodes to text. +/// +typedef struct { + EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; + EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; +} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL; + +extern EFI_GUID gEfiDevicePathToTextProtocolGuid; + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathUtilities.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathUtilities.h new file mode 100644 index 0000000..b286b4d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DevicePathUtilities.h @@ -0,0 +1,192 @@ +/** @file + EFI_DEVICE_PATH_UTILITIES_PROTOCOL as defined in UEFI 2.0. + Use to create and manipulate device paths and device nodes. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEVICE_PATH_UTILITIES_PROTOCOL_H__ +#define __DEVICE_PATH_UTILITIES_PROTOCOL_H__ + +/// +/// Device Path Utilities protocol +/// +#define EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID \ + { \ + 0x379be4e, 0xd706, 0x437d, {0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4 } \ + } + +/** + Returns the size of the device path, in bytes. + + @param DevicePath Points to the start of the EFI device path. + + @return Size Size of the specified device path, in bytes, including the end-of-path tag. + @retval 0 DevicePath is NULL + +**/ +typedef +UINTN +(EFIAPI *EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + Create a duplicate of the specified path. + + @param DevicePath Points to the source EFI device path. + + @retval Pointer A pointer to the duplicate device path. + @retval NULL insufficient memory or DevicePath is NULL + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Create a new path by appending the second device path to the first. + If Src1 is NULL and Src2 is non-NULL, then a duplicate of Src2 is returned. + If Src1 is non-NULL and Src2 is NULL, then a duplicate of Src1 is returned. + If Src1 and Src2 are both NULL, then a copy of an end-of-device-path is returned. + + @param Src1 Points to the first device path. + @param Src2 Points to the second device path. + + @retval Pointer A pointer to the newly created device path. + @retval NULL Memory could not be allocated + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_APPEND_PATH)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ); + +/** + Creates a new path by appending the device node to the device path. + If DeviceNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DeviceNode, followed by an end-of-device path device node is returned. + If both DeviceNode and DevicePath are NULL then a copy of an end-of-device-path device node is returned. + + @param DevicePath Points to the device path. + @param DeviceNode Points to the device node. + + @retval Pointer A pointer to the allocated device node. + @retval NULL There was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_APPEND_NODE)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ); + +/** + Creates a new path by appending the specified device path instance to the specified device path. + + @param DevicePath Points to the device path. If NULL, then ignored. + @param DevicePathInstance Points to the device path instance. + + @retval Pointer A pointer to the newly created device path + @retval NULL Memory could not be allocated or DevicePathInstance is NULL. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ); + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + @param DevicePathInstance 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. + @param DevicePathInstanceSize On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is NULL. + If NULL, then the instance size is not output. + + @retval Pointer A pointer to the copy of the current device path instance. + @retval NULL DevicePathInstace was NULL on entry or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE)( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN *DevicePathInstanceSize + ); + +/** + Creates a device node + + @param NodeType NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + @param NodeSubType NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + @param NodeLength NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + @retval Pointer A pointer to the newly created device node. + @retval NULL NodeLength is less than + the size of the header or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_CREATE_NODE)( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength +); + +/** + Returns whether a device path is multi-instance. + + @param DevicePath Points to the device path. If NULL, then ignored. + + @retval TRUE The device path has more than one instance + @retval FALSE The device path is empty or contains only a single instance. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/// +/// This protocol is used to creates and manipulates device paths and device nodes. +/// +typedef struct { + EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize; + EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH DuplicateDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_PATH AppendDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_NODE AppendDeviceNode; + EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE AppendDevicePathInstance; + EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE GetNextDevicePathInstance; + EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE IsDevicePathMultiInstance; + EFI_DEVICE_PATH_UTILS_CREATE_NODE CreateDeviceNode; +} EFI_DEVICE_PATH_UTILITIES_PROTOCOL; + +extern EFI_GUID gEfiDevicePathUtilitiesProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp4.h new file mode 100644 index 0000000..915db84 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp4.h @@ -0,0 +1,780 @@ +/** @file + EFI_DHCP4_PROTOCOL as defined in UEFI 2.0. + EFI_DHCP4_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0. + These protocols are used to collect configuration information for the EFI IPv4 Protocol + drivers and to provide DHCPv4 server and PXE boot server discovery services. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.0. + +**/ + +#ifndef __EFI_DHCP4_PROTOCOL_H__ +#define __EFI_DHCP4_PROTOCOL_H__ + +#define EFI_DHCP4_PROTOCOL_GUID \ + { \ + 0x8a219718, 0x4ef5, 0x4761, {0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \ + } + +#define EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x9d9a39d8, 0xbd42, 0x4a73, {0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \ + } + +typedef struct _EFI_DHCP4_PROTOCOL EFI_DHCP4_PROTOCOL; + + +#pragma pack(1) +typedef struct { + /// + /// DHCP option code. + /// + UINT8 OpCode; + /// + /// Length of the DHCP option data. Not present if OpCode is 0 or 255. + /// + UINT8 Length; + /// + /// Start of the DHCP option data. Not present if OpCode is 0 or 255 or if Length is zero. + /// + UINT8 Data[1]; +} EFI_DHCP4_PACKET_OPTION; +#pragma pack() + + +#pragma pack(1) +/// +/// EFI_DHCP4_PACKET defines the format of DHCPv4 packets. See RFC 2131 for more information. +/// +typedef struct { + UINT8 OpCode; + UINT8 HwType; + UINT8 HwAddrLen; + UINT8 Hops; + UINT32 Xid; + UINT16 Seconds; + UINT16 Reserved; + EFI_IPv4_ADDRESS ClientAddr; ///< Client IP address from client. + EFI_IPv4_ADDRESS YourAddr; ///< Client IP address from server. + EFI_IPv4_ADDRESS ServerAddr; ///< IP address of next server in bootstrap. + EFI_IPv4_ADDRESS GatewayAddr; ///< Relay agent IP address. + UINT8 ClientHwAddr[16]; ///< Client hardware address. + CHAR8 ServerName[64]; + CHAR8 BootFileName[128]; +}EFI_DHCP4_HEADER; +#pragma pack() + + +#pragma pack(1) +typedef struct { + /// + /// Size of the EFI_DHCP4_PACKET buffer. + /// + UINT32 Size; + /// + /// Length of the EFI_DHCP4_PACKET from the first byte of the Header field + /// to the last byte of the Option[] field. + /// + UINT32 Length; + + struct { + /// + /// DHCP packet header. + /// + EFI_DHCP4_HEADER Header; + /// + /// DHCP magik cookie in network byte order. + /// + UINT32 Magik; + /// + /// Start of the DHCP packed option data. + /// + UINT8 Option[1]; + } Dhcp4; +} EFI_DHCP4_PACKET; +#pragma pack() + + +typedef enum { + /// + /// The EFI DHCPv4 Protocol driver is stopped. + /// + Dhcp4Stopped = 0x0, + /// + /// The EFI DHCPv4 Protocol driver is inactive. + /// + Dhcp4Init = 0x1, + /// + /// The EFI DHCPv4 Protocol driver is collecting DHCP offer packets from DHCP servers. + /// + Dhcp4Selecting = 0x2, + /// + /// The EFI DHCPv4 Protocol driver has sent the request to the DHCP server and is waiting for a response. + /// + Dhcp4Requesting = 0x3, + /// + /// The DHCP configuration has completed. + /// + Dhcp4Bound = 0x4, + /// + /// The DHCP configuration is being renewed and another request has + /// been sent out, but it has not received a response from the server yet. + /// + Dhcp4Renewing = 0x5, + /// + /// The DHCP configuration has timed out and the EFI DHCPv4 + /// Protocol driver is trying to extend the lease time. + /// + Dhcp4Rebinding = 0x6, + /// + /// The EFI DHCPv4 Protocol driver was initialized with a previously + /// allocated or known IP address. + /// + Dhcp4InitReboot = 0x7, + /// + /// The EFI DHCPv4 Protocol driver is seeking to reuse the previously + /// allocated IP address by sending a request to the DHCP server. + /// + Dhcp4Rebooting = 0x8 +} EFI_DHCP4_STATE; + + +typedef enum{ + /// + /// The packet to start the configuration sequence is about to be sent. + /// + Dhcp4SendDiscover = 0x01, + /// + /// A reply packet was just received. + /// + Dhcp4RcvdOffer = 0x02, + /// + /// It is time for Dhcp4Callback to select an offer. + /// + Dhcp4SelectOffer = 0x03, + /// + /// A request packet is about to be sent. + /// + Dhcp4SendRequest = 0x04, + /// + /// A DHCPACK packet was received and will be passed to Dhcp4Callback. + /// + Dhcp4RcvdAck = 0x05, + /// + /// A DHCPNAK packet was received and will be passed to Dhcp4Callback. + /// + Dhcp4RcvdNak = 0x06, + /// + /// A decline packet is about to be sent. + /// + Dhcp4SendDecline = 0x07, + /// + /// The DHCP configuration process has completed. No packet is associated with this event. + /// + Dhcp4BoundCompleted = 0x08, + /// + /// It is time to enter the Dhcp4Renewing state and to contact the server + /// that originally issued the network address. No packet is associated with this event. + /// + Dhcp4EnterRenewing = 0x09, + /// + /// It is time to enter the Dhcp4Rebinding state and to contact any server. + /// No packet is associated with this event. + /// + Dhcp4EnterRebinding = 0x0a, + /// + /// The configured IP address was lost either because the lease has expired, + /// the user released the configuration, or a DHCPNAK packet was received in + /// the Dhcp4Renewing or Dhcp4Rebinding state. No packet is associated with this event. + /// + Dhcp4AddressLost = 0x0b, + /// + /// The DHCP process failed because a DHCPNAK packet was received or the user + /// aborted the DHCP process at a time when the configuration was not available yet. + /// No packet is associated with this event. + /// + Dhcp4Fail = 0x0c +} EFI_DHCP4_EVENT; + +/** + Callback routine. + + EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver + to intercept events that occurred in the configuration process. This structure + provides advanced control of each state transition of the DHCP process. The + returned status code determines the behavior of the EFI DHCPv4 Protocol driver. + There are three possible returned values, which are described in the following + table. + + @param This The pointer to the EFI DHCPv4 Protocol instance that is used to + configure this callback function. + @param Context The pointer to the context that is initialized by + EFI_DHCP4_PROTOCOL.Configure(). + @param CurrentState The current operational state of the EFI DHCPv4 Protocol + driver. + @param Dhcp4Event The event that occurs in the current state, which usually means a + state transition. + @param Packet The DHCP packet that is going to be sent or already received. + @param NewPacket The packet that is used to replace the above Packet. + + @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process. + When it is in the Dhcp4Selecting state, it tells the EFI DHCPv4 Protocol + driver to stop collecting additional packets. The driver will exit + the Dhcp4Selecting state and enter the Dhcp4Requesting state. + @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol + driver will continue to wait for more packets until the retry + timeout expires. + @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process and + return to the Dhcp4Init or Dhcp4InitReboot state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_CALLBACK)( + IN EFI_DHCP4_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP4_STATE CurrentState, + IN EFI_DHCP4_EVENT Dhcp4Event, + IN EFI_DHCP4_PACKET *Packet OPTIONAL, + OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL + ); + +typedef struct { + /// + /// The number of times to try sending a packet during the Dhcp4SendDiscover + /// event and waiting for a response during the Dhcp4RcvdOffer event. + /// Set to zero to use the default try counts and timeout values. + /// + UINT32 DiscoverTryCount; + /// + /// The maximum amount of time (in seconds) to wait for returned packets in each + /// of the retries. Timeout values of zero will default to a timeout value + /// of one second. Set to NULL to use default timeout values. + /// + UINT32 *DiscoverTimeout; + /// + /// The number of times to try sending a packet during the Dhcp4SendRequest event + /// and waiting for a response during the Dhcp4RcvdAck event before accepting + /// failure. Set to zero to use the default try counts and timeout values. + /// + UINT32 RequestTryCount; + /// + /// The maximum amount of time (in seconds) to wait for return packets in each of the retries. + /// Timeout values of zero will default to a timeout value of one second. + /// Set to NULL to use default timeout values. + /// + UINT32 *RequestTimeout; + /// + /// For a DHCPDISCOVER, setting this parameter to the previously allocated IP + /// address will cause the EFI DHCPv4 Protocol driver to enter the Dhcp4InitReboot state. + /// And set this field to 0.0.0.0 to enter the Dhcp4Init state. + /// For a DHCPINFORM this parameter should be set to the client network address + /// which was assigned to the client during a DHCPDISCOVER. + /// + EFI_IPv4_ADDRESS ClientAddress; + /// + /// The callback function to intercept various events that occurred in + /// the DHCP configuration process. Set to NULL to ignore all those events. + /// + EFI_DHCP4_CALLBACK Dhcp4Callback; + /// + /// The pointer to the context that will be passed to Dhcp4Callback when it is called. + /// + VOID *CallbackContext; + /// + /// Number of DHCP options in the OptionList. + /// + UINT32 OptionCount; + /// + /// List of DHCP options to be included in every packet that is sent during the + /// Dhcp4SendDiscover event. Pad options are appended automatically by DHCP driver + /// in outgoing DHCP packets. If OptionList itself contains pad option, they are + /// ignored by the driver. OptionList can be freed after EFI_DHCP4_PROTOCOL.Configure() + /// returns. Ignored if OptionCount is zero. + /// + EFI_DHCP4_PACKET_OPTION **OptionList; +} EFI_DHCP4_CONFIG_DATA; + + +typedef struct { + /// + /// The EFI DHCPv4 Protocol driver operating state. + /// + EFI_DHCP4_STATE State; + /// + /// The configuration data of the current EFI DHCPv4 Protocol driver instance. + /// + EFI_DHCP4_CONFIG_DATA ConfigData; + /// + /// The client IP address that was acquired from the DHCP server. If it is zero, + /// the DHCP acquisition has not completed yet and the following fields in this structure are undefined. + /// + EFI_IPv4_ADDRESS ClientAddress; + /// + /// The local hardware address. + /// + EFI_MAC_ADDRESS ClientMacAddress; + /// + /// The server IP address that is providing the DHCP service to this client. + /// + EFI_IPv4_ADDRESS ServerAddress; + /// + /// The router IP address that was acquired from the DHCP server. + /// May be zero if the server does not offer this address. + /// + EFI_IPv4_ADDRESS RouterAddress; + /// + /// The subnet mask of the connected network that was acquired from the DHCP server. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// The lease time (in 1-second units) of the configured IP address. + /// The value 0xFFFFFFFF means that the lease time is infinite. + /// A default lease of 7 days is used if the DHCP server does not provide a value. + /// + UINT32 LeaseTime; + /// + /// The cached latest DHCPACK or DHCPNAK or BOOTP REPLY packet. May be NULL if no packet is cached. + /// + EFI_DHCP4_PACKET *ReplyPacket; +} EFI_DHCP4_MODE_DATA; + + +typedef struct { + /// + /// Alternate listening address. It can be a unicast, multicast, or broadcast address. + /// + EFI_IPv4_ADDRESS ListenAddress; + /// + /// The subnet mask of above listening unicast/broadcast IP address. + /// Ignored if ListenAddress is a multicast address. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// Alternate station source (or listening) port number. + /// If zero, then the default station port number (68) will be used. + /// + UINT16 ListenPort; +} EFI_DHCP4_LISTEN_POINT; + + +typedef struct { + /// + /// The completion status of transmitting and receiving. + /// + EFI_STATUS Status; + /// + /// If not NULL, the event that will be signaled when the collection process + /// completes. If NULL, this function will busy-wait until the collection process competes. + /// + EFI_EVENT CompletionEvent; + /// + /// The pointer to the server IP address. This address may be a unicast, multicast, or broadcast address. + /// + EFI_IPv4_ADDRESS RemoteAddress; + /// + /// The server listening port number. If zero, the default server listening port number (67) will be used. + /// + UINT16 RemotePort; + /// + /// The pointer to the gateway address to override the existing setting. + /// + EFI_IPv4_ADDRESS GatewayAddress; + /// + /// The number of entries in ListenPoints. If zero, the default station address and port number 68 are used. + /// + UINT32 ListenPointCount; + /// + /// An array of station address and port number pairs that are used as receiving filters. + /// The first entry is also used as the source address and source port of the outgoing packet. + /// + EFI_DHCP4_LISTEN_POINT *ListenPoints; + /// + /// The number of seconds to collect responses. Zero is invalid. + /// + UINT32 TimeoutValue; + /// + /// The pointer to the packet to be transmitted. + /// + EFI_DHCP4_PACKET *Packet; + /// + /// Number of received packets. + /// + UINT32 ResponseCount; + /// + /// The pointer to the allocated list of received packets. + /// + EFI_DHCP4_PACKET *ResponseList; +} EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN; + + +/** + Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver. + + The GetModeData() function returns the current operating mode and cached data + packet for the EFI DHCPv4 Protocol driver. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param Dhcp4ModeData The pointer to storage for the EFI_DHCP4_MODE_DATA structure. + + @retval EFI_SUCCESS The mode data was returned. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_GET_MODE_DATA)( + IN EFI_DHCP4_PROTOCOL *This, + OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData + ); + +/** + Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver. + + The Configure() function is used to initialize, change, or reset the operational + settings of the EFI DHCPv4 Protocol driver for the communication device on which + the EFI DHCPv4 Service Binding Protocol is installed. This function can be + successfully called only if both of the following are true: + * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init, + Dhcp4InitReboot, or Dhcp4Bound states. + * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI + DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4 + Protocol driver. + When this driver is in the Dhcp4Stopped state, it can transfer into one of the + following two possible initial states: + * Dhcp4Init + * Dhcp4InitReboot. + The driver can transfer into these states by calling Configure() with a non-NULL + Dhcp4CfgData. The driver will transfer into the appropriate state based on the + supplied client network address in the ClientAddress parameter and DHCP options + in the OptionList parameter as described in RFC 2131. + When Configure() is called successfully while Dhcp4CfgData is set to NULL, the + default configuring data will be reset in the EFI DHCPv4 Protocol driver and + the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance + wants to make it possible for another instance to configure the EFI DHCPv4 Protocol + driver, it must call this function with Dhcp4CfgData set to NULL. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param Dhcp4CfgData The pointer to the EFI_DHCP4_CONFIG_DATA. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or + Dhcp4InitReboot state, if the original state of this driver + was Dhcp4Stopped, Dhcp4Init,Dhcp4InitReboot, or Dhcp4Bound + and the value of Dhcp4CfgData was not NULL. + Otherwise, the state was left unchanged. + @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the + Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state; + Or onother instance of this EFI DHCPv4 Protocol driver is already + in a valid configured state. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + This is NULL. + DiscoverTryCount > 0 and DiscoverTimeout is NULL + RequestTryCount > 0 and RequestTimeout is NULL. + OptionCount >0 and OptionList is NULL. + ClientAddress is not a valid unicast address. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_CONFIGURE)( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL + ); + + +/** + Starts the DHCP configuration process. + + The Start() function starts the DHCP configuration process. This function can + be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or + Dhcp4InitReboot state. + If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol + driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the + Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL. + If the process aborts, either by the user or by some unexpected network error, + the state is restored to the Dhcp4Init state. The Start() function can be called + again to restart the process. + Refer to RFC 2131 for precise state transitions during this process. At the + time when each event occurs in this process, the callback function that was set + by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this + opportunity to control the process. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param CompletionEvent If not NULL, it indicates the event that will be signaled when the + EFI DHCPv4 Protocol driver is transferred into the + Dhcp4Bound state or when the DHCP process is aborted. + EFI_DHCP4_PROTOCOL.GetModeData() can be called to + check the completion status. If NULL, + EFI_DHCP4_PROTOCOL.Start() will wait until the driver + is transferred into the Dhcp4Bound state or the process fails. + + @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed + when CompletionEvent is NULL. + @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped + state. EFI_DHCP4_PROTOCOL. Configure() needs to be called. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_TIMEOUT The DHCP configuration process failed because no response was + received from the server within the specified timeout value. + @retval EFI_ABORTED The user aborted the DHCP process. + @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the + DHCP process. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NO_MEDIA There was a media error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_START)( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_EVENT CompletionEvent OPTIONAL + ); + +/** + Extends the lease time by sending a request packet. + + The RenewRebind() function is used to manually extend the lease time when the + EFI DHCPv4 Protocol driver is in the Dhcp4Bound state, and the lease time has + not expired yet. This function will send a request packet to the previously + found server (or to any server when RebindRequest is TRUE) and transfer the + state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is + TRUE). When a response is received, the state is returned to Dhcp4Bound. + If no response is received before the try count is exceeded (the RequestTryCount + field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that + was issued by the previous server expires, the driver will return to the Dhcp4Bound + state, and the previous configuration is restored. The outgoing and incoming packets + can be captured by the EFI_DHCP4_CALLBACK function. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param RebindRequest If TRUE, this function broadcasts the request packets and enters + the Dhcp4Rebinding state. Otherwise, it sends a unicast + request packet and enters the Dhcp4Renewing state. + @param CompletionEvent If not NULL, this event is signaled when the renew/rebind phase + completes or some error occurs. + EFI_DHCP4_PROTOCOL.GetModeData() can be called to + check the completion status. If NULL, + EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait + until the DHCP process finishes. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the + Dhcp4Renewing state or is back to the Dhcp4Bound state. + @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped + state. EFI_DHCP4_PROTOCOL.Configure() needs to + be called. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_TIMEOUT There was no response from the server when the try count was + exceeded. + @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_RENEW_REBIND)( + IN EFI_DHCP4_PROTOCOL *This, + IN BOOLEAN RebindRequest, + IN EFI_EVENT CompletionEvent OPTIONAL + ); + +/** + Releases the current address configuration. + + The Release() function releases the current configured IP address by doing either + of the following: + * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the + Dhcp4Bound state + * Setting the previously assigned IP address that was provided with the + EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in + Dhcp4InitReboot state + After a successful call to this function, the EFI DHCPv4 Protocol driver returns + to the Dhcp4Init state, and any subsequent incoming packets will be discarded silently. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_RELEASE)( + IN EFI_DHCP4_PROTOCOL *This + ); + +/** + Stops the current address configuration. + + The Stop() function is used to stop the DHCP configuration process. After this + function is called successfully, the EFI DHCPv4 Protocol driver is transferred + into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called + before DHCP configuration process can be started again. This function can be + called when the EFI DHCPv4 Protocol driver is in any state. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_STOP)( + IN EFI_DHCP4_PROTOCOL *This + ); + +/** + Builds a DHCP packet, given the options to be appended or deleted or replaced. + + The Build() function is used to assemble a new packet from the original packet + by replacing or deleting existing options or appending new options. This function + does not change any state of the EFI DHCPv4 Protocol driver and can be used at + any time. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param SeedPacket Initial packet to be used as a base for building new packet. + @param DeleteCount Number of opcodes in the DeleteList. + @param DeleteList List of opcodes to be deleted from the seed packet. + Ignored if DeleteCount is zero. + @param AppendCount Number of entries in the OptionList. + @param AppendList The pointer to a DHCP option list to be appended to SeedPacket. + If SeedPacket also contains options in this list, they are + replaced by new options (except pad option). Ignored if + AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION + @param NewPacket The pointer to storage for the pointer to the new allocated packet. + Use the EFI Boot Service FreePool() on the resulting pointer + when done with the packet. + + @retval EFI_SUCCESS The new packet was built. + @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + SeedPacket is NULL. + SeedPacket is not a well-formed DHCP packet. + AppendCount is not zero and AppendList is NULL. + DeleteCount is not zero and DeleteList is NULL. + NewPacket is NULL + Both DeleteCount and AppendCount are zero and + NewPacket is not NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_BUILD)( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_PACKET *SeedPacket, + IN UINT32 DeleteCount, + IN UINT8 *DeleteList OPTIONAL, + IN UINT32 AppendCount, + IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL, + OUT EFI_DHCP4_PACKET **NewPacket + ); + + +/** + Transmits a DHCP formatted packet and optionally waits for responses. + + The TransmitReceive() function is used to transmit a DHCP packet and optionally + wait for the response from servers. This function does not change the state of + the EFI DHCPv4 Protocol driver. It can be used at any time because of this. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param Token The pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure. + + @retval EFI_SUCCESS The packet was successfully queued for transmission. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token.RemoteAddress is zero. + Token.Packet is NULL. + Token.Packet is not a well-formed DHCP packet. + The transaction ID in Token.Packet is in use by another DHCP process. + @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call + this function after collection process completes. + @retval EFI_NO_MAPPING The default station address is not available yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_UNSUPPORTED The implementation doesn't support this function + @retval Others Some other unexpected error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_TRANSMIT_RECEIVE)( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token + ); + + +/** + Parses the packed DHCP option data. + + The Parse() function is used to retrieve the option list from a DHCP packet. + If *OptionCount isn't zero, and there is enough space for all the DHCP options + in the Packet, each element of PacketOptionList is set to point to somewhere in + the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported, + the caller should reassemble the parsed DHCP options to get the final result. + If *OptionCount is zero or there isn't enough space for all of them, the number + of DHCP options in the Packet is returned in OptionCount. + + @param This The pointer to the EFI_DHCP4_PROTOCOL instance. + @param Packet The pointer to packet to be parsed. + @param OptionCount On input, the number of entries in the PacketOptionList. + On output, the number of entries that were written into the + PacketOptionList. + @param PacketOptionList A list of packet option entries to be filled in. End option or pad + options are not included. + + @retval EFI_SUCCESS The packet was successfully parsed. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + The packet is NULL. + The packet is not a well-formed DHCP packet. + OptionCount is NULL. + @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE: + 1) *OptionCount is smaller than the number of options that + were found in the Packet. + 2) PacketOptionList is NULL. + @retval EFI_OUT_OF_RESOURCE The packet failed to parse because of a resource shortage. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_PARSE)( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_PACKET *Packet, + IN OUT UINT32 *OptionCount, + OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL + ); + +/// +/// This protocol is used to collect configuration information for the EFI IPv4 Protocol drivers +/// and to provide DHCPv4 server and PXE boot server discovery services. +/// +struct _EFI_DHCP4_PROTOCOL { + EFI_DHCP4_GET_MODE_DATA GetModeData; + EFI_DHCP4_CONFIGURE Configure; + EFI_DHCP4_START Start; + EFI_DHCP4_RENEW_REBIND RenewRebind; + EFI_DHCP4_RELEASE Release; + EFI_DHCP4_STOP Stop; + EFI_DHCP4_BUILD Build; + EFI_DHCP4_TRANSMIT_RECEIVE TransmitReceive; + EFI_DHCP4_PARSE Parse; +}; + +extern EFI_GUID gEfiDhcp4ProtocolGuid; +extern EFI_GUID gEfiDhcp4ServiceBindingProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp6.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp6.h new file mode 100644 index 0000000..339fc12 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dhcp6.h @@ -0,0 +1,786 @@ +/** @file + UEFI Dynamic Host Configuration Protocol 6 Definition, which is used to get IPv6 + addresses and other configuration parameters from DHCPv6 servers. + + Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_DHCP6_PROTOCOL_H__ +#define __EFI_DHCP6_PROTOCOL_H__ + +#define EFI_DHCP6_PROTOCOL_GUID \ + { \ + 0x87c8bad7, 0x595, 0x4053, {0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b } \ + } + +#define EFI_DHCP6_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x9fb9a8a1, 0x2f4a, 0x43a6, {0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4, 0x7a, 0xd5 } \ + } + +typedef struct _EFI_DHCP6_PROTOCOL EFI_DHCP6_PROTOCOL; + +typedef enum { + /// + /// The EFI DHCPv6 Protocol instance is configured, and start() needs + /// to be called + /// + Dhcp6Init = 0x0, + /// + /// A Solicit packet is sent out to discover DHCPv6 server, and the EFI + /// DHCPv6 Protocol instance is collecting Advertise packets. + /// + Dhcp6Selecting = 0x1, + /// + /// A Request is sent out to the DHCPv6 server, and the EFI DHCPv6 + /// Protocol instance is waiting for Reply packet. + /// + Dhcp6Requesting = 0x2, + /// + /// A Decline packet is sent out to indicate one or more addresses of the + /// configured IA are in use by another node, and the EFI DHCPv6. + /// Protocol instance is waiting for Reply packet. + /// + Dhcp6Declining = 0x3, + /// + /// A Confirm packet is sent out to confirm the IPv6 addresses of the + /// configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet. + /// + Dhcp6Confirming = 0x4, + /// + /// A Release packet is sent out to release one or more IPv6 addresses of + /// the configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet. + /// + Dhcp6Releasing = 0x5, + /// + /// The DHCPv6 S.A.R.R process is completed for the configured IA. + /// + Dhcp6Bound = 0x6, + /// + /// A Renew packet is sent out to extend lifetime for the IPv6 addresses of + /// the configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet. + /// + Dhcp6Renewing = 0x7, + /// + /// A Rebind packet is sent out to extend lifetime for the IPv6 addresses of + /// the configured IA, and the EFI DHCPv6 Protocol instance is waiting for Reply packet. + /// + Dhcp6Rebinding = 0x8 +} EFI_DHCP6_STATE; + +typedef enum { + /// + /// A Solicit packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6SendSolicit = 0x0, + /// + /// An Advertise packet is received and will be passed to Dhcp6Callback. + /// + Dhcp6RcvdAdvertise = 0x1, + /// + /// It is time for Dhcp6Callback to determine whether select the default Advertise + /// packet by RFC 3315 policy, or overwrite it by specific user policy. + /// + Dhcp6SelectAdvertise = 0x2, + /// + /// A Request packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6SendRequest = 0x3, + /// + /// A Reply packet is received and will be passed to Dhcp6Callback. + /// + Dhcp6RcvdReply = 0x4, + /// + /// A Reconfigure packet is received and will be passed to Dhcp6Callback. + /// + Dhcp6RcvdReconfigure = 0x5, + /// + /// A Decline packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6SendDecline = 0x6, + /// + /// A Confirm packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6SendConfirm = 0x7, + /// + /// A Release packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6SendRelease = 0x8, + /// + /// A Renew packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6EnterRenewing = 0x9, + /// + /// A Rebind packet is about to be sent. The packet is passed to Dhcp6Callback and + /// can be modified or replaced in Dhcp6Callback. + /// + Dhcp6EnterRebinding = 0xa +} EFI_DHCP6_EVENT; + +/// +/// An IA which carries assigned not temporary address. +/// +#define EFI_DHCP6_IA_TYPE_NA 3 +/// +/// An IA which carries assigned temporary address. +/// +#define EFI_DHCP6_IA_TYPE_TA 4 + +#pragma pack(1) +/// +/// EFI_DHCP6_PACKET_OPTION +/// defines the format of the DHCPv6 option, See RFC 3315 for more information. +/// This data structure is used to reference option data that is packed in the DHCPv6 packet. +/// +typedef struct { + /// + /// The DHCPv6 option code, stored in network order. + /// + UINT16 OpCode; + /// + /// Length of the DHCPv6 option data, stored in network order. + /// From the first byte to the last byte of the Data field. + /// + UINT16 OpLen; + /// + /// The data for the DHCPv6 option, stored in network order. + /// + UINT8 Data[1]; +} EFI_DHCP6_PACKET_OPTION; + +/// +/// EFI_DHCP6_HEADER +/// defines the format of the DHCPv6 header. See RFC 3315 for more information. +/// +typedef struct{ + /// + /// The DHCPv6 transaction ID. + /// + UINT32 MessageType:8; + /// + /// The DHCPv6 message type. + /// + UINT32 TransactionId:24; +} EFI_DHCP6_HEADER; + +/// +/// EFI_DHCP6_PACKET +/// defines the format of the DHCPv6 packet. See RFC 3315 for more information. +/// +typedef struct { + /// + /// Size of the EFI_DHCP6_PACKET buffer. + /// + UINT32 Size; + /// + /// Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last + /// byte of the Option[] field. + /// + UINT32 Length; + struct{ + /// + /// The DHCPv6 packet header. + /// + EFI_DHCP6_HEADER Header; + /// + /// Start of the DHCPv6 packed option data. + /// + UINT8 Option[1]; + } Dhcp6; +} EFI_DHCP6_PACKET; + +#pragma pack() + +typedef struct { + /// + /// Length of DUID in octects. + /// + UINT16 Length; + /// + /// Array of DUID octects. + /// + UINT8 Duid[1]; +} EFI_DHCP6_DUID; + +typedef struct { + /// + /// Initial retransmission timeout. + /// + UINT32 Irt; + /// + /// Maximum retransmission count for one packet. If Mrc is zero, there's no upper limit + /// for retransmission count. + /// + UINT32 Mrc; + /// + /// Maximum retransmission timeout for each retry. It's the upper bound of the number of + /// retransmission timeout. If Mrt is zero, there is no upper limit for retransmission + /// timeout. + /// + UINT32 Mrt; + /// + /// Maximum retransmission duration for one packet. It's the upper bound of the numbers + /// the client may retransmit a message. If Mrd is zero, there's no upper limit for + /// retransmission duration. + /// + UINT32 Mrd; +} EFI_DHCP6_RETRANSMISSION; + +typedef struct { + /// + /// The IPv6 address. + /// + EFI_IPv6_ADDRESS IpAddress; + /// + /// The preferred lifetime in unit of seconds for the IPv6 address. + /// + UINT32 PreferredLifetime; + /// + /// The valid lifetime in unit of seconds for the IPv6 address. + /// + UINT32 ValidLifetime; +} EFI_DHCP6_IA_ADDRESS; + +typedef struct { + UINT16 Type; ///< Type for an IA. + UINT32 IaId; ///< The identifier for an IA. +} EFI_DHCP6_IA_DESCRIPTOR; + +typedef struct { + /// + /// The descriptor for IA. + /// + EFI_DHCP6_IA_DESCRIPTOR Descriptor; + /// + /// The state of the configured IA. + /// + EFI_DHCP6_STATE State; + /// + /// Pointer to the cached latest Reply packet. May be NULL if no packet is cached. + /// + EFI_DHCP6_PACKET *ReplyPacket; + /// + /// Number of IPv6 addresses of the configured IA. + /// + UINT32 IaAddressCount; + /// + /// List of the IPv6 addresses of the configured IA. When the state of the configured IA is + /// in Dhcp6Bound, Dhcp6Renewing and Dhcp6Rebinding, the IPv6 addresses are usable. + /// + EFI_DHCP6_IA_ADDRESS IaAddress[1]; +} EFI_DHCP6_IA; + +typedef struct { + /// + /// Pointer to the DHCPv6 unique identifier. The caller is responsible for freeing this buffer. + /// + EFI_DHCP6_DUID *ClientId; + /// + /// Pointer to the configured IA of current instance. The caller can free this buffer after + /// using it. + /// + EFI_DHCP6_IA *Ia; +} EFI_DHCP6_MODE_DATA; + +/** + EFI_DHCP6_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol instance to + intercept events that occurs in the DHCPv6 S.A.R.R process. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance that is used to configure this + callback function. + @param[in] Context Pointer to the context that is initialized by EFI_DHCP6_PROTOCOL.Configure(). + @param[in] CurrentState The current state of the configured IA. + @param[in] Dhcp6Event The event that occurs in the current state, which usually means a state transition. + @param[in] Packet Pointer to the DHCPv6 packet that is about to be sent or has been received. + The EFI DHCPv6 Protocol instance is responsible for freeing the buffer. + @param[out] NewPacket Pointer to the new DHCPv6 packet to overwrite the Packet. NewPacket can not + share the buffer with Packet. If *NewPacket is not NULL, the EFI DHCPv6 + Protocol instance is responsible for freeing the buffer. + + @retval EFI_SUCCESS Tell the EFI DHCPv6 Protocol instance to continue the DHCPv6 S.A.R.R process. + @retval EFI_ABORTED Tell the EFI DHCPv6 Protocol instance to abort the DHCPv6 S.A.R.R process, + and the state of the configured IA will be transferred to Dhcp6Init. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_CALLBACK)( + IN EFI_DHCP6_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP6_STATE CurrentState, + IN EFI_DHCP6_EVENT Dhcp6Event, + IN EFI_DHCP6_PACKET *Packet, + OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL + ); + +typedef struct { + /// + /// The callback function is to intercept various events that occur in the DHCPv6 S.A.R.R + /// process. Set to NULL to ignore all those events. + /// + EFI_DHCP6_CALLBACK Dhcp6Callback; + /// + /// Pointer to the context that will be passed to Dhcp6Callback. + /// + VOID *CallbackContext; + /// + /// Number of the DHCPv6 options in the OptionList. + /// + UINT32 OptionCount; + /// + /// List of the DHCPv6 options to be included in Solicit and Request packet. The buffer + /// can be freed after EFI_DHCP6_PROTOCOL.Configure() returns. Ignored if + /// OptionCount is zero. OptionList should not contain Client Identifier option + /// and any IA option, which will be appended by EFI DHCPv6 Protocol instance + /// automatically. + /// + EFI_DHCP6_PACKET_OPTION **OptionList; + /// + /// The descriptor for the IA of the EFI DHCPv6 Protocol instance. + /// + EFI_DHCP6_IA_DESCRIPTOR IaDescriptor; + /// + /// If not NULL, the event will be signaled when any IPv6 address information of the + /// configured IA is updated, including IPv6 address, preferred lifetime and valid + /// lifetime, or the DHCPv6 S.A.R.R process fails. Otherwise, Start(), + /// renewrebind(), decline(), release() and stop() will be blocking + /// operations, and they will wait for the exchange process completion or failure. + /// + EFI_EVENT IaInfoEvent; + /// + /// If TRUE, the EFI DHCPv6 Protocol instance is willing to accept Reconfigure packet. + /// Otherwise, it will ignore it. Reconfigure Accept option can not be specified through + /// OptionList parameter. + /// + BOOLEAN ReconfigureAccept; + /// + /// If TRUE, the EFI DHCPv6 Protocol instance will send Solicit packet with Rapid + /// Commit option. Otherwise, Rapid Commit option will not be included in Solicit + /// packet. Rapid Commit option can not be specified through OptionList parameter. + /// + BOOLEAN RapidCommit; + /// + /// Parameter to control Solicit packet retransmission behavior. The + /// buffer can be freed after EFI_DHCP6_PROTOCOL.Configure() returns. + /// + EFI_DHCP6_RETRANSMISSION *SolicitRetransmission; +} EFI_DHCP6_CONFIG_DATA; + +/** + EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol + instance to intercept events that occurs in the DHCPv6 Information Request exchange process. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance that is used to configure this + callback function. + @param[in] Context Pointer to the context that is initialized in the EFI_DHCP6_PROTOCOL.InfoRequest(). + @param[in] Packet Pointer to Reply packet that has been received. The EFI DHCPv6 Protocol instance is + responsible for freeing the buffer. + + @retval EFI_SUCCESS Tell the EFI DHCPv6 Protocol instance to finish Information Request exchange process. + @retval EFI_NOT_READY Tell the EFI DHCPv6 Protocol instance to continue Information Request exchange process. + @retval EFI_ABORTED Tell the EFI DHCPv6 Protocol instance to abort the Information Request exchange process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_INFO_CALLBACK)( + IN EFI_DHCP6_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP6_PACKET *Packet + ); + +/** + Retrieve the current operating mode data and configuration data for the EFI DHCPv6 Protocol instance. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + @param[out] Dhcp6ModeData Pointer to the DHCPv6 mode data structure. The caller is responsible for freeing this + structure and each reference buffer. + @param[out] Dhcp6ConfigData Pointer to the DHCPv6 configuration data structure. The caller is responsible for + freeing this structure and each reference buffer. + + @retval EFI_SUCCESS The mode data was returned. + @retval EFI_ACCESS_DENIED The EFI DHCPv6 Protocol instance has not been configured when Dhcp6ConfigData is not NULL. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + - This is NULL. + - Both Dhcp6ConfigData and Dhcp6ModeData are NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_GET_MODE_DATA)( + IN EFI_DHCP6_PROTOCOL *This, + OUT EFI_DHCP6_MODE_DATA *Dhcp6ModeData OPTIONAL, + OUT EFI_DHCP6_CONFIG_DATA *Dhcp6ConfigData OPTIONAL + ); + +/** + Initialize or clean up the configuration data for the EFI DHCPv6 Protocol instance. + + The Configure() function is used to initialize or clean up the configuration data of the EFI + DHCPv6 Protocol instance. + - When Dhcp6CfgData is not NULL and Configure() is called successfully, the + configuration data will be initialized in the EFI DHCPv6 Protocol instance and the state of the + configured IA will be transferred into Dhcp6Init. + - When Dhcp6CfgData is NULL and Configure() is called successfully, the configuration + data will be cleaned up and no IA will be associated with the EFI DHCPv6 Protocol instance. + + To update the configuration data for an EFI DCHPv6 Protocol instance, the original data must be + cleaned up before setting the new configuration data. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + @param[in] Dhcp6CfgData Pointer to the DHCPv6 configuration data structure. + + @retval EFI_SUCCESS The mode data was returned. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE + - This is NULL. + - OptionCount > 0 and OptionList is NULL. + - OptionList is not NULL, and Client Id option, Reconfigure Accept option, + Rapid Commit option or any IA option is specified in the OptionList. + - IaDescriptor.Type is neither EFI_DHCP6_IA_TYPE_NA nor EFI_DHCP6_IA_TYPE_NA. + - IaDescriptor is not unique. + - Both IaInfoEvent and SolicitRetransimssion are NULL. + - SolicitRetransmission is not NULL, and both SolicitRetransimssion->Mrc and + SolicitRetransmission->Mrd are zero. + @retval EFI_ACCESS_DENIED The EFI DHCPv6 Protocol instance has been already configured + when Dhcp6CfgData is not NULL. + The EFI DHCPv6 Protocol instance has already started the + DHCPv6 S.A.R.R when Dhcp6CfgData is NULL. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_CONFIGURE)( + IN EFI_DHCP6_PROTOCOL *This, + IN EFI_DHCP6_CONFIG_DATA *Dhcp6CfgData OPTIONAL + ); + +/** + Start the DHCPv6 S.A.R.R process. + + The Start() function starts the DHCPv6 S.A.R.R process. This function can be called only when + the state of the configured IA is in the Dhcp6Init state. If the DHCPv6 S.A.R.R process completes + successfully, the state of the configured IA will be transferred through Dhcp6Selecting and + Dhcp6Requesting to Dhcp6Bound state. The update of the IPv6 addresses will be notified through + EFI_DHCP6_CONFIG_DATA.IaInfoEvent. At the time when each event occurs in this process, the + callback function set by EFI_DHCP6_PROTOCOL.Configure() will be called and the user can take + this opportunity to control the process. If EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, the + Start() function call is a blocking operation. It will return after the DHCPv6 S.A.R.R process + completes or aborted by users. If the process is aborted by system or network error, the state of + the configured IA will be transferred to Dhcp6Init. The Start() function can be called again to + restart the process. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + + @retval EFI_SUCCESS The DHCPv6 S.A.R.R process is completed and at least one IPv6 + address has been bound to the configured IA when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL. + The DHCPv6 S.A.R.R process is started when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL. + @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ALREADY_STARTED The DHCPv6 S.A.R.R process has already started. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_NO_RESPONSE The DHCPv6 S.A.R.R process failed because of no response. + @retval EFI_NO_MAPPING No IPv6 address has been bound to the configured IA after the + DHCPv6 S.A.R.R process. + @retval EFI_ABORTED The DHCPv6 S.A.R.R process aborted by user. + @retval EFI_NO_MEDIA There was a media error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_START)( + IN EFI_DHCP6_PROTOCOL *This + ); + +/** + Request configuration information without the assignment of any IA addresses of the client. + + The InfoRequest() function is used to request configuration information without the assignment + of any IPv6 address of the client. Client sends out Information Request packet to obtain + the required configuration information, and DHCPv6 server responds with Reply packet containing + the information for the client. The received Reply packet will be passed to the user by + ReplyCallback function. If user returns EFI_NOT_READY from ReplyCallback, the EFI DHCPv6 + Protocol instance will continue to receive other Reply packets unless timeout according to + the Retransmission parameter. Otherwise, the Information Request exchange process will be + finished successfully if user returns EFI_SUCCESS from ReplyCallback. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + @param[in] SendClientId If TRUE, the EFI DHCPv6 Protocol instance will build Client + Identifier option and include it into Information Request + packet. If FALSE, Client Identifier option will not be included. + Client Identifier option can not be specified through OptionList + parameter. + @param[in] OptionRequest Pointer to the Option Request option in the Information Request + packet. Option Request option can not be specified through + OptionList parameter. + @param[in] OptionCount Number of options in OptionList. + @param[in] OptionList List of other DHCPv6 options. These options will be appended + to the Option Request option. The caller is responsible for + freeing this buffer. Type is defined in EFI_DHCP6_PROTOCOL.GetModeData(). + @param[in] Retransmission Parameter to control Information Request packet retransmission + behavior. The buffer can be freed after EFI_DHCP6_PROTOCOL.InfoRequest() + returns. + @param[in] TimeoutEvent If not NULL, this event is signaled when the information request + exchange aborted because of no response. If NULL, the function + call is a blocking operation; and it will return after the + information-request exchange process finish or aborted by users. + @param[in] ReplyCallback The callback function is to intercept various events that occur + in the Information Request exchange process. It should not be + set to NULL. + @param[in] CallbackContext Pointer to the context that will be passed to ReplyCallback. + + @retval EFI_SUCCESS The DHCPv6 S.A.R.R process is completed and at least one IPv6 + @retval EFI_SUCCESS The DHCPv6 information request exchange process completed + when TimeoutEvent is NULL. Information Request packet has been + sent to DHCPv6 server when TimeoutEvent is not NULL. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + - This is NULL. + - OptionRequest is NULL or OptionRequest->OpCode is invalid. + - OptionCount > 0 and OptionList is NULL. + - OptionList is not NULL, and Client Identify option or + Option Request option is specified in the OptionList. + - Retransimssion is NULL. + - Both Retransimssion->Mrc and Retransmission->Mrd are zero. + - ReplyCallback is NULL. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_NO_RESPONSE The DHCPv6 information request exchange process failed + because of no response, or not all requested-options are + responded by DHCPv6 servers when Timeout happened. + @retval EFI_ABORTED The DHCPv6 information request exchange process aborted by user. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_INFO_REQUEST)( + IN EFI_DHCP6_PROTOCOL *This, + IN BOOLEAN SendClientId, + IN EFI_DHCP6_PACKET_OPTION *OptionRequest, + IN UINT32 OptionCount, + IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL, + IN EFI_DHCP6_RETRANSMISSION *Retransmission, + IN EFI_EVENT TimeoutEvent OPTIONAL, + IN EFI_DHCP6_INFO_CALLBACK ReplyCallback, + IN VOID *CallbackContext OPTIONAL + ); + +/** + Manually extend the valid and preferred lifetimes for the IPv6 addresses of the configured + IA and update other configuration parameters by sending Renew or Rebind packet. + + The RenewRebind() function is used to manually extend the valid and preferred lifetimes for the + IPv6 addresses of the configured IA and update other configuration parameters by sending Renew or + Rebind packet. + - When RebindRequest is FALSE and the state of the configured IA is Dhcp6Bound, it + will send Renew packet to the previously DHCPv6 server and transfer the state of the configured + IA to Dhcp6Renewing. If valid Reply packet received, the state transfers to Dhcp6Bound + and the valid and preferred timer restarts. If fails, the state transfers to Dhcp6Bound but the + timer continues. + - When RebindRequest is TRUE and the state of the configured IA is Dhcp6Bound, it will + send Rebind packet. If valid Reply packet received, the state transfers to Dhcp6Bound and the + valid and preferred timer restarts. If fails, the state transfers to Dhcp6Init and the IA can't + be used. + + @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param[in] RebindRequest If TRUE, it will send Rebind packet and enter the Dhcp6Rebinding state. + Otherwise, it will send Renew packet and enter the Dhcp6Renewing state. + + @retval EFI_SUCCESS The DHCPv6 renew/rebind exchange process has completed and at + least one IPv6 address of the configured IA has been bound again + when EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL. + The EFI DHCPv6 Protocol instance has sent Renew or Rebind packet + when EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL. + @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured, or the state + of the configured IA is not in Dhcp6Bound. + @retval EFI_ALREADY_STARTED The state of the configured IA has already entered Dhcp6Renewing + when RebindRequest is FALSE. + The state of the configured IA has already entered Dhcp6Rebinding + when RebindRequest is TRUE. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or system error occurred. + @retval EFI_NO_RESPONSE The DHCPv6 renew/rebind exchange process failed because of no response. + @retval EFI_NO_MAPPING No IPv6 address has been bound to the configured IA after the DHCPv6 + renew/rebind exchange process. + @retval EFI_ABORTED The DHCPv6 renew/rebind exchange process aborted by user. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_RENEW_REBIND)( + IN EFI_DHCP6_PROTOCOL *This, + IN BOOLEAN RebindRequest + ); + +/** + Inform that one or more IPv6 addresses assigned by a server are already in use by + another node. + + The Decline() function is used to manually decline the assignment of IPv6 addresses, which + have been already used by another node. If all IPv6 addresses of the configured IA are declined + through this function, the state of the IA will switch through Dhcp6Declining to Dhcp6Init, + otherwise, the state of the IA will restore to Dhcp6Bound after the declining process. The + Decline() can only be called when the IA is in Dhcp6Bound state. If the + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, this function is a blocking operation. It + will return after the declining process finishes, or aborted by user. + + @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param[in] AddressCount Number of declining IPv6 addresses. + @param[in] Addresses Pointer to the buffer stored all the declining IPv6 addresses. + + @retval EFI_SUCCESS The DHCPv6 decline exchange process has completed when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL. + The EFI DHCPv6 Protocol instance has sent Decline packet when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE + - This is NULL. + - AddressCount is zero or Addresses is NULL. + @retval EFI_NOT_FOUND Any specified IPv6 address is not correlated with the configured IA + for this instance. + @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured, or the + state of the configured IA is not in Dhcp6Bound. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_ABORTED The DHCPv6 decline exchange process aborted by user. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_DECLINE)( + IN EFI_DHCP6_PROTOCOL *This, + IN UINT32 AddressCount, + IN EFI_IPv6_ADDRESS *Addresses + ); + +/** + Release one or more IPv6 addresses associated with the configured IA for current instance. + + The Release() function is used to manually release the one or more IPv6 address. If AddressCount + is zero, it will release all IPv6 addresses of the configured IA. If all IPv6 addresses of the IA + are released through this function, the state of the IA will switch through Dhcp6Releasing to + Dhcp6Init, otherwise, the state of the IA will restore to Dhcp6Bound after the releasing process. + The Release() can only be called when the IA is in Dhcp6Bound state. If the + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, the function is a blocking operation. It will return + after the releasing process finishes, or aborted by user. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + @param[in] AddressCount Number of releasing IPv6 addresses. + @param[in] Addresses Pointer to the buffer stored all the releasing IPv6 addresses. + Ignored if AddressCount is zero. + @retval EFI_SUCCESS The DHCPv6 release exchange process has completed when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL. + The EFI DHCPv6 Protocol instance has sent Release packet when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE + - This is NULL. + - AddressCount is not zero or Addresses is NULL. + @retval EFI_NOT_FOUND Any specified IPv6 address is not correlated with the configured + IA for this instance. + @retval EFI_ACCESS_DENIED The EFI DHCPv6 Child instance hasn't been configured, or the + state of the configured IA is not in Dhcp6Bound. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_ABORTED The DHCPv6 release exchange process aborted by user. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_RELEASE)( + IN EFI_DHCP6_PROTOCOL *This, + IN UINT32 AddressCount, + IN EFI_IPv6_ADDRESS *Addresses + ); + +/** + Stop the DHCPv6 S.A.R.R process. + + The Stop() function is used to stop the DHCPv6 S.A.R.R process. If this function is called + successfully, all the IPv6 addresses of the configured IA will be released and the state of + the configured IA will be transferred to Dhcp6Init. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + + @retval EFI_SUCCESS The DHCPv6 S.A.R.R process has been stopped when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL. + The EFI DHCPv6 Protocol instance has sent Release packet if + need release or has been stopped if needn't, when + EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_STOP)( + IN EFI_DHCP6_PROTOCOL *This + ); + +/** + Parse the option data in the DHCPv6 packet. + + The Parse() function is used to retrieve the option list in the DHCPv6 packet. + + @param[in] This Pointer to the EFI_DHCP6_PROTOCOL instance. + + @param[in] Packet Pointer to packet to be parsed. + @param[in] OptionCount On input, the number of entries in the PacketOptionList. + On output, the number of DHCPv6 options in the Packet. + @param[in] PacketOptionList List of pointers to the DHCPv6 options in the Packet. + The OpCode and OpLen in EFI_DHCP6_PACKET_OPTION are + both stored in network byte order. + @retval EFI_SUCCESS The packet was successfully parsed. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE + - This is NULL. + - Packet is NULL. + - Packet is not a well-formed DHCPv6 packet. + - OptionCount is NULL. + - *OptionCount is not zero and PacketOptionList is NULL. + @retval EFI_BUFFER_TOO_SMALL *OptionCount is smaller than the number of options that were + found in the Packet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP6_PARSE)( + IN EFI_DHCP6_PROTOCOL *This, + IN EFI_DHCP6_PACKET *Packet, + IN OUT UINT32 *OptionCount, + OUT EFI_DHCP6_PACKET_OPTION *PacketOptionList[] OPTIONAL +); + +/// +/// The EFI DHCPv6 Protocol is used to get IPv6 addresses and other configuration parameters +/// from DHCPv6 servers. +/// +struct _EFI_DHCP6_PROTOCOL { + EFI_DHCP6_GET_MODE_DATA GetModeData; + EFI_DHCP6_CONFIGURE Configure; + EFI_DHCP6_START Start; + EFI_DHCP6_INFO_REQUEST InfoRequest; + EFI_DHCP6_RENEW_REBIND RenewRebind; + EFI_DHCP6_DECLINE Decline; + EFI_DHCP6_RELEASE Release; + EFI_DHCP6_STOP Stop; + EFI_DHCP6_PARSE Parse; +}; + +extern EFI_GUID gEfiDhcp6ProtocolGuid; +extern EFI_GUID gEfiDhcp6ServiceBindingProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskInfo.h new file mode 100644 index 0000000..f9294ff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskInfo.h @@ -0,0 +1,227 @@ +/** @file + Provides the basic interfaces to abstract platform information regarding an + IDE controller. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.6 + Volume 5: Standards + +**/ + +#ifndef __DISK_INFO_H__ +#define __DISK_INFO_H__ + +/// +/// Global ID for EFI_DISK_INFO_PROTOCOL +/// +#define EFI_DISK_INFO_PROTOCOL_GUID \ + { \ + 0xd432a67f, 0x14dc, 0x484b, {0xb3, 0xbb, 0x3f, 0x2, 0x91, 0x84, 0x93, 0x27 } \ + } + +/// +/// Forward declaration for EFI_DISK_INFO_PROTOCOL +/// +typedef struct _EFI_DISK_INFO_PROTOCOL EFI_DISK_INFO_PROTOCOL; + +/// +/// Global ID for an IDE interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_IDE_INTERFACE_GUID \ + { \ + 0x5e948fe3, 0x26d3, 0x42b5, {0xaf, 0x17, 0x61, 0x2, 0x87, 0x18, 0x8d, 0xec } \ + } + +/// +/// Global ID for a SCSI interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_SCSI_INTERFACE_GUID \ + { \ + 0x8f74baa, 0xea36, 0x41d9, {0x95, 0x21, 0x21, 0xa7, 0xf, 0x87, 0x80, 0xbc } \ + } + +/// +/// Global ID for a USB interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_USB_INTERFACE_GUID \ + { \ + 0xcb871572, 0xc11a, 0x47b5, {0xb4, 0x92, 0x67, 0x5e, 0xaf, 0xa7, 0x77, 0x27 } \ + } + +/// +/// Global ID for an AHCI interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_AHCI_INTERFACE_GUID \ + { \ + 0x9e498932, 0x4abc, 0x45af, {0xa3, 0x4d, 0x2, 0x47, 0x78, 0x7b, 0xe7, 0xc6 } \ + } + +/// +/// Global ID for a NVME interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_NVME_INTERFACE_GUID \ + { \ + 0x3ab14680, 0x5d3f, 0x4a4d, {0xbc, 0xdc, 0xcc, 0x38, 0x0, 0x18, 0xc7, 0xf7 } \ + } + +/// +/// Global ID for a UFS interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_UFS_INTERFACE_GUID \ + { \ + 0x4b3029cc, 0x6b98, 0x47fb, { 0xbc, 0x96, 0x76, 0xdc, 0xb8, 0x4, 0x41, 0xf0 } \ + } + +/// +/// Global ID for an SD/MMC interface. Used to fill in EFI_DISK_INFO_PROTOCOL.Interface +/// +#define EFI_DISK_INFO_SD_MMC_INTERFACE_GUID \ + { \ + 0x8deec992, 0xd39c, 0x4a5c, { 0xab, 0x6b, 0x98, 0x6e, 0x14, 0x24, 0x2b, 0x9d } \ + } + +/** + Provides inquiry information for the controller type. + + This function is used by the IDE bus driver to get inquiry data. Data format + of Identify data is defined by the Interface GUID. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[in,out] InquiryData Pointer to a buffer for the inquiry data. + @param[in,out] InquiryDataSize Pointer to the value for the inquiry data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_INQUIRY)( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *InquiryDataSize + ); + +/** + Provides identify information for the controller type. + + This function is used by the IDE bus driver to get identify data. Data format + of Identify data is defined by the Interface GUID. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL + instance. + @param[in,out] IdentifyData Pointer to a buffer for the identify data. + @param[in,out] IdentifyDataSize Pointer to the value for the identify data + size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading IdentifyData from device + @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_IDENTIFY)( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ); + +/** + Provides sense data information for the controller type. + + This function is used by the IDE bus driver to get sense data. + Data format of Sense data is defined by the Interface GUID. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[in,out] SenseData Pointer to the SenseData. + @param[in,out] SenseDataSize Size of SenseData in bytes. + @param[out] SenseDataNumber Pointer to the value for the sense data size. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_NOT_FOUND Device does not support this data class. + @retval EFI_DEVICE_ERROR Error reading SenseData from device. + @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_SENSE_DATA)( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ); + +/** + This function is used by the IDE bus driver to get controller information. + + @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. + @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary. + @param[out] IdeDevice Pointer to the Ide Device number. Master or slave. + + @retval EFI_SUCCESS IdeChannel and IdeDevice are valid. + @retval EFI_UNSUPPORTED This is not an IDE device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_WHICH_IDE)( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ); + +/// +/// The EFI_DISK_INFO_PROTOCOL provides controller specific information. +/// +struct _EFI_DISK_INFO_PROTOCOL { + /// + /// A GUID that defines the format of buffers for the other member functions + /// of this protocol. + /// + EFI_GUID Interface; + /// + /// Return the results of the Inquiry command to a drive in InquiryData. Data + /// format of Inquiry data is defined by the Interface GUID. + /// + EFI_DISK_INFO_INQUIRY Inquiry; + /// + /// Return the results of the Identify command to a drive in IdentifyData. Data + /// format of Identify data is defined by the Interface GUID. + /// + EFI_DISK_INFO_IDENTIFY Identify; + /// + /// Return the results of the Request Sense command to a drive in SenseData. Data + /// format of Sense data is defined by the Interface GUID. + /// + EFI_DISK_INFO_SENSE_DATA SenseData; + /// + /// Specific controller. + /// + EFI_DISK_INFO_WHICH_IDE WhichIde; +}; + +extern EFI_GUID gEfiDiskInfoProtocolGuid; + +extern EFI_GUID gEfiDiskInfoIdeInterfaceGuid; +extern EFI_GUID gEfiDiskInfoScsiInterfaceGuid; +extern EFI_GUID gEfiDiskInfoUsbInterfaceGuid; +extern EFI_GUID gEfiDiskInfoAhciInterfaceGuid; +extern EFI_GUID gEfiDiskInfoNvmeInterfaceGuid; +extern EFI_GUID gEfiDiskInfoUfsInterfaceGuid; +extern EFI_GUID gEfiDiskInfoSdMmcInterfaceGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo.h new file mode 100644 index 0000000..c0c6e3b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo.h @@ -0,0 +1,117 @@ +/** @file + Disk IO protocol as defined in the UEFI 2.0 specification. + + The Disk IO protocol is used to convert block oriented devices into byte + oriented devices. The Disk IO protocol is intended to layer on top of the + Block IO protocol. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DISK_IO_H__ +#define __DISK_IO_H__ + +#define EFI_DISK_IO_PROTOCOL_GUID \ + { \ + 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define DISK_IO_PROTOCOL EFI_DISK_IO_PROTOCOL_GUID + +typedef struct _EFI_DISK_IO_PROTOCOL EFI_DISK_IO_PROTOCOL; + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_DISK_IO_PROTOCOL EFI_DISK_IO; + +/** + Read BufferSize bytes from Offset into Buffer. + + @param This Protocol instance pointer. + @param MediaId Id of the media, changes every time the media is replaced. + @param Offset The starting byte offset to read from + @param BufferSize Size of Buffer + @param Buffer Buffer containing read data + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not + valid for the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_READ)( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Writes a specified number of bytes to a device. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to be written. + @param Offset The starting byte offset on the logical block I/O device to write. + @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device. + @param Buffer A pointer to the buffer containing the data to be written. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not + valid for the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_WRITE)( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +#define EFI_DISK_IO_PROTOCOL_REVISION 0x00010000 + +/// +/// Revision defined in EFI1.1 +/// +#define EFI_DISK_IO_INTERFACE_REVISION EFI_DISK_IO_PROTOCOL_REVISION + +/// +/// This protocol is used to abstract Block I/O interfaces. +/// +struct _EFI_DISK_IO_PROTOCOL { + /// + /// The revision to which the disk I/O interface adheres. All future + /// revisions must be backwards compatible. If a future version is not + /// backwards compatible, it is not the same GUID. + /// + UINT64 Revision; + EFI_DISK_READ ReadDisk; + EFI_DISK_WRITE WriteDisk; +}; + +extern EFI_GUID gEfiDiskIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo2.h new file mode 100644 index 0000000..0fca0fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DiskIo2.h @@ -0,0 +1,172 @@ +/** @file + Disk I/O 2 protocol as defined in the UEFI 2.4 specification. + + The Disk I/O 2 protocol defines an extension to the Disk I/O protocol to enable + non-blocking / asynchronous byte-oriented disk operation. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DISK_IO2_H__ +#define __DISK_IO2_H__ + +#define EFI_DISK_IO2_PROTOCOL_GUID \ + { \ + 0x151c8eae, 0x7f2c, 0x472c, 0x9e, 0x54, 0x98, 0x28, 0x19, 0x4f, 0x6a, 0x88 \ + } + +typedef struct _EFI_DISK_IO2_PROTOCOL EFI_DISK_IO2_PROTOCOL; + +/** + The struct of Disk IO2 Token. +**/ +typedef struct { + // + // 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 I/O request is completed. + // The caller must be prepared to handle the case where the callback associated with Event occurs + // before the original asynchronous I/O request call returns. + // + EFI_EVENT Event; + + // + // Defines whether or not the signaled event encountered an error. + // + EFI_STATUS TransactionStatus; +} EFI_DISK_IO2_TOKEN; + +/** + Terminate outstanding asynchronous requests to a device. + + @param This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding requests were successfully terminated. + @retval EFI_DEVICE_ERROR The device reported an error while performing the cancel + operation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_CANCEL_EX) ( + IN EFI_DISK_IO2_PROTOCOL *This + ); + +/** + Reads a specified number of bytes from a device. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to be read. + @param Offset The starting byte offset on the logical block I/O device to read from. + @param Token A pointer to the token associated with the transaction. + If this field is NULL, synchronous/blocking IO is performed. + @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device. + @param Buffer A pointer to the destination buffer for the data. + The caller is responsible either having implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read correctly from the device. + If Event is not NULL (asynchronous I/O): The request was successfully queued for processing. + Event will be signaled upon completion. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no medium in the device. + @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium. + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not valid for the device. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_READ_EX) ( + IN EFI_DISK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN OUT EFI_DISK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Writes a specified number of bytes to a device. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to be written. + @param Offset The starting byte offset on the logical block I/O device to write to. + @param Token A pointer to the token associated with the transaction. + If this field is NULL, synchronous/blocking IO is performed. + @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device. + @param Buffer A pointer to the buffer containing the data to be written. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was written correctly to the device. + If Event is not NULL (asynchronous I/O): The request was successfully queued for processing. + Event will be signaled upon completion. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation. + @retval EFI_NO_MEDIA There is no medium in the device. + @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium. + @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not valid for the device. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_WRITE_EX) ( + IN EFI_DISK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN OUT EFI_DISK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flushes all modified data to the physical device. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to be written. + @param Token A pointer to the token associated with the transaction. + If this field is NULL, synchronous/blocking IO is performed. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was flushed successfully to the device. + If Event is not NULL (asynchronous I/O): The request was successfully queued for processing. + Event will be signaled upon completion. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation. + @retval EFI_NO_MEDIA There is no medium in the device. + @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_FLUSH_EX) ( + IN EFI_DISK_IO2_PROTOCOL *This, + IN OUT EFI_DISK_IO2_TOKEN *Token + ); + +#define EFI_DISK_IO2_PROTOCOL_REVISION 0x00020000 + +/// +/// This protocol is used to abstract Block I/O interfaces. +/// +struct _EFI_DISK_IO2_PROTOCOL { + /// + /// The revision to which the disk I/O interface adheres. All future + /// revisions must be backwards compatible. If a future version is not + /// backwards compatible, it is not the same GUID. + /// + UINT64 Revision; + EFI_DISK_CANCEL_EX Cancel; + EFI_DISK_READ_EX ReadDiskEx; + EFI_DISK_WRITE_EX WriteDiskEx; + EFI_DISK_FLUSH_EX FlushDiskEx; +}; + +extern EFI_GUID gEfiDiskIo2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns4.h new file mode 100644 index 0000000..2f3c57f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns4.h @@ -0,0 +1,543 @@ +/** @file + This file defines the EFI Domain Name Service Binding Protocol interface. It is split + into the following two main sections: + DNSv4 Service Binding Protocol (DNSv4SB) + DNSv4 Protocol (DNSv4) + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_DNS4_PROTOCOL_H__ +#define __EFI_DNS4_PROTOCOL_H__ + +#define EFI_DNS4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xb625b186, 0xe063, 0x44f7, {0x89, 0x5, 0x6a, 0x74, 0xdc, 0x6f, 0x52, 0xb4 } \ + } + +#define EFI_DNS4_PROTOCOL_GUID \ + { \ + 0xae3d28cc, 0xe05b, 0x4fa1, {0xa0, 0x11, 0x7e, 0xb5, 0x5a, 0x3f, 0x14, 0x1 } \ + } + +typedef struct _EFI_DNS4_PROTOCOL EFI_DNS4_PROTOCOL; + +/// +/// EFI_DNS4_CONFIG_DATA +/// +typedef struct { + /// + /// Count of the DNS servers. When used with GetModeData(), + /// this field is the count of originally configured servers when + /// Configure() was called for this instance. When used with + /// Configure() this is the count of caller-supplied servers. If the + /// DnsServerListCount is zero, the DNS server configuration + /// will be retrieved from DHCP server automatically. + /// + UINTN DnsServerListCount; + /// + /// Pointer to DNS server list containing DnsServerListCount entries or NULL + /// if DnsServerListCountis 0. For Configure(), this will be NULL when there are + /// no caller supplied server addresses, and, the DNS instance will retrieve + /// DNS server from DHCP Server. The provided DNS server list is + /// recommended to be filled up in the sequence of preference. When + /// used with GetModeData(), the buffer containing the list will + /// be allocated by the driver implementing this protocol and must be + /// freed by the caller. When used with Configure(), the buffer + /// containing the list will be allocated and released by the caller. + /// + EFI_IPv4_ADDRESS *DnsServerList; + /// + /// Set to TRUE to use the default IP address/subnet mask and default routing table. + /// + BOOLEAN UseDefaultSetting; + /// + /// If TRUE, enable DNS cache function for this DNS instance. If FALSE, all DNS + /// query will not lookup local DNS cache. + /// + BOOLEAN EnableDnsCache; + /// + /// Use the protocol number defined in "Links to UEFI-Related + /// Documents"(http://uefi.org/uefi) under the heading "IANA + /// Protocol Numbers". Only TCP or UDP are supported, and other + /// protocol values are invalid. An implementation can choose to + /// support only UDP, or both TCP and UDP. + /// + UINT8 Protocol; + /// + /// If UseDefaultSetting is FALSE indicates the station address to use. + /// + EFI_IPv4_ADDRESS StationIp; + /// + /// If UseDefaultSetting is FALSE indicates the subnet mask to use. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// Local port number. Set to zero to use the automatically assigned port number. + /// + UINT16 LocalPort; + /// + /// Retry number if no response received after RetryInterval. + /// + UINT32 RetryCount; + /// + /// Minimum interval of retry is 2 second. If the retry interval is less than 2 + /// seconds, then use the 2 seconds. + /// + UINT32 RetryInterval; +} EFI_DNS4_CONFIG_DATA; + + +/// +/// EFI_DNS4_CACHE_ENTRY +/// +typedef struct { + /// + /// Host name. + /// + CHAR16 *HostName; + /// + /// IP address of this host. + /// + EFI_IPv4_ADDRESS *IpAddress; + /// + /// Time in second unit that this entry will remain in DNS cache. A value of zero + /// means that this entry is permanent. A nonzero value will override the existing + /// one if this entry to be added is dynamic entry. Implementations may set its + /// default timeout value for the dynamically created DNS cache entry after one DNS + /// resolve succeeds. + /// + UINT32 Timeout; +} EFI_DNS4_CACHE_ENTRY; + +/// +/// EFI_DNS4_MODE_DATA +/// +typedef struct { + /// + /// The configuration data of this instance. + /// + EFI_DNS4_CONFIG_DATA DnsConfigData; + /// + /// Number of configured DNS server. Each DNS instance has its own DNS server + /// configuration. + /// + UINT32 DnsServerCount; + /// + /// Pointer to common list of addresses of all configured DNS server + /// used by EFI_DNS4_PROTOCOL instances. List will include + /// DNS servers configured by this or any other EFI_DNS4_PROTOCOL instance. + /// The storage for this list is allocated by the driver publishing this + /// protocol, and must be freed by the caller. + /// + EFI_IPv4_ADDRESS *DnsServerList; + /// + /// Number of DNS Cache entries. The DNS Cache is shared among all DNS instances. + /// + UINT32 DnsCacheCount; + /// + /// Pointer to a buffer containing DnsCacheCount DNS Cache + /// entry structures. The storage for this list is allocated by the driver + /// publishing this protocol and must be freed by caller. + /// + EFI_DNS4_CACHE_ENTRY *DnsCacheList; +} EFI_DNS4_MODE_DATA; + +/// +/// DNS_HOST_TO_ADDR_DATA +/// +typedef struct { + /// + /// Number of the returned IP addresses. + /// + UINT32 IpCount; + /// + /// Pointer to the all the returned IP addresses. + /// + EFI_IPv4_ADDRESS *IpList; +} DNS_HOST_TO_ADDR_DATA; + +/// +/// DNS_ADDR_TO_HOST_DATA +/// +typedef struct { + /// + /// Pointer to the primary name for this host address. It's the caller's + /// responsibility to free the response memory. + /// + CHAR16 *HostName; +} DNS_ADDR_TO_HOST_DATA; + +/// +/// DNS_RESOURCE_RECORD +/// +typedef struct { + /// + /// The Owner name. + /// + CHAR8 *QName; + /// + /// The Type Code of this RR. + /// + UINT16 QType; + /// + /// The CLASS code of this RR. + /// + UINT16 QClass; + /// + /// 32 bit integer which specify the time interval that the resource record may be + /// cached before the source of the information should again be consulted. Zero means + /// this RR can not be cached. + /// + UINT32 TTL; + /// + /// 16 big integer which specify the length of RData. + /// + UINT16 DataLength; + /// + /// A string of octets that describe the resource, the format of this information + /// varies according to QType and QClass difference. + /// + CHAR8 *RData; +} DNS_RESOURCE_RECORD; + +/// +/// DNS_GENERAL_LOOKUP_DATA +/// +typedef struct { + /// + /// Number of returned matching RRs. + /// + UINTN RRCount; + /// + /// Pointer to the all the returned matching RRs. It's caller responsibility to free + /// the allocated memory to hold the returned RRs. + /// + DNS_RESOURCE_RECORD *RRList; +} DNS_GENERAL_LOOKUP_DATA; + +/// +/// EFI_DNS4_COMPLETION_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI DNS + /// protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: The host name to address translation completed successfully. + /// EFI_NOT_FOUND: No matching Resource Record (RR) is found. + /// EFI_TIMEOUT: No DNS server reachable, or RetryCount was exhausted without + /// response from all specified DNS servers. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// EFI_NO_MEDIA: There was a media error. + /// + EFI_STATUS Status; + /// + /// Retry number if no response received after RetryInterval. If zero, use the + /// parameter configured through Dns.Configure() interface. + /// + UINT32 RetryCount; + /// + /// Minimum interval of retry is 2 second. If the retry interval is less than 2 + /// seconds, then use the 2 seconds. If zero, use the parameter configured through + /// Dns.Configure() interface. + UINT32 RetryInterval; + /// + /// DNSv4 completion token data + /// + union { + /// + /// When the Token is used for host name to address translation, H2AData is a pointer + /// to the DNS_HOST_TO_ADDR_DATA. + /// + DNS_HOST_TO_ADDR_DATA *H2AData; + /// + /// When the Token is used for host address to host name translation, A2HData is a + /// pointer to the DNS_ADDR_TO_HOST_DATA. + /// + DNS_ADDR_TO_HOST_DATA *A2HData; + /// + /// When the Token is used for a general lookup function, GLookupDATA is a pointer to + /// the DNS_GENERAL_LOOKUP_DATA. + /// + DNS_GENERAL_LOOKUP_DATA *GLookupData; + } RspData; +} EFI_DNS4_COMPLETION_TOKEN; + +/** + Retrieve mode data of this DNS instance. + + This function is used to retrieve DNS mode data for this DNS instance. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[out] DnsModeData Point to the mode data. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data + is available because this instance has not been + configured. + @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL. + @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_GET_MODE_DATA) ( + IN EFI_DNS4_PROTOCOL *This, + OUT EFI_DNS4_MODE_DATA *DnsModeData + ); + +/** + Configure this DNS instance. + + This function is used to configure DNS mode data for this DNS instance. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[in] DnsConfigData Point to the Configuration data. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED The designated protocol is not supported. + @retval EFI_INVALID_PARAMETER This is NULL. + The StationIp address provided in DnsConfigData is not a + valid unicast. + DnsServerList is NULL while DnsServerListCount + is not ZERO. + DnsServerListCount is ZERO while DnsServerList + is not NULL + @retval EFI_OUT_OF_RESOURCES The DNS instance data or required space could not be + allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The + EFI DNSv4 Protocol instance is not configured. + @retval EFI_ALREADY_STARTED Second call to Configure() with DnsConfigData. To + reconfigure the instance the caller must call Configure() + with NULL first to return driver to unconfigured state. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_CONFIGURE) ( + IN EFI_DNS4_PROTOCOL *This, + IN EFI_DNS4_CONFIG_DATA *DnsConfigData + ); + +/** + Host name to host address translation. + + The HostNameToIp () function is used to translate the host name to host IP address. A + type A query is used to get the one or more IP addresses for this host. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[in] HostName Host name. + @param[in] Token Point to the completion token to translate host name + to host address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token.Event is NULL. + HostName is NULL. HostName string is unsupported format. + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_NOT_STARTED This instance has not been started. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_HOST_NAME_TO_IP) ( + IN EFI_DNS4_PROTOCOL *This, + IN CHAR16 *HostName, + IN EFI_DNS4_COMPLETION_TOKEN *Token + ); + +/** + IPv4 address to host name translation also known as Reverse DNS lookup. + + The IpToHostName() function is used to translate the host address to host name. A type PTR + query is used to get the primary name of the host. Support of this function is optional. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[in] IpAddress Ip Address. + @param[in] Token Point to the completion token to translate host + address to host name. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token.Event is NULL. + IpAddress is not valid IP address . + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_ALREADY_STARTED This Token is being used in another DNS session. + @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_IP_TO_HOST_NAME) ( + IN EFI_DNS4_PROTOCOL *This, + IN EFI_IPv4_ADDRESS IpAddress, + IN EFI_DNS4_COMPLETION_TOKEN *Token + ); + +/** + Retrieve arbitrary information from the DNS server. + + This GeneralLookup() function retrieves arbitrary information from the DNS. The caller + supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. All + RR content (e.g., TTL) was returned. The caller need parse the returned RR to get + required information. The function is optional. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[in] QName Pointer to Query Name. + @param[in] QType Query Type. + @param[in] QClass Query Name. + @param[in] Token Point to the completion token to retrieve arbitrary + information. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED This function is not supported. Or the requested + QType is not supported + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token.Event is NULL. + QName is NULL. + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_ALREADY_STARTED This Token is being used in another DNS session. + @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_GENERAL_LOOKUP) ( + IN EFI_DNS4_PROTOCOL *This, + IN CHAR8 *QName, + IN UINT16 QType, + IN UINT16 QClass, + IN EFI_DNS4_COMPLETION_TOKEN *Token + ); + +/** + This function is to update the DNS Cache. + + The UpdateDnsCache() function is used to add/delete/modify DNS cache entry. DNS cache + can be normally dynamically updated after the DNS resolve succeeds. This function + provided capability to manually add/delete/modify the DNS cache. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[in] DeleteFlag If FALSE, this function is to add one entry to the + DNS Cahce. If TRUE, this function will delete + matching DNS Cache entry. + @param[in] Override If TRUE, the maching DNS cache entry will be + overwritten with the supplied parameter. If FALSE, + EFI_ACCESS_DENIED will be returned if the entry to + be added is already existed. + @param[in] DnsCacheEntry Pointer to DNS Cache entry. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DnsCacheEntry.HostName is NULL. + DnsCacheEntry.IpAddress is NULL. + DnsCacheEntry.Timeout is zero. + @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is + not TRUE. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_UPDATE_DNS_CACHE) ( + IN EFI_DNS4_PROTOCOL *This, + IN BOOLEAN DeleteFlag, + IN BOOLEAN Override, + IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function can be used by network drivers and applications to increase the + rate that data packets are moved between the communications device and the transmit + and receive queues. + In some systems, the periodic timer event in the managed network driver may not poll + the underlying communications device fast enough to transmit and/or receive all data + packets without missing incoming packets or dropping outgoing packets. Drivers and + applications that are experiencing packet loss should try calling the Poll() + function more often. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive + queue. Consider increasing the polling rate. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_POLL) ( + IN EFI_DNS4_PROTOCOL *This + ); + +/** + Abort an asynchronous DNS operation, including translation between IP and Host, and + general look up behavior. + + The Cancel() function is used to abort a pending resolution request. After calling + this function, Token.Status will be set to EFI_ABORTED and then Token.Event will be + signaled. If the token is not in one of the queues, which usually means that the + asynchronous operation has completed, this function will not signal the token and + EFI_NOT_FOUND is returned. + + @param[in] This Pointer to EFI_DNS4_PROTOCOL instance. + @param[in] Token Pointer to a token that has been issued by + EFI_DNS4_PROTOCOL.HostNameToIp (), + EFI_DNS4_PROTOCOL.IpToHostName() or + EFI_DNS4_PROTOCOL.GeneralLookup(). + If NULL, all pending tokens are aborted. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI DNS4 Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS + operation was not found in the transmit queue. It + was either completed or was not issued by + HostNameToIp(), IpToHostName() or GeneralLookup(). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS4_CANCEL) ( + IN EFI_DNS4_PROTOCOL *This, + IN EFI_DNS4_COMPLETION_TOKEN *Token + ); + +/// +/// The EFI_DNS4_Protocol provides the function to get the host name and address +/// mapping, also provides pass through interface to retrieve arbitrary information +/// from DNS. +/// +struct _EFI_DNS4_PROTOCOL { + EFI_DNS4_GET_MODE_DATA GetModeData; + EFI_DNS4_CONFIGURE Configure; + EFI_DNS4_HOST_NAME_TO_IP HostNameToIp; + EFI_DNS4_IP_TO_HOST_NAME IpToHostName; + EFI_DNS4_GENERAL_LOOKUP GeneralLookUp; + EFI_DNS4_UPDATE_DNS_CACHE UpdateDnsCache; + EFI_DNS4_POLL Poll; + EFI_DNS4_CANCEL Cancel; +}; + +extern EFI_GUID gEfiDns4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiDns4ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns6.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns6.h new file mode 100644 index 0000000..e8c7c25 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Dns6.h @@ -0,0 +1,539 @@ +/** @file + This file defines the EFI DNSv6 (Domain Name Service version 6) Protocol. It is split + into the following two main sections: + DNSv6 Service Binding Protocol (DNSv6SB) + DNSv6 Protocol (DNSv6) + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_DNS6_PROTOCOL_H__ +#define __EFI_DNS6_PROTOCOL_H__ + +#define EFI_DNS6_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x7f1647c8, 0xb76e, 0x44b2, {0xa5, 0x65, 0xf7, 0xf, 0xf1, 0x9c, 0xd1, 0x9e } \ + } + +#define EFI_DNS6_PROTOCOL_GUID \ + { \ + 0xca37bc1f, 0xa327, 0x4ae9, {0x82, 0x8a, 0x8c, 0x40, 0xd8, 0x50, 0x6a, 0x17 } \ + } + +typedef struct _EFI_DNS6_PROTOCOL EFI_DNS6_PROTOCOL; + +/// +/// EFI_DNS6_CONFIG_DATA +/// +typedef struct { + /// + /// If TRUE, enable DNS cache function for this DNS instance. If FALSE, all DNS query + /// will not lookup local DNS cache. + /// + BOOLEAN EnableDnsCache; + /// + /// Use the protocol number defined in + /// http://www.iana.org/assignments/protocol-numbers. Beside TCP/UDP, Other protocol + /// is invalid value. An implementation can choose to support UDP, or both TCP and UDP. + /// + UINT8 Protocol; + /// + /// The local IP address to use. Set to zero to let the underlying IPv6 + /// driver choose a source address. If not zero it must be one of the + /// configured IP addresses in the underlying IPv6 driver. + /// + EFI_IPv6_ADDRESS StationIp; + /// + /// Local port number. Set to zero to use the automatically assigned port number. + /// + UINT16 LocalPort; + /// + /// Count of the DNS servers. When used with GetModeData(), + /// this field is the count of originally configured servers when + /// Configure() was called for this instance. When used with + /// Configure() this is the count of caller-supplied servers. If the + /// DnsServerListCount is zero, the DNS server configuration + /// will be retrieved from DHCP server automatically. + /// + UINT32 DnsServerCount; + /// + /// Pointer to DNS server list containing DnsServerListCount + /// entries or NULL if DnsServerListCount is 0. For Configure(), + /// this will be NULL when there are no caller supplied server addresses + /// and the DNS instance will retrieve DNS server from DHCP Server. + /// The provided DNS server list is recommended to be filled up in the sequence + /// of preference. When used with GetModeData(), the buffer containing the list + /// will be allocated by the driver implementing this protocol and must be + /// freed by the caller. When used with Configure(), the buffer + /// containing the list will be allocated and released by the caller. + /// + EFI_IPv6_ADDRESS *DnsServerList; + /// + /// Retry number if no response received after RetryInterval. + /// + UINT32 RetryCount; + /// + /// Minimum interval of retry is 2 second. If the retry interval is less than 2 + /// seconds, then use the 2 seconds. + UINT32 RetryInterval; +} EFI_DNS6_CONFIG_DATA; + +/// +/// EFI_DNS6_CACHE_ENTRY +/// +typedef struct { + /// + /// Host name. This should be interpreted as Unicode characters. + /// + CHAR16 *HostName; + /// + /// IP address of this host. + /// + EFI_IPv6_ADDRESS *IpAddress; + /// + /// Time in second unit that this entry will remain in DNS cache. A value of zero means + /// that this entry is permanent. A nonzero value will override the existing one if + /// this entry to be added is dynamic entry. Implementations may set its default + /// timeout value for the dynamically created DNS cache entry after one DNS resolve + /// succeeds. + UINT32 Timeout; +} EFI_DNS6_CACHE_ENTRY; + +/// +/// EFI_DNS6_MODE_DATA +/// +typedef struct { + /// + /// The configuration data of this instance. + /// + EFI_DNS6_CONFIG_DATA DnsConfigData; + /// + /// Number of configured DNS6 servers. + /// + UINT32 DnsServerCount; + /// + /// Pointer to common list of addresses of all configured DNS server used by EFI_DNS6_PROTOCOL + /// instances. List will include DNS servers configured by this or any other EFI_DNS6_PROTOCOL + /// instance. The storage for this list is allocated by the driver publishing this protocol, + /// and must be freed by the caller. + /// + EFI_IPv6_ADDRESS *DnsServerList; + /// + /// Number of DNS Cache entries. The DNS Cache is shared among all DNS instances. + /// + UINT32 DnsCacheCount; + /// + /// Pointer to a buffer containing DnsCacheCount DNS Cache + /// entry structures. The storage for thislist is allocated by the driver + /// publishing this protocol and must be freed by caller. + /// + EFI_DNS6_CACHE_ENTRY *DnsCacheList; +} EFI_DNS6_MODE_DATA; + +/// +/// DNS6_HOST_TO_ADDR_DATA +/// +typedef struct { + /// + /// Number of the returned IP address. + /// + UINT32 IpCount; + /// + /// Pointer to the all the returned IP address. + /// + EFI_IPv6_ADDRESS *IpList; +} DNS6_HOST_TO_ADDR_DATA; + +/// +/// DNS6_ADDR_TO_HOST_DATA +/// +typedef struct { + /// + /// Pointer to the primary name for this host address. It's the caller's + /// responsibility to free the response memory. + /// + CHAR16 *HostName; +} DNS6_ADDR_TO_HOST_DATA; + +/// +/// DNS6_RESOURCE_RECORD +/// +typedef struct { + /// + /// The Owner name. + /// + CHAR8 *QName; + /// + /// The Type Code of this RR. + /// + UINT16 QType; + /// + /// The CLASS code of this RR. + /// + UINT16 QClass; + /// + /// 32 bit integer which specify the time interval that the resource record may be + /// cached before the source of the information should again be consulted. Zero means + /// this RR cannot be cached. + /// + UINT32 TTL; + /// + /// 16 big integer which specify the length of RData. + /// + UINT16 DataLength; + /// + /// A string of octets that describe the resource, the format of this information + /// varies according to QType and QClass difference. + /// + CHAR8 *RData; +} DNS6_RESOURCE_RECORD; + +/// +/// DNS6_GENERAL_LOOKUP_DATA +/// +typedef struct { + /// + /// Number of returned matching RRs. + /// + UINTN RRCount; + /// + /// Pointer to the all the returned matching RRs. It's caller responsibility to free + /// the allocated memory to hold the returned RRs. + /// + DNS6_RESOURCE_RECORD *RRList; +} DNS6_GENERAL_LOOKUP_DATA; + +/// +/// EFI_DNS6_COMPLETION_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI DNSv6 + /// protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: The host name to address translation completed successfully. + /// EFI_NOT_FOUND: No matching Resource Record (RR) is found. + /// EFI_TIMEOUT: No DNS server reachable, or RetryCount was exhausted without + /// response from all specified DNS servers. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// EFI_NO_MEDIA: There was a media error. + /// + EFI_STATUS Status; + /// + /// The parameter configured through DNSv6.Configure() interface. Retry number if no + /// response received after RetryInterval. + /// + UINT32 RetryCount; + /// + /// The parameter configured through DNSv6.Configure() interface. Minimum interval of + /// retry is 2 seconds. If the retry interval is less than 2 seconds, then use the 2 + /// seconds. + /// + UINT32 RetryInterval; + /// + /// DNSv6 completion token data + /// + union { + /// + /// When the Token is used for host name to address translation, H2AData is a pointer + /// to the DNS6_HOST_TO_ADDR_DATA. + /// + DNS6_HOST_TO_ADDR_DATA *H2AData; + /// + /// When the Token is used for host address to host name translation, A2HData is a + /// pointer to the DNS6_ADDR_TO_HOST_DATA. + /// + DNS6_ADDR_TO_HOST_DATA *A2HData; + /// + /// When the Token is used for a general lookup function, GLookupDATA is a pointer to + /// the DNS6_GENERAL_LOOKUP_DATA. + /// + DNS6_GENERAL_LOOKUP_DATA *GLookupData; + } RspData; +} EFI_DNS6_COMPLETION_TOKEN; + +/** + Retrieve mode data of this DNS instance. + + This function is used to retrieve DNS mode data for this DNS instance. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[out] DnsModeData Pointer to the caller-allocated storage for the + EFI_DNS6_MODE_DATA data. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED When DnsConfigData is queried, no configuration data + is available because this instance has not been + configured. + @retval EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL. + @retval EFI_OUT_OF_RESOURCE Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_DNS6_GET_MODE_DATA)( + IN EFI_DNS6_PROTOCOL *This, + OUT EFI_DNS6_MODE_DATA *DnsModeData + ); + +/** + Configure this DNS instance. + + The Configure() function is used to set and change the configuration data for this + EFI DNSv6 Protocol driver instance. Reset the DNS instance if DnsConfigData is NULL. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[in] DnsConfigData Pointer to the configuration data structure. All associated + storage to be allocated and released by caller. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + The StationIp address provided in DnsConfigData is not zero and not a valid unicast. + DnsServerList is NULL while DnsServerList Count is not ZERO. + DnsServerList Count is ZERO while DnsServerList is not NULL. + @retval EFI_OUT_OF_RESOURCES The DNS instance data or required space could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The + EFI DNSv6 Protocol instance is not configured. + @retval EFI_UNSUPPORTED The designated protocol is not supported. + @retval EFI_ALREADY_STARTED Second call to Configure() with DnsConfigData. To + reconfigure the instance the caller must call Configure() with + NULL first to return driver to unconfigured state. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_DNS6_CONFIGURE)( + IN EFI_DNS6_PROTOCOL *This, + IN EFI_DNS6_CONFIG_DATA *DnsConfigData + ); + +/** + Host name to host address translation. + + The HostNameToIp () function is used to translate the host name to host IP address. A + type AAAA query is used to get the one or more IPv6 addresses for this host. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[in] HostName Host name. + @param[in] Token Point to the completion token to translate host name + to host address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token.Event is NULL. + HostName is NULL or buffer contained unsupported characters. + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_ALREADY_STARTED This Token is being used in another DNS session. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS6_HOST_NAME_TO_IP) ( + IN EFI_DNS6_PROTOCOL *This, + IN CHAR16 *HostName, + IN EFI_DNS6_COMPLETION_TOKEN *Token + ); + +/** + Host address to host name translation. + + The IpToHostName () function is used to translate the host address to host name. A + type PTR query is used to get the primary name of the host. Implementation can choose + to support this function or not. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[in] IpAddress Ip Address. + @param[in] Token Point to the completion token to translate host + address to host name. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED This function is not supported. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token.Event is NULL. + IpAddress is not valid IP address. + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS6_IP_TO_HOST_NAME) ( + IN EFI_DNS6_PROTOCOL *This, + IN EFI_IPv6_ADDRESS IpAddress, + IN EFI_DNS6_COMPLETION_TOKEN *Token + ); + +/** + This function provides capability to retrieve arbitrary information from the DNS + server. + + This GeneralLookup() function retrieves arbitrary information from the DNS. The caller + supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned. All + RR content (e.g., TTL) was returned. The caller need parse the returned RR to get + required information. The function is optional. Implementation can choose to support + it or not. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[in] QName Pointer to Query Name. + @param[in] QType Query Type. + @param[in] QClass Query Name. + @param[in] Token Point to the completion token to retrieve arbitrary + information. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED This function is not supported. Or the requested + QType is not supported + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token.Event is NULL. + QName is NULL. + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS6_GENERAL_LOOKUP) ( + IN EFI_DNS6_PROTOCOL *This, + IN CHAR8 *QName, + IN UINT16 QType, + IN UINT16 QClass, + IN EFI_DNS6_COMPLETION_TOKEN *Token + ); + +/** + This function is to update the DNS Cache. + + The UpdateDnsCache() function is used to add/delete/modify DNS cache entry. DNS cache + can be normally dynamically updated after the DNS resolve succeeds. This function + provided capability to manually add/delete/modify the DNS cache. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[in] DeleteFlag If FALSE, this function is to add one entry to the + DNS Cahce. If TRUE, this function will delete + matching DNS Cache entry. + @param[in] Override If TRUE, the maching DNS cache entry will be + overwritten with the supplied parameter. If FALSE, + EFI_ACCESS_DENIED will be returned if the entry to + be added is already existed. + @param[in] DnsCacheEntry Pointer to DNS Cache entry. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DnsCacheEntry.HostName is NULL. + DnsCacheEntry.IpAddress is NULL. + DnsCacheEntry.Timeout is zero. + @retval EFI_ACCESS_DENIED The DNS cache entry already exists and Override is + not TRUE. + @retval EFI_OUT_OF_RESOURCE Failed to allocate needed resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS6_UPDATE_DNS_CACHE) ( + IN EFI_DNS6_PROTOCOL *This, + IN BOOLEAN DeleteFlag, + IN BOOLEAN Override, + IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function can be used by network drivers and applications to increase the + rate that data packets are moved between the communications device and the transmit + and receive queues. + + In some systems, the periodic timer event in the managed network driver may not poll + the underlying communications device fast enough to transmit and/or receive all data + packets without missing incoming packets or dropping outgoing packets. Drivers and + applications that are experiencing packet loss should try calling the Poll() + function more often. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI DNS Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NO_MAPPING There is no source address is available for use. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive + queue. Consider increasing the polling rate. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS6_POLL) ( + IN EFI_DNS6_PROTOCOL *This + ); + +/** + Abort an asynchronous DNS operation, including translation between IP and Host, and + general look up behavior. + + The Cancel() function is used to abort a pending resolution request. After calling + this function, Token.Status will be set to EFI_ABORTED and then Token.Event will be + signaled. If the token is not in one of the queues, which usually means that the + asynchronous operation has completed, this function will not signal the token and + EFI_NOT_FOUND is returned. + + @param[in] This Pointer to EFI_DNS6_PROTOCOL instance. + @param[in] Token Pointer to a token that has been issued by + EFI_DNS6_PROTOCOL.HostNameToIp (), + EFI_DNS6_PROTOCOL.IpToHostName() or + EFI_DNS6_PROTOCOL.GeneralLookup(). + If NULL, all pending tokens are aborted. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI DNS6 Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NO_MAPPING There's no source address is available for use. + @retval EFI_NOT_FOUND When Token is not NULL, and the asynchronous DNS + operation was not found in the transmit queue. It + was either completed or was not issued by + HostNameToIp(), IpToHostName() or GeneralLookup(). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DNS6_CANCEL) ( + IN EFI_DNS6_PROTOCOL *This, + IN EFI_DNS6_COMPLETION_TOKEN *Token + ); + +/// +/// The EFI_DNS6_PROTOCOL provides the function to get the host name and address +/// mapping, also provide pass through interface to retrieve arbitrary information from +/// DNSv6. +/// +struct _EFI_DNS6_PROTOCOL { + EFI_DNS6_GET_MODE_DATA GetModeData; + EFI_DNS6_CONFIGURE Configure; + EFI_DNS6_HOST_NAME_TO_IP HostNameToIp; + EFI_DNS6_IP_TO_HOST_NAME IpToHostName; + EFI_DNS6_GENERAL_LOOKUP GeneralLookUp; + EFI_DNS6_UPDATE_DNS_CACHE UpdateDnsCache; + EFI_DNS6_POLL Poll; + EFI_DNS6_CANCEL Cancel; +}; + +extern EFI_GUID gEfiDns6ServiceBindingProtocolGuid; +extern EFI_GUID gEfiDns6ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverBinding.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverBinding.h new file mode 100644 index 0000000..29f55c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverBinding.h @@ -0,0 +1,201 @@ +/** @file + UEFI DriverBinding Protocol is defined in UEFI specification. + + This protocol is produced by every driver that follows the UEFI Driver Model, + and it is the central component that allows drivers and controllers to be managed. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DRIVER_BINDING_H__ +#define __EFI_DRIVER_BINDING_H__ + +/// +/// The global ID for the ControllerHandle Driver Protocol. +/// +#define EFI_DRIVER_BINDING_PROTOCOL_GUID \ + { \ + 0x18a031ab, 0xb443, 0x4d1a, {0xa5, 0xc0, 0xc, 0x9, 0x26, 0x1e, 0x9f, 0x71 } \ + } + +typedef struct _EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL; + +/** + Tests to see if this driver supports a given controller. If a child device is provided, + it further tests to see if this driver supports creating a handle for the specified child device. + + This function checks to see if the driver specified by This supports the device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attached to + ControllerHandle to determine if the driver supports ControllerHandle. This function + may be called many times during platform initialization. In order to reduce boot times, the tests + performed by this function must be very small, and take as little time as possible to execute. This + function must not change the state of any hardware devices, and this function must be aware that the + device specified by ControllerHandle may already be managed by the same driver or a + different driver. This function must match its calls to AllocatePages() with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same driver, if a protocol is + already in the opened state, then it must not be closed with CloseProtocol(). This is required + to guarantee the state of ControllerHandle is not modified by this function. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For bus drivers, if this parameter is not NULL, then + the bus driver must determine if the bus controller specified + by ControllerHandle and the child controller specified + by RemainingDevicePath are both supported by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandle and + RemainingDevicePath is supported by the driver specified by This. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and + RemainingDevicePath is already being managed by the driver + specified by This. + @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and + RemainingDevicePath is already being managed by a different + driver or an application that requires exclusive access. + Currently not implemented. + @retval EFI_UNSUPPORTED The device specified by ControllerHandle and + RemainingDevicePath is not supported by the driver specified by This. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_SUPPORTED)( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Starts a device controller or a bus controller. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For a bus driver, if this parameter is NULL, then handles + for all the children of Controller are created by this driver. + If this parameter is not NULL and the first Device Path Node is + not the End of Device Path Node, then only the handle for the + child device specified by the first Device Path Node of + RemainingDevicePath is created by this driver. + If the first Device Path Node of RemainingDevicePath is + the End of Device Path Node, no child handle is created by this + driver. + + @retval EFI_SUCCESS The device was started. + @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval Others The driver failded to start the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_START)( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stops a device controller or a bus controller. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_STOP)( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); + +/// +/// This protocol provides the services required to determine if a driver supports a given controller. +/// If a controller is supported, then it also provides routines to start and stop the controller. +/// +struct _EFI_DRIVER_BINDING_PROTOCOL { + EFI_DRIVER_BINDING_SUPPORTED Supported; + EFI_DRIVER_BINDING_START Start; + EFI_DRIVER_BINDING_STOP Stop; + + /// + /// The version number of the UEFI driver that produced the + /// EFI_DRIVER_BINDING_PROTOCOL. This field is used by + /// the EFI boot service ConnectController() to determine + /// the order that driver's Supported() service will be used when + /// a controller needs to be started. EFI Driver Binding Protocol + /// instances with higher Version values will be used before ones + /// with lower Version values. The Version values of 0x0- + /// 0x0f and 0xfffffff0-0xffffffff are reserved for + /// platform/OEM specific drivers. The Version values of 0x10- + /// 0xffffffef are reserved for IHV-developed drivers. + /// + UINT32 Version; + + /// + /// The image handle of the UEFI driver that produced this instance + /// of the EFI_DRIVER_BINDING_PROTOCOL. + /// + EFI_HANDLE ImageHandle; + + /// + /// The handle on which this instance of the + /// EFI_DRIVER_BINDING_PROTOCOL is installed. In most + /// cases, this is the same handle as ImageHandle. However, for + /// UEFI drivers that produce more than one instance of the + /// EFI_DRIVER_BINDING_PROTOCOL, this value may not be + /// the same as ImageHandle. + /// + EFI_HANDLE DriverBindingHandle; +}; + +extern EFI_GUID gEfiDriverBindingProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration.h new file mode 100644 index 0000000..77b305c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration.h @@ -0,0 +1,167 @@ +/** @file + EFI Driver Configuration Protocol + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DRIVER_CONFIGURATION_H__ +#define __EFI_DRIVER_CONFIGURATION_H__ + +#include + +/// +/// Global ID for the Driver Configuration Protocol defined in EFI 1.1 +/// +#define EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID \ + { \ + 0x107a772b, 0xd5e1, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_DRIVER_CONFIGURATION_PROTOCOL EFI_DRIVER_CONFIGURATION_PROTOCOL; + +/** + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. This + is an optional parameter that may be NULL. It will be NULL + for device drivers, and for bus drivers that wish to set + options for the bus controller. It will not be NULL for a + bus driver that wishes to set options for one of its child + controllers. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be + presented to the user, and it must match one of the languages + specified in SupportedLanguages. The number of languages + supported by a driver is up to the driver writer. + @param ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. See "Related + Definitions" for a list of the actions that the calling + agent is required to perform prior to accessing + ControllerHandle again. + + @retval EFI_SUCCESS The driver specified by This successfully set the + configuration options for the controller specified + by ControllerHandle.. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support setting + configuration options for the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION_SET_OPTIONS)( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +/** + Tests to see if a controller's current configuration options are valid. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current + configuration options are valid. + @param ChildHandle The handle of the child controller to test if it's current + configuration options are valid. This is an optional + parameter that may be NULL. It will be NULL for device + drivers. It will also be NULL for bus drivers that wish + to test the configuration options for the bus controller. + It will not be NULL for a bus driver that wishes to test + configuration options for one of its child controllers. + + @retval EFI_SUCCESS The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has a valid set of configuration + options. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has an invalid set of configuration + options. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION_OPTIONS_VALID)( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +/** + Forces a driver to set the default configuration options for a controller. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration options on This is an optional parameter that may be NULL. It will be NULL for device drivers. It will also be NULL for bus drivers that wish to force default configuration options for the bus controller. It will not be NULL for a bus driver that wishes to force default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller specified by ControllerHandle and ChildHandle. See Table 9-1 for legal values. A DefaultType of 0x00000000 must be supported by this protocol. + @param ActionRequired A pointer to the action that the calling agent is required to perform when this function returns. See "Related Definitions" in Section 9.1 for a list of the actions that the calling agent is required to perform prior to accessing ControllerHandle again. + + @retval EFI_SUCCESS The driver specified by This successfully forced the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION_FORCE_DEFAULTS)( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + + +/// +/// Used to set configuration options for a controller that an EFI Driver is managing. +/// +struct _EFI_DRIVER_CONFIGURATION_PROTOCOL { + EFI_DRIVER_CONFIGURATION_SET_OPTIONS SetOptions; + EFI_DRIVER_CONFIGURATION_OPTIONS_VALID OptionsValid; + EFI_DRIVER_CONFIGURATION_FORCE_DEFAULTS ForceDefaults; + /// + /// A Null-terminated ASCII string that contains one or more + /// ISO 639-2 language codes. This is the list of language + /// codes that this protocol supports. + /// + CHAR8 *SupportedLanguages; +}; + + +extern EFI_GUID gEfiDriverConfigurationProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration2.h new file mode 100644 index 0000000..441a40c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverConfiguration2.h @@ -0,0 +1,190 @@ +/** @file + UEFI Driver Configuration2 Protocol + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DRIVER_CONFIGURATION2_H__ +#define __EFI_DRIVER_CONFIGURATION2_H__ + +/// +/// Global ID for the Driver Configuration Protocol defined in UEFI 2.0 +/// +#define EFI_DRIVER_CONFIGURATION2_PROTOCOL_GUID \ + { \ + 0xbfd7dc1d, 0x24f1, 0x40d9, {0x82, 0xe7, 0x2e, 0x09, 0xbb, 0x6b, 0x4e, 0xbe } \ + } + +typedef struct _EFI_DRIVER_CONFIGURATION2_PROTOCOL EFI_DRIVER_CONFIGURATION2_PROTOCOL; + +typedef enum { + /// + /// The controller is still in a usable state. No actions + /// are required before this controller can be used again. + /// + EfiDriverConfigurationActionNone = 0, + /// + /// The driver has detected that the controller is not in a + /// usable state, and it needs to be stopped. + /// + EfiDriverConfigurationActionStopController = 1, + /// + /// This controller needs to be stopped and restarted + /// before it can be used again. + /// + EfiDriverConfigurationActionRestartController = 2, + /// + /// A configuration change has been made that requires the platform to be restarted before + /// the controller can be used again. + /// + EfiDriverConfigurationActionRestartPlatform = 3, + EfiDriverConfigurationActionMaximum +} EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED; + +#define EFI_DRIVER_CONFIGURATION_SAFE_DEFAULTS 0x00000000 +#define EFI_DRIVER_CONFIGURATION_MANUFACTURING_DEFAULTS 0x00000001 +#define EFI_DRIVER_CONFIGURATION_CUSTOM_DEFAULTS 0x00000002 +#define EFI_DRIVER_CONFIGURATION_PERORMANCE_DEFAULTS 0x00000003 + +/** + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION2_PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. This + is an optional parameter that may be NULL. It will be NULL + for device drivers, and for bus drivers that wish to set + options for the bus controller. It will not be NULL for a + bus driver that wishes to set options for one of its child + controllers. + @param Language A Null-terminated ASCII string that contains one or more RFC 4646 + language codes. This is the list of language codes that this + protocol supports. The number of languages + supported by a driver is up to the driver writer. + @param ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. See "Related + Definitions" for a list of the actions that the calling + agent is required to perform prior to accessing + ControllerHandle again. + + @retval EFI_SUCCESS The driver specified by This successfully set the + configuration options for the controller specified + by ControllerHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support setting + configuration options for the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION2_SET_OPTIONS)( + IN EFI_DRIVER_CONFIGURATION2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +/** + Tests to see if a controller's current configuration options are valid. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION2_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current + configuration options are valid. + @param ChildHandle The handle of the child controller to test if it's current + configuration options are valid. This is an optional + parameter that may be NULL. It will be NULL for device + drivers. It will also be NULL for bus drivers that wish + to test the configuration options for the bus controller. + It will not be NULL for a bus driver that wishes to test + configuration options for one of its child controllers. + + @retval EFI_SUCCESS The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has a valid set of configuration + options. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has an invalid set of configuration + options. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION2_OPTIONS_VALID)( + IN EFI_DRIVER_CONFIGURATION2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +/** + Forces a driver to set the default configuration options for a controller. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION2_PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration options on This is an optional parameter that may be NULL. It will be NULL for device drivers. It will also be NULL for bus drivers that wish to force default configuration options for the bus controller. It will not be NULL for a bus driver that wishes to force default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller specified by ControllerHandle and ChildHandle. See Table 9-1 for legal values. A DefaultType of 0x00000000 must be supported by this protocol. + @param ActionRequired A pointer to the action that the calling agent is required to perform when this function returns. See "Related Definitions" in Section 9.1 for a list of the actions that the calling agent is required to perform prior to accessing ControllerHandle again. + + @retval EFI_SUCCESS The driver specified by This successfully forced the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION2_FORCE_DEFAULTS)( + IN EFI_DRIVER_CONFIGURATION2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +/// +/// Used to set configuration options for a controller that an EFI Driver is managing. +/// +struct _EFI_DRIVER_CONFIGURATION2_PROTOCOL { + EFI_DRIVER_CONFIGURATION2_SET_OPTIONS SetOptions; + EFI_DRIVER_CONFIGURATION2_OPTIONS_VALID OptionsValid; + EFI_DRIVER_CONFIGURATION2_FORCE_DEFAULTS ForceDefaults; + /// + /// A Null-terminated ASCII string that contains one or more RFC 4646 + /// language codes. This is the list of language codes that this protocol supports. + /// + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiDriverConfiguration2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics.h new file mode 100644 index 0000000..81d7e80 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics.h @@ -0,0 +1,131 @@ +/** @file + EFI Driver Diagnostics Protocol + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DRIVER_DIAGNOSTICS_H__ +#define __EFI_DRIVER_DIAGNOSTICS_H__ + +/// +/// The global ID for the Driver Diagnostics Protocol as defined in EFI 1.1. +/// +#define EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID \ + { \ + 0x0784924f, 0xe296, 0x11d4, {0x9a, 0x49, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_DRIVER_DIAGNOSTICS_PROTOCOL EFI_DRIVER_DIAGNOSTICS_PROTOCOL; + +typedef enum { + /// + /// Performs standard diagnostics on the controller. + /// + EfiDriverDiagnosticTypeStandard = 0, + /// + /// This is an optional diagnostic type that performs diagnostics on the controller that may + /// take an extended amount of time to execute. + /// + EfiDriverDiagnosticTypeExtended = 1, + /// + /// This is an optional diagnostic type that performs diagnostics on the controller that are + /// suitable for a manufacturing and test environment. + /// + EfiDriverDiagnosticTypeManufacturing= 2, + /// + /// This is an optional diagnostic type that would only be used in the situation where an + /// EFI_NOT_READY had been returned by a previous call to RunDiagnostics() + /// and there is a desire to cancel the current running diagnostics operation. + /// + EfiDriverDiagnosticTypeCancel = 3, + EfiDriverDiagnosticTypeMaximum +} EFI_DRIVER_DIAGNOSTIC_TYPE; + +/** + Runs diagnostics on a controller. + + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL instance. + @param ControllerHandle The handle of the controller to run diagnostics on. + @param ChildHandle The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a + bus drivers that wish to run diagnostics on the bus + controller. It will not be NULL for a bus driver that + wishes to run diagnostics on one of its child controllers. + @param DiagnosticType Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. See + "Related Definitions" for the list of supported types. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language in which the optional + error message should be returned in Buffer, and it must + match one of the languages specified in SupportedLanguages. + The number of languages supported by a driver is up to + the driver writer. + @param ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated string + plus some additional data whose format is defined by + ErrorType. Buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility + to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and + ChildHandle passed the diagnostic. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ErrorType is NULL. + @retval EFI_INVALID_PARAMETER BufferType is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + running diagnostics for the controller specified + by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete + the diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return + the status information in ErrorType, BufferSize, + and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and + ChildHandle did not pass the diagnostic. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_DIAGNOSTICS_RUN_DIAGNOSTICS)( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ); + +/// +/// Used to perform diagnostics on a controller that an EFI Driver is managing. +/// +struct _EFI_DRIVER_DIAGNOSTICS_PROTOCOL { + EFI_DRIVER_DIAGNOSTICS_RUN_DIAGNOSTICS RunDiagnostics; + /// + /// A Null-terminated ASCII string that contains one or more ISO 639-2 + /// language codes. This is the list of language codes that this protocol supports. + /// + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiDriverDiagnosticsProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics2.h new file mode 100644 index 0000000..081d5bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverDiagnostics2.h @@ -0,0 +1,111 @@ +/** @file + UEFI Driver Diagnostics2 Protocol + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DRIVER_DIAGNOSTICS2_H__ +#define __EFI_DRIVER_DIAGNOSTICS2_H__ + +#include + +#define EFI_DRIVER_DIAGNOSTICS2_PROTOCOL_GUID \ + { \ + 0x4d330321, 0x025f, 0x4aac, {0x90, 0xd8, 0x5e, 0xd9, 0x00, 0x17, 0x3b, 0x63 } \ + } + +typedef struct _EFI_DRIVER_DIAGNOSTICS2_PROTOCOL EFI_DRIVER_DIAGNOSTICS2_PROTOCOL; + +/** + Runs diagnostics on a controller. + + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS2_PROTOCOL instance. + @param ControllerHandle The handle of the controller to run diagnostics on. + @param ChildHandle The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for + bus drivers that wish to run diagnostics on the bus + controller. It will not be NULL for a bus driver that + wishes to run diagnostics on one of its child controllers. + @param DiagnosticType Indicates the type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. See + "Related Definitions" for the list of supported types. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller + is requesting, and it must match one of the + languages specified in SupportedLanguages. + The number of languages supported by a + driver is up to the driver writer. Language + is specified in RFC 4646 language code format. + @param ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by + ErrorType. Buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility + to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and + ChildHandle passed the diagnostic. + @retval EFI_ACCESS_DENIED The request for initiating diagnostics was unable + to be complete due to some underlying hardware or + software state. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ErrorType is NULL. + @retval EFI_INVALID_PARAMETER BufferType is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + running diagnostics for the controller specified + by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete + the diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return + the status information in ErrorType, BufferSize, + and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and + ChildHandle did not pass the diagnostic. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS)( + IN EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ); + +/// +/// Used to perform diagnostics on a controller that an EFI Driver is managing. +/// +struct _EFI_DRIVER_DIAGNOSTICS2_PROTOCOL { + EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS RunDiagnostics; + /// + /// A Null-terminated ASCII string that contains one or more RFC 4646 + /// language codes. This is the list of language codes that this protocol supports. + /// + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiDriverDiagnostics2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverFamilyOverride.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverFamilyOverride.h new file mode 100644 index 0000000..0352e08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverFamilyOverride.h @@ -0,0 +1,66 @@ +/** @file + UEFI Driver Family Protocol + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_DRIVER_FAMILY_OVERRIDE_H__ +#define __EFI_DRIVER_FAMILY_OVERRIDE_H__ + +#define EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID \ + { \ + 0xb1ee129e, 0xda36, 0x4181, { 0x91, 0xf8, 0x4, 0xa4, 0x92, 0x37, 0x66, 0xa7 } \ + } + +typedef struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL; + +// +// Prototypes for the Driver Family Override Protocol +// +// +/** + This function returns the version value associated with the driver specified by This. + + Retrieves the version of the driver that is used by the EFI Boot Service ConnectController() + to sort the set of Driver Binding Protocols in order from highest priority to lowest priority. + For drivers that support the Driver Family Override Protocol, those drivers are sorted so that + the drivers with higher values returned by GetVersion() are higher priority than drivers that + return lower values from GetVersion(). + + @param This A pointer to the EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL instance. + + @return The version value associated with the driver specified by This. + +**/ +typedef +UINT32 +(EFIAPI *EFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION)( + IN EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL *This + ); + +/// +/// When installed, the Driver Family Override Protocol produces a GUID that represents +/// a family of drivers. Drivers with the same GUID are members of the same family +/// When drivers are connected to controllers, drivers with a higher revision value +/// in the same driver family are connected with a higher priority than drivers +/// with a lower revision value in the same driver family. The EFI Boot Service +/// Connect Controller uses five rules to build a prioritized list of drivers when +/// a request is made to connect a driver to a controller. The Driver Family Protocol +/// rule is between the Platform Specific Driver Override Protocol and above the +/// Bus Specific Driver Override Protocol. +/// +struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL { + EFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION GetVersion; +}; + +extern EFI_GUID gEfiDriverFamilyOverrideProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverHealth.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverHealth.h new file mode 100644 index 0000000..bfed107 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverHealth.h @@ -0,0 +1,247 @@ +/** @file + EFI Driver Health Protocol definitions. + + When installed, the Driver Health Protocol produces a collection of services that allow + the health status for a controller to be retrieved. If a controller is not in a usable + state, status messages may be reported to the user, repair operations can be invoked, + and the user may be asked to make software and/or hardware configuration changes. + + The Driver Health Protocol is optionally produced by a driver that follows the + EFI Driver Model. If an EFI Driver needs to report health status to the platform, + provide warning or error messages to the user, perform length repair operations, + or request the user to make hardware or software configuration changes, then the + Driver Health Protocol must be produced. + + A controller that is managed by driver that follows the EFI Driver Model and + produces the Driver Health Protocol must report the current health of the + controllers that the driver is currently managing. The controller can initially + be healthy, failed, require repair, or require configuration. If a controller + requires configuration, and the user make configuration changes, the controller + may then need to be reconnected or the system may need to be rebooted for the + configuration changes to take affect. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Specification 2.3d + +**/ + +#ifndef __EFI_DRIVER_HEALTH_H__ +#define __EFI_DRIVER_HEALTH_H__ + +#define EFI_DRIVER_HEALTH_PROTOCOL_GUID \ + { \ + 0x2a534210, 0x9280, 0x41d8, { 0xae, 0x79, 0xca, 0xda, 0x1, 0xa2, 0xb1, 0x27 } \ + } + +typedef struct _EFI_DRIVER_HEALTH_PROTOCOL EFI_DRIVER_HEALTH_PROTOCOL; + +/// +/// EFI_DRIVER_HEALTH_HEALTH_STATUS +/// +typedef enum { + EfiDriverHealthStatusHealthy, + EfiDriverHealthStatusRepairRequired, + EfiDriverHealthStatusConfigurationRequired, + EfiDriverHealthStatusFailed, + EfiDriverHealthStatusReconnectRequired, + EfiDriverHealthStatusRebootRequired +} EFI_DRIVER_HEALTH_STATUS; + +/// +/// EFI_DRIVER_HEALTH_HII_MESSAGE +/// +typedef struct { + EFI_HII_HANDLE HiiHandle; + EFI_STRING_ID StringId; + + /// + /// 64-bit numeric value of the warning/error specified by this message. + /// A value of 0x0000000000000000 is used to indicate that MessageCode is not specified. + /// The values 0x0000000000000001 to 0x0fffffffffffffff are reserved for allocation by the UEFI Specification. + /// The values 0x1000000000000000 to 0x1fffffffffffffff are reserved for IHV-developed drivers. + /// The values 0x8000000000000000 to 0x8fffffffffffffff is reserved for platform/OEM drivers. + /// All other values are reserved and should not be used. + /// + UINT64 MessageCode; +} EFI_DRIVER_HEALTH_HII_MESSAGE; + +/** + Reports the progress of a repair operation + + @param[in] Value A value between 0 and Limit that identifies the current + progress of the repair operation. + + @param[in] Limit The maximum value of Value for the current repair operation. + For example, a driver that wants to specify progress in + percent would use a Limit value of 100. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_HEALTH_REPAIR_NOTIFY)( + IN UINTN Value, + IN UINTN Limit + ); + +/** + Retrieves the health status of a controller in the platform. This function can also + optionally return warning messages, error messages, and a set of HII Forms that may + be repair a controller that is not proper configured. + + @param[in] This A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. + + @param[in] ControllerHandle The handle of the controller to retrieve the health status + on. This is an optional parameter that may be NULL. If + this parameter is NULL, then the value of ChildHandle is + ignored, and the combined health status of all the devices + that the driver is managing is returned. + + @param[in] ChildHandle The handle of the child controller to retrieve the health + status on. This is an optional parameter that may be NULL. + This parameter is ignored of ControllerHandle is NULL. It + will be NULL for device drivers. It will also be NULL for + bus drivers when an attempt is made to collect the health + status of the bus controller. If will not be NULL when an + attempt is made to collect the health status for a child + controller produced by the driver. + + @param[out] HealthStatus A pointer to the health status that is returned by this + function. This is an optional parameter that may be NULL. + This parameter is ignored of ControllerHandle is NULL. + The health status for the controller specified by + ControllerHandle and ChildHandle is returned. + + @param[out] MessageList A pointer to an array of warning or error messages associated + with the controller specified by ControllerHandle and + ChildHandle. This is an optional parameter that may be NULL. + MessageList is allocated by this function with the EFI Boot + Service AllocatePool(), and it is the caller's responsibility + to free MessageList with the EFI Boot Service FreePool(). + Each message is specified by tuple of an EFI_HII_HANDLE and + an EFI_STRING_ID. The array of messages is terminated by tuple + containing a EFI_HII_HANDLE with a value of NULL. The + EFI_HII_STRING_PROTOCOL.GetString() function can be used to + retrieve the warning or error message as a Null-terminated + string in a specific language. Messages may be + returned for any of the HealthStatus values except + EfiDriverHealthStatusReconnectRequired and + EfiDriverHealthStatusRebootRequired. + + @param[out] FormHiiHandle A pointer to the HII handle containing the HII form used when + configuration is required. The HII handle is associated with + the controller specified by ControllerHandle and ChildHandle. + If this is NULL, then no HII form is available. An HII handle + will only be returned with a HealthStatus value of + EfiDriverHealthStatusConfigurationRequired. + + @retval EFI_SUCCESS ControllerHandle is NULL, and all the controllers + managed by this driver specified by This have a health + status of EfiDriverHealthStatusHealthy with no warning + messages to be returned. The ChildHandle, HealthStatus, + MessageList, and FormList parameters are ignored. + + @retval EFI_DEVICE_ERROR ControllerHandle is NULL, and one or more of the + controllers managed by this driver specified by This + do not have a health status of EfiDriverHealthStatusHealthy. + The ChildHandle, HealthStatus, MessageList, and + FormList parameters are ignored. + + @retval EFI_DEVICE_ERROR ControllerHandle is NULL, and one or more of the + controllers managed by this driver specified by This + have one or more warning and/or error messages. + The ChildHandle, HealthStatus, MessageList, and + FormList parameters are ignored. + + @retval EFI_SUCCESS ControllerHandle is not NULL and the health status + of the controller specified by ControllerHandle and + ChildHandle was returned in HealthStatus. A list + of warning and error messages may be optionally + returned in MessageList, and a list of HII Forms + may be optionally returned in FormList. + + @retval EFI_UNSUPPORTED ControllerHandle is not NULL, and the controller + specified by ControllerHandle and ChildHandle is not + currently being managed by the driver specified by This. + + @retval EFI_INVALID_PARAMETER HealthStatus is NULL. + + @retval EFI_OUT_OF_RESOURCES MessageList is not NULL, and there are not enough + resource available to allocate memory for MessageList. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_HEALTH_GET_HEALTH_STATUS)( + IN EFI_DRIVER_HEALTH_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL, + OUT EFI_DRIVER_HEALTH_STATUS *HealthStatus, + OUT EFI_DRIVER_HEALTH_HII_MESSAGE **MessageList OPTIONAL, + OUT EFI_HII_HANDLE *FormHiiHandle OPTIONAL + ); + +/** + Performs a repair operation on a controller in the platform. This function can + optionally report repair progress information back to the platform. + + @param[in] This A pointer to the EFI_DRIVER_HEALTH_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to repair. + @param[in] ChildHandle The handle of the child controller to repair. This is + an optional parameter that may be NULL. It will be NULL + for device drivers. It will also be NULL for bus + drivers when an attempt is made to repair a bus controller. + If will not be NULL when an attempt is made to repair a + child controller produced by the driver. + @param[in] RepairNotify A notification function that may be used by a driver to + report the progress of the repair operation. This is + an optional parameter that may be NULL. + + + @retval EFI_SUCCESS An attempt to repair the controller specified by + ControllerHandle and ChildHandle was performed. + The result of the repair operation can bet + determined by calling GetHealthStatus(). + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to perform the + repair operation. + +*/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_HEALTH_REPAIR)( + IN EFI_DRIVER_HEALTH_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_HEALTH_REPAIR_NOTIFY RepairNotify OPTIONAL + ); + +/// +/// When installed, the Driver Health Protocol produces a collection of services +/// that allow the health status for a controller to be retrieved. If a controller +/// is not in a usable state, status messages may be reported to the user, repair +/// operations can be invoked, and the user may be asked to make software and/or +/// hardware configuration changes. +/// +struct _EFI_DRIVER_HEALTH_PROTOCOL { + EFI_DRIVER_HEALTH_GET_HEALTH_STATUS GetHealthStatus; + EFI_DRIVER_HEALTH_REPAIR Repair; +}; + +extern EFI_GUID gEfiDriverHealthProtocolGuid; + +#endif + + + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverSupportedEfiVersion.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverSupportedEfiVersion.h new file mode 100644 index 0000000..34ffbf3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DriverSupportedEfiVersion.h @@ -0,0 +1,46 @@ +/** @file + The protocol provides information about the version of the EFI + specification that a driver is following. This protocol is + required for EFI drivers that are on PCI and other plug-in + cards. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DRIVER_SUPPORTED_EFI_VERSION_H__ +#define __DRIVER_SUPPORTED_EFI_VERSION_H__ + +#define EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL_GUID \ + { 0x5c198761, 0x16a8, 0x4e69, { 0x97, 0x2c, 0x89, 0xd6, 0x79, 0x54, 0xf8, 0x1d } } + + +/// +/// The EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL provides a +/// mechanism for an EFI driver to publish the version of the EFI +/// specification it conforms to. This protocol must be placed on +/// the driver's image handle when the driver's entry point is +/// called. +/// +typedef struct _EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL { + /// + /// The size, in bytes, of the entire structure. Future versions of this + /// specification may grow the size of the structure. + /// + UINT32 Length; + /// + /// The latest version of the UEFI specification that this driver conforms to. + /// + UINT32 FirmwareVersion; +} EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL; + +extern EFI_GUID gEfiDriverSupportedEfiVersionProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeMmReadyToLock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeMmReadyToLock.h new file mode 100644 index 0000000..68d93f1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeMmReadyToLock.h @@ -0,0 +1,25 @@ +/** @file + DXE MM Ready To Lock protocol introduced in the PI 1.5 specification. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _DXE_MM_READY_TO_LOCK_H_ +#define _DXE_MM_READY_TO_LOCK_H_ + +#define EFI_DXE_MM_READY_TO_LOCK_PROTOCOL_GUID \ + { \ + 0x60ff8964, 0xe906, 0x41d0, { 0xaf, 0xed, 0xf2, 0x41, 0xe9, 0x74, 0xe0, 0x8e } \ + } + +extern EFI_GUID gEfiDxeMmReadyToLockProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeSmmReadyToLock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeSmmReadyToLock.h new file mode 100644 index 0000000..930dcb6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/DxeSmmReadyToLock.h @@ -0,0 +1,40 @@ +/** @file + DXE SMM Ready To Lock protocol introduced in the PI 1.2 specification. + + According to PI 1.4a specification, this UEFI protocol indicates that + resources and services that should not be used by the third party code + are about to be locked. + This protocol is a mandatory protocol published by PI platform code. + This protocol in tandem with the End of DXE Event facilitates transition + of the platform from the environment where all of the components are + under the authority of the platform manufacturer to the environment where + third party extensible modules such as UEFI drivers and UEFI applications + are executed. The protocol is published immediately after signaling of the + End of DXE Event. PI modules that need to lock or protect their resources + in anticipation of the invocation of 3rd party extensible modules should + register for notification on installation of this protocol and effect the + appropriate protections in their notification handlers. For example, PI + platform code may choose to use notification handler to lock SMM by invoking + EFI_SMM_ACCESS2_PROTOCOL.Lock() function. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _DXE_SMM_READY_TO_LOCK_H_ +#define _DXE_SMM_READY_TO_LOCK_H_ + +#include + +#define EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL_GUID EFI_DXE_MM_READY_TO_LOCK_PROTOCOL_GUID + +extern EFI_GUID gEfiDxeSmmReadyToLockProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Eap.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Eap.h new file mode 100644 index 0000000..e1d70a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Eap.h @@ -0,0 +1,162 @@ +/** @file + EFI EAP(Extended Authenticaton Protocol) Protocol Definition + The EFI EAP Protocol is used to abstract the ability to configure and extend the + EAP framework. + The definitions in this file are defined in UEFI Specification 2.3.1B, which have + not been verified by one implementation yet. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_EAP_PROTOCOL_H__ +#define __EFI_EAP_PROTOCOL_H__ + + +#define EFI_EAP_PROTOCOL_GUID \ + { \ + 0x5d9f96db, 0xe731, 0x4caa, {0xa0, 0xd, 0x72, 0xe1, 0x87, 0xcd, 0x77, 0x62 } \ + } + +typedef struct _EFI_EAP_PROTOCOL EFI_EAP_PROTOCOL; + +/// +/// Type for the identification number assigned to the Port by the +/// System in which the Port resides. +/// +typedef VOID * EFI_PORT_HANDLE; + +/// +/// EAP Authentication Method Type (RFC 3748) +///@{ +#define EFI_EAP_TYPE_TLS 13 ///< REQUIRED - RFC 5216 +///@} + +// +// EAP_TYPE MD5, OTP and TOEKN_CARD has been removed from UEFI2.3.1B. +// Definitions are kept for backward compatibility. +// +#define EFI_EAP_TYPE_MD5 4 +#define EFI_EAP_TYPE_OTP 5 +#define EFI_EAP_TYPE_TOKEN_CARD 6 + +/** + One user provided EAP authentication method. + + Build EAP response packet in response to the EAP request packet specified by + (RequestBuffer, RequestSize). + + @param[in] PortNumber Specified the Port where the EAP request packet comes. + @param[in] RequestBuffer Pointer to the most recently received EAP- Request packet. + @param[in] RequestSize Packet size in bytes for the most recently received + EAP-Request packet. + @param[in] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. + On input, it is the buffer size provided by the caller. + On output, it is the buffer size in fact needed to contain + the packet. + + @retval EFI_SUCCESS The required EAP response packet is built successfully. + @retval others Failures are encountered during the packet building process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_BUILD_RESPONSE_PACKET)( + IN EFI_PORT_HANDLE PortNumber, + IN UINT8 *RequestBuffer, + IN UINTN RequestSize, + IN UINT8 *Buffer, + IN OUT UINTN *BufferSize + ); + +/** + Set the desired EAP authentication method for the Port. + + The SetDesiredAuthMethod() function sets the desired EAP authentication method indicated + by EapAuthType for the Port. + + If EapAuthType is an invalid EAP authentication type, then EFI_INVALID_PARAMETER is + returned. + If the EAP authentication method of EapAuthType is unsupported by the Ports, then it will + return EFI_UNSUPPORTED. + The cryptographic strength of EFI_EAP_TYPE_TLS shall be at least of hash strength + SHA-256 and RSA key length of at least 2048 bits. + + @param[in] This A pointer to the EFI_EAP_PROTOCOL instance that indicates + the calling context. + @param[in] EapAuthType The type of the EAP authentication method to register. It should + be the type value defined by RFC. See RFC 2284 for details. + @param[in] Handler The handler of the EAP authentication method to register. + + @retval EFI_SUCCESS The EAP authentication method of EapAuthType is + registered successfully. + @retval EFI_INVALID_PARAMETER EapAuthType is an invalid EAP authentication type. + @retval EFI_UNSUPPORTED The EAP authentication method of EapAuthType is + unsupported by the Port. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_SET_DESIRED_AUTHENTICATION_METHOD)( + IN EFI_EAP_PROTOCOL *This, + IN UINT8 EapAuthType + ); + +/** + Register an EAP authentication method. + + The RegisterAuthMethod() function registers the user provided EAP authentication method, + the type of which is EapAuthType and the handler of which is Handler. + + If EapAuthType is an invalid EAP authentication type, then EFI_INVALID_PARAMETER is + returned. + If there is not enough system memory to perform the registration, then + EFI_OUT_OF_RESOURCES is returned. + + @param[in] This A pointer to the EFI_EAP_PROTOCOL instance that indicates + the calling context. + @param[in] EapAuthType The type of the EAP authentication method to register. It should + be the type value defined by RFC. See RFC 2284 for details. + @param[in] Handler The handler of the EAP authentication method to register. + + @retval EFI_SUCCESS The EAP authentication method of EapAuthType is + registered successfully. + @retval EFI_INVALID_PARAMETER EapAuthType is an invalid EAP authentication type. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to perform the registration. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_REGISTER_AUTHENTICATION_METHOD)( + IN EFI_EAP_PROTOCOL *This, + IN UINT8 EapAuthType, + IN EFI_EAP_BUILD_RESPONSE_PACKET Handler + ); + +/// +/// EFI_EAP_PROTOCOL +/// is used to configure the desired EAP authentication method for the EAP +/// framework and extend the EAP framework by registering new EAP authentication +/// method on a Port. The EAP framework is built on a per-Port basis. Herein, a +/// Port means a NIC. For the details of EAP protocol, please refer to RFC 2284. +/// +struct _EFI_EAP_PROTOCOL { + EFI_EAP_SET_DESIRED_AUTHENTICATION_METHOD SetDesiredAuthMethod; + EFI_EAP_REGISTER_AUTHENTICATION_METHOD RegisterAuthMethod; +}; + +extern EFI_GUID gEfiEapProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapConfiguration.h new file mode 100644 index 0000000..5a9769a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapConfiguration.h @@ -0,0 +1,159 @@ +/** @file + This file defines the EFI EAP Configuration protocol. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_EAP_CONFIGURATION_PROTOCOL_H__ +#define __EFI_EAP_CONFIGURATION_PROTOCOL_H__ + +/// +/// EFI EAP Configuration protocol provides a way to set and get EAP configuration. +/// +#define EFI_EAP_CONFIGURATION_PROTOCOL_GUID \ + { \ + 0xe5b58dbb, 0x7688, 0x44b4, {0x97, 0xbf, 0x5f, 0x1d, 0x4b, 0x7c, 0xc8, 0xdb } \ + } + +typedef struct _EFI_EAP_CONFIGURATION_PROTOCOL EFI_EAP_CONFIGURATION_PROTOCOL; + +/// +/// Make sure it not conflict with any real EapTypeXXX +/// +#define EFI_EAP_TYPE_ATTRIBUTE 0 + +typedef enum { + /// + /// EFI_EAP_TYPE_ATTRIBUTE + /// + EfiEapConfigEapAuthMethod, + EfiEapConfigEapSupportedAuthMethod, + /// + /// EapTypeIdentity + /// + EfiEapConfigIdentityString, + /// + /// EapTypeEAPTLS/EapTypePEAP + /// + EfiEapConfigEapTlsCACert, + EfiEapConfigEapTlsClientCert, + EfiEapConfigEapTlsClientPrivateKeyFile, + EfiEapConfigEapTlsClientPrivateKeyFilePassword, // ASCII format, Volatile + EfiEapConfigEapTlsCipherSuite, + EfiEapConfigEapTlsSupportedCipherSuite, + /// + /// EapTypeMSChapV2 + /// + EfiEapConfigEapMSChapV2Password, // UNICODE format, Volatile + /// + /// EapTypePEAP + /// + EfiEapConfigEap2ndAuthMethod, + /// + /// More... + /// +} EFI_EAP_CONFIG_DATA_TYPE; + +/// +/// EFI_EAP_TYPE +/// +typedef UINT8 EFI_EAP_TYPE; +#define EFI_EAP_TYPE_ATTRIBUTE 0 +#define EFI_EAP_TYPE_IDENTITY 1 +#define EFI_EAP_TYPE_NOTIFICATION 2 +#define EFI_EAP_TYPE_NAK 3 +#define EFI_EAP_TYPE_MD5CHALLENGE 4 +#define EFI_EAP_TYPE_OTP 5 +#define EFI_EAP_TYPE_GTC 6 +#define EFI_EAP_TYPE_EAPTLS 13 +#define EFI_EAP_TYPE_EAPSIM 18 +#define EFI_EAP_TYPE_TTLS 21 +#define EFI_EAP_TYPE_PEAP 25 +#define EFI_EAP_TYPE_MSCHAPV2 26 +#define EFI_EAP_TYPE_EAP_EXTENSION 33 + +/** + Set EAP configuration data. + + The SetData() function sets EAP configuration to non-volatile storage or volatile + storage. + + @param[in] This Pointer to the EFI_EAP_CONFIGURATION_PROTOCOL instance. + @param[in] EapType EAP type. + @param[in] DataType Configuration data type. + @param[in] Data Pointer to configuration data. + @param[in] DataSize Total size of configuration data. + + @retval EFI_SUCCESS The EAP configuration data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The EapType or DataType is unsupported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_CONFIGURATION_SET_DATA) ( + IN EFI_EAP_CONFIGURATION_PROTOCOL *This, + IN EFI_EAP_TYPE EapType, + IN EFI_EAP_CONFIG_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get EAP configuration data. + + The GetData() function gets EAP configuration. + + @param[in] This Pointer to the EFI_EAP_CONFIGURATION_PROTOCOL instance. + @param[in] EapType EAP type. + @param[in] DataType Configuration data type. + @param[in, out] Data Pointer to configuration data. + @param[in, out] DataSize Total size of configuration data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The EAP configuration data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Data is NULL. + DataSize is NULL. + @retval EFI_UNSUPPORTED The EapType or DataType is unsupported. + @retval EFI_NOT_FOUND The EAP configuration data is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the buffer. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_CONFIGURATION_GET_DATA) ( + IN EFI_EAP_CONFIGURATION_PROTOCOL *This, + IN EFI_EAP_TYPE EapType, + IN EFI_EAP_CONFIG_DATA_TYPE DataType, + IN OUT VOID *Data, + IN OUT UINTN *DataSize + ); + +/// +/// The EFI_EAP_CONFIGURATION_PROTOCOL +/// is designed to provide a way to set and get EAP configuration, such as Certificate, +/// private key file. +/// +struct _EFI_EAP_CONFIGURATION_PROTOCOL { + EFI_EAP_CONFIGURATION_SET_DATA SetData; + EFI_EAP_CONFIGURATION_GET_DATA GetData; +}; + +extern EFI_GUID gEfiEapConfigurationProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement.h new file mode 100644 index 0000000..50d98a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement.h @@ -0,0 +1,403 @@ +/** @file + EFI EAP Management Protocol Definition + The EFI EAP Management Protocol is designed to provide ease of management and + ease of test for EAPOL state machine. It is intended for the supplicant side. + It conforms to IEEE 802.1x specification. + The definitions in this file are defined in UEFI Specification 2.2, which have + not been verified by one implementation yet. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_EAP_MANAGEMENT_PROTOCOL_H__ +#define __EFI_EAP_MANAGEMENT_PROTOCOL_H__ + +#include + +#define EFI_EAP_MANAGEMENT_PROTOCOL_GUID \ + { \ + 0xbb62e663, 0x625d, 0x40b2, {0xa0, 0x88, 0xbb, 0xe8, 0x36, 0x23, 0xa2, 0x45 } \ + } + +typedef struct _EFI_EAP_MANAGEMENT_PROTOCOL EFI_EAP_MANAGEMENT_PROTOCOL; + +/// +/// PAE Capabilities +/// +///@{ +#define PAE_SUPPORT_AUTHENTICATOR 0x01 +#define PAE_SUPPORT_SUPPLICANT 0x02 +///@} + +/// +/// EFI_EAPOL_PORT_INFO +/// +typedef struct _EFI_EAPOL_PORT_INFO { + /// + /// The identification number assigned to the Port by the System in + /// which the Port resides. + /// + EFI_PORT_HANDLE PortNumber; + /// + /// The protocol version number of the EAPOL implementation + /// supported by the Port. + /// + UINT8 ProtocolVersion; + /// + /// The capabilities of the PAE associated with the Port. This field + /// indicates whether Authenticator functionality, Supplicant + /// functionality, both, or neither, is supported by the Port's PAE. + /// + UINT8 PaeCapabilities; +} EFI_EAPOL_PORT_INFO; + +/// +/// Supplicant PAE state machine (IEEE Std 802.1X Section 8.5.10) +/// +typedef enum _EFI_EAPOL_SUPPLICANT_PAE_STATE { + Logoff, + Disconnected, + Connecting, + Acquired, + Authenticating, + Held, + Authenticated, + MaxSupplicantPaeState +} EFI_EAPOL_SUPPLICANT_PAE_STATE; + +/// +/// Definitions for ValidFieldMask +/// +///@{ +#define AUTH_PERIOD_FIELD_VALID 0x01 +#define HELD_PERIOD_FIELD_VALID 0x02 +#define START_PERIOD_FIELD_VALID 0x04 +#define MAX_START_FIELD_VALID 0x08 +///@} + +/// +/// EFI_EAPOL_SUPPLICANT_PAE_CONFIGURATION +/// +typedef struct _EFI_EAPOL_SUPPLICANT_PAE_CONFIGURATION { + /// + /// Indicates which of the following fields are valid. + /// + UINT8 ValidFieldMask; + /// + /// The initial value for the authWhile timer. Its default value is 30s. + /// + UINTN AuthPeriod; + /// + /// The initial value for the heldWhile timer. Its default value is 60s. + /// + UINTN HeldPeriod; + /// + /// The initial value for the startWhen timer. Its default value is 30s. + /// + UINTN StartPeriod; + /// + /// The maximum number of successive EAPOL-Start messages will + /// be sent before the Supplicant assumes that there is no + /// Authenticator present. Its default value is 3. + /// + UINTN MaxStart; +} EFI_EAPOL_SUPPLICANT_PAE_CONFIGURATION; + +/// +/// Supplicant Statistics (IEEE Std 802.1X Section 9.5.2) +/// +typedef struct _EFI_EAPOL_SUPPLICANT_PAE_STATISTICS { + /// + /// The number of EAPOL frames of any type that have been received by this Supplican. + /// + UINTN EapolFramesReceived; + /// + /// The number of EAPOL frames of any type that have been transmitted by this Supplicant. + /// + UINTN EapolFramesTransmitted; + /// + /// The number of EAPOL Start frames that have been transmitted by this Supplicant. + /// + UINTN EapolStartFramesTransmitted; + /// + /// The number of EAPOL Logoff frames that have been transmitted by this Supplicant. + /// + UINTN EapolLogoffFramesTransmitted; + /// + /// The number of EAP Resp/Id frames that have been transmitted by this Supplicant. + /// + UINTN EapRespIdFramesTransmitted; + /// + /// The number of valid EAP Response frames (other than Resp/Id frames) that have been + /// transmitted by this Supplicant. + /// + UINTN EapResponseFramesTransmitted; + /// + /// The number of EAP Req/Id frames that have been received by this Supplicant. + /// + UINTN EapReqIdFramesReceived; + /// + /// The number of EAP Request frames (other than Rq/Id frames) that have been received + /// by this Supplicant. + /// + UINTN EapRequestFramesReceived; + /// + /// The number of EAPOL frames that have been received by this Supplicant in which the + /// frame type is not recognized. + /// + UINTN InvalidEapolFramesReceived; + /// + /// The number of EAPOL frames that have been received by this Supplicant in which the + /// Packet Body Length field (7.5.5) is invalid. + /// + UINTN EapLengthErrorFramesReceived; + /// + /// The protocol version number carried in the most recently received EAPOL frame. + /// + UINTN LastEapolFrameVersion; + /// + /// The source MAC address carried in the most recently received EAPOL frame. + /// + UINTN LastEapolFrameSource; +} EFI_EAPOL_SUPPLICANT_PAE_STATISTICS; + +/** + Read the system configuration information associated with the Port. + + The GetSystemConfiguration() function reads the system configuration + information associated with the Port, including the value of the + SystemAuthControl parameter of the System is returned in SystemAuthControl + and the Port's information is returned in the buffer pointed to by PortInfo. + The Port's information is optional. + If PortInfo is NULL, then reading the Port's information is ignored. + + If SystemAuthControl is NULL, then EFI_INVALID_PARAMETER is returned. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + @param[out] SystemAuthControl Returns the value of the SystemAuthControl + parameter of the System. + TRUE means Enabled. FALSE means Disabled. + @param[out] PortInfo Returns EFI_EAPOL_PORT_INFO structure to describe + the Port's information. This parameter can be NULL + to ignore reading the Port's information. + + @retval EFI_SUCCESS The system configuration information of the + Port is read successfully. + @retval EFI_INVALID_PARAMETER SystemAuthControl is NULL. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_GET_SYSTEM_CONFIGURATION)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This, + OUT BOOLEAN *SystemAuthControl, + OUT EFI_EAPOL_PORT_INFO *PortInfo OPTIONAL + ); + +/** + Set the system configuration information associated with the Port. + + The SetSystemConfiguration() function sets the value of the SystemAuthControl + parameter of the System to SystemAuthControl. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + @param[in] SystemAuthControl The desired value of the SystemAuthControl + parameter of the System. + TRUE means Enabled. FALSE means Disabled. + + @retval EFI_SUCCESS The system configuration information of the + Port is set successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_SET_SYSTEM_CONFIGURATION)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This, + IN BOOLEAN SystemAuthControl + ); + +/** + Cause the EAPOL state machines for the Port to be initialized. + + The InitializePort() function causes the EAPOL state machines for the Port. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + + @retval EFI_SUCCESS The Port is initialized successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_INITIALIZE_PORT)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This + ); + +/** + Notify the EAPOL state machines for the Port that the user of the System has + logged on. + + The UserLogon() function notifies the EAPOL state machines for the Port. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + + @retval EFI_SUCCESS The Port is notified successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_USER_LOGON)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This + ); + +/** + Notify the EAPOL state machines for the Port that the user of the System has + logged off. + + The UserLogoff() function notifies the EAPOL state machines for the Port. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + + @retval EFI_SUCCESS The Port is notified successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_USER_LOGOFF)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This + ); + +/** + Read the status of the Supplicant PAE state machine for the Port, including the + current state and the configuration of the operational parameters. + + The GetSupplicantStatus() function reads the status of the Supplicant PAE state + machine for the Port, including the current state CurrentState and the configuration + of the operational parameters Configuration. The configuration of the operational + parameters is optional. If Configuration is NULL, then reading the configuration + is ignored. The operational parameters in Configuration to be read can also be + specified by Configuration.ValidFieldMask. + + If CurrentState is NULL, then EFI_INVALID_PARAMETER is returned. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + @param[out] CurrentState Returns the current state of the Supplicant PAE + state machine for the Port. + @param[in, out] Configuration Returns the configuration of the operational + parameters of the Supplicant PAE state machine + for the Port as required. This parameter can be + NULL to ignore reading the configuration. + On input, Configuration.ValidFieldMask specifies the + operational parameters to be read. + On output, Configuration returns the configuration + of the required operational parameters. + + @retval EFI_SUCCESS The configuration of the operational parameter + of the Supplicant PAE state machine for the Port + is set successfully. + @retval EFI_INVALID_PARAMETER CurrentState is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_GET_SUPPLICANT_STATUS)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This, + OUT EFI_EAPOL_SUPPLICANT_PAE_STATE *CurrentState, + IN OUT EFI_EAPOL_SUPPLICANT_PAE_CONFIGURATION *Configuration OPTIONAL + ); + +/** + Set the configuration of the operational parameter of the Supplicant PAE + state machine for the Port. + + The SetSupplicantConfiguration() function sets the configuration of the + operational Parameter of the Supplicant PAE state machine for the Port to + Configuration. The operational parameters in Configuration to be set can be + specified by Configuration.ValidFieldMask. + + If Configuration is NULL, then EFI_INVALID_PARAMETER is returned. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + @param[in] Configuration The desired configuration of the operational + parameters of the Supplicant PAE state machine + for the Port as required. + + @retval EFI_SUCCESS The configuration of the operational parameter + of the Supplicant PAE state machine for the Port + is set successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_SET_SUPPLICANT_CONFIGURATION)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This, + IN EFI_EAPOL_SUPPLICANT_PAE_CONFIGURATION *Configuration + ); + +/** + Read the statistical information regarding the operation of the Supplicant + associated with the Port. + + The GetSupplicantStatistics() function reads the statistical information + Statistics regarding the operation of the Supplicant associated with the Port. + + If Statistics is NULL, then EFI_INVALID_PARAMETER is returned. + + @param[in] This A pointer to the EFI_EAP_MANAGEMENT_PROTOCOL + instance that indicates the calling context. + @param[out] Statistics Returns the statistical information regarding the + operation of the Supplicant for the Port. + + @retval EFI_SUCCESS The statistical information regarding the operation + of the Supplicant for the Port is read successfully. + @retval EFI_INVALID_PARAMETER Statistics is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_GET_SUPPLICANT_STATISTICS)( + IN EFI_EAP_MANAGEMENT_PROTOCOL *This, + OUT EFI_EAPOL_SUPPLICANT_PAE_STATISTICS *Statistics + ); + +/// +/// EFI_EAP_MANAGEMENT_PROTOCOL +/// is used to control, configure and monitor EAPOL state machine on +/// a Port. EAPOL state machine is built on a per-Port basis. Herein, +/// a Port means a NIC. For the details of EAPOL, please refer to +/// IEEE 802.1x specification. +/// +struct _EFI_EAP_MANAGEMENT_PROTOCOL { + EFI_EAP_GET_SYSTEM_CONFIGURATION GetSystemConfiguration; + EFI_EAP_SET_SYSTEM_CONFIGURATION SetSystemConfiguration; + EFI_EAP_INITIALIZE_PORT InitializePort; + EFI_EAP_USER_LOGON UserLogon; + EFI_EAP_USER_LOGOFF UserLogoff; + EFI_EAP_GET_SUPPLICANT_STATUS GetSupplicantStatus; + EFI_EAP_SET_SUPPLICANT_CONFIGURATION SetSupplicantConfiguration; + EFI_EAP_GET_SUPPLICANT_STATISTICS GetSupplicantStatistics; +}; + +extern EFI_GUID gEfiEapManagementProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement2.h new file mode 100644 index 0000000..d1e5981 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EapManagement2.h @@ -0,0 +1,87 @@ +/** @file + This file defines the EFI EAP Management2 protocol. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_EAP_MANAGEMENT2_PROTOCOL_H__ +#define __EFI_EAP_MANAGEMENT2_PROTOCOL_H__ + +#include + +/// +/// This EFI EAP Management2 protocol provides the ability to configure and control EAPOL +/// state machine, and retrieve the information, status and the statistics information of +/// EAPOL state machine. +/// +#define EFI_EAP_MANAGEMENT2_PROTOCOL_GUID \ + { \ + 0x5e93c847, 0x456d, 0x40b3, {0xa6, 0xb4, 0x78, 0xb0, 0xc9, 0xcf, 0x7f, 0x20 } \ + } + +typedef struct _EFI_EAP_MANAGEMENT2_PROTOCOL EFI_EAP_MANAGEMENT2_PROTOCOL; + +/** + Return key generated through EAP process. + + The GetKey() function return the key generated through EAP process, so that the 802.11 + MAC layer driver can use MSK to derive more keys, e.g. PMK (Pairwise Master Key). + + @param[in] This Pointer to the EFI_EAP_MANAGEMENT2_PROTOCOL instance. + @param[in, out] Msk Pointer to MSK (Master Session Key) buffer. + @param[in, out] MskSize MSK buffer size. + @param[in, out] Emsk Pointer to EMSK (Extended Master Session Key) buffer. + @param[in, out] EmskSize EMSK buffer size. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + Msk is NULL. + MskSize is NULL. + Emsk is NULL. + EmskSize is NULL. + @retval EFI_NOT_READY MSK and EMSK are not generated in current session yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EAP_GET_KEY) ( + IN EFI_EAP_MANAGEMENT2_PROTOCOL *This, + IN OUT UINT8 *Msk, + IN OUT UINTN *MskSize, + IN OUT UINT8 *Emsk, + IN OUT UINT8 *EmskSize + ); + +/// +/// The EFI_EAP_MANAGEMENT2_PROTOCOL +/// is used to control, configure and monitor EAPOL state machine on a Port, and return +/// information of the Port. EAPOL state machine is built on a per-Port basis. Herein, a +/// Port means a NIC. For the details of EAPOL, please refer to IEEE 802.1x +/// specification. +/// +struct _EFI_EAP_MANAGEMENT2_PROTOCOL { + EFI_EAP_GET_SYSTEM_CONFIGURATION GetSystemConfiguration; + EFI_EAP_SET_SYSTEM_CONFIGURATION SetSystemConfiguration; + EFI_EAP_INITIALIZE_PORT InitializePort; + EFI_EAP_USER_LOGON UserLogon; + EFI_EAP_USER_LOGOFF UserLogoff; + EFI_EAP_GET_SUPPLICANT_STATUS GetSupplicantStatus; + EFI_EAP_SET_SUPPLICANT_CONFIGURATION SetSupplicantConfiguration; + EFI_EAP_GET_SUPPLICANT_STATISTICS GetSupplicantStatistics; + EFI_EAP_GET_KEY GetKey; +}; + +extern EFI_GUID gEfiEapManagement2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ebc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ebc.h new file mode 100644 index 0000000..8dccaf4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ebc.h @@ -0,0 +1,314 @@ +/** @file + Describes the protocol interface to the EBC interpreter. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_EBC_PROTOCOL_H__ +#define __EFI_EBC_PROTOCOL_H__ + +#define EFI_EBC_INTERPRETER_PROTOCOL_GUID \ + { \ + 0x13AC6DD1, 0x73D0, 0x11D4, {0xB0, 0x6B, 0x00, 0xAA, 0x00, 0xBD, 0x6D, 0xE7 } \ + } + +// +// Define OPCODES +// +#define OPCODE_BREAK 0x00 +#define OPCODE_JMP 0x01 +#define OPCODE_JMP8 0x02 +#define OPCODE_CALL 0x03 +#define OPCODE_RET 0x04 +#define OPCODE_CMPEQ 0x05 +#define OPCODE_CMPLTE 0x06 +#define OPCODE_CMPGTE 0x07 +#define OPCODE_CMPULTE 0x08 +#define OPCODE_CMPUGTE 0x09 +#define OPCODE_NOT 0x0A +#define OPCODE_NEG 0x0B +#define OPCODE_ADD 0x0C +#define OPCODE_SUB 0x0D +#define OPCODE_MUL 0x0E +#define OPCODE_MULU 0x0F +#define OPCODE_DIV 0x10 +#define OPCODE_DIVU 0x11 +#define OPCODE_MOD 0x12 +#define OPCODE_MODU 0x13 +#define OPCODE_AND 0x14 +#define OPCODE_OR 0x15 +#define OPCODE_XOR 0x16 +#define OPCODE_SHL 0x17 +#define OPCODE_SHR 0x18 +#define OPCODE_ASHR 0x19 +#define OPCODE_EXTNDB 0x1A +#define OPCODE_EXTNDW 0x1B +#define OPCODE_EXTNDD 0x1C +#define OPCODE_MOVBW 0x1D +#define OPCODE_MOVWW 0x1E +#define OPCODE_MOVDW 0x1F +#define OPCODE_MOVQW 0x20 +#define OPCODE_MOVBD 0x21 +#define OPCODE_MOVWD 0x22 +#define OPCODE_MOVDD 0x23 +#define OPCODE_MOVQD 0x24 +#define OPCODE_MOVSNW 0x25 // Move signed natural with word index +#define OPCODE_MOVSND 0x26 // Move signed natural with dword index +// +// #define OPCODE_27 0x27 +// +#define OPCODE_MOVQQ 0x28 // Does this go away? +#define OPCODE_LOADSP 0x29 +#define OPCODE_STORESP 0x2A +#define OPCODE_PUSH 0x2B +#define OPCODE_POP 0x2C +#define OPCODE_CMPIEQ 0x2D +#define OPCODE_CMPILTE 0x2E +#define OPCODE_CMPIGTE 0x2F +#define OPCODE_CMPIULTE 0x30 +#define OPCODE_CMPIUGTE 0x31 +#define OPCODE_MOVNW 0x32 +#define OPCODE_MOVND 0x33 +// +// #define OPCODE_34 0x34 +// +#define OPCODE_PUSHN 0x35 +#define OPCODE_POPN 0x36 +#define OPCODE_MOVI 0x37 +#define OPCODE_MOVIN 0x38 +#define OPCODE_MOVREL 0x39 + +// +// Bit masks for opcode encodings +// +#define OPCODE_M_OPCODE 0x3F // bits of interest for first level decode +#define OPCODE_M_IMMDATA 0x80 +#define OPCODE_M_IMMDATA64 0x40 +#define OPCODE_M_64BIT 0x40 // for CMP +#define OPCODE_M_RELADDR 0x10 // for CALL instruction +#define OPCODE_M_CMPI32_DATA 0x80 // for CMPI +#define OPCODE_M_CMPI64 0x40 // for CMPI 32 or 64 bit comparison +#define OPERAND_M_MOVIN_N 0x80 +#define OPERAND_M_CMPI_INDEX 0x10 + +// +// Masks for instructions that encode presence of indexes for operand1 and/or +// operand2. +// +#define OPCODE_M_IMMED_OP1 0x80 +#define OPCODE_M_IMMED_OP2 0x40 + +// +// Bit masks for operand encodings +// +#define OPERAND_M_INDIRECT1 0x08 +#define OPERAND_M_INDIRECT2 0x80 +#define OPERAND_M_OP1 0x07 +#define OPERAND_M_OP2 0x70 + +// +// Masks for data manipulation instructions +// +#define DATAMANIP_M_64 0x40 // 64-bit width operation +#define DATAMANIP_M_IMMDATA 0x80 + +// +// For MOV instructions, need a mask for the opcode when immediate +// data applies to R2. +// +#define OPCODE_M_IMMED_OP2 0x40 + +// +// The MOVI/MOVIn instructions use bit 6 of operands byte to indicate +// if an index is present. Then bits 4 and 5 are used to indicate the width +// of the move. +// +#define MOVI_M_IMMDATA 0x40 +#define MOVI_M_DATAWIDTH 0xC0 +#define MOVI_DATAWIDTH16 0x40 +#define MOVI_DATAWIDTH32 0x80 +#define MOVI_DATAWIDTH64 0xC0 +#define MOVI_M_MOVEWIDTH 0x30 +#define MOVI_MOVEWIDTH8 0x00 +#define MOVI_MOVEWIDTH16 0x10 +#define MOVI_MOVEWIDTH32 0x20 +#define MOVI_MOVEWIDTH64 0x30 + +// +// Masks for CALL instruction encodings +// +#define OPERAND_M_RELATIVE_ADDR 0x10 +#define OPERAND_M_NATIVE_CALL 0x20 + +// +// Masks for decoding push/pop instructions +// +#define PUSHPOP_M_IMMDATA 0x80 // opcode bit indicating immediate data +#define PUSHPOP_M_64 0x40 // opcode bit indicating 64-bit operation +// +// Mask for operand of JMP instruction +// +#define JMP_M_RELATIVE 0x10 +#define JMP_M_CONDITIONAL 0x80 +#define JMP_M_CS 0x40 + +// +// Macros to determine if a given operand is indirect +// +#define OPERAND1_INDIRECT(op) ((op) & OPERAND_M_INDIRECT1) +#define OPERAND2_INDIRECT(op) ((op) & OPERAND_M_INDIRECT2) + +// +// Macros to extract the operands from second byte of instructions +// +#define OPERAND1_REGNUM(op) ((op) & OPERAND_M_OP1) +#define OPERAND2_REGNUM(op) (((op) & OPERAND_M_OP2) >> 4) + +#define OPERAND1_CHAR(op) ('0' + OPERAND1_REGNUM (op)) +#define OPERAND2_CHAR(op) ('0' + OPERAND2_REGNUM (op)) + +// +// Condition masks usually for byte 1 encodings of code +// +#define CONDITION_M_CONDITIONAL 0x80 +#define CONDITION_M_CS 0x40 + +/// +/// Protocol Guid Name defined in spec. +/// +#define EFI_EBC_PROTOCOL_GUID EFI_EBC_INTERPRETER_PROTOCOL_GUID + +/// +/// Define for forward reference. +/// +typedef struct _EFI_EBC_PROTOCOL EFI_EBC_PROTOCOL; + +/** + Creates a thunk for an EBC entry point, returning the address of the thunk. + + A PE32+ EBC image, like any other PE32+ image, contains an optional header that specifies the + entry point for image execution. However, for EBC images, this is the entry point of EBC + instructions, so is not directly executable by the native processor. Therefore, when an EBC image is + loaded, the loader must call this service to get a pointer to native code (thunk) that can be executed, + which will invoke the interpreter to begin execution at the original EBC entry point. + + @param This A pointer to the EFI_EBC_PROTOCOL instance. + @param ImageHandle Handle of image for which the thunk is being created. + @param EbcEntryPoint Address of the actual EBC entry point or protocol service the thunk should call. + @param Thunk Returned pointer to a thunk created. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned. + @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_CREATE_THUNK)( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk + ); + +/** + Called prior to unloading an EBC image from memory. + + This function is called after an EBC image has exited, but before the image is actually unloaded. It + is intended to provide the interpreter with the opportunity to perform any cleanup that may be + necessary as a result of loading and executing the image. + + @param This A pointer to the EFI_EBC_PROTOCOL instance. + @param ImageHandle Image handle of the EBC image that is being unloaded from memory. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Image handle is not recognized as belonging + to an EBC image that has been executed. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_UNLOAD_IMAGE)( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ); + +/** + This is the prototype for the Flush callback routine. A pointer to a routine + of this type is passed to the EBC EFI_EBC_REGISTER_ICACHE_FLUSH protocol service. + + @param Start The beginning physical address to flush from the processor's instruction cache. + @param Length The number of bytes to flush from the processor's instruction cache. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EBC_ICACHE_FLUSH)( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +/** + Registers a callback function that the EBC interpreter calls to flush + the processor instruction cache following creation of thunks. + + @param This A pointer to the EFI_EBC_PROTOCOL instance. + @param Flush Pointer to a function of type EBC_ICACH_FLUSH. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_REGISTER_ICACHE_FLUSH)( + IN EFI_EBC_PROTOCOL *This, + IN EBC_ICACHE_FLUSH Flush + ); + +/** + Called to get the version of the interpreter. + + This function is called to get the version of the loaded EBC interpreter. The value and format of the + returned version is identical to that returned by the EBC BREAK 1 instruction. + + @param This A pointer to the EFI_EBC_PROTOCOL instance. + @param Version Pointer to where to store the returned version of the interpreter. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Version pointer is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_GET_VERSION)( + IN EFI_EBC_PROTOCOL *This, + IN OUT UINT64 *Version + ); + +/// +/// The EFI EBC protocol provides services to load and execute EBC images, which will typically be +/// loaded into option ROMs. The image loader will load the EBC image, perform standard relocations, +/// and invoke the CreateThunk() service to create a thunk for the EBC image's entry point. The +/// image can then be run using the standard EFI start image services. +/// +struct _EFI_EBC_PROTOCOL { + EFI_EBC_CREATE_THUNK CreateThunk; + EFI_EBC_UNLOAD_IMAGE UnloadImage; + EFI_EBC_REGISTER_ICACHE_FLUSH RegisterICacheFlush; + EFI_EBC_GET_VERSION GetVersion; +}; + +// +// Extern the global EBC protocol GUID +// +extern EFI_GUID gEfiEbcProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidActive.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidActive.h new file mode 100644 index 0000000..212f598 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidActive.h @@ -0,0 +1,52 @@ +/** @file + EDID Active Protocol from the UEFI 2.0 specification. + + Placed on the video output device child handle that is actively displaying output. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EDID_ACTIVE_H__ +#define __EDID_ACTIVE_H__ + +#define EFI_EDID_ACTIVE_PROTOCOL_GUID \ + { \ + 0xbd8c1056, 0x9f36, 0x44ec, {0x92, 0xa8, 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86 } \ + } + +/// +/// This protocol contains the EDID information for an active video output device. This is either the +/// EDID information retrieved from the EFI_EDID_OVERRIDE_PROTOCOL if an override is +/// available, or an identical copy of the EDID information from the +/// EFI_EDID_DISCOVERED_PROTOCOL if no overrides are available. +/// +typedef struct { + /// + /// The size, in bytes, of the Edid buffer. 0 if no EDID information + /// is available from the video output device. Otherwise, it must be a + /// minimum of 128 bytes. + /// + UINT32 SizeOfEdid; + + /// + /// A pointer to a read-only array of bytes that contains the EDID + /// information for an active video output device. This pointer is + /// NULL if no EDID information is available for the video output + /// device. The minimum size of a valid Edid buffer is 128 bytes. + /// EDID information is defined in the E-EDID EEPROM + /// specification published by VESA (www.vesa.org). + /// + UINT8 *Edid; +} EFI_EDID_ACTIVE_PROTOCOL; + +extern EFI_GUID gEfiEdidActiveProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidDiscovered.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidDiscovered.h new file mode 100644 index 0000000..fabfda6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidDiscovered.h @@ -0,0 +1,50 @@ +/** @file + EDID Discovered Protocol from the UEFI 2.0 specification. + + This protocol is placed on the video output device child handle. It represents + the EDID information being used for the output device represented by the child handle. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EDID_DISCOVERED_H__ +#define __EDID_DISCOVERED_H__ + +#define EFI_EDID_DISCOVERED_PROTOCOL_GUID \ + { \ + 0x1c0c34f6, 0xd380, 0x41fa, {0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa } \ + } + +/// +/// This protocol contains the EDID information retrieved from a video output device. +/// +typedef struct { + /// + /// The size, in bytes, of the Edid buffer. 0 if no EDID information + /// is available from the video output device. Otherwise, it must be a + /// minimum of 128 bytes. + /// + UINT32 SizeOfEdid; + + /// + /// A pointer to a read-only array of bytes that contains the EDID + /// information for an active video output device. This pointer is + /// NULL if no EDID information is available for the video output + /// device. The minimum size of a valid Edid buffer is 128 bytes. + /// EDID information is defined in the E-EDID EEPROM + /// specification published by VESA (www.vesa.org). + /// + UINT8 *Edid; +} EFI_EDID_DISCOVERED_PROTOCOL; + +extern EFI_GUID gEfiEdidDiscoveredProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidOverride.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidOverride.h new file mode 100644 index 0000000..7007874 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EdidOverride.h @@ -0,0 +1,67 @@ +/** @file + EDID Override Protocol from the UEFI 2.0 specification. + + Allow platform to provide EDID information to the producer of the Graphics Output + protocol. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EDID_OVERRIDE_H__ +#define __EDID_OVERRIDE_H__ + +#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \ + { \ + 0x48ecb431, 0xfb72, 0x45c0, {0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x4, 0xb, 0xd5 } \ + } + +typedef struct _EFI_EDID_OVERRIDE_PROTOCOL EFI_EDID_OVERRIDE_PROTOCOL; + +#define EFI_EDID_OVERRIDE_DONT_OVERRIDE 0x01 +#define EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG 0x02 + +/** + Returns policy information and potentially a replacement EDID for the specified video output device. + + @param This The EFI_EDID_OVERRIDE_PROTOCOL instance. + @param ChildHandle A child handle produced by the Graphics Output EFI + driver that represents a video output device. + @param Attributes The attributes associated with ChildHandle video output device. + @param EdidSize A pointer to the size, in bytes, of the Edid buffer. + @param Edid A pointer to callee allocated buffer that contains the EDID that + should be used for ChildHandle. A value of NULL + represents no EDID override for ChildHandle. + + @retval EFI_SUCCESS Valid overrides returned for ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle has no overrides. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID)( + IN EFI_EDID_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle, + OUT UINT32 *Attributes, + IN OUT UINTN *EdidSize, + IN OUT UINT8 **Edid + ); + +/// +/// This protocol is produced by the platform to allow the platform to provide +/// EDID information to the producer of the Graphics Output protocol. +/// +struct _EFI_EDID_OVERRIDE_PROTOCOL { + EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid; +}; + +extern EFI_GUID gEfiEdidOverrideProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EraseBlock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EraseBlock.h new file mode 100644 index 0000000..d136cce --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/EraseBlock.h @@ -0,0 +1,105 @@ +/** @file + This file defines the EFI Erase Block Protocol. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.6 + +**/ + +#ifndef __EFI_ERASE_BLOCK_PROTOCOL_H__ +#define __EFI_ERASE_BLOCK_PROTOCOL_H__ + +#define EFI_ERASE_BLOCK_PROTOCOL_GUID \ + { \ + 0x95a9a93e, 0xa86e, 0x4926, { 0xaa, 0xef, 0x99, 0x18, 0xe7, 0x72, 0xd9, 0x87 } \ + } + +typedef struct _EFI_ERASE_BLOCK_PROTOCOL EFI_ERASE_BLOCK_PROTOCOL; + +#define EFI_ERASE_BLOCK_PROTOCOL_REVISION ((2<<16) | (60)) + +/// +/// EFI_ERASE_BLOCK_TOKEN +/// +typedef struct { + // + // 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 erase request is completed. + // + EFI_EVENT Event; + // + // Defines whether the signaled event encountered an error. + // + EFI_STATUS TransactionStatus; +} EFI_ERASE_BLOCK_TOKEN; + +/** + Erase a specified number of device blocks. + + @param[in] This Indicates a pointer to the calling context. + @param[in] MediaId The media ID that the erase request is for. + @param[in] LBA The starting logical block address to be + erased. The caller is responsible for erasing + only legitimate locations. + @param[in, out] Token A pointer to the token associated with the + transaction. + @param[in] Size The size in bytes to be erased. This must be + a multiple of the physical block size of the + device. + + @retval EFI_SUCCESS The erase request was queued if Event is not + NULL. The data was erased correctly to the + device if the Event is NULL.to the device. + @retval EFI_WRITE_PROTECTED The device cannot be erased due to write + protection. + @retval EFI_DEVICE_ERROR The device reported an error while attempting + to perform the erase operation. + @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not + valid. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_ERASE) ( + IN EFI_ERASE_BLOCK_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_ERASE_BLOCK_TOKEN *Token, + IN UINTN Size + ); + +/// +/// The EFI Erase Block Protocol provides the ability for a device to expose +/// erase functionality. This optional protocol is installed on the same handle +/// as the EFI_BLOCK_IO_PROTOCOL or EFI_BLOCK_IO2_PROTOCOL. +/// +struct _EFI_ERASE_BLOCK_PROTOCOL { + // + // The revision to which the EFI_ERASE_BLOCK_PROTOCOL adheres. All future + // revisions must be backwards compatible. If a future version is not + // backwards compatible, it is not the same GUID. + // + UINT64 Revision; + // + // Returns the erase length granularity as a number of logical blocks. A + // value of 1 means the erase granularity is one logical block. + // + UINT32 EraseLengthGranularity; + EFI_BLOCK_ERASE EraseBlocks; +}; + +extern EFI_GUID gEfiEraseBlockProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalBootService.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalBootService.h new file mode 100644 index 0000000..339d541 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalBootService.h @@ -0,0 +1,217 @@ +/** @file + Definition of Extended SAL Boot Service Protocol + + The Extended SAL Boot Service Protocol provides a mechanisms for platform specific + drivers to update the SAL System Table and register Extended SAL Procedures that are + callable in physical or virtual mode using the SAL calling convention. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.2. + +**/ + +#ifndef _EXTENDED_SAL_BOOT_SERVICE_PROTOCOL_H_ +#define _EXTENDED_SAL_BOOT_SERVICE_PROTOCOL_H_ + +#include + +#define EXTENDED_SAL_BOOT_SERVICE_PROTOCOL_GUID \ + { 0xde0ee9a4, 0x3c7a, 0x44f2, {0xb7, 0x8b, 0xe3, 0xcc, 0xd6, 0x9c, 0x3a, 0xf7 } } + +typedef struct _EXTENDED_SAL_BOOT_SERVICE_PROTOCOL EXTENDED_SAL_BOOT_SERVICE_PROTOCOL; + +/** + Adds platform specific information to the to the header of the SAL System Table. + + @param This A pointer to the EXTENDED_SAL_BOOT_SERVICE_PROTOCOL instance. + @param SalAVersion Version of recovery SAL PEIM(s) in BCD format. Higher byte contains + the major revision and the lower byte contains the minor revision. + @param SalBVersion Version of DXE SAL Driver in BCD format. Higher byte contains + the major revision and the lower byte contains the minor revision. + @param OemId A pointer to a Null-terminated ASCII string that contains OEM unique string. + The string cannot be longer than 32 bytes in total length + @param ProductId A pointer to a Null-terminated ASCII string that uniquely identifies a family of + compatible products. The string cannot be longer than 32 bytes in total length. + + @retval EFI_SUCCESS The SAL System Table header was updated successfully. + @retval EFI_INVALID_PARAMETER OemId is NULL. + @retval EFI_INVALID_PARAMETER ProductId is NULL. + @retval EFI_INVALID_PARAMETER The length of OemId is greater than 32 characters. + @retval EFI_INVALID_PARAMETER The length of ProductId is greater than 32 characters. + +**/ +typedef +EFI_STATUS +(EFIAPI *EXTENDED_SAL_ADD_SST_INFO)( + IN EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *This, + IN UINT16 SalAVersion, + IN UINT16 SalBVersion, + IN CHAR8 *OemId, + IN CHAR8 *ProductId + ); + +/** + Adds an entry to the SAL System Table. + + This function adds the SAL System Table Entry specified by TableEntry and EntrySize + to the SAL System Table. + + @param This A pointer to the EXTENDED_SAL_BOOT_SERVICE_PROTOCOL instance. + @param TableEntry Pointer to a buffer containing a SAL System Table entry that is EntrySize bytes + in length. The first byte of the TableEntry describes the type of entry. + @param EntrySize The size, in bytes, of TableEntry. + + @retval EFI_SUCCESSThe SAL System Table was updated successfully. + @retval EFI_INVALID_PARAMETER TableEntry is NULL. + @retval EFI_INVALID_PARAMETER TableEntry specifies an invalid entry type. + @retval EFI_INVALID_PARAMETER EntrySize is not valid for this type of entry. + +**/ +typedef +EFI_STATUS +(EFIAPI *EXTENDED_SAL_ADD_SST_ENTRY)( + IN EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *This, + IN UINT8 *TableEntry, + IN UINTN EntrySize + ); + +/** + Internal ESAL procedures. + + This is prototype of internal Extended SAL procedures, which is registerd by + EXTENDED_SAL_REGISTER_INTERNAL_PROC service. + + @param FunctionId The Function ID associated with this Extended SAL Procedure. + @param Arg2 Second argument to the Extended SAL procedure. + @param Arg3 Third argument to the Extended SAL procedure. + @param Arg4 Fourth argument to the Extended SAL procedure. + @param Arg5 Fifth argument to the Extended SAL procedure. + @param Arg6 Sixth argument to the Extended SAL procedure. + @param Arg7 Seventh argument to the Extended SAL procedure. + @param Arg8 Eighth argument to the Extended SAL procedure. + @param VirtualMode TRUE if the Extended SAL Procedure is being invoked in virtual mode. + FALSE if the Extended SAL Procedure is being invoked in physical mode. + @param ModuleGlobal A pointer to the global context associated with this Extended SAL Procedure. + + @return The result returned from the specified Extended SAL Procedure + +**/ +typedef +SAL_RETURN_REGS +(EFIAPI *SAL_INTERNAL_EXTENDED_SAL_PROC)( + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + IN BOOLEAN VirtualMode, + IN VOID *ModuleGlobal OPTIONAL + ); + +/** + Registers an Extended SAL Procedure. + + The Extended SAL Procedure specified by InternalSalProc and named by ClassGuidLo, + ClassGuidHi, and FunctionId is added to the set of available Extended SAL Procedures. + + @param This A pointer to the EXTENDED_SAL_BOOT_SERVICE_PROTOCOL instance. + @param ClassGuidLo The lower 64-bits of the class GUID for the Extended SAL Procedure being added. + Each class GUID contains one or more functions specified by a Function ID. + @param ClassGuidHi The upper 64-bits of the class GUID for the Extended SAL Procedure being added. + Each class GUID contains one or more functions specified by a Function ID. + @param FunctionId The Function ID for the Extended SAL Procedure that is being added. This Function + ID is a member of the Extended SAL Procedure class specified by ClassGuidLo + and ClassGuidHi. + @param InternalSalProc A pointer to the Extended SAL Procedure being added. + @param PhysicalModuleGlobal Pointer to a module global structure. This is a physical mode pointer. + This pointer is passed to the Extended SAL Procedure specified by ClassGuidLo, + ClassGuidHi, FunctionId, and InternalSalProc. If the system is in physical mode, + then this pointer is passed unmodified to InternalSalProc. If the system is in + virtual mode, then the virtual address associated with this pointer is passed to + InternalSalProc. + + @retval EFI_SUCCESS The Extended SAL Procedure was added. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to add the Extended SAL Procedure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EXTENDED_SAL_REGISTER_INTERNAL_PROC)( + IN EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *This, + IN UINT64 ClassGuidLo, + IN UINT64 ClassGuidHi, + IN UINT64 FunctionId, + IN SAL_INTERNAL_EXTENDED_SAL_PROC InternalSalProc, + IN VOID *PhysicalModuleGlobal OPTIONAL + ); + +/** + Calls a previously registered Extended SAL Procedure. + + This function calls the Extended SAL Procedure specified by ClassGuidLo, ClassGuidHi, + and FunctionId. The set of previously registered Extended SAL Procedures is searched for a + matching ClassGuidLo, ClassGuidHi, and FunctionId. If a match is not found, then + EFI_SAL_NOT_IMPLEMENTED is returned. + + @param ClassGuidLo The lower 64-bits of the class GUID for the Extended SAL Procedure + that is being called. + @param ClassGuidHi The upper 64-bits of the class GUID for the Extended SAL Procedure + that is being called. + @param FunctionId Function ID for the Extended SAL Procedure being called. + @param Arg2 Second argument to the Extended SAL procedure. + @param Arg3 Third argument to the Extended SAL procedure. + @param Arg4 Fourth argument to the Extended SAL procedure. + @param Arg5 Fifth argument to the Extended SAL procedure. + @param Arg6 Sixth argument to the Extended SAL procedure. + @param Arg7 Seventh argument to the Extended SAL procedure. + @param Arg8 Eighth argument to the Extended SAL procedure. + + @retval EFI_SAL_NOT_IMPLEMENTED The Extended SAL Procedure specified by ClassGuidLo, + ClassGuidHi, and FunctionId has not been registered. + @retval EFI_SAL_VIRTUAL_ADDRESS_ERROR This function was called in virtual mode before virtual mappings + for the specified Extended SAL Procedure are available. + @retval Other The result returned from the specified Extended SAL Procedure + +**/ +typedef +SAL_RETURN_REGS +(EFIAPI *EXTENDED_SAL_PROC)( + IN UINT64 ClassGuidLo, + IN UINT64 ClassGuidHi, + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +/// +/// The EXTENDED_SAL_BOOT_SERVICE_PROTOCOL provides a mechanisms for platform specific +/// drivers to update the SAL System Table and register Extended SAL Procedures that are +/// callable in physical or virtual mode using the SAL calling convention. +/// +struct _EXTENDED_SAL_BOOT_SERVICE_PROTOCOL { + EXTENDED_SAL_ADD_SST_INFO AddSalSystemTableInfo; + EXTENDED_SAL_ADD_SST_ENTRY AddSalSystemTableEntry; + EXTENDED_SAL_REGISTER_INTERNAL_PROC RegisterExtendedSalProc; + EXTENDED_SAL_PROC ExtendedSalProc; +}; + +extern EFI_GUID gEfiExtendedSalBootServiceProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalServiceClasses.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalServiceClasses.h new file mode 100644 index 0000000..3566f45 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ExtendedSalServiceClasses.h @@ -0,0 +1,278 @@ +/** @file + The standard set of Extended SAL service classes. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.2. + +**/ + +#ifndef _EXTENDED_SAL_SERVICE_CLASSES_H_ +#define _EXTENDED_SAL_SERVICE_CLASSES_H_ + +/// +/// Extended SAL Base I/O Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID_LO 0x451531e15aea42b5 +#define EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID_HI 0xa6657525d5b831bc +#define EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID \ + { 0x5aea42b5, 0x31e1, 0x4515, {0xbc, 0x31, 0xb8, 0xd5, 0x25, 0x75, 0x65, 0xa6 } } + +typedef enum { + IoReadFunctionId, + IoWriteFunctionId, + MemReadFunctionId, + MemWriteFunctionId +} EFI_EXTENDED_SAL_BASE_IO_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Stall Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID_LO 0x4d8cac2753a58d06 +#define EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID_HI 0x704165808af0e9b5 +#define EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID \ + { 0x53a58d06, 0xac27, 0x4d8c, {0xb5, 0xe9, 0xf0, 0x8a, 0x80, 0x65, 0x41, 0x70 } } + +typedef enum { + StallFunctionId +} EFI_EXTENDED_SAL_STALL_FUNC_ID; +///@} + +/// +/// Extended SAL Real Time Clock Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID_LO 0x4d02efdb7e97a470 +#define EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID_HI 0x96a27bd29061ce8f +#define EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID \ + { 0x7e97a470, 0xefdb, 0x4d02, {0x8f, 0xce, 0x61, 0x90, 0xd2, 0x7b, 0xa2, 0x96 } } + +typedef enum { + GetTimeFunctionId, + SetTimeFunctionId, + GetWakeupTimeFunctionId, + SetWakeupTimeFunctionId, + GetRtcFreqFunctionId, + InitializeThresholdFunctionId, + BumpThresholdCountFunctionId, + GetThresholdCountFunctionId +} EFI_EXTENDED_SAL_RTC_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Variable Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID_LO 0x4370c6414ecb6c53 +#define EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID_HI 0x78836e490e3bb28c +#define EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID \ + { 0x4ecb6c53, 0xc641, 0x4370, {0x8c, 0xb2, 0x3b, 0x0e, 0x49, 0x6e, 0x83, 0x78 } } + +typedef enum { + EsalGetVariableFunctionId, + EsalGetNextVariableNameFunctionId, + EsalSetVariableFunctionId, + EsalQueryVariableInfoFunctionId +} EFI_EXTENDED_SAL_VARIABLE_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Monotonic Counter Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_MTC_SERVICES_PROTOCOL_GUID_LO 0x408b75e8899afd18 +#define EFI_EXTENDED_SAL_MTC_SERVICES_PROTOCOL_GUID_HI 0x54f4cd7e2e6e1aa4 +#define EFI_EXTENDED_SAL_MTC_SERVICES_PROTOCOL_GUID \ + { 0x899afd18, 0x75e8, 0x408b, {0xa4, 0x1a, 0x6e, 0x2e, 0x7e, 0xcd, 0xf4, 0x54 } } + +typedef enum { + GetNextHighMonotonicCountFunctionId +} EFI_EXTENDED_SAL_MTC_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Reset Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_RESET_SERVICES_PROTOCOL_GUID_LO 0x46f58ce17d019990 +#define EFI_EXTENDED_SAL_RESET_SERVICES_PROTOCOL_GUID_HI 0xa06a6798513c76a7 +#define EFI_EXTENDED_SAL_RESET_SERVICES_PROTOCOL_GUID \ + { 0x7d019990, 0x8ce1, 0x46f5, {0xa7, 0x76, 0x3c, 0x51, 0x98, 0x67, 0x6a, 0xa0 } } + +typedef enum { + ResetSystemFunctionId +} EFI_EXTENDED_SAL_RESET_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Status Code Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_PROTOCOL_GUID_LO 0x420f55e9dbd91d +#define EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_PROTOCOL_GUID_HI 0x4fb437849f5e3996 +#define EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_PROTOCOL_GUID \ + { 0xdbd91d, 0x55e9, 0x420f, {0x96, 0x39, 0x5e, 0x9f, 0x84, 0x37, 0xb4, 0x4f } } + +typedef enum { + ReportStatusCodeServiceFunctionId +} EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Firmware Volume Block Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID_LO 0x4f1dbcbba2271df1 +#define EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID_HI 0x1a072f17bc06a998 +#define EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID \ + { 0xa2271df1, 0xbcbb, 0x4f1d, {0x98, 0xa9, 0x06, 0xbc, 0x17, 0x2f, 0x07, 0x1a } } + +typedef enum { + ReadFunctionId, + WriteFunctionId, + EraseBlockFunctionId, + GetVolumeAttributesFunctionId, + SetVolumeAttributesFunctionId, + GetPhysicalAddressFunctionId, + GetBlockSizeFunctionId, +} EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL MP Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_MP_SERVICES_PROTOCOL_GUID_LO 0x4dc0cf18697d81a2 +#define EFI_EXTENDED_SAL_MP_SERVICES_PROTOCOL_GUID_HI 0x3f8a613b11060d9e +#define EFI_EXTENDED_SAL_MP_SERVICES_PROTOCOL_GUID \ + { 0x697d81a2, 0xcf18, 0x4dc0, {0x9e, 0x0d, 0x06, 0x11, 0x3b, 0x61, 0x8a, 0x3f } } + +typedef enum { + AddCpuDataFunctionId, + RemoveCpuDataFunctionId, + ModifyCpuDataFunctionId, + GetCpuDataByIDFunctionId, + GetCpuDataByIndexFunctionId, + SendIpiFunctionId, + CurrentProcInfoFunctionId, + NumProcessorsFunctionId, + SetMinStateFunctionId, + GetMinStateFunctionId +} EFI_EXTENDED_SAL_MP_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL PAL Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_PAL_SERVICES_PROTOCOL_GUID_LO 0x438d0fc2e1cd9d21 +#define EFI_EXTENDED_SAL_PAL_SERVICES_PROTOCOL_GUID_HI 0x571e966de6040397 +#define EFI_EXTENDED_SAL_PAL_SERVICES_PROTOCOL_GUID \ + { 0xe1cd9d21, 0x0fc2, 0x438d, {0x97, 0x03, 0x04, 0xe6, 0x6d, 0x96, 0x1e, 0x57 } } + +typedef enum { + PalProcFunctionId, + SetNewPalEntryFunctionId, + GetNewPalEntryFunctionId, + EsalUpdatePalFunctionId +} EFI_EXTENDED_SAL_PAL_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Base Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_LO 0x41c30fe0d9e9fa06 +#define EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID_HI 0xf894335a4283fb96 +#define EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID \ + { 0xd9e9fa06, 0x0fe0, 0x41c3, {0x96, 0xfb, 0x83, 0x42, 0x5a, 0x33, 0x94, 0xf8 } } + +typedef enum { + SalSetVectorsFunctionId, + SalMcRendezFunctionId, + SalMcSetParamsFunctionId, + EsalGetVectorsFunctionId, + EsalMcGetParamsFunctionId, + EsalMcGetMcParamsFunctionId, + EsalGetMcCheckinFlagsFunctionId, + EsalGetPlatformBaseFreqFunctionId, + EsalPhysicalIdInfoFunctionId, + EsalRegisterPhysicalAddrFunctionId +} EFI_EXTENDED_SAL_BASE_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL MCA Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_MCA_SERVICES_PROTOCOL_GUID_LO 0x42b16cc72a591128 +#define EFI_EXTENDED_SAL_MCA_SERVICES_PROTOCOL_GUID_HI 0xbb2d683b9358f08a +#define EFI_EXTENDED_SAL_MCA_SERVICES_PROTOCOL_GUID \ + { 0x2a591128, 0x6cc7, 0x42b1, {0x8a, 0xf0, 0x58, 0x93, 0x3b, 0x68, 0x2d, 0xbb } } + +typedef enum { + McaGetStateInfoFunctionId, + McaRegisterCpuFunctionId +} EFI_EXTENDED_SAL_MCA_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL PCI Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_LO 0x4905ad66a46b1a31 +#define EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID_HI 0x6330dc59462bf692 +#define EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID \ + { 0xa46b1a31, 0xad66, 0x4905, {0x92, 0xf6, 0x2b, 0x46, 0x59, 0xdc, 0x30, 0x63 } } + +typedef enum { + SalPciConfigReadFunctionId, + SalPciConfigWriteFunctionId +} EFI_EXTENDED_SAL_PCI_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL Cache Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID_LO 0x4ba52743edc9494 +#define EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID_HI 0x88f11352ef0a1888 +#define EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID \ + { 0xedc9494, 0x2743, 0x4ba5, { 0x88, 0x18, 0x0a, 0xef, 0x52, 0x13, 0xf1, 0x88 } } + +typedef enum { + SalCacheInitFunctionId, + SalCacheFlushFunctionId +} EFI_EXTENDED_SAL_CACHE_SERVICES_FUNC_ID; +///@} + +/// +/// Extended SAL MCA Log Services Class +/// +///@{ +#define EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_LO 0x4c0338a3cb3fd86e +#define EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID_HI 0x7aaba2a3cf905c9a +#define EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID \ + { 0xcb3fd86e, 0x38a3, 0x4c03, {0x9a, 0x5c, 0x90, 0xcf, 0xa3, 0xa2, 0xab, 0x7a } } + +typedef enum { + SalGetStateInfoFunctionId, + SalGetStateInfoSizeFunctionId, + SalClearStateInfoFunctionId, + EsalGetStateBufferFunctionId, + EsalSaveStateBufferFunctionId +} EFI_EXTENDED_SAL_MCA_LOG_SERVICES_FUNC_ID; +///@} + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareManagement.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareManagement.h new file mode 100644 index 0000000..15db3b2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareManagement.h @@ -0,0 +1,539 @@ +/** @file + UEFI Firmware Management Protocol definition + Firmware Management Protocol provides an abstraction for device to provide firmware + management support. The base requirements for managing device firmware images include + identifying firmware image revision level and programming the image into the device. + + GetImageInfo() is the only required function. GetImage(), SetImage(), + CheckImage(), GetPackageInfo(), and SetPackageInfo() shall return + EFI_UNSUPPORTED if not supported by the driver. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2013 - 2014, Hewlett-Packard Development Company, L.P.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.3 + +**/ + +#ifndef __EFI_FIRMWARE_MANAGEMENT_PROTOCOL_H__ +#define __EFI_FIRMWARE_MANAGEMENT_PROTOCOL_H__ + + +#define EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID \ + { \ + 0x86c77a67, 0xb97, 0x4633, {0xa1, 0x87, 0x49, 0x10, 0x4d, 0x6, 0x85, 0xc7 } \ + } + +typedef struct _EFI_FIRMWARE_MANAGEMENT_PROTOCOL EFI_FIRMWARE_MANAGEMENT_PROTOCOL; + +/// +/// EFI_FIRMWARE_IMAGE_DESCRIPTOR +/// +typedef struct { + /// + /// A unique number identifying the firmware image within the device. The number is + /// between 1 and DescriptorCount. + /// + UINT8 ImageIndex; + /// + /// A unique GUID identifying the firmware image type. + /// + EFI_GUID ImageTypeId; + /// + /// A unique number identifying the firmware image. + /// + UINT64 ImageId; + /// + /// A pointer to a null-terminated string representing the firmware image name. + /// + CHAR16 *ImageIdName; + /// + /// Identifies the version of the device firmware. The format is vendor specific and new + /// version must have a greater value than an old version. + /// + UINT32 Version; + /// + /// A pointer to a null-terminated string representing the firmware image version name. + /// + CHAR16 *VersionName; + /// + /// Size of the image in bytes. If size=0, then only ImageIndex and ImageTypeId are valid. + /// + UINTN Size; + /// + /// Image attributes that are supported by this device. See 'Image Attribute Definitions' + /// for possible returned values of this parameter. A value of 1 indicates the attribute is + /// supported and the current setting value is indicated in AttributesSetting. A + /// value of 0 indicates the attribute is not supported and the current setting value in + /// AttributesSetting is meaningless. + /// + UINT64 AttributesSupported; + /// + /// Image attributes. See 'Image Attribute Definitions' for possible returned values of + /// this parameter. + /// + UINT64 AttributesSetting; + /// + /// Image compatibilities. See 'Image Compatibility Definitions' for possible returned + /// values of this parameter. + /// + UINT64 Compatibilities; + /// + /// Describes the lowest ImageDescriptor version that the device will accept. Only + /// present in version 2 or higher. + /// + UINT32 LowestSupportedImageVersion; + /// + /// Describes the version that was last attempted to update. If no update attempted the + /// value will be 0. If the update attempted was improperly formatted and no version + /// number was available then the value will be zero. Only present in version 3 or higher. + UINT32 LastAttemptVersion; + /// + /// Describes the status that was last attempted to update. If no update has been attempted + /// the value will be LAST_ATTEMPT_STATUS_SUCCESS. Only present in version 3 or higher. + /// + UINT32 LastAttemptStatus; + /// + /// An optional number to identify the unique hardware instance within the system for + /// devices that may have multiple instances (Example: a plug in pci network card). This + /// number must be unique within the namespace of the ImageTypeId GUID and + /// ImageIndex. For FMP instances that have multiple descriptors for a single + /// hardware instance, all descriptors must have the same HardwareInstance value. + /// This number must be consistent between boots and should be based on some sort of + /// hardware identified unique id (serial number, etc) whenever possible. If a hardware + /// based number is not available the FMP provider may use some other characteristic + /// such as device path, bus/dev/function, slot num, etc for generating the + /// HardwareInstance. For implementations that will never have more than one + /// instance a zero can be used. A zero means the FMP provider is not able to determine a + /// unique hardware instance number or a hardware instance number is not needed. Only + /// present in version 3 or higher. + /// + UINT64 HardwareInstance; +} EFI_FIRMWARE_IMAGE_DESCRIPTOR; + + +// +// Image Attribute Definitions +// +/// +/// The attribute IMAGE_ATTRIBUTE_IMAGE_UPDATABLE indicates this device supports firmware +/// image update. +/// +#define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x0000000000000001 +/// +/// The attribute IMAGE_ATTRIBUTE_RESET_REQUIRED indicates a reset of the device is required +/// for the new firmware image to take effect after a firmware update. The device is the device hosting +/// the firmware image. +/// +#define IMAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 +/// +/// The attribute IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED indicates authentication is +/// required to perform the following image operations: GetImage(), SetImage(), and +/// CheckImage(). See 'Image Attribute - Authentication'. +/// +#define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x0000000000000004 +/// +/// The attribute IMAGE_ATTRIBUTE_IN_USE indicates the current state of the firmware image. +/// This distinguishes firmware images in a device that supports redundant images. +/// +#define IMAGE_ATTRIBUTE_IN_USE 0x0000000000000008 +/// +/// The attribute IMAGE_ATTRIBUTE_UEFI_IMAGE indicates that this image is an EFI compatible image. +/// +#define IMAGE_ATTRIBUTE_UEFI_IMAGE 0x0000000000000010 + + +// +// Image Compatibility Definitions +// +/// +/// Values from 0x0000000000000002 thru 0x000000000000FFFF are reserved for future assignments. +/// Values from 0x0000000000010000 thru 0xFFFFFFFFFFFFFFFF are used by firmware vendor for +/// compatibility check. +/// +#define IMAGE_COMPATIBILITY_CHECK_SUPPORTED 0x0000000000000001 + +/// +/// Descriptor Version exposed by GetImageInfo() function +/// +#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION 3 + + +/// +/// Image Attribute - Authentication Required +/// +typedef struct { + /// + /// It is included in the signature of AuthInfo. It is used to ensure freshness/no replay. + /// It is incremented during each firmware image operation. + /// + UINT64 MonotonicCount; + /// + /// Provides the authorization for the firmware image operations. It is a signature across + /// the image data and the Monotonic Count value. Caller uses the private key that is + /// associated with a public key that has been provisioned via the key exchange. + /// Because this is defined as a signature, WIN_CERTIFICATE_UEFI_GUID.CertType must + /// be EFI_CERT_TYPE_PKCS7_GUID. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; +} EFI_FIRMWARE_IMAGE_AUTHENTICATION; + + +// +// ImageUpdatable Definitions +// +/// +/// IMAGE_UPDATABLE_VALID indicates SetImage() will accept the new image and update the +/// device with the new image. The version of the new image could be higher or lower than +/// the current image. SetImage VendorCode is optional but can be used for vendor +/// specific action. +/// +#define IMAGE_UPDATABLE_VALID 0x0000000000000001 +/// +/// IMAGE_UPDATABLE_INVALID indicates SetImage() will reject the new image. No additional +/// information is provided for the rejection. +/// +#define IMAGE_UPDATABLE_INVALID 0x0000000000000002 +/// +/// IMAGE_UPDATABLE_INVALID_TYPE indicates SetImage() will reject the new image. The +/// rejection is due to the new image is not a firmware image recognized for this device. +/// +#define IMAGE_UPDATABLE_INVALID_TYPE 0x0000000000000004 +/// +/// IMAGE_UPDATABLE_INVALID_OLD indicates SetImage() will reject the new image. The +/// rejection is due to the new image version is older than the current firmware image +/// version in the device. The device firmware update policy does not support firmware +/// version downgrade. +/// +#define IMAGE_UPDATABLE_INVALID_OLD 0x0000000000000008 +/// +/// IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE indicates SetImage() will accept and update +/// the new image only if a correct VendorCode is provided or else image would be +/// rejected and SetImage will return appropriate error. +/// +#define IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE 0x0000000000000010 + + +// +// Package Attribute Definitions +// +/// +/// The attribute PACKAGE_ATTRIBUTE_VERSION_UPDATABLE indicates this device supports the +/// update of the firmware package version. +/// +#define PACKAGE_ATTRIBUTE_VERSION_UPDATABLE 0x0000000000000001 +/// +/// The attribute PACKAGE_ATTRIBUTE_RESET_REQUIRED indicates a reset of the device is +/// required for the new package info to take effect after an update. +/// +#define PACKAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 +/// +/// The attribute PACKAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED indicates authentication +/// is required to update the package info. +/// +#define PACKAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x0000000000000004 + +/** + Callback function to report the process of the firmware updating. + + @param[in] Completion A value between 1 and 100 indicating the current completion + progress of the firmware update. Completion progress is + reported as from 1 to 100 percent. A value of 0 is used by + the driver to indicate that progress reporting is not supported. + + @retval EFI_SUCCESS SetImage() continues to do the callback if supported. + @retval other SetImage() discontinues the callback and completes + the update and returns. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS)( + IN UINTN Completion + ); + +/** + Returns information about the current firmware image(s) of the device. + + This function allows a copy of the current firmware image to be created and saved. + The saved copy could later been used, for example, in firmware image recovery or rollback. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer. + On input, this is the size of the buffer allocated by the caller. + On output, it is the size of the buffer returned by the firmware + if the buffer was large enough, or the size of the buffer needed + to contain the image(s) information if the buffer was too small. + @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s) + information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number + associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] DescriptorCount A pointer to the location in which firmware returns the number of + descriptors or firmware images within this device. + @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes, + of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] PackageVersion A version number that represents all the firmware images in the device. + The format is vendor specific and new version must have a greater value + than the old version. If PackageVersion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison + is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates + that package version update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the + package version name. The buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility to free it with a call + to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size + needed to hold the image(s) information is returned in ImageInfoSize. + @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL. + @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GET_IMAGE_INFO)( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN OUT UINTN *ImageInfoSize, + IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, + OUT UINT32 *DescriptorVersion, + OUT UINT8 *DescriptorCount, + OUT UINTN *DescriptorSize, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName + ); + +/** + Retrieves a copy of the current firmware image of the device. + + This function allows a copy of the current firmware image to be created and saved. + The saved copy could later been used, for example, in firmware image recovery or rollback. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware image(s) within the device. + The number is between 1 and DescriptorCount. + @param[in, out] Image Points to the buffer where the current image is copied to. + @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes. + On return, points to the length of the image, in bytes. + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the + image. The current buffer size needed to hold the image is returned + in ImageSize. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_NOT_FOUND The current image is not copied to the buffer. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GET_IMAGE)( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN OUT VOID *Image, + IN OUT UINTN *ImageSize + ); + +/** + Updates the firmware image of the device. + + This function updates the hardware with the new firmware image. + This function returns EFI_UNSUPPORTED if the firmware image is not updatable. + If the firmware image is updatable, the function should perform the following minimal validations + before proceeding to do the firmware image update. + - Validate the image authentication if image has attribute + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns + EFI_SECURITY_VIOLATION if the validation fails. + - Validate the image is a supported image for this device. The function returns EFI_ABORTED if + the image is unsupported. The function can optionally provide more detailed information on + why the image is not a supported image. + - Validate the data from VendorCode if not null. Image validation must be performed before + VendorCode data validation. VendorCode data is ignored or considered invalid if image + validation failed. The function returns EFI_ABORTED if the data is invalid. + + VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if + the caller did not specify the policy or use the default policy. As an example, vendor can implement + a policy to allow an option to force a firmware image update when the abort reason is due to the new + firmware image version is older than the current firmware image version or bad image checksum. + Sensitive operations such as those wiping the entire firmware image and render the device to be + non-functional should be encoded in the image itself rather than passed with the VendorCode. + AbortReason enables vendor to have the option to provide a more detailed description of the abort + reason to the caller. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware image(s) within the device. + The number is between 1 and DescriptorCount. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy. + Null indicates the caller did not specify the policy or use the default policy. + @param[in] Progress A function used by the driver to report the progress of the firmware update. + @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more + details for the aborted operation. The buffer is allocated by this function + with AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with the new image. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_PROTOCOL_SET_IMAGE)( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + OUT CHAR16 **AbortReason + ); + +/** + Checks if the firmware image is valid for the device. + + This function allows firmware update application to validate the firmware image without + invoking the SetImage() first. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware image(s) within the device. + The number is between 1 and DescriptorCount. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides, + if available, additional information if the image is invalid. + + @retval EFI_SUCCESS The image was successfully checked. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_PROTOCOL_CHECK_IMAGE)( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ); + +/** + Returns information about the firmware package. + + This function returns package information. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[out] PackageVersion A version number that represents all the firmware images in the device. + The format is vendor specific and new version must have a greater value + than the old version. If PackageVersion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version + comparison is to be performed using PackageVersionName. A value of + 0xFFFFFFFD indicates that package version update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing + the package version name. The buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility to free it with a + call to FreePool(). + @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of + package version name. A value of 0 indicates the device does not support + update of package version name. Length is the number of Unicode characters, + including the terminating null character. + @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute + Definitions' for possible returned values of this parameter. A value of 1 + indicates the attribute is supported and the current setting value is + indicated in AttributesSetting. A value of 0 indicates the attribute is not + supported and the current setting value in AttributesSetting is meaningless. + @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned + values of this parameter + + @retval EFI_SUCCESS The package information was successfully returned. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GET_PACKAGE_INFO)( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName, + OUT UINT32 *PackageVersionNameMaxLen, + OUT UINT64 *AttributesSupported, + OUT UINT64 *AttributesSetting + ); + +/** + Updates information about the firmware package. + + This function updates package information. + This function returns EFI_UNSUPPORTED if the package information is not updatable. + VendorCode enables vendor to implement vendor-specific package information update policy. + Null if the caller did not specify this policy or use the default policy. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance. + @param[in] Image Points to the authentication image. + Null if authentication is not required. + @param[in] ImageSize Size of the authentication image in bytes. + 0 if authentication is not required. + @param[in] VendorCode This enables vendor to implement vendor-specific firmware + image update policy. + Null indicates the caller did not specify this policy or use + the default policy. + @param[in] PackageVersion The new package version. + @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing + the package version name. + The string length is equal to or less than the value returned in + PackageVersionNameMaxLen. + + @retval EFI_SUCCESS The device was successfully updated with the new package + information. + @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value + returned in PackageVersionNameMaxLen. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FIRMWARE_MANAGEMENT_PROTOCOL_SET_PACKAGE_INFO)( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN UINT32 PackageVersion, + IN CONST CHAR16 *PackageVersionName + ); + +/// +/// EFI_FIRMWARE_MANAGEMENT_PROTOCOL +/// The protocol for managing firmware provides the following services. +/// - Get the attributes of the current firmware image. Attributes include revision level. +/// - Get a copy of the current firmware image. As an example, this service could be used by a +/// management application to facilitate a firmware roll-back. +/// - Program the device with a firmware image supplied by the user. +/// - Label all the firmware images within a device with a single version. +/// +struct _EFI_FIRMWARE_MANAGEMENT_PROTOCOL { + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GET_IMAGE_INFO GetImageInfo; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GET_IMAGE GetImage; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_SET_IMAGE SetImage; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_CHECK_IMAGE CheckImage; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GET_PACKAGE_INFO GetPackageInfo; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_SET_PACKAGE_INFO SetPackageInfo; +}; + +extern EFI_GUID gEfiFirmwareManagementProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolume2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolume2.h new file mode 100644 index 0000000..e69eab2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolume2.h @@ -0,0 +1,762 @@ +/** @file + The Firmware Volume Protocol provides file-level access to the firmware volume. + Each firmware volume driver must produce an instance of the + Firmware Volume Protocol if the firmware volume is to be visible to + the system during the DXE phase. The Firmware Volume Protocol also provides + mechanisms for determining and modifying some attributes of the firmware volume. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: PI + Version 1.00. + +**/ + +#ifndef __FIRMWARE_VOLUME2_H__ +#define __FIRMWARE_VOLUME2_H__ + +#define EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID \ + { 0x220e73b6, 0x6bdb, 0x4413, { 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a } } + +typedef struct _EFI_FIRMWARE_VOLUME2_PROTOCOL EFI_FIRMWARE_VOLUME2_PROTOCOL; + + +/// +/// EFI_FV_ATTRIBUTES +/// +typedef UINT64 EFI_FV_ATTRIBUTES; + +// +// EFI_FV_ATTRIBUTES bit definitions +// +// EFI_FV_ATTRIBUTES bit semantics +#define EFI_FV2_READ_DISABLE_CAP 0x0000000000000001ULL +#define EFI_FV2_READ_ENABLE_CAP 0x0000000000000002ULL +#define EFI_FV2_READ_STATUS 0x0000000000000004ULL +#define EFI_FV2_WRITE_DISABLE_CAP 0x0000000000000008ULL +#define EFI_FV2_WRITE_ENABLE_CAP 0x0000000000000010ULL +#define EFI_FV2_WRITE_STATUS 0x0000000000000020ULL +#define EFI_FV2_LOCK_CAP 0x0000000000000040ULL +#define EFI_FV2_LOCK_STATUS 0x0000000000000080ULL +#define EFI_FV2_WRITE_POLICY_RELIABLE 0x0000000000000100ULL +#define EFI_FV2_READ_LOCK_CAP 0x0000000000001000ULL +#define EFI_FV2_READ_LOCK_STATUS 0x0000000000002000ULL +#define EFI_FV2_WRITE_LOCK_CAP 0x0000000000004000ULL +#define EFI_FV2_WRITE_LOCK_STATUS 0x0000000000008000ULL +#define EFI_FV2_ALIGNMENT 0x00000000001F0000ULL +#define EFI_FV2_ALIGNMENT_1 0x0000000000000000ULL +#define EFI_FV2_ALIGNMENT_2 0x0000000000010000ULL +#define EFI_FV2_ALIGNMENT_4 0x0000000000020000ULL +#define EFI_FV2_ALIGNMENT_8 0x0000000000030000ULL +#define EFI_FV2_ALIGNMENT_16 0x0000000000040000ULL +#define EFI_FV2_ALIGNMENT_32 0x0000000000050000ULL +#define EFI_FV2_ALIGNMENT_64 0x0000000000060000ULL +#define EFI_FV2_ALIGNMENT_128 0x0000000000070000ULL +#define EFI_FV2_ALIGNMENT_256 0x0000000000080000ULL +#define EFI_FV2_ALIGNMENT_512 0x0000000000090000ULL +#define EFI_FV2_ALIGNMENT_1K 0x00000000000A0000ULL +#define EFI_FV2_ALIGNMENT_2K 0x00000000000B0000ULL +#define EFI_FV2_ALIGNMENT_4K 0x00000000000C0000ULL +#define EFI_FV2_ALIGNMENT_8K 0x00000000000D0000ULL +#define EFI_FV2_ALIGNMENT_16K 0x00000000000E0000ULL +#define EFI_FV2_ALIGNMENT_32K 0x00000000000F0000ULL +#define EFI_FV2_ALIGNMENT_64K 0x0000000000100000ULL +#define EFI_FV2_ALIGNMENT_128K 0x0000000000110000ULL +#define EFI_FV2_ALIGNMENT_256K 0x0000000000120000ULL +#define EFI_FV2_ALIGNMENT_512K 0x0000000000130000ULL +#define EFI_FV2_ALIGNMENT_1M 0x0000000000140000ULL +#define EFI_FV2_ALIGNMENT_2M 0x0000000000150000ULL +#define EFI_FV2_ALIGNMENT_4M 0x0000000000160000ULL +#define EFI_FV2_ALIGNMENT_8M 0x0000000000170000ULL +#define EFI_FV2_ALIGNMENT_16M 0x0000000000180000ULL +#define EFI_FV2_ALIGNMENT_32M 0x0000000000190000ULL +#define EFI_FV2_ALIGNMENT_64M 0x00000000001A0000ULL +#define EFI_FV2_ALIGNMENT_128M 0x00000000001B0000ULL +#define EFI_FV2_ALIGNMENT_256M 0x00000000001C0000ULL +#define EFI_FV2_ALIGNMENT_512M 0x00000000001D0000ULL +#define EFI_FV2_ALIGNMENT_1G 0x00000000001E0000ULL +#define EFI_FV2_ALIGNMENT_2G 0x00000000001F0000ULL + +/** + Returns the attributes and current settings of the firmware volume. + + Because of constraints imposed by the underlying firmware + storage, an instance of the Firmware Volume Protocol may not + be to able to support all possible variations of this + architecture. These constraints and the current state of the + firmware volume are exposed to the caller using the + GetVolumeAttributes() function. GetVolumeAttributes() is + callable only from TPL_NOTIFY and below. Behavior of + GetVolumeAttributes() at any EFI_TPL above TPL_NOTIFY is + undefined. + + @param This Indicates the EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + + @param FvAttributes Pointer to an EFI_FV_ATTRIBUTES in which + the attributes and current settings are + returned. + + + @retval EFI_SUCCESS The firmware volume attributes were + returned. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FV_GET_ATTRIBUTES)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *FvAttributes +); + + +/** + Modifies the current settings of the firmware volume according to the input parameter. + + The SetVolumeAttributes() function is used to set configurable + firmware volume attributes. Only EFI_FV_READ_STATUS, + EFI_FV_WRITE_STATUS, and EFI_FV_LOCK_STATUS may be modified, and + then only in accordance with the declared capabilities. All + other bits of FvAttributes are ignored on input. On successful + return, all bits of *FvAttributes are valid and it contains the + completed EFI_FV_ATTRIBUTES for the volume. To modify an + attribute, the corresponding status bit in the EFI_FV_ATTRIBUTES + is set to the desired value on input. The EFI_FV_LOCK_STATUS bit + does not affect the ability to read or write the firmware + volume. Rather, once the EFI_FV_LOCK_STATUS bit is set, it + prevents further modification to all the attribute bits. + SetVolumeAttributes() is callable only from TPL_NOTIFY and + below. Behavior of SetVolumeAttributes() at any EFI_TPL above + TPL_NOTIFY is undefined. + + @param This Indicates the EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + + @param FvAttributes On input, FvAttributes is a pointer to + an EFI_FV_ATTRIBUTES containing the + desired firmware volume settings. On + successful return, it contains the new + settings of the firmware volume. On + unsuccessful return, FvAttributes is not + modified and the firmware volume + settings are not changed. + + @retval EFI_SUCCESS The requested firmware volume attributes + were set and the resulting + EFI_FV_ATTRIBUTES is returned in + FvAttributes. + + @retval EFI_INVALID_PARAMETER FvAttributes:EFI_FV_READ_STATUS + is set to 1 on input, but the + device does not support enabling + reads + (FvAttributes:EFI_FV_READ_ENABLE + is clear on return from + GetVolumeAttributes()). Actual + volume attributes are unchanged. + + @retval EFI_INVALID_PARAMETER FvAttributes:EFI_FV_READ_STATUS + is cleared to 0 on input, but + the device does not support + disabling reads + (FvAttributes:EFI_FV_READ_DISABL + is clear on return from + GetVolumeAttributes()). Actual + volume attributes are unchanged. + + @retval EFI_INVALID_PARAMETER FvAttributes:EFI_FV_WRITE_STATUS + is set to 1 on input, but the + device does not support enabling + writes + (FvAttributes:EFI_FV_WRITE_ENABL + is clear on return from + GetVolumeAttributes()). Actual + volume attributes are unchanged. + + @retval EFI_INVALID_PARAMETER FvAttributes:EFI_FV_WRITE_STATUS + is cleared to 0 on input, but + the device does not support + disabling writes + (FvAttributes:EFI_FV_WRITE_DISAB + is clear on return from + GetVolumeAttributes()). Actual + volume attributes are unchanged. + + @retval EFI_INVALID_PARAMETER FvAttributes:EFI_FV_LOCK_STATUS + is set on input, but the device + does not support locking + (FvAttributes:EFI_FV_LOCK_CAP is + clear on return from + GetVolumeAttributes()). Actual + volume attributes are unchanged. + + @retval EFI_ACCESS_DENIED Device is locked and does not + allow attribute modification + (FvAttributes:EFI_FV_LOCK_STATUS + is set on return from + GetVolumeAttributes()). Actual + volume attributes are unchanged. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FV_SET_ATTRIBUTES)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *FvAttributes +); + + +/** + Retrieves a file and/or file information from the firmware volume. + + ReadFile() is used to retrieve any file from a firmware volume + during the DXE phase. The actual binary encoding of the file in + the firmware volume media may be in any arbitrary format as long + as it does the following: It is accessed using the Firmware + Volume Protocol. The image that is returned follows the image + format defined in Code Definitions: PI Firmware File Format. + If the input value of Buffer==NULL, it indicates the caller is + requesting only that the type, attributes, and size of the + file be returned and that there is no output buffer. In this + case, the following occurs: + - BufferSize is returned with the size that is required to + successfully complete the read. + - The output parameters FoundType and *FileAttributes are + returned with valid values. + - The returned value of *AuthenticationStatus is undefined. + + If the input value of Buffer!=NULL, the output buffer is + specified by a double indirection of the Buffer parameter. The + input value of *Buffer is used to determine if the output + buffer is caller allocated or is dynamically allocated by + ReadFile(). If the input value of *Buffer!=NULL, it indicates + the output buffer is caller allocated. In this case, the input + value of *BufferSize indicates the size of the + caller-allocated output buffer. If the output buffer is not + large enough to contain the entire requested output, it is + filled up to the point that the output buffer is exhausted and + EFI_WARN_BUFFER_TOO_SMALL is returned, and then BufferSize is + returned with the size required to successfully complete the + read. All other output parameters are returned with valid + values. If the input value of *Buffer==NULL, it indicates the + output buffer is to be allocated by ReadFile(). In this case, + ReadFile() will allocate an appropriately sized buffer from + boot services pool memory, which will be returned in Buffer. + The size of the new buffer is returned in BufferSize and all + other output parameters are returned with valid values. + ReadFile() is callable only from TPL_NOTIFY and below. + Behavior of ReadFile() at any EFI_TPL above TPL_NOTIFY is + undefined. + + @param This Indicates the EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + + @param NameGuid Pointer to an EFI_GUID, which is the file + name. All firmware file names are EFI_GUIDs. + A single firmware volume must not have two + valid files with the same file name + EFI_GUID. + + @param Buffer Pointer to a pointer to a buffer in which the + file contents are returned, not including the + file header. + + @param BufferSize Pointer to a caller-allocated UINTN. It + indicates the size of the memory + represented by Buffer. + + @param FoundType Pointer to a caller-allocated EFI_FV_FILETYPE. + + @param FileAttributes Pointer to a caller-allocated + EFI_FV_FILE_ATTRIBUTES. + + @param AuthenticationStatus Pointer to a caller-allocated + UINT32 in which the + authentication status is + returned. + + @retval EFI_SUCCESS The call completed successfully. + + @retval EFI_WARN_BUFFER_TOO_SMALL The buffer is too small to + contain the requested + output. The buffer is + filled and the output is + truncated. + + @retval EFI_OUT_OF_RESOURCES An allocation failure occurred. + + @retval EFI_NOT_FOUND Name was not found in the firmware volume. + + @retval EFI_DEVICE_ERROR A hardware error occurred when + attempting to access the firmware volume. + + @retval EFI_ACCESS_DENIED The firmware volume is configured to + disallow reads. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FV_READ_FILE)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus +); + + + +/** + Locates the requested section within a file and returns it in a buffer. + + ReadSection() is used to retrieve a specific section from a file + within a firmware volume. The section returned is determined + using a depth-first, left-to-right search algorithm through all + sections found in the specified file. The output buffer is specified by a double indirection + of the Buffer parameter. The input value of Buffer is used to + determine if the output buffer is caller allocated or is + dynamically allocated by ReadSection(). If the input value of + Buffer!=NULL, it indicates that the output buffer is caller + allocated. In this case, the input value of *BufferSize + indicates the size of the caller-allocated output buffer. If + the output buffer is not large enough to contain the entire + requested output, it is filled up to the point that the output + buffer is exhausted and EFI_WARN_BUFFER_TOO_SMALL is returned, + and then BufferSize is returned with the size that is required + to successfully complete the read. All other + output parameters are returned with valid values. If the input + value of *Buffer==NULL, it indicates the output buffer is to + be allocated by ReadSection(). In this case, ReadSection() + will allocate an appropriately sized buffer from boot services + pool memory, which will be returned in *Buffer. The size of + the new buffer is returned in *BufferSize and all other output + parameters are returned with valid values. ReadSection() is + callable only from TPL_NOTIFY and below. Behavior of + ReadSection() at any EFI_TPL above TPL_NOTIFY is + undefined. + + @param This Indicates the EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + + @param NameGuid Pointer to an EFI_GUID, which indicates the + file name from which the requested section + will be read. + + @param SectionType Indicates the section type to return. + SectionType in conjunction with + SectionInstance indicates which section to + return. + + @param SectionInstance Indicates which instance of sections + with a type of SectionType to return. + SectionType in conjunction with + SectionInstance indicates which + section to return. SectionInstance is + zero based. + + @param Buffer Pointer to a pointer to a buffer in which the + section contents are returned, not including + the section header. + + @param BufferSize Pointer to a caller-allocated UINTN. It + indicates the size of the memory + represented by Buffer. + + @param AuthenticationStatus Pointer to a caller-allocated + UINT32 in which the authentication + status is returned. + + + @retval EFI_SUCCESS The call completed successfully. + + @retval EFI_WARN_BUFFER_TOO_SMALL The caller-allocated + buffer is too small to + contain the requested + output. The buffer is + filled and the output is + truncated. + + @retval EFI_OUT_OF_RESOURCES An allocation failure occurred. + + @retval EFI_NOT_FOUND The requested file was not found in + the firmware volume. EFI_NOT_FOUND The + requested section was not found in the + specified file. + + @retval EFI_DEVICE_ERROR A hardware error occurred when + attempting to access the firmware + volume. + + @retval EFI_ACCESS_DENIED The firmware volume is configured to + disallow reads. EFI_PROTOCOL_ERROR + The requested section was not found, + but the file could not be fully + parsed because a required + GUIDED_SECTION_EXTRACTION_PROTOCOL + was not found. It is possible the + requested section exists within the + file and could be successfully + extracted once the required + GUIDED_SECTION_EXTRACTION_PROTOCOL + is published. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FV_READ_SECTION)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus +); + +/// +/// EFI_FV_WRITE_POLICY, two policies (unreliable write and reliable write) are defined. +/// +typedef UINT32 EFI_FV_WRITE_POLICY; +#define EFI_FV_UNRELIABLE_WRITE 0x00000000 +#define EFI_FV_RELIABLE_WRITE 0x00000001 + +// +// EFI_FV_WRITE_FILE_DATA +// +typedef struct { + /// + /// Pointer to a GUID, which is the file name to be written. + /// + EFI_GUID *NameGuid; + /// + /// Indicates the type of file to be written. + /// + EFI_FV_FILETYPE Type; + /// + /// Indicates the attributes for the file to be written. + /// + EFI_FV_FILE_ATTRIBUTES FileAttributes; + /// + /// Pointer to a buffer containing the file to be written. + /// + VOID *Buffer; + /// + /// Indicates the size of the file image contained in Buffer. + /// + UINT32 BufferSize; +} EFI_FV_WRITE_FILE_DATA; + +/** + Locates the requested section within a file and returns it in a buffer. + + WriteFile() is used to write one or more files to a firmware + volume. Each file to be written is described by an + EFI_FV_WRITE_FILE_DATA structure. The caller must ensure that + any required alignment for all files listed in the FileData + array is compatible with the firmware volume. Firmware volume + capabilities can be determined using the GetVolumeAttributes() + call. Similarly, if the WritePolicy is set to + EFI_FV_RELIABLE_WRITE, the caller must check the firmware volume + capabilities to ensure EFI_FV_RELIABLE_WRITE is supported by the + firmware volume. EFI_FV_UNRELIABLE_WRITE must always be + supported. Writing a file with a size of zero + (FileData[n].BufferSize == 0) deletes the file from the firmware + volume if it exists. Deleting a file must be done one at a time. + Deleting a file as part of a multiple file write is not allowed. + Platform Initialization Specification VOLUME 3 Shared + Architectural Elements 84 August 21, 2006 Version 1.0 + WriteFile() is callable only from TPL_NOTIFY and below. + Behavior of WriteFile() at any EFI_TPL above TPL_NOTIFY is + undefined. + + @param This Indicates the EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + + @param NumberOfFiles Indicates the number of elements in the array pointed to by FileData + + @param WritePolicy Indicates the level of reliability for the + write in the event of a power failure or + other system failure during the write + operation. + + @param FileData Pointer to an array of + EFI_FV_WRITE_FILE_DATA. Each element of + FileData[] represents a file to be written. + + + @retval EFI_SUCCESS The write completed successfully. + + @retval EFI_OUT_OF_RESOURCES The firmware volume does not + have enough free space to + storefile(s). + + @retval EFI_DEVICE_ERROR A hardware error occurred when + attempting to access the firmware volume. + + @retval EFI_WRITE_PROTECTED The firmware volume is + configured to disallow writes. + + @retval EFI_NOT_FOUND A delete was requested, but the + requested file was not found in the + firmware volume. + + @retval EFI_INVALID_PARAMETER A delete was requested with a + multiple file write. + + @retval EFI_INVALID_PARAMETER An unsupported WritePolicy was + requested. + + @retval EFI_INVALID_PARAMETER An unknown file type was + specified. + + @retval EFI_INVALID_PARAMETER A file system specific error + has occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FV_WRITE_FILE)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData +); + + +/** + Retrieves information about the next file in the firmware volume store + that matches the search criteria. + + GetNextFile() is the interface that is used to search a firmware + volume for a particular file. It is called successively until + the desired file is located or the function returns + EFI_NOT_FOUND. To filter uninteresting files from the output, + the type of file to search for may be specified in FileType. For + example, if *FileType is EFI_FV_FILETYPE_DRIVER, only files of + this type will be returned in the output. If *FileType is + EFI_FV_FILETYPE_ALL, no filtering of file types is done. The Key + parameter is used to indicate a starting point of the search. If + the buffer *Key is completely initialized to zero, the search + re-initialized and starts at the beginning. Subsequent calls to + GetNextFile() must maintain the value of *Key returned by the + immediately previous call. The actual contents of *Key are + implementation specific and no semantic content is implied. + GetNextFile() is callable only from TPL_NOTIFY and below. + Behavior of GetNextFile() at any EFI_TPL above TPL_NOTIFY is + undefined. + + @param This Indicates the EFI_FIRMWARE_VOLUME2_PROTOCOL instance. + + @param Key Pointer to a caller-allocated buffer that contains implementation-specific data that is + used to track where to begin the search for the next file. The size of the buffer must be + at least This->KeySize bytes long. To re-initialize the search and begin from the + beginning of the firmware volume, the entire buffer must be cleared to zero. Other + than clearing the buffer to initiate a new search, the caller must not modify the data in + the buffer between calls to GetNextFile(). + + @param FileType Pointer to a caller-allocated + EFI_FV_FILETYPE. The GetNextFile() API can + filter its search for files based on the + value of the FileType input. A *FileType + input of EFI_FV_FILETYPE_ALL causes + GetNextFile() to search for files of all + types. If a file is found, the file's type + is returned in FileType. *FileType is not + modified if no file is found. + + @param NameGuid Pointer to a caller-allocated EFI_GUID. If a + matching file is found, the file's name is + returned in NameGuid. If no matching file is + found, *NameGuid is not modified. + + @param Attributes Pointer to a caller-allocated + EFI_FV_FILE_ATTRIBUTES. If a matching file + is found, the file's attributes are returned + in Attributes. If no matching file is found, + Attributes is not modified. Type + EFI_FV_FILE_ATTRIBUTES is defined in + ReadFile(). + + @param Size Pointer to a caller-allocated UINTN. If a + matching file is found, the file's size is + returned in *Size. If no matching file is found, + Size is not modified. + + @retval EFI_SUCCESS The output parameters are filled with data + obtained from the first matching file that + was found. + + @retval FI_NOT_FOUND No files of type FileType were found. + + + @retval EFI_DEVICE_ERROR A hardware error occurred when + attempting to access the firmware + volume. + + @retval EFI_ACCESS_DENIED The firmware volume is configured to + disallow reads. + + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FV_GET_NEXT_FILE)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size +); + +/** + Return information about a firmware volume. + + The GetInfo() function returns information of type + InformationType for the requested firmware volume. If the volume + does not support the requested information type, then + EFI_UNSUPPORTED is returned. If the buffer is not large enough + to hold the requested structure, EFI_BUFFER_TOO_SMALL is + returned and the BufferSize is set to the size of buffer that is + required to make the request. The information types defined by + this specification are required information types that all file + systems must support. + + @param This A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL + instance that is the file handle the requested + information is for. + + @param InformationType The type identifier for the + information being requested. + + @param BufferSize On input, the size of Buffer. On output, + the amount of data returned in Buffer. In + both cases, the size is measured in bytes. + + @param Buffer A pointer to the data buffer to return. The + buffer's type is indicated by InformationType. + + + @retval EFI_SUCCESS The information was retrieved. + + @retval EFI_UNSUPPORTED The InformationType is not known. + + @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_BUFFER_TOO_SMALL The BufferSize is too small to + read the current directory + entry. BufferSize has been + updated with the size needed to + complete the request. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_GET_INFO)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer +); + + +/** + Sets information about a firmware volume. + + The SetInfo() function sets information of type InformationType + on the requested firmware volume. + + + @param This A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL + instance that is the file handle the information + is for. + + @param InformationType The type identifier for the + information being set. + + @param BufferSize The size, in bytes, of Buffer. + + @param Buffer A pointer to the data buffer to write. The + buffer's type is indicated by InformationType. + + @retval EFI_SUCCESS The information was set. + + @retval EFI_UNSUPPORTED The InformationType is not known. + + @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 media is read only. + + @retval EFI_VOLUME_FULL The volume is full. + + @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the + size of the type indicated by + InformationType. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_SET_INFO)( + IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This, + IN CONST EFI_GUID *InformationType, + IN UINTN BufferSize, + IN CONST VOID *Buffer +); + + +/// +/// The Firmware Volume Protocol contains the file-level +/// abstraction to the firmware volume as well as some firmware +/// volume attribute reporting and configuration services. The +/// Firmware Volume Protocol is the interface used by all parts of +/// DXE that are not directly involved with managing the firmware +/// volume itself. This abstraction allows many varied types of +/// firmware volume implementations. A firmware volume may be a +/// flash device or it may be a file in the UEFI system partition, +/// for example. This level of firmware volume implementation +/// detail is not visible to the consumers of the Firmware Volume +/// Protocol. +/// +struct _EFI_FIRMWARE_VOLUME2_PROTOCOL { + EFI_FV_GET_ATTRIBUTES GetVolumeAttributes; + EFI_FV_SET_ATTRIBUTES SetVolumeAttributes; + EFI_FV_READ_FILE ReadFile; + EFI_FV_READ_SECTION ReadSection; + EFI_FV_WRITE_FILE WriteFile; + EFI_FV_GET_NEXT_FILE GetNextFile; + + /// + /// Data field that indicates the size in bytes + /// of the Key input buffer for the + /// GetNextFile() API. + /// + UINT32 KeySize; + + /// + /// Handle of the parent firmware volume. + /// + EFI_HANDLE ParentHandle; + EFI_FV_GET_INFO GetInfo; + EFI_FV_SET_INFO SetInfo; +}; + + +extern EFI_GUID gEfiFirmwareVolume2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolumeBlock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolumeBlock.h new file mode 100644 index 0000000..5c4645d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FirmwareVolumeBlock.h @@ -0,0 +1,366 @@ +/** @file + This file provides control over block-oriented firmware devices. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: PI + Version 1.0 and 1.2. + +**/ + +#ifndef __FIRMWARE_VOLUME_BLOCK_H__ +#define __FIRMWARE_VOLUME_BLOCK_H__ + +// +// EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is defined in PI 1.0 spec and its GUID value +// is later updated to be the same as that of EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL +// defined in PI 1.2 spec. +// +#define EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \ + { 0x8f644fa9, 0xe850, 0x4db1, {0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4 } } + +#define EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL_GUID \ + { 0x8f644fa9, 0xe850, 0x4db1, {0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4 } } + +typedef struct _EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL; + +typedef EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL; + +/** + The GetAttributes() function retrieves the attributes and + current settings of the block. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the + attributes and current settings are + returned. Type EFI_FVB_ATTRIBUTES_2 is defined + in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were + returned. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FVB_GET_ATTRIBUTES)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes +); + + +/** + The SetAttributes() function sets configurable firmware volume + attributes and returns the new settings of the firmware volume. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Attributes On input, Attributes is a pointer to + EFI_FVB_ATTRIBUTES_2 that contains the + desired firmware volume settings. On + successful return, it contains the new + settings of the firmware volume. Type + EFI_FVB_ATTRIBUTES_2 is defined in + EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were returned. + + @retval EFI_INVALID_PARAMETER The attributes requested are in + conflict with the capabilities + as declared in the firmware + volume header. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FVB_SET_ATTRIBUTES)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes +); + + +/** + The GetPhysicalAddress() function retrieves the base address of + a memory-mapped firmware volume. This function should be called + only for memory-mapped firmware volumes. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Address Pointer to a caller-allocated + EFI_PHYSICAL_ADDRESS that, on successful + return from GetPhysicalAddress(), contains the + base address of the firmware volume. + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_UNSUPPORTED The firmware volume is not memory mapped. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FVB_GET_PHYSICAL_ADDRESS)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address +); + +/** + The GetBlockSize() function retrieves the size of the requested + block. It also returns the number of additional blocks with + the identical size. The GetBlockSize() function is used to + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). + + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba Indicates the block for which to return the size. + + @param BlockSize Pointer to a caller-allocated UINTN in which + the size of the block is returned. + + @param NumberOfBlocks Pointer to a caller-allocated UINTN in + which the number of consecutive blocks, + starting with Lba, is returned. All + blocks in this range have a size of + BlockSize. + + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FVB_GET_BLOCK_SIZE)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks +); + + +/** + Reads the specified number of bytes into a buffer from the specified block. + + The Read() function reads the requested number of bytes from the + requested block and stores them in the provided buffer. + Implementations should be mindful that the firmware volume + might be in the ReadDisabled state. If it is in this state, + the Read() function must return the status code + EFI_ACCESS_DENIED without modifying the contents of the + buffer. The Read() function must also prevent spanning block + boundaries. If a read is requested that would span a block + boundary, the read must read up to the boundary but not + beyond. The output parameter NumBytes must be set to correctly + indicate the number of bytes actually read. The caller must be + aware that a read may be partially completed. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba The starting logical block index + from which to read. + + @param Offset Offset into the block at which to begin reading. + + @param NumBytes Pointer to a UINTN. At entry, *NumBytes + contains the total size of the buffer. At + exit, *NumBytes contains the total number of + bytes read. + + @param Buffer Pointer to a caller-allocated buffer that will + be used to hold the data that is read. + + @retval EFI_SUCCESS The firmware volume was read successfully, + and contents are in Buffer. + + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA + boundary. On output, NumBytes + contains the total number of bytes + returned in Buffer. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + ReadDisabled state. + + @retval EFI_DEVICE_ERROR The block device is not + functioning correctly and could + not be read. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_READ)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer +); + +/** + Writes the specified number of bytes from the input buffer to the block. + + The Write() function writes the specified number of bytes from + the provided buffer to the specified block and offset. If the + firmware volume is sticky write, the caller must ensure that + all the bits of the specified range to write are in the + EFI_FVB_ERASE_POLARITY state before calling the Write() + function, or else the result will be unpredictable. This + unpredictability arises because, for a sticky-write firmware + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY + state but cannot flip it back again. Before calling the + Write() function, it is recommended for the caller to first call + the EraseBlocks() function to erase the specified block to + write. A block erase cycle will transition bits from the + (NOT)EFI_FVB_ERASE_POLARITY state back to the + EFI_FVB_ERASE_POLARITY state. Implementations should be + mindful that the firmware volume might be in the WriteDisabled + state. If it is in this state, the Write() function must + return the status code EFI_ACCESS_DENIED without modifying the + contents of the firmware volume. The Write() function must + also prevent spanning block boundaries. If a write is + requested that spans a block boundary, the write must store up + to the boundary but not beyond. The output parameter NumBytes + must be set to correctly indicate the number of bytes actually + written. The caller must be aware that a write may be + partially completed. All writes, partial or otherwise, must be + fully flushed to the hardware before the Write() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba The starting logical block index to write to. + + @param Offset Offset into the block at which to begin writing. + + @param NumBytes The pointer to a UINTN. At entry, *NumBytes + contains the total size of the buffer. At + exit, *NumBytes contains the total number of + bytes actually written. + + @param Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an + LBA boundary. On output, NumBytes + contains the total number of bytes + actually written. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + WriteDisabled state. + + @retval EFI_DEVICE_ERROR The block device is malfunctioning + and could not be written. + + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FVB_WRITE)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer +); + + + + +/// +/// EFI_LBA_LIST_TERMINATOR +/// +#define EFI_LBA_LIST_TERMINATOR 0xFFFFFFFFFFFFFFFFULL + + +/** + Erases and initializes a firmware volume block. + + The EraseBlocks() function erases one or more blocks as denoted + by the variable argument list. The entire parameter list of + blocks must be verified before erasing any blocks. If a block is + requested that does not exist within the associated firmware + volume (it has a larger index than the last block of the + firmware volume), the EraseBlocks() function must return the + status code EFI_INVALID_PARAMETER without modifying the contents + of the firmware volume. Implementations should be mindful that + the firmware volume might be in the WriteDisabled state. If it + is in this state, the EraseBlocks() function must return the + status code EFI_ACCESS_DENIED without modifying the contents of + the firmware volume. All calls to EraseBlocks() must be fully + flushed to the hardware before the EraseBlocks() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL + instance. + + @param ... The variable argument list is a list of tuples. + Each tuple describes a range of LBAs to erase + and consists of the following: + - An EFI_LBA that indicates the starting LBA + - A UINTN that indicates the number of blocks to + erase. + + The list is terminated with an + EFI_LBA_LIST_TERMINATOR. For example, the + following indicates that two ranges of blocks + (5-7 and 10-11) are to be erased: EraseBlocks + (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); + + @retval EFI_SUCCESS The erase request successfully + completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + WriteDisabled state. + @retval EFI_DEVICE_ERROR The block device is not functioning + correctly and could not be written. + The firmware device may have been + partially erased. + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed + in the variable argument list do + not exist in the firmware volume. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_FVB_ERASE_BLOCKS)( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... +); + +/// +/// The Firmware Volume Block Protocol is the low-level interface +/// to a firmware volume. File-level access to a firmware volume +/// should not be done using the Firmware Volume Block Protocol. +/// Normal access to a firmware volume must use the Firmware +/// Volume Protocol. Typically, only the file system driver that +/// produces the Firmware Volume Protocol will bind to the +/// Firmware Volume Block Protocol. +/// +struct _EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL{ + EFI_FVB_GET_ATTRIBUTES GetAttributes; + EFI_FVB_SET_ATTRIBUTES SetAttributes; + EFI_FVB_GET_PHYSICAL_ADDRESS GetPhysicalAddress; + EFI_FVB_GET_BLOCK_SIZE GetBlockSize; + EFI_FVB_READ Read; + EFI_FVB_WRITE Write; + EFI_FVB_ERASE_BLOCKS EraseBlocks; + /// + /// The handle of the parent firmware volume. + /// + EFI_HANDLE ParentHandle; +}; + + +extern EFI_GUID gEfiFirmwareVolumeBlockProtocolGuid; +extern EFI_GUID gEfiFirmwareVolumeBlock2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FormBrowser2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FormBrowser2.h new file mode 100644 index 0000000..fe279c4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/FormBrowser2.h @@ -0,0 +1,180 @@ +/** @file + This protocol is defined in UEFI spec. + + The EFI_FORM_BROWSER2_PROTOCOL is the interface to call for drivers to + leverage the EFI configuration driver interface. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_FORM_BROWSER2_H__ +#define __EFI_FORM_BROWSER2_H__ + +#include + +#define EFI_FORM_BROWSER2_PROTOCOL_GUID \ + {0xb9d4c360, 0xbcfb, 0x4f9b, {0x92, 0x98, 0x53, 0xc1, 0x36, 0x98, 0x22, 0x58 }} + + +typedef struct _EFI_FORM_BROWSER2_PROTOCOL EFI_FORM_BROWSER2_PROTOCOL; + + + +/** + + @param LeftColumn The value that designates the text column + where the browser window will begin from + the left-hand side of the screen + + @param RightColumn The value that designates the text + column where the browser window will end + on the right-hand side of the screen. + + @param TopRow The value that designates the text row from the + top of the screen where the browser window + will start. + + @param BottomRow The value that designates the text row from the + bottom of the screen where the browser + window will end. +**/ +typedef struct { + UINTN LeftColumn; + UINTN RightColumn; + UINTN TopRow; + UINTN BottomRow; +} EFI_SCREEN_DESCRIPTOR; + +typedef UINTN EFI_BROWSER_ACTION_REQUEST; + +#define EFI_BROWSER_ACTION_REQUEST_NONE 0 +#define EFI_BROWSER_ACTION_REQUEST_RESET 1 +#define EFI_BROWSER_ACTION_REQUEST_SUBMIT 2 +#define EFI_BROWSER_ACTION_REQUEST_EXIT 3 +#define EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT 4 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT 5 +#define EFI_BROWSER_ACTION_REQUEST_FORM_APPLY 6 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD 7 +#define EFI_BROWSER_ACTION_REQUEST_RECONNECT 8 + + +/** + Initialize the browser to display the specified configuration forms. + + This function is the primary interface to the internal forms-based browser. + The forms browser will display forms associated with the specified Handles. + The browser will select all forms in packages which have the specified Type + and (for EFI_HII_PACKAGE_TYPE_GUID) the specified PackageGuid. + + @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance + + @param Handles A pointer to an array of Handles. This value should correspond + to the value of the HII form package that is required to be displayed. + + @param HandleCount The number of Handles specified in Handle. + + @param FormSetGuid This field points to the EFI_GUID which must match the Guid field or one of the + elements of the ClassId field in the EFI_IFR_FORM_SET op-code. If + FormsetGuid is NULL, then this function will display the form set class + EFI_HII_PLATFORM_SETUP_FORMSET_GUID. + + @param FormId This field specifies the identifier of the form within the form set to render as the first + displayable page. If this field has a value of 0x0000, then the Forms Browser will + render the first enabled form in the form set. + + @param ScreenDimensions Points to recommended form dimensions, including any non-content area, in + characters. + + @param ActionRequest Points to the action recommended by the form. + + @retval EFI_SUCCESS The function completed successfully + + @retval EFI_NOT_FOUND The variable was not found. + + @retval EFI_INVALID_PARAMETER One of the parameters has an + invalid value. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SEND_FORM2)( + IN CONST EFI_FORM_BROWSER2_PROTOCOL *This, + IN EFI_HII_HANDLE *Handle, + IN UINTN HandleCount, + IN EFI_GUID *FormSetGuid, OPTIONAL + IN EFI_FORM_ID FormId, OPTIONAL + IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL +); + + +/** + This function is called by a callback handler to retrieve uncommitted state data from the browser. + + This routine is called by a routine which was called by the + browser. This routine called this service in the browser to + retrieve or set certain uncommitted state information. + + @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance. + + @param ResultsDataSize A pointer to the size of the buffer + associated with ResultsData. On input, the size in + bytes of ResultsData. On output, the size of data + returned in ResultsData. + + @param ResultsData A string returned from an IFR browser or + equivalent. The results string will have + no routing information in them. + + @param RetrieveData A BOOLEAN field which allows an agent to + retrieve (if RetrieveData = TRUE) data + from the uncommitted browser state + information or set (if RetrieveData = + FALSE) data in the uncommitted browser + state information. + + @param VariableGuid An optional field to indicate the target + variable GUID name to use. + + @param VariableName An optional field to indicate the target + human-readable variable name. + + @retval EFI_SUCCESS The results have been distributed or are + awaiting distribution. + + @retval EFI_OUT_OF_RESOURCES The ResultsDataSize specified + was too small to contain the + results data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BROWSER_CALLBACK2)( + IN CONST EFI_FORM_BROWSER2_PROTOCOL *This, + IN OUT UINTN *ResultsDataSize, + IN OUT EFI_STRING ResultsData, + IN CONST BOOLEAN RetrieveData, + IN CONST EFI_GUID *VariableGuid, OPTIONAL + IN CONST CHAR16 *VariableName OPTIONAL +); + +/// +/// This interface will allow the caller to direct the configuration +/// driver to use either the HII database or use the passed-in packet of data. +/// +struct _EFI_FORM_BROWSER2_PROTOCOL { + EFI_SEND_FORM2 SendForm; + EFI_BROWSER_CALLBACK2 BrowserCallback; +} ; + +extern EFI_GUID gEfiFormBrowser2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ftp4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ftp4.h new file mode 100644 index 0000000..d259ecf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ftp4.h @@ -0,0 +1,524 @@ +/** @file + EFI FTPv4 (File Transfer Protocol version 4) Protocol Definition + The EFI FTPv4 Protocol is used to locate communication devices that are + supported by an EFI FTPv4 Protocol driver and to create and destroy instances + of the EFI FTPv4 Protocol child protocol driver that can use the underlying + communication device. + The definitions in this file are defined in UEFI Specification 2.3, which have + not been verified by one implementation yet. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_FTP4_PROTOCOL_H__ +#define __EFI_FTP4_PROTOCOL_H__ + + +#define EFI_FTP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xfaaecb1, 0x226e, 0x4782, {0xaa, 0xce, 0x7d, 0xb9, 0xbc, 0xbf, 0x4d, 0xaf } \ + } + +#define EFI_FTP4_PROTOCOL_GUID \ + { \ + 0xeb338826, 0x681b, 0x4295, {0xb3, 0x56, 0x2b, 0x36, 0x4c, 0x75, 0x7b, 0x9 } \ + } + +typedef struct _EFI_FTP4_PROTOCOL EFI_FTP4_PROTOCOL; + +/// +/// EFI_FTP4_CONNECTION_TOKEN +/// +typedef struct { + /// + /// The Event to signal after the connection is established and Status field is updated + /// by the EFI FTP v4 Protocol driver. The type of Event must be + /// EVENT_NOTIFY_SIGNAL, and its Task Priority Level (TPL) must be lower than or + /// equal to TPL_CALLBACK. If it is set to NULL, this function will not return until the + /// function completes. + /// + EFI_EVENT Event; + /// + /// The variable to receive the result of the completed operation. + /// EFI_SUCCESS: The FTP connection is established successfully + /// EFI_ACCESS_DENIED: The FTP server denied the access the user's request to access it. + /// EFI_CONNECTION_RESET: The connect fails because the connection is reset either by instance + /// itself or communication peer. + /// EFI_TIMEOUT: The connection establishment timer expired and no more specific + /// information is available. + /// EFI_NETWORK_UNREACHABLE: The active open fails because an ICMP network unreachable error is + /// received. + /// EFI_HOST_UNREACHABLE: The active open fails because an ICMP host unreachable error is + /// received. + /// EFI_PROTOCOL_UNREACHABLE: The active open fails because an ICMP protocol unreachable error is + /// received. + /// EFI_PORT_UNREACHABLE: The connection establishment timer times out and an ICMP port + /// unreachable error is received. + /// EFI_ICMP_ERROR: The connection establishment timer timeout and some other ICMP + /// error is received. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// + EFI_STATUS Status; +} EFI_FTP4_CONNECTION_TOKEN; + +/// +/// EFI_FTP4_CONFIG_DATA +/// +typedef struct { + /// + /// Pointer to a ASCII string that contains user name. The caller is + /// responsible for freeing Username after GetModeData() is called. + /// + UINT8 *Username; + /// + /// Pointer to a ASCII string that contains password. The caller is + /// responsible for freeing Password after GetModeData() is called. + /// + UINT8 *Password; + /// + /// Set it to TRUE to initiate an active data connection. Set it to + /// FALSE to initiate a passive data connection. + /// + BOOLEAN Active; + /// + /// Boolean value indicating if default network settting used. + /// + BOOLEAN UseDefaultSetting; + /// + /// IP address of station if UseDefaultSetting is FALSE. + /// + EFI_IPv4_ADDRESS StationIp; + /// + /// Subnet mask of station if UseDefaultSetting is FALSE. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// IP address of gateway if UseDefaultSetting is FALSE. + /// + EFI_IPv4_ADDRESS GatewayIp; + /// + /// IP address of FTPv4 server. + /// + EFI_IPv4_ADDRESS ServerIp; + /// + /// FTPv4 server port number of control connection, and the default + /// value is 21 as convention. + /// + UINT16 ServerPort; + /// + /// FTPv4 server port number of data connection. If it is zero, use + /// (ServerPort - 1) by convention. + /// + UINT16 AltDataPort; + /// + /// A byte indicate the representation type. The right 4 bit is used for + /// first parameter, the left 4 bit is use for second parameter + /// - For the first parameter, 0x0 = image, 0x1 = EBCDIC, 0x2 = ASCII, 0x3 = local + /// - For the second parameter, 0x0 = Non-print, 0x1 = Telnet format effectors, 0x2 = + /// Carriage Control. + /// - If it is a local type, the second parameter is the local byte byte size. + /// - If it is a image type, the second parameter is undefined. + /// + UINT8 RepType; + /// + /// Defines the file structure in FTP used. 0x00 = file, 0x01 = record, 0x02 = page. + /// + UINT8 FileStruct; + /// + /// Defines the transifer mode used in FTP. 0x00 = stream, 0x01 = Block, 0x02 = Compressed. + /// + UINT8 TransMode; +} EFI_FTP4_CONFIG_DATA; + +typedef struct _EFI_FTP4_COMMAND_TOKEN EFI_FTP4_COMMAND_TOKEN; + +/** + Callback function when process inbound or outbound data. + + If it is receiving function that leads to inbound data, the callback function + is called when data buffer is full. Then, old data in the data buffer should be + flushed and new data is stored from the beginning of data buffer. + If it is a transmit function that lead to outbound data and the size of + Data in daata buffer has been transmitted, this callback function is called to + supply additional data to be transmitted. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that + are used in this operation. + @return User defined Status. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_DATA_CALLBACK)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_COMMAND_TOKEN *Token + ); + +/// +/// EFI_FTP4_COMMAND_TOKEN +/// +struct _EFI_FTP4_COMMAND_TOKEN { + /// + /// The Event to signal after request is finished and Status field + /// is updated by the EFI FTP v4 Protocol driver. The type of Event + /// must be EVT_NOTIFY_SIGNAL, and its Task Priority Level + /// (TPL) must be lower than or equal to TPL_CALLBACK. If it is + /// set to NULL, related function must wait until the function + /// completes. + /// + EFI_EVENT Event; + /// + /// Pointer to a null-terminated ASCII name string. + /// + UINT8 *Pathname; + /// + /// The size of data buffer in bytes. + /// + UINT64 DataBufferSize; + /// + /// Pointer to the data buffer. Data downloaded from FTP server + /// through connection is downloaded here. + /// + VOID *DataBuffer; + /// + /// Pointer to a callback function. If it is receiving function that leads + /// to inbound data, the callback function is called when databuffer is + /// full. Then, old data in the data buffer should be flushed and new + /// data is stored from the beginning of data buffer. If it is a transmit + /// function that lead to outbound data and DataBufferSize of + /// Data in DataBuffer has been transmitted, this callback + /// function is called to supply additional data to be transmitted. The + /// size of additional data to be transmitted is indicated in + /// DataBufferSize, again. If there is no data remained, + /// DataBufferSize should be set to 0. + /// + EFI_FTP4_DATA_CALLBACK DataCallback; + /// + /// Pointer to the parameter for DataCallback. + /// + VOID *Context; + /// + /// The variable to receive the result of the completed operation. + /// EFI_SUCCESS: The FTP command is completed successfully. + /// EFI_ACCESS_DENIED: The FTP server denied the access to the requested file. + /// EFI_CONNECTION_RESET: The connect fails because the connection is reset either + /// by instance itself or communication peer. + /// EFI_TIMEOUT: The connection establishment timer expired and no more + /// specific information is available. + /// EFI_NETWORK_UNREACHABLE: The active open fails because an ICMP network unreachable + /// error is received. + /// EFI_HOST_UNREACHABLE: The active open fails because an ICMP host unreachable + /// error is received. + /// EFI_PROTOCOL_UNREACHABLE: The active open fails because an ICMP protocol unreachable + /// error is received. + /// EFI_PORT_UNREACHABLE: The connection establishment timer times out and an ICMP port + /// unreachable error is received. + /// EFI_ICMP_ERROR: The connection establishment timer timeout and some other ICMP + /// error is received. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// + EFI_STATUS Status; +}; + +/** + Gets the current operational settings. + + The GetModeData() function reads the current operational settings of this + EFI FTPv4 Protocol driver instance. EFI_FTP4_CONFIG_DATA is defined in the + EFI_FTP4_PROTOCOL.Configure. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[out] ModeData Pointer to storage for the EFI FTPv4 Protocol driver + mode data. The string buffers for Username and Password + in EFI_FTP4_CONFIG_DATA are allocated by the function, + and the caller should take the responsibility to free the + buffer later. + + @retval EFI_SUCCESS This function is called successfully. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ModeData is NULL. + @retval EFI_NOT_STARTED The EFI FTPv4 Protocol driver has not been started + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_GET_MODE_DATA)( + IN EFI_FTP4_PROTOCOL *This, + OUT EFI_FTP4_CONFIG_DATA *ModeData + ); + +/** + Disconnecting a FTP connection gracefully. + + The Connect() function will initiate a connection request to the remote FTP server + with the corresponding connection token. If this function returns EFI_SUCCESS, the + connection sequence is initiated successfully. If the connection succeeds or faild + due to any error, the Token->Event will be signaled and Token->Status will be updated + accordingly. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] Token Pointer to the token used to establish control connection. + + @retval EFI_SUCCESS The connection sequence is successfully initiated. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - Token is NULL. + - Token->Event is NULL. + @retval EFI_NOT_STARTED The EFI FTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_CONNECT)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_CONNECTION_TOKEN *Token + ); + +/** + Disconnecting a FTP connection gracefully. + + The Close() function will initiate a close request to the remote FTP server with the + corresponding connection token. If this function returns EFI_SUCCESS, the control + connection with the remote FTP server is closed. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] Token Pointer to the token used to close control connection. + + @retval EFI_SUCCESS The close request is successfully initiated. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - Token is NULL. + - Token->Event is NULL. + @retval EFI_NOT_STARTED The EFI FTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_CLOSE)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_CONNECTION_TOKEN *Token + ); + +/** + Sets or clears the operational parameters for the FTP child driver. + + The Configure() function will configure the connected FTP session with the + configuration setting specified in FtpConfigData. The configuration data can + be reset by calling Configure() with FtpConfigData set to NULL. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] FtpConfigData Pointer to configuration data that will be assigned to + the FTP child driver instance. If NULL, the FTP child + driver instance is reset to startup defaults and all + pending transmit and receive requests are flushed. + + @retval EFI_SUCCESS The FTPv4 driver was configured successfully. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + - This is NULL. + - FtpConfigData.RepType is invalid. + - FtpConfigData.FileStruct is invalid. + - FtpConfigData.TransMode is invalid. + - IP address in FtpConfigData is invalid. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_UNSUPPORTED One or more of the configuration parameters are not supported + by this implementation. + @retval EFI_OUT_OF_RESOURCES The EFI FTPv4 Protocol driver instance data could not be + allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI FTPv4 + Protocol driver instance is not configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_CONFIGURE)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_CONFIG_DATA *FtpConfigData OPTIONAL + ); + + +/** + Downloads a file from an FTPv4 server. + + The ReadFile() function is used to initialize and start an FTPv4 download process + and optionally wait for completion. When the download operation completes, whether + successfully or not, the Token.Status field is updated by the EFI FTPv4 Protocol + driver and then Token.Event is signaled (if it is not NULL). + + Data will be downloaded from the FTPv4 server into Token.DataBuffer. If the file size + is larger than Token.DataBufferSize, Token.DataCallback will be called to allow for + processing data and then new data will be placed at the beginning of Token.DataBuffer. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that + are used in this operation. + + @retval EFI_SUCCESS The data file is being downloaded successfully. + @retval EFI_INVALID_PARAMETER One or more of the parameters is not valid. + - This is NULL. + - Token is NULL. + - Token.Pathname is NULL. + - Token. DataBuffer is NULL. + - Token. DataBufferSize is 0. + @retval EFI_NOT_STARTED The EFI FTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_READ_FILE)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_COMMAND_TOKEN *Token + ); + +/** + Uploads a file from an FTPv4 server. + + The WriteFile() function is used to initialize and start an FTPv4 upload process and + optionally wait for completion. When the upload operation completes, whether successfully + or not, the Token.Status field is updated by the EFI FTPv4 Protocol driver and then + Token.Event is signaled (if it is not NULL). Data to be uploaded to server is stored + into Token.DataBuffer. Token.DataBufferSize is the number bytes to be transferred. + If the file size is larger than Token.DataBufferSize, Token.DataCallback will be called + to allow for processing data and then new data will be placed at the beginning of + Token.DataBuffer. Token.DataBufferSize is updated to reflect the actual number of bytes + to be transferred. Token.DataBufferSize is set to 0 by the call back to indicate the + completion of data transfer. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that + are used in this operation. + + @retval EFI_SUCCESS TThe data file is being uploaded successfully. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more of the parameters is not valid. + - This is NULL. + - Token is NULL. + - Token.Pathname is NULL. + - Token. DataBuffer is NULL. + - Token. DataBufferSize is 0. + @retval EFI_NOT_STARTED The EFI FTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_WRITE_FILE)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_COMMAND_TOKEN *Token + ); + +/** + Download a data file "directory" from a FTPv4 server. May be unsupported in some EFI + implementations. + + The ReadDirectory() function is used to return a list of files on the FTPv4 server that + logically (or operationally) related to Token.Pathname, and optionally wait for completion. + When the download operation completes, whether successfully or not, the Token.Status field + is updated by the EFI FTPv4 Protocol driver and then Token.Event is signaled (if it is not + NULL). Data will be downloaded from the FTPv4 server into Token.DataBuffer. If the file size + is larger than Token.DataBufferSize, Token.DataCallback will be called to allow for processing + data and then new data will be placed at the beginning of Token.DataBuffer. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that + are used in this operation. + + @retval EFI_SUCCESS The file list information is being downloaded successfully. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more of the parameters is not valid. + - This is NULL. + - Token is NULL. + - Token. DataBuffer is NULL. + - Token. DataBufferSize is 0. + @retval EFI_NOT_STARTED The EFI FTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_READ_DIRECTORY)( + IN EFI_FTP4_PROTOCOL *This, + IN EFI_FTP4_COMMAND_TOKEN *Token + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function can be used by network drivers and applications to increase the + rate that data packets are moved between the communications device and the transmit + and receive queues. In some systems, the periodic timer event in the managed network + driver may not poll the underlying communications device fast enough to transmit + and/or receive all data packets without missing incoming packets or dropping outgoing + packets. Drivers and applications that are experiencing packet loss should try calling + the Poll() function more often. + + @param[in] This Pointer to the EFI_FTP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI FTPv4 Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR EapAuthType An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FTP4_POLL)( + IN EFI_FTP4_PROTOCOL *This + ); + +/// +/// EFI_FTP4_PROTOCOL +/// provides basic services for client-side FTP (File Transfer Protocol) +/// operations. +/// +struct _EFI_FTP4_PROTOCOL { + EFI_FTP4_GET_MODE_DATA GetModeData; + EFI_FTP4_CONNECT Connect; + EFI_FTP4_CLOSE Close; + EFI_FTP4_CONFIGURE Configure; + EFI_FTP4_READ_FILE ReadFile; + EFI_FTP4_WRITE_FILE WriteFile; + EFI_FTP4_READ_DIRECTORY ReadDirectory; + EFI_FTP4_POLL Poll; +}; + +extern EFI_GUID gEfiFtp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiFtp4ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GraphicsOutput.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GraphicsOutput.h new file mode 100644 index 0000000..d32f9bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GraphicsOutput.h @@ -0,0 +1,276 @@ +/** @file + Graphics Output Protocol from the UEFI 2.0 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __GRAPHICS_OUTPUT_H__ +#define __GRAPHICS_OUTPUT_H__ + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { \ + 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ + } + +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + /// + /// A pixel is 32-bits and byte zero represents red, byte one represents green, + /// byte two represents blue, and byte three is reserved. This is the definition + /// for the physical frame buffer. The byte values for the red, green, and blue + /// components represent the color intensity. This color intensity value range + /// from a minimum intensity of 0 to maximum intensity of 255. + /// + PixelRedGreenBlueReserved8BitPerColor, + /// + /// A pixel is 32-bits and byte zero represents blue, byte one represents green, + /// byte two represents red, and byte three is reserved. This is the definition + /// for the physical frame buffer. The byte values for the red, green, and blue + /// components represent the color intensity. This color intensity value range + /// from a minimum intensity of 0 to maximum intensity of 255. + /// + PixelBlueGreenRedReserved8BitPerColor, + /// + /// The Pixel definition of the physical frame buffer. + /// + PixelBitMask, + /// + /// This mode does not support a physical frame buffer. + /// + PixelBltOnly, + /// + /// Valid EFI_GRAPHICS_PIXEL_FORMAT enum values are less than this value. + /// + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + /// + /// The version of this data structure. A value of zero represents the + /// EFI_GRAPHICS_OUTPUT_MODE_INFORMATION structure as defined in this specification. + /// + UINT32 Version; + /// + /// The size of video screen in pixels in the X dimension. + /// + UINT32 HorizontalResolution; + /// + /// The size of video screen in pixels in the Y dimension. + /// + UINT32 VerticalResolution; + /// + /// Enumeration that defines the physical format of the pixel. A value of PixelBltOnly + /// implies that a linear frame buffer is not available for this mode. + /// + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + /// + /// This bit-mask is only valid if PixelFormat is set to PixelPixelBitMask. + /// A bit being set defines what bits are used for what purpose such as Red, Green, Blue, or Reserved. + /// + EFI_PIXEL_BITMASK PixelInformation; + /// + /// Defines the number of pixel elements per video memory line. + /// + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Returns information for an available graphics mode that the graphics device + and the set of active video output devices supports. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Valid mode information was returned. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_INVALID_PARAMETER ModeNumber is not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +/// +/// actions for BltOperations +/// +typedef enum { + /// + /// Write data from the BltBuffer pixel (0, 0) + /// directly to every pixel of the video display rectangle + /// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + /// Only one pixel will be used from the BltBuffer. Delta is NOT used. + /// + EfiBltVideoFill, + + /// + /// Read data from the video display rectangle + /// (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + /// the BltBuffer rectangle (DestinationX, DestinationY ) + /// (DestinationX + Width, DestinationY + Height). If DestinationX or + /// DestinationY is not zero then Delta must be set to the length in bytes + /// of a row in the BltBuffer. + /// + EfiBltVideoToBltBuffer, + + /// + /// Write data from the BltBuffer rectangle + /// (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + /// video display rectangle (DestinationX, DestinationY) + /// (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + /// not zero then Delta must be set to the length in bytes of a row in the + /// BltBuffer. + /// + EfiBltBufferToVideo, + + /// + /// Copy from the video display rectangle (SourceX, SourceY) + /// (SourceX + Width, SourceY + Height) to the video display rectangle + /// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + /// The BltBuffer and Delta are not used in this mode. + /// + EfiBltVideoToVideo, + + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer. + + @param This Protocol instance pointer. + @param BltBuffer The data to transfer to the graphics screen. + Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). + @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen. + @param SourceX The X coordinate of source for the BltOperation. + @param SourceY The Y coordinate of source for the BltOperation. + @param DestinationX The X coordinate of destination for the BltOperation. + @param DestinationY The Y coordinate of destination for the BltOperation. + @param Width The width of a rectangle in the blt rectangle in pixels. + @param Height The height of a rectangle in the blt rectangle in pixels. + @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation. + If a Delta of zero is used, the entire BltBuffer is being operated on. + If a subrectangle of the BltBuffer is being used then Delta + represents the number of bytes in a row of the BltBuffer. + + @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +typedef struct { + /// + /// The number of modes supported by QueryMode() and SetMode(). + /// + UINT32 MaxMode; + /// + /// Current Mode of the graphics device. Valid mode numbers are 0 to MaxMode -1. + /// + UINT32 Mode; + /// + /// Pointer to read-only EFI_GRAPHICS_OUTPUT_MODE_INFORMATION data. + /// + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + /// + /// Size of Info structure in bytes. + /// + UINTN SizeOfInfo; + /// + /// Base address of graphics linear frame buffer. + /// Offset zero in FrameBufferBase represents the upper left pixel of the display. + /// + EFI_PHYSICAL_ADDRESS FrameBufferBase; + /// + /// Amount of frame buffer needed to support the active mode as defined by + /// PixelsPerScanLine xVerticalResolution x PixelElementSize. + /// + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +/// +/// Provides a basic abstraction to set video modes and copy pixels to and from +/// the graphics controller's frame buffer. The linear address of the hardware +/// frame buffer is also exposed so software can write directly to the video hardware. +/// +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + /// + /// Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE data. + /// + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +}; + +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GuidedSectionExtraction.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GuidedSectionExtraction.h new file mode 100644 index 0000000..b119eed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/GuidedSectionExtraction.h @@ -0,0 +1,141 @@ +/** @file + If a GUID-defined section is encountered when doing section + extraction, the section extraction driver calls the appropriate + instance of the GUIDed Section Extraction Protocol to extract + the section stream contained therein. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: PI + Version 1.00. + +**/ + +#ifndef __GUID_SECTION_EXTRACTION_PROTOCOL_H__ +#define __GUID_SECTION_EXTRACTION_PROTOCOL_H__ + +// +// The protocol interface structures are identified by associating +// them with a GUID. Each instance of a protocol with a given +// GUID must have the same interface structure. While all instances +// of the GUIDed Section Extraction Protocol must have the same +// interface structure, they do not all have the same GUID. The +// GUID that is associated with an instance of the GUIDed Section +// Extraction Protocol is used to correlate it with the GUIDed +// section type that it is intended to process. +// + +typedef struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL; + + +/** + The ExtractSection() function processes the input section and + allocates a buffer from the pool in which it returns the section + contents. If the section being extracted contains + authentication information (the section's + GuidedSectionHeader.Attributes field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values + returned in AuthenticationStatus must reflect the results of + the authentication operation. Depending on the algorithm and + size of the encapsulated data, the time that is required to do + a full authentication may be prohibitively long for some + classes of systems. To indicate this, use + EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by + the security policy driver (see the Platform Initialization + Driver Execution Environment Core Interface Specification for + more details and the GUID definition). If the + EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle + database, then, if possible, full authentication should be + skipped and the section contents simply returned in the + OutputBuffer. In this case, the + EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus + must be set on return. ExtractSection() is callable only from + TPL_NOTIFY and below. Behavior of ExtractSection() at any + EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is + defined in RaiseTPL() in the UEFI 2.0 specification. + + + @param This Indicates the EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance. + + @param InputSection Buffer containing the input GUIDed section + to be processed. OutputBuffer OutputBuffer + is allocated from boot services pool + memory and contains the new section + stream. The caller is responsible for + freeing this buffer. + + @param OutputSize A pointer to a caller-allocated UINTN in + which the size of OutputBuffer allocation + is stored. If the function returns + anything other than EFI_SUCCESS, the value + of OutputSize is undefined. + + @param AuthenticationStatus A pointer to a caller-allocated + UINT32 that indicates the + authentication status of the + output buffer. If the input + section's + GuidedSectionHeader.Attributes + field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VAL + bit as clear, AuthenticationStatus + must return zero. Both local bits + (19:16) and aggregate bits (3:0) + in AuthenticationStatus are + returned by ExtractSection(). + These bits reflect the status of + the extraction operation. The bit + pattern in both regions must be + the same, as the local and + aggregate authentication statuses + have equivalent meaning at this + level. If the function returns + anything other than EFI_SUCCESS, + the value of AuthenticationStatus + is undefined. + + @retval EFI_SUCCESS The InputSection was successfully + processed and the section contents were + returned. + + @retval EFI_OUT_OF_RESOURCES The system has insufficient + resources to process the + request. + + @retval EFI_INVALID_PARAMETER The GUID in InputSection does + not match this instance of the + GUIDed Section Extraction + Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXTRACT_GUIDED_SECTION)( + IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This, + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus +); + + +/// +/// Typically, protocol interface structures are identified by associating them with a GUID. Each +/// instance of a protocol with a given GUID must have the same interface structure. While all instances +/// of the GUIDed Section Extraction Protocol must have the same interface structure, they do not all +/// have the same GUID. The GUID that is associated with an instance of the GUIDed Section +/// Extraction Protocol is used to correlate it with the GUIDed section type that it is intended to process. +/// +struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL { + EFI_EXTRACT_GUIDED_SECTION ExtractSection; +}; + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash.h new file mode 100644 index 0000000..c8cdd98 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash.h @@ -0,0 +1,175 @@ +/** @file + EFI_HASH_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0. + EFI_HASH_PROTOCOL as defined in UEFI 2.0. + The EFI Hash Service Binding Protocol is used to locate hashing services support + provided by a driver and to create and destroy instances of the EFI Hash Protocol + so that a multiple drivers can use the underlying hashing services. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_HASH_PROTOCOL_H__ +#define __EFI_HASH_PROTOCOL_H__ + +#define EFI_HASH_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x42881c98, 0xa4f3, 0x44b0, {0xa3, 0x9d, 0xdf, 0xa1, 0x86, 0x67, 0xd8, 0xcd } \ + } + +#define EFI_HASH_PROTOCOL_GUID \ + { \ + 0xc5184932, 0xdba5, 0x46db, {0xa5, 0xba, 0xcc, 0x0b, 0xda, 0x9c, 0x14, 0x35 } \ + } + +#define EFI_HASH_ALGORITHM_SHA1_GUID \ + { \ + 0x2ae9d80f, 0x3fb2, 0x4095, {0xb7, 0xb1, 0xe9, 0x31, 0x57, 0xb9, 0x46, 0xb6 } \ + } + +#define EFI_HASH_ALGORITHM_SHA224_GUID \ + { \ + 0x8df01a06, 0x9bd5, 0x4bf7, {0xb0, 0x21, 0xdb, 0x4f, 0xd9, 0xcc, 0xf4, 0x5b } \ + } + +#define EFI_HASH_ALGORITHM_SHA256_GUID \ + { \ + 0x51aa59de, 0xfdf2, 0x4ea3, {0xbc, 0x63, 0x87, 0x5f, 0xb7, 0x84, 0x2e, 0xe9 } \ + } + +#define EFI_HASH_ALGORITHM_SHA384_GUID \ + { \ + 0xefa96432, 0xde33, 0x4dd2, {0xae, 0xe6, 0x32, 0x8c, 0x33, 0xdf, 0x77, 0x7a } \ + } + +#define EFI_HASH_ALGORITHM_SHA512_GUID \ + { \ + 0xcaa4381e, 0x750c, 0x4770, {0xb8, 0x70, 0x7a, 0x23, 0xb4, 0xe4, 0x21, 0x30 } \ + } + +#define EFI_HASH_ALGORTIHM_MD5_GUID \ + { \ + 0xaf7c79c, 0x65b5, 0x4319, {0xb0, 0xae, 0x44, 0xec, 0x48, 0x4e, 0x4a, 0xd7 } \ + } + +#define EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID \ + { \ + 0x24c5dc2f, 0x53e2, 0x40ca, {0x9e, 0xd6, 0xa5, 0xd9, 0xa4, 0x9f, 0x46, 0x3b } \ + } + +#define EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID \ + { \ + 0x8628752a, 0x6cb7, 0x4814, {0x96, 0xfc, 0x24, 0xa8, 0x15, 0xac, 0x22, 0x26 } \ + } + +// +// Note: Use of the following algorithms with EFI_HASH_PROTOCOL is deprecated. +// EFI_HASH_ALGORITHM_SHA1_GUID +// EFI_HASH_ALGORITHM_SHA224_GUID +// EFI_HASH_ALGORITHM_SHA256_GUID +// EFI_HASH_ALGORITHM_SHA384_GUID +// EFI_HASH_ALGORITHM_SHA512_GUID +// EFI_HASH_ALGORTIHM_MD5_GUID +// + +typedef struct _EFI_HASH_PROTOCOL EFI_HASH_PROTOCOL; + +typedef UINT8 EFI_MD5_HASH[16]; +typedef UINT8 EFI_SHA1_HASH[20]; +typedef UINT8 EFI_SHA224_HASH[28]; +typedef UINT8 EFI_SHA256_HASH[32]; +typedef UINT8 EFI_SHA384_HASH[48]; +typedef UINT8 EFI_SHA512_HASH[64]; + +typedef union { + EFI_MD5_HASH *Md5Hash; + EFI_SHA1_HASH *Sha1Hash; + EFI_SHA224_HASH *Sha224Hash; + EFI_SHA256_HASH *Sha256Hash; + EFI_SHA384_HASH *Sha384Hash; + EFI_SHA512_HASH *Sha512Hash; +} EFI_HASH_OUTPUT; + +/** + Returns the size of the hash which results from a specific algorithm. + + @param[in] This Points to this instance of EFI_HASH_PROTOCOL. + @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + @param[out] HashSize Holds the returned size of the algorithm's hash. + + @retval EFI_SUCCESS Hash size returned successfully. + @retval EFI_INVALID_PARAMETER HashSize is NULL or HashAlgorithm is NULL. + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported + by this driver. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH_GET_HASH_SIZE)( + IN CONST EFI_HASH_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + OUT UINTN *HashSize + ); + +/** + Creates a hash for the specified message text. + + @param[in] This Points to this instance of EFI_HASH_PROTOCOL. + @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + @param[in] Extend Specifies whether to create a new hash (FALSE) or extend the specified + existing hash (TRUE). + @param[in] Message Points to the start of the message. + @param[in] MessageSize The size of Message, in bytes. + @param[in,out] Hash On input, if Extend is TRUE, then this parameter holds a pointer + to a pointer to an array containing the hash to extend. If Extend + is FALSE, then this parameter holds a pointer to a pointer to a + caller-allocated array that will receive the result of the hash + computation. On output (regardless of the value of Extend), the + array will contain the result of the hash computation. + + @retval EFI_SUCCESS Hash returned successfully. + @retval EFI_INVALID_PARAMETER Message or Hash, HashAlgorithm is NULL or MessageSize is 0. + MessageSize is not an integer multiple of block size. + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this + driver. Or, Extend is TRUE, and the algorithm doesn't support extending the hash. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH_HASH)( + IN CONST EFI_HASH_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + IN BOOLEAN Extend, + IN CONST UINT8 *Message, + IN UINT64 MessageSize, + IN OUT EFI_HASH_OUTPUT *Hash + ); + +/// +/// This protocol allows creating a hash of an arbitrary message digest +/// using one or more hash algorithms. +/// +struct _EFI_HASH_PROTOCOL { + EFI_HASH_GET_HASH_SIZE GetHashSize; + EFI_HASH_HASH Hash; +}; + +extern EFI_GUID gEfiHashServiceBindingProtocolGuid; +extern EFI_GUID gEfiHashProtocolGuid; +extern EFI_GUID gEfiHashAlgorithmSha1Guid; +extern EFI_GUID gEfiHashAlgorithmSha224Guid; +extern EFI_GUID gEfiHashAlgorithmSha256Guid; +extern EFI_GUID gEfiHashAlgorithmSha384Guid; +extern EFI_GUID gEfiHashAlgorithmSha512Guid; +extern EFI_GUID gEfiHashAlgorithmMD5Guid; +extern EFI_GUID gEfiHashAlgorithmSha1NoPadGuid; +extern EFI_GUID gEfiHashAlgorithmSha256NoPadGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash2.h new file mode 100644 index 0000000..d049e8f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Hash2.h @@ -0,0 +1,202 @@ +/** @file + EFI_HASH2_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.5. + EFI_HASH2_PROTOCOL as defined in UEFI 2.5. + The EFI Hash2 Service Binding Protocol is used to locate hashing services support + provided by a driver and to create and destroy instances of the EFI Hash2 Protocol + so that a multiple drivers can use the underlying hashing services. + EFI_HASH2_PROTOCOL describes hashing functions for which the algorithm-required + message padding and finalization are performed by the supporting driver. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_HASH2_PROTOCOL_H__ +#define __EFI_HASH2_PROTOCOL_H__ + +#define EFI_HASH2_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xda836f8d, 0x217f, 0x4ca0, { 0x99, 0xc2, 0x1c, 0xa4, 0xe1, 0x60, 0x77, 0xea } \ + } + +#define EFI_HASH2_PROTOCOL_GUID \ + { \ + 0x55b1d734, 0xc5e1, 0x49db, { 0x96, 0x47, 0xb1, 0x6a, 0xfb, 0xe, 0x30, 0x5b } \ + } + +#include + +// +// NOTE: +// Algorithms EFI_HASH_ALGORITHM_SHA1_NOPAD and +// EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID are not compatible with +// EFI_HASH2_PROTOCOL and will return EFI_UNSUPPORTED if used with any +// EFI_HASH2_PROTOCOL function. +// + +// +// Note: SHA-1 and MD5 are included for backwards compatibility. +// New driver implementations are encouraged to consider stronger algorithms. +// + +typedef struct _EFI_HASH2_PROTOCOL EFI_HASH2_PROTOCOL; + +typedef UINT8 EFI_MD5_HASH2[16]; +typedef UINT8 EFI_SHA1_HASH2[20]; +typedef UINT8 EFI_SHA224_HASH2[28]; +typedef UINT8 EFI_SHA256_HASH2[32]; +typedef UINT8 EFI_SHA384_HASH2[48]; +typedef UINT8 EFI_SHA512_HASH2[64]; + +typedef union { + EFI_MD5_HASH2 Md5Hash; + EFI_SHA1_HASH2 Sha1Hash; + EFI_SHA224_HASH2 Sha224Hash; + EFI_SHA256_HASH2 Sha256Hash; + EFI_SHA384_HASH2 Sha384Hash; + EFI_SHA512_HASH2 Sha512Hash; +} EFI_HASH2_OUTPUT; + +/** + Returns the size of the hash which results from a specific algorithm. + + @param[in] This Points to this instance of EFI_HASH2_PROTOCOL. + @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + @param[out] HashSize Holds the returned size of the algorithm's hash. + + @retval EFI_SUCCESS Hash size returned successfully. + @retval EFI_INVALID_PARAMETER This or HashSize is NULL. + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver + or HashAlgorithm is null. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH2_GET_HASH_SIZE)( + IN CONST EFI_HASH2_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + OUT UINTN *HashSize + ); + +/** + Creates a hash for the specified message text. The hash is not extendable. + The output is final with any algorithm-required padding added by the function. + + @param[in] This Points to this instance of EFI_HASH2_PROTOCOL. + @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + @param[in] Message Points to the start of the message. + @param[in] MessageSize The size of Message, in bytes. + @param[in,out] Hash On input, points to a caller-allocated buffer of the size + returned by GetHashSize() for the specified HashAlgorithm. + On output, the buffer holds the resulting hash computed from the message. + + @retval EFI_SUCCESS Hash returned successfully. + @retval EFI_INVALID_PARAMETER This or Hash is NULL. + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver + or HashAlgorithm is Null. + @retval EFI_OUT_OF_RESOURCES Some resource required by the function is not available + or MessageSize is greater than platform maximum. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH2_HASH)( + IN CONST EFI_HASH2_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + IN CONST UINT8 *Message, + IN UINTN MessageSize, + IN OUT EFI_HASH2_OUTPUT *Hash + ); + +/** + This function must be called to initialize a digest calculation to be subsequently performed using the + EFI_HASH2_PROTOCOL functions HashUpdate() and HashFinal(). + + @param[in] This Points to this instance of EFI_HASH2_PROTOCOL. + @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + + @retval EFI_SUCCESS Initialized successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this driver + or HashAlgorithm is Null. + @retval EFI_OUT_OF_RESOURCES Process failed due to lack of required resource. + @retval EFI_ALREADY_STARTED This function is called when the operation in progress is still in processing Hash(), + or HashInit() is already called before and not terminated by HashFinal() yet on the same instance. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH2_HASH_INIT)( + IN CONST EFI_HASH2_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm + ); + +/** + Updates the hash of a computation in progress by adding a message text. + + @param[in] This Points to this instance of EFI_HASH2_PROTOCOL. + @param[in] Message Points to the start of the message. + @param[in] MessageSize The size of Message, in bytes. + + @retval EFI_SUCCESS Digest in progress updated successfully. + @retval EFI_INVALID_PARAMETER This or Hash is NULL. + @retval EFI_OUT_OF_RESOURCES Some resource required by the function is not available + or MessageSize is greater than platform maximum. + @retval EFI_NOT_READY This call was not preceded by a valid call to HashInit(), + or the operation in progress was terminated by a call to Hash() or HashFinal() on the same instance. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH2_HASH_UPDATE)( + IN CONST EFI_HASH2_PROTOCOL *This, + IN CONST UINT8 *Message, + IN UINTN MessageSize + ); + +/** + Finalizes a hash operation in progress and returns calculation result. + The output is final with any necessary padding added by the function. + The hash may not be further updated or extended after HashFinal(). + + @param[in] This Points to this instance of EFI_HASH2_PROTOCOL. + @param[in,out] Hash On input, points to a caller-allocated buffer of the size + returned by GetHashSize() for the specified HashAlgorithm specified in preceding HashInit(). + On output, the buffer holds the resulting hash computed from the message. + + @retval EFI_SUCCESS Hash returned successfully. + @retval EFI_INVALID_PARAMETER This or Hash is NULL. + @retval EFI_NOT_READY This call was not preceded by a valid call to HashInit() and at least one call to HashUpdate(), + or the operation in progress was canceled by a call to Hash() on the same instance. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH2_HASH_FINAL)( + IN CONST EFI_HASH2_PROTOCOL *This, + IN OUT EFI_HASH2_OUTPUT *Hash + ); + +/// +/// This protocol describes hashing functions for which the algorithm-required message padding and +/// finalization are performed by the supporting driver. +/// +struct _EFI_HASH2_PROTOCOL { + EFI_HASH2_GET_HASH_SIZE GetHashSize; + EFI_HASH2_HASH Hash; + EFI_HASH2_HASH_INIT HashInit; + EFI_HASH2_HASH_UPDATE HashUpdate; + EFI_HASH2_HASH_FINAL HashFinal; +}; + +extern EFI_GUID gEfiHash2ServiceBindingProtocolGuid; +extern EFI_GUID gEfiHash2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigAccess.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigAccess.h new file mode 100644 index 0000000..fd861e0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigAccess.h @@ -0,0 +1,226 @@ +/** @file + + The EFI HII results processing protocol invokes this type of protocol + when it needs to forward results to a driver's configuration handler. + This protocol is published by drivers providing and requesting + configuration data from HII. It may only be invoked by HII. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.1. + +**/ + + +#ifndef __EFI_HII_CONFIG_ACCESS_H__ +#define __EFI_HII_CONFIG_ACCESS_H__ + +#include + +#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \ + { 0x330d4706, 0xf2a0, 0x4e4f, { 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85 } } + +typedef struct _EFI_HII_CONFIG_ACCESS_PROTOCOL EFI_HII_CONFIG_ACCESS_PROTOCOL; + +typedef UINTN EFI_BROWSER_ACTION; + +#define EFI_BROWSER_ACTION_CHANGING 0 +#define EFI_BROWSER_ACTION_CHANGED 1 +#define EFI_BROWSER_ACTION_RETRIEVE 2 +#define EFI_BROWSER_ACTION_FORM_OPEN 3 +#define EFI_BROWSER_ACTION_FORM_CLOSE 4 +#define EFI_BROWSER_ACTION_SUBMITTED 5 +#define EFI_BROWSER_ACTION_DEFAULT_STANDARD 0x1000 +#define EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING 0x1001 +#define EFI_BROWSER_ACTION_DEFAULT_SAFE 0x1002 +#define EFI_BROWSER_ACTION_DEFAULT_PLATFORM 0x2000 +#define EFI_BROWSER_ACTION_DEFAULT_HARDWARE 0x3000 +#define EFI_BROWSER_ACTION_DEFAULT_FIRMWARE 0x4000 + +/** + + This function allows the caller to request the current + configuration for one or more named elements. The resulting + string is in format. Any and all alternative + configuration strings shall also be appended to the end of the + current configuration string. If they are, they must appear + after the current configuration. They must contain the same + routing (GUID, NAME, PATH) as the current configuration string. + They must have an additional description indicating the type of + alternative configuration the string represents, + "ALTCFG=". That (when + converted from Hex UNICODE to binary) is a reference to a + string in the associated string pack. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + + @param Request A null-terminated Unicode string in + format. Note that this + includes the routing information as well as + the configurable name / value pairs. It is + invalid for this string to be in + format. + If a NULL is passed in for the Request field, + all of the settings being abstracted by this function + will be returned in the Results field. In addition, + if a ConfigHdr is passed in with no request elements, + all of the settings being abstracted for that particular + ConfigHdr reference will be returned in the Results Field. + + @param Progress On return, points to a character in the + Request string. Points to the string's null + terminator if request was successful. Points + to the most recent "&" before the first + failing name / value pair (or the beginning + of the string if the failure is in the first + name / value pair) if the request was not + successful. + + @param Results A null-terminated Unicode string in + format which has all values + filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results string is filled with the + values corresponding to all requested + names. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + + @retval EFI_NOT_FOUND A configuration element matching + the routing data is not found. + Progress set to the first character + in the routing header. + + @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set + to most recent "&" before the + error or the beginning of the + string. + + @retval EFI_INVALID_PARAMETER Unknown name. Progress points + to the & before the name in + question. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_ACCESS_EXTRACT_CONFIG)( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +); + + +/** + + This function applies changes in a driver's configuration. + Input is a Configuration, which has the routing data for this + driver followed by name / value configuration pairs. The driver + must apply those pairs to its configurable storage. If the + driver's configuration is stored in a linear block of data + and the driver's name / value pairs are in + format, it may use the ConfigToBlock helper function (above) to + simplify the job. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + + @param Configuration A null-terminated Unicode string in + format. + + @param Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginn ing of the string if the failure + is in the first name / value pair) or + the terminating NULL if all was + successful. + + @retval EFI_SUCCESS The results have been distributed or are + awaiting distribution. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + Results parameter would result + in this type of error. + + @retval EFI_NOT_FOUND Target for the specified routing data + was not found + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_ACCESS_ROUTE_CONFIG)( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +); + +/** + + This function is called to provide results data to the driver. + This data consists of a unique key that is used to identify + which data is either being passed back or being asked for. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. The format of the data tends to + vary based on the opcode that generated the callback. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_ACCESS_FORM_CALLBACK)( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) + ; + +/// +/// This protocol provides a callable interface between the HII and +/// drivers. Only drivers which provide IFR data to HII are required +/// to publish this protocol. +/// +struct _EFI_HII_CONFIG_ACCESS_PROTOCOL { + EFI_HII_ACCESS_EXTRACT_CONFIG ExtractConfig; + EFI_HII_ACCESS_ROUTE_CONFIG RouteConfig; + EFI_HII_ACCESS_FORM_CALLBACK Callback; +} ; + +extern EFI_GUID gEfiHiiConfigAccessProtocolGuid; + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigKeyword.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigKeyword.h new file mode 100644 index 0000000..5ad9392 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigKeyword.h @@ -0,0 +1,205 @@ +/** @file + The file provides the mechanism to set and get the values + associated with a keyword exposed through a x-UEFI- prefixed + configuration language namespace. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.5. + + +**/ + +#ifndef __EFI_CONFIG_KEYWORD_HANDLER_H__ +#define __EFI_CONFIG_KEYWORD_HANDLER_H__ + +#define EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL_GUID \ +{ \ + 0x0a8badd5, 0x03b8, 0x4d19, {0xb1, 0x28, 0x7b, 0x8f, 0x0e, 0xda, 0xa5, 0x96 } \ +} + +//*********************************************************** +// Progress Errors +//*********************************************************** +#define KEYWORD_HANDLER_NO_ERROR 0x00000000 +#define KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND 0x00000001 +#define KEYWORD_HANDLER_MALFORMED_STRING 0x00000002 +#define KEYWORD_HANDLER_KEYWORD_NOT_FOUND 0x00000004 +#define KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED 0x00000008 +#define KEYWORD_HANDLER_ACCESS_NOT_PERMITTED 0x00000010 +#define KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR 0x80000000 + +typedef struct _EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL; + +/** + + This function accepts a formatted string, finds the associated + keyword owners, creates a string from it and forwards it to the + EFI_HII_ROUTING_PROTOCOL.RouteConfig function. + + If there is an issue in resolving the contents of the KeywordString, then the + function returns an error and also sets the Progress and ProgressErr with the + appropriate information about where the issue occurred and additional data about + the nature of the issue. + + In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND + error is generated during processing the second or later keyword element, the system + storage associated with earlier keywords is not modified. All elements of the + KeywordString must successfully pass all tests for format and access prior to making + any modifications to storage. + + In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString + containing multiple keywords, the state of storage associated with earlier keywords + is undefined. + + + @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance. + + @param KeywordString A null-terminated string in format. + + @param Progress On return, points to a character in the KeywordString. + Points to the string's NULL terminator if the request + was successful. Points to the most recent '&' before + the first failing name / value pair (or the beginning + of the string if the failure is in the first name / value + pair) if the request was not successful. + + @param ProgressErr If during the processing of the KeywordString there was + a failure, this parameter gives additional information + about the possible source of the problem. The various + errors are defined in "Related Definitions" below. + + + @retval EFI_SUCCESS The specified action was completed successfully. + + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + 1. KeywordString is NULL. + 2. Parsing of the KeywordString resulted in an + error. See Progress and ProgressErr for more data. + + @retval EFI_NOT_FOUND An element of the KeywordString was not found. + See ProgressErr for more data. + + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + See ProgressErr for more data. + + @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr + for more data. + + @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr + for more data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONFIG_KEYWORD_HANDLER_SET_DATA) ( + IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This, + IN CONST EFI_STRING KeywordString, + OUT EFI_STRING *Progress, + OUT UINT32 *ProgressErr + ); + + +/** + + This function accepts a formatted string, finds the underlying + keyword owners, creates a string from it and forwards it to the + EFI_HII_ROUTING_PROTOCOL.ExtractConfig function. + + If there is an issue in resolving the contents of the KeywordString, then the function + returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the + appropriate information about where the issue occurred and additional data about the + nature of the issue. + + In the case when KeywordString is NULL, or contains multiple keywords, or when + EFI_NOT_FOUND is generated while processing the keyword elements, the Results string + contains values returned for all keywords processed prior to the keyword generating the + error but no values for the keyword with error or any following keywords. + + + @param This Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance. + + @param NameSpaceId A null-terminated string containing the platform configuration + language to search through in the system. If a NULL is passed + in, then it is assumed that any platform configuration language + with the prefix of "x-UEFI-" are searched. + + @param KeywordString A null-terminated string in format. If a + NULL is passed in the KeywordString field, all of the known + keywords in the system for the NameSpaceId specified are + returned in the Results field. + + @param Progress On return, points to a character in the KeywordString. Points + to the string's NULL terminator if the request was successful. + Points to the most recent '&' before the first failing name / value + pair (or the beginning of the string if the failure is in the first + name / value pair) if the request was not successful. + + @param ProgressErr If during the processing of the KeywordString there was a + failure, this parameter gives additional information about the + possible source of the problem. See the definitions in SetData() + for valid value definitions. + + @param Results A null-terminated string in format is returned + which has all the values filled in for the keywords in the + KeywordString. This is a callee-allocated field, and must be freed + by the caller after being used. + + @retval EFI_SUCCESS The specified action was completed successfully. + + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + 1.Progress, ProgressErr, or Results is NULL. + 2.Parsing of the KeywordString resulted in an error. See + Progress and ProgressErr for more data. + + + @retval EFI_NOT_FOUND An element of the KeywordString was not found. See + ProgressErr for more data. + + @retval EFI_NOT_FOUND The NamespaceId specified was not found. See ProgressErr + for more data. + + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. See + ProgressErr for more data. + + @retval EFI_ACCESS_DENIED The action violated system policy. See ProgressErr for + more data. + + @retval EFI_DEVICE_ERROR An unexpected system error occurred. See ProgressErr + for more data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONFIG_KEYWORD_HANDLER_GET_DATA) ( + IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This, + IN CONST EFI_STRING NameSpaceId, OPTIONAL + IN CONST EFI_STRING KeywordString, OPTIONAL + OUT EFI_STRING *Progress, + OUT UINT32 *ProgressErr, + OUT EFI_STRING *Results + ); + +/// +/// The EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL provides the mechanism +/// to set and get the values associated with a keyword exposed +/// through a x-UEFI- prefixed configuration language namespace +/// + +struct _EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL { + EFI_CONFIG_KEYWORD_HANDLER_SET_DATA SetData; + EFI_CONFIG_KEYWORD_HANDLER_GET_DATA GetData; +}; + +extern EFI_GUID gEfiConfigKeywordHandlerProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigRouting.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigRouting.h new file mode 100644 index 0000000..2270015 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiConfigRouting.h @@ -0,0 +1,423 @@ +/** @file + The file provides services to manage the movement of + configuration data from drivers to configuration applications. + It then serves as the single point to receive configuration + information from configuration applications, routing the + results to the appropriate drivers. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.1. + + +**/ + +#ifndef __HII_CONFIG_ROUTING_H__ +#define __HII_CONFIG_ROUTING_H__ + +#define EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID \ + { 0x587e72d7, 0xcc50, 0x4f79, { 0x82, 0x09, 0xca, 0x29, 0x1f, 0xc1, 0xa1, 0x0f } } + + +typedef struct _EFI_HII_CONFIG_ROUTING_PROTOCOL EFI_HII_CONFIG_ROUTING_PROTOCOL; + +/** + + This function allows the caller to request the current + configuration for one or more named elements from one or more + drivers. The resulting string is in the standard HII + configuration string format. If Successful, Results contains an + equivalent string with "=" and the values associated with all + names added in. The expected implementation is for each + substring in the Request to call the HII + Configuration Routing Protocol ExtractProtocol function for the + driver corresponding to the at the start of the + substring. The request fails if no driver + matches the substring. Note: Alternative + configuration strings may also be appended to the end of the + current configuration string. If they are, they must appear + after the current configuration. They must contain the same + routing (GUID, NAME, PATH) as the current configuration string. + They must have an additional description indicating the type of + alternative configuration the string represents, + "ALTCFG=". That (when converted from + hexadecimal (encoded as text) to binary) is a reference to a string in the + associated string pack. As an example, assume that the Request + string is: + GUID=...&NAME=00480050&PATH=...&Fred&George&Ron&Neville A result + might be: + GUID=...&NAME=00480050&PATH=...&Fred=16&George=16&Ron=12&Neville=11& + GUID=...&NAME=00480050&PATH=...&ALTCFG=0037&Fred=12&Neville=7 + + @param This Points to the EFI_HII_CONFIG_ROUTING_PROTOCOL + instance. + + @param Request A null-terminated string in format. + + @param Progress On return, points to a character in the + Request string. Points to the string's null + terminator if the request was successful. Points + to the most recent '&' before the first + failing name / value pair (or the beginning + of the string if the failure is in the first + name / value pair) if the request was not + successful + + @param Results A null-terminated string in format + which has all values filled in for the names in the + Request string. + + @retval EFI_SUCCESS The Results string is filled with the + values corresponding to all requested + names. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + + @retval EFI_INVALID_PARAMETER For example, passing in a NULL + for the Request parameter + would result in this type of + error. The Progress parameter + is set to NULL. + + @retval EFI_NOT_FOUND Routing data doesn't match any + known driver. Progress set to + the "G" in "GUID" of the + routing header that doesn't + match. Note: There is no + requirement that all routing + data be validated before any + configuration extraction. + + @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set + to the most recent & before the + error, or the beginning of the + string. + @retval EFI_INVALID_PARAMETER The ExtractConfig function of the + underlying HII Configuration + Access Protocol returned + EFI_INVALID_PARAMETER. Progress + set to most recent & before the + error or the beginning of the + string. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_EXTRACT_CONFIG)( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +); + +/** + This function allows the caller to request the current configuration + for the entirety of the current HII database and returns the data in + a null-terminated string. + + This function allows the caller to request the current + configuration for all of the current HII database. The results + include both the current and alternate configurations as + described in ExtractConfig() above. + + @param This Points to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. + + @param Results Null-terminated Unicode string in + format which has all values + filled in for the entirety of the current HII + database. String to be allocated by the called + function. De-allocation is up to the caller. + + @retval EFI_SUCCESS The Results string is filled with the + values corresponding to all requested + names. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + + @retval EFI_INVALID_PARAMETERS For example, passing in a NULL + for the Results parameter + would result in this type of + error. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_EXPORT_CONFIG)( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + OUT EFI_STRING *Results +); + +/** + + This function routes the results of processing forms to the + appropriate targets. It scans for within the string + and passes the header and subsequent body to the driver whose + location is described in the . Many s may + appear as a single request. The expected implementation is to + hand off the various substrings to the + Configuration Access Protocol RouteConfig routine corresponding + to the driver whose routing information is defined by the + in turn. + + @param This Points to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. + + @param Configuration A null-terminated string in format. + + @param Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginning of the string if the failure is in + the first name / value pair), or the + terminating NULL if all was successful. + + @retval EFI_SUCCESS The results have been distributed or are + awaiting distribution. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the + parts of the results that must be + stored awaiting possible future + protocols. + + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + Results parameter would result + in this type of error. + + @retval EFI_NOT_FOUND The target for the specified routing data + was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_ROUTE_CONFIG)( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +); + + +/** + + This function extracts the current configuration from a block of + bytes. To do so, it requires that the ConfigRequest string + consists of a list of formatted names. It uses the + offset in the name to determine the index into the Block to + start the extraction and the width of each name to determine the + number of bytes to extract. These are mapped to a string + using the equivalent of the C "%x" format (with optional leading + spaces). The call fails if, for any (offset, width) pair in + ConfigRequest, offset+value >= BlockSize. + + @param This Points to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. + + @param ConfigRequest A null-terminated string in format. + + @param Block An array of bytes defining the block's + configuration. + + @param BlockSize The length in bytes of Block. + + @param Config The filled-in configuration string. String + allocated by the function. Returned only if + call is successful. The null-terminated string + will be format. + + @param Progress A pointer to a string filled in with the + offset of the most recent '&' before the + first failing name / value pair (or the + beginning of the string if the failure is in + the first name / value pair), or the + terminating NULL if all was successful. + + @retval EFI_SUCCESS The request succeeded. Progress points + to the null terminator at the end of the + ConfigRequest string. + + @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate + Config. Progress points to the + first character of ConfigRequest. + + @retval EFI_INVALID_PARAMETERS Passing in a NULL for the + ConfigRequest or Block + parameter would result in this + type of error. Progress points + to the first character of + ConfigRequest. + + @retval EFI_NOT_FOUND The target for the specified routing data + was not found. Progress points to the + 'G' in "GUID" of the errant routing + data. + @retval EFI_DEVICE_ERROR The block is not large enough. Progress undefined. + + @retval EFI_INVALID_PARAMETER Encountered non + formatted string. Block is + left updated and Progress + points at the '&' preceding + the first non-. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_BLOCK_TO_CONFIG)( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigRequest, + IN CONST UINT8 *Block, + IN CONST UINTN BlockSize, + OUT EFI_STRING *Config, + OUT EFI_STRING *Progress +); + + + +/** + This function maps a configuration containing a series of + formatted name value pairs in ConfigResp into a + Block so it may be stored in a linear mapped storage such as a + UEFI Variable. If present, the function skips GUID, NAME, and + PATH in . It stops when it finds a non- + name / value pair (after skipping the routing header) or when it + reaches the end of the string. + Example Assume an existing block containing: 00 01 02 03 04 05 + And the ConfigResp string is: + OFFSET=4&WIDTH=1&VALUE=7&OFFSET=0&WIDTH=2&VALUE=AA55 + The results are + 55 AA 02 07 04 05 + + @param This Points to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. + + @param ConfigResp A null-terminated string in format. + + @param Block A possibly null array of bytes + representing the current block. Only + bytes referenced in the ConfigResp + string in the block are modified. If + this parameter is null or if the + BlockLength parameter is (on input) + shorter than required by the + Configuration string, only the BlockSize + parameter is updated, and an appropriate + status (see below) is returned. + + @param BlockSize The length of the Block in units of UINT8. + On input, this is the size of the Block. On + output, if successful, contains the largest + index of the modified byte in the Block, or + the required buffer size if the Block is not + large enough. + + @param Progress On return, points to an element of the + ConfigResp string filled in with the offset + of the most recent "&" before the first + failing name / value pair (or the beginning + of the string if the failure is in the first + name / value pair), or the terminating NULL + if all was successful. + + @retval EFI_SUCCESS The request succeeded. Progress points to the null + terminator at the end of the ConfigResp string. + @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate Config. Progress + points to the first character of ConfigResp. + @retval EFI_INVALID_PARAMETER Passing in a NULL for the ConfigResp or + Block parameter would result in this type of + error. Progress points to the first character of + ConfigResp. + @retval EFI_INVALID_PARAMETER Encountered non formatted name / + value pair. Block is left updated and + Progress points at the '&' preceding the first + non-. + @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined. + @retval EFI_NOT_FOUND Target for the specified routing data was not found. + Progress points to the "G" in "GUID" of the errant + routing data. + @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined. + BlockSize is updated with the required buffer size. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_CONFIG_TO_BLOCK)( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigResp, + IN OUT UINT8 *Block, + IN OUT UINTN *BlockSize, + OUT EFI_STRING *Progress +); + +/** + This helper function is to be called by drivers to extract portions of + a larger configuration string. + + @param This A pointer to the EFI_HII_CONFIG_ROUTING_PROTOCOL instance. + @param ConfigResp A null-terminated string in format. + @param Guid A pointer to the GUID value to search for in the + routing portion of the ConfigResp string when retrieving + the requested data. If Guid is NULL, then all GUID + values will be searched for. + @param Name A pointer to the NAME value to search for in the + routing portion of the ConfigResp string when retrieving + the requested data. If Name is NULL, then all Name + values will be searched for. + @param DevicePath A pointer to the PATH value to search for in the + routing portion of the ConfigResp string when retrieving + the requested data. If DevicePath is NULL, then all + DevicePath values will be searched for. + @param AltCfgId A pointer to the ALTCFG value to search for in the + routing portion of the ConfigResp string when retrieving + the requested data. If this parameter is NULL, + then the current setting will be retrieved. + @param AltCfgResp A pointer to a buffer which will be allocated by the + function which contains the retrieved string as requested. + This buffer is only allocated if the call was successful. + The null-terminated string will be format. + + @retval EFI_SUCCESS The request succeeded. The requested data was extracted + and placed in the newly allocated AltCfgResp buffer. + @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate AltCfgResp. + @retval EFI_INVALID_PARAMETER Any parameter is invalid. + @retval EFI_NOT_FOUND The target for the specified routing data was not found. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_GET_ALT_CFG)( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigResp, + IN CONST EFI_GUID *Guid, + IN CONST EFI_STRING Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST UINT16 *AltCfgId, + OUT EFI_STRING *AltCfgResp + ); + +/// +/// This protocol defines the configuration routing interfaces +/// between external applications and the HII. There may only be one +/// instance of this protocol in the system. +/// +struct _EFI_HII_CONFIG_ROUTING_PROTOCOL { + EFI_HII_EXTRACT_CONFIG ExtractConfig; + EFI_HII_EXPORT_CONFIG ExportConfig; + EFI_HII_ROUTE_CONFIG RouteConfig; + EFI_HII_BLOCK_TO_CONFIG BlockToConfig; + EFI_HII_CONFIG_TO_BLOCK ConfigToBlock; + EFI_HII_GET_ALT_CFG GetAltConfig; +}; + +extern EFI_GUID gEfiHiiConfigRoutingProtocolGuid; + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiDatabase.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiDatabase.h new file mode 100644 index 0000000..db90a69 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiDatabase.h @@ -0,0 +1,534 @@ +/** @file + The file provides Database manager for HII-related data + structures. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.1. + +**/ + +#ifndef __HII_DATABASE_H__ +#define __HII_DATABASE_H__ + +#define EFI_HII_DATABASE_PROTOCOL_GUID \ + { 0xef9fc172, 0xa1b2, 0x4693, { 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42 } } + + +typedef struct _EFI_HII_DATABASE_PROTOCOL EFI_HII_DATABASE_PROTOCOL; + + +/// +/// EFI_HII_DATABASE_NOTIFY_TYPE. +/// +typedef UINTN EFI_HII_DATABASE_NOTIFY_TYPE; + +#define EFI_HII_DATABASE_NOTIFY_NEW_PACK 0x00000001 +#define EFI_HII_DATABASE_NOTIFY_REMOVE_PACK 0x00000002 +#define EFI_HII_DATABASE_NOTIFY_EXPORT_PACK 0x00000004 +#define EFI_HII_DATABASE_NOTIFY_ADD_PACK 0x00000008 +/** + + Functions which are registered to receive notification of + database events have this prototype. The actual event is encoded + in NotifyType. The following table describes how PackageType, + PackageGuid, Handle, and Package are used for each of the + notification types. + + @param PackageType Package type of the notification. + + @param PackageGuid If PackageType is + EFI_HII_PACKAGE_TYPE_GUID, then this is + the pointer to the GUID from the Guid + field of EFI_HII_PACKAGE_GUID_HEADER. + Otherwise, it must be NULL. + + @param Package Points to the package referred to by the notification. + + @param Handle The handle of the package + list which contains the specified package. + + @param NotifyType The type of change concerning the + database. See + EFI_HII_DATABASE_NOTIFY_TYPE. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_NOTIFY)( + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN CONST EFI_HII_PACKAGE_HEADER *Package, + IN EFI_HII_HANDLE Handle, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType +); + +/** + + This function adds the packages in the package list to the + database and returns a handle. If there is a + EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then + this function will create a package of type + EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list. For + each package in the package list, registered functions with the + notification type NEW_PACK and having the same package type will + be called. For each call to NewPackageList(), there should be a + corresponding call to + EFI_HII_DATABASE_PROTOCOL.RemovePackageList(). + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + @param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER structure. + + @param DriverHandle Associate the package list with this EFI handle. + If a NULL is specified, this data will not be associate + with any drivers and cannot have a callback induced. + + @param Handle A pointer to the EFI_HII_HANDLE instance. + + @retval EFI_SUCCESS The package list associated with the + Handle was added to the HII database. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary + resources for the new database + contents. + + @retval EFI_INVALID_PARAMETER PackageList is NULL, or Handle is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_NEW_PACK)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList, + IN EFI_HANDLE DriverHandle, OPTIONAL + OUT EFI_HII_HANDLE *Handle +); + + +/** + + This function removes the package list that is associated with a + handle Handle from the HII database. Before removing the + package, any registered functions with the notification type + REMOVE_PACK and the same package type will be called. For each + call to EFI_HII_DATABASE_PROTOCOL.NewPackageList(), there should + be a corresponding call to RemovePackageList. + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + @param Handle The handle that was registered to the data + that is requested for removal. + + @retval EFI_SUCCESS The data associated with the Handle was + removed from the HII database. + @retval EFI_NOT_FOUND The specified Handle is not in database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_REMOVE_PACK)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle +); + + +/** + + This function updates the existing package list (which has the + specified Handle) in the HII databases, using the new package + list specified by PackageList. The update process has the + following steps: Collect all the package types in the package + list specified by PackageList. A package type consists of the + Type field of EFI_HII_PACKAGE_HEADER and, if the Type is + EFI_HII_PACKAGE_TYPE_GUID, the Guid field, as defined in + EFI_HII_PACKAGE_GUID_HEADER. Iterate through the packages within + the existing package list in the HII database specified by + Handle. If a package's type matches one of the collected types collected + in step 1, then perform the following steps: + - Call any functions registered with the notification type + REMOVE_PACK. + - Remove the package from the package list and the HII + database. + Add all of the packages within the new package list specified + by PackageList, using the following steps: + - Add the package to the package list and the HII database. + - Call any functions registered with the notification type + ADD_PACK. + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + @param Handle The handle that was registered to the data + that is requested for removal. + + @param PackageList A pointer to an EFI_HII_PACKAGE_LIST + package. + + @retval EFI_SUCCESS The HII database was successfully updated. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory + for the updated database. + + @retval EFI_INVALID_PARAMETER PackageList was NULL. + @retval EFI_NOT_FOUND The specified Handle is not in database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_UPDATE_PACK)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList +); + + +/** + + This function returns a list of the package handles of the + specified type that are currently active in the database. The + pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package + handles to be listed. + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + @param PackageType Specifies the package type of the packages + to list or EFI_HII_PACKAGE_TYPE_ALL for + all packages to be listed. + + @param PackageGuid If PackageType is + EFI_HII_PACKAGE_TYPE_GUID, then this is + the pointer to the GUID which must match + the Guid field of + EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it + must be NULL. + + @param HandleBufferLength On input, a pointer to the length + of the handle buffer. On output, + the length of the handle buffer + that is required for the handles found. + + @param Handle An array of EFI_HII_HANDLE instances returned. + + @retval EFI_SUCCESS The matching handles are outputted successfully. + HandleBufferLength is updated with the actual length. + @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter + indicates that Handle is too + small to support the number of + handles. HandleBufferLength is + updated with a value that will + enable the data to fit. + @retval EFI_NOT_FOUND No matching handle could be found in database. + @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL. + @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not + zero and Handle was NULL. + @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but + PackageGuid is not NULL, PackageType is a EFI_HII_ + PACKAGE_TYPE_GUID but PackageGuid is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_LIST_PACKS)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle +); + +/** + + This function will export one or all package lists in the + database to a buffer. For each package list exported, this + function will call functions registered with EXPORT_PACK and + then copy the package list to the buffer. The registered + functions may call EFI_HII_DATABASE_PROTOCOL.UpdatePackageList() + to modify the package list before it is copied to the buffer. If + the specified BufferSize is too small, then the status + EFI_OUT_OF_RESOURCES will be returned and the actual package + size will be returned in BufferSize. + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + + @param Handle An EFI_HII_HANDLE that corresponds to the + desired package list in the HII database to + export or NULL to indicate all package lists + should be exported. + + @param BufferSize On input, a pointer to the length of the + buffer. On output, the length of the + buffer that is required for the exported + data. + + @param Buffer A pointer to a buffer that will contain the + results of the export function. + + + @retval EFI_SUCCESS Package exported. + + @retval EFI_OUT_OF_RESOURCES BufferSize is too small to hold the package. + + @retval EFI_NOT_FOUND The specified Handle could not be found in the + current database. + + @retval EFI_INVALID_PARAMETER BufferSize was NULL. + + @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero + and Buffer was NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_EXPORT_PACKS)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer +); + + +/** + + + This function registers a function which will be called when + specified actions related to packages of the specified type + occur in the HII database. By registering a function, other + HII-related drivers are notified when specific package types + are added, removed or updated in the HII database. Each driver + or application which registers a notification should use + EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before + exiting. + + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + @param PackageType The package type. See + EFI_HII_PACKAGE_TYPE_x in EFI_HII_PACKAGE_HEADER. + + @param PackageGuid If PackageType is + EFI_HII_PACKAGE_TYPE_GUID, then this is + the pointer to the GUID which must match + the Guid field of + EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it + must be NULL. + + @param PackageNotifyFn Points to the function to be called + when the event specified by + NotificationType occurs. See + EFI_HII_DATABASE_NOTIFY. + + @param NotifyType Describes the types of notification which + this function will be receiving. See + EFI_HII_DATABASE_NOTIFY_TYPE for a + list of types. + + @param NotifyHandle Points to the unique handle assigned to + the registered notification. Can be used + in EFI_HII_DATABASE_PROTOCOL.UnregisterPack + to stop notifications. + + + @retval EFI_SUCCESS Notification registered successfully. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary + data structures. + + @retval EFI_INVALID_PARAMETER PackageGuid is not NULL when + PackageType is not + EFI_HII_PACKAGE_TYPE_GUID. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_REGISTER_NOTIFY)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN EFI_HII_DATABASE_NOTIFY PackageNotifyFn, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType, + OUT EFI_HANDLE *NotifyHandle +); + + +/** + + Removes the specified HII database package-related notification. + + @param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + + @param NotificationHandle The handle of the notification + function being unregistered. + + @retval EFI_SUCCESS Successsfully unregistered the notification. + + @retval EFI_NOT_FOUND The incoming notification handle does not exist + in the current hii database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_UNREGISTER_NOTIFY)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + + +/** + + This routine retrieves an array of GUID values for each keyboard + layout that was previously registered in the system. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param KeyGuidBufferLength On input, a pointer to the length + of the keyboard GUID buffer. On + output, the length of the handle + buffer that is required for the + handles found. + + @param KeyGuidBuffer An array of keyboard layout GUID + instances returned. + + @retval EFI_SUCCESS KeyGuidBuffer was updated successfully. + + @retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength + parameter indicates that + KeyGuidBuffer is too small to + support the number of GUIDs. + KeyGuidBufferLength is updated + with a value that will enable + the data to fit. + @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL. + @retval EFI_INVALID_PARAMETER The value referenced by + KeyGuidBufferLength is not + zero and KeyGuidBuffer is NULL. + @retval EFI_NOT_FOUND There was no keyboard layout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_FIND_KEYBOARD_LAYOUTS)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN OUT UINT16 *KeyGuidBufferLength, + OUT EFI_GUID *KeyGuidBuffer +); + + +/** + + This routine retrieves the requested keyboard layout. The layout + is a physical description of the keys on a keyboard, and the + character(s) that are associated with a particular set of key + strokes. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param KeyGuid A pointer to the unique ID associated with a + given keyboard layout. If KeyGuid is NULL then + the current layout will be retrieved. + + @param KeyboardLayoutLength On input, a pointer to the length of the + KeyboardLayout buffer. On output, the length of + the data placed into KeyboardLayout. + + @param KeyboardLayout A pointer to a buffer containing the + retrieved keyboard layout. + + @retval EFI_SUCCESS The keyboard layout was retrieved + successfully. + + @retval EFI_NOT_FOUND The requested keyboard layout was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN CONST EFI_GUID *KeyGuid, + IN OUT UINT16 *KeyboardLayoutLength, + OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout +); + +/** + + This routine sets the default keyboard layout to the one + referenced by KeyGuid. When this routine is called, an event + will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID + group type. This is so that agents which are sensitive to the + current keyboard layout being changed can be notified of this + change. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param KeyGuid A pointer to the unique ID associated with a + given keyboard layout. + + @retval EFI_SUCCESS The current keyboard layout was successfully set. + + @retval EFI_NOT_FOUND The referenced keyboard layout was not + found, so action was taken. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_SET_KEYBOARD_LAYOUT)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN CONST EFI_GUID *KeyGuid +); + +/** + + Return the EFI handle associated with a package list. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param PackageListHandle An EFI_HII_HANDLE that corresponds + to the desired package list in the + HIIdatabase. + + @param DriverHandle On return, contains the EFI_HANDLE which + was registered with the package list in + NewPackageList(). + + @retval EFI_SUCCESS The DriverHandle was returned successfully. + + @retval EFI_INVALID_PARAMETER The PackageListHandle was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DATABASE_GET_PACK_HANDLE)( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE PackageListHandle, + OUT EFI_HANDLE *DriverHandle +); + +/// +/// Database manager for HII-related data structures. +/// +struct _EFI_HII_DATABASE_PROTOCOL { + EFI_HII_DATABASE_NEW_PACK NewPackageList; + EFI_HII_DATABASE_REMOVE_PACK RemovePackageList; + EFI_HII_DATABASE_UPDATE_PACK UpdatePackageList; + EFI_HII_DATABASE_LIST_PACKS ListPackageLists; + EFI_HII_DATABASE_EXPORT_PACKS ExportPackageLists; + EFI_HII_DATABASE_REGISTER_NOTIFY RegisterPackageNotify; + EFI_HII_DATABASE_UNREGISTER_NOTIFY UnregisterPackageNotify; + EFI_HII_FIND_KEYBOARD_LAYOUTS FindKeyboardLayouts; + EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout; + EFI_HII_SET_KEYBOARD_LAYOUT SetKeyboardLayout; + EFI_HII_DATABASE_GET_PACK_HANDLE GetPackageListHandle; +}; + +extern EFI_GUID gEfiHiiDatabaseProtocolGuid; + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiFont.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiFont.h new file mode 100644 index 0000000..9098185 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiFont.h @@ -0,0 +1,475 @@ +/** @file + The file provides services to retrieve font information. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.1. + +**/ + +#ifndef __HII_FONT_H__ +#define __HII_FONT_H__ + +#include +#include + +#define EFI_HII_FONT_PROTOCOL_GUID \ +{ 0xe9ca4775, 0x8657, 0x47fc, { 0x97, 0xe7, 0x7e, 0xd6, 0x5a, 0x8, 0x43, 0x24 } } + +typedef struct _EFI_HII_FONT_PROTOCOL EFI_HII_FONT_PROTOCOL; + +typedef VOID *EFI_FONT_HANDLE; + +/// +/// EFI_HII_OUT_FLAGS. +/// +typedef UINT32 EFI_HII_OUT_FLAGS; + +#define EFI_HII_OUT_FLAG_CLIP 0x00000001 +#define EFI_HII_OUT_FLAG_WRAP 0x00000002 +#define EFI_HII_OUT_FLAG_CLIP_CLEAN_Y 0x00000004 +#define EFI_HII_OUT_FLAG_CLIP_CLEAN_X 0x00000008 +#define EFI_HII_OUT_FLAG_TRANSPARENT 0x00000010 +#define EFI_HII_IGNORE_IF_NO_GLYPH 0x00000020 +#define EFI_HII_IGNORE_LINE_BREAK 0x00000040 +#define EFI_HII_DIRECT_TO_SCREEN 0x00000080 + +/** + Definition of EFI_HII_ROW_INFO. +**/ +typedef struct _EFI_HII_ROW_INFO { + /// + /// The index of the first character in the string which is displayed on the line. + /// + UINTN StartIndex; + /// + /// The index of the last character in the string which is displayed on the line. + /// If this is the same as StartIndex, then no characters are displayed. + /// + UINTN EndIndex; + UINTN LineHeight; ///< The height of the line, in pixels. + UINTN LineWidth; ///< The width of the text on the line, in pixels. + + /// + /// The font baseline offset in pixels from the bottom of the row, or 0 if none. + /// + UINTN BaselineOffset; +} EFI_HII_ROW_INFO; + +/// +/// Font info flag. All flags (FONT, SIZE, STYLE, and COLOR) are defined. +/// They are defined as EFI_FONT_INFO_*** +/// +typedef UINT32 EFI_FONT_INFO_MASK; + +#define EFI_FONT_INFO_SYS_FONT 0x00000001 +#define EFI_FONT_INFO_SYS_SIZE 0x00000002 +#define EFI_FONT_INFO_SYS_STYLE 0x00000004 +#define EFI_FONT_INFO_SYS_FORE_COLOR 0x00000010 +#define EFI_FONT_INFO_SYS_BACK_COLOR 0x00000020 +#define EFI_FONT_INFO_RESIZE 0x00001000 +#define EFI_FONT_INFO_RESTYLE 0x00002000 +#define EFI_FONT_INFO_ANY_FONT 0x00010000 +#define EFI_FONT_INFO_ANY_SIZE 0x00020000 +#define EFI_FONT_INFO_ANY_STYLE 0x00040000 + +// +// EFI_FONT_INFO +// +typedef struct { + EFI_HII_FONT_STYLE FontStyle; + UINT16 FontSize; ///< character cell height in pixels + CHAR16 FontName[1]; +} EFI_FONT_INFO; + +/** + Describes font output-related information. + + This structure is used for describing the way in which a string + should be rendered in a particular font. FontInfo specifies the + basic font information and ForegroundColor and BackgroundColor + specify the color in which they should be displayed. The flags + in FontInfoMask describe where the system default should be + supplied instead of the specified information. The flags also + describe what options can be used to make a match between the + font requested and the font available. +**/ +typedef struct _EFI_FONT_DISPLAY_INFO { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL ForegroundColor; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL BackgroundColor; + EFI_FONT_INFO_MASK FontInfoMask; + EFI_FONT_INFO FontInfo; +} EFI_FONT_DISPLAY_INFO; + +/** + + This function renders a string to a bitmap or the screen using + the specified font, color and options. It either draws the + string and glyphs on an existing bitmap, allocates a new bitmap, + or uses the screen. The strings can be clipped or wrapped. + Optionally, the function also returns the information about each + row and the character position on that row. If + EFI_HII_OUT_FLAG_CLIP is set, then text will be formatted only + based on explicit line breaks and all pixels which would lie + outside the bounding box specified by Width and Height are + ignored. The information in the RowInfoArray only describes + characters which are at least partially displayed. For the final + row, the LineHeight and BaseLine may describe pixels that are + outside the limit specified by Height (unless + EFI_HII_OUT_FLAG_CLIP_CLEAN_Y is specified) even though those + pixels were not drawn. The LineWidth may describe pixels which + are outside the limit specified by Width (unless + EFI_HII_OUT_FLAG_CLIP_CLEAN_X is specified) even though those + pixels were not drawn. If EFI_HII_OUT_FLAG_CLIP_CLEAN_X is set, + then it modifies the behavior of EFI_HII_OUT_FLAG_CLIP so that + if a character's right-most on pixel cannot fit, then it will + not be drawn at all. This flag requires that + EFI_HII_OUT_FLAG_CLIP be set. If EFI_HII_OUT_FLAG_CLIP_CLEAN_Y + is set, then it modifies the behavior of EFI_HII_OUT_FLAG_CLIP + so that if a row's bottom-most pixel cannot fit, then it will + not be drawn at all. This flag requires that + EFI_HII_OUT_FLAG_CLIP be set. If EFI_HII_OUT_FLAG_WRAP is set, + then text will be wrapped at the right-most line-break + opportunity prior to a character whose right-most extent would + exceed Width. If no line-break opportunity can be found, then + the text will behave as if EFI_HII_OUT_FLAG_CLIP_CLEAN_X is set. + This flag cannot be used with EFI_HII_OUT_FLAG_CLIP_CLEAN_X. If + EFI_HII_OUT_FLAG_TRANSPARENT is set, then BackgroundColor is + ignored and all 'off' pixels in the character's drawn + will use the pixel value from Blt. This flag cannot be used if + Blt is NULL upon entry. If EFI_HII_IGNORE_IF_NO_GLYPH is set, + then characters which have no glyphs are not drawn. Otherwise, + they are replaced with Unicode character code 0xFFFD (REPLACEMENT + CHARACTER). If EFI_HII_IGNORE_LINE_BREAK is set, then explicit + line break characters will be ignored. If + EFI_HII_DIRECT_TO_SCREEN is set, then the string will be written + directly to the output device specified by Screen. Otherwise the + string will be rendered to the bitmap specified by Bitmap. + + @param This A pointer to the EFI_HII_FONT_PROTOCOL instance. + + @param Flags Describes how the string is to be drawn. + + @param String Points to the null-terminated string to be + + @param StringInfo Points to the string output information, + including the color and font. If NULL, then + the string will be output in the default + system font and color. + + @param Blt If this points to a non-NULL on entry, this points + to the image, which is Width pixels wide and + Height pixels high. The string will be drawn onto + this image and EFI_HII_OUT_FLAG_CLIP is implied. + If this points to a NULL on entry, then a buffer + will be allocated to hold the generated image and + the pointer updated on exit. It is the caller's + responsibility to free this buffer. + + @param BltX, BltY Specifies the offset from the left and top + edge of the image of the first character + cell in the image. + + @param RowInfoArray If this is non-NULL on entry, then on + exit, this will point to an allocated buffer + containing row information and + RowInfoArraySize will be updated to contain + the number of elements. This array describes + the characters that were at least partially + drawn and the heights of the rows. It is the + caller's responsibility to free this buffer. + + @param RowInfoArraySize If this is non-NULL on entry, then on + exit it contains the number of + elements in RowInfoArray. + + @param ColumnInfoArray If this is non-NULL, then on return it + will be filled with the horizontal + offset for each character in the + string on the row where it is + displayed. Non-printing characters + will have the offset ~0. The caller is + responsible for allocating a buffer large + enough so that there is one entry for + each character in the string, not + including the null-terminator. It is + possible when character display is + normalized that some character cells + overlap. + + @retval EFI_SUCCESS The string was successfully updated. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for RowInfoArray or Blt. + + @retval EFI_INVALID_PARAMETER The String or Blt was NULL. + + @retval EFI_INVALID_PARAMETER Flags were invalid combination. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_STRING_TO_IMAGE)( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN EFI_HII_OUT_FLAGS Flags, + IN CONST EFI_STRING String, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY, + OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, + OUT UINTN *RowInfoArraySize OPTIONAL, + OUT UINTN *ColumnInfoArray OPTIONAL +); + + + +/** + + This function renders a string as a bitmap or to the screen + and can clip or wrap the string. The bitmap is either supplied + by the caller or allocated by the function. The + strings are drawn with the font, size and style specified and + can be drawn transparently or opaquely. The function can also + return information about each row and each character's + position on the row. If EFI_HII_OUT_FLAG_CLIP is set, then + text will be formatted based only on explicit line breaks, and + all pixels that would lie outside the bounding box specified + by Width and Height are ignored. The information in the + RowInfoArray only describes characters which are at least + partially displayed. For the final row, the LineHeight and + BaseLine may describe pixels which are outside the limit + specified by Height (unless EFI_HII_OUT_FLAG_CLIP_CLEAN_Y is + specified) even though those pixels were not drawn. If + EFI_HII_OUT_FLAG_CLIP_CLEAN_X is set, then it modifies the + behavior of EFI_HII_OUT_FLAG_CLIP so that if a character's + right-most on pixel cannot fit, then it will not be drawn at + all. This flag requires that EFI_HII_OUT_FLAG_CLIP be set. If + EFI_HII_OUT_FLAG_CLIP_CLEAN_Y is set, then it modifies the + behavior of EFI_HII_OUT_FLAG_CLIP so that if a row's bottom + most pixel cannot fit, then it will not be drawn at all. This + flag requires that EFI_HII_OUT_FLAG_CLIP be set. If + EFI_HII_OUT_FLAG_WRAP is set, then text will be wrapped at the + right-most line-break opportunity prior to a character whose + right-most extent would exceed Width. If no line-break + opportunity can be found, then the text will behave as if + EFI_HII_OUT_FLAG_CLIP_CLEAN_X is set. This flag cannot be used + with EFI_HII_OUT_FLAG_CLIP_CLEAN_X. If + EFI_HII_OUT_FLAG_TRANSPARENT is set, then BackgroundColor is + ignored and all off" pixels in the character's glyph will + use the pixel value from Blt. This flag cannot be used if Blt + is NULL upon entry. If EFI_HII_IGNORE_IF_NO_GLYPH is set, then + characters which have no glyphs are not drawn. Otherwise, they + are replaced with Unicode character code 0xFFFD (REPLACEMENT + CHARACTER). If EFI_HII_IGNORE_LINE_BREAK is set, then explicit + line break characters will be ignored. If + EFI_HII_DIRECT_TO_SCREEN is set, then the string will be + written directly to the output device specified by Screen. + Otherwise the string will be rendered to the bitmap specified + by Bitmap. + + + @param This A pointer to the EFI_HII_FONT_PROTOCOL instance. + + @param Flags Describes how the string is to be drawn. + + @param PackageList + The package list in the HII database to + search for the specified string. + + @param StringId The string's id, which is unique within + PackageList. + + @param Language Points to the language for the retrieved + string. If NULL, then the current system + language is used. + + @param StringInfo Points to the string output information, + including the color and font. If NULL, then + the string will be output in the default + system font and color. + + @param Blt If this points to a non-NULL on entry, this points + to the image, which is Width pixels wide and + Height pixels high. The string will be drawn onto + this image and EFI_HII_OUT_FLAG_CLIP is implied. + If this points to a NULL on entry, then a buffer + will be allocated to hold the generated image and + the pointer updated on exit. It is the caller's + responsibility to free this buffer. + + @param BltX, BltY Specifies the offset from the left and top + edge of the output image of the first + character cell in the image. + + @param RowInfoArray If this is non-NULL on entry, then on + exit, this will point to an allocated + buffer containing row information and + RowInfoArraySize will be updated to + contain the number of elements. This array + describes the characters which were at + least partially drawn and the heights of + the rows. It is the caller's + responsibility to free this buffer. + + @param RowInfoArraySize If this is non-NULL on entry, then on + exit it contains the number of + elements in RowInfoArray. + + @param ColumnInfoArray If non-NULL, on return it is filled + with the horizontal offset for each + character in the string on the row + where it is displayed. Non-printing + characters will have the offset ~0. + The caller is responsible to allocate + a buffer large enough so that there is + one entry for each character in the + string, not including the + null-terminator. It is possible when + character display is normalized that + some character cells overlap. + + + @retval EFI_SUCCESS The string was successfully updated. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate an output + buffer for RowInfoArray or Blt. + + @retval EFI_INVALID_PARAMETER The String, or Blt, or Height, or + Width was NULL. + @retval EFI_INVALID_PARAMETER The Blt or PackageList was NULL. + @retval EFI_INVALID_PARAMETER Flags were invalid combination. + @retval EFI_NOT_FOUND The specified PackageList is not in the Database, + or the stringid is not in the specified PackageList. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_STRING_ID_TO_IMAGE)( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN EFI_HII_OUT_FLAGS Flags, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST CHAR8 *Language, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY, + OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, + OUT UINTN *RowInfoArraySize OPTIONAL, + OUT UINTN *ColumnInfoArray OPTIONAL +); + + +/** + + Convert the glyph for a single character into a bitmap. + + @param This A pointer to the EFI_HII_FONT_PROTOCOL instance. + + @param Char The character to retrieve. + + @param StringInfo Points to the string font and color + information or NULL if the string should use + the default system font and color. + + @param Blt This must point to a NULL on entry. A buffer will + be allocated to hold the output and the pointer + updated on exit. It is the caller's responsibility + to free this buffer. + + @param Baseline The number of pixels from the bottom of the bitmap + to the baseline. + + + @retval EFI_SUCCESS The glyph bitmap created. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate the output buffer Blt. + + @retval EFI_WARN_UNKNOWN_GLYPH The glyph was unknown and was + replaced with the glyph for + Unicode character code 0xFFFD. + + @retval EFI_INVALID_PARAMETER Blt is NULL, or Width is NULL, or + Height is NULL + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_GLYPH)( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN CONST CHAR16 Char, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo, + OUT EFI_IMAGE_OUTPUT **Blt, + OUT UINTN *Baseline OPTIONAL +); + +/** + + This function iterates through fonts which match the specified + font, using the specified criteria. If String is non-NULL, then + all of the characters in the string must exist in order for a + candidate font to be returned. + + @param This A pointer to the EFI_HII_FONT_PROTOCOL instance. + + @param FontHandle On entry, points to the font handle returned + by a previous call to GetFontInfo() or NULL + to start with the first font. On return, + points to the returned font handle or points + to NULL if there are no more matching fonts. + + @param StringInfoIn Upon entry, points to the font to return + information about. If NULL, then the information + about the system default font will be returned. + + @param StringInfoOut Upon return, contains the matching font's information. + If NULL, then no information is returned. This buffer + is allocated with a call to the Boot Service AllocatePool(). + It is the caller's responsibility to call the Boot + Service FreePool() when the caller no longer requires + the contents of StringInfoOut. + + @param String Points to the string which will be tested to + determine if all characters are available. If + NULL, then any font is acceptable. + + @retval EFI_SUCCESS Matching font returned successfully. + + @retval EFI_NOT_FOUND No matching font was found. + + @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_FONT_INFO)( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN OUT EFI_FONT_HANDLE *FontHandle, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn, OPTIONAL + OUT EFI_FONT_DISPLAY_INFO **StringInfoOut, + IN CONST EFI_STRING String OPTIONAL +); + +/// +/// The protocol provides the service to retrieve the font informations. +/// +struct _EFI_HII_FONT_PROTOCOL { + EFI_HII_STRING_TO_IMAGE StringToImage; + EFI_HII_STRING_ID_TO_IMAGE StringIdToImage; + EFI_HII_GET_GLYPH GetGlyph; + EFI_HII_GET_FONT_INFO GetFontInfo; +}; + +extern EFI_GUID gEfiHiiFontProtocolGuid; + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImage.h new file mode 100644 index 0000000..b806c7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImage.h @@ -0,0 +1,359 @@ +/** @file + The file provides services to access to images in the images database. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.1. + +**/ + +#ifndef __HII_IMAGE_H__ +#define __HII_IMAGE_H__ + +#include + +#define EFI_HII_IMAGE_PROTOCOL_GUID \ + { 0x31a6406a, 0x6bdf, 0x4e46, { 0xb2, 0xa2, 0xeb, 0xaa, 0x89, 0xc4, 0x9, 0x20 } } + +typedef struct _EFI_HII_IMAGE_PROTOCOL EFI_HII_IMAGE_PROTOCOL; + + +/// +/// Flags in EFI_IMAGE_INPUT +/// +#define EFI_IMAGE_TRANSPARENT 0x00000001 + +/** + + Definition of EFI_IMAGE_INPUT. + + @param Flags Describe image characteristics. If + EFI_IMAGE_TRANSPARENT is set, then the image was + designed for transparent display. + + @param Width Image width, in pixels. + + @param Height Image height, in pixels. + + @param Bitmap A pointer to the actual bitmap, organized left-to-right, + top-to-bottom. The size of the bitmap is + Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). + + +**/ +typedef struct _EFI_IMAGE_INPUT { + UINT32 Flags; + UINT16 Width; + UINT16 Height; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Bitmap; +} EFI_IMAGE_INPUT; + + +/** + + This function adds the image Image to the group of images + owned by PackageList, and returns a new image identifier + (ImageId). + + @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance. + + @param PackageList Handle of the package list where this image will be added. + + @param ImageId On return, contains the new image id, which is + unique within PackageList. + + @param Image Points to the image. + + @retval EFI_SUCCESS The new image was added + successfully + + @retval EFI_OUT_OF_RESOURCES Could not add the image. + + @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is + NULL. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_IMAGE)( + IN CONST EFI_HII_IMAGE_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + OUT EFI_IMAGE_ID *ImageId, + IN CONST EFI_IMAGE_INPUT *Image +); + +/** + + This function retrieves the image specified by ImageId which + is associated with the specified PackageList and copies it + into the buffer specified by Image. If the image specified by + ImageId is not present in the specified PackageList, then + EFI_NOT_FOUND is returned. If the buffer specified by + ImageSize is too small to hold the image, then + EFI_BUFFER_TOO_SMALL will be returned. ImageSize will be + updated to the size of buffer actually required to hold the + image. + + @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance. + + @param PackageList The package list in the HII database to + search for the specified image. + + @param ImageId The image's id, which is unique within + PackageList. + + @param Image Points to the new image. + + @retval EFI_SUCCESS The image was returned successfully. + + @retval EFI_NOT_FOUND The image specified by ImageId is not + available. Or The specified PackageList is not in the database. + + @retval EFI_INVALID_PARAMETER The Image or Langugae was NULL. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not + enough memory. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_IMAGE)( + IN CONST EFI_HII_IMAGE_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + OUT EFI_IMAGE_INPUT *Image +); + +/** + + This function updates the image specified by ImageId in the + specified PackageListHandle to the image specified by Image. + + + @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance. + + @param PackageList The package list containing the images. + + @param ImageId The image id, which is unique within PackageList. + + @param Image Points to the image. + + @retval EFI_SUCCESS The image was successfully updated. + + @retval EFI_NOT_FOUND The image specified by ImageId is not in the database. + The specified PackageList is not in the database. + + @retval EFI_INVALID_PARAMETER The Image or Language was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_SET_IMAGE)( + IN CONST EFI_HII_IMAGE_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + IN CONST EFI_IMAGE_INPUT *Image +); + + +/// +/// EFI_HII_DRAW_FLAGS describes how the image is to be drawn. +/// These flags are defined as EFI_HII_DRAW_FLAG_*** +/// +typedef UINT32 EFI_HII_DRAW_FLAGS; + +#define EFI_HII_DRAW_FLAG_CLIP 0x00000001 +#define EFI_HII_DRAW_FLAG_TRANSPARENT 0x00000030 +#define EFI_HII_DRAW_FLAG_DEFAULT 0x00000000 +#define EFI_HII_DRAW_FLAG_FORCE_TRANS 0x00000010 +#define EFI_HII_DRAW_FLAG_FORCE_OPAQUE 0x00000020 +#define EFI_HII_DIRECT_TO_SCREEN 0x00000080 + +/** + + Definition of EFI_IMAGE_OUTPUT. + + @param Width Width of the output image. + + @param Height Height of the output image. + + @param Bitmap Points to the output bitmap. + + @param Screen Points to the EFI_GRAPHICS_OUTPUT_PROTOCOL which + describes the screen on which to draw the + specified image. + +**/ +typedef struct _EFI_IMAGE_OUTPUT { + UINT16 Width; + UINT16 Height; + union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Bitmap; + EFI_GRAPHICS_OUTPUT_PROTOCOL *Screen; + } Image; +} EFI_IMAGE_OUTPUT; + + +/** + + This function renders an image to a bitmap or the screen using + the specified color and options. It draws the image on an + existing bitmap, allocates a new bitmap or uses the screen. The + images can be clipped. If EFI_HII_DRAW_FLAG_CLIP is set, then + all pixels drawn outside the bounding box specified by Width and + Height are ignored. If EFI_HII_DRAW_FLAG_TRANSPARENT is set, + then all 'off' pixels in the images drawn will use the + pixel value from Blt. This flag cannot be used if Blt is NULL + upon entry. If EFI_HII_DIRECT_TO_SCREEN is set, then the image + will be written directly to the output device specified by + Screen. Otherwise the image will be rendered to the bitmap + specified by Bitmap. + + + @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance. + + @param Flags Describes how the image is to be drawn. + EFI_HII_DRAW_FLAGS is defined in Related + Definitions, below. + + @param Image Points to the image to be displayed. + + @param Blt If this points to a non-NULL on entry, this points + to the image, which is Width pixels wide and + Height pixels high. The image will be drawn onto + this image and EFI_HII_DRAW_FLAG_CLIP is implied. + If this points to a NULL on entry, then a buffer + will be allocated to hold the generated image and + the pointer updated on exit. It is the caller's + responsibility to free this buffer. + + @param BltX, BltY Specifies the offset from the left and top + edge of the image of the first pixel in + the image. + + @retval EFI_SUCCESS The image was successfully updated. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate an output + buffer for RowInfoArray or Blt. + + @retval EFI_INVALID_PARAMETER The Image or Blt or Height or + Width was NULL. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DRAW_IMAGE)( + IN CONST EFI_HII_IMAGE_PROTOCOL *This, + IN EFI_HII_DRAW_FLAGS Flags, + IN CONST EFI_IMAGE_INPUT *Image, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY +); + +/** + + This function renders an image as a bitmap or to the screen and + can clip the image. The bitmap is either supplied by the caller + or else is allocated by the function. The images can be drawn + transparently or opaquely. If EFI_HII_DRAW_FLAG_CLIP is set, + then all pixels drawn outside the bounding box specified by + Width and Height are ignored. If EFI_HII_DRAW_FLAG_TRANSPARENT + is set, then all "off" pixels in the character's glyph will + use the pixel value from Blt. This flag cannot be used if Blt + is NULL upon entry. If EFI_HII_DIRECT_TO_SCREEN is set, then + the image will be written directly to the output device + specified by Screen. Otherwise the image will be rendered to + the bitmap specified by Bitmap. + This function renders an image to a bitmap or the screen using + the specified color and options. It draws the image on an + existing bitmap, allocates a new bitmap or uses the screen. The + images can be clipped. If EFI_HII_DRAW_FLAG_CLIP is set, then + all pixels drawn outside the bounding box specified by Width and + Height are ignored. The EFI_HII_DRAW_FLAG_TRANSPARENT flag + determines whether the image will be drawn transparent or + opaque. If EFI_HII_DRAW_FLAG_FORCE_TRANS is set, then the image + will be drawn so that all 'off' pixels in the image will + be drawn using the pixel value from Blt and all other pixels + will be copied. If EFI_HII_DRAW_FLAG_FORCE_OPAQUE is set, then + the image's pixels will be copied directly to the + destination. If EFI_HII_DRAW_FLAG_DEFAULT is set, then the image + will be drawn transparently or opaque, depending on the + image's transparency setting (see EFI_IMAGE_TRANSPARENT). + Images cannot be drawn transparently if Blt is NULL. If + EFI_HII_DIRECT_TO_SCREEN is set, then the image will be written + directly to the output device specified by Screen. Otherwise the + image will be rendered to the bitmap specified by Bitmap. + + @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance. + + @param Flags Describes how the image is to be drawn. + + @param PackageList The package list in the HII database to + search for the specified image. + + @param ImageId The image's id, which is unique within PackageList. + + @param Blt If this points to a non-NULL on entry, this points + to the image, which is Width pixels wide and + Height pixels high. The image will be drawn onto + this image and EFI_HII_DRAW_FLAG_CLIP is implied. + If this points to a NULL on entry, then a buffer + will be allocated to hold the generated image and + the pointer updated on exit. It is the caller's + responsibility to free this buffer. + + @param BltX, BltY Specifies the offset from the left and top + edge of the output image of the first + pixel in the image. + + @retval EFI_SUCCESS The image was successfully updated. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate an output + buffer for RowInfoArray or Blt. + + @retval EFI_NOT_FOUND The image specified by ImageId is not in the database. + Or The specified PackageList is not in the database. + + @retval EFI_INVALID_PARAMETER The Blt was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DRAW_IMAGE_ID)( +IN CONST EFI_HII_IMAGE_PROTOCOL *This, +IN EFI_HII_DRAW_FLAGS Flags, +IN EFI_HII_HANDLE PackageList, +IN EFI_IMAGE_ID ImageId, +IN OUT EFI_IMAGE_OUTPUT **Blt, +IN UINTN BltX, +IN UINTN BltY +); + + +/// +/// Services to access to images in the images database. +/// +struct _EFI_HII_IMAGE_PROTOCOL { + EFI_HII_NEW_IMAGE NewImage; + EFI_HII_GET_IMAGE GetImage; + EFI_HII_SET_IMAGE SetImage; + EFI_HII_DRAW_IMAGE DrawImage; + EFI_HII_DRAW_IMAGE_ID DrawImageId; +}; + +extern EFI_GUID gEfiHiiImageProtocolGuid; + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageDecoder.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageDecoder.h new file mode 100644 index 0000000..ce4d46a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageDecoder.h @@ -0,0 +1,206 @@ +/** @file + This protocol provides generic image decoder interfaces to various image formats. + +(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2016-2018, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.6. + +**/ +#ifndef __HII_IMAGE_DECODER_H__ +#define __HII_IMAGE_DECODER_H__ + +#include + +#define EFI_HII_IMAGE_DECODER_PROTOCOL_GUID \ + {0x9e66f251, 0x727c, 0x418c, { 0xbf, 0xd6, 0xc2, 0xb4, 0x25, 0x28, 0x18, 0xea }} + + +#define EFI_HII_IMAGE_DECODER_NAME_JPEG_GUID \ + {0xefefd093, 0xd9b, 0x46eb, { 0xa8, 0x56, 0x48, 0x35, 0x7, 0x0, 0xc9, 0x8 }} + +#define EFI_HII_IMAGE_DECODER_NAME_PNG_GUID \ + {0xaf060190, 0x5e3a, 0x4025, { 0xaf, 0xbd, 0xe1, 0xf9, 0x5, 0xbf, 0xaa, 0x4c }} + +typedef struct _EFI_HII_IMAGE_DECODER_PROTOCOL EFI_HII_IMAGE_DECODER_PROTOCOL; + +typedef enum { + EFI_HII_IMAGE_DECODER_COLOR_TYPE_RGB = 0x0, + EFI_HII_IMAGE_DECODER_COLOR_TYPE_RGBA = 0x1, + EFI_HII_IMAGE_DECODER_COLOR_TYPE_CMYK = 0x2, + EFI_HII_IMAGE_DECODER_COLOR_TYPE_UNKNOWN = 0xFF +} EFI_HII_IMAGE_DECODER_COLOR_TYPE; + +// +// EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER +// +// DecoderName Name of the decoder +// ImageInfoSize The size of entire image information structure in bytes +// ImageWidth The image width +// ImageHeight The image height +// ColorType The color type, see EFI_HII_IMAGE_DECODER_COLOR_TYPE. +// ColorDepthInBits The color depth in bits +// +typedef struct _EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER { + EFI_GUID DecoderName; + UINT16 ImageInfoSize; + UINT16 ImageWidth; + UINT16 ImageHeight; + EFI_HII_IMAGE_DECODER_COLOR_TYPE ColorType; + UINT8 ColorDepthInBits; +} EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER; + +#define EFI_IMAGE_JPEG_SCANTYPE_PROGREESSIVE 0x01 +#define EFI_IMAGE_JPEG_SCANTYPE_INTERLACED 0x02 + +// +// EFI_HII_IMAGE_DECODER_JPEG_INFO +// Header The common header +// ScanType The scan type of JPEG image +// Reserved Reserved +// +typedef struct _EFI_HII_IMAGE_DECODER_JPEG_INFO { + EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER Header; + UINT16 ScanType; + UINT64 Reserved; +} EFI_HII_IMAGE_DECODER_JPEG_INFO; + +// +// EFI_HII_IMAGE_DECODER_PNG_INFO +// Header The common header +// Channels Number of channels in the PNG image +// Reserved Reserved +// +typedef struct _EFI_HII_IMAGE_DECODER_PNG_INFO { + EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER Header; + UINT16 Channels; + UINT64 Reserved; +} EFI_HII_IMAGE_DECODER_PNG_INFO; + +// +// EFI_HII_IMAGE_DECODER_OTHER_INFO +// +typedef struct _EFI_HII_IMAGE_DECODER_OTHER_INFO { + EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER Header; + CHAR16 ImageExtenion[1]; + // + // Variable length of image file extension name. + // +} EFI_HII_IMAGE_DECODER_OTHER_INFO; + +/** + There could be more than one EFI_HII_IMAGE_DECODER_PROTOCOL instances installed + in the system for different image formats. This function returns the decoder + name which callers can use to find the proper image decoder for the image. It + is possible to support multiple image formats in one EFI_HII_IMAGE_DECODER_PROTOCOL. + The capability of the supported image formats is returned in DecoderName and + NumberOfDecoderName. + + @param This EFI_HII_IMAGE_DECODER_PROTOCOL instance. + @param DecoderName Pointer to a dimension to retrieve the decoder + names in EFI_GUID format. The number of the + decoder names is returned in NumberOfDecoderName. + @param NumberofDecoderName Pointer to retrieve the number of decoders which + supported by this decoder driver. + + @retval EFI_SUCCESS Get decoder name success. + @retval EFI_UNSUPPORTED Get decoder name fail. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_IMAGE_DECODER_GET_NAME)( + IN EFI_HII_IMAGE_DECODER_PROTOCOL *This, + IN OUT EFI_GUID **DecoderName, + IN OUT UINT16 *NumberOfDecoderName + ); + +/** + This function returns the image information of the given image raw data. This + function first checks whether the image raw data is supported by this decoder + or not. This function may go through the first few bytes in the image raw data + for the specific data structure or the image signature. If the image is not supported + by this image decoder, this function returns EFI_UNSUPPORTED to the caller. + Otherwise, this function returns the proper image information to the caller. + It is the caller?s responsibility to free the ImageInfo. + + @param This EFI_HII_IMAGE_DECODER_PROTOCOL instance. + @param Image Pointer to the image raw data. + @param SizeOfImage Size of the entire image raw data. + @param ImageInfo Pointer to receive EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER. + + @retval EFI_SUCCESS Get image info success. + @retval EFI_UNSUPPORTED Unsupported format of image. + @retval EFI_INVALID_PARAMETER Incorrect parameter. + @retval EFI_BAD_BUFFER_SIZE Not enough memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_IMAGE_DECODER_GET_IMAGE_INFO)( + IN EFI_HII_IMAGE_DECODER_PROTOCOL *This, + IN VOID *Image, + IN UINTN SizeOfImage, + IN OUT EFI_HII_IMAGE_DECODER_IMAGE_INFO_HEADER **ImageInfo + ); + +/** + This function decodes the image which the image type of this image is supported + by this EFI_HII_IMAGE_DECODER_PROTOCOL. If **Bitmap is not NULL, the caller intends + to put the image in the given image buffer. That allows the caller to put an + image overlap on the original image. The transparency is handled by the image + decoder because the transparency capability depends on the image format. Callers + can set Transparent to FALSE to force disabling the transparency process on the + image. Forcing Transparent to FALSE may also improve the performance of the image + decoding because the image decoder can skip the transparency processing. If **Bitmap + is NULL, the image decoder allocates the memory buffer for the EFI_IMAGE_OUTPUT + and decodes the image to the image buffer. It is the caller?s responsibility to + free the memory for EFI_IMAGE_OUTPUT. Image decoder doesn?t have to handle the + transparency in this case because there is no background image given by the caller. + The background color in this case is all black (#00000000). + + @param This EFI_HII_IMAGE_DECODER_PROTOCOL instance. + @param Image Pointer to the image raw data. + @param ImageRawDataSize Size of the entire image raw data. + @param Blt EFI_IMAGE_OUTPUT to receive the image or overlap + the image on the original buffer. + @param Transparent BOOLEAN value indicates whether the image decoder + has to handle the transparent image or not. + + + @retval EFI_SUCCESS Image decode success. + @retval EFI_UNSUPPORTED Unsupported format of image. + @retval EFI_INVALID_PARAMETER Incorrect parameter. + @retval EFI_BAD_BUFFER_SIZE Not enough memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_IMAGE_DECODER_DECODE)( + IN EFI_HII_IMAGE_DECODER_PROTOCOL *This, + IN VOID *Image, + IN UINTN ImageRawDataSize, + IN OUT EFI_IMAGE_OUTPUT **Bitmap, + IN BOOLEAN Transparent + ); + +struct _EFI_HII_IMAGE_DECODER_PROTOCOL { + EFI_HII_IMAGE_DECODER_GET_NAME GetImageDecoderName; + EFI_HII_IMAGE_DECODER_GET_IMAGE_INFO GetImageInfo; + EFI_HII_IMAGE_DECODER_DECODE DecodeImage; +}; + +extern EFI_GUID gEfiHiiImageDecoderProtocolGuid; +extern EFI_GUID gEfiHiiImageDecoderNameJpegGuid; +extern EFI_GUID gEfiHiiImageDecoderNamePngGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageEx.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageEx.h new file mode 100644 index 0000000..86462d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiImageEx.h @@ -0,0 +1,254 @@ +/** @file + Protocol which allows access to the images in the images database. + +(C) Copyright 2016-2018 Hewlett Packard Enterprise Development LP
+ +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.6. + +**/ + +#ifndef __EFI_HII_IMAGE_EX_H__ +#define __EFI_HII_IMAGE_EX_H__ + +#include + +// +// Global ID for the Hii Image Ex Protocol. +// +#define EFI_HII_IMAGE_EX_PROTOCOL_GUID \ + {0x1a1241e6, 0x8f19, 0x41a9, { 0xbc, 0xe, 0xe8, 0xef, 0x39, 0xe0, 0x65, 0x46 }} + +typedef struct _EFI_HII_IMAGE_EX_PROTOCOL EFI_HII_IMAGE_EX_PROTOCOL; + +/** + The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.NewImage(). + This protocol invokes EFI_HII_IMAGE_PROTOCOL.NewImage() implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @param PackageList Handle of the package list where this image will + be added. + @param ImageId On return, contains the new image id, which is + unique within PackageList. + @param Image Points to the image. + + @retval EFI_SUCCESS The new image was added successfully. + @retval EFI_NOT_FOUND The specified PackageList could not be found in + database. + @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources. + @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_IMAGE_EX)( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + OUT EFI_IMAGE_ID *ImageId, + IN CONST EFI_IMAGE_INPUT *Image + ); + +/** + Return the information about the image, associated with the package list. + The prototype of this extension function is the same with EFI_HII_IMAGE_PROTOCOL.GetImage(). + + This function is similar to EFI_HII_IMAGE_PROTOCOL.GetImage().The difference is that + this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the + system if the decoder of the certain image type is not supported by the + EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the + EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that + supports the requested image type. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @param PackageList The package list in the HII database to search for the + specified image. + @param ImageId The image's id, which is unique within PackageList. + @param Image Points to the image. + + @retval EFI_SUCCESS The new image was returned successfully. + @retval EFI_NOT_FOUND The image specified by ImageId is not available. The specified + PackageList is not in the Database. + @retval EFI_INVALID_PARAMETER Image was NULL or ImageId was 0. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there + was not enough memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_IMAGE_EX)( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + OUT EFI_IMAGE_INPUT *Image + ); + +/** + Change the information about the image. + + Same with EFI_HII_IMAGE_PROTOCOL.SetImage(),this protocol invokes + EFI_HII_IMAGE_PROTOCOL.SetImage()implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @param PackageList The package list containing the images. + @param ImageId The image's id, which is unique within PackageList. + @param Image Points to the image. + + @retval EFI_SUCCESS The new image was successfully updated. + @retval EFI_NOT_FOUND The image specified by ImageId is not in the + database. The specified PackageList is not in + the database. + @retval EFI_INVALID_PARAMETER The Image was NULL, the ImageId was 0 or + the Image->Bitmap was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_SET_IMAGE_EX)( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + IN CONST EFI_IMAGE_INPUT *Image + ); + +/** + Renders an image to a bitmap or to the display. + + The prototype of this extension function is the same with + EFI_HII_IMAGE_PROTOCOL.DrawImage(). This protocol invokes + EFI_HII_IMAGE_PROTOCOL.DrawImage() implicitly. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @param Flags Describes how the image is to be drawn. + @param Image Points to the image to be displayed. + @param Blt If this points to a non-NULL on entry, this points + to the image, which is Width pixels wide and + Height pixels high. The image will be drawn onto + this image and EFI_HII_DRAW_FLAG_CLIP is implied. + If this points to a NULL on entry, then a buffer + will be allocated to hold the generated image and + the pointer updated on exit. It is the caller's + responsibility to free this buffer. + @param BltX Specifies the offset from the left and top edge of + the output image of the first pixel in the image. + @param BltY Specifies the offset from the left and top edge of + the output image of the first pixel in the image. + + @retval EFI_SUCCESS The image was successfully drawn. + @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt. + @retval EFI_INVALID_PARAMETER The Image or Blt was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DRAW_IMAGE_EX)( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_DRAW_FLAGS Flags, + IN CONST EFI_IMAGE_INPUT *Image, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY + ); + +/** + Renders an image to a bitmap or the screen containing the contents of the specified + image. + + This function is similar to EFI_HII_IMAGE_PROTOCOL.DrawImageId(). The difference is that + this function will locate all EFI_HII_IMAGE_DECODER_PROTOCOL instances installed in the + system if the decoder of the certain image type is not supported by the + EFI_HII_IMAGE_EX_PROTOCOL. The function will attempt to decode the image to the + EFI_IMAGE_INPUT using the first EFI_HII_IMAGE_DECODER_PROTOCOL instance that + supports the requested image type. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @param Flags Describes how the image is to be drawn. + @param PackageList The package list in the HII database to search for + the specified image. + @param ImageId The image's id, which is unique within PackageList. + @param Blt If this points to a non-NULL on entry, this points + to the image, which is Width pixels wide and + Height pixels high. The image will be drawn onto + this image and EFI_HII_DRAW_FLAG_CLIP is implied. + If this points to a NULL on entry, then a buffer + will be allocated to hold the generated image + and the pointer updated on exit. It is the caller's + responsibility to free this buffer. + @param BltX Specifies the offset from the left and top edge of + the output image of the first pixel in the image. + @param BltY Specifies the offset from the left and top edge of + the output image of the first pixel in the image. + + @retval EFI_SUCCESS The image was successfully drawn. + @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt. + @retval EFI_INVALID_PARAMETER The Blt was NULL or ImageId was 0. + @retval EFI_NOT_FOUND The image specified by ImageId is not in the database. + The specified PackageList is not in the database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_DRAW_IMAGE_ID_EX)( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_DRAW_FLAGS Flags, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY + ); + +/** + This function returns the image information to EFI_IMAGE_OUTPUT. Only the width + and height are returned to the EFI_IMAGE_OUTPUT instead of decoding the image + to the buffer. This function is used to get the geometry of the image. This function + will try to locate all of the EFI_HII_IMAGE_DECODER_PROTOCOL installed on the + system if the decoder of image type is not supported by the EFI_HII_IMAGE_EX_PROTOCOL. + + @param This A pointer to the EFI_HII_IMAGE_EX_PROTOCOL instance. + @param PackageList Handle of the package list where this image will + be searched. + @param ImageId The image's id, which is unique within PackageList. + @param Image Points to the image. + + @retval EFI_SUCCESS The new image was returned successfully. + @retval EFI_NOT_FOUND The image specified by ImageId is not in the + database. The specified PackageList is not in the database. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to + hold the image. + @retval EFI_INVALID_PARAMETER The Image was NULL or the ImageId was 0. + @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there + was not enough memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_IMAGE_INFO)( + IN CONST EFI_HII_IMAGE_EX_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_IMAGE_ID ImageId, + OUT EFI_IMAGE_OUTPUT *Image + ); + +/// +/// Protocol which allows access to the images in the images database. +/// +struct _EFI_HII_IMAGE_EX_PROTOCOL { + EFI_HII_NEW_IMAGE_EX NewImageEx; + EFI_HII_GET_IMAGE_EX GetImageEx; + EFI_HII_SET_IMAGE_EX SetImageEx; + EFI_HII_DRAW_IMAGE_EX DrawImageEx; + EFI_HII_DRAW_IMAGE_ID_EX DrawImageIdEx; + EFI_HII_GET_IMAGE_INFO GetImageInfo; +}; + +extern EFI_GUID gEfiHiiImageExProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPackageList.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPackageList.h new file mode 100644 index 0000000..d1cb9e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPackageList.h @@ -0,0 +1,33 @@ +/** @file + EFI_HII_PACKAGE_LIST_PROTOCOL as defined in UEFI 2.1. + Boot service LoadImage() installs EFI_HII_PACKAGE_LIST_PROTOCOL on the handle + if the image contains a custom PE/COFF resource with the type 'HII'. + The protocol's interface pointer points to the HII package list, which is + contained in the resource's data. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HII_PACKAGE_LIST_H__ +#define __HII_PACKAGE_LIST_H__ + +#define EFI_HII_PACKAGE_LIST_PROTOCOL_GUID \ + { 0x6a1ee763, 0xd47a, 0x43b4, {0xaa, 0xbe, 0xef, 0x1d, 0xe2, 0xab, 0x56, 0xfc}} + +typedef EFI_HII_PACKAGE_LIST_HEADER * EFI_HII_PACKAGE_LIST_PROTOCOL; + +extern EFI_GUID gEfiHiiPackageListProtocolGuid; + + + +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPopup.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPopup.h new file mode 100644 index 0000000..90925d4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiPopup.h @@ -0,0 +1,84 @@ +/** @file + This protocol provides services to display a popup window. + The protocol is typically produced by the forms browser and consumed by a driver callback handler. + + Copyright (c) 2017-2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.7. + +**/ + +#ifndef __HII_POPUP_H__ +#define __HII_POPUP_H__ + +#define EFI_HII_POPUP_PROTOCOL_GUID \ + {0x4311edc0, 0x6054, 0x46d4, {0x9e, 0x40, 0x89, 0x3e, 0xa9, 0x52, 0xfc, 0xcc}} + +#define EFI_HII_POPUP_PROTOCOL_REVISION 1 + +typedef struct _EFI_HII_POPUP_PROTOCOL EFI_HII_POPUP_PROTOCOL; + +typedef enum { + EfiHiiPopupStyleInfo, + EfiHiiPopupStyleWarning, + EfiHiiPopupStyleError +} EFI_HII_POPUP_STYLE; + +typedef enum { + EfiHiiPopupTypeOk, + EfiHiiPopupTypeOkCancel, + EfiHiiPopupTypeYesNo, + EfiHiiPopupTypeYesNoCancel +} EFI_HII_POPUP_TYPE; + +typedef enum { + EfiHiiPopupSelectionOk, + EfiHiiPopupSelectionCancel, + EfiHiiPopupSelectionYes, + EfiHiiPopupSelectionNo +} EFI_HII_POPUP_SELECTION; + +/** + Displays a popup window. + + @param This A pointer to the EFI_HII_POPUP_PROTOCOL instance. + @param PopupStyle Popup style to use. + @param PopupType Type of the popup to display. + @param HiiHandle HII handle of the string pack containing Message + @param Message A message to display in the popup box. + @param UserSelection User selection. + + @retval EFI_SUCCESS The popup box was successfully displayed. + @retval EFI_INVALID_PARAMETER HiiHandle and Message do not define a valid HII string. + @retval EFI_INVALID_PARAMETER PopupType is not one of the values defined by this specification. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to display the popup box. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HII_CREATE_POPUP) ( + IN EFI_HII_POPUP_PROTOCOL *This, + IN EFI_HII_POPUP_STYLE PopupStyle, + IN EFI_HII_POPUP_TYPE PopupType, + IN EFI_HII_HANDLE HiiHandle, + IN EFI_STRING_ID Message, + OUT EFI_HII_POPUP_SELECTION *UserSelection OPTIONAL +); + +typedef struct _EFI_HII_POPUP_PROTOCOL { + UINT64 Revision; + EFI_HII_CREATE_POPUP CreatePopup; +} EFI_HII_POPUP_PROTOCOL; + +extern EFI_GUID gEfiHiiPopupProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiString.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiString.h new file mode 100644 index 0000000..57a8bde --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HiiString.h @@ -0,0 +1,244 @@ +/** @file + The file provides services to manipulate string data. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.1. + +**/ + +#ifndef __HII_STRING_H__ +#define __HII_STRING_H__ + +#include + +#define EFI_HII_STRING_PROTOCOL_GUID \ + { 0xfd96974, 0x23aa, 0x4cdc, { 0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a } } + +typedef struct _EFI_HII_STRING_PROTOCOL EFI_HII_STRING_PROTOCOL; + +/** + This function adds the string String to the group of strings owned by PackageList, with the + specified font information StringFontInfo, and returns a new string id. + The new string identifier is guaranteed to be unique within the package list. + That new string identifier is reserved for all languages in the package list. + + @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. + @param PackageList The handle of the package list where this string will + be added. + @param StringId On return, contains the new strings id, which is + unique within PackageList. + @param Language Points to the language for the new string. + @param LanguageName Points to the printable language name to associate + with the passed in Language field.If LanguageName + is not NULL and the string package header's + LanguageName associated with a given Language is + not zero, the LanguageName being passed in will + be ignored. + @param String Points to the new null-terminated string. + @param StringFontInfo Points to the new string's font information or + NULL if the string should have the default system + font, size and style. + + @retval EFI_SUCCESS The new string was added successfully. + @retval EFI_NOT_FOUND The specified PackageList could not be found in + database. + @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources. + @retval EFI_INVALID_PARAMETER String is NULL, or StringId is NULL, or Language is NULL. + @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in + current database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_STRING)( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + OUT EFI_STRING_ID *StringId, + IN CONST CHAR8 *Language, + IN CONST CHAR16 *LanguageName, OPTIONAL + IN CONST EFI_STRING String, + IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL +); + + +/** + This function retrieves the string specified by StringId which is associated + with the specified PackageList in the language Language and copies it into + the buffer specified by String. + + @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. + @param Language Points to the language for the retrieved string. + @param PackageList The package list in the HII database to search for + the specified string. + @param StringId The string's id, which is unique within + PackageList. + @param String Points to the new null-terminated string. + @param StringSize On entry, points to the size of the buffer pointed + to by String, in bytes. On return, points to the + length of the string, in bytes. + @param StringFontInfo If not NULL, points to the string's font + information. It's caller's responsibility to free + this buffer. + + @retval EFI_SUCCESS The string was returned successfully. + @retval EFI_NOT_FOUND The string specified by StringId is not available. + The specified PackageList is not in the database. + @retval EFI_INVALID_LANGUAGE The string specified by StringId is available but + not in the specified language. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to + hold the string. + @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL. + @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and + String was NULL. + @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the + request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_STRING)( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN CONST CHAR8 *Language, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + OUT EFI_STRING String, + IN OUT UINTN *StringSize, + OUT EFI_FONT_INFO **StringFontInfo OPTIONAL +); + +/** + This function updates the string specified by StringId in the specified PackageList to the text + specified by String and, optionally, the font information specified by StringFontInfo. + + @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. + @param PackageList The package list containing the strings. + @param StringId The string's id, which is unique within + PackageList. + @param Language Points to the language for the updated string. + @param String Points to the new null-terminated string. + @param StringFontInfo Points to the string's font information or NULL if + the string font information is not changed. + + @retval EFI_SUCCESS The string was updated successfully. + @retval EFI_NOT_FOUND The string specified by StringId is not in the + database. + @retval EFI_INVALID_PARAMETER The String or Language was NULL. + @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in + current database. + @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the + task. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_SET_STRING)( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST CHAR8 *Language, + IN EFI_STRING String, + IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL +); + + +/** + This function returns the list of supported languages. + + @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. + @param PackageList The package list to examine. + @param Languages Points to the buffer to hold the returned + null-terminated ASCII string. + @param LanguagesSize On entry, points to the size of the buffer pointed + to by Languages, in bytes. On return, points to + the length of Languages, in bytes. + + @retval EFI_SUCCESS The languages were returned successfully. + @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL. + @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero + and Languages is NULL. + @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of + supported languages. LanguageSize is updated to + contain the required size. + @retval EFI_NOT_FOUND Could not find string package in specified + packagelist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_LANGUAGES)( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN OUT CHAR8 *Languages, + IN OUT UINTN *LanguagesSize +); + + +/** + Each string package has associated with it a single primary language and zero + or more secondary languages. This routine returns the secondary languages + associated with a package list. + + @param This A pointer to the EFI_HII_STRING_PROTOCOL instance. + @param PackageList The package list to examine. + @param PrimaryLanguage Points to the null-terminated ASCII string that specifies + the primary language. Languages are specified in the + format specified in Appendix M of the UEFI 2.0 specification. + @param SecondaryLanguages Points to the buffer to hold the returned null-terminated + ASCII string that describes the list of + secondary languages for the specified + PrimaryLanguage. If there are no secondary + languages, the function returns successfully, but + this is set to NULL. + @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed + to by SecondaryLanguages, in bytes. On return, + points to the length of SecondaryLanguages in bytes. + + @retval EFI_SUCCESS Secondary languages were correctly returned. + @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL. + @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not + zero and SecondaryLanguages is NULL. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is + too small to hold the returned information. + SecondaryLanguageSize is updated to hold the size of + the buffer required. + @retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not + present in the specified package list. + @retval EFI_NOT_FOUND The specified PackageList is not in the Database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_2ND_LANGUAGES)( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN CONST CHAR8 *PrimaryLanguage, + IN OUT CHAR8 *SecondaryLanguages, + IN OUT UINTN *SecondaryLanguagesSize +); + + +/// +/// Services to manipulate the string. +/// +struct _EFI_HII_STRING_PROTOCOL { + EFI_HII_NEW_STRING NewString; + EFI_HII_GET_STRING GetString; + EFI_HII_SET_STRING SetString; + EFI_HII_GET_LANGUAGES GetLanguages; + EFI_HII_GET_2ND_LANGUAGES GetSecondaryLanguages; +}; + + +extern EFI_GUID gEfiHiiStringProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Http.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Http.h new file mode 100644 index 0000000..c88cc9f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Http.h @@ -0,0 +1,522 @@ +/** @file + This file defines the EFI HTTP Protocol interface. It is split into + the following two main sections: + HTTP Service Binding Protocol (HTTPSB) + HTTP Protocol (HTTP) + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_HTTP_PROTOCOL_H__ +#define __EFI_HTTP_PROTOCOL_H__ + +#define EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \ + } + +#define EFI_HTTP_PROTOCOL_GUID \ + { \ + 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } \ + } + +typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL; + +/// +/// EFI_HTTP_VERSION +/// +typedef enum { + HttpVersion10, + HttpVersion11, + HttpVersionUnsupported +} EFI_HTTP_VERSION; + +/// +/// EFI_HTTP_METHOD +/// +typedef enum { + HttpMethodGet, + HttpMethodPost, + HttpMethodPatch, + HttpMethodOptions, + HttpMethodConnect, + HttpMethodHead, + HttpMethodPut, + HttpMethodDelete, + HttpMethodTrace, + HttpMethodMax +} EFI_HTTP_METHOD; + +/// +/// EFI_HTTP_STATUS_CODE +/// +typedef enum { + HTTP_STATUS_UNSUPPORTED_STATUS = 0, + HTTP_STATUS_100_CONTINUE, + HTTP_STATUS_101_SWITCHING_PROTOCOLS, + HTTP_STATUS_200_OK, + HTTP_STATUS_201_CREATED, + HTTP_STATUS_202_ACCEPTED, + HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION, + HTTP_STATUS_204_NO_CONTENT, + HTTP_STATUS_205_RESET_CONTENT, + HTTP_STATUS_206_PARTIAL_CONTENT, + HTTP_STATUS_300_MULTIPLE_CHOICES, + HTTP_STATUS_301_MOVED_PERMANENTLY, + HTTP_STATUS_302_FOUND, + HTTP_STATUS_303_SEE_OTHER, + HTTP_STATUS_304_NOT_MODIFIED, + HTTP_STATUS_305_USE_PROXY, + HTTP_STATUS_307_TEMPORARY_REDIRECT, + HTTP_STATUS_400_BAD_REQUEST, + HTTP_STATUS_401_UNAUTHORIZED, + HTTP_STATUS_402_PAYMENT_REQUIRED, + HTTP_STATUS_403_FORBIDDEN, + HTTP_STATUS_404_NOT_FOUND, + HTTP_STATUS_405_METHOD_NOT_ALLOWED, + HTTP_STATUS_406_NOT_ACCEPTABLE, + HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED, + HTTP_STATUS_408_REQUEST_TIME_OUT, + HTTP_STATUS_409_CONFLICT, + HTTP_STATUS_410_GONE, + HTTP_STATUS_411_LENGTH_REQUIRED, + HTTP_STATUS_412_PRECONDITION_FAILED, + HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE, + HTTP_STATUS_414_REQUEST_URI_TOO_LARGE, + HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE, + HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED, + HTTP_STATUS_417_EXPECTATION_FAILED, + HTTP_STATUS_500_INTERNAL_SERVER_ERROR, + HTTP_STATUS_501_NOT_IMPLEMENTED, + HTTP_STATUS_502_BAD_GATEWAY, + HTTP_STATUS_503_SERVICE_UNAVAILABLE, + HTTP_STATUS_504_GATEWAY_TIME_OUT, + HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED, + HTTP_STATUS_308_PERMANENT_REDIRECT +} EFI_HTTP_STATUS_CODE; + +/// +/// EFI_HTTPv4_ACCESS_POINT +/// +typedef struct { + /// + /// Set to TRUE to instruct the EFI HTTP instance to use the default address + /// information in every TCP connection made by this instance. In addition, when set + /// to TRUE, LocalAddress and LocalSubnet are ignored. + /// + BOOLEAN UseDefaultAddress; + /// + /// If UseDefaultAddress is set to FALSE, this defines the local IP address to be + /// used in every TCP connection opened by this instance. + /// + EFI_IPv4_ADDRESS LocalAddress; + /// + /// If UseDefaultAddress is set to FALSE, this defines the local subnet to be used + /// in every TCP connection opened by this instance. + /// + EFI_IPv4_ADDRESS LocalSubnet; + /// + /// This defines the local port to be used in + /// every TCP connection opened by this instance. + /// + UINT16 LocalPort; +} EFI_HTTPv4_ACCESS_POINT; + +/// +/// EFI_HTTPv6_ACCESS_POINT +/// +typedef struct { + /// + /// Local IP address to be used in every TCP connection opened by this instance. + /// + EFI_IPv6_ADDRESS LocalAddress; + /// + /// Local port to be used in every TCP connection opened by this instance. + /// + UINT16 LocalPort; +} EFI_HTTPv6_ACCESS_POINT; + +/// +/// EFI_HTTP_CONFIG_DATA_ACCESS_POINT +/// + + +typedef struct { + /// + /// HTTP version that this instance will support. + /// + EFI_HTTP_VERSION HttpVersion; + /// + /// Time out (in milliseconds) when blocking for requests. + /// + UINT32 TimeOutMillisec; + /// + /// Defines behavior of EFI DNS and TCP protocols consumed by this instance. If + /// FALSE, this instance will use EFI_DNS4_PROTOCOL and EFI_TCP4_PROTOCOL. If TRUE, + /// this instance will use EFI_DNS6_PROTOCOL and EFI_TCP6_PROTOCOL. + /// + BOOLEAN LocalAddressIsIPv6; + + union { + /// + /// When LocalAddressIsIPv6 is FALSE, this points to the local address, subnet, and + /// port used by the underlying TCP protocol. + /// + EFI_HTTPv4_ACCESS_POINT *IPv4Node; + /// + /// When LocalAddressIsIPv6 is TRUE, this points to the local IPv6 address and port + /// used by the underlying TCP protocol. + /// + EFI_HTTPv6_ACCESS_POINT *IPv6Node; + } AccessPoint; +} EFI_HTTP_CONFIG_DATA; + +/// +/// EFI_HTTP_REQUEST_DATA +/// +typedef struct { + /// + /// The HTTP method (e.g. GET, POST) for this HTTP Request. + /// + EFI_HTTP_METHOD Method; + /// + /// The URI of a remote host. From the information in this field, the HTTP instance + /// will be able to determine whether to use HTTP or HTTPS and will also be able to + /// determine the port number to use. If no port number is specified, port 80 (HTTP) + /// is assumed. See RFC 3986 for more details on URI syntax. + /// + CHAR16 *Url; +} EFI_HTTP_REQUEST_DATA; + +/// +/// EFI_HTTP_RESPONSE_DATA +/// +typedef struct { + /// + /// Response status code returned by the remote host. + /// + EFI_HTTP_STATUS_CODE StatusCode; +} EFI_HTTP_RESPONSE_DATA; + +/// +/// EFI_HTTP_HEADER +/// +typedef struct { + /// + /// Null terminated string which describes a field name. See RFC 2616 Section 14 for + /// detailed information about field names. + /// + CHAR8 *FieldName; + /// + /// Null terminated string which describes the corresponding field value. See RFC 2616 + /// Section 14 for detailed information about field values. + /// + CHAR8 *FieldValue; +} EFI_HTTP_HEADER; + +/// +/// EFI_HTTP_MESSAGE +/// +typedef struct { + /// + /// HTTP message data. + /// + union { + /// + /// When the token is used to send a HTTP request, Request is a pointer to storage that + /// contains such data as URL and HTTP method. + /// + EFI_HTTP_REQUEST_DATA *Request; + /// + /// When used to await a response, Response points to storage containing HTTP response + /// status code. + /// + EFI_HTTP_RESPONSE_DATA *Response; + } Data; + /// + /// Number of HTTP header structures in Headers list. On request, this count is + /// provided by the caller. On response, this count is provided by the HTTP driver. + /// + UINTN HeaderCount; + /// + /// Array containing list of HTTP headers. On request, this array is populated by the + /// caller. On response, this array is allocated and populated by the HTTP driver. It + /// is the responsibility of the caller to free this memory on both request and + /// response. + /// + EFI_HTTP_HEADER *Headers; + /// + /// Length in bytes of the HTTP body. This can be zero depending on the HttpMethod type. + /// + UINTN BodyLength; + /// + /// Body associated with the HTTP request or response. This can be NULL depending on + /// the HttpMethod type. + /// + VOID *Body; +} EFI_HTTP_MESSAGE; + + +/// +/// EFI_HTTP_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI HTTP + /// Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. The Task Priority + /// Level (TPL) of Event must be lower than or equal to TPL_CALLBACK. + /// + EFI_EVENT Event; + /// + /// Status will be set to one of the following value if the HTTP request is + /// successfully sent or if an unexpected error occurs: + /// EFI_SUCCESS: The HTTP request was successfully sent to the remote host. + /// EFI_HTTP_ERROR: The response message was successfully received but contains a + /// HTTP error. The response status code is returned in token. + /// EFI_ABORTED: The HTTP request was cancelled by the caller and removed from + /// the transmit queue. + /// EFI_TIMEOUT: The HTTP request timed out before reaching the remote host. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// + EFI_STATUS Status; + /// + /// Pointer to storage containing HTTP message data. + /// + EFI_HTTP_MESSAGE *Message; +} EFI_HTTP_TOKEN; + +/** + Returns the operational parameters for the current HTTP child instance. + + The GetModeData() function is used to read the current mode data (operational + parameters) for this HTTP protocol instance. + + @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. + @param[out] HttpConfigData Point to buffer for operational parameters of this + HTTP instance. It is the responsibility of the caller + to allocate the memory for HttpConfigData and + HttpConfigData->AccessPoint.IPv6Node/IPv4Node. In fact, + it is recommended to allocate sufficient memory to record + IPv6Node since it is big enough for all possibilities. + + @retval EFI_SUCCESS Operation succeeded. + @retval EFI_INVALID_PARAMETER This is NULL. + HttpConfigData is NULL. + HttpConfigData->AccessPoint.IPv4Node or + HttpConfigData->AccessPoint.IPv6Node is NULL. + @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_GET_MODE_DATA)( + IN EFI_HTTP_PROTOCOL *This, + OUT EFI_HTTP_CONFIG_DATA *HttpConfigData + ); + +/** + Initialize or brutally reset the operational parameters for this EFI HTTP instance. + + The Configure() function does the following: + When HttpConfigData is not NULL Initialize this EFI HTTP instance by configuring + timeout, local address, port, etc. + When HttpConfigData is NULL, reset this EFI HTTP instance by closing all active + connections with remote hosts, canceling all asynchronous tokens, and flush request + and response buffers without informing the appropriate hosts. + + No other EFI HTTP function can be executed by this instance until the Configure() + function is executed and returns successfully. + + @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. + @param[in] HttpConfigData Pointer to the configure data to configure the instance. + + @retval EFI_SUCCESS Operation succeeded. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + HttpConfigData->LocalAddressIsIPv6 is FALSE and + HttpConfigData->AccessPoint.IPv4Node is NULL. + HttpConfigData->LocalAddressIsIPv6 is TRUE and + HttpConfigData->AccessPoint.IPv6Node is NULL. + @retval EFI_ALREADY_STARTED Reinitialize this HTTP instance without calling + Configure() with NULL to reset it. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when + executing Configure(). + @retval EFI_UNSUPPORTED One or more options in ConfigData are not supported + in the implementation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_CONFIGURE)( + IN EFI_HTTP_PROTOCOL *This, + IN EFI_HTTP_CONFIG_DATA *HttpConfigData OPTIONAL + ); + +/** + The Request() function queues an HTTP request to this HTTP instance, + similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent + successfully, or if there is an error, Status in token will be updated and Event will + be signaled. + + @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. + @param[in] Token Pointer to storage containing HTTP request token. + + @retval EFI_SUCCESS Outgoing data was processed. + @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit or receive queue. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token->Message is NULL. + Token->Message->Body is not NULL, + Token->Message->BodyLength is non-zero, and + Token->Message->Data is NULL, but a previous call to + Request()has not been completed successfully. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources. + @retval EFI_UNSUPPORTED The HTTP method is not supported in current implementation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_REQUEST) ( + IN EFI_HTTP_PROTOCOL *This, + IN EFI_HTTP_TOKEN *Token + ); + +/** + Abort an asynchronous HTTP request or response token. + + The Cancel() function aborts a pending HTTP request or response transaction. If + Token is not NULL and the token is in transmit or receive queues when it is being + cancelled, its Token->Status will be set to EFI_ABORTED and then Token->Event will + be signaled. If the token is not in one of the queues, which usually means that the + asynchronous operation has completed, EFI_NOT_FOUND is returned. If Token is NULL, + all asynchronous tokens issued by Request() or Response() will be aborted. + + @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. + @param[in] Token Point to storage containing HTTP request or response + token. + + @retval EFI_SUCCESS Request and Response queues are successfully flushed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance hasn't been configured. + @retval EFI_NOT_FOUND The asynchronous request or response token is not + found. + @retval EFI_UNSUPPORTED The implementation does not support this function. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_CANCEL)( + IN EFI_HTTP_PROTOCOL *This, + IN EFI_HTTP_TOKEN *Token + ); + +/** + The Response() function queues an HTTP response to this HTTP instance, similar to + Receive() function in the EFI TCP driver. When the HTTP Response is received successfully, + or if there is an error, Status in token will be updated and Event will be signaled. + + The HTTP driver will queue a receive token to the underlying TCP instance. When data + is received in the underlying TCP instance, the data will be parsed and Token will + be populated with the response data. If the data received from the remote host + contains an incomplete or invalid HTTP header, the HTTP driver will continue waiting + (asynchronously) for more data to be sent from the remote host before signaling + Event in Token. + + It is the responsibility of the caller to allocate a buffer for Body and specify the + size in BodyLength. If the remote host provides a response that contains a content + body, up to BodyLength bytes will be copied from the receive buffer into Body and + BodyLength will be updated with the amount of bytes received and copied to Body. This + allows the client to download a large file in chunks instead of into one contiguous + block of memory. Similar to HTTP request, if Body is not NULL and BodyLength is + non-zero and all other fields are NULL or 0, the HTTP driver will queue a receive + token to underlying TCP instance. If data arrives in the receive buffer, up to + BodyLength bytes of data will be copied to Body. The HTTP driver will then update + BodyLength with the amount of bytes received and copied to Body. + + If the HTTP driver does not have an open underlying TCP connection with the host + specified in the response URL, Request() will return EFI_ACCESS_DENIED. This is + consistent with RFC 2616 recommendation that HTTP clients should attempt to maintain + an open TCP connection between client and host. + + @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. + @param[in] Token Pointer to storage containing HTTP response token. + + @retval EFI_SUCCESS Allocation succeeded. + @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been + initialized. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Token is NULL. + Token->Message->Headers is NULL. + Token->Message is NULL. + Token->Message->Body is not NULL, + Token->Message->BodyLength is non-zero, and + Token->Message->Data is NULL, but a previous call to + Response() has not been completed successfully. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources. + @retval EFI_ACCESS_DENIED An open TCP connection is not present with the host + specified by response URL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_RESPONSE) ( + IN EFI_HTTP_PROTOCOL *This, + IN EFI_HTTP_TOKEN *Token + ); + +/** + The Poll() function can be used by network drivers and applications to increase the + rate that data packets are moved between the communication devices and the transmit + and receive queues. + + In some systems, the periodic timer event in the managed network driver may not poll + the underlying communications device fast enough to transmit and/or receive all data + packets without missing incoming packets or dropping outgoing packets. Drivers and + applications that are experiencing packet loss should try calling the Poll() function + more often. + + @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed.. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_POLL) ( + IN EFI_HTTP_PROTOCOL *This + ); + +/// +/// The EFI HTTP protocol is designed to be used by EFI drivers and applications to +/// create and transmit HTTP Requests, as well as handle HTTP responses that are +/// returned by a remote host. This EFI protocol uses and relies on an underlying EFI +/// TCP protocol. +/// +struct _EFI_HTTP_PROTOCOL { + EFI_HTTP_GET_MODE_DATA GetModeData; + EFI_HTTP_CONFIGURE Configure; + EFI_HTTP_REQUEST Request; + EFI_HTTP_CANCEL Cancel; + EFI_HTTP_RESPONSE Response; + EFI_HTTP_POLL Poll; +}; + +extern EFI_GUID gEfiHttpServiceBindingProtocolGuid; +extern EFI_GUID gEfiHttpProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpBootCallback.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpBootCallback.h new file mode 100644 index 0000000..855c590 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpBootCallback.h @@ -0,0 +1,100 @@ +/** @file + This file defines the EFI HTTP Boot Callback Protocol interface. + + Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __EFI_HTTP_BOOT_CALLBACK_H__ +#define __EFI_HTTP_BOOT_CALLBACK_H__ + +#define EFI_HTTP_BOOT_CALLBACK_PROTOCOL_GUID \ + { \ + 0xba23b311, 0x343d, 0x11e6, {0x91, 0x85, 0x58, 0x20, 0xb1, 0xd6, 0x52, 0x99} \ + } + +typedef struct _EFI_HTTP_BOOT_CALLBACK_PROTOCOL EFI_HTTP_BOOT_CALLBACK_PROTOCOL; + +/// +/// EFI_HTTP_BOOT_CALLBACK_DATA_TYPE +/// +typedef enum { + /// + /// Data points to a DHCP4 packet which is about to transmit or has received. + /// + HttpBootDhcp4, + /// + /// Data points to a DHCP6 packet which is about to be transmit or has received. + /// + HttpBootDhcp6, + /// + /// Data points to an EFI_HTTP_MESSAGE structure, whichcontians a HTTP request message + /// to be transmitted. + /// + HttpBootHttpRequest, + /// + /// Data points to an EFI_HTTP_MESSAGE structure, which contians a received HTTP + /// response message. + /// + HttpBootHttpResponse, + /// + /// Part of the entity body has been received from the HTTP server. Data points to the + /// buffer of the entity body data. + /// + HttpBootHttpEntityBody, + HttpBootTypeMax +} EFI_HTTP_BOOT_CALLBACK_DATA_TYPE; + +/** + Callback function that is invoked when the HTTP Boot driver is about to transmit or has received a + packet. + + This function is invoked when the HTTP Boot driver is about to transmit or has received packet. + Parameters DataType and Received specify the type of event and the format of the buffer pointed + to by Data. Due to the polling nature of UEFI device drivers, this callback function should not + execute for more than 5 ms. + The returned status code determines the behavior of the HTTP Boot driver. + + @param[in] This Pointer to the EFI_HTTP_BOOT_CALLBACK_PROTOCOL instance. + @param[in] DataType The event that occurs in the current state. + @param[in] Received TRUE if the callback is being invoked due to a receive event. + FALSE if the callback is being invoked due to a transmit event. + @param[in] DataLength The length in bytes of the buffer pointed to by Data. + @param[in] Data A pointer to the buffer of data, the data type is specified by + DataType. + + @retval EFI_SUCCESS Tells the HTTP Boot driver to continue the HTTP Boot process. + @retval EFI_ABORTED Tells the HTTP Boot driver to abort the current HTTP Boot process. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_HTTP_BOOT_CALLBACK) ( + IN EFI_HTTP_BOOT_CALLBACK_PROTOCOL *This, + IN EFI_HTTP_BOOT_CALLBACK_DATA_TYPE DataType, + IN BOOLEAN Received, + IN UINT32 DataLength, + IN VOID *Data OPTIONAL + ); + +/// +/// EFI HTTP Boot Callback Protocol is invoked when the HTTP Boot driver is about to transmit or +/// has received a packet. The EFI HTTP Boot Callback Protocol must be installed on the same handle +/// as the Load File Protocol for the HTTP Boot. +/// +struct _EFI_HTTP_BOOT_CALLBACK_PROTOCOL { + EFI_HTTP_BOOT_CALLBACK Callback; +}; + +extern EFI_GUID gEfiHttpBootCallbackProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpUtilities.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpUtilities.h new file mode 100644 index 0000000..59c1ea2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/HttpUtilities.h @@ -0,0 +1,124 @@ +/** @file + EFI HTTP Utilities protocol provides a platform independent abstraction for HTTP + message comprehension. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_HTTP_UTILITIES_PROTOCOL_H__ +#define __EFI_HTTP_UTILITIES_PROTOCOL_H__ + +#include + +#define EFI_HTTP_UTILITIES_PROTOCOL_GUID \ + { \ + 0x3e35c163, 0x4074, 0x45dd, {0x43, 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 } \ + } + +typedef struct _EFI_HTTP_UTILITIES_PROTOCOL EFI_HTTP_UTILITIES_PROTOCOL; + + +/** + Create HTTP header based on a combination of seed header, fields + to delete, and fields to append. + + The Build() function is used to manage the headers portion of an + HTTP message by providing the ability to add, remove, or replace + HTTP headers. + + @param[in] This Pointer to EFI_HTTP_UTILITIES_PROTOCOL instance. + @param[in] SeedMessageSize Size of the initial HTTP header. This can be zero. + @param[in] SeedMessage Initial HTTP header to be used as a base for + building a new HTTP header. If NULL, + SeedMessageSize is ignored. + @param[in] DeleteCount Number of null-terminated HTTP header field names + in DeleteList. + @param[in] DeleteList List of null-terminated HTTP header field names to + remove from SeedMessage. Only the field names are + in this list because the field values are irrelevant + to this operation. + @param[in] AppendCount Number of header fields in AppendList. + @param[in] AppendList List of HTTP headers to populate NewMessage with. + If SeedMessage is not NULL, AppendList will be + appended to the existing list from SeedMessage in + NewMessage. + @param[out] NewMessageSize Pointer to number of header fields in NewMessage. + @param[out] NewMessage Pointer to a new list of HTTP headers based on. + + @retval EFI_SUCCESS Add, remove, and replace operations succeeded. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory for NewMessage. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_UTILS_BUILD) ( + IN EFI_HTTP_UTILITIES_PROTOCOL *This, + IN UINTN SeedMessageSize, + IN VOID *SeedMessage, OPTIONAL + IN UINTN DeleteCount, + IN CHAR8 *DeleteList[], OPTIONAL + IN UINTN AppendCount, + IN EFI_HTTP_HEADER *AppendList[], OPTIONAL + OUT UINTN *NewMessageSize, + OUT VOID **NewMessage + ); + +/** + Parses HTTP header and produces an array of key/value pairs. + + The Parse() function is used to transform data stored in HttpHeader + into a list of fields paired with their corresponding values. + + @param[in] This Pointer to EFI_HTTP_UTILITIES_PROTOCOL instance. + @param[in] HttpMessage Contains raw unformatted HTTP header string. + @param[in] HttpMessageSize Size of HTTP header. + @param[out] HeaderFields Array of key/value header pairs. + @param[out] FieldCount Number of headers in HeaderFields. + + @retval EFI_SUCCESS Allocation succeeded. + @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been + initialized. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + HttpMessage is NULL. + HeaderFields is NULL. + FieldCount is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HTTP_UTILS_PARSE) ( + IN EFI_HTTP_UTILITIES_PROTOCOL *This, + IN CHAR8 *HttpMessage, + IN UINTN HttpMessageSize, + OUT EFI_HTTP_HEADER **HeaderFields, + OUT UINTN *FieldCount + ); + + +/// +/// EFI_HTTP_UTILITIES_PROTOCOL +/// designed to be used by EFI drivers and applications to parse HTTP +/// headers from a byte stream. This driver is neither dependent on +/// network connectivity, nor the existence of an underlying network +/// infrastructure. +/// +struct _EFI_HTTP_UTILITIES_PROTOCOL { + EFI_HTTP_UTILS_BUILD Build; + EFI_HTTP_UTILS_PARSE Parse; +}; + +extern EFI_GUID gEfiHttpUtilitiesProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cBusConfigurationManagement.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cBusConfigurationManagement.h new file mode 100644 index 0000000..f630540 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cBusConfigurationManagement.h @@ -0,0 +1,171 @@ +/** @file + I2C Bus Configuration Management Protocol as defined in the PI 1.3 specification. + + The EFI I2C bus configuration management protocol provides platform specific + services that allow the I2C host protocol to reconfigure the switches and multiplexers + and set the clock frequency for the I2C bus. This protocol also enables the I2C host protocol + to reset an I2C device which may be locking up the I2C bus by holding the clock or data line low. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.3. + +**/ + +#ifndef __I2C_BUS_CONFIGURATION_MANAGEMENT_H__ +#define __I2C_BUS_CONFIGURATION_MANAGEMENT_H__ + +#define EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL_GUID \ + { 0x55b71fb5, 0x17c6, 0x410e, { 0xb5, 0xbd, 0x5f, 0xa2, 0xe3, 0xd4, 0x46, 0x6b }} + +/// +/// I2C bus configuration management protocol +/// +/// The EFI I2C bus configuration management protocol provides platform +/// specific services that allow the I2C host protocol to reconfigure the +/// switches and multiplexers and set the clock frequency for the I2C bus. +/// This protocol also enables the I2C host protocol to reset an I2C device +/// which may be locking up the I2C bus by holding the clock or data line +/// low. +/// +/// The I2C protocol stack uses the concept of an I2C bus configuration as +/// a way to describe a particular state of the switches and multiplexers +/// in the I2C bus. +/// +/// A simple I2C bus does not have any multiplexers or switches is described +/// to the I2C protocol stack with a single I2C bus configuration which +/// specifies the I2C bus frequency. +/// +/// An I2C bus with switches and multiplexers use an I2C bus configuration +/// to describe each of the unique settings for the switches and multiplexers +/// and the I2C bus frequency. However the I2C bus configuration management +/// protocol only needs to define the I2C bus configurations that the software +/// uses, which may be a subset of the total. +/// +/// The I2C bus configuration description includes a list of I2C devices +/// which may be accessed when this I2C bus configuration is enabled. I2C +/// devices before a switch or multiplexer must be included in one I2C bus +/// configuration while I2C devices after a switch or multiplexer are on +/// another I2C bus configuration. +/// +/// The I2C bus configuration management protocol is an optional protocol. +/// When the I2C bus configuration protocol is not defined the I2C host +/// protocol does not start and the I2C master protocol may be used for +/// other purposes such as SMBus traffic. When the I2C bus configuration +/// protocol is available, the I2C host protocol uses the I2C bus +/// configuration protocol to call into the platform specific code to set +/// the switches and multiplexers and set the maximum I2C bus frequency. +/// +/// The platform designers determine the maximum I2C bus frequency by +/// selecting a frequency which supports all of the I2C devices on the +/// I2C bus for the setting of switches and multiplexers. The platform +/// designers must validate this against the I2C device data sheets and +/// any limits of the I2C controller or bus length. +/// +/// During I2C device enumeration, the I2C bus driver retrieves the I2C +/// bus configuration that must be used to perform I2C transactions to +/// each I2C device. This I2C bus configuration value is passed into +/// the I2C host protocol to identify the I2C bus configuration required +/// to access a specific I2C device. The I2C host protocol calls +/// EnableBusConfiguration() to set the switches and multiplexers in the +/// I2C bus and the I2C clock frequency. The I2C host protocol may +/// optimize calls to EnableBusConfiguration() by only making the call +/// when the I2C bus configuration value changes between I2C requests. +/// +/// When I2C transactions are required on the same I2C bus to change the +/// state of multiplexers or switches, the I2C master protocol must be +/// used to perform the necessary I2C transactions. +/// +/// It is up to the platform specific code to choose the proper I2C bus +/// configuration when ExitBootServices() is called. Some operating systems +/// are not able to manage the I2C bus configurations and must use the I2C +/// bus configuration that is established by the platform firmware before +/// ExitBootServices() returns. +/// +typedef struct _EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL; + + +/** + Enable access to an I2C bus configuration. + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + Reconfigure the switches and multiplexers in the I2C bus to enable + access to a specific I2C bus configuration. Also select the maximum + clock frequency for this I2C bus configuration. + + This routine uses the I2C Master protocol to perform I2C transactions + on the local bus. This eliminates any recursion in the I2C stack for + configuration transactions on the same I2C bus. This works because the + local I2C bus is idle while the I2C bus configuration is being enabled. + + If I2C transactions must be performed on other I2C busses, then the + EFI_I2C_HOST_PROTOCOL, the EFI_I2C_IO_PROTCOL, or a third party I2C + driver interface for a specific device must be used. This requirement + is because the I2C host protocol controls the flow of requests to the + I2C controller. Use the EFI_I2C_HOST_PROTOCOL when the I2C device is + not enumerated by the EFI_I2C_ENUMERATE_PROTOCOL. Use a protocol + produced by a third party driver when it is available or the + EFI_I2C_IO_PROTOCOL when the third party driver is not available but + the device is enumerated with the EFI_I2C_ENUMERATE_PROTOCOL. + + When Event is NULL, EnableI2cBusConfiguration operates synchronously + and returns the I2C completion status as its return value. + + @param[in] This Pointer to an EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL + structure. + @param[in] I2cBusConfiguration Index of an I2C bus configuration. All + values in the range of zero to N-1 are + valid where N is the total number of I2C + bus configurations for an I2C bus. + @param[in] Event Event to signal when the transaction is complete + @param[out] I2cStatus Buffer to receive the transaction status. + + @return When Event is NULL, EnableI2cBusConfiguration operates synchrouously + and returns the I2C completion status as its return value. In this case it is + recommended to use NULL for I2cStatus. The values returned from + EnableI2cBusConfiguration are: + + @retval EFI_SUCCESS The asynchronous bus configuration request + was successfully started when Event is not + NULL. + @retval EFI_SUCCESS The bus configuration request completed + successfully when Event is NULL. + @retval EFI_DEVICE_ERROR The bus configuration failed. + @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL_ENABLE_I2C_BUS_CONFIGURATION) ( + IN CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *This, + IN UINTN I2cBusConfiguration, + IN EFI_EVENT Event OPTIONAL, + IN EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// I2C bus configuration management protocol +/// +struct _EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL { + /// + /// Enable an I2C bus configuration for use. + /// + EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL_ENABLE_I2C_BUS_CONFIGURATION EnableI2cBusConfiguration; +}; + +/// +/// Reference to variable defined in the .DEC file +/// +extern EFI_GUID gEfiI2cBusConfigurationManagementProtocolGuid; + +#endif // __I2C_BUS_CONFIGURATION_MANAGEMENT_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cEnumerate.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cEnumerate.h new file mode 100644 index 0000000..85fbf4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cEnumerate.h @@ -0,0 +1,110 @@ +/** @file + I2C Device Enumerate Protocol as defined in the PI 1.3 specification. + + This protocol supports the enumerations of device on the I2C bus. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.3. + +**/ + +#ifndef __I2C_ENUMERATE_H__ +#define __I2C_ENUMERATE_H__ + +#include + +#define EFI_I2C_ENUMERATE_PROTOCOL_GUID { 0xda8cd7c4, 0x1c00, 0x49e2, { 0x80, 0x3e, 0x52, 0x14, 0xe7, 0x01, 0x89, 0x4c }} + +typedef struct _EFI_I2C_ENUMERATE_PROTOCOL EFI_I2C_ENUMERATE_PROTOCOL; + +/** + Enumerate the I2C devices + + This function enables the caller to traverse the set of I2C devices + on an I2C bus. + + @param[in] This The platform data for the next device on + the I2C bus was returned successfully. + @param[in, out] Device Pointer to a buffer containing an + EFI_I2C_DEVICE structure. Enumeration is + started by setting the initial EFI_I2C_DEVICE + structure pointer to NULL. The buffer + receives an EFI_I2C_DEVICE structure pointer + to the next I2C device. + + @retval EFI_SUCCESS The platform data for the next device on + the I2C bus was returned successfully. + @retval EFI_INVALID_PARAMETER Device is NULL + @retval EFI_NO_MAPPING *Device does not point to a valid + EFI_I2C_DEVICE structure returned in a + previous call Enumerate(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_ENUMERATE_PROTOCOL_ENUMERATE) ( + IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This, + IN OUT CONST EFI_I2C_DEVICE **Device + ); + +/** + Get the requested I2C bus frequency for a specified bus configuration. + + This function returns the requested I2C bus clock frequency for the + I2cBusConfiguration. This routine is provided for diagnostic purposes + and is meant to be called after calling Enumerate to get the + I2cBusConfiguration value. + + @param[in] This Pointer to an EFI_I2C_ENUMERATE_PROTOCOL + structure. + @param[in] I2cBusConfiguration I2C bus configuration to access the I2C + device + @param[out] *BusClockHertz Pointer to a buffer to receive the I2C + bus clock frequency in Hertz + + @retval EFI_SUCCESS The I2C bus frequency was returned + successfully. + @retval EFI_INVALID_PARAMETER BusClockHertz was NULL + @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_ENUMERATE_PROTOCOL_GET_BUS_FREQUENCY) ( + IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This, + IN UINTN I2cBusConfiguration, + OUT UINTN *BusClockHertz + ); + +/// +/// I2C Enumerate protocol +/// +struct _EFI_I2C_ENUMERATE_PROTOCOL { + /// + /// Traverse the set of I2C devices on an I2C bus. This routine + /// returns the next I2C device on an I2C bus. + /// + EFI_I2C_ENUMERATE_PROTOCOL_ENUMERATE Enumerate; + + /// + /// Get the requested I2C bus frequency for a specified bus + /// configuration. + /// + EFI_I2C_ENUMERATE_PROTOCOL_GET_BUS_FREQUENCY GetBusFrequency; +}; + +/// +/// Reference to variable defined in the .DEC file +/// +extern EFI_GUID gEfiI2cEnumerateProtocolGuid; + +#endif // __I2C_ENUMERATE_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cHost.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cHost.h new file mode 100644 index 0000000..c4340c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cHost.h @@ -0,0 +1,152 @@ +/** @file + I2C Host Protocol as defined in the PI 1.3 specification. + + This protocol provides callers with the ability to do I/O transactions + to all of the devices on the I2C bus. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.3. + +**/ + +#ifndef __I2C_HOST_H__ +#define __I2C_HOST_H__ + +#include + +#define EFI_I2C_HOST_PROTOCOL_GUID { 0xa5aab9e3, 0xc727, 0x48cd, { 0x8b, 0xbf, 0x42, 0x72, 0x33, 0x85, 0x49, 0x48 }} + +/// +/// I2C Host Protocol +/// +/// The I2C bus driver uses the services of the EFI_I2C_HOST_PROTOCOL +/// to produce an instance of the EFI_I2C_IO_PROTOCOL for each I2C +/// device on an I2C bus. +/// +/// The EFI_I2C_HOST_PROTOCOL exposes an asynchronous interface to +/// callers to perform transactions to any device on the I2C bus. +/// Internally, the I2C host protocol manages the flow of the I2C +/// transactions to the host controller, keeping them in FIFO order. +/// Prior to each transaction, the I2C host protocol ensures that the +/// switches and multiplexers are properly configured. The I2C host +/// protocol then starts the transaction on the host controller using +/// the EFI_I2C_MASTER_PROTOCOL. +/// +typedef struct _EFI_I2C_HOST_PROTOCOL EFI_I2C_HOST_PROTOCOL; + + +/** + Queue an I2C transaction for execution on the I2C controller. + + This routine must be called at or below TPL_NOTIFY. For + synchronous requests this routine must be called at or below + TPL_CALLBACK. + + The I2C host protocol uses the concept of I2C bus configurations + to describe the I2C bus. An I2C bus configuration is defined as + a unique setting of the multiplexers and switches in the I2C bus + which enable access to one or more I2C devices. When using a + switch to divide a bus, due to bus frequency differences, the + I2C bus configuration management protocol defines an I2C bus + configuration for the I2C devices on each side of the switch. + When using a multiplexer, the I2C bus configuration management + defines an I2C bus configuration for each of the selector values + required to control the multiplexer. See Figure 1 in the I2C -bus + specification and user manual for a complex I2C bus configuration. + + The I2C host protocol processes all transactions in FIFO order. + Prior to performing the transaction, the I2C host protocol calls + EnableI2cBusConfiguration to reconfigure the switches and + multiplexers in the I2C bus enabling access to the specified I2C + device. The EnableI2cBusConfiguration also selects the I2C bus + frequency for the I2C device. After the I2C bus is configured, + the I2C host protocol calls the I2C master protocol to start the + I2C transaction. + + When Event is NULL, QueueRequest() operates synchronously and + returns the I2C completion status as its return value. + + When Event is not NULL, QueueRequest() synchronously returns + EFI_SUCCESS indicating that the asynchronously I2C transaction was + queued. The values above are returned in the buffer pointed to by + I2cStatus upon the completion of the I2C transaction when I2cStatus + is not NULL. + + @param[in] This Pointer to an EFI_I2C_HOST_PROTOCOL structure. + @param[in] I2cBusConfiguration I2C bus configuration to access the I2C + device + @param[in] SlaveAddress Address of the device on the I2C bus. Set + the I2C_ADDRESSING_10_BIT when using 10-bit + addresses, clear this bit for 7-bit addressing. + Bits 0-6 are used for 7-bit I2C slave addresses + and bits 0-9 are used for 10-bit I2C slave + addresses. + @param[in] Event Event to signal for asynchronous transactions, + NULL for synchronous transactions + @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET structure + describing the I2C transaction + @param[out] I2cStatus Optional buffer to receive the I2C transaction + completion status + + @retval EFI_SUCCESS The asynchronous transaction was successfully + queued when Event is not NULL. + @retval EFI_SUCCESS The transaction completed successfully when + Event is NULL. + @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is + too large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the + transaction. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_NOT_FOUND Reserved bit set in the SlaveAddress parameter + @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value + @retval EFI_NO_RESPONSE The I2C device is not responding to the slave + address. EFI_DEVICE_ERROR will be returned + if the controller cannot distinguish when the + NACK occurred. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction + @retval EFI_UNSUPPORTED The controller does not support the requested + transaction. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_HOST_PROTOCOL_QUEUE_REQUEST) ( + IN CONST EFI_I2C_HOST_PROTOCOL *This, + IN UINTN I2cBusConfiguration, + IN UINTN SlaveAddress, + IN EFI_EVENT Event OPTIONAL, + IN EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// I2C Host Protocol +/// +struct _EFI_I2C_HOST_PROTOCOL { + /// + /// Queue an I2C transaction for execution on the I2C bus + /// + EFI_I2C_HOST_PROTOCOL_QUEUE_REQUEST QueueRequest; + + /// + /// Pointer to an EFI_I2C_CONTROLLER_CAPABILITIES data structure + /// containing the capabilities of the I2C host controller. + /// + CONST EFI_I2C_CONTROLLER_CAPABILITIES *I2cControllerCapabilities; +}; + +/// +/// Reference to variable defined in the .DEC file +/// +extern EFI_GUID gEfiI2cHostProtocolGuid; + +#endif // __I2C_HOST_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cIo.h new file mode 100644 index 0000000..d70710f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cIo.h @@ -0,0 +1,172 @@ +/** @file + I2C I/O Protocol as defined in the PI 1.3 specification. + + The EFI I2C I/O protocol enables the user to manipulate a single + I2C device independent of the host controller and I2C design. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.3. + +**/ + +#ifndef __I2C_IO_H__ +#define __I2C_IO_H__ + +#include + +#define EFI_I2C_IO_PROTOCOL_GUID { 0xb60a3e6b, 0x18c4, 0x46e5, { 0xa2, 0x9a, 0xc9, 0xa1, 0x06, 0x65, 0xa2, 0x8e }} + +/// +/// I2C I/O protocol +/// +/// The I2C IO protocol enables access to a specific device on the I2C +/// bus. +/// +/// Each I2C device is identified uniquely in the system by the tuple +/// DeviceGuid:DeviceIndex. The DeviceGuid represents the manufacture +/// and part number and is provided by the silicon vendor or the third +/// party I2C device driver writer. The DeviceIndex identifies the part +/// within the system by using a unique number and is created by the +/// board designer or the writer of the EFI_I2C_ENUMERATE_PROTOCOL. +/// +/// I2C slave addressing is abstracted to validate addresses and limit +/// operation to the specified I2C device. The third party providing +/// the I2C device support provides an ordered list of slave addresses +/// for the I2C device required to implement the EFI_I2C_ENUMERATE_PROTOCOL. +/// The order of the list must be preserved. +/// +typedef struct _EFI_I2C_IO_PROTOCOL EFI_I2C_IO_PROTOCOL; + + +/** + Queue an I2C transaction for execution on the I2C device. + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + This routine queues an I2C transaction to the I2C controller for + execution on the I2C bus. + + When Event is NULL, QueueRequest() operates synchronously and returns + the I2C completion status as its return value. + + When Event is not NULL, QueueRequest() synchronously returns EFI_SUCCESS + indicating that the asynchronous I2C transaction was queued. The values + above are returned in the buffer pointed to by I2cStatus upon the + completion of the I2C transaction when I2cStatus is not NULL. + + The upper layer driver writer provides the following to the platform + vendor: + + 1. Vendor specific GUID for the I2C part + 2. Guidance on proper construction of the slave address array when the + I2C device uses more than one slave address. The I2C bus protocol + uses the SlaveAddressIndex to perform relative to physical address + translation to access the blocks of hardware within the I2C device. + + @param[in] This Pointer to an EFI_I2C_IO_PROTOCOL structure. + @param[in] SlaveAddressIndex Index value into an array of slave addresses + for the I2C device. The values in the array + are specified by the board designer, with the + third party I2C device driver writer providing + the slave address order. + + For devices that have a single slave address, + this value must be zero. If the I2C device + uses more than one slave address then the + third party (upper level) I2C driver writer + needs to specify the order of entries in the + slave address array. + + \ref ThirdPartyI2cDrivers "Third Party I2C + Drivers" section in I2cMaster.h. + @param[in] Event Event to signal for asynchronous transactions, + NULL for synchronous transactions + @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET structure + describing the I2C transaction + @param[out] I2cStatus Optional buffer to receive the I2C transaction + completion status + + @retval EFI_SUCCESS The asynchronous transaction was successfully + queued when Event is not NULL. + @retval EFI_SUCCESS The transaction completed successfully when + Event is NULL. + @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is too + large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the + transaction. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL. + @retval EFI_NO_MAPPING The EFI_I2C_HOST_PROTOCOL could not set the + bus configuration required to access this I2C + device. + @retval EFI_NO_RESPONSE The I2C device is not responding to the slave + address selected by SlaveAddressIndex. + EFI_DEVICE_ERROR will be returned if the + controller cannot distinguish when the NACK + occurred. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction + @retval EFI_UNSUPPORTED The controller does not support the requested + transaction. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_IO_PROTOCOL_QUEUE_REQUEST) ( + IN CONST EFI_I2C_IO_PROTOCOL *This, + IN UINTN SlaveAddressIndex, + IN EFI_EVENT Event OPTIONAL, + IN EFI_I2C_REQUEST_PACKET *RequestPacket, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// I2C I/O protocol +/// +struct _EFI_I2C_IO_PROTOCOL { + /// + /// Queue an I2C transaction for execution on the I2C device. + /// + EFI_I2C_IO_PROTOCOL_QUEUE_REQUEST QueueRequest; + + /// + /// Unique value assigned by the silicon manufacture or the third + /// party I2C driver writer for the I2C part. This value logically + /// combines both the manufacture name and the I2C part number into + /// a single value specified as a GUID. + /// + CONST EFI_GUID *DeviceGuid; + + /// + /// Unique ID of the I2C part within the system + /// + UINT32 DeviceIndex; + + /// + /// Hardware revision - ACPI _HRV value. See the Advanced Configuration + /// and Power Interface Specification, Revision 5.0 for the field format + /// and the Plug and play support for I2C web-page for restriction on values. + /// + UINT32 HardwareRevision; + + /// + /// Pointer to an EFI_I2C_CONTROLLER_CAPABILITIES data structure containing + /// the capabilities of the I2C host controller. + /// + CONST EFI_I2C_CONTROLLER_CAPABILITIES *I2cControllerCapabilities; +}; + +/// +/// Reference to variable defined in the .DEC file +/// +extern EFI_GUID gEfiI2cIoProtocolGuid; + +#endif // __I2C_IO_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cMaster.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cMaster.h new file mode 100644 index 0000000..b3c6334 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/I2cMaster.h @@ -0,0 +1,192 @@ +/** @file + I2C Master Protocol as defined in the PI 1.3 specification. + + This protocol manipulates the I2C host controller to perform transactions as a master + on the I2C bus using the current state of any switches or multiplexers in the I2C bus. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.3. + +**/ + +#ifndef __I2C_MASTER_H__ +#define __I2C_MASTER_H__ + +#include + +#define EFI_I2C_MASTER_PROTOCOL_GUID { 0xcd72881f, 0x45b5, 0x4feb, { 0x98, 0xc8, 0x31, 0x3d, 0xa8, 0x11, 0x74, 0x62 }} + +typedef struct _EFI_I2C_MASTER_PROTOCOL EFI_I2C_MASTER_PROTOCOL; + +/** + Set the frequency for the I2C clock line. + + This routine must be called at or below TPL_NOTIFY. + + The software and controller do a best case effort of using the specified + frequency for the I2C bus. If the frequency does not match exactly then + the I2C master protocol selects the next lower frequency to avoid + exceeding the operating conditions for any of the I2C devices on the bus. + For example if 400 KHz was specified and the controller's divide network + only supports 402 KHz or 398 KHz then the I2C master protocol selects 398 + KHz. If there are not lower frequencies available, then return + EFI_UNSUPPORTED. + + @param[in] This Pointer to an EFI_I2C_MASTER_PROTOCOL structure + @param[in] BusClockHertz Pointer to the requested I2C bus clock frequency + in Hertz. Upon return this value contains the + actual frequency in use by the I2C controller. + + @retval EFI_SUCCESS The bus frequency was set successfully. + @retval EFI_ALREADY_STARTED The controller is busy with another transaction. + @retval EFI_INVALID_PARAMETER BusClockHertz is NULL + @retval EFI_UNSUPPORTED The controller does not support this frequency. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_MASTER_PROTOCOL_SET_BUS_FREQUENCY) ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN OUT UINTN *BusClockHertz + ); + +/** + Reset the I2C controller and configure it for use + + This routine must be called at or below TPL_NOTIFY. + + The I2C controller is reset. The caller must call SetBusFrequench() after + calling Reset(). + + @param[in] This Pointer to an EFI_I2C_MASTER_PROTOCOL structure. + + @retval EFI_SUCCESS The reset completed successfully. + @retval EFI_ALREADY_STARTED The controller is busy with another transaction. + @retval EFI_DEVICE_ERROR The reset operation failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_MASTER_PROTOCOL_RESET) ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This + ); + +/** + Start an I2C transaction on the host controller. + + This routine must be called at or below TPL_NOTIFY. For synchronous + requests this routine must be called at or below TPL_CALLBACK. + + This function initiates an I2C transaction on the controller. To + enable proper error handling by the I2C protocol stack, the I2C + master protocol does not support queuing but instead only manages + one I2C transaction at a time. This API requires that the I2C bus + is in the correct configuration for the I2C transaction. + + The transaction is performed by sending a start-bit and selecting the + I2C device with the specified I2C slave address and then performing + the specified I2C operations. When multiple operations are requested + they are separated with a repeated start bit and the slave address. + The transaction is terminated with a stop bit. + + When Event is NULL, StartRequest operates synchronously and returns + the I2C completion status as its return value. + + When Event is not NULL, StartRequest synchronously returns EFI_SUCCESS + indicating that the I2C transaction was started asynchronously. The + transaction status value is returned in the buffer pointed to by + I2cStatus upon the completion of the I2C transaction when I2cStatus + is not NULL. After the transaction status is returned the Event is + signaled. + + Note: The typical consumer of this API is the I2C host protocol. + Extreme care must be taken by other consumers of this API to prevent + confusing the third party I2C drivers due to a state change at the + I2C device which the third party I2C drivers did not initiate. I2C + platform specific code may use this API within these guidelines. + + @param[in] This Pointer to an EFI_I2C_MASTER_PROTOCOL structure. + @param[in] SlaveAddress Address of the device on the I2C bus. Set the + I2C_ADDRESSING_10_BIT when using 10-bit addresses, + clear this bit for 7-bit addressing. Bits 0-6 + are used for 7-bit I2C slave addresses and bits + 0-9 are used for 10-bit I2C slave addresses. + @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET + structure describing the I2C transaction. + @param[in] Event Event to signal for asynchronous transactions, + NULL for asynchronous transactions + @param[out] I2cStatus Optional buffer to receive the I2C transaction + completion status + + @retval EFI_SUCCESS The asynchronous transaction was successfully + started when Event is not NULL. + @retval EFI_SUCCESS The transaction completed successfully when + Event is NULL. + @retval EFI_ALREADY_STARTED The controller is busy with another transaction. + @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is too + large. + @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the + transaction. + @retval EFI_INVALID_PARAMETER RequestPacket is NULL + @retval EFI_NOT_FOUND Reserved bit set in the SlaveAddress parameter + @retval EFI_NO_RESPONSE The I2C device is not responding to the slave + address. EFI_DEVICE_ERROR will be returned if + the controller cannot distinguish when the NACK + occurred. + @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction + @retval EFI_UNSUPPORTED The controller does not support the requested + transaction. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_I2C_MASTER_PROTOCOL_START_REQUEST) ( + IN CONST EFI_I2C_MASTER_PROTOCOL *This, + IN UINTN SlaveAddress, + IN EFI_I2C_REQUEST_PACKET *RequestPacket, + IN EFI_EVENT Event OPTIONAL, + OUT EFI_STATUS *I2cStatus OPTIONAL + ); + +/// +/// I2C master mode protocol +/// +/// This protocol manipulates the I2C host controller to perform transactions as a +/// master on the I2C bus using the current state of any switches or multiplexers +/// in the I2C bus. +/// +struct _EFI_I2C_MASTER_PROTOCOL { + /// + /// Set the clock frequency for the I2C bus. + /// + EFI_I2C_MASTER_PROTOCOL_SET_BUS_FREQUENCY SetBusFrequency; + + /// + /// Reset the I2C host controller. + /// + EFI_I2C_MASTER_PROTOCOL_RESET Reset; + + /// + /// Start an I2C transaction in master mode on the host controller. + /// + EFI_I2C_MASTER_PROTOCOL_START_REQUEST StartRequest; + + /// + /// Pointer to an EFI_I2C_CONTROLLER_CAPABILITIES data structure containing + /// the capabilities of the I2C host controller. + /// + CONST EFI_I2C_CONTROLLER_CAPABILITIES *I2cControllerCapabilities; +}; + +extern EFI_GUID gEfiI2cMasterProtocolGuid; + +#endif // __I2C_MASTER_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IScsiInitiatorName.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IScsiInitiatorName.h new file mode 100644 index 0000000..bfc6a41 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IScsiInitiatorName.h @@ -0,0 +1,87 @@ +/** @file + EFI_ISCSI_INITIATOR_NAME_PROTOCOL as defined in UEFI 2.0. + It provides the ability to get and set the iSCSI Initiator Name. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ISCSI_INITIATOR_NAME_H__ +#define __ISCSI_INITIATOR_NAME_H__ + +#define EFI_ISCSI_INITIATOR_NAME_PROTOCOL_GUID \ +{ \ + 0x59324945, 0xec44, 0x4c0d, {0xb1, 0xcd, 0x9d, 0xb1, 0x39, 0xdf, 0x7, 0xc } \ +} + +typedef struct _EFI_ISCSI_INITIATOR_NAME_PROTOCOL EFI_ISCSI_INITIATOR_NAME_PROTOCOL; + +/** + Retrieves the current set value of iSCSI Initiator Name. + + @param This Pointer to the EFI_ISCSI_INITIATOR_NAME_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer / Actual size of the + variable data buffer. + @param Buffer Pointer to the buffer for data to be read. The data is a null-terminated UTF-8 encoded string. + The maximum length is 223 characters, including the null-terminator. + + @retval EFI_SUCCESS Data was successfully retrieved into the provided buffer and the + BufferSize was sufficient to handle the iSCSI initiator name + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the result. + @retval EFI_INVALID_PARAMETER BufferSize or Buffer is NULL. + @retval EFI_DEVICE_ERROR The iSCSI initiator name could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISCSI_INITIATOR_NAME_GET)( + IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + + + +/** + Sets the iSCSI Initiator Name. + + @param This Pointer to the EFI_ISCSI_INITIATOR_NAME_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer. + @param Buffer Pointer to the buffer for data to be written. The data is a null-terminated UTF-8 encoded string. + The maximum length is 223 characters, including the null-terminator. + + @retval EFI_SUCCESS Data was successfully stored by the protocol. + @retval EFI_UNSUPPORTED Platform policies do not allow for data to be written. + @retval EFI_INVALID_PARAMETER BufferSize or Buffer is NULL, or BufferSize exceeds the maximum allowed limit. + @retval EFI_DEVICE_ERROR The data could not be stored due to a hardware error. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the data. + @retval EFI_PROTOCOL_ERROR Input iSCSI initiator name does not adhere to RFC 3720 + (and other related protocols) + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_ISCSI_INITIATOR_NAME_SET)( + IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/// +/// iSCSI Initiator Name Protocol for setting and obtaining the iSCSI Initiator Name. +/// +struct _EFI_ISCSI_INITIATOR_NAME_PROTOCOL { + EFI_ISCSI_INITIATOR_NAME_GET Get; + EFI_ISCSI_INITIATOR_NAME_SET Set; +}; + +extern EFI_GUID gEfiIScsiInitiatorNameProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IdeControllerInit.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IdeControllerInit.h new file mode 100644 index 0000000..3477e3c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IdeControllerInit.h @@ -0,0 +1,565 @@ +/** @file + This file declares EFI IDE Controller Init Protocol + + The EFI_IDE_CONTROLLER_INIT_PROTOCOL provides the chipset-specific information + to the driver entity. This protocol is mandatory for IDE controllers if the + IDE devices behind the controller are to be enumerated by a driver entity. + + There can only be one instance of EFI_IDE_CONTROLLER_INIT_PROTOCOL for each IDE + controller in a system. It is installed on the handle that corresponds to the + IDE controller. A driver entity that wishes to manage an IDE bus and possibly + IDE devices in a system will have to retrieve the EFI_IDE_CONTROLLER_INIT_PROTOCOL + instance that is associated with the controller to be managed. + + A device handle for an IDE controller must contain an EFI_DEVICE_PATH_PROTOCOL. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards. + +**/ + +#ifndef _EFI_IDE_CONTROLLER_INIT_PROTOCOL_H_ +#define _EFI_IDE_CONTROLLER_INIT_PROTOCOL_H_ + +#include + +/// +/// Global ID for the EFI_IDE_CONTROLLER_INIT_PROTOCOL. +/// +#define EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID \ + { \ + 0xa1e37052, 0x80d9, 0x4e65, {0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9 } \ + } + +/// +/// Forward declaration for EFI_IDE_CONTROLLER_INIT_PROTOCOL. +/// +typedef struct _EFI_IDE_CONTROLLER_INIT_PROTOCOL EFI_IDE_CONTROLLER_INIT_PROTOCOL; + +/// +/// The phase of the IDE Controller enumeration. +/// +typedef enum { + /// + /// The driver entity is about to begin enumerating the devices + /// behind the specified channel. This notification can be used to + /// perform any chipset-specific programming. + /// + EfiIdeBeforeChannelEnumeration, + /// + /// The driver entity has completed enumerating the devices + /// behind the specified channel. This notification can be used to + /// perform any chipset-specific programming. + /// + EfiIdeAfterChannelEnumeration, + /// + /// The driver entity is about to reset the devices behind the + /// specified channel. This notification can be used to perform any + /// chipset-specific programming. + /// + EfiIdeBeforeChannelReset, + /// + /// The driver entity has completed resetting the devices behind + /// the specified channel. This notification can be used to perform + /// any chipset-specific programming. + /// + EfiIdeAfterChannelReset, + /// + /// The driver entity is about to detect the presence of devices + /// behind the specified channel. This notification can be used to + /// set up the bus signals to default levels or for implementing + /// predelays. + /// + EfiIdeBusBeforeDevicePresenceDetection, + /// + /// The driver entity is done with detecting the presence of + /// devices behind the specified channel. This notification can be + /// used to perform any chipset-specific programming. + /// + EfiIdeBusAfterDevicePresenceDetection, + /// + /// The IDE bus is requesting the IDE controller driver to + /// reprogram the IDE controller hardware and thereby reset all + /// the mode and timing settings to default settings. + /// + EfiIdeResetMode, + EfiIdeBusPhaseMaximum +} EFI_IDE_CONTROLLER_ENUM_PHASE; + +/// +/// This extended mode describes the SATA physical protocol. +/// SATA physical layers can operate at different speeds. +/// These speeds are defined below. Various PATA protocols +/// and associated modes are not applicable to SATA devices. +/// +typedef enum { + EfiAtaSataTransferProtocol +} EFI_ATA_EXT_TRANSFER_PROTOCOL; + +/// +/// Automatically detects the optimum SATA speed. +/// +#define EFI_SATA_AUTO_SPEED 0 + +/// +/// Indicates a first-generation (Gen1) SATA speed. +/// +#define EFI_SATA_GEN1_SPEED 1 + +/// +/// Indicates a second-generation (Gen2) SATA speed. +/// +#define EFI_SATA_GEN2_SPEED 2 + +/// +/// EFI_ATA_MODE structure. +/// +typedef struct { + BOOLEAN Valid; ///< TRUE if Mode is valid. + UINT32 Mode; ///< The actual ATA mode. This field is not a bit map. +} EFI_ATA_MODE; + +/// +/// EFI_ATA_EXTENDED_MODE structure +/// +typedef struct { + /// + /// An enumeration defining various transfer protocols other than the protocols + /// that exist at the time this specification was developed (i.e., PIO, single + /// word DMA, multiword DMA, and UDMA). Each transfer protocol is associated + /// with a mode. The various transfer protocols are defined by the ATA/ATAPI + /// specification. This enumeration makes the interface extensible because we + /// can support new transport protocols beyond UDMA. Type EFI_ATA_EXT_TRANSFER_PROTOCOL + /// is defined below. + /// + EFI_ATA_EXT_TRANSFER_PROTOCOL TransferProtocol; + /// + /// The mode for operating the transfer protocol that is identified by TransferProtocol. + /// + UINT32 Mode; +} EFI_ATA_EXTENDED_MODE; + +/// +/// EFI_ATA_COLLECTIVE_MODE structure. +/// +typedef struct { + /// + /// This field specifies the PIO mode. PIO modes are defined in the ATA/ATAPI + /// specification. The ATA/ATAPI specification defines the enumeration. In + /// other words, a value of 1 in this field means PIO mode 1. The actual meaning + /// of PIO mode 1 is governed by the ATA/ATAPI specification. Type EFI_ATA_MODE + /// is defined below. + /// + EFI_ATA_MODE PioMode; + /// + /// This field specifies the single word DMA mode. Single word DMA modes are defined + /// in the ATA/ATAPI specification, versions 1 and 2. Single word DMA support was + /// obsoleted in the ATA/ATAPI specification, version 3. Therefore, most devices and + /// controllers will not support this transfer mode. The ATA/ATAPI specification defines + /// the enumeration. In other words, a value of 1 in this field means single word DMA + /// mode 1. The actual meaning of single word DMA mode 1 is governed by the ATA/ + /// ATAPI specification. + /// + EFI_ATA_MODE SingleWordDmaMode; + /// + /// This field specifies the multiword DMA mode. Various multiword DMA modes are + /// defined in the ATA/ATAPI specification. A value of 1 in this field means multiword + /// DMA mode 1. The actual meaning of multiword DMA mode 1 is governed by the + /// ATA/ATAPI specification. + /// + EFI_ATA_MODE MultiWordDmaMode; + /// + /// This field specifies the ultra DMA (UDMA) mode. UDMA modes are defined in the + /// ATA/ATAPI specification. A value of 1 in this field means UDMA mode 1. The + /// actual meaning of UDMA mode 1 is governed by the ATA/ATAPI specification. + /// + EFI_ATA_MODE UdmaMode; + /// + /// The number of extended-mode bitmap entries. Extended modes describe transfer + /// protocols beyond PIO, single word DMA, multiword DMA, and UDMA. This field + /// can be zero and provides extensibility. + /// + UINT32 ExtModeCount; + /// + /// ExtModeCount number of entries. Each entry represents a transfer protocol other + /// than the ones defined above (i.e., PIO, single word DMA, multiword DMA, and + /// UDMA). This field is defined for extensibility. At this time, only one extended + /// transfer protocol is defined to cover SATA transfers. Type + /// EFI_ATA_EXTENDED_MODE is defined below. + /// + EFI_ATA_EXTENDED_MODE ExtMode[1]; +} EFI_ATA_COLLECTIVE_MODE; + +/// +/// EFI_ATA_IDENTIFY_DATA & EFI_ATAPI_IDENTIFY_DATA structure +/// +/// The definition of these two structures is not part of the protocol +/// definition because the ATA/ATAPI Specification controls the definition +/// of all the fields. The ATA/ATAPI Specification can obsolete old fields +/// or redefine existing fields. +typedef ATA_IDENTIFY_DATA EFI_ATA_IDENTIFY_DATA; +typedef ATAPI_IDENTIFY_DATA EFI_ATAPI_IDENTIFY_DATA; + +/// +/// This flag indicates whether the IDENTIFY data is a response from an ATA device +/// (EFI_ATA_IDENTIFY_DATA) or response from an ATAPI device +/// (EFI_ATAPI_IDENTIFY_DATA). According to the ATA/ATAPI specification, +/// EFI_IDENTIFY_DATA is for an ATA device if bit 15 of the Config field is zero. +/// The Config field is common to both EFI_ATA_IDENTIFY_DATA and +/// EFI_ATAPI_IDENTIFY_DATA. +/// +#define EFI_ATAPI_DEVICE_IDENTIFY_DATA 0x8000 + +/// +/// EFI_IDENTIFY_DATA structure. +/// +typedef union { + /// + /// The data that is returned by an ATA device upon successful completion + /// of the ATA IDENTIFY_DEVICE command. + /// + EFI_ATA_IDENTIFY_DATA AtaData; + /// + /// The data that is returned by an ATAPI device upon successful completion + /// of the ATA IDENTIFY_PACKET_DEVICE command. + /// + EFI_ATAPI_IDENTIFY_DATA AtapiData; +} EFI_IDENTIFY_DATA; + +/** + Returns the information about the specified IDE channel. + + This function can be used to obtain information about a particular IDE channel. + The driver entity uses this information during the enumeration process. + + If Enabled is set to FALSE, the driver entity will not scan the channel. Note + that it will not prevent an operating system driver from scanning the channel. + + For most of today's controllers, MaxDevices will either be 1 or 2. For SATA + controllers, this value will always be 1. SATA configurations can contain SATA + port multipliers. SATA port multipliers behave like SATA bridges and can support + up to 16 devices on the other side. If a SATA port out of the IDE controller + is connected to a port multiplier, MaxDevices will be set to the number of SATA + devices that the port multiplier supports. Because today's port multipliers + support up to fifteen SATA devices, this number can be as large as fifteen. The IDE + bus driver is required to scan for the presence of port multipliers behind an SATA + controller and enumerate up to MaxDevices number of devices behind the port + multiplier. + + In this context, the devices behind a port multiplier constitute a channel. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel Zero-based channel number. + @param[out] Enabled TRUE if this channel is enabled. Disabled channels + are not scanned to see if any devices are present. + @param[out] MaxDevices The maximum number of IDE devices that the bus driver + can expect on this channel. For the ATA/ATAPI + specification, version 6, this number will either be + one or two. For Serial ATA (SATA) configurations with a + port multiplier, this number can be as large as fifteen. + + @retval EFI_SUCCESS Information was returned without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_GET_CHANNEL_INFO)( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + OUT BOOLEAN *Enabled, + OUT UINT8 *MaxDevices + ); + +/** + The notifications from the driver entity that it is about to enter a certain + phase of the IDE channel enumeration process. + + This function can be used to notify the IDE controller driver to perform + specific actions, including any chipset-specific initialization, so that the + chipset is ready to enter the next phase. Seven notification points are defined + at this time. + + More synchronization points may be added as required in the future. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Phase The phase during enumeration. + @param[in] Channel Zero-based channel number. + + @retval EFI_SUCCESS The notification was accepted without any errors. + @retval EFI_UNSUPPORTED Phase is not supported. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_NOT_READY This phase cannot be entered at this time; for + example, an attempt was made to enter a Phase + without having entered one or more previous + Phase. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_NOTIFY_PHASE)( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase, + IN UINT8 Channel + ); + +/** + Submits the device information to the IDE controller driver. + + This function is used by the driver entity to pass detailed information about + a particular device to the IDE controller driver. The driver entity obtains + this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData + is the pointer to the response data buffer. The IdentifyData buffer is owned + by the driver entity, and the IDE controller driver must make a local copy + of the entire buffer or parts of the buffer as needed. The original IdentifyData + buffer pointer may not be valid when + + - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or + - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point. + + The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to + compute the optimum mode for the device. These fields are not limited to the + timing information. For example, an implementation of the IDE controller driver + may examine the vendor and type/mode field to match known bad drives. + + The driver entity may submit drive information in any order, as long as it + submits information for all the devices belonging to the enumeration group + before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device + in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + should be called with IdentifyData set to NULL. The IDE controller driver may + not have any other mechanism to know whether a device is present or not. Therefore, + setting IdentifyData to NULL does not constitute an error condition. + EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a + given (Channel, Device) pair. + + @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel Zero-based channel number. + @param[in] Device Zero-based device number on the Channel. + @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command. + + @retval EFI_SUCCESS The information was accepted without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_SUBMIT_DATA)( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_IDENTIFY_DATA *IdentifyData + ); + +/** + Disqualifies specific modes for an IDE device. + + This function allows the driver entity or other drivers (such as platform + drivers) to reject certain timing modes and request the IDE controller driver + to recalculate modes. This function allows the driver entity and the IDE + controller driver to negotiate the timings on a per-device basis. This function + is useful in the case of drives that lie about their capabilities. An example + is when the IDE device fails to accept the timing modes that are calculated + by the IDE controller driver based on the response to the Identify Drive command. + + If the driver entity does not want to limit the ATA timing modes and leave that + decision to the IDE controller driver, it can either not call this function for + the given device or call this function and set the Valid flag to FALSE for all + modes that are listed in EFI_ATA_COLLECTIVE_MODE. + + The driver entity may disqualify modes for a device in any order and any number + of times. + + This function can be called multiple times to invalidate multiple modes of the + same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI + specification for more information on PIO modes. + + For Serial ATA (SATA) controllers, this member function can be used to disqualify + a higher transfer rate mode on a given channel. For example, a platform driver + may inform the IDE controller driver to not use second-generation (Gen2) speeds + for a certain SATA drive. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel The zero-based channel number. + @param[in] Device The zero-based device number on the Channel. + @param[in] BadModes The modes that the device does not support and that + should be disqualified. + + @retval EFI_SUCCESS The modes were accepted without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + @retval EFI_INVALID_PARAMETER IdentifyData is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_DISQUALIFY_MODE)( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_ATA_COLLECTIVE_MODE *BadModes + ); + +/** + Returns the information about the optimum modes for the specified IDE device. + + This function is used by the driver entity to obtain the optimum ATA modes for + a specific device. The IDE controller driver takes into account the following + while calculating the mode: + - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() + + The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + for all the devices that belong to an enumeration group before calling + EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group. + + The IDE controller driver will use controller- and possibly platform-specific + algorithms to arrive at SupportedModes. The IDE controller may base its + decision on user preferences and other considerations as well. This function + may be called multiple times because the driver entity may renegotiate the mode + with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode(). + + The driver entity may collect timing information for various devices in any + order. The driver entity is responsible for making sure that all the dependencies + are satisfied. For example, the SupportedModes information for device A that + was previously returned may become stale after a call to + EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B. + + The buffer SupportedModes is allocated by the callee because the caller does + not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE + is defined in a way that allows for future extensibility and can be of variable + length. This memory pool should be deallocated by the caller when it is no + longer necessary. + + The IDE controller driver for a Serial ATA (SATA) controller can use this + member function to force a lower speed (first-generation [Gen1] speeds on a + second-generation [Gen2]-capable hardware). The IDE controller driver can + also allow the driver entity to stay with the speed that has been negotiated + by the physical layer. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel A zero-based channel number. + @param[in] Device A zero-based device number on the Channel. + @param[out] SupportedModes The optimum modes for the device. + + @retval EFI_SUCCESS SupportedModes was returned. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + @retval EFI_INVALID_PARAMETER SupportedModes is NULL. + @retval EFI_NOT_READY Modes cannot be calculated due to a lack of + data. This error may happen if + EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() + were not called for at least one drive in the + same enumeration group. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_CALCULATE_MODE)( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes + ); + +/** + Commands the IDE controller driver to program the IDE controller hardware + so that the specified device can operate at the specified mode. + + This function is used by the driver entity to instruct the IDE controller + driver to program the IDE controller hardware to the specified modes. This + function can be called only once for a particular device. For a Serial ATA + (SATA) Advanced Host Controller Interface (AHCI) controller, no controller- + specific programming may be required. + + @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel Zero-based channel number. + @param[in] Device Zero-based device number on the Channel. + @param[in] Modes The modes to set. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data. + @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure. + The driver entity should not use this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_SET_TIMING)( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_ATA_COLLECTIVE_MODE *Modes + ); + +/// +/// Provides the basic interfaces to abstract an IDE controller. +/// +struct _EFI_IDE_CONTROLLER_INIT_PROTOCOL { + /// + /// Returns the information about a specific channel. + /// + EFI_IDE_CONTROLLER_GET_CHANNEL_INFO GetChannelInfo; + + /// + /// The notification that the driver entity is about to enter the + /// specified phase during the enumeration process. + /// + EFI_IDE_CONTROLLER_NOTIFY_PHASE NotifyPhase; + + /// + /// Submits the Drive Identify data that was returned by the device. + /// + EFI_IDE_CONTROLLER_SUBMIT_DATA SubmitData; + + /// + /// Submits information about modes that should be disqualified. The specified + /// IDE device does not support these modes and these modes should not be + /// returned by EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() + /// + EFI_IDE_CONTROLLER_DISQUALIFY_MODE DisqualifyMode; + + /// + /// Calculates and returns the optimum mode for a particular IDE device. + /// + EFI_IDE_CONTROLLER_CALCULATE_MODE CalculateMode; + + /// + /// Programs the IDE controller hardware to the default timing or per the modes + /// that were returned by the last call to EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode(). + /// + EFI_IDE_CONTROLLER_SET_TIMING SetTiming; + + /// + /// Set to TRUE if the enumeration group includes all the channels that are + /// produced by this controller. Set to FALSE if an enumeration group consists of + /// only one channel. + /// + BOOLEAN EnumAll; + + /// + /// The number of channels that are produced by this controller. Parallel ATA + /// (PATA) controllers can support up to two channels. Advanced Host Controller + /// Interface (AHCI) Serial ATA (SATA) controllers can support up to 32 channels, + /// each of which can have up to one device. In the presence of a multiplier, + /// each channel can have fifteen devices. + /// + UINT8 ChannelCount; +}; + +extern EFI_GUID gEfiIdeControllerInitProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h new file mode 100644 index 0000000..d1f8d88 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h @@ -0,0 +1,173 @@ +/** @file + This file declares Incompatible PCI Device Support Protocol + + Allows the PCI bus driver to support resource allocation for some PCI devices + that do not comply with the PCI Specification. + + @par Note: + This protocol is optional. Only those platforms that implement this protocol + will have the capability to support incompatible PCI devices. The absence of + this protocol can cause the PCI bus driver to configure these incompatible + PCI devices incorrectly. As a result, these devices may not work properly. + + The EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL is used by the PCI bus driver + to support resource allocation for some PCI devices that do not comply with the + PCI Specification. This protocol can find some incompatible PCI devices and + report their special resource requirements to the PCI bus driver. The generic + PCI bus driver does not have prior knowledge of any incompatible PCI devices. + It interfaces with the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL to find out + if a device is incompatible and to obtain the special configuration requirements + for a specific incompatible PCI device. + + This protocol is optional, and only one instance of this protocol can be present + in the system. If a platform supports this protocol, this protocol is produced + by a Driver Execution Environment (DXE) driver and must be made available before + the Boot Device Selection (BDS) phase. The PCI bus driver will look for the + presence of this protocol before it begins PCI enumeration. If this protocol + exists in a platform, it indicates that the platform has the capability to support + those incompatible PCI devices. However, final support for incompatible PCI + devices still depends on the implementation of the PCI bus driver. The PCI bus + driver may fully, partially, or not even support these incompatible devices. + + During PCI bus enumeration, the PCI bus driver will probe the PCI Base Address + Registers (BARs) for each PCI device regardless of whether the PCI device is + incompatible or not to determine the resource requirements so that the PCI bus + driver can invoke the proper PCI resources for them. Generally, this resource + information includes the following: + - Resource type + - Resource length + - Alignment + + However, some incompatible PCI devices may have special requirements. As a result, + the length or the alignment that is derived through BAR probing may not be exactly + the same as the actual resource requirement of the device. For example, there + are some devices that request I/O resources at a length of 0x100 from their I/O + BAR, but these incompatible devices will never work correctly if an odd I/O base + address, such as 0x100, 0x300, or 0x500, is assigned to the BAR. Instead, these + devices request an even base address, such as 0x200 or 0x400. The Incompatible + PCI Device Support Protocol can then be used to obtain these special resource + requirements for these incompatible PCI devices. In this way, the PCI bus driver + will take special consideration for these devices during PCI resource allocation + to ensure that they can work correctly. + + This protocol may support the following incompatible PCI BAR types: + - I/O or memory length that is different from what the BAR reports + - I/O or memory alignment that is different from what the BAR reports + - Fixed I/O or memory base address + + See the Conventional PCI Specification 3.0 for the details of how a PCI BAR + reports the resource length and the alignment that it requires. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef _INCOMPATIBLE_PCI_DEVICE_SUPPORT_H_ +#define _INCOMPATIBLE_PCI_DEVICE_SUPPORT_H_ + +/// +/// Global ID for EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL +/// +#define EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL_GUID \ + { \ + 0xeb23f55a, 0x7863, 0x4ac2, {0x8d, 0x3d, 0x95, 0x65, 0x35, 0xde, 0x03, 0x75} \ + } + +/// +/// Forward declaration for EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL +/// +typedef struct _EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL; + +/** + Returns a list of ACPI resource descriptors that detail the special resource + configuration requirements for an incompatible PCI device. + + This function returns a list of ACPI resource descriptors that detail the + special resource configuration requirements for an incompatible PCI device. + + Prior to bus enumeration, the PCI bus driver will look for the presence + of the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL. Only one instance of this + protocol can be present in the system. For each PCI device that the PCI bus + driver discovers, the PCI bus driver calls this function with the device's vendor + ID, device ID, revision ID, subsystem vendor ID, and subsystem device ID. If the + VendorId, DeviceId, RevisionId, SubsystemVendorId, or SubsystemDeviceId value is + set to (UINTN)-1, that field will be ignored. The ID values that are not (UINTN)-1 + will be used to identify the current device. + + This function will only return EFI_SUCCESS. However, if the device is an + incompatible PCI device, a list of ACPI resource descriptors will be returned + in Configuration. Otherwise, NULL will be returned in Configuration instead. + The PCI bus driver does not need to allocate memory for Configuration. However, + it is the PCI bus driver's responsibility to free it. The PCI bus driver then + can configure this device with the information that is derived from this list + of resource nodes, rather than the result of BAR probing. + + Only the following two resource descriptor types from the ACPI Specification + may be used to describe the incompatible PCI device resource requirements: + - QWORD Address Space Descriptor (ACPI 2.0, section 6.4.3.5.1; also ACPI 3.0) + - End Tag (ACPI 2.0, section 6.4.2.8; also ACPI 3.0) + + The QWORD Address Space Descriptor can describe memory, I/O, and bus number + ranges for dynamic or fixed resources. The configuration of a PCI root bridge + is described with one or more QWORD Address Space Descriptors, followed by an + End Tag. See the ACPI Specification for details on the field values. + + @param[in] This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL + instance. + @param[in] VendorId A unique ID to identify the manufacturer of + the PCI device. See the Conventional PCI + Specification 3.0 for details. + @param[in] DeviceId A unique ID to identify the particular PCI + device. See the Conventional PCI Specification + 3.0 for details. + @param[in] RevisionId A PCI device-specific revision identifier. + See the Conventional PCI Specification 3.0 + for details. + @param[in] SubsystemVendorId Specifies the subsystem vendor ID. See the + Conventional PCI Specification 3.0 for details. + @param[in] SubsystemDeviceId Specifies the subsystem device ID. See the + Conventional PCI Specification 3.0 for details. + @param[out] Configuration A list of ACPI resource descriptors that detail + the configuration requirement. + + @retval EFI_SUCCESS The function always returns EFI_SUCCESS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_CHECK_DEVICE)( + IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *This, + IN UINTN VendorId, + IN UINTN DeviceId, + IN UINTN RevisionId, + IN UINTN SubsystemVendorId, + IN UINTN SubsystemDeviceId, + OUT VOID **Configuration + ); + +/// +/// Interface structure for the Incompatible PCI Device Support Protocol +/// +struct _EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL { + /// + /// Returns a list of ACPI resource descriptors that detail any special + /// resource configuration requirements if the specified device is a recognized + /// incompatible PCI device. + /// + EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_CHECK_DEVICE CheckDevice; +}; + +extern EFI_GUID gEfiIncompatiblePciDeviceSupportProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4.h new file mode 100644 index 0000000..8bd60d5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4.h @@ -0,0 +1,612 @@ +/** @file + This file defines the EFI IPv4 (Internet Protocol version 4) + Protocol interface. It is split into the following three main + sections: + - EFI IPv4 Service Binding Protocol + - EFI IPv4 Variable (deprecated in UEFI 2.4B) + - EFI IPv4 Protocol. + The EFI IPv4 Protocol provides basic network IPv4 packet I/O services, + which includes support foR a subset of the Internet Control Message + Protocol (ICMP) and may include support for the Internet Group Management + Protocol (IGMP). + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.0. + +**/ + +#ifndef __EFI_IP4_PROTOCOL_H__ +#define __EFI_IP4_PROTOCOL_H__ + +#include + +#define EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xc51711e7, 0xb4bf, 0x404a, {0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4 } \ + } + +#define EFI_IP4_PROTOCOL_GUID \ + { \ + 0x41d94cd2, 0x35b6, 0x455a, {0x82, 0x58, 0xd4, 0xe5, 0x13, 0x34, 0xaa, 0xdd } \ + } + +typedef struct _EFI_IP4_PROTOCOL EFI_IP4_PROTOCOL; + +/// +/// EFI_IP4_ADDRESS_PAIR is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE InstanceHandle; + EFI_IPv4_ADDRESS Ip4Address; + EFI_IPv4_ADDRESS SubnetMask; +} EFI_IP4_ADDRESS_PAIR; + +/// +/// EFI_IP4_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 AddressCount; + EFI_IP4_ADDRESS_PAIR AddressPairs[1]; +} EFI_IP4_VARIABLE_DATA; + +typedef struct { + /// + /// The default IPv4 protocol packets to send and receive. Ignored + /// when AcceptPromiscuous is TRUE. + /// + UINT8 DefaultProtocol; + /// + /// Set to TRUE to receive all IPv4 packets that get through the receive filters. + /// Set to FALSE to receive only the DefaultProtocol IPv4 + /// packets that get through the receive filters. + /// + BOOLEAN AcceptAnyProtocol; + /// + /// Set to TRUE to receive ICMP error report packets. Ignored when + /// AcceptPromiscuous or AcceptAnyProtocol is TRUE. + /// + BOOLEAN AcceptIcmpErrors; + /// + /// Set to TRUE to receive broadcast IPv4 packets. Ignored when + /// AcceptPromiscuous is TRUE. + /// Set to FALSE to stop receiving broadcast IPv4 packets. + /// + BOOLEAN AcceptBroadcast; + /// + /// Set to TRUE to receive all IPv4 packets that are sent to any + /// hardware address or any protocol address. + /// Set to FALSE to stop receiving all promiscuous IPv4 packets + /// + BOOLEAN AcceptPromiscuous; + /// + /// Set to TRUE to use the default IPv4 address and default routing table. + /// + BOOLEAN UseDefaultAddress; + /// + /// The station IPv4 address that will be assigned to this EFI IPv4Protocol instance. + /// + EFI_IPv4_ADDRESS StationAddress; + /// + /// The subnet address mask that is associated with the station address. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// TypeOfService field in transmitted IPv4 packets. + /// + UINT8 TypeOfService; + /// + /// TimeToLive field in transmitted IPv4 packets. + /// + UINT8 TimeToLive; + /// + /// State of the DoNotFragment bit in transmitted IPv4 packets. + /// + BOOLEAN DoNotFragment; + /// + /// Set to TRUE to send and receive unformatted packets. The other + /// IPv4 receive filters are still applied. Fragmentation is disabled for RawData mode. + /// + BOOLEAN RawData; + /// + /// The timer timeout value (number of microseconds) for the + /// receive timeout event to be associated with each assembled + /// packet. Zero means do not drop assembled packets. + /// + UINT32 ReceiveTimeout; + /// + /// The timer timeout value (number of microseconds) for the + /// transmit timeout event to be associated with each outgoing + /// packet. Zero means do not drop outgoing packets. + /// + UINT32 TransmitTimeout; +} EFI_IP4_CONFIG_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS SubnetAddress; + EFI_IPv4_ADDRESS SubnetMask; + EFI_IPv4_ADDRESS GatewayAddress; +} EFI_IP4_ROUTE_TABLE; + +typedef struct { + UINT8 Type; + UINT8 Code; +} EFI_IP4_ICMP_TYPE; + +typedef struct { + /// + /// Set to TRUE after this EFI IPv4 Protocol instance has been successfully configured. + /// + BOOLEAN IsStarted; + /// + /// The maximum packet size, in bytes, of the packet which the upper layer driver could feed. + /// + UINT32 MaxPacketSize; + /// + /// Current configuration settings. + /// + EFI_IP4_CONFIG_DATA ConfigData; + /// + /// Set to TRUE when the EFI IPv4 Protocol instance has a station address and subnet mask. + /// + BOOLEAN IsConfigured; + /// + /// Number of joined multicast groups. + /// + UINT32 GroupCount; + /// + /// List of joined multicast group addresses. + /// + EFI_IPv4_ADDRESS *GroupTable; + /// + /// Number of entries in the routing table. + /// + UINT32 RouteCount; + /// + /// Routing table entries. + /// + EFI_IP4_ROUTE_TABLE *RouteTable; + /// + /// Number of entries in the supported ICMP types list. + /// + UINT32 IcmpTypeCount; + /// + /// Array of ICMP types and codes that are supported by this EFI IPv4 Protocol driver + /// + EFI_IP4_ICMP_TYPE *IcmpTypeList; +} EFI_IP4_MODE_DATA; + +#pragma pack(1) + +typedef struct { + UINT8 HeaderLength:4; + UINT8 Version:4; + UINT8 TypeOfService; + UINT16 TotalLength; + UINT16 Identification; + UINT16 Fragmentation; + UINT8 TimeToLive; + UINT8 Protocol; + UINT16 Checksum; + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS DestinationAddress; +} EFI_IP4_HEADER; +#pragma pack() + + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_IP4_FRAGMENT_DATA; + + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + UINT32 HeaderLength; + EFI_IP4_HEADER *Header; + UINT32 OptionsLength; + VOID *Options; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_RECEIVE_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS GatewayAddress; + UINT8 Protocol; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; +} EFI_IP4_OVERRIDE_DATA; + +typedef struct { + EFI_IPv4_ADDRESS DestinationAddress; + EFI_IP4_OVERRIDE_DATA *OverrideData; //OPTIONAL + UINT32 OptionsLength; //OPTIONAL + VOID *OptionsBuffer; //OPTIONAL + UINT32 TotalDataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_TRANSMIT_DATA; + +typedef struct { + /// + /// This Event will be signaled after the Status field is updated + /// by the EFI IPv4 Protocol driver. The type of Event must be + /// EFI_NOTIFY_SIGNAL. The Task Priority Level (TPL) of + /// Event must be lower than or equal to TPL_CALLBACK. + /// + EFI_EVENT Event; + /// + /// The status that is returned to the caller at the end of the operation + /// to indicate whether this operation completed successfully. + /// + EFI_STATUS Status; + union { + /// + /// When this token is used for receiving, RxData is a pointer to the EFI_IP4_RECEIVE_DATA. + /// + EFI_IP4_RECEIVE_DATA *RxData; + /// + /// When this token is used for transmitting, TxData is a pointer to the EFI_IP4_TRANSMIT_DATA. + /// + EFI_IP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_IP4_COMPLETION_TOKEN; + +/** + Gets the current operational settings for this instance of the EFI IPv4 Protocol driver. + + The GetModeData() function returns the current operational mode data for this + driver instance. The data fields in EFI_IP4_MODE_DATA are read only. This + function is used optionally to retrieve the operational mode data of underlying + networks or drivers. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param Ip4ModeData The pointer to the EFI IPv4 Protocol mode data structure. + @param MnpConfigData The pointer to the managed network configuration data structure. + @param SnpModeData The pointer to the simple network mode data structure. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_GET_MODE_DATA)( + IN CONST EFI_IP4_PROTOCOL *This, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +/** + Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance. + + The Configure() function is used to set, change, or reset the operational + parameters and filter settings for this EFI IPv4 Protocol instance. Until these + parameters have been set, no network traffic can be sent or received by this + instance. Once the parameters have been reset (by calling this function with + IpConfigData set to NULL), no more traffic can be sent or received until these + parameters have been set again. Each EFI IPv4 Protocol instance can be started + and stopped independently of each other by enabling or disabling their receive + filter settings with the Configure() function. + + When IpConfigData.UseDefaultAddress is set to FALSE, the new station address will + be appended as an alias address into the addresses list in the EFI IPv4 Protocol + driver. While set to TRUE, Configure() will trigger the EFI_IP4_CONFIG_PROTOCOL + to retrieve the default IPv4 address if it is not available yet. Clients could + frequently call GetModeData() to check the status to ensure that the default IPv4 + address is ready. + + If operational parameters are reset or changed, any pending transmit and receive + requests will be cancelled. Their completion token status will be set to EFI_ABORTED + and their events will be signaled. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param IpConfigData The pointer to the EFI IPv4 Protocol configuration data structure. + + @retval EFI_SUCCESS The driver instance was successfully opened. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + IpConfigData.StationAddress is not a unicast IPv4 address. + IpConfigData.SubnetMask is not a valid IPv4 subnet + @retval EFI_UNSUPPORTED One or more of the following conditions is TRUE: + A configuration protocol (DHCP, BOOTP, RARP, etc.) could + not be located when clients choose to use the default IPv4 + address. This EFI IPv4 Protocol implementation does not + support this requested filter or timeout setting. + @retval EFI_OUT_OF_RESOURCES The EFI IPv4 Protocol driver instance data could not be allocated. + @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the + IPv4 address or subnet mask can be changed. The interface must + also be stopped when switching to/from raw packet mode. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv4 + Protocol driver instance is not opened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIGURE)( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL + ); + +/** + Joins and leaves multicast groups. + + The Groups() function is used to join and leave multicast group sessions. Joining + a group will enable reception of matching multicast packets. Leaving a group will + disable the multicast packet reception. + + If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param JoinFlag Set to TRUE to join the multicast group session and FALSE to leave. + @param GroupAddress The pointer to the IPv4 multicast address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following is TRUE: + - This is NULL. + - JoinFlag is TRUE and GroupAddress is NULL. + - GroupAddress is not NULL and *GroupAddress is + not a multicast IPv4 address. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES System resources could not be allocated. + @retval EFI_UNSUPPORTED This EFI IPv4 Protocol implementation does not support multicast groups. + @retval EFI_ALREADY_STARTED The group address is already in the group table (when + JoinFlag is TRUE). + @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_GROUPS)( + IN EFI_IP4_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL + ); + +/** + Adds and deletes routing table entries. + + The Routes() function adds a route to or deletes a route from the routing table. + + Routes are determined by comparing the SubnetAddress with the destination IPv4 + address arithmetically AND-ed with the SubnetMask. The gateway address must be + on the same subnet as the configured station address. + + The default route is added with SubnetAddress and SubnetMask both set to 0.0.0.0. + The default route matches all destination IPv4 addresses that do not match any + other routes. + + A GatewayAddress that is zero is a nonroute. Packets are sent to the destination + IP address if it can be found in the ARP cache or on the local subnet. One automatic + nonroute entry will be inserted into the routing table for outgoing packets that + are addressed to a local subnet (gateway address of 0.0.0.0). + + Each EFI IPv4 Protocol instance has its own independent routing table. Those EFI + IPv4 Protocol instances that use the default IPv4 address will also have copies + of the routing table that was provided by the EFI_IP4_CONFIG_PROTOCOL, and these + copies will be updated whenever the EIF IPv4 Protocol driver reconfigures its + instances. As a result, client modification to the routing table will be lost. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param DeleteRoute Set to TRUE to delete this route from the routing table. Set to + FALSE to add this route to the routing table. SubnetAddress + and SubnetMask are used as the key to each route entry. + @param SubnetAddress The address of the subnet that needs to be routed. + @param SubnetMask The subnet mask of SubnetAddress. + @param GatewayAddress The unicast gateway IPv4 address for this route. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The driver instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - SubnetAddress is NULL. + - SubnetMask is NULL. + - GatewayAddress is NULL. + - *SubnetAddress is not a valid subnet address. + - *SubnetMask is not a valid subnet mask. + - *GatewayAddress is not a valid unicast IPv4 address. + @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table. + @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE). + @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when + DeleteRoute is FALSE). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_ROUTES)( + IN EFI_IP4_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ); + +/** + Places outgoing data packets into the transmit queue. + + The Transmit() function places a sending request in the transmit queue of this + EFI IPv4 Protocol instance. Whenever the packet in the token is sent out or some + errors occur, the event in the token will be signaled and the status is updated. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param Token The pointer to the transmit token. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more pameters are invalid. + @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event + was already in the transmit queue. + @retval EFI_NOT_READY The completion token could not be queued because the transmit + queue is full. + @retval EFI_NOT_FOUND Not route is found to destination address. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data. + @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too + short to transmit. + @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is + greater than MTU (or greater than the maximum packet size if + Token.Packet.TxData.OverrideData. + DoNotFragment is TRUE.) + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_TRANSMIT)( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_COMPLETION_TOKEN *Token + ); + +/** + Places a receiving request into the receiving queue. + + The Receive() function places a completion token into the receive packet queue. + This function is always asynchronous. + + The Token.Event field in the completion token must be filled in by the caller + and cannot be NULL. When the receive operation completes, the EFI IPv4 Protocol + driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event + is signaled. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param Token The pointer to a token that is associated with the receive data descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, RARP, etc.) + is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system + resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + The EFI IPv4 Protocol instance has been reset to startup defaults. + @retval EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already + in the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + @retval EFI_ICMP_ERROR An ICMP error packet was received. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_RECEIVE)( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_COMPLETION_TOKEN *Token + ); + +/** + Abort an asynchronous transmit or receive request. + + The Cancel() function is used to abort a pending transmit or receive request. + If the token is in the transmit or receive request queues, after calling this + function, Token->Status will be set to EFI_ABORTED and then Token->Event will + be signaled. If the token is not in one of the queues, which usually means the + asynchronous operation has completed, this function will not signal the token + and EFI_NOT_FOUND is returned. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + @param Token The pointer to a token that has been issued by + EFI_IP4_PROTOCOL.Transmit() or + EFI_IP4_PROTOCOL.Receive(). If NULL, all pending + tokens are aborted. Type EFI_IP4_COMPLETION_TOKEN is + defined in EFI_IP4_PROTOCOL.Transmit(). + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and + Token->Event was signaled. When Token is NULL, all + pending requests were aborted and their events were signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CANCEL)( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function polls for incoming data packets and processes outgoing data + packets. Network drivers and applications can call the EFI_IP4_PROTOCOL.Poll() + function to increase the rate that data packets are moved between the communications + device and the transmit and receive queues. + + In some systems the periodic timer event may not poll the underlying communications + device fast enough to transmit and/or receive all data packets without missing + incoming packets or dropping outgoing packets. Drivers and applications that are + experiencing packet loss should try calling the EFI_IP4_PROTOCOL.Poll() function + more often. + + @param This The pointer to the EFI_IP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_POLL)( + IN EFI_IP4_PROTOCOL *This + ); + +/// +/// The EFI IPv4 Protocol implements a simple packet-oriented interface that can be +/// used by drivers, daemons, and applications to transmit and receive network packets. +/// +struct _EFI_IP4_PROTOCOL { + EFI_IP4_GET_MODE_DATA GetModeData; + EFI_IP4_CONFIGURE Configure; + EFI_IP4_GROUPS Groups; + EFI_IP4_ROUTES Routes; + EFI_IP4_TRANSMIT Transmit; + EFI_IP4_RECEIVE Receive; + EFI_IP4_CANCEL Cancel; + EFI_IP4_POLL Poll; +}; + +extern EFI_GUID gEfiIp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiIp4ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config.h new file mode 100644 index 0000000..022464a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config.h @@ -0,0 +1,182 @@ +/** @file + This file provides a definition of the EFI IPv4 Configuration + Protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.0. + +**/ +#ifndef __EFI_IP4CONFIG_PROTOCOL_H__ +#define __EFI_IP4CONFIG_PROTOCOL_H__ + +#include + +#define EFI_IP4_CONFIG_PROTOCOL_GUID \ + { \ + 0x3b95aa31, 0x3793, 0x434b, {0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e } \ + } + +typedef struct _EFI_IP4_CONFIG_PROTOCOL EFI_IP4_CONFIG_PROTOCOL; + +#define IP4_CONFIG_VARIABLE_ATTRIBUTES \ + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS) + +/// +/// EFI_IP4_IPCONFIG_DATA contains the minimum IPv4 configuration data +/// that is needed to start basic network communication. The StationAddress +/// and SubnetMask must be a valid unicast IP address and subnet mask. +/// If RouteTableSize is not zero, then RouteTable contains a properly +/// formatted routing table for the StationAddress/SubnetMask, with the +/// last entry in the table being the default route. +/// +typedef struct { + /// + /// Default station IP address, stored in network byte order. + /// + EFI_IPv4_ADDRESS StationAddress; + /// + /// Default subnet mask, stored in network byte order. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// Number of entries in the following RouteTable. May be zero. + /// + UINT32 RouteTableSize; + /// + /// Default routing table data (stored in network byte order). + /// Ignored if RouteTableSize is zero. + /// + EFI_IP4_ROUTE_TABLE *RouteTable; +} EFI_IP4_IPCONFIG_DATA; + + +/** + Starts running the configuration policy for the EFI IPv4 Protocol driver. + + The Start() function is called to determine and to begin the platform + configuration policy by the EFI IPv4 Protocol driver. This determination may + be as simple as returning EFI_UNSUPPORTED if there is no EFI IPv4 Protocol + driver configuration policy. It may be as involved as loading some defaults + from nonvolatile storage, downloading dynamic data from a DHCP server, and + checking permissions with a site policy server. + Starting the configuration policy is just the beginning. It may finish almost + instantly or it may take several minutes before it fails to retrieve configuration + information from one or more servers. Once the policy is started, drivers + should use the DoneEvent parameter to determine when the configuration policy + has completed. EFI_IP4_CONFIG_PROTOCOL.GetData() must then be called to + determine if the configuration succeeded or failed. + Until the configuration completes successfully, EFI IPv4 Protocol driver instances + that are attempting to use default configurations must return EFI_NO_MAPPING. + Once the configuration is complete, the EFI IPv4 Configuration Protocol driver + signals DoneEvent. The configuration may need to be updated in the future. + Note that in this case the EFI IPv4 Configuration Protocol driver must signal + ReconfigEvent, and all EFI IPv4 Protocol driver instances that are using default + configurations must return EFI_NO_MAPPING until the configuration policy has + been rerun. + + @param This The pointer to the EFI_IP4_CONFIG_PROTOCOL instance. + @param DoneEvent Event that will be signaled when the EFI IPv4 + Protocol driver configuration policy completes + execution. This event must be of type EVT_NOTIFY_SIGNAL. + @param ReconfigEvent Event that will be signaled when the EFI IPv4 + Protocol driver configuration needs to be updated. + This event must be of type EVT_NOTIFY_SIGNAL. + + @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol + driver is now running. + @retval EFI_INVALID_PARAMETER One or more of the following parameters is NULL: + This + DoneEvent + ReconfigEvent + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol + driver was already started. + @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred. + @retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol + driver configuration. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG_START)( + IN EFI_IP4_CONFIG_PROTOCOL *This, + IN EFI_EVENT DoneEvent, + IN EFI_EVENT ReconfigEvent + ); + +/** + Stops running the configuration policy for the EFI IPv4 Protocol driver. + + The Stop() function stops the configuration policy for the EFI IPv4 Protocol driver. + All configuration data will be lost after calling Stop(). + + @param This The pointer to the EFI_IP4_CONFIG_PROTOCOL instance. + + @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol + driver has been stopped. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol + driver was not started. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG_STOP)( + IN EFI_IP4_CONFIG_PROTOCOL *This + ); + +/** + Returns the default configuration data (if any) for the EFI IPv4 Protocol driver. + + The GetData() function returns the current configuration data for the EFI IPv4 + Protocol driver after the configuration policy has completed. + + @param This The pointer to the EFI_IP4_CONFIG_PROTOCOL instance. + @param IpConfigDataSize On input, the size of the IpConfigData buffer. + On output, the count of bytes that were written + into the IpConfigData buffer. + @param IpConfigData The pointer to the EFI IPv4 Configuration Protocol + driver configuration data structure. + Type EFI_IP4_IPCONFIG_DATA is defined in + "Related Definitions" below. + + @retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol + driver is not running. + @retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running. + @retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete. + @retval EFI_BUFFER_TOO_SMALL *IpConfigDataSize is smaller than the configuration + data buffer or IpConfigData is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG_GET_DATA)( + IN EFI_IP4_CONFIG_PROTOCOL *This, + IN OUT UINTN *IpConfigDataSize, + OUT EFI_IP4_IPCONFIG_DATA *IpConfigData OPTIONAL + ); + +/// +/// The EFI_IP4_CONFIG_PROTOCOL driver performs platform-dependent and policy-dependent +/// configurations for the EFI IPv4 Protocol driver. +/// +struct _EFI_IP4_CONFIG_PROTOCOL { + EFI_IP4_CONFIG_START Start; + EFI_IP4_CONFIG_STOP Stop; + EFI_IP4_CONFIG_GET_DATA GetData; +}; + +extern EFI_GUID gEfiIp4ConfigProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config2.h new file mode 100644 index 0000000..e683e6a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip4Config2.h @@ -0,0 +1,323 @@ +/** @file + This file provides a definition of the EFI IPv4 Configuration II + Protocol. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +@par Revision Reference: +This Protocol is introduced in UEFI Specification 2.5 + +**/ +#ifndef __EFI_IP4CONFIG2_PROTOCOL_H__ +#define __EFI_IP4CONFIG2_PROTOCOL_H__ + +#include + +#define EFI_IP4_CONFIG2_PROTOCOL_GUID \ + { \ + 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \ + } + +typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL; + + +/// +/// EFI_IP4_CONFIG2_DATA_TYPE +/// +typedef enum { + /// + /// The interface information of the communication device this EFI + /// IPv4 Configuration II Protocol instance manages. This type of + /// data is read only. The corresponding Data is of type + /// EFI_IP4_CONFIG2_INTERFACE_INFO. + /// + Ip4Config2DataTypeInterfaceInfo, + /// + /// The general configuration policy for the EFI IPv4 network stack + /// running on the communication device this EFI IPv4 + /// Configuration II Protocol instance manages. The policy will + /// affect other configuration settings. The corresponding Data is of + /// type EFI_IP4_CONFIG2_POLICY. + /// + Ip4Config2DataTypePolicy, + /// + /// The station addresses set manually for the EFI IPv4 network + /// stack. It is only configurable when the policy is + /// Ip4Config2PolicyStatic. The corresponding Data is of + /// type EFI_IP4_CONFIG2_MANUAL_ADDRESS. When DataSize + /// is 0 and Data is NULL, the existing configuration is cleared + /// from the EFI IPv4 Configuration II Protocol instance. + /// + Ip4Config2DataTypeManualAddress, + /// + /// The gateway addresses set manually for the EFI IPv4 network + /// stack running on the communication device this EFI IPv4 + /// Configuration II Protocol manages. It is not configurable when + /// the policy is Ip4Config2PolicyDhcp. The gateway + /// addresses must be unicast IPv4 addresses. The corresponding + /// Data is a pointer to an array of EFI_IPv4_ADDRESS instances. + /// When DataSize is 0 and Data is NULL, the existing configuration + /// is cleared from the EFI IPv4 Configuration II Protocol instance. + /// + Ip4Config2DataTypeGateway, + /// + /// The DNS server list for the EFI IPv4 network stack running on + /// the communication device this EFI IPv4 Configuration II + /// Protocol manages. It is not configurable when the policy is + /// Ip4Config2PolicyDhcp. The DNS server addresses must be + /// unicast IPv4 addresses. The corresponding Data is a pointer to + /// an array of EFI_IPv4_ADDRESS instances. When DataSize + /// is 0 and Data is NULL, the existing configuration is cleared + /// from the EFI IPv4 Configuration II Protocol instance. + /// + Ip4Config2DataTypeDnsServer, + Ip4Config2DataTypeMaximum +} EFI_IP4_CONFIG2_DATA_TYPE; + +/// +/// EFI_IP4_CONFIG2_INTERFACE_INFO related definitions +/// +#define EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32 + +/// +/// EFI_IP4_CONFIG2_INTERFACE_INFO +/// +typedef struct { + /// + /// The name of the interface. It is a NULL-terminated Unicode string. + /// + CHAR16 Name[EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE]; + /// + /// The interface type of the network interface. See RFC 1700, + /// section "Number Hardware Type". + /// + UINT8 IfType; + /// + /// The size, in bytes, of the network interface's hardware address. + /// + UINT32 HwAddressSize; + /// + /// The hardware address for the network interface. + /// + EFI_MAC_ADDRESS HwAddress; + /// + /// The station IPv4 address of this EFI IPv4 network stack. + /// + EFI_IPv4_ADDRESS StationAddress; + /// + /// The subnet address mask that is associated with the station address. + /// + EFI_IPv4_ADDRESS SubnetMask; + /// + /// Size of the following RouteTable, in bytes. May be zero. + /// + UINT32 RouteTableSize; + /// + /// The route table of the IPv4 network stack runs on this interface. + /// Set to NULL if RouteTableSize is zero. Type EFI_IP4_ROUTE_TABLE is defined in + /// EFI_IP4_PROTOCOL.GetModeData(). + /// + EFI_IP4_ROUTE_TABLE *RouteTable OPTIONAL; +} EFI_IP4_CONFIG2_INTERFACE_INFO; + +/// +/// EFI_IP4_CONFIG2_POLICY +/// +typedef enum { + /// + /// Under this policy, the Ip4Config2DataTypeManualAddress, + /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration + /// data are required to be set manually. The EFI IPv4 Protocol will get all + /// required configuration such as IPv4 address, subnet mask and + /// gateway settings from the EFI IPv4 Configuration II protocol. + /// + Ip4Config2PolicyStatic, + /// + /// Under this policy, the Ip4Config2DataTypeManualAddress, + /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration data are + /// not allowed to set via SetData(). All of these configurations are retrieved from DHCP + /// server or other auto-configuration mechanism. + /// + Ip4Config2PolicyDhcp, + Ip4Config2PolicyMax +} EFI_IP4_CONFIG2_POLICY; + +/// +/// EFI_IP4_CONFIG2_MANUAL_ADDRESS +/// +typedef struct { + /// + /// The IPv4 unicast address. + /// + EFI_IPv4_ADDRESS Address; + /// + /// The subnet mask. + /// + EFI_IPv4_ADDRESS SubnetMask; +} EFI_IP4_CONFIG2_MANUAL_ADDRESS; + +/** + Set the configuration for the EFI IPv4 network stack running on the communication device this EFI + IPv4 Configuration II Protocol instance manages. + + This function is used to set the configuration data of type DataType for the EFI IPv4 network stack + running on the communication device this EFI IPv4 Configuration II Protocol instance manages. + The successfully configured data is valid after system reset or power-off. + The DataSize is used to calculate the count of structure instances in the Data for some + DataType that multiple structure instances are allowed. + This function is always non-blocking. When setting some typeof configuration data, an + asynchronous process is invoked to check the correctness of the data, such as doing address conflict + detection on the manually set local IPv4 address. EFI_NOT_READY is returned immediately to + indicate that such an asynchronous process is invoked and the process is not finished yet. The caller + willing to get the result of the asynchronous process is required to call RegisterDataNotify() + to register an event on the specified configuration data. Once the event is signaled, the caller can call + GetData()to get back the configuration data in order to know the result. For other types of + configuration data that do not require an asynchronous configuration process, the result of the + operation is immediately returned. + + @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. + @param[in] DataType The type of data to set. + @param[in] DataSize Size of the buffer pointed to by Data in bytes. + @param[in] Data The data buffer to set. The type ofthe data buffer is associated + with the DataType. + + @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 network stack is set + successfully. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + This is NULL. + One or more fields in Data and DataSize do not match the + requirement of the data type indicated by DataType. + @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified configuration + data can not be set under the current policy. + @retval EFI_ACCESS_DENIED Another set operation on the specified configuration data is already in process. + @retval EFI_NOT_READY An asynchronous process is invoked to set the specified configuration data and + the process is not finished yet. + @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type indicated by DataType. + @retval EFI_UNSUPPORTED This DataType is not supported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG2_SET_DATA) ( + IN EFI_IP4_CONFIG2_PROTOCOL *This, + IN EFI_IP4_CONFIG2_DATA_TYPE DataType, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Get the configuration data for the EFI IPv4 network stack running on the communication device this + EFI IPv4 Configuration II Protocol instance manages. + + This function returns the configuration data of type DataType for the EFI IPv4 network stack + running on the communication device this EFI IPv4 Configuration II Protocol instance manages. + The caller is responsible for allocating the buffer usedto return the specified configuration data and + the required size will be returned to the caller if the size of the buffer is too small. + EFI_NOT_READY is returned if the specified configuration data is not ready due to an already in + progress asynchronous configuration process. The caller can call RegisterDataNotify() to + register an event on the specified configuration data. Once the asynchronous configuration process is + finished, the event will be signaled and a subsequent GetData() call will return the specified + configuration data. + + @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. + @param[in] DataType The type of data to get. + @param[out] DataSize On input, in bytes, the size of Data. On output, in bytes, the size + of buffer required to store the specified configuration data. + @param[in] Data The data buffer in which the configuration data is returned. The + type of the data buffer is associated with the DataType. Ignored + if DataSize is 0. + + @retval EFI_SUCCESS The specified configuration data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSizeis not zero. + @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data + and the required size is returned in DataSize. + @retval EFI_NOT_READY The specified configuration data is not ready due to an already in + progress asynchronous configuration process. + @retval EFI_NOT_FOUND The specified configuration data is not found. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG2_GET_DATA) ( + IN EFI_IP4_CONFIG2_PROTOCOL *This, + IN EFI_IP4_CONFIG2_DATA_TYPE DataType, + IN OUT UINTN *DataSize, + IN VOID *Data OPTIONAL + ); + +/** + Register an event that is to be signaled whenever a configuration process on the specified + configuration data is done. + + This function registers an event that is to be signaled whenever a configuration process on the + specified configuration data is done. An event can be registered for different DataType + simultaneously and the caller is responsible for determining which type of configuration data causes + the signaling of the event in such case. + + @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. + @param[in] DataType The type of data to unregister the event for. + @param[in] Event The event to register. + + @retval EFI_SUCCESS The notification event for the specified configuration data is + registered. + @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. + @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not supported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The Event is already registered for the DataType. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG2_REGISTER_NOTIFY) ( + IN EFI_IP4_CONFIG2_PROTOCOL *This, + IN EFI_IP4_CONFIG2_DATA_TYPE DataType, + IN EFI_EVENT Event + ); + +/** + Remove a previously registered event for the specified configuration data. + + This function removes a previously registeredevent for the specified configuration data. + + @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. + @param[in] DataType The type of data to remove the previously registered event for. + @param[in] Event The event to unregister. + + @retval EFI_SUCCESS The event registered for the specified configuration data is removed. + @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. + @retval EFI_NOT_FOUND The Eventhas not been registered for the specified DataType. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG2_UNREGISTER_NOTIFY) ( + IN EFI_IP4_CONFIG2_PROTOCOL *This, + IN EFI_IP4_CONFIG2_DATA_TYPE DataType, + IN EFI_EVENT Event + ); + +/// +/// The EFI_IP4_CONFIG2_PROTOCOL is designed to be the central repository for the common +/// configurations and the administrator configurable settings for the EFI IPv4 network stack. +/// An EFI IPv4 Configuration II Protocol instance will be installed on each communication device that +/// the EFI IPv4 network stack runs on. +/// +struct _EFI_IP4_CONFIG2_PROTOCOL { + EFI_IP4_CONFIG2_SET_DATA SetData; + EFI_IP4_CONFIG2_GET_DATA GetData; + EFI_IP4_CONFIG2_REGISTER_NOTIFY RegisterDataNotify; + EFI_IP4_CONFIG2_UNREGISTER_NOTIFY UnregisterDataNotify; +}; + +extern EFI_GUID gEfiIp4Config2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6.h new file mode 100644 index 0000000..1598f82 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6.h @@ -0,0 +1,953 @@ +/** @file + This file defines the EFI IPv6 (Internet Protocol version 6) + Protocol interface. It is split into the following three main + sections: + - EFI IPv6 Service Binding Protocol + - EFI IPv6 Variable (deprecated in UEFI 2.4B) + - EFI IPv6 Protocol + The EFI IPv6 Protocol provides basic network IPv6 packet I/O services, + which includes support for Neighbor Discovery Protocol (ND), Multicast + Listener Discovery Protocol (MLD), and a subset of the Internet Control + Message Protocol (ICMPv6). + + Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_IP6_PROTOCOL_H__ +#define __EFI_IP6_PROTOCOL_H__ + +#include + + +#define EFI_IP6_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xec835dd3, 0xfe0f, 0x617b, {0xa6, 0x21, 0xb3, 0x50, 0xc3, 0xe1, 0x33, 0x88 } \ + } + +#define EFI_IP6_PROTOCOL_GUID \ + { \ + 0x2c8759d5, 0x5c2d, 0x66ef, {0x92, 0x5f, 0xb6, 0x6c, 0x10, 0x19, 0x57, 0xe2 } \ + } + +typedef struct _EFI_IP6_PROTOCOL EFI_IP6_PROTOCOL; + +/// +/// EFI_IP6_ADDRESS_PAIR is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct{ + /// + /// The EFI IPv6 Protocol instance handle that is using this address/prefix pair. + /// + EFI_HANDLE InstanceHandle; + /// + /// IPv6 address in network byte order. + /// + EFI_IPv6_ADDRESS Ip6Address; + /// + /// The length of the prefix associated with the Ip6Address. + /// + UINT8 PrefixLength; +} EFI_IP6_ADDRESS_PAIR; + +/// +/// EFI_IP6_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + /// + /// The handle of the driver that creates this entry. + /// + EFI_HANDLE DriverHandle; + /// + /// The number of IPv6 address pairs that follow this data structure. + /// + UINT32 AddressCount; + /// + /// List of IPv6 address pairs that are currently in use. + /// + EFI_IP6_ADDRESS_PAIR AddressPairs[1]; +} EFI_IP6_VARIABLE_DATA; + +/// +/// ICMPv6 type definitions for error messages +/// +///@{ +#define ICMP_V6_DEST_UNREACHABLE 0x1 +#define ICMP_V6_PACKET_TOO_BIG 0x2 +#define ICMP_V6_TIME_EXCEEDED 0x3 +#define ICMP_V6_PARAMETER_PROBLEM 0x4 +///@} + +/// +/// ICMPv6 type definition for informational messages +/// +///@{ +#define ICMP_V6_ECHO_REQUEST 0x80 +#define ICMP_V6_ECHO_REPLY 0x81 +#define ICMP_V6_LISTENER_QUERY 0x82 +#define ICMP_V6_LISTENER_REPORT 0x83 +#define ICMP_V6_LISTENER_DONE 0x84 +#define ICMP_V6_ROUTER_SOLICIT 0x85 +#define ICMP_V6_ROUTER_ADVERTISE 0x86 +#define ICMP_V6_NEIGHBOR_SOLICIT 0x87 +#define ICMP_V6_NEIGHBOR_ADVERTISE 0x88 +#define ICMP_V6_REDIRECT 0x89 +#define ICMP_V6_LISTENER_REPORT_2 0x8F +///@} + +/// +/// ICMPv6 code definitions for ICMP_V6_DEST_UNREACHABLE +/// +///@{ +#define ICMP_V6_NO_ROUTE_TO_DEST 0x0 +#define ICMP_V6_COMM_PROHIBITED 0x1 +#define ICMP_V6_BEYOND_SCOPE 0x2 +#define ICMP_V6_ADDR_UNREACHABLE 0x3 +#define ICMP_V6_PORT_UNREACHABLE 0x4 +#define ICMP_V6_SOURCE_ADDR_FAILED 0x5 +#define ICMP_V6_ROUTE_REJECTED 0x6 +///@} + +/// +/// ICMPv6 code definitions for ICMP_V6_TIME_EXCEEDED +/// +///@{ +#define ICMP_V6_TIMEOUT_HOP_LIMIT 0x0 +#define ICMP_V6_TIMEOUT_REASSEMBLE 0x1 +///@} + +/// +/// ICMPv6 code definitions for ICMP_V6_PARAMETER_PROBLEM +/// +///@{ +#define ICMP_V6_ERRONEOUS_HEADER 0x0 +#define ICMP_V6_UNRECOGNIZE_NEXT_HDR 0x1 +#define ICMP_V6_UNRECOGNIZE_OPTION 0x2 +///@} + +/// +/// EFI_IP6_CONFIG_DATA +/// is used to report and change IPv6 session parameters. +/// +typedef struct { + /// + /// For the IPv6 packet to send and receive, this is the default value + /// of the 'Next Header' field in the last IPv6 extension header or in + /// the IPv6 header if there are no extension headers. Ignored when + /// AcceptPromiscuous is TRUE. + /// + UINT8 DefaultProtocol; + /// + /// Set to TRUE to receive all IPv6 packets that get through the + /// receive filters. + /// Set to FALSE to receive only the DefaultProtocol IPv6 + /// packets that get through the receive filters. Ignored when + /// AcceptPromiscuous is TRUE. + /// + BOOLEAN AcceptAnyProtocol; + /// + /// Set to TRUE to receive ICMP error report packets. Ignored when + /// AcceptPromiscuous or AcceptAnyProtocol is TRUE. + /// + BOOLEAN AcceptIcmpErrors; + /// + /// Set to TRUE to receive all IPv6 packets that are sent to any + /// hardware address or any protocol address. Set to FALSE to stop + /// receiving all promiscuous IPv6 packets. + /// + BOOLEAN AcceptPromiscuous; + /// + /// The destination address of the packets that will be transmitted. + /// Ignored if it is unspecified. + /// + EFI_IPv6_ADDRESS DestinationAddress; + /// + /// The station IPv6 address that will be assigned to this EFI IPv6 + /// Protocol instance. This field can be set and changed only when + /// the EFI IPv6 driver is transitioning from the stopped to the started + /// states. If the StationAddress is specified, the EFI IPv6 Protocol + /// driver will deliver only incoming IPv6 packets whose destination + /// matches this IPv6 address exactly. The StationAddress is required + /// to be one of currently configured IPv6 addresses. An address + /// containing all zeroes is also accepted as a special case. Under this + /// situation, the IPv6 driver is responsible for binding a source + /// address to this EFI IPv6 protocol instance according to the source + /// address selection algorithm. Only incoming packets destined to + /// the selected address will be delivered to the user. And the + /// selected station address can be retrieved through later + /// GetModeData() call. If no address is available for selecting, + /// EFI_NO_MAPPING will be returned, and the station address will + /// only be successfully bound to this EFI IPv6 protocol instance + /// after IP6ModeData.IsConfigured changed to TRUE. + /// + EFI_IPv6_ADDRESS StationAddress; + /// + /// TrafficClass field in transmitted IPv6 packets. Default value + /// is zero. + /// + UINT8 TrafficClass; + /// + /// HopLimit field in transmitted IPv6 packets. + /// + UINT8 HopLimit; + /// + /// FlowLabel field in transmitted IPv6 packets. Default value is + /// zero. + /// + UINT32 FlowLabel; + /// + /// The timer timeout value (number of microseconds) for the + /// receive timeout event to be associated with each assembled + /// packet. Zero means do not drop assembled packets. + /// + UINT32 ReceiveTimeout; + /// + /// The timer timeout value (number of microseconds) for the + /// transmit timeout event to be associated with each outgoing + /// packet. Zero means do not drop outgoing packets. + /// + UINT32 TransmitTimeout; +} EFI_IP6_CONFIG_DATA; + +/// +/// EFI_IP6_ADDRESS_INFO +/// +typedef struct { + EFI_IPv6_ADDRESS Address; ///< The IPv6 address. + UINT8 PrefixLength; ///< The length of the prefix associated with the Address. +} EFI_IP6_ADDRESS_INFO; + +/// +/// EFI_IP6_ROUTE_TABLE +/// is the entry structure that is used in routing tables +/// +typedef struct { + /// + /// The IPv6 address of the gateway to be used as the next hop for + /// packets to this prefix. If the IPv6 address is all zeros, then the + /// prefix is on-link. + /// + EFI_IPv6_ADDRESS Gateway; + /// + /// The destination prefix to be routed. + /// + EFI_IPv6_ADDRESS Destination; + /// + /// The length of the prefix associated with the Destination. + /// + UINT8 PrefixLength; +} EFI_IP6_ROUTE_TABLE; + +/// +/// EFI_IP6_NEIGHBOR_STATE +/// +typedef enum { + /// + /// Address resolution is being performed on this entry. Specially, + /// Neighbor Solicitation has been sent to the solicited-node + /// multicast address of the target, but corresponding Neighbor + /// Advertisement has not been received. + /// + EfiNeighborInComplete, + /// + /// Positive confirmation was received that the forward path to the + /// neighbor was functioning properly. + /// + EfiNeighborReachable, + /// + ///Reachable Time has elapsed since the last positive confirmation + ///was received. In this state, the forward path to the neighbor was + ///functioning properly. + /// + EfiNeighborStale, + /// + /// This state is an optimization that gives upper-layer protocols + /// additional time to provide reachability confirmation. + /// + EfiNeighborDelay, + /// + /// A reachability confirmation is actively sought by retransmitting + /// Neighbor Solicitations every RetransTimer milliseconds until a + /// reachability confirmation is received. + /// + EfiNeighborProbe +} EFI_IP6_NEIGHBOR_STATE; + +/// +/// EFI_IP6_NEIGHBOR_CACHE +/// is the entry structure that is used in neighbor cache. It records a set +/// of entries about individual neighbors to which traffic has been sent recently. +/// +typedef struct { + EFI_IPv6_ADDRESS Neighbor; ///< The on-link unicast/anycast IP address of the neighbor. + EFI_MAC_ADDRESS LinkAddress; ///< Link-layer address of the neighbor. + EFI_IP6_NEIGHBOR_STATE State; ///< State of this neighbor cache entry. +} EFI_IP6_NEIGHBOR_CACHE; + +/// +/// EFI_IP6_ICMP_TYPE +/// is used to describe those ICMP messages that are supported by this EFI +/// IPv6 Protocol driver. +/// +typedef struct { + UINT8 Type; ///< The type of ICMP message. + UINT8 Code; ///< The code of the ICMP message. +} EFI_IP6_ICMP_TYPE; + +/// +/// EFI_IP6_MODE_DATA +/// +typedef struct { + /// + /// Set to TRUE after this EFI IPv6 Protocol instance is started. + /// All other fields in this structure are undefined until this field is TRUE. + /// Set to FALSE when the EFI IPv6 Protocol instance is stopped. + /// + BOOLEAN IsStarted; + /// + /// The maximum packet size, in bytes, of the packet which the upper layer driver could feed. + /// + UINT32 MaxPacketSize; + /// + /// Current configuration settings. Undefined until IsStarted is TRUE. + /// + EFI_IP6_CONFIG_DATA ConfigData; + /// + /// Set to TRUE when the EFI IPv6 Protocol instance is configured. + /// The instance is configured when it has a station address and + /// corresponding prefix length. + /// Set to FALSE when the EFI IPv6 Protocol instance is not configured. + /// + BOOLEAN IsConfigured; + /// + /// Number of configured IPv6 addresses on this interface. + /// + UINT32 AddressCount; + /// + /// List of currently configured IPv6 addresses and corresponding + /// prefix lengths assigned to this interface. It is caller's + /// responsibility to free this buffer. + /// + EFI_IP6_ADDRESS_INFO *AddressList; + /// + /// Number of joined multicast groups. Undefined until + /// IsConfigured is TRUE. + /// + UINT32 GroupCount; + /// + /// List of joined multicast group addresses. It is caller's + /// responsibility to free this buffer. Undefined until + /// IsConfigured is TRUE. + /// + EFI_IPv6_ADDRESS *GroupTable; + /// + /// Number of entries in the routing table. Undefined until + /// IsConfigured is TRUE. + /// + UINT32 RouteCount; + /// + /// Routing table entries. It is caller's responsibility to free this buffer. + /// + EFI_IP6_ROUTE_TABLE *RouteTable; + /// + /// Number of entries in the neighbor cache. Undefined until + /// IsConfigured is TRUE. + /// + UINT32 NeighborCount; + /// + /// Neighbor cache entries. It is caller's responsibility to free this + /// buffer. Undefined until IsConfigured is TRUE. + /// + EFI_IP6_NEIGHBOR_CACHE *NeighborCache; + /// + /// Number of entries in the prefix table. Undefined until + /// IsConfigured is TRUE. + /// + UINT32 PrefixCount; + /// + /// On-link Prefix table entries. It is caller's responsibility to free this + /// buffer. Undefined until IsConfigured is TRUE. + /// + EFI_IP6_ADDRESS_INFO *PrefixTable; + /// + /// Number of entries in the supported ICMP types list. + /// + UINT32 IcmpTypeCount; + /// + /// Array of ICMP types and codes that are supported by this EFI + /// IPv6 Protocol driver. It is caller's responsibility to free this + /// buffer. + /// + EFI_IP6_ICMP_TYPE *IcmpTypeList; +} EFI_IP6_MODE_DATA; + +/// +/// EFI_IP6_HEADER +/// The fields in the IPv6 header structure are defined in the Internet +/// Protocol version6 specification. +/// +#pragma pack(1) +typedef struct _EFI_IP6_HEADER { + UINT8 TrafficClassH:4; + UINT8 Version:4; + UINT8 FlowLabelH:4; + UINT8 TrafficClassL:4; + UINT16 FlowLabelL; + UINT16 PayloadLength; + UINT8 NextHeader; + UINT8 HopLimit; + EFI_IPv6_ADDRESS SourceAddress; + EFI_IPv6_ADDRESS DestinationAddress; +} EFI_IP6_HEADER; +#pragma pack() + +/// +/// EFI_IP6_FRAGMENT_DATA +/// describes the location and length of the IPv6 packet +/// fragment to transmit or that has been received. +/// +typedef struct _EFI_IP6_FRAGMENT_DATA { + UINT32 FragmentLength; ///< Length of fragment data. This field may not be set to zero. + VOID *FragmentBuffer; ///< Pointer to fragment data. This field may not be set to NULL. +} EFI_IP6_FRAGMENT_DATA; + +/// +/// EFI_IP6_RECEIVE_DATA +/// +typedef struct _EFI_IP6_RECEIVE_DATA { + /// + /// Time when the EFI IPv6 Protocol driver accepted the packet. + /// Ignored if it is zero. + /// + EFI_TIME TimeStamp; + /// + /// After this event is signaled, the receive data structure is released + /// and must not be referenced. + /// + EFI_EVENT RecycleSignal; + /// + ///Length of the IPv6 packet headers, including both the IPv6 + ///header and any extension headers. + /// + UINT32 HeaderLength; + /// + /// Pointer to the IPv6 packet header. If the IPv6 packet was + /// fragmented, this argument is a pointer to the header in the first + /// fragment. + /// + EFI_IP6_HEADER *Header; + /// + /// Sum of the lengths of IPv6 packet buffers in FragmentTable. May + /// be zero. + /// + UINT32 DataLength; + /// + /// Number of IPv6 payload fragments. May be zero. + /// + UINT32 FragmentCount; + /// + /// Array of payload fragment lengths and buffer pointers. + /// + EFI_IP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP6_RECEIVE_DATA; + +/// +/// EFI_IP6_OVERRIDE_DATA +/// The information and flags in the override data structure will override +/// default parameters or settings for one Transmit() function call. +/// +typedef struct _EFI_IP6_OVERRIDE_DATA { + UINT8 Protocol; ///< Protocol type override. + UINT8 HopLimit; ///< Hop-Limit override. + UINT32 FlowLabel; ///< Flow-Label override. +} EFI_IP6_OVERRIDE_DATA; + +/// +/// EFI_IP6_TRANSMIT_DATA +/// +typedef struct _EFI_IP6_TRANSMIT_DATA { + /// + /// The destination IPv6 address. If it is unspecified, + /// ConfigData.DestinationAddress will be used instead. + /// + EFI_IPv6_ADDRESS DestinationAddress; + /// + /// If not NULL, the IPv6 transmission control override data. + /// + EFI_IP6_OVERRIDE_DATA *OverrideData; + /// + /// Total length in byte of the IPv6 extension headers specified in + /// ExtHdrs. + /// + UINT32 ExtHdrsLength; + /// + /// Pointer to the IPv6 extension headers. The IP layer will append + /// the required extension headers if they are not specified by + /// ExtHdrs. Ignored if ExtHdrsLength is zero. + /// + VOID *ExtHdrs; + /// + /// The protocol of first extension header in ExtHdrs. Ignored if + /// ExtHdrsLength is zero. + /// + UINT8 NextHeader; + /// + /// Total length in bytes of the FragmentTable data to transmit. + /// + UINT32 DataLength; + /// + /// Number of entries in the fragment data table. + /// + UINT32 FragmentCount; + /// + /// Start of the fragment data table. + /// + EFI_IP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP6_TRANSMIT_DATA; + +/// +/// EFI_IP6_COMPLETION_TOKEN +/// structures are used for both transmit and receive operations. +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by + /// the EFI IPv6 Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// - EFI_SUCCESS: The receive or transmit completed + /// successfully. + /// - EFI_ABORTED: The receive or transmit was aborted + /// - EFI_TIMEOUT: The transmit timeout expired. + /// - EFI_ICMP_ERROR: An ICMP error packet was received. + /// - EFI_DEVICE_ERROR: An unexpected system or network + /// error occurred. + /// - EFI_SECURITY_VIOLATION: The transmit or receive was + /// failed because of an IPsec policy check. + /// - EFI_NO_MEDIA: There was a media error. + /// + EFI_STATUS Status; + union { + /// + /// When the Token is used for receiving, RxData is a pointer to the EFI_IP6_RECEIVE_DATA. + /// + EFI_IP6_RECEIVE_DATA *RxData; + /// + /// When the Token is used for transmitting, TxData is a pointer to the EFI_IP6_TRANSMIT_DATA. + /// + EFI_IP6_TRANSMIT_DATA *TxData; + } Packet; +} EFI_IP6_COMPLETION_TOKEN; + +/** + Gets the current operational settings for this instance of the EFI IPv6 Protocol driver. + + The GetModeData() function returns the current operational mode data for this driver instance. + The data fields in EFI_IP6_MODE_DATA are read only. This function is used optionally to + retrieve the operational mode data of underlying networks or drivers.. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[out] Ip6ModeData Pointer to the EFI IPv6 Protocol mode data structure. + @param[out] MnpConfigData Pointer to the managed network configuration data structure. + @param[out] SnpModeData Pointer to the simple network mode data structure. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_GET_MODE_DATA)( + IN EFI_IP6_PROTOCOL *This, + OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +/** + Assigns an IPv6 address and subnet mask to this EFI IPv6 Protocol driver instance. + + The Configure() function is used to set, change, or reset the operational parameters and filter + settings for this EFI IPv6 Protocol instance. Until these parameters have been set, no network traffic + can be sent or received by this instance. Once the parameters have been reset (by calling this + function with Ip6ConfigData set to NULL), no more traffic can be sent or received until these + parameters have been set again. Each EFI IPv6 Protocol instance can be started and stopped + independently of each other by enabling or disabling their receive filter settings with the + Configure() function. + + If Ip6ConfigData.StationAddress is a valid non-zero IPv6 unicast address, it is required + to be one of the currently configured IPv6 addresses list in the EFI IPv6 drivers, or else + EFI_INVALID_PARAMETER will be returned. If Ip6ConfigData.StationAddress is + unspecified, the IPv6 driver will bind a source address according to the source address selection + algorithm. Clients could frequently call GetModeData() to check get currently configured IPv6 + address list in the EFI IPv6 driver. If both Ip6ConfigData.StationAddress and + Ip6ConfigData.Destination are unspecified, when transmitting the packet afterwards, the + source address filled in each outgoing IPv6 packet is decided based on the destination of this packet. . + + If operational parameters are reset or changed, any pending transmit and receive requests will be + cancelled. Their completion token status will be set to EFI_ABORTED and their events will be + signaled. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] Ip6ConfigData Pointer to the EFI IPv6 Protocol configuration data structure. + + @retval EFI_SUCCESS The driver instance was successfully opened. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Ip6ConfigData.StationAddress is neither zero nor + a unicast IPv6 address. + - Ip6ConfigData.StationAddress is neither zero nor + one of the configured IP addresses in the EFI IPv6 driver. + - Ip6ConfigData.DefaultProtocol is illegal. + @retval EFI_OUT_OF_RESOURCES The EFI IPv6 Protocol driver instance data could not be allocated. + @retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing a source address for + this instance, but no source address was available for use. + @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the IPv6 + address or prefix length can be changed. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv6 + Protocol driver instance is not opened. + @retval EFI_UNSUPPORTED Default protocol specified through + Ip6ConfigData.DefaulProtocol isn't supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CONFIGURE)( + IN EFI_IP6_PROTOCOL *This, + IN EFI_IP6_CONFIG_DATA *Ip6ConfigData OPTIONAL + ); + +/** + Joins and leaves multicast groups. + + The Groups() function is used to join and leave multicast group sessions. Joining a group will + enable reception of matching multicast packets. Leaving a group will disable reception of matching + multicast packets. Source-Specific Multicast isn't required to be supported. + + If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave. + @param[in] GroupAddress Pointer to the IPv6 multicast address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following is TRUE: + - This is NULL. + - JoinFlag is TRUE and GroupAddress is NULL. + - GroupAddress is not NULL and *GroupAddress is + not a multicast IPv6 address. + - GroupAddress is not NULL and *GroupAddress is in the + range of SSM destination address. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_OUT_OF_RESOURCES System resources could not be allocated. + @retval EFI_UNSUPPORTED This EFI IPv6 Protocol implementation does not support multicast groups. + @retval EFI_ALREADY_STARTED The group address is already in the group table (when + JoinFlag is TRUE). + @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_GROUPS)( + IN EFI_IP6_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL + ); + +/** + Adds and deletes routing table entries. + + The Routes() function adds a route to or deletes a route from the routing table. + + Routes are determined by comparing the leftmost PrefixLength bits of Destination with + the destination IPv6 address arithmetically. The gateway address must be on the same subnet as the + configured station address. + + The default route is added with Destination and PrefixLegth both set to all zeros. The + default route matches all destination IPv6 addresses that do not match any other routes. + + All EFI IPv6 Protocol instances share a routing table. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to + FALSE to add this route to the routing table. Destination, + PrefixLength and Gateway are used as the key to each + route entry. + @param[in] Destination The address prefix of the subnet that needs to be routed. + @param[in] PrefixLength The prefix length of Destination. Ignored if Destination + is NULL. + @param[in] GatewayAddress The unicast gateway IPv6 address for this route. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The driver instance has not been started. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - When DeleteRoute is TRUE, both Destination and + GatewayAddress are NULL. + - When DeleteRoute is FALSE, either Destination or + GatewayAddress is NULL. + - *GatewayAddress is not a valid unicast IPv6 address. + - *GatewayAddress is one of the local configured IPv6 + addresses. + @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table. + @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE). + @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when + DeleteRoute is FALSE). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_ROUTES)( + IN EFI_IP6_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv6_ADDRESS *Destination OPTIONAL, + IN UINT8 PrefixLength, + IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL + ); + +/** + Add or delete Neighbor cache entries. + + The Neighbors() function is used to add, update, or delete an entry from neighbor cache. + IPv6 neighbor cache entries are typically inserted and updated by the network protocol driver as + network traffic is processed. Most neighbor cache entries will time out and be deleted if the network + traffic stops. Neighbor cache entries that were inserted by Neighbors() may be static (will not + timeout) or dynamic (will time out). + + The implementation should follow the neighbor cache timeout mechanism which is defined in + RFC4861. The default neighbor cache timeout value should be tuned for the expected network + environment + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] DeleteFlag Set to TRUE to delete the specified cache entry, set to FALSE to + add (or update, if it already exists and Override is TRUE) the + specified cache entry. TargetIp6Address is used as the key + to find the requested cache entry. + @param[in] TargetIp6Address Pointer to Target IPv6 address. + @param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL. + @param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor + cache, it will be deleted after Timeout. A value of zero means that + the entry is permanent. A non-zero value means that the entry is + dynamic. + @param[in] Override If TRUE, the cached link-layer address of the matching entry will + be overridden and updated; if FALSE, EFI_ACCESS_DENIED + will be returned if a corresponding cache entry already existed. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - TargetIpAddress is NULL. + - *TargetLinkAddress is invalid when not NULL. + - *TargetIpAddress is not a valid unicast IPv6 address. + - *TargetIpAddress is one of the local configured IPv6 + addresses. + @retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache. + @retval EFI_NOT_FOUND This entry is not in the neighbor cache (when DeleteFlag is + TRUE or when DeleteFlag is FALSE while + TargetLinkAddress is NULL.). + @retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache, + and that entry is tagged as un-overridden (when DeleteFlag + is FALSE). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_NEIGHBORS)( + IN EFI_IP6_PROTOCOL *This, + IN BOOLEAN DeleteFlag, + IN EFI_IPv6_ADDRESS *TargetIp6Address, + IN EFI_MAC_ADDRESS *TargetLinkAddress, + IN UINT32 Timeout, + IN BOOLEAN Override + ); + +/** + Places outgoing data packets into the transmit queue. + + The Transmit() function places a sending request in the transmit queue of this + EFI IPv6 Protocol instance. Whenever the packet in the token is sent out or some + errors occur, the event in the token will be signaled and the status is updated. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] Token Pointer to the transmit token. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING The IPv6 driver was responsible for choosing a source address for + this transmission, but no source address was available for use. + @retval EFI_INVALID_PARAMETER One or more of the following is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + - Token.Packet.TxData is NULL. + - Token.Packet.ExtHdrsLength is not zero and Token.Packet.ExtHdrs is NULL. + - Token.Packet.FragmentCount is zero. + - One or more of the Token.Packet.TxData.FragmentTable[].FragmentLength fields is zero. + - One or more of the Token.Packet.TxData.FragmentTable[].FragmentBuffer fields is NULL. + - Token.Packet.TxData.DataLength is zero or not equal to the sum of fragment lengths. + - Token.Packet.TxData.DestinationAddress is non-zero when DestinationAddress is configured as + non-zero when doing Configure() for this EFI IPv6 protocol instance. + - Token.Packet.TxData.DestinationAddress is unspecified when DestinationAddress is unspecified + when doing Configure() for this EFI IPv6 protocol instance. + @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event + was already in the transmit queue. + @retval EFI_NOT_READY The completion token could not be queued because the transmit + queue is full. + @retval EFI_NOT_FOUND Not route is found to destination address. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data. + @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too + short to transmit. + @retval EFI_BAD_BUFFER_SIZE If Token.Packet.TxData.DataLength is beyond the + maximum that which can be described through the Fragment Offset + field in Fragment header when performing fragmentation. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_TRANSMIT)( + IN EFI_IP6_PROTOCOL *This, + IN EFI_IP6_COMPLETION_TOKEN *Token + ); + +/** + Places a receiving request into the receiving queue. + + The Receive() function places a completion token into the receive packet queue. + This function is always asynchronous. + + The Token.Event field in the completion token must be filled in by the caller + and cannot be NULL. When the receive operation completes, the EFI IPv6 Protocol + driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event + is signaled. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] Token Pointer to a token that is associated with the receive data descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started. + @retval EFI_NO_MAPPING When IP6 driver responsible for binding source address to this instance, + while no source address is available for use. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system + resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + The EFI IPv6 Protocol instance has been reset to startup defaults. + @retval EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already + in the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_RECEIVE)( + IN EFI_IP6_PROTOCOL *This, + IN EFI_IP6_COMPLETION_TOKEN *Token + ); + +/** + Abort an asynchronous transmit or receive request. + + The Cancel() function is used to abort a pending transmit or receive request. + If the token is in the transmit or receive request queues, after calling this + function, Token->Status will be set to EFI_ABORTED and then Token->Event will + be signaled. If the token is not in one of the queues, which usually means the + asynchronous operation has completed, this function will not signal the token + and EFI_NOT_FOUND is returned. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + @param[in] Token Pointer to a token that has been issued by + EFI_IP6_PROTOCOL.Transmit() or + EFI_IP6_PROTOCOL.Receive(). If NULL, all pending + tokens are aborted. Type EFI_IP6_COMPLETION_TOKEN is + defined in EFI_IP6_PROTOCOL.Transmit(). + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and + Token->Event was signaled. When Token is NULL, all + pending requests were aborted and their events were signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CANCEL)( + IN EFI_IP6_PROTOCOL *This, + IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function polls for incoming data packets and processes outgoing data + packets. Network drivers and applications can call the EFI_IP6_PROTOCOL.Poll() + function to increase the rate that data packets are moved between the communications + device and the transmit and receive queues. + + In some systems the periodic timer event may not poll the underlying communications + device fast enough to transmit and/or receive all data packets without missing + incoming packets or dropping outgoing packets. Drivers and applications that are + experiencing packet loss should try calling the EFI_IP6_PROTOCOL.Poll() function + more often. + + @param[in] This Pointer to the EFI_IP6_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI IPv6 Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_POLL)( + IN EFI_IP6_PROTOCOL *This + ); + +/// +/// The EFI IPv6 Protocol implements a simple packet-oriented interface that can be +/// used by drivers, daemons, and applications to transmit and receive network packets. +/// +struct _EFI_IP6_PROTOCOL { + EFI_IP6_GET_MODE_DATA GetModeData; + EFI_IP6_CONFIGURE Configure; + EFI_IP6_GROUPS Groups; + EFI_IP6_ROUTES Routes; + EFI_IP6_NEIGHBORS Neighbors; + EFI_IP6_TRANSMIT Transmit; + EFI_IP6_RECEIVE Receive; + EFI_IP6_CANCEL Cancel; + EFI_IP6_POLL Poll; +}; + +extern EFI_GUID gEfiIp6ServiceBindingProtocolGuid; +extern EFI_GUID gEfiIp6ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6Config.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6Config.h new file mode 100644 index 0000000..3b76e81 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Ip6Config.h @@ -0,0 +1,374 @@ +/** @file + This file provides a definition of the EFI IPv6 Configuration + Protocol. + +Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#ifndef __EFI_IP6CONFIG_PROTOCOL_H__ +#define __EFI_IP6CONFIG_PROTOCOL_H__ + +#include + +#define EFI_IP6_CONFIG_PROTOCOL_GUID \ + { \ + 0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ + } + +typedef struct _EFI_IP6_CONFIG_PROTOCOL EFI_IP6_CONFIG_PROTOCOL; + +/// +/// EFI_IP6_CONFIG_DATA_TYPE +/// +typedef enum { + /// + /// The interface information of the communication + /// device this EFI IPv6 Configuration Protocol instance manages. + /// This type of data is read only.The corresponding Data is of type + /// EFI_IP6_CONFIG_INTERFACE_INFO. + /// + Ip6ConfigDataTypeInterfaceInfo, + /// + /// The alternative interface ID for the + /// communication device this EFI IPv6 Configuration Protocol + /// instance manages if the link local IPv6 address generated from + /// the interfaced ID based on the default source the EFI IPv6 + /// Protocol uses is a duplicate address. The length of the interface + /// ID is 64 bit. The corresponding Data is of type + /// EFI_IP6_CONFIG_INTERFACE_ID. + /// + Ip6ConfigDataTypeAltInterfaceId, + /// + /// The general configuration policy for the EFI IPv6 network + /// stack running on the communication device this EFI IPv6 + /// Configuration Protocol instance manages. The policy will affect + /// other configuration settings. The corresponding Data is of type + /// EFI_IP6_CONFIG_POLICY. + /// + Ip6ConfigDataTypePolicy, + /// + /// The number of consecutive + /// Neighbor Solicitation messages sent while performing Duplicate + /// Address Detection on a tentative address. A value of zero + /// indicates that Duplicate Address Detection will not be performed + /// on tentative addresses. The corresponding Data is of type + /// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS. + /// + Ip6ConfigDataTypeDupAddrDetectTransmits, + /// + /// The station addresses set manually for the EFI + /// IPv6 network stack. It is only configurable when the policy is + /// Ip6ConfigPolicyManual. The corresponding Data is a + /// pointer to an array of EFI_IPv6_ADDRESS instances. When + /// DataSize is 0 and Data is NULL, the existing configuration + /// is cleared from the EFI IPv6 Configuration Protocol instance. + /// + Ip6ConfigDataTypeManualAddress, + /// + /// The gateway addresses set manually for the EFI IPv6 + /// network stack running on the communication device this EFI + /// IPv6 Configuration Protocol manages. It is not configurable when + /// the policy is Ip6ConfigPolicyAutomatic. The gateway + /// addresses must be unicast IPv6 addresses. The corresponding + /// Data is a pointer to an array of EFI_IPv6_ADDRESS instances. + /// When DataSize is 0 and Data is NULL, the existing configuration + /// is cleared from the EFI IPv6 Configuration Protocol instance. + /// + Ip6ConfigDataTypeGateway, + /// + /// The DNS server list for the EFI IPv6 network stack + /// running on the communication device this EFI IPv6 + /// Configuration Protocol manages. It is not configurable when the + /// policy is Ip6ConfigPolicyAutomatic.The DNS server + /// addresses must be unicast IPv6 addresses. The corresponding + /// Data is a pointer to an array of EFI_IPv6_ADDRESS instances. + /// When DataSize is 0 and Data is NULL, the existing configuration + /// is cleared from the EFI IPv6 Configuration Protocol instance. + /// + Ip6ConfigDataTypeDnsServer, + /// + /// The number of this enumeration memebers. + /// + Ip6ConfigDataTypeMaximum +} EFI_IP6_CONFIG_DATA_TYPE; + +/// +/// EFI_IP6_CONFIG_INTERFACE_INFO +/// describes the operational state of the interface this +/// EFI IPv6 Configuration Protocol instance manages. +/// +typedef struct { + /// + /// The name of the interface. It is a NULL-terminated string. + /// + CHAR16 Name[32]; + /// + /// The interface type of the network interface. + /// + UINT8 IfType; + /// + /// The size, in bytes, of the network interface's hardware address. + /// + UINT32 HwAddressSize; + /// + /// The hardware address for the network interface. + /// + EFI_MAC_ADDRESS HwAddress; + /// + /// Number of EFI_IP6_ADDRESS_INFO structures pointed to by AddressInfo. + /// + UINT32 AddressInfoCount; + /// + /// Pointer to an array of EFI_IP6_ADDRESS_INFO instances + /// which contain the local IPv6 addresses and the corresponding + /// prefix length information. Set to NULL if AddressInfoCount + /// is zero. + /// + EFI_IP6_ADDRESS_INFO *AddressInfo; + /// + /// Number of route table entries in the following RouteTable. + /// + UINT32 RouteCount; + /// + /// The route table of the IPv6 network stack runs on this interface. + /// Set to NULL if RouteCount is zero. + /// + EFI_IP6_ROUTE_TABLE *RouteTable; +} EFI_IP6_CONFIG_INTERFACE_INFO; + +/// +/// EFI_IP6_CONFIG_INTERFACE_ID +/// describes the 64-bit interface ID. +/// +typedef struct { + UINT8 Id[8]; +} EFI_IP6_CONFIG_INTERFACE_ID; + +/// +/// EFI_IP6_CONFIG_POLICY +/// defines the general configuration policy the EFI IPv6 +/// Configuration Protocol supports. +/// +typedef enum { + /// + /// Under this policy, the IpI6ConfigDataTypeManualAddress, + /// Ip6ConfigDataTypeGateway and Ip6ConfigDataTypeDnsServer + /// configuration data are required to be set manually. + /// The EFI IPv6 Protocol will get all required configuration + /// such as address, prefix and gateway settings from the EFI + /// IPv6 Configuration protocol. + /// + Ip6ConfigPolicyManual, + /// + /// Under this policy, the IpI6ConfigDataTypeManualAddress, + /// Ip6ConfigDataTypeGateway and Ip6ConfigDataTypeDnsServer + /// configuration data are not allowed to set via SetData(). + /// All of these configurations are retrieved from some auto + /// configuration mechanism. + /// The EFI IPv6 Protocol will use the IPv6 stateless address + /// autoconfiguration mechanism and/or the IPv6 stateful address + /// autoconfiguration mechanism described in the related RFCs to + /// get address and other configuration information + /// + Ip6ConfigPolicyAutomatic +} EFI_IP6_CONFIG_POLICY; + +/// +/// EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS +/// describes the number of consecutive Neighbor Solicitation messages sent +/// while performing Duplicate Address Detection on a tentative address. +/// The default value for a newly detected communication device is 1. +/// +typedef struct { + UINT32 DupAddrDetectTransmits; ///< The number of consecutive Neighbor Solicitation messages sent. +} EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS; + +/// +/// EFI_IP6_CONFIG_MANUAL_ADDRESS +/// is used to set the station address information for the EFI IPv6 network +/// stack manually when the policy is Ip6ConfigPolicyManual. +/// +typedef struct { + EFI_IPv6_ADDRESS Address; ///< The IPv6 unicast address. + BOOLEAN IsAnycast; ///< Set to TRUE if Address is anycast. + UINT8 PrefixLength; ///< The length, in bits, of the prefix associated with this Address. +} EFI_IP6_CONFIG_MANUAL_ADDRESS; + + +/** + Set the configuration for the EFI IPv6 network stack running on the communication + device this EFI IPv6 Configuration Protocol instance manages. + + This function is used to set the configuration data of type DataType for the EFI + IPv6 network stack running on the communication device this EFI IPv6 Configuration + Protocol instance manages. + + The DataSize is used to calculate the count of structure instances in the Data for + some DataType that multiple structure instances are allowed. + + This function is always non-blocking. When setting some type of configuration data, + an asynchronous process is invoked to check the correctness of the data, such as + doing Duplicate Address Detection on the manually set local IPv6 addresses. + EFI_NOT_READY is returned immediately to indicate that such an asynchronous process + is invoked and the process is not finished yet. The caller willing to get the result + of the asynchronous process is required to call RegisterDataNotify() to register an + event on the specified configuration data. Once the event is signaled, the caller + can call GetData() to get back the configuration data in order to know the result. + For other types of configuration data that do not require an asynchronous configuration + process, the result of the operation is immediately returned. + + @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to set. + @param[in] DataSize Size of the buffer pointed to by Data in bytes. + @param[in] Data The data buffer to set. The type of the data buffer is + associated with the DataType. + + @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 + network stack is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - One or more fields in Data and DataSize do not match the + requirement of the data type indicated by DataType. + @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified + configuration data can not be set under the current policy + @retval EFI_ACCESS_DENIED Another set operation on the specified configuration + data is already in process. + @retval EFI_NOT_READY An asynchronous process is invoked to set the specified + configuration data and the process is not finished yet. + @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type + indicated by DataType. + @retval EFI_UNSUPPORTED This DataType is not supported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CONFIG_SET_DATA)( + IN EFI_IP6_CONFIG_PROTOCOL *This, + IN EFI_IP6_CONFIG_DATA_TYPE DataType, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Get the configuration data for the EFI IPv6 network stack running on the communication + device this EFI IPv6 Configuration Protocol instance manages. + + This function returns the configuration data of type DataType for the EFI IPv6 network + stack running on the communication device this EFI IPv6 Configuration Protocol instance + manages. + + The caller is responsible for allocating the buffer used to return the specified + configuration data and the required size will be returned to the caller if the size of + the buffer is too small. + + EFI_NOT_READY is returned if the specified configuration data is not ready due to an + already in progress asynchronous configuration process. The caller can call RegisterDataNotify() + to register an event on the specified configuration data. Once the asynchronous configuration + process is finished, the event will be signaled and a subsequent GetData() call will return + the specified configuration data. + + @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to get. + @param[in,out] DataSize On input, in bytes, the size of Data. On output, in bytes, the + size of buffer required to store the specified configuration data. + @param[in] Data The data buffer in which the configuration data is returned. The + type of the data buffer is associated with the DataType. + + @retval EFI_SUCCESS The specified configuration data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: + - This is NULL. + - DataSize is NULL. + - Data is NULL if *DataSize is not zero. + @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data + and the required size is returned in DataSize. + @retval EFI_NOT_READY The specified configuration data is not ready due to an already in + progress asynchronous configuration process. + @retval EFI_NOT_FOUND The specified configuration data is not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CONFIG_GET_DATA)( + IN EFI_IP6_CONFIG_PROTOCOL *This, + IN EFI_IP6_CONFIG_DATA_TYPE DataType, + IN OUT UINTN *DataSize, + IN VOID *Data OPTIONAL + ); + +/** + Register an event that is to be signaled whenever a configuration process on the specified + configuration data is done. + + This function registers an event that is to be signaled whenever a configuration process + on the specified configuration data is done. An event can be registered for different DataType + simultaneously and the caller is responsible for determining which type of configuration data + causes the signaling of the event in such case. + + @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to unregister the event for. + @param[in] Event The event to register. + + @retval EFI_SUCCESS The notification event for the specified configuration data is + registered. + @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. + @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not + supported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The Event is already registered for the DataType. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CONFIG_REGISTER_NOTIFY)( + IN EFI_IP6_CONFIG_PROTOCOL *This, + IN EFI_IP6_CONFIG_DATA_TYPE DataType, + IN EFI_EVENT Event + ); + +/** + Remove a previously registered event for the specified configuration data. + + This function removes a previously registered event for the specified configuration data. + + @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to remove the previously registered event for. + @param[in] Event The event to unregister. + + @retval EFI_SUCCESS The event registered for the specified configuration data is removed. + @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. + @retval EFI_NOT_FOUND The Event has not been registered for the specified + DataType. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CONFIG_UNREGISTER_NOTIFY)( + IN EFI_IP6_CONFIG_PROTOCOL *This, + IN EFI_IP6_CONFIG_DATA_TYPE DataType, + IN EFI_EVENT Event + ); + +/// +/// The EFI_IP6_CONFIG_PROTOCOL provides the mechanism to set and get various +/// types of configurations for the EFI IPv6 network stack. +/// +struct _EFI_IP6_CONFIG_PROTOCOL { + EFI_IP6_CONFIG_SET_DATA SetData; + EFI_IP6_CONFIG_GET_DATA GetData; + EFI_IP6_CONFIG_REGISTER_NOTIFY RegisterDataNotify; + EFI_IP6_CONFIG_UNREGISTER_NOTIFY UnregisterDataNotify; +}; + +extern EFI_GUID gEfiIp6ConfigProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSec.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSec.h new file mode 100644 index 0000000..33041c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSec.h @@ -0,0 +1,224 @@ +/** @file + EFI IPSEC Protocol Definition + The EFI_IPSEC_PROTOCOL is used to abstract the ability to deal with the individual + packets sent and received by the host and provide packet-level security for IP + datagram. + The EFI_IPSEC2_PROTOCOL is used to abstract the ability to deal with the individual + packets sent and received by the host and provide packet-level security for IP + datagram. In addition, it supports the Option (extension header) processing in + IPsec which doesn't support in EFI_IPSEC_PROTOCOL. It is also recommended to + use EFI_IPSEC2_PROTOCOL instead of EFI_IPSEC_PROTOCOL especially for IPsec Tunnel + Mode. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + The EFI_IPSEC2_PROTOCOL is introduced in UEFI Specification 2.3D. + +**/ + +#ifndef __EFI_IPSEC_PROTOCOL_H__ +#define __EFI_IPSEC_PROTOCOL_H__ + +#include + +#define EFI_IPSEC_PROTOCOL_GUID \ + { \ + 0xdfb386f7, 0xe100, 0x43ad, {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 } \ + } + +#define EFI_IPSEC2_PROTOCOL_GUID \ + { \ + 0xa3979e64, 0xace8, 0x4ddc, {0xbc, 0x7, 0x4d, 0x66, 0xb8, 0xfd, 0x9, 0x77 } \ + } + +typedef struct _EFI_IPSEC_PROTOCOL EFI_IPSEC_PROTOCOL; +typedef struct _EFI_IPSEC2_PROTOCOL EFI_IPSEC2_PROTOCOL; + +/// +/// EFI_IPSEC_FRAGMENT_DATA +/// defines the instances of packet fragments. +/// +typedef struct _EFI_IPSEC_FRAGMENT_DATA { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_IPSEC_FRAGMENT_DATA; + + +/** + Handles IPsec packet processing for inbound and outbound IP packets. + + The EFI_IPSEC_PROCESS process routine handles each inbound or outbound packet. + The behavior is that it can perform one of the following actions: + bypass the packet, discard the packet, or protect the packet. + + @param[in] This Pointer to the EFI_IPSEC_PROTOCOL instance. + @param[in] NicHandle Instance of the network interface. + @param[in] IpVer IPV4 or IPV6. + @param[in, out] IpHead Pointer to the IP Header. + @param[in] LastHead The protocol of the next layer to be processed by IPsec. + @param[in] OptionsBuffer Pointer to the options buffer. + @param[in] OptionsLength Length of the options buffer. + @param[in, out] FragmentTable Pointer to a list of fragments. + @param[in] FragmentCount Number of fragments. + @param[in] TrafficDirection Traffic direction. + @param[out] RecycleSignal Event for recycling of resources. + + @retval EFI_SUCCESS The packet was bypassed and all buffers remain the same. + @retval EFI_SUCCESS The packet was protected. + @retval EFI_ACCESS_DENIED The packet was discarded. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_PROCESS)( + IN EFI_IPSEC_PROTOCOL *This, + IN EFI_HANDLE NicHandle, + IN UINT8 IpVer, + IN OUT VOID *IpHead, + IN UINT8 *LastHead, + IN VOID *OptionsBuffer, + IN UINT32 OptionsLength, + IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection, + OUT EFI_EVENT *RecycleSignal + ); + +/// +/// EFI_IPSEC_PROTOCOL +/// provides the ability for securing IP communications by authenticating +/// and/or encrypting each IP packet in a data stream. +// EFI_IPSEC_PROTOCOL can be consumed by both the IPv4 and IPv6 stack. +// A user can employ this protocol for IPsec package handling in both IPv4 +// and IPv6 environment. +/// +struct _EFI_IPSEC_PROTOCOL { + EFI_IPSEC_PROCESS Process; ///< Handle the IPsec message. + EFI_EVENT DisabledEvent; ///< Event signaled when the interface is disabled. + BOOLEAN DisabledFlag; ///< State of the interface. +}; + +/** + Handles IPsec processing for both inbound and outbound IP packets. Compare with + Process() in EFI_IPSEC_PROTOCOL, this interface has the capability to process + Option(Extension Header). + + The EFI_IPSEC2_PROCESS process routine handles each inbound or outbound packet. + The behavior is that it can perform one of the following actions: + bypass the packet, discard the packet, or protect the packet. + + @param[in] This Pointer to the EFI_IPSEC2_PROTOCOL instance. + @param[in] NicHandle Instance of the network interface. + @param[in] IpVer IP version.IPv4 or IPv6. + @param[in, out] IpHead Pointer to the IP Header it is either + the EFI_IP4_HEADER or EFI_IP6_HEADER. + On input, it contains the IP header. + On output, 1) in tunnel mode and the + traffic direction is inbound, the buffer + will be reset to zero by IPsec; 2) in + tunnel mode and the traffic direction + is outbound, the buffer will reset to + be the tunnel IP header.3) in transport + mode, the related fielders (like payload + length, Next header) in IP header will + be modified according to the condition. + @param[in, out] LastHead For IP4, it is the next protocol in IP + header. For IP6 it is the Next Header + of the last extension header. + @param[in, out] OptionsBuffer On input, it contains the options + (extensions header) to be processed by + IPsec. On output, 1) in tunnel mode and + the traffic direction is outbound, it + will be set to NULL, and that means this + contents was wrapped after inner header + and should not be concatenated after + tunnel header again; 2) in transport + mode and the traffic direction is inbound, + if there are IP options (extension headers) + protected by IPsec, IPsec will concatenate + the those options after the input options + (extension headers); 3) on other situations, + the output of contents of OptionsBuffer + might be same with input's. The caller + should take the responsibility to free + the buffer both on input and on output. + @param[in, out] OptionsLength On input, the input length of the options + buffer. On output, the output length of + the options buffer. + @param[in, out] FragmentTable Pointer to a list of fragments. On input, + these fragments contain the IP payload. + On output, 1) in tunnel mode and the traffic + direction is inbound, the fragments contain + the whole IP payload which is from the + IP inner header to the last byte of the + packet; 2) in tunnel mode and the traffic + direction is the outbound, the fragments + contains the whole encapsulated payload + which encapsulates the whole IP payload + between the encapsulated header and + encapsulated trailer fields. 3) in transport + mode and the traffic direction is inbound, + the fragments contains the IP payload + which is from the next layer protocol to + the last byte of the packet; 4) in transport + mode and the traffic direction is outbound, + the fragments contains the whole encapsulated + payload which encapsulates the next layer + protocol information between the encapsulated + header and encapsulated trailer fields. + @param[in, out] FragmentCount Number of fragments. + @param[in] TrafficDirection Traffic direction. + @param[out] RecycleSignal Event for recycling of resources. + + @retval EFI_SUCCESS The packet was processed by IPsec successfully. + @retval EFI_ACCESS_DENIED The packet was discarded. + @retval EFI_NOT_READY The IKE negotiation is invoked and the packet + was discarded. + @retval EFI_INVALID_PARAMETER One or more of following are TRUE: + If OptionsBuffer is NULL; + If OptionsLength is NULL; + If FragmentTable is NULL; + If FragmentCount is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_PROCESSEXT) ( + IN EFI_IPSEC2_PROTOCOL *This, + IN EFI_HANDLE NicHandle, + IN UINT8 IpVer, + IN OUT VOID *IpHead, + IN OUT UINT8 *LastHead, + IN OUT VOID **OptionsBuffer, + IN OUT UINT32 *OptionsLength, + IN OUT EFI_IPSEC_FRAGMENT_DATA **FragmentTable, + IN OUT UINT32 *FragmentCount, + IN EFI_IPSEC_TRAFFIC_DIR TrafficDirection, + OUT EFI_EVENT *RecycleSignal + ); + +/// +/// EFI_IPSEC2_PROTOCOL +/// supports the Option (extension header) processing in IPsec which doesn't support +/// in EFI_IPSEC_PROTOCOL. It is also recommended to use EFI_IPSEC2_PROTOCOL instead +/// of EFI_IPSEC_PROTOCOL especially for IPsec Tunnel Mode. +/// provides the ability for securing IP communications by authenticating and/or +/// encrypting each IP packet in a data stream. +/// +struct _EFI_IPSEC2_PROTOCOL { +EFI_IPSEC_PROCESSEXT ProcessExt; +EFI_EVENT DisabledEvent; +BOOLEAN DisabledFlag; +}; + +extern EFI_GUID gEfiIpSecProtocolGuid; +extern EFI_GUID gEfiIpSec2ProtocolGuid; +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSecConfig.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSecConfig.h new file mode 100644 index 0000000..bd869bd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IpSecConfig.h @@ -0,0 +1,807 @@ +/** @file + EFI IPsec Configuration Protocol Definition + The EFI_IPSEC_CONFIG_PROTOCOL provides the mechanism to set and retrieve security and + policy related information for the EFI IPsec protocol driver. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_IPSE_CCONFIG_PROTOCOL_H__ +#define __EFI_IPSE_CCONFIG_PROTOCOL_H__ + + +#define EFI_IPSEC_CONFIG_PROTOCOL_GUID \ + { \ + 0xce5e5929, 0xc7a3, 0x4602, {0xad, 0x9e, 0xc9, 0xda, 0xf9, 0x4e, 0xbf, 0xcf } \ + } + +typedef struct _EFI_IPSEC_CONFIG_PROTOCOL EFI_IPSEC_CONFIG_PROTOCOL; + +/// +/// EFI_IPSEC_CONFIG_DATA_TYPE +/// +typedef enum { + /// + /// The IPsec Security Policy Database (aka SPD) setting. In IPsec, + /// an essential element of Security Association (SA) processing is + /// underlying SPD that specifies what services are to be offered to + /// IP datagram and in what fashion. The SPD must be consulted + /// during the processing of all traffic (inbound and outbound), + /// including traffic not protected by IPsec, that traverses the IPsec + /// boundary. With this DataType, SetData() function is to set + /// the SPD entry information, which may add one new entry, delete + /// one existed entry or flush the whole database according to the + /// parameter values. The corresponding Data is of type + /// EFI_IPSEC_SPD_DATA + /// + IPsecConfigDataTypeSpd, + /// + /// The IPsec Security Association Database (aka SAD) setting. A + /// SA is a simplex connection that affords security services to the + /// traffic carried by it. Security services are afforded to an SA by the + /// use of AH, or ESP, but not both. The corresponding Data is of + /// type EFI_IPSEC_SAD_DATA. + /// + IPsecConfigDataTypeSad, + /// + /// The IPsec Peer Authorization Database (aka PAD) setting, which + /// provides the link between the SPD and a security association + /// management protocol. The PAD entry specifies the + /// authentication protocol (e.g. IKEv1, IKEv2) method used and the + /// authentication data. The corresponding Data is of type + /// EFI_IPSEC_PAD_DATA. + /// + IPsecConfigDataTypePad, + IPsecConfigDataTypeMaximum +} EFI_IPSEC_CONFIG_DATA_TYPE; + +/// +/// EFI_IP_ADDRESS_INFO +/// +typedef struct _EFI_IP_ADDRESS_INFO { + EFI_IP_ADDRESS Address; ///< The IPv4 or IPv6 address + UINT8 PrefixLength; ///< The length of the prefix associated with the Address. +} EFI_IP_ADDRESS_INFO; + + +/// +/// EFI_IPSEC_SPD_SELECTOR +/// +typedef struct _EFI_IPSEC_SPD_SELECTOR { + /// + /// Specifies the actual number of entries in LocalAddress. + /// + UINT32 LocalAddressCount; + /// + /// A list of ranges of IPv4 or IPv6 addresses, which refers to the + /// addresses being protected by IPsec policy. + /// + EFI_IP_ADDRESS_INFO *LocalAddress; + /// + /// Specifies the actual number of entries in RemoteAddress. + /// + UINT32 RemoteAddressCount; + /// + /// A list of ranges of IPv4 or IPv6 addresses, which are peer entities + /// to LocalAddress. + /// + EFI_IP_ADDRESS_INFO *RemoteAddress; + /// + /// Next layer protocol. Obtained from the IPv4 Protocol or the IPv6 + /// Next Header fields. The next layer protocol is whatever comes + /// after any IP extension headers that are present. A zero value is a + /// wildcard that matches any value in NextLayerProtocol field. + /// + UINT16 NextLayerProtocol; + /// + /// Local Port if the Next Layer Protocol uses two ports (as do TCP, + /// UDP, and others). A zero value is a wildcard that matches any + /// value in LocalPort field. + /// + UINT16 LocalPort; + /// + /// A designed port range size. The start port is LocalPort, and + /// the total number of ports is described by LocalPortRange. + /// This field is ignored if NextLayerProtocol does not use + /// ports. + /// + UINT16 LocalPortRange; + /// + /// Remote Port if the Next Layer Protocol uses two ports. A zero + /// value is a wildcard that matches any value in RemotePort field. + /// + UINT16 RemotePort; + /// + /// A designed port range size. The start port is RemotePort, and + /// the total number of ports is described by RemotePortRange. + /// This field is ignored if NextLayerProtocol does not use ports. + /// + UINT16 RemotePortRange; +} EFI_IPSEC_SPD_SELECTOR; + +/// +/// EFI_IPSEC_TRAFFIC_DIR +/// represents the directionality in an SPD entry. +/// +typedef enum { + /// + /// The EfiIPsecInBound refers to traffic entering an IPsec implementation via + /// the unprotected interface or emitted by the implementation on the unprotected + /// side of the boundary and directed towards the protected interface. + /// + EfiIPsecInBound, + /// + /// The EfiIPsecOutBound refers to traffic entering the implementation via + /// the protected interface, or emitted by the implementation on the protected side + /// of the boundary and directed toward the unprotected interface. + /// + EfiIPsecOutBound +} EFI_IPSEC_TRAFFIC_DIR; + +/// +/// EFI_IPSEC_ACTION +/// represents three possible processing choices. +/// +typedef enum { + /// + /// Refers to traffic that is not allowed to traverse the IPsec boundary. + /// + EfiIPsecActionDiscard, + /// + /// Refers to traffic that is allowed to cross the IPsec boundary + /// without protection. + /// + EfiIPsecActionBypass, + /// + /// Refers to traffic that is afforded IPsec protection, and for such + /// traffic the SPD must specify the security protocols to be + /// employed, their mode, security service options, and the + /// cryptographic algorithms to be used. + /// + EfiIPsecActionProtect +} EFI_IPSEC_ACTION; + +/// +/// EFI_IPSEC_SA_LIFETIME +/// defines the lifetime of an SA, which represents when a SA must be +/// replaced or terminated. A value of all 0 for each field removes +/// the limitation of a SA lifetime. +/// +typedef struct _EFI_IPSEC_SA_LIFETIME { + /// + /// The number of bytes to which the IPsec cryptographic algorithm + /// can be applied. For ESP, this is the encryption algorithm and for + /// AH, this is the authentication algorithm. The ByteCount + /// includes pad bytes for cryptographic operations. + /// + UINT64 ByteCount; + /// + /// A time interval in second that warns the implementation to + /// initiate action such as setting up a replacement SA. + /// + UINT64 SoftLifetime; + /// + /// A time interval in second when the current SA ends and is + /// destroyed. + /// + UINT64 HardLifetime; +} EFI_IPSEC_SA_LIFETIME; + +/// +/// EFI_IPSEC_MODE +/// There are two modes of IPsec operation: transport mode and tunnel mode. In +/// EfiIPsecTransport mode, AH and ESP provide protection primarily for next layer protocols; +/// In EfiIPsecTunnel mode, AH and ESP are applied to tunneled IP packets. +/// +typedef enum { + EfiIPsecTransport, + EfiIPsecTunnel +} EFI_IPSEC_MODE; + +/// +/// EFI_IPSEC_TUNNEL_DF_OPTION +/// The option of copying the DF bit from an outbound package to +/// the tunnel mode header that it emits, when traffic is carried +/// via a tunnel mode SA. This applies to SAs where both inner and +/// outer headers are IPv4. +/// +typedef enum { + EfiIPsecTunnelClearDf, ///< Clear DF bit from inner header. + EfiIPsecTunnelSetDf, ///< Set DF bit from inner header. + EfiIPsecTunnelCopyDf ///< Copy DF bit from inner header. +} EFI_IPSEC_TUNNEL_DF_OPTION; + +/// +/// EFI_IPSEC_TUNNEL_OPTION +/// +typedef struct _EFI_IPSEC_TUNNEL_OPTION { + /// + /// Local tunnel address when IPsec mode is EfiIPsecTunnel. + /// + EFI_IP_ADDRESS LocalTunnelAddress; + /// + /// Remote tunnel address when IPsec mode is EfiIPsecTunnel. + /// + EFI_IP_ADDRESS RemoteTunnelAddress; + /// + /// The option of copying the DF bit from an outbound package + /// to the tunnel mode header that it emits, when traffic is + /// carried via a tunnel mode SA. + /// + EFI_IPSEC_TUNNEL_DF_OPTION DF; +} EFI_IPSEC_TUNNEL_OPTION; + +/// +/// EFI_IPSEC_PROTOCOL_TYPE +/// +typedef enum { + EfiIPsecAH, ///< IP Authentication Header protocol which is specified in RFC 4302. + EfiIPsecESP ///< IP Encapsulating Security Payload which is specified in RFC 4303. +} EFI_IPSEC_PROTOCOL_TYPE; + +/// +/// EFI_IPSEC_PROCESS_POLICY +/// describes a policy list for traffic processing. +/// +typedef struct _EFI_IPSEC_PROCESS_POLICY { + /// + /// Extended Sequence Number. Is this SA using extended sequence + /// numbers. 64 bit counter is used if TRUE. + /// + BOOLEAN ExtSeqNum; + /// + /// A flag indicating whether overflow of the sequence number + /// counter should generate an auditable event and prevent + /// transmission of additional packets on the SA, or whether rollover + /// is permitted. + /// + BOOLEAN SeqOverflow; + /// + /// Is this SA using stateful fragment checking. TRUE represents + /// stateful fragment checking. + /// + BOOLEAN FragCheck; + /// + /// A time interval after which a SA must be replaced with a new SA + /// (and new SPI) or terminated. + /// + EFI_IPSEC_SA_LIFETIME SaLifetime; + /// + /// IPsec mode: tunnel or transport. + /// + EFI_IPSEC_MODE Mode; + /// + /// Tunnel Option. TunnelOption is ignored if Mode is EfiIPsecTransport. + /// + EFI_IPSEC_TUNNEL_OPTION *TunnelOption; + /// + /// IPsec protocol: AH or ESP + /// + EFI_IPSEC_PROTOCOL_TYPE Proto; + /// + /// Cryptographic algorithm type used for authentication. + /// + UINT8 AuthAlgoId; + /// + /// Cryptographic algorithm type used for encryption. EncAlgo is + /// NULL when IPsec protocol is AH. For ESP protocol, EncAlgo + /// can also be used to describe the algorithm if a combined mode + /// algorithm is used. + /// + UINT8 EncAlgoId; +} EFI_IPSEC_PROCESS_POLICY; + +/// +/// EFI_IPSEC_SA_ID +/// A triplet to identify an SA, consisting of the following members. +/// +typedef struct _EFI_IPSEC_SA_ID { + /// + /// Security Parameter Index (aka SPI). An arbitrary 32-bit value + /// that is used by a receiver to identity the SA to which an incoming + /// package should be bound. + /// + UINT32 Spi; + /// + /// IPsec protocol: AH or ESP + /// + EFI_IPSEC_PROTOCOL_TYPE Proto; + /// + /// Destination IP address. + /// + EFI_IP_ADDRESS DestAddress; +} EFI_IPSEC_SA_ID; + + +#define MAX_PEERID_LEN 128 + +/// +/// EFI_IPSEC_SPD_DATA +/// +typedef struct _EFI_IPSEC_SPD_DATA { + /// + /// A null-terminated ASCII name string which is used as a symbolic + /// identifier for an IPsec Local or Remote address. + /// + UINT8 Name[MAX_PEERID_LEN]; + /// + /// Bit-mapped list describing Populate from Packet flags. When + /// creating a SA, if PackageFlag bit is set to TRUE, instantiate + /// the selector from the corresponding field in the package that + /// triggered the creation of the SA, else from the value(s) in the + /// corresponding SPD entry. The PackageFlag bit setting for + /// corresponding selector field of EFI_IPSEC_SPD_SELECTOR: + /// Bit 0: EFI_IPSEC_SPD_SELECTOR.LocalAddress + /// Bit 1: EFI_IPSEC_SPD_SELECTOR.RemoteAddress + /// Bit 2: + /// EFI_IPSEC_SPD_SELECTOR.NextLayerProtocol + /// Bit 3: EFI_IPSEC_SPD_SELECTOR.LocalPort + /// Bit 4: EFI_IPSEC_SPD_SELECTOR.RemotePort + /// Others: Reserved. + /// + UINT32 PackageFlag; + /// + /// The traffic direction of data gram. + /// + EFI_IPSEC_TRAFFIC_DIR TrafficDirection; + /// + /// Processing choices to indicate which action is required by this + /// policy. + /// + EFI_IPSEC_ACTION Action; + /// + /// The policy and rule information for a SPD entry. + /// + EFI_IPSEC_PROCESS_POLICY *ProcessingPolicy; + /// + /// Specifies the actual number of entries in SaId list. + /// + UINTN SaIdCount; + /// + /// The SAD entry used for the traffic processing. The + /// existed SAD entry links indicate this is the manual key case. + /// + EFI_IPSEC_SA_ID SaId[1]; +} EFI_IPSEC_SPD_DATA; + +/// +/// EFI_IPSEC_AH_ALGO_INFO +/// The security algorithm selection for IPsec AH authentication. +/// The required authentication algorithm is specified in RFC 4305. +/// +typedef struct _EFI_IPSEC_AH_ALGO_INFO { + UINT8 AuthAlgoId; + UINTN AuthKeyLength; + VOID *AuthKey; +} EFI_IPSEC_AH_ALGO_INFO; + +/// +/// EFI_IPSEC_ESP_ALGO_INFO +/// The security algorithm selection for IPsec ESP encryption and authentication. +/// The required authentication algorithm is specified in RFC 4305. +/// EncAlgoId fields can also specify an ESP combined mode algorithm +/// (e.g. AES with CCM mode, specified in RFC 4309), which provides both +/// confidentiality and authentication services. +/// +typedef struct _EFI_IPSEC_ESP_ALGO_INFO { + UINT8 EncAlgoId; + UINTN EncKeyLength; + VOID *EncKey; + UINT8 AuthAlgoId; + UINTN AuthKeyLength; + VOID *AuthKey; +} EFI_IPSEC_ESP_ALGO_INFO; + +/// +/// EFI_IPSEC_ALGO_INFO +/// +typedef union { + EFI_IPSEC_AH_ALGO_INFO AhAlgoInfo; + EFI_IPSEC_ESP_ALGO_INFO EspAlgoInfo; +} EFI_IPSEC_ALGO_INFO; + +/// +/// EFI_IPSEC_SA_DATA +/// +typedef struct _EFI_IPSEC_SA_DATA { + /// + /// IPsec mode: tunnel or transport. + /// + EFI_IPSEC_MODE Mode; + /// + /// Sequence Number Counter. A 64-bit counter used to generate the + /// sequence number field in AH or ESP headers. + /// + UINT64 SNCount; + /// + /// Anti-Replay Window. A 64-bit counter and a bit-map used to + /// determine whether an inbound AH or ESP packet is a replay. + /// + UINT8 AntiReplayWindows; + /// + /// AH/ESP cryptographic algorithm, key and parameters. + /// + EFI_IPSEC_ALGO_INFO AlgoInfo; + /// + /// Lifetime of this SA. + /// + EFI_IPSEC_SA_LIFETIME SaLifetime; + /// + /// Any observed path MTU and aging variables. The Path MTU + /// processing is defined in section 8 of RFC 4301. + /// + UINT32 PathMTU; + /// + /// Link to one SPD entry. + /// + EFI_IPSEC_SPD_SELECTOR *SpdSelector; + /// + /// Indication of whether it's manually set or negotiated automatically. + /// If ManualSet is FALSE, the corresponding SA entry is inserted through + /// IKE protocol negotiation. + /// + BOOLEAN ManualSet; +} EFI_IPSEC_SA_DATA; + +/// +/// EFI_IPSEC_SA_DATA2 +/// +typedef struct _EFI_IPSEC_SA_DATA2 { + /// + /// IPsec mode: tunnel or transport + /// + EFI_IPSEC_MODE Mode; + /// + /// Sequence Number Counter. A 64-bit counter used to generate the sequence + /// number field in AH or ESP headers. + /// + UINT64 SNCount; + /// + /// Anti-Replay Window. A 64-bit counter and a bit-map used to determine + /// whether an inbound AH or ESP packet is a replay. + /// + UINT8 AntiReplayWindows; + /// + /// AH/ESP cryptographic algorithm, key and parameters. + /// + EFI_IPSEC_ALGO_INFO AlgoInfo; + /// + /// Lifetime of this SA. + /// + EFI_IPSEC_SA_LIFETIME SaLifetime; + /// + /// Any observed path MTU and aging variables. The Path MTU processing is + /// defined in section 8 of RFC 4301. + /// + UINT32 PathMTU; + /// + /// Link to one SPD entry + /// + EFI_IPSEC_SPD_SELECTOR *SpdSelector; + /// + /// Indication of whether it's manually set or negotiated automatically. + /// If ManualSet is FALSE, the corresponding SA entry is inserted through IKE + /// protocol negotiation + /// + BOOLEAN ManualSet; + /// + /// The tunnel header IP source address. + /// + EFI_IP_ADDRESS TunnelSourceAddress; + /// + /// The tunnel header IP destination address. + /// + EFI_IP_ADDRESS TunnelDestinationAddress; +} EFI_IPSEC_SA_DATA2; + + +/// +/// EFI_IPSEC_PAD_ID +/// specifies the identifier for PAD entry, which is also used for SPD lookup. +/// IpAddress Pointer to the IPv4 or IPv6 address range. +/// +typedef struct _EFI_IPSEC_PAD_ID { + /// + /// Flag to identify which type of PAD Id is used. + /// + BOOLEAN PeerIdValid; + union { + /// + /// Pointer to the IPv4 or IPv6 address range. + /// + EFI_IP_ADDRESS_INFO IpAddress; + /// + /// Pointer to a null terminated ASCII string + /// representing the symbolic names. A PeerId can be a DNS + /// name, Distinguished Name, RFC 822 email address or Key ID + /// (specified in section 4.4.3.1 of RFC 4301) + /// + UINT8 PeerId[MAX_PEERID_LEN]; + } Id; +} EFI_IPSEC_PAD_ID; + +/// +/// EFI_IPSEC_CONFIG_SELECTOR +/// describes the expected IPsec configuration data selector +/// of type EFI_IPSEC_CONFIG_DATA_TYPE. +/// +typedef union { + EFI_IPSEC_SPD_SELECTOR SpdSelector; + EFI_IPSEC_SA_ID SaId; + EFI_IPSEC_PAD_ID PadId; +} EFI_IPSEC_CONFIG_SELECTOR; + +/// +/// EFI_IPSEC_AUTH_PROTOCOL_TYPE +/// defines the possible authentication protocol for IPsec +/// security association management. +/// +typedef enum { + EfiIPsecAuthProtocolIKEv1, + EfiIPsecAuthProtocolIKEv2, + EfiIPsecAuthProtocolMaximum +} EFI_IPSEC_AUTH_PROTOCOL_TYPE; + +/// +/// EFI_IPSEC_AUTH_METHOD +/// +typedef enum { + /// + /// Using Pre-shared Keys for manual security associations. + /// + EfiIPsecAuthMethodPreSharedSecret, + /// + /// IKE employs X.509 certificates for SA establishment. + /// + EfiIPsecAuthMethodCertificates, + EfiIPsecAuthMethodMaximum +} EFI_IPSEC_AUTH_METHOD; + +/// +/// EFI_IPSEC_PAD_DATA +/// +typedef struct _EFI_IPSEC_PAD_DATA { + /// + /// Authentication Protocol for IPsec security association management. + /// + EFI_IPSEC_AUTH_PROTOCOL_TYPE AuthProtocol; + /// + /// Authentication method used. + /// + EFI_IPSEC_AUTH_METHOD AuthMethod; + /// + /// The IKE ID payload will be used as a symbolic name for SPD + /// lookup if IkeIdFlag is TRUE. Otherwise, the remote IP + /// address provided in traffic selector playloads will be used. + /// + BOOLEAN IkeIdFlag; + /// + /// The size of Authentication data buffer, in bytes. + /// + UINTN AuthDataSize; + /// + /// Buffer for Authentication data, (e.g., the pre-shared secret or the + /// trust anchor relative to which the peer's certificate will be + /// validated). + /// + VOID *AuthData; + /// + /// The size of RevocationData, in bytes + /// + UINTN RevocationDataSize; + /// + /// Pointer to CRL or OCSP data, if certificates are used for + /// authentication method. + /// + VOID *RevocationData; +} EFI_IPSEC_PAD_DATA; + + +/** + Set the security association, security policy and peer authorization configuration + information for the EFI IPsec driver. + + This function is used to set the IPsec configuration information of type DataType for + the EFI IPsec driver. + The IPsec configuration data has a unique selector/identifier separately to identify + a data entry. The selector structure depends on DataType's definition. + Using SetData() with a Data of NULL causes the IPsec configuration data entry identified + by DataType and Selector to be deleted. + + @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to be set. + @param[in] Selector Pointer to an entry selector on operated configuration data + specified by DataType. A NULL Selector causes the entire + specified-type configuration information to be flushed. + @param[in] Data The data buffer to be set. The structure of the data buffer is + associated with the DataType. + @param[in] InsertBefore Pointer to one entry selector which describes the expected + position the new data entry will be added. If InsertBefore is NULL, + the new entry will be appended the end of database. + + @retval EFI_SUCCESS The specified configuration entry data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + @retval EFI_UNSUPPORTED The specified DataType is not supported. + @retval EFI_OUT_OF_RESOURCED The required system resource could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_CONFIG_SET_DATA)( + IN EFI_IPSEC_CONFIG_PROTOCOL *This, + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN VOID *Data, + IN EFI_IPSEC_CONFIG_SELECTOR *InsertBefore OPTIONAL + ); + +/** + Return the configuration value for the EFI IPsec driver. + + This function lookup the data entry from IPsec database or IKEv2 configuration + information. The expected data type and unique identification are described in + DataType and Selector parameters. + + @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to retrieve. + @param[in] Selector Pointer to an entry selector which is an identifier of the IPsec + configuration data entry. + @param[in, out] DataSize On output the size of data returned in Data. + @param[out] Data The buffer to return the contents of the IPsec configuration data. + The type of the data buffer is associated with the DataType. + + @retval EFI_SUCCESS The specified configuration data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: + - This is NULL. + - Selector is NULL. + - DataSize is NULL. + - Data is NULL and *DataSize is not zero + @retval EFI_NOT_FOUND The configuration data specified by Selector is not found. + @retval EFI_UNSUPPORTED The specified DataType is not supported. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_CONFIG_GET_DATA)( + IN EFI_IPSEC_CONFIG_PROTOCOL *This, + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN EFI_IPSEC_CONFIG_SELECTOR *Selector, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + Enumerates the current selector for IPsec configuration data entry. + + This function is called multiple times to retrieve the entry Selector in IPsec + configuration database. On each call to GetNextSelector(), the next entry + Selector are retrieved into the output interface. + + If the entire IPsec configuration database has been iterated, the error + EFI_NOT_FOUND is returned. + If the Selector buffer is too small for the next Selector copy, an + EFI_BUFFER_TOO_SMALL error is returned, and SelectorSize is updated to reflect + the size of buffer needed. + + On the initial call to GetNextSelector() to start the IPsec configuration database + search, a pointer to the buffer with all zero value is passed in Selector. Calls + to SetData() between calls to GetNextSelector may produce unpredictable results. + + @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. + @param[in] DataType The type of IPsec configuration data to retrieve. + @param[in, out] SelectorSize The size of the Selector buffer. + @param[in, out] Selector On input, supplies the pointer to last Selector that was + returned by GetNextSelector(). + On output, returns one copy of the current entry Selector + of a given DataType. + + @retval EFI_SUCCESS The specified configuration data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: + - This is NULL. + - SelectorSize is NULL. + - Selector is NULL. + @retval EFI_NOT_FOUND The next configuration data entry was not found. + @retval EFI_UNSUPPORTED The specified DataType is not supported. + @retval EFI_BUFFER_TOO_SMALL The SelectorSize is too small for the result. This parameter + has been updated with the size needed to complete the search + request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_CONFIG_GET_NEXT_SELECTOR)( + IN EFI_IPSEC_CONFIG_PROTOCOL *This, + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN OUT UINTN *SelectorSize, + IN OUT EFI_IPSEC_CONFIG_SELECTOR *Selector + ); + +/** + Register an event that is to be signaled whenever a configuration process on the + specified IPsec configuration information is done. + + This function registers an event that is to be signaled whenever a configuration + process on the specified IPsec configuration data is done (e.g. IPsec security + policy database configuration is ready). An event can be registered for different + DataType simultaneously and the caller is responsible for determining which type + of configuration data causes the signaling of the event in such case. + + @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. + @param[in] DataType The type of data to be registered the event for. + @param[in] Event The event to be registered. + + @retval EFI_SUCCESS The event is registered successfully. + @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. + @retval EFI_ACCESS_DENIED The Event is already registered for the DataType. + @retval EFI_UNSUPPORTED The notify registration unsupported or the specified + DataType is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_CONFIG_REGISTER_NOTIFY)( + IN EFI_IPSEC_CONFIG_PROTOCOL *This, + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN EFI_EVENT Event + ); + +/** + Remove the specified event that is previously registered on the specified IPsec + configuration data. + + This function removes a previously registered event for the specified configuration data. + + @param[in] This Pointer to the EFI_IPSEC_CONFIG_PROTOCOL instance. + @param[in] DataType The configuration data type to remove the registered event for. + @param[in] Event The event to be unregistered. + + @retval EFI_SUCCESS The event is removed successfully. + @retval EFI_NOT_FOUND The Event specified by DataType could not be found in the + database. + @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. + @retval EFI_UNSUPPORTED The notify registration unsupported or the specified + DataType is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IPSEC_CONFIG_UNREGISTER_NOTIFY)( + IN EFI_IPSEC_CONFIG_PROTOCOL *This, + IN EFI_IPSEC_CONFIG_DATA_TYPE DataType, + IN EFI_EVENT Event + ); + +/// +/// EFI_IPSEC_CONFIG_PROTOCOL +/// provides the ability to set and lookup the IPsec SAD (Security Association Database), +/// SPD (Security Policy Database) data entry and configure the security association +/// management protocol such as IKEv2. This protocol is used as the central +/// repository of any policy-specific configuration for EFI IPsec driver. +/// EFI_IPSEC_CONFIG_PROTOCOL can be bound to both IPv4 and IPv6 stack. User can use this +/// protocol for IPsec configuration in both IPv4 and IPv6 environment. +/// +struct _EFI_IPSEC_CONFIG_PROTOCOL { + EFI_IPSEC_CONFIG_SET_DATA SetData; + EFI_IPSEC_CONFIG_GET_DATA GetData; + EFI_IPSEC_CONFIG_GET_NEXT_SELECTOR GetNextSelector; + EFI_IPSEC_CONFIG_REGISTER_NOTIFY RegisterDataNotify; + EFI_IPSEC_CONFIG_UNREGISTER_NOTIFY UnregisterDataNotify; +}; + +extern EFI_GUID gEfiIpSecConfigProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IsaHc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IsaHc.h new file mode 100644 index 0000000..db9afb6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/IsaHc.h @@ -0,0 +1,116 @@ +/** @file + ISA HC Protocol as defined in the PI 1.2.1 specification. + + This protocol provides registration for ISA devices on a positive- or + subtractive-decode ISA bus. It allows devices to be registered and also + handles opening and closing the apertures which are positively-decoded. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.2.1. + +**/ + +#ifndef __ISA_HC_PROTOCOL_H__ +#define __ISA_HC_PROTOCOL_H__ + +#define EFI_ISA_HC_PROTOCOL_GUID \ + { \ + 0xbcdaf080, 0x1bde, 0x4e22, {0xae, 0x6a, 0x43, 0x54, 0x1e, 0x12, 0x8e, 0xc4} \ + } + +#define EFI_ISA_HC_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xfad7933a, 0x6c21, 0x4234, {0xa4, 0x34, 0x0a, 0x8a, 0x0d, 0x2b, 0x07, 0x81} \ + } + +typedef struct _EFI_ISA_HC_PROTOCOL EFI_ISA_HC_PROTOCOL; +typedef struct _EFI_ISA_HC_PROTOCOL *PEFI_ISA_HC_PROTOCOL; + +/** + Open I/O aperture. + + This function opens an I/O aperture in a ISA Host Controller for the I/O addresses + specified by IoAddress to IoAddress + IoLength - 1. It may be possible that a + single hardware aperture may be used for more than one device. This function + tracks the number of times that each aperture is referenced, and does not close + the hardware aperture (via CloseIoAperture()) until there are no more references to it. + + @param This A pointer to this instance of the EFI_ISA_HC_PROTOCOL. + @param IoAddress An unsigned integer that specifies the first byte of the + I/O space required. + @param IoLength An unsigned integer that specifies the number of bytes + of the I/O space required. + @param IoApertureHandle A pointer to the returned I/O aperture handle. This + value can be used on subsequent calls to CloseIoAperture(). + + @retval EFI_SUCCESS The I/O aperture was opened successfully. + @retval EFI_UNSUPPORTED The ISA Host Controller is a subtractive-decode controller. + @retval EFI_OUT_OF_RESOURCES There is no available I/O aperture. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_HC_OPEN_IO) ( + IN CONST EFI_ISA_HC_PROTOCOL *This, + IN UINT16 IoAddress, + IN UINT16 IoLength, + OUT UINT64 *IoApertureHandle + ); + +/** + Close I/O aperture. + + This function closes a previously opened I/O aperture handle. If there are no + more I/O aperture handles that refer to the hardware I/O aperture resource, + then the hardware I/O aperture is closed. It may be possible that a single + hardware aperture may be used for more than one device. This function tracks + the number of times that each aperture is referenced, and does not close the + hardware aperture (via CloseIoAperture()) until there are no more references to it. + + @param This A pointer to this instance of the EFI_ISA_HC_PROTOCOL. + @param IoApertureHandle The I/O aperture handle previously returned from a + call to OpenIoAperture(). + + @retval EFI_SUCCESS The IO aperture was closed successfully. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_HC_CLOSE_IO) ( + IN CONST EFI_ISA_HC_PROTOCOL *This, + IN UINT64 IoApertureHandle + ); + +/// +/// ISA HC Protocol +/// +struct _EFI_ISA_HC_PROTOCOL { + /// + /// The version of this protocol. Higher version numbers are backward + /// compatible with lower version numbers. + /// + UINT32 Version; + /// + /// Open an I/O aperture. + /// + EFI_ISA_HC_OPEN_IO OpenIoAperture; + /// + /// Close an I/O aperture. + /// + EFI_ISA_HC_CLOSE_IO CloseIoAperture; +}; + +/// +/// Reference to variable defined in the .DEC file +/// +extern EFI_GUID gEfiIsaHcProtocolGuid; +extern EFI_GUID gEfiIsaHcServiceBindingProtocolGuid; + +#endif // __ISA_HC_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Kms.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Kms.h new file mode 100644 index 0000000..64e47f4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Kms.h @@ -0,0 +1,1343 @@ +/** @file + The Key Management Service (KMS) protocol as defined in the UEFI 2.3.1 specification is to + provides services to generate, store, retrieve, and manage cryptographic keys. + The intention is to specify a simple generic protocol that could be used for many implementations. + + A driver implementing the protocol may need to provide basic key service that consists of a + key store and cryptographic key generation capability. It may connect to an external key + server over the network, or to a Hardware Security Module (HSM) attached to the system it + runs on, or anything else that is capable of providing the key management service. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __KMS_H__ +#define __KMS_H__ + +#define EFI_KMS_PROTOCOL_GUID \ + { \ + 0xEC3A978D, 0x7C4E, 0x48FA, {0x9A, 0xBE, 0x6A, 0xD9, 0x1C, 0xC8, 0xF8, 0x11 } \ + } + +typedef struct _EFI_KMS_PROTOCOL EFI_KMS_PROTOCOL; + +// +// Where appropriate, EFI_KMS_DATA_TYPE values may be combined using a bitwise 'OR' +// operation to indicate support for multiple data types. +// +#define EFI_KMS_DATA_TYPE_NONE 0 +#define EFI_KMS_DATA_TYPE_BINARY 1 +#define EFI_KMS_DATA_TYPE_ASCII 2 +#define EFI_KMS_DATA_TYPE_UNICODE 4 +#define EFI_KMS_DATA_TYPE_UTF8 8 + + +// +// The key formats recognized by the KMS protocol are defined by an EFI_GUID which specifies +// a (key-algorithm, key-size) pair. The names of these GUIDs are in the format +// EFI_KMS_KEY_(key-algorithm)_(key-size)_GUID, where the key-size is expressed in bits. +// The key formats recognized fall into three categories, generic (no algorithm), hash algorithms, +// and encrypted algorithms. +// + +/// +/// The following GUIDs define formats that contain generic key data of a specific size in bits, +/// but which is not associated with any specific key algorithm(s). +///@{ +#define EFI_KMS_FORMAT_GENERIC_128_GUID \ + { \ + 0xec8a3d69, 0x6ddf, 0x4108, {0x94, 0x76, 0x73, 0x37, 0xfc, 0x52, 0x21, 0x36 } \ + } +#define EFI_KMS_FORMAT_GENERIC_160_GUID \ + { \ + 0xa3b3e6f8, 0xefca, 0x4bc1, {0x88, 0xfb, 0xcb, 0x87, 0x33, 0x9b, 0x25, 0x79 } \ + } +#define EFI_KMS_FORMAT_GENERIC_256_GUID \ + { \ + 0x70f64793, 0xc323, 0x4261, {0xac, 0x2c, 0xd8, 0x76, 0xf2, 0x7c, 0x53, 0x45 } \ + } +#define EFI_KMS_FORMAT_GENERIC_512_GUID \ + { \ + 0x978fe043, 0xd7af, 0x422e, {0x8a, 0x92, 0x2b, 0x48, 0xe4, 0x63, 0xbd, 0xe6 } \ + } +#define EFI_KMS_FORMAT_GENERIC_1024_GUID \ + { \ + 0x43be0b44, 0x874b, 0x4ead, {0xb0, 0x9c, 0x24, 0x1a, 0x4f, 0xbd, 0x7e, 0xb3 } \ + } +#define EFI_KMS_FORMAT_GENERIC_2048_GUID \ + { \ + 0x40093f23, 0x630c, 0x4626, {0x9c, 0x48, 0x40, 0x37, 0x3b, 0x19, 0xcb, 0xbe } \ + } +#define EFI_KMS_FORMAT_GENERIC_3072_GUID \ + { \ + 0xb9237513, 0x6c44, 0x4411, {0xa9, 0x90, 0x21, 0xe5, 0x56, 0xe0, 0x5a, 0xde } \ + } +#define EFI_KMS_FORMAT_GENERIC_DYNAMIC_GUID \ + { \ + 0x2156e996, 0x66de, 0x4b27, {0x9c, 0xc9, 0xb0, 0x9f, 0xac, 0x4d, 0x2, 0xbe } \ + } +///@} + +/// +/// These GUIDS define key data formats that contain data generated by basic hash algorithms +/// with no cryptographic properties. +///@{ +#define EFI_KMS_FORMAT_MD2_128_GUID \ + { \ + 0x78be11c4, 0xee44, 0x4a22, {0x9f, 0x05, 0x03, 0x85, 0x2e, 0xc5, 0xc9, 0x78 } \ + } +#define EFI_KMS_FORMAT_MDC2_128_GUID \ + { \ + 0xf7ad60f8, 0xefa8, 0x44a3, {0x91, 0x13, 0x23, 0x1f, 0x39, 0x9e, 0xb4, 0xc7 } \ + } +#define EFI_KMS_FORMAT_MD4_128_GUID \ + { \ + 0xd1c17aa1, 0xcac5, 0x400f, {0xbe, 0x17, 0xe2, 0xa2, 0xae, 0x06, 0x67, 0x7c } \ + } +#define EFI_KMS_FORMAT_MDC4_128_GUID \ + { \ + 0x3fa4f847, 0xd8eb, 0x4df4, {0xbd, 0x49, 0x10, 0x3a, 0x0a, 0x84, 0x7b, 0xbc } \ + } +#define EFI_KMS_FORMAT_MD5_128_GUID \ + { \ + 0xdcbc3662, 0x9cda, 0x4b52, {0xa0, 0x4c, 0x82, 0xeb, 0x1d, 0x23, 0x48, 0xc7 } \ + } +#define EFI_KMS_FORMAT_MD5SHA_128_GUID \ + { \ + 0x1c178237, 0x6897, 0x459e, {0x9d, 0x36, 0x67, 0xce, 0x8e, 0xf9, 0x4f, 0x76 } \ + } +#define EFI_KMS_FORMAT_SHA1_160_GUID \ + { \ + 0x453c5e5a, 0x482d, 0x43f0, {0x87, 0xc9, 0x59, 0x41, 0xf3, 0xa3, 0x8a, 0xc2 } \ + } +#define EFI_KMS_FORMAT_SHA256_256_GUID \ + { \ + 0x6bb4f5cd, 0x8022, 0x448d, {0xbc, 0x6d, 0x77, 0x1b, 0xae, 0x93, 0x5f, 0xc6 } \ + } +#define EFI_KMS_FORMAT_SHA512_512_GUID \ + { \ + 0x2f240e12, 0xe14d, 0x475c, {0x83, 0xb0, 0xef, 0xff, 0x22, 0xd7, 0x7b, 0xe7 } \ + } +///@} + +/// +/// These GUIDs define key data formats that contain data generated by cryptographic key algorithms. +/// There may or may not be a separate data hashing algorithm associated with the key algorithm. +///@{ +#define EFI_KMS_FORMAT_AESXTS_128_GUID \ + { \ + 0x4776e33f, 0xdb47, 0x479a, {0xa2, 0x5f, 0xa1, 0xcd, 0x0a, 0xfa, 0xb3, 0x8b } \ + } +#define EFI_KMS_FORMAT_AESXTS_256_GUID \ + { \ + 0xdc7e8613, 0xc4bb, 0x4db0, {0x84, 0x62, 0x13, 0x51, 0x13, 0x57, 0xab, 0xe2 } \ + } +#define EFI_KMS_FORMAT_AESCBC_128_GUID \ + { \ + 0xa0e8ee6a, 0x0e92, 0x44d4, {0x86, 0x1b, 0x0e, 0xaa, 0x4a, 0xca, 0x44, 0xa2 } \ + } +#define EFI_KMS_FORMAT_AESCBC_256_GUID \ + { \ + 0xd7e69789, 0x1f68, 0x45e8, {0x96, 0xef, 0x3b, 0x64, 0x07, 0xa5, 0xb2, 0xdc } \ + } +#define EFI_KMS_FORMAT_RSASHA1_1024_GUID \ + { \ + 0x56417bed, 0x6bbe, 0x4882, {0x86, 0xa0, 0x3a, 0xe8, 0xbb, 0x17, 0xf8, 0xf9 } \ + } +#define EFI_KMS_FORMAT_RSASHA1_2048_GUID \ + { \ + 0xf66447d4, 0x75a6, 0x463e, {0xa8, 0x19, 0x07, 0x7f, 0x2d, 0xda, 0x05, 0xe9 } \ + } +#define EFI_KMS_FORMAT_RSASHA256_2048_GUID \ + { \ + 0xa477af13, 0x877d, 0x4060, {0xba, 0xa1, 0x25, 0xd1, 0xbe, 0xa0, 0x8a, 0xd3 } \ + } +#define EFI_KMS_FORMAT_RSASHA256_3072_GUID \ + { \ + 0x4e1356c2, 0xeed, 0x463f, {0x81, 0x47, 0x99, 0x33, 0xab, 0xdb, 0xc7, 0xd5 } \ + } +///@} + +#define EFI_KMS_ATTRIBUTE_TYPE_NONE 0x00 +#define EFI_KMS_ATTRIBUTE_TYPE_INTEGER 0x01 +#define EFI_KMS_ATTRIBUTE_TYPE_LONG_INTEGER 0x02 +#define EFI_KMS_ATTRIBUTE_TYPE_BIG_INTEGER 0x03 +#define EFI_KMS_ATTRIBUTE_TYPE_ENUMERATION 0x04 +#define EFI_KMS_ATTRIBUTE_TYPE_BOOLEAN 0x05 +#define EFI_KMS_ATTRIBUTE_TYPE_BYTE_STRING 0x06 +#define EFI_KMS_ATTRIBUTE_TYPE_TEXT_STRING 0x07 +#define EFI_KMS_ATTRIBUTE_TYPE_DATE_TIME 0x08 +#define EFI_KMS_ATTRIBUTE_TYPE_INTERVAL 0x09 +#define EFI_KMS_ATTRIBUTE_TYPE_STRUCTURE 0x0A +#define EFI_KMS_ATTRIBUTE_TYPE_DYNAMIC 0x0B + +typedef struct { + /// + /// Length in bytes of the KeyData. + /// + UINT32 KeySize; + /// + /// The data of the key. + /// + UINT8 KeyData[1]; +} EFI_KMS_FORMAT_GENERIC_DYNAMIC; + +typedef struct { + /// + /// The size in bytes for the client identifier. + /// + UINT16 ClientIdSize; + /// + /// Pointer to a valid client identifier. + /// + VOID *ClientId; + /// + /// The client name string type used by this client. The string type set here must be one of + /// the string types reported in the ClientNameStringTypes field of the KMS protocol. If the + /// KMS does not support client names, this field should be set to EFI_KMS_DATA_TYPE_NONE. + /// + UINT8 ClientNameType; + /// + /// The size in characters for the client name. This field will be ignored if + /// ClientNameStringType is set to EFI_KMS_DATA_TYPE_NONE. Otherwise, it must contain + /// number of characters contained in the ClientName field. + /// + UINT8 ClientNameCount; + /// + /// Pointer to a client name. This field will be ignored if ClientNameStringType is set to + /// EFI_KMS_DATA_TYPE_NONE. Otherwise, it must point to a valid string of the specified type. + /// + VOID *ClientName; +} EFI_KMS_CLIENT_INFO; + +typedef struct { + /// + /// The size of the KeyIdentifier field in bytes. This field is limited to the range 0 to 255. + /// + UINT8 KeyIdentifierSize; + /// + /// Pointer to an array of KeyIdentifierType elements. + /// + VOID *KeyIdentifier; + /// + /// An EFI_GUID which specifies the algorithm and key value size for this key. + /// + EFI_GUID KeyFormat; + /// + /// Pointer to a key value for a key specified by the KeyFormat field. A NULL value for this + /// field indicates that no key is available. + /// + VOID *KeyValue; + /// + /// Specifies the results of KMS operations performed with this descriptor. This field is used + /// to indicate the status of individual operations when a KMS function is called with multiple + /// EFI_KMS_KEY_DESCRIPTOR structures. + /// KeyStatus codes returned for the individual key requests are: + /// EFI_SUCCESS Successfully processed this key. + /// EFI_WARN_STALE_DATA Successfully processed this key, however, the key's parameters + /// exceed internal policies/limits and should be replaced. + /// EFI_COMPROMISED_DATA Successfully processed this key, but the key may have been + /// compromised and must be replaced. + /// EFI_UNSUPPORTED Key format is not supported by the service. + /// EFI_OUT_OF_RESOURCES Could not allocate resources for the key processing. + /// EFI_TIMEOUT Timed out waiting for device or key server. + /// EFI_DEVICE_ERROR Device or key server error. + /// EFI_INVALID_PARAMETER KeyFormat is invalid. + /// EFI_NOT_FOUND The key does not exist on the KMS. + /// + EFI_STATUS KeyStatus; +} EFI_KMS_KEY_DESCRIPTOR; + +typedef struct { + /// + /// Part of a tag-type-length triplet that identifies the KeyAttributeData formatting. The + /// definition of the value is outside the scope of this standard and may be defined by the KMS. + /// + UINT16 Tag; + /// + /// Part of a tag-type-length triplet that identifies the KeyAttributeData formatting. The + /// definition of the value is outside the scope of this standard and may be defined by the KMS. + /// + UINT16 Type; + /// + /// Length in bytes of the KeyAttributeData. + /// + UINT32 Length; + /// + /// An array of bytes to hold the attribute data associated with the KeyAttributeIdentifier. + /// + UINT8 KeyAttributeData[1]; +} EFI_KMS_DYNAMIC_FIELD; + +typedef struct { + /// + /// The number of members in the EFI_KMS_DYNAMIC_ATTRIBUTE structure. + /// + UINT32 FieldCount; + /// + /// An array of EFI_KMS_DYNAMIC_FIELD structures. + /// + EFI_KMS_DYNAMIC_FIELD Field[1]; +} EFI_KMS_DYNAMIC_ATTRIBUTE; + +typedef struct { + /// + /// The data type used for the KeyAttributeIdentifier field. Values for this field are defined + /// by the EFI_KMS_DATA_TYPE constants, except that EFI_KMS_DATA_TYPE_BINARY is not + /// valid for this field. + /// + UINT8 KeyAttributeIdentifierType; + /// + /// The length of the KeyAttributeIdentifier field in units defined by KeyAttributeIdentifierType + /// field. This field is limited to the range 0 to 255. + /// + UINT8 KeyAttributeIdentifierCount; + /// + /// Pointer to an array of KeyAttributeIdentifierType elements. For string types, there must + /// not be a null-termination element at the end of the array. + /// + VOID *KeyAttributeIdentifier; + /// + /// The instance number of this attribute. If there is only one instance, the value is set to + /// one. If this value is set to 0xFFFF (all binary 1's) then this field should be ignored if an + /// output or treated as a wild card matching any value if it is an input. If the attribute is + /// stored with this field, it will match any attribute request regardless of the setting of the + /// field in the request. If set to 0xFFFF in the request, it will match any attribute with the + /// same KeyAttributeIdentifier. + /// + UINT16 KeyAttributeInstance; + /// + /// The data type of the KeyAttributeValue (e.g. struct, bool, etc.). See the list of + /// KeyAttributeType definitions. + /// + UINT16 KeyAttributeType; + /// + /// The size in bytes of the KeyAttribute field. A value of zero for this field indicates that no + /// key attribute value is available. + /// + UINT16 KeyAttributeValueSize; + /// + /// Pointer to a key attribute value for the attribute specified by the KeyAttributeIdentifier + /// field. If the KeyAttributeValueSize field is zero, then this field must be NULL. + /// + VOID *KeyAttributeValue; + /// + /// KeyAttributeStatusSpecifies the results of KMS operations performed with this attribute. + /// This field is used to indicate the status of individual operations when a KMS function is + /// called with multiple EFI_KMS_KEY_ATTRIBUTE structures. + /// KeyAttributeStatus codes returned for the individual key attribute requests are: + /// EFI_SUCCESS Successfully processed this request. + /// EFI_WARN_STALE_DATA Successfully processed this request, however, the key's + /// parameters exceed internal policies/limits and should be replaced. + /// EFI_COMPROMISED_DATA Successfully processed this request, but the key may have been + /// compromised and must be replaced. + /// EFI_UNSUPPORTED Key attribute format is not supported by the service. + /// EFI_OUT_OF_RESOURCES Could not allocate resources for the request processing. + /// EFI_TIMEOUT Timed out waiting for device or key server. + /// EFI_DEVICE_ERROR Device or key server error. + /// EFI_INVALID_PARAMETER A field in the EFI_KMS_KEY_ATTRIBUTE structure is invalid. + /// EFI_NOT_FOUND The key attribute does not exist on the KMS. + /// + EFI_STATUS KeyAttributeStatus; +} EFI_KMS_KEY_ATTRIBUTE; + +/** + Get the current status of the key management service. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + + @retval EFI_SUCCESS The KMS is ready for use. + @retval EFI_NOT_READY No connection to the KMS is available. + @retval EFI_NO_MAPPING No valid connection configuration exists for the KMS. + @retval EFI_NO_RESPONSE No response was received from the KMS. + @retval EFI_DEVICE_ERROR An error occurred when attempting to access the KMS. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_GET_SERVICE_STATUS) ( + IN EFI_KMS_PROTOCOL *This + ); + +/** + Register client information with the supported KMS. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS The client information has been accepted by the KMS. + @retval EFI_NOT_READY No connection to the KMS is available. + @retval EFI_NO_RESPONSE There was no response from the device or the key server. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server. + @retval EFI_DEVICE_ERROR An error occurred when attempting to access the KMS. + @retval EFI_OUT_OF_RESOURCES Required resources were not available to perform the function. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_UNSUPPORTED The KMS does not support the use of client identifiers. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_REGISTER_CLIENT) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Request that the KMS generate one or more new keys and associate them with key identifiers. + The key value(s) is returned to the caller. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in, out] KeyDescriptorCount Pointer to a count of the number of key descriptors to be + processed by this operation. On return, this number + will be updated with the number of key descriptors + successfully processed. + @param[in, out] KeyDescriptors Pointer to an array of EFI_KMS_KEY_DESCRIPTOR + structures which describe the keys to be generated. + On input, the KeyIdentifierSize and the KeyIdentifier + may specify an identifier to be used for the key, + but this is not required. The KeyFormat field must + specify a key format GUID reported as supported by + the KeyFormats field of the EFI_KMS_PROTOCOL. + The value for this field in the first key descriptor will + be considered the default value for subsequent key + descriptors requested in this operation if those key + descriptors have a NULL GUID in the key format field. + On output, the KeyIdentifierSize and KeyIdentifier fields + will specify an identifier for the key which will be either + the original identifier if one was provided, or an identifier + generated either by the KMS or the KMS protocol + implementation. The KeyFormat field will be updated + with the GUID used to generate the key if it was a + NULL GUID, and the KeyValue field will contain a pointer + to memory containing the key value for the generated + key. Memory for both the KeyIdentifier and the KeyValue + fields will be allocated with the BOOT_SERVICES_DATA + type and must be freed by the caller when it is no longer + needed. Also, the KeyStatus field must reflect the result + of the request relative to that key. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully generated and retrieved all requested keys. + @retval EFI_UNSUPPORTED This function is not supported by the KMS. --OR-- + One (or more) of the key requests submitted is not supported by + the KMS. Check individual key request(s) to see which ones + may have been processed. + @retval EFI_OUT_OF_RESOURCES Required resources were not available to perform the function. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + request(s) to see which ones may have been processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either no id was + provided or an invalid id was provided. + @retval EFI_DEVICE_ERROR An error occurred when attempting to access the KMS. Check + individual key request(s) to see which ones may have been + processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyDescriptorCount is NULL, or Keys is NULL. + @retval EFI_NOT_FOUND One or more EFI_KMS_KEY_DESCRIPTOR structures + could not be processed properly. KeyDescriptorCount + contains the number of structures which were successfully + processed. Individual structures will reflect the status of the + processing for that structure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_CREATE_KEY) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN OUT UINT16 *KeyDescriptorCount, + IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptors, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Retrieve an existing key. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in, out] KeyDescriptorCount Pointer to a count of the number of key descriptors to be + processed by this operation. On return, this number + will be updated with the number of key descriptors + successfully processed. + @param[in, out] KeyDescriptors Pointer to an array of EFI_KMS_KEY_DESCRIPTOR + structures which describe the keys to be retrieved + from the KMS. + On input, the KeyIdentifierSize and the KeyIdentifier + must specify an identifier to be used to retrieve a + specific key. All other fields in the descriptor should + be NULL. + On output, the KeyIdentifierSize and KeyIdentifier fields + will be unchanged, while the KeyFormat and KeyValue + fields will be updated values associated with this key + identifier. Memory for the KeyValue field will be + allocated with the BOOT_SERVICES_DATA type and + must be freed by the caller when it is no longer needed. + Also, the KeyStatus field will reflect the result of the + request relative to the individual key descriptor. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully retrieved all requested keys. + @retval EFI_OUT_OF_RESOURCES Could not allocate resources for the method processing. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + request(s) to see which ones may have been processed. + @retval EFI_BUFFER_TOO_SMALL If multiple keys are associated with a single identifier, and the + KeyValue buffer does not contain enough structures + (KeyDescriptorCount) to contain all the key data, then + the available structures will be filled and + KeyDescriptorCount will be updated to indicate the + number of keys which could not be processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key request(s) to + see which ones may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyDescriptorCount is NULL, or Keys is NULL. + @retval EFI_NOT_FOUND One or more EFI_KMS_KEY_DESCRIPTOR structures + could not be processed properly. KeyDescriptorCount + contains the number of structures which were successfully + processed. Individual structures will reflect the status of the + processing for that structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_GET_KEY) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN OUT UINT16 *KeyDescriptorCount, + IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptors, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Add a new key. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in, out] KeyDescriptorCount Pointer to a count of the number of key descriptors to be + processed by this operation. On normal return, this + number will be updated with the number of key + descriptors successfully processed. + @param[in, out] KeyDescriptors Pointer to an array of EFI_KMS_KEY_DESCRIPTOR + structures which describe the keys to be added. + On input, the KeyId field for first key must contain + valid identifier data to be used for adding a key to + the KMS. The values for these fields in this key + definition will be considered default values for + subsequent keys requested in this operation. A value + of 0 in any subsequent KeyId field will be replaced + with the current default value. The KeyFormat and + KeyValue fields for each key to be added must contain + consistent values to be associated with the given KeyId. + On return, the KeyStatus field will reflect the result + of the operation for each key request. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully added all requested keys. + @retval EFI_OUT_OF_RESOURCES Could not allocate required resources. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + request(s) to see which ones may have been processed. + @retval EFI_BUFFER_TOO_SMALL If multiple keys are associated with a single identifier, and the + KeyValue buffer does not contain enough structures + (KeyDescriptorCount) to contain all the key data, then + the available structures will be filled and + KeyDescriptorCount will be updated to indicate the + number of keys which could not be processed + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key request(s) to + see which ones may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyDescriptorCount is NULL, or Keys is NULL. + @retval EFI_NOT_FOUND One or more EFI_KMS_KEY_DESCRIPTOR structures + could not be processed properly. KeyDescriptorCount + contains the number of structures which were successfully + processed. Individual structures will reflect the status of the + processing for that structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_ADD_KEY) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN OUT UINT16 *KeyDescriptorCount, + IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptors, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Delete an existing key from the KMS database. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in, out] KeyDescriptorCount Pointer to a count of the number of key descriptors to be + processed by this operation. On normal return, this + number will be updated with the number of key + descriptors successfully processed. + @param[in, out] KeyDescriptors Pointer to an array of EFI_KMS_KEY_DESCRIPTOR + structures which describe the keys to be deleted. + On input, the KeyId field for first key must contain + valid identifier data to be used for adding a key to + the KMS. The values for these fields in this key + definition will be considered default values for + subsequent keys requested in this operation. A value + of 0 in any subsequent KeyId field will be replaced + with the current default value. The KeyFormat and + KeyValue fields are ignored, but should be 0. + On return, the KeyStatus field will reflect the result + of the operation for each key request. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully deleted all requested keys. + @retval EFI_OUT_OF_RESOURCES Could not allocate required resources. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + request(s) to see which ones may have been processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key request(s) to + see which ones may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyDescriptorCount is NULL, or Keys is NULL. + @retval EFI_NOT_FOUND One or more EFI_KMS_KEY_DESCRIPTOR structures + could not be processed properly. KeyDescriptorCount + contains the number of structures which were successfully + processed. Individual structures will reflect the status of the + processing for that structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_DELETE_KEY) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN OUT UINT16 *KeyDescriptorCount, + IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptors, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Get one or more attributes associated with a specified key identifier. + If none are found, the returned attributes count contains a value of zero. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in] KeyIdentifierSize Pointer to the size in bytes of the KeyIdentifier variable. + @param[in] KeyIdentifier Pointer to the key identifier associated with this key. + @param[in, out] KeyAttributesCount Pointer to the number of EFI_KMS_KEY_ATTRIBUTE + structures associated with the Key identifier. If none + are found, the count value is zero on return. + On input this value reflects the number of KeyAttributes + that may be returned. + On output, the value reflects the number of completed + KeyAttributes structures found. + @param[in, out] KeyAttributes Pointer to an array of EFI_KMS_KEY_ATTRIBUTE + structures associated with the Key Identifier. + On input, the fields in the structure should be NULL. + On output, the attribute fields will have updated values + for attributes associated with this key identifier. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully retrieved all key attributes. + @retval EFI_OUT_OF_RESOURCES Could not allocate resources for the method processing. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + attribute request(s) to see which ones may have been + processed. + @retval EFI_BUFFER_TOO_SMALL If multiple key attributes are associated with a single identifier, + and the KeyAttributes buffer does not contain enough + structures (KeyAttributesCount) to contain all the key + attributes data, then the available structures will be filled and + KeyAttributesCount will be updated to indicate the + number of key attributes which could not be processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key attribute + request(s) (i.e. key attribute status for each) to see which ones + may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyIdentifierSize is NULL , or KeyIdentifier + is NULL, or KeyAttributes is NULL, or + KeyAttributesSize is NULL. + @retval EFI_NOT_FOUND The KeyIdentifier could not be found. + KeyAttributesCount contains zero. Individual + structures will reflect the status of the processing for that + structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_GET_KEY_ATTRIBUTES) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN UINT8 *KeyIdentifierSize, + IN CONST VOID *KeyIdentifier, + IN OUT UINT16 *KeyAttributesCount, + IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Add one or more attributes to a key specified by a key identifier. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in] KeyIdentifierSize Pointer to the size in bytes of the KeyIdentifier variable. + @param[in] KeyIdentifier Pointer to the key identifier associated with this key. + @param[in, out] KeyAttributesCount Pointer to the number of EFI_KMS_KEY_ATTRIBUTE + structures to associate with the Key. On normal returns, + this number will be updated with the number of key + attributes successfully processed. + @param[in, out] KeyAttributes Pointer to an array of EFI_KMS_KEY_ATTRIBUTE + structures providing the attribute information to + associate with the key. + On input, the values for the fields in the structure + are completely filled in. + On return the KeyAttributeStatus field will reflect the + result of the operation for each key attribute request. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully added all requested key attributes. + @retval EFI_OUT_OF_RESOURCES Could not allocate required resources. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + attribute request(s) to see which ones may have been + processed. + @retval EFI_BUFFER_TOO_SMALL If multiple keys attributes are associated with a single key + identifier, and the attributes buffer does not contain + enough structures (KeyAttributesCount) to contain all + the data, then the available structures will be filled and + KeyAttributesCount will be updated to indicate the + number of key attributes which could not be processed. The + status of each key attribute is also updated indicating success or + failure for that attribute in case there are other errors for those + attributes that could be processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key attribute + request(s) (i.e. key attribute status for each) to see which ones + may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyAttributesCount is NULL, or KeyAttributes + is NULL, or KeyIdentifierSize is NULL, or + KeyIdentifer is NULL. + @retval EFI_NOT_FOUND The KeyIdentifier could not be found. On return the + KeyAttributesCount contains the number of attributes + processed. Individual structures will reflect the status of the + processing for that structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_ADD_KEY_ATTRIBUTES) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN UINT8 *KeyIdentifierSize, + IN CONST VOID *KeyIdentifier, + IN OUT UINT16 *KeyAttributesCount, + IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Delete attributes to a key specified by a key identifier. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in] KeyIdentifierSize Pointer to the size in bytes of the KeyIdentifier variable. + @param[in] KeyIdentifier Pointer to the key identifier associated with this key. + @param[in, out] KeyAttributesCount Pointer to the number of EFI_KMS_KEY_ATTRIBUTE + structures to associate with the Key. + On input, the count value is one or more. + On normal returns, this number will be updated with + the number of key attributes successfully processed. + @param[in, out] KeyAttributes Pointer to an array of EFI_KMS_KEY_ATTRIBUTE + structures providing the attribute information to + associate with the key. + On input, the values for the fields in the structure + are completely filled in. + On return the KeyAttributeStatus field will reflect the + result of the operation for each key attribute request. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully deleted all requested key attributes. + @retval EFI_OUT_OF_RESOURCES Could not allocate required resources. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + attribute request(s) to see which ones may have been + processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key attribute + request(s) (i.e. key attribute status for each) to see which ones + may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyAttributesCount is NULL, or + KeyAttributes is NULL, or KeyIdentifierSize + is NULL, or KeyIdentifer is NULL. + @retval EFI_NOT_FOUND The KeyIdentifier could not be found or the attribute + could not be found. On return the KeyAttributesCount + contains the number of attributes processed. Individual + structures will reflect the status of the processing for that + structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_DELETE_KEY_ATTRIBUTES) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN UINT8 *KeyIdentifierSize, + IN CONST VOID *KeyIdentifier, + IN OUT UINT16 *KeyAttributesCount, + IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/** + Retrieve one or more key that has matched all of the specified key attributes. + + @param[in] This Pointer to the EFI_KMS_PROTOCOL instance. + @param[in] Client Pointer to a valid EFI_KMS_CLIENT_INFO structure. + @param[in, out] KeyAttributesCount Pointer to a count of the number of key attribute structures + that must be matched for each returned key descriptor. + On input the count value is one or more. + On normal returns, this number will be updated with + the number of key attributes successfully processed. + @param[in, out] KeyAttributes Pointer to an array of EFI_KMS_KEY_ATTRIBUTE + structure to search for. + On input, the values for the fields in the structure are + completely filled in. + On return the KeyAttributeStatus field will reflect the + result of the operation for each key attribute request. + @param[in, out] KeyDescriptorCount Pointer to a count of the number of key descriptors matched + by this operation. + On entry, this number will be zero. + On return, this number will be updated to the number + of key descriptors successfully found. + @param[in, out] KeyDescriptors Pointer to an array of EFI_KMS_KEY_DESCRIPTOR + structures which describe the keys from the KMS + having the KeyAttribute(s) specified. + On input, this pointer will be NULL. + On output, the array will contain an + EFI_KMS_KEY_DESCRIPTOR structure for each key + meeting the search criteria. Memory for the array + and all KeyValue fields will be allocated with the + EfiBootServicesData type and must be freed by the + caller when it is no longer needed. Also, the KeyStatus + field of each descriptor will reflect the result of the + request relative to that key descriptor. + @param[in, out] ClientDataSize Pointer to the size, in bytes, of an arbitrary block of + data specified by the ClientData parameter. This + parameter may be NULL, in which case the ClientData + parameter will be ignored and no data will be + transferred to or from the KMS. If the parameter is + not NULL, then ClientData must be a valid pointer. + If the value pointed to is 0, no data will be transferred + to the KMS, but data may be returned by the KMS. + For all non-zero values *ClientData will be transferred + to the KMS, which may also return data to the caller. + In all cases, the value upon return to the caller will + be the size of the data block returned to the caller, + which will be zero if no data is returned from the KMS. + @param[in, out] ClientData Pointer to a pointer to an arbitrary block of data of + *ClientDataSize that is to be passed directly to the + KMS if it supports the use of client data. This + parameter may be NULL if and only if the + ClientDataSize parameter is also NULL. Upon return to + the caller, *ClientData points to a block of data of + *ClientDataSize that was returned from the KMS. + If the returned value for *ClientDataSize is zero, + then the returned value for *ClientData must be NULL + and should be ignored by the caller. The KMS protocol + consumer is responsible for freeing all valid buffers + used for client data regardless of whether they are + allocated by the caller for input to the function or by + the implementation for output back to the caller. + + @retval EFI_SUCCESS Successfully retrieved all requested keys. + @retval EFI_OUT_OF_RESOURCES Could not allocate required resources. + @retval EFI_TIMEOUT Timed out waiting for device or key server. Check individual key + attribute request(s) to see which ones may have been + processed. + @retval EFI_BUFFER_TOO_SMALL If multiple keys are associated with the attribute(s), and the + KeyValue buffer does not contain enough structures + (KeyDescriptorCount) to contain all the key data, then + the available structures will be filled and + KeyDescriptorCount will be updated to indicate the + number of keys which could not be processed. + @retval EFI_ACCESS_DENIED Access was denied by the device or the key server; OR a + ClientId is required by the server and either none or an + invalid id was provided. + @retval EFI_DEVICE_ERROR Device or key server error. Check individual key attribute + request(s) (i.e. key attribute status for each) to see which ones + may have been processed. + @retval EFI_INVALID_PARAMETER This is NULL, ClientId is required but it is NULL, + KeyDescriptorCount is NULL, or + KeyDescriptors is NULL or KeyAttributes is + NULL, or KeyAttributesCount is NULL. + @retval EFI_NOT_FOUND One or more EFI_KMS_KEY_ATTRIBUTE structures could + not be processed properly. KeyAttributeCount contains + the number of structures which were successfully processed. + Individual structures will reflect the status of the processing for + that structure. + @retval EFI_UNSUPPORTED The implementation/KMS does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_KMS_GET_KEY_BY_ATTRIBUTES) ( + IN EFI_KMS_PROTOCOL *This, + IN EFI_KMS_CLIENT_INFO *Client, + IN OUT UINTN *KeyAttributeCount, + IN OUT EFI_KMS_KEY_ATTRIBUTE *KeyAttributes, + IN OUT UINTN *KeyDescriptorCount, + IN OUT EFI_KMS_KEY_DESCRIPTOR *KeyDescriptors, + IN OUT UINTN *ClientDataSize OPTIONAL, + IN OUT VOID **ClientData OPTIONAL + ); + +/// +/// The Key Management Service (KMS) protocol provides services to generate, store, retrieve, +/// and manage cryptographic keys. +/// +struct _EFI_KMS_PROTOCOL { + /// + /// Get the current status of the key management service. If the implementation has not yet + /// connected to the KMS, then a call to this function will initiate a connection. This is the + /// only function that is valid for use prior to the service being marked available. + /// + EFI_KMS_GET_SERVICE_STATUS GetServiceStatus; + /// + /// Register a specific client with the KMS. + /// + EFI_KMS_REGISTER_CLIENT RegisterClient; + /// + /// Request the generation of a new key and retrieve it. + /// + EFI_KMS_CREATE_KEY CreateKey; + /// + /// Retrieve an existing key. + /// + EFI_KMS_GET_KEY GetKey; + /// + /// Add a local key to KMS database. If there is an existing key with this key identifier in the + /// KMS database, it will be replaced with the new key. + /// + EFI_KMS_ADD_KEY AddKey; + /// + /// Delete an existing key from the KMS database. + /// + EFI_KMS_DELETE_KEY DeleteKey; + /// + /// Get attributes for an existing key in the KMS database. + /// + EFI_KMS_GET_KEY_ATTRIBUTES GetKeyAttributes; + /// + /// Add attributes to an existing key in the KMS database. + /// + EFI_KMS_ADD_KEY_ATTRIBUTES AddKeyAttributes; + /// + /// Delete attributes for an existing key in the KMS database. + /// + EFI_KMS_DELETE_KEY_ATTRIBUTES DeleteKeyAttributes; + /// + /// Get existing key(s) with the specified attributes. + /// + EFI_KMS_GET_KEY_BY_ATTRIBUTES GetKeyByAttributes; + /// + /// The version of this EFI_KMS_PROTOCOL structure. This must be set to 0x00020040 for + /// the initial version of this protocol. + /// + UINT32 ProtocolVersion; + /// + /// Optional GUID used to identify a specific KMS. This GUID may be supplied by the provider, + /// by the implementation, or may be null. If is null, then the ServiceName must not be null. + /// + EFI_GUID ServiceId; + /// + /// Optional pointer to a unicode string which may be used to identify the KMS or provide + /// other information about the supplier. + /// + CHAR16 *ServiceName; + /// + /// Optional 32-bit value which may be used to indicate the version of the KMS provided by + /// the supplier. + /// + UINT32 ServiceVersion; + /// + /// TRUE if and only if the service is active and available for use. To avoid unnecessary + /// delays in POST, this protocol may be installed without connecting to the service. In this + /// case, the first call to the GetServiceStatus () function will cause the implementation to + /// connect to the supported service and mark it as available. The capabilities of this service + /// as defined in the reminder of this protocol are not guaranteed to be valid until the service + /// has been marked available. + /// + BOOLEAN ServiceAvailable; + /// + /// TRUE if and only if the service supports client identifiers. Client identifiers may be used + /// for auditing, access control or any other purpose specific to the implementation. + /// + BOOLEAN ClientIdSupported; + /// + /// TRUE if and only if the service requires a client identifier in order to process key requests. + /// FALSE otherwise. + /// + BOOLEAN ClientIdRequired; + /// + /// The maximum size in bytes for the client identifier. + /// + UINT16 ClientIdMaxSize; + /// + /// The client name string type(s) supported by the KMS service. If client names are not + /// supported, this field will be set the EFI_KMS_DATA_TYPE_NONE. Otherwise, it will be set + /// to the inclusive 'OR' of all client name formats supported. Client names may be used for + /// auditing, access control or any other purpose specific to the implementation. + /// + UINT8 ClientNameStringTypes; + /// + /// TRUE if only if the KMS requires a client name to be supplied to the service. + /// FALSE otherwise. + /// + BOOLEAN ClientNameRequired; + /// + /// The maximum number of characters allowed for the client name. + /// + UINT16 ClientNameMaxCount; + /// + /// TRUE if and only if the service supports arbitrary client data requests. The use of client + /// data requires the caller to have specific knowledge of the individual KMS service and + /// should be used only if absolutely necessary. + /// FALSE otherwise. + /// + BOOLEAN ClientDataSupported; + /// + /// The maximum size in bytes for the client data. If the maximum data size is not specified + /// by the KMS or it is not known, then this field must be filled with all ones. + /// + UINTN ClientDataMaxSize; + /// + /// TRUE if variable length key identifiers are supported. + /// FALSE if a fixed length key identifier is supported. + /// + BOOLEAN KeyIdVariableLenSupported; + /// + /// If KeyIdVariableLenSupported is TRUE, this is the maximum supported key identifier length + /// in bytes. Otherwise this is the fixed length of key identifier supported. Key ids shorter + /// than the fixed length will be padded on the right with blanks. + /// + UINTN KeyIdMaxSize; + /// + /// The number of key format/size GUIDs returned in the KeyFormats field. + /// + UINTN KeyFormatsCount; + /// + /// A pointer to an array of EFI_GUID values which specify key formats/sizes supported by + /// this KMS. Each format/size pair will be specified by a separate EFI_GUID. At least one + /// key format/size must be supported. All formats/sizes with the same hashing algorithm + /// must be contiguous in the array, and for each hashing algorithm, the key sizes must be in + /// ascending order. See "Related Definitions" for GUIDs which identify supported key formats/sizes. + /// This list of GUIDs supported by the KMS is not required to be exhaustive, and the KMS + /// may provide support for additional key formats/sizes. Users may request key information + /// using an arbitrary GUID, but any GUID not recognized by the implementation or not + /// supported by the KMS will return an error code of EFI_UNSUPPORTED + /// + EFI_GUID *KeyFormats; + /// + /// TRUE if key attributes are supported. + /// FALSE if key attributes are not supported. + /// + BOOLEAN KeyAttributesSupported; + /// + /// The key attribute identifier string type(s) supported by the KMS service. If key attributes + /// are not supported, this field will be set to EFI_KMS_DATA_TYPE_NONE. Otherwise, it will + /// be set to the inclusive 'OR' of all key attribute identifier string types supported. + /// EFI_KMS_DATA_TYPE_BINARY is not valid for this field. + /// + UINT8 KeyAttributeIdStringTypes; + UINT16 KeyAttributeIdMaxCount; + /// + /// The number of predefined KeyAttributes structures returned in the KeyAttributes + /// parameter. If the KMS does not support predefined key attributes, or if it does not + /// provide a method to obtain predefined key attributes data, then this field must be zero. + /// + UINTN KeyAttributesCount; + /// + /// A pointer to an array of KeyAttributes structures which contains the predefined + /// attributes supported by this KMS. Each structure must contain a valid key attribute + /// identifier and should provide any other information as appropriate for the attribute, + /// including a default value if one exists. This variable must be set to NULL if the + /// KeyAttributesCount variable is zero. It must point to a valid buffer if the + /// KeyAttributesCount variable is non-zero. + /// This list of predefined attributes is not required to be exhaustive, and the KMS may + /// provide additional predefined attributes not enumerated in this list. The implementation + /// does not distinguish between predefined and used defined attributes, and therefore, + /// predefined attributes not enumerated will still be processed to the KMS. + /// + EFI_KMS_KEY_ATTRIBUTE *KeyAttributes; +}; + +extern EFI_GUID gEfiKmsFormatGeneric128Guid; +extern EFI_GUID gEfiKmsFormatGeneric160Guid; +extern EFI_GUID gEfiKmsFormatGeneric256Guid; +extern EFI_GUID gEfiKmsFormatGeneric512Guid; +extern EFI_GUID gEfiKmsFormatGeneric1024Guid; +extern EFI_GUID gEfiKmsFormatGeneric2048Guid; +extern EFI_GUID gEfiKmsFormatGeneric3072Guid; +extern EFI_GUID gEfiKmsFormatMd2128Guid; +extern EFI_GUID gEfiKmsFormatMdc2128Guid; +extern EFI_GUID gEfiKmsFormatMd4128Guid; +extern EFI_GUID gEfiKmsFormatMdc4128Guid; +extern EFI_GUID gEfiKmsFormatMd5128Guid; +extern EFI_GUID gEfiKmsFormatMd5sha128Guid; +extern EFI_GUID gEfiKmsFormatSha1160Guid; +extern EFI_GUID gEfiKmsFormatSha256256Guid; +extern EFI_GUID gEfiKmsFormatSha512512Guid; +extern EFI_GUID gEfiKmsFormatAesxts128Guid; +extern EFI_GUID gEfiKmsFormatAesxts256Guid; +extern EFI_GUID gEfiKmsFormatAescbc128Guid; +extern EFI_GUID gEfiKmsFormatAescbc256Guid; +extern EFI_GUID gEfiKmsFormatRsasha11024Guid; +extern EFI_GUID gEfiKmsFormatRsasha12048Guid; +extern EFI_GUID gEfiKmsFormatRsasha2562048Guid; +extern EFI_GUID gEfiKmsFormatRsasha2563072Guid; +extern EFI_GUID gEfiKmsProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacyRegion2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacyRegion2.h new file mode 100644 index 0000000..ba376ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacyRegion2.h @@ -0,0 +1,239 @@ +/** @file + The Legacy Region Protocol controls the read, write and boot-lock attributes for + the region 0xC0000 to 0xFFFFF. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef __LEGACY_REGION2_H__ +#define __LEGACY_REGION2_H__ + + +#define EFI_LEGACY_REGION2_PROTOCOL_GUID \ +{ \ + 0x70101eaf, 0x85, 0x440c, {0xb3, 0x56, 0x8e, 0xe3, 0x6f, 0xef, 0x24, 0xf0 } \ +} + +typedef struct _EFI_LEGACY_REGION2_PROTOCOL EFI_LEGACY_REGION2_PROTOCOL; + +/** + Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region. + + If the On parameter evaluates to TRUE, this function enables memory reads in the address range + Start to (Start + Length - 1). + If the On parameter evaluates to FALSE, this function disables memory reads in the address range + Start to (Start + Length - 1). + + @param This[in] Indicates the EFI_LEGACY_REGION2_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose attributes + should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address + was not aligned to a region's starting address or if the length + was greater than the number of bytes in the first region. + @param On[in] Decode / Non-Decode flag. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION2_DECODE)( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity, + IN BOOLEAN *On + ); + + +/** + Modify the hardware to disallow memory writes in a region. + + This function changes the attributes of a memory range to not allow writes. + + @param This[in] Indicates the EFI_LEGACY_REGION2_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION2_LOCK)( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ); + + +/** + Modify the hardware to disallow memory attribute changes in a region. + + This function makes the attributes of a region read only. Once a region is boot-locked with this + function, the read and write attributes of that region cannot be changed until a power cycle has + reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect. + + @param This[in] Indicates the EFI_LEGACY_REGION2_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in + a way that will not affect memory regions outside the legacy memory + region. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION2_BOOT_LOCK)( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ); + + +/** + Modify the hardware to allow memory writes in a region. + + This function changes the attributes of a memory range to allow writes. + + @param This[in] Indicates the EFI_LEGACY_REGION2_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION2_UNLOCK)( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ); + + +typedef enum { + LegacyRegionDecoded, ///< This region is currently set to allow reads. + LegacyRegionNotDecoded, ///< This region is currently set to not allow reads. + LegacyRegionWriteEnabled, ///< This region is currently set to allow writes. + LegacyRegionWriteDisabled, ///< This region is currently set to write protected. + LegacyRegionBootLocked, ///< This region's attributes are locked, cannot be modified until + ///< after a power cycle. + LegacyRegionNotLocked ///< This region's attributes are not locked. +} EFI_LEGACY_REGION_ATTRIBUTE; + + +typedef struct { + /// + /// The beginning of the physical address of this + /// region. + /// + UINT32 Start; + /// + /// The number of bytes in this region. + /// + UINT32 Length; + /// + /// Attribute of the Legacy Region Descriptor that + /// describes the capabilities for that memory region. + /// + EFI_LEGACY_REGION_ATTRIBUTE Attribute; + /// + /// Describes the byte length programmability + /// associated with the Start address and the specified + /// Attribute setting. + UINT32 Granularity; +} EFI_LEGACY_REGION_DESCRIPTOR; + + +/** + Get region information for the attributes of the Legacy Region. + + This function is used to discover the granularity of the attributes for the memory in the legacy + region. Each attribute may have a different granularity and the granularity may not be the same + for all memory ranges in the legacy region. + + @param This[in] Indicates the EFI_LEGACY_REGION2_PROTOCOL instance. + @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor + buffer. + @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy + region information is deposited. This buffer will contain a list of + DescriptorCount number of region descriptors. This function will + provide the memory for the buffer. + + @retval EFI_SUCCESS The information structure was returned. + @retval EFI_UNSUPPORTED This function is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION_GET_INFO)( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + OUT UINT32 *DescriptorCount, + OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor + ); + + +/// +/// The EFI_LEGACY_REGION2_PROTOCOL is used to abstract the hardware control of the memory +/// attributes of the Option ROM shadowing region, 0xC0000 to 0xFFFFF. +/// There are three memory attributes that can be modified through this protocol: read, write and +/// boot-lock. These protocols may be set in any combination. +/// +struct _EFI_LEGACY_REGION2_PROTOCOL { + EFI_LEGACY_REGION2_DECODE Decode; + EFI_LEGACY_REGION2_LOCK Lock; + EFI_LEGACY_REGION2_BOOT_LOCK BootLock; + EFI_LEGACY_REGION2_UNLOCK UnLock; + EFI_LEGACY_REGION_GET_INFO GetInfo; +}; + +extern EFI_GUID gEfiLegacyRegion2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiController.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiController.h new file mode 100644 index 0000000..2d36eae --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiController.h @@ -0,0 +1,265 @@ +/** @file + This file defines the Legacy SPI Controller Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __LEGACY_SPI_CONTROLLER_PROTOCOL_H__ +#define __LEGACY_SPI_CONTROLLER_PROTOCOL_H__ + +/// +/// Note: The UEFI PI 1.6 specification uses the character 'l' in the GUID +/// definition. This definition assumes it was supposed to be '1'. +/// +/// Global ID for the Legacy SPI Controller Protocol +/// +#define EFI_LEGACY_SPI_CONTROLLER_GUID \ + { 0x39136fc7, 0x1a11, 0x49de, \ + { 0xbf, 0x35, 0x0e, 0x78, 0xdd, 0xb5, 0x24, 0xfc }} + +typedef +struct _EFI_LEGACY_SPI_CONTROLLER_PROTOCOL +EFI_LEGACY_SPI_CONTROLLER_PROTOCOL; + +/** + Set the erase block opcode. + + This routine must be called at or below TPL_NOTIFY. + The menu table contains SPI transaction opcodes which are accessible after + the legacy SPI flash controller's configuration is locked. The board layer + specifies the erase block size for the SPI NOR flash part. The SPI NOR flash + peripheral driver selects the erase block opcode which matches the erase + block size and uses this API to load the opcode into the opcode menu table. + + @param[in] This Pointer to an EFI_LEGACY_SPI_CONTROLLER_PROTOCOL + structure. + @param[in] EraseBlockOpcode Erase block opcode to be placed into the opcode + menu table. + + @retval EFI_SUCCESS The opcode menu table was updated + @retval EFI_ACCESS_ERROR The SPI controller is locked + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_ERASE_BLOCK_OPCODE) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This, + IN UINT8 EraseBlockOpcode + ); + +/** + Set the write status prefix opcode. + + This routine must be called at or below TPL_NOTIFY. + The prefix table contains SPI transaction write prefix opcodes which are + accessible after the legacy SPI flash controller's configuration is locked. + The board layer specifies the write status prefix opcode for the SPI NOR + flash part. The SPI NOR flash peripheral driver uses this API to load the + opcode into the prefix table. + + @param[in] This Pointer to an + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL structure. + @param[in] WriteStatusPrefix Prefix opcode for the write status command. + + @retval EFI_SUCCESS The prefix table was updated + @retval EFI_ACCESS_ERROR The SPI controller is locked + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_WRITE_STATUS_PREFIX) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This, + IN UINT8 WriteStatusPrefix + ); + +/** + Set the BIOS base address. + + This routine must be called at or below TPL_NOTIFY. + The BIOS base address works with the protect range registers to protect + portions of the SPI NOR flash from erase and write operat ions. The BIOS + calls this API prior to passing control to the OS loader. + + @param[in] This Pointer to an EFI_LEGACY_SPI_CONTROLLER_PROTOCOL + structure. + @param[in] BiosBaseAddress The BIOS base address. + + @retval EFI_SUCCESS The BIOS base address was properly set + @retval EFI_ACCESS_ERROR The SPI controller is locked + @retval EFI_INVALID_PARAMETER The BIOS base address is greater than + This->Maxi.mumOffset + @retval EFI_UNSUPPORTED The BIOS base address was already set + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_BIOS_BASE_ADDRESS) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This, + IN UINT32 BiosBaseAddress + ); + +/** + Clear the SPI protect range registers. + + This routine must be called at or below TPL_NOTIFY. + The BIOS uses this routine to set an initial condition on the SPI protect + range registers. + + @param[in] This Pointer to an EFI_LEGACY_SPI_CONTROLLER_PROTOCOL structure. + + @retval EFI_SUCCESS The registers were successfully cleared + @retval EFI_ACCESS_ERROR The SPI controller is locked + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_CLEAR_SPI_PROTECT) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This + ); + +/** + Determine if the SPI range is protected. + + This routine must be called at or below TPL_NOTIFY. + The BIOS uses this routine to verify a range in the SPI is protected. + + @param[in] This Pointer to an EFI_LEGACY_SPI_CONTROLLER_PROTOCOL + structure. + @param[in] BiosAddress Address within a 4 KiB block to start protecting. + @param[in] BytesToProtect The number of 4 KiB blocks to protect. + + @retval TRUE The range is protected + @retval FALSE The range is not protected + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_IS_RANGE_PROTECTED) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This, + IN UINT32 BiosAddress, + IN UINT32 BlocksToProtect + ); + +/** + Set the next protect range register. + + This routine must be called at or below TPL_NOTIFY. + The BIOS sets the protect range register to prevent write and erase + operations to a portion of the SPI NOR flash device. + + @param[in] This Pointer to an EFI_LEGACY_SPI_CONTROLLER_PROTOCOL + structure. + @param[in] BiosAddress Address within a 4 KiB block to start protecting. + @param[in] BlocksToProtect The number of 4 KiB blocks to protect. + + @retval EFI_SUCCESS The register was successfully updated + @retval EFI_ACCESS_ERROR The SPI controller is locked + @retval EFI_INVALID_PARAMETER BiosAddress < This->BiosBaseAddress, or + BlocksToProtect * 4 KiB + > This->MaximumRangeBytes, or + BiosAddress - This->BiosBaseAddress + + (BlocksToProtect * 4 KiB) + > This->MaximumRangeBytes + @retval EFI_OUT_OF_RESOURCES No protect range register available + @retval EFI_UNSUPPORTED Call This->SetBaseAddress because the BIOS base + address is not set + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_PROTECT_NEXT_RANGE) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This, + IN UINT32 BiosAddress, + IN UINT32 BlocksToProtect + ); + +/** + Lock the SPI controller configuration. + + This routine must be called at or below TPL_NOTIFY. + This routine locks the SPI controller's configuration so that the software + is no longer able to update: + * Prefix table + * Opcode menu + * Opcode type table + * BIOS base address + * Protect range registers + + @param[in] This Pointer to an EFI_LEGACY_SPI_CONTROLLER_PROTOCOL structure. + + @retval EFI_SUCCESS The SPI controller was successfully locked + @retval EFI_ALREADY_STARTED The SPI controller was already locked + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_LOCK_CONTROLLER) ( + IN CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *This + ); + +/// +/// Support the extra features of the legacy SPI flash controller. +/// +struct _EFI_LEGACY_SPI_CONTROLLER_PROTOCOL { + /// + /// Maximum offset from the BIOS base address that is able to be protected. + /// + UINT32 MaximumOffset; + + /// + /// Maximum number of bytes that can be protected by one range register. + /// + UINT32 MaximumRangeBytes; + + /// + /// The number of registers available for protecting the BIOS. + /// + UINT32 RangeRegisterCount; + + /// + /// Set the erase block opcode. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_ERASE_BLOCK_OPCODE EraseBlockOpcode; + + /// + /// Set the write status prefix opcode. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_WRITE_STATUS_PREFIX WriteStatusPrefix; + + /// + /// Set the BIOS base address. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_BIOS_BASE_ADDRESS BiosBaseAddress; + + /// + /// Clear the SPI protect range registers. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_CLEAR_SPI_PROTECT ClearSpiProtect; + + /// + /// Determine if the SPI range is protected. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_IS_RANGE_PROTECTED IsRangeProtected; + + /// + /// Set the next protect range register. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_PROTECT_NEXT_RANGE ProtectNextRange; + + /// + /// Lock the SPI controller configuration. + /// + EFI_LEGACY_SPI_CONTROLLER_PROTOCOL_LOCK_CONTROLLER LockController; +}; + +extern EFI_GUID gEfiLegacySpiControllerProtocolGuid; + +#endif // __LEGACY_SPI_CONTROLLER_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiFlash.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiFlash.h new file mode 100644 index 0000000..fa9f463 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiFlash.h @@ -0,0 +1,201 @@ +/** @file + This file defines the Legacy SPI Flash Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __LEGACY_SPI_FLASH_PROTOCOL_H__ +#define __LEGACY_SPI_FLASH_PROTOCOL_H__ + +#include + +/// +/// Global ID for the Legacy SPI Flash Protocol +/// +#define EFI_LEGACY_SPI_FLASH_PROTOCOL_GUID \ + { 0xf01bed57, 0x04bc, 0x4f3f, \ + { 0x96, 0x60, 0xd6, 0xf2, 0xea, 0x22, 0x82, 0x59 }} + +typedef struct _EFI_LEGACY_SPI_FLASH_PROTOCOL EFI_LEGACY_SPI_FLASH_PROTOCOL; + +/** + Set the BIOS base address. + + This routine must be called at or below TPL_NOTIFY. + The BIOS base address works with the protect range registers to protect + portions of the SPI NOR flash from erase and write operat ions. + The BIOS calls this API prior to passing control to the OS loader. + + @param[in] This Pointer to an EFI_LEGACY_SPI_FLASH_PROTOCOL data + structure. + @param[in] BiosBaseAddress The BIOS base address. + + @retval EFI_SUCCESS The BIOS base address was properly set + @retval EFI_ACCESS_ERROR The SPI controller is locked + @retval EFI_INVALID_PARAMETER BiosBaseAddress > This->MaximumOffset + @retval EFI_UNSUPPORTED The BIOS base address was already set or not a + legacy SPI host controller + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_FLASH_PROTOCOL_BIOS_BASE_ADDRESS) ( + IN CONST EFI_LEGACY_SPI_FLASH_PROTOCOL *This, + IN UINT32 BiosBaseAddress + ); + +/** + Clear the SPI protect range registers. + + This routine must be called at or below TPL_NOTIFY. + The BIOS uses this routine to set an initial condition on the SPI protect + range registers. + + @param[in] This Pointer to an EFI_LEGACY_SPI_FLASH_PROTOCOL data structure. + + @retval EFI_SUCCESS The registers were successfully cleared + @retval EFI_ACCESS_ERROR The SPI controller is locked + @retval EFI_UNSUPPORTED Not a legacy SPI host controller + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_FLASH_PROTOCOL_CLEAR_SPI_PROTECT) ( + IN CONST EFI_LEGACY_SPI_FLASH_PROTOCOL *This + ); + +/** + Determine if the SPI range is protected. + + This routine must be called at or below TPL_NOTIFY. + The BIOS uses this routine to verify a range in the SPI is protected. + + @param[in] This Pointer to an EFI_LEGACY_SPI_FLASH_PROTOCOL data + structure. + @param[in] BiosAddress Address within a 4 KiB block to start protecting. + @param[in] BlocksToProtect The number of 4 KiB blocks to protect. + + @retval TRUE The range is protected + @retval FALSE The range is not protected + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_LEGACY_SPI_FLASH_PROTOCOL_IS_RANGE_PROTECTED) ( + IN CONST EFI_LEGACY_SPI_FLASH_PROTOCOL *This, + IN UINT32 BiosAddress, + IN UINT32 BlocksToProtect + ); + +/** + Set the next protect range register. + + This routine must be called at or below TPL_NOTIFY. + The BIOS sets the protect range register to prevent write and erase + operations to a portion of the SPI NOR flash device. + + @param[in] This Pointer to an EFI_LEGACY_SPI_FLASH_PROTOCOL data + structure. + @param[in] BiosAddress Address within a 4 KiB block to start protecting. + @param[in] BlocksToProtect The number of 4 KiB blocks to protect. + + @retval EFI_SUCCESS The register was successfully updated + @retval EFI_ACCESS_ERROR The SPI controller is locked + @retval EFI_INVALID_PARAMETER BiosAddress < This->BiosBaseAddress, or + @retval EFI_INVALID_PARAMETER BlocksToProtect * 4 KiB + > This->MaximumRangeBytes, or + BiosAddress - This->BiosBaseAddress + + (BlocksToProtect * 4 KiB) + > This->MaximumRangeBytes + @retval EFI_OUT_OF_RESOURCES No protect range register available + @retval EFI_UNSUPPORTED Call This->SetBaseAddress because the BIOS + base address is not set Not a legacy SPI host + controller + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_FLASH_PROTOCOL_PROTECT_NEXT_RANGE) ( + IN CONST EFI_LEGACY_SPI_FLASH_PROTOCOL *This, + IN UINT32 BiosAddress, + IN UINT32 BlocksToProtect + ); + +/** + Lock the SPI controller configuration. + + This routine must be called at or below TPL_NOTIFY. + This routine locks the SPI controller's configuration so that the software is + no longer able to update: + * Prefix table + * Opcode menu + * Opcode type table + * BIOS base address + * Protect range registers + + @param[in] This Pointer to an EFI_LEGACY_SPI_FLASH_PROTOCOL data structure. + + @retval EFI_SUCCESS The SPI controller was successfully locked + @retval EFI_ALREADY_STARTED The SPI controller was already locked + @retval EFI_UNSUPPORTED Not a legacy SPI host controller +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_SPI_FLASH_PROTOCOL_LOCK_CONTROLLER) ( + IN CONST EFI_LEGACY_SPI_FLASH_PROTOCOL *This + ); + +/// +/// The EFI_LEGACY_SPI_FLASH_PROTOCOL extends the EFI_SPI_NOR_FLASH_PROTOCOL +/// with APls to support the legacy SPI flash controller. +/// +struct _EFI_LEGACY_SPI_FLASH_PROTOCOL { + /// + /// This protocol manipulates the SPI NOR flash parts using a common set of + /// commands. + /// + EFI_SPI_NOR_FLASH_PROTOCOL FlashProtocol; + + // + // Legacy flash (SPI host) controller support + // + + /// + /// Set the BIOS base address. + /// + EFI_LEGACY_SPI_FLASH_PROTOCOL_BIOS_BASE_ADDRESS BiosBaseAddress; + + /// + /// Clear the SPI protect range registers. + /// + EFI_LEGACY_SPI_FLASH_PROTOCOL_CLEAR_SPI_PROTECT ClearSpiProtect; + + /// + /// Determine if the SPI range is protected. + /// + EFI_LEGACY_SPI_FLASH_PROTOCOL_IS_RANGE_PROTECTED IsRangeProtected; + + /// + /// Set the next protect range register. + /// + EFI_LEGACY_SPI_FLASH_PROTOCOL_PROTECT_NEXT_RANGE ProtectNextRange; + + /// + /// Lock the SPI controller configuration. + /// + EFI_LEGACY_SPI_FLASH_PROTOCOL_LOCK_CONTROLLER LockController; +}; + +extern EFI_GUID gEfiLegacySpiFlashProtocolGuid; + +#endif // __LEGACY_SPI_FLASH_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmController.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmController.h new file mode 100644 index 0000000..5e1d763 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmController.h @@ -0,0 +1,36 @@ +/** @file + This file defines the Legacy SPI SMM Controler Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __LEGACY_SPI_SMM_CONTROLLER_PROTOCOL_H__ +#define __LEGACY_SPI_SMM_CONTROLLER_PROTOCOL_H__ + +#include + +/// +/// Global ID for the Legacy SPI SMM Controller Protocol +/// +#define EFI_LEGACY_SPI_SMM_CONTROLLER_PROTOCOL_GUID \ + { 0x62331b78, 0xd8d0, 0x4c8c, \ + { 0x8c, 0xcb, 0xd2, 0x7d, 0xfe, 0x32, 0xdb, 0x9b }} + +typedef +struct _EFI_LEGACY_SPI_CONTROLLER_PROTOCOL +EFI_LEGACY_SPI_SMM_CONTROLLER_PROTOCOL; + +extern EFI_GUID gEfiLegacySpiSmmControllerProtocolGuid; + +#endif // __LEGACY_SPI_SMM_CONTROLLER_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmFlash.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmFlash.h new file mode 100644 index 0000000..a604a22 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LegacySpiSmmFlash.h @@ -0,0 +1,36 @@ +/** @file + This file defines the Legacy SPI SMM Flash Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __LEGACY_SPI_SMM_FLASH_PROTOCOL_H__ +#define __LEGACY_SPI_SMM_FLASH_PROTOCOL_H__ + +#include + +/// +/// Global ID for the Legacy SPI SMM Flash Protocol +/// +#define EFI_LEGACY_SPI_SMM_FLASH_PROTOCOL_GUID \ + { 0x5e3848d4, 0x0db5, 0x4fc0, \ + { 0x97, 0x29, 0x3f, 0x35, 0x3d, 0x4f, 0x87, 0x9f }} + +typedef +struct _EFI_LEGACY_SPI_FLASH_PROTOCOL +EFI_LEGACY_SPI_SMM_FLASH_PROTOCOL; + +extern EFI_GUID gEfiLegacySpiSmmFlashProtocolGuid; + +#endif // __SPI_SMM_FLASH_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile.h new file mode 100644 index 0000000..2f12697 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile.h @@ -0,0 +1,88 @@ +/** @file + Load File protocol as defined in the UEFI 2.0 specification. + + The load file protocol exists to supports the addition of new boot devices, + and to support booting from devices that do not map well to file system. + Network boot is done via a LoadFile protocol. + + UEFI 2.0 can boot from any device that produces a LoadFile protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_LOAD_FILE_PROTOCOL_H__ +#define __EFI_LOAD_FILE_PROTOCOL_H__ + +#define EFI_LOAD_FILE_PROTOCOL_GUID \ + { \ + 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } + +/// +/// Protocol Guid defined by EFI1.1. +/// +#define LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL_GUID + +typedef struct _EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL; + +/// +/// Backward-compatible with EFI1.1 +/// +typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_INTERFACE; + +/** + Causes the driver to load a specified file. + + @param This Protocol instance pointer. + @param FilePath The device specific path of the file to load. + @param BootPolicy If TRUE, indicates that the request originates from the + boot manager is attempting to load FilePath as a boot + selection. If FALSE, then FilePath must match as exact file + to be loaded. + @param BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_NO_MEDIA No medium was present to load the file. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NO_RESPONSE The remote system did not respond. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_ABORTED The file load process was manually cancelled. + @retval EFI_WARN_FILE_SYSTEM The resulting Buffer contains UEFI-compliant file system. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOAD_FILE)( + IN EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ); + +/// +/// The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from arbitrary devices. +/// +struct _EFI_LOAD_FILE_PROTOCOL { + EFI_LOAD_FILE LoadFile; +}; + +extern EFI_GUID gEfiLoadFileProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile2.h new file mode 100644 index 0000000..d666e90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadFile2.h @@ -0,0 +1,85 @@ +/** @file + Load File protocol as defined in the UEFI 2.0 specification. + + Load file protocol exists to supports the addition of new boot devices, + and to support booting from devices that do not map well to file system. + Network boot is done via a LoadFile protocol. + + UEFI 2.0 can boot from any device that produces a LoadFile protocol. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_LOAD_FILE2_PROTOCOL_H__ +#define __EFI_LOAD_FILE2_PROTOCOL_H__ + +#define EFI_LOAD_FILE2_PROTOCOL_GUID \ + { \ + 0x4006c0c1, 0xfcb3, 0x403e, {0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d } \ + } + +/// +/// Protocol Guid defined by UEFI2.1. +/// +#define LOAD_FILE2_PROTOCOL EFI_LOAD_FILE2_PROTOCOL_GUID + +typedef struct _EFI_LOAD_FILE2_PROTOCOL EFI_LOAD_FILE2_PROTOCOL; + + +/** + Causes the driver to load a specified file. + + @param This Protocol instance pointer. + @param FilePath The device specific path of the file to load. + @param BootPolicy Should always be FALSE. + @param BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then no the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED BootPolicy is TRUE. + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_NO_MEDIA No medium was present to load the file. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NO_RESPONSE The remote system did not respond. + @retval EFI_NOT_FOUND The file was not found + @retval EFI_ABORTED The file load process was manually canceled. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current + directory entry. BufferSize has been updated with + the size needed to complete the request. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOAD_FILE2)( + IN EFI_LOAD_FILE2_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ); + +/// +/// The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from arbitrary devices. +/// +struct _EFI_LOAD_FILE2_PROTOCOL { + EFI_LOAD_FILE2 LoadFile; +}; + +extern EFI_GUID gEfiLoadFile2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadedImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadedImage.h new file mode 100644 index 0000000..1d9d143 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/LoadedImage.h @@ -0,0 +1,88 @@ +/** @file + UEFI 2.0 Loaded image protocol definition. + + Every EFI driver and application is passed an image handle when it is loaded. + This image handle will contain a Loaded Image Protocol. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __LOADED_IMAGE_PROTOCOL_H__ +#define __LOADED_IMAGE_PROTOCOL_H__ + +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ + { \ + 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } + +#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf } \ + } + +/// +/// Protocol GUID defined in EFI1.1. +/// +#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID + +/// +/// EFI_SYSTEM_TABLE & EFI_IMAGE_UNLOAD are defined in EfiApi.h +/// +#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000 + +/// +/// Revision defined in EFI1.1. +/// +#define EFI_LOADED_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION + +/// +/// Can be used on any image handle to obtain information about the loaded image. +/// +typedef struct { + UINT32 Revision; ///< Defines the revision of the EFI_LOADED_IMAGE_PROTOCOL structure. + ///< All future revisions will be backward compatible to the current revision. + EFI_HANDLE ParentHandle; ///< Parent image's image handle. NULL if the image is loaded directly from + ///< the firmware's boot manager. + EFI_SYSTEM_TABLE *SystemTable; ///< the image's EFI system table pointer. + + // + // Source location of image + // + EFI_HANDLE DeviceHandle; ///< The device handle that the EFI Image was loaded from. + EFI_DEVICE_PATH_PROTOCOL *FilePath; ///< A pointer to the file path portion specific to DeviceHandle + ///< that the EFI Image was loaded from. + VOID *Reserved; ///< Reserved. DO NOT USE. + + // + // Images load options + // + UINT32 LoadOptionsSize;///< The size in bytes of LoadOptions. + VOID *LoadOptions; ///< A pointer to the image's binary load options. + + // + // Location of where image was loaded + // + VOID *ImageBase; ///< The base address at which the image was loaded. + UINT64 ImageSize; ///< The size in bytes of the loaded image. + EFI_MEMORY_TYPE ImageCodeType; ///< The memory type that the code sections were loaded as. + EFI_MEMORY_TYPE ImageDataType; ///< The memory type that the data sections were loaded as. + EFI_IMAGE_UNLOAD Unload; +} EFI_LOADED_IMAGE_PROTOCOL; + +// +// For backward-compatible with EFI1.1. +// +typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE; + +extern EFI_GUID gEfiLoadedImageProtocolGuid; +extern EFI_GUID gEfiLoadedImageDevicePathProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ManagedNetwork.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ManagedNetwork.h new file mode 100644 index 0000000..535b742 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ManagedNetwork.h @@ -0,0 +1,372 @@ +/** @file + EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0. + EFI_MANAGED_NETWORK_PROTOCOL as defined in UEFI 2.0. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.0 + +**/ + +#ifndef __EFI_MANAGED_NETWORK_PROTOCOL_H__ +#define __EFI_MANAGED_NETWORK_PROTOCOL_H__ + +#include + +#define EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xf36ff770, 0xa7e1, 0x42cf, {0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c } \ + } + +#define EFI_MANAGED_NETWORK_PROTOCOL_GUID \ + { \ + 0x7ab33a91, 0xace5, 0x4326, { 0xb5, 0x72, 0xe7, 0xee, 0x33, 0xd3, 0x9f, 0x16 } \ + } + +typedef struct _EFI_MANAGED_NETWORK_PROTOCOL EFI_MANAGED_NETWORK_PROTOCOL; + +typedef struct { + /// + /// Timeout value for a UEFI one-shot timer event. A packet that has not been removed + /// from the MNP receive queue will be dropped if its receive timeout expires. + /// + UINT32 ReceivedQueueTimeoutValue; + /// + /// Timeout value for a UEFI one-shot timer event. A packet that has not been removed + /// from the MNP transmit queue will be dropped if its receive timeout expires. + /// + UINT32 TransmitQueueTimeoutValue; + /// + /// Ethernet type II 16-bit protocol type in host byte order. Valid + /// values are zero and 1,500 to 65,535. + /// + UINT16 ProtocolTypeFilter; + /// + /// Set to TRUE to receive packets that are sent to the network + /// device MAC address. The startup default value is FALSE. + /// + BOOLEAN EnableUnicastReceive; + /// + /// Set to TRUE to receive packets that are sent to any of the + /// active multicast groups. The startup default value is FALSE. + /// + BOOLEAN EnableMulticastReceive; + /// + /// Set to TRUE to receive packets that are sent to the network + /// device broadcast address. The startup default value is FALSE. + /// + BOOLEAN EnableBroadcastReceive; + /// + /// Set to TRUE to receive packets that are sent to any MAC address. + /// The startup default value is FALSE. + /// + BOOLEAN EnablePromiscuousReceive; + /// + /// Set to TRUE to drop queued packets when the configuration + /// is changed. The startup default value is FALSE. + /// + BOOLEAN FlushQueuesOnReset; + /// + /// Set to TRUE to timestamp all packets when they are received + /// by the MNP. Note that timestamps may be unsupported in some + /// MNP implementations. The startup default value is FALSE. + /// + BOOLEAN EnableReceiveTimestamps; + /// + /// Set to TRUE to disable background polling in this MNP + /// instance. Note that background polling may not be supported in + /// all MNP implementations. The startup default value is FALSE, + /// unless background polling is not supported. + /// + BOOLEAN DisableBackgroundPolling; +} EFI_MANAGED_NETWORK_CONFIG_DATA; + +typedef struct { + EFI_TIME Timestamp; + EFI_EVENT RecycleEvent; + UINT32 PacketLength; + UINT32 HeaderLength; + UINT32 AddressLength; + UINT32 DataLength; + BOOLEAN BroadcastFlag; + BOOLEAN MulticastFlag; + BOOLEAN PromiscuousFlag; + UINT16 ProtocolType; + VOID *DestinationAddress; + VOID *SourceAddress; + VOID *MediaHeader; + VOID *PacketData; +} EFI_MANAGED_NETWORK_RECEIVE_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_MANAGED_NETWORK_FRAGMENT_DATA; + +typedef struct { + EFI_MAC_ADDRESS *DestinationAddress; //OPTIONAL + EFI_MAC_ADDRESS *SourceAddress; //OPTIONAL + UINT16 ProtocolType; //OPTIONAL + UINT32 DataLength; + UINT16 HeaderLength; //OPTIONAL + UINT16 FragmentCount; + EFI_MANAGED_NETWORK_FRAGMENT_DATA FragmentTable[1]; +} EFI_MANAGED_NETWORK_TRANSMIT_DATA; + + +typedef struct { + /// + /// This Event will be signaled after the Status field is updated + /// by the MNP. The type of Event must be + /// EFI_NOTIFY_SIGNAL. The Task Priority Level (TPL) of + /// Event must be lower than or equal to TPL_CALLBACK. + /// + EFI_EVENT Event; + /// + /// The status that is returned to the caller at the end of the operation + /// to indicate whether this operation completed successfully. + /// + EFI_STATUS Status; + union { + /// + /// When this token is used for receiving, RxData is a pointer to the EFI_MANAGED_NETWORK_RECEIVE_DATA. + /// + EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData; + /// + /// When this token is used for transmitting, TxData is a pointer to the EFI_MANAGED_NETWORK_TRANSMIT_DATA. + /// + EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData; + } Packet; +} EFI_MANAGED_NETWORK_COMPLETION_TOKEN; + +/** + Returns the operational parameters for the current MNP child driver. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param MnpConfigData The pointer to storage for MNP operational parameters. + @param SnpModeData The pointer to storage for SNP operational parameters. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this MNP implementation. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. The default + values are returned in MnpConfigData if it is not NULL. + @retval Other The mode data could not be read. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_GET_MODE_DATA)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +/** + Sets or clears the operational parameters for the MNP child driver. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param MnpConfigData The pointer to configuration data that will be assigned to the MNP + child driver instance. If NULL, the MNP child driver instance is + reset to startup defaults and all pending transmit and receive + requests are flushed. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Required system resources (usually memory) could not be + allocated. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this [MNP] + implementation. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval Other The MNP child driver instance has been reset to startup defaults. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_CONFIGURE)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL + ); + +/** + Translates an IP multicast address to a hardware (MAC) multicast address. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Ipv6Flag Set to TRUE to if IpAddress is an IPv6 multicast address. + Set to FALSE if IpAddress is an IPv4 multicast address. + @param IpAddress The pointer to the multicast IP address (in network byte order) to convert. + @param MacAddress The pointer to the resulting multicast MAC address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One of the following conditions is TRUE: + - This is NULL. + - IpAddress is NULL. + - *IpAddress is not a valid multicast IP address. + - MacAddress is NULL. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this MNP implementation. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval Other The address could not be converted. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_MCAST_IP_TO_MAC)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN BOOLEAN Ipv6Flag, + IN EFI_IP_ADDRESS *IpAddress, + OUT EFI_MAC_ADDRESS *MacAddress + ); + +/** + Enables and disables receive filters for multicast address. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param JoinFlag Set to TRUE to join this multicast group. + Set to FALSE to leave this multicast group. + @param MacAddress The pointer to the multicast MAC group (address) to join or leave. + + @retval EFI_SUCCESS The requested operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - JoinFlag is TRUE and MacAddress is NULL. + - *MacAddress is not a valid multicast MAC address. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_ALREADY_STARTED The supplied multicast group is already joined. + @retval EFI_NOT_FOUND The supplied multicast group is not joined. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this MNP implementation. + @retval Other The requested operation could not be completed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_GROUPS)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_MAC_ADDRESS *MacAddress OPTIONAL + ); + +/** + Places asynchronous outgoing data packets into the transmit queue. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Token The pointer to a token associated with the transmit data descriptor. + + @retval EFI_SUCCESS The transmit completion token was cached. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED The transmit completion token is already in the transmit queue. + @retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a lack of system resources + (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY The transmit request could not be queued because the transmit queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_TRANSMIT)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token + ); + +/** + Places an asynchronous receiving request into the receiving queue. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Token The pointer to a token associated with the receive data descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a lack of system resources + (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_ACCESS_DENIED The receive completion token was already in the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_RECEIVE)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token + ); + + +/** + Aborts an asynchronous transmit or receive request. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Token The pointer to a token that has been issued by + EFI_MANAGED_NETWORK_PROTOCOL.Transmit() or + EFI_MANAGED_NETWORK_PROTOCOL.Receive(). If + NULL, all pending tokens are aborted. + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and Token.Event + was signaled. When Token is NULL, all pending requests were + aborted and their events were signaled. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_CANCEL)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token OPTIONAL + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + @param This The pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data was processed. Consider increasing + the polling rate. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_POLL)( + IN EFI_MANAGED_NETWORK_PROTOCOL *This + ); + +/// +/// The MNP is used by network applications (and drivers) to +/// perform raw (unformatted) asynchronous network packet I/O. +/// +struct _EFI_MANAGED_NETWORK_PROTOCOL { + EFI_MANAGED_NETWORK_GET_MODE_DATA GetModeData; + EFI_MANAGED_NETWORK_CONFIGURE Configure; + EFI_MANAGED_NETWORK_MCAST_IP_TO_MAC McastIpToMac; + EFI_MANAGED_NETWORK_GROUPS Groups; + EFI_MANAGED_NETWORK_TRANSMIT Transmit; + EFI_MANAGED_NETWORK_RECEIVE Receive; + EFI_MANAGED_NETWORK_CANCEL Cancel; + EFI_MANAGED_NETWORK_POLL Poll; +}; + +extern EFI_GUID gEfiManagedNetworkServiceBindingProtocolGuid; +extern EFI_GUID gEfiManagedNetworkProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/McaInitPmi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/McaInitPmi.h new file mode 100644 index 0000000..1c0abd5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/McaInitPmi.h @@ -0,0 +1,207 @@ +/** @file + MCA/PMI/INIT Protocol as defined in PI Specification VOLUME 4. + + This protocol provides services to handle Machine Checks (MCA), + Initialization (INIT) events, and Platform Management Interrupt (PMI) events + on an Intel Itanium Processor Family based system. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __MCA_INIT_PMI_PROTOCOL_H__ +#define __MCA_INIT_PMI_PROTOCOL_H__ + +/// +/// Global ID for the MCA/PMI/INIT Protocol. +/// +#define EFI_SAL_MCA_INIT_PMI_PROTOCOL_GUID \ + { 0xb60dc6e8, 0x3b6f, 0x11d5, {0xaf, 0x9, 0x0, 0xa0, 0xc9, 0x44, 0xa0, 0x5b} } + + +/// +/// Declare forward reference for the Timer Architectural Protocol +/// +typedef struct _EFI_SAL_MCA_INIT_PMI_PROTOCOL EFI_SAL_MCA_INIT_PMI_PROTOCOL; + +#pragma pack(1) +/// +/// MCA Records Structure +/// +typedef struct { + UINT64 First : 1; + UINT64 Last : 1; + UINT64 EntryCount : 16; + UINT64 DispatchedCount : 16; + UINT64 Reserved : 30; +} SAL_MCA_COUNT_STRUCTURE; + +#pragma pack() + +/** + Prototype of MCA handler. + + @param ModuleGlobal The context of MCA Handler + @param ProcessorStateParameters The processor state parameters (PSP) + @param MinstateBase Base address of the min-state + @param RendezvouseStateInformation Rendezvous state information to be passed to + the OS on OS MCA entry + @param CpuIndex Index of the logical processor + @param McaCountStructure Pointer to the MCA records structure + @param CorrectedMachineCheck This flag is set to TRUE is the MCA has been + corrected by the handler or by a previous handler + + @retval EFI_SUCCESS Handler successfully returned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SAL_MCA_HANDLER)( + IN VOID *ModuleGlobal, + IN UINT64 ProcessorStateParameters, + IN EFI_PHYSICAL_ADDRESS MinstateBase, + IN UINT64 RendezvouseStateInformation, + IN UINT64 CpuIndex, + IN SAL_MCA_COUNT_STRUCTURE *McaCountStructure, + OUT BOOLEAN *CorrectedMachineCheck + ); + +/** + Prototype of INIT handler. + + @param ModuleGlobal The context of INIT Handler + @param ProcessorStateParameters The processor state parameters (PSP) + @param MinstateBase Base address of the min-state + @param McaInProgress This flag indicates if an MCA is in progress + @param CpuIndex Index of the logical processor + @param McaCountStructure Pointer to the MCA records structure + @param DumpSwitchPressed This flag indicates the crash dump switch has been pressed + + @retval EFI_SUCCESS Handler successfully returned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SAL_INIT_HANDLER)( + IN VOID *ModuleGlobal, + IN UINT64 ProcessorStateParameters, + IN EFI_PHYSICAL_ADDRESS MinstateBase, + IN BOOLEAN McaInProgress, + IN UINT64 CpuIndex, + IN SAL_MCA_COUNT_STRUCTURE *McaCountStructure, + OUT BOOLEAN *DumpSwitchPressed + ); + +/** + Prototype of PMI handler + + @param ModuleGlobal The context of PMI Handler + @param CpuIndex Index of the logical processor + @param PmiVector The PMI vector number as received from the PALE_PMI exit state (GR24) + + @retval EFI_SUCCESS Handler successfully returned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SAL_PMI_HANDLER)( + IN VOID *ModuleGlobal, + IN UINT64 CpuIndex, + IN UINT64 PmiVector + ); + +/** + Register a MCA handler with the MCA dispatcher. + + @param This The EFI_SAL_MCA_INIT_PMI_PROTOCOL instance + @param McaHandler The MCA handler to register + @param ModuleGlobal The context of MCA Handler + @param MakeFirst This flag specifies the handler should be made first in the list + @param MakeLast This flag specifies the handler should be made last in the list + + @retval EFI_SUCCESS MCA Handle was registered + @retval EFI_OUT_OF_RESOURCES No more resources to register an MCA handler + @retval EFI_INVALID_PARAMETER Invalid parameters were passed + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SAL_REGISTER_MCA_HANDLER)( + IN EFI_SAL_MCA_INIT_PMI_PROTOCOL *This, + IN EFI_SAL_MCA_HANDLER McaHandler, + IN VOID *ModuleGlobal, + IN BOOLEAN MakeFirst, + IN BOOLEAN MakeLast + ); + +/** + Register an INIT handler with the INIT dispatcher. + + @param This The EFI_SAL_MCA_INIT_PMI_PROTOCOL instance + @param InitHandler The INIT handler to register + @param ModuleGlobal The context of INIT Handler + @param MakeFirst This flag specifies the handler should be made first in the list + @param MakeLast This flag specifies the handler should be made last in the list + + @retval EFI_SUCCESS INIT Handle was registered + @retval EFI_OUT_OF_RESOURCES No more resources to register an INIT handler + @retval EFI_INVALID_PARAMETER Invalid parameters were passed + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SAL_REGISTER_INIT_HANDLER)( + IN EFI_SAL_MCA_INIT_PMI_PROTOCOL *This, + IN EFI_SAL_INIT_HANDLER InitHandler, + IN VOID *ModuleGlobal, + IN BOOLEAN MakeFirst, + IN BOOLEAN MakeLast + ); + +/** + Register a PMI handler with the PMI dispatcher. + + @param This The EFI_SAL_MCA_INIT_PMI_PROTOCOL instance + @param PmiHandler The PMI handler to register + @param ModuleGlobal The context of PMI Handler + @param MakeFirst This flag specifies the handler should be made first in the list + @param MakeLast This flag specifies the handler should be made last in the list + + @retval EFI_SUCCESS PMI Handle was registered + @retval EFI_OUT_OF_RESOURCES No more resources to register an PMI handler + @retval EFI_INVALID_PARAMETER Invalid parameters were passed + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SAL_REGISTER_PMI_HANDLER)( + IN EFI_SAL_MCA_INIT_PMI_PROTOCOL *This, + IN EFI_SAL_PMI_HANDLER PmiHandler, + IN VOID *ModuleGlobal, + IN BOOLEAN MakeFirst, + IN BOOLEAN MakeLast + ); + +/// +/// This protocol is used to register MCA, INIT and PMI handlers with their respective dispatcher +/// +struct _EFI_SAL_MCA_INIT_PMI_PROTOCOL { + EFI_SAL_REGISTER_MCA_HANDLER RegisterMcaHandler; + EFI_SAL_REGISTER_INIT_HANDLER RegisterInitHandler; + EFI_SAL_REGISTER_PMI_HANDLER RegisterPmiHandler; + BOOLEAN McaInProgress; ///< Whether MCA handler is in progress + BOOLEAN InitInProgress; ///< Whether Init handler is in progress + BOOLEAN PmiInProgress; ///< Whether Pmi handler is in progress +}; + +extern EFI_GUID gEfiSalMcaInitPmiProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Metronome.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Metronome.h new file mode 100644 index 0000000..23b16bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Metronome.h @@ -0,0 +1,80 @@ +/** @file + Metronome Architectural Protocol as defined in PI SPEC VOLUME 2 DXE + + This code abstracts the DXE core to provide delay services. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_METRONOME_H__ +#define __ARCH_PROTOCOL_METRONOME_H__ + +/// +/// Global ID for the Metronome Architectural Protocol +/// +#define EFI_METRONOME_ARCH_PROTOCOL_GUID \ + { 0x26baccb2, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +/// +/// Declare forward reference for the Metronome Architectural Protocol +/// +typedef struct _EFI_METRONOME_ARCH_PROTOCOL EFI_METRONOME_ARCH_PROTOCOL; + +/** + The WaitForTick() function waits for the number of ticks specified by + TickNumber from a known time source in the platform. If TickNumber of + ticks are detected, then EFI_SUCCESS is returned. The actual time passed + between entry of this function and the first tick is between 0 and + TickPeriod 100 nS units. If you want to guarantee that at least TickPeriod + time has elapsed, wait for two ticks. This function waits for a hardware + event to determine when a tick occurs. It is possible for interrupt + processing, or exception processing to interrupt the execution of the + WaitForTick() function. Depending on the hardware source for the ticks, it + is possible for a tick to be missed. This function cannot guarantee that + ticks will not be missed. If a timeout occurs waiting for the specified + number of ticks, then EFI_TIMEOUT is returned. + + @param This The EFI_METRONOME_ARCH_PROTOCOL instance. + @param TickNumber Number of ticks to wait. + + @retval EFI_SUCCESS The wait for the number of ticks specified by TickNumber + succeeded. + @retval EFI_TIMEOUT A timeout occurred waiting for the specified number of ticks. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_METRONOME_WAIT_FOR_TICK)( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ); + +/// +/// This protocol provides access to a known time source in the platform to the +/// core. The core uses this known time source to produce core services that +/// require calibrated delays. +/// +struct _EFI_METRONOME_ARCH_PROTOCOL { + EFI_METRONOME_WAIT_FOR_TICK WaitForTick; + + /// + /// The period of platform's known time source in 100 nS units. + /// This value on any platform must be at least 10 uS, and must not + /// exceed 200 uS. The value in this field is a constant that must + /// not be modified after the Metronome architectural protocol is + /// installed. All consumers must treat this as a read-only field. + /// + UINT32 TickPeriod; +}; + +extern EFI_GUID gEfiMetronomeArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmAccess.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmAccess.h new file mode 100644 index 0000000..eb94bc5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmAccess.h @@ -0,0 +1,133 @@ +/** @file + EFI MM Access Protocol as defined in the PI 1.5 specification. + + This protocol is used to control the visibility of the MMRAM on the platform. + It abstracts the location and characteristics of MMRAM. The expectation is + that the north bridge or memory controller would publish this protocol. + + The principal functionality found in the memory controller includes the following: + - Exposing the MMRAM to all non-MM agents, or the "open" state + - Shrouding the MMRAM to all but the MM agents, or the "closed" state + - Preserving the system integrity, or "locking" the MMRAM, such that the settings cannot be + perturbed by either boot service or runtime agents + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_ACCESS_H_ +#define _MM_ACCESS_H_ + +#define EFI_MM_ACCESS_PROTOCOL_GUID \ + { \ + 0xc2702b74, 0x800c, 0x4131, {0x87, 0x46, 0x8f, 0xb5, 0xb8, 0x9c, 0xe4, 0xac } \ + } + + +typedef struct _EFI_MM_ACCESS_PROTOCOL EFI_MM_ACCESS_PROTOCOL; + +/** + Opens the MMRAM area to be accessible by a boot-service driver. + + This function "opens" MMRAM so that it is visible while not inside of MM. The function should + return EFI_UNSUPPORTED if the hardware does not support hiding of MMRAM. The function + should return EFI_DEVICE_ERROR if the MMRAM configuration is locked. + + @param[in] This The EFI_MM_ACCESS_PROTOCOL instance. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_UNSUPPORTED The system does not support opening and closing of MMRAM. + @retval EFI_DEVICE_ERROR MMRAM cannot be opened, perhaps because it is locked. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_OPEN)( + IN EFI_MM_ACCESS_PROTOCOL *This + ); + +/** + Inhibits access to the MMRAM. + + This function "closes" MMRAM so that it is not visible while outside of MM. The function should + return EFI_UNSUPPORTED if the hardware does not support hiding of MMRAM. + + @param[in] This The EFI_MM_ACCESS_PROTOCOL instance. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_UNSUPPORTED The system does not support opening and closing of MMRAM. + @retval EFI_DEVICE_ERROR MMRAM cannot be closed. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_CLOSE)( + IN EFI_MM_ACCESS_PROTOCOL *This + ); + +/** + Inhibits access to the MMRAM. + + This function prohibits access to the MMRAM region. This function is usually implemented such + that it is a write-once operation. + + @param[in] This The EFI_MM_ACCESS_PROTOCOL instance. + + @retval EFI_SUCCESS The device was successfully locked. + @retval EFI_UNSUPPORTED The system does not support locking of MMRAM. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_LOCK)( + IN EFI_MM_ACCESS_PROTOCOL *This + ); + +/** + Queries the memory controller for the possible regions that will support MMRAM. + + @param[in] This The EFI_MM_ACCESS_PROTOCOL instance. + @param[in,out] MmramMapSize A pointer to the size, in bytes, of the MmramMemoryMap buffer. + @param[in,out] MmramMap A pointer to the buffer in which firmware places the current memory map. + + @retval EFI_SUCCESS The chipset supported the given resource. + @retval EFI_BUFFER_TOO_SMALL The MmramMap parameter was too small. The current buffer size + needed to hold the memory map is returned in MmramMapSize. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_CAPABILITIES)( + IN CONST EFI_MM_ACCESS_PROTOCOL *This, + IN OUT UINTN *MmramMapSize, + IN OUT EFI_MMRAM_DESCRIPTOR *MmramMap + ); + +/// +/// EFI MM Access Protocol is used to control the visibility of the MMRAM on the platform. +/// It abstracts the location and characteristics of MMRAM. The platform should report all +/// MMRAM via EFI_MM_ACCESS_PROTOCOL. The expectation is that the north bridge or memory +/// controller would publish this protocol. +/// +struct _EFI_MM_ACCESS_PROTOCOL { + EFI_MM_OPEN Open; + EFI_MM_CLOSE Close; + EFI_MM_LOCK Lock; + EFI_MM_CAPABILITIES GetCapabilities; + /// + /// Indicates the current state of the MMRAM. Set to TRUE if MMRAM is locked. + /// + BOOLEAN LockState; + /// + /// Indicates the current state of the MMRAM. Set to TRUE if MMRAM is open. + /// + BOOLEAN OpenState; +}; + +extern EFI_GUID gEfiMmAccessProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmBase.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmBase.h new file mode 100644 index 0000000..4ce410e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmBase.h @@ -0,0 +1,87 @@ +/** @file + EFI MM Base Protocol as defined in the PI 1.5 specification. + + This protocol is utilized by all MM drivers to locate the MM infrastructure services and determine + whether the driver is being invoked inside MMRAM or outside of MMRAM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_BASE_H_ +#define _MM_BASE_H_ + +#include + +#define EFI_MM_BASE_PROTOCOL_GUID \ + { \ + 0xf4ccbfb7, 0xf6e0, 0x47fd, {0x9d, 0xd4, 0x10, 0xa8, 0xf1, 0x50, 0xc1, 0x91 } \ + } + +typedef struct _EFI_MM_BASE_PROTOCOL EFI_MM_BASE_PROTOCOL; + +/** + Service to indicate whether the driver is currently executing in the MM Initialization phase. + + This service is used to indicate whether the driver is currently executing in the MM Initialization + phase. For MM drivers, this will return TRUE in InMmram while inside the driver's entry point and + otherwise FALSE. For combination MM/DXE drivers, this will return FALSE in the DXE launch. For the + MM launch, it behaves as an MM driver. + + @param[in] This The EFI_MM_BASE_PROTOCOL instance. + @param[out] InMmram Pointer to a Boolean which, on return, indicates that the driver is + currently executing inside of MMRAM (TRUE) or outside of MMRAM (FALSE). + + @retval EFI_SUCCESS The call returned successfully. + @retval EFI_INVALID_PARAMETER InMmram was NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_INSIDE_OUT)( + IN CONST EFI_MM_BASE_PROTOCOL *This, + OUT BOOLEAN *InMmram + ) +; + +/** + Returns the location of the Management Mode Service Table (MMST). + + This function returns the location of the Management Mode Service Table (MMST). The use of the + API is such that a driver can discover the location of the MMST in its entry point and then cache it in + some driver global variable so that the MMST can be invoked in subsequent handlers. + + @param[in] This The EFI_MM_BASE_PROTOCOL instance. + @param[in,out] Mmst On return, points to a pointer to the Management Mode Service Table (MMST). + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Mmst was invalid. + @retval EFI_UNSUPPORTED Not in MM. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_GET_MMST_LOCATION)( + IN CONST EFI_MM_BASE_PROTOCOL *This, + IN OUT EFI_MM_SYSTEM_TABLE **Mmst + ) +; + +/// +/// EFI MM Base Protocol is utilized by all MM drivers to locate the MM infrastructure +/// services and determine whether the driver is being invoked inside MMRAM or outside of MMRAM. +/// +struct _EFI_MM_BASE_PROTOCOL { + EFI_MM_INSIDE_OUT InMm; + EFI_MM_GET_MMST_LOCATION GetMmstLocation; +}; + +extern EFI_GUID gEfiMmBaseProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCommunication.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCommunication.h new file mode 100644 index 0000000..db87dd8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCommunication.h @@ -0,0 +1,93 @@ +/** @file + EFI MM Communication Protocol as defined in the PI 1.5 specification. + + This protocol provides a means of communicating between drivers outside of MM and MMI + handlers inside of MM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_COMMUNICATION_H_ +#define _MM_COMMUNICATION_H_ + +#pragma pack(1) + +/// +/// To avoid confusion in interpreting frames, the communication buffer should always +/// begin with EFI_MM_COMMUNICATE_HEADER +/// +typedef struct { + /// + /// Allows for disambiguation of the message format. + /// + EFI_GUID HeaderGuid; + /// + /// Describes the size of Data (in bytes) and does not include the size of the header. + /// + UINTN MessageLength; + /// + /// Designates an array of bytes that is MessageLength in size. + /// + UINT8 Data[1]; +} EFI_MM_COMMUNICATE_HEADER; + +#pragma pack() + +#define EFI_MM_COMMUNICATION_PROTOCOL_GUID \ + { \ + 0xc68ed8e2, 0x9dc6, 0x4cbd, { 0x9d, 0x94, 0xdb, 0x65, 0xac, 0xc5, 0xc3, 0x32 } \ + } + +typedef struct _EFI_MM_COMMUNICATION_PROTOCOL EFI_MM_COMMUNICATION_PROTOCOL; + +/** + Communicates with a registered handler. + + This function provides a service to send and receive messages from a registered UEFI service. + + @param[in] This The EFI_MM_COMMUNICATION_PROTOCOL instance. + @param[in] CommBuffer A pointer to the buffer to convey into MMRAM. + @param[in] CommSize The size of the data buffer being passed in. On exit, the size of data + being returned. Zero if the handler does not wish to reply with any data. + This parameter is optional and may be NULL. + + @retval EFI_SUCCESS The message was successfully posted. + @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. + If this error is returned, the MessageLength field + in the CommBuffer header or the integer pointed by + CommSize, are updated to reflect the maximum payload + size the implementation can accommodate. + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, + if not omitted, are in address range that cannot be + accessed by the MM environment. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_COMMUNICATE)( + IN CONST EFI_MM_COMMUNICATION_PROTOCOL *This, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommSize OPTIONAL + ); + +/// +/// EFI MM Communication Protocol provides runtime services for communicating +/// between DXE drivers and a registered MMI handler. +/// +struct _EFI_MM_COMMUNICATION_PROTOCOL { + EFI_MM_COMMUNICATE Communicate; +}; + +extern EFI_GUID gEfiMmCommunicationProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmConfiguration.h new file mode 100644 index 0000000..5bb5ddf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmConfiguration.h @@ -0,0 +1,86 @@ +/** @file + EFI MM Configuration Protocol as defined in the PI 1.5 specification. + + This protocol is used to: + 1) report the portions of MMRAM regions which cannot be used for the MMRAM heap. + 2) register the MM Foundation entry point with the processor code. The entry + point will be invoked by the MM processor entry code. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_CONFIGURATION_H_ +#define _MM_CONFIGURATION_H_ + +#include + +#define EFI_MM_CONFIGURATION_PROTOCOL_GUID \ + { \ + 0x26eeb3de, 0xb689, 0x492e, {0x80, 0xf0, 0xbe, 0x8b, 0xd7, 0xda, 0x4b, 0xa7 } \ + } + +/// +/// Structure describing a MMRAM region which cannot be used for the MMRAM heap. +/// +typedef struct _EFI_MM_RESERVED_MMRAM_REGION { + /// + /// Starting address of the reserved MMRAM area, as it appears while MMRAM is open. + /// Ignored if MmramReservedSize is 0. + /// + EFI_PHYSICAL_ADDRESS MmramReservedStart; + /// + /// Number of bytes occupied by the reserved MMRAM area. A size of zero indicates the + /// last MMRAM area. + /// + UINT64 MmramReservedSize; +} EFI_MM_RESERVED_MMRAM_REGION; + +typedef struct _EFI_MM_CONFIGURATION_PROTOCOL EFI_MM_CONFIGURATION_PROTOCOL; + +/** + Register the MM Foundation entry point. + + This function registers the MM Foundation entry point with the processor code. This entry point + will be invoked by the MM Processor entry code. + + @param[in] This The EFI_MM_CONFIGURATION_PROTOCOL instance. + @param[in] MmEntryPoint MM Foundation entry point. + + @retval EFI_SUCCESS Success to register MM Entry Point. + @retval EFI_INVALID_PARAMETER MmEntryPoint is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_REGISTER_MM_ENTRY)( + IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This, + IN EFI_MM_ENTRY_POINT MmEntryPoint + ); + +/// +/// The EFI MM Configuration Protocol is a mandatory protocol published by a DXE CPU driver to +/// indicate which areas within MMRAM are reserved for use by the CPU for any purpose, +/// such as stack, save state or MM entry point. +/// +/// The RegistermmEntry() function allows the MM IPL DXE driver to register the MM +/// Foundation entry point with the MM entry vector code. +/// +struct _EFI_MM_CONFIGURATION_PROTOCOL { + /// + /// A pointer to an array MMRAM ranges used by the initial MM entry code. + /// + EFI_MM_RESERVED_MMRAM_REGION *MmramReservedRegions; + EFI_MM_REGISTER_MM_ENTRY RegisterMmEntry; +}; + +extern EFI_GUID gEfiMmConfigurationProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmControl.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmControl.h new file mode 100644 index 0000000..e1d0dc1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmControl.h @@ -0,0 +1,106 @@ +/** @file + EFI MM Control Protocol as defined in the PI 1.5 specification. + + This protocol is used initiate synchronous MMI activations. This protocol could be published by a + processor driver to abstract the MMI IPI or a driver which abstracts the ASIC that is supporting the + APM port. Because of the possibility of performing MMI IPI transactions, the ability to generate this + event from a platform chipset agent is an optional capability for both IA-32 and x64-based systems. + + The EFI_MM_CONTROL_PROTOCOL is produced by a runtime driver. It provides an + abstraction of the platform hardware that generates an MMI. There are often I/O ports that, when + accessed, will generate the MMI. Also, the hardware optionally supports the periodic generation of + these signals. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_CONTROL_H_ +#define _MM_CONTROL_H_ + +#include + +#define EFI_MM_CONTROL_PROTOCOL_GUID \ + { \ + 0x843dc720, 0xab1e, 0x42cb, {0x93, 0x57, 0x8a, 0x0, 0x78, 0xf3, 0x56, 0x1b} \ + } + +typedef struct _EFI_MM_CONTROL_PROTOCOL EFI_MM_CONTROL_PROTOCOL; +typedef UINTN EFI_MM_PERIOD; + +/** + Invokes MMI activation from either the preboot or runtime environment. + + This function generates an MMI. + + @param[in] This The EFI_MM_CONTROL_PROTOCOL instance. + @param[in,out] CommandPort The value written to the command port. + @param[in,out] DataPort The value written to the data port. + @param[in] Periodic Optional mechanism to engender a periodic stream. + @param[in] ActivationInterval Optional parameter to repeat at this period one + time or, if the Periodic Boolean is set, periodically. + + @retval EFI_SUCCESS The MMI/PMI has been engendered. + @retval EFI_DEVICE_ERROR The timing is unsupported. + @retval EFI_INVALID_PARAMETER The activation period is unsupported. + @retval EFI_INVALID_PARAMETER The last periodic activation has not been cleared. + @retval EFI_NOT_STARTED The MM base service has not been initialized. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_ACTIVATE)( + IN CONST EFI_MM_CONTROL_PROTOCOL *This, + IN OUT UINT8 *CommandPort OPTIONAL, + IN OUT UINT8 *DataPort OPTIONAL, + IN BOOLEAN Periodic OPTIONAL, + IN UINTN ActivationInterval OPTIONAL + ); + +/** + Clears any system state that was created in response to the Trigger() call. + + This function acknowledges and causes the deassertion of the MMI activation source. + + @param[in] This The EFI_MM_CONTROL_PROTOCOL instance. + @param[in] Periodic Optional parameter to repeat at this period one time + + @retval EFI_SUCCESS The MMI/PMI has been engendered. + @retval EFI_DEVICE_ERROR The source could not be cleared. + @retval EFI_INVALID_PARAMETER The service did not support the Periodic input argument. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_DEACTIVATE)( + IN CONST EFI_MM_CONTROL_PROTOCOL *This, + IN BOOLEAN Periodic OPTIONAL + ); + +/// +/// The EFI_MM_CONTROL_PROTOCOL is produced by a runtime driver. It provides an +/// abstraction of the platform hardware that generates an MMI. There are often I/O ports that, when +/// accessed, will generate the MMI. Also, the hardware optionally supports the periodic generation of +/// these signals. +/// +struct _EFI_MM_CONTROL_PROTOCOL { + EFI_MM_ACTIVATE Trigger; + EFI_MM_DEACTIVATE Clear; + /// + /// Minimum interval at which the platform can set the period. A maximum is not + /// specified in that the MM infrastructure code can emulate a maximum interval that is + /// greater than the hardware capabilities by using software emulation in the MM + /// infrastructure code. + /// + EFI_MM_PERIOD MinimumTriggerPeriod; +}; + +extern EFI_GUID gEfiMmControlProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpu.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpu.h new file mode 100644 index 0000000..9670cda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpu.h @@ -0,0 +1,247 @@ +/** @file + EFI MM CPU Protocol as defined in the PI 1.5 specification. + + This protocol allows MM drivers to access architecture-standard registers from any of the CPU + save state areas. In some cases, difference processors provide the same information in the save state, + but not in the same format. These so-called pseudo-registers provide this information in a standard + format. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_CPU_H_ +#define _MM_CPU_H_ + +#define EFI_MM_CPU_PROTOCOL_GUID \ + { \ + 0xeb346b97, 0x975f, 0x4a9f, { 0x8b, 0x22, 0xf8, 0xe9, 0x2b, 0xb3, 0xd5, 0x69 } \ + } + +/// +/// Save State register index +/// +typedef enum { + /// + /// x86/X64 standard registers + /// + EFI_MM_SAVE_STATE_REGISTER_GDTBASE = 4, + EFI_MM_SAVE_STATE_REGISTER_IDTBASE = 5, + EFI_MM_SAVE_STATE_REGISTER_LDTBASE = 6, + EFI_MM_SAVE_STATE_REGISTER_GDTLIMIT = 7, + EFI_MM_SAVE_STATE_REGISTER_IDTLIMIT = 8, + EFI_MM_SAVE_STATE_REGISTER_LDTLIMIT = 9, + EFI_MM_SAVE_STATE_REGISTER_LDTINFO = 10, + EFI_MM_SAVE_STATE_REGISTER_ES = 20, + EFI_MM_SAVE_STATE_REGISTER_CS = 21, + EFI_MM_SAVE_STATE_REGISTER_SS = 22, + EFI_MM_SAVE_STATE_REGISTER_DS = 23, + EFI_MM_SAVE_STATE_REGISTER_FS = 24, + EFI_MM_SAVE_STATE_REGISTER_GS = 25, + EFI_MM_SAVE_STATE_REGISTER_LDTR_SEL = 26, + EFI_MM_SAVE_STATE_REGISTER_TR_SEL = 27, + EFI_MM_SAVE_STATE_REGISTER_DR7 = 28, + EFI_MM_SAVE_STATE_REGISTER_DR6 = 29, + EFI_MM_SAVE_STATE_REGISTER_R8 = 30, + EFI_MM_SAVE_STATE_REGISTER_R9 = 31, + EFI_MM_SAVE_STATE_REGISTER_R10 = 32, + EFI_MM_SAVE_STATE_REGISTER_R11 = 33, + EFI_MM_SAVE_STATE_REGISTER_R12 = 34, + EFI_MM_SAVE_STATE_REGISTER_R13 = 35, + EFI_MM_SAVE_STATE_REGISTER_R14 = 36, + EFI_MM_SAVE_STATE_REGISTER_R15 = 37, + EFI_MM_SAVE_STATE_REGISTER_RAX = 38, + EFI_MM_SAVE_STATE_REGISTER_RBX = 39, + EFI_MM_SAVE_STATE_REGISTER_RCX = 40, + EFI_MM_SAVE_STATE_REGISTER_RDX = 41, + EFI_MM_SAVE_STATE_REGISTER_RSP = 42, + EFI_MM_SAVE_STATE_REGISTER_RBP = 43, + EFI_MM_SAVE_STATE_REGISTER_RSI = 44, + EFI_MM_SAVE_STATE_REGISTER_RDI = 45, + EFI_MM_SAVE_STATE_REGISTER_RIP = 46, + EFI_MM_SAVE_STATE_REGISTER_RFLAGS = 51, + EFI_MM_SAVE_STATE_REGISTER_CR0 = 52, + EFI_MM_SAVE_STATE_REGISTER_CR3 = 53, + EFI_MM_SAVE_STATE_REGISTER_CR4 = 54, + EFI_MM_SAVE_STATE_REGISTER_FCW = 256, + EFI_MM_SAVE_STATE_REGISTER_FSW = 257, + EFI_MM_SAVE_STATE_REGISTER_FTW = 258, + EFI_MM_SAVE_STATE_REGISTER_OPCODE = 259, + EFI_MM_SAVE_STATE_REGISTER_FP_EIP = 260, + EFI_MM_SAVE_STATE_REGISTER_FP_CS = 261, + EFI_MM_SAVE_STATE_REGISTER_DATAOFFSET = 262, + EFI_MM_SAVE_STATE_REGISTER_FP_DS = 263, + EFI_MM_SAVE_STATE_REGISTER_MM0 = 264, + EFI_MM_SAVE_STATE_REGISTER_MM1 = 265, + EFI_MM_SAVE_STATE_REGISTER_MM2 = 266, + EFI_MM_SAVE_STATE_REGISTER_MM3 = 267, + EFI_MM_SAVE_STATE_REGISTER_MM4 = 268, + EFI_MM_SAVE_STATE_REGISTER_MM5 = 269, + EFI_MM_SAVE_STATE_REGISTER_MM6 = 270, + EFI_MM_SAVE_STATE_REGISTER_MM7 = 271, + EFI_MM_SAVE_STATE_REGISTER_XMM0 = 272, + EFI_MM_SAVE_STATE_REGISTER_XMM1 = 273, + EFI_MM_SAVE_STATE_REGISTER_XMM2 = 274, + EFI_MM_SAVE_STATE_REGISTER_XMM3 = 275, + EFI_MM_SAVE_STATE_REGISTER_XMM4 = 276, + EFI_MM_SAVE_STATE_REGISTER_XMM5 = 277, + EFI_MM_SAVE_STATE_REGISTER_XMM6 = 278, + EFI_MM_SAVE_STATE_REGISTER_XMM7 = 279, + EFI_MM_SAVE_STATE_REGISTER_XMM8 = 280, + EFI_MM_SAVE_STATE_REGISTER_XMM9 = 281, + EFI_MM_SAVE_STATE_REGISTER_XMM10 = 282, + EFI_MM_SAVE_STATE_REGISTER_XMM11 = 283, + EFI_MM_SAVE_STATE_REGISTER_XMM12 = 284, + EFI_MM_SAVE_STATE_REGISTER_XMM13 = 285, + EFI_MM_SAVE_STATE_REGISTER_XMM14 = 286, + EFI_MM_SAVE_STATE_REGISTER_XMM15 = 287, + /// + /// Pseudo-Registers + /// + EFI_MM_SAVE_STATE_REGISTER_IO = 512, + EFI_MM_SAVE_STATE_REGISTER_LMA = 513, + EFI_MM_SAVE_STATE_REGISTER_PROCESSOR_ID = 514 +} EFI_MM_SAVE_STATE_REGISTER; + +/// +/// The EFI_MM_SAVE_STATE_REGISTER_LMA pseudo-register values +/// If the processor acts in 32-bit mode at the time the MMI occurred, the pseudo register value +/// EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT is returned in Buffer. Otherwise, +/// EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT is returned in Buffer. +/// +#define EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT 32 +#define EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT 64 + +/// +/// Size width of I/O instruction +/// +typedef enum { + EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 = 0, + EFI_MM_SAVE_STATE_IO_WIDTH_UINT16 = 1, + EFI_MM_SAVE_STATE_IO_WIDTH_UINT32 = 2, + EFI_MM_SAVE_STATE_IO_WIDTH_UINT64 = 3 +} EFI_MM_SAVE_STATE_IO_WIDTH; + +/// +/// Types of I/O instruction +/// +typedef enum { + EFI_MM_SAVE_STATE_IO_TYPE_INPUT = 1, + EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT = 2, + EFI_MM_SAVE_STATE_IO_TYPE_STRING = 4, + EFI_MM_SAVE_STATE_IO_TYPE_REP_PREFIX = 8 +} EFI_MM_SAVE_STATE_IO_TYPE; + +/// +/// Structure of the data which is returned when ReadSaveState() is called with +/// EFI_MM_SAVE_STATE_REGISTER_IO. If there was no I/O then ReadSaveState() will +/// return EFI_NOT_FOUND. +/// +/// This structure describes the I/O operation which was in process when the MMI was generated. +/// +typedef struct _EFI_MM_SAVE_STATE_IO_INFO { + /// + /// For input instruction (IN, INS), this is data read before the MMI occurred. For output + /// instructions (OUT, OUTS) this is data that was written before the MMI occurred. The + /// width of the data is specified by IoWidth. + /// + UINT64 IoData; + /// + /// The I/O port that was being accessed when the MMI was triggered. + /// + UINT16 IoPort; + /// + /// Defines the size width (UINT8, UINT16, UINT32, UINT64) for IoData. + /// + EFI_MM_SAVE_STATE_IO_WIDTH IoWidth; + /// + /// Defines type of I/O instruction. + /// + EFI_MM_SAVE_STATE_IO_TYPE IoType; +} EFI_MM_SAVE_STATE_IO_INFO; + +typedef struct _EFI_MM_CPU_PROTOCOL EFI_MM_CPU_PROTOCOL; + +/** + Read data from the CPU save state. + + This function is used to read the specified number of bytes of the specified register from the CPU + save state of the specified CPU and place the value into the buffer. If the CPU does not support the + specified register Register, then EFI_NOT_FOUND should be returned. If the CPU does not + support the specified register width Width, then EFI_INVALID_PARAMETER is returned. + + @param[in] This The EFI_MM_CPU_PROTOCOL instance. + @param[in] Width The number of bytes to read from the CPU save state. + @param[in] Register Specifies the CPU register to read form the save state. + @param[in] CpuIndex Specifies the zero-based index of the CPU save state. + @param[out] Buffer Upon return, this holds the CPU register value read from the save state. + + @retval EFI_SUCCESS The register was read from Save State. + @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor. + @retval EFI_INVALID_PARAMETER Input parameters are not valid, for example, Processor No or register width + is not correct.This or Buffer is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_READ_SAVE_STATE)( + IN CONST EFI_MM_CPU_PROTOCOL *This, + IN UINTN Width, + IN EFI_MM_SAVE_STATE_REGISTER Register, + IN UINTN CpuIndex, + OUT VOID *Buffer + ); + + +/** + Write data to the CPU save state. + + This function is used to write the specified number of bytes of the specified register to the CPU save + state of the specified CPU and place the value into the buffer. If the CPU does not support the + specified register Register, then EFI_UNSUPPORTED should be returned. If the CPU does not + support the specified register width Width, then EFI_INVALID_PARAMETER is returned. + + @param[in] This The EFI_MM_CPU_PROTOCOL instance. + @param[in] Width The number of bytes to write to the CPU save state. + @param[in] Register Specifies the CPU register to write to the save state. + @param[in] CpuIndex Specifies the zero-based index of the CPU save state. + @param[in] Buffer Upon entry, this holds the new CPU register value. + + @retval EFI_SUCCESS The register was written to Save State. + @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor. + @retval EFI_INVALID_PARAMETER Input parameters are not valid. For example: + ProcessorIndex or Width is not correct. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_WRITE_SAVE_STATE)( + IN CONST EFI_MM_CPU_PROTOCOL *This, + IN UINTN Width, + IN EFI_MM_SAVE_STATE_REGISTER Register, + IN UINTN CpuIndex, + IN CONST VOID *Buffer + ); + +/// +/// EFI MM CPU Protocol provides access to CPU-related information while in MM. +/// +/// This protocol allows MM drivers to access architecture-standard registers from any of the CPU +/// save state areas. In some cases, difference processors provide the same information in the save state, +/// but not in the same format. These so-called pseudo-registers provide this information in a standard +/// format. +/// +struct _EFI_MM_CPU_PROTOCOL { + EFI_MM_READ_SAVE_STATE ReadSaveState; + EFI_MM_WRITE_SAVE_STATE WriteSaveState; +}; + +extern EFI_GUID gEfiMmCpuProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpuIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpuIo.h new file mode 100644 index 0000000..4298cf4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmCpuIo.h @@ -0,0 +1,96 @@ +/** @file + MM CPU I/O 2 protocol as defined in the PI 1.5 specification. + + This protocol provides CPU I/O and memory access within MM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_CPU_IO_H_ +#define _MM_CPU_IO_H_ + +#define EFI_MM_CPU_IO_PROTOCOL_GUID \ + { \ + 0x3242A9D8, 0xCE70, 0x4AA0, { 0x95, 0x5D, 0x5E, 0x7B, 0x14, 0x0D, 0xE4, 0xD2 } \ + } + +typedef struct _EFI_MM_CPU_IO_PROTOCOL EFI_MM_CPU_IO_PROTOCOL; + +/// +/// Width of the MM CPU I/O operations +/// +typedef enum { + MM_IO_UINT8 = 0, + MM_IO_UINT16 = 1, + MM_IO_UINT32 = 2, + MM_IO_UINT64 = 3 +} EFI_MM_IO_WIDTH; + +/** + Provides the basic memory and I/O interfaces used toabstract accesses to devices. + + The I/O operations are carried out exactly as requested. The caller is + responsible for any alignment and I/O width issues that the bus, device, + platform, or type of I/O might require. + + @param[in] This The EFI_MM_CPU_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the I/O operations. + @param[in] Address The base address of the I/O operations. The caller is + responsible for aligning the Address if required. + @param[in] Count The number of I/O operations to perform. + @param[in,out] Buffer For read operations, the destination buffer to store + the results. For write operations, the source buffer + from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the device. + @retval EFI_UNSUPPORTED The Address is not valid for this system. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack + of resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_CPU_IO)( + IN CONST EFI_MM_CPU_IO_PROTOCOL *This, + IN EFI_MM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + /// + /// This service provides the various modalities of memory and I/O read. + /// + EFI_MM_CPU_IO Read; + /// + /// This service provides the various modalities of memory and I/O write. + /// + EFI_MM_CPU_IO Write; +} EFI_MM_IO_ACCESS; + +/// +/// MM CPU I/O Protocol provides CPU I/O and memory access within MM. +/// +struct _EFI_MM_CPU_IO_PROTOCOL { + /// + /// Allows reads and writes to memory-mapped I/O space. + /// + EFI_MM_IO_ACCESS Mem; + /// + /// Allows reads and writes to I/O space. + /// + EFI_MM_IO_ACCESS Io; +}; + +extern EFI_GUID gEfiMmCpuIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmEndOfDxe.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmEndOfDxe.h new file mode 100644 index 0000000..743eea3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmEndOfDxe.h @@ -0,0 +1,30 @@ +/** @file + MM End Of Dxe protocol introduced in the PI 1.5 specification. + + This protocol is a mandatory protocol published by MM Foundation code. + This protocol is an MM counterpart of the End of DXE Event. + This protocol prorogates End of DXE notification into MM environment. + This protocol is installed prior to installation of the MM Ready to Lock Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_END_OF_DXE_H_ +#define _MM_END_OF_DXE_H_ + +#define EFI_MM_END_OF_DXE_PROTOCOL_GUID \ + { \ + 0x24e70042, 0xd5c5, 0x4260, { 0x8c, 0x39, 0xa, 0xd3, 0xaa, 0x32, 0xe9, 0x3d } \ + } + +extern EFI_GUID gEfiMmEndOfDxeProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmGpiDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmGpiDispatch.h new file mode 100644 index 0000000..9a43072 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmGpiDispatch.h @@ -0,0 +1,125 @@ +/** @file + MM General Purpose Input (GPI) Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + This protocol provides the parent dispatch service for the General Purpose Input + (GPI) MMI source generator. + + The EFI_MM_GPI_DISPATCH_PROTOCOL provides the ability to install child handlers for the + given event types. Several inputs can be enabled. This purpose of this interface is to generate an + MMI in response to any of these inputs having a true value provided. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.5. + +**/ + +#ifndef _MM_GPI_DISPATCH_H_ +#define _MM_GPI_DISPATCH_H_ + +#include + +#define EFI_MM_GPI_DISPATCH_PROTOCOL_GUID \ + { \ + 0x25566b03, 0xb577, 0x4cbf, {0x95, 0x8c, 0xed, 0x66, 0x3e, 0xa2, 0x43, 0x80 } \ + } + +/// +/// The dispatch function's context. +/// +typedef struct { + /// + /// A number from one of 2^64 possible GPIs that can generate an MMI. A + /// 0 corresponds to logical GPI[0]; 1 corresponds to logical GPI[1]; and + /// GpiNum of N corresponds to GPI[N], where N can span from 0 to 2^64-1. + /// + UINT64 GpiNum; +} EFI_MM_GPI_REGISTER_CONTEXT; + +typedef struct _EFI_MM_GPI_DISPATCH_PROTOCOL EFI_MM_GPI_DISPATCH_PROTOCOL; + +/** + Registers a child MMI source dispatch function with a parent MM driver. + + This service registers a function (DispatchFunction) which will be called when an MMI is + generated because of one or more of the GPIs specified by RegisterContext. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer pointing to another instance of + EFI_MM_GPI_REGISTER_CONTEXT describing the GPIs which actually caused the MMI and + CommBufferSize pointing to the size of the structure. + + @param[in] This Pointer to the EFI_MM_GPI_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified GPI causes an MMI. + @param[in] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the GPI(s) for which the dispatch function + should be invoked. + @param[out] DispatchHandle Handle generated by the dispatcher to track the + function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The GPI input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_GPI_REGISTER)( + IN CONST EFI_MM_GPI_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN CONST EFI_MM_GPI_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters a General Purpose Input (GPI) service. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called when the GPI triggers an MMI. + + @param[in] This Pointer to the EFI_MM_GPI_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS Handle of the service to remove. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_GPI_UNREGISTER)( + IN CONST EFI_MM_GPI_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Interface structure for the MM GPI MMI Dispatch Protocol +/// +/// The MM GPI MMI Dispatch Protocol provides the parent dispatch service +/// for the General Purpose Input (GPI) MMI source generator. +/// +struct _EFI_MM_GPI_DISPATCH_PROTOCOL { + EFI_MM_GPI_REGISTER Register; + EFI_MM_GPI_UNREGISTER UnRegister; + /// + /// Denotes the maximum value of inputs that can have handlers attached. + /// + UINTN NumSupportedGpis; +}; + +extern EFI_GUID gEfiMmGpiDispatchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmIoTrapDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmIoTrapDispatch.h new file mode 100644 index 0000000..dec60bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmIoTrapDispatch.h @@ -0,0 +1,136 @@ +/** @file + MM IO Trap Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + This protocol provides a parent dispatch service for IO trap MMI sources. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.5. + +**/ + +#ifndef _MM_IO_TRAP_DISPATCH_H_ +#define _MM_IO_TRAP_DISPATCH_H_ + +#include + +#define EFI_MM_IO_TRAP_DISPATCH_PROTOCOL_GUID \ + { \ + 0x58dc368d, 0x7bfa, 0x4e77, {0xab, 0xbc, 0xe, 0x29, 0x41, 0x8d, 0xf9, 0x30 } \ + } + +/// +/// IO Trap valid types +/// +typedef enum { + WriteTrap, + ReadTrap, + ReadWriteTrap, + IoTrapTypeMaximum +} EFI_MM_IO_TRAP_DISPATCH_TYPE; + +/// +/// IO Trap context structure containing information about the +/// IO trap event that should invoke the handler +/// +typedef struct { + UINT16 Address; + UINT16 Length; + EFI_MM_IO_TRAP_DISPATCH_TYPE Type; +} EFI_MM_IO_TRAP_REGISTER_CONTEXT; + +/// +/// IO Trap context structure containing information about the IO trap that occurred +/// +typedef struct { + UINT32 WriteData; +} EFI_MM_IO_TRAP_CONTEXT; + +typedef struct _EFI_MM_IO_TRAP_DISPATCH_PROTOCOL EFI_MM_IO_TRAP_DISPATCH_PROTOCOL; + +/** + Register an IO trap MMI child handler for a specified MMI. + + This service registers a function (DispatchFunction) which will be called when an MMI is + generated because of an access to an I/O port specified by RegisterContext. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). If the base of the I/O range specified is zero, then an I/O range with the + specified length and characteristics will be allocated and the Address field in RegisterContext + updated. If no range could be allocated, then EFI_OUT_OF_RESOURCES will be returned. + + The service will not perform GCD allocation if the base address is non-zero or + EFI_MM_READY_TO_LOCK has been installed. In this case, the caller is responsible for the + existence and allocation of the specific IO range. + An error may be returned if some or all of the requested resources conflict with an existing IO trap + child handler. + + It is not required that implementations will allow multiple children for a single IO trap MMI source. + Some implementations may support multiple children. + The DispatchFunction will be called with Context updated to contain information + concerning the I/O action that actually happened and is passed in RegisterContext, with + CommBuffer pointing to the data actually written and CommBufferSize pointing to the size of + the data in CommBuffer. + + @param[in] This Pointer to the EFI_MM_IO_TRAP_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when I/O trap location is accessed. + @param[in] RegisterContext Pointer to the dispatch function's context. The caller fills this + context in before calling the register function to indicate to the register + function the IO trap MMI source for which the dispatch function should be invoked. + @param[out] DispatchHandle Handle of the dispatch function, for when interfacing with the parent MM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully registered. + @retval EFI_DEVICE_ERROR The driver was unable to complete due to hardware error. + @retval EFI_OUT_OF_RESOURCES Insufficient resources are available to fulfill the IO trap range request. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The input value is not within a valid range. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_IO_TRAP_DISPATCH_REGISTER)( + IN CONST EFI_MM_IO_TRAP_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN OUT EFI_MM_IO_TRAP_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child MMI source dispatch function with a parent MM driver. + + This service removes a previously installed child dispatch handler. This does not guarantee that the + system resources will be freed from the GCD. + + @param[in] This Pointer to the EFI_MM_IO_TRAP_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the child service to remove. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_IO_TRAP_DISPATCH_UNREGISTER)( + IN CONST EFI_MM_IO_TRAP_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Interface structure for the MM IO Trap Dispatch Protocol. +/// +/// This protocol provides a parent dispatch service for IO trap MMI sources. +/// +struct _EFI_MM_IO_TRAP_DISPATCH_PROTOCOL { + EFI_MM_IO_TRAP_DISPATCH_REGISTER Register; + EFI_MM_IO_TRAP_DISPATCH_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiMmIoTrapDispatchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPciRootBridgeIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPciRootBridgeIo.h new file mode 100644 index 0000000..fef33a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPciRootBridgeIo.h @@ -0,0 +1,37 @@ +/** @file + MM PCI Root Bridge IO protocol as defined in the PI 1.5 specification. + + This protocol provides PCI I/O and memory access within MM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_PCI_ROOT_BRIDGE_IO_H_ +#define _MM_PCI_ROOT_BRIDGE_IO_H_ + +#include + +#define EFI_MM_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + { \ + 0x8bc1714d, 0xffcb, 0x41c3, { 0x89, 0xdc, 0x6c, 0x74, 0xd0, 0x6d, 0x98, 0xea } \ + } + +/// +/// This protocol provides the same functionality as the PCI Root Bridge I/O Protocol defined in the +/// UEFI 2.1 Specifcation, section 13.2, except that the functions for Map() and Unmap() may return +/// EFI_UNSUPPORTED. +/// +typedef EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_MM_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +extern EFI_GUID gEfiMmPciRootBridgeIoProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPeriodicTimerDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPeriodicTimerDispatch.h new file mode 100644 index 0000000..4982021 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPeriodicTimerDispatch.h @@ -0,0 +1,170 @@ +/** @file + MM Periodic Timer Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + This protocol provides the parent dispatch service for the periodical timer MMI source generator. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.5. + +**/ + +#ifndef _MM_PERIODIC_TIMER_DISPATCH_H_ +#define _MM_PERIODIC_TIMER_DISPATCH_H_ + +#include + +#define EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL_GUID \ + { \ + 0x4cec368e, 0x8e8e, 0x4d71, {0x8b, 0xe1, 0x95, 0x8c, 0x45, 0xfc, 0x8a, 0x53 } \ + } + +/// +/// Example: A chipset supports periodic MMIs on every 64ms or 2 seconds. +/// A child wishes schedule a period MMI to fire on a period of 3 seconds, there +/// are several ways to approach the problem: +/// 1. The child may accept a 4 second periodic rate, in which case it registers with +/// Period = 40000 +/// MmiTickInterval = 20000 +/// The resulting MMI will occur every 2 seconds with the child called back on +/// every 2nd MMI. +/// NOTE: the same result would occur if the child set MmiTickInterval = 0. +/// 2. The child may choose the finer granularity MMI (64ms): +/// Period = 30000 +/// MmiTickInterval = 640 +/// The resulting MMI will occur every 64ms with the child called back on +/// every 47th MMI. +/// NOTE: the child driver should be aware that this will result in more +/// MMIs occuring during system runtime which can negatively impact system +/// performance. +/// +typedef struct { + /// + /// The minimum period of time in 100 nanosecond units that the child gets called. The + /// child will be called back after a time greater than the time Period. + /// + UINT64 Period; + /// + /// The period of time interval between MMIs. Children of this interface should use this + /// field when registering for periodic timer intervals when a finer granularity periodic + /// MMI is desired. + /// + UINT64 MmiTickInterval; +} EFI_MM_PERIODIC_TIMER_REGISTER_CONTEXT; + +/// +/// The DispatchFunction will be called with Context set to the same value as was passed into +/// Register() in RegisterContext and with CommBuffer pointing to an instance of +/// EFI_MM_PERIODIC_TIMER_CONTEXT and CommBufferSize pointing to its size. +/// +typedef struct { + /// + /// ElapsedTime is the actual time in 100 nanosecond units elapsed since last called, a + /// value of 0 indicates an unknown amount of time. + /// + UINT64 ElapsedTime; +} EFI_MM_PERIODIC_TIMER_CONTEXT; + +typedef struct _EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL; + +/** + Register a child MMI source dispatch function for MM periodic timer. + + This service registers a function (DispatchFunction) which will be called when at least the + amount of time specified by RegisterContext has elapsed. On return, DispatchHandle + contains a unique handle which may be used later to unregister the function using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer pointing to an instance of + EFI_MM_PERIODIC_TIMER_CONTEXT and CommBufferSize pointing to its size. + + @param[in] This Pointer to the EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when at least the specified amount + of time has elapsed. + @param[in] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the period at which the dispatch function + should be invoked. + @param[out] DispatchHandle Handle generated by the dispatcher to track the function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The period input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_PERIODIC_TIMER_REGISTER)( + IN CONST EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN CONST EFI_MM_PERIODIC_TIMER_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters a periodic timer service. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called when the time has elapsed. + + @param[in] This Pointer to the EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS The service has been successfully removed. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_PERIODIC_TIMER_UNREGISTER)( + IN CONST EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/** + Returns the next MMI tick period supported by the chipset. + + The order returned is from longest to shortest interval period. + + @param[in] This Pointer to the EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL instance. + @param[in,out] MmiTickInterval Pointer to pointer of next shorter MMI interval + period supported by the child. This parameter works as a get-first, + get-next field.The first time this function is called, *MmiTickInterval + should be set to NULL to get the longest MMI interval.The returned + *MmiTickInterval should be passed in on subsequent calls to get the + next shorter interval period until *MmiTickInterval = NULL. + + @retval EFI_SUCCESS The service returned successfully. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_PERIODIC_TIMER_INTERVAL)( + IN CONST EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This, + IN OUT UINT64 **MmiTickInterval + ); + +/// +/// Interface structure for the MM Periodic Timer Dispatch Protocol +/// +/// This protocol provides the parent dispatch service for the periodical timer MMI source generator. +/// +struct _EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL { + EFI_MM_PERIODIC_TIMER_REGISTER Register; + EFI_MM_PERIODIC_TIMER_UNREGISTER UnRegister; + EFI_MM_PERIODIC_TIMER_INTERVAL GetNextShorterInterval; +}; + +extern EFI_GUID gEfiMmPeriodicTimerDispatchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPowerButtonDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPowerButtonDispatch.h new file mode 100644 index 0000000..ecadd90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmPowerButtonDispatch.h @@ -0,0 +1,117 @@ +/** @file + MM Power Button Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + This protocol provides the parent dispatch service for the power button MMI source generator. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.5. + +**/ + +#ifndef _MM_POWER_BUTTON_DISPATCH_H_ +#define _MM_POWER_BUTTON_DISPATCH_H_ + +#include + +#define EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL_GUID \ + { \ + 0x1b1183fa, 0x1823, 0x46a7, {0x88, 0x72, 0x9c, 0x57, 0x87, 0x55, 0x40, 0x9d } \ + } + +/// +/// Power Button phases. +/// +typedef enum { + EfiPowerButtonEntry, + EfiPowerButtonExit, + EfiPowerButtonMax +} EFI_POWER_BUTTON_PHASE; + +/// +/// The dispatch function's context. +/// +typedef struct { + /// + /// Designates whether this handler should be invoked upon entry or exit. + /// + EFI_POWER_BUTTON_PHASE Phase; +} EFI_MM_POWER_BUTTON_REGISTER_CONTEXT; + +typedef struct _EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL; + +/** + Provides the parent dispatch service for a power button event. + + This service registers a function (DispatchFunction) which will be called when an MMI is + generated because the power button was pressed or released, as specified by RegisterContext. + On return, DispatchHandle contains a unique handle which may be used later to unregister the + function using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer and CommBufferSize set to NULL. + + @param[in] This Pointer to the EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when power button is pressed or released. + @param[in] RegisterContext Pointer to the dispatch function's context. The caller fills in this context + before calling the Register() function to indicate to the Register() function + the power button MMI phase for which the dispatch function should be invoked. + @param[out] DispatchHandle Handle generated by the dispatcher to track the function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The power button input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_POWER_BUTTON_REGISTER)( + IN CONST EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN EFI_MM_POWER_BUTTON_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters a power-button service. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called when the standby button is pressed or released. + + @param[in] This Pointer to the EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS The service has been successfully removed. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_POWER_BUTTON_UNREGISTER)( + IN CONST EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Interface structure for the MM Power Button Dispatch Protocol. +/// +/// This protocol provides the parent dispatch service for the power button MMI source generator. +/// +struct _EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL { + EFI_MM_POWER_BUTTON_REGISTER Register; + EFI_MM_POWER_BUTTON_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiMmPowerButtonDispatchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReadyToLock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReadyToLock.h new file mode 100644 index 0000000..ce5c559 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReadyToLock.h @@ -0,0 +1,32 @@ +/** @file + MM Ready To Lock protocol introduced in the PI 1.5 specification. + + This protocol is a mandatory protocol published by the MM Foundation + code when the system is preparing to lock certain resources and interfaces + in anticipation of the invocation of 3rd party extensible modules. + This protocol is an MM counterpart of the DXE MM Ready to Lock Protocol. + This protocol prorogates resource locking notification into MM environment. + This protocol is installed after installation of the MM End of DXE Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_READY_TO_LOCK_H_ +#define _MM_READY_TO_LOCK_H_ + +#define EFI_MM_READY_TO_LOCK_PROTOCOL_GUID \ + { \ + 0x47b7fa8c, 0xf4bd, 0x4af6, { 0x82, 0x00, 0x33, 0x30, 0x86, 0xf0, 0xd2, 0xc8 } \ + } + +extern EFI_GUID gEfiMmReadyToLockProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReportStatusCodeHandler.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReportStatusCodeHandler.h new file mode 100644 index 0000000..fe70bb7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmReportStatusCodeHandler.h @@ -0,0 +1,84 @@ +/** @file + This protocol provides registering and unregistering services to status code consumers while in DXE MM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.1. + +**/ + +#ifndef __MM_REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ +#define __MM_REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ + +#define EFI_MM_RSC_HANDLER_PROTOCOL_GUID \ + { \ + 0x2ff29fa7, 0x5e80, 0x4ed9, {0xb3, 0x80, 0x1, 0x7d, 0x3c, 0x55, 0x4f, 0xf4} \ + } + +typedef +EFI_STATUS +(EFIAPI *EFI_MM_RSC_HANDLER_CALLBACK)( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data +); + +/** + Register the callback function for ReportStatusCode() notification. + + When this function is called the function pointer is added to an internal list and any future calls to + ReportStatusCode() will be forwarded to the Callback function. + + @param[in] Callback A pointer to a function of type EFI_MM_RSC_HANDLER_CALLBACK that is + called when a call to ReportStatusCode() occurs. + + @retval EFI_SUCCESS Function was successfully registered. + @retval EFI_INVALID_PARAMETER The callback function was NULL. + @retval EFI_OUT_OF_RESOURCES The internal buffer ran out of space. No more functions can be + registered. + @retval EFI_ALREADY_STARTED The function was already registered. It can't be registered again. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_RSC_HANDLER_REGISTER)( + IN EFI_MM_RSC_HANDLER_CALLBACK Callback +); + +/** + Remove a previously registered callback function from the notification list. + + A callback function must be unregistered before it is deallocated. It is important that any registered + callbacks that are not runtime complaint be unregistered when ExitBootServices() is called. + + @param[in] Callback A pointer to a function of type EFI_MM_RSC_HANDLER_CALLBACK that is to be + unregistered. + + @retval EFI_SUCCESS The function was successfully unregistered. + @retval EFI_INVALID_PARAMETER The callback function was NULL. + @retval EFI_NOT_FOUND The callback function was not found to be unregistered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_RSC_HANDLER_UNREGISTER)( + IN EFI_MM_RSC_HANDLER_CALLBACK Callback +); + +typedef struct _EFI_MM_RSC_HANDLER_PROTOCOL { + EFI_MM_RSC_HANDLER_REGISTER Register; + EFI_MM_RSC_HANDLER_UNREGISTER Unregister; +} EFI_MM_RSC_HANDLER_PROTOCOL; + +extern EFI_GUID gEfiMmRscHandlerProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStandbyButtonDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStandbyButtonDispatch.h new file mode 100644 index 0000000..c0a2ff9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStandbyButtonDispatch.h @@ -0,0 +1,119 @@ +/** @file + MM Standby Button Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + This protocol provides the parent dispatch service for the standby button MMI source generator. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.5. + +**/ + +#ifndef _MM_STANDBY_BUTTON_DISPATCH_H_ +#define _MM_STANDBY_BUTTON_DISPATCH_H_ + +#include + +#define EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL_GUID \ + { \ + 0x7300c4a1, 0x43f2, 0x4017, {0xa5, 0x1b, 0xc8, 0x1a, 0x7f, 0x40, 0x58, 0x5b } \ + } + +/// +/// Standby Button phases +/// +typedef enum { + EfiStandbyButtonEntry, + EfiStandbyButtonExit, + EfiStandbyButtonMax +} EFI_STANDBY_BUTTON_PHASE; + +/// +/// The dispatch function's context. +/// +typedef struct { + /// + /// Describes whether the child handler should be invoked upon the entry to the button + /// activation or upon exit. + /// + EFI_STANDBY_BUTTON_PHASE Phase; +} EFI_MM_STANDBY_BUTTON_REGISTER_CONTEXT; + +typedef struct _EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL; + +/** + Provides the parent dispatch service for a standby button event. + + This service registers a function (DispatchFunction) which will be called when an MMI is + generated because the standby button was pressed or released, as specified by + RegisterContext. On return, DispatchHandle contains a unique handle which may be used + later to unregister the function using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer and CommBufferSize set to NULL. + + @param[in] This Pointer to the EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the standby button is pressed or released. + @param[in] RegisterContext Pointer to the dispatch function's context. The caller fills in this context + before calling the register function to indicate to the register function the + standby button MMI source for which the dispatch function should be invoked. + @param[out] DispatchHandle Handle generated by the dispatcher to track the function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The standby button input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_STANDBY_BUTTON_REGISTER)( + IN CONST EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN EFI_MM_STANDBY_BUTTON_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters a child MMI source dispatch function with a parent MM driver. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called when the standby button is pressed or released. + + @param[in] This Pointer to the EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS The service has been successfully removed. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_STANDBY_BUTTON_UNREGISTER)( + IN CONST EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Interface structure for the MM Standby Button Dispatch Protocol. +/// +/// This protocol provides the parent dispatch service for the standby +/// button MMI source generator. +/// +struct _EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL { + EFI_MM_STANDBY_BUTTON_REGISTER Register; + EFI_MM_STANDBY_BUTTON_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiMmStandbyButtonDispatchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStatusCode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStatusCode.h new file mode 100644 index 0000000..33eda7a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmStatusCode.h @@ -0,0 +1,65 @@ +/** @file + EFI MM Status Code Protocol as defined in the PI 1.5 specification. + + This protocol provides the basic status code services while in MM. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_STATUS_CODE_H__ +#define _MM_STATUS_CODE_H__ + + +#define EFI_MM_STATUS_CODE_PROTOCOL_GUID \ + { \ + 0x6afd2b77, 0x98c1, 0x4acd, {0xa6, 0xf9, 0x8a, 0x94, 0x39, 0xde, 0xf, 0xb1} \ + } + +typedef struct _EFI_MM_STATUS_CODE_PROTOCOL EFI_MM_STATUS_CODE_PROTOCOL; + +/** + Service to emit the status code in MM. + + The EFI_MM_STATUS_CODE_PROTOCOL.ReportStatusCode() function enables a driver + to emit a status code while in MM. The reason that there is a separate protocol definition from the + DXE variant of this service is that the publisher of this protocol will provide a service that is + capability of coexisting with a foreground operational environment, such as an operating system + after the termination of boot services. + + @param[in] This Points to this instance of the EFI_MM_STATUS_CODE_PROTOCOL. + @param[in] CodeType DIndicates the type of status code being reported. + @param[in] Value Describes the current status of a hardware or software entity. + @param[in] Instance The enumeration of a hardware or software entity within the system. + @param[in] CallerId This optional parameter may be used to identify the caller. + @param[in] Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER The function should not be completed due to a device error. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_REPORT_STATUS_CODE)( + IN CONST EFI_MM_STATUS_CODE_PROTOCOL *This, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN CONST EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +struct _EFI_MM_STATUS_CODE_PROTOCOL { + EFI_MM_REPORT_STATUS_CODE ReportStatusCode; +}; + +extern EFI_GUID gEfiMmStatusCodeProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSwDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSwDispatch.h new file mode 100644 index 0000000..46c941d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSwDispatch.h @@ -0,0 +1,136 @@ +/** @file + MM Software Dispatch Protocol introduced from PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + This protocol provides the parent dispatch service for a given MMI source generator. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_SW_DISPATCH_H_ +#define _MM_SW_DISPATCH_H_ + +#include + +#define EFI_MM_SW_DISPATCH_PROTOCOL_GUID \ + { \ + 0x18a3c6dc, 0x5eea, 0x48c8, {0xa1, 0xc1, 0xb5, 0x33, 0x89, 0xf9, 0x89, 0x99 } \ + } + +/// +/// A particular chipset may not support all possible software MMI input values. +/// For example, the ICH supports only values 00h to 0FFh. The parent only allows a single +/// child registration for each SwMmiInputValue. +/// +typedef struct { + UINTN SwMmiInputValue; +} EFI_MM_SW_REGISTER_CONTEXT; + +/// +/// The DispatchFunction will be called with Context set to the same value as was passed into +/// this function in RegisterContext and with CommBuffer (and CommBufferSize) pointing +/// to an instance of EFI_MM_SW_CONTEXT indicating the index of the CPU which generated the +/// software MMI. +/// +typedef struct { + /// + /// The 0-based index of the CPU which generated the software MMI. + /// + UINTN SwMmiCpuIndex; + /// + /// This value corresponds directly to the CommandPort parameter used in the call to Trigger(). + /// + UINT8 CommandPort; + /// + /// This value corresponds directly to the DataPort parameter used in the call to Trigger(). + /// + UINT8 DataPort; +} EFI_MM_SW_CONTEXT; + +typedef struct _EFI_MM_SW_DISPATCH_PROTOCOL EFI_MM_SW_DISPATCH_PROTOCOL; + +/** + Register a child MMI source dispatch function for the specified software MMI. + + This service registers a function (DispatchFunction) which will be called when the software + MMI source specified by RegisterContext->SwMmiCpuIndex is detected. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + + @param[in] This Pointer to the EFI_MM_SW_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified software + MMI is generated. + @param[in, out] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Software MMI input value the + dispatch function should be invoked for. + @param[out] DispatchHandle Handle generated by the dispatcher to track the + function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_DEVICE_ERROR The SW driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW MMI input value + is not within a valid range or is already in use. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this + child. + @retval EFI_OUT_OF_RESOURCES A unique software MMI value could not be assigned + for this dispatch. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_SW_REGISTER)( + IN CONST EFI_MM_SW_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN OUT EFI_MM_SW_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child MMI source dispatch function for the specified software MMI. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to a software MMI. + + @param[in] This Pointer to the EFI_MM_SW_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_SW_UNREGISTER)( + IN CONST EFI_MM_SW_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle +); + +/// +/// Interface structure for the MM Software MMI Dispatch Protocol. +/// +/// The EFI_MM_SW_DISPATCH_PROTOCOL provides the ability to install child handlers for the +/// given software. These handlers will respond to software interrupts, and the maximum software +/// interrupt in the EFI_MM_SW_REGISTER_CONTEXT is denoted by MaximumSwiValue. +/// +struct _EFI_MM_SW_DISPATCH_PROTOCOL { + EFI_MM_SW_REGISTER Register; + EFI_MM_SW_UNREGISTER UnRegister; + /// + /// A read-only field that describes the maximum value that can be used in the + /// EFI_MM_SW_DISPATCH_PROTOCOL.Register() service. + /// + UINTN MaximumSwiValue; +}; + +extern EFI_GUID gEfiMmSwDispatchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSxDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSxDispatch.h new file mode 100644 index 0000000..99b757d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmSxDispatch.h @@ -0,0 +1,135 @@ +/** @file + MM Sx Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + Provides the parent dispatch service for a given Sx-state source generator. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _MM_SX_DISPATCH_H_ +#define _MM_SX_DISPATCH_H_ + +#include + +#define EFI_MM_SX_DISPATCH_PROTOCOL_GUID \ + { \ + 0x456d2859, 0xa84b, 0x4e47, {0xa2, 0xee, 0x32, 0x76, 0xd8, 0x86, 0x99, 0x7d } \ + } + +/// +/// Sleep states S0-S5 +/// +typedef enum { + SxS0, + SxS1, + SxS2, + SxS3, + SxS4, + SxS5, + EfiMaximumSleepType +} EFI_SLEEP_TYPE; + +/// +/// Sleep state phase: entry or exit +/// +typedef enum { + SxEntry, + SxExit, + EfiMaximumPhase +} EFI_SLEEP_PHASE; + +/// +/// The dispatch function's context +/// +typedef struct { + EFI_SLEEP_TYPE Type; + EFI_SLEEP_PHASE Phase; +} EFI_MM_SX_REGISTER_CONTEXT; + +typedef struct _EFI_MM_SX_DISPATCH_PROTOCOL EFI_MM_SX_DISPATCH_PROTOCOL; + +/** + Provides the parent dispatch service for a given Sx source generator. + + This service registers a function (DispatchFunction) which will be called when the sleep state + event specified by RegisterContext is detected. On return, DispatchHandle contains a + unique handle which may be used later to unregister the function using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer and CommBufferSize set to + NULL and 0 respectively. + + @param[in] This Pointer to the EFI_MM_SX_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified sleep state event occurs. + @param[in] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Sx state type and phase the caller + wishes to be called back on. For this intertace, + the Sx driver will call the registered handlers for + all Sx type and phases, so the Sx state handler(s) + must check the Type and Phase field of the Dispatch + context and act accordingly. + @param[out] DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state MM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_UNSUPPORTED The Sx driver or hardware does not support that + Sx Type/Phase. + @retval EFI_DEVICE_ERROR The Sx driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. Type & Phase are not + within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this + child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_SX_REGISTER)( + IN CONST EFI_MM_SX_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN CONST EFI_MM_SX_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters an Sx-state service. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to sleep event. + + @param[in] This Pointer to the EFI_MM_SX_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS The service has been successfully removed. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_SX_UNREGISTER)( + IN CONST EFI_MM_SX_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Interface structure for the MM Sx Dispatch Protocol +/// +/// The EFI_MM_SX_DISPATCH_PROTOCOL provides the ability to install child handlers to +/// respond to sleep state related events. +/// +struct _EFI_MM_SX_DISPATCH_PROTOCOL { + EFI_MM_SX_REGISTER Register; + EFI_MM_SX_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiMmSxDispatchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmUsbDispatch.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmUsbDispatch.h new file mode 100644 index 0000000..cf6c22a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MmUsbDispatch.h @@ -0,0 +1,130 @@ +/** @file + MM USB Dispatch Protocol as defined in PI 1.5 Specification + Volume 4 Management Mode Core Interface. + + Provides the parent dispatch service for the USB MMI source generator. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.5. + +**/ + +#ifndef _MM_USB_DISPATCH_H_ +#define _MM_USB_DISPATCH_H_ + +#include + +#define EFI_MM_USB_DISPATCH_PROTOCOL_GUID \ + { \ + 0xee9b8d90, 0xc5a6, 0x40a2, {0xbd, 0xe2, 0x52, 0x55, 0x8d, 0x33, 0xcc, 0xa1 } \ + } + +/// +/// USB MMI event types +/// +typedef enum { + UsbLegacy, + UsbWake +} EFI_USB_MMI_TYPE; + +/// +/// The dispatch function's context. +/// +typedef struct { + /// + /// Describes whether this child handler will be invoked in response to a USB legacy + /// emulation event, such as port-trap on the PS/2* keyboard control registers, or to a + /// USB wake event, such as resumption from a sleep state. + /// + EFI_USB_MMI_TYPE Type; + /// + /// The device path is part of the context structure and describes the location of the + /// particular USB host controller in the system for which this register event will occur. + /// This location is important because of the possible integration of several USB host + /// controllers in a system. + /// + EFI_DEVICE_PATH_PROTOCOL *Device; +} EFI_MM_USB_REGISTER_CONTEXT; + +typedef struct _EFI_MM_USB_DISPATCH_PROTOCOL EFI_MM_USB_DISPATCH_PROTOCOL; + +/** + Provides the parent dispatch service for the USB MMI source generator. + + This service registers a function (DispatchFunction) which will be called when the USB- + related MMI specified by RegisterContext has occurred. On return, DispatchHandle + contains a unique handle which may be used later to unregister the function using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer containing NULL and + CommBufferSize containing zero. + + @param[in] This Pointer to the EFI_MM_USB_DISPATCH_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when a USB-related MMI occurs. + @param[in] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the USB MMI types for which the dispatch + function should be invoked. + @param[out] DispatchHandle Handle generated by the dispatcher to track the function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the MMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the MMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The USB MMI type + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or MM) to manage this child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_USB_REGISTER)( + IN CONST EFI_MM_USB_DISPATCH_PROTOCOL *This, + IN EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, + IN CONST EFI_MM_USB_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters a USB service. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called when the USB event occurs. + + @param[in] This Pointer to the EFI_MM_USB_DISPATCH_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the MMI source has been disabled + if there are no other registered child dispatch + functions for this MMI source. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MM_USB_UNREGISTER)( + IN CONST EFI_MM_USB_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/// +/// Interface structure for the MM USB MMI Dispatch Protocol +/// +/// This protocol provides the parent dispatch service for the USB MMI source generator. +/// +struct _EFI_MM_USB_DISPATCH_PROTOCOL { + EFI_MM_USB_REGISTER Register; + EFI_MM_USB_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiMmUsbDispatchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MonotonicCounter.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MonotonicCounter.h new file mode 100644 index 0000000..29bda58 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MonotonicCounter.h @@ -0,0 +1,28 @@ +/** @file + Monotonic Counter Architectural Protocol as defined in PI SPEC VOLUME 2 DXE + + This code provides the services required to access the system's monotonic counter + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_MONTONIC_COUNTER_H__ +#define __ARCH_PROTOCOL_MONTONIC_COUNTER_H__ + +/// +/// Global ID for the Monotonic Counter Architectural Protocol. +/// +#define EFI_MONOTONIC_COUNTER_ARCH_PROTOCOL_GUID \ + {0x1da97072, 0xbddc, 0x4b30, {0x99, 0xf1, 0x72, 0xa0, 0xb5, 0x6f, 0xff, 0x2a} } + +extern EFI_GUID gEfiMonotonicCounterArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MpService.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MpService.h new file mode 100644 index 0000000..ac1d12c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/MpService.h @@ -0,0 +1,632 @@ +/** @file + When installed, the MP Services Protocol produces a collection of services + that are needed for MP management. + + The MP Services Protocol provides a generalized way of performing following tasks: + - Retrieving information of multi-processor environment and MP-related status of + specific processors. + - Dispatching user-provided function to APs. + - Maintain MP-related processor status. + + The MP Services Protocol must be produced on any system with more than one logical + processor. + + The Protocol is available only during boot time. + + MP Services Protocol is hardware-independent. Most of the logic of this protocol + is architecturally neutral. It abstracts the multi-processor environment and + status of processors, and provides interfaces to retrieve information, maintain, + and dispatch. + + MP Services Protocol may be consumed by ACPI module. The ACPI module may use this + protocol to retrieve data that are needed for an MP platform and report them to OS. + MP Services Protocol may also be used to program and configure processors, such + as MTRR synchronization for memory space attributes setting in DXE Services. + MP Services Protocol may be used by non-CPU DXE drivers to speed up platform boot + by taking advantage of the processing capabilities of the APs, for example, using + APs to help test system memory in parallel with other device initialization. + Diagnostics applications may also use this protocol for multi-processor. + +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in the UEFI Platform Initialization Specification 1.2, + Volume 2:Driver Execution Environment Core Interface. + +**/ + +#ifndef _MP_SERVICE_PROTOCOL_H_ +#define _MP_SERVICE_PROTOCOL_H_ + +/// +/// Global ID for the EFI_MP_SERVICES_PROTOCOL. +/// +#define EFI_MP_SERVICES_PROTOCOL_GUID \ + { \ + 0x3fdda605, 0xa76e, 0x4f46, {0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08} \ + } + +/// +/// Forward declaration for the EFI_MP_SERVICES_PROTOCOL. +/// +typedef struct _EFI_MP_SERVICES_PROTOCOL EFI_MP_SERVICES_PROTOCOL; + +/// +/// Terminator for a list of failed CPUs returned by StartAllAPs(). +/// +#define END_OF_CPU_LIST 0xffffffff + +/// +/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and +/// indicates whether the processor is playing the role of BSP. If the bit is 1, +/// then the processor is BSP. Otherwise, it is AP. +/// +#define PROCESSOR_AS_BSP_BIT 0x00000001 + +/// +/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and +/// indicates whether the processor is enabled. If the bit is 1, then the +/// processor is enabled. Otherwise, it is disabled. +/// +#define PROCESSOR_ENABLED_BIT 0x00000002 + +/// +/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and +/// indicates whether the processor is healthy. If the bit is 1, then the +/// processor is healthy. Otherwise, some fault has been detected for the processor. +/// +#define PROCESSOR_HEALTH_STATUS_BIT 0x00000004 + +/// +/// Structure that describes the pyhiscal location of a logical CPU. +/// +typedef struct { + /// + /// Zero-based physical package number that identifies the cartridge of the processor. + /// + UINT32 Package; + /// + /// Zero-based physical core number within package of the processor. + /// + UINT32 Core; + /// + /// Zero-based logical thread number within core of the processor. + /// + UINT32 Thread; +} EFI_CPU_PHYSICAL_LOCATION; + +/// +/// Structure that describes information about a logical CPU. +/// +typedef struct { + /// + /// The unique processor ID determined by system hardware. For IA32 and X64, + /// the processor ID is the same as the Local APIC ID. Only the lower 8 bits + /// are used, and higher bits are reserved. For IPF, the lower 16 bits contains + /// id/eid, and higher bits are reserved. + /// + UINT64 ProcessorId; + /// + /// Flags indicating if the processor is BSP or AP, if the processor is enabled + /// or disabled, and if the processor is healthy. Bits 3..31 are reserved and + /// must be 0. + /// + ///
+  /// BSP  ENABLED  HEALTH  Description
+  /// ===  =======  ======  ===================================================
+  ///  0      0       0     Unhealthy Disabled AP.
+  ///  0      0       1     Healthy Disabled AP.
+  ///  0      1       0     Unhealthy Enabled AP.
+  ///  0      1       1     Healthy Enabled AP.
+  ///  1      0       0     Invalid. The BSP can never be in the disabled state.
+  ///  1      0       1     Invalid. The BSP can never be in the disabled state.
+  ///  1      1       0     Unhealthy Enabled BSP.
+  ///  1      1       1     Healthy Enabled BSP.
+  /// 
+ /// + UINT32 StatusFlag; + /// + /// The physical location of the processor, including the physical package number + /// that identifies the cartridge, the physical core number within package, and + /// logical thread number within core. + /// + EFI_CPU_PHYSICAL_LOCATION Location; +} EFI_PROCESSOR_INFORMATION; + +/** + This service retrieves the number of logical processor in the platform + and the number of those logical processors that are enabled on this boot. + This service may only be called from the BSP. + + This function is used to retrieve the following information: + - The number of logical processors that are present in the system. + - The number of enabled logical processors in the system at the instant + this call is made. + + Because MP Service Protocol provides services to enable and disable processors + dynamically, the number of enabled logical processors may vary during the + course of a boot session. + + If this service is called from an AP, then EFI_DEVICE_ERROR is returned. + If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then + EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors + is returned in NumberOfProcessors, the number of currently enabled processor + is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[out] NumberOfProcessors Pointer to the total number of logical + processors in the system, including the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical + processors that exist in system, including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and enabled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL. + @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS)( + IN EFI_MP_SERVICES_PROTOCOL *This, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ); + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + This service retrieves detailed MP-related information about any processor + on the platform. Note the following: + - The processor information may change during the course of a boot session. + - The information presented here is entirely MP related. + + Information regarding the number of caches and their sizes, frequency of operation, + slot numbers is all considered platform-related information and is not provided + by this service. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where information for + the requested processor is deposited. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist in the platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_GET_PROCESSOR_INFO)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ); + +/** + This service executes a caller provided function on all enabled APs. APs can + run either simultaneously or one at a time in sequence. This service supports + both blocking and non-blocking requests. The non-blocking requests use EFI + events so the BSP can detect when the APs have finished. This service may only + be called from the BSP. + + This function is used to dispatch all the enabled APs to the function specified + by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned + immediately and Procedure is not started on any AP. + + If SingleThread is TRUE, all the enabled APs execute the function specified by + Procedure one by one, in ascending order of processor handle number. Otherwise, + all the enabled APs execute the function specified by Procedure simultaneously. + + If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all + APs finish or TimeoutInMicroSecs expires. Otherwise, execution is in non-blocking + mode, and the BSP returns from this service without waiting for APs. If a + non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT + is signaled, then EFI_UNSUPPORTED must be returned. + + If the timeout specified by TimeoutInMicroseconds expires before all APs return + from Procedure, then Procedure on the failed APs is terminated. All enabled APs + are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() + and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its + content points to the list of processor handle numbers in which Procedure was + terminated. + + Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() + to make sure that the nature of the code that is executed on the BSP and the + dispatched APs is well controlled. The MP Services Protocol does not guarantee + that the Procedure function is MP-safe. Hence, the tasks that can be run in + parallel are limited to certain independent tasks and well-controlled exclusive + code. EFI services and protocols may not be called by APs unless otherwise + specified. + + In blocking execution mode, BSP waits until all APs finish or + TimeoutInMicroSeconds expires. + + In non-blocking execution mode, BSP is freed to return to the caller and then + proceed to the next task without having to wait for APs. The following + sequence needs to occur in a non-blocking execution mode: + + -# The caller that intends to use this MP Services Protocol in non-blocking + mode creates WaitEvent by calling the EFI CreateEvent() service. The caller + invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent + is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests + the function specified by Procedure to be started on all the enabled APs, + and releases the BSP to continue with other tasks. + -# The caller can use the CheckEvent() and WaitForEvent() services to check + the state of the WaitEvent created in step 1. + -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP + Service signals WaitEvent by calling the EFI SignalEvent() function. If + FailedCpuList is not NULL, its content is available when WaitEvent is + signaled. If all APs returned from Procedure prior to the timeout, then + FailedCpuList is set to NULL. If not all APs return from Procedure before + the timeout, then FailedCpuList is filled in with the list of the failed + APs. The buffer is allocated by MP Service Protocol using AllocatePool(). + It is the caller's responsibility to free the buffer with FreePool() service. + -# This invocation of SignalEvent() function informs the caller that invoked + EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed + the specified task or a timeout occurred. The contents of FailedCpuList + can be examined to determine which APs did not complete the specified task + prior to the timeout. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[in] Procedure A pointer to the function to be run on + enabled APs of the system. See type + EFI_AP_PROCEDURE. + @param[in] SingleThread If TRUE, then all the enabled APs execute + the function specified by Procedure one by + one, in ascending order of processor handle + number. If FALSE, then all the enabled APs + execute the function specified by Procedure + simultaneously. + @param[in] WaitEvent The event created by the caller with CreateEvent() + service. If it is NULL, then execute in + blocking mode. BSP waits until all APs finish + or TimeoutInMicroSeconds expires. If it's + not NULL, then execute in non-blocking mode. + BSP requests the function specified by + Procedure to be started on all the enabled + APs, and go on executing immediately. If + all return from Procedure, or TimeoutInMicroSeconds + expires, this event is signaled. The BSP + can use the CheckEvent() or WaitForEvent() + services to check the state of event. Type + EFI_EVENT is defined in CreateEvent() in + the Unified Extensible Firmware Interface + Specification. + @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for + APs to return from Procedure, either for + blocking or non-blocking mode. Zero means + infinity. If the timeout expires before + all APs return from Procedure, then Procedure + on the failed APs is terminated. All enabled + APs are available for next function assigned + by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() + or EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). + If the timeout expires in blocking mode, + BSP returns EFI_TIMEOUT. If the timeout + expires in non-blocking mode, WaitEvent + is signaled with SignalEvent(). + @param[in] ProcedureArgument The parameter passed into Procedure for + all APs. + @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise, + if all APs finish successfully, then its + content is set to NULL. If not all APs + finish before timeout expires, then its + content is set to address of the buffer + holding handle numbers of the failed APs. + The buffer is allocated by MP Service Protocol, + and it's the caller's responsibility to + free the buffer with FreePool() service. + In blocking mode, it is ready for consumption + when the call returns. In non-blocking mode, + it is ready when WaitEvent is signaled. The + list of failed CPU is terminated by + END_OF_CPU_LIST. + + @retval EFI_SUCCESS In blocking mode, all APs have finished before + the timeout expired. + @retval EFI_SUCCESS In non-blocking mode, function has been dispatched + to all enabled APs. + @retval EFI_UNSUPPORTED A non-blocking mode request was made after the + UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was + signaled. + @retval EFI_DEVICE_ERROR Caller processor is AP. + @retval EFI_NOT_STARTED No enabled APs exist in the system. + @retval EFI_NOT_READY Any enabled APs are busy. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before + all enabled APs have finished. + @retval EFI_INVALID_PARAMETER Procedure is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_STARTUP_ALL_APS)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN EFI_EVENT WaitEvent OPTIONAL, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument OPTIONAL, + OUT UINTN **FailedCpuList OPTIONAL + ); + +/** + This service lets the caller get one enabled AP to execute a caller-provided + function. The caller can request the BSP to either wait for the completion + of the AP or just proceed with the next task by using the EFI event mechanism. + See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking + execution support. This service may only be called from the BSP. + + This function is used to dispatch one enabled AP to the function specified by + Procedure passing in the argument specified by ProcedureArgument. If WaitEvent + is NULL, execution is in blocking mode. The BSP waits until the AP finishes or + TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode. + BSP proceeds to the next task without waiting for the AP. If a non-blocking mode + is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, + then EFI_UNSUPPORTED must be returned. + + If the timeout specified by TimeoutInMicroseconds expires before the AP returns + from Procedure, then execution of Procedure by the AP is terminated. The AP is + available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and + EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[in] Procedure A pointer to the function to be run on the + designated AP of the system. See type + EFI_AP_PROCEDURE. + @param[in] ProcessorNumber The handle number of the AP. The range is + from 0 to the total number of logical + processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + @param[in] WaitEvent The event created by the caller with CreateEvent() + service. If it is NULL, then execute in + blocking mode. BSP waits until this AP finish + or TimeoutInMicroSeconds expires. If it's + not NULL, then execute in non-blocking mode. + BSP requests the function specified by + Procedure to be started on this AP, + and go on executing immediately. If this AP + return from Procedure or TimeoutInMicroSeconds + expires, this event is signaled. The BSP + can use the CheckEvent() or WaitForEvent() + services to check the state of event. Type + EFI_EVENT is defined in CreateEvent() in + the Unified Extensible Firmware Interface + Specification. + @param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for + this AP to finish this Procedure, either for + blocking or non-blocking mode. Zero means + infinity. If the timeout expires before + this AP returns from Procedure, then Procedure + on the AP is terminated. The + AP is available for next function assigned + by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() + or EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). + If the timeout expires in blocking mode, + BSP returns EFI_TIMEOUT. If the timeout + expires in non-blocking mode, WaitEvent + is signaled with SignalEvent(). + @param[in] ProcedureArgument The parameter passed into Procedure on the + specified AP. + @param[out] Finished If NULL, this parameter is ignored. In + blocking mode, this parameter is ignored. + In non-blocking mode, if AP returns from + Procedure before the timeout expires, its + content is set to TRUE. Otherwise, the + value is set to FALSE. The caller can + determine if the AP returned from Procedure + by evaluating this value. + + @retval EFI_SUCCESS In blocking mode, specified AP finished before + the timeout expires. + @retval EFI_SUCCESS In non-blocking mode, the function has been + dispatched to specified AP. + @retval EFI_UNSUPPORTED A non-blocking mode request was made after the + UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was + signaled. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before + the specified AP has finished. + @retval EFI_NOT_READY The specified AP is busy. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. + @retval EFI_INVALID_PARAMETER Procedure is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_STARTUP_THIS_AP)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN EFI_EVENT WaitEvent OPTIONAL, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL, + OUT BOOLEAN *Finished OPTIONAL + ); + +/** + This service switches the requested AP to be the BSP from that point onward. + This service changes the BSP for all purposes. This call can only be performed + by the current BSP. + + This service switches the requested AP to be the BSP from that point onward. + This service changes the BSP for all purposes. The new BSP can take over the + execution of the old BSP and continue seamlessly from where the old one left + off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT + is signaled. + + If the BSP cannot be switched prior to the return from this service, then + EFI_UNSUPPORTED must be returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. + @param[in] ProcessorNumber The handle number of AP that is to become the new + BSP. The range is from 0 to the total number of + logical processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an + enabled AP. Otherwise, it will be disabled. + + @retval EFI_SUCCESS BSP successfully switched. + @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to + this service returning. + @retval EFI_UNSUPPORTED Switching the BSP is not supported. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or + a disabled AP. + @retval EFI_NOT_READY The specified AP is busy. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_SWITCH_BSP)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ); + +/** + This service lets the caller enable or disable an AP from this point onward. + This service may only be called from the BSP. + + This service allows the caller enable or disable an AP from this point onward. + The caller can optionally specify the health status of the AP by Health. If + an AP is being disabled, then the state of the disabled AP is implementation + dependent. If an AP is enabled, then the implementation must guarantee that a + complete initialization sequence is performed on the AP, so the AP is in a state + that is compatible with an MP operating system. This service may not be supported + after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled. + + If the enable or disable AP operation cannot be completed prior to the return + from this service, then EFI_UNSUPPORTED must be returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. + @param[in] ProcessorNumber The handle number of AP. + The range is from 0 to the total number of + logical processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + @param[in] EnableAP Specifies the new state for the processor for + enabled, FALSE for disabled. + @param[in] HealthFlag If not NULL, a pointer to a value that specifies + the new health status of the AP. This flag + corresponds to StatusFlag defined in + EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only + the PROCESSOR_HEALTH_STATUS_BIT is used. All other + bits are ignored. If it is NULL, this parameter + is ignored. + + @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. + @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed + prior to this service returning. + @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber + does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_ENABLEDISABLEAP)( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag OPTIONAL + ); + +/** + This return the handle number for the calling processor. This service may be + called from the BSP and APs. + + This service returns the processor handle number for the calling processor. + The returned value is in the range from 0 to the total number of logical + processors minus 1. The total number of logical processors can be retrieved + with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be + called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER + is returned. Otherwise, the current processors handle number is returned in + ProcessorNumber, and EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. + @param[in] ProcessorNumber Pointer to the handle number of AP. + The range is from 0 to the total number of + logical processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + + @retval EFI_SUCCESS The current processor handle number was returned + in ProcessorNumber. + @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MP_SERVICES_WHOAMI)( + IN EFI_MP_SERVICES_PROTOCOL *This, + OUT UINTN *ProcessorNumber + ); + +/// +/// When installed, the MP Services Protocol produces a collection of services +/// that are needed for MP management. +/// +/// Before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, the module +/// that produces this protocol is required to place all APs into an idle state +/// whenever the APs are disabled or the APs are not executing code as requested +/// through the StartupAllAPs() or StartupThisAP() services. The idle state of +/// an AP before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled is +/// implementation dependent. +/// +/// After the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, all the APs +/// must be placed in the OS compatible CPU state as defined by the UEFI +/// Specification. Implementations of this protocol may use the UEFI event +/// EFI_EVENT_GROUP_READY_TO_BOOT to force APs into the OS compatible state as +/// defined by the UEFI Specification. Modules that use this protocol must +/// guarantee that all non-blocking mode requests on all APs have been completed +/// before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled. Since the +/// order that event notification functions in the same event group are executed +/// is not deterministic, an event of type EFI_EVENT_GROUP_READY_TO_BOOT cannot +/// be used to guarantee that APs have completed their non-blocking mode requests. +/// +/// When the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, the StartAllAPs() +/// and StartupThisAp() services must no longer support non-blocking mode requests. +/// The support for SwitchBSP() and EnableDisableAP() may no longer be supported +/// after this event is signaled. Since UEFI Applications and UEFI OS Loaders +/// execute after the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, these +/// UEFI images must be aware that the functionality of this protocol may be reduced. +/// +struct _EFI_MP_SERVICES_PROTOCOL { + EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors; + EFI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo; + EFI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs; + EFI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP; + EFI_MP_SERVICES_SWITCH_BSP SwitchBSP; + EFI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP; + EFI_MP_SERVICES_WHOAMI WhoAmI; +}; + +extern EFI_GUID gEfiMpServiceProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp4.h new file mode 100644 index 0000000..af8227e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp4.h @@ -0,0 +1,593 @@ +/** @file + EFI Multicast Trivial File Transfer Protocol Definition + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.0 + +**/ + +#ifndef __EFI_MTFTP4_PROTOCOL_H__ +#define __EFI_MTFTP4_PROTOCOL_H__ + +#define EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x2FE800BE, 0x8F01, 0x4aa6, {0x94, 0x6B, 0xD7, 0x13, 0x88, 0xE1, 0x83, 0x3F } \ + } + +#define EFI_MTFTP4_PROTOCOL_GUID \ + { \ + 0x78247c57, 0x63db, 0x4708, {0x99, 0xc2, 0xa8, 0xb4, 0xa9, 0xa6, 0x1f, 0x6b } \ + } + +typedef struct _EFI_MTFTP4_PROTOCOL EFI_MTFTP4_PROTOCOL; +typedef struct _EFI_MTFTP4_TOKEN EFI_MTFTP4_TOKEN; + +// +//MTFTP4 packet opcode definition +// +#define EFI_MTFTP4_OPCODE_RRQ 1 +#define EFI_MTFTP4_OPCODE_WRQ 2 +#define EFI_MTFTP4_OPCODE_DATA 3 +#define EFI_MTFTP4_OPCODE_ACK 4 +#define EFI_MTFTP4_OPCODE_ERROR 5 +#define EFI_MTFTP4_OPCODE_OACK 6 +#define EFI_MTFTP4_OPCODE_DIR 7 +#define EFI_MTFTP4_OPCODE_DATA8 8 +#define EFI_MTFTP4_OPCODE_ACK8 9 + +// +// MTFTP4 error code definition +// +#define EFI_MTFTP4_ERRORCODE_NOT_DEFINED 0 +#define EFI_MTFTP4_ERRORCODE_FILE_NOT_FOUND 1 +#define EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION 2 +#define EFI_MTFTP4_ERRORCODE_DISK_FULL 3 +#define EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION 4 +#define EFI_MTFTP4_ERRORCODE_UNKNOWN_TRANSFER_ID 5 +#define EFI_MTFTP4_ERRORCODE_FILE_ALREADY_EXISTS 6 +#define EFI_MTFTP4_ERRORCODE_NO_SUCH_USER 7 +#define EFI_MTFTP4_ERRORCODE_REQUEST_DENIED 8 + +// +// MTFTP4 pacekt definitions +// +#pragma pack(1) + +typedef struct { + UINT16 OpCode; + UINT8 Filename[1]; +} EFI_MTFTP4_REQ_HEADER; + +typedef struct { + UINT16 OpCode; + UINT8 Data[1]; +} EFI_MTFTP4_OACK_HEADER; + +typedef struct { + UINT16 OpCode; + UINT16 Block; + UINT8 Data[1]; +} EFI_MTFTP4_DATA_HEADER; + +typedef struct { + UINT16 OpCode; + UINT16 Block[1]; +} EFI_MTFTP4_ACK_HEADER; + +typedef struct { + UINT16 OpCode; + UINT64 Block; + UINT8 Data[1]; +} EFI_MTFTP4_DATA8_HEADER; + +typedef struct { + UINT16 OpCode; + UINT64 Block[1]; +} EFI_MTFTP4_ACK8_HEADER; + +typedef struct { + UINT16 OpCode; + UINT16 ErrorCode; + UINT8 ErrorMessage[1]; +} EFI_MTFTP4_ERROR_HEADER; + +typedef union { + /// + /// Type of packets as defined by the MTFTPv4 packet opcodes. + /// + UINT16 OpCode; + /// + /// Read request packet header. + /// + EFI_MTFTP4_REQ_HEADER Rrq; + /// + /// Write request packet header. + /// + EFI_MTFTP4_REQ_HEADER Wrq; + /// + /// Option acknowledge packet header. + /// + EFI_MTFTP4_OACK_HEADER Oack; + /// + /// Data packet header. + /// + EFI_MTFTP4_DATA_HEADER Data; + /// + /// Acknowledgement packet header. + /// + EFI_MTFTP4_ACK_HEADER Ack; + /// + /// Data packet header with big block number. + /// + EFI_MTFTP4_DATA8_HEADER Data8; + /// + /// Acknowledgement header with big block num. + /// + EFI_MTFTP4_ACK8_HEADER Ack8; + /// + /// Error packet header. + /// + EFI_MTFTP4_ERROR_HEADER Error; +} EFI_MTFTP4_PACKET; + +#pragma pack() + +/// +/// MTFTP4 option definition. +/// +typedef struct { + UINT8 *OptionStr; + UINT8 *ValueStr; +} EFI_MTFTP4_OPTION; + + +typedef struct { + BOOLEAN UseDefaultSetting; + EFI_IPv4_ADDRESS StationIp; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 LocalPort; + EFI_IPv4_ADDRESS GatewayIp; + EFI_IPv4_ADDRESS ServerIp; + UINT16 InitialServerPort; + UINT16 TryCount; + UINT16 TimeoutValue; +} EFI_MTFTP4_CONFIG_DATA; + + +typedef struct { + EFI_MTFTP4_CONFIG_DATA ConfigData; + UINT8 SupportedOptionCount; + UINT8 **SupportedOptoins; + UINT8 UnsupportedOptionCount; + UINT8 **UnsupportedOptoins; +} EFI_MTFTP4_MODE_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS GatewayIp; + EFI_IPv4_ADDRESS ServerIp; + UINT16 ServerPort; + UINT16 TryCount; + UINT16 TimeoutValue; +} EFI_MTFTP4_OVERRIDE_DATA; + +// +// Protocol interfaces definition +// + +/** + A callback function that is provided by the caller to intercept + the EFI_MTFTP4_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the + EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept + EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to + EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The token that the caller provided in the + EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() + or ReadDirectory() function. + @param PacketLen Indicates the length of the packet. + @param Packet The pointer to an MTFTPv4 packet. + + @retval EFI_SUCCESS The operation was successful. + @retval Others Aborts the transfer process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_CHECK_PACKET)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN UINT16 PacketLen, + IN EFI_MTFTP4_PACKET *Paket + ); + +/** + Timeout callback function. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The token that is provided in the + EFI_MTFTP4_PROTOCOL.ReadFile() or + EFI_MTFTP4_PROTOCOL.WriteFile() or + EFI_MTFTP4_PROTOCOL.ReadDirectory() functions + by the caller. + + @retval EFI_SUCCESS The operation was successful. + @retval Others Aborts download process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_TIMEOUT_CALLBACK)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ); + +/** + A callback function that the caller provides to feed data to the + EFI_MTFTP4_PROTOCOL.WriteFile() function. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The token provided in the + EFI_MTFTP4_PROTOCOL.WriteFile() by the caller. + @param Length Indicates the length of the raw data wanted on input, and the + length the data available on output. + @param Buffer The pointer to the buffer where the data is stored. + + @retval EFI_SUCCESS The operation was successful. + @retval Others Aborts session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_PACKET_NEEDED)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN OUT UINT16 *Length, + OUT VOID **Buffer + ); + + +/** + Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param ModeData The pointer to storage for the EFI MTFTPv4 Protocol driver mode data. + + @retval EFI_SUCCESS The configuration data was successfully returned. + @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated. + @retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_GET_MODE_DATA)( + IN EFI_MTFTP4_PROTOCOL *This, + OUT EFI_MTFTP4_MODE_DATA *ModeData + ); + + +/** + Initializes, changes, or resets the default operational setting for this + EFI MTFTPv4 Protocol driver instance. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param MtftpConfigData The pointer to the configuration data structure. + + @retval EFI_SUCCESS The EFI MTFTPv4 Protocol driver was configured successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED The EFI configuration could not be changed at this time because + there is one MTFTP background operation in progress. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) has not finished yet. + @retval EFI_UNSUPPORTED A configuration protocol (DHCP, BOOTP, RARP, etc.) could not + be located when clients choose to use the default address + settings. + @retval EFI_OUT_OF_RESOURCES The EFI MTFTPv4 Protocol driver instance data could not be + allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI + MTFTPv4 Protocol driver instance is not configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_CONFIGURE)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_CONFIG_DATA *MtftpConfigData OPTIONAL + ); + + +/** + Gets information about a file from an MTFTPv4 server. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param OverrideData Data that is used to override the existing parameters. If NULL, + the default parameters that were set in the + EFI_MTFTP4_PROTOCOL.Configure() function are used. + @param Filename The pointer to null-terminated ASCII file name string. + @param ModeStr The pointer to null-terminated ASCII mode string. If NULL, "octet" will be used. + @param OptionCount Number of option/value string pairs in OptionList. + @param OptionList The pointer to array of option/value string pairs. Ignored if + OptionCount is zero. + @param PacketLength The number of bytes in the returned packet. + @param Packet The pointer to the received packet. This buffer must be freed by + the caller. + + @retval EFI_SUCCESS An MTFTPv4 OACK packet was received and is in the Packet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Filename is NULL. + - OptionCount is not zero and OptionList is NULL. + - One or more options in OptionList have wrong format. + - PacketLength is NULL. + - One or more IPv4 addresses in OverrideData are not valid + unicast IPv4 addresses if OverrideData is not NULL. + @retval EFI_UNSUPPORTED One or more options in the OptionList are in the + unsupported list of structure EFI_MTFTP4_MODE_DATA. + @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) has not finished yet. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received and is in the Packet. + @retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received and the Packet is set to NULL. + @retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received and the Packet is set to NULL. + @retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received and the Packet is set to NULL. + @retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received and the Packet is set to NULL. + @retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received and is in the Buffer. + @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv4 packet was received and is in the Packet. + @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + @retval EFI_NO_MEDIA There was a media error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_GET_INFO)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData OPTIONAL, + IN UINT8 *Filename, + IN UINT8 *ModeStr OPTIONAL, + IN UINT8 OptionCount, + IN EFI_MTFTP4_OPTION *OptionList, + OUT UINT32 *PacketLength, + OUT EFI_MTFTP4_PACKET **Packet OPTIONAL + ); + +/** + Parses the options in an MTFTPv4 OACK packet. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param PacketLen Length of the OACK packet to be parsed. + @param Packet The pointer to the OACK packet to be parsed. + @param OptionCount The pointer to the number of options in following OptionList. + @param OptionList The pointer to EFI_MTFTP4_OPTION storage. Call the EFI Boot + Service FreePool() to release the OptionList if the options + in this OptionList are not needed any more. + + @retval EFI_SUCCESS The OACK packet was valid and the OptionCount and + OptionList parameters have been updated. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - PacketLen is 0. + - Packet is NULL or Packet is not a valid MTFTPv4 packet. + - OptionCount is NULL. + @retval EFI_NOT_FOUND No options were found in the OACK packet. + @retval EFI_OUT_OF_RESOURCES Storage for the OptionList array cannot be allocated. + @retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_PARSE_OPTIONS)( + IN EFI_MTFTP4_PROTOCOL *This, + IN UINT32 PacketLen, + IN EFI_MTFTP4_PACKET *Packet, + OUT UINT32 *OptionCount, + OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL + ); + + +/** + Downloads a file from an MTFTPv4 server. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The data file has been transferred successfully. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the + downloaded data in downloading process. + @retval EFI_ABORTED Current operation is aborted by user. + @retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received. + @retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received. + @retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received. + @retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received. + @retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received. + @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server. + @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + @retval EFI_NO_MEDIA There was a media error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_READ_FILE)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ); + + + +/** + Sends a file to an MTFTPv4 server. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The upload session has started. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are in + the unsupported list of structure EFI_MTFTP4_MODE_DATA. + @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv4 session. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_WRITE_FILE)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ); + + +/** + Downloads a data file "directory" from an MTFTPv4 server. May be unsupported in some EFI + implementations. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The MTFTPv4 related file "directory" has been downloaded. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are in + the unsupported list of structure EFI_MTFTP4_MODE_DATA. + @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv4 session. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_READ_DIRECTORY)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + @param This The pointer to the EFI_MTFTP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI MTFTPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_POLL)( + IN EFI_MTFTP4_PROTOCOL *This + ); + +/// +/// The EFI_MTFTP4_PROTOCOL is designed to be used by UEFI drivers and applications +/// to transmit and receive data files. The EFI MTFTPv4 Protocol driver uses +/// the underlying EFI UDPv4 Protocol driver and EFI IPv4 Protocol driver. +/// +struct _EFI_MTFTP4_PROTOCOL { + EFI_MTFTP4_GET_MODE_DATA GetModeData; + EFI_MTFTP4_CONFIGURE Configure; + EFI_MTFTP4_GET_INFO GetInfo; + EFI_MTFTP4_PARSE_OPTIONS ParseOptions; + EFI_MTFTP4_READ_FILE ReadFile; + EFI_MTFTP4_WRITE_FILE WriteFile; + EFI_MTFTP4_READ_DIRECTORY ReadDirectory; + EFI_MTFTP4_POLL Poll; +}; + +struct _EFI_MTFTP4_TOKEN { + /// + /// The status that is returned to the caller at the end of the operation + /// to indicate whether this operation completed successfully. + /// + EFI_STATUS Status; + /// + /// The event that will be signaled when the operation completes. If + /// set to NULL, the corresponding function will wait until the read or + /// write operation finishes. The type of Event must be + /// EVT_NOTIFY_SIGNAL. The Task Priority Level (TPL) of + /// Event must be lower than or equal to TPL_CALLBACK. + /// + EFI_EVENT Event; + /// + /// If not NULL, the data that will be used to override the existing configure data. + /// + EFI_MTFTP4_OVERRIDE_DATA *OverrideData; + /// + /// The pointer to the null-terminated ASCII file name string. + /// + UINT8 *Filename; + /// + /// The pointer to the null-terminated ASCII mode string. If NULL, "octet" is used. + /// + UINT8 *ModeStr; + /// + /// Number of option/value string pairs. + /// + UINT32 OptionCount; + /// + /// The pointer to an array of option/value string pairs. Ignored if OptionCount is zero. + /// + EFI_MTFTP4_OPTION *OptionList; + /// + /// The size of the data buffer. + /// + UINT64 BufferSize; + /// + /// The pointer to the data buffer. Data that is downloaded from the + /// MTFTPv4 server is stored here. Data that is uploaded to the + /// MTFTPv4 server is read from here. Ignored if BufferSize is zero. + /// + VOID *Buffer; + /// + /// The pointer to the context that will be used by CheckPacket, + /// TimeoutCallback and PacketNeeded. + /// + VOID *Context; + /// + /// The pointer to the callback function to check the contents of the received packet. + /// + EFI_MTFTP4_CHECK_PACKET CheckPacket; + /// + /// The pointer to the function to be called when a timeout occurs. + /// + EFI_MTFTP4_TIMEOUT_CALLBACK TimeoutCallback; + /// + /// The pointer to the function to provide the needed packet contents. + /// + EFI_MTFTP4_PACKET_NEEDED PacketNeeded; +}; + +extern EFI_GUID gEfiMtftp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiMtftp4ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp6.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp6.h new file mode 100644 index 0000000..3273550 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Mtftp6.h @@ -0,0 +1,826 @@ +/** @file + UEFI Multicast Trivial File Transfer Protocol v6 Definition, which is built upon + the EFI UDPv6 Protocol and provides basic services for client-side unicast and/or + multicast TFTP operations. + + Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_MTFTP6_PROTOCOL_H__ +#define __EFI_MTFTP6_PROTOCOL_H__ + + +#define EFI_MTFTP6_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xd9760ff3, 0x3cca, 0x4267, {0x80, 0xf9, 0x75, 0x27, 0xfa, 0xfa, 0x42, 0x23 } \ + } + +#define EFI_MTFTP6_PROTOCOL_GUID \ + { \ + 0xbf0a78ba, 0xec29, 0x49cf, {0xa1, 0xc9, 0x7a, 0xe5, 0x4e, 0xab, 0x6a, 0x51 } \ + } + +typedef struct _EFI_MTFTP6_PROTOCOL EFI_MTFTP6_PROTOCOL; +typedef struct _EFI_MTFTP6_TOKEN EFI_MTFTP6_TOKEN; + +/// +/// MTFTP Packet OpCodes +///@{ +#define EFI_MTFTP6_OPCODE_RRQ 1 ///< The MTFTPv6 packet is a read request. +#define EFI_MTFTP6_OPCODE_WRQ 2 ///< The MTFTPv6 packet is a write request. +#define EFI_MTFTP6_OPCODE_DATA 3 ///< The MTFTPv6 packet is a data packet. +#define EFI_MTFTP6_OPCODE_ACK 4 ///< The MTFTPv6 packet is an acknowledgement packet. +#define EFI_MTFTP6_OPCODE_ERROR 5 ///< The MTFTPv6 packet is an error packet. +#define EFI_MTFTP6_OPCODE_OACK 6 ///< The MTFTPv6 packet is an option acknowledgement packet. +#define EFI_MTFTP6_OPCODE_DIR 7 ///< The MTFTPv6 packet is a directory query packet. +#define EFI_MTFTP6_OPCODE_DATA8 8 ///< The MTFTPv6 packet is a data packet with a big block number. +#define EFI_MTFTP6_OPCODE_ACK8 9 ///< The MTFTPv6 packet is an acknowledgement packet with a big block number. +///@} + +/// +/// MTFTP ERROR Packet ErrorCodes +///@{ +/// +/// The error code is not defined. See the error message in the packet (if any) for details. +/// +#define EFI_MTFTP6_ERRORCODE_NOT_DEFINED 0 +/// +/// The file was not found. +/// +#define EFI_MTFTP6_ERRORCODE_FILE_NOT_FOUND 1 +/// +/// There was an access violation. +/// +#define EFI_MTFTP6_ERRORCODE_ACCESS_VIOLATION 2 +/// +/// The disk was full or its allocation was exceeded. +/// +#define EFI_MTFTP6_ERRORCODE_DISK_FULL 3 +/// +/// The MTFTPv6 operation was illegal. +/// +#define EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION 4 +/// +/// The transfer ID is unknown. +/// +#define EFI_MTFTP6_ERRORCODE_UNKNOWN_TRANSFER_ID 5 +/// +/// The file already exists. +/// +#define EFI_MTFTP6_ERRORCODE_FILE_ALREADY_EXISTS 6 +/// +/// There is no such user. +/// +#define EFI_MTFTP6_ERRORCODE_NO_SUCH_USER 7 +/// +/// The request has been denied due to option negotiation. +/// +#define EFI_MTFTP6_ERRORCODE_REQUEST_DENIED 8 +///@} + +#pragma pack(1) + +/// +/// EFI_MTFTP6_REQ_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_RRQ for a read request + /// or OpCode = EFI_MTFTP6_OPCODE_WRQ for a write request. + /// + UINT16 OpCode; + /// + /// The file name to be downloaded or uploaded. + /// + UINT8 Filename[1]; +} EFI_MTFTP6_REQ_HEADER; + +/// +/// EFI_MTFTP6_OACK_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_OACK. + /// + UINT16 OpCode; + /// + /// The option strings in the option acknowledgement packet. + /// + UINT8 Data[1]; +} EFI_MTFTP6_OACK_HEADER; + +/// +/// EFI_MTFTP6_DATA_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_DATA. + /// + UINT16 OpCode; + /// + /// Block number of this data packet. + /// + UINT16 Block; + /// + /// The content of this data packet. + /// + UINT8 Data[1]; +} EFI_MTFTP6_DATA_HEADER; + +/// +/// EFI_MTFTP6_ACK_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_ACK. + /// + UINT16 OpCode; + /// + /// The block number of the data packet that is being acknowledged. + /// + UINT16 Block[1]; +} EFI_MTFTP6_ACK_HEADER; + +/// +/// EFI_MTFTP6_DATA8_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_DATA8. + /// + UINT16 OpCode; + /// + /// The block number of data packet. + /// + UINT64 Block; + /// + /// The content of this data packet. + /// + UINT8 Data[1]; +} EFI_MTFTP6_DATA8_HEADER; + +/// +/// EFI_MTFTP6_ACK8_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_ACK8. + /// + UINT16 OpCode; + /// + /// The block number of the data packet that is being acknowledged. + /// + UINT64 Block[1]; +} EFI_MTFTP6_ACK8_HEADER; + +/// +/// EFI_MTFTP6_ERROR_HEADER +/// +typedef struct { + /// + /// For this packet type, OpCode = EFI_MTFTP6_OPCODE_ERROR. + /// + UINT16 OpCode; + /// + /// The error number as defined by the MTFTPv6 packet error codes. + /// + UINT16 ErrorCode; + /// + /// Error message string. + /// + UINT8 ErrorMessage[1]; +} EFI_MTFTP6_ERROR_HEADER; + +/// +/// EFI_MTFTP6_PACKET +/// +typedef union { + UINT16 OpCode; ///< Type of packets as defined by the MTFTPv6 packet opcodes. + EFI_MTFTP6_REQ_HEADER Rrq; ///< Read request packet header. + EFI_MTFTP6_REQ_HEADER Wrq; ///< write request packet header. + EFI_MTFTP6_OACK_HEADER Oack; ///< Option acknowledge packet header. + EFI_MTFTP6_DATA_HEADER Data; ///< Data packet header. + EFI_MTFTP6_ACK_HEADER Ack; ///< Acknowledgement packet header. + EFI_MTFTP6_DATA8_HEADER Data8; ///< Data packet header with big block number. + EFI_MTFTP6_ACK8_HEADER Ack8; ///< Acknowledgement header with big block number. + EFI_MTFTP6_ERROR_HEADER Error; ///< Error packet header. +} EFI_MTFTP6_PACKET; + +#pragma pack() + +/// +/// EFI_MTFTP6_CONFIG_DATA +/// +typedef struct { + /// + /// The local IP address to use. Set to zero to let the underlying IPv6 + /// driver choose a source address. If not zero it must be one of the + /// configured IP addresses in the underlying IPv6 driver. + /// + EFI_IPv6_ADDRESS StationIp; + /// + /// Local port number. Set to zero to use the automatically assigned port number. + /// + UINT16 LocalPort; + /// + /// The IP address of the MTFTPv6 server. + /// + EFI_IPv6_ADDRESS ServerIp; + /// + /// The initial MTFTPv6 server port number. Request packets are + /// sent to this port. This number is almost always 69 and using zero + /// defaults to 69. + UINT16 InitialServerPort; + /// + /// The number of times to transmit MTFTPv6 request packets and wait for a response. + /// + UINT16 TryCount; + /// + /// The number of seconds to wait for a response after sending the MTFTPv6 request packet. + /// + UINT16 TimeoutValue; +} EFI_MTFTP6_CONFIG_DATA; + +/// +/// EFI_MTFTP6_MODE_DATA +/// +typedef struct { + /// + /// The configuration data of this instance. + /// + EFI_MTFTP6_CONFIG_DATA ConfigData; + /// + /// The number of option strings in the following SupportedOptions array. + /// + UINT8 SupportedOptionCount; + /// + /// An array of null-terminated ASCII option strings that are recognized and supported by + /// this EFI MTFTPv6 Protocol driver implementation. The buffer is + /// read only to the caller and the caller should NOT free the buffer. + /// + UINT8 **SupportedOptions; +} EFI_MTFTP6_MODE_DATA; + +/// +/// EFI_MTFTP_OVERRIDE_DATA +/// +typedef struct { + /// + /// IP address of the MTFTPv6 server. If set to all zero, the value that + /// was set by the EFI_MTFTP6_PROTOCOL.Configure() function will be used. + /// + EFI_IPv6_ADDRESS ServerIp; + /// + /// MTFTPv6 server port number. If set to zero, it will use the value + /// that was set by the EFI_MTFTP6_PROTOCOL.Configure() function. + /// + UINT16 ServerPort; + /// + /// Number of times to transmit MTFTPv6 request packets and wait + /// for a response. If set to zero, the value that was set by + /// theEFI_MTFTP6_PROTOCOL.Configure() function will be used. + /// + UINT16 TryCount; + /// + /// Number of seconds to wait for a response after sending the + /// MTFTPv6 request packet. If set to zero, the value that was set by + /// the EFI_MTFTP6_PROTOCOL.Configure() function will be used. + /// + UINT16 TimeoutValue; +} EFI_MTFTP6_OVERRIDE_DATA; + +/// +/// EFI_MTFTP6_OPTION +/// +typedef struct { + UINT8 *OptionStr; ///< Pointer to the null-terminated ASCII MTFTPv6 option string. + UINT8 *ValueStr; ///< Pointer to the null-terminated ASCII MTFTPv6 value string. +} EFI_MTFTP6_OPTION; + +/** + EFI_MTFTP6_TIMEOUT_CALLBACK is a callback function that the caller provides to capture the + timeout event in the EFI_MTFTP6_PROTOCOL.ReadFile(), EFI_MTFTP6_PROTOCOL.WriteFile() or + EFI_MTFTP6_PROTOCOL.ReadDirectory() functions. + + Whenever a timeout occurs, the EFI MTFTPv6 Protocol driver will call the EFI_MTFTP6_TIMEOUT_CALLBACK + function to notify the caller of the timeout event. Any status code other than EFI_SUCCESS + that is returned from this function will abort the current download process. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] Token The token that the caller provided in the EFI_MTFTP6_PROTOCOl.ReadFile(), + WriteFile() or ReadDirectory() function. + @param[in] PacketLen Indicates the length of the packet. + @param[in] Packet Pointer to an MTFTPv6 packet. + + @retval EFI_SUCCESS Operation success. + @retval Others Aborts session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_CHECK_PACKET)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_TOKEN *Token, + IN UINT16 PacketLen, + IN EFI_MTFTP6_PACKET *Packet + ); + +/** + EFI_MTFTP6_TIMEOUT_CALLBACK is a callback function that the caller provides to capture the + timeout event in the EFI_MTFTP6_PROTOCOL.ReadFile(), EFI_MTFTP6_PROTOCOL.WriteFile() or + EFI_MTFTP6_PROTOCOL.ReadDirectory() functions. + + Whenever a timeout occurs, the EFI MTFTPv6 Protocol driver will call the EFI_MTFTP6_TIMEOUT_CALLBACK + function to notify the caller of the timeout event. Any status code other than EFI_SUCCESS + that is returned from this function will abort the current download process. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] Token The token that is provided in the EFI_MTFTP6_PROTOCOL.ReadFile() or + EFI_MTFTP6_PROTOCOL.WriteFile() or EFI_MTFTP6_PROTOCOL.ReadDirectory() + functions by the caller. + + @retval EFI_SUCCESS Operation success. + @retval Others Aborts session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_TIMEOUT_CALLBACK)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_TOKEN *Token + ); + +/** + EFI_MTFTP6_PACKET_NEEDED is a callback function that the caller provides to feed data to the + EFI_MTFTP6_PROTOCOL.WriteFile() function. + + EFI_MTFTP6_PACKET_NEEDED provides another mechanism for the caller to provide data to upload + other than a static buffer. The EFI MTFTP6 Protocol driver always calls EFI_MTFTP6_PACKET_NEEDED + to get packet data from the caller if no static buffer was given in the initial call to + EFI_MTFTP6_PROTOCOL.WriteFile() function. Setting *Length to zero signals the end of the session. + Returning a status code other than EFI_SUCCESS aborts the session. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] Token The token provided in the EFI_MTFTP6_PROTOCOL.WriteFile() by the caller. + @param[in, out] Length Indicates the length of the raw data wanted on input, and the + length the data available on output. + @param[out] Buffer Pointer to the buffer where the data is stored. + + @retval EFI_SUCCESS Operation success. + @retval Others Aborts session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_PACKET_NEEDED)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_TOKEN *Token, + IN OUT UINT16 *Length, + OUT VOID **Buffer + ); + +struct _EFI_MTFTP6_TOKEN { + /// + /// The status that is returned to the caller at the end of the operation + /// to indicate whether this operation completed successfully. + /// Defined Status values are listed below. + /// + EFI_STATUS Status; + /// + /// The event that will be signaled when the operation completes. If + /// set to NULL, the corresponding function will wait until the read or + /// write operation finishes. The type of Event must be EVT_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// If not NULL, the data that will be used to override the existing + /// configure data. + /// + EFI_MTFTP6_OVERRIDE_DATA *OverrideData; + /// + /// Pointer to the null-terminated ASCII file name string. + /// + UINT8 *Filename; + /// + /// Pointer to the null-terminated ASCII mode string. If NULL, octet is used. + /// + UINT8 *ModeStr; + /// + /// Number of option/value string pairs. + /// + UINT32 OptionCount; + /// + /// Pointer to an array of option/value string pairs. Ignored if + /// OptionCount is zero. Both a remote server and this driver + /// implementation should support these options. If one or more + /// options are unrecognized by this implementation, it is sent to the + /// remote server without being changed. + /// + EFI_MTFTP6_OPTION *OptionList; + /// + /// On input, the size, in bytes, of Buffer. On output, the number + /// of bytes transferred. + /// + UINT64 BufferSize; + /// + /// Pointer to the data buffer. Data that is downloaded from the + /// MTFTPv6 server is stored here. Data that is uploaded to the + /// MTFTPv6 server is read from here. Ignored if BufferSize is zero. + /// + VOID *Buffer; + /// + /// Pointer to the context that will be used by CheckPacket, + /// TimeoutCallback and PacketNeeded. + /// + VOID *Context; + /// + /// Pointer to the callback function to check the contents of the + /// received packet. + /// + EFI_MTFTP6_CHECK_PACKET CheckPacket; + /// + /// Pointer to the function to be called when a timeout occurs. + /// + EFI_MTFTP6_TIMEOUT_CALLBACK TimeoutCallback; + /// + /// Pointer to the function to provide the needed packet contents. + /// Only used in WriteFile() operation. + /// + EFI_MTFTP6_PACKET_NEEDED PacketNeeded; +}; + +/** + Read the current operational settings. + + The GetModeData() function reads the current operational settings of this EFI MTFTPv6 + Protocol driver instance. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[out] ModeData The buffer in which the EFI MTFTPv6 Protocol driver mode + data is returned. + + @retval EFI_SUCCESS The configuration data was successfully returned. + @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated. + @retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_GET_MODE_DATA)( + IN EFI_MTFTP6_PROTOCOL *This, + OUT EFI_MTFTP6_MODE_DATA *ModeData + ); + +/** + Initializes, changes, or resets the default operational setting for this EFI MTFTPv6 + Protocol driver instance. + + The Configure() function is used to set and change the configuration data for this EFI + MTFTPv6 Protocol driver instance. The configuration data can be reset to startup defaults by calling + Configure() with MtftpConfigData set to NULL. Whenever the instance is reset, any + pending operation is aborted. By changing the EFI MTFTPv6 Protocol driver instance configuration + data, the client can connect to different MTFTPv6 servers. The configuration parameters in + MtftpConfigData are used as the default parameters in later MTFTPv6 operations and can be + overridden in later operations. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] MtftpConfigData Pointer to the configuration data structure. + + @retval EFI_SUCCESS The EFI MTFTPv6 Protocol instance was configured successfully. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + - This is NULL. + - MtftpConfigData.StationIp is neither zero nor one + of the configured IP addresses in the underlying IPv6 driver. + - MtftpCofigData.ServerIp is not a valid IPv6 unicast address. + @retval EFI_ACCESS_DENIED - The configuration could not be changed at this time because there + is some MTFTP background operation in progress. + - MtftpCofigData.LocalPort is already in use. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for use. + @retval EFI_OUT_OF_RESOURCES The EFI MTFTPv6 Protocol driver instance data could not be + allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI + MTFTPv6 Protocol driver instance is not configured. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_CONFIGURE)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_CONFIG_DATA *MtftpConfigData OPTIONAL +); + +/** + Get information about a file from an MTFTPv6 server. + + The GetInfo() function assembles an MTFTPv6 request packet with options, sends it to the + MTFTPv6 server, and may return an MTFTPv6 OACK, MTFTPv6 ERROR, or ICMP ERROR packet. + Retries occur only if no response packets are received from the MTFTPv6 server before the + timeout expires. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] OverrideData Data that is used to override the existing parameters. If NULL, the + default parameters that were set in the EFI_MTFTP6_PROTOCOL.Configure() + function are used. + @param[in] Filename Pointer to null-terminated ASCII file name string. + @param[in] ModeStr Pointer to null-terminated ASCII mode string. If NULL, octet will be used + @param[in] OptionCount Number of option/value string pairs in OptionList. + @param[in] OptionList Pointer to array of option/value string pairs. Ignored if + OptionCount is zero. + @param[out] PacketLength The number of bytes in the returned packet. + @param[out] Packet The pointer to the received packet. This buffer must be freed by + the caller. + + @retval EFI_SUCCESS An MTFTPv6 OACK packet was received and is in the Packet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Filename is NULL + - OptionCount is not zero and OptionList is NULL. + - One or more options in OptionList have wrong format. + - PacketLength is NULL. + - OverrideData.ServerIp is not valid unicast IPv6 addresses. + @retval EFI_UNSUPPORTED One or more options in the OptionList are unsupported by + this implementation. + @retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for use. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received and is in the Packet. + @retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received and the Packet is set to NULL. + @retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received and the Packet is set to NULL. + @retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received and the Packet is set to NULL. + @retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received and the Packet is set to NULL. + @retval EFI_ICMP_ERROR Some other ICMP ERROR packet was received and the Packet is set to NULL. + @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv6 packet was received and is in the Packet. + @retval EFI_TIMEOUT No responses were received from the MTFTPv6 server. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + @retval EFI_NO_MEDIA There was a media error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_GET_INFO)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_OVERRIDE_DATA *OverrideData OPTIONAL, + IN UINT8 *Filename, + IN UINT8 *ModeStr OPTIONAL, + IN UINT8 OptionCount, + IN EFI_MTFTP6_OPTION *OptionList OPTIONAL, + OUT UINT32 *PacketLength, + OUT EFI_MTFTP6_PACKET **Packet OPTIONAL +); + +/** + Parse the options in an MTFTPv6 OACK packet. + + The ParseOptions() function parses the option fields in an MTFTPv6 OACK packet and + returns the number of options that were found and optionally a list of pointers to + the options in the packet. + If one or more of the option fields are not valid, then EFI_PROTOCOL_ERROR is returned + and *OptionCount and *OptionList stop at the last valid option. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] PacketLen Length of the OACK packet to be parsed. + @param[in] Packet Pointer to the OACK packet to be parsed. + @param[out] OptionCount Pointer to the number of options in the following OptionList. + @param[out] OptionList Pointer to EFI_MTFTP6_OPTION storage. Each pointer in the + OptionList points to the corresponding MTFTP option buffer + in the Packet. Call the EFI Boot Service FreePool() to + release the OptionList if the options in this OptionList + are not needed any more. + + @retval EFI_SUCCESS The OACK packet was valid and the OptionCount and + OptionList parameters have been updated. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - PacketLen is 0. + - Packet is NULL or Packet is not a valid MTFTPv6 packet. + - OptionCount is NULL. + @retval EFI_NOT_FOUND No options were found in the OACK packet. + @retval EFI_OUT_OF_RESOURCES Storage for the OptionList array can not be allocated. + @retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_PARSE_OPTIONS)( + IN EFI_MTFTP6_PROTOCOL *This, + IN UINT32 PacketLen, + IN EFI_MTFTP6_PACKET *Packet, + OUT UINT32 *OptionCount, + OUT EFI_MTFTP6_OPTION **OptionList OPTIONAL + ); + +/** + Download a file from an MTFTPv6 server. + + The ReadFile() function is used to initialize and start an MTFTPv6 download process and + optionally wait for completion. When the download operation completes, whether successfully or + not, the Token.Status field is updated by the EFI MTFTPv6 Protocol driver and then + Token.Event is signaled if it is not NULL. + + Data can be downloaded from the MTFTPv6 server into either of the following locations: + - A fixed buffer that is pointed to by Token.Buffer + - A download service function that is pointed to by Token.CheckPacket + + If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket + will be called first. If the call is successful, the packet will be stored in Token.Buffer. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The data file has been transferred successfully. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_BUFFER_TOO_SMALL BufferSize is not zero but not large enough to hold the + downloaded data in downloading process. + @retval EFI_ABORTED Current operation is aborted by user. + @retval EFI_NETWORK_UNREACHABLE An ICMP network unreachable error packet was received. + @retval EFI_HOST_UNREACHABLE An ICMP host unreachable error packet was received. + @retval EFI_PROTOCOL_UNREACHABLE An ICMP protocol unreachable error packet was received. + @retval EFI_PORT_UNREACHABLE An ICMP port unreachable error packet was received. + @retval EFI_ICMP_ERROR An ICMP ERROR packet was received. + @retval EFI_TIMEOUT No responses were received from the MTFTPv6 server. + @retval EFI_TFTP_ERROR An MTFTPv6 ERROR packet was received. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + @retval EFI_NO_MEDIA There was a media error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_READ_FILE)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_TOKEN *Token + ); + +/** + Send a file to an MTFTPv6 server. May be unsupported in some implementations. + + The WriteFile() function is used to initialize an uploading operation with the given option list + and optionally wait for completion. If one or more of the options is not supported by the server, the + unsupported options are ignored and a standard TFTP process starts instead. When the upload + process completes, whether successfully or not, Token.Event is signaled, and the EFI MTFTPv6 + Protocol driver updates Token.Status. + + The caller can supply the data to be uploaded in the following two modes: + - Through the user-provided buffer + - Through a callback function + + With the user-provided buffer, the Token.BufferSize field indicates the length of the buffer, + and the driver will upload the data in the buffer. With an EFI_MTFTP6_PACKET_NEEDED + callback function, the driver will call this callback function to get more data from the user to upload. + See the definition of EFI_MTFTP6_PACKET_NEEDED for more information. These two modes + cannot be used at the same time. The callback function will be ignored if the user provides the + buffer. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The upload session has started. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Filename is NULL. + - Token.OptionCount is not zero and Token.OptionList is NULL. + - One or more options in Token.OptionList have wrong format. + - Token.Buffer and Token.PacketNeeded are both NULL. + - Token.OverrideData.ServerIp is not valid unicast IPv6 addresses. + @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not + supported by this implementation. + @retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for use. + @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_WRITE_FILE)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_TOKEN *Token + ); + +/** + Download a data file directory from an MTFTPv6 server. May be unsupported in some implementations. + + The ReadDirectory() function is used to return a list of files on the MTFTPv6 server that are + logically (or operationally) related to Token.Filename. The directory request packet that is sent + to the server is built with the option list that was provided by caller, if present. + + The file information that the server returns is put into either of the following locations: + - A fixed buffer that is pointed to by Token.Buffer + - A download service function that is pointed to by Token.CheckPacket + + If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket + will be called first. If the call is successful, the packet will be stored in Token.Buffer. + + The returned directory listing in the Token.Buffer or EFI_MTFTP6_PACKET consists of a list + of two or three variable-length ASCII strings, each terminated by a null character, for each file in the + directory. If the multicast option is involved, the first field of each directory entry is the static + multicast IP address and UDP port number that is associated with the file name. The format of the + field is ip:ip:ip:ip:port. If the multicast option is not involved, this field and its terminating + null character are not present. + + The next field of each directory entry is the file name and the last field is the file information string. + The information string contains the file size and the create/modify timestamp. The format of the + information string is filesize yyyy-mm-dd hh:mm:ss:ffff. The timestamp is + Coordinated Universal Time (UTC; also known as Greenwich Mean Time [GMT]). + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + @param[in] Token Pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The MTFTPv6 related file "directory" has been downloaded. + @retval EFI_UNSUPPORTED The EFI MTFTPv6 Protocol driver does not support this function. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Filename is NULL. + - Token.OptionCount is not zero and Token.OptionList is NULL. + - One or more options in Token.OptionList have wrong format. + - Token.Buffer and Token.CheckPacket are both NULL. + - Token.OverrideData.ServerIp is not valid unicast IPv6 addresses. + @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are not + supported by this implementation. + @retval EFI_NOT_STARTED The EFI MTFTPv6 Protocol driver has not been started. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for use. + @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv6 session. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_READ_DIRECTORY)( + IN EFI_MTFTP6_PROTOCOL *This, + IN EFI_MTFTP6_TOKEN *Token +); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function can be used by network drivers and applications to increase the rate that data + packets are moved between the communications device and the transmit and receive queues. + In some systems, the periodic timer event in the managed network driver may not poll the + underlying communications device fast enough to transmit and/or receive all data packets without + missing incoming packets or dropping outgoing packets. Drivers and applications that are + experiencing packet loss should try calling the Poll() function more often. + + @param[in] This Pointer to the EFI_MTFTP6_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI MTFTPv6 Protocol instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP6_POLL)( + IN EFI_MTFTP6_PROTOCOL *This + ); + +/// +/// The EFI_MTFTP6_PROTOCOL is designed to be used by UEFI drivers and applications to transmit +/// and receive data files. The EFI MTFTPv6 Protocol driver uses the underlying EFI UDPv6 Protocol +/// driver and EFI IPv6 Protocol driver. +/// +struct _EFI_MTFTP6_PROTOCOL { + EFI_MTFTP6_GET_MODE_DATA GetModeData; + EFI_MTFTP6_CONFIGURE Configure; + EFI_MTFTP6_GET_INFO GetInfo; + EFI_MTFTP6_PARSE_OPTIONS ParseOptions; + EFI_MTFTP6_READ_FILE ReadFile; + EFI_MTFTP6_WRITE_FILE WriteFile; + EFI_MTFTP6_READ_DIRECTORY ReadDirectory; + EFI_MTFTP6_POLL Poll; +}; + +extern EFI_GUID gEfiMtftp6ServiceBindingProtocolGuid; +extern EFI_GUID gEfiMtftp6ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NetworkInterfaceIdentifier.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NetworkInterfaceIdentifier.h new file mode 100644 index 0000000..01fb6cb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NetworkInterfaceIdentifier.h @@ -0,0 +1,118 @@ +/** @file + EFI Network Interface Identifier Protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in EFI Specification 1.10. + +**/ + +#ifndef __EFI_NETWORK_INTERFACE_IDENTIFER_H__ +#define __EFI_NETWORK_INTERFACE_IDENTIFER_H__ + +// +// GUID retired from UEFI Specification 2.1b +// +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \ + { \ + 0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29 } \ + } + +// +// GUID intruduced in UEFI Specification 2.1b +// +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31 \ + { \ + 0x1ACED566, 0x76ED, 0x4218, {0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 } \ + } + +// +// Revision defined in UEFI Specification 2.4 +// +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION 0x00020000 + + +/// +/// Revision defined in EFI1.1. +/// +#define EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE_REVISION EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION + +/// +/// Forward reference for pure ANSI compatability. +/// +typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL; + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE; + +/// +/// An optional protocol that is used to describe details about the software +/// layer that is used to produce the Simple Network Protocol. +/// +struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL { + UINT64 Revision; ///< The revision of the EFI_NETWORK_INTERFACE_IDENTIFIER protocol. + UINT64 Id; ///< The address of the first byte of the identifying structure for this network + ///< interface. This is only valid when the network interface is started + ///< (see Start()). When the network interface is not started, this field is set to zero. + UINT64 ImageAddr; ///< The address of the first byte of the identifying structure for this + ///< network interface. This is set to zero if there is no structure. + UINT32 ImageSize; ///< The size of unrelocated network interface image. + CHAR8 StringId[4];///< A four-character ASCII string that is sent in the class identifier field of + ///< option 60 in DHCP. For a Type of EfiNetworkInterfaceUndi, this field is UNDI. + UINT8 Type; ///< Network interface type. This will be set to one of the values + ///< in EFI_NETWORK_INTERFACE_TYPE. + UINT8 MajorVer; ///< Major version number. + UINT8 MinorVer; ///< Minor version number. + BOOLEAN Ipv6Supported; ///< TRUE if the network interface supports IPv6; otherwise FALSE. + UINT16 IfNum; ///< The network interface number that is being identified by this Network + ///< Interface Identifier Protocol. This field must be less than or + ///< equal to the (IFcnt | IFcntExt <<8 ) fields in the !PXE structure. + +}; + +/// +///******************************************************* +/// EFI_NETWORK_INTERFACE_TYPE +///******************************************************* +/// +typedef enum { + EfiNetworkInterfaceUndi = 1 +} EFI_NETWORK_INTERFACE_TYPE; + +/// +/// Forward reference for pure ANSI compatability. +/// +typedef struct undiconfig_table UNDI_CONFIG_TABLE; + +/// +/// The format of the configuration table for UNDI +/// +struct undiconfig_table { + UINT32 NumberOfInterfaces; ///< The number of NIC devices + ///< that this UNDI controls. + UINT32 reserved; + UNDI_CONFIG_TABLE *nextlink; ///< A pointer to the next UNDI + ///< configuration table. + /// + /// The length of this array is given in the NumberOfInterfaces field. + /// + struct { + VOID *NII_InterfacePointer; ///< Pointer to the NII interface structure. + VOID *DevicePathPointer; ///< Pointer to the device path for this NIC. + } NII_entry[1]; +}; + +extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid; +extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid_31; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvdimmLabel.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvdimmLabel.h new file mode 100644 index 0000000..edfeec0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvdimmLabel.h @@ -0,0 +1,351 @@ +/** @file + EFI NVDIMM Label Protocol Definition + + The EFI NVDIMM Label Protocol is used to Provides services that allow management + of labels contained in a Label Storage Area that are associated with a specific + NVDIMM Device Path. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.7. + +**/ + +#ifndef __EFI_NVDIMM_LABEL_PROTOCOL_H__ +#define __EFI_NVDIMM_LABEL_PROTOCOL_H__ + +#define EFI_NVDIMM_LABEL_PROTOCOL_GUID \ + { \ + 0xd40b6b80, 0x97d5, 0x4282, {0xbb, 0x1d, 0x22, 0x3a, 0x16, 0x91, 0x80, 0x58 } \ + } + +typedef struct _EFI_NVDIMM_LABEL_PROTOCOL EFI_NVDIMM_LABEL_PROTOCOL; + +#define EFI_NVDIMM_LABEL_INDEX_SIG_LEN 16 +#define EFI_NVDIMM_LABEL_INDEX_ALIGN 256 +typedef struct { + /// + /// Signature of the Index Block data structure. Must be "NAMESPACE_INDEX\0". + /// + CHAR8 Sig[EFI_NVDIMM_LABEL_INDEX_SIG_LEN]; + + /// + /// Attributes of this Label Storage Area. + /// + UINT8 Flags[3]; + + /// + /// Size of each label in bytes, 128 bytes << LabelSize. + /// 1 means 256 bytes, 2 means 512 bytes, etc. Shall be 1 or greater. + /// + UINT8 LabelSize; + + /// + /// Sequence number used to identify which of the two Index Blocks is current. + /// + UINT32 Seq; + + /// + /// The offset of this Index Block in the Label Storage Area. + /// + UINT64 MyOff; + + /// + /// The size of this Index Block in bytes. + /// This field must be a multiple of the EFI_NVDIMM_LABEL_INDEX_ALIGN. + /// + UINT64 MySize; + + /// + /// The offset of the other Index Block paired with this one. + /// + UINT64 OtherOff; + + /// + /// The offset of the first slot where labels are stored in this Label Storage Area. + /// + UINT64 LabelOff; + + /// + /// The total number of slots for storing labels in this Label Storage Area. + /// + UINT32 NSlot; + + /// + /// Major version number. Value shall be 1. + /// + UINT16 Major; + + /// + /// Minor version number. Value shall be 2. + /// + UINT16 Minor; + + /// + /// 64-bit Fletcher64 checksum of all fields in this Index Block. + /// + UINT64 Checksum; + + /// + /// Array of unsigned bytes implementing a bitmask that tracks which label slots are free. + /// A bit value of 0 indicates in use, 1 indicates free. + /// The size of this field is the number of bytes required to hold the bitmask with NSlot bits, + /// padded with additional zero bytes to make the Index Block size a multiple of EFI_NVDIMM_LABEL_INDEX_ALIGN. + /// Any bits allocated beyond NSlot bits must be zero. + /// + UINT8 Free[]; +} EFI_NVDIMM_LABEL_INDEX_BLOCK; + +#define EFI_NVDIMM_LABEL_NAME_LEN 64 + +/// +/// The label is read-only. +/// +#define EFI_NVDIMM_LABEL_FLAGS_ROLABEL 0x00000001 + +/// +/// When set, the complete label set is local to a single NVDIMM Label Storage Area. +/// When clear, the complete label set is contained on multiple NVDIMM Label Storage Areas. +/// +#define EFI_NVDIMM_LABEL_FLAGS_LOCAL 0x00000002 + +/// +/// This reserved flag is utilized on older implementations and has been deprecated. +/// Do not use. +// +#define EFI_NVDIMM_LABEL_FLAGS_RESERVED 0x00000004 + +/// +/// When set, the label set is being updated. +/// +#define EFI_NVDIMM_LABEL_FLAGS_UPDATING 0x00000008 + +typedef struct { + /// + /// Unique Label Identifier UUID per RFC 4122. + /// + EFI_GUID Uuid; + + /// + /// NULL-terminated string using UTF-8 character formatting. + /// + CHAR8 Name[EFI_NVDIMM_LABEL_NAME_LEN]; + + /// + /// Attributes of this namespace. + /// + UINT32 Flags; + + /// + /// Total number of labels describing this namespace. + /// + UINT16 NLabel; + + /// + /// Position of this label in list of labels for this namespace. + /// + UINT16 Position; + + /// + /// The SetCookie is utilized by SW to perform consistency checks on the Interleave Set to verify the current + /// physical device configuration matches the original physical configuration when the labels were created + /// for the set.The label is considered invalid if the actual label set cookie doesn't match the cookie stored here. + /// + UINT64 SetCookie; + + /// + /// This is the default logical block size in bytes and may be superseded by a block size that is specified + /// in the AbstractionGuid. + /// + UINT64 LbaSize; + + /// + /// The DPA is the DIMM Physical address where the NVM contributing to this namespace begins on this NVDIMM. + /// + UINT64 Dpa; + + /// + /// The extent of the DPA contributed by this label. + /// + UINT64 RawSize; + + /// + /// Current slot in the Label Storage Area where this label is stored. + /// + UINT32 Slot; + + /// + /// Alignment hint used to advertise the preferred alignment of the data from within the namespace defined by this label. + /// + UINT8 Alignment; + + /// + /// Shall be 0. + /// + UINT8 Reserved[3]; + + /// + /// Range Type GUID that describes the access mechanism for the specified DPA range. + /// + EFI_GUID TypeGuid; + + /// + /// Identifies the address abstraction mechanism for this namespace. A value of 0 indicates no mechanism used. + /// + EFI_GUID AddressAbstractionGuid; + + /// + /// Shall be 0. + /// + UINT8 Reserved1[88]; + + /// + /// 64-bit Fletcher64 checksum of all fields in this Label. + /// This field is considered zero when the checksum is computed. + /// + UINT64 Checksum; +} EFI_NVDIMM_LABEL; + +typedef struct { + /// + /// The Region Offset field from the ACPI NFIT NVDIMM Region Mapping Structure for a given entry. + /// + UINT64 RegionOffset; + + /// + /// The serial number of the NVDIMM, assigned by the module vendor. + /// + UINT32 SerialNumber; + + /// + /// The identifier indicating the vendor of the NVDIMM. + /// + UINT16 VendorId; + + /// + /// The manufacturing date of the NVDIMM, assigned by the module vendor. + /// + UINT16 ManufacturingDate; + + /// + /// The manufacturing location from for the NVDIMM, assigned by the module vendor. + /// + UINT8 ManufacturingLocation; + + /// + /// Shall be 0. + /// + UINT8 Reserved[31]; +} EFI_NVDIMM_LABEL_SET_COOKIE_MAP; + +typedef struct { + /// + /// Array size is 1 if EFI_NVDIMM_LABEL_FLAGS_LOCAL is set indicating a Local Namespaces. + /// + EFI_NVDIMM_LABEL_SET_COOKIE_MAP Mapping[0]; +} EFI_NVDIMM_LABEL_SET_COOKIE_INFO; + +/** + Retrieves the Label Storage Area size and the maximum transfer size for the LabelStorageRead and + LabelStorageWrite methods. + + @param This A pointer to the EFI_NVDIMM_LABEL_PROTOCOL instance. + @param SizeOfLabelStorageArea The size of the Label Storage Area for the NVDIMM in bytes. + @param MaxTransferLength The maximum number of bytes that can be transferred in a single call to + LabelStorageRead or LabelStorageWrite. + + @retval EFI_SUCCESS The size of theLabel Storage Area and maximum transfer size returned are valid. + @retval EFI_ACCESS_DENIED The Label Storage Area for the NVDIMM device is not currently accessible. + @retval EFI_DEVICE_ERROR A physical device error occurred and the data transfer failed to complete. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVDIMM_LABEL_STORAGE_INFORMATION) ( + IN EFI_NVDIMM_LABEL_PROTOCOL *This, + OUT UINT32 *SizeOfLabelStorageArea, + OUT UINT32 *MaxTransferLength + ); + +/** + Retrieves the label data for the requested offset and length from within the Label Storage Area for + the NVDIMM. + + @param This A pointer to the EFI_NVDIMM_LABEL_PROTOCOL instance. + @param Offset The byte offset within the Label Storage Area to read from. + @param TransferLength Number of bytes to read from the Label Storage Area beginning at the byte + Offset specified. A TransferLength of 0 reads no data. + @param LabelData The return label data read at the requested offset and length from within + the Label Storage Area. + + @retval EFI_SUCCESS The label data from the Label Storage Area for the NVDIMM was read successfully + at the specified Offset and TransferLength and LabelData contains valid data. + @retval EFI_INVALID_PARAMETER Any of the following are true: + - Offset > SizeOfLabelStorageArea reported in the LabelStorageInformation return data. + - Offset + TransferLength is > SizeOfLabelStorageArea reported in the + LabelStorageInformation return data. + - TransferLength is > MaxTransferLength reported in the LabelStorageInformation return + data. + @retval EFI_ACCESS_DENIED The Label Storage Area for the NVDIMM device is not currently accessible and labels + cannot be read at this time. + @retval EFI_DEVICE_ERROR A physical device error occurred and the data transfer failed to complete. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVDIMM_LABEL_STORAGE_READ) ( + IN CONST EFI_NVDIMM_LABEL_PROTOCOL *This, + IN UINT32 Offset, + IN UINT32 TransferLength, + OUT UINT8 *LabelData + ); + +/** + Writes the label data for the requested offset and length in to the Label Storage Area for the NVDIMM. + + @param This A pointer to the EFI_NVDIMM_LABEL_PROTOCOL instance. + @param Offset The byte offset within the Label Storage Area to write to. + @param TransferLength Number of bytes to write to the Label Storage Area beginning at the byte + Offset specified. A TransferLength of 0 writes no data. + @param LabelData The return label data write at the requested offset and length from within + the Label Storage Area. + + @retval EFI_SUCCESS The label data from the Label Storage Area for the NVDIMM written read successfully + at the specified Offset and TransferLength. + @retval EFI_INVALID_PARAMETER Any of the following are true: + - Offset > SizeOfLabelStorageArea reported in the LabelStorageInformation return data. + - Offset + TransferLength is > SizeOfLabelStorageArea reported in the + LabelStorageInformation return data. + - TransferLength is > MaxTransferLength reported in the LabelStorageInformation return + data. + @retval EFI_ACCESS_DENIED The Label Storage Area for the NVDIMM device is not currently accessible and labels + cannot be written at this time. + @retval EFI_DEVICE_ERROR A physical device error occurred and the data transfer failed to complete. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVDIMM_LABEL_STORAGE_WRITE) ( + IN CONST EFI_NVDIMM_LABEL_PROTOCOL *This, + IN UINT32 Offset, + IN UINT32 TransferLength, + IN UINT8 *LabelData + ); + +/// +/// Provides services that allow management of labels contained in a Label Storage Area. +/// +struct _EFI_NVDIMM_LABEL_PROTOCOL { + EFI_NVDIMM_LABEL_STORAGE_INFORMATION LabelStorageInformation; + EFI_NVDIMM_LABEL_STORAGE_READ LabelStorageRead; + EFI_NVDIMM_LABEL_STORAGE_WRITE LabelStorageWrite; +}; + +extern EFI_GUID gEfiNvdimmLabelProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvmExpressPassthru.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvmExpressPassthru.h new file mode 100644 index 0000000..38c896f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/NvmExpressPassthru.h @@ -0,0 +1,289 @@ +/** @file + This protocol provides services that allow NVM Express commands to be sent to an + NVM Express controller or to a specific namespace in a NVM Express controller. + This protocol interface is optimized for storage. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.5. + +**/ + +#ifndef _UEFI_NVM_EXPRESS_PASS_THRU_H_ +#define _UEFI_NVM_EXPRESS_PASS_THRU_H_ + +#define EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL_GUID \ + { \ + 0x52c78312, 0x8edc, 0x4233, { 0x98, 0xf2, 0x1a, 0x1a, 0xa5, 0xe3, 0x88, 0xa5 } \ + } + +typedef struct _EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL; + +typedef struct { + UINT32 Attributes; + UINT32 IoAlign; + UINT32 NvmeVersion; +} EFI_NVM_EXPRESS_PASS_THRU_MODE; + +// +// If this bit is set, then the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL interface is +// for directly addressable namespaces. +// +#define EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001 +// +// If this bit is set, then the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL interface is +// for a single volume logical namespace comprised of multiple namespaces. +// +#define EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002 +// +// If this bit is set, then the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL interface +// supports non-blocking I/O. +// +#define EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004 +// +// If this bit is set, then the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL interface +// supports NVM command set. +// +#define EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM 0x0008 + +// +// FusedOperation +// +#define NORMAL_CMD 0x00 +#define FUSED_FIRST_CMD 0x01 +#define FUSED_SECOND_CMD 0x02 + +typedef struct { + UINT32 Opcode:8; + UINT32 FusedOperation:2; + UINT32 Reserved:22; +} NVME_CDW0; + +// +// Flags +// +#define CDW2_VALID 0x01 +#define CDW3_VALID 0x02 +#define CDW10_VALID 0x04 +#define CDW11_VALID 0x08 +#define CDW12_VALID 0x10 +#define CDW13_VALID 0x20 +#define CDW14_VALID 0x40 +#define CDW15_VALID 0x80 + +// +// Queue Type +// +#define NVME_ADMIN_QUEUE 0x00 +#define NVME_IO_QUEUE 0x01 + +typedef struct { + NVME_CDW0 Cdw0; + UINT8 Flags; + UINT32 Nsid; + UINT32 Cdw2; + UINT32 Cdw3; + UINT32 Cdw10; + UINT32 Cdw11; + UINT32 Cdw12; + UINT32 Cdw13; + UINT32 Cdw14; + UINT32 Cdw15; +} EFI_NVM_EXPRESS_COMMAND; + +typedef struct { + UINT32 DW0; + UINT32 DW1; + UINT32 DW2; + UINT32 DW3; +} EFI_NVM_EXPRESS_COMPLETION; + +typedef struct { + UINT64 CommandTimeout; + VOID *TransferBuffer; + UINT32 TransferLength; + VOID *MetadataBuffer; + UINT32 MetadataLength; + UINT8 QueueType; + EFI_NVM_EXPRESS_COMMAND *NvmeCmd; + EFI_NVM_EXPRESS_COMPLETION *NvmeCompletion; +} EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET; + +// +// Protocol function prototypes +// +/** + Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports + both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking + I/O functionality is optional. + + + @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. + @param[in] NamespaceId A 32 bit namespace ID as defined in the NVMe specification to which the NVM Express Command + Packet will be sent. A value of 0 denotes the NVM Express controller, a value of all 0xFF's + (all bytes are 0xFF) in the namespace ID specifies that the command packet should be sent to + all valid namespaces. + @param[in,out] Packet A pointer to the NVM Express Command Packet. + @param[in] Event If non-blocking I/O is not supported 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 NVM + Express Command Packet completes. + + @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred + to, or from DataBuffer. + @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred + is returned in TransferLength. + @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller + may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet. + @retval EFI_INVALID_PARAMETER NamespaceId or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM + Express Command Packet was not sent, so no additional status information is available. + @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the NVM Express + controller. The NVM Express Command Packet was not sent so no additional status information + is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVM_EXPRESS_PASS_THRU_PASSTHRU)( + IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, + IN UINT32 NamespaceId, + IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ); + +/** + Used to retrieve the next namespace ID for this NVM Express controller. + + The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves the next valid + namespace ID on this NVM Express controller. + + If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first valid namespace + ID defined on the NVM Express controller is returned in the location pointed to by NamespaceId + and a status of EFI_SUCCESS is returned. + + If on input the value pointed to by NamespaceId is an invalid namespace ID other than 0xFFFFFFFF, + then EFI_INVALID_PARAMETER is returned. + + If on input the value pointed to by NamespaceId is a valid namespace ID, then the next valid + namespace ID on the NVM Express controller is returned in the location pointed to by NamespaceId, + and EFI_SUCCESS is returned. + + If the value pointed to by NamespaceId is the namespace ID of the last namespace on the NVM + Express controller, then EFI_NOT_FOUND is returned. + + @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. + @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express + namespace present on the NVM Express controller. On output, a + pointer to the next NamespaceId of an NVM Express namespace on + an NVM Express controller. An input value of 0xFFFFFFFF retrieves + the first NamespaceId for an NVM Express namespace present on an + NVM Express controller. + + @retval EFI_SUCCESS The Namespace ID of the next Namespace was returned. + @retval EFI_NOT_FOUND There are no more namespaces defined on this controller. + @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than 0xFFFFFFFF. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVM_EXPRESS_PASS_THRU_GET_NEXT_NAMESPACE)( + IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *NamespaceId + ); + +/** + Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller. + + The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device + path node for the NVM Express namespace specified by NamespaceId. + + If the NamespaceId is not valid, then EFI_NOT_FOUND is returned. + + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. + + If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned. + + Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are + initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. + @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be + allocated and built. Caller must set the NamespaceId to zero if the + device path node will contain a valid UUID. + @param[in,out] DevicePath A pointer to a single device path node that describes the NVM Express + namespace specified by NamespaceId. This function is responsible for + allocating the buffer DevicePath with the boot service AllocatePool(). + It is the caller's responsibility to free DevicePath when the caller + is finished with DevicePath. + @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified + by NamespaceId was allocated and returned in DevicePath. + @retval EFI_NOT_FOUND The NamespaceId is not valid. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVM_EXPRESS_PASS_THRU_BUILD_DEVICE_PATH)( + IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, + IN UINT32 NamespaceId, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Used to translate a device path node to a namespace ID. + + The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamespace() function determines the namespace ID associated with the + namespace described by DevicePath. + + If DevicePath is a device path node type that the NVM Express Pass Thru driver supports, then the NVM Express + Pass Thru driver will attempt to translate the contents DevicePath into a namespace ID. + + If this translation is successful, then that namespace ID is returned in NamespaceId, and EFI_SUCCESS is returned + + @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. + @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on + the NVM Express controller. + @param[out] NamespaceId The NVM Express namespace ID contained in the device path node. + + @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId. + @retval EFI_INVALID_PARAMETER If DevicePath or NamespaceId are NULL, then EFI_INVALID_PARAMETER is returned. + @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver + supports, then EFI_UNSUPPORTED is returned. + @retval EFI_NOT_FOUND If DevicePath is a device path node type that the NVM Express Pass Thru driver + supports, but there is not a valid translation from DevicePath to a namespace ID, + then EFI_NOT_FOUND is returned. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NVM_EXPRESS_PASS_THRU_GET_NAMESPACE)( + IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *NamespaceId + ); + +// +// Protocol Interface Structure +// +struct _EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL { + EFI_NVM_EXPRESS_PASS_THRU_MODE *Mode; + EFI_NVM_EXPRESS_PASS_THRU_PASSTHRU PassThru; + EFI_NVM_EXPRESS_PASS_THRU_GET_NEXT_NAMESPACE GetNextNamespace; + EFI_NVM_EXPRESS_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_NVM_EXPRESS_PASS_THRU_GET_NAMESPACE GetNamespace; +}; + +extern EFI_GUID gEfiNvmExpressPassThruProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PartitionInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PartitionInfo.h new file mode 100644 index 0000000..9e67748 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PartitionInfo.h @@ -0,0 +1,74 @@ +/** @file + This file defines the EFI Partition Information Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __PARTITION_INFO_PROTOCOL_H__ +#define __PARTITION_INFO_PROTOCOL_H__ + +#include +#include + +// +// EFI Partition Information Protocol GUID value +// +#define EFI_PARTITION_INFO_PROTOCOL_GUID \ + { 0x8cf2f62c, 0xbc9b, 0x4821, { 0x80, 0x8d, 0xec, 0x9e, 0xc4, 0x21, 0xa1, 0xa0 }}; + + +#define EFI_PARTITION_INFO_PROTOCOL_REVISION 0x0001000 +#define PARTITION_TYPE_OTHER 0x00 +#define PARTITION_TYPE_MBR 0x01 +#define PARTITION_TYPE_GPT 0x02 + +#pragma pack(1) + +/// +/// Partition Information Protocol structure. +/// +typedef struct { + // + // Set to EFI_PARTITION_INFO_PROTOCOL_REVISION. + // + UINT32 Revision; + // + // Partition info type (PARTITION_TYPE_MBR, PARTITION_TYPE_GPT, or PARTITION_TYPE_OTHER). + // + UINT32 Type; + // + // If 1, partition describes an EFI System Partition. + // + UINT8 System; + UINT8 Reserved[7]; + union { + /// + /// MBR data + /// + MBR_PARTITION_RECORD Mbr; + /// + /// GPT data + /// + EFI_PARTITION_ENTRY Gpt; + } Info; +} EFI_PARTITION_INFO_PROTOCOL; + +#pragma pack() + +/// +/// Partition Information Protocol GUID variable. +/// +extern EFI_GUID gEfiPartitionInfoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pcd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pcd.h new file mode 100644 index 0000000..1f7301d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pcd.h @@ -0,0 +1,867 @@ +/** @file + Native Platform Configuration Database (PCD) Protocol + + Different with the EFI_PCD_PROTOCOL defined in PI 1.2 specification, the native + PCD protocol provide interfaces for dynamic and dynamic-ex type PCD. + The interfaces in dynamic type PCD do not require the token space guid as parameter, + but interfaces in dynamic-ex type PCD require token space guid as parameter. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.2. + +**/ + +#ifndef __PCD_H__ +#define __PCD_H__ + +extern EFI_GUID gPcdProtocolGuid; + +#define PCD_PROTOCOL_GUID \ + { 0x11b34006, 0xd85b, 0x4d0a, { 0xa2, 0x90, 0xd5, 0xa5, 0x71, 0x31, 0xe, 0xf7 } } + +#define PCD_INVALID_TOKEN_NUMBER ((UINTN) 0) + + +/** + Sets the SKU value for subsequent calls to set or get PCD token values. + + SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values. + SetSku() is normally called only once by the system. + + For each item (token), the database can hold a single value that applies to all SKUs, + or multiple values, where each value is associated with a specific SKU Id. Items with multiple, + SKU-specific values are called SKU enabled. + + The SKU Id of zero is reserved as a default. The valid SkuId range is 1 to 255. + For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the + single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the + last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token, + the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been + set for that Id, the results are unpredictable. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + +**/ +typedef +VOID +(EFIAPI *PCD_PROTOCOL_SET_SKU)( + IN UINTN SkuId + ); + + + +/** + Retrieves an 8-bit value for a given PCD token. + + Retrieves the current byte-sized value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT8 value. + +**/ +typedef +UINT8 +(EFIAPI *PCD_PROTOCOL_GET8)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 16-bit value for a given PCD token. + + Retrieves the current 16-bit value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT16 value. + +**/ +typedef +UINT16 +(EFIAPI *PCD_PROTOCOL_GET16)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 32-bit value for a given PCD token. + + Retrieves the current 32-bit value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT32 value. + +**/ +typedef +UINT32 +(EFIAPI *PCD_PROTOCOL_GET32)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 64-bit value for a given PCD token. + + Retrieves the current 64-bit value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The UINT64 value. + +**/ +typedef +UINT64 +(EFIAPI *PCD_PROTOCOL_GET64)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a pointer to a value for a given PCD token. + + Retrieves the current pointer to the buffer for a PCD token number. + Do not make any assumptions about the alignment of the pointer that + is returned by this function call. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The pointer to the buffer to be retrived. + +**/ +typedef +VOID * +(EFIAPI *PCD_PROTOCOL_GET_POINTER)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves a Boolean value for a given PCD token. + + Retrieves the current boolean value for a PCD token number. + Do not make any assumptions about the alignment of the pointer that + is returned by this function call. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The Boolean value. + +**/ +typedef +BOOLEAN +(EFIAPI *PCD_PROTOCOL_GET_BOOLEAN)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves the size of the value for a given PCD token. + + Retrieves the current size of a particular PCD token. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] TokenNumber The PCD token number. + + @return The size of the value for the PCD token. + +**/ +typedef +UINTN +(EFIAPI *PCD_PROTOCOL_GET_SIZE)( + IN UINTN TokenNumber + ); + + + +/** + Retrieves an 8-bit value for a given PCD token. + + Retrieves the 8-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 8-bit value for the PCD token. + +**/ +typedef +UINT8 +(EFIAPI *PCD_PROTOCOL_GET_EX_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 16-bit value for a given PCD token. + + Retrieves the 16-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 16-bit value for the PCD token. + +**/ +typedef +UINT16 +(EFIAPI *PCD_PROTOCOL_GET_EX_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a 32-bit value for a given PCD token. + + Retrieves the 32-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 32-bit value for the PCD token. + +**/ +typedef +UINT32 +(EFIAPI *PCD_PROTOCOL_GET_EX_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves an 64-bit value for a given PCD token. + + Retrieves the 64-bit value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size 64-bit value for the PCD token. + +**/ +typedef +UINT64 +(EFIAPI *PCD_PROTOCOL_GET_EX_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a pointer to a value for a given PCD token. + + Retrieves the current pointer to the buffer for a PCD token number. + Do not make any assumptions about the alignment of the pointer that + is returned by this function call. If the TokenNumber is invalid, + the results are unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The pointer to the buffer to be retrieved. + +**/ +typedef +VOID * +(EFIAPI *PCD_PROTOCOL_GET_EX_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves a Boolean value for a given PCD token. + + Retrieves the Boolean value of a particular PCD token. + If the TokenNumber is invalid or the token space + specified by Guid does not exist, the results are + unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size Boolean value for the PCD token. + +**/ +typedef +BOOLEAN +(EFIAPI *PCD_PROTOCOL_GET_EX_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Retrieves the size of the value for a given PCD token. + + Retrieves the current size of a particular PCD token. + If the TokenNumber is invalid, the results are unpredictable. + + @param[in] Guid The token space for the token number. + @param[in] TokenNumber The PCD token number. + + @return The size of the value for the PCD token. + +**/ +typedef +UINTN +(EFIAPI *PCD_PROTOCOL_GET_EX_SIZE)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + + + +/** + Sets an 8-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET8)( + IN UINTN TokenNumber, + IN UINT8 Value + ); + + + +/** + Sets a 16-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET16)( + IN UINTN TokenNumber, + IN UINT16 Value + ); + + + +/** + Sets a 32-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET32)( + IN UINTN TokenNumber, + IN UINT32 Value + ); + + + +/** + Sets a 64-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET64)( + IN UINTN TokenNumber, + IN UINT64 Value + ); + + + +/** + Sets a value of a specified size for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token. + On input, if the SizeOfValue is greater than the maximum size supported + for this TokenNumber then the output value of SizeOfValue will reflect + the maximum size supported for this TokenNumber. + @param[in] Buffer The buffer to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_POINTER)( + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ); + + + +/** + Sets a Boolean value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @param[in] TokenNumber The PCD token number. + @param[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_BOOLEAN)( + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + + + +/** + Sets an 8-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ); + + + +/** + Sets an 16-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ); + + + +/** + Sets a 32-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ); + + + +/** + Sets a 64-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ); + + + +/** + Sets a value of a specified size for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token. + On input, if the SizeOfValue is greater than the maximum size supported + for this TokenNumber then the output value of SizeOfValue will reflect + the maximum size supported for this TokenNumber. + @param[in] Buffer The buffer to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfBuffer, + IN VOID *Buffer + ); + + + +/** + Sets a Boolean value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the + size of the value being set is compatible with the Token's existing definition. + If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The procedure returned successfully. + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data + being set was incompatible with a call to this function. + Use GetSize() to retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + + + +/** + Callback on SET function prototype definition. + + This notification function serves two purposes. + Firstly, it notifies the module which did the registration that the value + of this PCD token has been set. Secondly, it provides a mechanism for the + module that did the registration to intercept the set operation and override + the value that has been set, if necessary. After the invocation of the callback function, + TokenData will be used by PCD service DXE driver to modify the internal data in + PCD database. + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in, out] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + + @retval VOID + +**/ +typedef +VOID +(EFIAPI *PCD_PROTOCOL_CALLBACK)( + IN CONST EFI_GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN OUT VOID *TokenData, + IN UINTN TokenDataSize + ); + + + +/** + Specifies a function to be called anytime the value of a designated token is changed. + + @param[in] TokenNumber The PCD token number. + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event + for the CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_CALLBACK_ONSET)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ); + + + +/** + Cancels a previously set callback function for a particular PCD token number. + + @param[in] TokenNumber The PCD token number. + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event + for the CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_CANCEL_CALLBACK)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ); + + + +/** + Retrieves the next valid token number in a given namespace. + + This is useful since the PCD infrastructure contains a sparse list of token numbers, + and one cannot a priori know what token numbers are valid in the database. + + If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned. + If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned. + If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned. + If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned. + The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid. + If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned. + If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned. + If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned. + + + @param[in] Guid The 128-bit unique value that designates the namespace from which to retrieve the next token. + This is an optional parameter that may be NULL. If this parameter is NULL, then a request is + being made to retrieve tokens from the default token space. + @param[in,out] TokenNumber + A pointer to the PCD token number to use to find the subsequent token number. + + @retval EFI_SUCCESS The PCD service has retrieved the next valid token number. + @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_GET_NEXT_TOKEN)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ); + + + +/** + Retrieves the next valid PCD token namespace for a given namespace. + + Gets the next valid token namespace for a given namespace. This is useful to traverse the valid + token namespaces on a platform. + + @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token namespace + from which the search will start. On output, it designates the next valid token + namespace on the platform. If *Guid is NULL, then the GUID of the first token + space of the current platform is returned. If the search cannot locate the next valid + token namespace, an error is returned and the value of *Guid is undefined. + + @retval EFI_SUCCESS The PCD service retrieved the value requested. + @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace. + +**/ +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_GET_NEXT_TOKENSPACE)( + IN OUT CONST EFI_GUID **Guid + ); + +/// +/// This service abstracts the ability to set/get Platform Configuration Database (PCD). +/// +typedef struct { + PCD_PROTOCOL_SET_SKU SetSku; + + PCD_PROTOCOL_GET8 Get8; + PCD_PROTOCOL_GET16 Get16; + PCD_PROTOCOL_GET32 Get32; + PCD_PROTOCOL_GET64 Get64; + PCD_PROTOCOL_GET_POINTER GetPtr; + PCD_PROTOCOL_GET_BOOLEAN GetBool; + PCD_PROTOCOL_GET_SIZE GetSize; + + PCD_PROTOCOL_GET_EX_8 Get8Ex; + PCD_PROTOCOL_GET_EX_16 Get16Ex; + PCD_PROTOCOL_GET_EX_32 Get32Ex; + PCD_PROTOCOL_GET_EX_64 Get64Ex; + PCD_PROTOCOL_GET_EX_POINTER GetPtrEx; + PCD_PROTOCOL_GET_EX_BOOLEAN GetBoolEx; + PCD_PROTOCOL_GET_EX_SIZE GetSizeEx; + + PCD_PROTOCOL_SET8 Set8; + PCD_PROTOCOL_SET16 Set16; + PCD_PROTOCOL_SET32 Set32; + PCD_PROTOCOL_SET64 Set64; + PCD_PROTOCOL_SET_POINTER SetPtr; + PCD_PROTOCOL_SET_BOOLEAN SetBool; + + PCD_PROTOCOL_SET_EX_8 Set8Ex; + PCD_PROTOCOL_SET_EX_16 Set16Ex; + PCD_PROTOCOL_SET_EX_32 Set32Ex; + PCD_PROTOCOL_SET_EX_64 Set64Ex; + PCD_PROTOCOL_SET_EX_POINTER SetPtrEx; + PCD_PROTOCOL_SET_EX_BOOLEAN SetBoolEx; + + PCD_PROTOCOL_CALLBACK_ONSET CallbackOnSet; + PCD_PROTOCOL_CANCEL_CALLBACK CancelCallback; + PCD_PROTOCOL_GET_NEXT_TOKEN GetNextToken; + PCD_PROTOCOL_GET_NEXT_TOKENSPACE GetNextTokenSpace; +} PCD_PROTOCOL; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PcdInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PcdInfo.h new file mode 100644 index 0000000..363061e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PcdInfo.h @@ -0,0 +1,108 @@ +/** @file + Native Platform Configuration Database (PCD) INFO PROTOCOL. + + The protocol that provides additional information about items that reside in the PCD database. + + Different with the EFI_GET_PCD_INFO_PROTOCOL defined in PI 1.2.1 specification, + the native PCD INFO PROTOCOL provide interfaces for dynamic and dynamic-ex type PCD. + The interfaces for dynamic type PCD do not require the token space guid as parameter, + but interfaces for dynamic-ex type PCD require token space guid as parameter. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.2. + +**/ + +#ifndef __PCD_INFO_H__ +#define __PCD_INFO_H__ + +extern EFI_GUID gGetPcdInfoProtocolGuid; + +#define GET_PCD_INFO_PROTOCOL_GUID \ + { 0x5be40f57, 0xfa68, 0x4610, { 0xbb, 0xbf, 0xe9, 0xc5, 0xfc, 0xda, 0xd3, 0x65 } } + +/// +/// The forward declaration for GET_PCD_INFO_PROTOCOL. +/// +typedef struct _GET_PCD_INFO_PROTOCOL GET_PCD_INFO_PROTOCOL; + +/** + 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. + + @param[in] TokenNumber The PCD token number. + @param[out] PcdInfo The returned information associated with the requested TokenNumber. + + @retval EFI_SUCCESS The PCD information was returned successfully + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_PCD_INFO_PROTOCOL_GET_INFO) ( + IN UINTN TokenNumber, + OUT EFI_PCD_INFO *PcdInfo +); + +/** + 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. + + @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. + + @retval EFI_SUCCESS The PCD information was returned successfully + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_PCD_INFO_PROTOCOL_GET_INFO_EX) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + OUT EFI_PCD_INFO *PcdInfo +); + +/** + 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. +**/ +typedef +UINTN +(EFIAPI *GET_PCD_INFO_PROTOCOL_GET_SKU) ( + VOID +); + +/// +/// This is the PCD service to use when querying for some additional data that can be contained in the +/// PCD database. +/// +struct _GET_PCD_INFO_PROTOCOL { + /// + /// Retrieve additional information associated with a PCD. + /// + GET_PCD_INFO_PROTOCOL_GET_INFO GetInfo; + GET_PCD_INFO_PROTOCOL_GET_INFO_EX GetInfoEx; + /// + /// Retrieve the currently set SKU Id. + /// + GET_PCD_INFO_PROTOCOL_GET_SKU GetSku; +}; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciEnumerationComplete.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciEnumerationComplete.h new file mode 100644 index 0000000..c817774 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciEnumerationComplete.h @@ -0,0 +1,30 @@ +/** @file + PCI Enumeration Complete Protocol as defined in the PI 1.1 specification. + This protocol indicates that pci enumeration complete + + Copyright (c) 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef _PCI_ENUMERATION_COMPLETE_H_ +#define _PCI_ENUMERATION_COMPLETE_H_ + +#define EFI_PCI_ENUMERATION_COMPLETE_GUID \ + { \ + 0x30cfe3e7, 0x3de1, 0x4586, { 0xbe, 0x20, 0xde, 0xab, 0xa1, 0xb3, 0xb7, 0x93 } \ + } + +extern EFI_GUID gEfiPciEnumerationCompleteProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h new file mode 100644 index 0000000..ffc42cf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h @@ -0,0 +1,428 @@ +/** @file + This file declares PCI Host Bridge Resource Allocation Protocol which + provides the basic interfaces to abstract a PCI host bridge resource allocation. + This protocol is mandatory if the system includes PCI devices. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards. + +**/ + +#ifndef _PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_H_ +#define _PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_H_ + +// +// This file must be included because EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL +// uses EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS +// +#include + +/// +/// Global ID for the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. +/// +#define EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GUID \ + { \ + 0xCF8034BE, 0x6768, 0x4d8b, {0xB7,0x39,0x7C,0xCE,0x68,0x3A,0x9F,0xBE } \ + } + +/// +/// Forward declaration for EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. +/// +typedef struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL; + +/// If this bit is set, then the PCI Root Bridge does not +/// support separate windows for Non-prefetchable and Prefetchable +/// memory. A PCI bus driver needs to include requests for Prefetchable +/// memory in the Non-prefetchable memory pool. +/// +#define EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM 1 + +/// +/// If this bit is set, then the PCI Root Bridge supports +/// 64 bit memory windows. If this bit is not set, +/// the PCI bus driver needs to include requests for 64 bit +/// memory address in the corresponding 32 bit memory pool. +/// +#define EFI_PCI_HOST_BRIDGE_MEM64_DECODE 2 + +/// +/// A UINT64 value that contains the status of a PCI resource requested +/// in the Configuration parameter returned by GetProposedResources() +/// The legal values are EFI_RESOURCE_SATISFIED and EFI_RESOURCE_NOT_SATISFIED +/// +typedef UINT64 EFI_RESOURCE_ALLOCATION_STATUS; + +/// +/// The request of this resource type could be fulfilled. Used in the +/// Configuration parameter returned by GetProposedResources() to identify +/// a PCI resources request that can be satisfied. +/// +#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL + +/// +/// The request of this resource type could not be fulfilled for its +/// absence in the host bridge resource pool. Used in the Configuration parameter +/// returned by GetProposedResources() to identify a PCI resources request that +/// can not be satisfied. +/// +#define EFI_RESOURCE_NOT_SATISFIED 0xFFFFFFFFFFFFFFFFULL + +/// +/// This enum is used to specify the phase of the PCI enumaeration process. +/// +typedef enum { + /// + /// Reset the host bridge PCI apertures and internal data structures. + /// PCI enumerator should issue this notification before starting fresh + /// enumeration process. Enumeration cannot be restarted after sending + /// any other notification such as EfiPciHostBridgeBeginBusAllocation. + /// + EfiPciHostBridgeBeginEnumeration, + + /// + /// The bus allocation phase is about to begin. No specific action + /// is required here. This notification can be used to perform any + /// chipset specific programming. + /// + EfiPciHostBridgeBeginBusAllocation, + + /// + /// The bus allocation and bus programming phase is complete. No specific + /// action is required here. This notification can be used to perform any + /// chipset specific programming. + /// + EfiPciHostBridgeEndBusAllocation, + + /// + /// The resource allocation phase is about to begin.No specific action is + /// required here. This notification can be used to perform any chipset specific programming. + /// + EfiPciHostBridgeBeginResourceAllocation, + + /// + /// Allocate resources per previously submitted requests for all the PCI Root + /// Bridges. These resource settings are returned on the next call to + /// GetProposedResources(). + /// + EfiPciHostBridgeAllocateResources, + + /// + /// Program the Host Bridge hardware to decode previously allocated resources + /// (proposed resources) for all the PCI Root Bridges. + /// + EfiPciHostBridgeSetResources, + + /// + /// De-allocate previously allocated resources previously for all the PCI + /// Root Bridges and reset the I/O and memory apertures to initial state. + /// + EfiPciHostBridgeFreeResources, + + /// + /// The resource allocation phase is completed. No specific action is required + /// here. This notification can be used to perform any chipset specific programming. + /// + EfiPciHostBridgeEndResourceAllocation, + + /// + /// The Host Bridge Enumeration is completed. No specific action is required here. + /// This notification can be used to perform any chipset specific programming. + /// + EfiPciHostBridgeEndEnumeration, + EfiMaxPciHostBridgeEnumerationPhase +} EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE; + +/// +/// Definitions of 2 notification points. +/// +typedef enum { + /// + /// This notification is only applicable to PCI-PCI bridges and + /// indicates that the PCI enumerator is about to begin enumerating + /// the bus behind the PCI-PCI Bridge. This notification is sent after + /// the primary bus number, the secondary bus number and the subordinate + /// bus number registers in the PCI-PCI Bridge are programmed to valid + /// (not necessary final) values + /// + EfiPciBeforeChildBusEnumeration, + + /// + /// This notification is sent before the PCI enumerator probes BAR registers + /// for every valid PCI function. + /// + EfiPciBeforeResourceCollection +} EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE; + +/** + These are the notifications from the PCI bus driver that it is about to enter a certain phase of the PCI + enumeration process. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in] Phase The phase during enumeration. + + @retval EFI_SUCCESS The notification was accepted without any errors. + @retval EFI_INVALID_PARAMETER The Phase is invalid. + @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error + is valid for a Phase of EfiPciHostBridgeAllocateResources if + SubmitResources() has not been called for one or more + PCI root bridges before this call. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid for + a Phase of EfiPciHostBridgeSetResources. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + This error is valid for a Phase of EfiPciHostBridgeAllocateResources + if the previously submitted resource requests cannot be fulfilled or were only + partially fulfilled + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_NOTIFY_PHASE)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase + ); + +/** + Returns the device handle of the next PCI root bridge that is associated with this host bridge. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in,out] RootBridgeHandle Returns the device handle of the next PCI root bridge. On input, it holds the + RootBridgeHandle that was returned by the most recent call to + GetNextRootBridge(). If RootBridgeHandle is NULL on input, the handle + for the first PCI root bridge is returned. + + @retval EFI_SUCCESS The requested attribute information was returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was returned + on a previous call to GetNextRootBridge(). + @retval EFI_NOT_FOUND There are no more PCI root bridge device handles. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_NEXT_ROOT_BRIDGE)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN OUT EFI_HANDLE *RootBridgeHandle + ); + +/** + Returns the allocation attributes of a PCI root bridge. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. + @param[out] Attribute The pointer to attributes of the PCI root bridge. + + @retval EFI_SUCCESS The requested attribute information was returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Attributes is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_ATTRIBUTES)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *Attributes + ); + +/** + Sets up the specified PCI root bridge for the bus enumeration process. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in] RootBridgeHandle The PCI root bridge to be set up. + @param[out] Configuration The pointer to the pointer to the PCI bus resource descriptor. + + @retval EFI_SUCCESS The PCI root bridge was set up and the bus range was returned in + Configuration. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_START_BUS_ENUMERATION)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ); + +/** + Programs the PCI root bridge hardware so that it decodes the specified PCI bus range. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in] RootBridgeHandle The PCI root bridge whose bus range is to be programmed. + @param[in] Configuration The pointer to the PCI bus resource descriptor. + + @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Configuration is NULL + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI (2.0 & 3.0) + resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource + descriptor. + @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI (2.0 & 3.0) resource + descriptors other than bus descriptors. + @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource + descriptors. + @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge. + @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SET_BUS_NUMBERS)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ); + +/** + Submits the I/O and memory resource requirements for the specified PCI root bridge. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being + submitted. + @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor. + + @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were + accepted. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI (2.0 & 3.0) + resource descriptor. + @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource + types that are not supported by this PCI root bridge. This error will + happen if the caller did not combine resources according to + Attributes that were returned by GetAllocAttributes(). + @retval EFI_INVALID_PARAMETER "Address Range Maximum" is invalid. + @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge. + @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SUBMIT_RESOURCES)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ); + +/** + Returns the proposed resource settings for the specified PCI root bridge. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + instance. + @param[in] RootBridgeHandle The PCI root bridge handle. + @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_PROPOSED_RESOURCES)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ); + +/** + Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various + stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual + PCI controllers before enumeration. + + @param[in] This The pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance. + @param[in] RootBridgeHandle The associated PCI root bridge handle. + @param[in] PciAddress The address of the PCI device on the PCI bus. + @param[in] Phase The phase of the PCI device enumeration. + + @retval EFI_SUCCESS The requested parameters were returned. + @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle. + @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in + EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE. + @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator + should not enumerate this device, including its child devices if it is + a PCI-to-PCI bridge. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER)( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase + ); + +/// +/// Provides the basic interfaces to abstract a PCI host bridge resource allocation. +/// +struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL { + /// + /// The notification from the PCI bus enumerator that it is about to enter + /// a certain phase during the enumeration process. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_NOTIFY_PHASE NotifyPhase; + + /// + /// Retrieves the device handle for the next PCI root bridge that is produced by the + /// host bridge to which this instance of the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is attached. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_NEXT_ROOT_BRIDGE GetNextRootBridge; + + /// + /// Retrieves the allocation-related attributes of a PCI root bridge. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_ATTRIBUTES GetAllocAttributes; + + /// + /// Sets up a PCI root bridge for bus enumeration. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_START_BUS_ENUMERATION StartBusEnumeration; + + /// + /// Sets up the PCI root bridge so that it decodes a specific range of bus numbers. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SET_BUS_NUMBERS SetBusNumbers; + + /// + /// Submits the resource requirements for the specified PCI root bridge. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SUBMIT_RESOURCES SubmitResources; + + /// + /// Returns the proposed resource assignment for the specified PCI root bridges. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_PROPOSED_RESOURCES GetProposedResources; + + /// + /// Provides hooks from the PCI bus driver to every PCI controller + /// (device/function) at various stages of the PCI enumeration process that + /// allow the host bridge driver to preinitialize individual PCI controllers + /// before enumeration. + /// + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER PreprocessController; +}; + +extern EFI_GUID gEfiPciHostBridgeResourceAllocationProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugInit.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugInit.h new file mode 100644 index 0000000..76c4ea1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugInit.h @@ -0,0 +1,278 @@ +/** @file + This file declares EFI PCI Hot Plug Init Protocol. + + This protocol provides the necessary functionality to initialize the Hot Plug + Controllers (HPCs) and the buses that they control. This protocol also provides + information regarding resource padding. + + @par Note: + This protocol is required only on platforms that support one or more PCI Hot + Plug* slots or CardBus sockets. + + The EFI_PCI_HOT_PLUG_INIT_PROTOCOL provides a mechanism for the PCI bus enumerator + to properly initialize the HPCs and CardBus sockets that require initialization. + The HPC initialization takes place before the PCI enumeration process is complete. + There cannot be more than one instance of this protocol in a system. This protocol + is installed on its own separate handle. + + Because the system may include multiple HPCs, one instance of this protocol + should represent all of them. The protocol functions use the device path of + the HPC to identify the HPC. When the PCI bus enumerator finds a root HPC, it + will call EFI_PCI_HOT_PLUG_INIT_PROTOCOL.InitializeRootHpc(). If InitializeRootHpc() + is unable to initialize a root HPC, the PCI enumerator will ignore that root HPC + and continue the enumeration process. If the HPC is not initialized, the devices + that it controls may not be initialized, and no resource padding will be provided. + + From the standpoint of the PCI bus enumerator, HPCs are divided into the following + two classes: + + - Root HPC: + These HPCs must be initialized by calling InitializeRootHpc() during the + enumeration process. These HPCs will also require resource padding. The + platform code must have a priori knowledge of these devices and must know + how to initialize them. There may not be any way to access their PCI + configuration space before the PCI enumerator programs all the upstream + bridges and thus enables the path to these devices. The PCI bus enumerator + is responsible for determining the PCI bus address of the HPC before it + calls InitializeRootHpc(). + - Nonroot HPC: + These HPCs will not need explicit initialization during enumeration process. + These HPCs will require resource padding. The platform code does not have + to have a priori knowledge of these devices. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef _EFI_PCI_HOT_PLUG_INIT_H_ +#define _EFI_PCI_HOT_PLUG_INIT_H_ + +/// +/// Global ID for the EFI_PCI_HOT_PLUG_INIT_PROTOCOL +/// +#define EFI_PCI_HOT_PLUG_INIT_PROTOCOL_GUID \ + { \ + 0xaa0e8bc1, 0xdabc, 0x46b0, {0xa8, 0x44, 0x37, 0xb8, 0x16, 0x9b, 0x2b, 0xea } \ + } + +/// +/// Forward declaration for EFI_PCI_HOT_PLUG_INIT_PROTOCOL +/// +typedef struct _EFI_PCI_HOT_PLUG_INIT_PROTOCOL EFI_PCI_HOT_PLUG_INIT_PROTOCOL; + +/// +/// Describes the current state of an HPC +/// +typedef UINT16 EFI_HPC_STATE; + +/// +/// The HPC initialization function was called and the HPC completed +/// initialization, but it was not enabled for some reason. The HPC may be +/// disabled in hardware, or it may be disabled due to user preferences, +/// hardware failure, or other reasons. No resource padding is required. +/// +#define EFI_HPC_STATE_INITIALIZED 0x01 + +/// +/// The HPC initialization function was called, the HPC completed +/// initialization, and it was enabled. Resource padding is required. +/// +#define EFI_HPC_STATE_ENABLED 0x02 + +/// +/// Location definition for PCI Hot Plug Controller +/// +typedef struct{ + /// + /// + /// The device path to the root HPC. An HPC cannot control its parent buses. + /// The PCI bus driver requires this information so that it can pass the + /// correct HpcPciAddress to the InitializeRootHpc() and GetResourcePadding() + /// functions. + /// + EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath; + /// + /// The device path to the Hot Plug Bus (HPB) that is controlled by the root + /// HPC. The PCI bus driver uses this information to check if a particular PCI + /// bus has hot-plug slots. The device path of a PCI bus is the same as the + /// device path of its parent. For Standard(PCI) Hot Plug Controllers (SHPCs) + /// and PCI Express*, HpbDevicePath is the same as HpcDevicePath. + /// + EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath; +} EFI_HPC_LOCATION; + +/// +/// Describes how resource padding should be applied +/// +typedef enum { + /// + /// Apply the padding at a PCI bus level. In other words, the resources + /// that are allocated to the bus containing hot-plug slots are padded by + /// the specified amount. If the hot-plug bus is behind a PCI-to-PCI + /// bridge, the PCI-to-PCI bridge apertures will indicate the padding + /// + EfiPaddingPciBus, + /// + /// Apply the padding at a PCI root bridge level. If a PCI root bridge + /// includes more than one hot-plug bus, the resource padding requests + /// for these buses are added together and the resources that are + /// allocated to the root bridge are padded by the specified amount. This + /// strategy may reduce the total amount of padding, but requires + /// reprogramming of PCI-to-PCI bridges in a hot-add event. If the hotplug + /// bus is behind a PCI-to-PCI bridge, the PCI-to-PCI bridge + /// apertures do not indicate the padding for that bus. + /// + EfiPaddingPciRootBridge +} EFI_HPC_PADDING_ATTRIBUTES; + +/** + Returns a list of root Hot Plug Controllers (HPCs) that require initialization + during the boot process. + + This procedure returns a list of root HPCs. The PCI bus driver must initialize + these controllers during the boot process. The PCI bus driver may or may not be + able to detect these HPCs. If the platform includes a PCI-to-CardBus bridge, it + can be included in this list if it requires initialization. The HpcList must be + self consistent. An HPC cannot control any of its parent buses. Only one HPC can + control a PCI bus. Because this list includes only root HPCs, no HPC in the list + can be a child of another HPC. This policy must be enforced by the + EFI_PCI_HOT_PLUG_INIT_PROTOCOL. The PCI bus driver may not check for such + invalid conditions. The callee allocates the buffer HpcList + + @param[in] This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance. + @param[out] HpcCount The number of root HPCs that were returned. + @param[out] HpcList The list of root HPCs. HpcCount defines the number of + elements in this list. + + @retval EFI_SUCCESS HpcList was returned. + @retval EFI_OUT_OF_RESOURCES HpcList was not returned due to insufficient + resources. + @retval EFI_INVALID_PARAMETER HpcCount is NULL or HpcList is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_ROOT_HPC_LIST)( + IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + OUT UINTN *HpcCount, + OUT EFI_HPC_LOCATION **HpcList + ); + +/** + Initializes one root Hot Plug Controller (HPC). This process may causes + initialization of its subordinate buses. + + This function initializes the specified HPC. At the end of initialization, + the hot-plug slots or sockets (controlled by this HPC) are powered and are + connected to the bus. All the necessary registers in the HPC are set up. For + a Standard (PCI) Hot Plug Controller (SHPC), the registers that must be set + up are defined in the PCI Standard Hot Plug Controller and Subsystem + Specification. + + @param[in] This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance. + @param[in] HpcDevicePath The device path to the HPC that is being initialized. + @param[in] HpcPciAddress The address of the HPC function on the PCI bus. + @param[in] Event The event that should be signaled when the HPC + initialization is complete. Set to NULL if the + caller wants to wait until the entire initialization + process is complete. + @param[out] HpcState The state of the HPC hardware. The state is + EFI_HPC_STATE_INITIALIZED or EFI_HPC_STATE_ENABLED. + + @retval EFI_SUCCESS If Event is NULL, the specific HPC was successfully + initialized. If Event is not NULL, Event will be + signaled at a later time when initialization is complete. + @retval EFI_UNSUPPORTED This instance of EFI_PCI_HOT_PLUG_INIT_PROTOCOL + does not support the specified HPC. + @retval EFI_OUT_OF_RESOURCES Initialization failed due to insufficient + resources. + @retval EFI_INVALID_PARAMETER HpcState is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INITIALIZE_ROOT_HPC)( + IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN UINT64 HpcPciAddress, + IN EFI_EVENT Event, OPTIONAL + OUT EFI_HPC_STATE *HpcState + ); + +/** + Returns the resource padding that is required by the PCI bus that is controlled + by the specified Hot Plug Controller (HPC). + + This function returns the resource padding that is required by the PCI bus that + is controlled by the specified HPC. This member function is called for all the + root HPCs and nonroot HPCs that are detected by the PCI bus enumerator. This + function will be called before PCI resource allocation is completed. This function + must be called after all the root HPCs, with the possible exception of a + PCI-to-CardBus bridge, have completed initialization. + + @param[in] This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance. + @param[in] HpcDevicePath The device path to the HPC. + @param[in] HpcPciAddress The address of the HPC function on the PCI bus. + @param[in] HpcState The state of the HPC hardware. + @param[out] Padding The amount of resource padding that is required by the + PCI bus under the control of the specified HPC. + @param[out] Attributes Describes how padding is accounted for. The padding + is returned in the form of ACPI 2.0 resource descriptors. + + @retval EFI_SUCCESS The resource padding was successfully returned. + @retval EFI_UNSUPPORTED This instance of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL + does not support the specified HPC. + @retval EFI_NOT_READY This function was called before HPC initialization + is complete. + @retval EFI_INVALID_PARAMETER HpcState or Padding or Attributes is NULL. + @retval EFI_OUT_OF_RESOURCES ACPI 2.0 resource descriptors for Padding + cannot be allocated due to insufficient resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_HOT_PLUG_PADDING)( + IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN UINT64 HpcPciAddress, + OUT EFI_HPC_STATE *HpcState, + OUT VOID **Padding, + OUT EFI_HPC_PADDING_ATTRIBUTES *Attributes + ); + +/// +/// This protocol provides the necessary functionality to initialize the +/// Hot Plug Controllers (HPCs) and the buses that they control. This protocol +/// also provides information regarding resource padding. +/// +struct _EFI_PCI_HOT_PLUG_INIT_PROTOCOL { + /// + /// Returns a list of root HPCs and the buses that they control. + /// + EFI_GET_ROOT_HPC_LIST GetRootHpcList; + + /// + /// Initializes the specified root HPC. + /// + EFI_INITIALIZE_ROOT_HPC InitializeRootHpc; + + /// + /// Returns the resource padding that is required by the HPC. + /// + EFI_GET_HOT_PLUG_PADDING GetResourcePadding; +}; + +extern EFI_GUID gEfiPciHotPlugInitProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugRequest.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugRequest.h new file mode 100644 index 0000000..55fa2e4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciHotPlugRequest.h @@ -0,0 +1,170 @@ +/** @file + Provides services to notify the PCI bus driver that some events have happened + in a hot-plug controller (such as a PC Card socket, or PHPC), and to ask the + PCI bus driver to create or destroy handles for PCI-like devices. + + A hot-plug capable PCI bus driver should produce the EFI PCI Hot Plug Request + protocol. When a PCI device or a PCI-like device (for example, 32-bit PC Card) + is installed after PCI bus does the enumeration, the PCI bus driver can be + notified through this protocol. For example, when a 32-bit PC Card is inserted + into the PC Card socket, the PC Card bus driver can call interface of this + protocol to notify PCI bus driver to allocate resource and create handles for + this PC Card. + + The EFI_PCI_HOTPLUG_REQUEST_PROTOCOL is installed by the PCI bus driver on a + separate handle when PCI bus driver starts up. There is only one instance in + the system. Any driver that wants to use this protocol must locate it globally. + The EFI_PCI_HOTPLUG_REQUEST_PROTOCOL allows the driver of hot-plug controller, + for example, PC Card Bus driver, to notify PCI bus driver that an event has + happened in the hot-plug controller, and the PCI bus driver is requested to + create (add) or destroy (remove) handles for the specified PCI-like devices. + For example, when a 32-bit PC Card is inserted, this protocol interface will + be called with an add operation, and the PCI bus driver will enumerate and + start the devices inserted; when a 32-bit PC Card is removed, this protocol + interface will be called with a remove operation, and the PCI bus driver will + stop the devices and destroy their handles. The existence of this protocol + represents the capability of the PCI bus driver. If this protocol exists in + system, it means PCI bus driver is hot-plug capable, thus together with the + effort of PC Card bus driver, hot-plug of PC Card can be supported. Otherwise, + the hot-plug capability is not provided. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef __PCI_HOTPLUG_REQUEST_H_ +#define __PCI_HOTPLUG_REQUEST_H_ + +/// +/// Global ID for EFI_PCI_HOTPLUG_REQUEST_PROTOCOL +/// +#define EFI_PCI_HOTPLUG_REQUEST_PROTOCOL_GUID \ + { \ + 0x19cb87ab, 0x2cb9, 0x4665, {0x83, 0x60, 0xdd, 0xcf, 0x60, 0x54, 0xf7, 0x9d} \ + } + +/// +/// Forward declaration for EFI_PCI_HOTPLUG_REQUEST_PROTOCOL +/// +typedef struct _EFI_PCI_HOTPLUG_REQUEST_PROTOCOL EFI_PCI_HOTPLUG_REQUEST_PROTOCOL; + +/// +/// Enumeration of PCI hot plug operations +/// +typedef enum { + /// + /// The PCI bus driver is requested to create handles for the specified devices. + /// An array of EFI_HANDLE is returned, with a NULL element marking the end of + /// the array. + /// + EfiPciHotPlugRequestAdd, + + /// + /// The PCI bus driver is requested to destroy handles for the specified devices. + /// + EfiPciHotplugRequestRemove +} EFI_PCI_HOTPLUG_OPERATION; + +/** + This function is used to notify PCI bus driver that some events happened in a + hot-plug controller, and the PCI bus driver is requested to start or stop + specified PCI-like devices. + + This function allows the PCI bus driver to be notified to act as requested when + a hot-plug event has happened on the hot-plug controller. Currently, the + operations include add operation and remove operation. If it is a add operation, + the PCI bus driver will enumerate, allocate resources for devices behind the + hot-plug controller, and create handle for the device specified by RemainingDevicePath. + The RemainingDevicePath is an optional parameter. If it is not NULL, only the + specified device is started; if it is NULL, all devices behind the hot-plug + controller are started. The newly created handles of PC Card functions are + returned in the ChildHandleBuffer, together with the number of child handle in + NumberOfChildren. If it is a remove operation, when NumberOfChildren contains + a non-zero value, child handles specified in ChildHandleBuffer are stopped and + destroyed; otherwise, PCI bus driver is notified to stop managing the controller + handle. + + @param[in] This A pointer to the EFI_PCI_HOTPLUG_REQUEST_PROTOCOL + instance. + @param[in] Operation The operation the PCI bus driver is requested + to make. + @param[in] Controller The handle of the hot-plug controller. + @param[in] RemainingDevicePath The remaining device path for the PCI-like + hot-plug device. It only contains device + path nodes behind the hot-plug controller. + It is an optional parameter and only valid + when the Operation is a add operation. If + it is NULL, all devices behind the PC Card + socket are started. + @param[in,out] NumberOfChildren The number of child handles. For an add + operation, it is an output parameter. For + a remove operation, it's an input parameter. + When it contains a non-zero value, children + handles specified in ChildHandleBuffer are + destroyed. Otherwise, PCI bus driver is + notified to stop managing the controller + handle. + @param[in,out] ChildHandleBuffer The buffer which contains the child handles. + For an add operation, it is an output + parameter and contains all newly created + child handles. For a remove operation, it + contains child handles to be destroyed when + NumberOfChildren contains a non-zero value. + It can be NULL when NumberOfChildren is 0. + It's the caller's responsibility to allocate + and free memory for this buffer. + + @retval EFI_SUCCESS The handles for the specified device have been + created or destroyed as requested, and for an + add operation, the new handles are returned in + ChildHandleBuffer. + @retval EFI_INVALID_PARAMETER Operation is not a legal value. + @retval EFI_INVALID_PARAMETER Controller is NULL or not a valid handle. + @retval EFI_INVALID_PARAMETER NumberOfChildren is NULL. + @retval EFI_INVALID_PARAMETER ChildHandleBuffer is NULL while Operation is + remove and NumberOfChildren contains a non-zero + value. + @retval EFI_INVALID_PARAMETER ChildHandleBuffer is NULL while Operation is add. + @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the + devices. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOTPLUG_REQUEST_NOTIFY)( + IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL *This, + IN EFI_PCI_HOTPLUG_OPERATION Operation, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN OUT UINT8 *NumberOfChildren, + IN OUT EFI_HANDLE *ChildHandleBuffer + ); + +/// +/// Provides services to notify PCI bus driver that some events have happened in +/// a hot-plug controller (for example, PC Card socket, or PHPC), and ask PCI bus +/// driver to create or destroy handles for the PCI-like devices. +/// +struct _EFI_PCI_HOTPLUG_REQUEST_PROTOCOL { + /// + /// Notify the PCI bus driver that some events have happened in a hot-plug + /// controller (for example, PC Card socket, or PHPC), and ask PCI bus driver + /// to create or destroy handles for the PCI-like devices. See Section 0 for + /// a detailed description. + /// + EFI_PCI_HOTPLUG_REQUEST_NOTIFY Notify; +}; + +extern EFI_GUID gEfiPciHotPlugRequestProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciIo.h new file mode 100644 index 0000000..5fd989b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciIo.h @@ -0,0 +1,557 @@ +/** @file + EFI PCI I/O Protocol provides the basic Memory, I/O, PCI configuration, + and DMA interfaces that a driver uses to access its PCI controller. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_IO_H__ +#define __PCI_IO_H__ + +/// +/// Global ID for the PCI I/O Protocol +/// +#define EFI_PCI_IO_PROTOCOL_GUID \ + { \ + 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a } \ + } + +typedef struct _EFI_PCI_IO_PROTOCOL EFI_PCI_IO_PROTOCOL; + +/// +/// ******************************************************* +/// EFI_PCI_IO_PROTOCOL_WIDTH +/// ******************************************************* +/// +typedef enum { + EfiPciIoWidthUint8 = 0, + EfiPciIoWidthUint16, + EfiPciIoWidthUint32, + EfiPciIoWidthUint64, + EfiPciIoWidthFifoUint8, + EfiPciIoWidthFifoUint16, + EfiPciIoWidthFifoUint32, + EfiPciIoWidthFifoUint64, + EfiPciIoWidthFillUint8, + EfiPciIoWidthFillUint16, + EfiPciIoWidthFillUint32, + EfiPciIoWidthFillUint64, + EfiPciIoWidthMaximum +} EFI_PCI_IO_PROTOCOL_WIDTH; + +// +// Complete PCI address generater +// +#define EFI_PCI_IO_PASS_THROUGH_BAR 0xff ///< Special BAR that passes a memory or I/O cycle through unchanged +#define EFI_PCI_IO_ATTRIBUTE_MASK 0x077f ///< All the following I/O and Memory cycles +#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 ///< I/O cycles 0x0000-0x00FF (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 ///< I/O cycles 0x0100-0x03FF or greater (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 ///< I/O cycles 0x3C6, 0x3C8, 0x3C9 (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 ///< MEM cycles 0xA0000-0xBFFFF (24 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 ///< I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 ///< I/O cycles 0x1F0-0x1F7, 0x3F6, 0x3F7 (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 ///< I/O cycles 0x170-0x177, 0x376, 0x377 (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 ///< Map a memory range so writes are combined +#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 ///< Enable the I/O decode bit in the PCI Config Header +#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 ///< Enable the Memory decode bit in the PCI Config Header +#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 ///< Enable the DMA bit in the PCI Config Header +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 ///< Map a memory range so all r/w accesses are cached +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 ///< Disable a memory range +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 ///< Clear for an add-in PCI Device +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 ///< Clear for a physical PCI Option ROM accessed through ROM BAR +#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 ///< Clear for PCI controllers that can not genrate a DAC +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 ///< I/O cycles 0x0100-0x03FF or greater (16 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 ///< I/O cycles 0x3C6, 0x3C8, 0x3C9 (16 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 ///< I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (16 bit decode) + +#define EFI_PCI_DEVICE_ENABLE (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) +#define EFI_VGA_DEVICE_ENABLE (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_IO) + +/// +/// ******************************************************* +/// EFI_PCI_IO_PROTOCOL_OPERATION +/// ******************************************************* +/// +typedef enum { + /// + /// A read operation from system memory by a bus master. + /// + EfiPciIoOperationBusMasterRead, + /// + /// A write operation from system memory by a bus master. + /// + EfiPciIoOperationBusMasterWrite, + /// + /// Provides both read and write access to system memory by both the processor and a + /// bus master. The buffer is coherent from both the processor's and the bus master's point of view. + /// + EfiPciIoOperationBusMasterCommonBuffer, + EfiPciIoOperationMaximum +} EFI_PCI_IO_PROTOCOL_OPERATION; + +/// +/// ******************************************************* +/// EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION +/// ******************************************************* +/// +typedef enum { + /// + /// Retrieve the PCI controller's current attributes, and return them in Result. + /// + EfiPciIoAttributeOperationGet, + /// + /// Set the PCI controller's current attributes to Attributes. + /// + EfiPciIoAttributeOperationSet, + /// + /// Enable the attributes specified by the bits that are set in Attributes for this PCI controller. + /// + EfiPciIoAttributeOperationEnable, + /// + /// Disable the attributes specified by the bits that are set in Attributes for this PCI controller. + /// + EfiPciIoAttributeOperationDisable, + /// + /// Retrieve the PCI controller's supported attributes, and return them in Result. + /// + EfiPciIoAttributeOperationSupported, + EfiPciIoAttributeOperationMaximum +} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; + +/** + Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory or I/O operations. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for the memory operation to perform. + @param Offset The offset within the selected BAR to start the memory operation. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_POLL_IO_MEM)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +/** + Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory or I/O operations. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for the memory or I/O operation to perform. + @param Offset The offset within the selected BAR to start the memory or I/O operation. + @param Count The number of memory or I/O operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI BAR specified by BarIndex. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_IO_MEM)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + /// + /// Read PCI controller registers in the PCI memory or I/O space. + /// + EFI_PCI_IO_PROTOCOL_IO_MEM Read; + /// + /// Write PCI controller registers in the PCI memory or I/O space. + /// + EFI_PCI_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_IO_PROTOCOL_ACCESS; + +/** + Enable a PCI driver to access PCI controller registers in PCI configuration space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory operations. + @param Offset The offset within the PCI configuration space for the PCI controller. + @param Count The number of PCI configuration operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + + @retval EFI_SUCCESS The data was read from or written to the PCI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI configuration header of the PCI controller. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_CONFIG)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + /// + /// Read PCI controller registers in PCI configuration space. + /// + EFI_PCI_IO_PROTOCOL_CONFIG Read; + /// + /// Write PCI controller registers in PCI configuration space. + /// + EFI_PCI_IO_PROTOCOL_CONFIG Write; +} EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; + +/** + Enables a PCI driver to copy one region of PCI memory space to another region of PCI + memory space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory operations. + @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the + base address for the memory operation to perform. + @param DestOffset The destination offset within the BAR specified by DestBarIndex to + start the memory writes for the copy operation. + @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the + base address for the memory operation to perform. + @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start + the memory reads for the copy operation. + @param Count The number of memory operations to perform. Bytes moved is Width + size * Count, starting at DestOffset and SrcOffset. + + @retval EFI_SUCCESS The data was copied from one memory region to another memory region. + @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count + is not valid for the PCI BAR specified by DestBarIndex. + @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is + not valid for the PCI BAR specified by SrcBarIndex. + @retval EFI_INVALID_PARAMETER Width is invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_COPY_MEM)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ); + +/** + Provides the PCI controller-specific addresses needed to access system memory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the PCI controller. + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_MAP)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_UNMAP)( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer + or EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Type This parameter is not used and must be ignored. + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @param Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_FREE_BUFFER)( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +/** + Flushes all PCI posted write transactions from a PCI host bridge to system memory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI + host bridge due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_FLUSH)( + IN EFI_PCI_IO_PROTOCOL *This + ); + +/** + Retrieves this PCI controller's current PCI bus number, device number, and function number. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param SegmentNumber The PCI controller's current PCI segment number. + @param BusNumber The PCI controller's current PCI bus number. + @param DeviceNumber The PCI controller's current PCI device number. + @param FunctionNumber The PCI controller's current PCI function number. + + @retval EFI_SUCCESS The PCI controller location was returned. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_LOCATION)( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ); + +/** + Performs an operation on the attributes that this PCI controller supports. The operations include + getting the set of supported attributes, retrieving the current attributes, setting the current + attributes, enabling attributes, and disabling attributes. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Operation The operation to perform on the attributes for this PCI controller. + @param Attributes The mask of attributes that are used for Set, Enable, and Disable + operations. + @param Result A pointer to the result mask of attributes that are returned for the Get + and Supported operations. + + @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED one or more of the bits set in + Attributes are not supported by this PCI controller or one of + its parent bridges when Operation is Set, Enable or Disable. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES)( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ); + +/** + Gets the attributes that this PCI controller supports setting on a BAR using + SetBarAttributes(), and retrieves the list of resource descriptors for a BAR. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for resource range. The legal range for this field is 0..5. + @param Supports A pointer to the mask of attributes that this PCI controller supports + setting for this BAR with SetBarAttributes(). + @param Resources A pointer to the resource descriptors that describe the current + configuration of this BAR of the PCI controller. + + @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI + controller supports are returned in Supports. If Resources + is not NULL, then the resource descriptors that the PCI + controller is currently using are returned in Resources. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate + Resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES)( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ); + +/** + Sets the attributes for a range of a BAR on a PCI controller. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Attributes The mask of attributes to set for the resource range specified by + BarIndex, Offset, and Length. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for resource range. The legal range for this field is 0..5. + @param Offset A pointer to the BAR relative base address of the resource range to be + modified by the attributes specified by Attributes. + @param Length A pointer to the length of the resource range to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource + range specified by BarIndex, Offset, and Length were + set on the PCI controller, and the actual resource range is returned + in Offset and Length. + @retval EFI_INVALID_PARAMETER Offset or Length is NULL. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the + resource range specified by BarIndex, Offset, and + Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES)( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ); + +/// +/// The EFI_PCI_IO_PROTOCOL provides the basic Memory, I/O, PCI configuration, +/// and DMA interfaces used to abstract accesses to PCI controllers. +/// There is one EFI_PCI_IO_PROTOCOL instance for each PCI controller on a PCI bus. +/// A device driver that wishes to manage a PCI controller in a system will have to +/// retrieve the EFI_PCI_IO_PROTOCOL instance that is associated with the PCI controller. +/// +struct _EFI_PCI_IO_PROTOCOL { + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_IO_PROTOCOL_ACCESS Io; + EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; + EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_IO_PROTOCOL_MAP Map; + EFI_PCI_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; + EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; + EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; + + /// + /// The size, in bytes, of the ROM image. + /// + UINT64 RomSize; + + /// + /// A pointer to the in memory copy of the ROM image. The PCI Bus Driver is responsible + /// for allocating memory for the ROM image, and copying the contents of the ROM to memory. + /// The contents of this buffer are either from the PCI option ROM that can be accessed + /// through the ROM BAR of the PCI controller, or it is from a platform-specific location. + /// The Attributes() function can be used to determine from which of these two sources + /// the RomImage buffer was initialized. + /// + VOID *RomImage; +}; + +extern EFI_GUID gEfiPciIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciOverride.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciOverride.h new file mode 100644 index 0000000..c1edcc5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciOverride.h @@ -0,0 +1,46 @@ +/** @file + This file declares EFI PCI Override protocol which provides the interface between + the PCI bus driver/PCI Host Bridge Resource Allocation driver and an implementation's + driver to describe the unique features of a platform. + This protocol is optional. + + Copyright (c) 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef _PCI_OVERRIDE_H_ +#define _PCI_OVERRIDE_H_ + +/// +/// EFI_PCI_OVERRIDE_PROTOCOL has the same structure with EFI_PCI_PLATFORM_PROTOCOL +/// +#include + +/// +/// Global ID for the EFI_PCI_OVERRIDE_PROTOCOL +/// +#define EFI_PCI_OVERRIDE_GUID \ + { \ + 0xb5b35764, 0x460c, 0x4a06, {0x99, 0xfc, 0x77, 0xa1, 0x7c, 0x1b, 0x5c, 0xeb} \ + } + +/// +/// Declaration for EFI_PCI_OVERRIDE_PROTOCOL +/// +typedef EFI_PCI_PLATFORM_PROTOCOL EFI_PCI_OVERRIDE_PROTOCOL; + + +extern EFI_GUID gEfiPciOverrideProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciPlatform.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciPlatform.h new file mode 100644 index 0000000..1e37731 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciPlatform.h @@ -0,0 +1,344 @@ +/** @file + This file declares PlatfromOpRom protocols that provide the interface between + the PCI bus driver/PCI Host Bridge Resource Allocation driver and a platform-specific + driver to describe the unique features of a platform. + This protocol is optional. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is defined in UEFI Platform Initialization Specification 1.2 + Volume 5: Standards + +**/ + +#ifndef _PCI_PLATFORM_H_ +#define _PCI_PLATFORM_H_ + +/// +/// This file must be included because the EFI_PCI_PLATFORM_PROTOCOL uses +/// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE. +/// +#include + +/// +/// Global ID for the EFI_PCI_PLATFORM_PROTOCOL. +/// +#define EFI_PCI_PLATFORM_PROTOCOL_GUID \ + { \ + 0x7d75280, 0x27d4, 0x4d69, {0x90, 0xd0, 0x56, 0x43, 0xe2, 0x38, 0xb3, 0x41} \ + } + +/// +/// Forward declaration for EFI_PCI_PLATFORM_PROTOCOL. +/// +typedef struct _EFI_PCI_PLATFORM_PROTOCOL EFI_PCI_PLATFORM_PROTOCOL; + +/// +/// EFI_PCI_PLATFORM_POLICY that is a bitmask with the following legal combinations: +/// - EFI_RESERVE_NONE_IO_ALIAS:
+/// Does not set aside either ISA or VGA I/O resources during PCI +/// enumeration. By using this selection, the platform indicates that it does +/// not want to support a PCI device that requires ISA or legacy VGA +/// resources. If a PCI device driver asks for these resources, the request +/// will be turned down. +/// - EFI_RESERVE_ISA_IO_ALIAS | EFI_RESERVE_VGA_IO_ALIAS:
+/// Sets aside the ISA I/O range and all the aliases during PCI +/// enumeration. VGA I/O ranges and aliases are included in ISA alias +/// ranges. In this scheme, seventy-five percent of the I/O space remains unused. +/// By using this selection, the platform indicates that it wants to support +/// PCI devices that require the following, at the cost of wasted I/O space: +/// ISA range and its aliases +/// Legacy VGA range and its aliases +/// The PCI bus driver will not allocate I/O addresses out of the ISA I/O +/// range and its aliases. The following are the ISA I/O ranges: +/// - n100..n3FF +/// - n500..n7FF +/// - n900..nBFF +/// - nD00..nFFF +/// +/// In this case, the PCI bus driver will ask the PCI host bridge driver for +/// larger I/O ranges. The PCI host bridge driver is not aware of the ISA +/// aliasing policy and merely attempts to allocate the requested ranges. +/// The first device that requests the legacy VGA range will get all the +/// legacy VGA range plus its aliased addresses forwarded to it. The first +/// device that requests the legacy ISA range will get all the legacy ISA +/// range, plus its aliased addresses, forwarded to it. +/// - EFI_RESERVE_ISA_IO_NO_ALIAS | EFI_RESERVE_VGA_IO_ALIAS:
+/// Sets aside the ISA I/O range (0x100 - 0x3FF) during PCI enumeration +/// and the aliases of the VGA I/O ranges. By using this selection, the +/// platform indicates that it will support VGA devices that require VGA +/// ranges, including those that require VGA aliases. The platform further +/// wants to support non-VGA devices that ask for the ISA range (0x100 - +/// 3FF), but not if it also asks for the ISA aliases. The PCI bus driver will +/// not allocate I/O addresses out of the legacy ISA I/O range (0x100 - +/// 0x3FF) range or the aliases of the VGA I/O range. If a PCI device +/// driver asks for the ISA I/O ranges, including aliases, the request will be +/// turned down. The first device that requests the legacy VGA range will +/// get all the legacy VGA range plus its aliased addresses forwarded to +/// it. When the legacy VGA device asks for legacy VGA ranges and its +/// aliases, all the upstream PCI-to-PCI bridges must be set up to perform +/// 10-bit decode on legacy VGA ranges. To prevent two bridges from +/// positively decoding the same address, all PCI-to-PCI bridges that are +/// peers to this bridge will have to be set up to not decode ISA aliased +/// ranges. In that case, all the devices behind the peer bridges can +/// occupy only I/O addresses that are not ISA aliases. This is a limitation +/// of PCI-to-PCI bridges and is described in the white paper PCI-to-PCI +/// Bridges and Card Bus Controllers on Windows 2000, Windows XP, +/// and Windows Server 2003. The PCI enumeration process must be +/// cognizant of this restriction. +/// - EFI_RESERVE_ISA_IO_NO_ALIAS | EFI_RESERVE_VGA_IO_NO_ALIAS:
+/// Sets aside the ISA I/O range (0x100 - 0x3FF) during PCI enumeration. +/// VGA I/O ranges are included in the ISA range. By using this selection, +/// the platform indicates that it wants to support PCI devices that require +/// the ISA range and legacy VGA range, but it does not want to support +/// devices that require ISA alias ranges or VGA alias ranges. The PCI +/// bus driver will not allocate I/O addresses out of the legacy ISA I/O +/// range (0x100-0x3FF). If a PCI device driver asks for the ISA I/O +/// ranges, including aliases, the request will be turned down. By using +/// this selection, the platform indicates that it will support VGA devices +/// that require VGA ranges, but it will not support VGA devices that +/// require VGA aliases. To truly support 16-bit VGA decode, all the PCIto- +/// PCI bridges that are upstream to a VGA device, as well as +/// upstream to the parent PCI root bridge, must support 16-bit VGA I/O +/// decode. See the PCI-to-PCI Bridge Architecture Specification for +/// information regarding the 16-bit VGA decode support. This +/// requirement must hold true for every VGA device in the system. If any +/// of these bridges does not support 16-bit VGA decode, it will positively +/// decode all the aliases of the VGA I/O ranges and this selection must +/// be treated like EFI_RESERVE_ISA_IO_NO_ALIAS | +/// EFI_RESERVE_VGA_IO_ALIAS. +/// +typedef UINT32 EFI_PCI_PLATFORM_POLICY; + +/// +/// Does not set aside either ISA or VGA I/O resources during PCI +/// enumeration. +/// +#define EFI_RESERVE_NONE_IO_ALIAS 0x0000 + +/// +/// Sets aside ISA I/O range and all aliases: +/// - n100..n3FF +/// - n500..n7FF +/// - n900..nBFF +/// - nD00..nFFF. +/// +#define EFI_RESERVE_ISA_IO_ALIAS 0x0001 + +/// +/// Sets aside ISA I/O range 0x100-0x3FF. +/// +#define EFI_RESERVE_ISA_IO_NO_ALIAS 0x0002 + +/// +/// Sets aside VGA I/O ranges and all aliases. +/// +#define EFI_RESERVE_VGA_IO_ALIAS 0x0004 + +/// +/// Sets aside VGA I/O ranges +/// +#define EFI_RESERVE_VGA_IO_NO_ALIAS 0x0008 + +/// +/// EFI_PCI_EXECUTION_PHASE is used to call a platform protocol and execute +/// platform-specific code. +/// +typedef enum { + /// + /// The phase that indicates the entry point to the PCI Bus Notify phase. This + /// platform hook is called before the PCI bus driver calls the + /// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL driver. + /// + BeforePciHostBridge = 0, + /// + /// The phase that indicates the entry point to the PCI Bus Notify phase. This + /// platform hook is called before the PCI bus driver calls the + /// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL driver. + /// + ChipsetEntry = 0, + /// + /// The phase that indicates the exit point to the Chipset Notify phase before + /// returning to the PCI Bus Driver Notify phase. This platform hook is called after + /// the PCI bus driver calls the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + /// driver. + /// + AfterPciHostBridge = 1, + /// + /// The phase that indicates the exit point to the Chipset Notify phase before + /// returning to the PCI Bus Driver Notify phase. This platform hook is called after + /// the PCI bus driver calls the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL + /// driver. + /// + ChipsetExit = 1, + MaximumChipsetPhase +} EFI_PCI_EXECUTION_PHASE; + +typedef EFI_PCI_EXECUTION_PHASE EFI_PCI_CHIPSET_EXECUTION_PHASE; + +/** + The notification from the PCI bus enumerator to the platform that it is + about to enter a certain phase during the enumeration process. + + The PlatformNotify() function can be used to notify the platform driver so that + it can perform platform-specific actions. No specific actions are required. + Eight notification points are defined at this time. More synchronization points + may be added as required in the future. The PCI bus driver calls the platform driver + twice for every Phase-once before the PCI Host Bridge Resource Allocation Protocol + driver is notified, and once after the PCI Host Bridge Resource Allocation Protocol + driver has been notified. + This member function may not perform any error checking on the input parameters. It + also does not return any error codes. If this member function detects any error condition, + it needs to handle those errors on its own because there is no way to surface any + errors to the caller. + + @param[in] This The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param[in] HostBridge The handle of the host bridge controller. + @param[in] Phase The phase of the PCI bus enumeration. + @param[in] ExecPhase Defines the execution phase of the PCI chipset driver. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_PHASE_NOTIFY)( + IN EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE HostBridge, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase, + IN EFI_PCI_EXECUTION_PHASE ExecPhase + ); + +/** + The notification from the PCI bus enumerator to the platform for each PCI + controller at several predefined points during PCI controller initialization. + + The PlatformPrepController() function can be used to notify the platform driver so that + it can perform platform-specific actions. No specific actions are required. + Several notification points are defined at this time. More synchronization points may be + added as required in the future. The PCI bus driver calls the platform driver twice for + every PCI controller-once before the PCI Host Bridge Resource Allocation Protocol driver + is notified, and once after the PCI Host Bridge Resource Allocation Protocol driver has + been notified. + This member function may not perform any error checking on the input parameters. It also + does not return any error codes. If this member function detects any error condition, it + needs to handle those errors on its own because there is no way to surface any errors to + the caller. + + @param[in] This The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param[in] HostBridge The associated PCI host bridge handle. + @param[in] RootBridge The associated PCI root bridge handle. + @param[in] PciAddress The address of the PCI device on the PCI bus. + @param[in] Phase The phase of the PCI controller enumeration. + @param[in] ExecPhase Defines the execution phase of the PCI chipset driver. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_PREPROCESS_CONTROLLER)( + IN EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE HostBridge, + IN EFI_HANDLE RootBridge, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase, + IN EFI_PCI_EXECUTION_PHASE ExecPhase + ); + +/** + Retrieves the platform policy regarding enumeration. + + The GetPlatformPolicy() function retrieves the platform policy regarding PCI + enumeration. The PCI bus driver and the PCI Host Bridge Resource Allocation Protocol + driver can call this member function to retrieve the policy. + + @param[in] This The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param[out] PciPolicy The platform policy with respect to VGA and ISA aliasing. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER PciPolicy is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_GET_PLATFORM_POLICY)( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy + ); + +/** + Gets the PCI device's option ROM from a platform-specific location. + + The GetPciRom() function gets the PCI device's option ROM from a platform-specific location. + The option ROM will be loaded into memory. This member function is used to return an image + that is packaged as a PCI 2.2 option ROM. The image may contain both legacy and EFI option + ROMs. See the UEFI 2.0 Specification for details. This member function can be used to return + option ROM images for embedded controllers. Option ROMs for embedded controllers are typically + stored in platform-specific storage, and this member function can retrieve it from that storage + and return it to the PCI bus driver. The PCI bus driver will call this member function before + scanning the ROM that is attached to any controller, which allows a platform to specify a ROM + image that is different from the ROM image on a PCI card. + + @param[in] This The pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param[in] PciHandle The handle of the PCI device. + @param[out] RomImage If the call succeeds, the pointer to the pointer to the option ROM image. + Otherwise, this field is undefined. The memory for RomImage is allocated + by EFI_PCI_PLATFORM_PROTOCOL.GetPciRom() using the EFI Boot Service AllocatePool(). + It is the caller's responsibility to free the memory using the EFI Boot Service + FreePool(), when the caller is done with the option ROM. + @param[out] RomSize If the call succeeds, a pointer to the size of the option ROM size. Otherwise, + this field is undefined. + + @retval EFI_SUCCESS The option ROM was available for this device and loaded into memory. + @retval EFI_NOT_FOUND No option ROM was available for this device. + @retval EFI_OUT_OF_RESOURCES No memory was available to load the option ROM. + @retval EFI_DEVICE_ERROR An error occurred in obtaining the option ROM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_GET_PCI_ROM)( + IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, + OUT UINTN *RomSize + ); + +/// +/// This protocol provides the interface between the PCI bus driver/PCI Host +/// Bridge Resource Allocation driver and a platform-specific driver to describe +/// the unique features of a platform. +/// +struct _EFI_PCI_PLATFORM_PROTOCOL { + /// + /// The notification from the PCI bus enumerator to the platform that it is about to + /// enter a certain phase during the enumeration process. + /// + EFI_PCI_PLATFORM_PHASE_NOTIFY PlatformNotify; + /// + /// The notification from the PCI bus enumerator to the platform for each PCI + /// controller at several predefined points during PCI controller initialization. + /// + EFI_PCI_PLATFORM_PREPROCESS_CONTROLLER PlatformPrepController; + /// + /// Retrieves the platform policy regarding enumeration. + /// + EFI_PCI_PLATFORM_GET_PLATFORM_POLICY GetPlatformPolicy; + /// + /// Gets the PCI device's option ROM from a platform-specific location. + /// + EFI_PCI_PLATFORM_GET_PCI_ROM GetPciRom; +}; + +extern EFI_GUID gEfiPciPlatformProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciRootBridgeIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciRootBridgeIo.h new file mode 100644 index 0000000..d3ae151 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PciRootBridgeIo.h @@ -0,0 +1,442 @@ +/** @file + PCI Root Bridge I/O protocol as defined in the UEFI 2.0 specification. + + PCI Root Bridge I/O protocol is used by PCI Bus Driver to perform PCI Memory, PCI I/O, + and PCI Configuration cycles on a PCI Root Bridge. It also provides services to perform + defferent types of bus mastering DMA. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_ROOT_BRIDGE_IO_H__ +#define __PCI_ROOT_BRIDGE_IO_H__ + +#include + +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + { \ + 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +/// +/// ******************************************************* +/// EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH +/// ******************************************************* +/// +typedef enum { + EfiPciWidthUint8, + EfiPciWidthUint16, + EfiPciWidthUint32, + EfiPciWidthUint64, + EfiPciWidthFifoUint8, + EfiPciWidthFifoUint16, + EfiPciWidthFifoUint32, + EfiPciWidthFifoUint64, + EfiPciWidthFillUint8, + EfiPciWidthFillUint16, + EfiPciWidthFillUint32, + EfiPciWidthFillUint64, + EfiPciWidthMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH; + +/// +/// ******************************************************* +/// EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION +/// ******************************************************* +/// +typedef enum { + /// + /// A read operation from system memory by a bus master that is not capable of producing + /// PCI dual address cycles. + /// + EfiPciOperationBusMasterRead, + /// + /// A write operation from system memory by a bus master that is not capable of producing + /// PCI dual address cycles. + /// + EfiPciOperationBusMasterWrite, + /// + /// Provides both read and write access to system memory by both the processor and a bus + /// master that is not capable of producing PCI dual address cycles. + /// + EfiPciOperationBusMasterCommonBuffer, + /// + /// A read operation from system memory by a bus master that is capable of producing PCI + /// dual address cycles. + /// + EfiPciOperationBusMasterRead64, + /// + /// A write operation to system memory by a bus master that is capable of producing PCI + /// dual address cycles. + /// + EfiPciOperationBusMasterWrite64, + /// + /// Provides both read and write access to system memory by both the processor and a bus + /// master that is capable of producing PCI dual address cycles. + /// + EfiPciOperationBusMasterCommonBuffer64, + EfiPciOperationMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION; + +#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 +#define EFI_PCI_ATTRIBUTE_ISA_IO 0x0002 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x0004 +#define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x0008 +#define EFI_PCI_ATTRIBUTE_VGA_IO 0x0010 +#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 +#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 +#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 +#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x0800 +#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x1000 +#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 +#define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 +#define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000 + +#define EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED | EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) + +#define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER) + +#define EFI_PCI_ADDRESS(bus, dev, func, reg) \ + (UINT64) ( \ + (((UINTN) bus) << 24) | \ + (((UINTN) dev) << 16) | \ + (((UINTN) func) << 8) | \ + (((UINTN) (reg)) < 256 ? ((UINTN) (reg)) : (UINT64) (LShiftU64 ((UINT64) (reg), 32)))) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 ExtendedRegister; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS; + +/** + Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory or I/O operations. + @param Address The base address of the memory or I/O operations. + @param Mask Mask used for the polling criteria. + @param Value The comparison value used for the polling exit criteria. + @param Delay The number of 100 ns units to poll. + @param Result Pointer to the last value read from the memory location. + + @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria. + @retval EFI_TIMEOUT Delay expired before a match occurred. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +/** + Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Width Signifies the width of the memory operations. + @param Address The base address of the memory operations. + @param Count The number of memory operations to perform. + @param Buffer For read operations, the destination buffer to store the results. For write + operations, the source buffer to write data from. + + @retval EFI_SUCCESS The data was read from or written to the PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + /// + /// Read PCI controller registers in the PCI root bridge memory space. + /// + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; + /// + /// Write PCI controller registers in the PCI root bridge memory space. + /// + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; + +/** + Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI + root bridge memory space. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. + @param Width Signifies the width of the memory operations. + @param DestAddress The destination address of the memory operation. + @param SrcAddress The source address of the memory operation. + @param Count The number of memory operations to perform. + + @retval EFI_SUCCESS The data was copied from one memory region to another memory region. + @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ); + +/** + Provides the PCI controller-specific addresses required to access system memory from a + DMA bus master. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Operation Indicates if the bus master is going to read or write to system memory. + @param HostAddress The system memory address to map to the PCI controller. + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or + EfiPciOperationBusMasterCommonBuffer64 mapping. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Type This parameter is not used and must be ignored. + @param MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory address of the + allocated range. + @param Attributes The requested bit mask of attributes for the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +/** + Flushes all PCI posted write transactions from a PCI host bridge to system memory. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + + @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host + bridge to system memory. + @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI + host bridge due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ); + +/** + Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the + attributes that a PCI root bridge is currently using. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Supports A pointer to the mask of attributes that this PCI root bridge supports + setting with SetAttributes(). + @param Attributes A pointer to the mask of attributes that this PCI root bridge is currently + using. + + @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root + bridge supports is returned in Supports. If Attributes is + not NULL, then the attributes that the PCI root bridge is currently + using is returned in Attributes. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supports, + OUT UINT64 *Attributes + ); + +/** + Sets attributes for a resource range on a PCI root bridge. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Attributes The mask of attributes to set. + @param ResourceBase A pointer to the base address of the resource range to be modified by the + attributes specified by Attributes. + @param ResourceLength A pointer to the length of the resource range to be modified by the + attributes specified by Attributes. + + @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource + range specified by ResourceBase and ResourceLength + were set on the PCI root bridge, and the actual resource range is + returned in ResuourceBase and ResourceLength. + @retval EFI_UNSUPPORTED A bit is set in Attributes that is not supported by the PCI Root + Bridge. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the + resource range specified by BaseAddress and Length. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ); + +/** + Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI + resource descriptors. + + @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + @param Resources A pointer to the resource descriptors that describe the current + configuration of this PCI root bridge. + + @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in + Resources. + @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be + retrieved. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION)( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ); + +/// +/// Provides the basic Memory, I/O, PCI configuration, and DMA interfaces that are +/// used to abstract accesses to PCI controllers behind a PCI Root Bridge Controller. +/// +struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + /// + /// The EFI_HANDLE of the PCI Host Bridge of which this PCI Root Bridge is a member. + /// + EFI_HANDLE ParentHandle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration; + + /// + /// The segment number that this PCI root bridge resides. + /// + UINT32 SegmentNumber; +}; + +extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcd.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcd.h new file mode 100644 index 0000000..84d2aa4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcd.h @@ -0,0 +1,424 @@ +/** @file + Platform Configuration Database (PCD) Protocol defined in PI 1.2 Vol3 + + A platform database that contains a variety of current platform settings or + directives that can be accessed by a driver or application. + PI PCD protocol only provide the accessing interfaces for Dynamic-Ex type PCD. + + Callers to this protocol must be at a TPL_APPLICATION task priority level. + This is the base PCD service API that provides an abstraction for accessing configuration content in + the platform. It a seamless mechanism for extracting information regardless of where the + information is stored (such as in Read-only data, or an EFI Variable). + This protocol allows access to data through size-granular APIs and provides a mechanism for a + firmware component to monitor specific settings and be alerted when a setting is changed. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2 Vol 3. +**/ + +#ifndef __PI_PCD_H__ +#define __PI_PCD_H__ + +extern EFI_GUID gEfiPcdProtocolGuid; + +#define EFI_PCD_PROTOCOL_GUID \ + { 0x13a3f0f6, 0x264a, 0x3ef0, { 0xf2, 0xe0, 0xde, 0xc5, 0x12, 0x34, 0x2f, 0x34 } } + +#define EFI_PCD_INVALID_TOKEN_NUMBER ((UINTN) 0) + +/** + SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values. SetSku() is + normally called only once by the system. + For each item (token), the database can hold a single value that applies to all SKUs, or multiple + values, where each value is associated with a specific SKU Id. Items with multiple, SKU-specific + values are called SKU enabled. + The SKU Id of zero is reserved as a default. The valid SkuId range is 1 to 255. For tokens that are + not SKU enabled, the system ignores any set SKU Id and works with the single value for that token. + For SKU-enabled tokens, the system will use the SKU Id set by the last call to SetSku(). If no SKU + Id is set or the currently set SKU Id isn't valid for the specified token, the system uses the default + SKU Id. If the system attempts to use the default SKU Id and no value has been set for that Id, the + results are unpredictable. + + @param[in] SkuId The SKU value to set. +**/ +typedef +VOID +(EFIAPI *EFI_PCD_PROTOCOL_SET_SKU)( + IN UINTN SkuId +); + +/** + Retrieves an 8-bit value for a given PCD token. + If the TokenNumber is invalid, the results are unpredictable. + + @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. + + @return 8-bit value for a given PCD token. +**/ +typedef +UINT8 +(EFIAPI *EFI_PCD_PROTOCOL_GET_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current word-sized value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @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. + + @return word-sized value for a given PCD token. +**/ +typedef +UINT16 +(EFIAPI *EFI_PCD_PROTOCOL_GET_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current 32-bit sized value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @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. + + @return 32-bit value for a given PCD token. +**/ +typedef +UINT32 +(EFIAPI *EFI_PCD_PROTOCOL_GET_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the 64-bit sized value for a PCD token number. + If the TokenNumber is invalid, the results are unpredictable. + + @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. + + @return 64-bit value for a given PCD token. + +**/ +typedef +UINT64 +(EFIAPI *EFI_PCD_PROTOCOL_GET_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current pointer to the value for a PCD token number. Do not make any assumptions + about the alignment of the pointer that is returned by this function call. If the TokenNumber is + invalid, the results are unpredictable. + + @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. + + @return pointer to a value for a given PCD token. +**/ +typedef +VOID * +(EFIAPI *EFI_PCD_PROTOCOL_GET_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current BOOLEAN-sized value for a PCD token number. If the TokenNumber is + invalid, the results are unpredictable. + + @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. + + @return Boolean value for a given PCD token. +**/ +typedef +BOOLEAN +(EFIAPI *EFI_PCD_PROTOCOL_GET_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Retrieves the current size of a particular PCD token. If the TokenNumber is invalid, the results are + unpredictable. + + @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. + + @return the size of the value for a given PCD token. +**/ +typedef +UINTN +(EFIAPI *EFI_PCD_PROTOCOL_GET_SIZE)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber +); + +/** + Sets an 8-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_SET_8)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value +); + +/** + Sets an 16-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_SET_16)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value +); + +/** + Sets an 32-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_SET_32)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value +); + +/** + Sets an 64-bit value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_SET_64)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value +); + +/** + Sets a value of a specified size for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @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[in] SizeOfValue The length of the value being set for the PCD token. If too large of a length is + specified, upon return from this function the value of SizeOfValue will + reflect the maximum size for the PCD token. + @param[in] Buffer A pointer to the buffer containing the value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_SET_POINTER)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN OUT UINTN *SizeOfValue, + IN VOID *Buffer +); + +/** + Sets a Boolean value for a given PCD token. + + When the PCD service sets a value, it will check to ensure that the size of the value being set is + compatible with the Token's existing definition. If it is not, an error will be returned. + + @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[in] Value The value to set for the PCD token. + + @retval EFI_SUCCESS The PCD service has set the value requested + @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data being set was + incompatible with a call to this function. Use GetSizeEx() to + retrieve the size of the target data. + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_SET_BOOLEAN)( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value +); + +typedef +VOID +(EFIAPI *EFI_PCD_PROTOCOL_CALLBACK)( + IN EFI_GUID *Guid OPTIONAL, + IN UINTN CallBackToken, + IN OUT VOID *TokenData, + IN UINTN TokenDataSize +); + +/** + Specifies a function to be called anytime the value of a designated token is changed. + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] CallBackToken The PCD token number to monitor. + @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event for the CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_CALLBACK_ON_SET)( + IN CONST EFI_GUID *Guid OPTIONAL, + IN UINTN CallBackToken, + IN EFI_PCD_PROTOCOL_CALLBACK CallBackFunction +); + +/** + Cancels a callback function that was set through a previous call to the CallBackOnSet function. + + @param[in] Guid The 128-bit unique value that designates the namespace from which to extract the value. + @param[in] CallBackToken The PCD token number to monitor. + @param[in] CallBackFunction The function prototype called when the value associated with the CallBackToken is set. + + @retval EFI_SUCCESS The PCD service has successfully established a call event for the CallBackToken requested. + @retval EFI_NOT_FOUND The PCD service could not find the referenced token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_CANCEL_CALLBACK)( + IN CONST EFI_GUID *Guid OPTIONAL, + IN UINTN CallBackToken, + IN EFI_PCD_PROTOCOL_CALLBACK CallBackFunction +); + +/** + Gets the next valid token number in a given namespace. This is useful since the PCD infrastructure + contains a sparse list of token numbers, and one cannot a priori know what token numbers are valid + in the database. + + @param[in] Guid The 128-bit unique value that designates the namespace from which to retrieve the next token. + @param[in] TokenNumber A pointer to the PCD token number to use to find the subsequent token number. To + retrieve the "first" token, have the pointer reference a TokenNumber value of 0. + @retval EFI_SUCCESS The PCD service has retrieved the value requested + @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_GET_NEXT_TOKEN)( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN *TokenNumber +); + +/** + Gets the next valid token namespace for a given namespace. This is useful to traverse the valid + token namespaces on a platform. + + @param[in, out] Guid An indirect pointer to EFI_GUID. On input it designates a known token namespace + from which the search will start. On output, it designates the next valid token + namespace on the platform. If *Guid is NULL, then the GUID of the first token + space of the current platform is returned. If the search cannot locate the next valid + token namespace, an error is returned and the value of *Guid is undefined. + + @retval EFI_SUCCESS The PCD service retrieved the value requested. + @retval EFI_NOT_FOUND The PCD service could not find the next valid token namespace. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCD_PROTOCOL_GET_NEXT_TOKEN_SPACE)( + IN OUT CONST EFI_GUID **Guid +); + +typedef struct _EFI_PCD_PROTOCOL { + EFI_PCD_PROTOCOL_SET_SKU SetSku; + EFI_PCD_PROTOCOL_GET_8 Get8; + EFI_PCD_PROTOCOL_GET_16 Get16; + EFI_PCD_PROTOCOL_GET_32 Get32; + EFI_PCD_PROTOCOL_GET_64 Get64; + EFI_PCD_PROTOCOL_GET_POINTER GetPtr; + EFI_PCD_PROTOCOL_GET_BOOLEAN GetBool; + EFI_PCD_PROTOCOL_GET_SIZE GetSize; + EFI_PCD_PROTOCOL_SET_8 Set8; + EFI_PCD_PROTOCOL_SET_16 Set16; + EFI_PCD_PROTOCOL_SET_32 Set32; + EFI_PCD_PROTOCOL_SET_64 Set64; + EFI_PCD_PROTOCOL_SET_POINTER SetPtr; + EFI_PCD_PROTOCOL_SET_BOOLEAN SetBool; + EFI_PCD_PROTOCOL_CALLBACK_ON_SET CallbackOnSet; + EFI_PCD_PROTOCOL_CANCEL_CALLBACK CancelCallback; + EFI_PCD_PROTOCOL_GET_NEXT_TOKEN GetNextToken; + EFI_PCD_PROTOCOL_GET_NEXT_TOKEN_SPACE GetNextTokenSpace; +} EFI_PCD_PROTOCOL; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcdInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcdInfo.h new file mode 100644 index 0000000..1b39f0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PiPcdInfo.h @@ -0,0 +1,83 @@ +/** @file + Platform Configuration Database (PCD) Info Protocol defined in PI 1.2.1 Vol3. + + The protocol that provides additional information about items that reside in the PCD database. + + Copyright (c) 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + PI Version 1.2.1 Vol 3. +**/ + +#ifndef __PI_PCD_INFO_H__ +#define __PI_PCD_INFO_H__ + +extern EFI_GUID gEfiGetPcdInfoProtocolGuid; + +#define EFI_GET_PCD_INFO_PROTOCOL_GUID \ + { 0xfd0f4478, 0xefd, 0x461d, { 0xba, 0x2d, 0xe5, 0x8c, 0x45, 0xfd, 0x5f, 0x5e } } + +/// +/// The forward declaration for EFI_GET_PCD_INFO_PROTOCOL. +/// +typedef struct _EFI_GET_PCD_INFO_PROTOCOL EFI_GET_PCD_INFO_PROTOCOL; + +/** + 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. + + @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. + + @retval EFI_SUCCESS The PCD information was returned successfully + @retval EFI_NOT_FOUND The PCD service could not find the requested token number. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_PCD_INFO_PROTOCOL_GET_INFO) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + OUT EFI_PCD_INFO *PcdInfo +); + +/** + 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. +**/ +typedef +UINTN +(EFIAPI *EFI_GET_PCD_INFO_PROTOCOL_GET_SKU) ( + VOID +); + +/// +/// Callers to this protocol must be at a TPL_APPLICATION task priority level. +/// This is the PCD service to use when querying for some additional data that can be contained in the +/// PCD database. +/// +struct _EFI_GET_PCD_INFO_PROTOCOL { + /// + /// Retrieve additional information associated with a PCD. + /// + EFI_GET_PCD_INFO_PROTOCOL_GET_INFO GetInfo; + /// + /// Retrieve the currently set SKU Id. + /// + EFI_GET_PCD_INFO_PROTOCOL_GET_SKU GetSku; +}; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pkcs7Verify.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pkcs7Verify.h new file mode 100644 index 0000000..d6751d0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Pkcs7Verify.h @@ -0,0 +1,229 @@ +/** @file + EFI_PKCS7_VERIFY_PROTOCOL as defined in UEFI 2.5. + The EFI_PKCS7_VERIFY_PROTOCOL is used to verify data signed using PKCS#7 + formatted authentication. The PKCS#7 data to be verified must be binary + DER encoded. + PKCS#7 is a general-purpose cryptographic standard (defined by RFC2315, + available at http://tools.ietf.org/html/rfc2315). + +Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_PKCS7_VERIFY_PROTOCOL_H__ +#define __EFI_PKCS7_VERIFY_PROTOCOL_H__ + +#include + +/// +/// Global ID for the PKCS7 Verification Protocol +/// +#define EFI_PKCS7_VERIFY_PROTOCOL_GUID \ + { \ + 0x47889fb2, 0xd671, 0x4fab, {0xa0, 0xca, 0xdf, 0x0e, 0x44, 0xdf, 0x70, 0xd6 } \ + } + +typedef struct _EFI_PKCS7_VERIFY_PROTOCOL EFI_PKCS7_VERIFY_PROTOCOL; + + +/** + Processes a buffer containing binary DER-encoded PKCS7 signature. + The signed data content may be embedded within the buffer or separated. Funtion + verifies the signature of the content is valid and signing certificate was not + revoked and is contained within a list of trusted signers. + + @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance. + @param[in] SignedData Points to buffer containing ASN.1 DER-encoded PKCS7 + signature. + @param[in] SignedDataSize The size of SignedData buffer in bytes. + @param[in] InData In case of detached signature, InData points to + buffer containing the raw message data previously + signed and to be verified by function. In case of + SignedData containing embedded data, InData must be + NULL. + @param[in] InDataSize When InData is used, the size of InData buffer in + bytes. When InData is NULL. This parameter must be + 0. + @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST + structures. The list is terminated by a null + pointer. The EFI_SIGNATURE_LIST structures contain + lists of X.509 certificates of approved signers. + Function recognizes signer certificates of type + EFI_CERT_X509_GUID. Any hash certificate in AllowedDb + list is ignored by this function. Function returns + success if signer of the buffer is within this list + (and not within RevokedDb). This parameter is + required. + @param[in] RevokedDb Optional pointer to a list of pointers to + EFI_SIGNATURE_LIST structures. The list is terminated + by a null pointer. List of X.509 certificates of + revoked signers and revoked file hashes. Except as + noted in description of TimeStampDb signature + verification will always fail if the signer of the + file or the hash of the data component of the buffer + is in RevokedDb list. This list is optional and + caller may pass Null or pointer to NULL if not + required. + @param[in] TimeStampDb Optional pointer to a list of pointers to + EFI_SIGNATURE_LIST structures. The list is terminated + by a null pointer. This parameter can be used to pass + a list of X.509 certificates of trusted time stamp + signers. This list is optional and caller must pass + Null or pointer to NULL if not required. + @param[out] Content On input, points to an optional caller-allocated + buffer into which the function will copy the content + portion of the file after verification succeeds. + This parameter is optional and if NULL, no copy of + content from file is performed. + @param[in,out] ContentSize On input, points to the size in bytes of the optional + buffer Content previously allocated by caller. On + output, if the verification succeeds, the value + referenced by ContentSize will contain the actual + size of the content from signed file. If ContentSize + indicates the caller-allocated buffer is too small + to contain content, an error is returned, and + ContentSize will be updated with the required size. + This parameter must be 0 if Content is Null. + + @retval EFI_SUCCESS Content signature was verified against hash of + content, the signer's certificate was not found in + RevokedDb, and was found in AllowedDb or if in signer + is found in both AllowedDb and RevokedDb, the + signing was allowed by reference to TimeStampDb as + described above, and no hash matching content hash + was found in RevokedDb. + @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but + signer was in RevokedDb or not in AllowedDb. Also + returned if matching content hash found in RevokedDb. + @retval EFI_COMPROMISED_DATA Calculated hash differs from signed hash. + @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero. + AllowedDb is NULL. + @retval EFI_INVALID_PARAMETER Content is not NULL and ContentSize is NULL. + @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb, + RevokedDb or AllowedDb list contents was detected. + @retval EFI_NOT_FOUND Content not found because InData is NULL and no + content embedded in SignedData. + @retval EFI_UNSUPPORTED The SignedData buffer was not correctly formatted + for processing by the function. + @retval EFI_UNSUPPORTED Signed data embedded in SignedData but InData is not + NULL. + @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too + small to hold the content. ContentSize updated to + required size. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PKCS7_VERIFY_BUFFER) ( + IN EFI_PKCS7_VERIFY_PROTOCOL *This, + IN VOID *SignedData, + IN UINTN SignedDataSize, + IN VOID *InData OPTIONAL, + IN UINTN InDataSize, + IN EFI_SIGNATURE_LIST **AllowedDb, + IN EFI_SIGNATURE_LIST **RevokedDb OPTIONAL, + IN EFI_SIGNATURE_LIST **TimeStampDb OPTIONAL, + OUT VOID *Content OPTIONAL, + IN OUT UINTN *ContentSize + ); + +/** + Processes a buffer containing binary DER-encoded detached PKCS7 signature. + The hash of the signed data content is calculated and passed by the caller. Function + verifies the signature of the content is valid and signing certificate was not revoked + and is contained within a list of trusted signers. + + Note: because this function uses hashes and the specification contains a variety of + hash choices, you should be aware that the check against the RevokedDb list + will improperly succeed if the signature is revoked using a different hash + algorithm. For this reason, you should either cycle through all UEFI supported + hashes to see if one is forbidden, or rely on a single hash choice only if the + UEFI signature authority only signs and revokes with a single hash (at time + of writing, this hash choice is SHA256). + + @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance. + @param[in] Signature Points to buffer containing ASN.1 DER-encoded PKCS + detached signature. + @param[in] SignatureSize The size of Signature buffer in bytes. + @param[in] InHash InHash points to buffer containing the caller + calculated hash of the data. The parameter may not + be NULL. + @param[in] InHashSize The size in bytes of InHash buffer. + @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST + structures. The list is terminated by a null + pointer. The EFI_SIGNATURE_LIST structures contain + lists of X.509 certificates of approved signers. + Function recognizes signer certificates of type + EFI_CERT_X509_GUID. Any hash certificate in AllowedDb + list is ignored by this function. Function returns + success if signer of the buffer is within this list + (and not within RevokedDb). This parameter is + required. + @param[in] RevokedDb Optional pointer to a list of pointers to + EFI_SIGNATURE_LIST structures. The list is terminated + by a null pointer. List of X.509 certificates of + revoked signers and revoked file hashes. Signature + verification will always fail if the signer of the + file or the hash of the data component of the buffer + is in RevokedDb list. This parameter is optional + and caller may pass Null if not required. + @param[in] TimeStampDb Optional pointer to a list of pointers to + EFI_SIGNATURE_LIST structures. The list is terminated + by a null pointer. This parameter can be used to pass + a list of X.509 certificates of trusted time stamp + counter-signers. + + @retval EFI_SUCCESS Signed hash was verified against caller-provided + hash of content, the signer's certificate was not + found in RevokedDb, and was found in AllowedDb or + if in signer is found in both AllowedDb and + RevokedDb, the signing was allowed by reference to + TimeStampDb as described above, and no hash matching + content hash was found in RevokedDb. + @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but + signer was in RevokedDb or not in AllowedDb. Also + returned if matching content hash found in RevokedDb. + @retval EFI_COMPROMISED_DATA Caller provided hash differs from signed hash. Or, + caller and encrypted hash are different sizes. + @retval EFI_INVALID_PARAMETER Signature is NULL or SignatureSize is zero. InHash + is NULL or InHashSize is zero. AllowedDb is NULL. + @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb, + RevokedDb or AllowedDb list contents was detected. + @retval EFI_UNSUPPORTED The Signature buffer was not correctly formatted + for processing by the function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PKCS7_VERIFY_SIGNATURE) ( + IN EFI_PKCS7_VERIFY_PROTOCOL *This, + IN VOID *Signature, + IN UINTN SignatureSize, + IN VOID *InHash, + IN UINTN InHashSize, + IN EFI_SIGNATURE_LIST **AllowedDb, + IN EFI_SIGNATURE_LIST **RevokedDb OPTIONAL, + IN EFI_SIGNATURE_LIST **TimeStampDb OPTIONAL + ); + +/// +/// The EFI_PKCS7_VERIFY_PROTOCOL is used to verify data signed using PKCS7 +/// structure. The PKCS7 data to be verified must be ASN.1 (DER) encoded. +/// SHA256 must be supported as digest algorithm with RSA digest encryption. +/// Support of other hash algorithms is optional. +/// +struct _EFI_PKCS7_VERIFY_PROTOCOL { + EFI_PKCS7_VERIFY_BUFFER VerifyBuffer; + EFI_PKCS7_VERIFY_SIGNATURE VerifySignature; +}; + +extern EFI_GUID gEfiPkcs7VerifyProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformDriverOverride.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformDriverOverride.h new file mode 100644 index 0000000..616b80a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformDriverOverride.h @@ -0,0 +1,140 @@ +/** @file + Platform Driver Override protocol as defined in the UEFI 2.1 specification. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_H__ +#define __EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_H__ + +/// +/// Global ID for the Platform Driver Override Protocol +/// +#define EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { \ + 0x6b30c738, 0xa391, 0x11d4, {0x9a, 0x3b, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL; + +// +// Prototypes for the Platform Driver Override Protocol +// + +/** + Retrieves the image handle of the platform override driver for a controller in the system. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller to check if a driver override + exists. + @param DriverImageHandle On input, a pointer to the previous driver image handle returned + by GetDriver(). On output, a pointer to the next driver + image handle. + + @retval EFI_SUCCESS The driver override for ControllerHandle was returned in + DriverImageHandle. + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not found. + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a + previous call to GetDriver(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER)( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE *DriverImageHandle + ); + +/** + Retrieves the device path of the platform override driver for a controller in the system. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance. + @param ControllerHandle The device handle of the controller to check if a driver override + exists. + @param DriverImagePath On input, a pointer to the previous driver device path returned by + GetDriverPath(). On output, a pointer to the next driver + device path. Passing in a pointer to NULL will return the first + driver device path for ControllerHandle. + + @retval EFI_SUCCESS The driver override for ControllerHandle was returned in + DriverImageHandle. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not found. + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER DriverImagePath is not a device path that was returned on a + previous call to GetDriverPath(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH)( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath + ); + +/** + Used to associate a driver image handle with a device path that was returned on a prior call to the + GetDriverPath() service. This driver image handle will then be available through the + GetDriver() service. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller. + @param DriverImagePath A pointer to the driver device path that was returned in a prior + call to GetDriverPath(). + @param DriverImageHandle The driver image handle that was returned by LoadImage() + when the driver specified by DriverImagePath was loaded + into memory. + + @retval EFI_SUCCESS The association between DriverImagePath and + DriverImageHandle was established for the controller specified + by ControllerHandle. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_NOT_FOUND DriverImagePath is not a device path that was returned on a prior + call to GetDriverPath() for the controller specified by + ControllerHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER DriverImagePath is not a valid device path. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a valid image handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED)( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath, + IN EFI_HANDLE DriverImageHandle + ); + +/// +/// This protocol matches one or more drivers to a controller. A platform driver +/// produces this protocol, and it is installed on a separate handle. This protocol +/// is used by the ConnectController() boot service to select the best driver +/// for a controller. All of the drivers returned by this protocol have a higher +/// precedence than drivers found from an EFI Bus Specific Driver Override Protocol +/// or drivers found from the general UEFI driver Binding search algorithm. If more +/// than one driver is returned by this protocol, then the drivers are returned in +/// order from highest precedence to lowest precedence. +/// +struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL { + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER GetDriver; + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH GetDriverPath; + EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED DriverLoaded; +}; + +extern EFI_GUID gEfiPlatformDriverOverrideProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformToDriverConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformToDriverConfiguration.h new file mode 100644 index 0000000..0310d59 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PlatformToDriverConfiguration.h @@ -0,0 +1,355 @@ +/** @file + UEFI Platform to Driver Configuration Protocol is defined in UEFI specification. + + This is a protocol that is optionally produced by the platform and optionally consumed + by a UEFI Driver in its Start() function. This protocol allows the driver to receive + configuration information as part of being started. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PLATFORM_TO_DRIVER_CONFIGUARTION_H__ +#define __PLATFORM_TO_DRIVER_CONFIGUARTION_H__ + +#define EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL_GUID \ + { 0x642cd590, 0x8059, 0x4c0a, { 0xa9, 0x58, 0xc5, 0xec, 0x7, 0xd2, 0x3c, 0x4b } } + + +typedef struct _EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL; + + +/** + The UEFI driver must call Query early in the Start() function + before any time consuming operations are performed. If + ChildHandle is NULL the driver is requesting information from + the platform about the ControllerHandle that is being started. + Information returned from Query may lead to the drivers Start() + function failing. + If the UEFI driver is a bus driver and producing a ChildHandle, + the driver must call Query after the child handle has been created + and an EFI_DEVICE_PATH_PROTOCOL has been placed on that handle, + but before any time consuming operation is performed. If information + return by Query may lead the driver to decide to not create the + ChildHandle. The driver must then cleanup and remove the ChildHandle + from the system. + The UEFI driver repeatedly calls Query, processes the information + returned by the platform, and calls Response passing in the + arguments returned from Query. The Instance value passed into + Response must be the same value passed into the corresponding + call to Query. The UEFI driver must continuously call Query and + Response until EFI_NOT_FOUND is returned by Query. + If the UEFI driver does not recognize the ParameterTypeGuid, it + calls Response with a ConfigurationAction of + EfiPlatformConfigurationActionUnsupportedGuid. The UEFI driver + must then continue calling Query and Response until EFI_NOT_FOUND + is returned by Query. This gives the platform an opportunity to + pass additional configuration settings using a different + ParameterTypeGuid that may be supported by the driver. + An Instance value of zero means return the first ParameterBlock + in the set of unprocessed parameter blocks. The driver should + increment the Instance value by one for each successive call to Query. + + @param This A pointer to the EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL instance. + + @param ControllerHandle The handle the platform will return + configuration information about. + + @param ChildHandle The handle of the child controller to + return information on. This is an optional + parameter that may be NULL. It will be + NULL for device drivers and for bus + drivers that attempt to get options for + the bus controller. It will not be NULL + for a bus driver that attempts to get + options for one of its child controllers. + + + @param Instance Pointer to the Instance value. Zero means + return the first query data. The caller should + increment this value by one each time to retrieve + successive data. + + @param ParameterTypeGuid An EFI_GUID that defines the contents + of ParameterBlock. UEFI drivers must + use the ParameterTypeGuid to determine + how to parse the ParameterBlock. The caller + should not attempt to free ParameterTypeGuid. + + @param ParameterBlock The platform returns a pointer to the + ParameterBlock structure which + contains details about the + configuration parameters specific to + the ParameterTypeGuid. This structure + is defined based on the protocol and + may be different for different + protocols. UEFI driver decodes this + structure and its contents based on + ParameterTypeGuid. ParameterBlock is + allocated by the platform and the + platform is responsible for freeing + the ParameterBlock after Result is + called. + + @param ParameterBlockSize The platform returns the size of + the ParameterBlock in bytes. + + + @retval EFI_SUCCESS The platform return parameter + information for ControllerHandle. + + @retval EFI_NOT_FOUND No more unread Instance exists. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER Instance is NULL. + + @retval EFI_DEVICE_ERROR A device error occurred while + attempting to return parameter block + information for the controller + specified by ControllerHandle and + ChildHandle. + + @retval EFI_OUT_RESOURCES There are not enough resources + available to set the configuration + options for the controller specified + by ControllerHandle and ChildHandle. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_TO_DRIVER_CONFIGURATION_QUERY)( + IN CONST EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL *This, + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE ChildHandle OPTIONAL, + IN CONST UINTN *Instance, + OUT EFI_GUID **ParameterTypeGuid, + OUT VOID **ParameterBlock, + OUT UINTN *ParameterBlockSize +); + +typedef enum { + /// + /// The controller specified by ControllerHandle is still + /// in a usable state, and its configuration has been updated + /// via parsing the ParameterBlock. If required by the + /// parameter block, and the module supports an NVRAM store, + /// the configuration information from PB was successfully + /// saved to the NVRAM. No actions are required before + /// this controller can be used again with the updated + /// configuration settings. + /// + EfiPlatformConfigurationActionNone = 0, + + /// + /// The driver has detected that the controller specified + /// by ControllerHandle is not in a usable state and + /// needs to be stopped. The calling agent can use the + /// DisconnectControservice to perform this operation, and + /// it should be performed as soon as possible. + /// + EfiPlatformConfigurationActionStopController = 1, + + /// + /// This controller specified by ControllerHandle needs to + /// be stopped and restarted before it can be used again. + /// The calling agent can use the DisconnectController() + /// and ConnectController() services to perform this + /// operation. The restart operation can be delayed until + /// all of the configuration options have been set. + /// + EfiPlatformConfigurationActionRestartController = 2, + + /// + /// A configuration change has been made that requires the + /// platform to be restarted before the controller + /// specified by ControllerHandle can be used again. The + /// calling agent can use the ResetSystem() services to + /// perform this operation. The restart operation can be + /// delayed until all of the configuration options have + /// been set. + /// + EfiPlatformConfigurationActionRestartPlatform = 3, + + /// + /// The controller specified by ControllerHandle is still + /// in a usable state; its configuration has been updated + /// via parsing the ParameterBlock. The driver tried to + /// update the driver's private NVRAM store with + /// information from ParameterBlock and failed. No actions + /// are required before this controller can be used again + /// with the updated configuration settings, but these + /// configuration settings are not guaranteed to persist + /// after ControllerHandle is stopped. + /// + EfiPlatformConfigurationActionNvramFailed = 4, + + /// + /// The controller specified by ControllerHandle is still + /// in a usable state; its configuration has not been updated + /// via parsing the ParameterBlock. The driver did not support + /// the ParameterBlock format identified by ParameterTypeGuid. + /// No actions are required before this controller can be used + /// again. On additional Query calls from this ControllerHandle, + /// the platform should stop returning a ParameterBlock + /// qualified by this same ParameterTypeGuid. If no other + /// ParameterTypeGuid is supported by the platform, Query + /// should return EFI_NOT_FOUND. + /// + EfiPlatformConfigurationActionUnsupportedGuid = 5, + EfiPlatformConfigurationActionMaximum +} EFI_PLATFORM_CONFIGURATION_ACTION; + + +/** + The UEFI driver repeatedly calls Query, processes the + information returned by the platform, and calls Response passing + in the arguments returned from Query. The UEFI driver must + continuously call Query until EFI_NOT_FOUND is returned. For + every call to Query that returns EFI_SUCCESS a corrisponding + call to Response is required passing in the same + ContollerHandle, ChildHandle, Instance, ParameterTypeGuid, + ParameterBlock, and ParameterBlockSize. The UEFI driver may + update values in ParameterBlock based on rules defined by + ParameterTypeGuid. The platform is responsible for freeing + ParameterBlock and the UEFI driver must not try to free it. + + @param This A pointer to the EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL instance. + + @param ControllerHandle The handle the driver is returning + configuration information about. + + @param ChildHandle The handle of the child controller to + return information on. This is an optional + parameter that may be NULL. It will be + NULL for device drivers, and for bus + drivers that attempt to get options for + the bus controller. It will not be NULL + for a bus driver that attempts to get + options for one of its child controllers. + Instance Instance data returned from + Query(). + + @param Instance Instance data passed to Query(). + + @param ParameterTypeGuid ParameterTypeGuid returned from Query. + + @param ParameterBlock ParameterBlock returned from Query. + + @param ParameterBlockSize The ParameterBlock size returned from Query. + + @param ConfigurationAction The driver tells the platform what + action is required for ParameterBlock to + take effect. + + + @retval EFI_SUCCESS The platform return parameter information + for ControllerHandle. + + @retval EFI_NOT_FOUND Instance was not found. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER Instance is zero. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_TO_DRIVER_CONFIGURATION_RESPONSE)( + IN CONST EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL *This, + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE ChildHandle OPTIONAL, + IN CONST UINTN *Instance, + IN CONST EFI_GUID *ParameterTypeGuid, + IN CONST VOID *ParameterBlock, + IN CONST UINTN ParameterBlockSize , + IN CONST EFI_PLATFORM_CONFIGURATION_ACTION ConfigurationAction +); + + +/// +/// The EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL is used by the +/// UEFI driver to query the platform for configuration information. +/// The UEFI driver calls Query() multiple times to get +/// configuration information from the platform. For every call to +/// Query() there must be a matching call to Response() so the +/// UEFI driver can inform the platform how it used the +/// information passed in from Query(). It's legal for a UEFI +/// driver to use Response() to inform the platform it does not +/// understand the data returned via Query() and thus no action was +/// taken. +/// +struct _EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL { + EFI_PLATFORM_TO_DRIVER_CONFIGURATION_QUERY Query; + EFI_PLATFORM_TO_DRIVER_CONFIGURATION_RESPONSE Response; +}; + + + +#define EFI_PLATFORM_TO_DRIVER_CONFIGURATION_CLP_GUID \ + {0x345ecc0e, 0xcb6, 0x4b75, { 0xbb, 0x57, 0x1b, 0x12, 0x9c, 0x47, 0x33,0x3e } } + +/** + + ParameterTypeGuid provides the support for parameters + communicated through the DMTF SM CLP Specification 1.0 Final + Standard to be used to configure the UEFI driver. In this + section the producer of the + EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL is platform + firmware and the consumer is the UEFI driver. Note: if future + versions of the DMTF SM CLP Specification require changes to the + parameter block definition, a newer ParameterTypeGuid will be + used. +**/ +typedef struct { + CHAR8 *CLPCommand; ///< A pointer to the null-terminated UTF-8 string that specifies the DMTF SM CLP command + ///< line that the driver is required to parse and process when this function is called. + ///< See the DMTF SM CLP Specification 1.0 Final Standard for details on the + ///< format and syntax of the CLP command line string. CLPCommand buffer + ///< is allocated by the producer of the EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOOL. + UINT32 CLPCommandLength; ///< The length of the CLP Command in bytes. + CHAR8 *CLPReturnString; ///< A pointer to the null-terminated UTF-8 string that indicates the CLP return status + ///< that the driver is required to provide to the calling agent. + ///< The calling agent may parse and/ or pass + ///< this for processing and user feedback. The SM CLP Command Response string + ///< buffer is filled in by the UEFI driver in the "keyword=value" format + ///< described in the SM CLP Specification, unless otherwise requested via the SM + ///< CLP Coutput option in the Command Line string buffer. UEFI driver's support + ///< for this default "keyword=value" output format is required if the UEFI + ///< driver supports this protocol, while support for other SM CLP output + ///< formats is optional (the UEFI Driver should return an EFI_UNSUPPORTED if + ///< the SM CLP Coutput option requested by the caller is not supported by the + ///< UEFI Driver). CLPReturnString buffer is allocated by the consumer of the + ///< EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOC OL and undefined prior to the call to + ///< Response(). + UINT32 CLPReturnStringLength; ///< The length of the CLP return status string in bytes. + UINT8 CLPCmdStatus; ///< SM CLP Command Status (see DMTF SM CLP Specification 1.0 Final Standard - + ///< Table 4) CLPErrorValue SM CLP Processing Error Value (see DMTF SM + ///< CLP Specification 1.0 Final Standard - Table 6). This field is filled in by + ///< the consumer of the EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOC + ///< OL and undefined prior to the call to Response(). + UINT8 CLPErrorValue; ///< SM CLP Processing Error Value (see DMTF SM CLP Specification 1.0 Final Standard - Table 6). + ///< This field is filled in by the consumer of the EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOCOL and undefined prior to the call to Response(). + UINT16 CLPMsgCode; ///< Bit 15: OEM Message Code Flag 0 = Message Code is an SM CLP Probable + ///< Cause Value. (see SM CLP Specification Table 11) 1 = Message Code is OEM + ///< Specific Bits 14-0: Message Code This field is filled in by the consumer of + ///< the EFI_PLATFORM_TO_DRIVER_CONFIGURATION_PROTOC OL and undefined prior to the call to + ///< Response(). + +} EFI_CONFIGURE_CLP_PARAMETER_BLK; + + + +extern EFI_GUID gEfiPlatformToDriverConfigurationClpGuid; + +extern EFI_GUID gEfiPlatformToDriverConfigurationProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCode.h new file mode 100644 index 0000000..798e078 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCode.h @@ -0,0 +1,932 @@ +/** @file + EFI PXE Base Code Protocol definitions, which is used to access PXE-compatible + devices for network access and network booting. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in EFI Specification 1.10. + +**/ +#ifndef __PXE_BASE_CODE_PROTOCOL_H__ +#define __PXE_BASE_CODE_PROTOCOL_H__ + +/// +/// PXE Base Code protocol. +/// +#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ + { \ + 0x03c4e603, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE_PROTOCOL; + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE; + +/// +/// Default IP TTL and ToS. +/// +#define DEFAULT_TTL 16 +#define DEFAULT_ToS 0 + +/// +/// ICMP error format. +/// +typedef struct { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + union { + UINT32 reserved; + UINT32 Mtu; + UINT32 Pointer; + struct { + UINT16 Identifier; + UINT16 Sequence; + } Echo; + } u; + UINT8 Data[494]; +} EFI_PXE_BASE_CODE_ICMP_ERROR; + +/// +/// TFTP error format. +/// +typedef struct { + UINT8 ErrorCode; + CHAR8 ErrorString[127]; +} EFI_PXE_BASE_CODE_TFTP_ERROR; + +/// +/// IP Receive Filter definitions. +/// +#define EFI_PXE_BASE_CODE_MAX_IPCNT 8 + +/// +/// IP Receive Filter structure. +/// +typedef struct { + UINT8 Filters; + UINT8 IpCnt; + UINT16 reserved; + EFI_IP_ADDRESS IpList[EFI_PXE_BASE_CODE_MAX_IPCNT]; +} EFI_PXE_BASE_CODE_IP_FILTER; + +#define EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP 0x0001 +#define EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST 0x0002 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS 0x0004 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST 0x0008 + +/// +/// ARP cache entries. +/// +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_MAC_ADDRESS MacAddr; +} EFI_PXE_BASE_CODE_ARP_ENTRY; + +/// +/// ARP route table entries. +/// +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_IP_ADDRESS SubnetMask; + EFI_IP_ADDRESS GwAddr; +} EFI_PXE_BASE_CODE_ROUTE_ENTRY; + +// +// UDP definitions +// +typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT; + +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP 0x0001 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT 0x0002 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP 0x0004 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT 0x0008 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER 0x0010 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT 0x0020 + +// +// Discover() definitions +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP 0 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_MS_WINNT_RIS 1 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_INTEL_LCM 2 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_DOSUNDI 3 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NEC_ESMPRO 4 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_WSoD 5 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_LCCM 6 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_CA_UNICENTER_TNG 7 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_HP_OPENVIEW 8 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_9 9 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_10 10 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_11 11 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NOT_USED_12 12 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_INSTALL 13 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_BOOT 14 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REMBO 15 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BEOBOOT 16 +// +// 17 through 32767 are reserved +// 32768 through 65279 are for vendor use +// 65280 through 65534 are reserved +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_PXETEST 65535 + +#define EFI_PXE_BASE_CODE_BOOT_LAYER_MASK 0x7FFF +#define EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL 0x0000 + +// +// PXE Tag definition that identifies the processor +// and programming environment of the client system. +// These identifiers are defined by IETF: +// http://www.ietf.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml +// +#if defined (MDE_CPU_IA32) +#define EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE 0x0006 +#elif defined (MDE_CPU_X64) +#define EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE 0x0007 +#elif defined (MDE_CPU_ARM) +#define EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE 0x000A +#elif defined (MDE_CPU_AARCH64) +#define EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE 0x000B +#endif + + +/// +/// Discover() server list structure. +/// +typedef struct { + UINT16 Type; + BOOLEAN AcceptAnyResponse; + UINT8 Reserved; + EFI_IP_ADDRESS IpAddr; +} EFI_PXE_BASE_CODE_SRVLIST; + +/// +/// Discover() information override structure. +/// +typedef struct { + BOOLEAN UseMCast; + BOOLEAN UseBCast; + BOOLEAN UseUCast; + BOOLEAN MustUseList; + EFI_IP_ADDRESS ServerMCastIp; + UINT16 IpCnt; + EFI_PXE_BASE_CODE_SRVLIST SrvList[1]; +} EFI_PXE_BASE_CODE_DISCOVER_INFO; + +/// +/// TFTP opcode definitions. +/// +typedef enum { + EFI_PXE_BASE_CODE_TFTP_FIRST, + EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_TFTP_READ_FILE, + EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, + EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_MTFTP_READ_FILE, + EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_LAST +} EFI_PXE_BASE_CODE_TFTP_OPCODE; + +/// +/// MTFTP information. This information is required +/// to start or join a multicast TFTP session. It is also required to +/// perform the "get file size" and "read directory" operations of MTFTP. +/// +typedef struct { + EFI_IP_ADDRESS MCastIp; + EFI_PXE_BASE_CODE_UDP_PORT CPort; + EFI_PXE_BASE_CODE_UDP_PORT SPort; + UINT16 ListenTimeout; + UINT16 TransmitTimeout; +} EFI_PXE_BASE_CODE_MTFTP_INFO; + +/// +/// DHCPV4 Packet structure. +/// +typedef struct { + UINT8 BootpOpcode; + UINT8 BootpHwType; + UINT8 BootpHwAddrLen; + UINT8 BootpGateHops; + UINT32 BootpIdent; + UINT16 BootpSeconds; + UINT16 BootpFlags; + UINT8 BootpCiAddr[4]; + UINT8 BootpYiAddr[4]; + UINT8 BootpSiAddr[4]; + UINT8 BootpGiAddr[4]; + UINT8 BootpHwAddr[16]; + UINT8 BootpSrvName[64]; + UINT8 BootpBootFile[128]; + UINT32 DhcpMagik; + UINT8 DhcpOptions[56]; +} EFI_PXE_BASE_CODE_DHCPV4_PACKET; + +/// +/// DHCPV6 Packet structure. +/// +typedef struct { + UINT32 MessageType:8; + UINT32 TransactionId:24; + UINT8 DhcpOptions[1024]; +} EFI_PXE_BASE_CODE_DHCPV6_PACKET; + +/// +/// Packet structure. +/// +typedef union { + UINT8 Raw[1472]; + EFI_PXE_BASE_CODE_DHCPV4_PACKET Dhcpv4; + EFI_PXE_BASE_CODE_DHCPV6_PACKET Dhcpv6; +} EFI_PXE_BASE_CODE_PACKET; + +// +// PXE Base Code Mode structure +// +#define EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 +#define EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 + +/// +/// EFI_PXE_BASE_CODE_MODE. +/// The data values in this structure are read-only and +/// are updated by the code that produces the +/// EFI_PXE_BASE_CODE_PROTOCOL functions. +/// +typedef struct { + BOOLEAN Started; + BOOLEAN Ipv6Available; + BOOLEAN Ipv6Supported; + BOOLEAN UsingIpv6; + BOOLEAN BisSupported; + BOOLEAN BisDetected; + BOOLEAN AutoArp; + BOOLEAN SendGUID; + BOOLEAN DhcpDiscoverValid; + BOOLEAN DhcpAckReceived; + BOOLEAN ProxyOfferReceived; + BOOLEAN PxeDiscoverValid; + BOOLEAN PxeReplyReceived; + BOOLEAN PxeBisReplyReceived; + BOOLEAN IcmpErrorReceived; + BOOLEAN TftpErrorReceived; + BOOLEAN MakeCallbacks; + UINT8 TTL; + UINT8 ToS; + EFI_IP_ADDRESS StationIp; + EFI_IP_ADDRESS SubnetMask; + EFI_PXE_BASE_CODE_PACKET DhcpDiscover; + EFI_PXE_BASE_CODE_PACKET DhcpAck; + EFI_PXE_BASE_CODE_PACKET ProxyOffer; + EFI_PXE_BASE_CODE_PACKET PxeDiscover; + EFI_PXE_BASE_CODE_PACKET PxeReply; + EFI_PXE_BASE_CODE_PACKET PxeBisReply; + EFI_PXE_BASE_CODE_IP_FILTER IpFilter; + UINT32 ArpCacheEntries; + EFI_PXE_BASE_CODE_ARP_ENTRY ArpCache[EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + UINT32 RouteTableEntries; + EFI_PXE_BASE_CODE_ROUTE_ENTRY RouteTable[EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; + EFI_PXE_BASE_CODE_ICMP_ERROR IcmpError; + EFI_PXE_BASE_CODE_TFTP_ERROR TftpError; +} EFI_PXE_BASE_CODE_MODE; + +// +// PXE Base Code Interface Function definitions +// + +/** + Enables the use of the PXE Base Code Protocol functions. + + This function enables the use of the PXE Base Code Protocol functions. If the + Started field of the EFI_PXE_BASE_CODE_MODE structure is already TRUE, then + EFI_ALREADY_STARTED will be returned. If UseIpv6 is TRUE, then IPv6 formatted + addresses will be used in this session. If UseIpv6 is FALSE, then IPv4 formatted + addresses will be used in this session. If UseIpv6 is TRUE, and the Ipv6Supported + field of the EFI_PXE_BASE_CODE_MODE structure is FALSE, then EFI_UNSUPPORTED will + be returned. If there is not enough memory or other resources to start the PXE + Base Code Protocol, then EFI_OUT_OF_RESOURCES will be returned. Otherwise, the + PXE Base Code Protocol will be started, and all of the fields of the EFI_PXE_BASE_CODE_MODE + structure will be initialized as follows: + StartedSet to TRUE. + Ipv6SupportedUnchanged. + Ipv6AvailableUnchanged. + UsingIpv6Set to UseIpv6. + BisSupportedUnchanged. + BisDetectedUnchanged. + AutoArpSet to TRUE. + SendGUIDSet to FALSE. + TTLSet to DEFAULT_TTL. + ToSSet to DEFAULT_ToS. + DhcpCompletedSet to FALSE. + ProxyOfferReceivedSet to FALSE. + StationIpSet to an address of all zeros. + SubnetMaskSet to a subnet mask of all zeros. + DhcpDiscoverZero-filled. + DhcpAckZero-filled. + ProxyOfferZero-filled. + PxeDiscoverValidSet to FALSE. + PxeDiscoverZero-filled. + PxeReplyValidSet to FALSE. + PxeReplyZero-filled. + PxeBisReplyValidSet to FALSE. + PxeBisReplyZero-filled. + IpFilterSet the Filters field to 0 and the IpCnt field to 0. + ArpCacheEntriesSet to 0. + ArpCacheZero-filled. + RouteTableEntriesSet to 0. + RouteTableZero-filled. + IcmpErrorReceivedSet to FALSE. + IcmpErrorZero-filled. + TftpErroReceivedSet to FALSE. + TftpErrorZero-filled. + MakeCallbacksSet to TRUE if the PXE Base Code Callback Protocol is available. + Set to FALSE if the PXE Base Code Callback Protocol is not available. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param UseIpv6 Specifies the type of IP addresses that are to be used during the session + that is being started. Set to TRUE for IPv6 addresses, and FALSE for + IPv4 addresses. + + @retval EFI_SUCCESS The PXE Base Code Protocol was started. + @retval EFI_DEVICE_ERROR The network device encountered an error during this oper + @retval EFI_UNSUPPORTED UseIpv6 is TRUE, but the Ipv6Supported field of the + EFI_PXE_BASE_CODE_MODE structure is FALSE. + @retval EFI_ALREADY_STARTED The PXE Base Code Protocol is already in the started state. + @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid + EFI_PXE_BASE_CODE_PROTOCOL structure. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory or other resources to start the + PXE Base Code Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_START)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN UseIpv6 + ); + +/** + Disables the use of the PXE Base Code Protocol functions. + + This function stops all activity on the network device. All the resources allocated + in Start() are released, the Started field of the EFI_PXE_BASE_CODE_MODE structure is + set to FALSE and EFI_SUCCESS is returned. If the Started field of the EFI_PXE_BASE_CODE_MODE + structure is already FALSE, then EFI_NOT_STARTED will be returned. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + + @retval EFI_SUCCESS The PXE Base Code Protocol was stopped. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is already in the stopped state. + @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid + EFI_PXE_BASE_CODE_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_STOP)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This + ); + +/** + Attempts to complete a DHCPv4 D.O.R.A. (discover / offer / request / acknowledge) or DHCPv6 + S.A.R.R (solicit / advertise / request / reply) sequence. + + This function attempts to complete the DHCP sequence. If this sequence is completed, + then EFI_SUCCESS is returned, and the DhcpCompleted, ProxyOfferReceived, StationIp, + SubnetMask, DhcpDiscover, DhcpAck, and ProxyOffer fields of the EFI_PXE_BASE_CODE_MODE + structure are filled in. + If SortOffers is TRUE, then the cached DHCP offer packets will be sorted before + they are tried. If SortOffers is FALSE, then the cached DHCP offer packets will + be tried in the order in which they are received. Please see the Preboot Execution + Environment (PXE) Specification for additional details on the implementation of DHCP. + This function can take at least 31 seconds to timeout and return control to the + caller. If the DHCP sequence does not complete, then EFI_TIMEOUT will be returned. + If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + then the DHCP sequence will be stopped and EFI_ABORTED will be returned. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param SortOffers TRUE if the offers received should be sorted. Set to FALSE to try the + offers in the order that they are received. + + @retval EFI_SUCCESS Valid DHCP has completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid + EFI_PXE_BASE_CODE_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory to complete the DHCP Protocol. + @retval EFI_ABORTED The callback function aborted the DHCP Protocol. + @retval EFI_TIMEOUT The DHCP Protocol timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the DHCP session. + @retval EFI_NO_RESPONSE Valid PXE offer was not received. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_DHCP)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN SortOffers + ); + +/** + Attempts to complete the PXE Boot Server and/or boot image discovery sequence. + + This function attempts to complete the PXE Boot Server and/or boot image discovery + sequence. If this sequence is completed, then EFI_SUCCESS is returned, and the + PxeDiscoverValid, PxeDiscover, PxeReplyReceived, and PxeReply fields of the + EFI_PXE_BASE_CODE_MODE structure are filled in. If UseBis is TRUE, then the + PxeBisReplyReceived and PxeBisReply fields of the EFI_PXE_BASE_CODE_MODE structure + will also be filled in. If UseBis is FALSE, then PxeBisReplyValid will be set to FALSE. + In the structure referenced by parameter Info, the PXE Boot Server list, SrvList[], + has two uses: It is the Boot Server IP address list used for unicast discovery + (if the UseUCast field is TRUE), and it is the list used for Boot Server verification + (if the MustUseList field is TRUE). Also, if the MustUseList field in that structure + is TRUE and the AcceptAnyResponse field in the SrvList[] array is TRUE, any Boot + Server reply of that type will be accepted. If the AcceptAnyResponse field is + FALSE, only responses from Boot Servers with matching IP addresses will be accepted. + This function can take at least 10 seconds to timeout and return control to the + caller. If the Discovery sequence does not complete, then EFI_TIMEOUT will be + returned. Please see the Preboot Execution Environment (PXE) Specification for + additional details on the implementation of the Discovery sequence. + If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + then the Discovery sequence is stopped and EFI_ABORTED will be returned. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param Type The type of bootstrap to perform. + @param Layer The pointer to the boot server layer number to discover, which must be + PXE_BOOT_LAYER_INITIAL when a new server type is being + discovered. + @param UseBis TRUE if Boot Integrity Services are to be used. FALSE otherwise. + @param Info The pointer to a data structure that contains additional information on the + type of discovery operation that is to be performed. + + @retval EFI_SUCCESS The Discovery sequence has been completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory to complete Discovery. + @retval EFI_ABORTED The callback function aborted the Discovery sequence. + @retval EFI_TIMEOUT The Discovery sequence timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the PXE discovery + session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_DISCOVER)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 Type, + IN UINT16 *Layer, + IN BOOLEAN UseBis, + IN EFI_PXE_BASE_CODE_DISCOVER_INFO *Info OPTIONAL + ); + +/** + Used to perform TFTP and MTFTP services. + + This function is used to perform TFTP and MTFTP services. This includes the + TFTP operations to get the size of a file, read a directory, read a file, and + write a file. It also includes the MTFTP operations to get the size of a file, + read a directory, and read a file. The type of operation is specified by Operation. + If the callback function that is invoked during the TFTP/MTFTP operation does + not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, then EFI_ABORTED will + be returned. + For read operations, the return data will be placed in the buffer specified by + BufferPtr. If BufferSize is too small to contain the entire downloaded file, + then EFI_BUFFER_TOO_SMALL will be returned and BufferSize will be set to zero + or the size of the requested file (the size of the requested file is only returned + if the TFTP server supports TFTP options). If BufferSize is large enough for the + read operation, then BufferSize will be set to the size of the downloaded file, + and EFI_SUCCESS will be returned. Applications using the PxeBc.Mtftp() services + should use the get-file-size operations to determine the size of the downloaded + file prior to using the read-file operations--especially when downloading large + (greater than 64 MB) files--instead of making two calls to the read-file operation. + Following this recommendation will save time if the file is larger than expected + and the TFTP server does not support TFTP option extensions. Without TFTP option + extension support, the client has to download the entire file, counting and discarding + the received packets, to determine the file size. + For write operations, the data to be sent is in the buffer specified by BufferPtr. + BufferSize specifies the number of bytes to send. If the write operation completes + successfully, then EFI_SUCCESS will be returned. + For TFTP "get file size" operations, the size of the requested file or directory + is returned in BufferSize, and EFI_SUCCESS will be returned. If the TFTP server + does not support options, the file will be downloaded into a bit bucket and the + length of the downloaded file will be returned. For MTFTP "get file size" operations, + if the MTFTP server does not support the "get file size" option, EFI_UNSUPPORTED + will be returned. + This function can take up to 10 seconds to timeout and return control to the caller. + If the TFTP sequence does not complete, EFI_TIMEOUT will be returned. + If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + then the TFTP sequence is stopped and EFI_ABORTED will be returned. + The format of the data returned from a TFTP read directory operation is a null-terminated + filename followed by a null-terminated information string, of the form + "size year-month-day hour:minute:second" (i.e. %d %d-%d-%d %d:%d:%f - note that + the seconds field can be a decimal number), where the date and time are UTC. For + an MTFTP read directory command, there is additionally a null-terminated multicast + IP address preceding the filename of the form %d.%d.%d.%d for IP v4. The final + entry is itself null-terminated, so that the final information string is terminated + with two null octets. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param Operation The type of operation to perform. + @param BufferPtr A pointer to the data buffer. + @param Overwrite Only used on write file operations. TRUE if a file on a remote server can + be overwritten. + @param BufferSize For get-file-size operations, *BufferSize returns the size of the + requested file. + @param BlockSize The requested block size to be used during a TFTP transfer. + @param ServerIp The TFTP / MTFTP server IP address. + @param Filename A Null-terminated ASCII string that specifies a directory name or a file + name. + @param Info The pointer to the MTFTP information. + @param DontUseBuffer Set to FALSE for normal TFTP and MTFTP read file operation. + + @retval EFI_SUCCESS The TFTP/MTFTP operation was completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_BUFFER_TOO_SMALL The buffer is not large enough to complete the read operation. + @retval EFI_ABORTED The callback function aborted the TFTP/MTFTP operation. + @retval EFI_TIMEOUT The TFTP/MTFTP operation timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the MTFTP session. + @retval EFI_TFTP_ERROR A TFTP error packet was received during the MTFTP session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_MTFTP)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS *ServerIp, + IN UINT8 *Filename OPTIONAL, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ); + +/** + Writes a UDP packet to the network interface. + + This function writes a UDP packet specified by the (optional HeaderPtr and) + BufferPtr parameters to the network interface. The UDP header is automatically + built by this routine. It uses the parameters OpFlags, DestIp, DestPort, GatewayIp, + SrcIp, and SrcPort to build this header. If the packet is successfully built and + transmitted through the network interface, then EFI_SUCCESS will be returned. + If a timeout occurs during the transmission of the packet, then EFI_TIMEOUT will + be returned. If an ICMP error occurs during the transmission of the packet, then + the IcmpErrorReceived field is set to TRUE, the IcmpError field is filled in and + EFI_ICMP_ERROR will be returned. If the Callback Protocol does not return + EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, then EFI_ABORTED will be returned. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param OpFlags The UDP operation flags. + @param DestIp The destination IP address. + @param DestPort The destination UDP port number. + @param GatewayIp The gateway IP address. + @param SrcIp The source IP address. + @param SrcPort The source UDP port number. + @param HeaderSize An optional field which may be set to the length of a header at + HeaderPtr to be prefixed to the data at BufferPtr. + @param HeaderPtr If HeaderSize is not NULL, a pointer to a header to be prefixed to the + data at BufferPtr. + @param BufferSize A pointer to the size of the data at BufferPtr. + @param BufferPtr A pointer to the data to be written. + + @retval EFI_SUCCESS The UDP Write operation was completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_BAD_BUFFER_SIZE The buffer is too long to be transmitted. + @retval EFI_ABORTED The callback function aborted the UDP Write operation. + @retval EFI_TIMEOUT The UDP Write operation timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the UDP write session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_UDP_WRITE)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIp, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, + IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL + IN EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSize, + IN VOID *BufferPtr + ); + +/** + Reads a UDP packet from the network interface. + + This function reads a UDP packet from a network interface. The data contents + are returned in (the optional HeaderPtr and) BufferPtr, and the size of the + buffer received is returned in BufferSize. If the input BufferSize is smaller + than the UDP packet received (less optional HeaderSize), it will be set to the + required size, and EFI_BUFFER_TOO_SMALL will be returned. In this case, the + contents of BufferPtr are undefined, and the packet is lost. If a UDP packet is + successfully received, then EFI_SUCCESS will be returned, and the information + from the UDP header will be returned in DestIp, DestPort, SrcIp, and SrcPort if + they are not NULL. + Depending on the values of OpFlags and the DestIp, DestPort, SrcIp, and SrcPort + input values, different types of UDP packet receive filtering will be performed. + The following tables summarize these receive filter operations. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param OpFlags The UDP operation flags. + @param DestIp The destination IP address. + @param DestPort The destination UDP port number. + @param SrcIp The source IP address. + @param SrcPort The source UDP port number. + @param HeaderSize An optional field which may be set to the length of a header at + HeaderPtr to be prefixed to the data at BufferPtr. + @param HeaderPtr If HeaderSize is not NULL, a pointer to a header to be prefixed to the + data at BufferPtr. + @param BufferSize A pointer to the size of the data at BufferPtr. + @param BufferPtr A pointer to the data to be read. + + @retval EFI_SUCCESS The UDP Read operation was completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_BUFFER_TOO_SMALL The packet is larger than Buffer can hold. + @retval EFI_ABORTED The callback function aborted the UDP Read operation. + @retval EFI_TIMEOUT The UDP Read operation timed out. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_UDP_READ)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSize, + IN VOID *BufferPtr + ); + +/** + Updates the IP receive filters of a network device and enables software filtering. + + The NewFilter field is used to modify the network device's current IP receive + filter settings and to enable a software filter. This function updates the IpFilter + field of the EFI_PXE_BASE_CODE_MODE structure with the contents of NewIpFilter. + The software filter is used when the USE_FILTER in OpFlags is set to UdpRead(). + The current hardware filter remains in effect no matter what the settings of OpFlags + are, so that the meaning of ANY_DEST_IP set in OpFlags to UdpRead() is from those + packets whose reception is enabled in hardware - physical NIC address (unicast), + broadcast address, logical address or addresses (multicast), or all (promiscuous). + UdpRead() does not modify the IP filter settings. + Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP receive + filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP. + If an application or driver wishes to preserve the IP receive filter settings, + it will have to preserve the IP receive filter settings before these calls, and + use SetIpFilter() to restore them after the calls. If incompatible filtering is + requested (for example, PROMISCUOUS with anything else), or if the device does not + support a requested filter setting and it cannot be accommodated in software + (for example, PROMISCUOUS not supported), EFI_INVALID_PARAMETER will be returned. + The IPlist field is used to enable IPs other than the StationIP. They may be + multicast or unicast. If IPcnt is set as well as EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP, + then both the StationIP and the IPs from the IPlist will be used. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewFilter The pointer to the new set of IP receive filters. + + @retval EFI_SUCCESS The IP receive filter settings were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_IP_FILTER)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter + ); + +/** + Uses the ARP protocol to resolve a MAC address. + + This function uses the ARP protocol to resolve a MAC address. The UsingIpv6 field + of the EFI_PXE_BASE_CODE_MODE structure is used to determine if IPv4 or IPv6 + addresses are being used. The IP address specified by IpAddr is used to resolve + a MAC address. If the ARP protocol succeeds in resolving the specified address, + then the ArpCacheEntries and ArpCache fields of the EFI_PXE_BASE_CODE_MODE structure + are updated, and EFI_SUCCESS is returned. If MacAddr is not NULL, the resolved + MAC address is placed there as well. + If the PXE Base Code protocol is in the stopped state, then EFI_NOT_STARTED is + returned. If the ARP protocol encounters a timeout condition while attempting + to resolve an address, then EFI_TIMEOUT is returned. If the Callback Protocol + does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, then EFI_ABORTED is + returned. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param IpAddr The pointer to the IP address that is used to resolve a MAC address. + @param MacAddr If not NULL, a pointer to the MAC address that was resolved with the + ARP protocol. + + @retval EFI_SUCCESS The IP or MAC address was resolved. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_ABORTED The callback function aborted the ARP Protocol. + @retval EFI_TIMEOUT The ARP Protocol encountered a timeout condition. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_ARP)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *IpAddr, + IN EFI_MAC_ADDRESS *MacAddr OPTIONAL + ); + +/** + Updates the parameters that affect the operation of the PXE Base Code Protocol. + + This function sets parameters that affect the operation of the PXE Base Code Protocol. + The parameter specified by NewAutoArp is used to control the generation of ARP + protocol packets. If NewAutoArp is TRUE, then ARP Protocol packets will be generated + as required by the PXE Base Code Protocol. If NewAutoArp is FALSE, then no ARP + Protocol packets will be generated. In this case, the only mappings that are + available are those stored in the ArpCache of the EFI_PXE_BASE_CODE_MODE structure. + If there are not enough mappings in the ArpCache to perform a PXE Base Code Protocol + service, then the service will fail. This function updates the AutoArp field of + the EFI_PXE_BASE_CODE_MODE structure to NewAutoArp. + The SetParameters() call must be invoked after a Callback Protocol is installed + to enable the use of callbacks. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewAutoArp If not NULL, a pointer to a value that specifies whether to replace the + current value of AutoARP. + @param NewSendGUID If not NULL, a pointer to a value that specifies whether to replace the + current value of SendGUID. + @param NewTTL If not NULL, a pointer to be used in place of the current value of TTL, + the "time to live" field of the IP header. + @param NewToS If not NULL, a pointer to be used in place of the current value of ToS, + the "type of service" field of the IP header. + @param NewMakeCallback If not NULL, a pointer to a value that specifies whether to replace the + current value of the MakeCallback field of the Mode structure. + + @retval EFI_SUCCESS The new parameters values were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_PARAMETERS)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN *NewAutoArp, OPTIONAL + IN BOOLEAN *NewSendGUID, OPTIONAL + IN UINT8 *NewTTL, OPTIONAL + IN UINT8 *NewToS, OPTIONAL + IN BOOLEAN *NewMakeCallback OPTIONAL + ); + +/** + Updates the station IP address and/or subnet mask values of a network device. + + This function updates the station IP address and/or subnet mask values of a network + device. + The NewStationIp field is used to modify the network device's current IP address. + If NewStationIP is NULL, then the current IP address will not be modified. Otherwise, + this function updates the StationIp field of the EFI_PXE_BASE_CODE_MODE structure + with NewStationIp. + The NewSubnetMask field is used to modify the network device's current subnet + mask. If NewSubnetMask is NULL, then the current subnet mask will not be modified. + Otherwise, this function updates the SubnetMask field of the EFI_PXE_BASE_CODE_MODE + structure with NewSubnetMask. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewStationIp The pointer to the new IP address to be used by the network device. + @param NewSubnetMask The pointer to the new subnet mask to be used by the network device. + + @retval EFI_SUCCESS The new station IP address and/or subnet mask were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_STATION_IP)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL + ); + +/** + Updates the contents of the cached DHCP and Discover packets. + + The pointers to the new packets are used to update the contents of the cached + packets in the EFI_PXE_BASE_CODE_MODE structure. + + @param This The pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewDhcpDiscoverValid The pointer to a value that will replace the current + DhcpDiscoverValid field. + @param NewDhcpAckReceived The pointer to a value that will replace the current + DhcpAckReceived field. + @param NewProxyOfferReceived The pointer to a value that will replace the current + ProxyOfferReceived field. + @param NewPxeDiscoverValid The pointer to a value that will replace the current + ProxyOfferReceived field. + @param NewPxeReplyReceived The pointer to a value that will replace the current + PxeReplyReceived field. + @param NewPxeBisReplyReceived The pointer to a value that will replace the current + PxeBisReplyReceived field. + @param NewDhcpDiscover The pointer to the new cached DHCP Discover packet contents. + @param NewDhcpAck The pointer to the new cached DHCP Ack packet contents. + @param NewProxyOffer The pointer to the new cached Proxy Offer packet contents. + @param NewPxeDiscover The pointer to the new cached PXE Discover packet contents. + @param NewPxeReply The pointer to the new cached PXE Reply packet contents. + @param NewPxeBisReply The pointer to the new cached PXE BIS Reply packet contents. + + @retval EFI_SUCCESS The cached packet contents were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER This is NULL or not point to a valid EFI_PXE_BASE_CODE_PROTOCOL structure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_PACKETS)( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + BOOLEAN *NewDhcpDiscoverValid, OPTIONAL + BOOLEAN *NewDhcpAckReceived, OPTIONAL + BOOLEAN *NewProxyOfferReceived, OPTIONAL + BOOLEAN *NewPxeDiscoverValid, OPTIONAL + BOOLEAN *NewPxeReplyReceived, OPTIONAL + BOOLEAN *NewPxeBisReplyReceived, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewDhcpDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewDhcpAck, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewProxyOffer, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeReply, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeBisReply OPTIONAL + ); + +// +// PXE Base Code Protocol structure +// +#define EFI_PXE_BASE_CODE_PROTOCOL_REVISION 0x00010000 + +// +// Revision defined in EFI1.1 +// +#define EFI_PXE_BASE_CODE_INTERFACE_REVISION EFI_PXE_BASE_CODE_PROTOCOL_REVISION + +/// +/// The EFI_PXE_BASE_CODE_PROTOCOL is used to control PXE-compatible devices. +/// An EFI_PXE_BASE_CODE_PROTOCOL will be layered on top of an +/// EFI_MANAGED_NETWORK_PROTOCOL protocol in order to perform packet level transactions. +/// The EFI_PXE_BASE_CODE_PROTOCOL handle also supports the +/// EFI_LOAD_FILE_PROTOCOL protocol. This provides a clean way to obtain control from the +/// boot manager if the boot path is from the remote device. +/// +struct _EFI_PXE_BASE_CODE_PROTOCOL { + /// + /// The revision of the EFI_PXE_BASE_CODE_PROTOCOL. All future revisions must + /// be backwards compatible. If a future version is not backwards compatible + /// it is not the same GUID. + /// + UINT64 Revision; + EFI_PXE_BASE_CODE_START Start; + EFI_PXE_BASE_CODE_STOP Stop; + EFI_PXE_BASE_CODE_DHCP Dhcp; + EFI_PXE_BASE_CODE_DISCOVER Discover; + EFI_PXE_BASE_CODE_MTFTP Mtftp; + EFI_PXE_BASE_CODE_UDP_WRITE UdpWrite; + EFI_PXE_BASE_CODE_UDP_READ UdpRead; + EFI_PXE_BASE_CODE_SET_IP_FILTER SetIpFilter; + EFI_PXE_BASE_CODE_ARP Arp; + EFI_PXE_BASE_CODE_SET_PARAMETERS SetParameters; + EFI_PXE_BASE_CODE_SET_STATION_IP SetStationIp; + EFI_PXE_BASE_CODE_SET_PACKETS SetPackets; + /// + /// The pointer to the EFI_PXE_BASE_CODE_MODE data for this device. + /// + EFI_PXE_BASE_CODE_MODE *Mode; +}; + +extern EFI_GUID gEfiPxeBaseCodeProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h new file mode 100644 index 0000000..bfbd859 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h @@ -0,0 +1,130 @@ +/** @file + It is invoked when the PXE Base Code Protocol is about to transmit, has received, + or is waiting to receive a packet. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in EFI Specification 1.10 + +**/ + +#ifndef _PXE_BASE_CODE_CALLBACK_H_ +#define _PXE_BASE_CODE_CALLBACK_H_ + +/// +/// Call Back Definitions. +/// +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID \ + { \ + 0x245dca21, 0xfb7b, 0x11d3, {0x8f, 0x01, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +/// +/// UEFI Revision Number Definition. +/// +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION 0x00010000 + +/// +/// EFI 1.1 Revision Number defintion. +/// +#define EFI_PXE_BASE_CODE_CALLBACK_INTERFACE_REVISION \ + EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION + +/// +/// UEFI Protocol name. +/// +typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL; + +/// +/// EFI1.1 Protocol name. +/// +typedef EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL EFI_PXE_BASE_CODE_CALLBACK; + +/// +/// Event type list for PXE Base Code Protocol function. +/// +typedef enum { + EFI_PXE_BASE_CODE_FUNCTION_FIRST, + EFI_PXE_BASE_CODE_FUNCTION_DHCP, + EFI_PXE_BASE_CODE_FUNCTION_DISCOVER, + EFI_PXE_BASE_CODE_FUNCTION_MTFTP, + EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE, + EFI_PXE_BASE_CODE_FUNCTION_UDP_READ, + EFI_PXE_BASE_CODE_FUNCTION_ARP, + EFI_PXE_BASE_CODE_FUNCTION_IGMP, + EFI_PXE_BASE_CODE_PXE_FUNCTION_LAST +} EFI_PXE_BASE_CODE_FUNCTION; + +/// +/// Callback status type. +/// +typedef enum { + EFI_PXE_BASE_CODE_CALLBACK_STATUS_FIRST, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_LAST +} EFI_PXE_BASE_CODE_CALLBACK_STATUS; + +/** + Callback function that is invoked when the PXE Base Code Protocol is about to transmit, has + received, or is waiting to receive a packet. + + This function is invoked when the PXE Base Code Protocol is about to transmit, has received, + or is waiting to receive a packet. Parameters Function and Received specify the type of event. + Parameters PacketLen and Packet specify the packet that generated the event. If these fields + are zero and NULL respectively, then this is a status update callback. If the operation specified + by Function is to continue, then CALLBACK_STATUS_CONTINUE should be returned. If the operation + specified by Function should be aborted, then CALLBACK_STATUS_ABORT should be returned. Due to + the polling nature of UEFI device drivers, a callback function should not execute for more than 5 ms. + The SetParameters() function must be called after a Callback Protocol is installed to enable the + use of callbacks. + + @param This The pointer to the EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL instance. + @param Function The PXE Base Code Protocol function that is waiting for an event. + @param Received TRUE if the callback is being invoked due to a receive event. FALSE if + the callback is being invoked due to a transmit event. + @param PacketLen The length, in bytes, of Packet. This field will have a value of zero if + this is a wait for receive event. + @param Packet If Received is TRUE, a pointer to the packet that was just received; + otherwise a pointer to the packet that is about to be transmitted. + + @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE if Function specifies a continue operation + @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT if Function specifies an abort operation + +**/ +typedef +EFI_PXE_BASE_CODE_CALLBACK_STATUS +(EFIAPI *EFI_PXE_CALLBACK)( + IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN BOOLEAN Received, + IN UINT32 PacketLen, + IN EFI_PXE_BASE_CODE_PACKET *Packet OPTIONAL + ); + +/// +/// Protocol that is invoked when the PXE Base Code Protocol is about +/// to transmit, has received, or is waiting to receive a packet. +/// +struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL { + /// + /// The revision of the EFI_PXE_BASE_CODE_PROTOCOL. All future revisions must + /// be backwards compatible. If a future version is not backwards compatible + /// it is not the same GUID. + /// + UINT64 Revision; + EFI_PXE_CALLBACK Callback; +}; + +extern EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RamDisk.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RamDisk.h new file mode 100644 index 0000000..61353fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RamDisk.h @@ -0,0 +1,106 @@ +/** @file + This file defines the EFI RAM Disk Protocol. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.6 + +**/ + +#ifndef __RAM_DISK_PROTOCOL_H__ +#define __RAM_DISK_PROTOCOL_H__ + +// +// EFI RAM Disk Protocol GUID value +// +#define EFI_RAM_DISK_PROTOCOL_GUID \ + { 0xab38a0df, 0x6873, 0x44a9, { 0x87, 0xe6, 0xd4, 0xeb, 0x56, 0x14, 0x84, 0x49 }}; + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_RAM_DISK_PROTOCOL EFI_RAM_DISK_PROTOCOL; + +/** + Register a RAM disk with specified address, size and type. + + @param[in] RamDiskBase The base address of registered RAM disk. + @param[in] RamDiskSize The size of registered RAM disk. + @param[in] RamDiskType The type of registered RAM disk. The GUID can be + any of the values defined in section 9.3.6.9, or a + vendor defined GUID. + @param[in] ParentDevicePath + Pointer to the parent device path. If there is no + parent device path then ParentDevicePath is NULL. + @param[out] DevicePath On return, points to a pointer to the device path + of the RAM disk device. + If ParentDevicePath is not NULL, the returned + DevicePath is created by appending a RAM disk node + to the parent device path. If ParentDevicePath is + NULL, the returned DevicePath is a RAM disk device + path without appending. This function is + responsible for allocating the buffer DevicePath + with the boot service AllocatePool(). + + @retval EFI_SUCCESS The RAM disk is registered successfully. + @retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL. + RamDiskSize is 0. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created + is already present in the handle database. + @retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to + resource limitation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RAM_DISK_REGISTER_RAMDISK) ( + IN UINT64 RamDiskBase, + IN UINT64 RamDiskSize, + IN EFI_GUID *RamDiskType, + IN EFI_DEVICE_PATH *ParentDevicePath OPTIONAL, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Unregister a RAM disk specified by DevicePath. + + @param[in] DevicePath A pointer to the device path that describes a RAM + Disk device. + + @retval EFI_SUCCESS The RAM disk is unregistered successfully. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_UNSUPPORTED The device specified by DevicePath is not a + valid ramdisk device path and not supported + by the driver. + @retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't + exist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RAM_DISK_UNREGISTER_RAMDISK) ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/// +/// RAM Disk Protocol structure. +/// +struct _EFI_RAM_DISK_PROTOCOL { + EFI_RAM_DISK_REGISTER_RAMDISK Register; + EFI_RAM_DISK_UNREGISTER_RAMDISK Unregister; +}; + +/// +/// RAM Disk Protocol GUID variable. +/// +extern EFI_GUID gEfiRamDiskProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RealTimeClock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RealTimeClock.h new file mode 100644 index 0000000..e1713e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RealTimeClock.h @@ -0,0 +1,36 @@ +/** @file + Real Time clock Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + This code abstracts time and data functions. Used to provide + Time and date related EFI runtime services. + + The GetTime (), SetTime (), GetWakeupTime (), and SetWakeupTime () UEFI 2.0 + services are added to the EFI system table and the + EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID protocol is registered with a NULL + pointer. + + No CRC of the EFI system table is required, since that is done in the DXE core. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_REAL_TIME_CLOCK_H__ +#define __ARCH_PROTOCOL_REAL_TIME_CLOCK_H__ + +/// +/// Global ID for the Real Time Clock Architectural Protocol +/// +#define EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID \ + { 0x27CFAC87, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +extern EFI_GUID gEfiRealTimeClockArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RegularExpressionProtocol.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RegularExpressionProtocol.h new file mode 100644 index 0000000..7e9d555 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/RegularExpressionProtocol.h @@ -0,0 +1,181 @@ +/** @file + This section defines the Regular Expression Protocol. This protocol isused to match + Unicode strings against Regular Expression patterns. + +Copyright (c) 2015-2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.5. + +**/ + +#ifndef __REGULAR_EXPRESSION_PROTOCOL_H__ +#define __REGULAR_EXPRESSION_PROTOCOL_H__ + +#define EFI_REGULAR_EXPRESSION_PROTOCOL_GUID \ + { \ + 0xB3F79D9A, 0x436C, 0xDC11, {0xB0, 0x52, 0xCD, 0x85, 0xDF, 0x52, 0x4C, 0xE6 } \ + } + +#define EFI_REGEX_SYNTAX_TYPE_POSIX_EXTENDED_GUID \ + { \ + 0x5F05B20F, 0x4A56, 0xC231, {0xFA, 0x0B, 0xA7, 0xB1, 0xF1, 0x10, 0x04, 0x1D } \ + } + +#define EFI_REGEX_SYNTAX_TYPE_PERL_GUID \ + { \ + 0x63E60A51, 0x497D, 0xD427, {0xC4, 0xA5, 0xB8, 0xAB, 0xDC, 0x3A, 0xAE, 0xB6 } \ + } + +#define EFI_REGEX_SYNTAX_TYPE_ECMA_262_GUID \ + { \ + 0x9A473A4A, 0x4CEB, 0xB95A, {0x41, 0x5E, 0x5B, 0xA0, 0xBC, 0x63, 0x9B, 0x2E } \ + } + +typedef struct _EFI_REGULAR_EXPRESSION_PROTOCOL EFI_REGULAR_EXPRESSION_PROTOCOL; + + +typedef struct { + CONST CHAR16 *CapturePtr; // Pointer to the start of the captured sub-expression + // within matched String. + + UINTN Length; // Length of captured sub-expression. +} EFI_REGEX_CAPTURE; + +typedef EFI_GUID EFI_REGEX_SYNTAX_TYPE; + +// +// Protocol member functions +// +/** + Returns information about the regular expression syntax types supported + by the implementation. + + This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL + instance. + + RegExSyntaxTypeListSize On input, the size in bytes of RegExSyntaxTypeList. + On output with a return code of EFI_SUCCESS, the + size in bytes of the data returned in + RegExSyntaxTypeList. On output with a return code + of EFI_BUFFER_TOO_SMALL, the size of + RegExSyntaxTypeListrequired to obtain the list. + + RegExSyntaxTypeList A caller-allocated memory buffer filled by the + driver with one EFI_REGEX_SYNTAX_TYPEelement + for each supported Regular expression syntax + type. The list must not change across multiple + calls to the same driver. The first syntax + type in the list is the default type for the + driver. + + @retval EFI_SUCCESS The regular expression syntax types list + was returned successfully. + @retval EFI_UNSUPPORTED The service is not supported by this driver. + @retval EFI_DEVICE_ERROR The list of syntax types could not be + retrieved due to a hardware or firmware error. + @retval EFI_BUFFER_TOO_SMALL The buffer RegExSyntaxTypeList is too small + to hold the result. + @retval EFI_INVALID_PARAMETER RegExSyntaxTypeListSize is NULL + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGULAR_EXPRESSION_GET_INFO) ( + IN EFI_REGULAR_EXPRESSION_PROTOCOL *This, + IN OUT UINTN *RegExSyntaxTypeListSize, + OUT EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList + ); + +/** + Checks if the input string matches to the regular expression pattern. + + This A pointer to the EFI_REGULAR_EXPRESSION_PROTOCOL instance. + Type EFI_REGULAR_EXPRESSION_PROTOCOL is defined in Section + XYZ. + + String A pointer to a NULL terminated string to match against the + regular expression string specified by Pattern. + + Pattern A pointer to a NULL terminated string that represents the + regular expression. + + SyntaxType A pointer to the EFI_REGEX_SYNTAX_TYPE that identifies the + regular expression syntax type to use. May be NULL in which + case the function will use its default regular expression + syntax type. + + Result On return, points to TRUE if String fully matches against + the regular expression Pattern using the regular expression + SyntaxType. Otherwise, points to FALSE. + + Captures A Pointer to an array of EFI_REGEX_CAPTURE objects to receive + the captured groups in the event of a match. The full + sub-string match is put in Captures[0], and the results of N + capturing groups are put in Captures[1:N]. If Captures is + NULL, then this function doesn't allocate the memory for the + array and does not build up the elements. It only returns the + number of matching patterns in CapturesCount. If Captures is + not NULL, this function returns a pointer to an array and + builds up the elements in the array. CapturesCount is also + updated to the number of matching patterns found. It is the + caller's responsibility to free the memory pool in Captures + and in each CapturePtr in the array elements. + + CapturesCount On output, CapturesCount is the number of matching patterns + found in String. Zero means no matching patterns were found + in the string. + + @retval EFI_SUCCESS The regular expression string matching + completed successfully. + @retval EFI_UNSUPPORTED The regular expression syntax specified by + SyntaxTypeis not supported by this driver. + @retval EFI_DEVICE_ERROR The regular expression string matching + failed due to a hardware or firmware error. + @retval EFI_INVALID_PARAMETER String, Pattern, Result, or CapturesCountis + NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGULAR_EXPRESSION_MATCH) ( + IN EFI_REGULAR_EXPRESSION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern, + IN EFI_REGEX_SYNTAX_TYPE *SyntaxType, OPTIONAL + OUT BOOLEAN *Result, + OUT EFI_REGEX_CAPTURE **Captures, OPTIONAL + OUT UINTN *CapturesCount + ); + +struct _EFI_REGULAR_EXPRESSION_PROTOCOL { + EFI_REGULAR_EXPRESSION_MATCH MatchString; + EFI_REGULAR_EXPRESSION_GET_INFO GetInfo; +} ; + +extern EFI_GUID gEfiRegularExpressionProtocolGuid; + +// +// For regular expression rules specified in the POSIX Extended Regular +// Expression (ERE) Syntax: +// +extern EFI_GUID gEfiRegexSyntaxTypePosixExtendedGuid; + +// +// For regular expression rules specifiedin the ECMA 262 Specification +// +extern EFI_GUID gEfiRegexSyntaxTypeEcma262Guid; + +// +// For regular expression rules specified in the Perl standard: +// +extern EFI_GUID gEfiRegexSyntaxTypePerlGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ReportStatusCodeHandler.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ReportStatusCodeHandler.h new file mode 100644 index 0000000..36bf3b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ReportStatusCodeHandler.h @@ -0,0 +1,97 @@ +/** @file + This protocol provide registering and unregistering services to status code + consumers while in DXE. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.2. + +**/ + +#ifndef __REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ +#define __REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ + +#define EFI_RSC_HANDLER_PROTOCOL_GUID \ + { \ + 0x86212936, 0xe76, 0x41c8, {0xa0, 0x3a, 0x2a, 0xf2, 0xfc, 0x1c, 0x39, 0xe2} \ + } + +typedef +EFI_STATUS +(EFIAPI *EFI_RSC_HANDLER_CALLBACK)( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data +); + +/** + Register the callback function for ReportStatusCode() notification. + + When this function is called the function pointer is added to an internal list and any future calls to + ReportStatusCode() will be forwarded to the Callback function. During the bootservices, + this is the callback for which this service can be invoked. The report status code router + will create an event such that the callback function is only invoked at the TPL for which it was + registered. The entity that registers for the callback should also register for an event upon + generation of exit boot services and invoke the unregister service. + If the handler does not have a TPL dependency, it should register for a callback at TPL high. The + router infrastructure will support making callbacks at runtime, but the caller for runtime invocation + must meet the following criteria: + 1. must be a runtime driver type so that its memory is not reclaimed + 2. not unregister at exit boot services so that the router will still have its callback address + 3. the caller must be self-contained (eg. Not call out into any boot-service interfaces) and be + runtime safe, in general. + + @param[in] Callback A pointer to a function of type EFI_RSC_HANDLER_CALLBACK that is called when + a call to ReportStatusCode() occurs. + @param[in] Tpl TPL at which callback can be safely invoked. + + @retval EFI_SUCCESS Function was successfully registered. + @retval EFI_INVALID_PARAMETER The callback function was NULL. + @retval EFI_OUT_OF_RESOURCES The internal buffer ran out of space. No more functions can be + registered. + @retval EFI_ALREADY_STARTED The function was already registered. It can't be registered again. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RSC_HANDLER_REGISTER)( + IN EFI_RSC_HANDLER_CALLBACK Callback, + IN EFI_TPL Tpl +); + +/** + Remove a previously registered callback function from the notification list. + + A callback function must be unregistered before it is deallocated. It is important that any registered + callbacks that are not runtime complaint be unregistered when ExitBootServices() is called. + + @param[in] Callback A pointer to a function of type EFI_RSC_HANDLER_CALLBACK that is to be + unregistered. + + @retval EFI_SUCCESS The function was successfully unregistered. + @retval EFI_INVALID_PARAMETER The callback function was NULL. + @retval EFI_NOT_FOUND The callback function was not found to be unregistered. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RSC_HANDLER_UNREGISTER)( + IN EFI_RSC_HANDLER_CALLBACK Callback +); + +typedef struct { + EFI_RSC_HANDLER_REGISTER Register; + EFI_RSC_HANDLER_UNREGISTER Unregister; +} EFI_RSC_HANDLER_PROTOCOL; + +extern EFI_GUID gEfiRscHandlerProtocolGuid; + +#endif // __REPORT_STATUS_CODE_HANDLER_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Reset.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Reset.h new file mode 100644 index 0000000..6737e31 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Reset.h @@ -0,0 +1,31 @@ +/** @file + Reset Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + Used to provide ResetSystem runtime services + + The ResetSystem () UEFI 2.0 service is added to the EFI system table and the + EFI_RESET_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_RESET_H__ +#define __ARCH_PROTOCOL_RESET_H__ + +/// +/// Global ID for the Reset Architectural Protocol +/// +#define EFI_RESET_ARCH_PROTOCOL_GUID \ + { 0x27CFAC88, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +extern EFI_GUID gEfiResetArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ResetNotification.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ResetNotification.h new file mode 100644 index 0000000..dac8717 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ResetNotification.h @@ -0,0 +1,86 @@ +/** @file + EFI Reset Notification Protocol as defined in UEFI 2.7. + This protocol provides services to register for a notification when ResetSystem is called. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __EFI_RESET_NOTIFICATION_H__ +#define __EFI_RESET_NOTIFICATION_H__ + +#define EFI_RESET_NOTIFICATION_PROTOCOL_GUID \ + { 0x9da34ae0, 0xeaf9, 0x4bbf, { 0x8e, 0xc3, 0xfd, 0x60, 0x22, 0x6c, 0x44, 0xbe } } + +typedef struct _EFI_RESET_NOTIFICATION_PROTOCOL EFI_RESET_NOTIFICATION_PROTOCOL; + +/** + Register a notification function to be called when ResetSystem() is called. + + The RegisterResetNotify() function registers a notification function that is called when + ResetSystem()is called and prior to completing the reset of the platform. + The registered functions must not perform a platform reset themselves. These + notifications are intended only for the notification of components which may need some + special-purpose maintenance prior to the platform resetting. + The list of registered reset notification functions are processed if ResetSystem()is called + before ExitBootServices(). The list of registered reset notification functions is ignored if + ResetSystem()is called after ExitBootServices(). + + @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance. + @param[in] ResetFunction Points to the function to be called when a ResetSystem() is executed. + + @retval EFI_SUCCESS The reset notification function was successfully registered. + @retval EFI_INVALID_PARAMETER ResetFunction is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to register the reset notification function. + @retval EFI_ALREADY_STARTED The reset notification function specified by ResetFunction has already been registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_RESET_NOTIFY) ( + IN EFI_RESET_NOTIFICATION_PROTOCOL *This, + IN EFI_RESET_SYSTEM ResetFunction +); + +/** + Unregister a notification function. + + The UnregisterResetNotify() function removes the previously registered + notification using RegisterResetNotify(). + + @param[in] This A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance. + @param[in] ResetFunction The pointer to the ResetFunction being unregistered. + + @retval EFI_SUCCESS The reset notification function was unregistered. + @retval EFI_INVALID_PARAMETER ResetFunction is NULL. + @retval EFI_INVALID_PARAMETER The reset notification function specified by ResetFunction was not previously + registered using RegisterResetNotify(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNREGISTER_RESET_NOTIFY) ( + IN EFI_RESET_NOTIFICATION_PROTOCOL *This, + IN EFI_RESET_SYSTEM ResetFunction +); + +typedef struct _EFI_RESET_NOTIFICATION_PROTOCOL { + EFI_REGISTER_RESET_NOTIFY RegisterResetNotify; + EFI_UNREGISTER_RESET_NOTIFY UnregisterResetNotify; +} EFI_RESET_NOTIFICATION_PROTOCOL; + + +extern EFI_GUID gEfiResetNotificationProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rest.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rest.h new file mode 100644 index 0000000..512dd08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rest.h @@ -0,0 +1,94 @@ +/** @file + This file defines the EFI REST Protocol interface. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_REST_PROTOCOL_H__ +#define __EFI_REST_PROTOCOL_H__ + +#include + +#define EFI_REST_PROTOCOL_GUID \ + { \ + 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09, 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b } \ + } + +typedef struct _EFI_REST_PROTOCOL EFI_REST_PROTOCOL; + +/** + Provides a simple HTTP-like interface to send and receive resources from a REST + service. + + The SendReceive() function sends an HTTP request to this REST service, and returns a + response when the data is retrieved from the service. RequestMessage contains the HTTP + request to the REST resource identified by RequestMessage.Request.Url. The + ResponseMessage is the returned HTTP response for that request, including any HTTP + status. + + @param[in] This Pointer to EFI_REST_PROTOCOL instance for a particular + REST service. + @param[in] RequestMessage Pointer to the HTTP request data for this resource. + @param[out] ResponseMessage Pointer to the HTTP response data obtained for this + requested. + + @retval EFI_SUCCESS Operation succeeded. + @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REST_SEND_RECEIVE) ( + IN EFI_REST_PROTOCOL *This, + IN EFI_HTTP_MESSAGE *RequestMessage, + OUT EFI_HTTP_MESSAGE *ResponseMessage + ); + +/** + The GetServiceTime() function is an optional interface to obtain the current time from + this REST service instance. If this REST service does not support retrieving the time, + this function returns EFI_UNSUPPORTED. + + @param[in] This Pointer to EFI_REST_PROTOCOL instance. + @param[out] Time A pointer to storage to receive a snapshot of the + current time of the REST service. + + @retval EFI_SUCCESS Operation succeeded + @retval EFI_INVALID_PARAMETER This or Time are NULL. + @retval EFI_UNSUPPORTED The RESTful service does not support returning the + time. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REST_GET_TIME) ( + IN EFI_REST_PROTOCOL *This, + OUT EFI_TIME *Time + ); + +/// +/// The EFI REST protocol is designed to be used by EFI drivers and applications to send +/// and receive resources from a RESTful service. This protocol abstracts REST +/// (Representational State Transfer) client functionality. This EFI protocol could be +/// implemented to use an underlying EFI HTTP protocol, or it could rely on other +/// interfaces that abstract HTTP access to the resources. +/// +struct _EFI_REST_PROTOCOL { + EFI_REST_SEND_RECEIVE SendReceive; + EFI_REST_GET_TIME GetServiceTime; +}; + +extern EFI_GUID gEfiRestProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rng.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rng.h new file mode 100644 index 0000000..6848d39 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Rng.h @@ -0,0 +1,156 @@ +/** @file + EFI_RNG_PROTOCOL as defined in UEFI 2.4. + The UEFI Random Number Generator Protocol is used to provide random bits for use + in applications, or entropy for seeding other random number generators. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_RNG_PROTOCOL_H__ +#define __EFI_RNG_PROTOCOL_H__ + +/// +/// Global ID for the Random Number Generator Protocol +/// +#define EFI_RNG_PROTOCOL_GUID \ + { \ + 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \ + } + +typedef struct _EFI_RNG_PROTOCOL EFI_RNG_PROTOCOL; + +/// +/// A selection of EFI_RNG_PROTOCOL algorithms. +/// The algorithms listed are optional, not meant to be exhaustive and be argmented by +/// vendors or other industry standards. +/// + +typedef EFI_GUID EFI_RNG_ALGORITHM; + +/// +/// The algorithms corresponds to SP800-90 as defined in +/// NIST SP 800-90, "Recommendation for Random Number Generation Using Deterministic Random +/// Bit Generators", March 2007. +/// +#define EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID \ + { \ + 0xa7af67cb, 0x603b, 0x4d42, {0xba, 0x21, 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96 } \ + } +#define EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID \ + { \ + 0xc5149b43, 0xae85, 0x4f53, {0x99, 0x82, 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7 } \ + } +#define EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID \ + { \ + 0x44f0de6e, 0x4d8c, 0x4045, {0xa8, 0xc7, 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e } \ + } +/// +/// The algorithms correspond to X9.31 as defined in +/// NIST, "Recommended Random Number Generator Based on ANSI X9.31 Appendix A.2.4 Using +/// the 3-Key Triple DES and AES Algorithm", January 2005. +/// +#define EFI_RNG_ALGORITHM_X9_31_3DES_GUID \ + { \ + 0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46 } \ + } +#define EFI_RNG_ALGORITHM_X9_31_AES_GUID \ + { \ + 0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9 } \ + } +/// +/// The "raw" algorithm, when supported, is intended to provide entropy directly from +/// the source, without it going through some deterministic random bit generator. +/// +#define EFI_RNG_ALGORITHM_RAW \ + { \ + 0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 } \ + } + +/** + Returns information about the random number generation implementation. + + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. + @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList. + On output with a return code of EFI_SUCCESS, the size + in bytes of the data returned in RNGAlgorithmList. On output + with a return code of EFI_BUFFER_TOO_SMALL, + the size of RNGAlgorithmList required to obtain the list. + @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver + with one EFI_RNG_ALGORITHM element for each supported + RNG algorithm. The list must not change across multiple + calls to the same driver. The first algorithm in the list + is the default algorithm for the driver. + + @retval EFI_SUCCESS The RNG algorithm list was returned successfully. + @retval EFI_UNSUPPORTED The services is not supported by this driver. + @retval EFI_DEVICE_ERROR The list of algorithms could not be retrieved due to a + hardware or firmware error. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_INFO) ( + IN EFI_RNG_PROTOCOL *This, + IN OUT UINTN *RNGAlgorithmListSize, + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList + ); + +/** + Produces and returns an RNG value using either the default or specified RNG algorithm. + + @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. + @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG + algorithm to use. May be NULL in which case the function will + use its default RNG algorithm. + @param[in] RNGValueLength The length in bytes of the memory buffer pointed to by + RNGValue. The driver shall return exactly this numbers of bytes. + @param[out] RNGValue A caller-allocated memory buffer filled by the driver with the + resulting RNG value. + + @retval EFI_SUCCESS The RNG value was returned successfully. + @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by + this driver. + @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or + firmware error. + @retval EFI_NOT_READY There is not enough random data available to satisfy the length + requested by RNGValueLength. + @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_RNG) ( + IN EFI_RNG_PROTOCOL *This, + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue + ); + +/// +/// The Random Number Generator (RNG) protocol provides random bits for use in +/// applications, or entropy for seeding other random number generators. +/// +struct _EFI_RNG_PROTOCOL { + EFI_RNG_GET_INFO GetInfo; + EFI_RNG_GET_RNG GetRNG; +}; + +extern EFI_GUID gEfiRngProtocolGuid; +extern EFI_GUID gEfiRngAlgorithmSp80090Hash256Guid; +extern EFI_GUID gEfiRngAlgorithmSp80090Hmac256Guid; +extern EFI_GUID gEfiRngAlgorithmSp80090Ctr256Guid; +extern EFI_GUID gEfiRngAlgorithmX9313DesGuid; +extern EFI_GUID gEfiRngAlgorithmX931AesGuid; +extern EFI_GUID gEfiRngAlgorithmRaw; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Runtime.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Runtime.h new file mode 100644 index 0000000..f235566 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Runtime.h @@ -0,0 +1,128 @@ +/** @file + Runtime Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + Allows the runtime functionality of the DXE Foundation to be contained + in a separate driver. It also provides hooks for the DXE Foundation to + export information that is needed at runtime. As such, this protocol allows + services to the DXE Foundation to manage runtime drivers and events. + This protocol also implies that the runtime services required to transition + to virtual mode, SetVirtualAddressMap() and ConvertPointer(), have been + registered into the UEFI Runtime Table in the UEFI System Table. This protocol + must be produced by a runtime DXE driver and may only be consumed by the DXE Foundation. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_RUNTIME_H__ +#define __ARCH_PROTOCOL_RUNTIME_H__ + +/// +/// Global ID for the Runtime Architectural Protocol +/// +#define EFI_RUNTIME_ARCH_PROTOCOL_GUID \ + { 0xb7dfb4e1, 0x52f, 0x449f, {0x87, 0xbe, 0x98, 0x18, 0xfc, 0x91, 0xb7, 0x33 } } + +typedef struct _EFI_RUNTIME_ARCH_PROTOCOL EFI_RUNTIME_ARCH_PROTOCOL; + +/// +/// LIST_ENTRY from BaseType +/// +typedef LIST_ENTRY EFI_LIST_ENTRY; + +typedef struct _EFI_RUNTIME_IMAGE_ENTRY EFI_RUNTIME_IMAGE_ENTRY; + +/// +/// EFI_RUNTIME_IMAGE_ENTRY +/// +struct _EFI_RUNTIME_IMAGE_ENTRY { + /// + /// Start of image that has been loaded in memory. It is a pointer + /// to either the DOS header or PE header of the image. + /// + VOID *ImageBase; + /// + /// Size in bytes of the image represented by ImageBase. + /// + UINT64 ImageSize; + /// + /// Information about the fix-ups that were performed on ImageBase when it was + /// loaded into memory. + /// + VOID *RelocationData; + /// + /// The ImageHandle passed into ImageBase when it was loaded. + /// + EFI_HANDLE Handle; + /// + /// Entry for this node in the EFI_RUNTIME_ARCHITECTURE_PROTOCOL.ImageHead list. + /// + EFI_LIST_ENTRY Link; +}; + +typedef struct _EFI_RUNTIME_EVENT_ENTRY EFI_RUNTIME_EVENT_ENTRY; + +/// +/// EFI_RUNTIME_EVENT_ENTRY +/// +struct _EFI_RUNTIME_EVENT_ENTRY { + /// + /// The same as Type passed into CreateEvent(). + /// + UINT32 Type; + /// + /// The same as NotifyTpl passed into CreateEvent(). + /// + EFI_TPL NotifyTpl; + /// + /// The same as NotifyFunction passed into CreateEvent(). + /// + EFI_EVENT_NOTIFY NotifyFunction; + /// + /// The same as NotifyContext passed into CreateEvent(). + /// + VOID *NotifyContext; + /// + /// The EFI_EVENT returned by CreateEvent(). Event must be in runtime memory. + /// + EFI_EVENT *Event; + /// + /// Entry for this node in the + /// EFI_RUNTIME_ARCHITECTURE_PROTOCOL.EventHead list. + /// + EFI_LIST_ENTRY Link; +}; + +/// +/// Allows the runtime functionality of the DXE Foundation to be contained in a +/// separate driver. It also provides hooks for the DXE Foundation to export +/// information that is needed at runtime. As such, this protocol allows the DXE +/// Foundation to manage runtime drivers and events. This protocol also implies +/// that the runtime services required to transition to virtual mode, +/// SetVirtualAddressMap() and ConvertPointer(), have been registered into the +/// EFI Runtime Table in the EFI System Partition. This protocol must be produced +/// by a runtime DXE driver and may only be consumed by the DXE Foundation. +/// +struct _EFI_RUNTIME_ARCH_PROTOCOL { + EFI_LIST_ENTRY ImageHead; ///< A list of type EFI_RUNTIME_IMAGE_ENTRY. + EFI_LIST_ENTRY EventHead; ///< A list of type EFI_RUNTIME_EVENT_ENTRY. + UINTN MemoryDescriptorSize; ///< Size of a memory descriptor that is returned by GetMemoryMap(). + UINT32 MemoryDesciptorVersion; ///< Version of a memory descriptor that is returned by GetMemoryMap(). + UINTN MemoryMapSize;///< Size of the memory map in bytes contained in MemoryMapPhysical and MemoryMapVirtual. + EFI_MEMORY_DESCRIPTOR *MemoryMapPhysical; ///< Pointer to a runtime buffer that contains a copy of + ///< the memory map returned via GetMemoryMap(). + EFI_MEMORY_DESCRIPTOR *MemoryMapVirtual; ///< Pointer to MemoryMapPhysical that is updated to virtual mode after SetVirtualAddressMap(). + BOOLEAN VirtualMode; ///< Boolean that is TRUE if SetVirtualAddressMap() has been called. + BOOLEAN AtRuntime; ///< Boolean that is TRUE if ExitBootServices () has been called. +}; + +extern EFI_GUID gEfiRuntimeArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SaveState.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SaveState.h new file mode 100644 index 0000000..c729517 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SaveState.h @@ -0,0 +1,176 @@ +/** @file + S3 Save State Protocol as defined in PI 1.6(Errata A) Specification VOLUME 5 Standard. + + This protocol is used by DXE PI module to store or record various IO operations + to be replayed during an S3 resume. + This protocol is not required for all platforms. + + Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.2 Volume 5: + Standards + +**/ + +#ifndef __S3_SAVE_STATE_H__ +#define __S3_SAVE_STATE_H__ + +#define EFI_S3_SAVE_STATE_PROTOCOL_GUID \ + { 0xe857caf6, 0xc046, 0x45dc, { 0xbe, 0x3f, 0xee, 0x7, 0x65, 0xfb, 0xa8, 0x87 }} + + +typedef VOID *EFI_S3_BOOT_SCRIPT_POSITION; + +typedef struct _EFI_S3_SAVE_STATE_PROTOCOL EFI_S3_SAVE_STATE_PROTOCOL; + +/** + Record operations that need to be replayed during an S3 resume. + + This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is + assumed this protocol has platform specific mechanism to store the OpCode set and replay them + during the S3 resume. + + @param[in] This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance. + @param[in] OpCode The operation code (opcode) number. + @param[in] ... Argument list that is specific to each opcode. See the following subsections for the + definition of each opcode. + + @retval EFI_SUCCESS The operation succeeded. A record was added into the specified + script table. + @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_S3_SAVE_STATE_WRITE)( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN UINTN OpCode, + ... +); + +/** + Record operations that need to be replayed during an S3 resume. + + This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is + assumed this protocol has platform specific mechanism to store the OpCode set and replay them + during the S3 resume. + The opcode is inserted before or after the specified position in the boot script table. If Position is + NULL then that position is after the last opcode in the table (BeforeOrAfter is TRUE) or before + the first opcode in the table (BeforeOrAfter is FALSE). The position which is pointed to by + Position upon return can be used for subsequent insertions. + + This function has a variable parameter list. The exact parameter list depends on the OpCode that is + passed into the function. If an unsupported OpCode or illegal parameter list is passed in, this + function returns EFI_INVALID_PARAMETER. + If there are not enough resources available for storing more scripts, this function returns + EFI_OUT_OF_RESOURCES. + OpCode values of 0x80 - 0xFE are reserved for implementation specific functions. + + @param[in] This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance. + @param[in] 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[in, out] 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[in] OpCode The operation code (opcode) number. See "Related Definitions" in Write() for the + defined opcode types. + @param[in] ... Argument list that is specific to each opcode. See the following subsections for the + definition of each opcode. + + @retval EFI_SUCCESS The operation succeeded. An opcode was added into the script. + @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value. + @retval EFI_INVALID_PARAMETER The Position is not a valid position in the boot script table. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script table. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_S3_SAVE_STATE_INSERT)( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN BOOLEAN BeforeOrAfter, + IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL, + IN UINTN OpCode, + ... +); + +/** + Find a label within the boot script table and, if not present, optionally create it. + + If the label Label is already exists in the boot script table, then no new label is created, the + position of the Label is returned in *Position and EFI_SUCCESS is returned. + If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be + created before or after the specified position and EFI_SUCCESS is returned. + If the label Label does not already exist and CreateIfNotFound is FALSE, then + EFI_NOT_FOUND is returned. + + @param[in] This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance. + @param[in] BeforeOrAfter Specifies whether the label 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 label is inserted at the beginning of the table (if TRUE) or end of + the table (if FALSE). + @param[in] CreateIfNotFound Specifies whether the label will be created if the label does not exists (TRUE) or not (FALSE). + @param[in, out] Position On entry, specifies the position in the boot script table where the label will be inserted, + either before or after, depending on BeforeOrAfter. On exit, specifies the position + of the inserted label in the boot script table. + @param[in] Label Points to the label which will be inserted in the boot script table. + + @retval EFI_SUCCESS The label already exists or was inserted. + @retval EFI_NOT_FOUND The label did not already exist and CreateifNotFound was FALSE. + @retval EFI_INVALID_PARAMETER The Label is NULL or points to an empty string. + @retval EFI_INVALID_PARAMETER The Position is not a valid position in the boot script table. + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_S3_SAVE_STATE_LABEL)( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN BOOLEAN BeforeOrAfter, + IN BOOLEAN CreateIfNotFound, + IN OUT EFI_S3_BOOT_SCRIPT_POSITION *Position OPTIONAL, + IN CONST CHAR8 *Label +); + +/** + Compare two positions in the boot script table and return their relative position. + + This function compares two positions in the boot script table and returns their relative positions. If + Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2, + then 0 is returned. If Position1 is after Position2, then 1 is returned. + + @param[in] This A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance. + @param[in] Position1 The positions in the boot script table to compare. + @param[in] Position2 The positions in the boot script table to compare. + @param[out] RelativePosition On return, points to the result of the comparison. + + @retval EFI_SUCCESS The operation succeeded. + @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table. + @retval EFI_INVALID_PARAMETER The RelativePosition is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_S3_SAVE_STATE_COMPARE)( + IN CONST EFI_S3_SAVE_STATE_PROTOCOL *This, + IN EFI_S3_BOOT_SCRIPT_POSITION Position1, + IN EFI_S3_BOOT_SCRIPT_POSITION Position2, + OUT UINTN *RelativePosition +); + +struct _EFI_S3_SAVE_STATE_PROTOCOL { + EFI_S3_SAVE_STATE_WRITE Write; + EFI_S3_SAVE_STATE_INSERT Insert; + EFI_S3_SAVE_STATE_LABEL Label; + EFI_S3_SAVE_STATE_COMPARE Compare; +}; + +extern EFI_GUID gEfiS3SaveStateProtocolGuid; + +#endif // __S3_SAVE_STATE_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SmmSaveState.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SmmSaveState.h new file mode 100644 index 0000000..ab7fd96 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/S3SmmSaveState.h @@ -0,0 +1,46 @@ +/** @file + S3 SMM Save State Protocol as defined in PI1.2 Specification VOLUME 5 Standard. + + The EFI_S3_SMM_SAVE_STATE_PROTOCOL publishes the PI SMMboot script abstractions + On an S3 resume boot path the data stored via this protocol is replayed in the order it was stored. + The order of replay is the order either of the S3 Save State Protocol or S3 SMM Save State Protocol + Write() functions were called during the boot process. Insert(), Label(), and + Compare() operations are ordered relative other S3 SMM Save State Protocol write() operations + and the order relative to S3 State Save Write() operations is not defined. Due to these ordering + restrictions it is recommended that the S3 State Save Protocol be used during the DXE phase when + every possible. + The EFI_S3_SMM_SAVE_STATE_PROTOCOL can be called at runtime and + EFI_OUT_OF_RESOURCES may be returned from a runtime call. It is the responsibility of the + platform to ensure enough memory resource exists to save the system state. It is recommended that + runtime calls be minimized by the caller. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This PPI is defined in UEFI Platform Initialization Specification 1.2 Volume 5: + Standards + +**/ + +#ifndef __S3_SMM_SAVE_STATE_H__ +#define __S3_SMM_SAVE_STATE_H__ + +#include + +#define EFI_S3_SMM_SAVE_STATE_PROTOCOL_GUID \ + {0x320afe62, 0xe593, 0x49cb, { 0xa9, 0xf1, 0xd4, 0xc2, 0xf4, 0xaf, 0x1, 0x4c }} + + +typedef EFI_S3_SAVE_STATE_PROTOCOL EFI_S3_SMM_SAVE_STATE_PROTOCOL; + +extern EFI_GUID gEfiS3SmmSaveStateProtocolGuid; + +#endif // __S3_SMM_SAVE_STATE_H__ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiIo.h new file mode 100644 index 0000000..d9f2089 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiIo.h @@ -0,0 +1,317 @@ +/** @file + EFI_SCSI_IO_PROTOCOL as defined in UEFI 2.0. + This protocol is used by code, typically drivers, running in the EFI boot + services environment to access SCSI devices. In particular, functions for + managing devices on SCSI buses are defined here. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_SCSI_IO_PROTOCOL_H__ +#define __EFI_SCSI_IO_PROTOCOL_H__ + +#define EFI_SCSI_IO_PROTOCOL_GUID \ + { \ + 0x932f47e6, 0x2362, 0x4002, {0x80, 0x3e, 0x3c, 0xd5, 0x4b, 0x13, 0x8f, 0x85 } \ + } + +/// +/// Forward reference for pure ANSI compatability +/// +typedef struct _EFI_SCSI_IO_PROTOCOL EFI_SCSI_IO_PROTOCOL; + +// +// SCSI Device type information, defined in the SCSI Primary Commands standard (e.g., SPC-4) +// +#define EFI_SCSI_IO_TYPE_DISK 0x00 ///< Disk device +#define EFI_SCSI_IO_TYPE_TAPE 0x01 ///< Tape device +#define EFI_SCSI_IO_TYPE_PRINTER 0x02 ///< Printer +#define EFI_SCSI_IO_TYPE_PROCESSOR 0x03 ///< Processor +#define EFI_SCSI_IO_TYPE_WORM 0x04 ///< Write-once read-multiple +#define EFI_SCSI_IO_TYPE_CDROM 0x05 ///< CD or DVD device +#define EFI_SCSI_IO_TYPE_SCANNER 0x06 ///< Scanner device +#define EFI_SCSI_IO_TYPE_OPTICAL 0x07 ///< Optical memory device +#define EFI_SCSI_IO_TYPE_MEDIUMCHANGER 0x08 ///< Medium Changer device +#define EFI_SCSI_IO_TYPE_COMMUNICATION 0x09 ///< Communications device +#define MFI_SCSI_IO_TYPE_A 0x0A ///< Obsolete +#define MFI_SCSI_IO_TYPE_B 0x0B ///< Obsolete +#define MFI_SCSI_IO_TYPE_RAID 0x0C ///< Storage array controller device (e.g., RAID) +#define MFI_SCSI_IO_TYPE_SES 0x0D ///< Enclosure services device +#define MFI_SCSI_IO_TYPE_RBC 0x0E ///< Simplified direct-access device (e.g., magnetic disk) +#define MFI_SCSI_IO_TYPE_OCRW 0x0F ///< Optical card reader/writer device +#define MFI_SCSI_IO_TYPE_BRIDGE 0x10 ///< Bridge Controller Commands +#define MFI_SCSI_IO_TYPE_OSD 0x11 ///< Object-based Storage Device +#define EFI_SCSI_IO_TYPE_RESERVED_LOW 0x12 ///< Reserved (low) +#define EFI_SCSI_IO_TYPE_RESERVED_HIGH 0x1E ///< Reserved (high) +#define EFI_SCSI_IO_TYPE_UNKNOWN 0x1F ///< Unknown no device type + +// +// SCSI Data Direction definition +// +#define EFI_SCSI_IO_DATA_DIRECTION_READ 0 +#define EFI_SCSI_IO_DATA_DIRECTION_WRITE 1 +#define EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL 2 + +// +// SCSI Host Adapter Status definition +// +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 ///< timeout when processing the command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT 0x0b ///< timeout when waiting for the command processing +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d ///< a message reject was received when processing command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET 0x0e ///< a bus reset was detected +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 ///< the adapter failed in issuing request sense command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 ///< selection timeout +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 ///< data overrun or data underrun +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE 0x13 ///< Unexepected bus free +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 ///< Target bus phase sequence failure +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_OTHER 0x7f + + +// +// SCSI Target Status definition +// +#define EFI_SCSI_IO_STATUS_TARGET_GOOD 0x00 +#define EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION 0x02 ///< check condition +#define EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET 0x04 ///< condition met +#define EFI_SCSI_IO_STATUS_TARGET_BUSY 0x08 ///< busy +#define EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE 0x10 ///< intermediate +#define EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 ///< intermediate-condition met +#define EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT 0x18 ///< reservation conflict +#define EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED 0x22 ///< command terminated +#define EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL 0x28 ///< queue full + +typedef struct { + /// + /// The timeout, in 100 ns units, to use for the execution of this SCSI + /// Request Packet. A Timeout value of 0 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. + /// + UINT64 Timeout; + /// + /// A pointer to the data buffer to transfer between the SCSI + /// controller and the SCSI device for SCSI READ command + /// + VOID *InDataBuffer; + /// + /// A pointer to the data buffer to transfer between the SCSI + /// controller and the SCSI device for SCSI WRITE command. + /// + VOID *OutDataBuffer; + /// + /// A pointer to the sense data that was generated by the execution of + /// the SCSI Request Packet. + /// + VOID *SenseData; + /// + /// A pointer to buffer that contains the Command Data Block to + /// send to the SCSI device. + /// + VOID *Cdb; + /// + /// On Input, the size, in bytes, of InDataBuffer. On output, the + /// number of bytes transferred between the SCSI controller and the SCSI device. + /// + UINT32 InTransferLength; + /// + /// On Input, the size, in bytes of OutDataBuffer. On Output, the + /// Number of bytes transferred between SCSI Controller and the SCSI device. + /// + UINT32 OutTransferLength; + /// + /// The length, in bytes, of the buffer Cdb. The standard values are + /// 6, 10, 12, and 16, but other values are possible if a variable length CDB is used. + /// + UINT8 CdbLength; + /// + /// The direction of the data transfer. 0 for reads, 1 for writes. A + /// value of 2 is Reserved for Bi-Directional SCSI commands. + /// + UINT8 DataDirection; + /// + /// The status of the SCSI Host Controller that produces the SCSI + /// bus where the SCSI device attached when the SCSI Request + /// Packet was executed on the SCSI Controller. + /// + UINT8 HostAdapterStatus; + /// + /// The status returned by the SCSI device when the SCSI Request + /// Packet was executed. + /// + UINT8 TargetStatus; + /// + /// On input, the length in bytes of the SenseData buffer. On + /// output, the number of bytes written to the SenseData buffer. + /// + UINT8 SenseDataLength; +} EFI_SCSI_IO_SCSI_REQUEST_PACKET; + +/** + Retrieves the device type information of the SCSI Controller. + + @param This Protocol instance pointer. + @param DeviceType A pointer to the device type information + retrieved from the SCSI Controller. + + @retval EFI_SUCCESS Retrieved the device type information successfully. + @retval EFI_INVALID_PARAMETER The DeviceType is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_GET_DEVICE_TYPE)( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT8 *DeviceType + ); + +/** + Retrieves the device location in the SCSI channel. + + @param This Protocol instance pointer. + @param Target A pointer to the Target ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of the SCSI device on + the SCSI channel. + + @retval EFI_SUCCESS Retrieves the device location successfully. + @retval EFI_INVALID_PARAMETER The Target or Lun is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_GET_DEVICE_LOCATION)( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT UINT8 **Target, + OUT UINT64 *Lun + ); + +/** + Resets the SCSI Bus that the SCSI Controller is attached to. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The SCSI bus is reset successfully. + @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus. + @retval EFI_UNSUPPORTED The bus reset operation is not supported by the + SCSI Host Controller. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset + the SCSI bus. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_RESET_BUS)( + IN EFI_SCSI_IO_PROTOCOL *This + ); + +/** + Resets the SCSI Controller that the device handle specifies. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Reset the SCSI controller successfully. + @retval EFI_DEVICE_ERROR Errors were encountered when resetting the + SCSI Controller. + @retval EFI_UNSUPPORTED The SCSI bus does not support a device + reset operation. + @retval EFI_TIMEOUT A timeout occurred while attempting to + reset the SCSI Controller. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_RESET_DEVICE)( + IN EFI_SCSI_IO_PROTOCOL *This + ); + + +/** + Sends a SCSI Request Packet to the SCSI Controller for execution. + + @param This Protocol instance pointer. + @param Packet The SCSI request packet to send to the SCSI + Controller specified by the device handle. + @param Event If the SCSI bus to which the SCSI device is attached + 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 Request + Packet completes. + + @retval EFI_SUCCESS The SCSI Request Packet was sent by the host + successfully, and TransferLength bytes were + transferred to/from DataBuffer. 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 TransferLength. 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 caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send + the SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid. + The SCSI Request Packet was not sent, so no + additional status information is available. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_EXEC_SCSI_COMMAND)( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ); + +/// +/// Provides services to manage and communicate with SCSI devices. +/// +struct _EFI_SCSI_IO_PROTOCOL { + EFI_SCSI_IO_PROTOCOL_GET_DEVICE_TYPE GetDeviceType; + EFI_SCSI_IO_PROTOCOL_GET_DEVICE_LOCATION GetDeviceLocation; + EFI_SCSI_IO_PROTOCOL_RESET_BUS ResetBus; + EFI_SCSI_IO_PROTOCOL_RESET_DEVICE ResetDevice; + EFI_SCSI_IO_PROTOCOL_EXEC_SCSI_COMMAND ExecuteScsiCommand; + + /// + /// Supplies the alignment requirement for any buffer used in a data transfer. + /// IoAlign values of 0 and 1 mean that the buffer can be placed anywhere in memory. + /// Otherwise, IoAlign must be a power of 2, and the requirement is that the + /// start address of a buffer must be evenly divisible by IoAlign with no remainder. + /// + UINT32 IoAlign; +}; + +extern EFI_GUID gEfiScsiIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThru.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThru.h new file mode 100644 index 0000000..c0df016 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThru.h @@ -0,0 +1,383 @@ +/** @file + SCSI Pass Through protocol as defined in EFI 1.1. + This protocol allows information about a SCSI channel to be collected, + and allows SCSI Request Packets to be sent to any SCSI devices on a SCSI + channel even if those devices are not boot devices. This protocol is attached + to the device handle of each SCSI channel in a system that the protocol + supports, and can be used for diagnostics. It may also be used to build + a Block I/O driver for SCSI hard drives and SCSI CD-ROM or DVD drives to + allow those devices to become boot devices. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SCSI_PASS_THROUGH_H__ +#define __SCSI_PASS_THROUGH_H__ + +#define EFI_SCSI_PASS_THRU_PROTOCOL_GUID \ + { \ + 0xa59e8fcf, 0xbda0, 0x43bb, {0x90, 0xb1, 0xd3, 0x73, 0x2e, 0xca, 0xa8, 0x77 } \ + } + +/// +/// Forward reference for pure ANSI compatability +/// +typedef struct _EFI_SCSI_PASS_THRU_PROTOCOL EFI_SCSI_PASS_THRU_PROTOCOL; + +#define EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001 +#define EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002 +#define EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004 + +// +// SCSI Host Adapter Status definition +// +#define EFI_SCSI_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 // timeout when processing the command +#define EFI_SCSI_STATUS_HOST_ADAPTER_TIMEOUT 0x0b // timeout when waiting for the command processing +#define EFI_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d // a message reject was received when processing command +#define EFI_SCSI_STATUS_HOST_ADAPTER_BUS_RESET 0x0e // a bus reset was detected +#define EFI_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 // the adapter failed in issuing request sense command +#define EFI_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 // selection timeout +#define EFI_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 // data overrun or data underrun +#define EFI_SCSI_STATUS_HOST_ADAPTER_BUS_FREE 0x13 // Unexepected bus free +#define EFI_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 // Target bus phase sequence failure +#define EFI_SCSI_STATUS_HOST_ADAPTER_OTHER 0x7f + +// +// SCSI Target Status definition +// +#define EFI_SCSI_STATUS_TARGET_GOOD 0x00 +#define EFI_SCSI_STATUS_TARGET_CHECK_CONDITION 0x02 // check condition +#define EFI_SCSI_STATUS_TARGET_CONDITION_MET 0x04 // condition met +#define EFI_SCSI_STATUS_TARGET_BUSY 0x08 // busy +#define EFI_SCSI_STATUS_TARGET_INTERMEDIATE 0x10 // intermediate +#define EFI_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 // intermediate-condition met +#define EFI_SCSI_STATUS_TARGET_RESERVATION_CONFLICT 0x18 // reservation conflict +#define EFI_SCSI_STATUS_TARGET_COMMOND_TERMINATED 0x22 // command terminated +#define EFI_SCSI_STATUS_TARGET_QUEUE_FULL 0x28 // queue full + +typedef struct { + /// + /// The timeout, in 100 ns units, to use for the execution of this SCSI + /// Request Packet. A Timeout value of 0 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. + /// + UINT64 Timeout; + /// + /// A pointer to the data buffer to transfer between the SCSI + /// controller and the SCSI device. Must be aligned to the boundary + /// specified in the IoAlign field of the + /// EFI_SCSI_PASS_THRU_MODE structure. + /// + VOID *DataBuffer; + /// + /// A pointer to the sense data that was generated by the execution of + /// the SCSI Request Packet. + /// + VOID *SenseData; + /// + /// A pointer to buffer that contains the Command Data Block to + /// send to the SCSI device. + /// + VOID *Cdb; + /// + /// On Input, the size, in bytes, of InDataBuffer. On output, the + /// number of bytes transferred between the SCSI controller and the SCSI device. + /// + UINT32 TransferLength; + /// + /// The length, in bytes, of the buffer Cdb. The standard values are + /// 6, 10, 12, and 16, but other values are possible if a variable length CDB is used. + /// + UINT8 CdbLength; + /// + /// The direction of the data transfer. 0 for reads, 1 for writes. A + /// value of 2 is Reserved for Bi-Directional SCSI commands. + /// + UINT8 DataDirection; + /// + /// The status of the SCSI Host Controller that produces the SCSI + /// bus where the SCSI device attached when the SCSI Request + /// Packet was executed on the SCSI Controller. + /// + UINT8 HostAdapterStatus; + /// + /// The status returned by the SCSI device when the SCSI Request + /// Packet was executed. + /// + UINT8 TargetStatus; + /// + /// On input, the length in bytes of the SenseData buffer. On + /// output, the number of bytes written to the SenseData buffer. + /// + UINT8 SenseDataLength; +} EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET; + +typedef struct { + /// + /// A Null-terminated Unicode string that represents the printable name of the SCSI controller. + /// + CHAR16 *ControllerName; + /// + /// A Null-terminated Unicode string that represents the printable name of the SCSI channel. + /// + CHAR16 *ChannelName; + /// + /// The Target ID of the host adapter on the SCSI channel. + /// + UINT32 AdapterId; + /// + /// Additional information on the attributes of the SCSI channel. + /// + UINT32 Attributes; + /// + /// Supplies the alignment requirement for any buffer used in a data transfer. + /// + UINT32 IoAlign; +} EFI_SCSI_PASS_THRU_MODE; + +/** + Sends a SCSI Request Packet to a SCSI device that is attached to + the SCSI channel. This function supports both blocking I/O and + non-blocking I/O. The blocking I/O functionality is required, + and the non-blocking I/O functionality is optional. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device to + send the SCSI Request Packet. + @param Lun The LUN of the SCSI device to send the + SCSI Request Packet. + @param Packet A pointer to the SCSI Request Packet to send + to the SCSI device specified by Target and Lun. + @param Event If non-blocking I/O is not supported 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 Request + Packet completes + + @retval EFI_SUCCESS The SCSI Request Packet was sent by the host, and + TransferLength bytes were transferred to/from + DataBuffer. 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 TransferLength. 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 Request Packets already + queued. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send + the SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket + are invalid. The SCSI Request Packet was not sent, + so no additional status information is available. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the host adapter. 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_PASSTHRU)( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ); + +/** + Used to retrieve the list of legal Target IDs for SCSI devices + on a SCSI channel. + + @param This Protocol instance pointer. + @param Target On input, a pointer to the Target ID of a + SCSI device present on the SCSI channel. + On output, a pointer to the Target ID of + the next SCSI device present on a SCSI channel. + An input value of 0xFFFFFFFF retrieves the + Target ID of the first SCSI device present on + a SCSI channel. + @param Lun On input, a pointer to the LUN of a SCSI device + present on the SCSI channel. On output, a pointer + to the LUN of the next SCSI device present on a + SCSI channel. + + @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI + channel was returned in Target and Lun. + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + @retval EFI_INVALID_PARAMETER Target is not 0xFFFFFFFF, and Target and Lun were + not returned on a previous call to GetNextDevice(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_GET_NEXT_DEVICE)( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *Target, + IN OUT UINT64 *Lun + ); + +/** + Used to allocate and build a device path node for a SCSI device + on a SCSI channel. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device for which + a device path node is to be allocated and built. + @param Lun The LUN of the SCSI device for which a device + path node is to be allocated and built. + @param DevicePath A pointer to a single device path node that + describes the SCSI device specified by + Target and Lun. This function is responsible + for allocating the buffer DevicePath with the boot + service AllocatePool(). It is the caller's + responsibility to free DevicePath when the caller + is finished with DevicePath. + + @retval EFI_SUCCESS The device path node that describes the SCSI device + specified by Target and Lun was allocated and + returned in DevicePath. + @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does + not exist on the SCSI channel. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate + DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_BUILD_DEVICE_PATH)( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Used to translate a device path node to a Target ID and LUN. + + @param This Protocol instance pointer. + @param DevicePath A pointer to the device path node that + describes a SCSI device on the SCSI channel. + @param Target A pointer to the Target ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of a SCSI device on + the SCSI channel. + + @retval EFI_SUCCESS DevicePath was successfully translated to a + Target ID and LUN, and they were returned + in Target and Lun. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER Target is NULL. + @retval EFI_INVALID_PARAMETER Lun is NULL. + @retval EFI_UNSUPPORTED This driver does not support the device path + node type in DevicePath. + @retval EFI_NOT_FOUND A valid translation from DevicePath to a + Target ID and LUN does not exist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_GET_TARGET_LUN)( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *Target, + OUT UINT64 *Lun + ); + +/** + Resets a SCSI channel.This operation resets all the + SCSI devices connected to the SCSI channel. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The SCSI channel was reset. + @retval EFI_UNSUPPORTED The SCSI channel does not support + a channel reset operation. + @retval EFI_DEVICE_ERROR A device error occurred while + attempting to reset the SCSI channel. + @retval EFI_TIMEOUT A timeout occurred while attempting + to reset the SCSI channel. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_RESET_CHANNEL)( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This + ); + +/** + Resets a SCSI device that is connected to a SCSI channel. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device to reset. + @param Lun The LUN of the SCSI device to reset. + + @retval EFI_SUCCESS The SCSI device specified by Target and + Lun was reset. + @retval EFI_UNSUPPORTED The SCSI channel does not support a target + reset operation. + @retval EFI_INVALID_PARAMETER Target or Lun are invalid. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to reset the SCSI device specified by Target + and Lun. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset + the SCSI device specified by Target and Lun. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_RESET_TARGET)( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun + ); + +/// +/// The EFI_SCSI_PASS_THRU_PROTOCOL provides information about a SCSI channel and +/// the ability to send SCSI Request Packets to any SCSI device attached to that SCSI channel. The +/// information includes the Target ID of the host controller on the SCSI channel, the attributes of +/// the SCSI channel, the printable name for the SCSI controller, and the printable name of the +/// SCSI channel. +/// +struct _EFI_SCSI_PASS_THRU_PROTOCOL { + /// + /// A pointer to the EFI_SCSI_PASS_THRU_MODE data for this SCSI channel. + /// + EFI_SCSI_PASS_THRU_MODE *Mode; + EFI_SCSI_PASS_THRU_PASSTHRU PassThru; + EFI_SCSI_PASS_THRU_GET_NEXT_DEVICE GetNextDevice; + EFI_SCSI_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_SCSI_PASS_THRU_GET_TARGET_LUN GetTargetLun; + EFI_SCSI_PASS_THRU_RESET_CHANNEL ResetChannel; + EFI_SCSI_PASS_THRU_RESET_TARGET ResetTarget; +}; + +extern EFI_GUID gEfiScsiPassThruProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThruExt.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThruExt.h new file mode 100644 index 0000000..d8d6d2d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ScsiPassThruExt.h @@ -0,0 +1,394 @@ +/** @file + EFI_EXT_SCSI_PASS_THRU_PROTOCOL as defined in UEFI 2.0. + This protocol provides services that allow SCSI Pass Thru commands + to be sent to SCSI devices attached to a SCSI channel. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EXT_SCSI_PASS_THROUGH_PROTOCOL_H__ +#define __EXT_SCSI_PASS_THROUGH_PROTOCOL_H__ + +#define EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID \ + { \ + 0x143b7632, 0xb81b, 0x4cb7, {0xab, 0xd3, 0xb6, 0x25, 0xa5, 0xb9, 0xbf, 0xfe } \ + } + +typedef struct _EFI_EXT_SCSI_PASS_THRU_PROTOCOL EFI_EXT_SCSI_PASS_THRU_PROTOCOL; + +#define TARGET_MAX_BYTES 0x10 + +#define EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001 +#define EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002 +#define EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004 + +// +// DataDirection +// +#define EFI_EXT_SCSI_DATA_DIRECTION_READ 0 +#define EFI_EXT_SCSI_DATA_DIRECTION_WRITE 1 +#define EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL 2 +// +// HostAdapterStatus +// +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT 0x0b +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET 0x0e +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE 0x13 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER 0x7f +// +// TargetStatus +// +#define EFI_EXT_SCSI_STATUS_TARGET_GOOD 0x00 +#define EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION 0x02 +#define EFI_EXT_SCSI_STATUS_TARGET_CONDITION_MET 0x04 +#define EFI_EXT_SCSI_STATUS_TARGET_BUSY 0x08 +#define EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE 0x10 +#define EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 +#define EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT 0x18 +#define EFI_EXT_SCSI_STATUS_TARGET_TASK_SET_FULL 0x28 +#define EFI_EXT_SCSI_STATUS_TARGET_ACA_ACTIVE 0x30 +#define EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED 0x40 + +typedef struct { + /// + /// The Target ID of the host adapter on the SCSI channel. + /// + UINT32 AdapterId; + /// + /// Additional information on the attributes of the SCSI channel. + /// + UINT32 Attributes; + /// + /// Supplies the alignment requirement for any buffer used in a data transfer. + /// + UINT32 IoAlign; +} EFI_EXT_SCSI_PASS_THRU_MODE; + +typedef struct { + /// + /// The timeout, in 100 ns units, to use for the execution of this SCSI + /// Request Packet. A Timeout value of 0 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. + /// + UINT64 Timeout; + /// + /// A pointer to the data buffer to transfer between the SCSI + /// controller and the SCSI device for read and bidirectional commands. + /// + VOID *InDataBuffer; + /// + /// A pointer to the data buffer to transfer between the SCSI + /// controller and the SCSI device for write or bidirectional commands. + /// + VOID *OutDataBuffer; + /// + /// A pointer to the sense data that was generated by the execution of + /// the SCSI Request Packet. + /// + VOID *SenseData; + /// + /// A pointer to buffer that contains the Command Data Block to + /// send to the SCSI device specified by Target and Lun. + /// + VOID *Cdb; + /// + /// On Input, the size, in bytes, of InDataBuffer. On output, the + /// number of bytes transferred between the SCSI controller and the SCSI device. + /// + UINT32 InTransferLength; + /// + /// On Input, the size, in bytes of OutDataBuffer. On Output, the + /// Number of bytes transferred between SCSI Controller and the SCSI device. + /// + UINT32 OutTransferLength; + /// + /// The length, in bytes, of the buffer Cdb. The standard values are 6, + /// 10, 12, and 16, but other values are possible if a variable length CDB is used. + /// + UINT8 CdbLength; + /// + /// The direction of the data transfer. 0 for reads, 1 for writes. A + /// value of 2 is Reserved for Bi-Directional SCSI commands. + /// + UINT8 DataDirection; + /// + /// The status of the host adapter specified by This when the SCSI + /// Request Packet was executed on the target device. + /// + UINT8 HostAdapterStatus; + /// + /// The status returned by the device specified by Target and Lun + /// when the SCSI Request Packet was executed. + /// + UINT8 TargetStatus; + /// + /// On input, the length in bytes of the SenseData buffer. On + /// output, the number of bytes written to the SenseData buffer. + /// + UINT8 SenseDataLength; +} EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET; + +/** + Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function + supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the + nonblocking I/O functionality is optional. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target is an array of size TARGET_MAX_BYTES and it represents + the id of the SCSI device to send the SCSI Request Packet. Each + transport driver may choose to utilize a subset of this size to suit the needs + of transport target representation. For example, a Fibre Channel driver + may use only 8 bytes (WWN) to represent an FC target. + @param Lun The LUN of the SCSI device to send the SCSI Request Packet. + @param Packet A pointer to the SCSI Request Packet to send to the SCSI device + specified by Target and Lun. + @param Event If nonblocking I/O is not supported 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 + nonblocking I/O is performed, and Event will be signaled when the + SCSI Request Packet completes. + + @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional + commands, InTransferLength bytes were transferred from + InDataBuffer. For write and bi-directional commands, + OutTransferLength bytes were transferred by + OutDataBuffer. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed. The number of bytes that + could be transferred is returned in InTransferLength. For write + and bi-directional commands, OutTransferLength bytes were + transferred by OutDataBuffer. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Request Packets already queued. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request + Packet. + @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported + by the host adapter. This includes the case of Bi-directional SCSI + commands not supported by the implementation. 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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_PASSTHRU)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun, + IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ); + +/** + Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These + can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal + Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the + Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI + channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target On input, a pointer to the Target ID (an array of size + TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel. + On output, a pointer to the Target ID (an array of + TARGET_MAX_BYTES) of the next SCSI device present on a SCSI + channel. An input value of 0xF(all bytes in the array are 0xF) in the + Target array retrieves the Target ID of the first SCSI device present on a + SCSI channel. + @param Lun On input, a pointer to the LUN of a SCSI device present on the SCSI + channel. On output, a pointer to the LUN of the next SCSI device present + on a SCSI channel. + + @retval EFI_SUCCESS The Target ID and LUN of the next SCSI device on the SCSI + channel was returned in Target and Lun. + @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were + not returned on a previous call to GetNextTargetLun(). + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET_LUN)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 **Target, + IN OUT UINT64 *Lun + ); + +/** + Used to allocate and build a device path node for a SCSI device on a SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target is an array of size TARGET_MAX_BYTES and it specifies the + Target ID of the SCSI device for which a device path node is to be + allocated and built. Transport drivers may chose to utilize a subset of + this size to suit the representation of targets. For example, a Fibre + Channel driver may use only 8 bytes (WWN) in the array to represent a + FC target. + @param Lun The LUN of the SCSI device for which a device path node is to be + allocated and built. + @param DevicePath A pointer to a single device path node that describes the SCSI device + specified by Target and Lun. This function is responsible for + allocating the buffer DevicePath with the boot service + AllocatePool(). It is the caller's responsibility to free + DevicePath when the caller is finished with DevicePath. + + @retval EFI_SUCCESS The device path node that describes the SCSI device specified by + Target and Lun was allocated and returned in + DevicePath. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist + on the SCSI channel. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_BUILD_DEVICE_PATH)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Used to translate a device path node to a Target ID and LUN. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param DevicePath A pointer to a single device path node that describes the SCSI device + on the SCSI channel. + @param Target A pointer to the Target Array which represents the ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of a SCSI device on the SCSI channel. + + @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and + LUN, and they were returned in Target and Lun. + @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL. + @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN + does not exist. + @retval EFI_UNSUPPORTED This driver does not support the device path node type in + DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_GET_TARGET_LUN)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT8 **Target, + OUT UINT64 *Lun + ); + +/** + Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + + @retval EFI_SUCCESS The SCSI channel was reset. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI channel. + @retval EFI_UNSUPPORTED The SCSI channel does not support a channel reset operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_RESET_CHANNEL)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This + ); + +/** + Resets a SCSI logical unit that is connected to a SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target is an array of size TARGET_MAX_BYTE and it represents the + target port ID of the SCSI device containing the SCSI logical unit to + reset. Transport drivers may chose to utilize a subset of this array to suit + the representation of their targets. + @param Lun The LUN of the SCSI device to reset. + + @retval EFI_SUCCESS The SCSI device specified by Target and Lun was reset. + @retval EFI_INVALID_PARAMETER Target or Lun is NULL. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI device + specified by Target and Lun. + @retval EFI_UNSUPPORTED The SCSI channel does not support a target reset operation. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI device + specified by Target and Lun. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_RESET_TARGET_LUN)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun + ); + +/** + Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either + be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs + for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to + see if a SCSI device is actually present at that location on the SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel. + On output, a pointer to the Target ID (an array of + TARGET_MAX_BYTES) of the next SCSI device present on a SCSI + channel. An input value of 0xF(all bytes in the array are 0xF) in the + Target array retrieves the Target ID of the first SCSI device present on a + SCSI channel. + + @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI + channel was returned in Target. + @retval EFI_INVALID_PARAMETER Target or Lun is NULL. + @retval EFI_TIMEOUT Target array is not all 0xF, and Target was not + returned on a previous call to GetNextTarget(). + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET)( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 **Target + ); + +/// +/// The EFI_EXT_SCSI_PASS_THRU_PROTOCOL provides information about a SCSI channel +/// and the ability to send SCI Request Packets to any SCSI device attached to +/// that SCSI channel. The information includes the Target ID of the host controller +/// on the SCSI channel and the attributes of the SCSI channel. +/// +struct _EFI_EXT_SCSI_PASS_THRU_PROTOCOL { + /// + /// A pointer to the EFI_EXT_SCSI_PASS_THRU_MODE data for this SCSI channel. + /// + EFI_EXT_SCSI_PASS_THRU_MODE *Mode; + EFI_EXT_SCSI_PASS_THRU_PASSTHRU PassThru; + EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET_LUN GetNextTargetLun; + EFI_EXT_SCSI_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_EXT_SCSI_PASS_THRU_GET_TARGET_LUN GetTargetLun; + EFI_EXT_SCSI_PASS_THRU_RESET_CHANNEL ResetChannel; + EFI_EXT_SCSI_PASS_THRU_RESET_TARGET_LUN ResetTargetLun; + EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET GetNextTarget; +}; + +extern EFI_GUID gEfiExtScsiPassThruProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SdMmcPassThru.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SdMmcPassThru.h new file mode 100644 index 0000000..ddbf456 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SdMmcPassThru.h @@ -0,0 +1,264 @@ +/** @file + The EFI_SD_MMC_PASS_THRU_PROTOCOL provides the ability to send SD/MMC Commands + to any SD/MMC device attached to the SD compatible pci host controller. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SD_MMC_PASS_THRU_H__ +#define __SD_MMC_PASS_THRU_H__ + +#define EFI_SD_MMC_PASS_THRU_PROTOCOL_GUID \ + { \ + 0x716ef0d9, 0xff83, 0x4f69, {0x81, 0xe9, 0x51, 0x8b, 0xd3, 0x9a, 0x8e, 0x70 } \ + } + +typedef struct _EFI_SD_MMC_PASS_THRU_PROTOCOL EFI_SD_MMC_PASS_THRU_PROTOCOL; + +typedef enum { + SdMmcCommandTypeBc, // Broadcast commands, no response + SdMmcCommandTypeBcr, // Broadcast commands with response + SdMmcCommandTypeAc, // Addressed(point-to-point) commands + SdMmcCommandTypeAdtc // Addressed(point-to-point) data transfer commands +} EFI_SD_MMC_COMMAND_TYPE; + +typedef enum { + SdMmcResponseTypeR1, + SdMmcResponseTypeR1b, + SdMmcResponseTypeR2, + SdMmcResponseTypeR3, + SdMmcResponseTypeR4, + SdMmcResponseTypeR5, + SdMmcResponseTypeR5b, + SdMmcResponseTypeR6, + SdMmcResponseTypeR7 +} EFI_SD_MMC_RESPONSE_TYPE; + +typedef struct _EFI_SD_MMC_COMMAND_BLOCK { + UINT16 CommandIndex; + UINT32 CommandArgument; + UINT32 CommandType; // One of the EFI_SD_MMC_COMMAND_TYPE values + UINT32 ResponseType; // One of the EFI_SD_MMC_RESPONSE_TYPE values +} EFI_SD_MMC_COMMAND_BLOCK; + +typedef struct _EFI_SD_MMC_STATUS_BLOCK { + UINT32 Resp0; + UINT32 Resp1; + UINT32 Resp2; + UINT32 Resp3; +} EFI_SD_MMC_STATUS_BLOCK; + +typedef struct _EFI_SD_MMC_PASS_THRU_COMMAND_PACKET { + UINT64 Timeout; + EFI_SD_MMC_COMMAND_BLOCK *SdMmcCmdBlk; + EFI_SD_MMC_STATUS_BLOCK *SdMmcStatusBlk; + VOID *InDataBuffer; + VOID *OutDataBuffer; + UINT32 InTransferLength; + UINT32 OutTransferLength; + EFI_STATUS TransactionStatus; +} EFI_SD_MMC_PASS_THRU_COMMAND_PACKET; + +/** + Sends SD command to an SD card that is attached to the SD controller. + + The PassThru() function sends the SD command specified by Packet to the SD card + specified by Slot. + + If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned. + + If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned. + + If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER + is returned. + + If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL, + EFI_INVALID_PARAMETER is returned. + + @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. + @param[in] Slot The slot number of the SD card to send the command to. + @param[in,out] Packet A pointer to the SD command data structure. + @param[in] Event If Event is NULL, blocking I/O is performed. If Event is + not NULL, then nonblocking I/O is performed, and Event + will be signaled when the Packet completes. + + @retval EFI_SUCCESS The SD Command Packet was sent by the host. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SD + command Packet. + @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid. + @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and + OutDataBuffer are NULL. + @retval EFI_NO_MEDIA SD Device not present in the Slot. + @retval EFI_UNSUPPORTED The command described by the SD Command Packet is not + supported by the host controller. + @retval EFI_BAD_BUFFER_SIZE The InTransferLength or OutTransferLength exceeds the + limit supported by SD card ( i.e. if the number of bytes + exceed the Last LBA). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_MMC_PASS_THRU_PASSTHRU) ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, + IN UINT8 Slot, + IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL +); + +/** + Used to retrieve next slot numbers supported by the SD controller. The function + returns information about all available slots (populated or not-populated). + + The GetNextSlot() function retrieves the next slot number on an SD controller. + If on input Slot is 0xFF, then the slot number of the first slot on the SD controller + is returned. + + If Slot is a slot number that was returned on a previous call to GetNextSlot(), then + the slot number of the next slot on the SD controller is returned. + + If Slot is not 0xFF and Slot was not returned on a previous call to GetNextSlot(), + EFI_INVALID_PARAMETER is returned. + + If Slot is the slot number of the last slot on the SD controller, then EFI_NOT_FOUND + is returned. + + @param[in] This A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance. + @param[in,out] Slot On input, a pointer to a slot number on the SD controller. + On output, a pointer to the next slot number on the SD controller. + An input value of 0xFF retrieves the first slot number on the SD + controller. + + @retval EFI_SUCCESS The next slot number on the SD controller was returned in Slot. + @retval EFI_NOT_FOUND There are no more slots on this SD controller. + @retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not returned on a previous call + to GetNextSlot(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_MMC_PASS_THRU_GET_NEXT_SLOT) ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 *Slot +); + +/** + Used to allocate and build a device path node for an SD card on the SD controller. + + The BuildDevicePath() function allocates and builds a single device node for the SD + card specified by Slot. + + If the SD card specified by Slot is not present on the SD controller, then EFI_NOT_FOUND + is returned. + + If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. + + If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES + is returned. + + Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of + DevicePath are initialized to describe the SD card specified by Slot, and EFI_SUCCESS is + returned. + + @param[in] This A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance. + @param[in] Slot Specifies the slot number of the SD card for which a device + path node is to be allocated and built. + @param[in,out] DevicePath A pointer to a single device path node that describes the SD + card specified by Slot. This function is responsible for + allocating the buffer DevicePath with the boot service + AllocatePool(). It is the caller's responsibility to free + DevicePath when the caller is finished with DevicePath. + + @retval EFI_SUCCESS The device path node that describes the SD card specified by + Slot was allocated and returned in DevicePath. + @retval EFI_NOT_FOUND The SD card specified by Slot does not exist on the SD controller. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_MMC_PASS_THRU_BUILD_DEVICE_PATH) ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, + IN UINT8 Slot, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath +); + +/** + This function retrieves an SD card slot number based on the input device path. + + The GetSlotNumber() function retrieves slot number for the SD card specified by + the DevicePath node. If DevicePath is NULL, EFI_INVALID_PARAMETER is returned. + + If DevicePath is not a device path node type that the SD Pass Thru driver supports, + EFI_UNSUPPORTED is returned. + + @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. + @param[in] DevicePath A pointer to the device path node that describes a SD + card on the SD controller. + @param[out] Slot On return, points to the slot number of an SD card on + the SD controller. + + @retval EFI_SUCCESS SD card slot number is returned in Slot. + @retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL. + @retval EFI_UNSUPPORTED DevicePath is not a device path node type that the SD + Pass Thru driver supports. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_MMC_PASS_THRU_GET_SLOT_NUMBER) ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT8 *Slot +); + +/** + Resets an SD card that is connected to the SD controller. + + The ResetDevice() function resets the SD card specified by Slot. + + If this SD controller does not support a device reset operation, EFI_UNSUPPORTED is + returned. + + If Slot is not in a valid slot number for this SD controller, EFI_INVALID_PARAMETER + is returned. + + If the device reset operation is completed, EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. + @param[in] Slot Specifies the slot number of the SD card to be reset. + + @retval EFI_SUCCESS The SD card specified by Slot was reset. + @retval EFI_UNSUPPORTED The SD controller does not support a device reset operation. + @retval EFI_INVALID_PARAMETER Slot number is invalid. + @retval EFI_NO_MEDIA SD Device not present in the Slot. + @retval EFI_DEVICE_ERROR The reset command failed due to a device error + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SD_MMC_PASS_THRU_RESET_DEVICE) ( + IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This, + IN UINT8 Slot +); + +struct _EFI_SD_MMC_PASS_THRU_PROTOCOL { + UINT32 IoAlign; + EFI_SD_MMC_PASS_THRU_PASSTHRU PassThru; + EFI_SD_MMC_PASS_THRU_GET_NEXT_SLOT GetNextSlot; + EFI_SD_MMC_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_SD_MMC_PASS_THRU_GET_SLOT_NUMBER GetSlotNumber; + EFI_SD_MMC_PASS_THRU_RESET_DEVICE ResetDevice; +}; + +extern EFI_GUID gEfiSdMmcPassThruProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security.h new file mode 100644 index 0000000..044b368 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security.h @@ -0,0 +1,103 @@ +/** @file + Security Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + Used to provide Security services. Specifically, dependening upon the + authentication state of a discovered driver in a Firmware Volume, the + portable DXE Core Dispatcher will call into the Security Architectural + Protocol (SAP) with the authentication state of the driver. + + This call-out allows for OEM-specific policy decisions to be made, such + as event logging for attested boots, locking flash in response to discovering + an unsigned driver or failed signature check, or other exception response. + + The SAP can also change system behavior by having the DXE core put a driver + in the Schedule-On-Request (SOR) state. This will allow for later disposition + of the driver by platform agent, such as Platform BDS. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_SECURITY_H__ +#define __ARCH_PROTOCOL_SECURITY_H__ + +/// +/// Global ID for the Security Code Architectural Protocol +/// +#define EFI_SECURITY_ARCH_PROTOCOL_GUID \ + { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } } + +typedef struct _EFI_SECURITY_ARCH_PROTOCOL EFI_SECURITY_ARCH_PROTOCOL; + +/** + The EFI_SECURITY_ARCH_PROTOCOL (SAP) is used to abstract platform-specific + policy from the DXE core response to an attempt to use a file that returns a + given status for the authentication check from the section extraction protocol. + + The possible responses in a given SAP implementation may include locking + flash upon failure to authenticate, attestation logging for all signed drivers, + and other exception operations. The File parameter allows for possible logging + within the SAP of the driver. + + If File is NULL, then EFI_INVALID_PARAMETER is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is not safe for the DXE Core to use under any circumstances, + then EFI_ACCESS_DENIED is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is not safe for the DXE Core to use right now, but it + might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is + returned. + + @param This The EFI_SECURITY_ARCH_PROTOCOL instance. + @param AuthenticationStatus + This is the authentication type returned from the Section + Extraction protocol. See the Section Extraction Protocol + Specification for details on this type. + @param File This is a pointer to the device path of the file that is + being dispatched. This will optionally be used for logging. + + @retval EFI_SUCCESS The file specified by File did authenticate, and the + platform policy dictates that the DXE Core may use File. + @retval EFI_INVALID_PARAMETER Driver is NULL. + @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and + the platform policy dictates that File should be placed + in the untrusted state. A file may be promoted from + the untrusted to the trusted state at a future time + with a call to the Trust() DXE Service. + @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and + the platform policy dictates that File should not be + used for any purpose. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE)( + IN CONST EFI_SECURITY_ARCH_PROTOCOL *This, + IN UINT32 AuthenticationStatus, + IN CONST EFI_DEVICE_PATH_PROTOCOL *File + ); + +/// +/// The EFI_SECURITY_ARCH_PROTOCOL is used to abstract platform-specific policy +/// from the DXE core. This includes locking flash upon failure to authenticate, +/// attestation logging, and other exception operations. +/// +struct _EFI_SECURITY_ARCH_PROTOCOL { + EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState; +}; + +extern EFI_GUID gEfiSecurityArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security2.h new file mode 100644 index 0000000..b4f0d86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Security2.h @@ -0,0 +1,107 @@ +/** @file + Security2 Architectural Protocol as defined in PI Specification1.2.1 VOLUME 2 DXE + + Abstracts security-specific functions from the DXE Foundation of UEFI Image Verification, + Trusted Computing Group (TCG) measured boot, and User Identity policy for image loading and + consoles. This protocol must be produced by a boot service or runtime DXE driver. + + This protocol is optional and must be published prior to the EFI_SECURITY_ARCH_PROTOCOL. + As a result, the same driver must publish both of these interfaces. + + When both Security and Security2 Architectural Protocols are published, LoadImage must use + them in accordance with the following rules: + The Security2 protocol must be used on every image being loaded. + The Security protocol must be used after the Securiy2 protocol and only on images that + have been read using Firmware Volume protocol. + + When only Security architectural protocol is published, LoadImage must use it on every image + being loaded. + + Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_SECURITY2_H__ +#define __ARCH_PROTOCOL_SECURITY2_H__ + +/// +/// Global ID for the Security2 Code Architectural Protocol +/// +#define EFI_SECURITY2_ARCH_PROTOCOL_GUID \ + { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } } + +typedef struct _EFI_SECURITY2_ARCH_PROTOCOL EFI_SECURITY2_ARCH_PROTOCOL; + +/** + The DXE Foundation uses this service to measure and/or verify a UEFI image. + + This service abstracts the invocation of Trusted Computing Group (TCG) measured boot, UEFI + Secure boot, and UEFI User Identity infrastructure. For the former two, the DXE Foundation + invokes the FileAuthentication() with a DevicePath and corresponding image in + FileBuffer memory. The TCG measurement code will record the FileBuffer contents into the + appropriate PCR. The image verification logic will confirm the integrity and provenance of the + image in FileBuffer of length FileSize . The origin of the image will be DevicePath in + these cases. + If the FileBuffer is NULL, the interface will determine if the DevicePath can be connected + in order to support the User Identification policy. + + @param This The EFI_SECURITY2_ARCH_PROTOCOL instance. + @param File A pointer to the device path of the file that is + being dispatched. This will optionally be used for logging. + @param FileBuffer A pointer to the buffer with the UEFI file image. + @param FileSize The size of the file. + @param BootPolicy A boot policy that was used to call LoadImage() UEFI service. If + FileAuthentication() is invoked not from the LoadImage(), + BootPolicy must be set to FALSE. + + @retval EFI_SUCCESS The file specified by DevicePath and non-NULL + FileBuffer did authenticate, and the platform policy dictates + that the DXE Foundation may use the file. + @retval EFI_SUCCESS The device path specified by NULL device path DevicePath + and non-NULL FileBuffer did authenticate, and the platform + policy dictates that the DXE Foundation may execute the image in + FileBuffer. + @retval EFI_SUCCESS FileBuffer is NULL and current user has permission to start + UEFI device drivers on the device path specified by DevicePath. + @retval EFI_SECURITY_VIOLATION The file specified by DevicePath and FileBuffer did not + authenticate, and the platform policy dictates that the file should be + placed in the untrusted state. The image has been added to the file + execution table. + @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not + authenticate, and the platform policy dictates that the DXE + Foundation may not use File. + @retval EFI_SECURITY_VIOLATION FileBuffer is NULL and the user has no + permission to start UEFI device drivers on the device path specified + by DevicePath. + @retval EFI_SECURITY_VIOLATION FileBuffer is not NULL and the user has no permission to load + drivers from the device path specified by DevicePath. The + image has been added into the list of the deferred images. +**/ +typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) ( + IN CONST EFI_SECURITY2_ARCH_PROTOCOL *This, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN VOID *FileBuffer, + IN UINTN FileSize, + IN BOOLEAN BootPolicy +); + +/// +/// The EFI_SECURITY2_ARCH_PROTOCOL is used to abstract platform-specific policy from the +/// DXE Foundation. This includes measuring the PE/COFF image prior to invoking, comparing the +/// image against a policy (whether a white-list/black-list of public image verification keys +/// or registered hashes). +/// +struct _EFI_SECURITY2_ARCH_PROTOCOL { + EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication; +}; + +extern EFI_GUID gEfiSecurity2ArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SecurityPolicy.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SecurityPolicy.h new file mode 100644 index 0000000..bedfd23 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SecurityPolicy.h @@ -0,0 +1,26 @@ +/** @file + Security Policy protocol as defined in PI Specification VOLUME 2 DXE + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SECURITY_POLICY_H_ +#define _SECURITY_POLICY_H_ + +/// +/// Security policy protocol GUID definition +/// +#define EFI_SECURITY_POLICY_PROTOCOL_GUID \ + {0x78E4D245, 0xCD4D, 0x4a05, {0xA2, 0xBA, 0x47, 0x43, 0xE8, 0x6C, 0xFC, 0xAB} } + +extern EFI_GUID gEfiSecurityPolicyProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SerialIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SerialIo.h new file mode 100644 index 0000000..bccf4fe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SerialIo.h @@ -0,0 +1,300 @@ +/** @file + Serial IO protocol as defined in the UEFI 2.0 specification. + + Abstraction of a basic serial device. Targeted at 16550 UART, but + could be much more generic. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SERIAL_IO_PROTOCOL_H__ +#define __SERIAL_IO_PROTOCOL_H__ + +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + { \ + 0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD } \ + } + +/// +/// Protocol GUID defined in EFI1.1. +/// +#define SERIAL_IO_PROTOCOL EFI_SERIAL_IO_PROTOCOL_GUID + +typedef struct _EFI_SERIAL_IO_PROTOCOL EFI_SERIAL_IO_PROTOCOL; + + +/// +/// Backward-compatible with EFI1.1. +/// +typedef EFI_SERIAL_IO_PROTOCOL SERIAL_IO_INTERFACE; + +/// +/// Parity type that is computed or checked as each character is transmitted or received. If the +/// device does not support parity, the value is the default parity value. +/// +typedef enum { + DefaultParity, + NoParity, + EvenParity, + OddParity, + MarkParity, + SpaceParity +} EFI_PARITY_TYPE; + +/// +/// Stop bits type +/// +typedef enum { + DefaultStopBits, + OneStopBit, + OneFiveStopBits, + TwoStopBits +} EFI_STOP_BITS_TYPE; + +// +// define for Control bits, grouped by read only, write only, and read write +// +// +// Read Only +// +#define EFI_SERIAL_CLEAR_TO_SEND 0x00000010 +#define EFI_SERIAL_DATA_SET_READY 0x00000020 +#define EFI_SERIAL_RING_INDICATE 0x00000040 +#define EFI_SERIAL_CARRIER_DETECT 0x00000080 +#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x00000100 +#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x00000200 + +// +// Write Only +// +#define EFI_SERIAL_REQUEST_TO_SEND 0x00000002 +#define EFI_SERIAL_DATA_TERMINAL_READY 0x00000001 + +// +// Read Write +// +#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x00001000 +#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x00002000 +#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x00004000 + +// +// Serial IO Member Functions +// +/** + Reset the serial device. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_RESET)( + IN EFI_SERIAL_IO_PROTOCOL *This + ); + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param This Protocol instance pointer. + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + @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. + @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. + @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. + @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. + @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. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_INVALID_PARAMETER One or more attributes has an unsupported value. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_ATTRIBUTES)( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +/** + Set the control bits on a serial device + + @param This Protocol instance pointer. + @param Control Set the bits of Control that are settable. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_CONTROL_BITS)( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ); + +/** + Retrieves the status of thecontrol bits on a serial device + + @param This Protocol instance pointer. + @param Control A pointer to return the current Control signals from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_GET_CONTROL_BITS)( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ); + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data actually written. + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_WRITE)( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data returned in Buffer. + @param Buffer The buffer to return the data into. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_READ)( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + @par Data Structure Description: + The data values in SERIAL_IO_MODE are read-only and are updated by the code + that produces the SERIAL_IO_PROTOCOL member functions. + + @param ControlMask + A mask for the Control bits that the device supports. The device + must always support the Input Buffer Empty control bit. + + @param TimeOut + If applicable, the number of microseconds to wait before timing out + a Read or Write operation. + + @param BaudRate + If applicable, the current baud rate setting of the device; otherwise, + baud rate has the value of zero to indicate that device runs at the + device's designed speed. + + @param ReceiveFifoDepth + The number of characters the device will buffer on input + + @param DataBits + The number of characters the device will buffer on input + + @param Parity + If applicable, this is the EFI_PARITY_TYPE that is computed or + checked as each character is transmitted or reveived. If the device + does not support parity the value is the default parity value. + + @param StopBits + If applicable, the EFI_STOP_BITS_TYPE number of stop bits per + character. If the device does not support stop bits the value is + the default stop bit values. + +**/ +typedef struct { + UINT32 ControlMask; + + // + // current Attributes + // + UINT32 Timeout; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 DataBits; + UINT32 Parity; + UINT32 StopBits; +} EFI_SERIAL_IO_MODE; + +#define EFI_SERIAL_IO_PROTOCOL_REVISION 0x00010000 +#define SERIAL_IO_INTERFACE_REVISION EFI_SERIAL_IO_PROTOCOL_REVISION + +/// +/// The Serial I/O protocol is used to communicate with UART-style serial devices. +/// These can be standard UART serial ports in PC-AT systems, serial ports attached +/// to a USB interface, or potentially any character-based I/O device. +/// +struct _EFI_SERIAL_IO_PROTOCOL { + /// + /// The revision to which the EFI_SERIAL_IO_PROTOCOL adheres. All future revisions + /// must be backwards compatible. If a future version is not backwards compatible, + /// it is not the same GUID. + /// + UINT32 Revision; + EFI_SERIAL_RESET Reset; + EFI_SERIAL_SET_ATTRIBUTES SetAttributes; + EFI_SERIAL_SET_CONTROL_BITS SetControl; + EFI_SERIAL_GET_CONTROL_BITS GetControl; + EFI_SERIAL_WRITE Write; + EFI_SERIAL_READ Read; + /// + /// Pointer to SERIAL_IO_MODE data. + /// + EFI_SERIAL_IO_MODE *Mode; +}; + +extern EFI_GUID gEfiSerialIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ServiceBinding.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ServiceBinding.h new file mode 100644 index 0000000..4bffd2e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ServiceBinding.h @@ -0,0 +1,94 @@ +/** @file + UEFI Service Binding Protocol is defined in UEFI specification. + + The file defines the generic Service Binding Protocol functions. + It provides services that are required to create and destroy child + handles that support a given set of protocols. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_SERVICE_BINDING_H__ +#define __EFI_SERVICE_BINDING_H__ + +/// +/// Forward reference for pure ANSI compatability +/// +typedef struct _EFI_SERVICE_BINDING_PROTOCOL EFI_SERVICE_BINDING_PROTOCOL; + +/** + Creates a child handle and installs a protocol. + + The CreateChild() function installs a protocol on ChildHandle. + If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. + + @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @param ChildHandle Pointer to the handle of the child to create. If it is NULL, + then a new handle is created. If it is a pointer to an existing UEFI handle, + then the protocol is added to the existing UEFI handle. + + @retval EFI_SUCCES The protocol was added to ChildHandle. + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create + the child + @retval other The child handle was not created + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERVICE_BINDING_CREATE_CHILD)( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN OUT EFI_HANDLE *ChildHandle + ); + +/** + Destroys a child handle with a protocol installed on it. + + The DestroyChild() function does the opposite of CreateChild(). It removes a protocol + that was installed by CreateChild() from ChildHandle. If the removed protocol is the + last protocol on ChildHandle, then ChildHandle is destroyed. + + @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @param ChildHandle Handle of the child to destroy + + @retval EFI_SUCCES The protocol was removed from ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. + @retval EFI_INVALID_PARAMETER Child handle is NULL. + @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle + because its services are being used. + @retval other The child handle was not destroyed + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERVICE_BINDING_DESTROY_CHILD)( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ); + +/// +/// The EFI_SERVICE_BINDING_PROTOCOL provides member functions to create and destroy +/// child handles. A driver is responsible for adding protocols to the child handle +/// in CreateChild() and removing protocols in DestroyChild(). It is also required +/// that the CreateChild() function opens the parent protocol BY_CHILD_CONTROLLER +/// to establish the parent-child relationship, and closes the protocol in DestroyChild(). +/// The pseudo code for CreateChild() and DestroyChild() is provided to specify the +/// required behavior, not to specify the required implementation. Each consumer of +/// a software protocol is responsible for calling CreateChild() when it requires the +/// protocol and calling DestroyChild() when it is finished with that protocol. +/// +struct _EFI_SERVICE_BINDING_PROTOCOL { + EFI_SERVICE_BINDING_CREATE_CHILD CreateChild; + EFI_SERVICE_BINDING_DESTROY_CHILD DestroyChild; +}; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Shell.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Shell.h new file mode 100644 index 0000000..cbcd1ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Shell.h @@ -0,0 +1,1268 @@ +/** @file + EFI Shell protocol as defined in the UEFI Shell 2.0 specification including errata. + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_SHELL_PROTOCOL_H__ +#define __EFI_SHELL_PROTOCOL_H__ + +#include + +#define EFI_SHELL_PROTOCOL_GUID \ + { \ + 0x6302d008, 0x7f9b, 0x4f30, { 0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e } \ + } +typedef VOID *SHELL_FILE_HANDLE; + +typedef enum { + /// + /// The operation completed successfully. + /// + SHELL_SUCCESS = 0, + + /// + /// The image failed to load. + /// + SHELL_LOAD_ERROR = 1, + + /// + /// The parameter was incorrect. + /// + SHELL_INVALID_PARAMETER = 2, + + /// + /// The operation is not supported. + /// + SHELL_UNSUPPORTED = 3, + + /// + /// The buffer was not the proper size for the request. + /// + SHELL_BAD_BUFFER_SIZE = 4, + + /// + /// The buffer was not large enough to hold the requested data. + /// The required buffer size is returned in the appropriate + /// parameter when this error occurs. + /// + SHELL_BUFFER_TOO_SMALL = 5, + + /// + /// There is no data pending upon return. + /// + SHELL_NOT_READY = 6, + + /// + /// The physical device reported an error while attempting the + /// operation. + /// + SHELL_DEVICE_ERROR = 7, + + /// + /// The device cannot be written to. + /// + SHELL_WRITE_PROTECTED = 8, + + /// + /// The resource has run out. + /// + SHELL_OUT_OF_RESOURCES = 9, + + /// + /// An inconsistency was detected on the file system causing the + /// operation to fail. + /// + SHELL_VOLUME_CORRUPTED = 10, + + /// + /// There is no more space on the file system. + /// + SHELL_VOLUME_FULL = 11, + + /// + /// The device does not contain any medium to perform the + /// operation. + /// + SHELL_NO_MEDIA = 12, + + /// + /// The medium in the device has changed since the last + /// access. + /// + SHELL_MEDIA_CHANGED = 13, + + /// + /// The item was not found. + /// + SHELL_NOT_FOUND = 14, + + /// + /// Access was denied. + /// + SHELL_ACCESS_DENIED = 15, + + // note the skipping of 16 and 17 + + /// + /// A timeout time expired. + /// + SHELL_TIMEOUT = 18, + + /// + /// The protocol has not been started. + /// + SHELL_NOT_STARTED = 19, + + /// + /// The protocol has already been started. + /// + SHELL_ALREADY_STARTED = 20, + + /// + /// The operation was aborted. + /// + SHELL_ABORTED = 21, + + // note the skipping of 22, 23, and 24 + + /// + /// A function encountered an internal version that was + /// incompatible with a version requested by the caller. + /// + SHELL_INCOMPATIBLE_VERSION = 25, + + /// + /// The function was not performed due to a security violation. + /// + SHELL_SECURITY_VIOLATION = 26, + + /// + /// The function was performed and resulted in an unequal + /// comparison.. + /// + SHELL_NOT_EQUAL = 27 +} SHELL_STATUS; + + +// replaced EFI_LIST_ENTRY with LIST_ENTRY for simplicity. +// they are identical outside of the name. +typedef struct { + LIST_ENTRY Link; ///< Linked list members. + EFI_STATUS Status; ///< Status of opening the file. Valid only if Handle != NULL. + CONST CHAR16 *FullName; ///< Fully qualified filename. + CONST CHAR16 *FileName; ///< name of this file. + SHELL_FILE_HANDLE Handle; ///< Handle for interacting with the opened file or NULL if closed. + EFI_FILE_INFO *Info; ///< Pointer to the FileInfo struct for this file or NULL. +} EFI_SHELL_FILE_INFO; + +/** + Returns whether any script files are currently being processed. + + @retval TRUE There is at least one script file active. + @retval FALSE No script files are active now. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_SHELL_BATCH_IS_ACTIVE) ( + VOID + ); + +/** + Closes the file handle. + + This function closes a specified file handle. All 'dirty' cached file data is + flushed to the device, and the file is closed. In all cases, the handle is + closed. + + @param[in] FileHandle The file handle to be closed. + + @retval EFI_SUCCESS The file closed sucessfully. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_CLOSE_FILE)( + IN SHELL_FILE_HANDLE FileHandle + ); + +/** + Creates a file or directory by name. + + This function creates an empty new file or directory with the specified attributes and + returns the new file's handle. If the file already exists and is read-only, then + EFI_INVALID_PARAMETER will be returned. + + If the file already existed, it is truncated and its attributes updated. If the file is + created successfully, the FileHandle is the file's handle, else, the FileHandle is NULL. + + If the file name begins with >v, then the file handle which is returned refers to the + shell environment variable with the specified name. If the shell environment variable + already exists and is non-volatile then EFI_INVALID_PARAMETER is returned. + + @param[in] FileName Pointer to NULL-terminated file path. + @param[in] FileAttribs The new file's attrbiutes. The different attributes are + described in EFI_FILE_PROTOCOL.Open(). + @param[out] FileHandle On return, points to the created file handle or directory's handle. + + @retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The file path could not be opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device, or could not + file the file system on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according + the DirName. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_CREATE_FILE)( + IN CONST CHAR16 *FileName, + IN UINT64 FileAttribs, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + Deletes the file specified by the file handle. + + This function closes and deletes a file. In all cases, the file handle is closed. If the file + cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is returned, but the + handle is still closed. + + @param[in] FileHandle The file handle to delete. + + @retval EFI_SUCCESS The file was closed and deleted and the handle was closed. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_DELETE_FILE)( + IN SHELL_FILE_HANDLE FileHandle + ); + +/** + Deletes the file specified by the file name. + + This function deletes a file. + + @param[in] FileName Points to the NULL-terminated file name. + + @retval EFI_SUCCESS The file was deleted. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_DELETE_FILE_BY_NAME)( + IN CONST CHAR16 *FileName + ); + +/** + Disables the page break output mode. +**/ +typedef +VOID +(EFIAPI *EFI_SHELL_DISABLE_PAGE_BREAK) ( + VOID + ); + +/** + Enables the page break output mode. +**/ +typedef +VOID +(EFIAPI *EFI_SHELL_ENABLE_PAGE_BREAK) ( + VOID + ); + +/** + Execute the command line. + + This function creates a nested instance of the shell and executes the specified + command (CommandLine) with the specified environment (Environment). Upon return, + the status code returned by the specified command is placed in StatusCode. + + If Environment is NULL, then the current environment is used and all changes made + by the commands executed will be reflected in the current environment. If the + Environment is non-NULL, then the changes made will be discarded. + + The CommandLine is executed from the current working directory on the current + device. + + @param[in] ParentImageHandle A handle of the image that is executing the specified + command line. + @param[in] CommandLine Points to the NULL-terminated UCS-2 encoded string + containing the command line. If NULL then the command- + line will be empty. + @param[in] Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. If this + is NULL, then the current shell environment is used. + @param[out] ErrorCode Points to the status code returned by the command. + + @retval EFI_SUCCESS The command executed successfully. The status code + returned by the command is pointed to by StatusCode. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Nested shell invocations are not allowed. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_EXECUTE) ( + IN EFI_HANDLE *ParentImageHandle, + IN CHAR16 *CommandLine OPTIONAL, + IN CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StatusCode OPTIONAL + ); + +/** + Find files that match a specified pattern. + + This function searches for all files and directories that match the specified + FilePattern. The FilePattern can contain wild-card characters. The resulting file + information is placed in the file list FileList. + + The files in the file list are not opened. The OpenMode field is set to 0 and the FileInfo + field is set to NULL. + + @param[in] FilePattern Points to a NULL-terminated shell file path, including wildcards. + @param[out] FileList On return, points to the start of a file list containing the names + of all matching files or else points to NULL if no matching files + were found. + + @retval EFI_SUCCESS Files found. + @retval EFI_NOT_FOUND No files found. + @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. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_FIND_FILES)( + IN CONST CHAR16 *FilePattern, + OUT EFI_SHELL_FILE_INFO **FileList + ); + +/** + Find all files in a specified directory. + + @param[in] FileDirHandle Handle of the directory to search. + @param[out] FileList On return, points to the list of files in the directory + or NULL if there are no files in the directory. + + @retval EFI_SUCCESS File information was returned successfully. + @retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_NO_MEDIA The device media is not present. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_FIND_FILES_IN_DIR)( +IN SHELL_FILE_HANDLE FileDirHandle, +OUT EFI_SHELL_FILE_INFO **FileList +); + +/** + Flushes data back to a device. + + This function flushes all modified data associated with a file to a device. + + @param[in] FileHandle The handle of the file to flush. + + @retval EFI_SUCCESS The data was flushed. + @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. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_FLUSH_FILE)( + IN SHELL_FILE_HANDLE FileHandle + ); + +/** + Frees the file list. + + This function cleans up the file list and any related data structures. It has no + impact on the files themselves. + + @param[in] FileList The file list to free. Type EFI_SHELL_FILE_INFO is + defined in OpenFileList(). + + @retval EFI_SUCCESS Free the file list successfully. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_FREE_FILE_LIST) ( + IN EFI_SHELL_FILE_INFO **FileList + ); + +/** + Returns the current directory on the specified device. + + If FileSystemMapping is NULL, it returns the current working directory. If the + FileSystemMapping is not NULL, it returns the current directory associated with the + FileSystemMapping. In both cases, the returned name includes the file system + mapping (i.e. fs0:\current-dir). + + Note that the current directory string should exclude the tailing backslash character. + + @param[in] FileSystemMapping A pointer to the file system mapping. If NULL, + then the current working directory is returned. + + @retval !=NULL The current directory. + @retval NULL Current directory does not exist. +**/ +typedef +CONST CHAR16 * +(EFIAPI *EFI_SHELL_GET_CUR_DIR) ( + IN CONST CHAR16 *FileSystemMapping OPTIONAL + ); + +typedef UINT32 EFI_SHELL_DEVICE_NAME_FLAGS; +#define EFI_DEVICE_NAME_USE_COMPONENT_NAME 0x00000001 +#define EFI_DEVICE_NAME_USE_DEVICE_PATH 0x00000002 + +/** + Gets the name of the device specified by the device handle. + + This function gets the user-readable name of the device specified by the device + handle. If no user-readable name could be generated, then *BestDeviceName will be + NULL and EFI_NOT_FOUND will be returned. + + If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the + device's name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on + DeviceHandle. + + If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the + device's name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle. + If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and + EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then + EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority. + + @param[in] DeviceHandle The handle of the device. + @param[in] Flags Determines the possible sources of component names. + @param[in] Language A pointer to the language specified for the device + name, in the same format as described in the UEFI + specification, Appendix M. + @param[out] BestDeviceName On return, points to the callee-allocated NULL- + terminated name of the device. If no device name + could be found, points to NULL. The name must be + freed by the caller... + + @retval EFI_SUCCESS Get the name successfully. + @retval EFI_NOT_FOUND Fail to get the device name. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_GET_DEVICE_NAME) ( + IN EFI_HANDLE DeviceHandle, + IN EFI_SHELL_DEVICE_NAME_FLAGS Flags, + IN CHAR8 *Language, + OUT CHAR16 **BestDeviceName + ); + +/** + Gets the device path from the mapping. + + This function gets the device path associated with a mapping. + + @param[in] Mapping A pointer to the mapping + + @retval !=NULL Pointer to the device path that corresponds to the + device mapping. The returned pointer does not need + to be freed. + @retval NULL There is no device path associated with the + specified mapping. +**/ +typedef +CONST EFI_DEVICE_PATH_PROTOCOL * +(EFIAPI *EFI_SHELL_GET_DEVICE_PATH_FROM_MAP) ( + IN CONST CHAR16 *Mapping + ); + +/** + Converts a file system style name to a device path. + + This function converts a file system style name to a device path, by replacing any + mapping references to the associated device path. + + @param[in] Path The pointer to the path. + + @return The pointer of the file path. The file path is callee + allocated and should be freed by the caller. +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL * +(EFIAPI *EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH) ( + IN CONST CHAR16 *Path + ); + +/** + Gets either a single or list of environment variables. + + If name is not NULL then this function returns the current value of the specified + environment variable. + + If Name is NULL than a list of all environment variable names is returned. Each a + NULL terminated string with a double NULL terminating the list. + + @param[in] Name A pointer to the environment variable name. If + Name is NULL, then the function will return all + of the defined shell environment variables. In + the case where multiple environment variables are + being returned, each variable will be terminated by + a NULL, and the list will be terminated by a double + NULL. + + @return A pointer to the returned string. + The returned pointer does not need to be freed by the caller. + + @retval NULL The environment variable doesn't exist or there are + no environment variables. +**/ +typedef +CONST CHAR16 * +(EFIAPI *EFI_SHELL_GET_ENV) ( + IN CONST CHAR16 *Name OPTIONAL + ); + +/** + Gets the environment variable and Attributes, or list of environment variables. Can be + used instead of GetEnv(). + + This function returns the current value of the specified environment variable and + the Attributes. If no variable name was specified, then all of the known + variables will be returned. + + @param[in] Name A pointer to the environment variable name. If Name is NULL, + then the function will return all of the defined shell + environment variables. In the case where multiple environment + variables are being returned, each variable will be terminated + by a NULL, and the list will be terminated by a double NULL. + @param[out] Attributes If not NULL, a pointer to the returned attributes bitmask for + the environment variable. In the case where Name is NULL, and + multiple environment variables are being returned, Attributes + is undefined. + + @retval NULL The environment variable doesn't exist. + @return The environment variable's value. The returned pointer does not + need to be freed by the caller. +**/ +typedef +CONST CHAR16 * +(EFIAPI *EFI_SHELL_GET_ENV_EX) ( + IN CONST CHAR16 *Name, + OUT UINT32 *Attributes OPTIONAL + ); + +/** + Gets the file information from an open file handle. + + This function allocates a buffer to store the file's information. It's the caller's + responsibility to free the buffer. + + @param[in] FileHandle A File Handle. + + @retval NULL Cannot get the file info. + @return A pointer to a buffer with file information. +**/ +typedef +EFI_FILE_INFO * +(EFIAPI *EFI_SHELL_GET_FILE_INFO)( + IN SHELL_FILE_HANDLE FileHandle + ); + +/** + Converts a device path to a file system-style path. + + This function converts a device path to a file system path by replacing part, or all, of + the device path with the file-system mapping. If there are more than one application + file system mappings, the one that most closely matches Path will be used. + + @param[in] Path The pointer to the device path. + + @return The pointer of the NULL-terminated file path. The path + is callee-allocated and should be freed by the caller. +**/ +typedef +CHAR16 * +(EFIAPI *EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Path + ); + +/** + Gets a file's current position. + + This function returns 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. + + @param[in] FileHandle The file handle on which to get the current position. + @param[out] Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was accessed. + @retval EFI_UNSUPPORTED The request is not valid on open directories. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_GET_FILE_POSITION)( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ); + +/** + Gets the size of a file. + + This function returns the size of the file specified by FileHandle. + + @param[in] FileHandle The handle of the file. + @param[out] Size The size of this file. + + @retval EFI_SUCCESS Get the file's size. + @retval EFI_DEVICE_ERROR Can't access the file. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_GET_FILE_SIZE)( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ); + +/** + Get the GUID value from a human readable name. + + If GuidName is a known GUID name, then update Guid to have the correct value for + that GUID. + + This function is only available when the major and minor versions in the + EfiShellProtocol are greater than or equal to 2 and 1, respectively. + + @param[in] GuidName A pointer to the localized name for the GUID being queried. + @param[out] Guid A pointer to the GUID structure to be filled in. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Guid was NULL. + @retval EFI_INVALID_PARAMETER GuidName was NULL. + @retval EFI_NOT_FOUND GuidName is not a known GUID Name. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_GET_GUID_FROM_NAME)( + IN CONST CHAR16 *GuidName, + OUT EFI_GUID *Guid + ); + +/** + Get the human readable name for a GUID from the value. + + If Guid is assigned a name, then update *GuidName to point to the name. The callee + should not modify the value. + + This function is only available when the major and minor versions in the + EfiShellProtocol are greater than or equal to 2 and 1, respectively. + + @param[in] Guid A pointer to the GUID being queried. + @param[out] GuidName A pointer to a pointer the localized to name for the GUID being requested + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Guid was NULL. + @retval EFI_INVALID_PARAMETER GuidName was NULL. + @retval EFI_NOT_FOUND Guid is not assigned a name. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_GET_GUID_NAME)( + IN CONST EFI_GUID *Guid, + OUT CONST CHAR16 **GuidName + ); + +/** + Return help information about a specific command. + + This function returns the help information for the specified command. The help text + can be internal to the shell or can be from a UEFI Shell manual page. + + If Sections is specified, then each section name listed will be compared in a casesensitive + manner, to the section names described in Appendix B. If the section exists, + it will be appended to the returned help text. If the section does not exist, no + information will be returned. If Sections is NULL, then all help text information + available will be returned. + + @param[in] Command Points to the NULL-terminated UEFI Shell command name. + @param[in] Sections Points to the NULL-terminated comma-delimited + section names to return. If NULL, then all + sections will be returned. + @param[out] HelpText On return, points to a callee-allocated buffer + containing all specified help text. + + @retval EFI_SUCCESS The help text was returned. + @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the + returned help text. + @retval EFI_INVALID_PARAMETER HelpText is NULL. + @retval EFI_NOT_FOUND There is no help text available for Command. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_GET_HELP_TEXT) ( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Sections OPTIONAL, + OUT CHAR16 **HelpText + ); + +/** + Gets the mapping(s) that most closely matches the device path. + + This function gets the mapping which corresponds to the device path *DevicePath. If + there is no exact match, then the mapping which most closely matches *DevicePath + is returned, and *DevicePath is updated to point to the remaining portion of the + device path. If there is an exact match, the mapping is returned and *DevicePath + points to the end-of-device-path node. + + If there are multiple map names they will be semi-colon seperated in the + NULL-terminated string. + + @param[in, out] DevicePath On entry, points to a device path pointer. On + exit, updates the pointer to point to the + portion of the device path after the mapping. + + @retval NULL No mapping was found. + @retval !=NULL Pointer to NULL-terminated mapping. The buffer + is callee allocated and should be freed by the caller. +**/ +typedef +CONST CHAR16 * +(EFIAPI *EFI_SHELL_GET_MAP_FROM_DEVICE_PATH) ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Gets the enable status of the page break output mode. + + User can use this function to determine current page break mode. + + @retval TRUE The page break output mode is enabled. + @retval FALSE The page break output mode is disabled. +**/ +typedef +BOOLEAN +(EFIAPI *EFI_SHELL_GET_PAGE_BREAK) ( + VOID + ); + +/** + Judges whether the active shell is the root shell. + + This function makes the user to know that whether the active Shell is the root shell. + + @retval TRUE The active Shell is the root Shell. + @retval FALSE The active Shell is NOT the root Shell. +**/ +typedef +BOOLEAN +(EFIAPI *EFI_SHELL_IS_ROOT_SHELL) ( +VOID +); + +/** + Opens a file or a directory by file name. + + This function opens the specified file in the specified OpenMode and returns a file + handle. + If the file name begins with '>v', then the file handle which is returned refers to the + shell environment variable with the specified name. If the shell environment variable + exists, is non-volatile and the OpenMode indicates EFI_FILE_MODE_WRITE, then + EFI_INVALID_PARAMETER is returned. + + If the file name is '>i', then the file handle which is returned refers to the standard + input. If the OpenMode indicates EFI_FILE_MODE_WRITE, then EFI_INVALID_PARAMETER + is returned. + + If the file name is '>o', then the file handle which is returned refers to the standard + output. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER + is returned. + + If the file name is '>e', then the file handle which is returned refers to the standard + error. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER + is returned. + + If the file name is 'NUL', then the file handle that is returned refers to the standard NUL + file. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER is + returned. + + If return EFI_SUCCESS, the FileHandle is the opened file's handle, else, the + FileHandle is NULL. + + @param[in] FileName Points to the NULL-terminated UCS-2 encoded file name. + @param[out] FileHandle On return, points to the file handle. + @param[in] OpenMode File open mode. Either EFI_FILE_MODE_READ or + EFI_FILE_MODE_WRITE from section 12.4 of the UEFI + Specification. + @retval EFI_SUCCESS The file was opened. FileHandle has the opened file's handle. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. FileHandle is NULL. + @retval EFI_UNSUPPORTED Could not open the file path. FileHandle is NULL. + @retval EFI_NOT_FOUND The specified file could not be found on the device or the file + system could not be found on the device. FileHandle is NULL. + @retval EFI_NO_MEDIA The device has no medium. FileHandle is NULL. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. FileHandle is NULL. + @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according + the FileName. FileHandle is NULL. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. FileHandle is NULL. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. FileHandle is NULL. + @retval EFI_ACCESS_DENIED The service denied access to the file. FileHandle is NULL. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. FileHandle + is NULL. + @retval EFI_VOLUME_FULL The volume is full. FileHandle is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_OPEN_FILE_BY_NAME) ( + IN CONST CHAR16 *FileName, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode + ); + +/** + Opens the files that match the path specified. + + This function opens all of the files specified by Path. Wildcards are processed + according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. Each + matching file has an EFI_SHELL_FILE_INFO structure created in a linked list. + + @param[in] Path A pointer to the path string. + @param[in] OpenMode Specifies the mode used to open each file, EFI_FILE_MODE_READ or + EFI_FILE_MODE_WRITE. + @param[in, out] FileList Points to the start of a list of files opened. + + @retval EFI_SUCCESS Create the file list successfully. + @return Can't create the file list. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_OPEN_FILE_LIST) ( + IN CHAR16 *Path, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **FileList + ); + +/** + Opens the root directory of a device. + + This function opens the root directory of a device and returns a file handle to it. + + @param[in] DevicePath Points to the device path corresponding to the device where the + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed. + @param[out] FileHandle On exit, points to the file handle corresponding to the root directory on the + device. + + @retval EFI_SUCCESS Root opened successfully. + @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory + could not be opened. + @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted. + @retval EFI_DEVICE_ERROR The device had an error. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_OPEN_ROOT)( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + Opens the root directory of a device on a handle. + + This function opens the root directory of a device and returns a file handle to it. + + @param[in] DeviceHandle The handle of the device that contains the volume. + @param[out] FileHandle On exit, points to the file handle corresponding to the root directory on the + device. + + @retval EFI_SUCCESS Root opened successfully. + @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory + could not be opened. + @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted. + @retval EFI_DEVICE_ERROR The device had an error. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_OPEN_ROOT_BY_HANDLE)( + IN EFI_HANDLE DeviceHandle, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + Reads data from the 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, then an error is returned. + + @param[in] FileHandle The opened file handle for read. + @param[in] ReadSize On input, the size of Buffer, in bytes. On output, the amount of data read. + @param[in, out] Buffer The buffer in which data is read. + + @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. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_READ_FILE) ( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN *ReadSize, + IN OUT VOID *Buffer + ); + +/** + Register a GUID and a localized human readable name for it. + + If Guid is not assigned a name, then assign GuidName to Guid. This list of GUID + names must be used whenever a shell command outputs GUID information. + + This function is only available when the major and minor versions in the + EfiShellProtocol are greater than or equal to 2 and 1, respectively. + + @param[in] Guid A pointer to the GUID being registered. + @param[in] GuidName A pointer to the localized name for the GUID being registered. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Guid was NULL. + @retval EFI_INVALID_PARAMETER GuidName was NULL. + @retval EFI_ACCESS_DENIED Guid already is assigned a name. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_REGISTER_GUID_NAME)( + IN CONST EFI_GUID *Guid, + IN CONST CHAR16 *GuidName + ); + +/** + Deletes the duplicate file names files in the given file list. + + @param[in] FileList A pointer to the first entry in the file list. + + @retval EFI_SUCCESS Always success. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_REMOVE_DUP_IN_FILE_LIST) ( + IN EFI_SHELL_FILE_INFO **FileList + ); + +/** + Changes a shell command alias. + + This function creates an alias for a shell command. + + @param[in] Command Points to the NULL-terminated shell command or existing alias. + @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and + Command refers to an alias, that alias will be deleted. + @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If + FALSE and the alias already exists, then the existing alias is unchanged and + EFI_ACCESS_DENIED is returned. + @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the + Alias being set will be stored in a non-volatile fashion. + + @retval EFI_SUCCESS Alias created or deleted successfully. + @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to + FALSE. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_SET_ALIAS)( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias, + IN BOOLEAN Replace, + IN BOOLEAN Volatile + ); + +/** + This function returns the command associated with a alias or a list of all + alias'. + + @param[in] Alias Points to the NULL-terminated shell alias. + If this parameter is NULL, then all + aliases will be returned in ReturnedData. + @param[out] Volatile Upon return of a single command if TRUE indicates + this is stored in a volatile fashion. FALSE otherwise. + @return If Alias is not NULL, it will return a pointer to + the NULL-terminated command for that alias. + If Alias is NULL, ReturnedData points to a ';' + delimited list of alias (e.g. + ReturnedData = "dir;del;copy;mfp") that is NULL-terminated. + @retval NULL An error ocurred. + @retval NULL Alias was not a valid Alias. +**/ +typedef +CONST CHAR16 * +(EFIAPI *EFI_SHELL_GET_ALIAS)( + IN CONST CHAR16 *Alias, + OUT BOOLEAN *Volatile OPTIONAL + ); + +/** + Changes the current directory on the specified device. + + If the FileSystem is NULL, and the directory Dir does not contain a file system's + mapped name, this function changes the current working directory. If FileSystem is + NULL and the directory Dir contains a mapped name, then the current file system and + the current directory on that file system are changed. + + If FileSystem is not NULL, and Dir is NULL, then this changes the current working file + system. + + If FileSystem is not NULL and Dir is not NULL, then this function changes the current + directory on the specified file system. + + If the current working directory or the current working file system is changed then the + %cwd% environment variable will be updated. + + @param[in] FileSystem A pointer to the file system's mapped name. If NULL, then the current working + directory is changed. + @param[in] Dir Points to the NULL-terminated directory on the device specified by FileSystem. + + @retval NULL Current directory does not exist. + @return The current directory. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_SET_CUR_DIR) ( + IN CONST CHAR16 *FileSystem OPTIONAL, + IN CONST CHAR16 *Dir + ); + +/** + Sets the environment variable. + + This function changes the current value of the specified environment variable. If the + environment variable exists and the Value is an empty string, then the environment + variable is deleted. If the environment variable exists and the Value is not an empty + string, then the value of the environment variable is changed. If the environment + variable does not exist and the Value is an empty string, there is no action. If the + environment variable does not exist and the Value is a non-empty string, then the + environment variable is created and assigned the specified value. + + For a description of volatile and non-volatile environment variables, see UEFI Shell + 2.0 specification section 3.6.1. + + @param[in] Name Points to the NULL-terminated environment variable name. + @param[in] Value Points to the NULL-terminated environment variable value. If the value is an + empty string then the environment variable is deleted. + @param[in] Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS The environment variable was successfully updated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_SET_ENV) ( + IN CONST CHAR16 *Name, + IN CONST CHAR16 *Value, + IN BOOLEAN Volatile + ); + +/** + Sets the file information to an opened file handle. + + This function changes file information. All file information in the EFI_FILE_INFO + struct will be updated to the passed in data. + + @param[in] FileHandle A file handle. + @param[in] FileInfo Points to new file information. + + @retval EFI_SUCCESS The information was set. + @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. + @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of EFI_FILE_INFO. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_SET_FILE_INFO)( + IN SHELL_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO *FileInfo + ); + +/** + Sets a file's current position. + + 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. + + @param[in] FileHandle The file handle on which requested position will be set. + @param[in] Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open directories. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_SET_FILE_POSITION)( + IN SHELL_FILE_HANDLE FileHandle, + IN UINT64 Position + ); + +/** + This function creates a mapping for a device path. + + @param[in] DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping, + then the mapping will be deleted. + @param[in] Mapping Points to the NULL-terminated mapping for the device path. + + @retval EFI_SUCCESS Mapping created or deleted successfully. + @retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath. See the + boot service function LocateDevicePath(). + @retval EFI_ACCESS_DENIED The mapping is a built-in alias. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_SET_MAP)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST CHAR16 *Mapping + ); + +/** + Writes data to the 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 automatically grows to + hold the data, if required. + + Direct writes to opened directories are not supported. + + @param[in] FileHandle The opened file handle for writing. + @param[in, out] BufferSize On input, size of Buffer. + @param[in] Buffer The buffer in which data to write. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to 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. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SHELL_WRITE_FILE)( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +// +// EFI_SHELL_PROTOCOL has been updated since UEFI Shell Spec 2.0 +// Usage of this protocol will require version checking before attempting +// to use any new members. There is no need to check the version for +// members that existed in UEFI Shell Spec 2.0. +// +// Update below for any future UEFI Shell spec changes to this protocol. +// +// Check EFI_SHELL_PROTOCOL MajorVersion and MinorVersion: +// if ((2 == gEfiShellProtocol->MajorVersion) && +// (0 == gEfiShellProtocol->MinorVersion)) { +// // +// // Cannot call: +// // RegisterGuidName - UEFI Shell 2.1 +// // GetGuidName - UEFI Shell 2.1 +// // GetGuidFromName - UEFI Shell 2.1 +// // GetEnvEx - UEFI Shell 2.1 +// // +// } else { +// // +// // Can use all members +// // +// } +// +typedef struct _EFI_SHELL_PROTOCOL { + EFI_SHELL_EXECUTE Execute; + EFI_SHELL_GET_ENV GetEnv; + EFI_SHELL_SET_ENV SetEnv; + EFI_SHELL_GET_ALIAS GetAlias; + EFI_SHELL_SET_ALIAS SetAlias; + EFI_SHELL_GET_HELP_TEXT GetHelpText; + EFI_SHELL_GET_DEVICE_PATH_FROM_MAP GetDevicePathFromMap; + EFI_SHELL_GET_MAP_FROM_DEVICE_PATH GetMapFromDevicePath; + EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH GetDevicePathFromFilePath; + EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH GetFilePathFromDevicePath; + EFI_SHELL_SET_MAP SetMap; + EFI_SHELL_GET_CUR_DIR GetCurDir; + EFI_SHELL_SET_CUR_DIR SetCurDir; + EFI_SHELL_OPEN_FILE_LIST OpenFileList; + EFI_SHELL_FREE_FILE_LIST FreeFileList; + EFI_SHELL_REMOVE_DUP_IN_FILE_LIST RemoveDupInFileList; + EFI_SHELL_BATCH_IS_ACTIVE BatchIsActive; + EFI_SHELL_IS_ROOT_SHELL IsRootShell; + EFI_SHELL_ENABLE_PAGE_BREAK EnablePageBreak; + EFI_SHELL_DISABLE_PAGE_BREAK DisablePageBreak; + EFI_SHELL_GET_PAGE_BREAK GetPageBreak; + EFI_SHELL_GET_DEVICE_NAME GetDeviceName; + EFI_SHELL_GET_FILE_INFO GetFileInfo; + EFI_SHELL_SET_FILE_INFO SetFileInfo; + EFI_SHELL_OPEN_FILE_BY_NAME OpenFileByName; + EFI_SHELL_CLOSE_FILE CloseFile; + EFI_SHELL_CREATE_FILE CreateFile; + EFI_SHELL_READ_FILE ReadFile; + EFI_SHELL_WRITE_FILE WriteFile; + EFI_SHELL_DELETE_FILE DeleteFile; + EFI_SHELL_DELETE_FILE_BY_NAME DeleteFileByName; + EFI_SHELL_GET_FILE_POSITION GetFilePosition; + EFI_SHELL_SET_FILE_POSITION SetFilePosition; + EFI_SHELL_FLUSH_FILE FlushFile; + EFI_SHELL_FIND_FILES FindFiles; + EFI_SHELL_FIND_FILES_IN_DIR FindFilesInDir; + EFI_SHELL_GET_FILE_SIZE GetFileSize; + EFI_SHELL_OPEN_ROOT OpenRoot; + EFI_SHELL_OPEN_ROOT_BY_HANDLE OpenRootByHandle; + EFI_EVENT ExecutionBreak; + UINT32 MajorVersion; + UINT32 MinorVersion; + // Added for Shell 2.1 + EFI_SHELL_REGISTER_GUID_NAME RegisterGuidName; + EFI_SHELL_GET_GUID_NAME GetGuidName; + EFI_SHELL_GET_GUID_FROM_NAME GetGuidFromName; + EFI_SHELL_GET_ENV_EX GetEnvEx; +} EFI_SHELL_PROTOCOL; + +extern EFI_GUID gEfiShellProtocolGuid; + +enum ShellVersion { + SHELL_MAJOR_VERSION = 2, + SHELL_MINOR_VERSION = 2 +}; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellDynamicCommand.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellDynamicCommand.h new file mode 100644 index 0000000..fd9149c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellDynamicCommand.h @@ -0,0 +1,85 @@ +/** @file + EFI Shell Dynamic Command registration protocol + + (C) Copyright 2012-2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL_H__ +#define __EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL_H__ + +#include +#include + +// {3C7200E9-005F-4EA4-87DE-A3DFAC8A27C3} +#define EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL_GUID \ + { \ + 0x3c7200e9, 0x005f, 0x4ea4, { 0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3 } \ + } + + +// +// Define for forward reference. +// +typedef struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL; + + +/** + This is the shell command handler function pointer callback type. This + function handles the command when it is invoked in the shell. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the context + of processing this command. + + @return EFI_SUCCESS the operation was sucessful + @return other the operation failed. +**/ +typedef +SHELL_STATUS +(EFIAPI * SHELL_COMMAND_HANDLER)( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ); + +/** + This is the command help handler function pointer callback type. This + function is responsible for displaying help information for the associated + command. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return string Pool allocated help string, must be freed by caller +**/ +typedef +CHAR16* +(EFIAPI * SHELL_COMMAND_GETHELP)( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ); + +/// EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL protocol structure. +struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL { + + CONST CHAR16 *CommandName; + SHELL_COMMAND_HANDLER Handler; + SHELL_COMMAND_GETHELP GetHelp; + +}; + +extern EFI_GUID gEfiShellDynamicCommandProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellParameters.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellParameters.h new file mode 100644 index 0000000..e9c0ee5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/ShellParameters.h @@ -0,0 +1,60 @@ +/** @file + EFI Shell protocol as defined in the UEFI Shell 2.0 specification. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_SHELL_PARAMETERS_PROTOCOL_H__ +#define __EFI_SHELL_PARAMETERS_PROTOCOL_H__ + +#include + +#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \ + { \ + 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ + } + +typedef struct _EFI_SHELL_PARAMETERS_PROTOCOL { + /// + /// Points to an Argc-element array of points to NULL-terminated strings containing + /// the command-line parameters. The first entry in the array is always the full file + /// path of the executable. Any quotation marks that were used to preserve + /// whitespace have been removed. + /// + CHAR16 **Argv; + + /// + /// The number of elements in the Argv array. + /// + UINTN Argc; + + /// + /// The file handle for the standard input for this executable. This may be different + /// from the ConInHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdIn; + + /// + /// The file handle for the standard output for this executable. This may be different + /// from the ConOutHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdOut; + + /// + /// The file handle for the standard error output for this executable. This may be + /// different from the StdErrHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdErr; +} EFI_SHELL_PARAMETERS_PROTOCOL; + +extern EFI_GUID gEfiShellParametersProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleFileSystem.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleFileSystem.h new file mode 100644 index 0000000..c6c28e6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleFileSystem.h @@ -0,0 +1,562 @@ +/** @file + SimpleFileSystem protocol as defined in the UEFI 2.0 specification. + + The SimpleFileSystem protocol is the programmatic access to the FAT (12,16,32) + file system specified in UEFI 2.0. It can also be used to abstract a file + system other than FAT. + + UEFI 2.0 can boot from any valid EFI image contained in a SimpleFileSystem. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_FILE_SYSTEM_H__ +#define __SIMPLE_FILE_SYSTEM_H__ + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { \ + 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +typedef struct _EFI_FILE_PROTOCOL EFI_FILE_PROTOCOL; +typedef struct _EFI_FILE_PROTOCOL *EFI_FILE_HANDLE; + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID + +/// +/// Protocol name defined in EFI1.1. +/// +typedef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_FILE_IO_INTERFACE; +typedef EFI_FILE_PROTOCOL EFI_FILE; + +/** + Open the root directory on a volume. + + @param This A pointer to the volume to open the root directory. + @param Root A pointer to the location to return the opened file handle for the + root directory. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_UNSUPPORTED This volume does not support the requested file system type. + @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_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. Any existing file handles for this volume are + no longer valid. To access the files on the new medium, the + volume must be reopened with OpenVolume(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **Root + ); + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 + +/// +/// Revision defined in EFI1.1 +/// +#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION + +struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + /// + /// The version of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. The version + /// specified by this specification is 0x00010000. All future revisions + /// must be backwards compatible. + /// + UINT64 Revision; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; +}; + +/** + Opens a new file relative to the source file's location. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to the source location. This would typically be an open + handle to a directory. + @param NewHandle A pointer to the location to return the opened handle for the new + file. + @param FileName The Null-terminated string of the name of the file to be opened. + The file name may contain the following path modifiers: "\", ".", + and "..". + @param OpenMode The mode to open the file. The only valid combinations that the + file may be opened with are: Read, Read/Write, or Create/Read/Write. + @param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the + attribute bits for the newly created file. + + @retval EFI_SUCCESS The file was opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_OPEN)( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +// +// Open modes +// +#define EFI_FILE_MODE_READ 0x0000000000000001ULL +#define EFI_FILE_MODE_WRITE 0x0000000000000002ULL +#define EFI_FILE_MODE_CREATE 0x8000000000000000ULL + +// +// File attributes +// +#define EFI_FILE_READ_ONLY 0x0000000000000001ULL +#define EFI_FILE_HIDDEN 0x0000000000000002ULL +#define EFI_FILE_SYSTEM 0x0000000000000004ULL +#define EFI_FILE_RESERVED 0x0000000000000008ULL +#define EFI_FILE_DIRECTORY 0x0000000000000010ULL +#define EFI_FILE_ARCHIVE 0x0000000000000020ULL +#define EFI_FILE_VALID_ATTR 0x0000000000000037ULL + +/** + Closes a specified file handle. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to close. + + @retval EFI_SUCCESS The file was closed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_CLOSE)( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Close and delete the file handle. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the + handle to the file to delete. + + @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed. + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_DELETE)( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Reads data from a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to read data from. + @param BufferSize On input, the size of the Buffer. On output, the amount of data + returned in Buffer. In both cases, the size is measured in bytes. + @param Buffer The buffer into which the data is read. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file. + @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory + entry. BufferSize has been updated with the size + needed to complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_READ)( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Writes data to a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to write data to. + @param BufferSize On input, the size of the Buffer. On output, the amount of data + actually written. In both cases, the size is measured in bytes. + @param Buffer The buffer of data to write. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to open directory files are not supported. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_WRITE)( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Sets a file's current position. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the + file handle to set the requested position on. + @param Position The byte position from the start of the file to set. + + @retval EFI_SUCCESS The position was set. + @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open + directories. + @retval EFI_DEVICE_ERROR An attempt was made to set the position of a deleted file. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_POSITION)( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ); + +/** + Returns a file's current position. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to get the current position on. + @param Position The address to return the file's current position value. + + @retval EFI_SUCCESS The position was returned. + @retval EFI_UNSUPPORTED The request is not valid on open directories. + @retval EFI_DEVICE_ERROR An attempt was made to get the position from a deleted file. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_POSITION)( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ); + +/** + Returns information about a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle the requested information is for. + @param InformationType The type identifier for the information being requested. + @param BufferSize On input, the size of Buffer. On output, the amount of data + returned in Buffer. In both cases, the size is measured in bytes. + @param Buffer A pointer to the data buffer to return. The buffer's type is + indicated by InformationType. + + @retval EFI_SUCCESS The information was returned. + @retval EFI_UNSUPPORTED The InformationType is not known. + @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_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry. + BufferSize has been updated with the size needed to complete + the request. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_INFO)( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Sets information about a file. + + @param File A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle the information is for. + @param InformationType The type identifier for the information being set. + @param BufferSize The size, in bytes, of Buffer. + @param Buffer A pointer to the data buffer to write. The buffer's type is + indicated by InformationType. + + @retval EFI_SUCCESS The information was set. + @retval EFI_UNSUPPORTED The InformationType is not known. + @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 InformationType is EFI_FILE_INFO_ID and the media is + read-only. + @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_PROTOCOL_SYSTEM_INFO_ID + and the media is read only. + @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_SYSTEM_VOLUME_LABEL_ID + and the media is read-only. + @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a + file that is already present. + @retval EFI_ACCESS_DENIED An attempt is being made to change the EFI_FILE_DIRECTORY + Attribute. + @retval EFI_ACCESS_DENIED An attempt is being made to change the size of a directory. + @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the file was opened + read-only and an attempt is being made to modify a field + other than Attribute. + @retval EFI_VOLUME_FULL The volume is full. + @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type indicated + by InformationType. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_INFO)( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flushes all modified data associated with a file to a device. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to flush. + + @retval EFI_SUCCESS The data was flushed. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_FLUSH)( + IN EFI_FILE_PROTOCOL *This + ); + +typedef struct { + // + // 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 read request is completed. + // The caller must be prepared to handle the case where the callback associated with Event + // occurs before the original asynchronous I/O request call returns. + // + EFI_EVENT Event; + + // + // Defines whether or not the signaled event encountered an error. + // + EFI_STATUS Status; + + // + // For OpenEx(): Not Used, ignored. + // For ReadEx(): On input, the size of the Buffer. On output, the amount of data returned in Buffer. + // In both cases, the size is measured in bytes. + // For WriteEx(): On input, the size of the Buffer. On output, the amount of data actually written. + // In both cases, the size is measured in bytes. + // For FlushEx(): Not used, ignored. + // + UINTN BufferSize; + + // + // For OpenEx(): Not Used, ignored. + // For ReadEx(): The buffer into which the data is read. + // For WriteEx(): The buffer of data to write. + // For FlushEx(): Not Used, ignored. + // + VOID *Buffer; +} EFI_FILE_IO_TOKEN; + +/** + Opens a new file relative to the source directory's location. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to the source location. + @param NewHandle A pointer to the location to return the opened handle for the new + file. + @param FileName The Null-terminated string of the name of the file to be opened. + The file name may contain the following path modifiers: "\", ".", + and "..". + @param OpenMode The mode to open the file. The only valid combinations that the + file may be opened with are: Read, Read/Write, or Create/Read/Write. + @param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the + attribute bits for the newly created file. + @param Token A pointer to the token associated with the transaction. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully. + If Event is not NULL (asynchronous I/O): The request was successfully + queued for processing. + @retval EFI_NOT_FOUND The specified file could not be found on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_OPEN_EX)( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes, + IN OUT EFI_FILE_IO_TOKEN *Token + ); + + +/** + Reads data from a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to read data from. + @param Token A pointer to the token associated with the transaction. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully. + If Event is not NULL (asynchronous I/O): The request was successfully + queued for processing. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file. + @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_READ_EX) ( + IN EFI_FILE_PROTOCOL *This, + IN OUT EFI_FILE_IO_TOKEN *Token +); + + +/** + Writes data to a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to write data to. + @param Token A pointer to the token associated with the transaction. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully. + If Event is not NULL (asynchronous I/O): The request was successfully + queued for processing. + @retval EFI_UNSUPPORTED Writes to open directory files are not supported. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file. + @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. + @retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_WRITE_EX) ( + IN EFI_FILE_PROTOCOL *This, + IN OUT EFI_FILE_IO_TOKEN *Token +); + +/** + Flushes all modified data associated with a file to a device. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to flush. + @param Token A pointer to the token associated with the transaction. + + @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read successfully. + If Event is not NULL (asynchronous I/O): The request was successfully + queued for processing. + @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. + @retval EFI_OUT_OF_RESOURCES Unable to queue the request due to lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_FLUSH_EX) ( + IN EFI_FILE_PROTOCOL *This, + IN OUT EFI_FILE_IO_TOKEN *Token + ); + +#define EFI_FILE_PROTOCOL_REVISION 0x00010000 +#define EFI_FILE_PROTOCOL_REVISION2 0x00020000 +#define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2 + +// +// Revision defined in EFI1.1. +// +#define EFI_FILE_REVISION EFI_FILE_PROTOCOL_REVISION + +/// +/// The EFI_FILE_PROTOCOL provides file IO access to supported file systems. +/// An EFI_FILE_PROTOCOL provides access to a file's or directory's contents, +/// and is also a reference to a location in the directory tree of the file system +/// in which the file resides. With any given file handle, other files may be opened +/// relative to this file's location, yielding new file handles. +/// +struct _EFI_FILE_PROTOCOL { + /// + /// The version of the EFI_FILE_PROTOCOL interface. The version specified + /// by this specification is EFI_FILE_PROTOCOL_LATEST_REVISION. + /// Future versions are required to be backward compatible to version 1.0. + /// + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + EFI_FILE_OPEN_EX OpenEx; + EFI_FILE_READ_EX ReadEx; + EFI_FILE_WRITE_EX WriteEx; + EFI_FILE_FLUSH_EX FlushEx; +}; + + +extern EFI_GUID gEfiSimpleFileSystemProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleNetwork.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleNetwork.h new file mode 100644 index 0000000..9522517 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleNetwork.h @@ -0,0 +1,681 @@ +/** @file + The EFI_SIMPLE_NETWORK_PROTOCOL provides services to initialize a network interface, + transmit packets, receive packets, and close a network interface. + + Basic network device abstraction. + + Rx - Received + Tx - Transmit + MCast - MultiCast + ... + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in EFI Specification 1.10. + +**/ + +#ifndef __SIMPLE_NETWORK_H__ +#define __SIMPLE_NETWORK_H__ + +#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + { \ + 0xA19832B9, 0xAC25, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } \ + } + +typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL; + + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK; + +/// +/// Simple Network Protocol data structures. +/// +typedef struct { + /// + /// Total number of frames received. Includes frames with errors and + /// dropped frames. + /// + UINT64 RxTotalFrames; + + /// + /// Number of valid frames received and copied into receive buffers. + /// + UINT64 RxGoodFrames; + + /// + /// Number of frames below the minimum length for the media. + /// This would be <64 for ethernet. + /// + UINT64 RxUndersizeFrames; + + /// + /// Number of frames longer than the maxminum length for the + /// media. This would be >1500 for ethernet. + /// + UINT64 RxOversizeFrames; + + /// + /// Valid frames that were dropped because receive buffers were full. + /// + UINT64 RxDroppedFrames; + + /// + /// Number of valid unicast frames received and not dropped. + /// + UINT64 RxUnicastFrames; + + /// + /// Number of valid broadcast frames received and not dropped. + /// + UINT64 RxBroadcastFrames; + + /// + /// Number of valid mutlicast frames received and not dropped. + /// + UINT64 RxMulticastFrames; + + /// + /// Number of frames w/ CRC or alignment errors. + /// + UINT64 RxCrcErrorFrames; + + /// + /// Total number of bytes received. Includes frames with errors + /// and dropped frames. + // + UINT64 RxTotalBytes; + + /// + /// Transmit statistics. + /// + UINT64 TxTotalFrames; + UINT64 TxGoodFrames; + UINT64 TxUndersizeFrames; + UINT64 TxOversizeFrames; + UINT64 TxDroppedFrames; + UINT64 TxUnicastFrames; + UINT64 TxBroadcastFrames; + UINT64 TxMulticastFrames; + UINT64 TxCrcErrorFrames; + UINT64 TxTotalBytes; + + /// + /// Number of collisions detection on this subnet. + /// + UINT64 Collisions; + + /// + /// Number of frames destined for unsupported protocol. + /// + UINT64 UnsupportedProtocol; + + /// + /// Number of valid frames received that were duplicated. + /// + UINT64 RxDuplicatedFrames; + + /// + /// Number of encrypted frames received that failed to decrypt. + /// + UINT64 RxDecryptErrorFrames; + + /// + /// Number of frames that failed to transmit after exceeding the retry limit. + /// + UINT64 TxErrorFrames; + + /// + /// Number of frames transmitted successfully after more than one attempt. + /// + UINT64 TxRetryFrames; +} EFI_NETWORK_STATISTICS; + +/// +/// The state of the network interface. +/// When an EFI_SIMPLE_NETWORK_PROTOCOL driver initializes a +/// network interface, the network interface is left in the EfiSimpleNetworkStopped state. +/// +typedef enum { + EfiSimpleNetworkStopped, + EfiSimpleNetworkStarted, + EfiSimpleNetworkInitialized, + EfiSimpleNetworkMaxState +} EFI_SIMPLE_NETWORK_STATE; + +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 + +#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01 +#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02 +#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04 +#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08 + +#define MAX_MCAST_FILTER_CNT 16 +typedef struct { + /// + /// Reports the current state of the network interface. + /// + UINT32 State; + /// + /// The size, in bytes, of the network interface's HW address. + /// + UINT32 HwAddressSize; + /// + /// The size, in bytes, of the network interface's media header. + /// + UINT32 MediaHeaderSize; + /// + /// The maximum size, in bytes, of the packets supported by the network interface. + /// + UINT32 MaxPacketSize; + /// + /// The size, in bytes, of the NVRAM device attached to the network interface. + /// + UINT32 NvRamSize; + /// + /// The size that must be used for all NVRAM reads and writes. The + /// start address for NVRAM read and write operations and the total + /// length of those operations, must be a multiple of this value. The + /// legal values for this field are 0, 1, 2, 4, and 8. + /// + UINT32 NvRamAccessSize; + /// + /// The multicast receive filter settings supported by the network interface. + /// + UINT32 ReceiveFilterMask; + /// + /// The current multicast receive filter settings. + /// + UINT32 ReceiveFilterSetting; + /// + /// The maximum number of multicast address receive filters supported by the driver. + /// + UINT32 MaxMCastFilterCount; + /// + /// The current number of multicast address receive filters. + /// + UINT32 MCastFilterCount; + /// + /// Array containing the addresses of the current multicast address receive filters. + /// + EFI_MAC_ADDRESS MCastFilter[MAX_MCAST_FILTER_CNT]; + /// + /// The current HW MAC address for the network interface. + /// + EFI_MAC_ADDRESS CurrentAddress; + /// + /// The current HW MAC address for broadcast packets. + /// + EFI_MAC_ADDRESS BroadcastAddress; + /// + /// The permanent HW MAC address for the network interface. + /// + EFI_MAC_ADDRESS PermanentAddress; + /// + /// The interface type of the network interface. + /// + UINT8 IfType; + /// + /// TRUE if the HW MAC address can be changed. + /// + BOOLEAN MacAddressChangeable; + /// + /// TRUE if the network interface can transmit more than one packet at a time. + /// + BOOLEAN MultipleTxSupported; + /// + /// TRUE if the presence of media can be determined; otherwise FALSE. + /// + BOOLEAN MediaPresentSupported; + /// + /// TRUE if media are connected to the network interface; otherwise FALSE. + /// + BOOLEAN MediaPresent; +} EFI_SIMPLE_NETWORK_MODE; + +// +// Protocol Member Functions +// +/** + Changes the state of a network interface from "stopped" to "started". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was started. + @retval EFI_ALREADY_STARTED The network interface is already in the started state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_START)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ); + +/** + Changes the state of a network interface from "started" to "stopped". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was stopped. + @retval EFI_ALREADY_STARTED The network interface is already in the stopped state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STOP)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ); + +/** + Resets a network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation + of additional transmit and receive buffers. + + @param This The protocol instance pointer. + @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + + @retval EFI_SUCCESS The network interface was initialized. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and + receive buffers. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_INITIALIZE)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ); + +/** + Resets a network adapter and re-initializes it with the parameters that were + provided in the previous call to Initialize(). + + @param This The protocol instance pointer. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The network interface was reset. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RESET)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Resets a network adapter and leaves it in a state that is safe for + another driver to initialize. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was shutdown. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_SHUTDOWN)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ); + +/** + Manages the multicast receive filters of a network interface. + + @param This The protocol instance pointer. + @param Enable A bit mask of receive filters to enable on the network interface. + @param Disable A bit mask of receive filters to disable on the network interface. + @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive + filters on the network interface to their default values. + @param McastFilterCnt Number of multicast HW MAC addresses in the new + MCastFilter list. This value must be less than or equal to + the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This + field is optional if ResetMCastFilter is TRUE. + @param MCastFilter A pointer to a list of new multicast receive filter HW MAC + addresses. This list will replace any existing multicast + HW MAC address list. This field is optional if + ResetMCastFilter is TRUE. + + @retval EFI_SUCCESS The multicast receive filter list was updated. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE_FILTERS)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL + ); + +/** + Modifies or resets the current station address, if supported. + + @param This The protocol instance pointer. + @param Reset Flag used to reset the station address to the network interfaces + permanent address. + @param New The new station address to be used for the network interface. + + @retval EFI_SUCCESS The network interfaces station address was updated. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STATION_ADDRESS)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New OPTIONAL + ); + +/** + Resets or collects the statistics on a network interface. + + @param This Protocol instance pointer. + @param Reset Set to TRUE to reset the statistics for the network interface. + @param StatisticsSize On input the size, in bytes, of StatisticsTable. On + output the size, in bytes, of the resulting table of + statistics. + @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + contains the statistics. + + @retval EFI_SUCCESS The statistics were collected from the network interface. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STATISTICS)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL + ); + +/** + Converts a multicast IP address to a multicast HW MAC address. + + @param This The protocol instance pointer. + @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set + to FALSE if the multicast IP address is IPv4 [RFC 791]. + @param IP The multicast IP address that is to be converted to a multicast + HW MAC address. + @param MAC The multicast HW MAC address that is to be generated from IP. + + @retval EFI_SUCCESS The multicast IP address was mapped to the multicast + HW MAC address. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ); + +/** + Performs read and write operations on the NVRAM device attached to a + network interface. + + @param This The protocol instance pointer. + @param ReadWrite TRUE for read operations, FALSE for write operations. + @param Offset Byte offset in the NVRAM device at which to start the read or + write operation. This must be a multiple of NvRamAccessSize and + less than NvRamSize. + @param BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS The NVRAM access was performed. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_NVDATA)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ); + +/** + Reads the current interrupt status and recycled transmit buffer status from + a network interface. + + @param This The protocol instance pointer. + @param InterruptStatus A pointer to the bit mask of the currently active interrupts + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from the device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param TxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array + is full. Reading the transmit buffer does not clear the + transmit interrupt. If this is NULL, then the transmit buffer + status will not be read. If there are no transmit buffers to + recycle and TxBuf is not NULL, * TxBuf will be set to NULL. + + @retval EFI_SUCCESS The status of the network interface was retrieved. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_GET_STATUS)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ); + +/** + Places a packet in the transmit queue of a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then it + must be equal to This->Mode->MediaHeaderSize and the DestAddr + and Protocol parameters must not be NULL. + @param BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param Buffer A pointer to the packet (media header followed by data) to be + transmitted. This parameter cannot be NULL. If HeaderSize is zero, + then the media header in Buffer must already be filled in by the + caller. If HeaderSize is non-zero, then the media header will be + filled in by the Transmit() function. + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then + This->Mode->CurrentAddress is used for the source HW MAC address. + @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this + parameter is ignored. + @param Protocol The type of header to build. If HeaderSize is zero, then this + parameter is ignored. See RFC 1700, section "Ether Types", for + examples. + + @retval EFI_SUCCESS The packet was placed on the transmit queue. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_TRANSMIT)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ); + +/** + Receives a packet from a network interface. + + @param This The protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header received on the network + interface. If this parameter is NULL, then the media header size + will not be returned. + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in + bytes, of the packet that was received on the network interface. + @param Buffer A pointer to the data buffer to receive both the media header and + the data. + @param SrcAddr The source HW MAC address. If this parameter is NULL, the + HW MAC source address will not be extracted from the media + header. + @param DestAddr The destination HW MAC address. If this parameter is NULL, + the HW MAC destination address will not be extracted from the + media header. + @param Protocol The media header type. If this parameter is NULL, then the + protocol will not be extracted from the media header. See + RFC 1700 section "Ether Types" for examples. + + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has + been updated to the number of bytes received. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE)( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ); + +#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000 + +// +// Revision defined in EFI1.1 +// +#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION EFI_SIMPLE_NETWORK_PROTOCOL_REVISION + +/// +/// The EFI_SIMPLE_NETWORK_PROTOCOL protocol is used to initialize access +/// to a network adapter. Once the network adapter initializes, +/// the EFI_SIMPLE_NETWORK_PROTOCOL protocol provides services that +/// allow packets to be transmitted and received. +/// +struct _EFI_SIMPLE_NETWORK_PROTOCOL { + /// + /// Revision of the EFI_SIMPLE_NETWORK_PROTOCOL. All future revisions must + /// be backwards compatible. If a future version is not backwards compatible + /// it is not the same GUID. + /// + UINT64 Revision; + EFI_SIMPLE_NETWORK_START Start; + EFI_SIMPLE_NETWORK_STOP Stop; + EFI_SIMPLE_NETWORK_INITIALIZE Initialize; + EFI_SIMPLE_NETWORK_RESET Reset; + EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown; + EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters; + EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress; + EFI_SIMPLE_NETWORK_STATISTICS Statistics; + EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac; + EFI_SIMPLE_NETWORK_NVDATA NvData; + EFI_SIMPLE_NETWORK_GET_STATUS GetStatus; + EFI_SIMPLE_NETWORK_TRANSMIT Transmit; + EFI_SIMPLE_NETWORK_RECEIVE Receive; + /// + /// Event used with WaitForEvent() to wait for a packet to be received. + /// + EFI_EVENT WaitForPacket; + /// + /// Pointer to the EFI_SIMPLE_NETWORK_MODE data for the device. + /// + EFI_SIMPLE_NETWORK_MODE *Mode; +}; + +extern EFI_GUID gEfiSimpleNetworkProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimplePointer.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimplePointer.h new file mode 100644 index 0000000..4a234ae --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimplePointer.h @@ -0,0 +1,143 @@ +/** @file + Simple Pointer protocol from the UEFI 2.0 specification. + + Abstraction of a very simple pointer device like a mouse or trackball. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_POINTER_H__ +#define __SIMPLE_POINTER_H__ + +#define EFI_SIMPLE_POINTER_PROTOCOL_GUID \ + { \ + 0x31878c87, 0xb75, 0x11d5, {0x9a, 0x4f, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_SIMPLE_POINTER_PROTOCOL EFI_SIMPLE_POINTER_PROTOCOL; + +// +// Data structures +// +typedef struct { + /// + /// The signed distance in counts that the pointer device has been moved along the x-axis. + /// + INT32 RelativeMovementX; + /// + /// The signed distance in counts that the pointer device has been moved along the y-axis. + /// + INT32 RelativeMovementY; + /// + /// The signed distance in counts that the pointer device has been moved along the z-axis. + /// + INT32 RelativeMovementZ; + /// + /// If TRUE, then the left button of the pointer device is being + /// pressed. If FALSE, then the left button of the pointer device is not being pressed. + /// + BOOLEAN LeftButton; + /// + /// If TRUE, then the right button of the pointer device is being + /// pressed. If FALSE, then the right button of the pointer device is not being pressed. + /// + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_STATE; + +typedef struct { + /// + /// The resolution of the pointer device on the x-axis in counts/mm. + /// If 0, then the pointer device does not support an x-axis. + /// + UINT64 ResolutionX; + /// + /// The resolution of the pointer device on the y-axis in counts/mm. + /// If 0, then the pointer device does not support an x-axis. + /// + UINT64 ResolutionY; + /// + /// The resolution of the pointer device on the z-axis in counts/mm. + /// If 0, then the pointer device does not support an x-axis. + /// + UINT64 ResolutionZ; + /// + /// TRUE if a left button is present on the pointer device. Otherwise FALSE. + /// + BOOLEAN LeftButton; + /// + /// TRUE if a right button is present on the pointer device. Otherwise FALSE. + /// + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_MODE; + +/** + Resets the pointer device hardware. + + @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL + instance. + @param ExtendedVerification Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_POINTER_RESET)( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Retrieves the current state of a pointer device. + + @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL + instance. + @param State A pointer to the state information on the pointer device. + + @retval EFI_SUCCESS The state of the pointer device was returned in State. + @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to + GetState(). + @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's + current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_POINTER_GET_STATE)( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ); + +/// +/// The EFI_SIMPLE_POINTER_PROTOCOL provides a set of services for a pointer +/// device that can use used as an input device from an application written +/// to this specification. The services include the ability to reset the +/// pointer device, retrieve get the state of the pointer device, and +/// retrieve the capabilities of the pointer device. +/// +struct _EFI_SIMPLE_POINTER_PROTOCOL { + EFI_SIMPLE_POINTER_RESET Reset; + EFI_SIMPLE_POINTER_GET_STATE GetState; + /// + /// Event to use with WaitForEvent() to wait for input from the pointer device. + /// + EFI_EVENT WaitForInput; + /// + /// Pointer to EFI_SIMPLE_POINTER_MODE data. + /// + EFI_SIMPLE_POINTER_MODE *Mode; +}; + +extern EFI_GUID gEfiSimplePointerProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextIn.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextIn.h new file mode 100644 index 0000000..d8df553 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextIn.h @@ -0,0 +1,133 @@ +/** @file + Simple Text Input protocol from the UEFI 2.0 specification. + + Abstraction of a very simple input device like a keyboard or serial + terminal. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_TEXT_IN_PROTOCOL_H__ +#define __SIMPLE_TEXT_IN_PROTOCOL_H__ + +#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \ + { \ + 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL; + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define SIMPLE_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID + +/// +/// Protocol name in EFI1.1 for backward-compatible. +/// +typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL SIMPLE_INPUT_INTERFACE; + +/// +/// The keystroke information for the key that was pressed. +/// +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} EFI_INPUT_KEY; + +// +// Required unicode control chars +// +#define CHAR_BACKSPACE 0x0008 +#define CHAR_TAB 0x0009 +#define CHAR_LINEFEED 0x000A +#define CHAR_CARRIAGE_RETURN 0x000D + +// +// EFI Scan codes +// +#define SCAN_NULL 0x0000 +#define SCAN_UP 0x0001 +#define SCAN_DOWN 0x0002 +#define SCAN_RIGHT 0x0003 +#define SCAN_LEFT 0x0004 +#define SCAN_HOME 0x0005 +#define SCAN_END 0x0006 +#define SCAN_INSERT 0x0007 +#define SCAN_DELETE 0x0008 +#define SCAN_PAGE_UP 0x0009 +#define SCAN_PAGE_DOWN 0x000A +#define SCAN_F1 0x000B +#define SCAN_F2 0x000C +#define SCAN_F3 0x000D +#define SCAN_F4 0x000E +#define SCAN_F5 0x000F +#define SCAN_F6 0x0010 +#define SCAN_F7 0x0011 +#define SCAN_F8 0x0012 +#define SCAN_F9 0x0013 +#define SCAN_F10 0x0014 +#define SCAN_ESC 0x0017 + +/** + Reset the input device and optionally run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_RESET)( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existence of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param Key A pointer to a buffer that is filled in with the keystroke + information for the key that was pressed. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data available. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to + hardware errors. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_READ_KEY)( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +/// +/// The EFI_SIMPLE_TEXT_INPUT_PROTOCOL is used on the ConsoleIn device. +/// It is the minimum required protocol for ConsoleIn. +/// +struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL { + EFI_INPUT_RESET Reset; + EFI_INPUT_READ_KEY ReadKeyStroke; + /// + /// Event to use with WaitForEvent() to wait for a key to be available + /// + EFI_EVENT WaitForKey; +}; + +extern EFI_GUID gEfiSimpleTextInProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextInEx.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextInEx.h new file mode 100644 index 0000000..38a6518 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextInEx.h @@ -0,0 +1,323 @@ +/** @file + Simple Text Input Ex protocol from the UEFI 2.0 specification. + + This protocol defines an extension to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL + which exposes much more state and modifier information from the input device, + also allows one to register a notification for a particular keystroke. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_TEXT_IN_EX_H__ +#define __SIMPLE_TEXT_IN_EX_H__ + +#include + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } + + +typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; + +/** + The Reset() function resets the input device hardware. As part + of initialization process, the firmware/device will make a quick + but reasonable attempt to verify that the device is functioning. + If the ExtendedVerification flag is TRUE the firmware may take + an extended amount of time to verify the device is operating on + reset. Otherwise the reset operation is to occur as quickly as + possible. The hardware verification process is not defined by + this specification and is left up to the platform firmware or + driver to implement. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param ExtendedVerification Indicates that the driver may + perform a more exhaustive + verification operation of the + device during reset. + + + @retval EFI_SUCCESS The device was reset. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_RESET_EX)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + + +/// +/// EFI_KEY_TOGGLE_STATE. The toggle states are defined. +/// They are: EFI_TOGGLE_STATE_VALID, EFI_SCROLL_LOCK_ACTIVE +/// EFI_NUM_LOCK_ACTIVE, EFI_CAPS_LOCK_ACTIVE +/// +typedef UINT8 EFI_KEY_TOGGLE_STATE; + +typedef struct _EFI_KEY_STATE { + /// + /// Reflects the currently pressed shift + /// modifiers for the input device. The + /// returned value is valid only if the high + /// order bit has been set. + /// + UINT32 KeyShiftState; + /// + /// Reflects the current internal state of + /// various toggled attributes. The returned + /// value is valid only if the high order + /// bit has been set. + /// + EFI_KEY_TOGGLE_STATE KeyToggleState; +} EFI_KEY_STATE; + +typedef struct { + /// + /// The EFI scan code and Unicode value returned from the input device. + /// + EFI_INPUT_KEY Key; + /// + /// The current state of various toggled attributes as well as input modifier values. + /// + EFI_KEY_STATE KeyState; +} EFI_KEY_DATA; + +// +// Any Shift or Toggle State that is valid should have +// high order bit set. +// +// Shift state +// +#define EFI_SHIFT_STATE_VALID 0x80000000 +#define EFI_RIGHT_SHIFT_PRESSED 0x00000001 +#define EFI_LEFT_SHIFT_PRESSED 0x00000002 +#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 +#define EFI_LEFT_CONTROL_PRESSED 0x00000008 +#define EFI_RIGHT_ALT_PRESSED 0x00000010 +#define EFI_LEFT_ALT_PRESSED 0x00000020 +#define EFI_RIGHT_LOGO_PRESSED 0x00000040 +#define EFI_LEFT_LOGO_PRESSED 0x00000080 +#define EFI_MENU_KEY_PRESSED 0x00000100 +#define EFI_SYS_REQ_PRESSED 0x00000200 + +// +// Toggle state +// +#define EFI_TOGGLE_STATE_VALID 0x80 +#define EFI_KEY_STATE_EXPOSED 0x40 +#define EFI_SCROLL_LOCK_ACTIVE 0x01 +#define EFI_NUM_LOCK_ACTIVE 0x02 +#define EFI_CAPS_LOCK_ACTIVE 0x04 + +// +// EFI Scan codes +// +#define SCAN_F11 0x0015 +#define SCAN_F12 0x0016 +#define SCAN_PAUSE 0x0048 +#define SCAN_F13 0x0068 +#define SCAN_F14 0x0069 +#define SCAN_F15 0x006A +#define SCAN_F16 0x006B +#define SCAN_F17 0x006C +#define SCAN_F18 0x006D +#define SCAN_F19 0x006E +#define SCAN_F20 0x006F +#define SCAN_F21 0x0070 +#define SCAN_F22 0x0071 +#define SCAN_F23 0x0072 +#define SCAN_F24 0x0073 +#define SCAN_MUTE 0x007F +#define SCAN_VOLUME_UP 0x0080 +#define SCAN_VOLUME_DOWN 0x0081 +#define SCAN_BRIGHTNESS_UP 0x0100 +#define SCAN_BRIGHTNESS_DOWN 0x0101 +#define SCAN_SUSPEND 0x0102 +#define SCAN_HIBERNATE 0x0103 +#define SCAN_TOGGLE_DISPLAY 0x0104 +#define SCAN_RECOVERY 0x0105 +#define SCAN_EJECT 0x0106 + +/** + The function reads the next keystroke from the input device. If + there is no pending keystroke the function returns + EFI_NOT_READY. If there is a pending keystroke, then + KeyData.Key.ScanCode is the EFI scan code defined in Error! + Reference source not found. The KeyData.Key.UnicodeChar is the + actual printable character or is zero if the key does not + represent a printable character (control key, function key, + etc.). The KeyData.KeyState is shift state for the character + reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode . + When interpreting the data from this function, it should be + noted that if a class of printable characters that are + normally adjusted by shift modifiers (e.g. Shift Key + "f" + key) would be presented solely as a KeyData.Key.UnicodeChar + without the associated shift state. So in the previous example + of a Shift Key + "f" key being pressed, the only pertinent + data returned would be KeyData.Key.UnicodeChar with the value + of "F". This of course would not typically be the case for + non-printable characters such as the pressing of the Right + Shift Key + F10 key since the corresponding returned data + would be reflected both in the KeyData.KeyState.KeyShiftState + and KeyData.Key.ScanCode values. UEFI drivers which implement + the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return + KeyData.Key and KeyData.KeyState values. These drivers must + always return the most current state of + KeyData.KeyState.KeyShiftState and + KeyData.KeyState.KeyToggleState. It should also be noted that + certain input devices may not be able to produce shift or toggle + state information, and in those cases the high order bit in the + respective Toggle and Shift state fields should not be active. + + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke state data for the key that was + pressed. + + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data available. + @retval EFI_DEVICE_ERROR The keystroke information was not returned due to + hardware errors. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_READ_KEY_EX)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +); + +/** + The SetState() function allows the input device hardware to + have state settings adjusted. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to + set the state for the input device. + + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not have the + setting adjusted. + + @retval EFI_UNSUPPORTED The device does not support the + ability to have its state set. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_STATE)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +/// +/// The function will be called when the key sequence is typed specified by KeyData. +/// +typedef +EFI_STATUS +(EFIAPI *EFI_KEY_NOTIFY_FUNCTION)( + IN EFI_KEY_DATA *KeyData +); + +/** + The RegisterKeystrokeNotify() function registers a function + which will be called when a specified keystroke will occur. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke information for the key that was + pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState + and KeyData.KeyState.KeyShiftState are 0, then any incomplete + keystroke will trigger a notification of the KeyNotificationFunction. + + @param KeyNotificationFunction Points to the function to be called when the key sequence + is typed specified by KeyData. This notification function + should be called at <=TPL_CALLBACK. + + + @param NotifyHandle Points to the unique handle assigned to + the registered notification. + + @retval EFI_SUCCESS Key notify was registered successfully. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary + data structures. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle +); + +/** + The UnregisterKeystrokeNotify() function removes the + notification which was previously registered. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param NotificationHandle The handle of the notification + function being unregistered. + + @retval EFI_SUCCESS Key notify was unregistered successfully. + + @retval EFI_INVALID_PARAMETER The NotificationHandle is + invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle +); + + +/// +/// The EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL is used on the ConsoleIn +/// device. It is an extension to the Simple Text Input protocol +/// which allows a variety of extended shift state information to be +/// returned. +/// +struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{ + EFI_INPUT_RESET_EX Reset; + EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + /// + /// Event to use with WaitForEvent() to wait for a key to be available. + /// + EFI_EVENT WaitForKeyEx; + EFI_SET_STATE SetState; + EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; +}; + + +extern EFI_GUID gEfiSimpleTextInputExProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextOut.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextOut.h new file mode 100644 index 0000000..c3bdd01 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SimpleTextOut.h @@ -0,0 +1,415 @@ +/** @file + Simple Text Out protocol from the UEFI 2.0 specification. + + Abstraction of a very simple text based output device like VGA text mode or + a serial terminal. The Simple Text Out protocol instance can represent + a single hardware device or a virtual device that is an aggregation + of multiple physical devices. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_TEXT_OUT_H__ +#define __SIMPLE_TEXT_OUT_H__ + +#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ + { \ + 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +/// +/// Protocol GUID defined in EFI1.1. +/// +#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID + +typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; + +/// +/// Backward-compatible with EFI1.1. +/// +typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE; + +// +// Define's for required EFI Unicode Box Draw characters +// +#define BOXDRAW_HORIZONTAL 0x2500 +#define BOXDRAW_VERTICAL 0x2502 +#define BOXDRAW_DOWN_RIGHT 0x250c +#define BOXDRAW_DOWN_LEFT 0x2510 +#define BOXDRAW_UP_RIGHT 0x2514 +#define BOXDRAW_UP_LEFT 0x2518 +#define BOXDRAW_VERTICAL_RIGHT 0x251c +#define BOXDRAW_VERTICAL_LEFT 0x2524 +#define BOXDRAW_DOWN_HORIZONTAL 0x252c +#define BOXDRAW_UP_HORIZONTAL 0x2534 +#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c +#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550 +#define BOXDRAW_DOUBLE_VERTICAL 0x2551 +#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552 +#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553 +#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554 +#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555 +#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556 +#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557 +#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558 +#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559 +#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a +#define BOXDRAW_UP_LEFT_DOUBLE 0x255b +#define BOXDRAW_UP_DOUBLE_LEFT 0x255c +#define BOXDRAW_DOUBLE_UP_LEFT 0x255d +#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e +#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f +#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560 +#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561 +#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562 +#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563 +#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564 +#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565 +#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566 +#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567 +#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568 +#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569 +#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a +#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b +#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c + +// +// EFI Required Block Elements Code Chart +// +#define BLOCKELEMENT_FULL_BLOCK 0x2588 +#define BLOCKELEMENT_LIGHT_SHADE 0x2591 + +// +// EFI Required Geometric Shapes Code Chart +// +#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2 +#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba +#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc +#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4 + +// +// EFI Required Arrow shapes +// +#define ARROW_LEFT 0x2190 +#define ARROW_UP 0x2191 +#define ARROW_RIGHT 0x2192 +#define ARROW_DOWN 0x2193 + +// +// EFI Console Colours +// +#define EFI_BLACK 0x00 +#define EFI_BLUE 0x01 +#define EFI_GREEN 0x02 +#define EFI_CYAN (EFI_BLUE | EFI_GREEN) +#define EFI_RED 0x04 +#define EFI_MAGENTA (EFI_BLUE | EFI_RED) +#define EFI_BROWN (EFI_GREEN | EFI_RED) +#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED) +#define EFI_BRIGHT 0x08 +#define EFI_DARKGRAY (EFI_BLACK | EFI_BRIGHT) +#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT) +#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT) +#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT) +#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT) +#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT) +#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT) +#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT) + +// +// Macro to accept color values in their raw form to create +// a value that represents both a foreground and background +// color in a single byte. +// For Foreground, and EFI_* value is valid from EFI_BLACK(0x00) to +// EFI_WHITE (0x0F). +// For Background, only EFI_BLACK, EFI_BLUE, EFI_GREEN, EFI_CYAN, +// EFI_RED, EFI_MAGENTA, EFI_BROWN, and EFI_LIGHTGRAY are acceptable +// +// Do not use EFI_BACKGROUND_xxx values with this macro. +// +#define EFI_TEXT_ATTR(Foreground,Background) ((Foreground) | ((Background) << 4)) + +#define EFI_BACKGROUND_BLACK 0x00 +#define EFI_BACKGROUND_BLUE 0x10 +#define EFI_BACKGROUND_GREEN 0x20 +#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN) +#define EFI_BACKGROUND_RED 0x40 +#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) + +// +// We currently define attributes from 0 - 7F for color manipulations +// To internally handle the local display characteristics for a particular character, +// Bit 7 signifies the local glyph representation for a character. If turned on, glyphs will be +// pulled from the wide glyph database and will display locally as a wide character (16 X 19 versus 8 X 19) +// If bit 7 is off, the narrow glyph database will be used. This does NOT affect information that is sent to +// non-local displays, such as serial or LAN consoles. +// +#define EFI_WIDE_ATTRIBUTE 0x80 + +/** + Reset the text output device hardware and optionaly run diagnostics + + @param This The protocol instance pointer. + @param ExtendedVerification Driver may perform more exhaustive verification + operation of the device during reset. + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and + could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_RESET)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Write a string to the output device. + + @param This The protocol instance pointer. + @param String The NULL-terminated string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing character codes defined in this file. + + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the string could not be + rendered and were skipped. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_STRING)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +/** + Verifies that all characters in a string can be output to the + target device. + + @param This The protocol instance pointer. + @param String The NULL-terminated string to be examined for the output + device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_TEST_STRING)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *String + ); + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param This The protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param Columns Returns the geometry of the text output device for the + requested ModeNumber. + @param Rows Returns the geometry of the text output device for the + requested ModeNumber. + + @retval EFI_SUCCESS The requested mode information was returned. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_QUERY_MODE)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + +/** + Sets the output device(s) to a specified mode. + + @param This The protocol instance pointer. + @param ModeNumber The mode number to set. + + @retval EFI_SUCCESS The requested text mode was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_MODE)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param This The protocol instance pointer. + @param Attribute The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + @retval EFI_SUCCESS The attribute was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_ATTRIBUTE)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +/** + Clears the output device(s) display to the currently selected background + color. + + @param This The protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_CLEAR_SCREEN)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +/** + Sets the current coordinates of the cursor position + + @param This The protocol instance pointer. + @param Column The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + @param Row The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + +/** + Makes the cursor visible or invisible + + @param This The protocol instance pointer. + @param Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the + request, or the device does not support changing + the cursor mode. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_ENABLE_CURSOR)( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +/** + @par Data Structure Description: + Mode Structure pointed to by Simple Text Out protocol. +**/ +typedef struct { + /// + /// The number of modes supported by QueryMode () and SetMode (). + /// + INT32 MaxMode; + + // + // current settings + // + + /// + /// The text mode of the output device(s). + /// + INT32 Mode; + /// + /// The current character output attribute. + /// + INT32 Attribute; + /// + /// The cursor's column. + /// + INT32 CursorColumn; + /// + /// The cursor's row. + /// + INT32 CursorRow; + /// + /// The cursor is currently visbile or not. + /// + BOOLEAN CursorVisible; +} EFI_SIMPLE_TEXT_OUTPUT_MODE; + +/// +/// The SIMPLE_TEXT_OUTPUT protocol is used to control text-based output devices. +/// It is the minimum required protocol for any handle supplied as the ConsoleOut +/// or StandardError device. In addition, the minimum supported text mode of such +/// devices is at least 80 x 25 characters. +/// +struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { + EFI_TEXT_RESET Reset; + + EFI_TEXT_STRING OutputString; + EFI_TEXT_TEST_STRING TestString; + + EFI_TEXT_QUERY_MODE QueryMode; + EFI_TEXT_SET_MODE SetMode; + EFI_TEXT_SET_ATTRIBUTE SetAttribute; + + EFI_TEXT_CLEAR_SCREEN ClearScreen; + EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + EFI_TEXT_ENABLE_CURSOR EnableCursor; + + /// + /// Pointer to SIMPLE_TEXT_OUTPUT_MODE data. + /// + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; +}; + +extern EFI_GUID gEfiSimpleTextOutProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardEdge.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardEdge.h new file mode 100644 index 0000000..93dc832 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardEdge.h @@ -0,0 +1,742 @@ +/** @file + The Smart Card Edge Protocol provides an abstraction for device to provide Smart + Card support. + + This protocol allows UEFI applications to interface with a Smart Card during + boot process for authentication or data signing/decryption, especially if the + application has to make use of PKI. + + Copyright (c) 2015-2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.5. + +**/ + +#ifndef __SMART_CARD_EDGE_H__ +#define __SMART_CARD_EDGE_H__ + +#define EFI_SMART_CARD_EDGE_PROTOCOL_GUID \ + { \ + 0xd317f29b, 0xa325, 0x4712, {0x9b, 0xf1, 0xc6, 0x19, 0x54, 0xdc, 0x19, 0x8c} \ + } + +typedef struct _EFI_SMART_CARD_EDGE_PROTOCOL EFI_SMART_CARD_EDGE_PROTOCOL; + +// +// Maximum size for a Smart Card AID (Application IDentifier) +// +#define SCARD_AID_MAXSIZE 0x0010 +// +// Size of CSN (Card Serial Number) +// +#define SCARD_CSN_SIZE 0x0010 +// +// Current specification version 1.00 +// +#define SMART_CARD_EDGE_PROTOCOL_VERSION_1 0x00000100 +// +// Parameters type definition +// +typedef UINT8 SMART_CARD_AID[SCARD_AID_MAXSIZE]; +typedef UINT8 SMART_CARD_CSN[SCARD_CSN_SIZE]; + +// +// Type of data elements in credentials list +// +// value of tag field for header, the number of containers +// +#define SC_EDGE_TAG_HEADER 0x0000 +// +// value of tag field for certificate +// +#define SC_EDGE_TAG_CERT 0x0001 +// +// value of tag field for key index associated with certificate +// +#define SC_EDGE_TAG_KEY_ID 0x0002 +// +// value of tag field for key type +// +#define SC_EDGE_TAG_KEY_TYPE 0x0003 +// +// value of tag field for key size +// +#define SC_EDGE_TAG_KEY_SIZE 0x0004 + +// +// Length of L fields of TLV items +// +// +// size of L field for header +// +#define SC_EDGE_L_SIZE_HEADER 1 +// +// size of L field for certificate (big endian) +// +#define SC_EDGE_L_SIZE_CERT 2 +// +// size of L field for key index +// +#define SC_EDGE_L_SIZE_KEY_ID 1 +// +// size of L field for key type +// +#define SC_EDGE_L_SIZE_KEY_TYPE 1 +// +// size of L field for key size (big endian) +// +#define SC_EDGE_L_SIZE_KEY_SIZE 2 + +// +// Some TLV items have a fixed value for L field +// +// value of L field for header +// +#define SC_EDGE_L_VALUE_HEADER 1 +// +// value of L field for key index +// +#define SC_EDGE_L_VALUE_KEY_ID 1 +// +// value of L field for key type +// +#define SC_EDGE_L_VALUE_KEY_TYPE 1 +// +// value of L field for key size +// +#define SC_EDGE_L_VALUE_KEY_SIZE 2 + +// +// Possible values for key type +// +// +// RSA decryption +// +#define SC_EDGE_RSA_EXCHANGE 0x01 +// +// RSA signature +// +#define SC_EDGE_RSA_SIGNATURE 0x02 +// +// ECDSA signature +// +#define SC_EDGE_ECDSA_256 0x03 +// +// ECDSA signature +// +#define SC_EDGE_ECDSA_384 0x04 +// +// ECDSA signature +// +#define SC_EDGE_ECDSA_521 0x05 +// +// ECDH agreement +// +#define SC_EDGE_ECDH_256 0x06 +// +// ECDH agreement +// +#define SC_EDGE_ECDH_384 0x07 +// +// ECDH agreement +// +#define SC_EDGE_ECDH_521 0x08 + +// +// Padding methods GUIDs for signature +// +// +// RSASSA- PKCS#1-V1.5 padding method, for signature +// +#define EFI_PADDING_RSASSA_PKCS1V1P5_GUID \ + { \ + 0x9317ec24, 0x7cb0, 0x4d0e, {0x8b, 0x32, 0x2e, 0xd9, 0x20, 0x9c, 0xd8, 0xaf} \ + } + +extern EFI_GUID gEfiPaddingRsassaPkcs1V1P5Guid; + +// +// RSASSA-PSS padding method, for signature +// +#define EFI_PADDING_RSASSA_PSS_GUID \ + { \ + 0x7b2349e0, 0x522d, 0x4f8e, {0xb9, 0x27, 0x69, 0xd9, 0x7c, 0x9e, 0x79, 0x5f} \ + } + +extern EFI_GUID gEfiPaddingRsassaPssGuid; + +// +// Padding methods GUIDs for decryption +// +// +// No padding, for decryption +// +#define EFI_PADDING_NONE_GUID \ + { \ + 0x3629ddb1, 0x228c, 0x452e, {0xb6, 0x16, 0x09, 0xed, 0x31, 0x6a, 0x97, 0x00} \ + } + +extern EFI_GUID gEfiPaddingNoneGuid; + +// +// RSAES-PKCS#1-V1.5 padding, for decryption +// +#define EFI_PADDING_RSAES_PKCS1V1P5_GUID \ + { \ + 0xe1c1d0a9, 0x40b1, 0x4632, {0xbd, 0xcc, 0xd9, 0xd6, 0xe5, 0x29, 0x56, 0x31} \ + } + +extern EFI_GUID gEfiPaddingRsaesPkcs1V1P5Guid; + +// +// RSAES-OAEP padding, for decryption +// +#define EFI_PADDING_RSAES_OAEP_GUID \ + { \ + 0xc1e63ac4, 0xd0cf, 0x4ce6, {0x83, 0x5b, 0xee, 0xd0, 0xe6, 0xa8, 0xa4, 0x5b} \ + } + +extern EFI_GUID gEfiPaddingRsaesOaepGuid; + +/** + This function retrieves the context driver. + + The GetContextfunction returns the context of the protocol, the application + identifiers supported by the protocol and the number and the CSN unique identifier + of Smart Cards that are present and supported by protocol. + + If AidTableSize, AidTable, CsnTableSize, CsnTable or VersionProtocol is NULL, + the function does not fail but does not fill in such variables. + + In case AidTableSize indicates a buffer too small to hold all the protocol AID table, + only the first AidTableSize items of the table are returned in AidTable. + + In case CsnTableSize indicates a buffer too small to hold the entire table of + Smart Card CSN present, only the first CsnTableSize items of the table are returned + in CsnTable. + + VersionScEdgeProtocol returns the version of the EFI_SMART_CARD_EDGE_PROTOCOL this + driver uses. For this protocol specification value is SMART_CARD_EDGE_PROTOCOL_VERSION_1. + + In case of Smart Card removal the internal CSN list is immediately updated, even if + a connection is opened with that Smart Card. + + @param[in] This Indicates a pointer to the calling context. + @param[out] NumberAidSupported Number of AIDs this protocol supports. + @param[in, out] AidTableSize On input, number of items allocated for the + AID table. On output, number of items returned + by protocol. + @param[out] AidTable Table of the AIDs supported by the protocol. + @param[out] NumberSCPresent Number of currently present Smart Cards that + are supported by protocol. + @param[in, out] CsnTableSize On input, the number of items the buffer CSN + table can contain. On output, the number of + items returned by the protocol. + @param[out] CsnTable Table of the CSN of the Smart Card present and + supported by protocol. + @param[out] VersionScEdgeProtocol EFI_SMART_CARD_EDGE_PROTOCOL version. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER NumberSCPresent is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_GET_CONTEXT) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + OUT UINTN *NumberAidSupported, + IN OUT UINTN *AidTableSize OPTIONAL, + OUT SMART_CARD_AID *AidTable OPTIONAL, + OUT UINTN *NumberSCPresent, + IN OUT UINTN *CsnTableSize OPTIONAL, + OUT SMART_CARD_CSN *CsnTable OPTIONAL, + OUT UINT32 *VersionScEdgeProtocol OPTIONAL + ); + +/** + This function establish a connection with a Smart Card the protocol support. + + In case of success the SCardHandle can be used. + + If the ScardCsn is NULL the connection is established with the first Smart Card + the protocol finds in its table of Smart Card present and supported. Else it + establish context with the Smart Card whose CSN given by ScardCsn. + + If ScardAid is not NULL the function returns the Smart Card AID the protocol supports. + After a successful connect the SCardHandle will remain existing even in case Smart Card + removed from Smart Card reader, but all function invoking this SCardHandle will fail. + SCardHandle is released only on Disconnect. + + @param[in] This Indicates a pointer to the calling context. + @param[out] SCardHandle Handle on Smart Card connection. + @param[in] ScardCsn CSN of the Smart Card the connection has to be + established. + @param[out] ScardAid AID of the Smart Card the connection has been + established. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER SCardHandle is NULL. + @retval EFI_NO_MEDIA No Smart Card supported by protocol is present, + Smart Card with CSN ScardCsn or Reader has been + removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_CONNECT) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + OUT EFI_HANDLE *SCardHandle, + IN UINT8 *ScardCsn OPTIONAL, + OUT UINT8 *ScardAid OPTIONAL + ); + +/** + This function releases a connection previously established by Connect. + + The Disconnect function releases the connection previously established by + a Connect. In case the Smart Card or the Smart Card reader has been removed + before this call, this function returns EFI_SUCCESS. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection to release. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_DISCONNECT) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle + ); + +/** + This function returns the Smart Card serial number. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[out] Csn The Card Serial number, 16 bytes array. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_GET_CSN) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + OUT UINT8 Csn[SCARD_CSN_SIZE] + ); + +/** + This function returns the name of the Smart Card reader used for this connection. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in, out] ReaderNameLength On input, a pointer to the variable that holds + the maximal size, in bytes, of ReaderName. + On output, the required size, in bytes, for ReaderName. + @param[out] ReaderName A pointer to a NULL terminated string that will + contain the reader name. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER ReaderNameLength is NULL. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_GET_READER_NAME) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN OUT UINTN *ReaderNameLength, + OUT CHAR16 *ReaderName OPTIONAL + ); + +/** + This function authenticates a Smart Card user by presenting a PIN code. + + The VerifyPinfunction presents a PIN code to the Smart Card. + + If Smart Card found the PIN code correct the user is considered authenticated + to current application, and the function returns TRUE. + + Negative or null PinSize value rejected if PinCodeis not NULL. + + A NULL PinCodebuffer means the application didn't know the PIN, in that case: + - If PinSize value is negative the caller only wants to know if the current + chain of the elements Smart Card Edge protocol, Smart Card Reader protocol + and Smart Card Reader supports the Secure Pin Entry PCSC V2 functionality. + - If PinSize value is positive or null the caller ask to perform the verify + PIN using the Secure PIN Entry functionality. + + In PinCode buffer, the PIN value is always given in plaintext, in case of secure + messaging the SMART_CARD_EDGE_PROTOCOL will be in charge of all intermediate + treatments to build the correct Smart Card APDU. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in] PinSize PIN code buffer size. + @param[in] PinCode PIN code to present to the Smart Card. + @param[out] PinResult Result of PIN code presentation to the Smart Card. + TRUE when Smard Card founds the PIN code correct. + @param[out] RemainingAttempts Number of attempts still possible. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_UNSUPPORTED Pinsize < 0 and Secure PIN Entry functionality not + supported. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER Bad value for PinSize: value not supported by Smart + Card or, negative with PinCode not null. + @retval EFI_INVALID_PARAMETER PinResult is NULL. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_VERIFY_PIN) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN INT32 PinSize, + IN UINT8 *PinCode, + OUT BOOLEAN *PinResult, + OUT UINT32 *RemainingAttempts OPTIONAL + ); + +/** + This function gives the remaining number of attempts for PIN code presentation. + + The number of attempts to present a correct PIN is limited and depends on Smart + Card and on PIN. + + This function will retrieve the number of remaining possible attempts. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[out] RemainingAttempts Number of attempts still possible. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER RemainingAttempts is NULL. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_GET_PIN_REMAINING) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + OUT UINT32 *RemainingAttempts + ); + +/** + This function returns a specific data from Smart Card. + + The function is generic for any kind of data, but driver and application must + share an EFI_GUID that identify the data. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in] DataId The type identifier of the data to get. + @param[in, out] DataSize On input, in bytes, the size of Data. On output, + in bytes, the size of buffer required to store + the specified data. + @param[out] Data The data buffer in which the data is returned. + The type of the data buffer is associated with + the DataId. Ignored if *DataSize is 0. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER DataId is NULL. + @retval EFI_INVALID_PARAMETER DataSize is NULL. + @retval EFI_INVALID_PARAMETER Data is NULL, and *DataSize is not zero. + @retval EFI_NOT_FOUND DataId unknown for this driver. + @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified + data and the required size is returned in DataSize. + @retval EFI_ACCESS_DENIED Operation not performed, conditions not fulfilled. + PIN not verified. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_GET_DATA) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN EFI_GUID *DataId, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + This function retrieve credentials store into the Smart Card. + + The function returns a series of items in TLV (Tag Length Value) format. + + First TLV item is the header item that gives the number of following + containers (0x00, 0x01, Nb containers). + + All these containers are a series of 4 TLV items: + - The certificate item (0x01, certificate size, certificate) + - The Key identifier item (0x02, 0x01, key index) + - The key type item (0x03, 0x01, key type) + - The key size item (0x04, 0x02, key size), key size in number of bits. + Numeric multi-bytes values are on big endian format, most significant byte first: + - The L field value for certificate (2 bytes) + - The L field value for key size (2 bytes) + - The value field for key size (2 bytes) + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in, out] CredentialSize On input, in bytes, the size of buffer to store + the list of credential. + On output, in bytes, the size of buffer required + to store the entire list of credentials. + + @param[out] CredentialList List of credentials stored into the Smart Card. + A list of TLV (Tag Length Value) elements organized + in containers array. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER CredentialSize is NULL. + @retval EFI_INVALID_PARAMETER CredentialList is NULL, if CredentialSize is not zero. + @retval EFI_BUFFER_TOO_SMALL The size of CredentialList is too small for the + specified data and the required size is returned in + CredentialSize. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_GET_CREDENTIAL) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN OUT UINTN *CredentialSize, + OUT UINT8 *CredentialList OPTIONAL + ); + +/** + This function signs an already hashed data with a Smart Card private key. + + This function signs data, actually it is the hash of these data that is given + to the function. + + SignatureData buffer shall be big enough for signature. Signature size is + function key size and key type. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in] KeyId Identifier of the key container, retrieved + in a key index item of credentials. + @param[in] KeyType The key type, retrieved in a key type item of + credentials. + + @param[in] HashAlgorithm Hash algorithm used to hash the, one of: + - EFI_HASH_ALGORITHM_SHA1_GUID + - EFI_HASH_ALGORITHM_SHA256_GUID + - EFI_HASH_ALGORITHM_SHA384_GUID + - EFI_HASH_ALGORITHM_SHA512_GUID + @param[in] PaddingMethod Padding method used jointly with hash algorithm, + one of: + - EFI_PADDING_RSASSA_PKCS1V1P5_GUID + - EFI_PADDING_RSASSA_PSS_GUID + @param[in] HashedData Hash of the data to sign. Size is function of the + HashAlgorithm. + + @param[out] SignatureData Resulting signature with private key KeyId. Size + is function of the KeyType and key size retrieved + in the associated key size item of credentials. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER KeyId is not valid. + @retval EFI_INVALID_PARAMETER KeyType is not valid or not corresponding to KeyId. + @retval EFI_INVALID_PARAMETER HashAlgorithm is NULL. + @retval EFI_INVALID_PARAMETER HashAlgorithm is not valid. + @retval EFI_INVALID_PARAMETER PaddingMethod is NULL. + @retval EFI_INVALID_PARAMETER PaddingMethod is not valid. + @retval EFI_INVALID_PARAMETER HashedData is NULL. + @retval EFI_INVALID_PARAMETER SignatureData is NULL. + @retval EFI_ACCESS_DENIED Operation not performed, conditions not fulfilled. + PIN not verified. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_SIGN_DATA) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN UINTN KeyId, + IN UINTN KeyType, + IN EFI_GUID *HashAlgorithm, + IN EFI_GUID *PaddingMethod, + IN UINT8 *HashedData, + OUT UINT8 *SignatureData + ); + +/** + This function decrypts data with a PKI/RSA Smart Card private key. + + The function decrypts some PKI/RSA encrypted data with private key securely + stored into the Smart Card. + + The KeyId must reference a key of type SC_EDGE_RSA_EXCHANGE. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in] KeyId Identifier of the key container, retrieved + in a key index item of credentials. + @param[in] HashAlgorithm Hash algorithm used to hash the, one of: + - EFI_HASH_ALGORITHM_SHA1_GUID + - EFI_HASH_ALGORITHM_SHA256_GUID + - EFI_HASH_ALGORITHM_SHA384_GUID + - EFI_HASH_ALGORITHM_SHA512_GUID + @param[in] PaddingMethod Padding method used jointly with hash algorithm, + one of: + - EFI_PADDING_NONE_GUID + - EFI_PADDING_RSAES_PKCS1V1P5_GUID + - EFI_PADDING_RSAES_OAEP_GUID + @param[in] EncryptedSize Size of data to decrypt. + @param[in] EncryptedData Data to decrypt + @param[in, out] PlaintextSize On input, in bytes, the size of buffer to store + the decrypted data. + On output, in bytes, the size of buffer required + to store the decrypted data. + @param[out] PlaintextData Buffer for decrypted data, padding removed. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER KeyId is not valid or associated key not of type + SC_EDGE_RSA_EXCHANGE. + @retval EFI_INVALID_PARAMETER HashAlgorithm is NULL. + @retval EFI_INVALID_PARAMETER HashAlgorithm is not valid. + @retval EFI_INVALID_PARAMETER PaddingMethod is NULL. + @retval EFI_INVALID_PARAMETER PaddingMethod is not valid. + @retval EFI_INVALID_PARAMETER EncryptedSize is 0. + @retval EFI_INVALID_PARAMETER EncryptedData is NULL. + @retval EFI_INVALID_PARAMETER PlaintextSize is NULL. + @retval EFI_INVALID_PARAMETER PlaintextData is NULL. + @retval EFI_ACCESS_DENIED Operation not performed, conditions not fulfilled. + PIN not verified. + @retval EFI_BUFFER_TOO_SMALL PlaintextSize is too small for the plaintext data + and the required size is returned in PlaintextSize. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_DECRYPT_DATA) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN UINTN KeyId, + IN EFI_GUID *HashAlgorithm, + IN EFI_GUID *PaddingMethod, + IN UINTN EncryptedSize, + IN UINT8 *EncryptedData, + IN OUT UINTN *PlaintextSize, + OUT UINT8 *PlaintextData + ); + +/** + This function performs a secret Diffie Hellman agreement calculation that would + be used to derive a symmetric encryption / decryption key. + + The function compute a DH agreement that should be diversified togenerate a symmetric + key to proceed encryption or decryption. + + The application and the Smart Card shall agree on the diversification process. + + The KeyId must reference a key of one of the types: SC_EDGE_ECDH_256, SC_EDGE_ECDH_384 + or SC_EDGE_ECDH_521. + + @param[in] This Indicates a pointer to the calling context. + @param[in] SCardHandle Handle on Smart Card connection. + @param[in] KeyId Identifier of the key container, retrieved + in a key index item of credentials. + @param[in] dataQx Public key x coordinate. Size is the same as + key size for KeyId. Stored in big endian format. + @param[in] dataQy Public key y coordinate. Size is the same as + key size for KeyId. Stored in big endian format. + @param[out] DHAgreement Buffer for DH agreement computed. Size must be + bigger or equal to key size for KeyId. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER No connection for SCardHandle value. + @retval EFI_INVALID_PARAMETER KeyId is not valid. + @retval EFI_INVALID_PARAMETER dataQx is NULL. + @retval EFI_INVALID_PARAMETER dataQy is NULL. + @retval EFI_INVALID_PARAMETER DHAgreement is NULL. + @retval EFI_ACCESS_DENIED Operation not performed, conditions not fulfilled. + PIN not verified. + @retval EFI_NO_MEDIA Smart Card or Reader of SCardHandle connection + has been removed. A Disconnect should be performed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_EDGE_BUILD_DH_AGREEMENT) ( + IN EFI_SMART_CARD_EDGE_PROTOCOL *This, + IN EFI_HANDLE SCardHandle, + IN UINTN KeyId, + IN UINT8 *dataQx, + IN UINT8 *dataQy, + OUT UINT8 *DHAgreement + ); + +/// +/// Smart card aware application invokes this protocol to get access to an inserted +/// smart card in the reader or to the reader itself. +/// +struct _EFI_SMART_CARD_EDGE_PROTOCOL { + EFI_SMART_CARD_EDGE_GET_CONTEXT GetContext; + EFI_SMART_CARD_EDGE_CONNECT Connect; + EFI_SMART_CARD_EDGE_DISCONNECT Disconnect; + EFI_SMART_CARD_EDGE_GET_CSN GetCsn; + EFI_SMART_CARD_EDGE_GET_READER_NAME GetReaderName; + EFI_SMART_CARD_EDGE_VERIFY_PIN VerifyPin; + EFI_SMART_CARD_EDGE_GET_PIN_REMAINING GetPinRemaining; + EFI_SMART_CARD_EDGE_GET_DATA GetData; + EFI_SMART_CARD_EDGE_GET_CREDENTIAL GetCredential; + EFI_SMART_CARD_EDGE_SIGN_DATA SignData; + EFI_SMART_CARD_EDGE_DECRYPT_DATA DecryptData; + EFI_SMART_CARD_EDGE_BUILD_DH_AGREEMENT BuildDHAgreement; +}; + +extern EFI_GUID gEfiSmartCardEdgeProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardReader.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardReader.h new file mode 100644 index 0000000..a39b379 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmartCardReader.h @@ -0,0 +1,325 @@ +/** @file + The UEFI Smart Card Reader Protocol provides an abstraction for device to provide + smart card reader support. This protocol is very close to Part 5 of PC/SC workgroup + specifications and provides an API to applications willing to communicate with a + smart card or a smart card reader. + + Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMART_CARD_READER_H__ +#define __SMART_CARD_READER_H__ + +#define EFI_SMART_CARD_READER_PROTOCOL_GUID \ + { \ + 0x2a4d1adf, 0x21dc, 0x4b81, {0xa4, 0x2f, 0x8b, 0x8e, 0xe2, 0x38, 0x00, 0x60} \ + } + +typedef struct _EFI_SMART_CARD_READER_PROTOCOL EFI_SMART_CARD_READER_PROTOCOL; + +// +// Codes for access mode +// +#define SCARD_AM_READER 0x0001 // Exclusive access to reader +#define SCARD_AM_CARD 0x0002 // Exclusive access to card +// +// Codes for card action +// +#define SCARD_CA_NORESET 0x0000 // Don't reset card +#define SCARD_CA_COLDRESET 0x0001 // Perform a cold reset +#define SCARD_CA_WARMRESET 0x0002 // Perform a warm reset +#define SCARD_CA_UNPOWER 0x0003 // Power off the card +#define SCARD_CA_EJECT 0x0004 // Eject the card +// +// Protocol types +// +#define SCARD_PROTOCOL_UNDEFINED 0x0000 +#define SCARD_PROTOCOL_T0 0x0001 +#define SCARD_PROTOCOL_T1 0x0002 +#define SCARD_PROTOCOL_RAW 0x0004 +// +// Codes for state type +// +#define SCARD_UNKNOWN 0x0000 /* state is unknown */ +#define SCARD_ABSENT 0x0001 /* Card is absent */ +#define SCARD_INACTIVE 0x0002 /* Card is present and not powered*/ +#define SCARD_ACTIVE 0x0003 /* Card is present and powered */ +// +// Macro to generate a ControlCode & PC/SC part 10 control code +// +#define SCARD_CTL_CODE(code) (0x42000000 + (code)) +#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) + +/** + This function requests connection to the smart card or the reader, using the + appropriate reset type and protocol. + + The SCardConnectfunction requests access to the smart card or the reader. Upon + success, it is then possible to call SCardTransmit. + + If AccessMode is set to SCARD_AM_READER, PreferredProtocols must be set to + SCARD_PROTOCOL_UNDEFINED and CardAction to SCARD_CA_NORESET else function + fails with EFI_INVALID_PARAMETER. + + @param[in] This Indicates a pointer to the calling context. + @param[in] AccessMode Codes of access mode. + @param[in] CardAction SCARD_CA_NORESET, SCARD_CA_COLDRESET or + SCARD_CA_WARMRESET. + @param[in] PreferredProtocols Bitmask of acceptable protocols. + @param[out] ActiveProtocol A flag that indicates the active protocol. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL + @retval EFI_INVALID_PARAMETER AccessMode is not valid. + @retval EFI_INVALID_PARAMETER CardAction is not valid. + @retval EFI_INVALID_PARAMETER Invalid combination of AccessMode/CardAction/ + PreferredProtocols. + @retval EFI_NOT_READY A smart card is inserted but failed to return an ATR. + @retval EFI_UNSUPPORTED PreferredProtocols does not contain an available + protocol to use. + @retval EFI_NO_MEDIA AccessMode is set to SCARD_AM_CARD but there is + no smart card inserted. + @retval EFI_ACCESS_DENIED Access is already locked by a previous SCardConnectcall. + @retval EFI_DEVICE_ERROR Any other error condition, typically a reader removal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_READER_CONNECT) ( + IN EFI_SMART_CARD_READER_PROTOCOL *This, + IN UINT32 AccessMode, + IN UINT32 CardAction, + IN UINT32 PreferredProtocols, + OUT UINT32 *ActiveProtocol + ); + +/** + This function releases a connection previously taken by SCardConnect. + + The SCardDisconnect function releases the lock previously taken by SCardConnect. + In case the smart card has been removed before this call, thisfunction + returns EFI_SUCCESS. If there is no previous call to SCardConnect, this + function returns EFI_SUCCESS. + + @param[in] This Indicates a pointer to the calling context. + @param[in] CardAction Codes for card action. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL + @retval EFI_INVALID_PARAMETER CardAction value is unknown. + @retval EFI_UNSUPPORTED Reader does not support Eject card feature + (disconnect was not performed). + @retval EFI_DEVICE_ERROR Any other error condition, typically a reader removal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_READER_DISCONNECT) ( + IN EFI_SMART_CARD_READER_PROTOCOL *This, + IN UINT32 CardAction + ); + +/** + This function retrieves some basic information about the smart card and reader. + + The SCardStatusfunction retrieves basic reader and card information. + + If ReaderName, State, CardProtocolor Atris NULL, the function does not fail but + does not fill in such variables. + + If EFI_SUCCESS is not returned, ReaderName and Atr contents shall not be considered + as valid. + + @param[in] This Indicates a pointer to the calling context. + @param[out] ReaderName A pointer to a NULL terminated string that will + contain the reader name. + @param[in, out] ReaderNameLength On input, a pointer to the variablethat holds the + maximal size, in bytes,of ReaderName. + On output, the required size, in bytes, for ReaderName. + @param[out] State Current state of the smart card reader. + @param[out] CardProtocol Current protocol used to communicate with the smart card. + @param[out] Atr A pointer to retrieve the ATR of the smart card. + @param[in, out] AtrLength On input, a pointer to hold the maximum size, in bytes, + of Atr(usually 33). + On output, the required size, inbytes, for the smart + card ATR. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL + @retval EFI_INVALID_PARAMETER ReaderName is not NULL but ReaderNameLength is NULL + @retval EFI_INVALID_PARAMETER Atr is not NULL but AtrLength is NULL + @retval EFI_BUFFER_TOO_SMALL ReaderNameLength is not big enough to hold the reader name. + ReaderNameLength has been updated to the required value. + @retval EFI_BUFFER_TOO_SMALL AtrLength is not big enough to hold the ATR. + AtrLength has been updated to the required value. + @retval EFI_DEVICE_ERROR Any other error condition, typically a reader removal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_READER_STATUS) ( + IN EFI_SMART_CARD_READER_PROTOCOL *This, + OUT CHAR16 *ReaderName OPTIONAL, + IN OUT UINTN *ReaderNameLength OPTIONAL, + OUT UINT32 *State OPTIONAL, + OUT UINT32 *CardProtocol OPTIONAL, + OUT UINT8 *Atr OPTIONAL, + IN OUT UINTN *AtrLength OPTIONAL + ); + +/** + This function sends a command to the card or reader and returns its response. + + The protocol to use to communicate with the smart card has been selected through + SCardConnectcall. + + In case RAPDULength indicates a buffer too small to holdthe response APDU, the + function fails with EFI_BUFFER_TOO_SMALL. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOLinstance. + @param[in] CAPDU A pointer to a byte array thatcontains the Command + APDU to send to the smart card or reader. + @param[in] CAPDULength Command APDU size, in bytes. + @param[out] RAPDU A pointer to a byte array that will contain the + Response APDU. + @param[in, out] RAPDULength On input, the maximum size, inbytes, of the Response + APDU. + On output, the size, in bytes, of the Response APDU. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER CAPDU is NULL or CAPDULength is 0. + @retval EFI_BUFFER_TOO_SMALL RAPDULength is not big enough to hold the response APDU. + RAPDULength has been updated to the required value. + @retval EFI_NO_MEDIA There is no card in the reader. + @retval EFI_NOT_READY Card is not powered. + @retval EFI_PROTOCOL_ERROR A protocol error has occurred. + @retval EFI_TIMEOUT The reader did not respond. + @retval EFI_ACCESS_DENIED A communication with the reader/card is already pending. + @retval EFI_DEVICE_ERROR Any other error condition, typically a reader removal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_READER_TRANSMIT) ( + IN EFI_SMART_CARD_READER_PROTOCOL *This, + IN UINT8 *CAPDU, + IN UINTN CAPDULength, + OUT UINT8 *RAPDU, + IN OUT UINTN *RAPDULength + ); + +/** + This function provides direct access to the reader. + + This function gives direct control to send commands to the driver or the reader. + The ControlCode to use is vendor dependant; the only standard code defined is + the one to get PC/SC part 10 features. + + InBuffer and Outbuffer may be NULL when ControlCode operation does not require + them. + + @param[in] This Indicates a pointer to the calling context. + @param[in] ControlCode The control code for the operation to perform. + @param[in] InBuffer A pointer to the input parameters. + @param[in] InBufferLength Size, in bytes, of input parameters. + @param[out] OutBuffer A pointer to the output parameters. + @param[in, out] OutBufferLength On input, maximal size, in bytes, to store output + parameters. + On output, the size, in bytes, of output parameters. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER ControlCode requires input parameters but: + InBuffer is NULL or InBufferLenth is NULL or + InBuffer is not NULL but InBufferLenth is less than + expected. + @retval EFI_INVALID_PARAMETER OutBuffer is not NULL but OutBufferLength is NULL. + @retval EFI_UNSUPPORTED ControlCode is not supported. + @retval EFI_BUFFER_TOO_SMALL OutBufferLength is not big enough to hold the output + parameters. + OutBufferLength has been updated to the required value. + @retval EFI_NO_MEDIA There is no card in the reader and the control code + specified requires one. + @retval EFI_NOT_READY ControlCode requires a powered card to operate. + @retval EFI_PROTOCOL_ERROR A protocol error has occurred. + @retval EFI_TIMEOUT The reader did not respond. + @retval EFI_ACCESS_DENIED A communication with the reader/card is already pending. + @retval EFI_DEVICE_ERROR Any other error condition, typically a reader removal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_READER_CONTROL) ( + IN EFI_SMART_CARD_READER_PROTOCOL *This, + IN UINT32 ControlCode, + IN UINT8 *InBuffer OPTIONAL, + IN UINTN InBufferLength OPTIONAL, + OUT UINT8 *OutBuffer OPTIONAL, + IN OUT UINTN *OutBufferLength OPTIONAL + ); + +/** + This function retrieves a reader or smart card attribute. + + Possibly supported attrib values are listed in "PC/SC specification, Part 3: + Requirements for PC-Connected Interface Devices". + + @param[in] This Indicates a pointer to the calling context. + @param[in] Attrib Identifier for the attribute to retrieve. + @param[out] OutBuffer A pointer to a buffer that will contain + attribute data. + @param[in, out] OutBufferLength On input, maximal size, in bytes, to store + attribute data. + On output, the size, in bytes, of attribute + data. + + @retval EFI_SUCCESS The requested command completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER OutBuffer is NULL or OutBufferLength is 0. + @retval EFI_BUFFER_TOO_SMALL OutBufferLength is not big enough to hold the output + parameters. + OutBufferLength has been updated to the required value. + @retval EFI_UNSUPPORTED Attribis not supported + @retval EFI_NO_MEDIA There is no card in the reader and Attrib value + requires one. + @retval EFI_NOT_READY Attrib requires a powered card to operate. + @retval EFI_PROTOCOL_ERROR A protocol error has occurred. + @retval EFI_TIMEOUT The reader did not respond. + @retval EFI_DEVICE_ERROR Any other error condition, typically a reader removal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMART_CARD_READER_GET_ATTRIB) ( + IN EFI_SMART_CARD_READER_PROTOCOL *This, + IN UINT32 Attrib, + OUT UINT8 *OutBuffer, + IN OUT UINTN *OutBufferLength + ); + +/// +/// Smart card aware application invokes this protocol to get access to an inserted +/// smart card in the reader or to the reader itself. +/// +struct _EFI_SMART_CARD_READER_PROTOCOL { + EFI_SMART_CARD_READER_CONNECT SCardConnect; + EFI_SMART_CARD_READER_DISCONNECT SCardDisconnect; + EFI_SMART_CARD_READER_STATUS SCardStatus; + EFI_SMART_CARD_READER_TRANSMIT SCardTransmit; + EFI_SMART_CARD_READER_CONTROL SCardControl; + EFI_SMART_CARD_READER_GET_ATTRIB SCardGetAttrib; +}; + +extern EFI_GUID gEfiSmartCardReaderProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Smbios.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Smbios.h new file mode 100644 index 0000000..4dd217a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Smbios.h @@ -0,0 +1,213 @@ +/** @file + SMBIOS Protocol as defined in PI1.2 Specification VOLUME 5 Standard. + + SMBIOS protocol allows consumers to log SMBIOS data records, and enables the producer + to create the SMBIOS tables for a platform. + + This protocol provides an interface to add, remove or discover SMBIOS records. The driver which + produces this protocol is responsible for creating the SMBIOS data tables and installing the pointer + to the tables in the EFI System Configuration Table. + The caller is responsible for only adding SMBIOS records that are valid for the SMBIOS + MajorVersion and MinorVersion. When an enumerated SMBIOS field's values are + controlled by the DMTF, new values can be used as soon as they are defined by the DMTF without + requiring an update to MajorVersion and MinorVersion. + The SMBIOS protocol can only be called a TPL < TPL_NOTIFY. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SMBIOS_PROTOCOL_H__ +#define __SMBIOS_PROTOCOL_H__ + +#include + +#define EFI_SMBIOS_PROTOCOL_GUID \ + { 0x3583ff6, 0xcb36, 0x4940, { 0x94, 0x7e, 0xb9, 0xb3, 0x9f, 0x4a, 0xfa, 0xf7 }} + +#define EFI_SMBIOS_TYPE_BIOS_INFORMATION SMBIOS_TYPE_BIOS_INFORMATION +#define EFI_SMBIOS_TYPE_SYSTEM_INFORMATION SMBIOS_TYPE_SYSTEM_INFORMATION +#define EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION SMBIOS_TYPE_BASEBOARD_INFORMATION +#define EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE SMBIOS_TYPE_SYSTEM_ENCLOSURE +#define EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION SMBIOS_TYPE_PROCESSOR_INFORMATION +#define EFI_SMBIOS_TYPE_MEMORY_CONTROLLER_INFORMATION SMBIOS_TYPE_MEMORY_CONTROLLER_INFORMATION +#define EFI_SMBIOS_TYPE_MEMORY_MODULE_INFORMATON SMBIOS_TYPE_MEMORY_MODULE_INFORMATON +#define EFI_SMBIOS_TYPE_CACHE_INFORMATION SMBIOS_TYPE_CACHE_INFORMATION +#define EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION +#define EFI_SMBIOS_TYPE_SYSTEM_SLOTS SMBIOS_TYPE_SYSTEM_SLOTS +#define EFI_SMBIOS_TYPE_ONBOARD_DEVICE_INFORMATION SMBIOS_TYPE_ONBOARD_DEVICE_INFORMATION +#define EFI_SMBIOS_TYPE_OEM_STRINGS SMBIOS_TYPE_OEM_STRINGS +#define EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS +#define EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION +#define EFI_SMBIOS_TYPE_GROUP_ASSOCIATIONS SMBIOS_TYPE_GROUP_ASSOCIATIONS +#define EFI_SMBIOS_TYPE_SYSTEM_EVENT_LOG SMBIOS_TYPE_SYSTEM_EVENT_LOG +#define EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY +#define EFI_SMBIOS_TYPE_MEMORY_DEVICE SMBIOS_TYPE_MEMORY_DEVICE +#define EFI_SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION +#define EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS +#define EFI_SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS +#define EFI_SMBIOS_TYPE_BUILT_IN_POINTING_DEVICE SMBIOS_TYPE_BUILT_IN_POINTING_DEVICE +#define EFI_SMBIOS_TYPE_PORTABLE_BATTERY SMBIOS_TYPE_PORTABLE_BATTERY +#define EFI_SMBIOS_TYPE_SYSTEM_RESET SMBIOS_TYPE_SYSTEM_RESET +#define EFI_SMBIOS_TYPE_HARDWARE_SECURITY SMBIOS_TYPE_HARDWARE_SECURITY +#define EFI_SMBIOS_TYPE_SYSTEM_POWER_CONTROLS SMBIOS_TYPE_SYSTEM_POWER_CONTROLS +#define EFI_SMBIOS_TYPE_VOLTAGE_PROBE SMBIOS_TYPE_VOLTAGE_PROBE +#define EFI_SMBIOS_TYPE_COOLING_DEVICE SMBIOS_TYPE_COOLING_DEVICE +#define EFI_SMBIOS_TYPE_TEMPERATURE_PROBE SMBIOS_TYPE_TEMPERATURE_PROBE +#define EFI_SMBIOS_TYPE_ELECTRICAL_CURRENT_PROBE SMBIOS_TYPE_ELECTRICAL_CURRENT_PROBE +#define EFI_SMBIOS_TYPE_OUT_OF_BAND_REMOTE_ACCESS SMBIOS_TYPE_OUT_OF_BAND_REMOTE_ACCESS +#define EFI_SMBIOS_TYPE_BOOT_INTEGRITY_SERVICE SMBIOS_TYPE_BOOT_INTEGRITY_SERVICE +#define EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION +#define EFI_SMBIOS_TYPE_64BIT_MEMORY_ERROR_INFORMATION SMBIOS_TYPE_64BIT_MEMORY_ERROR_INFORMATION +#define EFI_SMBIOS_TYPE_MANAGEMENT_DEVICE SMBIOS_TYPE_MANAGEMENT_DEVICE +#define EFI_SMBIOS_TYPE_MANAGEMENT_DEVICE_COMPONENT SMBIOS_TYPE_MANAGEMENT_DEVICE_COMPONENT +#define EFI_SMBIOS_TYPE_MANAGEMENT_DEVICE_THRESHOLD_DATA SMBIOS_TYPE_MANAGEMENT_DEVICE_THRESHOLD_DATA +#define EFI_SMBIOS_TYPE_MEMORY_CHANNEL SMBIOS_TYPE_MEMORY_CHANNEL +#define EFI_SMBIOS_TYPE_IPMI_DEVICE_INFORMATION SMBIOS_TYPE_IPMI_DEVICE_INFORMATION +#define EFI_SMBIOS_TYPE_SYSTEM_POWER_SUPPLY SMBIOS_TYPE_SYSTEM_POWER_SUPPLY +#define EFI_SMBIOS_TYPE_ADDITIONAL_INFORMATION SMBIOS_TYPE_ADDITIONAL_INFORMATION +#define EFI_SMBIOS_TYPE_ONBOARD_DEVICES_EXTENDED_INFORMATION SMBIOS_TYPE_ONBOARD_DEVICES_EXTENDED_INFORMATION +#define EFI_SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE +#define EFI_SMBIOS_TYPE_INACTIVE SMBIOS_TYPE_INACTIVE +#define EFI_SMBIOS_TYPE_END_OF_TABLE SMBIOS_TYPE_END_OF_TABLE +#define EFI_SMBIOS_OEM_BEGIN SMBIOS_OEM_BEGIN +#define EFI_SMBIOS_OEM_END SMBIOS_OEM_END + +typedef SMBIOS_TABLE_STRING EFI_SMBIOS_STRING; +typedef SMBIOS_TYPE EFI_SMBIOS_TYPE; +typedef SMBIOS_HANDLE EFI_SMBIOS_HANDLE; +typedef SMBIOS_STRUCTURE EFI_SMBIOS_TABLE_HEADER; + +typedef struct _EFI_SMBIOS_PROTOCOL EFI_SMBIOS_PROTOCOL; + +/** + Add an SMBIOS record. + + This function allows any agent to add SMBIOS records. The caller is responsible for ensuring + Record is formatted in a way that matches the version of the SMBIOS specification as defined in + the MajorRevision and MinorRevision fields of the EFI_SMBIOS_PROTOCOL. + Record must follow the SMBIOS structure evolution and usage guidelines in the SMBIOS + specification. Record starts with the formatted area of the SMBIOS structure and the length is + defined by EFI_SMBIOS_TABLE_HEADER.Length. Each SMBIOS structure is terminated by a + double-null (0x0000), either directly following the formatted area (if no strings are present) or + directly following the last string. The number of optional strings is not defined by the formatted area, + but is fixed by the call to Add(). A string can be a place holder, but it must not be a NULL string as + two NULL strings look like the double-null that terminates the structure. + + @param[in] This The EFI_SMBIOS_PROTOCOL instance. + @param[in] ProducerHandle The handle of the controller or driver associated with the SMBIOS information. NULL means no handle. + @param[in, out] SmbiosHandle On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle + will be assigned to the SMBIOS record. If the SMBIOS handle is already in use, + EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated. + @param[in] Record The data for the fixed portion of the SMBIOS record. The format of the record is + determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted + area is defined by EFI_SMBIOS_TABLE_HEADER.Length and either followed + by a double-null (0x0000) or a set of null terminated strings and a null. + + @retval EFI_SUCCESS Record was added. + @retval EFI_OUT_OF_RESOURCES Record was not added. + @retval EFI_ALREADY_STARTED The SmbiosHandle passed in was already in use. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBIOS_ADD)( + IN CONST EFI_SMBIOS_PROTOCOL *This, + IN EFI_HANDLE ProducerHandle OPTIONAL, + IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle, + IN EFI_SMBIOS_TABLE_HEADER *Record +); + +/** + Update the string associated with an existing SMBIOS record. + + This function allows the update of specific SMBIOS strings. The number of valid strings for any + SMBIOS record is defined by how many strings were present when Add() was called. + + @param[in] This The EFI_SMBIOS_PROTOCOL instance. + @param[in] SmbiosHandle SMBIOS Handle of structure that will have its string updated. + @param[in] StringNumber The non-zero string number of the string to update. + @param[in] String Update the StringNumber string with String. + + @retval EFI_SUCCESS SmbiosHandle had its StringNumber String updated. + @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. + @retval EFI_UNSUPPORTED String was not added because it is longer than the SMBIOS Table supports. + @retval EFI_NOT_FOUND The StringNumber.is not valid for this SMBIOS record. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBIOS_UPDATE_STRING)( + IN CONST EFI_SMBIOS_PROTOCOL *This, + IN EFI_SMBIOS_HANDLE *SmbiosHandle, + IN UINTN *StringNumber, + IN CHAR8 *String +); + +/** + Remove an SMBIOS record. + + This function removes an SMBIOS record using the handle specified by SmbiosHandle. + + @param[in] This The EFI_SMBIOS_PROTOCOL instance. + @param[in] SmbiosHandle The handle of the SMBIOS record to remove. + + @retval EFI_SUCCESS SMBIOS record was removed. + @retval EFI_INVALID_PARAMETER SmbiosHandle does not specify a valid SMBIOS record. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBIOS_REMOVE)( + IN CONST EFI_SMBIOS_PROTOCOL *This, + IN EFI_SMBIOS_HANDLE SmbiosHandle +); + +/** + Allow the caller to discover all or some of the SMBIOS records. + + This function allows all of the SMBIOS records to be discovered. It's possible to find + only the SMBIOS records that match the optional Type argument. + + @param[in] This The EFI_SMBIOS_PROTOCOL instance. + @param[in, out] SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the + next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record + handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS records. + @param[in] Type On entry, it points to the type of the next SMBIOS record to return. If NULL, it + indicates that the next record of any type will be returned. Type is not + modified by the this function. + @param[out] Record On exit, points to a pointer to the the SMBIOS Record consisting of the formatted area + followed by the unformatted area. The unformatted area optionally contains text strings. + @param[out] ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no + ProducerHandle was passed into Add() NULL is returned. If a NULL pointer is + passed in no data will be returned. + @retval EFI_SUCCESS SMBIOS record information was successfully returned in Record. + SmbiosHandle is the handle of the current SMBIOS record + @retval EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBIOS_GET_NEXT)( + IN CONST EFI_SMBIOS_PROTOCOL *This, + IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle, + IN EFI_SMBIOS_TYPE *Type OPTIONAL, + OUT EFI_SMBIOS_TABLE_HEADER **Record, + OUT EFI_HANDLE *ProducerHandle OPTIONAL +); + +struct _EFI_SMBIOS_PROTOCOL { + EFI_SMBIOS_ADD Add; + EFI_SMBIOS_UPDATE_STRING UpdateString; + EFI_SMBIOS_REMOVE Remove; + EFI_SMBIOS_GET_NEXT GetNext; + UINT8 MajorVersion; ///< The major revision of the SMBIOS specification supported. + UINT8 MinorVersion; ///< The minor revision of the SMBIOS specification supported. +}; + +extern EFI_GUID gEfiSmbiosProtocolGuid; + +#endif // __SMBIOS_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmbusHc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmbusHc.h new file mode 100644 index 0000000..77586f9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmbusHc.h @@ -0,0 +1,295 @@ +/** @file + The file provides basic SMBus host controller management + and basic data transactions over the SMBus. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: PI + Version 1.00. + +**/ + +#ifndef __SMBUS_HC_H__ +#define __SMBUS_HC_H__ + +#include + +#define EFI_SMBUS_HC_PROTOCOL_GUID \ + {0xe49d33ed, 0x513d, 0x4634, { 0xb6, 0x98, 0x6f, 0x55, 0xaa, 0x75, 0x1c, 0x1b} } + +typedef struct _EFI_SMBUS_HC_PROTOCOL EFI_SMBUS_HC_PROTOCOL; + +/** + + The Execute() function provides a standard way to execute an + operation as defined in the System Management Bus (SMBus) + Specification. The resulting transaction will be either that + the SMBus slave devices accept this transaction or that this + function returns with error. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + SlaveAddress The SMBus slave address of the device + with which to communicate. Type + EFI_SMBUS_DEVICE_ADDRESS is defined in + EFI_PEI_SMBUS_PPI.Execute() in the Platform + Initialization SMBus PPI Specification. + + @param Command This command is transmitted by the SMBus host + controller to the SMBus slave device and the + interpretation is SMBus slave device specific. + It can mean the offset to a list of functions + inside an SMBus slave device. Not all + operations or slave devices support this + command's registers. Type + EFI_SMBUS_DEVICE_COMMAND is defined in + EFI_PEI_SMBUS_PPI.Execute() in the Platform + Initialization SMBus PPI Specification. + + @param Operation Signifies the particular SMBus + hardware protocol instance it will use to + execute the SMBus transactions. This SMBus + hardware protocol is defined by the SMBus + Specification and is not related to PI + Architecture. Type EFI_SMBUS_OPERATION is + defined in EFI_PEI_SMBUS_PPI.Execute() in the + Platform Initialization SMBus PPI + Specification. + + @param PecCheck Defines if Packet Error Code (PEC) checking + is required for this operation. SMBus Host + Controller Code Definitions Version 1.0 + August 21, 2006 13 + + @param Length Signifies the number of bytes that this operation will do. + The maximum number of bytes can be revision + specific and operation specific. This field + will contain the actual number of bytes that + are executed for this operation. Not all + operations require this argument. + + @param Buffer Contains the value of data to execute to the + SMBus slave device. Not all operations require + this argument. The length of this buffer is + identified by Length. + + + @retval EFI_SUCCESS The last data that was returned from the + access matched the poll exit criteria. + + @retval EFI_CRC_ERROR Checksum is not correct (PEC is incorrect). + + @retval EFI_TIMEOUT Timeout expired before the operation was + completed. Timeout is determined by the + SMBus host controller device. + + @retval EFI_OUT_OF_RESOURCES The request could not be + completed due to a lack of + resources. + + @retval EFI_DEVICE_ERROR The request was not completed + because a failure that was reflected + in the Host Status Register bit. + Device errors are a result of a + transaction collision, illegal + command field, unclaimed cycle (host + initiated), or bus errors + (collisions). + + @retval EFI_INVALID_PARAMETER Operation is not defined in + EFI_SMBUS_OPERATION. + + @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for + operations except for + EfiSmbusQuickRead and + EfiSmbusQuickWrite. Length is + outside the range of valid + values. + + @retval EFI_UNSUPPORTED The SMBus operation or PEC is not + supported. + + @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for + this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_EXECUTE_OPERATION)( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer +); + + + +/** + + The ArpDevice() function provides a standard way for a device driver to + enumerate the entire SMBus or specific devices on the bus. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param ArpAll A Boolean expression that indicates if the + host drivers need to enumerate all the devices + or enumerate only the device that is + identified by SmbusUdid. If ArpAll is TRUE, + SmbusUdid and SlaveAddress are optional. If + ArpAll is FALSE, ArpDevice will enumerate + SmbusUdid and the address will be at + SlaveAddress. + + @param SmbusUdid The Unique Device Identifier (UDID) that is + associated with this device. Type + EFI_SMBUS_UDID is defined in + EFI_PEI_SMBUS_PPI.ArpDevice() in the + Platform Initialization SMBus PPI + Specification. + + @param SlaveAddress The SMBus slave address that is + associated with an SMBus UDID. + + @retval EFI_SUCCESS The last data that was returned from the + access matched the poll exit criteria. + + @retval EFI_CRC_ERROR Checksum is not correct (PEC is + incorrect). + + @retval EFI_TIMEOUT Timeout expired before the operation was + completed. Timeout is determined by the + SMBus host controller device. + + @retval EFI_OUT_OF_RESOURCES The request could not be + completed due to a lack of + resources. + + @retval EFI_DEVICE_ERROR The request was not completed + because a failure was reflected in + the Host Status Register bit. Device + Errors are a result of a transaction + collision, illegal command field, + unclaimed cycle (host initiated), or + bus errors (collisions). + + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are + not implemented by this driver. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_PROTOCOL_ARP_DEVICE)( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID *SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL +); + + +/** + The GetArpMap() function returns the mapping of all the SMBus devices + that were enumerated by the SMBus host driver. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param Length Size of the buffer that contains the SMBus + device map. + + @param SmbusDeviceMap The pointer to the device map as + enumerated by the SMBus controller + driver. + + @retval EFI_SUCCESS The SMBus returned the current device map. + + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are + not implemented by this driver. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_PROTOCOL_GET_ARP_MAP)( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap +); + +/** + The notify function does some actions. + + @param SlaveAddress + The SMBUS hardware address to which the SMBUS device is preassigned or allocated. + + @param Data + Data of the SMBus host notify command that the caller wants to be called. + + @return EFI_STATUS +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_NOTIFY_FUNCTION)( + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data +); + + +/** + + The Notify() function registers all the callback functions to + allow the bus driver to call these functions when the + SlaveAddress/Data pair happens. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param SlaveAddress Address that the host controller detects + as sending a message and calls all the registered function. + + @param Data Data that the host controller detects as sending + message and calls all the registered function. + + + @param NotifyFunction The function to call when the bus + driver detects the SlaveAddress and + Data pair. + + @retval EFI_SUCCESS NotifyFunction was registered. + + @retval EFI_UNSUPPORTED ArpDevice, GetArpMap, and Notify are + not implemented by this driver. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_PROTOCOL_NOTIFY)( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction +); + + +/// +/// The EFI_SMBUS_HC_PROTOCOL provides SMBus host controller management and basic data +/// transactions over SMBus. There is one EFI_SMBUS_HC_PROTOCOL instance for each SMBus +/// host controller. +/// +struct _EFI_SMBUS_HC_PROTOCOL { + EFI_SMBUS_HC_EXECUTE_OPERATION Execute; + EFI_SMBUS_HC_PROTOCOL_ARP_DEVICE ArpDevice; + EFI_SMBUS_HC_PROTOCOL_GET_ARP_MAP GetArpMap; + EFI_SMBUS_HC_PROTOCOL_NOTIFY Notify; +}; + + +extern EFI_GUID gEfiSmbusHcProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmAccess2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmAccess2.h new file mode 100644 index 0000000..8df2408 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmAccess2.h @@ -0,0 +1,44 @@ +/** @file + EFI SMM Access2 Protocol as defined in the PI 1.2 specification. + + This protocol is used to control the visibility of the SMRAM on the platform. + It abstracts the location and characteristics of SMRAM. The expectation is + that the north bridge or memory controller would publish this protocol. + + The principal functionality found in the memory controller includes the following: + - Exposing the SMRAM to all non-SMM agents, or the "open" state + - Shrouding the SMRAM to all but the SMM agents, or the "closed" state + - Preserving the system integrity, or "locking" the SMRAM, such that the settings cannot be + perturbed by either boot service or runtime agents + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_ACCESS2_H_ +#define _SMM_ACCESS2_H_ + +#include + +#define EFI_SMM_ACCESS2_PROTOCOL_GUID EFI_MM_ACCESS_PROTOCOL_GUID + +typedef EFI_MM_ACCESS_PROTOCOL EFI_SMM_ACCESS2_PROTOCOL; + +typedef EFI_MM_OPEN EFI_SMM_OPEN2; + +typedef EFI_MM_CLOSE EFI_SMM_CLOSE2; + +typedef EFI_MM_LOCK EFI_SMM_LOCK2; + +typedef EFI_MM_CAPABILITIES EFI_SMM_CAPABILITIES2; +extern EFI_GUID gEfiSmmAccess2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmBase2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmBase2.h new file mode 100644 index 0000000..860ccd8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmBase2.h @@ -0,0 +1,85 @@ +/** @file + EFI SMM Base2 Protocol as defined in the PI 1.2 specification. + + This protocol is utilized by all SMM drivers to locate the SMM infrastructure services and determine + whether the driver is being invoked inside SMRAM or outside of SMRAM. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_BASE2_H_ +#define _SMM_BASE2_H_ + +#include +#include + +#define EFI_SMM_BASE2_PROTOCOL_GUID EFI_MM_BASE_PROTOCOL_GUID + +typedef struct _EFI_SMM_BASE2_PROTOCOL EFI_SMM_BASE2_PROTOCOL; + +/** + Service to indicate whether the driver is currently executing in the SMM Initialization phase. + + This service is used to indicate whether the driver is currently executing in the SMM Initialization + phase. For SMM drivers, this will return TRUE in InSmram while inside the driver's entry point and + otherwise FALSE. For combination SMM/DXE drivers, this will return FALSE in the DXE launch. For the + SMM launch, it behaves as an SMM driver. + + @param[in] This The EFI_SMM_BASE2_PROTOCOL instance. + @param[out] InSmram Pointer to a Boolean which, on return, indicates that the driver is + currently executing inside of SMRAM (TRUE) or outside of SMRAM (FALSE). + + @retval EFI_SUCCESS The call returned successfully. + @retval EFI_INVALID_PARAMETER InSmram was NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_INSIDE_OUT2)( + IN CONST EFI_SMM_BASE2_PROTOCOL *This, + OUT BOOLEAN *InSmram + ) +; + +/** + Returns the location of the System Management Service Table (SMST). + + This function returns the location of the System Management Service Table (SMST). The use of the + API is such that a driver can discover the location of the SMST in its entry point and then cache it in + some driver global variable so that the SMST can be invoked in subsequent handlers. + + @param[in] This The EFI_SMM_BASE2_PROTOCOL instance. + @param[in,out] Smst On return, points to a pointer to the System Management Service Table (SMST). + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Smst was invalid. + @retval EFI_UNSUPPORTED Not in SMM. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_GET_SMST_LOCATION2)( + IN CONST EFI_SMM_BASE2_PROTOCOL *This, + IN OUT EFI_SMM_SYSTEM_TABLE2 **Smst + ) +; + +/// +/// EFI SMM Base2 Protocol is utilized by all SMM drivers to locate the SMM infrastructure +/// services and determine whether the driver is being invoked inside SMRAM or outside of SMRAM. +/// +struct _EFI_SMM_BASE2_PROTOCOL { + EFI_SMM_INSIDE_OUT2 InSmm; + EFI_SMM_GET_SMST_LOCATION2 GetSmstLocation; +}; + +extern EFI_GUID gEfiSmmBase2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCommunication.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCommunication.h new file mode 100644 index 0000000..52a27ef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCommunication.h @@ -0,0 +1,33 @@ +/** @file + EFI SMM Communication Protocol as defined in the PI 1.2 specification. + + This protocol provides a means of communicating between drivers outside of SMM and SMI + handlers inside of SMM. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_COMMUNICATION_H_ +#define _SMM_COMMUNICATION_H_ + +#include + + +typedef EFI_MM_COMMUNICATE_HEADER EFI_SMM_COMMUNICATE_HEADER; + +#define EFI_SMM_COMMUNICATION_PROTOCOL_GUID EFI_MM_COMMUNICATION_PROTOCOL_GUID + +typedef EFI_MM_COMMUNICATION_PROTOCOL EFI_SMM_COMMUNICATION_PROTOCOL; + +extern EFI_GUID gEfiSmmCommunicationProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmConfiguration.h new file mode 100644 index 0000000..27a3f2d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmConfiguration.h @@ -0,0 +1,84 @@ +/** @file + EFI SMM Configuration Protocol as defined in the PI 1.2 specification. + + This protocol is used to: + 1) report the portions of SMRAM regions which cannot be used for the SMRAM heap. + 2) register the SMM Foundation entry point with the processor code. The entry + point will be invoked by the SMM processor entry code. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_CONFIGURATION_H_ +#define _SMM_CONFIGURATION_H_ + +#include +#include + +#define EFI_SMM_CONFIGURATION_PROTOCOL_GUID EFI_MM_CONFIGURATION_PROTOCOL_GUID + +/// +/// Structure describing a SMRAM region which cannot be used for the SMRAM heap. +/// +typedef struct _EFI_SMM_RESERVED_SMRAM_REGION { + /// + /// Starting address of the reserved SMRAM area, as it appears while SMRAM is open. + /// Ignored if SmramReservedSize is 0. + /// + EFI_PHYSICAL_ADDRESS SmramReservedStart; + /// + /// Number of bytes occupied by the reserved SMRAM area. A size of zero indicates the + /// last SMRAM area. + /// + UINT64 SmramReservedSize; +} EFI_SMM_RESERVED_SMRAM_REGION; + +typedef struct _EFI_SMM_CONFIGURATION_PROTOCOL EFI_SMM_CONFIGURATION_PROTOCOL; + +/** + Register the SMM Foundation entry point. + + This function registers the SMM Foundation entry point with the processor code. This entry point + will be invoked by the SMM Processor entry code. + + @param[in] This The EFI_SMM_CONFIGURATION_PROTOCOL instance. + @param[in] SmmEntryPoint SMM Foundation entry point. + + @retval EFI_SUCCESS Success to register SMM Entry Point. + @retval EFI_INVALID_PARAMETER SmmEntryPoint is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_REGISTER_SMM_ENTRY)( + IN CONST EFI_SMM_CONFIGURATION_PROTOCOL *This, + IN EFI_SMM_ENTRY_POINT SmmEntryPoint + ); + +/// +/// The EFI SMM Configuration Protocol is a mandatory protocol published by a DXE CPU driver to +/// indicate which areas within SMRAM are reserved for use by the CPU for any purpose, +/// such as stack, save state or SMM entry point. +/// +/// The RegisterSmmEntry() function allows the SMM IPL DXE driver to register the SMM +/// Foundation entry point with the SMM entry vector code. +/// +struct _EFI_SMM_CONFIGURATION_PROTOCOL { + /// + /// A pointer to an array SMRAM ranges used by the initial SMM entry code. + /// + EFI_SMM_RESERVED_SMRAM_REGION *SmramReservedRegions; + EFI_SMM_REGISTER_SMM_ENTRY RegisterSmmEntry; +}; + +extern EFI_GUID gEfiSmmConfigurationProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmControl2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmControl2.h new file mode 100644 index 0000000..f0b19ee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmControl2.h @@ -0,0 +1,41 @@ +/** @file + EFI SMM Control2 Protocol as defined in the PI 1.2 specification. + + This protocol is used initiate synchronous SMI activations. This protocol could be published by a + processor driver to abstract the SMI IPI or a driver which abstracts the ASIC that is supporting the + APM port. Because of the possibility of performing SMI IPI transactions, the ability to generate this + event from a platform chipset agent is an optional capability for both IA-32 and x64-based systems. + + The EFI_SMM_CONTROL2_PROTOCOL is produced by a runtime driver. It provides an + abstraction of the platform hardware that generates an SMI. There are often I/O ports that, when + accessed, will generate the SMI. Also, the hardware optionally supports the periodic generation of + these signals. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_CONTROL2_H_ +#define _SMM_CONTROL2_H_ + +#include + +#define EFI_SMM_CONTROL2_PROTOCOL_GUID EFI_MM_CONTROL_PROTOCOL_GUID + +typedef EFI_MM_CONTROL_PROTOCOL EFI_SMM_CONTROL2_PROTOCOL; +typedef EFI_MM_PERIOD EFI_SMM_PERIOD; + +typedef EFI_MM_ACTIVATE EFI_SMM_ACTIVATE2; + +typedef EFI_MM_DEACTIVATE EFI_SMM_DEACTIVATE2; +extern EFI_GUID gEfiSmmControl2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpu.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpu.h new file mode 100644 index 0000000..6c64c4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpu.h @@ -0,0 +1,136 @@ +/** @file + EFI SMM CPU Protocol as defined in the PI 1.2 specification. + + This protocol allows SMM drivers to access architecture-standard registers from any of the CPU + save state areas. In some cases, difference processors provide the same information in the save state, + but not in the same format. These so-called pseudo-registers provide this information in a standard + format. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_CPU_H_ +#define _SMM_CPU_H_ + +#include + +#define EFI_SMM_CPU_PROTOCOL_GUID EFI_MM_CPU_PROTOCOL_GUID + +#define EFI_SMM_SAVE_STATE_REGISTER_GDTBASE EFI_MM_SAVE_STATE_REGISTER_GDTBASE +#define EFI_SMM_SAVE_STATE_REGISTER_IDTBASE EFI_MM_SAVE_STATE_REGISTER_IDTBASE +#define EFI_SMM_SAVE_STATE_REGISTER_LDTBASE EFI_MM_SAVE_STATE_REGISTER_LDTBASE +#define EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT EFI_MM_SAVE_STATE_REGISTER_GDTLIMIT +#define EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT EFI_MM_SAVE_STATE_REGISTER_IDTLIMIT +#define EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT EFI_MM_SAVE_STATE_REGISTER_LDTLIMIT +#define EFI_SMM_SAVE_STATE_REGISTER_LDTINFO EFI_MM_SAVE_STATE_REGISTER_LDTINFO +#define EFI_SMM_SAVE_STATE_REGISTER_ES EFI_MM_SAVE_STATE_REGISTER_ES +#define EFI_SMM_SAVE_STATE_REGISTER_CS EFI_MM_SAVE_STATE_REGISTER_CS +#define EFI_SMM_SAVE_STATE_REGISTER_SS EFI_MM_SAVE_STATE_REGISTER_SS +#define EFI_SMM_SAVE_STATE_REGISTER_DS EFI_MM_SAVE_STATE_REGISTER_DS +#define EFI_SMM_SAVE_STATE_REGISTER_FS EFI_MM_SAVE_STATE_REGISTER_FS +#define EFI_SMM_SAVE_STATE_REGISTER_GS EFI_MM_SAVE_STATE_REGISTER_GS +#define EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL EFI_MM_SAVE_STATE_REGISTER_LDTR_SEL +#define EFI_SMM_SAVE_STATE_REGISTER_TR_SEL EFI_MM_SAVE_STATE_REGISTER_TR_SEL +#define EFI_SMM_SAVE_STATE_REGISTER_DR7 EFI_MM_SAVE_STATE_REGISTER_DR7 +#define EFI_SMM_SAVE_STATE_REGISTER_DR6 EFI_MM_SAVE_STATE_REGISTER_DR6 +#define EFI_SMM_SAVE_STATE_REGISTER_R8 EFI_MM_SAVE_STATE_REGISTER_R8 +#define EFI_SMM_SAVE_STATE_REGISTER_R9 EFI_MM_SAVE_STATE_REGISTER_R9 +#define EFI_SMM_SAVE_STATE_REGISTER_R10 EFI_MM_SAVE_STATE_REGISTER_R10 +#define EFI_SMM_SAVE_STATE_REGISTER_R11 EFI_MM_SAVE_STATE_REGISTER_R11 +#define EFI_SMM_SAVE_STATE_REGISTER_R12 EFI_MM_SAVE_STATE_REGISTER_R12 +#define EFI_SMM_SAVE_STATE_REGISTER_R13 EFI_MM_SAVE_STATE_REGISTER_R13 +#define EFI_SMM_SAVE_STATE_REGISTER_R14 EFI_MM_SAVE_STATE_REGISTER_R14 +#define EFI_SMM_SAVE_STATE_REGISTER_R15 EFI_MM_SAVE_STATE_REGISTER_R15 +#define EFI_SMM_SAVE_STATE_REGISTER_RAX EFI_MM_SAVE_STATE_REGISTER_RAX +#define EFI_SMM_SAVE_STATE_REGISTER_RBX EFI_MM_SAVE_STATE_REGISTER_RBX +#define EFI_SMM_SAVE_STATE_REGISTER_RCX EFI_MM_SAVE_STATE_REGISTER_RCX +#define EFI_SMM_SAVE_STATE_REGISTER_RDX EFI_MM_SAVE_STATE_REGISTER_RDX +#define EFI_SMM_SAVE_STATE_REGISTER_RSP EFI_MM_SAVE_STATE_REGISTER_RSP +#define EFI_SMM_SAVE_STATE_REGISTER_RBP EFI_MM_SAVE_STATE_REGISTER_RBP +#define EFI_SMM_SAVE_STATE_REGISTER_RSI EFI_MM_SAVE_STATE_REGISTER_RSI +#define EFI_SMM_SAVE_STATE_REGISTER_RDI EFI_MM_SAVE_STATE_REGISTER_RDI +#define EFI_SMM_SAVE_STATE_REGISTER_RIP EFI_MM_SAVE_STATE_REGISTER_RIP +#define EFI_SMM_SAVE_STATE_REGISTER_RFLAGS EFI_MM_SAVE_STATE_REGISTER_RFLAGS +#define EFI_SMM_SAVE_STATE_REGISTER_CR0 EFI_MM_SAVE_STATE_REGISTER_CR0 +#define EFI_SMM_SAVE_STATE_REGISTER_CR3 EFI_MM_SAVE_STATE_REGISTER_CR3 +#define EFI_SMM_SAVE_STATE_REGISTER_CR4 EFI_MM_SAVE_STATE_REGISTER_CR4 +#define EFI_SMM_SAVE_STATE_REGISTER_FCW EFI_MM_SAVE_STATE_REGISTER_FCW +#define EFI_SMM_SAVE_STATE_REGISTER_FSW EFI_MM_SAVE_STATE_REGISTER_FSW +#define EFI_SMM_SAVE_STATE_REGISTER_FTW EFI_MM_SAVE_STATE_REGISTER_FTW +#define EFI_SMM_SAVE_STATE_REGISTER_OPCODE EFI_MM_SAVE_STATE_REGISTER_OPCODE +#define EFI_SMM_SAVE_STATE_REGISTER_FP_EIP EFI_MM_SAVE_STATE_REGISTER_FP_EIP +#define EFI_SMM_SAVE_STATE_REGISTER_FP_CS EFI_MM_SAVE_STATE_REGISTER_FP_CS +#define EFI_SMM_SAVE_STATE_REGISTER_DATAOFFSET EFI_MM_SAVE_STATE_REGISTER_DATAOFFSET +#define EFI_SMM_SAVE_STATE_REGISTER_FP_DS EFI_MM_SAVE_STATE_REGISTER_FP_DS +#define EFI_SMM_SAVE_STATE_REGISTER_MM0 EFI_MM_SAVE_STATE_REGISTER_MM0 +#define EFI_SMM_SAVE_STATE_REGISTER_MM1 EFI_MM_SAVE_STATE_REGISTER_MM1 +#define EFI_SMM_SAVE_STATE_REGISTER_MM2 EFI_MM_SAVE_STATE_REGISTER_MM2 +#define EFI_SMM_SAVE_STATE_REGISTER_MM3 EFI_MM_SAVE_STATE_REGISTER_MM3 +#define EFI_SMM_SAVE_STATE_REGISTER_MM4 EFI_MM_SAVE_STATE_REGISTER_MM4 +#define EFI_SMM_SAVE_STATE_REGISTER_MM5 EFI_MM_SAVE_STATE_REGISTER_MM5 +#define EFI_SMM_SAVE_STATE_REGISTER_MM6 EFI_MM_SAVE_STATE_REGISTER_MM6 +#define EFI_SMM_SAVE_STATE_REGISTER_MM7 EFI_MM_SAVE_STATE_REGISTER_MM7 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM0 EFI_MM_SAVE_STATE_REGISTER_XMM0 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM1 EFI_MM_SAVE_STATE_REGISTER_XMM1 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM2 EFI_MM_SAVE_STATE_REGISTER_XMM2 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM3 EFI_MM_SAVE_STATE_REGISTER_XMM3 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM4 EFI_MM_SAVE_STATE_REGISTER_XMM4 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM5 EFI_MM_SAVE_STATE_REGISTER_XMM5 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM6 EFI_MM_SAVE_STATE_REGISTER_XMM6 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM7 EFI_MM_SAVE_STATE_REGISTER_XMM7 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM8 EFI_MM_SAVE_STATE_REGISTER_XMM8 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM9 EFI_MM_SAVE_STATE_REGISTER_XMM9 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM10 EFI_MM_SAVE_STATE_REGISTER_XMM10 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM11 EFI_MM_SAVE_STATE_REGISTER_XMM11 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM12 EFI_MM_SAVE_STATE_REGISTER_XMM12 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM13 EFI_MM_SAVE_STATE_REGISTER_XMM13 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM14 EFI_MM_SAVE_STATE_REGISTER_XMM14 +#define EFI_SMM_SAVE_STATE_REGISTER_XMM15 EFI_MM_SAVE_STATE_REGISTER_XMM15 +#define EFI_SMM_SAVE_STATE_REGISTER_IO EFI_MM_SAVE_STATE_REGISTER_IO +#define EFI_SMM_SAVE_STATE_REGISTER_LMA EFI_MM_SAVE_STATE_REGISTER_LMA +#define EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID EFI_MM_SAVE_STATE_REGISTER_PROCESSOR_ID + +typedef EFI_MM_SAVE_STATE_REGISTER EFI_SMM_SAVE_STATE_REGISTER; + + +#define EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT +#define EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT + + +/// +/// Size width of I/O instruction +/// +#define EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 EFI_MM_SAVE_STATE_IO_WIDTH_UINT8 +#define EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16 EFI_MM_SAVE_STATE_IO_WIDTH_UINT16 +#define EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32 EFI_MM_SAVE_STATE_IO_WIDTH_UINT32 +#define EFI_SMM_SAVE_STATE_IO_WIDTH_UINT64 EFI_MM_SAVE_STATE_IO_WIDTH_UINT64 +typedef EFI_MM_SAVE_STATE_IO_WIDTH EFI_SMM_SAVE_STATE_IO_WIDTH; + +/// +/// Types of I/O instruction +/// +#define EFI_SMM_SAVE_STATE_IO_TYPE_INPUT EFI_MM_SAVE_STATE_IO_TYPE_INPUT +#define EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT +#define EFI_SMM_SAVE_STATE_IO_TYPE_STRING EFI_MM_SAVE_STATE_IO_TYPE_STRING +#define EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX EFI_MM_SAVE_STATE_IO_TYPE_REP_PREFIX +typedef EFI_MM_SAVE_STATE_IO_TYPE EFI_SMM_SAVE_STATE_IO_TYPE; + +typedef EFI_MM_SAVE_STATE_IO_INFO EFI_SMM_SAVE_STATE_IO_INFO; + +typedef EFI_MM_CPU_PROTOCOL EFI_SMM_CPU_PROTOCOL; + +typedef EFI_MM_READ_SAVE_STATE EFI_SMM_READ_SAVE_STATE; + +typedef EFI_MM_WRITE_SAVE_STATE EFI_SMM_WRITE_SAVE_STATE; +extern EFI_GUID gEfiSmmCpuProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpuIo2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpuIo2.h new file mode 100644 index 0000000..cc4fa91 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmCpuIo2.h @@ -0,0 +1,41 @@ +/** @file + SMM CPU I/O 2 protocol as defined in the PI 1.2 specification. + + This protocol provides CPU I/O and memory access within SMM. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_CPU_IO2_H_ +#define _SMM_CPU_IO2_H_ + +#include + +#define EFI_SMM_CPU_IO2_PROTOCOL_GUID EFI_MM_CPU_IO_PROTOCOL_GUID + +typedef EFI_MM_CPU_IO_PROTOCOL EFI_SMM_CPU_IO2_PROTOCOL; + +/// +/// Width of the SMM CPU I/O operations +/// +#define SMM_IO_UINT8 MM_IO_UINT8 +#define SMM_IO_UINT16 MM_IO_UINT16 +#define SMM_IO_UINT32 MM_IO_UINT32 +#define SMM_IO_UINT64 MM_IO_UINT64 + +typedef EFI_MM_IO_WIDTH EFI_SMM_IO_WIDTH; +typedef EFI_MM_CPU_IO EFI_SMM_CPU_IO2; + +typedef EFI_MM_IO_ACCESS EFI_SMM_IO_ACCESS2; + +extern EFI_GUID gEfiSmmCpuIo2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmEndOfDxe.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmEndOfDxe.h new file mode 100644 index 0000000..9e29ebd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmEndOfDxe.h @@ -0,0 +1,32 @@ +/** @file + SMM End Of Dxe protocol introduced in the PI 1.2.1 specification. + + According to PI 1.4a specification, this protocol indicates end of the + execution phase when all of the components are under the authority of + the platform manufacturer. + This protocol is a mandatory protocol published by SMM Foundation code. + This protocol is an SMM counterpart of the End of DXE Event. + This protocol prorogates End of DXE notification into SMM environment. + This protocol is installed prior to installation of the SMM Ready to Lock Protocol. + + Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_END_OF_DXE_H_ +#define _SMM_END_OF_DXE_H_ + +#include + +#define EFI_SMM_END_OF_DXE_PROTOCOL_GUID EFI_MM_END_OF_DXE_PROTOCOL_GUID + +extern EFI_GUID gEfiSmmEndOfDxeProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmGpiDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmGpiDispatch2.h new file mode 100644 index 0000000..111c36b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmGpiDispatch2.h @@ -0,0 +1,49 @@ +/** @file + SMM General Purpose Input (GPI) Dispatch2 Protocol as defined in PI 1.1 Specification + Volume 4 System Management Mode Core Interface. + + This protocol provides the parent dispatch service for the General Purpose Input + (GPI) SMI source generator. + + The EFI_SMM_GPI_DISPATCH2_PROTOCOL provides the ability to install child handlers for the + given event types. Several inputs can be enabled. This purpose of this interface is to generate an + SMI in response to any of these inputs having a true value provided. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.1. + +**/ + +#ifndef _SMM_GPI_DISPATCH2_H_ +#define _SMM_GPI_DISPATCH2_H_ + +#include +#include + +#define EFI_SMM_GPI_DISPATCH2_PROTOCOL_GUID EFI_MM_GPI_DISPATCH_PROTOCOL_GUID +/// +/// The dispatch function's context. +/// +typedef EFI_MM_GPI_REGISTER_CONTEXT EFI_SMM_GPI_REGISTER_CONTEXT; + +typedef EFI_MM_GPI_REGISTER EFI_SMM_GPI_REGISTER2; + +typedef EFI_MM_GPI_UNREGISTER EFI_SMM_GPI_UNREGISTER2; + +typedef EFI_MM_GPI_DISPATCH_PROTOCOL EFI_SMM_GPI_DISPATCH2_PROTOCOL; + + + +extern EFI_GUID gEfiSmmGpiDispatch2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmIoTrapDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmIoTrapDispatch2.h new file mode 100644 index 0000000..8fe2b33 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmIoTrapDispatch2.h @@ -0,0 +1,53 @@ +/** @file + SMM IO Trap Dispatch2 Protocol as defined in PI 1.1 Specification + Volume 4 System Management Mode Core Interface. + + This protocol provides a parent dispatch service for IO trap SMI sources. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.1. + +**/ + +#ifndef _SMM_IO_TRAP_DISPATCH2_H_ +#define _SMM_IO_TRAP_DISPATCH2_H_ + +#include + +#define EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL_GUID EFI_MM_IO_TRAP_DISPATCH_PROTOCOL_GUID + +/// +/// IO Trap valid types +/// +typedef EFI_MM_IO_TRAP_DISPATCH_TYPE EFI_SMM_IO_TRAP_DISPATCH_TYPE; + +/// +/// IO Trap context structure containing information about the +/// IO trap event that should invoke the handler +/// +typedef EFI_MM_IO_TRAP_REGISTER_CONTEXT EFI_SMM_IO_TRAP_REGISTER_CONTEXT; + +/// +/// IO Trap context structure containing information about the IO trap that occurred +/// +typedef EFI_MM_IO_TRAP_CONTEXT EFI_SMM_IO_TRAP_CONTEXT; + +typedef EFI_MM_IO_TRAP_DISPATCH_PROTOCOL EFI_SMM_IO_TRAP_DISPATCH2_PROTOCOL; + +typedef EFI_MM_IO_TRAP_DISPATCH_REGISTER EFI_SMM_IO_TRAP_DISPATCH2_REGISTER; + +typedef EFI_MM_IO_TRAP_DISPATCH_UNREGISTER EFI_SMM_IO_TRAP_DISPATCH2_UNREGISTER; + +extern EFI_GUID gEfiSmmIoTrapDispatch2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPciRootBridgeIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPciRootBridgeIo.h new file mode 100644 index 0000000..0f81f01 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPciRootBridgeIo.h @@ -0,0 +1,34 @@ +/** @file + SMM PCI Root Bridge IO protocol as defined in the PI 1.2 specification. + + This protocol provides PCI I/O and memory access within SMM. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_PCI_ROOT_BRIDGE_IO_H_ +#define _SMM_PCI_ROOT_BRIDGE_IO_H_ + +#include + +#define EFI_SMM_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID EFI_MM_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID + +/// +/// This protocol provides the same functionality as the PCI Root Bridge I/O Protocol defined in the +/// UEFI 2.1 Specifcation, section 13.2, except that the functions for Map() and Unmap() may return +/// EFI_UNSUPPORTED. +/// +typedef EFI_MM_PCI_ROOT_BRIDGE_IO_PROTOCOL EFI_SMM_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +extern EFI_GUID gEfiSmmPciRootBridgeIoProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch2.h new file mode 100644 index 0000000..6bcd0f6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch2.h @@ -0,0 +1,162 @@ +/** @file + SMM Periodic Timer Dispatch Protocol as defined in PI 1.1 Specification + Volume 4 System Management Mode Core Interface. + + This protocol provides the parent dispatch service for the periodical timer SMI source generator. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.1. + +**/ + +#ifndef _SMM_PERIODIC_TIMER_DISPATCH2_H_ +#define _SMM_PERIODIC_TIMER_DISPATCH2_H_ + +#include +#include + +#define EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL_GUID EFI_MM_PERIODIC_TIMER_DISPATCH_PROTOCOL_GUID + +/// +/// Example: A chipset supports periodic SMIs on every 64ms or 2 seconds. +/// A child wishes schedule a period SMI to fire on a period of 3 seconds, there +/// are several ways to approach the problem: +/// 1. The child may accept a 4 second periodic rate, in which case it registers with +/// Period = 40000 +/// SmiTickInterval = 20000 +/// The resulting SMI will occur every 2 seconds with the child called back on +/// every 2nd SMI. +/// NOTE: the same result would occur if the child set SmiTickInterval = 0. +/// 2. The child may choose the finer granularity SMI (64ms): +/// Period = 30000 +/// SmiTickInterval = 640 +/// The resulting SMI will occur every 64ms with the child called back on +/// every 47th SMI. +/// NOTE: the child driver should be aware that this will result in more +/// SMIs occuring during system runtime which can negatively impact system +/// performance. +/// +typedef struct { + /// + /// The minimum period of time in 100 nanosecond units that the child gets called. The + /// child will be called back after a time greater than the time Period. + /// + UINT64 Period; + /// + /// The period of time interval between SMIs. Children of this interface should use this + /// field when registering for periodic timer intervals when a finer granularity periodic + /// SMI is desired. + /// + UINT64 SmiTickInterval; +} EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT; + +/// +/// The DispatchFunction will be called with Context set to the same value as was passed into +/// Register() in RegisterContext and with CommBuffer pointing to an instance of +/// EFI_SMM_PERIODIC_TIMER_CONTEXT and CommBufferSize pointing to its size. +/// +typedef EFI_MM_PERIODIC_TIMER_CONTEXT EFI_SMM_PERIODIC_TIMER_CONTEXT; + +typedef struct _EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL; + +/** + Register a child SMI source dispatch function for SMM periodic timer. + + This service registers a function (DispatchFunction) which will be called when at least the + amount of time specified by RegisterContext has elapsed. On return, DispatchHandle + contains a unique handle which may be used later to unregister the function using UnRegister(). + The DispatchFunction will be called with Context set to the same value as was passed into + this function in RegisterContext and with CommBuffer pointing to an instance of + EFI_SMM_PERIODIC_TIMER_CONTEXT and CommBufferSize pointing to its size. + + @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when at least the specified amount + of time has elapsed. + @param[in] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the period at which the dispatch function + should be invoked. + @param[out] DispatchHandle Handle generated by the dispatcher to track the function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The period input value + is not within valid range. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this child. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_PERIODIC_TIMER_REGISTER2)( + IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This, + IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction, + IN CONST EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregisters a periodic timer service. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called when the time has elapsed. + + @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance. + @param[in] DispatchHandle Handle of the service to remove. + + @retval EFI_SUCCESS The service has been successfully removed. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_PERIODIC_TIMER_UNREGISTER2)( + IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +/** + Returns the next SMI tick period supported by the chipset. + + The order returned is from longest to shortest interval period. + + @param[in] This Pointer to the EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL instance. + @param[in,out] SmiTickInterval Pointer to pointer of next shorter SMI interval + period supported by the child. This parameter works as a get-first, + get-next field.The first time this function is called, *SmiTickInterval + should be set to NULL to get the longest SMI interval.The returned + *SmiTickInterval should be passed in on subsequent calls to get the + next shorter interval period until *SmiTickInterval = NULL. + + @retval EFI_SUCCESS The service returned successfully. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_PERIODIC_TIMER_INTERVAL2)( + IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This, + IN OUT UINT64 **SmiTickInterval + ); + +/// +/// Interface structure for the SMM Periodic Timer Dispatch Protocol +/// +/// This protocol provides the parent dispatch service for the periodical timer SMI source generator. +/// +struct _EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL { + EFI_SMM_PERIODIC_TIMER_REGISTER2 Register; + EFI_SMM_PERIODIC_TIMER_UNREGISTER2 UnRegister; + EFI_SMM_PERIODIC_TIMER_INTERVAL2 GetNextShorterInterval; +}; + +extern EFI_GUID gEfiSmmPeriodicTimerDispatch2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPowerButtonDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPowerButtonDispatch2.h new file mode 100644 index 0000000..a21a523 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmPowerButtonDispatch2.h @@ -0,0 +1,42 @@ +/** @file + SMM Power Button Dispatch2 Protocol as defined in PI 1.1 Specification + Volume 4 System Management Mode Core Interface. + + This protocol provides the parent dispatch service for the power button SMI source generator. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.1. + +**/ + +#ifndef _SMM_POWER_BUTTON_DISPATCH2_H_ +#define _SMM_POWER_BUTTON_DISPATCH2_H_ + +#include + +#define EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL_GUID EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL_GUID + +/// +/// The dispatch function's context. +/// +typedef EFI_MM_POWER_BUTTON_REGISTER_CONTEXT EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT; + +typedef EFI_MM_POWER_BUTTON_DISPATCH_PROTOCOL EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL; + +typedef EFI_MM_POWER_BUTTON_REGISTER EFI_SMM_POWER_BUTTON_REGISTER2; + +typedef EFI_MM_POWER_BUTTON_UNREGISTER EFI_SMM_POWER_BUTTON_UNREGISTER2; + +extern EFI_GUID gEfiSmmPowerButtonDispatch2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReadyToLock.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReadyToLock.h new file mode 100644 index 0000000..9c73a94 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReadyToLock.h @@ -0,0 +1,34 @@ +/** @file + SMM Ready To Lock protocol introduced in the PI 1.2 specification. + + According to PI 1.4a specification, this SMM protocol indicates that + SMM resources and services that should not be used by the third party + code are about to be locked. + This protocol is a mandatory protocol published by the SMM Foundation + code when the system is preparing to lock certain resources and interfaces + in anticipation of the invocation of 3rd party extensible modules. + This protocol is an SMM counterpart of the DXE SMM Ready to Lock Protocol. + This protocol prorogates resource locking notification into SMM environment. + This protocol is installed after installation of the SMM End of DXE Protocol. + + Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_READY_TO_LOCK_H_ +#define _SMM_READY_TO_LOCK_H_ + +#include + +#define EFI_SMM_READY_TO_LOCK_PROTOCOL_GUID EFI_MM_READY_TO_LOCK_PROTOCOL_GUID + +extern EFI_GUID gEfiSmmReadyToLockProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReportStatusCodeHandler.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReportStatusCodeHandler.h new file mode 100644 index 0000000..64ed4bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmReportStatusCodeHandler.h @@ -0,0 +1,35 @@ +/** @file + This protocol provides registering and unregistering services to status code consumers while in DXE SMM. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in PI Specification 1.1. + +**/ + +#ifndef __SMM_REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ +#define __SMM_REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ + +#include + +#define EFI_SMM_RSC_HANDLER_PROTOCOL_GUID EFI_MM_RSC_HANDLER_PROTOCOL_GUID + +typedef EFI_MM_RSC_HANDLER_CALLBACK EFI_SMM_RSC_HANDLER_CALLBACK; + +typedef EFI_MM_RSC_HANDLER_REGISTER EFI_SMM_RSC_HANDLER_REGISTER; + +typedef EFI_MM_RSC_HANDLER_UNREGISTER EFI_SMM_RSC_HANDLER_UNREGISTER; + +typedef EFI_MM_RSC_HANDLER_PROTOCOL EFI_SMM_RSC_HANDLER_PROTOCOL; + +extern EFI_GUID gEfiSmmRscHandlerProtocolGuid; + +#endif // __SMM_REPORT_STATUS_CODE_HANDLER_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStandbyButtonDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStandbyButtonDispatch2.h new file mode 100644 index 0000000..259bac8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStandbyButtonDispatch2.h @@ -0,0 +1,42 @@ +/** @file + SMM Standby Button Dispatch2 Protocol as defined in PI 1.1 Specification + Volume 4 System Management Mode Core Interface. + + This protocol provides the parent dispatch service for the standby button SMI source generator. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.1. + +**/ + +#ifndef _SMM_STANDBY_BUTTON_DISPATCH2_H_ +#define _SMM_STANDBY_BUTTON_DISPATCH2_H_ + +#include + +#define EFI_SMM_STANDBY_BUTTON_DISPATCH2_PROTOCOL_GUID EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL_GUID + +/// +/// The dispatch function's context. +/// +typedef EFI_MM_STANDBY_BUTTON_REGISTER_CONTEXT EFI_SMM_STANDBY_BUTTON_REGISTER_CONTEXT; + +typedef EFI_MM_STANDBY_BUTTON_DISPATCH_PROTOCOL EFI_SMM_STANDBY_BUTTON_DISPATCH2_PROTOCOL; + +typedef EFI_MM_STANDBY_BUTTON_REGISTER EFI_SMM_STANDBY_BUTTON_REGISTER2; + +typedef EFI_MM_STANDBY_BUTTON_UNREGISTER EFI_SMM_STANDBY_BUTTON_UNREGISTER2; + +extern EFI_GUID gEfiSmmStandbyButtonDispatch2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStatusCode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStatusCode.h new file mode 100644 index 0000000..4d6a5b8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmStatusCode.h @@ -0,0 +1,31 @@ +/** @file + EFI SMM Status Code Protocol as defined in the PI 1.2 specification. + + This protocol provides the basic status code services while in SMM. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_STATUS_CODE_H__ +#define _SMM_STATUS_CODE_H__ + +#include + +#define EFI_SMM_STATUS_CODE_PROTOCOL_GUID EFI_MM_STATUS_CODE_PROTOCOL_GUID + +typedef EFI_MM_STATUS_CODE_PROTOCOL EFI_SMM_STATUS_CODE_PROTOCOL; + +typedef EFI_MM_REPORT_STATUS_CODE EFI_SMM_REPORT_STATUS_CODE; + +extern EFI_GUID gEfiSmmStatusCodeProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSwDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSwDispatch2.h new file mode 100644 index 0000000..c4829ba --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSwDispatch2.h @@ -0,0 +1,134 @@ +/** @file + SMM Software Dispatch Protocol introduced from PI 1.2 Specification + Volume 4 System Management Mode Core Interface. + + This protocol provides the parent dispatch service for a given SMI source generator. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_SW_DISPATCH2_H_ +#define _SMM_SW_DISPATCH2_H_ + +#include +#include + +#define EFI_SMM_SW_DISPATCH2_PROTOCOL_GUID EFI_MM_SW_DISPATCH_PROTOCOL_GUID + +/// +/// A particular chipset may not support all possible software SMI input values. +/// For example, the ICH supports only values 00h to 0FFh. The parent only allows a single +/// child registration for each SwSmiInputValue. +/// +typedef struct { + UINTN SwSmiInputValue; +} EFI_SMM_SW_REGISTER_CONTEXT; + +/// +/// The DispatchFunction will be called with Context set to the same value as was passed into +/// this function in RegisterContext and with CommBuffer (and CommBufferSize) pointing +/// to an instance of EFI_SMM_SW_CONTEXT indicating the index of the CPU which generated the +/// software SMI. +/// +typedef struct { + /// + /// The 0-based index of the CPU which generated the software SMI. + /// + UINTN SwSmiCpuIndex; + /// + /// This value corresponds directly to the CommandPort parameter used in the call to Trigger(). + /// + UINT8 CommandPort; + /// + /// This value corresponds directly to the DataPort parameter used in the call to Trigger(). + /// + UINT8 DataPort; +} EFI_SMM_SW_CONTEXT; + +typedef struct _EFI_SMM_SW_DISPATCH2_PROTOCOL EFI_SMM_SW_DISPATCH2_PROTOCOL; + +/** + Register a child SMI source dispatch function for the specified software SMI. + + This service registers a function (DispatchFunction) which will be called when the software + SMI source specified by RegisterContext->SwSmiCpuIndex is detected. On return, + DispatchHandle contains a unique handle which may be used later to unregister the function + using UnRegister(). + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchFunction Function to register for handler when the specified software + SMI is generated. + @param[in, out] RegisterContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Software SMI input value the + dispatch function should be invoked for. + @param[out] DispatchHandle Handle generated by the dispatcher to track the + function instance. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source. + @retval EFI_INVALID_PARAMETER RegisterContext is invalid. The SW SMI input value + is not within a valid range or is already in use. + @retval EFI_OUT_OF_RESOURCES There is not enough memory (system or SMM) to manage this + child. + @retval EFI_OUT_OF_RESOURCES A unique software SMI value could not be assigned + for this dispatch. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_SW_REGISTER2)( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction, + IN OUT EFI_SMM_SW_REGISTER_CONTEXT *RegisterContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function for the specified software SMI. + + This service removes the handler associated with DispatchHandle so that it will no longer be + called in response to a software SMI. + + @param[in] This Pointer to the EFI_SMM_SW_DISPATCH2_PROTOCOL instance. + @param[in] DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered. + @retval EFI_INVALID_PARAMETER The DispatchHandle was not valid. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_SW_UNREGISTER2)( + IN CONST EFI_SMM_SW_DISPATCH2_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle +); + +/// +/// Interface structure for the SMM Software SMI Dispatch Protocol. +/// +/// The EFI_SMM_SW_DISPATCH2_PROTOCOL provides the ability to install child handlers for the +/// given software. These handlers will respond to software interrupts, and the maximum software +/// interrupt in the EFI_SMM_SW_REGISTER_CONTEXT is denoted by MaximumSwiValue. +/// +struct _EFI_SMM_SW_DISPATCH2_PROTOCOL { + EFI_SMM_SW_REGISTER2 Register; + EFI_SMM_SW_UNREGISTER2 UnRegister; + /// + /// A read-only field that describes the maximum value that can be used in the + /// EFI_SMM_SW_DISPATCH2_PROTOCOL.Register() service. + /// + UINTN MaximumSwiValue; +}; + +extern EFI_GUID gEfiSmmSwDispatch2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSxDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSxDispatch2.h new file mode 100644 index 0000000..ed8fb9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmSxDispatch2.h @@ -0,0 +1,38 @@ +/** @file + SMM Sx Dispatch Protocol as defined in PI 1.2 Specification + Volume 4 System Management Mode Core Interface. + + Provides the parent dispatch service for a given Sx-state source generator. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_SX_DISPATCH2_H_ +#define _SMM_SX_DISPATCH2_H_ + +#include + +#define EFI_SMM_SX_DISPATCH2_PROTOCOL_GUID EFI_MM_SX_DISPATCH_PROTOCOL_GUID + +/// +/// The dispatch function's context +/// +typedef EFI_MM_SX_REGISTER_CONTEXT EFI_SMM_SX_REGISTER_CONTEXT; + +typedef EFI_MM_SX_DISPATCH_PROTOCOL EFI_SMM_SX_DISPATCH2_PROTOCOL; + +typedef EFI_MM_SX_REGISTER EFI_SMM_SX_REGISTER2; + +typedef EFI_MM_SX_UNREGISTER EFI_SMM_SX_UNREGISTER2; + +extern EFI_GUID gEfiSmmSxDispatch2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmUsbDispatch2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmUsbDispatch2.h new file mode 100644 index 0000000..e3690f4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SmmUsbDispatch2.h @@ -0,0 +1,47 @@ +/** @file + SMM USB Dispatch2 Protocol as defined in PI 1.1 Specification + Volume 4 System Management Mode Core Interface. + + Provides the parent dispatch service for the USB SMI source generator. + + Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.1. + +**/ + +#ifndef _SMM_USB_DISPATCH2_H_ +#define _SMM_USB_DISPATCH2_H_ + +#include + +#define EFI_SMM_USB_DISPATCH2_PROTOCOL_GUID EFI_MM_USB_DISPATCH_PROTOCOL_GUID + +/// +/// USB SMI event types +/// +typedef EFI_USB_MMI_TYPE EFI_USB_SMI_TYPE; + +/// +/// The dispatch function's context. +/// +typedef EFI_MM_USB_REGISTER_CONTEXT EFI_SMM_USB_REGISTER_CONTEXT; + +typedef EFI_MM_USB_DISPATCH_PROTOCOL EFI_SMM_USB_DISPATCH2_PROTOCOL; + +typedef EFI_MM_USB_REGISTER EFI_SMM_USB_REGISTER2; + +typedef EFI_MM_USB_UNREGISTER EFI_SMM_USB_UNREGISTER2; + +extern EFI_GUID gEfiSmmUsbDispatch2ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiConfiguration.h new file mode 100644 index 0000000..4c5c8a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiConfiguration.h @@ -0,0 +1,293 @@ +/** @file + This file defines the SPI Configuration Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_CONFIGURATION_PROTOCOL_H__ +#define __SPI_CONFIGURATION_PROTOCOL_H__ + +/// +/// Global ID for the SPI Configuration Protocol +/// +#define EFI_SPI_CONFIGURATION_GUID \ + { 0x85a6d3e6, 0xb65b, 0x4afc, \ + { 0xb3, 0x8f, 0xc6, 0xd5, 0x4a, 0xf6, 0xdd, 0xc8 }} + +/// +/// Macros to easily specify frequencies in hertz, kilohertz and megahertz. +/// +#define Hz(Frequency) (Frequency) +#define KHz(Frequency) (1000 * Hz (Frequency)) +#define MHz(Frequency) (1000 * KHz (Frequency)) + +typedef struct _EFI_SPI_PERIPHERAL EFI_SPI_PERIPHERAL; + +/** + Manipulate the chip select for a SPI device. + + This routine must be called at or below TPL_NOTIFY. + Update the value of the chip select line for a SPI peripheral. + The SPI bus layer calls this routine either in the board layer or in the SPI + controller to manipulate the chip select pin at the start and end of a SPI + transaction. + + @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data structure + describing the SPI peripheral whose chip select pin + is to be manipulated. The routine may access the + ChipSelectParameter field to gain sufficient + context to complete the operation. + @param[in] PinValue The value to be applied to the chip select line of + the SPI peripheral. + + @retval EFI_SUCCESS The chip select was set successfully + @retval EFI_NOT_READY Support for the chip select is not properly + initialized + @retval EFI_INVALID_PARAMETER The SpiPeripheral->ChipSelectParameter value + is invalid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_CHIP_SELECT) ( + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral, + IN BOOLEAN PinValue + ); + +/** + Set up the clock generator to produce the correct clock frequency, phase and + polarity for a SPI chip. + + This routine must be called at or below TPL_NOTIFY. + This routine updates the clock generator to generate the correct frequency + and polarity for the SPI clock. + + @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure from + which the routine can access the ClockParameter, + ClockPhase and ClockPolarity fields. The routine + also has access to the names for the SPI bus and + chip which can be used during debugging. + @param[in] ClockHz Pointer to the requested clock frequency. The clock + generator will choose a supported clock frequency + which is less then or equal to this value. + Specify zero to turn the clock generator off. + The actual clock frequency supported by the clock + generator will be returned. + + @retval EFI_SUCCESS The clock was set up successfully + @retval EFI_UNSUPPORTED The SPI controller was not able to support the + frequency requested by CLockHz + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_SPI_CLOCK) ( + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral, + IN UINT32 *ClockHz + ); + +/// +/// The EFI_SPI_PART data structure provides a description of a SPI part which +/// is independent of the use on the board. This data is available directly +/// from the part's datasheet and may be provided by the vendor. +/// +typedef struct _EFI_SPI_PART { + /// + /// A Unicode string specifying the SPI chip vendor. + /// + CONST CHAR16 *Vendor; + + /// + /// A Unicode string specifying the SPI chip part number. + /// + CONST CHAR16 *PartNumber; + + /// + /// The minimum SPI bus clock frequency used to access this chip. This value + /// may be specified in the chip's datasheet. If not, use the value of zero. + /// + UINT32 MinClockHz; + + /// + /// The maximum SPI bus clock frequency used to access this chip. This value + /// is found in the chip's datasheet. + /// + UINT32 MaxClockHz; + + /// + /// Specify the polarity of the chip select pin. This value can be found in + /// the SPI chip's datasheet. Specify TRUE when a one asserts the chip select + ///and FALSE when a zero asserts the chip select. + /// + BOOLEAN ChipSelectPolarity; +} EFI_SPI_PART; + +/// +/// The EFI_SPI_BUS data structure provides the connection details between the +/// physical SPI bus and the EFI_SPI_HC_PROTOCOL instance which controls that +/// SPI bus. This data structure also describes the details of how the clock is +/// generated for that SPI bus. Finally this data structure provides the list +/// of physical SPI devices which are attached to the SPI bus. +/// +typedef struct _EFI_SPI_BUS { + /// + /// A Unicode string describing the SPI bus + /// + CONST CHAR16 *FriendlyName; + + /// + /// Address of the first EFI_SPI_PERIPHERAL data structure connected to this + /// bus. Specify NULL if there are no SPI peripherals connected to this bus. + /// + CONST EFI_SPI_PERIPHERAL *Peripherallist; + + /// + /// Address of an EFI_DEVICE_PATH_PROTOCOL data structure which uniquely + /// describes the SPI controller. + /// + CONST EFI_DEVICE_PATH_PROTOCOL *ControllerPath; + + /// + /// Address of the routine which controls the clock used by the SPI bus for + /// this SPI peripheral. The SPI host co ntroller's clock routine is called + /// when this value is set to NULL. + /// + EFI_SPI_CLOCK Clock; + + /// + /// Address of a data structure containing the additional values which + /// describe the necessary control for the clock. When Clock is NULL, + /// the declaration for this data structure is provided by the vendor of the + /// host's SPI controller driver. When Clock is not NULL, the declaration for + /// this data structure is provided by the board layer. + /// + VOID *ClockParameter; +} EFI_SPI_BUS; + +/// +/// The EFI_SPI_PERIPHERAL data structure describes how a specific block of +/// logic which is connected to the SPI bus. This data structure also selects +/// which upper level driver is used to manipulate this SPI device. +/// The SpiPeripheraLDriverGuid is available from the vendor of the SPI +/// peripheral driver. +/// +struct _EFI_SPI_PERIPHERAL { + /// + /// Address of the next EFI_SPI_PERIPHERAL data structure. Specify NULL if + /// the current data structure is the last one on the SPI bus. + /// + CONST EFI_SPI_PERIPHERAL *NextSpiPeripheral; + + /// + /// A unicode string describing the function of the SPI part. + /// + CONST CHAR16 *FriendlyName; + + /// + /// Address of a GUID provided by the vendor of the SPI peripheral driver. + /// Instead of using a " EFI_SPI_IO_PROTOCOL" GUID, the SPI bus driver uses + /// this GUID to identify an EFI_SPI_IO_PROTOCOL data structure and to + /// provide the connection points for the SPI peripheral drivers. + /// This reduces the comparison logic in the SPI peripheral driver's + /// Supported routine. + /// + CONST GUID *SpiPeripheralDriverGuid; + + /// + /// The address of an EFI_SPI_PART data structure which describes this chip. + /// + CONST EFI_SPI_PART *SpiPart; + + /// + /// The maximum clock frequency is specified in the EFI_SPI_P ART. When this + /// this value is non-zero and less than the value in the EFI_SPI_PART then + /// this value is used for the maximum clock frequency for the SPI part. + /// + UINT32 MaxClockHz; + + /// + /// Specify the idle value of the clock as found in the datasheet. + /// Use zero (0) if the clock'S idle value is low or one (1) if the the + /// clock's idle value is high. + /// + BOOLEAN ClockPolarity; + + /// + /// Specify the clock delay after chip select. Specify zero (0) to delay an + /// entire clock cycle or one (1) to delay only half a clock cycle. + /// + BOOLEAN ClockPhase; + + /// + /// SPI peripheral attributes, select zero or more of: + /// * SPI_PART_SUPPORTS_2_B1T_DATA_BUS_W1DTH - The SPI peripheral is wired to + /// support a 2-bit data bus + /// * SPI_PART_SUPPORTS_4_B1T_DATA_BUS_W1DTH - The SPI peripheral is wired to + /// support a 4-bit data bus + /// + UINT32 Attributes; + + /// + /// Address of a vendor specific data structure containing additional board + /// configuration details related to the SPI chip. The SPI peripheral layer + /// uses this data structure when configuring the chip. + /// + CONST VOID *ConfigurationData; + + /// + /// The address of an EFI_SPI_BUS data structure which describes the SPI bus + /// to which this chip is connected. + /// + CONST EFI_SPI_BUS *SpiBus; + + /// + /// Address of the routine which controls the chip select pin for this SPI + /// peripheral. Call the SPI host controller's chip select routine when this + /// value is set to NULL. + /// + EFI_SPI_CHIP_SELECT ChipSelect; + + /// + /// Address of a data structure containing the additional values which + /// describe the necessary control for the chip select. When ChipSelect is + /// NULL, the declaration for this data structure is provided by the vendor + /// of the host's SPI controller driver. The vendor's documentation specifies + /// the necessary values to use for the chip select pin selection and + /// control. When Chipselect is not NULL, the declaration for this data + /// structure is provided by the board layer. + /// + VOID *ChipSelectParameter; +}; + +/// +/// Describe the details of the board's SPI busses to the SPI driver stack. +/// The board layer uses the EFI_SPI_CONFIGURATION_PROTOCOL to expose the data +/// tables which describe the board's SPI busses, The SPI bus layer uses these +/// tables to configure the clock, chip select and manage the SPI transactions +/// on the SPI controllers. +/// +typedef struct _EFI_SPI_CONFIGURATION_PROTOCOL { + /// + /// The number of SPI busses on the board. + /// + UINT32 BusCount; + + /// + /// The address of an array of EFI_SPI_BUS data structure addresses. + /// + CONST EFI_SPI_BUS *CONST *CONST Buslist; +} EFI_SPI_CONFIGURATION_PROTOCOL; + +extern EFI_GUID gEfiSpiConfigurationProtocolGuid; + +#endif // __SPI_CONFIGURATION_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiHc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiHc.h new file mode 100644 index 0000000..13ad5f4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiHc.h @@ -0,0 +1,194 @@ +/** @file + This file defines the SPI Host Controller Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_HC_PROTOCOL_H__ +#define __SPI_HC_PROTOCOL_H__ + +#include +#include + +/// +/// Global ID for the SPI Host Controller Protocol +/// +#define EFI_SPI_HOST_GUID \ + { 0xc74e5db2, 0xfa96, 0x4ae2, \ + { 0xb3, 0x99, 0x15, 0x97, 0x7f, 0xe3, 0x0, 0x2d }} + +/// +/// EDK2-style name +/// +#define EFI_SPI_HC_PROTOCOL_GUID EFI_SPI_HOST_GUID + +typedef struct _EFI_SPI_HC_PROTOCOL EFI_SPI_HC_PROTOCOL; + +/** + Assert or deassert the SPI chip select. + + This routine is called at TPL_NOTIFY. + Update the value of the chip select line for a SPI peripheral. The SPI bus + layer calls this routine either in the board layer or in the SPI controller + to manipulate the chip select pin at the start and end of a SPI transaction. + + @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure. + @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data structure + describing the SPI peripheral whose chip select pin + is to be manipulated. The routine may access the + ChipSelectParameter field to gain sufficient + context to complete the operati on. + @param[in] PinValue The value to be applied to the chip select line of + the SPI peripheral. + + @retval EFI_SUCCESS The chip select was set as requested + @retval EFI_NOT_READY Support for the chip select is not properly + initialized + @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents are + invalid + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_SPI_HC_PROTOCOL_CHIP_SELECT) ( + IN CONST EFI_SPI_HC_PROTOCOL *This, + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral, + IN BOOLEAN PinValue + ); + +/** + Set up the clock generator to produce the correct clock frequency, phase and + polarity for a SPI chip. + + This routine is called at TPL_NOTIFY. + This routine updates the clock generator to generate the correct frequency + and polarity for the SPI clock. + + @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure. + @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure from + which the routine can access the ClockParameter, + ClockPhase and ClockPolarity fields. The routine + also has access to the names for the SPI bus and + chip which can be used during debugging. + @param[in] ClockHz Pointer to the requested clock frequency. The SPI + host controller will choose a supported clock + frequency which is less then or equal to this + value. Specify zero to turn the clock generator + off. The actual clock frequency supported by the + SPI host controller will be returned. + + @retval EFI_SUCCESS The clock was set up successfully + @retval EFI_UNSUPPORTED The SPI controller was not able to support the + frequency requested by ClockHz + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_SPI_HC_PROTOCOL_CLOCK) ( + IN CONST EFI_SPI_HC_PROTOCOL *This, + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral, + IN UINT32 *ClockHz + ); + +/** + Perform the SPI transaction on the SPI peripheral using the SPI host + controller. + + This routine is called at TPL_NOTIFY. + This routine synchronously returns EFI_SUCCESS indicating that the + asynchronous SPI transaction was started. The routine then waits for + completion of the SPI transaction prior to returning the final transaction + status. + + @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure. + @param[in] BusTransaction Pointer to a EFI_SPI_BUS_ TRANSACTION containing + the description of the SPI transaction to perform. + + @retval EFI_SUCCESS The transaction completed successfully + @retval EFI_BAD_BUFFER_SIZE The BusTransaction->WriteBytes value is invalid, + or the BusTransaction->ReadinBytes value is + invalid + @retval EFI_UNSUPPORTED The BusTransaction-> Transaction Type is + unsupported + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_SPI_HC_PROTOCOL_TRANSACTION) ( + IN CONST EFI_SPI_HC_PROTOCOL *This, + IN EFI_SPI_BUS_TRANSACTION *BusTransaction + ); + +/// +/// Support a SPI data transaction between the SPI controller and a SPI chip. +/// +struct _EFI_SPI_HC_PROTOCOL { + /// + /// Host control attributes, may have zero or more of the following set: + /// * HC_SUPPORTS_WRITE_ONLY_OPERATIONS + /// * HC_SUPPORTS_READ_ONLY_OPERATIONS + /// * HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS + /// * HC_TX_FRAME_IN_MOST_SIGNIFICANT_BITS + /// - The SPI host controller requires the transmit frame to be in most + /// significant bits instead of least significant bits.The host driver + /// will adjust the frames if necessary. + /// * HC_RX_FRAME_IN_MOST_SIGNIFICANT_BITS + /// - The SPI host controller places the receive frame to be in most + /// significant bits instead of least significant bits.The host driver + /// will adjust the frames to be in the least significant bits if + /// necessary. + /// * HC_SUPPORTS_2_BIT_DATA_BUS_W1DTH + /// - The SPI controller supports a 2 - bit data bus + /// * HC_SUPPORTS_4_B1T_DATA_BUS_WIDTH + /// - The SPI controller supports a 4 - bit data bus + /// * HC_TRANSFER_SIZE_INCLUDES_OPCODE + /// - Transfer size includes the opcode byte + /// * HC_TRANSFER_SIZE_INCLUDES_ADDRESS + /// - Transfer size includes the 3 address bytes + /// The SPI host controller must support full - duplex (receive while + /// sending) operation.The SPI host controller must support a 1 - bit bus + /// width. + /// + UINT32 Attributes; + + /// + /// Mask of frame sizes which the SPI host controller supports. Frame size of + /// N-bits is supported when bit N-1 is set. The host controller must support + /// a frame size of 8-bits. + /// + UINT32 FrameSizeSupportMask; + + /// + /// Maximum transfer size in bytes: 1 - Oxffffffff + /// + UINT32 MaximumTransferBytes; + + /// + /// Assert or deassert the SPI chip select. + /// + EFI_SPI_HC_PROTOCOL_CHIP_SELECT ChipSelect; + + /// + /// Set up the clock generator to produce the correct clock frequency, phase + /// and polarity for a SPI chip. + /// + EFI_SPI_HC_PROTOCOL_CLOCK Clock; + + /// + /// Perform the SPI transaction on the SPI peripheral using the SPI host + /// controller. + /// + EFI_SPI_HC_PROTOCOL_TRANSACTION Transaction; +}; + +extern EFI_GUID gEfiSpiHcProtocolGuid; + +#endif // __SPI_HC_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiIo.h new file mode 100644 index 0000000..0d21b52 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiIo.h @@ -0,0 +1,292 @@ +/** @file + This file defines the SPI I/O Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_IO_PROTOCOL_H__ +#define __SPI_IO_PROTOCOL_H__ + +#include +#include + +typedef struct _EFI_SPI_IO_PROTOCOL EFI_SPI_IO_PROTOCOL; + +/// +/// Note: The UEFI PI 1.6 specification does not specify values for the +/// members below. The order matches the specification. +/// +typedef enum { + /// + /// Data flowing in both direction between the host and + /// SPI peripheral.ReadBytes must equal WriteBytes and both ReadBuffer and + /// WriteBuffer must be provided. + /// + SPI_TRANSACTION_FULL_DUPLEX, + + /// + /// Data flowing from the host to the SPI peripheral.ReadBytes must be + /// zero.WriteBytes must be non - zero and WriteBuffer must be provided. + /// + SPI_TRANSACTION_WRITE_ONLY, + + /// + /// Data flowing from the SPI peripheral to the host.WriteBytes must be + /// zero.ReadBytes must be non - zero and ReadBuffer must be provided. + /// + SPI_TRANSACTION_READ_ONLY, + + /// + /// Data first flowing from the host to the SPI peripheral and then data + /// flows from the SPI peripheral to the host.These types of operations get + /// used for SPI flash devices when control data (opcode, address) must be + /// passed to the SPI peripheral to specify the data to be read. + /// + SPI_TRANSACTION_WRITE_THEN_READ +} EFI_SPI_TRANSACTION_TYPE; + +/** + Initiate a SPI transaction between the host and a SPI peripheral. + + This routine must be called at or below TPL_NOTIFY. + This routine works with the SPI bus layer to pass the SPI transaction to the + SPI controller for execution on the SPI bus. There are four types of + supported transactions supported by this routine: + * Full Duplex: WriteBuffer and ReadBuffer are the same size. + * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0 + * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0 + * Write Then Read: WriteBuffer contains control data to write to SPI + peripheral before data is placed into the ReadBuffer. + Both WriteBytes and ReadBytes must be non-zero. + + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. + @param[in] TransactionType Type of SPI transaction. + @param[in] DebugTransaction Set TRUE only when debugging is desired. + Debugging may be turned on for a single SPI + transaction. Only this transaction will display + debugging messages. All other transactions with + this value set to FALSE will not display any + debugging messages. + @param[in] ClockHz Specify the ClockHz value as zero (0) to use + the maximum clock frequency supported by the + SPI controller and part. Specify a non-zero + value only when a specific SPI transaction + requires a reduced clock rate. + @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4 + @param[in] FrameSize Frame size in bits, range: 1 - 32 + @param[in] WriteBytes The length of the WriteBuffer in bytes. + Specify zero for read-only operations. + @param[in] WriteBuffer The buffer containing data to be sent from the + host to the SPI chip. Specify NULL for read + only operations. + * Frame sizes 1-8 bits: UINT8 (one byte) per + frame + * Frame sizes 7-16 bits: UINT16 (two bytes) per + frame + * Frame sizes 17-32 bits: UINT32 (four bytes) + per frame The transmit frame is in the least + significant N bits. + @param[in] ReadBytes The length of the ReadBuffer in bytes. + Specify zero for write-only operations. + @param[out] ReadBuffer The buffer to receeive data from the SPI chip + during the transaction. Specify NULL for write + only operations. + * Frame sizes 1-8 bits: UINT8 (one byte) per + frame + * Frame sizes 7-16 bits: UINT16 (two bytes) per + frame + * Frame sizes 17-32 bits: UINT32 (four bytes) + per frame The received frame is in the least + significant N bits. + + @retval EFI_SUCCESS The SPI transaction completed successfully + @retval EFI_BAD_BUFFER_SIZE The writeBytes value was invalid + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid + @retval EFI_INVALID_PARAMETER TransactionType is not valid, + or BusWidth not supported by SPI peripheral or + SPI host controller, + or WriteBytes non-zero and WriteBuffer is + NULL, + or ReadBytes non-zero and ReadBuffer is NULL, + or ReadBuffer != WriteBuffer for full-duplex + type, + or WriteBuffer was NULL, + or TPL is too high + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction + @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI bus + layer or the SPI host controller + @retval EFI_UNSUPPORTED The SPI controller was not able to support + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_IO_PROTOCOL_TRANSACTION) ( + IN CONST EFI_SPI_IO_PROTOCOL *This, + IN EFI_SPI_TRANSACTION_TYPE TransactionType, + IN BOOLEAN DebugTransaction, + IN UINT32 ClockHz OPTIONAL, + IN UINT32 BusWidth, + IN UINT32 FrameSize, + IN UINT32 WriteBytes, + IN UINT8 *WriteBuffer, + IN UINT32 ReadBytes, + OUT UINT8 *ReadBuffer + ); + +/** + Update the SPI peripheral associated with this SPI 10 instance. + + Support socketed SPI parts by allowing the SPI peripheral driver to replace + the SPI peripheral after the connection is made. An example use is socketed + SPI NOR flash parts, where the size and parameters change depending upon + device is in the socket. + + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. + @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure. + + @retval EFI_SUCCESS The SPI peripheral was updated successfully + @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL, + or the SpiPeripheral->SpiBus is NULL, + or the SpiP eripheral - >SpiBus pointing at + wrong bus, + or the SpiP eripheral - >SpiPart is NULL + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_SPI_IO_PROTOCOL_UPDATE_SPI_PERIPHERAL) ( + IN CONST EFI_SPI_IO_PROTOCOL *This, + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral + ); + +/// +/// The EFI_SPI_BUS_ TRANSACTION data structure contains the description of the +/// SPI transaction to perform on the host controller. +/// +typedef struct _EFI_SPI_BUS_TRANSACTION { + /// + /// Pointer to the SPI peripheral being manipulated. + /// + CONST EFI_SPI_PERIPHERAL *SpiPeripheral; + + /// + /// Type of transaction specified by one of the EFI_SPI_TRANSACTION_TYPE + /// values. + /// + EFI_SPI_TRANSACTION_TYPE TransactionType; + + /// + /// TRUE if the transaction is being debugged. Debugging may be turned on for + /// a single SPI transaction. Only this transaction will display debugging + /// messages. All other transactions with this value set to FALSE will not + /// display any debugging messages. + /// + BOOLEAN DebugTransaction; + + /// + /// SPI bus width in bits: 1, 2, 4 + /// + UINT32 BusWidth; + + /// + /// Frame size in bits, range: 1 - 32 + /// + UINT32 FrameSize; + + /// + /// Length of the write buffer in bytes + /// + UINT32 WriteBytes; + + /// + /// Buffer containing data to send to the SPI peripheral + /// Frame sizes 1 - 8 bits: UINT8 (one byte) per frame + /// Frame sizes 7 - 16 bits : UINT16 (two bytes) per frame + /// + UINT8 *WriteBuffer; + + /// + /// Length of the read buffer in bytes + /// + UINT32 ReadBytes; + + /// + /// Buffer to receive the data from the SPI peripheral + /// * Frame sizes 1 - 8 bits: UINT8 (one byte) per frame + /// * Frame sizes 7 - 16 bits : UINT16 (two bytes) per frame + /// * Frame sizes 17 - 32 bits : UINT32 (four bytes) per frame + /// + UINT8 *ReadBuffer; +} EFI_SPI_BUS_TRANSACTION; + +/// +/// Support managed SPI data transactions between the SPI controller and a SPI +/// chip. +/// +struct _EFI_SPI_IO_PROTOCOL { + /// + /// Address of an EFI_SPI_PERIPHERAL data structure associated with this + /// protocol instance. + /// + CONST EFI_SPI_PERIPHERAL *SpiPeripheral; + + /// + /// Address of the original EFI_SPI_PERIPHERAL data structure associated with + /// this protocol instance. + /// + CONST EFI_SPI_PERIPHERAL *OriginalSpiPeripheral; + + /// + /// Mask of frame sizes which the SPI 10 layer supports. Frame size of N-bits + /// is supported when bit N-1 is set. The host controller must support a + /// frame size of 8-bits. Frame sizes of 16, 24 and 32-bits are converted to + /// 8-bit frame sizes by the SPI bus layer if the frame size is not supported + /// by the SPI host controller. + /// + UINT32 FrameSizeSupportMask; + + /// + /// Maximum transfer size in bytes: 1 - Oxffffffff + /// + UINT32 MaximumTransferBytes; + + /// + /// Transaction attributes: One or more from: + /// * SPI_10_SUPPORTS_2_B1T_DATA_BUS_W1DTH + /// - The SPI host and peripheral supports a 2-bit data bus + /// * SPI_IO_SUPPORTS_4_BIT_DATA_BUS_W1DTH + /// - The SPI host and peripheral supports a 4-bit data bus + /// * SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE + /// - Transfer size includes the opcode byte + /// * SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS + /// - Transfer size includes the 3 address bytes + /// + UINT32 Attributes; + + /// + /// Pointer to legacy SPI controller protocol + /// + CONST EFI_LEGACY_SPI_CONTROLLER_PROTOCOL *LegacySpiProtocol; + + /// + /// Initiate a SPI transaction between the host and a SPI peripheral. + /// + EFI_SPI_IO_PROTOCOL_TRANSACTION Transaction; + + /// + /// Update the SPI peripheral associated with this SPI 10 instance. + /// + EFI_SPI_IO_PROTOCOL_UPDATE_SPI_PERIPHERAL UpdateSpiPeripheral; +}; + +#endif // __SPI_IO_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiNorFlash.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiNorFlash.h new file mode 100644 index 0000000..133701f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiNorFlash.h @@ -0,0 +1,262 @@ +/** @file + This file defines the SPI NOR Flash Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_NOR_FLASH_PROTOCOL_H__ +#define __SPI_NOR_FLASH_PROTOCOL_H__ + +#include + +/// +/// Global ID for the SPI NOR Flash Protocol +/// +#define EFI_SPI_NOR_FLASH_PROTOCOL_GUID \ + { 0xb57ec3fe, 0xf833, 0x4ba6, \ + { 0x85, 0x78, 0x2a, 0x7d, 0x6a, 0x87, 0x44, 0x4b }} + +typedef struct _EFI_SPI_NOR_FLASH_PROTOCOL EFI_SPI_NOR_FLASH_PROTOCOL; + +/** + Read the 3 byte manufacture and device ID from the SPI flash. + + This routine must be called at or below TPL_NOTIFY. + This routine reads the 3 byte manufacture and device ID from the flash part + filling the buffer provided. + + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data structure. + @param[out] Buffer Pointer to a 3 byte buffer to receive the manufacture and + device ID. + + + + @retval EFI_SUCCESS The manufacture and device ID was read + successfully. + @retval EFI_INVALID_PARAMETER Buffer is NULL + @retval EFI_DEVICE_ERROR Invalid data received from SPI flash part. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_GET_FLASH_ID) ( + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, + OUT UINT8 *Buffer + ); + +/** + Read data from the SPI flash. + + This routine must be called at or below TPL_NOTIFY. + This routine reads data from the SPI part in the buffer provided. + + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data + structure. + @param[in] FlashAddress Address in the flash to start reading + @param[in] LengthInBytes Read length in bytes + @param[out] Buffer Address of a buffer to receive the data + + @retval EFI_SUCCESS The data was read successfully. + @retval EFI_INVALID_PARAMETER Buffer is NULL, or + FlashAddress >= This->FlashSize, or + LengthInBytes > This->FlashSize - FlashAddress + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_READ_DATA) ( + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, + IN UINT32 FlashAddress, + IN UINT32 LengthInBytes, + OUT UINT8 *Buffer + ); + +/** + Read the flash status register. + + This routine must be called at or below TPL_NOTIFY. + This routine reads the flash part status register. + + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data + structure. + @param[in] LengthInBytes Number of status bytes to read. + @param[out] FlashStatus Pointer to a buffer to receive the flash status. + + @retval EFI_SUCCESS The status register was read successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_READ_STATUS) ( + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, + IN UINT32 LengthInBytes, + OUT UINT8 *FlashStatus + ); + +/** + Write the flash status register. + + This routine must be called at or below TPL_N OTIFY. + This routine writes the flash part status register. + + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data + structure. + @param[in] LengthInBytes Number of status bytes to write. + @param[in] FlashStatus Pointer to a buffer containing the new status. + + @retval EFI_SUCCESS The status write was successful. + @retval EFI_OUT_OF_RESOURCES Failed to allocate the write buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_STATUS) ( + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, + IN UINT32 LengthInBytes, + IN UINT8 *FlashStatus + ); + +/** + Write data to the SPI flash. + + This routine must be called at or below TPL_NOTIFY. + This routine breaks up the write operation as necessary to write the data to + the SPI part. + + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data + structure. + @param[in] FlashAddress Address in the flash to start writing + @param[in] LengthInBytes Write length in bytes + @param[in] Buffer Address of a buffer containing the data + + @retval EFI_SUCCESS The data was written successfully. + @retval EFI_INVALID_PARAMETER Buffer is NULL, or + FlashAddress >= This->FlashSize, or + LengthInBytes > This->FlashSize - FlashAddress + @retval EFI_OUT_OF_RESOURCES Insufficient memory to copy buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_DATA) ( + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, + IN UINT32 FlashAddress, + IN UINT32 LengthInBytes, + IN UINT8 *Buffer + ); + +/** + Efficiently erases one or more 4KiB regions in the SPI flash. + + This routine must be called at or below TPL_NOTIFY. + This routine uses a combination of 4 KiB and larger blocks to erase the + specified area. + + @param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data + structure. + @param[in] FlashAddress Address within a 4 KiB block to start erasing + @param[in] BlockCount Number of 4 KiB blocks to erase + + @retval EFI_SUCCESS The erase was completed successfully. + @retval EFI_INVALID_PARAMETER FlashAddress >= This->FlashSize, or + BlockCount * 4 KiB + > This->FlashSize - FlashAddress + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SPI_NOR_FLASH_PROTOCOL_ERASE) ( + IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, + IN UINT32 FlashAddress, + IN UINT32 BlockCount + ); + +/// +/// The EFI_SPI_NOR_FLASH_PROTOCOL exists in the SPI peripheral layer. +/// This protocol manipulates the SPI NOR flash parts using a common set of +/// commands. The board layer provides the interconnection and configuration +/// details for the SPI NOR flash part. The SPI NOR flash driver uses this +/// configuration data to expose a generic interface which provides the +/// following APls: +/// * Read manufacture and device ID +/// * Read data +/// * Read data using low frequency +/// * Read status +/// * Write data +/// * Erase 4 KiB blocks +/// * Erase 32 or 64 KiB blocks +/// * Write status +/// The EFI_SPI_NOR_FLASH_PROTOCOL also exposes some APls to set the security +/// features on the legacy SPI flash controller. +/// +struct _EFI_SPI_NOR_FLASH_PROTOCOL { + /// + /// Pointer to an EFI_SPI_PERIPHERAL data structure + /// + CONST EFI_SPI_PERIPHERAL *SpiPeripheral; + + /// + /// Flash size in bytes + /// + UINT32 FlashSize; + + /// + /// Manufacture and Device ID + /// + UINT8 Deviceid[3]; + + /// + /// Erase block size in bytes + /// + UINT32 EraseBlockBytes; + + /// + /// Read the 3 byte manufacture and device ID from the SPI flash. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_GET_FLASH_ID GetFlashid; + + /// + /// Read data from the SPI flash. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_READ_DATA ReadData; + + /// + /// Low frequency read data from the SPI flash. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_READ_DATA LfReadData; + + /// + /// Read the flash status register. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_READ_STATUS ReadStatus; + + /// + /// Write the flash status register. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_STATUS WriteStatus; + + /// + /// Write data to the SPI flash. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_WRITE_DATA WriteData; + + /// + /// Efficiently erases one or more 4KiB regions in the SPI flash. + /// + EFI_SPI_NOR_FLASH_PROTOCOL_ERASE Erase; +}; + +extern EFI_GUID gEfiSpiNorFlashProtocolGuid; + +#endif // __SPI_NOR_FLASH_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmConfiguration.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmConfiguration.h new file mode 100644 index 0000000..913d4cb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmConfiguration.h @@ -0,0 +1,36 @@ +/** @file + This file defines the SPI SMM Configuration Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_SMM_CONFIGURATION_PROTOCOL_H__ +#define __SPI_SMM_CONFIGURATION_PROTOCOL_H__ + +#include + +/// +/// Global ID for the SPI SMM Configuration Protocol +/// +#define EFI_SPI_SMM_CONFIGURATION_PROTOCOL_GUID \ + { 0x995c6eca, 0x171b, 0x45fd, \ + { 0xa3, 0xaa, 0xfd, 0x4c, 0x9c, 0x9d, 0xef, 0x59 }} + +typedef +struct _EFI_SPI_CONFIGURATION_PROTOCOL +EFI_SPI_SMM_CONFIGURATION_PROTOCOL; + +extern EFI_GUID gEfiSpiSmmConfigurationProtocolGuid; + +#endif // __SPI_SMM_CONFIGURATION_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmHc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmHc.h new file mode 100644 index 0000000..91d2312 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmHc.h @@ -0,0 +1,36 @@ +/** @file + This file defines the SPI SMM Host Controller Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_SMM_HC_H__ +#define __SPI_SMM_HC_H__ + +#include + +/// +/// Global ID for the SPI SMM Host Controller Protocol +/// +#define EFI_SPI_SMM_HC_PROTOCOL_GUID \ + { 0xe9f02217, 0x2093, 0x4470, \ + { 0x8a, 0x54, 0x5c, 0x2c, 0xff, 0xe7, 0x3e, 0xcb }} + +typedef +struct _EFI_SPI_HC_PROTOCOL +EFI_SPI_SMM_HC_PROTOCOL; + +extern EFI_GUID gEfiSpiSmmHcProtocolGuid; + +#endif // __SPI_SMM_HC_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmNorFlash.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmNorFlash.h new file mode 100644 index 0000000..495c70f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SpiSmmNorFlash.h @@ -0,0 +1,36 @@ +/** @file + This file defines the SPI SMM NOR Flash Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD + License which accompanies this distribution. The full text of the license may + be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI PI Specification 1.6. + +**/ + +#ifndef __SPI_SMM_NOR_FLASH_PROTOCOL_H__ +#define __SPI_SMM_NOR_FLASH_PROTOCOL_H__ + +#include + +/// +/// Global ID for the SPI SMM NOR Flash Protocol +/// +#define EFI_SPI_SMM_NOR_FLASH_PROTOCOL_GUID \ + { 0xaab18f19, 0xfe14, 0x4666, \ + { 0x86, 0x04, 0x87, 0xff, 0x6d, 0x66, 0x2c, 0x9a } } + +typedef +struct _EFI_SPI_NOR_FLASH_PROTOCOL +EFI_SPI_SMM_NOR_FLASH_PROTOCOL; + +extern EFI_GUID gEfiSpiSmmNorFlashProtocolGuid; + +#endif // __SPI_SMM_NOR_FLASH_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StatusCode.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StatusCode.h new file mode 100644 index 0000000..0f1a6d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StatusCode.h @@ -0,0 +1,59 @@ +/** @file + Status code Runtime Protocol as defined in PI Specification 1.4a VOLUME 2 DXE + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __STATUS_CODE_RUNTIME_PROTOCOL_H__ +#define __STATUS_CODE_RUNTIME_PROTOCOL_H__ + +#define EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID \ +{ 0xd2b2b828, 0x826, 0x48a7, { 0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0 } } + +/** + Provides an interface that a software module can call to report a status code. + + @param Type Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REPORT_STATUS_CODE)( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/// +/// Provides the service required to report a status code to the platform firmware. +/// This protocol must be produced by a runtime DXE driver. +/// +typedef struct _EFI_STATUS_CODE_PROTOCOL { + EFI_REPORT_STATUS_CODE ReportStatusCode; +} EFI_STATUS_CODE_PROTOCOL; + +extern EFI_GUID gEfiStatusCodeRuntimeProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StorageSecurityCommand.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StorageSecurityCommand.h new file mode 100644 index 0000000..a558c11 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/StorageSecurityCommand.h @@ -0,0 +1,212 @@ +/** @file + EFI Storage Security Command Protocol as defined in UEFI 2.3.1 specification. + This protocol is used to abstract mass storage devices to allow code running in + the EFI boot services environment to send security protocol commands to mass + storage devices without specific knowledge of the type of device or controller + that manages the device. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __STORAGE_SECURITY_COMMAND_H__ +#define __STORAGE_SECURITY_COMMAND_H__ + +#define EFI_STORAGE_SECURITY_COMMAND_PROTOCOL_GUID \ + { \ + 0xC88B0B6D, 0x0DFC, 0x49A7, {0x9C, 0xB4, 0x49, 0x07, 0x4B, 0x4C, 0x3A, 0x78 } \ + } + +typedef struct _EFI_STORAGE_SECURITY_COMMAND_PROTOCOL EFI_STORAGE_SECURITY_COMMAND_PROTOCOL; + +/** + Send a security protocol command to a device that receives data and/or the result + of one or more commands sent by SendData. + + The ReceiveData function sends a security protocol command to the given MediaId. + The security protocol command sent is defined by SecurityProtocolId and contains + the security protocol specific data SecurityProtocolSpecificData. The function + returns the data from the security protocol command in PayloadBuffer. + + For devices supporting the SCSI command set, the security protocol command is sent + using the SECURITY PROTOCOL IN command defined in SPC-4. + + For devices supporting the ATA command set, the security protocol command is sent + using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize + is non-zero. + + If the PayloadBufferSize is zero, the security protocol command is sent using the + Trusted Non-Data command defined in ATA8-ACS. + + If PayloadBufferSize is too small to store the available data from the security + protocol command, the function shall copy PayloadBufferSize bytes into the + PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. + + If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero, + the function shall return EFI_INVALID_PARAMETER. + + If the given MediaId does not support security protocol commands, the function shall + return EFI_UNSUPPORTED. If there is no media in the device, the function returns + EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device, + the function returns EFI_MEDIA_CHANGED. + + If the security protocol fails to complete within the Timeout period, the function + shall return EFI_TIMEOUT. + + If the security protocol command completes without an error, the function shall + return EFI_SUCCESS. If the security protocol command completes with an error, the + function shall return EFI_DEVICE_ERROR. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to receive data from. + @param Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value of 0 + means that this function will wait indefinitely for the + security protocol command to execute. If Timeout is greater + than zero, then this function will return EFI_TIMEOUT if the + time required to execute the receive data command is greater than Timeout. + @param SecurityProtocolId The value of the "Security Protocol" parameter of + the security protocol command to be sent. + @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter + of the security protocol command to be sent. + @param PayloadBufferSize Size in bytes of the payload data buffer. + @param PayloadBuffer A pointer to a destination buffer to store the security + protocol command specific payload data for the security + protocol command. The caller is responsible for having + either implicit or explicit ownership of the buffer. + @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the + data written to the payload data buffer. + + @retval EFI_SUCCESS The security protocol command completed successfully. + @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available + data from the device. The PayloadBuffer contains the truncated data. + @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands. + @retval EFI_DEVICE_ERROR The security protocol command completed with an error. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and + PayloadBufferSize is non-zero. + @retval EFI_TIMEOUT A timeout occurred while waiting for the security + protocol command to execute. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_STORAGE_SECURITY_RECEIVE_DATA)( + IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Timeout, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN PayloadBufferSize, + OUT VOID *PayloadBuffer, + OUT UINTN *PayloadTransferSize + ); + +/** + Send a security protocol command to a device. + + The SendData function sends a security protocol command containing the payload + PayloadBuffer to the given MediaId. The security protocol command sent is + defined by SecurityProtocolId and contains the security protocol specific data + SecurityProtocolSpecificData. If the underlying protocol command requires a + specific padding for the command payload, the SendData function shall add padding + bytes to the command payload to satisfy the padding requirements. + + For devices supporting the SCSI command set, the security protocol command is sent + using the SECURITY PROTOCOL OUT command defined in SPC-4. + + For devices supporting the ATA command set, the security protocol command is sent + using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize + is non-zero. If the PayloadBufferSize is zero, the security protocol command is + sent using the Trusted Non-Data command defined in ATA8-ACS. + + If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall + return EFI_INVALID_PARAMETER. + + If the given MediaId does not support security protocol commands, the function + shall return EFI_UNSUPPORTED. If there is no media in the device, the function + returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the + device, the function returns EFI_MEDIA_CHANGED. + + If the security protocol fails to complete within the Timeout period, the function + shall return EFI_TIMEOUT. + + If the security protocol command completes without an error, the function shall return + EFI_SUCCESS. If the security protocol command completes with an error, the function + shall return EFI_DEVICE_ERROR. + + @param This Indicates a pointer to the calling context. + @param MediaId ID of the medium to receive data from. + @param Timeout The timeout, in 100ns units, to use for the execution + of the security protocol command. A Timeout value of 0 + means that this function will wait indefinitely for the + security protocol command to execute. If Timeout is greater + than zero, then this function will return EFI_TIMEOUT if the + time required to execute the receive data command is greater than Timeout. + @param SecurityProtocolId The value of the "Security Protocol" parameter of + the security protocol command to be sent. + @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter + of the security protocol command to be sent. + @param PayloadBufferSize Size in bytes of the payload data buffer. + @param PayloadBuffer A pointer to a destination buffer to store the security + protocol command specific payload data for the security + protocol command. + + @retval EFI_SUCCESS The security protocol command completed successfully. + @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands. + @retval EFI_DEVICE_ERROR The security protocol command completed with an error. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero. + @retval EFI_TIMEOUT A timeout occurred while waiting for the security + protocol command to execute. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_STORAGE_SECURITY_SEND_DATA) ( + IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Timeout, + IN UINT8 SecurityProtocolId, + IN UINT16 SecurityProtocolSpecificData, + IN UINTN PayloadBufferSize, + IN VOID *PayloadBuffer +); + +/// +/// The EFI_STORAGE_SECURITY_COMMAND_PROTOCOL is used to send security protocol +/// commands to a mass storage device. Two types of security protocol commands +/// are supported. SendData sends a command with data to a device. ReceiveData +/// sends a command that receives data and/or the result of one or more commands +/// sent by SendData. +/// +/// The security protocol command formats supported shall be based on the definition +/// of the SECURITY PROTOCOL IN and SECURITY PROTOCOL OUT commands defined in SPC-4. +/// If the device uses the SCSI command set, no translation is needed in the firmware +/// and the firmware can package the parameters into a SECURITY PROTOCOL IN or SECURITY +/// PROTOCOL OUT command and send the command to the device. If the device uses a +/// non-SCSI command set, the firmware shall map the command and data payload to the +/// corresponding command and payload format defined in the non-SCSI command set +/// (for example, TRUSTED RECEIVE and TRUSTED SEND in ATA8-ACS). +/// +/// The firmware shall automatically add an EFI_STORAGE_SECURITY_COMMAND_PROTOCOL +/// for any storage devices detected during system boot that support SPC-4, ATA8-ACS +/// or their successors. +/// +struct _EFI_STORAGE_SECURITY_COMMAND_PROTOCOL { + EFI_STORAGE_SECURITY_RECEIVE_DATA ReceiveData; + EFI_STORAGE_SECURITY_SEND_DATA SendData; +}; + +extern EFI_GUID gEfiStorageSecurityCommandProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIo.h new file mode 100644 index 0000000..2e3adf7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIo.h @@ -0,0 +1,175 @@ +/** @file + The Super I/O Protocol is installed by the Super I/O driver. The Super I/O driver is a UEFI driver + model compliant driver. In the Start() routine of the Super I/O driver, a handle with an instance + of EFI_SIO_PROTOCOL is created for each device within the Super I/O. The device within the + Super I/O is powered up, enabled, and assigned with the default set of resources. In the Stop() + routine of the Super I/O driver, the device is disabled and Super I/O protocol is uninstalled. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_SUPER_IO_PROTOCOL_H__ +#define __EFI_SUPER_IO_PROTOCOL_H__ +#include + +#define EFI_SIO_PROTOCOL_GUID \ + { 0x215fdd18, 0xbd50, 0x4feb, { 0x89, 0xb, 0x58, 0xca, 0xb, 0x47, 0x39, 0xe9 } } + +typedef union { + ACPI_SMALL_RESOURCE_HEADER *SmallHeader; + ACPI_LARGE_RESOURCE_HEADER *LargeHeader; +} ACPI_RESOURCE_HEADER_PTR; + +typedef struct { + UINT8 Register; ///< Register number. + UINT8 AndMask; ///< Bitwise AND mask. + UINT8 OrMask; ///< Bitwise OR mask. +} EFI_SIO_REGISTER_MODIFY; + +typedef struct _EFI_SIO_PROTOCOL EFI_SIO_PROTOCOL; + +/** + Provides a low level access to the registers for the Super I/O. + + @param[in] This Indicates a pointer to the calling context. + @param[in] Write Specifies the type of the register operation. If this parameter is TRUE, Value is + interpreted as an input parameter and the operation is a register write. If this parameter + is FALSE, Value is interpreted as an output parameter and the operation is a register + read. + @param[in] ExitCfgMode Exit Configuration Mode Indicator. If this parameter is set to TRUE, the Super I/O + driver will turn off configuration mode of the Super I/O prior to returning from this + function. If this parameter is set to FALSE, the Super I/O driver will leave Super I/O + in the configuration mode. + The Super I/O driver must track the current state of the Super I/O and enable the + configuration mode of Super I/O if necessary prior to register access. + @param[in] Register Register number. + @param[in, out] Value If Write is TRUE, Value is a pointer to the buffer containing the byte of data to be + written to the Super I/O register. If Write is FALSE, Value is a pointer to the + destination buffer for the byte of data to be read from the Super I/O register. + + @retval EFI_SUCCESS The operation completed successfully + @retval EFI_INVALID_PARAMETER The Value is NULL + @retval EFI_INVALID_PARAMETER Invalid Register number + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_REGISTER_ACCESS)( + IN CONST EFI_SIO_PROTOCOL *This, + IN BOOLEAN Write, + IN BOOLEAN ExitCfgMode, + IN UINT8 Register, + IN OUT UINT8 *Value +); + +/** + Provides an interface to get a list of the current resources consumed by the device in the ACPI + Resource Descriptor format. + + GetResources() returns a list of resources currently consumed by the device. The + ResourceList is a pointer to the buffer containing resource descriptors for the device. The + descriptors are in the format of Small or Large ACPI resource descriptor as defined by ACPI + specification (2.0 & 3.0). The buffer of resource descriptors is terminated with the 'End tag' + resource descriptor. + + @param[in] This Indicates a pointer to the calling context. + @param[out] ResourceList A pointer to an ACPI resource descriptor list that defines the current resources used by + the device. Type ACPI_RESOURCE_HEADER_PTR is defined in the "Related + Definitions" below. + + @retval EFI_SUCCESS The operation completed successfully + @retval EFI_INVALID_PARAMETER ResourceList is NULL + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_GET_RESOURCES)( + IN CONST EFI_SIO_PROTOCOL *This, + OUT ACPI_RESOURCE_HEADER_PTR *ResourceList +); + +/** + Sets the resources for the device. + + @param[in] This Indicates a pointer to the calling context. + @param[in] ResourceList Pointer to the ACPI resource descriptor list. Type ACPI_RESOURCE_HEADER_PTR + is defined in the "Related Definitions" section of + EFI_SIO_PROTOCOL.GetResources(). + + @retval EFI_SUCCESS The operation completed successfully + @retval EFI_INVALID_PARAMETER ResourceList is invalid + @retval EFI_ACCESS_DENIED Some of the resources in ResourceList are in use + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_SET_RESOURCES)( + IN CONST EFI_SIO_PROTOCOL *This, + IN ACPI_RESOURCE_HEADER_PTR ResourceList +); + +/** + Provides a collection of resource descriptor lists. Each resource descriptor list in the collection + defines a combination of resources that can potentially be used by the device. + + @param[in] This Indicates a pointer to the calling context. + @param[out] ResourceCollection Collection of the resource descriptor lists. + + @retval EFI_SUCCESS The operation completed successfully + @retval EFI_INVALID_PARAMETER ResourceCollection is NULL +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_POSSIBLE_RESOURCES)( + IN CONST EFI_SIO_PROTOCOL *This, + OUT ACPI_RESOURCE_HEADER_PTR *ResourceCollection +); + +/** + Provides an interface for a table based programming of the Super I/O registers. + + The Modify() function provides an interface for table based programming of the Super I/O + registers. This function can be used to perform programming of multiple Super I/O registers with a + single function call. For each table entry, the Register is read, its content is bitwise ANDed with + AndMask, and then ORed with OrMask before being written back to the Register. The Super + I/O driver must track the current state of the Super I/O and enable the configuration mode of Super I/ + O if necessary prior to table processing. Once the table is processed, the Super I/O device has to be + returned to the original state. + + @param[in] This Indicates a pointer to the calling context. + @param[in] Command A pointer to an array of NumberOfCommands EFI_SIO_REGISTER_MODIFY + structures. Each structure specifies a single Super I/O register modify operation. Type + EFI_SIO_REGISTER_MODIFY is defined in the "Related Definitions" below. + @param[in] NumberOfCommands Number of elements in the Command array. + + @retval EFI_SUCCESS The operation completed successfully + @retval EFI_INVALID_PARAMETER Command is NULL + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_MODIFY)( + IN CONST EFI_SIO_PROTOCOL *This, + IN CONST EFI_SIO_REGISTER_MODIFY *Command, + IN UINTN NumberOfCommands +); + +struct _EFI_SIO_PROTOCOL { + EFI_SIO_REGISTER_ACCESS RegisterAccess; + EFI_SIO_GET_RESOURCES GetResources; + EFI_SIO_SET_RESOURCES SetResources; + EFI_SIO_POSSIBLE_RESOURCES PossibleResources; + EFI_SIO_MODIFY Modify; +}; + +extern EFI_GUID gEfiSioProtocolGuid; + +#endif // __EFI_SUPER_IO_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIoControl.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIoControl.h new file mode 100644 index 0000000..f5af14c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/SuperIoControl.h @@ -0,0 +1,92 @@ +/** @file + The Super I/O Control Protocol is installed by the Super I/O driver. It provides + the low-level services for SIO devices that enable them to be used in the UEFI + driver model. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This protocol is from PI Version 1.2.1. + +**/ + +#ifndef __EFI_SUPER_IO_CONTROL_PROTOCOL_H__ +#define __EFI_SUPER_IO_CONTROL_PROTOCOL_H__ + +#define EFI_SIO_CONTROL_PROTOCOL_GUID \ + { \ + 0xb91978df, 0x9fc1, 0x427d, { 0xbb, 0x5, 0x4c, 0x82, 0x84, 0x55, 0xca, 0x27 } \ + } + +typedef struct _EFI_SIO_CONTROL_PROTOCOL EFI_SIO_CONTROL_PROTOCOL; +typedef struct _EFI_SIO_CONTROL_PROTOCOL *PEFI_SIO_CONTROL_PROTOCOL; + +/** + Enable an ISA-style device. + + This function enables a logical ISA device and, if necessary, configures it + to default settings, including memory, I/O, DMA and IRQ resources. + + @param This A pointer to this instance of the EFI_SIO_CONTROL_PROTOCOL. + + @retval EFI_SUCCESS The device is enabled successfully. + @retval EFI_OUT_OF_RESOURCES The device could not be enabled because there + were insufficient resources either for the device + itself or for the records needed to track the device. + @retval EFI_ALREADY_STARTED The device is already enabled. + @retval EFI_UNSUPPORTED The device cannot be enabled. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_CONTROL_ENABLE)( + IN CONST EFI_SIO_CONTROL_PROTOCOL *This + ); + +/** + Disable a logical ISA device. + + This function disables a logical ISA device so that it no longer consumes + system resources, such as memory, I/O, DMA and IRQ resources. Enough information + must be available so that subsequent Enable() calls would properly reconfigure + the device. + + @param This A pointer to this instance of the EFI_SIO_CONTROL_PROTOCOL. + + @retval EFI_SUCCESS The device is disabled successfully. + @retval EFI_OUT_OF_RESOURCES The device could not be disabled because there + were insufficient resources either for the device + itself or for the records needed to track the device. + @retval EFI_ALREADY_STARTED The device is already disabled. + @retval EFI_UNSUPPORTED The device cannot be disabled. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIO_CONTROL_DISABLE)( + IN CONST EFI_SIO_CONTROL_PROTOCOL *This + ); + +struct _EFI_SIO_CONTROL_PROTOCOL { + /// + /// The version of this protocol. + /// + UINT32 Version; + /// + /// Enable a device. + /// + EFI_SIO_CONTROL_ENABLE EnableDevice; + /// + /// Disable a device. + /// + EFI_SIO_CONTROL_DISABLE DisableDevice; +}; + +extern EFI_GUID gEfiSioControlProtocolGuid; + +#endif // __EFI_SUPER_IO_CONTROL_PROTOCOL_H__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Supplicant.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Supplicant.h new file mode 100644 index 0000000..1f1e2ff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Supplicant.h @@ -0,0 +1,464 @@ +/** @file + This file defines the EFI Supplicant Protocol. + + Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.6 + +**/ + +#ifndef __EFI_SUPPLICANT_PROTOCOL_H__ +#define __EFI_SUPPLICANT_PROTOCOL_H__ + +#include + +/// +/// The EFI Supplicant Service Binding Protocol is used to locate EFI +/// Supplicant Protocol drivers to create and destroy child of the driver to +/// communicate with other host using Supplicant protocol. +/// +#define EFI_SUPPLICANT_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x45bcd98e, 0x59ad, 0x4174, { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 } \ + } + +/// +/// The EFI Supplicant protocol provides services to process authentication and +/// data encryption/decryption for security management. +/// +#define EFI_SUPPLICANT_PROTOCOL_GUID \ + { \ + 0x54fcc43e, 0xaa89, 0x4333, { 0x9a, 0x85, 0xcd, 0xea, 0x24, 0x5, 0x1e, 0x9e } \ + } + +typedef struct _EFI_SUPPLICANT_PROTOCOL EFI_SUPPLICANT_PROTOCOL; + +/// +/// EFI_SUPPLICANT_CRYPT_MODE +/// +typedef enum { + // + // Encrypt data provided in the fragment buffers. + // + EfiSupplicantEncrypt, + // + // Decrypt data provided in the fragment buffers. + // + EfiSupplicantDecrypt, +} EFI_SUPPLICANT_CRYPT_MODE; + +/// +/// EFI_SUPPLICANT_DATA_TYPE +/// +typedef enum { + // + // Session Configuration + // + + // + // Current authentication type in use. The corresponding Data is of type + // EFI_80211_AKM_SUITE_SELECTOR. + // + EfiSupplicant80211AKMSuite, + // + // Group data encryption type in use. The corresponding Data is of type + // EFI_SUPPLICANT_CIPHER_SUITE_SELECTOR. + // + EfiSupplicant80211GroupDataCipherSuite, + // + // Pairwise encryption type in use. The corresponding Data is of type + // EFI_80211_CIPHER_SUITE_SELECTOR. + // + EfiSupplicant80211PairwiseCipherSuite, + // + // PSK password. The corresponding Data is a NULL-terminated ASCII string. + // + EfiSupplicant80211PskPassword, + // + // Target SSID name. The corresponding Data is of type EFI_80211_SSID. + // + EfiSupplicant80211TargetSSIDName, + // + // Station MAC address. The corresponding Data is of type + // EFI_80211_MAC_ADDRESS. + // + EfiSupplicant80211StationMac, + // + // Target SSID MAC address. The corresponding Data is 6 bytes MAC address. + // + EfiSupplicant80211TargetSSIDMac, + + // + // Session Information + // + + // + // 802.11 PTK. The corresponding Data is of type EFI_SUPPLICANT_KEY. + // + EfiSupplicant80211PTK, + // + // 802.11 GTK. The corresponding Data is of type EFI_SUPPLICANT_GTK_LIST. + // + EfiSupplicant80211GTK, + // + // Supplicant state. The corresponding Data is + // EFI_EAPOL_SUPPLICANT_PAE_STATE. + // + EfiSupplicantState, + // + // 802.11 link state. The corresponding Data is EFI_80211_LINK_STATE. + // + EfiSupplicant80211LinkState, + // + // Flag indicates key is refreshed. The corresponding Data is + // EFI_SUPPLICANT_KEY_REFRESH. + // + EfiSupplicantKeyRefresh, + + // + // Session Configuration + // + + // + // Supported authentication types. The corresponding Data is of type + // EFI_80211_AKM_SUITE_SELECTOR. + // + EfiSupplicant80211SupportedAKMSuites, + // + // Supported software encryption types provided by supplicant driver. The + // corresponding Data is of type EFI_80211_CIPHER_SUITE_SELECTOR. + // + EfiSupplicant80211SupportedSoftwareCipherSuites, + // + // Supported hardware encryption types provided by wireless UNDI driver. The + // corresponding Data is of type EFI_80211_CIPHER_SUITE_SELECTOR. + // + EfiSupplicant80211SupportedHardwareCipherSuites, + + // + // Session Information + // + + // + // 802.11 Integrity GTK. The corresponding Data is of type + // EFI_SUPPLICANT_GTK_LIST. + // + EfiSupplicant80211IGTK, + // + // 802.11 PMK. The corresponding Data is 32 bytes pairwise master key. + // + EfiSupplicant80211PMK, + EfiSupplicantDataTypeMaximum +} EFI_SUPPLICANT_DATA_TYPE; + +/// +/// EFI_80211_LINK_STATE +/// +typedef enum { + // + // Indicates initial start state, unauthenticated, unassociated. + // + Ieee80211UnauthenticatedUnassociated, + // + // Indicates authenticated, unassociated. + // + Ieee80211AuthenticatedUnassociated, + // + // Indicates authenticated and associated, but pending RSN authentication. + // + Ieee80211PendingRSNAuthentication, + // + // Indicates authenticated and associated. + // + Ieee80211AuthenticatedAssociated +} EFI_80211_LINK_STATE; + +/// +/// EFI_SUPPLICANT_KEY_TYPE (IEEE Std 802.11 Section 6.3.19.1.2) +/// +typedef enum { + Group, + Pairwise, + PeerKey, + IGTK +} EFI_SUPPLICANT_KEY_TYPE; + +/// +/// EFI_SUPPLICANT_KEY_DIRECTION (IEEE Std 802.11 Section 6.3.19.1.2) +/// +typedef enum { + // + // Indicates that the keys are being installed for the receive direction. + // + Receive, + // + // Indicates that the keys are being installed for the transmit direction. + // + Transmit, + // + // Indicates that the keys are being installed for both the receive and + // transmit directions. + // + Both +} EFI_SUPPLICANT_KEY_DIRECTION; + +/// +/// EFI_SUPPLICANT_KEY_REFRESH +/// +typedef struct { + // + // If TRUE, indicates GTK is just refreshed after a successful call to + // EFI_SUPPLICANT_PROTOCOL.BuildResponsePacket(). + // + BOOLEAN GTKRefresh; +} EFI_SUPPLICANT_KEY_REFRESH; + +#define EFI_MAX_KEY_LEN 64 + +/// +/// EFI_SUPPLICANT_KEY +/// +typedef struct { + // + // The key value. + // + UINT8 Key[EFI_MAX_KEY_LEN]; + // + // Length in bytes of the Key. Should be up to EFI_MAX_KEY_LEN. + // + UINT8 KeyLen; + // + // The key identifier. + // + UINT8 KeyId; + // + // Defines whether this key is a group key, pairwise key, PeerKey, or + // Integrity Group. + // + EFI_SUPPLICANT_KEY_TYPE KeyType; + // + // The value is set according to the KeyType. + // + EFI_80211_MAC_ADDRESS Addr; + // + // The Receive Sequence Count value. + // + UINT8 Rsc[8]; + // + // Length in bytes of the Rsc. Should be up to 8. + // + UINT8 RscLen; + // + // Indicates whether the key is configured by the Authenticator or + // Supplicant. The value true indicates Authenticator. + // + BOOLEAN IsAuthenticator; + // + // The cipher suite required for this association. + // + EFI_80211_SUITE_SELECTOR CipherSuite; + // + // Indicates the direction for which the keys are to be installed. + // + EFI_SUPPLICANT_KEY_DIRECTION Direction; +} EFI_SUPPLICANT_KEY; + +/// +/// EFI_SUPPLICANT_GTK_LIST +/// +typedef struct { + // + // Indicates the number of GTKs that are contained in GTKList. + // + UINT8 GTKCount; + // + // A variable-length array of GTKs of type EFI_SUPPLICANT_KEY. The number of + // entries is specified by GTKCount. + // + EFI_SUPPLICANT_KEY GTKList[1]; +} EFI_SUPPLICANT_GTK_LIST; + +/// +/// EFI_SUPPLICANT_FRAGMENT_DATA +/// +typedef struct { + // + // Length of data buffer in the fragment. + // + UINT32 FragmentLength; + // + // Pointer to the data buffer in the fragment. + // + VOID *FragmentBuffer; +} EFI_SUPPLICANT_FRAGMENT_DATA; + +/** + BuildResponsePacket() is called during STA and AP authentication is in + progress. Supplicant derives the PTK or session keys depend on type of + authentication is being employed. + + @param[in] This Pointer to the EFI_SUPPLICANT_PROTOCOL + instance. + @param[in] RequestBuffer Pointer to the most recently received EAPOL + packet. NULL means the supplicant need + initiate the EAP authentication session and + send EAPOL-Start message. + @param[in] RequestBufferSize + Packet size in bytes for the most recently + received EAPOL packet. 0 is only valid when + RequestBuffer is NULL. + @param[out] Buffer Pointer to the buffer to hold the built + packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On + input, it is the buffer size provided by the + caller. On output, it is the buffer size in + fact needed to contain the packet. + + @retval EFI_SUCCESS The required EAPOL packet is built + successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + RequestBuffer is NULL, but RequestSize is + NOT 0. + RequestBufferSize is 0. + Buffer is NULL, but RequestBuffer is NOT 0. + BufferSize is NULL. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response + packet. + @retval EFI_NOT_READY Current EAPOL session state is NOT ready to + build ResponsePacket. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SUPPLICANT_BUILD_RESPONSE_PACKET) ( + IN EFI_SUPPLICANT_PROTOCOL *This, + IN UINT8 *RequestBuffer, OPTIONAL + IN UINTN RequestBufferSize, OPTIONAL + OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize + ); + +/** + ProcessPacket() is called to Supplicant driver to encrypt or decrypt the data + depending type of authentication type. + + @param[in] This Pointer to the EFI_SUPPLICANT_PROTOCOL + instance. + @param[in, out] FragmentTable Pointer to a list of fragment. The caller + will take responsible to handle the original + FragmentTable while it may be reallocated in + Supplicant driver. + @param[in] FragmentCount Number of fragment. + @param[in] CryptMode Crypt mode. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + FragmentTable is NULL. + FragmentCount is NULL. + CryptMode is invalid. + @retval EFI_NOT_READY Current supplicant state is NOT Authenticated. + @retval EFI_ABORTED Something wrong decryption the message. + @retval EFI_UNSUPPORTED This API is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SUPPLICANT_PROCESS_PACKET) ( + IN EFI_SUPPLICANT_PROTOCOL *This, + IN OUT EFI_SUPPLICANT_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_SUPPLICANT_CRYPT_MODE CryptMode + ); + +/** + Set Supplicant configuration data. + + @param[in] This Pointer to the EFI_SUPPLICANT_PROTOCOL + instance. + @param[in] DataType The type of data. + @param[in] Data Pointer to the buffer to hold the data. + @param[in] DataSize Pointer to the buffer size in bytes. + + @retval EFI_SUCCESS The Supplicant configuration data is set + successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SUPPLICANT_SET_DATA) ( + IN EFI_SUPPLICANT_PROTOCOL *This, + IN EFI_SUPPLICANT_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get Supplicant configuration data. + + @param[in] This Pointer to the EFI_SUPPLICANT_PROTOCOL + instance. + @param[in] DataType The type of data. + @param[out] Data Pointer to the buffer to hold the data. + Ignored if DataSize is 0. + @param[in, out] DataSize Pointer to the buffer size in bytes. On + input, it is the buffer size provided by the + caller. On output, it is the buffer size in + fact needed to contain the packet. + + @retval EFI_SUCCESS The Supplicant configuration data is got + successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The Supplicant configuration data is not + found. + @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the + specified configuration data and the required + size is returned in DataSize. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SUPPLICANT_GET_DATA) ( + IN EFI_SUPPLICANT_PROTOCOL *This, + IN EFI_SUPPLICANT_DATA_TYPE DataType, + OUT UINT8 *Data, OPTIONAL + IN OUT UINTN *DataSize + ); + +/// +/// The EFI_SUPPLICANT_PROTOCOL is designed to provide unified place for WIFI +/// and EAP security management. Both PSK authentication and 802.1X EAP +/// authentication can be managed via this protocol and driver or application +/// as a consumer can only focus on about packet transmitting or receiving. +/// +struct _EFI_SUPPLICANT_PROTOCOL { + EFI_SUPPLICANT_BUILD_RESPONSE_PACKET BuildResponsePacket; + EFI_SUPPLICANT_PROCESS_PACKET ProcessPacket; + EFI_SUPPLICANT_SET_DATA SetData; + EFI_SUPPLICANT_GET_DATA GetData; +}; + +extern EFI_GUID gEfiSupplicantServiceBindingProtocolGuid; +extern EFI_GUID gEfiSupplicantProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TapeIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TapeIo.h new file mode 100644 index 0000000..153b41a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TapeIo.h @@ -0,0 +1,237 @@ +/** @file + EFI_TAPE_IO_PROTOCOL as defined in the UEFI 2.0. + Provide services to control and access a tape device. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_TAPE_IO_PROTOCOL_H__ +#define __EFI_TAPE_IO_PROTOCOL_H__ + +#define EFI_TAPE_IO_PROTOCOL_GUID \ + { \ + 0x1e93e633, 0xd65a, 0x459e, {0xab, 0x84, 0x93, 0xd9, 0xec, 0x26, 0x6d, 0x18 } \ + } + +typedef struct _EFI_TAPE_IO_PROTOCOL EFI_TAPE_IO_PROTOCOL; + +typedef struct _EFI_TAPE_HEADER { + UINT64 Signature; + UINT32 Revision; + UINT32 BootDescSize; + UINT32 BootDescCRC; + EFI_GUID TapeGUID; + EFI_GUID TapeType; + EFI_GUID TapeUnique; + UINT32 BLLocation; + UINT32 BLBlocksize; + UINT32 BLFilesize; + CHAR8 OSVersion[40]; + CHAR8 AppVersion[40]; + CHAR8 CreationDate[10]; + CHAR8 CreationTime[10]; + CHAR8 SystemName[256]; // UTF-8 + CHAR8 TapeTitle[120]; // UTF-8 + CHAR8 pad[468]; // pad to 1024 +} EFI_TAPE_HEADER; + +/** + Reads from the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param BufferSize The size of the buffer in bytes pointed to by Buffer. + @param Buffer The pointer to the buffer for data to be read into. + + @retval EFI_SUCCESS Data was successfully transferred from the media. + @retval EFI_END_OF_FILE A filemark was encountered which limited the data + transferred by the read operation or the head is positioned + just after a filemark. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The transfer failed since the device was not ready (e.g. not + online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of transfer. + @retval EFI_TIMEOUT The transfer failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + The transfer was aborted since the current position of the + media may be incorrect. + @retval EFI_INVALID_PARAMETER A NULL Buffer was specified with a non-zero + BufferSize, or the device is operating in fixed block + size mode and the BufferSize was not a multiple of + device's fixed block size + @retval EFI_DEVICE_ERROR A device error occurred while attempting to transfer data + from the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_READ)( + IN EFI_TAPE_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Writes to the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer. + @param Buffer The pointer to the buffer for data to be written from. + + @retval EFI_SUCCESS Data was successfully transferred to the media. + @retval EFI_END_OF_MEDIA The logical end of media has been reached. Data may have + been successfully transferred to the media. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The transfer failed since the device was not ready (e.g. not + online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of transfer. + @retval EFI_TIMEOUT The transfer failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + The transfer was aborted since the current position of the + media may be incorrect. + @retval EFI_WRITE_PROTECTED The media in the device is write-protected. The transfer + was aborted since a write cannot be completed. + @retval EFI_INVALID_PARAMETER A NULL Buffer was specified with a non-zero + BufferSize, or the device is operating in fixed block + size mode and the BufferSize was not a multiple of + device's fixed block size + @retval EFI_DEVICE_ERROR A device error occurred while attempting to transfer data + from the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_WRITE)( + IN EFI_TAPE_IO_PROTOCOL *This, + IN UINTN *BufferSize, + IN VOID *Buffer + ); + + +/** + Rewinds the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The media was successfully repositioned. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY Repositioning the media failed since the device was not + ready (e.g. not online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of media repositioning. + @retval EFI_TIMEOUT Repositioning of the media did not complete within the timeout specified. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reposition the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_REWIND)( + IN EFI_TAPE_IO_PROTOCOL *This + ); + + +/** + Positions the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param Direction Direction and number of data blocks or filemarks to space over on media. + @param Type Type of mark to space over on media. + The following Type marks are mandatory: + BLOCK type : 0 + FILEMARK type : 1 + + @retval EFI_SUCCESS The media was successfully repositioned. + @retval EFI_END_OF_MEDIA Beginning or end of media was reached before the + indicated number of data blocks or filemarks were found. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The reposition failed since the device was not ready (e.g. not + online). The reposition may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of repositioning. + @retval EFI_TIMEOUT The repositioning failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + Repositioning the media was aborted since the current + position of the media may be incorrect. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reposition the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_SPACE)( + IN EFI_TAPE_IO_PROTOCOL *This, + IN INTN Direction, + IN UINTN Type + ); + + +/** + Writes filemarks to the media. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param Count Number of filemarks to write to the media. + + @retval EFI_SUCCESS Data was successfully transferred from the media. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The transfer failed since the device was not ready (e.g. not + online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of repositioning. + @retval EFI_TIMEOUT The transfer failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + The transfer was aborted since the current position of the + media may be incorrect. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to transfer data from the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_WRITEFM)( + IN EFI_TAPE_IO_PROTOCOL *This, + IN UINTN Count + ); + + +/** + Resets the tape device. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param ExtendedVerification Indicates whether the parent bus should also be reset. + + @retval EFI_SUCCESS The bus and/or device were successfully reset. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The reset failed since the device and/or bus was not ready. + The reset may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of reset. + @retval EFI_TIMEOUT The reset did not complete within the timeout allowed. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the bus and/or device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_RESET)( + IN EFI_TAPE_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/// +/// The EFI_TAPE_IO_PROTOCOL provides basic sequential operations for tape devices. +/// These include read, write, rewind, space, write filemarks and reset functions. +/// Per this specification, a boot application uses the services of this protocol +/// to load the bootloader image from tape. +/// +struct _EFI_TAPE_IO_PROTOCOL { + EFI_TAPE_READ TapeRead; + EFI_TAPE_WRITE TapeWrite; + EFI_TAPE_REWIND TapeRewind; + EFI_TAPE_SPACE TapeSpace; + EFI_TAPE_WRITEFM TapeWriteFM; + EFI_TAPE_RESET TapeReset; +}; + +extern EFI_GUID gEfiTapeIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcg2Protocol.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcg2Protocol.h new file mode 100644 index 0000000..884d94b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcg2Protocol.h @@ -0,0 +1,341 @@ +/** @file + TPM2 Protocol as defined in TCG PC Client Platform EFI Protocol Specification Family "2.0". + See http://trustedcomputinggroup.org for the latest specification + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TCG2_PROTOCOL_H__ +#define __TCG2_PROTOCOL_H__ + +#include +#include + +#define EFI_TCG2_PROTOCOL_GUID \ + {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }} + +typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL; + +typedef struct tdEFI_TCG2_VERSION { + UINT8 Major; + UINT8 Minor; +} EFI_TCG2_VERSION; + +typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP; +typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT; +typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP; + +#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001 +#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002 + +typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY { + // + // Allocated size of the structure + // + UINT8 Size; + // + // Version of the EFI_TCG2_BOOT_SERVICE_CAPABILITY structure itself. + // For this version of the protocol, the Major version shall be set to 1 + // and the Minor version shall be set to 1. + // + EFI_TCG2_VERSION StructureVersion; + // + // Version of the EFI TCG2 protocol. + // For this version of the protocol, the Major version shall be set to 1 + // and the Minor version shall be set to 1. + // + EFI_TCG2_VERSION ProtocolVersion; + // + // Supported hash algorithms (this bitmap is determined by the supported PCR + // banks in the TPM and the hashing algorithms supported by the firmware) + // + EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap; + // + // Bitmap of supported event log formats + // + EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs; + // + // False = TPM not present + // + BOOLEAN TPMPresentFlag; + // + // Max size (in bytes) of a command that can be sent to the TPM + // + UINT16 MaxCommandSize; + // + // Max size (in bytes) of a response that can be provided by the TPM + // + UINT16 MaxResponseSize; + // + // 4-byte Vendor ID + // (see TCG Vendor ID registry, Section "TPM Capabilities Vendor ID") + // + UINT32 ManufacturerID; + // + // Maximum number of PCR banks (hashing algorithms) supported. + // No granularity is provided to support a specific set of algorithms. + // Minimum value is 1. + // + UINT32 NumberOfPCRBanks; + // + // A bitmap of currently active PCR banks (hashing algorithms). + // This is a subset of the supported hashing algorithms reported in HashAlgorithmBitMap. + // NumberOfPcrBanks defines the number of bits that are set. + // + EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks; +} EFI_TCG2_BOOT_SERVICE_CAPABILITY; + +#define EFI_TCG2_BOOT_HASH_ALG_SHA1 0x00000001 +#define EFI_TCG2_BOOT_HASH_ALG_SHA256 0x00000002 +#define EFI_TCG2_BOOT_HASH_ALG_SHA384 0x00000004 +#define EFI_TCG2_BOOT_HASH_ALG_SHA512 0x00000008 +#define EFI_TCG2_BOOT_HASH_ALG_SM3_256 0x00000010 + +// +// This bit is shall be set when an event shall be extended but not logged. +// +#define EFI_TCG2_EXTEND_ONLY 0x0000000000000001 +// +// This bit shall be set when the intent is to measure a PE/COFF image. +// +#define PE_COFF_IMAGE 0x0000000000000010 + +#define MAX_PCR_INDEX 23 + +#pragma pack(1) + +#define EFI_TCG2_EVENT_HEADER_VERSION 1 + +typedef struct { + // + // Size of the event header itself (sizeof(EFI_TCG2_EVENT_HEADER)). + // + UINT32 HeaderSize; + // + // Header version. For this version of this specification, the value shall be 1. + // + UINT16 HeaderVersion; + // + // Index of the PCR that shall be extended (0 - 23). + // + TCG_PCRINDEX PCRIndex; + // + // Type of the event that shall be extended (and optionally logged). + // + TCG_EVENTTYPE EventType; +} EFI_TCG2_EVENT_HEADER; + +typedef struct tdEFI_TCG2_EVENT { + // + // Total size of the event including the Size component, the header and the Event data. + // + UINT32 Size; + EFI_TCG2_EVENT_HEADER Header; + UINT8 Event[1]; +} EFI_TCG2_EVENT; + +#pragma pack() + +/** + The EFI_TCG2_PROTOCOL GetCapability function call provides protocol + capability information and state information. + + @param[in] This Indicates the calling context + @param[in, out] ProtocolCapability The caller allocates memory for a EFI_TCG2_BOOT_SERVICE_CAPABILITY + structure and sets the size field to the size of the structure allocated. + The callee fills in the fields with the EFI protocol capability information + and the current EFI TCG2 state information up to the number of fields which + fit within the size of the structure passed in. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + The ProtocolCapability variable will not be populated. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + The ProtocolCapability variable will not be populated. + @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response. + It will be partially populated (required Size field will be set). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG2_GET_CAPABILITY) ( + IN EFI_TCG2_PROTOCOL *This, + IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability + ); + +/** + The EFI_TCG2_PROTOCOL Get Event Log function call allows a caller to + retrieve the address of a given event log and its last entry. + + @param[in] This Indicates the calling context + @param[in] EventLogFormat The type of the event log for which the information is requested. + @param[out] EventLogLocation A pointer to the memory address of the event log. + @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the + address of the start of the last entry in the event log in memory. + @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would + have exceeded the area allocated for events, this value is set to TRUE. + Otherwise, the value will be FALSE and the Event Log will be complete. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect + (e.g. asking for an event log whose format is not supported). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG2_GET_EVENT_LOG) ( + IN EFI_TCG2_PROTOCOL *This, + IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, + OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry, + OUT BOOLEAN *EventLogTruncated + ); + +/** + The EFI_TCG2_PROTOCOL HashLogExtendEvent function call provides callers with + an opportunity to extend and optionally log events without requiring + knowledge of actual TPM commands. + The extend operation will occur even if this function cannot create an event + log entry (e.g. due to the event log being full). + + @param[in] This Indicates the calling context + @param[in] Flags Bitmap providing additional information. + @param[in] DataToHash Physical address of the start of the data buffer to be hashed. + @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash. + @param[in] EfiTcgEvent Pointer to data buffer containing information about the event. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_UNSUPPORTED The PE/COFF image type is not supported. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_TCG2_HASH_LOG_EXTEND_EVENT) ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT64 Flags, + IN EFI_PHYSICAL_ADDRESS DataToHash, + IN UINT64 DataToHashLen, + IN EFI_TCG2_EVENT *EfiTcgEvent + ); + +/** + This service enables the sending of commands to the TPM. + + @param[in] This Indicates the calling context + @param[in] InputParameterBlockSize Size of the TPM input parameter block. + @param[in] InputParameterBlock Pointer to the TPM input parameter block. + @param[in] OutputParameterBlockSize Size of the TPM output parameter block. + @param[in] OutputParameterBlock Pointer to the TPM output parameter block. + + @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. + @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG2_SUBMIT_COMMAND) ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT32 InputParameterBlockSize, + IN UINT8 *InputParameterBlock, + IN UINT32 OutputParameterBlockSize, + IN UINT8 *OutputParameterBlock + ); + +/** + This service returns the currently active PCR banks. + + @param[in] This Indicates the calling context + @param[out] ActivePcrBanks Pointer to the variable receiving the bitmap of currently active PCR banks. + + @retval EFI_SUCCESS The bitmap of active PCR banks was stored in the ActivePcrBanks parameter. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG2_GET_ACTIVE_PCR_BANKS) ( + IN EFI_TCG2_PROTOCOL *This, + OUT UINT32 *ActivePcrBanks + ); + +/** + This service sets the currently active PCR banks. + + @param[in] This Indicates the calling context + @param[in] ActivePcrBanks Bitmap of the requested active PCR banks. At least one bit SHALL be set. + + @retval EFI_SUCCESS The bitmap in ActivePcrBank parameter is already active. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG2_SET_ACTIVE_PCR_BANKS) ( + IN EFI_TCG2_PROTOCOL *This, + IN UINT32 ActivePcrBanks + ); + +/** + This service retrieves the result of a previous invocation of SetActivePcrBanks. + + @param[in] This Indicates the calling context + @param[out] OperationPresent Non-zero value to indicate a SetActivePcrBank operation was invoked during the last boot. + @param[out] Response The response from the SetActivePcrBank request. + + @retval EFI_SUCCESS The result value could be returned. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS) ( + IN EFI_TCG2_PROTOCOL *This, + OUT UINT32 *OperationPresent, + OUT UINT32 *Response + ); + +struct tdEFI_TCG2_PROTOCOL { + EFI_TCG2_GET_CAPABILITY GetCapability; + EFI_TCG2_GET_EVENT_LOG GetEventLog; + EFI_TCG2_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; + EFI_TCG2_SUBMIT_COMMAND SubmitCommand; + EFI_TCG2_GET_ACTIVE_PCR_BANKS GetActivePcrBanks; + EFI_TCG2_SET_ACTIVE_PCR_BANKS SetActivePcrBanks; + EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks; +}; + +extern EFI_GUID gEfiTcg2ProtocolGuid; + +// +// Log entries after Get Event Log service +// + +#define EFI_TCG2_FINAL_EVENTS_TABLE_GUID \ + {0x1e2ed096, 0x30e2, 0x4254, { 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25 }} + +extern EFI_GUID gEfiTcg2FinalEventsTableGuid; + +typedef struct tdEFI_TCG2_FINAL_EVENTS_TABLE { + // + // The version of this structure. + // + UINT64 Version; + // + // Number of events recorded after invocation of GetEventLog API + // + UINT64 NumberOfEvents; + // + // List of events of type TCG_PCR_EVENT2. + // +//TCG_PCR_EVENT2 Event[1]; +} EFI_TCG2_FINAL_EVENTS_TABLE; + +#define EFI_TCG2_FINAL_EVENTS_TABLE_VERSION 1 + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TcgService.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TcgService.h new file mode 100644 index 0000000..065db27 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TcgService.h @@ -0,0 +1,201 @@ +/** @file + TCG Service Protocol as defined in TCG_EFI_Protocol_1_22_Final + See http://trustedcomputinggroup.org for the latest specification + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TCG_SERVICE_PROTOCOL_H_ +#define _TCG_SERVICE_PROTOCOL_H_ + +#include + +#define EFI_TCG_PROTOCOL_GUID \ + {0xf541796d, 0xa62e, 0x4954, { 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd } } + +typedef struct _EFI_TCG_PROTOCOL EFI_TCG_PROTOCOL; + +typedef struct { + UINT8 Major; + UINT8 Minor; + UINT8 RevMajor; + UINT8 RevMinor; +} TCG_VERSION; + +typedef struct _TCG_EFI_BOOT_SERVICE_CAPABILITY { + UINT8 Size; /// Size of this structure. + TCG_VERSION StructureVersion; + TCG_VERSION ProtocolSpecVersion; + UINT8 HashAlgorithmBitmap; /// Hash algorithms . + /// This protocol is capable of : 01=SHA-1. + BOOLEAN TPMPresentFlag; /// 00h = TPM not present. + BOOLEAN TPMDeactivatedFlag; /// 01h = TPM currently deactivated. +} TCG_EFI_BOOT_SERVICE_CAPABILITY; + +typedef UINT32 TCG_ALGORITHM_ID; + +/** + This service provides EFI protocol capability information, state information + about the TPM, and Event Log state information. + + @param This Indicates the calling context + @param ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY + structure and fills in the fields with the EFI protocol + capability information and the current TPM state information. + @param TCGFeatureFlags This is a pointer to the feature flags. No feature + flags are currently defined so this parameter + MUST be set to 0. However, in the future, + feature flags may be defined that, for example, + enable hash algorithm agility. + @param EventLogLocation This is a pointer to the address of the event log in memory. + @param EventLogLastEntry If the Event Log contains more than one entry, + this is a pointer to the address of the start of + the last entry in the event log in memory. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG_STATUS_CHECK)( + IN EFI_TCG_PROTOCOL *This, + OUT TCG_EFI_BOOT_SERVICE_CAPABILITY + *ProtocolCapability, + OUT UINT32 *TCGFeatureFlags, + OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry + ); + +/** + This service abstracts the capability to do a hash operation on a data buffer. + + @param This Indicates the calling context. + @param HashData The pointer to the data buffer to be hashed. + @param HashDataLen The length of the data buffer to be hashed. + @param AlgorithmId Identification of the Algorithm to use for the hashing operation. + @param HashedDataLen Resultant length of the hashed data. + @param HashedDataResult Resultant buffer of the hashed data. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER HashDataLen is NULL. + @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL. + @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen. + @retval EFI_UNSUPPORTED AlgorithmId not supported. + @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG_HASH_ALL)( + IN EFI_TCG_PROTOCOL *This, + IN UINT8 *HashData, + IN UINT64 HashDataLen, + IN TCG_ALGORITHM_ID AlgorithmId, + IN OUT UINT64 *HashedDataLen, + IN OUT UINT8 **HashedDataResult + ); + +/** + This service abstracts the capability to add an entry to the Event Log. + + @param This Indicates the calling context + @param TCGLogData The pointer to the start of the data buffer containing + the TCG_PCR_EVENT data structure. All fields in + this structure are properly filled by the caller. + @param EventNumber The event number of the event just logged. + @param Flags Indicates additional flags. Only one flag has been + defined at this time, which is 0x01 and means the + extend operation should not be performed. All + other bits are reserved. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG_LOG_EVENT)( + IN EFI_TCG_PROTOCOL *This, + IN TCG_PCR_EVENT *TCGLogData, + IN OUT UINT32 *EventNumber, + IN UINT32 Flags + ); + +/** + This service is a proxy for commands to the TPM. + + @param This Indicates the calling context. + @param TpmInputParameterBlockSize Size of the TPM input parameter block. + @param TpmInputParameterBlock The pointer to the TPM input parameter block. + @param TpmOutputParameterBlockSize Size of the TPM output parameter block. + @param TpmOutputParameterBlock The pointer to the TPM output parameter block. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Invalid ordinal. + @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK. + @retval EFI_TIMEOUT The TIS timed-out. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG_PASS_THROUGH_TO_TPM)( + IN EFI_TCG_PROTOCOL *This, + IN UINT32 TpmInputParameterBlockSize, + IN UINT8 *TpmInputParameterBlock, + IN UINT32 TpmOutputParameterBlockSize, + IN UINT8 *TpmOutputParameterBlock + ); + +/** + This service abstracts the capability to do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, and add an entry to the Event Log + + @param This Indicates the calling context + @param HashData The physical address of the start of the data buffer + to be hashed, extended, and logged. + @param HashDataLen The length, in bytes, of the buffer referenced by HashData + @param AlgorithmId Identification of the Algorithm to use for the hashing operation + @param TCGLogData The physical address of the start of the data + buffer containing the TCG_PCR_EVENT data structure. + @param EventNumber The event number of the event just logged. + @param EventLogLastEntry The physical address of the first byte of the entry + just placed in the Event Log. If the Event Log was + empty when this function was called then this physical + address will be the same as the physical address of + the start of the Event Log. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA. + @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK. + @retval EFI_DEVICE_ERROR The command was unsuccessful. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCG_HASH_LOG_EXTEND_EVENT)( + IN EFI_TCG_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS HashData, + IN UINT64 HashDataLen, + IN TCG_ALGORITHM_ID AlgorithmId, + IN OUT TCG_PCR_EVENT *TCGLogData, + IN OUT UINT32 *EventNumber, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry + ); + +/// +/// The EFI_TCG Protocol abstracts TCG activity. +/// +struct _EFI_TCG_PROTOCOL { + EFI_TCG_STATUS_CHECK StatusCheck; + EFI_TCG_HASH_ALL HashAll; + EFI_TCG_LOG_EVENT LogEvent; + EFI_TCG_PASS_THROUGH_TO_TPM PassThroughToTpm; + EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; +}; + +extern EFI_GUID gEfiTcgProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp4.h new file mode 100644 index 0000000..8967b1f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp4.h @@ -0,0 +1,577 @@ +/** @file + EFI TCPv4(Transmission Control Protocol version 4) Protocol Definition + The EFI TCPv4 Service Binding Protocol is used to locate EFI TCPv4 Protocol drivers to create + and destroy child of the driver to communicate with other host using TCP protocol. + The EFI TCPv4 Protocol provides services to send and receive data stream. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.0. + +**/ + +#ifndef __EFI_TCP4_PROTOCOL_H__ +#define __EFI_TCP4_PROTOCOL_H__ + +#include + +#define EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x00720665, 0x67EB, 0x4a99, {0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9 } \ + } + +#define EFI_TCP4_PROTOCOL_GUID \ + { \ + 0x65530BC7, 0xA359, 0x410f, {0xB0, 0x10, 0x5A, 0xAD, 0xC7, 0xEC, 0x2B, 0x62 } \ + } + +typedef struct _EFI_TCP4_PROTOCOL EFI_TCP4_PROTOCOL; + +/// +/// EFI_TCP4_SERVICE_POINT is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE InstanceHandle; + EFI_IPv4_ADDRESS LocalAddress; + UINT16 LocalPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_TCP4_SERVICE_POINT; + +/// +/// EFI_TCP4_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 ServiceCount; + EFI_TCP4_SERVICE_POINT Services[1]; +} EFI_TCP4_VARIABLE_DATA; + +typedef struct { + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; + BOOLEAN ActiveFlag; +} EFI_TCP4_ACCESS_POINT; + +typedef struct { + UINT32 ReceiveBufferSize; + UINT32 SendBufferSize; + UINT32 MaxSynBackLog; + UINT32 ConnectionTimeout; + UINT32 DataRetries; + UINT32 FinTimeout; + UINT32 TimeWaitTimeout; + UINT32 KeepAliveProbes; + UINT32 KeepAliveTime; + UINT32 KeepAliveInterval; + BOOLEAN EnableNagle; + BOOLEAN EnableTimeStamp; + BOOLEAN EnableWindowScaling; + BOOLEAN EnableSelectiveAck; + BOOLEAN EnablePathMtuDiscovery; +} EFI_TCP4_OPTION; + +typedef struct { + // + // I/O parameters + // + UINT8 TypeOfService; + UINT8 TimeToLive; + + // + // Access Point + // + EFI_TCP4_ACCESS_POINT AccessPoint; + + // + // TCP Control Options + // + EFI_TCP4_OPTION *ControlOption; +} EFI_TCP4_CONFIG_DATA; + +/// +/// TCP4 connnection state +/// +typedef enum { + Tcp4StateClosed = 0, + Tcp4StateListen = 1, + Tcp4StateSynSent = 2, + Tcp4StateSynReceived = 3, + Tcp4StateEstablished = 4, + Tcp4StateFinWait1 = 5, + Tcp4StateFinWait2 = 6, + Tcp4StateClosing = 7, + Tcp4StateTimeWait = 8, + Tcp4StateCloseWait = 9, + Tcp4StateLastAck = 10 +} EFI_TCP4_CONNECTION_STATE; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; +} EFI_TCP4_COMPLETION_TOKEN; + +typedef struct { + /// + /// The Status in the CompletionToken will be set to one of + /// the following values if the active open succeeds or an unexpected + /// error happens: + /// EFI_SUCCESS: The active open succeeds and the instance's + /// state is Tcp4StateEstablished. + /// EFI_CONNECTION_RESET: The connect fails because the connection is reset + /// either by instance itself or the communication peer. + /// EFI_CONNECTION_REFUSED: The connect fails because this connection is initiated with + /// an active open and the connection is refused. + /// EFI_ABORTED: The active open is aborted. + /// EFI_TIMEOUT: The connection establishment timer expires and + /// no more specific information is available. + /// EFI_NETWORK_UNREACHABLE: The active open fails because + /// an ICMP network unreachable error is received. + /// EFI_HOST_UNREACHABLE: The active open fails because an + /// ICMP host unreachable error is received. + /// EFI_PROTOCOL_UNREACHABLE: The active open fails + /// because an ICMP protocol unreachable error is received. + /// EFI_PORT_UNREACHABLE: The connection establishment + /// timer times out and an ICMP port unreachable error is received. + /// EFI_ICMP_ERROR: The connection establishment timer timeout and some other ICMP + /// error is received. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// EFI_NO_MEDIA: There was a media error. + /// + EFI_TCP4_COMPLETION_TOKEN CompletionToken; +} EFI_TCP4_CONNECTION_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP4_LISTEN_TOKEN; + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_TCP4_FRAGMENT_DATA; + +typedef struct { + BOOLEAN UrgentFlag; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_RECEIVE_DATA; + +typedef struct { + BOOLEAN Push; + BOOLEAN Urgent; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_TRANSMIT_DATA; + +typedef struct { + /// + /// When transmission finishes or meets any unexpected error it will + /// be set to one of the following values: + /// EFI_SUCCESS: The receiving or transmission operation + /// completes successfully. + /// EFI_CONNECTION_FIN: The receiving operation fails because the communication peer + /// has closed the connection and there is no more data in the + /// receive buffer of the instance. + /// EFI_CONNECTION_RESET: The receiving or transmission operation fails + /// because this connection is reset either by instance + /// itself or the communication peer. + /// EFI_ABORTED: The receiving or transmission is aborted. + /// EFI_TIMEOUT: The transmission timer expires and no more + /// specific information is available. + /// EFI_NETWORK_UNREACHABLE: The transmission fails + /// because an ICMP network unreachable error is received. + /// EFI_HOST_UNREACHABLE: The transmission fails because an + /// ICMP host unreachable error is received. + /// EFI_PROTOCOL_UNREACHABLE: The transmission fails + /// because an ICMP protocol unreachable error is received. + /// EFI_PORT_UNREACHABLE: The transmission fails and an + /// ICMP port unreachable error is received. + /// EFI_ICMP_ERROR: The transmission fails and some other + /// ICMP error is received. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurs. + /// EFI_NO_MEDIA: There was a media error. + /// + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + union { + /// + /// When this token is used for receiving, RxData is a pointer to EFI_TCP4_RECEIVE_DATA. + /// + EFI_TCP4_RECEIVE_DATA *RxData; + /// + /// When this token is used for transmitting, TxData is a pointer to EFI_TCP4_TRANSMIT_DATA. + /// + EFI_TCP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_TCP4_IO_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + BOOLEAN AbortOnClose; +} EFI_TCP4_CLOSE_TOKEN; + +// +// Interface definition for TCP4 protocol +// + +/** + Get the current operational status. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param Tcp4State The pointer to the buffer to receive the current TCP state. + @param Tcp4ConfigData The pointer to the buffer to receive the current TCP configuration. + @param Ip4ModeData The pointer to the buffer to receive the current IPv4 configuration + data used by the TCPv4 instance. + @param MnpConfigData The pointer to the buffer to receive the current MNP configuration + data used indirectly by the TCPv4 instance. + @param SnpModeData The pointer to the buffer to receive the current SNP configuration + data used indirectly by the TCPv4 instance. + + @retval EFI_SUCCESS The mode data was read. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED No configuration data is available because this instance hasn't + been started. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_GET_MODE_DATA)( + IN EFI_TCP4_PROTOCOL *This, + OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL, + OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +/** + Initialize or brutally reset the operational parameters for this EFI TCPv4 instance. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param Tcp4ConfigData The pointer to the configure data to configure the instance. + + @retval EFI_SUCCESS The operational settings are set, changed, or reset + successfully. + @retval EFI_INVALID_PARAMETER Some parameter is invalid. + @retval EFI_NO_MAPPING When using a default address, configuration (through + DHCP, BOOTP, RARP, etc.) is not finished yet. + @retval EFI_ACCESS_DENIED Configuring TCP instance when it is configured without + calling Configure() with NULL to reset it. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_UNSUPPORTED One or more of the control options are not supported in + the implementation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when + executing Configure(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CONFIGURE)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL + ); + + +/** + Add or delete a route entry to the route table + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param DeleteRoute Set it to TRUE to delete this route from the routing table. Set it to + FALSE to add this route to the routing table. + DestinationAddress and SubnetMask are used as the + keywords to search route entry. + @param SubnetAddress The destination network. + @param SubnetMask The subnet mask of the destination network. + @param GatewayAddress The gateway address for this route. It must be on the same + subnet with the station address unless a direct route is specified. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI TCPv4 Protocol instance has not been configured. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - SubnetAddress is NULL. + - SubnetMask is NULL. + - GatewayAddress is NULL. + - *SubnetAddress is not NULL a valid subnet address. + - *SubnetMask is not a valid subnet mask. + - *GatewayAddress is not a valid unicast IP address or it + is not in the same subnet. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the entry to the + routing table. + @retval EFI_NOT_FOUND This route is not in the routing table. + @retval EFI_ACCESS_DENIED The route is already defined in the routing table. + @retval EFI_UNSUPPORTED The TCP driver does not support this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_ROUTES)( + IN EFI_TCP4_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ); + +/** + Initiate a nonblocking TCP connection request for an active TCP instance. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param ConnectionToken The pointer to the connection token to return when the TCP three + way handshake finishes. + + @retval EFI_SUCCESS The connection request is successfully initiated and the state + of this TCPv4 instance has been changed to Tcp4StateSynSent. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE: + - This instance is not configured as an active one. + - This instance is not in Tcp4StateClosed state. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ConnectionToken is NULL. + - ConnectionToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to initiate the activ eopen. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CONNECT)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken + ); + + +/** + Listen on the passive instance to accept an incoming connection request. This is a nonblocking operation. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param ListenToken The pointer to the listen token to return when operation finishes. + + @retval EFI_SUCCESS The listen token has been queued successfully. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following are TRUE: + - This instance is not a passive instance. + - This instance is not in Tcp4StateListen state. + - The same listen token has already existed in the listen + token queue of this TCP instance. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ListenToken is NULL. + - ListentToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_ACCEPT)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_LISTEN_TOKEN *ListenToken + ); + +/** + Queues outgoing data into the transmit queue. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param Token The pointer to the completion token to queue to the transmit queue. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - Token is NULL. + - Token->CompletionToken.Event is NULL. + - Token->Packet.TxData is NULL L. + - Token->Packet.FragmentCount is zero. + - Token->Packet.DataLength is not equal to the sum of fragment lengths. + @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE: + - A transmit completion token with the same Token->CompletionToken.Event + was already in the transmission queue. + - The current instance is in Tcp4StateClosed state. + - The current instance is a passive one and it is in + Tcp4StateListen state. + - User has called Close() to disconnect this connection. + @retval EFI_NOT_READY The completion token could not be queued because the + transmit queue is full. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of resource + shortage. + @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_TRANSMIT)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_IO_TOKEN *Token + ); + + +/** + Places an asynchronous receive request into the receiving queue. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param Token The pointer to a token that is associated with the receive data + descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, RARP, + etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token->CompletionToken.Event is NULL. + - Token->Packet.RxData is NULL. + - Token->Packet.RxData->DataLength is 0. + - The Token->Packet.RxData->DataLength is not + the sum of all FragmentBuffer length in FragmentTable. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of + system resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE: + - A receive completion token with the same Token- + >CompletionToken.Event was already in the receive + queue. + - The current instance is in Tcp4StateClosed state. + - The current instance is a passive one and it is in + Tcp4StateListen state. + - User has called Close() to disconnect this connection. + @retval EFI_CONNECTION_FIN The communication peer has closed the connection and there is + no any buffered data in the receive buffer of this instance. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_RECEIVE)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_IO_TOKEN *Token + ); + +/** + Disconnecting a TCP connection gracefully or reset a TCP connection. This function is a + nonblocking operation. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param CloseToken The pointer to the close token to return when operation finishes. + + @retval EFI_SUCCESS The Close() is called successfully. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following are TRUE: + - Configure() has been called with + TcpConfigData set to NULL and this function has + not returned. + - Previous Close() call on this instance has not + finished. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - CloseToken is NULL. + - CloseToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CLOSE)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_CLOSE_TOKEN *CloseToken + ); + +/** + Abort an asynchronous connection, listen, transmission or receive request. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + @param Token The pointer to a token that has been issued by + EFI_TCP4_PROTOCOL.Connect(), + EFI_TCP4_PROTOCOL.Accept(), + EFI_TCP4_PROTOCOL.Transmit() or + EFI_TCP4_PROTOCOL.Receive(). If NULL, all pending + tokens issued by above four functions will be aborted. Type + EFI_TCP4_COMPLETION_TOKEN is defined in + EFI_TCP4_PROTOCOL.Connect(). + + @retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event + is signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance hasn't been configured. + @retval EFI_NO_MAPPING When using the default address, configuration + (DHCP, BOOTP,RARP, etc.) hasn't finished yet. + @retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the + transmission or receive queue. It has either + completed or wasn't issued by Transmit() and Receive(). + @retval EFI_UNSUPPORTED The implementation does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CANCEL)( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL + ); + + +/** + Poll to receive incoming data and transmit outgoing segments. + + @param This The pointer to the EFI_TCP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmission or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_POLL)( + IN EFI_TCP4_PROTOCOL *This + ); + +/// +/// The EFI_TCP4_PROTOCOL defines the EFI TCPv4 Protocol child to be used by +/// any network drivers or applications to send or receive data stream. +/// It can either listen on a specified port as a service or actively connected +/// to remote peer as a client. Each instance has its own independent settings, +/// such as the routing table. +/// +struct _EFI_TCP4_PROTOCOL { + EFI_TCP4_GET_MODE_DATA GetModeData; + EFI_TCP4_CONFIGURE Configure; + EFI_TCP4_ROUTES Routes; + EFI_TCP4_CONNECT Connect; + EFI_TCP4_ACCEPT Accept; + EFI_TCP4_TRANSMIT Transmit; + EFI_TCP4_RECEIVE Receive; + EFI_TCP4_CLOSE Close; + EFI_TCP4_CANCEL Cancel; + EFI_TCP4_POLL Poll; +}; + +extern EFI_GUID gEfiTcp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiTcp4ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp6.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp6.h new file mode 100644 index 0000000..b725391 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tcp6.h @@ -0,0 +1,864 @@ +/** @file + EFI TCPv6(Transmission Control Protocol version 6) Protocol Definition + The EFI TCPv6 Service Binding Protocol is used to locate EFI TCPv6 Protocol drivers to create + and destroy child of the driver to communicate with other host using TCP protocol. + The EFI TCPv6 Protocol provides services to send and receive data stream. + + Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_TCP6_PROTOCOL_H__ +#define __EFI_TCP6_PROTOCOL_H__ + +#include +#include + +#define EFI_TCP6_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xec20eb79, 0x6c1a, 0x4664, {0x9a, 0x0d, 0xd2, 0xe4, 0xcc, 0x16, 0xd6, 0x64 } \ + } + +#define EFI_TCP6_PROTOCOL_GUID \ + { \ + 0x46e44855, 0xbd60, 0x4ab7, {0xab, 0x0d, 0xa6, 0x79, 0xb9, 0x44, 0x7d, 0x77 } \ + } + + +typedef struct _EFI_TCP6_PROTOCOL EFI_TCP6_PROTOCOL; + +/// +/// EFI_TCP6_SERVICE_POINT is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + /// + /// The EFI TCPv6 Protocol instance handle that is using this + /// address/port pair. + /// + EFI_HANDLE InstanceHandle; + /// + /// The local IPv6 address to which this TCP instance is bound. Set + /// to 0::/128, if this TCP instance is configured to listen on all + /// available source addresses. + /// + EFI_IPv6_ADDRESS LocalAddress; + /// + /// The local port number in host byte order. + /// + UINT16 LocalPort; + /// + /// The remote IPv6 address. It may be 0::/128 if this TCP instance is + /// not connected to any remote host. + /// + EFI_IPv6_ADDRESS RemoteAddress; + /// + /// The remote port number in host byte order. It may be zero if this + /// TCP instance is not connected to any remote host. + /// + UINT16 RemotePort; +} EFI_TCP6_SERVICE_POINT; + +/// +/// EFI_TCP6_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE DriverHandle; ///< The handle of the driver that creates this entry. + UINT32 ServiceCount; ///< The number of address/port pairs following this data structure. + EFI_TCP6_SERVICE_POINT Services[1]; ///< List of address/port pairs that are currently in use. +} EFI_TCP6_VARIABLE_DATA; + +/// +/// EFI_TCP6_ACCESS_POINT +/// +typedef struct { + /// + /// The local IP address assigned to this TCP instance. The EFI + /// TCPv6 driver will only deliver incoming packets whose + /// destination addresses exactly match the IP address. Set to zero to + /// let the underlying IPv6 driver choose a source address. If not zero + /// it must be one of the configured IP addresses in the underlying + /// IPv6 driver. + /// + EFI_IPv6_ADDRESS StationAddress; + /// + /// The local port number to which this EFI TCPv6 Protocol instance + /// is bound. If the instance doesn't care the local port number, set + /// StationPort to zero to use an ephemeral port. + /// + UINT16 StationPort; + /// + /// The remote IP address to which this EFI TCPv6 Protocol instance + /// is connected. If ActiveFlag is FALSE (i.e. a passive TCPv6 + /// instance), the instance only accepts connections from the + /// RemoteAddress. If ActiveFlag is TRUE the instance will + /// connect to the RemoteAddress, i.e., outgoing segments will be + /// sent to this address and only segments from this address will be + /// delivered to the application. When ActiveFlag is FALSE, it + /// can be set to zero and means that incoming connection requests + /// from any address will be accepted. + /// + EFI_IPv6_ADDRESS RemoteAddress; + /// + /// The remote port to which this EFI TCPv6 Protocol instance + /// connects or from which connection request will be accepted by + /// this EFI TCPv6 Protocol instance. If ActiveFlag is FALSE it + /// can be zero and means that incoming connection request from + /// any port will be accepted. Its value can not be zero when + /// ActiveFlag is TRUE. + /// + UINT16 RemotePort; + /// + /// Set it to TRUE to initiate an active open. Set it to FALSE to + /// initiate a passive open to act as a server. + /// + BOOLEAN ActiveFlag; +} EFI_TCP6_ACCESS_POINT; + +/// +/// EFI_TCP6_OPTION +/// +typedef struct { + /// + /// The size of the TCP receive buffer. + /// + UINT32 ReceiveBufferSize; + /// + /// The size of the TCP send buffer. + /// + UINT32 SendBufferSize; + /// + /// The length of incoming connect request queue for a passive + /// instance. When set to zero, the value is implementation specific. + /// + UINT32 MaxSynBackLog; + /// + /// The maximum seconds a TCP instance will wait for before a TCP + /// connection established. When set to zero, the value is + /// implementation specific. + /// + UINT32 ConnectionTimeout; + /// + ///The number of times TCP will attempt to retransmit a packet on + ///an established connection. When set to zero, the value is + ///implementation specific. + /// + UINT32 DataRetries; + /// + /// How many seconds to wait in the FIN_WAIT_2 states for a final + /// FIN flag before the TCP instance is closed. This timeout is in + /// effective only if the application has called Close() to + /// disconnect the connection completely. It is also called + /// FIN_WAIT_2 timer in other implementations. When set to zero, + /// it should be disabled because the FIN_WAIT_2 timer itself is + /// against the standard. The default value is 60. + /// + UINT32 FinTimeout; + /// + /// How many seconds to wait in TIME_WAIT state before the TCP + /// instance is closed. The timer is disabled completely to provide a + /// method to close the TCP connection quickly if it is set to zero. It + /// is against the related RFC documents. + /// + UINT32 TimeWaitTimeout; + /// + /// The maximum number of TCP keep-alive probes to send before + /// giving up and resetting the connection if no response from the + /// other end. Set to zero to disable keep-alive probe. + /// + UINT32 KeepAliveProbes; + /// + /// The number of seconds a connection needs to be idle before TCP + /// sends out periodical keep-alive probes. When set to zero, the + /// value is implementation specific. It should be ignored if keep- + /// alive probe is disabled. + /// + UINT32 KeepAliveTime; + /// + /// The number of seconds between TCP keep-alive probes after the + /// periodical keep-alive probe if no response. When set to zero, the + /// value is implementation specific. It should be ignored if keep- + /// alive probe is disabled. + /// + UINT32 KeepAliveInterval; + /// + /// Set it to TRUE to enable the Nagle algorithm as defined in + /// RFC896. Set it to FALSE to disable it. + /// + BOOLEAN EnableNagle; + /// + /// Set it to TRUE to enable TCP timestamps option as defined in + /// RFC1323. Set to FALSE to disable it. + /// + BOOLEAN EnableTimeStamp; + /// + /// Set it to TRUE to enable TCP window scale option as defined in + /// RFC1323. Set it to FALSE to disable it. + /// + BOOLEAN EnableWindowScaling; + /// + /// Set it to TRUE to enable selective acknowledge mechanism + /// described in RFC 2018. Set it to FALSE to disable it. + /// Implementation that supports SACK can optionally support + /// DSAK as defined in RFC 2883. + /// + BOOLEAN EnableSelectiveAck; + /// + /// Set it to TRUE to enable path MTU discovery as defined in + /// RFC 1191. Set to FALSE to disable it. + /// + BOOLEAN EnablePathMtuDiscovery; +} EFI_TCP6_OPTION; + +/// +/// EFI_TCP6_CONFIG_DATA +/// +typedef struct { + /// + /// TrafficClass field in transmitted IPv6 packets. + /// + UINT8 TrafficClass; + /// + /// HopLimit field in transmitted IPv6 packets. + /// + UINT8 HopLimit; + /// + /// Used to specify TCP communication end settings for a TCP instance. + /// + EFI_TCP6_ACCESS_POINT AccessPoint; + /// + /// Used to configure the advance TCP option for a connection. If set + /// to NULL, implementation specific options for TCP connection will be used. + /// + EFI_TCP6_OPTION *ControlOption; +} EFI_TCP6_CONFIG_DATA; + +/// +/// EFI_TCP6_CONNECTION_STATE +/// +typedef enum { + Tcp6StateClosed = 0, + Tcp6StateListen = 1, + Tcp6StateSynSent = 2, + Tcp6StateSynReceived = 3, + Tcp6StateEstablished = 4, + Tcp6StateFinWait1 = 5, + Tcp6StateFinWait2 = 6, + Tcp6StateClosing = 7, + Tcp6StateTimeWait = 8, + Tcp6StateCloseWait = 9, + Tcp6StateLastAck = 10 +} EFI_TCP6_CONNECTION_STATE; + +/// +/// EFI_TCP6_COMPLETION_TOKEN +/// is used as a common header for various asynchronous tokens. +/// +typedef struct { + /// + /// The Event to signal after request is finished and Status field is + /// updated by the EFI TCPv6 Protocol driver. + /// + EFI_EVENT Event; + /// + /// The result of the completed operation. + /// + EFI_STATUS Status; +} EFI_TCP6_COMPLETION_TOKEN; + +/// +/// EFI_TCP6_CONNECTION_TOKEN +/// will be set if the active open succeeds or an unexpected +/// error happens. +/// +typedef struct { + /// + /// The Status in the CompletionToken will be set to one of + /// the following values if the active open succeeds or an unexpected + /// error happens: + /// EFI_SUCCESS: The active open succeeds and the instance's + /// state is Tcp6StateEstablished. + /// EFI_CONNECTION_RESET: The connect fails because the connection is reset + /// either by instance itself or the communication peer. + /// EFI_CONNECTION_REFUSED: The receiving or transmission operation fails because this + /// connection is refused. + /// EFI_ABORTED: The active open is aborted. + /// EFI_TIMEOUT: The connection establishment timer expires and + /// no more specific information is available. + /// EFI_NETWORK_UNREACHABLE: The active open fails because + /// an ICMP network unreachable error is received. + /// EFI_HOST_UNREACHABLE: The active open fails because an + /// ICMP host unreachable error is received. + /// EFI_PROTOCOL_UNREACHABLE: The active open fails + /// because an ICMP protocol unreachable error is received. + /// EFI_PORT_UNREACHABLE: The connection establishment + /// timer times out and an ICMP port unreachable error is received. + /// EFI_ICMP_ERROR: The connection establishment timer times + /// out and some other ICMP error is received. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// EFI_SECURITY_VIOLATION: The active open was failed because of IPSec policy check. + /// EFI_NO_MEDIA: There was a media error. + /// + EFI_TCP6_COMPLETION_TOKEN CompletionToken; +} EFI_TCP6_CONNECTION_TOKEN; + +/// +/// EFI_TCP6_LISTEN_TOKEN +/// returns when list operation finishes. +/// +typedef struct { + /// + /// The Status in CompletionToken will be set to the + /// following value if accept finishes: + /// EFI_SUCCESS: A remote peer has successfully established a + /// connection to this instance. A new TCP instance has also been + /// created for the connection. + /// EFI_CONNECTION_RESET: The accept fails because the connection is reset either + /// by instance itself or communication peer. + /// EFI_ABORTED: The accept request has been aborted. + /// EFI_SECURITY_VIOLATION: The accept operation was failed because of IPSec policy check. + /// + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP6_LISTEN_TOKEN; + +/// +/// EFI_TCP6_FRAGMENT_DATA +/// allows multiple receive or transmit buffers to be specified. The +/// purpose of this structure is to provide scattered read and write. +/// +typedef struct { + UINT32 FragmentLength; ///< Length of data buffer in the fragment. + VOID *FragmentBuffer; ///< Pointer to the data buffer in the fragment. +} EFI_TCP6_FRAGMENT_DATA; + +/// +/// EFI_TCP6_RECEIVE_DATA +/// When TCPv6 driver wants to deliver received data to the application, +/// it will pick up the first queued receiving token, update its +/// Token->Packet.RxData then signal the Token->CompletionToken.Event. +/// +typedef struct { + /// + /// Whether the data is urgent. When this flag is set, the instance is in + /// urgent mode. + /// + BOOLEAN UrgentFlag; + /// + /// When calling Receive() function, it is the byte counts of all + /// Fragmentbuffer in FragmentTable allocated by user. + /// When the token is signaled by TCPv6 driver it is the length of + /// received data in the fragments. + /// + UINT32 DataLength; + /// + /// Number of fragments. + /// + UINT32 FragmentCount; + /// + /// An array of fragment descriptors. + /// + EFI_TCP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP6_RECEIVE_DATA; + +/// +/// EFI_TCP6_TRANSMIT_DATA +/// The EFI TCPv6 Protocol user must fill this data structure before sending a packet. +/// The packet may contain multiple buffers in non-continuous memory locations. +/// +typedef struct { + /// + /// Push If TRUE, data must be transmitted promptly, and the PUSH bit in + /// the last TCP segment created will be set. If FALSE, data + /// transmission may be delayed to combine with data from + /// subsequent Transmit()s for efficiency. + /// + BOOLEAN Push; + /// + /// The data in the fragment table are urgent and urgent point is in + /// effect if TRUE. Otherwise those data are NOT considered urgent. + /// + BOOLEAN Urgent; + /// + /// Length of the data in the fragments. + /// + UINT32 DataLength; + /// + /// Number of fragments. + /// + UINT32 FragmentCount; + /// + /// An array of fragment descriptors. + /// + EFI_TCP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP6_TRANSMIT_DATA; + +/// +/// EFI_TCP6_IO_TOKEN +/// returns When transmission finishes or meets any unexpected error. +/// +typedef struct { + /// + /// When transmission finishes or meets any unexpected error it will + /// be set to one of the following values: + /// EFI_SUCCESS: The receiving or transmission operation + /// completes successfully. + /// EFI_CONNECTION_FIN: The receiving operation fails because the communication peer + /// has closed the connection and there is no more data in the + /// receive buffer of the instance. + /// EFI_CONNECTION_RESET: The receiving or transmission operation fails + /// because this connection is reset either by instance + /// itself or the communication peer. + /// EFI_ABORTED: The receiving or transmission is aborted. + /// EFI_TIMEOUT: The transmission timer expires and no more + /// specific information is available. + /// EFI_NETWORK_UNREACHABLE: The transmission fails + /// because an ICMP network unreachable error is received. + /// EFI_HOST_UNREACHABLE: The transmission fails because an + /// ICMP host unreachable error is received. + /// EFI_PROTOCOL_UNREACHABLE: The transmission fails + /// because an ICMP protocol unreachable error is received. + /// EFI_PORT_UNREACHABLE: The transmission fails and an + /// ICMP port unreachable error is received. + /// EFI_ICMP_ERROR: The transmission fails and some other + /// ICMP error is received. + /// EFI_DEVICE_ERROR: An unexpected system or network error occurs. + /// EFI_SECURITY_VIOLATION: The receiving or transmission + /// operation was failed because of IPSec policy check + /// EFI_NO_MEDIA: There was a media error. + /// + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + union { + /// + /// When this token is used for receiving, RxData is a pointer to + /// EFI_TCP6_RECEIVE_DATA. + /// + EFI_TCP6_RECEIVE_DATA *RxData; + /// + /// When this token is used for transmitting, TxData is a pointer to + /// EFI_TCP6_TRANSMIT_DATA. + /// + EFI_TCP6_TRANSMIT_DATA *TxData; + } Packet; +} EFI_TCP6_IO_TOKEN; + +/// +/// EFI_TCP6_CLOSE_TOKEN +/// returns when close operation finishes. +/// +typedef struct { + /// + /// When close finishes or meets any unexpected error it will be set + /// to one of the following values: + /// EFI_SUCCESS: The close operation completes successfully. + /// EFI_ABORTED: User called configure with NULL without close stopping. + /// EFI_SECURITY_VIOLATION: The close operation was failed because of IPSec policy check. + /// + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + /// + /// Abort the TCP connection on close instead of the standard TCP + /// close process when it is set to TRUE. This option can be used to + /// satisfy a fast disconnect. + /// + BOOLEAN AbortOnClose; +} EFI_TCP6_CLOSE_TOKEN; + +/** + Get the current operational status. + + The GetModeData() function copies the current operational settings of this EFI TCPv6 + Protocol instance into user-supplied buffers. This function can also be used to retrieve + the operational setting of underlying drivers such as IPv6, MNP, or SNP. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[out] Tcp6State The buffer in which the current TCP state is returned. + @param[out] Tcp6ConfigData The buffer in which the current TCP configuration is returned. + @param[out] Ip6ModeData The buffer in which the current IPv6 configuration data used by + the TCP instance is returned. + @param[out] MnpConfigData The buffer in which the current MNP configuration data used + indirectly by the TCP instance is returned. + @param[out] SnpModeData The buffer in which the current SNP mode data used indirectly by + the TCP instance is returned. + + @retval EFI_SUCCESS The mode data was read. + @retval EFI_NOT_STARTED No configuration data is available because this instance hasn't + been started. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_GET_MODE_DATA)( + IN EFI_TCP6_PROTOCOL *This, + OUT EFI_TCP6_CONNECTION_STATE *Tcp6State OPTIONAL, + OUT EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL, + OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +/** + Initialize or brutally reset the operational parameters for this EFI TCPv6 instance. + + The Configure() function does the following: + - Initialize this TCP instance, i.e., initialize the communication end settings and + specify active open or passive open for an instance. + - Reset this TCP instance brutally, i.e., cancel all pending asynchronous tokens, flush + transmission and receiving buffer directly without informing the communication peer. + + No other TCPv6 Protocol operation except Poll() can be executed by this instance until + it is configured properly. For an active TCP instance, after a proper configuration it + may call Connect() to initiates the three-way handshake. For a passive TCP instance, + its state will transit to Tcp6StateListen after configuration, and Accept() may be + called to listen the incoming TCP connection requests. If Tcp6ConfigData is set to NULL, + the instance is reset. Resetting process will be done brutally, the state machine will + be set to Tcp6StateClosed directly, the receive queue and transmit queue will be flushed, + and no traffic is allowed through this instance. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] Tcp6ConfigData Pointer to the configure data to configure the instance. + If Tcp6ConfigData is set to NULL, the instance is reset. + + @retval EFI_SUCCESS The operational settings are set, changed, or reset + successfully. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for + use. + @retval EFI_INVALID_PARAMETER One or more of the following conditions are TRUE: + - This is NULL. + - Tcp6ConfigData->AccessPoint.StationAddress is neither zero nor + one of the configured IP addresses in the underlying IPv6 driver. + - Tcp6ConfigData->AccessPoint.RemoteAddress isn't a valid unicast + IPv6 address. + - Tcp6ConfigData->AccessPoint.RemoteAddress is zero or + Tcp6ConfigData->AccessPoint.RemotePort is zero when + Tcp6ConfigData->AccessPoint.ActiveFlag is TRUE. + - A same access point has been configured in other TCP + instance properly. + @retval EFI_ACCESS_DENIED Configuring TCP instance when it is configured without + calling Configure() with NULL to reset it. + @retval EFI_UNSUPPORTED One or more of the control options are not supported in + the implementation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when + executing Configure(). + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CONFIGURE)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL + ); + +/** + Initiate a nonblocking TCP connection request for an active TCP instance. + + The Connect() function will initiate an active open to the remote peer configured + in current TCP instance if it is configured active. If the connection succeeds or + fails due to any error, the ConnectionToken->CompletionToken.Event will be signaled + and ConnectionToken->CompletionToken.Status will be updated accordingly. This + function can only be called for the TCP instance in Tcp6StateClosed state. The + instance will transfer into Tcp6StateSynSent if the function returns EFI_SUCCESS. + If TCP three-way handshake succeeds, its state will become Tcp6StateEstablished, + otherwise, the state will return to Tcp6StateClosed. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] ConnectionToken Pointer to the connection token to return when the TCP three + way handshake finishes. + + @retval EFI_SUCCESS The connection request is successfully initiated and the state of + this TCP instance has been changed to Tcp6StateSynSent. + @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE: + - This instance is not configured as an active one. + - This instance is not in Tcp6StateClosed state. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ConnectionToken is NULL. + - ConnectionToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to initiate the active open. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CONNECT)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_CONNECTION_TOKEN *ConnectionToken + ); + +/** + Listen on the passive instance to accept an incoming connection request. This is a + nonblocking operation. + + The Accept() function initiates an asynchronous accept request to wait for an incoming + connection on the passive TCP instance. If a remote peer successfully establishes a + connection with this instance, a new TCP instance will be created and its handle will + be returned in ListenToken->NewChildHandle. The newly created instance is configured + by inheriting the passive instance's configuration and is ready for use upon return. + The new instance is in the Tcp6StateEstablished state. + + The ListenToken->CompletionToken.Event will be signaled when a new connection is + accepted, user aborts the listen or connection is reset. + + This function only can be called when current TCP instance is in Tcp6StateListen state. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] ListenToken Pointer to the listen token to return when operation finishes. + + + @retval EFI_SUCCESS The listen token has been queued successfully. + @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following are TRUE: + - This instance is not a passive instance. + - This instance is not in Tcp6StateListen state. + - The same listen token has already existed in the listen + token queue of this TCP instance. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ListenToken is NULL. + - ListentToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_ACCEPT)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_LISTEN_TOKEN *ListenToken + ); + +/** + Queues outgoing data into the transmit queue. + + The Transmit() function queues a sending request to this TCP instance along with the + user data. The status of the token is updated and the event in the token will be + signaled once the data is sent out or some error occurs. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] Token Pointer to the completion token to queue to the transmit queue. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a + source address for this instance, but no source address was + available for use. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - Token is NULL. + - Token->CompletionToken.Event is NULL. + - Token->Packet.TxData is NULL. + - Token->Packet.FragmentCount is zero. + - Token->Packet.DataLength is not equal to the sum of fragment lengths. + @retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE: + - A transmit completion token with the same Token-> + CompletionToken.Event was already in the + transmission queue. + - The current instance is in Tcp6StateClosed state. + - The current instance is a passive one and it is in + Tcp6StateListen state. + - User has called Close() to disconnect this connection. + @retval EFI_NOT_READY The completion token could not be queued because the + transmit queue is full. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of resource + shortage. + @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_TRANSMIT)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_IO_TOKEN *Token + ); + +/** + Places an asynchronous receive request into the receiving queue. + + The Receive() function places a completion token into the receive packet queue. This + function is always asynchronous. The caller must allocate the Token->CompletionToken.Event + and the FragmentBuffer used to receive data. The caller also must fill the DataLength which + represents the whole length of all FragmentBuffer. When the receive operation completes, the + EFI TCPv6 Protocol driver updates the Token->CompletionToken.Status and Token->Packet.RxData + fields and the Token->CompletionToken.Event is signaled. If got data the data and its length + will be copied into the FragmentTable, at the same time the full length of received data will + be recorded in the DataLength fields. Providing a proper notification function and context + for the event will enable the user to receive the notification and receiving status. That + notification function is guaranteed to not be re-entered. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] Token Pointer to a token that is associated with the receive data + descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for use. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token->CompletionToken.Event is NULL. + - Token->Packet.RxData is NULL. + - Token->Packet.RxData->DataLength is 0. + - The Token->Packet.RxData->DataLength is not the + sum of all FragmentBuffer length in FragmentTable. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of + system resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + The EFI TCPv6 Protocol instance has been reset to startup defaults. + @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE: + - A receive completion token with the same Token->CompletionToken.Event + was already in the receive queue. + - The current instance is in Tcp6StateClosed state. + - The current instance is a passive one and it is in + Tcp6StateListen state. + - User has called Close() to disconnect this connection. + @retval EFI_CONNECTION_FIN The communication peer has closed the connection and there is no + any buffered data in the receive buffer of this instance + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_RECEIVE)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_IO_TOKEN *Token + ); + +/** + Disconnecting a TCP connection gracefully or reset a TCP connection. This function is a + nonblocking operation. + + Initiate an asynchronous close token to TCP driver. After Close() is called, any buffered + transmission data will be sent by TCP driver and the current instance will have a graceful close + working flow described as RFC 793 if AbortOnClose is set to FALSE, otherwise, a rest packet + will be sent by TCP driver to fast disconnect this connection. When the close operation completes + successfully the TCP instance is in Tcp6StateClosed state, all pending asynchronous + operations are signaled and any buffers used for TCP network traffic are flushed. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] CloseToken Pointer to the close token to return when operation finishes. + + @retval EFI_SUCCESS The Close() is called successfully. + @retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following are TRUE: + - CloseToken or CloseToken->CompletionToken.Event is already in use. + - Previous Close() call on this instance has not finished. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - CloseToken is NULL. + - CloseToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CLOSE)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_CLOSE_TOKEN *CloseToken + ); + +/** + Abort an asynchronous connection, listen, transmission or receive request. + + The Cancel() function aborts a pending connection, listen, transmit or + receive request. + + If Token is not NULL and the token is in the connection, listen, transmission + or receive queue when it is being cancelled, its Token->Status will be set + to EFI_ABORTED and then Token->Event will be signaled. + + If the token is not in one of the queues, which usually means that the + asynchronous operation has completed, EFI_NOT_FOUND is returned. + + If Token is NULL all asynchronous token issued by Connect(), Accept(), + Transmit() and Receive() will be aborted. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + @param[in] Token Pointer to a token that has been issued by + EFI_TCP6_PROTOCOL.Connect(), + EFI_TCP6_PROTOCOL.Accept(), + EFI_TCP6_PROTOCOL.Transmit() or + EFI_TCP6_PROTOCOL.Receive(). If NULL, all pending + tokens issued by above four functions will be aborted. Type + EFI_TCP6_COMPLETION_TOKEN is defined in + EFI_TCP_PROTOCOL.Connect(). + + @retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event + is signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance hasn't been configured. + @retval EFI_NOT_FOUND The asynchronous I/O request isn't found in the transmission or + receive queue. It has either completed or wasn't issued by + Transmit() and Receive(). + @retval EFI_UNSUPPORTED The implementation does not support this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CANCEL)( + IN EFI_TCP6_PROTOCOL *This, + IN EFI_TCP6_COMPLETION_TOKEN *Token OPTIONAL + ); + +/** + Poll to receive incoming data and transmit outgoing segments. + + The Poll() function increases the rate that data is moved between the network + and application and can be called when the TCP instance is created successfully. + Its use is optional. + + @param[in] This Pointer to the EFI_TCP6_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmission or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_POLL)( + IN EFI_TCP6_PROTOCOL *This + ); + +/// +/// EFI_TCP6_PROTOCOL +/// defines the EFI TCPv6 Protocol child to be used by any network drivers or +/// applications to send or receive data stream. It can either listen on a +/// specified port as a service or actively connect to remote peer as a client. +/// Each instance has its own independent settings. +/// +struct _EFI_TCP6_PROTOCOL { + EFI_TCP6_GET_MODE_DATA GetModeData; + EFI_TCP6_CONFIGURE Configure; + EFI_TCP6_CONNECT Connect; + EFI_TCP6_ACCEPT Accept; + EFI_TCP6_TRANSMIT Transmit; + EFI_TCP6_RECEIVE Receive; + EFI_TCP6_CLOSE Close; + EFI_TCP6_CANCEL Cancel; + EFI_TCP6_POLL Poll; +}; + +extern EFI_GUID gEfiTcp6ServiceBindingProtocolGuid; +extern EFI_GUID gEfiTcp6ProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timer.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timer.h new file mode 100644 index 0000000..0b62778 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timer.h @@ -0,0 +1,180 @@ +/** @file + Timer Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + This code is used to provide the timer tick for the DXE core. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_TIMER_H__ +#define __ARCH_PROTOCOL_TIMER_H__ + +/// +/// Global ID for the Timer Architectural Protocol +/// +#define EFI_TIMER_ARCH_PROTOCOL_GUID \ + { 0x26baccb3, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +/// +/// Declare forward reference for the Timer Architectural Protocol +/// +typedef struct _EFI_TIMER_ARCH_PROTOCOL EFI_TIMER_ARCH_PROTOCOL; + +/** + This function of this type is called when a timer interrupt fires. This + function executes at TPL_HIGH_LEVEL. The DXE Core will register a function + of this type to be called for the timer interrupt, so it can know how much + time has passed. This information is used to signal timer based events. + + @param Time Time since the last timer interrupt in 100 ns units. This will + typically be TimerPeriod, but if a timer interrupt is missed, and the + EFI_TIMER_ARCH_PROTOCOL driver can detect missed interrupts, then Time + will contain the actual amount of time since the last interrupt. + + None. + +**/ +typedef +VOID +(EFIAPI *EFI_TIMER_NOTIFY)( + IN UINT64 Time + ); + +/** + This function registers the handler NotifyFunction so it is called every time + the timer interrupt fires. It also passes the amount of time since the last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS is + returned. If the CPU does not support registering a timer interrupt handler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to unregister a handler when a handler is not registered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR + is returned. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when a timer interrupt fires. This + function executes at TPL_HIGH_LEVEL. The DXE Core will + register a handler for the timer interrupt, so it can know + how much time has passed. This information is used to + signal timer based events. NULL will unregister the handler. + + @retval EFI_SUCCESS The timer handler was registered. + @retval EFI_UNSUPPORTED The platform does not support timer interrupts. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not + previously registered. + @retval EFI_DEVICE_ERROR The timer handler could not be registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_REGISTER_HANDLER)( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction +); + +/** + This function adjusts the period of timer interrupts to the value specified + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust the + interrupt controller so that a CPU interrupt is not generated when the timer + interrupt fires. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is + returned. If the timer is programmable, then the timer period + will be rounded up to the nearest timer period that is supported + by the timer hardware. If TimerPeriod is set to 0, then the + timer interrupts will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_SET_TIMER_PERIOD)( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ); + +/** + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is + returned, then the timer is currently disabled. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If + 0 is returned, then the timer is currently disabled. + + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_GET_TIMER_PERIOD)( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ); + +/** + This function generates a soft timer interrupt. If the platform does not support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() + service, then a soft timer interrupt will be generated. If the timer interrupt is + enabled when this service is called, then the registered handler will be invoked. The + registered handler should not be able to distinguish a hardware-generated timer + interrupt from a software-generated timer interrupt. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + @retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_GENERATE_SOFT_INTERRUPT)( + IN EFI_TIMER_ARCH_PROTOCOL *This + ); + + +/// +/// This protocol provides the services to initialize a periodic timer +/// interrupt, and to register a handler that is called each time the timer +/// interrupt fires. It may also provide a service to adjust the rate of the +/// periodic timer interrupt. When a timer interrupt occurs, the handler is +/// passed the amount of time that has passed since the previous timer +/// interrupt. +/// +struct _EFI_TIMER_ARCH_PROTOCOL { + EFI_TIMER_REGISTER_HANDLER RegisterHandler; + EFI_TIMER_SET_TIMER_PERIOD SetTimerPeriod; + EFI_TIMER_GET_TIMER_PERIOD GetTimerPeriod; + EFI_TIMER_GENERATE_SOFT_INTERRUPT GenerateSoftInterrupt; +}; + +extern EFI_GUID gEfiTimerArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timestamp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timestamp.h new file mode 100644 index 0000000..549c792 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Timestamp.h @@ -0,0 +1,101 @@ +/** @file + EFI Timestamp Protocol as defined in UEFI2.4 Specification. + Used to provide a platform independent interface for retrieving a high resolution timestamp counter. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.4 + +**/ + +#ifndef __EFI_TIME_STAMP_PROTOCOL_H__ +#define __EFI_TIME_STAMP_PROTOCOL_H__ + + +#define EFI_TIMESTAMP_PROTOCOL_GUID \ + { 0xafbfde41, 0x2e6e, 0x4262, {0xba, 0x65, 0x62, 0xb9, 0x23, 0x6e, 0x54, 0x95 } } + +/// +/// Declare forward reference for the Time Stamp Protocol +/// +typedef struct _EFI_TIMESTAMP_PROTOCOL EFI_TIMESTAMP_PROTOCOL; + +/// +/// EFI_TIMESTAMP_PROPERTIES +/// +typedef struct { + /// + /// The frequency of the timestamp counter in Hz. + /// + UINT64 Frequency; + /// + /// The value that the timestamp counter ends with immediately before it rolls over. + /// For example, a 64-bit free running counter would have an EndValue of 0xFFFFFFFFFFFFFFFF. + /// A 24-bit free running counter would have an EndValue of 0xFFFFFF. + /// + UINT64 EndValue; +} EFI_TIMESTAMP_PROPERTIES; + +/** + Retrieves the current value of a 64-bit free running timestamp counter. + + The counter shall count up in proportion to the amount of time that has passed. The counter value + will always roll over to zero. The properties of the counter can be retrieved from GetProperties(). + The caller should be prepared for the function to return the same value twice across successive calls. + The counter value will not go backwards other than when wrapping, as defined by EndValue in GetProperties(). + The frequency of the returned timestamp counter value must remain constant. Power management operations that + affect clocking must not change the returned counter frequency. The quantization of counter value updates may + vary as long as the value reflecting time passed remains consistent. + + @param None. + + @retval The current value of the free running timestamp counter. + +**/ +typedef +UINT64 +(EFIAPI *TIMESTAMP_GET)( + VOID + ); + +/** + Obtains timestamp counter properties including frequency and value limits. + + @param[out] Properties The properties of the timestamp counter. + + @retval EFI_SUCCESS The properties were successfully retrieved. + @retval EFI_DEVICE_ERROR An error occurred trying to retrieve the properties of the timestamp + counter subsystem. Properties is not pedated. + @retval EFI_INVALID_PARAMETER Properties is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *TIMESTAMP_GET_PROPERTIES)( + OUT EFI_TIMESTAMP_PROPERTIES *Properties + ); + + + +/// +/// EFI_TIMESTAMP_PROTOCOL +/// The protocol provides a platform independent interface for retrieving a high resolution +/// timestamp counter. +/// +struct _EFI_TIMESTAMP_PROTOCOL { + TIMESTAMP_GET GetTimestamp; + TIMESTAMP_GET_PROPERTIES GetProperties; +}; + +extern EFI_GUID gEfiTimestampProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tls.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tls.h new file mode 100644 index 0000000..6bb8d77 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Tls.h @@ -0,0 +1,471 @@ +/** @file + EFI TLS Protocols as defined in UEFI 2.5. + + The EFI TLS Service Binding Protocol is used to locate EFI TLS Protocol drivers + to create and destroy child of the driver to communicate with other host using + TLS protocol. + The EFI TLS Protocol provides the ability to manage TLS session. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_TLS_PROTOCOL_H__ +#define __EFI_TLS_PROTOCOL_H__ + +/// +/// The EFI TLS Service Binding Protocol is used to locate EFI TLS Protocol drivers to +/// create and destroy child of the driver to communicate with other host using TLS +/// protocol. +/// +#define EFI_TLS_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d } \ + } + +/// +/// The EFI TLS protocol provides the ability to manage TLS session. +/// +#define EFI_TLS_PROTOCOL_GUID \ + { \ + 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 0x43, 0x90 } \ + } + +typedef struct _EFI_TLS_PROTOCOL EFI_TLS_PROTOCOL; + +/// +/// EFI_TLS_SESSION_DATA_TYPE +/// +typedef enum { + /// + /// Session Configuration + /// + + /// + /// TLS session Version. The corresponding Data is of type EFI_TLS_VERSION. + /// + EfiTlsVersion, + /// + /// TLS session as client or as server. The corresponding Data is of + /// EFI_TLS_CONNECTION_END. + /// + EfiTlsConnectionEnd, + /// + /// A priority list of preferred algorithms for the TLS session. + /// The corresponding Data is a list of EFI_TLS_CIPHER. + /// + EfiTlsCipherList, + /// + /// TLS session compression method. + /// The corresponding Data is of type EFI_TLS_COMPRESSION. + /// + EfiTlsCompressionMethod, + /// + /// TLS session extension data. + /// The corresponding Data is a list of type EFI_TLS_EXTENSION . + /// + EfiTlsExtensionData, + /// + /// TLS session verify method. + /// The corresponding Data is of type EFI_TLS_VERIFY. + /// + EfiTlsVerifyMethod, + /// + /// TLS session data session ID. + /// For SetSessionData(), it is TLS session ID used for session resumption. + /// For GetSessionData(), it is the TLS session ID used for current session. + /// The corresponding Data is of type EFI_TLS_SESSION_ID. + /// + EfiTlsSessionID, + /// + /// TLS session data session state. + /// The corresponding Data is of type EFI_TLS_SESSION_STATE. + /// + EfiTlsSessionState, + + /// + /// Session information + /// + + /// + /// TLS session data client random. + /// The corresponding Data is of type EFI_TLS_RANDOM. + /// + EfiTlsClientRandom, + /// + /// TLS session data server random. + /// The corresponding Data is of type EFI_TLS_RANDOM. + /// + EfiTlsServerRandom, + /// + /// TLS session data key material. + /// The corresponding Data is of type EFI_TLS_MASTER_SECRET. + /// + EfiTlsKeyMaterial, + + EfiTlsSessionDataTypeMaximum + +} EFI_TLS_SESSION_DATA_TYPE; + +/// +/// EFI_TLS_VERSION +/// Note: The TLS version definition is from SSL3.0 to the latest TLS (e.g. 1.2). +/// SSL2.0 is obsolete and should not be used. +/// +typedef struct { + UINT8 Major; + UINT8 Minor; +} EFI_TLS_VERSION; + +/// +/// EFI_TLS_CONNECTION_END to define TLS session as client or server. +/// +typedef enum { + EfiTlsClient, + EfiTlsServer, +} EFI_TLS_CONNECTION_END; + +/// +/// EFI_TLS_CIPHER +/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC 5246, A.4.1. +/// Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher +/// Suite Registry of IANA. +/// +#pragma pack (1) +typedef struct { + UINT8 Data1; + UINT8 Data2; +} EFI_TLS_CIPHER; +#pragma pack () + +/// +/// EFI_TLS_COMPRESSION +/// Note: The value of EFI_TLS_COMPRESSION definition is from "RFC 3749". +/// +typedef UINT8 EFI_TLS_COMPRESSION; + +/// +/// EFI_TLS_EXTENSION +/// Note: The definition of EFI_TLS_EXTENSION if from "RFC 5246 A.4.1. +/// Hello Messages". +/// +#pragma pack (1) +typedef struct { + UINT16 ExtensionType; + UINT16 Length; + UINT8 Data[1]; +} EFI_TLS_EXTENSION; +#pragma pack () + +/// +/// EFI_TLS_VERIFY +/// Use either EFI_TLS_VERIFY_NONE or EFI_TLS_VERIFY_PEER, the last two options +/// are 'ORed' with EFI_TLS_VERIFY_PEER if they are desired. +/// +typedef UINT32 EFI_TLS_VERIFY; +/// +/// No certificates will be sent or the TLS/SSL handshake will be continued regardless +/// of the certificate verification result. +/// +#define EFI_TLS_VERIFY_NONE 0x0 +/// +/// The TLS/SSL handshake is immediately terminated with an alert message containing +/// the reason for the certificate verification failure. +/// +#define EFI_TLS_VERIFY_PEER 0x1 +/// +/// TLS session will fail peer certificate is absent. +/// +#define EFI_TLS_VERIFY_FAIL_IF_NO_PEER_CERT 0x2 +/// +/// TLS session only verify client once, and doesn't request certificate during +/// re-negotiation. +/// +#define EFI_TLS_VERIFY_CLIENT_ONCE 0x4 + +/// +/// EFI_TLS_RANDOM +/// Note: The definition of EFI_TLS_RANDOM is from "RFC 5246 A.4.1. +/// Hello Messages". +/// +#pragma pack (1) +typedef struct { + UINT32 GmtUnixTime; + UINT8 RandomBytes[28]; +} EFI_TLS_RANDOM; +#pragma pack () + +/// +/// EFI_TLS_MASTER_SECRET +/// Note: The definition of EFI_TLS_MASTER_SECRET is from "RFC 5246 8.1. +/// Computing the Master Secret". +/// +#pragma pack (1) +typedef struct { + UINT8 Data[48]; +} EFI_TLS_MASTER_SECRET; +#pragma pack () + +/// +/// EFI_TLS_SESSION_ID +/// Note: The definition of EFI_TLS_SESSION_ID is from "RFC 5246 A.4.1. Hello Messages". +/// +#define MAX_TLS_SESSION_ID_LENGTH 32 +#pragma pack (1) +typedef struct { + UINT16 Length; + UINT8 Data[MAX_TLS_SESSION_ID_LENGTH]; +} EFI_TLS_SESSION_ID; +#pragma pack () + +/// +/// EFI_TLS_SESSION_STATE +/// +typedef enum { + /// + /// When a new child of TLS protocol is created, the initial state of TLS session + /// is EfiTlsSessionNotStarted. + /// + EfiTlsSessionNotStarted, + /// + /// The consumer can call BuildResponsePacket() with NULL to get ClientHello to + /// start the TLS session. Then the status is EfiTlsSessionHandShaking. + /// + EfiTlsSessionHandShaking, + /// + /// During handshake, the consumer need call BuildResponsePacket() with input + /// data from peer, then get response packet and send to peer. After handshake + /// finish, the TLS session status becomes EfiTlsSessionDataTransferring, and + /// consumer can use ProcessPacket() for data transferring. + /// + EfiTlsSessionDataTransferring, + /// + /// Finally, if consumer wants to active close TLS session, consumer need + /// call SetSessionData to set TLS session state to EfiTlsSessionClosing, and + /// call BuildResponsePacket() with NULL to get CloseNotify alert message, + /// and sent it out. + /// + EfiTlsSessionClosing, + /// + /// If any error happen during parsing ApplicationData content type, EFI_ABORT + /// will be returned by ProcessPacket(), and TLS session state will become + /// EfiTlsSessionError. Then consumer need call BuildResponsePacket() with + /// NULL to get alert message and sent it out. + /// + EfiTlsSessionError, + + EfiTlsSessionStateMaximum + +} EFI_TLS_SESSION_STATE; + +/// +/// EFI_TLS_FRAGMENT_DATA +/// +typedef struct { + /// + /// Length of data buffer in the fragment. + /// + UINT32 FragmentLength; + /// + /// Pointer to the data buffer in the fragment. + /// + VOID *FragmentBuffer; +} EFI_TLS_FRAGMENT_DATA; + +/// +/// EFI_TLS_CRYPT_MODE +/// +typedef enum { + /// + /// Encrypt data provided in the fragment buffers. + /// + EfiTlsEncrypt, + /// + /// Decrypt data provided in the fragment buffers. + /// + EfiTlsDecrypt, +} EFI_TLS_CRYPT_MODE; + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All session data should + be set before BuildResponsePacket() invoked. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in] Data Pointer to session data. + @param[in] DataSize Total size of session data. + + @retval EFI_SUCCESS The TLS session data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_ACCESS_DENIED If the DataType is one of below: + EfiTlsClientRandom + EfiTlsServerRandom + EfiTlsKeyMaterial + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionStateNotStarted. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TLS_SET_SESSION_DATA) ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get TLS session data. + + The GetSessionData() function return the TLS session information. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in, out] Data Pointer to session data. + @param[in, out] DataSize Total size of session data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS session data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The TLS session data is not found. + @retval EFI_NOT_READY The DataType is not ready in current session state. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TLS_GET_SESSION_DATA) ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ); + +/** + Build response packet according to TLS state machine. This function is only valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in response to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session + will be initiated and the response packet needs to be ClientHello. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS + session will be closed and response packet needs to be CloseNotify. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS + session has errors and the response packet needs to be Alert message based on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL + means TLS need initiate the TLS session and response + packet need to be ClientHello. + @param[in] RequestSize Packet size in bytes for the most recently received TLS + packet. 0 is only valid when RequestBuffer is NULL. + @param[out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + RequestBuffer is NULL but RequestSize is NOT 0. + RequestSize is 0 but RequestBuffer is NOT NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready to build + ResponsePacket. + @retval EFI_ABORTED Something wrong build response packet. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TLS_BUILD_RESPONSE_PACKET) ( + IN EFI_TLS_PROTOCOL *This, + IN UINT8 *RequestBuffer, OPTIONAL + IN UINTN RequestSize, OPTIONAL + OUT UINT8 *Buffer, OPTIONAL + IN OUT UINTN *BufferSize + ); + +/** + Decrypt or encrypt TLS packet during session. This function is only valid after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP packet. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take + responsible to handle the original FragmentTable while + it may be reallocated in TLS driver. If CryptMode is + EfiTlsEncrypt, on input these fragments contain the TLS + header and plain text TLS APP payload; on output these + fragments contain the TLS header and cipher text TLS + APP payload. If CryptMode is EfiTlsDecrypt, on input + these fragments contain the TLS header and cipher text + TLS APP payload; on output these fragments contain the + TLS header and plain text TLS APP payload. + @param[in] FragmentCount Number of fragment. + @param[in] CryptMode Crypt mode. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + FragmentTable is NULL. + FragmentCount is NULL. + CryptoMode is invalid. + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionDataTransferring. + @retval EFI_ABORTED Something wrong decryption the message. TLS session + status will become EfiTlsSessionError. The caller need + call BuildResponsePacket() to generate Error Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TLS_PROCESS_PACKET) ( + IN EFI_TLS_PROTOCOL *This, + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_TLS_CRYPT_MODE CryptMode + ); + +/// +/// The EFI_TLS_PROTOCOL is used to create, destroy and manage TLS session. +/// For detail of TLS, please refer to TLS related RFC. +/// +struct _EFI_TLS_PROTOCOL { + EFI_TLS_SET_SESSION_DATA SetSessionData; + EFI_TLS_GET_SESSION_DATA GetSessionData; + EFI_TLS_BUILD_RESPONSE_PACKET BuildResponsePacket; + EFI_TLS_PROCESS_PACKET ProcessPacket; +}; + +extern EFI_GUID gEfiTlsServiceBindingProtocolGuid; +extern EFI_GUID gEfiTlsProtocolGuid; + +#endif // __EFI_TLS_PROTOCOL_H__ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TlsConfig.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TlsConfig.h new file mode 100644 index 0000000..512fa3b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TlsConfig.h @@ -0,0 +1,133 @@ +/** @file + EFI TLS Configuration Protocol as defined in UEFI 2.5. + The EFI TLS Configuration Protocol provides a way to set and get TLS configuration. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ +#ifndef __EFI_TLS_CONFIGURATION_PROTOCOL_H__ +#define __EFI_TLS_CONFIGURATION_PROTOCOL_H__ + +/// +/// The EFI Configuration protocol provides a way to set and get TLS configuration. +/// +#define EFI_TLS_CONFIGURATION_PROTOCOL_GUID \ + { \ + 0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d } \ + } + +typedef struct _EFI_TLS_CONFIGURATION_PROTOCOL EFI_TLS_CONFIGURATION_PROTOCOL; + +/// +/// EFI_TLS_CONFIG_DATA_TYPE +/// +typedef enum { + /// + /// Local host configuration data: public certificate data. + /// This data should be DER-encoded binary X.509 certificate + /// or PEM-encoded X.509 certificate. + /// + EfiTlsConfigDataTypeHostPublicCert, + /// + /// Local host configuration data: private key data. + /// + EfiTlsConfigDataTypeHostPrivateKey, + /// + /// CA certificate to verify peer. This data should be PEM-encoded + /// RSA or PKCS#8 private key. + /// + EfiTlsConfigDataTypeCACertificate, + /// + /// CA-supplied Certificate Revocation List data. This data should + /// be DER-encoded CRL data. + /// + EfiTlsConfigDataTypeCertRevocationList, + + EfiTlsConfigDataTypeMaximum + +} EFI_TLS_CONFIG_DATA_TYPE; + +/** + Set TLS configuration data. + + The SetData() function sets TLS configuration to non-volatile storage or volatile + storage. + + @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance. + @param[in] DataType Configuration data type. + @param[in] Data Pointer to configuration data. + @param[in] DataSize Total size of configuration data. + + @retval EFI_SUCCESS The TLS configuration data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TLS_CONFIGURATION_SET_DATA)( + IN EFI_TLS_CONFIGURATION_PROTOCOL *This, + IN EFI_TLS_CONFIG_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get TLS configuration data. + + The GetData() function gets TLS configuration. + + @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance. + @param[in] DataType Configuration data type. + @param[in, out] Data Pointer to configuration data. + @param[in, out] DataSize Total size of configuration data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The TLS configuration data is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TLS_CONFIGURATION_GET_DATA)( + IN EFI_TLS_CONFIGURATION_PROTOCOL *This, + IN EFI_TLS_CONFIG_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ); + +/// +/// The EFI_TLS_CONFIGURATION_PROTOCOL is designed to provide a way to set and get +/// TLS configuration, such as Certificate, private key data. +/// +struct _EFI_TLS_CONFIGURATION_PROTOCOL { + EFI_TLS_CONFIGURATION_SET_DATA SetData; + EFI_TLS_CONFIGURATION_GET_DATA GetData; +}; + +extern EFI_GUID gEfiTlsConfigurationProtocolGuid; + +#endif //__EFI_TLS_CONFIGURATION_PROTOCOL_H__ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TrEEProtocol.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TrEEProtocol.h new file mode 100644 index 0000000..6beac44 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/TrEEProtocol.h @@ -0,0 +1,249 @@ +/** @file + This protocol is defined to abstract TPM2 hardware access in boot phase. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __TREE_H__ +#define __TREE_H__ + +#include +#include + +#define EFI_TREE_PROTOCOL_GUID \ + {0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f} + +typedef struct _EFI_TREE_PROTOCOL EFI_TREE_PROTOCOL; + +typedef struct _TREE_VERSION { + UINT8 Major; + UINT8 Minor; +} TREE_VERSION; + +typedef UINT32 TREE_EVENT_LOG_BITMAP; +typedef UINT32 TREE_EVENT_LOG_FORMAT; + +#define TREE_EVENT_LOG_FORMAT_TCG_1_2 0x00000001 + +typedef struct _TREE_BOOT_SERVICE_CAPABILITY { + // + // Allocated size of the structure passed in + // + UINT8 Size; + // + // Version of the TREE_BOOT_SERVICE_CAPABILITY structure itself. + // For this version of the protocol, the Major version shall be set to 1 + // and the Minor version shall be set to 0. + // + TREE_VERSION StructureVersion; + // + // Version of the TrEE protocol. + // For this version of the protocol, the Major version shall be set to 1 + // and the Minor version shall be set to 0. + // + TREE_VERSION ProtocolVersion; + // + // Supported hash algorithms + // + UINT32 HashAlgorithmBitmap; + // + // Bitmap of supported event log formats + // + TREE_EVENT_LOG_BITMAP SupportedEventLogs; + // + // False = TrEE not present + // + BOOLEAN TrEEPresentFlag; + // + // Max size (in bytes) of a command that can be sent to the TrEE + // + UINT16 MaxCommandSize; + // + // Max size (in bytes) of a response that can be provided by the TrEE + // + UINT16 MaxResponseSize; + // + // 4-byte Vendor ID (see Trusted Computing Group, "TCG Vendor ID Registry," + // Version 1.0, Revision 0.1, August 31, 2007, "TPM Capabilities Vendor ID" section) + // + UINT32 ManufacturerID; +} TREE_BOOT_SERVICE_CAPABILITY_1_0; + +typedef TREE_BOOT_SERVICE_CAPABILITY_1_0 TREE_BOOT_SERVICE_CAPABILITY; + +#define TREE_BOOT_HASH_ALG_SHA1 0x00000001 +#define TREE_BOOT_HASH_ALG_SHA256 0x00000002 +#define TREE_BOOT_HASH_ALG_SHA384 0x00000004 +#define TREE_BOOT_HASH_ALG_SHA512 0x00000008 + +// +// This bit is shall be set when an event shall be extended but not logged. +// +#define TREE_EXTEND_ONLY 0x0000000000000001 +// +// This bit shall be set when the intent is to measure a PE/COFF image. +// +#define PE_COFF_IMAGE 0x0000000000000010 + +typedef UINT32 TrEE_PCRINDEX; +typedef UINT32 TrEE_EVENTTYPE; + +#define MAX_PCR_INDEX 23 +#define TREE_EVENT_HEADER_VERSION 1 + +#pragma pack(1) + +typedef struct { + // + // Size of the event header itself (sizeof(TrEE_EVENT_HEADER)). + // + UINT32 HeaderSize; + // + // Header version. For this version of this specification, the value shall be 1. + // + UINT16 HeaderVersion; + // + // Index of the PCR that shall be extended (0 - 23). + // + TrEE_PCRINDEX PCRIndex; + // + // Type of the event that shall be extended (and optionally logged). + // + TrEE_EVENTTYPE EventType; +} TrEE_EVENT_HEADER; + +typedef struct { + // + // Total size of the event including the Size component, the header and the Event data. + // + UINT32 Size; + TrEE_EVENT_HEADER Header; + UINT8 Event[1]; +} TrEE_EVENT; + +#pragma pack() + +/** + The EFI_TREE_PROTOCOL GetCapability function call provides protocol + capability information and state information about the TrEE. + + @param[in] This Indicates the calling context + @param[out] ProtocolCapability The caller allocates memory for a TREE_BOOT_SERVICE_CAPABILITY + structure and sets the size field to the size of the structure allocated. + The callee fills in the fields with the EFI protocol capability information + and the current TrEE state information up to the number of fields which + fit within the size of the structure passed in. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + The ProtocolCapability variable will not be populated. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + The ProtocolCapability variable will not be populated. + @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response. + It will be partially populated (required Size field will be set). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TREE_GET_CAPABILITY) ( + IN EFI_TREE_PROTOCOL *This, + IN OUT TREE_BOOT_SERVICE_CAPABILITY *ProtocolCapability + ); + +/** + The EFI_TREE_PROTOCOL Get Event Log function call allows a caller to + retrieve the address of a given event log and its last entry. + + @param[in] This Indicates the calling context + @param[in] EventLogFormat The type of the event log for which the information is requested. + @param[out] EventLogLocation A pointer to the memory address of the event log. + @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the + address of the start of the last entry in the event log in memory. + @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would + have exceeded the area allocated for events, this value is set to TRUE. + Otherwise, the value will be FALSE and the Event Log will be complete. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect + (e.g. asking for an event log whose format is not supported). +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TREE_GET_EVENT_LOG) ( + IN EFI_TREE_PROTOCOL *This, + IN TREE_EVENT_LOG_FORMAT EventLogFormat, + OUT EFI_PHYSICAL_ADDRESS *EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry, + OUT BOOLEAN *EventLogTruncated + ); + +/** + The EFI_TREE_PROTOCOL HashLogExtendEvent function call provides callers with + an opportunity to extend and optionally log events without requiring + knowledge of actual TPM commands. + The extend operation will occur even if this function cannot create an event + log entry (e.g. due to the event log being full). + + @param[in] This Indicates the calling context + @param[in] Flags Bitmap providing additional information. + @param[in] DataToHash Physical address of the start of the data buffer to be hashed. + @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash. + @param[in] Event Pointer to data buffer containing information about the event. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_UNSUPPORTED The PE/COFF image type is not supported. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_TREE_HASH_LOG_EXTEND_EVENT) ( + IN EFI_TREE_PROTOCOL *This, + IN UINT64 Flags, + IN EFI_PHYSICAL_ADDRESS DataToHash, + IN UINT64 DataToHashLen, + IN TrEE_EVENT *Event + ); + +/** + This service enables the sending of commands to the TrEE. + + @param[in] This Indicates the calling context + @param[in] InputParameterBlockSize Size of the TrEE input parameter block. + @param[in] InputParameterBlock Pointer to the TrEE input parameter block. + @param[in] OutputParameterBlockSize Size of the TrEE output parameter block. + @param[in] OutputParameterBlock Pointer to the TrEE output parameter block. + + @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. + @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TREE_SUBMIT_COMMAND) ( + IN EFI_TREE_PROTOCOL *This, + IN UINT32 InputParameterBlockSize, + IN UINT8 *InputParameterBlock, + IN UINT32 OutputParameterBlockSize, + IN UINT8 *OutputParameterBlock + ); + +struct _EFI_TREE_PROTOCOL { + EFI_TREE_GET_CAPABILITY GetCapability; + EFI_TREE_GET_EVENT_LOG GetEventLog; + EFI_TREE_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; + EFI_TREE_SUBMIT_COMMAND SubmitCommand; +}; + +extern EFI_GUID gEfiTrEEProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp4.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp4.h new file mode 100644 index 0000000..5297fcb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp4.h @@ -0,0 +1,445 @@ +/** @file + UDP4 Service Binding Protocol as defined in UEFI specification. + + The EFI UDPv4 Protocol provides simple packet-oriented services + to transmit and receive UDP packets. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.0. + +**/ + +#ifndef __EFI_UDP4_PROTOCOL_H__ +#define __EFI_UDP4_PROTOCOL_H__ + +#include +// +//GUID definitions +// +#define EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x83f01464, 0x99bd, 0x45e5, {0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6 } \ + } + +#define EFI_UDP4_PROTOCOL_GUID \ + { \ + 0x3ad9df29, 0x4501, 0x478d, {0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3 } \ + } + +typedef struct _EFI_UDP4_PROTOCOL EFI_UDP4_PROTOCOL; + +/// +/// EFI_UDP4_SERVICE_POINT is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE InstanceHandle; + EFI_IPv4_ADDRESS LocalAddress; + UINT16 LocalPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP4_SERVICE_POINT; + +/// +/// EFI_UDP4_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 ServiceCount; + EFI_UDP4_SERVICE_POINT Services[1]; +} EFI_UDP4_VARIABLE_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_UDP4_FRAGMENT_DATA; + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + UINT16 SourcePort; + EFI_IPv4_ADDRESS DestinationAddress; + UINT16 DestinationPort; +} EFI_UDP4_SESSION_DATA; +typedef struct { + // + // Receiving Filters + // + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN AcceptAnyPort; + BOOLEAN AllowDuplicatePort; + // + // I/O parameters + // + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; + // + // Access Point + // + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP4_CONFIG_DATA; + +typedef struct { + EFI_UDP4_SESSION_DATA *UdpSessionData; //OPTIONAL + EFI_IPv4_ADDRESS *GatewayAddress; //OPTIONAL + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_TRANSMIT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + EFI_UDP4_SESSION_DATA UdpSession; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_RECEIVE_DATA; + + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_UDP4_RECEIVE_DATA *RxData; + EFI_UDP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_UDP4_COMPLETION_TOKEN; + +/** + Reads the current operational settings. + + The GetModeData() function copies the current operational settings of this EFI + UDPv4 Protocol instance into user-supplied buffers. This function is used + optionally to retrieve the operational mode data of underlying networks or + drivers. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param Udp4ConfigData The pointer to the buffer to receive the current configuration data. + @param Ip4ModeData The pointer to the EFI IPv4 Protocol mode data structure. + @param MnpConfigData The pointer to the managed network configuration data structure. + @param SnpModeData The pointer to the simple network mode data structure. + + @retval EFI_SUCCESS The mode data was read. + @retval EFI_NOT_STARTED When Udp4ConfigData is queried, no configuration data is + available because this instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_GET_MODE_DATA)( + IN EFI_UDP4_PROTOCOL *This, + OUT EFI_UDP4_CONFIG_DATA *Udp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + + +/** + Initializes, changes, or resets the operational parameters for this instance of the EFI UDPv4 + Protocol. + + The Configure() function is used to do the following: + * Initialize and start this instance of the EFI UDPv4 Protocol. + * Change the filtering rules and operational parameters. + * Reset this instance of the EFI UDPv4 Protocol. + Until these parameters are initialized, no network traffic can be sent or + received by this instance. This instance can be also reset by calling Configure() + with UdpConfigData set to NULL. Once reset, the receiving queue and transmitting + queue are flushed and no traffic is allowed through this instance. + With different parameters in UdpConfigData, Configure() can be used to bind + this instance to specified port. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param Udp4ConfigData The pointer to the buffer to receive the current configuration data. + + @retval EFI_SUCCESS The configuration settings were set, changed, or reset successfully. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER UdpConfigData.StationAddress is not a valid unicast IPv4 address. + @retval EFI_INVALID_PARAMETER UdpConfigData.SubnetMask is not a valid IPv4 address mask. The subnet + mask must be contiguous. + @retval EFI_INVALID_PARAMETER UdpConfigData.RemoteAddress is not a valid unicast IPv4 address if it + is not zero. + @retval EFI_ALREADY_STARTED The EFI UDPv4 Protocol instance is already started/configured + and must be stopped/reset before it can be reconfigured. + @retval EFI_ACCESS_DENIED UdpConfigData. AllowDuplicatePort is FALSE + and UdpConfigData.StationPort is already used by + other instance. + @retval EFI_OUT_OF_RESOURCES The EFI UDPv4 Protocol driver cannot allocate memory for this + EFI UDPv4 Protocol instance. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred and this instance + was not opened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_CONFIGURE)( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_CONFIG_DATA *UdpConfigData OPTIONAL + ); + +/** + Joins and leaves multicast groups. + + The Groups() function is used to enable and disable the multicast group + filtering. If the JoinFlag is FALSE and the MulticastAddress is NULL, then all + currently joined groups are left. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param JoinFlag Set to TRUE to join a multicast group. Set to FALSE to leave one + or all multicast groups. + @param MulticastAddress The pointer to multicast group address to join or leave. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Could not allocate resources to join the group. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - JoinFlag is TRUE and MulticastAddress is NULL. + - JoinFlag is TRUE and *MulticastAddress is not + a valid multicast address. + @retval EFI_ALREADY_STARTED The group address is already in the group table (when + JoinFlag is TRUE). + @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is + FALSE). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_GROUPS)( + IN EFI_UDP4_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS *MulticastAddress OPTIONAL + ); + +/** + Adds and deletes routing table entries. + + The Routes() function adds a route to or deletes a route from the routing table. + Routes are determined by comparing the SubnetAddress with the destination IP + address and arithmetically AND-ing it with the SubnetMask. The gateway address + must be on the same subnet as the configured station address. + The default route is added with SubnetAddress and SubnetMask both set to 0.0.0.0. + The default route matches all destination IP addresses that do not match any + other routes. + A zero GatewayAddress is a nonroute. Packets are sent to the destination IP + address if it can be found in the Address Resolution Protocol (ARP) cache or + on the local subnet. One automatic nonroute entry will be inserted into the + routing table for outgoing packets that are addressed to a local subnet + (gateway address of 0.0.0.0). + Each instance of the EFI UDPv4 Protocol has its own independent routing table. + Instances of the EFI UDPv4 Protocol that use the default IP address will also + have copies of the routing table provided by the EFI_IP4_CONFIG_PROTOCOL. These + copies will be updated automatically whenever the IP driver reconfigures its + instances; as a result, the previous modification to these copies will be lost. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param DeleteRoute Set to TRUE to delete this route from the routing table. + Set to FALSE to add this route to the routing table. + @param SubnetAddress The destination network address that needs to be routed. + @param SubnetMask The subnet mask of SubnetAddress. + @param GatewayAddress The gateway IP address for this route. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + - RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table. + @retval EFI_NOT_FOUND This route is not in the routing table. + @retval EFI_ACCESS_DENIED The route is already defined in the routing table. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_ROUTES)( + IN EFI_UDP4_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function can be used by network drivers and applications to increase + the rate that data packets are moved between the communications device and the + transmit and receive queues. + In some systems, the periodic timer event in the managed network driver may not + poll the underlying communications device fast enough to transmit and/or receive + all data packets without missing incoming packets or dropping outgoing packets. + Drivers and applications that are experiencing packet loss should try calling + the Poll() function more often. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_POLL)( + IN EFI_UDP4_PROTOCOL *This + ); + +/** + Places an asynchronous receive request into the receiving queue. + + The Receive() function places a completion token into the receive packet queue. + This function is always asynchronous. + The caller must fill in the Token.Event field in the completion token, and this + field cannot be NULL. When the receive operation completes, the EFI UDPv4 Protocol + driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event + is signaled. Providing a proper notification function and context for the event + will enable the user to receive the notification and receiving status. That + notification function is guaranteed to not be re-entered. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param Token The pointer to a token that is associated with the receive data + descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, RARP, etc.) + is not finished yet. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_INVALID_PARAMETER Token is NULL. + @retval EFI_INVALID_PARAMETER Token.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system + resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_ACCESS_DENIED A receive completion token with the same Token.Event was already in + the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_RECEIVE)( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token + ); + +/** + Queues outgoing data packets into the transmit queue. + + The Transmit() function places a sending request to this instance of the EFI + UDPv4 Protocol, alongside the transmit data that was filled by the user. Whenever + the packet in the token is sent out or some errors occur, the Token.Event will + be signaled and Token.Status is updated. Providing a proper notification function + and context for the event will enable the user to receive the notification and + transmitting status. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param Token The pointer to the completion token that will be placed into the + transmit queue. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED The transmit completion token with the same + Token.Event was already in the transmit queue. + @retval EFI_NOT_READY The completion token could not be queued because the + transmit queue is full. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data. + @retval EFI_NOT_FOUND There is no route to the destination network or address. + @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP packet + size. Or the length of the IP header + UDP header + data + length is greater than MTU if DoNotFragment is TRUE. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_TRANSMIT)( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token + ); + +/** + Aborts an asynchronous transmit or receive request. + + The Cancel() function is used to abort a pending transmit or receive request. + If the token is in the transmit or receive request queues, after calling this + function, Token.Status will be set to EFI_ABORTED and then Token.Event will be + signaled. If the token is not in one of the queues, which usually means that + the asynchronous operation has completed, this function will not signal the + token and EFI_NOT_FOUND is returned. + + @param This The pointer to the EFI_UDP4_PROTOCOL instance. + @param Token The pointer to a token that has been issued by + EFI_UDP4_PROTOCOL.Transmit() or + EFI_UDP4_PROTOCOL.Receive().If NULL, all pending + tokens are aborted. + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and Token.Event + was signaled. When Token is NULL, all pending requests are + aborted and their events are signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_CANCEL)( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL + ); + +/// +/// The EFI_UDP4_PROTOCOL defines an EFI UDPv4 Protocol session that can be used +/// by any network drivers, applications, or daemons to transmit or receive UDP packets. +/// This protocol instance can either be bound to a specified port as a service or +/// connected to some remote peer as an active client. Each instance has its own settings, +/// such as the routing table and group table, which are independent from each other. +/// +struct _EFI_UDP4_PROTOCOL { + EFI_UDP4_GET_MODE_DATA GetModeData; + EFI_UDP4_CONFIGURE Configure; + EFI_UDP4_GROUPS Groups; + EFI_UDP4_ROUTES Routes; + EFI_UDP4_TRANSMIT Transmit; + EFI_UDP4_RECEIVE Receive; + EFI_UDP4_CANCEL Cancel; + EFI_UDP4_POLL Poll; +}; + +extern EFI_GUID gEfiUdp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiUdp4ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp6.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp6.h new file mode 100644 index 0000000..647ebd8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Udp6.h @@ -0,0 +1,580 @@ +/** @file + The EFI UDPv6 (User Datagram Protocol version 6) Protocol Definition, which is built upon + the EFI IPv6 Protocol and provides simple packet-oriented services to transmit and receive + UDP packets. + + Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_UDP6_PROTOCOL_H__ +#define __EFI_UDP6_PROTOCOL_H__ + +#include + +#define EFI_UDP6_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x66ed4721, 0x3c98, 0x4d3e, {0x81, 0xe3, 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54 } \ + } + +#define EFI_UDP6_PROTOCOL_GUID \ + { \ + 0x4f948815, 0xb4b9, 0x43cb, {0x8a, 0x33, 0x90, 0xe0, 0x60, 0xb3, 0x49, 0x55 } \ + } + +/// +/// EFI_UDP6_SERVICE_POINT is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + /// + /// The EFI UDPv6 Protocol instance handle that is using this address/port pair. + /// + EFI_HANDLE InstanceHandle; + /// + /// The IPv6 address to which this instance of the EFI UDPv6 Protocol is bound. + /// Set to 0::/128, if this instance is used to listen all packets from any + /// source address. + /// + EFI_IPv6_ADDRESS LocalAddress; + /// + /// The port number in host byte order on which the service is listening. + /// + UINT16 LocalPort; + /// + /// The IPv6 address of the remote host. May be 0::/128 if it is not connected + /// to any remote host or connected with more than one remote host. + /// + EFI_IPv6_ADDRESS RemoteAddress; + /// + /// The port number in host byte order on which the remote host is + /// listening. Maybe zero if it is not connected to any remote host. + /// + UINT16 RemotePort; +} EFI_UDP6_SERVICE_POINT; + +/// +/// EFI_UDP6_VARIABLE_DATA is deprecated in the UEFI 2.4B and should not be used any more. +/// The definition in here is only present to provide backwards compatability. +/// +typedef struct { + /// + /// The handle of the driver that creates this entry. + /// + EFI_HANDLE DriverHandle; + /// + /// The number of address/port pairs that follow this data structure. + /// + UINT32 ServiceCount; + /// + /// List of address/port pairs that are currently in use. + /// + EFI_UDP6_SERVICE_POINT Services[1]; +} EFI_UDP6_VARIABLE_DATA; + +typedef struct _EFI_UDP6_PROTOCOL EFI_UDP6_PROTOCOL; + +/// +/// EFI_UDP6_FRAGMENT_DATA allows multiple receive or transmit buffers to be specified. +/// The purpose of this structure is to avoid copying the same packet multiple times. +/// +typedef struct { + UINT32 FragmentLength; ///< Length of the fragment data buffer. + VOID *FragmentBuffer; ///< Pointer to the fragment data buffer. +} EFI_UDP6_FRAGMENT_DATA; + +/// +/// The EFI_UDP6_SESSION_DATA is used to retrieve the settings when receiving packets or +/// to override the existing settings (only DestinationAddress and DestinationPort can +/// be overridden) of this EFI UDPv6 Protocol instance when sending packets. +/// +typedef struct { + /// + /// Address from which this packet is sent. This field should not be used when + /// sending packets. + /// + EFI_IPv6_ADDRESS SourceAddress; + /// + /// Port from which this packet is sent. It is in host byte order. This field should + /// not be used when sending packets. + /// + UINT16 SourcePort; + /// + /// Address to which this packet is sent. When sending packet, it'll be ignored + /// if it is zero. + /// + EFI_IPv6_ADDRESS DestinationAddress; + /// + /// Port to which this packet is sent. When sending packet, it'll be + /// ignored if it is zero. + /// + UINT16 DestinationPort; +} EFI_UDP6_SESSION_DATA; + +typedef struct { + /// + /// Set to TRUE to accept UDP packets that are sent to any address. + /// + BOOLEAN AcceptPromiscuous; + /// + /// Set to TRUE to accept UDP packets that are sent to any port. + /// + BOOLEAN AcceptAnyPort; + /// + /// Set to TRUE to allow this EFI UDPv6 Protocol child instance to open a port number + /// that is already being used by another EFI UDPv6 Protocol child instance. + /// + BOOLEAN AllowDuplicatePort; + /// + /// TrafficClass field in transmitted IPv6 packets. + /// + UINT8 TrafficClass; + /// + /// HopLimit field in transmitted IPv6 packets. + /// + UINT8 HopLimit; + /// + /// The receive timeout value (number of microseconds) to be associated with each + /// incoming packet. Zero means do not drop incoming packets. + /// + UINT32 ReceiveTimeout; + /// + /// The transmit timeout value (number of microseconds) to be associated with each + /// outgoing packet. Zero means do not drop outgoing packets. + /// + UINT32 TransmitTimeout; + /// + /// The station IP address that will be assigned to this EFI UDPv6 Protocol instance. + /// The EFI UDPv6 and EFI IPv6 Protocol drivers will only deliver incoming packets + /// whose destination matches this IP address exactly. Address 0::/128 is also accepted + /// as a special case. Under this situation, underlying IPv6 driver is responsible for + /// binding a source address to this EFI IPv6 protocol instance according to source + /// address selection algorithm. Only incoming packet from the selected source address + /// is delivered. This field can be set and changed only when the EFI IPv6 driver is + /// transitioning from the stopped to the started states. If no address is available + /// for selecting, the EFI IPv6 Protocol driver will use EFI_IP6_CONFIG_PROTOCOL to + /// retrieve the IPv6 address. + EFI_IPv6_ADDRESS StationAddress; + /// + /// The port number to which this EFI UDPv6 Protocol instance is bound. If a client + /// of the EFI UDPv6 Protocol does not care about the port number, set StationPort + /// to zero. The EFI UDPv6 Protocol driver will assign a random port number to transmitted + /// UDP packets. Ignored it if AcceptAnyPort is TRUE. + /// + UINT16 StationPort; + /// + /// The IP address of remote host to which this EFI UDPv6 Protocol instance is connecting. + /// If RemoteAddress is not 0::/128, this EFI UDPv6 Protocol instance will be connected to + /// RemoteAddress; i.e., outgoing packets of this EFI UDPv6 Protocol instance will be sent + /// to this address by default and only incoming packets from this address will be delivered + /// to client. Ignored for incoming filtering if AcceptPromiscuous is TRUE. + EFI_IPv6_ADDRESS RemoteAddress; + /// + /// The port number of the remote host to which this EFI UDPv6 Protocol instance is connecting. + /// If it is not zero, outgoing packets of this EFI UDPv6 Protocol instance will be sent to + /// this port number by default and only incoming packets from this port will be delivered + /// to client. Ignored if RemoteAddress is 0::/128 and ignored for incoming filtering if + /// AcceptPromiscuous is TRUE. + UINT16 RemotePort; +} EFI_UDP6_CONFIG_DATA; + +/// +/// The EFI UDPv6 Protocol client must fill this data structure before sending a packet. +/// The packet may contain multiple buffers that may be not in a continuous memory location. +/// +typedef struct { + /// + /// If not NULL, the data that is used to override the transmitting settings.Only the two + /// filed UdpSessionData.DestinationAddress and UdpSessionData.DestionPort can be used as + /// the transmitting setting filed. + /// + EFI_UDP6_SESSION_DATA *UdpSessionData; + /// + /// Sum of the fragment data length. Must not exceed the maximum UDP packet size. + /// + UINT32 DataLength; + /// + /// Number of fragments. + /// + UINT32 FragmentCount; + /// + /// Array of fragment descriptors. + /// + EFI_UDP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP6_TRANSMIT_DATA; + +/// +/// EFI_UDP6_RECEIVE_DATA is filled by the EFI UDPv6 Protocol driver when this EFI UDPv6 +/// Protocol instance receives an incoming packet. If there is a waiting token for incoming +/// packets, the CompletionToken.Packet.RxData field is updated to this incoming packet and +/// the CompletionToken.Event is signaled. The EFI UDPv6 Protocol client must signal the +/// RecycleSignal after processing the packet. +/// FragmentTable could contain multiple buffers that are not in the continuous memory locations. +/// The EFI UDPv6 Protocol client might need to combine two or more buffers in FragmentTable to +/// form their own protocol header. +/// +typedef struct { + /// + /// Time when the EFI UDPv6 Protocol accepted the packet. + /// + EFI_TIME TimeStamp; + /// + /// Indicates the event to signal when the received data has been processed. + /// + EFI_EVENT RecycleSignal; + /// + /// The UDP session data including SourceAddress, SourcePort, DestinationAddress, + /// and DestinationPort. + /// + EFI_UDP6_SESSION_DATA UdpSession; + /// + /// The sum of the fragment data length. + /// + UINT32 DataLength; + /// + /// Number of fragments. Maybe zero. + /// + UINT32 FragmentCount; + /// + /// Array of fragment descriptors. Maybe zero. + /// + EFI_UDP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP6_RECEIVE_DATA; + +/// +/// The EFI_UDP6_COMPLETION_TOKEN structures are used for both transmit and receive operations. +/// When used for transmitting, the Event and TxData fields must be filled in by the EFI UDPv6 +/// Protocol client. After the transmit operation completes, the Status field is updated by the +/// EFI UDPv6 Protocol and the Event is signaled. +/// When used for receiving, only the Event field must be filled in by the EFI UDPv6 Protocol +/// client. After a packet is received, RxData and Status are filled in by the EFI UDPv6 Protocol +/// and the Event is signaled. +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI UDPv6 Protocol + /// driver. The type of Event must be EVT_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// - EFI_SUCCESS: The receive or transmit operation completed successfully. + /// - EFI_ABORTED: The receive or transmit was aborted. + /// - EFI_TIMEOUT: The transmit timeout expired. + /// - EFI_NETWORK_UNREACHABLE: The destination network is unreachable. RxData is set to + /// NULL in this situation. + /// - EFI_HOST_UNREACHABLE: The destination host is unreachable. RxData is set to NULL in + /// this situation. + /// - EFI_PROTOCOL_UNREACHABLE: The UDP protocol is unsupported in the remote system. + /// RxData is set to NULL in this situation. + /// - EFI_PORT_UNREACHABLE: No service is listening on the remote port. RxData is set to + /// NULL in this situation. + /// - EFI_ICMP_ERROR: Some other Internet Control Message Protocol (ICMP) error report was + /// received. For example, packets are being sent too fast for the destination to receive them + /// and the destination sent an ICMP source quench report. RxData is set to NULL in this situation. + /// - EFI_DEVICE_ERROR: An unexpected system or network error occurred. + /// - EFI_SECURITY_VIOLATION: The transmit or receive was failed because of IPsec policy check. + /// - EFI_NO_MEDIA: There was a media error. + /// + EFI_STATUS Status; + union { + /// + /// When this token is used for receiving, RxData is a pointer to EFI_UDP6_RECEIVE_DATA. + /// + EFI_UDP6_RECEIVE_DATA *RxData; + /// + /// When this token is used for transmitting, TxData is a pointer to EFI_UDP6_TRANSMIT_DATA. + /// + EFI_UDP6_TRANSMIT_DATA *TxData; + } Packet; +} EFI_UDP6_COMPLETION_TOKEN; + +/** + Read the current operational settings. + + The GetModeData() function copies the current operational settings of this EFI UDPv6 Protocol + instance into user-supplied buffers. This function is used optionally to retrieve the operational + mode data of underlying networks or drivers. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + @param[out] Udp6ConfigData The buffer in which the current UDP configuration data is returned. + @param[out] Ip6ModeData The buffer in which the current EFI IPv6 Protocol mode data is returned. + @param[out] MnpConfigData The buffer in which the current managed network configuration data is + returned. + @param[out] SnpModeData The buffer in which the simple network mode data is returned. + + @retval EFI_SUCCESS The mode data was read. + @retval EFI_NOT_STARTED When Udp6ConfigData is queried, no configuration data is available + because this instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_GET_MODE_DATA)( + IN EFI_UDP6_PROTOCOL *This, + OUT EFI_UDP6_CONFIG_DATA *Udp6ConfigData OPTIONAL, + OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL +); + +/** + Initializes, changes, or resets the operational parameters for this instance of the EFI UDPv6 + Protocol. + + The Configure() function is used to do the following: + - Initialize and start this instance of the EFI UDPv6 Protocol. + - Change the filtering rules and operational parameters. + - Reset this instance of the EFI UDPv6 Protocol. + + Until these parameters are initialized, no network traffic can be sent or received by this instance. + This instance can be also reset by calling Configure() with UdpConfigData set to NULL. + Once reset, the receiving queue and transmitting queue are flushed and no traffic is allowed through + this instance. + + With different parameters in UdpConfigData, Configure() can be used to bind this instance to specified + port. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + @param[in] UdpConfigData Pointer to the buffer contained the configuration data. + + @retval EFI_SUCCESS The configuration settings were set, changed, or reset successfully. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available for use. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + - This is NULL. + - UdpConfigData.StationAddress neither zero nor one of the configured IP + addresses in the underlying IPv6 driver. + - UdpConfigData.RemoteAddress is not a valid unicast IPv6 address if it + is not zero. + @retval EFI_ALREADY_STARTED The EFI UDPv6 Protocol instance is already started/configured and must be + stopped/reset before it can be reconfigured. Only TrafficClass, HopLimit, + ReceiveTimeout, and TransmitTimeout can be reconfigured without stopping + the current instance of the EFI UDPv6 Protocol. + @retval EFI_ACCESS_DENIED UdpConfigData.AllowDuplicatePort is FALSE and UdpConfigData.StationPort + is already used by other instance. + @retval EFI_OUT_OF_RESOURCES The EFI UDPv6 Protocol driver cannot allocate memory for this EFI UDPv6 + Protocol instance. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred and this instance was not + opened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_CONFIGURE)( + IN EFI_UDP6_PROTOCOL *This, + IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL +); + +/** + Joins and leaves multicast groups. + + The Groups() function is used to join or leave one or more multicast group. + If the JoinFlag is FALSE and the MulticastAddress is NULL, then all currently joined groups are left. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + @param[in] JoinFlag Set to TRUE to join a multicast group. Set to FALSE to leave one + or all multicast groups. + @param[in] MulticastAddress Pointer to multicast group address to join or leave. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI UDPv6 Protocol instance has not been started. + @retval EFI_OUT_OF_RESOURCES Could not allocate resources to join the group. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - JoinFlag is TRUE and MulticastAddress is NULL. + - JoinFlag is TRUE and *MulticastAddress is not a valid multicast address. + @retval EFI_ALREADY_STARTED The group address is already in the group table (when JoinFlag is TRUE). + @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_GROUPS)( + IN EFI_UDP6_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv6_ADDRESS *MulticastAddress OPTIONAL +); + +/** + Queues outgoing data packets into the transmit queue. + + The Transmit() function places a sending request to this instance of the EFI UDPv6 Protocol, + alongside the transmit data that was filled by the user. Whenever the packet in the token is + sent out or some errors occur, the Token.Event will be signaled and Token.Status is updated. + Providing a proper notification function and context for the event will enable the user to + receive the notification and transmitting status. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + @param[in] Token Pointer to the completion token that will be placed into the + transmit queue. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This EFI UDPv6 Protocol instance has not been started. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available + for use. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + - Token.Packet.TxData is NULL. + - Token.Packet.TxData.FragmentCount is zero. + - Token.Packet.TxData.DataLength is not equal to the sum of fragment + lengths. + - One or more of the Token.Packet.TxData.FragmentTable[].FragmentLength + fields is zero. + - One or more of the Token.Packet.TxData.FragmentTable[].FragmentBuffer + fields is NULL. + - Token.Packet.TxData.UdpSessionData.DestinationAddress is not zero + and is not valid unicast Ipv6 address if UdpSessionData is not NULL. + - Token.Packet.TxData.UdpSessionData is NULL and this instance's + UdpConfigData.RemoteAddress is unspecified. + - Token.Packet.TxData.UdpSessionData.DestinationAddress is non-zero + when DestinationAddress is configured as non-zero when doing Configure() + for this EFI Udp6 protocol instance. + - Token.Packet.TxData.UdpSesionData.DestinationAddress is zero when + DestinationAddress is unspecified when doing Configure() for this + EFI Udp6 protocol instance. + @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event was already + in the transmit queue. + @retval EFI_NOT_READY The completion token could not be queued because the transmit queue + is full. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data. + @retval EFI_NOT_FOUND There is no route to the destination network or address. + @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP packet size. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_TRANSMIT)( + IN EFI_UDP6_PROTOCOL *This, + IN EFI_UDP6_COMPLETION_TOKEN *Token +); + +/** + Places an asynchronous receive request into the receiving queue. + + The Receive() function places a completion token into the receive packet queue. This function is + always asynchronous. + The caller must fill in the Token.Event field in the completion token, and this field cannot be + NULL. When the receive operation completes, the EFI UDPv6 Protocol driver updates the Token.Status + and Token.Packet.RxData fields and the Token.Event is signaled. + Providing a proper notification function and context for the event will enable the user to receive + the notification and receiving status. That notification function is guaranteed to not be re-entered. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + @param[in] Token Pointer to a token that is associated with the receive data descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI UDPv6 Protocol instance has not been started. + @retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source + address for this instance, but no source address was available + for use. + @retval EFI_INVALID_PARAMETER One or more of the following is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system + resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI UDPv6 Protocol + instance has been reset to startup defaults. + @retval EFI_ACCESS_DENIED A receive completion token with the same Token.Event was already in + the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_RECEIVE)( + IN EFI_UDP6_PROTOCOL *This, + IN EFI_UDP6_COMPLETION_TOKEN *Token +); + +/** + Aborts an asynchronous transmit or receive request. + + The Cancel() function is used to abort a pending transmit or receive request. If the token is in the + transmit or receive request queues, after calling this function, Token.Status will be set to + EFI_ABORTED and then Token.Event will be signaled. If the token is not in one of the queues, + which usually means that the asynchronous operation has completed, this function will not signal the + token and EFI_NOT_FOUND is returned. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + @param[in] Token Pointer to a token that has been issued by EFI_UDP6_PROTOCOL.Transmit() + or EFI_UDP6_PROTOCOL.Receive().If NULL, all pending tokens are aborted. + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and Token.Event was signaled. + When Token is NULL, all pending requests are aborted and their events + are signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was not found in + the transmit or receive queue. It has either completed or was not issued + by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_CANCEL)( + IN EFI_UDP6_PROTOCOL *This, + IN EFI_UDP6_COMPLETION_TOKEN *Token OPTIONAL +); + +/** + Polls for incoming data packets and processes outgoing data packets. + + The Poll() function can be used by network drivers and applications to increase the rate that data + packets are moved between the communications device and the transmit and receive queues. + In some systems, the periodic timer event in the managed network driver may not poll the underlying + communications device fast enough to transmit and/or receive all data packets without missing incoming + packets or dropping outgoing packets. Drivers and applications that are experiencing packet loss should + try calling the Poll() function more often. + + @param[in] This Pointer to the EFI_UDP6_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_POLL)( + IN EFI_UDP6_PROTOCOL *This +); + +/// +/// The EFI_UDP6_PROTOCOL defines an EFI UDPv6 Protocol session that can be used by any network drivers, +/// applications, or daemons to transmit or receive UDP packets. This protocol instance can either be +/// bound to a specified port as a service or connected to some remote peer as an active client. +/// Each instance has its own settings, such as group table, that are independent from each other. +/// +struct _EFI_UDP6_PROTOCOL { + EFI_UDP6_GET_MODE_DATA GetModeData; + EFI_UDP6_CONFIGURE Configure; + EFI_UDP6_GROUPS Groups; + EFI_UDP6_TRANSMIT Transmit; + EFI_UDP6_RECEIVE Receive; + EFI_UDP6_CANCEL Cancel; + EFI_UDP6_POLL Poll; +}; + +extern EFI_GUID gEfiUdp6ServiceBindingProtocolGuid; +extern EFI_GUID gEfiUdp6ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UfsDeviceConfig.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UfsDeviceConfig.h new file mode 100644 index 0000000..e1b278d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UfsDeviceConfig.h @@ -0,0 +1,143 @@ +/** @file + This file defines the EFI UFS Device Config Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.7 + +**/ + +#ifndef __UFS_DEVICE_CONFIG_PROTOCOL_H__ +#define __UFS_DEVICE_CONFIG_PROTOCOL_H__ + +// +// EFI UFS Device Config Protocol GUID value +// +#define EFI_UFS_DEVICE_CONFIG_GUID \ + { 0xb81bfab0, 0xeb3, 0x4cf9, { 0x84, 0x65, 0x7f, 0xa9, 0x86, 0x36, 0x16, 0x64 }}; + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_UFS_DEVICE_CONFIG_PROTOCOL EFI_UFS_DEVICE_CONFIG_PROTOCOL; + +/** + Read or write specified device descriptor of a UFS device. + + The service is used to read/write UFS device descriptors. The consumer of this API is responsible + for allocating the data buffer pointed by Descriptor. + + @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance. + @param[in] Read The boolean variable to show r/w direction. + @param[in] DescId The ID of device descriptor. + @param[in] Index The Index of device descriptor. + @param[in] Selector The Selector of device descriptor. + @param[in, out] Descriptor The buffer of device descriptor to be read or written. + @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes, + of the data buffer specified by Descriptor. On output, the number + of bytes that were actually transferred. + + @retval EFI_SUCCESS The device descriptor is read/written successfully. + @retval EFI_INVALID_PARAMETER This is NULL or Descriptor is NULL or DescSize is NULL. + DescId, Index and Selector are invalid combination to point to a + type of UFS device descriptor. + @retval EFI_DEVICE_ERROR The device descriptor is not read/written successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UFS_DEVICE_CONFIG_RW_DESCRIPTOR) ( + IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This, + IN BOOLEAN Read, + IN UINT8 DescId, + IN UINT8 Index, + IN UINT8 Selector, + IN OUT UINT8 *Descriptor, + IN OUT UINT32 *DescSize + ); + +/** + Read or write specified flag of a UFS device. + + The service is used to read/write UFS flag descriptors. The consumer of this API is responsible + for allocating the buffer pointed by Flag. The buffer size is 1 byte as UFS flag descriptor is + just a single Boolean value that represents a TRUE or FALSE, '0' or '1', ON or OFF type of value. + + @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance. + @param[in] Read The boolean variable to show r/w direction. + @param[in] FlagId The ID of flag to be read or written. + @param[in, out] Flag The buffer to set or clear flag. + + @retval EFI_SUCCESS The flag descriptor is set/clear successfully. + @retval EFI_INVALID_PARAMETER This is NULL or Flag is NULL. + FlagId is an invalid UFS flag ID. + @retval EFI_DEVICE_ERROR The flag is not set/clear successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UFS_DEVICE_CONFIG_RW_FLAG) ( + IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This, + IN BOOLEAN Read, + IN UINT8 FlagId, + IN OUT UINT8 *Flag + ); + +/** + Read or write specified attribute of a UFS device. + + The service is used to read/write UFS attributes. The consumer of this API is responsible for + allocating the data buffer pointed by Attribute. + + @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance. + @param[in] Read The boolean variable to show r/w direction. + @param[in] AttrId The ID of Attribute. + @param[in] Index The Index of Attribute. + @param[in] Selector The Selector of Attribute. + @param[in, out] Attribute The buffer of Attribute to be read or written. + @param[in, out] AttrSize The size of Attribute buffer. On input, the size, in bytes, of the + data buffer specified by Attribute. On output, the number of bytes + that were actually transferred. + + @retval EFI_SUCCESS The attribute is read/written successfully. + @retval EFI_INVALID_PARAMETER This is NULL or Attribute is NULL or AttrSize is NULL. + AttrId, Index and Selector are invalid combination to point to a + type of UFS attribute. + @retval EFI_DEVICE_ERROR The attribute is not read/written successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UFS_DEVICE_CONFIG_RW_ATTRIBUTE) ( + IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This, + IN BOOLEAN Read, + IN UINT8 AttrId, + IN UINT8 Index, + IN UINT8 Selector, + IN OUT UINT8 *Attribute, + IN OUT UINT32 *AttrSize + ); + +/// +/// UFS Device Config Protocol structure. +/// +struct _EFI_UFS_DEVICE_CONFIG_PROTOCOL { + EFI_UFS_DEVICE_CONFIG_RW_DESCRIPTOR RwUfsDescriptor; + EFI_UFS_DEVICE_CONFIG_RW_FLAG RwUfsFlag; + EFI_UFS_DEVICE_CONFIG_RW_ATTRIBUTE RwUfsAttribute; +}; + +/// +/// UFS Device Config Protocol GUID variable. +/// +extern EFI_GUID gEfiUfsDeviceConfigProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaDraw.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaDraw.h new file mode 100644 index 0000000..9559931 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaDraw.h @@ -0,0 +1,166 @@ +/** @file + UGA Draw protocol from the EFI 1.10 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UGA_DRAW_H__ +#define __UGA_DRAW_H__ + + +#define EFI_UGA_DRAW_PROTOCOL_GUID \ + { \ + 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \ + } + +typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL; + +/** + Return the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE)( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ); + +/** + Set the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE)( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_UGA_PIXEL; + +typedef union { + EFI_UGA_PIXEL Pixel; + UINT32 Raw; +} EFI_UGA_PIXEL_UNION; + +/// +/// Enumration value for actions of Blt operations. +/// +typedef enum { + EfiUgaVideoFill, ///< Write data from the BltBuffer pixel (SourceX, SourceY) + ///< directly to every pixel of the video display rectangle + ///< (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + ///< Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiUgaVideoToBltBuffer, ///< Read data from the video display rectangle + ///< (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + ///< the BltBuffer rectangle (DestinationX, DestinationY ) + ///< (DestinationX + Width, DestinationY + Height). If DestinationX or + ///< DestinationY is not zero then Delta must be set to the length in bytes + ///< of a row in the BltBuffer. + + EfiUgaBltBufferToVideo, ///< Write data from the BltBuffer rectangle + ///< (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + ///< video display rectangle (DestinationX, DestinationY) + ///< (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + ///< not zero then Delta must be set to the length in bytes of a row in the + ///< BltBuffer. + + EfiUgaVideoToVideo, ///< Copy from the video display rectangle (SourceX, SourceY) + ///< (SourceX + Width, SourceY + Height) .to the video display rectangle + ///< (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + ///< The BltBuffer and Delta are not used in this mode. + + EfiUgaBltMax ///< Maxmimum value for enumration value of Blt operation. If a Blt operation + ///< larger or equal to this enumration value, it is invalid. +} EFI_UGA_BLT_OPERATION; + +/** + Blt a rectangle of pixels on the graphics screen. + + @param[in] This - Protocol instance pointer. + @param[in] BltBuffer - Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + @param[in] BltOperation - Operation to perform on BlitBuffer and video memory + @param[in] SourceX - X coordinate of source for the BltBuffer. + @param[in] SourceY - Y coordinate of source for the BltBuffer. + @param[in] DestinationX - X coordinate of destination for the BltBuffer. + @param[in] DestinationY - Y coordinate of destination for the BltBuffer. + @param[in] Width - Width of rectangle in BltBuffer in pixels. + @param[in] Height - Hight of rectangle in BltBuffer in pixels. + @param[in] Delta - OPTIONAL + + @retval EFI_SUCCESS - The Blt operation completed. + @retval EFI_INVALID_PARAMETER - BltOperation is not valid. + @retval EFI_DEVICE_ERROR - A hardware error occured writting to the video buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT)( + IN EFI_UGA_DRAW_PROTOCOL * This, + IN EFI_UGA_PIXEL * BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +/// +/// This protocol provides a basic abstraction to set video modes and +/// copy pixels to and from the graphics controller's frame buffer. +/// +struct _EFI_UGA_DRAW_PROTOCOL { + EFI_UGA_DRAW_PROTOCOL_GET_MODE GetMode; + EFI_UGA_DRAW_PROTOCOL_SET_MODE SetMode; + EFI_UGA_DRAW_PROTOCOL_BLT Blt; +}; + +extern EFI_GUID gEfiUgaDrawProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaIo.h new file mode 100644 index 0000000..874d959 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UgaIo.h @@ -0,0 +1,197 @@ +/** @file + UGA IO protocol from the EFI 1.10 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UGA_IO_H__ +#define __UGA_IO_H__ + +#define EFI_UGA_IO_PROTOCOL_GUID \ + { 0x61a4d49e, 0x6f68, 0x4f1b, { 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 } } + +typedef struct _EFI_UGA_IO_PROTOCOL EFI_UGA_IO_PROTOCOL; + +typedef UINT32 UGA_STATUS; + +typedef enum { + UgaDtParentBus = 1, + UgaDtGraphicsController, + UgaDtOutputController, + UgaDtOutputPort, + UgaDtOther +} UGA_DEVICE_TYPE, *PUGA_DEVICE_TYPE; + +typedef UINT32 UGA_DEVICE_ID, *PUGA_DEVICE_ID; + +typedef struct { + UGA_DEVICE_TYPE deviceType; + UGA_DEVICE_ID deviceId; + UINT32 ui32DeviceContextSize; + UINT32 ui32SharedContextSize; +} UGA_DEVICE_DATA, *PUGA_DEVICE_DATA; + +typedef struct _UGA_DEVICE { + VOID *pvDeviceContext; + VOID *pvSharedContext; + VOID *pvRunTimeContext; + struct _UGA_DEVICE *pParentDevice; + VOID *pvBusIoServices; + VOID *pvStdIoServices; + UGA_DEVICE_DATA deviceData; +} UGA_DEVICE, *PUGA_DEVICE; + +typedef enum { + UgaIoGetVersion = 1, + UgaIoGetChildDevice, + UgaIoStartDevice, + UgaIoStopDevice, + UgaIoFlushDevice, + UgaIoResetDevice, + UgaIoGetDeviceState, + UgaIoSetDeviceState, + UgaIoSetPowerState, + UgaIoGetMemoryConfiguration, + UgaIoSetVideoMode, + UgaIoCopyRectangle, + UgaIoGetEdidSegment, + UgaIoDeviceChannelOpen, + UgaIoDeviceChannelClose, + UgaIoDeviceChannelRead, + UgaIoDeviceChannelWrite, + UgaIoGetPersistentDataSize, + UgaIoGetPersistentData, + UgaIoSetPersistentData, + UgaIoGetDevicePropertySize, + UgaIoGetDeviceProperty, + UgaIoBtPrivateInterface +} UGA_IO_REQUEST_CODE, *PUGA_IO_REQUEST_CODE; + +typedef struct { + IN UGA_IO_REQUEST_CODE ioRequestCode; + IN VOID *pvInBuffer; + IN UINT64 ui64InBufferSize; + OUT VOID *pvOutBuffer; + IN UINT64 ui64OutBufferSize; + OUT UINT64 ui64BytesReturned; +} UGA_IO_REQUEST, *PUGA_IO_REQUEST; + + +/** + Dynamically allocate storage for a child UGA_DEVICE. + + @param[in] This The EFI_UGA_IO_PROTOCOL instance. + @param[in] ParentDevice ParentDevice specifies a pointer to the parent device of Device. + @param[in] DeviceData A pointer to UGA_DEVICE_DATA returned from a call to DispatchService() + with a UGA_DEVICE of Parent and an IoRequest of type UgaIoGetChildDevice. + @param[in] RunTimeContext Context to associate with Device. + @param[out] Device The Device returns a dynamically allocated child UGA_DEVICE object + for ParentDevice. The caller is responsible for deleting Device. + + + @retval EFI_SUCCESS Device was returned. + @retval EFI_INVALID_PARAMETER One of the arguments was not valid. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_IO_PROTOCOL_CREATE_DEVICE)( + IN EFI_UGA_IO_PROTOCOL *This, + IN UGA_DEVICE *ParentDevice, + IN UGA_DEVICE_DATA *DeviceData, + IN VOID *RunTimeContext, + OUT UGA_DEVICE **Device + ); + + +/** + Delete a dynamically allocated child UGA_DEVICE object that was allocated via CreateDevice(). + + @param[in] This The EFI_UGA_IO_PROTOCOL instance. Type EFI_UGA_IO_PROTOCOL is + defined in Section 10.7. + @param[in] Device The Device points to a UGA_DEVICE object that was dynamically + allocated via a CreateDevice() call. + + + @retval EFI_SUCCESS Device was returned. + @retval EFI_INVALID_PARAMETER The Device was not allocated via CreateDevice(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_IO_PROTOCOL_DELETE_DEVICE)( + IN EFI_UGA_IO_PROTOCOL * This, + IN UGA_DEVICE * Device + ); + +/** + This is the main UGA service dispatch routine for all UGA_IO_REQUEST s. + + @param pDevice pDevice specifies a pointer to a device object associated with a + device enumerated by a pIoRequest->ioRequestCode of type + UgaIoGetChildDevice. The root device for the EFI_UGA_IO_PROTOCOL + is represented by pDevice being set to NULL. + + @param pIoRequest + pIoRequest points to a caller allocated buffer that contains data + defined by pIoRequest->ioRequestCode. See Related Definitions for + a definition of UGA_IO_REQUEST_CODE s and their associated data + structures. + + @return UGA_STATUS + +**/ +typedef UGA_STATUS +(EFIAPI *PUGA_FW_SERVICE_DISPATCH)( + IN PUGA_DEVICE pDevice, + IN OUT PUGA_IO_REQUEST pIoRequest + ); + +/// +/// Provides a basic abstraction to send I/O requests to the graphics device and any of its children. +/// +struct _EFI_UGA_IO_PROTOCOL { + EFI_UGA_IO_PROTOCOL_CREATE_DEVICE CreateDevice; + EFI_UGA_IO_PROTOCOL_DELETE_DEVICE DeleteDevice; + PUGA_FW_SERVICE_DISPATCH DispatchService; +}; + +extern EFI_GUID gEfiUgaIoProtocolGuid; + +// +// Data structure that is stored in the EFI Configuration Table with the +// EFI_UGA_IO_PROTOCOL_GUID. The option ROMs listed in this table may have +// EBC UGA drivers. +// +typedef struct { + UINT32 Version; + UINT32 HeaderSize; + UINT32 SizeOfEntries; + UINT32 NumberOfEntries; +} EFI_DRIVER_OS_HANDOFF_HEADER; + +typedef enum { + EfiUgaDriverFromPciRom, + EfiUgaDriverFromSystem, + EfiDriverHandoffMax +} EFI_DRIVER_HANOFF_ENUM; + +typedef struct { + EFI_DRIVER_HANOFF_ENUM Type; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VOID *PciRomImage; + UINT64 PciRomSize; +} EFI_DRIVER_OS_HANDOFF; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UnicodeCollation.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UnicodeCollation.h new file mode 100644 index 0000000..07e4648 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UnicodeCollation.h @@ -0,0 +1,192 @@ +/** @file + Unicode Collation protocol that follows the UEFI 2.0 specification. + This protocol is used to allow code running in the boot services environment + to perform lexical comparison functions on Unicode strings for given languages. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UNICODE_COLLATION_H__ +#define __UNICODE_COLLATION_H__ + +#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \ + { \ + 0x1d85cd7f, 0xf43d, 0x11d2, {0x9a, 0xc, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_UNICODE_COLLATION_PROTOCOL2_GUID \ + { \ + 0xa4c751fc, 0x23ae, 0x4c3e, {0x92, 0xe9, 0x49, 0x64, 0xcf, 0x63, 0xf3, 0x49 } \ + } + +typedef struct _EFI_UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_PROTOCOL; + + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_PROTOCOL_GUID + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_UNICODE_COLLATION_PROTOCOL UNICODE_COLLATION_INTERFACE; + +/// +/// Protocol data structures and defines +/// +#define EFI_UNICODE_BYTE_ORDER_MARK (CHAR16) (0xfeff) + +// +// Protocol member functions +// +/** + Performs a case-insensitive comparison of two Null-terminated strings. + + @param This A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + @param Str1 A pointer to a Null-terminated string. + @param Str2 A pointer to a Null-terminated string. + + @retval 0 Str1 is equivalent to Str2. + @retval >0 Str1 is lexically greater than Str2. + @retval <0 Str1 is lexically less than Str2. + +**/ +typedef +INTN +(EFIAPI *EFI_UNICODE_COLLATION_STRICOLL)( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ); + +/** + Performs a case-insensitive comparison of a Null-terminated + pattern string and a Null-terminated string. + + @param This A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + @param String A pointer to a Null-terminated string. + @param Pattern A pointer to a Null-terminated pattern string. + + @retval TRUE Pattern was found in String. + @retval FALSE Pattern was not found in String. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_UNICODE_COLLATION_METAIMATCH)( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ); + +/** + Converts all the characters in a Null-terminated string to + lower case characters. + + @param This A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + @param String A pointer to a Null-terminated string. + +**/ +typedef +VOID +(EFIAPI *EFI_UNICODE_COLLATION_STRLWR)( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ); + +/** + Converts all the characters in a Null-terminated string to upper + case characters. + + @param This A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + @param String A pointer to a Null-terminated string. + +**/ +typedef +VOID +(EFIAPI *EFI_UNICODE_COLLATION_STRUPR)( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ); + +/** + Converts an 8.3 FAT file name in an OEM character set to a Null-terminated + string. + + @param This A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + @param FatSize The size of the string Fat in bytes. + @param Fat A pointer to a Null-terminated string that contains an 8.3 file + name using an 8-bit OEM character set. + @param String A pointer to a Null-terminated string. The string must + be allocated in advance to hold FatSize characters. + +**/ +typedef +VOID +(EFIAPI *EFI_UNICODE_COLLATION_FATTOSTR)( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ); + +/** + Converts a Null-terminated string to legal characters in a FAT + filename using an OEM character set. + + @param This A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + @param String A pointer to a Null-terminated string. + @param FatSize The size of the string Fat in bytes. + @param Fat A pointer to a string that contains the converted version of + String using legal FAT characters from an OEM character set. + + @retval TRUE One or more conversions failed and were substituted with '_' + @retval FALSE None of the conversions failed. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_UNICODE_COLLATION_STRTOFAT)( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ); + +/// +/// The EFI_UNICODE_COLLATION_PROTOCOL is used to perform case-insensitive +/// comparisons of strings. +/// +struct _EFI_UNICODE_COLLATION_PROTOCOL { + EFI_UNICODE_COLLATION_STRICOLL StriColl; + EFI_UNICODE_COLLATION_METAIMATCH MetaiMatch; + EFI_UNICODE_COLLATION_STRLWR StrLwr; + EFI_UNICODE_COLLATION_STRUPR StrUpr; + + // + // for supporting fat volumes + // + EFI_UNICODE_COLLATION_FATTOSTR FatToStr; + EFI_UNICODE_COLLATION_STRTOFAT StrToFat; + + /// + /// A Null-terminated ASCII string array that contains one or more language codes. + /// When this field is used for UnicodeCollation2, it is specified in RFC 4646 format. + /// When it is used for UnicodeCollation, it is specified in ISO 639-2 format. + /// + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiUnicodeCollationProtocolGuid; +extern EFI_GUID gEfiUnicodeCollation2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Usb2HostController.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Usb2HostController.h new file mode 100644 index 0000000..df6cb68 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Usb2HostController.h @@ -0,0 +1,664 @@ +/** @file + EFI_USB2_HC_PROTOCOL as defined in UEFI 2.0. + The USB Host Controller Protocol is used by code, typically USB bus drivers, + running in the EFI boot services environment, to perform data transactions over + a USB bus. In addition, it provides an abstraction for the root hub of the USB bus. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USB2_HOSTCONTROLLER_H_ +#define _USB2_HOSTCONTROLLER_H_ + +#include + +#define EFI_USB2_HC_PROTOCOL_GUID \ + { \ + 0x3e745226, 0x9818, 0x45b6, {0xa2, 0xac, 0xd7, 0xcd, 0xe, 0x8b, 0xa2, 0xbc } \ + } + +/// +/// Forward reference for pure ANSI compatability +/// +typedef struct _EFI_USB2_HC_PROTOCOL EFI_USB2_HC_PROTOCOL; + + +typedef struct { + UINT16 PortStatus; ///< Contains current port status bitmap. + UINT16 PortChangeStatus; ///< Contains current port status change bitmap. +} EFI_USB_PORT_STATUS; + +/// +/// EFI_USB_PORT_STATUS.PortStatus bit definition +/// +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_LOW_SPEED 0x0200 +#define USB_PORT_STAT_HIGH_SPEED 0x0400 +#define USB_PORT_STAT_SUPER_SPEED 0x0800 +#define USB_PORT_STAT_OWNER 0x2000 + +/// +/// EFI_USB_PORT_STATUS.PortChangeStatus bit definition +/// +#define USB_PORT_STAT_C_CONNECTION 0x0001 +#define USB_PORT_STAT_C_ENABLE 0x0002 +#define USB_PORT_STAT_C_SUSPEND 0x0004 +#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +#define USB_PORT_STAT_C_RESET 0x0010 + + +/// +/// Usb port features value +/// Each value indicates its bit index in the port status and status change bitmaps, +/// if combines these two bitmaps into a 32-bit bitmap. +/// +typedef enum { + EfiUsbPortEnable = 1, + EfiUsbPortSuspend = 2, + EfiUsbPortReset = 4, + EfiUsbPortPower = 8, + EfiUsbPortOwner = 13, + EfiUsbPortConnectChange = 16, + EfiUsbPortEnableChange = 17, + EfiUsbPortSuspendChange = 18, + EfiUsbPortOverCurrentChange = 19, + EfiUsbPortResetChange = 20 +} EFI_USB_PORT_FEATURE; + +#define EFI_USB_SPEED_FULL 0x0000 ///< 12 Mb/s, USB 1.1 OHCI and UHCI HC. +#define EFI_USB_SPEED_LOW 0x0001 ///< 1 Mb/s, USB 1.1 OHCI and UHCI HC. +#define EFI_USB_SPEED_HIGH 0x0002 ///< 480 Mb/s, USB 2.0 EHCI HC. +#define EFI_USB_SPEED_SUPER 0x0003 ///< 4.8 Gb/s, USB 3.0 XHCI HC. + +typedef struct { + UINT8 TranslatorHubAddress; ///< device address + UINT8 TranslatorPortNumber; ///< the port number of the hub that device is connected to. +} EFI_USB2_HC_TRANSACTION_TRANSLATOR; + +// +// Protocol definitions +// + +/** + Retrieves the Host Controller capabilities. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param MaxSpeed Host controller data transfer speed. + @param PortNumber Number of the root hub ports. + @param Is64BitCapable TRUE if controller supports 64-bit memory addressing, + FALSE otherwise. + + @retval EFI_SUCCESS The host controller capabilities were retrieved successfully. + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to + retrieve the capabilities. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_GET_CAPABILITY)( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ); + +#define EFI_USB_HC_RESET_GLOBAL 0x0001 +#define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 +#define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 +#define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 +/** + Provides software reset for the USB host controller. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param Attributes A bit mask of the reset operation to perform. + + @retval EFI_SUCCESS The reset operation succeeded. + @retval EFI_INVALID_PARAMETER Attributes is not valid. + @retval EFI_UNSUPPORTED The type of reset specified by Attributes is not currently + supported by the host controller hardware. + @retval EFI_ACCESS_DENIED Reset operation is rejected due to the debug port being configured + and active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or + EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Attributes can be used to + perform reset operation for this host controller. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to + retrieve the capabilities. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_RESET)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ); + +/** + Enumration value for status of USB HC. +**/ +typedef enum { + EfiUsbHcStateHalt, ///< The host controller is in halt + ///< state. No USB transactions can occur + ///< while in this state. The host + ///< controller can enter this state for + ///< three reasons: 1) After host + ///< controller hardware reset. 2) + ///< Explicitly set by software. 3) + ///< Triggered by a fatal error such as + ///< consistency check failure. + + EfiUsbHcStateOperational, ///< The host controller is in an + ///< operational state. When in + ///< this state, the host + ///< controller can execute bus + ///< traffic. This state must be + ///< explicitly set to enable the + ///< USB bus traffic. + + EfiUsbHcStateSuspend, ///< The host controller is in the + ///< suspend state. No USB + ///< transactions can occur while in + ///< this state. The host controller + ///< enters this state for the + ///< following reasons: 1) Explicitly + ///< set by software. 2) Triggered + ///< when there is no bus traffic for + ///< 3 microseconds. + + EfiUsbHcStateMaximum ///< Maximum value for enumration value of HC status. +} EFI_USB_HC_STATE; + +/** + Retrieves current state of the USB host controller. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param State A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + + @retval EFI_SUCCESS The state information of the host controller was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the + host controller's current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_GET_STATE)( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State +); + +/** + Sets the USB host controller to a specific state. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param State Indicates the state of the host controller that will be set. + + @retval EFI_SUCCESS The USB host controller was successfully placed in the state + specified by State. + @retval EFI_INVALID_PARAMETER State is not valid. + @retval EFI_DEVICE_ERROR Failed to set the state specified by State due to device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_SET_STATE)( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ); + +/** + Submits control transfer to a target USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size that the default control transfer + endpoint is capable of sending or receiving. + @param Request A pointer to the USB device request that will be sent to the USB device. + @param TransferDirection Specifies the data direction for the transfer. There are three values + available, EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData. + @param Data A pointer to the buffer of data that will be transmitted to USB device or + received from USB device. + @param DataLength On input, indicates the size, in bytes, of the data buffer specified by Data. + On output, indicates the amount of data actually transferred. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer is + allowed to complete. + @param Translator A pointer to the transaction translator data. + @param TransferResult A pointer to the detailed result information generated by this control + transfer. + + @retval EFI_SUCCESS The control transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources. + @retval EFI_TIMEOUT The control transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_CONTROL_TRANSFER)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +#define EFI_USB_MAX_BULK_BUFFER_NUM 10 + +/** + Submits bulk transfer to a bulk endpoint of a USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param DataBuffersNumber Number of data buffers prepared for the transfer. + @param Data Array of pointers to the buffers of data that will be transmitted to USB + device or received from USB device. + @param DataLength When input, indicates the size, in bytes, of the data buffers specified by + Data. When output, indicates the actually transferred data size. + @param DataToggle A pointer to the data toggle value. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer is + allowed to complete. + @param Translator A pointer to the transaction translator data. + @param TransferResult A pointer to the detailed result information of the bulk transfer. + + @retval EFI_SUCCESS The bulk transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_BULK_TRANSFER)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +/** + Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. + Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated in the following specification version. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between the host and the + target interrupt endpoint. If FALSE, the specified asynchronous interrupt + pipe is canceled. If TRUE, and an interrupt transfer exists for the target + end point, then EFI_INVALID_PARAMETER is returned. + @param DataToggle A pointer to the data toggle value. + @param PollingInterval Indicates the interval, in milliseconds, that the asynchronous interrupt + transfer is polled. + @param DataLength Indicates the length of data to be received at the rate specified by + PollingInterval from the target asynchronous interrupt endpoint. + @param Translator A pointr to the transaction translator data. + @param CallBackFunction The Callback function. This function is called at the rate specified by + PollingInterval. + @param Context The context that is passed to the CallBackFunction. This is an + optional parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully + submitted or canceled. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ); + +/** + Submits synchronous interrupt transfer to an interrupt endpoint of a USB device. + Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated in the following specification version. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB device or + received from USB device. + @param DataLength On input, the size, in bytes, of the data buffer specified by Data. On + output, the number of bytes transferred. + @param DataToggle A pointer to the data toggle value. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer is + allowed to complete. + @param Translator A pointr to the transaction translator data. + @param TransferResult A pointer to the detailed result information from the synchronous + interrupt transfer. + + @retval EFI_SUCCESS The synchronous interrupt transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The synchronous interrupt transfer could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The synchronous interrupt transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The synchronous interrupt transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +#define EFI_USB_MAX_ISO_BUFFER_NUM 7 +#define EFI_USB_MAX_ISO_BUFFER_NUM1 2 + +/** + Submits isochronous transfer to an isochronous endpoint of a USB device. + + This function is used to submit isochronous transfer to a target endpoint of a USB device. + The target endpoint is specified by DeviceAddressand EndpointAddress. Isochronous transfers are + used when working with isochronous date. It provides periodic, continuous communication between + the host and a device. Isochronous transfers can beused only by full-speed, high-speed, and + super-speed devices. + + High-speed isochronous transfers can be performed using multiple data buffers. The number of + buffers that are actually prepared for the transfer is specified by DataBuffersNumber. For + full-speed isochronous transfers this value is ignored. + + Data represents a list of pointers to the data buffers. For full-speed isochronous transfers + only the data pointed by Data[0]shall be used. For high-speed isochronous transfers and for + the split transactions depending on DataLengththere several data buffers canbe used. For the + high-speed isochronous transfers the total number of buffers must not exceed EFI_USB_MAX_ISO_BUFFER_NUM. + + For split transactions performed on full-speed device by high-speed host controller the total + number of buffers is limited to EFI_USB_MAX_ISO_BUFFER_NUM1. + If the isochronous transfer is successful, then EFI_SUCCESSis returned. The isochronous transfer + is designed to be completed within one USB frame time, if it cannot be completed, EFI_TIMEOUT + is returned. If an error other than timeout occurs during the USB transfer, then EFI_DEVICE_ERROR + is returned and the detailed status code will be returned in TransferResult. + + EFI_INVALID_PARAMETERis returned if one of the following conditionsis satisfied: + - Data is NULL. + - DataLength is 0. + - DeviceSpeed is not one of the supported values listed above. + - MaximumPacketLength is invalid. MaximumPacketLength must be 1023 or less for full-speed devices, + and 1024 or less for high-speed and super-speed devices. + - TransferResult is NULL. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL, + EFI_USB_SPEED_HIGH, or EFI_USB_SPEED_SUPER. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param DataBuffersNumber Number of data buffers prepared for the transfer. + @param Data Array of pointers to the buffers of data that will be transmitted to USB + device or received from USB device. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received from + the USB device. + @param Translator A pointer to the transaction translator data. + @param TransferResult A pointer to the detailed result information of the isochronous transfer. + + @retval EFI_SUCCESS The isochronous transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The isochronous transfer could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The isochronous transfer cannot be completed within the one USB frame time. + @retval EFI_DEVICE_ERROR The isochronous transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_ISOCHRONOUS_TRANSFER)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ); + +/** + Submits nonblocking isochronous transfer to an isochronous endpoint of a USB device. + + This is an asynchronous type of USB isochronous transfer. If the caller submits a USB + isochronous transfer request through this function, this function will return immediately. + + When the isochronous transfer completes, the IsochronousCallbackfunction will be triggered, + the caller can know the transfer results. If the transfer is successful, the caller can get + the data received or sent in this callback function. + + The target endpoint is specified by DeviceAddressand EndpointAddress. Isochronous transfers + are used when working with isochronous date. It provides periodic, continuous communication + between the host and a device. Isochronous transfers can be used only by full-speed, high-speed, + and super-speed devices. + + High-speed isochronous transfers can be performed using multiple data buffers. The number of + buffers that are actually prepared for the transfer is specified by DataBuffersNumber. For + full-speed isochronous transfers this value is ignored. + + Data represents a list of pointers to the data buffers. For full-speed isochronous transfers + only the data pointed by Data[0] shall be used. For high-speed isochronous transfers and for + the split transactions depending on DataLength there several data buffers can be used. For + the high-speed isochronous transfers the total number of buffers must not exceed EFI_USB_MAX_ISO_BUFFER_NUM. + + For split transactions performed on full-speed device by high-speed host controller the total + number of buffers is limited to EFI_USB_MAX_ISO_BUFFER_NUM1. + + EFI_INVALID_PARAMETER is returned if one of the following conditionsis satisfied: + - Data is NULL. + - DataLength is 0. + - DeviceSpeed is not one of the supported values listed above. + - MaximumPacketLength is invalid. MaximumPacketLength must be 1023 or less for full-speed + devices and 1024 or less for high-speed and super-speed devices. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL, + EFI_USB_SPEED_HIGH, or EFI_USB_SPEED_SUPER. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param DataBuffersNumber Number of data buffers prepared for the transfer. + @param Data Array of pointers to the buffers of data that will be transmitted to USB + device or received from USB device. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received from + the USB device. + @param Translator A pointer to the transaction translator data. + @param IsochronousCallback The Callback function. This function is called if the requested + isochronous transfer is completed. + @param Context Data passed to the IsochronousCallback function. This is an + optional parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous isochronous transfer request has been successfully + submitted or canceled. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The asynchronous isochronous transfer could not be submitted due to + a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +/** + Retrieves the current status of a USB root hub port. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. + @param PortStatus A pointer to the current port status bits and port status change bits. + + @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + @retval EFI_INVALID_PARAMETER PortNumber is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ); + +/** + Sets a feature for the specified root hub port. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port whose feature is requested to be set. This + value is zero based. + @param PortFeature Indicates the feature selector associated with the feature set request. + + @retval EFI_SUCCESS The feature specified by PortFeature was set for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +/** + Clears a feature for the specified root hub port. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port whose feature is requested to be cleared. This + value is zero based. + @param PortFeature Indicates the feature selector associated with the feature clear request. + + @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE)( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +/// +/// The EFI_USB2_HC_PROTOCOL provides USB host controller management, basic +/// data transactions over a USB bus, and USB root hub access. A device driver +/// that wishes to manage a USB bus in a system retrieves the EFI_USB2_HC_PROTOCOL +/// instance that is associated with the USB bus to be managed. A device handle +/// for a USB host controller will minimally contain an EFI_DEVICE_PATH_PROTOCOL +/// instance, and an EFI_USB2_HC_PROTOCOL instance. +/// +struct _EFI_USB2_HC_PROTOCOL { + EFI_USB2_HC_PROTOCOL_GET_CAPABILITY GetCapability; + EFI_USB2_HC_PROTOCOL_RESET Reset; + EFI_USB2_HC_PROTOCOL_GET_STATE GetState; + EFI_USB2_HC_PROTOCOL_SET_STATE SetState; + EFI_USB2_HC_PROTOCOL_CONTROL_TRANSFER ControlTransfer; + EFI_USB2_HC_PROTOCOL_BULK_TRANSFER BulkTransfer; + EFI_USB2_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER AsyncInterruptTransfer; + EFI_USB2_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER SyncInterruptTransfer; + EFI_USB2_HC_PROTOCOL_ISOCHRONOUS_TRANSFER IsochronousTransfer; + EFI_USB2_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER AsyncIsochronousTransfer; + EFI_USB2_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS GetRootHubPortStatus; + EFI_USB2_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE SetRootHubPortFeature; + EFI_USB2_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE ClearRootHubPortFeature; + + /// + /// The major revision number of the USB host controller. The revision information + /// indicates the release of the Universal Serial Bus Specification with which the + /// host controller is compliant. + /// + UINT16 MajorRevision; + + /// + /// The minor revision number of the USB host controller. The revision information + /// indicates the release of the Universal Serial Bus Specification with which the + /// host controller is compliant. + /// + UINT16 MinorRevision; +}; + +extern EFI_GUID gEfiUsb2HcProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbFunctionIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbFunctionIo.h new file mode 100644 index 0000000..17c2a19 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbFunctionIo.h @@ -0,0 +1,690 @@ +/** @file + The USB Function Protocol provides an I/O abstraction for a USB Controller + operating in Function mode (also commonly referred to as Device, Peripheral, + or Target mode) and the mechanisms by which the USB Function can communicate + with the USB Host. It is used by other UEFI drivers or applications to + perform data transactions and basic USB controller management over a USB + Function port. + + This simple protocol only supports USB 2.0 bulk transfers on systems with a + single configuration and a single interface. It does not support isochronous + or interrupt transfers, alternate interfaces, or USB 3.0 functionality. + Future revisions of this protocol may support these or additional features. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol was introduced in UEFI Specification 2.5. + +**/ + +#ifndef __USB_FUNCTION_IO_H__ +#define __USB_FUNCTION_IO_H__ + +#include + +#define EFI_USBFN_IO_PROTOCOL_GUID \ + { \ + 0x32d2963a, 0xfe5d, 0x4f30, {0xb6, 0x33, 0x6e, 0x5d, 0xc5, 0x58, 0x3, 0xcc} \ + } + +typedef struct _EFI_USBFN_IO_PROTOCOL EFI_USBFN_IO_PROTOCOL; + +#define EFI_USBFN_IO_PROTOCOL_REVISION 0x00010001 + +typedef enum _EFI_USBFN_PORT_TYPE { + EfiUsbUnknownPort = 0, + EfiUsbStandardDownstreamPort, + EfiUsbChargingDownstreamPort, + EfiUsbDedicatedChargingPort, + EfiUsbInvalidDedicatedChargingPort +} EFI_USBFN_PORT_TYPE; + +typedef struct { + EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptorTable; +} EFI_USB_INTERFACE_INFO; + +typedef struct { + EFI_USB_CONFIG_DESCRIPTOR *ConfigDescriptor; + EFI_USB_INTERFACE_INFO **InterfaceInfoTable; +} EFI_USB_CONFIG_INFO; + +typedef struct { + EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor; + EFI_USB_CONFIG_INFO **ConfigInfoTable; +} EFI_USB_DEVICE_INFO; + +typedef enum _EFI_USB_ENDPOINT_TYPE { + UsbEndpointControl = 0x00, + //UsbEndpointIsochronous = 0x01, + UsbEndpointBulk = 0x02, + //UsbEndpointInterrupt = 0x03 +} EFI_USB_ENDPOINT_TYPE; + +typedef enum _EFI_USBFN_DEVICE_INFO_ID { + EfiUsbDeviceInfoUnknown = 0, + EfiUsbDeviceInfoSerialNumber, + EfiUsbDeviceInfoManufacturerName, + EfiUsbDeviceInfoProductName +} EFI_USBFN_DEVICE_INFO_ID; + +typedef enum _EFI_USBFN_ENDPOINT_DIRECTION { + EfiUsbEndpointDirectionHostOut = 0, + EfiUsbEndpointDirectionHostIn, + EfiUsbEndpointDirectionDeviceTx = EfiUsbEndpointDirectionHostIn, + EfiUsbEndpointDirectionDeviceRx = EfiUsbEndpointDirectionHostOut +} EFI_USBFN_ENDPOINT_DIRECTION; + +typedef enum _EFI_USBFN_MESSAGE { + // + // Nothing + // + EfiUsbMsgNone = 0, + // + // SETUP packet is received, returned Buffer contains + // EFI_USB_DEVICE_REQUEST struct + // + EfiUsbMsgSetupPacket, + // + // Indicates that some of the requested data has been received from the + // host. It is the responsibility of the class driver to determine if it + // needs to wait for any remaining data. Returned Buffer contains + // EFI_USBFN_TRANSFER_RESULT struct containing endpoint number, transfer + // status and count of bytes received. + // + EfiUsbMsgEndpointStatusChangedRx, + // + // Indicates that some of the requested data has been transmitted to the + // host. It is the responsibility of the class driver to determine if any + // remaining data needs to be resent. Returned Buffer contains + // EFI_USBFN_TRANSFER_RESULT struct containing endpoint number, transfer + // status and count of bytes sent. + // + EfiUsbMsgEndpointStatusChangedTx, + // + // DETACH bus event signaled + // + EfiUsbMsgBusEventDetach, + // + // ATTACH bus event signaled + // + EfiUsbMsgBusEventAttach, + // + // RESET bus event signaled + // + EfiUsbMsgBusEventReset, + // + // SUSPEND bus event signaled + // + EfiUsbMsgBusEventSuspend, + // + // RESUME bus event signaled + // + EfiUsbMsgBusEventResume, + // + // Bus speed updated, returned buffer indicated bus speed using + // following enumeration named EFI_USB_BUS_SPEED + // + EfiUsbMsgBusEventSpeed +} EFI_USBFN_MESSAGE; + +typedef enum _EFI_USBFN_TRANSFER_STATUS { + UsbTransferStatusUnknown = 0, + UsbTransferStatusComplete, + UsbTransferStatusAborted, + UsbTransferStatusActive, + UsbTransferStatusNone +} EFI_USBFN_TRANSFER_STATUS; + +typedef struct _EFI_USBFN_TRANSFER_RESULT { + UINTN BytesTransferred; + EFI_USBFN_TRANSFER_STATUS TransferStatus; + UINT8 EndpointIndex; + EFI_USBFN_ENDPOINT_DIRECTION Direction; + VOID *Buffer; +} EFI_USBFN_TRANSFER_RESULT; + +typedef enum _EFI_USB_BUS_SPEED { + UsbBusSpeedUnknown = 0, + UsbBusSpeedLow, + UsbBusSpeedFull, + UsbBusSpeedHigh, + UsbBusSpeedSuper, + UsbBusSpeedMaximum = UsbBusSpeedSuper +} EFI_USB_BUS_SPEED; + +typedef union _EFI_USBFN_MESSAGE_PAYLOAD { + EFI_USB_DEVICE_REQUEST udr; + EFI_USBFN_TRANSFER_RESULT utr; + EFI_USB_BUS_SPEED ubs; +} EFI_USBFN_MESSAGE_PAYLOAD; + +typedef enum _EFI_USBFN_POLICY_TYPE { + EfiUsbPolicyUndefined = 0, + EfiUsbPolicyMaxTransactionSize, + EfiUsbPolicyZeroLengthTerminationSupport, + EfiUsbPolicyZeroLengthTermination +} EFI_USBFN_POLICY_TYPE; + +/** + Returns information about what USB port type was attached. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[out] PortType Returns the USB port type. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to + process this request or there is no USB port + attached to the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_DETECT_PORT) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_PORT_TYPE *PortType + ); + +/** + Configures endpoints based on supplied device and configuration descriptors. + + Assuming that the hardware has already been initialized, this function configures + the endpoints using the device information supplied by DeviceInfo, activates the + port, and starts receiving USB events. + + This function must ignore the bMaxPacketSize0field of the Standard Device Descriptor + and the wMaxPacketSize field of the Standard Endpoint Descriptor that are made + available through DeviceInfo. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[out] DeviceInfo A pointer to EFI_USBFN_DEVICE_INFO instance. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of + resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_CONFIGURE_ENABLE_ENDPOINTS) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USB_DEVICE_INFO *DeviceInfo + ); + +/** + Returns the maximum packet size of the specified endpoint type for the supplied + bus speed. + + If the BusSpeed is UsbBusSpeedUnknown, the maximum speed the underlying controller + supports is assumed. + + This protocol currently does not support isochronous or interrupt transfers. Future + revisions of this protocol may eventually support it. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOLinstance. + @param[in] EndpointType Endpoint type as defined as EFI_USB_ENDPOINT_TYPE. + @param[in] BusSpeed Bus speed as defined as EFI_USB_BUS_SPEED. + @param[out] MaxPacketSize The maximum packet size, in bytes, of the specified + endpoint type. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_GET_ENDPOINT_MAXPACKET_SIZE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_ENDPOINT_TYPE EndpointType, + IN EFI_USB_BUS_SPEED BusSpeed, + OUT UINT16 *MaxPacketSize + ); + +/** + Returns device specific information based on the supplied identifier as a Unicode string. + + If the supplied Buffer isn't large enough, or is NULL, the method fails with + EFI_BUFFER_TOO_SMALL and the required size is returned through BufferSize. All returned + strings are in Unicode format. + + An Id of EfiUsbDeviceInfoUnknown is treated as an invalid parameter. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOLinstance. + @param[in] Id The requested information id. + + + @param[in] BufferSize On input, the size of the Buffer in bytes. On output, the + amount of data returned in Buffer in bytes. + @param[out] Buffer A pointer to a buffer to returnthe requested information + as a Unicode string. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + BufferSize is NULL. + *BufferSize is not 0 and Buffer is NULL. + Id in invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the buffer. + *BufferSize has been updated with the size needed to hold the request string. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_GET_DEVICE_INFO) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USBFN_DEVICE_INFO_ID Id, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer OPTIONAL +); + +/** + Returns the vendor-id and product-id of the device. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[out] Vid Returned vendor-id of the device. + @param[out] Pid Returned product-id of the device. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Unable to return the vendor-id or the product-id. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_GET_VENDOR_ID_PRODUCT_ID) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINT16 *Vid, + OUT UINT16 *Pid +); + +/** + Aborts the transfer on the specified endpoint. + + This function should fail with EFI_INVALID_PARAMETER if the specified direction + is incorrect for the endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] EndpointIndex Indicates the endpoint on which the ongoing transfer + needs to be canceled. + @param[in] Direction Direction of the endpoint. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_ABORT_TRANSFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction +); + +/** + Returns the stall state on the specified endpoint. + + This function should fail with EFI_INVALID_PARAMETER if the specified direction + is incorrect for the endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] EndpointIndex Indicates the endpoint. + @param[in] Direction Direction of the endpoint. + @param[in, out] State Boolean, true value indicates that the endpoint + is in a stalled state, false otherwise. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_GET_ENDPOINT_STALL_STATE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT BOOLEAN *State +); + +/** + Sets or clears the stall state on the specified endpoint. + + This function should fail with EFI_INVALID_PARAMETER if the specified direction + is incorrect for the endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] EndpointIndex Indicates the endpoint. + @param[in] Direction Direction of the endpoint. + @param[in] State Requested stall state on the specified endpoint. + True value causes the endpoint to stall; false + value clears an existing stall. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_SET_ENDPOINT_STALL_STATE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT BOOLEAN *State +); + +/** + This function is called repeatedly to get information on USB bus states, + receive-completion and transmit-completion events on the endpoints, and + notification on setup packet on endpoint 0. + + A class driver must call EFI_USBFN_IO_PROTOCOL.EventHandler()repeatedly + to receive updates on the transfer status and number of bytes transferred + on various endpoints. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[out] Message Indicates the event that initiated this notification. + @param[in, out] PayloadSize On input, the size of the memory pointed by + Payload. On output, the amount ofdata returned + in Payload. + @param[out] Payload A pointer to EFI_USBFN_MESSAGE_PAYLOAD instance + to return additional payload for current message. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + @retval EFI_BUFFER_TOO_SMALL The Supplied buffer is not large enough to hold + the message payload. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_EVENTHANDLER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload +); + +/** + This function handles transferring data to or from the host on the specified + endpoint, depending on the direction specified. + + A class driver must call EFI_USBFN_IO_PROTOCOL.EventHandler() repeatedly to + receive updates on the transfer status and the number of bytes transferred on + various endpoints. Upon an update of the transfer status, the Buffer field of + the EFI_USBFN_TRANSFER_RESULT structure (as described in the function description + for EFI_USBFN_IO_PROTOCOL.EventHandler()) must be initialized with the Buffer + pointer that was supplied to this method. + + The overview of the call sequence is illustrated in the Figure 54. + + This function should fail with EFI_INVALID_PARAMETER if the specified direction + is incorrect for the endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] EndpointIndex Indicates the endpoint on which TX or RX transfer + needs to take place. + @param[in] Direction Direction of the endpoint. + @param[in, out] BufferSize If Direction is EfiUsbEndpointDirectionDeviceRx: + On input, the size of the Bufferin bytes. + On output, the amount of data returned in Buffer + in bytes. + If Direction is EfiUsbEndpointDirectionDeviceTx: + On input, the size of the Bufferin bytes. + On output, the amount of data transmitted in bytes. + @param[in, out] Buffer If Direction is EfiUsbEndpointDirectionDeviceRx: + The Buffer to return the received data. + If Directionis EfiUsbEndpointDirectionDeviceTx: + The Buffer that contains the data to be transmitted. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_TRANSFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer +); + +/** + Returns the maximum supported transfer size. + + Returns the maximum number of bytes that the underlying controller can accommodate + in a single transfer. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[out] MaxTransferSize The maximum supported transfer size, in bytes. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready to process + this request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_GET_MAXTRANSFER_SIZE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINTN *MaxTransferSize + ); + +/** + Allocates a transfer buffer of the specified sizethat satisfies the controller + requirements. + + The AllocateTransferBuffer() function allocates a memory region of Size bytes and + returns the address of the allocated memory that satisfies the underlying controller + requirements in the location referenced by Buffer. + + The allocated transfer buffer must be freed using a matching call to + EFI_USBFN_IO_PROTOCOL.FreeTransferBuffer()function. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] Size The number of bytes to allocate for the transfer buffer. + @param[out] Buffer A pointer to a pointer to the allocated buffer if the + call succeeds; undefined otherwise. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES The requested transfer buffer could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_ALLOCATE_TRANSFER_BUFFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Deallocates the memory allocated for the transfer buffer by the + EFI_USBFN_IO_PROTOCOL.AllocateTransferBuffer() function. + + The EFI_USBFN_IO_PROTOCOL.FreeTransferBuffer() function deallocates the + memory specified by Buffer. The Buffer that is freed must have been allocated + by EFI_USBFN_IO_PROTOCOL.AllocateTransferBuffer(). + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] Buffer A pointer to the transfer buffer to deallocate. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_FREE_TRANSFER_BUFFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer + ); + +/** + This function supplies power to the USB controller if needed and initializes + the hardware and the internal data structures. The port must not be activated + by this function. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_START_CONTROLLER) ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +/** + This function stops the USB hardware device. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_STOP_CONTROLLER) ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +/** + This function sets the configuration policy for the specified non-control + endpoint. + + This function can only be called before EFI_USBFN_IO_PROTOCOL.StartController() + or after EFI_USBFN_IO_PROTOCOL.StopController() has been called. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] EndpointIndex Indicates the non-control endpoint for which the + policy needs to be set. + @param[in] Direction Direction of the endpoint. + @param[in] PolicyType Policy type the user is trying to set for the + specified non-control endpoint. + @param[in] BufferSize The size of the Bufferin bytes. + @param[in] Buffer The new value for the policy parameter that + PolicyType specifies. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_UNSUPPORTED Changing this policy value is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_SET_ENDPOINT_POLICY) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + This function sets the configuration policy for the specified non-control + endpoint. + + This function can only be called before EFI_USBFN_IO_PROTOCOL.StartController() + or after EFI_USBFN_IO_PROTOCOL.StopController() has been called. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance. + @param[in] EndpointIndex Indicates the non-control endpoint for which the + policy needs to be set. + @param[in] Direction Direction of the endpoint. + @param[in] PolicyType Policy type the user is trying to retrieve for + the specified non-control endpoint. + @param[in, out] BufferSize On input, the size of Bufferin bytes. On output, + the amount of data returned in Bufferin bytes. + @param[in, out] Buffer A pointer to a buffer to return requested endpoint + policy value. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The specified policy value is not supported. + @retval EFI_BUFFER_TOO_SMALL Supplied buffer is not large enough to hold requested + policy value. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_GET_ENDPOINT_POLICY) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ); + +/// +/// The EFI_USBFN_IO_PROTOCOL provides basic data transactions and basic USB +/// controller management for a USB Function port. +/// +struct _EFI_USBFN_IO_PROTOCOL { + UINT32 Revision; + EFI_USBFN_IO_DETECT_PORT DetectPort; + EFI_USBFN_IO_CONFIGURE_ENABLE_ENDPOINTS ConfigureEnableEndpoints; + EFI_USBFN_IO_GET_ENDPOINT_MAXPACKET_SIZE GetEndpointMaxPacketSize; + EFI_USBFN_IO_GET_DEVICE_INFO GetDeviceInfo; + EFI_USBFN_IO_GET_VENDOR_ID_PRODUCT_ID GetVendorIdProductId; + EFI_USBFN_IO_ABORT_TRANSFER AbortTransfer; + EFI_USBFN_IO_GET_ENDPOINT_STALL_STATE GetEndpointStallState; + EFI_USBFN_IO_SET_ENDPOINT_STALL_STATE SetEndpointStallState; + EFI_USBFN_IO_EVENTHANDLER EventHandler; + EFI_USBFN_IO_TRANSFER Transfer; + EFI_USBFN_IO_GET_MAXTRANSFER_SIZE GetMaxTransferSize; + EFI_USBFN_IO_ALLOCATE_TRANSFER_BUFFER AllocateTransferBuffer; + EFI_USBFN_IO_FREE_TRANSFER_BUFFER FreeTransferBuffer; + EFI_USBFN_IO_START_CONTROLLER StartController; + EFI_USBFN_IO_STOP_CONTROLLER StopController; + EFI_USBFN_IO_SET_ENDPOINT_POLICY SetEndpointPolicy; + EFI_USBFN_IO_GET_ENDPOINT_POLICY GetEndpointPolicy; +}; + +extern EFI_GUID gEfiUsbFunctionIoProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbHostController.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbHostController.h new file mode 100644 index 0000000..8710c92 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbHostController.h @@ -0,0 +1,508 @@ +/** @file + EFI_USB_HC_PROTOCOL as defined in EFI 1.10. + + The USB Host Controller Protocol is used by code, typically USB bus drivers, + running in the EFI boot services environment, to perform data transactions + over a USB bus. In addition, it provides an abstraction for the root hub of the USB bus. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USB_HOSTCONTROLLER_H_ +#define _USB_HOSTCONTROLLER_H_ + +#include + +#define EFI_USB_HC_PROTOCOL_GUID \ + { \ + 0xf5089266, 0x1aa0, 0x4953, {0x97, 0xd8, 0x56, 0x2f, 0x8a, 0x73, 0xb5, 0x19 } \ + } + +/// +/// Forward reference for pure ANSI compatability +/// +typedef struct _EFI_USB_HC_PROTOCOL EFI_USB_HC_PROTOCOL; + +// +// Protocol definitions +// + +/** + Provides software reset for the USB host controller. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param Attributes A bit mask of the reset operation to perform. + + @retval EFI_SUCCESS The reset operation succeeded. + @retval EFI_UNSUPPORTED The type of reset specified by Attributes is not currently supported + by the host controller hardware. + @retval EFI_INVALID_PARAMETER Attributes is not valid. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to perform the reset operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_RESET)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT16 Attributes + ); + +/** + Retrieves current state of the USB host controller. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param State A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + + @retval EFI_SUCCESS The state information of the host controller was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the host controller's + current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_GET_STATE)( + IN EFI_USB_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ); + +/** + Sets the USB host controller to a specific state. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param State Indicates the state of the host controller that will be set. + + @retval EFI_SUCCESS The USB host controller was successfully placed in the state specified by + State. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR Failed to set the state specified by State due to device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_SET_STATE)( + IN EFI_USB_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ); + +/** + Submits control transfer to a target USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param IsSlowDevice Indicates whether the target device is slow device or full-speed + device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Request A pointer to the USB device request that will be sent to the USB + device. + @param TransferDirection Specifies the data direction for the transfer. There are three + values available, EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength On input, indicates the size, in bytes, of the data buffer specified + by Data. On output, indicates the amount of data actually + transferred. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer + is allowed to complete. + @param TransferResult A pointer to the detailed result information generated by this + control transfer. + + @retval EFI_SUCCESS The control transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The control transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_CONTROL_TRANSFER)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +/** + Submits bulk transfer to a bulk endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the control + endpoint (whose default endpoint address is 0). It is the + caller's responsibility to make sure that the EndPointAddress + represents a bulk endpoint. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength On input, indicates the size, in bytes, of the data buffer specified + by Data. On output, indicates the amount of data actually + transferred. + @param DataToggle A pointer to the data toggle value. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer + is allowed to complete. + @param TransferResult A pointer to the detailed result information of the bulk transfer. + + @retval EFI_SUCCESS The bulk transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_BULK_TRANSFER)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +/** + Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the control + endpoint (whose default endpoint address is zero). It is the + caller's responsibility to make sure that the + EndPointAddress represents an interrupt endpoint. + @param IsSlowDevice Indicates whether the target device is slow device or full-speed + device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between the host + and the target interrupt endpoint. If FALSE, the specified asynchronous + interrupt pipe is canceled. If TRUE, and an interrupt transfer exists + for the target end point, then EFI_INVALID_PARAMETER is returned. + @param DataToggle A pointer to the data toggle value. On input, it is valid when + IsNewTransfer is TRUE, and it indicates the initial data toggle + value the asynchronous interrupt transfer should adopt. On output, + it is valid when IsNewTransfer is FALSE, and it is updated to indicate + the data toggle value of the subsequent asynchronous interrupt transfer. + @param PollingInterval Indicates the interval, in milliseconds, that the asynchronous + interrupt transfer is polled. + @param DataLength Indicates the length of data to be received at the rate specified by + PollingInterval from the target asynchronous interrupt + endpoint. This parameter is only required when IsNewTransfer is TRUE. + @param CallBackFunction The Callback function. This function is called at the rate specified by + PollingInterval. This parameter is only required when IsNewTransfer is TRUE. + @param Context The context that is passed to the CallBackFunction. + + @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully + submitted or canceled. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ); + +/** + Submits synchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the control + endpoint (whose default endpoint address is zero). It is the + caller's responsibility to make sure that the + EndPointAddress represents an interrupt endpoint. + @param IsSlowDevice Indicates whether the target device is slow device or full-speed + device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. asynchronous interrupt pipe is canceled. + @param DataLength On input, the size, in bytes, of the data buffer specified by Data. + On output, the number of bytes transferred. + @param DataToggle A pointer to the data toggle value. On input, it indicates the initial + data toggle value the synchronous interrupt transfer should adopt; + on output, it is updated to indicate the data toggle value of the + subsequent synchronous interrupt transfer. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer + is allowed to complete. + @param TransferResult A pointer to the detailed result information from the synchronous + interrupt transfer. + + @retval EFI_SUCCESS The synchronous interrupt transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The synchronous interrupt transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The synchronous interrupt transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +/** + Submits isochronous transfer to an isochronous endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the control + endpoint (whose default endpoint address is 0). It is the caller's + responsibility to make sure that the EndPointAddress + represents an isochronous endpoint. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. asynchronous interrupt pipe is canceled. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received + from the USB device. + @param TransferResult A pointer to the detailed result information from the isochronous + transfer. + + @retval EFI_SUCCESS The isochronous transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The isochronous could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The isochronous transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The isochronous transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_ISOCHRONOUS_TRANSFER)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *TransferResult + ); + +/** + Submits nonblocking isochronous transfer to an isochronous endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the control + endpoint (whose default endpoint address is zero). It is the + caller's responsibility to make sure that the + EndPointAddress represents an isochronous endpoint. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. For isochronous + endpoints, this value is used to reserve the bus time in the schedule, + required for the perframe data payloads. The pipe may, on an ongoing basis, + actually use less bandwidth than that reserved. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. asynchronous interrupt pipe is canceled. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received + from the USB device. + @param IsochronousCallback The Callback function.This function is called if the requested + isochronous transfer is completed. + @param Context Data passed to the IsochronousCallback function. This is + an optional parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous isochronous transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The asynchronous isochronous could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +/** + Retrieves the number of root hub ports. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber A pointer to the number of the root hub ports. + + @retval EFI_SUCCESS The port number was retrieved successfully. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the port number. + @retval EFI_INVALID_PARAMETER PortNumber is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_NUMBER)( + IN EFI_USB_HC_PROTOCOL *This, + OUT UINT8 *PortNumber + ); + +/** + Retrieves the current status of a USB root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. For example, if a root hub has two ports, + then the first port is numbered 0, and the second port is + numbered 1. + @param PortStatus A pointer to the current port status bits and port status change bits. + + @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + @retval EFI_INVALID_PARAMETER PortNumber is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ); + +/** + Sets a feature for the specified root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. For example, if a root hub has two ports, + then the first port is numbered 0, and the second port is + numbered 1. + @param PortFeature Indicates the feature selector associated with the feature set + request. + + @retval EFI_SUCCESS The feature specified by PortFeature was set for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +/** + Clears a feature for the specified root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. For example, if a root hub has two ports, + then the first port is numbered 0, and the second port is + numbered 1. + @param PortFeature Indicates the feature selector associated with the feature clear + request. + + @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE)( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + + +/// +/// The EFI_USB_HC_PROTOCOL provides USB host controller management, basic data transactions +/// over a USB bus, and USB root hub access. A device driver that wishes to manage a USB bus in a +/// system retrieves the EFI_USB_HC_PROTOCOL instance that is associated with the USB bus to be +/// managed. A device handle for a USB host controller will minimally contain an +/// EFI_DEVICE_PATH_PROTOCOL instance, and an EFI_USB_HC_PROTOCOL instance. +/// +struct _EFI_USB_HC_PROTOCOL { + EFI_USB_HC_PROTOCOL_RESET Reset; + EFI_USB_HC_PROTOCOL_GET_STATE GetState; + EFI_USB_HC_PROTOCOL_SET_STATE SetState; + EFI_USB_HC_PROTOCOL_CONTROL_TRANSFER ControlTransfer; + EFI_USB_HC_PROTOCOL_BULK_TRANSFER BulkTransfer; + EFI_USB_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER AsyncInterruptTransfer; + EFI_USB_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER SyncInterruptTransfer; + EFI_USB_HC_PROTOCOL_ISOCHRONOUS_TRANSFER IsochronousTransfer; + EFI_USB_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER AsyncIsochronousTransfer; + EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_NUMBER GetRootHubPortNumber; + EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS GetRootHubPortStatus; + EFI_USB_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE SetRootHubPortFeature; + EFI_USB_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE ClearRootHubPortFeature; + /// + /// The major revision number of the USB host controller. The revision information + /// indicates the release of the Universal Serial Bus Specification with which the + /// host controller is compliant. + /// + UINT16 MajorRevision; + /// + /// The minor revision number of the USB host controller. The revision information + /// indicates the release of the Universal Serial Bus Specification with which the + /// host controller is compliant. + /// + UINT16 MinorRevision; +}; + +extern EFI_GUID gEfiUsbHcProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbIo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbIo.h new file mode 100644 index 0000000..741f2ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UsbIo.h @@ -0,0 +1,512 @@ +/** @file + EFI Usb I/O Protocol as defined in UEFI specification. + This protocol is used by code, typically drivers, running in the EFI + boot services environment to access USB devices like USB keyboards, + mice and mass storage devices. In particular, functions for managing devices + on USB buses are defined here. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __USB_IO_H__ +#define __USB_IO_H__ + +#include + +// +// Global ID for the USB I/O Protocol +// +#define EFI_USB_IO_PROTOCOL_GUID \ + { \ + 0x2B2F68D6, 0x0CD2, 0x44cf, {0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } \ + } + +typedef struct _EFI_USB_IO_PROTOCOL EFI_USB_IO_PROTOCOL; + +// +// Related Definition for EFI USB I/O protocol +// + +// +// USB standard descriptors and reqeust +// +typedef USB_DEVICE_REQUEST EFI_USB_DEVICE_REQUEST; +typedef USB_DEVICE_DESCRIPTOR EFI_USB_DEVICE_DESCRIPTOR; +typedef USB_CONFIG_DESCRIPTOR EFI_USB_CONFIG_DESCRIPTOR; +typedef USB_INTERFACE_DESCRIPTOR EFI_USB_INTERFACE_DESCRIPTOR; +typedef USB_ENDPOINT_DESCRIPTOR EFI_USB_ENDPOINT_DESCRIPTOR; + +/// +/// USB data transfer direction +/// +typedef enum { + EfiUsbDataIn, + EfiUsbDataOut, + EfiUsbNoData +} EFI_USB_DATA_DIRECTION; + +// +// USB Transfer Results +// +#define EFI_USB_NOERROR 0x00 +#define EFI_USB_ERR_NOTEXECUTE 0x01 +#define EFI_USB_ERR_STALL 0x02 +#define EFI_USB_ERR_BUFFER 0x04 +#define EFI_USB_ERR_BABBLE 0x08 +#define EFI_USB_ERR_NAK 0x10 +#define EFI_USB_ERR_CRC 0x20 +#define EFI_USB_ERR_TIMEOUT 0x40 +#define EFI_USB_ERR_BITSTUFF 0x80 +#define EFI_USB_ERR_SYSTEM 0x100 + +/** + Async USB transfer callback routine. + + @param Data Data received or sent via the USB Asynchronous Transfer, if the + transfer completed successfully. + @param DataLength The length of Data received or sent via the Asynchronous + Transfer, if transfer successfully completes. + @param Context Data passed from UsbAsyncInterruptTransfer() request. + @param Status Indicates the result of the asynchronous transfer. + + @retval EFI_SUCCESS The asynchronous USB transfer request has been successfully executed. + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ASYNC_USB_TRANSFER_CALLBACK)( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Status + ); + +// +// Prototype for EFI USB I/O protocol +// + + +/** + This function is used to manage a USB device with a control transfer pipe. A control transfer is + typically used to perform device initialization and configuration. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param Request A pointer to the USB device request that will be sent to the USB + device. + @param Direction Indicates the data direction. + @param Timeout Indicating the transfer should be completed within this time frame. + The units are in milliseconds. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + @param Status A pointer to the result of the USB transfer. + + @retval EFI_SUCCESS The control transfer has been successfully executed. + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status is returned in Status. + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_TIMEOUT The control transfer fails due to timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_CONTROL_TRANSFER)( + IN EFI_USB_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT32 Timeout, + IN OUT VOID *Data OPTIONAL, + IN UINTN DataLength OPTIONAL, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with the bulk transfer pipe. Bulk Transfers are + typically used to transfer large amounts of data to/from USB devices. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint The destination USB device endpoint to which the + device request is being sent. DeviceEndpoint must + be between 0x01 and 0x0F or between 0x81 and 0x8F, + otherwise EFI_INVALID_PARAMETER is returned. If + the endpoint is not a BULK endpoint, EFI_INVALID_PARAMETER + is returned. The MSB of this parameter indicates + the endpoint direction. The number "1" stands for + an IN endpoint, and "0" stands for an OUT endpoint. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + On input, the size, in bytes, of the data buffer specified by Data. + On output, the number of bytes that were actually transferred. + @param Timeout Indicating the transfer should be completed within this time frame. + The units are in milliseconds. If Timeout is 0, then the + caller must wait for the function to be completed until + EFI_SUCCESS or EFI_DEVICE_ERROR is returned. + @param Status This parameter indicates the USB transfer status. + + @retval EFI_SUCCESS The bulk transfer has been successfully executed. + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status is returned in Status. + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The control transfer fails due to timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_BULK_TRANSFER)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with an interrupt transfer pipe. An Asynchronous + Interrupt Transfer is typically used to query a device's status at a fixed rate. For example, + keyboard, mouse, and hub devices use this type of transfer to query their interrupt endpoints at + a fixed rate. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint The destination USB device endpoint to which the + device request is being sent. DeviceEndpoint must + be between 0x01 and 0x0F or between 0x81 and 0x8F, + otherwise EFI_INVALID_PARAMETER is returned. If + the endpoint is not a BULK endpoint, EFI_INVALID_PARAMETER + is returned. The MSB of this parameter indicates + the endpoint direction. The number "1" stands for + an IN endpoint, and "0" stands for an OUT endpoint. + @param IsNewTransfer If TRUE, a new transfer will be submitted to USB controller. If + FALSE, the interrupt transfer is deleted from the device's interrupt + transfer queue. + @param PollingInterval Indicates the periodic rate, in milliseconds, that the transfer is to be + executed.This parameter is required when IsNewTransfer is TRUE. The + value must be between 1 to 255, otherwise EFI_INVALID_PARAMETER is returned. + The units are in milliseconds. + @param DataLength Specifies the length, in bytes, of the data to be received from the + USB device. This parameter is only required when IsNewTransfer is TRUE. + @param InterruptCallback The Callback function. This function is called if the asynchronous + interrupt transfer is completed. This parameter is required + when IsNewTransfer is TRUE. + @param Context Data passed to the InterruptCallback function. This is an optional + parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous USB transfer request transfer has been successfully executed. + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack OPTIONAL, + IN VOID *Context OPTIONAL + ); + +/** + This function is used to manage a USB device with an interrupt transfer pipe. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint The destination USB device endpoint to which the + device request is being sent. DeviceEndpoint must + be between 0x01 and 0x0F or between 0x81 and 0x8F, + otherwise EFI_INVALID_PARAMETER is returned. If + the endpoint is not a BULK endpoint, EFI_INVALID_PARAMETER + is returned. The MSB of this parameter indicates + the endpoint direction. The number "1" stands for + an IN endpoint, and "0" stands for an OUT endpoint. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength On input, then size, in bytes, of the buffer Data. On output, the + amount of data actually transferred. + @param Timeout The time out, in seconds, for this transfer. If Timeout is 0, + then the caller must wait for the function to be completed + until EFI_SUCCESS or EFI_DEVICE_ERROR is returned. If the + transfer is not completed in this time frame, then EFI_TIMEOUT is returned. + @param Status This parameter indicates the USB transfer status. + + @retval EFI_SUCCESS The sync interrupt transfer has been successfully executed. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The sync interrupt transfer request failed. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The transfer fails due to timeout. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_SYNC_INTERRUPT_TRANSFER)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with an isochronous transfer pipe. An Isochronous + transfer is typically used to transfer streaming data. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint The destination USB device endpoint to which the + device request is being sent. DeviceEndpoint must + be between 0x01 and 0x0F or between 0x81 and 0x8F, + otherwise EFI_INVALID_PARAMETER is returned. If + the endpoint is not a BULK endpoint, EFI_INVALID_PARAMETER + is returned. The MSB of this parameter indicates + the endpoint direction. The number "1" stands for + an IN endpoint, and "0" stands for an OUT endpoint. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + @param Status This parameter indicates the USB transfer status. + + @retval EFI_SUCCESS The isochronous transfer has been successfully executed. + @retval EFI_INVALID_PARAMETER The parameter DeviceEndpoint is not valid. + @retval EFI_DEVICE_ERROR The transfer failed due to the reason other than timeout, The error status + is returned in Status. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The transfer fails due to timeout. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_ISOCHRONOUS_TRANSFER)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with an isochronous transfer pipe. An Isochronous + transfer is typically used to transfer streaming data. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint The destination USB device endpoint to which the + device request is being sent. DeviceEndpoint must + be between 0x01 and 0x0F or between 0x81 and 0x8F, + otherwise EFI_INVALID_PARAMETER is returned. If + the endpoint is not a BULK endpoint, EFI_INVALID_PARAMETER + is returned. The MSB of this parameter indicates + the endpoint direction. The number "1" stands for + an IN endpoint, and "0" stands for an OUT endpoint. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + This is an optional parameter and may be NULL. + @param IsochronousCallback The IsochronousCallback() function.This function is + called if the requested isochronous transfer is completed. + @param Context Data passed to the IsochronousCallback() function. + + @retval EFI_SUCCESS The asynchronous isochronous transfer has been successfully submitted + to the system. + @retval EFI_INVALID_PARAMETER The parameter DeviceEndpoint is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +/** + Resets and reconfigures the USB controller. This function will work for all USB devices except + USB Hub Controllers. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The USB controller was reset. + @retval EFI_INVALID_PARAMETER If the controller specified by This is a USB hub. + @retval EFI_DEVICE_ERROR An error occurred during the reconfiguration process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_PORT_RESET)( + IN EFI_USB_IO_PROTOCOL *This + ); + +/** + Retrieves the USB Device Descriptor. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceDescriptor A pointer to the caller allocated USB Device Descriptor. + + @retval EFI_SUCCESS The device descriptor was retrieved successfully. + @retval EFI_INVALID_PARAMETER DeviceDescriptor is NULL. + @retval EFI_NOT_FOUND The device descriptor was not found. The device may not be configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_DEVICE_DESCRIPTOR)( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor + ); + +/** + Retrieves the USB Device Descriptor. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param ConfigurationDescriptor A pointer to the caller allocated USB Active Configuration + Descriptor. + @retval EFI_SUCCESS The active configuration descriptor was retrieved successfully. + @retval EFI_INVALID_PARAMETER ConfigurationDescriptor is NULL. + @retval EFI_NOT_FOUND An active configuration descriptor cannot be found. The device may not + be configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_CONFIG_DESCRIPTOR)( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor + ); + +/** + Retrieves the Interface Descriptor for a USB Device Controller. As stated earlier, an interface + within a USB device is equivalently to a USB Controller within the current configuration. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param InterfaceDescriptor A pointer to the caller allocated USB Interface Descriptor within + the configuration setting. + @retval EFI_SUCCESS The interface descriptor retrieved successfully. + @retval EFI_INVALID_PARAMETER InterfaceDescriptor is NULL. + @retval EFI_NOT_FOUND The interface descriptor cannot be found. The device may not be + correctly configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_INTERFACE_DESCRIPTOR)( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor + ); + +/** + Retrieves an Endpoint Descriptor within a USB Controller. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param EndpointIndex Indicates which endpoint descriptor to retrieve. + @param EndpointDescriptor A pointer to the caller allocated USB Endpoint Descriptor of + a USB controller. + + @retval EFI_SUCCESS The endpoint descriptor was retrieved successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_NOT_FOUND The endpoint descriptor cannot be found. The device may not be + correctly configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor + ); + +/** + Retrieves a string stored in a USB Device. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param LangID The Language ID for the string being retrieved. + @param StringID The ID of the string being retrieved. + @param String A pointer to a buffer allocated by this function with + AllocatePool() to store the string.If this function + returns EFI_SUCCESS, it stores the string the caller + wants to get. The caller should release the string + buffer with FreePool() after the string is not used any more. + + @retval EFI_SUCCESS The string was retrieved successfully. + @retval EFI_NOT_FOUND The string specified by LangID and StringID was not found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the return buffer String. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_STRING_DESCRIPTOR)( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT16 LangID, + IN UINT8 StringID, + OUT CHAR16 **String + ); + +/** + Retrieves all the language ID codes that the USB device supports. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param LangIDTable Language ID for the string the caller wants to get. + This is a 16-bit ID defined by Microsoft. This + buffer pointer is allocated and maintained by + the USB Bus Driver, the caller should not modify + its contents. + @param TableSize The size, in bytes, of the table LangIDTable. + + @retval EFI_SUCCESS The support languages were retrieved successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_SUPPORTED_LANGUAGE)( + IN EFI_USB_IO_PROTOCOL *This, + OUT UINT16 **LangIDTable, + OUT UINT16 *TableSize + ); + +/// +/// The EFI_USB_IO_PROTOCOL provides four basic transfers types described +/// in the USB 1.1 Specification. These include control transfer, interrupt +/// transfer, bulk transfer and isochronous transfer. The EFI_USB_IO_PROTOCOL +/// also provides some basic USB device/controller management and configuration +/// interfaces. A USB device driver uses the services of this protocol to manage USB devices. +/// +struct _EFI_USB_IO_PROTOCOL { + // + // IO transfer + // + EFI_USB_IO_CONTROL_TRANSFER UsbControlTransfer; + EFI_USB_IO_BULK_TRANSFER UsbBulkTransfer; + EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER UsbAsyncInterruptTransfer; + EFI_USB_IO_SYNC_INTERRUPT_TRANSFER UsbSyncInterruptTransfer; + EFI_USB_IO_ISOCHRONOUS_TRANSFER UsbIsochronousTransfer; + EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER UsbAsyncIsochronousTransfer; + + // + // Common device request + // + EFI_USB_IO_GET_DEVICE_DESCRIPTOR UsbGetDeviceDescriptor; + EFI_USB_IO_GET_CONFIG_DESCRIPTOR UsbGetConfigDescriptor; + EFI_USB_IO_GET_INTERFACE_DESCRIPTOR UsbGetInterfaceDescriptor; + EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR UsbGetEndpointDescriptor; + EFI_USB_IO_GET_STRING_DESCRIPTOR UsbGetStringDescriptor; + EFI_USB_IO_GET_SUPPORTED_LANGUAGE UsbGetSupportedLanguages; + + // + // Reset controller's parent port + // + EFI_USB_IO_PORT_RESET UsbPortReset; +}; + +extern EFI_GUID gEfiUsbIoProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential.h new file mode 100644 index 0000000..1d3cd49 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential.h @@ -0,0 +1,292 @@ +/** @file + UEFI 2.2 User Credential Protocol definition.It has been removed from UEFI 2.3.1 and replaced + by EFI_USER_CREDENTIAL2_PROTOCOL. + + Attached to a device handle, this protocol identifies a single means of identifying the user. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __USER_CREDENTIAL_H__ +#define __USER_CREDENTIAL_H__ + +#include + +#define EFI_USER_CREDENTIAL_PROTOCOL_GUID \ + { \ + 0x71ee5e94, 0x65b9, 0x45d5, { 0x82, 0x1a, 0x3a, 0x4d, 0x86, 0xcf, 0xe6, 0xbe } \ + } + +typedef struct _EFI_USER_CREDENTIAL_PROTOCOL EFI_USER_CREDENTIAL_PROTOCOL; + +/** + Enroll a user on a credential provider. + + This function enrolls and deletes a user profile using this credential provider. If a user profile + is successfully enrolled, it calls the User Manager Protocol function Notify() to notify the user + manager driver that credential information has changed. If an enrolled user does exist, delete the + user on the credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile to enroll. + + @retval EFI_SUCCESS User profile was successfully enrolled. + @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the user profile + handle. Either the user profile cannot enroll on any user profile or + cannot enroll on a user profile other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support enrollment in the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be created because of a device error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_ENROLL)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + +/** + Returns the user interface information used during user identification. + + This function returns information about the form used when interacting with the user during user + identification. The form is the first enabled form in the form-set class + EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If + the user credential provider does not require a form to identify the user, then this function should + return EFI_NOT_FOUND. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] FormSetId On return, holds the identifier of the form set which contains + the form used during user identification. + @param[out] FormId On return, holds the identifier of the form used during user + identification. + + @retval EFI_SUCCESS Form returned successfully. + @retval EFI_NOT_FOUND Form not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_FORM)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_GUID *FormSetId, + OUT EFI_FORM_ID *FormId + ); + +/** + Returns bitmap used to describe the credential provider type. + + This optional function returns a bitmap which is less than or equal to the number of pixels specified + by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no bitmap + information will be returned. On exit, points to the width of the + bitmap returned. + @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no bitmap + information will be returned. On exit, points to the height of the + bitmap returned + @param[out] Hii On return, holds the HII database handle. + @param[out] Image On return, holds the HII image identifier. + + @retval EFI_SUCCESS Image identifier returned successfully. + @retval EFI_NOT_FOUND Image identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_TILE)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT UINTN *Width, + IN OUT UINTN *Height, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_IMAGE_ID *Image + ); + +/** + Returns string used to describe the credential provider type. + + This function returns a string which describes the credential provider. If no such string exists, then + EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] String On return, holds the HII string identifier. + + @retval EFI_SUCCESS String identifier returned successfully. + @retval EFI_NOT_FOUND String identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_TITLE)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_STRING_ID *String + ); + +/** + Return the user identifier associated with the currently authenticated user. + + This function returns the user identifier of the user authenticated by this credential provider. This + function is called after the credential-related information has been submitted on a form OR after a + call to Default() has returned that this credential is ready to log on. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile handle of the user profile currently being considered + by the user identity manager. If NULL, then no user profile is currently + under consideration. + @param[out] Identifier On return, points to the user identifier. + + @retval EFI_SUCCESS User identifier returned successfully. + @retval EFI_NOT_READY No user identifier can be returned. + @retval EFI_ACCESS_DENIED The user has been locked out of this user credential. + @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be found in user + profile database + @retval EFI_INVALID_PARAMETER Identifier is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_USER)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + OUT EFI_USER_INFO_IDENTIFIER *Identifier + ); + +/** + Indicate that user interface interaction has begun for the specified credential. + + This function is called when a credential provider is selected by the user. If AutoLogon returns + FALSE, then the user interface will be constructed by the User Identity Manager. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, points to the credential provider's capabilities after + the credential provider has been selected by the user. + + @retval EFI_SUCCESS Credential provider successfully selected. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_SELECT)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Indicate that user interface interaction has ended for the specified credential. + + This function is called when a credential provider is deselected by the user. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + + @retval EFI_SUCCESS Credential provider successfully deselected. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_DESELECT)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This + ); + +/** + Return the default logon behavior for this user credential. + + This function reports the default login behavior regarding this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, holds whether the credential provider should be + used by default to automatically log on the user. + + @retval EFI_SUCCESS Default information successfully returned. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_DEFAULT)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Return information attached to the credential provider. + + This function returns user information. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, holds the user + information. If the buffer is too small to hold the information, then + EFI_BUFFER_TOO_SMALL is returned and InfoSize is updated to contain the + number of bytes actually required. + @param[in,out] InfoSize On entry, points to the size of Info. On return, points to the size of the user + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the user + information. The size required is returned in *InfoSize. + @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_GET_INFO)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ); + +/** + Enumerate all of the user information records on the credential provider. + + This function returns the next user information record. To retrieve the first user information record + handle, point UserInfo at a NULL. Each subsequent call will retrieve another user information + record handle until there are no more, at which point UserInfo will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in,out] UserInfo On entry, points to the previous user information handle or NULL to + start enumeration. On exit, points to the next user information handle + or NULL if there is no more user information. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL_GET_NEXT_INFO)( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +/// +/// This protocol provides support for a single class of credentials +/// +struct _EFI_USER_CREDENTIAL_PROTOCOL { + EFI_GUID Identifier; ///< Uniquely identifies this credential provider. + EFI_GUID Type; ///< Identifies this class of User Credential Provider. + EFI_CREDENTIAL_ENROLL Enroll; + EFI_CREDENTIAL_FORM Form; + EFI_CREDENTIAL_TILE Tile; + EFI_CREDENTIAL_TITLE Title; + EFI_CREDENTIAL_USER User; + EFI_CREDENTIAL_SELECT Select; + EFI_CREDENTIAL_DESELECT Deselect; + EFI_CREDENTIAL_DEFAULT Default; + EFI_CREDENTIAL_GET_INFO GetInfo; + EFI_CREDENTIAL_GET_NEXT_INFO GetNextInfo; + EFI_CREDENTIAL_CAPABILITIES Capabilities; +}; + +extern EFI_GUID gEfiUserCredentialProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential2.h new file mode 100644 index 0000000..d3e9f2d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserCredential2.h @@ -0,0 +1,314 @@ +/** @file + UEFI 2.3.1 User Credential Protocol definition. + + Attached to a device handle, this protocol identifies a single means of identifying the user. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __USER_CREDENTIAL2_H__ +#define __USER_CREDENTIAL2_H__ + +#include + +#define EFI_USER_CREDENTIAL2_PROTOCOL_GUID \ + { \ + 0xe98adb03, 0xb8b9, 0x4af8, { 0xba, 0x20, 0x26, 0xe9, 0x11, 0x4c, 0xbc, 0xe5 } \ + } + +typedef struct _EFI_USER_CREDENTIAL2_PROTOCOL EFI_USER_CREDENTIAL2_PROTOCOL; + +/** + Enroll a user on a credential provider. + + This function enrolls a user on this credential provider. If the user exists on this credential + provider, update the user information on this credential provider; otherwise add the user information + on credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[in] User The user profile to enroll. + + @retval EFI_SUCCESS User profile was successfully enrolled. + @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the user profile + handle. Either the user profile cannot enroll on any user profile or + cannot enroll on a user profile other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support enrollment in the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be created because of a device error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_ENROLL)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + +/** + Returns the user interface information used during user identification. + + This function returns information about the form used when interacting with the user during user + identification. The form is the first enabled form in the form-set class + EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If + the user credential provider does not require a form to identify the user, then this function should + return EFI_NOT_FOUND. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] FormSetId On return, holds the identifier of the form set which contains + the form used during user identification. + @param[out] FormId On return, holds the identifier of the form used during user + identification. + + @retval EFI_SUCCESS Form returned successfully. + @retval EFI_NOT_FOUND Form not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_FORM)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_GUID *FormSetId, + OUT EFI_FORM_ID *FormId + ); + +/** + Returns bitmap used to describe the credential provider type. + + This optional function returns a bitmap which is less than or equal to the number of pixels specified + by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no bitmap + information will be returned. On exit, points to the width of the + bitmap returned. + @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no bitmap + information will be returned. On exit, points to the height of the + bitmap returned + @param[out] Hii On return, holds the HII database handle. + @param[out] Image On return, holds the HII image identifier. + + @retval EFI_SUCCESS Image identifier returned successfully. + @retval EFI_NOT_FOUND Image identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_TILE)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + IN OUT UINTN *Width, + IN OUT UINTN *Height, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_IMAGE_ID *Image + ); + +/** + Returns string used to describe the credential provider type. + + This function returns a string which describes the credential provider. If no such string exists, then + EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] String On return, holds the HII string identifier. + + @retval EFI_SUCCESS String identifier returned successfully. + @retval EFI_NOT_FOUND String identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_TITLE)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_STRING_ID *String + ); + +/** + Return the user identifier associated with the currently authenticated user. + + This function returns the user identifier of the user authenticated by this credential provider. This + function is called after the credential-related information has been submitted on a form OR after a + call to Default() has returned that this credential is ready to log on. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[in] User The user profile handle of the user profile currently being considered + by the user identity manager. If NULL, then no user profile is currently + under consideration. + @param[out] Identifier On return, points to the user identifier. + + @retval EFI_SUCCESS User identifier returned successfully. + @retval EFI_NOT_READY No user identifier can be returned. + @retval EFI_ACCESS_DENIED The user has been locked out of this user credential. + @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be found in user + profile database + @retval EFI_INVALID_PARAMETER Identifier is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_USER)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + OUT EFI_USER_INFO_IDENTIFIER *Identifier + ); + +/** + Indicate that user interface interaction has begun for the specified credential. + + This function is called when a credential provider is selected by the user. If AutoLogon returns + FALSE, then the user interface will be constructed by the User Identity Manager. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[out] AutoLogon On return, points to the credential provider's capabilities after + the credential provider has been selected by the user. + + @retval EFI_SUCCESS Credential provider successfully selected. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_SELECT)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Indicate that user interface interaction has ended for the specified credential. + + This function is called when a credential provider is deselected by the user. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + + @retval EFI_SUCCESS Credential provider successfully deselected. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_DESELECT)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This + ); + +/** + Return the default logon behavior for this user credential. + + This function reports the default login behavior regarding this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[out] AutoLogon On return, holds whether the credential provider should be + used by default to automatically log on the user. + + @retval EFI_SUCCESS Default information successfully returned. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_DEFAULT)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Return information attached to the credential provider. + + This function returns user information. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, holds the user + information. If the buffer is too small to hold the information, then + EFI_BUFFER_TOO_SMALL is returned and InfoSize is updated to contain the + number of bytes actually required. + @param[in,out] InfoSize On entry, points to the size of Info. On return, points to the size of the user + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the user + information. The size required is returned in *InfoSize. + @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_GET_INFO)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ); + +/** + Enumerate all of the user information records on the credential provider. + + This function returns the next user information record. To retrieve the first user information record + handle, point UserInfo at a NULL. Each subsequent call will retrieve another user information + record handle until there are no more, at which point UserInfo will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[in,out] UserInfo On entry, points to the previous user information handle or NULL to + start enumeration. On exit, points to the next user information handle + or NULL if there is no more user information. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_GET_NEXT_INFO)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +/** + Delete a user on this credential provider. + + This function deletes a user on this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL2_PROTOCOL. + @param[in] User The user profile handle to delete. + + @retval EFI_SUCCESS User profile was successfully deleted. + @retval EFI_ACCESS_DENIED Current user profile does not permit deletion on the user profile handle. + Either the user profile cannot delete on any user profile or cannot delete + on a user profile other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support deletion in the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be deleted because of a device error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREDENTIAL2_DELETE)( + IN CONST EFI_USER_CREDENTIAL2_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User +); + +/// +/// This protocol provides support for a single class of credentials +/// +struct _EFI_USER_CREDENTIAL2_PROTOCOL { + EFI_GUID Identifier; ///< Uniquely identifies this credential provider. + EFI_GUID Type; ///< Identifies this class of User Credential Provider. + EFI_CREDENTIAL2_ENROLL Enroll; + EFI_CREDENTIAL2_FORM Form; + EFI_CREDENTIAL2_TILE Tile; + EFI_CREDENTIAL2_TITLE Title; + EFI_CREDENTIAL2_USER User; + EFI_CREDENTIAL2_SELECT Select; + EFI_CREDENTIAL2_DESELECT Deselect; + EFI_CREDENTIAL2_DEFAULT Default; + EFI_CREDENTIAL2_GET_INFO GetInfo; + EFI_CREDENTIAL2_GET_NEXT_INFO GetNextInfo; + EFI_CREDENTIAL_CAPABILITIES Capabilities; + EFI_CREDENTIAL2_DELETE Delete; +}; + +extern EFI_GUID gEfiUserCredential2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserManager.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserManager.h new file mode 100644 index 0000000..0e92f56 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/UserManager.h @@ -0,0 +1,624 @@ +/** @file + UEFI User Manager Protocol definition. + + This protocol manages user profiles. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __USER_MANAGER_H__ +#define __USER_MANAGER_H__ + +/// +/// Global ID for the User Manager Protocol +/// +#define EFI_USER_MANAGER_PROTOCOL_GUID \ + { \ + 0x6fd5b00c, 0xd426, 0x4283, { 0x98, 0x87, 0x6c, 0xf5, 0xcf, 0x1c, 0xb1, 0xfe } \ + } + +#define EFI_EVENT_GROUP_USER_PROFILE_CHANGED \ + { \ + 0xbaf1e6de, 0x209e, 0x4adb, { 0x8d, 0x96, 0xfd, 0x8b, 0x71, 0xf3, 0xf6, 0x83 } \ + } + +typedef VOID *EFI_USER_PROFILE_HANDLE; +typedef VOID *EFI_USER_INFO_HANDLE; + +/// +/// The attributes of the user profile information. +/// +typedef UINT16 EFI_USER_INFO_ATTRIBS; +#define EFI_USER_INFO_STORAGE 0x000F +#define EFI_USER_INFO_STORAGE_VOLATILE 0x0000 +#define EFI_USER_INFO_STORAGE_CREDENTIAL_NV 0x0001 +#define EFI_USER_INFO_STORAGE_PLATFORM_NV 0x0002 + +#define EFI_USER_INFO_ACCESS 0x0070 +#define EFI_USER_INFO_PUBLIC 0x0010 +#define EFI_USER_INFO_PRIVATE 0x0020 +#define EFI_USER_INFO_PROTECTED 0x0030 +#define EFI_USER_INFO_EXCLUSIVE 0x0080 + +/// +/// User information structure +/// +typedef struct { + /// + /// The user credential identifier associated with this user information or else Nil if the + /// information is not associated with any specific credential. + /// + EFI_GUID Credential; + /// + /// The type of user information. + /// + UINT8 InfoType; + /// + /// Must be set to 0. + /// + UINT8 Reserved1; + /// + /// The attributes of the user profile information. + /// + EFI_USER_INFO_ATTRIBS InfoAttribs; + /// + /// The size of the user information, in bytes, including this header. + /// + UINT32 InfoSize; +} EFI_USER_INFO; + +/// +/// User credential class GUIDs +/// +#define EFI_USER_CREDENTIAL_CLASS_UNKNOWN \ + { 0x5cf32e68, 0x7660, 0x449b, { 0x80, 0xe6, 0x7e, 0xa3, 0x6e, 0x3, 0xf6, 0xa8 } } +#define EFI_USER_CREDENTIAL_CLASS_PASSWORD \ + { 0xf8e5058c, 0xccb6, 0x4714, { 0xb2, 0x20, 0x3f, 0x7e, 0x3a, 0x64, 0xb, 0xd1 } } +#define EFI_USER_CREDENTIAL_CLASS_SMART_CARD \ + { 0x5f03ba33, 0x8c6b, 0x4c24, { 0xaa, 0x2e, 0x14, 0xa2, 0x65, 0x7b, 0xd4, 0x54 } } +#define EFI_USER_CREDENTIAL_CLASS_FINGERPRINT \ + { 0x32cba21f, 0xf308, 0x4cbc, { 0x9a, 0xb5, 0xf5, 0xa3, 0x69, 0x9f, 0x4, 0x4a } } +#define EFI_USER_CREDENTIAL_CLASS_HANDPRINT \ + { 0x5917ef16, 0xf723, 0x4bb9, { 0xa6, 0x4b, 0xd8, 0xc5, 0x32, 0xf4, 0xd8, 0xb5 } } +#define EFI_USER_CREDENTIAL_CLASS_SECURE_CARD \ + { 0x8a6b4a83, 0x42fe, 0x45d2, { 0xa2, 0xef, 0x46, 0xf0, 0x6c, 0x7d, 0x98, 0x52 } } + +typedef UINT64 EFI_CREDENTIAL_CAPABILITIES; +#define EFI_CREDENTIAL_CAPABILITIES_ENROLL 0x0000000000000001 + +/// +/// Credential logon flags +/// +typedef UINT32 EFI_CREDENTIAL_LOGON_FLAGS; +#define EFI_CREDENTIAL_LOGON_FLAG_AUTO 0x00000001 +#define EFI_CREDENTIAL_LOGON_FLAG_DEFAULT 0x00000002 + +/// +/// User information record types +/// + +/// +/// No information. +/// +#define EFI_USER_INFO_EMPTY_RECORD 0x00 +/// +/// Provide the user's name for the enrolled user. +/// +#define EFI_USER_INFO_NAME_RECORD 0x01 +typedef CHAR16 *EFI_USER_INFO_NAME; +/// +/// Provides the date and time when the user profile was created. +/// +#define EFI_USER_INFO_CREATE_DATE_RECORD 0x02 +typedef EFI_TIME EFI_USER_INFO_CREATE_DATE; +/// +/// Provides the date and time when the user profile was selected. +/// +#define EFI_USER_INFO_USAGE_DATE_RECORD 0x03 +typedef EFI_TIME EFI_USER_INFO_USAGE_DATE; +/// +/// Provides the number of times that the user profile has been selected. +/// +#define EFI_USER_INFO_USAGE_COUNT_RECORD 0x04 +typedef UINT64 EFI_USER_INFO_USAGE_COUNT; +/// +/// Provides a unique non-volatile user identifier for each enrolled user. +/// +#define EFI_USER_INFO_IDENTIFIER_RECORD 0x05 +typedef UINT8 EFI_USER_INFO_IDENTIFIER[16]; +/// +/// Specifies the type of a particular credential associated with the user profile. +/// +#define EFI_USER_INFO_CREDENTIAL_TYPE_RECORD 0x06 +typedef EFI_GUID EFI_USER_INFO_CREDENTIAL_TYPE; +/// +/// Specifies the user-readable name of a particular credential type. +/// +#define EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD 0x07 +typedef CHAR16 *EFI_USER_INFO_CREDENTIAL_TYPE_NAME; +/// +/// Specifies the credential provider. +/// +#define EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD 0x08 +typedef EFI_GUID EFI_USER_INFO_CREDENTIAL_PROVIDER; +/// +/// Specifies the user-readable name of a particular credential's provider. +/// +#define EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD 0x09 +typedef CHAR16 *EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME; +/// +/// Provides PKCS#11 credential information from a smart card. +/// +#define EFI_USER_INFO_PKCS11_RECORD 0x0A +/// +/// Provides standard biometric information in the format specified by the ISO 19785 (Common +/// Biometric Exchange Formats Framework) specification. +/// +#define EFI_USER_INFO_CBEFF_RECORD 0x0B +typedef VOID *EFI_USER_INFO_CBEFF; +/// +/// Indicates how close of a match the fingerprint must be in order to be considered a match. +/// +#define EFI_USER_INFO_FAR_RECORD 0x0C +typedef UINT8 EFI_USER_INFO_FAR; +/// +/// Indicates how many attempts the user has to with a particular credential before the system prevents +/// further attempts. +/// +#define EFI_USER_INFO_RETRY_RECORD 0x0D +typedef UINT8 EFI_USER_INFO_RETRY; +/// +/// Provides the user's pre-OS access rights. +/// +#define EFI_USER_INFO_ACCESS_POLICY_RECORD 0x0E + +typedef struct { + UINT32 Type; ///< Specifies the type of user access control. + UINT32 Size; ///< Specifies the size of the user access control record, in bytes, including this header. +} EFI_USER_INFO_ACCESS_CONTROL; + +typedef EFI_USER_INFO_ACCESS_CONTROL EFI_USER_INFO_ACCESS_POLICY; + +/// +/// User Information access types +/// + +/// +/// Forbids the user from booting or loading executables from the specified device path or any child +/// device paths. +/// +#define EFI_USER_INFO_ACCESS_FORBID_LOAD 0x00000001 +/// +/// Permits the user from booting or loading executables from the specified device path or any child +/// device paths. +/// Note: in-consistency between code and the UEFI 2.3 specification here. +/// The definition EFI_USER_INFO_ACCESS_PERMIT_BOOT in the specification should be typo and wait for +/// spec update. +/// +#define EFI_USER_INFO_ACCESS_PERMIT_LOAD 0x00000002 +/// +/// Presence of this record indicates that a user can update enrollment information. +/// +#define EFI_USER_INFO_ACCESS_ENROLL_SELF 0x00000003 +/// +/// Presence of this record indicates that a user can enroll new users. +/// +#define EFI_USER_INFO_ACCESS_ENROLL_OTHERS 0x00000004 +/// +/// Presence of this record indicates that a user can update the user information of any user. +/// +#define EFI_USER_INFO_ACCESS_MANAGE 0x00000005 +/// +/// Describes permissions usable when configuring the platform. +/// +#define EFI_USER_INFO_ACCESS_SETUP 0x00000006 +/// +/// Standard GUIDs for access to configure the platform. +/// +#define EFI_USER_INFO_ACCESS_SETUP_ADMIN_GUID \ + { 0x85b75607, 0xf7ce, 0x471e, { 0xb7, 0xe4, 0x2a, 0xea, 0x5f, 0x72, 0x32, 0xee } } +#define EFI_USER_INFO_ACCESS_SETUP_NORMAL_GUID \ + { 0x1db29ae0, 0x9dcb, 0x43bc, { 0x8d, 0x87, 0x5d, 0xa1, 0x49, 0x64, 0xdd, 0xe2 } } +#define EFI_USER_INFO_ACCESS_SETUP_RESTRICTED_GUID \ + { 0xbdb38125, 0x4d63, 0x49f4, { 0x82, 0x12, 0x61, 0xcf, 0x5a, 0x19, 0xa, 0xf8 } } + +/// +/// Forbids UEFI drivers from being started from the specified device path(s) or any child device paths. +/// +#define EFI_USER_INFO_ACCESS_FORBID_CONNECT 0x00000007 +/// +/// Permits UEFI drivers to be started on the specified device path(s) or any child device paths. +/// +#define EFI_USER_INFO_ACCESS_PERMIT_CONNECT 0x00000008 +/// +/// Modifies the boot order. +/// +#define EFI_USER_INFO_ACCESS_BOOT_ORDER 0x00000009 +typedef UINT32 EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR; + +#define EFI_USER_INFO_ACCESS_BOOT_ORDER_MASK 0x0000000F +/// +/// Insert new boot options at the beginning of the boot order. +/// +#define EFI_USER_INFO_ACCESS_BOOT_ORDER_INSERT 0x00000000 +/// +/// Append new boot options to the end of the boot order. +/// +#define EFI_USER_INFO_ACCESS_BOOT_ORDER_APPEND 0x00000001 +/// +/// Replace the entire boot order. +/// +#define EFI_USER_INFO_ACCESS_BOOT_ORDER_REPLACE 0x00000002 +/// +/// The Boot Manager will not attempt find a default boot device +/// when the default boot order is does not lead to a bootable device. +/// +#define EFI_USER_INFO_ACCESS_BOOT_ORDER_NODEFAULT 0x00000010 + +/// +/// Provides the expression which determines which credentials are required to assert user identity. +/// +#define EFI_USER_INFO_IDENTITY_POLICY_RECORD 0x0F + +typedef struct { + UINT32 Type; ///< Specifies either an operator or a data item. + UINT32 Length; ///< The length of this block, in bytes, including this header. +} EFI_USER_INFO_IDENTITY_POLICY; + +/// +/// User identity policy expression operators. +/// +#define EFI_USER_INFO_IDENTITY_FALSE 0x00 +#define EFI_USER_INFO_IDENTITY_TRUE 0x01 +#define EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE 0x02 +#define EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER 0x03 +#define EFI_USER_INFO_IDENTITY_NOT 0x10 +#define EFI_USER_INFO_IDENTITY_AND 0x11 +#define EFI_USER_INFO_IDENTITY_OR 0x12 + +/// +/// Provides placeholder for additional user profile information identified by a GUID. +/// +#define EFI_USER_INFO_GUID_RECORD 0xFF +typedef EFI_GUID EFI_USER_INFO_GUID; + +/// +/// User information table +/// A collection of EFI_USER_INFO records, prefixed with this header. +/// +typedef struct { + UINT64 Size; ///< Total size of the user information table, in bytes. +} EFI_USER_INFO_TABLE; + +typedef struct _EFI_USER_MANAGER_PROTOCOL EFI_USER_MANAGER_PROTOCOL; + +/** + Create a new user profile. + + This function creates a new user profile with only a new user identifier attached and returns its + handle. The user profile is non-volatile, but the handle User can change across reboots. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] User On return, points to the new user profile handle. + The user profile handle is unique only during this boot. + + @retval EFI_SUCCESS User profile was successfully created. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to create a user profile. + @retval EFI_UNSUPPORTED Creation of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_CREATE)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ); + +/** + Delete an existing user profile. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User User profile handle. + + @retval EFI_SUCCESS User profile was successfully deleted. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to delete a user + profile or there is only one user profile. + @retval EFI_UNSUPPORTED Deletion of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_DELETE)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + +/** + Enumerate all of the enrolled users on the platform. + + This function returns the next enrolled user profile. To retrieve the first user profile handle, point + User at a NULL. Each subsequent call will retrieve another user profile handle until there are no + more, at which point User will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in,out] User On entry, points to the previous user profile handle or NULL to + start enumeration. On exit, points to the next user profile handle + or NULL if there are no more user profiles. + + @retval EFI_SUCCESS Next enrolled user profile successfully returned. + @retval EFI_ACCESS_DENIED Next enrolled user profile was not successfully returned. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_GET_NEXT)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User + ); + +/** + Return the current user profile handle. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] CurrentUser On return, points to the current user profile handle. + + @retval EFI_SUCCESS Current user profile handle returned successfully. + @retval EFI_INVALID_PARAMETER The CurrentUser parameter is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_CURRENT)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *CurrentUser + ); + +/** + Identify a user. + + Identify the user and, if authenticated, returns the user handle and changes the current user profile. + All user information marked as private in a previously selected profile is no longer available for + inspection. + Whenever the current user profile is changed then the an event with the GUID + EFI_EVENT_GROUP_USER_PROFILE_CHANGED is signaled. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] User On return, points to the user profile handle for the current user profile. + + @retval EFI_SUCCESS User was successfully identified. + @retval EFI_ACCESS_DENIED User was not successfully identified. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_IDENTIFY)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ); + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. The search starts + with the user information record handle following UserInfo and continues until either the + information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record type and the + user information record data matches the portion of Info. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in,out] User On entry, points to the previously returned user profile handle or NULL to start + searching with the first user profile. On return, points to the user profile handle or + NULL if not found. + @param[in,out] UserInfo On entry, points to the previously returned user information handle or NULL to start + searching with the first. On return, points to the user information handle of the user + information record or NULL if not found. Can be NULL, in which case only one user + information record per user can be returned. + @param[in] Info Points to the buffer containing the user information to be compared to the user + information record. If the user information record data is empty, then only the user + information record type is compared. + If InfoSize is 0, then the user information record must be empty. + + @param[in] InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User information was found. User points to the user profile handle and UserInfo + points to the user information handle. + @retval EFI_NOT_FOUND User information was not found. User points to NULL and UserInfo points to NULL. + @retval EFI_INVALID_PARAMETER User is NULL. Or Info is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_FIND)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo OPTIONAL, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ); + +/** + Called by credential provider to notify of information change. + + This function allows the credential provider to notify the User Identity Manager when user status + has changed. + If the User Identity Manager doesn't support asynchronous changes in credentials, then this function + should return EFI_UNSUPPORTED. + If current user does not exist, and the credential provider can identify a user, then make the user + to be current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event. + If current user already exists, and the credential provider can identify another user, then switch + current user to the newly identified user, and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event. + If current user was identified by this credential provider and now the credential provider cannot identify + current user, then logout current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] Changed Handle on which is installed an instance of the + EFI_USER_CREDENTIAL_PROTOCOL where the user has changed. + + @retval EFI_SUCCESS The User Identity Manager has handled the notification. + @retval EFI_NOT_READY The function was called while the specified credential provider was not selected. + @retval EFI_UNSUPPORTED The User Identity Manager doesn't support asynchronous notifications. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_NOTIFY)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_HANDLE Changed + ); + +/** + Return information attached to the user. + + This function returns user information. The format of the information is described in User + Information. The function may return EFI_ACCESS_DENIED if the information is marked private + and the handle specified by User is not the current user profile. The function may return + EFI_ACCESS_DENIED if the information is marked protected and the information is associated + with a credential provider for which the user has not been authenticated. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose profile will be retrieved. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, holds the user + information. If the buffer is too small to hold the information, then + EFI_BUFFER_TOO_SMALL is returned and InfoSize is updated to contain the + number of bytes actually required. + @param[in,out] InfoSize On entry, points to the size of Info. On return, points to the size of the user + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The information about the specified user cannot be accessed by the current user. + @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold + the returned data. The actual size required is returned in *InfoSize. + @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not refer to a valid + user info handle. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_GET_INFO)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ); + +/** + Add or update user information. + + This function changes user information. If NULL is pointed to by UserInfo, then a new user + information record is created and its handle is returned in UserInfo. Otherwise, the existing one is + replaced. + If EFI_USER_INFO_IDENTITY_POLICY_RECORD is changed, it is the caller's responsibility to keep it to + be synced with the information on credential providers. + If EFI_USER_INFO_EXCLUSIVE is specified in Info and a user information record of the same + type already exists in the user profile, then EFI_ACCESS_DENIED will be returned and + UserInfo will point to the handle of the existing record. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose profile will be retrieved. + @param[in,out] UserInfo Handle of the user information data record. + @param[in] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, holds the user + information. If the buffer is too small to hold the information, then + EFI_BUFFER_TOO_SMALL is returned and InfoSize is updated to contain the + number of bytes actually required. + @param[in] InfoSize On entry, points to the size of Info. On return, points to the size of the user + information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SECURITY_VIOLATION The current user does not have permission to change the specified + user profile or user information record. + @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not refer to a valid + user info handle. + @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_SET_INFO)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ); + +/** + Delete user information. + + Delete the user information attached to the user profile specified by the UserInfo. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose information will be deleted. + @param[in] UserInfo Handle of the user information to remove. + + @retval EFI_SUCCESS User information deleted successfully. + @retval EFI_NOT_FOUND User information record UserInfo does not exist in the user profile. + @retval EFI_ACCESS_DENIED The current user does not have permission to delete this user information. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_DELETE_INFO)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo + ); + +/** + Enumerate user information of all the enrolled users on the platform. + + This function returns the next user information record. To retrieve the first user information record + handle, point UserInfo at a NULL. Each subsequent call will retrieve another user information + record handle until there are no more, at which point UserInfo will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose information will be deleted. + @param[in,out] UserInfo Handle of the user information to remove. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USER_PROFILE_GET_NEXT_INFO)( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +/// +/// This protocol provides the services used to manage user profiles. +/// +struct _EFI_USER_MANAGER_PROTOCOL { + EFI_USER_PROFILE_CREATE Create; + EFI_USER_PROFILE_DELETE Delete; + EFI_USER_PROFILE_GET_NEXT GetNext; + EFI_USER_PROFILE_CURRENT Current; + EFI_USER_PROFILE_IDENTIFY Identify; + EFI_USER_PROFILE_FIND Find; + EFI_USER_PROFILE_NOTIFY Notify; + EFI_USER_PROFILE_GET_INFO GetInfo; + EFI_USER_PROFILE_SET_INFO SetInfo; + EFI_USER_PROFILE_DELETE_INFO DeleteInfo; + EFI_USER_PROFILE_GET_NEXT_INFO GetNextInfo; +}; + +extern EFI_GUID gEfiUserManagerProtocolGuid; +extern EFI_GUID gEfiEventUserProfileChangedGuid; +extern EFI_GUID gEfiUserCredentialClassUnknownGuid; +extern EFI_GUID gEfiUserCredentialClassPasswordGuid; +extern EFI_GUID gEfiUserCredentialClassSmartCardGuid; +extern EFI_GUID gEfiUserCredentialClassFingerprintGuid; +extern EFI_GUID gEfiUserCredentialClassHandprintGuid; +extern EFI_GUID gEfiUserCredentialClassSecureCardGuid; +extern EFI_GUID gEfiUserInfoAccessSetupAdminGuid; +extern EFI_GUID gEfiUserInfoAccessSetupNormalGuid; +extern EFI_GUID gEfiUserInfoAccessSetupRestrictedGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Variable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Variable.h new file mode 100644 index 0000000..3eb412b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/Variable.h @@ -0,0 +1,45 @@ +/** @file + Variable Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + This provides the services required to get and set environment variables. This + protocol must be produced by a runtime DXE driver and may be consumed only by + the DXE Foundation. The DXE driver that produces this protocol must be a runtime + driver. This driver is responsible for initializing the GetVariable(), + GetNextVariableName(), and SetVariable() fields of the UEFI Runtime Services Table. + + After the three fields of the UEFI Runtime Services Table have been initialized, + the driver must install the EFI_VARIABLE_ARCH_PROTOCOL_GUID on a new handle with + a NULL interface pointer. The installation of this protocol informs the DXE Foundation + that the read-only and the volatile environment variable related services are + now available and that the DXE Foundation must update the 32-bit CRC of the UEFI + Runtime Services Table. The full complement of environment variable services are + not available until both this protocol and EFI_VARIABLE_WRITE_ARCH_PROTOCOL are + installed. DXE drivers that require read-only access or read/write access to volatile + environment variables must have this architectural protocol in their dependency + expressions. DXE drivers that require write access to nonvolatile environment + variables must have the EFI_VARIABLE_WRITE_ARCH_PROTOCOL in their dependency + expressions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_VARIABLE_ARCH_H__ +#define __ARCH_PROTOCOL_VARIABLE_ARCH_H__ + +/// +/// Global ID for the Variable Architectural Protocol +/// +#define EFI_VARIABLE_ARCH_PROTOCOL_GUID \ + { 0x1e5668e2, 0x8481, 0x11d4, {0xbc, 0xf1, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +extern EFI_GUID gEfiVariableArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VariableWrite.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VariableWrite.h new file mode 100644 index 0000000..78625f7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VariableWrite.h @@ -0,0 +1,45 @@ +/** @file + Variable Write Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + This provides the services required to set nonvolatile environment variables. + This protocol must be produced by a runtime DXE driver and may be consumed only + by the DXE Foundation. + + The DXE driver that produces this protocol must be a runtime driver. This driver + may update the SetVariable() field of the UEFI Runtime Services Table. + + After the UEFI Runtime Services Table has been initialized, the driver must + install the EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID on a new handle with a NULL + interface pointer. The installation of this protocol informs the DXE Foundation + that the write services for nonvolatile environment variables are now available + and that the DXE Foundation must update the 32-bit CRC of the UEFI Runtime Services + Table. The full complement of environment variable services are not available + until both this protocol and EFI_VARIABLE_ARCH_PROTOCOL are installed. DXE drivers + that require read-only access or read/write access to volatile environment variables + must have the EFI_VARIABLE_WRITE_ARCH_PROTOCOL in their dependency expressions. + DXE drivers that require write access to nonvolatile environment variables must + have this architectural protocol in their dependency expressions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __ARCH_PROTOCOL_VARIABLE_WRITE_ARCH_H__ +#define __ARCH_PROTOCOL_VARIABLE_WRITE_ARCH_H__ + +/// +/// Global ID for the Variable Write Architectural Protocol +/// +#define EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID \ + { 0x6441f818, 0x6362, 0x4e44, {0xb5, 0x70, 0x7d, 0xba, 0x31, 0xdd, 0x24, 0x53 } } + +extern EFI_GUID gEfiVariableWriteArchProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VlanConfig.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VlanConfig.h new file mode 100644 index 0000000..63784b8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/VlanConfig.h @@ -0,0 +1,143 @@ +/** @file + EFI VLAN Config protocol is to provide manageability interface for VLAN configuration. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.2 + +**/ + +#ifndef __EFI_VLANCONFIG_PROTOCOL_H__ +#define __EFI_VLANCONFIG_PROTOCOL_H__ + + +#define EFI_VLAN_CONFIG_PROTOCOL_GUID \ + { \ + 0x9e23d768, 0xd2f3, 0x4366, {0x9f, 0xc3, 0x3a, 0x7a, 0xba, 0x86, 0x43, 0x74 } \ + } + +typedef struct _EFI_VLAN_CONFIG_PROTOCOL EFI_VLAN_CONFIG_PROTOCOL; + + +/// +/// EFI_VLAN_FIND_DATA +/// +typedef struct { + UINT16 VlanId; ///< Vlan Identifier. + UINT8 Priority; ///< Priority of this VLAN. +} EFI_VLAN_FIND_DATA; + + +/** + Create a VLAN device or modify the configuration parameter of an + already-configured VLAN. + + The Set() function is used to create a new VLAN device or change the VLAN + configuration parameters. If the VlanId hasn't been configured in the + physical Ethernet device, a new VLAN device will be created. If a VLAN with + this VlanId is already configured, then related configuration will be updated + as the input parameters. + + If VlanId is zero, the VLAN device will send and receive untagged frames. + Otherwise, the VLAN device will send and receive VLAN-tagged frames containing the VlanId. + If VlanId is out of scope of (0-4094), EFI_INVALID_PARAMETER is returned. + If Priority is out of the scope of (0-7), then EFI_INVALID_PARAMETER is returned. + If there is not enough system memory to perform the registration, then + EFI_OUT_OF_RESOURCES is returned. + + @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL. + @param[in] VlanId A unique identifier (1-4094) of the VLAN which is being created + or modified, or zero (0). + @param[in] Priority 3 bit priority in VLAN header. Priority 0 is default value. If + VlanId is zero (0), Priority is ignored. + + @retval EFI_SUCCESS The VLAN is successfully configured. + @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE: + - This is NULL. + - VlanId is an invalid VLAN Identifier. + - Priority is invalid. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to perform the registration. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_VLAN_CONFIG_SET)( + IN EFI_VLAN_CONFIG_PROTOCOL *This, + IN UINT16 VlanId, + IN UINT8 Priority + ); + +/** + Find configuration information for specified VLAN or all configured VLANs. + + The Find() function is used to find the configuration information for matching + VLAN and allocate a buffer into which those entries are copied. + + @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL. + @param[in] VlanId Pointer to VLAN identifier. Set to NULL to find all + configured VLANs. + @param[out] NumberOfVlan The number of VLANs which is found by the specified criteria. + @param[out] Entries The buffer which receive the VLAN configuration. + + @retval EFI_SUCCESS The VLAN is successfully found. + @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE: + - This is NULL. + - Specified VlanId is invalid. + @retval EFI_NOT_FOUND No matching VLAN is found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_VLAN_CONFIG_FIND)( + IN EFI_VLAN_CONFIG_PROTOCOL *This, + IN UINT16 *VlanId OPTIONAL, + OUT UINT16 *NumberOfVlan, + OUT EFI_VLAN_FIND_DATA **Entries + ); + +/** + Remove the configured VLAN device. + + The Remove() function is used to remove the specified VLAN device. + If the VlanId is out of the scope of (0-4094), EFI_INVALID_PARAMETER is returned. + If specified VLAN hasn't been previously configured, EFI_NOT_FOUND is returned. + + @param[in] This Points to the EFI_VLAN_CONFIG_PROTOCOL. + @param[in] VlanId Identifier (0-4094) of the VLAN to be removed. + + @retval EFI_SUCCESS The VLAN is successfully removed. + @retval EFI_INVALID_PARAMETER One or more of following conditions is TRUE: + - This is NULL. + - VlanId is an invalid parameter. + @retval EFI_NOT_FOUND The to-be-removed VLAN does not exist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_VLAN_CONFIG_REMOVE)( + IN EFI_VLAN_CONFIG_PROTOCOL *This, + IN UINT16 VlanId + ); + +/// +/// EFI_VLAN_CONFIG_PROTOCOL +/// provide manageability interface for VLAN setting. The intended +/// VLAN tagging implementation is IEEE802.1Q. +/// +struct _EFI_VLAN_CONFIG_PROTOCOL { + EFI_VLAN_CONFIG_SET Set; + EFI_VLAN_CONFIG_FIND Find; + EFI_VLAN_CONFIG_REMOVE Remove; +}; + +extern EFI_GUID gEfiVlanConfigProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WatchdogTimer.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WatchdogTimer.h new file mode 100644 index 0000000..9e3d0f3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WatchdogTimer.h @@ -0,0 +1,144 @@ +/** @file + Watchdog Timer Architectural Protocol as defined in PI Specification VOLUME 2 DXE + + Used to provide system watchdog timer services + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __ARCH_PROTOCOL_WATCHDOG_TIMER_H__ +#define __ARCH_PROTOCOL_WATCHDOG_TIMER_H__ + +/// +/// Global ID for the Watchdog Timer Architectural Protocol +/// +#define EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID \ + { 0x665E3FF5, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +/// +/// Declare forward reference for the Timer Architectural Protocol +/// +typedef struct _EFI_WATCHDOG_TIMER_ARCH_PROTOCOL EFI_WATCHDOG_TIMER_ARCH_PROTOCOL; + +/** + A function of this type is called when the watchdog timer fires if a + handler has been registered. + + @param Time The time in 100 ns units that has passed since the watchdog + timer was armed. For the notify function to be called, this + must be greater than TimerPeriod. + + @return None. + +**/ +typedef +VOID +(EFIAPI *EFI_WATCHDOG_TIMER_NOTIFY)( + IN UINT64 Time + ); + +/** + This function registers a handler that is to be invoked when the watchdog + timer fires. By default, the EFI_WATCHDOG_TIMER protocol will call the + Runtime Service ResetSystem() when the watchdog timer fires. If a + NotifyFunction is registered, then the NotifyFunction will be called before + the Runtime Service ResetSystem() is called. If NotifyFunction is NULL, then + the watchdog handler is unregistered. If a watchdog handler is registered, + then EFI_SUCCESS is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to uninstall a handler when a handler is not installed, + then return EFI_INVALID_PARAMETER. + + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when the watchdog timer fires. If this + is NULL, then the handler will be unregistered. + + @retval EFI_SUCCESS The watchdog timer handler was registered or + unregistered. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not + previously registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_TIMER_REGISTER_HANDLER)( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction + ); + +/** + This function sets the amount of time to wait before firing the watchdog + timer to TimerPeriod 100 nS units. If TimerPeriod is 0, then the watchdog + timer is disabled. + + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The amount of time in 100 nS units to wait before the watchdog + timer is fired. If TimerPeriod is zero, then the watchdog + timer is disabled. + + @retval EFI_SUCCESS The watchdog timer has been programmed to fire in Time + 100 nS units. + @retval EFI_DEVICE_ERROR A watchdog timer could not be programmed due to a device + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD)( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ); + +/** + This function retrieves the amount of time the system will wait before firing + the watchdog timer. This period is returned in TimerPeriod, and EFI_SUCCESS + is returned. If TimerPeriod is NULL, then EFI_INVALID_PARAMETER is returned. + + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the amount of time in 100 nS units that the system + will wait before the watchdog timer is fired. If TimerPeriod of + zero is returned, then the watchdog timer is disabled. + + @retval EFI_SUCCESS The amount of time that the system will wait before + firing the watchdog timer was returned in TimerPeriod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD)( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ); + + +/// +/// This protocol provides the services required to implement the Boot Service +/// SetWatchdogTimer(). It provides a service to set the amount of time to wait +/// before firing the watchdog timer, and it also provides a service to register +/// a handler that is invoked when the watchdog timer fires. This protocol can +/// implement the watchdog timer by using the event and timer Boot Services, or +/// it can make use of custom hardware. When the watchdog timer fires, control +/// will be passed to a handler if one has been registered. If no handler has +/// been registered, or the registered handler returns, then the system will be +/// reset by calling the Runtime Service ResetSystem(). +/// +struct _EFI_WATCHDOG_TIMER_ARCH_PROTOCOL { + EFI_WATCHDOG_TIMER_REGISTER_HANDLER RegisterHandler; + EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD SetTimerPeriod; + EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD GetTimerPeriod; +}; + +extern EFI_GUID gEfiWatchdogTimerArchProtocolGuid; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi.h new file mode 100644 index 0000000..cbc1a17 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi.h @@ -0,0 +1,1129 @@ +/** @file + This file provides management service interfaces of 802.11 MAC layer. It is used by + network applications (and drivers) to establish wireless connection with an access + point (AP). + + Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.5 + +**/ + +#ifndef __EFI_WIFI_PROTOCOL_H__ +#define __EFI_WIFI_PROTOCOL_H__ + +#include + +#define EFI_WIRELESS_MAC_CONNECTION_PROTOCOL_GUID \ + { \ + 0xda55bc9, 0x45f8, 0x4bb4, {0x87, 0x19, 0x52, 0x24, 0xf1, 0x8a, 0x4d, 0x45 } \ + } + +typedef struct _EFI_WIRELESS_MAC_CONNECTION_PROTOCOL EFI_WIRELESS_MAC_CONNECTION_PROTOCOL; + +/// +/// EFI_80211_ACC_NET_TYPE +/// +typedef enum { + IeeePrivate = 0, + IeeePrivatewithGuest = 1, + IeeeChargeablePublic = 2, + IeeeFreePublic = 3, + IeeePersonal = 4, + IeeeEmergencyServOnly = 5, + IeeeTestOrExp = 14, + IeeeWildcard = 15 +} EFI_80211_ACC_NET_TYPE; + +/// +/// EFI_80211_ASSOCIATE_RESULT_CODE +/// +typedef enum { + AssociateSuccess, + AssociateRefusedReasonUnspecified, + AssociateRefusedCapsMismatch, + AssociateRefusedExtReason, + AssociateRefusedAPOutOfMemory, + AssociateRefusedBasicRatesMismatch, + AssociateRejectedEmergencyServicesNotSupported, + AssociateRefusedTemporarily +} EFI_80211_ASSOCIATE_RESULT_CODE; + +/// +/// EFI_80211_SCAN_RESULT_CODE +/// +typedef enum { + /// + /// The scan operation finished successfully. + /// + ScanSuccess, + /// + /// The scan operation is not supported in current implementation. + /// + ScanNotSupported +} EFI_80211_SCAN_RESULT_CODE; + +/// +/// EFI_80211_REASON_CODE +/// +typedef enum { + Ieee80211UnspecifiedReason = 1, + Ieee80211PreviousAuthenticateInvalid = 2, + Ieee80211DeauthenticatedSinceLeaving = 3, + Ieee80211DisassociatedDueToInactive = 4, + Ieee80211DisassociatedSinceApUnable = 5, + Ieee80211Class2FrameNonauthenticated = 6, + Ieee80211Class3FrameNonassociated = 7, + Ieee80211DisassociatedSinceLeaving = 8, + // ... +} EFI_80211_REASON_CODE; + +/// +/// EFI_80211_DISASSOCIATE_RESULT_CODE +/// +typedef enum { + /// + /// Disassociation process completed successfully. + /// + DisassociateSuccess, + /// + /// Disassociation failed due to any input parameter is invalid. + /// + DisassociateInvalidParameters +} EFI_80211_DISASSOCIATE_RESULT_CODE; + +/// +/// EFI_80211_AUTHENTICATION_TYPE +/// +typedef enum { + /// + /// Open system authentication, admits any STA to the DS. + /// + OpenSystem, + /// + /// Shared Key authentication relies on WEP to demonstrate knowledge of a WEP + /// encryption key. + /// + SharedKey, + /// + /// FT authentication relies on keys derived during the initial mobility domain + /// association to authenticate the stations. + /// + FastBSSTransition, + /// + /// SAE authentication uses finite field cryptography to prove knowledge of a shared + /// password. + /// + SAE +} EFI_80211_AUTHENTICATION_TYPE; + +/// +/// EFI_80211_AUTHENTICATION_RESULT_CODE +/// +typedef enum { + AuthenticateSuccess, + AuthenticateRefused, + AuthenticateAnticLoggingTokenRequired, + AuthenticateFiniteCyclicGroupNotSupported, + AuthenticationRejected, + AuthenticateInvalidParameter +} EFI_80211_AUTHENTICATE_RESULT_CODE; + +/// +/// EFI_80211_ELEMENT_HEADER +/// +typedef struct { + /// + /// A unique element ID defined in IEEE 802.11 specification. + /// + UINT8 ElementID; + /// + /// Specifies the number of octets in the element body. + /// + UINT8 Length; +} EFI_80211_ELEMENT_HEADER; + +/// +/// EFI_80211_ELEMENT_REQ +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Start of elements that are requested to be included in the Probe Response frame. + /// The elements are listed in order of increasing element ID. + /// + UINT8 RequestIDs[1]; +} EFI_80211_ELEMENT_REQ; + +/// +/// EFI_80211_ELEMENT_SSID +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Service set identifier. If Hdr.Length is zero, this field is ignored. + /// + UINT8 SSId[32]; +} EFI_80211_ELEMENT_SSID; + +/// +/// EFI_80211_SCAN_DATA +/// +typedef struct { + /// + /// Determines whether infrastructure BSS, IBSS, MBSS, or all, are included in the + /// scan. + /// + EFI_80211_BSS_TYPE BSSType; + /// + /// Indicates a specific or wildcard BSSID. Use all binary 1s to represent all SSIDs. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Length in bytes of the SSId. If zero, ignore SSId field. + /// + UINT8 SSIdLen; + /// + /// Specifies the desired SSID or the wildcard SSID. Use NULL to represent all SSIDs. + /// + UINT8 *SSId; + /// + /// Indicates passive scanning if TRUE. + /// + BOOLEAN PassiveMode; + /// + /// The delay in microseconds to be used prior to transmitting a Probe frame during + /// active scanning. If zero, the value can be overridden by an + /// implementation-dependent default value. + /// + UINT32 ProbeDelay; + /// + /// Specifies a list of channels that are examined when scanning for a BSS. If set to + /// NULL, all valid channels will be scanned. + /// + UINT32 *ChannelList; + /// + /// Indicates the minimum time in TU to spend on each channel when scanning. If zero, + /// the value can be overridden by an implementation-dependent default value. + /// + UINT32 MinChannelTime; + /// + /// Indicates the maximum time in TU to spend on each channel when scanning. If zero, + /// the value can be overridden by an implementation-dependent default value. + /// + UINT32 MaxChannelTime; + /// + /// Points to an optionally present element. This is an optional parameter and may be + /// NULL. + /// + EFI_80211_ELEMENT_REQ *RequestInformation; + /// + /// Indicates one or more SSID elements that are optionally present. This is an + /// optional parameter and may be NULL. + /// + EFI_80211_ELEMENT_SSID *SSIDList; + /// + /// Specifies a desired specific access network type or the wildcard access network + /// type. Use 15 as wildcard access network type. + /// + EFI_80211_ACC_NET_TYPE AccessNetworkType; + /// + /// Specifies zero or more elements. This is an optional parameter and may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_SCAN_DATA; + +/// +/// EFI_80211_COUNTRY_TRIPLET_SUBBAND +/// +typedef struct { + /// + /// Indicates the lowest channel number in the subband. It has a positive integer + /// value less than 201. + /// + UINT8 FirstChannelNum; + /// + /// Indicates the number of channels in the subband. + /// + UINT8 NumOfChannels; + /// + /// Indicates the maximum power in dBm allowed to be transmitted. + /// + UINT8 MaxTxPowerLevel; +} EFI_80211_COUNTRY_TRIPLET_SUBBAND; + +/// +/// EFI_80211_COUNTRY_TRIPLET_OPERATE +/// +typedef struct { + /// + /// Indicates the operating extension identifier. It has a positive integer value of + /// 201 or greater. + /// + UINT8 OperatingExtId; + /// + /// Index into a set of values for radio equipment set of rules. + /// + UINT8 OperatingClass; + /// + /// Specifies aAirPropagationTime characteristics used in BSS operation. Refer the + /// definition of aAirPropagationTime in IEEE 802.11 specification. + /// + UINT8 CoverageClass; +} EFI_80211_COUNTRY_TRIPLET_OPERATE; + +/// +/// EFI_80211_COUNTRY_TRIPLET +/// +typedef union { + /// + /// The subband triplet. + /// + EFI_80211_COUNTRY_TRIPLET_SUBBAND Subband; + /// + /// The operating triplet. + /// + EFI_80211_COUNTRY_TRIPLET_OPERATE Operating; +} EFI_80211_COUNTRY_TRIPLET; + +/// +/// EFI_80211_ELEMENT_COUNTRY +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Specifies country strings in 3 octets. + /// + UINT8 CountryStr[3]; + /// + /// Indicates a triplet that repeated in country element. The number of triplets is + /// determined by the Hdr.Length field. + /// + EFI_80211_COUNTRY_TRIPLET CountryTriplet[1]; +} EFI_80211_ELEMENT_COUNTRY; + +/// +/// EFI_80211_ELEMENT_DATA_RSN +/// +typedef struct { + /// + /// Indicates the version number of the RSNA protocol. Value 1 is defined in current + /// IEEE 802.11 specification. + /// + UINT16 Version; + /// + /// Specifies the cipher suite selector used by the BSS to protect group address frames. + /// + UINT32 GroupDataCipherSuite; + /// + /// Indicates the number of pairwise cipher suite selectors that are contained in + /// PairwiseCipherSuiteList. + /// +//UINT16 PairwiseCipherSuiteCount; + /// + /// Contains a series of cipher suite selectors that indicate the pairwise cipher + /// suites contained in this element. + /// +//UINT32 PairwiseCipherSuiteList[PairwiseCipherSuiteCount]; + /// + /// Indicates the number of AKM suite selectors that are contained in AKMSuiteList. + /// +//UINT16 AKMSuiteCount; + /// + /// Contains a series of AKM suite selectors that indicate the AKM suites contained in + /// this element. + /// +//UINT32 AKMSuiteList[AKMSuiteCount]; + /// + /// Indicates requested or advertised capabilities. + /// +//UINT16 RSNCapabilities; + /// + /// Indicates the number of PKMIDs in the PMKIDList. + /// +//UINT16 PMKIDCount; + /// + /// Contains zero or more PKMIDs that the STA believes to be valid for the destination + /// AP. +//UINT8 PMKIDList[PMKIDCount][16]; + /// + /// Specifies the cipher suite selector used by the BSS to protect group addressed + /// robust management frames. + /// +//UINT32 GroupManagementCipherSuite; +} EFI_80211_ELEMENT_DATA_RSN; + +/// +/// EFI_80211_ELEMENT_RSN +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Points to RSN element. The size of a RSN element is limited to 255 octets. + /// + EFI_80211_ELEMENT_DATA_RSN *Data; +} EFI_80211_ELEMENT_RSN; + +/// +/// EFI_80211_ELEMENT_EXT_CAP +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Indicates the capabilities being advertised by the STA transmitting the element. + /// This is a bit field with variable length. Refer to IEEE 802.11 specification for + /// bit value. + /// + UINT8 Capabilities[1]; +} EFI_80211_ELEMENT_EXT_CAP; + +/// +/// EFI_80211_BSS_DESCRIPTION +/// +typedef struct { + /// + /// Indicates a specific BSSID of the found BSS. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the SSID of the found BSS. If NULL, ignore SSIdLen field. + /// + UINT8 *SSId; + /// + /// Specifies the SSID of the found BSS. If NULL, ignore SSIdLen field. + /// + UINT8 SSIdLen; + /// + /// Specifies the type of the found BSS. + /// + EFI_80211_BSS_TYPE BSSType; + /// + /// The beacon period in TU of the found BSS. + /// + UINT16 BeaconPeriod; + /// + /// The timestamp of the received frame from the found BSS. + /// + UINT64 Timestamp; + /// + /// The advertised capabilities of the BSS. + /// + UINT16 CapabilityInfo; + /// + /// The set of data rates that shall be supported by all STAs that desire to join this + /// BSS. + /// + UINT8 *BSSBasicRateSet; + /// + /// The set of data rates that the peer STA desires to use for communication within + /// the BSS. + /// + UINT8 *OperationalRateSet; + /// + /// The information required to identify the regulatory domain in which the peer STA + /// is located. + /// + EFI_80211_ELEMENT_COUNTRY *Country; + /// + /// The cipher suites and AKM suites supported in the BSS. + /// + EFI_80211_ELEMENT_RSN RSN; + /// + /// Specifies the RSSI of the received frame. + /// + UINT8 RSSI; + /// + /// Specifies the RCPI of the received frame. + /// + UINT8 RCPIMeasurement; + /// + /// Specifies the RSNI of the received frame. + /// + UINT8 RSNIMeasurement; + /// + /// Specifies the elements requested by the request element of the Probe Request frame. + /// This is an optional parameter and may be NULL. + /// + UINT8 *RequestedElements; + /// + /// Specifies the BSS membership selectors that represent the set of features that + /// shall be supported by all STAs to join this BSS. + /// + UINT8 *BSSMembershipSelectorSet; + /// + /// Specifies the parameters within the Extended Capabilities element that are + /// supported by the MAC entity. This is an optional parameter and may be NULL. + /// + EFI_80211_ELEMENT_EXT_CAP *ExtCapElement; +} EFI_80211_BSS_DESCRIPTION; + +/// +/// EFI_80211_SUBELEMENT_INFO +/// +typedef struct { + /// + /// Indicates the unique identifier within the containing element or sub-element. + /// + UINT8 SubElementID; + /// + /// Specifies the number of octets in the Data field. + /// + UINT8 Length; + /// + /// A variable length data buffer. + /// + UINT8 Data[1]; +} EFI_80211_SUBELEMENT_INFO; + +/// +/// EFI_80211_MULTIPLE_BSSID +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Indicates the maximum number of BSSIDs in the multiple BSSID set. When Indicator + /// is set to n, 2n is the maximum number. + /// + UINT8 Indicator; + /// + /// Contains zero or more sub-elements. + /// + EFI_80211_SUBELEMENT_INFO SubElement[1]; +} EFI_80211_MULTIPLE_BSSID; + +/// +/// EFI_80211_BSS_DESP_PILOT +/// +typedef struct { + /// + /// Indicates a specific BSSID of the found BSS. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the type of the found BSS. + /// + EFI_80211_BSS_TYPE BSSType; + /// + /// One octet field to report condensed capability information. + /// + UINT8 ConCapInfo; + /// + /// Two octet's field to report condensed country string. + /// + UINT8 ConCountryStr[2]; + /// + /// Indicates the operating class value for the operating channel. + /// + UINT8 OperatingClass; + /// + /// Indicates the operating channel. + /// + UINT8 Channel; + /// + /// Indicates the measurement pilot interval in TU. + /// + UINT8 Interval; + /// + /// Indicates that the BSS is within a multiple BSSID set. + /// + EFI_80211_MULTIPLE_BSSID *MultipleBSSID; + /// + /// Specifies the RCPI of the received frame. + /// + UINT8 RCPIMeasurement; + /// + /// Specifies the RSNI of the received frame. + /// + UINT8 RSNIMeasurement; +} EFI_80211_BSS_DESP_PILOT; + +/// +/// EFI_80211_SCAN_RESULT +/// +typedef struct { + /// + /// The number of EFI_80211_BSS_DESCRIPTION in BSSDespSet. If zero, BSSDespSet should + /// be ignored. + /// + UINTN NumOfBSSDesp; + /// + /// Points to zero or more instances of EFI_80211_BSS_DESCRIPTION. + /// + EFI_80211_BSS_DESCRIPTION **BSSDespSet; + /// + /// The number of EFI_80211_BSS_DESP_PILOT in BSSDespFromPilotSet. If zero, + /// BSSDespFromPilotSet should be ignored. + /// + UINTN NumofBSSDespFromPilot; + /// + /// Points to zero or more instances of EFI_80211_BSS_DESP_PILOT. + /// + EFI_80211_BSS_DESP_PILOT **BSSDespFromPilotSet; + /// + /// Specifies zero or more elements. This is an optional parameter and may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_SCAN_RESULT; + +/// +/// EFI_80211_SCAN_DATA_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI Wireless + /// MAC Connection Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: Scan operation completed successfully. + /// EFI_NOT_FOUND: Failed to find available BSS. + /// EFI_DEVICE_ERROR: An unexpected network or system error occurred. + /// EFI_ACCESS_DENIED: The scan operation is not completed due to some underlying + /// hardware or software state. + /// EFI_NOT_READY: The scan operation is started but not yet completed. + EFI_STATUS Status; + /// + /// Pointer to the scan data. + /// + EFI_80211_SCAN_DATA *Data; + /// + /// Indicates the scan state. + /// + EFI_80211_SCAN_RESULT_CODE ResultCode; + /// + /// Indicates the scan result. It is caller's responsibility to free this buffer. + /// + EFI_80211_SCAN_RESULT *Result; +} EFI_80211_SCAN_DATA_TOKEN; + +/// +/// EFI_80211_ELEMENT_SUPP_CHANNEL_TUPLE +/// +typedef struct { + /// + /// The first channel number in a subband of supported channels. + /// + UINT8 FirstChannelNumber; + /// + /// The number of channels in a subband of supported channels. + /// + UINT8 NumberOfChannels; +} EFI_80211_ELEMENT_SUPP_CHANNEL_TUPLE; + +/// +/// EFI_80211_ELEMENT_SUPP_CHANNEL +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Indicates one or more tuples of (first channel, number of channels). + /// + EFI_80211_ELEMENT_SUPP_CHANNEL_TUPLE Subband[1]; +} EFI_80211_ELEMENT_SUPP_CHANNEL; + +/// +/// EFI_80211_ASSOCIATE_DATA +/// +typedef struct { + /// + /// Specifies the address of the peer MAC entity to associate with. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the requested operational capabilities to the AP in 2 octets. + /// + UINT16 CapabilityInfo; + /// + /// Specifies a time limit in TU, after which the associate procedure is terminated. + /// + UINT32 FailureTimeout; + /// + /// Specifies if in power save mode, how often the STA awakes and listens for the next + /// beacon frame in TU. + /// + UINT32 ListenInterval; + /// + /// Indicates a list of channels in which the STA is capable of operating. + /// + EFI_80211_ELEMENT_SUPP_CHANNEL *Channels; + /// + /// The cipher suites and AKM suites selected by the STA. + /// + EFI_80211_ELEMENT_RSN RSN; + /// + /// Specifies the parameters within the Extended Capabilities element that are + /// supported by the MAC entity. This is an optional parameter and may be NULL. + /// + EFI_80211_ELEMENT_EXT_CAP *ExtCapElement; + /// + /// Specifies zero or more elements. This is an optional parameter and may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_ASSOCIATE_DATA; + +/// +/// EFI_80211_ELEMENT_TIMEOUT_VAL +/// +typedef struct { + /// + /// Common header of an element. + /// + EFI_80211_ELEMENT_HEADER Hdr; + /// + /// Specifies the timeout interval type. + /// + UINT8 Type; + /// + /// Specifies the timeout interval value. + /// + UINT32 Value; +} EFI_80211_ELEMENT_TIMEOUT_VAL; + +/// +/// EFI_80211_ASSOCIATE_RESULT +/// +typedef struct { + /// + /// Specifies the address of the peer MAC entity from which the association request + /// was received. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the operational capabilities advertised by the AP. + /// + UINT16 CapabilityInfo; + /// + /// Specifies the association ID value assigned by the AP. + /// + UINT16 AssociationID; + /// + /// Indicates the measured RCPI of the corresponding association request frame. It is + /// an optional parameter and is set to zero if unavailable. + /// + UINT8 RCPIValue; + /// + /// Indicates the measured RSNI at the time the corresponding association request + /// frame was received. It is an optional parameter and is set to zero if unavailable. + /// + UINT8 RSNIValue; + /// + /// Specifies the parameters within the Extended Capabilities element that are + /// supported by the MAC entity. This is an optional parameter and may be NULL. + /// + EFI_80211_ELEMENT_EXT_CAP *ExtCapElement; + /// + /// Specifies the timeout interval when the result code is AssociateRefusedTemporarily. + /// + EFI_80211_ELEMENT_TIMEOUT_VAL TimeoutInterval; + /// + /// Specifies zero or more elements. This is an optional parameter and may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_ASSOCIATE_RESULT; + +/// +/// EFI_80211_ASSOCIATE_DATA_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI Wireless + /// MAC Connection Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: Association operation completed successfully. + /// EFI_DEVICE_ERROR: An unexpected network or system error occurred. + /// + EFI_STATUS Status; + /// + /// Pointer to the association data. + /// + EFI_80211_ASSOCIATE_DATA *Data; + /// + /// Indicates the association state. + /// + EFI_80211_ASSOCIATE_RESULT_CODE ResultCode; + /// + /// Indicates the association result. It is caller's responsibility to free this + /// buffer. + /// + EFI_80211_ASSOCIATE_RESULT *Result; +} EFI_80211_ASSOCIATE_DATA_TOKEN; + +/// +/// EFI_80211_DISASSOCIATE_DATA +/// +typedef struct { + /// + /// Specifies the address of the peer MAC entity with which to perform the + /// disassociation process. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the reason for initiating the disassociation process. + /// + EFI_80211_REASON_CODE ReasonCode; + /// + /// Zero or more elements, may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_DISASSOCIATE_DATA; + +/// +/// EFI_80211_DISASSOCIATE_DATA_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI Wireless + /// MAC Connection Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: Disassociation operation completed successfully. + /// EFI_DEVICE_ERROR: An unexpected network or system error occurred. + /// EFI_ACCESS_DENIED: The disassociation operation is not completed due to some + /// underlying hardware or software state. + /// EFI_NOT_READY: The disassociation operation is started but not yet completed. + /// + EFI_STATUS Status; + /// + /// Pointer to the disassociation data. + /// + EFI_80211_DISASSOCIATE_DATA *Data; + /// + /// Indicates the disassociation state. + /// + EFI_80211_DISASSOCIATE_RESULT_CODE ResultCode; +} EFI_80211_DISASSOCIATE_DATA_TOKEN; + +/// +/// EFI_80211_AUTHENTICATION_DATA +/// +typedef struct { + /// + /// Specifies the address of the peer MAC entity with which to perform the + /// authentication process. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the type of authentication algorithm to use during the authentication + /// process. + /// + EFI_80211_AUTHENTICATION_TYPE AuthType; + /// + /// Specifies a time limit in TU after which the authentication procedure is + /// terminated. + /// + UINT32 FailureTimeout; + /// + /// Specifies the set of elements to be included in the first message of the FT + /// authentication sequence, may be NULL. + /// + UINT8 *FTContent; + /// + /// Specifies the set of elements to be included in the SAE Commit Message or SAE + /// Confirm Message, may be NULL. + /// + UINT8 *SAEContent; + /// + /// Zero or more elements, may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_AUTHENTICATE_DATA; + +/// +/// EFI_80211_AUTHENTICATION_RESULT +/// +typedef struct { + /// + /// Specifies the address of the peer MAC entity from which the authentication request + /// was received. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the set of elements to be included in the second message of the FT + /// authentication sequence, may be NULL. + /// + UINT8 *FTContent; + /// + /// Specifies the set of elements to be included in the SAE Commit Message or SAE + /// Confirm Message, may be NULL. + /// + UINT8 *SAEContent; + /// + /// Zero or more elements, may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_AUTHENTICATE_RESULT; + +/// +/// EFI_80211_AUTHENTICATE_DATA_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI Wireless + /// MAC Connection Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: Authentication operation completed successfully. + /// EFI_PROTOCOL_ERROR: Peer MAC entity rejects the authentication. + /// EFI_NO_RESPONSE: Peer MAC entity does not response the authentication request. + /// EFI_DEVICE_ERROR: An unexpected network or system error occurred. + /// EFI_ACCESS_DENIED: The authentication operation is not completed due to some + /// underlying hardware or software state. + /// EFI_NOT_READY: The authentication operation is started but not yet completed. + /// + EFI_STATUS Status; + /// + /// Pointer to the authentication data. + /// + EFI_80211_AUTHENTICATE_DATA *Data; + /// + /// Indicates the association state. + /// + EFI_80211_AUTHENTICATE_RESULT_CODE ResultCode; + /// + /// Indicates the association result. It is caller's responsibility to free this + /// buffer. + /// + EFI_80211_AUTHENTICATE_RESULT *Result; +} EFI_80211_AUTHENTICATE_DATA_TOKEN; + +/// +/// EFI_80211_DEAUTHENTICATE_DATA +/// +typedef struct { + /// + /// Specifies the address of the peer MAC entity with which to perform the + /// deauthentication process. + /// + EFI_80211_MAC_ADDRESS BSSId; + /// + /// Specifies the reason for initiating the deauthentication process. + /// + EFI_80211_REASON_CODE ReasonCode; + /// + /// Zero or more elements, may be NULL. + /// + UINT8 *VendorSpecificInfo; +} EFI_80211_DEAUTHENTICATE_DATA; + +/// +/// EFI_80211_DEAUTHENTICATE_DATA_TOKEN +/// +typedef struct { + /// + /// This Event will be signaled after the Status field is updated by the EFI Wireless + /// MAC Connection Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. + /// + EFI_EVENT Event; + /// + /// Will be set to one of the following values: + /// EFI_SUCCESS: Deauthentication operation completed successfully. + /// EFI_DEVICE_ERROR: An unexpected network or system error occurred. + /// EFI_ACCESS_DENIED: The deauthentication operation is not completed due to some + /// underlying hardware or software state. + /// EFI_NOT_READY: The deauthentication operation is started but not yet + /// completed. + /// + EFI_STATUS Status; + /// + /// Pointer to the deauthentication data. + /// + EFI_80211_DEAUTHENTICATE_DATA *Data; +} EFI_80211_DEAUTHENTICATE_DATA_TOKEN; + +/** + Request a survey of potential BSSs that administrator can later elect to try to join. + + The Scan() function returns the description of the set of BSSs detected by the scan + process. Passive scan operation is performed by default. + + @param[in] This Pointer to the EFI_WIRELESS_MAC_CONNECTION_PROTOCOL + instance. + @param[in] Data Pointer to the scan token. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + Data->Data is NULL. + @retval EFI_UNSUPPORTED One or more of the input parameters are not supported + by this implementation. + @retval EFI_ALREADY_STARTED The scan operation is already started. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_SCAN)( + IN EFI_WIRELESS_MAC_CONNECTION_PROTOCOL *This, + IN EFI_80211_SCAN_DATA_TOKEN *Data + ); + +/** + Request an association with a specified peer MAC entity that is within an AP. + + The Associate() function provides the capability for MAC layer to become associated + with an AP. + + @param[in] This Pointer to the EFI_WIRELESS_MAC_CONNECTION_PROTOCOL + instance. + @param[in] Data Pointer to the association token. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + Data->Data is NULL. + @retval EFI_UNSUPPORTED One or more of the input parameters are not supported + by this implementation. + @retval EFI_ALREADY_STARTED The association process is already started. + @retval EFI_NOT_READY Authentication is not performed before this association + process. + @retval EFI_NOT_FOUND The specified peer MAC entity is not found. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_ASSOCIATE)( + IN EFI_WIRELESS_MAC_CONNECTION_PROTOCOL *This, + IN EFI_80211_ASSOCIATE_DATA_TOKEN *Data + ); + +/** + Request a disassociation with a specified peer MAC entity. + + The Disassociate() function is invoked to terminate an existing association. + Disassociation is a notification and cannot be refused by the receiving peer except + when management frame protection is negotiated and the message integrity check fails. + + @param[in] This Pointer to the EFI_WIRELESS_MAC_CONNECTION_PROTOCOL + instance. + @param[in] Data Pointer to the disassociation token. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + @retval EFI_ALREADY_STARTED The disassociation process is already started. + @retval EFI_NOT_READY The disassociation service is invoked to a + nonexistent association relationship. + @retval EFI_NOT_FOUND The specified peer MAC entity is not found. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_DISASSOCIATE)( + IN EFI_WIRELESS_MAC_CONNECTION_PROTOCOL *This, + IN EFI_80211_DISASSOCIATE_DATA_TOKEN *Data + ); + +/** + Request the process of establishing an authentication relationship with a peer MAC + entity. + + The Authenticate() function requests authentication with a specified peer MAC entity. + This service might be time-consuming thus is designed to be invoked independently of + the association service. + + @param[in] This Pointer to the EFI_WIRELESS_MAC_CONNECTION_PROTOCOL + instance. + @param[in] Data Pointer to the authentication token. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + Data.Data is NULL. + @retval EFI_UNSUPPORTED One or more of the input parameters are not supported + by this implementation. + @retval EFI_ALREADY_STARTED The authentication process is already started. + @retval EFI_NOT_FOUND The specified peer MAC entity is not found. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_AUTHENTICATE)( + IN EFI_WIRELESS_MAC_CONNECTION_PROTOCOL *This, + IN EFI_80211_AUTHENTICATE_DATA_TOKEN *Data + ); + +/** + Invalidate the authentication relationship with a peer MAC entity. + + The Deauthenticate() function requests that the authentication relationship with a + specified peer MAC entity be invalidated. Deauthentication is a notification and when + it is sent out the association at the transmitting station is terminated. + + @param[in] This Pointer to the EFI_WIRELESS_MAC_CONNECTION_PROTOCOL + instance. + @param[in] Data Pointer to the deauthentication token. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + Data.Data is NULL. + @retval EFI_ALREADY_STARTED The deauthentication process is already started. + @retval EFI_NOT_READY The deauthentication service is invoked to a + nonexistent association or authentication relationship. + @retval EFI_NOT_FOUND The specified peer MAC entity is not found. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_DEAUTHENTICATE)( + IN EFI_WIRELESS_MAC_CONNECTION_PROTOCOL *This, + IN EFI_80211_DEAUTHENTICATE_DATA_TOKEN *Data + ); + +/// +/// The EFI_WIRELESS_MAC_CONNECTION_PROTOCOL is designed to provide management service +/// interfaces for the EFI wireless network stack to establish wireless connection with +/// AP. An EFI Wireless MAC Connection Protocol instance will be installed on each +/// communication device that the EFI wireless network stack runs on. +/// +struct _EFI_WIRELESS_MAC_CONNECTION_PROTOCOL { + EFI_WIRELESS_MAC_CONNECTION_SCAN Scan; + EFI_WIRELESS_MAC_CONNECTION_ASSOCIATE Associate; + EFI_WIRELESS_MAC_CONNECTION_DISASSOCIATE Disassociate; + EFI_WIRELESS_MAC_CONNECTION_AUTHENTICATE Authenticate; + EFI_WIRELESS_MAC_CONNECTION_DEAUTHENTICATE Deauthenticate; +}; + +extern EFI_GUID gEfiWiFiProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi2.h new file mode 100644 index 0000000..d7cc3a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Protocol/WiFi2.h @@ -0,0 +1,413 @@ +/** @file + This file defines the EFI Wireless MAC Connection II Protocol. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + This Protocol is introduced in UEFI Specification 2.6 + +**/ + +#ifndef __EFI_WIFI2_PROTOCOL_H__ +#define __EFI_WIFI2_PROTOCOL_H__ + +#define EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL_GUID \ + { \ + 0x1b0fb9bf, 0x699d, 0x4fdd, { 0xa7, 0xc3, 0x25, 0x46, 0x68, 0x1b, 0xf6, 0x3b } \ + } + +typedef struct _EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL; + +/// +/// EFI_80211_BSS_TYPE +/// +typedef enum { + IeeeInfrastructureBSS, + IeeeIndependentBSS, + IeeeMeshBSS, + IeeeAnyBss +} EFI_80211_BSS_TYPE; + +/// +/// EFI_80211_CONNECT_NETWORK_RESULT_CODE +/// +typedef enum { + // + // The connection establishment operation finished successfully. + // + ConnectSuccess, + // + // The connection was refused by the Network. + // + ConnectRefused, + // + // The connection establishment operation failed (i.e, Network is not + // detected). + // + ConnectFailed, + // + // The connection establishment operation was terminated on timeout. + // + ConnectFailureTimeout, + // + // The connection establishment operation failed on other reason. + // + ConnectFailedReasonUnspecified +} EFI_80211_CONNECT_NETWORK_RESULT_CODE; + +/// +/// EFI_80211_MAC_ADDRESS +/// +typedef struct { + UINT8 Addr[6]; +} EFI_80211_MAC_ADDRESS; + +#define EFI_MAX_SSID_LEN 32 + +/// +/// EFI_80211_SSID +/// +typedef struct { + // + // Length in bytes of the SSId. If zero, ignore SSId field. + // + UINT8 SSIdLen; + // + // Specifies the service set identifier. + // + UINT8 SSId[EFI_MAX_SSID_LEN]; +} EFI_80211_SSID; + +/// +/// EFI_80211_GET_NETWORKS_DATA +/// +typedef struct { + // + // The number of EFI_80211_SSID in SSIDList. If zero, SSIDList should be + // ignored. + // + UINT32 NumOfSSID; + // + // The SSIDList is a pointer to an array of EFI_80211_SSID instances. The + // number of entries is specified by NumOfSSID. The array should only include + // SSIDs of hidden networks. It is suggested that the caller inputs less than + // 10 elements in the SSIDList. It is the caller's responsibility to free + // this buffer. + // + EFI_80211_SSID SSIDList[1]; +} EFI_80211_GET_NETWORKS_DATA; + +/// +/// EFI_80211_SUITE_SELECTOR +/// +typedef struct { + // + // Organization Unique Identifier, as defined in IEEE 802.11 standard, + // usually set to 00-0F-AC. + // + UINT8 Oui[3]; + // + // Suites types, as defined in IEEE 802.11 standard. + // + UINT8 SuiteType; +} EFI_80211_SUITE_SELECTOR; + +/// +/// EFI_80211_AKM_SUITE_SELECTOR +/// +typedef struct { + // + // Indicates the number of AKM suite selectors that are contained in + // AKMSuiteList. If zero, the AKMSuiteList is ignored. + // + UINT16 AKMSuiteCount; + // + // A variable-length array of AKM suites, as defined in IEEE 802.11 standard, + // Table 8-101. The number of entries is specified by AKMSuiteCount. + // + EFI_80211_SUITE_SELECTOR AKMSuiteList[1]; +} EFI_80211_AKM_SUITE_SELECTOR; + +/// +/// EFI_80211_CIPHER_SUITE_SELECTOR +/// +typedef struct { + // + // Indicates the number of cipher suites that are contained in + // CipherSuiteList. If zero, the CipherSuiteList is ignored. + // + UINT16 CipherSuiteCount; + // + // A variable-length array of cipher suites, as defined in IEEE 802.11 + // standard, Table 8-99. The number of entries is specified by + // CipherSuiteCount. + // + EFI_80211_SUITE_SELECTOR CipherSuiteList[1]; +} EFI_80211_CIPHER_SUITE_SELECTOR; + +/// +/// EFI_80211_NETWORK +/// +typedef struct { + // + // Specifies the type of the BSS. + // + EFI_80211_BSS_TYPE BSSType; + // + // Specifies the SSID of the BSS. + // + EFI_80211_SSID SSId; + // + // Pointer to the AKM suites supported in the wireless network. + // + EFI_80211_AKM_SUITE_SELECTOR *AKMSuite; + // + // Pointer to the cipher suites supported in the wireless network. + // + EFI_80211_CIPHER_SUITE_SELECTOR *CipherSuite; +} EFI_80211_NETWORK; + +/// +/// EFI_80211_NETWORK_DESCRIPTION +/// +typedef struct { + // + // Specifies the found wireless network. + // + EFI_80211_NETWORK Network; + // + // Indicates the network quality as a value between 0 to 100, where 100 + // indicates the highest network quality. + // + UINT8 NetworkQuality; +} EFI_80211_NETWORK_DESCRIPTION; + +/// +/// EFI_80211_GET_NETWORKS_RESULT +/// +typedef struct { + // + // The number of EFI_80211_NETWORK_DESCRIPTION in NetworkDesc. If zero, + // NetworkDesc should be ignored. + // + UINT8 NumOfNetworkDesc; + // + // The NetworkDesc is a pointer to an array of EFI_80211_NETWORK_DESCRIPTION + // instances. It is caller's responsibility to free this buffer. + // + EFI_80211_NETWORK_DESCRIPTION NetworkDesc[1]; +} EFI_80211_GET_NETWORKS_RESULT; + +/// +/// EFI_80211_GET_NETWORKS_TOKEN +/// +typedef struct { + // + // If the status code returned by GetNetworks() is EFI_SUCCESS, then this + // Event will be signaled after the Status field is updated by the EFI + // Wireless MAC Connection Protocol II driver. The type of Event must be + // EFI_NOTIFY_SIGNAL. + // + EFI_EVENT Event; + // + // Will be set to one of the following values: + // EFI_SUCCESS: The operation completed successfully. + // EFI_NOT_FOUND: Failed to find available wireless networks. + // EFI_DEVICE_ERROR: An unexpected network or system error occurred. + // EFI_ACCESS_DENIED: The operation is not completed due to some underlying + // hardware or software state. + // EFI_NOT_READY: The operation is started but not yet completed. + // + EFI_STATUS Status; + // + // Pointer to the input data for getting networks. + // + EFI_80211_GET_NETWORKS_DATA *Data; + // + // Indicates the scan result. It is caller's responsibility to free this + // buffer. + // + EFI_80211_GET_NETWORKS_RESULT *Result; +} EFI_80211_GET_NETWORKS_TOKEN; + +/// +/// EFI_80211_CONNECT_NETWORK_DATA +/// +typedef struct { + // + // Specifies the wireless network to connect to. + // + EFI_80211_NETWORK *Network; + // + // Specifies a time limit in seconds that is optionally present, after which + // the connection establishment procedure is terminated by the UNDI driver. + // This is an optional parameter and may be 0. Values of 5 seconds or higher + // are recommended. + // + UINT32 FailureTimeout; +} EFI_80211_CONNECT_NETWORK_DATA; + +/// +/// EFI_80211_CONNECT_NETWORK_TOKEN +/// +typedef struct { + // + // If the status code returned by ConnectNetwork() is EFI_SUCCESS, then this + // Event will be signaled after the Status field is updated by the EFI + // Wireless MAC Connection Protocol II driver. The type of Event must be + // EFI_NOTIFY_SIGNAL. + // + EFI_EVENT Event; + // + // Will be set to one of the following values: + // EFI_SUCCESS: The operation completed successfully. + // EFI_DEVICE_ERROR: An unexpected network or system error occurred. + // EFI_ACCESS_DENIED: The operation is not completed due to some underlying + // hardware or software state. + // EFI_NOT_READY: The operation is started but not yet completed. + // + EFI_STATUS Status; + // + // Pointer to the connection data. + // + EFI_80211_CONNECT_NETWORK_DATA *Data; + // + // Indicates the connection state. + // + EFI_80211_CONNECT_NETWORK_RESULT_CODE ResultCode; +} EFI_80211_CONNECT_NETWORK_TOKEN; + +/// +/// EFI_80211_DISCONNECT_NETWORK_TOKEN +/// +typedef struct { + // + // If the status code returned by DisconnectNetwork() is EFI_SUCCESS, then + // this Event will be signaled after the Status field is updated by the EFI + // Wireless MAC Connection Protocol II driver. The type of Event must be + // EFI_NOTIFY_SIGNAL. + // + EFI_EVENT Event; + // + // Will be set to one of the following values: + // EFI_SUCCESS: The operation completed successfully + // EFI_DEVICE_ERROR: An unexpected network or system error occurred. + // EFI_ACCESS_DENIED: The operation is not completed due to some underlying + // hardware or software state. + // + EFI_STATUS Status; +} EFI_80211_DISCONNECT_NETWORK_TOKEN; + +/** + Request a survey of potential wireless networks that administrator can later + elect to try to join. + + @param[in] This Pointer to the + EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL + instance. + @param[in] Token Pointer to the token for getting wireless + network. + + @retval EFI_SUCCESS The operation started, and an event will + eventually be raised for the caller. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + This is NULL. + Token is NULL. + @retval EFI_UNSUPPORTED One or more of the input parameters is not + supported by this implementation. + @retval EFI_ALREADY_STARTED The operation of getting wireless network is + already started. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be + allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_II_GET_NETWORKS) ( + IN EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL *This, + IN EFI_80211_GET_NETWORKS_TOKEN *Token + ); + +/** + Connect a wireless network specified by a particular SSID, BSS type and + Security type. + + @param[in] This Pointer to the + EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL + instance. + @param[in] Token Pointer to the token for connecting wireless + network. + + @retval EFI_SUCCESS The operation started successfully. Results + will be notified eventually. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + This is NULL. + Token is NULL. + @retval EFI_UNSUPPORTED One or more of the input parameters are not + supported by this implementation. + @retval EFI_ALREADY_STARTED The connection process is already started. + @retval EFI_NOT_FOUND The specified wireless network is not found. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be + allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_II_CONNECT_NETWORK) ( + IN EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL *This, + IN EFI_80211_CONNECT_NETWORK_TOKEN *Token + ); + +/** + Request a disconnection with current connected wireless network. + + @param[in] This Pointer to the + EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL + instance. + @param[in] Token Pointer to the token for disconnecting + wireless network. + + @retval EFI_SUCCESS The operation started successfully. Results + will be notified eventually. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is + TRUE: + This is NULL. + Token is NULL. + @retval EFI_UNSUPPORTED One or more of the input parameters are not + supported by this implementation. + @retval EFI_NOT_FOUND Not connected to a wireless network. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be + allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WIRELESS_MAC_CONNECTION_II_DISCONNECT_NETWORK) ( + IN EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL *This, + IN EFI_80211_DISCONNECT_NETWORK_TOKEN *Token + ); + +/// +/// The EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL provides network management +/// service interfaces for 802.11 network stack. It is used by network +/// applications (and drivers) to establish wireless connection with a wireless +/// network. +/// +struct _EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL { + EFI_WIRELESS_MAC_CONNECTION_II_GET_NETWORKS GetNetworks; + EFI_WIRELESS_MAC_CONNECTION_II_CONNECT_NETWORK ConnectNetwork; + EFI_WIRELESS_MAC_CONNECTION_II_DISCONNECT_NETWORK DisconnectNetwork; +}; + +extern EFI_GUID gEfiWiFi2ProtocolGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi.h new file mode 100644 index 0000000..ada1b37 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi.h @@ -0,0 +1,27 @@ +/** @file + + Root include file for Mde Package UEFI, UEFI_APPLICATION type modules. + + This is the include file for any module of type UEFI and UEFI_APPLICATION. Uefi modules only use + types defined via this include file and can be ported easily to any + environment. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PI_UEFI_H__ +#define __PI_UEFI_H__ + +#include +#include + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiAcpiDataTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiAcpiDataTable.h new file mode 100644 index 0000000..1e638a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiAcpiDataTable.h @@ -0,0 +1,29 @@ +/** @file + UEFI ACPI Data Table Definition. + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_ACPI_DATA_TABLE_H__ +#define __UEFI_ACPI_DATA_TABLE_H__ + +#include + +#pragma pack(1) +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + GUID Identifier; + UINT16 DataOffset; +} EFI_ACPI_DATA_TABLE; +#pragma pack() + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiBaseType.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiBaseType.h new file mode 100644 index 0000000..c814c3f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiBaseType.h @@ -0,0 +1,291 @@ +/** @file + Defines data types and constants introduced in UEFI. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Portions copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.
+ +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_BASETYPE_H__ +#define __UEFI_BASETYPE_H__ + +#include + +// +// Basic data type definitions introduced in UEFI. +// + +/// +/// 128-bit buffer containing a unique identifier value. +/// +typedef GUID EFI_GUID; +/// +/// Function return status for EFI API. +/// +typedef RETURN_STATUS EFI_STATUS; +/// +/// A collection of related interfaces. +/// +typedef VOID *EFI_HANDLE; +/// +/// Handle to an event structure. +/// +typedef VOID *EFI_EVENT; +/// +/// Task priority level. +/// +typedef UINTN EFI_TPL; +/// +/// Logical block address. +/// +typedef UINT64 EFI_LBA; + +/// +/// 64-bit physical memory address. +/// +typedef UINT64 EFI_PHYSICAL_ADDRESS; + +/// +/// 64-bit virtual memory address. +/// +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +/// +/// EFI Time Abstraction: +/// Year: 1900 - 9999 +/// Month: 1 - 12 +/// Day: 1 - 31 +/// Hour: 0 - 23 +/// Minute: 0 - 59 +/// Second: 0 - 59 +/// Nanosecond: 0 - 999,999,999 +/// TimeZone: -1440 to 1440 or 2047 +/// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + + +/// +/// 4-byte buffer. An IPv4 internet protocol address. +/// +typedef IPv4_ADDRESS EFI_IPv4_ADDRESS; + +/// +/// 16-byte buffer. An IPv6 internet protocol address. +/// +typedef IPv6_ADDRESS EFI_IPv6_ADDRESS; + +/// +/// 32-byte buffer containing a network Media Access Control address. +/// +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +/// +/// 16-byte buffer aligned on a 4-byte boundary. +/// An IPv4 or IPv6 internet protocol address. +/// +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + + +/// +/// Enumeration of EFI_STATUS. +///@{ +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE +#define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE +#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA +#define EFI_HTTP_ERROR RETURN_HTTP_ERROR + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL +#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA +#define EFI_WARN_FILE_SYSTEM RETURN_WARN_FILE_SYSTEM +///@} + +/// +/// Define macro to encode the status code. +/// +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_ERROR(A) RETURN_ERROR(A) + +/// +/// ICMP error definitions +///@{ +#define EFI_NETWORK_UNREACHABLE EFIERR(100) +#define EFI_HOST_UNREACHABLE EFIERR(101) +#define EFI_PROTOCOL_UNREACHABLE EFIERR(102) +#define EFI_PORT_UNREACHABLE EFIERR(103) +///@} + +/// +/// Tcp connection status definitions +///@{ +#define EFI_CONNECTION_FIN EFIERR(104) +#define EFI_CONNECTION_RESET EFIERR(105) +#define EFI_CONNECTION_REFUSED EFIERR(106) +///@} + +// +// The EFI memory allocation functions work in units of EFI_PAGEs that are +// 4KB. This should in no way be confused with the page size of the processor. +// An EFI_PAGE is just the quanta of memory in EFI. +// +#define EFI_PAGE_SIZE SIZE_4KB +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 + +/** + Macro that converts a size, in bytes, to a number of EFI_PAGESs. + + @param Size A size in bytes. This parameter is assumed to be type UINTN. + Passing in a parameter that is larger than UINTN may produce + unexpected results. + + @return The number of EFI_PAGESs associated with the number of bytes specified + by Size. + +**/ +#define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0)) + +/** + Macro that converts a number of EFI_PAGEs to a size in bytes. + + @param Pages The number of EFI_PAGES. This parameter is assumed to be + type UINTN. Passing in a parameter that is larger than + UINTN may produce unexpected results. + + @return The number of bytes associated with the number of EFI_PAGEs specified + by Pages. + +**/ +#define EFI_PAGES_TO_SIZE(Pages) ((Pages) << EFI_PAGE_SHIFT) + +/// +/// PE32+ Machine type for IA32 UEFI images. +/// +#define EFI_IMAGE_MACHINE_IA32 0x014C + +/// +/// PE32+ Machine type for IA64 UEFI images. +/// +#define EFI_IMAGE_MACHINE_IA64 0x0200 + +/// +/// PE32+ Machine type for EBC UEFI images. +/// +#define EFI_IMAGE_MACHINE_EBC 0x0EBC + +/// +/// PE32+ Machine type for X64 UEFI images. +/// +#define EFI_IMAGE_MACHINE_X64 0x8664 + +/// +/// PE32+ Machine type for ARM mixed ARM and Thumb/Thumb2 images. +/// +#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2 + +/// +/// PE32+ Machine type for AARCH64 A64 images. +/// +#define EFI_IMAGE_MACHINE_AARCH64 0xAA64 + + +#if defined (MDE_CPU_IA32) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64) + +#elif defined (MDE_CPU_X64) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32) + +#elif defined (MDE_CPU_ARM) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE) + +#elif defined (MDE_CPU_AARCH64) + +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_AARCH64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE) + +#elif defined (MDE_CPU_EBC) + +/// +/// This is just to make sure you can cross compile with the EBC compiler. +/// It does not make sense to have a PE loader coded in EBC. +/// +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC) + +#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE) + +#else +#error Unknown Processor Type +#endif + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiGpt.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiGpt.h new file mode 100644 index 0000000..0c68339 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiGpt.h @@ -0,0 +1,145 @@ +/** @file + EFI Guid Partition Table Format Definition. + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_GPT_H__ +#define __UEFI_GPT_H__ + +/// +/// The primary GUID Partition Table Header must be +/// located in LBA 1 (i.e., the second logical block). +/// +#define PRIMARY_PART_HEADER_LBA 1 +/// +/// EFI Partition Table Signature: "EFI PART". +/// +#define EFI_PTAB_HEADER_ID SIGNATURE_64 ('E','F','I',' ','P','A','R','T') +/// +/// Minimum bytes reserve for EFI entry array buffer. +/// +#define EFI_GPT_PART_ENTRY_MIN_SIZE 16384 + +#pragma pack(1) + +/// +/// GPT Partition Table Header. +/// +typedef struct { + /// + /// The table header for the GPT partition Table. + /// This header contains EFI_PTAB_HEADER_ID. + /// + EFI_TABLE_HEADER Header; + /// + /// The LBA that contains this data structure. + /// + EFI_LBA MyLBA; + /// + /// LBA address of the alternate GUID Partition Table Header. + /// + EFI_LBA AlternateLBA; + /// + /// The first usable logical block that may be used + /// by a partition described by a GUID Partition Entry. + /// + EFI_LBA FirstUsableLBA; + /// + /// The last usable logical block that may be used + /// by a partition described by a GUID Partition Entry. + /// + EFI_LBA LastUsableLBA; + /// + /// GUID that can be used to uniquely identify the disk. + /// + EFI_GUID DiskGUID; + /// + /// The starting LBA of the GUID Partition Entry array. + /// + EFI_LBA PartitionEntryLBA; + /// + /// The number of Partition Entries in the GUID Partition Entry array. + /// + UINT32 NumberOfPartitionEntries; + /// + /// The size, in bytes, of each the GUID Partition + /// Entry structures in the GUID Partition Entry + /// array. This field shall be set to a value of 128 x 2^n where n is + /// an integer greater than or equal to zero (e.g., 128, 256, 512, etc.). + /// + UINT32 SizeOfPartitionEntry; + /// + /// The CRC32 of the GUID Partition Entry array. + /// Starts at PartitionEntryLBA and is + /// computed over a byte length of + /// NumberOfPartitionEntries * SizeOfPartitionEntry. + /// + UINT32 PartitionEntryArrayCRC32; +} EFI_PARTITION_TABLE_HEADER; + +/// +/// GPT Partition Entry. +/// +typedef struct { + /// + /// Unique ID that defines the purpose and type of this Partition. A value of + /// zero defines that this partition entry is not being used. + /// + EFI_GUID PartitionTypeGUID; + /// + /// GUID that is unique for every partition entry. Every partition ever + /// created will have a unique GUID. + /// This GUID must be assigned when the GUID Partition Entry is created. + /// + EFI_GUID UniquePartitionGUID; + /// + /// Starting LBA of the partition defined by this entry + /// + EFI_LBA StartingLBA; + /// + /// Ending LBA of the partition defined by this entry. + /// + EFI_LBA EndingLBA; + /// + /// Attribute bits, all bits reserved by UEFI + /// Bit 0: If this bit is set, the partition is required for the platform to function. The owner/creator of the + /// partition indicates that deletion or modification of the contents can result in loss of platform + /// features or failure for the platform to boot or operate. The system cannot function normally if + /// this partition is removed, and it should be considered part of the hardware of the system. + /// Actions such as running diagnostics, system recovery, or even OS install or boot, could + /// potentially stop working if this partition is removed. Unless OS software or firmware + /// recognizes this partition, it should never be removed or modified as the UEFI firmware or + /// platform hardware may become non-functional. + /// Bit 1: If this bit is set, then firmware must not produce an EFI_BLOCK_IO_PROTOCOL device for + /// this partition. By not producing an EFI_BLOCK_IO_PROTOCOL partition, file system + /// mappings will not be created for this partition in UEFI. + /// Bit 2: This bit is set aside to let systems with traditional PC-AT BIOS firmware implementations + /// inform certain limited, special-purpose software running on these systems that a GPT + /// partition may be bootable. The UEFI boot manager must ignore this bit when selecting + /// a UEFI-compliant application, e.g., an OS loader. + /// Bits 3-47: Undefined and must be zero. Reserved for expansion by future versions of the UEFI + /// specification. + /// Bits 48-63: Reserved for GUID specific use. The use of these bits will vary depending on the + /// PartitionTypeGUID. Only the owner of the PartitionTypeGUID is allowed + /// to modify these bits. They must be preserved if Bits 0-47 are modified.. + /// + UINT64 Attributes; + /// + /// Null-terminated name of the partition. + /// + CHAR16 PartitionName[36]; +} EFI_PARTITION_ENTRY; + +#pragma pack() +#endif + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h new file mode 100644 index 0000000..c911f39 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiInternalFormRepresentation.h @@ -0,0 +1,2135 @@ +/** @file + This file defines the encoding for the VFR (Visual Form Representation) language. + IFR is primarily consumed by the EFI presentation engine, and produced by EFI + internal application and drivers as well as all add-in card option-ROM drivers + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + These definitions are from UEFI 2.1 and 2.2. + +**/ + +#ifndef __UEFI_INTERNAL_FORMREPRESENTATION_H__ +#define __UEFI_INTERNAL_FORMREPRESENTATION_H__ + +#include + +/// +/// The following types are currently defined: +/// +typedef VOID* EFI_HII_HANDLE; +typedef CHAR16* EFI_STRING; +typedef UINT16 EFI_IMAGE_ID; +typedef UINT16 EFI_QUESTION_ID; +typedef UINT16 EFI_STRING_ID; +typedef UINT16 EFI_FORM_ID; +typedef UINT16 EFI_VARSTORE_ID; +typedef UINT16 EFI_ANIMATION_ID; + +typedef UINT16 EFI_DEFAULT_ID; + +typedef UINT32 EFI_HII_FONT_STYLE; + + + +#pragma pack(1) + +// +// Definitions for Package Lists and Package Headers +// Section 27.3.1 +// + +/// +/// The header found at the start of each package list. +/// +typedef struct { + EFI_GUID PackageListGuid; + UINT32 PackageLength; +} EFI_HII_PACKAGE_LIST_HEADER; + +/// +/// The header found at the start of each package. +/// +typedef struct { + UINT32 Length:24; + UINT32 Type:8; + // UINT8 Data[...]; +} EFI_HII_PACKAGE_HEADER; + +// +// Value of HII package type +// +#define EFI_HII_PACKAGE_TYPE_ALL 0x00 +#define EFI_HII_PACKAGE_TYPE_GUID 0x01 +#define EFI_HII_PACKAGE_FORMS 0x02 +#define EFI_HII_PACKAGE_STRINGS 0x04 +#define EFI_HII_PACKAGE_FONTS 0x05 +#define EFI_HII_PACKAGE_IMAGES 0x06 +#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07 +#define EFI_HII_PACKAGE_DEVICE_PATH 0x08 +#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x09 +#define EFI_HII_PACKAGE_ANIMATIONS 0x0A +#define EFI_HII_PACKAGE_END 0xDF +#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 +#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF + +// +// Definitions for Simplified Font Package +// + +/// +/// Contents of EFI_NARROW_GLYPH.Attributes. +///@{ +#define EFI_GLYPH_NON_SPACING 0x01 +#define EFI_GLYPH_WIDE 0x02 +#define EFI_GLYPH_HEIGHT 19 +#define EFI_GLYPH_WIDTH 8 +///@} + +/// +/// The EFI_NARROW_GLYPH has a preferred dimension (w x h) of 8 x 19 pixels. +/// +typedef struct { + /// + /// The Unicode representation of the glyph. The term weight is the + /// technical term for a character code. + /// + CHAR16 UnicodeWeight; + /// + /// The data element containing the glyph definitions. + /// + UINT8 Attributes; + /// + /// The column major glyph representation of the character. Bits + /// with values of one indicate that the corresponding pixel is to be + /// on when normally displayed; those with zero are off. + /// + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +/// +/// The EFI_WIDE_GLYPH has a preferred dimension (w x h) of 16 x 19 pixels, which is large enough +/// to accommodate logographic characters. +/// +typedef struct { + /// + /// The Unicode representation of the glyph. The term weight is the + /// technical term for a character code. + /// + CHAR16 UnicodeWeight; + /// + /// The data element containing the glyph definitions. + /// + UINT8 Attributes; + /// + /// The column major glyph representation of the character. Bits + /// with values of one indicate that the corresponding pixel is to be + /// on when normally displayed; those with zero are off. + /// + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; + /// + /// The column major glyph representation of the character. Bits + /// with values of one indicate that the corresponding pixel is to be + /// on when normally displayed; those with zero are off. + /// + UINT8 GlyphCol2[EFI_GLYPH_HEIGHT]; + /// + /// Ensures that sizeof (EFI_WIDE_GLYPH) is twice the + /// sizeof (EFI_NARROW_GLYPH). The contents of Pad must + /// be zero. + /// + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + +/// +/// A simplified font package consists of a font header +/// followed by a series of glyph structures. +/// +typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; + // EFI_NARROW_GLYPH NarrowGlyphs[]; + // EFI_WIDE_GLYPH WideGlyphs[]; +} EFI_HII_SIMPLE_FONT_PACKAGE_HDR; + +// +// Definitions for Font Package +// Section 27.3.3 +// + +// +// Value for font style +// +#define EFI_HII_FONT_STYLE_NORMAL 0x00000000 +#define EFI_HII_FONT_STYLE_BOLD 0x00000001 +#define EFI_HII_FONT_STYLE_ITALIC 0x00000002 +#define EFI_HII_FONT_STYLE_EMBOSS 0x00010000 +#define EFI_HII_FONT_STYLE_OUTLINE 0x00020000 +#define EFI_HII_FONT_STYLE_SHADOW 0x00040000 +#define EFI_HII_FONT_STYLE_UNDERLINE 0x00080000 +#define EFI_HII_FONT_STYLE_DBL_UNDER 0x00100000 + +typedef struct _EFI_HII_GLYPH_INFO { + UINT16 Width; + UINT16 Height; + INT16 OffsetX; + INT16 OffsetY; + INT16 AdvanceX; +} EFI_HII_GLYPH_INFO; + +/// +/// The fixed header consists of a standard record header, +/// then the character values in this section, the flags +/// (including the encoding method) and the offsets of the glyph +/// information, the glyph bitmaps and the character map. +/// +typedef struct _EFI_HII_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 GlyphBlockOffset; + EFI_HII_GLYPH_INFO Cell; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontFamily[1]; +} EFI_HII_FONT_PACKAGE_HDR; + +// +// Value of different glyph info block types +// +#define EFI_HII_GIBT_END 0x00 +#define EFI_HII_GIBT_GLYPH 0x10 +#define EFI_HII_GIBT_GLYPHS 0x11 +#define EFI_HII_GIBT_GLYPH_DEFAULT 0x12 +#define EFI_HII_GIBT_GLYPHS_DEFAULT 0x13 +#define EFI_HII_GIBT_GLYPH_VARIABILITY 0x14 +#define EFI_HII_GIBT_DUPLICATE 0x20 +#define EFI_HII_GIBT_SKIP2 0x21 +#define EFI_HII_GIBT_SKIP1 0x22 +#define EFI_HII_GIBT_DEFAULTS 0x23 +#define EFI_HII_GIBT_EXT1 0x30 +#define EFI_HII_GIBT_EXT2 0x31 +#define EFI_HII_GIBT_EXT4 0x32 + +typedef struct _EFI_HII_GLYPH_BLOCK { + UINT8 BlockType; +} EFI_HII_GLYPH_BLOCK; + +// +// Definition of different glyph info block types +// + +typedef struct _EFI_HII_GIBT_DEFAULTS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; +} EFI_HII_GIBT_DEFAULTS_BLOCK; + +typedef struct _EFI_HII_GIBT_DUPLICATE_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + CHAR16 CharValue; +} EFI_HII_GIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_GLYPH_GIBT_END_BLOCK { + EFI_HII_GLYPH_BLOCK Header; +} EFI_GLYPH_GIBT_END_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_GIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_GIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT4_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_GIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPH_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT16 Count; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPHS_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 Count; + UINT8 BitmapData[1]; +} EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_VARIABILITY_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT8 GlyphPackInBits; + UINT8 BitmapData [1]; +} EFI_HII_GIBT_VARIABILITY_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_GIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_GIBT_SKIP2_BLOCK; + +// +// Definitions for Device Path Package +// Section 27.3.4 +// + +/// +/// The device path package is used to carry a device path +/// associated with the package list. +/// +typedef struct _EFI_HII_DEVICE_PATH_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + // EFI_DEVICE_PATH_PROTOCOL DevicePath[]; +} EFI_HII_DEVICE_PATH_PACKAGE_HDR; + +// +// Definitions for GUID Package +// Section 27.3.5 +// + +/// +/// The GUID package is used to carry data where the format is defined by a GUID. +/// +typedef struct _EFI_HII_GUID_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + EFI_GUID Guid; + // Data per GUID definition may follow +} EFI_HII_GUID_PACKAGE_HDR; + +// +// Definitions for String Package +// Section 27.3.6 +// + +#define UEFI_CONFIG_LANG "x-UEFI" +#define UEFI_CONFIG_LANG_2 "x-i-UEFI" + +/// +/// The fixed header consists of a standard record header and then the string identifiers +/// contained in this section and the offsets of the string and language information. +/// +typedef struct _EFI_HII_STRING_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 StringInfoOffset; + CHAR16 LanguageWindow[16]; + EFI_STRING_ID LanguageName; + CHAR8 Language[1]; +} EFI_HII_STRING_PACKAGE_HDR; + +typedef struct { + UINT8 BlockType; +} EFI_HII_STRING_BLOCK; + +// +// Value of different string information block types +// +#define EFI_HII_SIBT_END 0x00 +#define EFI_HII_SIBT_STRING_SCSU 0x10 +#define EFI_HII_SIBT_STRING_SCSU_FONT 0x11 +#define EFI_HII_SIBT_STRINGS_SCSU 0x12 +#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13 +#define EFI_HII_SIBT_STRING_UCS2 0x14 +#define EFI_HII_SIBT_STRING_UCS2_FONT 0x15 +#define EFI_HII_SIBT_STRINGS_UCS2 0x16 +#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17 +#define EFI_HII_SIBT_DUPLICATE 0x20 +#define EFI_HII_SIBT_SKIP2 0x21 +#define EFI_HII_SIBT_SKIP1 0x22 +#define EFI_HII_SIBT_EXT1 0x30 +#define EFI_HII_SIBT_EXT2 0x31 +#define EFI_HII_SIBT_EXT4 0x32 +#define EFI_HII_SIBT_FONT 0x40 + +// +// Definition of different string information block types +// + +typedef struct _EFI_HII_SIBT_DUPLICATE_BLOCK { + EFI_HII_STRING_BLOCK Header; + EFI_STRING_ID StringId; +} EFI_HII_SIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_SIBT_END_BLOCK { + EFI_HII_STRING_BLOCK Header; +} EFI_HII_SIBT_END_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_SIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_SIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT4_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_SIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_SIBT_FONT_BLOCK { + EFI_HII_SIBT_EXT2_BLOCK Header; + UINT8 FontId; + UINT16 FontSize; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontName[1]; +} EFI_HII_SIBT_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_SIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_SIBT_SKIP2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK; + +// +// Definitions for Image Package +// Section 27.3.7 +// + +typedef struct _EFI_HII_IMAGE_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 ImageInfoOffset; + UINT32 PaletteInfoOffset; +} EFI_HII_IMAGE_PACKAGE_HDR; + +typedef struct _EFI_HII_IMAGE_BLOCK { + UINT8 BlockType; +} EFI_HII_IMAGE_BLOCK; + +// +// Value of different image information block types +// +#define EFI_HII_IIBT_END 0x00 +#define EFI_HII_IIBT_IMAGE_1BIT 0x10 +#define EFI_HII_IIBT_IMAGE_1BIT_TRANS 0x11 +#define EFI_HII_IIBT_IMAGE_4BIT 0x12 +#define EFI_HII_IIBT_IMAGE_4BIT_TRANS 0x13 +#define EFI_HII_IIBT_IMAGE_8BIT 0x14 +#define EFI_HII_IIBT_IMAGE_8BIT_TRANS 0x15 +#define EFI_HII_IIBT_IMAGE_24BIT 0x16 +#define EFI_HII_IIBT_IMAGE_24BIT_TRANS 0x17 +#define EFI_HII_IIBT_IMAGE_JPEG 0x18 +#define EFI_HII_IIBT_IMAGE_PNG 0x19 +#define EFI_HII_IIBT_DUPLICATE 0x20 +#define EFI_HII_IIBT_SKIP2 0x21 +#define EFI_HII_IIBT_SKIP1 0x22 +#define EFI_HII_IIBT_EXT1 0x30 +#define EFI_HII_IIBT_EXT2 0x31 +#define EFI_HII_IIBT_EXT4 0x32 + +// +// Definition of different image information block types +// + +typedef struct _EFI_HII_IIBT_END_BLOCK { + EFI_HII_IMAGE_BLOCK Header; +} EFI_HII_IIBT_END_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_IIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_IIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT4_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_IIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_1BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_RGB_PIXEL { + UINT8 b; + UINT8 g; + UINT8 r; +} EFI_HII_RGB_PIXEL; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BASE { + UINT16 Width; + UINT16 Height; + EFI_HII_RGB_PIXEL Bitmap[1]; +} EFI_HII_IIBT_IMAGE_24BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_4BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_8BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_PALETTE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_TRAN_BLOCK; + +typedef struct _EFI_HII_IIBT_DUPLICATE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_IMAGE_ID ImageId; +} EFI_HII_IIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_IIBT_JPEG_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT32 Size; + UINT8 Data[1]; +} EFI_HII_IIBT_JPEG_BLOCK; + +typedef struct _EFI_HII_IIBT_PNG_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT32 Size; + UINT8 Data[1]; +} EFI_HII_IIBT_PNG_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_IIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_IIBT_SKIP2_BLOCK; + +// +// Definitions for Palette Information +// + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO_HEADER { + UINT16 PaletteCount; +} EFI_HII_IMAGE_PALETTE_INFO_HEADER; + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO { + UINT16 PaletteSize; + EFI_HII_RGB_PIXEL PaletteValue[1]; +} EFI_HII_IMAGE_PALETTE_INFO; + +// +// Definitions for Forms Package +// Section 27.3.8 +// + +/// +/// The Form package is used to carry form-based encoding data. +/// +typedef struct _EFI_HII_FORM_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + // EFI_IFR_OP_HEADER OpCodeHeader; + // More op-codes follow +} EFI_HII_FORM_PACKAGE_HDR; + +typedef struct { + UINT8 Hour; + UINT8 Minute; + UINT8 Second; +} EFI_HII_TIME; + +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; +} EFI_HII_DATE; + +typedef struct { + EFI_QUESTION_ID QuestionId; + EFI_FORM_ID FormId; + EFI_GUID FormSetGuid; + EFI_STRING_ID DevicePath; +} EFI_HII_REF; + +typedef union { + UINT8 u8; + UINT16 u16; + UINT32 u32; + UINT64 u64; + BOOLEAN b; + EFI_HII_TIME time; + EFI_HII_DATE date; + EFI_STRING_ID string; ///< EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION + EFI_HII_REF ref; ///< EFI_IFR_TYPE_REF + // UINT8 buffer[]; ///< EFI_IFR_TYPE_BUFFER +} EFI_IFR_TYPE_VALUE; + +// +// IFR Opcodes +// +#define EFI_IFR_FORM_OP 0x01 +#define EFI_IFR_SUBTITLE_OP 0x02 +#define EFI_IFR_TEXT_OP 0x03 +#define EFI_IFR_IMAGE_OP 0x04 +#define EFI_IFR_ONE_OF_OP 0x05 +#define EFI_IFR_CHECKBOX_OP 0x06 +#define EFI_IFR_NUMERIC_OP 0x07 +#define EFI_IFR_PASSWORD_OP 0x08 +#define EFI_IFR_ONE_OF_OPTION_OP 0x09 +#define EFI_IFR_SUPPRESS_IF_OP 0x0A +#define EFI_IFR_LOCKED_OP 0x0B +#define EFI_IFR_ACTION_OP 0x0C +#define EFI_IFR_RESET_BUTTON_OP 0x0D +#define EFI_IFR_FORM_SET_OP 0x0E +#define EFI_IFR_REF_OP 0x0F +#define EFI_IFR_NO_SUBMIT_IF_OP 0x10 +#define EFI_IFR_INCONSISTENT_IF_OP 0x11 +#define EFI_IFR_EQ_ID_VAL_OP 0x12 +#define EFI_IFR_EQ_ID_ID_OP 0x13 +#define EFI_IFR_EQ_ID_VAL_LIST_OP 0x14 +#define EFI_IFR_AND_OP 0x15 +#define EFI_IFR_OR_OP 0x16 +#define EFI_IFR_NOT_OP 0x17 +#define EFI_IFR_RULE_OP 0x18 +#define EFI_IFR_GRAY_OUT_IF_OP 0x19 +#define EFI_IFR_DATE_OP 0x1A +#define EFI_IFR_TIME_OP 0x1B +#define EFI_IFR_STRING_OP 0x1C +#define EFI_IFR_REFRESH_OP 0x1D +#define EFI_IFR_DISABLE_IF_OP 0x1E +#define EFI_IFR_ANIMATION_OP 0x1F +#define EFI_IFR_TO_LOWER_OP 0x20 +#define EFI_IFR_TO_UPPER_OP 0x21 +#define EFI_IFR_MAP_OP 0x22 +#define EFI_IFR_ORDERED_LIST_OP 0x23 +#define EFI_IFR_VARSTORE_OP 0x24 +#define EFI_IFR_VARSTORE_NAME_VALUE_OP 0x25 +#define EFI_IFR_VARSTORE_EFI_OP 0x26 +#define EFI_IFR_VARSTORE_DEVICE_OP 0x27 +#define EFI_IFR_VERSION_OP 0x28 +#define EFI_IFR_END_OP 0x29 +#define EFI_IFR_MATCH_OP 0x2A +#define EFI_IFR_GET_OP 0x2B +#define EFI_IFR_SET_OP 0x2C +#define EFI_IFR_READ_OP 0x2D +#define EFI_IFR_WRITE_OP 0x2E +#define EFI_IFR_EQUAL_OP 0x2F +#define EFI_IFR_NOT_EQUAL_OP 0x30 +#define EFI_IFR_GREATER_THAN_OP 0x31 +#define EFI_IFR_GREATER_EQUAL_OP 0x32 +#define EFI_IFR_LESS_THAN_OP 0x33 +#define EFI_IFR_LESS_EQUAL_OP 0x34 +#define EFI_IFR_BITWISE_AND_OP 0x35 +#define EFI_IFR_BITWISE_OR_OP 0x36 +#define EFI_IFR_BITWISE_NOT_OP 0x37 +#define EFI_IFR_SHIFT_LEFT_OP 0x38 +#define EFI_IFR_SHIFT_RIGHT_OP 0x39 +#define EFI_IFR_ADD_OP 0x3A +#define EFI_IFR_SUBTRACT_OP 0x3B +#define EFI_IFR_MULTIPLY_OP 0x3C +#define EFI_IFR_DIVIDE_OP 0x3D +#define EFI_IFR_MODULO_OP 0x3E +#define EFI_IFR_RULE_REF_OP 0x3F +#define EFI_IFR_QUESTION_REF1_OP 0x40 +#define EFI_IFR_QUESTION_REF2_OP 0x41 +#define EFI_IFR_UINT8_OP 0x42 +#define EFI_IFR_UINT16_OP 0x43 +#define EFI_IFR_UINT32_OP 0x44 +#define EFI_IFR_UINT64_OP 0x45 +#define EFI_IFR_TRUE_OP 0x46 +#define EFI_IFR_FALSE_OP 0x47 +#define EFI_IFR_TO_UINT_OP 0x48 +#define EFI_IFR_TO_STRING_OP 0x49 +#define EFI_IFR_TO_BOOLEAN_OP 0x4A +#define EFI_IFR_MID_OP 0x4B +#define EFI_IFR_FIND_OP 0x4C +#define EFI_IFR_TOKEN_OP 0x4D +#define EFI_IFR_STRING_REF1_OP 0x4E +#define EFI_IFR_STRING_REF2_OP 0x4F +#define EFI_IFR_CONDITIONAL_OP 0x50 +#define EFI_IFR_QUESTION_REF3_OP 0x51 +#define EFI_IFR_ZERO_OP 0x52 +#define EFI_IFR_ONE_OP 0x53 +#define EFI_IFR_ONES_OP 0x54 +#define EFI_IFR_UNDEFINED_OP 0x55 +#define EFI_IFR_LENGTH_OP 0x56 +#define EFI_IFR_DUP_OP 0x57 +#define EFI_IFR_THIS_OP 0x58 +#define EFI_IFR_SPAN_OP 0x59 +#define EFI_IFR_VALUE_OP 0x5A +#define EFI_IFR_DEFAULT_OP 0x5B +#define EFI_IFR_DEFAULTSTORE_OP 0x5C +#define EFI_IFR_FORM_MAP_OP 0x5D +#define EFI_IFR_CATENATE_OP 0x5E +#define EFI_IFR_GUID_OP 0x5F +#define EFI_IFR_SECURITY_OP 0x60 +#define EFI_IFR_MODAL_TAG_OP 0x61 +#define EFI_IFR_REFRESH_ID_OP 0x62 +#define EFI_IFR_WARNING_IF_OP 0x63 +#define EFI_IFR_MATCH2_OP 0x64 + +// +// Definitions of IFR Standard Headers +// Section 27.3.8.2 +// + +typedef struct _EFI_IFR_OP_HEADER { + UINT8 OpCode; + UINT8 Length:7; + UINT8 Scope:1; +} EFI_IFR_OP_HEADER; + +typedef struct _EFI_IFR_STATEMENT_HEADER { + EFI_STRING_ID Prompt; + EFI_STRING_ID Help; +} EFI_IFR_STATEMENT_HEADER; + +typedef struct _EFI_IFR_QUESTION_HEADER { + EFI_IFR_STATEMENT_HEADER Header; + EFI_QUESTION_ID QuestionId; + EFI_VARSTORE_ID VarStoreId; + union { + EFI_STRING_ID VarName; + UINT16 VarOffset; + } VarStoreInfo; + UINT8 Flags; +} EFI_IFR_QUESTION_HEADER; + +// +// Flag values of EFI_IFR_QUESTION_HEADER +// +#define EFI_IFR_FLAG_READ_ONLY 0x01 +#define EFI_IFR_FLAG_CALLBACK 0x04 +#define EFI_IFR_FLAG_RESET_REQUIRED 0x10 +#define EFI_IFR_FLAG_RECONNECT_REQUIRED 0x40 +#define EFI_IFR_FLAG_OPTIONS_ONLY 0x80 + +// +// Definition for Opcode Reference +// Section 27.3.8.3 +// +typedef struct _EFI_IFR_DEFAULTSTORE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DefaultName; + UINT16 DefaultId; +} EFI_IFR_DEFAULTSTORE; + +// +// Default Identifier of default store +// +#define EFI_HII_DEFAULT_CLASS_STANDARD 0x0000 +#define EFI_HII_DEFAULT_CLASS_MANUFACTURING 0x0001 +#define EFI_HII_DEFAULT_CLASS_SAFE 0x0002 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_END 0x7fff +#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000 +#define EFI_HII_DEFAULT_CLASS_HARDWARE_END 0xbfff +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000 +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END 0xffff + +typedef struct _EFI_IFR_VARSTORE { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_VARSTORE_ID VarStoreId; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE; + +typedef struct _EFI_IFR_VARSTORE_EFI { + EFI_IFR_OP_HEADER Header; + EFI_VARSTORE_ID VarStoreId; + EFI_GUID Guid; + UINT32 Attributes; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE_EFI; + +typedef struct _EFI_IFR_VARSTORE_NAME_VALUE { + EFI_IFR_OP_HEADER Header; + EFI_VARSTORE_ID VarStoreId; + EFI_GUID Guid; +} EFI_IFR_VARSTORE_NAME_VALUE; + +typedef struct _EFI_IFR_FORM_SET { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID Help; + UINT8 Flags; + // EFI_GUID ClassGuid[]; +} EFI_IFR_FORM_SET; + +typedef struct _EFI_IFR_END { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END; + +typedef struct _EFI_IFR_FORM { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + EFI_STRING_ID FormTitle; +} EFI_IFR_FORM; + +typedef struct _EFI_IFR_IMAGE { + EFI_IFR_OP_HEADER Header; + EFI_IMAGE_ID Id; +} EFI_IFR_IMAGE; + +typedef struct _EFI_IFR_MODAL_TAG { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODAL_TAG; + +typedef struct _EFI_IFR_LOCKED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LOCKED; + +typedef struct _EFI_IFR_RULE { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE; + +typedef struct _EFI_IFR_DEFAULT { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_DEFAULT; + +typedef struct _EFI_IFR_DEFAULT_2 { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; +} EFI_IFR_DEFAULT_2; + +typedef struct _EFI_IFR_VALUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VALUE; + +typedef struct _EFI_IFR_SUBTITLE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + UINT8 Flags; +} EFI_IFR_SUBTITLE; + +#define EFI_IFR_FLAGS_HORIZONTAL 0x01 + +typedef struct _EFI_IFR_CHECKBOX { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_CHECKBOX; + +#define EFI_IFR_CHECKBOX_DEFAULT 0x01 +#define EFI_IFR_CHECKBOX_DEFAULT_MFG 0x02 + +typedef struct _EFI_IFR_TEXT { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_STRING_ID TextTwo; +} EFI_IFR_TEXT; + +typedef struct _EFI_IFR_REF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; +} EFI_IFR_REF; + +typedef struct _EFI_IFR_REF2 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_REF2; + +typedef struct _EFI_IFR_REF3 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; +} EFI_IFR_REF3; + +typedef struct _EFI_IFR_REF4 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; + EFI_STRING_ID DevicePath; +} EFI_IFR_REF4; + +typedef struct _EFI_IFR_REF5 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_REF5; + +typedef struct _EFI_IFR_RESET_BUTTON { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_DEFAULT_ID DefaultId; +} EFI_IFR_RESET_BUTTON; + +typedef struct _EFI_IFR_ACTION { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_STRING_ID QuestionConfig; +} EFI_IFR_ACTION; + +typedef struct _EFI_IFR_ACTION_1 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_ACTION_1; + +typedef struct _EFI_IFR_DATE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_DATE; + +// +// Flags that describe the behavior of the question. +// +#define EFI_QF_DATE_YEAR_SUPPRESS 0x01 +#define EFI_QF_DATE_MONTH_SUPPRESS 0x02 +#define EFI_QF_DATE_DAY_SUPPRESS 0x04 + +#define EFI_QF_DATE_STORAGE 0x30 +#define QF_DATE_STORAGE_NORMAL 0x00 +#define QF_DATE_STORAGE_TIME 0x10 +#define QF_DATE_STORAGE_WAKEUP 0x20 + +typedef union { + struct { + UINT8 MinValue; + UINT8 MaxValue; + UINT8 Step; + } u8; + struct { + UINT16 MinValue; + UINT16 MaxValue; + UINT16 Step; + } u16; + struct { + UINT32 MinValue; + UINT32 MaxValue; + UINT32 Step; + } u32; + struct { + UINT64 MinValue; + UINT64 MaxValue; + UINT64 Step; + } u64; +} MINMAXSTEP_DATA; + +typedef struct _EFI_IFR_NUMERIC { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_NUMERIC; + +// +// Flags related to the numeric question +// +#define EFI_IFR_NUMERIC_SIZE 0x03 +#define EFI_IFR_NUMERIC_SIZE_1 0x00 +#define EFI_IFR_NUMERIC_SIZE_2 0x01 +#define EFI_IFR_NUMERIC_SIZE_4 0x02 +#define EFI_IFR_NUMERIC_SIZE_8 0x03 + +#define EFI_IFR_DISPLAY 0x30 +#define EFI_IFR_DISPLAY_INT_DEC 0x00 +#define EFI_IFR_DISPLAY_UINT_DEC 0x10 +#define EFI_IFR_DISPLAY_UINT_HEX 0x20 + +typedef struct _EFI_IFR_ONE_OF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_ONE_OF; + +typedef struct _EFI_IFR_STRING { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MinSize; + UINT8 MaxSize; + UINT8 Flags; +} EFI_IFR_STRING; + +#define EFI_IFR_STRING_MULTI_LINE 0x01 + +typedef struct _EFI_IFR_PASSWORD { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT16 MinSize; + UINT16 MaxSize; +} EFI_IFR_PASSWORD; + +typedef struct _EFI_IFR_ORDERED_LIST { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MaxContainers; + UINT8 Flags; +} EFI_IFR_ORDERED_LIST; + +#define EFI_IFR_UNIQUE_SET 0x01 +#define EFI_IFR_NO_EMPTY_SET 0x02 + +typedef struct _EFI_IFR_TIME { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_TIME; + +// +// A bit-mask that determines which unique settings are active for this opcode. +// +#define QF_TIME_HOUR_SUPPRESS 0x01 +#define QF_TIME_MINUTE_SUPPRESS 0x02 +#define QF_TIME_SECOND_SUPPRESS 0x04 + +#define QF_TIME_STORAGE 0x30 +#define QF_TIME_STORAGE_NORMAL 0x00 +#define QF_TIME_STORAGE_TIME 0x10 +#define QF_TIME_STORAGE_WAKEUP 0x20 + +typedef struct _EFI_IFR_DISABLE_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DISABLE_IF; + +typedef struct _EFI_IFR_SUPPRESS_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUPPRESS_IF; + +typedef struct _EFI_IFR_GRAY_OUT_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GRAY_OUT_IF; + +typedef struct _EFI_IFR_INCONSISTENT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_INCONSISTENT_IF; + +typedef struct _EFI_IFR_NO_SUBMIT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_NO_SUBMIT_IF; + +typedef struct _EFI_IFR_WARNING_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Warning; + UINT8 TimeOut; +} EFI_IFR_WARNING_IF; + +typedef struct _EFI_IFR_REFRESH { + EFI_IFR_OP_HEADER Header; + UINT8 RefreshInterval; +} EFI_IFR_REFRESH; + +typedef struct _EFI_IFR_VARSTORE_DEVICE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_VARSTORE_DEVICE; + +typedef struct _EFI_IFR_ONE_OF_OPTION { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Option; + UINT8 Flags; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_ONE_OF_OPTION; + +// +// Types of the option's value. +// +#define EFI_IFR_TYPE_NUM_SIZE_8 0x00 +#define EFI_IFR_TYPE_NUM_SIZE_16 0x01 +#define EFI_IFR_TYPE_NUM_SIZE_32 0x02 +#define EFI_IFR_TYPE_NUM_SIZE_64 0x03 +#define EFI_IFR_TYPE_BOOLEAN 0x04 +#define EFI_IFR_TYPE_TIME 0x05 +#define EFI_IFR_TYPE_DATE 0x06 +#define EFI_IFR_TYPE_STRING 0x07 +#define EFI_IFR_TYPE_OTHER 0x08 +#define EFI_IFR_TYPE_UNDEFINED 0x09 +#define EFI_IFR_TYPE_ACTION 0x0A +#define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C + +#define EFI_IFR_OPTION_DEFAULT 0x10 +#define EFI_IFR_OPTION_DEFAULT_MFG 0x20 + +typedef struct _EFI_IFR_GUID { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + //Optional Data Follows +} EFI_IFR_GUID; + +typedef struct _EFI_IFR_REFRESH_ID { + EFI_IFR_OP_HEADER Header; + EFI_GUID RefreshEventGroupId; +} EFI_IFR_REFRESH_ID; + +typedef struct _EFI_IFR_DUP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DUP; + +typedef struct _EFI_IFR_EQ_ID_ID { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId1; + EFI_QUESTION_ID QuestionId2; +} EFI_IFR_EQ_ID_ID; + +typedef struct _EFI_IFR_EQ_ID_VAL { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 Value; +} EFI_IFR_EQ_ID_VAL; + +typedef struct _EFI_IFR_EQ_ID_VAL_LIST { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 ListLength; + UINT16 ValueList[1]; +} EFI_IFR_EQ_ID_VAL_LIST; + +typedef struct _EFI_IFR_UINT8 { + EFI_IFR_OP_HEADER Header; + UINT8 Value; +} EFI_IFR_UINT8; + +typedef struct _EFI_IFR_UINT16 { + EFI_IFR_OP_HEADER Header; + UINT16 Value; +} EFI_IFR_UINT16; + +typedef struct _EFI_IFR_UINT32 { + EFI_IFR_OP_HEADER Header; + UINT32 Value; +} EFI_IFR_UINT32; + +typedef struct _EFI_IFR_UINT64 { + EFI_IFR_OP_HEADER Header; + UINT64 Value; +} EFI_IFR_UINT64; + +typedef struct _EFI_IFR_QUESTION_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_QUESTION_REF1; + +typedef struct _EFI_IFR_QUESTION_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF2; + +typedef struct _EFI_IFR_QUESTION_REF3 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF3; + +typedef struct _EFI_IFR_QUESTION_REF3_2 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_QUESTION_REF3_2; + +typedef struct _EFI_IFR_QUESTION_REF3_3 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; + EFI_GUID Guid; +} EFI_IFR_QUESTION_REF3_3; + +typedef struct _EFI_IFR_RULE_REF { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE_REF; + +typedef struct _EFI_IFR_STRING_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID StringId; +} EFI_IFR_STRING_REF1; + +typedef struct _EFI_IFR_STRING_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_STRING_REF2; + +typedef struct _EFI_IFR_THIS { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_THIS; + +typedef struct _EFI_IFR_TRUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TRUE; + +typedef struct _EFI_IFR_FALSE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_FALSE; + +typedef struct _EFI_IFR_ONE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONE; + +typedef struct _EFI_IFR_ONES { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONES; + +typedef struct _EFI_IFR_ZERO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ZERO; + +typedef struct _EFI_IFR_UNDEFINED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_UNDEFINED; + +typedef struct _EFI_IFR_VERSION { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VERSION; + +typedef struct _EFI_IFR_LENGTH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LENGTH; + +typedef struct _EFI_IFR_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT; + +typedef struct _EFI_IFR_BITWISE_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_NOT; + +typedef struct _EFI_IFR_TO_BOOLEAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_BOOLEAN; + +/// +/// For EFI_IFR_TO_STRING, when converting from +/// unsigned integers, these flags control the format: +/// 0 = unsigned decimal. +/// 1 = signed decimal. +/// 2 = hexadecimal (lower-case alpha). +/// 3 = hexadecimal (upper-case alpha). +///@{ +#define EFI_IFR_STRING_UNSIGNED_DEC 0 +#define EFI_IFR_STRING_SIGNED_DEC 1 +#define EFI_IFR_STRING_LOWERCASE_HEX 2 +#define EFI_IFR_STRING_UPPERCASE_HEX 3 +///@} + +/// +/// When converting from a buffer, these flags control the format: +/// 0 = ASCII. +/// 8 = Unicode. +///@{ +#define EFI_IFR_STRING_ASCII 0 +#define EFI_IFR_STRING_UNICODE 8 +///@} + +typedef struct _EFI_IFR_TO_STRING { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_TO_STRING; + +typedef struct _EFI_IFR_TO_UINT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UINT; + +typedef struct _EFI_IFR_TO_UPPER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UPPER; + +typedef struct _EFI_IFR_TO_LOWER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_LOWER; + +typedef struct _EFI_IFR_ADD { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ADD; + +typedef struct _EFI_IFR_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_AND; + +typedef struct _EFI_IFR_BITWISE_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_AND; + +typedef struct _EFI_IFR_BITWISE_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_OR; + +typedef struct _EFI_IFR_CATENATE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CATENATE; + +typedef struct _EFI_IFR_DIVIDE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DIVIDE; + +typedef struct _EFI_IFR_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_EQUAL; + +typedef struct _EFI_IFR_GREATER_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_EQUAL; + +typedef struct _EFI_IFR_GREATER_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_THAN; + +typedef struct _EFI_IFR_LESS_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_EQUAL; + +typedef struct _EFI_IFR_LESS_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_THAN; + +typedef struct _EFI_IFR_MATCH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MATCH; + +typedef struct _EFI_IFR_MATCH2 { + EFI_IFR_OP_HEADER Header; + EFI_GUID SyntaxType; +} EFI_IFR_MATCH2; + +typedef struct _EFI_IFR_MULTIPLY { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MULTIPLY; + +typedef struct _EFI_IFR_MODULO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODULO; + +typedef struct _EFI_IFR_NOT_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT_EQUAL; + +typedef struct _EFI_IFR_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_OR; + +typedef struct _EFI_IFR_SHIFT_LEFT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_LEFT; + +typedef struct _EFI_IFR_SHIFT_RIGHT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_RIGHT; + +typedef struct _EFI_IFR_SUBTRACT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUBTRACT; + +typedef struct _EFI_IFR_CONDITIONAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CONDITIONAL; + +// +// Flags governing the matching criteria of EFI_IFR_FIND +// +#define EFI_IFR_FF_CASE_SENSITIVE 0x00 +#define EFI_IFR_FF_CASE_INSENSITIVE 0x01 + +typedef struct _EFI_IFR_FIND { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_FIND; + +typedef struct _EFI_IFR_MID { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MID; + +typedef struct _EFI_IFR_TOKEN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TOKEN; + +// +// Flags specifying whether to find the first matching string +// or the first non-matching string. +// +#define EFI_IFR_FLAGS_FIRST_MATCHING 0x00 +#define EFI_IFR_FLAGS_FIRST_NON_MATCHING 0x01 + +typedef struct _EFI_IFR_SPAN { + EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_SPAN; + +typedef struct _EFI_IFR_SECURITY { + /// + /// Standard opcode header, where Header.Op = EFI_IFR_SECURITY_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Security permission level. + /// + EFI_GUID Permissions; +} EFI_IFR_SECURITY; + +typedef struct _EFI_IFR_FORM_MAP_METHOD { + /// + /// The string identifier which provides the human-readable name of + /// the configuration method for this standards map form. + /// + EFI_STRING_ID MethodTitle; + /// + /// Identifier which uniquely specifies the configuration methods + /// associated with this standards map form. + /// + EFI_GUID MethodIdentifier; +} EFI_IFR_FORM_MAP_METHOD; + +typedef struct _EFI_IFR_FORM_MAP { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_FORM_MAP_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// The unique identifier for this particular form. + /// + EFI_FORM_ID FormId; + /// + /// One or more configuration method's name and unique identifier. + /// + // EFI_IFR_FORM_MAP_METHOD Methods[]; +} EFI_IFR_FORM_MAP; + +typedef struct _EFI_IFR_SET { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_SET_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Specifies the identifier of a previously declared variable store to + /// use when storing the question's value. + /// + EFI_VARSTORE_ID VarStoreId; + union { + /// + /// A 16-bit Buffer Storage offset. + /// + EFI_STRING_ID VarName; + /// + /// A Name Value or EFI Variable name (VarName). + /// + UINT16 VarOffset; + } VarStoreInfo; + /// + /// Specifies the type used for storage. + /// + UINT8 VarStoreType; +} EFI_IFR_SET; + +typedef struct _EFI_IFR_GET { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_GET_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Specifies the identifier of a previously declared variable store to + /// use when retrieving the value. + /// + EFI_VARSTORE_ID VarStoreId; + union { + /// + /// A 16-bit Buffer Storage offset. + /// + EFI_STRING_ID VarName; + /// + /// A Name Value or EFI Variable name (VarName). + /// + UINT16 VarOffset; + } VarStoreInfo; + /// + /// Specifies the type used for storage. + /// + UINT8 VarStoreType; +} EFI_IFR_GET; + +typedef struct _EFI_IFR_READ { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_READ; + +typedef struct _EFI_IFR_WRITE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_WRITE; + +typedef struct _EFI_IFR_MAP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MAP; +// +// Definitions for Keyboard Package +// Releated definitions are in Section of EFI_HII_DATABASE_PROTOCOL +// + +/// +/// Each enumeration values maps a physical key on a keyboard. +/// +typedef enum { + EfiKeyLCtrl, + EfiKeyA0, + EfiKeyLAlt, + EfiKeySpaceBar, + EfiKeyA2, + EfiKeyA3, + EfiKeyA4, + EfiKeyRCtrl, + EfiKeyLeftArrow, + EfiKeyDownArrow, + EfiKeyRightArrow, + EfiKeyZero, + EfiKeyPeriod, + EfiKeyEnter, + EfiKeyLShift, + EfiKeyB0, + EfiKeyB1, + EfiKeyB2, + EfiKeyB3, + EfiKeyB4, + EfiKeyB5, + EfiKeyB6, + EfiKeyB7, + EfiKeyB8, + EfiKeyB9, + EfiKeyB10, + EfiKeyRShift, + EfiKeyUpArrow, + EfiKeyOne, + EfiKeyTwo, + EfiKeyThree, + EfiKeyCapsLock, + EfiKeyC1, + EfiKeyC2, + EfiKeyC3, + EfiKeyC4, + EfiKeyC5, + EfiKeyC6, + EfiKeyC7, + EfiKeyC8, + EfiKeyC9, + EfiKeyC10, + EfiKeyC11, + EfiKeyC12, + EfiKeyFour, + EfiKeyFive, + EfiKeySix, + EfiKeyPlus, + EfiKeyTab, + EfiKeyD1, + EfiKeyD2, + EfiKeyD3, + EfiKeyD4, + EfiKeyD5, + EfiKeyD6, + EfiKeyD7, + EfiKeyD8, + EfiKeyD9, + EfiKeyD10, + EfiKeyD11, + EfiKeyD12, + EfiKeyD13, + EfiKeyDel, + EfiKeyEnd, + EfiKeyPgDn, + EfiKeySeven, + EfiKeyEight, + EfiKeyNine, + EfiKeyE0, + EfiKeyE1, + EfiKeyE2, + EfiKeyE3, + EfiKeyE4, + EfiKeyE5, + EfiKeyE6, + EfiKeyE7, + EfiKeyE8, + EfiKeyE9, + EfiKeyE10, + EfiKeyE11, + EfiKeyE12, + EfiKeyBackSpace, + EfiKeyIns, + EfiKeyHome, + EfiKeyPgUp, + EfiKeyNLck, + EfiKeySlash, + EfiKeyAsterisk, + EfiKeyMinus, + EfiKeyEsc, + EfiKeyF1, + EfiKeyF2, + EfiKeyF3, + EfiKeyF4, + EfiKeyF5, + EfiKeyF6, + EfiKeyF7, + EfiKeyF8, + EfiKeyF9, + EfiKeyF10, + EfiKeyF11, + EfiKeyF12, + EfiKeyPrint, + EfiKeySLck, + EfiKeyPause +} EFI_KEY; + +typedef struct { + /// + /// Used to describe a physical key on a keyboard. + /// + EFI_KEY Key; + /// + /// Unicode character code for the Key. + /// + CHAR16 Unicode; + /// + /// Unicode character code for the key with the shift key being held down. + /// + CHAR16 ShiftedUnicode; + /// + /// Unicode character code for the key with the Alt-GR being held down. + /// + CHAR16 AltGrUnicode; + /// + /// Unicode character code for the key with the Alt-GR and shift keys being held down. + /// + CHAR16 ShiftedAltGrUnicode; + /// + /// Modifier keys are defined to allow for special functionality that is not necessarily + /// accomplished by a printable character. Many of these modifier keys are flags to toggle + /// certain state bits on and off inside of a keyboard driver. + /// + UINT16 Modifier; + UINT16 AffectedAttribute; +} EFI_KEY_DESCRIPTOR; + +/// +/// A key which is affected by all the standard shift modifiers. +/// Most keys would be expected to have this bit active. +/// +#define EFI_AFFECTED_BY_STANDARD_SHIFT 0x0001 + +/// +/// This key is affected by the caps lock so that if a keyboard driver +/// would need to disambiguate between a key which had a "1" defined +/// versus an "a" character. Having this bit turned on would tell +/// the keyboard driver to use the appropriate shifted state or not. +/// +#define EFI_AFFECTED_BY_CAPS_LOCK 0x0002 + +/// +/// Similar to the case of CAPS lock, if this bit is active, the key +/// is affected by the num lock being turned on. +/// +#define EFI_AFFECTED_BY_NUM_LOCK 0x0004 + +typedef struct { + UINT16 LayoutLength; + EFI_GUID Guid; + UINT32 LayoutDescriptorStringOffset; + UINT8 DescriptorCount; + // EFI_KEY_DESCRIPTOR Descriptors[]; +} EFI_HII_KEYBOARD_LAYOUT; + +typedef struct { + EFI_HII_PACKAGE_HEADER Header; + UINT16 LayoutCount; + // EFI_HII_KEYBOARD_LAYOUT Layout[]; +} EFI_HII_KEYBOARD_PACKAGE_HDR; + +// +// Modifier values +// +#define EFI_NULL_MODIFIER 0x0000 +#define EFI_LEFT_CONTROL_MODIFIER 0x0001 +#define EFI_RIGHT_CONTROL_MODIFIER 0x0002 +#define EFI_LEFT_ALT_MODIFIER 0x0003 +#define EFI_RIGHT_ALT_MODIFIER 0x0004 +#define EFI_ALT_GR_MODIFIER 0x0005 +#define EFI_INSERT_MODIFIER 0x0006 +#define EFI_DELETE_MODIFIER 0x0007 +#define EFI_PAGE_DOWN_MODIFIER 0x0008 +#define EFI_PAGE_UP_MODIFIER 0x0009 +#define EFI_HOME_MODIFIER 0x000A +#define EFI_END_MODIFIER 0x000B +#define EFI_LEFT_SHIFT_MODIFIER 0x000C +#define EFI_RIGHT_SHIFT_MODIFIER 0x000D +#define EFI_CAPS_LOCK_MODIFIER 0x000E +#define EFI_NUM_LOCK_MODIFIER 0x000F +#define EFI_LEFT_ARROW_MODIFIER 0x0010 +#define EFI_RIGHT_ARROW_MODIFIER 0x0011 +#define EFI_DOWN_ARROW_MODIFIER 0x0012 +#define EFI_UP_ARROW_MODIFIER 0x0013 +#define EFI_NS_KEY_MODIFIER 0x0014 +#define EFI_NS_KEY_DEPENDENCY_MODIFIER 0x0015 +#define EFI_FUNCTION_KEY_ONE_MODIFIER 0x0016 +#define EFI_FUNCTION_KEY_TWO_MODIFIER 0x0017 +#define EFI_FUNCTION_KEY_THREE_MODIFIER 0x0018 +#define EFI_FUNCTION_KEY_FOUR_MODIFIER 0x0019 +#define EFI_FUNCTION_KEY_FIVE_MODIFIER 0x001A +#define EFI_FUNCTION_KEY_SIX_MODIFIER 0x001B +#define EFI_FUNCTION_KEY_SEVEN_MODIFIER 0x001C +#define EFI_FUNCTION_KEY_EIGHT_MODIFIER 0x001D +#define EFI_FUNCTION_KEY_NINE_MODIFIER 0x001E +#define EFI_FUNCTION_KEY_TEN_MODIFIER 0x001F +#define EFI_FUNCTION_KEY_ELEVEN_MODIFIER 0x0020 +#define EFI_FUNCTION_KEY_TWELVE_MODIFIER 0x0021 + +// +// Keys that have multiple control functions based on modifier +// settings are handled in the keyboard driver implementation. +// For instance, PRINT_KEY might have a modifier held down and +// is still a nonprinting character, but might have an alternate +// control function like SYSREQUEST +// +#define EFI_PRINT_MODIFIER 0x0022 +#define EFI_SYS_REQUEST_MODIFIER 0x0023 +#define EFI_SCROLL_LOCK_MODIFIER 0x0024 +#define EFI_PAUSE_MODIFIER 0x0025 +#define EFI_BREAK_MODIFIER 0x0026 + +#define EFI_LEFT_LOGO_MODIFIER 0x0027 +#define EFI_RIGHT_LOGO_MODIFIER 0x0028 +#define EFI_MENU_MODIFIER 0x0029 + +/// +/// Animation IFR opcode +/// +typedef struct _EFI_IFR_ANIMATION { + /// + /// Standard opcode header, where Header.OpCode is + /// EFI_IFR_ANIMATION_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Animation identifier in the HII database. + /// + EFI_ANIMATION_ID Id; +} EFI_IFR_ANIMATION; + +/// +/// HII animation package header. +/// +typedef struct _EFI_HII_ANIMATION_PACKAGE_HDR { + /// + /// Standard package header, where Header.Type = EFI_HII_PACKAGE_ANIMATIONS. + /// + EFI_HII_PACKAGE_HEADER Header; + /// + /// Offset, relative to this header, of the animation information. If + /// this is zero, then there are no animation sequences in the package. + /// + UINT32 AnimationInfoOffset; +} EFI_HII_ANIMATION_PACKAGE_HDR; + +/// +/// Animation information is encoded as a series of blocks, +/// with each block prefixed by a single byte header EFI_HII_ANIMATION_BLOCK. +/// +typedef struct _EFI_HII_ANIMATION_BLOCK { + UINT8 BlockType; + //UINT8 BlockBody[]; +} EFI_HII_ANIMATION_BLOCK; + +/// +/// Animation block types. +/// +#define EFI_HII_AIBT_END 0x00 +#define EFI_HII_AIBT_OVERLAY_IMAGES 0x10 +#define EFI_HII_AIBT_CLEAR_IMAGES 0x11 +#define EFI_HII_AIBT_RESTORE_SCRN 0x12 +#define EFI_HII_AIBT_OVERLAY_IMAGES_LOOP 0x18 +#define EFI_HII_AIBT_CLEAR_IMAGES_LOOP 0x19 +#define EFI_HII_AIBT_RESTORE_SCRN_LOOP 0x1A +#define EFI_HII_AIBT_DUPLICATE 0x20 +#define EFI_HII_AIBT_SKIP2 0x21 +#define EFI_HII_AIBT_SKIP1 0x22 +#define EFI_HII_AIBT_EXT1 0x30 +#define EFI_HII_AIBT_EXT2 0x31 +#define EFI_HII_AIBT_EXT4 0x32 + +/// +/// Extended block headers used for variable sized animation records +/// which need an explicit length. +/// + +typedef struct _EFI_HII_AIBT_EXT1_BLOCK { + /// + /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT1. + /// + EFI_HII_ANIMATION_BLOCK Header; + /// + /// The block type. + /// + UINT8 BlockType2; + /// + /// Size of the animation block, in bytes, including the animation block header. + /// + UINT8 Length; +} EFI_HII_AIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_AIBT_EXT2_BLOCK { + /// + /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT2. + /// + EFI_HII_ANIMATION_BLOCK Header; + /// + /// The block type + /// + UINT8 BlockType2; + /// + /// Size of the animation block, in bytes, including the animation block header. + /// + UINT16 Length; +} EFI_HII_AIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_AIBT_EXT4_BLOCK { + /// + /// Standard animation header, where Header.BlockType = EFI_HII_AIBT_EXT4. + /// + EFI_HII_ANIMATION_BLOCK Header; + /// + /// The block type + /// + UINT8 BlockType2; + /// + /// Size of the animation block, in bytes, including the animation block header. + /// + UINT32 Length; +} EFI_HII_AIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_ANIMATION_CELL { + /// + /// The X offset from the upper left hand corner of the logical + /// window to position the indexed image. + /// + UINT16 OffsetX; + /// + /// The Y offset from the upper left hand corner of the logical + /// window to position the indexed image. + /// + UINT16 OffsetY; + /// + /// The image to display at the specified offset from the upper left + /// hand corner of the logical window. + /// + EFI_IMAGE_ID ImageId; + /// + /// The number of milliseconds to delay after displaying the indexed + /// image and before continuing on to the next linked image. If value + /// is zero, no delay. + /// + UINT16 Delay; +} EFI_HII_ANIMATION_CELL; + +/// +/// An animation block to describe an animation sequence that does not cycle, and +/// where one image is simply displayed over the previous image. +/// +typedef struct _EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK { + /// + /// This is image that is to be reference by the image protocols, if the + /// animation function is not supported or disabled. This image can + /// be one particular image from the animation sequence (if any one + /// of the animation frames has a complete image) or an alternate + /// image that can be displayed alone. If the value is zero, no image + /// is displayed. + /// + EFI_IMAGE_ID DftImageId; + /// + /// The overall width of the set of images (logical window width). + /// + UINT16 Width; + /// + /// The overall height of the set of images (logical window height). + /// + UINT16 Height; + /// + /// The number of EFI_HII_ANIMATION_CELL contained in the + /// animation sequence. + /// + UINT16 CellCount; + /// + /// An array of CellCount animation cells. + /// + EFI_HII_ANIMATION_CELL AnimationCell[1]; +} EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK; + +/// +/// An animation block to describe an animation sequence that does not cycle, +/// and where the logical window is cleared to the specified color before +/// the next image is displayed. +/// +typedef struct _EFI_HII_AIBT_CLEAR_IMAGES_BLOCK { + /// + /// This is image that is to be reference by the image protocols, if the + /// animation function is not supported or disabled. This image can + /// be one particular image from the animation sequence (if any one + /// of the animation frames has a complete image) or an alternate + /// image that can be displayed alone. If the value is zero, no image + /// is displayed. + /// + EFI_IMAGE_ID DftImageId; + /// + /// The overall width of the set of images (logical window width). + /// + UINT16 Width; + /// + /// The overall height of the set of images (logical window height). + /// + UINT16 Height; + /// + /// The number of EFI_HII_ANIMATION_CELL contained in the + /// animation sequence. + /// + UINT16 CellCount; + /// + /// The color to clear the logical window to before displaying the + /// indexed image. + /// + EFI_HII_RGB_PIXEL BackgndColor; + /// + /// An array of CellCount animation cells. + /// + EFI_HII_ANIMATION_CELL AnimationCell[1]; +} EFI_HII_AIBT_CLEAR_IMAGES_BLOCK; + +/// +/// An animation block to describe an animation sequence that does not cycle, +/// and where the screen is restored to the original state before the next +/// image is displayed. +/// +typedef struct _EFI_HII_AIBT_RESTORE_SCRN_BLOCK { + /// + /// This is image that is to be reference by the image protocols, if the + /// animation function is not supported or disabled. This image can + /// be one particular image from the animation sequence (if any one + /// of the animation frames has a complete image) or an alternate + /// image that can be displayed alone. If the value is zero, no image + /// is displayed. + /// + EFI_IMAGE_ID DftImageId; + /// + /// The overall width of the set of images (logical window width). + /// + UINT16 Width; + /// + /// The overall height of the set of images (logical window height). + /// + UINT16 Height; + /// + /// The number of EFI_HII_ANIMATION_CELL contained in the + /// animation sequence. + /// + UINT16 CellCount; + /// + /// An array of CellCount animation cells. + /// + EFI_HII_ANIMATION_CELL AnimationCell[1]; +} EFI_HII_AIBT_RESTORE_SCRN_BLOCK; + +/// +/// An animation block to describe an animation sequence that continuously cycles, +/// and where one image is simply displayed over the previous image. +/// +typedef EFI_HII_AIBT_OVERLAY_IMAGES_BLOCK EFI_HII_AIBT_OVERLAY_IMAGES_LOOP_BLOCK; + +/// +/// An animation block to describe an animation sequence that continuously cycles, +/// and where the logical window is cleared to the specified color before +/// the next image is displayed. +/// +typedef EFI_HII_AIBT_CLEAR_IMAGES_BLOCK EFI_HII_AIBT_CLEAR_IMAGES_LOOP_BLOCK; + +/// +/// An animation block to describe an animation sequence that continuously cycles, +/// and where the screen is restored to the original state before +/// the next image is displayed. +/// +typedef EFI_HII_AIBT_RESTORE_SCRN_BLOCK EFI_HII_AIBT_RESTORE_SCRN_LOOP_BLOCK; + +/// +/// Assigns a new character value to a previously defined animation sequence. +/// +typedef struct _EFI_HII_AIBT_DUPLICATE_BLOCK { + /// + /// The previously defined animation ID with the exact same + /// animation information. + /// + EFI_ANIMATION_ID AnimationId; +} EFI_HII_AIBT_DUPLICATE_BLOCK; + +/// +/// Skips animation IDs. +/// +typedef struct _EFI_HII_AIBT_SKIP1_BLOCK { + /// + /// The unsigned 8-bit value to add to AnimationIdCurrent. + /// + UINT8 SkipCount; +} EFI_HII_AIBT_SKIP1_BLOCK; + +/// +/// Skips animation IDs. +/// +typedef struct _EFI_HII_AIBT_SKIP2_BLOCK { + /// + /// The unsigned 16-bit value to add to AnimationIdCurrent. + /// + UINT16 SkipCount; +} EFI_HII_AIBT_SKIP2_BLOCK; + +#pragma pack() + + + +/// +/// References to string tokens must use this macro to enable scanning for +/// token usages. +/// +/// +/// STRING_TOKEN is not defined in UEFI specification. But it is placed +/// here for the easy access by C files and VFR source files. +/// +#define STRING_TOKEN(t) t + +/// +/// IMAGE_TOKEN is not defined in UEFI specification. But it is placed +/// here for the easy access by C files and VFR source files. +/// +#define IMAGE_TOKEN(t) t + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiMultiPhase.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiMultiPhase.h new file mode 100644 index 0000000..9ca307f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiMultiPhase.h @@ -0,0 +1,235 @@ +/** @file + This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_MULTIPHASE_H__ +#define __UEFI_MULTIPHASE_H__ + +/// +/// Attributes of variable. +/// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +/// +/// This attribute is identified by the mnemonic 'HR' +/// elsewhere in this specification. +/// +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 +/// +/// Attributes of Authenticated Variable +/// +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 +#define EFI_VARIABLE_APPEND_WRITE 0x00000040 +/// +/// NOTE: EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is deprecated and should be considered reserved. +/// +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 + +#ifndef VFRCOMPILE +#include +/// +/// Enumeration of memory types introduced in UEFI. +/// +typedef enum { + /// + /// Not used. + /// + EfiReservedMemoryType, + /// + /// The code portions of a loaded application. + /// (Note that UEFI OS loaders are UEFI applications.) + /// + EfiLoaderCode, + /// + /// The data portions of a loaded application and the default data allocation + /// type used by an application to allocate pool memory. + /// + EfiLoaderData, + /// + /// The code portions of a loaded Boot Services Driver. + /// + EfiBootServicesCode, + /// + /// The data portions of a loaded Boot Serves Driver, and the default data + /// allocation type used by a Boot Services Driver to allocate pool memory. + /// + EfiBootServicesData, + /// + /// The code portions of a loaded Runtime Services Driver. + /// + EfiRuntimeServicesCode, + /// + /// The data portions of a loaded Runtime Services Driver and the default + /// data allocation type used by a Runtime Services Driver to allocate pool memory. + /// + EfiRuntimeServicesData, + /// + /// Free (unallocated) memory. + /// + EfiConventionalMemory, + /// + /// Memory in which errors have been detected. + /// + EfiUnusableMemory, + /// + /// Memory that holds the ACPI tables. + /// + EfiACPIReclaimMemory, + /// + /// Address space reserved for use by the firmware. + /// + EfiACPIMemoryNVS, + /// + /// Used by system firmware to request that a memory-mapped IO region + /// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services. + /// + EfiMemoryMappedIO, + /// + /// System memory-mapped IO region that is used to translate memory + /// cycles to IO cycles by the processor. + /// + EfiMemoryMappedIOPortSpace, + /// + /// Address space reserved by the firmware for code that is part of the processor. + /// + EfiPalCode, + /// + /// A memory region that operates as EfiConventionalMemory, + /// however it happens to also support byte-addressable non-volatility. + /// + EfiPersistentMemory, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +/// +/// Enumeration of reset types. +/// +typedef enum { + /// + /// Used to induce 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 withgout regard to cycle boundaries. EfiColdReset + /// is tantamount to a system power cycle. + /// + EfiResetCold, + /// + /// Used to induce 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. + /// + EfiResetWarm, + /// + /// Used to induce an entry into a power state equivalent to the ACPI G2/S5 or G3 + /// state. If the system does not support this reset type, then when the system + /// is rebooted, it should exhibit the EfiResetCold attributes. + /// + EfiResetShutdown, + /// + /// Used to induce a system-wide reset. The exact type of the reset is defined by + /// the EFI_GUID that follows the Null-terminated Unicode string passed into + /// ResetData. If the platform does not recognize the EFI_GUID in ResetData the + /// platform must pick a supported reset type to perform. The platform may + /// optionally log the parameters from any non-normal reset that occurs. + /// + EfiResetPlatformSpecific +} EFI_RESET_TYPE; + +/// +/// Data structure that precedes all of the standard EFI table types. +/// +typedef struct { + /// + /// A 64-bit signature that identifies the type of table that follows. + /// Unique signatures have been generated for the EFI System Table, + /// the EFI Boot Services Table, and the EFI Runtime Services Table. + /// + UINT64 Signature; + /// + /// The revision of the EFI Specification to which this table + /// conforms. The upper 16 bits of this field contain the major + /// revision value, and the lower 16 bits contain the minor revision + /// value. The minor revision values are limited to the range of 00..99. + /// + UINT32 Revision; + /// + /// The size, in bytes, of the entire table including the EFI_TABLE_HEADER. + /// + UINT32 HeaderSize; + /// + /// The 32-bit CRC for the entire table. This value is computed by + /// setting this field to 0, and computing the 32-bit CRC for HeaderSize bytes. + /// + UINT32 CRC32; + /// + /// Reserved field that must be set to 0. + /// + UINT32 Reserved; +} EFI_TABLE_HEADER; + +/// +/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType +/// WIN_CERTIFICATE_UEFI_GUID and the CertType +/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies +/// authenticated access, then the Data buffer should begin with an +/// authentication descriptor prior to the data payload and DataSize +/// should reflect the the data.and descriptor size. The caller +/// shall digest the Monotonic Count value and the associated data +/// for the variable update using the SHA-256 1-way hash algorithm. +/// The ensuing the 32-byte digest will be signed using the private +/// key associated w/ the public/private 2048-bit RSA key-pair. The +/// WIN_CERTIFICATE shall be used to describe the signature of the +/// Variable data *Data. In addition, the signature will also +/// include the MonotonicCount value to guard against replay attacks. +/// +typedef struct { + /// + /// Included in the signature of + /// AuthInfo.Used to ensure freshness/no + /// replay. Incremented during each + /// "Write" access. + /// + UINT64 MonotonicCount; + /// + /// Provides the authorization for the variable + /// access. It is a signature across the + /// variable data and the Monotonic Count + /// value. Caller uses Private key that is + /// associated with a public key that has been + /// provisioned via the key exchange. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; +} EFI_VARIABLE_AUTHENTICATION; + +/// +/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is +/// set, then the Data buffer shall begin with an instance of a complete (and serialized) +/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new +/// variable value and DataSize shall reflect the combined size of the descriptor and the new +/// variable value. The authentication descriptor is not part of the variable data and is not +/// returned by subsequent calls to GetVariable(). +/// +typedef struct { + /// + /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and + /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT. + /// + EFI_TIME TimeStamp; + /// + /// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; + } EFI_VARIABLE_AUTHENTICATION_2; +#endif // VFRCOMPILE + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiPxe.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiPxe.h new file mode 100644 index 0000000..d57d7d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiPxe.h @@ -0,0 +1,1792 @@ +/** @file + This header file contains all of the PXE type definitions, + structure prototypes, global variables and constants that + are needed for porting PXE to EFI. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Revision Reference: + 32/64-bit PXE specification: + alpha-4, 99-Dec-17. + +**/ + +#ifndef __EFI_PXE_H__ +#define __EFI_PXE_H__ + +#pragma pack(1) + +#define PXE_BUSTYPE(a, b, c, d) \ + ( \ + (((PXE_UINT32) (d) & 0xFF) << 24) | (((PXE_UINT32) (c) & 0xFF) << 16) | (((PXE_UINT32) (b) & 0xFF) << 8) | \ + ((PXE_UINT32) (a) & 0xFF) \ + ) + +/// +/// UNDI ROM ID and devive ID signature. +/// +#define PXE_BUSTYPE_PXE PXE_BUSTYPE ('!', 'P', 'X', 'E') + +/// +/// BUS ROM ID signatures. +/// +#define PXE_BUSTYPE_PCI PXE_BUSTYPE ('P', 'C', 'I', 'R') +#define PXE_BUSTYPE_PC_CARD PXE_BUSTYPE ('P', 'C', 'C', 'R') +#define PXE_BUSTYPE_USB PXE_BUSTYPE ('U', 'S', 'B', 'R') +#define PXE_BUSTYPE_1394 PXE_BUSTYPE ('1', '3', '9', '4') + +#define PXE_SWAP_UINT16(n) ((((PXE_UINT16) (n) & 0x00FF) << 8) | (((PXE_UINT16) (n) & 0xFF00) >> 8)) + +#define PXE_SWAP_UINT32(n) \ + ((((PXE_UINT32)(n) & 0x000000FF) << 24) | \ + (((PXE_UINT32)(n) & 0x0000FF00) << 8) | \ + (((PXE_UINT32)(n) & 0x00FF0000) >> 8) | \ + (((PXE_UINT32)(n) & 0xFF000000) >> 24)) + +#define PXE_SWAP_UINT64(n) \ + ((((PXE_UINT64)(n) & 0x00000000000000FFULL) << 56) | \ + (((PXE_UINT64)(n) & 0x000000000000FF00ULL) << 40) | \ + (((PXE_UINT64)(n) & 0x0000000000FF0000ULL) << 24) | \ + (((PXE_UINT64)(n) & 0x00000000FF000000ULL) << 8) | \ + (((PXE_UINT64)(n) & 0x000000FF00000000ULL) >> 8) | \ + (((PXE_UINT64)(n) & 0x0000FF0000000000ULL) >> 24) | \ + (((PXE_UINT64)(n) & 0x00FF000000000000ULL) >> 40) | \ + (((PXE_UINT64)(n) & 0xFF00000000000000ULL) >> 56)) + + +#define PXE_CPBSIZE_NOT_USED 0 ///< zero +#define PXE_DBSIZE_NOT_USED 0 ///< zero +#define PXE_CPBADDR_NOT_USED (PXE_UINT64) 0 ///< zero +#define PXE_DBADDR_NOT_USED (PXE_UINT64) 0 ///< zero +#define PXE_CONST CONST + +#define PXE_VOLATILE volatile + +typedef VOID PXE_VOID; +typedef UINT8 PXE_UINT8; +typedef UINT16 PXE_UINT16; +typedef UINT32 PXE_UINT32; +typedef UINTN PXE_UINTN; + +/// +/// Typedef unsigned long PXE_UINT64. +/// +typedef UINT64 PXE_UINT64; + +typedef PXE_UINT8 PXE_BOOL; +#define PXE_FALSE 0 ///< zero +#define PXE_TRUE (!PXE_FALSE) + +typedef PXE_UINT16 PXE_OPCODE; + +/// +/// Return UNDI operational state. +/// +#define PXE_OPCODE_GET_STATE 0x0000 + +/// +/// Change UNDI operational state from Stopped to Started. +/// +#define PXE_OPCODE_START 0x0001 + +/// +/// Change UNDI operational state from Started to Stopped. +/// +#define PXE_OPCODE_STOP 0x0002 + +/// +/// Get UNDI initialization information. +/// +#define PXE_OPCODE_GET_INIT_INFO 0x0003 + +/// +/// Get NIC configuration information. +/// +#define PXE_OPCODE_GET_CONFIG_INFO 0x0004 + +/// +/// Changed UNDI operational state from Started to Initialized. +/// +#define PXE_OPCODE_INITIALIZE 0x0005 + +/// +/// Re-initialize the NIC H/W. +/// +#define PXE_OPCODE_RESET 0x0006 + +/// +/// Change the UNDI operational state from Initialized to Started. +/// +#define PXE_OPCODE_SHUTDOWN 0x0007 + +/// +/// Read & change state of external interrupt enables. +/// +#define PXE_OPCODE_INTERRUPT_ENABLES 0x0008 + +/// +/// Read & change state of packet receive filters. +/// +#define PXE_OPCODE_RECEIVE_FILTERS 0x0009 + +/// +/// Read & change station MAC address. +/// +#define PXE_OPCODE_STATION_ADDRESS 0x000A + +/// +/// Read traffic statistics. +/// +#define PXE_OPCODE_STATISTICS 0x000B + +/// +/// Convert multicast IP address to multicast MAC address. +/// +#define PXE_OPCODE_MCAST_IP_TO_MAC 0x000C + +/// +/// Read or change non-volatile storage on the NIC. +/// +#define PXE_OPCODE_NVDATA 0x000D + +/// +/// Get & clear interrupt status. +/// +#define PXE_OPCODE_GET_STATUS 0x000E + +/// +/// Fill media header in packet for transmit. +/// +#define PXE_OPCODE_FILL_HEADER 0x000F + +/// +/// Transmit packet(s). +/// +#define PXE_OPCODE_TRANSMIT 0x0010 + +/// +/// Receive packet. +/// +#define PXE_OPCODE_RECEIVE 0x0011 + +/// +/// Last valid PXE UNDI OpCode number. +/// +#define PXE_OPCODE_LAST_VALID 0x0011 + +typedef PXE_UINT16 PXE_OPFLAGS; + +#define PXE_OPFLAGS_NOT_USED 0x0000 + +// +// ////////////////////////////////////// +// UNDI Get State +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Start +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Stop +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// +// No Opflags + +//////////////////////////////////////// +// UNDI Get Config Info +// +// No Opflags + +/// +/// UNDI Initialize +/// +#define PXE_OPFLAGS_INITIALIZE_CABLE_DETECT_MASK 0x0001 +#define PXE_OPFLAGS_INITIALIZE_DETECT_CABLE 0x0000 +#define PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE 0x0001 + +/// +/// +/// UNDI Reset +/// +#define PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS 0x0001 +#define PXE_OPFLAGS_RESET_DISABLE_FILTERS 0x0002 + +/// +/// UNDI Shutdown. +/// +/// No OpFlags. + +/// +/// UNDI Interrupt Enables. +/// +/// +/// Select whether to enable or disable external interrupt signals. +/// Setting both enable and disable will return PXE_STATCODE_INVALID_OPFLAGS. +/// +#define PXE_OPFLAGS_INTERRUPT_OPMASK 0xC000 +#define PXE_OPFLAGS_INTERRUPT_ENABLE 0x8000 +#define PXE_OPFLAGS_INTERRUPT_DISABLE 0x4000 +#define PXE_OPFLAGS_INTERRUPT_READ 0x0000 + +/// +/// Enable receive interrupts. An external interrupt will be generated +/// after a complete non-error packet has been received. +/// +#define PXE_OPFLAGS_INTERRUPT_RECEIVE 0x0001 + +/// +/// Enable transmit interrupts. An external interrupt will be generated +/// after a complete non-error packet has been transmitted. +/// +#define PXE_OPFLAGS_INTERRUPT_TRANSMIT 0x0002 + +/// +/// Enable command interrupts. An external interrupt will be generated +/// when command execution stops. +/// +#define PXE_OPFLAGS_INTERRUPT_COMMAND 0x0004 + +/// +/// Generate software interrupt. Setting this bit generates an external +/// interrupt, if it is supported by the hardware. +/// +#define PXE_OPFLAGS_INTERRUPT_SOFTWARE 0x0008 + +/// +/// UNDI Receive Filters. +/// +/// +/// Select whether to enable or disable receive filters. +/// Setting both enable and disable will return PXE_STATCODE_INVALID_OPCODE. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_OPMASK 0xC000 +#define PXE_OPFLAGS_RECEIVE_FILTER_ENABLE 0x8000 +#define PXE_OPFLAGS_RECEIVE_FILTER_DISABLE 0x4000 +#define PXE_OPFLAGS_RECEIVE_FILTER_READ 0x0000 + +/// +/// To reset the contents of the multicast MAC address filter list, +/// set this OpFlag: +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST 0x2000 + +/// +/// Enable unicast packet receiving. Packets sent to the current station +/// MAC address will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +/// +/// Enable broadcast packet receiving. Packets sent to the broadcast +/// MAC address will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +/// +/// Enable filtered multicast packet receiving. Packets sent to any +/// of the multicast MAC addresses in the multicast MAC address filter +/// list will be received. If the filter list is empty, no multicast +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +/// +/// Enable promiscuous packet receiving. All packets will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +/// +/// Enable promiscuous multicast packet receiving. All multicast +/// packets will be received. +/// +#define PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +/// +/// UNDI Station Address. +/// +#define PXE_OPFLAGS_STATION_ADDRESS_READ 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_WRITE 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_RESET 0x0001 + +/// +/// UNDI Statistics. +/// +#define PXE_OPFLAGS_STATISTICS_READ 0x0000 +#define PXE_OPFLAGS_STATISTICS_RESET 0x0001 + +/// +/// UNDI MCast IP to MAC. +/// +/// +/// Identify the type of IP address in the CPB. +/// +#define PXE_OPFLAGS_MCAST_IP_TO_MAC_OPMASK 0x0003 +#define PXE_OPFLAGS_MCAST_IPV4_TO_MAC 0x0000 +#define PXE_OPFLAGS_MCAST_IPV6_TO_MAC 0x0001 + +/// +/// UNDI NvData. +/// +/// +/// Select the type of non-volatile data operation. +/// +#define PXE_OPFLAGS_NVDATA_OPMASK 0x0001 +#define PXE_OPFLAGS_NVDATA_READ 0x0000 +#define PXE_OPFLAGS_NVDATA_WRITE 0x0001 + +/// +/// UNDI Get Status. +/// +/// +/// Return current interrupt status. This will also clear any interrupts +/// that are currently set. This can be used in a polling routine. The +/// interrupt flags are still set and cleared even when the interrupts +/// are disabled. +/// +#define PXE_OPFLAGS_GET_INTERRUPT_STATUS 0x0001 + +/// +/// Return list of transmitted buffers for recycling. Transmit buffers +/// must not be changed or unallocated until they have recycled. After +/// issuing a transmit command, wait for a transmit complete interrupt. +/// When a transmit complete interrupt is received, read the transmitted +/// buffers. Do not plan on getting one buffer per interrupt. Some +/// NICs and UNDIs may transmit multiple buffers per interrupt. +/// +#define PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS 0x0002 + +/// +/// Return current media status. +/// +#define PXE_OPFLAGS_GET_MEDIA_STATUS 0x0004 + +/// +/// UNDI Fill Header. +/// +#define PXE_OPFLAGS_FILL_HEADER_OPMASK 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_WHOLE 0x0000 + +/// +/// UNDI Transmit. +/// +/// +/// S/W UNDI only. Return after the packet has been transmitted. A +/// transmit complete interrupt will still be generated and the transmit +/// buffer will have to be recycled. +/// +#define PXE_OPFLAGS_SWUNDI_TRANSMIT_OPMASK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_BLOCK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_DONT_BLOCK 0x0000 + +#define PXE_OPFLAGS_TRANSMIT_OPMASK 0x0002 +#define PXE_OPFLAGS_TRANSMIT_FRAGMENTED 0x0002 +#define PXE_OPFLAGS_TRANSMIT_WHOLE 0x0000 + +/// +/// UNDI Receive. +/// +/// No OpFlags. +/// + +/// +/// PXE STATFLAGS. +/// +typedef PXE_UINT16 PXE_STATFLAGS; + +#define PXE_STATFLAGS_INITIALIZE 0x0000 + +/// +/// Common StatFlags that can be returned by all commands. +/// +/// +/// The COMMAND_COMPLETE and COMMAND_FAILED status flags must be +/// implemented by all UNDIs. COMMAND_QUEUED is only needed by UNDIs +/// that support command queuing. +/// +#define PXE_STATFLAGS_STATUS_MASK 0xC000 +#define PXE_STATFLAGS_COMMAND_COMPLETE 0xC000 +#define PXE_STATFLAGS_COMMAND_FAILED 0x8000 +#define PXE_STATFLAGS_COMMAND_QUEUED 0x4000 + +/// +/// UNDI Get State. +/// +#define PXE_STATFLAGS_GET_STATE_MASK 0x0003 +#define PXE_STATFLAGS_GET_STATE_INITIALIZED 0x0002 +#define PXE_STATFLAGS_GET_STATE_STARTED 0x0001 +#define PXE_STATFLAGS_GET_STATE_STOPPED 0x0000 + +/// +/// UNDI Start. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Get Init Info. +/// +#define PXE_STATFLAGS_CABLE_DETECT_MASK 0x0001 +#define PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED 0x0001 + +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK 0x0002 +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED 0x0002 + +/// +/// UNDI Initialize. +/// +#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA 0x0001 + +/// +/// UNDI Reset. +/// +#define PXE_STATFLAGS_RESET_NO_MEDIA 0x0001 + +/// +/// UNDI Shutdown. +/// +/// No additional StatFlags. + +/// +/// UNDI Interrupt Enables. +/// +/// +/// If set, receive interrupts are enabled. +/// +#define PXE_STATFLAGS_INTERRUPT_RECEIVE 0x0001 + +/// +/// If set, transmit interrupts are enabled. +/// +#define PXE_STATFLAGS_INTERRUPT_TRANSMIT 0x0002 + +/// +/// If set, command interrupts are enabled. +/// +#define PXE_STATFLAGS_INTERRUPT_COMMAND 0x0004 + +/// +/// UNDI Receive Filters. +/// + +/// +/// If set, unicast packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +/// +/// If set, broadcast packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +/// +/// If set, multicast packets that match up with the multicast address +/// filter list will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +/// +/// If set, all packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +/// +/// If set, all multicast packets will be received. +/// +#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +/// +/// UNDI Station Address. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Statistics. +/// +/// No additional StatFlags. +/// + +/// +//// UNDI MCast IP to MAC. +//// +//// No additional StatFlags. + +/// +/// UNDI NvData. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Get Status. +/// + +/// +/// Use to determine if an interrupt has occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK 0x000F +#define PXE_STATFLAGS_GET_STATUS_NO_INTERRUPTS 0x0000 + +/// +/// If set, at least one receive interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_RECEIVE 0x0001 + +/// +/// If set, at least one transmit interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_TRANSMIT 0x0002 + +/// +/// If set, at least one command interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_COMMAND 0x0004 + +/// +/// If set, at least one software interrupt occurred. +/// +#define PXE_STATFLAGS_GET_STATUS_SOFTWARE 0x0008 + +/// +/// This flag is set if the transmitted buffer queue is empty. This flag +/// will be set if all transmitted buffer addresses get written into the DB. +/// +#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY 0x0010 + +/// +/// This flag is set if no transmitted buffer addresses were written +/// into the DB. (This could be because DBsize was too small.) +/// +#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN 0x0020 + +/// +/// This flag is set if there is no media detected. +/// +#define PXE_STATFLAGS_GET_STATUS_NO_MEDIA 0x0040 + +/// +/// UNDI Fill Header. +/// +/// No additional StatFlags. +/// + +/// +/// UNDI Transmit. +/// +/// No additional StatFlags. + +/// +/// UNDI Receive +///. + +/// +/// No additional StatFlags. +/// +typedef PXE_UINT16 PXE_STATCODE; + +#define PXE_STATCODE_INITIALIZE 0x0000 + +/// +/// Common StatCodes returned by all UNDI commands, UNDI protocol functions +/// and BC protocol functions. +/// +#define PXE_STATCODE_SUCCESS 0x0000 + +#define PXE_STATCODE_INVALID_CDB 0x0001 +#define PXE_STATCODE_INVALID_CPB 0x0002 +#define PXE_STATCODE_BUSY 0x0003 +#define PXE_STATCODE_QUEUE_FULL 0x0004 +#define PXE_STATCODE_ALREADY_STARTED 0x0005 +#define PXE_STATCODE_NOT_STARTED 0x0006 +#define PXE_STATCODE_NOT_SHUTDOWN 0x0007 +#define PXE_STATCODE_ALREADY_INITIALIZED 0x0008 +#define PXE_STATCODE_NOT_INITIALIZED 0x0009 +#define PXE_STATCODE_DEVICE_FAILURE 0x000A +#define PXE_STATCODE_NVDATA_FAILURE 0x000B +#define PXE_STATCODE_UNSUPPORTED 0x000C +#define PXE_STATCODE_BUFFER_FULL 0x000D +#define PXE_STATCODE_INVALID_PARAMETER 0x000E +#define PXE_STATCODE_INVALID_UNDI 0x000F +#define PXE_STATCODE_IPV4_NOT_SUPPORTED 0x0010 +#define PXE_STATCODE_IPV6_NOT_SUPPORTED 0x0011 +#define PXE_STATCODE_NOT_ENOUGH_MEMORY 0x0012 +#define PXE_STATCODE_NO_DATA 0x0013 + +typedef PXE_UINT16 PXE_IFNUM; + +/// +/// This interface number must be passed to the S/W UNDI Start command. +/// +#define PXE_IFNUM_START 0x0000 + +/// +/// This interface number is returned by the S/W UNDI Get State and +/// Start commands if information in the CDB, CPB or DB is invalid. +/// +#define PXE_IFNUM_INVALID 0x0000 + +typedef PXE_UINT16 PXE_CONTROL; + +/// +/// Setting this flag directs the UNDI to queue this command for later +/// execution if the UNDI is busy and it supports command queuing. +/// If queuing is not supported, a PXE_STATCODE_INVALID_CONTROL error +/// is returned. If the queue is full, a PXE_STATCODE_CDB_QUEUE_FULL +/// error is returned. +/// +#define PXE_CONTROL_QUEUE_IF_BUSY 0x0002 + +/// +/// These two bit values are used to determine if there are more UNDI +/// CDB structures following this one. If the link bit is set, there +/// must be a CDB structure following this one. Execution will start +/// on the next CDB structure as soon as this one completes successfully. +/// If an error is generated by this command, execution will stop. +/// +#define PXE_CONTROL_LINK 0x0001 +#define PXE_CONTROL_LAST_CDB_IN_LIST 0x0000 + +typedef PXE_UINT8 PXE_FRAME_TYPE; + +#define PXE_FRAME_TYPE_NONE 0x00 +#define PXE_FRAME_TYPE_UNICAST 0x01 +#define PXE_FRAME_TYPE_BROADCAST 0x02 +#define PXE_FRAME_TYPE_FILTERED_MULTICAST 0x03 +#define PXE_FRAME_TYPE_PROMISCUOUS 0x04 +#define PXE_FRAME_TYPE_PROMISCUOUS_MULTICAST 0x05 + +#define PXE_FRAME_TYPE_MULTICAST PXE_FRAME_TYPE_FILTERED_MULTICAST + +typedef PXE_UINT32 PXE_IPV4; + +typedef PXE_UINT32 PXE_IPV6[4]; +#define PXE_MAC_LENGTH 32 + +typedef PXE_UINT8 PXE_MAC_ADDR[PXE_MAC_LENGTH]; + +typedef PXE_UINT8 PXE_IFTYPE; +typedef UINT16 PXE_MEDIA_PROTOCOL; + +/// +/// This information is from the ARP section of RFC 1700. +/// +/// 1 Ethernet (10Mb) [JBP] +/// 2 Experimental Ethernet (3Mb) [JBP] +/// 3 Amateur Radio AX.25 [PXK] +/// 4 Proteon ProNET Token Ring [JBP] +/// 5 Chaos [GXP] +/// 6 IEEE 802 Networks [JBP] +/// 7 ARCNET [JBP] +/// 8 Hyperchannel [JBP] +/// 9 Lanstar [TU] +/// 10 Autonet Short Address [MXB1] +/// 11 LocalTalk [JKR1] +/// 12 LocalNet (IBM* PCNet or SYTEK* LocalNET) [JXM] +/// 13 Ultra link [RXD2] +/// 14 SMDS [GXC1] +/// 15 Frame Relay [AGM] +/// 16 Asynchronous Transmission Mode (ATM) [JXB2] +/// 17 HDLC [JBP] +/// 18 Fibre Channel [Yakov Rekhter] +/// 19 Asynchronous Transmission Mode (ATM) [Mark Laubach] +/// 20 Serial Line [JBP] +/// 21 Asynchronous Transmission Mode (ATM) [MXB1] +/// +/// * Other names and brands may be claimed as the property of others. +/// +#define PXE_IFTYPE_ETHERNET 0x01 +#define PXE_IFTYPE_TOKENRING 0x04 +#define PXE_IFTYPE_FIBRE_CHANNEL 0x12 + +typedef struct s_pxe_hw_undi { + PXE_UINT32 Signature; ///< PXE_ROMID_SIGNATURE. + PXE_UINT8 Len; ///< sizeof(PXE_HW_UNDI). + PXE_UINT8 Fudge; ///< makes 8-bit cksum equal zero. + PXE_UINT8 Rev; ///< PXE_ROMID_REV. + PXE_UINT8 IFcnt; ///< physical connector count lower byte. + PXE_UINT8 MajorVer; ///< PXE_ROMID_MAJORVER. + PXE_UINT8 MinorVer; ///< PXE_ROMID_MINORVER. + PXE_UINT8 IFcntExt; ///< physical connector count upper byte. + PXE_UINT8 reserved; ///< zero, not used. + PXE_UINT32 Implementation; ///< implementation flags. + ///< reserved ///< vendor use. + ///< UINT32 Status; ///< status port. + ///< UINT32 Command; ///< command port. + ///< UINT64 CDBaddr; ///< CDB address port. + ///< +} PXE_HW_UNDI; + +/// +/// Status port bit definitions. +/// + +/// +/// UNDI operation state. +/// +#define PXE_HWSTAT_STATE_MASK 0xC0000000 +#define PXE_HWSTAT_BUSY 0xC0000000 +#define PXE_HWSTAT_INITIALIZED 0x80000000 +#define PXE_HWSTAT_STARTED 0x40000000 +#define PXE_HWSTAT_STOPPED 0x00000000 + +/// +/// If set, last command failed. +/// +#define PXE_HWSTAT_COMMAND_FAILED 0x20000000 + +/// +/// If set, identifies enabled receive filters. +/// +#define PXE_HWSTAT_PROMISCUOUS_MULTICAST_RX_ENABLED 0x00001000 +#define PXE_HWSTAT_PROMISCUOUS_RX_ENABLED 0x00000800 +#define PXE_HWSTAT_BROADCAST_RX_ENABLED 0x00000400 +#define PXE_HWSTAT_MULTICAST_RX_ENABLED 0x00000200 +#define PXE_HWSTAT_UNICAST_RX_ENABLED 0x00000100 + +/// +/// If set, identifies enabled external interrupts. +/// +#define PXE_HWSTAT_SOFTWARE_INT_ENABLED 0x00000080 +#define PXE_HWSTAT_TX_COMPLETE_INT_ENABLED 0x00000040 +#define PXE_HWSTAT_PACKET_RX_INT_ENABLED 0x00000020 +#define PXE_HWSTAT_CMD_COMPLETE_INT_ENABLED 0x00000010 + +/// +/// If set, identifies pending interrupts. +/// +#define PXE_HWSTAT_SOFTWARE_INT_PENDING 0x00000008 +#define PXE_HWSTAT_TX_COMPLETE_INT_PENDING 0x00000004 +#define PXE_HWSTAT_PACKET_RX_INT_PENDING 0x00000002 +#define PXE_HWSTAT_CMD_COMPLETE_INT_PENDING 0x00000001 + +/// +/// Command port definitions. +/// + +/// +/// If set, CDB identified in CDBaddr port is given to UNDI. +/// If not set, other bits in this word will be processed. +/// +#define PXE_HWCMD_ISSUE_COMMAND 0x80000000 +#define PXE_HWCMD_INTS_AND_FILTS 0x00000000 + +/// +/// Use these to enable/disable receive filters. +/// +#define PXE_HWCMD_PROMISCUOUS_MULTICAST_RX_ENABLE 0x00001000 +#define PXE_HWCMD_PROMISCUOUS_RX_ENABLE 0x00000800 +#define PXE_HWCMD_BROADCAST_RX_ENABLE 0x00000400 +#define PXE_HWCMD_MULTICAST_RX_ENABLE 0x00000200 +#define PXE_HWCMD_UNICAST_RX_ENABLE 0x00000100 + +/// +/// Use these to enable/disable external interrupts. +/// +#define PXE_HWCMD_SOFTWARE_INT_ENABLE 0x00000080 +#define PXE_HWCMD_TX_COMPLETE_INT_ENABLE 0x00000040 +#define PXE_HWCMD_PACKET_RX_INT_ENABLE 0x00000020 +#define PXE_HWCMD_CMD_COMPLETE_INT_ENABLE 0x00000010 + +/// +/// Use these to clear pending external interrupts. +/// +#define PXE_HWCMD_CLEAR_SOFTWARE_INT 0x00000008 +#define PXE_HWCMD_CLEAR_TX_COMPLETE_INT 0x00000004 +#define PXE_HWCMD_CLEAR_PACKET_RX_INT 0x00000002 +#define PXE_HWCMD_CLEAR_CMD_COMPLETE_INT 0x00000001 + +typedef struct s_pxe_sw_undi { + PXE_UINT32 Signature; ///< PXE_ROMID_SIGNATURE. + PXE_UINT8 Len; ///< sizeof(PXE_SW_UNDI). + PXE_UINT8 Fudge; ///< makes 8-bit cksum zero. + PXE_UINT8 Rev; ///< PXE_ROMID_REV. + PXE_UINT8 IFcnt; ///< physical connector count lower byte. + PXE_UINT8 MajorVer; ///< PXE_ROMID_MAJORVER. + PXE_UINT8 MinorVer; ///< PXE_ROMID_MINORVER. + PXE_UINT8 IFcntExt; ///< physical connector count upper byte. + PXE_UINT8 reserved1; ///< zero, not used. + PXE_UINT32 Implementation; ///< Implementation flags. + PXE_UINT64 EntryPoint; ///< API entry point. + PXE_UINT8 reserved2[3]; ///< zero, not used. + PXE_UINT8 BusCnt; ///< number of bustypes supported. + PXE_UINT32 BusType[1]; ///< list of supported bustypes. +} PXE_SW_UNDI; + +typedef union u_pxe_undi { + PXE_HW_UNDI hw; + PXE_SW_UNDI sw; +} PXE_UNDI; + +/// +/// Signature of !PXE structure. +/// +#define PXE_ROMID_SIGNATURE PXE_BUSTYPE ('!', 'P', 'X', 'E') + +/// +/// !PXE structure format revision +///. +#define PXE_ROMID_REV 0x02 + +/// +/// UNDI command interface revision. These are the values that get sent +/// in option 94 (Client Network Interface Identifier) in the DHCP Discover +/// and PXE Boot Server Request packets. +/// +#define PXE_ROMID_MAJORVER 0x03 +#define PXE_ROMID_MINORVER 0x01 + +/// +/// Implementation flags. +/// +#define PXE_ROMID_IMP_HW_UNDI 0x80000000 +#define PXE_ROMID_IMP_SW_VIRT_ADDR 0x40000000 +#define PXE_ROMID_IMP_64BIT_DEVICE 0x00010000 +#define PXE_ROMID_IMP_FRAG_SUPPORTED 0x00008000 +#define PXE_ROMID_IMP_CMD_LINK_SUPPORTED 0x00004000 +#define PXE_ROMID_IMP_CMD_QUEUE_SUPPORTED 0x00002000 +#define PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED 0x00001000 +#define PXE_ROMID_IMP_NVDATA_SUPPORT_MASK 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_BULK_WRITABLE 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_SPARSE_WRITABLE 0x00000800 +#define PXE_ROMID_IMP_NVDATA_READ_ONLY 0x00000400 +#define PXE_ROMID_IMP_NVDATA_NOT_AVAILABLE 0x00000000 +#define PXE_ROMID_IMP_STATISTICS_SUPPORTED 0x00000200 +#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE 0x00000100 +#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED 0x00000080 +#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED 0x00000040 +#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED 0x00000020 +#define PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED 0x00000010 +#define PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED 0x00000008 +#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED 0x00000004 +#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED 0x00000002 +#define PXE_ROMID_IMP_CMD_COMPLETE_INT_SUPPORTED 0x00000001 + +typedef struct s_pxe_cdb { + PXE_OPCODE OpCode; + PXE_OPFLAGS OpFlags; + PXE_UINT16 CPBsize; + PXE_UINT16 DBsize; + PXE_UINT64 CPBaddr; + PXE_UINT64 DBaddr; + PXE_STATCODE StatCode; + PXE_STATFLAGS StatFlags; + PXE_UINT16 IFnum; + PXE_CONTROL Control; +} PXE_CDB; + +typedef union u_pxe_ip_addr { + PXE_IPV6 IPv6; + PXE_IPV4 IPv4; +} PXE_IP_ADDR; + +typedef union pxe_device { + /// + /// PCI and PC Card NICs are both identified using bus, device + /// and function numbers. For PC Card, this may require PC + /// Card services to be loaded in the BIOS or preboot + /// environment. + /// + struct { + /// + /// See S/W UNDI ROMID structure definition for PCI and + /// PCC BusType definitions. + /// + PXE_UINT32 BusType; + + /// + /// Bus, device & function numbers that locate this device. + /// + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + } + PCI, PCC; + +} PXE_DEVICE; + +/// +/// cpb and db definitions +/// +#define MAX_PCI_CONFIG_LEN 64 ///< # of dwords. +#define MAX_EEPROM_LEN 128 ///< # of dwords. +#define MAX_XMIT_BUFFERS 32 ///< recycling Q length for xmit_done. +#define MAX_MCAST_ADDRESS_CNT 8 + +typedef struct s_pxe_cpb_start_30 { + /// + /// PXE_VOID Delay(UINTN microseconds); + /// + /// UNDI will never request a delay smaller than 10 microseconds + /// and will always request delays in increments of 10 microseconds. + /// The Delay() CallBack routine must delay between n and n + 10 + /// microseconds before returning control to the UNDI. + /// + /// This field cannot be set to zero. + /// + UINT64 Delay; + + /// + /// PXE_VOID Block(UINT32 enable); + /// + /// UNDI may need to block multi-threaded/multi-processor access to + /// critical code sections when programming or accessing the network + /// device. To this end, a blocking service is needed by the UNDI. + /// When UNDI needs a block, it will call Block() passing a non-zero + /// value. When UNDI no longer needs a block, it will call Block() + /// with a zero value. When called, if the Block() is already enabled, + /// do not return control to the UNDI until the previous Block() is + /// disabled. + /// + /// This field cannot be set to zero. + /// + UINT64 Block; + + /// + /// PXE_VOID Virt2Phys(UINT64 virtual, UINT64 physical_ptr); + /// + /// UNDI will pass the virtual address of a buffer and the virtual + /// address of a 64-bit physical buffer. Convert the virtual address + /// to a physical address and write the result to the physical address + /// buffer. If virtual and physical addresses are the same, just + /// copy the virtual address to the physical address buffer. + /// + /// This field can be set to zero if virtual and physical addresses + /// are equal. + /// + UINT64 Virt2Phys; + /// + /// PXE_VOID Mem_IO(UINT8 read_write, UINT8 len, UINT64 port, + /// UINT64 buf_addr); + /// + /// UNDI will read or write the device io space using this call back + /// function. It passes the number of bytes as the len parameter and it + /// will be either 1,2,4 or 8. + /// + /// This field can not be set to zero. + /// + UINT64 Mem_IO; +} PXE_CPB_START_30; + +typedef struct s_pxe_cpb_start_31 { + /// + /// PXE_VOID Delay(UINT64 UnqId, UINTN microseconds); + /// + /// UNDI will never request a delay smaller than 10 microseconds + /// and will always request delays in increments of 10 microseconds. + /// The Delay() CallBack routine must delay between n and n + 10 + /// microseconds before returning control to the UNDI. + /// + /// This field cannot be set to zero. + /// + UINT64 Delay; + + /// + /// PXE_VOID Block(UINT64 unq_id, UINT32 enable); + /// + /// UNDI may need to block multi-threaded/multi-processor access to + /// critical code sections when programming or accessing the network + /// device. To this end, a blocking service is needed by the UNDI. + /// When UNDI needs a block, it will call Block() passing a non-zero + /// value. When UNDI no longer needs a block, it will call Block() + /// with a zero value. When called, if the Block() is already enabled, + /// do not return control to the UNDI until the previous Block() is + /// disabled. + /// + /// This field cannot be set to zero. + /// + UINT64 Block; + + /// + /// PXE_VOID Virt2Phys(UINT64 UnqId, UINT64 virtual, UINT64 physical_ptr); + /// + /// UNDI will pass the virtual address of a buffer and the virtual + /// address of a 64-bit physical buffer. Convert the virtual address + /// to a physical address and write the result to the physical address + /// buffer. If virtual and physical addresses are the same, just + /// copy the virtual address to the physical address buffer. + /// + /// This field can be set to zero if virtual and physical addresses + /// are equal. + /// + UINT64 Virt2Phys; + /// + /// PXE_VOID Mem_IO(UINT64 UnqId, UINT8 read_write, UINT8 len, UINT64 port, + /// UINT64 buf_addr); + /// + /// UNDI will read or write the device io space using this call back + /// function. It passes the number of bytes as the len parameter and it + /// will be either 1,2,4 or 8. + /// + /// This field can not be set to zero. + /// + UINT64 Mem_IO; + /// + /// PXE_VOID Map_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + /// UINT32 Direction, UINT64 mapped_addr); + /// + /// UNDI will pass the virtual address of a buffer, direction of the data + /// flow from/to the mapped buffer (the constants are defined below) + /// and a place holder (pointer) for the mapped address. + /// This call will Map the given address to a physical DMA address and write + /// the result to the mapped_addr pointer. If there is no need to + /// map the given address to a lower address (i.e. the given address is + /// associated with a physical address that is already compatible to be + /// used with the DMA, it converts the given virtual address to it's + /// physical address and write that in the mapped address pointer. + /// + /// This field can be set to zero if there is no mapping service available. + /// + UINT64 Map_Mem; + + /// + /// PXE_VOID UnMap_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + /// UINT32 Direction, UINT64 mapped_addr); + /// + /// UNDI will pass the virtual and mapped addresses of a buffer. + /// This call will un map the given address. + /// + /// This field can be set to zero if there is no unmapping service available. + /// + UINT64 UnMap_Mem; + + /// + /// PXE_VOID Sync_Mem(UINT64 unq_id, UINT64 virtual, + /// UINT32 size, UINT32 Direction, UINT64 mapped_addr); + /// + /// UNDI will pass the virtual and mapped addresses of a buffer. + /// This call will synchronize the contents of both the virtual and mapped. + /// buffers for the given Direction. + /// + /// This field can be set to zero if there is no service available. + /// + UINT64 Sync_Mem; + + /// + /// protocol driver can provide anything for this Unique_ID, UNDI remembers + /// that as just a 64bit value associated to the interface specified by + /// the ifnum and gives it back as a parameter to all the call-back routines + /// when calling for that interface! + /// + UINT64 Unique_ID; +} PXE_CPB_START_31; + +#define TO_AND_FROM_DEVICE 0 +#define FROM_DEVICE 1 +#define TO_DEVICE 2 + +#define PXE_DELAY_MILLISECOND 1000 +#define PXE_DELAY_SECOND 1000000 +#define PXE_IO_READ 0 +#define PXE_IO_WRITE 1 +#define PXE_MEM_READ 2 +#define PXE_MEM_WRITE 4 + +typedef struct s_pxe_db_get_init_info { + /// + /// Minimum length of locked memory buffer that must be given to + /// the Initialize command. Giving UNDI more memory will generally + /// give better performance. + /// + /// If MemoryRequired is zero, the UNDI does not need and will not + /// use system memory to receive and transmit packets. + /// + PXE_UINT32 MemoryRequired; + + /// + /// Maximum frame data length for Tx/Rx excluding the media header. + /// + PXE_UINT32 FrameDataLen; + + /// + /// Supported link speeds are in units of mega bits. Common ethernet + /// values are 10, 100 and 1000. Unused LinkSpeeds[] entries are zero + /// filled. + /// + PXE_UINT32 LinkSpeeds[4]; + + /// + /// Number of non-volatile storage items. + /// + PXE_UINT32 NvCount; + + /// + /// Width of non-volatile storage item in bytes. 0, 1, 2 or 4 + /// + PXE_UINT16 NvWidth; + + /// + /// Media header length. This is the typical media header length for + /// this UNDI. This information is needed when allocating receive + /// and transmit buffers. + /// + PXE_UINT16 MediaHeaderLen; + + /// + /// Number of bytes in the NIC hardware (MAC) address. + /// + PXE_UINT16 HWaddrLen; + + /// + /// Maximum number of multicast MAC addresses in the multicast + /// MAC address filter list. + /// + PXE_UINT16 MCastFilterCnt; + + /// + /// Default number and size of transmit and receive buffers that will + /// be allocated by the UNDI. If MemoryRequired is non-zero, this + /// allocation will come out of the memory buffer given to the Initialize + /// command. If MemoryRequired is zero, this allocation will come out of + /// memory on the NIC. + /// + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + /// + /// Hardware interface types defined in the Assigned Numbers RFC + /// and used in DHCP and ARP packets. + /// See the PXE_IFTYPE typedef and PXE_IFTYPE_xxx macros. + /// + PXE_UINT8 IFtype; + + /// + /// Supported duplex. See PXE_DUPLEX_xxxxx #defines below. + /// + PXE_UINT8 SupportedDuplexModes; + + /// + /// Supported loopback options. See PXE_LOOPBACK_xxxxx #defines below. + /// + PXE_UINT8 SupportedLoopBackModes; +} PXE_DB_GET_INIT_INFO; + +#define PXE_MAX_TXRX_UNIT_ETHER 1500 + +#define PXE_HWADDR_LEN_ETHER 0x0006 +#define PXE_MAC_HEADER_LEN_ETHER 0x000E + +#define PXE_DUPLEX_ENABLE_FULL_SUPPORTED 1 +#define PXE_DUPLEX_FORCE_FULL_SUPPORTED 2 + +#define PXE_LOOPBACK_INTERNAL_SUPPORTED 1 +#define PXE_LOOPBACK_EXTERNAL_SUPPORTED 2 + +typedef struct s_pxe_pci_config_info { + /// + /// This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + /// For PCI bus devices, this field is set to PXE_BUSTYPE_PCI. + /// + UINT32 BusType; + + /// + /// This identifies the PCI network device that this UNDI interface. + /// is bound to. + /// + UINT16 Bus; + UINT8 Device; + UINT8 Function; + + /// + /// This is a copy of the PCI configuration space for this + /// network device. + /// + union { + UINT8 Byte[256]; + UINT16 Word[128]; + UINT32 Dword[64]; + } Config; +} PXE_PCI_CONFIG_INFO; + +typedef struct s_pxe_pcc_config_info { + /// + /// This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + /// For PCC bus devices, this field is set to PXE_BUSTYPE_PCC. + /// + PXE_UINT32 BusType; + + /// + /// This identifies the PCC network device that this UNDI interface + /// is bound to. + /// + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + /// + /// This is a copy of the PCC configuration space for this + /// network device. + /// + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCC_CONFIG_INFO; + +typedef union u_pxe_db_get_config_info { + PXE_PCI_CONFIG_INFO pci; + PXE_PCC_CONFIG_INFO pcc; +} PXE_DB_GET_CONFIG_INFO; + +typedef struct s_pxe_cpb_initialize { + /// + /// Address of first (lowest) byte of the memory buffer. This buffer must + /// be in contiguous physical memory and cannot be swapped out. The UNDI + /// will be using this for transmit and receive buffering. + /// + PXE_UINT64 MemoryAddr; + + /// + /// MemoryLength must be greater than or equal to MemoryRequired + /// returned by the Get Init Info command. + /// + PXE_UINT32 MemoryLength; + + /// + /// Desired link speed in Mbit/sec. Common ethernet values are 10, 100 + /// and 1000. Setting a value of zero will auto-detect and/or use the + /// default link speed (operation depends on UNDI/NIC functionality). + /// + PXE_UINT32 LinkSpeed; + + /// + /// Suggested number and size of receive and transmit buffers to + /// allocate. If MemoryAddr and MemoryLength are non-zero, this + /// allocation comes out of the supplied memory buffer. If MemoryAddr + /// and MemoryLength are zero, this allocation comes out of memory + /// on the NIC. + /// + /// If these fields are set to zero, the UNDI will allocate buffer + /// counts and sizes as it sees fit. + /// + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + /// + /// The following configuration parameters are optional and must be zero + /// to use the default values. + /// + PXE_UINT8 DuplexMode; + + PXE_UINT8 LoopBackMode; +} PXE_CPB_INITIALIZE; + +#define PXE_DUPLEX_DEFAULT 0x00 +#define PXE_FORCE_FULL_DUPLEX 0x01 +#define PXE_ENABLE_FULL_DUPLEX 0x02 +#define PXE_FORCE_HALF_DUPLEX 0x04 +#define PXE_DISABLE_FULL_DUPLEX 0x08 + +#define LOOPBACK_NORMAL 0 +#define LOOPBACK_INTERNAL 1 +#define LOOPBACK_EXTERNAL 2 + +typedef struct s_pxe_db_initialize { + /// + /// Actual amount of memory used from the supplied memory buffer. This + /// may be less that the amount of memory suppllied and may be zero if + /// the UNDI and network device do not use external memory buffers. + /// + /// Memory used by the UNDI and network device is allocated from the + /// lowest memory buffer address. + /// + PXE_UINT32 MemoryUsed; + + /// + /// Actual number and size of receive and transmit buffers that were + /// allocated. + /// + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; +} PXE_DB_INITIALIZE; + +typedef struct s_pxe_cpb_receive_filters { + /// + /// List of multicast MAC addresses. This list, if present, will + /// replace the existing multicast MAC address filter list. + /// + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_CPB_RECEIVE_FILTERS; + +typedef struct s_pxe_db_receive_filters { + /// + /// Filtered multicast MAC address list. + /// + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_DB_RECEIVE_FILTERS; + +typedef struct s_pxe_cpb_station_address { + /// + /// If supplied and supported, the current station MAC address + /// will be changed. + /// + PXE_MAC_ADDR StationAddr; +} PXE_CPB_STATION_ADDRESS; + +typedef struct s_pxe_dpb_station_address { + /// + /// Current station MAC address. + /// + PXE_MAC_ADDR StationAddr; + + /// + /// Station broadcast MAC address. + /// + PXE_MAC_ADDR BroadcastAddr; + + /// + /// Permanent station MAC address. + /// + PXE_MAC_ADDR PermanentAddr; +} PXE_DB_STATION_ADDRESS; + +typedef struct s_pxe_db_statistics { + /// + /// Bit field identifying what statistic data is collected by the + /// UNDI/NIC. + /// If bit 0x00 is set, Data[0x00] is collected. + /// If bit 0x01 is set, Data[0x01] is collected. + /// If bit 0x20 is set, Data[0x20] is collected. + /// If bit 0x21 is set, Data[0x21] is collected. + /// Etc. + /// + PXE_UINT64 Supported; + + /// + /// Statistic data. + /// + PXE_UINT64 Data[64]; +} PXE_DB_STATISTICS; + +/// +/// Total number of frames received. Includes frames with errors and +/// dropped frames. +/// +#define PXE_STATISTICS_RX_TOTAL_FRAMES 0x00 + +/// +/// Number of valid frames received and copied into receive buffers. +/// +#define PXE_STATISTICS_RX_GOOD_FRAMES 0x01 + +/// +/// Number of frames below the minimum length for the media. +/// This would be <64 for ethernet. +/// +#define PXE_STATISTICS_RX_UNDERSIZE_FRAMES 0x02 + +/// +/// Number of frames longer than the maxminum length for the +/// media. This would be >1500 for ethernet. +/// +#define PXE_STATISTICS_RX_OVERSIZE_FRAMES 0x03 + +/// +/// Valid frames that were dropped because receive buffers were full. +/// +#define PXE_STATISTICS_RX_DROPPED_FRAMES 0x04 + +/// +/// Number of valid unicast frames received and not dropped. +/// +#define PXE_STATISTICS_RX_UNICAST_FRAMES 0x05 + +/// +/// Number of valid broadcast frames received and not dropped. +/// +#define PXE_STATISTICS_RX_BROADCAST_FRAMES 0x06 + +/// +/// Number of valid mutlicast frames received and not dropped. +/// +#define PXE_STATISTICS_RX_MULTICAST_FRAMES 0x07 + +/// +/// Number of frames w/ CRC or alignment errors. +/// +#define PXE_STATISTICS_RX_CRC_ERROR_FRAMES 0x08 + +/// +/// Total number of bytes received. Includes frames with errors +/// and dropped frames. +/// +#define PXE_STATISTICS_RX_TOTAL_BYTES 0x09 + +/// +/// Transmit statistics. +/// +#define PXE_STATISTICS_TX_TOTAL_FRAMES 0x0A +#define PXE_STATISTICS_TX_GOOD_FRAMES 0x0B +#define PXE_STATISTICS_TX_UNDERSIZE_FRAMES 0x0C +#define PXE_STATISTICS_TX_OVERSIZE_FRAMES 0x0D +#define PXE_STATISTICS_TX_DROPPED_FRAMES 0x0E +#define PXE_STATISTICS_TX_UNICAST_FRAMES 0x0F +#define PXE_STATISTICS_TX_BROADCAST_FRAMES 0x10 +#define PXE_STATISTICS_TX_MULTICAST_FRAMES 0x11 +#define PXE_STATISTICS_TX_CRC_ERROR_FRAMES 0x12 +#define PXE_STATISTICS_TX_TOTAL_BYTES 0x13 + +/// +/// Number of collisions detection on this subnet. +/// +#define PXE_STATISTICS_COLLISIONS 0x14 + +/// +/// Number of frames destined for unsupported protocol. +/// +#define PXE_STATISTICS_UNSUPPORTED_PROTOCOL 0x15 + +/// +/// Number of valid frames received that were duplicated. +/// +#define PXE_STATISTICS_RX_DUPLICATED_FRAMES 0x16 + +/// +/// Number of encrypted frames received that failed to decrypt. +/// +#define PXE_STATISTICS_RX_DECRYPT_ERROR_FRAMES 0x17 + +/// +/// Number of frames that failed to transmit after exceeding the retry limit. +/// +#define PXE_STATISTICS_TX_ERROR_FRAMES 0x18 + +/// +/// Number of frames transmitted successfully after more than one attempt. +/// +#define PXE_STATISTICS_TX_RETRY_FRAMES 0x19 + +typedef struct s_pxe_cpb_mcast_ip_to_mac { + /// + /// Multicast IP address to be converted to multicast MAC address. + /// + PXE_IP_ADDR IP; +} PXE_CPB_MCAST_IP_TO_MAC; + +typedef struct s_pxe_db_mcast_ip_to_mac { + /// + /// Multicast MAC address. + /// + PXE_MAC_ADDR MAC; +} PXE_DB_MCAST_IP_TO_MAC; + +typedef struct s_pxe_cpb_nvdata_sparse { + /// + /// NvData item list. Only items in this list will be updated. + /// + struct { + /// + /// Non-volatile storage address to be changed. + /// + PXE_UINT32 Addr; + + /// + /// Data item to write into above storage address. + /// + union { + PXE_UINT8 Byte; + PXE_UINT16 Word; + PXE_UINT32 Dword; + } Data; + } Item[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_SPARSE; + +/// +/// When using bulk update, the size of the CPB structure must be +/// the same size as the non-volatile NIC storage. +/// +typedef union u_pxe_cpb_nvdata_bulk { + /// + /// Array of byte-wide data items. + /// + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + /// + /// Array of word-wide data items. + /// + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + /// + /// Array of dword-wide data items. + /// + PXE_UINT32 Dword[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_BULK; + +typedef struct s_pxe_db_nvdata { + /// + /// Arrays of data items from non-volatile storage. + /// + union { + /// + /// Array of byte-wide data items. + /// + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + /// + /// Array of word-wide data items. + /// + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + /// + /// Array of dword-wide data items. + /// + PXE_UINT32 Dword[MAX_EEPROM_LEN]; + } Data; +} PXE_DB_NVDATA; + +typedef struct s_pxe_db_get_status { + /// + /// Length of next receive frame (header + data). If this is zero, + /// there is no next receive frame available. + /// + PXE_UINT32 RxFrameLen; + + /// + /// Reserved, set to zero. + /// + PXE_UINT32 reserved; + + /// + /// Addresses of transmitted buffers that need to be recycled. + /// + PXE_UINT64 TxBuffer[MAX_XMIT_BUFFERS]; +} PXE_DB_GET_STATUS; + +typedef struct s_pxe_cpb_fill_header { + /// + /// Source and destination MAC addresses. These will be copied into + /// the media header without doing byte swapping. + /// + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + /// + /// Address of first byte of media header. The first byte of packet data + /// follows the last byte of the media header. + /// + PXE_UINT64 MediaHeader; + + /// + /// Length of packet data in bytes (not including the media header). + /// + PXE_UINT32 PacketLen; + + /// + /// Protocol type. This will be copied into the media header without + /// doing byte swapping. Protocol type numbers can be obtained from + /// the Assigned Numbers RFC 1700. + /// + PXE_UINT16 Protocol; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaHeaderLen; +} PXE_CPB_FILL_HEADER; + +#define PXE_PROTOCOL_ETHERNET_IP 0x0800 +#define PXE_PROTOCOL_ETHERNET_ARP 0x0806 +#define MAX_XMIT_FRAGMENTS 16 + +typedef struct s_pxe_cpb_fill_header_fragmented { + /// + /// Source and destination MAC addresses. These will be copied into + /// the media header without doing byte swapping. + /// + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + /// + /// Length of packet data in bytes (not including the media header). + /// + PXE_UINT32 PacketLen; + + /// + /// Protocol type. This will be copied into the media header without + /// doing byte swapping. Protocol type numbers can be obtained from + /// the Assigned Numbers RFC 1700. + /// + PXE_MEDIA_PROTOCOL Protocol; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaHeaderLen; + + /// + /// Number of packet fragment descriptors. + /// + PXE_UINT16 FragCnt; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT16 reserved; + + /// + /// Array of packet fragment descriptors. The first byte of the media + /// header is the first byte of the first fragment. + /// + struct { + /// + /// Address of this packet fragment. + /// + PXE_UINT64 FragAddr; + + /// + /// Length of this packet fragment. + /// + PXE_UINT32 FragLen; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} +PXE_CPB_FILL_HEADER_FRAGMENTED; + +typedef struct s_pxe_cpb_transmit { + /// + /// Address of first byte of frame buffer. This is also the first byte + /// of the media header. + /// + PXE_UINT64 FrameAddr; + + /// + /// Length of the data portion of the frame buffer in bytes. Do not + /// include the length of the media header. + /// + PXE_UINT32 DataLen; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaheaderLen; + + /// + /// Reserved, must be zero. + /// + PXE_UINT16 reserved; +} PXE_CPB_TRANSMIT; + +typedef struct s_pxe_cpb_transmit_fragments { + /// + /// Length of packet data in bytes (not including the media header). + /// + PXE_UINT32 FrameLen; + + /// + /// Length of the media header in bytes. + /// + PXE_UINT16 MediaheaderLen; + + /// + /// Number of packet fragment descriptors. + /// + PXE_UINT16 FragCnt; + + /// + /// Array of frame fragment descriptors. The first byte of the first + /// fragment is also the first byte of the media header. + /// + struct { + /// + /// Address of this frame fragment. + /// + PXE_UINT64 FragAddr; + + /// + /// Length of this frame fragment. + /// + PXE_UINT32 FragLen; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} +PXE_CPB_TRANSMIT_FRAGMENTS; + +typedef struct s_pxe_cpb_receive { + /// + /// Address of first byte of receive buffer. This is also the first byte + /// of the frame header. + /// + PXE_UINT64 BufferAddr; + + /// + /// Length of receive buffer. This must be large enough to hold the + /// received frame (media header + data). If the length of smaller than + /// the received frame, data will be lost. + /// + PXE_UINT32 BufferLen; + + /// + /// Reserved, must be set to zero. + /// + PXE_UINT32 reserved; +} PXE_CPB_RECEIVE; + +typedef struct s_pxe_db_receive { + /// + /// Source and destination MAC addresses from media header. + /// + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + /// + /// Length of received frame. May be larger than receive buffer size. + /// The receive buffer will not be overwritten. This is how to tell + /// if data was lost because the receive buffer was too small. + /// + PXE_UINT32 FrameLen; + + /// + /// Protocol type from media header. + /// + PXE_MEDIA_PROTOCOL Protocol; + + /// + /// Length of media header in received frame. + /// + PXE_UINT16 MediaHeaderLen; + + /// + /// Type of receive frame. + /// + PXE_FRAME_TYPE Type; + + /// + /// Reserved, must be zero. + /// + PXE_UINT8 reserved[7]; + +} PXE_DB_RECEIVE; + +#pragma pack() + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiSpec.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiSpec.h new file mode 100644 index 0000000..3adb6ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/Uefi/UefiSpec.h @@ -0,0 +1,2213 @@ +/** @file + Include file that supports UEFI. + + This include file must contain things defined in the UEFI 2.7 specification. + If a code construct is defined in the UEFI 2.7 specification it must be included + by this include file. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __UEFI_SPEC_H__ +#define __UEFI_SPEC_H__ + +#include + +#include +#include +#include +#include + +/// +/// Enumeration of EFI memory allocation types. +/// +typedef enum { + /// + /// Allocate any available range of pages that satisfies the request. + /// + AllocateAnyPages, + /// + /// Allocate any available range of pages whose uppermost address is less than + /// or equal to a specified maximum address. + /// + AllocateMaxAddress, + /// + /// Allocate pages at a specified address. + /// + AllocateAddress, + /// + /// Maximum enumeration value that may be used for bounds checking. + /// + MaxAllocateType +} EFI_ALLOCATE_TYPE; + +// +// Bit definitions for EFI_TIME.Daylight +// +#define EFI_TIME_ADJUST_DAYLIGHT 0x01 +#define EFI_TIME_IN_DAYLIGHT 0x02 + +/// +/// Value definition for EFI_TIME.TimeZone. +/// +#define EFI_UNSPECIFIED_TIMEZONE 0x07FF + +// +// Memory cacheability attributes +// +#define EFI_MEMORY_UC 0x0000000000000001ULL +#define EFI_MEMORY_WC 0x0000000000000002ULL +#define EFI_MEMORY_WT 0x0000000000000004ULL +#define EFI_MEMORY_WB 0x0000000000000008ULL +#define EFI_MEMORY_UCE 0x0000000000000010ULL +// +// Physical memory protection attributes +// +// Note: UEFI spec 2.5 and following: use EFI_MEMORY_RO as write-protected physical memory +// protection attribute. Also, EFI_MEMORY_WP means cacheability attribute. +// +#define EFI_MEMORY_WP 0x0000000000001000ULL +#define EFI_MEMORY_RP 0x0000000000002000ULL +#define EFI_MEMORY_XP 0x0000000000004000ULL +#define EFI_MEMORY_RO 0x0000000000020000ULL +// +// Physical memory persistence attribute. +// The memory region supports byte-addressable non-volatility. +// +#define EFI_MEMORY_NV 0x0000000000008000ULL +// +// The memory region provides higher reliability relative to other memory in the system. +// If all memory has the same reliability, then this bit is not used. +// +#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000ULL +// +// Runtime memory attribute +// +#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL + +/// +/// Memory descriptor version number. +/// +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +/// +/// Definition of an EFI memory descriptor. +/// +typedef struct { + /// + /// Type of the memory region. + /// Type EFI_MEMORY_TYPE is defined in the + /// AllocatePages() function description. + /// + UINT32 Type; + /// + /// Physical address of the first byte in the memory region. PhysicalStart must be + /// aligned on a 4 KiB boundary, and must not be above 0xfffffffffffff000. Type + /// EFI_PHYSICAL_ADDRESS is defined in the AllocatePages() function description + /// + EFI_PHYSICAL_ADDRESS PhysicalStart; + /// + /// Virtual address of the first byte in the memory region. + /// VirtualStart must be aligned on a 4 KiB boundary, + /// and must not be above 0xfffffffffffff000. + /// + EFI_VIRTUAL_ADDRESS VirtualStart; + /// + /// NumberOfPagesNumber of 4 KiB pages in the memory region. + /// NumberOfPages must not be 0, and must not be any value + /// that would represent a memory page with a start address, + /// either physical or virtual, above 0xfffffffffffff000. + /// + UINT64 NumberOfPages; + /// + /// Attributes of the memory region that describe the bit mask of capabilities + /// for that memory region, and not necessarily the current settings for that + /// memory region. + /// + UINT64 Attribute; +} EFI_MEMORY_DESCRIPTOR; + +/** + Allocates memory pages from the system. + + @param[in] Type The type of allocation to perform. + @param[in] MemoryType The type of memory to allocate. + MemoryType values in the range 0x70000000..0x7FFFFFFF + are reserved for OEM use. MemoryType values in the range + 0x80000000..0xFFFFFFFF are reserved for use by UEFI OS loaders + that are provided by operating system vendors. + @param[in] Pages The number of contiguous 4 KB pages to allocate. + @param[in, out] Memory The pointer to a physical address. On input, the way in which the address is + used depends on the value of Type. + + @retval EFI_SUCCESS The requested pages were allocated. + @retval EFI_INVALID_PARAMETER 1) Type is not AllocateAnyPages or + AllocateMaxAddress or AllocateAddress. + 2) MemoryType is in the range + EfiMaxMemoryType..0x6FFFFFFF. + 3) Memory is NULL. + 4) MemoryType is EfiPersistentMemory. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_NOT_FOUND The requested pages could not be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_PAGES)( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param[in] Memory The base physical address of the pages to be freed. + @param[in] Pages The number of contiguous 4 KB 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(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_PAGES)( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +/** + Returns the current memory map. + + @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the MemoryMap buffer. + On input, this is the size of the buffer allocated by the caller. + On output, it is the size of the buffer returned by the firmware if + the buffer was large enough, or the size of the buffer needed to contain + the map if the buffer was too small. + @param[in, out] MemoryMap A pointer to the buffer in which firmware places the current memory + map. + @param[out] MapKey A pointer to the location in which firmware returns the key for the + current memory map. + @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes, of + an individual EFI_MEMORY_DESCRIPTOR. + @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number + associated with the EFI_MEMORY_DESCRIPTOR. + + @retval EFI_SUCCESS The memory map was returned in the MemoryMap buffer. + @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current buffer size + needed to hold the memory map is returned in MemoryMapSize. + @retval EFI_INVALID_PARAMETER 1) MemoryMapSize is NULL. + 2) The MemoryMap buffer is not too small and MemoryMap is + NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_MAP)( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +/** + Allocates pool memory. + + @param[in] PoolType The type of pool to allocate. + MemoryType values in the range 0x70000000..0x7FFFFFFF + are reserved for OEM use. MemoryType values in the range + 0x80000000..0xFFFFFFFF are reserved for use by UEFI OS loaders + that are provided by operating system vendors. + @param[in] Size The number of bytes to allocate from the pool. + @param[out] Buffer A pointer to a pointer to the allocated buffer if the call succeeds; + undefined otherwise. + + @retval EFI_SUCCESS The requested number of bytes was allocated. + @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF. + PoolType is EfiPersistentMemory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_POOL)( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Returns pool memory to the system. + + @param[in] Buffer The pointer to the buffer to free. + + @retval EFI_SUCCESS The memory was returned to the system. + @retval EFI_INVALID_PARAMETER Buffer was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_POOL)( + IN VOID *Buffer + ); + +/** + Changes the runtime addressing mode of EFI firmware from physical to virtual. + + @param[in] MemoryMapSize The size in bytes of VirtualMap. + @param[in] DescriptorSize The size in bytes of an entry in the VirtualMap. + @param[in] DescriptorVersion The version of the structure entries in VirtualMap. + @param[in] VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. + + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP)( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR *VirtualMap + ); + +/** + Connects one or more drivers to a controller. + + @param[in] ControllerHandle The handle of the controller to which driver(s) are to be connected. + @param[in] DriverImageHandle A pointer to an ordered list handles that support the + EFI_DRIVER_BINDING_PROTOCOL. + @param[in] RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + @param[in] Recursive If TRUE, then ConnectController() is called recursively + until the entire tree of controllers below the controller specified + by ControllerHandle have been created. If FALSE, then + the tree of controllers is only expanded one level. + + @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle. + 2) No drivers were connected to ControllerHandle, but + RemainingDevicePath is not NULL, and it is an End Device + Path Node. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances + present in the system. + 2) No drivers were connected to ControllerHandle. + @retval EFI_SECURITY_VIOLATION + The user has no permission to start UEFI device drivers on the device path + associated with the ControllerHandle or specified by the RemainingDevicePath. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONNECT_CONTROLLER)( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle, OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, OPTIONAL + IN BOOLEAN Recursive + ); + +/** + Disconnects one or more drivers from a controller. + + @param[in] ControllerHandle The handle of the controller from which driver(s) are to be disconnected. + @param[in] DriverImageHandle The driver to disconnect from ControllerHandle. + If DriverImageHandle is NULL, then all the drivers currently managing + ControllerHandle are disconnected from ControllerHandle. + @param[in] ChildHandle The handle of the child to destroy. + If ChildHandle is NULL, then all the children of ControllerHandle are + destroyed before the drivers are disconnected from ControllerHandle. + + @retval EFI_SUCCESS 1) One or more drivers were disconnected from the controller. + 2) On entry, no drivers are managing ControllerHandle. + 3) DriverImageHandle is not NULL, and on entry + DriverImageHandle is not managing ControllerHandle. + @retval EFI_INVALID_PARAMETER 1) ControllerHandle is NULL. + 2) DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE. + 3) ChildHandle is not NULL, and it is not a valid EFI_HANDLE. + 4) DriverImageHandle does not support the EFI_DRIVER_BINDING_PROTOCOL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to disconnect any drivers from + ControllerHandle. + @retval EFI_DEVICE_ERROR The controller could not be disconnected because of a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISCONNECT_CONTROLLER)( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle, OPTIONAL + IN EFI_HANDLE ChildHandle OPTIONAL + ); + + + +// +// ConvertPointer DebugDisposition type. +// +#define EFI_OPTIONAL_PTR 0x00000001 + +/** + Determines the new virtual address that is to be used on subsequent memory accesses. + + @param[in] DebugDisposition Supplies type information for the pointer being converted. + @param[in, out] Address A pointer to a pointer that is to be fixed to be the value needed + for the new virtual address mappings being applied. + + @retval EFI_SUCCESS The pointer pointed to by Address was modified. + @retval EFI_INVALID_PARAMETER 1) Address is NULL. + 2) *Address is NULL and DebugDisposition does + not have the EFI_OPTIONAL_PTR bit set. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONVERT_POINTER)( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ); + + +// +// These types can be ORed together as needed - for example, +// EVT_TIMER might be Ored with EVT_NOTIFY_WAIT or +// EVT_NOTIFY_SIGNAL. +// +#define EVT_TIMER 0x80000000 +#define EVT_RUNTIME 0x40000000 +#define EVT_NOTIFY_WAIT 0x00000100 +#define EVT_NOTIFY_SIGNAL 0x00000200 + +#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +// +// The event's NotifyContext pointer points to a runtime memory +// address. +// The event is deprecated in UEFI2.0 and later specifications. +// +#define EVT_RUNTIME_CONTEXT 0x20000000 + + +/** + Invoke a notification event + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +typedef +VOID +(EFIAPI *EFI_EVENT_NOTIFY)( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Creates an event. + + @param[in] Type The type of event to create and its mode and attributes. + @param[in] NotifyTpl The task priority level of event notifications, if needed. + @param[in] NotifyFunction The pointer to the event's notification function, if any. + @param[in] NotifyContext The pointer to the notification function's context; corresponds to parameter + Context in the notification function. + @param[out] Event The pointer to the newly created event if the call succeeds; undefined + otherwise. + + @retval EFI_SUCCESS The event structure was created. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The event could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT)( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT EFI_EVENT *Event + ); + +/** + Creates an event in a group. + + @param[in] Type The type of event to create and its mode and attributes. + @param[in] NotifyTpl The task priority level of event notifications,if needed. + @param[in] NotifyFunction The pointer to the event's notification function, if any. + @param[in] NotifyContext The pointer to the notification function's context; corresponds to parameter + Context in the notification function. + @param[in] EventGroup The pointer to the unique identifier of the group to which this event belongs. + If this is NULL, then the function behaves as if the parameters were passed + to CreateEvent. + @param[out] Event The pointer to the newly created event if the call succeeds; undefined + otherwise. + + @retval EFI_SUCCESS The event structure was created. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The event could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT_EX)( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, + IN CONST VOID *NotifyContext OPTIONAL, + IN CONST EFI_GUID *EventGroup OPTIONAL, + OUT EFI_EVENT *Event + ); + +/// +/// Timer delay types +/// +typedef enum { + /// + /// An event's timer settings is to be cancelled and not trigger time is to be set/ + /// + TimerCancel, + /// + /// An event is to be signaled periodically at a specified interval from the current time. + /// + TimerPeriodic, + /// + /// An event is to be signaled once at a specified interval from the current time. + /// + TimerRelative +} EFI_TIMER_DELAY; + +/** + Sets the type of timer and the trigger time for a timer event. + + @param[in] Event The timer event that is to be signaled at the specified time. + @param[in] Type The type of time that is specified in TriggerTime. + @param[in] TriggerTime The number of 100ns units until the timer expires. + A TriggerTime of 0 is legal. + If Type is TimerRelative and TriggerTime is 0, then the timer + event will be signaled on the next timer tick. + If Type is TimerPeriodic and TriggerTime is 0, then the timer + event will be signaled on every timer tick. + + @retval EFI_SUCCESS The event has been set to be signaled at the requested time. + @retval EFI_INVALID_PARAMETER Event or Type is not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIMER)( + IN EFI_EVENT Event, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ); + +/** + Signals an event. + + @param[in] Event The event to signal. + + @retval EFI_SUCCESS The event has been signaled. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIGNAL_EVENT)( + IN EFI_EVENT Event + ); + +/** + Stops execution until an event is signaled. + + @param[in] NumberOfEvents The number of events in the Event array. + @param[in] Event An array of EFI_EVENT. + @param[out] Index The pointer to the index of the event which satisfied the wait condition. + + @retval EFI_SUCCESS The event indicated by Index was signaled. + @retval EFI_INVALID_PARAMETER 1) NumberOfEvents is 0. + 2) The event indicated by Index is of type + EVT_NOTIFY_SIGNAL. + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WAIT_FOR_EVENT)( + IN UINTN NumberOfEvents, + IN EFI_EVENT *Event, + OUT UINTN *Index + ); + +/** + Closes an event. + + @param[in] Event The event to close. + + @retval EFI_SUCCESS The event has been closed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_EVENT)( + IN EFI_EVENT Event + ); + +/** + Checks whether an event is in the signaled state. + + @param[in] Event The event to check. + + @retval EFI_SUCCESS The event is in the signaled state. + @retval EFI_NOT_READY The event is not in the signaled state. + @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CHECK_EVENT)( + IN EFI_EVENT Event + ); + + +// +// Task priority level +// +#define TPL_APPLICATION 4 +#define TPL_CALLBACK 8 +#define TPL_NOTIFY 16 +#define TPL_HIGH_LEVEL 31 + + +/** + Raises a task's priority level and returns its previous level. + + @param[in] NewTpl The new task priority level. + + @return Previous task priority level + +**/ +typedef +EFI_TPL +(EFIAPI *EFI_RAISE_TPL)( + IN EFI_TPL NewTpl + ); + +/** + Restores a task's priority level to its previous value. + + @param[in] OldTpl The previous task priority level to restore. + +**/ +typedef +VOID +(EFIAPI *EFI_RESTORE_TPL)( + IN EFI_TPL OldTpl + ); + +/** + Returns the value of a variable. + + @param[in] VariableName A Null-terminated string that is the name of the vendor's + variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[out] Attributes If not NULL, a pointer to the memory location to return the + attributes bitmask for the variable. + @param[in, out] DataSize On input, the size in bytes of the return Data buffer. + On output the size of data returned in Data. + @param[out] Data The buffer to return the contents of the variable. May be NULL + with a zero DataSize in order to determine the size buffer needed. + + @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. + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_VARIABLE)( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + Enumerates the current variable names. + + @param[in, out] VariableNameSize The size of the VariableName buffer. The size must be large + enough to fit input string supplied in VariableName buffer. + @param[in, out] VariableName On input, supplies the last VariableName that was returned + by GetNextVariableName(). On output, returns the Nullterminated + string of the current variable. + @param[in, out] VendorGuid On input, supplies the last VendorGuid that was returned by + GetNextVariableName(). On 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_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and + GUID of an existing variable. + @retval EFI_INVALID_PARAMETER Null-terminator is not found in the first VariableNameSize bytes of + the input VariableName buffer. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME)( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + +/** + Sets the value of a variable. + + @param[in] VariableName A Null-terminated string that is the name of the vendor's variable. + Each VariableName is unique for each VendorGuid. VariableName must + contain 1 or more characters. If VariableName is an empty string, + then EFI_INVALID_PARAMETER is returned. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] Attributes Attributes bitmask to set for the variable. + @param[in] DataSize The size in bytes of the Data buffer. Unless the EFI_VARIABLE_APPEND_WRITE or + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a size of zero + causes the variable to be deleted. When the EFI_VARIABLE_APPEND_WRITE attribute is + set, then a SetVariable() call with a DataSize of zero will not cause any change to + the variable value (the timestamp associated with the variable may be updated however + even if no new data value is provided,see the description of the + EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the DataSize will not + be zero since the EFI_VARIABLE_AUTHENTICATION_2 descriptor will be populated). + @param[in] Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied, or the + DataSize exceeds the maximum allowed. + @retval EFI_INVALID_PARAMETER VariableName is an empty string. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. + @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, + but the AuthInfo does NOT pass the validation check carried out by the firmware. + + @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VARIABLE)( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + + +/// +/// This provides the capabilities of the +/// real time clock device as exposed through the EFI interfaces. +/// +typedef struct { + /// + /// Provides the reporting resolution of the real-time clock device in + /// counts per second. For a normal PC-AT CMOS RTC device, this + /// value would be 1 Hz, or 1, to indicate that the device only reports + /// the time to the resolution of 1 second. + /// + UINT32 Resolution; + /// + /// Provides the timekeeping accuracy of the real-time clock in an + /// error rate of 1E-6 parts per million. For a clock with an accuracy + /// of 50 parts per million, the value in this field would be + /// 50,000,000. + /// + UINT32 Accuracy; + /// + /// A TRUE indicates that a time set operation clears the device's + /// time below the Resolution reporting level. A FALSE + /// indicates that the state below the Resolution level of the + /// device is not cleared when the time is set. Normal PC-AT CMOS + /// RTC devices set this value to FALSE. + /// + BOOLEAN SetsToZero; +} EFI_TIME_CAPABILITIES; + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param[out] Time A pointer to storage to receive a snapshot of the current time. + @param[out] 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 hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_TIME)( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ); + +/** + Sets the current local time and date information. + + @param[in] Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIME)( + IN EFI_TIME *Time + ); + +/** + Returns the current wakeup alarm clock setting. + + @param[out] Enabled Indicates if the alarm is currently enabled or disabled. + @param[out] Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param[out] Time The current alarm setting. + + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_WAKEUP_TIME)( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + +/** + Sets the system wakeup alarm clock time. + + @param[in] Enable Enable or disable the wakeup alarm. + @param[in] Time If Enable is TRUE, the time to set the wakeup alarm for. + If Enable is FALSE, then this parameter is optional, and may be NULL. + + @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. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WAKEUP_TIME)( + IN BOOLEAN Enable, + IN EFI_TIME *Time OPTIONAL + ); + +/** + Loads an EFI image into memory. + + @param[in] BootPolicy 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. Ignored if SourceBuffer is + not NULL. + @param[in] ParentImageHandle The caller's image handle. + @param[in] DevicePath The DeviceHandle specific file path from which the image is + loaded. + @param[in] SourceBuffer If not NULL, a pointer to the memory location containing a copy + of the image to be loaded. + @param[in] SourceSize The size in bytes of SourceBuffer. Ignored if SourceBuffer is NULL. + @param[out] ImageHandle The pointer to the returned image handle that is created when the + image is successfully loaded. + + @retval EFI_SUCCESS Image was loaded into memory correctly. + @retval EFI_NOT_FOUND Both SourceBuffer and DevicePath are NULL. + @retval EFI_INVALID_PARAMETER One or more parametes are invalid. + @retval EFI_UNSUPPORTED The image type is not supported. + @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient resources. + @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not + understood. + @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error. + @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the + image from being loaded. NULL is returned in *ImageHandle. + @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a + valid EFI_LOADED_IMAGE_PROTOCOL. However, the current + platform policy specifies that the image should not be started. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_LOAD)( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ); + +/** + Transfers control to a loaded image's entry point. + + @param[in] ImageHandle Handle of image to be started. + @param[out] ExitDataSize The pointer to the size, in bytes, of ExitData. + @param[out] ExitData The pointer to a pointer to a data buffer that includes a Null-terminated + string, optionally followed by additional binary data. + + @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle or the image + has already been initialized with StartImage. + @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started. + @return Exit code from image + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_START)( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +/** + Terminates a loaded EFI image and returns control to boot services. + + @param[in] ImageHandle Handle that identifies the image. This parameter is passed to the + image on entry. + @param[in] ExitStatus The image's exit code. + @param[in] ExitDataSize The size, in bytes, of ExitData. Ignored if ExitStatus is EFI_SUCCESS. + @param[in] ExitData The pointer to a data buffer that includes 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 image's exit. ExitData is only valid if ExitStatus + is something other than EFI_SUCCESS. The ExitData buffer + must be allocated by calling AllocatePool(). + + @retval EFI_SUCCESS The image specified by ImageHandle was unloaded. + @retval EFI_INVALID_PARAMETER The image specified by ImageHandle has been loaded and + started with LoadImage() and StartImage(), but the + image is not the currently executing image. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT)( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ); + +/** + Unloads an image. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_UNLOAD)( + IN EFI_HANDLE ImageHandle + ); + +/** + Terminates all boot services. + + @param[in] ImageHandle Handle that identifies the exiting image. + @param[in] MapKey Key to the latest memory map. + + @retval EFI_SUCCESS Boot services have been terminated. + @retval EFI_INVALID_PARAMETER MapKey is incorrect. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT_BOOT_SERVICES)( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ); + +/** + Induces a fine-grained stall. + + @param[in] Microseconds The number of microseconds to stall execution. + + @retval EFI_SUCCESS Execution was stalled at least the requested number of + Microseconds. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_STALL)( + IN UINTN Microseconds + ); + +/** + Sets the system's watchdog timer. + + @param[in] Timeout The number of seconds to set the watchdog timer to. + @param[in] WatchdogCode The numeric code to log on a watchdog timer timeout event. + @param[in] DataSize The size, in bytes, of WatchdogData. + @param[in] WatchdogData A data buffer that includes a Null-terminated string, optionally + followed by additional binary data. + + @retval EFI_SUCCESS The timeout has been set. + @retval EFI_INVALID_PARAMETER The supplied WatchdogCode is invalid. + @retval EFI_UNSUPPORTED The system does not have a watchdog timer. + @retval EFI_DEVICE_ERROR The watchdog timer could not be programmed due to a hardware + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WATCHDOG_TIMER)( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ); + +/** + 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. ResetData is only + valid if ResetStatus is something other than EFI_SUCCESS + unless the ResetType is EfiResetPlatformSpecific + where a minimum amount of ResetData is always required. + For a ResetType of EfiResetPlatformSpecific the data buffer + also starts with a Null-terminated string that is followed + by an EFI_GUID that describes the specific type of reset to perform. +**/ +typedef +VOID +(EFIAPI *EFI_RESET_SYSTEM)( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ); + +/** + Returns a monotonically increasing count for the platform. + + @param[out] Count The pointer to returned value. + + @retval EFI_SUCCESS The next monotonic count was returned. + @retval EFI_INVALID_PARAMETER Count is NULL. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT)( + OUT UINT64 *Count + ); + +/** + Returns the next high 32 bits of the platform's monotonic counter. + + @param[out] HighCount The pointer to returned value. + + @retval EFI_SUCCESS The next high monotonic count was returned. + @retval EFI_INVALID_PARAMETER HighCount is NULL. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT)( + OUT UINT32 *HighCount + ); + +/** + Computes and returns a 32-bit CRC for a data buffer. + + @param[in] Data A pointer to the buffer on which the 32-bit CRC is to be computed. + @param[in] DataSize The number of bytes in the buffer Data. + @param[out] Crc32 The 32-bit CRC that was computed for the data buffer specified by Data + and DataSize. + + @retval EFI_SUCCESS The 32-bit CRC was computed for the data buffer and returned in + Crc32. + @retval EFI_INVALID_PARAMETER Data is NULL. + @retval EFI_INVALID_PARAMETER Crc32 is NULL. + @retval EFI_INVALID_PARAMETER DataSize is 0. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CALCULATE_CRC32)( + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *Crc32 + ); + +/** + Copies the contents of one buffer to another buffer. + + @param[in] Destination The pointer to the destination buffer of the memory copy. + @param[in] Source The pointer to the source buffer of the memory copy. + @param[in] Length Number of bytes to copy from Source to Destination. + +**/ +typedef +VOID +(EFIAPI *EFI_COPY_MEM)( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +/** + The SetMem() function fills a buffer with a specified value. + + @param[in] Buffer The pointer to the buffer to fill. + @param[in] Size Number of bytes in Buffer to fill. + @param[in] Value Value to fill Buffer with. + +**/ +typedef +VOID +(EFIAPI *EFI_SET_MEM)( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +/// +/// Enumeration of EFI Interface Types +/// +typedef enum { + /// + /// Indicates that the supplied protocol interface is supplied in native form. + /// + EFI_NATIVE_INTERFACE +} EFI_INTERFACE_TYPE; + +/** + Installs a protocol interface on a device handle. If the handle does not exist, it is created and added + to the list of handles in the system. InstallMultipleProtocolInterfaces() performs + more error checking than InstallProtocolInterface(), so it is recommended that + InstallMultipleProtocolInterfaces() be used in place of + InstallProtocolInterface() + + @param[in, out] Handle A pointer to the EFI_HANDLE on which the interface is to be installed. + @param[in] Protocol The numeric ID of the protocol interface. + @param[in] InterfaceType Indicates whether Interface is supplied in native form. + @param[in] Interface A pointer to the protocol interface. + + @retval EFI_SUCCESS The protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES Space for a new handle could not be allocated. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER InterfaceType is not EFI_NATIVE_INTERFACE. + @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE)( + IN OUT EFI_HANDLE *Handle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ); + +/** + Installs one or more protocol interfaces into the boot services environment. + + @param[in, out] Handle The pointer to a handle to install the new protocol interfaces on, + or a pointer to NULL if a new handle is to be allocated. + @param ... A variable argument list containing pairs of protocol GUIDs and protocol + interfaces. + + @retval EFI_SUCCESS All the protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in + the handle database. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES)( + IN OUT EFI_HANDLE *Handle, + ... + ); + +/** + Reinstalls a protocol interface on a device handle. + + @param[in] Handle Handle on which the interface is to be reinstalled. + @param[in] Protocol The numeric ID of the interface. + @param[in] OldInterface A pointer to the old interface. NULL can be used if a structure is not + associated with Protocol. + @param[in] NewInterface A pointer to the new interface. + + @retval EFI_SUCCESS The protocol interface was reinstalled. + @retval EFI_NOT_FOUND The OldInterface on the handle was not found. + @retval EFI_ACCESS_DENIED The protocol interface could not be reinstalled, + because OldInterface is still being used by a + driver that will not release it. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ); + +/** + Removes a protocol interface from a device handle. It is recommended that + UninstallMultipleProtocolInterfaces() be used in place of + UninstallProtocolInterface(). + + @param[in] Handle The handle on which the interface was installed. + @param[in] Protocol The numeric ID of the interface. + @param[in] Interface A pointer to the interface. + + @retval EFI_SUCCESS The interface was removed. + @retval EFI_NOT_FOUND The interface was not found. + @retval EFI_ACCESS_DENIED The interface was not removed because the interface + is still being used by a driver. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +/** + Removes one or more protocol interfaces into the boot services environment. + + @param[in] Handle The handle to remove the protocol interfaces from. + @param ... A variable argument list containing pairs of protocol GUIDs and + protocol interfaces. + + @retval EFI_SUCCESS All the protocol interfaces were removed. + @retval EFI_INVALID_PARAMETER One of the protocol interfaces was not previously installed on Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES)( + IN EFI_HANDLE Handle, + ... + ); + +/** + Queries a handle to determine if it supports a specified protocol. + + @param[in] Handle The handle being queried. + @param[in] Protocol The published unique identifier of the protocol. + @param[out] Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + + @retval EFI_SUCCESS The interface information for the specified protocol was returned. + @retval EFI_UNSUPPORTED The device does not support the specified protocol. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER Interface is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HANDLE_PROTOCOL)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ); + +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +/** + Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the + handle, it opens the protocol on behalf of the calling agent. + + @param[in] Handle The handle for the protocol interface that is being opened. + @param[in] Protocol The published unique identifier of the protocol. + @param[out] Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + @param[in] AgentHandle The handle of the agent that is opening the protocol interface + specified by Protocol and Interface. + @param[in] ControllerHandle If the agent that is opening a protocol is a driver that follows the + UEFI Driver Model, then this parameter is the controller handle + that requires the protocol interface. If the agent does not follow + the UEFI Driver Model, then this parameter is optional and may + be NULL. + @param[in] Attributes The open mode of the protocol interface specified by Handle + and Protocol. + + @retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the + protocol interface was returned in Interface. + @retval EFI_UNSUPPORTED Handle does not support Protocol. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment. + @retval EFI_ALREADY_STARTED Item on the open list already has requierd attributes whose agent + handle is the same as AgentHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface, OPTIONAL + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ); + + +/** + Closes a protocol on a handle that was opened using OpenProtocol(). + + @param[in] Handle The handle for the protocol interface that was previously opened + with OpenProtocol(), and is now being closed. + @param[in] Protocol The published unique identifier of the protocol. + @param[in] AgentHandle The handle of the agent that is closing the protocol interface. + @param[in] ControllerHandle If the agent that opened a protocol is a driver that follows the + UEFI Driver Model, then this parameter is the controller handle + that required the protocol interface. + + @retval EFI_SUCCESS The protocol instance was closed. + @retval EFI_INVALID_PARAMETER 1) Handle is NULL. + 2) AgentHandle is NULL. + 3) ControllerHandle is not NULL and ControllerHandle is not a valid EFI_HANDLE. + 4) Protocol is NULL. + @retval EFI_NOT_FOUND 1) Handle does not support the protocol specified by Protocol. + 2) The protocol interface specified by Handle and Protocol is not + currently open by AgentHandle and ControllerHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_PROTOCOL)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ); + +/// +/// EFI Oprn Protocol Information Entry +/// +typedef struct { + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +/** + Retrieves the list of agents that currently have a protocol interface opened. + + @param[in] Handle The handle for the protocol interface that is being queried. + @param[in] Protocol The published unique identifier of the protocol. + @param[out] EntryBuffer A pointer to a buffer of open protocol information in the form of + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + @param[out] EntryCount A pointer to the number of entries in EntryBuffer. + + @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, and the + number of entries was returned EntryCount. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer. + @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION)( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ); + +/** + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + + @param[in] Handle The handle from which to retrieve the list of protocol interface + GUIDs. + @param[out] ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are + installed on Handle. + @param[out] ProtocolBufferCount A pointer to the number of GUID pointers present in + ProtocolBuffer. + + @retval EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in + ProtocolBuffer. The number of protocol interface GUIDs was + returned in ProtocolBufferCount. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results. + @retval EFI_INVALID_PARAMETER Handle is NULL. + @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL. + @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PROTOCOLS_PER_HANDLE)( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ); + +/** + Creates an event that is to be signaled whenever an interface is installed for a specified protocol. + + @param[in] Protocol The numeric ID of the protocol for which the event is to be registered. + @param[in] Event Event that is to be signaled whenever a protocol interface is registered + for Protocol. + @param[out] Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS The notification event has been registered. + @retval EFI_OUT_OF_RESOURCES Space for the notification event could not be allocated. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER Event is NULL. + @retval EFI_INVALID_PARAMETER Registration is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY)( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ); + +/// +/// Enumeration of EFI Locate Search Types +/// +typedef enum { + /// + /// Retrieve all the handles in the handle database. + /// + AllHandles, + /// + /// Retrieve the next handle fron a RegisterProtocolNotify() event. + /// + ByRegisterNotify, + /// + /// Retrieve the set of handles from the handle database that support a + /// specified protocol. + /// + ByProtocol +} EFI_LOCATE_SEARCH_TYPE; + +/** + Returns an array of handles that support a specified protocol. + + @param[in] SearchType Specifies which handle(s) are to be returned. + @param[in] Protocol Specifies the protocol to search by. + @param[in] SearchKey Specifies the search key. + @param[in, out] BufferSize On input, the size in bytes of Buffer. On output, the size in bytes of + the array returned in Buffer (if the buffer was large enough) or the + size, in bytes, of the buffer needed to obtain the array (if the buffer was + not large enough). + @param[out] Buffer The buffer in which the array is returned. + + @retval EFI_SUCCESS The array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. + @retval EFI_INVALID_PARAMETER SearchType is not a member of EFI_LOCATE_SEARCH_TYPE. + @retval EFI_INVALID_PARAMETER SearchType is ByRegisterNotify and SearchKey is NULL. + @retval EFI_INVALID_PARAMETER SearchType is ByProtocol and Protocol is NULL. + @retval EFI_INVALID_PARAMETER One or more matches are found and BufferSize is NULL. + @retval EFI_INVALID_PARAMETER BufferSize is large enough for the result and Buffer is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE)( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ); + +/** + Locates the handle to a device on the device path that supports the specified protocol. + + @param[in] Protocol Specifies the protocol to search for. + @param[in, out] DevicePath On input, a pointer to a pointer to the device path. On output, the device + path pointer is modified to point to the remaining part of the device + path. + @param[out] Device A pointer to the returned device handle. + + @retval EFI_SUCCESS The resulting handle was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_INVALID_PARAMETER Protocol is NULL. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_DEVICE_PATH)( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device + ); + +/** + Adds, updates, or removes a configuration table entry from the EFI System Table. + + @param[in] Guid A pointer to the GUID for the entry to add, update, or remove. + @param[in] Table A pointer to the configuration table for the entry to add, update, or + remove. May be NULL. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_NOT_FOUND An attempt was made to delete a nonexistent entry. + @retval EFI_INVALID_PARAMETER Guid is NULL. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE)( + IN EFI_GUID *Guid, + IN VOID *Table + ); + +/** + Returns an array of handles that support the requested protocol in a buffer allocated from pool. + + @param[in] SearchType Specifies which handle(s) are to be returned. + @param[in] Protocol Provides the protocol to search by. + This parameter is only valid for a SearchType of ByProtocol. + @param[in] SearchKey Supplies the search key depending on the SearchType. + @param[in, out] NoHandles The number of handles returned in Buffer. + @param[out] Buffer A pointer to the buffer to return the requested array of handles that + support Protocol. + + @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of + handles in Buffer was returned in NoHandles. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results. + @retval EFI_INVALID_PARAMETER NoHandles is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE_BUFFER)( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ); + +/** + Returns the first protocol instance that matches the given protocol. + + @param[in] Protocol Provides the protocol to search for. + @param[in] Registration Optional registration key returned from + RegisterProtocolNotify(). + @param[out] Interface On return, a pointer to the first interface that matches Protocol and + Registration. + + @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in + Interface. + @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and + Registration. + @retval EFI_INVALID_PARAMETER Interface is NULL. + Protocol is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_PROTOCOL)( + IN EFI_GUID *Protocol, + IN VOID *Registration, OPTIONAL + OUT VOID **Interface + ); + +/// +/// EFI Capsule Block Descriptor +/// +typedef struct { + /// + /// Length in bytes of the data pointed to by DataBlock/ContinuationPointer. + /// + UINT64 Length; + union { + /// + /// Physical address of the data block. This member of the union is + /// used if Length is not equal to zero. + /// + EFI_PHYSICAL_ADDRESS DataBlock; + /// + /// Physical address of another block of + /// EFI_CAPSULE_BLOCK_DESCRIPTOR structures. This + /// member of the union is used if Length is equal to zero. If + /// ContinuationPointer is zero this entry represents the end of the list. + /// + EFI_PHYSICAL_ADDRESS ContinuationPointer; + } Union; +} EFI_CAPSULE_BLOCK_DESCRIPTOR; + +/// +/// EFI Capsule Header. +/// +typedef struct { + /// + /// A GUID that defines the contents of a capsule. + /// + EFI_GUID CapsuleGuid; + /// + /// The size of the capsule header. This may be larger than the size of + /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply + /// extended header entries + /// + UINT32 HeaderSize; + /// + /// Bit-mapped list describing the capsule attributes. The Flag values + /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values + /// of 0x10000 - 0xFFFFFFFF are defined by this specification + /// + UINT32 Flags; + /// + /// Size in bytes of the capsule. + /// + UINT32 CapsuleImageSize; +} EFI_CAPSULE_HEADER; + +/// +/// The EFI System Table entry must point to an array of capsules +/// that contain the same CapsuleGuid value. The array must be +/// prefixed by a UINT32 that represents the size of the array of capsules. +/// +typedef struct { + /// + /// the size of the array of capsules. + /// + UINT32 CapsuleArrayNumber; + /// + /// Point to an array of capsules that contain the same CapsuleGuid value. + /// + VOID* CapsulePtr[1]; +} EFI_CAPSULE_TABLE; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 +#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 + +/** + 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[in] CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. + @param[in] CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param[in] ScatterGatherList Physical pointer to a set of + EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the + location in physical memory of a set of capsules. + + @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 is NULL, or an incompatible set of flags were + set in the capsule header. + @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 When ExitBootServices() has been previously called this error indicates the capsule + is compatible with this platform but is not capable of being submitted or processed + in runtime. The caller may resubmit the capsule prior to ExitBootServices(). + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has not been previously called then this error indicates + the capsule is compatible with this platform but there are insufficient resources to process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UPDATE_CAPSULE)( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +/** + Returns if the capsule can be supported via UpdateCapsule(). + + @param[in] CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. + @param[in] CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param[out] MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can + support as an argument to UpdateCapsule() via + CapsuleHeaderArray and ScatterGatherList. + @param[out] ResetType Returns the type of reset required for the capsule update. + + @retval EFI_SUCCESS Valid answer returned. + @retval EFI_UNSUPPORTED The capsule type is not supported on this platform, and + MaximumCapsuleSize and ResetType are undefined. + @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL. + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has been previously called this error indicates the capsule + is compatible with this platform but is not capable of being submitted or processed + in runtime. The caller may resubmit the capsule prior to ExitBootServices(). + @retval EFI_OUT_OF_RESOURCES When ExitBootServices() has not been previously called then this error indicates + the capsule is compatible with this platform but there are insufficient resources to process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES)( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +/** + Returns information about the EFI variables. + + @param[in] Attributes Attributes bitmask to specify the type of variables on + which to return information. + @param[out] MaximumVariableStorageSize On output the maximum size of the storage space + available for the EFI variables associated with the + attributes specified. + @param[out] RemainingVariableStorageSize Returns the remaining size of the storage space + available for the EFI variables associated with the + attributes specified. + @param[out] MaximumVariableSize Returns the maximum size of the individual EFI + variables associated with the attributes specified. + + @retval EFI_SUCCESS Valid answer returned. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied + @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the + MaximumVariableStorageSize, + RemainingVariableStorageSize, MaximumVariableSize + are undefined. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_VARIABLE_INFO)( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ); + +// +// Firmware should stop at a firmware user interface on next boot +// +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 +#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED 0x0000000000000004 +#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED 0x0000000000000008 +#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED 0x0000000000000010 +#define EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY 0x0000000000000040 + +// +// EFI Runtime Services Table +// +#define EFI_SYSTEM_TABLE_SIGNATURE SIGNATURE_64 ('I','B','I',' ','S','Y','S','T') +#define EFI_2_70_SYSTEM_TABLE_REVISION ((2 << 16) | (70)) +#define EFI_2_60_SYSTEM_TABLE_REVISION ((2 << 16) | (60)) +#define EFI_2_50_SYSTEM_TABLE_REVISION ((2 << 16) | (50)) +#define EFI_2_40_SYSTEM_TABLE_REVISION ((2 << 16) | (40)) +#define EFI_2_31_SYSTEM_TABLE_REVISION ((2 << 16) | (31)) +#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) +#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) +#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) +#define EFI_SYSTEM_TABLE_REVISION EFI_2_70_SYSTEM_TABLE_REVISION +#define EFI_SPECIFICATION_VERSION EFI_SYSTEM_TABLE_REVISION + +#define EFI_RUNTIME_SERVICES_SIGNATURE SIGNATURE_64 ('R','U','N','T','S','E','R','V') +#define EFI_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_VERSION + +/// +/// EFI Runtime Services Table. +/// +typedef struct { + /// + /// The table header for the EFI Runtime Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // Time Services + // + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + + // + // Virtual Memory Services + // + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + + // + // Variable Services + // + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + + // + // Miscellaneous Services + // + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + + // + // UEFI 2.0 Capsule Services + // + EFI_UPDATE_CAPSULE UpdateCapsule; + EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; + + // + // Miscellaneous UEFI 2.0 Service + // + EFI_QUERY_VARIABLE_INFO QueryVariableInfo; +} EFI_RUNTIME_SERVICES; + + +#define EFI_BOOT_SERVICES_SIGNATURE SIGNATURE_64 ('B','O','O','T','S','E','R','V') +#define EFI_BOOT_SERVICES_REVISION EFI_SPECIFICATION_VERSION + +/// +/// EFI Boot Services Table. +/// +typedef struct { + /// + /// The table header for the EFI Boot Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // Task Priority Services + // + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory Services + // + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & Timer Services + // + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol Handler Services + // + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + VOID *Reserved; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image Services + // + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Miscellaneous Services + // + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // DriverSupport Services + // + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Open and Close Protocol Services + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Library Services + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; + + // + // 32-bit CRC Services + // + EFI_CALCULATE_CRC32 CalculateCrc32; + + // + // Miscellaneous Services + // + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; + EFI_CREATE_EVENT_EX CreateEventEx; +} EFI_BOOT_SERVICES; + +/// +/// Contains a set of GUID/pointer pairs comprised of the ConfigurationTable field in the +/// EFI System Table. +/// +typedef struct { + /// + /// The 128-bit GUID value that uniquely identifies the system configuration table. + /// + EFI_GUID VendorGuid; + /// + /// A pointer to the table associated with VendorGuid. + /// + VOID *VendorTable; +} EFI_CONFIGURATION_TABLE; + +/// +/// EFI System Table +/// +typedef struct { + /// + /// The table header for the EFI System Table. + /// + EFI_TABLE_HEADER Hdr; + /// + /// A pointer to a null terminated string that identifies the vendor + /// that produces the system firmware for the platform. + /// + CHAR16 *FirmwareVendor; + /// + /// A firmware vendor specific value that identifies the revision + /// of the system firmware for the platform. + /// + UINT32 FirmwareRevision; + /// + /// The handle for the active console input device. This handle must support + /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL. + /// + EFI_HANDLE ConsoleInHandle; + /// + /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is + /// associated with ConsoleInHandle. + /// + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + /// + /// The handle for the active console output device. + /// + EFI_HANDLE ConsoleOutHandle; + /// + /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface + /// that is associated with ConsoleOutHandle. + /// + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + /// + /// The handle for the active standard error console device. + /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. + /// + EFI_HANDLE StandardErrorHandle; + /// + /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface + /// that is associated with StandardErrorHandle. + /// + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; + /// + /// A pointer to the EFI Runtime Services Table. + /// + EFI_RUNTIME_SERVICES *RuntimeServices; + /// + /// A pointer to the EFI Boot Services Table. + /// + EFI_BOOT_SERVICES *BootServices; + /// + /// The number of system configuration tables in the buffer ConfigurationTable. + /// + UINTN NumberOfTableEntries; + /// + /// A pointer to the system configuration tables. + /// The number of entries in the table is NumberOfTableEntries. + /// + EFI_CONFIGURATION_TABLE *ConfigurationTable; +} EFI_SYSTEM_TABLE; + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including + both device drivers and bus drivers. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_ENTRY_POINT)( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// EFI Load Option. This data structure describes format of UEFI boot option variables. +// +// NOTE: EFI Load Option is a byte packed buffer of variable length fields. +// The first two fields have fixed length. They are declared as members of the +// EFI_LOAD_OPTION structure. All the other fields are variable length fields. +// They are listed in the comment block below for reference purposes. +// +#pragma pack(1) +typedef struct _EFI_LOAD_OPTION { + /// + /// The attributes for this load option entry. All unused bits must be zero + /// and are reserved by the UEFI specification for future growth. + /// + UINT32 Attributes; + /// + /// Length in bytes of the FilePathList. OptionalData starts at offset + /// sizeof(UINT32) + sizeof(UINT16) + StrSize(Description) + FilePathListLength + /// of the EFI_LOAD_OPTION descriptor. + /// + UINT16 FilePathListLength; + /// + /// The user readable description for the load option. + /// This field ends with a Null character. + /// + // CHAR16 Description[]; + /// + /// A packed array of UEFI device paths. The first element of the array is a + /// device path that describes the device and location of the Image for this + /// load option. The FilePathList[0] is specific to the device type. Other + /// device paths may optionally exist in the FilePathList, but their usage is + /// OSV specific. Each element in the array is variable length, and ends at + /// the device path end structure. Because the size of Description is + /// arbitrary, this data structure is not guaranteed to be aligned on a + /// natural boundary. This data structure may have to be copied to an aligned + /// natural boundary before it is used. + /// + // EFI_DEVICE_PATH_PROTOCOL FilePathList[]; + /// + /// The remaining bytes in the load option descriptor are a binary data buffer + /// that is passed to the loaded image. If the field is zero bytes long, a + /// NULL pointer is passed to the loaded image. The number of bytes in + /// OptionalData can be computed by subtracting the starting offset of + /// OptionalData from total size in bytes of the EFI_LOAD_OPTION. + /// + // UINT8 OptionalData[]; +} EFI_LOAD_OPTION; +#pragma pack() + +// +// EFI Load Options Attributes +// +#define LOAD_OPTION_ACTIVE 0x00000001 +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 +#define LOAD_OPTION_HIDDEN 0x00000008 +#define LOAD_OPTION_CATEGORY 0x00001F00 + +#define LOAD_OPTION_CATEGORY_BOOT 0x00000000 +#define LOAD_OPTION_CATEGORY_APP 0x00000100 + +#define EFI_BOOT_OPTION_SUPPORT_KEY 0x00000001 +#define EFI_BOOT_OPTION_SUPPORT_APP 0x00000002 +#define EFI_BOOT_OPTION_SUPPORT_SYSPREP 0x00000010 +#define EFI_BOOT_OPTION_SUPPORT_COUNT 0x00000300 + +/// +/// EFI Boot Key Data +/// +typedef union { + struct { + /// + /// Indicates the revision of the EFI_KEY_OPTION structure. This revision level should be 0. + /// + UINT32 Revision : 8; + /// + /// Either the left or right Shift keys must be pressed (1) or must not be pressed (0). + /// + UINT32 ShiftPressed : 1; + /// + /// Either the left or right Control keys must be pressed (1) or must not be pressed (0). + /// + UINT32 ControlPressed : 1; + /// + /// Either the left or right Alt keys must be pressed (1) or must not be pressed (0). + /// + UINT32 AltPressed : 1; + /// + /// Either the left or right Logo keys must be pressed (1) or must not be pressed (0). + /// + UINT32 LogoPressed : 1; + /// + /// The Menu key must be pressed (1) or must not be pressed (0). + /// + UINT32 MenuPressed : 1; + /// + /// The SysReq key must be pressed (1) or must not be pressed (0). + /// + UINT32 SysReqPressed : 1; + UINT32 Reserved : 16; + /// + /// Specifies the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3. If + /// zero, then only the shift state is considered. If more than one, then the boot option will + /// only be launched if all of the specified keys are pressed with the same shift state. + /// + UINT32 InputKeyCount : 2; + } Options; + UINT32 PackedValue; +} EFI_BOOT_KEY_DATA; + +/// +/// EFI Key Option. +/// +#pragma pack(1) +typedef struct { + /// + /// Specifies options about how the key will be processed. + /// + EFI_BOOT_KEY_DATA KeyData; + /// + /// The CRC-32 which should match the CRC-32 of the entire EFI_LOAD_OPTION to + /// which BootOption refers. If the CRC-32s do not match this value, then this key + /// option is ignored. + /// + UINT32 BootOptionCrc; + /// + /// The Boot#### option which will be invoked if this key is pressed and the boot option + /// is active (LOAD_OPTION_ACTIVE is set). + /// + UINT16 BootOption; + /// + /// The key codes to compare against those returned by the + /// EFI_SIMPLE_TEXT_INPUT and EFI_SIMPLE_TEXT_INPUT_EX protocols. + /// The number of key codes (0-3) is specified by the EFI_KEY_CODE_COUNT field in KeyOptions. + /// + //EFI_INPUT_KEY Keys[]; +} EFI_KEY_OPTION; +#pragma pack() + +// +// EFI File location to boot from on removable media devices +// +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 L"\\EFI\\BOOT\\BOOTIA32.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA64 L"\\EFI\\BOOT\\BOOTIA64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_X64 L"\\EFI\\BOOT\\BOOTX64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_ARM L"\\EFI\\BOOT\\BOOTARM.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 L"\\EFI\\BOOT\\BOOTAA64.EFI" + +#if defined (MDE_CPU_IA32) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 +#elif defined (MDE_CPU_X64) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_X64 +#elif defined (MDE_CPU_EBC) +#elif defined (MDE_CPU_ARM) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_ARM +#elif defined (MDE_CPU_AARCH64) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 +#else + #error Unknown Processor Type +#endif + +// +// The directory within the active EFI System Partition defined for delivery of capsule to firmware +// +#define EFI_CAPSULE_FILE_DIRECTORY L"\\EFI\\UpdateCapsule\\" + +#include +#include +#include + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/Nasm.inc b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/Nasm.inc new file mode 100644 index 0000000..7b907f0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/Nasm.inc @@ -0,0 +1,28 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2019, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Abstract: +; +; This file provides macro definitions for NASM files. +; +;------------------------------------------------------------------------------ + +%macro SETSSBSY 0 + DB 0xF3, 0x0F, 0x01, 0xE8 +%endmacro + +%macro READSSP_RAX 0 + DB 0xF3, 0x48, 0x0F, 0x1E, 0xC8 +%endmacro + +%macro INCSSP_RAX 0 + DB 0xF3, 0x48, 0x0F, 0xAE, 0xE8 +%endmacro diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/ProcessorBind.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/ProcessorBind.h new file mode 100644 index 0000000..8e7741c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Include/X64/ProcessorBind.h @@ -0,0 +1,347 @@ +/** @file + Processor or Compiler specific defines and types x64 (Intel 64, AMD64). + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_X64 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#if !defined(__GNUC__) +#pragma pack() +#endif + +#if defined(__GNUC__) && defined(__pic__) && !defined(USING_LTO) +// +// Mark all symbol declarations and references as hidden, meaning they will +// not be subject to symbol preemption. This allows the compiler to refer to +// symbols directly using relative references rather than via the GOT, which +// contains absolute symbol addresses that are subject to runtime relocation. +// +// The LTO linker will not emit GOT based relocations when all symbol +// references can be resolved locally, and so there is no need to set the +// pragma in that case (and doing so will cause other issues). +// +#pragma GCC visibility push (hidden) +#endif + +#if defined(__INTEL_COMPILER) +// +// Disable ICC's remark #869: "Parameter" was never referenced warning. +// This is legal ANSI C code so we disable the remark that is turned on with -Wall +// +#pragma warning ( disable : 869 ) + +// +// Disable ICC's remark #1418: external function definition with no prior declaration. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1418 ) + +// +// Disable ICC's remark #1419: external declaration in primary source file +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 1419 ) + +// +// Disable ICC's remark #593: "Variable" was set but never used. +// This is legal ANSI C code so we disable the remark that is turned on with /W4 +// +#pragma warning ( disable : 593 ) + +#endif + + +#if defined(_MSC_EXTENSIONS) + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning +// +#pragma warning ( disable : 4127 ) + +// +// This warning is caused by functions defined but not used. For precompiled header only. +// +#pragma warning ( disable : 4505 ) + +// +// This warning is caused by empty (after preprocessing) source file. For precompiled header only. +// +#pragma warning ( disable : 4206 ) + +#if _MSC_VER == 1800 || _MSC_VER == 1900 || _MSC_VER >= 1910 + +// +// Disable these warnings for VS2013. +// + +// +// This warning is for potentially uninitialized local variable, and it may cause false +// positive issues in VS2013 and VS2015 build +// +#pragma warning ( disable : 4701 ) + +// +// This warning is for potentially uninitialized local pointer variable, and it may cause +// false positive issues in VS2013 and VS2015 build +// +#pragma warning ( disable : 4703 ) + +#endif + +#endif + + +#if defined(_MSC_EXTENSIONS) + // + // use Microsoft C compiler dependent integer width types + // + + /// + /// 8-byte unsigned value + /// + typedef unsigned __int64 UINT64; + /// + /// 8-byte signed value + /// + typedef __int64 INT64; + /// + /// 4-byte unsigned value + /// + typedef unsigned __int32 UINT32; + /// + /// 4-byte signed value + /// + typedef __int32 INT32; + /// + /// 2-byte unsigned value + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character + /// + typedef char CHAR8; + /// + /// 1-byte signed value + /// + typedef signed char INT8; +#else + /// + /// 8-byte unsigned value + /// + typedef unsigned long long UINT64; + /// + /// 8-byte signed value + /// + typedef long long INT64; + /// + /// 4-byte unsigned value + /// + typedef unsigned int UINT32; + /// + /// 4-byte signed value + /// + typedef int INT32; + /// + /// 2-byte unsigned value + /// + typedef unsigned short UINT16; + /// + /// 2-byte Character. Unless otherwise specified all strings are stored in the + /// UTF-16 encoding format as defined by Unicode 2.1 and ISO/IEC 10646 standards. + /// + typedef unsigned short CHAR16; + /// + /// 2-byte signed value + /// + typedef short INT16; + /// + /// Logical Boolean. 1-byte value containing 0 for FALSE or a 1 for TRUE. Other + /// values are undefined. + /// + typedef unsigned char BOOLEAN; + /// + /// 1-byte unsigned value + /// + typedef unsigned char UINT8; + /// + /// 1-byte Character + /// + typedef char CHAR8; + /// + /// 1-byte signed value + /// + typedef signed char INT8; +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef UINT64 UINTN; +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef INT64 INTN; + + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x8000000000000000ULL +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC000000000000000ULL + +/// +/// Maximum legal x64 address +/// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL + +/// +/// Maximum usable address at boot time +/// +#define MAX_ALLOC_ADDRESS MAX_ADDRESS + +/// +/// Maximum legal x64 INTN and UINTN values. +/// +#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL) +#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL) + +/// +/// Minimum legal x64 INTN value. +/// +#define MIN_INTN (((INTN)-9223372036854775807LL) - 1) + +/// +/// The stack alignment required for x64 +/// +#define CPU_STACK_ALIGNMENT 16 + +/// +/// Page allocation granularity for x64 +/// +#define DEFAULT_PAGE_ALLOCATION_GRANULARITY (0x1000) +#define RUNTIME_PAGE_ALLOCATION_GRANULARITY (0x1000) + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#ifdef EFIAPI + /// + /// If EFIAPI is already defined, then we use that definition. + /// +#elif defined(_MSC_EXTENSIONS) + /// + /// Microsoft* compiler specific method for EFIAPI calling convention. + /// + #define EFIAPI __cdecl +#elif defined(__GNUC__) + /// + /// Define the standard calling convention regardless of optimization level. + /// The GCC support assumes a GCC compiler that supports the EFI ABI. The EFI + /// ABI is much closer to the x64 Microsoft* ABI than standard x64 (x86-64) + /// GCC ABI. Thus a standard x64 (x86-64) GCC compiler can not be used for + /// x64. Warning the assembly code in the MDE x64 does not follow the correct + /// ABI for the standard x64 (x86-64) GCC. + /// + #define EFIAPI +#else + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI +#endif + +#if defined(__GNUC__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On x64 CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ +#endif + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c new file mode 100644 index 0000000..2326047 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/ArmCache.c @@ -0,0 +1,247 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf new file mode 100644 index 0000000..ae16421 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf @@ -0,0 +1,55 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni new file mode 100644 index 0000000..9df91be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c new file mode 100644 index 0000000..efbb03a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c @@ -0,0 +1,231 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c new file mode 100644 index 0000000..9462bb9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCacheMaintenanceLib/X86Cache.c @@ -0,0 +1,278 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S new file mode 100644 index 0000000..4b9a326 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm new file mode 100644 index 0000000..846d23a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuFlushTlb.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S new file mode 100644 index 0000000..b08bdfb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm new file mode 100644 index 0000000..aca244e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/AArch64/CpuSleep.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S new file mode 100644 index 0000000..e014723 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# CpuFlushTlb() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm new file mode 100644 index 0000000..78ee84b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuFlushTlb.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; CpuFlushTlb() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S new file mode 100644 index 0000000..001db87 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm new file mode 100644 index 0000000..0bcad14 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Arm/CpuSleep.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf new file mode 100644 index 0000000..7d82eda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf @@ -0,0 +1,74 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 +# + +[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 + + X64/CpuSleep.nasm| GCC + X64/CpuSleep.S | GCC + X64/CpuFlushTlb.nasm| GCC + X64/CpuFlushTlb.S | GCC + +[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 + +[Packages] + MdePkg/MdePkg.dec + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni new file mode 100644 index 0000000..19510f4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.uni @@ -0,0 +1,24 @@ +// /** @file +// Instance of CPU Library for various architecture. +// +// CPU Library implemented using ASM functions for IA-32 and X64, +// 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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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 and X64, PAL CALLs for IPF, and empty functions for EBC." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c new file mode 100644 index 0000000..81ae029 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ebc/CpuSleepFlushTlb.c @@ -0,0 +1,46 @@ +/** @file + Base Library CPU Functions for EBC + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c new file mode 100644 index 0000000..25b16c5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.c @@ -0,0 +1,34 @@ +/** @file + CpuFlushTlb function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm new file mode 100644 index 0000000..aa34345 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlb.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c new file mode 100644 index 0000000..4cff851 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuFlushTlbGcc.c @@ -0,0 +1,32 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c new file mode 100644 index 0000000..40b0453 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.c @@ -0,0 +1,34 @@ +/** @file + CpuSleep function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm new file mode 100644 index 0000000..c808f96 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleep.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c new file mode 100644 index 0000000..b61a61f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/Ia32/CpuSleepGcc.c @@ -0,0 +1,33 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.S new file mode 100644 index 0000000..009b280 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.S @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuFlushTlb.Asm +# +# Abstract: +# +# CpuFlushTlb function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(CpuFlushTlb) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# CpuFlushTlb ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(CpuFlushTlb): + mov %cr3, %rax + mov %rax, %cr3 + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm new file mode 100644 index 0000000..cdcbbca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuFlushTlb.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.S new file mode 100644 index 0000000..44d58e9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.S @@ -0,0 +1,34 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuSleep.S +# +# Abstract: +# +# CpuSleep function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# CpuSleep ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(CpuSleep) +ASM_PFX(CpuSleep): + hlt + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm new file mode 100644 index 0000000..0deed7f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseCpuLib/X64/CpuSleep.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf new file mode 100644 index 0000000..b5ada20 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf @@ -0,0 +1,36 @@ +## @file +# Debug Library with empty functions. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni new file mode 100644 index 0000000..3cf6a75 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.uni @@ -0,0 +1,21 @@ +// /** @file +// Debug Library with empty functions. +// +// Debug Library with empty functions. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c new file mode 100644 index 0000000..4056af6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibNull/DebugLib.c @@ -0,0 +1,198 @@ +/** @file + Null Base Debug Library instance with empty functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + 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 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf new file mode 100644 index 0000000..c938553 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf @@ -0,0 +1,49 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni new file mode 100644 index 0000000..4b90207 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c new file mode 100644 index 0000000..34b2793 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugLibSerialPort/DebugLib.c @@ -0,0 +1,284 @@ +/** @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 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +/** + 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, + ... + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // 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 + // + VA_START (Marker, Format); + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + // + // Send the print string to a Serial Port + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); +} + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c new file mode 100644 index 0000000..ab26fc1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c @@ -0,0 +1,59 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf new file mode 100644 index 0000000..4d30288 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf @@ -0,0 +1,40 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni new file mode 100644 index 0000000..2b306d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c new file mode 100644 index 0000000..a211df0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.c @@ -0,0 +1,484 @@ +/** @file + Provide generic extract guided section functions. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf new file mode 100644 index 0000000..ce015fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf @@ -0,0 +1,54 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni new file mode 100644 index 0000000..fcb7d65 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.uni @@ -0,0 +1,27 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S new file mode 100644 index 0000000..85f5932 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.S @@ -0,0 +1,148 @@ +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm new file mode 100644 index 0000000..bd235a5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/AArch64/ArmVirtMmio.asm @@ -0,0 +1,149 @@ +; +; Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http:;opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; + + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S new file mode 100644 index 0000000..0fa87fc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.S @@ -0,0 +1,147 @@ +# +# Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm new file mode 100644 index 0000000..c0c06c5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Arm/ArmVirtMmio.asm @@ -0,0 +1,151 @@ +; +; Copyright (c) 2014-2018, Linaro Limited. All rights reserved. +; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http:;opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; + + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf new file mode 100644 index 0000000..fc51bb2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf @@ -0,0 +1,71 @@ +## @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(). +# +# 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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 +# + +[Sources] + IoLibMmioBuffer.c + BaseIoLibIntrinsicInternal.h + IoHighLevel.c + +[Sources.IA32] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLibIcc.c | INTEL + IoLib.c + Ia32/IoFifo.nasm + +[Sources.X64] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLibIcc.c | INTEL + IoLib.c + X64/IoFifo.nasm + +[Sources.EBC] + IoLibEbc.c + IoLib.c + +[Sources.ARM] + IoLibArm.c + +[Sources.AARCH64] + IoLibArm.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni new file mode 100644 index 0000000..3696eda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.uni @@ -0,0 +1,24 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf new file mode 100644 index 0000000..f9060c8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf @@ -0,0 +1,52 @@ +## @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.
+# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni new file mode 100644 index 0000000..7e510e6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials are licensed and made available +// under the terms and conditions of the BSD License which accompanies this +// distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h new file mode 100644 index 0000000..9b20df0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h @@ -0,0 +1,26 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __BASEIOLIB_INTRINSIC_INTERNAL_H_ +#define __BASEIOLIB_INTRINSIC_INTERNAL_H_ + + + +#include + +#include +#include +#include + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf new file mode 100644 index 0000000..82f9b4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf @@ -0,0 +1,59 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + IoLibIcc.c | INTEL + IoLib.c + Ia32/IoFifoSev.nasm + +[Sources.X64] + IoLibGcc.c | GCC + IoLibMsc.c | MSFT + IoLibIcc.c | INTEL + IoLib.c + X64/IoFifoSev.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm new file mode 100644 index 0000000..102bbb8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifo.nasm @@ -0,0 +1,137 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + SECTION .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm new file mode 100644 index 0000000..02551b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/Ia32/IoFifoSev.nasm @@ -0,0 +1,299 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + SECTION .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c new file mode 100644 index 0000000..a5cc891 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c @@ -0,0 +1,2356 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + The 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c new file mode 100644 index 0000000..5091b2b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c @@ -0,0 +1,317 @@ +/** @file + Common I/O Library routines. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c new file mode 100644 index 0000000..02e2d2a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArm.c @@ -0,0 +1,599 @@ +/** @file + I/O Library for ARM. + + 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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +// +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c new file mode 100644 index 0000000..aff58b4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c @@ -0,0 +1,733 @@ +/** @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.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c new file mode 100644 index 0000000..d000675 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibEbc.c @@ -0,0 +1,342 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c new file mode 100644 index 0000000..5132d74 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c @@ -0,0 +1,196 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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. + +**/ +__inline__ +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. + +**/ +__inline__ +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. + +**/ +__inline__ +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. + +**/ +__inline__ +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. + +**/ +__inline__ +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. + +**/ +__inline__ +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibIcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibIcc.c new file mode 100644 index 0000000..3c92ebc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibIcc.c @@ -0,0 +1,214 @@ +/** @file + I/O Library. This file has compiler specifics for ICC as there + is no ANSI C standard for doing IO. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 { + mov dx, word ptr [Port] + in al, dx + + mov Data, al + } + 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 { + mov al, byte ptr [Value] + mov dx, word ptr [Port] + out dx, al + } + 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 { + mov dx, word ptr [Port] + in ax, dx + mov word ptr [Data], ax + } + + 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 { + mov ax, word ptr [Value] + mov dx, word ptr [Port] + out dx, ax + } + + 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 { + mov dx, word ptr [Port] + in eax, dx + mov dword ptr [Data], eax + } + + 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 { + mov eax, dword ptr [Value] + mov dx, word ptr [Port] + out dx, eax + } + + return Value; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c new file mode 100644 index 0000000..f8de86c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMmioBuffer.c @@ -0,0 +1,411 @@ +/** @file + I/O Library MMIO Buffer Functions. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c new file mode 100644 index 0000000..156ebbc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c @@ -0,0 +1,228 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm new file mode 100644 index 0000000..27c97d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifo.nasm @@ -0,0 +1,126 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm new file mode 100644 index 0000000..03337e0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm @@ -0,0 +1,288 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+; Copyright (c) 2017, AMD Incorporated. All rights reserved.
+; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S new file mode 100644 index 0000000..68bc055 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.S @@ -0,0 +1,37 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm new file mode 100644 index 0000000..fc4c720 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/CpuBreakpoint.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S new file mode 100644 index 0000000..9d67d07 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm new file mode 100644 index 0000000..90ddde5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/DisableInterrupts.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S new file mode 100644 index 0000000..14915ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm new file mode 100644 index 0000000..18b7c92 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/EnableInterrupts.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S new file mode 100644 index 0000000..1818c62 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.S @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm new file mode 100644 index 0000000..eff4036 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/GetInterruptsState.asm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S new file mode 100644 index 0000000..8dbd54a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.S @@ -0,0 +1,39 @@ +##------------------------------------------------------------------------------ +# +# MemoryFence() for AArch64 +# +# Copyright (c) 2013, ARM Ltd. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +##------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm new file mode 100644 index 0000000..91bd0c8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/MemoryFence.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; MemoryFence() for AArch64 +; +; Copyright (c) 2013, ARM Ltd. All rights reserved. +; +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S new file mode 100644 index 0000000..9fa096e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S @@ -0,0 +1,97 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2009-2013, ARM Ltd. All rights reserved. +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm new file mode 100644 index 0000000..eec63e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm @@ -0,0 +1,101 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2009-2013, ARM Ltd. All rights reserved. +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S new file mode 100644 index 0000000..c6e9d4d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.S @@ -0,0 +1,39 @@ +##------------------------------------------------------------------------------ +# +# SpeculationBarrier() for AArch64 +# +# Copyright (c) 2019, Linaro Ltd. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +##------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm new file mode 100644 index 0000000..101bb1c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SpeculationBarrier.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; SpeculationBarrier() for AArch64 +; +; Copyright (c) 2019, Linaro Ltd. All rights reserved. +; +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S new file mode 100644 index 0000000..ea22ac9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.S @@ -0,0 +1,71 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm new file mode 100644 index 0000000..b97ffae --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/AArch64/SwitchStack.asm @@ -0,0 +1,71 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ARShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ARShiftU64.c new file mode 100644 index 0000000..be33df3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ARShiftU64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S new file mode 100644 index 0000000..977ec98 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# CpuBreakpoint() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm new file mode 100644 index 0000000..9eceea4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuBreakpoint.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; CpuBreakpoint() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm new file mode 100644 index 0000000..97c2944 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/CpuPause.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; CpuPause() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S new file mode 100644 index 0000000..93e427c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.S @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# +# DisableInterrupts() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm new file mode 100644 index 0000000..728c98b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/DisableInterrupts.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; DisableInterrupts() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S new file mode 100644 index 0000000..56e4f77 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# EnableInterrupts() for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm new file mode 100644 index 0000000..e1c3a6f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/EnableInterrupts.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; EnableInterrupts() for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S new file mode 100644 index 0000000..cef88f1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# GetInterruptState() function for ARM +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm new file mode 100644 index 0000000..a9bf83b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/GetInterruptsState.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; GetInterruptState() function for ARM +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c new file mode 100644 index 0000000..c731731 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/InternalSwitchStack.c @@ -0,0 +1,79 @@ +/** @file + SwitchStack() function for ARM. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Math64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Math64.S new file mode 100644 index 0000000..632f050 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Math64.S @@ -0,0 +1,269 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S new file mode 100644 index 0000000..2208dd3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.S @@ -0,0 +1,39 @@ +##------------------------------------------------------------------------------ +# +# MemoryFence() for AArch64 +# +# Copyright (c) 2013, ARM Ltd. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +##------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm new file mode 100644 index 0000000..f1bc4eb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/MemoryFence.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; MemoryFence() for AArch64 +; +; Copyright (c) 2013, ARM Ltd. All rights reserved. +; +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S new file mode 100644 index 0000000..78f1ec8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.S @@ -0,0 +1,70 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm new file mode 100644 index 0000000..74c37be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SetJumpLongJump.asm @@ -0,0 +1,70 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S new file mode 100644 index 0000000..bebb9ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.S @@ -0,0 +1,39 @@ +##------------------------------------------------------------------------------ +# +# SpeculationBarrier() for AArch64 +# +# Copyright (c) 2019, Linaro Ltd. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +##------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm new file mode 100644 index 0000000..4a4fb90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SpeculationBarrier.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; SpeculationBarrier() for AArch64 +; +; Copyright (c) 2019, Linaro Ltd. All rights reserved. +; +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S new file mode 100644 index 0000000..71e12b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.S @@ -0,0 +1,68 @@ +//------------------------------------------------------------------------------ +// +// 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.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm new file mode 100644 index 0000000..728a56c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/SwitchStack.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c new file mode 100644 index 0000000..2593e08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Arm/Unaligned.c @@ -0,0 +1,252 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.inf new file mode 100644 index 0000000..0a0d3cd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.inf @@ -0,0 +1,626 @@ +## @file +# Base Library implementation. +# +# Copyright (c) 2007 - 2019, 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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 +# + +[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/SetJump.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/LongJump.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/DivU64x64Remainder.nasm| 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/Thunk16.nasm | MSFT + Ia32/EnablePaging64.nasm| MSFT + Ia32/EnableCache.c | MSFT + Ia32/DisableCache.c | MSFT + Ia32/RdRand.nasm| MSFT + + Ia32/Wbinvd.nasm| INTEL + Ia32/WriteMm7.nasm| INTEL + Ia32/WriteMm6.nasm| INTEL + Ia32/WriteMm5.nasm| INTEL + Ia32/WriteMm4.nasm| INTEL + Ia32/WriteMm3.nasm| INTEL + Ia32/WriteMm2.nasm| INTEL + Ia32/WriteMm1.nasm| INTEL + Ia32/WriteMm0.nasm| INTEL + Ia32/WriteLdtr.nasm| INTEL + Ia32/WriteIdtr.nasm| INTEL + Ia32/WriteGdtr.nasm| INTEL + Ia32/WriteDr7.nasm| INTEL + Ia32/WriteDr6.nasm| INTEL + Ia32/WriteDr5.nasm| INTEL + Ia32/WriteDr4.nasm| INTEL + Ia32/WriteDr3.nasm| INTEL + Ia32/WriteDr2.nasm| INTEL + Ia32/WriteDr1.nasm| INTEL + Ia32/WriteDr0.nasm| INTEL + Ia32/WriteCr4.nasm| INTEL + Ia32/WriteCr3.nasm| INTEL + Ia32/WriteCr2.nasm| INTEL + Ia32/WriteCr0.nasm| INTEL + Ia32/WriteMsr64.nasm| INTEL + Ia32/SwapBytes64.nasm| INTEL + Ia32/SetJump.nasm| INTEL + Ia32/RRotU64.nasm| INTEL + Ia32/RShiftU64.nasm| INTEL + Ia32/ReadPmc.nasm| INTEL + Ia32/ReadTsc.nasm| INTEL + Ia32/ReadLdtr.nasm| INTEL + Ia32/ReadIdtr.nasm| INTEL + Ia32/ReadGdtr.nasm| INTEL + Ia32/ReadTr.nasm| INTEL + Ia32/ReadSs.nasm| INTEL + Ia32/ReadGs.nasm| INTEL + Ia32/ReadFs.nasm| INTEL + Ia32/ReadEs.nasm| INTEL + Ia32/ReadDs.nasm| INTEL + Ia32/ReadCs.nasm| INTEL + Ia32/ReadMsr64.nasm| INTEL + Ia32/ReadMm7.nasm| INTEL + Ia32/ReadMm6.nasm| INTEL + Ia32/ReadMm5.nasm| INTEL + Ia32/ReadMm4.nasm| INTEL + Ia32/ReadMm3.nasm| INTEL + Ia32/ReadMm2.nasm| INTEL + Ia32/ReadMm1.nasm| INTEL + Ia32/ReadMm0.nasm| INTEL + Ia32/ReadEflags.nasm| INTEL + Ia32/ReadDr7.nasm| INTEL + Ia32/ReadDr6.nasm| INTEL + Ia32/ReadDr5.nasm| INTEL + Ia32/ReadDr4.nasm| INTEL + Ia32/ReadDr3.nasm| INTEL + Ia32/ReadDr2.nasm| INTEL + Ia32/ReadDr1.nasm| INTEL + Ia32/ReadDr0.nasm| INTEL + Ia32/ReadCr4.nasm| INTEL + Ia32/ReadCr3.nasm| INTEL + Ia32/ReadCr2.nasm| INTEL + Ia32/ReadCr0.nasm| INTEL + Ia32/Mwait.nasm| INTEL + Ia32/Monitor.nasm| INTEL + Ia32/ModU64x32.nasm| INTEL + Ia32/MultU64x64.nasm| INTEL + Ia32/MultU64x32.nasm| INTEL + Ia32/LShiftU64.nasm| INTEL + Ia32/LRotU64.nasm| INTEL + Ia32/LongJump.nasm| INTEL + Ia32/Invd.nasm| INTEL + Ia32/FxRestore.nasm| INTEL + Ia32/FxSave.nasm| INTEL + Ia32/FlushCacheLine.nasm| INTEL + Ia32/EnablePaging32.nasm| INTEL + Ia32/EnableInterrupts.nasm| INTEL + Ia32/EnableDisableInterrupts.nasm| INTEL + Ia32/DivU64x64Remainder.nasm| INTEL + Ia32/DivU64x32Remainder.nasm| INTEL + Ia32/DivU64x32.nasm| INTEL + Ia32/DisablePaging32.nasm| INTEL + Ia32/DisableInterrupts.nasm| INTEL + Ia32/CpuPause.nasm| INTEL + Ia32/CpuIdEx.nasm| INTEL + Ia32/CpuId.nasm| INTEL + Ia32/CpuBreakpoint.nasm| INTEL + Ia32/ARShiftU64.nasm| INTEL + Ia32/Thunk16.nasm | INTEL + Ia32/EnablePaging64.nasm| INTEL + Ia32/EnableCache.nasm| INTEL + Ia32/DisableCache.nasm| INTEL + Ia32/RdRand.nasm| INTEL + + Ia32/GccInline.c | GCC + Ia32/Thunk16.nasm | GCC + Ia32/Thunk16.S | XCODE + Ia32/EnableDisableInterrupts.nasm| GCC + Ia32/EnableDisableInterrupts.S | GCC + Ia32/EnablePaging64.nasm| GCC + Ia32/EnablePaging64.S | GCC + Ia32/DisablePaging32.nasm| GCC + Ia32/DisablePaging32.S | GCC + Ia32/EnablePaging32.nasm| GCC + Ia32/EnablePaging32.S | GCC + Ia32/Mwait.nasm| GCC + Ia32/Mwait.S | GCC + Ia32/Monitor.nasm| GCC + Ia32/Monitor.S | GCC + Ia32/CpuIdEx.nasm| GCC + Ia32/CpuIdEx.S | GCC + Ia32/CpuId.nasm| GCC + Ia32/CpuId.S | GCC + Ia32/LongJump.nasm| GCC + Ia32/LongJump.S | GCC + Ia32/SetJump.nasm| GCC + Ia32/SetJump.S | GCC + Ia32/SwapBytes64.nasm| GCC + Ia32/SwapBytes64.S | GCC + Ia32/DivU64x64Remainder.nasm| GCC + Ia32/DivU64x64Remainder.S | GCC + Ia32/DivU64x32Remainder.nasm| GCC + Ia32/DivU64x32Remainder.S | GCC + Ia32/ModU64x32.nasm| GCC + Ia32/ModU64x32.S | GCC + Ia32/DivU64x32.nasm| GCC + Ia32/DivU64x32.S | GCC + Ia32/MultU64x64.nasm| GCC + Ia32/MultU64x64.S | GCC + Ia32/MultU64x32.nasm| GCC + Ia32/MultU64x32.S | GCC + Ia32/RRotU64.nasm| GCC + Ia32/RRotU64.S | GCC + Ia32/LRotU64.nasm| GCC + Ia32/LRotU64.S | GCC + Ia32/ARShiftU64.nasm| GCC + Ia32/ARShiftU64.S | GCC + Ia32/RShiftU64.nasm| GCC + Ia32/RShiftU64.S | GCC + Ia32/LShiftU64.nasm| GCC + Ia32/LShiftU64.S | GCC + Ia32/EnableCache.nasm| GCC + Ia32/EnableCache.S | GCC + Ia32/DisableCache.nasm| GCC + Ia32/DisableCache.S | GCC + Ia32/RdRand.nasm| GCC + Ia32/RdRand.S | GCC + + Ia32/DivS64x64Remainder.c + Ia32/InternalSwitchStack.c | MSFT + Ia32/InternalSwitchStack.c | INTEL + Ia32/InternalSwitchStack.S | GCC + 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 + X86MemoryFence.c | INTEL + 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/RdRand.nasm| MSFT + X64/CpuPause.nasm| MSFT + X64/EnableDisableInterrupts.nasm| MSFT + X64/DisableInterrupts.nasm| MSFT + X64/EnableInterrupts.nasm| MSFT + X64/FlushCacheLine.nasm| MSFT + X64/Invd.nasm| MSFT + X64/Wbinvd.nasm| MSFT + X64/DisablePaging64.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/CpuBreakpoint.nasm| INTEL + X64/WriteMsr64.nasm| INTEL + X64/ReadMsr64.nasm| INTEL + X64/RdRand.nasm| INTEL + X64/CpuPause.nasm| INTEL + X64/EnableDisableInterrupts.nasm| INTEL + X64/DisableInterrupts.nasm| INTEL + X64/EnableInterrupts.nasm| INTEL + X64/FlushCacheLine.nasm| INTEL + X64/Invd.nasm| INTEL + X64/Wbinvd.nasm| INTEL + X64/DisablePaging64.nasm| INTEL + X64/Mwait.nasm| INTEL + X64/Monitor.nasm| INTEL + X64/ReadPmc.nasm| INTEL + X64/ReadTsc.nasm| INTEL + X64/WriteMm7.nasm| INTEL + X64/WriteMm6.nasm| INTEL + X64/WriteMm5.nasm| INTEL + X64/WriteMm4.nasm| INTEL + X64/WriteMm3.nasm| INTEL + X64/WriteMm2.nasm| INTEL + X64/WriteMm1.nasm| INTEL + X64/WriteMm0.nasm| INTEL + X64/ReadMm7.nasm| INTEL + X64/ReadMm6.nasm| INTEL + X64/ReadMm5.nasm| INTEL + X64/ReadMm4.nasm| INTEL + X64/ReadMm3.nasm| INTEL + X64/ReadMm2.nasm| INTEL + X64/ReadMm1.nasm| INTEL + X64/ReadMm0.nasm| INTEL + X64/FxRestore.nasm| INTEL + X64/FxSave.nasm| INTEL + X64/WriteLdtr.nasm| INTEL + X64/ReadLdtr.nasm| INTEL + X64/WriteIdtr.nasm| INTEL + X64/ReadIdtr.nasm| INTEL + X64/WriteGdtr.nasm| INTEL + X64/ReadGdtr.nasm| INTEL + X64/ReadTr.nasm| INTEL + X64/ReadSs.nasm| INTEL + X64/ReadGs.nasm| INTEL + X64/ReadFs.nasm| INTEL + X64/ReadEs.nasm| INTEL + X64/ReadDs.nasm| INTEL + X64/ReadCs.nasm| INTEL + X64/WriteDr7.nasm| INTEL + X64/WriteDr6.nasm| INTEL + X64/WriteDr5.nasm| INTEL + X64/WriteDr4.nasm| INTEL + X64/WriteDr3.nasm| INTEL + X64/WriteDr2.nasm| INTEL + X64/WriteDr1.nasm| INTEL + X64/WriteDr0.nasm| INTEL + X64/ReadDr7.nasm| INTEL + X64/ReadDr6.nasm| INTEL + X64/ReadDr5.nasm| INTEL + X64/ReadDr4.nasm| INTEL + X64/ReadDr3.nasm| INTEL + X64/ReadDr2.nasm| INTEL + X64/ReadDr1.nasm| INTEL + X64/ReadDr0.nasm| INTEL + X64/WriteCr4.nasm| INTEL + X64/WriteCr3.nasm| INTEL + X64/WriteCr2.nasm| INTEL + X64/WriteCr0.nasm| INTEL + X64/ReadCr4.nasm| INTEL + X64/ReadCr3.nasm| INTEL + X64/ReadCr2.nasm| INTEL + X64/ReadCr0.nasm| INTEL + X64/ReadEflags.nasm| INTEL + + X64/Non-existing.c + Math64.c + Unaligned.c + X86WriteIdtr.c + X86WriteGdtr.c + X86Thunk.c + X86ReadIdtr.c + X86ReadGdtr.c + X86Msr.c + X86MemoryFence.c | MSFT + X86MemoryFence.c | INTEL + 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/Thunk16.S | XCODE + X64/SwitchStack.nasm| GCC + X64/SwitchStack.S | GCC + X64/SetJump.nasm| GCC + X64/SetJump.S | GCC + X64/LongJump.nasm| GCC + X64/LongJump.S | GCC + X64/EnableDisableInterrupts.nasm| GCC + X64/EnableDisableInterrupts.S | GCC + X64/DisablePaging64.nasm| GCC + X64/DisablePaging64.S | GCC + X64/CpuId.nasm| GCC + X64/CpuId.S | GCC + X64/CpuIdEx.nasm| GCC + X64/CpuIdEx.S | GCC + X64/EnableCache.nasm| GCC + X64/EnableCache.S | GCC + X64/DisableCache.nasm| GCC + X64/DisableCache.S | GCC + X64/RdRand.nasm| GCC + X64/RdRand.S | GCC + 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 + +[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 + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.uni new file mode 100644 index 0000000..6e4c32e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Base Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "Base Library implementation." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h new file mode 100644 index 0000000..d02feff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BaseLibInternals.h @@ -0,0 +1,875 @@ +/** @file + Declaration of internal functions in BaseLib. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BitField.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BitField.c new file mode 100644 index 0000000..05dbe01 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/BitField.c @@ -0,0 +1,1008 @@ +/** @file + Bit field functions of BaseLib. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CheckSum.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CheckSum.c new file mode 100644 index 0000000..92f0930 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CheckSum.c @@ -0,0 +1,632 @@ +/** @file + Utility functions to generate checksum based on 2's complement + algorithm. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c new file mode 100644 index 0000000..099fb95 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ChkStkGcc.c @@ -0,0 +1,24 @@ +/** @file + Provides hack function for passng GCC build. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BaseLibInternals.h" + +/** + Hack function for passing GCC build. +**/ +VOID +__chkstk() +{ +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Cpu.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Cpu.c new file mode 100644 index 0000000..38bab1e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Cpu.c @@ -0,0 +1,65 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c new file mode 100644 index 0000000..21c6f39 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/CpuDeadLoop.c @@ -0,0 +1,38 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c new file mode 100644 index 0000000..9b8abbd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivS64x64Remainder.c @@ -0,0 +1,53 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32.c new file mode 100644 index 0000000..501adda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c new file mode 100644 index 0000000..e18a0a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x32Remainder.c @@ -0,0 +1,49 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c new file mode 100644 index 0000000..13509b8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/DivU64x64Remainder.c @@ -0,0 +1,49 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c new file mode 100644 index 0000000..4f33bd8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c @@ -0,0 +1,129 @@ +/** @file + Base Library CPU Functions for EBC + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c new file mode 100644 index 0000000..3c26c78 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SetJumpLongJump.c @@ -0,0 +1,68 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c new file mode 100644 index 0000000..25a9116 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SpeculationBarrier.c @@ -0,0 +1,30 @@ +/** @file + SpeculationBarrier() function for EBC. + + Copyright (C) 2018, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c new file mode 100644 index 0000000..c90b07a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ebc/SwitchStack.c @@ -0,0 +1,58 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/FilePaths.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/FilePaths.c new file mode 100644 index 0000000..ebba690 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/FilePaths.c @@ -0,0 +1,121 @@ +/** @file + Defines file-path manipulation functions. + + Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Dell Technologies. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#include +#include + +/** + 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 occured. +**/ +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c new file mode 100644 index 0000000..67b64d6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo32.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c new file mode 100644 index 0000000..021b30e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/GetPowerOfTwo64.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet32.c new file mode 100644 index 0000000..7d73398 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet32.c @@ -0,0 +1,47 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet64.c new file mode 100644 index 0000000..4fc96fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/HighBitSet64.c @@ -0,0 +1,55 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.S new file mode 100644 index 0000000..aeaadd7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ARShiftU64.S +# +# Abstract: +# +# 64-bit arithmetic right shift function for IA-32 +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathARShiftU64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathARShiftU64 ( +# IN UINT64 Operand, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathARShiftU64): + movb 12(%esp), %cl + movl 8(%esp), %eax + cltd + testb $32, %cl + jnz L0 + movl %eax, %edx + movl 4(%esp), %eax +L0: + shrdl %cl, %edx, %eax + sar %cl, %edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c new file mode 100644 index 0000000..c2ebaeb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.c @@ -0,0 +1,51 @@ +/** @file + 64-bit arithmetic right shift function for IA-32. + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm new file mode 100644 index 0000000..448e3ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ARShiftU64.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c new file mode 100644 index 0000000..e933313 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.c @@ -0,0 +1,41 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm new file mode 100644 index 0000000..4f91895 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuBreakpoint.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.S new file mode 100644 index 0000000..6f9e10c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.S @@ -0,0 +1,63 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuId.S +# +# Abstract: +# +# AsmCpuid function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(AsmCpuid) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmCpuid ( +# IN UINT32 RegisterInEax, +# OUT UINT32 *RegisterOutEax OPTIONAL, +# OUT UINT32 *RegisterOutEbx OPTIONAL, +# OUT UINT32 *RegisterOutEcx OPTIONAL, +# OUT UINT32 *RegisterOutEdx OPTIONAL +# ) +#------------------------------------------------------------------------------ +ASM_PFX(AsmCpuid): + push %ebx + push %ebp + movl %esp, %ebp + movl 12(%ebp), %eax + cpuid + push %ecx + movl 16(%ebp), %ecx + jecxz L1 + movl %eax, (%ecx) +L1: + movl 20(%ebp), %ecx + jecxz L2 + movl %ebx, (%ecx) +L2: + movl 24(%ebp), %ecx + jecxz L3 + popl (%ecx) +L3: + movl 28(%ebp), %ecx + jecxz L4 + movl %edx, (%ecx) +L4: + movl 12(%ebp), %eax + leave + pop %ebx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c new file mode 100644 index 0000000..d9c7266 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.c @@ -0,0 +1,74 @@ +/** @file + AsmCpuid function. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm new file mode 100644 index 0000000..5996b92 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuId.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.S new file mode 100644 index 0000000..edcaa89 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.S @@ -0,0 +1,67 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuIdEx.S +# +# Abstract: +# +# AsmCpuidEx function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + .code: + +#------------------------------------------------------------------------------ +# 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 +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmCpuidEx) +ASM_PFX(AsmCpuidEx): + push %ebx + push %ebp + movl %esp, %ebp + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + cpuid + push %ecx + movl 20(%ebp), %ecx + jecxz L1 + movl %eax, (%ecx) +L1: + movl 24(%ebp), %ecx + jecxz L2 + movl %ebx, (%ecx) +L2: + movl 32(%ebp), %ecx + jecxz L3 + movl %edx, (%ecx) +L3: + movl 28(%ebp), %ecx + jecxz L4 + popl (%ecx) +L4: + movl 12(%ebp), %eax + leave + pop %ebx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c new file mode 100644 index 0000000..1b3d91d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.c @@ -0,0 +1,82 @@ +/** @file + AsmCpuidEx function. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm new file mode 100644 index 0000000..e3d16ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuIdEx.nasm @@ -0,0 +1,67 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c new file mode 100644 index 0000000..e3094e2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.c @@ -0,0 +1,35 @@ +/** @file + CpuPause function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm new file mode 100644 index 0000000..fb92687 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/CpuPause.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.S new file mode 100644 index 0000000..cadfa7a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DisableCache.S +# +# 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: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmDisableCache ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmDisableCache) +ASM_PFX(AsmDisableCache): + movl %cr0, %eax + btsl $30, %eax + btrl $29, %eax + movl %eax, %cr0 + wbinvd + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c new file mode 100644 index 0000000..5980639 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.c @@ -0,0 +1,36 @@ +/** @file + AsmDisableCache function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm new file mode 100644 index 0000000..c956b72 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableCache.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c new file mode 100644 index 0000000..a20b3d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.c @@ -0,0 +1,32 @@ +/** @file + DisableInterrupts function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + _asm { + cli + } +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm new file mode 100644 index 0000000..ccf69b0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisableInterrupts.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.S new file mode 100644 index 0000000..08b3cc6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DisablePaging32.S +# +# Abstract: +# +# InternalX86DisablePaging32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalX86DisablePaging32) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalX86DisablePaging32 ( +# IN SWITCH_STACK_ENTRY_POINT EntryPoint, +# IN VOID *Context1, OPTIONAL +# IN VOID *Context2, OPTIONAL +# IN VOID *NewStack +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalX86DisablePaging32): + movl 4(%esp), %ebx + movl 8(%esp), %ecx + movl 12(%esp), %edx + pushfl + pop %edi # save EFLAGS to edi + cli + movl %cr0, %eax + btrl $31, %eax + movl 16(%esp), %esp + movl %eax, %cr0 + push %edi + popfl # restore EFLAGS from edi + push %edx + push %ecx + call *%ebx + jmp . # EntryPoint() should not return diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c new file mode 100644 index 0000000..eb75566 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.c @@ -0,0 +1,77 @@ +/** @file + AsmDisablePaging32 function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm new file mode 100644 index 0000000..62813c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DisablePaging32.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c new file mode 100644 index 0000000..90c1042 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivS64x64Remainder.c @@ -0,0 +1,53 @@ +/** @file + Integer division worker functions for Ia32. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.S new file mode 100644 index 0000000..55a6854 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DivU64x32.S +# +# Abstract: +# +# Calculate the quotient of a 64-bit integer by a 32-bit integer +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathDivU64x32) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathDivU64x32 ( +# IN UINT64 Dividend, +# IN UINT32 Divisor +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathDivU64x32): + movl 8(%esp), %eax + movl 12(%esp), %ecx + xorl %edx, %edx + divl %ecx + push %eax # save quotient on stack + movl 8(%esp), %eax + divl %ecx + pop %edx # restore high-order dword of the quotient + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c new file mode 100644 index 0000000..e680bf2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.c @@ -0,0 +1,50 @@ +/** @file + Calculate the quotient of a 64-bit integer by a 32-bit integer + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm new file mode 100644 index 0000000..6b96f82 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.S new file mode 100644 index 0000000..743abf2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DivError.S +# +# Abstract: +# +# Set error flag for all division functions +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathDivRemU64x32) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathDivRemU64x32 ( +# IN UINT64 Dividend, +# IN UINT32 Divisor, +# OUT UINT32 *Remainder +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathDivRemU64x32): + movl 12(%esp), %ecx # ecx <- divisor + movl 8(%esp), %eax # eax <- dividend[32..63] + xorl %edx, %edx + divl %ecx # eax <- quotient[32..63], edx <- remainder + push %eax + movl 8(%esp), %eax # eax <- dividend[0..31] + divl %ecx # eax <- quotient[0..31] + movl 20(%esp), %ecx # ecx <- Remainder + jecxz L1 # abandon remainder if Remainder == NULL + movl %edx, (%ecx) +L1: + pop %edx # edx <- quotient[32..63] + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c new file mode 100644 index 0000000..87f9352 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.c @@ -0,0 +1,55 @@ +/** @file + Set error flag for all division functions + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm new file mode 100644 index 0000000..1ccc4de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x32Remainder.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.S new file mode 100644 index 0000000..709c69f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.S @@ -0,0 +1,89 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DivU64x64Remainder.S +# +# Abstract: +# +# Calculate the quotient of a 64-bit integer by a 64-bit integer and returns +# both the quotient and the remainder +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathDivRemU64x32), ASM_PFX(InternalMathDivRemU64x64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathDivRemU64x64 ( +# IN UINT64 Dividend, +# IN UINT64 Divisor, +# OUT UINT64 *Remainder OPTIONAL +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathDivRemU64x64): + movl 16(%esp), %ecx # ecx <- divisor[32..63] + testl %ecx, %ecx + jnz Hard # call _@DivRemU64x64 if Divisor > 2^32 + movl 20(%esp), %ecx + jecxz L1 + andl $0, 4(%ecx) # zero high dword of remainder + movl %ecx, 16(%esp) # set up stack frame to match DivRemU64x32 +L1: + jmp ASM_PFX(InternalMathDivRemU64x32) +Hard: + push %ebx + push %esi + push %edi + mov 20(%esp), %edx + mov 16(%esp), %eax # edx:eax <- dividend + movl %edx, %edi + movl %eax, %esi # edi:esi <- dividend + mov 24(%esp), %ebx # ecx:ebx <- divisor +L2: + shrl %edx + rcrl $1, %eax + shrdl $1, %ecx, %ebx + shrl %ecx + jnz L2 + divl %ebx + movl %eax, %ebx # ebx <- quotient + movl 28(%esp), %ecx # ecx <- high dword of divisor + mull 24(%esp) # edx:eax <- quotient * divisor[0..31] + imull %ebx, %ecx # ecx <- quotient * divisor[32..63] + addl %ecx, %edx # edx <- (quotient * divisor)[32..63] + mov 32(%esp), %ecx # ecx <- addr for Remainder + jc TooLarge # product > 2^64 + cmpl %edx, %edi # compare high 32 bits + ja Correct + jb TooLarge # product > dividend + cmpl %eax, %esi + jae Correct # product <= dividend +TooLarge: + decl %ebx # adjust quotient by -1 + jecxz Return # return if Remainder == NULL + sub 24(%esp), %eax + sbb 28(%esp), %edx # edx:eax <- (quotient - 1) * divisor +Correct: + jecxz Return + subl %eax, %esi + sbbl %edx, %edi # edi:esi <- remainder + movl %esi, (%ecx) + movl %edi, 4(%ecx) +Return: + movl %ebx, %eax # eax <- quotient + xorl %edx, %edx # quotient is 32 bits long + pop %edi + pop %esi + pop %ebx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm new file mode 100644 index 0000000..c70e129 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/DivU64x64Remainder.nasm @@ -0,0 +1,94 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.S new file mode 100644 index 0000000..da60eeb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EnableCache.S +# +# 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: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmEnableCache ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmEnableCache) +ASM_PFX(AsmEnableCache): + wbinvd + movl %cr0, %eax + btrl $30, %eax + btrl $29, %eax + movl %eax, %cr0 + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c new file mode 100644 index 0000000..912defb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.c @@ -0,0 +1,36 @@ +/** @file + AsmEnableCache function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm new file mode 100644 index 0000000..63c605d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableCache.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.S new file mode 100644 index 0000000..446c36b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EnableDisableInterrupts.S +# +# Abstract: +# +# EnableDisableInterrupts function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(EnableDisableInterrupts) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# EnableDisableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_PFX(EnableDisableInterrupts): + sti + cli + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c new file mode 100644 index 0000000..d351afb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.c @@ -0,0 +1,36 @@ +/** @file + EnableDisableInterrupts function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm new file mode 100644 index 0000000..d5cb3e6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableDisableInterrupts.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c new file mode 100644 index 0000000..7fe14cb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.c @@ -0,0 +1,32 @@ +/** @file + EnableInterrupts function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + _asm { + sti + } +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm new file mode 100644 index 0000000..f4a4111 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnableInterrupts.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.S new file mode 100644 index 0000000..2449556 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EnablePaging32.S +# +# Abstract: +# +# InternalX86EnablePaging32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalX86EnablePaging32) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalX86EnablePaging32 ( +# IN SWITCH_STACK_ENTRY_POINT EntryPoint, +# IN VOID *Context1, OPTIONAL +# IN VOID *Context2, OPTIONAL +# IN VOID *NewStack +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalX86EnablePaging32): + movl 4(%esp), %ebx + movl 8(%esp), %ecx + movl 12(%esp), %edx + pushfl + pop %edi # save flags in edi + cli + movl %cr0, %eax + btsl $31, %eax + movl 16(%esp), %esp + movl %eax, %cr0 + push %edi + popfl # restore flags + push %edx + push %ecx + call *%ebx + jmp . diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c new file mode 100644 index 0000000..18e9d11 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.c @@ -0,0 +1,81 @@ +/** @file + AsmEnablePaging32 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm new file mode 100644 index 0000000..f0949be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging32.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.S new file mode 100644 index 0000000..e1c7f60 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.S @@ -0,0 +1,63 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EnablePaging64.S +# +# Abstract: +# +# InternalX86EnablePaging64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalX86EnablePaging64) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalX86EnablePaging64 ( +# IN UINT16 CodeSelector, +# IN UINT64 EntryPoint, +# IN UINT64 Context1, OPTIONAL +# IN UINT64 Context2, OPTIONAL +# IN UINT64 NewStack +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalX86EnablePaging64): + cli + movl $LongStart, (%esp) # offset for far retf, seg is the 1st arg + movl %cr4, %eax + orb $0x20, %al + movl %eax, %cr4 # enable PAE + movl $0xc0000080, %ecx + rdmsr + orb $1, %ah # set LME + wrmsr + movl %cr0, %eax + btsl $31, %eax # set PG + movl %eax, %cr0 # enable paging + lret # topmost 2 dwords hold the address +LongStart: # long mode starts here + .byte 0x67, 0x48 # 32-bit address size, 64-bit operand size + movl (%esp), %ebx # mov rbx, [esp] + .byte 0x67, 0x48 + movl 8(%esp), %ecx # mov rcx, [esp + 8] + .byte 0x67, 0x48 + movl 0x10(%esp), %edx # mov rdx, [esp + 10h] + .byte 0x67, 0x48 + movl 0x18(%esp), %esp # mov rsp, [esp + 18h] + .byte 0x48 + addl $-0x20, %esp # add rsp, -20h + call *%ebx # call rbx + jmp . # no one should get here diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm new file mode 100644 index 0000000..91c89ee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/EnablePaging64.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c new file mode 100644 index 0000000..bd6d2bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.c @@ -0,0 +1,58 @@ +/** @file + AsmFlushCacheLine function + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm new file mode 100644 index 0000000..088b7aa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FlushCacheLine.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c new file mode 100644 index 0000000..b64284a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.c @@ -0,0 +1,40 @@ +/** @file + AsmFxRestore function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm new file mode 100644 index 0000000..5c33747 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxRestore.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c new file mode 100644 index 0000000..0de252f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.c @@ -0,0 +1,40 @@ +/** @file + AsmFxSave function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm new file mode 100644 index 0000000..f22e19e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/FxSave.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c new file mode 100644 index 0000000..e46a6c6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/GccInline.c @@ -0,0 +1,1771 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "BaseLibInternals.h" + + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + // This is a little bit of overkill and it is more about the compiler that it is + // actually processor synchronization. This is like the _ReadWriteBarrier + // Microsoft specific intrinsic + __asm__ __volatile__ ("":::"memory"); +} + + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("sti"::: "memory"); +} + + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("cli"::: "memory"); +} + + + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ + __asm__ __volatile__ ("pause"); +} + + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __asm__ __volatile__ ("int $3"); +} + + + +/** + 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 EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a + 64-bit value on X64. + + @return EFLAGS on IA-32 or RFLAGS on X64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ) +{ + UINTN Eflags; + + __asm__ __volatile__ ( + "pushfl \n\t" + "popl %0 " + : "=r" (Eflags) + ); + + return Eflags; +} + + + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr0,%0" + : "=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr2, %0" + : "=r" (Data) + ); + + return Data; +} + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr3, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%cr4, %0" + : "=a" (Data) + ); + + return Data; +} + + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr0" + : + : "r" (Cr0) + ); + return Cr0; +} + + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr2" + : + : "r" (Cr2) + ); + return Cr2; +} + + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr3" + : + : "r" (Cr3) + ); + return Cr3; +} + + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%cr4" + : + : "r" (Cr4) + ); + return Cr4; +} + + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr0, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr1, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr2, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr3, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr4, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr5, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr6, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ) +{ + UINTN Data; + + __asm__ __volatile__ ( + "movl %%dr7, %0" + : "=r" (Data) + ); + + return Data; +} + + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr0" + : + : "r" (Dr0) + ); + return Dr0; +} + + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr1" + : + : "r" (Dr1) + ); + return Dr1; +} + + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr2" + : + : "r" (Dr2) + ); + return Dr2; +} + + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr3" + : + : "r" (Dr3) + ); + return Dr3; +} + + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr4" + : + : "r" (Dr4) + ); + return Dr4; +} + + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr5" + : + : "r" (Dr5) + ); + return Dr5; +} + + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr6" + : + : "r" (Dr6) + ); + return Dr6; +} + + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ) +{ + __asm__ __volatile__ ( + "movl %0, %%dr7" + : + : "r" (Dr7) + ); + return Dr7; +} + + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and X64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%cs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and X64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%ds, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and X64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%es, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and X64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%fs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and X64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%gs, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and X64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "mov %%ds, %0" + :"=a" (Data) + ); + + return Data; +} + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and X64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "str %0" + : "=a" (Data) + ); + + return Data; +} + + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and X64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + __asm__ __volatile__ ( + "sgdt %0" + : "=m" (*Gdtr) + ); +} + + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and X64. + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + __asm__ __volatile__ ( + "lgdt %0" + : + : "m" (*Gdtr) + ); + +} + + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and X64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86ReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + __asm__ __volatile__ ( + "sidt %0" + : "=m" (*Idtr) + ); +} + + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and X64. + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +InternalX86WriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + __asm__ __volatile__ ( + "lidt %0" + : + : "m" (*Idtr) + ); +} + + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and X64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ) +{ + UINT16 Data; + + __asm__ __volatile__ ( + "sldt %0" + : "=g" (Data) // %0 + ); + + return Data; +} + + +/** + Writes the current Local Descriptor Table Register (GDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and X64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ) +{ + __asm__ __volatile__ ( + "lldtw %0" + : + : "g" (Ldtr) // %0 + ); +} + + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and X64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxSave ( + OUT IA32_FX_BUFFER *Buffer + ) +{ + __asm__ __volatile__ ( + "fxsave %0" + : + : "m" (*Buffer) // %0 + ); +} + + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and X64. + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +InternalX86FxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ) +{ + __asm__ __volatile__ ( + "fxrstor %0" + : + : "m" (*Buffer) // %0 + ); +} + + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and X64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm0, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and X64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm1, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and X64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm2, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and X64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm3, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and X64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm4, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and X64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm5, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and X64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm6, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and X64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "push %%eax \n\t" + "push %%eax \n\t" + "movq %%mm7, (%%esp)\n\t" + "pop %%eax \n\t" + "pop %%edx \n\t" + : "=A" (Data) // %0 + ); + + return Data; +} + + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm0" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm1" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm2" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm3" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm4" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm5" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm6" // %0 + : + : "m" (Value) + ); +} + + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ) +{ + __asm__ __volatile__ ( + "movq %0, %%mm7" // %0 + : + : "m" (Value) + ); +} + + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and X64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "rdtsc" + : "=A" (Data) + ); + + return Data; +} + + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and X64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ) +{ + UINT64 Data; + + __asm__ __volatile__ ( + "rdpmc" + : "=A" (Data) + : "c" (Index) + ); + + return Data; +} + + + + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ) +{ + __asm__ __volatile__ ("wbinvd":::"memory"); +} + + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ) +{ + __asm__ __volatile__ ("invd":::"memory"); + +} + + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and X64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ) +{ + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.S new file mode 100644 index 0000000..cf732b0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.S @@ -0,0 +1,48 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2011, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# InternalSwitchStack.S +# +# Abstract: +# +# Implementation of a stack switch on IA-32. +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalSwitchStack) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalSwitchStack ( +# IN SWITCH_STACK_ENTRY_POINT EntryPoint, +# IN VOID *Context1, OPTIONAL +# IN VOID *Context2, OPTIONAL +# IN VOID *NewStack +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalSwitchStack): + pushl %ebp + movl %esp, %ebp + + movl 20(%ebp), %esp # switch stack + subl $8, %esp + + movl 16(%ebp), %eax + movl %eax, 4(%esp) + movl 12(%ebp), %eax + movl %eax, (%esp) + pushl $0 # keeps gdb from unwinding stack + jmp *8(%ebp) # call and never return + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c new file mode 100644 index 0000000..182b0b0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.c @@ -0,0 +1,60 @@ +/** @file + SwitchStack() function for IA-32. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm new file mode 100644 index 0000000..b3c4f7b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/InternalSwitchStack.nasm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; Portions copyright (c) 2011, Apple Inc. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c new file mode 100644 index 0000000..e5c29b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.c @@ -0,0 +1,35 @@ +/** @file + AsmInvd function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm new file mode 100644 index 0000000..13b8795 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Invd.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.S new file mode 100644 index 0000000..451f527 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.S @@ -0,0 +1,48 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# LRotU64.S +# +# Abstract: +# +# 64-bit left rotation for Ia32 +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathLRotU64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathLRotU64 ( +# IN UINT64 Operand, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathLRotU64): + push %ebx + movb 16(%esp), %cl + movl 12(%esp), %edx + movl 8(%esp), %eax + shldl %cl, %edx, %ebx + shldl %cl, %eax, %edx + rorl %cl, %ebx + shldl %cl, %ebx, %eax + testb $32, %cl # Count >= 32? + jz L0 + movl %eax, %ecx + movl %edx, %eax + movl %ecx, %edx +L0: + pop %ebx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c new file mode 100644 index 0000000..1dfef3b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.c @@ -0,0 +1,55 @@ +/** @file + 64-bit left rotation for Ia32 + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm new file mode 100644 index 0000000..e3dc015 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LRotU64.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.S new file mode 100644 index 0000000..15394ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# LShiftU64.S +# +# Abstract: +# +# 64-bit left shift function for IA-32 +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathLShiftU64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathLShiftU64 ( +# IN UINT64 Operand, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathLShiftU64): + movb 12(%esp), %cl + xorl %eax, %eax + movl 4(%esp), %edx + testb $32, %cl # Count >= 32? + jnz L0 + movl %edx, %eax + movl 0x8(%esp), %edx +L0: + shld %cl, %eax, %edx + shl %cl, %eax + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c new file mode 100644 index 0000000..08266f7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.c @@ -0,0 +1,51 @@ +/** @file + 64-bit left shift function for IA-32. + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm new file mode 100644 index 0000000..93de11d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LShiftU64.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm new file mode 100644 index 0000000..7802a5f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Lfence.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2018, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.S new file mode 100644 index 0000000..dfd52f2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# LongJump.S +# +# Abstract: +# +# Implementation of _LongJump() on IA-32. +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalLongJump) + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalLongJump ( +# IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalLongJump): + pop %eax # skip return address + pop %edx # edx <- JumpBuffer + pop %eax # eax <- Value + movl (%edx), %ebx + movl 4(%edx), %esi + movl 8(%edx), %edi + movl 12(%edx), %ebp + movl 16(%edx), %esp + jmp *20(%edx) # restore "eip" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.c new file mode 100644 index 0000000..9d271ad --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.c @@ -0,0 +1,76 @@ +/** @file + Implementation of _LongJump() on IA-32. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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. + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is restored. + +**/ +__declspec (naked) +VOID +EFIAPI +InternalLongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ) +{ + _asm { + mov eax, [PcdGet32 (PcdControlFlowEnforcementPropertyMask)] + test eax, eax + jz CetDone + _emit 0x0F + _emit 0x20 + _emit 0xE0 ; 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 + _emit 0xF3 + _emit 0x0F + _emit 0x1E + _emit 0xC8 ; READSSP EAX + sub edx, eax ; edx = delta + mov eax, edx ; eax = delta + + shr eax, 2 ; eax = delta/sizeof(UINT32) + _emit 0xF3 + _emit 0x0F + _emit 0xAE + _emit 0xE8 ; 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 ptr [edx + 20] + } +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm new file mode 100644 index 0000000..1af52ee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/LongJump.nasm @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.S new file mode 100644 index 0000000..91ea463 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.S @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DivU64x32.S +# +# Abstract: +# +# Calculate the remainder of a 64-bit integer by a 32-bit integer +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathModU64x32) + +#------------------------------------------------------------------------------ +# UINT32 +# EFIAPI +# InternalMathModU64x32 ( +# IN UINT64 Dividend, +# IN UINT32 Divisor +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathModU64x32): + movl 8(%esp), %eax + movl 12(%esp), %ecx + xorl %edx, %edx + divl %ecx + movl 4(%esp), %eax + divl %ecx + movl %edx, %eax + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c new file mode 100644 index 0000000..3186ccb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.c @@ -0,0 +1,48 @@ +/** @file + Calculate the remainder of a 64-bit integer by a 32-bit integer + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm new file mode 100644 index 0000000..cb3681c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ModU64x32.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.S new file mode 100644 index 0000000..b6bfbee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.S @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Monitor.S +# +# Abstract: +# +# AsmMonitor function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(AsmMonitor) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmMonitor ( +# IN UINTN Eax, +# IN UINTN Ecx, +# IN UINTN Edx +# ); +#------------------------------------------------------------------------------ +ASM_PFX(AsmMonitor): + movl 4(%esp), %eax + movl 8(%esp), %ecx + movl 12(%esp), %edx + monitor %eax, %ecx, %edx # monitor + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c new file mode 100644 index 0000000..d9c9325 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.c @@ -0,0 +1,48 @@ +/** @file + AsmMonitor function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm new file mode 100644 index 0000000..6cf8ffd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Monitor.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.S new file mode 100644 index 0000000..245687a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# MultU64x32.S +# +# Abstract: +# +# Calculate the product of a 64-bit integer and a 32-bit integer +# +#------------------------------------------------------------------------------ + + + .code: + +ASM_GLOBAL ASM_PFX(InternalMathMultU64x32) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathMultU64x32 ( +# IN UINT64 Multiplicand, +# IN UINT32 Multiplier +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathMultU64x32): + movl 12(%esp), %ecx + movl %ecx, %eax + imull 8(%esp), %ecx # overflow not detectable + mull 0x4(%esp) + addl %ecx, %edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c new file mode 100644 index 0000000..8b534aa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.c @@ -0,0 +1,47 @@ +/** @file + Calculate the product of a 64-bit integer and a 32-bit integer + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm new file mode 100644 index 0000000..d4c9e51 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x32.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.S new file mode 100644 index 0000000..a3a8ec7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.S @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# MultU64x64.S +# +# Abstract: +# +# Calculate the product of a 64-bit integer and another 64-bit integer +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathMultU64x64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathMultU64x64 ( +# IN UINT64 Multiplicand, +# IN UINT64 Multiplier +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathMultU64x64): + push %ebx + movl 8(%esp), %ebx # ebx <- M1[0..31] + movl 16(%esp), %edx # edx <- M2[0..31] + movl %ebx, %ecx + movl %edx, %eax + imull 20(%esp), %ebx # ebx <- M1[0..31] * M2[32..63] + imull 12(%esp), %edx # edx <- M1[32..63] * M2[0..31] + addl %edx, %ebx # carries are abandoned + mull %ecx # edx:eax <- M1[0..31] * M2[0..31] + addl %ebx, %edx # carries are abandoned + pop %ebx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c new file mode 100644 index 0000000..5f10486 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.c @@ -0,0 +1,51 @@ +/** @file + Calculate the product of a 64-bit integer and another 64-bit integer + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm new file mode 100644 index 0000000..4fdbf86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/MultU64x64.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.S new file mode 100644 index 0000000..1b8ef9b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Mwait.S +# +# Abstract: +# +# AsmMwait function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(AsmMwait) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmMwait ( +# IN UINTN Eax, +# IN UINTN Ecx +# ); +#------------------------------------------------------------------------------ +ASM_PFX(AsmMwait): + movl 4(%esp), %eax + movl 8(%esp), %ecx + mwait + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c new file mode 100644 index 0000000..0cac0ac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.c @@ -0,0 +1,44 @@ +/** @file + AsmMwait function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm new file mode 100644 index 0000000..1a369d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Mwait.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c new file mode 100644 index 0000000..20146c0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Non-existing.c @@ -0,0 +1,57 @@ +/** @file + Non-existing BaseLib functions on Ia32 + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.S new file mode 100644 index 0000000..ddb2029 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.S @@ -0,0 +1,48 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# RRotU64.S +# +# Abstract: +# +# 64-bit right rotation for Ia32 +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMathRRotU64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathRRotU64 ( +# IN UINT64 Operand, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathRRotU64): + push %ebx + movb 16(%esp), %cl + movl 8(%esp), %eax + movl 12(%esp), %edx + shrdl %cl, %eax, %ebx + shrdl %cl, %edx, %eax + roll %cl, %ebx + shrdl %cl, %ebx, %edx + testb $32, %cl # Count >= 32? + jz L0 + movl %eax, %ecx # switch eax & edx if Count >= 32 + movl %edx, %eax + movl %ecx, %edx +L0: + pop %ebx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c new file mode 100644 index 0000000..bbf0146 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.c @@ -0,0 +1,55 @@ +/** @file + 64-bit right rotation for Ia32 + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm new file mode 100644 index 0000000..5946b3d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RRotU64.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.S new file mode 100644 index 0000000..607ec2e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# RShiftU64.S +# +# Abstract: +# +# 64-bit logical right shift function for IA-32 +# +#------------------------------------------------------------------------------ + + + .code: + +ASM_GLOBAL ASM_PFX(InternalMathRShiftU64) + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathRShiftU64 ( +# IN UINT64 Operand, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMathRShiftU64): + movb 12(%esp), %cl # cl <- Count + xorl %edx, %edx + movl 8(%esp), %eax + testb $32, %cl # Count >= 32? + jnz L0 + movl %eax, %edx + movl 0x4(%esp), %eax +L0: + shrdl %cl, %edx, %eax + shr %cl, %edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c new file mode 100644 index 0000000..2db0d97 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.c @@ -0,0 +1,51 @@ +/** @file + 64-bit logical right shift function for IA-32 + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm new file mode 100644 index 0000000..67de7ee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RShiftU64.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.S new file mode 100644 index 0000000..92048b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.S @@ -0,0 +1,80 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# RdRand.S +# +# Abstract: +# +# Generates random number through CPU RdRand instruction under 32-bit platform. +# +# Notes: +# +#------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Generates a 16 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI InternalX86RdRand16 (UINT16 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalX86RdRand16) +ASM_PFX(InternalX86RdRand16): + .byte 0x0f, 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 0x4(%esp), %edx + mov %ax, (%edx) + mov $0x1, %eax + 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); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalX86RdRand32) +ASM_PFX(InternalX86RdRand32): + .byte 0x0f, 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 0x4(%esp), %edx + mov %eax, (%edx) + mov $0x1, %eax + 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); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalX86RdRand64) +ASM_PFX(InternalX86RdRand64): + .byte 0x0f, 0xc7, 0xf0 // rdrand r32: "0f c7 /6 ModRM:r/m(w)" + jnc rn64_ret // jmp if CF=0 + mov 0x4(%esp), %edx + mov %eax, (%edx) + + .byte 0x0f, 0xc7, 0xf0 // generate another 32 bit RN + jnc rn64_ret // jmp if CF=0 + mov %eax, 0x4(%edx) + + mov $0x1, %eax + ret +rn64_ret: + xor %eax, %eax + ret // return with failure status diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm new file mode 100644 index 0000000..0668f43 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/RdRand.nasm @@ -0,0 +1,90 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c new file mode 100644 index 0000000..0e39ee7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.c @@ -0,0 +1,37 @@ +/** @file + AsmReadCr0 function + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm new file mode 100644 index 0000000..d09ceea --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr0.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c new file mode 100644 index 0000000..e75b950 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.c @@ -0,0 +1,38 @@ +/** @file + AsmReadCr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm new file mode 100644 index 0000000..5b83d89 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr2.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c new file mode 100644 index 0000000..2f01731 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.c @@ -0,0 +1,38 @@ +/** @file + AsmReadCr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm new file mode 100644 index 0000000..366e4cc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr3.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c new file mode 100644 index 0000000..d12bf5c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.c @@ -0,0 +1,40 @@ +/** @file + AsmReadCr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm new file mode 100644 index 0000000..7276092 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCr4.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c new file mode 100644 index 0000000..fe10702 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.c @@ -0,0 +1,38 @@ +/** @file + AsmReadCs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm new file mode 100644 index 0000000..3bfa816 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadCs.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c new file mode 100644 index 0000000..a3a9387 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDr0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm new file mode 100644 index 0000000..28a846e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr0.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c new file mode 100644 index 0000000..7adbd78 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDr1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm new file mode 100644 index 0000000..63c3341 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr1.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c new file mode 100644 index 0000000..5ec9695 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm new file mode 100644 index 0000000..49f16bb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr2.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c new file mode 100644 index 0000000..07b587c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm new file mode 100644 index 0000000..c09b2a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr3.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c new file mode 100644 index 0000000..c42fb1c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.c @@ -0,0 +1,40 @@ +/** @file + AsmReadDr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm new file mode 100644 index 0000000..5d784df --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr4.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c new file mode 100644 index 0000000..9743fe2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.c @@ -0,0 +1,40 @@ +/** @file + AsmReadDr5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm new file mode 100644 index 0000000..a12ecb6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr5.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c new file mode 100644 index 0000000..da04965 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDr6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm new file mode 100644 index 0000000..1daa361 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr6.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c new file mode 100644 index 0000000..e3ec1eb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDr7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm new file mode 100644 index 0000000..2777a11 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDr7.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c new file mode 100644 index 0000000..a73aa2e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.c @@ -0,0 +1,38 @@ +/** @file + AsmReadDs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm new file mode 100644 index 0000000..f9b194c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadDs.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c new file mode 100644 index 0000000..f537474 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.c @@ -0,0 +1,39 @@ +/** @file + AsmReadEflags function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm new file mode 100644 index 0000000..51c5202 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEflags.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c new file mode 100644 index 0000000..d537fcd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.c @@ -0,0 +1,38 @@ +/** @file + AsmReadEs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm new file mode 100644 index 0000000..497c647 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadEs.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c new file mode 100644 index 0000000..9cc92b5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.c @@ -0,0 +1,38 @@ +/** @file + AsmReadFs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm new file mode 100644 index 0000000..2de6296 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadFs.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c new file mode 100644 index 0000000..01d0a72 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.c @@ -0,0 +1,39 @@ +/** @file + AsmReadGdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm new file mode 100644 index 0000000..2637cbd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c new file mode 100644 index 0000000..53eab43 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.c @@ -0,0 +1,38 @@ +/** @file + AsmReadGs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm new file mode 100644 index 0000000..9c6fcee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadGs.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c new file mode 100644 index 0000000..42d9aab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.c @@ -0,0 +1,38 @@ +/** @file + AsmReadIdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm new file mode 100644 index 0000000..3ee40e5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadIdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c new file mode 100644 index 0000000..d185572 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.c @@ -0,0 +1,37 @@ +/** @file + AsmReadLdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm new file mode 100644 index 0000000..29eddf2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadLdtr.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c new file mode 100644 index 0000000..8db4ca5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm new file mode 100644 index 0000000..1330c71 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm0.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c new file mode 100644 index 0000000..f0750f4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm new file mode 100644 index 0000000..e411df8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm1.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c new file mode 100644 index 0000000..17929b2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm new file mode 100644 index 0000000..4190119 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm2.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c new file mode 100644 index 0000000..a505f18 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm new file mode 100644 index 0000000..89125e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm3.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c new file mode 100644 index 0000000..ecc3896 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm new file mode 100644 index 0000000..a0e8d16 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm4.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c new file mode 100644 index 0000000..e974717 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm new file mode 100644 index 0000000..2c96bfa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm5.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c new file mode 100644 index 0000000..a64cf50 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm new file mode 100644 index 0000000..f6a6047 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm6.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c new file mode 100644 index 0000000..0cea219 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.c @@ -0,0 +1,42 @@ +/** @file + AsmReadMm7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm new file mode 100644 index 0000000..655aa40 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMm7.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c new file mode 100644 index 0000000..e16c917 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c @@ -0,0 +1,43 @@ +/** @file + AsmReadMsr64 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm new file mode 100644 index 0000000..f1dbd41 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadMsr64.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c new file mode 100644 index 0000000..faa1f56 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.c @@ -0,0 +1,37 @@ +/** @file + AsmReadPmc function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm new file mode 100644 index 0000000..8eb0501 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadPmc.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c new file mode 100644 index 0000000..f1ced5e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.c @@ -0,0 +1,38 @@ +/** @file + AsmReadSs function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm new file mode 100644 index 0000000..6b3da79 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadSs.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c new file mode 100644 index 0000000..23273f3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.c @@ -0,0 +1,37 @@ +/** @file + AsmReadTr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm new file mode 100644 index 0000000..811153c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTr.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c new file mode 100644 index 0000000..79f676e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.c @@ -0,0 +1,37 @@ +/** @file + AsmReadTsc function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm new file mode 100644 index 0000000..f28e20e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/ReadTsc.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.S new file mode 100644 index 0000000..744a77e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.S @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetJump.S +# +# Abstract: +# +# Implementation of SetJump() on IA-32. +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(SetJump), ASM_PFX(InternalAssertJumpBuffer) + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# SetJump ( +# OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer +# ); +#------------------------------------------------------------------------------ +ASM_PFX(SetJump): + pushl 0x4(%esp) + call ASM_PFX(InternalAssertJumpBuffer) # To validate JumpBuffer + pop %ecx + pop %ecx # ecx <- return address + movl (%esp), %edx + movl %ebx, (%edx) + movl %esi, 4(%edx) + movl %edi, 8(%edx) + movl %ebp, 12(%edx) + movl %esp, 16(%edx) + movl %ecx, 20(%edx) # eip value to restore in LongJump + xorl %eax, %eax + jmp *%ecx diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.c new file mode 100644 index 0000000..3bb9ac9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.c @@ -0,0 +1,101 @@ +/** @file + Implementation of SetJump() on IA-32. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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 + ); + +/** + 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(). + +**/ +_declspec (naked) +RETURNS_TWICE +UINTN +EFIAPI +SetJump ( + OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ) +{ + _asm { + push [esp + 4] + call InternalAssertJumpBuffer + pop ecx + pop ecx + mov edx, [esp] + + xor eax, eax + mov [edx + 24], eax ; save 0 to SSP + + mov eax, [PcdGet32 (PcdControlFlowEnforcementPropertyMask)] + test eax, eax + jz CetDone + _emit 0x0F + _emit 0x20 + _emit 0xE0 ; mov eax, cr4 + bt eax, 23 ; check if CET is enabled + jnc CetDone + + mov eax, 1 + _emit 0xF3 + _emit 0x0F + _emit 0xAE + _emit 0xE8 ; INCSSP EAX to read original SSP + _emit 0xF3 + _emit 0x0F + _emit 0x1E + _emit 0xC8 ; 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 + xor eax, eax + jmp ecx + } +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm new file mode 100644 index 0000000..820ffec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SetJump.nasm @@ -0,0 +1,69 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.S new file mode 100644 index 0000000..265b6b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuId.S +# +# Abstract: +# +# AsmCpuid function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InternalMathSwapBytes64 ( +# IN UINT64 Operand +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMathSwapBytes64) +ASM_PFX(InternalMathSwapBytes64): + movl 8(%esp), %eax # eax <- upper 32 bits + movl 4(%esp), %edx # edx <- lower 32 bits + bswapl %eax + bswapl %edx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c new file mode 100644 index 0000000..3e03b65 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.c @@ -0,0 +1,43 @@ +/** @file + Implementation of 64-bit swap bytes + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm new file mode 100644 index 0000000..32fc1a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/SwapBytes64.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.S new file mode 100644 index 0000000..f5189d0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.S @@ -0,0 +1,222 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Thunk16.S +# +# Abstract: +# +# Real mode thunk +# +#------------------------------------------------------------------------------ + +#include + +ASM_GLOBAL ASM_PFX(m16Start), ASM_PFX(m16Size), ASM_PFX(mThunk16Attr), ASM_PFX(m16Gdt), ASM_PFX(m16GdtrBase), ASM_PFX(mTransition) +ASM_GLOBAL ASM_PFX(InternalAsmThunk16) + +# define the structure of IA32_REGS +.set _EDI, 0 #size 4 +.set _ESI, 4 #size 4 +.set _EBP, 8 #size 4 +.set _ESP, 12 #size 4 +.set _EBX, 16 #size 4 +.set _EDX, 20 #size 4 +.set _ECX, 24 #size 4 +.set _EAX, 28 #size 4 +.set _DS, 32 #size 2 +.set _ES, 34 #size 2 +.set _FS, 36 #size 2 +.set _GS, 38 #size 2 +.set _EFLAGS, 40 #size 4 +.set _EIP, 44 #size 4 +.set _CS, 48 #size 2 +.set _SS, 50 #size 2 +.set IA32_REGS_SIZE, 52 + + .text + .code16 + +ASM_PFX(m16Start): + +SavedGdt: .space 6 + +ASM_PFX(BackFromUserCode): + push %ss + push %cs + + calll L_Base1 # push eip +L_Base1: + pushfl + cli # disable interrupts + push %gs + push %fs + push %es + push %ds + pushal + .byte 0x66, 0xba # mov edx, imm32 +ASM_PFX(ThunkAttr): .space 4 + testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl + jz 1f + movw $0x2401, %ax + int $0x15 + cli # disable interrupts + jnc 2f +1: + testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl + jz 2f + inb $0x92, %al + orb $2, %al + outb %al, $0x92 # deactivate A20M# +2: + xorl %eax, %eax + movw %ss, %ax + leal IA32_REGS_SIZE(%esp), %ebp + mov %ebp, (_ESP - IA32_REGS_SIZE)(%bp) + mov (_EIP - IA32_REGS_SIZE)(%bp), %bx + shll $4, %eax + addl %eax, %ebp + .byte 0x66, 0xb8 # mov eax, imm32 +SavedCr4: .space 4 + movl %eax, %cr4 + lgdtl %cs:(SavedGdt - L_Base1)(%bx) + .byte 0x66, 0xb8 # mov eax, imm32 +SavedCr0: .space 4 + movl %eax, %cr0 + .byte 0xb8 # mov ax, imm16 +SavedSs: .space 2 + movl %eax, %ss + .byte 0x66, 0xbc # mov esp, imm32 +SavedEsp: .space 4 + lretl # return to protected mode + +_EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start) + .word 0x8 +_16Idtr: .word 0x3ff + .long 0 +_16Gdtr: .word GdtEnd - _NullSegDesc - 1 +_16GdtrBase: .long _NullSegDesc + +ASM_PFX(ToUserCode): + movw %ss, %dx + movw %cx, %ss # set new segment selectors + movw %cx, %ds + movw %cx, %es + movw %cx, %fs + movw %cx, %gs + movl %eax, %cr0 # real mode starts at next instruction + # which (per SDM) *must* be a far JMP. + ljmpw $0,$0 # will be filled in by InternalAsmThunk16 +L_Base: # to point here. + movl %ebp, %cr4 + movw %si, %ss # set up 16-bit stack segment + xchgl %ebx, %esp # set up 16-bit stack pointer + + movw IA32_REGS_SIZE(%esp), %bp # get BackToUserCode address from stack + mov %dx, %cs:(SavedSs - ASM_PFX(BackFromUserCode))(%bp) + mov %ebx, %cs:(SavedEsp - ASM_PFX(BackFromUserCode))(%bp) + lidtl %cs:(_16Idtr - ASM_PFX(BackFromUserCode))(%bp) + popal + pop %ds + pop %es + pop %fs + pop %gs + popfl + lretl # transfer control to user code + +_NullSegDesc: .quad 0 +_16CsDesc: + .word -1 + .word 0 + .byte 0 + .byte 0x9b + .byte 0x8f # 16-bit segment, 4GB limit + .byte 0 +_16DsDesc: + .word -1 + .word 0 + .byte 0 + .byte 0x93 + .byte 0x8f # 16-bit segment, 4GB limit + .byte 0 +GdtEnd: + + .code32 +# +# @param RegSet The pointer to a IA32_DWORD_REGS structure +# @param Transition The pointer to the transition code +# @return The address of the 16-bit stack after returning from user code +# +ASM_PFX(InternalAsmThunk16): + push %ebp + push %ebx + push %esi + push %edi + push %ds + push %es + push %fs + push %gs + movl 36(%esp), %esi # esi <- RegSet + movzwl _SS(%esi), %edx + mov _ESP(%esi), %edi + add $(-(IA32_REGS_SIZE + 4)), %edi + movl %edi, %ebx # ebx <- stack offset + imul $0x10, %edx, %eax + push $(IA32_REGS_SIZE / 4) + addl %eax, %edi # edi <- linear address of 16-bit stack + pop %ecx + rep + movsl # copy RegSet + movl 40(%esp), %eax # eax <- address of transition code + movl %edx, %esi # esi <- 16-bit stack segment + lea (SavedCr0 - ASM_PFX(m16Start))(%eax), %edx + movl %eax, %ecx + andl $0xf, %ecx + shll $12, %eax + lea (ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start))(%ecx), %ecx + movw %cx, %ax + stosl # [edi] <- return address of user code + addl $(L_Base - ASM_PFX(BackFromUserCode)), %eax + movl %eax, (L_Base - SavedCr0 - 4)(%edx) + sgdtl (SavedGdt - SavedCr0)(%edx) + sidtl 0x24(%esp) + movl %cr0, %eax + movl %eax, (%edx) # save CR0 in SavedCr0 + andl $0x7ffffffe, %eax # clear PE, PG bits + movl %cr4, %ebp + mov %ebp, (SavedCr4 - SavedCr0)(%edx) + andl $0xffffffcf, %ebp # clear PAE, PSE bits + pushl $0x10 + pop %ecx # ecx <- selector for data segments + lgdtl (_16Gdtr - SavedCr0)(%edx) + pushfl + lcall *(_EntryPoint - SavedCr0)(%edx) + popfl + lidtl 0x24(%esp) + lea -IA32_REGS_SIZE(%ebp), %eax + pop %gs + pop %fs + pop %es + pop %ds + pop %edi + pop %esi + pop %ebx + pop %ebp + ret + + .const: + +ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) +ASM_PFX(mThunk16Attr): .word ASM_PFX(ThunkAttr) - ASM_PFX(m16Start) +ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start) +ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start) +ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start) diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm new file mode 100644 index 0000000..1c02140 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm @@ -0,0 +1,263 @@ + +#include "BaseLibInternals.h" + +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c new file mode 100644 index 0000000..16b9cf7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.c @@ -0,0 +1,35 @@ +/** @file + AsmWbinvd function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm new file mode 100644 index 0000000..7bdf793 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/Wbinvd.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c new file mode 100644 index 0000000..177da80 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteCr0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm new file mode 100644 index 0000000..0c0ea5c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr0.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c new file mode 100644 index 0000000..efbdf63 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteCr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm new file mode 100644 index 0000000..2b7afa8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr2.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c new file mode 100644 index 0000000..6aeb0f2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteCr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm new file mode 100644 index 0000000..90a2219 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr3.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c new file mode 100644 index 0000000..f145564 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.c @@ -0,0 +1,39 @@ +/** @file + AsmWriteCr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm new file mode 100644 index 0000000..486fe24 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteCr4.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c new file mode 100644 index 0000000..bd5e101 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteDr0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm new file mode 100644 index 0000000..5c2af94 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr0.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c new file mode 100644 index 0000000..695f346 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteDr1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm new file mode 100644 index 0000000..a35389e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr1.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c new file mode 100644 index 0000000..8a24b94 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteDr2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm new file mode 100644 index 0000000..936cefc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr2.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c new file mode 100644 index 0000000..3a0921b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteDr3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm new file mode 100644 index 0000000..d7a58cf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr3.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c new file mode 100644 index 0000000..acfe93f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.c @@ -0,0 +1,39 @@ +/** @file + AsmWriteDr4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm new file mode 100644 index 0000000..95c6d06 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr4.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c new file mode 100644 index 0000000..4e00ceb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.c @@ -0,0 +1,39 @@ +/** @file + AsmWriteDr5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm new file mode 100644 index 0000000..a6256ef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr5.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c new file mode 100644 index 0000000..29ab483 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteDr6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm new file mode 100644 index 0000000..75ae84b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr6.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c new file mode 100644 index 0000000..aa2286f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteDr7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm new file mode 100644 index 0000000..06539e3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteDr7.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c new file mode 100644 index 0000000..905d585 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.c @@ -0,0 +1,39 @@ +/** @file + AsmWriteGdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm new file mode 100644 index 0000000..4f4f590 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteGdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c new file mode 100644 index 0000000..ceef0e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.c @@ -0,0 +1,41 @@ +/** @file + AsmWriteIdtr function + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm new file mode 100644 index 0000000..f82f3a8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteIdtr.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c new file mode 100644 index 0000000..fe9ad0f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.c @@ -0,0 +1,39 @@ +/** @file + AsmWriteLdtr function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm new file mode 100644 index 0000000..e3d9e0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteLdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c new file mode 100644 index 0000000..076ccd9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.c @@ -0,0 +1,38 @@ +/** @file + AsmWriteMm0 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm new file mode 100644 index 0000000..c43005b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm0.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c new file mode 100644 index 0000000..dadf7c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.c @@ -0,0 +1,38 @@ +/** @file + AsmWriteMm1 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm new file mode 100644 index 0000000..b3171b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm1.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c new file mode 100644 index 0000000..830a03e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.c @@ -0,0 +1,38 @@ +/** @file + AsmWriteMm2 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm new file mode 100644 index 0000000..ff7bcee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm2.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c new file mode 100644 index 0000000..c9c6476 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.c @@ -0,0 +1,38 @@ +/** @file + AsmWriteMm3 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm new file mode 100644 index 0000000..0e60af5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm3.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c new file mode 100644 index 0000000..1822811 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteMm4 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm new file mode 100644 index 0000000..26552fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm4.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c new file mode 100644 index 0000000..f6ad0e0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.c @@ -0,0 +1,37 @@ +/** @file + AsmWriteMm5 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm new file mode 100644 index 0000000..8bf690c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm5.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c new file mode 100644 index 0000000..28e06b5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.c @@ -0,0 +1,38 @@ +/** @file + AsmWriteMm6 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm new file mode 100644 index 0000000..6234135 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm6.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c new file mode 100644 index 0000000..d7350bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.c @@ -0,0 +1,38 @@ +/** @file + AsmWriteMm7 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm new file mode 100644 index 0000000..c4afbe5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMm7.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c new file mode 100644 index 0000000..39a792b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c @@ -0,0 +1,49 @@ +/** @file + AsmWriteMsr64 function + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm new file mode 100644 index 0000000..4eb9706 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteMsr64.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm new file mode 100644 index 0000000..1fc18e1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Ia32/WriteTr.nasm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2017, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU32.c new file mode 100644 index 0000000..573c30c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU32.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU64.c new file mode 100644 index 0000000..c938456 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LRotU64.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LShiftU64.c new file mode 100644 index 0000000..e3be23f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LShiftU64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LinkedList.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LinkedList.c new file mode 100644 index 0000000..0c7cd83 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LinkedList.c @@ -0,0 +1,605 @@ +/** @file + Linked List Library Functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LongJump.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LongJump.c new file mode 100644 index 0000000..f432cfd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LongJump.c @@ -0,0 +1,47 @@ +/** @file + Long Jump functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet32.c new file mode 100644 index 0000000..b613cd2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet32.c @@ -0,0 +1,47 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet64.c new file mode 100644 index 0000000..911fbda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/LowBitSet64.c @@ -0,0 +1,50 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Math64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Math64.c new file mode 100644 index 0000000..662d559 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Math64.c @@ -0,0 +1,368 @@ +/** @file + Leaf math worker functions that require 64-bit arithmetic support from the + compiler. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ModU64x32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ModU64x32.c new file mode 100644 index 0000000..57c3e41 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/ModU64x32.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultS64x64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultS64x64.c new file mode 100644 index 0000000..c953b0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultS64x64.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x32.c new file mode 100644 index 0000000..1c49106 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x32.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x64.c new file mode 100644 index 0000000..fee7f00 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/MultU64x64.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU32.c new file mode 100644 index 0000000..64fdd76 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU32.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU64.c new file mode 100644 index 0000000..28fdf41 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RRotU64.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RShiftU64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RShiftU64.c new file mode 100644 index 0000000..3494c32 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/RShiftU64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SafeString.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SafeString.c new file mode 100644 index 0000000..baf6e41 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SafeString.c @@ -0,0 +1,3650 @@ +/** @file + Safe String functions. + + Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BaseLibInternals.h" + +#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength)) + +#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength)) + +#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \ + do { \ + ASSERT (Expression); \ + if (!(Expression)) { \ + 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 would be returned, then the function will also 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 would be returned, then the function will also 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 would be returned, then the function will also 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 would be returned, then the function will also 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in 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(). + + 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 NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If String is not aligned in 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(). + + 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 NULL, then ASSERT(). + + If Address is NULL, then ASSERT(). + + If String is not aligned in 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(). + + 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 NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + 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(). + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), 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 would be returned, then the function will also ASSERT(). + + 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 would be returned, then the function will also ASSERT(). + + 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 would be returned, then the function will also ASSERT(). + + 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 would be returned, then the function will also ASSERT(). + + 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength Ascii characters, not including the + Null-terminator, 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 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 would be returned, then the function will also 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 would be returned, then the function will also 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 would be returned, then the function will also 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 would be returned, then the function will also 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 String is NULL, then ASSERT(). + + If Address is NULL, 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 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 String is NULL, then ASSERT(). + + If Address is NULL, 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 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] + + If String is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + + @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. + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), then ASSERT(). + + @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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SetJump.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SetJump.c new file mode 100644 index 0000000..4e6e00c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SetJump.c @@ -0,0 +1,40 @@ +/** @file + Internal ASSERT () functions for SetJump. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/String.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/String.c new file mode 100644 index 0000000..a8ff885 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/String.c @@ -0,0 +1,2143 @@ +/** @file + Unicode and ASCII string primitives. + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 + +// +// The basis for Base64 encoding is RFC 4686 https://tools.ietf.org/html/rfc4648 +// +// RFC 4686 has a number of MAY and SHOULD cases. This implementation chooses +// the more restrictive versions for security concerns (see RFC 4686 section 3.3). +// +// A invalid character, if encountered during the decode operation, causes the data +// to be rejected. In addition, the '=' padding character is only allowed at the end +// of the Base64 encoded string. +// +#define BAD_V 99 + +STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +STATIC UINT8 DecodingTable[] = { + // + // Valid characters ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ + // Also, set '=' as a zero for decoding + // 0 , 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 0 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 10 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, 62, BAD_V, BAD_V, BAD_V, 63, // 20 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD_V, BAD_V, BAD_V, 0, BAD_V, BAD_V, // 30 + BAD_V, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 50 + BAD_V, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 70 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 80 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // 90 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // a0 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // b0 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // c0 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // d0 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, // d0 + BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V, BAD_V // f0 +}; + +/** + 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; +} + +/** + Convert Base64 ascii string to binary data based on RFC4648. + + Produce Null-terminated binary data in the output buffer specified by Destination and DestinationSize. + The binary data is produced by converting the Base64 ascii string specified by Source and SourceLength. + + @param Source Input ASCII characters + @param SourceLength Number of ASCII characters + @param Destination Pointer to output buffer + @param DestinationSize Caller is responsible for passing in buffer of at least DestinationSize. + Set 0 to get the size needed. Set to bytes stored on return. + + @retval RETURN_SUCCESS When binary 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_INVALID_PARAMETER If there is any invalid character in input stream. + @retval RETURN_BUFFER_TOO_SMALL If buffer length is smaller than required buffer size. + **/ +RETURN_STATUS +EFIAPI +Base64Decode ( + IN CONST CHAR8 *Source, + IN UINTN SourceLength, + OUT UINT8 *Destination OPTIONAL, + IN OUT UINTN *DestinationSize + ) +{ + + UINT32 Value; + CHAR8 Chr; + INTN BufferSize; + UINTN SourceIndex; + UINTN DestinationIndex; + UINTN Index; + UINTN ActualSourceLength; + + // + // Check pointers are not NULL + // + if ((Source == NULL) || (DestinationSize == NULL)) { + return RETURN_INVALID_PARAMETER; + } + + // + // Check if SourceLength or DestinationSize is valid + // + if ((SourceLength >= (MAX_ADDRESS - (UINTN)Source)) || (*DestinationSize >= (MAX_ADDRESS - (UINTN)Destination))){ + return RETURN_INVALID_PARAMETER; + } + + ActualSourceLength = 0; + BufferSize = 0; + + // + // Determine the actual number of valid characters in the string. + // All invalid characters except selected white space characters, + // will cause the Base64 string to be rejected. White space to allow + // properly formatted XML will be ignored. + // + // See section 3.3 of RFC 4648. + // + for (SourceIndex = 0; SourceIndex < SourceLength; SourceIndex++) { + + // + // '=' is part of the quantum + // + if (Source[SourceIndex] == '=') { + ActualSourceLength++; + BufferSize--; + + // + // Only two '=' characters can be valid. + // + if (BufferSize < -2) { + return RETURN_INVALID_PARAMETER; + } + } + else { + Chr = Source[SourceIndex]; + if (BAD_V != DecodingTable[(UINT8) Chr]) { + + // + // The '=' characters are only valid at the end, so any + // valid character after an '=', will be flagged as an error. + // + if (BufferSize < 0) { + return RETURN_INVALID_PARAMETER; + } + ActualSourceLength++; + } + else { + + // + // The reset of the decoder will ignore all invalid characters allowed here. + // Ignoring selected white space is useful. In this case, the decoder will + // ignore ' ', '\t', '\n', and '\r'. + // + if ((Chr != ' ') &&(Chr != '\t') &&(Chr != '\n') &&(Chr != '\r')) { + return RETURN_INVALID_PARAMETER; + } + } + } + } + + // + // The Base64 character string must be a multiple of 4 character quantums. + // + if (ActualSourceLength % 4 != 0) { + return RETURN_INVALID_PARAMETER; + } + + BufferSize += ActualSourceLength / 4 * 3; + if (BufferSize < 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // BufferSize is >= 0 + // + if ((Destination == NULL) || (*DestinationSize < (UINTN) BufferSize)) { + *DestinationSize = BufferSize; + return RETURN_BUFFER_TOO_SMALL; + } + + // + // If no decodable characters, return a size of zero. RFC 4686 test vector 1. + // + if (ActualSourceLength == 0) { + *DestinationSize = 0; + return RETURN_SUCCESS; + } + + // + // Input data is verified to be a multiple of 4 valid charcters. Process four + // characters at a time. Uncounted (ie. invalid) characters will be ignored. + // + for (SourceIndex = 0, DestinationIndex = 0; (SourceIndex < SourceLength) && (DestinationIndex < *DestinationSize); ) { + Value = 0; + + // + // Get 24 bits of data from 4 input characters, each character representing 6 bits + // + for (Index = 0; Index < 4; Index++) { + do { + Chr = DecodingTable[(UINT8) Source[SourceIndex++]]; + } while (Chr == BAD_V); + Value <<= 6; + Value |= (UINT32)Chr; + } + + // + // Store 3 bytes of binary data (24 bits) + // + *Destination++ = (UINT8) (Value >> 16); + DestinationIndex++; + + // + // Due to the '=' special cases for the two bytes at the end, + // we have to check the length and not store the padding data + // + if (DestinationIndex++ < *DestinationSize) { + *Destination++ = (UINT8) (Value >> 8); + } + if (DestinationIndex++ < *DestinationSize) { + *Destination++ = (UINT8) Value; + } + } + + return RETURN_SUCCESS; +} + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes16.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes16.c new file mode 100644 index 0000000..39373bd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes16.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes32.c new file mode 100644 index 0000000..a0aecf5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes32.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes64.c new file mode 100644 index 0000000..946fc83 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwapBytes64.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwitchStack.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwitchStack.c new file mode 100644 index 0000000..656c673 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/SwitchStack.c @@ -0,0 +1,76 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Unaligned.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Unaligned.c new file mode 100644 index 0000000..04249c8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/Unaligned.c @@ -0,0 +1,222 @@ +/** @file + Unaligned access functions of BaseLib. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c new file mode 100644 index 0000000..2f08ca9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.c @@ -0,0 +1,39 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm new file mode 100644 index 0000000..d39f8fe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuBreakpoint.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.S new file mode 100644 index 0000000..19ae1c7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.S @@ -0,0 +1,60 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuId.S +# +# Abstract: +# +# AsmCpuid function +# +# Notes: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmCpuid ( +# IN UINT32 RegisterInEax, +# OUT UINT32 *RegisterOutEax OPTIONAL, +# OUT UINT32 *RegisterOutEbx OPTIONAL, +# OUT UINT32 *RegisterOutEcx OPTIONAL, +# OUT UINT32 *RegisterOutEdx OPTIONAL +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmCpuid) +ASM_PFX(AsmCpuid): + push %rbx + mov %ecx, %eax + push %rax # save Index on stack + push %rdx + cpuid + test %r9, %r9 + jz L1 + mov %ecx, (%r9) +L1: + pop %rcx + jrcxz L2 + mov %eax, (%rcx) +L2: + mov %r8, %rcx + jrcxz L3 + mov %ebx, (%rcx) +L3: + mov 0x38(%rsp), %rcx + jrcxz L4 + mov %edx, (%rcx) +L4: + pop %rax # restore Index to rax as return value + pop %rbx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm new file mode 100644 index 0000000..3f3060f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuId.nasm @@ -0,0 +1,64 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.S new file mode 100644 index 0000000..c41456f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.S @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CpuIdEx.S +# +# Abstract: +# +# AsmCpuidEx function +# +# Notes: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# 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 +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmCpuidEx) +ASM_PFX(AsmCpuidEx): + push %rbx + movl %ecx,%eax + movl %edx,%ecx + push %rax # save Index on stack + cpuid + mov 0x38(%rsp), %r10 + test %r10, %r10 + jz L1 + mov %ecx,(%r10) +L1: + mov %r8, %rcx + jrcxz L2 + movl %eax,(%rcx) +L2: + mov %r9, %rcx + jrcxz L3 + mov %ebx, (%rcx) +L3: + mov 0x40(%rsp), %rcx + jrcxz L4 + mov %edx, (%rcx) +L4: + pop %rax # restore Index to rax as return value + pop %rbx + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm new file mode 100644 index 0000000..624b8df --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuIdEx.nasm @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm new file mode 100644 index 0000000..83efe57 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/CpuPause.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.S new file mode 100644 index 0000000..45c1a22 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DisableCache.S +# +# 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: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmDisableCache ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmDisableCache) +ASM_PFX(AsmDisableCache): + movq %cr0, %rax + btsq $30, %rax + btrq $29, %rax + movq %rax, %cr0 + wbinvd + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm new file mode 100644 index 0000000..9f565b1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableCache.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm new file mode 100644 index 0000000..eb11e14 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisableInterrupts.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.S new file mode 100644 index 0000000..ecf580b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.S @@ -0,0 +1,82 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# DisablePaging64.S +# +# Abstract: +# +# AsmDisablePaging64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalX86DisablePaging64 ( +# IN UINT16 Cs, +# IN UINT32 EntryPoint, +# IN UINT32 Context1, OPTIONAL +# IN UINT32 Context2, OPTIONAL +# IN UINT32 NewStack +# ); +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalX86DisablePaging64) +ASM_PFX(InternalX86DisablePaging64): + cli + lea L1(%rip), %rsi # rsi <- The start address of transition code + mov 0x28(%rsp), %edi # rdi <- New stack + lea _mTransitionEnd(%rip), %rax # rax <- end of transition code + sub %rsi, %rax # rax <- The size of transition piece code + add $4, %rax # round rax up to the next 4 byte boundary + and $0xfc, %al + sub %rax, %rdi # rdi <- use stack to hold transition code + mov %edi, %r10d # r10 <- The start address of transicition code below 4G + push %rcx # save rcx to stack + mov %rax, %rcx # rcx <- The size of transition piece code + rep + movsb # copy transition code to (new stack - 64byte) below 4G + pop %rcx # restore rcx + + mov %r8d, %esi + mov %r9d, %edi + mov %r10d, %eax + sub $4, %eax + push %rcx # push Cs to stack + push %r10 # push address of transition code on stack + .byte 0x48, 0xcb # retq: Use far return to load CS register from stack + # (Use raw byte code since some GNU assemblers generates incorrect code for "retq") +L1: + mov %eax,%esp # set up new stack + mov %cr0,%rax + btr $0x1f,%eax # clear CR0.PG + mov %rax,%cr0 # disable paging + + mov %edx,%ebx # save EntryPoint to ebx, for rdmsr will overwrite edx + mov $0xc0000080,%ecx + rdmsr + and $0xfe,%ah # clear LME + wrmsr + mov %cr4,%rax + and $0xdf,%al # clear PAE + mov %rax,%cr4 + push %rdi # push Context2 + push %rsi # push Context1 + callq *%rbx # transfer control to EntryPoint + jmp . # no one should get here + +_mTransitionEnd : diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm new file mode 100644 index 0000000..9410b35 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/DisablePaging64.nasm @@ -0,0 +1,84 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.S new file mode 100644 index 0000000..9af08df --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EnableCache.S +# +# 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: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmEnableCache ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(AsmEnableCache) +ASM_PFX(AsmEnableCache): + wbinvd + movq %cr0, %rax + btrq $30, %rax + btrq $29, %rax + movq %rax, %cr0 + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm new file mode 100644 index 0000000..317ee8c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableCache.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.S new file mode 100644 index 0000000..0ffc6e9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.S @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EnableDisableInterrupts.S +# +# Abstract: +# +# EnableDisableInterrupts function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# EnableDisableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(EnableDisableInterrupts) +ASM_PFX(EnableDisableInterrupts): + sti + cli + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm new file mode 100644 index 0000000..ad90580 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableDisableInterrupts.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm new file mode 100644 index 0000000..2b9f67c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/EnableInterrupts.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm new file mode 100644 index 0000000..6fff993 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FlushCacheLine.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm new file mode 100644 index 0000000..6b2db0e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxRestore.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm new file mode 100644 index 0000000..f729b3a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/FxSave.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/GccInline.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/GccInline.c new file mode 100644 index 0000000..f8a9ff8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/GccInline.c @@ -0,0 +1,1806 @@ +/** @file + GCC inline implementation of BaseLib processor specific functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "BaseLibInternals.h" + + + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + // This is a little bit of overkill and it is more about the compiler that it is + // actually processor synchronization. This is like the _ReadWriteBarrier + // Microsoft specific intrinsic + __asm__ __volatile__ ("":::"memory"); +} + + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("sti"::: "memory"); +} + + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + __asm__ __volatile__ ("cli"::: "memory"); +} + + + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ) +{ + __asm__ __volatile__ ("pause"); +} + + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __asm__ __volatile__ ("int $3"); +} + + + +/** + 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 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; +} + + + +/** + 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 + ); +} + + +/** + 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; +} + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm new file mode 100644 index 0000000..8fcd187 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Invd.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm new file mode 100644 index 0000000..814d025 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Lfence.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2018, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.S new file mode 100644 index 0000000..885fdd9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.S @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# LongJump.S +# +# Abstract: +# +# Implementation of _LongJump() on x64. +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# InternalLongJump ( +# IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalLongJump) +ASM_PFX(InternalLongJump): + mov (%rcx), %rbx + mov 0x8(%rcx), %rsp + mov 0x10(%rcx), %rbp + mov 0x18(%rcx), %rdi + mov 0x20(%rcx), %rsi + mov 0x28(%rcx), %r12 + mov 0x30(%rcx), %r13 + mov 0x38(%rcx), %r14 + mov 0x40(%rcx), %r15 + # load non-volatile fp registers + ldmxcsr 0x50(%rcx) + movdqu 0x58(%rcx), %xmm6 + movdqu 0x68(%rcx), %xmm7 + movdqu 0x78(%rcx), %xmm8 + movdqu 0x88(%rcx), %xmm9 + movdqu 0x98(%rcx), %xmm10 + movdqu 0xA8(%rcx), %xmm11 + movdqu 0xB8(%rcx), %xmm12 + movdqu 0xC8(%rcx), %xmm13 + movdqu 0xD8(%rcx), %xmm14 + movdqu 0xE8(%rcx), %xmm15 + mov %rdx, %rax # set return value + jmp *0x48(%rcx) diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm new file mode 100644 index 0000000..f328222 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/LongJump.nasm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm new file mode 100644 index 0000000..980678a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Monitor.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm new file mode 100644 index 0000000..912d7a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Mwait.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c new file mode 100644 index 0000000..76503e3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Non-existing.c @@ -0,0 +1,153 @@ +/** @file + Non-existing BaseLib functions on x64 + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.S new file mode 100644 index 0000000..0556979 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.S @@ -0,0 +1,72 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# RdRand.S +# +# Abstract: +# +# Generates random number through CPU RdRand instruction under 64-bit platform. +# +# Notes: +# +#------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Generates a 16 bit random number through RDRAND instruction. +// Return TRUE if Rand generated successfully, or FALSE if not. +// +// BOOLEAN EFIAPI InternalX86RdRand16 (UINT16 *Rand); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalX86RdRand16) +ASM_PFX(InternalX86RdRand16): + .byte 0x0f, 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 %ax, (%rcx) + mov $0x1, %rax + 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); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalX86RdRand32) +ASM_PFX(InternalX86RdRand32): + .byte 0x0f, 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 %eax, (%rcx) + mov $0x1, %rax + 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); +//------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalX86RdRand64) +ASM_PFX(InternalX86RdRand64): + .byte 0x48, 0x0f, 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 %rax, (%rcx) + mov $0x1, %rax + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm new file mode 100644 index 0000000..e1a21eb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/RdRand.nasm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm new file mode 100644 index 0000000..0c6e2f9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr0.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm new file mode 100644 index 0000000..45055ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr2.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm new file mode 100644 index 0000000..3a3a935 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr3.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm new file mode 100644 index 0000000..68b6028 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCr4.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm new file mode 100644 index 0000000..e5d09cb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadCs.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm new file mode 100644 index 0000000..bf5955a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr0.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm new file mode 100644 index 0000000..a797490 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr1.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm new file mode 100644 index 0000000..2ef64f4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr2.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm new file mode 100644 index 0000000..1222185 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr3.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm new file mode 100644 index 0000000..c8d1581 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr4.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm new file mode 100644 index 0000000..771e71c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr5.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm new file mode 100644 index 0000000..a75656d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr6.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm new file mode 100644 index 0000000..65d8f76 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDr7.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm new file mode 100644 index 0000000..6eba940 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadDs.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm new file mode 100644 index 0000000..98d4b49 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEflags.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm new file mode 100644 index 0000000..ea016d8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadEs.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm new file mode 100644 index 0000000..123790e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadFs.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm new file mode 100644 index 0000000..0f51605 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm new file mode 100644 index 0000000..8786454 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadGs.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm new file mode 100644 index 0000000..cfc32c7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadIdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm new file mode 100644 index 0000000..9fbf5ac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadLdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm new file mode 100644 index 0000000..a69149b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm0.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm new file mode 100644 index 0000000..917494c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm1.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm new file mode 100644 index 0000000..d31c34a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm2.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm new file mode 100644 index 0000000..9cabaa2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm3.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm new file mode 100644 index 0000000..7eae1fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm4.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm new file mode 100644 index 0000000..4784d6a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm5.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm new file mode 100644 index 0000000..58f8b98 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm6.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm new file mode 100644 index 0000000..46e4807 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMm7.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c new file mode 100644 index 0000000..06a9dbc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.c @@ -0,0 +1,39 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm new file mode 100644 index 0000000..650be2c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadMsr64.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm new file mode 100644 index 0000000..507e9b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadPmc.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm new file mode 100644 index 0000000..be764ba --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadSs.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm new file mode 100644 index 0000000..df2f7d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm new file mode 100644 index 0000000..61fa2f0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/ReadTsc.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.S new file mode 100644 index 0000000..ef6beee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.S @@ -0,0 +1,53 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetJump.S +# +# Abstract: +# +# Implementation of SetJump() on x86_64 +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(SetJump) +ASM_PFX(SetJump): + push %rcx + add $0xffffffffffffffe0,%rsp + call ASM_PFX(InternalAssertJumpBuffer) + add $0x20,%rsp + pop %rcx + pop %rdx + mov %rbx,(%rcx) + mov %rsp,0x8(%rcx) + mov %rbp,0x10(%rcx) + mov %rdi,0x18(%rcx) + mov %rsi,0x20(%rcx) + mov %r12,0x28(%rcx) + mov %r13,0x30(%rcx) + mov %r14,0x38(%rcx) + mov %r15,0x40(%rcx) + mov %rdx,0x48(%rcx) + # save non-volatile fp registers + stmxcsr 0x50(%rcx) + movdqu %xmm6, 0x58(%rcx) + movdqu %xmm7, 0x68(%rcx) + movdqu %xmm8, 0x78(%rcx) + movdqu %xmm9, 0x88(%rcx) + movdqu %xmm10, 0x98(%rcx) + movdqu %xmm11, 0xA8(%rcx) + movdqu %xmm12, 0xB8(%rcx) + movdqu %xmm13, 0xC8(%rcx) + movdqu %xmm14, 0xD8(%rcx) + movdqu %xmm15, 0xE8(%rcx) + xor %rax,%rax + jmpq *%rdx diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm new file mode 100644 index 0000000..42ad913 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SetJump.nasm @@ -0,0 +1,87 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.S new file mode 100644 index 0000000..40a2ae9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SwitchStack.S +# +# Abstract: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# 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 +# +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalSwitchStack) +ASM_PFX(InternalSwitchStack): + pushq %rbp + movq %rsp, %rbp + + mov %rcx, %rax // Shift registers for new call + mov %rdx, %rcx + mov %r8, %rdx + # + # Reserve space for register parameters (rcx, rdx, r8 & r9) on the stack, + # in case the callee wishes to spill them. + # + lea -0x20(%r9), %rsp + pushq $0 // stop gdb stack unwind + jmp *%rax // call EntryPoint () diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm new file mode 100644 index 0000000..652baf6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -0,0 +1,51 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.S new file mode 100644 index 0000000..c382906 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.S @@ -0,0 +1,334 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Thunk16.S +# +# Abstract: +# +# Real mode thunk +# +#------------------------------------------------------------------------------ + +#include + +ASM_GLOBAL ASM_PFX(m16Start) +ASM_GLOBAL ASM_PFX(m16Size) +ASM_GLOBAL ASM_PFX(mThunk16Attr) +ASM_GLOBAL ASM_PFX(m16Gdt) +ASM_GLOBAL ASM_PFX(m16GdtrBase) +ASM_GLOBAL ASM_PFX(mTransition) +ASM_GLOBAL ASM_PFX(InternalAsmThunk16) + +# define the structure of IA32_REGS +.set _EDI, 0 #size 4 +.set _ESI, 4 #size 4 +.set _EBP, 8 #size 4 +.set _ESP, 12 #size 4 +.set _EBX, 16 #size 4 +.set _EDX, 20 #size 4 +.set _ECX, 24 #size 4 +.set _EAX, 28 #size 4 +.set _DS, 32 #size 2 +.set _ES, 34 #size 2 +.set _FS, 36 #size 2 +.set _GS, 38 #size 2 +.set _EFLAGS, 40 #size 8 +.set _EIP, 48 #size 4 +.set _CS, 52 #size 2 +.set _SS, 54 #size 2 +.set IA32_REGS_SIZE, 56 + + .data + +.set Lm16Size, ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) +ASM_PFX(m16Size): .word Lm16Size +.set LmThunk16Attr, L_ThunkAttr - ASM_PFX(m16Start) +ASM_PFX(mThunk16Attr): .word LmThunk16Attr +.set Lm16Gdt, ASM_PFX(NullSeg) - ASM_PFX(m16Start) +ASM_PFX(m16Gdt): .word Lm16Gdt +.set Lm16GdtrBase, _16GdtrBase - ASM_PFX(m16Start) +ASM_PFX(m16GdtrBase): .word Lm16GdtrBase +.set LmTransition, _EntryPoint - ASM_PFX(m16Start) +ASM_PFX(mTransition): .word LmTransition + + .text + +ASM_PFX(m16Start): + +SavedGdt: .space 10 + +#------------------------------------------------------------------------------ +# _BackFromUserCode() takes control in real mode after 'retf' has been executed +# by user code. It will be shadowed to somewhere in memory below 1MB. +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(BackFromUserCode) +ASM_PFX(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. + # + # Some instructions for manipulation of segment registers have to be written + # in opcode since 64-bit MASM prevents accesses to those registers. + # + .byte 0x16 # push ss + .byte 0xe # push cs + .byte 0x66 + call L_Base # push eip +L_Base: + .byte 0x66 + pushq $0 # reserved high order 32 bits of EFlags + .byte 0x66, 0x9c # pushfd actually + cli # disable interrupts + push %gs + push %fs + .byte 6 # push es + .byte 0x1e # push ds + .byte 0x66,0x60 # pushad + .byte 0x66,0xba # mov edx, imm32 +L_ThunkAttr: .space 4 + testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl + jz L_1 + movl $0x15cd2401,%eax # mov ax, 2401h & int 15h + cli # disable interrupts + jnc L_2 +L_1: + testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl + jz L_2 + inb $0x92,%al + orb $2,%al + outb %al, $0x92 # deactivate A20M# +L_2: + xorw %ax, %ax # xor eax, eax + movl %ss, %eax # mov ax, ss + lea IA32_REGS_SIZE(%esp), %bp + # + # rsi in the following 2 instructions is indeed bp in 16-bit code + # + movw %bp, (_ESP - IA32_REGS_SIZE)(%rsi) + .byte 0x66 + movl (_EIP - IA32_REGS_SIZE)(%rsi), %ebx + shlw $4,%ax # shl eax, 4 + addw %ax,%bp # add ebp, eax + movw %cs,%ax + shlw $4,%ax + lea (L_64BitCode - L_Base)(%ebx, %eax), %ax + .byte 0x66,0x2e,0x89,0x87 # mov cs:[bx + (L_64Eip - L_Base)], eax + .word L_64Eip - L_Base + .byte 0x66,0xb8 # mov eax, imm32 +L_SavedCr4: .space 4 + movq %rax, %cr4 + # + # rdi in the instruction below is indeed bx in 16-bit code + # + .byte 0x66,0x2e # 2eh is "cs:" segment override + lgdt (SavedGdt - L_Base)(%rdi) + .byte 0x66 + movl $0xc0000080,%ecx + rdmsr + orb $1,%ah + wrmsr + .byte 0x66,0xb8 # mov eax, imm32 +L_SavedCr0: .space 4 + movq %rax, %cr0 + .byte 0x66,0xea # jmp far cs:L_64Bit +L_64Eip: .space 4 +L_SavedCs: .space 2 +L_64BitCode: + .byte 0x90 + .byte 0x48,0xbc # mov rsp, imm64 +L_SavedSp: .space 8 # restore stack + nop + ret + +_EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start) + .word CODE16 +_16Gdtr: .word GDT_SIZE - 1 +_16GdtrBase: .quad 0 +_16Idtr: .word 0x3ff + .long 0 + +#------------------------------------------------------------------------------ +# _ToUserCode() takes control in real mode before passing control to user code. +# It will be shadowed to somewhere in memory below 1MB. +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(ToUserCode) +ASM_PFX(ToUserCode): + movl %edx,%ss # set new segment selectors + movl %edx,%ds + movl %edx,%es + movl %edx,%fs + movl %edx,%gs + .byte 0x66 + movl $0xc0000080,%ecx + movq %rax, %cr0 + rdmsr + andb $0xfe, %ah # $0b11111110 + wrmsr + movq %rbp, %cr4 + movl %esi,%ss # set up 16-bit stack segment + movw %bx,%sp # set up 16-bit stack pointer + .byte 0x66 # make the following call 32-bit + call L_Base1 # push eip +L_Base1: + popw %bp # ebp <- address of L_Base1 + pushq (IA32_REGS_SIZE + 2)(%esp) + lea 0x0c(%rsi), %eax + pushq %rax + lret # execution begins at next instruction +L_RealMode: + .byte 0x66,0x2e # CS and operand size override + lidt (_16Idtr - L_Base1)(%rsi) + .byte 0x66,0x61 # popad + .byte 0x1f # pop ds + .byte 0x7 # pop es + .byte 0x0f, 0xa1 # pop fs + .byte 0x0f, 0xa9 # pop gs + .byte 0x66, 0x9d # popfd + leaw 4(%esp),%sp # skip high order 32 bits of EFlags + .byte 0x66 # make the following retf 32-bit + lret # transfer control to user code + +.set CODE16, ASM_PFX(_16Code) - . +.set DATA16, ASM_PFX(_16Data) - . +.set DATA32, ASM_PFX(_32Data) - . + +ASM_PFX(NullSeg): .quad 0 +ASM_PFX(_16Code): + .word -1 + .word 0 + .byte 0 + .byte 0x9b + .byte 0x8f # 16-bit segment, 4GB limit + .byte 0 +ASM_PFX(_16Data): + .word -1 + .word 0 + .byte 0 + .byte 0x93 + .byte 0x8f # 16-bit segment, 4GB limit + .byte 0 +ASM_PFX(_32Data): + .word -1 + .word 0 + .byte 0 + .byte 0x93 + .byte 0xcf # 16-bit segment, 4GB limit + .byte 0 + +.set GDT_SIZE, . - ASM_PFX(NullSeg) + +#------------------------------------------------------------------------------ +# IA32_REGISTER_SET * +# EFIAPI +# InternalAsmThunk16 ( +# IN IA32_REGISTER_SET *RegisterSet, +# IN OUT VOID *Transition +# ); +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalAsmThunk16) +ASM_PFX(InternalAsmThunk16): + pushq %rbp + pushq %rbx + pushq %rsi + pushq %rdi + + movl %ds, %ebx + pushq %rbx # Save ds segment register on the stack + movl %es, %ebx + pushq %rbx # Save es segment register on the stack + movl %ss, %ebx + pushq %rbx # Save ss segment register on the stack + + .byte 0x0f, 0xa0 #push fs + .byte 0x0f, 0xa8 #push gs + movq %rcx, %rsi + movzwl _SS(%rsi), %r8d + movl _ESP(%rsi), %edi + lea -(IA32_REGS_SIZE + 4)(%edi), %rdi + imul $16, %r8d, %eax + movl %edi,%ebx # ebx <- stack for 16-bit code + pushq $(IA32_REGS_SIZE / 4) + addl %eax,%edi # edi <- linear address of 16-bit stack + popq %rcx + rep + movsl # copy RegSet + lea (L_SavedCr4 - ASM_PFX(m16Start))(%rdx), %ecx + movl %edx,%eax # eax <- transition code address + andl $0xf,%edx + shll $12,%eax # segment address in high order 16 bits + .set LBackFromUserCodeDelta, ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start) + lea (LBackFromUserCodeDelta)(%rdx), %ax + stosl # [edi] <- return address of user code + sgdt 0x60(%rsp) # save GDT stack in argument space + movzwq 0x60(%rsp), %r10 # r10 <- GDT limit + lea ((ASM_PFX(InternalAsmThunk16) - L_SavedCr4) + 0xf)(%rcx), %r11 + andq $0xfffffffffffffff0, %r11 # r11 <- 16-byte aligned shadowed GDT table in real mode buffer + + movw %r10w, (SavedGdt - L_SavedCr4)(%rcx) # save the limit of shadowed GDT table + movq %r11, (SavedGdt - L_SavedCr4 + 0x2)(%rcx) # save the base address of shadowed GDT table + + movq 0x62(%rsp) ,%rsi # rsi <- the original GDT base address + xchg %r10, %rcx # save rcx to r10 and initialize rcx to be the limit of GDT table + incq %rcx # rcx <- the size of memory to copy + xchg %r11, %rdi # save rdi to r11 and initialize rdi to the base address of shadowed GDT table + rep + movsb # perform memory copy to shadow GDT table + movq %r10, %rcx # restore the orignal rcx before memory copy + movq %r11, %rdi # restore the original rdi before memory copy + + sidt 0x50(%rsp) + movq %cr0, %rax + .set LSavedCrDelta, L_SavedCr0 - L_SavedCr4 + movl %eax, (LSavedCrDelta)(%rcx) + andl $0x7ffffffe,%eax # clear PE, PG bits + movq %cr4, %rbp + movl %ebp, (%rcx) # save CR4 in SavedCr4 + andl $0xffffffcf,%ebp # clear PAE, PSE bits + movl %r8d, %esi # esi <- 16-bit stack segment + .byte 0x6a, DATA32 + popq %rdx + lgdt (_16Gdtr - L_SavedCr4)(%rcx) + movl %edx,%ss + pushfq + lea -8(%rdx), %edx + lea L_RetFromRealMode(%rip), %r8 + pushq %r8 + movl %cs, %r8d + movw %r8w, (L_SavedCs - L_SavedCr4)(%rcx) + movq %rsp, (L_SavedSp - L_SavedCr4)(%rcx) + .byte 0xff, 0x69 # jmp (_EntryPoint - L_SavedCr4)(%rcx) + .set Ltemp1, _EntryPoint - L_SavedCr4 + .byte Ltemp1 +L_RetFromRealMode: + popfq + lgdt 0x60(%rsp) # restore protected mode GDTR + lidt 0x50(%rsp) # restore protected mode IDTR + lea -IA32_REGS_SIZE(%rbp), %eax + .byte 0x0f, 0xa9 # pop gs + .byte 0x0f, 0xa1 # pop fs + + popq %rbx + movl %ebx, %ss + popq %rbx + movl %ebx, %es + popq %rbx + movl %ebx, %ds + + popq %rdi + popq %rsi + popq %rbx + popq %rbp + + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm new file mode 100644 index 0000000..955e716 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Thunk16.nasm @@ -0,0 +1,325 @@ + +#include "BaseLibInternals.h" + +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm new file mode 100644 index 0000000..6f7e03e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/Wbinvd.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm new file mode 100644 index 0000000..245d64e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr0.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm new file mode 100644 index 0000000..b85864e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr2.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm new file mode 100644 index 0000000..3297fd9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr3.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm new file mode 100644 index 0000000..426e27e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteCr4.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm new file mode 100644 index 0000000..e6ffa16 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr0.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm new file mode 100644 index 0000000..59db62d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr1.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm new file mode 100644 index 0000000..c7562d8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr2.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm new file mode 100644 index 0000000..3b36fb6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr3.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm new file mode 100644 index 0000000..09277a4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr4.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm new file mode 100644 index 0000000..9461613 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr5.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm new file mode 100644 index 0000000..315bf9f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr6.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm new file mode 100644 index 0000000..5dc7613 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteDr7.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm new file mode 100644 index 0000000..b2671a3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteGdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm new file mode 100644 index 0000000..12d2e2d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteIdtr.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm new file mode 100644 index 0000000..f29e0a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteLdtr.nasm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm new file mode 100644 index 0000000..0fcd95d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm0.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm new file mode 100644 index 0000000..ed76786 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm1.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm new file mode 100644 index 0000000..ccdcbbc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm2.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm new file mode 100644 index 0000000..7f6a6d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm3.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm new file mode 100644 index 0000000..3ea63e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm4.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm new file mode 100644 index 0000000..4b99ed4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm5.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm new file mode 100644 index 0000000..24a715b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm6.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm new file mode 100644 index 0000000..0696c6d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMm7.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c new file mode 100644 index 0000000..7099e2a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.c @@ -0,0 +1,42 @@ +/** @file + CpuBreakpoint function. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm new file mode 100644 index 0000000..feec7e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteMsr64.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm new file mode 100644 index 0000000..cfd552f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X64/WriteTr.nasm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2017, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c new file mode 100644 index 0000000..77466b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging32.c @@ -0,0 +1,66 @@ +/** @file + IA-32/x64 AsmDisablePaging32() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c new file mode 100644 index 0000000..4f248ce --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86DisablePaging64.c @@ -0,0 +1,63 @@ +/** @file + IA-32/x64 AsmDisablePaging64() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c new file mode 100644 index 0000000..a596662 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging32.c @@ -0,0 +1,69 @@ +/** @file + IA-32/x64 AsmEnablePaging32() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c new file mode 100644 index 0000000..4a96a84 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86EnablePaging64.c @@ -0,0 +1,65 @@ +/** @file + IA-32/x64 AsmEnablePaging64() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxRestore.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxRestore.c new file mode 100644 index 0000000..39ba95c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxRestore.c @@ -0,0 +1,49 @@ +/** @file + IA-32/x64 AsmFxRestore() + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxSave.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxSave.c new file mode 100644 index 0000000..270b1fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86FxSave.c @@ -0,0 +1,48 @@ +/** @file + IA-32/x64 AsmFxSave() + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c new file mode 100644 index 0000000..51166e5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86GetInterruptState.c @@ -0,0 +1,41 @@ +/** @file + IA-32/x64 GetInterruptState() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c new file mode 100644 index 0000000..8c3d094 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86MemoryFence.c @@ -0,0 +1,32 @@ +/** @file + IA-32/x64 MemoryFence(). + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Msr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Msr.c new file mode 100644 index 0000000..6e888a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Msr.c @@ -0,0 +1,660 @@ +/** @file + IA-32/x64 MSR functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c new file mode 100644 index 0000000..18abe98 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86PatchInstruction.c @@ -0,0 +1,89 @@ +/** @file + IA-32/x64 PatchInstructionX86() + + Copyright (C) 2018, Intel Corporation. All rights reserved.
+ Copyright (C) 2018, Red Hat, Inc. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86RdRand.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86RdRand.c new file mode 100644 index 0000000..5aaab4e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86RdRand.c @@ -0,0 +1,79 @@ +/** @file + IA-32/x64 AsmRdRandxx() + Generates random number through CPU RdRand instruction. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c new file mode 100644 index 0000000..d0a5919 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadGdtr.c @@ -0,0 +1,39 @@ +/** @file + IA-32/x64 AsmReadGdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c new file mode 100644 index 0000000..8a55011 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86ReadIdtr.c @@ -0,0 +1,39 @@ +/** @file + IA-32/x64 AsmReadIdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c new file mode 100644 index 0000000..eb763cd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86SpeculationBarrier.c @@ -0,0 +1,32 @@ +/** @file + SpeculationBarrier() function for IA32 and x64. + + Copyright (C) 2018, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 + ) +{ + AsmLfence (); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Thunk.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Thunk.c new file mode 100644 index 0000000..93e74cd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86Thunk.c @@ -0,0 +1,268 @@ +/** @file + Real Mode Thunk Functions for IA32 and x64. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c new file mode 100644 index 0000000..7544e8a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteGdtr.c @@ -0,0 +1,39 @@ +/** @file + IA-32/x64 AsmWriteGdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c new file mode 100644 index 0000000..9060a92 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseLib/X86WriteIdtr.c @@ -0,0 +1,39 @@ +/** @file + IA-32/x64 AsmWriteIdtr() + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf new file mode 100644 index 0000000..e172080 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf @@ -0,0 +1,57 @@ +## @file +# Instance of Base Memory Library without assembly. +# +# Base Memory Library implementation - no ASM. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni new file mode 100644 index 0000000..458e262 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.uni @@ -0,0 +1,21 @@ +// /** @file +// Instance of Base Memory Library without assembly. +// +// Base Memory Library implementation - no ASM. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c new file mode 100644 index 0000000..c181c3d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c new file mode 100644 index 0000000..0bd481d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMem.c @@ -0,0 +1,154 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c new file mode 100644 index 0000000..f27de29 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c new file mode 100644 index 0000000..f16755b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c @@ -0,0 +1,293 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c new file mode 100644 index 0000000..9eb2832 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h new file mode 100644 index 0000000..87b4b64 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/MemLibInternals.h @@ -0,0 +1,251 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c new file mode 100644 index 0000000..8e90816 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c new file mode 100644 index 0000000..49a5fde --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem.c @@ -0,0 +1,87 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c new file mode 100644 index 0000000..8e6daa3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c new file mode 100644 index 0000000..7758e1f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c new file mode 100644 index 0000000..5273a86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLib/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf new file mode 100644 index 0000000..e0af1d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf @@ -0,0 +1,129 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/ScanMem64.S + Ia32/ScanMem32.nasm + Ia32/ScanMem32.S + Ia32/ScanMem16.nasm + Ia32/ScanMem16.S + Ia32/ScanMem8.nasm + Ia32/ScanMem8.S + Ia32/CompareMem.nasm + Ia32/CompareMem.S + Ia32/SetMem64.nasm + Ia32/SetMem64.S + Ia32/SetMem32.nasm + Ia32/SetMem32.S + Ia32/SetMem16.nasm + Ia32/SetMem16.S + Ia32/ZeroMem.nasm + Ia32/ZeroMem.S + Ia32/SetMem.nasm + Ia32/SetMem.S + Ia32/CopyMem.nasm + Ia32/CopyMem.S + 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/ScanMem64.S + X64/ScanMem32.nasm + X64/ScanMem32.S + X64/ScanMem16.nasm + X64/ScanMem16.S + X64/ScanMem8.nasm + X64/ScanMem8.S + X64/CompareMem.nasm + X64/CompareMem.S + X64/SetMem64.nasm + X64/SetMem64.S + X64/SetMem32.nasm + X64/SetMem32.S + X64/SetMem16.nasm + X64/SetMem16.S + X64/ZeroMem.nasm + X64/ZeroMem.S + X64/SetMem.nasm + X64/SetMem.S + X64/CopyMem.nasm + X64/CopyMem.S + X64/IsZeroBuffer.nasm + + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni new file mode 100644 index 0000000..6bc43ba --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c new file mode 100644 index 0000000..161171b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.S new file mode 100644 index 0000000..1c9239e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.S @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.Asm +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCompareMem): + push %esi + push %edi + movl 12(%esp), %esi + movl 16(%esp), %edi + movl 20(%esp), %ecx + repe cmpsb + movzbl -1(%esi), %eax + movzbl -1(%edi), %edx + subl %edx, %eax + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm new file mode 100644 index 0000000..e8d1abd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CompareMem.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.S new file mode 100644 index 0000000..0c204a3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.S @@ -0,0 +1,86 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.asm +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCopyMem): + push %esi + push %edi + movl 16(%esp), %esi # esi <- Source + movl 12(%esp), %edi # edi <- Destination + movl 20(%esp), %edx # edx <- Count + leal -1(%esi,%edx,), %eax # eax <- End of Source + cmpl %edi, %esi + jae L0 + cmpl %edi, %eax # Overlapped? + jae L_CopyBackward # Copy backward if overlapped +L0: + xorl %ecx, %ecx + subl %esi, %ecx + andl $7, %ecx # ecx + esi aligns on 8-byte boundary + jz L1 + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx # edx <- remaining bytes to copy + rep + movsb +L1: + movl %edx, %ecx + andl $7, %edx + shrl $3, %ecx # ecx <- # of Qwords to copy + jz L_CopyBytes + pushl %eax + pushl %eax + movq %mm0, (%esp) # save mm0 +L2: + movq (%esi), %mm0 + movq %mm0, (%edi) + addl $8, %esi + addl $8, %edi + loop L2 + movq (%esp), %mm0 # restore mm0 + popl %ecx # stack cleanup + popl %ecx # stack cleanup + jmp L_CopyBytes +L_CopyBackward: + movl %eax, %esi # esi <- Last byte in Source + leal -1(%edi,%edx,), %edi # edi <- Last byte in Destination + std +L_CopyBytes: + movl %edx, %ecx + rep + movsb + cld + movl 12(%esp), %eax + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm new file mode 100644 index 0000000..21e4427 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/CopyMem.nasm @@ -0,0 +1,77 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm new file mode 100644 index 0000000..cfd41a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.S new file mode 100644 index 0000000..c485543 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.Asm +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem16): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasw + leal -2(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm new file mode 100644 index 0000000..78d9f30 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem16.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.S new file mode 100644 index 0000000..a9b4975 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.Asm +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem32): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasl + leal -4(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm new file mode 100644 index 0000000..bbacf38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem32.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.S new file mode 100644 index 0000000..e23cf5f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.S @@ -0,0 +1,61 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.Asm +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + cmpl (%edi), %eax + leal 8(%edi), %edi + loopne L0 + jne L1 + cmpl -4(%edi), %edx + jecxz L1 + jne L0 +L1: + leal -8(%edi), %eax + cmovne %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm new file mode 100644 index 0000000..e994d4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem64.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.S new file mode 100644 index 0000000..afefaab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.Asm +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem8): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movb 16(%esp), %al + repne scasb + leal -1(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm new file mode 100644 index 0000000..d13c9c7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ScanMem8.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.S new file mode 100644 index 0000000..52b5da6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.S @@ -0,0 +1,66 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.asm +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem): + push %edi + movb 16(%esp), %al + movb %al, %ah + shrdl $16, %eax, %edx + shldl $16, %edx, %eax + movl 12(%esp), %ecx # ecx <- Count + movl 8(%esp), %edi # edi <- Buffer + movl %ecx, %edx + andl $7, %edx + shrl $3, %ecx # # of Qwords to set + jz L1 + addl $-16, %esp + movq %mm0, (%esp) # save mm0 + movq %mm1, 8(%esp) # save mm1 + movd %eax, %mm0 + movd %eax, %mm1 + psllq $32, %mm0 + por %mm1, %mm0 # fill mm0 with 8 Value's +L0: + movq %mm0, (%edi) + addl $8, %edi + loop L0 + movq (%esp), %mm0 # restore mm0 + movq 8(%esp), %mm1 # restore mm1 + addl $0x10, %esp # stack cleanup +L1: + movl %edx, %ecx + rep + stosb + movl 8(%esp), %eax # eax <- Buffer as return value + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm new file mode 100644 index 0000000..ab71586 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem.nasm @@ -0,0 +1,68 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.S new file mode 100644 index 0000000..af10605 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.S @@ -0,0 +1,59 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.asm +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem16): + push %edi + movl 16(%esp), %eax + shrdl $16, %eax, %edx + shldl $16, %edx, %eax + movl 12(%esp), %edx + movl 8(%esp), %edi + movl %edx, %ecx + andl $3, %edx + shrl $2, %ecx + jz L1 + movd %eax, %mm0 + movd %eax, %mm1 + psllq $32, %mm0 + por %mm1, %mm0 +L0: + movq %mm0, (%edi) + addl $8, %edi + loop L0 +L1: + movl %edx, %ecx + rep + stosw + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm new file mode 100644 index 0000000..61d1ef0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem16.nasm @@ -0,0 +1,61 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.S new file mode 100644 index 0000000..acf273d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.asm +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem32): + movl 4(%esp), %eax + movl 8(%esp), %ecx + movd 12(%esp), %mm0 + shrl %ecx + movl %eax, %edx + jz L1 + movq %mm0, %mm1 + psllq $32, %mm1 + por %mm1, %mm0 +L0: + movq %mm0, (%edx) + lea 8(%edx), %edx + loop L0 +L1: + jnc L2 + movd %mm0, (%edx) +L2: + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm new file mode 100644 index 0000000..9289f33 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem32.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.S new file mode 100644 index 0000000..be4b42b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.asm +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem64): + movl 4(%esp), %eax + movl 8(%esp), %ecx + movq 12(%esp), %mm0 + movl %eax, %edx +L0: + movq %mm0, (%edx) + lea 8(%edx), %edx + loop L0 + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm new file mode 100644 index 0000000..13fa52f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/SetMem64.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.S new file mode 100644 index 0000000..ac92ec2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.S @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.asm +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemZeroMem): + push %edi + movl 8(%esp), %edi + movl 12(%esp), %ecx + movl %ecx, %edx + shrl $3, %ecx + jz L_ZeroBytes + pxor %mm0, %mm0 +L0: + movq %mm0, (%edi) + addl $8, %edi + loop L0 +L_ZeroBytes: + andl $7, %edx + xorl %eax, %eax + movl %edx, %ecx + rep + stosb + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm new file mode 100644 index 0000000..bcf7cf6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/Ia32/ZeroMem.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h new file mode 100644 index 0000000..ce1c17f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/MemLibInternals.h @@ -0,0 +1,251 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c new file mode 100644 index 0000000..ff19a9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c new file mode 100644 index 0000000..6d974d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c new file mode 100644 index 0000000..8e6daa3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c new file mode 100644 index 0000000..7758e1f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c new file mode 100644 index 0000000..5273a86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.S new file mode 100644 index 0000000..12fde1c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.S @@ -0,0 +1,59 @@ +# +# ConvertAsm.py: Automatically generated from CompareMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + pushq %rsi + pushq %rdi + movq %rcx, %rsi + movq %rdx, %rdi + movq %r8, %rcx + repe cmpsb + movzbq -1(%rsi), %rax + movzbq -1(%rdi), %rdx + subq %rdx, %rax + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm new file mode 100644 index 0000000..cb0d886 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CompareMem.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.S new file mode 100644 index 0000000..aec628e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.S @@ -0,0 +1,74 @@ +# +# ConvertAsm.py: Automatically generated from CopyMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + pushq %rsi + pushq %rdi + movq %rdx, %rsi # rsi <- Source + movq %rcx, %rdi # rdi <- Destination + leaq -1(%rsi, %r8,), %r9 # r9 <- End of Source + cmpq %rdi, %rsi + movq %rdi, %rax # rax <- Destination as return value + jae L0 + cmpq %rdi, %r9 + jae L_CopyBackward # Copy backward if overlapped +L0: + movq %r8, %rcx + andq $7, %r8 + shrq $3, %rcx # rcx <- # of Qwords to copy + jz L_CopyBytes + movd %mm0, %r10 # (Save mm0 in r10) +L1: + movq (%rsi), %mm0 + movntq %mm0, (%rdi) + addq $8, %rsi + addq $8, %rdi + loop L1 + mfence + movd %r10, %mm0 # (Restore mm0) + jmp L_CopyBytes +L_CopyBackward: + movq %r9, %rsi # rsi <- End of Source + leaq -1(%rdi, %r8,), %rdi # rdi <- End of Destination + std # set direction flag +L_CopyBytes: + movq %r8, %rcx + rep movsb # Copy bytes backward + cld + popq %rdi + popq %rsi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm new file mode 100644 index 0000000..b3b9634 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/CopyMem.nasm @@ -0,0 +1,74 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm new file mode 100644 index 0000000..3b855a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.S new file mode 100644 index 0000000..718dd80 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.S +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + movq %rdx, %rcx + repne scasw + leaq -2(%rdi), %rax + cmovnz %rcx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm new file mode 100644 index 0000000..9f0de63 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem16.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.S new file mode 100644 index 0000000..b34d916 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.S +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + movq %rdx, %rcx + repne scasl + leaq -4(%rdi), %rax + cmovnz %rcx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm new file mode 100644 index 0000000..5c9ae5d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem32.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.S new file mode 100644 index 0000000..7d5f902 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.S @@ -0,0 +1,55 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + movq %rdx, %rcx + repne scasq + leaq -8(%rdi), %rax + cmovnz %rcx, %rax + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm new file mode 100644 index 0000000..b98c6de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem64.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.S new file mode 100644 index 0000000..efd877b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem8.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasb + leaq -1(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm new file mode 100644 index 0000000..8499795 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ScanMem8.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.S new file mode 100644 index 0000000..ba16ab2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.S @@ -0,0 +1,61 @@ +# +# ConvertAsm.py: Automatically generated from SetMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push %rdi + movq %r8, %rax + movb %al, %ah + movd %rax, %mm0 + movq %rcx, %r8 + movq %r8, %rdi # rdi <- Buffer + movq %rdx, %rcx + andq $7, %rdx + shrq $3, %rcx + jz L_SetBytes + .byte 0x0f, 0x70, 0x0C0, 0x00 +L0: + movntq %mm0, (%rdi) + addq $8, %rdi + loop L0 + mfence +L_SetBytes: + movl %edx, %ecx + rep stosb + movq %r8, %rax + pop %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm new file mode 100644 index 0000000..1b50e5e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem.nasm @@ -0,0 +1,60 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.S new file mode 100644 index 0000000..7d28278 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.S @@ -0,0 +1,60 @@ +# +# ConvertAsm.py: Automatically generated from SetMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + pushq %rdi + movq %r8, %rax + movd %rax, %mm0 + movq %rcx, %r8 + movq %r8, %rdi + movq %rdx, %rcx + andl $3, %edx + shrq $2, %rcx + jz L_SetWords + .byte 0x0f, 0x70, 0x0C0, 0x00 +L0: + movntq %mm0, (%rdi) + addq $8, %rdi + loop L0 + mfence +L_SetWords: + movl %edx, %ecx + rep stosw + movq %r8, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm new file mode 100644 index 0000000..4343550 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem16.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.S new file mode 100644 index 0000000..b60e06a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.S @@ -0,0 +1,55 @@ +# +# ConvertAsm.py: Automatically generated from SetMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + movd %r8, %mm0 # mm0 <- Value + movq %rcx, %rax # rax <- Buffer + xchgq %rdx, %rcx # rcx <- Count rdx <- Buffer + shrq $1, % rcx # rcx <- # of qwords to set + jz L_SetDwords + .byte 0x0f, 0x70, 0x0C0, 0x44 +L0: + movntq %mm0, (%rdx) + leaq 8(%rdx), %rdx # use "lea" to avoid flag changes + loop L0 + mfence +L_SetDwords: + jnc L1 + movd %mm0, (%rdx) +L1: + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm new file mode 100644 index 0000000..cf659b0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem32.nasm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.S new file mode 100644 index 0000000..c8cbb9a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + movd %r8, %mm0 #Value + movq %rcx, %rax #rax <- Buffer + xchg %rdx, %rcx #rcx <- Count +L0: + movntq %mm0, (%rdx) + addq $8, %rdx + loop L0 + mfence + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm new file mode 100644 index 0000000..f4aa51c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/SetMem64.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.S new file mode 100644 index 0000000..1994f9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.S @@ -0,0 +1,57 @@ +# +# ConvertAsm.py: Automatically generated from ZeroMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %rdi, %r8 + andq $7, %rdx + shrq $3, %rcx + jz L_ZeroBytes + pxor %mm0, %mm0 +L0: + movntq %mm0, (%rdi) + addq $8, %rdi + loop L0 + mfence +L_ZeroBytes: + xorl %eax, %eax + movl %edx, %ecx + rep stosb + movq %r8, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm new file mode 100644 index 0000000..9eb4d26 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/X64/ZeroMem.nasm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibMmx/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S new file mode 100644 index 0000000..8544c01 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S @@ -0,0 +1,40 @@ +// +// Copyright (c) 2016, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Linaro nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S new file mode 100644 index 0000000..7e5bf8a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S @@ -0,0 +1,142 @@ +// +// Copyright (c) 2013, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Linaro nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S new file mode 100644 index 0000000..ec5f696 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S @@ -0,0 +1,284 @@ +// +// Copyright (c) 2012 - 2016, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Linaro nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// +// Copyright (c) 2015 ARM Ltd +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the company may not be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S new file mode 100644 index 0000000..3fe772f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S @@ -0,0 +1,161 @@ +// +// Copyright (c) 2014, ARM Limited +// All rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the company nor the names of its contributors +// may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S new file mode 100644 index 0000000..384fbdc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S @@ -0,0 +1,247 @@ +// +// Copyright (c) 2012 - 2016, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Linaro nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// +// Copyright (c) 2015 ARM Ltd +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the company may not be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S new file mode 100644 index 0000000..78a4525 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S @@ -0,0 +1,66 @@ +// +// Copyright (c) 2016, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Linaro nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm new file mode 100644 index 0000000..0373404 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm @@ -0,0 +1,70 @@ +; +; Copyright (c) 2016, Linaro Limited +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the Linaro nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S new file mode 100644 index 0000000..8e17760 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S @@ -0,0 +1,139 @@ +// +// Copyright (c) 2013 - 2016, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Linaro nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm new file mode 100644 index 0000000..4c72dcf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm @@ -0,0 +1,140 @@ +; +; Copyright (c) 2013 - 2016, Linaro Limited +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the Linaro nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; + +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S new file mode 100644 index 0000000..85d6811 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.S @@ -0,0 +1,176 @@ +#------------------------------------------------------------------------------ +# +# 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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm new file mode 100644 index 0000000..f544740 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CopyMem.asm @@ -0,0 +1,147 @@ +;------------------------------------------------------------------------------ +; +; 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.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c new file mode 100644 index 0000000..b2942f3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/MemLibGuid.c @@ -0,0 +1,165 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S new file mode 100644 index 0000000..5502f28 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S @@ -0,0 +1,148 @@ +// Copyright (c) 2010-2011, Linaro Limited +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Linaro Limited nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +// +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm new file mode 100644 index 0000000..bb489f1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm @@ -0,0 +1,147 @@ +; Copyright (c) 2010-2011, Linaro Limited +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; * Neither the name of Linaro Limited nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; + +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c new file mode 100644 index 0000000..e48db72 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMemGeneric.c @@ -0,0 +1,142 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S new file mode 100644 index 0000000..35481b5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.S @@ -0,0 +1,94 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2016, Linaro Ltd. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + + .text + .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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm new file mode 100644 index 0000000..000c2a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Arm/SetMem.asm @@ -0,0 +1,96 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Linaro Ltd. All rights reserved.
+; +; This program and the accompanying materials are licensed and made available +; under the terms and conditions of the BSD License which accompanies this +; distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +;------------------------------------------------------------------------------ + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf new file mode 100644 index 0000000..baf313a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf @@ -0,0 +1,152 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/ScanMem64.S + Ia32/ScanMem32.nasm + Ia32/ScanMem32.S + Ia32/ScanMem16.nasm + Ia32/ScanMem16.S + Ia32/ScanMem8.nasm + Ia32/ScanMem8.S + Ia32/CompareMem.nasm + Ia32/CompareMem.S + Ia32/ZeroMem.nasm + Ia32/ZeroMem.S + Ia32/SetMem64.nasm + Ia32/SetMem64.S + Ia32/SetMem32.nasm + Ia32/SetMem32.S + Ia32/SetMem16.nasm + Ia32/SetMem16.S + Ia32/SetMem.nasm + Ia32/SetMem.S + Ia32/CopyMem.nasm + Ia32/CopyMem.S + 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/ScanMem64.S + X64/ScanMem32.nasm + X64/ScanMem32.S + X64/ScanMem16.nasm + X64/ScanMem16.S + X64/ScanMem8.nasm + X64/ScanMem8.S + X64/CompareMem.nasm + X64/CompareMem.S + X64/ZeroMem.nasm + X64/ZeroMem.S + X64/SetMem64.nasm + X64/SetMem64.S + X64/SetMem32.nasm + X64/SetMem32.S + X64/SetMem16.nasm + X64/SetMem16.S + X64/SetMem.nasm + X64/SetMem.S + X64/CopyMem.nasm + X64/CopyMem.S + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni new file mode 100644 index 0000000..bb0cd56 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c new file mode 100644 index 0000000..161171b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.S new file mode 100644 index 0000000..a430453 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.S @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCompareMem): + push %esi + push %edi + movl 12(%esp), %esi + movl 16(%esp), %edi + movl 20(%esp), %ecx + repe cmpsb + movzbl -1(%esi), %eax + movzbl -1(%edi), %edx + subl %edx, %eax + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm new file mode 100644 index 0000000..e8d1abd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CompareMem.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.S new file mode 100644 index 0000000..dbd052b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.S @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCopyMem): + push %esi + push %edi + movl 16(%esp), %esi # esi <- Source + movl 12(%esp), %edi # edi <- Destination + movl 20(%esp), %edx # edx <- Count + leal -1(%esi,%edx,), %eax # eax <- End of Source + cmpl %edi, %esi + jae L0 + cmpl %edi, %eax # Overlapped? + jae L_CopyBackward # Copy backward if overlapped +L0: + xorl %ecx, %ecx + subl %edi, %ecx + andl $15, %ecx # ecx + edi aligns on 16-byte boundary + jz L1 + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx # edx <- remaining bytes to copy + rep + movsb +L1: + movl %edx, %ecx + andl $15, %edx + shrl $4, %ecx # ecx <- # of DQwords to copy + jz L_CopyBytes + addl $-16, %esp + movdqu %xmm0, (%esp) +L2: + movdqu (%esi), %xmm0 + movntdq %xmm0, (%edi) + addl $16, %esi + addl $16, %edi + loop L2 + mfence + movdqu (%esp),%xmm0 + addl $16, %esp # stack cleanup + jmp L_CopyBytes +L_CopyBackward: + movl %eax, %esi # esi <- Last byte in Source + leal -1(%edi,%edx,), %edi # edi <- Last byte in Destination + std +L_CopyBytes: + movl %edx, %ecx + rep + movsb + cld + movl 12(%esp), %eax # eax <- Destination as return value + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm new file mode 100644 index 0000000..6913874 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/CopyMem.nasm @@ -0,0 +1,84 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm new file mode 100644 index 0000000..cfd41a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.S new file mode 100644 index 0000000..c485543 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.Asm +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem16): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasw + leal -2(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm new file mode 100644 index 0000000..78d9f30 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem16.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.S new file mode 100644 index 0000000..016ebd2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.S +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem32): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasl + leal -4(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm new file mode 100644 index 0000000..bbacf38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem32.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.S new file mode 100644 index 0000000..6e42856 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.S @@ -0,0 +1,61 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + cmpl (%edi), %eax + leal 8(%edi), %edi + loopne L0 + jne L1 + cmpl -4(%edi), %edx + jecxz L1 + jne L0 +L1: + leal -8(%edi), %eax + cmovne %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm new file mode 100644 index 0000000..e994d4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem64.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.S new file mode 100644 index 0000000..02bb27f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem8): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movb 16(%esp), %al + repne scasb + leal -1(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm new file mode 100644 index 0000000..d13c9c7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ScanMem8.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.S new file mode 100644 index 0000000..ee0b659 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.S @@ -0,0 +1,50 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem): + push %edi + movl 12(%esp),%ecx + movb 16(%esp),%al + movb %al, %ah + shrd $16, %eax, %edx + shld $16, %edx, %eax + movl %ecx, %edx + movl 8(%esp),%edi + shr $2, %ecx + rep stosl + movl %edx, %ecx + andl $3, %ecx + rep stosb + movl 8(%esp),%eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm new file mode 100644 index 0000000..3a75363 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.S new file mode 100644 index 0000000..8989bdd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem16): + push %edi + movl 16(%esp), %eax + movl 8(%esp), %edi + movl 12(%esp), %ecx + rep + stosw + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm new file mode 100644 index 0000000..cfa4906 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem16.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.S new file mode 100644 index 0000000..b2c9a85 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem32): + push %edi + movl 16(%esp),%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + rep + stosl + movl 8(%esp),%eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm new file mode 100644 index 0000000..78e09b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem32.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.S new file mode 100644 index 0000000..f25dfe1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + mov %eax, -8(%edi, %ecx, 8) + mov %edx, -4(%edi, %ecx, 8) + loop L0 + movl %edi, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm new file mode 100644 index 0000000..d0afacb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/SetMem64.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.S new file mode 100644 index 0000000..70cede6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.S @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemZeroMem): + push %edi + xorl %eax,%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + movl %ecx,%edx + shrl $2,%ecx + andl $3,%edx + pushl %edi + rep + stosl + movl %edx,%ecx + rep + stosb + popl %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm new file mode 100644 index 0000000..31efb6a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/Ia32/ZeroMem.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h new file mode 100644 index 0000000..be7952e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/MemLibInternals.h @@ -0,0 +1,251 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c new file mode 100644 index 0000000..613e667 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ScanMem8Wrapper.c @@ -0,0 +1,100 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c new file mode 100644 index 0000000..8e6daa3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c new file mode 100644 index 0000000..7758e1f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c new file mode 100644 index 0000000..5273a86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.S new file mode 100644 index 0000000..eef1ccb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.S @@ -0,0 +1,59 @@ +# +# ConvertAsm.py: Automatically generated from CompareMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + pushq %rsi + pushq %rdi + movq %rcx, %rsi + movq %rdx, %rdi + movq %r8, %rcx + repe cmpsb + movzbq -1(%rsi) , %rax + movzbq -1(%rdi) , %rdx + sub %dl, %al + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm new file mode 100644 index 0000000..cb0d886 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CompareMem.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.S new file mode 100644 index 0000000..4d96623 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.S @@ -0,0 +1,82 @@ +# +# ConvertAsm.py: Automatically generated from CopyMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + pushq %rsi + pushq %rdi + movq %rdx, %rsi # rsi <- Source + movq %rcx, %rdi # rdi <- Destination + leaq -1(%rsi,%r8,), %r9 # r9 <- Last byte of Source + cmpq %rdi, %rsi + movq %rdi, %rax # rax <- Destination as return value + jae L0 # Copy forward if Source > Destination + cmpq %rdi, %r9 # Overlapped? + jae L_CopyBackward # Copy backward if overlapped +L0: + xorq %rcx, %rcx + subq %rdi, %rcx # rcx <- -rdi + andq $15, %rcx # rcx + rsi should be 16 bytes aligned + jz L1 # skip if rcx == 0 + cmpq %r8, %rcx + cmova %r8, %rcx + subq %rcx, %r8 + rep movsb +L1: + movq %r8, %rcx + andq $15, %r8 + shrq $4, %rcx # rcx <- # of DQwords to copy + jz L_CopyBytes + movdqu %xmm0, 0x18(%rsp) # save xmm0 on stack +L2: + movdqu (%rsi), %xmm0 # rsi may not be 16-byte aligned + movntdq %xmm0, (%rdi) # rdi should be 16-byte aligned + addq $16, %rsi + addq $16, %rdi + loop L2 + mfence + movdqa 0x18(%rsp), %xmm0 # restore xmm0 + jmp L_CopyBytes # copy remaining bytes +L_CopyBackward: + movq %r9, %rsi # rsi <- Last byte of Source + leaq -1(%rdi, %r8,), %rdi # rdi <- Last byte of Destination + std +L_CopyBytes: + movq %r8, %rcx + rep movsb + cld + popq %rdi + popq %rsi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm new file mode 100644 index 0000000..9fe45d4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/CopyMem.nasm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm new file mode 100644 index 0000000..3b855a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.S new file mode 100644 index 0000000..ea82f55 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.S +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + movq %rdx, %rcx + repne scasw + leaq -2(%rdi), %rax + cmovnz %rcx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm new file mode 100644 index 0000000..9f0de63 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem16.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.S new file mode 100644 index 0000000..7ff1c08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.S +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + movq %rdx, %rcx + repne scasl + leaq -4(%rdi), %rax + cmovnz %rcx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm new file mode 100644 index 0000000..5c9ae5d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem32.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.S new file mode 100644 index 0000000..1948c16 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.S @@ -0,0 +1,55 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + movq %rdx, %rcx + repne scasq + leaq -8(%rdi), %rax + cmovnz %rcx, %rax + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm new file mode 100644 index 0000000..b98c6de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem64.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.S new file mode 100644 index 0000000..688884f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem8.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasb + leaq -1(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm new file mode 100644 index 0000000..8499795 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ScanMem8.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.S new file mode 100644 index 0000000..7219c5c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.S @@ -0,0 +1,57 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + pushq %rdi + pushq %rbx + pushq %rcx # push Buffer + movq %r8, %rax # rax = Value + andq $0xff, %rax # rax = lower 8 bits of r8, upper 56 bits are 0 + movb %al, %ah # ah = al + movw %ax, %bx # bx = ax + shlq $0x10, %rax # rax = ax << 16 + movw %bx, %ax # ax = bx + movq %rax, %rbx # ebx = eax + shlq $0x20, %rax # rax = rax << 32 + orq %rbx, %rax # eax = ebx + movq %rcx, %rdi # rdi = Buffer + movq %rdx, %rcx # rcx = Count + shrq $3, %rcx # rcx = rcx / 8 + cld + rep stosq + movq %rdx, %rcx # rcx = rdx + andq $7, %rcx # rcx = rcx & 7 + rep stosb + popq %rax # rax = Buffer + popq %rbx + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm new file mode 100644 index 0000000..48d69ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem.nasm @@ -0,0 +1,62 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.S new file mode 100644 index 0000000..d6f570f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchg %rdx, %rcx + rep stosw + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm new file mode 100644 index 0000000..d9a3d35 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem16.nasm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.S new file mode 100644 index 0000000..7dba067 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosl + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm new file mode 100644 index 0000000..6f97704 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem32.nasm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.S new file mode 100644 index 0000000..a94f038 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.S @@ -0,0 +1,46 @@ +# +# ConvertAsm.py: Automatically generated from SetMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchg %rdx, %rcx + rep stosq + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm new file mode 100644 index 0000000..9b0b8ac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/SetMem64.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.S new file mode 100644 index 0000000..38b8678 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.S @@ -0,0 +1,51 @@ +# +# ConvertAsm.py: Automatically generated from ZeroMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + pushq %rdi + pushq %rcx + xorq %rax, %rax + movq %rcx, %rdi + movq %rdx, %rcx + shrq $3, %rcx + andq $7, %rdx + cld + rep stosq + movq %rdx, %rcx + rep stosb + popq %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm new file mode 100644 index 0000000..12c1da9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/X64/ZeroMem.nasm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptDxe/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf new file mode 100644 index 0000000..ef3b909 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf @@ -0,0 +1,130 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/ScanMem64.S + Ia32/ScanMem32.nasm + Ia32/ScanMem32.S + Ia32/ScanMem16.nasm + Ia32/ScanMem16.S + Ia32/ScanMem8.nasm + Ia32/ScanMem8.S + Ia32/CompareMem.nasm + Ia32/CompareMem.S + Ia32/ZeroMem.nasm + Ia32/ZeroMem.S + Ia32/SetMem64.nasm + Ia32/SetMem64.S + Ia32/SetMem32.nasm + Ia32/SetMem32.S + Ia32/SetMem16.nasm + Ia32/SetMem16.S + Ia32/SetMem.nasm + Ia32/SetMem.S + Ia32/CopyMem.nasm + Ia32/CopyMem.S + 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/ScanMem64.S + X64/ScanMem32.nasm + X64/ScanMem32.S + X64/ScanMem16.nasm + X64/ScanMem16.S + X64/ScanMem8.nasm + X64/ScanMem8.S + X64/CompareMem.nasm + X64/CompareMem.S + X64/ZeroMem.nasm + X64/ZeroMem.S + X64/SetMem64.nasm + X64/SetMem64.S + X64/SetMem32.nasm + X64/SetMem32.S + X64/SetMem16.nasm + X64/SetMem16.S + X64/SetMem.nasm + X64/SetMem.S + X64/CopyMem.nasm + X64/CopyMem.S + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni new file mode 100644 index 0000000..dda230e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c new file mode 100644 index 0000000..161171b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.S new file mode 100644 index 0000000..a430453 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.S @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCompareMem): + push %esi + push %edi + movl 12(%esp), %esi + movl 16(%esp), %edi + movl 20(%esp), %ecx + repe cmpsb + movzbl -1(%esi), %eax + movzbl -1(%edi), %edx + subl %edx, %eax + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm new file mode 100644 index 0000000..e8d1abd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CompareMem.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.S new file mode 100644 index 0000000..1200675 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.S @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCopyMem): + push %esi + push %edi + movl 16(%esp), %esi # esi <- Source + movl 12(%esp), %edi # edi <- Destination + movl 20(%esp), %edx # edx <- Count + cmpl %esi, %edi + je L_CopyDone + cmpl $0, %edx + je L_CopyDone + leal -1(%esi, %edx), %eax # eax <- End of Source + cmpl %edi, %esi + jae L_CopyBytes + cmpl %edi, %eax + jb L_CopyBytes # Copy backward if overlapped + movl %eax, %esi # esi <- End of Source + leal -1(%edi, %edx), %edi # edi <- End of Destination + std +L_CopyBytes: + movl %edx, %ecx + rep + movsb # Copy bytes backward + cld +L_CopyDone: + movl 12(%esp), %eax # eax <- Destination as return value + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm new file mode 100644 index 0000000..d7e62aa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/CopyMem.nasm @@ -0,0 +1,62 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm new file mode 100644 index 0000000..cfd41a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.S new file mode 100644 index 0000000..9e383c2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.S +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem16): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasw + leal -2(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm new file mode 100644 index 0000000..78d9f30 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem16.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.S new file mode 100644 index 0000000..a9b4975 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.Asm +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem32): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasl + leal -4(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm new file mode 100644 index 0000000..bbacf38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem32.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.S new file mode 100644 index 0000000..6e42856 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.S @@ -0,0 +1,61 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + cmpl (%edi), %eax + leal 8(%edi), %edi + loopne L0 + jne L1 + cmpl -4(%edi), %edx + jecxz L1 + jne L0 +L1: + leal -8(%edi), %eax + cmovne %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm new file mode 100644 index 0000000..e994d4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem64.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.S new file mode 100644 index 0000000..02bb27f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem8): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movb 16(%esp), %al + repne scasb + leal -1(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm new file mode 100644 index 0000000..d13c9c7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ScanMem8.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.S new file mode 100644 index 0000000..ee0b659 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.S @@ -0,0 +1,50 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem): + push %edi + movl 12(%esp),%ecx + movb 16(%esp),%al + movb %al, %ah + shrd $16, %eax, %edx + shld $16, %edx, %eax + movl %ecx, %edx + movl 8(%esp),%edi + shr $2, %ecx + rep stosl + movl %edx, %ecx + andl $3, %ecx + rep stosb + movl 8(%esp),%eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm new file mode 100644 index 0000000..3a75363 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem.nasm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.S new file mode 100644 index 0000000..8989bdd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem16): + push %edi + movl 16(%esp), %eax + movl 8(%esp), %edi + movl 12(%esp), %ecx + rep + stosw + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm new file mode 100644 index 0000000..cfa4906 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem16.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.S new file mode 100644 index 0000000..b2c9a85 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem32): + push %edi + movl 16(%esp),%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + rep + stosl + movl 8(%esp),%eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm new file mode 100644 index 0000000..78e09b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem32.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.S new file mode 100644 index 0000000..f25dfe1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + mov %eax, -8(%edi, %ecx, 8) + mov %edx, -4(%edi, %ecx, 8) + loop L0 + movl %edi, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm new file mode 100644 index 0000000..d0afacb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/SetMem64.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.S new file mode 100644 index 0000000..70cede6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.S @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemZeroMem): + push %edi + xorl %eax,%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + movl %ecx,%edx + shrl $2,%ecx + andl $3,%edx + pushl %edi + rep + stosl + movl %edx,%ecx + rep + stosb + popl %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm new file mode 100644 index 0000000..31efb6a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/Ia32/ZeroMem.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h new file mode 100644 index 0000000..0c5bbe0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/MemLibInternals.h @@ -0,0 +1,251 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c new file mode 100644 index 0000000..6d974d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c new file mode 100644 index 0000000..8e6daa3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c new file mode 100644 index 0000000..c51b846 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c new file mode 100644 index 0000000..5273a86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.S new file mode 100644 index 0000000..503127c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.S @@ -0,0 +1,59 @@ +# +# ConvertAsm.py: Automatically generated from CompareMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + pushq %rsi + pushq %rdi + movq %rcx, %rsi + movq %rdx, %rdi + movq %r8, %rcx + repe cmpsb + movzbq -1(%rsi) , %rax + movzbq -1(%rdi) , %rdx + subq %rdx, %rax + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm new file mode 100644 index 0000000..cb0d886 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CompareMem.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.S new file mode 100644 index 0000000..e3a7aef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.S @@ -0,0 +1,66 @@ +# +# ConvertAsm.py: Automatically generated from CopyMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + pushq %rsi + pushq %rdi + movq %rdx, %rsi # rsi <- Source + movq %rcx, %rdi # rdi <- Destination + leaq -1(%rsi, %r8,), %r9 # r9 <- End of Source + cmpq %rdi, %rsi + movq %rdi, %rax # rax <- Destination as return value + jae _InternalMemCopyMem_al_0000 + cmpq %rdi, %r9 + jae _atSym_CopyBackward # Copy backward if overlapped +_InternalMemCopyMem_al_0000: + movq %r8, %rcx + andq $7, %r8 + shrq $3, %rcx + rep movsq # Copy as many Qwords as possible + jmp _atSym_CopyBytes +_atSym_CopyBackward: + movq %r9, %rsi # rsi <- End of Source + leaq -1(%rdi, %r8), %rdi # rdi <- End of Destination + std # set direction flag +_atSym_CopyBytes: + movq %r8, %rcx + rep movsb # Copy bytes backward + cld + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm new file mode 100644 index 0000000..b304123 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/CopyMem.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm new file mode 100644 index 0000000..3b855a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.S new file mode 100644 index 0000000..5bdf247 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.S +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasw + leaq -2(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm new file mode 100644 index 0000000..9f0de63 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem16.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.S new file mode 100644 index 0000000..2aac851 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.S +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasl + leaq -4(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm new file mode 100644 index 0000000..5c9ae5d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem32.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.S new file mode 100644 index 0000000..21f0590 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasq + leaq -8(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm new file mode 100644 index 0000000..b98c6de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem64.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.S new file mode 100644 index 0000000..5209983 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem8.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasb + leaq -1(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm new file mode 100644 index 0000000..8499795 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ScanMem8.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.S new file mode 100644 index 0000000..b3804e5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + pushq %rdi + movq %r8, %rax # rax = Value + movq %rcx, %rdi # rdi = Buffer + xchgq %rdx, %rcx # rcx = Count, rdx = Buffer + rep stosb + movq %rdx, %rax # rax = Buffer + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm new file mode 100644 index 0000000..ae05517 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem.nasm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.S new file mode 100644 index 0000000..3434e86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosw + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm new file mode 100644 index 0000000..d9c0e54 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem16.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.S new file mode 100644 index 0000000..7dba067 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosl + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm new file mode 100644 index 0000000..4da3d33 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem32.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.S new file mode 100644 index 0000000..ad28243 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.S @@ -0,0 +1,46 @@ +# +# ConvertAsm.py: Automatically generated from SetMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosq + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm new file mode 100644 index 0000000..6f364d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/SetMem64.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.S new file mode 100644 index 0000000..e5cb074 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.S @@ -0,0 +1,50 @@ +# +# ConvertAsm.py: Automatically generated from ZeroMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + pushq %rdi + pushq %rcx + xorq %rax, %rax + movq %rcx, %rdi + movq %rdx, %rcx + shrq $3, %rcx + andq $7, %rdx + rep stosq + movl %edx, %ecx + rep stosb + popq %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm new file mode 100644 index 0000000..8e0a5e4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/X64/ZeroMem.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibOptPei/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf new file mode 100644 index 0000000..2d0f0a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf @@ -0,0 +1,127 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/ScanMem64.S + Ia32/ScanMem32.nasm + Ia32/ScanMem32.S + Ia32/ScanMem16.nasm + Ia32/ScanMem16.S + Ia32/ScanMem8.nasm + Ia32/ScanMem8.S + Ia32/CompareMem.nasm + Ia32/CompareMem.S + Ia32/ZeroMem.nasm + Ia32/ZeroMem.S + Ia32/SetMem64.nasm + Ia32/SetMem64.S + Ia32/SetMem32.nasm + Ia32/SetMem32.S + Ia32/SetMem16.nasm + Ia32/SetMem16.S + Ia32/SetMem.nasm + Ia32/SetMem.S + Ia32/CopyMem.nasm + Ia32/CopyMem.S + 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/ScanMem64.S + X64/ScanMem32.nasm + X64/ScanMem32.S + X64/ScanMem16.nasm + X64/ScanMem16.S + X64/ScanMem8.nasm + X64/ScanMem8.S + X64/CompareMem.nasm + X64/CompareMem.S + X64/ZeroMem.nasm + X64/ZeroMem.S + X64/SetMem64.nasm + X64/SetMem64.S + X64/SetMem32.nasm + X64/SetMem32.S + X64/SetMem16.nasm + X64/SetMem16.S + X64/SetMem.nasm + X64/SetMem.S + X64/CopyMem.nasm + X64/CopyMem.S + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni new file mode 100644 index 0000000..b6e1b5a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c new file mode 100644 index 0000000..161171b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.S new file mode 100644 index 0000000..1c9239e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.S @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.Asm +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCompareMem): + push %esi + push %edi + movl 12(%esp), %esi + movl 16(%esp), %edi + movl 20(%esp), %ecx + repe cmpsb + movzbl -1(%esi), %eax + movzbl -1(%edi), %edx + subl %edx, %eax + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm new file mode 100644 index 0000000..e8d1abd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.S new file mode 100644 index 0000000..9276699 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.S @@ -0,0 +1,65 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.Asm +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCopyMem): + push %esi + push %edi + movl 16(%esp), %esi # esi <- Source + movl 12(%esp), %edi # edi <- Destination + movl 20(%esp), %edx # edx <- Count + leal -1(%esi, %edx), %eax # eax <- End of Source + cmpl %edi, %esi + jae L0 + cmpl %edi, %eax + jae L_CopyBackward # Copy backward if overlapped +L0: + movl %edx, %ecx + andl $3, %edx + shrl $2, %ecx + rep + movsl # Copy as many Dwords as possible + jmp L_CopyBytes +L_CopyBackward: + movl %eax, %esi # esi <- End of Source + leal -1(%edi, %edx), %edi # edi <- End of Destination + std +L_CopyBytes: + movl %edx, %ecx + rep + movsb # Copy bytes backward + cld + movl 12(%esp), %eax # eax <- Destination as return value + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm new file mode 100644 index 0000000..ff9931d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.nasm @@ -0,0 +1,64 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm new file mode 100644 index 0000000..cfd41a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.S new file mode 100644 index 0000000..42735ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.S @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.Asm +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem16): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasw + leal -2(%edi), %eax + jz L0 + movl %ecx, %eax +L0: + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm new file mode 100644 index 0000000..71171ee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.nasm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.S new file mode 100644 index 0000000..a27be9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.S @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.Asm +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem32): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasl + leal -4(%edi), %eax + jz L0 + movl %ecx, %eax +L0: + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm new file mode 100644 index 0000000..9d1b028 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.nasm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.S new file mode 100644 index 0000000..96c2d31 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.S @@ -0,0 +1,63 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.Asm +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + cmpl (%edi), %eax + leal 8(%edi), %edi + loopne L0 + jne L1 + cmpl -4(%edi), %edx + jecxz L1 + jne L0 +L1: + leal -8(%edi), %eax + jz L2 + movl %ecx, %eax +L2: + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm new file mode 100644 index 0000000..108263d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S new file mode 100644 index 0000000..6fddf08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.S @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.Asm +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem8): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movb 16(%esp), %al + repne scasb + leal -1(%edi), %eax + jz L0 + movl %ecx, %eax +L0: + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm new file mode 100644 index 0000000..c6ecdfd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.nasm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.S new file mode 100644 index 0000000..63065ea --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.Asm +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + .code: + +ASM_GLOBAL ASM_PFX(InternalMemSetMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem): + push %edi + movl 16(%esp),%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + rep + stosb + movl 8(%esp),%eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm new file mode 100644 index 0000000..c27207d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.S new file mode 100644 index 0000000..d32ce4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.Asm +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem16): + push %edi + movl 16(%esp), %eax + movl 8(%esp), %edi + movl 12(%esp), %ecx + rep + stosw + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm new file mode 100644 index 0000000..cfa4906 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.S new file mode 100644 index 0000000..7fbe11d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.Asm +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem32): + push %edi + movl 16(%esp),%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + rep + stosl + movl 8(%esp),%eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm new file mode 100644 index 0000000..78e09b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.nasm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.S new file mode 100644 index 0000000..9a0bb07 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.Asm +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + mov %eax, -8(%edi, %ecx, 8) + mov %edx, -4(%edi, %ecx, 8) + loop L0 + movl %edi, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm new file mode 100644 index 0000000..d0afacb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.S new file mode 100644 index 0000000..33b31ad --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.S @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.Asm +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemZeroMem): + push %edi + xorl %eax,%eax + movl 8(%esp),%edi + movl 12(%esp),%ecx + movl %ecx,%edx + shrl $2,%ecx + andl $3,%edx + pushl %edi + rep + stosl + movl %edx,%ecx + rep + stosb + popl %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm new file mode 100644 index 0000000..31efb6a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h new file mode 100644 index 0000000..83b0f06 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/MemLibInternals.h @@ -0,0 +1,251 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c new file mode 100644 index 0000000..6d974d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c new file mode 100644 index 0000000..8e6daa3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c new file mode 100644 index 0000000..7758e1f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c new file mode 100644 index 0000000..5273a86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.S new file mode 100644 index 0000000..435f29a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.S @@ -0,0 +1,59 @@ +# +# ConvertAsm.py: Automatically generated from CompareMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + pushq %rsi + pushq %rdi + movq %rcx, %rsi + movq %rdx, %rdi + movq %r8, %rcx + repe cmpsb + movzbq -1(%rsi) , %rax + movzbq -1(%rdi) , %rdx + subq %rdx, %rax + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm new file mode 100644 index 0000000..cb0d886 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CompareMem.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.S new file mode 100644 index 0000000..73f5964 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.S @@ -0,0 +1,66 @@ +# +# ConvertAsm.py: Automatically generated from CopyMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + pushq %rsi + pushq %rdi + movq %rdx, %rsi # rsi <- Source + movq %rcx, %rdi # rdi <- Destination + leaq -1(%rsi, %r8,), %r9 # r9 <- End of Source + cmpq %rdi, %rsi + movq %rdi, %rax # rax <- Destination as return value + jae L0 + cmpq %rdi, %r9 + jae L_CopyBackward # Copy backward if overlapped +L0: + movq %r8, %rcx + andq $7, %r8 + shrq $3, %rcx + rep movsq # Copy as many Qwords as possible + jmp L_CopyBytes +L_CopyBackward: + movq %r9, %rsi # rsi <- End of Source + leaq -1(%rdi, %r8), %rdi # esi <- End of Destination + std # set direction flag +L_CopyBytes: + movq %r8, %rcx + rep movsb # Copy bytes backward + cld + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm new file mode 100644 index 0000000..b304123 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/CopyMem.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm new file mode 100644 index 0000000..3b855a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/IsZeroBuffer.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.S new file mode 100644 index 0000000..5bdf247 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.S +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasw + leaq -2(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm new file mode 100644 index 0000000..9f0de63 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem16.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.S new file mode 100644 index 0000000..2aac851 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.S +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasl + leaq -4(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm new file mode 100644 index 0000000..5c9ae5d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem32.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.S new file mode 100644 index 0000000..21f0590 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasq + leaq -8(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm new file mode 100644 index 0000000..b98c6de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem64.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.S new file mode 100644 index 0000000..5209983 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem8.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasb + leaq -1(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm new file mode 100644 index 0000000..8499795 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ScanMem8.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.S new file mode 100644 index 0000000..059bb66 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + pushq %rdi + movq %r8, %rax # rax = Value + movq %rcx, %rdi # rdi = Buffer + xchgq %rdx, %rcx # rcx = Count, rdx = Buffer + rep stosb + movq %rdx, %rax # rax = Buffer + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm new file mode 100644 index 0000000..e80f671 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.S new file mode 100644 index 0000000..3434e86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosw + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm new file mode 100644 index 0000000..d9c0e54 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem16.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.S new file mode 100644 index 0000000..7dba067 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.S @@ -0,0 +1,47 @@ +# +# ConvertAsm.py: Automatically generated from SetMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosl + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm new file mode 100644 index 0000000..4da3d33 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem32.nasm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.S new file mode 100644 index 0000000..ad28243 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.S @@ -0,0 +1,46 @@ +# +# ConvertAsm.py: Automatically generated from SetMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + pushq %rdi + movq %rcx, %rdi + movq %r8, %rax + xchgq %rdx, %rcx + rep stosq + movq %rdx, %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm new file mode 100644 index 0000000..6f364d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/SetMem64.nasm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.S new file mode 100644 index 0000000..e5cb074 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.S @@ -0,0 +1,50 @@ +# +# ConvertAsm.py: Automatically generated from ZeroMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + pushq %rdi + pushq %rcx + xorq %rax, %rax + movq %rcx, %rdi + movq %rdx, %rcx + shrq $3, %rcx + andq $7, %rdx + rep stosq + movl %edx, %ecx + rep stosb + popq %rax + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm new file mode 100644 index 0000000..8e0a5e4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/X64/ZeroMem.nasm @@ -0,0 +1,49 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibRepStr/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf new file mode 100644 index 0000000..a6af7de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf @@ -0,0 +1,126 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/ScanMem64.S + Ia32/ScanMem32.nasm + Ia32/ScanMem32.S + Ia32/ScanMem16.nasm + Ia32/ScanMem16.S + Ia32/ScanMem8.nasm + Ia32/ScanMem8.S + Ia32/CompareMem.nasm + Ia32/CompareMem.S + Ia32/ZeroMem.nasm + Ia32/ZeroMem.S + Ia32/SetMem64.nasm + Ia32/SetMem64.S + Ia32/SetMem32.nasm + Ia32/SetMem32.S + Ia32/SetMem16.nasm + Ia32/SetMem16.S + Ia32/SetMem.nasm + Ia32/SetMem.S + Ia32/CopyMem.nasm + Ia32/CopyMem.S + 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/ScanMem64.S + X64/ScanMem32.nasm + X64/ScanMem32.S + X64/ScanMem16.nasm + X64/ScanMem16.S + X64/ScanMem8.nasm + X64/ScanMem8.S + X64/CompareMem.nasm + X64/CompareMem.S + X64/ZeroMem.nasm + X64/ZeroMem.S + X64/SetMem64.nasm + X64/SetMem64.S + X64/SetMem32.nasm + X64/SetMem32.S + X64/SetMem16.nasm + X64/SetMem16.S + X64/SetMem.nasm + X64/SetMem.S + X64/CopyMem.nasm + X64/CopyMem.S + X64/IsZeroBuffer.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni new file mode 100644 index 0000000..70155dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c new file mode 100644 index 0000000..161171b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.S new file mode 100644 index 0000000..1c9239e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.S @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.Asm +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCompareMem): + push %esi + push %edi + movl 12(%esp), %esi + movl 16(%esp), %edi + movl 20(%esp), %ecx + repe cmpsb + movzbl -1(%esi), %eax + movzbl -1(%edi), %edx + subl %edx, %eax + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm new file mode 100644 index 0000000..e8d1abd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CompareMem.nasm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.S new file mode 100644 index 0000000..0716182 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.S @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.asm +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemCopyMem): + push %esi + push %edi + movl 16(%esp), %esi # esi <- Source + movl 12(%esp), %edi # edi <- Destination + movl 20(%esp), %edx # edx <- Count + leal -1(%esi,%edx,), %eax # eax <- End of Source + cmpl %edi, %esi + jae L0 + cmpl %edi, %eax # Overlapped? + jae L_CopyBackward # Copy backward if overlapped +L0: + xorl %ecx, %ecx + subl %edi, %ecx + andl $15, %ecx # ecx + edi aligns on 16-byte boundary + jz L1 + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx # edx <- remaining bytes to copy + rep + movsb +L1: + movl %edx, %ecx + andl $15, %edx + shrl $4, %ecx # ecx <- # of DQwords to copy + jz L_CopyBytes + addl $-16, %esp + movdqu %xmm0, (%esp) +L2: + movdqu (%esi), %xmm0 + movntdq %xmm0, (%edi) + addl $16, %esi + addl $16, %edi + loop L2 + mfence + movdqu (%esp),%xmm0 + addl $16, %esp # stack cleanup + jmp L_CopyBytes +L_CopyBackward: + movl %eax, %esi # esi <- Last byte in Source + leal -1(%edi,%edx,), %edi # edi <- Last byte in Destination + std +L_CopyBytes: + movl %edx, %ecx + rep + movsb + cld + movl 12(%esp), %eax # eax <- Destination as return value + pop %edi + pop %esi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm new file mode 100644 index 0000000..6913874 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/CopyMem.nasm @@ -0,0 +1,84 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm new file mode 100644 index 0000000..e09ef85 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/IsZeroBuffer.nasm @@ -0,0 +1,74 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.S new file mode 100644 index 0000000..c485543 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.Asm +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem16): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasw + leal -2(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm new file mode 100644 index 0000000..78d9f30 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem16.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.S new file mode 100644 index 0000000..a9b4975 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.Asm +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem32): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movl 16(%esp), %eax + repne scasl + leal -4(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm new file mode 100644 index 0000000..bbacf38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem32.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.S new file mode 100644 index 0000000..e23cf5f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.S @@ -0,0 +1,61 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.Asm +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem64): + push %edi + movl 12(%esp), %ecx + movl 16(%esp), %eax + movl 20(%esp), %edx + movl 8(%esp), %edi +L0: + cmpl (%edi), %eax + leal 8(%edi), %edi + loopne L0 + jne L1 + cmpl -4(%edi), %edx + jecxz L1 + jne L0 +L1: + leal -8(%edi), %eax + cmovne %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm new file mode 100644 index 0000000..e994d4a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem64.nasm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.S new file mode 100644 index 0000000..afefaab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.S @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.Asm +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemScanMem8): + push %edi + movl 12(%esp), %ecx + movl 8(%esp), %edi + movb 16(%esp), %al + repne scasb + leal -1(%edi), %eax + cmovnz %ecx, %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm new file mode 100644 index 0000000..d13c9c7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ScanMem8.nasm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.S new file mode 100644 index 0000000..bcbe0cd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.S @@ -0,0 +1,76 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.asm +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + #.MODEL flat,C + .xmm: + .code: + +#------------------------------------------------------------------------------ +# VOID * +# _mem_SetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + push %edi + movl 12(%esp), %edx # edx <- Count + movl 8(%esp), %edi # edi <- Buffer + movb 16(%esp), %al # al <- Value + xorl %ecx, %ecx + subl %edi, %ecx + andl $15, %ecx # ecx + edi aligns on 16-byte boundary + jz L0 + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx + rep + stosb +L0: + movl %edx, %ecx + andl $15, %edx + shrl $4, %ecx # ecx <- # of DQwords to set + jz L_SetBytes + movb %al, %ah # ax <- Value | (Value << 8) + addl $-16, %esp + movdqu %xmm0, (%esp) + movd %eax, %xmm0 + pshuflw $0, %xmm0, %xmm0 + movlhps %xmm0, %xmm0 +L1: + movntdq %xmm0, (%edi) + addl $16, %edi + loop L1 + mfence + movdqu (%esp), %xmm0 + addl $16, %esp # stack cleanup +L_SetBytes: + movl %edx, %ecx + rep + stosb + movl 8(%esp), %eax # eax <- Buffer as return value + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm new file mode 100644 index 0000000..2852ee5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm @@ -0,0 +1,73 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.S new file mode 100644 index 0000000..4269833 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.S @@ -0,0 +1,69 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.asm +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem16): + push %edi + movl 12(%esp), %edx + movl 8(%esp), %edi + xorl %ecx, %ecx + subl %edi, %ecx + andl $15, %ecx # ecx + edi aligns on 16-byte boundary + movl 16(%esp), %eax + jz L0 + shrl %ecx + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx + rep + stosw +L0: + movl %edx, %ecx + andl $7, %edx + shrl $3, %ecx + jz L_SetWords + movd %eax, %xmm0 + pshuflw $0, %xmm0, %xmm0 + movlhps %xmm0, %xmm0 +L1: + movntdq %xmm0, (%edi) + addl $16, %edi + loop L1 + mfence +L_SetWords: + movl %edx, %ecx + rep + stosw + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm new file mode 100644 index 0000000..3a79e79 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm @@ -0,0 +1,69 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.S new file mode 100644 index 0000000..9e9c7e2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.S @@ -0,0 +1,68 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.asm +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem32): + push %edi + movl 12(%esp), %edx + movl 8(%esp), %edi + xorl %ecx, %ecx + subl %edi, %ecx + andl $15, %ecx # ecx + edi aligns on 16-byte boundary + movl 16(%esp), %eax + jz L0 + shrl $2, %ecx + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx + rep + stosl +L0: + movl %edx, %ecx + andl $3, %edx + shrl $2, %ecx + jz L_SetDwords + movd %eax, %xmm0 + pshufd $0, %xmm0, %xmm0 +L1: + movntdq %xmm0, (%edi) + addl $16, %edi + loop L1 + mfence +L_SetDwords: + movl %edx, %ecx + rep + stosl + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm new file mode 100644 index 0000000..7d2d9fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm @@ -0,0 +1,68 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.S new file mode 100644 index 0000000..d5983e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.S @@ -0,0 +1,58 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemSetMem64): + movl 4(%esp), %eax + movl 8(%esp), %ecx + testb $8, %al + movl %eax, %edx + movq 0xc(%esp), %xmm0 + jz L1 + movq %xmm0, (%edx) + addl $8, %edx + decl %ecx +L1: + shrl %ecx + jz L_SetQwords + movlhps %xmm0, %xmm0 +L2: + movntdq %xmm0, (%edx) + leal 16(%edx), %edx + loop L2 + mfence +L_SetQwords: + jnc L3 + movq %xmm0, (%edx) +L3: + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm new file mode 100644 index 0000000..ace6274 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm @@ -0,0 +1,60 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.S new file mode 100644 index 0000000..2a8c8b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.S @@ -0,0 +1,65 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.asm +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_PFX(InternalMemZeroMem): + push %edi + movl 8(%esp), %edi + movl 12(%esp), %edx + xorl %ecx, %ecx + subl %edi, %ecx + xorl %eax, %eax + andl $15, %ecx + jz L0 + cmpl %edx, %ecx + cmova %edx, %ecx + subl %ecx, %edx + rep + stosb +L0: + movl %edx, %ecx + andl $15, %edx + shrl $4, %ecx + jz L_ZeroBytes + pxor %xmm0, %xmm0 +L1: + movntdq %xmm0, (%edi) + addl $16, %edi + loop L1 + mfence +L_ZeroBytes: + movl %edx, %ecx + rep + stosb + movl 8(%esp), %eax + pop %edi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm new file mode 100644 index 0000000..cee3618 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h new file mode 100644 index 0000000..e7afa23 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/MemLibInternals.h @@ -0,0 +1,251 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c new file mode 100644 index 0000000..6d974d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c new file mode 100644 index 0000000..8e6daa3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c new file mode 100644 index 0000000..7758e1f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c new file mode 100644 index 0000000..5273a86 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.S new file mode 100644 index 0000000..503127c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.S @@ -0,0 +1,59 @@ +# +# ConvertAsm.py: Automatically generated from CompareMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CompareMem.S +# +# Abstract: +# +# CompareMem function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# INTN +# EFIAPI +# InternalMemCompareMem ( +# IN CONST VOID *DestinationBuffer, +# IN CONST VOID *SourceBuffer, +# IN UINTN Length +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCompareMem) +ASM_PFX(InternalMemCompareMem): + pushq %rsi + pushq %rdi + movq %rcx, %rsi + movq %rdx, %rdi + movq %r8, %rcx + repe cmpsb + movzbq -1(%rsi) , %rax + movzbq -1(%rdi) , %rdx + subq %rdx, %rax + popq %rdi + popq %rsi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm new file mode 100644 index 0000000..cb0d886 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CompareMem.nasm @@ -0,0 +1,58 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.S new file mode 100644 index 0000000..7c07eda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.S @@ -0,0 +1,83 @@ +# +# ConvertAsm.py: Automatically generated from CopyMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CopyMem.S +# +# Abstract: +# +# CopyMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemCopyMem ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINTN Count +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemCopyMem) +ASM_PFX(InternalMemCopyMem): + pushq %rsi + pushq %rdi + movq %rdx, %rsi # rsi <- Source + movq %rcx, %rdi # rdi <- Destination + leaq -1(%rsi, %r8,), %r9 # r9 <- Last byte of Source + cmpq %rdi, %rsi + movq %rdi, %rax # rax <- Destination as return value + jae L0 # Copy forward if Source > Destination + cmpq %rdi, %r9 # Overlapped? + jae L_CopyBackward # Copy backward if overlapped +L0: + xorq %rcx, %rcx + subq %rdi, %rcx # rcx <- -rdi + andq $15, %rcx # rcx + rsi should be 16 bytes aligned + jz L1 # skip if rcx == 0 + cmpq %r8, %rcx + cmova %r8, %rcx + subq %rcx, %r8 + rep movsb +L1: + movq %r8, %rcx + andq $15, %r8 + shrq $4, %rcx # rcx <- # of DQwords to copy + jz L_CopyBytes + movdqa %xmm0, 0x18(%rsp) # save xmm0 on stack +L2: + movdqu (%rsi), %xmm0 # rsi may not be 16-byte aligned + movntdq %xmm0, (%rdi) # rdi should be 16-byte aligned + addq $16, %rsi + addq $16, %rdi + loop L2 + mfence + movdqa 0x18(%rsp), %xmm0 # restore xmm0 + jmp L_CopyBytes # copy remaining bytes +L_CopyBackward: + movq %r9, %rsi # rsi <- Last byte of Source + leaq -1(%rdi, %r8,), %rdi # rdi <- Last byte of Destination + std +L_CopyBytes: + movq %r8, %rcx + rep movsb + cld + popq %rdi + popq %rsi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm new file mode 100644 index 0000000..9fe45d4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/CopyMem.nasm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm new file mode 100644 index 0000000..3d5b6a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/IsZeroBuffer.nasm @@ -0,0 +1,76 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.S new file mode 100644 index 0000000..5bdf247 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem16.S +# +# Abstract: +# +# ScanMem16 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem16 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT16 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem16) +ASM_PFX(InternalMemScanMem16): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasw + leaq -2(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm new file mode 100644 index 0000000..9f0de63 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem16.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.S new file mode 100644 index 0000000..9979e97 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem32.S +# +# Abstract: +# +# ScanMem32 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem32 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem32) +ASM_PFX(InternalMemScanMem32): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasl + leaq -4(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm new file mode 100644 index 0000000..5c9ae5d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem32.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.S new file mode 100644 index 0000000..4c994b9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem64.S +# +# Abstract: +# +# ScanMem64 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem64 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem64) +ASM_PFX(InternalMemScanMem64): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasq + leaq -8(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm new file mode 100644 index 0000000..b98c6de --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem64.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.S new file mode 100644 index 0000000..1bb04aa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.S @@ -0,0 +1,56 @@ +# +# ConvertAsm.py: Automatically generated from ScanMem8.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ScanMem8.S +# +# Abstract: +# +# ScanMem8 function +# +# Notes: +# +# The following BaseMemoryLib instances contain the same copy of this file: +# +# BaseMemoryLibRepStr +# BaseMemoryLibMmx +# BaseMemoryLibSse2 +# BaseMemoryLibOptDxe +# BaseMemoryLibOptPei +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# CONST VOID * +# EFIAPI +# InternalMemScanMem8 ( +# IN CONST VOID *Buffer, +# IN UINTN Length, +# IN UINT8 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemScanMem8) +ASM_PFX(InternalMemScanMem8): + pushq %rdi + movq %rcx, %rdi + movq %rdx, %rcx + movq %r8, %rax + repne scasb + leaq -1(%rdi), %rax + cmovnz %rcx, %rax # set rax to 0 if not found + popq %rdi + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm new file mode 100644 index 0000000..8499795 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ScanMem8.nasm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.S new file mode 100644 index 0000000..25012d4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.S @@ -0,0 +1,72 @@ +# +# ConvertAsm.py: Automatically generated from SetMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem.S +# +# Abstract: +# +# SetMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT8 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem) +ASM_PFX(InternalMemSetMem): + pushq %rdi + movq %rcx, %rdi # rdi <- Buffer + movb %r8b, %al # al <- Value + movq %rdi, %r9 # r9 <- Buffer as return value + xorq %rcx, %rcx + subq %rdi, %rcx + andq $15, %rcx # rcx + rdi aligns on 16-byte boundary + jz L0 + cmpq %rdx, %rcx + cmova %rdx, %rcx + subq %rcx, %rdx + rep stosb +L0: + movq %rdx, %rcx + andq $15, %rdx + shrq $4, %rcx + jz L_SetBytes + movb %al, %ah # ax <- Value repeats twice + movdqa %xmm0, 0x10(%rsp) # save xmm0 + movd %eax, %xmm0 # xmm0[0..16] <- Value repeats twice + pshuflw $0, %xmm0, %xmm0 # xmm0[0..63] <- Value repeats 8 times + movlhps %xmm0, %xmm0 # xmm0 <- Value repeats 16 times +L1: + movntdq %xmm0, (%rdi) # rdi should be 16-byte aligned + add $16, %rdi + loop L1 + mfence + movdqa 0x10(%rsp), %xmm0 # restore xmm0 +L_SetBytes: + movl %edx, %ecx # high 32 bits of rcx are always zero + rep stosb + movq %r9, %rax # rax <- Return value + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm new file mode 100644 index 0000000..fddf4c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm @@ -0,0 +1,71 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.S new file mode 100644 index 0000000..e6bdc14 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.S @@ -0,0 +1,70 @@ +# +# ConvertAsm.py: Automatically generated from SetMem16.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem16.S +# +# Abstract: +# +# SetMem16 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem16 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT16 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem16) +ASM_PFX(InternalMemSetMem16): + pushq %rdi + movq %rcx, %rdi + movq %rdi, %r9 + xorq %rcx, %rcx + subq %rdi, %rcx + andq $15, %rcx + movq %r8, %rax + jz L0 + shrq $1, %rcx + cmpq %rdx, %rcx + cmova %rdx, %rcx + subq %rcx, %rdx + rep stosw +L0: + movq %rdx, %rcx + andl $7, %edx + shrq $3, %rcx + jz L_SetWords + movd %eax, %xmm0 + pshuflw $0, %xmm0, %xmm0 + movlhps %xmm0, %xmm0 +L1: + movntdq %xmm0, (%rdi) + addq $16, %rdi + loop L1 + mfence +L_SetWords: + movl %edx, %ecx + rep stosw + movq %r9, %rax + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm new file mode 100644 index 0000000..f2e61e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm @@ -0,0 +1,69 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.S new file mode 100644 index 0000000..e0abd71 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.S @@ -0,0 +1,69 @@ +# +# ConvertAsm.py: Automatically generated from SetMem32.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem32.S +# +# Abstract: +# +# SetMem32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InternalMemSetMem32 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem32) +ASM_PFX(InternalMemSetMem32): + pushq %rdi + movq %rcx, %rdi + movq %rdi, %r9 + xorq %rcx, %rcx + subq %rdi, %rcx + andq $15, %rcx + movq %r8, %rax + jz L0 + shrq $2, %rcx + cmpq %rdx, %rcx + cmova %rdx, %rcx + subq %rcx, %rdx + rep stosl +L0: + movq %rdx, %rcx + andl $3, %edx + shrq $2, %rcx + jz L_SetDwords + movd %eax, %xmm0 + pshufd $0, %xmm0, %xmm0 +L1: + movntdq %xmm0, (%rdi) + addq $16, %rdi + loop L1 + mfence +L_SetDwords: + movl %edx, %ecx + rep stosl + movq %r9, %rax + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm new file mode 100644 index 0000000..d4ecf17 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm @@ -0,0 +1,68 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.S new file mode 100644 index 0000000..de48ff2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.S @@ -0,0 +1,60 @@ +# +# ConvertAsm.py: Automatically generated from SetMem64.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SetMem64.S +# +# Abstract: +# +# SetMem64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemSetMem64 ( +# IN VOID *Buffer, +# IN UINTN Count, +# IN UINT64 Value +# ) +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemSetMem64) +ASM_PFX(InternalMemSetMem64): + movq %rcx, %rax # rax <- Buffer + xchgq %rdx, %rcx # rcx <- Count & rdx <- Buffer + testb $8, %dl + movd %r8, %xmm0 + jz L0 + movq %r8, (%rdx) + addq $8, %rdx + decq %rcx +L0: + shrq $1, %rcx + jz L_SetQwords + movlhps %xmm0, %xmm0 +L1: + movntdq %xmm0, (%rdx) + leaq 16(%rdx), %rdx + loop L1 + mfence +L_SetQwords: + jnc L2 + movq %r8, (%rdx) +L2: + ret + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm new file mode 100644 index 0000000..f543693 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.S new file mode 100644 index 0000000..7cf7a26 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.S @@ -0,0 +1,65 @@ +# +# ConvertAsm.py: Automatically generated from ZeroMem.asm +# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# ZeroMem.S +# +# Abstract: +# +# ZeroMem function +# +# Notes: +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID * +# InternalMemZeroMem ( +# IN VOID *Buffer, +# IN UINTN Count +# ); +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX(InternalMemZeroMem) +ASM_PFX(InternalMemZeroMem): + pushq %rdi + movq %rcx, %rdi + xorq %rcx, %rcx + xorl %eax, %eax + subq %rdi, %rcx + andq $15, %rcx + movq %rdi, %r8 + jz L0 + cmpq %rdx, %rcx + cmova %rdx, %rcx + subq %rcx, %rdx + rep stosb +L0: + movq %rdx, %rcx + andl $15, %edx + shrq $4, %rcx + jz L_ZeroBytes + pxor %xmm0, %xmm0 +L1: + movntdq %xmm0, (%rdi) # rdi should be 16-byte aligned + addq $16, %rdi + loop L1 + mfence +L_ZeroBytes: + movl %edx, %ecx + rep stosb + movq %r8, %rax + popq %rdi + ret diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm new file mode 100644 index 0000000..1dd0a14 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm @@ -0,0 +1,65 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseMemoryLibSse2/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c new file mode 100644 index 0000000..3089c1d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.c @@ -0,0 +1,1454 @@ +/** @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.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License that accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf new file mode 100644 index 0000000..bc4ab56 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf @@ -0,0 +1,51 @@ +## @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. +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License that accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +# IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni new file mode 100644 index 0000000..73f1fb4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.uni @@ -0,0 +1,31 @@ +// /** @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. +// +// This program and the accompanying materials are licensed and made available +// under the terms and conditions of the BSD License that accompanies this +// distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +// IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf new file mode 100644 index 0000000..abc8680 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf @@ -0,0 +1,42 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni new file mode 100644 index 0000000..a51c8bd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c new file mode 100644 index 0000000..907aeed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePcdLibNull/PcdLib.c @@ -0,0 +1,1480 @@ +/** @file + A emptry template implementation of PCD Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf new file mode 100644 index 0000000..dbddf8d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf @@ -0,0 +1,42 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni new file mode 100644 index 0000000..6e44ffd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c new file mode 100644 index 0000000..5e2239b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciCf8Lib/PciCf8Lib.c @@ -0,0 +1,1784 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + +// +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf new file mode 100644 index 0000000..9f8cc48 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf @@ -0,0 +1,46 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni new file mode 100644 index 0000000..b04bd0e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c new file mode 100644 index 0000000..cd34bf4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciExpressLib/PciExpressLib.c @@ -0,0 +1,1419 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf new file mode 100644 index 0000000..2afc1dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf @@ -0,0 +1,40 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni new file mode 100644 index 0000000..1f1e5fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c new file mode 100644 index 0000000..47aa21a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibCf8/PciLib.c @@ -0,0 +1,1138 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf new file mode 100644 index 0000000..d223a1d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf @@ -0,0 +1,41 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni new file mode 100644 index 0000000..a811604 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c new file mode 100644 index 0000000..74657b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciLibPciExpress/PciLib.c @@ -0,0 +1,1138 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf new file mode 100644 index 0000000..c280f84 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf @@ -0,0 +1,41 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni new file mode 100644 index 0000000..25e8cce --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.uni @@ -0,0 +1,20 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c new file mode 100644 index 0000000..36a7a3b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c @@ -0,0 +1,38 @@ +/** @file + Default PCI Segment Information Library that returns one segment whose + segment base address equals to PcdPciExpressBaseAddress. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + 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 * +GetPciSegmentInfo ( + UINTN *Count + ) +{ + ASSERT (FALSE); + *Count = 0; + return NULL; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf new file mode 100644 index 0000000..6586b85 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf @@ -0,0 +1,43 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni new file mode 100644 index 0000000..b6d4ef6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c new file mode 100644 index 0000000..735d598 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePciSegmentLibPci/PciSegmentLib.c @@ -0,0 +1,1290 @@ +/** @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.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf new file mode 100644 index 0000000..9195f94 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf @@ -0,0 +1,38 @@ +## @file +# Null PE/Coff Extra Action library instances with empty functions. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c new file mode 100644 index 0000000..b4cdebc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLib.c @@ -0,0 +1,54 @@ +/** @file + Null PE/Coff Extra Action library instances with empty functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni new file mode 100644 index 0000000..27af386 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffExtraActionLibNull/PeCoffExtraActionLibNull.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf new file mode 100644 index 0000000..bea61c2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf @@ -0,0 +1,40 @@ +## @file +# PE/COFF Entry Point Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni new file mode 100644 index 0000000..a94dac8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.uni @@ -0,0 +1,21 @@ +// /** @file +// PE/COFF Entry Point Library implementation. +// +// PE/COFF Entry Point Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c new file mode 100644 index 0000000..13b3f45 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c @@ -0,0 +1,388 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include + +#include + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c new file mode 100644 index 0000000..ad24eb4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c @@ -0,0 +1,250 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c new file mode 100644 index 0000000..3885abe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoff.c @@ -0,0 +1,1949 @@ +/** @file + Base PE/COFF loader supports loading any PE32/PE32+ or TE image, but + only supports relocating IA32, x64, IPF, 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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf new file mode 100644 index 0000000..11a4d03 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/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. +# +# 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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + PeCoffExtraActionLib + BaseMemoryLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni new file mode 100644 index 0000000..e78d680 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.uni @@ -0,0 +1,29 @@ +// /** @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. +// +// 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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h new file mode 100644 index 0000000..a2feecd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h @@ -0,0 +1,133 @@ +/** @file + Declaration of internal functions in PE/COFF Lib. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_PECOFF_LIB_INTERNALS__ +#define __BASE_PECOFF_LIB_INTERNALS__ + +#include +#include +#include +#include +#include +#include + + + +/** + 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 + ); + + +/** + 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 + ); + + +/** + 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 + ); + +/** + Retrieves the magic value from the PE/COFF header. + + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. + + @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32 + @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+ + +**/ +UINT16 +PeCoffLoaderGetPeHeaderMagicValue ( + IN EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr + ); + +/** + Retrieves the PE or TE Header from a PE/COFF or TE image. + + @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 + ); + +/** + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c new file mode 100644 index 0000000..e21fb99 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c @@ -0,0 +1,90 @@ +/** @file + Specific relocation fixups for none Itanium architecture. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf new file mode 100644 index 0000000..10fd330 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf @@ -0,0 +1,45 @@ +## @file +# Instance of Performance Library with empty functions. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni new file mode 100644 index 0000000..3194683 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.uni @@ -0,0 +1,21 @@ +// /** @file +// Instance of Performance Library with empty functions. +// +// Instance of Performance Library with empty functions. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c new file mode 100644 index 0000000..8bfc796 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c @@ -0,0 +1,361 @@ +/** @file + Base Performance Library which provides no service. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf new file mode 100644 index 0000000..97ceb4d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf @@ -0,0 +1,50 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni new file mode 100644 index 0000000..9a26925 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c new file mode 100644 index 0000000..e9cf568 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibDebug/PostCode.c @@ -0,0 +1,127 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf new file mode 100644 index 0000000..c88eb90 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf @@ -0,0 +1,48 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni new file mode 100644 index 0000000..c86bf7c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c new file mode 100644 index 0000000..625a718 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePostCodeLibPort80/PostCode.c @@ -0,0 +1,145 @@ +/** @file + Post Code Library instance that writes post code values to I/O port 0x80. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf new file mode 100644 index 0000000..70f7f22 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf @@ -0,0 +1,50 @@ +## @file +# Print Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni new file mode 100644 index 0000000..75fec00 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/BasePrintLib.uni @@ -0,0 +1,21 @@ +// /** @file +// Print Library implementation. +// +// Print Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Print Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "Print Library implementation." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLib.c new file mode 100644 index 0000000..f0f59e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLib.c @@ -0,0 +1,961 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c new file mode 100644 index 0000000..0a8cfe3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.c @@ -0,0 +1,1269 @@ +/** @file + Print Library internal worker functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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'}; + +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 * CONST mStatusString[] = { + "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 + "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 = mStatusString [Index + WARNING_STATUS_NUMBER]; + } + } else { + Index = Status; + if (Index <= WARNING_STATUS_NUMBER) { + ArgumentString = mStatusString [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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h new file mode 100644 index 0000000..d2603d3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BasePrintLib/PrintLibInternal.h @@ -0,0 +1,277 @@ +/** @file + Base Print Library instance Internal Functions definition. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c new file mode 100644 index 0000000..e9416b2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLib.c @@ -0,0 +1,392 @@ +/** @file + Null Base Report Status Code Library instance with empty functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf new file mode 100644 index 0000000..92a28ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf @@ -0,0 +1,39 @@ +## @file +# Report Status Code Library with empty functions. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni new file mode 100644 index 0000000..50818f3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.uni @@ -0,0 +1,21 @@ +// /** @file +// Report Status Code Library with empty functions. +// +// Report Status Code Library with empty functions. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRng.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRng.c new file mode 100644 index 0000000..b21c54a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRng.c @@ -0,0 +1,189 @@ +/** @file + Random number generator services that uses RdRand instruction access + to provide high-quality random numbers. + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf new file mode 100644 index 0000000..0d5a2a2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf @@ -0,0 +1,41 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni new file mode 100644 index 0000000..db36a38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseRngLib/BaseRngLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf new file mode 100644 index 0000000..ebf0540 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf @@ -0,0 +1,43 @@ +## @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.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni new file mode 100644 index 0000000..169a95a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.uni @@ -0,0 +1,24 @@ +// /** @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.
+// +// This program and the accompanying materials are +// licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c new file mode 100644 index 0000000..8925fc9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3BootScriptLibNull/BootScriptLib.c @@ -0,0 +1,568 @@ +/** @file + Null function implementation for EFI S3 boot script. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf new file mode 100644 index 0000000..5b73d61 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf @@ -0,0 +1,46 @@ +## @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.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni new file mode 100644 index 0000000..04dbb20 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/BaseS3IoLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials are +// licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c new file mode 100644 index 0000000..acb9b45 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3IoLib/S3IoLib.c @@ -0,0 +1,3312 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf new file mode 100644 index 0000000..48a3c99 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf @@ -0,0 +1,47 @@ +## @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.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni new file mode 100644 index 0000000..a577b11 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/BaseS3PciLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials are +// licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c new file mode 100644 index 0000000..8eede55 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciLib/S3PciLib.c @@ -0,0 +1,1269 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf new file mode 100644 index 0000000..50b4fca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf @@ -0,0 +1,45 @@ +## @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.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni new file mode 100644 index 0000000..2991c4b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials are +// licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c new file mode 100644 index 0000000..9a8d015 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3PciSegmentLib/S3PciSegmentLib.c @@ -0,0 +1,1249 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf new file mode 100644 index 0000000..b42aecc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf @@ -0,0 +1,47 @@ +## @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.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni new file mode 100644 index 0000000..e8fa60f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials are +// licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c new file mode 100644 index 0000000..e10b2a8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3SmbusLib/S3SmbusLib.c @@ -0,0 +1,502 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf new file mode 100644 index 0000000..a1f7cc9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf @@ -0,0 +1,45 @@ +## @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.
+# +# This program and the accompanying materials are +# licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni new file mode 100644 index 0000000..fcff510 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/BaseS3StallLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials are +// licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c new file mode 100644 index 0000000..ad39260 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseS3StallLib/S3StallLib.c @@ -0,0 +1,52 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf new file mode 100644 index 0000000..e2b543d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf @@ -0,0 +1,62 @@ +## @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 +# +# All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +## + +[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 +# + +[Sources] + SafeIntLib.c + +[Sources.Ia32, Sources.ARM] + SafeIntLib32.c + +[Sources.X64, Sources.AARCH64] + SafeIntLib64.c + +[Sources.EBC] + SafeIntLibEbc.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c new file mode 100644 index 0000000..72f464f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib.c @@ -0,0 +1,4165 @@ +/** @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. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#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 = (((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 = (((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 = (((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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c new file mode 100644 index 0000000..d34c735 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib32.c @@ -0,0 +1,555 @@ +/** @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. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c new file mode 100644 index 0000000..e8d3016 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLib64.c @@ -0,0 +1,508 @@ +/** @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. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c new file mode 100644 index 0000000..d715cdc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSafeIntLib/SafeIntLibEbc.c @@ -0,0 +1,614 @@ +/** @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. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c new file mode 100644 index 0000000..ed173e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.c @@ -0,0 +1,197 @@ +/** @file + Null Serial Port library instance with empty functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf new file mode 100644 index 0000000..79dda12 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf @@ -0,0 +1,36 @@ +## @file +# Null instance of Serial Port Library with empty functions. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni new file mode 100644 index 0000000..5af091f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c new file mode 100644 index 0000000..ffd61b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.c @@ -0,0 +1,544 @@ +/** @file +Null implementation of SmBusLib class library. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf new file mode 100644 index 0000000..0abd266 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf @@ -0,0 +1,35 @@ +## @file +# Null implementation of the SMBUS Library. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni new file mode 100644 index 0000000..00e6d6b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.uni @@ -0,0 +1,21 @@ +// /** @file +// Null implementation of the SMBUS Library. +// +// Null implementation of the SMBUS Library. +// +// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c new file mode 100644 index 0000000..ad3f268 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckGcc.c @@ -0,0 +1,55 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +/// "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf new file mode 100644 index 0000000..4a6466c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf @@ -0,0 +1,45 @@ +## @file +# Stack Check Library +# +# Stack Check Library +# +# Copyright (c) 2014, ARM Ltd. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni new file mode 100644 index 0000000..1c50362 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.uni @@ -0,0 +1,21 @@ +// /** @file +// Stack Check Library +// +// Stack Check Library +// +// Copyright (c) 2014, ARM Ltd. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Stack Check Library" + +#string STR_MODULE_DESCRIPTION #language en-US "Stack Check Library" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c new file mode 100644 index 0000000..9f7a3b5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseStackCheckLib/BaseStackCheckNull.c @@ -0,0 +1,15 @@ +/** @file + This file is purely empty as a work around for BaseStackCheck to pass MSVC build. + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +extern int __BaseStackCheckNull; diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S new file mode 100644 index 0000000..2edd526 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.S @@ -0,0 +1,205 @@ +// 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. +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm new file mode 100644 index 0000000..52f49a5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/AArch64/Synchronization.asm @@ -0,0 +1,205 @@ +; 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. +; +; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S new file mode 100644 index 0000000..b63feba --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.S @@ -0,0 +1,213 @@ +// Implementation of synchronization functions for ARM architecture +// +// Copyright (c) 2012-2015, ARM Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. All rights reserved. +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// + +.text +.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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm new file mode 100644 index 0000000..fac8794 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Arm/Synchronization.asm @@ -0,0 +1,214 @@ +// Implementation of synchronization functions for ARM architecture +// +// Copyright (c) 2012-2015, ARM Limited. All rights reserved. +// Copyright (c) 2015, Linaro Limited. All rights reserved. +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// + + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf new file mode 100644 index 0000000..76fe20a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + PcdLib + TimerLib + DebugLib + BaseMemoryLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout ## SOMETIMES_CONSUMES + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni new file mode 100644 index 0000000..e12e05f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h new file mode 100644 index 0000000..46cc5c0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLibInternals.h @@ -0,0 +1,151 @@ +/** @file + Declaration of internal functions in BaseSynchronizationLib. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c new file mode 100644 index 0000000..bf30338 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ebc/Synchronization.c @@ -0,0 +1,147 @@ +/** @file + Implementation of synchronization functions on EBC. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c new file mode 100644 index 0000000..0a9a124 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/GccInline.c @@ -0,0 +1,207 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c new file mode 100644 index 0000000..81a890a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.c @@ -0,0 +1,51 @@ +/** @file + InterlockedCompareExchange16 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm new file mode 100644 index 0000000..5beeede --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange16.nasm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c new file mode 100644 index 0000000..3dd737b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.c @@ -0,0 +1,50 @@ +/** @file + InterlockedCompareExchange32 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm new file mode 100644 index 0000000..62cbb11 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange32.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c new file mode 100644 index 0000000..68c5274 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.c @@ -0,0 +1,50 @@ +/** @file + InterlockedCompareExchange64 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm new file mode 100644 index 0000000..c55d55c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedCompareExchange64.nasm @@ -0,0 +1,48 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm new file mode 100644 index 0000000..397c0bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedDecrement.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm new file mode 100644 index 0000000..3925e85 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InterlockedIncrement.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c new file mode 100644 index 0000000..0fefda7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c @@ -0,0 +1,64 @@ +/** @file + Internal function to get spin lock alignment. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c new file mode 100644 index 0000000..b11588e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedDecrementMsc.c @@ -0,0 +1,46 @@ +/** @file + InterlockedDecrement function + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c new file mode 100644 index 0000000..206729a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/InterlockedIncrementMsc.c @@ -0,0 +1,46 @@ +/** @file + InterLockedIncrement function + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c new file mode 100644 index 0000000..0ad0ec7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/Synchronization.c @@ -0,0 +1,416 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c new file mode 100644 index 0000000..d0d8296 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c @@ -0,0 +1,432 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c new file mode 100644 index 0000000..5591d24 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/SynchronizationMsc.c @@ -0,0 +1,434 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c new file mode 100644 index 0000000..e137305 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/GccInline.c @@ -0,0 +1,206 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c new file mode 100644 index 0000000..d51d6e3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.c @@ -0,0 +1,54 @@ +/** @file + InterlockedCompareExchange16 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm new file mode 100644 index 0000000..b9ef3d4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange16.nasm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; Copyright (c) 2015, Linaro Ltd. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c new file mode 100644 index 0000000..b275d67 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.c @@ -0,0 +1,54 @@ +/** @file + InterlockedCompareExchange32 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm new file mode 100644 index 0000000..e199ef9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange32.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c new file mode 100644 index 0000000..c7b6daa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.c @@ -0,0 +1,53 @@ +/** @file + InterlockedCompareExchange64 function + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm new file mode 100644 index 0000000..e78de53 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedCompareExchange64.nasm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm new file mode 100644 index 0000000..bd24b96 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedDecrement.nasm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm new file mode 100644 index 0000000..b37fedf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseSynchronizationLib/X64/InterlockedIncrement.nasm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf new file mode 100644 index 0000000..106c1d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf @@ -0,0 +1,45 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni new file mode 100644 index 0000000..eaffc8e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.uni @@ -0,0 +1,24 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c new file mode 100644 index 0000000..93766b5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseTimerLibNullTemplate/TimerLibNull.c @@ -0,0 +1,134 @@ +/** @file + A non-functional instance of the Timer Library. + + Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c new file mode 100644 index 0000000..2ea481c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c @@ -0,0 +1,822 @@ +/** @file + UEFI Decompress Library implementation refer to UEFI specification. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include +#include +#include + +#include "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) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + if (Index >= MaxTableLength) { + return (UINT16) BAD_TABLE; + } + 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(). + + @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 + ) +{ + UINT32 CompSize; + UINT32 OrigSize; + SCRATCH_DATA *Sd; + CONST UINT8 *Src; + UINT8 *Dst; + + ASSERT (Source != NULL); + ASSERT (Destination != NULL); + ASSERT (Scratch != NULL); + + Src = Source; + Dst = Destination; + + Sd = (SCRATCH_DATA *) Scratch; + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return RETURN_SUCCESS; + } + + Src = Src + 8; + SetMem (Sd, sizeof (SCRATCH_DATA), 0); + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For UEFI 2.0 de/compression algorithm(Version 1), mPBit = 4 + // + Sd->mPBit = 4; + 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; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf new file mode 100644 index 0000000..7c1e7cc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf @@ -0,0 +1,43 @@ +## @file +# UEFI Decompress Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni new file mode 100644 index 0000000..3d7db17 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.uni @@ -0,0 +1,21 @@ +// /** @file +// UEFI Decompress Library implementation. +// +// UEFI Decompress Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI Decompress Library implementation" + +#string STR_MODULE_DESCRIPTION #language en-US "UEFI Decompress Library implementation." + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h new file mode 100644 index 0000000..91d7ad9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLibInternals.h @@ -0,0 +1,211 @@ +/** @file + Internal data structure defintions for Base UEFI Decompress Library. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_UEFI_DECOMPRESS_LIB_INTERNALS_H__ +#define __BASE_UEFI_DECOMPRESS_LIB_INTERNALS_H__ + +// +// 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. + /// + 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 + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c new file mode 100644 index 0000000..dc6d96c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c @@ -0,0 +1,79 @@ +/** @file + Entry point to the DXE Core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + + +#include +#include +#include + +// +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf new file mode 100644 index 0000000..49677c0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf @@ -0,0 +1,41 @@ +## @file +# Module entry point library for DXE core. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni new file mode 100644 index 0000000..3af375f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.uni @@ -0,0 +1,21 @@ +// /** @file +// Module entry point library for DXE core. +// +// Module entry point library for DXE core. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf new file mode 100644 index 0000000..b39992f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf @@ -0,0 +1,44 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni new file mode 100644 index 0000000..5d90208 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c new file mode 100644 index 0000000..4b6f895 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeCoreHobLib/HobLib.c @@ -0,0 +1,603 @@ +/** @file + HOB Library implementation for DxeCore driver. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c new file mode 100644 index 0000000..7ecc93b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.c @@ -0,0 +1,455 @@ +/** @file + Provide generic extract guided section functions for Dxe phase. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include + +#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 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 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 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 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 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; + + // + // 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf new file mode 100644 index 0000000..15fba0a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf @@ -0,0 +1,47 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni new file mode 100644 index 0000000..c37815a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf new file mode 100644 index 0000000..a3654a7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.inf @@ -0,0 +1,48 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni new file mode 100644 index 0000000..a7592fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/DxeHobLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/HobLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/HobLib.c new file mode 100644 index 0000000..7a7c952 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHobLib/HobLib.c @@ -0,0 +1,637 @@ +/** @file + HOB Library implemenation for Dxe Phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf new file mode 100644 index 0000000..0f76fd7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.inf @@ -0,0 +1,48 @@ +## @file +# DXE instance of Hsti Library. +# +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni new file mode 100644 index 0000000..6a09ddd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/DxeHstiLib.uni @@ -0,0 +1,19 @@ +// /** @file +// DXE instance of Hsti Library. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c new file mode 100644 index 0000000..0c2b444 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiAip.c @@ -0,0 +1,175 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c new file mode 100644 index 0000000..424c488 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.c @@ -0,0 +1,612 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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)) { + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h new file mode 100644 index 0000000..517f348 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeHstiLib/HstiDxe.h @@ -0,0 +1,65 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h new file mode 100644 index 0000000..e903c89 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeCpuIo2LibInternal.h @@ -0,0 +1,172 @@ +/** @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.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf new file mode 100644 index 0000000..79f65af --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf @@ -0,0 +1,53 @@ +## @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.
+# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni new file mode 100644 index 0000000..6d68716 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials are licensed and made available +// under the terms and conditions of the BSD License which accompanies this +// distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c new file mode 100644 index 0000000..8d88a35 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoHighLevel.c @@ -0,0 +1,2307 @@ +/** @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.
+ This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c new file mode 100644 index 0000000..c437ef9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLib.c @@ -0,0 +1,869 @@ +/** @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.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "DxeCpuIo2LibInternal.h" + +// +// Globle varible 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c new file mode 100644 index 0000000..c25cb9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeIoLibCpuIo2/IoLibMmioBuffer.c @@ -0,0 +1,413 @@ +/** @file + I/O Library MMIO Buffer Functions. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c new file mode 100644 index 0000000..c7eefac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.c @@ -0,0 +1,1626 @@ +/** @file +Implementation of PcdLib class library for DXE phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf new file mode 100644 index 0000000..5135325 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -0,0 +1,68 @@ +## @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 aviable in OS runtime phase. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni new file mode 100644 index 0000000..33bf628 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxePcdLib/DxePcdLib.uni @@ -0,0 +1,31 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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 supporst 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c new file mode 100644 index 0000000..154bf20 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DebugLib.c @@ -0,0 +1,346 @@ +/** @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 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 + +/** + 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->CreateEventEx (EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, ExitBootServicesEvent, NULL, + &gEfiEventExitBootServicesGuid, + &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, + ... + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + 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 + // + VA_START (Marker, Format); + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + // + // Send the print string to a Serial Port + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); +} + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf new file mode 100644 index 0000000..f1bb2bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf @@ -0,0 +1,55 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 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 + +[Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni new file mode 100644 index 0000000..bf3dad5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf new file mode 100644 index 0000000..6c48180 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf @@ -0,0 +1,58 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[Guids] + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni new file mode 100644 index 0000000..d9e72f1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.uni @@ -0,0 +1,26 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c new file mode 100644 index 0000000..f9096bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c @@ -0,0 +1,1660 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// Define 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->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DxeRuntimePciExpressLibVirtualNotify, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &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 registerd 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 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; + + // + // 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 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; + + // + // 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/Allocate.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/Allocate.c new file mode 100644 index 0000000..fe40549 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/Allocate.c @@ -0,0 +1,54 @@ +/** @file + DxeServicesLib memory allocation routines + + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c new file mode 100644 index 0000000..3024b8f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.c @@ -0,0 +1,1098 @@ +/** @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
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + 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 succesfully 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 ( + (EFI_HANDLE *) 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 sepcifed + 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 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 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 absracted 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 seperate. 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf new file mode 100644 index 0000000..c641d08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf @@ -0,0 +1,65 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 +# + +[Sources] + DxeServicesLib.c + +[Sources.IA32, Sources.EBC, Sources.ARM, Sources.AARCH64] + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni new file mode 100644 index 0000000..57f3176 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/DxeServicesLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c new file mode 100644 index 0000000..913a8a1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesLib/X64/Allocate.c @@ -0,0 +1,69 @@ +/** @file + DxeServicesLib memory allocation routines + + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c new file mode 100644 index 0000000..16b7689 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c @@ -0,0 +1,68 @@ +/** @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 contruct function to retrieve EFI_DXE_SERIVCE, this construct + function will be invoked in DXE driver's autogen file. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +// +// 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf new file mode 100644 index 0000000..bbb8d00 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf @@ -0,0 +1,49 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni new file mode 100644 index 0000000..e437230 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c new file mode 100644 index 0000000..cf87294 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c @@ -0,0 +1,104 @@ +/** @file +Implementation of SmBusLib class library for DXE phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + +#include "InternalSmbusLib.h" + + +// +// Globle varible 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf new file mode 100644 index 0000000..0eb8408 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf @@ -0,0 +1,51 @@ +## @file +# SMBUS Library that layers on top of the SMBUS Protocol. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni new file mode 100644 index 0000000..30adce8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h new file mode 100644 index 0000000..82bb301 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h @@ -0,0 +1,85 @@ +/** @file +Internal header file for Smbus library. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __INTERNAL_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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c new file mode 100644 index 0000000..bdce7bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/DxeSmbusLib/SmbusLib.c @@ -0,0 +1,592 @@ +/** @file +Implementation of SmBusLib class library for DXE phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c new file mode 100644 index 0000000..3ddd05f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.c @@ -0,0 +1,63 @@ +/** @file + MM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf new file mode 100644 index 0000000..33001ae --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf @@ -0,0 +1,45 @@ +## @file +# MM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni new file mode 100644 index 0000000..a02c96f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/MmServicesTableLib/MmServicesTableLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c new file mode 100644 index 0000000..4a4f014 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLib.c @@ -0,0 +1,71 @@ +/** @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.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf new file mode 100644 index 0000000..a852257 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf @@ -0,0 +1,46 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni new file mode 100644 index 0000000..49793c8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c new file mode 100644 index 0000000..862dfbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLib.c @@ -0,0 +1,321 @@ +/** @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.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DxeRuntimePciSegmentLibVirtualNotify, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &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 registerd 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf new file mode 100644 index 0000000..d7019f5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf @@ -0,0 +1,55 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[Guids] + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni new file mode 100644 index 0000000..b8cfcfa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c new file mode 100644 index 0000000..02d84d0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.c @@ -0,0 +1,1375 @@ +/** @file + Provide common routines used by BasePciSegmentLibSegmentInfo and + DxeRuntimePciSegmentLibSegmentInfo libraries. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 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; + 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 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; + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h new file mode 100644 index 0000000..936d499 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PciSegmentLibSegmentInfo/PciSegmentLibCommon.h @@ -0,0 +1,57 @@ +/** @file + Provide common routines used by BasePciSegmentLibSegmentInfo and + DxeRuntimePciSegmentLibSegmentInfo libraries. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c new file mode 100644 index 0000000..d790638 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c @@ -0,0 +1,101 @@ +/** @file + Entry point to a the PEI Core. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf new file mode 100644 index 0000000..5fccbef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf @@ -0,0 +1,39 @@ +## @file +# Module entry point library for PEI core. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni new file mode 100644 index 0000000..e5ae4b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.uni @@ -0,0 +1,21 @@ +// /** @file +// Module entry point library for PEI core. +// +// Module entry point library for PEI core. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf new file mode 100644 index 0000000..a4c9f61 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf @@ -0,0 +1,45 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni new file mode 100644 index 0000000..67b761a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c new file mode 100644 index 0000000..549ef9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PostCode.c @@ -0,0 +1,159 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c new file mode 100644 index 0000000..70dd998 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.c @@ -0,0 +1,519 @@ +/** @file + Provide generic extract guided section functions for PEI phase. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf new file mode 100644 index 0000000..d2cc94a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf @@ -0,0 +1,48 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni new file mode 100644 index 0000000..6842496 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/HobLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/HobLib.c new file mode 100644 index 0000000..c37cded --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/HobLib.c @@ -0,0 +1,858 @@ +/** @file + Provide Hob Library functions for Pei phase. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf new file mode 100644 index 0000000..0a04ba7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.inf @@ -0,0 +1,56 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni new file mode 100644 index 0000000..38fc17c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiHobLib/PeiHobLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c new file mode 100644 index 0000000..707d83a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c @@ -0,0 +1,2356 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c new file mode 100644 index 0000000..6b8141e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLib.c @@ -0,0 +1,835 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c new file mode 100644 index 0000000..5453d13 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c @@ -0,0 +1,418 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf new file mode 100644 index 0000000..7c1b680 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf @@ -0,0 +1,48 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni new file mode 100644 index 0000000..4931d69 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 0000000..1b512d8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,848 @@ +/** @file + Support routines for memory allocation routines + based on PeiService for PEI phase drivers. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + + +#include +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf new file mode 100644 index 0000000..9939d94 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf @@ -0,0 +1,45 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni new file mode 100644 index 0000000..6f84d69 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c new file mode 100644 index 0000000..a80ea43 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c new file mode 100644 index 0000000..c3429d1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLib.c @@ -0,0 +1,71 @@ +/** @file + Base Memory Library functions implementation bases on PeiServcie. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c new file mode 100644 index 0000000..42e2e7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c @@ -0,0 +1,289 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h new file mode 100644 index 0000000..71897bb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/MemLibInternals.h @@ -0,0 +1,249 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf new file mode 100644 index 0000000..42bfdfc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf @@ -0,0 +1,60 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni new file mode 100644 index 0000000..f4ac7bb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c new file mode 100644 index 0000000..6d974d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c new file mode 100644 index 0000000..7001f29 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c new file mode 100644 index 0000000..c51b846 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c new file mode 100644 index 0000000..f412897 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c new file mode 100644 index 0000000..f9ed175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiMemoryLib/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c new file mode 100644 index 0000000..998743c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.c @@ -0,0 +1,1625 @@ +/** @file +Implementation of PcdLib class library for PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + + + + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf new file mode 100644 index 0000000..b5d87ff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.inf @@ -0,0 +1,66 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni new file mode 100644 index 0000000..e892581 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPcdLib/PeiPcdLib.uni @@ -0,0 +1,33 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c new file mode 100644 index 0000000..07a2578 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PciLib.c @@ -0,0 +1,1422 @@ +/** @file + PCI Library using PCI CFG2 PPI. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf new file mode 100644 index 0000000..dc0a12e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf @@ -0,0 +1,56 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni new file mode 100644 index 0000000..3bba2e8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.uni @@ -0,0 +1,25 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c new file mode 100644 index 0000000..7c65956 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PciSegmentLib.c @@ -0,0 +1,1414 @@ +/** @file + PCI Segment Library implementation using PCI CFG2 PPI. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf new file mode 100644 index 0000000..82594a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf @@ -0,0 +1,53 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni new file mode 100644 index 0000000..82d1cca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.uni @@ -0,0 +1,24 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c new file mode 100644 index 0000000..abd0c09 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c @@ -0,0 +1,58 @@ +/** @file + Resource Publication Library that uses PEI Core Services to publish system memory. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +#include + + +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf new file mode 100644 index 0000000..37495ac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf @@ -0,0 +1,42 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni new file mode 100644 index 0000000..593f877 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c new file mode 100644 index 0000000..251773c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.c @@ -0,0 +1,817 @@ +/** @file + Implementation for PEI Services Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +/** + 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. ResetData is only valid if ResetStatus is something + other than EFI_SUCCESS unless the ResetType is EfiResetPlatformSpecific + where a minimum amount of ResetData is always required. + +**/ +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf new file mode 100644 index 0000000..6476169 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.inf @@ -0,0 +1,48 @@ +## @file +# PEI Services Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni new file mode 100644 index 0000000..ce1028e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesLib/PeiServicesLib.uni @@ -0,0 +1,21 @@ +// /** @file +// PEI Services Library implementation. +// +// PEI Services Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c new file mode 100644 index 0000000..9a6ce37 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c @@ -0,0 +1,116 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf new file mode 100644 index 0000000..cab883c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf @@ -0,0 +1,44 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni new file mode 100644 index 0000000..96fd42d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c new file mode 100644 index 0000000..7392d3c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointer.c @@ -0,0 +1,131 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf new file mode 100644 index 0000000..93dc134 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf @@ -0,0 +1,43 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni new file mode 100644 index 0000000..e290665 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h new file mode 100644 index 0000000..c7504e2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/InternalSmbusLib.h @@ -0,0 +1,80 @@ +/** @file +Internal header file for Smbus library. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#ifndef __INTERNAL_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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c new file mode 100644 index 0000000..1ce9d04 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLib.c @@ -0,0 +1,95 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf new file mode 100644 index 0000000..bf78fe5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf @@ -0,0 +1,50 @@ +## @file +# SMBUS library that layers on top of the SMBUS2 PPI. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni new file mode 100644 index 0000000..e783ddc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c new file mode 100644 index 0000000..e1785bf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeiSmbusLibSmbus2Ppi/SmbusLib.c @@ -0,0 +1,584 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c new file mode 100644 index 0000000..77dcada --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c @@ -0,0 +1,81 @@ +/** @file + Entry point to a PEIM. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf new file mode 100644 index 0000000..724c4a8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf @@ -0,0 +1,39 @@ +## @file +# Module entry point library for PEIM. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni new file mode 100644 index 0000000..a1894f5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.uni @@ -0,0 +1,21 @@ +// /** @file +// Module entry point library for PEIM. +// +// Module entry point library for PEIM. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf new file mode 100644 index 0000000..a511000 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf @@ -0,0 +1,59 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni new file mode 100644 index 0000000..a758c7f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.uni @@ -0,0 +1,31 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c new file mode 100644 index 0000000..4b99a70 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/X86TimerLib.c @@ -0,0 +1,375 @@ +/** @file + Timer Library functions built upon local APIC on IA32/x64. + + Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c new file mode 100644 index 0000000..cd5c81a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c @@ -0,0 +1,78 @@ +/** @file + NULL instance of SmiHandlerProfile Library. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf new file mode 100644 index 0000000..edfce21 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf @@ -0,0 +1,36 @@ +## @file +# NULL instance of SmiHandlerProfile Library. +# +# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni new file mode 100644 index 0000000..5d7e75b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.uni @@ -0,0 +1,21 @@ +// /** @file +// NULL instance of SmiHandlerProfile Library. +// +// NULL instance of SmiHandlerProfile Library. +// +// Copyright (c) 2017, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c new file mode 100644 index 0000000..cd44631 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.c @@ -0,0 +1,331 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf new file mode 100644 index 0000000..25c04c3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.inf @@ -0,0 +1,53 @@ +## @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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni new file mode 100644 index 0000000..2498b08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLib/SmmIoLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c new file mode 100644 index 0000000..e8f007f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoHighLevel.c @@ -0,0 +1,2312 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + The 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c new file mode 100644 index 0000000..d25239c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLib.c @@ -0,0 +1,803 @@ +/** @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.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c new file mode 100644 index 0000000..59ccec0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/IoLibMmioBuffer.c @@ -0,0 +1,417 @@ +/** @file + I/O Library MMIO Buffer Functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h new file mode 100644 index 0000000..4f764c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmCpuIoLibInternal.h @@ -0,0 +1,118 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMM_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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf new file mode 100644 index 0000000..5cfd4e5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf @@ -0,0 +1,49 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni new file mode 100644 index 0000000..bc800c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c new file mode 100644 index 0000000..cf6730c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.c @@ -0,0 +1,103 @@ +/** @file + NULL instance of SMM Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf new file mode 100644 index 0000000..323e237 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.inf @@ -0,0 +1,37 @@ +## @file +# NULL instance of SMM Library. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni new file mode 100644 index 0000000..578342c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmLibNull/SmmLibNull.uni @@ -0,0 +1,21 @@ +// /** @file +// NULL instance of SMM Library. +// +// NULL instance of SMM Library. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c new file mode 100644 index 0000000..5b2fd8b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.c @@ -0,0 +1,658 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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 DesinationBuffer 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 DesinationBuffer 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf new file mode 100644 index 0000000..74a45bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.inf @@ -0,0 +1,62 @@ +## @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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni new file mode 100644 index 0000000..9a5e257 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemLib/SmmMemLib.uni @@ -0,0 +1,24 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 0000000..3e98817 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,982 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf new file mode 100644 index 0000000..1f443f7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf @@ -0,0 +1,50 @@ +## @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.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni new file mode 100644 index 0000000..75b26ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c new file mode 100644 index 0000000..befb6a4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c @@ -0,0 +1,1430 @@ +/** @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. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include + +/// +/// 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 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; + + // + // 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 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; + + // + // 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf new file mode 100644 index 0000000..b5e83b5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf @@ -0,0 +1,42 @@ +## @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. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c new file mode 100644 index 0000000..4717ff5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/PciLib.c @@ -0,0 +1,1434 @@ +/** @file + PCI Library using SMM PCI Root Bridge I/O Protocol. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include +#include +#include +#include +#include +#include + + +/** + 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_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 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf new file mode 100644 index 0000000..a4d25be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf @@ -0,0 +1,55 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni new file mode 100644 index 0000000..e2c5b9d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.uni @@ -0,0 +1,25 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c new file mode 100644 index 0000000..1b6db7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.c @@ -0,0 +1,1175 @@ +/** @file + SMM Periodic SMI Library. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/// +/// 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 PeriodcSmiExecutionTime(). This allows the + /// time value returned by PeriodcSmiExecutionTime() 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 transferd + /// 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 Disatch Protocol that was located in the constuctor. +/// +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 seperate 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 intial 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 occured 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 dispacthed. + // + PeriodicSmiLibraryHandler->DispatchFunction ( + PeriodicSmiLibraryHandler->Context, + PeriodicSmiLibraryHandler->ElapsedTime + ); + + // + // If this DispatchFunction() returns, then unconditially call PeriodicSmiExit() + // to perform a LongJump() back to PeriodicSmiDispatchFunctionOnCpu(). The + // LongJump() will resume exection on the original stack. + // + PeriodicSmiExit (); +} + +/** + Internal worker function that transfers control to an enabled periodic SMI + handler on the specified logial 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 intial 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 registerd 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 dispacthed. + // + PeriodicSmiLibraryHandler->DispatchFunction ( + PeriodicSmiLibraryHandler->Context, + PeriodicSmiLibraryHandler->ElapsedTime + ); + + // + // If this DispatchFunction() returns, then unconditially 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 logial 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 excuting 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_LIBARRY_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 givien 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 speficied 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 + // Dipatch 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf new file mode 100644 index 0000000..943588b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf @@ -0,0 +1,52 @@ +## @file +# SMM Periodic SMI Library. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni new file mode 100644 index 0000000..bc59e9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.uni @@ -0,0 +1,21 @@ +// /** @file +// SMM Periodic SMI Library. +// +// SMM Periodic SMI Library. +// +// Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c new file mode 100644 index 0000000..1ee4726 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.c @@ -0,0 +1,85 @@ +/** @file + SMM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +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 explicity 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf new file mode 100644 index 0000000..4a3d7dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf @@ -0,0 +1,45 @@ +## @file +# SMM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni new file mode 100644 index 0000000..935682d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.uni @@ -0,0 +1,21 @@ +// /** @file +// SMM Services Table Library. +// +// SMM Services Table Library. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c new file mode 100644 index 0000000..f745280 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c @@ -0,0 +1,87 @@ +/** @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.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf new file mode 100644 index 0000000..d88e13e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf @@ -0,0 +1,43 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni new file mode 100644 index 0000000..5896813 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c new file mode 100644 index 0000000..e7637db --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.c @@ -0,0 +1,41 @@ +/** @file + MM Services Table Library. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf new file mode 100644 index 0000000..8ef0882 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf @@ -0,0 +1,39 @@ +## @file +# Standalone MM Services Table Library. +# +# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni new file mode 100644 index 0000000..37efb93 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.uni @@ -0,0 +1,20 @@ +// /** @file +// +// Standalone MM Services Table Library. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c new file mode 100644 index 0000000..5618055 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c @@ -0,0 +1,121 @@ +/** @file + Entry point library instance to a UEFI application. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf new file mode 100644 index 0000000..8a03ef5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf @@ -0,0 +1,40 @@ +## @file +# Module entry point library for UEFI Application. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni new file mode 100644 index 0000000..f81c388 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.uni @@ -0,0 +1,21 @@ +// /** @file +// Module entry point library for UEFI Application. +// +// Module entry point library for UEFI Application. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c new file mode 100644 index 0000000..ebc9a4b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf new file mode 100644 index 0000000..f47b177 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf @@ -0,0 +1,40 @@ +## @file +# UEFI Boot Services Table Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni new file mode 100644 index 0000000..1c98829 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.uni @@ -0,0 +1,21 @@ +// /** @file +// UEFI Boot Services Table Library implementation. +// +// UEFI Boot Services Table Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c new file mode 100644 index 0000000..991e429 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/DebugLib.c @@ -0,0 +1,278 @@ +/** @file + UEFI Debug Library that sends messages to the Console Output Device in the EFI System Table. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +/** + 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, + ... + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // 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 + // + VA_START (Marker, Format); + UnicodeVSPrintAsciiFormat (Buffer, MAX_DEBUG_MESSAGE_LENGTH, Format, Marker); + VA_END (Marker); + + + // + // Send the print string to the Console Output device + // + if ((gST != NULL) && (gST->ConOut != NULL)) { + gST->ConOut->OutputString (gST->ConOut, Buffer); + } +} + + +/** + 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]; + + // + // 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 ((gST != NULL) && (gST->ConOut != NULL)) { + gST->ConOut->OutputString (gST->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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf new file mode 100644 index 0000000..c957f2f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf @@ -0,0 +1,54 @@ +## @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 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + DebugLib.c + + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + UefiBootServicesTableLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni new file mode 100644 index 0000000..34e6bcf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c new file mode 100644 index 0000000..a3b3f28 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c @@ -0,0 +1,331 @@ +/** @file + UEFI Debug Library that sends messages to EFI_DEBUGPORT_PROTOCOL.Write. + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// 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; + +/** + 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 mDebugPort is NULL, initialize first. + // + if (mDebugPort == NULL) { + Status = gBS->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, + ... + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // 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 + // + VA_START (Marker, Format); + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + // + // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write. + // + UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer)); +} + + +/** + 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 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf new file mode 100644 index 0000000..4775744 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf @@ -0,0 +1,57 @@ +## @file +# Instance of Debug Library using EFI_DEBUGPORT_PROTOCOL. +# +# Debug Lib that sends messages to EFI_DEBUGPORT_PROTOCOL.Write. +# +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + + +[Sources] + DebugLib.c + + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + UefiBootServicesTableLib + DebugPrintErrorLevelLib + +[Protocols] + gEfiDebugPortProtocolGuid ## CONSUMES + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni new file mode 100644 index 0000000..890f314 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c new file mode 100644 index 0000000..181f9da --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c @@ -0,0 +1,279 @@ +/** @file + UEFI Debug Lib that sends messages to the Standard Error Device in the EFI System Table. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + + +/** + 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, + ... + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // 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 + // + VA_START (Marker, Format); + UnicodeVSPrintAsciiFormat (Buffer, MAX_DEBUG_MESSAGE_LENGTH, Format, Marker); + VA_END (Marker); + + // + // Send the print string to the Standard Error device + // + if ((gST != NULL) && (gST->StdErr != NULL)) { + gST->StdErr->OutputString (gST->StdErr, Buffer); + } +} + + +/** + 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]; + + // + // 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 ((gST != NULL) && (gST->StdErr != NULL)) { + gST->StdErr->OutputString (gST->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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf new file mode 100644 index 0000000..6b34baf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf @@ -0,0 +1,52 @@ +## @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 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + DebugLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseMemoryLib + BaseLib + PcdLib + PrintLib + UefiBootServicesTableLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni new file mode 100644 index 0000000..50f217a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c new file mode 100644 index 0000000..56905e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathFromText.c @@ -0,0 +1,3672 @@ +/** @file + DevicePathFromText protocol as defined in the UEFI 2.0 specification. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c new file mode 100644 index 0000000..3be5e53 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c @@ -0,0 +1,2461 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c new file mode 100644 index 0000000..a70865f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c @@ -0,0 +1,903 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c new file mode 100644 index 0000000..369733e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c @@ -0,0 +1,360 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h new file mode 100644 index 0000000..d9dc09b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.h @@ -0,0 +1,457 @@ +/** @file + Definition for Device Path library. + +Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf new file mode 100644 index 0000000..71b1dbb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf @@ -0,0 +1,79 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni new file mode 100644 index 0000000..9ea680d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c new file mode 100644 index 0000000..8ba8ed9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.c @@ -0,0 +1,484 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf new file mode 100644 index 0000000..521f6ca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf @@ -0,0 +1,89 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni new file mode 100644 index 0000000..3a42133 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c new file mode 100644 index 0000000..b79c863 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c @@ -0,0 +1,871 @@ +/** @file + Library instance that implement UEFI Device Path Library class based on protocol + gEfiDevicePathUtilitiesProtocolGuid. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf new file mode 100644 index 0000000..3b285f7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf @@ -0,0 +1,61 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni new file mode 100644 index 0000000..6f78e46 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c new file mode 100644 index 0000000..47f1e0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c @@ -0,0 +1,173 @@ +/** @file + Entry point to a EFI/DXE driver. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +#include + +#include + +#include +#include +#include +#include + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf new file mode 100644 index 0000000..e0fd421 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf @@ -0,0 +1,67 @@ +## @file +# Module entry point library for UEFI driver, DXE driver and SMM driver. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni new file mode 100644 index 0000000..3cbbde4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.uni @@ -0,0 +1,21 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c new file mode 100644 index 0000000..d94e820 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c @@ -0,0 +1,1272 @@ +/** @file + Provides interface to EFI_FILE_HANDLE functionality. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +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); + // + // 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) && (FileInfo != NULL)) { + 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 { + // + // We got info... do we have a name? if yes precede the current path with it... + // + if (StrLen (FileInfo->FileName) == 0) { + 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); + } + } + // + // Move to the parent directory + // + Status = CurrentHandle->Open (CurrentHandle, &NextHigherHandle, L"..", EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + break; + } + + FileHandleClose(CurrentHandle); + 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; + 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){ + *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16); + if (!Truncate) { + if (Buffer != NULL && *Size != 0) { + ZeroMem(Buffer, *Size); + } + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf new file mode 100644 index 0000000..ff6bb08 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf @@ -0,0 +1,48 @@ +## @file +# Provides interface to shell functionality for shell commands and applications. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +## + +[Defines] + INF_VERSION = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni new file mode 100644 index 0000000..23eca00 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.uni @@ -0,0 +1,26 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Acpi.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Acpi.c new file mode 100644 index 0000000..f94c451 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Acpi.c @@ -0,0 +1,428 @@ +/** @file + This module provides help function for finding ACPI table. + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Console.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Console.c new file mode 100644 index 0000000..cf443dd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/Console.c @@ -0,0 +1,572 @@ +/** @file + This module provide help function for displaying unicode string. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c new file mode 100644 index 0000000..8e7d933 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiDriverModel.c @@ -0,0 +1,2026 @@ +/** @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.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.c new file mode 100644 index 0000000..7296846 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.c @@ -0,0 +1,2001 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#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 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; + while (*SupportedLanguages != 0) { + if (Iso639Language) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + Found = TRUE; + break; + } + SupportedLanguages += 3; + } else { + for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); + if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) { + Found = TRUE; + break; + } + SupportedLanguages += Index; + for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); + } + } + + // + // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED + // + if (!Found) { + return EFI_UNSUPPORTED; + } + + // + // 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; + while (*SupportedLanguages != 0) { + if (Iso639Language) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + Found = TRUE; + break; + } + SupportedLanguages += 3; + } else { + for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++); + if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) { + Found = TRUE; + break; + } + SupportedLanguages += Index; + for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++); + } + } + + // + // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED + // + if (!Found) { + return EFI_UNSUPPORTED; + } + + // + // 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.inf new file mode 100644 index 0000000..b40c8cf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.inf @@ -0,0 +1,93 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.uni new file mode 100644 index 0000000..d8bf83e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLib.uni @@ -0,0 +1,25 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h new file mode 100644 index 0000000..4a3145c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibInternal.h @@ -0,0 +1,44 @@ +/** @file + Internal include file for UefiLib. + + Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c new file mode 100644 index 0000000..d93686b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiLibPrint.c @@ -0,0 +1,822 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c new file mode 100644 index 0000000..f992739 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiLib/UefiNotTiano.c @@ -0,0 +1,336 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 0000000..c2621c5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,821 @@ +/** @file + Support routines for memory allocation routines based + on boot services for Dxe phase drivers. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf new file mode 100644 index 0000000..a8c283b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf @@ -0,0 +1,42 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni new file mode 100644 index 0000000..b97ef82 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c new file mode 100644 index 0000000..a80ea43 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CompareMemWrapper.c @@ -0,0 +1,66 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c new file mode 100644 index 0000000..1a01fbe --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/CopyMemWrapper.c @@ -0,0 +1,63 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c new file mode 100644 index 0000000..078c924 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/IsZeroBufferWrapper.c @@ -0,0 +1,54 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c new file mode 100644 index 0000000..84b853e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLib.c @@ -0,0 +1,63 @@ +/** @file + Base Memory Library functions implementation bases on Uefi Boot Service. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c new file mode 100644 index 0000000..e493046 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c @@ -0,0 +1,289 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c new file mode 100644 index 0000000..28b08c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibGuid.c @@ -0,0 +1,171 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h new file mode 100644 index 0000000..9aab2c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/MemLibInternals.h @@ -0,0 +1,249 @@ +/** @file + Declaration of internal functions for Base Memory Library. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c new file mode 100644 index 0000000..7b37607 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem16Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c new file mode 100644 index 0000000..654306a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem32Wrapper.c @@ -0,0 +1,66 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c new file mode 100644 index 0000000..9606caa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem64Wrapper.c @@ -0,0 +1,67 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c new file mode 100644 index 0000000..6d974d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ScanMem8Wrapper.c @@ -0,0 +1,99 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c new file mode 100644 index 0000000..7001f29 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem16Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c new file mode 100644 index 0000000..c51b846 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem32Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c new file mode 100644 index 0000000..f412897 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMem64Wrapper.c @@ -0,0 +1,64 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c new file mode 100644 index 0000000..65b8606 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/SetMemWrapper.c @@ -0,0 +1,91 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf new file mode 100644 index 0000000..58a484c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf @@ -0,0 +1,60 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni new file mode 100644 index 0000000..8eb667a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c new file mode 100644 index 0000000..d768dd1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiMemoryLib/ZeroMemWrapper.c @@ -0,0 +1,56 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c new file mode 100644 index 0000000..a97b4b9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/PciLib.c @@ -0,0 +1,1434 @@ +/** @file + PCI Library using PCI Root Bridge I/O Protocol. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf new file mode 100644 index 0000000..4d13837 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf @@ -0,0 +1,57 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni new file mode 100644 index 0000000..b5498a8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.uni @@ -0,0 +1,25 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c new file mode 100644 index 0000000..1bd4589 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.c @@ -0,0 +1,1491 @@ +/** @file + PCI Segment Library implementation using PCI Root Bridge I/O Protocol. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h new file mode 100644 index 0000000..2ed4e79 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/PciSegmentLib.h @@ -0,0 +1,58 @@ +/** @file + Include file of PciSegmentPciRootBridgeIo Library. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf new file mode 100644 index 0000000..733f2dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf @@ -0,0 +1,60 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni new file mode 100644 index 0000000..dc4a06a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.uni @@ -0,0 +1,25 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c new file mode 100644 index 0000000..c840e46 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/RuntimeLib.c @@ -0,0 +1,843 @@ +/** @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.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include + +/// +/// 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->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + RuntimeLibVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mEfiVirtualNotifyEvent + ); + + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + RuntimeLibExitBootServicesEvent, + NULL, + &gEfiEventExitBootServicesGuid, + &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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf new file mode 100644 index 0000000..b89e1cc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf @@ -0,0 +1,51 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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 + +[Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni new file mode 100644 index 0000000..7220ae6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.uni @@ -0,0 +1,23 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c new file mode 100644 index 0000000..72b631d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c @@ -0,0 +1,49 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf new file mode 100644 index 0000000..a8a7db0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf @@ -0,0 +1,41 @@ +## @file +# UEFI Runtime Services Table Library implementation. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni new file mode 100644 index 0000000..9f045be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.uni @@ -0,0 +1,21 @@ +// /** @file +// UEFI Runtime Services Table Library implementation. +// +// UEFI Runtime Services Table Library implementation. +// +// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c new file mode 100644 index 0000000..cf9d94c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.c @@ -0,0 +1,2067 @@ +/** @file + UEFI SCSI Library implementation + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include +#include +#include +#include +#include + +#include + + + // + // Scsi Command Length + // +#define EFI_SCSI_OP_LENGTH_SIX 0x6 +#define EFI_SCSI_OP_LENGTH_TEN 0xa +#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; + 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; + 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; +} + + +/** + 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf new file mode 100644 index 0000000..7ae36c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.inf @@ -0,0 +1,47 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni new file mode 100644 index 0000000..67644ce --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiScsiLib/UefiScsiLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/Hid.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/Hid.c new file mode 100644 index 0000000..1e2658e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/Hid.c @@ -0,0 +1,488 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf new file mode 100644 index 0000000..2a615d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf @@ -0,0 +1,48 @@ +## @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.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = 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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni new file mode 100644 index 0000000..1a86975 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLib.uni @@ -0,0 +1,22 @@ +// /** @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.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#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/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h new file mode 100644 index 0000000..3857fb6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h @@ -0,0 +1,29 @@ +/** @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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _UEFI_USB_LIB_INTERNAL_H_ +#define _UEFI_USB_LIB_INTERNAL_H_ + +#include + +#include +#include +#include +#include + +#include + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c new file mode 100644 index 0000000..93f6ecc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/Library/UefiUsbLib/UsbDxeLib.c @@ -0,0 +1,672 @@ +/** @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.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of + the BSD License which accompanies this distribution. The full + text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dec b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dec new file mode 100644 index 0000000..d5fd2f1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dec @@ -0,0 +1,2307 @@ +## @file MdePkg.dec +# This Package provides all definitions, library classes and libraries instances. +# +# It also provides the definitions(including PPIs/PROTOCOLs/GUIDs) of +# EFI1.10/UEFI2.7/PI1.7 and some Industry Standards. +# +# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = MdePkg + PACKAGE_UNI_FILE = MdePkg.uni + PACKAGE_GUID = 1E73767F-8F52-4603-AEB4-F29B510B6766 + PACKAGE_VERSION = 1.08 + + +[Includes] + Include + +[Includes.IA32] + Include/Ia32 + +[Includes.X64] + Include/X64 + +[Includes.EBC] + Include/Ebc + +[Includes.ARM] + Include/Arm + +[Includes.AARCH64] + Include/AArch64 + +[LibraryClasses] + ## @libraryclass 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. + ## + UefiUsbLib|Include/Library/UefiUsbLib.h + + ## @libraryclass Provides a service to retrieve a pointer to the EFI Runtime Services Table. + # Only available to DXE and UEFI module types. + UefiRuntimeServicesTableLib|Include/Library/UefiRuntimeServicesTableLib.h + + ## @libraryclass Provides library functions for each of the UEFI Runtime Services. + # Only available to DXE and UEFI module types. + UefiRuntimeLib|Include/Library/UefiRuntimeLib.h + + ## @libraryclass Provides library functions for common UEFI operations. + # Only available to DXE and UEFI module types. + ## + UefiLib|Include/Library/UefiLib.h + + ## @libraryclass Module entry point library for UEFI drivers, DXE Drivers, DXE SMM Driver and DXE Runtime Drivers + UefiDriverEntryPoint|Include/Library/UefiDriverEntryPoint.h + + ## @libraryclass UEFI Decompress Library Functions defintion for UEFI compress algorithm. + UefiDecompressLib|Include/Library/UefiDecompressLib.h + + ## @libraryclass Provides a service to retrieve a pointer to the EFI Boot Services Table. + # Only available to DXE and UEFI module types. + UefiBootServicesTableLib|Include/Library/UefiBootServicesTableLib.h + + ## @libraryclass Module entry point library for UEFI Applications. + UefiApplicationEntryPoint|Include/Library/UefiApplicationEntryPoint.h + + ## @libraryclass Provides calibrated delay and performance counter services. + TimerLib|Include/Library/TimerLib.h + + ## @libraryclass Provides library functions to access SMBUS devices. + # Libraries of this class must be ported to a specific SMBUS controller. + SmbusLib|Include/Library/SmbusLib.h + + ## @libraryclass Provides the functions to submit Scsi commands defined in SCSI-2 specification for scsi device. + UefiScsiLib|Include/Library/UefiScsiLib.h + + ## @libraryclass Provides a service to publish discovered system resources. + ResourcePublicationLib|Include/Library/ResourcePublicationLib.h + + ## @libraryclass Provides services to log status code records. + ReportStatusCodeLib|Include/Library/ReportStatusCodeLib.h + + ## @libraryclass Provides services to print a formatted string to a buffer. + # All combinations of Unicode and ASCII strings are supported. + ## + PrintLib|Include/Library/PrintLib.h + + ## @libraryclass Provides an ordered collection data structure. + OrderedCollectionLib|Include/Library/OrderedCollectionLib.h + + ## @libraryclass Provides services to send progress/error codes to a POST card. + PostCodeLib|Include/Library/PostCodeLib.h + + ## @libraryclass Provides services to log the execution times and retrieve them later. + PerformanceLib|Include/Library/PerformanceLib.h + + ## @libraryclass Provides a service to retrieve a pointer to the PEI Services Table. + PeiServicesTablePointerLib|Include/Library/PeiServicesTablePointerLib.h + + ## @libraryclass Provides library functions for all PEI Services. + PeiServicesLib|Include/Library/PeiServicesLib.h + + ## @libraryclass Module entry point library for PEIM. + PeimEntryPoint|Include/Library/PeimEntryPoint.h + + ## @libraryclass Module entry point library for PEI core. + PeiCoreEntryPoint|Include/Library/PeiCoreEntryPoint.h + + ## @libraryclass Provides services to load and relocate a PE/COFF image. + PeCoffLib|Include/Library/PeCoffLib.h + ## @libraryclass Provides extra action services for unloading and relocating a PE/COFF image on some specific platform such + ## as NT32 emulator. + PeCoffExtraActionLib|Include/Library/PeCoffExtraActionLib.h + + ## @libraryclass Provides a service to retrieve the PE/COFF entry point from a PE/COFF image. + PeCoffGetEntryPointLib|Include/Library/PeCoffGetEntryPointLib.h + + ## @libraryclass Provides services to return the PCI segment information. + PciSegmentInfoLib|Include/Library/PciSegmentInfoLib.h + + ## @libraryclass Provides services to access PCI Configuration Space on a platform with multiple PCI segments. + PciSegmentLib|Include/Library/PciSegmentLib.h + + ## @libraryclass 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. + S3PciSegmentLib|Include/Library/PciSegmentLib.h + + ## @libraryclass Provides services to access PCI Configuration Space. + PciLib|Include/Library/PciLib.h + + ## @libraryclass Provides services to access PCI Configuration Space using the MMIO PCI Express window. + PciExpressLib|Include/Library/PciExpressLib.h + + ## @libraryclass Provides services to access PCI Configuration Space using the I/O ports 0xCF8 and 0xCFC. + PciCf8Lib|Include/Library/PciCf8Lib.h + + ## @libraryclass Provides library services to get and set Platform Configuration Database entries. + PcdLib|Include/Library/PcdLib.h + + ## @libraryclass Provides services to allocate and free memory buffers of various memory types and alignments. + MemoryAllocationLib|Include/Library/MemoryAllocationLib.h + + ## @libraryclass Provide services to access I/O Ports and MMIO registers. + IoLib|Include/Library/IoLib.h + + ## @libraryclass Provide services to create, get and update HSTI table in AIP protocol. + HstiLib|Include/Library/HstiLib.h + + ## @libraryclass Provides services to create and parse HOBs. Only available for PEI and DXE module types. + HobLib|Include/Library/HobLib.h + + ## @libraryclass Provides a service to retrieve a pointer to the DXE Services Table. + # Only available to DXE module types. + ## + DxeServicesTableLib|Include/Library/DxeServicesTableLib.h + + ## @libraryclass Module entry point library for DXE core. + DxeCoreEntryPoint|Include/Library/DxeCoreEntryPoint.h + + ## @libraryclass Provides library functions to construct and parse UEFI Device Paths. + DevicePathLib|Include/Library/DevicePathLib.h + + ## @libraryclass Provides services to print debug and assert messages to a debug output device. + DebugLib|Include/Library/DebugLib.h + + ## @libraryclass Provides CPU architecture specific functions that can not be defined in the Base Library + # due to dependencies on the PAL Library + ## + CpuLib|Include/Library/CpuLib.h + + ## @libraryclass Provides services to maintain instruction and data caches. + CacheMaintenanceLib|Include/Library/CacheMaintenanceLib.h + + ## @libraryclass Provides copy memory, fill memory, zero memory, and GUID functions. + BaseMemoryLib|Include/Library/BaseMemoryLib.h + + ## @libraryclass Provides string functions, linked list functions, math functions, synchronization functions + # and CPU architecture specific functions. + ## + BaseLib|Include/Library/BaseLib.h + + ## @libraryclass This library provides common functions to process the different guided section data. + ExtractGuidedSectionLib|Include/Library/ExtractGuidedSectionLib.h + + ## @libraryclass Provides three common serial I/O port functions. + SerialPortLib|Include/Library/SerialPortLib.h + + ## @libraryclass Provides a set of PI library functions and macros for DXE phase. + DxeServicesLib|Include/Library/DxeServicesLib.h + + ## @libraryclass Provides synchronization functions. + ## + SynchronizationLib|Include/Library/SynchronizationLib.h + + ## @libraryclass Defines library APIs used by modules to save S3 Boot + # Script Opcodes. These OpCode will be restored by S3 + # related modules. + S3BootScriptLib|Include/Library/S3BootScriptLib.h + + ## @libraryclass I/O and MMIO Library Services that do I/O and also enable + # the I/O operatation to be replayed during an S3 resume. + # This library class maps directly on top of the IoLib class. + S3IoLib|Include/Library/S3IoLib.h + + ## @libraryclass 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. + S3PciLib|Include/Library/S3PciLib.h + + ## @libraryclass 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. + S3SmbusLib|Include/Library/S3SmbusLib.h + + ## @libraryclass 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. + S3StallLib|Include/Library/S3StallLib.h + + ## @libraryclass Defines library APIs used by modules to get/set print error level. + DebugPrintErrorLevelLib|Include/Library/DebugPrintErrorLevelLib.h + + ## @libraryclass provides EFI_FILE_HANDLE services + FileHandleLib|Include/Library/FileHandleLib.h + + ## @libraryclass provides helper functions to prevent integer overflow during + # type conversion, addition, subtraction, and multiplication. + ## + SafeIntLib|Include/Library/SafeIntLib.h + + ## @libraryclass Provides a service to retrieve a pointer to the Standalone MM Services Table. + # Only available to MM_STANDALONE, SMM/DXE Combined and SMM module types. + MmServicesTableLib|Include/Library/MmServicesTableLib.h + + ## @libraryclass Module entry point library for standalone MM drivers. + StandaloneMmDriverEntryPoint|Include/Library/StandaloneMmDriverEntryPoint.h + +[LibraryClasses.IA32, LibraryClasses.X64] + ## @libraryclass Abstracts both S/W SMI generation and detection. + ## + SmmLib|Include/Library/SmmLib.h + + ## @libraryclass Provides a service to retrieve a pointer to the SMM Services Table. + # Only available to SMM/DXE Combined and SMM module types. + SmmServicesTableLib|Include/Library/SmmServicesTableLib.h + + ## @libraryclass Provides services for Smm Memory Operation. + # + SmmMemLib|Include/Library/SmmMemLib.h + + ## @libraryclass Provides services for Smm IO Operation. + # + SmmIoLib|Include/Library/SmmIoLib.h + + ## @libraryclass Provides services to enable/disable periodic SMI handlers. + # + SmmPeriodicSmiLib|Include/Library/SmmPeriodicSmiLib.h + + ## @libraryclass Provides services to generate random number. + # + RngLib|Include/Library/RngLib.h + + ## @libraryclass Provides services to log the SMI handler registration. + SmiHandlerProfileLib|Include/Library/SmiHandlerProfileLib.h + +[Guids] + # + # GUID defined in UEFI2.1/UEFI2.0/EFI1.1 + # + ## Include/Guid/GlobalVariable.h + gEfiGlobalVariableGuid = { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }} + + ## Include/Guid/PcAnsi.h + gEfiVT100PlusGuid = { 0x7BAEC70B, 0x57E0, 0x4C76, { 0x8E, 0x87, 0x2F, 0x9E, 0x28, 0x08, 0x83, 0x43 }} + + ## Include/Guid/PcAnsi.h + gEfiVT100Guid = { 0xDFA66065, 0xB419, 0x11D3, { 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/PcAnsi.h + gEfiPcAnsiGuid = { 0xE0C14753, 0xF9BE, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/PcAnsi.h + gEfiVTUTF8Guid = { 0xAD15A0D6, 0x8BEC, 0x4ACF, { 0xA0, 0x73, 0xD0, 0x1D, 0xE7, 0x7E, 0x2D, 0x88 }} + + ## Include/Guid/PcAnsi.h + gEfiUartDevicePathGuid = { 0x37499a9d, 0x542f, 0x4c89, { 0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 }} + + ## Include/Guid/PcAnsi.h + gEfiSasDevicePathGuid = { 0xd487ddb4, 0x008b, 0x11d9, { 0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d }} + + ## Include/Guid/Gpt.h + gEfiPartTypeLegacyMbrGuid = { 0x024DEE41, 0x33E7, 0x11D3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }} + + ## Include/Guid/Gpt.h + gEfiPartTypeSystemPartGuid = { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }} + + ## Include/Guid/Gpt.h + gEfiPartTypeUnusedGuid = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }} + + ## Include/Guid/DebugImageInfoTable.h + gEfiDebugImageInfoTableGuid = { 0x49152E77, 0x1ADA, 0x4764, { 0xB7, 0xA2, 0x7A, 0xFE, 0xFE, 0xD9, 0x5E, 0x8B }} + + ## Include/Guid/Acpi.h + gEfiAcpiTableGuid = { 0x8868E871, 0xE4F1, 0x11D3, { 0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Guid/Acpi.h + gEfiAcpi20TableGuid = { 0x8868E871, 0xE4F1, 0x11D3, { 0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Guid/Acpi.h + gEfiAcpi10TableGuid = { 0xEB9D2D30, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/SmBios.h + gEfiSmbiosTableGuid = { 0xEB9D2D31, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/Mps.h + gEfiMpsTableGuid = { 0xEB9D2D2F, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/SalSystemTable.h + gEfiSalSystemTableGuid = { 0xEB9D2D32, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/AuthenticationInfo.h + gEfiAuthenticationChapLocalGuid = { 0xC280C73E, 0x15CA, 0x11DA, { 0xB0, 0xCA, 0x00, 0x10, 0x83, 0xFF, 0xCA, 0x4D }} + + ## Include/Protocol/AuthenticationInfo.h + gEfiAuthenticationChapRadiusGuid = { 0xD6062B50, 0x15CA, 0x11DA, { 0x92, 0x19, 0x00, 0x10, 0x83, 0xFF, 0xCA, 0x4D }} + + ## Include/Guid/FileSystemVolumeLabelInfo.h + gEfiFileSystemVolumeLabelInfoIdGuid = { 0xDB47D7D3, 0xFE81, 0x11D3, { 0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/FileSystemInfo.h + gEfiFileSystemInfoGuid = { 0x09576E93, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Guid/FileInfo.h + gEfiFileInfoGuid = { 0x09576E92, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/Bis.h + gBootObjectAuthorizationParmsetGuid = { 0xEDD35E31, 0x07B9, 0x11D2, { 0x83, 0xA3, 0x00, 0xA0, 0xC9, 0x1F, 0xAD, 0xCF }} + + ## Include/Protocol/PlatformToDriverConfiguration.h + gEfiPlatformToDriverConfigurationClpGuid = { 0x345ecc0e, 0xcb6, 0x4b75, { 0xbb, 0x57, 0x1b, 0x12, 0x9c, 0x47, 0x33,0x3e }} + + ## Include/Guid/HiiKeyBoardLayout.h + gEfiHiiKeyBoardLayoutGuid = { 0x14982a4f, 0xb0ed, 0x45b8, { 0xa8, 0x11, 0x5a, 0x7a, 0x9b, 0xc2, 0x32, 0xdf }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmMD5Guid = { 0x0AF7C79C, 0x65B5, 0x4319, { 0xB0, 0xAE, 0x44, 0xEC, 0x48, 0x4E, 0x4A, 0xD7 }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmSha512Guid = { 0xCAA4381E, 0x750C, 0x4770, { 0xB8, 0x70, 0x7A, 0x23, 0xB4, 0xE4, 0x21, 0x30 }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmSha384Guid = { 0xEFA96432, 0xDE33, 0x4DD2, { 0xAE, 0xE6, 0x32, 0x8C, 0x33, 0xDF, 0x77, 0x7A }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmSha256Guid = { 0x51AA59DE, 0xFDF2, 0x4EA3, { 0xBC, 0x63, 0x87, 0x5F, 0xB7, 0x84, 0x2E, 0xE9 }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmSha224Guid = { 0x8DF01A06, 0x9BD5, 0x4BF7, { 0xB0, 0x21, 0xDB, 0x4F, 0xD9, 0xCC, 0xF4, 0x5B }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmSha1Guid = { 0x2AE9D80F, 0x3FB2, 0x4095, { 0xB7, 0xB1, 0xE9, 0x31, 0x57, 0xB9, 0x46, 0xB6 }} + + ## Include/Guid/EventGroup.h + gEfiEventReadyToBootGuid = { 0x7CE88FB3, 0x4BD7, 0x4679, { 0x87, 0xA8, 0xA8, 0xD8, 0xDE, 0xE5, 0x0D, 0x2B }} + + ## Include/Guid/EventGroup.h + gEfiEventMemoryMapChangeGuid = { 0x78BEE926, 0x692F, 0x48FD, { 0x9E, 0xDB, 0x01, 0x42, 0x2E, 0xF0, 0xD7, 0xAB }} + + ## Include/Guid/EventGroup.h + gEfiEventVirtualAddressChangeGuid = { 0x13FA7698, 0xC831, 0x49C7, { 0x87, 0xEA, 0x8F, 0x43, 0xFC, 0xC2, 0x51, 0x96 }} + + ## Include/Guid/EventGroup.h + gEfiEventExitBootServicesGuid = { 0x27ABF055, 0xB1B8, 0x4C26, { 0x80, 0x48, 0x74, 0x8F, 0x37, 0xBA, 0xA2, 0xDF }} + + ## Include/Protocol/DebugPort.h + gEfiDebugPortVariableGuid = { 0xEBA4E8D2, 0x3858, 0x41EC, { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 }} + + ## Include/Protocol/DebugPort.h + gEfiDebugPortDevicePathGuid = { 0xEBA4E8D2, 0x3858, 0x41EC, { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 }} + + ## Include/Guid/HiiPlatformSetupFormset.h + gEfiHiiPlatformSetupFormsetGuid = { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x04, 0x0e }} + + ## Include/Guid/HiiPlatformSetupFormset.h + gEfiHiiDriverHealthFormsetGuid = { 0xf22fc20c, 0x8cf4, 0x45eb, { 0x8e, 0x6, 0xad, 0x4e, 0x50, 0xb9, 0x5d, 0xd3 }} + + ## Include/Guid/HiiPlatformSetupFormset.h + gEfiHiiUserCredentialFormsetGuid = { 0x337f4407, 0x5aee, 0x4b83, { 0xb2, 0xa7, 0x4e, 0xad, 0xca, 0x30, 0x88, 0xcd }} + + ## Include/Guid/HiiFormMapMethodGuid.h + gEfiHiiStandardFormGuid = { 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 }} + + ## Include/Guid/MemoryOverwriteControl.h + gEfiMemoryOverwriteControlDataGuid = { 0xe20939be, 0x32d4, 0x41be, {0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29 }} + + ## Include/IndustryStandard/MemoryOverwriteRequestControlLock.h + gEfiMemoryOverwriteRequestControlLockGuid = { 0xBB983CCF, 0x151D, 0x40E1, {0xA0, 0x7B, 0x4A, 0x17, 0xBE, 0x16, 0x82, 0x92}} + + ## Include/Guid/WinCertificate.h + gEfiCertTypeRsa2048Sha256Guid = { 0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeCmcGuid = { 0x2DCE8BB1, 0xBDD7, 0x450e, { 0xB9, 0xAD, 0x9C, 0xF4, 0xEB, 0xD4, 0xF8, 0x90 }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeCpeGuid = { 0x4E292F96, 0xD843, 0x4a55, { 0xA8, 0xC2, 0xD4, 0x81, 0xF2, 0x7E, 0xBE, 0xEE }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeMceGuid = { 0xE8F56FFE, 0x919C, 0x4cc5, { 0xBA, 0x88, 0x65, 0xAB, 0xE1, 0x49, 0x13, 0xBB }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypePcieGuid = { 0xCF93C01F, 0x1A16, 0x4dfc, { 0xB8, 0xBC, 0x9C, 0x4D, 0xAF, 0x67, 0xC1, 0x04 }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeInitGuid = { 0xCC5263E8, 0x9308, 0x454a, { 0x89, 0xD0, 0x34, 0x0B, 0xD3, 0x9B, 0xC9, 0x8E }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeNmiGuid = { 0x5BAD89FF, 0xB7E6, 0x42c9, { 0x81, 0x4A, 0xCF, 0x24, 0x85, 0xD6, 0xE9, 0x8A }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeBootGuid = { 0x3D61A466, 0xAB40, 0x409a, { 0xA6, 0x98, 0xF3, 0x62, 0xD4, 0x64, 0xB3, 0x8F }} + + ## Include/Guid/Cper.h + gEfiEventNotificationTypeDmarGuid = { 0x667DD791, 0xC6B3, 0x4c27, { 0x8A, 0x6B, 0x0F, 0x8E, 0x72, 0x2D, 0xEB, 0x41 }} + + ## Include/Guid/Cper.h + gEfiProcessorGenericErrorSectionGuid = { 0x9876ccad, 0x47b4, 0x4bdb, { 0xb6, 0x5e, 0x16, 0xf1, 0x93, 0xc4, 0xf3, 0xdb }} + + ## Include/Guid/Cper.h + gEfiProcessorSpecificErrorSectionGuid = { 0xdc3ea0b0, 0xa144, 0x4797, { 0xb9, 0x5b, 0x53, 0xfa, 0x24, 0x2b, 0x6e, 0x1d }} + + ## Include/Guid/Cper.h + gEfiIa32X64ProcessorErrorSectionGuid = { 0xdc3ea0b0, 0xa144, 0x4797, { 0xb9, 0x5b, 0x53, 0xfa, 0x24, 0x2b, 0x6e, 0x1d }} + + ## Include/Guid/Cper.h + gEfiPlatformMemoryErrorSectionGuid = { 0xa5bc1114, 0x6f64, 0x4ede, { 0xb8, 0x63, 0x3e, 0x83, 0xed, 0x7c, 0x83, 0xb1 }} + + ## Include/Guid/Cper.h + gEfiPcieErrorSectionGuid = { 0xd995e954, 0xbbc1, 0x430f, { 0xad, 0x91, 0xb4, 0x4d, 0xcb, 0x3c, 0x6f, 0x35 }} + + ## Include/Guid/Cper.h + gEfiFirmwareErrorSectionGuid = { 0x81212a96, 0x09ed, 0x4996, { 0x94, 0x71, 0x8d, 0x72, 0x9c, 0x8e, 0x69, 0xed }} + + ## Include/Guid/Cper.h + gEfiPciBusErrorSectionGuid = { 0xc5753963, 0x3b84, 0x4095, { 0xbf, 0x78, 0xed, 0xda, 0xd3, 0xf9, 0xc9, 0xdd }} + + ## Include/Guid/Cper.h + gEfiPciDevErrorSectionGuid = { 0xeb5e4685, 0xca66, 0x4769, { 0xb6, 0xa2, 0x26, 0x06, 0x8b, 0x00, 0x13, 0x26 }} + + ## Include/Guid/Cper.h + gEfiDMArGenericErrorSectionGuid = { 0x5b51fef7, 0xc79d, 0x4434, { 0x8f, 0x1b, 0xaa, 0x62, 0xde, 0x3e, 0x2c, 0x64 }} + + ## Include/Guid/Cper.h + gEfiDirectedIoDMArErrorSectionGuid = { 0x71761d37, 0x32b2, 0x45cd, { 0xa7, 0xd0, 0xb0, 0xfe, 0xdd, 0x93, 0xe8, 0xcf }} + + ## Include/Guid/Cper.h + gEfiIommuDMArErrorSectionGuid = { 0x036f84e1, 0x7f37, 0x428c, { 0xa7, 0x9e, 0x57, 0x5f, 0xdf, 0xaa, 0x84, 0xec }} + + # + # GUID defined in UEFI2.2 + # + ## Include/Protocol/UserManager.h + gEfiEventUserProfileChangedGuid = { 0xbaf1e6de, 0x209e, 0x4adb, {0x8d, 0x96, 0xfd, 0x8b, 0x71, 0xf3, 0xf6, 0x83 }} + + ## Include/Protocol/UserManager.h + gEfiUserCredentialClassUnknownGuid = { 0x5cf32e68, 0x7660, 0x449b, { 0x80, 0xe6, 0x7e, 0xa3, 0x6e, 0x3, 0xf6, 0xa8 }} + + ## Include/Protocol/UserManager.h + gEfiUserCredentialClassPasswordGuid = { 0xf8e5058c, 0xccb6, 0x4714, { 0xb2, 0x20, 0x3f, 0x7e, 0x3a, 0x64, 0xb, 0xd1 }} + + ## Include/Protocol/UserManager.h + gEfiUserCredentialClassSmartCardGuid = { 0x5f03ba33, 0x8c6b, 0x4c24, { 0xaa, 0x2e, 0x14, 0xa2, 0x65, 0x7b, 0xd4, 0x54 }} + + ## Include/Protocol/UserManager.h + gEfiUserCredentialClassFingerprintGuid = { 0x32cba21f, 0xf308, 0x4cbc, { 0x9a, 0xb5, 0xf5, 0xa3, 0x69, 0x9f, 0x4, 0x4a }} + + ## Include/Protocol/UserManager.h + gEfiUserCredentialClassHandprintGuid = { 0x5917ef16, 0xf723, 0x4bb9, { 0xa6, 0x4b, 0xd8, 0xc5, 0x32, 0xf4, 0xd8, 0xb5 }} + + ## Include/Protocol/UserManager.h + gEfiUserCredentialClassSecureCardGuid = { 0x8a6b4a83, 0x42fe, 0x45d2, { 0xa2, 0xef, 0x46, 0xf0, 0x6c, 0x7d, 0x98, 0x52 }} + + ## Include/Protocol/UserManager.h + gEfiUserInfoAccessSetupAdminGuid = { 0x85b75607, 0xf7ce, 0x471e, { 0xb7, 0xe4, 0x2a, 0xea, 0x5f, 0x72, 0x32, 0xee }} + + ## Include/Protocol/UserManager.h + gEfiUserInfoAccessSetupNormalGuid = { 0x1db29ae0, 0x9dcb, 0x43bc, { 0x8d, 0x87, 0x5d, 0xa1, 0x49, 0x64, 0xdd, 0xe2 }} + + ## Include/Protocol/UserManager.h + gEfiUserInfoAccessSetupRestrictedGuid = { 0xbdb38125, 0x4d63, 0x49f4, { 0x82, 0x12, 0x61, 0xcf, 0x5a, 0x19, 0xa, 0xf8 }} + + ## Include/Guid/ImageAuthentication.h + gEfiImageSecurityDatabaseGuid = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }} + gEfiCertSha256Guid = { 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 }} + gEfiCertRsa2048Guid = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6 }} + gEfiCertRsa2048Sha256Guid = { 0xe2b36190, 0x879b, 0x4a3d, {0xad, 0x8d, 0xf2, 0xe7, 0xbb, 0xa3, 0x27, 0x84 }} + gEfiCertSha1Guid = { 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd }} + gEfiCertRsa2048Sha1Guid = { 0x67f8444f, 0x8743, 0x48f1, {0xa3, 0x28, 0x1e, 0xaa, 0xb8, 0x73, 0x60, 0x80 }} + gEfiCertX509Guid = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 }} + + # + # GUIDs defined in UEFI2.3.1 + # + ## Include/Protocol/Kms.h + gEfiKmsFormatGeneric128Guid = { 0xec8a3d69, 0x6ddf, 0x4108, {0x94, 0x76, 0x73, 0x37, 0xfc, 0x52, 0x21, 0x36 }} + gEfiKmsFormatGeneric160Guid = { 0xa3b3e6f8, 0xefca, 0x4bc1, {0x88, 0xfb, 0xcb, 0x87, 0x33, 0x9b, 0x25, 0x79 }} + gEfiKmsFormatGeneric256Guid = { 0x70f64793, 0xc323, 0x4261, {0xac, 0x2c, 0xd8, 0x76, 0xf2, 0x7c, 0x53, 0x45 }} + gEfiKmsFormatGeneric512Guid = { 0x978fe043, 0xd7af, 0x422e, {0x8a, 0x92, 0x2b, 0x48, 0xe4, 0x63, 0xbd, 0xe6 }} + gEfiKmsFormatGeneric1024Guid = { 0x43be0b44, 0x874b, 0x4ead, {0xb0, 0x9c, 0x24, 0x1a, 0x4f, 0xbd, 0x7e, 0xb3 }} + gEfiKmsFormatGeneric2048Guid = { 0x40093f23, 0x630c, 0x4626, {0x9c, 0x48, 0x40, 0x37, 0x3b, 0x19, 0xcb, 0xbe }} + gEfiKmsFormatGeneric3072Guid = { 0xb9237513, 0x6c44, 0x4411, {0xa9, 0x90, 0x21, 0xe5, 0x56, 0xe0, 0x5a, 0xde }} + gEfiKmsFormatMd2128Guid = { 0x78be11c4, 0xee44, 0x4a22, {0x9f, 0x05, 0x03, 0x85, 0x2e, 0xc5, 0xc9, 0x78 }} + gEfiKmsFormatMdc2128Guid = { 0xf7ad60f8, 0xefa8, 0x44a3, {0x91, 0x13, 0x23, 0x1f, 0x39, 0x9e, 0xb4, 0xc7 }} + gEfiKmsFormatMd4128Guid = { 0xd1c17aa1, 0xcac5, 0x400f, {0xbe, 0x17, 0xe2, 0xa2, 0xae, 0x06, 0x67, 0x7c }} + gEfiKmsFormatMdc4128Guid = { 0x3fa4f847, 0xd8eb, 0x4df4, {0xbd, 0x49, 0x10, 0x3a, 0x0a, 0x84, 0x7b, 0xbc }} + gEfiKmsFormatMd5128Guid = { 0xdcbc3662, 0x9cda, 0x4b52, {0xa0, 0x4c, 0x82, 0xeb, 0x1d, 0x23, 0x48, 0xc7 }} + gEfiKmsFormatMd5sha128Guid = { 0x1c178237, 0x6897, 0x459e, {0x9d, 0x36, 0x67, 0xce, 0x8e, 0xf9, 0x4f, 0x76 }} + gEfiKmsFormatSha1160Guid = { 0x453c5e5a, 0x482d, 0x43f0, {0x87, 0xc9, 0x59, 0x41, 0xf3, 0xa3, 0x8a, 0xc2 }} + gEfiKmsFormatSha256256Guid = { 0x6bb4f5cd, 0x8022, 0x448d, {0xbc, 0x6d, 0x77, 0x1b, 0xae, 0x93, 0x5f, 0xc6 }} + gEfiKmsFormatSha512512Guid = { 0x2f240e12, 0xe14d, 0x475c, {0x83, 0xb0, 0xef, 0xff, 0x22, 0xd7, 0x7b, 0xe7 }} + gEfiKmsFormatAesxts128Guid = { 0x4776e33f, 0xdb47, 0x479a, {0xa2, 0x5f, 0xa1, 0xcd, 0x0a, 0xfa, 0xb3, 0x8b }} + gEfiKmsFormatAesxts256Guid = { 0xdc7e8613, 0xc4bb, 0x4db0, {0x84, 0x62, 0x13, 0x51, 0x13, 0x57, 0xab, 0xe2 }} + gEfiKmsFormatAescbc128Guid = { 0xa0e8ee6a, 0x0e92, 0x44d4, {0x86, 0x1b, 0x0e, 0xaa, 0x4a, 0xca, 0x44, 0xa2 }} + gEfiKmsFormatAescbc256Guid = { 0xd7e69789, 0x1f68, 0x45e8, {0x96, 0xef, 0x3b, 0x64, 0x07, 0xa5, 0xb2, 0xdc }} + gEfiKmsFormatRsasha11024Guid = { 0x56417bed, 0x6bbe, 0x4882, {0x86, 0xa0, 0x3a, 0xe8, 0xbb, 0x17, 0xf8, 0xf9 }} + gEfiKmsFormatRsasha12048Guid = { 0xf66447d4, 0x75a6, 0x463e, {0xa8, 0x19, 0x07, 0x7f, 0x2d, 0xda, 0x05, 0xe9 }} + gEfiKmsFormatRsasha2562048Guid = { 0xa477af13, 0x877d, 0x4060, {0xba, 0xa1, 0x25, 0xd1, 0xbe, 0xa0, 0x8a, 0xd3 }} + gEfiKmsFormatRsasha2563072Guid = { 0x4e1356c2, 0xeed, 0x463f, {0x81, 0x47, 0x99, 0x33, 0xab, 0xdb, 0xc7, 0xd5 }} + + ## Include/Guid/ImageAuthentication.h + gEfiCertSha224Guid = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd }} + gEfiCertSha384Guid = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1 }} + gEfiCertSha512Guid = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a }} + gEfiCertPkcs7Guid = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7 }} + + ## Include/Protocol/Hash.h + gEfiHashAlgorithmSha1NoPadGuid = { 0x24c5dc2f, 0x53e2, 0x40ca, { 0x9e, 0xd6, 0xa5, 0xd9, 0xa4, 0x9f, 0x46, 0x3b }} + gEfiHashAlgorithmSha256NoPadGuid = { 0x8628752a, 0x6cb7, 0x4814, { 0x96, 0xfc, 0x24, 0xa8, 0x15, 0xac, 0x22, 0x26 }} + + # + # GUIDs defined in UEFI2.4 + # + ## Include/Guid/FmpCapsule.h + gEfiFmpCapsuleGuid = { 0x6dcbd5ed, 0xe82d, 0x4c44, {0xbd, 0xa1, 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a }} + + ## Include/Guid/ImageAuthentication.h + gEfiCertX509Sha256Guid = { 0x3bd2a492, 0x96c0, 0x4079, {0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed }} + gEfiCertX509Sha384Guid = { 0x7076876e, 0x80c2, 0x4ee6, {0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b }} + gEfiCertX509Sha512Guid = { 0x446dbf63, 0x2502, 0x4cda, {0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d }} + + ## Include/Protocol/Rng.h + gEfiRngAlgorithmSp80090Hash256Guid = { 0xa7af67cb, 0x603b, 0x4d42, {0xba, 0x21, 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96 }} + gEfiRngAlgorithmSp80090Hmac256Guid = { 0xc5149b43, 0xae85, 0x4f53, {0x99, 0x82, 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7 }} + gEfiRngAlgorithmSp80090Ctr256Guid = { 0x44f0de6e, 0x4d8c, 0x4045, {0xa8, 0xc7, 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e }} + gEfiRngAlgorithmX9313DesGuid = { 0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46 }} + gEfiRngAlgorithmX931AesGuid = { 0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9 }} + gEfiRngAlgorithmRaw = { 0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61 }} + + ## Include/Protocol/AdapterInformation.h + gEfiAdapterInfoMediaStateGuid = { 0xD7C74207, 0xA831, 0x4A26, {0xB1, 0xF5, 0xD1, 0x93, 0x06, 0x5C, 0xE8, 0xB6 }} + gEfiAdapterInfoNetworkBootGuid = { 0x1FBD2960, 0x4130, 0x41E5, {0x94, 0xAC, 0xD2, 0xCF, 0x03, 0x7F, 0xB3, 0x7C }} + gEfiAdapterInfoSanMacAddressGuid = { 0x114da5ef, 0x2cf1, 0x4e12, {0x9b, 0xbb, 0xc4, 0x70, 0xb5, 0x52, 0x5, 0xd9 }} + + ## Include/Guid/CapsuleReport.h + gEfiCapsuleReportGuid = { 0x39b68c46, 0xf7fb, 0x441b, {0xb6, 0xec, 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3 }} + + # + # GUIDs defined in UEFI2.5 + # + + ## Include/Guid/PropertiesTable.h + gEfiPropertiesTableGuid = { 0x880aaca3, 0x4adc, 0x4a04, {0x90, 0x79, 0xb7, 0x47, 0x34, 0x8, 0x25, 0xe5 }} + + ## Include/Guid/SystemResourceTable.h + gEfiSystemResourceTableGuid = { 0xb122a263, 0x3661, 0x4f68, {0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 }} + + ## Include/Protocol/AdapterInformation.h + gEfiAdapterInfoUndiIpv6SupportGuid = { 0x4bd56be3, 0x4975, 0x4d8a, {0xa0, 0xad, 0xc4, 0x91, 0x20, 0x4b, 0x5d, 0x4d }} + + ## Include/Protocol/RegularExpressionProtocol.h + gEfiRegexSyntaxTypePosixExtendedGuid = {0x5F05B20F, 0x4A56, 0xC231, {0xFA, 0x0B, 0xA7, 0xB1, 0xF1, 0x10, 0x04, 0x1D }} + + ## Include/Protocol/RegularExpressionProtocol.h + gEfiRegexSyntaxTypeEcma262Guid = { 0x9A473A4A, 0x4CEB, 0xB95A, {0x41, 0x5E, 0x5B, 0xA0, 0xBC, 0x63, 0x9B, 0x2E }} + + ## Include/Protocol/RegularExpressionProtocol.h + gEfiRegexSyntaxTypePerlGuid = {0x63E60A51, 0x497D, 0xD427, {0xC4, 0xA5, 0xB8, 0xAB, 0xDC, 0x3A, 0xAE, 0xB6 }} + + ## Include/Guid/Cper.h + gEfiPlatformMemory2ErrorSectionGuid = { 0x61EC04FC, 0x48E6, 0xD813, { 0x25, 0xC9, 0x8D, 0xAA, 0x44, 0x75, 0x0B, 0x12 }} + + ## Include/Protocol/BlockIoCrypto.h + gEfiBlockIoCryptoAlgoAesXtsGuid = { 0x2f87ba6a, 0x5c04, 0x4385, {0xa7, 0x80, 0xf3, 0xbf, 0x78, 0xa9, 0x7b, 0xec }} + gEfiBlockIoCryptoAlgoAesCbcMsBitlockerGuid = { 0x689e4c62, 0x70bf, 0x4cf3, {0x88, 0xbb, 0x33, 0xb3, 0x18, 0x26, 0x86, 0x70 }} + + ## Include/Protocol/SmartCardEdge.h + gEfiPaddingRsassaPkcs1V1P5Guid = { 0x9317ec24, 0x7cb0, 0x4d0e, {0x8b, 0x32, 0x2e, 0xd9, 0x20, 0x9c, 0xd8, 0xaf }} + gEfiPaddingRsassaPssGuid = { 0x7b2349e0, 0x522d, 0x4f8e, {0xb9, 0x27, 0x69, 0xd9, 0x7c, 0x9e, 0x79, 0x5f }} + gEfiPaddingNoneGuid = { 0x3629ddb1, 0x228c, 0x452e, {0xb6, 0x16, 0x09, 0xed, 0x31, 0x6a, 0x97, 0x00 }} + gEfiPaddingRsaesPkcs1V1P5Guid = { 0xe1c1d0a9, 0x40b1, 0x4632, {0xbd, 0xcc, 0xd9, 0xd6, 0xe5, 0x29, 0x56, 0x31 }} + gEfiPaddingRsaesOaepGuid = { 0xc1e63ac4, 0xd0cf, 0x4ce6, {0x83, 0x5b, 0xee, 0xd0, 0xe6, 0xa8, 0xa4, 0x5b }} + + ## Include/Guid/SmBios.h + gEfiSmbios3TableGuid = { 0xF2FD1544, 0x9794, 0x4A2C, { 0x99, 0x2E, 0xE5, 0xBB, 0xCF, 0x20, 0xE3, 0x94 }} + + ## Include/Protocol/BootManagerPolicy.h + gEfiBootManagerPolicyConsoleGuid = { 0xCAB0E94C, 0xE15F, 0x11E3, { 0x91, 0x8D, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA }} + gEfiBootManagerPolicyNetworkGuid = { 0xD04159DC, 0xE15F, 0x11E3, { 0xB2, 0x61, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA }} + gEfiBootManagerPolicyConnectAllGuid = { 0x113B2126, 0xFC8A, 0x11E3, { 0xBD, 0x6C, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA }} + + ## Include/Protocol/DevicePath.h + gEfiVirtualDiskGuid = { 0x77AB535A, 0x45FC, 0x624B, {0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E }} + gEfiVirtualCdGuid = { 0x3D5ABD30, 0x4175, 0x87CE, {0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB }} + gEfiPersistentVirtualDiskGuid = { 0x5CEA02C9, 0x4D07, 0x69D3, {0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 }} + gEfiPersistentVirtualCdGuid = { 0x08018188, 0x42CD, 0xBB48, {0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D }} + + # + # GUIDs defined in UEFI2.6 + # + + ## Include/Guid/MemoryAttributesTable.h + gEfiMemoryAttributesTableGuid = { 0xdcfa911d, 0x26eb, 0x469f, {0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20}} + + ## Include/Guid/Cper.h + gEfiArmProcessorErrorSectionGuid = { 0xe19e3d16, 0xbc11, 0x11e4, { 0x9c, 0xaa, 0xc2, 0x05, 0x1d, 0x5d, 0x46, 0xb0 }} + + ## Guid for Image decoder + ## Include/Protocol/ImageDecoder.h + gEfiHiiImageDecoderNameJpegGuid = { 0xefefd093, 0x0d9b, 0x46eb, { 0xa8, 0x56, 0x48, 0x35, 0x07, 0x00, 0xc9, 0x08 }} + gEfiHiiImageDecoderNamePngGuid = { 0xaf060190, 0x5e3a, 0x4025, { 0xaf, 0xbd, 0xe1, 0xf9, 0x05, 0xbf, 0xaa, 0x4c }} + + # + # GUIDs defined in UEFI2.7 + # + ## Include/Guid/Btt.h + gEfiBttAbstractionGuid = { 0x18633bfc, 0x1735, 0x4217, { 0x8a, 0xc9, 0x17, 0x23, 0x92, 0x82, 0xd3, 0xf8 }} + + # + # GUID defined in PI1.0 + # + ## Include/Guid/AprioriFileName.h + gPeiAprioriFileNameGuid = { 0x1b45cc0a, 0x156a, 0x428a, { 0XAF, 0x62, 0x49, 0x86, 0x4d, 0xa0, 0xe6, 0xe6 }} + + ## Include/Guid/Apriori.h + gAprioriGuid = { 0xFC510EE7, 0xFFDC, 0x11D4, { 0xBD, 0x41, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Guid/FirmwareFileSystem2.h + gEfiFirmwareFileSystem2Guid = { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 }} + + ## Include/Guid/FirmwareFileSystem2.h + gEfiFirmwareVolumeTopFileGuid = { 0x1BA0062E, 0xC779, 0x4582, { 0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x09 }} + + ## Include/Guid/MemoryAllocationHob.h + gEfiHobMemoryAllocModuleGuid = { 0xF8E21975, 0x0899, 0x4F58, { 0xA4, 0xBE, 0x55, 0x25, 0xA9, 0xC6, 0xD7, 0x7A }} + + ## Include/Guid/MemoryAllocationHob.h + gEfiHobMemoryAllocStackGuid = { 0x4ED4BF27, 0x4092, 0x42E9, { 0x80, 0x7D, 0x52, 0x7B, 0x1D, 0x00, 0xC9, 0xBD }} + + ## Include/Guid/MemoryAllocationHob.h + gEfiHobMemoryAllocBspStoreGuid = { 0x564B33CD, 0xC92A, 0x4593, { 0x90, 0xBF, 0x24, 0x73, 0xE4, 0x3C, 0x63, 0x22 }} + + ## Include/Guid/EventLegacyBios.h + gEfiEventLegacyBootGuid = { 0x2A571201, 0x4966, 0x47F6, { 0x8B, 0x86, 0xF3, 0x1E, 0x41, 0xF3, 0x2F, 0x10 }} + + ## Include/Guid/HobList.h + gEfiHobListGuid = { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Guid/DxeServices.h + gEfiDxeServicesTableGuid = { 0x05AD34BA, 0x6F02, 0x4214, { 0x95, 0x2E, 0x4D, 0xA0, 0x39, 0x8E, 0x2B, 0xB9 }} + + ## Include/Guid/MdePkgTokenSpace.h + gEfiMdePkgTokenSpaceGuid = { 0x914AEBE7, 0x4635, 0x459b, { 0xAA, 0x1C, 0x11, 0xE2, 0x19, 0xB0, 0x3A, 0x10 }} + + ## Include/Guid/HardwareErrorVariable.h + gEfiHardwareErrorVariableGuid = { 0x414E6BDD, 0xE47B, 0x47cc, { 0xB2, 0x44, 0xBB, 0x61, 0x02, 0x0C, 0xF5, 0x16 }} + + # + # GUID defined in PI1.2 + # + ## Include/Guid/EventGroup.h + gEfiEventDxeDispatchGuid = { 0x7081E22F, 0xCAC6, 0x4053, { 0x94, 0x68, 0x67, 0x57, 0x82, 0xCF, 0x88, 0xE5 }} + + ## Guid for EFI_DISK_INFO_PROTOCOL.Interface to specify Ide interface. + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoIdeInterfaceGuid = { 0x5E948FE3, 0x26D3, 0x42B5, { 0xAF, 0x17, 0x61, 0x02, 0x87, 0x18, 0x8D, 0xEC }} + + ## Guid for EFI_DISK_INFO_PROTOCOL.Interface to specify Scsi interface. + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoScsiInterfaceGuid = { 0x08F74BAA, 0xEA36, 0x41D9, { 0x95, 0x21, 0x21, 0xA7, 0x0F, 0x87, 0x80, 0xBC }} + + ## Guid for EFI_DISK_INFO_PROTOCOL.Interface to specify Usb interface. + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoUsbInterfaceGuid = { 0xCB871572, 0xC11A, 0x47B5, { 0xB4, 0x92, 0x67, 0x5E, 0xAF, 0xA7, 0x77, 0x27 }} + + ## Guid for EFI_DISK_INFO_PROTOCOL.Interface to specify Ahci interface. + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoAhciInterfaceGuid = { 0x9e498932, 0x4abc, 0x45af, { 0xa3, 0x4d, 0x02, 0x47, 0x78, 0x7b, 0xe7, 0xc6 }} + + ## Include/Guid/StatusCodeDataTypeId.h + gEfiStatusCodeDataTypeStringGuid = { 0x92D11080, 0x496F, 0x4D95, { 0xBE, 0x7E, 0x03, 0x74, 0x88, 0x38, 0x2B, 0x0A }} + + ## Include/Guid/StatusCodeDataTypeId.h + gEfiStatusCodeSpecificDataGuid = { 0x335984BD, 0xE805, 0x409A, { 0xB8, 0xF8, 0xD2, 0x7E, 0xCE, 0x5F, 0xF7, 0xA6 }} + + ## Include/Guid/FirmwareFileSystem3.h + gEfiFirmwareFileSystem3Guid = { 0x5473c07a, 0x3dcb, 0x4dca, { 0xbd, 0x6f, 0x1e, 0x96, 0x89, 0xe7, 0x34, 0x9a }} + + # + # GUID defined in PI1.2.1 + # + ## Include/Guid/EventGroup.h + gEfiEndOfDxeEventGroupGuid = { 0x2ce967a, 0xdd7e, 0x4ffc, { 0x9e, 0xe7, 0x81, 0xc, 0xf0, 0x47, 0x8, 0x80 }} + + ## Include/Guid/FirmwareContentsSigned.h + gEfiFirmwareContentsSignedGuid = { 0xf9d89e8, 0x9259, 0x4f76, { 0xa5, 0xaf, 0xc, 0x89, 0xe3, 0x40, 0x23, 0xdf }} + + ## Include/Guid/VectorHandoffTable.h + gEfiVectorHandoffTableGuid = { 0x996ec11c, 0x5397, 0x4e73, { 0xb5, 0x8f, 0x82, 0x7e, 0x52, 0x90, 0x6d, 0xef }} + + ## Include/IndustryStandard/Hsti.h + gAdapterInfoPlatformSecurityGuid = {0x6be272c7, 0x1320, 0x4ccd, { 0x90, 0x17, 0xd4, 0x61, 0x2c, 0x01, 0x2b, 0x25 }} + + # + # GUID defined in PI1.3 + # + ## Guid for EFI_DISK_INFO_PROTOCOL.Interface to specify Nvme interface. + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoNvmeInterfaceGuid = { 0x3ab14680, 0x5d3f, 0x4a4d, { 0xbc, 0xdc, 0xcc, 0x38, 0x0, 0x18, 0xc7, 0xf7 }} + + # + # GUID defined in PI1.4 + # + ## Include/Guid/GraphicsInfoHob.h + gEfiGraphicsInfoHobGuid = { 0x39f62cce, 0x6825, 0x4669, { 0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07 }} + + ## Guid for EFI_DISK_INFO_PROTOCOL.Interface to specify UFS interface. + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoUfsInterfaceGuid = { 0x4b3029cc, 0x6b98, 0x47fb, { 0xbc, 0x96, 0x76, 0xdc, 0xb8, 0x4, 0x41, 0xf0 }} + + # + # GUID defined in PI1.5 + # + ## Include/Guid/GraphicsInfoHob.h + gEfiGraphicsDeviceInfoHobGuid = { 0xe5cb2ac9, 0xd35d, 0x4430, { 0x93, 0x6e, 0x1d, 0xe3, 0x32, 0x47, 0x8d, 0xe7 }} + + # + # GUID defined in PI1.6 + # + ## Include/Protocol/DiskInfo.h + gEfiDiskInfoSdMmcInterfaceGuid = { 0x8deec992, 0xd39c, 0x4a5c, { 0xab, 0x6b, 0x98, 0x6e, 0x14, 0x24, 0x2b, 0x9d }} + + # + # GUID defined in Windows UEFI Firmware Update Platform doc + # + ## Include/IndustryStandard/WindowsUxCapsule.h + gWindowsUxCapsuleGuid = { 0x3b8c8162, 0x188c, 0x46a4, { 0xae, 0xc9, 0xbe, 0x43, 0xf1, 0xd6, 0x56, 0x97}} + +[Guids.IA32, Guids.X64] + ## Include/Guid/Cper.h + gEfiIa32X64ErrorTypeCacheCheckGuid = { 0xA55701F5, 0xE3EF, 0x43de, { 0xAC, 0x72, 0x24, 0x9B, 0x57, 0x3F, 0xAD, 0x2C }} + + ## Include/Guid/Cper.h + gEfiIa32X64ErrorTypeTlbCheckGuid = { 0xFC06B535, 0x5E1F, 0x4562, { 0x9F, 0x25, 0x0A, 0x3B, 0x9A, 0xDB, 0x63, 0xC3 }} + + ## Include/Guid/Cper.h + gEfiIa32X64ErrorTypeBusCheckGuid = { 0x1CF3F8B3, 0xC5B1, 0x49a2, { 0xAA, 0x59, 0x5E, 0xEF, 0x92, 0xFF, 0xA6, 0x3C }} + + ## Include/Guid/Cper.h + gEfiIa32X64ErrorTypeMsCheckGuid = { 0x48AB7F57, 0xDC34, 0x4f6c, { 0xA7, 0xD3, 0xB0, 0xB5, 0xB0, 0xA7, 0x43, 0x14 }} + +[Ppis] + ## Include/Ppi/MasterBootMode.h + gEfiPeiMasterBootModePpiGuid = { 0x7408d748, 0xfc8c, 0x4ee6, {0x92, 0x88, 0xc4, 0xbe, 0xc0, 0x92, 0xa4, 0x10 } } + + ## Include/Ppi/DxeIpl.h + gEfiDxeIplPpiGuid = {0xae8ce5d, 0xe448, 0x4437, {0xa8, 0xd7, 0xeb, 0xf5, 0xf1, 0x94, 0xf7, 0x31 }} + + ## Include/Ppi/MemoryDiscovered.h + gEfiPeiMemoryDiscoveredPpiGuid = {0xf894643d, 0xc449, 0x42d1, {0x8e, 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } } + + ## Include/Ppi/BootInRecoveryMode.h + gEfiPeiBootInRecoveryModePpiGuid = { 0x17ee496a, 0xd8e4, 0x4b9a, {0x94, 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } } + + ## Include/Ppi/EndOfPeiPhase.h + gEfiEndOfPeiSignalPpiGuid = {0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } } + + ## Include/Ppi/Reset.h + gEfiPeiResetPpiGuid = { 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78, 0xc6, 0xf4, 0xfe, 0x71, 0x2f } } + + ## Include/Ppi/StatusCode.h + gEfiPeiStatusCodePpiGuid = { 0x229832d3, 0x7a30, 0x4b36, {0xb8, 0x27, 0xf4, 0xc, 0xb7, 0xd4, 0x54, 0x36 } } + + ## Include/Ppi/Security2.h + gEfiPeiSecurity2PpiGuid = { 0xdcd0be23, 0x9586, 0x40f4, { 0xb6, 0x43, 0x6, 0x52, 0x2c, 0xed, 0x4e, 0xde } } + + ## Include/Ppi/TemporaryRamSupport.h + gEfiTemporaryRamSupportPpiGuid = { 0xdbe23aa9, 0xa345, 0x4b97, {0x85, 0xb6, 0xb2, 0x26, 0xf1, 0x61, 0x73, 0x89} } + + ## Include/Ppi/CpuIo.h + gEfiPeiCpuIoPpiInstalledGuid = { 0xe6af1f7b, 0xfc3f, 0x46da, {0xa8, 0x28, 0xa3, 0xb4, 0x57, 0xa4, 0x42, 0x82 } } + + ## Include/Ppi/PciCfg2.h + gEfiPciCfg2PpiGuid = { 0x57a449a, 0x1fdc, 0x4c06, { 0xbf, 0xc9, 0xf5, 0x3f, 0x6a, 0x99, 0xbb, 0x92 } } + + ## Include/Ppi/Stall.h + gEfiPeiStallPpiGuid = { 0x1f4c6f90, 0xb06b, 0x48d8, {0xa2, 0x01, 0xba, 0xe5, 0xf1, 0xcd, 0x7d, 0x56 } } + + ## Include/Ppi/ReadOnlyVariable2.h + gEfiPeiReadOnlyVariable2PpiGuid = { 0x2ab86ef5, 0xecb5, 0x4134, { 0xb5, 0x56, 0x38, 0x54, 0xca, 0x1f, 0xe1, 0xb4 } } + + ## Include/Ppi/SecPlatformInformation.h + gEfiSecPlatformInformationPpiGuid = { 0x6f8c2b35, 0xfef4, 0x448d, {0x82, 0x56, 0xe1, 0x1b, 0x19, 0xd6, 0x10, 0x77 } } + + ## Include/Ppi/LoadImage.h + gEfiPeiLoadedImagePpiGuid = { 0xc1fcd448, 0x6300, 0x4458, { 0xb8, 0x64, 0x28, 0xdf, 0x1, 0x53, 0x64, 0xbc } } + + ## Include/Ppi/Smbus2.h + gEfiPeiSmbus2PpiGuid = { 0x9ca93627, 0xb65b, 0x4324, { 0xa2, 0x2, 0xc0, 0xb4, 0x61, 0x76, 0x45, 0x43 } } + + ## Include/Ppi/FirmwareVolumeInfo.h + gEfiPeiFirmwareVolumeInfoPpiGuid = { 0x49edb1c1, 0xbf21, 0x4761, { 0xbb, 0x12, 0xeb, 0x0, 0x31, 0xaa, 0xbb, 0x39 } } + + ## Include/Ppi/LoadFile.h + gEfiPeiLoadFilePpiGuid = { 0xb9e0abfe, 0x5979, 0x4914, { 0x97, 0x7f, 0x6d, 0xee, 0x78, 0xc2, 0x78, 0xa6 } } + + ## Include/Ppi/Decompress.h + gEfiPeiDecompressPpiGuid = { 0x1a36e4e7, 0xfab6, 0x476a, { 0x8e, 0x75, 0x69, 0x5a, 0x5, 0x76, 0xfd, 0xd7 } } + + ## Include/Ppi/Pcd.h + gPcdPpiGuid = { 0x6e81c58, 0x4ad7, 0x44bc, { 0x83, 0x90, 0xf1, 0x2, 0x65, 0xf7, 0x24, 0x80 } } + + ## Include/Ppi/PcdInfo.h + gGetPcdInfoPpiGuid = { 0x4d8b155b, 0xc059, 0x4c8f, { 0x89, 0x26, 0x6, 0xfd, 0x43, 0x31, 0xdb, 0x8a } } + + # + # PPIs defined in PI 1.2. + # + + ## Include/Ppi/RecoveryModule.h + gEfiPeiRecoveryModulePpiGuid = { 0xFB6D9542, 0x612D, 0x4f45, { 0x87, 0x2f, 0x5c, 0xff, 0x52, 0xe9, 0x3d, 0xcf }} + + ## Include/Ppi/DeviceRecoveryModule.h + gEfiPeiDeviceRecoveryModulePpiGuid = { 0x0DE2CE25, 0x446A, 0x45a7, { 0xBF, 0xC9, 0x37, 0xDA, 0x26, 0x34, 0x4B, 0x37 }} + + ## Include/Ppi/BlockIo.h + gEfiPeiVirtualBlockIoPpiGuid = { 0x695d8aa1, 0x42ee, 0x4c46, { 0x80, 0x5c, 0x6e, 0xa6, 0xbc, 0xe7, 0x99, 0xe3 }} + + ## Include/Ppi/S3Resume2.h + gEfiPeiS3Resume2PpiGuid = { 0x6D582DBC, 0xDB85, 0x4514, {0x8F, 0xCC, 0x5A, 0xDF, 0x62, 0x27, 0xB1, 0x47 }} + + ## Include/Ppi/ReportStatusCodeHandler.h + gEfiPeiRscHandlerPpiGuid = { 0x65d394, 0x9951, 0x4144, {0x82, 0xa3, 0xa, 0xfc, 0x85, 0x79, 0xc2, 0x51 }} + + ## Include/Ppi/PiPcd.h + gEfiPeiPcdPpiGuid = { 0x1f34d25, 0x4de2, 0x23ad, { 0x3f, 0xf3, 0x36, 0x35, 0x3f, 0xf3, 0x23, 0xf1 } } + + # + # PPIs defined in PI 1.2.1. + # + + ## Include/Ppi/PiPcdInfo.h + gEfiGetPcdInfoPpiGuid = { 0xa60c6b59, 0xe459, 0x425d, { 0x9c, 0x69, 0xb, 0xcc, 0x9c, 0xb2, 0x7d, 0x81 } } + + ## Include/Ppi/TemporaryRamDone.h + gEfiTemporaryRamDonePpiGuid = { 0xceab683c, 0xec56, 0x4a2d, { 0xa9, 0x6, 0x40, 0x53, 0xfa, 0x4e, 0x9c, 0x16 } } + + ## Include/Ppi/VectorHandoffInfo.h + gEfiVectorHandoffInfoPpiGuid = { 0x3cd652b4, 0x6d33, 0x4dce, { 0x89, 0xdb, 0x83, 0xdf, 0x97, 0x66, 0xfc, 0xca }} + + ## Include/Ppi/IsaHc.h + gEfiIsaHcPpiGuid = { 0x8d48bd70, 0xc8a3, 0x4c06, {0x90, 0x1b, 0x74, 0x79, 0x46, 0xaa, 0xc3, 0x58 } } + + ## Include/Ppi/SuperIo.h + gEfiSioPpiGuid = { 0x23a464ad, 0xcb83, 0x48b8, {0x94, 0xab, 0x1a, 0x6f, 0xef, 0xcf, 0xe5, 0x22 } } + + # + # PPIs defined in PI 1.3. + # + + ## Include/Ppi/I2cMaster.h + gEfiPeiI2cMasterPpiGuid = { 0xb3bfab9b, 0x9f9c, 0x4e8b, { 0xad, 0x37, 0x7f, 0x8c, 0x51, 0xfc, 0x62, 0x80 }} + + ## Include/Ppi/FirmwareVolumeInfo2.h + gEfiPeiFirmwareVolumeInfo2PpiGuid = { 0xea7ca24b, 0xded5, 0x4dad, { 0xa3, 0x89, 0xbf, 0x82, 0x7e, 0x8f, 0x9b, 0x38 } } + + # + # PPIs defined in PI 1.4. + # + + ## Include/Ppi/Graphics.h + gEfiPeiGraphicsPpiGuid = { 0x6ecd1463, 0x4a4a, 0x461b, { 0xaf, 0x5f, 0x5a, 0x33, 0xe3, 0xb2, 0x16, 0x2b } } + + ## Include/Ppi/MpServices.h + gEfiPeiMpServicesPpiGuid = { 0xee16160a, 0xe8be, 0x47a6, { 0x82, 0xa, 0xc6, 0x90, 0xd, 0xb0, 0x25, 0xa } } + + ## Include/Ppi/Capsule.h + gEfiPeiCapsulePpiGuid = { 0x3acf33ee, 0xd892, 0x40f4, { 0xa2, 0xfc, 0x38, 0x54, 0xd2, 0xe1, 0x32, 0x3d }} + ## Keep name backwards compatible before PI Version 1.4 + gPeiCapsulePpiGuid = { 0x3acf33ee, 0xd892, 0x40f4, { 0xa2, 0xfc, 0x38, 0x54, 0xd2, 0xe1, 0x32, 0x3d }} + + ## Include/Ppi/Reset2.h + gEfiPeiReset2PpiGuid = { 0x6cc45765, 0xcce4, 0x42fd, {0xbc, 0x56, 0x1, 0x1a, 0xaa, 0xc6, 0xc9, 0xa8 } } + + ## Include/Ppi/BlockIo2.h + gEfiPeiVirtualBlockIo2PpiGuid = { 0x26cc0fad, 0xbeb3, 0x478a, { 0x91, 0xb2, 0xc, 0x18, 0x8f, 0x72, 0x61, 0x98 }} + + ## Include/Ppi/SecPlatformInformation.h + gEfiSecPlatformInformation2PpiGuid = { 0x9e9f374b, 0x8f16, 0x4230, {0x98, 0x24, 0x58, 0x46, 0xee, 0x76, 0x6a, 0x97 } } + + # + # PPIs defined in PI 1.5. + # + + ## Include/Ppi/SecHobData.h + gEfiSecHobDataPpiGuid = { 0x3ebdaf20, 0x6667, 0x40d8, {0xb4, 0xee, 0xf5, 0x99, 0x9a, 0xc1, 0xb7, 0x1f } } + + # + # PPIs defined in PI 1.7. + # + + ## Include/Ppi/PeiCoreFvLocation.h + gEfiPeiCoreFvLocationPpiGuid = { 0x52888eae, 0x5b10, 0x47d0, { 0xa8, 0x7f, 0xb8, 0x22, 0xab, 0xa0, 0xca, 0xf4 }} + +[Protocols] + ## Include/Protocol/Pcd.h + gPcdProtocolGuid = { 0x11B34006, 0xD85B, 0x4D0A, { 0xA2, 0x90, 0xD5, 0xA5, 0x71, 0x31, 0x0E, 0xF7 }} + + ## Include/Protocol/PcdInfo.h + gGetPcdInfoProtocolGuid = { 0x5be40f57, 0xfa68, 0x4610, { 0xbb, 0xbf, 0xe9, 0xc5, 0xfc, 0xda, 0xd3, 0x65 } } + + # + # Protocols defined in PI1.0. + # + + ## Include/Protocol/Bds.h + gEfiBdsArchProtocolGuid = { 0x665E3FF6, 0x46CC, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/Cpu.h + gEfiCpuArchProtocolGuid = { 0x26BACCB1, 0x6F42, 0x11D4, { 0xBC, 0xE7, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Protocol/Metronome.h + gEfiMetronomeArchProtocolGuid = { 0x26BACCB2, 0x6F42, 0x11D4, { 0xBC, 0xE7, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Protocol/MonotonicCounter.h + gEfiMonotonicCounterArchProtocolGuid = { 0x1DA97072, 0xBDDC, 0x4B30, { 0x99, 0xF1, 0x72, 0xA0, 0xB5, 0x6F, 0xFF, 0x2A }} + + ## Include/Protocol/RealTimeClock.h + gEfiRealTimeClockArchProtocolGuid = { 0x27CFAC87, 0x46CC, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/Reset.h + gEfiResetArchProtocolGuid = { 0x27CFAC88, 0x46CC, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/Runtime.h + gEfiRuntimeArchProtocolGuid = { 0xb7dfb4e1, 0x052f, 0x449f, { 0x87, 0xbe, 0x98, 0x18, 0xfc, 0x91, 0xb7, 0x33 }} + + ## Include/Protocol/Security.h + gEfiSecurityArchProtocolGuid = { 0xA46423E3, 0x4617, 0x49F1, { 0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 }} + + ## Include/Protocol/SecurityPolicy.h + gEfiSecurityPolicyProtocolGuid = { 0x78E4D245, 0xCD4D, 0x4A05, { 0xA2, 0xBA, 0x47, 0x43, 0xE8, 0x6C, 0xFC, 0xAB }} + + ## Include/Protocol/Timer.h + gEfiTimerArchProtocolGuid = { 0x26BACCB3, 0x6F42, 0x11D4, { 0xBC, 0xE7, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Protocol/VariableWrite.h + gEfiVariableWriteArchProtocolGuid = { 0x6441F818, 0x6362, 0x4E44, { 0xB5, 0x70, 0x7D, 0xBA, 0x31, 0xDD, 0x24, 0x53 }} + + ## Include/Protocol/Variable.h + gEfiVariableArchProtocolGuid = { 0x1E5668E2, 0x8481, 0x11D4, { 0xBC, 0xF1, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }} + + ## Include/Protocol/WatchdogTimer.h + gEfiWatchdogTimerArchProtocolGuid = { 0x665E3FF5, 0x46CC, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/StatusCode.h + gEfiStatusCodeRuntimeProtocolGuid = { 0xD2B2B828, 0x0826, 0x48A7, { 0xB3, 0xDF, 0x98, 0x3C, 0x00, 0x60, 0x24, 0xF0 }} + + ## Include/Protocol/SmbusHc.h + gEfiSmbusHcProtocolGuid = {0xe49d33ed, 0x513d, 0x4634, { 0xb6, 0x98, 0x6f, 0x55, 0xaa, 0x75, 0x1c, 0x1b} } + + ## Include/Protocol/FirmwareVolume2.h + gEfiFirmwareVolume2ProtocolGuid = { 0x220e73b6, 0x6bdb, 0x4413, { 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a } } + + ## Include/Protocol/FirmwareVolumeBlock.h + gEfiFirmwareVolumeBlockProtocolGuid = { 0x8f644fa9, 0xe850, 0x4db1, {0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4 } } + + ## Include/Protocol/Capsule.h + gEfiCapsuleArchProtocolGuid = { 0x5053697E, 0x2CBC, 0x4819, { 0x90, 0xD9, 0x05, 0x80, 0xDE, 0xEE, 0x57, 0x54 }} + + # + # Protocols defined in PI 1.2. + # + + ## Include/Protocol/MpService.h + gEfiMpServiceProtocolGuid = { 0x3fdda605, 0xa76e, 0x4f46, { 0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08 }} + + ## Include/Protocol/PciHostBridgeResourceAllocation.h + gEfiPciHostBridgeResourceAllocationProtocolGuid = { 0xCF8034BE, 0x6768, 0x4d8b, { 0xb7, 0x39, 0x7c, 0xce, 0x68, 0x3a, 0x9f, 0xbe }} + + ## Include/Protocol/PciPlatform.h + gEfiPciPlatformProtocolGuid = { 0x07d75280, 0x27d4, 0x4d69, { 0x90, 0xd0, 0x56, 0x43, 0xe2, 0x38, 0xb3, 0x41 }} + + ## Include/Protocol/PciOverride.h + gEfiPciOverrideProtocolGuid = { 0xb5b35764, 0x460c, 0x4a06, {0x99, 0xfc, 0x77, 0xa1, 0x7c, 0x1b, 0x5c, 0xeb }} + + ## Include/Protocol/PciEnumerationComplete.h + gEfiPciEnumerationCompleteProtocolGuid = { 0x30cfe3e7, 0x3de1, 0x4586, {0xbe, 0x20, 0xde, 0xab, 0xa1, 0xb3, 0xb7, 0x93}} + + + ## Include/Protocol/IncompatiblePciDeviceSupport.h + gEfiIncompatiblePciDeviceSupportProtocolGuid = { 0xeb23f55a, 0x7863, 0x4ac2, { 0x8d, 0x3d, 0x95, 0x65, 0x35, 0xde, 0x03, 0x75 }} + + ## Include/Protocol/PciHotPlugInit.h + gEfiPciHotPlugInitProtocolGuid = { 0xaa0e8bc1, 0xdabc, 0x46b0, { 0xa8, 0x44, 0x37, 0xb8, 0x16, 0x9b, 0x2b, 0xea }} + + ## This protocol is used to add or remove all PCI child devices on the PCI root bridge. + # Include/Protocol/PciHotPlugRequest.h + gEfiPciHotPlugRequestProtocolGuid = { 0x19CB87AB, 0x2CB9, 0x4665, { 0x83, 0x60, 0xDD, 0xCF, 0x60, 0x54, 0xF7, 0x9D }} + + ## Include/Protocol/IdeControllerInit.h + gEfiIdeControllerInitProtocolGuid = { 0xa1e37052, 0x80d9, 0x4e65, { 0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9 }} + + ## Disk Info protocol is used to export Inquiry Data for a drive. + # Include/Protocol/DiskInfo.h + gEfiDiskInfoProtocolGuid = { 0xD432A67F, 0x14DC, 0x484B, { 0xB3, 0xBB, 0x3F, 0x02, 0x91, 0x84, 0x93, 0x27 }} + + ## Include/Protocol/Smbios.h + gEfiSmbiosProtocolGuid = {0x3583ff6, 0xcb36, 0x4940, { 0x94, 0x7e, 0xb9, 0xb3, 0x9f, 0x4a, 0xfa, 0xf7}} + + ## Include/Protocol/S3SaveState.h + gEfiS3SaveStateProtocolGuid = {0xe857caf6, 0xc046, 0x45dc, { 0xbe, 0x3f, 0xee, 0x7, 0x65, 0xfb, 0xa8, 0x87}} + + ## Include/Protocol/S3SmmSaveState.h + gEfiS3SmmSaveStateProtocolGuid = {0x320afe62, 0xe593, 0x49cb, { 0xa9, 0xf1, 0xd4, 0xc2, 0xf4, 0xaf, 0x1, 0x4c}} + + ## Include/Protocol/ReportStatusCodeHandler.h + gEfiRscHandlerProtocolGuid = { 0x86212936, 0xe76, 0x41c8, { 0xa0, 0x3a, 0x2a, 0xf2, 0xfc, 0x1c, 0x39, 0xe2 }} + + ## Include/Protocol/SmmReportStatusCodeHandler.h + gEfiSmmRscHandlerProtocolGuid = { 0x2ff29fa7, 0x5e80, 0x4ed9, { 0xb3, 0x80, 0x1, 0x7d, 0x3c, 0x55, 0x4f, 0xf4 }} + + ## Include/Protocol/AcpiSystemDescriptionTable.h + gEfiAcpiSdtProtocolGuid = { 0xeb97088e, 0xcfdf, 0x49c6, { 0xbe, 0x4b, 0xd9, 0x6, 0xa5, 0xb2, 0xe, 0x86 }} + + ## Include/Protocol/SuperIo.h + gEfiSioProtocolGuid = { 0x215fdd18, 0xbd50, 0x4feb, { 0x89, 0xb, 0x58, 0xca, 0xb, 0x47, 0x39, 0xe9 }} + + ## Include/Protocol/SmmCpuIo2.h + gEfiSmmCpuIo2ProtocolGuid = { 0x3242a9d8, 0xce70, 0x4aa0, { 0x95, 0x5d, 0x5e, 0x7b, 0x14, 0x0d, 0xe4, 0xd2 }} + + ## Include/Protocol/SmmBase2.h + gEfiSmmBase2ProtocolGuid = { 0xf4ccbfb7, 0xf6e0, 0x47fd, { 0x9d, 0xd4, 0x10, 0xa8, 0xf1, 0x50, 0xc1, 0x91 }} + + ## Include/Protocol/SmmAccess2.h + gEfiSmmAccess2ProtocolGuid = { 0xc2702b74, 0x800c, 0x4131, { 0x87, 0x46, 0x8f, 0xb5, 0xb8, 0x9c, 0xe4, 0xac }} + + ## Include/Protocol/SmmControl2.h + gEfiSmmControl2ProtocolGuid = { 0x843dc720, 0xab1e, 0x42cb, { 0x93, 0x57, 0x8a, 0x0, 0x78, 0xf3, 0x56, 0x1b}} + + ## Include/Protocol/SmmConfiguration.h + gEfiSmmConfigurationProtocolGuid= { 0x26eeb3de, 0xb689, 0x492e, { 0x80, 0xf0, 0xbe, 0x8b, 0xd7, 0xda, 0x4b, 0xa7 }} + + ## Include/Protocol/SmmReadyToLock.h + gEfiSmmReadyToLockProtocolGuid = { 0x47b7fa8c, 0xf4bd, 0x4af6, { 0x82, 0x00, 0x33, 0x30, 0x86, 0xf0, 0xd2, 0xc8 }} + + ## Include/Protocol/DxeSmmReadyToLock.h + gEfiDxeSmmReadyToLockProtocolGuid = { 0x60ff8964, 0xe906, 0x41d0, { 0xaf, 0xed, 0xf2, 0x41, 0xe9, 0x74, 0xe0, 0x8e }} + + ## Include/Protocol/SmmCommunication.h + gEfiSmmCommunicationProtocolGuid = { 0xc68ed8e2, 0x9dc6, 0x4cbd, { 0x9d, 0x94, 0xdb, 0x65, 0xac, 0xc5, 0xc3, 0x32 }} + + ## Include/Protocol/SmmStatusCode.h + gEfiSmmStatusCodeProtocolGuid = { 0x6afd2b77, 0x98c1, 0x4acd, { 0xa6, 0xf9, 0x8a, 0x94, 0x39, 0xde, 0xf, 0xb1}} + + ## Include/Protocol/SmmCpu.h + gEfiSmmCpuProtocolGuid = { 0xeb346b97, 0x975f, 0x4a9f, { 0x8b, 0x22, 0xf8, 0xe9, 0x2b, 0xb3, 0xd5, 0x69 }} + + ## Include/Protocol/SmmPciRootBridgeIo.h + gEfiSmmPciRootBridgeIoProtocolGuid = { 0x8bc1714d, 0xffcb, 0x41c3, { 0x89, 0xdc, 0x6c, 0x74, 0xd0, 0x6d, 0x98, 0xea }} + + ## Include/Protocol/SmmSwDispatch2.h + gEfiSmmSwDispatch2ProtocolGuid = { 0x18a3c6dc, 0x5eea, 0x48c8, {0xa1, 0xc1, 0xb5, 0x33, 0x89, 0xf9, 0x89, 0x99 }} + + ## Include/Protocol/SmmSxDispatch2.h + gEfiSmmSxDispatch2ProtocolGuid = { 0x456d2859, 0xa84b, 0x4e47, {0xa2, 0xee, 0x32, 0x76, 0xd8, 0x86, 0x99, 0x7d }} + + ## Include/Protocol/SmmPeriodicTimerDispatch2.h + gEfiSmmPeriodicTimerDispatch2ProtocolGuid = { 0x4cec368e, 0x8e8e, 0x4d71, {0x8b, 0xe1, 0x95, 0x8c, 0x45, 0xfc, 0x8a, 0x53 }} + + ## Include/Protocol/SmmUsbDispatch2.h + gEfiSmmUsbDispatch2ProtocolGuid = { 0xee9b8d90, 0xc5a6, 0x40a2, {0xbd, 0xe2, 0x52, 0x55, 0x8d, 0x33, 0xcc, 0xa1 }} + + ## Include/Protocol/SmmGpiDispatch2.h + gEfiSmmGpiDispatch2ProtocolGuid = { 0x25566b03, 0xb577, 0x4cbf, {0x95, 0x8c, 0xed, 0x66, 0x3e, 0xa2, 0x43, 0x80 }} + + ## Include/Protocol/SmmStandbyButtonDispatch2.h + gEfiSmmStandbyButtonDispatch2ProtocolGuid = { 0x7300c4a1, 0x43f2, 0x4017, {0xa5, 0x1b, 0xc8, 0x1a, 0x7f, 0x40, 0x58, 0x5b }} + + ## Include/Protocol/SmmPowerButtonDispatch2.h + gEfiSmmPowerButtonDispatch2ProtocolGuid = { 0x1b1183fa, 0x1823, 0x46a7, {0x88, 0x72, 0x9c, 0x57, 0x87, 0x55, 0x40, 0x9d }} + + ## Include/Protocol/SmmIoTrapDispatch2.h + gEfiSmmIoTrapDispatch2ProtocolGuid = { 0x58dc368d, 0x7bfa, 0x4e77, {0xab, 0xbc, 0xe, 0x29, 0x41, 0x8d, 0xf9, 0x30 }} + + ## Include/Protocol/PiPcd.h + gEfiPcdProtocolGuid = { 0x13a3f0f6, 0x264a, 0x3ef0, { 0xf2, 0xe0, 0xde, 0xc5, 0x12, 0x34, 0x2f, 0x34 } } + + ## Include/Protocol/FirmwareVolumeBlock.h + gEfiFirmwareVolumeBlock2ProtocolGuid = { 0x8f644fa9, 0xe850, 0x4db1, {0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4 } } + + ## Include/Protocol/CpuIo2.h + gEfiCpuIo2ProtocolGuid = {0xad61f191, 0xae5f, 0x4c0e, {0xb9, 0xfa, 0xe8, 0x69, 0xd2, 0x88, 0xc6, 0x4f } } + + ## Include/Protocol/LegacyRegion2.h + gEfiLegacyRegion2ProtocolGuid = {0x70101eaf, 0x85, 0x440c, {0xb3, 0x56, 0x8e, 0xe3, 0x6f, 0xef, 0x24, 0xf0 } } + + ## Include/Protocol/McaInitPmi.h + gEfiSalMcaInitPmiProtocolGuid = { 0xb60dc6e8, 0x3b6f, 0x11d5, {0xaf, 0x9, 0x0, 0xa0, 0xc9, 0x44, 0xa0, 0x5b } } + + ## Include/Protocol/ExtendedSalBootService.h + gEfiExtendedSalBootServiceProtocolGuid = { 0xde0ee9a4, 0x3c7a, 0x44f2, {0xb7, 0x8b, 0xe3, 0xcc, 0xd6, 0x9c, 0x3a, 0xf7 } } + + ## Include/Protocol/ExtendedSalServiceClasses.h + gEfiExtendedSalBaseIoServicesProtocolGuid = { 0x5aea42b5, 0x31e1, 0x4515, {0xbc, 0x31, 0xb8, 0xd5, 0x25, 0x75, 0x65, 0xa6 } } + gEfiExtendedSalStallServicesProtocolGuid = { 0x53a58d06, 0xac27, 0x4d8c, {0xb5, 0xe9, 0xf0, 0x8a, 0x80, 0x65, 0x41, 0x70 } } + gEfiExtendedSalRtcServicesProtocolGuid = { 0x7e97a470, 0xefdb, 0x4d02, {0x8f, 0xce, 0x61, 0x90, 0xd2, 0x7b, 0xa2, 0x96 } } + gEfiExtendedSalVariableServicesProtocolGuid = { 0x4ecb6c53, 0xc641, 0x4370, {0x8c, 0xb2, 0x3b, 0x0e, 0x49, 0x6e, 0x83, 0x78 } } + gEfiExtendedSalMtcServicesProtocolGuid = { 0x899afd18, 0x75e8, 0x408b, {0xa4, 0x1a, 0x6e, 0x2e, 0x7e, 0xcd, 0xf4, 0x54 } } + gEfiExtendedSalResetServicesProtocolGuid = { 0x7d019990, 0x8ce1, 0x46f5, {0xa7, 0x76, 0x3c, 0x51, 0x98, 0x67, 0x6a, 0xa0 } } + gEfiExtendedSalStatusCodeServicesProtocolGuid = { 0xdbd91d, 0x55e9, 0x420f, {0x96, 0x39, 0x5e, 0x9f, 0x84, 0x37, 0xb4, 0x4f } } + gEfiExtendedSalFvBlockServicesProtocolGuid = { 0xa2271df1, 0xbcbb, 0x4f1d, {0x98, 0xa9, 0x06, 0xbc, 0x17, 0x2f, 0x07, 0x1a } } + gEfiExtendedSalMpServicesProtocolGuid = { 0x697d81a2, 0xcf18, 0x4dc0, {0x9e, 0x0d, 0x06, 0x11, 0x3b, 0x61, 0x8a, 0x3f } } + gEfiExtendedSalPalServicesProtocolGuid = { 0xe1cd9d21, 0x0fc2, 0x438d, {0x97, 0x03, 0x04, 0xe6, 0x6d, 0x96, 0x1e, 0x57 } } + gEfiExtendedSalBaseServicesProtocolGuid = { 0xd9e9fa06, 0x0fe0, 0x41c3, {0x96, 0xfb, 0x83, 0x42, 0x5a, 0x33, 0x94, 0xf8 } } + gEfiExtendedSalMcaServicesProtocolGuid = { 0x2a591128, 0x6cc7, 0x42b1, {0x8a, 0xf0, 0x58, 0x93, 0x3b, 0x68, 0x2d, 0xbb } } + gEfiExtendedSalPciServicesProtocolGuid = { 0xa46b1a31, 0xad66, 0x4905, {0x92, 0xf6, 0x2b, 0x46, 0x59, 0xdc, 0x30, 0x63 } } + gEfiExtendedSalCacheServicesProtocolGuid = { 0xedc9494, 0x2743, 0x4ba5, { 0x88, 0x18, 0x0a, 0xef, 0x52, 0x13, 0xf1, 0x88 } } + gEfiExtendedSalMcaLogServicesProtocolGuid = { 0xcb3fd86e, 0x38a3, 0x4c03, {0x9a, 0x5c, 0x90, 0xcf, 0xa3, 0xa2, 0xab, 0x7a } } + + # + # Protocols defined in PI 1.2.1 + # + + ## Include/Protocol/Security2.h + gEfiSecurity2ArchProtocolGuid = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } } + + ## Include/Protocol/SmmEndOfDxe.h + gEfiSmmEndOfDxeProtocolGuid = { 0x24e70042, 0xd5c5, 0x4260, { 0x8c, 0x39, 0xa, 0xd3, 0xaa, 0x32, 0xe9, 0x3d }} + + ## Include/Protocol/IsaHc.h + gEfiIsaHcProtocolGuid = { 0xbcdaf080, 0x1bde, 0x4e22, {0xae, 0x6a, 0x43, 0x54, 0x1e, 0x12, 0x8e, 0xc4 } } + gEfiIsaHcServiceBindingProtocolGuid = { 0xfad7933a, 0x6c21, 0x4234, {0xa4, 0x34, 0x0a, 0x8a, 0x0d, 0x2b, 0x07, 0x81 } } + + ## Include/Protocol/SuperIoControl.h + gEfiSioControlProtocolGuid = { 0xb91978df, 0x9fc1, 0x427d, { 0xbb, 0x5, 0x4c, 0x82, 0x84, 0x55, 0xca, 0x27 } } + + ## Include/Protocol/PiPcdInfo.h + gEfiGetPcdInfoProtocolGuid = { 0xfd0f4478, 0xefd, 0x461d, { 0xba, 0x2d, 0xe5, 0x8c, 0x45, 0xfd, 0x5f, 0x5e } } + + # + # Protocols defined in PI 1.3. + # + + ## Include/Protocol/I2cMaster.h + gEfiI2cMasterProtocolGuid = { 0xcd72881f, 0x45b5, 0x4feb, { 0x98, 0xc8, 0x31, 0x3d, 0xa8, 0x11, 0x74, 0x62 }} + + ## Include/Protocol/I2cIo.h + gEfiI2cIoProtocolGuid = { 0xb60a3e6b, 0x18c4, 0x46e5, { 0xa2, 0x9a, 0xc9, 0xa1, 0x06, 0x65, 0xa2, 0x8e }} + + ## Include/Protocol/I2cEnumerate.h + gEfiI2cEnumerateProtocolGuid = { 0xda8cd7c4, 0x1c00, 0x49e2, { 0x80, 0x3e, 0x52, 0x14, 0xe7, 0x01, 0x89, 0x4c }} + + ## Include/Protocol/I2cHost.h + gEfiI2cHostProtocolGuid = { 0xa5aab9e3, 0xc727, 0x48cd, { 0x8b, 0xbf, 0x42, 0x72, 0x33, 0x85, 0x49, 0x48 }} + + ## Include/Protocol/I2cBusConfigurationManagement.h + gEfiI2cBusConfigurationManagementProtocolGuid = { 0x55b71fb5, 0x17c6, 0x410e, { 0xb5, 0xbd, 0x5f, 0xa2, 0xe3, 0xd4, 0x46, 0x6b }} + + # + # Protocols defined in PI 1.5. + # + + ## Include/Protocol/MmEndOfDxe.h + gEfiMmEndOfDxeProtocolGuid = { 0x24e70042, 0xd5c5, 0x4260, { 0x8c, 0x39, 0xa, 0xd3, 0xaa, 0x32, 0xe9, 0x3d }} + + ## Include/Protocol/MmIoTrapDispatch.h + gEfiMmIoTrapDispatchProtocolGuid = { 0x58dc368d, 0x7bfa, 0x4e77, {0xab, 0xbc, 0xe, 0x29, 0x41, 0x8d, 0xf9, 0x30 }} + + ## Include/Protocol/MmPowerButtonDispatch.h + gEfiMmPowerButtonDispatchProtocolGuid = { 0x1b1183fa, 0x1823, 0x46a7, {0x88, 0x72, 0x9c, 0x57, 0x87, 0x55, 0x40, 0x9d }} + + ## Include/Protocol/MmStandbyButtonDispatch.h + gEfiMmStandbyButtonDispatchProtocolGuid = { 0x7300c4a1, 0x43f2, 0x4017, {0xa5, 0x1b, 0xc8, 0x1a, 0x7f, 0x40, 0x58, 0x5b }} + + ## Include/Protocol/MmGpiDispatch.h + gEfiMmGpiDispatchProtocolGuid = { 0x25566b03, 0xb577, 0x4cbf, {0x95, 0x8c, 0xed, 0x66, 0x3e, 0xa2, 0x43, 0x80 }} + + ## Include/Protocol/MmUsbDispatch.h + gEfiMmUsbDispatchProtocolGuid = { 0xee9b8d90, 0xc5a6, 0x40a2, {0xbd, 0xe2, 0x52, 0x55, 0x8d, 0x33, 0xcc, 0xa1 }} + + ## Include/Protocol/MmPeriodicTimerDispatch.h + gEfiMmPeriodicTimerDispatchProtocolGuid = { 0x4cec368e, 0x8e8e, 0x4d71, {0x8b, 0xe1, 0x95, 0x8c, 0x45, 0xfc, 0x8a, 0x53 }} + + ## Include/Protocol/MmSxDispatch.h + gEfiMmSxDispatchProtocolGuid = { 0x456d2859, 0xa84b, 0x4e47, {0xa2, 0xee, 0x32, 0x76, 0xd8, 0x86, 0x99, 0x7d }} + + ## Include/Protocol/MmSwDispatch.h + gEfiMmSwDispatchProtocolGuid = { 0x18a3c6dc, 0x5eea, 0x48c8, {0xa1, 0xc1, 0xb5, 0x33, 0x89, 0xf9, 0x89, 0x99 }} + + ## Include/Protocol/MmPciRootBridgeIo.h + gEfiMmPciRootBridgeIoProtocolGuid = { 0x8bc1714d, 0xffcb, 0x41c3, { 0x89, 0xdc, 0x6c, 0x74, 0xd0, 0x6d, 0x98, 0xea }} + + ## Include/Protocol/MmCpu.h + gEfiMmCpuProtocolGuid = { 0xeb346b97, 0x975f, 0x4a9f, { 0x8b, 0x22, 0xf8, 0xe9, 0x2b, 0xb3, 0xd5, 0x69 }} + + ## Include/Protocol/MmStatusCode.h + gEfiMmStatusCodeProtocolGuid = { 0x6afd2b77, 0x98c1, 0x4acd, { 0xa6, 0xf9, 0x8a, 0x94, 0x39, 0xde, 0xf, 0xb1}} + + ## Include/Protocol/DxeMmReadyToLock.h + gEfiDxeMmReadyToLockProtocolGuid = { 0x60ff8964, 0xe906, 0x41d0, { 0xaf, 0xed, 0xf2, 0x41, 0xe9, 0x74, 0xe0, 0x8e }} + + ## Include/Protocol/MmConfiguration.h + gEfiMmConfigurationProtocolGuid= { 0x26eeb3de, 0xb689, 0x492e, { 0x80, 0xf0, 0xbe, 0x8b, 0xd7, 0xda, 0x4b, 0xa7 }} + + ## Include/Protocol/MmReadyToLock.h + gEfiMmReadyToLockProtocolGuid = { 0x47b7fa8c, 0xf4bd, 0x4af6, { 0x82, 0x00, 0x33, 0x30, 0x86, 0xf0, 0xd2, 0xc8 }} + + ## Include/Protocol/MmControl.h + gEfiMmControlProtocolGuid = { 0x843dc720, 0xab1e, 0x42cb, { 0x93, 0x57, 0x8a, 0x0, 0x78, 0xf3, 0x56, 0x1b}} + + ## Include/Protocol/MmAccess.h + gEfiMmAccessProtocolGuid = { 0xc2702b74, 0x800c, 0x4131, { 0x87, 0x46, 0x8f, 0xb5, 0xb8, 0x9c, 0xe4, 0xac }} + + ## Include/Protocol/MmBase.h + gEfiMmBaseProtocolGuid = { 0xf4ccbfb7, 0xf6e0, 0x47fd, { 0x9d, 0xd4, 0x10, 0xa8, 0xf1, 0x50, 0xc1, 0x91 }} + + ## Include/Protocol/MmCpuIo.h + gEfiMmCpuIoProtocolGuid = { 0x3242a9d8, 0xce70, 0x4aa0, { 0x95, 0x5d, 0x5e, 0x7b, 0x14, 0x0d, 0xe4, 0xd2 }} + + ## Include/Protocol/MmReportStatusCodeHandler.h + gEfiMmRscHandlerProtocolGuid = { 0x2ff29fa7, 0x5e80, 0x4ed9, { 0xb3, 0x80, 0x1, 0x7d, 0x3c, 0x55, 0x4f, 0xf4 }} + + ## Include/Protocol/MmCommunication.h + gEfiMmCommunicationProtocolGuid = { 0xc68ed8e2, 0x9dc6, 0x4cbd, { 0x9d, 0x94, 0xdb, 0x65, 0xac, 0xc5, 0xc3, 0x32 }} + + # + # Protocols defined in PI 1.6. + # + + ## Include/Protocol/LegacySpiController.h + gEfiLegacySpiControllerProtocolGuid = { 0x39136fc7, 0x1a11, 0x49de, { 0xbf, 0x35, 0x0e, 0x78, 0xdd, 0xb5, 0x24, 0xfc }} + + ## Include/Protocol/LegacySpiFlash.h + gEfiLegacySpiFlashProtocolGuid = { 0xf01bed57, 0x04bc, 0x4f3f, { 0x96, 0x60, 0xd6, 0xf2, 0xea, 0x22, 0x82, 0x59 }} + + ## Include/Protocol/LegacySpiSmmController.h + gEfiLegacySpiSmmControllerProtocolGuid = { 0x62331b78, 0xd8d0, 0x4c8c, { 0x8c, 0xcb, 0xd2, 0x7d, 0xfe, 0x32, 0xdb, 0x9b }} + + ## Include/Protocol/LegacySpiSmmFlash.h + gEfiLegacySpiSmmFlashProtocolGuid = { 0x5e3848d4, 0x0db5, 0x4fc0, { 0x97, 0x29, 0x3f, 0x35, 0x3d, 0x4f, 0x87, 0x9f }} + + ## Include/Protocol/SpiConfiguration.h + gEfiSpiConfigurationProtocolGuid = { 0x85a6d3e6, 0xb65b, 0x4afc, { 0xb3, 0x8f, 0xc6, 0xd5, 0x4a, 0xf6, 0xdd, 0xc8 }} + + ## Include/Protocol/SpiHc.h + gEfiSpiHcProtocolGuid = { 0xc74e5db2, 0xfa96, 0x4ae2, { 0xb3, 0x99, 0x15, 0x97, 0x7f, 0xe3, 0x0, 0x2d }} + + ## Include/Protocol/SpiNorFlash.h + gEfiSpiNorFlashProtocolGuid = { 0xb57ec3fe, 0xf833, 0x4ba6, { 0x85, 0x78, 0x2a, 0x7d, 0x6a, 0x87, 0x44, 0x4b }} + + ## Include/Protocol/SpiSmmConfiguration.h + gEfiSpiSmmConfigurationProtocolGuid = { 0x995c6eca, 0x171b, 0x45fd, { 0xa3, 0xaa, 0xfd, 0x4c, 0x9c, 0x9d, 0xef, 0x59 }} + + ## Include/Protocol/SpiSmmHc.h + gEfiSpiSmmHcProtocolGuid = { 0xe9f02217, 0x2093, 0x4470, { 0x8a, 0x54, 0x5c, 0x2c, 0xff, 0xe7, 0x3e, 0xcb }} + + ## Include/Protocol/SpiSmmNorFlash.h + gEfiSpiSmmNorFlashProtocolGuid = { 0xaab18f19, 0xfe14, 0x4666, { 0x86, 0x04, 0x87, 0xff, 0x6d, 0x66, 0x2c, 0x9a }} + + # + # Protocols defined in UEFI2.1/UEFI2.0/EFI1.1 + # + + ## Include/Protocol/DebugPort.h + gEfiDebugPortProtocolGuid = { 0xEBA4E8D2, 0x3858, 0x41EC, { 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 }} + + ## Include/Protocol/DebugSupport.h + gEfiDebugSupportProtocolGuid = { 0x2755590C, 0x6F3C, 0x42FA, { 0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 }} + + ## Include/Protocol/Decompress.h + gEfiDecompressProtocolGuid = { 0xD8117CFE, 0x94A6, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/DeviceIo.h + gEfiDeviceIoProtocolGuid = { 0xAF6AC311, 0x84C3, 0x11D2, { 0x8E, 0x3C, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/DevicePath.h + gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/DevicePathFromText.h + gEfiDevicePathFromTextProtocolGuid = { 0x05C99A21, 0xC70F, 0x4AD2, { 0x8A, 0x5F, 0x35, 0xDF, 0x33, 0x43, 0xF5, 0x1E }} + + ## Include/Protocol/DevicePathToText.h + gEfiDevicePathToTextProtocolGuid = { 0x8B843E20, 0x8132, 0x4852, { 0x90, 0xCC, 0x55, 0x1A, 0x4E, 0x4A, 0x7F, 0x1C }} + + ## Include/Protocol/DevicePathUtilities.h + gEfiDevicePathUtilitiesProtocolGuid = { 0x0379BE4E, 0xD706, 0x437D, { 0xB0, 0x37, 0xED, 0xB8, 0x2F, 0xB7, 0x72, 0xA4 }} + + ## Include/Protocol/DriverBinding.h + gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }} + + ## Include/Protocol/PlatformDriverOverride.h + gEfiPlatformDriverOverrideProtocolGuid = { 0x6b30c738, 0xa391, 0x11d4, {0x9a, 0x3b, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + + ## Include/Protocol/DriverFamilyOverride.h + gEfiDriverFamilyOverrideProtocolGuid = { 0xb1ee129e, 0xda36, 0x4181, { 0x91, 0xf8, 0x4, 0xa4, 0x92, 0x37, 0x66, 0xa7 }} + + ## Include/Protocol/BusSpecificDriverOverride.h + gEfiBusSpecificDriverOverrideProtocolGuid = { 0x3BC1B285, 0x8A15, 0x4A82, { 0xAA, 0xBF, 0x4D, 0x7D, 0x13, 0xFB, 0x32, 0x65 }} + + ## Include/Protocol/DriverDiagnostics2.h + gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x90, 0xD8, 0x5E, 0xD9, 0x00, 0x17, 0x3B, 0x63 }} + + ## Include/Protocol/DriverDiagnostics.h + gEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/ComponentName2.h + gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }} + + ## Include/Protocol/ComponentName.h + gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/DriverConfiguration2.h + gEfiDriverConfiguration2ProtocolGuid = { 0xBFD7DC1D, 0x24F1, 0x40D9, { 0x82, 0xE7, 0x2E, 0x09, 0xBB, 0x6B, 0x4E, 0xBE }} + + ## Include/Protocol/DriverConfiguration.h + gEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/PlatformToDriverConfiguration.h + gEfiPlatformToDriverConfigurationProtocolGuid = { 0x642cd590, 0x8059, 0x4c0a, { 0xa9, 0x58, 0xc5, 0xec, 0x7, 0xd2, 0x3c, 0x4b } } + + ## Include/Protocol/DriverSupportedEfiVersion.h + gEfiDriverSupportedEfiVersionProtocolGuid = { 0x5c198761, 0x16a8, 0x4e69, { 0x97, 0x2c, 0x89, 0xd6, 0x79, 0x54, 0xf8, 0x1d } } + + ## Include/Protocol/SimpleTextIn.h + gEfiSimpleTextInProtocolGuid = { 0x387477C1, 0x69C7, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/SimpleTextInEx.h + gEfiSimpleTextInputExProtocolGuid = {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } + + ## Include/Protocol/SimpleTextOut.h + gEfiSimpleTextOutProtocolGuid = { 0x387477C2, 0x69C7, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/SimplePointer.h + gEfiSimplePointerProtocolGuid = { 0x31878C87, 0x0B75, 0x11D5, { 0x9A, 0x4F, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/AbsolutePointer.h + gEfiAbsolutePointerProtocolGuid = { 0x8D59D32B, 0xC655, 0x4AE9, { 0x9B, 0x15, 0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43 } } + + ## Include/Protocol/SerialIo.h + gEfiSerialIoProtocolGuid = { 0xBB25CF6F, 0xF1D4, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD }} + + ## Include/Protocol/GraphicsOutput.h + gEfiGraphicsOutputProtocolGuid = { 0x9042A9DE, 0x23DC, 0x4A38, { 0x96, 0xFB, 0x7A, 0xDE, 0xD0, 0x80, 0x51, 0x6A }} + + ## Include/Protocol/EdidDiscovered.h + gEfiEdidDiscoveredProtocolGuid = { 0x1C0C34F6, 0xD380, 0x41FA, { 0xA0, 0x49, 0x8A, 0xD0, 0x6C, 0x1A, 0x66, 0xAA }} + + ## Include/Protocol/EdidActive.h + gEfiEdidActiveProtocolGuid = { 0xBD8C1056, 0x9F36, 0x44EC, { 0x92, 0xA8, 0xA6, 0x33, 0x7F, 0x81, 0x79, 0x86 }} + + ## Include/Protocol/EdidOverride.h + gEfiEdidOverrideProtocolGuid = { 0x48ECB431, 0xFB72, 0x45C0, { 0xA9, 0x22, 0xF4, 0x58, 0xFE, 0x04, 0x0B, 0xD5 }} + + ## Include/Protocol/UgaIo.h + gEfiUgaIoProtocolGuid = { 0x61A4D49E, 0x6F68, 0x4F1B, { 0xB9, 0x22, 0xA8, 0x6E, 0xED, 0x0B, 0x07, 0xA2 }} + + ## Include/Protocol/UgaDraw.h + gEfiUgaDrawProtocolGuid = { 0x982C298B, 0xF4FA, 0x41CB, { 0xB8, 0x38, 0x77, 0xAA, 0x68, 0x8F, 0xB8, 0x39 }} + + ## Include/Protocol/LoadedImage.h + gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/LoadedImage.h + gEfiLoadedImageDevicePathProtocolGuid = { 0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf }} + + ## Include/Protocol/LoadFile.h + gEfiLoadFileProtocolGuid = { 0x56EC3091, 0x954C, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/LoadFile2.h + gEfiLoadFile2ProtocolGuid = { 0x4006c0c1, 0xfcb3, 0x403e, {0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d }} + + ## Include/Protocol/SimpleFileSystem.h + gEfiSimpleFileSystemProtocolGuid = { 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/TapeIo.h + gEfiTapeIoProtocolGuid = { 0x1E93E633, 0xD65A, 0x459E, { 0xAB, 0x84, 0x93, 0xD9, 0xEC, 0x26, 0x6D, 0x18 }} + + ## Include/Protocol/DiskIo.h + gEfiDiskIoProtocolGuid = { 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/BlockIo.h + gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/UnicodeCollation.h + gEfiUnicodeCollationProtocolGuid = { 0x1D85CD7F, 0xF43D, 0x11D2, { 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/UnicodeCollation.h + gEfiUnicodeCollation2ProtocolGuid = {0xa4c751fc, 0x23ae, 0x4c3e, { 0x92, 0xe9, 0x49, 0x64, 0xcf, 0x63, 0xf3, 0x49 }} + + ## Include/Protocol/PciRootBridgeIo.h + gEfiPciRootBridgeIoProtocolGuid = { 0x2F707EBB, 0x4A1A, 0x11D4, { 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/PciIo.h + gEfiPciIoProtocolGuid = { 0x4CF5B200, 0x68B8, 0x4CA5, { 0x9E, 0xEC, 0xB2, 0x3E, 0x3F, 0x50, 0x02, 0x9A }} + + ## Include/Protocol/ScsiIo.h + gEfiScsiIoProtocolGuid = { 0x932F47e6, 0x2362, 0x4002, { 0x80, 0x3E, 0x3C, 0xD5, 0x4B, 0x13, 0x8F, 0x85 }} + + ## Include/Protocol/ScsiPassThruExt.h + gEfiExtScsiPassThruProtocolGuid = { 0x143b7632, 0xb81b, 0x4cb7, {0xab, 0xd3, 0xb6, 0x25, 0xa5, 0xb9, 0xbf, 0xfe }} + + ## Include/Protocol/ScsiPassThru.h + gEfiScsiPassThruProtocolGuid = { 0xA59E8FCF, 0xBDA0, 0x43BB, { 0x90, 0xB1, 0xD3, 0x73, 0x2E, 0xCA, 0xA8, 0x77 }} + + ## Include/Protocol/IScsiInitiatorName.h + gEfiIScsiInitiatorNameProtocolGuid = { 0x59324945, 0xEC44, 0x4C0D, { 0xB1, 0xCD, 0x9D, 0xB1, 0x39, 0xDF, 0x07, 0x0C }} + + ## Include/Protocol/Usb2HostController.h + gEfiUsb2HcProtocolGuid = { 0x3E745226, 0x9818, 0x45B6, { 0xA2, 0xAC, 0xD7, 0xCD, 0x0E, 0x8B, 0xA2, 0xBC }} + + ## Include/Protocol/UsbHostController.h + gEfiUsbHcProtocolGuid = { 0xF5089266, 0x1AA0, 0x4953, { 0x97, 0xD8, 0x56, 0x2F, 0x8A, 0x73, 0xB5, 0x19 }} + + ## Include/Protocol/UsbIo.h + gEfiUsbIoProtocolGuid = { 0x2B2F68D6, 0x0CD2, 0x44CF, { 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 }} + + ## Include/Protocol/AcpiTable.h + gEfiAcpiTableProtocolGuid = { 0xFFE06BDD, 0x6107, 0x46A6, { 0x7B, 0xB2, 0x5A, 0x9C, 0x7E, 0xC5, 0x27, 0x5C }} + + ## Include/Protocol/Ebc.h + gEfiEbcProtocolGuid = { 0x13AC6DD1, 0x73D0, 0x11D4, { 0xB0, 0x6B, 0x00, 0xAA, 0x00, 0xBD, 0x6D, 0xE7 }} + + ## Include/Protocol/SimpleNetwork.h + gEfiSimpleNetworkProtocolGuid = { 0xA19832B9, 0xAC25, 0x11D3, { 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/NetworkInterfaceIdentifier.h + gEfiNetworkInterfaceIdentifierProtocolGuid_31 = { 0x1ACED566, 0x76ED, 0x4218, { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }} + + ## Include/Protocol/NetworkInterfaceIdentifier.h + gEfiNetworkInterfaceIdentifierProtocolGuid = { 0xE18541CD, 0xF755, 0x4F73, { 0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29 }} + + ## Include/Protocol/PxeBaseCodeCallBack.h + gEfiPxeBaseCodeCallbackProtocolGuid = { 0x245DCA21, 0xFB7B, 0x11D3, { 0x8F, 0x01, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }} + + ## Include/Protocol/PxeBaseCode.h + gEfiPxeBaseCodeProtocolGuid = { 0x03C4E603, 0xAC28, 0x11D3, { 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} + + ## Include/Protocol/Bis.h + gEfiBisProtocolGuid = { 0x0B64AAB0, 0x5429, 0x11D4, { 0x98, 0x16, 0x00, 0xA0, 0xC9, 0x1F, 0xAD, 0xCF }} + + ## Include/Protocol/ManagedNetwork.h + gEfiManagedNetworkServiceBindingProtocolGuid = { 0xF36FF770, 0xA7E1, 0x42CF, { 0x9E, 0xD2, 0x56, 0xF0, 0xF2, 0x71, 0xF4, 0x4C }} + + ## Include/Protocol/ManagedNetwork.h + gEfiManagedNetworkProtocolGuid = { 0x7ab33a91, 0xace5, 0x4326, { 0xb5, 0x72, 0xe7, 0xee, 0x33, 0xd3, 0x9f, 0x16 }} + + ## Include/Protocol/Arp.h + gEfiArpServiceBindingProtocolGuid = { 0xF44C00EE, 0x1F2C, 0x4A00, { 0xAA, 0x09, 0x1C, 0x9F, 0x3E, 0x08, 0x00, 0xA3 }} + + ## Include/Protocol/Arp.h + gEfiArpProtocolGuid = { 0xF4B427BB, 0xBA21, 0x4F16, { 0xBC, 0x4E, 0x43, 0xE4, 0x16, 0xAB, 0x61, 0x9C }} + + ## Include/Protocol/Dhcp4.h + gEfiDhcp4ServiceBindingProtocolGuid = { 0x9D9A39D8, 0xBD42, 0x4A73, { 0xA4, 0xD5, 0x8E, 0xE9, 0x4B, 0xE1, 0x13, 0x80 }} + + ## Include/Protocol/Dhcp4.h + gEfiDhcp4ProtocolGuid = { 0x8A219718, 0x4EF5, 0x4761, { 0x91, 0xC8, 0xC0, 0xF0, 0x4B, 0xDA, 0x9E, 0x56 }} + + ## Include/Protocol/Tcp4.h + gEfiTcp4ServiceBindingProtocolGuid = { 0x00720665, 0x67EB, 0x4A99, { 0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9 }} + + ## Include/Protocol/Tcp4.h + gEfiTcp4ProtocolGuid = { 0x65530BC7, 0xA359, 0x410F, { 0xB0, 0x10, 0x5A, 0xAD, 0xC7, 0xEC, 0x2B, 0x62 }} + + ## Include/Protocol/Ip4.h + gEfiIp4ServiceBindingProtocolGuid = { 0xC51711E7, 0xB4BF, 0x404A, { 0xBF, 0xB8, 0x0A, 0x04, 0x8E, 0xF1, 0xFF, 0xE4 }} + + ## Include/Protocol/Ip4.h + gEfiIp4ProtocolGuid = { 0x41D94CD2, 0x35B6, 0x455A, { 0x82, 0x58, 0xD4, 0xE5, 0x13, 0x34, 0xAA, 0xDD }} + + ## Include/Protocol/Ip4Config.h + gEfiIp4ConfigProtocolGuid = { 0x3B95AA31, 0x3793, 0x434B, { 0x86, 0x67, 0xC8, 0x07, 0x08, 0x92, 0xE0, 0x5E }} + + ## Include/Protocol/Udp4.h + gEfiUdp4ServiceBindingProtocolGuid = { 0x83F01464, 0x99BD, 0x45E5, { 0xB3, 0x83, 0xAF, 0x63, 0x05, 0xD8, 0xE9, 0xE6 }} + + ## Include/Protocol/Udp4.h + gEfiUdp4ProtocolGuid = { 0x3AD9DF29, 0x4501, 0x478D, { 0xB1, 0xF8, 0x7F, 0x7F, 0xE7, 0x0E, 0x50, 0xF3 }} + + ## Include/Protocol/Mtftp4.h + gEfiMtftp4ServiceBindingProtocolGuid = { 0x2FE800BE, 0x8F01, 0x4AA6, { 0x94, 0x6B, 0xD7, 0x13, 0x88, 0xE1, 0x83, 0x3F }} + + ## Include/Protocol/Mtftp4.h + gEfiMtftp4ProtocolGuid = { 0x78247C57, 0x63DB, 0x4708, { 0x99, 0xC2, 0xA8, 0xB4, 0xA9, 0xA6, 0x1F, 0x6B }} + + ## Include/Protocol/AuthenticationInfo.h + gEfiAuthenticationInfoProtocolGuid = { 0x7671D9D0, 0x53DB, 0x4173, { 0xAA, 0x69, 0x23, 0x27, 0xF2, 0x1F, 0x0B, 0xC7 }} + + ## Include/Protocol/Hash.h + gEfiHashServiceBindingProtocolGuid = { 0x42881c98, 0xa4f3, 0x44b0, { 0xa3, 0x9d, 0xdf, 0xa1, 0x86, 0x67, 0xd8, 0xcd }} + + ## Include/Protocol/Hash.h + gEfiHashProtocolGuid = { 0xC5184932, 0xDBA5, 0x46DB, { 0xA5, 0xBA, 0xCC, 0x0B, 0xDA, 0x9C, 0x14, 0x35 }} + + ## Include/Protocol/TcgService.h + gEfiTcgProtocolGuid = { 0xf541796d, 0xa62e, 0x4954, { 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }} + + ## Include/Protocol/TrEEProtocol.h + gEfiTrEEProtocolGuid = {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }} + + ## Include/Protocol/Tcg2Protocol.h + gEfiTcg2ProtocolGuid = {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }} + gEfiTcg2FinalEventsTableGuid = {0x1e2ed096, 0x30e2, 0x4254, { 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25 }} + + ## Include/Protocol/FormBrowser2.h + gEfiFormBrowser2ProtocolGuid = {0xb9d4c360, 0xbcfb, 0x4f9b, {0x92, 0x98, 0x53, 0xc1, 0x36, 0x98, 0x22, 0x58}} + + ## Include/Protocol/HiiString.h + gEfiHiiStringProtocolGuid = {0x0fd96974, 0x23aa, 0x4cdc, {0xb9, 0xcb, 0x98, 0xd1, 0x77, 0x50, 0x32, 0x2a}} + + ## Include/Protocol/HiiImage.h + gEfiHiiImageProtocolGuid = {0x31a6406a, 0x6bdf, 0x4e46, {0xb2, 0xa2, 0xeb, 0xaa, 0x89, 0xc4, 0x09, 0x20}} + + ## Include/Protocol/HiiConfigRouting.h + gEfiHiiConfigRoutingProtocolGuid = {0x587e72d7, 0xcc50, 0x4f79, {0x82, 0x09, 0xca, 0x29, 0x1f, 0xc1, 0xa1, 0x0f}} + + ## Include/Protocol/HiiDatabase.h + gEfiHiiDatabaseProtocolGuid = {0xef9fc172, 0xa1b2, 0x4693, {0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42}} + + ## Include/Protocol/HiiFont.h + gEfiHiiFontProtocolGuid = {0xe9ca4775, 0x8657, 0x47fc, {0x97, 0xe7, 0x7e, 0xd6, 0x5a, 0x08, 0x43, 0x24}} + + ## Include/Protocol/HiiConfigAccess.h + gEfiHiiConfigAccessProtocolGuid = {0x330d4706, 0xf2a0, 0x4e4f, {0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85}} + + ## Include/Protocol/HiiPackageList.h + gEfiHiiPackageListProtocolGuid = { 0x6a1ee763, 0xd47a, 0x43b4, {0xaa, 0xbe, 0xef, 0x1d, 0xe2, 0xab, 0x56, 0xfc}} + + # + # Protocols defined in UEFI2.2 + # + ## Include/Protocol/Ip6.h + gEfiIp6ServiceBindingProtocolGuid = { 0xec835dd3, 0xfe0f, 0x617b, {0xa6, 0x21, 0xb3, 0x50, 0xc3, 0xe1, 0x33, 0x88 }} + + ## Include/Protocol/Ip6.h + gEfiIp6ProtocolGuid = { 0x2c8759d5, 0x5c2d, 0x66ef, {0x92, 0x5f, 0xb6, 0x6c, 0x10, 0x19, 0x57, 0xe2 }} + + ## Include/Protocol/Ip6Config.h + gEfiIp6ConfigProtocolGuid = { 0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a }} + + ## Include/Protocol/Mtftp6.h + gEfiMtftp6ServiceBindingProtocolGuid = { 0xd9760ff3, 0x3cca, 0x4267, {0x80, 0xf9, 0x75, 0x27, 0xfa, 0xfa, 0x42, 0x23 }} + + ## Include/Protocol/Mtftp6.h + gEfiMtftp6ProtocolGuid = { 0xbf0a78ba, 0xec29, 0x49cf, {0xa1, 0xc9, 0x7a, 0xe5, 0x4e, 0xab, 0x6a, 0x51 }} + + ## Include/Protocol/Dhcp6.h + gEfiDhcp6ServiceBindingProtocolGuid = { 0x9fb9a8a1, 0x2f4a, 0x43a6, {0x88, 0x9c, 0xd0, 0xf7, 0xb6, 0xc4, 0x7a, 0xd5 }} + + ## Include/Protocol/Dhcp6.h + gEfiDhcp6ProtocolGuid = { 0x87c8bad7, 0x595, 0x4053, {0x82, 0x97, 0xde, 0xde, 0x39, 0x5f, 0x5d, 0x5b }} + + ## Include/Protocol/Udp6.h + gEfiUdp6ServiceBindingProtocolGuid = { 0x66ed4721, 0x3c98, 0x4d3e, {0x81, 0xe3, 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54 }} + + ## Include/Protocol/Udp6.h + gEfiUdp6ProtocolGuid = { 0x4f948815, 0xb4b9, 0x43cb, {0x8a, 0x33, 0x90, 0xe0, 0x60, 0xb3, 0x49, 0x55 }} + + ## Include/Protocol/Tcp6.h + gEfiTcp6ServiceBindingProtocolGuid = { 0xec20eb79, 0x6c1a, 0x4664, {0x9a, 0x0d, 0xd2, 0xe4, 0xcc, 0x16, 0xd6, 0x64 }} + + ## Include/Protocol/Tcp6.h + gEfiTcp6ProtocolGuid = { 0x46e44855, 0xbd60, 0x4ab7, {0xab, 0x0d, 0xa6, 0x79, 0xb9, 0x44, 0x7d, 0x77 }} + + ## Include/Protocol/VlanConfig.h + gEfiVlanConfigProtocolGuid = { 0x9e23d768, 0xd2f3, 0x4366, {0x9f, 0xc3, 0x3a, 0x7a, 0xba, 0x86, 0x43, 0x74 }} + + ## Include/Protocol/Eap.h + gEfiEapProtocolGuid = { 0x5d9f96db, 0xe731, 0x4caa, {0xa0, 0xd, 0x72, 0xe1, 0x87, 0xcd, 0x77, 0x62 }} + + ## Include/Protocol/EapManagement.h + gEfiEapManagementProtocolGuid = { 0xbb62e663, 0x625d, 0x40b2, {0xa0, 0x88, 0xbb, 0xe8, 0x36, 0x23, 0xa2, 0x45 }} + + ## Include/Protocol/Ftp4.h + gEfiFtp4ServiceBindingProtocolGuid = { 0xfaaecb1, 0x226e, 0x4782, {0xaa, 0xce, 0x7d, 0xb9, 0xbc, 0xbf, 0x4d, 0xaf }} + + ## Include/Protocol/Ftp4.h + gEfiFtp4ProtocolGuid = { 0xeb338826, 0x681b, 0x4295, {0xb3, 0x56, 0x2b, 0x36, 0x4c, 0x75, 0x7b, 0x9 }} + + ## Include/Protocol/IpSecConfig.h + gEfiIpSecConfigProtocolGuid = { 0xce5e5929, 0xc7a3, 0x4602, {0xad, 0x9e, 0xc9, 0xda, 0xf9, 0x4e, 0xbf, 0xcf }} + + ## Include/Protocol/DriverHealth.h + gEfiDriverHealthProtocolGuid = { 0x2a534210, 0x9280, 0x41d8, {0xae, 0x79, 0xca, 0xda, 0x1, 0xa2, 0xb1, 0x27 }} + + ## Include/Protocol/DeferredImageLoad.h + gEfiDeferredImageLoadProtocolGuid = { 0x15853d7c, 0x3ddf, 0x43e0, {0xa1, 0xcb, 0xeb, 0xf8, 0x5b, 0x8f, 0x87, 0x2c }} + + ## Include/Protocol/UserCredential.h + gEfiUserCredentialProtocolGuid = { 0x71ee5e94, 0x65b9, 0x45d5, {0x82, 0x1a, 0x3a, 0x4d, 0x86, 0xcf, 0xe6, 0xbe }} + + ## Include/Protocol/UserManager.h + gEfiUserManagerProtocolGuid = { 0x6fd5b00c, 0xd426, 0x4283, {0x98, 0x87, 0x6c, 0xf5, 0xcf, 0x1c, 0xb1, 0xfe }} + + ## Include/Protocol/AtaPassThru.h + gEfiAtaPassThruProtocolGuid = { 0x1d3de7f0, 0x807, 0x424f, {0xaa, 0x69, 0x11, 0xa5, 0x4e, 0x19, 0xa4, 0x6f }} + + # + # Protocols defined in UEFI2.3 + # + ## Include/Protocol/FirmwareManagement.h + gEfiFirmwareManagementProtocolGuid = { 0x86c77a67, 0xb97, 0x4633, {0xa1, 0x87, 0x49, 0x10, 0x4d, 0x6, 0x85, 0xc7 }} + + ## Include/Protocol/IpSec.h + gEfiIpSecProtocolGuid = { 0xdfb386f7, 0xe100, 0x43ad, {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 }} + + ## Include/Protocol/IpSec.h + gEfiIpSec2ProtocolGuid = { 0xa3979e64, 0xace8, 0x4ddc, {0xbc, 0x7, 0x4d, 0x66, 0xb8, 0xfd, 0x9, 0x77 }} + + # + # Protocols defined in UEFI2.3.1 + # + ## Include/Protocol/Kms.h + gEfiKmsProtocolGuid = { 0xEC3A978D, 0x7C4E, 0x48FA, {0x9A, 0xBE, 0x6A, 0xD9, 0x1C, 0xC8, 0xF8, 0x11 }} + + ## Include/Protocol/BlockIo2.h + gEfiBlockIo2ProtocolGuid = { 0xa77b2472, 0xe282, 0x4e9f, {0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1 }} + + ## Include/Protocol/StorageSecurityCommand.h + gEfiStorageSecurityCommandProtocolGuid = { 0xc88b0b6d, 0x0dfc, 0x49a7, {0x9c, 0xb4, 0x49, 0x7, 0x4b, 0x4c, 0x3a, 0x78 }} + + ## Include/Protocol/UserCredential2.h + gEfiUserCredential2ProtocolGuid = { 0xe98adb03, 0xb8b9, 0x4af8, {0xba, 0x20, 0x26, 0xe9, 0x11, 0x4c, 0xbc, 0xe5 }} + + # + # Protocols defined in UEFI2.4 + # + ## Include/Protocol/DiskIo2.h + gEfiDiskIo2ProtocolGuid = { 0x151c8eae, 0x7f2c, 0x472c, { 0x9e, 0x54, 0x98, 0x28, 0x19, 0x4f, 0x6a, 0x88 }} + + ## Include/Protocol/Timestamp.h + gEfiTimestampProtocolGuid = { 0xafbfde41, 0x2e6e, 0x4262, {0xba, 0x65, 0x62, 0xb9, 0x23, 0x6e, 0x54, 0x95 }} + + ## Include/Protocol/Rng.h + gEfiRngProtocolGuid = { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 }} + + ## Include/Protocol/AdapterInformation.h + gEfiAdapterInformationProtocolGuid = { 0xE5DD1403, 0xD622, 0xC24E, {0x84, 0x88, 0xC7, 0x1B, 0x17, 0xF5, 0xE8, 0x02 }} + + # + # Protocols defined in UEFI2.5 + # + ## Include/Protocol/NvmExpressPassthru.h + gEfiNvmExpressPassThruProtocolGuid = { 0x52c78312, 0x8edc, 0x4233, { 0x98, 0xf2, 0x1a, 0x1a, 0xa5, 0xe3, 0x88, 0xa5 }} + + ## Include/Protocol/Hash2.h + gEfiHash2ServiceBindingProtocolGuid = { 0xda836f8d, 0x217f, 0x4ca0, { 0x99, 0xc2, 0x1c, 0xa4, 0xe1, 0x60, 0x77, 0xea }} + + ## Include/Protocol/Hash2.h + gEfiHash2ProtocolGuid = { 0x55b1d734, 0xc5e1, 0x49db, { 0x96, 0x47, 0xb1, 0x6a, 0xfb, 0xe, 0x30, 0x5b }} + + ## Include/Protocol/BlockIoCrypto.h + gEfiBlockIoCryptoProtocolGuid = { 0xa00490ba, 0x3f1a, 0x4b4c, { 0xab, 0x90, 0x4f, 0xa9, 0x97, 0x26, 0xa1, 0xe8 }} + + ## Include/Protocol/SmartCardReader.h + gEfiSmartCardReaderProtocolGuid = { 0x2a4d1adf, 0x21dc, 0x4b81, {0xa4, 0x2f, 0x8b, 0x8e, 0xe2, 0x38, 0x00, 0x60 }} + + ## Include/Protocol/SmartCardEdge.h + gEfiSmartCardEdgeProtocolGuid = { 0xd317f29b, 0xa325, 0x4712, {0x9b, 0xf1, 0xc6, 0x19, 0x54, 0xdc, 0x19, 0x8c }} + + ## Include/Protocol/UsbFunctionIo.h + gEfiUsbFunctionIoProtocolGuid = { 0x32d2963a, 0xfe5d, 0x4f30, {0xb6, 0x33, 0x6e, 0x5d, 0xc5, 0x58, 0x3, 0xcc }} + + ## Include/Protocol/BluetoothHc.h + gEfiBluetoothHcProtocolGuid = { 0xb3930571, 0xbeba, 0x4fc5, { 0x92, 0x3, 0x94, 0x27, 0x24, 0x2e, 0x6a, 0x43 }} + + ## Include/Protocol/BluetoothIo.h + gEfiBluetoothIoServiceBindingProtocolGuid = { 0x388278d3, 0x7b85, 0x42f0, { 0xab, 0xa9, 0xfb, 0x4b, 0xfd, 0x69, 0xf5, 0xab }} + gEfiBluetoothIoProtocolGuid = { 0x467313de, 0x4e30, 0x43f1, { 0x94, 0x3e, 0x32, 0x3f, 0x89, 0x84, 0x5d, 0xb5 }} + + ## Include/Protocol/BluetoothConfig.h + gEfiBluetoothConfigProtocolGuid = { 0x62960cf3, 0x40ff, 0x4263, { 0xa7, 0x7c, 0xdf, 0xde, 0xbd, 0x19, 0x1b, 0x4b }} + + ## Include/Protocol/RegularExpressionProtocol.h + gEfiRegularExpressionProtocolGuid = { 0xB3F79D9A, 0x436C, 0xDC11, {0xB0, 0x52, 0xCD, 0x85, 0xDF, 0x52, 0x4C, 0xE6 }} + + ## Include/Protocol/BootManagerPolicy.h + gEfiBootManagerPolicyProtocolGuid = { 0xfedf8e0c, 0xe147, 0x11e3, { 0x99, 0x03, 0xb8, 0xe8, 0x56, 0x2c, 0xba, 0xfa }} + + ## Include/Protocol/HiiConfigKeyword.h + gEfiConfigKeywordHandlerProtocolGuid = {0x0a8badd5, 0x03b8, 0x4d19, {0xb1, 0x28, 0x7b, 0x8f, 0x0e, 0xda, 0xa5, 0x96}} + + ## Include/Protocol/WiFi.h + gEfiWiFiProtocolGuid = { 0xda55bc9, 0x45f8, 0x4bb4, {0x87, 0x19, 0x52, 0x24, 0xf1, 0x8a, 0x4d, 0x45 }} + + ## Include/Protocol/EapManagement2.h + gEfiEapManagement2ProtocolGuid = { 0x5e93c847, 0x456d, 0x40b3, {0xa6, 0xb4, 0x78, 0xb0, 0xc9, 0xcf, 0x7f, 0x20 }} + + ## Include/Protocol/EapConfiguration.h + gEfiEapConfigurationProtocolGuid = { 0xe5b58dbb, 0x7688, 0x44b4, {0x97, 0xbf, 0x5f, 0x1d, 0x4b, 0x7c, 0xc8, 0xdb }} + + ## Include/Protocol/Pkcs7Verify.h + gEfiPkcs7VerifyProtocolGuid = { 0x47889fb2, 0xd671, 0x4fab, { 0xa0, 0xca, 0xdf, 0x0e, 0x44, 0xdf, 0x70, 0xd6 }} + + ## Include/Protocol/Ip4Config2.h + gEfiIp4Config2ProtocolGuid = { 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 }} + + ## Include/Protocol/Dns4.h + gEfiDns4ServiceBindingProtocolGuid = { 0xb625b186, 0xe063, 0x44f7, { 0x89, 0x5, 0x6a, 0x74, 0xdc, 0x6f, 0x52, 0xb4 }} + + ## Include/Protocol/Dns4.h + gEfiDns4ProtocolGuid = { 0xae3d28cc, 0xe05b, 0x4fa1, { 0xa0, 0x11, 0x7e, 0xb5, 0x5a, 0x3f, 0x14, 0x1 }} + + ## Include/Protocol/Dns6.h + gEfiDns6ServiceBindingProtocolGuid = { 0x7f1647c8, 0xb76e, 0x44b2, { 0xa5, 0x65, 0xf7, 0xf, 0xf1, 0x9c, 0xd1, 0x9e }} + + ## Include/Protocol/Dns6.h + gEfiDns6ProtocolGuid = { 0xca37bc1f, 0xa327, 0x4ae9, { 0x82, 0x8a, 0x8c, 0x40, 0xd8, 0x50, 0x6a, 0x17 }} + + ## Include/Protocol/Http.h + gEfiHttpServiceBindingProtocolGuid = { 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c }} + + ## Include/Protocol/Http.h + gEfiHttpProtocolGuid = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b }} + + ## Include/Protocol/HttpUtilities.h + gEfiHttpUtilitiesProtocolGuid = { 0x3e35c163, 0x4074, 0x45dd, {0x43, 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 }} + + ## Include/Protocol/Tls.h + gEfiTlsServiceBindingProtocolGuid = { 0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d }} + + ## Include/Protocol/Tls.h + gEfiTlsProtocolGuid = { 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 0x43, 0x90 }} + + ## Include/Protocol/TlsConfig.h + gEfiTlsConfigurationProtocolGuid = { 0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }} + + ## Include/Protocol/Rest.h + gEfiRestProtocolGuid = { 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09, 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b }} + + ## Include/Protocol/Supplicant.h + gEfiSupplicantServiceBindingProtocolGuid = { 0x45bcd98e, 0x59ad, 0x4174, { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 }} + gEfiSupplicantProtocolGuid = { 0x54fcc43e, 0xaa89, 0x4333, { 0x9a, 0x85, 0xcd, 0xea, 0x24, 0x5, 0x1e, 0x9e }} + + # + # Protocols defined in UEFI2.6 + # + ## Include/Protocol/WiFi2.h + gEfiWiFi2ProtocolGuid = { 0x1b0fb9bf, 0x699d, 0x4fdd, {0xa7, 0xc3, 0x25, 0x46, 0x68, 0x1b, 0xf6, 0x3b }} + + ## Include/Protocol/RamDisk.h + gEfiRamDiskProtocolGuid = { 0xab38a0df, 0x6873, 0x44a9, { 0x87, 0xe6, 0xd4, 0xeb, 0x56, 0x14, 0x84, 0x49 }} + + ## Include/Protocol/ImageDecoder.h + gEfiHiiImageDecoderProtocolGuid = { 0x9e66f251, 0x727c, 0x418c, { 0xbf, 0xd6, 0xc2, 0xb4, 0x25, 0x28, 0x18, 0xea }} + + ## Include/Protocol/HiiImageEx.h + gEfiHiiImageExProtocolGuid = { 0x1a1241e6, 0x8f19, 0x41a9, { 0xbc, 0xe, 0xe8, 0xef, 0x39, 0xe0, 0x65, 0x46 }} + + ## Include/Protocol/SdMmcPassThru.h + gEfiSdMmcPassThruProtocolGuid = { 0x716ef0d9, 0xff83, 0x4f69, {0x81, 0xe9, 0x51, 0x8b, 0xd3, 0x9a, 0x8e, 0x70 }} + + ## Include/Protocol/EraseBlock.h + gEfiEraseBlockProtocolGuid = { 0x95a9a93e, 0xa86e, 0x4926, {0xaa, 0xef, 0x99, 0x18, 0xe7, 0x72, 0xd9, 0x87 }} + + # + # Protocols defined in UEFI2.7 + # + ## Include/Protocol/BluetoothAttribute.h + gEfiBluetoothAttributeProtocolGuid = { 0x898890e9, 0x84b2, 0x4f3a, { 0x8c, 0x58, 0xd8, 0x57, 0x78, 0x13, 0xe0, 0xac } } + gEfiBluetoothAttributeServiceBindingProtocolGuid = { 0x5639867a, 0x8c8e, 0x408d, {0xac, 0x2f, 0x4b, 0x61, 0xbd, 0xc0, 0xbb, 0xbb }} + + ## Include/Protocol/BluetoothLeConfig.h + gEfiBluetoothLeConfigProtocolGuid = { 0x8f76da58, 0x1f99, 0x4275, { 0xa4, 0xec, 0x47, 0x56, 0x51, 0x5b, 0x1c, 0xe8 } } + + ## Include/Protocol/UfsDeviceConfig.h + gEfiUfsDeviceConfigProtocolGuid = { 0xb81bfab0, 0xeb3, 0x4cf9, { 0x84, 0x65, 0x7f, 0xa9, 0x86, 0x36, 0x16, 0x64 }} + + ## Include/Protocol/HttpBootCallback.h + gEfiHttpBootCallbackProtocolGuid = {0xba23b311, 0x343d, 0x11e6, {0x91, 0x85, 0x58, 0x20, 0xb1, 0xd6, 0x52, 0x99}} + + ## Include/Protocol/ResetNotification.h + gEfiResetNotificationProtocolGuid = { 0x9da34ae0, 0xeaf9, 0x4bbf, { 0x8e, 0xc3, 0xfd, 0x60, 0x22, 0x6c, 0x44, 0xbe } } + + ## Include/Protocol/PartitionInfo.h + gEfiPartitionInfoProtocolGuid = { 0x8cf2f62c, 0xbc9b, 0x4821, { 0x80, 0x8d, 0xec, 0x9e, 0xc4, 0x21, 0xa1, 0xa0 }} + + ## Include/Protocol/HiiPopup.h + gEfiHiiPopupProtocolGuid = { 0x4311edc0, 0x6054, 0x46d4, { 0x9e, 0x40, 0x89, 0x3e, 0xa9, 0x52, 0xfc, 0xcc }} + + ## Include/Protocol/NvdimmLabel.h + gEfiNvdimmLabelProtocolGuid = { 0xd40b6b80, 0x97d5, 0x4282, { 0xbb, 0x1d, 0x22, 0x3a, 0x16, 0x91, 0x80, 0x58 }} + + # + # Protocols defined in Shell2.0 + # + ## Include/Protocol/Shell.h + gEfiShellProtocolGuid = { 0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e }} + + ## Include/Protocol/ShellParameters.h + gEfiShellParametersProtocolGuid = { 0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca }} + + # + # Protocols defined in Shell2.1 + # + ## Include/Protocol/ShellDynamicCommand.h + gEfiShellDynamicCommandProtocolGuid = { 0x3c7200e9, 0x005f, 0x4ea4, {0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3 }} + +# +# [Error.gEfiMdePkgTokenSpaceGuid] +# 0x80000001 | Invalid value provided. +# 0x80000002 | Reserved bits must be set to zero. +# 0x80000003 | Incorrect progress code provided. +# + +[PcdsFeatureFlag] + ## Indicates if the component name protocol will be installed.

+ # TRUE - Does not install component name protocol.
+ # FALSE - Install component name protocol.
+ # @Prompt Disable Component Name Protocol. + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d + + ## Indicates if the diagnostics name protocol will be installed.

+ # TRUE - Does not install diagnostics name protocol.
+ # FALSE - Install diagnostics name protocol.
+ # @Prompt Disable Diagnostics Name protocol. + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|FALSE|BOOLEAN|0x0000000e + + ## Indicates if the component name2 protocol will be installed.

+ # TRUE - Does not install component name2 protocol.
+ # FALSE - Install component name2 protocol.
+ # @Prompt Disable Component Name2 Protocol. + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|FALSE|BOOLEAN|0x00000010 + + ## Indicates if the diagnostics2 name protocol will be installed.

+ # TRUE - Does not install diagnostics2 name protocol.
+ # FALSE - Install diagnostics2 name protocol.
+ # @Prompt Disable Diagnostics2 Name Protocol. + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|FALSE|BOOLEAN|0x00000011 + + ## Indicates if EFI 1.1 ISO 639-2 language supports are obsolete

+ # TRUE - Deprecate global variable LangCodes.
+ # FALSE - Does not deprecate global variable LangCodes.
+ # @Prompt Deprecate Global Variable LangCodes. + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate|FALSE|BOOLEAN|0x00000012 + + ## Indicates if UGA Draw Protocol is still consumed.

+ # TRUE - Consume UGA Draw protocol.
+ # FALSE - Does not consume UGA Draw protocol.
+ # @Prompt Consume UGA Draw Protocol. + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport|TRUE|BOOLEAN|0x00000027 + + ## Indicates if a check will be made to see if a specified node is a member of linked list + # in the following BaseLib functions: GetNextNode(), IsNull(), IsNodeAtEnd(), SwapListEntries().

+ # TRUE - Verify a specified node is a member of linked list.
+ # FALSE - Does not verify a specified node is a member of linked list.
+ # @Prompt Verify Node In List. + gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList|FALSE|BOOLEAN|0x00000028 + + ## If TRUE, OrderedCollectionLib is instructed to validate the + # ORDERED_COLLECTION structure at the end of such operations (typically + # structure modifications) that justify validation of the structure for unit + # testing purposes. + # @Prompt Validate ORDERED_COLLECTION structure + gEfiMdePkgTokenSpaceGuid.PcdValidateOrderedCollection|FALSE|BOOLEAN|0x0000002a + +[PcdsFixedAtBuild] + ## Status code value for indicating a watchdog timer has expired. + # EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_TIMER_EXPIRED + # @Prompt Progress Code for WatchDog Timer Expired. + # @ValidList 0x80000003 | 0x00011003 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueEfiWatchDogTimerExpired|0x00011003|UINT32|0x00000013 + + ## Status code value for indicating the invocation of SetVirtualAddressMap() + # EFI_SOFTWARE_EFI_RUNTIME_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP + # @Prompt Progress Code for Invocation of SetVirtualAddressMap. + # @ValidList 0x80000003 | 0x03111004 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueSetVirtualAddressMap|0x03111004|UINT32|0x00000014 + + ## Status code value for indicating the start of memory test + # EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_TEST + # @Prompt Progress Code for Memory Test Start. + # @ValidList 0x80000003 | 0x00051006 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueMemoryTestStarted|0x00051006|UINT32|0x00000015 + + ## Status code value for indicating memory error in memory test + # EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_EC_UNCORRECTABLE + # @Prompt Progress Code for Memory Error. + # @ValidList 0x80000003 | 0x00051003 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueUncorrectableMemoryError|0x00051003|UINT32|0x00000016 + + ## Status code value for console operation failure. + # EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR + # @Prompt Progress Code for Console Error. + # @ValidList 0x80000003 | 0x01040006 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueRemoteConsoleError|0x01040006|UINT32|0x00000017 + + ## Status code value for console reset operation failure. + # EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET + # @Prompt Progress Code for Console Reset. + # @ValidList 0x80000003 | 0x01040001 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueRemoteConsoleReset|0x01040001|UINT32|0x00000018 + + ## Status code value for console input operation failure. + # EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR + # @Prompt Progress Code for Console Input Error. + # @ValidList 0x80000003 | 0x01040007 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueRemoteConsoleInputError|0x01040007|UINT32|0x00000019 + + ## Status code value for console output operation failure. + # EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR + # @Prompt Progress Code for Console Output Error. + # @ValidList 0x80000003 | 0x01040008 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueRemoteConsoleOutputError|0x01040008|UINT32|0x0000001a + + ## Status code value for mouse operation failure. + # EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR + # @Prompt Progress Code for Module Device Failure. + # @ValidList 0x80000003 | 0x01020005 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueMouseInterfaceError|0x01020005|UINT32|0x30001000 + + ## Status code value for indicating mouse device has been enabled. + # EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE + # @Prompt Progress Code for Enable Mouse Device. + # @ValidList 0x80000003 | 0x01020004 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueMouseEnable|0x01020004|UINT32|0x30001001 + + ## Status code value for indicating mouse device has been disabled. + # EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE + # @Prompt Progress Code for Disable Mouse Device. + # @ValidList 0x80000003 | 0x01020002 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueMouseDisable|0x01020002|UINT32|0x30001002 + + ## Status code value for enabling keyboard device. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE + # @Prompt Progress Code for Enable Keyboard Device. + # @ValidList 0x80000003 | 0x01010004 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardEnable|0x01010004|UINT32|0x30001003 + + ## Status code value for disabling keyboard device. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE + # @Prompt Progress Code for Disable Keyboard Device. + # @ValidList 0x80000003 | 0x01010002 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardDisable|0x01010002|UINT32|0x30001004 + + ## Status code value for indicating presence of keyboard. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT + # @Prompt Progress Code for Detect Keyboard Device. + # @ValidList 0x80000003 | 0x01010003 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardPresenceDetect|0x01010003|UINT32|0x30001005 + + ## Status code value for keyboard operation reset operation. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET + # @Prompt Progress Code for Keyboard Device Reset. + # @ValidList 0x80000003 | 0x01010001 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardReset|0x01010001|UINT32|0x30001006 + + ## Status code value for keyboard clear buffer operation. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER + # @Prompt Progress Code for Keyboard Device Clear Buffer. + # @ValidList 0x80000003 | 0x01011000 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardClearBuffer|0x01011000|UINT32|0x30001007 + + ## Status code value for keyboard device self-test. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST + # @Prompt Progress Code for Keyboard Device SelfTest. + # @ValidList 0x80000003 | 0x01011001 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardSelfTest|0x01011001|UINT32|0x30001008 + + ## Status code value for indicating keyboard device failure. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR + # @Prompt Progress Code for Keyboard Device Failure. + # @ValidList 0x80000003 | 0x01010005 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardInterfaceError|0x01010005|UINT32|0x30001009 + + ## Status code value for indicating keyboard input handler failure. + # EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR + # @Prompt Progress Code for Keyboard Input Failure. + # @ValidList 0x80000003 | 0x01010007 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueKeyboardInputError|0x01010007|UINT32|0x3000100a + + ## Status code value for mouse input handler failure. + # EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR + # @Prompt Progress Code for Mouse Input Failure. + # @ValidList 0x80000003 | 0x01020007 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueMouseInputError|0x01020007|UINT32|0x3000100b + + ## Status code value for mouse device reset operation. + # EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET + # @Prompt Progress Code for Mouse Device Reset. + # @ValidList 0x80000003 | 0x01020001 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueMouseReset|0x01020001|UINT32|0x3000100c + + ## Status code value for indicating the handoff from PEI phase to DXE phase. + # EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT + # @Prompt Progress Code for Handoff from Pei phase to Dxe phase. + # @ValidList 0x80000003 | 0x3021001 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValuePeiHandoffToDxe|0x3021001|UINT32|0x3000100d + + ## Status code value for indicating one PEIM is dispatched. + # EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN + # @Prompt Progress Code for Dispatching One PEIM. + # @ValidList 0x80000003 | 0x3020002 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValuePeimDispatch|0x3020002|UINT32|0x3000100e + + ## Status code value for PeiCore entry. + # EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT + # @Prompt Progress Code for PeiCore Entry. + # @ValidList 0x80000003 | 0x3020000 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValuePeiCoreEntry|0x3020000|UINT32|0x3000100f + + ## Status code value for DxeCore entry. + # EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT + # @Prompt Progress Code for DxeCore Entry. + # @ValidList 0x80000003 | 0x3041000 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeCoreEntry|0x3041000|UINT32|0x30001010 + + ## Status code value for handoff from DxeCore to BDS. + # EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT + # @Prompt Progress Code for Handoff from DxeCore to BDS. + # @ValidList 0x80000003 | 0x3041001 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeCoreHandoffToBds|0x3041001|UINT32|0x30001011 + + ## Status code value for indicating boot service exit. + # EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES + # @Prompt Progress Code for Exit of Boot Service. + # @ValidList 0x80000003 | 0x3101019 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueBootServiceExit|0x3101019|UINT32|0x30001012 + + ## Status code value for indicating the beginning of DXE driver. + # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN + # @Prompt Progress Code for Begin of DXE Driver. + # @ValidList 0x80000003 | 0x3040002 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverBegin|0x3040002|UINT32|0x30001013 + + ## Status code value for indicating the end of DXE drive. + # EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END + # @Prompt Progress Code for End of DXE Driver. + # @ValidList 0x80000003 | 0x3040003 + gEfiMdePkgTokenSpaceGuid.PcdStatusCodeValueDxeDriverEnd|0x3040003|UINT32|0x30001014 + + ## This flag is used to control build time optimization based on debug print level. + # Its default value is 0xFFFFFFFF to expose all debug print level. + # BIT0 - Initialization message.
+ # BIT1 - Warning message.
+ # BIT2 - Load Event message.
+ # BIT3 - File System message.
+ # BIT4 - Allocate or Free Pool message.
+ # BIT5 - Allocate or Free Page message.
+ # BIT6 - Information message.
+ # BIT7 - Dispatcher message.
+ # BIT8 - Variable message.
+ # BIT10 - Boot Manager message.
+ # BIT12 - BlockIo Driver message.
+ # BIT14 - Network Driver message.
+ # BIT16 - UNDI Driver message.
+ # BIT17 - LoadFile message.
+ # BIT19 - Event message.
+ # BIT20 - Global Coherency Database changes message.
+ # BIT21 - Memory range cachability changes message.
+ # BIT22 - Detailed debug message.
+ # BIT31 - Error message.
+ # @Prompt Fixed Debug Message Print Level. + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel|0xFFFFFFFF|UINT32|0x30001016 + + ## Indicates the control flow enforcement enabling state. + # If enabled, it uses control flow enforcement technology to prevent ROP or JOP.

+ # BIT0 - SMM CET Shadow Stack is enabled.
+ # Other - reserved + # @Prompt Enable control flow enforcement. + gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask|0x0|UINT32|0x30001017 + +[PcdsFixedAtBuild,PcdsPatchableInModule] + ## Indicates the maximum length of unicode string used in the following + # BaseLib functions: StrLen(), StrSize(), StrCmp(), StrnCmp(), StrCpy(), StrnCpy()

+ # 0 - No length check for unicode string.
+ # >0 - Maximum length of unicode string.
+ # @Prompt Maximum Length of Unicode String. + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000|UINT32|0x00000001 + + ## Indicates the maximum length of ascii string used in the following + # BaseLib functions: AsciiStrLen(), AsciiStrSize(), AsciiStrCmp(), AsciiStrnCmp(), + # AsciiStrCpy(), AsciiStrnCpy().

+ # 0 - No length check for ascii string.
+ # >0 - Maximum length of ascii string.
+ # @Prompt Maximum Length of Ascii String. + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000|UINT32|0x00000002 + + ## Indicates the maximum node number of linked list.

+ # 0 - No node number check for linked list.
+ # >0 - Maximum node number of linked list.
+ # @Prompt Maximum Length of Linked List. + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000|UINT32|0x00000003 + + ## Indicates the maximum node number of device path.

+ # 0 - No node number check for device path.
+ # >0 - Maximum node number of device path.
+ # @Prompt Maximum node number of device path. + gEfiMdePkgTokenSpaceGuid.PcdMaximumDevicePathNodeCount|0|UINT32|0x00000029 + + ## Indicates the timeout tick of holding spin lock.

+ # 0 - No timeout.
+ # >0 - Timeout tick of holding spin lock.
+ # @Prompt Spin Lock Timeout (us). + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000|UINT32|0x00000004 + + ## The mask is used to control DebugLib behavior.

+ # BIT0 - Enable Debug Assert.
+ # BIT1 - Enable Debug Print.
+ # BIT2 - Enable Debug Code.
+ # BIT3 - Enable Clear Memory.
+ # BIT4 - Enable BreakPoint as ASSERT.
+ # BIT5 - Enable DeadLoop as ASSERT.
+ # @Prompt Debug Property. + # @Expression 0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask & 0xC0) == 0 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0|UINT8|0x00000005 + + ## This flag is used to control the print out Debug message.

+ # BIT0 - Initialization message.
+ # BIT1 - Warning message.
+ # BIT2 - Load Event message.
+ # BIT3 - File System message.
+ # BIT4 - Allocate or Free Pool message.
+ # BIT5 - Allocate or Free Page message.
+ # BIT6 - Information message.
+ # BIT7 - Dispatcher message.
+ # BIT8 - Variable message.
+ # BIT10 - Boot Manager message.
+ # BIT12 - BlockIo Driver message.
+ # BIT14 - Network Driver message.
+ # BIT16 - UNDI Driver message.
+ # BIT17 - LoadFile message.
+ # BIT19 - Event message.
+ # BIT20 - Global Coherency Database changes message.
+ # BIT21 - Memory range cachability changes message.
+ # BIT22 - Detailed debug message.
+ # BIT31 - Error message.
+ # @Prompt Debug Message Print Level. + # @Expression 0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel & 0x7F84AA00) == 0 + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000|UINT32|0x00000006 + + ## The mask is used to control ReportStatusCodeLib behavior.

+ # BIT0 - Enable Progress Code.
+ # BIT1 - Enable Error Code.
+ # BIT2 - Enable Debug Code.
+ # @Prompt Report Status Code Property. + # @Expression 0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask & 0xF8) == 0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0|UINT8|0x00000007 + + ## This value is used to fill a segment of memory when PcdDebugPropertyMask Clear Memory is enabled. + # @Prompt Value to Clear Memory. + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF|UINT8|0x00000008 + + ## The mask is used to control PerformanceLib behavior.

+ # BIT0 - Enable Performance Measurement.
+ # BIT1 - Disable Start Image Logging.
+ # BIT2 - Disable Load Image logging.
+ # BIT3 - Disable Binding Support logging.
+ # BIT4 - Disable Binding Start logging.
+ # BIT5 - Disable Binding Stop logging.
+ # BIT6 - Disable all other general Perfs.
+ # BIT1-BIT6 are evaluated when BIT0 is set.
+ # @Prompt Performance Measurement Property. + # @Expression 0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask & 0x80) == 0 + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0|UINT8|0x00000009 + + ## The mask is used to control PostCodeLib behavior.

+ # BIT0 - Enable Post Code.
+ # BIT1 - Enable Post Code with Description.
+ # @Prompt Post Code Property. + # @Expression 0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask & 0xFC) == 0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0|UINT8|0x0000000b + + ## The bit width of data to be written to Port80. The default value is 8. + # @Prompt Port80 Data Width + # @ValidList 0x80000001 | 8, 16, 32 + gEfiMdePkgTokenSpaceGuid.PcdPort80DataWidth|8|UINT8|0x0000002d + + ## This value is used to configure X86 Processor FSB clock. + # @Prompt FSB Clock. + gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000|UINT32|0x0000000c + + ## The maximum printable number of characters. UefLib functions: AsciiPrint(), AsciiErrorPrint(), + # PrintXY(), AsciiPrintXY(), Print(), ErrorPrint() base on this PCD value to print characters. + # @Prompt Maximum Printable Number of Characters. + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320|UINT32|0x101 + + ## This is the print buffer length for FileHandleLib. + # FileHandlePrintLine() sizes buffers based on this PCD value for printing. + # @Prompt Number of Printable Characters. + gEfiMdePkgTokenSpaceGuid.PcdUefiFileHandleLibPrintBufferSize|1536|UINT16|0x201 + + ## Indicates the allowable maximum number in extract handler table. + # @Prompt Maximum Number of GuidedExtractHandler. + gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10|UINT32|0x00000025 + + ## Indicates the default timeouts for USB transfers in milliseconds. + # @Prompt USB Transfer Timeout (ms). + gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue|3000|UINT32|0x00000026 + + ## This value is used to set the available memory address to store Guided Extract Handlers. + # The required memory space is decided by the value of PcdMaximumGuidedExtractHandler. + # @Prompt Memory Address of GuidedExtractHandler Table. + gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|0x1000000|UINT64|0x30001015 + +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] + ## This value is used to set the base address of PCI express hierarchy. + # @Prompt PCI Express Base Address. + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000|UINT64|0x0000000a + + ## Default current ISO 639-2 language: English & French. + # @Prompt Default Value of LangCodes Variable. + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes|"engfraengfra"|VOID*|0x0000001c + + ## Default current ISO 639-2 language: English. + # @Prompt Default Value of Lang Variable. + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang|"eng"|VOID*|0x0000001d + + ## Default platform supported RFC 4646 languages: (American) English & French. + # @Prompt Default Value of PlatformLangCodes Variable. + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes|"en;fr;en-US;fr-FR"|VOID*|0x0000001e + + ## Default current RFC 4646 language: (American) English. + # @Prompt Default Value of PlatformLang Variable. + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang|"en-US"|VOID*|0x0000001f + + ## Indicates the default baud rate of UART. + # @Prompt Default UART Baud Rate. + # @ValidList 0x80000001 | 115200, 57600, 38400, 19200, 9600, 7200, 4800, 3600, 2400, 2000, 1800, 1200, 600, 300, 150, 134, 110, 75, 50 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200|UINT64|0x00000020 + + ## Indicates the number of efficient data bit in UART transaction. + # @Prompt Default UART Data Bit. + # @ValidRange 0x80000001 | 5 - 8 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8|UINT8|0x00000021 + + ## Indicates the setting of data parity in UART transaction.

+ # 0 - Default Parity.
+ # 1 - No Parity.
+ # 2 - Even Parity.
+ # 3 - Odd Parity.
+ # 4 - Mark Parity.
+ # 5 - Space Parity.
+ # @Prompt Default UART Parity. + # @ValidRange 0x80000001 | 0 - 5 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1|UINT8|0x00000022 + + ## Indicates the setting of stop bit in UART transaction.

+ # 0 - Default Stop Bits.
+ # 1 - One Stop Bit.
+ # 2 - One Five Stop Bits.
+ # 3 - Two Stop Bits.
+ # @Prompt Default UART Stop Bits. + # @ValidRange 0x80000001 | 0 - 3 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1|UINT8|0x00000023 + + ## Indicates the usable type of terminal.

+ # 0 - PCANSI
+ # 1 - VT100
+ # 2 - VT100+
+ # 3 - UTF8
+ # 4 - TTYTERM, NOT defined in UEFI SPEC
+ # @Prompt Default Terminal Type. + # @ValidRange 0x80000001 | 0 - 4 + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|0|UINT8|0x00000024 + + ## Indicates the receive FIFO depth of UART controller.

+ # @Prompt Default UART Receive FIFO Depth. + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultReceiveFifoDepth|1|UINT16|0x00000030 + + ## Error level for hardware recorder. + # If value 0, platform does not support feature of hardware error record. + # @Prompt Error Level For Hardware Recorder + gEfiMdePkgTokenSpaceGuid.PcdHardwareErrorRecordLevel|0|UINT16|0x0000002b + + ## The number of seconds that the firmware will wait before initiating the original default boot selection. + # A value of 0 indicates that the default boot selection is to be initiated immediately on boot. + # The value of 0xFFFF then firmware will wait for user input before booting. + # @Prompt Boot Timeout (s) + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000002c + +[UserExtensions.TianoCore."ExtraFiles"] + MdePkgExtra.uni diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dsc b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dsc new file mode 100644 index 0000000..48a4a74 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.dsc @@ -0,0 +1,158 @@ +## @file +# EFI/PI MdePkg Package +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + PLATFORM_NAME = Mde + PLATFORM_GUID = 082F8BFC-0455-4859-AE3C-ECD64FB81642 + PLATFORM_VERSION = 1.08 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Mde + SUPPORTED_ARCHITECTURES = IA32|X64|EBC|ARM|AARCH64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[PcdsFeatureFlag] + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport|TRUE + +[PcdsFixedAtBuild] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 + +[Components] + MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + MdePkg/Library/BaseLib/BaseLib.inf + MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf + MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf + MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf + MdePkg/Library/BasePciSegmentInfoLibNull/BasePciSegmentInfoLibNull.inf + MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf + MdePkg/Library/PciSegmentLibSegmentInfo/DxeRuntimePciSegmentLibSegmentInfo.inf + MdePkg/Library/BaseS3PciSegmentLib/BaseS3PciSegmentLib.inf + MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + MdePkg/Library/BasePostCodeLibDebug/BasePostCodeLibDebug.inf + MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf + MdePkg/Library/BasePrintLib/BasePrintLib.inf + MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf + MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + + MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + MdePkg/Library/DxeHobLib/DxeHobLib.inf + MdePkg/Library/DxePcdLib/DxePcdLib.inf + MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf + MdePkg/Library/DxeIoLibCpuIo2/DxeIoLibCpuIo2.inf + MdePkg/Library/DxeHstiLib/DxeHstiLib.inf + MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf + MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf + + MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + MdePkg/Library/PeiDxePostCodeLibReportStatusCode/PeiDxePostCodeLibReportStatusCode.inf + MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + MdePkg/Library/PeiHobLib/PeiHobLib.inf + MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf + MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + MdePkg/Library/PeiMemoryLib/PeiMemoryLib.inf + MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf + MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf + MdePkg/Library/PeiPciLibPciCfg2/PeiPciLibPciCfg2.inf + MdePkg/Library/PeiPciSegmentLibPciCfg2/PeiPciSegmentLibPciCfg2.inf + + MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf + MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf + MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf + MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf + MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + MdePkg/Library/UefiLib/UefiLib.inf + MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + MdePkg/Library/UefiMemoryLib/UefiMemoryLib.inf + MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + MdePkg/Library/UefiPciLibPciRootBridgeIo/UefiPciLibPciRootBridgeIo.inf + MdePkg/Library/UefiPciSegmentLibPciRootBridgeIo/UefiPciSegmentLibPciRootBridgeIo.inf + MdePkg/Library/SmmLibNull/SmmLibNull.inf + MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf + + MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf + MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf + +[Components.IA32, Components.X64] + MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf + MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.inf + MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf + MdePkg/Library/BaseMemoryLibOptPei/BaseMemoryLibOptPei.inf + MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf + MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.inf + MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf + MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf + MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + MdePkg/Library/SmmIoLibSmmCpuIo2/SmmIoLibSmmCpuIo2.inf + MdePkg/Library/SmmPciLibPciRootBridgeIo/SmmPciLibPciRootBridgeIo.inf + MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf + MdePkg/Library/SmmPeriodicSmiLib/SmmPeriodicSmiLib.inf + MdePkg/Library/BaseS3BootScriptLibNull/BaseS3BootScriptLibNull.inf + MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf + MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf + MdePkg/Library/BaseS3SmbusLib/BaseS3SmbusLib.inf + MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf + MdePkg/Library/SmmMemLib/SmmMemLib.inf + MdePkg/Library/SmmIoLib/SmmIoLib.inf + MdePkg/Library/BaseRngLib/BaseRngLib.inf + MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf + MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf + MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf + +[Components.EBC] + MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + +[Components.ARM, Components.AARCH64] + MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf + MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.uni new file mode 100644 index 0000000..2238e24 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkg.uni @@ -0,0 +1,413 @@ +// /** @file +// This Package provides all definitions, library classes and libraries instances. +// +// It also provides the definitions(including PPIs/PROTOCOLs/GUIDs) of +// EFI1.10/UEFI2.4/PI1.3 and some Industry Standards. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License which accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_PACKAGE_ABSTRACT #language en-US "This Package provides all definitions, library classes and libraries instances." + +#string STR_PACKAGE_DESCRIPTION #language en-US "It also provides the definitions(including PPIs/PROTOCOLs/GUIDs) of EFI1.10/UEFI2.4/PI1.3 and some Industry Standards." + + + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueEfiWatchDogTimerExpired_PROMPT #language en-US "Progress Code for WatchDog Timer Expired" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueEfiWatchDogTimerExpired_HELP #language en-US "Status code value for indicating a watchdog timer has expired. EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_TIMER_EXPIRED" + +#string STR_gEfiMdePkgTokenSpaceGuid_ERR_80000003 #language en-US "Incorrect progress code provided." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueSetVirtualAddressMap_PROMPT #language en-US "Progress Code for Invocation of SetVirtualAddressMap" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueSetVirtualAddressMap_HELP #language en-US "Status code value for indicating the invocation of SetVirtualAddressMap() EFI_SOFTWARE_EFI_RUNTIME_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMemoryTestStarted_PROMPT #language en-US "Progress Code for Memory Test Start" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMemoryTestStarted_HELP #language en-US "Status code value for indicating the start of memory test EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_TEST" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueUncorrectableMemoryError_PROMPT #language en-US "Progress Code for Memory Error" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueUncorrectableMemoryError_HELP #language en-US "Status code value for indicating memory error in memory test EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_EC_UNCORRECTABLE" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleError_PROMPT #language en-US "Progress Code for Console Error" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleError_HELP #language en-US "Status code value for console operation failure. EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleReset_PROMPT #language en-US "Progress Code for Console Reset" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleReset_HELP #language en-US "Status code value for console reset operation failure. EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleInputError_PROMPT #language en-US "Progress Code for Console Input Error" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleInputError_HELP #language en-US "Status code value for console input operation failure. EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleOutputError_PROMPT #language en-US "Progress Code for Console Output Error" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueRemoteConsoleOutputError_HELP #language en-US "Status code value for console output operation failure. EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseInterfaceError_PROMPT #language en-US "Progress Code for Module Device Failure" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseInterfaceError_HELP #language en-US "Status code value for mouse operation failure. EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseEnable_PROMPT #language en-US "Progress Code for Enable Mouse Device" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseEnable_HELP #language en-US "Status code value for indicating mouse device has been enabled. EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseDisable_PROMPT #language en-US "Progress Code for Disable Mouse Device" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseDisable_HELP #language en-US "Status code value for indicating mouse device has been disabled. EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardEnable_PROMPT #language en-US "Progress Code for Enable Keyboard Device" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardEnable_HELP #language en-US "Status code value for enabling keyboard device. EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardDisable_PROMPT #language en-US "Progress Code for Disable Keyboard Device" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardDisable_HELP #language en-US "Status code value for disabling keyboard device. EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardPresenceDetect_PROMPT #language en-US "Progress Code for Detect Keyboard Device" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardPresenceDetect_HELP #language en-US "Status code value for indicating presence of keyboard. EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardReset_PROMPT #language en-US "Progress Code for Keyboard Device Reset" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardReset_HELP #language en-US "Status code value for keyboard operation reset operation. EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardClearBuffer_PROMPT #language en-US "Progress Code for Keyboard Device Clear Buffer" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardClearBuffer_HELP #language en-US "Status code value for keyboard clear buffer operation. EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardSelfTest_PROMPT #language en-US "Progress Code for Keyboard Device SelfTest" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardSelfTest_HELP #language en-US "Status code value for keyboard device self-test. EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardInterfaceError_PROMPT #language en-US "Progress Code for Keyboard Device Failure" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardInterfaceError_HELP #language en-US "Status code value for indicating keyboard device failure. EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardInputError_PROMPT #language en-US "Progress Code for Keyboard Input Failure" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueKeyboardInputError_HELP #language en-US "Status code value for indicating keyboard input handler failure. EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseInputError_PROMPT #language en-US "Progress Code for Mouse Input Failure" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseInputError_HELP #language en-US "Status code value for mouse input handler failure. EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseReset_PROMPT #language en-US "Progress Code for Mouse Device Reset" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueMouseReset_HELP #language en-US "Status code value for mouse device reset operation. EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValuePeiHandoffToDxe_PROMPT #language en-US "Progress Code for Handoff from PEI phase to DXE phase" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValuePeiHandoffToDxe_HELP #language en-US "Status code value for indicating the handoff from PEI phase to DXE phase. EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValuePeimDispatch_PROMPT #language en-US "Progress Code for Dispatching One PEIM" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValuePeimDispatch_HELP #language en-US "Status code value for indicating one PEIM is dispatched. EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValuePeiCoreEntry_PROMPT #language en-US "Progress Code for PeiCore Entry" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValuePeiCoreEntry_HELP #language en-US "Status code value for PeiCore entry. EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeCoreEntry_PROMPT #language en-US "Progress Code for DxeCore Entry" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeCoreEntry_HELP #language en-US "Status code value for DxeCore entry. EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeCoreHandoffToBds_PROMPT #language en-US "Progress Code for Handoff from DxeCore to BDS" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeCoreHandoffToBds_HELP #language en-US "Status code value for handoff from DxeCore to BDS. EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueBootServiceExit_PROMPT #language en-US "Progress Code for Exit of Boot Service" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueBootServiceExit_HELP #language en-US "Status code value for indicating boot service exit. EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeDriverBegin_PROMPT #language en-US "Progress Code for Begin of DXE Driver" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeDriverBegin_HELP #language en-US "Status code value for indicating the beginning of DXE driver. EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeDriverEnd_PROMPT #language en-US "Progress Code for End of DXE Driver" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdStatusCodeValueDxeDriverEnd_HELP #language en-US "Status code value for indicating the end of DXE drive. EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumUnicodeStringLength_PROMPT #language en-US "Maximum Length of Unicode String" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumUnicodeStringLength_HELP #language en-US "Sets the maximum number of unicode characters used for string functions. This affects the following BaseLib functions: StrLen(), StrSize(), StrCmp(), StrnCmp(), StrCpy(), StrnCpy()

\n" + "0 - No length check for unicode string.
\n" + ">0 - Maximum length of unicode string.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdControlFlowEnforcementPropertyMask_PROMPT #language en-US "Enable control flow enforcement." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdControlFlowEnforcementPropertyMask_HELP #language en-US "Indicates the control flow enforcement enabling state.\n" + "If enabled, it uses control flow enforcement technology to prevent ROP or JOP.

\n" + " BIT0 - SMM CET Shadow Stack is enabled.
\n" + " Other - reserved" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumAsciiStringLength_PROMPT #language en-US "Maximum Length of Ascii String" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumAsciiStringLength_HELP #language en-US "Sets the maximum number of ASCII characters used for string functions. This affects the following BaseLib functions: AsciiStrLen(), AsciiStrSize(), AsciiStrCmp(), AsciiStrnCmp(), AsciiStrCpy(), AsciiStrnCpy().

\n" + "0 - No length check for ASCII string.
\n" + ">0 - Maximum length of ASCII string.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumLinkedListLength_PROMPT #language en-US "Maximum Length of Linked List" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumLinkedListLength_HELP #language en-US "Indicates the maximum node number of linked list.

\n" + "0 - No node number check for linked list.
\n" + ">0 - Maximum node number of linked list.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumDevicePathNodeCount_PROMPT #language en-US "Maximum node number of device path" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumDevicePathNodeCount_HELP #language en-US "Indicates the maximum node number of device path.

\n" + "0 - No node number check for device path.
\n" + ">0 - Maximum node number of device path.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdSpinLockTimeout_PROMPT #language en-US "Spin Lock Timeout (us)" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdSpinLockTimeout_HELP #language en-US "Indicates the timeout tick of holding spin lock.

\n" + "0 - No timeout.
\n" + ">0 - Timeout tick of holding spin lock.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDebugPropertyMask_PROMPT #language en-US "Debug Property" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDebugPropertyMask_HELP #language en-US "The mask is used to control DebugLib behavior.

\n" + "BIT0 - Enable Debug Assert.
\n" + "BIT1 - Enable Debug Print.
\n" + "BIT2 - Enable Debug Code.
\n" + "BIT3 - Enable Clear Memory.
\n" + "BIT4 - Enable BreakPoint as ASSERT.
\n" + "BIT5 - Enable DeadLoop as ASSERT.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_ERR_80000002 #language en-US "Reserved bits must be set to zero." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDebugPrintErrorLevel_PROMPT #language en-US "Debug Message Print Level" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDebugPrintErrorLevel_HELP #language en-US "This flag is used to control the print out Debug message.

\n" + "BIT0 - Initialization message.
\n" + "BIT1 - Warning message.
\n" + "BIT2 - Load Event message.
\n" + "BIT3 - File System message.
\n" + "BIT4 - Allocate or Free Pool message.
\n" + "BIT5 - Allocate or Free Page message.
\n" + "BIT6 - Information message.
\n" + "BIT7 - Dispatcher message.
\n" + "BIT8 - Variable message.
\n" + "BIT10 - Boot Manager message.
\n" + "BIT12 - BlockIo Driver message.
\n" + "BIT14 - Network Driver message.
\n" + "BIT16 - UNDI Driver message.
\n" + "BIT17 - LoadFile message.
\n" + "BIT19 - Event message.
\n" + "BIT20 - Global Coherency Database changes message.
\n" + "BIT21 - Memory range cacheability changes message.
\n" + "BIT22 - Detailed debug message.
\n" + "BIT31 - Error message.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdFixedDebugPrintErrorLevel_PROMPT #language en-US "Fixed Debug Message Print Level" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdFixedDebugPrintErrorLevel_HELP #language en-US "This flag is used to control build time optimization based on debug print level.

\n" + "BIT0 - Initialization message.
\n" + "BIT1 - Warning message.
\n" + "BIT2 - Load Event message.
\n" + "BIT3 - File System message.
\n" + "BIT4 - Allocate or Free Pool message.
\n" + "BIT5 - Allocate or Free Page message.
\n" + "BIT6 - Information message.
\n" + "BIT7 - Dispatcher message.
\n" + "BIT8 - Variable message.
\n" + "BIT10 - Boot Manager message.
\n" + "BIT12 - BlockIo Driver message.
\n" + "BIT14 - Network Driver message.
\n" + "BIT16 - UNDI Driver message.
\n" + "BIT17 - LoadFile message.
\n" + "BIT19 - Event message.
\n" + "BIT20 - Global Coherency Database changes message.
\n" + "BIT21 - Memory range cacheability changes message.
\n" + "BIT22 - Detailed debug message.
\n" + "BIT31 - Error message.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdReportStatusCodePropertyMask_PROMPT #language en-US "Report Status Code Property" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdReportStatusCodePropertyMask_HELP #language en-US "The mask is used to control ReportStatusCodeLib behavior.

\n" + "BIT0 - Enable Progress Code.
\n" + "BIT1 - Enable Error Code.
\n" + "BIT2 - Enable Debug Code.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDebugClearMemoryValue_PROMPT #language en-US "Value to Clear Memory" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDebugClearMemoryValue_HELP #language en-US "This value is used to fill a segment of memory when PcdDebugPropertyMask Clear Memory is enabled." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPerformanceLibraryPropertyMask_PROMPT #language en-US "Performance Measurement Property" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPerformanceLibraryPropertyMask_HELP #language en-US "The mask is used to control PerformanceLib behavior.

\n" + "BIT0 - Enable Performance Measurement.
" + "BIT1 - Disable Start Image Logging.
" + "BIT2 - Disable Load Image logging.
" + "BIT3 - Disable Binding Support logging.
" + "BIT4 - Disable Binding Start logging.
" + "BIT5 - Disable Binding Stop logging.
" + "BIT6 - Disable all other general Perfs.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPostCodePropertyMask_PROMPT #language en-US "Post Code Property" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPostCodePropertyMask_HELP #language en-US "The mask is used to control PostCodeLib behavior.

\n" + "BIT0 - Enable Post Code.
\n" + "BIT1 - Enable Post Code with Description.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdFSBClock_PROMPT #language en-US "FSB Clock" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdFSBClock_HELP #language en-US "This value is used to configure X86 Processor FSB clock." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiLibMaxPrintBufferSize_PROMPT #language en-US "Maximum Printable Number of Characters" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiLibMaxPrintBufferSize_HELP #language en-US "The maximum printable number of characters. UefLib functions: AsciiPrint(), AsciiErrorPrint(), PrintXY(), AsciiPrintXY(), Print(), ErrorPrint() base on this PCD value to print characters." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumGuidedExtractHandler_PROMPT #language en-US "Maximum Number of GuidedExtractHandler" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdMaximumGuidedExtractHandler_HELP #language en-US "Indicates the allowable maximum number in extract handler table." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUsbTransferTimeoutValue_PROMPT #language en-US "USB Transfer Timeout (ms)" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUsbTransferTimeoutValue_HELP #language en-US "Indicates the default timeouts for USB transfers in milliseconds." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdGuidedExtractHandlerTableAddress_PROMPT #language en-US "Memory Address of GuidedExtractHandler Table" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdGuidedExtractHandlerTableAddress_HELP #language en-US "This value is used to set the available memory address to store Guided Extract Handlers. The required memory space is decided by the value of PcdMaximumGuidedExtractHandler." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPciExpressBaseAddress_PROMPT #language en-US "PCI Express Base Address" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPciExpressBaseAddress_HELP #language en-US "This value is used to set the base address of PCI express hierarchy." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultLangCodes_PROMPT #language en-US "Default Value of LangCodes Variable" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultLangCodes_HELP #language en-US "Default current ISO 639-2 language: English & French." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultLang_PROMPT #language en-US "Default Value of Lang Variable" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultLang_HELP #language en-US "Default current ISO 639-2 language: English." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultPlatformLangCodes_PROMPT #language en-US "Default Value of PlatformLangCodes Variable" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultPlatformLangCodes_HELP #language en-US "Default platform supported RFC 4646 languages: (American) English & French." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultPlatformLang_PROMPT #language en-US "Default Value of PlatformLang Variable" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultPlatformLang_HELP #language en-US "Default current RFC 4646 language: (American) English." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultBaudRate_PROMPT #language en-US "Default UART Baud Rate" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultBaudRate_HELP #language en-US "Indicates the default baud rate of UART." + +#string STR_gEfiMdePkgTokenSpaceGuid_ERR_80000001 #language en-US "Invalid value provided." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultDataBits_PROMPT #language en-US "Default UART Data Bit" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultDataBits_HELP #language en-US "Indicates the number of efficient data bit in UART transaction." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultParity_PROMPT #language en-US "Default UART Parity" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultParity_HELP #language en-US "Indicates the setting of data parity in UART transaction.

\n" + "0 - Default Parity.
\n" + "1 - No Parity.
\n" + "2 - Even Parity.
\n" + "3 - Odd Parity.
\n" + "4 - Mark Parity.
\n" + "5 - Space Parity.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultStopBits_PROMPT #language en-US "Default UART Stop Bits" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultStopBits_HELP #language en-US "Indicates the setting of stop bit in UART transaction.

\n" + "0 - Default Stop Bits.
\n" + "1 - One Stop Bit.
\n" + "2 - One Five Stop Bits.
\n" + "3 - Two Stop Bits.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDefaultTerminalType_PROMPT #language en-US "Default Terminal Type" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDefaultTerminalType_HELP #language en-US "Selects default terminal type.

\n" + "0 - PCANSI
\n" + "1 - VT100
\n" + "2 - VT100+
\n" + "3 - UTF8
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdComponentNameDisable_PROMPT #language en-US "Disable Component Name Protocol" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdComponentNameDisable_HELP #language en-US "Indicates if the component name protocol will be installed.

\n" + "TRUE - Does not install component name protocol.
\n" + "FALSE - Install component name protocol.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDriverDiagnosticsDisable_PROMPT #language en-US "Disable Diagnostics Name protocol" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDriverDiagnosticsDisable_HELP #language en-US "Indicates if the diagnostics name protocol will be installed.

\n" + "TRUE - Does not install diagnostics name protocol.
\n" + "FALSE - Install diagnostics name protocol.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdComponentName2Disable_PROMPT #language en-US "Disable Component Name2 Protocol" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdComponentName2Disable_HELP #language en-US "Indicates if the component name2 protocol will be installed.

\n" + "TRUE - Does not install component name2 protocol.
\n" + "FALSE - Install component name2 protocol.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDriverDiagnostics2Disable_PROMPT #language en-US "Disable Diagnostics2 Name Protocol" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdDriverDiagnostics2Disable_HELP #language en-US "Indicates if the diagnostics2 name protocol will be installed.

\n" + "TRUE - Does not install diagnostics2 name protocol.
\n" + "FALSE - Install diagnostics2 name protocol.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultLangDeprecate_PROMPT #language en-US "Deprecate Global Variable LangCodes" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiVariableDefaultLangDeprecate_HELP #language en-US "Indicates if EFI 1.1 ISO 639-2 language supports are obsolete

\n" + "TRUE - Deprecate global variable LangCodes.
\n" + "FALSE - Does not deprecate global variable LangCodes.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUgaConsumeSupport_PROMPT #language en-US "Consume UGA Draw Protocol" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUgaConsumeSupport_HELP #language en-US "Indicates if UGA Draw Protocol is still consumed.

\n" + "TRUE - Consume UGA Draw protocol.
\n" + "FALSE - Does not consume UGA Draw protocol.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdVerifyNodeInList_PROMPT #language en-US "Verify Node In List" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdVerifyNodeInList_HELP #language en-US "Indicates if a check will be made to see if a specified node is a member of linked list in the following BaseLib functions: GetNextNode(), IsNull(), IsNodeAtEnd(), SwapListEntries().

\n" + "TRUE - Verify a specified node is a member of linked list.
\n" + "FALSE - Does not verify a specified node is a member of linked list.
" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdValidateOrderedCollection_PROMPT #language en-US "Validate ORDERED_COLLECTION structure" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdValidateOrderedCollection_HELP #language en-US "If TRUE, OrderedCollectionLib is instructed to validate the ORDERED_COLLECTION structure at the end of such operations (typically structure modifications) that justify validation of the structure for unit testing purposes." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiFileHandleLibPrintBufferSize_PROMPT #language en-US "Number of Printable Characters." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUefiFileHandleLibPrintBufferSize_HELP #language en-US "This is the print buffer length for FileHandleLib.\n" + "FileHandlePrintLine() sizes buffers based on this PCD value for printing." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdHardwareErrorRecordLevel_PROMPT #language en-US "Error Level For Hardware Recorder" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdHardwareErrorRecordLevel_HELP #language en-US "Error level for hardware recorder.\n" + "If value 0, platform does not support feature of hardware error record." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPlatformBootTimeOut_PROMPT #language en-US "Boot Timeout (s)" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPlatformBootTimeOut_HELP #language en-US "The number of seconds that the firmware will wait before initiating the original default boot selection.\n" + "A value of 0 indicates that the default boot selection is to be initiated immediately on boot.\n" + "The value of 0xFFFF then firmware will wait for user input before booting." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPort80DataWidth_PROMPT #language en-US "Port80 Data Width" + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdPort80DataWidth_HELP #language en-US "The bit width of data to be written to Port80. The default value is 8. " + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultReceiveFifoDepth_PROMPT #language en-US "Default UART Receive FIFO Depth." + +#string STR_gEfiMdePkgTokenSpaceGuid_PcdUartDefaultReceiveFifoDepth_HELP #language en-US "Indicates the receive FIFO depth of UART controller.

" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkgExtra.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkgExtra.uni new file mode 100644 index 0000000..a66efe9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/MdePkg/MdePkgExtra.uni @@ -0,0 +1,20 @@ +// /** @file +// Mde Package Localized Strings and Content. +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// This program and the accompanying materials are licensed and made available under +// the terms and conditions of the BSD License which accompanies this distribution. +// The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_PROPERTIES_PACKAGE_NAME +#language en-US +"Mde package" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/OpensslLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/OpensslLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..9a23da5ed87451f71a15f83a6b035cfd96942fb8 GIT binary patch literal 46687900 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
?hUFk(5xN~pE`!bvmBq!c1Q4S z(r2#68qI>o5?I898E8UsTXlJSfOAll1D75?gqC?8IxKUezqwPFK^eK=@60Q^fCU_6 zO9edmfce@QkpjkEaA!pFWcb=>cLK7tu*OgbtEi2Bqj89b4q9H~`s_~O(WX8-IX*Hd zB6#(yF|%MZ@gWxjsybIW1@zcp5eS!6G$S;W*0g|c30}7c!b;DI8fkW;t1oWC0RUIO zv;flEp9Q4LEx%mKeEgb>#X1K(qa(EiXPoc7x!`j$7*|rGT5^@pY~1klDraUWETf$J6AXP{Tcu8AB>yeAGOu5S}&Cp|kpJ~{zms~aIV zl|^z+nU~~|2RwO&aVzj~6Twef@K660!kD$R7o6N#*nC6v#!$1QV${>eI;i*RVv*R8eD1*UgEqos0PM0 zE1m9vklclrGsaSNpt6orav>%i|0>K)CKtu7DeJY5Xks zbK5%^8GZn9z<>c6!c8DZGwnMM9c_Bg0}-0}KD<-mCMe6>=+7xJcHn^(PHS;mV6+0D z1yruji1S$!dT4Y7VHBqo%(TgenB=W&iY|lkPD6mJt%}lpOPnhA;avvG(Z2M!w$ZQl z5pe1?ysl+9y*vzRF2sDq_TkguyXdE$HYQXM)C4S-A?ouJ+)s4dc&>|BJm==a%1+ZX zD+}`RCi}$mxlH#Q`hn+W&Ydt%2Q{2;8n~=_jTT`-!A2{bt+wN>90sqc2hU$dFR1~{ zRibK%Dhy1j&8o#z;=cH?RQn{k)s zyq%zS0?3@8r$TZk!5fUQiE1=dV^cfWn1htuNDjyWpII8l&{&LHoVsoTL030HL{T@k zFP^svMBXN-k(b^0jWl+SMq(zpIi_LlwD%I;f;n&$IR`3l1&zM3D}ioLw4Aw4@ z-3^+h(Z#?h&Hm)25o}IrxG>-jz#O|`jAoZXC^7>ux=`#L%VT#T9|U2M!2PM-sFvUe z5?2UtX8n3g;lT>HTTtVIj@)F_KRVGw`wFD!NtNSfp-_o_nA;2Jge1-boVkcer-W#x zpTpH0lG3~a7yFn=LNtM~T7bGJGaT`-03=SjYR($=aThC*sqF0@&(2OJI&J{2H`q6D zcp)4a>8LV<4l26FSsBKyecgvj8sj8RkKp`hJU!AQvJPc4C~pp2tle#BHEg0EvGS5>xs)H4Bg70U1uiTqX<`n~3H;ohxDhS|t?>iUgAp^$lhhxxZec8(dZ( z_RQQNK5*>5d z0KP5|p0NjM994@-2vAelg25OIOHfUZ5uepAyw5_41m-Pum}8|%P&qIhDw70)DK*i; zQLZ>WHQA4I1{(p`1~`crCh~-OS=1ObP?|{&;){*mGcUSO38E34gKgq;Xrm!9apt9` z9agP3o?Cw+kN%*Pdj5D);~Qy>FP&I6*UX?`DwBdxMvZ5ID z*eFsu;k^^TVFNFkz~@B+!dBW`nH9B$e`GTF6KogExOQqDn)c;P>Z zDbOlI0CgDxV3r|Uq@;nYJcb#6uY|Z;Mlf(D!TuV+ zaV4&A;JgE&-8dZ9P|$})xa@J^L_XaAq!9JvT!4U#%D1-m(iy}#gotqL$x`rYc#>AR zVjF2z$D|J}AYl*J>20)*t=CrBG(PO@5ynRv;@USk+LQh02RMCj*>L%d!Q|(!4B&hV z4%mHIklZu6h6Rg)MuJl%CVm;VDd1_qi!k{>a?k)Vm6g98ZVw@S#HG74BjE#0umweF zWbjCQFHzbe>`q{03(Y)uER(<`-;3(d14kk#w=@(fy)sYXo!nUJOL0-7M=4ITB<1ht2?!v>KO23@I?Nph72SJ#u!2JXwi~vfZ&KRO6!$v3| zmT3mU5Dny2=*?|q;FlTP#)AK~nKmO=BRF2F;l$1fCbrL|RhS9k0SV~i;l@eVd)10H zuk?KvHoP*AAtzr8y`TzX5Hoi!U$|gr%S%{j)?i6U-70gc*K+s)gEMFdm#J&bcCH7o z@rK{N&|#KNR>6>Z<81`247&8rlMJuZ2AaFjxnh~=2BkWKF$0d}Q3~@P*<`9bDB$y2 z@*0VcX667lBTYQ$8#e^g=Lwy4Ug&GY^fV91N7a@aR0jevtgwtdC)}IVcyfh#8M}Ta zFc@OU0N~KjY@%ugwiU1#f#sZznlC9=sX^6&8wMl+FUx3wiic&n3pEB(-P{~s0t*R@ zKb%R%q96xfke2xYaVX9oSzOj@IDCV8T%#aDFe!3pvT*LwdxS-8g0c3mTpzI2xzfzj z1hkWY)6Djr19jN+u}fq@CM@aIK&*yPSi*G=YEy7@fL%q!tcOVo1}a>|LCua&ppFA8 zD04j!&6tP1a?8f;0`A#UvPG)46WkpdtkMiR-X5eeEGuIS9i7-t=%C@`7kFqU!2U`^ z^>jjScx;YmM`tIy<2g4v94mOl0AxP1&1$bU;10bHk!P&ElUnFysP2@|Ac5?v1P2Ln z{o38!zRPMg6nY_Cj^R5W3Aw6CBOVXVK&J*PjuxsrBjJxhl$E$}g0)Gu-ssQC{_fi1 zqBUedHt@mgA_d3Ns6cPrNB|85m|zX4gsa%6ntgzE73t-K5F}F_3aJg0h7$v9oZ#Pc z6Equ0mKP25@jvpgL%m%ao+?|3d zh0!Qh2}D?0B{TtBERQZh=^oQ1=?+j4Oz~RXG8RI&geWDi9et!PgrpaegErT?kqf0; z0+Um0*J}MN;QEV4UZD7{)%g|&E_kX5melk}C0r~5{O1BEFI?3?lFdT*8LS=!TMBDj zBA_wmY^)ne@iZOSumyB~t{EC!ODSX(zJ~`X?lM>`%RwGwu;_H1t5du(wXVvBPxb&F zJn_ud_U6SWh!{Zymm^UVFx)vhI*|EQG6o$&wY`;`Y?4~QGrZn*BEe7>+UGba($Ou3Rc_U# zp+=F0EeK_XLH{#pSuG41jl*i-T4HU$+cH|&{qq;5oYgqaWFgeDcX&PEzhcrxH6lrm@rK@Ob86#-vJ_I?CrQrkuvC?8D z^|6UpF{Fh=5Hqzt{Lv^;dO-k19)r=t(y0Wb>QjIfg~vsjTvFWEOAn4u!SK~=BBDD$ zJk4+|4B1;=7Duxk?pI9%k+$v}Yy(AgCn5d#3c0B|aChsn_Cu0Crg zrExZL60Sm}al{qjv87P?1Z0*(MnY4`K_tUX%q$8M-uPrr!$cVs2 z1bUkT>XST-wcvnm{yHU~c#2Upi4s|D;72ttNN!Y6hf4Aavjcr8L*1jF<ib}EI=h?smg#q7ErMqX&vPTleOX2Na*!?X@55I;hnrF$vWxrt!;DK{wDIEg#Od z>l7|zAize$&S`({kVh3LgXA1nwrsQjJD`NmI@r_*RI;@p;VT^6rwZ1|G}ttj)_g*Q z6GnK}4F?@G^Vrj>r0}373%9qbgu`}BII_EV6l`ow6!ZgNCIHVB7+dmf0T*;ue)ueR z;avpEnvNWI=y{kmK!$@mGF}|Y`5dZ2z2d&6>=9Zf?1v zjqKAXoDCxH9Q$dcq#L4{Qeee$1gQb(z*#Jb}UeMmdQb00T{O=NG!0ALt{;i z{`w$>nB0SoEUUuek6=3;Ktq=) z)4V3IiEu1n*Y_Jq#PI4YBxtcq(F3kh8LLXe+8O1pV3(&yLgnRrjYcvx97ZyM-b?T* z2DeLiPXgnt&=m$+-T+2vIq#!#vL*Vcz9A}OPX@C3G*n@O25FSgFxgEFvAU_idU7>L z5_(=7k|IA`a#+q&`(BY{PzCUaU17X1(kDhC-nI|1JK}1lI=q6-FM>>*9<;C)Zsp)L z?i3HE@R1-nIV>X}?qOY)pT;aIknEiTC^QF!z5w|n)idP#1TT%jS$l0TwUq6pA{qO} zbS?02w!Ez3gzYtpFv}BgY@877QYX_Unc=Z}UPnO@(FDz;~+Dc9~L2xL{?(Y{C*@Lvkgq0OcDiVmfIJW^T2P-$G z)2%A7%_v&r)_#pw3p}EdL(xnK?-v%~GQ;FnkiZspM^QoVqzg_563FLqSz_~zTvHE; zIhL!z%;2l%3RoqYZJ;m?HNX!BXhI0FP=obPDMq78-Du>%gDGAXMCg^3exrW}8BgLt zPO}}*f~m*8sTkdT7`v8WS0;EJonqH!qSO70(+OTA5|2k~?H}k%lmS$g1_ldg zldU1uuJbCQb2^6rL^qK7)W~dgDsjR94yf_WQG4i^Ge`ZLx9$;qwC4j4-Wa()_1a91 z^0{4tEH6m#rWhaXwb}LcK-go<=Fr2DOGvh!SRxH{kl!sO0kIZgrWE>kSFD60fqv{* z=8}I6C4@dP{B&0b5V3mY09tdZYPyuLThzI4mqUXZTP##7`9xsN)r=6`;4f*r(xs$b z6>_Dd&n@_h)*vZ0Jz!8uSabjbV*Bao0?(i0NjZ8^SawVPRntT7lE5qqEC;)4+&Ib- zr@b&KM}sd;M?3Ur^(pX&e4LQA6w%VW3wl-Hu8`C25oKV}tH-2e#WD}}U0j3aSB@vT z3phH5_S$tCE(;n^K`E^9)C}SEYY5lzRI}n;`kUJize}6kzH`<@gdacc39u z1r-jqs6hd=)~knCw`UC&l=E;!hbI-Nk!ziPB+-KcH|cd%=TH-;sX`dcTsq3A9D>X! zEjw06XIBmOD&ywiz%mHK=1&snvYa!Cg&?)?a%}^~vxzmZ4CIGq2>8vEN_BWOE6X^H zamy5TR5}KFx=<2>4_4G-`OaL6F^ZKB=ayg>vwc`)S|6mT3)8(&m>6F)B#!Hl9l_TU zm>{g3KAF%dGPNAQn-usk>}@z^bE)Fs45J1!9g0G5sXqhnhxxVX?}Mj=y%3{$3|mI9 zwhb3b^qmwGR4Fi7^nHl5aD>h|o`66Fl#B=DIENn=tmUeqCdGqxD_WO2q3;HY5Y*%! zBTCdX@fiXPGsryU0PR9JY zfu|DXge<^6hmVsHo0r}Qmtmz61Il-NY!GU6mtj^`r{wN|PS6 znKDhGrJ&afPP{0O(=3A`jJc+8a0P7X1aSd-gvQ%_Bs+&%u0&t#! zsHS%s$?dAz+1N7K=qoqaMw@c-#EMlcbga?i(S?nr3m4SVC04buI@KqwP_gh<;9kY8 z@dzL>BCrRlF?i`m`xuVyXni!XkBO!sqv9gQq>y!C|cdrRJ7c! zK==gkeg(lY%ym@nv3G!H2A>)n&(>!7Xa>ze{?H_C1v;eByHM={e9R&xU*!9fTc z3g{p;SGvwcFJPk;;t{KV&WOV=MG1dMK9PECV^FsXHi-JvMFC>z z3Y>$Zrw9i>Y!msmZ>ZhETV@?V$rILa2f(<-!=}&(@@f#zpxMNFWv_&(R#&i=hsnhN zW+1X;u_{H)wUc;|?gk~j?I?$UhE1$nYHDNMDv(@$3ZT|4L5dI#Foc_4Rkr|I32_;} zfJ-_aoA!g&P=FmykaPp_> zptw0@!EFM)pTLrdS9;BDi%p5q2bn}RL4I3X7}}_}FlsQ{!sO8lbqH3f-o_}s+S62e z1(E5+wD-dhJeVAt8a)7pM?VA{q)GvE8=SNx&%?`amb(bxVgQp@(odsUj5K;K5Jfo0 zhSHi_kZ2W*W5e-XJNA@LK|W;7$c3TS;IQHtTg0@Rw_-JtSYX17IrT7fVM11Qo@=WKV-i54exx-0!)X2t++kBG|r{2!VUhAj~n4CciuX`Qg|A=ZajNUrJWVo zfT4m%YBlEI=;&_AP_`mSclvrmpq7l4OLMkbU{g(}9eK`#Q+Y$FzSGWSs`9jB&zU?{ zCc{nT7O|Q4`jbnWz$BidM7FnSRR1_=; z{K$cIDETS@Q1=Otc%hW#TyFIns^WozePIGtD3;9@-__5mIUI+3k~g-`+>pkGAb1+dmK zmyBp1F%OuRN3lnV0+F^n?~3y{U5WMxso5xCdM76C;>UtD4e6a)mW|L3A`|;m#}N@ zrt;|MSVfXRs=#~cF=#NHo{ULFMBXv5TVpI3!yfcWG2<}S$5N&(W}|;NnK5^yy08H6 zdgpN+fK@vM4oZto@C(?Ps1uSafQTq(<}gYnxTS!vM5r&6(5Kknhn)c2 zYBDz+{Tb|EG*-dW1v$ikEe-Vh3FJ6hZw!H$AEQ@p^DjL_|i-8R6DsmHcC4W2e6QmxN=ET zSTJm`7jg$HbLI_JD{v3 zT*!b(afFEg&onA~+&r-kDgVm?VgMEuS}NPymACVE8t4$-+`;&gwQ{1#t(~ zx^c*pRvt`kON+6D&AKt_Sm9=_h`2mZ8?(D~y|oIyGagi`YnLq8u|thccP}$FEy!;$ z#qhX|#R%s?M<<4LFb+QOam#?L+N9XY8bnTjVvDrUnz;IKyHF1B0s~(HaEpA2mI5i@ z2%o|jm)-H$bni;pU|;MKC19GMnQIMuaKr5yI9Biy5W&^5=fHUhX=w&RZDOs&Nf=eK^x$q{>uIYsjJuN7}4T7v{ zRR|~QdY=S8k_mHkg%F5Va9@z)AT~ELJ%Y%M31QaTXn~m#5;D(+C54qyHPXOodMV1x zSm8J;Lc$fzl4UDL9EY<=t#COPeZG>%sEj5}& zJ^fQ)4&yAD8DYQ*eJqGtSVx%oF{u3`BK=vllPUAAEQk;@CxjUgQ$u`1=d&^X{4q2f z@=5^N*TgO!n#21VCHz7an2@`tNB5wC&FSZk$0o)sCNNkaRx2DlwWg81-K>$03NxDt zV_TTxK@;UVBcph3X2#lwQ7IU~W`&#wgwyjf5OsfYLM%kPLby?a>t=|dVtW?pa27*4 zIygAGhYlpP$l&@yN=UA!h;!+r!hQ2i49&pFJuD6Q%d%Rk7QZ>TYnqb}&UXs)d05V} zwSNpfQoK-LQ!H#P(q!miflXozBdt8F*}H^CU^sv=jT2T+0B6miuZFX4(6exV4@*s` zWS>hQacs4R6Zyc@XGUCV=|Np}W4%EXa!xKTjk>9Drjo%q#ULzhh})##Y-R+57Y=FQ zk8KXl*yD+A>Wr1+#W7|gf&Er{8D2jl)I{K_1`mVFndf^jofKp+OxFNWfLR};rvp5i z&EM`eCqvP!Y*|mpFOiuK7Q_)egb~UZB*>g?ANA{e^!_yzh7%b7-)Oh6W-)+kVLTy; z$C{kY2$bs5>gqaC5!}R9tO~Rkm%feu(Y~q>`34m%`e{Wp4^He)!lS%EzeBBL47xh2 zd|0T0Vg3Nd6K)^VFo_{mw}tLd*BQYV#t4_OT_8K%-zS6{6x>0cv3{dR@XK)m0Uo>Y^1X)fzlUr$7ehRtKqc(G#nOyK8VGyyCJ{UbmgS3!m_Ej zIbGCos!ZKQ7HM~eKiOs2Y=*c(vDJPCHw-9LYQ9&KyCb76q!uR3=SHw`5S&?~ zu*>7!yDj-zGfvBLTNOgrcq&CcI-8{wq`|C-?N$@GJw*iNW7nQ?Gp;e|6lHGmx^@m7 z?(UeK08!5kD`9^`2&izJe}Yn2Fl|^AbnX-oGg&wWw|l80+Ebw8OcAG15u2X*Q^4}J zr+~nQOi7nDXI?0+!8zAyX&@VzL}>}!o-B$vZ?ep|#$-{HC4|z|8;pAmY)>qeFn40< zB}jW}`JTfk-=Lg~El`;$m>ZJ;WJVLTBb4xl#+Kf^NbHX1N1k34JH5_{5xroj6Eq@B zLxV;X`L=1+gz>;*qV!T(qkSyGC~R~}Qkn(!U^h!^0?a-(;j(*8xa=9=aK|=29a}}K zPEyfE5rj^p|0SCszZ)$u!E<>lwHZ%DkS=K7vA>O^iPyNO?Og7}YcnU^a-A zCK8(cX~HEVn9l{(C^H!XEE5dskEfMN9PN%6F}j@+Cap%h_^jF|_6#>dx4 zP6Ii&oW=S4N^=Elf+!Dh9Ql3;LW58}XF zNh-ODvRg#C$d&f|OfrV@SU#GRhbDGDu}eA%;`ePnN)jfnAcj_ejKP6VoO_;J?4K8C zH{^Dqf{0cTit8#)OBJCQ)y)XH;Tvze$}L*#VphEtF(ebJ{8|TIMzz`w#90{5Ya)x7 z*F-`!PJ$U@L*-LMyL>#-qFZbdLB^)s9z82kQ=b7C6LOlkCL-|Qg18NH$If;%wds1< zDW2b@MQ*yQOFe$-6zTFaTwxV8Cz$~uKwv&sjdTEUC#wbwB@urJ@&W^R2KU42ld}$C16x$Or{1lS43MP@) zEkhXFESTj$4#9?!&~FdwG5m{PLx@9R=`(3?^Ior*8FbrdmcbC0=}63vIXfYp9Gr;O zC0`dQ;@ej-m88WvFk@KR!a0w)`s!$=Rs_Tm&Aw#1G$otw6x~YvEG$|$-KvXfV2L>yLxwljxi$J#$ zTi1+MjJjorm==NEhHG+{;`oR_h(gjVa$Celj-te!MR9&uixq8W7sJk+W``M2k=eRn z8Z~xinM54bND+2*64DwUGeX^Y%reYdm4sW37bw+=YryAp${;qSXFfJI)Ta3tB8mYr z>I)Io$``J<57BUnnop1T=pYRf^+`gT@)$<5&^N>@Zg~XP&?Sg0HlTDL6m${08sf=} zgNfWziBjUzJtMtQ!D44nY0ga_h9HQQfyK$Ej(w3Te&ch97Xdklkri|5;BfO=a}L_6 zx**%zqd6B>DCm@k3ka`BMq3gv46^iH#ZxhWb#GyVM3d3Fni0^PYWkj^wLQbFMlwgQ ztgd#H9zdfFtqi2$z|0_Hv8l%_2;E4+i4RRx@&tLP|&9tXtj%6+dVu;C&VNz#xxt z;^qf^|H!MLp9}{&cdlY$Z9v=FOq=tvc`R#?TLcA6h zLXBS)V~s!^7GOM#us2MOhC#yUgIULd*5u8O(+oCTsWY(j_kcSKsW^&hWH2Jm&7mT2 z0UNLWcw1Qx@s&QTp9m`H-YDXh~qgJNDVwY>{ix?#; z?T|)#99S$5)yAAb%6T!+6z|vi%)uYC>mke|&sE}SI>#Ozw(Q7dgx!1v7RZl>+VDtF z2xpb%Gk0^!np2MEa#9@)H}q@p6@<4hg~t%40&%79JZR_G-d+*`7wGw7`W%w*>RNATGT@wDb;KLJUOc%X8h0>h48$b~c zi)xU;0Vr>pnTGl)=Vhpp*;&suc!gy&L6F!EJYwYIYmirpjM1@9cdND zrWmA$oti<32BNeYovlT0g0C8zfrekF&pMIrv;ot-*1&eR?KrF7R+QOs9bxsn0d99) zjtD05S#psrzz<)N#;{H^9B41%^u;R!bkg=Ww5j(}n8q2N!)89MR*m#a1s**p;CzIo z-?$CVjb-`E^z5S-;3-flilPjUB`al|rv(f;;dV~_(@s{_k}`+KA81e(Kw5b9&h;6# zhK3|{hIczXH`rL;z6@4 zEKW*1#D{m;nq;55#Hc|m-(yE_&z1eo+Tpz z97zOF?S}JYyo!Cai#dWS1Ep9d%%Mfec727l4779YbUaf#4g-OT8ty{nb%z)V2gRuF9(eEjDvM@ohN*R0 zxinbkr=qtYREj3@FsHAS^!{WN_r)RcbP1>kFMv7T9W%^Rmh#LEqY{o}4oCW_k!3%I z&qJ6~k%MJznYWz7UJSm(kangG-)vIOf4Hp;`pqrEfuXHds%;^R3p z`0_r&Ip5AiP&>ymUcb%oI&KaJ6NclVRnUY5p64qV*ffs8aS4~Zk%x1Yt+Iw5E^v$} z4x4h}J~ie=&@9bKPb^9fXHV+27%oN}kne(-mcAJ~0t6;2nU#Qh&xP|;hm~e-qt$Xy zmr5^+;cLT%a=6xPUxkNadgZJnMf&}-skX3K56D6Nz{iWVUbx7Jay75(HLQGKlM+xa zZY!ta;J1lhvrQmZ0o&^2+OcJ-3AqvcYR6JsZT$yRf?=pakOlnZIPSp)6n(ibp-OqoQJcz)R)RsdgDxLX`TClNayTW0L@ zY{~#)fi2-GoO|Tz7~Fa_b4&0jT7cMt9f0BC8YZ<~3PW|6cFd-5j{%tzi)Llh(aFUL z96Tnk-Pp`|%_9C%~$#+2;=q&kgo)qADb@3+YnM%Hdm$>lu z2t99Nyl%Wy!a)f91;B#=ys^omm+^RE9Mv#jya=K}LF++;7trt~{3ad*SKxk(hdJC7 z6e}@Q`Z(5?RNM;OgC)Kn$2dqPhZfnk0+*QZ$_H8$U4{vQ&QriZKg1yo$0Sqc7*s{A z!jT_dXoibS@hFv!Nzw}MI+xDHZGSr@=CT;oRlHS&oeF0--p>Gmt_OAvZjpl!FTSwX zi@0-qk!cODQP&Z93znBpRo=RndahSsg5cYPuX7z2W>JjF$U8Cq&`U!71x%Xp%;-8E znDOCBoSe|8BnyosU~jBw}l?F@nS%9l0~LgVI(QM z1h3lE&i2Yevnw&45zS!pkL-Rbjb2Tsuumpj^T{4))mxwk6#54A+h^XsOJN@OJb~K@X&HXd-Lq@@?FHKqpRGr$`eIUWGUvn;rm+Ovzt zV(2|icR&s{c(B9+q3}6K{uZv66dM5e%pTYZvUSZ32DZFqfkb%I2fN>u zIfWVHkGGF%c*eo2*>Hx0C$3v#1uDJ(xHsWh1hw!cR@XG8Rn3!ri zyi=xNCnY#vGkHeRPwt?ZMV*c=E#hdD+cwUzsD_s!uw5{~3L3x-3#^s#K$Rg?S%Uv~ zJj4U%EZE0%+BEdjA_cb*c%h+q4lu*5H=~2XfWoF6kIRCUQ0jwd32$XbgF%jM>Q18# z@FJhU#Wh}qG7c@AqqPs=1w1_%ercDg90xkyETlbB*H*_Fd~?C+ePuX;Uc%{GCE&Bb z&!Mhu*~gv0&*8U|c1TskGDJ{#@E*>At4;0Ac{#(W4R7#xsd#jWb_|^!jF>DVHZCnv z4Tj&}$S=_nT7Cw&&Y&+B@iS9_@wOu#Mo-uyc|M-Fm$TBxq=b0W0n8}8uxZu10{_); zY?URfp{^d=mDsB?pin}X2pmy`t>95pypM+Bv0<1Is{wLk5zMg#a;q$OpxIAwCc{-b zw70FpKPgK1nFXLI*8*LvEiZ*te&QVN>2X|W zv~XsZM|$H}@$ljZ9DNVid*2q#x|+f_Lk1Vjl!G}nQB|+zAm<_%e&H!*v9C|aRie@1 zL;_y6D5}4(s4}g=YjX^rTB);hbVhG=YCqWP5F!&@jH(WyO0=t;A@E#8NIfSQuceH^;VXspxKOjUwJDJb!R zT*bjx3TwqW-Jc{a06)mXdy5s;Z?d*c`A4Gv&G=znI$6wfLL*d-6o z4o>k_?aArJ0;%Jej?l2(!lzM2Q_H+OGS>>6DDrvf=pg%{3&!CAe|W(F3~1dL#)H@G z;k1YwlHJr%Au zZG4+E!;Kk$Qx5p92G1N``{$0T(FwBy^aLL$aJZYYM@tN?%B9D*#Df}j4K_YzrCAf% z%|M0afPCjMfmlN<20Cxxm$-s~=sX8e+BL$HS%qT-fUPaU_nfT6i=h!% z2r6qZfz!_!Q%xXr9-Tr#_OkUlB|M|&prfI(VPs?OP2g*CV?88=Mtx!-Hix?k zj3wZ%2QE1!iqOfS>WAysFoTK!yf(@Xz(3!3a(rqe8DQJM&9a7U;L7*_jzrZ7MPe=` z598uJ^m2?RCbwvRB*ks=2LbjZ|7IdJqAbKWjj8y_i(zrZpJ(I;DcgwhytE>A;Sf(# zNAjdwj`3UzBx>~V%2d-0n9972d|FQP1*OVJW#?=kS8Tcu!oydGs$iT!;w$1PCW)X0 zo1HN!p@I?1x0#M$M!J1gBG&+ z;AxmbG7tVpAv&u-dO;yXc=S=yYdCu`w7)<-`*<7~w-7U`elc2j&K-O#qa>dH zoPv2D&WofTsW{zb8$^jnVxypT)9pAagh@=!OHKHq;#g`iqzkbJhDZ+P*#*_z#jLKu zpdo5u(O{o|YRd4=P@LnQdSPL4X}Q0$y0(tv75L_KM)LhyPIIF*BaWfsTg7YciOwU~ z13HtDNEIX#kuaN$8pA{gGA?vlAmQD{hO<>>gGlMMk(=qkVo5c@WEEs*CK16L5EsO^ zk_zQ%8&0!qLuhp{&pB-{R2vgme2j^;U^J18)&725`s?W#~9dy%9XF8sV zNN5s-9D^(u3^@vY(msLXnwt)@4Qoq+xeJow*_7RHrUE&CTM#f^uQp7Tj`A@GIS@dKODqD zGRYc_JBo1=fR-F2vwn$-lkOHVP0yxhbY1Gx%uz4ROc9utX`0X>aB)iNApC08XBQ_L z95BI+I>2#)UIiEma5KHRS#1&t1Yd*DeIUPfj8Vz55JyvaH`V!}>>5^hggzTM#C^oG zd#vAT*MaZ#%=HHm-aw_Q5op}$F4nIi*=04GZ2oH-G9~fOE zl|jlF^O9p{Xu%aivWnOWCY|VJc8Zt>o6`bHI2+ri|&|{)1o{BMk zT4h0Tt$+*!rSVkrnaWso33iSW!YH0>K5rS@Fky)cAp@!Mh1~OfnZKZP{hvKtdWpJC|mA ztIplKzz@^BJ4gfy-2MwN@Aw2YM3N8!fT@n+p;ZrRbqKbgH7|%yv3bQ1r?B{@1fT>* zxd71xg*q1B6o$eU8oF{IPHG;%-4t0=czpJZwpPK8J|UdRK%hM5`EMF z;f(@x0kVOTm(Z4yf(;05DvXV6L`(QsI|DB&BMDi~OfqkfyTv(_|YOU${F}f*M23ds#R8=YT6CcGXS2kWD zpW9EfhK{g?*jFgtmwI+Aw(5J;YQei@OexlGRUNtG3 znV*=gJ3rkQeyn10nxB;9=O-rU{KThheqw5xpZ%onH?#SP*~9$Agfu@XN#-X$b>}C& z@bhC5;{3$4e10UkJ3lTh&5z1HZnxNRe*Pu=R^Uf{KosV7VSG}kiTH#PO>t&p!fy3_ z27x&{KrrN15 z-3$5!ebnB%4<=hkO%z)}6as(&r;I^l(XEQg<5{hh#V14JiOAZAHSO%b8-XBM?Yym~ zDI(J#>3--hY6yFLB?{~?=5_O1GOf5kNz`Cz(uwyPX9lipv?!a!9Hl^w?ecns2K7u( z(BbtHCy!*6NbxgOd*SSJha(DcWhAF6%SA5W7Z^n1TPrPw6me=YHATORK&p{1C&OrS%>#vl$x z=G15gDNA?D{BRi|x!!pbsDQ(-^<;hLRXAes)>>fPgI?zO+iD$GO^><4TmbVCFcRF- zOz((TF(GZU^xlCTB#=8ex2q20&Ir%z%Unp8>VViY+4ps)y7^eeR5iOS2>4 zQe*^dMb&<}DjPtGReFTTgxZpWLN9QeROKV6U))QooZ3Zwx%B)>K3vi`KhUT1Vm8J< zf%qwnv3EVi(Ew*f%)E8!T3O*4?vsOdi2U_`T@m?Lx}uNr!&iM?OtCOVnhLi+v36Y- z7}AdBOY9LPl$pM9f2FWbGWA@RW5O>Fu|3ls;8W;<3i#zlHKdD3+DEdLcRW41L69fv zj`_m+3<)}T@xizMvT3mzBM!X#?!Uy=T=VeDd{>@A-SRuDn}k%iJovgXs}Z|qRCf9qsOE$LnBKl6jkG-ve&-dTG4fE ztUe|T4EGp=O1sCjaNKhmVD}t4?w+LU>9gwo(|Nvmyw%m5a&;cB({O2>oyY4ifJejG zY=kae701b<=m=f8*n+ca%Q&D%#CEDMPQVf=**qOB31~JP5Q2%k$$aPtv)hJ%t7@;F zZr5WXXiXY5!#FmT9AjrX8dT1@9kF-(#Ba7YjB2Z5@ z5$qh1;JR5-z#6?CC7Y5!8sgFgn-05T)JO~}v65Q-5MLANUhMbfY=+Ao5!J-SbMNi4 z-{Pm)Ot9^~x}=qIJ%I~p5BzsQsgktUuP-N zQ^~a}_${f>BDy&Rmo)bceGM-=wVGc;hWq2StJo%(5`O0&3p5G)chEoT#SMSlR-#vG2L0n?WPl&;5^r1R zbNx_e3*GiPsKjuu><@)j7f3pd-};7GPRy>5b?HeRft7F6~-StYmjwR&zeiW1?i-7*O6zX_1Ar2mSXpnSzO&$ah)A_ z5tf{@zIp@$T(92FqLbYZIqR1f1K5JffnS{;z@Lwt9}6>pSUb%H4Ud4%^3o5<&j)aS z)VyLZjaEo7qZE@oXyuLHaUtD|T1bkcWfHDX}nDwL%g6P-XKGcg}GsT|{C4nLn_9!Tvjy%e^v4mUqfx9R|Pp#|12q;U_Or= zTPtV_Q!btCE>Aki{d2UYiqCoZ`{UQFJ~21)I4b~v-QflGtOh_fO&iwDC_@?C$q&8* zie;}RDTGjSeg6#7?ZLN_!wKF5lFS(+*|x}gm31EarkveBD=Y)rEhlB(>xaHO)DL;_ zem~@`vjaKwvA^q~l)lF%N~llg$bG1mgJYmYzu$CzZ=SR{V&)RLsL)6#O&)!rkV_@qSmr znG~BS3+mn&t;)BUxev0!-e0%TLNaTO%=msA8MsbE^ytqmZ8a&ksMVz0qShs4rn8!) zqnYopke;2k+UxX2nEBX&lpK!WJonxXi3PfwBEHyL@9|B(o@25b^8;-P`}x4De7D4^ zB$*@qKmoS_-hBafS7*n>I$g>ATC+u^x%F)Gu>kTB);IeDugUuZuPbWPIW^)J4i3B& zIXv+4=D@&9^1*?Z7w-(bygD%OA$fm@PcPmX_>@6v^<*FH7>1Yl_2XN65Soq- zMMn!2aGfCXJWDIoYj|V*O|ftA?5-KoGQk~6PqCf8IcFuR zKCop5eUV1VF!bHBr(~f-VY+W&Ja7*AeFZGqv78@q zoAD%QvvD)$onz1!_JgY^F8VPxrg$#TfuuaRO#ZEs?`2%?o9!1k%_@lu@QYj4Kt^JZf4GK+ zcWaO#^eb1c$j@ROu}3fK8}zDAxNbh}++>(S`;3Sb@R(B%tFIaVA+P*7CQ{GN_jMA2 zC&Ynw?o;VDHmv~6tyAFs5D_om=fyi+VXGY={H2WG?RVAYmRTpd1T)zMlQIb%!T??}IuwiUODQ?OiVG;P4+F z;LhM`3q?#LO|~u7G2Cy0xMH|$i6vf^8ZNrK3VkxlGntiPVU#;QmQa)U>+?n~1d)U;*juv1Q$;WnT}(S;(eK!=D^`^~=jc zL!jw_YO^&(4#Oty55eAwh&0^Z5J=Xa4S~FWZwTaFJ_Ncvmq?FqoyF>;vj`)yvBD5P%Nm zNXdOUBpsEEgXEKx8^4MPFjiXgkCfala2g?= zfP66J#sFh9noh6@L#lHmjrYTQj&H|kGRC27FuKlOj4?fEC*WZ5!h(mKk8vi$DUQ2- zv&&x8!?xiHpXxV`FVi<_JV+*mct-FI^8$pD82~zf@6xra9zIF2%*Aq4;5&yhNnecs z8w^dp91bzG8c%dUe$R_tjz{zHyco}7u`~v~vKfHdjJjHe=BoGS%PJ{Zz&IQ?!cw9xnYT!KnV_mYhv%XTLT6X zvq6d3T^MAr3yNVJX-r54%L)`QVjSwS>9mpHBA5(~3V?P(6Bt+92HfsJJHpe_Oi11c z&>|)kAX9j3g+@?^Z3TfXW^+LQu}PAdIoJ~XbHEZBHlsG=(ecVgyrnmb#drXwR;VY< zN_Q_iV#e)dxig^nAXFZ>Kt6sX6g*)xB-LpMcj_FEd%wH9#VcM8Jpbr7nz+=}EH5yB z`hp2@etLCArHT^~2b@)iJLm!o&B0+hSmQyKo{~;y!lz60xkgK}3uV3a(O zrt+#Fx0UcivUD`j^AQ?LD6A74$wsq=02cuW<189?sj@PH!w}5k?P>S+{7eK~ShQrS z3Wni`eGB?%--VMP>V<(72U|;E4!}X{w=v*LoEA)ihd`xcW(Rh?hBou1W20FlVk8rv zWmGazW$r#MRuwTX4~~3yQD#y)G|a&lky6z0f;Ka*`0_*~n^e0da7TAiM5~b{9d%0` z-E>P4F!o_5yPn8(x6fO-(qm(VLJSzjZo(sTrLDAL+ehM0iP4gB1f5O?3Q!BF?$c#6 zzV|-WO+;#ePwqJKi*^6O5542q&monMgeGJop(*c=gdB5`h|_L_lw2$yi95}cm+-O8 zWOV=4QS4l2`k?F0>R}v-czKFaq6SJVy^^Q+3KH-}$T=N6`{VfdG^BA?gr6suF%?)e zO%3|6$6NR6@z&o2w3ut}hbX}`qvwakT|+JkUS}ycJKd=I0)p3Mi%&L-P?i1)k*eg; zEjFz{)}VX)`7iM$h>0$bPu!qj@@#`rrCL!^>uDkGQ>W%zJ7GY4{_;6#?Npyf!m*Q- znLM2YFTx5LparszeC>Q>`z3!b7j{-a5?Isj%nY^u@bDD++&hjF5TET=cIU2I^62TBcAu z@Wo zT{)QY-{De`rgmqzqs`r5#>$XD2g#023$iVf7KtR27KjUzgmuBKsD^Y;+4K#!b~jNj za`L_-OqREt$^vrd3M%W9uHYg)ivhU~k|xD_+2xSOJj1UliqsONQ!u7lZ9*vJ(_+2m zxs%1zJaPsPsb-rHiutryvw7}h@ipJ?7?YRRdv5=~ZbV`7fVf;n$nW=ZE~tUU6v(2# zSrzUQx2vL5*^(O;{h8YCUg>jamrIH*Pmg&9Ga`^6B9D(N&OC=QAt@|C{~Q;ee+~=J zKOz!jafJ~8rhAFa?+|pLgIm%=&?%#ncH@82xd=Sn8180>T7LCv>iaZk`e=p-Eof7sptQqe(&9Lnv@jMn$?IHLO<8N)b83xyj;(Qz zzBPeW93u6YO^ODQf>>_iX{Z*i5}`s3IrR_0FWeIhq6jY>@1Rl9VKh1kT#mo+%1Jm> zy&uf`GqL9J3_SX_0zL=B?l8HRK+iS>aR2>>`_Ft*JsxQj2WrgIs{o^^7enH65v}Q+ zOi1W}XC6*RTt(VW*MkrEv4pFW#?+Q)evyf`OpgKt`O2%t5=z1 zN#C8B3~5g9q8W9RToG>)F7?=i8`xozq)%D8rV6Q^>WNP`8eUq8bolKuoPq_2`u zeF2X-)=BU&@Y19L-t2$Y38{D+gjAYSBv&>8BdBktb?GrRualPAr!O8>sOnPpI%%C+ zQf7T&s@f99ev1X&%Qx+j#;cJy7W(8SbH9sn3%O~C(*^Q%p@IC|Pnkizbw#bR_3w9^P5gD} zHPiaG`$dac-pz0N;|Ur!P;pahqH= zV^F!ulBlP2%!PZ_mTSCa!ZUZ)#q>kNi2~i(R8ppKmBL_i;aM=DwZ=) z`f;lKpDjMpPYeq_Als`mnGT8WfjmuEc>+^kopBVnA@wP4eD40d`N0|q%^BkINRJ3r zL%1x&;cBIRF8Nl}d89iZO!jp!WErdm~25)Hr{ z5a|WMYQ$q-V~Y!Nx!BL={}VqpZ!n*PbU^tN#H?P{qoJ0EXdqCd|8`bEEZ+G%Ge;nj z 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%0ALJj! z9P{92Sb-BEFF_)G_qi@g^IBEH)7=%4fe96`g5F+7u~5``5VoXwrtA7&7EA{*4p`5x zg2BlWJEE?tj5J6vS5sAG-c*~QXc(?~EfUw1B4^CQsYWP7dMI4y#SOukw0+AB5Ka=^ z;E^Ex#HX==e}!>|FcPraZ{@IxF$NVkF^^G9SiI%+@%cQT?Hxc!(9^X>iSDCwoOfpZ zN$8(yr|G`FRRfhPx1}GF*I_4u&vw@!ZV5%u!*E7*CurYhRDsU{&V-ioVW~`@5%}iZwOpXM^^tY>z=wm*@ zVo8`(U-SERHVh5eKtSM7ogppjBS7{7=W zh=do#3*@ud#R28BSOcRQOphzz!^ibHpg5m%8awbu?^Uh<1MZ|6g z5nqJDAATAW-$!;f@tlraOeeNx1Ov(0%c>#1)r7kB_lKk8#8NJfVnpY}f`u$U=C31J zP>TF0>>FbLjrkcf)A|-6$>GYF{CgZOyxN4gXm|B1)*2!CAONmHDZV&+SiYMFg0NW@ zJ%JicGqv4~5m!x2MFcnjL$WANUSk7d+1EM_sjH3M3pZzH)uG4jTXpQ#M9Jd+mps!@ zn!e>kf;l4dQT#iE(p6OQP%z&LKsd$=2QIzVp`YMNS0K_87jJAT zUp-R{5X%nRf6_41`+a)?ia#Ji$h@<2U~njv9v&IZkQ_;)6-!-2f)kK{(Y>c-@3Wpu zAyCq4paS#{ci--UyG1cCK8DGxu$z#(8Q^&#mJ&e;G7@)hiaD$zc~;QqU@I}3(-!N| zuxR=p06FbRXXApc!W<}&r;$L<{8|w1gPy>^`-6W|3bTg$JiL5NRbeA19xlCR#agTcL57|t_7Fe`$tM&w9-hr8yOdy` z&*E!@?gv*Ak#Qn68XGW%9TjvyZ6Fb2ACPbugsrD)7@8gOqQC<7KhhZvvXh_zVE)FX zqUNilPVzuN?lEwREqrATDf8fBx6iRi3Zbh+LKFY2i1LYoU!vD_ucB^Yw!$ytk-bR- zp4c_!96Tqf3LclZH?V2e!CVvfjrF0_K%W9H4`w;cvKW(iqBRgPRFez1F6k$>Kt*UE z{Pr)azP$`RkKp8fPHdbdbgLUWn{L^_$ z$!>@TCz}4neT$pZOQLkxMmuDmD6^I$JvnyMT4$ZQEIVACrwjMNkrosa_ zeUHiuc9@JVY$#Izb)fKL4Qq=wm7zMqc!*69e+SF84sRLluGsVq7dy1&a$`hwHOPW# z(}Wq;O*|CG(xLI^ceO-302kgis5gp$8N%AffdGGoHdX0JaC`DXQG-& z2(o=273(Aw!c$|JPS&;|I{kY-qAEz}gwI65yI)6SL^r3$ z8wX8dHVN4>>iS>&65#2BUXF_rdKw`BY>C_SK0G+Yj~{RT?8eMKU||;5a&vR*c~s~7 zo#(cJbIvho`v#?t3korG=LibyQM-7JJ7gF_2OmUYL6iExn5Js^-IK1$1ISsRtC1bj zlJG!Oi;Sn3x(YJjVyduTbSq)^@!L%H3cEwPCJ&q%0ImQ~Ui_sTCah1WLid&jan9k@ zgc0r&(Xj6UJj6emFo#lWC2`Hc4O7mgeGEl4HBYK?Y`-b*-rDEl2ki*>cs z1Y%ZU5-~?v#stAesvg8H?01A?6>yEv9fz44KpdAdGUA9U0TG@E9w!?1D)HdIfawR% zkmNmt0rt%nNA4mJ74)DYPEY-QmUe&>b(3OKxJexEP)kLVM@*Wf@jikr!T-D^x$NRj zw3|(zhK^#y^w9_cZrB3N93%8(V|jXWR>{s3BPk$(ImDt#-0~uUWrx!QQw~B4Lt_Yn zHP251azpB`Qfp7r-IT*G6%Rtoqw%(ljc|1=Ekca(LeQy8SeQ8C;frj18>4-Hb8BS< zL;>ypVv6Bj29ldKK@N@%q(;Uvqafm7b#b0fkQ|^hhm&ZO_YTB7k1Z7Jbv25XUORRd zDc440ith@3OF;J=cAupb$&v|FClUtr^wjPNw3$;Kpc09m=_x!YMZWBs&>1lYie?g> zAieE+vC}7bC=n~gt}UEgg~1z#e=*ip6*n*C@Td@1-*_H$qKV*GL8Vx|Ohkg9!pGD_ z9MR>6(bI42G|-z%^0%&cN^Y%S-iIxB+(blnQkq9fRY?&7leE3Pm^z#eAcG#hqrwTs zW;HX196^%$h*Bp_i&hL-kwIf&$orGxr~?|gc`op!u)UkGKqz8VB)XJ?y}?n-a>fGI zDON`GpVN*VhjQ%mMS#aleG%C)rkc`3U&ptJ4kZ1ZHATjOnhq+3JeH_!KtRw$T0QLH zRPtaK;0h|a$LSLhf+rTx@mnRA?m6ZI?n;PEeLXj!VAgpgh;-!sMLO*();A-7ufh!+ zi=*=XAy9|;?L3n#=U^&tXMHs$ggg{LnH+IfiCR|NVNr1?OgAY;)(;{n{tstox*fN% zWb5-V{Qwdr+14-BJWrRT+;;z|#i1zih-A?$QkMJa@3$idL;@)KxR?91SU@6?$T5Z; zJAw};jKaki3=*Z!kaGA8Wj=BT==N9E(#W~Zt(180LXfc5k{M|Qb#Wr3ib+AiANaKU zLNpS{n`?;xg`i0(0LV~|S#(hX)__z33Q_b2v2F}}zlx*5i6q}#p&wG)8i%05N$Q|D zPw1o$VY47H_?j3hli-6PwI;*&L70&y8;p0OI?o1vPgq~H*!mEwdgCeOTgi$fVr%Br>OcXkC9Mu{ql48n}2lhy{g)B17dn>>SLGp zlP(#fVMBxDH@c)+I8!g>$g0HJu}pCv&4F$>lBpLeDTTa2LN3UUZAuA`Hgt;X*4W|4~sHL>8+tkz08IAzq=Gp|%yp(CHL|La}U+ zJKcjhD_e%?3&A|AYT2aat$Va=34algMZGh)EP_Z^Snepc8j{qGcQzMe(QCM8dhoSE z3SS$wU(p|~g{v$SCWU5_4#Z<9(hgdzaS~oZ5yo~_z23?d*^-%CSe!5zV78U$Z6c+t zq^IT*^<79zcn>ekq;V*-!xZKEq*_$?OcWIW(YGFsR5f3a@uk9k4<_g~Wr7*n2a!Js z5kvC|%>bKR@!qxaMZ&V?zSo3-n(VeBqKH!-CnD!!gj0w0;cHt#`Gdj)Ls^Br`iird zJ*JShR*>6wNiqxa{C>AVak;o_k+z^CfNL2ws9HclysvF~@c5IA53 z=3*X6b02K?)z`XkA%ZhhcAHbA(ZUY(z%BqJ#8DgYYWVk+x{YkcQ9U&1S{;%`IYRoy zD-g5~n2?7}D5Ode1VFChOmYU|tYu>%paK=rcrb!|6wG{$PvAIHOj~old)zp0o#K#N za!}RBcGN4DIY4%>x#S({o=xpAXqtAZ42TBwCebeK9L|1jZqTtLGB##ODQXeSLI4d! zySElRza^A-i_zDom;urS>}y7(ZXBv>pjIsZ-TJ0?`{V%!6eQ(0cGO^@3aY0dB2Q&% zIn^lf2m@Jap5c_gn`^)ssVFxDXa_SuY4OD(%|ZC`__%+<2~gU6d4`1EVxn<%+umCa z9_83uFjox=DfF5UUp1Iyd0!lB89^Y ztAwP{#NakTN)v6xtY9H0A4QAHjA8ToC|GZz&OfreqvH)gN-w0XR$Am|s_g5sN_z2%R3e-F@1ENybL zg~gcTe;O+xK(mE~#7m4W`CccZU^UIomnl%=Pag}sF(rp&^@JC-S^#{+321f{DS&mX$Fmg;D+NH?0>LKV7V#)I4Y<0g@AA1>=@+4 zn)cDytOh}Th*2dE+}UStxhO^7HkhqvP-5c1iyQQ(4~RWFI*Sux&>4~0mPB-u5Sn3L zBHTkIMf<(oau!PfexZ!g!4!J^a-~;yAxQG*52^**2#+N6 z)NqNwLB}sXoArY(`Da7HhSeYAsV9@g6 zegY(6Fj~vz6zGN!T3udfzGbo`xwp7@Z9YUI_vU;66$OS6`$6|@JQQ6M) zL4mftXb9BUWVJ$>$y4*VU_!m5h=go998Xc?xZV*~s9-=}FY#pKjpD8zu+d}hA~+BK z+=rkV`hrm2&Y+hIwpKHWKJ3}0>MrL2F(IUn1N%@(vQql!q5JVkorWZ}U`{R2o6BGYE(BIp2l!E{i_H(D(e;L6_p>7)N#cx=I%U{p6W zfc7g3M=Di%s$=(4MgTW+r64wEF33kEAH(~QXYTpe+e5oZO})ym!&%Y^UhWUKAW_ks zEFjveew0+|aKiU2spyB#XHu6$J5vu;rzE^20O(=lk2+;I+=bcyFcn_NsoJC#!P184 zoOai=3zv>oilH1sEE~2iNTp1L5%pSQF9bV)R~CCkwXa8c#Vaz@2wHbU1|XKjxJ#I{ zl9>S;?w6gQ(AQ5FE+ZH-Z3Fr0g5pC0g(kG_pAHHmd<7

u9j_qZWWnDww1J34ykKLd~ z*sUiRqw~n55yIrFERzAt<(4DKcF4E`ecY&87sjaHSQsh^$s87)u*nN;*}BV9kR2GR zK()e5O3@V`JV0+)D=0c2kf_nXi8~z(YZpiWE?m@ z7I6i=1LPAp|I?_kPi5b6wG1c*teI%j&L46tKO;0;;y42+#qsHj!9xg08+s|N7R{7o zHL0mSLqunyXGV%Os#G5Yrn>T@f~-J7?c93CK-v(%D2OphG+;KGznp!2+Kb*Clv&Ra z9x^`wCc-6wxSIwYS$zN4{1zCdAnC@DThXYqT$QL{h|uelAF6}{d^#aC`vNQR9Vft#(3(2Pza*JFL!jsfKc7GGuoqk;knP?jmx~ zj|#&(T=7|cbl{oB$P9(fChbt4KD6vnREcs-{FeDYgA5Ju(gNeYJUNMtf}}gaLj#zN za5mV)?pm$5DhHzq$=aEXch}Px48vR#QDV_TfMT%ItU3s$CY`j#fv7$JNl`qCu48GE z=Y*D`f)zF5WhNFRsGE`i0NKhC_4pNrl;Yhu-^Xy3U=UA)5Kx5on=$~b68Q88Ef;5Z z#(wJcVs^N7%x?@L9LY+U5}e$I#kvsQWB72T^V>IcOmw`O%4U;sH6~*eekW=K5Hp^_ zysVceBb-@R3no(DJ%LYyWY^%pOe$tSKC)>M^~dUt-;>OAJ?Vgj21tzqfVgsaO9r#2QEnwIeFG|o~4G_ZUo}2Tb(7c8n#S$umj0K9JjACWP<-xLgdEVc+-~dYE1!jOl zG#wUzz9KT22wzO*@Z(EPDgu}}*NbtJmAF1`Fc(00UZy!~e?&m7sYEAh)L zoWTTF?3r_j+R2n&vm~|_B&d0aJFj@Pujm(Kw)Hp%0U6ZFxoILETCdfC8>?*flOG2m%^FJ;F=KFty z{L%Ap1`lvK*LD;LGU^)|aB|dr;_`xL^dIQSyhe=m3k*zAHa^{b8R2x}tSTTY6x@K7 zfQYQVUt@4B_DsCwkb4nTEW!Dgt(cO`j97x6hXSQ{0f|>jIvtNegQ<%;U{WAWfx_kd z^z#`6PK;l*Df)3F8Ey|GiG=0;+0RBwg0KEpfz5`sa?k;?_>xlKW@TBB-E~ABz*I1J zK^hih@~%L5hX)DP8yDKyGBe1C%KkTl_?H|=A0t1EzW42?_eOzN%r^)^x^QeS>x>Ge z4T-mp$%!F9f_#%1QD7t}7gX+yBPvU_ur40x`nQ*sE((%v0_yYTw>JusvS9)kEY+B& z5n5Z(o1`m7;z5M5R8Ey&8|vHQ?8D=wyuQIaK&Tc<-QC4i(-VOHivcHj42Mn0uqx zTh~)4U}cQ2mRXyvM>V25ZVCjO3D;7;fAb4yy&xOl8s)Zs&SLaEdDcHKrZ5Sr@#-@< zuBuWdCDb$}c?UOen062}WD-m>xt1Y`35BMRViU zX`(AWCNACLW2C7Q35E}|YN8+}Wg1Dc>Y)y9bA_?@H?V&KFG=QxWAP$at)aT$2B-I;sA)&qbK^uvog=O~K{fDp5g9+W-7Gsj9msJX=&j0&YV=;pV<(Sfa3^c44xcRP#tWG2+t3@^tA1Lb{8u#gE!>%Ifh z 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 z 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�gcp2|2- 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� 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 z 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

$pkQYS;Qd4o)m3m*7T@ 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

ushx_ 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

MI`Kg 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

skBO3FKv)EN}HrD(l%+k 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

Yo{A?t&%~3S=WvvY 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 eMB}}ACoQC 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 z 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

=1jYqi&4`Y%msEumh#4zgcadyZ51!F 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

}KZJCoEA-K)>` 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

nY2P$C9Rg$O6#Nz(k5xE zv`yM6?UnXR2c(12pVATOgmh9mC7qVeNN1%B(naaAbXB@0U6*c2|48?w2hwBdiS$&; z4rv$CA*5qSr;yGeT|&BsbPMSb(lex2Nbit7A$>#oh4c>@5Hc`iNXXET;UObKMuq$* z`%+|u6kNxkcO0*rz$+*5$|<~d8n2$gYk%Rjvncg9N}WTg^C)!zr7oh>C6v01Qddyw zDoR~Lsp}|p1Ep@F)Gd^{jZ*)h)E$(%i&FPc>OM+6K&gi)^~l=S`WPjjpyX4Oe1?+Q zw!7ALwtLq0w)@r&wg=XZwujbEwnx^^w#T?+5iPpw^T&#c{S*|>k&*?QQrtv&JR zWowVSse`SLt)s24trPC6&bI!xF17)-9NR$LYlCdvY=co_2x<(q^|TGM^|B2|jS;9Z z5;aDl#%Ri(Ap+Hng}ME$%>zJJI4Uw745B z?y+^S?!{xDZG~+=T0Vf558`nMt^bME52N)XX#FT!KZe$iqxBPL{UlmHh1O4_^)qPw zFSLFZt^bYI&!P46X#E0Ozi8WQyJXvEyNuSap!KV0{Tf=oj@ECW^_yt@7FxfJ*8f54 zchLG>w0;k*-$&~Y(E3BP{s^r~|eQ?e`qR?DrkR?GGFy><=9y?T;Lz?2jFz z?W=8L@EB`<;uvRt>KJc-=9pm57AD%;36t#Yg~|2~!W4T)VXD28FwNdsm~QVP%&_MO zGwof4S@v$iY_rFw2u`w*~bZ+ z(dHJkvlZ=ZLp$5i&JMJ*6YcD>j~8~Mojqu0FWT9McJ`y418C*v= z5{{sqqiE+C+BuGPPN1EWXy+8#Ic=XToIyK(p`Ej6=Wn!g4(*&rI~UN-Mf()tl6|Uh z**;CUVxKNtwa*Z)p}p(&nZgbGEa4`8zJ4LRZI9p_^lw z(A}|I=;2r)^mMEgdO21Jy&bECK8`g)U&mUZpJScS-?3g8;MgDxbZis`IW`G{9h-$A zjxEAa$5vsOW1BGCv0WJ9*ddH`>=Z^hb_t^$yM-~1J;GSWUSXVLpD^CB#5KW@>ze3T z>YC(O=9=tS?waCQ;hO4L>6+$P<(lqT?V90Ozd_Q=bG(U@0#P-;F{~$=$hx) z{{U1;#%m~>RRO3=34C7?pos5;mURFbS-u4axHW0b}e`8ajkIdb**&lbFFgh zcdd3DaIJA1bggw9a;00kN?AqWs;@apq>e}Qu=GyEy?%Luw;o9mr>DuNv<=XBz z?b_iu>cU)&2cU^xu?zzr7?z{eWJaCq5$aY_Iv~yo~w0GZdba3BvbadZxbaLNz zbawya=;FTP$Z_9wbamfzbaUT#bay{+^l(3P^mIRR^m0FT^madS^l?9R^mRXT^mAtm z{oU<^0q*v~Kz9dWkh`NW*xgAO;_fUAb$7udM;PYrDhzjb6GphZ3nSeg!W{QlVXk|eFwZ?+nD3q-EO1X07P==1i`68BUg z*F8;G>YgqvbI%Z#yJre3+_Qw0?%BdB_Z(rhd#iSDr|Kx6SldR3)|f*gdOgc!cO-pVV8Tgu-m;x*yCO+>~*gb_PN&! z``sIa1MZE&LH8!%kbAT6r+bTV*u7Oa;@&14b#E7rxp&~PQ#kJ4C7f{Y7EZeN2&de8 zh12eR!Ws8|;V<_A;jH_h@VEPraL)awaNd1bxZpk_Ty!55F1e2hm)*yOEAA7*Rrg8Z zn){S+-F;fP;XWhWbpIvXa-S7$yZ;vcai0_JxX%lB-4}#=?u){G_a)(h`?B!ReMNZW zzA8L+UlX3VuM1DzH-u;In?g3bCA4F=h4$sEUY@l-j8|0kG z20JIQAPKEq88YE1a9yO6O*_%DIKDc5Y>B zoZHx1=XSQvxr42D?qnOByVyqOZnnv}hi!K5Wm}y4*jDF$w#|8fZFe4IJDi8uPUoL& zm-8^&?L5NvIFGWu&SPw!^Elh@Ji!h)PqKr~Q|u5Pe>zXI!_G782p&hBf3aiEv+TI@ zZ+60Yj-7O#XQ!MO*lFiQcE)*${pGyO&N{EKznxdvIp;NY-g%u}aNb}SofE<@IVXl+ zc1{Yv;+!0Q)j1{nnsaLSb?3D38_wzBH=Q%WZ#id%-*(Ol|HnBy{El-@_+97R@O#dA z;rE^M!yh;oggL|{s z)Ja^P+F4wY+C_XClY>WBab;>ZaaC$}JbH-dB72JGBYTP0h2G)~p^w-us;{`NMn7>( zdVjPrKzx=qP|QvrB#uoVERIVbB6gF8;+@+tyweyio)$-l_hUzj4`N4&J5xuCyHdx9 z?h0+M+h^;zRp=< zKj&<*zjKawGG?xLDrTN|I%d8&JamD0Bz2*9GSY!Z7&o5i~| zw}|&@ZWZs>+$LtnZ5OAc?+~Y^?-bj`?Gn${+%0xa+aq>K+bhnD-6!@;+b>Q_KOkO> zJt($IKO~-t{ZpKteptK~dqnJ#epEaYdrX{>eq6jBdqO-Ndr~|ZdrIt>ep);pdq$j@ z{+D^X5(`g!qY>;>^u}By*>=kik+EsB?+BI=w>~*oH z^@ezb-4t&yyl->g77x7tkGL@Oj<_iFuDDUShsS;KiTiiM`baa}eWgLxe$p=1U)miyK-v>J5RXC9VC!IMZ|D$dU+7Rg zhDk%L!=)+i5mFELNa>1el(g49S{iB{BMlbDO4}=slXlt0gJXg;k4=JV$ThayBZE*b~J+s}xmE+Gr7IU%#HT|+tx-9nZM z-9zSBdxW$XdWH;e_X>I7?j5pC=o7L}=oGbXvnPaVIlLa!_n>tv^g^50vi=_#{IVC&Fn0P#qw%3`7pa|M(W}pgM*$u!}*S- zT6$XJtg@k@eJqx2^_jA%t<#!hwN1mp7EUNpCg>0ONA6GACK=6y^rp&lg>Wq#)JZPN z{ZYy^ZKgbjvjUV!mbe1=AEiu23+3rxrHr8&wM^R2N*VdIt#HuTpM6Uy?PUISU0l);&r{HF*Wg@d-^;FSL(GraWSN1+ufTl4;u`#3DDQl$zXhgHaXPX4J} zXlTWX6%ju!U!jsx;hUE%mS@j`EUBH_k4{Rd{B(Y?iHE1xoH6|1BD+|3?H_duSxOcw zVv%1nVw}; zk6W#Ev)ZI)v`j7^S}rU(s%7)$ZCYex{gV7eRC2wREt_Q~*Q|>l%T*{_zEaupVdct& zCV!jJB00WgW>$mB6_tb8CgsbfHfv_Lz6ls6f3T36(agfq|L=#qE!ET9 z#l+*Mn$Z>(_lt$aW@IIP`+aPi7AU3u9NjppF@A3O|M2u#hs3Egnoj+H*mT|*w{oz} z;xa!fU#Vhcbg*`6M&qV6+hifbLcRZ#i;A+m7F*`g8x?{+YKzGzj}$IhI(zYtmJg87 zrM`F>>s6@_8Ia%GUHB&twM=t^9pLND9wkSo*4Yehgn<8*S(W)dGOXk zC3b#dx&z;4v{c%@dbrlnw<=g`j4QqFzm};h{wT4an(4Nieb+eiJEipxJDzDfGI>cv z)j13I^65Y{aqp|#dPEHhmI+2(|=I}s@@Bc>fQaV%Z#|BQdf#}|6hrW|NA|xWxF;$+W*T7 zSS6+Pj+2KU_Ye!U%jgN@0RwE`Z zBC26ZTw>jNDYdId)h$=Pnx*~omf)b0W1N=k&*aY$Erl#)+iG<~qiWTz6&Vp9RgKC8 z$>nmCawU$w^{>ar@2*ii=#p)H)8nPfkGprH@=E9FJ@;R+Wm;6kl;(|_q_k?CmYLQf z%hEaMIoZZ!_X9(JIIiqL8CVGyceYrHeN#Nh@`_up)if4gtTm7Of5Xz9QNd>M4?%b>r$3=02V=B%3))T>Ro0;+pnz@W-e)+C=ks|St zg`+OadJaNen&$u^~6t?E$GS181a2o$J3V*??HGCqNp1idz1Y_p<(b1eWZH+RL@%h8xH$RE@;M>h)`< z$bOF6n4}e2?TM&ct6WNC&DwSA)k&xohxR|lS0|MA=Om`JZIvQ_G@sTw1z$R7nUa}> z*Jo&T>lp>;w;3$iv$aC|Jdp{BsMS<;+`(llTafx`E!yh+jm0Z-l>Ua|!+Yv)otUVE z+9?UOViUcw=W4B9Z=iInRz%I1l$cue>NJGHB#k>GLfIEVo1zVIl-|3gDo0Vv_DG1u zG)Rexs8J&_BC0xcbozO!PH?dwEQ(IuggD%KS)sUD<-5(2Er01^KA3~uwJeE|pUK~X zD4*Fv?@}~gUZ8ZTMXIudr(|X{ZNZJ=X!ZS1@abxL9@L0WNp0DFozbFcN><}1 z!H+l=xUQ_s6xbJ?XAFdv$UNV0JT20GN@>vs+*$^gLAhK7=%-XQeKCNwV(KXK31F@7 z8#q1Kjh6BkSkz7pK^seDt;w8LX3N%DI*%1)mdR!Q`qC0#Ga@P_HUpkQZz2gDUoOAA zB*CI&c|xsvF>$~Eu+Ex|LMu?HsO9Z&3?7ozI}uiDWB2r}`lww?eWO;?@=?B->NV)A zw2I$<-Kup)+s0XGDOj%6;a;P@7TkjCS!!AuZZ_ngjuwgTt&{oJ=nIkD$>@lB5z2a? zkHc?haJ|xp<8NhV{F;`6+f;r-S=5qU1$}DUG9%S{0V#`i@h3R?Gj&)Jqw2-fOHuC- zWhK();1{&JK?WGhk;;o|ljf~bl(i%$SY5Re(C9{mp-HlG&(y0^zivHDb}=>4i&|Ex zOHKV+317t2sT)y4za{kr=V6+9v!u09cH*>Db-cD}W7#rUOK+ud?}^$@V>*o^&B#oV z6DCdm2B4Z&!NA<1U{=g`3cVJAoto@99jk3xGdMHC+D(#!ILXZKGSc(b@(&=lSCPBp zQ8F~DUIUDYi>hu*w8VT-JEdkc)`wr^Z_%lcad>&3Qfq3olDITC^&%o`#GpFeuSG4l z)ADXFtb<>~)WCv=0tYno6);!oCWFN#IuT1c}AiahZLTpc}r_dojO|1$Qg+yccU2o6t%RAQ>g1TRAAa`>+-7}OrORRStAi^ zuGbwyKt(Ohd}i6J%%57n=IINa*QRz@d$n$omM1X{>Y@7yiM70yj%ekc&+Cnbr6*-~ ztutG`(i)4ZQ^Pyuj;hTBkKpG2S9}dkzcJ+n>XB3jw?>h1JJLfr&ph0d+tOl#z!Xwi8X6ecAe5Fzl&4$9QiCqy_xlF_&pUPl9#@; zJ79oymeX1z%hj&bt60vro53Hd`!CK+%Bx@WRWmjeRnI7dWvVEv5jN?VD0w+*t&M7K zW$5$M?mfE+n)p^#TyLPImd;(i))Iqkif$kN(&`E{pE%UbXys+07HJSqbPJ`n@13S+ zwN~EHGq6s~7m3wlqP+*{Z?#nLvO3CAqTIk4O>t!M?Jq4FH&4?ylL(YMr;NzmD2+R! zMqFYYZ^`qTWOn|O<8>=u(28zS$0sr|u|`Y;Hc0F}SOWg0l_{nc-exCa->oGN{w1x_ z1}!;bEBj7qQOm39l;L(mm5;Qc>J|rVeO>XUzM{4Iz^7+ki}_Wp%s(_GsmdU!Ie9~S zv2|3l?^0^U)J#cj)4VxOw6kw(uVj6#q*0y=uAy<2iq*K{V&HMKea##2j@HUbwcA`l zsL-7m+=g38GFsq!t@2w+HKi+IExD^qU@1dBc+JZ_RV(-|x30@ucHX+Kx!8$l^1jk! z%Y2q6J)IwD`0uF`qrRO0cZxO!%?#DOh#nHr=Unevv}vw)P2Q9rDI9kiXt|kZ?Y*=8 zF}3y6Czhx>4Qtm+Olh9h99~3k>IW2fqBQkGYk6_O$#30=*qF$OIPgCIy0Sq9Zza2k z%~+WxeZBq)wR1w`{7tN^Ee!zj%A*(6CW=}f`rf%-3)f3pq5rB`Bd-sT*Hfm0?#l9O zIfKAaqmbI&qLyRWsZxA)Ts=vPQMV3Iw-Rvb?*0Ct9$M+8^y>9Ii>t4)uWGPQ@@`pq zXd$l~uS@z%y2T*(Q`A!0kd0oQDy}tNOii7}&6>7st=@ERs(lOI!6mAkH~Mt+Mqcz) zz>CQJ*JearG4$@2)HGgJHI!8i^qRog>b(2M5~-()2M`0H5L}Xfr`KF(Xp0hqA~KTBgbyT7K`42FsnNm<6K%em^cwbdL!||4| zWfOfN?~Lk0Wr=UO`-vMk*>?<6BxdM&tgo}JVTd>7A4P@;C*2 zot{>z?b7qrp|$@b7Hb@T15IAC(fnhz`J$Fb`L81Sf+lE9tk>7>`t`J($a~>-Y6Y9q z``CoKb?d{aMAV8-sf%HYkas9aD|Fki{pir|Yh}t+iK!KrP)qh>pJO8NC%6|s8f`Ma z)6-LaXFpAz>toza(mD-q;nVObvG#_05Xw!L%hluBYTLM3o4i8!6w@+88QV?yb=zwS znMPY$FUW0K-V0(`t?cSZufr5{@1!;xU*zM)y~IA$8mO+Psvw)Wcy_ zWc_+E-jfxoHS|;$%q!=$I+xSRl`y^^@#4}~`l8Bhf*#${oZlhMrpt#q^ltDYwbkH` z+ziM^HQa12R3;!@+neO2bfHtJ)ggCtQfiPLP z;PCI&6Fb$~a%Xm*VvLr^H_0*DC+oL@VBWj#FY$V=GKLvG??Anh$3xTnzG}BKziV7h zzYANUfn`bqO*Lw5enF^DZlf5*#eNY{qrSWh{6>dwnRG}+yPJ%jA`gh(d~-CvT;^YC zJPz_c(fR}BR>tW<+hA{3>S)#?)vPrLL{lwItf&`{vQh>3vFr zbBJ55Qt{hX7-sLaYPF)C)fzWCZ_>Q)=LjuFisg5o>dQl*c`}^A3LH5A3zx^+q!rl-||W zSE0N^2(Ltn)yU>2%49h0j;FW4fYFcGzxVb%bcn4RpLnf_Ty+{F6SPx2G@-2*|Ks|j z&P7VAtkycQh#qZKh(Dm4D(~za?dWe+7e-^Yl+2|JRWinVE2ysVtmEG1BqYT|`yN63 z?&W}eXEJyzmpY_#8mm38diuT&XrK)Pq3n-J86V?^4JoH`Kh7@)pNy zQLL?T{gls*;Z^Q)t=#=2f4KOSkA{ImQKQ&#IX@L|d#tsnSq7;`9hUzKg zn*-CDOS|L1ik2vRHc~UKxqjz4QRS3UWqv-R<;6-_6#N~(!{Qg6n`Y&C?Q}GET4`=} z{sZLI;iqLYfEme2KL2Ko@! zYnswDicIyGfp$0gc&VsmXuP&!>+jO^6i?Ucjy4w3-zPQI3ib5O1HH(1T9L)Hn5ZAI zVdivqIV1nH_ZqMat&tJFFkZd=UMsZB>wRTPJl@i7vXeSFiX1+7e% zFzWbI)G|{y$$1|P%fHpGyjW9z5yR&NpnpKoA^*csuMRa+QG(+mE%H13R&8(|qkOul zoxD{9$yLmM@C0txNNtn%R=6s7t|=)pfnTV+kXmY8{xRPjL!a$d#Iu*XTj_vNvo8H0 zcvBJlHos-rOO}?OqLw%G_0jkJp)TE8LtLsRi1&w$d07(tH8&34dwxk^-Bz#?)a_2U zQ>eaO+wPXAt;f`=UlV7r^`8y6yO_ z)T@cMY7_Y8F+Q+sgWuRUeuD{LcP`r&-*>hYd9_h?wp{T4w?B#RWe1nCS`w|DRXCln8o;s|fWgMJhbn^ims z#p9LPQ4;-C%P>Li=W#v5jvDm23_C?bj%aSk&jaW0%Iq(~`JaX($vA%l;zltD_fm$v zmo@jVg0U_T7NR+<8^F3&nOz~QUbG0jFH>DJP+c)lsmsDm!a+2Lb00W&E3})QIK?ih20OI3E+sWbf_iV}r7q&y~$8R)wO66sJ+|73<}JVt&@^6Y49XxxPj~ z`BPG!Am^#!l>BPi2_jCa4kR6IRqPJMu3@YTiSo|9tDa$94EkJ# z^`Id~G&kh^fzvmP^(GwNx%UOcdU@D&=ia+utO10DXbx)xu!e=PA%w*__hAOAAqFaS zLmx>vh~{u60B2kn8$&ppb025G8RG|MBHf z=e}CMp;v-{zn7L9nAEIYM?-{YZiu#nZEG0Y9L6>h8}Hn=8jv>YxEl>{Tq5ltMnrRr z2f(;5jO`&n&bjY1@a-{BsY7;7vSa845o z=iE;ll+}DbYgX|B6wi?&=iJXhF+b~dk@|{guCG_2e3_Ja=YH8BjaQg(Hy}& z5Zno4x5L;?;^3Y89e!DXbH9ye_Q(s3?%Zz{%zB?#5zVm%d1BeKF!qE%dFTGj*Bs_P zG2{!NcPh>uS5G02dY*z95Y}kTxxWFdlAe6d+)H|LI_#INgpYH7lavw7DZc~dw>_*B ziSy3=ZI5<>psHkH|CbTcPb|DouWyuA zQ>6iEBbw9x3fhfGn|J7q{Aqtp+KA?~)1ckN!y1!3=gpg75j<+ekp<4v8yiSe7n5!l zpd|pBd)N;imO%`hD{rpfvOj=;zh^QGOsd6fMT3KAZg749+fN?W#=|m+jd$fg8IaoO zxS2*cHEn(+Iz)4H?Ln9AVSf-B=f|@RWPccWlpDGO;UJpB=?0t}59>@goFC6I;B@wb z)17b-&EfO`PA_8N{CF>evYN?#%_rAOhmbPw$A=iC zvCHRKi{V6oXpUe42*!EX7!Mmo9K0VNr!6IL;$!ghF?m_R>G`OF`6dz{qB*`<;G5xL z(+H0D;4^&9UhXtQj=%~YRy;Vap4o(j_;0bI@x7O?mG8WCt`f^SR>{YIcdU}r;bcDk zyGs?-`6C9d+7qhXtFW#l%zN+dRW$G2)ySZ(UcCqcF>r|ffapsEyzlN?C8y&lU*CON z@!hz329P>p;OaxF`19O(LPJRiF>s-g=;m_0Ab5{G8`8XAnCTB@9>E|6 z4zm<6ORBI%1jG63B?gv7Miyl|UPdU0fupPi%IYd?C82QMdbI&%r5}`agn}42%4VQ! zBo5wJZ#2rPOUxG1MGRbbCv>-yF7K(g`_tV;x`=`69)#}xDr_%FbAEb17Pm9xr}r8t zR2Oo{jQA;tpQyr)RbfX+pYzfu^xN_n)cJekh=E7-(x+)q5Cb2SOW?Xtg`KOy&Jq{z zqc0e6&grOUjbLh;TqZKaz{zfd>}C~qov=6$ebYd7-N>TcwEqwaV&Eu`fbyUUyGJOT ze|}&Wiexd*&Anvhd7#)}R=vBL=Si2GmPdWv^9buMz|AmrGWqr2>BWHT?V+`Q=v& zW_y#^5Cdm>4{T+sveE>`d*w2K;S5@CX&~`t244A;;+1jrSP2R7-y-e&1m6*VY@zRn zmkEz$rNi^_%ca9}I-JYLFTWeErU{}sWdX|eaAqZO-ZR_7HP37{a3F6kDBcxUkCSi^ z&Eb3ioDgE+-E&BIPRDD$?)kbxfUCzv1c>GcJ`DHgp!38+Net1PSOs*qJaw0I(d9AT z*Yk1FADdMSgJLC8pluCpMf# z6AtgIV*znN9(MhkCea0BB@h;(Ijqltl^D)y5*FvM6Ae@~4OFV5sY5u3=5QJU=gV+b zpKv&r{iOk?z8{<>7LuZ13zn6YA zFsWJlGYt` zNGJ{`Mb4oQhhl!#YZUbr(Oh50L3s=*^DcdiK^nQ3XFtXh0irpA86cPz&ZdO3NyNcB z^=bUF0>3^5&)k(48vUCllL}^?Nvw$GSQmkHK{%U7puBTm;A;+Z=Na+^(AN~_j;m)e zVIlrotOeEJ+&5^>y<|izdo6;!9HE-`t<~^d|NHpr`XBOF*I&ao(mU87{7CtB^doET z%Xp@<{LDk;nTN`6I_B8q-*m*)^Lm78>k-Xiy$!5V#I&QD`pbuXWTaAx64D8f_~pa< z+AklLHmhiZ;(HOS42kZQ2SWa3)BdvRdr%!;2Ks=25X}LV1JH*Nj1kZ=4(LNKAXYF?c>+Q-2UH0_ z9}~@nYU*z$50yvfV*`M?>r^IXM03hjq3j{$Yfz4~Te3&V${t>MxDCG(jTb$ikTRk< z|m( zH$c1>K&&5t>Sh5x2S8#3t4RQlXmwCVAkhn;rXPShW&yqcKs{2w={@=NpqL|%xwI&MjvJC`C z(iO@O;Ogl_Lx5;*2zmghTLjA?Ab!j028h|TW#tqM)RTY^%>fMnP`?P)hk*DktDhH8 zpMrq~5)h&}pkV+SLNwf#HN*g*Zdt=g8PS~bXef^)Wp2wF$t&xt))-PoG^acX$`c~k zI1=Z!tO*d;wybgZd6j&h_-t8|%>v8>!1M?oRcYq}S}R6hW-%mOR`z`O`HhXA-O zYn~Ut96taH%>v{CU@@t4Th?MIdaX_RIG2tD(Fyf-NU;Zp&J!Z&}NE41I}Q zV^)4M$Cxj_%i5`JSr>qDE`psQ41UWx2ae4$ zhrVT=udgTh>2N-A7y2Edv2)_9;VvtLGjK0iwAfcnYA$5$quW@mtnoKy08b>tVq_&j<+7 z9MJQT_{24m6~aG`BL9s`{FW6QnFmw|Kl5|MjZl$D`XDyaBv3H`y+kzJmi3YWK;5!l zCS^o(L-87vUnOO3%X*bp)>o|(q>N}zxfGP&jAXBqIJafJ32|-9dL2LiDc>hPTh@Qf z0=x%+GLft_0dQMZ883j+egLdy0Ym@@k<3m2+?FMH0oeTjNM-?C0C=C&xh?B`D0=0+ zKKX8%d_;4TUmnV#k*q9R};xh<=5B);`8Zw&gD z^|2p}D*qniBYgeUp?v*y7Z7%kKKB<#?10({Ip2ML{cJalJ>tI|`#jZyP~9KN_L4CF zQU3l&?W6p?1_tn)Qg#MhJ%sV)KsiDj{Kxo5Fazi08R+Zv7e<^{)N%D3Cw0WY z)lWzI`v^Zz=nM%V1}=0C-8@U(sWkKzT8W6^T*}5BE|1iw2Y; zc!tkR6{Q%VAO?=|8c<#(4*p~MR}HdUnv@`Q#K6_xg8Cbz&VNMzM#1W(NF6b7_4lA& zCW@6N0Pf@YGEq4lFUgCZ{_%Wi1Ce^XY&C=MJ`kiR=8R$vqToK7m!h;SzzKE!o^cp> z)U^13h6XY4q4@}0<)YY!QH&86|FL{I1I~v!Dl>p_iBp025Ci9{3O-L1t4wg*NAey6 zTV(^0I#iz!3S!_W(LjleV$}$R`#3(*fKts5N(`YO29EL>P~wS$`zSu%psMC>bu(&- zP^(F5+{f@Wp_ZRzs!e@F47`u^pjwAi`H$f17-W%mdG?_`sUrri{x#H-qgYZDYd{SA z$M4DfvVo7^lkm(nc_Gn1es54PX9{s52G02%IMbt8Dnarey{7|-GjzGBhWr5VIoaaL zS5F2ZAqIjJqB!h7fb?4w`iHibAqI}r z2}m7?hdT`Ffbn<$ao@wB&SunlK&@L8%OOGjAgCJ@pV2{3jzJwH&y=p?>gh>cM-05{ z0|3)6iuEBF{t&1i0B+JDP@jTf1`-Tn;4mWqGc1Y?AsGGuXqXqwkb+@G5)5MCFyjC- zhDf->pD_k;br%^=s)&KBPKN44QsoYQCi1HKd;ckNJM@_WVeQao z8h&nPM;7`V`ph;Xz7XQ`qu5*$=MH@4dx_8WBfiLt_;QFZjbckkoIC7U>LtF!kN65R z;%gwjij=v7o>fruT6grxUQ3gW82DswhU&&Bww{E!L!OOM+9A(+9zj3k*7t) zv27&H9q{bLLf;X&m3P3i%@4w!e~)lADlzD1W&3#ygomWh9q>GaS{FIDeGYh@(3m6s z+cD2mEgX$Eozd(W3G)X$LD8DKe`a6+PglGA9Wz`#!O`@lGui~oi$Ez7t-j;r4|s}1 z=XC5X&w%#SY(kPrh$3I$TxXyzs)?trJPfyiwjQg`!mgn}42N@bu_jAj)G zg*)J>Xh5mp2PKS95CcaE2TE1q;177J8f3XN`IOWV16PlRdL*gy2RxAltK*-tQT~Mu z#K6^SK>f357Eb`&0ncYx^!m$-o_@d+Zy-|NB;y}S3>@JLAk>Ryb)s2qqTmjA>ghLa z9jNp7Ol<>?nxS9P&>#lR^$obbj%LZxEQz@I1D>x9ILSI{k^ziMoW{h57&u=B_?kwu zG=k#}c$ym6(hNlEP<>A*h=HU02$Yu5tT~}@2RtneD9!z#v?dh9z)^kzN*m(f4tUxa zRMp)5*^Jt6Q2UkCxC5SFp_ZRz`knfS7CIoG`d<2_lPcOTci+pOY#DDEXi&Ux?kqjrynkKv@QM)4T-N(?JTB%CuZ9@ClrvBg(Fz~4*73`}a)mZTv43 zf7^gmO2>WE0LLX#8Dc~<$LIv3BZk=skaOq`1E0-6r4E@$IEdzO7;s!M?0v%FT)NAE z^S&RPvV?^1S;v_ikntdqJ@WDRR!e zhabh>W)%lQv40HfOQO7U@2_WAUxPlEVS{MM5zP(xNZ<^QVM7UrckaUhF<%~b-MJ4f z7;6+^A)3RQ1gr@$Y#d>6&V7P`YMg;e-Owi!4x%}nS-_bQ!=@1q=iFx)aHjdenN2u| z=5Q7OXCATe&V8OinoFC7M1W|HU?~We5CQMpmlRB}j0h0T5v&El>KL|?AUNl~8jIs< zd2!U8`$_|q>U7qb#n=vvtubtK4BJQ~oO9o*-_V;uz~4(74NPj*?w}z;G&e*C!L~n! z?Tul(iH&#e`wd8Yb==(sI4+S65hJ2G#*<(?9>b0jAm`kV8~BbIsMH}lML3A&aLxng z?-=$M;c(9VZv)O>esC@j4x%}ntH8NTESz({Y*1G7`I=e9TTr|~ikx%50mb~R*KO)6 zqPf1_gYq3x=AHW;gEVq6&wkt|0z`8JL9zI|U1Qjj81{%bc<26%UsmAUpWvDG@N}z*$HJwEVGd~@7x`++5w8qzyYSsif_i%BN7gxIUE;o z-X|8`xxbIe*(v9Yw{zd65a8-@69J+*g3wr!|3>?Vo8K*NvD83!^Tf)L7@|3`kI~(a zNRM;wA7Q+A$@A{x+$)+@^gyvPDRR!evLD4NW)&l#_-QQrghYAg{;8f}pBVJH42z^8 zM>IF&3BZZNQ3K)d&OHtgo8@8GoqJ5dSf3FVqB*QOz^Wa~Y7rLa+-n=CY8j~14ZSYm zAezHT0#1Wi_66Z^&b@&F=L&GHZZAK`wI;bqPZbz54P-B_6L4Tf!KKGo^3$-L&yEi0LLX#2Vz7t$JiZ= zU2$GRfShyhYT)Z)pi+md2jL)^!|4y4zOk$~;c(8quK}mGADjV%gJ=$CC~yW73+LPi z8lt>@ zpwDI4H5zh6b3=XyIJfbS>ktm_+;0Qoh&=4NbH77#RSda0GDTKv2_s0gR zhXyKjLw`m%h~{vf$D5nrI94bwpTC$OIL>#F3gH<(TUDGQaq58!qB)#mzX6ej}Sxfd^(pd=9>nj?4{1f}BGn*_l*_fl~=9nZ>(qwd__G*GEd zr?goN0T}i;W{qR-5(($r?Qz;+j}-*`z4WeuNlgKkHSU`if|-uZd8uNy@x) zuW67*F6P;f+C+e8j-Vk3zKmn_<5*qd;GO%I{IUY)ULVg~kQW-=xz{b2HHlae&9OEC zYvVYULZG~JZwxHX9OkAN@&(YR6z7hsCzY@e1Hw9@Irl!m>P1YPbMFO!%d(a5aqfLd z8PS~bU?>laWBo~-ckToAb*;aF158&H-;Aqg2;m@_!x;&j;l#o__u-hFt_~mP-pwKZ zPAjgSQAB`fj$m9InJ2@Ud!E>M5<@g6HW}TWNZsX}`$UX)H}uxmxlb{xI0K5)NRe~y z)BGsTG^;otigV-GY!c<2`&>Q4W*hXm3|l}$j%aSkmjNd?jx8n}-nr)j;wtCd7Z;4R zoUjnhVXX(&+BmkFusG+w)i`^35Pp#-)g|w><4ED;UJpB z*$bTA#KJrG-3DncZT1lXqB(*;L2!@=c;|kwV1mO$fM|~36bMelv10_mIrkG-9DB-( zqwd^~8K_jJbJ{G%C16~LW9Q=7St8+_`vv`mJ_iE+UOH=FQnU6l4H2TbA^Hbwx8m51 zIChQLc;|l0fOJF0y=H*p66p>xBAR1-0>(#i>;VCC&i#>r?}33z9kQo{gJ=%tx%gOC zIGzQ?t8dXc=UzD8cLsy-48JX@IM2tcZ_yFW;S>eVi^Re?_ZJPyYCab;t5_V0uaF|= z++TrWe%9+X>MNqTzP=}bUgbHaq!N)Ogy)& zz`2*kGkxWSMtAQ2DVWtttcd1V-v_G{&zuCxJ9i0KoH@*O8uA6uU1hr{Up*fX7GgkH zZxy2NxsLmac9$FseJ#X0x=2CBUVDs=}vL^z1% za83Z{SUfvIIGl4oX23b(2j?W=AezHD3!F2=!aMgf25ByB{w4xMa|D+_aDfPT=YFAJ zg3CmJXpZ0(2yVo)YXreL_ZwIoN6Cw$?%b~#s8pwO+bqUoU_6Xx_v6`JBH^6-L;Z%n z4+8#Px@%xkv-SxM5u&*vdOiW46eX}i3Cxn9I#J%a2PgO<6-v-{I166mS6nWUiX_m- zM+qhwUj^gK39Kjqa?br_17A@Cl{#d_2?x>Kki7+*HxgJ$!r`3z8wQ+`esD?=4x%}n zGQcTKESz&MZBSP8`CYS$b|_j&k#p`=DCTFq9Mo4tbA6Sd>?CF0xjPNg$i+PS5kdrr z<_OAx;KKyQ5}1oPc<26M0=KNdxidU7PF`qq=k6+)wLGyRnq#d3*02Oti9mVh9tJGV z9OhOs;Oe!YUZWxV zi~u+nUIUBXTzS#cUHE4PBGt7dnn7p)gfAMhdJS0}qTn3(7y3|x z4plQkK@1!v6DU76WGxAWbKO50P+Iyy$s!cQz)^ky%1^|>Iqshfs%q~3YDVo3sQpH2 zoZJ2lYWZ2F|4|_bOVM+{uOC)B$)WL+DwF2umQ?C$)s z0hiqs&n%P|65VBYDVVbtaUurJIT)M+8?ycc$vfV5@H}o z)fI<54MeJpzGefU8&%dnt*%kd)u~b}<9aOFHTcc#U64xx{&u_z(l< zdkcJTB(ahN$2sgb3~VJ0MCwqLA{4~HQQiYenIu-4P&kKO#(+}V4~msg5CcbX0>wcb zoWph)RMp%S&8U3LX&{ef$urj8u7t%?z^0yFB|4O6rJ#tA|0o zQWE<(iG4&2yu+@P#4Q_e*dODW&GJH`JM51N=JXIJV&I%n;EYIOpAsbRup@xP8M@q0 z4f!DhD-Ii1Pc$JR27**qao7!k^d<3d4*N@pZ6VW(n3_Q^To?XdSN>bQEEk~(7G>OUm;JHyTs zYDPkcfeW=lH(O9QIfvZ>W4vFUXCH_CqZzd}P|GAW&S7WzQEO{P?Ki0Xn#6u4LEd5i zs%O*B25l~zey3qZ41Ab70;PQt%O(`wVYdgs4tc0`hn-z8QYS(}3>>K^kh&+au7t!n z?Cu7lt_C7?Q|?75h=HRF1WNxT)|XH?huzWG1>kA?bZQs*7^=z`V9kvd}F>QkXUIf+dq0M21g#-evfUi5T_J<&jg^HK8dX*IL=|OH?XZW5UE48iBJ#&N7)IK?MZAap>Pg+y8&gZACz5$ zf*3f;exU3n4$fikHK?k&d%%p^VW=GL7HPQ|+UNSI%=ak}carL}PD2RchybhES#KAl45{>XrdCNKC z?Xb@)>bQE|Aa%sR)&JATpTo`*dYgn00~dN1-F%0-$vNzIFvjQQdG>MG@0n3^K+Q&K zoWr*HQ4`FleE_wPMoc6@-eHI6*(4gYxomRLFe3&&%;kX++K81U6y9Nn0^pQ9)Vjki zTQJf`goGG4QWYSDHDZ+riF4Rt2BJy^B6U-)N+^hdqeKBEq7nO)P&kJjVLr}*Cch`Vb?5Jy*8;M2Cn`k)ay55bqRoT*!8jK zU6L0)-C@@?5UDPuff#jrG(UhV zqY-P`h@}x1@31orI8AlbGy@oyIL(L;F>t;t@U?ElS`i%Quv;70S{aDcp=v`Yh=HU0 z29#eLv7ZTrbJ)KcP=5A<@;jj*29DAmDA~lpIqYnMs+zkU%&2vNS|?KD9CjzD$&_pt|5yOApIu)7&#k#~9ap(m*$2ChB`>H`|FevMckV&EP20Djqk!|sP?uE`6D z?y&n5%sH4i5d-HO1I|&6*a(8;9rh?+Lzg?kkRJd(r#Ng}J!1(8F%YE2io;$8q+H_R z&aiVKep9vsJ`Q_1sUilhx)!Rd8?lun%scGW`kJ-UzyO}xipRy(vyM;@14r2ml#Rr} zJM4{^kOy*(csuNeiaM^IEu@YZxcUyi4m(e1CkY`2F0>cj+)dr&9QJOE@k4o@eH`{a zGiryRc7W74hkd}0+Mj0BPC)HgBX)!Yd53*W&!!^=Z7!Qm(l8?iKFsHUa<&mWLnyq% zJ_~@`@=)sz`%J+|=LrchaHQ)%y4r|cCM3>bUo{Y2HV~@ViQ0_Ehw+V%F z*mn#lxBZ~pCltiMQJw(h5pnPi`;kGGOOvOhju^Ol;pA8rl&qd>@D4jD+4pwj)Ps}N z^9{tn)r&&?#bj25062&JVscK$C-S1FJM1C`BGsi7GlTF35K1Pq*OJ+*M8P@ilF8a3 z%WF{Q@0nK(JZgr%NkfAe_|Uuut}@B2bTa!7aq$kji~*;#j`|-17&moR;zJCaF9dvI zG7|`nbJ(JRO)wCtL-jtPAO?;S3Y4)cwb_Ii~ zn!AYqV9KAFWP zvuI-A9dX)-`yQuJi9yo=Se@lPa11=&OK-D+?l-+A@;{o zJFUY`081UHAEv|Z0ODOBL&gp}k*dPzzv{1``f~(HqQY#4{WG3fNhS~Ar<^Eu!M*pq+4Oaf7KG+WXPgsx)wML3|*n>26cn(XU>M;7R-X((f9rhEUu2cv{|Al(M zG`rJjG97kz$nhX`oedp!&p_1rf?98?#&p=dIcog^Q5ytm10zT}6=XZ?fmluHCT*sg z2Gcad=zp3=ft3*vWEi!=cGx4pKsPnj*kKPV-qL7l2}b`dO$JL7BglAaiRrK>njDQc zInr;+nbZo5{#%&^R%S$yY19hSVb3sGnZ~h_MXkW-zm<7lC7b$SJM3(eEK?@)sXC1Q zt1kxiMO2;buoo4tzJ#j7=)d}EP+u8AmQw>vhrJRGy`k!%haL8ElOw%LSrdqbEnp!x zf^3W+>!}N-!_LJ`yAjmcJ+t2AN3YPWG&L~#pPD`3YgYuxk05!}7u#X)GTF&Tt9d44 zOyTUM{$TXq-%;>)ID#Cc=9muqu*us&lOsJ<$EXz;{kL)ktelDn8WjpMf zCRwPvC+))>st%+7>h_lKdov@*!w7PpdSE;3$Lz5I9ri=GGEzNA@H_1L#rrJLQvdP* zM*n^O3w%D?l9Xzxe|y1p*w3~!G;}$oS{j=lFr1;bcw<{+dcuj76qR*j0m7?@a1m~IU^U8d`< z0r{SyuDhY@elt+TFi;GoicIGn%2BKnsA7Fke7hy7OGVl4`)#bSx+Z<5!Wz(&!x&h~ z-vv8OTaw1q4%>k@1ry`cv||U}xOiLdQClzuX6qBM^-)XmA+^PH;UAe?eQ0u}-?%@e zc3=$5P7AQ}RZH>(wZnAcUzzND!LjoVwF6^dcA~*fB=y2}`kJ2l93=sisSx|>|-DeFz`z!;dFfnX=SCFw`)FkO1O$xc6xoeXLR z#=z_h13N>g7p7AmVp7)Yd3d0Tqd{>bRb;yLk)UYRdX1rTg)y+XP5|X`RGIDA$C;#| z7N4{q6R86j19LDF987OXrnV%R)Cb$OPiK!6=-Q{kl`Qq3!LB{Cc(1dlR~Q5Hx)8k1 zZ%O7-qip9s-`E`H%r(^un9kHXcX$q4L~X(7m#q`N&V38m%B7x|&OH|lWUH-&p>y9# zm0=7_c_%3EXi2tHakg{cf#=$GlMnDTPwSiEIcyiT17l!z_Jf_h)C=3W?}f!#tkz7? z&V7mI0G`7RPzNvu=HLjobAKXsl#0O^nAk~}?r}O@rgJ|I`Cg)~yP$QSJNKJlVxF3I z?A!~Bw{?fwf-x{#w#X*rQA_fG+G0BQM^uW@o{l6XBlT}M zn9lv_NMn*p!WFh!bvw^eJ1_=j=igwbH1)!E?xjuAOxcvB4qyz-!3*G^Jaxc!?&XVj z@FH~pV_*(m0|&1}l8V#>)49JAnbu{wdN^X|UeV-A?{q2!YC{4WVkB`z5(jm{bnarL z@5>$+IAHgZ!{kXX6Pcz6#=ue(0^X`d5^p34rry}jy{gHQ7wra{%rS*jje3MJFpsst zW35P1lNw|?_gW@@HBGMcl!Z|{Fa~C)KG=CXlGLSkn9luelbyO8I}NBE7z4A@6znvn zUYO3ku}N94=VpN_HV4J`s3Oz3zXys|t=9*1t}q5R*N;ItoGP=Od$>s&YVk??@dWS&x)4;$wwUsb*?!BlojDabq zgL1z}(uaz(oqIn#*ZP=zfTs;w-we-T1E?Js1G6&(>hx#tz{U?+6|V_*&rfP;OJWDhmL zbng4$aNMgNj@Y^HF}cz^or8heC;%HLBFV8xa)dfzI`%&e_gRTD4yPqH~2Yu(_56(q?2QUWa;6LEtTRNUo%$1@@2L=s{tLB(X||=)WV-aWkmEDzIvcw5_JOD+g4$11jp@*T;;3~D zMC~_F`z4AbQ$e;n{{^cl*`&=>)9*CRF#4b7&R``aiu^^bu$_4d7&xY;8awm9ino+X zEy3u&rCwmEM-=H!Eiqkr50j(rCP(_sx;M1~qyJV0f|c|r(vMnUI`VXrm3|y68Pp1l z{#zLaR)$a?Y&Sl{B+Hb^aHB1+$ zp?6+A^soz`U~;5);Zp*!Fb6DTMUk0NWIA=hbl_RIX=j2uyJx1G{OA>$O;ZD-|EXC5 zzH*|-!YDGI`eM899Fv`eXm!5H7*jY)sXrL~_qP`Ot&SoqsX3If0@VXlmF=_-m}H^up0p2#sXC1QtDgq-f+%t#iX5XJ*e<((JvN}r zJ^@!Qs|N{o*~g0ad4~Fg(SM&;!RO^Da*>*3JM7EGhA!u#sXoB)X|2PC=df$k5{&*> z3e!65plJBl{n7fzL8imDN5el5R@(tXhg~w7{;U4z092m?)n}r~(^Q!4u%C(cb=Xgv zJb<4=fTRqsSmcp{&zI|`&zX|igwudGq*Muq$!Y9D%4wpe9BW7ZqeX zY!R!;WzuG481uNcY5=^bI9kv$?6soDl4m-GbORrN)F#2z)7FenoO=?g} zOov_52F;s5*@PtG^HG?^1QP!+y7T_2yI^M*r161@(`kNjNpYbl4xmq4!Wd^svJYH#yR~ zl+OaO&=M?s6HUI3CSOt)Oo#mqZrZOwo!v8En*8V$8c90y{@O*8w$vQcVYf4RYin|(r|Kta1xEj^`~p^zqe(|< zh3T-9O;$Q`to%x?!05k~zre~L)CbdH|6x+qYxnO!)KWpM6IEk6>`tI&)iQOVbA-|V zIi`VXH>%2Z*xgLBPbHn`fueLSh+%dupRallPpsv*Qq*;{;S^x^_x_k z?XYhauYQNB!|1>IV^Dt>P3}_zOo#mt4!!>Bp@$vzeUl@-OR>cSVBy)ACZtphc`Akk z#pqw}FdcTO7~hvHPsJGbOb}dQ4=lYxpNrAI`hn5^)KmapXEK1k|irrVu(u82z8)8=zX9sh}w8i8%x!g4tp#|Z9*VwQ$Z~=mQ138Y=@nR)ilYZ%~aDgnr0aN zPxBnGk`+s4QY&nSodpJlsj0>eduH*LvZ*B){kOCjEG>#93#cWg!(L=^w7}#@zbP-F zR$%ns%4)E(GL|f-R+tWZrOC>2j+Hgk3XJ|+*$7tFQy*-Hz1}3tl*uNl4x|6-+dzE_ zRcAZwEyb&Er|K~Juf7M=cg2!?YJlmmcfp}IT|M-$!_GH3(z}$sfmk>O7LLS{L$Txl zb-{GlM{v^~0(ExJ95DIOEA%)`4UGP$<~;a18%s{dk^<_B?Xb_9?3_lc1tw!m;as5p zVD#T#A^5u%ORi9JOox5V)C!FLTe%Nb?#7ba)C$vK-!)me&9U-;T7l7j zEA}|}f9g>mOo#p0q^j3$iMRmNo(8p&aeB+dbl4^1tXrm1aeB)HqyKaK7pOiv zS(7Z(-IMmAG*ySufAtqZy+Rx*7e~rc4{V2BA&xmVpu;W)SF+TD1Uu}q#ru4T`h?Mc zpOwL9r8x2`HOY3^mB13y(B-@eme}S83}HrEdtb9#F4M4AlqTLz-s!+q|H=QOPXdF{ZDf& zSot=NL{lqlhy5)Wn5U*1JM8GF&*{~CP!^dj`W*yJ8A_+ z|E(l}mBcvm6Scy0*oh`9KXI%iQ!6m~Z{>He@+9Esr)Aj>(cF*)N`OzyhgQf;X|5Gyxe2s`B!{W#g>Wl5LN0{skL#snf#+bqxP5r^> zzrV@gZ(*lXd+I`tsI4tsU+J~vUHF#7K^AAIJ;k!{o@ z+hOM!8@ilrruqQG%d`#~p2K!hOECIlDJ9+a|0sDa9{%bn-r{@gSK`xBH>xdxq06om zuYV|mF)(ETl%4UUG8Jb#ZD+i%)2?jt0iJTTUKgIjL}~}d!0c23J2LgccH44%T9;#L zy%g=Xk82L#IV_kufH5!!RpWUb_Y<+#sThobiPeDVR-@Bpy6$R_@8jya8@lc{0#ytJ z#W$%U(|NziQLG)P;@hBDH=fj?qHOnF7b~oeNuQ~(cWBCC3@qhM!A|3N(vaF=JMhL} zB3Dg2cHj+*x7Cc=f-x{#AAzk8<4JRBi|N8YG`VVSa;4w6Kc;qI49w0~VCRc?@)@O)y>g_i#8CsD~qV<=>fH>7C7wf!at08y(|GLOkg}oiLqwN8Hc};DFsr z9Za6|s{NU!2*$utlmg!ViYI@>li#Q}wmbjJWa$sI`HSQ0`f%(Fpmtyk%+3(7Gl+U&I`u&& zWxbw<2C6s`6o*qqrduBlidL=HC^}ad1DoqOP#!~-*^YgTNg8VLN&7LLI)E`S2h+j9 z)OeB^PbN_xY}Y=OJyxJ=&x9*y)q@7R_DRKiok6|A7?{`j;B{_1nL~}To%>v4bC@&7 zR4-uqnAW+&bJzlE3&#J|R+F!M|Mkgl3Gn}SNU-SIe@RG7y`Z)chOYhh1ifpA(SOxW zp!#9sA!2zK;D*lLzo~N$Z#4Ijl3a0;B&{x`UOj)Cb$GcTGs^QmEER(Qf^Q zrVh_xX;d9X|J8dZG|_V(9lA_wlvDouyv^1erujsu4;6yZf1z}kWq3q|H>*Xqsji{ZI2GureWm zjH6cA&U^wGxTK~UJM(eHTbfKQ!RWuGSzu{K0+~iFFt(M)C!FLTUiQL7E>Q=H@?^;%aqA7st%+7>Z?J0B~@oT@s-7^ zuc7KN`mde~>KhZtdTM~_!Z*U9cUwL5unS*ra-?@Hn**`13oPU(kh}!4jk;hu@O<2~ zd7#ejnQbONdWG($se#e|)Eog{hZ4wv1hS9%V!Q7{COZev>OPY(rf`l@e=z#*?+o}m zl|W8Xb4=%b%H-{&$&sF_v(yTV{#&^MRxTxw3)BkJbzd@BxxleZ zblim|RlRm^1)_Ej)b3CM*-rbRNfzqvN&8?+)EhP! z{a1fB5&k_!B6%v21SRSX3)^LvN@R`==(3-JEBDod1iS2@L}PjwpU+XBF#7Ma0{ASK zNXk-^Y=>PAEHMpTPFb+THa}pvQ0uVaIqU^$3C91`(!rO*?G?i94_L3!EdnU-8G8?{-xBYund0W}=5~_>W z!tF1sE?xr{UU1PqiTs#Een=v1l1OWxqe?mLtsI3WC)rf)f2GntEbCk<$d>X#1)D9W zHDJ>v_$O-VQcfHAxv%J%OH z6+gx^5M!7cqtI17Ew#V&eie=A%=r<*43|QGRl~UGD}I>gA!@QCllnys#jkL}}wDw;>^@jButJcL>DW{tnUc1@_f9eeH zk5bu6qkpsH3^ok~5UnYY1=_Vzo{pf}+&7A#N>XXc8HmL^6CU^I^C>T$&HlpyfG30?!|X+dmGs zeYrksO;D;Z4KM3j%>Jmg~96hshRj(~!VIg?9JxW@XRK%Bh zpe|C4q-ZwPm-N{19k)5^yJJhkJ|0^dB1cO(|D11=yQSVJ9Rj9kLSy*SYKG`hQ+tc* z^jm4MwitGe8@3hB8|`{5T$c*ohcuVBrPN{5Y?w}wn2@zquI5^(DiA8%9><*0nA&tn zT9yQ0IG~@bo*}FatQrsKc&Xm^`jWk)T3VKrmYSiiZH5a&FQerHS8tS-ma8gDwZpx& zG%rb7@(Jv>v63yN0q`a7hwy5x!^jatJ*}05X(~w%+g~Y-@Faus*lxb@bgo zs-t9I`Izgdjj@ithdP4b;r1V3t4N!}^D{=Wu&lX=#$Q?*9Y&F=t5< zREVbJ3f-;-Z^z13(JrvW~BHjNETCN@8px0;kfnkQy!lK8sJ_9w4Ig3?;+D|$7(;_u9 z>iGy~@=&}w7_Q=(yi1*SlIkJ(AFUZK75;#G|7SLN;r3rXD_KR0|0~?KcR(Uww&C{Q zv?Fbsq|fie|9O6@N)T_NV@vZUx?9!$U7hG3fll;K<3#_0;)M8BV2|Z%?5&Srn(9uO;oB*-_d-$Z{!&lE=kPA>)_kdGML$_#edX~>srj&qGt~R- z45@jj8tf1a_LZ8^Cr60k2H;>1+9wC4dZ+xyH1%Af=d)g2CO0Rkn{QM%Bf;xUwGMBV z&KV9rYc&Z=Rg_hG4)WShLmn_5tafX0iyf= zH%1zbK|2BMewETgjiEO3>PtVmfs{TF0OWhYpv^^n4V}S{9h;D2N#sZpIg~^WB$0i- zwjiZ10HATuOX1rhr2x10oMS~&cce(_4&in_09WaD&e;b)XRAe#Ej8C~!Y8y`^aBZP zQtC^8CN&TOz@!FfbAcb!*D$G$FsZXi6(na-zzFAtjz#O+{G3%#cF21bm^U||k`-T>N6ol7Sf3&LePnxP9eY3Eb&KL+{ zn$B3b2-DH^#;GzzKmAFU)Cr_Nx${F`!O6e+!Oz@Rq>P7yP2uHy|*v`oPd}!)9Nlmjl z+O$_%Q)+XB-h>kYVuFc@V1i9R6?hZgm`vZGTUcM{Ot`33yZX|fYM%uGAoz3`v_({3 zL$#+uwFe~=dop>PL>?xQ`$^<(61k0)pQY2(kM_WxqYrao$O%eTTa?;mlGQin!4)Ye zS*qe|ygEQm^fv1KDmrAo3hCQXPi3N-GCcyM8$NzL#wvUWi{Lv&3zyGkX)Okj6C zom}LzX3l+_*Ik%_Z+8`)P3^K;_+=1YTbSjl&OezB?k8yl{FdbcQl`2z# zez)>7EQj=rI)PzNcGnFlNB3zu-Hf{{P3ycB7J`^2z78(J#6bwwaXm%Q?WM2u1{I;+ zA=Q`uY_Ba40D|Yjpsk|%8n#zo*k1ohCNC$G7n4baWKu4fei4_lRVQqRL0Z*O?+X4@ zb5;&=qkqmV@<|C&m7*s(4+tiV-e^HDmZEf3fPvQ0a*XUC@oUY$+<3D3Y3keJC}Zp zs~j3k%yIS8E_^Z6MNPIgDF{{G zlv2Yi;N@JkVCO=?dZ_CI{}-+gTDd-?y9Oa}eOP@FR0VPlFOI;AoR`(5sO{A*9EA(g z%gO4(JfnXi*RLN_ftI!8+s>x%CZwHj!AhxLQ+0>jXqBL5S*ofY3~L>_ta|Iy4tDq+ zO)nlo({WsN@=x|}af_(_%6PU0VbUkzB4hxB;6=gzGBN$LfbN`r4ox|w26$1udzG&J zI`w`Uu1V5YdS&!dD?`h%I{p7KiP{%Dkgu_&^;^C(w3=r73@ES@tD?Vg7T$o*k|D6$ zzzt0Boa%-7#!xroh0MeG2_I>6^B@A>7yfTc>~p7nxmX1xLGHXNSM)}JpW22=(rfC{ z!;OHe!nRrTMsPt5S@U~6n|;+<(nfa$bYWJ=9&;19o9`&HY7?(hl59s%D_ocNv1Piv$U}0vDnBbiHd7LGK=LMgrox zics$!>dPm0k0AT9(8@Nuy^P&%UmR*n{K1wMWD6?!jLmLKc?SMtn=&Py4zjOB$f{6V zo7i7$-RyuV37C#{`wAW_7g-xZZLQk>*dZn%&X!iv7yT7q^z9UBC@{v3romIg6ZAp|%bk6N)6F!_(l&ev-$$hRn;>%!@qcU1Z*}X5Qd2 zA0zVt5AsxP-@=xt%`PmavJ61 z+Ll>-o)^rC!TxK_e9f%!3NKhN29vFWxp~a$$b8+JNqEdqVCu=N$%E9z;9&*`?zIL8 zd7B4mj*xeYS+%CMVbgW^)v%&XwH0m53;hL#{#2z~?OD71V*?w@sSUE@4Ui9fo3{f( zel#!V4?I>fvJ$Oqedvq+JH=^7NeaBs*W*t^+;AVhD?&Q+AiYt#2N-6KlI}cC26EDk zHPlGUe?J~`6f%cfGl%k+laM*ynmLxooQ}*XJjfh`%;G_E0HSAmfn`yCq)mJtkG=*K zR+{T#x%G^e@`7!}V7b=Jjb@GYykL7U*iP$UJ9x|^$UJDx+|Oec08>xqaUSFx20v|p z;9k3okPAG>9faI0X4MKUkCKnI6}`p_T_VhP`+3aUvv&JK0~>edOUSMe#@@U>^KITr z2ze#UboZ&qV+qJ|gjt+$U;Cmf6sH{}1YYRt5p0Ot!iTSpkk@&T+9>@d7-o)=H+Y=- z$f*}*xSs}TUCCQK=6lF&YRzoSV}63naBJoVJmy!({G11gM94QhNIXFFY_|%t>Po)R z3NMC7?|=$Fn(N{R>lwA-1^W$y{cO!lGHWFAf~8`x6zgDr@tD1knP$!G#$%=fQ%`1J z9%L{EA83H!UK@dsp*+YWgp4m{)yAru&eWAeXe&CJ7di_=&*1G@yM3C0jXSe@9p6FJ zr4D(KD@K_nhO0Q#altlZY52HBkC>aee^z|5Fh#TX>Pe9069%LFy zXM$noD4E3LWFsf5j^$A@lgC_w%thAB1w7^&WUjPkF6S{fA#*(svK=8?c#ypS(X+j) zj@41}tyXyXJo<4|IAX4gL)J4ozzcQ(gPpZzo;GU~@PggIVArgJUEwhwAoH#@^EQuJ z;w@h?AM+rk0HS}HQ1UI#UMr1|XL*p95K`eS{;HLG%jzg;rLAaLUT6n~uB6h9A8^z? zYq!5@VB^mGZ$01iUaiMYFW$F#-3W2jGaV%k9?OF)rJjYYcE0E#6sH{}HQ|L`+|>;9%mv&QedV7)L{ znsu;lJmx@T_P1vCc6+vgjXU#&`o5#2Tzy-s_;y9UbxYNB%hb1h$6W3Pm$iNWDp2+0RjhAo z`(2SQD${%r7e=pK-xga0k)g$|#N!1cPiA>38qdw+RY%_IRy@Mvg(9ye4^kH)VLV79 zfanRSU*Fa~sbi7(>c`RB2Id4`p58}hGizoO9`h4qhFdc~;4#0%34LaO;PORc@NXcU zZEf93(C^z_cKg>nQaqAc0jYgV+qOk&YNob+(LCOZh zeW4H16{B}%t7DlKJB7#VgS?(BFH7U4@pyxfH^7S5pT`@4yrDeEScHt?K{5fNSK~zM z${258uJGk)7BZ(>GpF*H^O2ct&793+F2)HhG(d3qR$=hvkWRK5m-0xPkhC61hH6}` zt=}3R_Z)gUZLG$P8uNs)8aMk=cok(Y8KQ6XL2hI88*Fv#)M8)f@g5`Z0n1yb@$T_> zr5gB7`jQQpvsmYqXuzJ~=(7y+p5sBvBcv=3@*jZc)%a2a%d_zX19P7*PYz^OvSz-@ zW6H=Bt(h(!(~A?TVt`;;YGCjXNGDs3Re7X3ND2j#p&Acr>sOP<%|lOH8?a6P5nrnI zB4k$sQ`4W%V;x4;fd&>$|7lA$S4=vTbZZ7_7aN;iIgpzc|_ zJ=Va+qWl}#e*l~5?r&(!Um6;k{@ZX_+xOjoswXeCA$!BP>x1;c=sg=UH=4&<>@*&4 z5b_4FylWb-KaV#GdBd%ELwURj$Q#RpOhL#b9wZAOdO~J2w7juRGcfJtXet*VbFMXW z4v)DEnTxHNi+Ie{IH45=2rl0y489)H$==x3@<=<7v<*mx8(T@3vE9Cz$9;&N?imWU zlrL2!8{x^_$aH``=CPhbR;fl7o20BSdRdCo3j76lp|5ATM(mmXybu2$guKLqI8eG0 z7-nv4ukttwa@>s!x2I>d3<^AEHDp$`W_o$d+Q@v##TX_crzaTOH}yGTo<2M&*&pwuow&$Y0Zod8#vLH@+xzZoF7*E%EQZyuyKLV6UlYTeaMXZkklWo<>f@B&;xmU)^1NX zuyJSRAbWuU@``Wsu0+T(^KvfXvDPDNjg>9Q7kx9uX-7#OywKNUt0AuJ!|z5&J`ZvT zrS}_;lD#}m0dkHTYv?sC|3`VuOUOKL%{*7f20A*44CG8m-?f?=jBN#}7!BWHxMhH7XT9L8g2B6FfOb3Bikh0Gb&%xOI4 zd}LF%y!H!|D z!`8tL@|b6ldCHo3lE=IZOg)(wc#uL2e$@cMy>x=$HlDLL(8M2k+!1u zd7(>V=x3W)93|?WwcATIVQ($CGb(3w=Fm7~+Qe@O2Op%7ZjO>9@f!bClHOao$5t(5%pp9;7z{qr0KvUB5h3GvkXZ+{$C^L)LC9ThYGg zhbc}wN>0EFeLapE;>P&!XAn}rgIq@G3&x}59FKDgIfcd=YN6%-8jtxHnGdX)_jt@w zO?~&5l1&ZAm#$f&DSHFJB$Pqsb38}|ggnoKyb2IK+ZCHy9VM~a#9!jk-KgMdYP!WZ ztY`FJUa;3OnAe&aY}QbC!9p=uP3vGac+7W@S=X9bhsSIJOg)(md64%pcryb8_u5AY z`G5y$fsikYS+&obS{)_dX)F3EFLW%1j#25x4>;rvhHNwhP4`1{N6sJi|ffxFEOftmn>BG-N$TS{g9!k#v!%SC_#p5hRPL8pL ze$+C!kjGqy%+=P+l|1HFWae5kH}aS}k(tMX>_^BR9^^Pc^lTroEXqFG#1HZ47f|7> zxh_sy&!~VG>?Q`gZq2-E*0{_I_6URBw+?of$9%e(?{p7pW;osTGO#yePj{@#(!kV{ z`794o4uk*O0KvWX5<)8QAP$67YG!o<&{yr%W>!Z@y0)VK;e`&y(6UN59wq9YwcFhW zHfCS~vd0=A89>zb_cVlLHZ$FQCh=Iaku}rG)^K0+`4p!~Eru8RdMq@=9pS^TK*&-a zWIal+0mIBuvWmyqhMdjD8tR~Ba1)QY7n!@PnfW~CQDh#nW**=%Pa*RJ4{`w^XL*o9 zfaux2YFU({wTWNm(I2A1J#$^$v7XT_Ua(T{`u1?icMW@3&wq(`O|@rxm)+J_BhO>7 zGS_nLwbHxE)BA+Nt{b(H9fwcc3q#jd>Bgf(-LrOkEdv{~{`f235 zykM;`ShO`W(yS4|3)U8cwXqJ?n#b&j%%7~8?Rm`KfT<_*XCCBl4E~1!f_tqCLOSsv zeG$^Dm{secZaULQOFS?1-O$zv@- z)_f~lD}B+IQJi*^tcDl*daN+SUFE}XK*(AiWE)CvHXbFLc$_`R*=eky#ajM%@R&!D zdB~c1fX6(8%mQoX2_EwjGSBlMg$TLIgWLy*p6xr9MY&d+_$?m&sTRIlOot!(Y|MQ=-Sn$%D5LSK(|hPbv$2M@Y8g!7G5aF3mo>8ok2x5b1Ff0qJmyGb4&y<_BV-H@G7TVlwlgh@a<4Y= zNj&;IRG4F~i!AFI&Ey4Jj=`2#Gjq%u3wgmdV6e5;!B+E_+mX4&nwiUE?gplw%zPf? z00!S{fZ$#`ijYG*$T@_ZE@ssVERT|d+KQgwg)YR^;IC&5cN-JQP zIZ7lRrv`FDzA@ZSk7@a@%45ET%-Yt>T0CYWWY)K4zRhF4hs>rt$VUkIfCu>sAbPex z|HkV6c3zwKr#$+%s1RkYiwYkHgTTd3)AwA8BCY z&RmM@90TNLIEaWjCA@e>DQZmAKkFZCu_Xtd7 zX@Kb2em27DD0!$&ycCcA5-L=PFx_IxMHmibJ&R>|!5kQ@k~Q;Hv&MgT!Kz>|$vT+G zV^%|ERcoe~$E*cRJ(+LtAa7yt+6D;jwfYFD$Ai3&kY>fKT9XK?qr_ewJlY%aLVu2- zKT+w%4>;<}@C2 zJ~Fd;kR=FN#DlB>h@S10mPJ`noA`1beJd*Dn(Jbt^^Df@g6+j%yR4b{W{o^vuwxkP zuywG5Jmy(sp0Z}1aWSj*(DEpGOF(p?vAoEtVr5JAMXyG2 zn$(-{LSK&>hPa9kUk4$fJV*nSej5xkM@d~C=RM>!ZE3ilI<*Wo<}p7-=111d4|&XQ zkolE0^9vp`2APpONNa?|@*wR2qG!8pORKKLqfPvK9{pETNH*6+N9!3S@PegcuoP?N zUuKOzc)@yOupZXIy7QPB$V|6p_Tw>!15;1t5FTU<1|MmF;9i@Eka0Z7EQCxiX4R&u zo6htB=XGsGGkKvGVd(k1Jq!P}tAUL>b1SlQ4Up=-&ASUBJIu?uoyR(Wti4vY!hF$> zQk-^_6u=98J&qgV*74!bA>=dEyiU% zBL^>7H4IkOn&~xb1oMK0VX#`(!D{lD4UqY^HM1^{*$kL^G8^+CA7JqJ3=rIFpCBZh z2Z=z)*Tt;bmyuRSNds*~Kj(#x$Iz`*y72>!x@Yb77y}!NvKO+`43Ne^)b{rPg!D5n zXCEGGD6$4w+4|HMeH6uMQsd!;z8+%?aX<6nGZ8Y82bqP^)4?#)l}zPv79eM?v4)yz z8Jxpou0ZBeYvy7ea|1HhS~FMkm|KyV%Y*DhNFEPz5FmQC_gNO@m)gYl@aU&d;e@#^ zj#2rt+b40h3)dETsXmKW>}2D@n;tdPgFMfvUv53QN^dCaGQsV6fiioF3~>HZ6Y zKVyL4UV9!PWq6QR5b|=A)eS&jwHKqTj*@S*6|KMvEn;Y=N;e)Q>YlaRD;wB2y|0k{ zxd9RhL~VaZAtWNoboXh&W5prsTPs`fzUbdmoF>&CUg+!5))2R~58n|XKk*>Hqx3Ie zm^n(4d7M<_q(m7yglH{;fAN^Tk=etV*`3GCKxVo%vmcK+9GOFSkg*6E#e+-%h@S09 zmPPr!Ht`8OdNwL#nd@Sv^^B(Tf-S{hIo8aDW{vs0VCyj0YU^MtdCaZI%(Z520biuN_9n0UqQGLJEpmwG);{Njq&tkMTlZ!_b#`d)98hXkg>cEE(-P zhV9YpVfvGA^ZpAV&qSM!lBapBa>)93w8aVct1tRX6sH{}ufhv`Jt`XF{^r9w5K@T; zkx^O%!^~0Q;&EO_jyKwHlq72T59TpLky+E4S%b%X2bp!PnRR%~Cdh2agEU9TyFAEe z0MWDkakSO_?N4pu;XHaIDtu$Ei?6L`^d&FYcNi?rn%T;%5yK1i69#K%9jq;n`71J$ zt(hHp%)f!DC-V;;qzeY`WPspa>w%DNJjg(V^e<-B`l_4G^j%3OZAE+YLXX1G!+Cqw zZXar3+++_C;S!ahlWyc%iSyT0`7EKKvGh zY~n$7qI90|DA~s297N7OV-0oF^1p}2EI{UQYvxfN^CB|OSu@Y@nAeecg$KEVkefV+ zEykDahn7XzUz_-S9{o9>>%T3dRE+5s^HhxCK-RMu6vN)Ha9Ll#VCAftWz8C8c)==R zuve^uRpc?<$aGmV9XzH7n0o0dJV*!zCk6=awVDX2&V#&-khfy2ZUFkKg~eDMB^la^ zhVnwci=msSbmIpcbm$Xsd7T+U-|LgsoNWIIB(@F05uqGx+otW{A?*Cw9NqaR0wBj&m|WIdw;ykHkF z*ja1lX|qNFFW3zXcFj826&~{eGVfY5Z}XTX;(W<`%!8By2>ne(ah$zY8X?c}ATJ@L zLL7h9%Eeh7C0W{vmgR+ZVCYIJ-FTF!dlr6Ek%5gnGYr|a43KOfYWurBLh8ktj*_={ ztft6nWMylaFM4x|)1*Fz7kY7jXo$PqhyMa0pYk9rQMv^fW{#4tc$_%od>dytO6F-9 zjOH=hA@c`oW*Z(e8JUUJ%%6D7Kalw=57HSSfAb(c0itKSyJb>g>`A%Nw|PZ`IO9!6 zNo5`@7+G?>#R+%J7yWgL(~goi;Dx>()eLcu`|!09@+J@R4ocSr!^}}qhsSA#oW}8n zqa;_$e?uPgV`P44&1}wNevQm8teKzjm{G`#;6dUL@+}YYBS7?Qe;;pke=E=?{vD70 zGb(g6*F}Q$j5_dwb;4kOSu_7IYy8Fw))Rwuw+_~o#~gsne%8!BJmyef>d73$gN(x9 z!wnGJYvU0zh6kB}kg3J2TBf?`Oy8B9)mC&8FZ2QoJ(ssFA3~X za>2KGJ0s-p1k+LSCy$ketgZ)tY@^17wjkoJ7mo~VAj~j3w9QRow5#glE=J?%uCkH3q0m6 zVCu;%+>~?#5D-FB-N4VUkV_ZTJ@mDISwts*(5@XsH{Y`}Bv^Uzo8$ZUhifP-r z2-uq2pc{gG#8&JR6Mu&?>Q7^(aVNRBK33T1iO8Gd8;| z<#la_Ba>{feCh<#f_(2JX-OTfy;J0}p6j93DH&{;61zPEt~1449c0Utu$P#hWcv=3 z)%bSZkXJQSV$qYOpw~6s5;@Gu*-Ms$Idrs_mKy;LP=T;Cvd|b(=@Es;E48)X$=lpufYM%8tk)P1K5M-X+;*&%DF+un{>RT zj#?$1wU#{1ku0#5w3oP~&8U4VZEw?jKCdnOMa%;Hc2G6{PFqrm5*PFgSfmo{Kb5Q> zA!U;F^YGtvEKA4dwNc#&LCHnSgzfRLwb$Rt>0h&2(D#$uJ!P}m8iqxDo*0*q81YM7Li=AL8pS34 z(6N1oh%eeCCdIVYru8XeDLRYc3xL({MZWLF^x#A3YsC$fixI0ss>t5jAvSW&4nq!t@wqv1Vv16%YwPUSgy0~6T>Q`zl2>b&B-15cWw`Xo z%!TQ!f(c!5U3C?@9>B!L2$O{zVT*87xUNldtT-1Yx>3x9$sQH2i(TDAVWJ~py82Xe zVX9l*+ub|dJ7L-v-4EQ4+>hNUQfH~F)J^IxrAa-dK2l$)zmzTwlrp5j(okubG+Y`X zjgm%7W2N!Z1Zk2qS(+kEm8MD4r5VyJDNC9y&5^RDxzapofwWLsB;`npr6tl*X_>S_ zS}CoPR!eK8b@rLNJpjP(g~?R zIxU@%&Pf-fi_#_OvUEkdDqWWfr5n;M>9%xNx+gu59!ig-$5M*iNlul!$lc`ba+=&z z?j`q;`^x>~{_+5MkUU%-C6ARS%9G^Da;7{(&XVWI+44epxx7MNC2x>(HQtQ|Ybr zQ~E0dl`+aVWr8wMnWSVYQOc+P?6#qhjDtFS)fI0`L^MJYlsEdHQ z1gOh^x&o-HfVu{#>wqc*)D1x01k^1+-3HVhK-~q@JwV-eq&pq}@*yA}0rD{*Q=GRP zot(EFot<|asm{BOF3x+7uFm_8Zq5g=4<9E?MBEG!w?M?L5OEts+zt`*AmR>Zsv{pB zJDtm%yCCvzh`a|Ldm;Khh`t}9AAslwA^IVRei))3f#^pe`Z0)p9HO6q=qDk10YpCq z(N9D4GZ6hOL_g=ucb<3dbY6hy7a{s3h<+KOUxDaXA^J6lejTD0Li8ID{U$`e1<`Lq z^g9s!E=0cv(eFd_2N3#Werbx!E*IxqBbT@d=ZE(-lzmxTVV%R;*AiZH-+RT${HCSZuQu5@t$JQlhJh>KhU#T-|LxY#vFT;dumE_DqNm$`pXLW^`2~DgJ-U=(KAojfSt8_lmI^yO%Y=N-a$%=ug|N%BQrPWTCG7F67WR792>U#1h5ep& z!U4~E;h<-OaLBV!IPBRZ9P#7|M?IT`W1cO-anDxaglC&@(z9JC@Z<@nJUfKbo_yhq zXQy!1vr9PV*)5#+>=7<__6iq0`-DrL{laC>0pW`0pm5c5NVuRJ7Or`Y2-iJFg+k9U z;fCk9aMN=_xaB!1-1Za*cRZ(ryPng+JQ$t@SGPOdM*f$JQsz>o=ZZC z_p;E*dqwE%y(*-7uL)he(A#(mg>K#(LU->?AE4mz4DTp$rgyYB%R5HQ@{Sc}d&h}$yyL}e?*wtKccM7Y zJ4u}Hoh&Z!W{L~FQ^ZBysbY?Inz-0IU0mXwAujdK6qk8tiOaoN;tKCTxXPO? zuJ+Cq*LdfNYrXTub>0QydhbGUgLjd*(VHV~@-7y0y-UQ+-lgIe?=o?#ce%LDyF%RV zT`A^ySBX2ktHpfp8gZw0t+>m(PTcKXFYfVf5chgFiu=5q#Qok}@ql-;c+k5=JmlR9 zk8R>%?{@KsH%~n3-60;UE)daZn40-M?B@-E1vf56VG_}i)XzD#B<(* z;(6~O@q+iTc+q=AyyQJ9UiKanuXvA(SG_01Yu=OMb#H-K=shLg@SYZLde4Zryl2JR z-gDv|?|JdA_kwuOdr`day(B*HUKSsEuZWMlSH;KPYhntyE_Nb?VrOzgOeHtPF65Tj zmE0D)kvn2{a#u_v_rxCLzSxsI5POk_VsG+D>_Z-leMySDAL-=oPddBPNveAQ>Ea$p zy1Fw+H}@dY-94D3xrdM*?xCcodl>2E9!`3@N02`5k)*GC6zS(4P5QgXkaYK0GQd5K z40Mkt8SV*Wkb5E-?4Cr1xF?gL?o2YwJ%tQ+PbDMV)5u8o0dbW3pg7t+os4nMAY?sa6Tdp%j^ z-awYSH)m-|gL?s@hAt9R8sz1}tVjC$AIGwT()XVtsm z&Z>9QJ-gm5_ndmS-P!f-xaZcp>z-Hdo_l`1`|btx9=P*jAG-I%K63AkeeBMUO_6rS zc9M3*c9wR>rb>?*cY#M&saJeAsds#LDXUhRG`m(0>0E42>3nQ2c=VR;H0dMVZPHh| z9@F_vA9@TQ+tWDw)Rr^1hq^m2wN_l3R@wa4qGXm30oyCt+iTOR%?wk#UQ)Y@ytH;#xs$7#+}YJ# zPIaZp%UwO>8P$5qGpqHIXI1MhPpREUo?5%FJgs&=`H|FLek`TSXJQA)!{Z0ar`FxWJav#S;`68JlUnP^}o8C-0J7kJHH)N_jFJzj$yUKKVe#i`YLC8#by*LXV zS@J{gZ23HyBX1zt@?Pg$Ii==2d8li?+}E){?&nx2_xCQ6`#W;vbjMLWY;r;#vJaL6@yT$k^|mpTueH{fwo z9wFY6M>uZFOT2gFk&e6a81WulyDyJ&Jdjs=9?HEPkK}o=kLCHXDavKBlX64stSpU9 zRhGqefk#(md2BajMQnF?q$wwa9?A+wPbH1?QtrbSNDrNT;L%q(B=l2GIr=Lryy?mq z#{hV5pz_F>0gpk-ir~RYrzSmC5GN}~LNb-3AyeQnRk+3v}Kj%%?p(Yr+1UuCH> zHguUXyvcIqn6N_G>0GHyaja6Z>#bIHJJu-Y9BY-Sj&;fq*LvlwX9LV>qw?6f2_Cu1 zbjN0;r?^F#;n=E-AlsCgj_t}UN1k%nvqM=>FJC$B-KlKz?ox(3b}Q>Wdz9Uty~+@A zpRy%*zcPj#Q06%fDp`(0N;mPavRFK#%yt}A<}^8`Y;zn}MunbGI*TWj3~zz5E%=mj z*LzyoES^zzif5J8;yGmkIj?LNFDTa>7nQ~2lJdZDS;=->QTBVTDzoZcQ|3CZgH|DE z+)&Pvo63OTTgnOVE4G(X+6p#X*>}{x4XoNGcHvJY?T;VB*K@Xa;^SgERt*X1Z?mQ7 zSE|M)#I@>}90%V|!ryEF#{QT3BlD+ft2S-L_}1FB67U>k@2WzXKN_ZWTkTp9JO|mU zR$&0}Lc_Far(K5cYXAc-4SzID+%MWy^-I$rd*f82n1)IGRl~p+;eaX8S9?+9NyETb zqw1eh@CdRGd_j9r|w0+O=xEQM2|NPp+vyRSOAu^GyI&s~J+G zR!#Lv^m8`bJ#!RMaWb47Em;?#^!GvMB_J^zk2PnvfXH%oyzsS8l#58`O<)wiC7 z$6-$q5d4TZnt%1(mVeo8r+GNK1}d(3Z}@`SU=ZWcbx?5`@Ru(A-c+mT$sZL52_G*5J7Y!pmYu~N)#|mYRSSvuwoSW;X6+L@ zeiizr_Vs$J>Q!UgwskpP0y9MY+q~E|ZEYm}pMO=~UjI%$qE*7L9Xhs;(Ervm0{-eT z>W4OoiB((KNNoE=8)?zTM!vMY0Z(7q2z+Co&;i~FZw(K4GyL1?Hqy8m{PaO18)^Eh zjWlV~G5p)_nT$0n2s^?;N;r z+?4Wj1CJh;kf6nW+Yxu`&xqEZpyby7`r};O&hj<>_oUMe>08}4?cgug+QqchH)`89 z-)chRzF1$fOt<^9T=Vw0l+o|iD}TA+|0C|r3oAzHllTmqf%hS6TzWQnP z{dLz4GH!fQ$98f4iNo%+1iGAQ)iV3^JrBK_np^*9)kp5H`{Ph!0l9#6vRa?Ibm7xjCR;s;*wMHlDqn0X}$(Fr@B3!^0yE89#Txdzamjgk$-EJ`tES3NQjSM{EbM+YUwrRTbMduMpjsa7K^Pa5gHf27wx-aB@DrDa8xRup;P zD)O!>@~$oNzE|WuRpbR#?GkTPUaTjxPjc_9tPDTKVnU((`VYR5g*JUK++O701W(B!!tYZvhy`>Pw8a)<;{a|wKbzNGBbPj@8g#ymfDzNpR~aj zpVhm)KcQEjtn7a2y;ISCM|^+8YX6PQ!inSjLr07oURdNGF=p6UKfZwIDSgCmUM_Gt)h{_Qy^lY=cS>e3+oSfS!v|ROz2kc&`;&WT z;~y0Bl)h-gjfl7I_(1a8c}#S=u*MeqECFK41N@2c85s%ji9Mm?AkMUP4i2^ME&d53 zZXd&X`ZT^~ivOba^>D^2Bh6nhb_f>7$yH^=drDu1)MFT}sE65r4jVD1zz-`qO@40+ zr?tXqk6VL!eV#omL1QYvQ;Pp;c%Dy^cWLyhXvCP?{l!CW8&#;X-dJ@!>MzCuJ6Jry z4`1c*EP>E0$upSo1TE^S${OLk*%r`mL)99Ym7dx=xt}#00Ji)7A=85o8e8OaYChVS zBej+?tqEg`iXEP4oHN(bY0wQFM==DC!4r1BUkzIoK^dB7pZQb%xS|mghZGlD-{7<= za=v;kY7E0DC@e(vV!WN1l>n9n7E5VouuQ}^A+6P#CdKu58UIB+!Tv4fNA?M-MrLVl^I|wr8lr%NXg134WRSLiyE8RdrFod{z$7`UFpMzkYtX#utzE zj~-Gq(mAI#+Ir6F%IjgrAZW%sZ=?Ag^ofO|@b-kzUnH#F86Im@QGJ$*{j*bI9mNqi z?IlSykKs=kK4Ms46>J0amo2PiNx_X}$0uYYBhfS;YIsH!2Fe%9#4X7gSPyW*D>m%9 z9`*u($(xjkmB63Uzjq=|u?PGFtMS`0;00sv7~>x`b_h~gNu_czcwV!3b_Z4-nN#Xy zQhatin*0K%;lCQ5$*C4~c8&!znP%^*BKyW^-|(T<-aoVuGsa&32LXJ!rBvI8Dz)Jg zGBUA#1Y%N_lDLGNDT}5{O%44C= z2RL{f*Vy7)l(^HtSo`Meahw6&+?|{5yY{t<3)Jd|J>C)Hg51R_8)BmLML~eU1-aI4 zW#&Npq<+b_WcEx>3Qp2G`>ZpG_F3^6shRzPTUu|Qb2fa=gXYqE_Nkjyw-YimGm_(b zdps~jnDB#W9ZK$<=ugZ<&Gwc#-DqF*paeG?4s$rrZVdX*n`B5-JC zMwPHNW5gJITe;Yobe*vDY_}9=Y4s2^fL|)DDEtB)y?Y5-gxmRt6c@{1^HDeWRGhm5 zO-7w&_XcSO0`~^n1HJ(LuPps>VOA}t_P@6K+C&YvvgPQc-yZSN+T}s`-w=LZmJ0RG zHgLP&X>p7hU{`#=JqJ&XZ*7#H$MaNx=BQ1R8EdZrXe_9*zOyfG(OF&`>+jPq{T6@E z(NC&O*b?#ULaqj=DChGbG3R7O2$6B@tUfh@M{2Li`4x7hB^aN$rXc85cD5wK5k`x3Su1tn!VErj z`^5K)?}g?cv`hX@ylF({KhY zHOJM7QIn{AhKw391ampGe15fv577I^^sKD@uqyGrll)moZ@j#hov;;8X*VjTV<$=M zTo+HGoEw=zsX-H?@bW2{xtTnFv;4;qJtKY}L^(5USDb1(|;=o<6qSmpe7| zrqfeTE&o&5kjniRXQ`9rF}amAX{&s}+bh<)2FLrSIeE>>##Rw9>7(%)o{y9{ah4P3 zngRwiWK2Qf81|0Xc@uh>T6f5$qU~sV$+m5h zBD#$vrKjR84-_1a_oMUP&)!IIY9`8VePFU>G;fK|=r7+8-D5lXcU8}Ehwp8@^VU-^ zE>W#QzuI;DN$7j1poOIh4c1OJPYdv?WW{`zPP2yV*mzVjHz>iCT-Bzp8Ls}EPFAx| zyVAZx2N7Ltzj(xF&j$2=5qXL|qt*R$=Eke-{I6#91k-XM?YB#?$XYV3Gg-(XQY$W_kiau&KgM~>NA zwJj!Hy|yPdSDvti)hRYnoi^@8f1j}WJAfvhwSSs~zS4?R!_#E2y$}ccjbI;s1&!2- za3iHHg8#MjexmJae2b$5+tpZfaAz(WF=Uil5a^a0byt`XbLg9ae!lGB9ClX87_|v! z?;pyA^GQoI+9_J=4MouE-oPHN-@;7Rpz|8q=Z(*`EU9yELdO1QFE@WX?#J3V2%4u? z+n29XRgoUwQD2J+H)Ut^!xG<b$5{WEka3>Rm)M{3%BFd0A{#^fv+}6NcO# z>FvM^@|si5%qS?d_Q~PUtv`67%vug|`l39qL+HD|AtlAbt#8aYMc*9fF14!pt?-Lb zP={LC9WUdXFhOZ-O?^Jj*NBqQe*BS*(fF`2Xy;gdRVZq$(-pSwz#+!~@)Zm6a%CCh zd_$#_+f(GNFe4E}K11+k3L5XO4IfBNk`S2cx##U zl+p(>H9QN_?A2av5(ck*ZS8B9=qEY$r=5M$%+PUgPHAtS@(!&GYQGpcb8K3R@P!`K z+YWXki$h_8dV7O?(z`+L0R3rr4@i5vH`*uUkT1jr1iFlG_>7@t#@P>i&2gK7k1gfj zOu>Iq8P3P+cA>EObQh@1Lwoy+ z7X|r_EZ^tZt)ieL@aDD)xK~?1jri&mgcN6|=9jRy31=1a5zm)wR?&u^{XT9s1mCp; zZwt2;2g%aHRKs(HvnYnXMRTOP*obRXA!R0JCx@{@gIFGdJ;7zbT4!OspJUzQoKI6w zjGx&Pc(rOhxp)6w*b~i8mX^V()EU8_={scIY_fCC%_;O#^X}>teDfFI(l2=!&+@f@aM7jijrL=ZtrB`Azy`}%f z&sq3i%-Yx#u_iVn^HMzS8@p~=e6gpr3esA>Cbn!!S@d;fQzl1y`paWRynNBOF4mJ> zDcjo`F|%%JwkI23#Jq69h4Keb-WV(1Bk}Cmb!Ahg)by0rkm?&_A=V%NFMm(t0Mly?Co~sd!Zb6^dI9sBRZp}HQryD zDt-&aZ%A=bu;Mon6u&c7{2vs5h!wj@^e(%?n#+Fv;8fUdO`lcRUP?KlS;`LrXMe2t ziE!?>aau~8{ebwbCWL2NX`dNg{!_(RhX@PN4C^;w9gh`932P=T0<9(0agFMzMx~a8 z6NH0khVv(IPREK2xvbjJ6h-L&) zaVerwoLU*?F@j2Qp;MI+REbk7HKG|oO%PO%6V(V}I8EO6G7Ht?%BHTAi{snY;r{H3uCh+MYtpF2fY(VN0z@-{o*+n%6RB|`nK;JS9Ep-6 zoi8hIN0+DKnay&c*ouPhvj{> zdI9tTX&2?ucMD-5y26@oJNMzh8b(aaxeo)t=hDH2IQJ2xjA*7j7RsaJ#7Gk7&V97A zu8q_Rnb`g4?!DAq=G^Z^zPHJ74{`3LrixRcIGGfgbDtbR@j+9?N1*s{oOp;txpRNm zsj!DMeO6&JDCLM|DW3zJS#jbq!r{(+79cjsv^&oIv5K+g5*DHv)*@gnh!gV(i#hiN z8r6J_O5M;G6Aq#o&hx-|Hcl)d9Om4g)o_+XzD@1^3 zMz8_|%ZY$H_vIB6yg>wrW(2E2uqsZhBnal*S7CAdLN1Pub6=@ZDW_9zit#=$HpGeb zabhizFz3F(nb7M&z~|ChjY(DQ2b3a2vlM*>wk>hu<2dmVv2o|VMML`7!Tm^sV}qug9Q#gp|2+KcY#a76bOd=m3(SH1<@7O)3$TJ99Wn6!tA+U<|~`>m9!Ee&ix8fMl@5t8p;iP zqCSap=ib0)Z=lrIIjp^TUn2rRGy`c0kZ7Xdo;})EHuXDMEy13Bm*v@U^fe;_L^Fbx zzDS-uAl8b+5Y5D{LwDOycbR8zgG}#|BOc<}g{fkDD7Ga<=GoguQ0!o;7z@RleBwqD z<(~Z}r?zg?^zk_gKKJp(QL+)ulHCI!-F%`8fpE9p4f0diK6{r)K=A~GXacadJzuu>6sc%uLwB(2nW#&=T_kKCl>D0`|HxG zR0fbXqM3F+wDU-tJM_Fr+Ji_N(M-D#+CzO}2+1>VJ`{`K?r3aTU_X6`MxtEIFjIiB z02u8PBYk27F)&v?+L^K=LBQwC2#rZu%yE<)M6=}F3AQ_YqQoaA5F2;pcW6i@4({BSQB~*;UJpfOb1SxPfQ~m=Euu4oM{no9w8h= zGn~hPGm}`DAD^iyt4f|_s`vyH=a3@v<8z=G&QQ&xz9O3Sbpe#;lQQ??^EGMQbwNFC}o|OYr!6xvXIK{HcohULZb1Grr~Ed(|hF5ghm6 zuZEhv@?~0$zzTk6d2k$kuM-yHzr{+z_g)5B-+7tVIYmtE9L9f7?OZnHe_{OhL!FiL zM|7|HC{!QmEFLCd?!6!BYDbQbFgg?Z}@8p`?zC?60CqI;B&f$|Y?a9{nA zE~}Q9Pe>Qhz3x`%enz_7Q-2mocN^&%x?gn`Uy?NQ(_dk6`;q+gml}m~Av;aP z_dQ|k`nzW|~1<^gqUqCtAS)3sh=AX}MC}$#| zoF^1S_bA>j*s&xI=AAESs;X)$bum!82x?JXlo4XSIjT!|BUH7EGD3*%`&a|27n3UY z%ol62@XP^gP?OXV-K$>?^~<`5OS_2L#K8UXWnE~gfM328kAEV+T)SenD~JuzJzEp7 zHR>W75*YW&jR3<8T6setaWez2yw~!|IQpUq3Gv?|ZS9Khh@bb+cf=cYOA!sbh4IS` zyOm8j5XLVz?xxBF(M-8Hl$&-F(In12bJK3NXO7l5P&bDx?~0?Z1>qo?;j{rxD`Mg9 zxmCBasmDXz^RE^Gj=pP&0MU$~ZMR4cIw01L#1PHIZbWxGPrRkf2SMTll8dH`(q zcN6z^6L%9E_u}_!NcTFpcWZF0kR}r&q8a0KFqU-_(+H5c@-mHYnntBk_6Xr1n&Hd_ z&g0$0Ou}K#{BaFuW(1r$go9{?Gaoqfh=sZHd784S=O;}S7ejF&DKdw?5Q^cf*HhG2 zM6WRXq<1F zyjU^oYs89Z#<~iuE4zs|36wkcm7(Ua{7tQ10DatY?l}71AuPmyi?y-`oco8ibH6M; zMO+#$YQ-z_zNH7g>;EUdx_+Ph>iVVlM*5U%ApDp0?dZRv%WL78Y4VwK)-&g<-*hay zM*gNFj=p;F%GM*AVKo3&ePa5&hx+Bi$0bsIO9|x!Nc{5QpY|^wHZ)bd28vDMMI#dZ zQYJ$FvgsVD+61a|uYul_n&pi&0?^F0Qh=kcDWw3>ECsCr)G}VQAfTN#(0?UROF)!L zAp9C&i;98T5D=mnP6Q~YxRQrX9q7hZ$kiN=e*uB41;rkn`n_;}Hs#69t9ZagE! z;~{`s4rQIUK`TA_tku7ean$yckUK`$&G7lpl&4!)x-!uvFF?j^%?RU<`AK zvCY0^O$0`9yckCq{FYS=jyENTbITfsXWo|21mCjWvDRxGeRt5{Ai5eH2kTy7-AzpF zmUTB0@lK#DobkBNRB96+_--{bs6o8j7dl#qT7_Z&|0Hx`S?6ziR}b z*p9*13v-E)Wo+8PG)u_{23qRKhOG6iS?fJO;BIY90j8Gy*_NQ-Es$(3;fQEvq#YgX-QH{Of4&5zPj_1C-k(i0et5 z-Ll#x*zdBg=NQf{>jqPKALL^bL`RZmx2)I%eCuD{7@S*H#|Rjm|2@VH`1)%z>+7%E zfbco#vp*d1In?&ZdJp;avo9$3i2pYC0o8Ay`c;DXl7#t3`Cld2ALW0kF@R^Ub!WiQ zx06s1-J^UDlwHKZKgQpM5jY@6U{=r{j5uhiO%xXhiG5t} zO$;Tvpb@D%eN>|I7>MpsY5?WpL{T+S86Ngg{lyweRXoEhQ=!x(6h!wZmjb0Waqy4n zYiqKsOzM(4qI>l#p?*23^N;8+uUNf4sUx~qZvyp3iJ~C^u#e{(C6-P7MJ{^I$MX#} zBDK97ZGzAm2rUyui$u|kDA-5yEfeiqKntkzInzwzQDxDFQiJF|H8+5(eWGZaC9PFd`G)-02Zch`nOsMrDHTE%lFQ|pHOns=2i0=EC4b^_6 z%0Ghdr^%x30`{RlsUx~q9|ZM*i6S>q3?K&n@%uo&Y~bVfTs(7JE+o#!?*l64^b;qd zd(PqD9F`~w2$FyFJ`70A(3KZx^#R}m(&EXZZv-JBx4WYA^>%`G_KOrHyM|u!QQ;3Ic22DXe&O$tNGiaKL+6<^oPZVV& z$TxzfL-7J_1eIy(Ah}?59Y^1z)OAGnU7rh>*@@zDg5jG$vjK2|Hh~_m80HCrL39tZ z2rvs0#e9O{8$b(!VCGj0vzTBI-NQT!m?cEQHh-3A;_5E)9H}C@S6vF#7f6+D{Jg+b zo%jAPkt(8l)#XrqHBl@hVYcb>DunG#pJjObKvPs<$fnQhCgN{H{H;Xs28pu`pSOa< z--sZ-%0zrE#MdN>)g;a~d)5SruZ|$T&P048#NQ)jw$bw*)PmL>XRzO=!A5jH*dIgn zqeQWZgxMy~M~U_(&nAxGZ1Q|!BK-xVw7 zJIT8J{0)S^NS|%+`~|g#WNn9R@cctLNBp-r52!{Z;qO!@2~U!Gr^h#VDka(O-jfu{ z0G@}N%I}!r=&O>X-gF|mN2v~!YQ(`ec&a6pO?^y`K=207p>&LZ;v*D9_bA*)22WQ_mX%2l zQb%;Jo(%OwQs)~yi507-kUFA!^DjYn1J07?y_`_v2pmp@75Cy6}b;u}1E4JY40&C|eG z;oL@ii0=9R1HR!&Vi>`(4W8i|+c1qtrD`OhAi75>0?N1~F@{js2G2MRWlRK=350^^ z9%T|xCK3nR;F+kYs@lENMD1Rv-A!t2gXeCjg|kfeQ6CZA_i-{*OG%Y)@RVw@sJnoD zm_q7^?$u{NeR`58OA^zFfp73k=gS5*c*^k1f8|2rZ17C0nDbHMM0C$N51ez8#B74( z8$5GE4PE(ctv&$!n6!BE==(1rA-X{--DrR7ryN-C5EFCR?*L$dv;-k8dkrZgnkjF9 z^7klT_8EyGnu&dZ?rx>-GS|Ho`Ccl=J;ZfyH&y%^iaSV=Iqw}26u&W5{2q$C zlEk+p%H8)ar^3F~^jU@dKq*HwOZm^h`7ufCB^>U+e+0xLnRds4@2wbXKVc!7VI2e3 zktA`Lu$T)!qEQ{zsML-7IN>0g;rs!dlS$$P;V>tDQo}hB0p~Q~Ae!O)1)Q_Q!rk~; zO`4U>c_KhGBk(5UkEsv=cjOl;Ca9FGHX#tr2rdRe)nrj6S?!51S6(%_Z0a((I6AJp zN^s2w zmBhx~c|#59DhKyU4UQF3V`4-!V~hb~^JLMK0GUH?uJJY1s8q^Y5)Psn&h@~#E?Kl8 z9Olxm({S2Ez-dc3h-Nr90;dD9FsI%@Q&vvBqp4yX6g!b3bL*X;7|we6sIQ1-eeDM2 zE~LyIdlyX_wHUA;-H8Cvj35mJDaj%!StJk#ckL;BS%GU$!ZXX|LgTphgo;_yi51a| zwI5jfB#Yhz%AI>3U@>!8-dn2|K)+}?cN~3LgoWq|>uoRnJ);T08c$5jxsM0H8`4UI zIQL>wMl@5t3(Av{#Y7V4&V7=zu1(Z9!1R{on{o8rO*n{VIHkb3k65^KzYl}6R@O|g zb6;l>;OKjR2oTK(9!!q3R~`_XMq-F&V$;#xGU_gK?q$gLIyvqk&ixTn#mAudC@C`M z{%8cn$4wRIL2+)fm`$SGxzBYfY__J)D(t_MazwL~KLwmc$zlQFaOb`V5O2w}JI;MU z#aK@h7NQx}QeeH1ES@7Q=GfC5u-GhdKAxG@Mr=;H)4V zL^GVXf%6uzaOeJ(Ce6xb6%ins5xfh6aw6c)y}V+AwM2kuM(_a$HYSVr2!c8HjaVEv z$i>ld?(b<-%IRz}#rPZ;pC*e>lEr2sVb1+iXF`7h0zQ{EYfP$Yw^E7_%~G@zY+omf z9m!%lv2o}AwT86A!QHOGu|oQm7!l1F_kwXxviP0=nRDNx@qMpRsg&&_97HpmL%=zZ zEPf^&=G+fxI6p_gIZQZ+W;n-zbCg(^b3dvnt9t&`RPiJfPmm&W?kAua&U&4qz9O3S z^-n0DCS~s2PixYs#en@dO9Y5!1eH=!geOJ(lPt~?2Y2qC6t=9ux&MQOW|LfK9Or(% zV%EwjYU2XYjI}0MtK&-)M7ueF>zj=oxih3E?F9oxA#0ahbo zV$Qu005(f25#rpVNg2^hIR?tj@yAF>oICgCDfR|RQ;h>mA6vc|M_)_AK{Ug;4mfRy zg**2)7@V!LW`dpjHj4m9pCAH6GlKRhBtO{xhnpMM@pv-O-GEpJ5<@f-y9wRBk@T2z zzY+P~CdWO*xpy*E>K_L-v=U!Mb!Eho# zG$R-bg3nPS`tj63khNbzrz6A5$fcQ_Ne1O$98 zP0*NB)!s!ZLNrU!6tF#jKSqjwNSxTXbALcXy5GUQSA%1PG?f?;%@}8ZaXR*E2#`7V z=^9^|Mx|2rDB&QQ;mifjZ2U1&!eP#RwubX~1e_-b2hj{?0dVFM3v=%CHDy)L3r!WD zhT>vUWX^pt6vJ7sCDd0$v%WqLvXomAGaK0fH?%cn@;Ovz(6YSjgSp+!xz9RxeGlCy%Pp3KefY=@qLo^fn5#8NO z-DS>wFY>)lj(do6|H)MGAQbnLB6IHhBPbp+RXh&GqbcGS66MbQs8eCTX!@+eex;Nn znx*_Sa89L&-wB61_fvq_CDZOW_unhVIzw29W>^=1^*4Sog|L`&|68N_OQTXZbWf_< z;XpLQshXN1s-%j_sbT&wL6y|dBvr;Uyjm4bHNrtO!>I+F8pOh#dksyRmCYqYfM`Z= z83-;V0`A-|t(c%55g?ioGz7s_sp3k4V9x!j)Uv5R%f-=g?pJD5%IREfiqQfX%~HiR zsiFyyFz4PZ)!yv61_XRAHPM(sB@!hCVsg%VL4x$-O58!l56_=ZBKr|!B z1;Kz+aZ9SmCJyf02k>PD&ixiVb4V^Uj&skhm^F`B5zSZ&zJIU!}<_dAEb(ngvFfu z2O8BzjY{3nKO!7NGn~(X^J%L1gmBoN`==VtClPSA5)Psn&JN&gCl>D9w`aMr6X^%c>quUA019w~F@ zUQd%oEe7nzl|+DOMi32x#%bc}G|_-KxN~ou#+DU0_p9;DEVj!tk)1Lq8V!& zu(nDQF$Bt;dn;fub66gu)eE2>mUdAdeb*8eqARQ`E7AAdp99u2#KfHYGXR(?9bAZW zf1Z>P&6Jlx`K2`RB8hY7{!*H~f%2lp0jA$9=Z>TA6~aL@!&w2G<;23B`*IA<0$DS` zd+rM@=Z>TA4I)4^BX~P4l5-D;ts*f*GqE-3?rQ2TbMC8=?}c*QL-yR?HC22Mit9*` zIrnuD6gQYEegwr$Y2tkn<<5PRQ(^CG`mDk>Q_2y|Qoa>9pQVW{gu|WtXMp&PIrl9U zV{IcWL^G_N!1_8(>>w=W+`rbSc4$=U4*D(OAe!O)4>&)hiQR<5ocj+N&h7{}dkF{8 z3}-)Zej*m`+<(%fS=k&Q0z@-{BOo|T1l+kFu9)B`5g?iooCLv%H1R7zFz0>(i{n#r zade#fuNswdI;TuA{szWhY2s{}I71}Nx&P%%=(8Z;bLou6q^kBGN)e)2imImLlcID{ zIbC?ul@sO8y-Ip0Qss2}4(G*de8pvjR4rY3Q$#byI$*pcUDPB%=G-sQ_-blYDrJ`v z4x$-Oec)V?F6t2ubM9AYIQ1gnTtzsDW;l(3b2YIr=YF-Otm?UmsbVuIUPFq^xnBdt zaMr6i^%c>qudSdQL(1H_$7s^1#en^2O$3N$1RX%oE?r!oF0LaE?%dm@vt(PEP-<8?gJJxhvl(ay#RWF<=k=fbtNpse~a}C{(57& z_17Ek7=UjL4p0jXbL}Mq%BH*^-CKxjpEN)%B8cu)?}O?+1H@e<%pLnZ1MKzeE{y>^ zOD(^Qqwjt~L3EEY6)2O5gS+*~1MtsK$~p;l>&q>59DNUxI-+~^hX+J*>H(qYB!uW* zXePQjgSyFF`V8cFxg6&Zm;RWE+8n6OA~ojFXGKt(YofLQYV!w(c_hf)`Fy9E=4slj znif);5#6WxS)eQ#Af6%=?#!0}V5v;C^KF=?Dn@#akPzJ?y#l0{2Z*JF#9aBy8qrdX zNZqVoB@{&WC~pDfjRE3yLSc^l4Grb>2q-HF1<^f9IZ)mq4(`U^(PUYftRZzo_v-IK zeI2QDC%&#?^$nzs=w5v@)IS^`J|F<*!au~K_l8{b92fq9MxWUs?aYfHHhw0vm0FB4G=pAh_8u@yYKHboShEp*BTfrobQPb z(LLYK;QMia*h_HCdH<-f?bV1>s`e8KqI;C1K>1~WI7BGSb^oHF9EyN)j8G8Wqx=q( z--v@b?%y<3Rl6rm)XqTd4^m@p`wysvvrKs}FN8h!Cg6JNl9Z;?(4(_n8$AD~*H4^NwH(KgA z`r4B^qI>m@IguQ8KrMiq%JvI-+~^2~Z!OBgPT{bJ*jt=xvgVp5w5`YDCJV z6q_L23xvCK#GN_f4x(TV`)+5_-U)R+XYSB=RE6G0sX=s~nuoykV2+rQBOV|w?yw)! zaHcq@4`^VlaLR}e(LLYe;G3BvW)K{6*fTY@85)sF)ht3mbdNG0DD!f}TtZ)dx)(Z(ZXTp=GKYN-IsQtHbBM$K#YF8m)Q*xGbJ#~CsQqf9 z_6O8X=7ynshKOP6AE+KH8qs#5m0Iq z3Znb0)B{Rg;@}Rut|rUMh(#TJM8)ut2ZQdMEB}Vp&p$p8WR9>*wMLV zQ+LWm&vDp|H6rCwnwcP62ZT1cqE)VlAqwWO+vM7tEUlo<=S+;oqbgKTY7pJ0<|c66 zm@7Kuigv`s9rleHP6r3Iod(7VrxWoZy65W-zOK2VGr=*3-Bn}jtP!bH^&k{P_b91A zNzN6Cgu)zlvWAiv0VR!45Z$Bn0!mNfU=F*drmAYUw~1OmsP!Q==CJ!fEu3Y_qCO(J z@8hjd?N6%QVfWW$QFj6RFo4t%-K!6Qx<6Os=ZZXH;11i*mkl`Vd_1#TE+me_&a0U7 zHsVBd&p8sDBXY&<1j!xt2p};-SAM%z9{}EAIcyw#qX-Gn4brWa!!8BVeZ<2Y_I(iF zBke$l!+wBN5#6gk1l0#~#S{|e4*Nl8&6=VyfM>7eadGsO5elMvlt+Q`2yt+S{Rjr+ zfUJ>Vhkeje$I&;F)DhjQ&(4jshaC`_Lqdq|h5n0fK0)1N4*Ln@_@Er;5QjbAL~Rk& z7LXcq*b5@4EjCem4rT)&G643< zR67oPX~jsd5)z_&q?JH=Ggqu2B<8T+)QDDSMCzveHlZN8M_CJ$HMwFnp)iNNMnhR0 z0c9PbAi76+A1E7$gFEaEnk*}m4@e!+z52&c|A^GN!~UpZ^-oA0(Y^W?P~Vy>J|h6; zu(x8-`$aB#j>G;;BT_D9y9vTBAbguEzR49|5e0MD-#U}_8>sU+^OeS~&E0Xke^x_7fkXd%k1fJCZ976C88cM>Mv>8j(uXaY8|K zkMajlPUeaegu)#5Ne$&h1eDW+g6JOQFQA+y4(71WYO1Ps&zq=u^68%JLQLPB(d zG{kb)Hv*{x@i2$o0pcg59SCvQ9Z40@y=rHu#^s4lB+MOlT%Nsw(Me+f&q>SU;^^x_ zD2VP+;(^kgIJm>^jsZCm}yhsi^Ae2f%i0*}YqMPZ|P3ExE zk>hi6oI@OThKX7qsP!f_=CFH5Q0r@=b}Q8S=ZP#5 z`c$Y-&J(2sz#R5uEP8*-MbB~Ar5cfPDG!<;%ml)WJTW~_lo17U*fX3-J00qL&Xj39 zszM*5)F8S~&3tgp%M)|+#BAc?4tt)4GuJ_#t%0$^d6M`L-Sa&IzNhoVVuE81`)Q4B zu|}j)^(>(vx<`2#C`q>kub{R60P%oFeBiFL%l9ri}P zY`|f^hi4vW9_+B!Rm{1GI1$}*eh$u0^Ta0v$sP8mp@y#f6Rkb~eAaToHgsX#sHpa&E?#t(LGWVAT=5&8WIw7*o`!zh8mH& zDMu3uqI;B`hfomRqYMVhpn+l_p)iL%NJAMI0c8lGAi75x29yHgU=F)L zQ&qKlyNTLJsEr^s=CDUVEu3WU_Oa)aGNPICQ&3(sP%I#E?z9&< zYu5se15D3YUKdB-(}aU)hVwjdo+TFUwx7k|ES2>V?6zOB2ypbhKm>?p1TPPaw5J^q zTSj7tW@5|H-B+o*%yqwte7_{eJ;ZgtZmRee6yG34=DgpCpt#ahaSaq#4-~6Nl)LZM zPKB+~^jU?yODRV*OZof2*)UM7Cmim;Hvr-pnRds4udf*E1HwWy!}=6hp9~b635&V# zPc*8{8kM?ne?~ZnW;i>5vwfi0MmWrgZ`W|PMZo!ra1hOKz5~uqV&QIlrzXwHW)~44 zni2dD1V0b~cjP}*Ot6;-5X}eb}QeCP^nmD*?Z=TPV6}a}Mc;o0D7tA+;Q}^CoDu)SU=j%JsDVu#KfF?A^_f$RwBf?r;swD znQ{h{Z_XEKB+i}t&H47OW}3zUrj?d&#?jY{a1hOK`T?g8v2f?!2ZOUl)=aQ-f7c?w z(U(O8h-L)0=0|ew0kHujhG-@>5Z%qC?lR||i+sN;$34Wk=bI`Hfuf%jnRE9?P`u4l zaX1u*<%n0zscaJX|H1BjI}?T&LFRWa6h!a_8| zx)WG;bh< zr5e%;4(@Xr94n+{#E59d_$C-vU|rBe15;UJpftO3sIe6fmfm~&sP z;jD^)^Df~an&E5!&U#{D&V9Y6tm=8Asp5xF{D2ghbN>K};jGt3)K^5azHWi?$E3`i z`^TCzYB69xJ|zM~GlH)`@MXUEB42DJ4({B)qM34aC|4UKE+TR6+^Y?;o%=-^2beZnz8Obf4Z=Y*!>I$DONfO#_e%!h zcVcDD1UvVyECL*Tml6S@8Nua)B02Yf*cBv(XeQPG-K|gEWzM}m^8J+@_Ymja&{VMr z6dREubMB2IC`Owq#z3+8AkmaWxpQysR9I6@pH)~(N;#rg%C85`b%R73!r{*SIzVie zX?L7^n~Jg85*DHvRwrO}93*ZaEau!hYE(C9RO*HvOE`#TINgEMb&%*xILx_s)o?mT z!0ACah-Ns+z)2()?%WeKX;wBVM1W{U&=UmdM8KVUdc_18M1W{UkOhLigG44lFz4PE zi{nnYI6BTfQ=?K&C)*Sw9~gOqM9v^_E0Hkgp65*H91!ribgRass&){i2+=G>w}Y*4 zkQh2h3?Vk|+zU0Np$_g44UQGkaAHI>V;l#@F@wY?0%Xp8jK()gqf#jwPdJEXIFo=g zagZn`9Om37YBK-x+? z%(ZWY_#SB^LR|ZHQblyHx)Z8j4-z{_m^=2bo%L*o#sHqZmS4uv_bs6yx<~l|D7%S+ zyY<}|kOQ(#g5CN-OC3kw9#Thiul{31rydaciG&c{3mrr^_ft2SOW%(iAC%)9;?fV9 zs2zpcFQmpC`Y#dGj+v;PgxZNg;#U&n?)-#PO}}c|teQ?yni1Wn`7fZH9VE^W3U}sb z0kBu5+HvM*Dn>d_NQmx{qWt)P+%G(S_12uZ@=E?tA`hP7<)CiXRs8e;x!(Y#CQz#T zMKwZUj=Z{tQY`{XEkZ$bpOv~msY4vxjn~m+S(#i$>WJ>u>qGqtQs++mii*{*B6URf z>d{bd>=#!P0CVAu{rKYua?x{K_|+PbaxK@GAhZEOE5C^Gi{?bZ9C$0gy=fBzbv|dB zYdoq#ucg!=x=+oG;OgKP?fl|;;^OYRgND=2LA_oBV};X^_z>Ombp>B%zlb9^=Da&= zY;hWqN>w*PL3EFj43tE_h$j^0x)U{&_y{N|go5ZEr6*9*iGw-rbWK&&Zib0kAE@;v zHRiT^LoJ+T>Pvk@bl=DRP|YG$?zFQsS=3#?KHNg;i0;+>P|x>^Jio{x2JW)+`LY3* zorho**O(+4kk`S_nafZdAnZ}5+rxnw*!e8y7EG;J^*~ca@aWf{zFKJZjgMI z!@dVdcM%VB*mptvgtP-84*OnGMRcz^1*#AD#r-7A9rgpxnsvX%0G^YU$Hmb%l~54f zqdW|hhlqna?1wNQXJw59JM43oI*z{Sq>kubeWpLsUU)$0F%m*_FEj_;oJHMa4to}I zd`^yYh{K+1qBb9D^GJ<3?0FH?o-|Q=8fuIEVj&4~hrQUTriGd|tEMHCW<>XCUJ8^K z{Ng!6;ST!+0GyPmb{zI|6(hYwNQmx{Rsd z{9+}cFo(TLLs=OCrJPU@-J`4r%39*!4tuR8%gW?EQb%;Jz6t8@lR9_U?^mq;A*my} zSN{y^Tm0f<0$>h%3l_b<<)Y^}?2k1fGikqsI-fIN zXgsPycT#E)-KSrnRvCrb-KsuN|Qvx<}~3vw+ffu*f77?y&m;V46(z%xF)4c`VPY7%7{O5ZxmU1XAu`F@TVm z!_L)+253a;rkqbGi0)AefO6YlF_=)8!@f;J85{wnkWdiaqx=Ub!-<1C?BSX$E0d9= zj_6)}9Ms2WJ>uCqaGUU{Oo}%wbQ&qW8F5^c;s>tPv@fa;FKxWFV9d z7WWMn_Yehh*rm>-y$|Yq&fKH%s0y7zsX=s~ni=4lK3J3u7So7}JM8HiPML!`O#@?v z^C%%_8g6EmPVvfHIGmb-J>i9%EH0oNkU-`d!dH%WCWC_2nEqS z%5y+@hB%nRenwMOwfnq@+DlM-k<^&Oei3TnEYr)>M@091d=09vkScfBuV}KUyMTRI zPU?v6)!%{o+k?ehgT))fz#aD6eA$4*ehbgcl?#cphy6yyoU4fw(LLuzaK1NKtRqP7 zu-^+cbmi-``T+0@Y4POI_dX#Z{#&FUhh}=)Sq}Tc&=m3a&@kWa{(ETIl>bUQ5VD8u zDNt{T5Z$X@RDgePuRv5PP{Q0{M-|u(yHY_Y19+aaJT8vDs)T~*9;GHwsuKry*wqX0 zd$6)bf*tltmO75UTBMHXUj5R7NDez7RF{Mh-3wiTZq}o2GKXCcIetlwbBM#f(nPHx z)UF~m=CH4dpmw#1T2rV+7l_6r$Q^dHQ%#LEZB|XqD9woO)7%CqtqMd8p>T)Y3II>a zR67nkredUP2?^0X(hWdrUm)5N5_8z?HKMi}k-910NGOQzQ91)9u0V7m6y~twG?Y#e zP`VHbqI;BhpmZk=?y$RSvaC!JNFC9=dMebDNu4|F%6P)Y~|(LKstK$%1w%wbQ`R8{TXZK8HR)b1rU=CJRDS~$y8N_|9h z-^Zy?olL6SVNcd%QFj6R@F1xpx>uhG^%(_XdVwe-2JWzD@MQxIdpe$ZT`nY!!!E0s z^D*K?bk8{-obw9AT!Q2ddtRuaE1#>?2Y{Da4jV_`lZ1rm21$KO zlQk0Tu-9AaIQlk_I-+~^O%WY-K+y~RXrE7U$C zHRiBCi=ej6MD1&+?I;l2Nsv429ZofE*R)wReM4zRbf4xQfU>(ld`BqUVebaON||cM zVSiUK(jG!WbdPiZNIw^d9|?&$?4LEFA2lL%Q$9#2i0)C21LbIe_=QlI!#=8^{1O4> zS3*H_k8%nqzY_;{*uQJCtW5qObwu~-=b-*4sdI<@XT|D&kvgJ#^-6^)!c!>zApqvE zJ%wdcH_AoNaoGQ8M9QU9E;K->354o}qFSN2s8H>)Fo#{ea9VtEfBe6^T4Cs%xd_kj z1xrJS%q*!47=x(;d`4U84emBfeWp05e`8WoC$1jih9 zBaN-0Mx;^|O(=-&QCb3}MWJX$D9mBE&`_F1KxsuNi0)AYP_88o=CH5TR8{R>Z=%)# zYVAmkIqY^&3ul>bpgtnH?_(#Zb|h8qusdq9sJnoDh$VGI_v-Ob?_Man7K+Zqz#VpX zzHGo@cf~Uw%7w&n*qtlpOdw7~_nbY!nO-PT36eYPbRaQ9SDvcX2Y}aE4jV^b1|cE3 zK`NbP|BaF-fHjAhn9H66fRCjm2yxl-NEy*gc@dNs6pHyI&YkuGXYHD=ae!%y<#loN zEhZd9Gn{9EvxHc<+g^gf*(>WM*lq8#2ypa0M+Asw1WOAe?P&+ZULr9>GqG3E-DT8W z=DL?5-}~gahq&(7OcmdN;_IZyocHSy6yG#eTn)ulg<>U%a`(N;sj!urKC7^DN;#rg z$~ORKeW6%OINX7+2gDYccE^FQtr%+~VIi7feFCh_h2lfPVlI5MM)jdarEc6?2nW#& zXFG7V6^hRZhdJ?W8qVhtaK0oQL^GV7!1<8s%?zR$PIcf^8zwFqrru>SmtIZ7xd_kj+mgbmK{$wJICX$? z39&Gzeu<{6>iJSr#mk|187VTiei;6IjL!jKbUk5B^ z4$IqU^#bUT-rg8FtucV-nB|vo^!-IBi0)B5MJeJR;^1!mpYdf=Ps%z8cI&4s zbsT-(B9#b4_v%%OQdI5-$F8%Ca%tl_9#00k84$XNgb>{eRYy0g6)7#|(yJ9oEeM9V z^cp5=wV_sv)R;rB6+x|ziP{xVt5+oIk|1~I^@{9js;gEfkB(jP`U*h8KyT68$<)HS}z*yl7AU;I*e1pL^s7MSXIOe0>EB9*Ek zgo5ZEWjIiV6^Q~uVXk|ahEfm#Wdxxhx-y-e4GSk~M z(;J=TLCo^R+*O<+ju(rg#p0J@ai~}vD7L&44wnY}PZ=+dSrE z;F**1nV9llip!>)ZxLIi1kJUipPZ`}x9Hj0dZktQQJnX8i`a|gd9CRu=RCC4+ImHl zAHaDRTEtZ?@kqeyW6~1VO|DwmQ(EaVkLLy$CXf7JQeBAOMB5ZCpBrI4hX)hw2hHSz z3;?#Xu2GB2Z^dY_eRk#6Xgt%~rTh@2Hbuu)FY(aBcF$h=M08xW5>IP9C*`}w9GkEX zEqO|-M35(5pj>E?5nDqx+%4u%AWNH~d-`gkLF<+7;hT%8U1D{Gw^d8F)dOwe)&U!IkA}0KwGBn;!jGm!H-(NB>N!d}YWy^rg^d@Il_Far0kO~d?f^3Qs zrenv|QJG6I#Y$CJX&5dv*%~yN-kzw)n3O!cA34{|Q(6r}l3|x-uksTZ&2!D-E>-%y z|4;hyk<*f?^!q>`O=f!g#cV59rBDO9q=x>VYeq$n$LCwfYWx34P+bL>^?w2^iVT>o z0Q&Vqz}`y;748CGBnW61sr; zxI&&il%5J(Os%a`3fNUw%Bu=x##>tths6xfQ~kY4_Sfm&$!5WqS>=%tS6^OyyLGYk zaJbgP5$FbJGrj+bX*E)ZWFUvP&=Ezsx43QT3xenbD>HcrtIOm0#Bz6?JvB$}LJ);NxV^B^&E{YG+oG z_t4S@@iW2{>tkm68TZp|xSuvF5!aN6CMBX#iD+0t_tVm8>Vk(e(1MdH1zYS#J{CR%WJj1}+NfQwyw<>V-$~0#I6&Sg&@# z;P>=hk5{k5daj=Ic9c)H#*^i(O7Jk|i9%J+t)y-YboWW!k6UCkjTLGrOJ_>PHYG8O z3c-jErc1At=USJ`Wr|$|+AXp$N*|LKwJwQi*ITtOZ0~yuVP*wwoXt zqDzVJm5A69ag(!NyreF8S)CUjJeiYFTM3xV>Pec+c(OcRR&LD6@oKVlmsM~RM*fH# zd5mk**hCuGWoR{KKUGVDJg*zhv#X^G9^2L8b0$M9o~6kUb8bAQANIOSljXIRtTkbR z)u4F{wUlh-?^Or}jdTz6K)vu9Uci8%JFNj{4cKxzmj(dmB44k|^W*@?AKeVVTWA37 zyn$d1fczN)upa}^yF_G^h?`49T8T(;24JPS;B6IFsqhX$Om>NL|2xxEE_18pv$q7E zJ!w6=Mn0QW60@ub$(jjEmWE`>B$Uc|V&y9ZIXxyv=TB?ln%OLNu+`gll}vdSUZ2@a zE|t}=RBnlB_tKP4Vz9zNwzWEQT|^N%xgv-Ru|(F(OK&L&5&2Atd@4oIi`MGQ4f4zt zMXIcN%OMX2@0?R&WppFXYJHp4^!s>No&k8gIV?b7s)tzU;V_3{sPP=q_5sccnrVIT z0$#)mn*x`|jFqLf7^RjC-I(`eF1N>cN^c3JKoYlG_esl=lztd!!jiS`orRXbN2Kgg zu1G4Y7dGPs-vH~JPw=qyFzex#Kx47PL%MT2uElep{*)S}x|NOMMZEACUWn;i5_3wz z?*x3VgumIDS!qa=eVYkREXH7Gj14}*YU*>+2m)6xYz-jtl$G~I>pNpY(z8t>`Nyl3 zJzwHDr|pc9)~fW2K!a8S|%G_6Y*m|UO`qy|E^H!wFu_l9D@1tW! zS*L%4#~~G=Uf3zy=~oi7N~Tc0z43>RzbshH6uD#3BzCmb+PBnNP_onu-{FPwTacHN zO=HJkA-#X3D(wQXVWR4kB5;G|{8`g=`_ixPfH~gn!~myuVZ{-v;~;lT*?KC*cx#u4Q7oVr{p6knXiB zRz~XwX-&IgvRgk$!`KzQ%b+G(s|L^FY56*nJclQ(J31E1pgVeH@4DC~9zOdpQ&!niIjWk+i%p+89#5@G7ghFda!%P8>lsln$urH1bE0rgvDf=vq^q_#S8a~< z3>`aq+>oL|Pg#`RdIP)lZFHU`^%Z{bSTx&1+HGi`|DAKnH<3=+>q!3qV1~Op(lv*i zYxc)_#$lH}kce>?fyw(*q$^K2R~`?4<VpTzNjyDOKX^fvptB z2i8etEu5mVT|Le-tf;VXSjm{7L1T0ya_;q3i*)&wjzYaStuE@uh0S7}NR3_NG}bu$ zl~?N;4I(wx#%Zi&_{Lg9y0U|FW!vyqibz++;!2gwj*(93>NM^PImMZ43C=0qBb}1r zoRVI_sHMhX(v7<_WJFV~5lxQN^es-)S@QC5bJpwa8*;T%P9vPFhlQNd%bvXBoKr^Y z!#Oh2RTG`7CWOQ4ZMS|moo6j2rT9UO$Gsu#X4>aJ=$tY+(kU|>>4yQ#mXe1eT{G9Y zW>#noC0Y4@EYg*WohuiFzjA)0D_?M~d^Y@*OCnwQigV>lkxqHTIc0gIQ_69Q%J!a`gq-5cwd2kyM6AD}`X&IgrR2s)*Tg&5bn}JWPb*ulq)VhLZ+5Os4S!{Fq$~S5 zSN=cZz5}|6Yl~JgCM1+cAS5IqB$B2nkp>KbU<+_?1-}3$l!R`IW$+7_Vw;d|Fc{N& z@4feGdhfmW-h1!mpP9LHtSQ&)$NFo1XGzzR_C9;xbKB8KCb8zs8Z>5oWY(iWnj)kT z4Uzy5CEG1MW>rZedEzyv(c7a!TjRX=#k@y}v|ztuuwTuYsYZ=tTCj8smS!I8ZyK{V zGBeGY88qfVU@FP%M}rK*;DdD#Tx+8dGJ*z~ijYY;jM@Zg(HW|e#`1`cqlKQ2q36)n ztkpV8$HtY}qoTSIb*re|O5)VT+YceVD;l2yFnyq9ijk5?j^DCNeC39)aRmfan&Rj-gZbIgIbLLtaa|bfF z(jfZ~vYQ4u1`s9Nhbx+GB`xHMcaTQEfC^`g^WwC5k51Bp-NInk&6!t?8kcFo9%HZv z=E3gKn6Huf!kqbx#tf*WCi5K)k`Ext#e~30l(kk6As^5npCII;O7u}HQps#9X(^9r zVOnS#hAt`5^>1*bHEXq&(6Mo4ei^EEuSBS}dkN~|v z!O2@md3c~q?y|bL?Nq!6Ar)wlFq94j!fGFAiCDd$Ec9c7wNTYW~g;e9bNH*_L2U@VM80;T& z=3hpQKWM>vW3Wu~U>P*#U}O$3XZE8pM*>qx<}ey$90nh)gWy`5jF1U5$XtZX%3;)I zNQ=%;m2{FvbQ&%6atytMwq~u?MLIUF%wl2cR#GI)(lQ~*=c-$}tXn9|(pvL$20SgV z`w~D^lJ{wtrA=#}3zeBF#DUSj3bVxfAcn}XOVW7XAWzWp(qtY-zI?(JpF*oYUa#n8nZSsW6ha0Xw09nLv?i! z9KNO)yb+|cjU^+1TyJ++tqo|T1SGWtQoH7D+W5?=x$^imqj7&lPbvD@xJYKU*U!eK zY6|~G**|pAm#dKO7`>}@cC3+Or_p$Qk=IMhn=kV+X}qDx8)U{CK;w-@-Uu3G0z$^p zAkzV&%*H9^Gh>pDxlYZ~JY>!`XU?QCmm+hKIdcJxxe`0HTnEA7+knB>LOQjxaW##! z14&zfq??T!|jy?+^FFy@Z6d{Fakk0_3%*Ic`P4~uPI_7aT zPc~$hG-sBeF$H9@=1d2T>BbIyt%G1%zQy1{kWTGvEJY(#L{c!2bhGi4JbvYA-2Lcj zPq?<|KdYwd7(xz*8;bseG}akpoeVcA`md_dFA|)5_+Ntu%6MMZ#l5EDZzJRe4e|)3 z?}K4Y(SMi5d4-(k;ku&#yqv+OG-hCgx&o{brp$LVW6x^u_4CA~Xlh zJ2`eHjW-l|gS5N{GH(ElHx_xL%y=VcyvfL$K!eOc$W$6+K0uU&%!x2P*kX8 z%aFO)oVk$3T!YM&=FAl|=0@z$IvoUuZwCh73hC4yY@2DM14!BnB;COl2tBr1chR_S z(bFs4gw3a>DsQB^a|c8kHZV)1cJD=20c5=&X|hNPtIpa>nTA(6@31N70xwkU7>fXun( z%-J;NGGs2MK~^Iqiw4;Y5GC6iOebX(x#R0-^u4IC%Q!D~nD=NKE!c4kcEp@{$f$9E z7VH8BJ8K^7G>v%!nODu3mubv2+LKni&`J+v?5^2rC_tT@bM+>e@8?sC4AXR}VuWtb%Y_#F@anM*Ivc561 zRa1>#mf&Qm3h+P~k8--Wu`0e2LPBVe2$Ze@hBaGBD2?+2a;in^&eLjg2BT@ry2$*| zoEb}FHb!OxbLP)9W(#D-(IBl6;-x{_14PMoThmEdTkiNTH2UwT@T+lNq?-3AnHH=Y z2J2$Z{Ku&A7cE#{4A#p$SSF1*6q$p}nFDCd(ZE!aIf4e6fWgP=Ah_11B4iQ`G9Mvx zau~H)(xNlG!TCuZ(HXSRSr~d5ZOvM(OLS~pnY)p_LkDS~F5W{3*>4=qy)@PdWF0lL z)l7|kmf+;AgOl!K7nUkCXGi1PX# ziI8E&;T%F^jYrlPGh02?=u-$zmYN9C;vj#aU z^>e7LoWT_|=2m2GGG}g}G4~>KmpO9>jd>WE2WXI!2suWBTm*=c?Q^D+vaj6nGc@{b zRJdWB7uU>tbcGh|DF%CF&U|3hxJL{24uicm5B8GA%vVi47Xqv4c6VhO1XR=R?l>| zR$j-(3`{}xL>*)Z5asnf8zD2Q8BU*RG}c07%`>w#N{zmZ;AE*)@IV=l6}q^iRs4E{ ztf4`+q4Z`jtl3I7(m4B&vs*uh+RGW-Nn;*I<`Hw|AsX{MGS8SZPtllHk$H&*xs8w; zG{|FsDA|5sIw{A=9luATzeR;t#(D9=yhqPy!QPKi*Kpn#-5OT%pC`sJ_pCA6WsP&B z2nPF)d9Z>s=4Z(K#GF}-#{3GHN;1EoL0AlK*FkWteT@*F2Kg2tK`~}qi85-XV$8OZ zN%DxgX`w4)XpcnKZza;2wOWI9Y|MJ+`sxs-*4GZqR3OUh`yYh-S>G_6ztdRVk=3=n ziLJS6^j-ufOZA5b%6RnA#hs_(hahAi4Kf;~M}T3?Rx*snnT(tX^>tHux}3prH0B&+ z&NOFEr!kixbD=qNK8?8&nagRA^$1x*gKP(glI<<^%_ikSx#OE?^n<9d&p0pknD=NG zE!b%ccEX%_%&2jM7VHWJyJ#NlJdJq=nK#Xu*J;d0z*LfXp9Xo3!Jp_LxYphv)Xd1rX)+?LvsN zfnh7*X{<8HDrIJCy&C;Hf|I2x!UJVIf^~5>sQ4-fsZ4`ZMd?T|tl3J!X`EQ(RBxc$ zN><7l{4b4JADQ*cnRRH)X2@(}&TK?uCLpsV4blc7i8M$GK$L8EFrAc}<&L+b(f>w; zKaBI@H}f9-N(+{W!Md9>(~TNkXu$?zuzu#j`p}pokvYtqIfTX>4@@PQV`z{m7<{4* zf@^IiLZ;CmixILQhf$knx|M8~M|2J?^coDklD1~8))hK7uFONo-min~QWx(@gd8&t z=Mfs~JhIN1**c^~zd~^GR&o;_DC2QW7x%D=zlV_9G{{qwex%<@9?&>%k@HGFhxW+% ze?epBYlx>rL)|8%FasKD4*~2-VPqCGXXd9dKSpLz8l(h5KBYkzfGF9vH8eZlj>#SW zl13L%;hTnrBgSdoBc2wl0tPE*&Ma%x2%-h6g25`A2dhY9Rzqf#IWvOBtO-mdnLp4V zbuf4>9R$}}eT3AbL0TXrE{9QT($K6bIVF#1BU#GuJ&04LkbZnf?U6B2^ z4ssTV^7_t1NO$9Krqfvckk#AF)>Sq7V1kpSM!*AQJcjDxUQ_X75i*JfnS#<2!LX(( z8BgQPLC#G596B#&a5{~-6q$?6nG0ylHOO3P&RjubZbIgI8e|7Tw$dO60HS1juj!<` zDR+D~jeZIhjvMF2QS%-hrUko#!7iFJ&l@$)(t_Q^V7JVJ-Jmg_BJ+_s^8tB2pg&LV10LrKpXk@mP+?7Z416t_MF?4Z>uHQ-Yc%ImulLP8oDPM-=iRyeZ0H?#FZjb4@DWU1=#KpBr1UEG%{ z{zrt=q(SPVbUiSv*-GlrIL(mLq>-++cqC`A5sjIM%mj00JdN1_nMvl%HZ#7x0U3laf&0SSYzE*@}8XkqBN!rnI+AcC1^}1GC6Z5Lt~ag zri%tChmbNfNF{(Mvp=M<+4=UV-0=!DdNe9TK$>;`Dsz~5kG`h`tA)X8m@|JcYQ)fj zHNap$nFp&&V>U--Q*&lx8nYEJm1M@#AZ;*sq7H&(tn+D)~Yl z(G*(f?ijkOMAug((wene({yZHnIn)rR0sJAi1PX#kB~9O;T%O{O-0ruGh2cheHOvV zQuE<~G9Ghuah)oD2|^aqAgfS%g?=kpM&oQk&U*bEvdbAe_HX8FVG7p$D z_tBUqk$H>;IggMtG{|*;DA~SZIw@Up$1l<74^iQsabDap@6jzir&}A@mDT%J%N~ASwwYqg|%w06HBXp3mK$O>a4TSu+iQ)9A zMq|}MRxLAI9yNM>f|I41zyoDG8tUR!RPikk5=Vn1qI3cn*1W-qr*S$UCrLkt%E=jQ zLu3Aq%wNr!sWfI+Wd38${ENoSL}qsyq#r_h(;&kDqGWrp>7)#mJ3f#`pMVNujq_r( zd5=cYg3ZEU)6JPvjT)0_!4_k%1?Iu#(U_}{xx$>ejKYi$=o zw$mU-5OOewQQL32m4wS9x|bIE9ELtkTeDW{NgW$kW?)lw1GhHS?$lB0;w^xX_nR8F zlJ{t=BFOqrQ#BGgLQ2vg0!p)BShJNlXq?i>aW~Z+ zWL4$-e?wyiBeT3Y^IICT3NkC3Gb_@V(a4OTL8>Dph6bq%5GC6`HZ?onewI5POQSbM zg+|7C(ZIY%KhuJ>#$aA^W=o?+b6T(t7%a&=SQ{GiH)M7)XQt4Y{{T}-=ASf3Hw@lI z2f?-06CoKi$Y6vF$YIp_NsG?#H#m*t5$!_@Jr+ZcqODo0b%c(MEAs%d_v#=`)x~=p zAxDhEd5Fe3i>y;-wi49nmk3VYO0L5LWjwCv;Fq5A<8fJsRgVa$e}? zP%}CI&uGlNaq4Cq5U1OO6s9FkyGLVJ3L!JUIrDuQ^CM(_NP~QakWXk3J3y3de;H@C zmHbcc_!l&~3l*Gkh9ibI?-5H2Rvv?uHD?AHHA>Nfg<`OZ=D|W}%xGjrm@~s@%<8~Y zk{LsT{D{G8>L9q*enLnc8l)LQn&dEQjpEFV>QxX10D)qxUB`S!xJ8P{w1RF7EFtek4MM(I690 zdMp^$R3)QnoEgZOs-Hv2at0^Um_(IGIQn<8gm^oSJNO{5VDa5*#i(I z+dEAsI;JlGW)^C2?tnKSRu zn9qT!B=ZRk@&<#y)Io5q1vFF7rFS$)L4O-iL_>|)*?DKuFS8I&FdiDfGDr;AcTm`45yEa#`+Ff-kd;5)WQUusMlVWm zvQ%++po~W`UECQe{tJYBMuRXYZ3Dxat>jA@$AuhcylyKQ3DWQfku+vGWR@{!mZmW) zAv46BS%Jn3N9Ol5NHv5+(IB+|qGY>9yxI9STkiM|GY4Yb4lP(b25WB4 zj5BI9p#^J;!Tx6+tTm09ip-AY%=R?qAHYbhu2pTnqC_L^-aTjUX~NDEyZL&r#T{Tm!<&04Khb!;5MVaOh=gKP()yuQaGWR!6@ zN6=W4ku|~0)_FDh41$xT=E4JIJZ90LrM@63n)e>+*$`wNO6=d)={^W6s2*#Le3W*b+hk|oWaj&OeZoqb0$M$1|d^4XS!(2?~wT|4N?gq zAv8!NK$L8Ubu^ol&*YAOPovjFg&!czx^KJ2nD?kEEm(aFR?nPS$EfimEm(65*3>*$ zV;VCNnF;31cp9@EFqLGsp+QnGcn2K>*V=Cg=|qF1BP1<{QTw~2*;evO9??H(q5ER! zUJ_lul}KyWYR%NKab@05`O1>VnkV2@ipATpqx|c;l!6v(K%M|gY5`#83CNrJrQE(p z+I*yapR^y4How#c33@JWtb6$E^pYH88DRZ?QS6x%ugsaKb640*(C8OiO}aKSb5rz zpYO8$lJqOPhczHf+i7WXfc09+R0yb_T2x+>4N{9(^1zyGrVMRBbEVDGBK0G=i!I6H zc&UZ1ddcGi@_H-sxHWk_kv#q%X@4QOHsoXelJ*F2@wC@GDWQ|gmx>ByIs<4>uUHow5s%3hJl(o_$q1G6b5rDI|X zpI7?HulxuS!9LIaEbSWsbyF<~NzL1OeO~xghSyHDbS@th;`6+;i zHb1PAHK2T%JpY@Pl-FXhM0gt4OZIk5Zrs`1v0dlJk>2EAQrfj|{8M6bYV$Vrya|b7 z+vdqB-j0o7-* zE%`n!(Zk-`-qU_XSY}^oUt#a(++;su-)-M--)lc3Jh#8LzqIcWG96om(T;JBMUJJ8 z+m5bGceW3^mEFy5XGaJ-*`C4(Zag=Ndmt?4mT^0{6WlH?&AEr0ChX&83kSHJ!Xa+F zFh znf7JSkCpaK(2Kp$k0bVT_Ivi{(2v*lOh|*Hac6KN9_Z<6>?aqyWzK-F>LZ7AnZigQ4gdXqV_HhTeL(uyR z+$HWZcZ<8t-QgZ{Pq}B@bM7_whI`AsKH#eha^i-_Gygck;XV-TWSYFTamJz#rld^GEoj{4xFnf094VpW)B) z=lBc!CH^vhg}=t%;BWG``8)hw{vQ8|?;>;+(uHn9Poa;{SLi1U6^02TUW;eH$3Z-@IGaK97ocftK`xZeZ!du^j^`{1|zwk5U$fIA4!9D-*K!!t+VnWON` zF?i-UJaYn`ISJ340$-;=?+mEpKs^A|LqI(O)MG$B0n}4KJp`$GrrDp`y4auDy4s)H((Ny7-Rv)I-R-Yz8TQw(&feHE?Qd;8?eA>8>}jy(y4d^J z(`9jOq4ywi&>h39MPbnhmTuz?uuJdG=wp z`S#(q1@;lPh4zuQMfOp)#Sm!;L|O`wmO-TD5NQQO%7REM?KAAF;I`Vn$+iX}u7!x} zAmVz6xB((=govB$^X;4M3+!9$3+-F&i|pI%i|yMX;tq(o6C&<{h`S-;9*DRXBJP8T z`yt{1d%Eo)+z#2-*bhVGBM|v0+>Sx?;}HD>L_Z19PeJt45d929KMT>%LG<$w{Q^Y4 z2+=P=^ve+a3PisO(XT=D>k$2h{h|Gq!?Oh!=?CFl1_HK?_ z_U?{LOorn!)5CFv$#h(0dOEH#y&Tt>-i{kgAID9muj3Ze&vBdS@3_MZaNK1EI_@!p z9QT>Qjt9&T$3teQ;}J8=@t7Izc*2ZuJY_~Yo-v~w&zaGV7t9#POJ=O&6*JE9ni=m{ zZ=V3SiHlq+qdPmxk-^S(^kC;WGTFI~ zp6onFFLu78H@m>mhh6CC%Pw;CV;4L6vr8NU*rkqv>@v75cMM`zI0my>jv?$y$53{a zV;H;IF`QlF7{RV}jAYk2MzQN1quC9PG3-XiSay?R9J|>up55Y@z;1O+WVbmcvD+c$ z4v4c8;_QMryCKdVh_e^s>~l|Ka=&oP(1@0iCvfZrd&?GfA_!|e&&p2F=J+@8bj1>9c3?G@Z!JLa=* z91GaDj)m+y$09b3S;Tf>7PDQMC2Ts}x-m=H?#wbagIUh@U{;Ps1JCNDP4q`U3gPG0j5M~QIl-bG-W45uw8K@MP9qdSE zCp(JS#g1lnvtyV&>{w6PN?+MCKqni8;hhW>&bSFj=mt%u3fZW|eC? zv)VO-S>u|?taZ&|*12Xg>s@o04X(M&M%O%MlWRV+*|mV#;#$aTbuD7HxfV0qT}zl9 zuBFUQ*D_|8YdN#qwSw8>%3}7qRxP=A>&YbIP@iIqllcoN?`7&boFo=Uls(^RC^@1=k+tqH8a6$+eHU z?Ap&nL-}b&R>~I?mj2onY>|PBQmgrC;w-4B>)GTBk?p6qCMFLsQ(H#^qdhaKnc%T8hY!L2_#-aUYw;2y|MbPr-Dxd*e8 z-9y+Z?xE~d_b_&vdpJAYJ%XL#9?8yhk78%JN3*ltW7s+FvFu#;ICh?UJUib#fnDI9 z$S!nGVi&n5vy0tR*d^|%>{9nMcA0xRyWBm4UE!X|X1QmvE8Vl%Rqi?LYWG}rje8!u z);*tH=U%|BcQ0f&xEHY--HX{x?j`JI_fmF?dl|dcy`0_VUcqj6XR$lnE7_gyRqQVJ zYIe7K4ZFv^mfh=K$L@2lXZO1|um{{5*@Ny)>>>AN_ON>kd&Iq!J?h@Z9&>MJkGprU zC)_*PlkQ#YDfe#nw0jTS_OfT(``EMY{p>mS0rtH6AbY`mh`s1O%wBRIVK2LnvRB;4 z*sJd2>^1iZ_PYBdd&7N-z3D#9-g2K|Z@bU3ciiXLyYBPsJ@*CnzWXBkz)_t>}Y`|LaS12#>3 z$aWDQv0cT-Y`XY_?Iu2DyNl1*4DmVJLwvzziZ9uo;w!e7_?qo4zG3@_Z`r=$JGP&g z#`PDwa0A4y+(0p%8zgq)28-RfAz}tMRP4bG6EnHtVoz>_*ozw}_U1;3eYnwLUv7-p zj~grY=f;TxxbfmZZh|<7nLCMia3m$Dh}tSi6gk_;z(|WIEtGoj^<{G zW4M#-Snd=%j+-rx=jMnLxasUfxJ}~bij%o{;uLPaIF(xEu(*pmBJSpnihHLGHA8h&v-5 z=FW;oxO3uB?!0&mZpXO`;tB4ecoJ@>xJ%+`?y`7>yCRG zpPL=}fSVKgkeeI&h?^Jsn42H^gj*2$lv^13j9V1?oLe0Ff?E>$l3N=3idz=?nwuT; zhU;JTEw?}Z9d{r;jbG&G!Y_7o<(D|p`ODsJ{1tC^{;D^FU+d_>pQ@F~pRU!Dzvk`5 zU-$OrZ+QFg_iFa#d)MyA_o>~Ve`+7V&vXprFR+97i|klwh-&|`fzophVz9%=H@5N2vdvg={qw$mYWAT&uYw=U~ z>+w_ho8D>sE$?*xws!`9$2*h1>z&2l^Umh)d*|@Igt>fgVII7Dna`h%U%)@`F61x7 zFXAu8FXkV5m+%X{OZi3KW&C3Aa{iHb1^?Ka#Xs?`dUx<=qIU9Uqjo{N8`?em zJMUgTEny#jm)+0bV-N86*@JwSh(mnWh{OD*sz>-P2}k*^3CH-y>~a25{0aVY{7F7N z;S_&9{4{?d{0x6F{4C!s;T+#R;XJ>ExxjB_F7nswU*d1nzszSOT;bobSNTEgHGT|x zoj(+PgFhU7lh0~!i|^sM&1X99@I4)O`5p=P_{@a+{3Xu={;KC8f6eoVzwUX=ABld# zAB}#>FOPo4AB%p@ACG>)uZn)j_e^-j_eyxppNM|LpNxLXpNf9RpN>uw`r5h(x5ci) zeKB2l;_fCa3hFK_4$2Ug1oaS(e4QyQ4eBW@3+g3oWqZS|kMPFbSJ)=@6OP&Y3;k>Z zg#NaH!T{SKVW4fWFvvDUfOqr49osNrmpEM588kxJ6*LlVql6*0(ZW#M7-4tNSYc1l zIAL$lcwt}A1h`EU=C~&b!)%ji~Zo3u<2i=Q>k+vnmaCWJ%&%R7J8@(Jntq>N8S;APy zN@1&Qm2lI&TIeIL5th5x3J;id!ZLBaa6D*(a3W|U+%^eo+0DWeW{Yq#Xsd84XdB$N z3x~xW!s(!$!kM65aN8}sf-57h?R(+2PsoVgFN|gn2%~KWg;nlD!rbV?!Wi2TVLW>j zo@gg5rHa62b#EPGzKV!I%$b6*seeSb+9Z@Uby zUlHEgufpw`Fwu5hm}I*l3=nS$lWn(z*O9k{o$forPS;(Ce@|HY{e9tV&;#LI&_lRA z67DdMg>AMc!W7$6VXEz!FwOQHyu5(hOX0o?-fg>H3%9?1BfNCI70yM!6RrlOIj;qE zfm>JSbX&T!i@Te1io3h>kUhgW!`8#OC^XY~#MaY!!`92$+tb@Q)7Hm%-PPCm3a%Kv zv-gMF0O$GWfzH{sLC#+6VCTZJL!1vBL!EPM!Bc1bXqnu}4qn*n_ z$2hOL$2#}A$2mvY#yhvVCOD6{COU_+lbqwl$<8IVDb69~r#k1`ra5~?Pj~i?p5e@3 zXF6B1vz!ZTvz-^C=Qz8vbDcxn^PDf-^PRic1YNb0 z%(+rr?tE=q;ap_Pa-MLlbj}N1rA4O(kJXRY(PxXyXe{ki3nw0Op1DO^SRV5L-I z{PGTg)_3pVdX=S0g131}si2?%7E7A)OsV*e-j*qyyl{aIu4e#fVhIy<_ z{??1hagu+NF>px|FxC6W4}9)q3|t$Oe)7RBk97!KAJzUy9`cv|wrsg_w(OrW;fxlB;dci(*nZMoo(??NPev-}pzyLVPgd`8#t4da5}E-pCr#OxY#Mju_~ z;OlJM5fxzhs9-*e^xD+O01JE?Bmej&TzW!Ew_D%C{2wZbAW4^S>42G~!&R|-Sj9K- z67E;dViBbg@cBU;Nxt-wl=>;UAwnD(013D8Ppf4v4Mzq+!aar|Xg5`B5aW@7kZ{r; zoVP41O{44|2?q%krTLoJ#@o^3fQ!YoI<{-ov3XltG(3}Rb9N5??(4=i5?gj`m)tHP z#im>~w$({VjZbXXxNK0Fkj4@1+O|ziN=*5!@lO$r>$YpxCb@BqI`C_ma;3^vC{;G3 zOqrm@EfSL&S8JD?Qa|`R`2usxvZdnNv~k!z0W)ICZ|%MDiES)m!vFon>UPRi>BcQP z{?6D#i>pY3M zHGF44(Y=-Z?m&ygc5>`HCu*K5Ud~p1Qi)A}SZ1#IyXcZCe#dUpx_NSIIeO`C7dwq@ zydtd9f~AKBFP}K0=wkn)!$hDb#)XXOB5m8-98_U+;g4UTo>NfV6#8kfV2- zKKjU&Z9zd@w$jch{ zR#5uv)Kc_R@qe8`+P?pxH7e-XiLQSa?6hym=~HtA$&$lC2-6Sod`f_|I-bkkpif zU`>==Qk28LK$OQl^ijT)qFDcvWsH&}eG^u(k`JuxmVy*bf*@sj!f%}dz)Z2B-vx~M z&U&a);LA#Z;A(fQbziKtRxRsKwX7X#1$3^J=bu^u;i=Z@sR1og16rj9PD!;!cCt3; z6tJ)J`+<#uEwQztYSyV!Judl|xMZ*N-4^&<8G?JDHrfMv1uXsHL*Y0nNfqJ}I(oec z(g|outEp6O1uTQIU&gFIbV z&fq8TLKPgV>eb@n+cj^~#?m#PG*2yQGePP!j8;N$k<(4dZx{ejATr!FMCpfVu~Sk@`awqDJcpQ38l39F7X9~W=3 zSDDn_BzaHv#w-19r{?53PD44kZ^Ao}+|1HAO-zoH2F)vd-%AyuybaSxCbv#Z$le#f0l8;V26x9=qJF9sS0fTu?C)N*Qw(A} zm+j1ols7dcDRFhf!mCF?^2iD*0AKCNp3JbZ{1jCkb`Svku9{p^McqrRfV0$$9PxO&`)Ge$*0o^vS+tSwS?D)k;6=epklW$C4H0 z%_TPczflp=?$S}+U9y59zIJSVhcHtOzEcT~0oti^)`FD*Io$Ek?WuCd#w+_1TyINk z?^9hYQ%!V|>LMS5zH_mc8l_)j6;wOwr`R8&B7Kw4TSYyKP*GvktH##$jnqfQyfDwH z&ob((Lboa14v&qk9u)@15gZ9HSDTVuC8}mbTtqBP*P2pJ`>Uia>V%38HjYGLWh7v! z0OeaX1HG$)ZQK)lT@O^FzSQ;1XUiR=V%n1B5uez~3)PamN=B$Jc8qA#I<7`kjkx&K zwr$~BL)vKdl{-!3({3TMN$8iK_jtlz~wS zXz(4U=Af;C?&D|@arC36cS)&jv1`)NIa&6RR9~H&*>$e(B%Y#Lx!gfo@$h!3PFQqQ zcvw|%b6a&28?3HY2<9^frmAE(yS0nSXCIxWf*va)E-hIIj>Dafg^n?DV1rK5HY@cV zx9lWs4sTP zUV60~)RLARmN_l)B|PRytx>=-#4xLTIyhGiUQn3=&D*qU*HKwKxDC`K0ctqob^R?A-!YqmZH@?@r)e6|jV1X%2-*QoDHRATTTV7s*mLJftjwGXN`)1?<)JOT#cC-6`uON5lO*toXvuBKf}Jco({d$BZ%Ei{u@(@UvtUm{D-!3l_) zTl@E9g#s2v=^PZQG0_d;YK7Gfs{sbOt8*6$a{biAb+}aR!bYF-G^|cF;QvZGFj8Z$ zeY^J91F2qICcCSoD@JezEmz}rfNc;i=0SR;%@D%BR>Bvsq?oTyw75bIu?2UT{woAh3H zgM>M)Ss)#~@TS%apRK8HL5BfuqlBxgiPfojo78L&eD-76BwO8XmSCS1yIJvH!14tG zHOG$c#<)ert`GOQIsi#Hr;htRlWN#UY^xgJ2b}rx){CP=D!l@h-y5p)JFG5TVhOKT zH_CTfY*PdMYJ&6GrMIiNqQ>_FKE80rFCecv=+Q&9D66HG$E-SD|u7+8uQx`6~fDQ7AUjfTjr6Rz60y*&- zf6bHPy-Aw)i1_yGk?iBUa_T$rkCY9DRDhsmQ}>p?Omm8BcaNIWWAYA3F1kp6=Amr# zWRoml=}1nI$e60|UI7%ae!7Tnsnoa8I0N>o(Hlp}Mchwe)$2*?>`!$-RwZ9=%VU~V7Y~0k0_U#pn%gg}xqbL1x&>_ea0OET zR{DTE=65>4?9~&$CAEKlSePh%yyhctn zcrFj=VQbB7g*{(efCNFdj!1p{GW*h&bXnMNZR@Dq#T}+A9lak@?JbFwj#s#1SuOht z7+wqgpYJhGE=1xve}ed)BEKhX9-qCq%E2qAWEWY=WC)L`ORf(-WO(HT7@|Ho@!YnjHWypNhKoBJKv4*jN02xn!-J%VN|64jqqPS zbs=VpjC9~m%_Q`FgZmeFJu7>yPga$DQ85yHlHI6)<*R1up6OdP_?E@zRG*i~#oNT> z6qaET=0f zeT_1LF=6G68;dst60BCG>U8z-fN${+HtH;Wf{@ZNRekG-*C4+~3(_SX9|u=e2XW>q zI9aZ#z)SKPSC$s^@<;Xg3}uGEQ{=Kv0ZRw7ddx@sy2|}rKM*K;LxpU_LcynG^Eq>G zsz8VNeDsmMr9zjPTs!f>-Bxgcd5xugYI5^dv;zN*Jhv8`FJGVVcU2pi+G__sow`RH z+|{no)V6VnDc-ipn#-5>W!aCF^HrM9FcMkH6bu~toh1UUl>1)e79jKk#i>aad_0hW z4~&%GJ;H_<_iH=&ht1U0R2t$ul;bQg@3Bv)M{1AD;7RN=j~}bA?!+rn1reC1vic6B zCH!G(N9`$`A3(3=L7a=lVD=|;(x05mRb&l(5t8g<6EAGPHoq|E)9p9JPPK50^hURR zD!gNnKZ8=Q`d9(*Rtev!3)0uMlBP(QNGTso8HJD}l#%GOeU`FY&QyDMtEn z({xkEJ;$ox0uO3d9l7A87H5M%uq%AItbnD3+0N-Bt8OFV%CQEEw?$$KtX=ZSj0gIb zE(iJqw>bTKA+#1qthG?Cm?y#|^CUd~+z_d|9BHL8F=Hd@Mwyi;zHb_%6XDAxzV8}Y zh>`(O0-I`*?Ry-51by!z3vFy5AA9&A1dP>g_1IgXn23TQgbR;#qok?<7f2u9&%?2M z@2ey963;9BC(a)z5cmS41-=^rUyiioE8Hk8O&;0*Uw5%zr3HR!v&7oc-dbY6E!3na z4DA>1=i$;8NRIxqp{S*BY{2Z`SZmsFcw7hm<5veqiz|bx#}}%L{4E zS{a;~o@sMurgybj>Ph$2!=x8IYl1Cx1L|78hBmfn)w-6t@J+IJ?{cBM36wVki|dGZ z-QYEu>FEV6X$2(p4Z$E*4{llO3_ifq{eqS-`QEdc*n!qRJ3GM6HsYnJdyryfuJeD-O)Y}7)@6pn@L;qpi``D`gAdmN9e-)2|;!&bF##iwuMe&5ciswM_ zOt5&0i2kn5Fjng48JuCK4EmZGcAlghTK`gh4eVSA7B3My|EP8Z$<7rpalar4_mk7! z&z5y5XIs~aEol9-bsucq4Hj<`Tm8r;@U`UXuEEu9gDYiQctGqx>z|$HVCQMD_?Xxk z>}%(#!OmlfofpIowEo$73wB-;FC*0vb4j^*ZIISXn|H(kwEj5=42c#4LX@3hn8ras zh<>SR9OMmAc4}z-b5IZ*MPjF?ubt8cJ0itSSz-rT|Ljx%JLQR&>AuHPd4sYtpM(8XtOSZ4qBx86UM{^n zplDWlRVICf*1x`nf%5l6d5SborCO)5G*7=bNW)yru64qR18Dto@B=uA2@$J?h*88x zlIkNu@)4umR+iebs=_ndq>X01ywR+;Wku!ewL0+%t$$wYf!8`A;*Z4WL@+9qf@%Mi zjMf2Ln&L3)N5gyp)1#zvQM&j1L~KEuD_bMf%Dpw%N+6yzm3smh*dtYNy2?F~C`0R? zayw9N8zTNf#I==sTin-vG57#ao8`J0?mg{^9ccZtlL~f{i5G3`D|h zm3vo;Vt0QPdxK)n5U~dl)mH93afbCU=xb(JAChut{Y&{^urn}3>`&}yEBAq5VzZQX ztlazOY-s&POH;XzGPoLHaHSmRV~HJT{j)O#>`V#~ClEWD%6*c- z&IF2`sl*Pn{@IxYc4iPS+RA-~L0U6yW)la{`sZK)IG9HqXe;-5IXhTL96;-zgB9Rl zS%|oVn9x-2%V2ZdFKv!kxi2xeQYxJ+e{F088|y>FwISka;zU!qug3+w7942T(rSYz zW!7#YDT3C&6zv9YJ43|nA>vlzOcDEYLX(rMh;t^W^JRSj$heE^y#Gs~f zKVH#TL0{v0XwHc#1q7hrgA@JuycZ9=Pa=Ut$%hdft?G)i>7kFU{F@( z^JRY(uY=-MqNu6duY#gk>2-tj6z{*X;NVG! z_$WktKzwK`_b1wI1uFMP@XP^eqruAkLC#*E6R*(v=hf>S z%oi}dSFYUQ-V@+auBSkoD_i5$%Kc-o^^wQqn)^qd%=E)jDWR*}KOxG{`ltK_D1Yt| zKPBSY%KdYXdI9BAqYwGoyr(2F0Oh ze+~o>t!B>_a}qIV{S$LTcfTRs)zs|YK&DShBd)92MSm5`fMRK)sHxdYQxwbks~8N5 z-+9DxL{wX|e}{9coIxKxM}g0MJRv06(E69`DqtkkBUU0twAFej$fs+rvsa=S3L}P~ z_0LcY7^>I9x;)4&{XAZamoGy4zz0~(cnobG24^mK2p!LsPS8$i+5&tIEH1&9z!P(zNKk|Z3 zCw8Fq&rUC}lj#vNh#gHmo@ua?L9x@D*n!qRI|IN@KjKAGkM}buD>HeZzluXaaWGNT z)Z>Fe(X5~vM*0e^e|;SV$|H!fwjLj0kcLw}yR;Zh96;-zgDK!(l1H525yuf9+IoDF zx|KjBJ^_9|Ep01s^?Y2;{-zRt(E8_Z9{8K%5oZx|+8TV0zSzr}WtbyS3Z9T_aJcu( zC$^ydx3(hTdoNAp@4RGGj2639G^xM4Rm@C3XHtLnsHjx_(B@vXFR1peDE1`6+SU zBtp>UUT7?Ib2RCurrsV6*}Y&=Z;$gwZ4#(WAZnUgdjdsmvOj7wL2Y_PaVini*4fi> z9!)i9lRA4ANiejzPw+x8F~6cXmzdDj*z-YJTQAI|nOQ{4K%09rE5Xc)isCY2MpIv} zFnC#J^dcX}tB4h7b8lrMSXp0DTuZEIYU}j|D{CoMHW4e(=HAM7u(Fl-(AL#kjk3xX zvxDeDn|s~8pu3ysYHRAgK>o=7mtcN=hLF zZSMP608~F9s@j_Q1A{Eo%-N+uL81gB>Yd;5fVgEsfxz5;J0D~TnDF>S3}63l1{w5$?fNn6Z7t$bdtmEqoFBbK23x0d!+ zhVO{Kwvg|Lmkf;-ON5%#%OyfH)32J;%U^~n(*#=olvz-Ago-vIuC19Jp=!-+Gx&gc zb6u`o;oid$JJ9-P=Nqu&Bwn=Dvokca+g*M2d{1@&_Z}B<0Ih!xN{7-a=xnhdA_lF0 zV&$N_Wl486RdiX%_dSy;y1c)NA)r`+C~7L{3KT_;zlv2rF*H=HL`1dKbSTcSN(Oz+ z3=1PEht|K8R|7lIp<*Plqpho>!Nheb?f6ZT$eeA(5L?jtXX{6>6&otnAht9WcC5iw z4TCGCqNz>nK5W!7rg=A~B(_D7o>hM%t(8=IHyOuf_JSnrbGf5G&{-vl3c>5<*{3}%agLu={;{O;d z{e^b_FqqR!q^`sxwElVQ1s*d)#SCIlQ_F?Eok3t{K&aS{*wIwx z0}OWhQS1yRcA)jo&IqtGjCj#h=fe!j%6uN_ui{ux98DB875ZpUG%LNvk-kFfUtcGI z@&ux+t*mmiaf18DtoFb5pW3KeIBiqnV>ZKXa-yRAUIJ_DY4Ds43QO_OOk zd!0+XLhGN`W#Dy5sJMt2)mH9H^u=Ko{2x?w1r(URD_8Dt?^#Z4LHloQEvW*P`xdow z|0pb4ED|Ob3R8;romJqw{?Fm7>wimMT`vOPNKdze@GJS-(XVV-h2WVC>6w@EGcV=8 zbj-9%f9VMKo?>B2Sr4s$wmt`2pAt`dswjVaI6$)WsjLLk2~5HtA3j(A_^^b(igr-^ zDoiX%L=Q@dkp9?ou%!AGs1C7%UV6c-k_HFhW{8{uxc4|n3ZV5b1z&?9Axz|mp<}9{ z;gTT%Or%MM;LiZLoDF?L3_AI4TK|+QfwG4v-v#Axhb3*Cr0mfukG8|#M8k`o%0wAj|CA#@ zIV?>4o`_q*l(jKY5)T9M>u@mw?y|mz-zURDO&@KS)(IF<&YMVo4g41jR0|WMiGjSn z2CDfOh^83$!CwPEf`QmDu?8{litG+@24Z~-)Swus?XQ8Kz(8H1{=j$e>w;pYlyhZo z!omNU3_i5}4So|)ZWJaqAmUF+*QZH?-$9$bFwB(>hUwCLgZr#z6dMV-w6RY;vO0l{lrXV9v7tS(QozR|$p;=;?ctfF(lfqC z)^d5jhI`MiWN@I()!?A5zrfZX#FOU8`U4WNJbPN;c>L|JVmDCi8YZR@QSFh{6;#)d zBP-3|04C`gIR$X<=}uArt$!)#1BQBqiJ8QZ_Q>i5CgzhPD>G+9eTgAx{WCNK3=Iks z2M|NrBWsY4p#eD?8cGa7>z|=fU}yw!qdBrh7z`*!)@Y&(t$)hnL3u1u)*M-5waU0_ zO(4q9`lmb%l&6G=lZd$H$eIG;>X9`GeqSf86Wx(D-CqN9!NBY=aV9aKIkIN^7??>h zFwb8DOTfUQFmVAfpgFP@`50J0F|gEM16g2TIZ@XfS<6AuXK%v6Ur7cZTK@)rJt(gY z6IT;)&5^YhkF3>N8@NSo@K=62$Zri3HxYTwk+l^LhKgJMAN*MJKQd`;9fN7mP%=riwe@ZDtaq4jU@%Yt%HxLAsaYmTg-aP?hQ zDXk4WvcC0K-UIT%;bM6ruQ{@U!{J;1(!qd7R(XnzivQlmxA65>M*jNiKCrNd=xhGr zh&`ZoR+{g+KR??~au4ml&3(4&QBXY`E*>Pp+K=)NhpQjuA2fIXKj-C>0q#A=h!tpa zZ{;*tIZ1qIKgK@^BXCt3fq_2%V8k_99qv76h&r^nSHBQW`v^Z<=pqqs{6?owBdU0)0{26B9@@dy`?-6(V{g%d`B#4 zKCZV$=pDT?I8sjfzzC(rfHwD53V@XlBE)O=H5yX zuu_=#(0)u`*dVK!CPj%lw7FL=4(cBhb?ry=ALp$8DN%w%}4V>gn9&UpsrmrjKPmGExsYCfj0N4 z`4)VYi4aRih$8W&{aC(?!A@zkDjJMwCQdox58B-Os|5Z$5n?bgr};?UWAGMiaHOQF zGO+?}?yW?EmGB6$3bCU3I6mB9r3%GL6tMzr?ydY6tW+aDG#|xRGpH(a_XmH}VnMA2 zQPX@3Ujx+4N~T(*kI?46k99${Hc{1n1Yg@A3-d0!e5gm%q0PN|Q&4XlAvTN<>k|*! zkKY?>w+;CCy&*hvSK3JMZ zRN_hZonBhG(8h&-h*tdLdVxaPRqt zSb{e9mb!zbbmB*IF(@7K@dCv47lShVQR@S0y&}X+BB;F()C&~fkqbeY26b@qPVPF~ zd-{^DL!0}q4*@fSBE$j2jP@eXATaQNTm%}Bvzej9479m7GX~6ziV#N-GujJ4qkPPa z$l1(TVg}mWo0$Y=CJ-l@i$4<#;>sy9nW#dWd)4WnI+dtuF8oZ@s^WY98AKJ@+^fz5 z)j1L3EF!GA=rad|)r&r};P);Ln1#BFKJ)z%Ukc)jBgBP7Tyw!^v5)vdiuf{r#8-p( z$_Q}<5!YPoS?MFbf+D`gAMp(!zK$qsF7&JeHJ^P42YVwKY-n>o*xNyMYlOI&2x~6# zY>iMa@@&>xz>7RP{E^-d(t9JsT|`=QfoCsl^xa@?WnbXgMX_+;-&?pF5o_%%A3txv z!YiV$xxn)Z)OtvBTX%uyEy+2w|2F5@s)3R4?^H*MmPqBDp7sJyK%`pTTO#!yz)w$y z^c^#}_vDRK-gH8ndn@_D%KOBJ_5#oQk(u54OC#WWfoFiM4)>k{L>=1Ps~3)>UEs+U z`j7}gn|q;R(9NQxo0oF5DSkl& zwHJ84#M$(PL0dDM>?F<5=043%u);@*EU}`!z{7)qo>Hpu0uP(BrLT!4Xmf9=3|J~1 zDT>6B<^oS?gCo)4NIA{R5-ZT=-bx5qsSqiaCss5Ucq$mIl&4tn5G&B;-pco2r84oM zy}(o1Agh@sRfsyYxmS+@^$4P_y}%QZvwAd9hc@@>H9-A`NHK;O&|Kj80XDtC(x!(O zcw!8WlsCyW{ju;fSg02%)`=8fno9hU!OjDUou|YOwEo$71$JH#FWPGSg+W>~ zZC(=x(E8`V8U_ED3UQ#V$lvAcARtP)2m!5s4n6<}`J%+UQOY$DO;w&RDzn=xX>-J? zJa3fw29n=j8y|sb!)((r0M5xWSxeB7I3bLhGML9z3#9qJtRJROqb1pTpovNtrl#kmnyv@y@ihS-bFzW=^g1E z{=bnG@QE9@tlaztlS{xfif z*HwoS4)5HD17eOg?aa9k%^zzdVIexhnh31%b=9$i#X0x!0@YZ7%6OnpA{<0#I5U9r zOI>v;;c(9V7XfFg1ZO7UAUeaD2b?*?!aMglf;6{m<`V&;GlIn+$RPsWx##3hu!IN@ zoe``8!OFVoa)RKT`$`;+E40IrIrrrPmEm+&JH^-nj7@db4RzIZM8Y}uO>9GN00F<3 z)(K3;s@+Ocgy?LF_JVCsU3FJobqBHW&V7%7w2R^H5a76l^gA&kI%7Np#)Ea$KM9a? z?gs_FKLsjd%Kj!CL}xfBfpfgBdX#WD=YCwkIV!<9ML3AgaLxngEU|FT{j8vDtmg|( z6)!{aA}Mmt{UQ{ttk)G9E26Wp-hlEoQs$leH9;C{G1q?FBmzWd1QGS>sjhnJy}Ifh z;^3XTs~&f(z`5VUL9<#rXqa=qlRs-@J>!E5L}#qUz*-c4iGti2@7#+5lrx7pMe3Oi z6rh*r&K<9z;)I203u{5xxjzrA=ZJ}O?#}^Won|FW&OM5h5uGXfq3pvCBPDU(x%=vc zKS1#c9AH|n`)0g`0)&I;3?~{m<%xxN?&WcFwrXo8uXEp~6W}$Z5&@z!f|u%%d}{a~ zZZ2KIk>Df|4x%%hmcU6N z7T&q12-4iLd6x(foe{hbf^;I_oqKxz1RoFqqBDYzLGT~^Fj9ixocn)pIPTOAN9No= z5~vKP)6OYICNMt74}7bN`%e=ubhw@1;)!CS%opK~se2Y>K*otrLD2DgGgG zV&k2ACjseOhWoVu$1S9;#E9sOu_qXN;PV;+}TcIwP14f@%0+r1%HLiGz3U)A(Zr&V355{H7f=%(+j>pLGVY zB06JT2-f-dVWb4gJNNl!bC@$%STBIysylbQhH?lC(H2%t*tu^4)&^qYocjg<{GnM1 zlXKrp%81UCcS3nP{>lc4^Ui%cJJ+@f9AMg~`)0g`b`cJuGo0Un^Bb}7&iyysoI~20 z$?M$z)(P+$`hy4%oe>-edpg0n=ZYO9F+^u#hcVnkG+fTPAHsb9t=)H%b3fu#@dOl) zks{~Zk4Y3yI#oOm#k2L)(*@;hp;xKNTL}xgKW9q2|W7NnPiyur- zFvdJdk+{OIRs*L9;UGH0DGr%Hf^+Uq#bkFqsvVBZxj!LL8BXU}rx;~`p~R@381;D~;heh?6aKKr0|I_8 zJufgB%fwGpgy?LFUId#OqXuKta>T|vcU3?NGTd?k9Ji1v5F?^9#>!xPHAa1f06FLW zs=)V(KxIr>6~aMuhVuq+UXM|$5f10vUl(wyNpNZs4x%%hdcdheESz(%BPbi|ImW4C z11QFlBIn#=p=f2j8q!!1osG2-l;0v{-nqXeNMkML+K{Rg=C{86s&bd#OC{A~(I2VeuW7L@>$~*VjY=zAf^tlx_ zkER^a*_1B<&Y~D~A>r`OeGwqean5~V{#Z*13(*s6A*is)>tk3+c>Df7;~lpu|@ zm}@_tAOb{Z1W_O;U0;2+zWOwA@Xoz-eePI+bAJ|B`f3LabM8;)&*~voL}#q!!CJPy z>L*a%xt9eNXAX1x!g>Mp_nKYQUPD2`LbQeTLVU>oaw~EJNN0hIYYHIllL?C zVY+k2YiJe`AUY$MS6}AbbH(P97@{+=MHucv8ZPJD7h=ALY4_dqnfqd=ip!z6loUDV zzEq;P!l~j~D6X!r{z{^}b6?F?*sp>Z#-+_E`N1c=TE&Vb+)5%A9aRQ?2Ki2%_V!DSF!tgl`m2+p}*#Nqg} zb~rNUenFrzoX!=e7F|$~*Uhv1X*m*zgn1jo;%>Ty7y1i8Z__qBF)4V0wPZ18HGn~@Ed6rl>=l-mqY^>+!ohm9&^pGOw z+&xgVvR*zKE26WpmW8sPlzHdw7o@QkbL~etB0zLTP!R+bV$~O7)o9}2oqL5??pT3y ze*ssCQ#nFhk(VI!<@>(dI9uM-MQm6RGqL8|5vQj z`00(Y`cH5CygB~XU~}W3;avNt&9l3V*W8=QwP!Rp4iQBAs^38MtLEw#B+NVZubPL? zvo8b&@J!VGGG0U95(=Vyl&(POOdPyh@7x^!45hYC^1Aiux;kD%-AEnLzWVpgWllX; zs0Rrl+864LVfLh9axT3m=6JexpG_|PM<;6iq1KnwIEUU>qBg*Z+EAzsZmtd@LEfDY zW~*tCpv|qOVKmK%_NRFaP)0RZe(nU4a%L~W|s--h`)f26U5glHdWDv%~OS0@q@ z=gKDwL=y!f<6%9GP!R2-%mK=*=IRVW;T-ua0cC~+WiFv0+DFL&$^zox-S`4QmRlx^ zNFC9>`f{i*C3W73FU?J9HO8*rweAb$-um5_pUix|5~`(f-uz2iG6X)xFKtJ;cSk?>_{by$p4a z0LCqxKZy^~KHpLB9d523A~?=@9~RgS2}H(J9U~M(`zU9Da=N*Cl2AC;eOf>{DM2|$ zD2Vn^E&=5q;@}+jKZ2^Ub}u_oyAHLhq{g}Jt5CDDOgCtZi1x>L2dcM7m3P{=1X--R zT>EgB)Di8g7s7vbR3KiBh*w?lhFRoYc7b^A*nrE9z?FI0LBd?NE8aXk9B1Kp`jeA* z2b?9q`B1!Cj39Z3{Sc5iLzhzwNWA$0@GrW<#%t&iLPE4Nbq#cftpLeGJe9UwJ}SDO$L=dhazL`?)DWKE$KZ1H|Qs*6Z>-^Q*kUFA$^-rMQK3@Hp062%; z9*5p)?a*Tm`(uH~a48*~AbbskFXPqBc=dCl;2idsY|~~!o!>K`3p~aO{f4Fn(f-tY z2d-}MYL|Gm6LIklyPJU1g`sv5z_^8zO?-&<`TBsbcf8t@;5difTVU%c5E)a|mrxMx zqYMVhpm=ovp>Pg+kbp8kf-;0q5bdM<43y!-!8z>Vf~v80M>Gi#5)0G=(n$Hi-CAE6-HNBIjV2Z)1r z*avV!c4=!QufyK0tK&6vh}047s~?p*>|CK^B!p;R=oE%|f`-XC>=T&d-P(ONIqcI; z)XqcgEU9r0`>aImf)ll?P`ezjUL--@VP9se>7t;`t)^=<&4~7=`7Tgy$E!C9g?HGu z0kB1zYUZ$S=8trbkPz)76-vOz4+&~Sg7Mh{=dcSTn292AgWKE$y-<%zP)id4=dhy^vb*lp4n5|uOAADXOHrI4L<6CGf?75~^%Di>u*)ZeKV&Hj zb$-wI1s-FCsx&o-_NV4maJ`bCR!mSU5Et*TUlDLBGSmtJ7`JdWRvgHRCdqr?EEZh~5yP&kKOS3s#PL8(tDi1tz51WE(q;2d@XLDg8h zZ#hx>H`E%D8t1SZLCwlCHK8#g+8^UPP;Ex4yu)rL$YR~)+K1+(j%Z)KCDcNkTwOfMPg@k#B-Hn}DT?7X3 z9MU~5UPIZ0f@mM57f^m64&Gt^fE#jLTO)ZL_6c1buc6+gj%Z)KUxMs2>|CM#B!p;R z=qC(wAPtjq*aI=gC$#%)a@d2Ns11kOP*UR@_E3r12q$V|p*A`}9Z7<`!ye66(?~&^ zTTSC=ni1_!^HiWrPEaQj3h%Hd1K^N0)y!c}%pYkQAtBmFnhT`a3F=Hj;vDvDfoP^c zWIUAT5elMxlqEn}l%Oso6wYBU5>OUOP?i!3qJ5NKfwF=)c!#}0kmZ)iDpE(Zuf87Y zYe}7V*lY7w-$3e!_SLsTeQSccnE*J4y%mSvY3v1 zLm^T}w6Fd!)Qcyo4<@P)5CiY9izjl&1|0T-xN=@QNSMQZAb-vh#EEF1^C@sXk*GdK zki5fw0!W;p%Xth)y!ip}aou6#HS{zgA=*J|sXOdffK-uqIEP&k;ukeLU~<@%NEOk( zYE`IKNmO4WVcua^Neq90@tVK@p3Az&#cQYWKE$>m|w@cCJti2_f1SYJg$J(l9xP9g8`>rQK(f!*1wAtr67TA~nuoza>#? z>_qJys5MJen~)&yu$!^f)I`wcR#S7DW<>kboC1{OL^Y96c!!+~fXmucGl!j+KT;|o zA=*d!07$J8)igrl9Cj;#C`}+T9?Go=1<^iAJD{{pRND{==djxfC~YJt?Fj|ZKFVi6 z=|~*B!|o`^a?9j%Qb)9}{uR`}Aa&khf04iX*QAbUU%e~TJ144H1i(4$&N%e$YKILgFg9Mxb47HyC#x0y7#D{2~Z#4KuCaNO{j&s-}1-20akugOebn{p*EY;IEOtOYF3tM9*q&v{upzh zx`0%9hrK|M#k$M24~s}0(Z2dBsIN>^mnW)AiGg?6EBRvs4tqJSbn@kO*h};0Tuq#a z_BpqJb5o+afgpK@y~%9oayAI-1HdOYCl+ zUn2m{VOL4Y?mAdI^q9kbO&~H{N;M}4b%9VjNv)Zr)*uSbVb^AxwkFj1JyS#AF;-|j zni@p=QxgZSHR&)TBT4-%N$p4syu;4mj}18N z&v0e9c95{ousi0@`6Y28+UM*F&dy0{7D4h3yEBkDLzj~!tPcPW&@7(z8tO(!h<1>& z4!Y>40R9B5fyBhQ?12CnsaXQk=h%Zu8PS>Y&rlwoqz)x<-f0hKXV*}H15BfJuZ!2v zNWwvMhBFR0V~B-!+hcHZCTi;?uiKua6W}#8o(K?~5ll{!eWsl&Hig6xorz7yaHr95 zIoCZ6^F2ws?QsND9$29&Uw$0D9&}NxCn|1lhpYn%DeA{Y=zAi^tlzbn5G=j z*_8hZoE1sxGQ!~<_zFOb)~1~~@MZa9ts*Q$XIPtnwINAeM_8N--yl$}6R3;__h!OD zbcVAFI6IQmZG^))@f`xrHVMvd!a;O~^9OMD5)1Ff_X^V7ve`!jh|UQ90>J?y;2rsa z{0R;b0irX46CgO2q#hv%&Xpg-;W$-09GNRWB2XF5=A=`Mi@>;$q@GJs&kzac%rCGF zeGUZtUOFQ%8LRdZO%bBADY^}|n@Q^RB=st>@$USlfOMVVUKQZDg>;7)5uGs>NUou}h)*9BH>V&a^8Z2-*Htc1zA*CS;_XUYws{I6uS zK8f?r{a?x9Pc`cc9AKKO`)0g`-Xt7EXE^@`P9tLBoqHqPoJHE2$?Mz~>jZcWH6a2- zX9Vvg%ba_zSaT9XbS9RB;U>^~$`ChEucaw8ZcBYG%oNtrWuL*~9?%xVHUrTU06Aq#?obQ0sjaYc+ z-c69^mQ6MhAUY%H1%e-lfOqac2oRkS3{WVJ6raL&Cy4##EM;mDkOUxCVS zI)j{Ij0DDrWOZ1wI)q3#=RSgM=wTq>_tFr7$yl|cXo?V>P0?hqO-xqDC#z$Ljd$)7 z1*Gu|cdP)%Eu<;Li0F)QHW+6ntJ4XPbM7+*zUcy$F=cZI2hkbMBH%1cR_7BA=iCx`$X1ov|JS z>z~Q$J_6;P`=4fWn6pn{vs?yTUd9(&ONe4J=NX9_%57t?(P=ZUDjw; z!sOfwv@pKsMs%iJ6v{a2_HS-nl>2 z0{=~{wr27=_uV=HUPF%%0irX4$6Cmod#>2yB!=ir>}d@5Ng6Ka+@HjJ@7C_S$+Z-Zz;O%d17bvU#@G&wZCj{q2#|B`Z3VtI0+lgk z?Fk3b8BPXpK5L;lD3q{un< zPEfS6UR`Odh|b2E4dw2n%scn)f;84*uKoC)2oRkS^aDYk7HaPnYER(T>B1EMYONF7pi+&sJlp*ckFxEdA3Vn0M8-aFXJ`z zJE0)jM>znL{lvk$_5HXZ$F+5m*R7w>)$tlSNa~38)elRZdalqB5<;{ubOOUXM#JP> z`Z3J$3GF_cT>42TYG4Komt)?q9&4~7= z`8H5)wotDV3h&Hs0^pD~)y$b+&mZXyAtBmFDv*LdAWuWKE$qo7_oMSYe4I2T?z1wR}?JM@?fe^wweT#LsELU|yRO;P>inMZ2|UIM4bs#g+Mk+Nz*R9tt&pO=KwP~0t|;JCV5lz$VBEr~ zM0|+$`Kp7jYKmHg;5g@9RbZx+9_&HLg8F@Z2_gG1f?FKAlgT1 z0F+qb;2d|XplYn$hECKPLG3M4=A4=4HLAv)ijEx8PWbUPXx;N6m=}2@D6)C04{4&%^ddF{E;RR5~6*inLwJJ zqD~_u&S6g%h^7fd#zT1)p&;5vSqPN*De7E8;T-mS0cEZPC5KQD?V~IM$`az>9rhAI zmRlyvNgdI?`f8~EO6t7B{xyH~HKdMcUwt#wH>RlT34n9h8*%8})eb%8u-6MjhD+Jv z1mQOz>`qa4rl{MAf^*or*{0nIb$-um7kG>nx|gN~(f-sN0@uM5_0JS_A93*x`=EgH zCqvyQfN=}wZ{kC=&vy!ZCsNd71jjk-69U^YfykJu(}aR(ALSxYE~KdE2!(Ul7X*}Z z5|m4Xf@mM*I#8|>2j{S_3aZB1z2QXd4%BXu8t1TYLCwlC-K8-i+8?7kwVryPRC$Me zUy#MR%e4;?sm5m`i1yVVg!%)iYT;D1V5;#+4eziYNac(y2^dhg~q$JUtv| zG2%qD&-oZQA5B#sAxPd~KMEwy(B(V=B;Nc0_@?f#@fv!ZkPz)4Rn;AKSs?j|hjZ9| zh8Y)eybimUu8!BxtE7%-UpJRgED*-eJeG)f6LWbE~N#O*5kXX>J0P#;Ix?q3{m7 zF#x)2Q{6kt)l7TMiOV0UDIp=+M@j-xLaN%FkT{2(AP_Ydh>VAFGNB;aM@a+9yQyj_ zp>PiST>&Lkf|5=si1txF1j+}*!8_~^1X*sGd_?Mq_SM@#y)CKp4!dps>g`D#(Y|^H z)IUpAI}!lrus_40*GD__n8WTU5E(8d(+NUnAY`Sg-=wNv5e4V4v)HEn2I~Bt`AXn1 zR%jQR8bte3(-T}hQq}BKwL5X~4!ehdlg&`O3t-&B=|y~q_W1^auYaoAm*6;u-Ctnq zD-an|HHc6U?W2qU%CJ;*2%&HedzgSSM1t}&p&;5v84Hxr#KAf2(SoY6cE>qUn*_B9 zq{cby2~e}LOp|Ghi1x?$3sk3)D(|qT3bI&tx%Oc?sUzA~UjX%asp_0mbrv!34tpMd zY`|g9!Ic5pLBc-6o|Ql6LgGZU&$$wu%Tv{*1j#$>dvs73g0Pd+-Jnc2~DZy0%v-rE+ci+qI@{?u*b!-F2Jj5gJuY5Dg$V`GK1wm56eSMcVHZuqe+R3rk-QFjlCF-|P;pX6w6Fe1 zn#^J63Y8=wMEgRIW0<9An4H5dg*l$2-Di`-e!_{`Gf;bq)HsLzltk@WCu&}(MWv~w zNsxEgQEWAp7PPt5q|h`Y+Mnj~Kq;H1`U!=1*ku7QM4M{nu>JWX1qlh!KGMrTdMQnP zk&rlt{gOcRqCjLklwTnfMEfXJfl?(+eT`5!hh0TLc};>+jZhHnqtpaS4dUP(b`3$6 zTPC$g9nrpe4AkqAI`6RS=C59#)Di8g$3gwgG_?T%a1Q%T9C}l=LytM^1_F`cQW`ly zhzG(uX=<}HwFyyh4*MOpX`4Zv-!n}F9%F?j(9|H>pPKi;)iO;@NmG-Fi+9*91)LOy znk;~E3nz{E5bg7|0pEvd>IVeJIqVMwwhsg%W2*i`D2Vn^Is&Cbn%a&~IEURqKxrpI z`IJx)?W24FlnmnF9Cn7FYOLKaov3{awXaEybJ$-)&B`)m(HIf!kFhIMJCiE!usaK~ zSa-Shp&O|q+E?!l^`2>Jk2E!#7lRq}#uzTRj4DBFc4m&%4&L4>r(LU#3a1KgS z2M{Fhum_n9UCsbueE@i(?y&J18bU~jc94v}B{CaGGl_@$40|TTXKQxATDs3h%J@17NN;)y!f4kw4NwLPE5U zbR0-W)6~O+#5wGv0?}cC$apB9AQVLVDCdE4HcdTED4fGSE1;Z~pj;pnMEfXLfO3gA zc!zySkmZ)iRZ>T^uYL>aH%Og#*f;W5zfJ0h_SGZO>#44E^&SCm4%?NU-F2mQ=rM07R%r2bkqXd9bCS6qsg>%?t1QbPrQkGB4F(TR@<7-f@M5?^Qt|Z7}-R0Vc%A}5HU%e*OYox2y)77fPz&q?3{ILOtT^(1} zXa@;%*j4lAtVNuN_Bk7XGd5j~AxPd~#{!8nbU87?`T+1!-C^T3)R2%6?I30K4gZXi zfxzldOq|Q^4}kTWB`~?{L8Of6OnEqzho-B8Nt}1uL)qCiSl|HDM&0Y;H8g^75S`(S z0nR95;obHq+?+$&ddcgy|JDic8X8Lkh|UNmrprFl&J~+PVu;SfreU~KXt=n zbae^g@D6+#AU0~#&K&rX{IOON7NRq(4ZvELuC5_0&V{cNsMZKn#)Eq!;UGH0*#Vqw z>FO53;hgw30cVQ@XD8txI>XruoIS+CyYW4OG`DPiCjvxg1P4H{p9pwIzCVA0gG7Mn zjNljuj-;!969nhVkKk}TsvVBZmH#bJ8P4XoQ;ZA1IG3)TNmox13Fpkuu?>9&1pHn) zB`_JQ_8*!eL}ycU6KvPh)vM|1Wn$yq`E>#5D#N`jz;O%d7BM0^V~l8pZ?0OY_Xv=4 z=&n}gDZ3|78B-S7%J^mm(HTxr;1p@47HVaDm&LjCA_7h!T;U%}2F`$MpWr!8g8S4vRjc%ouCs5wGM+1v9 zhdJei^#bTax^u^C=taUp{9mz7)eisdlgsV#^Bvk-{OyyA?X$a_(QJgtwO?s(>{>+o zs<)teqrG~Kgn7q)qkZ^;k!u12c+Tm58Ly$+go0=v#nqvndXG4Gw|=jEcGt_=I?3zS zujuM{4Y@lQ6M<-7yoR;q(qk_35oUaCWQHI)>!xz+RpO*5kXX)X#7p=LreXK2iWkWjd$|A#tv}j6kFaM8?yxETJIUM|lw_ zY6mq)D4Zi#1(cu!r2?TK+DEAbl$VKvcjGS$vfMIxmDCaKt5=136;kJ&c$NIstC2dQ zef8Q(Z!uh}8H>viqWV=lagKxDX!3F2pf)Bh-hDR{aGEgG#sV0(aGDbzqJ6$p@U`fmCJ`Lx zyjuutNdl2ERV@hx(LTxtKxx%MO(PV}b+-~w(j+LY2?fzUN?V|`Ar8)Qw-Hp0wfnIX zwNIedp42$E-5zRImZ>9+5z+n_Gobnzsq#+yGeH*XF4sO}k~*S&_0CYw>Y#qpLH&vt zc$b~U9~*Gl-{8t^?I2+;`>XspyAUU$ea@cX?9oBZCP?04_W%-S=yI}!^#S0^y2Hk6 zs23q2{;x>;pNMmN;@qX1xDcDT{1ZOG4}i~5S7xZoGt{LS>f#JFCqrG3q0Y-t=Va)< zEY9tXb1QLfU!2>YGbbav%j&2qn=)Klhk$=w#>?4Vx)gI&%+FC0#D$;lCxjQVbms@07`zmk~BZh6b*#j%rwC zi=kBBU%%GU&V?ggSrL!AT)KkxXOxDxo~m7|sb9k{+J=9jXuoI(kf2^;oHJ`Oz#iQ+ zvK*S116`b3^{>tF=X|mh$*!y-P{>(@fp+twb2op^O8k0MG5mT|v7F@$b1D1PV)m;X z_NxVXYSy!>>vFF)q#1fKXRY?zI-aNUR*j|t&st8u_>w=ex-kO}=A8lmHf{b^N97nI z*`1XfCeo#tHu8#wK%Sw$+%%%8yPP%)C1aYpnr7X{|Kgs{D)3~KD=sSQo-6L<;>ji5 z1qwV{B(hA_O#DHL>!Fn;T@S}aXsf4koV${C?<-^VY{u$2l%XEXQ2)$O_hqQRXQ;nr zsJk=Nof+!(@am}&=MKfWtH!yj=WNIDv3gD#_w;rDQPb+F;XlT$o;R?1PT?M*z+akM zJ;!ME9HrH>lTERqq0dRfDyI#ln*ZDC(f{~cy9aFb)XH;54r{llHdYUsmjhj#yN>^e zY4se!K*Ou&VD3H7`IBMpW54>H{pvUNtKE5OjM=yL)x$)L)e~z77^_Dg`oHwmqy5sx>WPbUH`G>799B;bR?nRb^;U*@BSXEG zpj&uJz&fUcSNTxnX zv;~{`OXlYF_BZgC;@-x&oB1Elz0${zO_hi%{zi>(p!M;)vPxn{HpCIA|5j4YEHZcl3M3HoEg6P z-YPXST{$J#dr##zAc$*m?hkcsyp3~zgz59|ss?PF*;!9o9wd5?W>^Z^i1b6fjlb}J ztrBtq^4X~ZR zXt+?nDlZJx#{B3t9Z-|I9LnK(ock01gPA!GXtSA9RC|pev5r`9|7}nYY6aYIKE(p_ zH~bXS-W#jsX<98sn)u-GKO^?95-Bgc)kG^!Y_r7CrCj|&S|?(645-keAwrzEcQ z4zEeQPpQ0DD%ZhmpnIG5HlmPgMat1``Czp@qiutr?&!e$Q_P zz(s1TFBWg*fCiA2g(oKuaW*f6zCfiA5GjW?8bnqnG-~1s1#zhyz7VxDG^;Z%BXrYb z+BY%|l;^cQt#5BU0*Cwao-K4P;d&o`!^$xjL_`v12cHEapkmYX0X5sE;wB5F`E}JOQ|b zw>|N;X`v9tTMi>?S`e3dX+s(KDjn)&wR?F(KQwhXZ{9bxYq?y}INI@Z9Pp?&P7>pu z-O^Vker-JVvwEYc@pv)nmCFC33GA=Q84pn71^{6Iu7zIF0SDrjO$(MoHm(oSa&Kf9 zjY??81up)iUA#pX^X$Qg>2Z@a7zx;S#{D$DlL)1088N zYV~Doyd9yns`Ht#Wh-dA0(EZvrsQeauu4O{_~&r3@pdHMnx`iO&dU1q7#t64b6pNs zX_Wd#^;WJz_i&V^&kx0TK$wSO9LK^e;%Ti9?oFLwW4~S?guoSLox+$kVG~l{meAe7N3tJ3*^2mg%oWEvjlQ z@|I~6UsyL5MGDe0K5G(+a*E|X(tMR0(Y#Im|Kt2y$C(nwG2Twq>iMmzuiV@{8Ge@I zQK?Nb4wHOt0qxc4=-RY!s4><6K=YD&D>otX8JhC&@FDTKw&XgO#LsiVi?L#ivdCPL z|E{ZjYslXmS&bo)XB$Qsa(S*qTHMlR`W()JjJ|h_w{wiqHpOT$xc{HNMen!u-gCpf z@wS}S5|fA{YM!Q1D1;qV4qHaw{qwa;1wz{Mw>&+T7vfSm_<9uN;Ftf~H<=#`A5mm2 z*7_Nz=n}2pt!l~xEO4v92?DVEpu=Kx|u)RYi%l>cPml%s6 zw`7G@691VomO2 z)huOYWmoI83|DtIata`)quae)R<)5;t*h*M@8kcpYuO>)m0cj*{poP`ZIq`=?Zz9I zPP4<*_nC11A1viJS;`?MeE`55?tWR#Nmg^Lva20F3eKH~c7?#?J|e5U$STiUSDuws z-ei^6tShg`D(|z(JF=95Rl+wmq6&Xw*;E!siZRn2*c)t+^`8=I=x za%#=0TbWYc3~%0cEagAq?fghq^%<-B#0u-JaQ81MPd`es@W!|wUz_^Ih4Z_yl+Lo0 zo=p0C0CPvlce0uRtfsGd4b{=-|3_Kn2v#}Nx^l3ray+XXV_i8)RymbbPLid}Vky&Q zDLF_nW_!NnqHLrOe6Fl~6;oItu8U>XBU&PBwuLp@XkEEp)L1KP_8V)q%evVPS>-`i zx!=0-4_W0=R2q}{w=CrpYku66!uHyEmU2dxa)YH@&F8LNwmeE2>v!~`taU^v{P?*q z+p})>T~jsNnUAyTM??I>t7&-iKF3m?4hc`6CuLO%tBML)oN)2s?qw-YKT1@*G44ls zQ{RMeenpn@qAaBflYSMz+)?t1tfnTbc|Bx$o<{1fq?)YqU#v35y0WgU^53j7&bsnV zS!Hup*-Vzwf~6$NQd%L!nCBQpV(S*G6fZ zPH-hj`W^jQ)_MkOJx#V}-R>!-YPK`Ks~SFtx>n_nl9ce~?afkts45&K-^;27u&TaQ zEsm1ZaQ7jUrynIh*7!A z5$%&TJHwitw5~iZY8;g{yTY1Xv~G4mR(Xe2-n6c~E~|{F7M{%evXsI|F+NNvP))Me zim{XjWGRoclt-({@7g2Ptd5fR^gH^ntaTJ?{hU^A{su?evu^h@rfRk`OTQi--ZQWB z!)q1Zyk%I5_jTbYiIPa@Sjv=q?%E`6(+RHRGyRTEkhNaGTF;g3 zS+{$(shaJ~QZ>Uz$s;vg@3m^1=To;Xx^D5Bt`E4&-Empp_s^izn7k)zy4rk@=Yz`Z zaEh08f4-(GEl*9~%6Hg+nwnDB?Q6lBCt^C= zxVlHs=j~p%J6=}QiWR+wqK{j)X_IG7{i5H$R9WrkjH#n}HO|&6+nHD6yzmr$!(_iS zbzcxp>BhQu=2yp3y?2(Zt{1E8!Pm{u>#}8a16f@^tGYh2x?!wtuqTUXAMRW4!!T3||Hw{InDz6{gJuf`>^q7AHQ zEs9L5@mKx+t&-KAVob-)t8u+vdDy%fH-)G0A0~Uw)O|}h9VY(H1q%JiSs2mXw#ygX9~)E3r78S4=#vSzQaW-nP+z9?#_ zvS!s;vygSO%CgG3tg@DMyS z`p@fkw7INxYu37zR&M_MK-;r!cbci1Ey{0M^;f9o-2D~3GNZQ1^k2tiecyLSsWEw7 zYV!|_o8gpRtb32z+=J%6-aA`XH;~o!(;#kCl}-X9~^4bQX3vt78Z)lpJjA9%sK z{KJCXiBe4Ak-EYo=Ha@g1KF6x;<9F?S+i%XE1wcIo{%*Qux38%W?ot4i>xx*y0W~i zvJxtd$*d?#39;s{nNrwZtHDyL$x>ojO1*sUTAjL9N68EN9jzs6-GsGnq?MaJvbJa4 z?zc?UY&~>j)$L6wFQHK1-(Rwn4Doh;Cadbis=l$psuu3vo$_?4AMnPwAK9k9)x-IH zSV}Kh%1=ys0Dw7H(oa@1lGO}1uc4Rq85}CBoWv@}TUU;iRnBCUzgSmJl~vAXm2+e% zOIS*dEM+xPjM-jkxhUVz2fkcZzLhC#64%8B>k+M!HT#`4+hbk1OVrpQYxXy5cF?-n zpR&qRtn#>Z{ONp!(enz%ZyLQj=D5<00 z(L1u%#aZj3^(>AOZO`KGr`O{jEo^5-vFhhcDKRM2_jiD$`05EyAFr%RWmV;^u-*!H zuSj{i)N6QS+>cjGedEIU)mTauSxRjt{RV)!qvUm2O#@a_zn2Ip=4j!u%b&S9J=avtcIIYQy}^_cAKtvXSju+sc5anb z{lTh!v%*RZcRxsZ`cZNOZ;bnK$kexGIR7L|IVMZFz@*QbkCM}}n(M6Qig^ts=<|O` zR_TffKPB#3SKgLY7GaeIV@$`Fp&1#&KLFSyJj5y=l%Syw zfj=QD_cH}0MtH<{tVi^`tXT!tOtr2IiW=o)&8o0wuUa>IMOImpRlaUrSxr_MgGysE z>&Q|XvgWa-6t>qIvy``FDTyqlc|LdT?HH@0P)viMMlrtZF2y8g7O4eYpEL%G0GL>6u!*}C$gsBuBo>^^ID$GX`qS!Ln+ z;paku`li#}SOyXG`O}@P%i^dsCbOt4r6g=g=)ymCBiMD6mZojFT&A>QTJ=&Bq0EPPgp2|`t)fb*V6J%AhSk-hZ ztfArV^C?f4T8uZw{a9$~J1m^Pf~72#rL1Gps{za%CBMpQwy~Pc<~7t#pTUi?%HLV# z9_z|ovdTlO@_=>aep%&lR(V90a+al>lBHZhiZR<4Ef?j_`oJ&9%I`6S+v2*oX+5Ir zvSvkM!+W@3tZ5G$^B);2tUY%uzpdFCd4x54$huiES>;o#@^S0RQnJeDQE5!(v$7N) zYwj_nu)S7}rTAqjFSC>iu~tWkao1jmwK_`1=yx<)*19@t9n#9pM~Sv)-R{b!YBuW` z&BM3w)8_n*8IMAJe}BtTzG^Pq&M#zD-B?xU<`!7LguC~kJYDKXyfN-aPgCFN;rszC zrLQby7?U0hVD2axB&!+AYDP6TE#-;&4E`*uoW?3ATUSn$RnBFVv#cv;$SN1H$_28N z6)a_`EM+}XjM-k(+-gzI(g(guR=$%dY!lbT7V8mhk~RC2HT%Q5a<8bdN7n2ZYj)VW z*&$iwIaYbvy7Hu~@-ixo$^1u_a)UL$YD!^y?Ji5XB}*wBAKtMA;^lWOBHrpKnWx`T zSG;7WKf+o+q?MbG5^c}A-Nj7RY-jpdwa1jQ5QX~w4ziT8@xoE!msP#Qs$Q_dS`qI4 zD&^@?Rq@8SAC*mgSBCT7U@6sQDKSjC4uH9%q?W8Ej@2}bHytI5^cnn@tg<<)Y-U~A zL{^!~DwC}%6J?dHSmk@Nlr}7-wJfD0QjFPdZ@DN}>jVE-R{jlB_)=UKnbsrvT-Gd` zHS1%33dy?OC^bp{bhf%w4Q{yD4Q;c=PUKDSO4+xkpxYh*cf1 z!rB$?evI<;qvSN+8296ZsqgM^{soqDR+e&&NnbV}B^PBi_gKws^BUTs&;LzXW#I(& zlt?fgLPljo0{;+TLwT507PGD_Dyw{qRhE>cJi}6+l%*(0F=jg|!Rq<8S08w3S-Hv- z$|neqn6lO*^2?gN#+toiU0G4os32?h25VN`x>;3OWqnpz*SfN{tnw{X8k5;TmePbZ zZ)8egd#yQ3X(mf~m!+iSbJvm+tX#={{f;KeTDM`XTWjTJSEB7%xBGolHCxV|SoJri zl!GYL_jfi+=_cOJF0!iLtm+3VtmEPC{V7kE8jLr_{TOKKdm@}af~5?VrHo_JqXEph zl995SX{=_lc?})XXKDp$x-Hn5bnvXmW2F=l(K z<)S>T4}7z%d_Pn8U0fHxS&wM9tl2Tv?67s^AyMO?tl4?i?2L7@Q?klytn#vTA`|%s5KAe+Qi>;9Jphcm_F$sbQF30tqYubhKh0V{ zp_QAD5^c}A-H(~7+0LxQsw^IBJ%;jhsfKuC z+>cmO-&^7Q#w_J6SxR#z-3-9oQPM&o%6%9*G%Ci53r$~@M5wkd_}wM8stfh=V;OIexEU0ZH> zl(_MaG`ZbNWv#ce)|+H|*6rS4s%AU$EUP|cN+|$YeScqODgTJK^SrF;Cabz;g;grt z{T}7%QjtmF`{7FB59PEaerJ@{%m28d8kaUnR-v`Szqf@YiJJ^_W6!Ota~y zGS{>oQ4LwMMy%PJ)|CxJjaXT;c-HJ~>t;=5l`UCi3+u`xS>^kvG$u1mmePhbZ*59p zd#yc7X)8UXrGtaUfmy0cbpb|u=Lb-S}n)of=DX4L~tDbJ%& z-`^uy%5d>^4wY4nXH{dYuma)kQz%cDnt?aQ{g`IzTQ;0Om!-^-r7ULB3(ZH#d|AyZ zR?ceBbJ)|K02mHSxbURlZ^mU2LrauO-VY#*~+ltF#q zM`Y!fn8F2dU7WKX(HU8@JFMAF>&ok*##LFfg2~}$Nkp>gxnSH(S2F*gVymk-t1N0= zSwvR(C@PJ~EFnvIk~M$Kl*0Dfb1da)SxSJV_>!$20LESOCR-gPFY0$RO4j-%*7^ml z+^w%cw^j; z1XJIt;rw@5N{TF{HIr@yVD1~7G+9l1R@2tJhF;NUu#K$p3s(8Lb>*kB%Fe9vTkFcN zWtG{ivYRZWH%s|JmNEz_#%%YuT$Hct1Me#N;&X-lLM5QsA%Va5QS@Tt<6t>qkv6S_)lsznEXFhjryX8?* zOTVLAWv%~Wt^btmS+{$ishaJ~0xiM^xVr^^Qr8V{-UnGqkru*HQb<TlN<)?sD@$pL6l1mEQvnhm8mt1N0=SwvR(D61?XOL>Z=JT6P|AjO#N(kWI) z$%p#DpOuvdnL^nV;SuAv9+6MhtP*Qh(YmsNsPTfV+3T!XRqJL|WR>+;Wo_%qnzG7< zs5B-sR+iG3HGj*L!uHzRETxGoC6%Ql=X2K*Q>>1Xw)!27m$m+owSHeKH-Cep?OC@w z-Bit%^Vh8U3sXva6zcoCD@*Al-p+4jRXteMcUD-L;qE_Do-Q>2Z;boV*VOlmaQ+aM zGDwy(ib;7r zQht@CY(a`K+Z!zx<=6Va*UQTHGKJmZy4YzwqV2L~f3s!>ttJ=wlVd`S?fo&a`RE5?OC_`5mPnWndMlu-;~l7h5G)kz*5vy;pr2URlUlpUbe#O z8SY+{@^q;;@W!|w)lGeSh4bsOlv=WshDhPta6xjY&*G1gP1S5?y3)eO;NAE5v+5_v>ifGeODT{h z93>HHlB(jYs%V2 zF7r{cLsoN;)$BK~p}G3}{~@b9!77hhS00vCUSO4Htt(HmB!Ky%2Hlt%`2Ev*j}s5QYy((YO$0W`P{YY=~hR{8vTw| zm9=ijTE}YT=5KJcJ?nPIn5x+=9K@>on^M-JP~YDpSjtfGb`F+Rjb&A%tgsG+yHBD# zUFsLSG496{Q{TVC`LkKd3|UGJlb#P?&XvrS)vRPS%gk$NqdtR6WR)9PnZ9aHV~C)-Sf_ zC+Q3d_5FRDrQB#QJbkXos@xsIjqkO$z`7jnUWoE^sR!}KxF1D2@HAJ#`6XCNaaqa} zOuAGD(@|1VR`WcodA5UT^_|ma@M&3PSyoxbx>Au&hmgMq^pCmaJI|>t;!^ z%GRv1m33vBtny=28k5;ZmeP?mZ*NLrdo7ctd?rij!cwyGxoh8ausTX^>v!}kS?gY` zbq}rFe3WQ=*6q$VRkNMBCgXWmq&qTVQ$}f|MMi9fnAt8p z&%X;;@KLS%$_&%L91^Afo9fFmTx~f|ur$Nfx?_3=?%HBpOXIHOWVk+Q*`{NgbiR0j zaXF8;p)xPS)vo0ypP19<7?<;;*D0Z$jqZr`8Lm&;wr)oS?g9l|9#=jLc{Z~p|qryndj<5+W8j|iK}@o8i&S1nXV5x zmExI(uc0%<9pTQzKm9{z4TCG1>1t#~c|6ngUdN0)sU>vTM>0*vk~`wzOxLHJ=z~Br zw=0$Ds@1N|OL_Vk!zi5Ts@XcvRefS{(&_&%P`qIALip1DU#NKD;)M$pa~0M9IaQbI z!48i-cKY0#ozAVk^hQpfN-srzIH7Gpm&;W8)C;|7rON9tcTw>oibfW0NvoeI@DN>21v!|~@`ZM3@47Bse9~3;v1h*X{NVZCGcz#Xv&gg1^G9HnXOCyIXS-*sXG-9P=Z@!= zXILQHJ0LL3`?Ghpcb@mGx3kjC*VDJwx7oMecf!BX_nUuknUQ6NmRTH_Q)Ygd4Q2i) zv#HF+z?L#s{oBgi^6w}!IIyeC1^-$9kAbWk7*XV-QA)=y#YPqTr`VNZSBqsub&cu~ z)jO(x)QG52QDdVfL`{mC5;Z+)X4HbHMNvzlevMikwIS+6)b*&lQQv{|2hWe5ex5;| z!JZMGQJ(Rh$)5S(UgTK?>aF13T!E*!LcRbnNTxgx8!?u@e3yLP$_&OhhGR6wNH&$(Qf6D39c6Z5OlQm7DRZyP{W6{Wo&8<>-TdGA zv;95%Klpq4d-;3&fAsh9_x1Pl5AYB4|KuO+AL1YCALbwK|Jgs%KiWUWKh8hiKhZzQ zKgB=I|BHWyf2M!7f3AO?e}R9Yf02K&f2n_&e}#Xgf0ci=f31I=e}jLkf17{1e~14! z{~!K+{{8-g{-ge5{u7wT3;v7#%l@nWTmHNLd;a_WtU%{L*Fd+xcY*A{_kkXP9|AoC zy#hZ5`Ud(11_TBNh6P3hMg~R)#stO%#s?+@rUa%1ehJJB%nK|CEDYoX76+CFRtMGu z)&|xE)(3Fs0$T&y0y_h{0=oly1Ahb#1pW#f2^E4y%IH?Hi#mEUk>FRuKKD}Uh1K3v%ku0Nr70Kan(zw;M< z=MaAHZ~X3I{N54#-ce*7L)LL*oj}$}WSv6RX=I&2)>&koL)Lj@T|m}9$hwHEOUSy6 ztSiX6imYqMx{j%6GVdbu9y0GEGs|-=s*~q>RA9~^}XkQR1Z%Uc0wmlPfu1gnt0h8@z~ z)8F%*XMiW$GZ4FGkf(>|CsYhZ#Sl*~&rnZq&oERBN5u$K{EUi`s2GKc(Wn@Mim|8| zhl=s2n1G6jp6OAOP&FAijLdRaXUKh@N|jViLYIrrJmjBya%0s!`EJP z{~g``K=*ymA>8!NGO%{Rr{-8a?yoo|{q+xLt2d*5_#58n*$55Ae+p1xV$UcTAh-o82B zAANJZeSGu0eSP!swZPlYx6s?)m*XAaTjU++TkIX=TjKr6x70h>x6C`lx7<6_x57Kj zx6(V@_p5h=Z_MO3&}XlAobPwAs8j z^(A~=#@7{mUB%Zmd|k)a4Se0i*DZYA#@8M14BuVvOy524EZ=?aY+sf#+t*2%x8lS7n~Bn=;?mU0LA!PFd*7R&spbD~o(Rl*PUulqJ5N%2Ho1Wtp$HvfTHhvclI# zS?TMm{Oaqctn&3&R{I7hYkUKhwZ1{hI^R#qdf#AWgKvnk(Kl4tK+z1|1ZU&Dlw}K~>vt>^zw}YpYJHgY+-QXGJUhu4PKX^{b ziaxJ&ioT$9j{ZmK5`9tW8V!FDeOc)qeMR{$`l^y0eNFj3`nu91`iAmD^i8E_^ev@V z^lhbg^d05L=(|dv=zB`v==(~)=qz9V=uW-?(Vcw*qr3P9MR)c66y41?IJ&!UNc4C3 z%JvP7{@yn%x`%Ig^bfuf(LH@XNB8oL^YzBpkG_%7eSD*$`}#&l_w$X3?(Z8LJ-|0E zdZ2H7^dR4a=%0KOqX+vYMGx^!jvnfp5<#RjN|s3@XK*n*IYp$Se>?evukVUGS{}y z<*x0aD_lE5SGsnFu5#@PUG3T(y2iC9bggS|=sMTF(DknUp&MMkgl=>l2;JoRHFUG< zVCWXtq0p_a!=c+;zlCnc=MLAA(4DTMp}SnahwgSA3*F;79=g|cB6OeYkI?>vZTr*O|~muCt+sUFSl7bDa-8;<^xe)O9iRch{xRW3J1g$6Z%KPq?mz z{^9y7^iS8d(37seLr=M`hn{xb2tDKaC-kiA-_Uceo1y1jw?Z$tZiilU-3h(qx*K}g zbuaXa>wf4}SC;t8)m>b3^$>r%dW!3=UgC!9EAfx3xA@ofwYcfZ7PnmAh}*6{;*RTE zao5#X+;e>=?z{SlEcf@KySu;W;T|A*x(AA0?m^-!_h8Z6{e$@0Jw#-?e-z)ihl)P# zVd7i&aM9O2LVV{QDf+obiSOM%iT>`(7j45a<3MP@wvpkM&!8Hily##;%E1IvCO?eEO&1dE8LsJO7~{5%DqLbc5fAH z+}p%j_ja+)y+f>b?-U!{yTnHKZn4R|M{IWQ6-G7MR+<%HA?vvuE z`;_?IeOerIpApC1XT=HkIq`@4y!g|7L7a476sO#m#A)|samIZ`oOMr#IOm=iao#;C z;(~i}#6|a%h)eFN5trT5BCfcnM_hH!i1^DrGvba@#*%8;>b0TiI=SKYFo)_`2 zdw#@C_kxI9?u8Mz-HRgbxbM5}x{s#cbN`-x-+e4S%QG*eyJvn#56^;-o}LL6dU+;R z_{uY>LT}IU^shZ9(z88(q<`b-71GBuB;;Gqk0E_MD?+~WeCO@w>F534^S!&jr@woE zXJ>_ho?R6Nd1h7^?3q>J2hZ#ZLpe)RMR8S3d7GR!m3JKQtKJHm6U{7BF7@}oR+ zD*WV`TVb?kUWGB91r^467FHPNSyW-XXK{rIo+T9~dU7gE@(d4|>=_X<#WONws%L$< zX`T(`rhCR$o8g&IZKmg5wOM#}H`~+SJI6D?JJ&PVJJ0ijcfMzA)dik$RTp~3S6$?p zSZ%RqQne+Xo7HnX!@Ns9>#F|jSzmRTr+>(D&w!8>o`E4NJzs~c@??js_Iwkv#xvTx z)-%St&NJ4#-m|5`2G8~i8$CNJZ1N0A-|YD@eT!#j>{id**lnI&vD-c0Id^z2h@GA* zVwdN7=x)!vusxpnVS7Cb!uEOgzqH@8Fzgr4qOb#=4X$7DdC+q=^pIzxIP5u4_BT&I z=Mm5M&ZD0Gp}%|jJCAt=IFEaF$DZ&EbpGKPSsXFY?R z=R8}S=RH3-FL<_vUG!`ZyX4sscGb&cj5_-?mH}t;eLd7iap3v^zVa^`jA6-51Y_6Ag zXW6g31Dw6R=gNKUohP!r8=T*G&xQ8!_7&fH7l-!sUM=^XcaiAl{Wa`+@4>MC_#EI} z;Tq_@UT%>0P}pGa;jka@ImEk9{OJ8HY^e80*f4w!_uj_y`a5Mu;&YUDgzG2o2lFdp>YFM9}|hrNqEzj>!Sk9hmIj(TS}fA@|M$Gl5Ij(cZ1Pk8bC&wHfe zpWa0gc-|X&%DW@_l_19ybGKcy|bN{yuDqQy-QtJymOpa zy*r$Ld2>Rpd3(72_6`oc?!6g$!@Je>k9V)@U+)^%P49Sd%e&Kc+k4e{$GgdS*Sl2Q z^WJgZ_s(->l|NXqd-+)rJ<88__ALLmr&swOU0;>&?d@IuYPqk=FK}j;KO?>=e8&y=g@yHZII@gKDy4N!Z=KmK9g8nm zdB;8lzR54So2w+nSPuuAM5*IaT5Fd-Bt z{6k|X@^aOxRVzDlKPp!b53f<9TJ`X1xsPdIRSpY#<&{^U)v8pjUPF7NWf6zt{`~@u zwB9{NC#KfCH^11#gVP(#81c)Z5KrSZ*DDruJX!1^hxWbQ6$(1=>WKc~UvTXKt=yr3 zBP>$fC#8SNaR&Hw$n@e6BzLS_B{c&mm0CMQ zT8AzUk(l8S?>MSq)65~T!rHkbzLW4CKJm?jcdIx=OkI4{Alf0~K6Z%MjLd|0{}yMR~Ui1HY6y}-BXy3YB*EFn%)0ynjs!e*A%vP=6uhiC2yujk`I}Hl$yQIzW zXYS6pUcPL#64B}oMz83H4?8}w@T)IpZmH7vdi?nxw-hX~<5lGWyqnQMKla6g4G%w4 z%~^k3>9wCarY`@Y#DdqAkKL|qt1fNzqrcqiM7L4NOCoE}S-5x5;;~ao%vV1;UZ~WM z{hBlV#^=fJRV>u)y`rC;P2XFh>VGdfU6AJ4&1jDoLfW@#XI!Z5GTzmV#=gCw@T0wN z&k9-aOGx>j-iRo1DN4CSt-7?YtRKA8FO~O=tzT$~_r~E7Gqx5vSz=iW<%54zJuE!6 zTbqw{gWCU;_cpol+1E4T5=&ip=-V$#oM^3VpiN*k^rQEhJYxUJjbUNkH#Yt#0 zN}N-#jfSruJoCA4u6KWPc;Z(T-ubC`wMYIeaaR4{#@wqPK6OC132D39uc%gLNAD&3 z_SPtI_?iD)nV>Uz@dEEZ_3e@mf1W=mQoPW;MfXDc9~;!g(WqWjW198x8s7sCV-CwI zh1U^>dGN)M3`|dpdpjIyZHpIpux_0~o;M1ds8_(-uz)+WK>5r9g_CMJ5*o!cY}~kh zYM1v@yWrgr*@f^H3H+!J!C^R#QPlB0Uf)aAY-*&o>71V4M!P#WvP#1PA4MGlbH8o9 zjo*>=y!q{oE%4LLwDzf=kWjB_qg3r?OUEca23+&u*6u=$8o`Ssrtzy}ml}3HYh^j5t)( zF*VH^)LSu8@r_dB8^$L1vw6)QZQD$zZy4DiCN-vElee1VFq2HUj7WWE0#d43$0%zE zOHH$Fbzm0LEHx^!e*HR;QT5{cGTP18?mr6lvT_?^>=Cd-6q zZ8pKEI%l+hFEz8(yY14As=r_iyzp(tg4s_B^TT}IL3_KAF{q(9#w^WiGV|)vp>w9i;ZQKN9D`vDzQO8Q-!fM(u{_U8z8b{W*degeRx}+Ozm)>5Vc+%61!T8L9p0OH5 zKe&I{YSVzHG181KsaomNwRe9RC#Wzmm+P3b^Q^Dm)evFYrdn9t(%T^-5!UNuIfPku zX`9g|cjl@9yEVGqv}k==F$SI5B(hHZ7!-$kxTvFDdTz_%(tbOpKCWTx5N$#%f8D&O zalu6=;Ob3{ZQ3vjyO<~GD(lPlaFWtGeAqs#bDc zijHg&i9_zfZultb=n>rG0mFb-VmSA(BCQE-0#8M(U@3PdwpvTrcR1^u&B4{`!~-U#$gJN zWM}ddyrYC&v|IJU{VxVb(W?^Qut`iD<_ACU`XnK$%+lwVzPujhHCy;_qyZJf|j(&rgm28E9l4e2Z~# z>i`|hmUCFQR=PV{cda+gpB`{JdtPKhbkl-`AE19Ly=5MyU$VK=TQP4Z z)QgGsFG6EuufpXs&9I~OwACd~c>PjbU3u9heaJNXwryj7?m28fNpH4)x4ScL+j0MimfT1smF~og)0F+Qq`=` zw{gI>E_r|IMDwV(0!HRHVMsCI2r8^kn7P3!u>2Ux+% zN;AK6F-1Q)xxuQw$@Ofk$rTraTe5lc@CR&T9%Y3wY_=m@=u#@&m0jc+?eXq0?R~e# z{8$5X#cBNn4v^Zw@4U1%yb9l7Q?7Pj%$;)0I5ZK5JgXnFV;(by)y4la@n1AfjFC{m zood$L1L?>8h~6inH`(agcm2Q`ns(>ApmVfuX7*-oko0fz4@{IlJ83fl5`E*y*qAzz zS`_}s{9Zy$^J>Py{CeOMa|hgd`NifpO@3! z_+8eAY*bqQ{aUx0VfBzTKXrUicPi>AXAA~WF+R3=YNN=vA{zkYEAwI)(AjvZoBD36 z_l$b>HOqhq9N2i)Ro2hkX^r2lGO}@99Qs2V<1j|vv4i#wT_fUZVeWe!ymmm6u$rmA zdHhb8yZtkQyZhIk=n%ngK74+G^<-<`jLG4@xpZN($<<=wC8d|wbT9^ zYi9gLL+6Ziys%#-%pVBwOV3e{Qa4T`RHHwaV1E3Dz0FMX&!9b!;&1(AGt7{Y)AI zZq+_5y*+!%Wjz~u(wH46q2bt0b7J^B&!Spa*JKm@fIiL9szMrGSulo1GhI=~adYVU zsI2=;XSx$a$HyVR!`O;7C#)wj=95#aGp3lP$IOG8^~3?JVkXDvbL-oY^_yzZ|1E_Ui<<+EC1!kDLJ!9U1{fK6o-#qV&dAkwJVzhOwk;WM<+?F*e=40L7irir! zouy4F-i8i5Ye;RMkyb@}F~^*8isRt3^^t7O^ZK?B=a>`=5;O{|!`01Q`>|H|{^x%q zrsXy3PCU;%M2>OF>cpEjNsPzLpI@@^7=UaakpyvsQQuYZd>y%;#WTq_Z}o3qxNs ziv}l6G({aRwlt?h|C_mg;9P8S{z2=G8C|+`#kwOV0IUOd&S=%nxH#!-yRo*#qt40=z}N7@Q^X6LTvGcRie z?llWRTLAGRSZ)%e=Ivs2#0qoAKlDr0xJWR{7tF_d8*PAxtVNGbc?BLn^Ofe$J{Nc* zEZbG)E^DkCy>QSmIuy`9>nR#IMz^AEe^#cY>dMxw(XU~*nBV=wyeZPNOygR&o@j2d z7JleO8^5}2HIH$@cpgc&4qE*#>KIDMw);9Ye;; zzU^rd##$SiX{EE=*NC*=UdBgJM+57dD4!pIwXl09@0BaR0qrqR3fHaU(4J0q?3$Ts zyi#H=i#&uK_M#69Phit@TG!m?TeZQnPjA&Sd}i=N+HVf|T%J?3HG}*@JbT#XL90Jz zRu~Aw1G?e6dCh}s7^OxiCq^vBhYyQ7|B)phaxRle8;LN(`NT~W~N(n6GJ^yeach(#Y=`s8X zt;Z7zPOq6zAnQl`e`EaTSynSvEUj5T;R$^GX3gcjBQqUY51`07OKWEL%yx!m_w3Y6ZXiqD*t5(k*B6mvxCTi-gufvVwb2F^xeX`!+7bvm+2YAhRTX7?J7O7t3_RRY`k zAQ<7)2(a~SAp)ox!H$}-#(8LI+P?sMZnl%mplW7&G2GoW+;?j(@9|I}M^;&Fw7XI7 z5!!jj_;KF*I_uZd&-Xr6$6w+23ptMTcl;%Y<3Ux&-{E+qrZ`NdpO_uy(#Cnj>afF- zKkKk#RC1_V$xj34WKHo0;e2W0cr~1pfVff&#{KlN_jBg_kw4ZM!h)({T>;jmn&JXs z^`lAPC5`HmM0G);GNy&AgacK>`4>1hYKp%JXOKV64GHJ(AUHP(2daj14>)&-Wte%! zDr&X4BU!VyxlaU8HG;z7v7%tOF*6Kd1O>wbFI7hHK)5keL)8e1fuKmZc$gsC(#2a@ zt3r|R>|P7B$#J1RInHwCJSN!-bmw zd--2kUWv~wQ5hwxKsZn}oXWs?Ia~omaI!eND1PFXm>QIz#|f zBd7<0_;3*yE@FtIy~z=!am4d!WuY@C4v%cqCYn|HM6=476O%t{ePV^Gu{H&3<8bjN zfsO^J76r53&_Ejli-p6SH>G|7^l&XMYFppigax&QHPlS*ZGqK>m{@Xe1Ay&Xf(uCQ z8RQIAbM64=55mR!WX_ZO2iCmyzQh5hb$V{b*4L46plUc>fzyRpcyjN8le0tX8JsRF zx$o2ou=RB#0;n3nC*i@8d#>51WCm3;`x3+boQBJi`{$_lPVKx0B=;;;$6j#kL5?iB z_Xy(nm8#>naQr4*d`+f2xqoAI*w>Oj>#)95a;RF#2LWe5xcHuMcyb>Ah;>@ot>pfF z{#b(v3#x`S5?I5-#Zbax$$hv)HB_Q9Zs?;32daiM0XXBr#Tde2$$gxJGbRYmM8bip z;Y%#e}cJ0097Mc0)j>1VgW(0C5i9 zPm2-($^B_^hN?L~59jB6q7<3)Hr^$119hHR1S*PgEmQp4nfqdaIh`kJnM~x{oiMiVamO_UizN@QK<4!qa*L?0d3x z_S(UKA_)kp1{4pVIG>0iAePhPB%TymvR1pJ!GkeG~!*^!C^RV&WNVEfP~ zy81*HV&kd&LkX#?h1*4jGuq}8qJyf@^#EO#PkcdWERSbNWM9ZU`UTySaG+{9eSnkg z6TJzCBXl^}_a!PmcO(+XD4f6AY4 zBJn}h_-27`hEGf*IG(|01ctqwX;P0M3LexmIJUmoga!StSkZXjOAGxyFTHEUie9zy z$ltwcW%v9&kNo|0EhG6u?Yn*l*KccyZ^)Qu?{90F+4~!r!I-`J5d_pe#2`QnAOfDd z2h_^$bu2JH5`~dM4yc$PgZa@~;KpyiYX5)U)T%E$DqjIGZ}NYMX^wBuF0NBoY1 z-XmTnB36`+$RjV8j>ztLDv!MULWI#KP&H>4oI@gnlgxQ$4v8=`vs2A^H&xOXmG0oPI%Y1`!Ta4QD8Dh7b!&=R+iCqo0SVI*x+l2y$cz zeFPlyie5j_SfOfT9S7$zWOF69H6>U5qqOsm-GAV!7nZycJV_gK+1rcH%f%4?OATS)}%#->B(3kY&j;(JoVL|^Z)`HiO z+}E4Q{mIB!@kFF}G|~v~TVBU|{r|;V*T2x-y8Z;-k>0Z`jBo4jj=t^8c@&TI)*iW~ zKXOa|O~>rA+HX2y>nj;)#CoV2)^orrMNHdYH-7oBzlKywcS1V>62E--uldV|rBxlv z!tupOQHD(SXob*z*>sTR`XXEhmxW)?VmW0b0?-WBOMtB}gh~KaE5SCIAv5MFRr3O|yeufdoH*20;McQU!P$08PmKs{hGv0>^Bv=EmG)o&0y`WD`cYLEEevKH&}HMYJF>Eu9d zog546b6|Z+Ozf8RDGISTw=Jym@r9~mFF5vy6j@}-Z&^Lyx}0uVSrP%7bh%yvY<*u* z37~2v=nJ4eks_Ob_${jsAZF7oD?5Ln?+6I01~eEz10zL$0^+x!^9TBYfS_tX z!vQpuXxJ@ls03i#vPO_IRLyxboJWx}yJd~y&ep6ohMb{l&XeFgAySMZb9T#`0CV$} zH4a~|)UK0&Th?S%fSCZ89x0|00J~*P_XC(31YnjbzybiwixhJRfZej@`2oxc0oX+l|RsZ0)namJy-{?xYiK` z@ef64e{qT5vI^J91uBTI`8i@0dZ-S)5L-tPs2G5X5DmL!6_EgpTh^oG3{@+|6L5Z< zoY^hwaqeu*S|!LCs^(k@&QI47CCQxKvYv*ydCMw^uYc99lYm>+v#J0u0-#JCQJMhQ zEvt+lKg^ z1OnAS{dbJ2 zc>8NP{q3(ifv}zY*&mMB4!5IPzX$yK*)FO*^uN|V*Yy{;?yDpAkTHKLe_tK*rTje- z19*<I2M7gfALTco93l?>GX5c)fm7NU7~uB@BTnn?*!qr;JJi1W@jAg?!p}82 zK}JyfMyD{$KWUik<@-NT&KDGHQFqQpZ{M&MyD)juMkJcLJhXBsHQ2nA{% z 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 z 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

d2bwV_-JJzyh-dmVtpK!QvuffI704_!wBkFtFUL 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%0D7_E+;Q}_B`icoSO+cV9tW%#Vq(rc1^_Fi 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⋘_dCycR&T*=^5Q+=3**p>z-S+~% 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 z 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%0AY<(7wce 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

uqHk4b5Fx{30 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%0AcplsNCo!zus%ND!o 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

  • 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 E%f23Fkg1 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ܺ>D~FS9!bYY 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 oe_7|JO> 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

    ji=9< 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�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

    TaKU>6!sApQe{}BRVPRx=){jaCiX@i?z_U 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

    E9 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 V_DmlY}mEn7Dq3vX-wm4Dq(JJ6K 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

    oCqlA69wuYB^D@6$srSVQ_WVKlMCq% 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%0A4avz)ALy^ajJWNT>pyVVaxdIZcwJ$OU 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

    x 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%0D?)d9R)&7>Srxk5vpRH-XHDo{&)U#^o^_!=c-DvR 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%0DFK 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

    OMc6F=F)QAu!4VH`v^obJFmjaj4{Kh2UBWs|`K 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[Q|f^cRFjH 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

    LNlB4!f#`a*+Y$5<)@rk8&AME+r1( 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
    <~7Rox&!v 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

    )(T?#Cy6Xq>+aAJli-- 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%0A`Gga&Y#ZIKi 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%0AR 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

    K@ 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 z zVu2l{Dc;RCc0PWMdPM1-w6^sx_9QRKwJjw*lBIX^_qfcL_$@x!wPS8t9oGUxa2$94 z@o3m`JGVObm*?I4%VGOfe9#zE*oKG)vPFq|hJDz|dvj|rpKunY?_QNyzq-ovZnu>2 z1UI?#QJ{QUJSg%8PY-709sW1Bi4tdW5>tB7a}e;lM)_gJ>x^)g^QWksr$ezIK5Y|E z8R)zzEq$JhcIdrX<(T=&I5ODL7ER>a*N4!TKkUAAp-o~xVzuUv4wcF=m*l%gU!>iL zbk1koetb$#wCR}y4g-AVVEx?>+L2CPx&QeLvAj1m0n(p9D)%(Y8ac#yM(4g|v2Jx| zZSpE|-PkwHh-37e%axgFZwGmFqkG@F8}(;tO6<4c5o`S~w|t#5Jt+xo)m?m7JVwWL zlTh)KXMX;5j_Nv@l`uQ2`Kn`fDep&wD4@vbCMtt+gjG>-F84dfR6lB6Q?JdfuNpBGvlq`S#>DkhjT*b#MI@ zefwWmc|X64==ddW($~&gU%H+2bzvu@yGJNJw2F|g;?_Q)CP|NA{TCl>ivM{>R;E;S zQ&!O~cRu{Vm`RIM!+$+S^tPJY$V4wpL~pCRN$*6w!ODUGPo_tq)_={wrtM0e3LmN9 zoW&0p456n<^!%&bPWs$fl!(oXbD&x*ncUglOi|DibXy7OR2Z9k}Sj*{s zx#Ywc>z(tkkt4F4&+^t=%WpCbLC3zp=ahW z&hpH;5lzlOljUA!H=F#CrSELpqvy}ss+Txjx88ctGaC6xK_z}fMhrk*>eVi`aq0P+ zdrVD(#!Ooy*YBW@XpYXQ$}wf+iR*ncB~Rxo+~u^!S=l|3dUf$JJejQPk?x=-ux8s> zZ)VsxQ2Ch*rv7912D;j5y~{1VyW|NCE$hK1$oHj3%dsPLbd9@kgNsDX#GS5_?BtZ=Etbm_(#F;#n%c|ER2 zsPI{Qe>?s!c5Pf&u_i9PM|FJNGj834gb^`?O5KE@T@hc3e_(Pm2)hdBpgIDoIio{N1QlKI8R67{Gs5S*5I5a97Hpme}MBhvCMR5>_67n z{H;i{WpjZD5X}h6#dj5D;+>OW1|ujF@7=15pnSY@QX`rXTmphh@uDI@45ZC_oiz%T z;)};Gw+_b@_TjjsQAtIG$~i!)m||Q8j9T%cM!cv-BqM2Y#91V@;@w+D4G{3XR83)W zR&5;`B1E$xY6P|h@#4yOaRssUb*HMG1=m19x>Dj^p}?_eyowkR%^0r%}!?_7KZHZ-JioO_|E;&>>IBSq%i z$7vKFHC22ZiWB3-VK`#4B3~2gJ_1c4>)_{ z#n*(xocmq{=W7kle!@XC!}%UK-w_LQ?%yfO&U*gARPhKD50N5s?uVf0XT5%+z9O3S z^%#_ok}`MhM-^$T#ZvomoCpxj2+n}u_jqwCUYsNj?%aRp#|oVLDZH}NI%uSGKN+3% zPhv$hV-1D7iVN}LJb`lOe!*)FOU^6n1<;?^&K=iqnXvOb1u+oT3$Amo4Xm1BpJ(nh z!^K6PTUNs3+%F?#L^I_pp?pPH)FpB5+^-0`4^Zl=9QL#MaD4(nGy`c2kVZtoJ$s{Y z@%XQ;)e`C1_t>5t*KiXeKr|z`I;`{TrDDxV4AD%iCA!;!y30I!3ykz0YsNjEU6?9f z2gO#T$UJ*1jba;9#W*P57#25>DEI6)%C&WaqL0r}@VQSoo(3DyY_K~4q+?jLClKz| zJ3_vQJ!fyP14Ah8HXQ})jX(O6xXF$6zX>*6(SErpx+K6V_cR@QZEOJPm zdGkCRf_od`kp-To=O`qOi|KC)FcbiT!{Y9+C?E#r$_L9Wdp8L9o+(h69E&-O1_#k> za7Kge{;(Js7WWYwcjfmhNFycgeJY%@Z2m`dh-P%-Kvx(RV+oD<@j``ctjc3==pw>F zG{cz$oZ_&UKsd~g7b`duG&qkF4x$;(6yQuI7Ust%E6UDFo@%Q23>2RxMdrt!hN7RL znn8Ubw}NaHSFYAt3H0iqef%OIE^7W2YlE^%-_KHoh`;Kb+Q>u;=M z1y9fCM(0~Ve28XzOThO=SS%tq?!n*in!S=m${K+c{Mz>5xQ5>(EX03{)fqqcl4<|U z%Y=4a#rSqU{(F48;-YVT{P$z+9OsW1T=hw)KHg4DBw_BoA8+S+?};jdb9zlC2*ltJ zPXl5q5pdre)A zK7MgQJAnQx~-{VJQQytMdqY$(kO;a6+1z(V@J`RM7f*pC|6i}MW3y( z1R8Qgvms9gPS=j2GvRPw-4zf=tYMcwY0^15RtjMunql<>R*#ONJ7F=0-9w@3u24CS z<~G7XG{flwoI5*;-h{(k_MHk&Zw=0W2?x;(Ckr?k#KN6+h9b?DO*RoAni1Ruf;=MN zo;xo(L4P7ZG$R-cg1bA40)k-f`)(YLzgdT){7I7nh01X=LrgL52gb;b;=YdJULs*W ze5Bma_kn=#rF#`7XVpGHLxgBHM2~>&;f~^=j$#b4aWDR`g7lEY9izapg*1*B5zQDU zfw8!wm_UHcl@}{~6BH_E$Q~ygL^GUez?srfOeP%W%%>wK!pN{^kQAriNGQoP~oc+o<`!^knud;sA5!Z071jp7Rnqgf5th&Usy_56Hhf^%1 zy0#LQ6Cm-+hkv@id|1y^@hT`bOc3=+beA;{)-RhrZK*bd>h!CiS9D29eT4ut)9oR^ zHQbnn0MTp+t^v^138EPR?RJ5lwScY$M4<(QUju9w9jFBXA({bQ2cT97LJ-h545(EE zkcbY{hJX;wfNla%TcUZtlk=O&Gp*5Ss{lB6oj6iPG*fO5L4B#4_yJSM@}8!uYo2@pSmhY`4x+>EbZ!bUBceU-IO0OH(l zI-3Hd0w6g-bR~fDkpRgN09`czX{G=@0nj5sbSHqn=yb40phpBicMZU8rT}*Upckp1 zjGX*lP%O5_+&P=%BMg4a8Uc=F7KglL z4Z|xdtXCp$S*z^x8rSgsG&zWYCP!jD1gtT{#BNz*Fc7OsmxY{v zWsQUCI=W>QDg;=h>+B)GHT)=a#k56kss`UQZCO5dgboy&eJZng(Er zDZp|7EK3ke34q^5_!woZlBkliVyTh=iQ#CB^d zdfsLIYO44L6i+9J-$<0-vQ9(wGrDE{rVxPUGkXYd4WFSQKr|bIe*pA%f;dM&{Fe1M zAl|22*170F7YGQ^4CtaneBzoY%HThMV*SM>e#+q+sa1oN5zUnALiw^pQH#XcE$cFfySJ=b z`1&hrpLlLrmzx4K1VH^nQI7!FEvtS6Ks^mWBU6A_05nY$jR}C=vYJK!G}ZuIZ3^%o z09-@r?3Q&66eHHXocxwF`G{td-v-L96UDV8&Td()6Ww=N*K!Pb%evlFJ`DM|MA4Sy z*)1zB5kK{B-5BI8tE~p3-M`1U9zXut#QyQu9YEMl`s@!!Y=_!@YrT7Z{p?d3d&GY` z_NA&{LiO`Rv5SQHNBN&8x*z55QW(HfY;2-1f!3-R-W?*W> zAB;F`tK%BpN9u^d)xS&BeS}{sbdZD)g9{x(H-DgRvXAe7z!)F4=GpU0XNOJHjzaAx zQez+8|D;j-#YF8lsQsEKj*}q&*#1|!nvN^lY&D&tVMYu-%;$jeXQKFnQ20moe*)lu zHPn;s2ika^`$u%7zX%C2I8xc9t|F8qE)Wv?xIUERCAy#xId}SUNsh-r431J6C>JM* z3Q3OPVIS3Bte{lDD|}@-D3=flVsMn|K&eU`{A2p6iY!|uHAo#XxOyF^*CuuT5q<6G z>UBvSF}Qj|sMk*t^$37{JYPSlc>K@Sp(j6{ucr_>kCz*nAY224tCK{tB+-N@*hlkM zC%LzPW>DvQrisGiEQ=O2G>E~6=6Y~lmn2#x2|--^WBKb8oK_N5C}3>i+(3MY!TH*Q zFPtRe2#$RuA6D4n6e4G+IuHtCaFotKNlX%*2!(wdpQxa8(x7x96vW^tsX$344)#%e zvZCs&-82)m9#HE}YV2e9?ojiyOt(@W5rg-!7gTQ}RsIqDZHg?`U8#NOP3nlj)ia^q zFG>72N&Fu%@Q>g7@nZuYzyBAn9JdY<`SJVzMd!>SPQ>7x1HsupN#qkG|LDCxkeHz> z$ye3~fDc&~&$@;S2njI=Qghp3j|I|$N#X%Q;tzx#1k!11l;i`U2k^=n>y^j{LT7E) ziEH>_LP89V^eB*uh=)B4D#Cc2g}C=&&;%2;C!jVdNfeVHe-JbYiWlfXP_d#8k_&d% zaScC7T}KSw_340_mL#SS41WkT4FD(UA<&fQFwYPSVsMz}0W&K}JV!A60nn@nnCGIy z%pn-W;4t$6Gml8v!=HJIxN{eIiBu7Tt1g7<0#aoUeim?5`QHCkQbi1|x&*3kB#A{N z%pUr@0b%!{&mw&NNMo!*&qJR#O~h9~{Ou(17KyV5K5s{ezoijhX(GNB;%kz`Y7%D; zd)7pVuhxjKGZEhi@eQQR9`tO0TEw{{Cwmi3He&F}-U`(%Nn$ezvxhuelH7+pn>m7f z$g|Bv`cp`Mk|aJNY4(8U6CCv8v9?Md@O-2}*!k}f_H^qJdceN@{M4THBrnJU@4H-svI!+c7Uy{S~UmyNO>&m_Oh--pzIQzbFjgnb_F+88ckNCkX{H zILaSDIZYh=0nh1f#p9o{W+3tb&lFo7*YFuqM+~n1S2x`Qo>HN|NeD5xP)u@H@eg&A zJ>dBVV?4#0XU_wkP_ltqd8n05c2*U8z*9EaU+p3jwM(E@DOpq`LH>ZJQnI_6Dk|D+ zHC0J=7B*t=VXg&~8p)y>q3{PhH2^Tt8fy7~r&@HR+JuA{9H~B#>LrWI35h-6sizQK zt`IqQ^9F>17#yV;P?{u*s|bZX;Ax_uT%|#YB^1QqDE|SS)rY2Xb^)BO?PmmC5x0~(T%wH1D-SmCq<%mQ^455 zxrO);gY(@1zFx`VHiBahczP*pw<$!wpxx~R9@Z>70&f2}pM6Cd714xZM;28ilKg%?T`iL03k3*n(52^A8JohNFSa+rN zVJN9123LOo>Z6jyh-5LG82AI8QT*7z1D+9hkq>x=N9P<(oQT0W$APmjS&St} z{(z?tNX*ccj8)bLfSiFDfwZ30}w zZxaEc8NsS#o#QSQTTNn!W@2m6-8Ix*=DOElycb&Y?s47gOcggmaRVtb=eJ1cSXFXqKs@M#QO-PZs^(IjCvtF^( zS46YEwt#YTQs$1mxgw3VSZY81Lj;Is1UG=7O^RrpBCaJ4?%La=uwwZwJotCnz42SYx@)tCQ$C&+XIW4!;-MFUI6`y?c8w<-%MDDfv{GD=5f+_~q=b1hfl0MpyHZ^kt|fN&7aaP9%lAY$Rp zeGn#Rt+i$%o%=eQ0N3zfB0w}FxHm=T+)KrVlNh3z*eG;&1a+4=_YoNHb=JIlocsNz ziesQSniQFHAFWY*&{T086bnOv5G!hVMR3Lh-O1R2{^?mVgliC=Uxnm zx2<89&V533tj7rp(G2TpU`8F0MU$KAqW-_0e9{Tq7%GI1c+t?Z-QWPig=wM zm~&r@!|`3~aFovdb%n}tI!jG4N`SE{MXX2>Zxab~?yKa6UI7BWm)=&GoK?Gqh6vGY zh~5L+#uTw3MXVz>?%X#jNE;;XIt7j`q|L;LXvX+47(YxATM3Xk_YW1mtqPShWZMY` z(G2Hv;Ot5fpArsp?zv^xK;()<41eM~XO2pxn9t;WdXPr~2rD6?84AD%iF}mA`y33q< zBaHVBYu-K1y@{#f)lh6kip;q;(_bs+;0HHR%_U$b8izJ>n6fNG{d?XSRGPDJHlely@Nv4PN8yc=$!}$(F~^> zaJr<5B*J0Ny^DgAq`^rh97Hpm?!ZYS7Vg~B6lu0>ZXp6hGlJVe(31$bbMG0QpcfG! zni2E`L7!A{CqXdh-Uo-{F6(fV&izh>%5ggVOfl{PMqaAONflW{!kl}a+|W57;Cm@c zVRBY&e;Oi0vmqJ^w!x|5?o?4gY}~mIR*>$NxCIIvTS&u*5z&nC0WgkA6(b0cIrmWt z-w1`u8M4uYgJ_0R2%NF0;z7b;&V8(c^PmRj5yC+|JVE>+A(71N1>JNM`K zu>$8l1Fw8(9W>IpPmj(zn^+OeSYHO~{8TZIK)G|D?=^=d^OW@h=ud3tj%#=UVIc;> zDsi3rDqyW3CicvI1pvObtc1t8uO?+gGv)PAUYjb`kT`elYvsANM&SU{9@{tL8s0!S zh-NsOfwPHNxO3lx$vI%HnMmjUolSsi_Irp6!#m`L@_dxNhRPiN=a_9b)Twz}-`fP>mr6ET&8}fs| zIgl#$6ApLo2LQ3h8g}X2_eaP2p0E(ju#N)jr&Mv6u$XiINufHdP&qgBUkC@$4CfSZ zPNs?zgu|TsNd@PG2In;4Ae!Nv1(sifGo?_D~L!GI#D_MH*|d)P8gz0z@-{t{~`~CKA&` zC*t7Fy)!>n;M^1O$`R|Jk0?e6PtLP`=ln;@3i6?ew+vp%?O@K(>-%96`Mk0h-PBb z(cNj(UFO`UVZ0}yw_fM|jH%*GC_YPy%(*|SQJiI}I1h?*)5P;6%ANaMxx$`T^w|n~ zk%k=6Y{*{)&MRr+Wy0ak{S`nQW6u5M=vc227NQx}TfllVO)MrX=G@;@s1_?!&JBGT z;UJpflmKT{npi1ce1{Y&XUL8c4x$;(Z@~FAO&lj2=G=c(aE@zmP7w~G8P1=;`GZ)PbN@q8 zcGmM*Q^oU8{EHNsbN>s9e%9+B>MNpIU(2L-6*1|~`*7~uW756SSc|3hqinkKFaXhv z;1Up2N*5K=#YM!yoqMHpcC5g;SHvq*t%F87_lu&lRv}hIGuF$%S}R@DAW-hyYXOUy z!;%`n;sy%P6D_-FUBh(<3o#H@oig-u?oR>hNn&Eo{Yd~!w;Y_uxlbWwL^I_XP@bMH zrja;z?$guV2Po4N4lw;{J9k{e&k_!z8P4;-nMEwzxzEDn%(B)@6V+P^g?6`ewpGG{gA_INQ?22ZY0%`!)sV0}al{go9{?vlBQwh=n`% z9g1|z$YryO2oTK(c7xyxBH+&bi|7Pj5doqZ!M7mTmoD}a1at2Da5&Dj4oB(S_bOD5 z(>Y*@@e?o(r;8uc#rH(Qocm$9p??Gc-%H;sOwOwPnT80_Y=};Q?PR(*kuHuA8+Yy} z6{Hgq_m~3LGIAlECPqXv#=pUME?xXdfXum{Q~3T=sGK1?PdJEXIOV!`6=k}MnC^~) zWX`=zckc|w;1zyba&XFbcf2H`8BQhOR3sMW+$$=|&U&tFs#q0@RY;LJ_bO2IvtHGx zuZU)Stp(*8q|BXr4MiGjvDALlCIUn=f(9VCvb(sVyQoVX+__)bogFK1?pNTI`PM-r zoqOHrtPP13(Tue@SYx}3rUc5Jdn~Y+IV@?atQSDfvYk7w;cEyB@!w)C?%N}jV*mBV z{C@buNBw+$#yz)RanSwUHzPGf*4%&Zm1UY69Y(?JNANpu45mdFo0*F?U!*4 z-$N*f!BOr7%249qZhdG!{AVbwbrR{;m)PpKhKG|nVsQ0Q{d7*fROo&ZLJTf62HhM@ z-DEC(G{$&|HP0TG{-B9kA=Ji_8guAlHENHTs67U?NBfB)66EguQMsCm6m7PeifNb; zgAemlKzXvCc$`qUGk+2Q3$3A+KMnJEbfhVSgcuy@IUvpGC#Dk;bLBG>qUj2eb9bCc zD2TyP<^g4HKk+=FFh@RDL3v(-@*<%i21j`XC@&KScjGTBvTT_wBz45#>Tf`O5vg-0 zz9_o-Vp2y8uD%@V%le6>1i)PQG8}quS%;o<;Y$@F$F;05L0Aujwf)4JequFIFbBR? zZrU|a=X++g!sD#a4Ky@}!G~rmxVH2YoBN4P#KqnB76oUsMBSu-v4yjZ_z;8h?F8SB zequYpG3UKQVcV_{IYYIJP!NNod<~S{{lpi9!d&-m1?3A3${s>N436?GQ1%fAbKLtB zReA?$qV@yS4w4#k+XtcMXPJJaJ|YJ1<4;gMOsd>zA68_s?n>>$&!mnRT>TW(Pxcch z`iW!2z+Lu9er&*HpTH|Ctb;_l>|@b6PZK9%aL)7K{HvchOOV`Q|K&AwC1;iO0pP{9 z!^SoI4AanWka4tN}P^$f>hBL-Kk1J&9Yq9zG*hh00v zb=Wl(2Jo!0Jua@{x`cul9Hl-`>JbNb*!427JghYm>99B2>bQm*kUC;;^~M=Ghg~Yv zgoF@-3tf$FHluDbhusWgywRFxkHcEl7=qg|VWM_D)UL}Atw@kN?Ca!e zYNcqi)pP?5Gh*;zZU>b33~>{oaEBcafHl@oONV_^bfor#gcuyDGmsK9L?=RG4m(jH z>ZA}kH{~vbf*2en9Vn?8BAHN_!%kIDk~JvZ2?a4Y%56Zol{mP=zEzQB%j9-aM+~n1 ze^9@J)VagHBf5GYQb!D~o(=WP4AGAOn8VJ*p|{yO^rXY?rw}$0%&06(VP-#u5r*aFj=ZQj{ScAr$7YixiYcG$<1Y1u;0v<3O26 z9L!-)R8*a{`-F+w6sS!mHRiA1k;S?zwGT5$9Wl82 z3s9evA!cWYnZ&>y_8fj}z+unED_gCDL^|x5(K+W4Ct`5U*TA_jLo6Uj?ywhn4PD6s zWqnw{w!_9XyoitxgCN~*JM0ZWT1PzWCr{Qv{3FW_cpUb-q>30^bqiECXNXNC%pLY- zd1h@=7{IgL_PDr)KOhvu;3yvhQ6x05T(N1OVHup_UH&P;{iDgoGFz=@gJoW{4An#2ofX zh3JGr;~6IJm>UpvbaiQYO=R z!hjfDy#mzBXFAU{xWg`=>D`V@y&|b223M~N^(vX7G667$T_v-4{BG;elMcJGLgcuV zY9HOG$!%oF3d#!^+I_%`=oIQvWF*xV{f%A?` z(TgCt!@dJZ%+QteQq~86KeHV+uHim}gct6g#kPVY>$g;cqE}921ofHP#z!-?yw)ggdDQgNTkC)Y^&oM z9z*Jg!POtm)IGy46)Gel#Na~X(amwxP3Ex2VT=!3^XzfhkD91WgxX`I#vJxz8nsC# zYEz&#Ia54Ag4|(GmaFLrMVqarsWi-p!H4-dpv=e=(+Pz;>=^(!U=6i&*wdpU%_Jnm z;7Bh5>4i)&hme@VenBCcqYyba<@tny7#!s_pe)Q33kZcd?1c)-0u9O{LO~3U@+MFg z69;$LixpY6OqP;5VsP~pP=A}$xx;=ty822|M+~mM4(jh@iV^}~4*MM(dOur-o^;qH z3X$Vd)|()F0EG85#e11zBT+Di{l46^??IjKnT-mMvqHDh&>#jMnw{XR)d|zdXFA0u0?5`BIFBKwZsP+;HVsMm$Ksk^p_7e(o z*asAp{Th_-2?a4Y$`PO(A`a%T4=Jk7+WpBy?HJUKk{WZ^N1^6tnT}H*5rg;fH>mzf zs@!4!s>ov9mD-0>q>dO|{cotB%M^cRia&^fJM44(*nq?S6R#Y%4if3G|A@|co;VSM zb6%9yRg}vTWwM;77u;c&%kmhyk}_Fd^8?^Rw!_9XTp`POnt~VvDaUr$R{^OZ@i2$o z5aK5-JK%BHjY$R8R#Wj2lp&$lFxfUobiGw@r zmY9&U)*6X)*yn6@T*IwM9Wl82^;tTHT`F_~2_Xg-ibFSVq;4{YeIv&BoHfrLhaGRC z)&XkmNR2t{b{e&gCTg9bmY5|vksx>2iE=e{QncA>>O#Ye7<`!1fs&dfk_m-7>{I}p zvW8kZ?BwW3-3bXXI8tvQ-JT_S5)yORw<|;ci$2a!5raP@nkJ~T@VCIIHJ zhvLvXZykElVGmY_9G5cO1YryiMrVopv&2ZEU=Dk<+_d*Yo$r~E3XiiwAEco{3_diE zf~zP?Jd!0ICNA!JTktHS(9CO%DC~T7yB4?s5)zRj)~ffPdU0c9rnwLEY@AAeOO59h{4sDLVZb=cq2y7@TtrI9F$hl?2Hh_G+)8D_N@Oic9wX#+*k6+>VsO=Op}H?i>?L9Du=mL`Yp=opo(WB@zv+i-_yD0G21of3DBlwY zci7)!LZ(}5B+_9&W2@sDK1Aw>!PS4(I_y%Rqa=hFT<8S4d5pTr9QHAc@iW#udmQ$! zCTgdl_8X}&hy9yI?ROKkzo2$DOPnD=?y%3w)pSPDW~=FM8fL`c!(2AIs|aO_3xvWQ zb|~9gw-A*M`$BZ2a@o#%XvE-1mjJ0!wy2oxysc*ryOKgw5wGy&;M|m}5DH>&lv+Tk zku9nb3Uk;s6qITjl-h)X7#!sapwuM}?y&1BvTT{uBXz{!>W!e@fYiCeZV+AlDpE%b zuHGE#vDu<20WgOhn_WEqIqT4q4!fyB?*nHe0kL3g)m|XS)wsu7x_^ zGc6S!XN6u*LxUK6Xxf7-oGs$A#f`+p9d=m3iIb=|Dqw8kbRa&&;Cx-cmy|6M2#z`I zB!w+OA##SQE1@6;N9hifv}}<=D9mA}DJUr#lv@Y|F*wTYK6XQ_uHoT? zgct;=aDNQ_6~OVp8b?gbWsd{E3zjADJjZ^Nlo8F8ABXb9Z1EV0bEiE~o?VYA9AJ9U z_PV%+pCBAWGn}cwd5T!L+kOg@v(Q>Ek#74{n*i7FG$KGWBbbq`d!}6~_AH4Znu*Ou zcV|*}nd_d3@qX2scaQ6S-c)fO6z7s6bKY|`iZ7ZfE`;KOZ1EC_a`(MJuCSLBeYV10 zr6ET&8}c`Svp8G4PB`3wF9yVm*04(l{(5w*rG$lOhP4`4E3?IN!eTCbr9!n_p>l5A zC4_@$hVw3P)@O^ggu|TpdIe{#24^GTAe!N90nTP(;ck4hBF&b~2Sk8qM({BRJ|qI} z$Ulruu$>4H%?LgR!LDraDM2t-z6*!r>(=2YUHPX9mE&x_FvZvpjBm2Vo^0_IkuYce zjoi?CK*0CXR|=D}YQLo+LNptqBVap}Eq=%r2Z@cl^Fs>K4-)sF0>>88PsE65#&{Bp zC$hyc0%Q*Tgu-`Bp>l@oH^MfgJayj@jh&j%)59Zd(K$cC5g)SH&xDS_h4E?Ny?))*@C!GuHZGt(PM%Cs6L(>j8_I z!;;H^#SIjo7uwDp*Kh;ELJWj;&~@%@fYq9qm~(FpfMu4I@HqGDNg2^hIUdS4<%qT< z&Yk;BIqn0Jwh9NBmfOA=*Kn9{5Y2FI22KZJ;m*ASCTEScW+I*YJ2nBX;Z8(=XhzUE zN9Wv2#k!CfqM29Qqh6vGYh-QFodXAWuBc>1=cka^_q-hd&iUP+L z(zC>fXvX*g80X}O*#yX(`y7RDwnF6$**wBQG{ad4oCP`JCBk9OeSw1Wk_P8h!a+2{ zSqz-liG?}$*A-=FJufj;Tn5FZq{y86QYiXaueYhMh-Q6V1?3f_%$@rRMH*|d)PAfc z0z@-{jUd>NBi7}JcZh>K_YM45fpcGnS2kG(jdbqsL}%SZtcYf;AAxmSj`)B;xpUv< zHHRf1DC-5#Yi#F^YxrZrLJWlUx9i-01=ew5V$S_I0N%H(gvYs`BxOW1kr>%MSIQNRCikCpK5-Bq0UP+@^#Z<8- z6szZoswB#td-YuRyqN)8lCTiX zu$ls^ajs}YSj@RMR;U^&RL%{(8Q~zB;j{!!i(Jv1aF}y%q2M&v;0VG&G{b2FoYus` zoqKCVnk}2_i2%`zAPxjK5&?JaH%2FjCjvw>f=(dlm@C>71as~kbMg05tiw?{_x1{v z<8%^CF;an%oGZHKiq1sBoO`m|&|N{m_fltt$yv2&G(?DIL(~gwx8;gkbHy#h#-00Z z3ev3-_Z9_?Eu`MWh-k)`0mi<$q7MNw=iXQ0>!VOPLzYQ6h-Nr<0Vgk4E-bMGUUG8LFFd#k(ZT9s4GEp1rFufaieimvIfhPbi4NQ9cC9R^s4peJdv9khM-C z-TGl$9oO(jq>dO|eTUYmmkNDKLWseIK1VlqQ8$@O--R(gY|XRBrGH_f_BGUYlNxjA zyESTiOw{5=bX<#W6x+uKa{TbW9;~Zq~mM3Sw}Svp_kMD}E;w=E%<|D8Fk^&JhY? zaFh!`IZqtijh|O!*)oaAbKW;223Iei*Hx6wbKWy^CtfzsyB(SOMWl`xT)hg^E9Z%e z34poq%6a&kD%PPVUHHWck>gq}H9@EYgxYzcW}c`{6wHCw&U4>V*MvIXGu0IyXNA_K zp+O8jG*^MEVVAo&v_Et}*c;2Ip%5zUFx%mf)E4ZmzJ!Dn!mu z{fAHxgQK(oO6xpvEuk>i-C9ApR)caqp&$lFi37@w#K9c*jf$$XcH>RdIzX)*sWG?R z4r+dusU!6fF?b&nq1uU5xzp~X$YR}<+J_`kM+~l>4)xSLk(?*G5(9VHsr=Z0%TC5C z$E|}zy6mpeIlB`lVsOqoz}YKL+(wYxVfO+OGjt`lDeD8khir$9Yxqt=LJWcwwjFi> zkOmMBbJznQe$ui79)~@MR1t%#4uk5DJaG>RbB8@do>})O4B$Csdt6+@_Yw+XaFkI% z89^M}VUNIsoVC_Sq{BXEtK%BJpVSe9tB=XkJqs@tdXR(=g9{a+n`5b)%wdnk7@xD| z+2gPuF;ROIYDJ{R9CndLZGwr~6HuF!CyGgsJM2kvH5Dt`Y&AVe!;Bbwn5P3}TAr9f zDBNLB1HdV3sHMZ65*_IoLP89VGzUnt^TbR-Vh($@LNrq$a&F3V2?a4Y$^xLglqX&! z6y~sBQczyhpu9pTh`~`_2g+;2!5#K%iY!|uZ;(1-aP_yK{wAq&hy7-B^<|`v7+k#s z>Z|g^3Ibpbdle47^VXp!9rg-^$Z;uaOc34!!p1zYAy2F$3g)mk%1yfg>U__vQ+S*e zx|xOsG5FAI2iHe=Vq2d0fVjBB{z$>uCQ(07z}Uk1g!mAH^L+`v&-27Cf@2Q*bA@e} zLgWn9ZbCr}j*njY2 z0}lH%UU{Thq{IF#I_Fv9L=4VZCcmqQ$rt|+BzM>``5r@8@{h7U0DRVV*tmwv=F?9h zJ|B-E(vpoeMP?e0HdzL z0G?dt?T*FOB9Wl82)%iMyT`JU^ zgb;%ZwL~{tP&b*wZh9BJYBFCllH$fN*gu(gZ?tD=| z6wF}{mYeo&sPjEjpzt^=bQlc{V(_6E4X*q1#mIbdA8~PqeZPV;Qlj3cfU$-1KjK3S z&NmKxh52GE!7+zjsIZMyh@7D+A{4~nD3gFvoG&I23Uk=S3d#fx%HxEB7#w8^P$m-x zbJ&v=RcGx^HBoy8YEP3IbJ$Nq&CfE;pgtl7@8c|}K1ZtDVLzwHV%?S6huNf#7+n2j zsL#(A^YX=9V&D#YK0h|#u;<~G>DECapJC69&bfd%5rcCs0p}a}Vi7@dhy8}v(3LDw z)(3!}uq>W+4Zlf9i2oL8$ABK8*0#g`Wk6T)^8g=*{qun0qGv5T;CY69Y=GnI5reCq zg6hcu;sgnEhkbIugoF{j@&6?!6bA6jv^_4a;nReI7#!s+P|gqsci3kJ;P+syH4^Et zU$xb74WA=*#Ng`x4A433QlSeZgcw|?>_GfEy@5VI%N-hsU;nk{+2gRw4Kz@z2(^ny zjXCU#G-?-{s8xkpm4Tu%337*BWuUv7Dl6J-HB}qvENsN!!(0a_wFiotgu)$mZ2-)) zhFUu8n$eN!5)xu?q((q$Fi>1cNX%h3P>8Nnh@6}9RfK{V9Hlu>Vh4(*gu)zltb)>1 zgK`a_AO=Ud7AP%=gFEb&iY!|utwu6gR8fPdU&9SBLL>G z!vpb$46H*>I_x-w$Z;thOc1&Pq4PkII8byV3g)mo%T1dIb-rghDLl>!?M6d`7<_1M z1=lSDMfyOIN?hDw-=g58OVm^aj4hm=#D^H1uMha{94LAd9CO%rDr~(KB4?=nODKrJ zQF4HiHBe*_3Uk<53QC3sC6`bTgQE-p%3Z|49QIv`s#>M;BnaVNEI=->MKxvd7zk2!rWoMEYGa@3IlkS+a4F!@IpdC436>!P!Q67n3?-aP_wa>Kt~d&@vK23@)@1-CR!HWY4gdV~p2Z^Xzfh zt4!41fm#WvF^65EQCn-Gwh3zQ4ixK2kUQ*m@CreJ|ZN<;7FeVY3D$(gOHfR-l-7nP>7tH^5=wt7#w9UP`(~0b`uJ7 z*k3CsyEQ1^5DH>&l<$D@Epc#%{jDO)mdQaWIPBPeA?H zKyj1+n8QAXLvN#X=t+ltR3UO)%C9B}XMu2Lp!j{DI7Jl9VV{wk_IIfBJ#$LoaaQO# z8XCmlLsPZ@4<^+}C6?D|mivrLVskBGth*c7UbNtHY7#)>S~U8#L&M(T*c)vtwm%L37&Kr|-? z?yy@Huww%by9Hi(-#SR7!)_j(vlVe72Iq_e=Zyv827=@c`$ix!LsxQxvOWO3&UV)Q=SOr#|p%wB+i}oV+HQh$43fNOXP5g?ioOfS$m?ozR5NDR?T zY$m$tq#a#Gug=(2X z<=nVe5e}jm&U)aiEf8x6hdJ@J3eFl0&IZCkG{e~poK3{S-S{R&nk}36i2%`z;6o5> zB?9iqw?-%UhzJnP2zG(s(*p4cK`>YTDGtXUtiw^d@=p{h$Ju;lit!CF_7sS(3dEO0 z!kqaYxuL%T0pCksDooC*-A6-&Xf{NL!1hCdI9MPK5F2;rKPX5CCGG(QjxD6a#E59d zcmj;a3dB(YWDfn9!go}ma)#_z!a+2{IRl*E3&bhHVJ`i51?Q9o=TE{xG{ZR$oWF>L zIrYC3WoJGAW2#tYP*)K%$a%ZO+9{Rq)CY>!6XYy>fKc8pMid###@omk$zk2$Vbb z%YntrVM!feaRUYD1GaO=HGCyuA^uyey>)toYWE1$x;+N*_L$hCgYk=Bqr{X^V)7_^ z8TANV7W>So>x+wuE{SPl{da-WdW7o4K3n?A-_7t!-5#OKV`r7VILCUi9tvY?3|(hc z#T1sW855Ikx8O9^Fz%I6F_!F=vB`<+##JaAQ&b zUyO0TsBC?a4xRc=YJ#m3o<0g~Ht1FM8Z_S{bQMrbo*8BR)AhxV)Qq{hxM*T5C~WE` zv4b<$p^=!vOQ2jb8EKPat+eJydpfo?e!;g10QNUYx2YP%Ep&*RmOP8pzni%&PLGXU z&>h`;yKzk6Wz@~L8@t_n)#7Lto;NDy8vD!G*iU*ms+UuL%b+JUlr|y%c4NrD-8en| zHLH!Q?KbQ$TcCe{=@DufJ9AX*@nH~OgE4MW+6@%Wi?zmkjWuH;_Qhe2W~`Mm6ZmVa zuB~Z8gM+V6Q8ydLEwWm^)>gB>Y!y56UsS(tRkyaQ?JwKJ?i>uhg|RV(EvUoR1V?r_ z4&(j0HQozj0kSYQ-5t9(thTPV+p@pBL20W-VPVfuOv#i{n8$LSW;^McU2HXbqus3i zWgOOSY?XUKIj31n;k9fOC)=ZFFX;G^Ss1uEn0IS8G>m_9R7~s!8ky^?BIlpcg*naG zxW+HR!@2qnbU9_nnbu!ZRC1vH82#==Nc_fAr;GQC3ASlg&Zw_Y*53NPS) zWkc)Y8peb|RYIZAnz)$z?v5!g8&kGi#h4IwZMB$~DrGJz8`>;WHpayiOXQwUc?;TfH4n+D(cGXNQGMQ%DSi#?>mas zbd6ml8*AWSd8Mjxg|4v{vazfE8*8SkY$GdM`Bw^EWgIGr&EXN=lSj>lTkqH*BOMcLTin*iP@a916yh6aJ|6P4+r!O&RHls6r92^}CjyuqC6DQ9rpubC z-Zj+O9{;Cwm2+g}EdR>qbd?Ka<$V9jdAiEiW#y~7l(%Hc5?x9OQk>CV>ANUzwL89C zSN@(-~GQR@c~e+1Q8vm0MMfExN|Ol#PAn-`GxF<$hVY*T3>>UF8p`bO!S~ zUCK|g@k5>zxz~=%l%u+oKV{1AQD*Iw?@`jzp3#%Krptug+s_5vo(+Z0d#dHmyi8Wt z4D*{;FL(3Smnm0-mAg+}T~!lV)hO(9!u4@mZ%%pkQ6lh-GaoHH?f%!zZzEG$=~CjQ z^o;;!N68Jkngm(XG3>dYmbG0;dtGI!tnB7r*+o}*o2=~NU)fz(`G2yqw=N}9ru5aN z^hb&_+Ie9=SJKyBcsaWAVNzkRx-Rba?@@uSvH!`&?)R@8scPJ(Yph5%R_Nc@SY74g zva;B}a)PdMDk`19oUBWkAsc_%lOp%pY?<<$E@gpCnIC1==2@FgaV7oi8J(+Z`c2vN z8@fFk3N7+f%bodHJNF?m2Ft63&%-fZW4lq}X&z9TDF`&X{iRlX-H-}SFt zudCc9E4S!UcF2^Ebt$`%;*9p^?fj0CTzlc|(v^QF751y^;v4@S?a?)MR5o_Rzw(f( z@q@0h)3ULX{*9f`RsJn2&-z!M(N&gd?+)e#T}lO{I1dxbwb$&mOJvH$x|GXgO3n8A zS*zaO?_TT`BWl(fY+&f;$4X?LibAC@UM=~5D;bVmTQqolpACPmhC?dUm5 z2HGRoSyy?RtnA@m* z15#n6x-RbX@6o-w#>UCU9`>(%NYxmlYwU5^Sh0U&6LghN%gQPKm6LUqGg0Xb<_ulR zT-o?+Pm0`YFUgd7x|GE-Wl@w_d)3->iYpmq&*&?qQQaU5W8IXj8n4u#_MD*7=j&Al; zzT}QmnygIruk5O;yiHd2@UQHytGrWosFx>2PG6>Myf23Ho|p+`=y`kNP^gctsJ|@A zL($Njd+v!?Q;Y5S%huK2FPTPoSK~6fa+r5Du5gENtdt$&X?>NO@~CWm9A6#l?6wPa zbx+E=Nxbe&yRKMQ_l&HY=2tgGS2tVMJ*P{VCsXF=QWhe`S&c9IuZ;Pg$_?%~Es>S4 z`&YiEt6U)~m-$yN)m5&M9a`l{k<+(PHohLi$yeiAUC}mKv;{?;)ws!?zxQ;tKS`!T z-qpC(t~}^njUTx~_^XsX=4pMqn{r0Bewwe2&+N8;)74#&b$|1^_wBlKy1EL9?nz%R zk)6d(U719FhD**WvaXUYrG`wYs!O>XDb8xVEYbIDtmUcv${nXhva-H^Wj$Tx)v~gw ze`RA`WlPziYdk4(Sgx0ix5jYt)p)J0sGTf|Ly>1S?zQKyt*-V{$+SI@oBsXoQ0A&f0wRmpRC%G=wtd1xvd|hJp1N<7~eSa`Gcq3!*2dBGUX>-$|))RD}b5lKd!6! zOV<3E=rR2V>=FD!S6ME}-2tH_-^vTR%1dPB#r~BQlK7O!L8u`stLjqf%9Pr=ltxH# zM!SBJpXvYE?sz?2c?+pYkBx(|FxUyKaiEZjP**5*f#5mcFLkpP~^F>l|zq1 zp^tR6KX-GF<-^_hDO$lDs*^J1csJz$`$boEMpm8f=Cetvx~>0BdG-PiCA;(akEh*g zZvI6wrED?>mMK+`;yi$?l-kq+uB(idl}-FB zuhLbvl$F=$QrgIrR=SihQk>m$Q?lQUt)|`awz~4pQXv7u?D>hXoBey#LD$$VvavM( z$`nQeqdiZj}$d>3U4yW=NyO0uyEDW0R;8UOMr%5haTh2Kl$8mTE8tLER>rMk*`va+s!3ct5E3- zW&>SHtZclACq?eH|Hzc)x|FsurA><84ZxYT)+v5R$+h;3UaM>RX4!OmtK55(SbH`U z3VW*MsAtRS3{T2+D75$Y0GX1nPG_#JYOt&tA^RjZLf912f%K5VL1zpOk zGG&1-Whqje(O&GkC_C95e_dC;Mk=gQ*To9|9=)w=Y_n`^qkrWFRb!p5vF)<45B(e4 zs;m4$R_^kz{8U%D7nROnex*w}ARFK3Ns)W)N11X^mvTa;{1Ro>e)c^|I@>dPMA!6L z+4LW}JsS$0_EgKAc}c2!Yq>a;pYh$?&0ABZR7+Lv443MvE|*o8rTUz3x45l0pgj91 zX@YN@`Do;6w}+eGT&6VBrL>aLEdk7qk`}s}n`F%msh+!HvOWH7bd{ZCWe5MtcDl-B zS=q(EGD%l?i>yr3rSy_1J#{Jlkm8JXpH#p5+iiBo@6?s|mkN36y2$bGQI@W;VY0Eo z{*`yD8U?z>M$5)V`8PH~SNVvn9P3~Cpsw;UR62t>UYGKOYJ^@pKJMn-AXC<=)44`h^}ejy z(Zqf3cNbMF!7btx5*;*56rG{2)H-|l$XG=7VbGf_h- zR83QEF;&t$2eLDYm356>DI2@ozp{?1QCrtoGuc>U|Hc~WDut|U;a}NYS9v`uoxyCa zONo<>xAmmRz1Bgdgmo$1WJ>2KvzD0Vca#jYXS9>9>7KIbTdZ>L8ysuThC=C{YPlZ9 z%IYzml)F)A@9#%t$~bj83w2eG%c^2Otch;xQz*}tdIsM(^D)iS?j$#VmP~n8m-3>N zo(o{+N}ku%ye4a2@vfo4_6WYLt6U~4-}J9stgBojD_8kfuFzG!D=XLOQntvH_jDB_&73SX$};xqpq?bJ1PP&W3hf8{<^W3R5Uqq4Ch{*4{dRi2WS zzxr1m*HxZHr8Ag+=u-ZXjsN9Ik$bIdx_bkNN#`fHOsOJMDy93~0GwH?nC^F!Otok9 zB3;vUWYe{*a_>=M?b%SMhNoKY%qg<^Nl(gj6x#dyS(!3DUAg;A(^bupRkQrCX1T4; zr#xF~A--|u<7H2~v)%kRWXfy0l((hyQUJ4~WQnfk9a*zF-E%)3W{==XUFBw3xzWFJ zgRb&pS-H)>@&jGvE?K!lm-3ZN`9ha+04dIB@AF-hbM21r)s_D&6%MQG;z$1;eXncm zv~298f8_~Pqt1RE$-O6RU`!0i+?tF*Kby*pe&R|y5rBsuRSMj9C zy;fVM)X=3glqpws_d80QS-YaU-%&E(p3%CxrmvAr$6Dpyqr}>?p-@v#wH$%F`nhA5 z+m8>@0uZvPFR~xc~-K*p3!5vrvH&m z|E1frq0m`RwcMH2Gu)%((hPo-tadkVU71olLpe%n>Z%&Zs(KkdN6EWx>rE)nK1!P7 z8)rV6dD`9R<_nq9LYH!bl)etY>?moat7$K5;xjx)$r^k7Z_-tEk(G)5m7R2z-DPE} ze`T_+@^)Eyt1hLFOu0jsl7kdyv@A~RW?4^lOp%p44Lw@E@hrfnG>DYSh;?CS+qR{2Obot86PP+xSXDcr8Agux|B|` z@eZC8x!1bLltf)h51Eo4W!6$N{f?5o_KYU$n(iZ;zQZc_zQM8fY$(*rQ!SU%5Ltb< zCuKhh?fpGcrVLl7bC|AbjI4UV59^TIdLiZ6Qjg*rXFkSx+CA*%Pm(E*=~AXj>B#_Q zuH*?_%}iM{!@GtK*dsVyS2Rxb3fT%fC5Dk~T3QdY{8w{ZT@ zJHCtZXS?Giy7H}3;eB;oyyxGejk?Bm$;Nj0S8i7|KGHR|S2p&Qe`8neXjr8Ag^bScMW<3~Lya<83|DZlDc&dZc@QD*H=-=pNXJ)?iD9VD8w#!TRLhI9Ln|_B^TM_e?eDSMOIew zudJBOk8#QS zTBc0tt4kRuQ|^i~YkApzN6D4;jOOT?9xj_6YL$E6;8=S$6dLTQmdp83Sv}5^(h!CA z{(eHHOjM`yFmAs^@ zSt@H5d)Lra_6WYNt1OX~EBz~%>nb-hmg>Te#vB$qhU+EhANj7%Kzw!rF9fE~PwDoL@67lf&;Wa<5gADHU`nwPZ^59KRcYGiz0I{Em`V_Ka51HQhiqUC%1_ z9wpYE4TUcERLh-ty{vBSNoj*Zdw+*z%1t@S-KVXts*|kh;D;4?rA}tI3o#eRDjnXJup4{VS)b8dG$Q z&6ADI@o#LluJTn`xxl~jC0*qbR62wCx-R8y+4xdVirj0fWy%U&$|jkzA210_8w!2ksg^tQq^v&fN$KKl-alo^@9K1((pCKA$dpRDlv>neC{#VybCguo)m$lSF3T9*zbY3-V*;sS`#$t7q*UQS* z{*~A2D&tY<4Calxl#a6TcAgZu*OFvPCtXT+nUWf1){^u5j*=nvjCR#EeWz@?msRdP zN~}E_3f<Q zHwmPWLLzBby9Q~3Nx@hUZrm^=U?-FWjEO_QfD_uKrQ8$)22Ah0_ui}Nz4sb=@4a{U z-`)LotXn zW*bFj1S_%#MYPdg5HKnKP&+;^SoJlA!b)>qEDzkHrNJ88W;C`raLtWojrGAA+ix_s zCvaoCg4H}`)I1!x=D}b!&!DC@m?wi3xo9+g&aa4ZuU#{WTn<*`fl=gc9@-d+Jx)xHI20Y8S4@Z(dobsNUa2jUw;VGc6@Wg4Gg? zTJ}I#UG>%@sGKUr@ITso6!&Yln_m7SqezKhMWPMqQUK=>|)f+4qUTCu$sM4Qya|g z!HV=Z8t>y*#JJan7)1sKD>BX~GCGf08>!rMrZ7L?U^LxMsqX&*N4aOi!rJ)NHtx)kM(tsKMP{R-dVfza zii|Z+=jdRyrWv&+2f|vaw?3Q7sZtB@KiYiE^=o&TUVe#DBqvyr)rRy6|D|MEusWNK zIvf0RXs$Yf>w?wXW7OOkxaRg?H4hs#4+O5cKUmF^M$Kcvikvr!oC#LsI*MqceI;O0 zu2egIDOmM~hQd8_Ufc=Xqg%lm3(wG(|F8_drCb~TXJ(Bj!5VwnXzZoHjr}Ww->8i2 zdc&w$C~(bJgVlT&HMPMk60C^bXuPOj5#wHS8AY7Iij**lcrpTQ0NSh-&j_@XtW{?; zB3RSWM$@H~>i$cKa?gf^ed1T!7`t{x?M%NS8&FZbzdIX6I%b%5pZ39O^)zaA3xsuC zZ@nLtQ>6yuf3*1+;MeX6z5EEH$k1R##v9UO0L;C>85OL~bfeA`{~X$+j^LzVH5V8) z=LW7hJ6O%-M$ILGYc2{_bFEQxRj?wPjUpR@71@m<+Gy_xn3Sj0j&BQA{fMD((3}^4 z2kz0nV2zzK8ao}h=1H^0@nDTzHyXPVxUoyYYTh?$-U(duREhXpG87&a3>GzDL-&U&oFD1%78y5DK zUv1;g?A!VSTmG>8`9`+3r8jS`emlPP`>2sW-vlk@pGa{MJwKV^6pB+RPNO)T;tVC` z%b#zi`u{J7g@yHQZEN;Z`ma8J3~ZQ6*R!>)UY%cCa5sJT*0$z81^-=GS=hqz4QOrq zB|~{WEc{=#Fk9whrGb3?P&i%vBV+Wm`eFBcgQ3^z2U4V;sEYXpp&9&vH=`Nlw|`&G z|8oB43))^%|FD0#T>M!Zd zoBom-pWfo9mQ9rF)9Yuj#&ue>OmCi=5dS5sSTXgNQlF$&NpF;1r$u^d z(;t3JO>UOnq(zHHl`?+t`S!zR^?tD3yivsV!W+dqI=VPIIX1}i9g7?b9XI9Gj=hd8 zjvbC|j^*-w$79Ds$8m~IUQ!RKlRQ}JCm)kW$WNpZ5t+}0*=+d>6&6~yYFF@j z!AyHwdzQVuy|cZKeVBcueT;p)eWHD`eY$<7eSv+EeTjXQeT{vi{ha-t{fWIJy4c0h z!_nK(-!afJ%rVk2&N0a`A01xgSdH#(Lx=Y|jybM5?xVwx9obH;yK~eIUvoZIJDnpe z61E6Og=4}w;ihm)cr0k0pChhAw>P2l$Hbdrd)Gj8dZ=p{I!RzD>x%1^>#pm8>#^&J>!~YKYAa<)?WK-Vw$w@LB6XFzN!>93y`(-;U#XweUm7S4 zk_Jn|q><8SX^b>Z8ZS+dCP|Z}Dbh4)x-?UoCC!%RO7o=!(n2XmS|lx%R!A$QRnlr{ zgS1)NB5jj)NPkNQq(jm%>7;a8IxC%*E=#whyV3*cq4Y?4EIpB)N^Rv1awoZ~++FS| z_mX?d{p5l2V0nlXSbicu zm7mF(5p5%~B05H7M|6(p645oHTSWJW9uYkwdPVe(=o>LGVsOOJh+z>UBHqrtoZn`f zhnb#lpNF}gZ(oRO4z7!EU98UiV*65Lz%pEyMTl~L#gv9bpfR=qSPgnx{Oj+Q0gj5 zT|=qsD0Ks+ZlcsJl)8;lcTnmsO5H=L`zZAQr5>WxBYQ9VW0ZV?l21|c8A@h4?%LZp z?%CTq?%Ufr9@w)S5AE$8kL(>Bk8x)_v1dD;+B-R(**iNjahJ4lbaiCfyW!E@(H8ei zJ4a7PmZO)WJ?@?kjy{f#j=qj;M?c(A{T-bh15jfiY7BC8a}0KLcML&|p{OwoHHM?c z2-Fyf8lzBSG-`}Njj^aP4mHN3#stT7`$W{5gj$nPYYJ*jMXhP5HQmwQKEpA0;EId2L5owtPn&O5?D=Urit^PVu+d0!afd>{;UJ`{#I9|^;qkA)G=6^@a3jB-8^ zMmwJhW1P=~vCd3!oU@HM-q}{1;A|&ObY_W@obAQQ&JN-fXGd|WGh3YI>?BTib{1zi zyNENLUBy|>ZsKfbcX5uhhd9^SQ=I4QCC_5 z=Rk3pbC9^)Iaplb93rlC4i#59hl#75!^Jhu5#n0sNO7HWl(^nGTHJs(H=>(1%o4SatSk6U=$#^Vkick#G~$9+5=;PDWTM|eDT&JdqCXNpgqv&3i4 z*AE!hErVut4l6EEKba9I=zINbD>u7P|;b#IC|pv74|= z>@F-9dk8DUp2AA8m#|9gEvy#%2y4W?!dkJPuukkRtQQ9e8^nRaMsbj^NgOO}7KaF1 z#G%4gahR}894>4ZM+iH_k-|=Kl(0)2E$kM@2n*d~g&g-dVUc^hu-H98SmK^2EOk#3 zmboVj%iU9i74E6RO7}Ejm3z9d+C4*9fd%m#Q zy+GLFUMOsJ=Lp-}i-hg&#ljBv5@Dx%sj$nvOxW#SF6?oy5caxP3j5rvg#GT-!r$&S z!U6YM;h=k+aLB!0IPBga9C2?Hj=DDq$K0ER+md!KO0yJ|J9m9~7>+4++=ZhlNWKM}!;hqry%1 zG2xc`xNzHjLb&5TDcp6R67IQA3-{e;ga_`k!bA5t;c~=z;gS1-@YsD(c;db!Jau0d zp1H3GnVzdc8_zYNt>?PX&T~V^^4t{Kdu|CGJhz38o;yOe=dRGnb5H2(xi56_JP^8i z9tzz&kA&`?$3hR!6QQT)snE;wOz7>&6#IDEhEo=_C&EbQXttx`@L(UB%&^ZsJ(6J03m65uTpnNKY?ul&7~i+S5lI-&meJX6xC~=l&v^d){ zMx5grE6(+d6X$uxi}O7b#08#-;zG|PF~>7mT;!P|F7`|nmw2X$OFh%YWu6)0a?eb0 zg=dzy(lc9J<(VU{_RJO6c;<;~J@dtNo(1B1&q8s7Cr8}qStM@qEEYF=mWW$COU138 zW#Tr^a&fz7g}B4BQrziTCGPU97I%Brh=2K6c8bS6yTlWo-Qr2l9`TfCuXx(CPdwwp3sp^IQ<`doGF(JeS0Wp3CAR&lT~p=c@R`b4`5exh_8Q+z>O_O|cETCAMX^ z#dhqDn8ogj?b$uC1G_JFWDmq__E7A^9*LdVW3dZ+B6ej@#cu4G*qvp%dayRGo~*5_ z7i;J0&9Yp5SbJAr*1^?}b#(P-*{%VslWQRB>>9+nxCXPXt|6?OYbfjP8pe9KhO?fo z5v-SMB+c%J2DrwvfvyQ`kZU3v?3%=exF)lqu7lz**CBDZ zYYH3Tn#xAHCWxc(810(I#<-@lv91|xoNFc<@0!IXxMs77t~qRyYc8AYn#ZQN=Ci4; z1#FsYA)D^XVKZEd*i6@AHp{hy&2}wib6m^VT-S0o&$WWhcdcX#@L1?t#d2J$*&^2( zw%E0nEpe@5OI_>PGS>#S+_jOdaBX5MU7Oh|*A}+gwUw=LZDVU)+u1tT4z}L4lWlPA zVjEq%*(TQ>w%N6pZE@{mTV4CvHrL;5yXyek;X256x(=~juET7%>j>N9I?DFCjDaE) znb>a9#mMf`rN|!A(4?Nyu%uqn@TA_-+2}sfyqLbykjQ@0RCj-AntOn>D0-l@IC_w@ zBzmxPHEM`-Eo!KAJ!+VABWgGvBcu^YBc+i^qoh$uqovVFW27-jW2Lc44|5Hw4QC1)<^@T zU;9z1pZ%D$CGxnmHS&bCE%KzaJ@OPDr=_W$Gg5#1S!p{vC+&zlFYS!HfX78?fc=uR zC+f1aH|mNstJqaMu1Wi%u1ou)Zs2iK`a9~DbRg0s1T=}^=&>2Or0yzs*|@`?}J%15Hw$w#BIOHu806YfD7d?aIE761Hu55_Bz%x|7Aqajd{& zrF_P|N?z_+EnkdUBVUSIi^n>7gnd2AY>=NiHsY~K9%bJwkG5}-d$O(a82dK)a@2PD zO4JTKcFLPPyW~yo-O$}5AC25AAB)_F$A0;W@V7kHen1{)KPZp49|GH9JdVg$qmRnh z-N)o7?&I=9_X+uIpV19`grp?t*s zNIvU%EN}BXkq6tK%IneoPXie4Q0aq zRKDfDKCGM3NUYyLeJ&ra`NP^NMY%7vOoK-1b2u|V8N0+4!2hUaGMcDQhpS~w&1hxP ze^JXQhjRJDGJo(drMA=JSGCOZYMDRVssH11QOn@yP5F8OkNjb`aG=P4DGV=_C|UC3 zQXkokuacieM@L0{@@cfsbIK1(Mn;w@RSNOr(jP^aRG#_%C7bQpvoKq|4w)lT(n>#_ zQ*hjYDV3)V**D)QRb5s1y?nO91z)f!KfCr$J{$hNtNP_T;K~!qaC`iF_|mJ|K+vEo z<=UXkWWREs+g|4l3Jl@iwffMy+)0k_BR2;TK?KB zy|0+e-_+SJM>Mh+x*vNEt{tP@@ZtWdP%GI5k3>n>NRa)V<{On_O0y`Tx!@D z&V!pb!%vbM;DH|||L~EGB~-w7mE&zJ@mCuwpV2b;habzg!e^oB`}jI7>)`vQ{|`^7 z6;Oo{2iIu1-v7gvbC1E*vu~Ez;^U8^N|i?czN(i|r$OabEs zPr{ySj*0jP>09{S%mx3o{e@&M^3BUwtBMp?R;(h*(XeZt?_b>IiLQ_irU-v?v zwTvcp8?~y3<9nLL7Io^Uw`f_X?oS^!w7nX(pvQmvc)BjEf8wntQ}0ALJ}DG$T|vte zwfV>s39D~ZQ#z|xD{+>G zs7{L}CDq1@>?^rvRHgh2<-3Q5Ox^s_nL>-dv)s6P%eJont13|TUW8oj?(ZF^CZ-g* z{6d$%3Z1BHS)kcZbz4NKt!GUbviHpT$jCP9tNxPFZT#gz7p#wsg0D8-@|{k1+I&4Y zrG4>lhrjyCi>C`6dg~vf2VQPp4GaHok9#E+cW5|na@XeE%NJHP@(VoqB1Fn%1q;GNWme+_sdrE}tlEJ^wx0T7#GC8F(5@wTekz|7?I*3HuDW;AP<-aIX%N&Tj2 zEn4E||I+JjF$>TKeQlWq^g_G6u@#e1tAS>c3fLyrGkRVnA+F+AX%&;oC#U(a71XOX zsG-s)#Z*p6OGv6#r6!sguft`;sB0FG()7WOGrF)y7uymGv4k3FaWR!D#m2;a2^|CR zWnJfNUG?rrYmw2Q3D?sR+H@4Ky4z#za@Dkf#0F__i-7IcLk91cdIG zrtnT&Hq_5(QZEggWQVYDH8&$rtcN4qJ_+%v&NwDsS%1*m<{3>Iq_wQ`L!)$U zHs03;B>WM_f{m_ai!|&QHl1fAgnB7F-*Y@o(tl2C(yCD-BfW~ETyGWVT3szat5!@* zN~oev6Z%DC626wx!wTQDxzVYCXrqs!HG$J=(X@F>gU60CeN~-z%Aw;(65qLbL+|&L zfZ5_RLT~CNPu6bMJfn4;mg#Bu?0_~lMYNxVH{meqrKcmSkq1VfW5F_5;gz{1piVty z1!($Ht7b;YtC;yADs^TVP`7THQP21O{SXb|D|{3usH{wN8#hZ+@4f7BZ7HaTqC?e| z4%JeVt6G)nRjXlu3+hR?T)Q=^Csq6=p-R=5N=9}YH)!*8EpgMEsB30=J+0ezeMrt3 zDWx{ge8$=e@?PR z!;Jd53uJM~O;qJ3#j6XG*6FlrF|m~rFgTR$1#Ca1=O!l>hi?)pVHH4u;yT3A&-G;i zw`P1Y?*Fv%)sx~-M4zM^Tn0B#wvVPiH^GeK7fm|k({9gU;F+q;Qto<_P^Aj?9A&jk zi;t-mgC=*N7`_VF+9ayf)oQ9RZS}?K6)%!S=ZUS9jD^T2g$byD?X=%~`IKRLzls}W ze3r})^`CC8sV^c4HL76?s+gSQt5iZS_k3<|bSxviy6ByWsjW8_SEZ6~@Hl4=jJLcq`qTNN^fL|)|+ajN}79GRNH})W4}m3wRUZ_gKH_2Zn#QP3{S1)xpPA?TxDKWWvn8%a;1crB%2Ke2DfQ#T0Ihy;?m-hk(Noyn3mHkt<}@2d};GcyrRtnZV6QRSRaAT ziNH4QeP8O&^;RGF^~`7KjM2+9qT8TeMgzQ9)lw-@|6%jEMh(*{Csa@zP(npXH-ZtYdAyRr7_j%6I0+^#m+G{6#KWa(Er{s-E`Xl57OY5Ev6 zGFA5>`kIKo=6ctpRb!)T$`-gwYKz>b(G}N`W=Z1KJ#2nFVNiohVfYw ztLuesX|t-_mgtT#rR@yo5vb+ESlQG3b|@oZzSWz4J=b#?%VJIahplq&jw&_3Qtk}H zQT$;1$k=gdTQ6YiW14s$z7)Ojg4!(AY1E)81_8HYW}Nn;@U2`Nn=A4bC0(Yv|IXIF}; zS^@QcCcHr$UbCjT239dxCsn#K#=5WV?nWNe)!Y9s)*EF{#6pBs2hBg$nlE5$5%@+h z5bNnptTC3K>eckc)OYPk*9)GZ7aJ9;R;`XbGA1cLtt!SQMpvLn{;B zo$q<877dO2Sb3>+5nT^I%q1E=gWNnL9q*Fp+kStPyQGw>#Z^*yR44m z`aoUu$^6DT{kuj%ZiV$-ADZZ8SH$|fXvGj5(?@<=0E6cv)>LocOC$Hx704JT!?FCD zqOWB!)!=1gt5-|#otS2NL#+dp^I5F^tCuTewzxiA#==)X&3p9drtUwIb?2wN`lgo( zEwom{v$z>hUORKMc}JZ9hjuH`AxGteY88^>A#h2*m*#tYUplKxj$sok7{gSx8jc50 zjo!?`@rkw@8n>=dr!EIvr%Ao^Cfw^B<0VL84UF6l+P3RRzXu#t%tO#DPFoPJ>1nyq-){Ttu)ok`?&og1diZpG%iQ}(x#=FL(^)W3A{p?% z>F{sqJD88s|MVYT@+N%q6eB6gIBs44G zo46^)*^;rS{sGo@U=7E=52t!n{YFQY|^Ryfzgor=TQ<{5PwX?GEAE8)Kd7-xf90Cxw4yAM~YRTJ&p z!uJ@jqe}jPkvytL^jQP5b*^S9>IfL?F1mM2zxN&+yR!Of%qO`!>D8BNb5t?rQ}d0P z9*xn_?U9~!J`Bdo!JV~!QI5`AHgBcB%rMTK${7fXG4LVitP`XKRx#3{i(c@QdLL?c z2zr@cf4;poy?DxasoyM+rSK8&s@Hwne}E0yZhDcG#!laS<+BD;Gjsq~!Lhqh`_r$I0`+FQ-5*@16j zAA~+SYDfOHs87fH66IC?K5f-FEu&?6W4z1ZbL`bmm3>3o!<1acY~|=_Iw!zr_~;l3 zFe5OvPtpE5b)>Ol`Q+;W{ihrK-)r#c_&~kTCG74cB`AieGg zb0K3t9;_GY=0CDVks*4K1$1|6XI&UG!#9Y5lg+2ML-j_6`osA2c9>phv5);vtAG~( zbSO1kFHnPw3XX@dKH`niCUl};9CS=G>`(4{C-GSE@KwN8+4v!b&j-Lbu6z{u7{;eV zBQ%uovE1TW&*wnBEYwD-nf4xkU;7A-qE>csSxW~Hx@+%^hDNIm{Sat%@@bB4)dIFR zjAg>#kQ+AlwFG6yGxDa3@7sI^**Kl-fw5fszmYaxD}s+Q*H4x*lo%7 z%%`^Gk6*4`2=9Nr_pkh}%$W+(zwul7uO#Q2QaU*-a{&IoD*ls}lrGN}m9CWh8ovL! z^wJJ7Ep3_4VK{RZmCkOLZTDoiYiqYvSFV*}lplJRmbO*PS1qgXHa#eG2( z4_H+^2E`+#*&!1BP0uh<>E{t6!w#ABxePl_Lyl-|$j<@iOlfwCaQ@P9WCiC8Ag&jL zaCddsyW4Y4<&AZoun?_bT?f|H((E!}b*Dw3m_l{cM0MFjr7a6L2nW#`&VAtAEzNEd zP9I;KyC$65L2w=r4x%-jr@(nkEQ9nJb1P%>*d)!R%`+lEv_=pfU7qEO)>el896`Ql z|67$KcrIF7sS&La6a>Lb(d=IY(U5N5lFBH&6rG(lS6LkAsf*)ud(OX1RN4aavQ>;X zf$@4YD-_LMC6ZQ@9HkYK*Q50qgeuRG|@TY6po7gvNF$} zlZa>5D+|pEb)i{d&q>IewGy!+T4Sva)~eC$YXThwP{j&nexZO?1r}!xbG|m^3!n!p zc2T){zacEdkgx{o&b=Y9>Jt;^-0K5itK#7NoO=c-BU)2#3gyPp>?acEoqJlNtAc)os10Y zXwv60tSb#UqO~FK1DsybtOw!n&b=2P)+obnIQJfTWA!C0L~B?>fi*aq4J0hixeqo` z4Kz_{8~QN9L9~W57C57$*+|0Socm}K&d4A*;|K@Q8qQ?kOe7ZGxlc4nb7?b$2oS9i z%ml%7BH*3-^t=gX5doq#f`uTMAI;_x1n1o6V{zP}ERKeApKGGhoKB8aj8(u`5zUrG zvn52rIrkOD4ZREm{Jpfq#H3~IY8oO$YeTdJY@4FlhG@2q*m&o@$%M4Qz+Gp8;}U5r zF(O)H+zZCt(QGFHa?X9XiEpQgN*l6$go9`e=Lm2PMY98h!#VduCY%F7aE=lVqBWdT zz&SxIoO3^6Qr7bMv{l9PP&`YDoO3@5#X#2U0`(QqT3@d~`4TDf&i#@}8o8KjKdur1 zqBVkhAh;9FZbh>j#KAlFJN&W&=Y9*%>{J#S!@1wcoAo}iB3fe&^Ok4NqS+Gy<(>O8 ze{-1g#FQ_9-ljTtT)p|c+Ib3MNLV9u=l%w;3VQ>bxfk|kx7(vw2|wrlCMhFYQ+^N1 z?|4}e66c-!J6`<&rHGkBJ)8FyB@jewAWneTiGug+c5imp0VP{}J^Mk`v*YR&hyc+V zf$RlArNDR@Mm=6ia#8 zCnU;y_EJV}ePYtb`zUzd#~V$9jc9GKKLF$9EY4X7f3 z61^;efH}5ZBSq3q1uDr2v%l-rc{+`J&F=-aF84V7iwZZunY(INhD=%w7Y`iP~ z*@V=}z-?iM)6(WQqC>Ps*A{e{UiK%Uaeh40ME0kdN4=rj5e}j?oX)_>_OcFy!};-S z6HbR9I9&(_(Hc%q;B+Sz&X0FDDQlVB%c^2ODE1*m&X4zjVjx4+pZbbut*?WjJdl)m zKR(bTja@$1S_~lqL~8_NK``3OMta$B;^6)GXniSx6Ca814=c+GPS1zu%{Pwt5Uue| z2j5gLn@n)L2cPP1_Hrhhas*cJfa<|<_0AwH#D9tvkI%h)r+((8Lz(g{t4sj@omD2g z-LU}vyJH#6`6Gs|+6}5*%CJr(%zN)HWpwY|$;_awUfl@-F?5JNfapa8yzlN+COhl6 zzwbVw`fgmkeMucLboGH{f_d&-p+O{s7`o6fbaM!Glk?j{FuErK`0e3V)J8*XB&l&; zdt?x`F;>(jL2W`AHjV^&pFP3Iqj4r}^4XJVfDuC<;8}o}QHD(;2;O7QfHdzHrUiqU zO)!X|!z=>K!ZK_=!EpY1p^0U_nMK`>7ZVC%=qRgzvZ4%IMkt)OUSUF676fHAp&*8i zvH>XTh=cdl>&&v+60?zX5kuGA2Hh>B%X{iA!F0EiE@J4q`=Gn04BJK0oS)u<#qA{d z>0KrY&4ui@B7Pj=N6WCoW!OQ|=e+b$fO_Gw?6tD&6=LB1a^bSHRKPF4hVM_2 zUw$QTwl|3lF?6;Mz*e*@dzZj?uUr%`oI%TZ7f8IBfmc4RdSzU_c0xk@r%2mA!)L@F z+vqdmMaz|E@0JVTm)|Xy-R^7vzx;kVElm)uDT`2cmSc7j=RLEtobH+JCJyAydDXk( z>U9wgqBWf2z=<3Zm$>s`xn+%avngNtAcf<%|p~YtrX3EQW?0(b|w# z08aUGES_+9UtJy$=apeMK4}u4H&#W$LbQhUHL#M)vC4$SIqYN;Rb>;E=4h%A4x%-j zn!x$C9IH+^oXh^!gi}2TP72{5TEj^LPHkf0opx=LG?zBt69J+%f^-nnB?8`a*Ug)t zJ`o^VBWMhQpUSZeg5ccuPgoppDvP7>Ns|l{mF8xeSjG4m7_G{&7UkG~iG=gvt&AJG z1qk?i>Axl>Eo*wWL0q(6o-%^=g@~hF_85dPJKnR*4NQc9!bi)OCM>HMlR;sk1<4mXpLYh2qu?f z6U(vj#KAlD$^5bczdjMq+*KADdFMXY-yG)5HsuST zud2=+SMLJCLj0##b3cc3U#mO!!ZGF9YccHQ7|pzI`W&D2zmJcu|EYX*{WW|dy`2NX zkJL{`KeFe%jAuG1&pcG0d8q!TW41&2O-Ee4ug7S%9?=@sJHRSJOj|$Ke)+Jcf>cCR zLOKBwzkGOK|K-DXttvX8_(2RSN}{`zflz+gw2z|t0aW`spx3ToPEiv9X!@!{fUDO@ zLx5;)2#Ntnj$tkW+OGo*P=I7WWGX=TH9%M1K*b3N(Hc-m0F{VgjDQYvKqY*DSl&P% z5fGv^peO)+N;GRf*M2j3kTN=-ngFz2r!*-eT2n3yWiKgTg>tOZmN{He_VUU@9Qd7R z{LuRuDI;1_j)QVc4Eqm>+hVkPW0WEu1M%}XjKC%5KlpwOZq#-|9LjwH5N*GSw+iqD z04l_=@&xdlFF*w!fbu~AzO)MPH2{)hSY-luM5}{30?9rAm4g6Ou?p}F0IHGt4d2PH z2E}Y;%(b=2nEY>P@)4~~er+h%ieWWL{4RBUyfXQ>swZ9V6=>3%?N|vvRZ;;w!&d-S6>>{)d5Bkee39eEexuF$;=qV^}7M@>^D0 zs4k@~E7L@PBweZw0j}QmGz5s&hM+5eI>)eV0^+x<&VZOfTUK`7K-~xk(Hc-+0QHVx zJqd{4vU>Xf^~@Wn9|0j+0~!pVfkeY?Sp!V~+Lkqhlo72dkAU(pQs%a-VZ5@jYK~eTTSxZmbDHW!zyKCFt)7KK`=J{bBsC4tE_GMmUSK&XJgn& z!r-^8v*6gEa2Q+GNj$SzdB%6k+N!SCxOy+pFiC0qY7eaa-0E48&IDR`h$7 zb=|7sT`1m;VK+&X-?DB)bvJEUH%$bf*{u!%uHJhz1c=s#;35bS}i$Dbd^b*l< zTh>b^0By^9nUoQ&4aI9veub2|E$bCt*;us-kust+veqp zw{oBOZCP(y1^55}MPu2!1i)=sMSTF?4FX`d3LpVMjAc#&;I=H$2f!HwK(-3t20$@V z=eDe3Q1r=rWAZ&T`H0pg|05_z#t{P?>=FOz*ypP5 zgX*4Gwu^-MxAOPI>Tl)mGBJSXxVkgo>fKK$h@qn#2FgL=;NQkSh#5Gm%s?-ne=y>l zs*bDo2&p56u6`mm*jxCyLMKTGF?6A`=;mqaCinLJX^inXWuEFk^pwM$UDKx*7u z_ZNbwUACfj6KdCE*;Nwc-?qPQWYblXHkVDeXqXX0ALfTZxgX2!5(@v8{e1u&SBAQ~ zdZ3N-+`D-rJt8E;(2?@Tm1kjb>=_|(Z`X&#`4c@e5otSpc%0@j5JN{P0F)Qw*b8x* z;o;t@f6;{U0-oVBQ$s08D2Sn>yatq4h=YHd{uPrfmnMZs9WiwEx1jz8sq=5qzmd0k z5mHACUHt>77mZ`@5&-x1e9^e66X`*Lkyj-Ecm=} ztTe%KZ^?U2Y^6;^+E9H)D2Sn>!~-QZj(tuj+}rW7CX~;Epd=6qV(2Je0Hp$PaBsy| zFsW*}`=u4NWT;gpHSTTr%1{ernZBYvB8J|_YEZ30s{C8Y4Hbz-JYUr(C@mgoGFhQiSTT{{+(SaqJgD;tzy=2hwe2l#BzRU+~O5wN*!JC5}v82%8bHvn$XAyCh}VfqmaV(2hK0W&y`4I~);0BEoe%)q>1 zh7k;6=rE%JGm=QS!=I5RacvhFL#l|Ot4@IGI8x;fe#Y^t#%uqHq>322>U5}1jboEZ zm^<{D3Ss@wXEMHT<3twv9s10$B0dk|bK=-666X$l=J<%u3L-w=iue+UFN$LeNt`?E zS>z+WFo^h4E8;65zMPb~gP!G3^I3O{$zDa1jTri5Z-DB$IJSm_xkH|Harz<88Xmzo zdQ+K>RyC*a1(j&?_W_7`jklbn`XpCU?N| zT6}i9p2|G?9q_zvMXde8EWHzN5~r~f{+kHM~Vc}hw;oqNZbL>hbAJAiAdYcOA-oV z=qROuQYxN(LMYq;Pbm}1CqYo62?a59lyX2ROC0JmnQ!qb;Qusihvu zY~JelLp17N*gyRq7TDV}wVXYGlBKj7)aFB>@E>4;|rC<}>kz|%f&&aT9X7&>P^aQ2C3y$F&& z;OXOU=yH0Q@&mv<6pN=^z5NLZF%+cCmHMZC76NNNF>x+?J^%(QmcY+t=a4d@HRa_{ zUK-C9lQ{3Rml|u=ViO0LhN@l{SMLhKL9~Xm7C5Vkg?HPlF*)OveDQVL6I23Rz3Yeo z(Hg;~ppH9NY%_@=S`*uj?rx>-a;|$T#(RP??|!a(hgHQrP~1g|ob%olL~*ZG#Y0d$ z5YP6LDDS=x7#X(Tq|as8VH$EoYeRktI49!SF~Z>;_z6G^RfgSg;K%aDI!#!J*03%E z>tZ}RPgtA_zi6U5Z=%vR?kj|YXbtB!aBjx4>x9EO@tY=`>p^ht5Dua>oQJ@$QG%;yeTbPCj(b^Eb2ex+- zSdj$wCb9AE{2dcg5d-&46C9UFMTrs78lwx0LIQITAm`8p6Q9FGr45-xIEdD87;xMP ztQg^NF5PXyDHa6hL&8C{hVwCSN)ij_)JvL_HK+cGRmIX!EJcc(TQ3F0K-Mdo`if|+ zub)A=3@P)Dy^Kj3xtMD|$`JvgHG)JCBqXr71QtUaylYS3mle47I6O05S!fK`9+Nj~ z1!6_C#`-l_lM`5F0_B~1GO##vm{Zx5FMuAeI(J;XRR{|)B&>O1^zRup2Uas;;+%Uk z0L)UXgr9S7LCT2Mlz)Zt&k3v*iSy3=XJcJ!W#RzS9Mw1D>ivyy5Ut_-1)M*Kg?H|M zU~-lyIpgcxm#PG~dNYXt(HcQkLa?*)T(R~fhGjRFyIVHV1o#UckV*~ zF-IA8!?_R28*4aWAzH&453I2XY&2nU&V8(jYP5+;+t4Qv4x%-j>A;zqz$Oz8=iH~7 za3%-AnL#*+)^O$mXEw3$&V9B?noFB`M1W|GU=auw5&`er7v@c{mdsddrU~X4BQw@0-Q_4!a4U#CS@(3uUb{S3B~KA$T|1x zPz+?fZc$$mt@ZUDl<$x-@7(X0q>+oc_TxSgAX*~`E02HMHGw@zV2_A{cka*lWd+Xt z37%P_EHs95f0Q?CzVh0^1)??90$_a+AEF?4#yj^H%lnzboEOUb8z?|8QJp)k-hzaM z7!uY3-MPOHtoMkCbMEf}V7+1`{G9s-q>N}y*#%{xJadpZ@7#s*`T>f=!~v!as&B^C zD-jN&H5@l^iV+L%+>2pywkbK|>)f}i1h{%VM1W|GAhJBkf3N@H=J#K<*(#yCxndR^az5}mv9iR z;S2)K0Ak^s`v8-&md}H&Dh`L@P*UWa`%owbvR)&ouZY(AItI$4NSSx;qfFAs#a#O_ zmIx575ljQYl=5s6{_qZQ@Xmb-zpTKyPr@_%l!eA{?i2E6oldNX)>s#Sbsm1(fIxZY zKF{AA=FBnW3!t~D&K+0pLc&4}2`fi;?wf$MftWbwz5xIS6f5E9+&7alqBZ56P~MJ@ zY>+tb+_xL++Ex<>m=3DG8CUNv!a=l#vmZEniG_FWdoel3m7MW)?k7|NT)lr20ird6 z!$F;UuGkS0L$oG#0^L1E-Q}G7F^u;KW#0Xq`$?;cXQ6nS6glU9I*8&qtBO~kcnSad z0g3X?{gRPk7fkwGhFzs0N3=HNcYt#Xe_V%fc;|i#5C@fEH=O&8ys_>Q7NRw*r@(rQ zUrZq^&bdD}Q9U$KX&d@8!a=l#^E_VMgeS6mi2?p$g78HDLCS|`_-xg1UP#mqToA3{ z6a>yo#KJrGmrT-J+Pq8zh}H-Sf#6jl;GO%cc@q>S0z_*B?|`64B72h{IOkp@F+1zD zvN#&f{Y?{<=5*e*iXj5SnaJ#k?0q8PoVznoKkTuCfWMdCH!*2x;-Vo!v^GQ^g3Xi2 ziYKxNV&k2=$Anbez>P4$afwud7!j>8MuG9uMD{TOa?brz6W_-sDs9M06Aq#^oc{pl zvqV;ga5(4wnF*&%5S-5m2hkc%0&wDpg>&w4CS@(3%Uf0a0*Vz#k#p`9pcu${eMx;q zwAR;TC|4$B-nmycNh23??Z;O{fM|`NCJ4SwWYrT{RpQ{C`?vhE0_R>G&zx5l8pF9) z&6_oaSP`wU)&*;wM3zRNymPMuEY2L}q?z&s(8pEhj;psGVIhWubx?QiJ%QDom^kO& z9RQaUE8*wddyz7tHRSC8P>Yz&DZS`(Xq?vA7Ga?X7m#=A3m>+jqr zT2-71#mS_|Irqsy6sK8LoCC#KiEIXm^3Hvhkzq4T`do(1r6EVOHsp(elat665DxF$ za{zILbM6cB##%yHh}N*y0BcnuTR~Wyb6;hmT4AEnHuSZGgJ=zB3vf0ivJHg8ow;u^ z;cN(kvz2fVt>Nqf&JJSXo%;@xG?zBJi2%_W!QUX*M+Cfc-&L^_7iR?6yaL)a_aYLU40e>%@HZf^gdx?e! z(b^E*2HVX9 zb3v<$uR`(Pq{un;gk5v{Qn1FKwtxd@bZ?lQ1AbC}~YLKAKB0ns zfHKa+0jBG!bH~*?nQ#!T;miQeG-BbM`!r0>U?pdK&)kQo&K+0pOd>$EMliQRFz22t zHjl&*t%>EJy9=nhoO54*@gAbgyWg4nBCCqaptyt-Ip@A4h~jdqiff^`x&m8CqP%lo zZDiO=lRlSW>uAUktqu8B;B2nIHWCi++&2T_I_KOs=8d(Dun?_b?E}`H3Tzi)an5~@ ziE5XLO4~vA6Aq#^oTI=wT!9@V9L~8PHsKr$f^&>;5Ut^y2F^)h;hpH7CkD_wb7TNck%2 zJDd$a<5yfRkzS}sZy!~($oL8vU#`ds5FqE=UpDa-Fi~kk_A22ZS{t&rfb&L0R+w-& z=l+HXr*IIQB7}oz4W}q@-X#{!xxZ^t*7Es%tBOu2+DVaf?sg~!vR(r9713H>WhlEy znRo6klQeQM*M3A00ird6k{~Eik+F)*O&q*)FHwiv^Y5JN|4 z2b4C%!MpV~HSlLBl|1ov>(flhine-ZO|=A1i8upf;ce>qmmTJ0Di6)})CL(RKo!7}-23th{oC{xrMQ@g}=ov12m5E4mE$giy>;S^H8f;4qwuvY>2fod?X}3U~ zzh^d?c(e@NNkfAe`p_H%*WWeRz8Y)~aq;f^ZxhZw19guHj7ywD#D^F<-zo5&sKJgA z9Ot}GnAnb)h_sYg&OP}p>VGIf(hkZ5R}V=f*3l=4WL{j4$g63GpTC1 zd((>AU8vnAHO_6{hFT!YbdUOo7UnRuT<4>^+u99V(99h)C}gZ zbA>)7A;i#yqS4JL>L%x~qcFxRm3j7a*j_7Y<)BuU)HsJ-Hi+7Ptf(bGEv_buAwk|@ z#~IlaW76ibsXPrcV(7zM87N=YWEBa8ci3M7V39J^hQqFyH&PNIA%>3h4UnqUWK{@> zbJ*2PL{&^g+NS(1p&*8i@*Pl8YqAtV;T(3V2_+>6N*bXchK^DXC_fMf@34O`$#Q9u zPU?uEtN#e~hNR9r?1p)(|3vDDp{qBCdb66W2?1~pyBQX}HOiuAIP4}SBF&|=u!8VA z5Pqx4eyPb?69wn6e=}~{U!cz4Gp$WLT892XLxULl&~yM-R!!EnCd(u)-eG5%aM~KE znIq2mx!|rBc>tZ6(hN>r_Acl@I04V)xvOa{uIqZHWls-XF z1`-Nl=qSU0GK4rdhdsoks^#u*D{7;mHj>mhhdmN%fh^M)>LX(4eVhQ*aiq#S>~SVp z`!FVCw~`~i4ttNPj;r?= zsUwE2ek!QL&J{XMLWrRYokus%Qa3q=eHLT9N110ohke0{+7+l>A~nuoUkajj)r#6} zsNJl|u9G0|ux}dKbls%QWz!uRX2j5k`7ux))@1hyg?HEw0kBmWYQtgQ&l~9pAt8p2 z^jr##A5vIYiuSUebJ+P){E5Qw44)3#ru=*goiLij+9GVy2`>Y<@Q41H)m z1=q(ZtYiu+L0r7U{@8?5(m*X?0^<^=6!9U3&Q}h6WmA}!;5dg}*2LyD5ots9A3{M4 z9i==_;!{{Gp>Pg6-h>hx1SOGB5JN|)1e7m`gLBwlm{hggt!zc@Yp5lY8t1T+p%%z8 zRiQp2hTg|-pjwSod52xiB#XSuwGZEtI%4SR-$VVo6qcI8Qiy?f*x&KX1{`)Oo;jo} zB!0RuyOVNL`aCCAbqPk?7x8Y z2k~$Y`wxg8RqTMD!_FjC#L!hcKs76cwIyNRVP_d@R$CJTc#f+c7gujbLO~22r7KW6 z69@0GJ7Yr5Dmmiou+ORLxO%&hI%4SRy;6dmVdo0u;C=gJM580HVrpvbJ;Y8h8Z#RVV(?>i79M6 zq3{lSA^?snLv1+h@p&UnAtc1mk>&ttRtlRzNSwo-Wg?nkBGNYHxrBlkI?7_8T5}zci3z5R^LGCh@q=* zhx*nOwwVAphrJbx-bH26GaUA26Orapc343;0EGQ1Y;OwNO%$BN-f!Hrd!f$XGrLVZ zT818^p+O9NXikCaL<&2W!j2FZ@32ppaE=+MM@(Q`;+!Tv#L)RJgYRMrJ5O+&!@g)@ zJ8vS=hUyBTAcl@|8z?tZ*mXkT9QI8U%Jm>9cL)VBbd-lcxlbIN!@h4))pGZd6}4wj zdqQfQ!+rv_K$gi?OFNxF484!xwaT-6wX{Bkvd}N>i>p%!CLI4 zTI^rMz&q@MwYX&i4*MlMb5&VL42S)%yg6SXPQ=hTi-7aZTI_X#{wLIqZ@UzoFOxKZpGZsUn81>V<0QTC5Za^A5Xo zE&Twal!*a6w^WadtG5iHAcl_eIZ(}p0fRWWIE+4L<9Gh*n&{2fqIYq1nU;T?7=0B$KmZ8+?dyphrf2{Ck}20%)$#p)6g z=djaFM0HI>+NRu)P!K~$X$q9awb)OD!a3~5CX}Copfn>C#L!V%0i^|T@D96$NtR2K z)})RYy88d1{wt~T4*S=<)qf{-#L(5-LA^~a_7?$g4!aE&y(h||XE^M?OhlSX$+Cjb z4G3Lou}-yEN21^yb{FHO?F4oHp6O`f(K56<4Gm)GLo)ze{c5p3wOB9W;vIHB6HXrk zwU-HuOPqnkhZs8FNbn7>#fB0b=dg#H*oK;jw4oYBD2Sn>Oa#jKT5K$#a1MLC31w^$ zlu3kw7&^*ypiCtW&S6hAscN}9!;0D*sLdiZ&SB4jS|H0bm->hpdLI`;bv~)`4tu^y z7I~LzA96??F?97+P+w7tEvvu8l=cZb0 z13~f*dy~JR%h_Pc4*)+<9X77st%QUa3Q`l*VP6E&dE((5_IZeBVTAl0_9aq93|;jG zRIk-yS4fz5*w>6T>xzj1JRL;k-}J-Pdy`NQLr1v>lsm-1JM24{kiJTe_&V%+RvfR-!tV*JX(e((9j@;J~T<- zs+7vUNM#j>i+9+SOgLW{s1;0LT;e1XA7bcy--54tDyvFxoWrheVykK*(uS%Ap&*8i zk_MF8sjL>Ea1Oh+38hvLl#==eP~ANh@q?h3iY2;S*ujmf*5#*{WHI8z+tz-Geeby z#5lulkvHdW#EBR>XFG7VNo9W#B=4}>0EshnIe(e*1HgS1i>F+@S%icb3R31#8~rPQ z{ejh&m^hc+7XTv^OW=2oJ%E%Ettk(K@{m+Eh{SoPJ;YeM2AMd(G)nclxO#^Z4x%-j zF~Au`EWFzug~^$qK#i2h}H-urUpCH&J~+PVu;qnrlGr2sJoo&o`Uh7 zsLZ>c>z-~^aW)iZk|O84X9iK6V^uK+iVITNJQC&I_W~os=9%=l3|mA)j%aPjR|02w zDqBi8yaQhjh*8S08xDMF-dL*$3(*?ZCSYwyW$OrwbKx6IRO?Js+Qz+^a1gEG>;le? zRJM(9I48ctgtILO&Thg%w1)FHaP|=k@5c9;q`9;?Km>@^2#$i_FcI*M{BYg`$A|#Y z8o^l*oK9sY34(Lwr?EIrQ5HwTm7g?GY0l=HRgCMvxSGl?r?QJg!a4J+#tnTL1pK{p z(Zr->?F||tL~BFz5N!8T+1*rjo7i}Fe&2+2*TB7Pg5whD5iufKW6WQ>JPWJMo)IAD z(8Fr`57{#ll{RGIwY9?tL~A$&fb(K)_Cjs#FotvKFPd;(z%%@|q~R1K97Jn4uL0*3 zV&R-84(713H>--Ytqq|7_^w@uQ>#a#RG9uXi~ zBXEI0sLdR;*$2eIyLO>Ax2(XmJMhd5WuY-#`v-ZmO2mq2jkN?=S#9PfP~N#SU~%R! z$8E|NKu=JeJFebH!a@uQ>!j}72GB!*~BtQNXkle)_}_nH{*#mc<sVE60LAp$tS*W2 z&OP18u(~FFF2fqqkRw_f@}|IPT$}wwIJ|Rj42ZePup7?(r@XP65f-8~tY3iDx;AS` zSe$cjZK7&vqSAKIUkL}%8crr~{;bV@CmhbX|7pVcJqS)4!a=l#(*ZbH#KJrGER!^s zHXVro(HcQl5OgL2-nn1P#V zI539RW`k?9fkeVN_o2oOJs1T1y)@9oq-E_08X`n%Lo^X=<7>0Awb^K56Vg}% zceDwPOQcD}h-i&*78qyL{y)UM2Y3_5)&?wr6GDIsfsk+^1eM)YKpHTF5L*xjV@wHP zbHNa*WxzJ^rDI4hrkmb-@4bX>dhfl4-h1yI|7Uk+51QQ_|KFAV=lRJajU~VDdEYs6 zX7*@p2$@d}GM)QEgTMI(S8B=@Q#&vQXD0*ftY}J>Q9DfMzQSN<8OP2lY6r&P?5qbn zYpEBeb6;yvR_l2~u!>tiaT8T!I`>VWXx4gdrE`TbxVi2GR%B_U1bI%^H ze&&WTIOUw6oFksRN5$FBJx9FOxxZ)d0iL!ieKS0JKcseG49-qou#<;+VLSIc@$h$I z<(l#D+>a;@;MtpxI)E`a2Or1tI`?;C1*sT}!HNAFru!+KF4MVx3i&=Fue+{uFC47m z=b-o*Rb)E%&p3+3f>jhj(HT$dRFv)9omgRZgFaJX5=}Xb!KIvl9d|q_PVKOryBkbw zm(z}&d-1Gom87;{49-?LuvIpml%ckm&b_R`RT+aT^@9F2wF6^tb|Sz|g?Qqnc9_n+ zg29fLW9M6H2gcy+R0cbhs28?#uVj#B$|jmRfH61+-+_Z_)B)SMSIgQ#4e9{K;2hKe z2eso#3^l=Y?zQ1?JT4!O*ty3TT&bN--C%7r0UM3tNrQM&pE_YW_eQv(8-N3LFV#1A zQmeKpO%aU2r6?J^CB~EH@g#wIV>|amgQezZH^E?zDWsOvBaFd$YzH3O#FJLkAk(?G zG5Bj`aHXcKJ+%X4aCUwIJDuZ6Dz(FO?wt*GQaN^hrgmTq&dwiT=Qrww>D+%aD694S zXRwN0K{1UgGM#%GD4Mli-RN9l3~sKyK)DB1W;^#D25G3pckM?ybpT^<4hDmRf$^k& zJn2h)u$}ur_E>?=y+6EjN^)Acz!2w# z`UP&M{!Zv36@oEvp{p>>%XFGdmwp*?d`(_wU6+0>7`0oVc7v)h9r_K9+U;P}9)jBa zcygBtvfcT8tfspLZKj$Y(KN#tc$!~=mFMx~DYe3O=Fh>vc{$bCnLo|i(kp5S#=tFQ z_rVXyeI%1wV!CpxPwyzx;7Gk#hxq6Z$bCUr$puz&`bZ9+dY6Fd$a5O3He-vwOyA@S~PR37Q%h z15eGD;H$Kcl=2ZmeX-qlX@i|oXq6a@F@;l>`hziWe-*%=*GIyrIi~aW8oY%W9I2`L zhFXC!a4VI;N+lnuNUbnkcO`?BiX1D^)C!D&Tlo&GRHHtaj=P#cRju6`!KlT8S}m%^ zblbH+&8%grP3H(>;B$-v)jCv_?X>F{WTEcfwGZ{EI*fs<$AfwkA8F(x4X6jU%WlFR z8_;Dpf_Lu92MKoB4YKy>qds8_+~*JAGucNHsY$lOP6kU%Lzj_gs1GoFRq3$d*_%Qw z!5D}ouhL=v29|!IewYsX7Z86Sw*$Hk`**4eW8kV?K{d@s{-nZehnA#8?XY{og1nGx#J|ISsi?!Vw>MRXF>v+%KHk0XcR~ZG5R8Ef z4S{J6qSItL>_L#@m-0I6I_#mrsEq`*;Z%+3u!nQhMg^lb0o2C%$QUZfcG%;vn#LHk znQEFy(+p$aX`TUAruoPeYK85vr-6Y-a;mYzo|3htnbZ=Dfm>P#mgf7&TxyBwu;&{b z%{4euFUpIk6&M4zvI49u^N}Ug3e#aPGgw)|v9gj{fiZ9^Yr)ED>VxgDR~uxRGFeB} zVGLY-GpKK*>THL-F>CcLR2{~^)pvvXP9ND$4KN+{PB`@5$cG+w*xL<`)GlRDFcyx2 zg~L8_&`0)D7fgqJ7&q-fP-pkdeuE#iLXXkZz!-RH&VjEpK61)OPEcQLhkeFi=M-8! zVKBxN&Uxw&#=!ku2Y*+6A#bTF z+hM;o$U@z{Yagr$>b(&d16ThL)IUfd?!12qy!aaJ8Vyab_1h?!2|f|DJuV_ifHkcqE=uG z+)7!nQil3qJM1#BApPVT@$azvE9&s<{fer?7`S?P0fidvZ^aWqN6G*QF(u4Y9JM7*DJH60q4}&qLaQaby zFb3{#82B5KKn78BOou(h;BAn>k(#RE)C!D&TNwvd#w3tY)C$vKk1<#o#j!G;T7fZe zD^tMABH`e-lUqFb*}IWig7JT~bfHD8HB{-a-?peiUbis$-R{>d(z}h6 z+X3A@?93MGM3(wy76IClP25u!6 zSjkC!upM^JMEHBKa*gM#bbo-dKtVZRglhzh|NxKKfuW&t`)ro%1( zIi4l2v#!JbBp9{ApjL>gF&%axj#`mm)a;;EERhtYf^3If46CWAL7S;22Te1Kfv34R zSaBs1ky>FpY!?_9EvFhgY%yy~C8#AB1GiKLEQKbLlGGB@VTT$Vl{7d~FUnt1D=-Fb z#S2!#5=l8~h3T-v3|7iM#bb9s}w%6Ulef0MlXDghOwxeCT0^{hh&)+NHz>W1#_9sGmsU5=kBEg6Xj9 z{CmjDe@7IrvIQB=L!)3H8Nx*a-$Z@o2S)!5C9GEvP>j1NYYo z{G}w4med^6VW$|pwKOFhHw?zI1OADzV<{tJ!5ML~}1G)}-F;#^zaMhKd zx;&9ArNV57y&TW1r3Me+XQ|TT!m~GnT7fZeE9=0@8tQ}Xu-CwXtd(oTzr$XqsKc{& zJynM>aP`gH4*Q+Z7Agc|;6giKn%n3!nGSm!;~J9JPJH zs2u^dLy6=76=XZ?Ls(4*4BAXJ9i?f8G4M2>1}i5M$v@Nz+hLys154#pV~71u)|Spt zOE3m*=?Yl7lt?a6OH7A-$>8XM!I64VzDljY7`T-?VC7aKxk0Tk9ri7Ql^Yx@cc~Q^ z1Gn-BtURDT*be)FL6#|#$5b80z|~)X`ZKD|cG%CdR)0y=VGLZ|ngsukfJE|!8elr? zOgQv5%7-3y*l!Gu)Gj4kQVosqSP_zlgIZxaY{6i~!Lj0^R$vU=iU+Kepgx!myM#ei ztz8m~T4_)#Mb(%NyA-IIwM=E`9AON6j^#kLELCMY?6L+~sJnOV!`Dr~E&{~`RFUbt7jP8+4pwmm zC@xDPOQDr_Z9IgG)jd_CA%n?zPqJ8TEO7EJ7t(~ceZ>a1;TptfKP z&ejgFwJnKkp|+SVe4D}57K1DG!o8E)fiXBc2f)t0B(jIvVLI`B20ME=b`DZIFa~Gm z7}z;Ny|CT*5rZ^SHpi(07=v?g8XTOY4%m+TWY!MOPzNvu=io9pxR^xFQxi;Aei07G z%ktrfUHN%~E48z^60D88VB>ZYxtT<+QzuMkej7LRO>n^OrRxSyYSrGODS|P$6g>xT zPm{>wB=V4YW4rUG21}38?n8q)rjTAxk1z)3(V7e&u9CC$r~>sRnSc!#|#sdhf3c3=$7PF}E+hk9W;^*jb;wVv|@ ztN1Y}=BJ8Gx1Jvq&04R5bgnQ4H`jlI@~2dp?btsxNJA~YYd;E82QUWbzzGiQ$)s2^ zDN22?UAsM*IaZ)+F9z>imk%23+KXoGRiIvB49+V7ukK`0oEl|2cQ@E#n!}9ZhI#?h z=atSKp1mchEg1h-Tcz)vPCfopH89dbgV*e0@`_Sw_azh_!y4aRJ^vFMOHaty^wO zv9OyRK%?N7aG%4X?z8h9EX9>KKapxTUn{?#_5?zzc!>2-1aSWBaAzbxzPH6D2e2x4 zOVscHJTKG)y+TH-#s801|E;rnOSW2AXH|K#$p30Jo0-+mrN1hz?V2OICGDAUDa)K-@C?3U~yA6TrGv=8!GEP1lMpWV6z zAsfRiDTzN@dRhS!0+>!#>v|q*7qYg8Sz5Gf)4o~9BujdT7QL_*eLux1Qb*v0MR9Xb z7q^IpKY@^AJji*JJ_CjsyQg@Z>&UqhW@+E4qhBK0zYm_Qmw3zv$h>RLyv<|2K;~0( z=3^c+6Pd4hkoUs1h0PYuE-a=p4?xsxe;95_?wFL6+_`NFzcnfgIk#Fr;L$%tg^$Ax zb&)^ZG>iFo!R#39b93frMvcO}U?nh^%RHFKW0pZ?DRU;_F~fkVCi5#E1KP@YW|`CJmbQ7@ zBczRSIa~2qKO!sD%vOvR{WpqJj*>KZp{~aty120#z6V0O@*w?Cx;GeRj*?zH&M@Q* z*4I#FCI16?%<;$^W6m7KV@^lr6m#Yz9&;`-XYn9^BV+*&k^vAk+sjRhvbHkur9Ap( zRM=pwi*@ERTEh#r7lZ9GXYMd+Y~uwxhQSV-2Rq1Po<-&Ntcq}KfY+jQSuAvtF3yM>Y5&|#O^(di>+epKgK}abcBpjv7fnnw-Da+$T zA}7MDyPjrOx{?Y!=6A@fYR-)2G3y{R)|^?3$83PidOS!xLK^cR$pBHa-NI|ul{8ig zuNjZt9u?Xc>!OwUj8b^Pe#KxvnKL^ZHBx!Ox?!+1^I(7Sn0=9%ZqDqCt_g!CxRmG67zw>oHarx0!~YijYY>$Q+cO z35J=YWIB(t7&!~en;s?edCb+wTxrf+&SP#y<_2@-Iv#T;GPm&{`w_B-2RRN9HQPtZ zn;j+1mBKs3qhCOUv&OnOZ9b!uykNI5*mZN}RinmbUa-d)?16c(dpzcAWWF$GKI1X7 zRnU@|$%EtohmU4X zRHkbX2SzUzX-V`$3{zqkT&d~jyYA!Qw?NRGiO%eG3y{R)|^?3$NU~A6sLpW^2KBD#*og|mY&(@ z{dR}d+K@*|Mp6qPwQJV8wO>umSJp3q$NdRCb<$VkVujgWUyaMO6#j{_zv-f{&>%f9 zdRMkO)+({nc)b3|>%;OED!g<_iU*m5knudoOn|7>IL*8=rs$aK zwLC3A=3H~;Y#wtNG8daO7x9>@a6&6|5L~{E7xr__Cp>o6M3&$-d2V8lE=$YNjvF7 zDluoV%F9-XJ;Tvw9^`$D{am!Wz-$mX#a=L8XpsIGy-yT#p~+NYr}KEjkvD|pJy3Xq zc)an*8)L>B#p6vy-XtDm7DA@;APWJaCS+ce>4j~Mj%odfrgAwlmzXpE<}ueIbCo%B zC6BoYC$wG%!R6bD!M8y=*$dki9_b*G_5n$EVGDs7Tdli!+&AdyrLJIeXsHURj3;+x z!vU7bV||FM9F9LY%QK>X^@{HZNE+3>I(BY+}@C#0&Oc4A#;-SQ3xf5t;4GnQeH?pMj|+vojC! z2L}ID2f@A86(N7|ApH>1JBwB8C2u;z-K%XN^# z+UDJWkhR9;T+L%`L)K<9Tap%iH^nJO$pLtwuE$5p+8EF^Ej80 zb3tE2pDFo2$79|>=1p_vbsqBxG9Q{V@AH_ikolYku|{hbfVVtIPJpP{em~mmC@G;# zJS3Vu)Nv&WphCWA!zJcl(Yga!&0=m|u%Z~OusO4kQR5R{FbRV>&4bx_%#z4-n=^~^ zm}P;fCbKjT5{|*k=^(h*A`nuZ2dRdT=qy$(D%$KQDXFYzBrkLw3>_=e^*yq@XRX#+ zIyTlrDze+_Af0C zyu@SP1*V$JTRg}k41Qk+!M*kzAy0UaY*n;tL}nJN_Qv!msjRH%D_-c_7&>PalcPl5 zvsP=4D(s~NcV;nUf2M;}1){RQC4@Mu7_L5c9?OHQ;%2sDwCJTNPLV1HFVyw;QWrN? z!b!(eIV%s-79zw?6i!(hG5 zgZ1Juhaq#YIddS7IR=<&GDq?t6EXNW9R&BUx~h z#cihHuOZ|z4{{f!Z|RSc8$8ZaXP$MP(4|vQ>WWF|MzT`1;RMoC8Aysw9m#Ueq zDtiIIB;-Nnhdf9DgyiEviU35-cA=_fM@gbG@lSYk5fvO&4VM_3`HVj21uKQYJm$<2 zMvX6c!NM@uSLVUK{ikR;^xD zv!mn(Wku`qLMLMAW-?v>0Y~1mR;y3P#-bdI>;XDRDAWaw+Cjgr9?JmywpZZc!r=eXL2$2q zf{+3{hz%h{tC?K@)Kx1|&Fm-{tgPt2d7(>SXqQaaA0_ghwOU0T8#6E!*^_jTVL(*& z_Z)=GtY*0SOy{u{A#1*wtub2kWfZ4Kt%4WodaTgJ9joEjBV-K^vJIs-gJI?<*~sJU zL(Xn}4YgM?xRb{`j?5$G%tJipIb@zTXP)FSuORax4{{43*Ljdf08z7j-?S(vC=v+EgE%p`O$Wif_60&j9;6IHN>w*IO4L;&)yk+bs2iXn~HQQSnm=)#U%EUME=m$|@pRq3Xn9pbzFW4yz_K!L9m{H>hFW6-a zcELQ@IUe&iGH;kOukn}?;?S;WlN1}*wm z6sJge;f1;$U+dy-)bQUTqyi681*N0FFmsed@;EWbsnJk(l&n%RSe?iG9+`3G%sM=# z51CEOnT>eNBxE+{L0Tc?2OcC9AZoVTn-=93W#Vml^gmGHS7TlLY(AqOdBJ*NuroSRQ052A`yZ;9i@Bkm)?gVuUQrV%6rG z9wj@J6`jiqy#_;P@b;|LxJi=q0L)K|CTZgsimnlv; zN^Zalbv>@?;vUiPcM)=n2YG_h5A{dMeIDlxa$f3dXs?q0=RD^7jqobbNOuUSOlu?d z7{{sn3z@mhnK^mPkCFKi4^kK*pYk9MfT-Cn*2wJoc3hcwQ6Alc3dI{4E-^0i8Hv1L zsWXHfL7iF>3)+P3CtzNF59wtApTP`yL^2JV-Ny z#AmT;O&XbXC8v}XZNv-R3Pb-O)Ae16yl1V}WE~sJIStu==pbi-sO;}v2vO=aS{dGwR0aNJlIN6lw+ zm>29a2D@O+JZIE6!wYr?gWWU_cAdw3g3O2J%==%!^UPu$z5edKj4M_H-`R1rt6OqdCyv{AM4n-Gs_~ov<~tB zh|2yhkC3p&hO19G9xD=A5oWetXwj=soFY{NUa0F)O&9m2hOdo~T0F@2C>;lenWLl* zkK;p5lg7H<;*pZUMm**Z$V@V4w%{?_BeRV;vlWl|BQjHYklzvV3lGvAAZoU|m=@(5 zW#WJF=mSupudyzAo6o2hFW4vyHr$*!)Tl9-7i=;Hn_wPn9FI90nKR6p(|F8t$o$NlS(wLkAyY7CI(STi%o04vmk0^vLCOO} zt^TkkX4khu%EZg@=+UT93DT_lSD7oC&nSWyEEa>+G-rNi)TqV_)&PUmGY?jm$4o$G zQ*&lx9y1x3YBF2!AgwU?4>}0$we|>U!-M>ake{+xwa!h%yEfT-ENY+96VW#Sik^arSL*H{;~&1ZCz7wi=Vdv4BrYSehl3l`E;yOvm+>aGjw zVrKG~xsjREoSCC3d;P+?%nwX8nR$7TPcit%ItcEy&k*u&9z;Tjv#HqyKwUL^Q?sL_ zl(M45c%efvG?D50qeR}bR;ydb#tcLwyOIu428hc3u8EN9O$}F{sytR5WW}1<@@mn) zr#MBb3A|9(qoFQtc@5tTA@MxO4=9}khM5mIEqI*v$Z4amp|VN_Tk)8`AoE9aW+xuA z3o`#SXa3G(_CjWN9;81)`tTsb0itGmh-pzqC=(yVqfbPIamKnBV?Lu%ykN62*bH;# zG^558Ua-X&Y@vCu`8?(-WUer0F5@vb08>roS{`I82H&KE;9lE>knKFk5riDfV%7GW z9wn8O72V4VeHKHX;_X?h^@NU%J2QK{c7R*r+4DA9+q@qlBuBjAD0z>^%7?5x@g^r+ zT`hV+ic^k~!tg>}k56@R<1~CRgnY(>NGRhprN z#9)c$%;rXo1YWTA7_5zXuvR?g&&cd-&P?So{{*I*%-?vBZWugG2f@9Tj*uQa$Pk1K z%wpC0%bU*dcW@djE83SAdK`ux&D*n9>qs3Ncjf_P@6|!#wat4RAxDhMd5Fh4gRGNg zwvx5z7b#9TO0K~Rbv-WY;(XXfy+r#mJgKQi<3AcYW8kO#2=M9p?lpV?9JUuEJ&c=Qse;PM$R zF{1g5oV;LVF<5DHW+|fv;RX8!gL%z^h4Glt$gE_}tjJ^50H&JEYCK473|>nI!M#=w zA$52VA3~aBv1*NcW=Ba|WknnCLZ@KpWSOr2fFti&_=mW3Y%I#(k^PGf(gBFd{_cj5 zG~;sq$z%0KR!=iqzi811P@Ez)6ke$7F-RBpR}DW3A;Wo)i6}h|3^QHH7#?RPa;E8P zC{@Ye6drRCGUuB!=kk~T8+Yax z$QE^w?m$%bcPWH;5)4Z@ggrFj#MMW-p^g4_>h07;K1nut7ZLcw~+-XO7}A zrvg(=<|H0u76zZLgWz79kB~V$$O?ok&0^ISn;s>@loegX3%wCTujB1m_))TsjXN{5 zg?0?SZo!^aBel)@exe4+o@h8qtce^}Ze-<5G&$jBYSBNUIOQn$1YW4?Q9u`WmWD5a zkU~6&1Eq_BVdf|)%Hxzkjw?}jl#EvLFY=gQA~V#SS(3*rkIXQ0W;q@+5}6S^NL7SX z=0RcsqGr2hqS^Irt}^lOc=U#-P~TV=app6s!wc2|gC&?VVR8Gw+!S*%)bdD9v0l`K?Nv==Y*C=5NE zw`Z-^p*lA1%*DuFsDmulHg5((mK&FIDUY=tS!>K}t<|D$p*ZCz*$FSy_1LD1yH3OJ zL&$C(kbLK}zjl8^I z#W2`s=D`Z{m@Z@r=1d2VNr0)AZV4Ww3JZ zMvaHOVA+zjLoU-i*c%@6LuBSi)}4iF8N8Rwo`qPK`GBb=GY=0^5QFE}L2$1XM#!f; zh=34#ve{9hu3E8Vv!mp?vZ6(Kp-W*Paq=nKVX|c3K zS|%-*R!A$Q3~80LT3Q1+*&uC{HcQ*3UD6(DpL9SvC>@rLNJpjP(h2FLbVj-$U6L+K zSEOsw4e5?_SGp(NmmWxuq^Hs|>ACb$dL_M)GNrDr9E@z zJghIfv@J4fN2WAM&#c;_E@=LEcS65crlzD|SQ8Tigw z_|7@_&UyIW1^Dho_}(S>-eo{t0n}AMT?5p0K-~b;O+eiO)NMfB0n}YU-2>EpKs^A| zLqI(O)MG$B0n}4KJpmcHKh`0eFZiI-NAmV2GLi-l`BKubR z-}Y_x#rEy?CH5T2iqQ8LXFCqFX zi2fR)zp?kUy@f|6sH8cr*}FKd+q*h$*tfEoFg2M zog*DjoTD61oueJkoMRl%onsv@oZ}oXo#P#^oD&?cof91!?33Uz+406X#qriT)sg9( z=13E!JGuxn99@N(j&8y%M|WYiqlYlZ(Nmb~=q1c^qzm&My@dsiKEgsrUty7>pYXS% zzp&UbKv?1!C@ggh5|%jz3(MiL!ZAcx=@=?xIED$U9K(gxjuFBd$4FtVW0bJYFgH@f04<;PD(DFW~VK9+Obf0<5(oTb^I-4Iu;9Q&c#9( z=Mtf-bE(h`9^IYGgdWc2LQm%kp_g-|knYS7dOKGMeVnU>zRop5Kj&JZzjK{1z`0%+ z=-eO-a&8m`J2weKoSTKA&Mm?)=T>33bDJ>2xm_6PgzKqur!d;NOBmzaEsS;U5ym<9 z3geyogbB|5!bIl*VUqKpFxh!XnBqJvOm(hwPjhCtr#n}FH#(2GH#v{HH#`4v zZ*iV*Z*`t@Z*!h|!nlRMUMHuGkDh&5@6GnKt3nM)} zgi)TJ!e~z~c%%zsJiUdno<71jPhVlYr=Kvv(_fe-41mW#VWMY{Fv&AmnCuxMOz{jA zrh0}6(>%k4>7Eh749`emre~Be%QIS-?HMD?@r)Jbdd3O!JmZD=o(aMN&qQINXOghU zGgp38t^Bfe;dkzT~Jcosgo+H8~&r#vB=a_KC zb6mLU`A4|sIU!v4oD^<&P6;cZ7oN(83UbyGEAl&y{6drgk2@gG& zg-4z%!eh@>;fd#(@YHi%c;>kwJonrbUU+T^FFm(~SDrhExx*o4gYGkk>+A@XOQ5l550;uz9T983C(qBxIC5@!mN;W0&=Po|0s$TV>wnJz9OGsM5iOmQ)pB`zVe#ieA9xQxsd zmy>zo3Nl|@NfwA1WTCi=lobed0f4zj%Ti5KoeW;wf@SJWURZXUGxpEIBHkBge$^ z29;d`h0i^F1Gh{I!Eif6-Li6dfOiz8#+i08uJiv4Ywpp_<_ z5APz~Ctal{o^I0O(C*Tb&>qs#(4NxK;=QD0q3P1{(B9HEp$|OzN^d;jrNv~0w9U3s zy6MS~`jJ)A3eRfkfpd+toUE1p30)_h2we}44bnPcqx8hNNje$2SvnQE1s+?aBV?O& zI&`~qCUgfpc1o|{GvjOfZg}jG#tM6-v9^8EYR`UYob7-#Q8)eq;sLy;Q^nMoHwOuwp-G4+ihuv?G9+(g$I0ca^IKUxF1L_-4CU! zp^v0%p^xG5M4D-PDs}NZlcsr|ONZ?*q*=C?(ox$h>4xpKG~4z@y6%1pJ~E|DdzvfL z-o-W7*45QV=;oSd>+ZS~-orJP^mNU)^>Qt+rMu3!d%LcB`ndLa`nty0`nk5b`@4?1 z2e?KG16>ozAlFjcU{{ZlLtG1OLtQ)IrYb4?}VUHgRzt_QY>u2p1`Yq4#z>x6rXYl&?t#GD54rn|0_8Lo?-!j@0cu6$;( z!0$M z%%74iQd$eiEtU7O!E<(N7a7X@Q7|oAEAPQ)Nx*coGXQv@U{cyDZ-*!tLl_m4^s|DI z?|Wpo_H3?4DREMNQ84c-n8a?%3%@4?19vy%KRMu$-C94N^1|;)_V8h;(xuCm4Y%Q+ z(qDy#fBkjYufogVTgn%uLqp4zD`&Hn{_^YaGGEGXC46YHWM*0|i9ORMHu8nNU6OnH ziMh4rjXk#9A=TY9wQx2|f!sMP^7sDwcQ%Wr?w@eki=1wceuf|BQxidxF5|iZW{wV5 z(UPyCf8u4_bce-4fUg4%%N3R2Jch&CLu4Tt&ZERKGomATwKZlho z-lSGai;nG5+a-6hsW-lCbvt!VOljAoOlaxwCQ>PIz+YuB!IYLi-Z z;mguxOP2Y%WSQ{Nr9+!EPifnvTD#Ov4Z_MPx5!$QDVf;1wZrxacp;sBX`hss(%M3j z|L?ck+Nt-|nzZQnOZ!gkn*97#Xt?s^OH4{G*}_5++of7aqZAAI-clBx8dwP2bL-e1 zz7yLL9`McB=4C7-x*B{{tFnbu{l!A6q;!gH{@*H{+X71cx^lBl&EV^H{~z83l$|Oj z;qD-WPW=Bc^t*eF$_++RHTBCfUzZDm3D!bQcv~^2q z+oE;nM7T#v*D}B&;4qid66eWD< zh3O&RlRwxp+jG->J1{$tBrzu!nY zod3)JJ?V5iYO9;l7H*BVZPr@drma(&D?*d&ZwtxO^VI^!(qoP|4vlUDQcG5 zwzLww(6Q1-CfCfq()IMz*m=7@ypn%)e9*y_J^N$wFN#2gXJ5GDp8nozUe!j0Zs+Lx zSN;nvf);4sszvJ8O7!kC#~!`1Jv6k-_PRf(^q+A%|Bc{tBimPkcPiZbNtgeOY1E^{ z_Y?A!&3QSS<$MS6+i!hQ6@8&$QQuXs78M;`@!QhvJEr{DtW#1&OV{@;A=aFeL`&KY z`KL#gY?e!i4~>ec9aAZ?T2w`fv&uO6XG1dXD&opjii)gWHTJv85V%EB$4;pfow`JQWwV{*`Wy)J)^=~ zw7p%uspr|gg%EDhufLd&F1@osCzeqM{jQssSq8uRHvVFnCGENP?QQYER#v=bY;28swS98y zMPt0sKpVV~bz@5VD%Gl8H?B_gn5q!}tB+{>MX^agw)eG2Y5zk~M_)?Yl9sIi4RY99sd_B1TB^-)F3YS$oK&6YsOq(S)nlr}`g_Z+QCl`p+{Z-L ziuOgv#KFIIY)PA;nM;XOu2f*jr{ysUr?5&B+fxa|q8s?4B5T&H6d6?mbkJgmrgOE0 zawhsxQ(CrVW;#)wX~>0&xK=f*`PBcvde?^!y>m!!W7J8YGwKA0<-Fv(zd0qQ?uq!QA*Z7S0^6witz$%Os7;I z^aB>n&m<5^m;EF#e%dDe?PS_4?6u>PFVY+QjYEF-a}Eq_)Z# zo|LFg<`ZqA*RW8O;QnbVL?=9lahj6qlT)9Rhzk?~Hb*Nq7ntVPZ#NXyWaH7+k4dee zWu~@1qmm;S$N*p*5V#(kkg)$-&mHA6*mn zFaT_tiM18AO${5aaxCm#UzK_>Q2@~v=>b!h$~CRsPi=jz+cksfXHz%bcdB>sNvp!Hyh0smRDbGGLcQSU{Q5y`WKI+ zh6x$RtmLooJ15Mhov9=)B^shAS*acq7hM(32S4LqXol+1no&-w6WSKoqHclu)$3M= z^+$)e0XEVt5*HO$9sWnqepjAt#$y{VUBxxg4F4L5img?fR!9jA@IzJQER{dd;r=I`R+**(|s>!%=rHvCPT3*@vv6a4yj*>TjM{VXAVGy5P8vhmWXu)@> z!7)HPt>iLs@#xhNuUbUoj!RUJ54g9N(%$d#yj(NUS#B)+4EmQ+Ni9nMCK{+tbp6;G z(Utv^P)b8RjnYt&HLJ$f@sAX$VV;}k)NdD*)}Y(fX;+Gktr;B|W3fP20lTj$Jrts2 zqI^-YP;D`CPQTPhTeWJb5@uY9yy{9orOOm81AVH3ZQRoSuD{ZvzR=Cg??f!8VOrDb zPE2VD_YKris-S(dV^r%Oe6^x$`4T&~X#@8w)4tWdbGxaM{CAC0P0d%KDw?mV(QwJt zE)M<%Bef{&)M+z7P@$VBq%*ULQ`*Ask9ET1|7$o4HYwY9kYSnq)+I{S3VF&Lsq%F% z5sy@@y_gOmwF=#SquNO;=CXy5GoZgmfD`YQI6Y>(_MPeW&!ulB;e`oLwDFBaf<~93XxImPr5J zx^25e`K&f;YL6&VCnI%fgiuGp2>c0Y&QuHIRqjHMDgowU72qk-{(Xg?%i>fmLc>u1b-0s{#KfYHu`SuYEiDcUjeLQtq3MEAGnU zxvyTdu?`w&@jJkI19#{kN%E-!;a{uab6HZ&Hv(F0sD;>q$4|XD?J)H}dm3rLEA*2= z^}2QI!8I~6rn0XtJE#7D`&j;5bPlE-a+)c$j!EzV zC<%UKrKM;D;LgjqI40JQ&02SU2ZA4|SS~1e+-^2Szshf}xi5l1=7jY>A6jVG4VC;p zNkR(FX_?<=(zp4EC29d`VC^X<5atOxmR}laXIW$%d>pS-FD}}DVUn~!KbqkD4y$Ah zm*3dA`uW0xFPBpHFr$ZB{}HP-bn-`H`U&6%HEKwAW(DLAy3A_cR2E>l*Z*^@a-?A2 zR}IrpHx53NgRVu(z|_Wj*7X}CRF zX-PY-95M70cq05%Mm-VfDU-|6fgZP&t5=1l78I}-xPaZg_K6LbxV09&akSEq)Q_xL zPi}dC*D}6Zoq27z38Q>mGNzz?l)B;XY028D?~?tlpl#@49cQ*xBK)>^r+52B-c)y$ z<;rbVC}_T&X8u#{3gxHNUi;=PZ*=|I&{apv_i4tdSr7SvDHb^NlzPT%NGLdXpg7oJ zx`)t0M@?l(tgHg}jjFx7SAln={_B4sqPK(aO4LaUk)fu#QuR3cK@j|E{nTHKUo~I8 z_MPOrqv}~Lf#au&<0*;iCx~}jB()?^@TDvP5H_q1k}dpwoFC*91sET1Q6M~?qx&%c5CMe})) z-X}{*P3;W#$zT)0eant1&04D)gkBLselVS4AZZS@*2sLBT^zq8 z9`KXg!Nxz!_trag?5ur4z&k+^XhFWF`#JbibKo;q!Il0?171?Lm|FZW%a_{G)Rqs{KV6=nE%!%7-hR?kd1he^lKRWt~XsZpxwNf{A9an(B&o{k^OMpRb0q> z#`dstYO|KSCb5T0{v^5BeDC>%@2T17#ePKen^Z6A;4ZtpI=AtqbV_QI%G_j1S7ZyS zmmaxJVI?xO5?o?3Q$HPC+=b?@{h+-y*P(c!@vFr?+IM&A@5}p5ysrkjrGAc~$8}!q z?a|e=V@tg$;eQbH(?AoAAiRwB*FgRCnMKF|4YGpnJoU~JcF+0=4x>>HF;z?N3uxD{ zArNS|5~#V^$>SG}Zo^!bf_Mbz`(!*WMrgTQr7ml1R9v*l6*iukpa12m0N5I-*xJ}o zInnVhD3rz?Z9A=0qesWos|B}C;-clN8P-i-{~w8=vr(F}7kCuwf9Nz?g}|?S!RL$) zmh3r8(VsF{a=;Iw;aAIGyb5EEQpyjO;nfXz^`Y{rB>dPI-hjUrm_3jGPle&Vd+^@B z@ICpbzLp$$8>gkoGXKB*i7l2EQpjeBwWYna#D1BlX@2+_)n^}M7tGhcPyP)i_HW{60@+W&p~YL3v{sSx?2|!q%pD>z3P+mP=OO7zSeX z;E}Q3-~&9}&uxiRp1oVB9TO{))#qiYJ0qJO_$r!pJEq`m0u9f;`VNSYf9O z`b>qLrzwXqxRhT5J6FQUC2Hp{&5ld9a|KM?&ke!@l(Y}9Wn9YI)^%zN#^7w-2U~Z; z$ZcwC06heX%dYMkT-`RfQjdiP)DDcn*?A6jo`#Xf)Xq?UJ5LRE9&_xxpmtyk&dyt~ z^O|}Yt*w|_&dqCsG*dR2)B%jaIS2`_Lb8RcC&LKFLAG%HR%IN#7p|VvFb3x!H#qn( zoP0n{{6IHvX*mlYhNpL5Dj$x^l*4g>E#m`&EA;@$6ReF-z{bbnB!4)`N1b%0#Stbu z`8Zs=WaI}2>|V-e@T6Alr!++{2A3imc>6q@d=^d$Q*Vv6r7AC*``lpZGqhXSV2)Wv zJM{=-a2|_;M^`uzslo34JIiJ8CmLL-DJwzkz!;pJ(qN}lI3d(dZ+|a| zbt?Bd-^g|Ptw9=U@m;S|i8_EWI0rSrLG^G_HJn6KA8j=sQL>Nf?6I=UmQfYn*)AV6 z8Y%$GY#(xa;0;b2v?V|kb ztxs*i7?7<|TIc=)*h;3Jn9e;J4D6LVI9=zSLX}|*PPrW@w+Sb$s5slXx50C*mB9yi z+M@K$@a%0*?Z6nEoz7q-XEz07=v^0YdEiSe<$`E z6@xK2vApJ(eU=_QAVppojbnaa_iaml=>tTjaE3=RPoNTf?X=7=yDl4s4AHC!?q> zrgI--a5c){O1+?ur*>cr&dxNjGbNl%qIQ_heTu=(B#xcw)DDcn*_i`&W>GI}=RV6I z&6Let>Hx;z94rC{3#bFOb6=3PgTJW*7=v@L5*#cKCrhabrgL8ohvNbHaKz4islk=n z>0|_JV-wie5Kh*GlQq-{)46ZJ4ZRK=uzP8Z!IN6Gn`w$*3@$}`z}v2HvLl>qqu$ug zeV4(~4z#E3kGGio-YThcpVh4Qbne7zY2m5+OMU~mk{gy!*YVlqBahE!PF*pa$z`>Jn@+h1~AG}yU6 z$lB|3>J`S|yjs0gNM<;BLyfYXd#1iQ%y?s{7cjj~>D=Mjo6W1x0Wr9@<1I2P)QkIIcJ$pHCQ`x zwnJ~s(~hUwFb1cc1lldUq#2cGdh-@=2%fUREep7x-pt@c?P8LHHP8+WwDFQwUXnsR zFkN{Y+_J5}0lQ~X44%{$vpr1?jKL-67x4Czmvr`$RO*fG%6~Fg>Wp?%jpo#{`IWkZ zF*tW!!Cjh{{7J1b{dk(e*`G!~%7*Sn?Z6nEojzbE-Aj5>J4`>GZm`pnW2Y~*17mP@ z27#Rc)C<#(4=^aJl{`3D#o?ehlqxd)_)t(ZYp6!hxxyIST*rX&D5}i%yC`CuHq!I`s!*aQ+s6zj|IE0!T7)0stmvP60iKuOV9FENcZw4{df2B>D|tm z^xwV8tDQfLfvffh)xPCPZz|08-hIn!y?1Y;2lezCKuy3HxQU@)VlZ{U_T7War*}WE z@4GK3eK$ONhf#GH16Lnap4W4~6B`BFzL4^1fwot8z{)o2gYB!g8D-TYW+&B!F>u{|pu30avOV=4p6-6C3uEBA$3XW;d2)zK zGyU`tINUDMe)^EXh1!K24@Uevh@UM_PM0SqsXo(7pT%u?8r0dnanj&N?WHf!q`(+> zQf`8;>*dMS^5io0#rDzH4R)@g)yqa>YMI=k&R`7O*&}fFpgg%pZ81Ic1B0u3MlZ^y zeN3&u7`T;JVC6-5@{C$x`sWu0E6+GqUQ;VD25!Y#0q$5*A58C@X;4+GHd}=t)ZPcR zkP2!e#PrP}70er<92L|?2*$wYmMQdPER&S{W^p7~vCkejN*7`S>tP%lt{d{lwt zr5@ORxj+SaR6xJ{5qy1#_RD#*_Vx+&24mpfih;MH6-W_kjO~?+f*Gbk%P0bt*k%TL zpQGUvm__!75e+ z#fS(}fr_%-bOcsd1%p0QVUaZDFb0?MYG9{I1gT8zuzhtEFmYW@JN~9g<*aR0r?y}W z&engxR%`^RMQt%1cC5iwErTnyqp3sfz!;pJhG6IW2vU#QVY=+^4R-2r>@=cwU<}TV z59~ChUf52%sX>}4n*{0r#^4+zfrA#*0o!x8$l5_NbpT^<4%&c&RuLqHnqa!`R&Y2z zln+PzO_LOZE47r3sx z7@VCUU}sPS89?nYo%tYxodFy>L#Z7YgR?UV?2MpZnC^UpL0PTm(ZMQ?2gR{ek?GLK zf}&aLHG$3*#^B~U1(YXIWwuM7WRQkheAj+Vr4C>W&cQrzFeie{iXbzn54KaE!yYTp zug`*ap2`Oe{-(){ti8^sUSSN*>vHhAG=eOqM%m7NslGYPSZt^lFnw3)+~L`~g4%-d zf3>x=B6RLswa&djWEJvJB*_!0Ht)MC!teS&hhJU)Q~uTUkKi}byV*hbmGaxsuWT84 z;GLfGJ1>=YUMhdnG2JfzO-Fe4ejKT`^)Lo!t1#FqL_O`TsQ%@{L9(SniV~C)n1sK4 z_+0zThed)_w1Z-?NK%xF9+DFw|7FvmvT89<9cBl;Zn-mx8XSO|VM+?%+3TPwfHAlf z6bD1DNFq{0$2CJEWkW77ktQ30zXm8~ZKwn_1Y>Z9N`s+Nk%Uk~rx`<~{0xz-4V9sW zU<}UC*I?)?>Sk+2^=~GRmb3Gf!GLE+|)WSkflQ%3fA^tR4PN zGrLfg z4SWX%szs72)WCcG2CDfPsKPN&BUl6f0Ryp-q!u;sik=Qi24ejT)Z!SZ6Rd&yU?7gF zKk#4tI8aQNbFQ9ExcJ}G#fLGt#cvAAjU!1zD*lvCeTKaFjpahC2ak+~tPMOO}8riugxV2qB4&1iSLYUg;gAN=Kv@={58w(z_tNi1gm8`F}IB z?@7*_Ia%w?ytSB3u6ytAH>b^)2@k#i#%DEIGr|xbS)YMps=>h@S;v=hP z0if=M1N9*wL~lR?0Mw6Yghy6C3BY<}4J2hmZ_2+wc`zvpkF3F>GC#G3k}{$<;v?$zqUYn$6}A;2OD1LxAXQ2>u1ojhgHl0f~>S8-Vzo9$D84 z2g)NLL~lU1CEzEn39JbIu>s?6ToNByMHBLYis1L+90?;-EP;Lyo8S?s1c2@!8sU+3 zhXi0fvhE^fL~lb;8pk{16~0t0-!q)Qj5y)3fU{900@W`r~ zfIszbJQ(;R>uCi>wf`OCN&N9w&HUr9>w&PA^o74TVlCA680+2ke?QwmV~_a1j(xuB zR;X@CV4Fx-{89dvgy@g*H%ScO*=If(aE)vu6h!wZyMVHTIK&_0@4yTkGG?Ghfxj@~ zu&It~WH+fJx>w(yp!yMhzR&>@LUb>52)B8VZd3U2{XvZJVPl?c|EIIVUeu05?I@`U zKe|7vP&?s8?Htt3B(PH?DE`>~3|~#BByC|eou^?&bU)13fN~{)T_P0mNA_0$u+JFk zZsrSZywANcGEmuM%-lZdP*ebGeAV<5Umxf3YG6IroD z%kT(4sxK~~6vHRt%Ct~Q5DKDul+r*cNgU#j=}Sto!ZNvs)DhjQ-v{-wq%Qu5zHH&@ z_meuJd-aM?uaL;f6M*pJ`3i|0+8i?uJ^thQ@)D8tdO6k$LM0%?C9+^5(}+U&(R^HD z^brt*y0~XFiN{(Nm1$@Y-4D%^;CeifRY_!wxWpgJKQ7@^;iyak6Bf=>#E0mfuR8c5 ziL5HY2|tpLNNiOlB5SCgClo~YC`mv`NMtV(ityw31PSFu1xhlZAi76+2`H(=A^a#l zRZ_Lq?#o`(>O!p!sR=)ZuLCtF%k&!EBcl6ztPjUhzMdqDb(e1+-XL{E_v#r? zPfuiNiL3!Jh(CT$7mp46_&p7uoH7m){^R!sg>z;SC!%}Kcfr{-k!2I4_@noxKoSgH zZnm^O0DQ=>c*ZsI9w8yRL3+e=*gpX2yF~UCA&D=9z5~()W0d#{p|9}CW#f~AFNCg| zt`pbDkA#Hi9;q#mS`&}(GN?7i<0{1MFN4~7QR@P=PKm4o35qX*IzcgyUIcZJ)IpMG z-a4+4u5{~&?r*&}V0tF9?gS&g1nLQZv-A?Ed*LvB2nNwT%pkxFNM!v8MtlJ@pa4w2 z!eIsz45E9OVSpJ*B*M#|p^~`u6d6vci0)NKLvGK{43W!fph|lyQJ`dt^64`7L z7hd+vDIh*uAwJ)W_+p4JBxT`6&qAmbICuDDFQLgsbU)cEpt?MfEhAy!CC~E2=u4hu zA_9NOv(k(721u_6N#|Ld6NtKO1?Z#t7$9tn#tczj7wcb_LQfTv@?_%mj>Mv5lUH=Riy zP>KVkSd#S}r}%=WSW<^JKN&Mn@C8qIQytgH9i)!vejx5nQoZ2G7b;0Yi0*~T;5JLs zZ3-`VN+)$_-QAdH+Y6q1y{O#}wQ{5;yx=LPPCq$>CM4kn&!ZAiSR%5X z=8qE!qI;C8KzSyKJw+(O3!Y~rl&2IZ&k+iudz2bLsZJc?3!dtdtguX8Aaz9d>Pb*f zAa(HtPeS49_=j%He_;dBz4|Lqe<_Kj5`gf6=Or9^y^KSTzu-xgh^%jt>v%zU6A1N_ zSiL0n8c_%@c_TMz2uo_S5;u~z6?G&G3rhb9YL8A&WXiKP*j_<|=x!b#_-X%d*Q zaNZ_9ME88}f$yCpmP2sD3!Zl*wj7Db8mjjR1<^gqe}VEz68nfygcm%YNGKmEP(CFT zME59P0_Ah!5MJKn%k(|nBcl6zYzfsLNmYEo^P?n- zb(e1+T9G=Ud-cvx@0i5eC$YA~Aim(~C>|Sl!P6d}^fe9={(`4%;hbHF6VW|qA8__c zVm$~_e8JPpZs>A*Nb3W@KN%L!xJG^^Bt$nzEfz=r)X!{S%_JtlWzPh_0K*d4Ty`!g zBYIO_2<7=nY%Yn5PJ2E-yXHz9U>an4U0frJ2nW#{&hNlkN-Uz=UW&;XWvrKiZhN#z zfNNwq5g>XaSfzB_`C_X{4AGm|dfe_>x?RC_uf=$eHs;;tx;J=L+ycc-q$oJ=O$x<7 zy(;d6;`SuAjYLKFy`8VHZIZsQ!gkS+BYGS1zk#zqiR~pE(Sh#=#2{nXxdY!@IMzYJ zLiC1p0$9hA*b%}KT=+4G>WD;TJ-AO24x%@l3&1&-#Lf_o;Ka{KIA;_%7YPT^8_qT0 zTp9g{j@*?OO?Ey&ihISl2NgoEe} zhXE%(nN=bj!KKGbIF%GQj}i`|H=HMd^Ej~xPW^F7*>dVnc~z_m#b-!SaO=-N(aCx} zNB4^8?OvaUay3#G9eXuN8f!7%e$*fWL~jHsAV^MTiOH-cafq%xSv*$Y+7t1~MB||0 zuDxdAtf|C`=#BONz*;w%)ge&Pxz`1jU=DNZNb3dAqfF)(~K2YqH%zBWh=-hkp71l%27gpHMG~|fhhI}w^1}3xq zgd;llfq_1apZ1(Hp@M z5G+b&3kX7R?u&3ZE;0^B?%WqhRF>0O>J?)RFjghA70GNlkqFLx72nV+Kp^g=bA$l94tzg@d%r+&n4a6oo_bn3ACXTy7f)f_fHey8d#<&-ZyOY^Y0u-G4Zi#QF zL}d-xKEgrthI1G=|0J`&2}f}5|42B0D{zhw4x%@llfXGnEP``CE-72<`IJ}1b5J}( zih^@L14Sq6b)N1O(c8UVhVn&H7M=S=Ng8W0-+o*n0z_{FzFPRZU6a|(WOki6MCYC- z9xHI}H}T0bSiIIS6H~7W0$1=-jnh(HAIwi33b4 zOy7)aBt$rf-f-f9Q;Aqa=Uxeuv(8vE1)ckPlK|I9mA+HUb6ufF69MQR_0AhtP?A*C07moE3VIg|Mst2ssYOz-d zOK|S5NmQ>&RMrFib;3dPhLZ-I2DR9mgd;fj1`^Jj3Y3pg3XB0BdBNm^Jo zZxaEcH-e@h$R+~Oxn~zn@D33mdL#H41RvI7?-PXJ+&{$OxXCyixpRMCqOzRMCtfkW z0>&5ktBh)~Pl-fu?qBc?{TT?vz4WQXWUbn-X^0TL4N)twwW!5@!2e5u*hJ^vLPGk1 z<9;W>2@9z;F(P_n>KSmG%qBnvGAQ)eZjm1B_LmZ-WA1@v&aPDLA$yVc_;m&<@;j9yh710~(EU?bN z|J#5-Mdv=lZVq#&N$UmB>rCg4Yh*TIA-clKjXL*Lz*<2}f^%O1fbE8rusQeDq>SiI zc_Wn9kF%UKI~P@gOM*&i$Z5@vv9L zlTbX4zx{wjMdyB;udt(%zOceh(U2p08}f_5Igfu_hj2vaejX4zjA7@_{cPb_mk0~d z8`i(Tx`F>=3SkM({f0z!O`@_M=y`;L=ndyKd~;JYg%wG0_=^dOrq~Cm2tE;4tA$f6 z#d_g_=nba?aPA-$(YfCtNej#7E+RnmMsN=ZN)dtR+)EWsP=*K)y%9VJg8NfgIf4+J z`~4{$+8i_vNABFqNmQ28Deo0S2Sy-;#ip=_i9~Sjft2XWo>&lwd+A|`$yz2s8X`n* zL-Z)v!YQnB3VVduMCTrskScTBMiiN!m1ID;M|{=aH=VAUL+huZ#c=oNhB7*xhG1>)_ShxRq-V#rjnxI+*6_G zWW8RddqwniuXUkZhm=Lz;VM$*qnP0QbzQq+!xAyQdln%7oB?_ey;VBIKXt$^v$?N`VkJIH=M!1 z8AvRmb03Jw>8RP9dne8K|Fq&78A1ez-Ux=Jka?2cx#x=wCox2CVxw`pBk6Vp=ROkS z-3fPVckW}nD*gt=ail0X_i+lv30@VaL2*h7n?$0bbDzRj*d$3`SYgv?$Pv8_`CQ=S zrm$IrBRcn7K%5ku`>evT<`EX6H>_pAT9U#R5tiWGmq=8LBr5BH{yX6ydc#=*oK-1o z1>p$q+*e6BD-<|u2?x;|&L-e&AQsWNZ;+&gWwV(G5WNxn1%jwU9JzDfB~e*UXTMjBW576)!VaadgG3@Y_al5m9|D26mkvry z)~Y>DLxkvUh%SKbTnamr!cGyJ=-kgqNM|_iDG5$kNEe9_(HrAUFkVk#R|!yX?$;&0 zs}hwpWd9NlqBopdQ){tXQkgH+`W9Vq?zg1cXV8aF#K)3_b6cwQEjpq%oI8P2oLB_s zUR+YP)^iE3ilv}1RXA4Q+{@#W9>zh#o%;iYv&IrDqBqt`V2w*`(>dmOL?bC?^H z)(fCJ8g|jRMk*5)qARTXiqM~P9|o+U#3VTPp#bP@I5?YgA5O}M-jv5ed2}ipN#de& zADtR~fihC!0Mi-Mx#JocM>vSya3%p~00j--iGM5+W1LPZC0cYlnQPH^rPh4Rk6{}4@KC11Ju_PGps?F{sK*71+CGp)UQCUM)if|CU4cUFbDO;PB zAsoTEmz8kJC~)p497Jz86@XKoSOn)@UQ)K!^TS>h15k`5MZvkpLea^3X>_lM-tILH z%0W^VoqJG{##+p`ACC|LqBnxaK~SYOW3^d4afr^nN^Rj-fpcg0WSDW#aOWOhIO`L{ zis+5C8d#sJ&7LJt(YZedEWsS+J}a#kKo2mTJFb!HgoXIOVjacb-dNlG+Z(^YpC|pS zfpyRbuKlwH9a@hx+?&m{f7!q~L=fGpeh<}e8?diQSaj^)Hi({QUrP+&8EyJyTq8da z3Zi?I)<9`V9HLuq*#Q3xrLj&5y7h^sIkuby+Z?)Q_mObNJ5D2g}UN4JJW3n zF1<6xc%m`SHkaPbi&{^pbtg5!p?6oP_41niC-6M?y(wGKp6d?(&e2hdiN+Plz*5e5U z(LKskpiFMSCK8I^$R|rE6BQ`a2nEqS%50#_Bo5Jy&y-|^Ws*zki0;)FKz$ymi%xuA z;pz)X9nrn|a;PtBz?Kkz;KG;T(3@f$dfbICk%%nU@`o3M4M14efURl3RuP5Zz}N9j zy9Vmwo>?XFSSxfR4Gp6Eq1gehzZ$Tu4cHdq65aP-63$kRxG_1b(e1+Zjd^nd-Yoz;)f#* znXe(sBL>lB-_lSxHsG>-_+*B0kZ_lsS2*Ww4e2K*4Lxv{1m|51*_{n7M=Lt)yMQDZ zy4*V(+RYDuCzuW!*GMTsLUc29FPjcK0Hj#r5gc|b#Ah3Jz~-_5(9YVm>w6`NM%AnbdOR6D2zBnhs`h{i;Oi=&|xn&)p3nHM(T*})t_pp za@hGoPm>U$d!grWo6pj13J&{OjPYV)o^1|0;zg|n)T)!3;IOMJ)L!tSmJGGThO8zD ziVi!Gucn%kwy>IN(J&*rALcqhdAT90O(>$nei;CBjG^WZyLRD7uM!fXd!#pkRKFps zM@WLht}hYQlZdQ`@>_(0=pH2lDCrGZ8leadJ6%FaQ=nuL3Zi?IY@qyyI7Em2A4yhN zCOM>z=wAJOsJ~0*%w41IP7ouru_=);-2|J;;~lf_cSz!?uVuwxY{&its1fx#3efHHWE%N zj@m*36BbT;;zM-L_Y?TKHe{U%PH@;=CAQ8Iku_A^2?fzTN?)M#X~=pJir}#ONGQD& zDE$Zp(LKswpbR7q!C?=SRIRl;#EaT6s0}4G!C?=Dnv-Q3PWOoD{vJm|btI{Z4tt~| zi*=W8AI6Y6qI>lzP@mM0O=!r*6NBimCyB=f9QFi!vcfn>xWgV_IOkO2M0C$N7o52b z*(`z-9d@qW(B;mO)`tOXI&54c^9Tvi4btnT!`=v_^~57M?DY^|ZP)>u!`?)yi0)PY zg6h_WYzqmC4tpyx=q1hAHo=KG3MFku#b9CI|;Spq$W7*;|jG?Ueqo? z?Oa24h6F{2eU7iDGm^Hjnl92XBf1~v8$h|%kX<1Z(P3W$z*=Ldxx>CvIMPi*LUfOG zYZ_iZq%mKb^=-Z2uy0AT6Z!CoxE!p9@@;AKh9S)Z%3VOYGmRA|6v1KNDWMcspxjL; zi0((F3{XlFhv=|NOR~Z;xtG)t-K#$U_4`O&blCS5uKpmYBf3}jL%m`et3UvP!>*Xt zq0Khq(Blrff<$Dwlz?X99Cng~lAu6IArwUSD6atJCE^eq_DhngwRY=xQTsor)g?8-Vb_J4lVz$$ z_lW5J9^Zs&eNq)2c6~_}>n`6uyhZAW?$xuPo{`4V(^wiYhz>hLJT~C4)A7kp;~?P< zJFRfew}}(cJ?H!2d^e3XB}ma>zY8S6(B(Fj)(3z$n+_Y-$OnXk=mzO6(_#Mzr0amDCa4tM^D#y~EBI>PbR~?uCBFZT6g2V2wP#fe$Z5Y&srm-O;C_3z+d^HV`w1w3)oQ4_E{VEFO-W;u2uX0*QzW8E5|Q;#o=zx;?os9fB{z-DA{4=4 z=SnEE6e#lu1<^gqVxTM}4$)yRlw^fvvV_zT-K+lr_1{TdblATauD*iQ5#6h=hx*zy zwweG0hrJeu-ZA6Q;|_bZL}a;?4PFqo17TYl`!kJgCJMn}Z{wTxPpFG~X0ya&tGnp=5KKAPh)%2*lywy9rk_+XD>(HErAIO=OFPRy5~CqzGG?Z2*C*s`Lj5cx<|PHlyhn9450`P`<#SwMuBpXP!QdtTm#A#;t(A66-m`vyVt#_>`cqvRHTd_Tg4iM|7`#H`GfsVs|uRw-bZt zuuC)&jtw~MJMhUV;~?P<`}V>)OA;rdd(Qj8S*{Vgmmo!lT@FZsq07A&NTT@x@FCM- z;~IH@kPzJdB2%4m)3{76~D` z7kUY|nM$`QIP6r6@ik+fZ4UcoFKTt6R)^FChh0aZ_L>*9H=$O)5vxanqQkDwS5rMn zTUbqR(J&*rALb08q&H$|gd#fZbO4+;hMGI zsDDlBqQm~WaP{v<9nrmdYpAzu#C{|I!C|+=p?A|b^ti+RQ6jQjN*gZ-U4hWK5$o89 zwI>R}VRz=6wj;reHyV|jaU!j5*>CQ38xoF?ID2)3#T9P zA-d-q3cewY*dT%v9QF{2ZIDD{4b`uNg6JM)3{XZjVj~DeaM+_Hlo1M)v4n!?9%Uj> zej^USVgDwnT5ETb7qw|nn?h=W!=3^)C(AUQ?h(=bJn`6u#XvF3bgXpjqiN^*U_5ys;QZMMR=M~PmlsFOHbFKmBszz)DL5dE0mEF+g zu8`ITfUlYk8`sEMLPB(d^s(u%j{)fj@dyt42*lf9gzOIcIH@AKS3L{W(~a0k5*8iy zX?|v%lo-I%PB;EeKU^c{2nEqS%4MKjBo5JGU&Ms;Hr7Z%huz0i$2D?=)DhjQ-%vX2 ze4(2pgy>$#myUn5oP74xEY7u4=d zXT?cSbl7*MN55YyE@=y^>F#vvO#`C)VJ-`lGU==|p@B5o95fY+% zq=$j@P&#{%kOYVQkVN#LL}WdbD-sH#dz27R^mG;=6v1KZ5=uaU5=SVA?oq-(sZ1QA z!>%mJ3d@9%I-+~^C!qcqsf!N#vBK4#By~jh>Jg|{O=r&#fZ(vJrgv!5&p7nB!+u60 zvRq0vF9=CMNJwWdrn4GEAvo*=zG+{Cy0~X*NIcdGO{SqibU!q&g6oxZ_EI`aB`(on zzarth#8FcvFk#`;B|b#=d~bp8jdb=p!3hrg4T9wiefjni2pLJ=Hx zV+o~^0ws%35Z$BX0Hq0W2oAf6q-w3*re4(EhuXWOCOGVOq2^?nKA?LWJ>uzlQpk>Fo1#)|?nbhyA5^Y`|fEj!y;|2MK?N-MnzlZ-^7o zJ!flhwoGR~5~S#`TLMWibh$rD>jS{O4U1=7BW(x?(G60IJu&pR0R9ZD-ozxh?A`$Q z#jpgn_tkvXZ=ZBblL;?+0|d-0MoCg*Tpq5gm4hO;S2}Puf!s{?O!oD zqmA`a&~1+~32=>!AOb{h1Y^=w@3iy9#*!GKH?ax0-SKq0g6kfS@g8H$yUle^^r|=& zijzrEaNd&@iqpI*=0b5+I-5bFqWhl3SJ(_mUsz#tXvh)04f$f=EKFzf2}g9`3jy(~ zG3?xd&o3Nn31K06!&(Kb73pj_VF@mLg+#SnqOu;`s|g3u8_p)+Y)EJ82uE<@8zh`{ z3Y^V^gXj(CFW_t?7SWAwm86Abvz-VKy%FpI!7d^Y9r>=p3HA~JqBnv=AUK%L4iJRk z$`9gj9B&+s+?5}Ys4Qo5*ek{vV4O;4C(_w5A`zVVDZZgkfI!?!$0R0e)t;pxLi9F7 z*T8lqon1<27l=)C=T{`8OC0xt1Sc${>%@rYjq#SowV1Cl%OgO+q5B%!hb&K`vWBc^ zW9wxEqBop7fm6IOE7sV086&v#;u20Vd?G%UESwUAgXj&XG;m51i{R8tO3K!HzQ?O# zIVj#sih^6e7m7~S>pr?yL~r+69?B1pvgp_!kfgB|^X{4anZTgZXA89nIdt3X}al~ zagDq}IEdbG{tq~HiA8kobul?}j5Slxxz9BTaE;U>0z_{FZ#Gsr_k6LpNDR@NSR>qS zL%LnTxi`dk&o$=V=G@c0DrP}3gA@hlo}o~D+pFR`P|Rt}nvkgI+;jK}Ya;0jE9_kw zazt-K{t0kCYRo<$9MQRd1c>Rzuyg1BLE%`<2n*30)>pv#qA~l7umtD+g+%q4L}fie zza|_+Z#XT0^Fw3y9pMPh{Rau>I|WWl!a?+g(+)Uoh(&bnZ6s-7*|aADL~jILK+uT@ zMCabAaDuKxfar~&Hwbz*X59%waPB>EI4&>_NABFaOH`KA>Ejh+2rvdUW&;|tencWT z_d$F^4*-FXP~MCU$ALK?wwhe>e4LK;hqh~5~d zfN@e|Hh};I=RQf|n;=nHLpGIg5WV5#0%ulZHiK{k=RQlqnW4a$LpX@ua25h*KCuYS zeZHh@t>;Bv6_-JA2`LKBeF+qutk>^!uZZ66btRPlAZ5|H{~<|ZE#}*gRYZX3jbJkf zHa2GK8?&{(0h(JAsPMeW%?V=5CkP z3!vwi&K=jt9>PL&g>@t9+>2z?Vlf%kx4nXMkICrJ`gg-h*qr+<8P@mQh~AWoL%CQ6 zyOqR6=Uyx$>fCRYIKcFW>6>wl+(9^q-f&6+=PqIqo%>xG`2WNjYo?%c-(nKr8Yx8t zh~5b9%}_b_e6g}5hUiV~0o?9=bi0CczYpWR#h7=SbAQmQ;=@pUh!h3q{*XekqF2Qr z6txWICsEP4YkY0_XD#)|_wz=l;2b z(_De`72zOy!}%UK-x7=9+`pBSt@ZqaSH)IPY(a{Gb8i7fC+pRk?iJD7y|#yPTT&LC zds|5wYcbz`bRYsmZv;I+@KXlsn!!2~hv?jY5|0%)_pbP4r*Y75=ia$+)}F+Q=#6zC zSo>$Nz62^d_x^TsnA=xcFM!@`I(J+ng9r=pf5n=cQP=mJ`RCEs18FVs2(EoC#P=9B z!sgmHkSd~k)vZw7lEF5Su;|#g@bhew!~mXsreDT2vW-v>-J|RR$`0ZX-TDqp$RT5$ z6m;u{O?6x&yGb3h0HkW?bi`sFh9VIov zp&wPKo$#V|4r*sI*eMbe-T4{5noddD!fHBC!;I*Dn6CllN(Q?`D55jJ0)TzSP;+N~ zsc@w0goNlG>6T3VfIO4s5t87_eVKNmJc-D9SQpKtACPByK)Dkr#WPv4OzSOy;K++h zD8=xJxH2u25`=>2epE^Wr6h5PZoH%y%qy&zNqLR=;bW-^T^1P30M8GUIJgu1wAG>OMr z7L{pe5Zw>Wli+$hlU2!NjJQPi{kVivg`+YFOjtNi5g(#^zUttMWU{IRCphnj#8y=z zvWDt;LP2zok_425O!gw72(CLpLU~bvl1wOw?onO>N-A*(jyqLSwbt&-UexMBtq!RP zZo3ZDoGjC8bdQMc@3B5q>yfJHwChQ-SajS`tOoxqYll?%#qQh>%&#WIL2JoCWJua@1)`WuS z9;E|N+7XB7u-jomt{Q8kpu@gqs^c2zNa~30)w^b@-i7B2bt54}_d-2!o89R)1&7@o zV|>k+XPd+BsKc^~IzvI_$-Tt1lyU zMEB~ep}sPc{XqbN!(NF)@1}9+afkhfL}a;?HC_<@1j6P_wlR~fCknw~Z|0kJBhuGuh5eww<^{hrL_E*~wA2OJKsn*++bc?)i>@?@%T?NN|F~ zJ|wXnl!&aMI!Y*r?orMF3hF=?2{+qWgP{$*RTvB~{U3|0~I2-R0W{UzYW51kt_v9ZMTZ^E zioU?8EHQwmUC{hHRe~{*DujaQ9_1;ZJV6|y!+ru2(#2RK1s!%*QytgH)1;2*Uj4Z& zmBY>#ijWYZd!ZV*&FXZUg2S$kG45*2v&~_@;6*JFYBfnsaM(2!YDr$yUV>U`7OO>q zqQg$*tErZxEv%-OX_yh+4|6@Byq3jYB^1$NzXpJI#!z#I{c7PzuM-lYd!$A{YM8~| zA|%0KHTxi0;)tf%-?JE;{Uw3RiDN>WJ>uzl8edS*$q$2oC#m9D3c2LytS`<`R+RQoizn z&=LqgX0h+H*tbL>IP4$!ru`o3;-2|d;;~j}D;gR^_e0YeTphDm`z+R$xI~BDQNn4@ zQQJyj!oul7e2DJ(dV{ZL7VA!Mg2V19v2~Y-tfA^dD2VP+1_5P27VAeSg2Nslq4ZOr z3?>vr_b9`FGL$$3hdoqMwbt%%FKVNqHj>l?hdmN%PL^p5-6Nv=d;ATm<49F>*yAKw zth;>sFoDz&-K)=p`t&R|HH%Fq2GLacy;b_VeDH$5({k=wE@6h!wZcLJq2 zaflAPcsBlju*MoG=&;9_>bOQqkUFA!^-|d?hn+7}nuHMD3zfxfmZ94e9CjIu@fc&C zZ4SGf7qthWc0Z{J4*PzET6r&OeyCNWf54TM%`&oCI&p~(J4?dJ;Hc>mn6Pk~5Fes@z7N3nUN(D&-~@;Lp2YT! zL}U%shlGOY9;G=@{+rD{Ar!%3|5rl!M1k@dp&+_P`5Gu+5{KZhzm!z1wfl`1wI87N z9jOTp`#Y#PS*9Q99ueK&V{53kBvsL2x0GbD?(*$J8&XGfuih2vowHfTY}TF_M2Fp3 zJT~C4JK~c`#zDdzcKgCPyAda%d(OV#?32xU5v1s_``8U#ZZBzl0C=?NuyKv_BP2vO zNY z3Zi?I1wffc9HPUXhY6W)tdW8adx5ErYh)p*Bf3{#s&v@-Ld!@9(Y??L+~#t+O~GL= z#~3d#=Go@3S9(!f3$@jxCOGWX3bl1!)V4rvQ#RW`f}+FT#8=Y>Nn2P=f6_1`x*z6U zK-rPa{vs67VebIIbYrNw!~Uyqq}_ys=pN}GApM=q_7jreu>Y2b_De+8L-`P)Ai766 z36$g6>?olK4*R%-a#VqGick>UqnroIS>g~K_E||*SSA-p9nrn|Rj6MkbN?3lK|JqFd{(o zMldQz^-eoqY&3}>dJ`Lu+Z{`{E4c2l81MbYyxUy&Z(bEALvbQ03eJ0?LUD>$#aU3C zk;A5usOY|D@D(;q(ic|PY#MSzZ$rKiIP-JZT*46@_coM1N*AbKM>2!aDSY#%`guKWNF$AiY<$X)q9iOO;| z|9HhX1&k9p>{t#vLL`DSKfyQjF%XD*>4?N+t=iKxM2Oyo=nB{_<**Am>>RO)?);L3 zbb;fZli-Afbd?wpy)pWl;+v}+c9Q@Fhn^?#-IS=TAuH0<`ep{v8%}ZH6l=$#Ly#e1Q64=D<6{T?VfS+BBm zuZZ66^#Lf~N6MmOzfY3JTFkc}4-x^QHv$a={-&&AQ&xdEMAz{-5vb_gJdI9u4)4Agsd6cja|5vP?_to{4s_QHH zdJN+0F`?7%)iU=^U0>7Wc>D?l=?CCTjb$?bt|?g zdVg$8-PjiY#?*cCuEzKHiWYt7_FIB2CgXd7n7bF>6H~Ho5ksPEUEjTiL|I7u!zIdv z{*Fo2!>8XC5{^sAydNmtqX}tb$yQ*5|tovl1o$$ zosLSJG9=hg)K9DSCU1FQ&!qrD9_4DstN` zzGXaRan+djvcHOH=R;0Wn%J1U}_dX}Bi+i4P9K}+qW`5r6Vdu(+WQ_+^%_{R|an8+xs>&yLWfkX2rmC!p zN^3BmR;4`8n@4OZe6J<&lowPfuke)Gh0I#YbJ%pvzP8P1iaDdns@8Av)~_4oPJ7np z`#)PXUrz7w>ZZ1oI?>JBjHi4gPv-}!sxNp|b0@4B6Nu0$4ao+N)}M^O_#^HI!tI|4*vQ!Mt*Sb7enO zsw(&J%AL-Y+f|hZQE3h4epSj*-u#d)h3~afJmt75|D{i-UBSH(sgPPm5A?vGHOd6Y1G zVa-QnTi>*3{u4Zs(n!RoQ@7zM)FV;3nI?cSgA%%fxozOd$FpsnxQ(fr{&WvD7;9G4yqVBshksj8XEYbI55JW3|0 zD(CXb+0Kqe|I^6l=7%RC78?{$nn@O{((!Tw#yA zE_ONJ(GFF!l{a|hRp-jfs>&kOql1~JN-2gE>t#aG z>WaNqf~OQ$rIh0-WvZ)Zt#oy#qoj#Bqa{_XV|nWeM!EeP9AnS=eC2J`d}lsfBYJz~ zYlyekG`e|%JS9*=I!a__Ly?`4f|Rn0o{W*wZHwNq90 z;+5T$LwNInwiLeChVzu6s+0*lWn3Y%HpbX=k}LVboY7IL*0Xr) z>8d^J^G&r?^PPEb&FE25x@Jt1rXLr0>(<)Ty{l%-yTZrq@Ugk?%cIm9y!&g$eE4pG z7nL2NDFNQSV$GQB0vWx{-W61Jm3dv9Sl7a=3##g#;B{4;>X@poDzAH5mGV4KiKtSN zkYWu;&6+WveEwO1`?Zdv7i^WoqvP~4uS|8Wtfi`~$1CePSJqKgzQu2-zAc4MUj}d9 z2*dedOuHiVzCGacHB=QfpH0F`tZ7*PIcW?bpv@_KUK<5o-$aK zG8!q?Y8>IbGKSeI7e>cvBCj0pTsc-%IfGYDb*`MOs+_}bXqGL7Pv2tRd;x}2T#fTo zMJsvHaunHC;}UcJma1xxa;8J})wsf}JYZjqtD{4BhRdF`bzd7zxy-v?5Ld@$v-dew zT^_HyA=dqF)?HK86-$Vo^hFbdv)HODk|3VpobxVTcZVwF9-dNCmGS^mtkqa9!SQUo z*H-ygbev*&Wd-NT@~X->Ua31*22_<{enXXPDSTL- z`6qbFQB}%$E`0{Tg6Th{s=3Z;|uOy-pd&Xq5!DqlvWHJGWYl-GFkI<^$P*WTbM^;9XDJSDx5SxZZF zGX1B_8Ev3y{T^@K)F`*VKQQ*J&zEhh=8N)2Ui}@a1$TeJto$m`X8JGVV{_lPL#Z`* ztrNuu#?@#_SKhr-qVS-}GkbSX)%D?ZJ;l1SW?gqx-C$lfz^SgEs%|*18>&hf!&648 zQYInA8j#--9UpAtY?Z#!G?X)WER`TY{F`VLq zZJDZQBQIKqBHM$lDDK$jTdk_S$(gR%7HqNTP!&z$CwG!`faR&G?%-9$k{mWk$!PbI zlxHsRd+~)epQV$;Grd$a{{fy-PL&eNr7Hkfc(9dM)jYy$f=RZ=Q*mLJY|zAWfzy;Za+%4scH`Ln*H`Q^pH9J zdsUSudF3(Z$|I`Ei@frjbLAOT<#k?pMU~=9jy?eXRizY1iZ$A|B|9A@mCYM3nk*jb zd?w0pg;L4VBj)a8+ktG2VhL5V3cT5a&XxDe8s${YLcE#g+{~}4e3VzlJ6BdxRX&AE zYcL;Ir98)*KVwVbd#wgfsisOvh7X&sWD* z&DTS7Ufs-=@;D03{rwG3`BI+F&s9||c-8k#Sk)d^o%^U>bc_xWi4PdufI zD&=P`-3!2iE9s%C8NzD@+SkyN<_PvzRgUJBBb+OTsVXP&%HNzT$Ehl3@XD#Gl({@* zwkl;QQmoNlSIDg0bUaFu%o)9|YF&c2 zE?&#wC^7b|&sVIL_-Nrfvm&p4$d;0VLUVtIc#2j_diwZPRbgIL$qDP#X!pk{&y;!w zUs&_;q^)n=Xnr-GQdO0bz@=XRuyB+-uc~>8*QC_4Jx^235lmK9zRoLObFO?sjqg;=y6|Qlotw2+RrcnUJ)A3lQdJH>r8Ss+RVlyl=7Vf0e6Nk*DZi>xCi0Z= zh0NMmW7A3B;Jj(h=x9~z*}U}()t>eFrrE0b&Ror_SJ+Y-MmO&!p0Zw^&b6wlzj)Q3 zPFPvd?z<_^JW3AW3u`|1+WNj7%|Faj4ysa4ap~jsqvWWn<`ScjdJ@pIL4m!`7&+Qd{Oq` z)!l3A9*@^sj7zXs)0^e9i!ccQ=Ta`247h7G1AtzQ#5}9PZ_65na-uB z09bG(lT@_ zNwuBs)-v#=il;kYmnBeX4Q6pwN@?EwZd(f9Yvp)K8C6OwPpOdV^Z>ACt$eD}QPRVl z(FatmEA!TIM!EecG4`y_7qnIL5g5*^huTtlqtM*n<9N#GRO#t6QdKpXS50uj8W8P1 zgYrzNIrzewk6E_91Ecv1dCELh%5pBf6u`n!vRGBKj@PWVuc2n<2(DCBZsV0(oGUk} zD);irUCxy|RF(hm$^)vD<2>bvD&;&xG0C1H-1W0ev>O)lh?%+=R3NjYF4av zbPpG;ZQH}v_!p@yt-YAq;I4#O4=8Z2=m2cz<>*RH@#`%s`shaKN&Hi$(+$w8qQ8hcro9%aQwpUeo zf>$1Ot~{)&JcmkaFi)#eF7xIWY$<%N-QX!#RVlYMjPBT58mec_*U;%GnPJXoo~m^z z-uf=1+v!QrS@SUmg>R4OKY!sUNyE0FSYbYHhK~>dbyoxztEsA!3n(|Dk z2)?l9<5^qZ#nJp1cuI9uN-Zv(2w>qTsi~@YmDjx7&~}u}F-Ners`4#fS>L&`o~kmF zSEf5xrl~4(c;$aoDIf5ZcU39Pkz$Q@Gsi`_%)IfBRpsAvg>U3_@s;x(eW7aBo;Pdb zT-i$2XrXG>oj2?1+^n;zvLCPP<6PNGRXGHe)?f})r3~lIhuTv3UK_(xMygV#@{~!1 z%-RIUqhy6SqvKVr=keCLsy*xT&9YVVowar<(jVOmePFP*v7Jr8Sr@sZ#3k=5=i; ze6PL5Q|hZy-sUM8h0I!dnv*NpY0hYxs`UrF^}9y7-IW-7*5_+#tLDqO1+V_zma+$h z=KgNaQ`*SW*-BN_l~;9g!a5Y~-jni7slNEanvdSLzK5gvgLq1RRmyNKJrux#D;c7y z8P99R*w@fLa|B1JDyQ?xDbAIXRF(61Wv+AOELG(aUb#?}vVy1lu1eW}6l=8CIxfm% z=8dmbmG9sR+vIier}G_cRy8}wo9%b5+$(GBRy8}xn;mm*c0^TqkyoB`t~{fvypBq1 zFt4amVj4vsIyY@8e6QWgQ;IYaA3!{%Bu^>P$ms!K&DtG}oQ{%H=8WF1YW)CjUCt=C zA0@_~_4)3#Rr8(s6t8~VmU0$_=Kik6Q>r$So<7g0s%rA88ctYOqupy!o+e>1HR+9P-r~GDf@!MCcX?%wb7d1%Wiwv+k#pq- zs>&~TWph=^cRb~5RZ1JASfkz2aZ%nhZ~RA9c{i@mSzZ?%o$sibl!Z5Ersv3T%Iyhm9mtlEGlHy7C0Uy zzI%+rV4kY=THbnqfaRh1Qa zd9zoXD_@c|QdP|w@Mdo~H+x-GnZ+v`J6ASRRW?PXHJD9QDIf6W@7hxM zUTelvK2oK8!&AO2WY#`UcXA~UnKRm4)w&ID-O?zxyAos1`g}jys`<9-%d30aQYxa* z+}}fZ%0PKK`>U!(@Ty;(u;QZK$5NgtH4$G}^D*Am_mOD+G@de9l`@A*&$1sSGgLK8 zc+Eol8uFVXIA2w{npduHu3WCF+{`OCI9IMyRc_~%TU9B0dCD$T%3-8fqkYhEQO27$ zen3@zmMff+*To6vJ36LncAYo7;#_%2*0`W*RSS>kJKdoEa$nWw5O!7Gb9R~Bn5 zKEL?7ya$!mV3t&++{c^WYfIsK?IE7>fGQ=#Q?$lT4*+Y{{EeNCk}BqmR#dfqjJIY+ zx&0_H_N>nrZ>#1bkj$$SY$;Em(A?jz@RZt(rKeAds;VBZs_TRmiFSXB@=U38d|}N; zLtEc!(fqf0N`@-sT`rviVBs5_CaRidyyheO8hXkc!4FiGU-QZ@oGU+5Rkq}nKR8!@ zr>bnvE8D12y7H7xs+2xRu|~V6qqk|@|1^EDIqSc0a!Rn{HmHqc};wV?Ln4ej(;Up<+Hr< zDd);3RFyCA%IeOQ5mjX}uS`&-yv$QlRVl9{#TxC`GMt`oZ<#m#s;ay(S4flBMFZzM zdQ;Wx9o{V4x$-}Ms)LT<0)I@ z>D;8M+RdwWIAJx7c0WLQ=23DOUs&^T(AM{zX#NSFa#WRao=cyxA0?+$HP?B~75f^> zGROats#!It}K=*p6+}Q?%|asRVnxLl(MRnSfp5^T_Mxy zD0$z!@$#zj%3L8XQ+mV%o$p9fHG7ITd)&FQimbs@&7SAYBF@dKsw$ItWrB0%i>k_( zQE3fksw(9*-n@=2h3~aDcuGB0N+wT9FJ#uzGM$c+kIflvplbadZ{5@=w||3U>{96-_d$ivwghTZs*FKvc`5*v!lG(A?IcX zRh4IXcHP+HF}*M@dU_ zMvG>NPbjWlmbbpgD7POa#-8>0O4+LU&U}Pd2W=^BP-yP&Dm*2eB|UvAtE!&nRZlo! zb%}P5P@XCE0=}^3qq?nc*JyqcPpPR&d6`S60$4aoYN={o=QXco*}O$Na|B;iRi^XG zhR&65sVcL1<=f7cnX1b7dF4B*lx95TBUQ>*NU=uybH_#5-MsPUs`6G`;YWF0eD8cm z->RB*;mtZaSGJcm+NzrM;mvwFH|wsd9Ly^RI9K*lRSrj`HJC$HDPwr^k+u}R*Cz0k zajKMAJY{+zvo_W7DCup^=wwyv#k}Cwb*#&Xtdz zH*fqURe3|M@TR;j>O0?2Jyo+NyjhlWWrnPgu4?unZ}y&Zvv*XLpYh87I#+(8s{96( z)?j|AO8JpD|IU`e_gWjC(o&Vuji+=jWY#(wn@)OHGRd6L_NvzXc8h%QylS2k*8FJqWt3+gB`fiTH6P1ueHTRY*YT9qs+2#u z^d|dJvO!g|o7e2Huc7JY`2VGag zL(a_}R8_|DO5M3KpsHl3w3cpVRmu~*c@HEY##oQ{&; z%^8iTTEEO&ryAw+{vJRr4wA!>fDRQdXeQ+~0$EN`HAe`>Lvj@v2{(u=Yi} zkET3R>Nk90&Bs_<-~G}2DLiGODrGj8o&jLNl}uCBEaElu?Q3Y2If8Rll`DDWa_7or zs>+SLa-DPK8dc>sUb#h;vYV&uP^J8X6l=5(I4;VA=8f-Dm7nGcC**Z;%=wOvsG42n z%`Q1tUXV4;shSmO8a?FloSWTLRo=lXi#4^Kh1N2-wW)X(@^x7XmDXV1rAjHwo8Mzg z;d|{to^qcmMdvC0rcOtRHER`{IvpiP%o(kqYW*m09dDG|j}l|g`h1ma)qDi@{?{6H zb0;4t_{Bd3zc^Cxi{k~qIF(^gZ^`+s!}A`7}K_ z>19^CcKTP(Je6KA=fj-0o9Co|@}Kw9>o&{zxOwvrUwQ981%CTzv+V!GoI87eOtG@% z+xt8FJNh?;X8Py&XZtUNmiqtnukmm2uk)`7UGd-WU-K^vbqLH34GatkObyHkoCvhi z+Ui~O<@y?Zh5l1$m7W*u7yKnSAh;_uEjTl{GPpgsI(Q_sHaIA>J~%YAF*q-@Irwv^ zS7=(O#a!IcXJ<;Zh;0+wDYjSa;Mk$D!(&Iqj)@%?J27^0?5x;1vGZb=#4d|n8GAVP za_r66_F(Jm|H6Er>EPwymEhIjwP0SbRj75SO{jgSOQ>t;C*0T1p?;wOp+TXcq2Zwsp^>3cp)sMc zp>d({q2EFiLK8!iLX$&NaQ8DpGefgO^Fj+li$hC8zlWBGR)kiDR)yAt)`ixGHifo^ z{t9gm?Fj7(?Fk(S{T(_O`X_WKbR={#^lvCH)FQ5B zT&uX&ac$z-#kG&?7}qJTb6l6Wu5sPsev0cJ*CVcHT<^G_#7vj1I*TuLl!F8!QCre|0$IL9p^$%QE;JOmm zRk*Ikbq%g-aa|WXAa*@|w;^_V>_+5m!Y7;Y$rgO_CqCJVPqyKczwpU+e6j;%^? z=Btn0BoVs9YxCNlp;W*#zI_%Fq_^k0r` z<-Zc!+J7~+jsIF~TmSXgcK#b!l{aHM`2UUV=+BGo}-y*gves%M=!g_7( z@9uBo@8NHYmD|qW%irGL+uy<82dnvKebHtQ85e^!%;B;6(dnG3KgUM6Jy7qYAmY8p=vy;enZs+R892%96QP1H+HhWU+ffr z|JbSi0kPB2X*xR1K&P4LGz*<(qf;(A&GC=%&&98K{-v?=(QyGfE=0#g=(rdim!RWP z|0Mr1|78E~{wey{L}m^&~YU?u0qGv=(q+Q*P`P(bX<>)8_;p1zjf>;{MziF z@85#Xf1>kN{Mv@@f1&$!bl-vQJJEd?y6;B!J?Op{-S?sUesn*8?ti2EL3IBI-4CJr zVRS!&?nnKb{Kx#8{m0S$1iGI@_fzP88r{#J`&o29hwkUm{Q|mQME6VRei_}bp!-#H zzlQGD(ftOx-}JYO{TILTpwc36*xxd6#NR4#)ZaRA%-<$(+}}3vx7IFjP-`FfN9zzc zq;(7&);a}_Xq^K`wJw2UTGzmFty|!P_EX@b);(}a>k&Au^$eWRdIipEy#wd8K7sSv z&w&eC-@rw!U*M9~KX6$a5V)cZ3|!R)1+Hm>1J|`7fg9Q{fkpnI`1NbxrZz0_uQoi8 zr;P}-&_@PZ>Z1a!^wELV`j|i)eQcnuJ}%HsA0KG1{}$+=PY86>Ck8s{lLDRf$$>8V zlt5Q~YM`4wE%1{*J(FO?V7R^keKw-cCiK~iK3mY|PxRS}KHCB#^uGcl_3eRC`VREji9Wl~XE*xnL7%(C27ijD9RIRzDsXr=JLn*G~q1(@&w_>A(d2 zOkkpZ7Qa7-U+3}b0)Ab@uS@uK8NaUJ*H!$whF{n5>qcObelsvx|2Hs2&kIb|TWC}D zmfAGEl{Q^(jbClF8G2i7rru7QrMK5+>m9UQy`wfq@1)JuJ8SdwF4}y(tF}PzrY+Qe z(iZ96wZ(c5ZHeAfTdMccmg&8<-}OG)a{XuR552FpLhq-o)cb3z^a0vxeW12RAEd3- z2W#u}A=-NV7j1(+RNJWks%_GTX`A)o+U)odT5kMEZBG0sZEpN%ZC?BsZGQY%Z9)7v zZDIU)ZBhJh+T!>L+LHK*+S2$*+Oqh`+VAmGwB_+rwLjvgX)EHVYb)btXshC9YOCXC zX=~zVYir|kwRQ1xwDs|GwGHv}w2krewN3F0w9WAgwJq_Bv_In)Yg^-&XxrkKYJbHq z)3(R|uI-3luI-HfL)#U1O4}R1TH6=DM%y31Ryz>CPWwB4y>>8ugZ5AS zM(t4iChc(iX6;D)7VT*KpW3nbt=jSUZQ6|T%d|GQ2KBKh`pViug@!Sue*V=_IXzjxnwGQD+TF3BZtyB1l z);WAt>k_`Ebq!zFx`l6OKZS2<-NXNCJ;Hff&u|O9SGc9#JKRd|6K<{l9B!lc4Y$?% zh1==~L-onw zU-c>BVfxhYaD7^Mgg!kyQlAkXrOynH)@Oys=(EFP_1y3{eNK41J~#ZEJ}*2$pC6v6 zF9=W47ltS6i^5a%#o?*?lJGQrX?VK6EIdR1Jv>ui9-gKD5uUBD2Q}K)iMy(7D>cVaj6&g`b%h5f5{WqEox z)*|>5YZ>g$S_ONs*1?{vO|Tbh8|=;61^ck}!Jk=&U|-fT*pGDz_Gg`g16Y^fK-M)l zh;<7NWlGZvdIyKIKEV;}=io@zH#my*3yx;}gJal$;8->= zIF1bp?$8GZcj`leY)Wt*n;M+YrUe(U>A{6;MsN}Pf8x#r zJc^5t0 zR>P_&vV#bsfC~r$BFG}h4)^Qs)0H_>(|N94_jxY=pFS|Ds_(5+r>noI3AilmE3q73 zUxcj_g<)Td6=C0qm0|0}s<3ax>aY!BP1r`UHf)plGHkQ>Dr}2b7q(S=9kxw;6SiHf z58ENW4f{@P2-_((hJ7zKh3yiX!*+`;VLyniVSB{3uphpeEk%5Q0xu+UF^fx{;)&h=di=#m#{y?uVF{TZ(&Ep zfv{uZVA!AH_psyQP}pDMaM%g)N7zYmBrL!q!Bc4_h1cZ`hd73mEGn`d1{#fI6?^~fG zyl;n&^p34t;2j$}%KJ{}8{ToDqrKxp-}Igg9pl|1-tumac-y-rVl2Mi@lFUG=bacj z-n%tof_GcQMDO;9|9N*rOv2Y>@5gngc>fnV)w@GX^L`gG-Mcg5U3|UgofJC5`+daw z-dzzh@iogkIrIbXyt=c!Z`S?Ld!o)9@Aq}*dZ&cW^G>QY-@Bv6M_^dsT_isCejECU z_juif-Z#ak-sN>a^PYL&bMG>-$oo^oV(;FFCHPwET~lkB_xuCPz561*@a~T&#McV% zZn4t)bHpm|FA=NpwZ?k|@A$6P_!3`Vd8gG{=baY%wRdIRZ@kk(*L!Ew`WCNk@V*qBXlQT|K5AO#x8vA_Rb9b!8FZlY^d-8$byt6|Ocs~q1=$#Y#J2VgB z>#+B9oj<(S>KyT6|Mwn=IOaVX@h85Hd*_D!~r&^tAWS z&@ih$abKV;@&g1J}?}E?^-ZyGp^nM(A$vaJ4_I?t2#k(-{s`r;V*StsS zUiWUVd&4_5G(Y^?Izz*MsPkI*q*}wmXNck9OF~}{|1@+&_=s8~!&lTQ2>&c}RQPMP z-Uy#icXarrx^ISWsWm2iSFN|g*VTGE`~xvId`GQ!!q0?`3tu6|hc6195Wct0#PG$T z|HF8bFxKSoV`579?{%ws?#lnVn#WVFnQ;Ek=Sqg$xZ&}X@HFd|+c~dZM8sH+ zC*OLdUQYkqu6cuU@iy8Mg0B)GuNc2&zv^}E*{fE!?&fPZ;aVbOn9-E|GTU_TWxj^@ zg=q6(P1XQ^Fx&L(W4>I{Y|}ZgiPa|e1@m>|w4y}Fh)#iG<~Rcen{7&&ZC1Qy{=x5J zw!xW%@#_|Rl?W+Y-u#2##bCJY;rjI-Y1kxG{;K~-R8*5DjUI_=AYU?nQ$Hf2apT6J zq4gU!ZWvMDc&XEE9?y*%A)cHO`7<)IBd;$m`{CXNPkuaY&$61{*6W_U^CnNFvbT7Q z@71n!lgC!~Pq@Kiq`Pk53~wuMC4!P}wnLkb0@^k6lyByrc%$9_aGLg@u>yX-WIIZ} z@hxMhH33T`+tC6T?HXl;c-A_#qeU><^}-VTlg|O=c(f2kyUpc1p6n7g8NZdkjCM$< zFzU5uuiXB=nmD9t*}rf1{+)Y=CgGIJ*lRdlk?>nGxx4cm6xGJ=D-oTum zeKQ+G)Q`%H@7ufgz&<_m24}X5&ur7TZ?6HFPqxNy>o=;`ph>+3QT6LbWOnJD8-d=v`nDd4v1q=Jf345#9dp56Svkr(v00`w#Ay*Eh3YZtu)~ zgP!fyJFi|>kI3mez#}qxdc@P7M!2;12pp63?}zWCb;lRJnbxI&MFUt;;h>1N)$r_4|a*d7bh5zW)yo?g$abc^Ek7|KY$zhlA#cphzCjutAf?k(ge~ zoSvP#KRGZDr4`}-tA2dEr$W+wS1LCOxx={a8=!V8-J8GsInOv$^4;xj$3}JcL&kP> zcmB;GW~^gg>sqhfYQ9$Sqsag3S=dX~vrpGv19NbwNlQ4ObGO_9d7ZmHTd#+we8}>* zpBrEI%`dtgta9z+^AFZ&R54y(!737S_=tlamVET#yv+?-pHKN~(&n2gZhKUF0$qCc zHOD@=x5fS{jY3mr-TU=Rp82a^skpeA_Sn68bRN*d9R117S{?OC!m2Xt~aLJ5FPg={w z7Oh*SW)FBadq8fUr=Ud1Td@)3`|!y8GYlVOc;3Qi6xl7Gh;Q8_yIcR<+-}C^=*d5h zPgU@%jOU%AZ_6Jj@#OzyfBV}k^loqDFEuUgiMB1XjmHd)al&r2))(8lMg8o!CtJ2| z(<-G!GRA+T0*(J^TJE5J*yg_(yJw$neX|GT;rnOpzFSoR`mq*I{&~C6_rAE4 zH1z6j8G$mMc{y@YtrFu?T4txTNJ{f(``7N;y}e1_BKFC|?8Fvr@UNVD^5@uaJz~vU z6G+*19^>T{R@h=&;vkmTK07`(H8n0a{t4(v#0$30k*;PDWDn@sy$_q|468-S1I^@G zr8dvD{=3Sr-D21%PyT#JUBqgYEMN=Tt!JN{Z0z|XLP{F#@*hOAOXi}A4)(J6t?6Z( zWmbZ5J7HG+d-my`o!7ZbuUsqZ_gfP$d6}_b-_9G5jSbLa^SlqCD+W(C}fo)}CV#o)gNH|%*Y2wD|>8S+%3s{FlUzy3W3b+{0*4$%a_f%)Y5{ z!zHBQ?#)hW+aexK>_s}w>asf)DW~uAeX@J??TqQ)WZiV{f@h-1v#)5kNNm+Ao468U z+r(nX@6Zgt%6RgVP3ku3Cd_O0R&$3B#bWcsrKVvU@heOMD&sjEuwH&`?y~3gkZj|( z8CS8tyCvP;8WP*L!LuPHt%bkR-FCa1i)LeE$?_U)PbRjbJy?9JRR7|+#~P;OG`5m2 z;!|;U(@r%L*CP?5m|00_(Izn&`-30&y*5x=su}b7u-Co?zP4_Gb}6k>u>O)z-T+_H zEz%~wO$z=4uzpXT_3E}QA6?aK(J%aKBtGrQmQ*44*$uiUn|rD8_QtxkcxPW`R$0c?KZurx^sGV z#~UT9lpeOf`CNRj9@$SOKAD{}uy=2q&Ez+*zjLCanfxN-lxlNTNwT?;6YJOtg_60>(bcLDtVr5sm61!XiK&2 z#fKPjxjAH?AUlJs(nuTsersVY2MX?NI|t7y-TjE7h^Qr-U7vxy<Orx?BrTEr<`4)tx?v}FgFlCfg4PqPv0D4 zuMTEvH<(g;V*}ENp?&}eewFOZs)ex{E_9LvHHI_RH^H$b^Kp10o= z{}1hU8SPrLu?BVSHL$1=j*mUN%{+b^Y>IxB-`1wDDjTvL)_;F!XSZD&=l4z$DfrFK z{PrNe%}?xUdw|Df?U_4}%#(C1gEQ>CEVd2aj>olaljy%N?d^dE1!?EES*6?UDyYuY zk4tWRx0!X18J)HLN1AQujJL$}4xocIYRO@21&lYkY&Cx|7htK+|9z~vrAXhGEYr}s z4c?POmp&yZ<5_P#?c}W~`*dYMo%`hE_F->NeN-|6>6r>k8DBZpNj!iCcwmo`AqG?Fl#iq73EbkCI z<14J0x5Ocg`F2T7LEm`mhCgMO-Nrzd?DquiM2oeD-BvmHdDgt5`^C7a4w}nVCRm|J z_%1g5UG@{oPpPZ@&Evkrb}iwm6OD74=~mWDc4x(cP0y@n`3#8w!C{kNW6*m@BIMdC zi_#1goEtSSI;)T;Qa$}2M06Y^pG4j5A-=Fu9hcIE-Ux!%_EWDgUMpYO{qp+DjmQh) zKTYCUIo3OfqEjr4Bi;9s1l-EzQqu#`Tvh*lSPmGoA!+(#>4PbAKm$%kh8g`5UNSHs|kjPS$h4fPpwC!%c{D z%lZ^}1X9Uytku9i)=7f@aoOJ{d39MAroHpqzWUl+{W46W zEw@Ze?>GClx+)*2<{K%$y6tCoUuC5~CH4{Zp38|sc5G*37nC1^d?&ZF!wbeqYhM3> z_B#Z55)>m5jAyzZ!E-i2R&W)$(*5m*zniz1Rs5LcNqcL1-CAC}B;S1Z3+4v=#0S`8 z-V>N$DVt|E`BFY4{S1TO^JbvkutxA=@{=88H(eU!EwW#`=dE@nOUC*iy_)uL;DFBE zolN3Ivt~XIe((7WKiI|?!QUeKP3lD=ILU9XfxWYP=H>Ptzz&(Nn6h_Tj~=5=u@Z%L z2`&mUQ$HQKxC?_*`!yY6Q%A@LjbAOkY=3uC;JLit#9y%+{bjw6q3!x6`{l{a?QP3C zl@C_BDHuX@M|)vmItP zTH)u)vzx=0(^=7QyFq*M7dVW?l=0bFA9|xN&mTUPuBGU6h6LWK~P&0=AhRhk**rfjS4< zdHjZ>+pvu1PPqjH`eeCXjIwiCXf116e4E4|PuPxZe*TZEO2B%<#QG}T+|lJJC`x0i zeLF3;Mo(F+N{Cs0o|G)i8 ztDax-?odx!X#RCiTEp8rR>WsW)ov{jmj9W7bO-+GXSuYSK8j2W$)AKjx5odxD+#}y%y?eYg|)fjc@u^MS9xY)Fz}hVp_%I zHl8;4L4zANTqv)D@|Tff4T-moTwO41SXobg8AJWcNQkw?SK%6k15BsOdScD1?`y(A z)Wg{boNtMxqrviKs3-qUgXP=Eg5gt~ z{QZ#UV%td!QBUl9O!qsQZs*9=uia9@lV8J_?RUucG-KT{f2{kPp{Y-p>%B`?@kc2B zK#J4+6@PG0{7F~wS1A4*DfW@*V7tO<8T0&ER@gp8pHU*MM_{SSH&mR>#QA6-Anr&2=I`)FUVnl_Wx< ztes&ZBM6BKyj2-N$tY{5M${uH1A@{~;ueDFPB(9TBMYUY3WhH+Hpivr=D0Al@D_#2 z+Ca+cVpIl3r6^G$N|Ym#JSvVzgQQZF{m7^Q0)8)*Q<$u(y^B(WsF$MZV7o6$+#4nC zA+`*AsiF2FF>o3Y%N+m5QzJ#$s^=!UiqTMvBE|VMd((PFK{1&1 zYD#lO)SGKFD94cU2S%M5UguGxPGb~l)MAm>i6sI=J%YzU&^$^cMTrFB=xuYv8ywB~ zwz4#|FbS`0FgBVm&5h>E(87e`S)U+QL_O9vU~Ls8S`z5{05z;&{^JH{D_}8mSlCjj z7eG%n?4oh?wIwV>S6Gv6=iVJyxx~brdoBRB84fPMx%VJtL_Os`Q0^5ao*{AW+x-$pcP*V&TrcKNe@ZQ8QRB>D+gi1i1PJ5&@zf!Qdz-=UycC zB8egDiM@j94x#BX=RO4a-eIhJfOCIUS8*5=hms<5?n50EhwCc70mXtSF@i+7b1#q; zHbT*76*ihuj;NRNaljcHCEg+&?%c-$;u|CF(z(A?Jl1%^Le#^W2COMjViI97=RQTD znxs%!5A^ATgQ$n|0dQtUi5Y~$ocl}#XNCjLY{Eg*!numCZ*)fT&0C zDF{9x0`A;DDW2dnB0$t5SPp`vQDQMcFz3D$o8x!J<|v)}Vui|bI$!8wdM`yHYW$xUME7GXNBKvWY2oUuM z{sqCgC~-DQoF)$L+|TiC1X5` zSCx7J^mfy^iGq9f>b`>EdyQ)G_w4&j&yK6FCJ`X&5qN!0 zp1nvcoWv0I#Oh$WwQ0J{v)4wZ_Zcf5;MwcyDn>xD9w{= zm`_hqcoI||+?O6-3gIB?;j{!!3!g|O9OlzoC^)GOI8PA{q8?5=;IttY?$g_-(pITF zP1=Zh+L_SKAZ_l@Gn}+Lk~X5Ab`G?=_(Ug?XWqOEHo^U&II_TbdMAa%axuBO0DS<^ z%O{@ki5|qjTzM~f%RU1Fe$Vt!m@JFgmy(01mz)>CHpnOPe4;P1Brz;Hi2oiIT`=soApUzqwB`H} z-K)L{)im8(N3PbNN6$%A-Wfuj%iM%X)?b(71=!)#BaZ=qc#(2Gf0hj?HLYgvvkzvL2XX7 zm`#G*XU~y!G+WUopFN)vjOaeWp8;ZFwD_1HxW`@yY3>(3c7pkwU=ZEI6ar>>v{*_o z%wI28SeB|R=Hqw;p&+_P`3fj&qs3}MVcvSJg0k8HWgVd)x<}anl=Z~Hef4@(*4kn= zk}jfq-EGj_Lb}{jZ*kJyPP&Nhb$@{Fu4u87q?w=Ih0X1E^3yvN3d@D;(GmX*;=e?T z{n27C=`%0=i@YuOL!I9ndleqbOCO-5Ai7V=pWr$gE&hlWhlq>&=%WhG9}@MD3TBnb zaUw%>Pj(h$r=!K+gvC7cX@%-3bwIg7D2VP+ zJWX+8NgT{OUsqJEstswXp>{LWN;I{M5cAC?ng%yQrJ7ns2+{ot%@u> zbCESDL+Xg`)$fFQ#ipWsQ*j3|aKBu!DQy+-%jNO=L*$q5D4wk{u_3x=yB}=Tnu@9f z#=UYiz%YYWSQSXz%)l!jFugLazUqX8_+OE>J&KvC0HdPx%2T*N73-Nt}D;8ZowKuC8#PZjPDW6<1#^!a>x-sSTWPV&U#NJf>jy z-+}J=lu3ZA?;#>U)FY@DLLI{iv+4Xhok@STjmFqF&0Afs+^`;t7ZQ>O?>sGtw@9(j>lk ztmcG;sE5@OSS?~iDq%5)-9n*CRj4dS^AzDA>fy8pPP-VtYN7MqZ5QA0zq^3G?B3@`mmY0)8*`Q<$u(eV$T;sF$LAu)Pu^hQx>$ ziH&>lR}`cn68A*~jup~SVnozq90kUaG2(RsWUhRq!uPsDWu@#5!a>x-c?URe$A~e6 z!<_ls3eFe@oNP3MlQZy8}B{#UHU&EVYE+s?gWY?3G+E6T=N z=6zE${H*^){OI~C#*eO-$4{gWs{!FF=1)go2`wy(S4J4GTsB|1Z2nEhf*Qu(bi~zH zDb}*}hLDkpf^nb()Ye zqMmXzl%q)bB$VT7dh*{hl%u%vv>Nz3(fFpXDJdiBDaS#%S*(a5@f&n+%rwNCLHrmF zBXB8v4dXrmi1oaQ*9AxcKys`|B!H5!*3D@GB>Mp*IsiPb3(yh(En-C~ z0bKUaKnp*BR0n{kbOG7|0RQT)`4{3(`!9ZLC>9twxArEv`0Z%%5%m^76UrH}qCJV9 zr>V~|7C*x%w6^#vY|k;|7THl(J_qt$VnsH|A0YXU4EZj2FnnS>80H%FhHGKA14gb( zj2-qPYalQN#EQOz!5>)zz_G~SkdLgscx9>aivJ^Pxw&8C>KjChgXn5;B-RjMy+};# zk@X@HvAn1(ZM>bfJViN zkp#paS)%~)DLt}A77z3$0U_!EjR(*>vEpq4;*YF%{D9sr9%upqA?g850nj9(VUMgy z3V`*QMi{2`P-h!rzQoISEWfVln0nu*`9HSUvu zN7fu&fR6$2QLLCp0PK0Tu(`^H}jI0kB8b=Y9a6Ish!u1^5C0%SfF) zvX(*7Z*P)|Ur39OsJHlQp}aa)tR!*v$XYEQSt~h)+#S-s0DX^22dLkT`o} zJsfAh%Mu(zKC&9<%11%INt|dz^6Zh-Bo06IZ#)>}Bdd`EhVQ>)jEzVOdBFVf*X=;q zO8V>{j@SydUyXVX`0HmoDEEl}HTOlTKR|U?oY+ai{GhJ?$r;(Iemm*By^C35Zw#?foUG1 zX|j*+4$=-dz9ONa%;RO6>k|H_EG(<3Q8%w!Yk84DMKiT?orAE@RSAH7JYOxoVEA!k(~}?1S5=6t zN9B`*H4 ze1w8iPomaUz*yllBtAsGiWf}?j(sE_rLZ+oh^$mKB@{&WDDgmvjTes*3i~)d zRzZ2p0VRP@5Z$As0413?*hlfnimFw+kL#$lfLbc4v5(I1+>42x%6eLV;X(GAjrro(<2NH4{U=Lv})2)zWP zb4Hfrfzb1K<%02w|AEjY({u%0kGBtbzUBz>kY}Tg^bSaGix-@&ley2?fL7Hdes@fM=|!j;pUUsUx~i#O(=A2RubW zcaRXGd!dS$W_g+>JK!mwP%vz)vCaVpJe73Rsz9wWsj&l|$_{FG>!{riwQ32XDhcuf zo@%n1swnyOQp5#6WR3zS+3q9&p61D;v{7-ghd9`MvG9x0rV5Zxm^3?z{t>JSn; z;1LQ@9finxnnw@{qI;AkKzSrVG$a&u!1IWL($E1Vl28!cqdW?fXyV`pJkg3QE0Y*f zM|7_q5A|45=LbBo#j7WfI-+~^C!n5^Ad(4y9q^=J(;IJWdh&oLSs}9CB&X^iv;{)z z1o2dYNFxe%z|&gZv`;~u-!o|nk5!@VC^d-gQ`=pLmXQ2Hc@UWCF9c={+Py&O=UBNRmU zD1(5KM;z>cCr?qeYWH~^wU?kanAF$-&tRwpvrI#1j)?B(m=D!gNR=P(yrRgW?uzWg zP*O*9ul@$q3lhYL1TmZ#_yJD=-!^c-GXk$nGBy%-|IL9T3u>{Ev zc*X@9y27zaeE|4v!{QlN-$X(}bc2-tmHksc%Yn6&n3&663V^AGB?xfYUyw4Qp7I(f zuSyUrNSr(ERdVlIp>Tj{y6JUs^{piwL_M5ufU}NRxZ7Tb#hGK&i@)2RYZBn5YvscO9%dI@mPll3sDd2FJS$d zAdV6ibK!p~R7Vvm>%o13a1ixy{sGRJ1aXRRm=iyv;GA;6IY&5%dN`MWbAed68^54P zv$DBN1c-VBH$ZTW2)HA^Ry=_x(K>`c)FZehF-hE88JMq#q5wj!knQ7=XJg6*C}Q6*7S zCN}QQ?@^GdNZiT_94n-1#E7WJSPP6b6GbQiGKXGM;R{u$tdxZj4x%1TUEn;FC>|sn z=F%Tha2|BP5rl)NhtmK!5yZlrdW52EIrWCRicO&S2q`kR{sgB9%b7b8i7GW)2Hem3jg69Mieu>U)Z?5M5y{4WWO}=s95ZB_`(F`vTx|!%74= z_x_}esHgk_lm{h>JQC;5eURMO@)Qm*EjE2KuD-#9gQ$n|3UG!H3wQ2AusExXn(=q; zt4#u2eXkM$q8`DpM5nXzBC+8lhNvf2fa#8)=`!a&0{LETtb2fSAEm1}28yFekvaF# z4vKH-Do%jnxI{6QM7eVxCo62MqR%R9BBdNrFXhvLGc{36CLHeErvhTJk#_0aCl`

    1a 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%0A6AsDdVWk-aRL;JNRc`B zA}9v3UK44qhgo(<<9*@e{)#!f>JMl-fud0T)hhj3-RA#y_=O9 z5@r58`d%RICLZS6cSHO;!$$bI_RmQb(Y@+Hs2<1?Uyv|&><8q2_JzU#o};E;#?|{3 zp&+_P`35M5iG#cK!&s0LMxFS&^^>MLuHJ7+9nrn|F-NCfD)a*hA-WejfoUG6X)>37 z963H|th1j>KdGbk3)D`N8guBU9n{X~sQnJL-?GG666EguH(5<*6>U~ce^8nc-KY5q zP%dSOi-f|R`6U1xHBv2|`NiN!R|yHxJyO|hd_bNpt`ib-tP+5O&^eF zYoJsFN`-7uKHEAaV2-?kf>Iu@@XEAMDiI2z`>a$0N)_VZZoG;j%gUrWsUx~quMPED zq|Tjqt>Ef)NFC9=dPAr;$QJbofVuDn+4##5j7?9v@Olc7T77R@L%i0)I<7F?~fMaygN@L)(TEbi7FH@Rygg5579ke zXYhHmMI^y7=j~P4A{8PlRd*2zqI;Bhpu}d2E`-8dcdUZa#Q`OOP!Qdt+yj(k;$V(D zSy8oW_g)>fRH$_$HRiUvK`oGF>OpfvbU(-5Q0+;o+-dhzWKnme_Ms1{Bf3}5f_i4Q zNY57iiGjQ9OulWvWvAnnv&KduU3UNAoY};Q=$>;3IPx`T+0= z(_!Q4Eg&RBH%MO7VLuF{@x;R%_IQY&H|&6)!+wNR5#6g!fND{;c#MR(!!DA0)?*3- zc>XXwF0S5*go5ZEr5GraiGw@r$ykufMveG7>?@`^uHGr6j_6)}TDH?!c&X5I5<+w@ zG!xUDLDOUodj@iR#aL%QhdoP2?FFdKAvNZ(=Qya%)lpjnwFTK?9tm=Xy+BseJVl#T z(@T_QME7Z43Y1r~#S%i{4*OLA{9&Y8I_xFEk(Ln>qI;w@KzbuvtRy7nu-{OKRw_i+ zL-|cYL3EF@5h!nGi?;}cIqbI;l(!sE-XRo3_b6L{@-A_3hyAW1%gSUcsUx~q{{ZUm zlR9_U?*~`^kkk>~tA7ghPqM{M0$>jN6Kr~a8=IbV*gF*>%cXp#gYYE~_GgQI*5BqbDa({6nhTVgIAZqV7uVLr9KwHiGD0 z{U)g2m?Lh;5urKO@d$U=H|DTy0}lHJyz)d-Uxyu<lp_bBav(uO#=!)}8GdB&&_Uxz)-RL9lZ zp41WDt4HNHIqXs)F9{*K7mCI-JJU3o!|se6Pczop&tc!KqZS9X7*b;nJH|mRUPtX7 zs3qr!L=xl0U}RqWd)W1WJz_(VbAZ!|nlq$wsQB!|om&sTUz3x<|?Y zQd*AaM@YVg6JNl04RfrgFEcO ziYzOW|B^bQd-ah}A5QArVGj?kK8n;4-K#$c^|3jkkN}v&9*a$HhOy~Mhh3-;SuW)v z9fT)<@OX}RG)Fv46wF~iE^pdLq0aA_hZP>HLMKpa5Z$L{D!8WPh^KPIlf=ax_7nx@ zDT(@|0>%pG8RA29&o>)r=ZMr zKv_sAi0)CA0A(?8Fo(TZQMGFK6&Izcj4ts?n zi@Gbd4{wklXP+y-T*5!ydiGe%p^?cia!(NA1W*ZxcJi~r7IOj&V2P(5dSUGu|cUJtxSjg&!9wcZBT%p?Y=gsc;X9& z9q>EDzCOr$ON8iNwOlU#y}eu!l4}Wbhg~+;cGw}g{tV!G(e${udT+?JP!QdtR0K)| z;@}RuLN5LstWhJr4tu$&j;ps4sUx~qubS)RuuFxikr1MLp<0+`4Vor%*fo&j<;FVu zIqaKt)apX54yiGRUB^MKo{m~0s5Q(L4M>nX?1r+M8YtSVni^A@5#6Wx4xmKjil&6Z z9d-l&UNllI9d^^;NX-Zd(LGWdAhpUBcM=kF*sTrwxdOWFfhaDeWJ&Dv2-K%$pde>ZW z4*@WT-4&bON@LTL4*MR3$Z{#EItcxN&^K4~&J{h0f;sHI@}}(#b$-wERCufkO{3Hx zx=+ph;L6DrS-B#UxVXd4QE;*(YNi6l3TF`UA-d-q3ci9|F__?(!!A(R1}j8Xs)i8? zqI;A=pgfQ(MiL5h*bgWuBOOr25DKDul<`1$kT{sbeo#@hYWIISYL7wf5mI9g`w^%G zvP_TD91-2maUxWoAXVBNcXp7RB8&dC+C2$DPOIsS&OWR_AN0A6M~Y+Su_2?@~+lJ!#}Yk{V{mgo`ku>-XQm^^$G)c)|(y|S8oZSAi77{3Y5*n z!5#KyEXWq4MtmLiR#P2U?>16Lbg%w_qr)y0`jCVW-3xt;Y3`tDGKakbIo@ilv!BEM zL`Q8m)IKFO=CD6?P}`%Ub^vN$plwWeiX+mKR z`xgb}v;)dnLP2zo@&{1P69;$L=M`C2CKpH@(Y^X*sQ*Rk++qI}T>T2EBf3`)$-}=9 zkSqQs0Oqi-W7B)z*z}~s{#zlkTuPZd4TOq7sE{Yh=ZSK8)+q~f*cI|7$BgNNUnS-9 z{O_4^c!h6RR)to|v(8%(-KVA&xN78yYI&jxadC%TL&2#gQL89mtZ;57K1BC?w}P*J zo~TQ3%wgA8*y<`oR;n5j3Zi?IaG*5F6O9RlIqW71N@E9<2tq-0kJ17t&4`0J>}HCp zRl7n*tu@qIk{WZ^Euj|3GPR*OBD$Yr2dK6qRqn9cDYB@$Qv1-6)DhjQcY%6zp6Hw> zyu`pAc61)wHsG*3~^F$&+a)+G^BxdMJ5|#P@@D|fy z$|Cte_N?zCT&d)EsJ z2bgx5UKdyI0>VMm!+9AvFA)oO+b>~pjvDpi>$Z=X1h{&a5CNhd!O}dZGwo8bWh92E zC$wjBNX4x6K|0yci(Tz3VTb@ zXBGAir5sT&<=cR>B~QFdINX760mLpN?b3n28yxFB!a~%;`WRR{^2CRP#a#Ffh3Z3v z%6f2rLO6(eIG+P&PoDUUaF`R{qu_kzfU}Qq5cO~l0_Om+a5sKHk!EG{6%ion5qtxJ z!$iOx`QhLM-x2|$9>H-C{E#P(5(IPQKVWk_ZfuUyl^<28ENAnRF2-44oXHbE=ZRB9 z!kqaTc|-pU0)8)@Qkbl&Jx3`*)JxGNuwBd(7xKjK#KztEMFr`C#Qj}?V}*2?7!mat zL-O(FDo^}PfXty^SNQ%`sH~Kg$+zCjAnM^%08aUQQ7+$lm&IIq`F#HsEQeS4W68p~ ziEt40aH;^OGO;kHURhDL>ba_}VofMkCq?Ggt3xr6^{Pd4Mbw+?El{pa%G|NnR-{pj zrS_vP5g_Uj+y;V1`J!RIXh0m?wKvLV+X`HJL%edz*l46{ZxEcd39%yTu?ny@&lh(P zD0lA7fyK;W$sJ0)0Q#uu+;R2ZNmz*g7VAju)R5}tPoHcUohXhKith`>w}s+Jp>+o( zkKR%|abhJ;(Vx{lo|0pQ#&7xpdSrXGCvbkmX}c;!?W zzCINeexeZZ!?5tIp@2STw7|71{z-J`z?^wWjnBtd74-h#svPf zkEgAPZz9`Yg1D{medEN%er@97O7hEpnwFd{H0aD;B`5K<|5W-JQ@LtRUOA{%-_LMn%ZglvlR6b|(im-Unlz0nimDY~($$5Xk?4P`?KTciRx;Z=HMvU; z?)7UT@3mOjEP5q@K>$D@AZrrPbFluaf$HF-u# zPXRF7N}h7+Gh6m~&cBA@&HO*>)N`TiIWKU}xlTP_lRcLN?zz~h=Stagxl@z1vdLQ#e7#fm52V6-YF%s%JfqD{gYA}s?F!uUV^w2^(_jbXVEY3Pw$G{O zce3Y^z&#H+^*oNARx*z{H90K@KjGIz-fL%NlV6;gT#`-x46)s!^0!}ad1u}%d)M&thgWa==4~LG)b%P)pE^#xZj-&jya9H&G<)>hshzo% z2>ixck7j=3rrYh?$R;hFnnX$I4gh9bNjs-LF|tpz*Y9~+)^sJEoqFCQdnN_$nc&p3 zr|g*;xMw$~p8aLdK2A-tWRnc1Ci!S$WqXh}kSobB3vZxP_fb+|xLOxO1J9_yX|Vsv z!5$3UbF8XS=rq_wIapEP!5(w!IaT&74%~CHQ_ttn(@N%arzX$K!Dsn3k@wns*<`L$ zlh{Q^MCsd8&PJ>;LgPjjN*g2=3*JRJjfqVYt z)U!-yJDJy=nv_Qq>o6g-v%|esNj9nA)Z}K_q(*1wRjbxH&{i_YT+u2{Lx;(s8yMaF z-{2VcY)D8wzuxlByfxaMUcG2Oy?p!TZ7Q2Ij#jpkFsEM4Wv|<#17MA?M{h;#%&nw7 zeq$AP8^3W!+U>ovNk^w9F;Y4jz-%k&?9?Yk_DPKP+e(I*8H{)8*;DpR4cxPvQ_pnS zvtQtzeVlsc$esh7n&itSgPfX-Kocw5L!$!~->7lJF{kty_Hmp@eIlz;dAOX(bTOR z;~BzUo{X2x`@SB!TFI*u;~6%@=b*CKZqite-Y~|K>(gSkId%i5e$8aR2;Q&A?AO$( zUmMx4WuSh-sb8e**WRhgU9ySSsYyJVSP6-V@r)ch#%I3Pc67I2&sXd`-79-02kx2Z z)U&7TnHsofH>aNcJ{sr|>Z;`>@~W8|@}f%F!qA>eynAUF6hnn(X&9@3+S6 zSM1bpj_fxxP`?>Y{pQPlbDf$jmQ5BqHCcuxRyDpFxH6Xb_1tFXX|?RRGH}n=oqE14 zd#(%I^G&Coo8*Kx`ZbZu_r4r_E7HlUakEpWPh_VZ=;T+8+s*a+z^U(P$#lZM8b3CB z{@`DYpV}$>P0If2H~Mb7$zO8x3%ok^n`8g()bG0Nca8V^$n1B;sbBe6d#4YLWqYyJ zuS_i8!zE{B+3zN&Ce>w=Do#yqK@+PQZ;lPPH`es)`L&&=Fxj&~;GXrIdPc~eO#=69 z?9{V`oX{P9O=Mcy%E4P9oxB?Fbn4Vec8WwNziK>Uu3vknzMo5`-Lc&Ce`lxaE7{~g ztYZ4VaO(A~>~%OcfayPBkNyL-GavpZ@f&MBkNb^#(r$l7HaYFoUC0$Rt#kJ*zl1sUw@za%vKW zCRVl^#04__KbsS;=hVHKREUUE>Y{1j8QtbISUWjb>%cu*sv5#+u)E}7-oS%JI`vGD zJ!1p+?Bdk(Ui7q*ne5c0ha9|{UlVz+^^r|_IyK3bO)`V5T6$a{(|^`n(f&?D7s#RW zjqd*E2gW@c5|ZoJTNdTxviBqC&D{M3v*$x`ey0B~ylme0lhM^m-o!Zmz_@HTnI=bn zI*vVPuA5^QJN26*`_1J2&YS&aIQ3g7`^^i~Z?03nS7g7%PED4}Ca*a)S%W54LRQ5E ze6X$X>lspwQn^9)d@FFzwN5>^$ex=5_k72x=XN=vZGKJU@_ix)-+^@U2iu2Eo%YF2 zd(g@6!4`@chlG6U)c2ZXy6ji5kzK(2C%c)62DP14H?7>#osZWIL(x zo{_R=`@lWhI`xc}Jv%uyiI+`coSJk+6D!*(@qr#}HOz@8Id$(V6?&<4abMsWr8*6k zBL^E0xMzl{k>)g5fgCJ9@L;)4Js*%gM+ELU%&F&t=xHT$j8l_G+)DQ1H`aQ5<~MGH-Tr`Vvd^i>5h?w(|5kF)sn3tH&r$yx zs&D51JExv!WY5!qd!BUac|rC(AGqf^r=C}2&%d0ScoOUfz~4?yZbTC++vO4hZ6(dj ziI+{_o4QQbRfg7S!|oZz=1TUo5=G+2E(*e!v3)>buYIStlS4%RsEU|~)@h3wfZ zaL?PFdbUMRE19jFnncRM+xs<<_u5^uiPxz~l57$mWYuC50&OLCnk(AHY3Tdp(A|yh z{vO%5XG21|`t_FeFk1E=>DQz+I-2+Qc-dr}x}0O2dOa?CJrW43vpxDGYG+DK!Edbf znCv(1U3UBFvdL7ZCUd0pOaL=iGQ+9QLfL1Ye+{)YGdS0&=Th18mB2k;cIvrW_FNgb z=j%>A*UO%3otkWtO*T3;*^VYwwzmZ=$}Z-_w>WkGOe%b$*2T`iGy2GBu!C~2{egS# zQ#JNF4feep?3=)Y9d_z@QuaI^xaSW}J%2?{E15q#HThi*e(wJecOKwTlv~{209Np# zs8=t_Wy|cYy8B8%5wdWRkghnz=;8YiGpcd`9h|;Z_o>jOcx{ z)P;HKXX6dF5_!!=L_8fY9xZ%j{+ma?5#o}7KxKWqxr;Micly}PqI^8+EhDVzTJ}it zQ>4n`8+AO&gyc=u`~%#joS92Bm#ze0VJoR<7L&wd;^RZk(?q2QW6dIK@W^E2$ZBSh zsXX#?B^n$w_>pj>oZ(ybUz}Gu-8rnagD^eIax!IcFAgi^tpuokOWg|6enU ze9R*s7)RbSi+nmkJ6{SWglu1`W<-K`0Ps#I!XuwEb1BAMiki6;hl|?VuO%35C5@DZ zziJjPaRo<$?uaRA+@ca@$=>D3e8!P)>ovS)$;$C$?;9s8V;1=#kF01M88C~CL!{c7 zRm@yI;>i<2T=-f`<}OvuTvE8pXZeg;tpua3q=_=3HOx{sLd=)DR=A&RX^{)&uj(}}nww=$xyo27o6r}oIBoUASCZl&3`#}Sz_k0j!Ulwu&|Y^G>h5BV>XA*p;k%{ZZwPB z&m;F3NA5C-!h(@?#y{aQ*O0t3 zH2=QbrI(q@5H39sz`|D2-z;Vfj~Q7fWGYWodT_W|#+EIm&Qp<7CIpA}{gC^Tv^9%_46glJ;dYmpeT9%@7y9)*f<~duA?Ar)Vp-V2b&uMWh&Q zCG(XLePWjSMV|TvIXrYLk=JZQMBx;1pWrLg#iQ*ZE{hPTtnYWYi#J8LmAK8KB6$=u z!dj_iFH3%kQ~=+o<54ao?<&pzL+(=1%q5;n#{gK^N}|nTs`HqSQ$n_q#Yzt*nMHoi zBWoE))-a1q%@~~8%MU+Yh;-v>&26GH%`{oEOHQ!>~9>|*DP`bBGt|uYUVPQCm$8!!q?g) z?lRuYWe#_lna`+AH{41#DkD18EcH^JI@fH?Mno(OiRLSFH;>*C;<80sya&05>IgfAD@i-HbcdzDug}YodbGgN(Z-j0o*UVxb@tFIeb7-5= z|98zIpHAhcL~6(;q((-hirYAE%0GByVdKc>%pzamkuRCK6z49lnYlROqV{&lRHO6l zfYR_1X5oIW@OG;1i18Y?$ZeMF1D@dvFO7-5~!viBiBMQR|vQOBcSNZzxW|1j<{ z*vw@tmmURRp(+_+7BiK{ObVStCzKwXU=}%#N6t2moM{%hlt<lqCIBGPV;0ZjU$iiHIAAkyUdeaFiv*P zEbGOeER5XvO zWQ283%N|dDiqyyWMjemDki7Rb|4+C}H8YpbxpXZ63tLGIvzRmII+Tt&z2UE== zoAAhV&617g$wn9_8)gQ|9O*QRWIXa6Gne7iN)-5vg`&Lo=7AJb9B47rxe7ahK+1F8|{$-{muEZR;9UC2uMtnrW6go2PCk zhlf@r@|ul^_%$S&FS~&}x?hM(NdzkEdjxkGsvpk5W>MpK)Mz6tua`6*H}@Qpei zQ$zB;rTNe0F0;&B7IW!^pt50Bhw9J$>r z@*t1gZ{~8GyBsldISUuHw@({RN}tm3Kg`0fbA>DVd2z|OMHkGHJ>bdi8b{vNYuq$T zR_IIZEQ$Cseb{L9S6 z!(Cio8XW-Ys5!ng+Db|(BU;idbtF&C0;*6A1-Qd_c5H5m6V3} zG7BHc6^7~O#Sr5b4KhnMnJ1fI963&}F~%&}9G+~ZakA-Vk&AicLgUE!W|1oqsdnZv zGnaKd`RWiCzScH#mknkvd%4T5d`4}D;Z{;b8PRQKsgLp0ht1Y(M8v_6XudKF*3&j{ zTRm~VjnfwI^W5c`db+LTDYK{-dDIK_40gDhTJ~4TPuWU};~RB6UJJ=vOY<+uUEVZv z@o;GufQ7BZVHWc)kMY$DImi-}{(svnvK)_m-#D_2S>%U2vZ8Thz$`M3M^-U&`Ix&T znz_`3i`v_t)H6EYK35uE-7Ne|u8^vq7j=wV^qE<*uX(aY#*ts?HR_usYsHf_H%`{n zEb@CE+15BR(=75AM5>+nqnS$wo;)kWg|D?7?(&pW~puV=en1j$H*Fv|FD`qhdc+B0v`|L0j#=sqp1QFd9{L7HUbFazxI&`&r2L6T{}AHx4FZ+*-GRGg z>4)kxR^6)^e9sW-eRdqW1PC!%6wG((nyt z;rqG59{s%7W!$12X30+QWJir759>7!nk75Wlbtb6cG@iRI*+_!9C^ts@(v=^&b(>n z@{lLL7vjR#T10*ATzYKgQkc6uTi@saP)F_Q`bJwxJ7q)*)fZ1FuKp@dT}%!S-Ad#& z8xiqhNHkxWZ}Dh%h)XsCmGxbUyZGztPM>$oqRR59GDcY4wCn-$Q=~q`H|ls)49VMF z^N-~&(Pl0mbLm6?3tLINSxikH^GW@X+M=V+;AHjY77P!Ak$T%_869 zk&(uc@0vwc;F0BxBR?>UjOLM*%v=(F$-xR7SLuS?WPNb$_!p8xherB$}_xIXrr1h|3&p@#b=u z1^VHfXBM@BM=dqNTBc=ROMc2$vI*a)T*|9>}&Ji{YT8AqNpi@d@kFB(UlH;cTY8AK!T{U3bJhlOD1mtG)PCx_I*NVf`mh_Ofy0OL~o>X30wOWN#WLD{dC)<&lzc zq|+>tAyS>X@0hui;mJ#dxbU@Bj=Q{X<`T_aDy1780P3h!OgGv})+r+zFiZV0Pn{@- zhrYp)*K9;Yd`L7O!u~wEPl(G#1S;!$7)xyvClmp|d6_Vyo!lk&9E@Dpa?SGmF^{k*tf+@f=4$?oxFw~Zrj>NRed zB`eTa+vJ`YCwpWT`8Q)yS!%R zB5@Z-W23D^9kr5;jkc0=%7~UQOZ_fS?UTbpw-R~HMnt?F63u(yRHoMJCo^qrgMLky z`n!yeXWANm74%E1ZYbG~X4<|Fa=ooQc{tPdRjZ(9<=^wA><<^Y#Cb7J{fYFm#&Jb# z&nv%S%VsOw`qfu2T&~vc^4c4fb9m_`W=TnPzyILI<`Ab zdhR+NI_^96cygRuJwu%%oO7J>otK>LUB5})r1jEPX`?j8vsvot8RQ=69^$^`nd@HQ z-sC>$-r{cO-R7R@+2Nk++2!8p+2fw815M581IxSzug?^MY7cJN*ZAL4O zOE;w7+=I}9VQ7cihAr-G?j7!3?mcMDdG}TK4fjp=E%$Br9rpwGL-%8MmZzPkgQugX zv!{!vtEZc%r>Bpnucx19pl66@q-T_84B9){Gu1QQGt)EIv%s^^v&fU{S>jphS>{>p zS?O8jS?yWlS?gJcUfJZ??Ahu;FM0NP4tNfF4tb7vj(U!Hj(bjePI*py&Ur3+u6nL} zZg~Fk-16M)Ubo?O2VQsKbq`+m;q}1Y+x`%qkKp+jo=@PJ<+yEc=eT2U@3?F4;J9bc zcHFoB=6GQ5=y-_P`pBN+cx>0=9h!}y0k%$9`Qh?szgiH;feNr;+^s40k=il}LbnvSR$jsfj=}ahjv@BB$TSa` z<|ESrWLk(!i;yW7nHD=HIhNqD)Un3C3>lXr;|gS4iHxg|aWyioam;kAbUteaO5Yj|0g5 zJF*`{_Cv^i7}<{?`%z>+hU~|Y{RFa~MD{mFM)p6E{S307MfP*Ze%`U$alx_2 zaS_=sA^T-yzk=*nk^LI7Uq|*E$o?0y-$eFX$bK8y?;!hKWWR^(_mTYpvOh%jM~;s6 z$9Oz}N|y7iqn-1dqrLOIql5E;Binh=@tgCMtE2O@tCRCjSB~?HtF!a0tBdoTtE=<8 ztDEzJtGn}}tB3QFtEcm_tC#bNtGDy2tB>=VtFQCAtDp0RtH1Lv*8t~D*Ffhj*C6L@ z*I?%z*AVAj*HGs@*D&XO*Kp?p*9hlB*GT6|$0$5TJ0H2mI3K&lI-j`4IkTkk&UVrS zXM1U)vx79rnJrCr{w7Uvc9f<%J4w@=Ins1zXK9ABi!{^ORhs4OCe3zsm*zNoNOPS% zrFqU?(tKxcX#pM!oqeQ5&c0Hvv!Ars*_(nF$g>xD_94%HCRC;jdmFCBDFkPacwVdOc2JV%k|81fuPo)gG((m7H319?s% z&uQfO6M4=c&spR-hdk$!{a_45Ab;CoGCqW&XOKGXG>3nS}yf)t&n=UR!Y5GtEAqp)lwhV z8mX^qt<=x8PU`PkFAZ>QkOsOoN`qXRq`|Ju(h%1cX{c+fG|aV48t&RIjd1OdM!I%N zqg=bB(XQRn7}p+YtZR{PoGaHi-nG~_!L`IU(Y4e!$+gTk*|pp^#kImW)wR+$&9%xm z-L={`!?ngY)3w$&%eBro+qK>|$F;#X*R|0%&$Y=n-?iDdz_rD<(6!aK$hFOv>)P&H z?Aqa5;@at3>e}U7=GyIB?%Ly9;o9q4>DuR8<=XFC?K&8v#dX5B)pgRh&Gm((-Bd&{Y9d%vz9dq6A9e4fZJK?(N zJL$UR`@?nHcgl6gciMH=_owTg?~Lod@2u<6TjyL4eCJ&ceHUDhd>37heV1HMe3xBW z{wuC_{;RI`{%fud{_C!6{|(n~{=Zxu{Wo2m{I^^={@bq3{yVNN{=2TO{(G)&{`;=( z{s*oe{)euf{ztA}{>QG~{wJ;vOB&_xEsgf~k;eG@N@M-~q;dZK(s=&> zX@Y;CG|@jun&clWP4*9wruc_SQ~krFY5w8TbpHrxhJU0q(?3d@7*TY0^^vbZMD?hP2#2Q(EDlC9U+& zmR9-aNUQyGr8WL}(pvv~X`O$8wBEl^+TdR#ZS?0#oBWHV&Hg3Q7XMOdtACla&A(jQ z?q4D8@UN71`d3N2{Hvwi{x#Ab|5|CUf1R|?zh2t!-yj|EZp zS?RX_oOH*3Ub^eQAl>s{l>9PNs^u&K%%3?R9cI+>yJ-aD& zV7H`fc3b+5-H|%7yHY21Ps(BUrOxbu)P+5iy0S-7H}+WS&Ynm;SeCmdYv=C8+PizR z4(>iI+ufJ_=I+Njy8E+E?g1>vJ&<*F4`N;1gIQPi5Z28-ly!FxV?Er%Sx@%}*2_JT z^>&Y9ecYp2U-uZ+&pnp)caLKO+~e6m_XIY`J&_G|Phvydli5)B6gJF#NE+@wERAqa zWh33w*eLfzX*3>V+|$`u_Y5}9J(G=h&tenYv)M%V95%^4mrZuhV^iGo*;MxeHqE_| zO?NM1Gu*jsrh74)|V>3 zxYx0z?)7Y$djnhU-pE$CH?fuO&1{u>3tR2p%GS8Iv9<2)Y@K@tTkqbh% z9l+yv_eplp{RcaQ$6@y=cEo*}9d-Z7j=9gU#j=|0c?a9?1j+!xtt_a*kH z`!YM@zQWGBud;LQYwW!Hg!6)Xo$I1|z3YGci(3Z+z;48_ngQ_?zxeV-SZ-! zxW`q?@{F(6&NHD}d(W|I9X!XYWqamC{pQK3hIa(jI(gWxPq&m(_d&j!}dbHLHx)5AW%)6+iC)5|}|)5|{C zbE4W1&&g^-J@cZ5d3xK2d-~W%c>3B$dM?{XdA6|8p3RYCJX<2i;xW$C&pzJM-#)>! zHFBb7TjV6q_Q=Ve9g$P;nChA4pXM20pYGYgW_Wf+&h+exoQ211&p`Ve&+f>%o;{KC z@R;uzWMAN!YmTQaWP~=w6;mB=xZ1?PCJ3L1s zcY2OS?!sfY=K8R=eowRqc}J zT=~nM(e^8zG4`vTUhJA@to^!Yv;T%?v+plx-1HoayyZC_c^i*Ap3APgo^kejp7Hkk zo(c8`;CP6~BhNM8W6vYs6VH8LmiJ6#JMY=Z_IPygPPAux+xdURQt`-i`{?Vni--n7|@R+ewByqnQz;WvdMo;9SE#<;uNZHmVGNO8KI6WaI}Qd|OXI@J$VvgYt%7oWNKRZ$8(E}KRC78w4wVKI6XC2m-<%$+sj3svB|F$e!YNA zQxEQN8AtAJe`pJze^Ko$>U7yp?(!)iewA%6R#qBH9WVR+;6Ofk1cLr>Kk9t>rC0D6 zF9kW_OYTPlAipYif3BGy4T9_^4?*i}5s>Gjfsp;=Vff)0c^c*Yk^Ru2OrEb9&C**3 zoVZo?N$Zwhw{Fnf9*<`-?QeZw{)4ycR?BGEx@Bg|#%=8CO*4DVHfEHDgS|T zd#z!acN;Zp=CuD4Fs#iFtNafsL#s9|>$Xa7EUQhbRAuf88~Jrg5Q2J`pjH?kIfV{41q{Q74vV6%Gt9eK-oJ?p6m z#rl-1Uw!Ub<+);0%l}`uLL0V>77d%VZG_vaG>n-I8mDKrY0$9gyG?8_Ml9_4O<#Yv zMU79s_GsFzw;b;mi?yzxP8215()x{5AEr|7yjvd`krF%{ryg-)u@ebMho0kZ_%Kcx=Nd6e5DAD{%n1r z7dk$e;heYM`PPV!DiymFW4VhOWVR@+B!7K>>AjmKY z?c2sbC;}DlyydNR`=?IR5>j8k^i0=Zi=Av}S)f(ZhMDD*?Aa5C?)!5?WMsPyHNVg3 zKH*Za6`xzquI!2OvT9Sj^R0HD4oUs(ozF+S`2KUJ3)s$NxWVOmw;*&m# ztNuxH<(Rk{wUXkKVxnusRkpQ%+Eyr{$SAih>yG^4jjh<>*Zww;@gDtR#PriiwN`!q z$`37u{&!?%>*Fo{F{!oflelVWt`X>1y6Q~zgsoP%>1rp z>qcq##LJfT91`PCVOtM;u9Wu4$1yd_r8RDyp59nKNNicpYcKcCdzt@4ku9sR_VW6A zh?X0iRy8^KJ=3BrU0W zd~z_`%UbBybrkyQ(beM8;;PreKXYr#nxMgDL@S#ZkkYhHj^RyMtch){0G)lwi*fFAzGFje&+W=+6*%#Wd1dZuy8q1hidE-H=T4%KQI;~BEubQQ+ zz5Z{t;e{RuEI8rXWXe<1rtyq|&>)$ozQEHW{kyalZJRaYQ?La52Frf$HMM1wX{4?U zh1PD%dILDa6xyo|)%jO5DWQ5?4P~s*Xsu(`2{73ATejvc9t45mvcNZuY9U}WN>9hs z#$@0fQUxsI6qc+CVEMLXMx)?W_by(>pF*RBG+5MW4V$-0QF^iI z46aq9cFkJowj%0$Dr{S!uDaUQlRk^9Q8T(KpSXPOwN6*(WO@r_uS;*FHs)=up=bFl zQj!OEn~xeiMIg<{Oq07ly%8UvLcpA+V9qe?-=L+!G}(F_>)Z5ZD76Ty6iE&cBr}_2 zG|t=e-htd~MQ&28vgfFcPOBAN1;75)mPHf1u&rr&-ju_-|17R57C0Q<(;${r)>b@L zV{9^(c3OPx>M?N92I;ymFTchhHEQ`?i?n7f8=(0G)D<}#JoD92%G*lfYSc(0uGr{W z(MY)yZunE!mX)AT*Gf@f+H3nz(Euik##5zgGWM9DiAg|(ZKp%VE6C>qtzGYMpP-$( zoc8LL6m8##t5XZ7N>Xz5V5Rb!-_v=m(XjaR>Z&y+`b#ZYOpU6+lP5||Q)rkllK;bx zIS7k(vC?r(;*dq@m89ym;u5ew1c6u3fNIm6Q4WuT+7ei+E`iUIY9?X)IU!#Ft7wVT zim8=UO&)&!%6k2t&d;@qnrLqD9EnM;_6g09|7Z?hCny`O{7z9_T6{!rHAJiOrXcNl z!A+~AC0VLM*7~5dz5yjFC~H5t%13cA^5SnzhshUeQK57juPpeYv?28hrE_!314A6a z;DM^FF>F>DxK2xLWuOFl;yz3MI4(B0uVPfMLhm-UH7b*#6=2vX?Y68qytZCx?5!9rMRe7K{8JZc$e7m$b3ORgX!FNydz=E|1GcTF^Re#>JP{k7iMI zG_hI`@}AZ`ofCk~w}oKps#?~&AuS8qRjX+}&1i)*%J>@ZS=H%SQ+u&>OtU6w)lkGX zYTLXyZk1(yroD3MOJ!v8DzmB@*K6?_S3(?)ZS8;w2CSoHS*|u)aD)miw?b`&jUb~1 ze(b3YpRMJvpBz*Mu$OKQ1dU6os#WN=ur14HXWq7~)i2|b^01P!g~9H^r*K^jzoa@a zYKaT(G_4Ps>cWGFz9gbgh1Rub+nhH|J{^xK9L?)!b2G0J4W8j?8cK3`ZMh;KXq@Y7 z4h`buN~>jKrMLiV1MP*@q0202AN@*m`b!;dc`+lFk97xLtr$rj!D)~da;ou})JRMH zN?!HFx6;Pii*56kO^uXKmZA2iiSUQkJt z{U->+79Cvsw`kc&J}!)k?#qhQq3Dp#Myh=P!Jk5336o7=l?&l3N`h&867fx_)zeCR zVVg@uM9r8KpOW@TbdBh0NdKEQBEDW)YRz07bTCHOOho*5gg02gYt>TziAuGg zl}op43S9+$rl@rTpDo{L`M<$-g_}$0Bze<9`iE-z!nRD~b;J={Ybn<7-K%yjZ7&Yq zx-vD#Kk3a$Qq7vRaZE>7k4>wIzKNFi=(d{E4c!LJp}$jo3iS|M-Zrxd-v;FOZFkZ1 zLPvy&);b+;(9-c?i`GR0;CD~_O#6Vgu2S}0o>0r`!%Fq$2_ zay7po5d1z{*?4$?naI1LW-Z(^fG&OJQ`oj%JuLasq zDkbE$Ys>d1!%pMNBU|gV1IiXdcL*Bc0|j;8q+O=4?Hk&ZW0Mk4S3`l95-0f^4DC%L zAL8G%?5S}|J@Z*~)!K5^{gc+?OVpNsf}2FjJ2rh6w2Dy|{8eq*Z3->agAU-1G*}0O zWz`5jBi$x%y~vBIlQLZO;^g8n@8rzUaElntAl|CZn%isI0T+bOMSJmLAnvnIQ1Qpf zH<*U0!%?V-FpIDoDifU_E|Ea%s-SH&TwENXo2D`+SysUfuf)9jC`Gjw{~LTl(S0m_ zMD@_Ta@8@Yl2nV{q=Hwg(|#3r)s9SS)uuJyp*$e&r4Wy4q`te!yZwedyyTx3i#4vy z0Xiv_;SSz#dTTsugwio7H7+*vz1q(~#R=~c8kItug|WvSD$e>dSokK3{)@yd<9&O4%5+uMN<+TBRxlJl{*vyyMz>d&o~(<=tD*yd9{8 zFH^feDY~qFF{VeMceIj6n@~Xv{O#keFTR&=5w~gGR(t2c?^0Fb2=ZYcL@-DrNHbR9 zBRyDiJf$o#b@HQ?54An-H+6XN6u&Xh%BV~T5+9=F{8wlPbJ?Mq%SwKF22~P42hlLi z(P2E9f@Ftlt_uv_mk0TcQ2h!$rLP;?W;XcRta==&%$eE7YcDAMC=H{d_|`M1QKO0A zinzSmHc!LH7|k<<8(?D;*;mywNuH+|iCk?8&NXOhkPaW*8OGE>u46UoNPYqZ&Bbxr ztD8bUPzY-Hc+Kge`ZkERYr4Bz*fuCp+qTp@A;BBL1TA)i-ie>D6E&x9p*_o8CTT7U zY2~SRz0ha84v>r|Qc!CrYe|NN!UVN;isrN=s9aA=M8Qt?v8HMcb*S*bjbbzzACI=6 z8wmWq#&llJbWC=DmNY2({_T zOnXyYvq6G0D9dhP*3$h3t;&{vB4<6Cj)r)6_h7yJa14IjSR3Kj|au+{cV(J!*H z3ttw)=V5O?ThN^~OGf$!{vLDDDvpJ!?Lc(%BF)#R7(^{3^Rb&PIf z%X$huoV&PuPKO-3Kc_=`yREi-tr{)A7+6-`R;xg*h__*rizU>u)xwXLJb4m^@){_w zD$iDsc&+lwayoPX^;P8|RvVAp6*>+uT`OXXR<41ygad00XA^KX5KBForJLQB z^@_~0p?psE5cEWLZ@DLMtqOvnc9{Uzz-A(VwMMYLe7rgi^)>l_LtYfyL1M7h#P*=M zyQsNem0#BWnS!<~huqp-=F#XhDmZekMbFISf?+{uoKkfu-3Z#EO7oT&rT7}uNsb5#`zNv*NQ;6htlmm z?764%$2vz?u-34y0qaV6c8Rch&?fMio8x?CbDUw%eO5=MZXhpM#rP*MUWsDG zqS%W>(v~Jid70#uDDB871_E&{y{KbSXYFg$MX=Vo$PTuDN3l1fSaD+eLK~_IGTgs) zNN;l7;yO5C7#+k2YmM=3FnXhyn*g(eSC&`D=hjiFUG@&)z*@s84V+R@j1f-fV4PAq z9A<)3hHzl5;gkbTSz?(Od_0xaDXa6jyj8`DPz;db6l%RvdIg|pRC@h~+6rr}tN{v*%R4|UR*i+Qz96(WGOM({BRlA>5b6pJH{78*y4%#kE+EA#ES33z6M zywR*wHky_8+_?N%s}d`$HP+f-tr^8WCD73Tl}o{_k7UrAz!HkX+)s7$1<*s}a#6kp zJ|isHu&@Scm3tFlH6|vZa&HWPZE^({Qn_c4GORV_mQZdU#hQ}1Sh+Xn`&v^S2bk6> zbu+GkR)hm<4W}(|GKod3+%qva+vPcf;o_D14ut^Mz_&yIYmMN4QD&8Up4g8h25U|1 zS2Xu$YOYYZ|BU|LA&+}V<(_3#F&m2QNl~cW+nXrv8(6gx+;P9!Q;?w$Dz>!i~c zW>`1sa#(9!-WNE%qgYSE5i9rJfLJScJFnb(=8x5nuwboW4FlGYC^m?&gvx!0j%tvO zNSz6U9amj!?Oe(cz3T!5L3Du-0&<0A~`hh?V;!owP7*rV;_HHG)|n zm_Y<$YmHzL2o^-Kc?2O;?hCLv?vyu2Ub)ZHQK^+qu2qcHz*rf@mPfIr zL?Tq~EBS(64gzs4E!8opvvv)25v;W?+6uPKQEX!rTTg6a<-S>mw2|Yk*TD%BX&W)Z zT4US?#ywGN7Xb>D`yL(NE*+KHW%~&S)*8-H;2e%(2MI^0+z;z;4w~Q`BOF+3IH!Pf zl30Yw{iIG=ozJJODxQPl8B!D~_cKs5D!tBATVbuW^)i$%lCoI2U(`usF6NaVSBL=C z8o?b9+=^mAf7#mVvh(^tlXc3 z7Kgcybn^w!+m*^4*Fb@QdOrm=EUb}Q<^C$LUJe-CbALII(_yb%N`zGI|0HEtYszmz zxp;uRPU2$aUOb@PKzUuyq1>AflpqjTYamX5*oi`{+3kUx?1S=b39i`>DK$H;0T&U# zS|jiV%xd;LvA0MJ)|!|f&3%WOE7a`opr;SXBOX$-GpmZFp;(F(g_^yTiDDV6ishmB zL4dtaqGHYd0iRp%>-6zC3O@GS$p z109K4#Wc1G&=LU61FUI)We|f0wkZh2HIt!ZQcKKM)H$%$I_C$leHUPD11yu+ z#H#!|9a3A4o2iFWr_KL}4%Ql7d(dSC*e`@8)Z<*6a5|dcbR`^EYdF1t(}P%qdc22DS)Iwftt$41Vqa1e>hZo%G%BbDP+MWGwRH%T z2a&Q^j}OvGStTlphAQ%&1qXKLMaftQ!7;P&-B|ZvYACb2e+&v$WKi_!b zgSEyt1ANm0Yzo1NHTbm9VlQ`!ZjPW7JgC&*xCUkt7VO`}ip9^p)Kh-urDKJ7mR-T1 z{?4wD)8V*5{oSd8TKU6cvL9x!B$mh{`oi^3kQ>cSs!|&kPfS6fgz>1mIZniAl$8{-An#w~j)sLJn9FKLPP$71)sq>=5Y-we&H*ERR54TpNdUJZdd{k~#%8{7$(5 zu5%UGnF{PQafx;GIUUX!j(S=TrcRTKLLUV&XDETM+JuA{oDXHgdIO+tYU zALRj1?p0uS2t}x$@99wPn4ml)6xi@lA}ZpJC2zLD5PGJfS_r|0-^RjFeU4Pcn)x}MENbSw(x3>b!-lW^D%4-D$X=?*iV}lZFTY%o zwhGkCFX8J`R4*6JpY5N-1{*$GNwAfu$lf3@u~set7@m^bH?+7;J;n{Z&Q;k*N!w}?fop5LmJlYJ$$dcLX<;2Q7|0jxEGQkBdq=sdAV z5`(oS_CA_hhMFr>(PhxzR}HG@vQ`zNpjeI+g-W`diDJO2Vr3{+s>CXis8~%`;xnwG zPG6W|(bVOz*19|qIPsNOEa8ZCbvz)>$=%L>(j+#2tR%vMwTAU6u#zjWYJ??J*vUGo zYC0;lqNzbRu-0%=fb)4JR-15yD*JOCPHhvMRKkI^hLZ-IFNsC0w7=9z3)7}P5x`m_ zNC!bfA`olthWQgTCIVP%1kFLvv=Yl82%-9Jip}wcygBlpG|A9Wsntvis~Fz_qirRY zS&4l^BtjkDmM`c`5QuB(8y%B6Yrm&1g08pg+3IDMy1yXYAdX@wvK`FC{h-y^ieu#%*DL& zV=NKCS|gYSf+>~Qq)Kc8afp@r6meTYy*>%g+?F>Q{*xvX@@Jh+tgzNt7l3tMB{qjZ z#maqNXmOZ3M>k&peMPCzmfACkB&T3s8XW$|c;pTo@vTyj6e*JH6z zI}CNm>jWU`c@t|D;3EJeMzeSVcq$kmF$f^u1mI(<0G|RNIhs`?fCscYC_RuI1W?Tc zpoUd|&j3)1)UO8*ek~~G$bGKvO?>b_r@@D{Huzsc`HN_lLgKfn=@aC^|3aQu<%~}zL zcx1H!#~hi1A6c#N%zXKo;3I3HvR~sG_>Kk#Hmt$nSU&^nM`99=tRK-43-hK0ACF(G zDrQ5meKgA=QSr!X57lLKWM%0HFiDpwU4U!gH|hddYhBO{KwY9)4grZrRu@3bq$4XQ zf1vIJ1ZxebAAtHqvt9%w9$9^YfO_Q*)SrN0tpN=I&>*4_j;ujC0QJZkO3JX-lt)5& zI4KK9)^Jgo?^>fs8P=Ne1SpS-W@AWPII_k;TsyMH;OiCgIte+lCRzoU4uGlAY%&1| zN7mFJfXOBRGpqv41HhbUHj4m+BWq3&z$_Dh`BnjP0kDwNg(GVr6od9AKKP4i@L{bD z{z@n>k7i3rTsX3p^CN4ih{3nWRaWIULVkTTTSM}~k+mKN!)p0p;78UP6O2uNA7ifk zE^E7XWSs-XnP~P0VTec88E|ZrIrx$F2cFp?KNEapZBzDZTm$E6aA5!L;D}gPfpwXf zgd^)RI%1o=6hq!+U9+lq8;Uoh*$omEkF1+e-9ty#4IKe!_9$I|Yv2xb0j#wycnqM2 z(d<3}iAUB$K&+!9>wf+~PY4Ls8qm{K@QG^`Rsg@dK>in(#3QRvl{}yV_*xtzp@*KS zLLbCdu?SQIK+hA6aAZBN15l5w7f2b_T35UT<)Wl499cz0Wxi__BV|}?%CAHDpHuLV zRrvtq%U5A#NnSXz%2&Zp{mTafKeEc2U{v_~81Lc7UtP+NzwQ9SHqsaV;fQTeJ0{Qf zkiUMmllmU^@AiG3>VBy1t-^Mbu=r8_-YVKh`MY%t;5nh347dgk5DIMgC`W*Dh&aTL z@eg4H&d4LsJLn&bIIF1R8aPVou;HtptYY>NexA@DBm^72&>1xIG&NKB`2IBd_^dq6 zA%E%YtQED3P&-d*!bkV#P1G(~QM&=PYgO145)?nSzs6_N6`i&)oBpD1h7G@)?*rv- z6?U6Y#ER3|G;lVYR} z8@~E$P=A%w#gFJ;&0qa>Qily+y(H92#IQFAK=^pRL`+Wh1$oosAJ4y`BT{cK+pQqH z4FqotbH^|jQ3xN+dta=)=x&}7r zlsH0x4Ikwrpd=E9@KJoCPF0<|A6rpNhFUdJ6F!Eo1~sFS=@V)rZ1`=g1=Sj)Dt-iC zLnn)QmsdX2CUw~G)$2jMZVXF}VReW>{P?}DxNYF$_f$M{MczpG$M1FW=S(9`*zh@< zfU|K7YebOZNAHb+BouVHjdb$^z-QzVPre2+2njYEq_>m``xhYn6vMtJB=LsOPe8gU z_Y%J$^gW)rBR>;-L+GATb>bTMm5^Y=NBRv&9f(J`8Poy&aS!65H-kD_QR@b^E-@^J z1jQRcU7+}cZUp7%)Ist@X*#Zf?$mVH@SENbFnwZJFM<(o0`&pFb-D@ED}R{&1OppB z%rL+ViD82XM!W$uBnW0u{xHJ{1~z<{F@PCGB*M*~Q95z;6d6mZu;Hstgz9)w6>j{D z7ghOt|4F0@8@}ocs7{MvQ%G32=`#(&+D)G+_`01FvoPeQ&rB=g^C3PrhRr5%;fBxL zAo1BI;tQ;ZFNOHx7`BMSg_}K#gTxn^h%d7uz6#C`wk!M)il_!;Scsk zsIHG;Ye`tR$+JF2yUDXwMBq1hHd&G03F+-IYzs*XH+Z&VqtC|N%Dcg{#ROs3-$%F< zlN|BAa{N31!adR#Zt&cLS|@pKhuq+KNPQ0bcl$g~wLokbM4;BX!vD)nAA; zyTOwu^bZn(4PU4jn)xC%Q@FwNVr))_Uh+7H+~9fHirQ;XdzI9L8$7R?sJ(7Q?cY#) zGnN%6LGcF9n|wAE*J%s0sU&qXZ1~;m0g4pMoP;9Y;E@2(S?+3ngU6Xal9!NR!$&Fw zBo@njge2VHVLBq8jz~StBMAjIe3WuPDI3e)BNX8VPgxzxdnPF52?aKMl>Y#w0&$2p zcq-^*g=tcW)M3L{kAZqLsf#ywqVrdeC3V>F)jx)MQY=d#0O1Bt5;ncQ@}|dc@FeJn z)Hlghtsv9}Ld{tAX)H@73gHG%O}=P9g}S(Al65@l4E>C{1~&YzNdwoHvFwXjmO@qU^_4W2%s1zm10-TVM>Pr1aCuYvxA1RD-g)++6%eij02J~0VZ z_Iv;gkxPP*Dti$r!&*~b4&|k>Y%z(8mG)A;cP-X&fN7Xg>*5+%K{&A1aMl86HL-}* z_G%2y1bMy$SKAX60$c;@hyd0a!6ws+J5OvgiNRVE+m7aLrREA%_g3`xM0wmps_q?D z756}K7byyr_bwB~y;cic&-!}ja+g&B63x*XP8m;V8r6S3?V;fNLZ z2|x^!yPa3y$MVNIMOd)bur31Yd@MUlSV9$kUPpCSN2MOzmk0;e8qQz9xgN`|5{^)b zU)SMWHNm+_IIz}m?g8fxv53|99i6l=ZSE5RtTlosAb3OsVnzNae*#;adJ_WH8o@Jh z@$9KMRxnPz7a>&TPsQbAPmwoAUX>S&Gu}X+wTkf)Fp9>p7vfl9A`vR{qH!JRmo2^k z0&y)B)-kEGwitC0thFwB18o0_W3R=rSBXum&i|!DdX3}0s)G|I(woExYmHF?qce`# z2~eoeojN|dj!Nw^H{rlq!|?;>ojCRu;RsdwJ35@VOmGWzst#we3C;|{fwhJ+7dW$tMXcOs>!gKgGmi*h ztr6scU?CBRmHWc{2^JFptTlpFAXpK{mJx(dxv#+HxKiF6dF8%LN2OLetF2;e0mh~{ zwjqwKBNCx<-^3U61`vpAX`PNqowZx3i(svF(LS*4iDSFs*bZV7EB8G*q+J|$hYn7d zNc)Kq)*9n6Fdm6xhX_!p+>hw^4(X`WE;~**u-0(S0OxcZ`-5wPS|hN<$Fs+A>|q?cPaI<9{#e{rP`N+EGi&9IhF9+Q^Jk5SS8rUvT4Q}4tk2?y zD5yFUEB9yPLyE)Pr{hBlC_pb&DtBB1g$WBbEUblEH2!Pzd)nc&KO zheCjBz()kI)(A?)lYD*c7dQX=MVqZEnwuvUNn)_p#NJ19%aEQ>xtBqI?~unmq;fB7 zRWS;R9L2COPph9dqIv5F)rR_>Mf46CTq7iL&AbvdlHE>8pw{?|TP5i9q2 zKx~w|omcL$`C}y!7OXX_Pr;OoAI7I%5-Rs(9aS|Qm3pApARJh0I4QvS9KXMcaD>YJ za~)1?6P#4SfwhK{2AnU6MXcPv)JY4|ralqCS|dmYK|>-CEBA)^6Er3QSZf5$LC`dw zWe|i=xi`h;xLe*FdF7s=qf#rK7FIF714di?V)A(Q4Uq_ydt1JsGeID(rEhdh>a6{q zx(L=<7qtW1ulOzE_$Q5sO|0C1)gk@Naevgo2@|P3F~VA7>;lFd+^-=(p>ogB@paTu zsa@8UaA2+B^Z`yU{9Y@<5i0jyI-DLRIDH8R)*8+r;0z!Zp>iLfQmV5^G5p*WNj zh01*>6pc!+5!6;#Yi%6^#8(wK{R<;PeefVD<24Fps0+r;D91mX}Y_bKAG zg35gop4l&NG`w=3kU#5mVuiKFx&W;6@DCCZs93qr3oQcH8ze4P?%VmkwpGUgrb9~IjB8*Q z;lNtM*$uxt~-Ba19(F0$6JVhfOQ@Jh3Ar25U|11e$w{nk!W9 z$I#y=<#7+G+)r9n{1b|&NKvTVPnjs5v8s3piWl&Ec1TpL+%NDMc21`+%&^PU<*?Se z{3dX2;Gahz9IFPc9=F(QDqM({5Xyq3UTB?zH%e=Q*=`?S0{^2+^H9hF+?6t{}u0)``j zl}unIh(xH|9SPdao{}IC*HQ@`lR8Z#>LOTcUBtlVOJHv&FfXx*mAg-e^ft%!>fnTl z^e!>NT4VeGjPEC~G6X18?(ggP%IK)nE-Obku-0%Y0jFXD3lNS_xmVQT1Wa%~Bpg_4 zII+N~LM%e%UPY&@&gVF*ib+sRAVr~aPk^FP>Gct{71ml?t3$aeDT|eRRh=~EVqW=? zOa!pj2^wSEGtN1$Tm zULROOahO|AH(vmKLaE$w4KySy*s!n;X_b3VV09-Zp>ppIfQxb|5mLGLB4t=>$^)R> zFM;(Taj|mm$M>~9Iu0;hR_bP40|N;M)*8+*;0z%av2q`R!RhP@socA`H9C{89tp>m&WqBzZ} z;v6W>N?o+fwhLS3phK7 zMXcO+=%j^dvzrKDtq~jm!9F4oEBAf*6Z}pDu+|8UgWzZaJ4_Hl<$e^KV|RIT<9vEj6*q;gP6p;v(`&quA{{(@!mQLxI)LDChx(L=<7ySjc>j~^?0=rCX zVahjf+WUe>`06X_-~!dhc|2*&#f>@EQcmHT}i-(4M*+GURj2i6)+p~QGrAd%S; z)wk$EitP8?$8{$`@Et)Ox* zj%Rwy8x61AU(cVlB(cI;V|@#(o^bCJ@=tX<&JA$CK13|Bbb|LR=MYi%_A{bYhsJg+y&HJ zp>kh<{vIlid&oWaT&s%9ptyt-h01-2iQ;mriff^`I+3j;QL%Dg&1cw3oxU)`)=`(k zTI=$yz}cM0HWH3lxo-xyE)#@MxnITRI6~eWdF6gtN2OLeH>_ej0LHyUb|;bDA`+o;zsDE! z9T13X>6VU3owX0Ci(svF(NjtIq$r6+B(W#NCRXkRlR}XqlC%@+~3KcwKTE9T4N1>wR{r$fI!8{ zy*#jl;xP9E-FyM`5T$a*HBf=DVE-=GiqDfHl9YeF@!LB1hmY#0>sYAT+tkVFFkY_S zLaO%f>ZqFtZ1}1_L-ofx><1DSEA}7jX#3d@ItK7eRO)411HTXoZ1^Z0fYOdQ#A>}= z9sC+fd7cDU>oXK}Tm#vp4jaCDP93vKJx{1J3BiUh)E&+2O3f6i^seaR8S*%XROvme zsP%zbFH#dK^j;=veXXbshT6b7tUn2g)%id^oBHdth1oQOx*0b7ZXOMkk#*Q`LJ=$T zkpP$|cQyZMnBn;&jUgo1@R6nfX;K|Ffsll%e3Fi6f{sW%tfvwRZ1^a1fHJENn?Wc- zMLtW1GQ$LAE}_7NkFp3T3y4Fk#uw;hg=vyY>agLfFNgY4QWq=nrTMF`Aa&UA)z?FP zZ5_6n0E8-hEjGQ`@}|eD@YOmZwQAX51z{%;w%1`>>#)s4AynYo`J&wlb#cvX*72w_ zbQg6EZ1`Ps2wcC{Vf*W_y~HI}-@of{_H)#|Ixu14940>4@cB-G?_?czoZy7Y`=pNT zxQ2pfJIA3*gUsfv~MJ)JD(U0(U{kknzrSAQx6?@CixL<)OC3}TgC zFh$rlP-REpnfdZY!mI2j`Ex#kUe5B8SR4awmAS9u}uB9WY zp(9cc<aC&PDuuNm0HMNeg-vg*yy@`@yM>NOtx__rAp8V`|D~|+ zQ`omeAynA^WI{?>P0B9;iC)$O8*qrmr#TXyT1;luL;T^LV*n* zWjIiV5{FP>57nuvb9aOlwJ}f|MQTEYJql_@CDT}HBW(C>oCwwNq$*a}<8`u_cX{Q* zBvOYBUwt;zXQr^}DQqe+h!yrsaoa$JJsr<%ls6JyVNcDUa}IIBhR?YKoVh7%Awh~2 zc5Y}vm%C6mKV)E~!p1eQl#pPwVgLs4rdk4g~$mKvtg}s|pVZ&Gb9jg0N z*j^GAEA0Jz&)TbF0M9n1#>F*okWgU5M>z(RBg7$A*herRd*nG1Tw(83)Nu_QCw18H z)lZpL*m**yNeDK4p>t^F8EU3bVV^-C@0G_nq{2RLMeQ=wE|Qv1VP7;+yJAJ{Ce&`E zuxlhJR@gWAY`Uh?7G~2e>SoyRyZIqd?x(Q3gd$eh_W`g??rL6P-_0NC5h1~bkMvY3 zZa<{5h*b4$y-;BnObsQ9z%$}>P!Hv&Q|S&vss)r6fKoV>Jx3@)gN2&xMtis9(9KLscT@v@0zmU zdM}lgPGzNtORTWp)8UlnsHJpZ!o>N2_+Z25s|3D^sVqQnLWNyX#}?2Lsa^FUp}>ZZ z5)YKvR91yhgbF)Whf>7^C4o?2!$+wKl#hr*sIWiMsj73gniaKAp_WW)LWP|SHKUTL z2DK43{5F0D)mo$~R@k+4vY2;y<-_Ns4jaCDeW=$_8-6!W0m`IQ zHi1yY3VRX&PRL!&E9?pRBTXeF*zl3&0%>+Cn@LDQg*{tGG*d^U9?J6w1vY$?B|ynd zWeW*KsIYT&C<{$cmJ$kV_$aG@vVu6o3VVf4R+uKMNgXzP^$k#8N9tmQy)J+Cjie46 zzWNTRZ%buc2tcT?{||BR0Ukxw{qgTY6cKzu6!k@v-JRK4W%pu0#AHDvKqyjzG=Y>2 zreI#G1QdJdy@T}LrFTN_z4zXw_ulhAGjr!;@66mh|KHC4dH%f5&P_Jwd%mAr=j@PI zcEO={O+NIn!royZQmd4`RuGN>!jUHAP!n>1QZN zqCguu$^$^T*M!`mC`^TY&wz4=gYuA~KpQ&BGeCJlIhYFjiNRG}yU(q-Wr5pE>c&*q zFTu^MWU|GoPbZ)ay^mqB@PA^BRiBcu6?U#zy)CS}?DF9?>JDw_?*9Sz{ITTCSn>vC zU@PqWvCOdn751C(&Mo;M!3z70oH+|nPH02t`~W!LizV+;NVdX$50IFGF7sVLVv8RD zzNA#xaP|L}B0(DpQd6bE{v41>QXZzlE(zv$<#Iq*VV9<^(1z~n2iJ&LQid9{6?R0d z_5h=dfdP2#D>W`${beZ%w4tL^0F?5SgRQX3!-PDQ*GO=M{Y-I(t3QgmLmRq#bS$sJ z&Niw-ji3$P=o{!}HQG(4!mb8m{7jx_U4>o4idzi0)uL`pgz84LvX7fOX^ZX zw!*HDtEsNRn^{fY(P4%*^kGf_l(<;Zgrcw&b{qiQmxmfF>?S!Q1t=1ro!$Bhu%y1(8CJ*F9VTU zrF5}^&=(MT$C940q&uZxD(v34X?ub@yJxx^c+?fzj}8sAp%2Y4;2IiB2FH?tl#8vf zhZ=AOBkDi{7_)GOQ$A=z=Nk`vV`Ir^3ddB~V-0Mh4MgftO`s^yhK@2FP^QL`$rOdD zu%{YOCUa0`P!woGN0|dCvnU5sVb3zSs%v+y6}N@pHlMmN7502^Gb@=E(LO>OdLNg8 z>k{h9R@h4nwy^H9%ZE(r4sGb}>%o0(ELj~(R#FDG!d}ZB8&F}dhIcxO!4>w(oH;j8 zPH02t+zFi9W64$u$yV6g^#xt#R>S%L;HOH34OjmziUe&aNUf9#`x+o!p*&25eFec2-(pbZ`6F`zu89BhUC z5GG`Zyheg6?4gP~T>Vd|JG7y@zu;Eb*+ws^5wxKj+2g8^EZR+`!p?#*9xBhXuENe0 zXTj}ta0`o5KX5Y@c37ObTOKQJZ-HCBIFgqdvK4l|IPLRVUV}HYn*I}~K52k9^kFUx zDDT9Pw@V%349F3DLsc17H@ z6~LX{Gvy6D>I#jfLj!H-LsJ{LYQ~Xo;z%{h#a7rg4LIK*YBd8Gvv6W4AGD$KeFuCE z;z&IT$5hx23~cobMCwpAqA1XYjuHTr_&5?vQJ4xl-hdLzK}n=2(1wnZ0w_t8gQ>8S z46f?hO||0oKXChjx-k{@58!52GBu}tgf{d(wg%Uh)RnEUTN-R(-DQ^#ZKyl6p}YSA z?mx$o_HiVgGO!i)&+M@Q6?S`gXS95f;4|#>oH>7`oY02O*%>%H#*x1$BwJy31SF=Q z%lyl*J^*-#T;j=Be;0}bZ74_?r)~7V0{Ayz4WUd-l|2Li#>pjt?m6}_>I|(l=P}?s zDvpex=4_=s3eT<)1`c4Fpwzl>^^c`E&|1Tp1UM5Y3tMeZfXSIAub1Fzd%8jZSN~*6 z0IfBG>2bVg+Sz6^s2Q}@%w|J(XVUI6RrgF7@9FZq>#FWKRvj0B<2>rfRNnJAjti|i zW`g6=II@_UveoxeTw#k1{>%znPKO*?YeT*caMr|;RTPJ<65^ab!2eVJh*x2Atg-oC6dGT5C8* z0p~DfVXN`O25V;79HRu#S|d0O1Scs0Talm4ncxg1fYutpB_OyMN6u3SrYgS(hvQ87 zaKx(oyn#xsY%W{HxC0os;>e9Sa*dKOmH92)&^Lg9-AmUDOzNt=ONR(rYeV!5*q+3Z zM{(oc4LEt=9rm`Q;^e0|&|1TJ8*mCx7N$}!U~pE~b0Mpa?}6jH z)RC#y-vvjr((8TNS7@#E^+Ry}FLh=s_Wv5JVJ&8tA4MqvwAKjRKp?~uXFMrJIoPUQ zh-Z!!sM?+I&RqGR!K%Gj&a4t;h1MGDXTVD0iI;-1l{*0}rZ~*>8rBOyPg5#)xcb8> z7PKK@o!2V&%79goGBK5VMF3bJmlC?lJ(@a0Yt6X^I9HD+RjD~!xmSc~{?2^`0!RvnvxV@f7hdupj7I(<&Y$t*cZ$PQ?tdC^e&^tHq&U!8!|4V%T__7%xpy&GGs~ts zC4kl%K_4LKMG4r-y;sfzeJKI7)(D0G!Jv3DfI={p`yeX0pOW1fpbZJ@g;u%eN~l6?3F^mQrgFC>^ys`v zE+ur8d+r4FGdHx>ob!Tno&@q5HD@dLJPBIm{+fXUn6@Z&GhF>|QXFWl;S>Ozw-BO2NeRi`U_G5Xsr>vo4|YKo^4i`nn7#L?7z_6_i1;T%Kd#9?}PHZ z>nismRvkYE$D-7csoaZl9E(|Xbc3UiK%CT+t=t7%VNQcTv%(}gcg88>mVdsMH(!mlOwDYdGZrr(6Q@ zQyivpFK58WQ8z87g3E0ZLTFwMDC;_zA z2l&0(LJo zG%%^FHl7Xcz0?)j&|MFM>%j!FpBl3j z`$0U<_8S<0=d4mM!_|L;qCguu%1J;uPC3|W{Wwg>C3&3$SL>G*cewgbQFmxVcR$Ci z)U%DwQzK|YH@XDfyhyvrROuICj4#XctgF&5TXDM%Zda)rQ=wnwxZSYgb`RX{B#>Lw zkgd+|;A*;M@Mc!ieLBq0hCa;C0Od&nc|=jz%KQlcoRxUvVhaOhp9~y|%s>NXi;Zs2H1c*C81WLhF;GTf?(8dk!?4A(}JnFJ2PKO5C(1+%8 z;3^p)p9Kh^Tx|7S(tz_Bq7nlbvv5jNK4?SdD+hf30EwV*Oy%u2utgY%)S>!{qCguu zN@YN)7$6lW3R87gG@w-AphQy?XhTQ&22iR|4yNL+W^h&4ZVfALG2m8w{}u>dIEybq%(#?y}2=2Gkwe(A^WjJuX0+1V|&wz*gCD?6Cn=b`yB# zmVA(4mE9<3&H&|vHgwJ(fHO5fk|`uxVW$ETQ_y858`cK^Us5V;xcbv5611Tp`IQR$ zH$eJ@@-P+lFJOLGE(dfK_V3gc+R$A)fon#9{7H@33OfVOtUnD5z;j=zapCIkOi`c> z9i<1LbfX+>h20G%BTKv^6h3n>ayVJ|kIEaadpqbSgZjJDw_?i;{;9d&0b z>~%T2Z=~+fhVH%t+_weD77D;r*xTUHdnq4!SYdB55UEwlPAdq90O3G@>lqK>+nuTcW{LrmZ%>dhBF`Kgf?`}cY(7| zA}L5A*$TT5ATb49WI!Y>t|h?Lmq?0JW46NfC29{aiW?Y!r<+^(Z>qR${?8~1w4tMv29#2igRQVj!G!dY z*GO=M-B)pktN#n?4sGb}k%_ztJKM-lji3$Ps62GD9PK7kVV8q3?kmr;uEPG>id!Xc zi=u8!g&oClt8B&X8*r^cC@ zO&)5juxsaxRF5J-8#+=fAT>@T-%%u{!ftFJ`p!V4-jw4g3bdi4Bmqj(L=vDVOoiRl zfD+)KBvTY9Kk5!`=`HfOA74~1aY5xFscF+7~;89m- zCpt9HhCVdCfvaaC>7GcsQZBZ_?rFg3j;LJ?V9dhlL;0W$oo@*64N4>fC>&E^4>GU~ zFc7IjHI$-28#>BpKpB}xhEo)#!X9Zr8O}i&Ls6g&9c3b*jHet-g+1Qjs;=EhR@|n6 z+Z5`?RM=C%&8%daPWuRL=zW|8uK!S1w!;3$U<>OmyL^~U-JuQLeF?ZPN+b&s$vn!y zR@jT!V*@Je1@O)g`5?h(*zaIQ`yD=8#fVXxK~beSs+>jQxM$R(b9 z^{=By(EeYM&Lzdz!<7pARZm zo~#luJ&gi_?7YeF|AUp+NN|NcU2%u2 zKRg`u18&~7pn_B$}f)8%>ARoL%YaVr9DA5b@@!v28c z_MsIwC%6?$CLd8lw!$uktLYLd8o0%cIS*# zoFYLRI#MY>3Qr~_C=yd)hZ~4W7>LxH^5+x<+R#z_fD(~R%1{)h!j3SYl;NP1r6|yb zj#2?o%2N)u!Y*&HWtK@4b%!=|_bT9CnYyzTcIBMit5SDpLwBzY?lqIiHxz)WuxrAh zH&Z_Ju)_YvK%`bFF;);70YbxMQa_p0r4&qs-4HizeQ;;@OkD$yxMwlC7|Z>I=He!G`q#z|)ip8?OH06baf;kksE2 znGZ;FDG&1udoGwSkjnvGg}s2fLL0j4GH_jzOcqgNw!&V5XVxME1MnJDw_?oYw}F?DAv z?8iB~Kcnu@hVE`pfqx?)nY^R`Oog2Vhu%8*(8CJ*rGZGTQgWqOK*$FOc~eN96!Kb% z`jmyKu=A#Li)z;ZUYU7P^n2ztc!xc()D@aPMSb1^ZRkT&7`Wa^A#bOU0+frbu-`G@ zyp5;@3}DQ{d5`iz8#>>|z*jVd6rpfTgVN04plLV0&VCh5}=4F#6?k<3R^Uw zxHu>tiUMuuC_X?bPC1wgySTwsUAx4JTS;*HjJh!u_GjQ`Rx*{MeS|jjK9&L3($tl$ zuuB_kVclhy4_{JuXhV0e0Pf{eNVyc^rwnX`T|R|5HlV^T2k&f>4-%}f{W)_+QBG(> z=lljZtEG@C6q2p5s{s;I&}CLJtPcQQrBv8(_1B15Jtzm5itj#H8BgJB>@XZFQjRq?9#=VW=Kx++WFW~G>Av-A! zQ;F|3;Oyk!?4vl)TEjUEI0q>UTa6zySToD!2ql2l8o@~*I8F)Jiu`!a1g9tgwAKhN z0>Swda+X3cRrz^1952d;BUa^S4OD7n^RHEmTYzyRg!LE zq^{cAbcmp}HbhT=?NJJOkV5WJHnuu{WI%d=xc3Zj%tCrf8KJetXitR?S1IHr1!OAp zECb(51C=^txl+{+GtgSY$qP7nQpszn>ZdHGO3#z3pTXDQ9rm`Q;=D<5ptXim0C3)- zEKH^TmcdzF&jqbIz6*|ps3TLY7XnAK(yK7-E40@7`d@H;SStC5aH%eri}R0DV@e+~MjkL9w9yzha$uKgM22`R$YGZL5%T>Euj0Ih9UMq^moqTH94U zI(N=*%XnDGX3IR6E`QTNzGR+B@6qL+yMcVkJO%GRk_(NiZX5jcsyp)pymQ3?Ute)Z zm(ro#=#WY@2k6^!1YB#vzji7Ad-503)vXV0=;*Tn{c1Y7Orc}ju7Zatwha3_HrwY4 zzJjcM3B;evKbN1lXzz6%pC7+`<<7jCF4HNh%**h#zAK;0U3so_Pdjf4x zPjcH=MHI8y?Qhxb_T>?_^yao6xox?_-muwi8E+J{+1|?adT#qh3|SXpOH1xx>t=_T zFoGFQ4#UI0v!@Q8Q zXnhKR8Qc>*%@x%A8)0kHu5Hjjw0Rwv>=$^-yQsWnuDrohK1JmtbL9h`G7FV2cp+N;^HMj&)b(V!*`BrAztyR6Ii;aGRTolA+q`Wsq@{5>oAXpZ zp(@=BtG1T?HyWoLB^mIIIv;=N^2TWKT`{B+FQgAz_XJ?(DCy4A3_;C6{TiyQjDLTg zatta*nk$F%lv7YS(Ofy6r<{q(>AaBn7&3#-A zqm{g5yD-^ybLCc}$7Wu#!ac91V>UaF?&8xn)c|XFCB7Vc& z=L4QfK$XL9a>6y%vVTJ3l%s^eH|l&8*X3=Z#h1d6&v+q`Xk7+?nWLmMPZNcj@_ya@ zG`CWfl;bJCL1k5QWi(G&7nL#Q%33^SBUCovg(P4|EH5M#Le$Yt@|#s9vC6`0%9FQ2 zhnB{5(cHX8X}n~=VzQsjmFAYl}F<<|P?f|fGdh-+dM>7(#oM!X`#(B0?#%9GwS%ZjS@tLi zXq&emhV(9LI7)i*R6|fTu&l{ZlBi`LLF1I8WGsB6&c`TS-lkgoBn%nP3;74FrvWf? zluY4i7NBNsS<|CrHcz<%mCMYPOL)o+s9bBVT+LH%L*-^($Q}&Y$qP9GA?j!!ENga@ ze6K9L{XF?ObU1BX7bneobexy$IwrefuDoRQxX4TP0F&J{Pj;K9e1XcR=E}!BWv+7C zU}o_`@<53CFd?iQXRqbQki5K*_b}w0a{O6)yPVlklBCRN0bXhcrv6Bl>p$Sgd)99M zP^ZS7`Ehxzdmol(yO*kMUN?rg${UUn2T$ci)hFdmuv%%^!)csylzai-sEfOlE^lis z-j5+)@l-C_4KPV$unWwCa${2HHEuOLoD!(&VHsC1}Q5nw* zNyU&PUPvnlQAfLZd9y{?R_S;ePu>9?+8ftJx_OU&GGyCR3$$tGdh)* zdMTz}#M`rW`vRRBcjmiM+EMa$lr1T>RnSwn&Wi6_QMMnLx4XgH%D(>)r0U>(5M^ue zL(qfD9$JVCvlol9B?mT&e7PB}>%ry8iNX0EKlQ`SXgjJdKFPx&2osJ<=)r!N7M$HH*7 zuyxBtpSQd0_QpI>DvFXo)VgVl7C~!jwlaT-JnhfO)K0$|7bwa$`qj8t8^S-)_BUPj zrCLZ=%-)Gz9jlbw89ZHI)b(O@a}`|=o^B}W2ASyw@N}b4H=GwT9z(|PLZ(58x*8{& zuZ)R0xpD?ixfqoT%$4(a%H`OhrMeKDzIB*fYpq6vB`KypaDwh`Jizt7v*QzN=Fn)yBzz%8$&I zAM%tQREp+G7fqO(Sz`keTB*V=E)*>%4k$p zG*?#ODQkdI9n5OHkUE&WmM#SMS_2HJ%L@r$NL&uH)})eI(SJ*s(MG(~X_z`ymg}D% z$a~gqPu8h%QT~PM-$Bh(_YV|hhf2Dl|1rF+?E7vYRR^zgCH98#R14{g*?U!DZZug+ z?jAhdP}B`#b$1or0G@6P>PDLBhVyijP&b|zG95#v@IvN7h&mv%Dw*Ec{?RGzZ_}Y% zg35*F%K1FyDpW2vS1#iz*JFp)=t6M%wqf$kFr4g-Z6i;#4@J8{q`R?&L67bB9X#y| zWO}Mwuz9qh%3WDIxowpV2iPl~Dle*DuWYhO3TWB?L*tYM{tkSj&S$~O?3rFri~j&a z3iCpWp>t1RK}1f zUPw&{QAfLaWwRUGJ4(l^^5hNCp`LMFd~4pL7+$hOOcrmhj5T^R<|RwRWU1!Kl6lG> zQQ68|*@CD18I&(~h2UQ6h#`OSLV9CJj~r&Lo4n}^PqW@vX0!`0^-xSb zh_`3$_5nII?#yMVUaSi#qHW$a7_!nhoy&QuO{iLLh9zm)x6?S~DA@zwsPnN?m)E1k zAH|Jm6v(S2dKPjuDs1tK11bWUWhGP zy8*o9g}ebF>S(_fZFZCtS2~_MnmyEUCJLcLfoQ`m=B;Smfvk>VK3=k-nC!pi%J+>P zg?Y)`n9OCK%)wIo%#-L`Tehq!DjNovdaw;k(nJXvo zlyguy(_A@&r(A@}`Mi+j7_yWXvK~Uz(OzS^C@Ux(U&WK}M2Bt0b+N^~N1J%b4r8(d z=E{9Wk3GC(XE51G^JK?)%FC#{Xs$fZQ{DunI+)jZA@?x(ZCwcNwZ|CpfEQw~qTM52 z718l*oJ5ZhyTBduzd+`7x?L)P+<9p|Zc-7~-m8xcfMG zDle)&F~h2@We=xuiq#kJjXEEtba`X6ct3`G$qR`>>+%5193|y=n(C;jQbl(^t)`4% zWuCGwDr3x*wRp-VsQk`c*?^}^L}ffLBo#xFcp=wsRm`fAx=P2>c=8VD(B8N% z(#?DHBQIGeO!k+#@(-iOZ@gr^FbL#+|tx)mwBSjkV3Y4?}hv zr*kJybp%xh&9D-+>?diQa+I8dZ`AoXt;^d~i@$^+7kD8z(fXSHD7nJZJVebs{Tgbb zjQ<^;@)atdn=7C4l&@FS?k~Bk>W(kf(_WRm0pK9yM`d1KNFfXum?sy}!CBRCiz#N_qmOvWN?#&z+pd5ZzjUG37$zEczXXeSC@RYAr(@ytX z)pV!3x(sa9*wY=?Wj;`G(~a`~^BZHLi=t<~@4IOZIwoZ4c+J zuG_=v_}i-+)?OAbSpiIz-#poy)!739SJ(TfeAirAh^PDrl;f1&`c`;oG?lljF zh`f-J7*e9T*-@g-nyKlnzSkKVexbF}!u7&3qtG7_za0Wfov z4CQGiqGntp-BO;WjNllaawaOLn=7aClnYTg&s;f&r_4m<5?;s}3|Yww*#aTzXm4y} zwkYQ-9beCr??Z>(#&xmNyhq!4$xdLhqvp!PMvsHMWEU~nIrC&^c*+~7ylSqz%v0V2 zB|VpUA&)Wn16>I2wHFxjlo#@PV{OOgZp@!GdtW*4wd!Im34W_04n3ml}&ic6jXlC3u%ra zKk!1*Aw(VRHl~YmqtfwKJoz8!@T+lMbTIGHPrPK^FP+6A zwcD5K)VMSEqk4}nWQVqSk73AR<8&V6sm`G4q#4!$E&D|pryM0$;Tv^6F6r_f)Z%Yp z$aP-GL$to9KT7WKG%r!}OuvS9DdYcyr+mE$-X)so4k1-(Z^9nq*p>gFGM~9JFHiX{ zD&OXX6v2@9c_A(cQAfL26SMo<5vAiF@#H>q__T@P7UMDRk(-yS3?}>BTv^iS@fk1K z*O;uFc``pwSrwI)&6O2-%37dQ2lE?VNL@@GqYJ^k_8o@Q=Y=%Ikc1p&Ev|`KRdPa^ z(I&jq%`x>4vRq%4$a~gqPt~b$IcK2y4_(M<5Gwn-JBD;IPG={csxPW~nPFYhvJawh ziq$aqMxBo#y1bXQ_|X_Lf)_Fgt;Yi}Q=>a4vPYj%{}QfBlGUh4m1>i1;1{wR_6tlj>uPK`UWG^$JLLhgc4+23U`BqG*u z_bJ0uMWL#^8P-!Rdled|Sk-`U)cL5U%lk}=uY)1Acp=}Rb$tM4j*_}OO#n4G)qfc|UaM zZCn>U&3n|HmuxsD8)~i`Z1fn&OEv+MjWtg;nx~wB%Bkkc$vov;P^yDDix;v8lh4?TUd+FgCSvY?7590|A7$oKLV65PIr{# zv3c&4F*!`IxE8`-v965JTqi zLYAZTQvFe~n5S8fnl<`0GElsmfE;MOBO$mS4;M9gS10 z;@}%~J{s%tmet~$Vn_lnP7+Vk1~o19YpAp`g3Wo#Ur_mzxw0Kk*%6h0 znk#?jDZ8Vx3ooQEhVqUx;#lM}9< zmc1~IQ;w1%@Qpej@9Xl`*W!y|NKsyhgw_H8Ge?P&rzwFNZ-VYdR#h4QPkG8OQCZqt zS&FCp8kObDm42Qw8kH4!AvG|h8ZV?Cgs7ukC&BFg_MOu4+B|tYIy5n^i$>->YRF60 z43j0BE5A2-B=VBA!DKDXlQrilJD{??xiX!n{1cSwVE)Dn>5R!UbRoFcdSFObUdSK} z>7T=_^_4fB;s1jZtITL`Uh2`9dIWFJ+U>)1YTTK7QN2qSlAvwgBN%efIGy`>s#B;s zZibbrWj{~jl%wP_e520CMP1%zTKo+RxylQEP^yDjjTce}lh@LP z;9hHhA$55n0St-DVb+=i%#M;)%8WMRrB1`tsj^)E0Y~1m@E_vRsc}*Mj_O}@AwPmp z+25TpB*QqJfAUm4QPs^1>lZD1KN_c44Tf*j`52(f`>Pf|97BfkLdK!>XaHual94>k zG}KJiuc35h1Sj&8^H4e4Tsf1cT!zZU=E{XUHaZqS*~Vowe5!&5n|e%8Z63vUezSFN~=R$#VTsBJWwd zy`WBwJM$A%yLBO5K&b5R&oIQ7Xt?_n=c&FxRVg#9K3aA^jZ>_?hHupQD5uNYSBtNV zAyK@L8faY&fSIGD3QtoHHFXkowM92&1Z(q@aj0x;uKbRtOh#o>b7g?1{2wZt@j}{Q zNK0Nw2MAF|yS?e69H4YOohR>v4u2Wf#UJK9`i+;Y4<_qruIz5~=*mkr6q5}yPd0$3 z9D~Y{=E~tbotQw|m-q(}0kle|Jqr{%fQRPQf-ei*#Zkm?;Z5pQ>CGWvE z>U_MT%R60*{}4ky;Dxx*x)=a6N6AM#O>xwCl66PP2xa`;Jmu%83^!Mn;3>@t$E5{L8%Vr&%BVoF!}Gg5Zr5BFr*_dq#uU#&SBPi%A3yc ztYoe-quqI_hhyrYygh5T57w!1XD&eXTwTZlZS!Vg$P(jpF5;=yplYQV)+#OgMjEFa zCEMT|bv`!h@~+n6cVoy7UdSP|-mgDO_VP5RP;*?rh88K~f0U=Zgvtx%%5yyBEmU4N zS6<~QAE5FsFXS19Jm!VuO3_9;%XCq$Q#$^VC(jRZ_1AaurWkH9c~W!-vO0>drLcD% zoYwa+**oUSw~ZbJc*%-kvZCh6itv;kREp+G7f(q*sV?2(ypU3u{4-q$?zJy5q%Su2-fc9d*VX4KD1T?12BljZskIP#vg+pFl*IE6z|JxCX_6@<$E9*rR* zjMF)cr<#bWab{R&wd~VqoMJT#zES66hA!_pEq*?R%;AMBL+ix=%v2={d78DTS*2e? z+m#Vq!BcKSSFp0(RQ z)v0j=E~IOtelFeCKIot6QvWUEGwHUZ?}Pr)s(VVdQ|Y!2L7|V7H&3M7zHbxsuKe$O zDd)p=w7AOZ)Za+IY_7|1dsF!rwrsY1Z3`E^cC%K;n;Y*{$QFt}gXpoYcMp`yaZZY_vX_}rA*ZTYa#l^HqX_cPdqGsCnL0^_=ll;By-rWyuc?y5n-PzmO(|KK5;#}@r z=IrO$;5_8q>D=qw?Yt;GalUXqa~_s@xb{e+Tw`4eT#H>dT%CljVjpp{xKrFJPL#Hb z{iWgVaqf}shtfj#68ARuG4~F4N6#+zTxpMcp|sC^Ksw-_Ax)LGOBvgtN9{W2AD{nD z{tQPKM=!@<#~8nFdj_yF%+u7ea z$oaQ(xO0qiymN|khI0wOQmH} zrnEv@DXo%LOKYWd(t2rwv`N|`ZG~~!DeaQ>NC%|D(oyNSbW%DcosrH;=cMz}Md^}s zS-LLWmhMXTr2EoC>9O=&dLg}(UP)O}M^6_|S5G%j4^K}|FHav&KhHqVV9(#4VV>ch z5uTBrQJ&GBF`luW@tz5uNuJ4`DW0jGX`bnx8J>SUGd;6Bb3F4r3p@)w|IPR-x6QT~ z#(#-pG0eac$1=EP!gV=ZS12>G!m$eGWi?#az;!KL*THo?TsJ7QwZX9o=4>-ux4?BP zT(`k>J6w0bbthbR!F9J|q+<_!wb!x8u@B<*!#fAyorCbsA$aF7ymJKJISTI_gLjU@ zJ12naB>0_zpPYuDoPnR5g`b^+pPq-GU4Wlmgs6WZ>Jmg!3nDX| zj~pGHj~$(yPaK_{PaR#H&m3Ky&mG;IFJQI4bo6k(a`bd&IeIxWVC8mn_Hkx7`ogQ9 zvlFc2&dveOF3y3@uCSuJIR`ttJBK)XIETV2|J&KiISdrTK{3MF*E!PJ&p8Sdqd_qS z6k|a#4iw`-F#!}4K`{vwlR+^B6jMPl%{j+09aJ+w^$)0Kf@&71W`k;u^KZvo=P<`S z=Wxe-=Lp9F=Sasw$g~JDErv`>Ak$LFvCP4KTIt;2SOpnZL&i0baV=zA z2N~Bx#tqK7&W+A_&P~qw&dtsR&MnS`&aIGf8)V!L8FxU&ose-CWZVrI_dv$Ika3^0 zvtvKJ4meji4?^ZckohpYjzIRKko_2BKMvVXK=zZ6{S;(B4cX5?_Op=v9ArNa*)Kr$ zi;(?a$bJd3Uxw^gAp2G4e&;pk0q1qdegm@KgzUE<`)$a62eRLV?Dru1eaQX*vOk3E zk0ASF$o>SfKZWeiAp3L3{sOYUbar#Rf>#!}WVkLnJG!noJGrhpJG-tqyST19ySgq2 z-CP%i?yi4@9y9wk zbypbTx+e^E-536LJrIVu9ty)*OE{t`(5XQOII>*Cn zg6pL)(e+B0MH)@>L$)~br)y3dWf@KJ;gb$ zUgBI=Z*iWhk2v4eS6txgCoXjL7ZKkV#U=1s>KY_2a}5?VT|>m>uA$-z*Wcnw z*D!IFYq+@DH9}nD8Y!-IjS|0T?1VhKAkS{dv&S__+zWa3L7x4P=K$n62zd@cp2Lvmh-I03i6zWJZB)!S;%wFHBCGZc`iVni;(AE$a4wuT!uVXAkS6Tbn%*NhIrlek9fm1 zQ@rV#CEkL3w_UTvJFYq6UHJMQyzay60lXf<>k+&j!|MsWp2F)Hyq?4Bg=?<((lt+f z<(e;MxfX~S!UD0Quu$wIED}4ztBbH$>?$k~y9rCh?!q#$hma}u6qbv;$UH;I7HYa4iz?we+yg0VZv5%xUfweA#4{% z3OmG6!cK9tuuB{x>=wrgd&F_VUU9szPn;m^7bgk_#7V+3?_?p}-QMNG9`6cauXm-e&$~+4?_Dh%@U9UKde;hvyz7L+-u1!} z?*`$hccXC3yGc0i-7K8&ZV^s;w+g4c+l15J?ZO%F4&khKr*O`@OE~Y{EnM*K5iWZ7 z3jccd375S4h0ERp!WHj9;i~tLaLs#Ixb8h7-0&V1ZhDUix4g%N+ujqx9q&ou`X{G^ zyWZ2nJ?|OezW1!~zr5i_H_}5`MQe3 zeci+nzV7hqA&&I*6i4}biKBhJ#WB7<;#gl_akAJCUj4;!z5(KR-#~GKZ;&|AH&~qH z8zN5j4Hc*O{uZbDhKbXB!^P>o5#kKrNbw)vC~>B5v^dK*Mx5;%E6(wa6X*KIi}QRF z#QDC7;sW0!aiMRrxX3p}TRO)(l=XN<(ng} z_RSU7_~wagee=b2z6IiX-$HSNZ;`msw^-cdTOw}uEfu%;mWf+^nc_Cza&fzFg}B4F zQrziVCGPUA7I*vBhDvXb-Qp?V9`UqquXx6{Pdw|}FP`%q5YPJ#iWhu`#EZVe;=jHl z;w9fv@v`rjc*S>Iyy`n4Uh|z4ulr7kH+-kXo4zyRE#F!3w(p#H$9G=5>$@P{^Ia70 z`~DRl_%4YLeV4^YzANHm-&OI6@0$43cU^quyCFXJ-4tK=Ziz2_x5Zb!J7Sjau9!jY zi5J|Wo{2rlbFmkBA@(LO#XjVf*q3C9{YZwp zKk4WmKsvbxlFsfyq>Fnn>FORry19pv?(V-y5BD(A(>GSoep{Oz7XhPkJb;qGZ7GGGx&I-f z-N(f-?i1oz_e?U*J&TNYPZKA=YodELndF{BCcEd7Deie>s(U_}=3YRiyBCrf?nUGu z_hK^By@bqiFD0|x%g7veCYkGAPUg8+kooSFWPy7XS?FF(7P;4u#qPCaiF+Mc3a@4E z^(521fh>1#BrDvT$V&HSvdX=MtafiDYuww&TK9Ic&b@=Ickd({+`Gs|_inPuy@zae z?~L^XE)k!*CtFv^bRu^ebWLK$2E%-!GtGjd|qKDMi(Nnrz zvzK&(^p@_BKGH*9U+K`N{iMa={iP-01EkI3KzI$3Uit=0TgVXUh;yja&+)g^-!V)Y z;2SOtaEy=!Iz~!oYmJi5)fz3$jT|Ela*UM*JH|;j9pj}PWP-Fke4?}?d=k7SOG6w} zq@j+f($4T{(ys97((dpX(w^{t;5Ad4<(nn_?U*g?A#;o21h2)?aK{p9x^Jn}$G1$n;mwrx`<6>194n+@;!0_ca~1HcmKKmT(%+G5rOl3Y z(ly_DsSnv8E%j}b`q$bd4XCwQx)iZRx+`pzmXK}I(eUlkvG5)6+9|CTcS#S0-O};! zJ<^Hrz3|#69VGjuli>%XQ{e~Ubx3*+pEX}NkHG7wG)g=sjdC29R`^axqa7!uapEa> z@3b_=aYkD2Ju9tooRglB^HL9T0dyCom(G9TbxHcyaamg9yCMybyef@zT!WuomtHw< z!0VD4hv^1h2=^P2q_&+3{4G;&>)a zbvy^}7w~#1-SNJXUV5{nXWk6YrSOiP%i*2i)!8%6(Z$oz*VQxG*UfXl+1)eU(Zh2s zx~J!mqnGEZqqk>fL*a}t%9(XzK{>L_3ad`%U{$Ly(eECOms*hYjLGUHU z(Fu@$y0oU<_AxJxPJ$da{x_TLP%9P?^U;Zr<6iy8W@~@V7zYDN9om6p`Db$aX6b`JHSnWJ92_Q`3j<4T2>jEt+)x@F7u ztaLqTcpR;ss~?|EM211mnBL?mMj?__kCKcxN5D_+ck0Perc1EoYuldQvcsSs%x!2lZ#7g`%9a4t>fCHw3J_gl(ub4B-u!E>vS7w zl4c{{*-FEuk&VF9y0&fLCo#?71wV}WzLbqbSA(x=Rko3;zt~8Xw01Gy|F25>RuH9r zUAbwyrto#^{|}!ZYK-t$5i%$Lf0#M@A*J$Ul2lFqywsOvBA|bDlGBhHt@9^+9p@!1^HLHM`P!m8(yE z?+xX>LUkkmU-v?rw6s=9E!ro;!&N$o=}l8p(%UsnYF^?8TS5EM{yz@(^;wpB?){gu z9)991UFcebWe0VcDCxt`O$qzzvv%7{)q7a|`mpV}3SF_D{`<7nO75G-YM*$&w4>(4 z4>$Z~o3ZN8LVYV(MsM*$)AS#d?4NZx|I?VbWl`nkEj}=K>4fQpKDSOTZy0&dzjmZN z`XjEHH}_A?^8J1_b3FN&dm%k_RW$%)QL>=)|a5JKp@aP~UjV$vb=z z9vS#4^%upU+~ZF?^&kD-eOA>bAKb{(`>#R^zqf4Arg>8OmrC|7(?%WocT0G9$1U|b zr1hP8qfqOHmb1(FO7eC^dOqyCQ5SHo7ve*B-AZEewY>jql1ZkimZ6J0Bi-mYz0t7hr8ZuZyYdveBF`1_f4Zup`e z+O1xgu>bb)sw6t5-9S-aL?=(hmOiChQGa;fEiu2Sq+xVlw=wPK`?S zz6_+cO-V_W&rw^(2FM71^4XHIe~iCRW6Rj6{djmhs2j;sS~Di5MuR#5`Iba;$bUnw z2)T>{&dhM!^KmXhGXMx%&KeY)YrM3AXrEMUsRcdSK9Q=HTrX6cE zpug2)%h;_2#Ya@E9s{aoYSEC-_G=P$s%~_p>U9FuYgdU0X4|7lBfnGVYe&_J4n)_k z5C4%@TgD$6T*WA569ZB}8^=o6h2@&rvhS587f4TQ){5!GPpV1S@(MT&HLC^Ge=)jK z9(m?$88aZuUYLlmaAvMj(^@45;Nb6O4^w9N6A0U<%vV-pZN!77Yroc=x|QV3OBYC> zUDNMdq^JY>P^Aq!$gsfS-7Y-WS%?>Ppg!l1FhP(Xn_mpBZxbw0ImC8 zT|M=xSFIggR~c#Om)7^Oj31m@t=nR!hC_}+vR7@!E4_8wcF5y^n8S+CgRh|DFwZcJ zxB`x7{ru1(vtpPIHy2{cdnMID>tbe;+`7|AIqurR?3`&!*|!P$*EW%hd8K#xnhfwAAcFsW{kO zRqPs7QceuD(}DU?72%&QwPnyXoX_@Ea`uvgUE46aCTvd#xUNC`T|wKgu;D7lMAfVr zsM4TzB?!?bX*;tno53U{xBj`6a>UxY+euUcI%>yc4G-t5mmU@Z!0vrU|RW%;c}|SMz65MWSbVD zZ0nec-$YlE_jPqmlo$#5wZ%Z!QP4J$f73!)H1*Zwn4pTbn)czm(0dvlhL1IEt0eVg zfF~7cZGvv9@-MwB$*U%4bF1bLUL{Yopg^n^R5!X|OpWNu!GrKri<(kVi;AjQHKuNG zre|8rcJna}THw#M&~MdlSB#0N868y{eqlo4{fzGS=-QP6m11Ba)t1Nfr6!8e7DAN> z<4lZDX95;6NZ!;WkyQX2cWW?pmKHKy*R!Bmvb{qGvOHb5$!X2tgOIwEUe|uOI!;*w z*+q?@rQU+OqG~kUGquw_7~>5sOEtA~Oknm}4=c*-!n9WK`!enD{QeR)b5BXW8GLV; z%%IVKQ}qhl!<>oojVt?1)arvNkg~Uu@?-2o_SVL=m|w%6p$@-V9Rhb5Z45p%$b*R9 zqC`(3uyTU=YSq3ac1^xD^;0;${!Uwg*+pFNQZ1mNJc`iv9SDMEv!E7GS-&lU&Z@Vy zpiSzm%9{_mgHxJ;6@gji#c=-!=EvMU@cq6=$3teU+C>Nc(; zuYbJLm&PCAosiyc^Vw1i6CcF)o|gP?b(Wg8Xx6%|x{7nDKMI@5tOPFRq^l{pf{l>UHaKV41b#qkEy(g+( zHPHV|@hUKQZCcB}OQ)8Da^W*pp?eEYclEA|>!6sHKiYh`BZxx_Opn%%xCZsLgE9Do zacY4}X#rooUcClzzl*9}IZzKqAWA+k1ubZz;WR`vw;B`n1>3*&=|A9Zl|Q~rg${-- zW@fu>3Ve`FfrshZK>Q7H)8x44%*OwzX^ZyRLGZBGHeDI5pUk=#w7x&p=(pox!jdf%Y z7oK86l|>A5w@oV9X+VXbu=hoN5m zs7f`!*9P+gfAZPtsJAZMXQ=st0czSRIi(fzVFBy-G3th-1qkGRto5n3>7d~*D5VYB zJmtJlAD9G^;lZ$aywM{gpRE!-J1bYO3MD2u;O%>%t{xAXlFzm5Z&p@nh=x%$8^{G{ zJ&i6}?Rgz|+M#@S(GNk`JZ2vx!!ND2%UuQDdQ@Z+;XD5|`lWxm=wmW#Q3BDTz*EL^joQvr5r?m9+_VD}(wi7(+Yn#@zg}T(~ z5gz6=8A3!70BJ2Ch54DN_N~-U=)sSn)+yw7+1pUiK~z!Ws@PbmfAR2x?k&+a$ZovP zDW773)@>zCUR53b>QP_lcTYZB{@{I~EvO&{{1`Qh!`}_@TBUJ8sG&$6)g+TF&ciV9@DPRSRij ze)~hdYFglZ^Tia@=jvK$yvgU&ptx_;xUkdg;+Ctn_UTQV@oKjn%9?3vzW0LC*VHh| zu%FL@dS8nYY+(u7w+y7UOKAzu#DgB*>{e{YsW%b%(*exH0Bs32G3jZL4^D1^IdxEI zj7FUcZy7;rv5xlBQTj*OK^^~A3tFXqyr9Q5eKMKPR;{XbY|&5bLH2buZEa%^-Vp0) zLFM!#iy`&3kSMzI)F(DDW_aU%WWJDsdfPxtQbP|D)Z2zy(2$^FIZzGCW%{7zJ1w9% ztrXxPC!Bq)+NHFjpR)18e|@ayvmeb@hSLoG**0i;1>dgT0jyIB*5F3UiH=VfVQEa#wo^qldvxsvwcv?H z{b>1ahU+Fi8OC3|Ee9>!1dVJ59>w~eIDx_&-&6v00>n9Pb zx<$3KWxNK%nb|b5N9P_6Uysh69JU7XwPuw3Lw|Clt$wch_D`XWDO9z-tv>uMepXfp z&i@1FA0kOAHGdwlsz>L}`E42bWcME;!K?wiGE)s4z;q|SElRoin^PQUt>Lr*oK}?O zwMby;qU?9pW;j6|1#@<_n7CJ>Br$OLfp|40d-wMNiBvWhwnc{KZv!Jaky ziJC!c&Foj`ZU@@kypgLq<;iW!aLT>y0OLJMo_FX!%zGb4%^J#l|7O+kFL3;WI#vpH z{Db3|Vb!r4IChC7ov5i(9#(mUiE=-?;0o(x@Ml(7cRJ+IS{w3yfYT?E^rASDhU1ZO z`T)e8{9xQq8TNjT%w9QT^`}_STEiL!SVJSpV2brcq!+SPQ3ptUwcTYzm-B-s#2)={=x+EkU5 z;WinNHX!ag101uEwo*oDtugKe#@&%*Ck6Bd@2uShzMTdtb;$Nn9B8fK90i=ik>nu7 z2@l3OY`{6l!8t~8ptXi`8gNchmfFF$r;`R}bv>W4>UaSh&r!#3Y44TN>l`?mm0lNV zU!k?u*DK(Bi8|Mi*Qs3Vd?l~bO9pFLi`li#RZ0M@HG+FUa3_-7iX=BEM`4YllFV_3 zJysSwGH<~a=9p9{VypNv>{;)*DCh{{wm}xze(l(mcK{mU2+AdtK19v)yf@OYtHY1^Sgdh zh?=vN`@4RvaxY}y0H%#f-3(X%`xFOSYdA##rwCEd_au3H9R>I)Vtgz4NkV9*2$o+s5;U{G%4qLfL0K`Ul*s*dilQULXiUqAT ztV)0tl_?Ii)^KV7PIW)2N^zLVy}ALXDhH<~#evou&bNRQ zLs{6$J;q?oEStKN09tDV-vL1bO2Ag`4RR)EL_Ryv7RG135|nV+QiNfIStD)(l%p;Lf>-AhRZCUw>Rj}8&E)`ln@*naer)_&5G zvayx>j|QaHh}+Tt$1J3Flo48MjK2fpuYS^j0y35RuLiyj1}b&P{-8L}TEpoAIGy|? zgW@oidnW@<1_!4r#evouPA|aeL0Oo}y@$bBUC+I(I`#+0zSNPa-1~x~S?M)^_7z%d zeH{YMgQzoGxeqc}!&=NPKZa5QXsr>91%lCjGSW|mQx3LrAI%;sP`QtUclOB#4OZ^M zb7mb!S)sMYIvrT2`pIMp%2w`E^~GW4WW#y^=-o=?4p;vSiUn;*SmU(HeI;Nmr%cQ< z_vHX^P%b5OmHR5{46QZi4dA@aPu5U#wsK#G=h_-0hw|jqzmbAKYYk)@fNY@@Y|Xv} zrsbHtT7ql#<4VmASO0cO0IfBG-Q1cz+iVXtgVvha0qE{N+Fhn*-v=XoT%K`V&3@3T z<56%tOdXk;{V>Pzm{rF!;CRYUPEb>}Wx97{{vHLM%KOjK!G_k_U|$B1fBobF z1!1f8f5E;p^PK$x59kU7g4P<)9RRxJCpRb%Q>WiD@Z2!+D1Y&Gm*PNc4d)5qJo1wV z6o;wP9~p2SaB!Yd9B8fKyaJpTl!dL+Ul^^`rIJOxp|$26R<;VsRaSk5!dB?H%IY^J zU8b*#! zQU<0ff43|?$N>U&&lEH;sU_z7ba0@xHaHGo`?xGAT9y={Y;0Bju>q+l;ubN&smsPm z>7cbn_bJeM$`Ut4W9o5_fy`~>Q8sjOiUX}RoRWa^Sy@6T4pWbRX22mFoKh4AT5C98 z0?rqdg{jBCFgU9#Il`)AIdJq-N2VV4gQHnN^%d1y+F%WL`Rvl7 zA|-&<8bJ*ps9u&-ElZ*)2V0L<*NzgX#H+&BC*@-Wo}NeN%vY20L2He#0r1r;OTMLW zYzQEL!mZ=)C8|RM4>j!joKKfjVj4Tkf7+ZNAYzuLeeG! zGnNJz(fI&R0mP(|Yyv@u9(xj`MZYjX1v8ak5S_!!0nDtDY$m}7{(6?gGE-(T9>;SD z1<^UmVxTN6$>tM^;H?)*DDxF4O9%zgIm$|)EGG`pS1*@k%_C+N=^{GUT@T&0q$_&r zwJO~Wq>JcWcRO^qmSmerTJY0bakw2NKfPI^FkQ$FH{u5%o?VjdEy;G1zTl;^`L^5( zb#ZU(mUv7reUJtP(fOd90@sO>>{v;5gt$Z>eL})H#!-*RVCFJ8O=O79$^HS^g_7(X zVF@1kf<$#rW--4gCX^gEC^vv|tt7ibD1v{!CZSwWpxh)BMCYS&7bv%hL-5YGB~^3P z-gBdN-+L99=RNbwU%@wf-m^DC_rGU;@r&sE9v^~geo_@ZbACw{o;lYVJWT3{&eb1> zdZG7N!S`4JVi5guq4(&hfL|_%|9_19a)HQfg^3N(Ioq>fEBYRLiois#Tof>ZLCbmy zNTQj6S3YcbWn4qg5fbA6igX%Yxy9`$`Wf--r7EzirEGrE6{MOR;}RT=dMhONHN{_*dew$3NE@p>CDy_ZCv#Kxm7F-#m7id zaMF({6pOf3EDFV^O0y?ORCLo%l@714CnSAgg*`(&7LP5(N{+U;B%D_i zIByaTqC1=tzd-?rCGJo>`P)3y?By@RE^_)DZvQ~DTNpj-7#i>v1V!Z6#)vayr#tWl|*F@SuMgr zbcgdTaO#z2-w=-A%=ib$74zoH->jlsk4Cjt(s0U#o{;ybF%D}m= z3_JI8Wh$^UW!T9wre_^l20!b613$X{yZ)o=XUb%@Y3+sZE#s%7Z$)RF#4GLeSN=6# z`PcYO$4syOn~u1K&X+M=ETTKC%fQMZrZHvAUq0-vBjuFQm9U%uiC;dv5&q@FD{dA4 zh2o7e>>7zq)CWTURlr`l>J6y&_Cl|9fvjs10cd&~Lx5}O77YQSyCKL|wgQVP%kC1; zv@lRV9Y`PW7CI1q4e)Mcp!>?2bAsp&=n()tRF>s0Yc7>p0?{9?4J8 z<=?|EFHP1T3}f~6hHF*{1;+ahF*b)ES(SiMu`I(McQgJbf%wR(2#yY+OJh*xIm zujGAX%`whvTtlDH&QU02?)_0(02f;UzXJ+ zAn}n^KMzpd$UqGU2+d}XoN@B_Y#2l$ZA5$i0+h|Lis0B79LqYiOT%c`h}Dc z-6{V8<>qDCuOu!!vYJCY{K)zh|9`Q*Pb`nD7H$FB0iaD;)`|dxM^>9W0Id`N?cD-& z0YIm+tOEfEkE~9406HiDy1E7E34rdTE z{rDrRkBGq^Sp(h54~P8FvTQKP3y-X!crYx}9}N7FHCTZ$;(y0@L;wEBrtl+cDKHk7 zW%CI`d}J*K#~Pi3KeFcImG$~7c^_FDjq@7U&@!4F#Q$}2M65NyT18C4BWo1~Vxztl zEsw0VZWT8}absDwoVp(>c#Dz!JMTmzVS?BTp_vrh?^2oa67T^W| zu9an12tasbUCRS-MFDWrExx|0XsmI5Fu&gB%`ABXRx;=eSZ|JgC& zk(Dn_IGgz7KM+UXL3OMAA1FT@#~vhc;gR)lT==W32Sp72$SUAgzA)q;i(>^zUU+0Z z7Kfku*B=c0kyTKEQRIKe7#vs0)71F!*NH$FPx``-zmA96L4Cbje*J6`jXmQ3y76*V zXFzpY9GgPI;P^|q&@>Z^8CSw zQ-(UOp)68IbgsTIPW3JPT%koIgy>vo8E$h4-KOyE`z09TQ~Eqxe(7wv8@1I?TS;od zx9(Re)YiCB+XS@@acmt4ir=>1z*o~cNn2P=n`xL4oe%RapzMfa+XzMcmi-O@9M*@r ztMP_5-p}0@8EH2mAv#Ao1f&CTESr#oZ`U7?h_WRj^GSc0P!OG?oC3;;IChLsgm2ZK zkWh{(P)-vHqH~nk-*CitJ?d98U5FRL3f!$Y*dCIYSL?L`@{=RbIM}ViCbn_(myhiGX&ecOu zf43ZayBvFy7{qVCzgtc?Ht_BDxADpa{UG7ret$DEXG!8jbk12GoN?t?8G;nQ^&ST# z!O&%uk=6%*PwEy=zlP!o3DF5si>2W=h3WvS7BLAfyA}X)bW31y+24>dqC4dVQ2w?Y zt4HFZ)Bcv9UG*dmFkLphF0P@5goEe~rwMQx6N~7!8)I_r=<6k~+rDcM;2Qdo2oT*7 z{8CQkxO2stkr<*ovEOmKztQaquKPEP_g#J7Ew1|yw~DQy*pd_l=iO4F*v745M<`~N zW9>*(bl;hLg|(CPg%#F`h8)q|koN>m_j0T&;fM~rJ0LFW!_FOe*T`7C2n*32)*xUF zD98E{mf*q%NL2kKD)YfTm~ar?;fw^%@N#S@;RsHAxP&uQfisG55Z&R72hLbx5#9J$ zNm^Jo6NmuO9l=x(OeO-+kx!0HFpUTh-4VjaXGfI9Gg!hf-_&tH}pafhB-w(pEocxNH9>GV66>MRdm+RlWkd zTaMi(P|>;HwVK1M+tPXg^c};w;~MgmH{T3Ebc8j_L%;6k1=b7Y&9?#s=l()@`~(SiJ`6VdFlxG@=i_Sf!eE1C#P2vDkN1y&vqqv5O5e}j|oZ`R<5{u~EgXJ^Z z^wQT%UgzH1Aiy>B3K1Z>BY2~{%DLx?y-8w-?!?~3?Y>R7D>(PJG2XrPdAB(C5^fbs zL9rw$3eLTxLb0@4#qv;$E6>W1sOa3|_zEi{=?g0i|LG*-zX^lrZpc3Y&PV0h2ZSR! z_m2S4Q6F~h+&_qnRgtg|-C=zRtjgut=Y%CV_sSC0=Mt6qK(9(Ti0*Jwfs<4oBn3_y;UK!hNe9l?#3DNPuO(?=*<=s_qC0}RAgDtGqI0hknV=pKAi5*?9s~`` zv+oE(aPAFpIQG*INB(~LcM_H9bQ-(G_!StxlxIJeXFn2&;M{-V8~SGuh8IAI~RBSu7bj9tOlxjgGgfP!=HEb(=e zsLUbjMmUJ>aQXtLcX`&6a0KVxTf*t7!0AUgi0*I(17{$y2+n<=q-?I|A#N3iLvbi6 z3eJ5f6z#0n2)b89clSC5%A-hGbnc@hX{^Ou`!SXX5Zw_>1HqK?Y*KkPfjC6xK1DoM z;M^zSl|lMJ!=3wt$gI_fH{>^f zbFDnPLO7yxzXph*`ml57ekC&2O~OKShvkW{!0wf2cL+;x?)N0BI}(-oK+hL%etm=J z4(DOuJQ&X&h&SI&5S;si@zz0l0I!Iv)x>#(a1h<${2y>0B^J@SKPpKJ%cc+!Ai5*? zF9-?~f#}=|M<#fJ2oT*7JO_ej;@Q&#AvpJE;xpTf*AGYT+@F@HOsDg_TZ|Wh5r}90 zc;+P%!MO+G+tGjj)(--4FL@;$9wh*u`-2Mu@bRU@;e5-XxR*4kjrh-WnkRCMkc zz!J=1R!wQW0D83H+;I)nAuL2kSXp7`{tK{vCMLnT{|ta>x|Ogv_hzJw=uWu>lz)$B zzmd4;+<)ii+HVpEn5G-P8P`xt!a;P0(+)Uoh(&bnZ7?}=^fi;$xz9BSa1FI50z`KN zo#IvRx#x;?CNV^JV%>4OUFmiO=iU|LJy)N1i*xVcRlC7kIBoY{nf=niK-aI%O+bnaP_ zw6JUz5CNh)f~6o>Oa!8HUmTfW84)15BUlT9)$wd4K?u%$H4ex5`r*i(`$~z*bUN$Y zVr&P-)_Ar#o^2!&!MShc8+tPc#J#jpVlr3l4jLjvcSCdlY}xT_Z#>&gY@&0|mXP*x z+}#qKu#gTCBceOTlVCg^&yEtH;M|W(d`BfJbI48+4x&4p3&1%S&(08z;M~tiIA;_% z7YPT^9nKZtTp||1xnGi$&GmfMt>R56UMEGtxnGB(o%Q;c?iJD9z21fLZBiDU`)x@Y zYcbb;+#>=+cLWbrz@MV7!0yK{qmt)P9|vn8{7EbV6`gw_UrOP`9e`qpWt?L#l9dhM0a9Ual2JW zPjK#4Fy2S>dAB(CYHk&ip_oL9f^$z&D5khotO>=hDzG#X6`lK6e1)Y+`oaoJry)ml zH{|tz^GyX-n{Y(u{tX~j=)=yPd+o?r^$82n9o7%P`o02dNLYe%|6ZbMC{dXY^d^LZ z=nm&s;QWGj69`9e?!QPlKPzy4BOF9`I4yzm2eF9G{SQf6ST?PQ0MQ*mdl0lG0@1m* zjZBb91c>ekx`Chz{zwu*2+q9=4#(sA;mDnPCyB~*I^Er33;;&I3ak&_03Z^!|}rp_%BHjo9Nt!OGraG?hpx1SV*IY5z!svBrr~> zz{U}v;M^xjeB&f4bI2wW4x&4pzko9Xe^i2S1m`|O!kMPPnMF8=?r`P-XD+b_&V8<= zY_8||ZWR|paUm%R&V3;i?X1@lx>rPZ_qqbg%Sc&t?#m=;ti@dWv62W7-4Sd8!G;QK zT?Mv=I7H{ZK|EIA+}Gii)A~Wfo%@=|tec4y(H-j^uk?BdI9ud z!@1)c+Dll7j?}ceuB-MAcHFG9T#e2nW#}P8Z;GN?;ubM{w?)B%BTkoUVj}=nkhBaC#7n=-hiq z(!#RoO$3PU2nK+l9}$SoyW3qD?n5Lh)9H+G zi!l)x;}h7}1U8yT1m`}UZ|Jcg5ckq(iOF2GlW2$#-3`$!u+2RQ zSc|##V>b~Xx+6FYf`bWce*)V_9HMhSC>|?t?)&k|P5q$Z&V65G)+5A<=#KRaSWhRg zlLRU{_tRE$m~~QGFM!T5oI9?evxJ5CzhX74TFLXF@z)zasD>Zys%GQbD^$yDeOtE? z7T5k^HPf{tI#;a()r!^F$0RH|_KMZQj{Rea0X%mNzl>|>GeSXhj`Af?Dieq3)+<-b zY}3YXaqDgU`tQZ!8mda_h|blkS5rClT%lwVLUb-v1GkwpQn6>7EIsMUvB-D<2335xE#E?-S`ByC|eeM`fP=zN%e0Lu5(SVKY)o%#0w zxGOmGhLMq)5E7zuq~CzltQu=dNP;VGCJ{B2h|Gs|b3#FMj?xAwt*WsWgd#ZdRuW1J z1xi~&L3EDN5h$6&A-eHQNmf`Uok$(gxq5e~cO`YviFb{x-hjFzDlZy&Q)(g^=378orFb)eUqPA*Cht<^e{XwuA$q6g6JH@lZaoU zBM#AF-@}CT)7MDe_rv=e>bQpTCDQNBCAv`0pQv)!xk3+;5Tf(j{10yP;Y9N*DZybs zoS50Vzdp~F_rVLeQ7Z(sf}|!m?1Bol$K0qr3AO(wvce=NI_&=@hQD4bENKg?=_wj! zMCZf&0#KeyWX}+a=&+vyKo5PW`Fr2bL`I4xBt+*(F99hgk!ge^IP4gSNRx=nhjKAO zL3EDtDo~0ivLK-d4!gL75>%kPMkt8RQQij1o5UeH>^CJ@VVS%`>WI$O--CLH)J2CK zimYCW)DfMlmxp>>A}d1xg2RqW#GhHv4?XU%%Sc3~ONn=b@F@^JNn{@-vJZ$taM+*l zP5Tkl#Xa+Z#AB||N;EWx&W9!uTvZcUl|=RhafuGQs)SR8qkbWQ2@5BQ_z<1*eGR@E zi7b`i1czNiVoQ~X%%Q4DD2UEc>H?)sBCACxg2S#Oq0~~K)FTu`=O_(<@*Qyq4*NSv z)m*!c+^98yT4PcZ9Cl-<*;%F^=^hcC-{UV({h3rnhyAl8i*=W4ADWRmqI31uP;Z&Y z{zzoai9vMOEyZI44*L(hGE_fExWjH9nX?UXB0A^n0?tl}tOG%c4!aYO1VfkAL0TUG z?q@h`Tti(63DF5sWy4{Q1k!Ng5ghh#h>y_ifW={tB2`4^suQ3(E|HBPVbNia<7d_w zi2*#L43CRzXd;IU1X%qgoNlEX*ZB|CbI2>BslDy647>v z$b2a8ArwUCD2IS@AdzJgir}yhNGRC~l*5FA=p5w)P>vCY=&+ATvcfVsN$QBs)z3ox zZ&DW>_TQ1!&yhN!bM?zm&q-t#2|#ezIXLvD=!YJ6*cT-t)1_Q-gK!53w-VXSM0TAh z1c!Z#Z`zws7x&C{iN{=_cWG!4oe#}}Nfp=wN$kEP=1DT&ju0L814&k#`;x+6!F%v; z;z=qjoQIOkcVrNq^A!SL!6a6I-~@+VP+}_}5t&2v7@;6KM|lb;Pb9G-gd#ZXCnS_2 z3Y4b_1<^Um^FVo)I0T3NtfXqL-51=b`Jv_|HNjzfp=M{9G`dGb=lA#$RAWe0bl5SH zEY@AFeJDoih|bkthx)5YtauU&5`*ZlUriE@4LI!Lcx8rukZ^|`jLi84aUweBd=H$V zB=#;riViyjB*D;Sy(_H`08cO+Hm;#kgoNk>shZ)iKL=7J;t?EnC5X?`?SRE$e?h8< z&Q%kkS~ZDPAz{&BSLJ6`6^Q{na}1A*Ybc3O5S^o>0VRbvM2DS%30bJGk-QFjk)e)j zs0OJcI#*8*|DK}s^W3>Y86<@0T<9CzW^KAn!C}|N7%$T2+2XM4x>5TMYV}D?aM<+~ zY7N||HGx{=B-V%oMTgy(uck(lwy>Ihq+v#MKFq%XrCAbdN+_bkZU%rk`cQL+-83>% zb3#INj?@-Nt&>6FAe5Q^ZiJ4q-V6ewK@1<^T5 zFQD`w4$)!vkYt5r(wo!~ovROkdOuPZ9d^IS>H|p~(Yg9?s1HqILkK`{*h6vXE!7V_ z?y!eQM5ap_;RazM5XL95u}N$+Q3wuuJm0iqp)T&3(GrijLMPGCAUYqKS>T$P#HJ^) zsl+8Z?3ohIbdEYz0uvU_Y~n+7&bJ7B3zFD8f)gC}0*P&&L}U)tVnRW5jV3boCoCOGWPP_wg4+vpwiEwYSGV~&?E9)` zwqB##0gJ=VU)}st9MQRI0jNGwojpXtqQicqdiY&|ha?8@tTQ|=uAxT>1<^Um<3K4y z9HPT6R6VoJ7JZH6b=X@CbzDP*NgdI-`jgdFKP8eY^b`ppIv08tw^@{KQ*hWtF~(c< zdA2z0=iI1yq4ol)2@d-Og__Te+DlN2sm?SK6diU9Urm~%Ev%+uG|Y(3hxt{Y6tB*L zgd#fZ;s98u4>fn#!N^Fj5fY+vq!K`Sr#gF!kOYVQjzsj9L}WgcLxh6p9HlH!-mlI| z5sKij-yJ|J~O=js)q{xPYG4*TQC>YtK2qI2~x zpdtgXnx{>Vm6Ibyll7OD8VTVb_sxYH`$b2~1cx^@tDAIbUP&HLA`U5S-w!8%b;p zBqDRDejpS?=P1p9(zH7JiBJTG-Bd#PNrCb!p&&X(X#teqi9>MMze}p-+HL7Ztu54A zlbYbLTSLvxGPR?7M09?S9if^@s-nZrlw`5)a_vJWQb%;I-W%#YtF!LaSyy5Z9d=Lg z*nq?Cj#u{R2MKrBT_bb$Ax=c+oPUCIaCJ72AVr5g*lOsq21@G#z*`K5jcaHqAt5?J zYG63*1wfidJi>d}^B|tB+X0KiUP!8l&Q+H~b!m0Bn1n@#y_BC>izNo|956gCuAvo# zg6JG&El^eyhv=|ZV?xgAYb3A3K4+-o8d^u{h|bkFDIIpM&}I@sbS|_Vx4D&WQ*hW@ zF~;ZgdA2z09d6Y2Ky4SP2@ZRgLT#@bwL?%lP@QFypy;p<@YR$pX$!0AFby-J^I<*( zloQq2F+vd?_6YzS(1)5k>|>FUP7@NMbEJQObfG#sM@WLhz912ulZecRat@&&I!Czy zlxx-56+#gl_B9FRiUQ>(p&&X(xeJur#34HD+mfuXOzx37qI328lkvxJlg;-vM2DR( z*}5GC^#_v8_csuos~3R!BgyO`0uUVbBgvUCM=dIW2~+1K zK1Any#lZJsG7Au#;ILnm*a8xfIaDtb3ZiqA*MRa$GGl}yIP6y>6sACVolp>+qr3x@ zw}?Y<*l$Uy=GuMNjoN!q3z3@OutQL@vrMJv9ub}2V_B%aPpYEBeqWNsy34f>aiosu zT>WFHf0)b?l36@4hz|Qh@z{XFPQWXd^@D^v?D)u>pAaXabIvcpSvi?~PLQI*t_&o> z&}Drttq%a7H5@jsp{j(0=me?7!6^DGfZqVCHZch>6XCavg?vEqC4e=Q2s8N z)hBV$X@AGhuKE%Om~I$e7uQfD!a;P0^CNJ6AQsVW|A5K4tFM>5Zu_1=fNSU{B0zLU z&@5T?o_4O-uOx=(PV5idZgaX_!F4ysc;D0K-Qv1ixK(Te#a5&!IPX>p#kOu0J3+BS zGHXwwqWkW^S6F*VUsz$CX~+@X4S6r%^hjpi2uF0_Jpge-A9n7*yG6$8O<0KTum%Hb zU^44ZSb_^5C{gv7sLTiV5W+!phcgN|Ba+!L!V#SK2nlDH0%tVgAiBeu0Gx5eBD(Q$ zlC-dFCK3UnJA!E-m_h`iBcBqPU^)>Xx+9nig4xOJFM<$U`D`4Ht+c$Z{4a^hbT(OT zF_r;iNitiM%oY%d;LMls4ZR2i;$B)HF`27&ISmn_yCK>DwspyDO)^_WY@$0~Cn2rj zxT_>MVIgfKMnrdvJHfa;nQbLN!J%)L__j(^=8)|o97K0G2Y{2E%=QwF;L@`toV^O1 zgM@?V4(Awfju4CB)Q?EY=6XKvR`E0xPm-eG)=xsw&U*b#_loH5Ue81MEGdhQ{j4O7 zwU}!^E)W5tJA&&VxSGr^C$k*l5MBFK@mPUtzl>Mf=?4vW?KzQIZxAb@J62B${vJj$ zyF;L&bH8Ubhgo-|^#bU-hI7X?lrM$;NJfe?tfOJ){sgd!q}cofN|BVz)*UcXR_FdC zDI+=>5U%_jl%GjqPm{Rl+@DDazd`b}!~v#Gn*R6ra1A|AIEe0W{J`-Ni|E|FDKPE& zn#t?jdm03|hBP8TbVu+~ipsg?iWMU(O9jCW6c-Yw3(xLd{7q4+8( z3eNpih2k4-6-z+zofP&KiHgqs9lpZelJtcY7NQ|XbT{N>f%AR}D@8b>bAKNYo%CVn z&b?G*tT@6#bcgj3us%p(6$ndk?jJ~06(lP2f&MY!AiBf(0yv+guulm`aPFT;IG-wT zDiaQ(JDfz|R3#SCxmT5>g=LdO1c>ek(m;?x1fp|KiA+#~2oT*7)CNID3ad#Ff^*Nn z;n+t%9Qpg{H6<$3>C|zH(Fhm~QrNdCtR9gF&b3j2cq1?S#U;`>9QGKZ`U;UK!h z=>(h(DXcx=2+qBOgwtMu)0uD(-Qn~APB&r^oO?G(*<8;(-75BlVsBCuoO^F5+F7rD zbgzi+?sX892avMp+y_X~Sc|##V=xgQx+543f{`g~cnTXz9HMg{DIP0u?!)oQ0R5oh z&V6WP)-lA2=#F(NSSP2ji3BP-_sLdsm^D#aFS>Qq?V^4SO(QHsM_9MR&V2{4wh@!? zp8GZc4A!lLSiJIUCA*Q`l}27oGcFey;77IKcF$;hS*{?I#>WcQ{9YbBI_( z=Y9y2GeKW7d7b-2g8 zt>QmWyg-VAbHAWa%yFxD9g0^|*kuwGo%>b3!Y)ht!V0@VLyqWf$nOE?P71q4IHGgE z1BgHMVdu{MR%EQGRP$?hM0Z#ZrQ$z4oXYM`HNSipoO}LME7kpYMO+@{1N~vbL3D>x z2si~(SpmWkoO?kDr+@1!k!m@di2oT*7JPU%NL?Al%qLB%n zBLYNs1R4l@sVtfx1n2Hc#UDP<4@d6Yqa`ZS=>*(j6bD8ymA#zGULq2~xd&6jZ}z+l z0&y?BBr%z*_7xf;M0Z2DX-2oT*7q=Vq=R8}LE zr4one+`kr&6*%`Acx8ru&~WFT8kseNSP|W^eh1e2sjM!6iq5@0ump3MRaaUsfSzDD zcU(ga2n+Fl#p;q;$y37kdGz5x8cIBZYaa^nS-Op|xb_jGis)Q*98|}ovQZ=~I`%RA zJR2o3fM<^3mvIe^Clo~IC{utki8w^JJ_!@DP+uo`-TER!9oNuQQb%;IJ~LJI9(%6P zUnGR+Txc$Cb2iMfj2G$iY;oyXZqyb+Z9b_94t>5tZIK(b6;NB2%9fCz=+2k% z)wD#?7FN?r8fHZ2!@L0~>r&YoLJ^($IsnYkhnhR{HIb1v5)z_wq@6(8p31folHkg> zOGH~GBJ*Lri%<}qqZ|NAb}HLTD1sx;mQeO8P!19bqH~mEKsiDjq8mRV$qLKlIH@B# zSN|L8r$}9N;-@03pCNTb=ju67znIF-6M*2tFXGT!svmmXg`by*OxJSB4Zq~Q-Bq%lt#yGLB2`@S#DisMNOf3a{+ z0uvTa{xtei3283)3WBdd8ha$o{1RJm-UTGKNAQYxwwpuse}sbQe5jrPN|7}7IH3rx zyNHDHxB}%#LP2zn@+?q_5{KZpi%P2I+I`NAnipy>kecAOUx1pOW%AKIB09gv7^rHb zDmraVlEu2qwGS_nI-+y+SD{`!jRn)#%fukM?BZ#{u>qGI#49WHgM_>6mm_n&Mx2Pw zIYZ!lH;uhbkfOtW7f6Dk%X(W{9{^rxIBZ-)B?$@92~x;#*cE~FG4Tiv`(uc&(d~f6 zVSh@hh|X23K=q3>_8AF_4*Ls!W_>0xfM=cIad8cONhpZUQK|zakvK$$ornq9qOXy> z4tuMij%z5H)DfMl*GN-2>|CL*NC?rnPzG+ZCf%msuxnzBx9an3aoDxosMUp99a0k< zb{&OUJvVBNpw=LbeM^F(!*0M=)3=hgu$sQ7VMcU5%uRvvQyObRD5Asu2>|Q#q2>;| zNo1s72no?SQcEEHk;a-6lHjoakcgT~MCL=e6`>$HN9h2R_Gzpwp$HDUy@b+Mfzpvs z5S^oR14 z*yJ=ek+?*MJypV)%uy#wV8X(gL41hL`R0LdZW^0SaDv00E3wU%h|HmyPbi4aQI-K^ zNg7*3D1yUYBB3l&pe!d8MCT}LfU=4>1c$v!QZ?7^S~qGNp|+mX1c$vIYIc@s6Wt@C z^LyL|)h(ndI_xcyEY@AFeb`Rwh|bmbLw#Qw+mpt25rgQk_ld^_9QGc(vPVBixWnER znezZ~B0A?h3C`nb>?lEs4*R&(&}AK!)(3#M7!DiP&?!Pfbb?gUaM(A2be(tvhkYI5 z*}5IDIP8B(716nBRE-MkZW_By!lJ{z%g?Oa5(9V+7#9)szlQmi zfatLAuaVj2n7&5xI_%?yIsA&S&(j1aM%TFWVSx8 z&$Gp0Kjud5zfdboYJ$TqtWbNxjoPzND_Vm+MS`NkE?Oh}9@A5jwy>I>qhUsLKFk_W zd^K1!p@_mP;-YJ9T_P=NQlmn7?5IXuwsNHIP6%7sF*}#K9q|S3ZiqAw}A3S z4fYzL2oC!V3FS2f%G-p3=p3aaP)ZPo=&(yjvcfWXkJJ&JtCxlP`=l;9?Dr$9$B{as zbM+6Qo=}6u6M*2b6L9FA(hoiEu;V2n)1`dm2B9(#KCi(l)nFBgLU7oh^G#a`>f)ZM zDDjvpvUAW z>~`X@0f*fNubkBn67H~DMds{4oQTdjdxEoj4c3()MTgzpYUr}MO6vo_#|(#!Yp53? zA^xvOGiz4zylOb?Ej25!O*L(PD|1uL%+?olJ796xTWgxO7SXxtZm908$+nZQ=&*Oz z411#O5(9YtF+47=p*@6x=p5w$P_l_bblBN7@q4iP8p-Rh?-}a2h7OWCqI315HB}Bf zSLhfCAvza2h1)zqw<$R66By%r`aD}4_Gve2=b(0m)C7lpMxl1zjoM|X<^h-{4*Mnm{?Uh;JM8O`k!}+bqI0DC)A1Mb(pglx z&ChPs;=p3a0P##HV4-tysupg079#Wt@N+^iVQ62|MA>t4n zb|FbtSSE!@9nrb^Q&4|`)J2E=L}c}+NgdI-dNkCZPiM~(fZ(v7PsiU!3FLLy&q_q5 zOYyovco_&UrL&lHrV)kUuwP0KKLTQ)F76pk;xSifEDa5!^PzbYT(76ISJPQ>;u0P9 z>k`hZ9JROvCM=w{h!4>@Un%gFOlKtsPH@;ICAJb0kvUYQ2?fzPN<2`?rL(exA~@`F z5=vPGN(DkebdK^dP(CCM!C`+WshVr|6E|v~LG4pg6CC!ZP_wg4pVK`eI={y+p<0<# zMTcEklEu2qwGUNE9nraZ4XCH4v*dJ^L=2+CP8E+0IP7G+(oR1}xWi70%=r~@B0A@+ z3(h*}tQJ9v4!aJJ1VfiqOIjZQzH2yaTtoE;3DF6X`BNgTfz*YQT`?iO^)-^$ zVfQiAaSin#bwuatebQA9J6EVL2_ZTc8i?EMPq!&J?EV1+a_hz@%a06OVI%^miH z$VgKO3DG&y93ag~XEO;&cn^D)L^M+(G9Suw2?fzP%3`1_OlR{6MR3>)C6xIJlqH0M z=p1DwP?i&i=&+YdvcfW1Me2yo)z?FPEvbtRdu?R(4Wy3fTzxy#x2Chr1RyxxUkH4|}sjWV)0cZV(OtAv>MzO=r7_LU7pGeADiQy0~X{OFZTZJxD`?=zM5Sf$Ky% zJC@Fl5SQq%Pe?e&IO-7zOjtOli4V~^-#_5Hkj~B#oZzr8NNndMB6Fy62nEqO$_=1g zOJ`RIMR3^HB$O)(l$(Tt=p5xPP;L{4;IMB?s^;3g=SJIBZXby=A&T z!+duF(fK_-1l9bcDmv`^k}TF;u6=lz)DfMlKMwUm8LVIiD?kjQ!!DE|92;=h1@X#Y z{UG5EyFg^l!o-Q_oby?57R_K!5v1s_ivme7bXiXUNi;tI?yXxq{Th0XkPw|9wdfK4 z8zr@Yl|f8`%gzA6P~8$(-p8&(%82fizk_o93|5!KMWm{$-o@)@`8froWi0%lQW~dx@uGlXmhUiYLId1n? zx?RC_|BCURtIxZ|b^q>Gu@w|skfPwcTPPG;yH)G}#r7GjEs2WmyFFiFZ6$qSg>|GM zM|3yjJ%H0KgLNSs(SdgZ#BhDsxdZPK8LKB@A-cmF2(11YtS?~+F1)`))mNf2AKZfo z2hknQ2;dCMV1E*h;KYYXIDaZ|MiLI9JDhRA8AB|h8y_P{3(ICa5g@uFm;!=HL?Aly zNs$Sr5&@z+g4rPWD}&7-2*H*Ag~M^aemHVhK0~51oy{D#7)yY$D1$A?VDpGXaOR8n zhF$;yaWBo2n9NnXl!ge=-4Lw<+nNlvDub;cHqo80k&sq#+!Yd>u#nahBceOT?O@!R z!8Q}1;Lx{9e48aIbI5iO4x&4pY~bw8V7m!NaOry`oZSkX{e*+)4(AAP4iSss)DKC@ z=6XKrR`DbhkCUR{){jHc&U&4qdqs42uVjw>Y?H41nUL#gScdYlodMAV3B2dw}-?5s*tXtB00rVWh zx#Jp&s%3u3h4{Z>Wj|TTQ?HVzZsjP%%26>B8=Ho)lBe+-?aDUsm>YC*WBl_ERq|Ew z6x09j;|W!wsw&}5tZKXyGCC(t`(Jef4F*;npRRUSg6IhgxZDaU#9 zBbF4t*Z$@yCsiqzdCET#X6=H$=^FiFnb8DeM$f5Q-{GzQRqa`i=Z2-4@61A>@KN$; zNIXg^hBxn%Jf%oTI!Yc_RXxY6iiT{Cl260keUxV$B`@L=b3Qan-%8>9AWtc#N_m4z zzY1XCC@HS0DamWz4Oxzo^2YeTt*R`~E6dtfzOSnMgjarOUzwn){DN0jQl%vFlrL2& zUm?XD?bMLnQSzB_dR(E7ye?|l-%+}%Srgvud;7|Uvc`9+X3crCX7Xg^ZY?kGt%7T!au@+Y}Mk&^NwrljRSHb=3Ls+pHJd)~hC zSy`i~s@coD*^Bng0;5gQutnr<0893_MBi8&wrEq%WZ=MUp4LsThax%4Oi3$A2@s%9#$nPk6)Ca5as^2%BE zl`~b9OL*l%`^x#M%2m8_xhiD?Pg$!<*?|-~xNR3@O=Ib7R+S&*3fc0y*lT}ByH(9j z^JXXPE04(29VO|;j22L}evY>;s+U`j5`E8lJWpAw`OdsiDtvoaONqBv zJG^=C@s!)8q^Hlns;UP{ha2ZBZG+Vy-2D;CGmet~!zbo^6eumyGz{k#;VF-)Ql8<` zPnEVDB~Peo{JbW*wB>pFjWL4Ht15%MvY374i>k^udF5;Nm9MBOL%i}GRZ1D2Qc9Kb z0aDD-jxTMuC>t9$UQSj11y`tqVYa-7R?+^BK2|kL;mwllE33&GU#gnb;>~K>H~UIe z`5mvUXJ7e^s`3X^nuFO$mC}?q|Iw1d_gZtF(oB`oo~N{lFl(*!O(%VU^OG^7EmW<0 z@YY>bd)DLWY^mlu^L&}`jz3c-D!q1tJny=-Hgr#xiTXx(xgB0M_Wc!RmyWnF$bh**{Fs;Hpz3p=5h3trE+9=oHSnPwXb|ZRT;}GU$U=^QB}UmZ-`k^ z`1HNQo4<+S{5GmxK6=01=kdI*Dtez6y@#TPUw`{;o;5Yun7)vchPqo)`1B3r z&HG_E#nsqHRWyPZ4MmY{*&SEizv@{_%FvN=6o)( z^gR{MU&B*Ys!}#{=?wrD-alBUs@ctJcEnjs|6yYUx2Y-*^U4GEmD#Gw)4cM8edRG# zS&zJBs&I%?j~mkJ?xM zN7i__oVa578hM&Gd&0h15mlv^S3YlF`K+q)MO2!Dsi{(eym>K83g2t5@s#4Kl#)E< z-E!(#d%K*S>Azsi=$oq6@w|1MUT%H=K;N?-PZ>)!AN6l|buCLu4hoI^-H@kzD^F)V zRn?EYs<9o`opASNlxIl&flti&_|4MyZaBXUPid)2>BOZo0W2IP?Nl|rcujZf8oF$Z zU{_V;U|u=EzOtXHaulx|ZeKZ6RXKrIj#Z^h<0+F>DRYrxj`l3uMd^7=Upg~Y<;%Fj zVtHLGw7;YIs%9H_v$gh>t7VOqs%ATRvu*axwx}u(@XCGmm3vf`$53ew=3!OJY2N&V zC57*`^E~B@D&;y)xe{U4F4-O>4;VB0kE*q&eE8vTSG8w7p4*mczB7Hi`i1i18UGMu zjs0DWr^J+(o<5qY>J?rUEN^qd6%KcQlkyCy68OZNkGCy-i-hw_^OTaRlz1*32VmhS zDWj^X$ZI|-Z+V_RVvPR>s>-Uova)^U=c>vyUYTrPnWU=B;FVviQtI)PI;xb$NHIsd zVR^gf+mptPf2S({jVt^juZy4U@90NWvv#~$Yx~NUvc?~(X5DzR&i2hZsw(^O%HH;s zJyn%MP-zb4Kvl{J-h8Mfh3~boJY|$BWjarp5@FUR>6=b^EAkm*MklCR&*!b@s`jkM zGuu+lcjhKuz21`Ye0cNjD;2K%H~yj?63mi?uRMQI7&|76LUU}TKdL>^Uv^< zQ>v64E`7mzl$=x5+~hUatZV26WBjkED)YsMkMeu=m3LH?kMPO|<1NRRsrf*>c)IgJ zD8wrtRi!+^Qwpn6o=1u~+Rwz>9VNw#8-H3={t{OR#7mDDzx^F~Rn1=K&0evuWU@xA zs#!_i>|Oh2Z>uWH@yasxm8DgcAEMG6%nGWMPkHl?Eh&7jRpu$5sZvsTO7#e{mKbk$ zlrUpPtEyVp;jJ_Da_bj3`kwW8YFeuKqHM;if3~E&ib7+5x8y0m%hUOrs;WJ&YGa4> zPPlt#$}^;T;1hE`x?1|a8_w^`Q+laVhH&YD02W+He^t$BUNgeFhF&v9aG0uc3a^}K zUpZb?Ih$9`w6C15s$9S;vs5X|c*>zKJZC|-p*4V9Tc8WJUZr|*vs`4VQJZE2dMpbzgmF8exQlKgd_r;c!n}1Mz1(_~=zG@VDQKzYJF^V0E@erH zL!q(16L?Db3ewXjPE}QrSAArM^;Nk07nEm6Rl_Idd{nXY{W_eV!c&q|Dd}ALD*y{e zNt&vrKCk(vg2f?}H%73ws?^0K zD(9op9L%|@lqJ0RLQ4wYYb$xmGF8fEp0XjrtgW*>O1?2>bd9R@Ufz0_YR`H+J1o_F zXMT|oKI1ASh-X#(@a9e8DOD4sqoj(ess^u0Nw7KLz7KcLpgiL!sf$m{`KWE_+c=!x zfTz?~rToaH8v|H4N*bwZn)8}w36`TI!5IIhs>*h}vbB9>OI2l8UfIdMvV*F!H?QoW zN*Tyg`l(VzAjKT*p$T@+w;zogAEGLs#1+QN>td|^9gS8so6Vcew6B~lYfM!&Tg;m+ zux~a`Rk@m1uCT9MrmEbCN^>yRsZzG_=9?`ke6Q{1DLYgtM|jG?2(z|d-*nP@CBGOm zx=+>mEN^{UwP!t^la^|}Ge4{rK1wQ76OWSL!khOqo>H-zbd-Fos;bJXDp#{PO4@|G zCsUqrlzfFx%=t*Q^lcl?ufk8GsaXwEI@GJ4!N*8}F?uAITMl$?M`z`#Tz} zYBrfSn_yo#PSzNsYBrlUn`z%{x~g&!ubgjRnWd^+fl6~Qm#R|M^5&~7DSWSO;wkG@ zDSLRz&Iq%%UEg%lQPSC%(XFc1M|tZ*sy*xR9I#aLoq3g4U$Ufh3vb@rJmsc5o!3=W z`4Yot)IB?_e&Oy9Ql4>?6u>9ud_0^e9&G)?`H%6Gf~u6Kxb%M$Ek{XVRZTRnc`ng% zl=Lvh{~1+fFo2ryjJSC(`iARb#+Hr|?N68@L#>=S6 zD{+NSFwB-8CjZF(jy_N|OXAI{+E-SQHNH?atI3)2P;QdKrWr8$`2 zsZxIA%^O=%_+D$qQ+`&ZwBac&Bh1<#iFQZHP-8}$t6F#Etvl)E*7r*EJ?rswuvGJ% zIf_>gx1@|fp|QUw@|1D%bdFI~P3Kip?64+;yU(UPLux)gG3R5hrSHUW{t}+DP?fTp zORumVCCgMbn|aL!>lzwmjNm#|?V_Aw-1tRR`CYDXOI{Z@?eFNis@X$H;U~`nNtUDB9RK^0q~pqyBtCBV8hMO2 zD`?-WfU5FoUipN5Wf4{73#c>)^I27j#+!RBDSWRL<0&z!ls9x0-Sw&SyreyWraNHIrysO_R$YTWn`Rrw^YFkW64W9{!~w5r)` z-fX6Q<#btNs;b#y-fV$=vw5n@)x2_redRJ$eb4@r+*+-n@_Ult-#dPlkt7 zRfTy~q3Sj#+?H_nrzp=jN}j_f=6n>j^xYcH_wke$R4K){bPRxnqeN5HyvA#aSGPPB z*BRpcKdc;)-{m8DdbAMna}Rm!J4}KdCBPqS749-&HB? zc=Ohl6u#Fw@svzeN*|umGs3KO*EgN?UdbL~M!Tw759O@~tM;tNGtg4acjiJ~JhzGa_HI_>AB~`6yD% z(S9V^?kKrv-1tMP@+Y}Mk!0x+^LVo5KsHCQkgA!NH+$Z`@>yAt^* z*LmeD_LWRk`7SEW!F)@VQi?YZSyK33i{mNpt5QDUDIZ3dwS;85qvWzNqw%WNRe9^m zdb#xr9DUE?&jDGg`Eshut7}_QuA$J_-;H?6ck*=BS5^JQtA4Pr3Y^RrzwRutZ)Li|p@cfvVX?-fW$HK>qQmV?2 zdF2Q8l@(N#m3if7_LZNiDwB9+RaHt2o|2+Use=@Av@=rdT*-fp8?UJ<|DG!}kk`ex z_IFfI)$CW^tf_tFPqIc6RkJp{Sxft7f2b-u^U4nPmF-oPJyB^6W;azzKi<5zC57*` z!8~PvDrF2$85v>LhU=S7`U2-^V@8LnT2JGxC#&|X$1~AV&3EQbUcJqd@@#nX?&m3c z<>}n5syfQ64%uP79PWOK@{FV896mAU<8Mpf*l>OhPr0B&yMWf4`%b3CP}DkXpvbF_V_ zc1KBZ7Cy@FOS2rv=J z!6vH8R=n~L`^x63%8tCUy?td{Rb_Wx*+rGom#6enrTmE$bF>H9F3Kv#jSocylMWs2It5hkQc=Pp^ z6u#HC^OP;Blmk3vUxZoPV|$b&8Z){})%p}~eO$F?J)WbMYQ8i7<<-|MDaql@>!}fb zVBD3b^R}w$L0)x#4Vx1#J>0zjhNY6_RVUlDjV|3Z|y7V zsVaX&r8$_5RVmGQ^Pep#e6Rh%Q+`vWbl@rNBFtJFebY(rmDD$8w3VuLFW$PlYR`H+ zT`kpoXKt+-J|{NS6gO{!@aEmaQ+C#rmdtil)j?jBUDM_$`90kI808s9$!UCI&c_K$ z-#^0n=XuH*Rmv4EodaOOm0VQS+~zemYg&$yM#lJGS5-cc9v;Db>9&EgihTX~dM zK4M?_kgBpUuPmfWd77s@p-S;0#T@PD)9sFuR>qA#t16G>3NNKg>mtVfjx<%Xw|KMH z?JHlEHHxd6mFCS#+BYkqs;s~(%h^|!RaJh1N^>wjRHb~*n}2Fa;d`wrPpPa*`HH8c zMwqqabi1RZoiU?Hs@C;*>pFV5^$Q$*&w4zyEY*BDx8c<-Eh!yPXzcG!JS9_}&UUJ* z9=xin9aisf_r8>8NDaa#=6v+G^z9SQAI4LLs8Ysq=}`a{j*=0onyI{Il64JrGDdKM zs&X!`oMm4*Q&qWyS1z=#oUf`}#VePqQa13EwW^dINHIrytL>ufZ`}B1Rrx`#kS(u^ zz4mvsTh;6|Z+61I@|dh~MAa;ZH@jfp?3}9dCa=6^UwK7Uc@LH5VBS`x+@BGC=y)>3 zrwiX}5A&4#s+7V!rBH_51HhcMf*E#4$zWqf3#eK@$6FWG%dJO=zGv~@hOt!homq!h zXIN5(qR`mi4R}iZ4C(1pS5?)7SAB1XH7DHt7s@lFe#a-~eEe$ZJ2#x)ny0i-rF7)d z?Ex$tC2dtTJ$X&H42!oIZj4|TRplUF+26jhuc~q+uN-Dy`KPLKJg*$1N}0-2CaF^9 zAjKT*zib!feB;JvsLGdeg+=nZSYUrg^Hj~&^JZ)8D_6-HD^$&P@Mc@>n{8HA?&pQ^rJmqqPSxcSH8a7I)TK9(^zy9{iTD9x4@4o(_Nv*~y@#Q~eAAXq9 z^zAoOzNqzWt*?KmmC~?gy_8CgYBl)bhi^ZrTQkr9E#4@jX4Iver=lMG@6+wQoxB~q z17c=-=XvLP=fy1d?(}Z(Zt-sN_KG>=Z54CLd)3>)*V(t+x7WAdf6PBb8>tP|_63G( z>jM|HYg&#rGNxmoOJG=FT3|$AYRss>slb@P*}%9!yO;@qBY}f~JAoFHa3@XvDbOOi zO?1cTUeQCMheeN!9uqw-dP4M+=xNb&qUS{~h+Y=GB6@A~sp#v`ccR;asgt*xx2LzS zx4(CYcbIpycf5DDPUu|@zD*$9={@AlrCa6O4#GRW?*5Vf+5WYDo%OoEqc#Mz!@)dT zTdVEYE`s+ms7>M#fl*)`7nlI{C4uFE6@it3Re|+^O@YmUZGqi^J%N4TKN2_=IDxx5 z8@Ld-82BfU6Sy3>61W<;7Pua`5x5!nH*gF0crVZ*rd3S4n9P`tF`Z+&#B_`49@8VH zS4^LnzA*!0hQthw85T1Iq z(=B4}i;9|sahx4J3nMu@dM>V6xX#0MzA>`%qZeX)7vZ`X*Cn_v#dR63%Z*WA9=#G{ zzY5pYxURusGIIgEchf`2`Ve>;YMJC3Xq$U2FvQ^-1vtiO?U23cp3 zbq-nQk#zxC7m@W3vT~4h30aqsbp=^hk#!AO*O7GtSvQgOFS2e$_lUlY%sa@ui_Ck- zY~j5Y-O_tKx|R1vbZhU;=r-PequY9KMYr?b#=5%`o$0+B-NAb=x}&!R)?iC-XK#z> zF8Ju`ZG{!t+S}dR#@oZ&7HhMex0koQx3@Rb+Xw5lueYPOA1eBzVt}`ccc8bccMvKD zqhbgu{zS!4R18DKa8!&y#Yj|)Ld9rQj6ua%@093qs2Y!|38? z{i3IN`$tdr4v3!N9T+_mo&G|nS?Dwyo#vp^Ty)Apr+MCS-ud`g;9VZQ5FHnx<6?AN zf{shkaTz);_fGY$@J{ot^iKD#^3L$C_RjRKLC3Y|xDFlHqvHm2+=z~w&~Y<5Zb8Sb z-qz9E@Uh*y(7OYjccSwyeC$T|J?Op{-S?q;HoEWk9`hgY9`_&gp70;?p7bB~p7I~@ zp7tO0{_Q{JJ>x&_J?lT=J?B5^J?}r|z2HCXz3Bhj`;Y&OH^+b0d&z&!d)a^9d&Pgj zd)0r@d(Hok_qspFd&7Upd((f}`>+3s_m=;v_qP8Uw6EjihWC#DruVM@U++EtEpH3$ zwzs8r$Jus&w^S04i_}XeMeeJYXzV=#cU#8Z^*FkIR>!`K!b<*1VI%}D}E?Ng) zSFNM3o7TzKUF+=Yp>@GWS6@%9o3EGF-Pc>|;p?OI^!3$x`TA+Sef_mQz5!Za-$1RO zZ;;mCH&`3s8=?*L{izM|4b=wwhG|25!?izsBebFDIShS=l1H%go88?8F}__m{R0 zAKAWH+J4_`?SOBNcF;FhJLJpK4*TY5M||_OqrL^&G2cS%xNnhm!nasE>06?m@-5X) z`<7{c`<82Gd@HoGzLnZJ-zx3AZ?$&8w?@0@TdV!!Tc_pt)@zr18??*5joKC8Che+k zvv$q5MZ50Xs@?Ey({B2faFC z&A&0WyMI$`5C7)ap8hSdz5H8ad;7P=_VI6z?d#tW+t0r;V7n*n$2%v4i}3 zV+Z^9#SZaj$NuTxA3M~4Aa^~bj#eXh#s{efKH2;Oz>HdqcGyMO=&h(#s=`Vjy z>@5GK*xCNev2*-aV(0p=#%B4i#m@6zkDc$o5xc;DGj^f>-`GX|b1yCS--=!0za6{O ze-C2K#86f_=5k!G7A7V1I3EaDcWgI8fUj9Hi|C4%T)ChiJQk ze`>pfL$y7@VcOo{aBW|3gq9r~sqGJr!pCUsKyZw9FgR8_6db1=4vyE31Se=mgA=u5 z!AaWj;AHJYaEf*^I8{3poTi-)PS^ep&d|;TXKH7Ie`)7}v$XTU+1iER9PMIouJ%tb zOUnt)(=G+)YnOuyv@5}d+STA9?OJfLc0IU6yAfQf-3%_%{tYhIZUt9pw}UISJHb`j z-Qa5NUT}@pg00nBvUOT3wq9$^HfU|wMy)N|q_tz4wf1a_mdUni9oROlBipWZVmq|X zY^T1a?{5r(MyqwX51hc1@eau4`kp8~C`XO=kaUQ`jwSD!Z*sV|TRa?5;M0-P2~W z7JtYAF@D_O6=D%Lx&n)L~+VSNK@S--$K)<3YG4G3&t0|Oh`pui?J zIIx)w32b412DY-Hfo*J9U^^Qg*uh2wcCwLyU2IffHya(;!^Q;mvax}EY+N9ljSuW+ z69Na=#K1u|DR78Q4jg7v@G&)Tg#ABp?*eC2_5c5$VM-bzDN=G=&XLPvh?+ShbDwb= zF)lO4oRJw!u9;Eh(``bUl9E(%DXFB0LNs!TM3h^kLKh{M5-Euy|JU04z4tlqv*yg> z*IwVpqhgik zn0ViFT$Fi!7OOqKhz~p`#2U}9Vy)+-Sm!w<)_Z;vA9~I<+~8RiyU{b%{Skh?3Fkic z{MmA|XIb!=6aDU@@&i$?Dv*_uev*+{ZUp#xFPvGlU z&rJ78&%&0cJWsa#&2yr~Y0u{^fA_rT{=@S^lQYo&)3Z#R^=x+k<@vegInR^gyk}L* zzdffL|AR5U;Q1>0qUY=AfAMw6v#v>r_s_vbPa@uBx^_Xh70_eSqGEk5!dX}QU}qvglmS?z zv&om<)9$altHsyeW$yjnuUj1OE_WY9d*7g~Z@tIFcitab)^lA~Qg)-uRim@qg=U`XM_w26+s_10V6?l$diZ5w-wJe7N;%XR5ege!0I!!Kv~WBy%U?e(u0 zbzeMt-^xbb-W&ULsN}k)S{0Z4SsPy^7ye-;<4pHt?b`DOwyzb!^E?09o0zrT5>nQp1NBi;hW~-o!@U49v4S@XVhEWl&iLJw2M}r`L z`a`M9mG}||wA-VBkk>_B<8pbM$}$T4k=G%iLe^`+i2Sj>M%b3=Id=5Wv4cjslX0fd zee?L3TbpHfFBm*_bm8bBMQ(G0#@)MUTwcNG?6%QuVzU!Qj~qE}R6$X3cHe~TjM1Y< z6lQntjc?nuYt{C)R&8V3w298Xt6)@i>gd9v{xP>2TRDT<(Dx*xS%w{LY!Rdt)o39D|&Wf4YfVH{hU=dLi$)mjwu|J(~}&cy&idc z>!NLKd;gjC%M05o)!K2pb_eb%7;Uuu>(@OF)M@ALHvfi??svVp_MuuUI%~H*V%VU< zVMgn%C;f2m-0b(`I==JXo@ZCRvar^2{nqoxjy2l8!<~Qj!R(Vf0=durYC z-;+-FqBXh&qp*KFYS0Mt9vx9|mm%~@-_4QLC;zjg(TaVIZhomtr&=cxv{N*wa8w(k z@w)rk?0uzM<@cMOJurLmr&s<|>w_Ha#>cmhj`iO=q}UMX_}9%%GtNHn*y5C|x+khk zdAQc0!P)|2h7T^h&1ikn8?(RoX-jnUBU^fpFPOUEM6LDxv|E?>M&m{G9{=-^J7;A* z+PvROHQQA^T* z7hgdaU$8Ik-Z?%wtxHmmp6S88qt{fEuc<+=X;o~eB(8HpdVIH(9_c+g_v#&YNBf?= z()t=X>6(;DFRdwG+L&JIvtQb?b5i%X1s10gfi5iZ;+u9kSa(KDzzQ|2 zW@P0z?~X_v8?khJrK`4@E!;P@peUa=F*)KgX*o-x(Zsv5iBqzPooM2QVKpmNUUGND z0NF&uRXf5p;YV4!f}2?;ng%P#cgrw|C^Hn9nOc=-qN%NAmTzPof-D8!F|GK>m*q`5s9by%XYkCi&&u;O{M` zl^zL6Hcw}?w?Vcybuii+hxUw&G#?>(E`aA;C{LIMEx-gcxJfpck%tDqvH)9;kboBe z`09AqnBn=w{-OCr{;`FFKvLPLvxa!#$MS{E^YOx(kGfnhYC$gCbhM<`T(aen~*GhSX5wAkLrP)THR(T^S`}Bis(m>uM!d^a98p*~rSf(a6ha#JG*~jNAB5fbfAG_3cLD^(lD0kqbZNBI2q?LK&z5D-T&{;DBu4581$5Xu!xre=84>17ck1J(GI$ z?%mB_INV>DUxaapG>Y7Zr{aTnX_V{ovGS2*%%H-;`$mt=^AElY?F~f3_!H%N3h&DM zjT_%TWNd!^5czE6D#@{a{7m4-_J^rmC4TG2n{)7LV;=98p5C=jPrrQ3q&9M`i$3(l z_3qKeAK$%a?~Gn)JyOtqd;C2vhWyg>{Cmgv2N#SPmOs{CFlxwXe_;`RKG=HgXQ}{w zq}x?8#JXsYFFq|DuNrD@1Vp(O=GmR+%z@;$lAK_7VYMk1S!JjzuWf;uLNobpS4jcd|Jg|XXYoKu>hDj8>((tk zE}<(Z><$dKD2@y^45GiVVCX282l=59{E0l&*&gO@ss6mtcm{S&s1hlER`Mo5PCzU2 zaaIdM3P$Dm@jN&=B2r#gax*Ub)j$#htU(JJ@lhsAaDJV5>~`;yE0 zGAjQ*|EO{3vsK*naoryV$f?0*@%Bzj>5w>*OeZI`Cn2y=RpWLTM0xq#e@-(Y;>3Q---#5xX zV)P(%zmho#%mvRhgXchCZcFOb%THX1aT#%Fau+VcpD3(Z26aZJ0W-n6w`=%NQ5H{p zw{%QvLDfq@QLe)w;}vwxGgiNv+t&mw9n-C!ewt}bRZ0Cbu*{{U_Xt*c*1GQUKyNH8 zyS%1YorxQ0H3pX*Ts$+(W+LaXk^CP%wZQ8B&A@^2?BrK0_sCG zW8AV|oA*hSYm<2k^iAuXhVi!v?HgbN-69zY8EM_+@Y_GxtS%$=Li>UxS{7U*3F+N? zQiaU4E*P3(%-V7@*1Was5&d&8dKD-^nn{DZ_M+9u8WS?();4Mf>US_E{q*=QNeOa> z7)vw60MptVX|s)=eN$FK)3c1^mc;;rk6`dX%{Cb#pDuD?1~DqZ9-(^p*&L&hZ6=@% zG1@BIOLhT}AFx;AxmM@qz0z&$Mm3!y@{TjV%45fqHVr&x>ZYP}8f$ugtRrYXZ5G%m|ct;n-%T9ylJ zU|O~;-0Ns^h0)}wa%LC1O5d~a8<+!QdTwz0tsD$jULHiWl8EkPy&E-dq}?^SI<7J} zM)tRAGhmH_i}-yDB|XNvUGajTaV{gVyt^$w8F#U3ZFe^gd(s-?14ijzHqf$k=4r0OZhb(+{v3+PYT|407?Adms^}}(2 zJF8b_PkC3_M&&O1NA^NaZXwF`tWq>Vd>>hjS2IU=(1@X5wSNjuyP~#R4EJEx!y7?Jq@4SJaKS<-EdO@2yRpM+;v;(!?2}A^GLP6Eyg z-M9$e-ZE{!+`QNY^2p(L8&9}$#kKc0aEaSh@;NTqV|4B(dJIeJ-MbIWLtKwUYykF3 zi<2wI7Z%*_%CcbR;7j6q)6}vb9gPP*D1D8e@0T$B&H2RMCo$)egZS|`2FN8JI3Ze- z8hnb6%(%i~_G~Agh`*I>9%MJm*nB+H=Hp`<*2CuWxb8c7T?T9G-a#YA1unwJ3S8eC z1e?nnf}nf+kVzKhs%Kxw)}i28^atzO595RO5YWBvtjgF?jzbO-`_XEkt9}0%^R%6K z+Zz^VSu=iI2DWM9`(z{q7tUeIXV>1Yq`p026_YZJAKTN)b-3UsBLVl8(^AmHeS}(y z32F&XD{bVSgPrr*xag?SS}pZiBdCA0%tX1Oj5z?A`Q37R>6QhTn=16ocAT^)v5}Np zC9EobF_c&Og7-L#N!a$|sdhShXJA(cy7VcODA#7wTiDZ-{hGlHXway<{88+IlAiS< zs|_`lOv8mwgwz+V|%$Vt(FgqRbqF_%ysf6S5Z@`7q-(6X_pQG}gW+y&(R_ zAfBIRJ}L$_SJ7|#5otvtW)h+ z_Shw~Ssw)JMT4~;6|=EHmME=@O74pJi8#8)a@81@F_A+$?XH26kN-9z1B)i>PgsSd?o_ zma$UWGd8;Soprxmu>FSdv>Q~nm8_SqHPfFK*IucHCFVM7FT@6(8*d8XwT~Kj`LRf! z-jBvTZQgB2>%Z0{`>0t@IAw3^j498Z z1$E{st25V!j;P&@8q^KH>3>3e*46mwbc5nvB2V&}VcbYRJ~A*8?+ylSguZCVUTZF=@)ko6%FMeb z^6eta^Y*m2w5=kNu6LI4+U4bBE(nHdGs?B3{H_IEdV|%qXnTbXx|MFUe!4aE?XaNi z)VD7B#e5)^77ab3_Y0z2GgGZ;+1wcmp6G6}Ui*@Ik?kKESQkARntuBdw{^)Xnpw;( zQefCFs7d*S8PwZ`RwIA;5>xTgo2^-Rb|_p>?;BY!`XJ~*&Yy}$IobqmY+cZwY#3@5 zDZmHVM$zt*y(#v#ZSDeZ_a$QX#-Auxcl(D(XApq34S#UBQ91U^VpWX?`U{Mz`KSCn zy`T&mi+i#}_sFxTm)wZXx&_^G8Mr>`eMY&d+rIenK zkyMUr$zcfywgA_F`yE4VL#8nr_FD+3sn4uc@_n=Qq#k{`W6v-nNje0(R;L8N`)!l8 zvB=Kbt5@jz%Wcg|@F{i|K7!|}Ts!FFa&G#-ovR8yU+1b^7oR(Fm;d8k_;FQGhtoBT)5ZtR=c`87T)Q;@rufxl6NH1RU2x#YNS_M6q6oN@&f+5H~!~c6O$}f$8<}-8sFa;vvzV^ zk*nk~)JfUun9_-*?v|w!C%9dGJj>KkGp)(2l@>lF?#{Z`EtXB>T-2nSIQXDe{F5KE3^dD87F zsV!Ny#FS2&g-lF(MrH!XZXlTLmIOHZwh;lM9>I>7WOE#HE%}=u&&76<7^0ro9&~p% zb@#5AwG*mTc9k@gz1@v`&z9qk{$t#qba(4&jQ3t$#jl{aj}+$wEA9)U__eO$cToH$ zMjRl~|5+8*ME3I=yTT4A`mDmfr<5b=rTi#xeu@!463)XGPE(2V6Ci%82H~fSv_Iu8 z`>|rIV}ymMhxHq2ThTf`-;IdeA zrbg5ws0M;7W5pE&F^q2BHZluW#+FW6At%T8jLC6{yX*>u%A7!|>tb97jM}lHR;;K= zB;%+!VkAlJSZm3s1pvrlZqF!I)pnL}@zb5Nc zdY#*4o!+5HqZR{RC!Pop^$5CxAT3s;#EK;17-exJNRBi!8cBfJ=fSx7oqCEQg5*DH(teKW` z9|o);#KfHY5CCkK4lcyG7mzZdp7LlYkBk+=Nt`?Pk@mbcT;TxICc`)5=o>>ghMBlw;^VR6F%sp@{c*d(9#iyLg*{0rN7PICv%q;K zRy<8O+_^skh)pu>wsU{FVyqd2g{X%$2UxRW#Z1Ct&V80bHB+H77xcM=gQ$n|8gS;v zig|>?ocnwQXI>bb*9iwv59cl5EF>20+!rd+tZWt$0iqtkJ0Ms>1l+kVshHqhB0$t5 zcpn5SW5o)BV9tFdCdXZJaT8-ej*tXLN-)({DE?jPDW^g0mmduffr zWLE7*lp;jE6nzG^ZL#8$Sh1PdxO3m8Abn!vZdTw}A#Eo{L_NkYz_=$?>?T0w-1jJa zyA>)kW%~#RQ4i-E;2ek*UlR^-n&*;xQ;5 zAw}lgk3g|J>vf#^im2DuU!nX9DRbxkiz1C$4A_s8M1ZJA@D~XFj1_;xiqpiwo%^4B zT7h%_17~*2iN<#Brz>VXN34i?tP#FsaVb_@Bv9_$FNK=JvWrT+0D6bv+;Q|(@|pW7 zh>oycww(L5z`Dj)&Yt@Jtc}9!MjAxQT*$cDJu|($}(Df<60w!?WY)YfJ=)dIU{<;XHdl>}C=})Dvro?l!0H zGSA)|ncgo)JjAmLUBxy~Y)y*Hv$qbT*j86D28y@(L^~4Yp8Zz4w%RHBcpnAt`}krh z*@$|{?hKGlKGBgtxLfZ8`H5_wy<<3_I08b{14;u>iccgF5cBCN3Qv;CgZt9u>q0n) zdN_9iC*3Ey6Ats~=?YHwFgU#k2T>2FA8`5*3-{@LRB5wR`ja-Ip7ua!4LsTbZ1?%ZIG-paHtx#rQ;^2lxP>a5SvLP8Iz&CX37{+SiH8V{ z`SB8k>>-uMxS=N!4x%2;6Tm6;iOGb+{CKH?GdT>-6v9E&!$la#q1pQ%V=l@C~p*+hV-NAMa5=KI7vpLmHl zxF4TyO(k&R^YHyaIjvy#{H2QdUMD_8J-#L2TkI2W5ghm6i$l#`*;`7DzzTkCcyJtj zO9>0{zhWigb1yl@XI>_ENEVYil;giAbts+qT{-^yu@0v5M|7?_6{=G@h{s8od+#Y7 zEbsle%3#i3PZ0#7bBJdF@eC1g-~CL7(n;Tk`tC!9@5a$LgVYh7tIzBZ&T|KZUL+wz z=R$MQ&DqpV=C@}fyNAm0+b`*;&4=1NQe$3wUKq7kb=2O3+8Z6j>m4J z&wh&%jOaYU?*d|J2k|yRaF4wd(%dh+9S&w0!5}(^Sq+%?JBXD8!~FI83d>5B#aNC% zAQVLBC>w$DVF$5}P?)#=P(fK22IV6{L3EDt2~ai@2lv&RRatY2*-E;I&UJS{_cPMv zp8B(Jx;sf1(YfwE=fUSNc^;FZ5OyfThHHz6VZSEL=c<1^wHT=W_7`kj)+4V}vI%Qti?op_`izkE|CvrG{6 zl$$`gQ77RhaqgKLb+SCOTj4<695cKtjy@0JAnM^X2hPpJ!rk-Dok}O240X?^3<4Z| zEr1rP(d~5=W1)B(DKaO0TNp*3u3~2> zcIqTLk|=l6o$LzhsOYl_i=&hy>ZLptILVzvBH?gfoeYR$GVS&!O%f}{N+T>pJ*+!{ zmEK8oCoJZ$(-o@j3YF<-dJzty9!@53`gIb02#2}sehN;XFgRI+gQ$n&2hKoZ;ZA#? zBF)Msmk1E`2=YNNm>Iie1pHpQM`1Fnc08pBQ7=W0fbHQ<;=xYheq!TZ{9y&@ zK^yme1&$Tc1Y$(gV|)UPrJclN0%WedRNh*O#l;@E$cj@yK zY1CrCe!NNqh3?_9smiRLuG|u_EfRt_16f zPGT8>a_7Dx)Et&AQ|blKCk^M0qi+>qA^uma6`kSSKen9vHF3$}>Nrt7&NT1aI^(nc z=kU?>hvY}suf`|RCpLueKgOq{|8bX9$C=6U%-_bDzm4B?ENv)%(-B8s?KsocBkEz* z16EyP+TPjx<-=(bsji`fasniN`S6_e%ZE4UDmH{-gEL_e2_kiTsDtW<3P)fo+; zH?dk-eT4utGmI4A=xanNK-5b?GXOP>6CMKk(gJ!x0yPChi3Gy00eUJ1YED3idO&Re z)H+TG0y@ZmS_c7%ih3?-nVt3ufVt|#kTRm4az`lpNckj` z;~Tk3UXsc_t~|RTekU3~^xaO%hzcecaXR%&b&8Xk>YU>KZeZ+9Lny%_pjnc zojALpyiWjPt~ZIg09^o(8Yhwo;Id$V)F6Q5FaTY30qz7qdYtG^0RPbJU}PXY2%viy zfL^))eF2a`>ZgMTKLd)TGUw*pWDkBn8hk{(!5;|a0dXRe#LrUK7s$aMAPcPzzREH= zhCM~*=*s6qesG+~CHX@n|CW>=jD_KCxiGvT>kY@U+%OnJ9AfOWmaKb$Q4}Y}5C&he ziomfpzGO`g0-9Da&~pTYs0TC)Kr@MkEm<=a0CUNjP0EOR$}dBCE-AAm zYc5x|XRUdpjHsu)0Lrh$iTNbXmaNwxZY^2!@%?&vpM)$~Z|DNN4S+>);!OfzOV*+w zfH%VcEYSs60f1$3;vE8DOV+X=fOoY4j>L%{2!k(KN5JukvN>`nzJFO9X_d2XuKn-f@i=mGDo5$iH!kFIkcC0ia6wo{tgBP?dOkBQ{M7TS@^$f|Hi@$(>pF;A zOIB@s|CPK?LYA!SbpaXxpnkl#fdJT&RX+&ehA;qbT>vitn#7An1i+T8CP4s=!T>bY z1!w_)W~9!RtY%OQs(X9zThibo>J5HdC`ZSORwT}rtmt^_DXSI7u$Qb`bme`JkBJxU zNuDiPG4c4+zg!sXC98cHj1K=D;}(4UwXyN>*PTGvPWtRGj@S;hZ)LrQ{QB80%01$L z&3!<1A5{0oi_b}zzm>l?-g+zlbA4*oX&evH5oIReiF z{e=-n4RsuS-;g?@bM-^<;oiaz2>n1ph|YzMpqq!Oo9ylT!^rVbInE)!baqrn?H8yW zCpGrg{qZnrCv?<)huUxP;v@<3x9xwktLdbo&8q1SN;9JKH2)2hbMfLVq42lt&jH|j znd+yE4Q=e_o~;<^A3{QOj#N1zSwtj=ON7MUu8&9vCAy>#nJax{g6T03oufnnrD}qx zl3*Gh_EvpW1*Hnk@X9n%su2pJbCj!rQiC}7+w?UQSym>sNFC9+dL5`=OX~bB`fDpz zuS@EP&ea=0y?%nYfdJUs^Ys%-C;coZJ^StX8x$gQd)cjn&K!6&|xJnp0{Jou}p&aJ5MgtrLVGF8;QB8wIDejVcr{Rygg5579YaNAUR) zL=3^Px8!{aTZ}?vrs{S=L3ECi2$c8)(V0-#+wt)VO6M>rNrZyv9Hk3TQi+4T6`!i8 znzh?iM=c#{-ARqT4c{GV5R;hy&*InXa16Bf;WWD8?F;a-@}B2 z=p5-$AWbA5wiz@L`8W^p(9NL9I%-cs?TG|YN`ibN=m{uZqK%+ZMI9uUjIQJ8n@U|r zbl&wDfSH~krV$L^1ey+j)3gaRtzwwx2nNwP%pAbXN)R&%hHn7P3WAwgG0a?oL39o? zA29QXgl+!JQ^d_x1FDr0lZ7i${7b@ogU6LTEu3kMc+y+lT=qeIIbS_j2-KHkg4&IVq8722?^0TQfnZIMA3qf*anYKh*~H_=4u{ID2UEcZUajDL~#qD zunnH}3d${EP+|xL(K*WPKxq4Tq zrzMIM0$>|FX_)k$m6M*m!IPp8nGea`bP)Ogp?9LVGf|`y1>4~1ZQrzaLY?0;=?afo zp?xVeh|W{v2iL$vF(6T75*Od#8K~e4uu(G=FjhFZ#E0mdZy5N7B#JzOV;ej}6t+Bt z$V^oMp&&X(83UA2iDCqyunnG33d)EuDEANwqH~mcfl@>qY=fsrQ8jD#J{`6Dp;k<4 zY=fs5YUNp`2dIyT&ihyb)rUxxZ}2>%$fE87_TdpyM|7_K1k_6t#pFaWi5U0>Pbr@^ zu)#AKXI_vKiM_!ysbbD4#EIyfa|Sr4CyHqV$v1eWhZ?%FX-a(n_-SeJSqDf+C!4p7Pw^-}%= zaK29z-x3aY;NJscj!e7lz`v~+>qo*u)WiA(SjQ8^QNm&_{J27ORG~5#?h}NAsE6|h za84(RQ-s5u_-O^_R2ZBygoCJua~?Q<5es+Ye<{+eZ2l$!L_LB_Ah<{b+>u|bn81}} zZbBgH5mZS^7MCT7%1P#41asw=C6!KkOHPiqE3ceX{seM`F2>cssF5V9Cy6K`Va~ip z(q#I_7OR7R-%C*nlUcR3C`E{RDY^k{*C&ZON#a^!-=1*wjWd#wV;3h72-MATz! z0>(y3!cBn8p*K?a+zOSMG7sS(>fy8mPV*#jGvP3o-dw@CISh^<97H{ww!n!d7UtBW z6=l<@-=eE{8x-4h-lFlzpVk9lKAFMlA;H$L&Obs7H_tg2W^d zpCmdH2Y2m>d|H8PkH?uMa-y+ad*_N-Q-~E&kF_UQdnAc&1j?Oz4`4BKSk_Ic7eFsC zoI8%bI|&QX5!QPV^!FLv1FX@+#GLzR0K6-$M2K@AOUj6P%HyGYZ;~h?aqisjwdb`W zg#%2>4d0BTub6NU^>7{n&I824o%;hAoHep$f}Q(Xg8)b0!$g3nM=&ud++KM=Y!Znf z>WP)2yOXKA%(+iSzSqie4{`2~>ncu#;uKP3&V5Q4#iw)?XFzd!l9)!K+__J;D{Pvg z&noOWN;#rl%I5%QR+5-WINZ6<0>pBecH6nntQc!9VIk^ay$-Bblf)~8#hm-A3e_tL zmARlVARI(JoVS6qC`r6YILx^(QgGf3gR_Ki5cP1D1Ls|0;m-YCMVgh(3L-$%BPavG zDk9*{eO1K-tBC+nk6;4`)+dRz1i_s9dQ6TV%E{4o?rRk))9Gx~#rPB$Ta(0=B=Iqk zFz3G2zM;2(fZt0WD@UM}TuUN&G-K%()*{aDE7bbChrp^>9uA=VxMJ z&i!Xa*{tVZbrnxT@f0aC=Y9%`qwZd@Shv0e$*EASx-a%bGRUy&SQ z4$Cf24mD7KUSl|S9DPxQh3E)tmF3*)1M3E2V$S^r0Bn&~BE-4hM9PSI%1xl$2>)gk ziF4=PDB0RTaVs2P`o!?fIQl$}arQ^f+lqKfe(-o@j3YEE__aYobJ)BJ7^uxbjML5j4_fv5Cgu%%o97H`FKX3*T z3wQ1V6=_yBxkP}dN01MK!9>8F`{0TRh7bXw9>GWu3{MsX1i_s9a7>P$%gNDp?ga{! z>2yZvV%!IearlSHlf^wm!kqg!`-UzA0l$~-QJBoC9ZxAj)JxGLV0#$^K^yme1&$Tc1Y$(gV|)UPrP!|_K<3;_6~4&|m6@_BgoCJuGaWe7@b6j?4s-6) z6r88R;5hcO z1nUa?g+v6(o%@PVb6B=asTV-+Fq}J%zEy;U=m@LKa_(D!wS}0NbKe4huceg;aqinl z8BtGp7nFD4BO4^no%;@ZUi(bp0MmZMH{D_%r^U9TMfv{b#$vjw$-A!hWTcBkHC63~+wOUyndI+`0b_i2X9{wsZfjVyr(2 z3sDd2BC!6!FQyO{bMF5rROb~cb3y-?a1ixyE=x%kl~Y7SN;!WqLFJUtBt_s1uT~T1 z@)UE!1yK(t3OH4Xg**4EiZm;mYD9pjM{qR=Y7hZ;?lmeVs6_;bdIZ;lpiYXomLQmO zuai9Cv}ZRdWiLS;Igdb${mfzdEUG)NKkiG(@#hAGx&PXiF}d#S#{WR^)2N)e)7 ziUinNq=;rIqA9U)=iWj=YG&g$Rp3}5wIW7DJ;qzX*e*r1B|zrf+bMi)6)H1jw-FAa z9!@9VbW9OG!eP$6qk`iLgL4PrAnM^H0wMNpNUwc5g8!2<=-c6B4Ee7mIIuRi15%dQ^-xQINB6<-AckX@pv;yazfiuVCL}NSm zUKO)u5-Xw}>s?^YO%XW+%AI>Iu$Vb4%TekD(BB)*9Y^0_!a{U}wcm2?PXlWzF)`;p z6#&0TD-q({r;#$Ep7Qfho{=J^lQ?(oGwgY7y21gbUk%@kqwfX6LDa*U1DsjJ!kzmp z49???L!A2)jpgsO;^>=81c-VBucVN9Quf>fV)IE1QBQ0Ey89Y+mpS*>knbnZ+fe8J zhOXiwD85OG%(=fAMscyO;xZ_{lOmRoD0lAf*cG-!(PtI5oKlXcm-5xXc|S$0BpmMC z-v`96%(<_u80!PVLe#_h2v{3Z#CpPF&V7SIwO*kz7xYbpgQ$n|DR8!?h%JP}_T0BB zI9tNtd`38kdN{j*vy)i3bKj{*v$FY|2oUuMz68M+M8KW<7ZnqHMFfa?1mA(+n-pZRxpu$@j3r&7eP#KxWbX$9$&jr*$t#|r5TF(T?QUI63YDdHRfGUxuc!go%gGE;Vu za1ixyB2$w^rBvZcH6PKLbFY*dI)W~o;meYVb6KkSh>oa-b0u)DAQtA_uTYfDdXCan ztO3R9q{y6mbtsl+y=qcl5%v078_KmvnLGDdiZp65U_Y)U0z^H6n?P`5s;HML>JkTc z?l-2gX$8)`9?m=?CmP$i*R7bf0kInfQpxn88fyK;WSresR0R6bMi}L7e zMp%fBute1(2IrowCGtI6j(f9~y#hm*dg=)7#Wv-z6 z2nSIQ=NsT0NEKfb4s-4Y6r8Wa;CxFsh++33Kk} z?Hl?p5b%5HPld^>+6$B-M7xI}E+xmQjLMT$tXR=7(F94n;D)9CG^ zG)=~{M7@+<2b|hzq88yW=U!XEsTBsN4&fl` z;oJzEdc?wInE(2{V5%_=}?ocjhkx;0>8- z`_nLUD@K}6NQlmn-U8CX{$c?kF;~7&AzGjinTz!zLP2znvJ5Ei^cPDAg*ozf6qF@l zP?i%4qH~n@fwGb~xEo)o$g(miBXvaQ>g%AshSa$eUsJLAdQwMpuD%)SoBE551i)PQ zCQN$o%1O_5;Tshq)3t2TLD&U^9sR{;{lzw-U=DnTebashb$-umQ+Uh@-A$=Mbe@|1 z;QFe+*w@-;dxs)L(o@aLjohQrNyzh|E+SCKN>H zD8B&ZczMmd(E|5B+bM?zI@l={AA~MA#V&E>jaweNL;Ibod<~=!) z*e?50#hjOC($i_C24@X$R?iesnWm%V4!b&#n4v3+$_zC>0DjwW*f{!X5)z`5)O9r+ zb|WCUiHA9CH^kqUb|A!IHzrj?=c>)1+B8#mNSHh9rkR$*_9zVCS#5Y+9DU6R1<^T5 zYoG|?;0{}0Kt7Z;66~-y80t9sqDdXmxq7?Ia1J{l)SiS8oeRaHo3~LnnZv#fIo=@0 zImBW6bksUQts|*1hutxZ+8sJ-Nl;736mcZT9d?3UO>v4gtEOa1Gote}cLz$>Op!(? z++lYGz-pOl+hM0wjMRgW5S=6S1yV+)=tW4(VP_~ry%ZvIQSL`5h|W=RfRddlvIvDa z>}&-kD-4RCP!OG?cdE#JM3WWI$O--Y_pO!0Q6SVRomVK3#=1|0U= zIP-~|NNk6_sAA4##EIyf^8;{}Wr|e<$sKlCsG%!crPPN6HXJsNzBPn|=me>^;jniD zX(#b8hrJWxpGrFr;;=s_RYd2iUqN+Wrr1lu++pvt=d8U719-L@9v4U7*Mx%T9OYY} z93&3zun%HD_Q)CucG!CjbsT-)kvgJt^&i7J?10c=5<+w?bPU}*LfvEz`v`KpSB`Ut z!#=K~_AAtWAvNZ(e+i>@Qb+9!)PBztzmXt!*uUG=^qZp1s_9QkGote}UjWMAnc^Iw zaEJXj0Jh6i+Yb9&#Yh(k3DG&yWm(vM$Py7*=3_l`*p;(Fi6U@@mxH+|U!Fxf3|Sf| z)qxU~C8`n%bJ$S|O4TqZR}l)L^Q>G0l>@JM60!Sym>sNgdI-`t?w+L+adN*Qr>& z9;qWbS8oXQ23ev$0WgQ%AggrJmvYjx9d><%$aE={}F^Ha2Q&1&kHWt;C1uoUar3I%WwU z!7+#3QDO5bL}se)AQVLBD9J!c%o6d0!W?#@f)XDFC52EBouhOEN*Cf_4!et@YSwOd z9kn~5mQHHSVW&f_Jj>LJ`iSVfkA0z4h{ zhn>Tx4LIyX?zSs9Yhk^7U@i2$|AjH3wb|A!Imyjx=bJfXEos=aekT7@Hlk7Qbg2Div?+uTO zqwg_7L3EDtBv76p4(_m@z z)J^8FXCTK%=$&@W<%{oQezJL#V~4fbkycUZC;jmi3GXBo@ZCnONutDrdKJ= zh|bge7El&ui3Nnh9ri*1d@oaNJM0A&BP}8%MCVA$f%I;cSV~CDVZW;oEmerjMR^6G zAUa3+04QZyVilnR;hyA5} z(|!SUe$VVtc+3jjPpLt4o|+%Qbtp@GmnFU-F7B`oDLCKRsNX1HtZ)t!AEI-<6X5$f zOB^FO=CFTO*p4YgW~zQA6h!AJXMpm1miUcOn8W^ELHR8V%AbUS=p5y5pqwKP=CIEx zs%Gu}qoZ~SY8Oe3IqZv2E6*~y2AI1Oh|c>MIRL-JI>6i|;SRgffKXY~UBEtEM(T*p z)vtnjwE^PF0pbc`;10Xm05)yFVPA#|*GGFm6>C!1IUUadGr@AQVLBD4l`Qi8#2!?t}q3FKZ;&VgGHYVj^jQa72yPDPIYmg5}au)FH0r9-VdsWFG$J&amU9ksqt%NQVf zksx>28Fn@GQnXn$^`kT+I!|*BP_hSzEJEQ9I~xFh$W+@7JF8+OKOrGHM;Z#G`~hMx zAu)%YuMiDZh|EQK7@;6KM;Q&2kpskVLSYVjq=GU$49XZnL3EBX4k(4h!5wy?BFoC; zUQ$PNu6{q%i%Fe3?Ba^mA0Tx^=js!o{>T9FFaa=!{Rk$#i*nMl9rnWtk?B$<=^#u6 z!ju8x@d4s7qF@etiha{Q4t0LdJf`rN75WsV2GMzHUI5o~1H`if#52Uj9rkky&a*b^ zGYS|hoSDRj=$vmJ_+A`Tb;b8?(R9CoE_4YkXm7MX26a5IM;nO(kG z6&aeIRY{OL?5J$(d9A9V&8q3DY;&gp(RrG$1%m_o%j%)^YsH?pKQ^a;F!biqph|E;=Clo~ID1M*}%oYO( zg*ohj3d(>mD7l1!=o}>Mmd(#*jLqbM<1V-$;12sfK5f8ZkHeWcaw4(!unQ~Z{2y^5 zI_I1S&PTGv!vx74_9H-IhOX>kr9J>WLs~p}^i3ipL?=ik-@52;0el`=^)f zSz3aSee4%V8BtGpE|h0yix)|pJMG!_-1VZu0j5_BuZyGaCBi|}!+8}ruMi7&+pl17 z-jMYY?6wyg1UUL$BLYM{f`!@P_Ot_HZ;}|Ip4i*y?jq_gbKQ%O?}c*QLtOU~UBzWk ze1{a7^L{6c;&NTZGAORf7VnWLci*e*3VTn{XBD=ZQjVyX@(sXQpDorB4tL<|0r84V zyY0Z&R*bcgun_gIwgKytY_XZJm<#_zq1voanG5%)goCJu^Eq&KWs4nz!<_go1!qSX zoIQktsE6|vaP|=kcjNmMX;wC069J+g!M7kdNCe!GAFP<*J0d{TBRB$r!`b2of?%%v zFeb-Ea&oj?`40+}>1>YbV*Cb-liA`#w)mMym@_|V-_R#O!0)A>6(+N4Pg9Bz^-}aV z*v@5(v)SSdv2k~PPC+_rqP{JdIWu~e^p!gmv;hU{YVT^Piz3Xn@Qbe z&OHgW9Bt=5O`$TK&U3mLF9BoDKrw5em`NnexzDk0=vg4( z_tH#-$*kI!DMg5SDOw1&1p~!v1I2t|NSQnLEs8X1FGW6x)e| zJNMmuT7h%li8CAJL}NSm?G>}`C00Z|)^EUiV4(P#K)G{25NZy~zE!aOYk<2fq_5YbMya?==W;^wlH+L_LDqIpOx)17g>b z7^0ro_2_OL>MnEcb&&79a@<3ldp%vno1l0jDKh7NV;IE-x{4ksHqH?ZNt8SH#&(4@ zRPShoVJU5;o=Sj@S%Q>fZ1 zROW(y8{r`8;dBB{#~k4!9Om3RDmcC{ICl^Zq8?5naN>!DJNI}+nw3ow5g_UjbOAvs z5pd_8S}{RaB0$t5=mmnFIid$aFz4PAljE0iaQLZBA3{>bI((d?y_-n6*yK%Lx~Ylk8v~@ zN9Ks(1jwBGNQG~>LS?3G4B;T^;oJwDaXF%paF}x+r{ENZ!5L3DhUBvS(Ybm9sMq(48wh~8@cMrIbEv+JW%KNOk;(|EQ{up8bs%*xdmKp{GzpA2;$=IyN!a= z+C~)$7%QB1#E0mduOs+;ei1`(%z671wit!TOx5j#g6JG25h(F~(V0+~>yB4YI)_0? zA{0dDC|!V(N*v5_rz)yu?RM2sONUx_Qe$qrJJiavOg*WOh|c?%0o7il%AIyEMHY1z zun&Dm9nraZ4%D;#BFiuO69aeI*?ii7%g(}?lX4=lU3UM9IsL?m=$vyHIEVN}9zk-4 zJp@S1(3RyW^#R}`hQr3uS3pRJPLO^XKd%~G^kHN8w}Ms%L$1weVtFXj^pci681;18K<+hNbI80if{LUfL_6i9FT z#Uest4*P9|Xpur>F3Rr^3ZiqARX};qFP0MubJ*`GD9gj3yiX{I&QaC^F zgfD=w$1isK#ZIDN4ttM%)9!{kzh`zTJZ6RNqtqZePtAAW`o=E~_{G=6#U1uH3eEu= z^=k!;70&m>hv=N|82FC(#bJVD4*Q70c32@YQ+1qB5S^p^29%S2ae`2o!#=5?oCt$* znotm(qnriG8RB3L`;4M$*6v?AYX3m(JgG55MJ}5*;IJ>pnMXXq4m&b8G(C(niZ~IS zbJhlDtz1!)Ai2Y?1tezZ%4!0Mn;!t5Hyk#OzH12y(Fsxq!(lfCl81Ph!}dUY5;7F( zux}<+MCYolpxQE5G$uv_L@8yL+M2JlSw7=NdV$K`8HD2UEc+5x34ad3y-76bC6 ztdU@cJ=IXh(bt~T5uK~Y=7w|F0U;j=Avzc8gl=}EZZe165jmbJ$2r7d-=U+H0JS($ zV-7nmj9Q|OS{JCL=89wz+6SS|@0t4*9q%FHk*a|s2}Im&#X%p(rwu;(eNX6?SJqxJ^WUMDr?uwRE-d6sD*^%2o| z9~VRQEmGwU`z=Klbr-M?Z<9KrbM=)_Uy&=8<%)NRfjjIKeAYpI6WfTaM=G2P8Jsi zm-E@~3xi81z98*D$R75k!R8|oqI1>D^6>BN<%x(qQrpT0MCnt$Hmci zd7g=a=o}>qC{>ArJM5}?_&r!zBf$=Pp`nhWuNtW%I#;im7tUb^gsvtbMCU@+qMO%H zH<`n}2030R$2r7dU#Fv14{CKujXCVPVbpHWQELdb26>`B337+sz^d8<~Bz5kv6Dw9v zA$3IO>OG*|El+eI0Oqi}VbWV9Cq3I?cTtE;my)i7&>skW^F&6T=tUIFVfVFf+6<`k zd#0DdV^(M;r3TS?YVHD8Zl1`=6WPSY9d@pQlVhW1D`2c}1`{8mbH3r=E65W=3644J z0)=g;LS&|D1fd{0M=1o#J$Yg@p)iMikAgBf3`!B9AUa1W2FiWJ!5sE|imF+=|I<-> z2x^f2`i(Rm*yLiG_+?wTOfWv+qXO_x|#CF(^Rm}MmaUweBd;y%#<%wqrk~{3@LJeKnvr2sc_zlBhq#Bax%x+89dU)M{~~qnu>Y!9 z{clo7bgmwekAEW|Ph2Db=CChe(%T>>J=aaq2(%fcLX z)%?kEMSbv9RwY05p1BNX_=IIvXtjKEzXj2GYOV#>HTmM|d{KkAxWm3i!MWN-t)YOi z!nuz45S{bg1il;dMLmLJ4*N!ht)4<;rm6vWI$OJ43xwzUY`Qe8j*VcBgzcZNOo7#F>xfL}EK^U&Wkp#EIyfvkN#=^F=a2a)+G? zBxdN!l9l=Z@LI!Rl0vY z&KH{qi@EU43e_fs%3Qd&5)Pss&Mx5W$QPdx4s+r=6r9h(;Or(GL_M5+z}ZVI+>P&5 zq*>W~Nd$;`1P4K|p9r`k-(NAoH$;G_M{pPfKje$=34*!uA22x{mXo9H%D-2rOlR|x zF2+eIwB>cqmFdUZwFtmm4#inXCwixin#uLZ^Otk<>FS46$O zUJvCuq|6e#iV6DL-4mHb)DY%Yyr-nlSbpX z$AzCB_msVcGsoQc{+QdlbUflFxA)Dv0ewndfnzuPYnOikeernn)<<-Xz7^=p#*23d zdcfGV*i3PiRKCXLy2ZdZkgab)e2e_K+;OqaO`KQF{wjM@08P(C9*3Q zjjmioS7d9x71R?%Cp~Fo48jidWX*W7`v0saYl3>RI;ba`Xi&=Q$vWx@qLZF9HhS_U zdh+Rbv30!IGG2UKZaIAl9;=+T29?tmoPX3CTuvVck?$h%gTq70X$5}MVLPECI!8YU z^gZLn?*Fqv*aQ3(P0VuIT~1dH$*zQy(-+heL?=CIVhqAh=*gk+;=A$UoAKg6xr1;B zJk}t57c>ap;QV835Do;9AE800GBjim_ zsV2J;G6=s=PY|8-q-lDDx3?=jqG@lJ_Yd^vukqr~@#2s1;xu{{;Z469=lKl#7r?C1 z_%moU{=oSuY&1>>b>RYyM)MINqw$2-GwxH3vE;ZJ&llE}Jl zSGv38Usw7q)d$v!h>X1Piprjncd(J;x@to$SB>;aa(xKy#yNE3(s*$(&;k9~_7b}C zgx9=1E|$}+*0Nh6BNI_<_ey^2pjXl95v}Fm;Io(BSI1+6zF1T#Hdej#h&JgFZOf_@ zmrk7PiLD`(ZZTH}ELzVXrBTJMX2$7u-fG3(nBG_;r+Zx`*J8b)SD`a=J>A;M%e$sW zwD)%Hy>>#C%C3?+p_kyNx0Y3d(lg%Jno{XDMaeiFQ&trh&Gg1xUF?$7vEHYP%qDM; zO`1Q9md!x=8E-eV>!Y*Oyam%CqjEDek{;2Keh}zXdc^HUouGeCG8&g2aff7!Lq_Wt z;!}sk;<{o{yI9n+@*1BWk>I_d*qc{~l+E?HN*YM`y6Blz^w$;Jw!&VJ=XlF%;S%x_ zGOKev=wBj+4b5OcN*c*#Y8wec_h)*`Zov0*<;{*!p#Ig9eNHm^C%<)2F}>3xdddFv zM*mu(f6ady_(g5E-BX4||Fr0xOsgE<3wQ5z2bFfzHi_|-$h3s!{qrdW72mS4r z9?@6!w;%f39{p`!EN&?lZHh%}+0DM?OkeH6W{u=6LH%rl^E27>)jFsbKI+BWvKPSy zQQm8}$!_#Bx*@;S?1m5BxV>0(2y`HLoa~C5XuHAx2eWuPy0U-`QHOFmx2&8Yx+Bmx z`K^P#Wg4TC9+8P5NLsB|=k#l@aDof=;tibn5vAMXln0eUDbc15^UO9`&9YMs1wOL+*RuLv2`7X)1TPGNoBb-?Z)E&&gd8D3&SB`&U|3=I zB#CnkIhXwmS-IJ6iOBi@JQ**NnD>!+N1u6%#C(p-C;H4sB<5RWz9K=2IpvP^aw~$&)t=A#JqX*^0z!hpZeuTd}hGUlLAO zO7h`_*dPB@>BhA#+KPLV$?bUaC7N{?ypys{2~mzW+ZwRMrflQ7p?SLlui=sfMS2@ zGuvuo>eO5L|p=uOG&akdHW)ySAb?I=|N%*M%I7; zou#CytUf}*2}{XXcp>)3D3xwA89xaj<4KU27KuFrf*VtUn-llhheDGm_vW`a*m!dxqbkP;-w zmk9a1Cb`!>tEsn?G#7gGQI)ox&Kiy1sMt6&zppJf@0;4n=B3G#*NPBJ zZOu|*BC+hqvenkHl_9J9N;qLDsRl2^!ChIUnaMTN`j;zq&W$a0T40Ut!nEH%50(G=_Go4 zjL=p)E^_o+^an|-6N>$-&-|}8#$P0{UMNC39E8mN`pmv0<_KVl$s9_8j79NL zDhSTCNeCHFg3Lk4%y;zKbbiuls*-j>k4_~?FGK0Yq&aIeE>y8`W_}SYFD0J^8=9wO zxZQQ@EX4gd*w9jOx*MDp=KVK76_Zyk*wDJA+l|Ts8Dc^8AA$`jZivBx_ID&+1>~_x zUcSJyl6aMo_oE(Qjf+Zati;!uz#u4m&uT>sNP9AI#vtX`6ON+hY<_Ww45^o6d z2I}$plX#<$H=G0+kB~7W$TWb6qj9qS$e5^Nu9fpN7n!s4nKMYtCCFT;&zw(UuD}K@ zQ$eu%)}#0uNT+f%t|F1PBWVkeRHJc&(0?0A-0SG+ih49|6POp&qj9I4!h0C@wn}}s z40(#`kCdb1prHML#CwapS4!Syf%k&MD;^@R^gbbqwOHhNg(%l>^!YLJJ|aQNAmmdL zoYARrUM&PUIoFlR6%iHNT+f%RwR)E zkmLs>)o45^^j|d+cOQD%9ilAy&&a7dijYGgnxg*ziFF!TCqi_J{wuQj1qml?{#W6J z*q@hFx>sfVEreVrK^|i0dtg{m^xq+IULxmNh^pv6CuHymiRlw6&j4enF7qvkSqhmY z^qIv&m0f~KD1*#TNsw{~DNBNw03v4lyHLHN|Ax@;Z%FhC7=aDdj0>xNizt#$Xub%Tux$czy_^VL9qL_qxcp`r*dQ4L?Z1+ z(jFkGHZ~ttA8TlgaQ6J zyb$}dbeM8YFD>KCA*3t`@&ktc77Qykwy#MX7CCg7YI`anWY9ul`XZClXWB_jKV(+Z zXI3FGYa=s&1PMb(FbNU^5HZ`)VR{?e=R(6HN%RI7p`LbJ{G{KaIFeXX6#G@5`HMD2 zBa&D;ilym`rI46^ATvXs*_y=s6PRK$b4ifDQ9Mrt!MWBEA^(sdy%19Hj$Z4=Pdd%r ztgnO~?Lv|sg3<#?bJl3=uVUlOT#oD|D#+LJs zUU(t)$1asFE8`C#WIqXV5H7OuCHR1g~O9j;u|u_wx4gipgYTg=Ddss&lhVo8$N zwedbr%7-dOfRur@7i#!91q#Z&Qw7v0a2LWc?fBz?ao{h>tAI3 zt!JyItlmY!388wx3$Z`CsdQ_}_`V3~MS={$&;!A+qAKZ6;*3GgNc9-1B4ltli8&RS zlk}MrNX)s&oTbm4L1HdO<^mFA1wxjQAR7Q8W_zvfpbQckzM4eeg%P%E$Hi9t7HuYp z9YL{!`po^>7<)-#XHo2wzSs#8^C~hg=`$~on74r`Ci4af@&Lu}svtPmo+9KC31W

    $o@tJi3FlBzpV(dL}+#& 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�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�th?Fo$)pFIY?uGTqipk;NL@9xuIRU{(BT+5OraZlWM$9V?cW>NSP$)y z-NpbZ4McT+|A~+!^KvGzSe=pex0S7mdi1UYr%LsNH`;o1GsOKy$M;1@FBW77N)H6X z)Q{W!S)4TFj5O9zSv7;hS+D5CCZ+)+w)eZ zZ!NepKS%bb21pGcs{5Nmh@-mc?(+qURUBEOm94sZ^pXUpN|l8-+Ij>U;)d(^AcTCy zf_#V46~Qodl!UN2HIP%ay5W9WQ_Wx%7PB5Q>sT{uvzR|4vynBk0gD-d%wJiM76^%E zL0SVu%XWNqtFENJI`KFby#p#Fn(N|s>lw9U1xvedR%CB7KpN|tcMn2#nwN7si**QD`>kw6>Cul9oO+a;hBw-JoG`?V*6|k* za+U?Tj?!0*N694?=RR`o7;ESkHUGC*%ooUfYR!DiV&<)(-vsP649AzI`I^Oi7nyI> zpzjfwr~C+cp9Lub5G~t~4+jX&Thd)97mVqjy%^+$Fe1EduY)%`sTA%o4!IgrIlL)J(uTfOw?69`U~ znhI~U^_XOc+gr!aLdbL$WFbn=1H)8TGKa;co$+=vPqTqPZ^4ThHh$E7&~@cH5eH)2wlw z73?_%dtx2z5sMj6Q$O8pH4Ue`RtB$F%y)pPCG*Xi^y!YJ`vC@j&j7)_RtO>aS&(7~ z`K+eZ4M1D9A~mg!l0oWkfA_S_xE&!OsQ$Q z`%Gf7<|1pBm95cw^hE@xN-cvo+IlQ8#7)!jD-n{(f^0zPwP2V!N>;NtJCL*0SVQgA z3~pvI4TKXQg*D~y3E&s308ZTMF-p63?S_gZ(7QNfCx(Xw+pfxi;i&+$yS~82U zAPx*(%mBf?CLqMcf|Nptx0cmWqODqqT2@ENBy~mItkA(2y1YU+9wo}2wcE=X*qFOf zb@e42UYAbqR3NJRdjdkn)-@d^X)M+>WKFJXVQaP?eKx_VQVZaXwjOg0ap&mxr3hKX zf~-X8OfXCxCCgZxjmTM7*HFrx)eNp-F?S(zyEStwi+Ko{`>mOKSud%$oVctnr8y?9Fh!r~|?+7tc48z8vXzCcJ(7Q~GZA)LKxT)5RyvRGYFCo6Or z3|&g08;=rY&)VU?oyy4F{lmP3sv|X9fES zgEh2f);DX^V+D)CU`?%q{mNptL}rXNvpI{|7MNNxTd^RC7`(j!f_v>Rg#5vRbVbO2 zxvW~}U#yOj&FYGFVukLDp?fKG<58mQS-ZWbfsH$JJhI0aAlrbb?(b;`nQUIpi7eI} zWX-g)wNH<}kl<9Qba88EeEe!_x$iNQZN zKya_|2ywC?B@yEJ)#?VIty=M4t&Wmo>WWIN&_NjbD}`=6N|Zfox0f}rF?V&5UE2UT z0Yr6wH$q7LUrl$PdMwtj$okpJ)&)I!6v3%dG4MuPk7kCr7j^t^2#I4sen;uHV3_&= zr!|Yy5jh=ykCGeeiXLW#zKo$Su=cFoe$K$go%sUUPYsaU z`sNL2f;WsNrlaH)i}en&-fUuV!adfbe?V~RQBnxrXzP)`34PyqqT`Doq%aHeB}#t| zhN+|EGZsfe4&TIZSG=p{-^F4EB2%_zdRWXLWPWAMEX!hki_8ivNL7SXWbqz^(;b6K?>%BC~@Udd~9MZ2*=55v%dS$o!QA826X z&Rl@(xdup{f}|^1hL9!Zm#k_&ctJciREap9A-ey6bAmkwnVr!~r z`=w=3exOeLIg9=-(6wKjf2*nK7V}0^!-1@2F`y}Zhrnh12!j={W`1bac%K!l7zX>y zI#>}FQ$VK6n(1IMJ;2mT*Uf?iVsP02!M*ksLdvip-yx)8Q>z<*wrU|wt&Wm{>WT)j zLf693)fKw&2OMS3+U->hY+S-PWVbLt3IkEy-)#}n%DkNMELIY-ez&qE=+Qe8oGSG% zywTR9lOe9C<5Lil%!2er>7HPi>Pot^ID?Thz*s|{s2S|XVx}Q;q&0Imi#ZvY6Rerz zSj?HooW_F8N5~u&WEnuTY%j4a%Hrz87qRH;P+_&XE>>F4XgMp`4h*){nz`Amv5^(* zAO_oK9c&Mac>Su6*#ibYtQa6x)>f#B4m zqy)Ut)kliJ1WBJ{#H?)cm#{y1{HoY*F{U~8O5@K{fWVnteFXB zjrOcy$r!A&b+Aq>W-2nfTQgHw%>KaClG%p^8G^wF8X&mWMj~Vw3o;2I<8xWHvC5`1 z{eV+RUC}gF=s6gACTq{y?b8ix+?nf;z1jc?)i>`}glsY|=LQyQH?nqE*{ZEaKR|Hm zQF0XCXzOvv5I0Q6pG3%U7UTj-pEVvOr&*jE$hm5)p=xUWFSD2rk$KOWd56V(iOgr# z%qJ{nK%{>Autm~00L;@n2ziqQDF6^H+aE+)9VOxF#PhM}MNy$hr0Ev(airlu*0T5! zE0}=6T-Hp7S>p>g%f-x?se*Qz5Vlm)4W zkUF`nTJ1=yqojelqP19|f5Ff{DRkoxILe;2+Z!3!SaJU$`yT`3M<$MbYl(utY&a3 zi@6w?3#^&*Sj-j3%&=yrvzY6Uxtaypf{=|Y$R2=b+1_bclr7bXZ)eeup~7KvT^zKY z(SBC2^BC-mHS?5N;{+?%4GebGI@o0v^8qsNS~G96n9qQzCG#;0@*0D`FhFpx<&Dzs z5%wth9)XY#5b|D>)eS&fwRfVdj*`~uioV4PT?9iHR_Ml~MA@@;dm#fGcV-x}YZ)Nz zfT-^81_-GaWxD&+Ww9C~>qjeFf9laA2u_u14sW#eh%&_eOUJiFNDK?o4y9XzVd^OP zjm7yBIZ085`|0m$1`}A!WMp=>W_DsRQ<2%-nwi34_D5zP7Gx+w2C*Px0HS4klx0zN zQYSuwMW2QWlg)K8(RxPXS-}=yu({UE*=CKItYDcKEZsWT5*BkEGFMwOSF)H}fT<;O zBMY(#RH+Z)jkX^7qUl4qkBf;GWljjfqKnKc@*g2iC4X4b)?Sj;xa{LPx# zlEq8}rk2e1EXZFN{0{>J_gZI!{LO;&L`b(>R;{bD=}h013|3b(nH72vhVIYWvvzx5 z0~>ed6l6~{K!)j?cQ!(1n3r=Ji?tA0^Q>%*)uX2qoO+b3fH&HDWEkR()A4H&vWf-S zg3=p}N6C5?XAg3A8f$2Tn*Z%A=22uGvSuD&G0!0Lq%|{(#k_>f^DM{>gj{7o9soqk z_Fc=OoTyIxHjDlW6`q^x;;HqF9z--!6wcCRXY|MJ67<~!>DG7hEFz%ca#&L|dV8geGb7)p7Tn!$-I=6qz%v1ZO< zF_$58i8XT(i@6G!%UO^O2wBU5>;QINSr+Afb>baa^i)*nZmx?I z>lt-n1sjaP23RxunKk;bf~8@wk=DV6vzU{SIl-Daj>Vh_Of8wySde)be6|6Cdu=g7 z7O)_z5VAa%Rm-qEN)D?ln$8Nn1w(IS?OD5hy@8E8vp}4F41N$tpH;{7&07Q^h2u;| zNg)>N3uG0IvpC`I>d`rZQ;!liywTP}FvPv5<7I@DU_r{EbZIb59VMk$oQlW^jx!u3 zS!({jW-+TFvx+sd5{p>}ncrJ8YqFRPkXerfX^fB`S&(ReXxWa4v%0@MR43kqMQ?=) zEzNZiYdxbDtYCj&umo#nd$UGcRuxj zmKfbSi7FRB-_S0b;MZVHl426{$aW?2l|)*RI_W(^AO@RZyD1jM)}OH zmEJqb|9d3QvqW2~n2to(o;NQPWm29zFCl&hTh})Mo8RWNCAWY$c6**zFsEiQWpV^j zD$btgDNL$$oIY0)#h&LmI7<2}2il{eA1B%pV$^>MGl!G+1GN9W8DN)^^bI5=S!RXP zF6Wr1mPBWgIV)c#v9bb6WkE?<)e1Q(ry5zw>SU}z#+qdOo{Y807)HiAWUNcZaBU2z zN5&t>_4+V^WE?cL_!$?taQ;OctW6u+m zWNW9CUyh|pRI8($Y9;oMw#{>Vq!mti_^3r}j?3y!hE;qspY2`s9|g79-b*N4_}a}n zU2bl?S1EJgSEU1fo7VOXo6Qy)(xg#hOhRIlzhV;F{neyuOk%5~cI}(|7@zn@bn8Yj zvGH=7=tQXRCe^CemTT2&@>ltCP3p(Aj)_i;Y0|FQZ%xA6$FxmMY#kQgEXT`|?OQan z-Md@F_EzC9dpi3#dpRFS>CWZO4Cgra2InE?PUl|dZs#rOiSvc?ne&X4>Y5>@xyHE` zxt6+axVmz~`LX;F{v>~lUnphqqokR_0%5k$#l2D3A{-a42`7XB?o+~Q>5Q;JIwzcz zE(jS?7qO4nQ=BOE7YB4=oS!8z4A z)0qylSnk{abJz{DIOII-yzP7fvv}c5b@g%$c4_litj^@7>$dBT>%QxS>m|%;8MmD~ z$=%^ncx8SI`He8gV|*6O^A4XP3>Rj?9OuGJwOO7JP6=m(bHW9f?=#`K@IrVgycUwh zE@Fz~;s|k+I9ePdjupp=h-Qr$xpSWK< zARZDAi$}y`;&CxcJRzPEPm5>7bK-gNf_O>1EM5_>ir2*J;tlbZcw4+9-V^VO55$M! zBk_s&RD3SJ5MPO1q#jZ)X@E3D8YYd9MoD9&vC>3ovNTniANPDGy(thcHbWl13t9nd2E}fLlNav&r(naaAbVa%*U6*c1 zx1>ALUFm`JTzV?xF5s?&0o{?osYB?s4u(?y2q> z?wRg6?z!%H?)mNo?nUm!?sWGu_j30N_bT^l_Zs(F_d54__eS?7_h$Dt_fGd-_dfTh z$;I;8Y)heP(j7~oZqgkY@SF+H%i(#2T1P7!tDu@z!}A(=UJK9b;CVefZ%}J&gJTm^ z+Gcp(0?%9Fc^f=$hvyyeyc3>x!Sim%XvZFSwb!x4u@7+j;mQHHauBW@f-8sN$`QD7 z6s{bDE63qV7Wg^=dMDwNQ}D@Y_~ZN23N0O~5Bt^w*g zpl$%_CZKKs>NcS60O~HF?g8pPpdJ9~A)p=s>M@|60O~2Ao&oB)W02zoAYTIV6(C;& zGTHga(Z%`L(bf6Hk>Y&n=;nOp=VS)%nWN%lX>T+nEeIu8Xs;GuhD( z9{rtNVgIE#2Rges2RXaLPVC_v;_T@h>P&SGgWWmY+1oh+7$bo(%Gu93+S%Wk28=Pl z7z>PXz!(pV3BZ^Lj7h+l42&tjmPknZTL_tl7Yt1FX5gn&%wunC~3n zSl}G#Sm+$(SmYe-SPYStK%}J*DIFp$gGd<=DH9?scg}FGfX7Pb2FEIhxEdm^frx7% z;yQ@99wKgV&UbEfE^uygE_7~oE^=;hE_QB(h}$6Ic8ItGBJPBUyCC9jh`0wL?uCf^ zoGFg|@HpUH+QP2^>JP0`ns-h{an|%{;nI`0M|`!pz9Vl$aR|=?7G7Z zaoy#Hy6$nqT=%)*t_R!**F$ck>k&7~^_Uy&dcvi-o^oSc&$zL!=iE5g3vRq?t#blA zCc0j7lU%R3$*$Mj6jw4o)zyWc=IY8%cct(%T;2GYuI~ISR}X%+t0zClmCDa`_2TEb zdh_#LefR~gzWhR0KYo#`Kfl;DfM4Po$S-vb;?v==%r%(La1G%zT|@chu3`KN*KmHN zYXrZ_HIiTL8pW@1jpo<7()e|*G5mVhSbl?R9KX>up5Nq}z;AX<~T%z_d=X~5NAKcIRJ4ELYzYo=P<-M;+n!Abxq}uxu)^QAx;*= zIRSA_LYz|&=QPAQ198r}rt{|@&UuJ)0peVQIF}&KWr%YH;#_sj;IFx6^4DFn_#3X- z{7u&!{uac$?V8Kqan0lJ!s~nRxDSs9@OTK1NAP$Ik0siIE^Q`99d)9CpJZrg)o^{+N&w6gN zX9Kszvyt2C*~D%0Z05Fmws1Q zJ*T*Hp3~fU&l&E5=PY;8bB?>@InQ18T;Q&FE^=2rm$+-5%iML(74C-TDtFU!jl1Q! z&fWIh;O=;Ca@XCrxVxU)+&#}7?!MEj`QF}Md>?ObzOT0r-_P5Z@9*u$5AgQq2YLtagS-Rz!QMgq5bt1qsCNiI z%sZ4H?j6RD@DArkdPnf1yd&W;iXZJA&8Kz?k@pHZN z`FY+2{Cw|1et~xpztFpwU*uiFFZM3wmw40prQT(Hx;KMg=FQ|YyvzAa?+SjocO}2V zyNX}wUCpoZuHjdE*Yaz;>-e?a_53>T27bMFBfr7BiQnkm%y05;;WvA?@>{&y_^saU z{5J0ne!F)kzr(wW-|5}W@AB^9cYF8pd%XMjz25!&KJNj3zxN=2z4=snCI@*d$2 zdyn!*yvO*X-sAi+Zx(;tdxFpMp5#w>Pr>6ff6{w~Kjl5kpZ1>P&v?)CXT2BrbKZ;m zdG96ug7-3i(R+oznG^vGN3AoIFt&FHaIC$diSM@)Ti`JXM%1PZOrd(}k(>3}Ko)QH<-@`r`G~MrJ}T^!j|uzb5Dv*Fg~ReG;fQ=%I4YkJj>%_*jp$H|58|E%}LXTYf6sk)H{f;&WlO_(E7Bz7+NZzY;ca zuZ7KAviO|uA`TL|ii3p|afr}O+#B3o+!x$K+#lRiJRX!PW(D;UPXzTAPX_f7PX+ZA zdzI)1kN)Dg&;jE3(1GISutDO4Q25C%bO=0#im&-$;=$nI;-TOX;^E+t;*sD{;?dyI z;<4Z~@p$kUF)Mhicp`Y5*pC|zKj}<>pLF17!q7?Lw9v`omar+}^icT8D0CV;ri;e| zXNXyWGvP5yToyQ6%m|z#E()A0E)JY0E(x43rhT_S9P`~maqM@C#6_;f;$qhlafxfG zxHT+Y+!nS>obz=C{1lWaj(07GpLAA;ui>Yvd0(#*v#PBYPgGkYj&`kupKjNQV_fUS zIi)vd& z5jO?y6*mX&6SoBJ7wAdxMgtLt$N{!(m;eeL*SG{-AEs z{xaRABVj$HqhURz13{_Mv9Mm!@vz>~!Jt0Up`gCffinH1!$JL}tgr#niLimvk)T1+ z(V)RnKgSU1hCEcdSaO(jM;2%OU=}gchcubbI$Wx@NrKd_qoYSQKj_J|>#|&wpccwJZF-sccm@N%<%#nsT z=1S=$=1Dgl^Q9f~0%?2TLTN|fB6uv8hB}r=!yHScoq_4nuE1r|?!XLbPhciImP>QI zE2QC$mC_!0m9#f-wX`pA4LsILBOL3bQzh0*`vW&f2Ld<3W0Q2c#AfMv@D^#LW2-d7 zyG`or-7ekm?2z_*cS@riyQC33{Os%81D^Iui{yP0{QM_f^B$1;$_J%o-a}Hld{{af z2tN-89)-s-X*GXbddOu-u>YkKfhVPtfv4bcT6zxOu)J`dg~vH5jXy7?IW9;myceY< zL6@X4j?2<`{t8^bDvfnqlh%8#OKTiAq*VDP@NP*jowwm}N4n^^E3NU~lg2yl!}SN! zE9XOaJd!3l9!qOWJdrjyo=QXcXVN6cb7`RbLYnM&DQ)+@lD2zZL+oVtslYDo(}7*# zk>b9|b#vb>+1)+G(ZfB}(bIjlM5=q5qnCR;-y0r%+;=>E-7h`;+|NAy-IoFfxGx6| zgvTKFbjM(KM$iyE7*F?(WL3a1Zsabnh;)%Kg;4+P#Bc<37Nzb;F(CJy~Aw-otNjUoO4Teb=$c zy)tOCd%3*D{lc-;y~wf6eay4nJ)_(X_hQFR(Axz%yWO`-?r~o#xz~L~-se8&{mk}p z@-Ls;Y#&xqenF#Te2Znj=e56n4c~FuD#gY`CzT8g9B8v8YgbCPNQh~k)FB4Gr~sc{lJsu=h(9x%)MsBdySsTlZvQTg*0JOb=T;k#`5kK*Co zQl-lTmkoB{pVD6i2Y>x_xvzpt<0bV)>A=A9<;y!9rQxHpFghGj@7ipyU)yahdi*#3 zm&l-3i}OuAHoMN8w8QBxvBCN~!Fg zS8)FUW|je0$(FxT&crLYC8Et%Tv>q}e-KBKuY5EB9w&?E0KrSdkp)mbU7BFGwJyQH zkws8G{j!(M<{V2K#CT*O6kK2UtGr60QbyT-6dWW}R_ZmrbxcBt3%+o!m(VUQA-avD zI$TL~xc>?&U%W}3_~r@i65GWlIkc~y9SxHHXc6D8NtwXX!A(NjwQ2K5+xVo8O@0h* z(y(2-)`?B(G=P_-%attib;&ZprAr4kX%^qMNzHbNNk0dbSHGlgUZ!M=)~#KRkHL(b z)Uka`i}=XJ&32RK2_4%fwQCZc*tT?&_FqN9-@24+Zj)QIOSH+q#M|Vb zY~|qTXPXS)c_*}oPr~Ei0Uw4pD`S(Z)r42@kDALhI@;vw@k!y$eygs0g->2rjZTV& z*X{m4ehW`5!guo!xW)g+z}esQt6%TSH4@8~`MP`%Os`&x_~^Jgez@cR&N-;CI^pS+y&(CsW& zu&VzGT9v5b1J6#)`%S5&?PVG~taW|F_B;i5f8+NAn#H$MW8XYhH|vvfj<88ZH*~Vi zT=j3kC6)Y+-MVFTVoNo8scz>wjBS!px#EJQ2Zk)0IHTZV|D(fS1FNyWbHqIA+$7Eu z&>`-=4^g6{z^wEj4`fPtQ3uekpR}tv>%1Y#QUYK>JqB6TeoYcblGe z=;D^Zz%E-F{1xAC+Kqxu!u^h}*jIxmeb(z?mmfy|(!In_1t z2n`CY9rk_oy7j75s#m32y~_0~*CFtCl*rGu$Y&597+SYp-71x9hE^gl`via$SN@va zRxs<6|8pWNZ#((zb+=ZHJYDO*IZrG8Q?ErxANvO#5^OEX#7F8L;ctQ8cpJ{zS2FF>6wxn0PCQ_8u%Nq^7MpW zvt|A~c}i-m)(JLUC$eqKpQu#~Sceo=u~xvU0IYXf=C|efRAaTv!HP|YiLrHkOX>e? z$w5FntkC)^w3;!w>UxRGn^{Ulv&>$=_ zv6W&H*zhYIKnj7bFbml4+1`zVkCd5w9jVM-{TqB+aubLSf8MjbpZziZdXz1>ss3@5 zC}97r?BTHR@Y;>)MJk;Xi4mcL)`nDWP`7ksl{)nrG^}5%ZVk}?3Vvxojqm*-rbGKk z?blHvJCP|5raEnJj6F}&u;wOso1A8vA?H}M4pzKPO6BJtyM!e4;{ePZRp+yBVd78>IoIHK zecrD=X;iCj!@4#b2ibbhCRr9qj)W!X#E8iD3Gp4GlVT#_H=wjsC261KZA-ao5fcN& z49kxxr~=j=sn$+@k{JJYOe9pdCZAjZtafM@-y-L}D+zG;lXoH&7ItoA^ET}xwO_Bv zt8L+00DY`R{;8>2!wu^;gn=z%lO#rgRKO}rAUy$l67qAsRK9CHj!{MK|_ThN;g2fXPZ`4 zMQCY>Y*@KUST#r=*#z&|F2`oqESwELRttke002FRjW2R4kUNLAUyA}FRh3v(Nk2GX zQ&$a#6C$#Dqq?CGMPKQ=RPD#XO1EhDXWPiu?V`bQ9xaDsVN$)+cv;yeQnmW^BZ>8@ zl^a%ukb40Jf8MkGTSJ{#!^W!LuKIEIVF;|I?x#vvI2=_us+|~m&lY7^^c+@b~J!|dH*=J^;7kgH41f*r)42lAO&IS643eUa={mvmxm21eZ&*SZi#qy=#Lk1nMb++HflD(RMXOID|})aXf= zYSE@`wGr>?7na5+(_%1l9!T& zYU^sv=}T_XYPVX_6V#Qc=BxxN9Vw~q3_O(qY`LYQsi(NT{^c22)Uo=C+h!llbl(B} z@wmY$rPtiQ9F%hR9eG{Sy5#j8a?d?@#92Ju{hK?S1uQdXIWAYNbeAh54Yzgo4igRd zrrXPMXV|PERA{Tj4Pl#jz`gjU&%yG@z7A)>40{__QIdCno9J$zgGCnkJFe^{&bm4# z89W2sDIB1rM-6B`5#7Wl=iVXr$eFS3uJ76$`+K^jUFKz@NB17})u)4VUvz5Ee&-^O z%NA&}!0s(8!QJ)fHL8~0r(TkHFBY@xB?E01+Pxg~?%b#|_XDS=%Axzp&Ie44tgR8! z9;xz`LpyQj$n)F*W#xY8bR7;o8uiw006c>A#=Cj(>!IRM@i}NyZdy@zc2T*?q4UdJ zqdcBVUA`k_+qqlM8?CJ@?a>!bO?T*?)&(zHUD^l0E}0=c16h~Kp=wG2M-6X@+d~zn zT^KQo6CRul^&)i0bmD`aV^yf~SxRY|}*`lW6 zufMRT?entT4;0)zq^ui!To(G$hF#@1sZm?|D|cpU%ZBV$7=6fYcH6EHWc}iprsmJ_b8VY>V4LC%G@|V_dGmc(=hZ*-=t=Jex`G(LF7?6t=qU{_trRb(nwc zwmVOKixI^|caO@U%J!bbh|0U$@N?IBThB-6{oXfjuT5nkI)y;B7&nqFjrBN$6~edn z%1rRw@vUm3CsaFJfklz%CnC1{ca2GLQK*|$<9!~6F_hg~KQ8s1-F>E<;+wnU;Sa_{ zpSV^It#Jxi9!c_T!4GV(1^4#tcQ1RROYbl%hmP7$EUvxAeP&S8Im^i6LaT*4e=>O$Md!@YWcr+d%w*wUbeMD z?xXJ8fRCJ+xDikP?6=wKlnhL94!%QfiGSvO>lC$ayBxi^Z`da9i=X=$T(&o@E&hYO zL{jB|BXV&BHVD*Q?-`+dY2sH=6Paue! zo)yAd7wf0qT3R1`x`$9ZbpEqVm?~GV>sPxY0yFNXq zl%8m>+eN9f6v-Xjy9vhQ*81aYJkEUP4IFI!oS<`8Zj2G_vx)0dos>OZML+T_+k#Zr zWt01`S3UZS+wbzMba?16?9eMM)%zxTSQ~U^KPZcu5?Zym^{fP<5Ab1N{h!Ucg;?#k z$f@9@gC*`U=3dxs=sc9}0XzHU0?6AYC)z?pTkGH4vE z*g$;DEX7)*#bLXb-?AMa=iUV{ONZUv`w)KkV2E_yC^>IkpgjO@P{q1%vt9S zNv+k*-!BnEaQ&)Vxlsd=&l$SpJY;>=FnG`q_x-DU*tvw6tSH8#4rAp|p1+Db2>x^% z{%r4cXP03f^4!FN{qd{6Z++bFibUExJOPkEx+oh03})OQ9$iVFJc-XHv9W6bwI z38K0`x1RLvm=awiP8PdOZZ;6YY-qX7F=z`~--P0^rA#1uq^k?Rhtfosg zgx^l1_TBkzlYD2}TMw4-$?}cpoZkE5J3m7xP<+=2e*Z!k|3|DCS8hg8sA4%hDySIs zdPTfG(|R52U9keb9VJx$Ec-|IE8rVW@Mr5gOz<75ct(cbBoMAx9^F;P6EXA=jw@F& zE?geJb_6e>m)Ur+LI~ILmE4Vi#2@i>I8>opc5$%<_5ba^tV@dHYR8AN;*0+cWwolB za~?i;ytrcdM#b-1NaucXUZ`4Dxj6}0;o=wZ_09NSLp`i(=OpVdBg+y(-OF_kH$}`kFQa>?JH8q4%$WenE1~>J zg7}!kyC*Cw88Mp z-zSLgNc0i6!Y;GM`Ms>L?-YGjVL#H8BbrV5ufX{wLHtZOkGnWcESz5eakvVE$J*0A zHoo-d*jW1r3(*YgFt83Lh~EfnEFA((EvkbG)o%)wb1WPo97Hpm6TtZ^LHtQL6Qgnd zQgHs%;QUQEh-Ntd0_PO5yyULfmDb#xQlwegoFM{4GlICpbWtwRITb%n{P+6!rl5Y4729&Gg!#l?xD4zXpsOV!4LtFItk zEOF~7aBLYbB}POu#-?Cwk|-Jx;K=Bm)kNWIq)<6ib_L-en&GqnPP0TI2xoLOPBR5Z zXmDB*4x$;(b--y&EVH6-PpuVYr=Al`7285FLW;9#^tSbiK+(^7T~A|0G#hIYly4yA zH?2Cgyw3Gjo!+2GqZZ4&PBIZ7nh|sYL5D<)h`ERv|Gl=Uxba4VHuRIQIdhjA*8OAC&J&6nBw0ckcJdbL}pL15B%I-;8Ty zAmJdI;S2#z5wURRUWCQjXw?jsOFH*WHUX}Y2Z#XCjNp+(opUb}8%kn`W@3+HxWj0; z%()N4d~dSW-Q(PgO%+E%aX2Y5=RRDc_@t@g7$}ZT6i<;TckZKQg*~O{vkH5LrX101 z$|nM6e4==caJX|H4~SLPv`gpyTx_i82@BB->lI+VoG2y}7IW?|D^!yeD(8kim2eQv zaNY#Y^h7a@aF}zSuHa15;LIQ#L^GV(zp`#Z4- z-Xj7;GlIn+Sd=Ih5(IPZi*Pu8X&sKzxi3_x9H&!iit#BhRwRn$iDD^{Fz3EPZs_G8 z;CpGQ!sJx#N}3`>vnl!lZ0i%nxrW;j0sXE(7h=e}D}cItVL zsp38;?j=R$-1kD!&wA~ru_Bs{^>-*AAZ6~{4=B>8#WMSGkO&aX2#$l`SfV(ZD2@;Z zckajdu>$9Q6t8?`9W>IpABoL+f>;sFSi_NYaVAlmCQ$C&&v?yY>1m~20KL(6?zl$E zMV#j;h=H(PbDeuFVAYKHJaexZDH*ZVvJxKWegP>Xnkiol}T_ldIW-K2GRf^@kGHrdwis1~a!AG!wfD z!@Yur%RKuPnCTtXihDe}FjZ^;#b%_)JbN>ZVoOuS1Snn`5!a9?_w3io+PX&3$LA>c z+$WMqlZ|LL+3f++E+X0z2zTr4AU}dVXK$+mN+KXcGoTIt%7}&sA{Ov>DkPgbOHmoKvxQ-}c3jNnZWOpl0Z z5%DTP&G_B{-`t3pO>o?U&-I$U(%DLlzzTkA zdvIJM^9c*_zhb50`(ASG?|B*3CS8nd$vT>$ zXp_&LO%se5e1hKt#QZj59zk%AJs;BCFU-@yEFc)f;4n)7v$%~|L@>->FIHFf>lF&hat+E#LO~3UvJNO~h=cp;HL9$0#C%4&h{1I?LiY>O z<(~Qro$e;mMGUUH4Z2&~h|MI;{Pb2FZaILHy=}xE;^IDfpMtYjqV7?_oH98;WQf7Zj)Lq+ z8*zxRn1?>1P#scP>`nV8p&$lF`3ER}w-Lt)h56^d6_n!|lv9L)7#tMQKPM>Mhx69*KA8i1^jXi{P}0{%hh7DT|jJz!PzbWTfMfTE`f2cTn{kJpq17I z5;rsO%0Jp(8P`ZWAtC-(q>b0(d&EzL=zGNLwM!Ru+xhtAy6s9v?Dg@>_1igRf@r3E z8I&8e6Y(U@J#&M0u4j%{I8ZnHZ10L|q!HmDn&DgloXd%YyXVW>m5e;-bFq=+;c#D_4v2l$w9D@_NsW!wfv^zGuxz{w#N?zD3h zX;wD*M1W{U&<_N+69M(`0}`<+z!9 zO)(w>#*lWRsGYc4#QUtw~p_92=gM6)S+0&I`B6T{kxp~S|$_~Q!F zFo`=p6(F|uYa3&E8bLW#3Wv8BBGF6-k#VMr79QqU}`dP16X{?B5W1SA=X{5|u`ZPrv zwOD39-XH=*GlIDwnB7ji)lSSL4(`-v^J4{m{Vlxmmvzv{?=+bin{^(sBAT%-0_(zd zVgZ42=f2Qu4oep(^#bUFwsXfd@*!a%{#UGp?cv;4yUx94Qo5*-B&sGk=6!v8e6Rlr zeCzsS*0-+Lz;~pNxD>+w*xw!fPkd=ryfVsq<)r<}N&6=qOD?s3(h=9l`ALqgM>NB# z1FYJ_w4uH8!-wN6q}sL;$_bG8;lmT|4C80O(HYN1_+MI}}T-Id{$`x%juz;vE~8sku|j|%U1m=Ku8}8c3J}ev;28itog_*Kh~KiF2E=^2 zWtGGRdX|6?&48W<(1av0j)3?rYeE#zxY$515D=mn(8~atOf>A4HCX|0Zdp@E8PQDn zH7HLdWp>M&%9Z7*HI0-J&6HrIHex2);-^T*ac@!YaznF7oMz?>xU zHUY3()|@DSw>1Fom;x*Wz=9<4E&;Gx)`BR2cQpVXm;#gn;6qYpx2zAL7#(WfUr_urN&G>g{Fe16RJYJA>kowhG+XQ`z%_E5rU21w z3jPJqsU&fdfcP!z6d+d9E$d`#pfd!7Xa;n4GCpxl7Ul3yj#$5OiQlr~lFNX~;m>@H z*bG%jrVnD14S}iv=p3S9x2$s%0Oyufm6Q?9rlJOvtC2FhWmV(K^3*zylo8F8YeV^h zWN|);vs=~$5O;4`=i|@Yt$pITWnE+na0vkFC5yTQz;0Rfq5$e@0OCyn8Ux_6WYK^C z*e&a_D1ZhUfF`B@R|23Zsk2*FQz%B&yxv7QZEwnANAsOHGZ`~N=EvvN#qs@QEXoYWoZD@b{>n0#u90sD1u;0vPN3`{ z4*oIz4y?dlYX!zf{lbV}ZFO8D-;+9GaP{5Ex{vV7gnl9+#Na}EG0Z(QO!o2p9?bEt z);fEB=x(bo=csbq#p(zlW zq=-f-q9IYRkLH`CxVL~tQ0IH5p~B;o#T7I)h{30(6}VcYh-N855EuVgzJ-F*Ori<} zj1|r`#D^H1uPyi@DI$U3*hlgag)KoLa;EBfLO~3Uk_wdM6w#hg*vIk73QBtoN*bXc z21n@#luY7aAH`=Xs!r{8GEvKdS{G7dAH#QnnxAF5k;aG^e2m?p+Kp8CNATSgS=3#b zeds~zh{4r!q24=1^hy!85d;7Dy*EEL@bP;uymHVwNaV-wx5ehnBTmHNoOgh;Fh%qw zNdD1#A&{7%EA6Y)2Y~ll7SFmy1`rZr5Twg(hy56k9!(Js5fXnO^eB-2v}Q>@5PAr& z9JgMHejxO>?K*LdJWfc6!I7Q>(g@;V4}(TvKK_Qd_hHZ|6SZfc_H>FUAwm8i=xHdP zp$9=FiaJQn*h9xP@+=JIwtfnX4W!@L5Rms7-K zg5eK&}S}$-G@H2@#iNRpb9+?ede2pe*p3KQ^b2D&K~%@A0_^tMtqTp z_)>^3NfC=loIUJW5+%M^BfiW;{1b?OOv>y*&&N=UI(Ot^e@csu7<{qUL3K@vSVh9@ zAc1hgMK7xtLy>K=Ng2s{yW0|QnJDi*|(p+ zfpDDk*#n;APsGR70uh;@=c;iiG(Co`0ofKBX{#XLJMWd(3c+ zgj1b2oru9v&IU?cs`HMMKj4W=EgAWowF1!(c*fc4xJD|FI%073%Bi{sJY_;vNC+{w zP<0IRTpA{Oz;kYD$%t{*I(r`Q)G$%21+|)_#vbt0)TmuxqINOV>ZFR=B*-7|)Jb*U zE7n%DSvA$8X+{h_&6feCL8^!+6#jsx0RTo@Q!O9x#K%TzL`aCikpz&gOchNDi9O)C zQXy)p5IJ}As|f`$I7(}vv`Q5%2!%c1X{DgF(4bsPD2TyP+5jbyIQRpeL`9aBNn27! z46dF8^&3c?Kj66`wt6zDBL-LR0QHPikwyUQ0Z#@Fy@}SLCm-;nDMZejz;lz_v{_K+d!~!R<5XyOni|C5Q{QV+RoqHk`~gq4g40u?-l~AH z!pS8*#Nd2|;Om!T1kQ`MhP5QC%K3zWN4#hrx09`M|)pxmiJxsOl~ zgQE-v${^xk4|oPCs!r_=F;ROMY7decd%*J`)ch>dBQ!?D;A4CYs*jQ?f57voB8$2! zvk#AxI%0735~z<#6(du{aAM#Oct-JK0}psc;*}SzgG4^y86KN+G;tyZ=bQk}aj9Y~ zLGlMY|2_0M6)UX5jeY2#ZJQE4ty6NUa_WKI`Eybv33&{q8ZkH zVEvjZejzO8!hcn$eo?5L8~6VR2hj}Y2yhOiir)!`Iq^dZ&hHwWKL`iW4Cgp-ju8uY zQS^^3Rt5pzOO+HRr)sOGInQYj&8Fxguw9rY zYNd&q#KztEg$hzFiCa^FV}(?Q7!l1F8-OuBP1Gkq=FsC6zWNH4Gi4142hj}Y3gBFx zCK?kCbLp2WIE^(pR}v1Q8BTNHTum&@sb8%qJ5IfYsbXs=wjxF5)>}c*&w5=;V?{I@ zYXr&(q|6^F zo@FIG&V3*$Bbq5c0Oi4HVi1XQ=RR1TYl9RHFuia4W?Ul=5)Psn&ZEG2gjl$9e*}xO z)T)_i=f2D)z%??A2oTK(o=DR@D=!lpPGX2=VxutJku+T9+(%-*ms#uXaqdrM>L!Amw_`mO-v#j?%XE>;(cq{ zrE{MY8*2(-A(~;m0j$^4#A}4bocrqv)oTisb3=cVa1hOK<^bpIG%<^Cm~($y!I`DO znM*i`W;pKwXFjoT=RRMNW@WR02oTK(J_NxBM8KW<2eAnj69J+b!N(w2mL@(T2OrlT)?pX^Ifdrf3V; zzDg6D(!>U0VqfaQ+9JeZ<0?`#we4spkWxiie>1J1H{f{yP-?tk+>0 zE27z0|Ag`%q|BZBABr?;vCMuPBLYM-f`379DovbB6DNp+JNHxkSb=jtiC0!x2aR;@ zCt|anAyz~)){5!r;%s~q1-Ucs+|N$;n8VVzbgzK|^itco;~J@y?mR3&421Qe>)h)C z>mp)e&ix_)thKC!$GKlj%7|vl4WJy4f8(3PxpR+CcORhCS2)15&i2i?Mj8?hq8ZNR zz-de@+_^W#;%u~PCfd1gvI%gFG$jH=GXjxL^7-yR++4qUDAXClEfc$%#1PHIT4K1( zNsl@A=9uqI*1CI~dn;4L>!8@06q$2xtx-%cRcr@E{Qh6}pC#kYy{)XUh@#Ib>;{^0 zM6)SR2M(T}x<9POoqH-E)>+dooqKX@tPH|JG{edQR+n_qiI#>r_bv)mCxyznq2EY2 zh-Nsq0;dQ5d2qsE&b^0%bF&8LHo`$P!^r_oHnDK$o~=l;vdJX^L^FchK~O*h+_@LT zCg@89h-L(LfnY$o=uZ&LxevhMxY;@!rE~AEP&rQLZc~gQz$i)=_os{dh=e)!BDtaO z2Lazp_bE(H)jmK|glINJkArO(exFggc$nC@b04N44VAbLD{!okiir`?jIjiaqwu_j z0GV?irSOeZsGKPqO*n{VIOBjbHeEbJILx_^RdAls;EX36L^GU8zMKohw2-XGZ;#~se&V7N`9G1ST)C-_D+Rh!< z$OnXl7znG>b?$3{wVIfib6*XBZ!Ig~aqjC#8PQC6Bb2|uw``C&ckW-vb8WrC0j3?c zZ^kvUiEt3jaJB+xGqG^zz8Q=2qg6A}&V9E{fNSJyB0w}F_*U!O%fxn&7^0cjE(~`k z4VO9hotW?4*1CI~`wymyKSOahDKh82TcfzgRPldM+=pKQMWWof?~@g_SJ7t`c7UcF z(QL~90M6lbagcDhb3Y7-9oDo<=YB9Y)=|PjG{gD_SbyUOQwWPW_rDdY;|i5?LqA10 zh-NtDGw?eSGQ=6eVa`3A;hm&28l1Qc`W*=whB%dgQz66oHWBXJD*%RX6jnCp5CNju zgj54TRU+Wdy=rWN>O_EOMsOhrYGsI;1i_qpt&Eb9d#uAzI`^6imE&}3n_^rFj7u^^ zy$n&8NSJfKB*T5!Q%@TO1c+t? zw}7B~hUk_dZX^!w+`IE*17@PH0VnsA#%?E34hUiV8+_~ohitmkxi5^3RZ3WhW>}v9>*EZujIfw< z|5%|~rcgOI^iK%~(G2G^;H=FMs|klW_q7VnY7NeM!a+2{*#w*o#KN8X21S~c&6h-g zXh!fg2(}ObckWwa6Ko>_L^Fc#LGWFM_?94;bN>#9hOiV)4F=m^*jWr*K1!~tUC&i#;r^t;48pun+0 z`hyq|%@|LD@kECBivXE(KcVpbrBFFj_7CA8n&FhoOc$X{@h{;p=N`)RuHe5Kobs8@ zTXaM-oQl9XJJWfK&Yb(%VDY;lRx(wr3dPE#$eep+DEe8ib7`!IW@9}M%GF7kJNN2} zG-|QTe$*raL^FbmK~N`C)Xo$a5C?bebu!tp0_R>EuZ*`28tL3Gh|OA$SP{)w8-w+- zOwoWqxpTh^Sj-%jHc;vX(4#H8Xk8;s2n#U~)`jKh``ljx)>L9*&V4EXp0^yF$GJ}< zWkfUOnNWT+Q%omu?%dzZbRVEhS2)0Q*mmx?MrIKXq8ZLy;LIi#?%Zc%abC7+CiR`#L}zX3l+0Y^=`- z3(*W~3$VV*6q^W(Irpy=s!a-&b3@-sIEZFA-vQ^_Oz{ojFz5cQg7b|AXD8txn&IpQ z&JV=Go%;`pG%K5*hyc-y;8zg*LIm8o{}P*E9}ys$5gY=+@0sENK``h3I}XQJt;10| z_X7%*LWvz$Zl=#FTtqM!AO zr?DcMjrB4pHy~y1+#4v;sKqk-(TE5T%?Pdr!Bri^6&=Lo#KE2WRUO!|0_T1OUYTwk zG}5_W9-Flpu_BtWCV=(Y4&oXD<<9+DU@>!8dW}*qfPUF_?zl!02@CPRV(rIoZ!8{H zo}BySuK0(hyE=QBIrm9jOGeDF9Gu6wztq(^ND$4GUxV`0u3`#_bLT#_tLxmSC>&rq zZ98{dBhv^6(F|t>aNZym?%dz#S~7BuRWs4feXi}?agEF*0z@-{*Lq(re z*ixEuM6)Sh37k*5ijN70JNHijahf^zk7Hx4A}mBRtS^AIzN=VASj@SvSE$x0RL%{3 z1K}W=;cNxY=C0yP!eP#Rvx4)b2Ip(SK{UhJ0i5l`!kzneMVgh(cSL|_M(`sDb`b%0 z?z>_W>?Q(4GlG2}*xOa?AqeK&_u_DzZyk=(x$jY^9H+D26ypzI9PTO(b``%733Kj; z<%T{80=}1iQ<$8pJxWuAXf{Qsz;?2$IMG%7MQq%;pHz@eNZh{^I95ofi4oC^@vJQT zil8hJ&hl~Y<+Hp~7RD?5KHyB**;&s0AJGh_DsU=iiAsdSoO@*jr;-NeT*5&#!>I|J z8pOh!dksa|sps=e6>CHB0#ano{Q@ZZS+9#|tcYe~tq0}0q|BXrT}2wTSY|)!69J+b zK@$)($`TE;#HGZ+oqMA!cC5g;H^eLNTL+DF?w7`9y_{GP%~)H2wON)B1j?OzGhi`u zSSply0rVW(x#JpXNmz*g6{~kvR=9)xd)NQyiKDQmk83~Nvt+~~%e{GA`_Z1xu0;&4 z`ZrXM_Y}uSm^=34Jzd9sOkn`eV%sm{8aYWQh`~|L0Od4saJPQCXUWLrR-Ht<^^a|J zTqB`g&O{&vSC8wZbLwS6XOR$MaG^@Q@V&adoONa{y+SYi8`su4dtCZCCTizGtqQ3z zhh9aaR?S4M7Sw9?5;aJWyYrg8+-jWIPBBT!Eub?(FyVym|yb;RK6$xv_KOSB^Z=EB?e z!aqT79eUD*w^N85*OFp_&>09Fdx^|mBAqCh1Mes|Z6?(Do=I1DoC@tiQ-c_MYHk5n z_g@+)gOWb@x+HZr7mPK`4m9QSJfCUBtm0_g#vrQ@i(?s11VJKvH9Fdmz;OEK?DU z5i$4}AB5@KS?e`eVMkHdbAR1t%#&VcG0y~OJz%pLX{^2~Z&VF1tPw#UUaGLujcgQLs=%G<=j z9roK;kgu#7iFVkVZFO8Db4eXBxca+Vhg~N09tj}^7y1Che4mEN9QON|sSs^ch@6}97D7P`j=F*sjk@Kwqd6|#MvZC6s* zD&Q4J2v33o8pykt%F25>?W}}uO?2!;GEZivvsy;MUdQKw+0e3bfvA7`T+1(w!_9X zl0Zm^L6B~?9d;KWbs`?-uscC~r)38`4!bL$g;qz9oO21n@yl-r1dJM7!AAbYGDiFVk(*y^}OvPm5=xO$%Z+uM|%@GKL`Cn3b( zLVYpJJ~T|`u=`++f3eot25`v zRnz@6&4|IL`5~Y@kSzui3U}BK0AQCj)zV=Pj*av%At44wdICs~XNzHk#2ohH3ehly z$hj#GCltisD5HV$RJM4MP?*DhNgTcH9?pKgc;f5jcoBc zQ80%+LvGqPpw9Qq>k5xkp>NUDAO@eB_rNtjTg=NAbBK#O?D-1LJc&9-0b_-;fcOxD z^DP12;%u>q;MgVtcmOMhx6x@8HJ<9QJm+@|$&#NQb>GHs|-mi5Q%7FF5yPi=PORJM2APLs$Bf zQXc@`V>@hIBfk<7Vi2TTZHN62kp3nf=CJ>U_#w*;uqnb5f;gcw}tJPfls4U;+S>b*-woUqo}VP7n(sg9z}s_7D%X2jsr+!!dA^%e~Xg*)ua0C2>bYU!{W#71gDNQl9a zngL1l7FQAybJ#*5x>6x>ZpzIG1u;0vbwFv|TeKn+=CE5UD6KRo350?e9OZhTv>^`e zu-hoItW4UGI%0736sRYWI(OJfvDH&a9Wl6iC#ZMmEiwpzIqVKN^!~99J?XGB6e7o^ zbT&cg0fd`-i<^3jETUiz`)0XmZ-P4CGg%6cQ=zxe)F1|*nmlmj^cLB@MNi`54m(G| z$(E=+6);vf`NW49obL|s74{Z=3644JLWQlbLgY-<075|wjxrD^_x2Wd6AE+K_bMoN zYf$bd6vW^t4*+E_aWIEHSW$Iq_dyf2p-_96)R@D57;1i&=}{UZV(>8*L-jFI=bHSz)>AqGJzupRb%Ak8Bl=CJ2MeE4NpE04o|msAmh zt1g1-!ro#533G?NP@Y)}6bA5&yv+Jtfw)FKBoxHpC`*B|ggCgvUV;UA8Z*Eg_840o z*T^zbM+~n1iPmA434KaJh{1){V3@0Dn9O0X!W@sW*4g8**P5t(4zU~cTWFdQgHQ7gplt6gwh;<<*xLax(wb`Nu(!oV`i_tg zgCqS6q}{#64}`=V_HKpf2ZhMFDeoZ^#Na3gfU>{0_?1wY!``o;{Hj6ujZhGSqZ|Rs zA>!Z;`;a2b%H$7HM+~lh9O}nNojdGfvDHtII%073Gf+R>Tl_-+%weC#p*Pk#^rXZ7 zM*9yK4dv7$Gd0B;}w2jITd03VGF4FS*GSR zM#SJ_yauW*NtHY7mWnLuuFO8PCUwN%>g}N3Hb+EqL;^8zhut=Z9UE}i5xg?NI!L6$ zPKeEU192h-=gb6WdX7jXNba!Hfy4}5X{u5m0DjuCc-A%2fshb`Al+*_>_Q;*B_8Im z`$GH$%MN%Pc7IYu46b?)RPV|W14x)V?7QTdH9%ni&x^Ll#Wiv-p&$lFDFVv<#K9f* z{aBD0R*ghI!=7oY;~E)E>WIPBAIi}^!!8qgn1m363k}0Chte>a!ybw`o@uSK$6-Ha zqBb0A#iYg@cCkingo)Z{s6CYFo(TdZrY_#=X+*}!sArvCp0yP z!KY?DxYp%}H92AxadC&ePQh6tQCBHotZ+UjKE&XBTfp~Kj@U$S%wd0}ux(O^oT=JM zD2TyPz5~j)IpP~aVGjFS1?3wJ%1%N-434rJC_fMfbJ#y9s!r|xWTLhgYI{hHIqW@9 z^RrC9(ijngkMRIh_me7j*!vY()Lof<_>I&NgR38d`q3P5Bu5+~2JWzr@?!%I`v_i{ zXB{NcVIPXk`4@2_2Io8j&eJ*KAA;l#`?S~4mHwmD2Y_eT4jb1psY+rEq|0 zf$ep1jnp9=L^GUAfK!iHxZAFmTQYL7RWH$QyVNGYH4;w*h-L(r zis3e);WF3V1oK^Lt-Hr{Uty|vH59KRMdrM((kM1FRcsB#R=J`DiE{VdN>*44MW0pJ zwKV03W>bDWaN6XGM8e??ybT~0Sko>Ycw%gf|Dpbh|m2>0H zARI(9oUXv>oGUsK4s+t26`YP5oGijYG{fl*oNmOz-FP=enw3otB0w}F=mmn?h=4ot z+hP-B69J+bK_3w0=Zai{V6HqLhvQP~aFnh*SD|v8&F!WbcLU?jTyaOPC?pc*%d8!MS2kt{6yc+?@|rkOoQIfeIWeqz8!+(TwqNFb>NV zLkW;M^kE9$P=(5wvSPwPG{bocI8Ww^5ro5B`jZOI2n|jN;UJpfJPVvL#KN5V7)9Bs z=dq@W6QDSb6q#Ee2Sq>YHIc@OXg1atq5J|VbI1OIB8^%svmcX*0MU%#br8IkE2id( zDa65D`)mAIfoq?NS5{aDjdbl(VzW*sRzx$_IbeM|SIi<%?%dz@n#0mrO1%JjvF+S( zjm#x1#6Va-xz2qBu$B`ObMDIlu+p*;9_RiEDI=OGuZ8mJT(OeGxpQAF&$X2b2bfmd zz8TlZI>JFT!`T3w&xwUQ_s_97pIbE(?cBex32=>UBmzV;g3VgzUM9AM#1PHIzQJ(6 zrr|Q@{x#D+&fjrAL0A(~aarP+|Z8^ z4x$;(Dd3#U6(OWgVj94n+o z#E59dD8P7So@h#d%(-8w@HJJaoGH7Sa1hOKS_7w5o@hZh%(=Hxa9U_^t|c5qGn_WS zNhB8L+!GaLr=HuIDz=AWJ5prMy&V+&tXC3^713<0X;4lfW$xTl6lv6Anf*v70z@-{ zED&_b6P@xz2jbw)y$e59;M_aml`YmmBb|GP*sM1aE20@|Pq5yaCwdSlckZ_Wi~vmGC(C$4ME{O!-MDkH`~GkT`el zBjmaEgu(%)?Y3{mH8P5D5Y2GL0B1C@aOXZ6i?he7nP}(!i%o!Q$qYk6WSiE`)u znyj#?iax8b=``htW>fw)aAxI+8HB@~`z%0gx29b>_ZhLVW)l{o8P)<|y_+ZAAuQ(H z-&LsIQK+07`ul`~Xoj-{IE(YdBEn(LeX)YGNQ3hc;UJpftN_k(V&TqxxgyQV<`W`7 zG$U98f>lJoo%^cT1Z#-^(Trdt2)@V@>j{E6_b+fb?z0X@>D<>VRF2cxWQwsJ7~As1 z);zJ9NSJfqCO7m}5b(XUSz&Uj_FI}FM6)US32Z;+iCuYOC$Vwo{-c7lOXBWS;8-F3 zOpJ(Tj0eEDKTrHhfXun?SNMKasGKSLjc^dnaE=1!NS-)EILx^pQE(1vaQ-A5L^GVf zfpeT#m~%g_C_D9h(p2$ZD4rrk=G;#~(a(CFp|K*GjkSC}{)N|k=Wzsg?%{l|G-|QT ze#GTFk0TJx2&#gha=xgPFDeiRckY$**|7rWUJ0-KW*s!rxmSqIdM>ddnz3F8)>`?Z zCV_J2UJF>v9G2Du7B^6U-eWs=TqCs!3-P~VU6-E~PPD%ty%Uf+5D#W%rLD+zPQeq+A-;H0a<0G=bZU&b|ZGoc^`N4X6sw-5(+>$hM*j$3sS z?bc7&>bORFk~(5=^_+a2Q!f+BB_YJ%LVYmId>STm>G_!B6V^I=T>9-MYW<~sNJ0}?j%9(&hM7hbf==ts_8zOX2jsr`~Xk}=Zisv!kzhG035NVS~~MV zv5_7mB*frIj{|8~z8FeK%#{yQh=wXe&ds`*P!NNoJOz{|^Th~4VUGMs1!aT=rG!ur zgQGkPlrhA?-S`+qmX*m^Qb!D~J`w8UNu4|K@v+sPCw0W&>QkWpQoeYR0GJDZ35VW4 z)}bd|_=^gW<62%ZL6`xAH}b{n`QkOAU=I8ZxoKaAI^Q#|DLhVv&ZMb93_dmU!8I>m z%*hvT6Bl>i^Awyp67_8bj1|ti#D^H1Z!!25<%@*`$DH>fg>9iieTL96SdEw_8F-$xBVH^{4CQKG)BbW zWBd}T8%dQr?Tv~o>aNT_d`0Sr!PR#_eS5yxmM^vv19#cm`LO|)y$!FNu?`aHvbV6Qquy_gpioSZmJM9QHY$I@>PU_7#yV)P+Am- zW`x2Vb_)finFi$=LO~3Uk_eRRh=V)q>l9g5CJ|Cc46c3y)UPLX?y#?qt=^v05reB| zKs~KMq!0je*l9TQ##)D-bl52hk>gS_O%QGZLRNw3QXo1J1#{S0a?^H!I^Q#$6dtES zyV2Aj2A`U2aP=$@w-$&V#Kj$UPX*^ziP}Q}V};Y3_z;8h^#xy_0+CN}%whLY*zy%3 zXR7)U3Sw}SyMc0Nfw+TEn8UtPLAgVNau1;(21gkLl!3&-9QHs()v4Vg6SW7SHiXoe z!yW=PKg;wGjS(^U7$1e|Bc#e5_9Kcc>aNT_3?p^K;Oe8GKC(azFA&AVz#aBTer&*D z563GLtb;^4?Bdv*PZ1|#aL#ey99tlsAxQ49$9fH2=`%`w0QhOk;#t?octS!9g4D)# z*lz&ob>d+T`*n!FVA%nW!+w)g5reDFhU!}dVkQZ5hy9j3vt}v`;Ca#ZxVT2<5DH>& zly`yh4smdY{SFpns#PP=&#+&$)p3oyN9u^d)j!ZW>@uN6B!n1TXbFb7n1;z5_F~NO ztJXSu9QH>hY9B*w8L2Ucy-cIF!bEKi)K(RUPf3tF>{YUwK2@|?HLay-Mhrg98-emg zfmlx{++lwKfETT)mJWM;Y@|(ugcuy@8z6mMAhr+^bJ$-iL|YUh=cc@!P!NNo`~Z~i z3&eMX!W{PZ3d(mHlphHNF*wREK>3+CxWoQgk!5AFm(&r1s~>>+ep2TSdw*>8-$)%X zxcX73A1M%r2!J{4BRKS4w+=n&un#Fjj!XH|1mQFg{wWZD7l`9T!5sEKa?}0|b-rhg zD?Cnx{!3GX7<_6f^hp3M zCDfbu5m)ySR}lku*vSTI!L6$zA83nE8;{9&e;~6kv<}UAi2Yi0Erp8 z(gdYG06f)p*tkZnCnUuGij>nYE8N_6*pKu}7Z3Gw4io0EAL>^!;w{S#cpUc7e$GLG z7+m!Us6O6L3?pIgupjT|o>{{b2Jp)19OWsXJV_kfVL#aqKL=~oNVLN) zwbgNrl#n`NaP?>U>7HSi2|Y_fh{1)%W0=p;Fqy-C4s%>;t+U5rPcTuN1hwZ$jXCV+ zHEJ)Ks7;01lz!qR666khimaxW6m3>buhKLl2A}2`KzXB|c%4wV!+rw*v#qI?4*T`k zNHYluF*wpYK$_c6%qAq}u;(g7vlSxeraYfe5QC#E0?NXEVgaErhrLiiS)f7rkWdhV zqbvo=65`+vdx;{;%48X-BL-Lh6zVHTojdFmvDH_SI%073^-y2ePplyT=CIe{&|7L9 zdeUL9QHUIu^0^7ZRv>KdC%)__HWCGM*qi01{SxYY&umn9oC^J#rUo(i)a(M+&VFJ? zKe3&-xWnG5;Ovm7+Z8ZYI6n{{VsO4+!S_o)@iW0Ohy9Df_On9dOw~R@K@5&^2q?ez z69))|IqcsRlmi-+!-Rqu9OW2LjuHoR*hdvrr*{7`Q9B8>6Qsr*_6ex@S*CwzjEKR< zcm}GcNtHY7(~2zWuFO7!3LV3S7+k$lA%2g4p*X8hlrMD5B6rvo3fZv%hkX`aSz#R{ z(qWe`^iB`sJcl?DgLBpdXN^KpjUc(ht^p)w=t`>riJKn)FSZ>vu95Qz2{8zg^IakW zNLLaMbJ$lxe5GXvJP!M6Qbi1|dJR-t7K-L1%pG>iLf2t8R~W#v+V;4(Mp_dJVsMlQ zP!foPJM083$VRJ1q8;`oTOHR(8&XFMu6{#dx>K;qzaC#E)SiS8gA1i%n8`Fu=CG47 z$D6Em_BiY`6SWRd%OEx8uroAj9Zl43gj&}^(U}Cf!|p1psk5TZs_7=0X2jsrd>c@1 zDHPoag*)t90I=GcYU!}M$42T&NQl9a3V@VXC~^piIqW=zC`Tc3ZpwWK1u;0v0HE|Q z6#WQ=Iqd!lNWIPBhd{lE)Vaehimmo!wQk(QXVrwcnSzl7K#yt;t8T)4*N;DX-7bv@0lkQ z9;ZS}Xlf9HPtAC6Jy$56Efiyji#zP+6r5)z>KFx#70v|WLk!OMGWaGJib({=9QI^| zZIVLdOw|-ZK@5&E9VpWZ#jAwE9QHH?^V^LvrO;M7!iYyaRF4{B~|XQ-&JH$cV+hBeNsmZuD%rNOA5u}La~S#xWit; zj}18N#du|#b&yDhy(l*4GU7xG&bbDhs|v-Z1j!xtDzBj{{Zy$B0B^J%Hm;GigoGFb zsd&8mJ4&ke$45{7eV${V+rMPQx0WUFxa=DJowr4ZX37^rxmJHslf=2xuGQal+BFpp zFnwoxU0frz2?x;(ryg+X5({_Rb^Di$JYv;LwA=o}CcrgPp9m1m2paTH*EsGnv4$ju zXeQPK!)-*vWv;ss=KBw8-94`Ra#O{tpm+r-GUt7TMp2k5wt`}d{-PO)a`)XrR#-Dd zpHMl>tbWIB`icUtW;nn_ZRI6i@ES*g{r+m z<=nW_2nW#&r!#Om_7|Ci!<=|W1t(L3(}i#l&2YK_=SE`TZu~|?nw8DXM1W{Ua2p72 zAp-8mZ;4INlL!#a2=YOY+h6o12Z289r=FiNRU8M!v82e{`dBFXS+DUlRz$P0z5wNkq|6=rL`534SY|&a5doqZ!D}Fx z+FwlRFJ2-J?%JpFV+F2#3SRl!I%uS8e$2PWp#1YrX zdqs}JM+{Cl6oiY4#6rTmy2~;c`cUx&(R7QzF|jcSCN?fzh(C|Dm@o#sa=Jlh=eSu+ zFo?ln?jA(W`XYChE{fvdqyLBm5rYffhtV&iq1W%SY=MIg}NycXO!m9B6-5B-R#*)kR`uk@&>n$O_kQ{6$f#k`W`Sgj!m2-6<=4N#l)W zuN-WESK=FgS@z1bDtM&wyWZ;*OKhl@Q31W@LtsYqN??W&X8>s*@~$MH|}1(DZ0%HHz{3> zS{`ioc4@-*)=QT+UR`8;T^yf~q-4a5 z#?4Dcyx#yo?>Fe2xXWR`;{SsEN{9U_u%p|ouqge^Vo&_R`r_)wpV`zE9b)^n=9u-y zTiRldu{gz-N6%X0AB*fMbGqnJGQ6QR{r1YVDE$)CKdp*8{kxqZwEVvqLMvwo*I)?f zHY?n^bSWpC>#3_0$dd22I=XqBT0HJGQX}o}%pIw8l;Ea%Quw)qW$E>Yz2y5ml@ytZq$gsSXzO^qrSz~pQLXHq zdP%}DrwDHSk43QF@5H;!=@d6%$VLuXYtRz~0g0?|HcoYCfxB39^t-!yr3ZlXuXS7h zw^8YS`RcFoPYy1v>t9w^y=e$#I!*1@a~nT)m$Rl_Es5wv3_MST%eNQ8;yf>-d#HQy z8T?m1ye#38P&iyQ91br@2o>EGDk&c-A6GFH4i#6d9tu@0cXs*kD%s?dgwTM#4~0gB z(IyUU28Y8R>$29%thEWD+wZ$)V8Nh%p^`Ya_d0Ixo2Z>FwH054Y?`k;{nmBce=D18 z(>3`~N`DVvhWni^XP?aZB_T9$@Sv!P7gx7Bl-k)xNin`~)?=8b-z>NNld{QhU6W^|^k@LHqvR=F z&hs*7ytjr@?fHLBmpN5tzU-elS(iCOW={9doTkg1BQxL9HF-}qc}Lfz6iuAjUgTSp zH`)VVs7qfd6;`NqvD|+|OLd)Xke#jf&s?W!tkHG0O?I}$zq7A&nY(1>cmA2*>N58r z)0xcOx+eQ&=X*U(=iwt>$+UTz5Sfg?b&env?p8c z%nM|8%?Q7Fb$2&!J=vsAM7jIa)@3!6S@98{6RxM*`{mTmK1u|>aMt4rPrtp~_AO>QS0I^{}Bz)b@qtt>_Pv`A*x1^uCo!cvts|w z9@Axxk(nj_nWJ=>zd4vO{T|KwQ1I-Q(Q@JdqrQ> zbv<8pJy*A9!{OPUY`HU^YU3V6Birz!B+uQvV`Y;uZIq*Av@Yv;nKizR&ry=^_WlyJ zvyYNj@rAPSWGG~4p-=k!nF7qRqx!6B*kuGzk z%v|B0xm=g|nao_HYqCi;`9jy^8#HlddutoNqoj{rc$;3Iw^SCavTw8ZC&*+*|KojR-LR?$TUaKOTRMIuM zKsKq_R=;XB+WH+Ox7#aPP1kk2?7E(n?tOz}?b&d+t|wdW%=+!z;ni)&hgaxs-bS)X zgLcYM60gg;Qf6J=&IjvWxA*4M&OS<7;|r&_TYCDv&ut%(O|H{5Ns`j-0L+e(wz`}S zGAF&A=P0?up21XIW;dCc<)7I_m)T2Z-s+#(LzkH^GjnuJ3T2bqbxrO?6KA&XYUfv! zgY1D1(4{{l6^5vFQRF|O`*ocSmz_QCpE*p`7^>@RjO?t$zq3)g%!x8{oPXw6UFJ*3 zbS86>uF0#i^C_Mta<9E1n@rO+nJ1gfjpCq|hDgP%kkq|n`WL_Mf1aho)dyKoPKdAsj=y1Xl7UK5^IZ09x7<+YS~&HVC&E-yjmwbnJcUN(v7nxvwMGa*Syq5Fmm zjvB9X9Npl_e8ZimPBJsoKQmpI*-d6<`Db>~W!@?W)ZNoWE?=(fJR8$_cW6{Odfwh3 z9PX)0DwIjLBk8_^yYG&wsd@JL>EzY8RG0LbOj?5^Pc?pO zuir{t?taO%*ISM2?989M)%dwPg@>i=@1EW_xJ{1B-v8v)vBmED4_)3FnRklkt+w+{ z>hdZiyC;2IGCPZ%ymHC>440f$W!^cuCg;f})pSiRLKCMNFG%)18_)M-Zg=M?US`(w z&#bGeJ`_iB>R~Dy>9P6Q9JwQ|0}+5)^m@i-(TJKzsV;1bxn>+ z>B9hKrvIQW=O3AKBH3g5f3#=tFI{F_in{~CDZZI!beUCTW+ng33MqU^6*l&i8I^vQv6K+|LlR+)umq{6`G_dbPvt_!Vn@ACs|&xXT&J=wA-AD7vWBAdDUKkdwiQaq;rI9|5*{V1e5lQ$xT-!T4m zn>;Ife>#QTXwKMum+10dka-h$-Vr-*oGx#w%zN1{Z?Z1$4VgDh*W@kPWQMNEd^B+; zWNwP@jcv9kGhBnFa*@n@-#_y`UFI^Gxx_znu`csdIiQa{P2}=@COcn)>Et)IRl20F zWYR_?d2VcR7;!lKxi0slWIFCC*b44cg;U*=`(O2NIi<_0AhY69eKtuoxA!X4&Mxp8 z_`+Gwb5r@5UfpeffoxJ!*QB15u9NDyvDMb)G?FoTvFnOFK}Hq~Wb zD>Ga9XSUE~ww0NQx+cl8$ql+D9nr*@?Tl2v8(U3#;Ay(_?o#0 zuIwz^KeMN*ajUMg{<5>a{+;#FW!@(<@Al8UQj6Jm&qne)a6{P z%UUV3R`_8xc6(n(?d+pu1HN$9W4))}CT{!9vdJc0lW(Q;Ht$igRhP3{=Irv;(8c!r z@6=`fPiFq=pZSX}^ADMM$UpOUUFHdyc}&;jU)kgzU6ZrZ+}SRl=694_VGlf<#t(J5 z64jCJd}LHLO*u*`r+E%!XBI2zI;$f)yU;(gma0)x*I7f^S-gK|^>vw7%FN6CGaKtN zTOiXZ-K%v?u9cm)@-&fqt&MDwplgyQnkS&#T(wRL+RPVH=|r|^Zd9wR;dUhlSl zMm8C(Ycf$vj{`7!yFFHyGezc1_SR4&)lSHY|wS~z3gm< ze`niunZL-)pZqg_)MXw(rZbuQbWIM+&VTnbk$df!Z1RV$$r;(?RE$+S>3fu<+ADfO z*L9_I_vUbRy3bK!?b&cRE}h?6ap(;?tG8PkmihQ<>G+538%& z`_3;Qe*!4@iX~wJz@WAJKif z&WdGc!~8Rcsu~aLIvXuJ8|B~GNL}W5nK{-!^BG;{i^y~)^Lbs9S7hfed78+*_PT8H zs;&ccobDhjy?P=1}-MpJ*lP}ce zT(8UeT4rtb!^(Gi-$Cu{qvQvC;jG6_Prn6j`#rMBZe5cDQhJ~FDA}vaIVy7wduynd zJ^u%FnWtpt-~O4$b(wJ)?oA+^;W@q>%`>{pb7W?P41SN0^Hg0nsj6#I8%>aVPZPPeSxeJN*{(eC=nV>G`I9=8hnKjuDYqZ<@G-_u{&A=DVdQA89`?TAB zwrny>*W^7Z{SJVcE19dyDU~^kyft)>J%bB%nV-tckNq>3=`z>L%(ecRt96-Q%FGSA zCfj6_ExIPV(8QVT?|h5$S$p8$>eBZ~gO*|ttj9u6zf;`yOJ$Q%U6YkkdIf;lQLzK$tDeSO`6FjS9S0^N}N@@qJ!U2GTmO$%XM8R%C4`q(!EEC zwP(ZOYdqOeE^DUDdZVik)*QF@In>UUdKX_f z>oL#M?_9V22eQcmU6Z9!x)i|dDEUyAvr6WC($!PS!|WOSSeLm$X0G?oT&K(YT4rwc z&-_xC`JK$%u4}SeHrb_XvL8*H+1}gLuPEo+1K*=dKPnXtt95bEe?-6OIy)^pJL#W! zLe=<7*V)-wZc&%d@?Feu7O!<#UFXWo%Kn*^beZQP)0xZ~x+WLN&M)vZk$bJaY*JU( zwy8fN(&CGXoSda17Kma^++R=W2nvG!~@EIiqA?vD0!XZ>(bKD~>OXz%Zn zvdQtD%29Gmmlf*ec6_?057u(G_p_*-Ep-mQaMq(jFHZCSh%dckRqaxmzebnUxgec#YCDnn5NWMA**kJ zK7y}^lqyro)=G~^S(Yh%*2*#>Wd)`zFAAy1LZU<=aR@O+yUJHqi*lvj@ya533Ul}n z!yNK+CDp8ZR8^GhbC#^8wenN5$H$^%by>1+tdo5$QZ{1BG;3vjk+Lb2#$f&+3Q1?l zn}>w3z4j{$X(bA2!$SVbW7huo%IYXttIz1~qSRej>W-Q`^eEBxtkc;cM9p^QaHbv- z60!k8eSeQ*A*0RHIZ~vW!c-Hju(k)X&!lm>)jWJ+%*X7IygLH%i&)44QOHVWy)5)7 zSt8PGWSVuMYiN@`f@?&|olLpSTA3qK9%RaW*2+C1<#DDwA__UpLQaZ8E+fPk?F*KR za<|^`b0Ya&=5WirE^b)&=$a^5!LI{X9>>=qN4YWnkIWtqM9GS$Sc8HpdU3I4ZC?w<%g!=xj#X>&)+I02#Sfu)zslKqnIvL1bm&WN< zY52sLkMBbA{u7A*4-5HT6!H_ZZVF)T8=NL0&2LQebLbj6qK{xpk+Ka_{$;KFL!|7) zlpU;r2= zRI|rqQL;rW*#hfi^F+#3Ou5`zxm2Xw0HraQYegYBEcvF85VqHLvXE_}ki#tGKpwNU z&+;g_pwH+YQR>qy^-0m5bvjRksM*eZz|?m`LM{h3Z^7E^f>GOalspoto@S~iYg?Rf zw*%RqqjCCC@&Z0F=HvO={B`3_Aig9Ec~KPdCbNDGz}!*tsz{?Uja)nAs(4i&e~(BR z$&|!e86i?eF=Yj7<=Y}iKE=%@}weoAT$CsjHjajmW*2x-(ls_?LQ)^`tk@6QPjlpaw3i%&P{#!^0+iR^^ z$e*H+&MYJ=k6CN4Z93D>l|0sGw5=$0UzWO;XwN#GJwnuMXU<^isUaZ+iqooOJ`0&+ zp3Ye!)e@#!XodAmAp1%hrynKj@QE=Wt3&b@4#aO}Asa*?JDK&i(4!19ffwbCV0 zMnGvS-EdJzBuh?0LfBrbz(UH4LOx(2mAj z?OCTYK19u?@O!3i5EAktg!=w&%0hlHPiJG1swGqXWQFAoWdDuE=~jQ@6JtJp56P

    RvhCK% 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ⅇ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%0DVT^l2+K20f`cHc^_-)1Ax0o z5>GltRzW1NWkJeV>%BMrEnwA0ChDg!>jOZxq`v%A_IDT=tg*=dfyh6_kRLEOt+aoV zwgdV1r~IJd0H%Jj)`er_&xixo7)}$wX@o4a+HM3nA0gF?ui73d6TmSt8417|BltB& zPjQz7OT}PdjRk87!)=bkrBruw$oEKT-u*t&-O6ahwh*xmMx>N?8=Z)0Mk98Dh#g`` zI}A#z?+$8(wbR6>Dy%c69IUaFcLAKgW5}O~Lo4vV0ivIj_I}>qpYmtvSX~hdtTC+K zfRzpfHj6Q2yh0(kba0mDe(asoPIhugAoU;F`N;AGYna1 zH9kxenkt)-NC4It!8jlog9Nl9A5%KPcq9O8j9@AdOpYNF5rR_XlVNilBW;eVDxavK zQk2a!qZso6V{QzY9Yba!38l>EstbBH5YTIBriMwW+69;*u*Oof9N3n{kR>rB7ujfa zzD$F(M8(b3z)^*?0vW*?V=Ms1wJ~Hh0#XWnt%h&4hDu46S85QkFf zTQoSEba1vK4p?J2y8)*VStzAmsEMr9^B$uS4?x6y7?D!z`ygT<>2(mt3f9llI z&OecbR__0dg`Yr@YQ|T&&yxw@82J$rfHg*7i`7%^CBfj2?8(1}5UjCaJPg;4!=;qF z9r8U-ns-0tE*OpIf`}qUq?Eg;6OkB=_$frJ97{gNptN$YtX9~^n)pMLOHB`z4Jsxqu8pBBh zoP=2N72;6JJwb!>l@3lV!~tsz=NrJOi!8Kqud4}7l}$Y)0Belkdm#80325d1ZRrF* zAOToo1it{m&#|N-LQu;6XV@GUN}Hpq+#71B6s6P1D8_#QNt;;G3fXAo-d2OuM#XKVfujnk9WsJ7#`q^N{vJy@ zAt0sPf7kGJ(oiWW`wMZv8pG)hIGM4e3*u19JyV0zMF*z`;(#@V(+6;RAq%D4dubvo z^_*=q;sA))4rjY17$eileXu4p)MAPJ7={F3jS-9og0Zn= zbSxQ(9JF#DOK&Tn+(*NiCDKNtD)*74v*sWxSYxa+fOT3dnS!9Sa-Zfe4)dmH>II$>)IIm*0FWn12|wkYkCDL|i(CMa*T$077@St_Yt?;i zwT1(jmdm;sj*;sT2dpuiEr7ELS!m_H2_|QaR5QNHeXUFY$H=Wn0M;16PF>|*608t| zfi)IvFAR4#4wq8yyCL6erFr*L?)!{JJOmLBU_?r}AJBjq$5izQbOi&E~_ zG*nkKRLTYYCgOlKhVuY$?!}Tjh(js&dm5ZOIyesz2dpuiXMpnrS!m_{L=&1So99RX z))+xZTn!Qwr`%him3vT}|5Bw0%Ec+~^1&J-cm)Vvjw3H21f|?xj?3z{UfLX0<^Ga} zN>Mr$jAFb47;nXqigDz1B%zf1TXEi-Jr#j~UQ4fQn3Sr07gGe*Sc)vb_E8-9R~-2O z*=Xhdkp}5sD((jwIBFWL$OzULqXQWEIATXYO1bkIKD&lWNtuW^V2$Ba2Aq%M2tgc5 zxqqy|Av!ppAP!h#IAMVE8M08y{WDEurJlo$Myv`EBQYYS+#?}kAn8>N#|qZiSYsga z7Z{mV?q6s^LoJrbk60uCYmC4H1U2KxmvJN>IcVixlipT9xqk^~HcK0gs@&sCXH7&_ zu*O&$0BgNC@->3e%Do<7QQ|P~YfZgK(6VxeW8}Ap1-49Bd0yrID_}K6CQ7+C1%Pdm zl<-sTsTdiovB<3(e({@=m!!fcA;(#@V(++UbkcC$6X)rl^ zq?++n?t5hdI7YTd0+hVb1w<@I|c)5EZE;L+&^)+lyd(Q^1WA@cR%HxVKibl zh}ab)Qp&xnPQ>m;Bldxaz2Znu3`#5aUTTH))WoMMEE`h})>z611J1xW(jReXmMbXF9Ub%6+;fG*vdUkN~VPg84u&7YS(PKDTs&1xNta7{M|iSQ1Ba z5rR_gOJH+6AZ?DSa?jOJDM}~LD8@R#SQAH9#gUarLMit(>VjSc1oT>3sbNy8wg6KE z)>w+R1KZX(vN?`yL^fKvZ`B}eR&h6K;HW~{fs9~{G42P(y>VnW0#eF-uZC~8hDu4< z0mK1o4Cff&9El@Eh(js&BO06{9h~Ec1J)SM8NfM(ER=FTrHQQ6^I4-2FF?d%j7TZ> zVu%<>dR@e^f;BeQs}T7zMy8efWldfe z!aD3#?v((`$piR3`#5aI%>EruSYs*w0dT%^lLm-GEBEgJ;)IlTRk=4P9qUKL0&5JbF<|}TCO;zB zS0tg7dk=L%cLM@?Ep^o}DOKAGQv}vniUtAO05|F9CfUeFEB65!q<$)Hwg!$Wq`}At z))?bxU>xZt!x4~D?jtpP!!=Y&%EllLSYtSo0B3@mj7J zX~;q;_i38QNq<{$Ac`ia`(h%b<37&##g!bwMoAZ z29A-nkpQeQf^XvWlzU0AdKe6>v0&f9a2w!oDdpY(^4(XOcR%I+z0rsbA>xl1ky7qI z>O}mH(TGhTVxxGHgh6TL-bk&mBu#v(!jduNV2!1`IpCzmlV*rREB91@I87<{W~F1b zKrFDvu+jmmZ9Hj%Sd?;atD$P6p;9jB?GOj7F`PdDr*k~%h&YsT@2tV;sDtw-;(#@V z(-m+skcC$68Jf^k*<>OCSYrfPK+ppTXyx9cbb?+;0M;1603hfWPqGn$Qttg=a~vRT zj;eCc)=()*XP{AxQGhWbo(zj8Ly&}0?jzI%Jq!rwwKPP-q*U!_Oc7XPDVhvy6XQuv zJQ;^l}SCl6UD<({XBtkm;LqY>9Y#8nuPQtqoDVj$_Y7RL(K z*jP6}!`LPiRz#1bc1cDv$WLrGhf*iDR-$8FHpxn2?nIY0fquz7h zQabA{WCd%CwFp=b#*_UBN-Ot+{^BrizouRQI$M&9(lPQdVuAf%vAQO}?_D1djLJRA z1Gkzz0hD`$Co6Nfq~QGSxmWcl${nn+$gvQ)x`#w#a9X)n_jr|iw1xwiuFJ|Dj*)SQ z1J)SMSAbIkS!m^6!;{r*tW-0;%6*)y+~F8m6A8c?BdF!kQ|=|fYGW|4#)5qV!>xELuk9I(c4{sf%gk%d<7ziUEMW%CyjfHg*t2?Sk`fL88Z zN+;-s1YnI3^Z|li9?}ybDCOP@HpdCl=BO(7o*F7e>0}$l7z!AJJ!GJV^hXj(xerzs z^gtk>*HV8ClTx+AFhyXErD!~`jrEYx9x@WyXyraugEU&j9jSq%3MmH}!5U+n4vbSh zWHJI$%6+PaZ?c9;N!bj<0c#9rKH$vtklBbsDfhV=oY^`!3lImaF`OlUlZz~ra?jO7 zR_b}F(TFP`Vjf1MlzSdT3?#i);#k2N8|xZ~yb2@J%6*k4G}K~={8)8#t36|6DVeZacMLv|r3t=#wci^IHKntB1~ zv9fZ9W8{9s0{g#WnG!*{Z}9$B$fU#?TlrY-LWII~zfGebTz!2mO3F?b4S;gh>4uTP8jG9-k$Yg|NQfK@ zE2fqdxd$D2t1U4`dNHyWMh0sva({^2H<9$g;EA|4>Po@;LhuXlN8sR)*9ZQ;M_MOa z<#hre$~qZf6kr$t3`rz|5a4THfFV8rgLD9f8wD5(0HYJhNCf!O7htpxz(^f{aYg|q z0zeK%ujV`XIS|ojZ&D|J5>7r?W0OAvB2P;sQ!sce4!wai`O^}i&>FxaZwif}Zjm#M zhF<{T=OvQa7@lDGAEfZ};KFcJx-cA&FAN84d9!se7M2mC(0j>R2N-J-$;$taxHkch zqS*ewdy=4B0YOl~eP()$;u5?Xz<$rJb_dIW&CtcIsXZh5rQ&nd=%PoyWu2nyHI9L;Y;e$)Yj8N$XTaLYn1n5BCjxPbOvSJ*YnM}x``~d; zhPInI6}PNC@OqYQS-UL+pgBuJfMZ}k3jtbZA@~|VhcmQ83`pFv4g=yC+p-Ro4RnM7 zp>+my96-l1v~L-ZxMdwP0exFG&{gDJpaNx z3tQGNqG!Hpon@ZUI`jNHJYUGr&N1i0mURKnjV4iL6XMTUKimP-fXc zZ5a?+XFyK_=t)K+Y*|lQ0Q4=ZJ@bs#ndj%=`B~;!*s`7#J@ZxTdFC0dGtXV&xpOP6 zBXcfnS)JkB*s?m}^-vX=8MbBRIt6$U0C}yn?hHWKvhqv--6a4$odOg9AitH?n*j)0 zR=x?Kw*;WjDZncL=*zqdTUK9qG_6g1@cXgBN9%0x-+<@WT4@8Ab79MRjc-{4L=3)V zz3J5b5V#-QN*l=B3tQG;Yz%KB-%7Wvff9_N|2xLfnpv(!S+0g{6|`-Y=;SnfRBxsh z$khCqv~2-3l&va6ST+M*zCb|lKTb6vd4m8J*UYISIjR z$WN7E9FKZ*1N1fFqK=v|3Bzn#Vy8JZNnf^%-WIPvFxyC&AIwBfty9TE-gRp9z2-B) zJVKZjeZZ{Q*en}e$9xv9`9yRIQe|Kb1sSnPWq<~78+NlIy{Tgx_u8_1)o^b!iyiKb zA-UAfK6~`O%_V(HA!CQpBL>yq&@`uVI$)=m2=bR4o{RHNS= zOtNH(Spxcebe*P%LUkp$og|E&cQg{l{HabS&15!D!bhv4mD4oy<^VcIN8CZg$g+{wH-ZQL8u4R{Kmp=U9!#g${al3w+psCqT?9A+WC_)_%qnM?{B{$5qVc#I(9 zLD#{;=#E%DTIzXsfW+c?7$h@&U=2MnAU>KDw`5r)vmY1Xz*=ZF?F^NQc=G#0ym=bGnuqaItE7(iLz&3K3wSust-F242G$= zGMS9QF$5=EhA+%CGlFA@OdidSusiRNJ1^29p*=9-Jr37R@kW>6>Rnu<@g}F`nCQVt zFaSFf(9n33bHuwb;{9r-)<08wB~$Cm<4u;l=r=M$uhLlS(L=KDCF^x?3c2}UraqAm zk%_E}(ZGcI(;ne9GVK-GZ#}R3;x&6ykP$PGc4{gNnFjB544!`DJ>sG4p?L%5_L8+= zg#LDz4#+gqIo>eWS^7^hT$}cOG z*NYXCebZuQY~sP?kVlADpb3paN8YFV1+mPkU{f74n$j zIq%ZYuY}LA(Car=lRk_L+sx!n^;FbnL8%n+Z?~BRL&W-s|L2A_(z2li*N`BMK#)o| zwehqkYpp%eZ>%R8rA%yd(@hwgTW|vr8Vs}8;KFWg#I64!66n@{9fr*!nkhHvDjYL` z_G}BJ!p2CyvDE}!+QD!uypP+6_z?6Fs}_yyqofQsg(h6nbj!3iMDks82LodZ4(2Vg zcqcB>1&5rLE;x~{kpBV2<*MRxxmNm>!WWg2NF_3=qT*756{{&qm57@nU7NVbdcTs_ zwVyJ?1(_(w6uDe$Wm-G9)>gmLrBAQ?P6fG2Nt9vzZo~TLOpdzRhZBX;d=X~%9z*_1 zE^5Snz zBg1njg~orlOmi~VoM5l{u1s?#*L>ez^F5j7JgzxgCh`#%`A{aZ0wQ{}Ke0{9*0kdv z%hWe=59_RXvBthft7XPMSm+PM}Z9X%r2aL_D zYCzn5vW>}m7Zpmt&my+5z(Z?e?%tIaWFpUSk*8!L zogtz}J11aQl{`xm?>U)zPwpYlnit*edz33P_A)nCXs`K_)khzhu{XJ~*X)fAkZBI( znuF~%2gx)?LQ@as+cJ@Nxbe|pB7Ck*kK$rPOE z<1sPJZYM*2Iv06QCNh`1{s6$jQZiGfvzY5FjI~`#7RWSLan0rSnxDutH*(E&_L^&C zn%lYN7MaNBT;x-k$U%tc(cTwpx0H0IiML0l{vG%5jWsX6w(rqlnX#X_u^;U&Fj$AgLzdZ5*cUAH6>0m*D7+63Nn%ET%>B8eAKGM z*)1hq=!jO5nZB2szKf`bzri7M*5#@hrp;&OUrmheU1}nBubVM>uXB;BO)N{vKQgVT zc*C$O-Uh3;Vf|lBjxHs);zS>hO7S91A49$d7pW!_xtqJL86UQk+#%EPa-9d_!&P@?xaQ+Bk)~WEPA1YEB6_q_;_Z^MfOb4drv3!? zkclvdJwwZ|?@^k}*t6W&)ApKAT76{8jCJM4I@ue`k!kkintAq`-DR2u(A0z3M<((L zH(nGb!sps+T%^BDWC#~2E@RXNl1XQ&N?xWT`lihE7;bu`Y|gq|!^5=s%$%BF%=k$O z;^ggbOx{^sWO{-nWv0or=5wt%2{uc~K*Rb+OpY!kpWs9vk0oJt2O09KxX5yu$Oi6u zEr5lpBqY<>!F9GKge@hn()e$dY3}8kyX`f1$uz&>nuqK)56CpXdL{4&%<1&#m z5YeN3I>Bx!d5d=ZluZ3H_wc(lFD}^k=$y>h4Q}k3z2+6GkH2NcDkd69T_MqSFe4Mi zT<6(UjcZo1*Q_Mdyc3#wFl)#}?%~F3g^BRF=H?>z$wVIEA`d0XNA1BxyQO3p9Z^+g zx*<1RkEn-NC1lRJT#tom^VmJbwX?%SMnI9y@8`M5vx%0aq`ge5E7$5|hc(Htp2y^< ztKK-#$K%B?yORz1LN1ao6B)o=zXD)kDd{WI8N_wo49}raG=i_oG>3D|5_`=dGR<*Z zbBw*_D4FJDt~o&_GM$UOCli?m5k1*W4-7JOE8Sn0sX+UvcAy!bJF7`<9Cwk%^q*A}7lj zwG*~W$qYK8-^)y2;HH0*%~_Z0Oqe#GnYSew3;3-`;!6F2F?nlokvozsOGyox*8N=T zo+O(UZn0rqWpZ>Wc^D`9csv+pcZngdagj%4A`Q9gdH@!dlE-8^aa<=RDQqK~L*w6A zrkTn$lk7DUWSXtGW}3Zb3z=qHuGv~9(w>VvDHG`g5k1<^C)w?9pU{qXkg31OJ@l~V zMK}8%b(IqrxaFJR?-ojEHnKfH$6`_XI-v2VcL9VuIJio!bC#G>dSbDf{U zb7&2X|4EtVMXq_yUh}L>^B=DHr@iJSndS|yc}*r#A=%g?B9g^Df`_sSMD%Fil5Dq> zY@;2oC{wS=J=~sb*=AD4A$wyF$~5b9&ByFD zHJPR#ntCuB$wZoP{KG%}CNK=_e1{Y~r#;7$HN;;BE77``JzngWv*3dhjqZP{wkBBu7Wtx$K&-dy9W*V zx46h4naBw4dKiF(s${54=UuKdHav%R(+G~1X-?ysQ|vV-$u#G1%~|%EGh~_zx#oPC z$Wkt{SSAvJh#u{gwn=%Ic6_-^eJl5{$(k1%?0d9MX6y@YY?r;}r&b?3WX2A2V+ZYx z?U!jDH@!ar64ln7og3kp?N2-KU;RD~@Z$q}Z%*R}JflOpY!k z&2XZRM{=0mYleI}7il3AX~SJ-0a#c{TFG>t;W|&Hgzcx_)A+ZOX?Ee79ql!rmubGp zHG9}=c9Uto#5H@%L|)+{MKX~$A)-h7wG_Lm$PF`x* zQt|_xQQc*leYs|Vy=J~l^L4H{z+SVTOtYA424y0{xX2Kh$XJNz(H@m*x0F<)i8n%~ zK9zfzWX+2S_C0!6W^4{OHp^afhSkUWGGmLmv4!@=7RWSLa?NG-noDJx>!7IzGb9t) z%#Cjd6XA1h2N&5Y6WPZ_z9?hVJ|~mTvXtCTNAxq9>2J8{uVi!9<@z#Ao6pR+bYm%r zNf(!rn#SZ!<{}B{mZcka@GmXc>=I^DTW*YvQZ7t1Y4(~^tv)8pj4j~C=Gq&ZEz?}e zH5c1!E|O`kf~FqKQle%Gn5{}CLUbn4xqvNhDL-c{071xn7~D_ZZcCNv8J(*L&4YufI%hFxML>6B))uhR8(5KtvD7 z$PA@V-y&0g^^{bhmP*P2t(tiE6G3&&IAs2zPO}JHxDZ zGeq`t>wCoP=t*twmgybgdWS{5=c(QyncfMmcg#-jTbbU^T<=Gj$XPD(i%jGXi0IjP z!9Fw2g=zLS;&g>;{$;OuS*Gb~W%#^quX#_^NQ@x3mh+#)>kf zJGfGHD1~L?OLY9I%5)oXruwbI*2Y(;W}Q}HYvTYTgmK($Oqli843T7RJpp8M=Xxzfy&|gDOs3bC>$SGi%arN0=Xy`dM4sm&&&ot{A);qv=T^3BW5+Pfp+=l~ za?Lz@&F(VILav!_ui0Cs*^hUqZzN7NdDdsQOwzXYCRz3$4olFQm|yi3n! zD)?6cFwOrFf&Q0n?Qy+lE(#icy@>t=+*7#TxoVn}uAn1*(2)p?RS^g8B>{g?0-h%U?`{vC zUlz^ljAkIGc~wHwUqbVWgr={F##I`|Hy~~^&U+Dh1m|rw%H!DRzRTM2tewCyOC*>> zB$$IGn1f81rqLd0JK7^)#4_5W>@$6|G}DL62c)uc3$3garBcBicl`QWtAW35`#m8v zrcu4f7v}b^fd9pj9O%%lFt?zvL%-aDKK(kRHFO~SiS1K;r)+yuy45fjyh7Etd3W& zsPCz>)z8&0)Zlm!Mpmz(78O^XQTamUOO=D}!S1)+=TQ`>^|G_i6VPcd73ao^zh_Aeif2Qa@4`t4q|S>N0h? zxIL

    z6rjGzRA96zW04IeRF&Zd>{H2`abe4 z@qO%D>ifjE%(vXP!ne}5#&=h+VuYfsKrB|eS0EZI-K%j7;kX9JwKO_w-Rlvf4LEMZ zaTAW4aomFARvNjj?(K-*4jgyl_$iK`;kXOO&vD$1;}H%Og>)Okow`H%Xp z=ej!Hb3>ir3Hl~_2Kpv>2Kgp?ihWZ&gMCvyZ~5Ny4Dn6#4E4S5De+DB4D-$KyzQIm z8Sb0q8R7fDGtxKPGs-u|Guk)TGsZX1GuAgB-wQnN_&)TE^DXqe>s#a*@B7Fz!ME5m z(YM4i$@j5mvTvzpitiK8RNpesd%oqKX}%Sn_kAlp(|xNvGkmK(Gkqb?EZ-W~Tnjtv zU}rt-Y=E7Ou(JtvHhVtsZGoMwu(J(zw!_X2*x3m?pTf>(p4q-#o;kkHJ#&4#Vdo3j z*#kR!VP_xg?1!BLuyfEe&vyuRzJ#5_u=5q{d<{ECVCNgyIqI43`_{9-_nqfM-!acZ z-}jzHzT>cW!t;^u2hU>PNxc3M-#_8|6uy7P_i23pg707PeFooW@%R{O4aLcXh>HNI<}wZ8v& z*7>e`*86UFHu!?xjlO~2O};_i&Awvq7T;j+R^MCRZN4Gi?Y^Pj9ljFpPTw%^r@ptn zpZSJ+clkzmKlhFF?)HuHe&HMK-QyeM-Rm3c-RFD9yWcm?d%*Xu_n>dQcaeXB_apyA z?_&QX?-KuH@5lZr-lhJj-cS7Rd6)U8d6)a&_pb0y_pbEM@UHUD^se^L@`n5$c-Q!6 zd)NBsc-Q&ode6D%dC$A&doQ>bcrUs?^p15e^#1N%Ug5pwUg`ahdzJUPd$sq5JLC;|)_4bc)_Q~Pb@*QI9pu^I zE%t2m4)$#FzUA5M9pc&I9qQTYE%9vg4)bjHzU|rJ9q!rb9pU-ZJJR!+ca&$BceLko z?-{_uY6x#V5yx$OPK^QU*2=P&Pa&)?n^o`1Y6Jy*P|JXgJ|J=eS;&wspYJlDNz zJvY4TJVCYCJrLi6)b*ZXb%STHy3z9%zK5urJVVvZo)UG7XPCOx^R~LpGhE%CHbUKz zHc}n?;3)N-2S=;p9vq|I@Qqb>roE$nnl?_|*!W#_Q{(aKH~tCgQU65sTmK~WJO5<$ zn16~o?2)PXeows=Gfll5^S*kp`E+$}%nbFXn3?LSm|5zdF(0UZ#mrX!j+uk+x$2?j z^VBb!&sRV3E>M?wKU9}{7peoji_}5hkJMuCVs(ReiMl2BV|8onQgvJGC+csp%hYqR z%hmI-E7ZktE7c`&tJI6JtJU9QL+T%~Yt%VuYt^}F>(qH^>(xzZ8`RBd8`aO!HmSeF zZdNY^wy5J;ZdLchZd3QhZddok?odB@Xs5bA_EUAJ_cOJ`yGtGB{aoFZwp;x??F)5x z+8%XtXybw)UA!bQMWZd zs%~%mt-7P}cj`#@F?B)X@6}Q6nV@^sJ?^MdK^~k->_PL{OD=* zU98sQv06{SYCX|?R-NSjOp_x>yDasO3(UsIR+|D(R=zOGL9-GE%sH_biJx6M7sx6xgU6=E<}hqv%O z#P^eXsBgNv1lNXPwRjuf!+kT|BYa!kBYm^nqkJE@NBgE?cm7Qs>)Yvm$2Z$O&Ns*X zu5Ye;yl*;o?CIFEPsL2~&2vxot@cmxO?`B#@5e^(`R2Q)`Mz|&@B76)-M7F!1NLWP zC7Olr4}7Z{&-N{J&+)zOo9kQTp6C0>J>R$3y}&oc{UNL^^euNU@-188 z?D!x12B8M{996(U)B#&i3G78JaM8Wex6Z%Hcg?-p_lY~?TjpK^{k70v=L5|ve*R4CfhWZ0C#Y9y2qB7lk(rb}8M!NRb6a;WWW%7E{%TZM3U*RIUOm07V zom8%ot{2IF`xCyXox=X~8s0iV=BZ>s04G$YYiD}-W-3$bmT(!uaLZ%$8u;rqcJr@# zjbdUNH*VM{rXIgUU(~Bx_wmOcce@+ct?NgFuZ}Qy8FRMJ~$ih~O zrXF7Djc&VT?rkomM&+9oa&J&Imx4Eh^vfJ@a)E^V(eQBIQcdpw3p$Y_A^$K;Eu+7$ZHxML&Fj;le%*R89g_R>>eaV*UQz!JPbPQB?$f7dVTV?2@v>gS zI`tdZsUK6XUfm9z^Llq^(WkKJY5(K&O-`5kb-MQK>2==;GOeh8es0&io{HA(zkkEj zM}KG3p-Vyk{GvV`@L;1Job<^dFY0trw61*$744ZkMSDtVh{My0hIdT``M8tS9pAW_ z)w#Z+rMAE;{Qi{IyuYF~%PY$2{6aJG-|^V%lukvR@Vd|c;rloaiT8If-Sz*_bm_ZA z`W8`ZUf7_1Vop?($BK5J|L zs7q15rZG)@DOq?lhlg!V8{u^;X0r~l*^%0;ezfNQ90SS3uIBpdm-)gmJH#X-$=>p7De`A3|B=VGGPb2JY3 zHdK^2c&_kQTm;;nr=Dx2N8GyGr2k4mUQwxmyWw{*F%TGwLoN&iTe@0Qi>#d0#I>PG z1WerBG@^Y|*Y&2Z%Pm|tTDT&ClTM&o!fs@GX+XO5>|59)2MYy_3hX=$({B;e$y0Fn zPa{R?)S_Bc#NAC@uy^aNCe^~+qQ3cN)oiE^A*yNk$JxOxk1NXKEvi)jkn7firmhs^ zcIwJQL4I3hDAB1t9f!Qe*tO7)h|0RVuT5(CeTxdYnj2~*MD3m#I2?l7?IiGL>$-NQ zxo-X5q}Dyxq(;0ABWgbpwJLt*t%mOHvPrEAek9r%>r+mbq5}NffThg8q5n3~KQ|MH z0fzqLy8daizFAF$+Hj)w*DM@=5vaRv#jg(V97m7MTCYQEB+;6^5Qja`ddSe)9#5wd)x>D#B}s(} zq-G0}pF4~pn!hc=;pJFGxvfXFNY{4c(r%L`@fW7~4m8IR&G{eUu;0+!2hD>fP2#h# zZ?|xt?-I=}_;=&MI;eKI&u>hc#Alc$@j0Go-j7l$ILy$5�&UN>=OC%(iVaatdF} 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 z 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�kpn3m;(-Gg-SC*rD?Dio#`?>no* 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 z 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�-> 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 @N4N5h11})_h%&?Wt(03As7v5nhV+NY? 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%0D;>2PG>GHV@zAg8=|NT7S-AcYqXL59rDwp zvhYA3kB&ik#~A)O%;i0i%STN50|0YdNq139Zx)jqJckBpJ@~08asZ3$XC2vB6gh%L z4z-RPEQ%bw+s z?I+8vWU@A*r$ni*vecJFYu4%fEhw6;%(Ah@)!@-sey5&hEZ+Yxm-4Zut>iIL)YB}g zQmn-ex6sHglb^PgRKWv%Ji>$WE;9V9GneN@E-y0aS^(y@k{Y6z`Ygs58+0L?q4mF4 z6xonP##u+kh$53&WMk{dMxw~(EHYK(@&%&XQ$YN4{s)$Py*{j3xWnI#~}L@334eg7VkFZ zve`VG8%0sOS=3G|tc^zYZ^=*FO1{GbeLM~X<=tfXA7w7zi(F1K=@Y?Q$&aF#3oPbb z@ElsL_5aVJ$Uj)*73;`LqR87U@=xo?8=^=@oN)p8TjX*-b15FjUn5vomV%4k+a=G=iWW5*5h>}Sx+0)jMPnk8I6eW9}C40^~S-2>&HjAub z9a&uz8Hq@}Gb2PU(JXmXkPBODam=NG$fYTBdAW#DONz7FN_J`^+EA4GRhGKB8Xo)t zM_sc{XIfA+n@;br==MP_yAi0Z@AsHXXY+7&6h*zyqH?UT4j9=#CO=K8Cm!hI@o7-r zgNA<}=F(f_GLT942QXKa&P*p$eAp1nsww9QRI9U zIY;EOgt;sdxvYkZ-rFlJC*@(S;mbwgTbaTp^Ssz#-J*4(WZ$r4yR9R?Hf!t>wQP-@~`A<+ZTbVUjv=Yx>ypAJKTiVISz+BV zvd5C2CY6W>`gp_#<-Ke8H(@S~L@v#kbP9mEtt43#^CpXVEk5XadQ$7bS45F*S!65g z$aGO;M;4iB9ob$K*_B0RiCjKlF5N^fxp2{Y`;&O9s^p&5@Q*~{{h2~v^St=nx<$Q3 z$wshbL#-nRn>7ZCl1*UA##$#EEsC7MBBxqMP8LPZL!{oBvqdgnvE&PaT-aJ$&Rmv= zTsAP5wMC5DYIV_>Uf>kRpK&^!t3;{4W~sM})~wUHH7J^`%-95DBYG);-%9R>thT-z zF_(r3rmZAi6y;}8O%g12xROTp=H#bIy^aU^c)Svn_YuSYE#~s3$R&eGw+1k`mAoyA z>BM5*NeJ3Xe$rM{2T^2q7MX1w`JO29Qx^G=b>xSl$UGL=Q{>X0x%3se41lTd^C7a2TO|y=iV%C@>O16k4n{Sh^qyPy2Dt)w{~=;M(Zl((|s z|2lJdMdb1}lm0J&xvk_)QA`IGlhHV6E4iX=C2d5J@3F|v){z}Wksq?i?$(hxqR7u! zn60M3ig_OE%Fua=ck%tSH%B zmTZ=FvKgYtB`k80b>sq3qSS|3>Vu*+>vZl9ie@YGp(e&w@<0jp@AIDQq{9Y z_VIyd4CI(VshU|Mr}BY68_2H(BEQLyU+0mT zdj`{KV@7UeiJZislrVq^s(cV)<3cx2}OG1KW`M*hGOxjV1? zvVq*2rRr&o{23p3&Oq)Hh}@4M_vMk9`*5Z+)QmjX5_ur6+{8d0%TkTDM*fly{KY_? z5QsdPAy4FynfqL(GuwOmjxoPWXQ{TWahq!>1;3~ zud_s6!z=p@4(ZbJ&c0$P)Pgubg5apJb_y zTO%Li11}oLKLsM6WyoiEWafT_>0B}+U$jKNz$>R3$TwN4>($hQKK?=s}u zJTh~?zo~J-4r^+9p@b-{KtlX$sV4NjW^wFW6<8 zau;mo{uI-B(v18cOXMebu94n&S&$S?88%)K$wX=FxDv_wwem0vNC(^#q$Yvg1;Fb98H zsLh2Ifyl2js$es8=^{%ysoD+!r0YmOCaL;2p zz0AnDmdKy-sahGxU$9jDtdaZjfu{`QL4nA_81fK-`$VQQ-i$of5_vSAiXqQnsis*Y zPvHX@^6Wt5`3!lkz6|bl z|7eMPluy;xm>9pXRA;S`&+vimjKC`_@RFI~q9wxxJ{4oQ$x>anX83~-B!-fXhqZt8 z;&7Dc`uO9&UTWI&($+s36byN>X7P7scD~QyaK!mqw#d%tn%(k)jILQ9w2aTlem5tp zOUqX>v%9tG*dn7{rqZcZc1}jumI?8Vl}3$Peh^WoWm-nZj8@qhEwfs`)6(B1qjPq4 z$0nJr1AeUDrEP1+A6F|l9(eq|f$kyh>F!zX6YlHodD3!ev9wCg-38_1Wpl2V%ys3t z`n!g^Cb%ZMrnzRiX1nIP7P`K2t#qw+t#xg7eeL?ib=#%qn1L*d-K*VO+=0(kyANG*4O}Et0;1`f_QN zR3NR9)=KN84bmoQv$RFpDs7XtOFN{U($~^1X}7dT+ADn{?UTNh_Dct(gVG`CJL$0W zgLFhXCjBTKmrh70rBl*r=_l!o^s{tMIxk(6E=j*j*QA@$U(#Lap48Km=jrR|?-}43 z>>1`6=^5o2=b7l4?3w17>6zo1=UM1k>{;en;VJN}^=$BL@@(_$^z8EN^?d6&==sj` zgXfs%gy)p!jOU!^g6E>=vgfMjy62|nmglbLo~NgrC-;^6%LC*g@^E>iJVl-^&zG0U ztK`-48hNd}PF^o>lsCzn<*o8|`D=NX{EfU%{#HI9ACwQt-^<73ALZln3Hg+KTK-8s zBmXR)mCwoN<^SZqSj^#Aj{aZaT813JAg9>apn-te1|iK zaprrR`2lB+;LK5+IR>sDp?4h5oWL_D@ysbacN)+Bgy+uSxu4;67GCGz^$Wbt!|MXP zeudXXc>M;iOYpi3uPgBS9bQ-A^#{DJ!RtD_Zoum%y#92Z@%-ib*>lTv)^po+&U450 zi|4NEyytJ%1wAaeakb*ecLnGeaADzeb+P8z0o}k-^1O1dq%kb@r-oe z^L**fl}EXI%A?)AqACJkI^OJl@?$p5X2)Pju(YlidB}$?pF06!#bMRQCXR zntPx;-91R2;T|l{bPthdxrfTL@jb^qOrGl=F3)q1kmtKc$_w0I$_w42lLL z@?!T`d5L?Rywp8jUgn-4FLzIrSGXt1E8UajRqiQrfqSaF8adY>&syYJhdk?%X9MzV zM4nCVY4T>|*@8Sl9zIIQSce!WCyWKP8J;<{cdA>oOeaQ1I^6W>R z1ITmGJxe}>Jl`SDVdVK9d452iBgk_Ud5*bf%Rjp3$j9At|P{aaepQM?p`ckbuW?s!1p!x zQu(@jnS2A^H{HwSKiws}-O?OrSY<6bA<9h65(^Sxh63%sMGh2GK9BJUXKEALoov3H!b#5-PE z>YX4h^G=kOdnZXNypyGs-YL>5?^LP4J55^coi45M&XCr6XG+_`XG!}aXG_~WbENH_ zxzZhZo;38C`O>gw7D&UNStxxQxk%a{`IU4aa7Kk=IuyA^`Yv*Oj_MDOy);*1wpQJ6}XQVaq z&(hY!v(g;-oHSSdMH=iqFAectkj_;3RT|*EC=K-fCjC_9k~IJM%hCw>3fO-K`&DVQ z{0Drm!S}lK?ejO_dlSBYO5Z&H7kqC?E2`d>_B?+FK6l~sx707%Ab1%MD+0t_V)D*@#cF5M)dOx@b>o%^nT$P6fpq413iap4}$Mt z_zv;hsX7$C!{9sIGdN-dd`H6fOV5yqQScq@85%LhGb~~(e8$0Nyk~gC1o%vZ&m_-? zh{^Do;u#q+75Szi-*nHH5i{UB6TY)NqatR*cMg2#dPYaggYSILn1}`NT?pSrp0N>M z!FMrymw3iSEQRkf_%8R1k5~cUm7WO^tKeGz-_@Rp5o_SP7QX8|lOoo`cLRJkdL~C~ zg70R}l!z^!sS#V@vkgAmJ<}p~z-K3XzV=Ly*ae^6o;|hqAm3i(`^K}k_CEN23*Y^o z84(BIdl0^dJToJ{gYRL_ueHC2?+@@j;yGXYD148>_eamHh~w}*0pF9J*%7DUd)hN6 z;wSi?f$z_rxe;gKdk((8c;-c%hwlaW{_2?@aS^`1c@{)mg70PcUhyo9_#M7i;roYY zQN%U)UWe}u&sPyQ;rpj&al~Kny#?Rfo+S}?JQtGgdVWp%+p{#{AJ4_4d!FBta^+^SDz2xN)z2(2^@P2B_=SA7&H(vX!a#X; zok8-qbq33Wy+h<7-l6iUh+*;o?{ImbcZ6IJF;brY{Fn0Th*9#Ih|%)eh%xfIh_Uke zh;j0Ui1G5qhzathh>7y%h)MF6h{^J{#3}Oj#HsSi7pKWrlcvjmB+ZbwM$DAAMa+`7 zN6eN7y5`7(U32B3u6gos*L?YsYk@q%wNM`ES|oqz`br+)Ihtb?ua=xxU78yW~rr-STwT9{F_Dz4A=gH;CDX?{C4iU!LVU zAg}Tsl)rNwk}tTvljpb&%kx~{qr&+?Uf?<+FLWK1f2w*+9_#uMe8=Twt`l+}`J_C$ z&M8zpr{!L#Vs@jBIfzPTGisTAsAkrBf038C&cpu#{3|-j=O#Vra6H;T{pHo_nQd3T z7v{Wo4>hQxLA#7rIn`^_7~*i`>SwCA?V8ahr+WrURQ!uX_&7gRf8@TZx5?}%w`;GR zL(K%A-l{A2rTMh)sGTd0V{zv`g>%3I%?I!4s9$0DF7Esjuig1C%_rjn?W9_<7kBR2 z$a_$p><_imYJ%cUS3^r5)aB~e1NbiPEL}o-5O7c#9)6)_oroH>UF@soi;(+TO zvL-vF{ZO+;jfjW{mn*Ustaj$@haHZ4_neNleLkD?M!NT(r6p$^nb&mwxWg-?@MfEP zwRbwom3+XVKKE8TrvtB_wXeVqS5K(jT`jmfA14=t)cNXD58=C4Qo3ff@7k)9t0B&0yPo^N8&RcY)66zqv$C_=<+${h zY_4WG-P&emwX9X6W@O8_tWKS}bAS^S*Lofy47n%)~s2h zW$Vn&Et9gcb6)dCXfN*C)T-XLV@JtV9%M?+hg~w-W_ENa?f&;K6tnbKge}{2{jf_; zR?Ak|oolwt!7;sCPRHtP97@})Y=`njrbBtvQ3r?D91317cI|>^{O$3LC;hE!Ih2GX z{M0nwp(K9jP#R|D_*=izQ2qCo^mBZxoL2Zb>;LfeD}%)ATBL6Kf0(-PRkHTdSV_#T zU8`<{7Y$5lo7t*;({4GKUo`^1YR1Jm$~1iH&f|5Q_<2L_VC@ZhGU3Bc8UF42vp%^|zjLt?r3R%sG|cuHIq7XWWM#I=NYBQ-xi&dj zUGa+}_o-L&+z4>2l<~ueLpYpIb~wtvUAmZ~)JTfWE+RG(v8&bCm%qco=XW@se!FyW zN2%Eq+crz>p?8^<>c2+yuXY%RW$@4K>F7|pcv!0_XQwD<_b6v#tg}?zv_k5P&TZ25 z|JGdmL6tTP8P=*9h9ALUbc(|vH&AI8kfQ3Ji7T3;*8^%Ttew{Debd zGaRO=!%;jjw%EzW&e?uvSf?mQT-xg?&Hd@klhP7m;cz(XL@!{x{)}Jg{kjjYhk-%p_cGkdR$DCCb2PbjnmohWI1w^ z(L#KMooc|)nk1#S&1%)LBSu^2pMymERQ`S(f4j`iZPRhp?c>D1LI>4zaQjwk!^C)P zQDx_J&FtJhJ*QRcj#ySXa8Z9tOI5qgso~m~lbw!>3{#wpRQpxMw>ibm8Skfe?glcW z+n$2o0o89Smk_(YwtjUk_1|EXYYoT{u3CBNAv}lyv96N(YZCz(hr)@??7cGcU$3pC|CU*RZ z?93h+>F63Yu!JKw3L@RJGTUksNc-2-j@;^SSJO`6(rUX-r!MLA|E=|D)CjKMYneCb z)2KyqqgN8rn#D9>vw|j5*jz4KW_G&T9~o`gXoexx4_d0X60{lFsChzD%%T)@%1<3rc%cMaC;rt&N*#4m6Kzjwy|1 zvVd*o9f7I-*HB#*I52VkrYSTmZy644618QnzQoa&H|xf=x^nY~n!&JPv;7W#?91tR zg;1+=X5n^V@h0&L-1=a)`(1xX_Dwq3!D#ajNl!5aID|oBq0Xd02Van*fyj8 z8+wDgp@ie}L}TRDIT)C=t&#P6eJe`BRV5(}NV^QA3HpjkNRIQz>z4?p5pz9=HlXJ+ z44?PnI(A5Jiq+ho`Z`GWM5l-1N`v zjJHU0*yd6fYvfmLXmH6?FL&5mQkujxS0`zCLts#{0rN^slNJeqE8|_=C+r5dGpJi) z;m%-e?dtEW{-$ZYW3kximy;d2oebIYO*NvJ_*lS%8)w^_VgvSt&V-Z7wYhV*POQP| zZhA$7@OzCN1FZ`foi2t_Z*~o^diE@%(|1yR;ng;Rk6~j<58C$FFn2Y)$`xMA*s{+t zp4_94tGeBz1B|VH57*ONc{3PoyP>u1epTIQ9xYvCj=gW>e%-2bI*Ylc6~Ga7r~>ZJ zF3zoTvN~n9!HcRw(p#AB{WQ|!?7FO9;{vz%{s!t{Z4uLJiMF_DsZRr1$0Z!E=vNT! z8Ufaijf>a|4&j2t#p;u1M>t(HjZz!FA{- z0oS_V&I$XP>*>JC?i0|A1Wi~E3vRZLc;NM=>NTA6>eg9*p%VDAb(Ge$bvkdOm>11+ zB_k5eHZE;O9|x>ZDoaZ^&IMhd(aY@WoNk?jwS2VEbG6vQ&|ZfIZsTJNpS5hm3fS)h zUOkL899LKr)B)3NobDGE787^}K)bef%WlrZf{eK6l2X!tR|giIOPX-5p$VtxU8hf ztG|paT-zlaqk~c|f>nR>fPuo#n z2%5+NojA)#(3B-WcLlJ~%l{IN5kVKUfMqvZPZE|G>rhL*F5Pm{^_xFN^?wtWgE{Kd zn9gkiZMzi~SM>lpS9RIXO*4AQVpJu=;5AR1N3E?^aR4_hs1lCSY=s7w6l}%MH#*@I z>nOSu1|(cyIIY&l*dNzC!Mur=aGVLw5ztW!siWTFx*>2=Er$j!(i*r*mq|!&(G;%% znMu6W>v!gk!ei~@F4uY+DyzLs{AHRs!c)EL`o!coa_>XK3s!scd*{3G zA)CEi4t(%Budis&Ddw zqy@eUHkdfT^t<+P_c;2t5)Q0AoUehigIL~DSq8WqxsRzVJG}XMW6=|NL)D(ZQT=Gx zaW3^kv~l$9A_7=@1mAcY>f`XXAzvBtyx2YxgS97i5Y63B&28<~KjYr5wst@Idz?D% zXg|h%fUAlA8MKG&D*gb)!=yMqQ1P%p@rYf;lTbYFRgRHp4`YVOYCDg!8FtL1&&@D= z%BMErVeNJKFTgqLRn8F3X9mu*D$ZFz{9Y2mgS2iR9yKR5^nCB6R{-djusx@NlH^ zAVGAX#amPDg@+^a^OmWb<8p0tT<9uz&_tzgAo!eDdl=<`@mQo%Hc}}~B;9CocvX_e zB8^K%SrG7RskDhnpSAe7SZ$DC?XkJQRyk6s6sc4swl|HTic;Y!n~*9o+=?bRZW!If z2y2hA3K*Y_RGuNgyug+9tcmX#6P4a&__SNC%V6!{)CA58k%~e%{Q_}bFySZy9DK5_ zh68I4r!H__B$io$m!}s^%KCiv+EuIvMIR~7rPgbumk)|orB{7wE3Cb?#z6TcQl75P zQ?=Hqug=q#OwyQ(g|!YoCRpojSbGGGLC`2tNsLqyh@-Q?5vOuA;J0PIyOxS+~ClayiYDQ7{sQ>5}PiSw0vC$_J>YvKUYR;_Nv z(T5Li*5(qdJ)Ca9$tD)Qa?i%#e51}83>T~1_h|$;`nnSVtUZDrk)q1IQ0yZTgS992 z8JhbEHJ7X0KS6)*Q^!51a?iD^mub{I zW*9zHTbp69_PTsHaE3-Ig9(SP+=l{UtJ>|XavxkY)(FCawTCqxSYsoV(S*fS?qf|< zqfJ!$1sxv)uJsbEJ)G&lnHs4~CLFGEpK8LHEWnvTII#9`<^pFnvGA4qY?CxMZSaZa zT8F^eBlrpg3yFZQ+!q#2fDc922w?3ItOCJ`NM#v8aFzQCY>wZmnm!x5M8Z|>8`*+h4+4HItu-;}vlgGuu5}TtJ+?hy+ZCzoj8wK08(+Ea zG9m3`xZ6!|+(g<-jIj0?zXRjJNM%0(a+Ui*6W@LlmEL8C2?y35&T-%zi&Tyf4p+G! zGvOQ&;NXMowGo81hjRuvr-_BD+)ta7_4)j>UB&ZIJV%OL<$ex|R;AYkYAdY0wqAnr zMN;M~_lqWJ%*Dd;<1!Jz+9UWA1UDj;Ymv%T;@~Uy8~nC{%KaM7>{mA$R=Hm-n)NSY zg|)}(^fgrOMJj(2C||kX3oZ@|{x;1QK!2lE?l}62`Sb}38xqzeqjG;7Smk^c_uR|* z@_QdrONpS$y*w$y+EcCs<%&L~0*UjLdqtmd1EqqQL%TQcdx}6{?SV)DaS;Vyv%7rx zc}LXQ5?Hez)oOMeeI6o!wMX!*PgJuPiakeSu=d2Np}AG5xm?X&6+L}a9r2)=U9qcJ z6N)d8B3HA&AW*DjSJ4Z_2%l1iMEROMg3YZuCVjk*g7-={Ps9Ij6H zn{b*6aMB0|)*jBQz-d7&e4XCHEUizK*GL=Ip7wvC{U&Mi75bYZ?YBr9)}D3-wA=WU zRwU2W=54SE9&_QA1@5P}GLh(2Ogp;(SpewdQ{MF{nZ&?V<(=4)eHR4$n#nXV=_O_t z>Ks^mo%12s-uEfpd`dR4@m2ZzCZui*H`@%SPn#Y@2WyY67wB?*%BO_J)#JG)vQN!C z+Jf#)II#9``U5B5r}QBlt{%@f;q(#Ud_g#{_Hc#(XArS)_4pu@vObfC+EpA0#o?sL z)#JmVXjM>sNo|F-*VeI69!<)8JwDnbjjMcNX)%rnVC@l12fK9Q;KN99^?=PZ^+Pj~b zLEpUw5d>`L5W@j6lnD5`duUXC-l^ca`?OYfad}!kB$=6+=W78NC-A`p$TZ_ zIBF(WZ;wOop0=pBC)!b)3bo0k#?{)B1!~jmsLg@etSDs$3G#LJEH;m3n6#TfejsIHDFdnDJuwutFKp?SXP)>w9D}tLV*n( zWiwDVMk(tFg{!SMno!mYP__^XZ0IOEfwG-A__}(#Syta-z9wDR&~?9o?jF+RYwA5B z-F>7B8@ldc=pKqv4v;igPaneO_7m092TT-t74p3u@ly~#5vBYXr5q)Fu9iN*mgSF7 z=hwzj6OUd?pQcWM4ZTx-1=sl~4gwiH;2`;E`%Parx!x7p|`OFR39Q$zGi;NB#WB4urw%1>ad}! zKMwVB^^`L8lt+nyub0c!qpbqM2hW7+)(t1sJYC zD|iw}d@+Ms`IJ^Gi&z z_!1QBM=Mbz%2(6%*$j&^>2ouz0d+a7y)I7#PC~R2M>u?4odAgQYPYlBG>I!3D~YgR z?O~+=D>+(eLRegdoou3NVxrP3npDDpwTJT>a9)X4niCFJWxry=X)eHdop507;k*T$ zmc+tW+AU4e+_Xt20$6(lZ9&kQ2>6=2bug1Xq2(gU#^|b#r9D zY0|+&rB^eZ>|%5WMozTSHCpLHBwQVy!xnT`5b$fMi-}2}weM3G!P@JhT(Er_t$ZA< z^dL6A7XQ?Q^fANjVS?i(Qcq%pwa3^GjD4e(&k2yL%KMu5J~vV6UDls)VC~@y1}rY?ZB*9Ff3C_F}y3Fxo^G)e^u2Slz4 zgg*n6iw3GfK(O|JY5=Huj8ct&j&VTM1AwX(4OEkWVC?}#0H_YpY;B>~SC5oo?J37Xxj~E)P2%@xZA?+c z8$kR#Zbslx5RIRwVWIXO=T_GVK=kWPoLzuM07#5c5(pqHMqiv7KwY_Wc4i?XaE7h+5;L6prJ9!U;^SVSwjPW1{V!9f`DM{ z0gVCBD5BvmS))t<`Xy^DDZ|=Ro(Sdfq|9Bi#`DT-*P2Aiu=bQ^KzUk>GKIvsOV%`q z8<(sp_<4i6PJ%93GwlM*2f*AIWi|nDm#nz~0J8-E3+w_c1;FAMWf1{zm#oDB0E+|w z%j^QI0>BDV=Pp?*pct?>vB58(!H2as_#2?SE=E~H;@l-`9lK<$;W5}2xzVot4#;nd zQ8tr2cgfm@3&Uph!oV(Bn*|s<|2@VM^;On4#wF_)V4RInP7?-y$vO*;ohk>rWSz#D z-RhaZOV(a(zsAvbo(2c@-wqCsbs1Q{5fgXG`VAei7XZPpvaZ-wyaB~)G0IgE({$0h!fRXny3$cdl%G2(jY{#gB`IIKOO5&(LLXt+z(LnZ+Il2wwFVeKiG zhH@!V<}O*KcxAS0l_6zVd&*Bh`SDn#9Eo$6tj8g4T(ZjH=O5H{5_HL`U>Be=04l{Q z6$ya5WK{|Ps3-t<+AhE|0Pw^rZUW#gS)Kp@w*VmAECF?mT2F!al_|Mbe z!`d7CnoxcrR#8ZtyJWo(YrM)*cno&Qs%2L`67qFpl{zHPU9#%N;v7>|2F;+jKDc{1cnCu!-!urbsT*^k~(bY>Zf8w zZ{ZgTohBjJ(1p&TnP;e(+}rnO(8s^1;~exyXXosw{R*}7q{h8_xs9lLw zE|DPrw*3`0n=YBOx!Lpwbu(<}-Fyouf5s{|2!(&k{!aj$QoDMPc0(KYb8i%lbeoW1 zLq{qW*HCf9DgO`>_jbJ_E|};a6On$UFCM4Y7_gzEJPecv2jMv&gvTjzoFWkg_tt!PoN)<|q0X-v$;6{i ziz?JLu%UNNEpXL{Q>w=))rgCKTfT+~r#eHeW&-0TPHp0Y4V^Cve35ZVU4rA@l8-d8 z)in|6T~&`zU_(cV14>Ms@)DtNZ^y@&P+k(C#1jf^=qQbVl1LofTk(k|RekQhY)35_ zYE4LudmFw9)T~M-KeZ7y^foqwYAUJnZ^5UUWHIjw%ZKKq4ja1qf1&`#F7QJnHVA@MhaJ_6EpwU^ipq4#m-PxVaT4WV0F)rq6;Q$m6b z9Vrh;y@-dq8Pp5?aSP(XH-kR6qxJ>V`o$@INszx0)DMdH=tfXqlR8N5X-&t`H-MTB z8+y}+17>KPGMHfan?OSWaFuQX4K5mH1i`?D4l@ogW8#!i1jF9|8WR9Bs%V(;1Opp7 z%oM;(A`#euBu@E?#JL+jO9I5d5{NIiBfbXW1#!ws66bFA6aq(ir(X$?E0s9Uc>`gS-u%Qq34ybO6Q?`&WcavvZoN<$93y;8V^6a!D zy${lR=0J7zfg?hy)X=qO?F_?Ox7`YTTU z22Zj0{Jg>H2n62X8KSA<=({gof5{6Qy81)$q8mJgLJyM=Z0JIz(9Dw5Ozs9x$@u)< zL)38&y210P9kp^$D?@7B4W2Rrwa4tJRfJlFc%?iE@;7)Y#2c>_%bT>h+4LlJGi>PH zECIz8uT&-!{sxZ=0R7aiW;b{$7meg0B-qfAo(EEuc;#6_;%@L%F%dm$BGRws)d&SP zbd=gasTr@lKq%Y|o|-0<7X&DE2n9BDlt`e|B@X@uPhFENH%)w`4ja1qOHi**>ii9! z`bDcZAa&T#)f1tf5U<1$0C$5Y0h``%b<<-vc;ZY%`itZwI|!*j@W(4nin8%Y~s;pXc~15Z0KF{Cb(XYS6+=*S`Zh1gXeV<&Z`Wyg$azCI4y|}HgvwW z;AoRrWGchP9`>8p^BU zl@%n;SK6!C-nGKS0jBX)K6Ar9BoEyNoMl5_a ze$6D!O`DrU0Beun4hU`$0bh~dDw^Of5y09bD4x(zaV9AD2!gB1oeBAQbJfj}Rps|g zRC;9-mS7X(5nz-^P##K99!Svdig1;AiG)7%VT%tX1h1tBaE9O1^jTXfLBCT1Yp;u* z0NdjUO1T8346*Um`Qs*}atybO367gc6^Iem9-|A4l@pXo1jtqBl}&t=OjLT8xd{i> z9?o;X2~SXD!r`j)a1)L!z^Otwu=a4O1E(6XaFu#Bld?XaU$CoK8;Uhak*n5gLeZ-9 zszYsswbxcJlp{!)uh=6@(wK{dq2}&0d=PUQFY+vhQ;sDc9t!~EA*Nt#s?cwwQ z&IiQ8SMDERaMr4GCa`i}rxD=j`-li&?Gb#IAi7sxD3(iNu=d3A(A-|sT&{BOh5lZr zj(bq${<&Sneo*X7id^O1SD@J6uHq0V4oXl4kSJfd4`MTHfJvX5VMD3QVeNJKXyAOA zpo}0KzHFAH4p+I)GU3b+;LIf)SbI2&fU|&D_{x2ONt&BBUl9SUJ%Z&RSV{zZ<-W9Nf)zvn zYmZg|Xg}EYB`A9nl-?&S@;zd&AD));}v?{$WQ(Ix}we=4u|4zz$<^H=#8gsF*{J2I0u=WVha# zlQ{Uw{Wia?pmP5UXSS*v4XfO57R~xMvBKJ8y}u#;Gc10If~qsVat~`5R2&u*YZzQW z0eY=gx#Q@2prL-V05&A7l}6?MA7DK}OkCyu1ORrZr9@EWUXhex?J2vUTp7PZPvU&# zUb&%h1ErFQ157)$x*12Gn{Z(5;e-Q6CKkSOmoYfssBsiSm`ZkIgWzNuQfx^{LBY?R9xPaPXH+4G4#?++zW;Q|)$Exi=^pD}k_J z?O`dt(z-BNLT=K~E+eSbI1vfYS`WrB66q<=)JMlPbV@g>Yc);k*f) z*NKI%++R0IbJM0J5y09bXa$0FBH%0c^r8t`69KF}f=m#!$Dafc1XsDY$L4rI-5gov zo?)WWE1h@jVq^p3y@pB_K4XhWxXS%KwxF{>z^|oFCMJE>=1>>G+UufE!1hr?)eM*e5_89wsF%S1^2#~AX^GtlbOjLT8^(7owdpLuDGoYc; zpK!R!eSit4zW`@2;lSF%83CMO#KKkX!%WKhd>(06aSRkkks?>QkAk9A={1(x3Tv;e z6QMkwl=;eiyh$2!v9SD@L?_{x1IzpbEhpN=z!)s2Q#?o*3q zokOg!_E?vI^(%btIDzt&`&YrmVZlPvd;#<~TIG(TZz*BHhJ;mMRPNh=wS}0t%6$s} zj;N(XQ02azlws{D?}73z{K^K2^OgH9wy*6pae(QlRyX75+eOSGk`QDE?$u@jMjIHB^2kQND6N$7a~iCVg&(U7#+9wb$jp1LrdS^%LRnmHTBt z996rWRqnqPjdhisD%-0w>aUMSqOd5{QT?GZczf)Yf)SMDW>CMZP& zu=WTZ2SK?+r3^uEm3z6w{Jfvl&5>2^WlU6hrBmK6#?!!fDp7edQTY#%aFzR0iN?*I zCqclkrT>_i^jYhoE`qh!MODD|Y@+f^qT(SozH)!og!Bx<^_bweiBy#sVeK*20%MIt zr8)s}m3s{nUv(3e-et832i6{r4>;aLC4z9c%H35nOC9t^Su;2~Td;#<+ zt#ZfFmrhu)Az>XgD)%pd)sL9C%Do=|E~=$OP~|>=lws{D4}?+QJ;tW#cD)$)z#o2Zh7eaAz zqFQ63(l6*62?y35&JN&gOH{TH4p+HvGvRCz;OrzESbI2ofwP-f_{x2^Nt&BB-w*+; zJ%WQE*iQs}<-WgYf^t{iAt|@ezc2m78qv| zmD7pJNh0AY_cLrkp9TTHmQI?O^jUk3x(L=@7hM6{r9|aoqH=-Q_{#l~3F#ukysSGnIb@m)7j>0NeIFcGF|0F7R35ToP|1sg*72r6N z^q1(c_Hgb8PFRxu5}m8u!;-8oh!5CRECI!bNRg}DAA+J)=~a^23Tv;erJ-Dkl=;fN zlt~(Mv9SCoLjVC@ksN)lD>g<@Zk7_2?9WoYgaYA#o~FF}8gQ^!5%p8ImUiUm+y zNs3(MzEYsL+OFb8D6UUZ){-b+xvyt4Y^_P3n_-)%%VF(x`A*<$Pg1rL4qv%%2gL7O z<-WCOtgi_R)*jY=VC_p%_7WCXx$iSk?KM&97xV*!18WcG2ynhnQobV`u5$n0g!7#M z=P2R8+QT^soa4m8SMJA6(%iH;MFg<+2+o4w3=!~^`ww;6B?t%BUYC^xPU%KUDZ=3@_tGYuQUaWEgad02rvh-w6AM?lmp3Wv^Z7q^ z6`z9QlcdO1?oUF|s`RQ%ZH2YhRtd^3Qsygnmq{9Pv9SE`5CN<`f@&bB+DLh>krGZE zeC1xX5x1?Na(@nIrm7natK7qjW>tt4)*fpFSnD)WY7r=3xz_;}R~#19GR+r2kJT!7 z9DQ{O3-;e)ootFvlp0c;D)&*z_@L=zeJyj9`^e<{-ZRt+E~s)Jovd#pu=bQELV0|$ zGM2>o%6)vYQMr#bae(P>t#ZfFH;Hgy?cq!Z&QxOIEBC3%`FZoyITKj9&(|t<9DOs0 z0M;JCoMchuUMMz~#9-}-EktwYQ**h>eLnhozB=wfmHQ&Qic6umm=w9neX&4snO()z zP+XO)tRPXoa$m(}*b0+AH^bIYm&4lY^3A~6n5?WP9KLej2#CMA%6)y&SX&4S)*jYw zV11pe>>w=X+w| zEBEhB(%iH;N(8X>2u_0FI1%ub`|+X)P7wjDJ%V3Aa5h;vLl9i$eiobKB6V|QmHQbJ zm0szbw~KKV7*~>&OUcSbBH=3cD{Mhu0s+64E}EG1S^Ecd5v;u~x&yXb$;zL}$_--U zEB9L_q(2$%4HFzUk?s;BtUbmsKmN?luQ>b`m3uLNaF;o7hQAKzU3Q;ezy8D8!zl@z zhyBWfgu_+t51Viv6yQ8UII#9`$^xe}v2c}pX_K-(pUc@*d;*G(lOk8SKMqB!(yIcs z71mx`D?zy;Df5+kMUyn{lee;vx>da+m$wwt~uC!kMM&M#Cz1 zSJAA`5-Y4d)*4`~?pLZ2C||i(2NqWx7F09M7eLR`Dt8=xH3TlDZi- z^lokglvXK9I-&5Dc`E>{QoEY{9(#JxNNouTHgu$pKzb)d=|D(aRsN2NsDp_}zgTx7 z6xh&Fa)8n`Md?B)Tt(j1gwjQT(v47HLr3WWln;o5uf{(x$#T==BT|PAT|F1-pOQLX ziGNzOdQVb^4P8AS>U~m_JObdV@IKh|HmjQ+tHSe4M0(ZI&kn*cAPh-S2Bjzih=QxY zhpkufE5ca7HuKFHKRu%YwK z0N=C}WeUM@_spl6*ru3>^sbsoD6pZUEC9;96lD&fa8>s_6UrO`%0fbc4IO1EP!ksp@lgnH{xNP+LK2T(!LdYE~sv0ksh}^fs=8>KanzEA2HVS}~wEfhv0o&TLmV5>{nzDw=aAal(eqxgVVSQk1;}$yeC>f(yEW zy{7pA;PqOCjic`XA;E@%^t@JKp99j*#KYYe{~6+6tK~pYh5ZYu!iKJT391)UlnW%x zSJ)TXo^`>*0G{1ijfx@e>?ZVW*nd{3as3tC|xEZ0IO&0_F8o zN#gvF$`_*l8##Wy|0&S>~}t0P!a*xOV&V*qc80eX%KWZFV@^yMg6gC zVsl6H+rzw@vl!`_Rqx{Z#erJ8ZGurQb zsh~1zmE+l7y|=n*Of56gRSh(b+Bi5}-fC%%|H0{g&B^arYMnOobFY`d|HQ1N{){}0=xHpW-X&{m4o`b)=;>Y# zPmEpH>w)5q+&>YbNwrWlHLn)=7)teAjCKw`l1Ce6dD zK)~;8s$m8^lia*`6|}_f^oMtkT8A)4?rjJM5<<0i$#72^?Ddj*7pOwiZtZLn4OH^h zR5PXU>Q%Ip&Hc_61)hNJtEIR1mGDkcdVBx2l2u#tD#7S|V07YZ07nkL^L0IKK%3ss zmKo-1D9h}>erHQ{T>pz@RyVDo@?x4&+gM|7`JL$nwK23uJ>Hivt@R(ZoiH*Q(-`Oc z&bM_={LS}0Y{p)k##4T0tMJIQf)^31ZL}UZxgpc3Z z#w3NO{LZ$4VAy)qExItDtEj17NbPrKXx)eggwl;2{Lc1jH+DcbF2HUTpQgkb-I(cj zz7w99hVI4cKquwiR~9oaUh5l7r{kW2Sgnuo^HGnwYVN74@7;n#oW1AqHqvKKM|!OG zkpufrADK;%$?7WW6!5&d>kQMDr~^y1ES~Kg@T|Ip@C!H#lM6C_XBVvx8iv*f*?wnN zwGXn<2TRZgP12N?jXucnJG+JZgZrRKKp(tp(FffN{CXdx>V5Ej`0aZ7>UjuVs4YTu zX@;k%i*>7uybF5>Q+0AlJk`6Ty0AVlJxhXK!eYA<&EdFJ+l32zzPudfI6Ycq>}&Fzh_ zf|gp}My9LSxp_Dfuvxx|HK#w(M^z}g+x0}EZqMyoC|2kbey|>0D;}{N%2(CBvqgR{ zZ9!-gJU8Dek2b{mI6m!tTWd-`Y6@M%)u!lA^jDiQGJ z4o3py849D#B=s?7(i+U9_GwB+n$jjsX~kyJ2;F-mO!zy&GpT*ROveGR^m;pD2=FABM!{WMw|av!@dTd46Qk8UZIGvr?Cq?t_S`Wl5Gcjr`m%+?SNN>HLmESd(bQ8LC-e;=cWj|(0C-?#R?|PKZYAoFjYA9;I~eg`yqcgD zsIQmwW@%?86rQn6sf~OU-FG5<1J)cm11Tq|`PEkj>cdb*e;N`X&r}#~^wq~0{jnJR zu4zgaHty4PzZo#$-O>uWXrqe`(tcS{y@qzhnN!-!9JNQr$Teohj+QNp&ZFuDD|aq3 z6?D_m;JSJg)j*EcqIo#4wMcy!N{g21q)TA57O9WXqA6(6$7xEBH01-xcK@Zk8M`7F4vB-54cQ{H!4%f)n6uP2Cr_iELF=6%R*5kSG&(Z=isWr|x z8LtY)qL+G4l+_o26J@n$HmSb7(h5G%Iw!D?Kf{@cxRUEHCI9C>-l`JyDokVSd?RSd zY*U{vO!^#<=BP-s<;am*leWXbmycHH4|fRt3mc3E?1UR8Jyh`E8#Shg4s@aeyFSNGfie6?DWu=VzygneGERD7d=rpNB5*prPBTh@`Qm}Bv&V2Ir$ z>9JK13%o-rUSStJh%Q)!F34L*1(VA=8vB%`gAQ38LV!l*VI}oS|7kTun|j}=Q2(2k zEV=6PGG3{4Hhy3)S#l5KX?^gxj{Y8}(b14YOHSbd=6P;f0BvbBXR$h>U&)wW)8+8q zY1)3O?kn+)eM8WFgVG#y*7+jNB3_+e&%LO+$2YD5mxA7Dcp@Nc1uO!(k0E&nYvQLN zUXY8KHeH*Z>M|jZf}V&j`?PnA=Jyltr*`*pxv))D;N=5R6+P=O@NQl_K-m>AL&s_f z&%;HVq54Dh6`!?#p$PiwBHXHAUgO70YQ)EC3%%pC6PIzq{-9OSlU+eFi-G$cr?pKE zJ4C=HSKPVI`?SO9e8lN=uJ$^z-*w~{cN7nM(BX9CK3Lk}c%<0<#hqK3%O=UL2IucJ#&*MN@bazB`yXGD=#S>$Ew$lpYfw^-y&>&WY($a^gE zuE^!SNMm4&Me+m7y7CdY=)L`Lq@!KejEr{OI=2ZJqdMqwr}IHk_!CUwu}IUrC>v?n zi={=$+$>pT>&QxGjf$dVRavrUt&=??imb&VU$Bl;M3G)Z>Ye$b$fZ6@?hA5ZYb}wiyZA249sb68Ko2lVeYu4#Z4T@&dDU(IF3vy{{EZ#26 zrIUF$-xWo5XHnT!Sjk5AkH}BkN^Mc= z;aix(M)SN_Z{4D`qGWqnvR&4ZJIxx~Mad4cWCyL2?H5I!V3EhHBaet8e@3LKvz1w%MVIsO z7q8~V;(dy_RP>pyJ{3e!9v0>DS?qAH8`+;DKW!^f@IW7rszG_*F#KyVmls4XkxV)Q zz}!|+M-&soVxoOP*VE!!RZ>qB`7(=4w2n*=MW(Sxzjb6&QRHhZvW3XyE#~s3$fX@z z^xkgcv#Lto)FxglQFs@o(8)Y6-nDK~rYKntmh64&$ZlqhY*Dh_ELpB~vQI^kU$Dr0 z>&QN$$f1bTJ9Ci8iMEI z>vYZyie@XbZ#u$UcVrw5?wom_<>RTgd`Z$h$1^mUZNxqR3+PjLy6#a(MtQ`ptx}dV;l9lDRx2aw*ST%GDE(TA6xQ zTS*&jL?0EUcCpk?so}vdaMU&HbUqmr%~s}9(MIzsM)S>UXDnWsxwxZETglU+sH!aL z*=P%_&PMhZ$WPl!>fnJsxoZaH%`*HWnM;Jor2&(!4`6O9i4w&mv6zJDpsl2X)`M}P z$W#`YY#rG|6!|)fe8oDlxhOK7MYa^VWH6W3B9~5Z(R=%yXsb!tRcm+$QTY2zA;&x~ zx>~oWizr!7mh4mO$dAn$Jw(a+vt)g(lYK6V9L6FCTSpEQMUFk#|{BED)S8&H_Ki*#?dywV}zEwk|?eUiwo!D zaF6jzhQRkw<(CW@=e;_8T8>M@r{kxLw0^bTndD`5WlYj*dRX=zhE8biO7E%3wjQ5tP-cW5<9w zwLlxcbWv<~#*`gA8<%L2S;4b$xzUB6FxehK*;g7ac`SQRes-+Wa(^a@8^GfF@o|f^ zxW1ye5iD+~Roq}v+*lSjO5`$$xr`UN%!G?R8>d;%j445p8;pKhz#`{bN6r>SE@P34 zts@tSA`4i9Rs^}Q;oHcPuS0k8vvG|mXeSHWhM=I?xLF&&&7#=zjOlFfY}~0uo(`Uk zyNxcq!eoC7%D&fdxyiC$<7dY~E%#MX+&?Vt4j;Eoi@PO?yFb?0>5Ip5d$AtpjOF)m z##xfZJtT4|!(2*PW0b(f|L5`w#dis_*|F-%Wy`ARzXJyF0UBltDVlQcT%|#FR}!P*L9RNC^oY(W7+s^E6 zHmAJak5N5!^FM_rT7Mq*^LyG`{~WJ!#;D3wE`15WLehW1$mR~WxfSJ?^dD6tc*Dpt zINCb{EYSfi9~fDd=9Z-bTRsvkb_ox{6Wp?_QI%(Tm8XoVyn-rPv|ox2l=T0lHv9!6 z^H8o(DOxu!Zf+SF*z!#y%eP>u1+$S+ z6%Tiw=vRf$wRB!3)u_sUd6oBz=(VQNfs+1ljH^RtnGPj#xRAoA^@|{tYd8ncVWOj7Gjcul%r4_%>poVe@w_F(5 za)FWMDsEX2*m9YXS-cUW{Rqp8*mpevQCEVWiKFA$ll9cm$e~jv>y;2TOwEisP7T5Ih-uh4RDo+?y zd67#$=l0v!o-wkKxQ)&2w>>?oMzErhWfg828rZV3k!3AzSv|1j8%CBcZduo;N(8Uc zz^FUtiZDgLt6+8&D-zUP70=Fo^$XPS)tZ87&ck~)fjGSe1XDtFd z`@qPu1GoGzuw`2#%dW80g4x-qN_XzOn_m?^*S_FY{%2IB53iC}M6dN^lTP<)*0XAl z<`}si%v}#OnzL4Ge?MzJGZ%B~@BOO0;GMiHd6nh*?p$hQwT@e@34~S2>wOc|Qk7C*n0z4dqVDnA)j`ISrm;=h#qY-DqU+Z^&ALoccEKVW2ehFhKtYyQpdCjQGJznK+qbeaW-e_B60xc!4sSST*itsKd;^x+(5+%rr51Ny-LDFt zYvH^~9iuAIyh=n7z1A=$&{9%W?a}&1u9LXyx0tzqj?Ct))f(q#&AYH8w{GWGr8*4N z`Q43I>7wt>&PGgU(v ztzU;%scBTD0he|GSXfHJjBH}KO;oJkej2AnFv7?(nOi0Vwv0Eje4AS~4s4lfWZ8^c zHZ`i!f>+5fs`4SKXwhyH8z?JDQyZRXWS-3xKGKhiPJvt0!N}Q{+}US=EkD(3d}8FR z4|kRq*jY~_%Wt@4|G<|0j4Z!}r54N~MpZ_0=Og^8@VPdDR~c(mWhSpOt%zRxj!in< z4bIzYk4`pny@4&#Z|9|!#WHuu*5lUF%nROKv}KIOlZoG`Mv!fh`4kD>R}_@6hjyu&ST1-86l zWEs@Ry9qoDYHv9=Aa~oH9xsh&* zd9jh-f~-aHc_U}9ac7kSTRQa`l998T+*!52&Z-(&*5j68fi3G8Sw_NA3uZ&3DzV&o zv|klI*AjS@IHM{}c$KswdM%|)wl|lOM9B5=Uidzj2gw@yUeLU4urKaGC)*lo7{Py$KpTVn4HL5b7OV0tY zkd@3bvRTG$7Wt~9dT!Ywxjwp?#yxszLNH>&arud>Ie${|$I zqWycoK{-He_^(Fhr?|p#{kS+5xJ5^doL%P5E(Eqbr`I@Z}FtR*NrT#ao*Ma zL14>!MwTUEsRc76PF&sj&@IEAKk8S7&$TCbm9j=vUgTAtiwm>?XubAKT%e_7u-cpN&jlQmjLq#kIgKx?n6s#1|Vf6=cB zpKB7YVl%3u@G7sx2U<$BUVAk@&{8s4?a@j`uIqBwwV1j8Qo`n})mp>Pn#XQrvbPJr zO%}sD6^82kp1`Y&P1Y?Xqm8Vla;wS70kCF!z0ab0s?>Zu(fVVKpWiv&`ips$?~SUg z`GRMDb+GC9zooUbI>Q)Ipwr zooVriW1Ww#$GPQWfh|iJSw0C%EtutvsyxS?KkZkA&$X9%l^2YvROVG=k8!U#Jb{*y zMQV@Qj9gdeuB$S0|D}Y@S*x{*pEZwNc#1dbbyCFeE`^~wzaw~+1}VCwq@IygEVqhI z34pc6>pg+$sZuF;qV-3TpWh$6^_%c2X+~9=ap|T27M7BCjBHwQo8~Egqi?wy!3-nI z4&3s?z?N-|EW2^bE`cpO8(DtFExQ|4>A|afX;h^zs%X*fof2qJ{-`!Q&&YfzR~V!p z7Xt&gsK1f3aopMHz?LKR8pDm8P2yb$Z{UHoE_M5rjg}hSZcxi-l$3ecfQoG z3ZH9hc$Jk#RkrXd8;j_*^=#7VUUuE2_UJkz*FSUDyNu?n)%ug4HJ_QMx%COZDqFpi z_ad)yPT!qpjjXP7t1E%9_ISPjP4(2JIJLz#dz8H<`sM`-qYOUlL0+Gk!FFzZka;1P|i^1nLskupl8!8T{5$o5B#kK z_LX~3wm~`A8XQz5t)e9erGnCmvMMWsf`i`Bo(ET>^VO-Wp_c5s{wf9}eksk;sk4Cl zf+4Ow&C|eM|LQ1bu>K4U%!XlW_j3T3r%aXSZZO9{hO7vA@Ymv@L?3N2Lw?*%#>X zm^@@dh_xn}e5Z2Xi2;4TW$4>u==*(&R0c)n1Fq3DpvF5m+p&FSN1>yeu#-N6zXHBw z)M{;Ph|??(4jP&T7&au^6HEtIqT4#s^G+PDO+dKJfQtB?3Jgu*H+vsZ0h?o7p(TZr zmd#BzX+I3ar*=g)2(|sUOPVFycOf{+hNQJ~Kmz8on|39;Lua2ZW~&6+{Uvn*zTz{p zOBWV`;DKpnSkr^QNh{4}XYimje61!zGn7IxOe=%GrRT$`96{wsl+4d4dOn)UF>1-i z=jUmbj@{a~XM(<8$@#y4?dopWuAW$VTDMn!O`IkzYm_zUD@>GDEqvNqk;ObH7aixb z9$ABWs4G`y%j`}n2V1A?mI~IO9N1^K@Lf4&IKT|Y|3}JL9#em*8DGZR<>{yYx{%c4 z!iK961%ql=5B_jk#}fFu(r8z+CS5bTbZyo>vrDJ$&D@z?+hup^-0bbFuHBlqZ<5(M zOX<+OYj$RrW-;yrB|g4c_d2zjrDe9yY~D4qS*I2sHuH4O?AWzy`^2mkJ`byQMvJaq zdCpSu=?Z=9U)%fIZ^=vTE9}edgPrT``|LaHyX`yeSLNIGd-gl_)AAU{c*jD=632N* zPwAlar}T$3Ts|#blpaVur<7^XcQ*6_0Gi_SyE^PTOwT?%Vo+sxLUMd&J ztL1g_26?l*P2MT*lMl&<&&e0$i}Gdps(f9(B|nfK%6ZOS z&fd;^XFuoH&H>JW&cV)M&XLYh&e6^>&T-E1&PmS6&MD6CoKv0CoYS2%oO7IWo%5W} z=X@4qu`EGMm)e#fs!MIlaV)@b1&%A#D6h1wMy%K1_ydk>aa@Pvk2tPZdtkk7Bl=+z zj+=4Zg5y>kx8b-Q#~nESgyT-zXxlD4+HG5G+k<*P}jwXUGnRn)qMTGvtQ25Q|zty`#d8@2vMtvjf7*EZO84>j+j<^$Axh?+U} zo3f#T@4)+Ac)thl_wBuH5AgF4DmjkR_8yKi_MVQj_FTtb_B_WqdoRavskh^V)W>mB z%6FWS`Z`Wa{TyecuN`Nl{*J$-0giLhK*xFM8^;A{kmI5>*l|f3;9oMB1jvLZQ$4zOJV?nx6IYwZ*9Gs$sZn(TNW zO>sPwzH{WrQyo3zX^x)qbVsf{!;vS?bo7#EIeN>p9ew0Ej(mBpqpv*A(NCW5_*!1z z=r4co7$7fn43rl+zL6I@2FXhtgXN|8S>_lbFLw-;3mn7b6^?J^m5$-^D#r+UwPU2b z#xY9%!7*B1>lh=ibBvXLbc~bNJI2c!924Y?j*0Rn$0T{PW3s#jKDWZpHu%{NKRe*( zC-~V3Kf4@L65rptfA&vE!U0Y4|<=M?;$hMzO=bJj6K{>w2_KIfPvpLfibFF5AN7vb-c zW3GJJF;BjN$5-)l4L{fMa|1s&@pB75xAF5ge(vDsE`IJg=F9gT3*-lm@8yS%g>sIx zQ0^ful6y*vU z{zh6W50ci&gQXwkA<}wzsI);ICT*0zl{U%4rOomPX^T8k+A5Edw#lQV?eZ9DhdfsL zNggNdl*dcEnEtFP9~8Vbi%z&I_cgnopSGxPP>1S&bW6i$i-=Kfu}?mi&x3O^_fb{>+3I1fuhoqtFN z!j4D>!;VUa!j4IY!;nXW9hdsPb^<>qrH!sr(k9nw>3aAX=|=cjX>X&yq?6(2q*LMN zrJLawq+8(^rQ6|`@N-!jiT!&NcJQN^bqg@-zQ?Rvh*`G?vu-hF-H+JQ*JD@jU-zyw z$97MeYr8MavptZG*L^5mi_4Ku)$JjluGxtQxi`h0BqiGCg+gQxBjnWW#lQdKw;v6Oqbz)?PVPuDmz|Tl|R_#&p z?AoK{n~lcEw;GL=Z^n(2Z^ez5Z^uoL|Bjm|--(+f-;J9r-;0|f-;euFeh@cRei%1R z&WWEcZ>=*!KGSHXe74anxnJek^4FE;$m_%B${WJx$vxud%RS>4$hq;~%X#q&(b?moGFbkS{h`A#bg{Qr=X1mAt*qYWY;`8hKmoALQP3 z*2=r%*2#O~ev}{9UN29M+aOPg+bCbEy-EJ7(PsH_qb>55+FRwRaogl+aogn!wRgxj zZ9mBaY&+#&?YrcGw%zhKwmtG7+t2b~+g^Ey?H75dZJ&I>wqG7*`&Itd_M1H1_Pad7 zc0e9!J1CE`9g;^N|Jh~#1ND!{;~YojO}1n5-?l&HWA5Yf73qY$2076U>6CmIx#m6l z8T_0@ruCOR#&%9#9CltFYr7y%K(;hSz9f&cU6y~aT|wQe@_qX?{9Kn$+HS}bY&UTZ znUwuDe*Tt!cZ@VW?w%wPf*dD6~iIbxyP8IVZ@y z@YCCQD!h+#x-H+iJgl#ChP|Kjy!&hCUVDG%4BG(bKHEU&S=%?xnYKaByU3Ft+K1q0 zsB^Y$n6sb!t#giTxO1*;gma#4q;s@wl=HBAv~z?!#<|!w);Zrc&e>ZY?_42Ia4xV- zbndiGa`u!bJGaYIoO|W(oIlD_ox9{|&MUU*&fncLoU6iSI`7$LITzYyI~UpJz|UOg zW%oSib@zPud%^NdPST4OOSuU4`cKuYR?9vLu|9l=?AsF2Ix-v-ud~N$ovxp%r*S8XI{!;opZFZqI=G8r z|4QN~*xIm+`o!nJ7~ZH}t4?@z8~<0mc6fN*y0vQio?{oQSF2X1P92ohYg7*pV`n~i z%wl=?&}wPb`>P4>WrRIgRA%b$vy!3+0_`?YUv;w)T2INS5y9Lu`G-e0l7cw2h~eiizR5fz8(Uqu;H488+DfhceN>9 zI<@K2yn`(kXS&*6?H*Pqv{_PC%PyU|c50n%)9!C=jkCM8%IegtMz!kU&7wPX=+LcW zR`#dO-i~gT-lf!s>O>5MC$Hu%9sPm3BBB_%x~5)YlP|MqO*xs9Prt4NPg3)x1qow``2BYQF!f zM@L(ph<*9))3vP28>1^~U;sb)V$QOUEMYc_<+-;X$71!|Yi!ASE~kW5EnioURkU-Z z)N>VPhW+DKc>67@W6Sp4TH&P->c_6lTW5C7Zr-w8)wY)M)@9#(G_*?p<*koBdw`Nj30 zS!S;OvO+EMzS-zjoj3@se)Hb(+M??FOyOOY&WZ*4<_Nw*x^IK zDrI)_HZ@w{4Y%GwB~-@0@Y?bNX0qr<9LmL6EEPV0NsCl#*=_NfNmh1dhm2M=vLI7J zmC1oj4=1X3SdYV-u&LU%e2DdWg0<}R1RtBs?y6aDt0uJyQazd3@(nnggxMQy%a;l| zo?tznVl8_<#iEWvRV}kai_BJJti_VO>zT`puWiI(X*>>LA#vp&t$Ui09v(-K#{WJtSYc(giGtYbzOW={RC_01nZXxR<#AC&Zh)x-pi(wYXqLLb?%bYAuBrz z`LlO)v2gZgj?3M|VH38qoC9!Ns?_cJ)*XomN2%K>){?0}4QifhJ&HCrCzo*765Z)_ z6p8Na!yJ7ZgzYW=Z9EzTM~{?&qf2h(vJ;nN6gah( zy-oerI;&%=jLeR$xZ4_Vo6p>SQVwp9zsm#=!QkL_$=){NBNu8XwCsepO19z36qyJn4yY>TBE{Dk0} zIaKrXrYSM1K+lqFcBAQN%|KP4f0DX2WpvHX@WMoMsVuYr|3X5NIB8;BhV~6sURUp; z&Npxs(nn~H*6-}E(BX|HD835FL8@YOq#EL`* zC#NS{EbMkCq`jciDl@aQYQ(9dAU0eTJN#_dtp8=Q&SZwAEnn7y$j6Il{IYHd_CNsfOzCarN~BJXe-TOl(9Z&_V4SUfV> zB-Wx90#_qdSHV&02#ZgTNy>AE$ahn&_Q^m}PEHWMX1QY?I_@G{M`;_(-WXd5VZ> zS@;_de<4o^^N4jrt4^PEL_XIX9T}u`Kq3$)sNxR_7lN3yvZhSK9Kp3q#WjAC>5dP6#kYOItzf(W@j@{`gTF=5NP0j>kygN_+wRfu=!vbUJ1=+QYBhP^WCo z8nlkCrYwoY5cjLvo}>lvQ;1DgnGX5(UbH7Eh5Bxa7pIh4?K^gxuZ<5Lz7-lsdY$Te z$Yo(Zp`~8&S!KTSdjG@KqFd{X4#>&W#nk0JU&;gf!d1(6g_`QEv!4%Zz1^$sTt3U)M_#Y9JZhWbVj|r!X+WCf9igNAkbGh_!)v^p51&Rc$uVi( z1<)6Nrnl}Y4OFODI8;Kq3d1$4BR&hk5*BT6)J2?Tse|JdEe$bADT$HkY^WfRYEKwmxWYC z&~J#&TcPT|##-tPD2*F$Lsw~SDQziTuW(*M;(y*LYfVts&6KqGr1*5~|LPXgSX(q2 zYsMjxFqS%YYQ+|;Kxx<-mFIqvU)Z6SN5lIAVRQ%$V$1mts)Jd4c<{A={W)L!D{Z;0 ztxYlSrpKfu`@#l!TYA!G;f-vJ`^TJ0ns{l;I=--F)o6taYpH=d5-m|pVl$GEw6y8c z>646>_&^dqpcbU<$PH0z9l%0H(15__1v9!fS8uYkk^KT{{HUV8sD(4K3A>SDpUA?$ zkP$+oJFB>YS>d~8oQI?TLKH?PPJuq{I&!(wI~7F<>guI^1ank^8%jY#B$cg>5DURNAsZ>t8+>xy>~-Evi$?dq=W>=N8&N?3;z{)*wQ*`YemI*YM76gF1WE*4$B- z5V|L1_w3rhqE)1{<*v4Ws=FUhFCq;1SK3lQ!xs0(YP#>w9CAk(ZmncQ5pcK+t=vyoe;)JY*hV5602KX-WbW6^+ zv){Zx%e3}K#ivuoj^I#tg?u4MX-yaIJSsu#0E60+Y+);S^HzANhTR=&ubQx|Ap-th zhS))ssY#@FMWS6tjk)g}IphUfr-9LAihnQ0?Vn?R=ChmoM>^z!&~3Qc;$x-?B6*lW zcMs4!UQ0sL{$RBR3$?m+)NU=k85WyPN7SaR)Oh0~Yx@tO(iV$0-+i|rgoW=vEyEEN z?{@6%DW7RgDSF6Nx6i9F!svJajH4>Xe**jB@j2#=ZwWs2)E6Us_k};bbsh`2)dQXO z`O=o=ftN=vciii0ae%uJpE+r1=Cr`0%E$dFFUC`Rx7F4M z?}qz?sN1bW27A4@t8klpnhl4mVxp-4yRU zw77Y1K34lI&OU31cOPvDCl}P_gvWSizLwhhuJjkZQg7-j@q3C(-b#vpTzQqt-YQFI zE^2osXpDD7`@?UEWj*Je%IsB`D=KS!e+-|Ibk(czhfmU&5r?#q?$)n)E6nEmW8v$e zZp>44+X?cUeLmfF-RmHMJ3#1s5a_j>(w1<)9o%QhxS=`0y9(;U+__t}wlMR=?Fd%E zn` @)Vc77h}m`um9s;$Yf#RYt@at9i-);_0fu3unoE7yCC__f_ET)o7K1>EW>nn z>-7@}rN32%4+5=PK24_Op|oX*VV1?0oIBq5E#fhzObC>37@kC+?rTBTWMYz=AWy;lySs2u;!`*l+}7b&E<${Nax5Y2*DykI zaMLHAhg0?Z|5e)lk9v4Fl{E3~sv-Ezmyi(rl)_JW{N%8$TP<_c(uT(o>^Yul=kXaB z^}3e>?>u;)m&7}}mf%uVZ0vp32KfBa%XnH+eV3L!!|$a9KjOV~6i=*{lI7l4J;V9` zpZ2euMqy@tv zc~R^q5<_WDY!8~di<D(;8kFQhoy zSMe7E#b3=T9){w8P}2;S%AXG>3B& zIM>6JtAsPy7w5VT=c)nDEy6)*4(A?l?hwleZ;!psVsl3)EexCcM1ay9K~Q+CVhPt) zhG7DMCES0i3IxI7+DeVm9KmBCC>5?eLJ+NK@>XY2C>5Tcx0o%COVq`2o~_^!9hJ6# zls1d;6fi1;E9JwLvP9CA21ghpsSxhnGRlKMoJ(bOOxmb@nnHxqT!<=y?WJ(#g>dCL zVr%N{s(K9WB^}ZW9QQdLoY0N05F<)+jFrLY3|Axq?CCqRoH{;9N2P`ARl-4O4(AQv zDB;TMgww|tN73QDZh%vba8R1VsSTW(#4^=)d#b5Z*2Z%kvx+V#hLPe7YQ36zg+Vb; z>Q#^0iqc$L--L1lQl8AlDa&;luyNWzCylXKnCnCk0ZMZO@gQgvuEc~Z(Ztc-%Mr~u z8i~uw5?etG&TM82&02M#S!*kZE}Hc%Vnu0=wJ}&z!xayKP5>xN1#{kFpsBzTlEVUz zZoB|`G)ouR(UneED2s(P(wn)r239L#5;FHz0QiYzaDJJ48&XDTPPqe=+l4DxBray| z?fANurQ-n81~qTS(bbV~P@2Q(3Y?FKMa6r8%6*z?m4Xj3*o+bDyZg8E=3yg>X=s!UP;mQgk5i<8Rd_u1RfjE~|=$N!oyN*JH(p-qPfo)5;vMF5IKx|^>zD0+$ ziQ{h2!3hItJ29d($G8`ad%~4n1Sn+gdvtuebW~c%ejyx`=5P)I=l5{sSHcl8_uq9m zzZ&2iA{>+KSR#ThBrHEGdhb z`&ped#$sXmah?cJnj^RYf@|T*m2l+}afq4wHE~%%=6(fd_OOM9XYQAZX1z(QD9y1x z1nd290bB@(hWKnfr4t?+Yl;=sDEa=3Orm2ugDxHh@$l3NdG|=*rLg zosAaXoc(~Bv*YNp69Gzd1WuPx&R!^1iNsKv6MGHKeU+Lkdj({2gv<}M|J zdJ9H(!*)PraRH0G)I>Mx-VVI=Y%HY<6r8?KG*Z8 z6S@cCpfrb*51igEC691~e7v^~C(i(g52ZQ2IpCY+Qf3gGn1j#qPxcCC=*9?A!Qa&!97oq&!b16P zv7+#~m;b7tdC996tMsfFAph=JFF*H4fc(2xJuUM`S$x&6q1v~e(uah_+`Df*Z|>bk z&!DYd{RskP@gW8S;u|6m^X_lz<>wvs&%2MQc{h%(A*7D7`0B&!8RguCLL*2BW$}f^ zpqZnnnL@rj3ei0lAm1KqMr|V0#*>Kuhm}gJr<7kRboAT@# z6kwFa5Ab|I%&n))CI~Udo(pL)UzlwKvw&bw79VCgV3yWX788t+UoX|MEY`EA+i?M* zpe#PhTA-|{r>r6rA-7(mLs?~jvW`$t79V93P&N>Um{)Jm%W6x^X3|AjeBB+;-A1}% zPQA@Y_b1XtS$y4Jp!;(@Wj9F+`Sj0N-2S9|dbf^3%R=^<5&r|?hw3Q@>M6gGzK}~F z;?wc~)Wx~+n~q1zrH@chP!>NZXTWu;o^qm|@+WbLdGskA&IykCryfijCTEEZW%0?b zfb3E|_^^_ZgBIM7vbSO6rQ0@>4%HpFu1j>El z5OU}HI#q4dTI!on3#lKg1l89PAt7%LsvkHJDp6lcgisd0jgLaLB&muyb4i^na^}L+ z;4xB1S$y>;q5edDrCfdGabghj@H~*jWCpqNQ8ib_(N&R3n8|LR-^v|9zsRTH>9w7ph<^u9qL!%73P^>hGp)@B}4$Xa>nk!_{k2lQEy%Zpe zE^k)xDJWJTMIn=}V4(Q4S;ZHj_E|1IN7%DEePM*XL?K6MF60t$>h&qL6{WehegWmrNLkF%KhsHLEEc98UlIXIa|C@r(5s=6+feC2 z9Ac*4OI%ivujk^-O}5bRPnz^7nl+zTQJP~N4AyTNDgy{q%-p~6PYw$P=*A16FRGb4 zj;l_ivU)_ z1JqVWC@V=&%+6Qy(X>*hEsUnM6lRpg5A$ZAY>ZIW6N;FbZv?Q_482wD?&L#074f27Z$xv*&gdW%AXviPB~M8+x)B9wa( z${peov+oBwoO>Mgjt)#1IMzsQ<3w3}zDL1VGEylKsqNT8=3NpSlNhQJ>Q?2uwrin! zj8IS(ALR+4l#5gzCln#;E~i6z+yJElp`a{2%CkUunmB}v`)Qr3Hg=ygqxKTiULZ9g z+kOFRfl{WIsf{R$-$pxBUm;a7(|$!Kiykjb9~`8PviRz+Lp?N7sT`>|i9yV=L-Biy zKFbEO?8-RPmn|eb%XSvcS%o-J7N4^=IBP~K)d^C}uxkQINazZx>&6Fwd$1Ib9bI(@ z31xARa@KiY8-EvA_(nec_ouuKfc`A|^2@TDk}^tj${A4pPo(lbiHn)`f7o)Met*jQ zIu0-mRC8S%T^|q*N^>}wz-dV=Vz%89F(1jsi*L3)N+rP2)tU%Unj`oy(kSCD6l+If zD9wp=LUTJ%bA_zC1L8f3^}F9Ex;vXy%!XnYQWP@pE(VI-%qo5c#ZM!ZPe@eEzCYz7 z>=T{7Fv32kkfSsg@?7Bbh*Z8J95Dm$0f>Pt?EJOyuZqUXBP^8Wu=)e5U!;;xSV9)w zPe+xnqtZ6+0fd9n9L_M{42e_*5sr|F57FTaGQjzka8R1V84a9~#3E+nBX!ckuo*)H zD9sT}1i^SB5Hs@eMH5US0+i+mW`JN?r1Bj>2wC|wERJK@;>fe|?{rjJW;4?)#zJ5$ zh*ai9DszZL$jle;2|W)4;#``eW70QE4IDL^vqT;rs-g?UBk>!V$9c?K+&T1~@wj z2cb!{szVUq$p(T`=J;p_4=LKiqc$L4@3DNDT^8VL7g4&aMrlrYBb3)iDeFjF%-q-Wb#0xF157K_yctK= zCc;5!4re=Xwi1h&xo<`1tYu@yH*;U765#0CK?Eqx5$rb1+zZ9_kQhpHV*AkCz0_PG zbKi@2uVel0m$~mZt9Ss4zmcMlx&LOMc+jlkF(@91QVx@-n7JR}BkZtFUl?J3Qpi!7 z3;9{#oQ_gX5{{U;p9aJV7IvPwpDY^dFTz4;4(lqgE=MUB2}{V_FYBl->Zr60{Tkt* zG>3BsIJcven}j1|?zeR~Hw|#^5)MjpIF@L9)PY#U%>98*S{OFgX!;;Sv`KD{fXx=IRE$<$A~rE|x9N~7a@?16 za6&gq#E8-yi8<_sI-t(Asm$EaB2dldbIKe;Ru;~bsf$d1~|0{ z2c79n%5t5ep-v&*bvLnziKMIm#q55+*K*PGNp_oUCLgt=l zpxDQ(;s7Xq9j){wQ89D>nvbx)I(=b;4Wy8xG#B!3fipB(8B920<~|e5m6qwOG>fqT7(YfUYonDlL?UGFKk^B^76js4TBBpqM(sul5lV9*+6lHD z(aN@HWec&1nfneM(l(B}MF%Ggq+P^_(j4QjVB8n2>?J@UbKj@q+pD9}LiQWspfrbb z1UQGIm4k#MWbTJ`I0p@IjuH+^b2uk~bDUU&%>B4dSsTx%%qso`#WSQRWbS967%25R zM{PxEuC14#e1Vk3%>9B+8e_3A{kTj7D9sW44T4+I%8h8{8gYo3`z>)dtX4QspA0C5jAhd(G^BG zD9zzC08Tw(5i|FC=$yN3%=l*R_f!HLT@8rBj(D9wpALUUuNxkBb1 zgLvO#{qC2!$C*`3gyLJIC}i$$87L;1Rcs8!RJY6?hPFn+<4upf!98MSDbS4%tbMLH^7KTk%B0y=5pgRaYCIT^Y|F~#^ zPl*7fIf5JzeCbv`CkP>P{}PMiL$)~b%>8p6m6qxBFpJR-82N6cw_C|05+QTX=M%a& z2*kORr(@Da?bj3{l;%P-3~WQ(${@Egkl4h`eTWWe5XT*;gA)eQx5S9j9OF1Jj&Uoa z2vEq}$LRP*>8P}jjVBzG=5VG0XNp^yL^wj`K1GK!$pB{>;h;2!GaEQFiABiVXX=!- z@jS<@;sPknBSj%|p9jT2sn_?^R+Q%2x&+FLNLkF>7wM!i77Nplr9^Ki?pSefJX!i^#%_+x2xlxP~L*ioQ z-YBLw{f26cjsr}8s(CYxuD1vWr8yiAaFU2c%-oY=^7Hz$G2@%L4{)&WgTc|2LIfzy z5v0c$W$uMyO-Kx-IkBc_?mN_6A#;BR@gBhX-7j;0&#dBqq1cQRh0MK~fntVP#Y`x+ zj8U4CsF=C8a`ifjTNJ z(-~?OV=OR6$0#FXl;K1oWbUK+gdPb3aV`zlF=?ZA9EAv_xe!eQ+jlX_7r7Kp}IVtK*xkqtZgQfN)Tn!&wHLB{9k(!Vxm} zB|4l%1~|(J2c~z zz-dG*V&>i`AwO>%8#BI{`*<~T$I1 zlbN8jBpfkw&jiFJA#-n8G*(-}LTL`GGq5@)DD4SL$lN>XsM_nOv<>|u!a->cr#o;y zPEfK5N66ei*5PCu;CxCrD9zz~37pS~MayWv{5^PLWI&>h$ezDQn|- zxmm?kP+UQZLgu~#ih)wE)zns$=GwXr%0G~@n7RL;lg3yqOh0}k0+i+mwu4}6g0eY5 z*+?8>=Dt;2R*<=G#+j*Xq2ZbP#-dqw5GzV^toy*aH$mA$pkn5}*FQNd*rOXSfF7r2 z?l`*k6Bf#Ui}h$ zAwX#^1c?B8D@lnXpgUfmSO)YKAm%fmfwqFUqJfeK2&FlobO5C#DJcZ>PykBv0ZJ(v zs0jg~Gzat^fZipVGl{EluV=}LW6^n62cYdb?~^i0bIKV|{tqcXk+iyZ6lP2kQ~r;r zyv>mq$u7D+AZ3*1lv_i&Rg%(z#HA!{Zlo~rRuDgfKLUqCK?^+onaz`J>O296Hc#4^ z1?T{Pc1cPW0lex9(9Q=S%K)IGS%7Q+bV*V=6F@~@fG$1&oecoGnFaV10H2WhQ@)-5 z2^4+SCf@n~qs~WZuJd!C{AH5zIf*|{O>e?F|H~u{v?ll|_*}%`OJonT^7)YOouuTF zd+SmTLF*s{hW5U1Ew^xLu~nN^$)#i>ck6cQD;tf^2v zPg~X$9RX<0t0BPAHG@Kc(p(7U188oNGMj+JEo&|y{-7;ucF{l!2neM)pk)ABlB6sm zAaToD;sdm(XrSc;gwh<)Y5=Vy8ez*?sRPiqtTm*J(wy>-P+m*Q!j`pGROYMJdQwJd zPI)VoHzz3@NnF^nHbdOIWo^Xci)^0wZCTsQ0_+CB&Lm|A0SH^xP9K0B1^|1^0{jYq zeM!n*0uZ*WeLett4FG;K3vdVk2S{DmvJODeXKmu0f0#NSrMb>O4&`G>$`KM5wya}( z%Q_-r@Ga|vS^0C2KbxeSB6(rUI*X0r3fma?mUYSik0$5m-C`Vk%PN60ci0)3Hz zihf(xlV%m4hvKuz%F`q&ZduPlwWp-rWj(DU08LLx{lixhzEYGzfYMwD>;QTtS$Ua& z#4YO;KwPIS>*b<>90Y{Y98f5LDkm#W0ur~Z%058OqJdr`Ae82S-T;t7G{Tmp=m4}W zs~RbzG^bn($~8z?*s^Mf%6!$TP0A?EDc6H?c(PKL#Dy&@9OB+Bt1ce*k@QAd%FCEh`az*l~fWJwyeg<-n*<+5rc18Z=03>59HrZR^BCfVas|S8$&;gx56#! zT?35&{(Fq$$sTK{`Ue?Hd$3)30=%97s3$*n02}XqZ|9fs(2nH!*Rd~DtpL^X9;GY^ zi*MzZ_jupRFRNn!&o}DMfTQb4LP7a&he09Ab3l29IK;Q{pYi19eam{l_ig;)sydFY z=Sdx9@zr1U7`=sGC{&SzP!?avfo9sMnZn!mHpF;1>u0~W?Jk#l;v>BYqy`?P9w7;D*Ei4+)zcAaJADM9pe#O0BcQ~1lxRW`-l~t$p+p;?#1RV0 z;-e%1C4o4^x9JmfvcfP)CUum>S8ojUR8kk;qE9VaJ)P817GM2+s5kW}?+}3S_Iy(; zdZXB)$KRfRM@OW+yxhzTLM9MedX(lKC4(r0x8_^&N!uLi;+)CQ@n|EoHH8Lc@k7%I zTpc`0JCBk@T;kjE9dtPDIBJ#-Oc*$wi4SG*`MQJeV~>(eaKc;iAM4n%bwpaIJ|z^C z#Yf2j%9kGHb3zf`j{j1J^0@&@4?;m%e3afm$s-Qot@u2hsy24}m{I#0YJEvfcpJVi z)B>eU{i%&8i{HjUP#s9B;#=?ob+QQ_0dot=~0GzlwrgmzWqK@TsH9b z`*55Y#}*R)_WQ7+ImZwu%Hnf=2hPbJWgc$6vzhx;NJG!P463XHr zy{=~11wdLxJi^z@Era+(mJax3*eggCW${(lLUoNtSw+HPhP{TbS*vsm;F+xExH!7j z5emxUqih1o2I3Gi><#FU8ElOBX4o@TbsSxrNgZYJ)wdgF*o8tnNC;)|g?6KvJE@sM zhP@Lpp2_;zFT>trMr|L|_L7>AVed6i+iyng5Y!HMl;22D%&-se(e#^6TNq7;Dai%q>eiH4EFoY|-Nxc8Qe03&dk)5S|3W6Ddl$ z6yNj?JMX(n3|4P*4^hr7BRWq$sZuijZMf(V@I%fbs^R zpe#O0EuhpO4k5#?p;Of|?Am73!l71|)PxMXF4O|0OfG68%Hp@NAyn&=s+eKd*U4hs z6{Zhwk~+%btH(h-Hbrr#C{e^9X4tXfvVjcSjWY|_Lc%lbsG>RJi4$e1Hd!X3>!yRV?sjtZ;=i@>#;WRSkoI@P&T$yS{R3y6jId%*JFLV zpk*o+xSH&Pf{ySusg}a$73Hwjsg_Wj^H|?eD`=nF%fv}s@L1oi)FM@@UM0WBla`t| zgoM0mu~eHD^}WRFdaO;=Z^edLamd?wtZf;2JCJXS$1l{RD(zF14^x%4-X^s7SUXhe zl3G*!Y-$bm3knGyYsZ4Nsrk7JrSNWyv{R+Fsi=aB3#Eim^;G9dAHf9Jm3!u1E~7TD zM$acY!}Oy{*Aui4POiqMxKIu6zOIne8ck3`dq6RJsQ#7qj*wc;-lSbF6|_e6<#l}Yx>u@_o2v9kRlZ79zDQL*OI1EiRX*{C^?x4gXO;3(E1gf#g0T(3 z;B7DHg~qL5jawlVukKWnik(KUL}HjbzT(u&Ok^aD;A<(8Qenn#%#~;-u7q zL28`XkbJIke(ru-wHdklY#6co)XD?3%HOccQwlvTRxb|HE)Ld;AzCq1D~4&swni34@=c% zWHy@X&acpF#mk5On8uvXDsFkWs z@RMv>jpp-qB)Zum*s5C)SbZ3$Q-jA^Onn0ZEWZB^VHs3I^*8Nig(0*xH2@nQ*6Pn%sU*tL17 zm7K(P#*dE;D67HFz=7Z#h)X0sDzWFN8y3!9E>me5yE?H1F&(ru=&B*@A;CB@zujXVUp-G zb3-ck&b=U2n-+OqDjj}_ny~}6)Qrojv!8InuNm3}_PMox)(p0;7txGexJ=F1jfZFk zV9<;`Ou%RksL>b3SYabg%z(Yn485Yt?_=^4jklr8>Q1vCwF)L;dSAv!?(w7zYg;cF ztA3uWtsx;5aQ*)mbN4q!epMy^oiR;LWt&FWHLRoBLyhM*3qcYdB<&)VxflKPR_6^*VI2n3h_4E`T!r{{>jHdlF?Aq*9E%U^9 zufRIwd7Sh~?_UXfK>hjxt35oZ2abjWKdA&@ff$XYJ{%HdS<)06!Id(?&Pli=d`KJR;Xh=zT zh}GYcW(kFauwq!#SSVyv5J!3_E`-7W7oE81y*Uj^^FCzDX({ZbgJq_Xg8zuYEjOsI0xupaKI}#Ue_uWOlS9V zYOPRQ#DyxjP%x974G$rGh1LBh5zJvX@I_3_s&GV6d;P*uoa|thz_D{D} z)Kp_s*DEdbh67oPshop}e0w-voJ zqe{^`^LCmf^;iqFREv#83&!FQj77Xe%En@jCD>vq9afTJT_2Uvf(BaA5Jjb*QY&S% zv~2^@wx^L*F)MW>2ph3q{-&jUZ!+nh)GSY%?B3obM;RC^l9bawiuhnis# z>0uNz6VgLplbwF)VKi!|KN5KgTk3-R6)OR+@%lW2T|5Vc})yR64W& zN2?WkS+0oHstFv?YV|fArk4zb1fu^A6Tot;?b8KQ)$KaCJZ-D*va8c+r^G7CcFLyg zoW7;+;WUc}YP^q!7aECe%IMcQEL>tKb)(S?0|s+OtN^WA~Tg<*4U6FlFSy znlqjUcf@Jxhfa8y{)nqQ8VDm{?|p)tbY)J2`R>c+OTv04oB77<#KUf??@;&&g@2s* zgn2UT=kBa}31%CLE>stX&u~f`jA0e9f&Cw2I2?7-=YWX7jQ&@`jXLw zghB!h$zfbG)GhrlBD%jmug9?+g~UJ32#cqS3}zH9<6sVlMX zec2?O41HepG?}hje6LTz$@E~?LUqMq@7h#alv*EaAWYPhsR7=dQJprx%^iCX)Bvv^ zvIijzu4oTRG{Cz7?93yq4*P9o<}_4u`5k+R2;uBhJp4!9-l~XhpT_)sulk#ghXv!+ z*%J1G+QJ!3VT<~7_J$%HnbveD{;(avAc& zDwg-J__A+BwdIU2F~RjBhPoy^``-vx^!FE}`3r?VglP_ZF%_Yk=HjIKPV87Ty*Tg0 zE{6j+UyMRsW!ZD&jkQu^mDkgh&@`oTn&M1Tq%_5zro56ypL57zf5jSRE3{&zR;<#B z)mpIzMZqg+>{ZS1hH49bz!{$wC}m8$11&%R!}t! zL11oj)?!$e_Fi7kF4ssau*1g^Nqo;~6Rs87l`kFkCar^;aRJTP!ECFgiSJ2;!jbnK zyUJGOU_u z1vNn8^E%5e)|zUJBRrDYv76QWCo3nvsm#gq*(3|!x7`CrVizGiKjS3s$)nI;5Y(hu zrH8MCMXMdVm#paBD%P>M5DEiW|ALDJwOIhe-GsXjr~VNxfAiG<_g508IRRk^{)UrC zDIkU?2bdJPHrn@X+1Gg|`gF3|Y&A#JdKP_wSMsa-_azN!TrK>3Mb1H}P?y9|8xJwz z{})|y7>;yZ@&`_$jSxc{k20z1-f>b;Qynfm&p(E%1+`fG!(xf;I5QBkK3y{t!{ey( z30C=^G$hA2>oe%ElW^v$uTr1FL%gI488qQEdlKSm^#2j}9pF(^-TS*qz(P<25j#6O zGhmQaKmwakBt1X~up9VL(MSmr1rkV5v4-BH_ui!UPUu~Fks?)klirmg|M!-;+1Z)l z<70o%^M_~m%-nm*d(S=h+%vPY8$^u;@* zSv{}`d$(YZGyCU&+vpbMD`~U$-#+K_lHP$U1qN&EgRhz|MUTx>=BO zY!)%tEb4n)DIS-{+9#;*qS=jLBmmp?mB#4n*6U-uQKwwj_uh3?w>f@8|WzUxvztKcBXRh2eJ4jVQS>b z{g^mNYkUihSbjgl*P61o86TYqjjcG^@&E=EaOY6m4#N7mhp@gxStHv+5$kj2^|5>O zVdw)48SPkUu!s|tFn!{;|E6FXwEfp3_TNSXHr-`E7e~oBV*Bl&9(TYIw67|)XeargoUM}zgjM%=V&0M`PxDR1GZG!AC@`}`hDw$^ z3ATz5#5EpZg~2Qu+@v8S3dK*2BKDqShNHx`Vm`x_p(wHyHCBaLh6z}% zhLf-iOfQX88UulCjZe z|NhJP5}}NbuR0EK9}s4My#_IotYyyJ&kzL*WKn?BB)yGkdSLhOAdy5g!2>v~MKt9L z!x(UqOn6&+*a8*-QJb{-J~^9PUo3u~G(jD!d#s19B$_R(BZy53m`b+3hEI>YpSzHK}wT_@EClp;m)fPkX@DNvz7HB%xB?0IE3#Q z%mzfM^0(d)Y`*m{RKEXjzTJd8dj(oZt-|F%RvA&Q=M>HT)Oz*6-HYQ$BRH_v{r7Or&D-_pX6+ZpK6|@gkAIFdMmV2umO0B|yCK=LIgs(a zuMY>CPQX6NwEwq&{}PJ0!@j~HCaW)e1T(rFuOD?{3oy`yEB47Sbc8_wAX^gY;K<%+ z&^(%frvKHWELC9OPnRJ~{nr{exc~Zd|Ft2|{xAHO1x4I{**Jv%2EYR_qx0WD>Y}z_ z@be!!!XNiJ?JLV{2SGpFe_28zU zsl=-#yX1F_=bG??USxfBCx&L{?QQIN=pGD3PmtU}$n>}lTFay77b5T^(eooo0A$Kr zXa{+Bbb3Jvjdr%0CelgojYdQP3;|bPVtNEjFX6Y|^v~oI;e5s2>o}->1k_|t?kKVY zYpJ6@X&gn}`$%gWKy5^>N2Ea(b_R0EJX1a?j7o)p8H|I$m^+#1C$=9HcW>afhoS@h z!$?21PX{KuH}d}B#KMy}>}SnSCJq|`B?gC$L?a4G7=ry##Qr#XN98wedGwQ7{^>E6 z$C_Cl$1KATERQE!D6!Jk-o=F77H(WH*yT|C5ajajUE~1tHe|?Be>k1#;BMy{ZnXDNUzTw z<^_PkCu=Jo>q3Go(8*c^C5Fjbj7DtT+mH}ojF}}&aP)TSuq9lIU+N-Ng`p!10`O)o z!R43Sm!S<^%R%z;MWNymyP#g=kC*(;9~O7-fL8F(?PZNl7@fO$$6C_C){lD+6tY9M zP3XVm7=~`ZSO)=Y%)di9bf94a(J+->j_u`2H=^l@yi32r^_X0-35pCJ-b@jM!B`kj z0KrybZnk;8*p9y3X*7%N_AqG2*!Pi>;K-dYh52Ul;6A`dx*wh3IRKIuDfx;=9QKVIyWe?!zw;o!^XH4Z z55XFA(8xLnwNAPnWVl$P-K|v!)Qe6gF%erPhyIdH}-P4(@)BcGo{TK*TN|d2B(9tn$mC8LtL&~3TfvbB z5fWP1U1y?vaR|;Eq#0|52Dav{o22n^(SD2S49uNpDOWQFJdR_St zZDA~2{w0#rY0f!DH9sQ!e^+KVLgIXbw8U|OcfG?nL1^w6np884X&_I0vc1H&z_p{5 zUWJf)_i3&|@aLe2OY?!y#Z1m|719V-As0Qa3m(@wkL!%bb;{#9A+A531y6}9c?CYZ z#s3`B^gQXjp4WMde6K#I0BOCcFCs#jKtV=cARM~Dgh@KNT*1pEXCgd{W6OdrI2r-;D4xj3utS{90FOgp^1LMntk!fPLwF~o( zqUeAVOI(e`P2^*^iQE8K$&F*?%~y!rbs#tz>L`(>)I7&;>F0th>OHBUch_q{I; z0Iz`o+f)&+Eexj7@H!e`*cTK;fPmQ!11GrNBzmcb1Pb;P)~(Po7@@;ml(M}=lsy;6 zg8mZ{^xAh<@twLn2eW~|t;cZRFN}%4O+>F~IAEN`SaH&P!sBC=q@^Q@U~qr|buJtX zm=aEyok|Zpw8e>*uvh4zOjOM!k4T?{e?KR&pv`pQ5~t`^pv^Koa8x0GBkd?QhhkJ( zfi!hAJ5|Z)eY(<15)-ddrgw12l)7Kz6B~x6C(83VeSP-I9P))zZAZ(yLF^P3*F;g2%5)cDRRq;@~0@4Cnhe411mOmm&Og@N|oExZmJt%cA3n(0-|b zvp`yo*kwpRz#&5JO@y3graYPeJDgavdpUAA{Z=RmyIY}T;a5OsuH8#cbJ;p9GrsVA zvgOj;TajuFgI4gmal%I#iNmnBXlo@LmRLb1{4^%K>3^B<6Li8)V8Y*~(v^u$va;A| zl{^z45);KKQ#BmIeiTTF+gk8qAZHXZkTW!cMU&3W1ja}5~$sFg{@QHSTP|bVsL^lhIL>z`m)M9lU zVl*`vsmVwZBefVwW~4SFbr`A3h=&m`BPop3W28PK|6!y7BOfvHF$fz2LHc%aw-b3j zFFFg5bBga1Fg{Uq=8*3n|Cb1D2xUA%KgA)|63k%qpXt!NS==rAq6scQ&M9N+6QlX# zzoTiCho&(@12aI=l%Vn5FcfY*jaa|tDRCnXfpr{#^(6@`kz>i$ahz_%&4`9;2(RN} z>nOo>d_i>lPc^8;YHtoj+?VM%#K#vf0rX!I+YCL2fVCk$rUk=SggYcsMQ+dr)&fl! znD3w=gb|7nwIo`#5$P9!7T>L?-Z1EekxatRw)!&UVWE-zRd{=^Z#pgZ?#| zO8gtg%9@tGDJ7em2T1&VOXejUAD5CM=pQHm>Tihf|HZU_OB9{v+kGZM;cJgLs2w=? zOtMk{lgKuv@6f|T=6f6>WB?BmKai7M>&C8!EgG&u;ag6)7DglIhZs$jb&E%~dUG$04hYs{e(+*zO4&KlX-qa4>CI{qsVlvt=Ht-xA^76-B3aN-Lae^7Q zu5k|L_IVs+Qy@{Ozoj3>_&O4=v65U|!gL~r*goBvsJZEZ<_P*jyU^T)NZg2J^;~N* z!Mf5799@af6=aurvb!`z(=D&Xcgn+9Z+G;fT!R4!_aLm)q9~}*+LN#ZrP#wzUq96q z&LAj&o`E3L3^~UY&foYArm|kw`(BsJt3B;In6VCFWGG093f^27st*5~(8JM}Th@#G zL4VJOOn|MpJDR7G5u}%i<-YI5rN7Trwz!Ei5==ynf9muB1vd(fa0nCu@@SltDDS0A z<+?<-B}-@`+QQtJc&eA$RooHW?j$0hdx(N^Ve2c5fneP)l#|>soO!aQJ-V&E0@pqT zZMo&WIHQ`2yJIPksc4RbkuY{TjYz&vaRq7LvYJjAvEuGT-nj^! z|0mEELy-a65;P*w!WiZ$mzW~4hG+=q(Xf;-;9*rvyasm}VZ)jT_gX~taw-!B87N&r zxZl?%Ker-{0r9-dO2QgUf+h^H1@={FV7_oy=N?#1G(5@V=$~dVpP)5RX7IvViXsdK zfnXg$z!$Dx#IEPUy5+io2$SSQCi`h_zZ`@D*!=^90wCu|PS21hO}(xZugl|g)$zKL zy{;s$tAuAKXfiVp41~J9_DhjllXp6)U(S3{XhJ*ntPVNxi|CaM|Q{ZcMr%`MM404VvLv4-@4f^Duv-X(0wCvf4&q&H zy{;^;tF_3rg&AuRklfZZTe`pJ9(oyVCBF6YW>RhA$(p9qJ&5HVbHfE{Bzrq zD59SRad93#KXBcz5V6>#UE zW2i0X8xnsMU1{S%T|`HlGhU-vkrE%_pAWev7Cf6HiW`X5yVtfFVmD6bd=V#9znNz|UUSk7Cwk z#;1Vf{!FHdKnZfXJ5nhX%|1SDk7dLdQFCUXT znGv0k4f1;J#$Iaq9ioJ3CmccIaw3dF;_d<@46_s(;dQ9S$-A6`KgPy5N)ry^P;&Y- z4vl~UC=UmrR>(OVs-l7!=5-D6x(0b&1H7(&URNKltC!c+)9dQ)b#?W+ItyP%G8L5= zsmw?fMyi6880*dLW8%;cN#8hc?pW$m;pZqc=MF>LQrSHbPGyJG<@8sZ>0KXmP`J@V z$4IXa6T6E_?v!eGVqyr-7+)Up(?I>nXB~yXLqD^RB|M{jdB{)kvCl&^J#mC*lrK-H zfhV5uV7z&tUlu$*D@#m!0{D^0Cm{m0Ate$OBfTY7;Kwa-S(@`5SC-u2nQX=2aw5Wk0PT$ z#1upiMQ%DBLCmR&8*DU|>Osd7rR z^c+DO8=w(I572?*BXSZFhKa<<$K)h93_*jFhB)yVc@7!5dm10or|5j5AvM!RVKSW0 zhy}hNr$2r;=mw-z2pER*IT`^P$iUHvs2t#hA1I&fp1}b(79A{F91*i%aS-8T5$15u z#9Bck)zgfy51}RMY})Vz8i-2%Y!*Bj#yXl4PCke^j~@iO0Wlo{Pvp9sDUXkaFF7Qh zx7p-=g+|OL#sX8BKG^0y9viwL(3(gGhrww$$s*Ds^z8-Q^JsH6nn~89nS-Vtzs1EK zb_!$MUlS!gvFfgcy602*Z}M7vwbQ3d!Wc_C!qSTgEucc*<+bDqISMc##_|JU=?tO% zq3(rL=*PSkpF|VJI)5ge-N8OK)V+wZ=j65Uq|>3Wqh=WE>_9rZg8f#gdogA2nAhTy zfWla3XVS^`CjV`y3%W=o@eP?xTURvF?UtP8ZMVVpW$xlOyS<>@ZeQZIWqoDCebeBO zXYnyz&a?PFTfw0G!S=O+WtH2O-t=2r7dv=Dz>{saudtHZB&0UDZA~&-W;SY*X6qKB zX@6bQzMb^44*$jlE+ z_7hf;SB2yybIHG~B<~8zTjr8CtRx=_$$M5T!4cZT+9LE5D_mIsEX>=_M%bFQNlR{#9FH+SgKgD)DSEQkD0Z&2rRnHc78LOKxZ_@N_C1* zU6+WPty#Ohwx6^Jr!RzbQ$Lnk+Tv{`SiUk&XS$VCwvcLV1}j<9-j4IpRPqx}*nE8N zr?^LE|qk)lIbsG`uN9CEcJgcE6EW;a;UlFU@OT9LUOFR0t_j$pa@m|44Sno8=@ z8NF(y+7_v8KM$?etlfU!Pg<3=y`LT$#HcYS# zwqlteSjIkP)<%;>XQ)aV(it6TrFy1NJifX-ore zmzDT2Vd01|E)JQG=zx{73qsjhbIH?28z-%l-4M#Ink&0(C3#Os-ZhuJZ6#@|tU2?c z6-z#_u$u`%l`YoV^Md6WE0&i9%S)B5XYIwxW~rnJoza3;s^1o>-yq`t7dT|i+U>9T zNsE>FPZe!=cdF=z*GyZywyGM-!zzYUa^FfSzmN*9Y67d3ro8~?qp742PFQdktg1(o zq45_LEQPID-V~-^tLm3Zido4hLPo0Umr9yb4;HtQbP35)=92GNNrnr_a^{j{tRyQ5 zNw*bClwhf9#ZnzC%-iu*&4RKG9eAvjxK~)H12_BKLrXRvQIeIiPld9N%_SQcZPd3? z)=VgCVy>)_m1HX+`IWh3x|L)$B$+c?Td}kg%D?tw5o_%y!ScNoOEv^+7qntt)N(-!Zqf@NGaL&%J=lA0!@CRZ~_ zCG9osvpFA4B@1xE=3}m(-VPdnu3%YY#j;wMUID7Ne&W{{mmu&T1k!&l0&Un#tD|uRxDG& z!n{4nG$=>Xf&XeHK3`avV~mSg<|CS6rEG;zw$xm5iP6R)D`gvnvUTRl)>ujI5RzNX zB{y41?u8_C=58yNgF^X!KNhjp{uC^Stysy?l74z; zYy9sEmeN)%6@=*z09cnw%38@(6*85g{Wh|R)c+Ayk_kdG)?6~$O0u?)Ofr|OVI^5l zNP4VTJ`pSptXP_Wg?an)XtVuo9v%2+R^ly%g)fb9(cFAQ&8(DtBa~&EOSUoE$h10P7o9~LYJtXNJ8)5rW%$x$nrzl6*={}@_I{eQ+v@}`iyW-fWfO7gyt z{M%gej+LZ6M%w`XwPJZju!O|u_Xy$27s0~39U5bnO4ieXKW`=eny~OnjA4s;ImRy` zGcOjlQYH&!4s*%3jW*u2QdU|h3o}<%(n_+tkSuF1`M#B8BqW(LD_XI9D3n+BV-agD zRa>M>@iWD}jy1S{1Igz9=k-2VcHtXaF=>nAP3=_?`K+>d1|1nK&2 zBUmzw)7jEW>RTbz)(qC~n)V+#A2rnhCu}}`_S3sZ5QI{j4O%2+5J=lEbYeCkx46%_YZMNzN3K)2vwL3zj)nEX%;cyuHLUDEHHW zFR~KfAS|pk#>Hy$5v{aRwo@qEW-htKXk(L=vI9cdK67PztR#;M$)o0yhpi;fLXtW2 zloiWGq5Qlbi&$&d1j}VBmV1Kb?qg={wrMIkL}&D-mFkdKZHKbQnxqo4X6^Pze$rxP zmKDbN-f~AHP zONuaE7l3uCq_&kzLm~4~tlxfmjC$}tR+4E#vaz}3=T?#}h2)p!lFh9ovxH=(6-zt8 z^0gI9d$2HX{}gLhl{}&Y|G`SUr?Ak?7#Cg4N7Ttm*&v~;zqw>zqmABH%0>%iBg~Zz zvyz-7Bqx|lj}g=7aSmY#y8n-$9durP1;jWbIng=paQwh|vDEDSfs#ZdDR4YpD? zSt$F}Tynh8##k$5bA+;)=E|m9NiGqR3(Y0xTS=~jBy;96E0%Ra`D#BFvDP*TmJL=c zzYCU~kD0aYWYHN?$;)&`w_2$_B2*u=TC;ZhAAZteWmc)FrIN^+`czU(TfDJ?C90+& zm3(L=RYOQ6)HF#YZ)w_Vb3U3%QgFiNqpqLcw>AEc1WSD@md}OhPXSn$No;V8zl|uyn9u=>-<%?H)DFQi((Z zubY+l5Mg1UF)sR>kEpMevT;J$XmiPtMjOMeluZ-LCYvjpXeBvMNX|BwoM|Pw1d_~| z3$0jI2<1!tSj1XeD_B-pv1}78n;$c4zmY{}NF^$r(G6Cr_Y2i~tk$gEzS~b)tjvnF zv{X{QmaR#%RzBb6Do5>>sby=fYYx{IbybKm=T)j@Yth{23vd-RmN=n3x|Xe}4@V5u zUCm0amXNEVmwTVeC0fbV6LKCixjI&Ip9r}IRxFA3Ot+G3DPOJ-V0ekTU>jUS7czV<@-PjF`oTbCgIJx-_H{)3fJ zcOldTLK%%(wD5_khIIZqTFDL4 zh2#!%$!%7W2ZZE4bICncl1IgW4*9W&={qfypMX2{(Rj>C=#mh+03p9vCfUs=KI_oKwgZ*UM#7 zxwow3N(s4=W^$^PTp1zfvSJArEaj|NDuabNBqG@~H&*nM?5g=GMo3mOm#k_fSwl!B zm`lc4N!AtvO7de7(^p?8_rjg}Xsl}`^qCO)1VVn%*n`er11s6k+9Dcj>x=$gnyZQk zmO`}+MgI#{Qm+ZAS8AIS{ev{^Z*x9c^vgJ5^Xc%@J6Pj?N3f_?Ebj}`r2$x1^p~=d zsVHR1*Y+#=`%n*-vy!YPB&(Q9Rz6q0e~k}+12$wIQG6-$a>scXg35G>5wAJsN1 z`iIeh|Hn$anXu5r7#EGqN0e%%EK?|JX)gJd(MGzJvUWn**XGKytt8tE$)C(6f3TA5 z3Q6Y7PF5_x2<6@VSj1ZECs=x0v5XKbLmxA1gUO;Z6#b*O@znpvtt77q$&2Qa7px@j2+5n~lGm*y9|*~RtXP8TXnVvX zE0*WM!o2-V9kWz2gAP1j9sL#~X5wXG;iWo;E#}2KehHa*v7nW*w}rAd%q3ql+9+nF ztfWw;m@9KyNxm;6OPfoUvXTskBy(mtE0##1yrLhASZf~&mdaKv)dfrZV`eS3j#(<1 zLuWMFO0`$0u0zEApS2)s)^1PslNRxiR=2n<$Q~TjtnS-j3l92%&>-^jKuzk}vKxKj zv!~O=p2_*!a{jL=CH$@G+R}Y5nU_$*E$Z4@q_xV^QrK?)5{$S{A%1sgA!Te{*OvKp zBV22W_IYS87-SD>UDwvc)+N8q9`dSfoGr(evx*1=wSho(OHIa(-!PJFIpnq>e!-|K zP?FJf7w9@eN%prs+LuzR9qZaMGP7+R$PXOZ@dHPhc6E~^-Rj!fd`+y|*^e$^KqE1rU<_z(U0Yh4HuP{_-NJN?^XtB3 z3l0hnS`OT8zvaClE9-{Zf`WoWR@E&)<~L+@UHrxq=oa3-7477F8*ksm+jpZKhC+Vl z?T65Ahn~Zn{|IXjI>qPzG$@ImGyME4qrvCu79s7y=h=D41y27WG$=UuBJaP%`7iVS zEByQ_KflJ$uXFwzoZdt`(SM8g-{$;xc>7&;p6_o?|6w%v9-|@m`S}A-qURy>V%)+1 z^7coZ+B|e!1lu_c0ww&x{5*uye7rqBqxqg;?fIW&G~aWaKF?_Z-XF@(3v&7br!R6^ zh|`xC4K55y>=$7)-^;weD5tM58eELiS3wE?Yo3>Bl)TQ`gWjN&tlQyrZB5fMvzzO} zeW>|z8EjlG15KApf8%oLYr0%|>z0dTLw@+hbh-4fTrQLA+OpDGr>12zA?w(Vbu3{W z2aTpnC7Y%sk{#@}ob@zui~=@e>oi!+;<<~$9+TA=<}uy8N_q^Nm+IlM&41I6M!a42V8`{} zh9%NS;)k=cZMe9{X1)uT^=KP83wH$e`yQX2lJ8aapmH9Q5dOep62j%-*l#lp3%88N z5Pt7@Y|UCU`hsrB+)zPe>u~r*AChRvxj^M2Vi^9QZ~oQ(xpA5H4$r;p4NhX%tkU{ z9z%XGk*rEGE?$W1i99#qufS^c;954{LF+hO&*=t6gEw;e8>gE%-OOmv7EZTvx{cHA zobKRsC#SnWQDFw}X6M1bGa9mopYP>#AE*0y{~wG79pLmJ??1%pVNlew!AJP{QAUIQ zZn9}f2~aQJ#4RRW1x_Fp>+ zMg(6*1e0`&KLVyj@O@8VdS&wfpR1B9nnGS$y9T`kiffhN!kiXiG~{J|UX;^UyzH8z z7(aiNpTEY>U+3p<@bfo0eT%oh&CiSDoa_t^elC%7M5Ghvq?VRBRd~P3Xh;cuUXs&y zczYP5L8U;+kl*F~r70zme9<)QF8I!2-bT%Sp7xy2tc!>~BVtT6oyvYr^dV+2mBk&f$ z_!h&}p@7B>j~Eo4UR!qKj0}2zfR~Bc_(41#SX#-MuOJDn54@~!b9?DEa8QJo?d;Lq z?=g&q#PahvPUAUE;Qfh=234n&%u`vfwo=IL08C; z@mB{Qe_@r9{6K?f1Xn(hDh&>r#Eb+_W;A39YtJ{8od-?h{nPpR41PY7(^-V#UeauK z9x{iw&t)`d9;fp;UBKx=P8V^ym{Jma!!T7QclCyN4Hrg(=!!Dl*Be0F{ll`K(RqDL zoQL20VX@+$oO=>xn$Y<4vYg!=xEO>y0SEnA&#vepAoAKtcC*_%qn#}Fy!OH*>tWJH zW75QMNKnvie-v8zU_{$kpXrsv?E|yrFcPq}DgrgFJ!lL>O>+$*p5*8Jp|*Ns#kCLZH4j;J!vh{8fB$5%xL^&!`hi?t+KLOB&9d@ zIeag(X=B@s>#y3LDf&_`sju{_G+Fvnx+N`gE_E((E?3VuFF4OR52!bso#gw@N6v@N z1?nPsqnsTkxM<+*TM-Rs@j^2&|jzNyWjv>jtP!Qjwz0*j%kkRj#-X5j>V3p zj^&QEj`fbsj(v{(j&qKC4u)?cMR-g)E}f80N~fhO(pBL7R~q6R?VRMC;amjVOPwp7 zYn&ULzd5%#cRKev4>-?Y6c?N~ocA$;M;J?Qd7L~~o+r8+lkdv+;fYR4 zXQhkMRq3wuP<3{r+DLzUsm2xXKqS{b8^RmLe3lwXxe%4B7V zGF6$b%ur@2vz0l@JY_z7x=>lHEP-cNDyx(=%35W;vO(DhKW~Po_bL08Ka>N?A?2`g zL^-M)Q;sVqlvB!S<&1JpIj>w${!%U}mzAr^HRZZ;Q@N$wQSK`LDEE{cb&xtvouK}z zPE;qUlhrBeRCR_rOP#IGRWZA2uDV=Zt*%!$s2kO->Na(|x>Mby?os!u2h=0#3H79U zNhJ{d+L4lf%;m`<{+DGA!c%sVJKlFV zhC6oRXqRJwV>kGIN6Q|x>_y8ywCqRAA80v%mV;^qoNO zN%WmU-)V520oPe@odef-a9se`U*Nh3u1ny$46ZBSx(cpq;JOa38{oPLu3O-`4X!)j zy6ZS4|Lr&}|Km6#-*cRm?>o-P4;<&^hmH&KzmC7;M~;hfj&w9NLS>J(p9;W zbWQFoU6;E^H{`C;O}U$NOYSb+mU~Edyn z)I%93^;E`7zbF%=UdpdhZ)Kv?N0}t`RVGXQlqq;kmHI2wqyfrwX`nJg8l=pW1}n3q zAi~$O5>HK(76nHmP5}9 z=vfIptDt8!^sJF4C~Ki-9rUb+o(<5m5qf@uo=woRS^8DkB284bN|Tgr(6b$Sc0kWg z=-CB5yP@ZI=-DGpR`x>AKIqvGJ%2#Y0q8jhJ%^y@urx(EB286}O4F1-rRmBsX@+tf z`c6nQm6OsepWf;@cIj{i+Eka>oQ(fq}j?ZMRqjhml?T!?<)O4(`Bz$@Jd#!_InGr| zd*^DUgL942(YaRXo&P_@W=Vqm+bBpqebF0$JxlQTq z+^+O-?oj$VcPjmyyOjRU-O2#x@5(^u9%YbohI_DcrhABUmV2mkwtJX!j(fOsu6u-Y zo_nNozI&8&fqS%bp?i#Tk$bFjv3s0ziF>>=*FC|x)cvb-nR}vhxqFiHies|#s$+`t znq#W-x?`HNpJTf7hGT~Fremh_mSdLlwqv&Qj$@AVu4AtAZ^u06KaTm%dyWOp`;LXq z2aZL~hmOV0e;rGlj~uzq9BHYuy|m1k<5-T@3TFptrL&{7%GpU;?d&YAadwf`I=f2i zoZY1L&hF9%XAfzkv#0c%^A~B8vzN5l*<0G;>?3V;_La6d`$^lK{iPkw0n$$AKxvnA zkhI%5So+;LMB3vVD(!U+llD1>OZ%O(9Dg`RNC%uFrGw5<(jn()>9BK*bi_GUI_ezk z_|rMWam+c?aojn~al$#=andC#o_4C$J4rgYsoOS<8lE!}j^k#0HXO1GW!q&v>}(p~2Q>2K#k z=^y7J>7H}3bl2d^2yjS@~POd^6A)d z@|oE2^4Zu4^10Yw<@2!<SqOYslo%klrpClVgXClhj% zQwi;r(+M4vGYK8>>ZEKT#5iSsiSf$x#0kob#9x(}i4&DQiIbGQiIbIm ziBpt22~(B33DcBA5!02!5i^t{5i^zjiL;bH5@#z166Yx0kO2=S&QlI0&Q}g6E>Nyi zT&P^FxJWsYxL7%wxJ3CgF;}@&aj9~<;xc7T*mAs9D2pqhvZ=I6SzdXyaz1{Iav^@L z@>l#iWW4prcpH%MHYzKT`EJB-Qtl;eR_-Tk0nb+OY*VhpZ&$9y?@(^W?^LeE?^3SE z?^bTb|E}DQ-=o}#-;38iSXLK#u!q|(QIO6lu9t@LxB!TDL7pTqfioL^Ap#{H$ti@T`YkG-Tk zh`p>ljJ=`^LxnXQHP#4JSu2$r%8A6A%E`oA%BjTL%5di$WrXvtGSd0CGA!;NWq8~@ zWklS4do+u>aFlj>h18(>YeZ|>fP|J z>fhnr)PKUetM|ftsQ1Hrst>|{Q6Gl)QhPait9{G$QF}Z3s(l>&)V_}XYCp#SwZCJa ziuzi;>=>*LbPQ1kIfkl(9mCX1;ltG-juGnR@R91VQlr#O;iJ{f;bYXHjAsGf+Oq@GNetX`L=sJG>*>Ih|;I>Iqs-TJ`{b%A@PI?^#q9iz-f z`y6$YW3IZ&F;87tYQB13TA)6Z7UH!?J>yuc{u{nTz5YS2dOC5bI>xaK{mWJCe0Z%? z$2nH1;~lHjV+m{2o~75SkHXif6CCT+>+u_)ccXe){!RVOu}S^av00ty*rHByY=zBj zcx_kDM(j{0J9er|+`H6EvAfld<$qVFIQFRf9DCIZj(uuQh5hPO#~-kFKz$?~#Oshc z-EmkQ_TCY-hjLV%;rLUX={Tm&avWE8l|P{(|Eou1Pr(nT)dh|->TJhZwTp62o#QyK z4lRE{U8?-0?r>aGJ1CdbtMQlB-#@sbZdILcid7B#@<$! zyYHwE9Cy`uj=$9@<^NIVJMKaEef3)G1NBzyL)duT_DW9h8#ddE)yM-!@1-|g+&aYm z=n<}=Y}J~jHOhXkOqsqm8~(^VX?d?{8{EnIIt>?t_*5M&_Mgb1?%#V&(pxCazMyTW z!NJp!u7wUvZxkKH~9detgwzg{skUa=#P4y?AEM zMJB-KpWx%ZCtc6sWtV-Ja47h=|4HwQMeMfct@!vH5Wb?H+ib5@&;u0u_&gB4nlB;_ z1{?X{WETn7^cHDtBAvJ|QKwDD7i}7~bi|`2%kj>)?h0WIYo#}7laZCtEZf2EP&mBV zZJVZNG%Q!9Y(&GDjFv6iwo1=#*RXy}!xY?&&T3f8i^Hby{%a&=_IK5TF z#Eh)$2JQ;0g#KJ5lW6jN9)>fQXKyLzyx0FBc#sP4-L zlMfdw??@W|#=7rqQ&;>{cz(5jb+>5VD62Wu{(h&EUyo|IB&zb9g?k1p9yg`%yuh{N zgGQ?RLr2=39~*x0Zt&M%6!_sn+MdGY|97YJ<*3arJ^)K=)2dMmwoF^3H>QTh)!!IW zu*>~f&IS9O?~JZdweb0vfL%lq09F3#{<3?=B?T`jdFSwm8C#z}Q}|e|{}bieRQn6N zLc2ASPgK3Rto*{FEvq*#T&T|ftli2-^qD$%j2il*&ZxNa(^{18TYA@yD-U~>Ec{j7 zr!_=#BURo4_t~lTdL3_mET8D`=;(9jCndes>tK*=p;!Iz!_=5+sb$Km}Xw!(*t1%yH*zb07Zt2g&rJFW57$+Zf0T~g%PCIep>l1v^e ziSj0wO|2i5R4*>IRoj-h@g7Xdg`D01uv^8!EA#O7Otj7Rd}1NHy{_B-!f1avd`#OG ze`Pf|_*o*^50bwV$-YFg6eM3rEEHrM%A{kA9gfhXt{uf2sA zAEkx70CW@(@MN}Vl%19;lrlsgL+K%+RKA9{zW>47NPA+Te9yR&g3BZYS4;{Xl58KH z416K&;FIVSd{){fwFw>qqLb~g}R_CDUe``BiSCR4V)g8hYd+&E?`l|0}| zzLBoQ$Y2;gLd0r3#9QbmcuR!g{Lc@nU@z^q@2MPguQF^uGdelwJ~1D((3>wh#r{GI z&BNvJ!Sc7MnQhWrre~+4HrEsrHytI4KO(!}@rEcLF`f|Nq``3WV6KEZ1CQqOxLpX* zKZ$6e=OFqV>g604FogsIQ&lfMuC<4J;?EzzYzT01r0B(p=QX=O2y`D(=3jKs?)^c=Q@k6(!N1HAz#}kA3j3gTi`oG z_}1$bVmHiaBXE&l_diRRChL@CWwgO#zkG-e@SLOAJJqdKy;fXmohVOKEm$bb{8Pa8 zT2(j^?)P=xd9Cx`V)d#grzG2Kq}UH>rL)sCEiID@3DnUrc7Yl@T8zweDqKSZ3)pfh z!N}Jc=}l9`-!Qi2ya#rocAQQvSvy#6sr=94GJjMD>t9s!Di&+?lB?H`^LV3@L{w-I zH%+H4Ju8*?BaI|L7Ih&|b&;z2ERKe4^^~|;h@v`hN@X52c#MZm^cMt6^NjQ+m}Y#y z*(BS?`=5gM64kRkk}_xFb8Qw4SGbzNIw)Dq)0>e5&PG%UFs?y7$UG$XYUE{U}M z9O$@C)&CkxVX}dyrbI<2#pOj@0o!I~U0Yxz8aFfh1#BgfsVG)GeX@+Y)RuEY>y|_} z2|(UU#)W?cY+mM`l%yCos#~lh1P>1h=g_AgQ`r;gY+Q}Ob%%`0#aDi2+w4>ZP6TBa z@Z6qV51}ZA%VIj<)b>pljO_)wE4wI1gVB6I;l1iib=GV@fjES0)rM; z-7%Pu&v=MCM6~X2>=5YJsXVqQ>cHSsbAtdMKQH&)!`E~O=D=1 zK*NDtD6>Ej4qeVHr&K6wM3w9IaW zY5iLmj@r>R;$lb@A=bzB7$|QLUM3V{Y0*5j7P4E@wk=!Y&R9-9t*1!5W;r1)InJY{QC|qpXuK=g5Oj=r zQ54cv7s=_Z@Z<<7df3XWh*<7M9pT~GB(7GSq^J}UhBdUI^iI~mu*%ve$e&{%LT>A_ z0NEn)vVgYLkw5#;gWCGiWZj6upnx{6FAQ8ht38w(uB#gztNHWxkzUl?<;b}DbyDlp zjQfZMM6I}#MEtBP?m}pprM6p31Q@B$Oue9CQ7hG{8RK=Q*6~!YpGp)}PmU)A(GE>R zN3nsLi62JBN%c#3V$us~MvCO^^kSJ8);hPbStgqy>}ng~Hl5#ze?*$<19uOg>eP!y2msu24fz_M z9316MMAtVAcLCd*BKMIiHd_w48ldLBW*t%Wh!4Enlf!g_$jl&*2Itiy!|512Oi)~C zkV_6cD{RYoLz~M?VSTJ zJBLpK57Y20V)Ze5=GC5i!fQ*cpoqMcZtA zEWM|7UKBef#znr?PeE2O&PGUcT^Jx?(QG0%p)wfYYziygcN60G3d9yzRx`Yy4(7#d zxAt8MA86dU%+Wpto+zF}e%1kF-qKwNl>oE_fEI#>-bJm586$PP2<4p!x`h<~oLC?; zTay?SpUNQN1tlJe`-QD>*g6(ej+{n2*`^Gzgu{(vi=4%$x}Dm9)WMicI@D zGd1(8w05cVvZG~McJqv;Y~_f0YX$RA^{8;;+W3SeF5hh!V-tIDS_I}nD`vDf^2tx) z!X(w4Q6R3YA@1dO1>>_Is%SiE43u9L1YEoXDqveKQn=5~>QgCK)l@Aqxv=sv`61&A z35oK(Q$=g4wpoq7u&S(9)2W(i9;80%qcj*9Y(ywO*xc|6q=2o1{-Vcc2+F#wagiW+O(|Q>^n%{NQ6uOwTm)G5N5@X=6$ecSJBV z{B}qITO=E4UcH3Xj(&1)m8P}2`YRvi4sr1_Fi~6g?DEuir-;`K4>vN2>zM?NshhuJ z1xupFvY4+6o`pmX@RzMAnVXoy;_EA?;QUTjQzjDE6S=Z8(yu@Y`x6GQ- ziY%FRg#4<@W=-4XRnC=xaVH7K-MYBtSHfE9*B@NFXka!rOB_CM`3fyyDJ_lE4p>; z7;4KYK&-EE!&p7Ma#tB}0MoTlTNHhdT+iWv1_oy{;QYq1d`7VR;;`ksOtAds?$&8I zJkhBi@dVzJfMA4!Ai#U%7LEWkFa$f?@oXMG*UY~S^Lk@DxiQedjP1d2ck|&kcCYC0 zOt39SBBR|6e~%#Zj`3sOe{m$$r1QNuP>Tm(aX+^>(%0gC3yTK>wRj8`kGfrlxzX>m z2vf*7kBSI8Y_PA3u;bk2pn?{uP#CWO#>)||!V#`Q z97$Uq9BzW--51XL z1~@JYIORAT(7@nS1e|b=WwP(~6mGE0;@KUj#mcZ4$t_Ofqo<`;BrKYhURC&5K?56W z6fA$pE&od5l+-#^NSuCXFpXHut97C|0?@z^)C7X+5w3&?R~*ODO2ZLDa8%c)m4%Mn z1ho7{63uFwXjVIN;~tMSiDLx~3~N1L^+vera-ib?l$3%wH3(2IVCjm(+`5K%0qEhR zTqN(2^*Joir-C(9tK6FdRx^%CSGhL>fbFD$^Q+v`xn2IlesfYUF+)rZ5;SML1)Vm)!YsNDNJ9@an(3p6lTBLQo8 zgli~=rK{YB8&C~3pkf>PC=LfSFgU*g&iDw|SPn;5xsNx%8EXM&B8LMS7@TQEs3qV=Z8;j&QAva4qLZbd~#Rv7lE1fqpG5H(+8>yNxwRj#D&vJ{p%Ka=Xnw4G` z_*g*$8|!6QzQ`@>EBA{A(}=~q^5Y6e02&yAyFhR|!gVvkb)DnTSMImFAj4b8sY_@chJfm?~y@~?0yR9Q^6Xe zRqjOrt4O5DJ@+D!-8$|irG#JQ{tCAY8kprbVfpn)*Q?yPzH)y(QoDijsu2ghHy`;H z2Lc)x5GQ~*I0}8u?uhKx=^%*~-#A<`Ac0qN@W1OuKp zBOa_vTVxFm2Q)A^bpfY#q^lN(qpQ5xOrV|-ULbTumiU&a6i3~0ST*Ongt3V z0{~h^y1t5ZrE?6rs=TFGvR?s#e$AvCFtHLdlRF1AFz2)bwr?U`Z6jS-9Gku>|Hc5R zt$>?l1joYWJB|)CFmxS&E+^9U6Njd&$8!wGelp^r3%VnR0~#2d9)Qy=($$5-(bePK z3~;(w!0E~1fCdJqFW~g%SakJxZ-ZqP$^8PgI0zO8aErQnd;lz(6;y-ySV03D>u^{e z$}Q{b@u3FO*yZy|ixC_FXkZ9_1%mOBuCbA>(Hw`q9v`oz5>(=2aeRcN72G`^{djy6 zIX=+9@XZ3g8Ii7O9Gt!epW$EZvY_|?mj{5ZoEehMqQN$=v!`(fgFd~3=K{p+ zO0Jn4gucd}4b%F1VWt(Bc^nMr(}P(GFiR@A7I84T`g(~0%OWEdx*ad$P(Ys^%345K zUCFhQL($dNs|`?AT0mLHp@2R;ludxLk>k+U)fAcM9m!JLNCnI$z0kwvy{K$EB~M&l}*J6;Mwbfw3^T$dQ3QJ+hlX zcD<78Du<=3p|2ZIT{U8%i}n_W0{Zk&?gPp{m0Wi@6kYxNj{(YE3n&jb6ws%KVy}!l zmK=w!c79~A%Az)?asbxy!&*pXRtV|p=8($fh0rsVSs?`a^kXaltIu((`kMJUgIUzf zd8I)pw+{OB){DY=k;<-@D!X3f81(gWk;*((pk96n$ESF`{Nm%Wy~449K0UVL!1h*U z*Bcy|zE*wRh%2w*UVB?t!6H6z=60qPit4aM=Bf+Xkc){0H-9! zqOYDyR_)g5ihuQdl_J1;nw9EFZ3}iY^O(Up1+s z%Li)F4T}}HMO`Ib!NOuhpcX%b#VS=@mAFxTHC;tSSS5pfU4&KRE(ZPq2obX9hJ1Dq5KI3IC1pn<{p3~(B9Ec!~jp~18+Y*IM_(7+Hh1%k#LfxhN${CEUu z906!x2wDKamsMTOIS5_#{Uws)4U!zilP1j#s8}`AGEf*_14edLSDUJ?OpZiXhi8ig z-3AEsYbn!!iAC)<+(n>)xhMzNeyZyFp{naUj!j>S|73vlgMj;;0h}(7+H;Jcfnn?p zj9sg`I&*-!s=TWKUuOd<=CU3f4rpL-`TL7Hyyi4c zK#~Q3x`6_y2LSjLR{DkbYrd23g~e{f=PWmg$*<2RA2hJZZwSjDN4Xks7k)UBj{P_{KaH4gjE!L?*%&61c*A>css)U+r-ZRn z+p^jMMpl$7gTv5oSy{j_kKhnnRt8!Yk`~`BYcb8&c#r&=PY&o)O^$%|17Ll}G3mCf z@8F2Vd0`>u+H9#&WIE$e3k0tD#_>H@q+cH%Ao4a@~S0jPVF zt1Abj-?F*`#B9E0b$vXbUpOGpzyJ*Zpng%VJ{*vK%j)L?sL$g84dj480|PV+fQE21 zx-Dyn0RY>whI7lHfmt36%OkmE-Ig^{Z&_rmG2Aj}V3sGs@`NbYIBs0GWlex_ZOa;m z<5gsx_-$E}0tGMw0H#H`rf>kdEo+(&fGHLLW(EpiJ^;*(a?R!dbX(S39{{s004xX; zz!Csh#I5VLtVOWslbgik=km!14Q%pP!SaeI*D`Kgw`HvmTh=l?43Q#N2WtK|nBNfP zTFcGrwyX`<7}k=FL2OxTEnsZ=-(k!nS6Mr>E$bX$oQZOs;4t)C)*0Z~L~w{L>jYZ1 zk`~`BYdg)?c#k~KCkOO@og6)^D}Z&0W72I|m*9x)0N{U>bv00nw_)*Sl&*K68%K?D~1}I;2 zyel}`Wyg=PlV4oYZ&|_7d4TLV*3Xg7L;0iGr8sC{fC>Q6a~zFs%X-cLfNfc!+%jlj zmJ7l13*549%X&d?S!Au3xMk45EEj|2qS3A*+_-MbDhlJ;mQ@7D2go|{+p=B_6u{d6 z@Mg5@bq+wcWxeSG;B^ZC#RCPP0)QOtk~jd}mL>ZDkSqX{2oyjm0C?yBvGyJCQ5D<& zyGbYtB1HieVRvtV__#=C6Gee+3IYj9R^L;3A|)zH6R^MMi-0ugz4zWbgx-7ay+{}7 zz5l;6cXqOKOZ>U}*H7-bckVgo`<*jq=ANCqBn(}6WR(G8P~P*w{|6g<$nXZg0+8RV zrD+UYcx1gg4PV*p>RmR6a;3y-X7weYQf@?hYPtjabtV*fsk%J}-L zM8E#J0~EF~eBl>IYy;W}lJACpezudv9`f(TJ{xsEQ1{l-b~9k{RsP;ufmivvO&q}I z6n!$_7<+(Gfef9>QBXO|c!;m@4`T$*lM(0>^a~>{P;?w)k1=$}(9uuTvU`P}4Ro3T zL52==4&6M%x+%QAKZ6)wAmeQKM`!25LHh$}7a5xH>i(h)+U0Q2ZUF6CE$s>e6kpq4 z&^1_?o_e306pxLJS=;bo8P?e~F=sujpUO8NC=ohYTIPB+yI5X|FN@!t41G zaa}t8K^8s!dj3@tBYk_hR5%pMfPxyQ$#I&8u@GL(t8sxxfDCkT&Uj3G^t6a(p@9rN zG!?-d@`D(~7*@i8ipp;M_1Dv6AT@G3shgsSK6d*PrZ1FbGY z6JEpD1)5dKl*0N58G0Ynftt!t#aHmDCRpTMcKP6E=#ZhK{~PEZ$7vtNY5!y##Mkd1 zi^~RHzki69t7IYJuiyWfGtW;LPsq@Deh!`)aat2bQhfEE0ZKwam(|3SA0T|5lz8MA z`vs!}849H`w8H)`DE$V%wCcn$_Gd;3GIUBE zL8(3CBWwn>M?4+?+_)L^YdC1X0j+DC)|ml{8$n%x_>64?bvB`c$urt@9Amq)u0w|2 z^?o4JCr<0d$cURjeL&y_+XU*BGnxL33}onJhJnnGIBgIkBW?f<2_iEnXEMVX8OYGd zi~*TZjES)MGs*<6KSjneRLIa#CjxamLlriD#*3)@v;QQ93K=@;44_Vn)21+BVbfov8}J3;fG-7jR-CqofeV{GSwY~7 zY`~X=1HKC2D;Tn{(X#?*LF*15?A2_rAwwVRjX+%=r>$kc!Y0r9xWFdQT9E?ZJy5vA@P!SYJ3#A9a@(-M zbDzZ=^6$nx8}%trAIE7A8L+s)^O%>+4^14vr>lp2#|+2VXN(GD=v1P7_?6i{{S&9S z!4u)@(y=`|K+$k4;= z0Tq`|E6J#c8$2!$=t@G(H+V|sOi5ytAVa704^WEsX{8w@VS^{y#Hh51k^VF<%cwwx zPNfp4RPbqUGAhCbPX!Z|H*Kg?W>g?UrxF7y)ff+PgQuDaR!Earh7K7z`ny1{&d|jT zp6WTH*I?+7p`#}PJ>I9qF#^H{PdpaAeq_<(8$59)M*4^3q;M#tfonMCA(`DlHfl$k3^@ z0hQK_hp@rZ+Jvg-ZrgCsz607f3{BYJ`37iKCDZq;kC37F@jpQQk)etkJU^OXk$2hU z!+#k%Wa#LffZoxkwfAY6jDxtr(@|VDu))(FErZBH!Z&y_bLQEZ@q`SWXK(QA>C?J1 zlHvwWPh&xs)!mdIAl!?Tc;pz{hf#tIg;M6~z_)(pfz}+xNvN{tfWS~v5*VuN`3xB{ zJme)nUhLBrGH|idUd-37g(e>0G@RDDIL0nzbRff{vkG)pFfL-Xy#j+Xk>pEowLOV4 zz%h0;V*nW*gY~u*cQ)7t1_l`(*cNnm6YH)}b#FqvCy{YCRNY&{McfI*?F><zq$J!)OUr_&F1+GbUF0gZm<*0~sEjYoK$*r(I@rgi8F1iOyvkI@cK; z$nfag0i9cni&%}{GC>PzbC)rI43EJhFnGWih!y#RoEbc33?Rc}5E-AKIpeiwjD%2? zJL9`_oJtl)UX?#HvC=D>sQ55xyZ{>c;hABJ0Q1-*IF}hv2t(2 z*R|Fr9^f>O*3CG^e#7WMhDYZ|(D|Nm5i9raF*wUe&IDKP%P9jKV}D`{Aj4zuzj(X7 z@@%k71_l`(SVwfXJ?pMexwl8Wmy>ZfRPMiqi`W&2of)D~xp%ff>=rI!Zy@%J*Sa%M zv2yRpGpxG_U&ydNEaZ^kg?upR42;+MGdg1BJ`g14k+Ad1y?@TMhA>)?;n5lcTBG8% z5sa2lxsNij8ew9kKhVcAI*{SfnF2bK;?SmotNfi~(eL43>kz(s(V4kq|2PrC1zSk;Rc$?pY>Q zdZn`>TpAleV|~1~HeOrJm!*A6g(LgjwQ#P5KKl^(LAj1FXYbbbe&Q}Nmf zMn|aJPnqbPu%UB?(SZz)&PC8U&$tMc`*{m443EKMFnAcR-H+GqG9F^({!m<2P`Ten%Q~{q@XGye z&Rm}`u8`qz&7FYX42v&Ou1DKX$1yffg1%V*84|5Ufy(_A z&??3_36*;>5ZFjc2}9-nDno`057`CelK2ii0~agzk_mwgloBQ$;IxU>%{a!o86C** z=%}D0GcID~E@Nt2IL4M{3?Rc}@Q(xr|7qY4HpG7@knMmqWaFl5saw?iIpCtOCSJ3{j}uE7>4c4HxlkAmVRjcp0czxySMh^P2F5 z46DvU4jEp^eV~JX*;Iqk5i9pvAhC&romcKPa;6o}XhDWYs~%|8!QT#Nw1mpNj)_%m z6D$3Jp3LY#hDYap&`HO)^cfwYa!)tWNwuN#0iy#M9-WUt=R?LttlU2|K?`ZqfH8m! zk3l0aXvi3dm3zaS88l`LAj4zO3=BTUKM7zYgv$MMERK7~;>aua3==E8()lu68f`)2 z>jbS8{>Bz#B2?~Q^9kJw48*zA!o*3>+IB2Nkl}^szu@*$g7yRc#unoyR_;HUDE+|c zerF;lB+}1}BV>3SJAq?I?AI`YLgn7k#IL=Hl^(Lrj1FXYbb5kL_XMpQqa#%A-A#15 z+0g05=s<=?r$6ZQWn6^Hy{`#b&*uT*A`SuKAciPZ?t_46ReB9&eT59KuOopxoFR*q z`*0I9axuI77{wSshR0ws7)-=JT1e2wG9F^(K2cm&P`Qss%K@^`@XCE`&RnN3u8`qz zoeQqB@ps1=QL%ELZ7dG6W}5N^q<7HD9mm*tj22`_w6X$~`+Cq?%Qy*@`&tkROA2K?S;n8s>;xFwaXipd&p>ls_ zqVvRtPDG-+qjFV8gcLjmVq?9mJ?%f$OWO&GZf!sS$>&d{y z%Dp#V*Ls?GfYTLPH{%%FkI{h)kIrDw8OXSZmHR*pPFKlLxp$MuziGuWb_int86JZX ziL6>N?YU=zjbvbu;em}scSp1C3YGh4#Jd}MYpmSIg^M@|h!Ys1P`OXAL7W^e;!Ge; zPt>L|P_c5K&NFPP317&tSuEs`;e~u5=*&;l<}x~BokYHJxCp>khuqO;b9&L&0&GCVrlL1!!D zB3ABOP0&Kx>|hKa!(*@)40baHV&%R&X9oKi1IX|g90h~JiP}L%La5viV{z<37DryW zA2hMjE1hHE(l`eiXA-s3iP}lVM5x@)@Ckhy48*x~(!@#6+Vd<#kl}^s8n|6a)GjA# zml!v(a=&7tbeYq=WFjXd(sjlWGCYp=!SQaQcAF6tD)+l4ez#4m^pHJZbRff{<48)- zo+fIK86BZ=e`=!h*oKZXN&kor86KV7pc9p(e?%85_oyW62V$OZ5%U4@Iff`y?#}_y zs`Sdw`U)9dUkd`c07Dil_W~wpO+VV293FCg8Ol#ApTt1w!SA<-%p z!M^7{0 zmvvXD+~*?R!^pTB_S_eQi+!xs(E(sTL6%bb>Y0DU>Sh=s@8Me%XFJ#zi z7IMh&LcR%fHY9257#*>4-vAQVh01+h&a^f&T9Dz<+6`JeleF!OmQcCxG_l%lVx>RO z_b@t;;n6t^ItP=q{fv%KxgRvq*>6MV2%`fT9-Wh*bDVJzEBE6jXd!J*F$R#~F*pYX zXBY#qazB$ZgY%35WOxj&fWhS??Ghs)RPL9tIF2NXBd^>qnONzS`_*u1+yjj}N!qO> z?FM5aRPJ~9guVp^;#|66;-qKoeHJ3f@IvIQjW_#_&?&;`K!!)BIOr5*T!hNKs0mrm=U2i-d>x3dF+`zqe+`IMrB_MTSIF@C>H)Hg zA&Zr}%LI*F%q~A9#sD%r24%tEjoMn7+M3FEh?V;rwS{E`m3tYqj3o;VuiVv~xoV6n zWO!Vwf@|g4T17@wtlTSumQWmKRW#)bNDrlzJC3o{7%j-ZOY3Ak{6(qWk*snbl#D+# zovhDgp>iLP+@-?=Qo$K2_rb~fLIN2c@<<>LPu7MqaItb9o*by$hnjeR(-T^`;}|=N z(SZz)&Unxn%eaV@``F|z9jB3;39j6y)5;yk*a?gQWOxjwB->T)*0Gtu4Y zth++xJ{|F%PR89(xz7q0aUKxoFhrqppJRhKKU~BmKwO-xEo7i#<-V9_*g_M&kYP(% z$RWcE`5Mq!m8`8`bi~Si6-Yc0D)$vR(^|`DL54?bD`;&_);2O)Lgl{M#A>67mHt5A z#^^wXM`thS>`vBpGCD%#zS~4+rwyHbj1FXYbPj{gLB>U_+z*uQLXa;W1FbKu*y-DVmG%5G!{%MOao)xqHwuk1RC2a(Cs-wKU@j86Ma2 z;94$4E6a$Am3ukR5{kpDvZj0i>1nib$1%17qXqeQX%(!W;*6occYRU)1Z_cmi>iG= z{Vp9AlIqP+wJ)x(&sxaPQC9$US$%B@0~RaxW%UCU`w|le@X4a}GLEq;85PLTsjLH) zHH?Q?t*@!yrDG@AP_1{C$v0$hj9t&rAwx&sT;Hxz&j#AUfFMH$+JSCvW8D<0^lgZ7 zXY|rorSA*}Z7-))1oFC4TZKs!`lJHPiiJTrUNEyA)Ah}FhhnO=HEf( zRDJCPqas%3r$8W!Oey|7_7gc%I>RVIhEC}+C|#;bH6ysE1HW3pN zrv&2%89F~1{5+|ei;)xd%snP-P;r+xq3RWPrEt)y0j&x{6RPbhK(i{DysVFqq4)7^pvE#(vC@t;!6NUn z%ZKU=9Wr$E1fcs;wOXlK4aPyNvVG#RfhxNeT6&U&gjd-$a^{)HctVEGvp#qxr)qT> zNwLCC1|^}O%c^V24-oD|N<4CmO=XlI|1PDkQd6AKw8HKON_`j~VPCut!26KO%TQtW zXQ+^&qYee?;8blO0~Ran!F;3)A<{vwiUh8~)G;B_ZeyOpZlV7$Z%`;LjuEl%}@iI|W$_ZdIP(D^yi@CEKv?J*-KRM<~V z+#Z`4>7jC_>7UaeL#L7#RC1?jQEB?;G@-)Ion{=hD71)=8J)^=j0$AvR0@Dfe#S$n zu=ATx_1t|i9JC@pE5y)*3cC={tV*VrSRWxn?_+VG7GEKNVP^yR84zUXK>tEFKVaPyD(nvs;~8X}4Hfo>;h_B+Xdg2)p~C*y2JMq@(3%3R zahmoi0~9Ol#yp!oHDL?cl)=Ib8G4wTgUXj_+82z9SYdw&0uxE7d4>H&&Xig(N|2#b z`UaHRrfFX@N6+7FD1P+|XMqVj_cm7f_E$k3^D z0F_@D53$1j#RMy)Nk@hb89I7bpm%2IVujr~XY_6i9Wr$EK0xo4ruAS1gbKSC7QNYI z(c=|%4-+H3O6eO8g<+sDBuyKXrVU^$gbI5IpR|L3F3y<&CO&$G4rif(3_Uaxz-wHZ zHYQCQ#dwJo_Ba!rF`Vis6EPuiCNh4Iq4S#we$&&msf?UZVNW-4n`&aDhiVq10vS4$ zg`hG&O`FT82o?5x6P39(R2DHRkfBpq1}aM!523EytAVzXp$QfCN}ySl zOlw#lAw%!u2B5BEsA7e^&IF6R%Pt=_GIYq$(RTrTN1C=RP20jah!yq@aoIqHy$vn% z$wI;_>@7L-+|77GhR*W{cpggA4lt5pg?-3a&}AJk&UED*x{&zvrI=`hvR*mWDQI2 z(&3);J~?C!!TD)&ep<>Jg!3mJoIml@)#vgEf>6dE;de%p)53{WktjZW7_ z256Qw(bOr94Wc+Yh~h{S#qq?uMk$ih5GZ<6oK=YvFDUlF?_Zvlu1!hTCZ%f=0xV;) zCQ%OFdFc*zTE0t%(fMO=O)O(moNuK#-&SX*s~@H4QLlxlXH83IA2vw*pV8P)$?jOC zE*(1LchJzQ6Vf49%5^J3u}+G!de&@WO3WN??|g#sj^3n?%ZzkKG;MuXot3WceS0}| zl^M^5n#NFFKzy!q>2~jTX)o2SNJztdjjUOqF*?7_pp8 zu6%?qjjc@AmZxh=)3vO0ZBZay($zKTdT0@|B{I6~S2w1U@H*M}zMta!K;4|4wG_i} zPpZ`AmmvZ-?wX1rz<0^N`C=?zo@cNpb!g zEUfSAw4!03;%t}$wYRpV6O~5Mr-^7Bq?s3;J_N812W9W?u>Zow zF$upu`*rgFXTM)YpCx|3%G#1nQowr-L#3bUi%cq+?}1gMLw*)n-F;912!3u7#=0@^ zkm77k8XVbCp^Yunb?NG*G~MwhB>KT*gS-XSsFqpl$e>VPlJ`8Q(d(e$Em*o!hf{L- zi8W8k9-=_7TctQ#r#Qb>cLpba&`9b|%3?;KXTKD2MMVVWP#bkex_T!KOWjJ@k=cYW z+=&5SBBQ?;e1Rd+!GvjRlTL)QJ|Mv!f(LpBJg+34gVQI)+0GvojgF)^zYPq@h0up2 zk3J;ukmCH#FeJ3```E4I-jC52iTIDYDL7{0f^nX7_rF=2K>NH*0#^o8>k*m94`qEw zf6RG8{hxF4f6~0zoI?*GF9nBRFH5* z*-ZR7hlC5Bf$DnlJh`1ekc63C2#xGS^mzZI{=1^t5K{fdZ=$~Jy+ZZ7ljim5=t=gp z(C_rb9iUQYZ1v9UO|`Fj!+h?dj7tb0qAu_EW8x>$Ll$&|>Jmeq%I&I$&H_bX#Pa&BBs7hL{~p|I76y z$Wf)hLXArM0JsH~mp}@Ph0Cmi>F6aP`m9vUO~jC2ldAiFdWJ^I-WwPJ+(zKW!HVi< zk1KBC#(2VTeY)=9MR>#lkvRd4{#>ybyl4!7KMGBgh~9>DwOU<$o#;qrV)o;f&Iuaz zjf5IqvI2}J!<0=bNm`b=w@WcRn$*uC!<_(eV!U68va99+bNz_6y()IfYn8BOWxT7NRMO z<_mEbQObLlc4HBNEzk0-8yW8)zjfspJ6F6gRJ`DlXZ!95T zVsb)#8Cs+7Q_JNhOWa?HMt`LKbZ)3_OMe@^ggQm2jw+X&IIH7HN4sAgMI1Sas*dM4 zImuNW3k&v!2kbB&)sywOx0m{KQ(nDS_o+2b8jM`_V7b zw@gPtha;c&Rlg3nlX!UEpY?!d5B8AoFT3$PdEy}{w2Rz)kdFIkqLo|bZZzTJAIx$8 zu;96PKJRPH>rry!SvrG!=JLKy^^c>OaCoM#IFWuww0`3xZm4;J`w^90qXznMiYVpv z2X$o?TJi;MpT-3SzXY6uhJap@(Km|T7?$w_8czYwiMh3+?*#C zdHl2|0WTLwTVC4c2((?KrqRR{tPrn1iIS5lWs+i}7-B)idS-69)8`MfT4BAXL$ zgZdrf<~iy{uj69ffPg;k-OIkGf2fVdJ+wa%AadvPdRR;z5rh1J1fZWzkp=j7XBhJ7 z5@Gik8W2x(@l+QMCn)Plqkp26D2x-$Bra@4BqOZfh$Q+v2_y1(WriPx8)^aCnZT#; z%-n)=&iD}gqw9#KK9u|?tbC4Zoi z)`4}R(U=uQ*rh#GXQ`O7=vSe@wO*Rh+bGTcfjHncI^uy9Mb2J@a1%EqLbi}!_ZTS6WHjP2iV#L4 zAoMY+5WT{Fu{3*;z|y`@0`%;;KpX#9q{1|-aDX8`p=cDjG@1>R^c&GcKPW@J<*5D} zgh4I?1DelBm#pAmfbEs}h@CZxMW<_zH4E zP2VP_!2zvI16n<2!)RUW9cW?A02)ZtAfCiQLu*Z<5*dvL0xsf+N-$Uz#xnsou(JIB znaS+QA?nRpUjJ@DkB)BUemE;9q|s?VSG4jy|w$@czGrH&f!&#Do04L_gh?mj2l3H~e} z?haK*t(_M&>S)y3HAg8~@m8&#zoQ&i%fTPyUl6QBzq+pKa#GW0jw9<*0$Jh8;(Za` zO|_ST5FL1AP9TrW@#K-&(-nkjyj7RJln7KM%>a{?NZfkgqr?0qZ_o!M4(q*s=PPpO zZ*)D9J3s`R!v_JnPN}u@u;*Fs_BF&0Q$co}offtH8_y56h)+gXL z5gAJgsZ!o{lvXBg1g)+A1SkE*FNDfRe?=uLg+6YBUtVUmCs-c=EBgiJH!NNqh|`B} z>pMzQkjxaCEF1i7s7@03+aW)F>UA^`#8CW-Mt`noxWz>$auF4caN?pfxrmI$0O6u5 zF7y$L`Ia&0h9+dpzk&xM1D$Sy(pYa~r7;?_{zW=xA8n7fDf9Xpys94>Yhr3n*Tmqg z;5Bh~VkE4k@6%ucGy9>CiZ}+o3s4W|?EM+Q^oJ%%%pP!r(iB~Y1|eFS_CynL;?$=f zh823fh+bqgLV=6k1igWu4U|3;(A*ErVtmw3{Va2!G*Q9+@)rR5OpF(l$Vyneimnn3 zmA{VO=PY{t36;May#X-F`jllf+3z5+$!b8;j`wDus6-a(+xh=a%n>2P`Lx929au64 ziJl7rex;oCA>f~Q_y`Y%5+a%Z_Qh{WmGwMb5Ws1x((8nmC zd(ogrM`0|QSgedGGoIX{t2~)MDA2!SU7CO!e-*}7z-WIqr!Do(2Wb+<#7ObM-Rez-bzgP#*F(l+<0`m8kT5gruAqV;Xw*KvOI`2bukY@?G*GtfXfA>t)oBdKbX+^7eFjFB9{`S4t{kY`_#CQjF4`Dp5K$;0P;5b z8V^oK=g;~c4vlY?*1%6zN3!;l5EU#H(+xSouL~KjpOo@;!C*oMJl7ElzXoxS?TUN2 zk9!-k@3AdF+(Y{o0@on`hrNg2X!BMy6MXh5t3CYaH+Bg6PfK~bvl+3I0O*0!_u=4t z7isGdLtPWZII;P^Rr=IDnr^5Oms-YfRgLn6^Xw+91C+ zz_0b=bM{Z%RflI6tJWH(S@Bpl_wFC(D5jN0)=FLGXJ!KV1^C z2H<=&IY;93!+Bs$&;vaTLjZVyJkZ%cBv{$ht-oCsvj~i{m4a3*y7aod3*iDQ^~oa^i24s3ZNsXn3`7mA+uQ zN?$NV5RK9PtdWSsRS$_KA%8nRsSyGdS0r>;2(w0$`5U+qg&TM?vjkLuXdi&brMycS zquek-H}VkJiAG{qD6uP)SYDz5ViQ5^3MEEftck>)gN`M!=ZSH@U}N%Sjg1N_GyNr6 zJ}7|sGB5`-5X#Ts^i1Ksk0u)EA2bROFxvgMrugYVzKE9S<@9DjVm`{)AN+L{AYP~a zDMU2J__Ic#Ki6r0$SgQ6Aq9>}&^kun^b{sqn@WzojQt{hIIH&EYi63us5MYNqPf%;OX z4q)R+_P6Ns*03Jj^pNJ8fv>h>OWTZ|CTP^)!J=s&Z}ZQT`?IV zDEACGM8DZr%DWkfk-d77Z+7-2t7l=7W(D(++jOx=A-?nh@or&l^+{W{Em@=RNm^Gz z0?==yXQqlu`YK3sIIs+-K?8d-@QP9LEfLInOk4IG3oFjo7W@c zLw2<8;S=JW+60ecL$uQJkIc~Q@-Nc4+*``wbiUwpI+u7IZNGAKiF8Cp<#jk6nR)S5 zlNTa#M>^MWmDOHHv!>rWuy+?36$PDkPUlKHt1aAWqu0@-Rg2b*+GIGoL5YG-qi+nn<{TDNNx6o}Tj!O3~X&hiGg zylQRvr=8^kZh6<*^0uAjGj93VP9;}NU|=I+#DV3Zd;uzYw4aZ0eAXr-yk9GI61g$A1leQv&+G za+UUWD&0ABR}dDKlFoKE{kcsaV-ERf{CnA1j^LI3p5_f*ypu*?cRjzW`PUSvVxs$`F-LhOtQt61^uyY*| z8+iOYvzxO{=M#f9pP5Cub&*){;pGoZ-q*RxtFfl1PjNddiCej1EmpV>1K!IpJ-U== zxX{Pr4TIm00{RuX%A0m7F&w%o2n$O|WjmXi+~%EF!}BzfRwZxSS-!_D6Rj=d?JU!{ zWs0?BJv+;Pam)AZR6gM||%z2bOv;d)lcC7-TlIO%Vk!AF;C%?wqf5z1TWTduOUTw!OqnOknKQ`yN?w%Ms1go+;ReQ#MUC5>s~?XfdI z%@IzR^WvCwkB-^66H!`j(3JIlx1@`1JGJv+;Yw*$d^W~Y(| zD*9$Z)Y~?5Ek9Rz&Q7H$S1Izg{iqds+iEFkLPzvPJJ&Am`gLM%{D4E|tke0L!J5y^ z*WU?r@6~t2?tK=RyfRmDzhhcTO4(Vx!L3TaV?nEB!26p_k1i#ZaiJ%71%uyK0sR=R zQq@kS28XT=!opJWmYq!!w~2qpu#|j3BN%6AnaVAbtu5=?S$@bZKd`p++gUc`mJRGw zGPp`(JCznt(WCw4J61{AhIaf5JM-^2LOXL_w6X3{YddGZaA!YTTmHw4@uQuyZroXC zYiGaOS@z|Yy{s*J*jWySr5?-yb}A#d^PvV6KG()_l~Hyo)49r&97b&tnRKSAjF zj^%#r}8#e ziLq0OgNh!I8Z{lQzG)ZKUwt`x$6z@w5U2OJWumoZyq#q#w@kLStZQfa0q;<{L4^Vs?Bb;J3 zF10h-#EsU&$dHX|==iO%v%SbUoik?RCTe-wn2lQlA-u+6|1@~t9#FZzwS=`;w{zAK*Kp1=Kev0%PNfi6DPX5k94dM?zFf<4 zZ7gE2JQRpiDQ;Q9+VWL9OO;zn)|PHN%YX0=l`*LBuvFyE-$XdYY}D+GV!2T@7#Xth zC>_7bcD6e?r){;wqW?r7R0p`q-dd)jf4800F>ZCZmPOHjKH&W{)1wdn^SIE*^Nhjo zg@FELu5!^%MoyAx?t7d2ETF1{FTn{9Gl~PURD>@^KEM z_F(A}_h;}!qT`xPk;oNSBmE9mayRqDEl%2{X zt}@bFD3B+gUE-mRZ)8i|i~{^A4>rsPN(2#GS84 zIK>CsT05g%+-N(D3=g&_^w{a#VrP4wbGlx2m&5O%JJF8s2znpKs@tg~K}C;tywB>vR)lsu&dxlIBcveAhHr$` zv+hwHJ7*2Jvk$E;|7pf}-_BVEch=b2*{61vEx6^E)|Ow`S+<3x9?aHuD&KSG-xyT* zT>CFq`O!|LGgs-D!>F|-jMZRffkcl{nQH`d5x z&N`h*25UZqExGkq29*jhr1Se5uF}RloUQGwe&SZ&ThV$u;60P+>18)A^zmqK@LN5g z-;Jwuwo~cDp?iX`@Nv7loy`z#Gtihrm1qR}+gXm~mZPjKN7z|T<(8AIEhpGn&gPag z>{J$Vm3ek5E1;rBd#Pno)}S5FvNPYr5!RdYVy$(LR@*t-!=3H4w%l&U*lOqOD0gHZ2TuOX&MDN|DCIxv{Sjnq0bwalCyR;H@MAJV-9^prs5g&eS!rua#f%}@Ijh8-mA7_Q&d%~JZt1nQtZHXj6P9`~ z-?39k;LhU=DtxZh;VMaXD(`cZv>ZmQexlV<@&z5yWINXlx$6eR-1q^9%vq=NBZD>1 zxbED#t3l-}7}ELOkE`@H4`)w1t0CNKpcSpI0q-N39)%i*3w=CB8~k<)=uhS<6YNxG zap>tFEL0^^?Q9ltoB75ZYC$77*UoYkw_I**xzx^b6SrJ%ZMoLYatF8EYNxV~tL(N@ zIR+Iy+J`NZvIp(>K|AyF9N~;PFHT$c=%k&q>)hEDYs<@Kj7xUT9&l%Ot)1Prvvei} zR`;jYmXGZ$^T1LMW>k{6y7Sb{&z(PKP~mf}5LYQ+r}7$CDV}8Y0MJLRXp+@Z(ua=d zOLndm?%G4ljY|ocvrebWV9mQXl3NcmsPu;+o!=9<%Ge~+(`U4u)iiE3*^1WCfcM!< zk3ucLg+3m04St6O^p|jzMRqEyIrIt;7M7A_b~c;2&4why^RzXM;5s|YJ=}7qwdHm@ z%Ol+Kpta?GJIhnt^0=MKd9HHCPUR|8^k`qUOv;h8@2r&%gxr78|^Ijam(G-mOJe%k8sO_b}Fa1%5giDi%`*{ zeJ2h))v<~q-= z7r5o~)|PqgEQ`QW4`x9-mEzp_%LWxb*Iwr;uiB}U<|=ZE{iu0Ttd^2_bVOZtt}AfY z<%qd)DIs&#=`3ro=CNB`KM?f=^~LZmgdv^ZE4j+D`lh91iJjGYZndVq1+CopwNljk z7N$opcH%-Gk8K9Oc>?eM9zT(FmTfv;31=Ub42l zU}t%oTi&p?yk=+lkXzofQ*opQ2KI@aN?xew(ax1>m6Z7qbEh*hRm=-M5`{U!i>ao( zcp=p?iuvrEmEg`^v9>H`#(3GznZliUtev^+EH!TVhP7oGJIhM2)Pq^xPQ}ZeS23vY zxmKO4#M-GOaur_=qgE@`YAGo|N3@2W>s0PKnV1`w5;A9<&bkI`o)7)GbsvLDp}^!F z##IKJhjXBv)fjFy(u&qA0q+x;9$iYN;X)se$p*i#2J~lhl^J#_i#YUr5Ehn_xpp=y zxy>?T4i%vhTw-UriCeC>wp?pxxrPlKp5 zabe|o`64X!VCJ_|d5JqOWKiLA?G>(4)J{d>Dy}rE2Y^0mCDW{y5;q;u5_YaN?)nX4 zZd^*poOL?O7_4~&YH{m#4JtAW>HMzERT9!nPamJ1RSLJNYelPUz`LL6QK%1bp^wK0 z2ESTB{}ZnAv7Jf=hi(kQ!cy|7olOgF^QAF|R2soA>@2_KmTj#qzqYgdnOpv3ZTW+p zWk+uLi=9e0uF}~~r7u+UX!o*A%JQ`1J?zYfbA%!0yclHNqXBl#CUR%vtS!fwF-F-r zo5h_?w{|ww&Tg@VT~;tE{tA+09jUkJj}=(hdJ0;WTX?lI3pwHL!#`CTu3GPWuMd19iKIC z^m$uh(U@Y1KFJz=f`IOJWa`~{0l2f%9nCXZ64y@lYeFMur8^pb^BL*9Q~&LvF7oTE zB4?&MS_c~8f;8e6j;?0(x26{+^dq*V7ji^KL`LmN&+l+T?oH1}x)Zf89lxj)@-S;Z z!rG7O?GY#S?nj(rVK|*$gofjH7LGIQ`Ye;@nBI9NFEDwL-M_@-AI$zTyZ)11Ut#hp zlh+`@Ki75rI@b**ZxR_18F@>;j=Zg3=eonL?=pE0k__Md^q0_oGHff;9gUhaZ`4*C zx8>=Mc8xw4hH|OpP-a;Vr;syZeY&G<#@9_+wQLtOplKU}PcEXqfM0?nM?r&)c>YnMUR(+5t37Ub+WJ<`SDv#n2Puw81^hQDk}?GM!}R zdwhgz_#Id``17#<{r89O_#KT5jW0wvBYb{G(+WY*L+QGa;CD1J0y-lSjiVM1iI1T zmpXw_W?uB2UT4Hdbab0G3VsaG$9lvkAe7OjdE4MS6X^go@S7g^&WH~QK!7S)t^;-J8KF<;U(tvOYgoZLnHDAlDiX;*j0I}4zc8&Gr}$~n6|n#vCDU{v>-Zufv5+rj z*I7(1VR9*x%XAsJ+^-j1E7hGX0t zw`xV}d{%i-?-65&_m;sk;u!f@5HS+T->wao$)KEWN$-p{j4G{x#=?!GeFRDwC#H$Z z88Hg^BU;n%JVcBK>)?7TOP?ngY-i*|ko+MSkbL8cP9IF8-1!~P)89AbaO7+A^2>i* zsrSp3bvJ8d^{!GO^2>=Wb2%K2xY!2ox6NqNw!!xqZCZWbz?XpsNvqZkK4{kVn?}vw z&-kpF)}m3{b{TCN#QW-KwQD!{zG~$LX&KEk8nw-6(5ms54N_WXv~1h9dEI7>gHFq} zZra#!^G0z;o|lVucK_z?>K>pjbT4r)cF$4Qy7#-cxp%pDxO=Pj-H+W5-M^~CJR?1G zJqtX4dfH3ZJe!q8(lcqZbXB<{Et40^TjXu>UiqwiU%o8gRt77>l|{;0CG!T@M;0#P zlG=61-#7p0{MYl}&Y$UO@9OCK)z!`Qo2$F4r>nQCpKE|?gln{GoNJ4??&a?59_SwI9^oGCp5UJ1UI^Mt+-pI4 z2WanipLAby-v{l-?k*mk_&iGeis!25n&-ObrsuKe2|6-Cnl3GpmPpIcl^xPC>9}-S zx+UF_?xAyiMc76uqm{ABIAy#tL7AvbR;DOZmFdb1WtK8qnXAlG7AOl5+AIWjy|O{ssBBiY zDchBu$}VNUa$32lTvcu=x0OfAW95nRRC%Uks_oSd>aS{NwX6D@+Fk9b_E!6<1Jq&a zaCL+_PMx4mR41uZ)T!z;b%r`qoukfE7phCuW$JQug}PE*t*%kms~gmf>Lzuwx<%cp zZd13bJJj9k9(Aw!N~SB);aGqXTj*MVF za9m4AcdctZ#&`pc8*$u(<7OPU;J6jXZ8&bnaffTDYbVZjx#qieLvIgS_M&AUTK1#m z09p>B+#dx1n_hT6dv!4_f!3^#EEAq4mhs$MqPRPoVh} zn$Mt_>Avgw#eL7!-hJQI!TrG1(f!c%tNW3wllw7p`-!WI`>Cs|`^Si@Uo! z)71k%J>Bh*^&Q;3-5uS1+`l6KJGuM0JG=Y4ySN8nP7HK+a}R>WU|0-s_izt&_jC_~ z#c)`RfW=5yjDp2zSd4+iSXhjM#dugufW<^uOmfe3O@`GJSWSi1G+0fC)eKn8bPsgR zau0INb`N&VaSw6Lbq{sTgQxlMv;dwK!qXynS`1HF@U+A|*}W7$%iL>S%i(baJg$Vt zRq(hP9@oI*TK6pXI`?e%diNan2KQX|M)y4TCV1Qok6YkzD?Dz4$L;XA10Hw6<1TpI z?e5^(gP*FH6CcNK*_uKG(2j1_( z`#pHS5AP4){UN+Rg7?Sp{>0tM^%OtPfRgFC;QqyP(cRv2$=$*8hr6Tavin!h8L5-! ztkl_aPU_-0FLm`?kh*y;O22t7N!>kvNIg84rJkNYrCy#ZQg6>ysgLKH)Yo%e>gTy3 z_4nMA26%2s13kB;L7qF(V9#A?i07U()N@}N=6N6u_dJwFcpgb3J&&bPo>lJA_!;AQ zB8~MtmBx9VN#i}4@&wN>@2f-@w3R&S6=MtCue#3%S${1yuvd?Ug;Ssuks9&S9^xbYdj<5wVsjkI?pJ1y=Sz%!81nQ=ou?-g3rzHvju*( z!p}DN*$zKD;Af|2oV*KucEise_}L3T``~9k{2YLvgP!s7A z@^ERpJVM$bkCb-GqoiH(Xlb`RM%p8fmG;Wxr0L%A(hTneX{L9gG|M|ln(dt|&GAl= z=6a_}^Sslf`QGW$0`ClIp?9XV$U93~?42!TdFMz=ymO_c-g(k8?|f;Wyg=G7FO&|* zi=>0{V(E~aB^{QRNJr$Q(ouPtbWC0@9hX-~C*+mVNqLoYN?t9Ume)wX%WI`G@;d3P zyk0sdZ;;N*8>I{KCh4NQS-K=|k^YdkN|)tr(x38n>59BVx+?FKuF1Qk>+){thP+3* zDeskT$@`?+@_y-#d_cM@AC&INhot-RVd;Ta6@Jby2QJU6rd+ zH|3i2n{r+1uH2A%C^w~^$}Opva$D++5~z=ISL&QqFArBb$Rm`F@<`=Zd6d#g9<6ki$0%Lou}W8YoYGAm zuly!YP`b+#l^*gWrKdbu=_T*<^_F+}`pCO|edRsAe)3*le|ev8fV|%~P(I)rBp>t* zmJj)c$cKGHFWt zoNuCh-Zx3U;F~O8^i7d3`KHQ$_@>F1ebePXeKX`MzM1k>-z@o>Z?=5hH%GqVn=9Y+ z&698W=F7Kz3*@0m3*})+i{#-+i{&HUEcvK+iG0kvR6g!qCZF&wm%F~P0zWI|oiVHA z6N#(klZk8OQ;BQkUp(vN_MY`}2hRqq5F6#b$|kv=vROXq-6EgzZpF_w`F6~9`A*CZ zd2ixQ`CQB{`FzZ7`EJY}`CiOk`F_kk{Op(aB_5FXCmxh9CLWS6B_5VXBps1QCLNVW zB^{H`BpjE|CY+GZC7hJk$DWcm#GaP_Nc>&Co_I#Sk$6@`AFgw`Do%*`B>sL`FP@WaK8cWH|0MQZpl{?Zp)_=@5sL=-j&ZJ z-jmNJ-j~lMKETgId34evc}&t{d2G@Xd0f&{d3@3{c|uaAGBN2FWl~amWdgG97HYx{ zrGHgAmhPndTDr5+sdN`*a#B}iN>VpvYSM4Y)GFPTX;peC(~^2B)028BGm?5MGn4u# zvy%EMvy=KMcN6<7_YwyvbCL!sbCU)s^O6QD^OJ@s3zCK^3zLQ^i;{*bi<3quC##H9 zPE{GD43dv0cor<2UX@=)R`k=Cn%$0Cn{M`# zU6~g>Lzy2vQyJ=+r3~}TR)%}#C`*#&Doc~*Da(@PD_0X1DAy7eDz_3ADK`@qD-RR1 zlt+n6l#2;Vl}icBls^)dGmyVBFU1Lr$&z6Ii_5ya$NbN$_eFim6J*j*C}O+=d^Or{kziB zbw=ssI;-?{okL&GD}7xTlzy&@$`#iorN8SBWq|9lGSKy>@@JJRsJgGB?!Jbf>&hV4 z4dqIeo67lwTgv0a+sc!~JNUV)Y^rikneMr-40b(Gu2y-d3~@bD2FZ_=o$e>f2G>*N zwC|bndt#<~L;6MCU8%jgLhhj6kvgi6@ZsvQyAysotHb0j>M&PVb-uToI^6Y}I!f-2 zwjSyTS5I}Ns~2>8t54j0@Y7d4=jx}9a`i{s0QISRAbtj^V_bvPwXPxRSl3W>oNJhR zBVjn~N2ph%k?Ka*DD_&E(dsB^j5^*mR-ND)r(Q}JuTFGL0M11GOj6IsOjakkrl^a( zQ`J9x)6~80>FQ+H40XS2rh3UWOP%7H4ZJz(GxuEl%u^>T^VMmt1?sa(3)OD&B6YfJ zv5IOnKa;;W7$!pXl@>+GaYn{5owO(y6 zZ&0_&8`Zt?CUuRxS=}jbQE#}msuPrL>S5n@b(wdEdMt6LI@h&Jo#)yOUwhQ+zP;*g z-#++!)loFl`I^J=Vh!>=g>ucBF8Vsk`Ro}!dOB)+meHtPx$@vdAn5GFn_BTds?)3` zZH&S(()paIfGet#@jY!PANC`iFBUO^QJuCwP#x@@Kfj?i`7aNCBAs)tYRj3jZQ>|L%Dlrv!6FsR=zI@fHRb8%XRV&0)q%EI5?{GZB zpEYjU>3^d>YUq7BFaLzY)9Othc3`1LO<$84?Q|5$pT|M&H7MhBU^|)q7aVZXK*C+t z*u&=w>VaTECwe60Qw@4G90hC8jLH}_*7JPDxgud7-K}tB~dTap5 z-DRsB4ws!C8w8>k5$|vuJ50{9|KtAHK#)5>1NcNqu_HteA=OB}Hfx^ICf0*Jp89QC zecq-~3s(YK+Pcbo@2wi$pkA{kZCbT$^;tWYzT4wUZ}&~pW~~}jEMFm}L0qdAExu{l ztlbX{K8S1J$1Ygg2KCZ$TA^~eiq*5jq`5ZsEnbNqTLyJ$s8Gd(}miU81OK8?ErSX>uM%Y(K=6n-~+_l=viqQ0*jPCizE#B;;ut(r8a-rw(V>m%uO`)9|WyEw7#D?JWJI8G!h@4nkGu13T1 z<>Qj;C)cW(6j!5$qkV2il+!s{ab*5LHpCr;j}{Ay1)p$DkXWrRwkdY`(2EaFjV!(R zNP3S}1>UNIw@?jhrYBcu_(9FO@5eW6`ArK)C%l2cY{(o30;?sQl<1B_$4Yo?B^7i! zlfBLYwTyOnZSxKO)NN#BUSc^BmTQRRKw>!wmIaauMmSSpnP#*ke}mQ0J`a6%WRibo zv6dLV)Dwrom9ZU9AREGPRc#05N#2=}WsVq;N3|n!J&ZOGqoFf#$f$uD>7Za4EgEMu6-`rNx`~+1B&J7Tn)!kAi-M8Q z-FrKtVzTp{Pw;6dh>YyivOh(It5uv6;ARyBLRq zwH%H{=tb09b)2>8IMeE&I}ruGWgc3$Y1X1yyJp`STo6`Uh>H?SaabIO!*B;!<+}H_ zQ;BzKgpBhm+~TJ`Fu`_pPC zC*tNLy_(49*cDr=HWtjx&-I3=PJ+MBnzd}&5NmBG@|GT2WuUc<`m9xxP71vHY1Z=d zhV2?PZl2K)FH9Yoy_utb3yxZ5e20W2f7F4odmU=q;VG&v3j|&PV}^ajp@tv=JBY$~ z!4Z8;+&&LsgBM(IvXj!;UbkNDdhreG*G#Kf4>zJ=jQ{dEZdXTC(8GrOSFSiRcj-5y zz7iZa&B$m?wK&CE@V=XR|LqhdK$^LGpEGjMQRBtrY$1- z_ntcxn1*o*j5?i+^tkv`s5z|{%G%bwth`LyRxOS#m+e|*m44wbvp%8vGD79mztyqR zQxnt<+o`?~6&o_mwpp1S+hnMJ_*$)b4!m|NY!1JYJpJ{?jEViKYGv4RJ}j!Xcj8ln z2`S1h4qM&PLU}&IHw-;-`#!0XaHYETuQqDh z2;~W1`LecU)Ensu>F8yk@=bcDU)gL-UaBSFlPFYU((BgLkN1-&WP-FZA=_Y|#t19t5)08w^~bWsn~7g499 zN)KJ5E>BEroEn$Tmj5j+L9G;Rvg(yRq`8i1KIJ)ZBi@4aOQvkO$2G6AIxqfr(`~sY zRIjLj0IbRgm6jboCl%UMkG6Aw7E-`dG{zH&>eX6p2&HU%-&BClX=RjLey-|=C~G@c ze0KBA^p`f1-_)YB(+{Phldr7po|xiZ!}A|$ZD>nTwrArejnW#WRzIU4|E+F>#OCRVO#-2#e5sMG;9DiDRvR#!)n0f=Wr%Cm9M86;q+bb1 zyLMqe)}S6>?C?FOwuU-lu~bm@AO<yT#Y+I9);)eD;A7rNf(rM*Z*f7i1m zG|aOH9)LJ z_w4q3r!eVpMT!0^yd14-WdY&`{hiyypLE4i)qlqYxNvSM?I6#>AOWo*T-{>V%yZ zAv^r0mTsOeRJ|#>jbCgMIcwAOxP%l;gFbpHYg?_ZoBlZNm4^NcIc`I*f48)x|EedP za)x2lbK2hgnfeLRR1psP;qNx84lm+=T7rw(fe|w0+v|7zg`AV&(~f%I0E!fTuudfH`(ZLWNUdyxv$D6UTU?91A2>(4$^ zjURliyqL0fSxBI1hjcL)94(9;`OL~_mDv%dOhVT64$bFo!;>9cbgY-Py<@!9c{=v* zb(MvfXCRnDQr@Ncy<)t!A+C38u2uM%uO4)C?3cAgivlL(l75dCJI4Sg#E(}gV2l&u z%KqKDGQ)qkltzI_N0+tj4?j?|YPH7e<+P})qBK!w!qtflC^9tbgRL$R~2=Fr@M;E88jrBc^$R_S}(p+!X&u7kZN9g`U)4CEO2q zmiCFuvE`OQX$lv53i1jZ&lcqMcG#M++tfJrqHmGMmL8FAuMQimjDHJ|jt{YK-!4Vw z70A5IBQK%kuXvUg1KGAvX4n~oou$7Q17v9-7$Zx`#?u(in89nTg|u~8Mjf!(V-c)nPl8yHRE1n z-0hKfQquRe4s)}4?&ck~QP#a1I0FLOCQJtdxDQ zqwrwKSjPwp)*9AXVEyHhPZ8DtIs~dSs=stpr*u^6v2c!XV6EX?1e- z;aoJqxkfm!)^KhB=Q^=`rLEXAtTxwmsfD(=Nd&Og2<+Y@`8E*@7YJ^bOc3E!Pik0e z1b2hrPOn_Xs~%68w0Uc?D%|NU$e+&+#|6saILlF3#%p|l++!7^3NR{pzdRN$uMEs6?>VO7tk$9`?!)dgW@w)?8bv7zX#S4(UOTTTKTi zG}2?l2y2Zo8jNnQ>>|Kkp*zd1<8$e#)RH|(IIz}mo&(OaUioRl=@W|ctPbaC6P)J> z2i6)+ZQ#@*mhVC@PqlQJ)eB-Bs~Nq>_#$PTO0!p_*Nez#B)xnzS6FLvjYZ~qlz9^C zQ>Jz5vp%h-OO0ME);cc{0jxEGh9F4t%6_jLPaN-R90`mgNjz2-I12rEW-U8tRwxI} z3P)jl$*hft71kPS6RN-w+P0HJquynM^FAa-XbAEws%vB7n6<@B;{D5P_)NXOv7Z ziwIz?5i9_~Jg@vCK?ury9uCJX>~Q4D{YM>@s&sy`im@CROTF@9uUtqZf^uKVH}ql< zh_VamOVPyHkZ)>`HVk-3^ru1d*8)Qv2F>~?7J1sj$5CD2w<%dxP4}ty*Swu zlnmBdvg(-blQdmHvpDZ2$uAR*pwm-zI4_&v1PKS$8csTJnh=Yq)0^m1tF6+E za>H87{RVP3r`)1KZ*G?RP09^xEq5#Ae#a-jP3Z+~{tgboJq~=jPc^$4WkE=7am);E)|VE{|6+8f!Tz4N* zbT@8&!zep!>9dcBG1J_|iN2ylu%%Bl2Gblx(-idfC{*{5f!-c#CEEmK8%Nm$tv${p z+e9nbrXbsQG4eN*P}JGq@jm)Smz#9IRUO?G4hcZ z`4Dl5I{KIn=LknVqz6;m7mY(ba$j-&cX9!Es(C2hiXY?$}roBigu%$=&2PoHK zW2}bW}hum&g4h zq?gN;%vOciU`x;T2-qH~CqF=7qE>zgFoHlUd;mzIn1NP4sAy%}`W_`D*#8yjCH6Do zH*NGY;(ymqlCRb`(92ir7vvo`(98eSSK9>ETIT;CCVr$=}IOU@3WfmA!K|YR=%H-ifa0SSgphE z*X0*F>|rW7thJK6fa8djA0r%5S33Z4l9iqRq{(9?V@ZSsYYpoeU{#NmpCl|nVOQ5t zJ*lHo70t7R18WWE1>n?-m7gaZL1ov};XH4GQ=4#Lt>Jiq^CGc`O8Z4!YN2g>L;!1z z;3W{$CjwD(*Dsl%0TIAjBS;28Vyv7%5Q6$n#Nl{}9gh4bO%iles+wtN72_3P1Y_m2 zSUH7A1RWma8#)aH;$BM8F{xeKgh~W!twe8v?e$pswOF|sv58vzbsf@c9JiScPH3bS z#0YDRu?-ko#mesxprFcI>GM@A#*^#RQl*4kV@M&^$wv#8QP(xpZ(7R!%M zhyd0aK_3w0$I889 zgTuvP;Xqx#0Q#Jw+;Qt0Mp&@_E7l88?jI)l6h9L zEkw2jluc0R3rw>8Y$e+=WLwfeUPK8+b-sjm(;{7Np_`UdnPE#`<~2YmY9Oy76j7NM z0pNz9%vY6+w3d)yOOLb}NE;i->j_Cvvcrx#d-^&z?L56PoQjXAa5fSL6L9Q zp=>ij*-0p{rAOHZls&{Ds_{L#v_hNgr|ht$&wd2i4^ehei61IC`%%gcTl(yOA^WKY z@(BVERQM?zdY`jHkE`$#IwDoIoUwv%6$qCb$QK*P=ZQj4;FtNPy@>4Mo;k1MQ9JY+ zl?Jx-rMV5RTMgtJ4dm;@C93aRI-DCE^|}sBXdGLddf|jEJ>Ok%_*67bj*3&S*n;xD z0~aQ-R8h*MD)ekuOLaG)z?L4RB2dc5$>j(|P~GKqDCJC0DiI27=~3^X8m~Ka!uAsU*qTZv~x`+KlcNeP}vyt&V$|xxB_e?V8Sk3qm zGJX&z_n@Sr`u>1-SPxx(p~HGo$ziRPyf<)i<18WUuG;l@| zi>Ss&>QW1BGlmFYtr1KB!8jri75TW52__N&tTlqEAebB{e@hU8DxZwQ@oRQCa#jAV zj!IQF)2w3r2#ncr@(*$H3?dPf`E0(Se*l5FmuBdg)UKUNC4#k9qQzhQ~S|d0Pf}?Tr;W+sqafqt@sCcYEwI9Ya6WKw-Rr|q`Sx*ov ztTomPU_BQnpCM3Dxt|LchlOW!{Q~GwigL%T?;>HrmI`ZuoqnpNQhbtJ0l#Qp_nQwZ z#24g!%cMk@a<3e(zRicVmiYl>zCT{RkCKbZ{r-4Ox!88Mnt)5=WE)EN)==ufFvlQiy zTi*=Af-M!+LQT0Z1=eC>5w|_x-%X_UiHr z9d?LH4r{ICCxLT3UOq}VqH;eDh()aIT)7`D8S4~b!CJ$*2(0t*@>#+Xl>2!d)ma^t zdO^QLIIz}mt^?=qc=;;f2+I9$9nMt~oPP-i)*8-j;M^h>QMupJr54)8mOwwqkYJIZ zOhS?znV`Op5tVynLikn{2<{*PSZg)77X)P!6EvM zQ4JVX6XYrhawQ@WlzY_#?ZcibAQ1ObB^{I6wGU8)?cCbP*%0HO8mG_*8-%O@M-Oe@e#}t)o&)_6*^`TEnRYoEi!8bA%%(_Zm8! z=S*;3ARJh0I3D2CB^E)s*VScK``K$XV|`?dp^SoZk3mKw=@m$4Z5YPO|4jQi9lS*byBUV^z ztgnJKJwa|lprUe52bLfX3!CWrg+VLI9k;&M2n)7UScRH$&jMCEViJ^lI{>U_QX)*b zcc9F$)-rcR=FSOnM@lX#_s;xW>!{-Z(*{L1eP^ViA>l4i;xC>zPpH zzD*&(t?zvzfVD=@Gr{aL_u^z9Q!-d<$#OB>PieY>a{mAKWH+sq^aSZf47f?zfgh{}C-$pmwW0M;5oAqW;G$O{NUQ0@zH zIPPGFBUkPVbX2O+S!5MsH855t$jcMtr9>hq_mzA@F9(6RmzL_7)UGX}62V$4(MGVX zPmq60kk=BMsNC1x?jb1F4ALoex)*8V-Ah?zwUrCTJ5r?SUuZhPBl=~Gtvzr|> zT)AH=ne{rc!dhdE@F&SOzx*G8ipt&Q4-t1#>Rd*KuJaA-k5h-K$lU%&jhU(O>ELAm$k8~Sq)h`e<~5IwGs^n+c3X8#4isbHc`0`(;*GvxPx?XLL+@ijIh=izXszNzdVWn1?4_Q z$2UqxrIu_Q;lNtM`3^YW_~nU&BPjQ8bT|`Da3&KDtTmkPfisO*1m!+Wms#!S8CEmS zM#di~qoCY>Kt?0!HHYR3Yi+Lck$Em<7M1&4U261VvHVy-1hCc!mVsc2UtZ*we`%8%hd3{i+aOEDKsJ>@_wU)UdGAAX*5rQBdx0nq++2YQ{Fm*eX$ehmwlQ zy%q1UcXauM4$GvH!&)nON8ofwl-m=IsN6dM;;^9H+n0>hiLhX;VRZ*qcB1?qVF}7T zTSxVtj!M0t_aGctYdD_(r)Q%4A>jzhy{8W6Llc}&2?y31P9AW25sRqYd+AaOZIe#~ zu+|9rfuJuDh|0Zh$prn00M;78Fc1t$lm`)npxlSxa2(1GN3Prl>8Mnt^MzH6vA`Ie zD345(M-Yji+(+{bJrV@sUK*ieQoHtRDiN%;5={o%w~6wkM0o#+ zj4}$!y_reI=2kPljf^c)~Q4Dy|0c+RXPK$VvGRB@DzDiiadl!1m!-QZ|Gql5ckp$9h2I%Ur~u*t(9m3 z*v6&EV^ieO#3m~DaXO^29Cx%1PH3cw#0YDRaT*w>q{!b9prG8R==i?VQK==HPB^gE zaOMDKR*F26a0KN(ONTSl1m{P>fwhM76L97ei=f=+>oTkTywGaK#mHDl83pBDh>S+k zYYEL2*4kWGAoDWHEGqY9y42{!V)?O>2w<%dtOLQXDe{^WxrjJK<^HR9tU$T1!84QD zLBo}MQOT_9i51ow>mOjMcyQ?@LuxJ8bE*9zoVasqz6zEGqUxshVOxpkn~f_ljP| zt?wwIz?L566i`kOhp5(1q!#4QVSN&+)_+v8`?*vzrCyxqJSBoHeWJ^l z=0%#Opwcg*#y_%k4pZq@tYrHK*{)GGL7`tW$#&gJw%f>dD^} zxSMQgYGcEezRY)~CCO#dxjzfh}4U9B|?EMJ<0<>xj#+5k5B|fe!mXoJ`$xoe?B|(xC(ztN2ID2 z*$P5kAk2PkJ_OxQfXjIUz!HsicOR2rO7_x64iIC z4yPVR_36Nb#)%_7*wXVg0$*~PoJeqj@=n&VCF+ROQoT$lu%$JAr#osqr3)`X2c;V?q<5IYVS6;lC1@@y+PRowfzRN8A+zMXpXR@pJPj8&7iEJ z($3JOMc)<6hgOsww)ENGMfR*Txm}u^NerUO&JvFesO)xl=4W=0aFv}|GG|BPge^U1 zcW`E>$?p-QsIaqvBnY~~_jLUM;5mxI#;vahA;Fdg=@~^~_Xkn|@d*Elv;fH$GdU2Z zum@09*wSYmhO9%<K7g3qpY{J<3R+j35qCVUNIqtY$qD zs<4Zc?6~!fqU^Ax&;E6qnZhnkG>#I%mOjxWOmhNFQ&89wP~#%D&S47s8!OqSAlrA8 zO;Fh1nPi)4CEE|kHX}`*P69cP|_AQiMRM=Ze&c2PZ!hJ+oiOqju;qDh+Ju zOLGofXVT=;Y4S~!^ z!TzsEd#VNPRf6`)O>MAEZP6c9u3+bVJwe=r3)6TFd#1s$O|-_$D)@6UMR@RD`%@!khk51nLi%1 zJEB(v3KuFsFBJ5u^1zb?c{?06rsZvS!08Zkat7_Lpxs@#Kq2*R0h|2^-{OF+x^g!< zB--|5@4O;Mjc+QAa6HSZu9V*4`8{Bx=o;*ss$M(}+MiU0Q0_iexB_Dza(TAGQN63N zoO0EemVZ)t1>d)bUKuccy;ec~QCEs@8=x>o(EbcOmE`IR)$u~mE|)+WQxss8d%pS~ z%(F&_=Uu4CU!cf4?ec7AFV>9iN!`^M-DT{F_1x~FIn&zub^uNp;DzWOA?;aM7|=fP zQkMb#o5NzOBQ|KS?OV-E-Rgfb^Wy(JO3?06NAOkO$wr7NT!~G4)aBU~u(8S4i(VC= zreiaWC(Dp`R^qN3)Y+xzdnYP^S3~vd#bUWLtVQY(!4Q!_*iJcMZ zzDC(R2vxUvGHL+4puM5C27B3~Mx`x(q*DHr>dGiDt1YGU|Kpy0Y86tV|E{N=i65|4 z#qua;V)TA?4i-5=_a~mnE5{DTRC<;l8t0vOHVy0;G-wZ~-PE}H0ru#X=;fg`77vn} ztUOH$m!k?dU7mwjIrT29c|~lnkrKA~R}y7dc3JCq?E_uIn2UeS2|a@`-ZkyN7S0W`TuIev?y-uh{rug zS=zUhw94JLQE+4o+B2eGrGw+^uxW@#P0*fc-tfg|eaL1p+5l~F6@L`T$m4x!WmvWB9&RJ+ZVV`?j;VZ$sTTiu<-pdKo1XCY2r)w0G4S;y8nN z&+6_~M(HN(-VVjj-z(w132o?Vf1A zo)9so1M*2t!F(KjHc)t4S$B4F*l^lUl4?wepC~bkTw6t(tt?%GJ_*`CEj-IEL!N)s z8h#diE>L()J`4+Y3*nM^;BDe$cr$9+;=Sqpat; znjtrj4Rk@vqKF-&!jHaS-0`gAbMxT=(+39gyA-;;uA+l4V|%Gj()PlWg_qbYqGM9j z3*~og>tDb$#0X#}L>UfUgb|wlQ)Cuu+?&sAu*}0eQS4x^oA@gO)?Q zzT^&K!$tc3#c*0-2eaY+XGj`eJ=0nBhbSXg$H;gvls$+@w^u(?x<<_%jsY;v7ci`0 zmB(1r9%$Oz0r^%yzM=JP?w6|TNSMM~Si8+GPx+u4H44u~M+WI>P4^aS@Yxb0AHyPV zEA3o?0>`qaB7^wl|B|OtP`j(Bn2;+fUQyt_F7^&{3AwJSXvzW?-cWW*aqY%o0G~a` zCORH>)5}!H(0DL`J&5vE4BD!LOarRS?`kvBF7bFp0h)+7@(y$PzXY0u0SM?Dg`qlz zt_}`BeaoJRtd1Jv!4#HBotn1_WuJ=YqN9Q|OKqp(7w}+T9AGLZcRKTk2o^@6!UvoT zksUWz%GJPTq%$V>d**W^5aPq6BQscPwUX*vpQ;McOgzodtE&%xz(X|reRu+V zA)R3KeyYslp8IJMvsn6wAUpeRYe=)hGd`eXoTFt_AO5IjtcHx*U~|>MLb68{i)n52 zd2IBEAQG~qc8BLd@P^J0k5Rk%S~m6J0wr5@mJM^n>kIiXF?R-)Zul9`RDVc$u@HBo zpGZ`@U@1E~LK5IO#lN*iR~~jUg_^qv&b~X8xFu|ehn2faahE3Ic|>_;8GA+@2SZ#b zr@gH11^%W%nWyhjfU03D!o!MdT^(KkSP2j6!qvE2{W0a)BKE9`wT3ou5isyzzczQ6-D_kOCo274Nyf6*H`73=V~10~<{y8M%U0S2`J33t)0>g?D`M&B7^!U5y6`P{6J$tvAZAB(~6l&O!Ruse6u#|lFx ze{kfrmY}K z8~q_|^bO>vr1~8XYzob$uyG&O{C9AdZDua}cg2+Bd?peM0mA@y=~@l4_wr0-|4lr?UtF@wtMH+ zA!}3{HMiT#c*VZpD{&vsP|2(7iwa)DD&A{0*kgRKhm9j2)aR&XHrSJVFt_nwF0;tz zdE~Rkkx!dN){Hy~JJWnYlFLE=eVjK>TP?;*cZ|AA(aV|e69Bvh3C5A* z%p#}p$jN3dv$)F)Gnb#>qE>sJVN*6%CjO&Y_zIq3slG238_%fFY_N5Fu(igKzvy$U zHXCdkA8d>9V4KV$_wdM_#*sVBA`c-_E#`hRm*af!BVjIlul>bcPMWz~>ShWj= zN69P7ik>qY`Zgc>rrDmg+y4!V<~y^BPrGF3v^{CI_ zgnL~Z{R#3@j*_SGKwXa~!^V9>^M9VZJZt7sm#2OKz`{{d(<~;I$He%;uBVZTD)E{{ zCi6(Yab&z%WRORu8b`it7TJtPHZgN~le;uGb7>71wc79aj8w^+O5?q47T$?x=%DY5 z_Qo@6Yc|;Xe6Sqj$Zq-^UCjo|<%4}#|us>K{&<}#cQJ~YgQ z@3m3fWrUf_H{4}H39B}aZ91JQX`!s>ShJyL@}Z}j?OD5hYFISinfWo=QPL|$JW4XO z%{zd*6vXI`l0Ifp!+6x-7=xqa9c}cl$WJ*+#^Qmx9;3p>ZK?TBZRi(JDaSDU$P;4Z(Jx%>eawc5YO z7#$_8l*Zd^7QUZn*rV@@UB)x|(`>Mle6VB2kw^474w(&hkq>sxc(5~Ok=J?THRH%D zW|6lMsTT95nM+hXZLitune4T@xyv19E>*Zo#d_weR=%FmQPNsj(Q;-(Kgx%Gh=qs0 z!C`yWZhs&wn(xei>TA=xT3?)ATW#~+<}Nqu>yDCt&7#W0Y6C~a8enzSM!$#rl%u2q z9;oY4E>@)JqWRy)T`HNmJj_!+5F2)s+;0{m@fb&J*iq76so-N~kc){znnl*; zku{AYpEry2@yHj=TpDnf`erT-;i6VMG1jOlyD1Y-Fbi+OGXzoQu+PxajAxW$HdqTj z*z3lTujz9%GaD?E57x?fuy@QNJMqX4#*yvKBC`>x7PG6F%Ljb$?qM!`uYJN@J~DIZ z%U$wIShe14)9F-64`oGj&4wPvhaPOUXYKZZVbOeNe%(OZ@uM4voA*O)^M1=+CN|Ku z%y_e?={#ym1B0Wamp1w=@>7nId3d0%$DFWndu#qbbC(5XF3Wl9B>)yw$s)6uwLGS% zLD*5!Q>p(dv&bzxa-(tNdb7x#JaW5n&f(3|!P|pK4%qlzgsC z{DfKfHJ;(JzAr8s&*;3_V754|4{sSq-q7c`ZZ_E6e6Ty>3>PyhPV9BwU6pubdE>}( zW|7qpsTT7-GnYsB;17nm@V(~bE{~bHJi}d{iZfre=s2UJq@S{)ZnL55@S$t5@NiYa z_N?7rBP^QNt~rlx7UnV#fy(~Q;4UrVbVtb>W>J|us+AGeC~fo(B&=n0AS%L>0uU=$76ECduXsy!B5R12lB{%#*ux^BERI3!;B+`m_?4^ zkt5AqCUTc?W-imsdVN-ssO#EB3@VPw0Y<*w+U_7H4W`ix^gB2P_F4X5(U^dt< ze6Ur8AtwV7P$?PYB9H%x$NYFZx3_fdu<g1a0oVbu;B9wif% z6+LJ+^hG}OIkP=$x1R}%<~y@;ymmFH5HFt8-)fupLGE&YyzVHu&n)V39`#7P!3j4@ z8{JKQ%284s57hOD4jXs2=KmabdB)784o_VRz`{{d!z`vgkMYHaUC1UY_4k-XCh^Dw zeFczSl-_ zmoLp+CUKYXC9K-lY}4u9;QXYl=oqu1XYiq?neAD-eM(p~-&+)L?V9)Tuo-!UR+AQ(~9$CXU z@;S3eFCx`q)-`j9<%7qBx$wP~z+D=cxukKImrGc+h6zST$*;_s|BVfsMVN>oTFk>{E~ok6C&FC#UOUfS&X~De=PuVuShXvLN6Btw zMK75R9qHGuP&U88QNs4D-Tq%#G~byuc(m*nFJAi)sO;|-xl3)o?&?#^EUG?_@)=>> z&_<6ZKP6Q%9;oZ#4;%NU=AX)48kxB?<*6G3SU5@oW-)K_nCAYl>*)cdg0GrIw&9U2 zjUzM6B0KWPEaS*_W|7@^WEV4+54cNrGnZVrsMY?&Z=_0YD--W&7T%v{=&SFG&y8o4 zXExZEe6V50kwf%32AK^ujt@4*c(74sk&}7kH^z|@%_3(YQZ42*GnYAh@E^il_+DGU zUFMp(EaxsuN?5f;Y}4u9;6&ml^6mDY&4&Js552~0&)V%pVbOeN#wThA(MyTqQE~^; zD*L+;cS%ar9VLFVs34C@O*A;+%4wsglb@36bv#hl zCGVKUbmB1`62p#?!^)0oZx-2uM`jyGzGoKsDUa-F9QmPHWIm7VW#-bKyYw}4`2sF# zwTC1c9VHc&#v5c7{x#1qTHhBVjb}8%Y_KVOuy2hcC+TxcFdJ+(A8e-aVBecXF65E( zjU(rpMJ`38TFgaeF01(9%fnpwUR%puip*So=PsK{ShWpo)9H?q`;--3XEyX6KJ-qr zJ!`k`2#e-BvtEjJlz3CbqokU)c@wxxgB0CS5^EOKh({%*7#t;!YNH3pPdQ4O;(@vz zjl;%$O!IHfU7DG>Wbo8204y9OZ|`AIu36*1F0J5H4!9`=uBiB~GRB`kIA*#WM`o_r);d84WQTY$6|QoN?q> zeU8y)gH7jyO)(zqJG00idE_kP$eCu53lXUnbH16&5KtLn*Vj~a?Q-emZr_=7J!AL7fdB1VweP)r5^T zES`D>fQ6%Ex>?LmJZ4^a57k#H_@i0mavr(FIC7C$CHy8T7e$|wyd0xe_J0^0%rtlJz93up2qLmVRB#D z_Vanw92X++KRT zkL&^RKS-}1!ej789;Vlis5a`TYRep>=Z}*;p;-2t8wvxq%ucN`+X&~`Lc@A3FsYY4 zVi^`M^SvBpaqQ}EfM~`RCt^v!X7KFFfURYA=b9ON%5b|_O<>^(xWZZW37fRe4d2iIcQTC`c;B4KVR+h$5Ru-?~|1$P68{q+9BNzP6 ziZe>zL`Gf4V%xFUS7@=X(qjLk7BS*F*?)O4PixbqUxT3(!G6-TZf8S^Pm{1moWmd? zWLif@-irmkB+l3#c|qGYG*3m$D|5VteUa0tt5!5V3?^s~s@;7@Q0?wJv6Il<5#@tQ z7e`hgTT!)9m0(#HR#t6974`Xu`&1iQl^)+uwi-SE0NDp&S^Psmbr(EL_7QshQL>NG z^N*8t1n&bE>(bjHh2peg=2 zB(q~?%k0b+U0QW$5$u}TIXk;!YF4X|yU%rP)5><~;sdrjtKL1xIn?=`bErdA<*FM()*Kyast}ms0X{Ypqv`ETjzo06zN={z6E9G(>y&d_E&mH|80~`Y#!yO|W z;~WzmlN{eVrZ}cKzIV)W%yBGqEOIPyta21NesgSh>~NfL{Oc&rbHI7fdB}O#dCqwr zIfuALy2iVvyOy{%xHh^ryMA|V1;cibFpfj6qhLAdI^{a;`pb3JbmS#3klu9VOM|2@rLUxs(r9UnG*8^~DbiGFnlxRSAr=-86v(kC#f^<>3D*Y|} zBVCvNm2OJ6r2nMbQg8R??mq6m?gDo|cYpT)_dxd`_h9!B_fYpR_ZRLj-6PyzxgX3u zYPZ=Ipe8>#7N9CWIex}%A#NApcCk{W#g3(@)iT^J$L$K-uEgys+^$wCxZ3dx>bM5C zYjOK4Zhyn=I^3?u?FQU##O)@>7{_MZ+v1q-_#J**@ys?n^9P>Uj%Rk@nLqK&PCT;< z&+NuCd%(39`S#(J{dna7UO9-@4&l|qc8m;dKpOe>;vy|2U3H*B!^Ce;voA8;%pwO~*;;mgAK4 zpX0Q2+wqr_>pUa%a-NlXJI_gZ&ht{f^Mdrb^P<$pc}eQ)yet(suSorzSEc^WYtjJc z-_k(mKhhxQb!o8kUulT*hBVZ9QyS)6;rs$$!=1OJFP;BMBb>LTubjE=kg7-znFtn+jC*Umofan8Q(@y-JG1ZO|@L}!2ZB^oIKOhwa*lM*c8+q-agKKX=p5so>m2Kz z=lt3|-#N~`z&YOilXHT5p>v}9XXhk$q4OK}B8<5h<1E2AOEJzejI$i$tiU)co!`1w zVVu<%rwHTxf^pVhoV6I|SB&$U^E>xC=VbSK=M?t_jI$BrY{EF3G0ql@^E<}bigC6% zr@H^ZINLGK4vh0B#@UH+c43^|7-x@jntQKvx_h7Vd-s0l4EF)&O!q;IcgXpJ`>=DC z`v~qI#n&->9mm%Re4WJCDSVyA*I)QLgRisrI_I42KJT34zTo`PebG7BeF)Zof>)nG~8{C6k z8{I=(o7_WPo87})Tijo`es>RdZFPU?+U6eNn(6t<^@C@mYnEq}Yqn>!YmR4(>qpO6 z*Idunu6dquuKAwvt_7Y6uAe*;T?;*vTt9ohaTR*LbuIFI=UVKU>{{ZP;@a$=>e}L; z=K9?~-L=*Ky=$9)hU*XiOxJe*53U{lS*}0*vt2v=b6mUpKe~4N=eqXz=ehR!=ezd# z7r6HOe{vo0FLWLB|Li*CFLWLDFLE96FLoXEFL537FLfRFFLRynFL#~vuW+66uXLUE zuX6q6U+p^MFLIsr|Kd95U*kIOU+cQy|J8NT|C{TQf1T^Hf4%F9e}ikYccW|A6PsLL zJh9m|{E02DKNEjwssU>!4>pz7Dvqcn`X+dJnm_B_DPj^B!>>_a1d!^B!~k?LF@L$9n=_CtZIepK@(a zKJ7Z0{Fm!g@)_6Z0T$>&^Glh3=3BwcVFO}gkhmUPMWi|?{)jqi%V;Fex3oselWw^4rCrIN zOS_Z%NPCj|N_&$Fq1@(a=}_`8>2UHF z(vjrh($VBErDMq>@b#5+DS4!HIeC1w5{O`=~%;= z((#5rNSBgkN&hC#mTn}^kxnN4D4j~0E1gc7C!I^0FP%?XAYD%SNxG1#X?>mFr2p!ylcv;OFAZ{RkcK!mO2ZtRq&0OmOT!&oq_d9Sr7s;@r4f#8 z(pQc@q%(E4OCudSq_cJYlx`;Plx`*O!q;x;*E)No(T=^+NcTQzjbp!b$bSHJJBVxD zA!(WWFs^tR(|S2h>-EmRq+^aV(l?H?Sch}cw~q6e z-v#(w#8vZ>wAOK1`n>KH={v_&)Z>~o#ql@B_y=FtrQ_az!F)rS>bNQW?71bK@&6}n zcifgvIda|89lhK$9KCT(&2#_Y$al|jeC{6O=;Pk!@9Q3ktL=P8KU{bFyBFb_+Z$Ki z^GSo;>v84XhHLLCTzz->hq;${zHskN9`2s&_!2QA+!y>`xv%&~B6gI!Pu+)X_vhaA zu+3JX0edU?TvnTf??u^f--g1mHE5gJGUvG(HHO-3_ziXJndjPc%WR#~BNGA$zj6-G z*gs`=h5w#woz>CZww>}^1a2ekdCXP#Pw{EjQF$&Bw~_YKRRsq;P<*mFD^Eu$K6i(^ zs6Lq=D9(2a!Vc})A03rWzKdL=@i4|knV`a=Wa}_Fbwt5$1=I%B)?pI%anBx$v%_aknn*y0z@&NWwGOj;B8G)UDnk zEvt36F4%2acvW-P>e!X;G_2O>c{YE}c4c@0^wMVT)H2TBLXB(lNV5T2tJu zS^K$KFFsexTeD`37Ok>6w`kZUJEys)uJTTzb*<;xbnNJI+z&FDz4K|4)zK!m{l9-# z(nWpy(V}&?54+}cX~EvKx5&Y5M(51;pKEQC+jPmc$!}!YX5{KTOi%{x6EmY`(6GYzFFdscoT)8+x$Nq zy7(=b@;*#X&VHfRi*-GiVBq{SLV~SQ(xW%3*0v9S1xry24P52n z+=cJi2BDoFc=cW!Ru4SQj;sfA%itX*>@&*kv+8qqDbH1&=J~&#g|=>4om+S8-Ue?a zX&tj$w$04WY1#VS=i1vU+7}LaZ}_tVe{OrI+O3&apK{i&9A`a)+9}HLH4aUVs{ee> zx>`-IHu`Jix`@gzSs%VtRu^ULv%3O&s?~O+e)I6^p0?>rKdt3vd8-9nccc6 zW549cy!J_pcF#oiXjk^*Q<>W;`_n9wv$EtUqnF=OuAr@SDE9K=+6$_7YSg~+%E13T zdgw{QM$YKirFBPT^k#XN-;fUVzP<16lT%V39JDLK_Q)$wy!28=LW7JNH4*}i1MzVU z6B;zI^}fRvWw%d!!j^lBeF$i)yr-Ha3Vu|y#+LZ(;{(sM?%A!yxZ}_Cd++y4!^@Xv zpRZ-aH4W6vcr`AySt2|6GCFtf$Ubn6ybGH-w`ygZ?FTpRteAwG*)g~vH>_y0zvZ!) zU);#1L}uk=c4C2uDWk+ZkC-_uX5K2?RA`9vpnXNVeSE-PetaM#Ci4R&tdG46yO`(x zgbDx1!n&`<%_|5i-@ammeOY6B`DKmOk5rXZ$_Kg>8L33F-!D9uMc!S6n}LYT?PhOS zF|yp(btC?)7x8yJ`^MCWq{jA?#`f16+uv?%|G06)FO4HMH;#DZm8kOTLI-b+Pp7)s z*dKLbNKu%{JT~wF{3_wx{V&^Wfrb?$BK~M>-_9r0<6o2EBu6iCL4 zQ&k~V*0#kL-zbPD+G$UmOHq!HjO?5YZQukR)*REpe^G5yc-GX08Ev|>M4$G)Gm5>I z%f5kAh`dpK1hlqUo!eyKiq(gG{tUOLkZ_TL7ayl=(CnOUS)JQuw%+`$OOe`Re~>SMW3 z`V9WVH@4gcSYzeI|Ee`>6iCM!OL!Rdu8^lqW@c9lZ^-*R9YR3Z0 z+CGUvk{(^M+GOxwoNUW|j;i`~U0c)4oV3hNe4uN9Tg7HJUdV{1%4prGYX<$AUbU8u zFv@Br=@PZOngtrYn%JaiTqanP)!f0998LU*wH-gkoh{8}s%1{yUN~1PPPfW{5 zY~C34TB6n~YPc{)cKfWh#f|_9O``3 zlSQdkAO14y9A&oZQK-E7w>oxuYJ%FF$?9T7rBE-mLzUWQWp-?nq5fiSwM=)w>oo8ta51~U@@-|)G z?~HbCiSMvQsD)+UmR+wTecl2ZGN?fQxb!&WXMfa8nWDq5)F=J*#;j~tP*&yX zaz1pC1|OdqOh_?kCsbE|aPU^BPRlr2SjLa=y$WH=Y*1kDibp=R5d!In$%#$S?wz{Q zdZcN4WTo16uQqDh2+Pbf@q=v{wPkujIyNBY!(WLFU5SKXT4P!Vd<#~c@ST3;Kw@uX z)V1cNC{zbcuUk`}@F!15nW(}cn;YK(Q%64@fM4;U5PASK)_lI=t%%D?XEYXj7lSLY z_WD|tBN+d3VnRAzIHaxBhz1zEd7T>GjJVX~V3W{=YN7=fsloBVU}|C<4jCL5I4f3Z z^-A*S=T_aXEeUIm&{3OeqZR~}IW!4q>DP2y}%Asntkp65=Q^JqiYFh^Too(sj{i$6k*$*V_QgW5&v%|Sh zEl)p_Y0G^>n^#$#SIDvcCM6CCv+LZw6Q3G8XZIpq)SvZi2~A#aoF2^h2p8@y_-*3qHT=4F2oLfP3rt20V$o}Snw5IUVRDnnUYa>$7o*OZC&s@hAv_(_yi zs|{Z0pw(}W`a)c@=6H4!&E_kCwQCpl{cQC@$S%@`L(2d?nbNoVgwD3OaOiT4Qudh(K2)uk=!C9~NS>uFsHj!i6yniijKXvW34*ZzT zs*pE8!pL`F)%YJgaa?%D16PGs8mBJ*h}G*Y)rNZ?F-h^!Tj{V?n$g>q(i(OTEa z0&X_V@)aQ$eyF2+@gVpV)OJM~q^(h1L$+^sb+od!Mf{)<&d|_|KOV#($KV-B1Lx$7XXV9e*wCd}a$o zm(UM2ym`LRcOA<64XzLpIeOFdxCFdm%%u;W%i30}eZhAbkGZTM)UB;)@4-P#JLHlW zDq=p;AX+FV1HJQUgO4ZGUZcaItnFX*8l+rhKyeOBsZ8)^YFfOTQ&es^P89wQ=8s$@@qyf4do|w=JAcvNyVZpv<6Wh3n=QO1vMTG zn7k*L+DVVoju^T=C}j+7@O&-f3N<6`ghp>9`ojg~MI18!a*3Cw+%*HFQ$duR1cQ0Uv~zRJ`Vsl1Ki>V$ViS=$PAvxZ&@P(OYhXyrv! zw7$`nAY@N+4co%lkx#xrE8dYXu^ZAr{WPC-Dpc4N7hH6?Eo*zn_~7E{`fEeYGtl56 zDF>*2QT@d=Vb|~O*)7|dUBw3~b$!LSWkQA@q+$G_&Is2=bw6vDNBlD_t-9Ei&}JFz zDv~X{VH?cW`eLH`;T$!m@=heQb)G?{AqrKrsLVr@=unMjjzLjE{PtWZpkZn3z9VBXFs*MTHuHADo)Q_;VHy&l-Fh*&g z9_o_eBat?WpcqS`lZ3;jP4{9UR}ZuJn)T>wLNn9bDD7Bh|7>HNk|D$Bs0f)5?a8vX z`KF?S@AL6mb%upsTtfz&pgAp6*EpDvo~XZAl(l^sK1N6dCsG;S6v_~~1FN76lavWA zP}3v^nx)}=X?mi+xSQ~;Z5zJ3fbW{y?yT@;ZZ3QH|Lwovj?tix63-`WN z86U(xa#!RNxpNp&`IVJz6@n4dJosaMBk{N?{*Ny7B*_assliIPAMmJujkXLXUbxUx zkXPWqpA78nV1Jsiw<9$Uf9=oaTjWvyfFEqgAMh(h<`u}i%p)(Mfhybve|Azy~nb3 z$NaJG10AU;${%d}-D<||$heI%jtox1!& zhwY=1!&)o(QQ#c*$Oj4MV-4p?hI1GY7s?^=V5RJX9fb!=#yUn=u-3570_!i2e2TCJ z&>>KrQT?T(I;EphkA-uD18WWEDsV1)?)1uKyz23kNt?GOtHPb$ zg8cdHa9p4qjyRGgxYcxULL)s!jIh=iqrvF*$}R%z6}q$B zIzE?y@7-oIasA&+2fVHoENgS-l|E zv6|6~j4x8gsWf{@m(1FTSYfTPHUVp6uN)xI z@c?B~F!yB!+89`ZI4lh4`UTKqm|SGHzNUl)TPmzknsUzsR%>DslzVFcY-9>9Ou4tE z%&^uncSPn6Ub#Ib7nOSley+9Gae%2v(apH^bs`*CYdGD2)0J36<=z#Gvx)T#mWwO* z%?bf-ec40+YmMN2ubFZ$PWAyMgSD3IV@&rWny#SSKSI4Xvvm(s?w?rA*b5myql|)b z|I8#~Z>t##kg<0~>)d(GxdO;sUIIz}mCIM%HR~|<=f^wgr!x?9S^9|v^ zTEm$NoXNx@D)-5{)I!@#BLY}!1V4aa1`&wLeMZRyvxorJ8o>e(%=5}W5`>`K=izYN z!VX8S+<(+jsY>T3s~F3HvD7Os_R57sA}IHzd_yk=fw-3nbxdm4uAmaZS}W0SU|Z{z zfAPwziA_}QYjsG!aNN~8IH8f&5hJWM#;su7;*~cMprG8h==e72sML~eBOF+3IJ<$f z(<|>F96`D7)Zy$f!P!GNu-0%60%t$52+DoGF0KaMW4ZE z?iGCnd4Dh|5vJU$_|#8wV6A0-5Sgp_RdVb@}mq6nx*uSC@(nYpvMz z0TSbry#ykv^%$hj6Fz76ngPWU5Ue$zBmnt+ay$VEI^D11iP!Te-*`(V99U~O0pO(i z{-f`kKW4JREqO^8L*=}q*h)mCXnxnZs4egnCiQ*KeAH#f`uCgp~; zmb(>lzvGkNru2d~e+P%)9tS?Mz~||2>qt};)7mOPM*wv2$?bh|TVfDYc?Z5_+k-&d zGi`NDs>JL>#eua}oE~7y@yXqMa#vy#Re6pMsT;@bs)tkC=6#}rwMO?D=sxkuJqb*qe1I;q+R1~h zX8Zyfhf+pCj}JvgBSAHs<_c?Vt|O6o1Z5WW_y}EUT;+?U#V8_xwMH-r1QUGnIG;S0 zI7B@@K|4yI#K+`-_6n!!dIVB%m!iRO z>zhefu>UJo9DeTQZRKZP@?w(YUNHvxyH`v>-T?#sogbs>Z`jgj?T@SlF>)VDENbt9 z7)^Wk(KD#0*8qZmEj`3gKnx}VQFjlHDabz zQbc+c0r|gXcXqOKyPMzF?C0_L>mxUJyYKRx_q=E3y}OrC)2`;ucQl$hLR)x8bDWl?WWaN=zWyiKCsxLSLXjkl>zyv>BS?`kU3sYAZb{*L9*bdzsdXV0Pm zMqBs*F95{+n#x=X!PnUH;hL`(=GwvFcih!)7ojaY%yPgit*QJ-VYvEwsfp!BGmE+% zub?Ps3y-oEC~Imet0)RrTdy&ptg=B_M^Vrg9%VC7Hc}40uHI;Nt1U5Gs9&^&_qzjr zw^6@*O})*|?@sC$ZQ=dygWo+hm0ziAuAbh5#qBh$r++n3XjRC5C(e(<`O%un;hM@J z>YuBnkFsfb7~c80amd7@)zT+uP|y}WDCfa-wx)8XrgDmM@pbfB6V4fidddu@rO5?K zhPLoz*FbiqrgDj5aW(W66V)X%i#lnqQxvp?NBJ8lcWNrPC<<3U-!Y-wvO&2=QP371 zZRou0-LWrxI-Lp`cpYa*ej|eS895AERFRn)xx4 zThz??rNNWbJKDl~FAeV{Ybj6FQi@XszFsa_i!K$Ym!HD>GqheVUNGA;lnrg+*{=2r8CTN{`{uiDf)K>nX&iR`8L2bQe{>Q|Dyt$y(u6PZ9L~+nM!wISr zs|3{10>M|$0d@NIy5e6wUsVb48eXK177(<~2%fBCS3&1HD@vWAb>{3TbhkL|E>}et zuhTF0sznw3v{R4Iz+)-uk*lOj*?4@`smB-Lv1}dXdFqs}rpwmRGwgYje=fsbq9I4? zEaW0^Jav>;DGpy(djN5Pgq?lU zw9arU1E*pg$oe{)=Af}EIO(D4II|hs64YD}0Z<<7#sI+RPo>PnzVEF1N4eBTfl!U9p zeQZKE00BRj5==~5);6ReLhCFzI!e@*qw2-A!9JJ1G+5_jKI!Zf=!&T-VnQ+?K;B=rkXr1A722Ll+ z!d2&;OrEuT&T{JUQ+Vt`J#rO#7kIQPy}Hr9qIK5SFW~tz>Y1<7KQp;TF6NgXUs3|J z&ItN|pjREGXB{Pna`2UUFMe4;z1|Z??vRCsebXeTVAj5r6|FPYpZ_YPKVd25z1uhn6KEUM(Fj_WD^5;?yL1OUcBkh6ZinL-Pn+4OB(}mpHCSZR12+c)lkhaaS}_35wKq zY_9Tt3>y<4svvc%GOq1fsGg)KXbX>05-3kaD#a-ZS9L#SLMd*8Qi`IWEj-HeKzWvO za25BnCa+rVmT}_kC3t&*dgH3?7vRmRWO|wQ5pCi7=z-T)saL+ze%0g_Bc5MA2-G{; z!h3%c-rtB+LLwEJGVoRQ8~D9N!?J-YI|N7ilZAv;*>b_0Z&6OPh3BjS&PtI=1q#Vm z*p-096?AzOO!)!e9;C!0ui;fG657Hb<*e85jW-2WW6H$+7G`4r3?$W;UzPn1^^De; z=MUhyd8E>eI_E3x=43fg|9(m{69x>{H(yrppclHr=hSr(0j_7WC+Fh>dZjX46BjfJ(jqXgR9<$)_6Y7zx zyg#w=nC;Z#XYkl9Qt3*a^3``YmSJ5@{<#eMoQ52&vyk@$PEMrq6~*Bz@Ekx4CShmy z#=j~UE0}~CQ$;uBA-++!Bk3s))~Pp5X^{FzNHXc zRXziY<3zGJva0-B6O~rk%yx>g2p9_^mG2{!d6a~!%onl={XGcyxirtjq-E`58X~mL zLbM8Od6CNUNM$Kyi4p*gbH{twjgR_g`pmm0`7dX2q3sWyb7F`DGOh@zZ`|%Kq5I~tlSr>1b7X9jS`@BMj%DmRqpxD zWaH@Z`DCLtVC6lu8m3x*6 z=@W*VX@cVtsVikf>x}U$Fn$rGd`1De%KZxy-)AN&Eo5I)9JJ1G`T(a_l+u&paFu&6 z6HZSXoW2wXtuvf~z!^YUxXOKi$+MQvgPeLC29HCiN3L=o0*_Xu*Kpcbw9fiE8lFc| z&wS-R(&QSsm|uR3p#*515ljWayepx}~J`qQjk%fj;?&Aw)okm&F zI%Ay+*4a_YObW_Z?z8=i!@QZMd;#uvSqf?w)B|z(p;8)wqJ>S`G>I|(jXZz9Jy|lYr<-Qm3UQfo|uW~=&)Z<}z zJVZTmmHQzZk4Kz(JPD5{qLgFQDPOstU>SDIavMS+t6=N9JJ1G?g8g+lyaNmaFzRA z6V7cLoPQ_|T4y+qfb)>D@Rj>RlWQ(*T+#H44ABk=ibTgMfzjG^3}3kiM*B}yj^Hs$ zfYw=UW-;WgaM}-W#KCK zY9`NGKG$&Su{J!`q#n7-y(Try8d6Zca!&;oR~+Uw zH029{Rx5YBhBu{HXbXjvr&sP7z-mjGxXQgP0Ctd4!mo1wh!>DGOh@XJc^olAJMC?)y{%yoP^D3D7zt_&nO~ zo_oHtFQ_xL&Yb0-yI;}na+Uj6i1$7+?tYbf52qe`!(%S>$W`vSHXi#p^*9h72Sh9V zs8hajAHXuKpUFR$VS{MM(K-wHNZ<^QR)$g>zH%Q9h@B+tta2Y(FxDuFh1MC?Bw$U5 zR>n~*u5zDXq8ewS(l+$T6bG#{oEgCRHd>iRak$F;TNBPS8=RRG2dy)ldBB-NS@_C* zj>$EbHuEU~T4w}{K(LS!@Rj?*f(aH=0<_Ku@<6aWT3JdVxXOJw7RQ5Rab%VIQWKR{ z>8x~$u@M;Sqm{MM${I?-RqpHAgkB2*elD#sF=<)5iG~QRvk>h9+m2{uTePy3vhkJs z4inNghP%}S$0gD)lo72n#)DwoAFb@AfL!Ii-^91qM5Tr75XC|34Ce%Jjzud+C=OS- zA2Z<`vBCMB;-Gbg^9OKFQx>jrKW*}?&w9W|r2Emxf>tzYQ$KYw>Lv z#oI6UI4LFkD)$Q1Gg@b!tHE;>uTqIR=PUOrUi}72B@+jjepl;eyoOh&IB1>W)B;X8 zW#KFLa173Uk~7B2{een=*YMhu0If5ENUvSxp6@J*Iz#KsSuDEirQPK!cQ4}ofQ-9e ze4CiCuWO$Xf z6o;$aGfX&bZE)IC9JJ1GJ^@Z9W#KFLOp|LaZ8}o|w9W`V1wj`|z*p{F3MS}A3D7zt z_!*91XsC#iN)~|SsYpA{<(=tt8{XlV)O?_U$4^JtK?D=u5$0oCUkEQ@N+5G z#H3~I02(5+&O$T-Y{R_D5U(&$aKc#e%xywo{gxyQ!z zp}(Q(HF1FHv|2agH9Vf;pmm0m1e`?5!dLEzG5vZCBspWO+y{yHW#L@BhWjW1T4w}} zV(cpSd}pcD8Cqw~-a&Vp(C%`TdlSTa5E*yB%KcrZ9^Z$@_ozp%a(~ap;|ESXwuZ-+ zG0KP3DPOs_WEu9M$v>B2=``eMorSzTa6XDr+EE<7a{mYrr@6|#UBOr#C>C00SY3dX z6{CDYvAD`T%S82wiAvkhyHXsq&Tzg2&gU^ocZ$PR?w^}*y4&DOc6oRYVhhT9WN)|^}xeqc? zX_d}!rx+7}F)l_K6QhixBwXb_j!oz>AmHcHC=-*GwG(NG&^imz46uD0qfCoYrcgG% za{tzZG>zd-F~M<(G?Ox-b;h^=jPqlZxfGDA+~=G4=9;LqkS(M*Xr19K1J05dWiiF! zD)%KOoW(Xc%P9_8XE>{Yvy!rKmHSGQXDy%CIQ6(59@kQjT;;wN9<55R4YaRlo%MAK zJa3|&`O1Bh$u)8@zx>!r3D7zt*bRbTVw9aR%67`ZSMI;?%L*#@oj5X*EHvz%`}Tra z_fS@}&RCCt^|u)1AO+WceARCj{L~R~Tb?R{@Jbss; zOs7tpl0e{}jLfM>ynY9-i$(a$EuJ^sL;#w_Y6$QeK8uC`t+Nm;0MPsdWiAD3t^-vi zK=T1HnE(y;kMcafR-dEiz!eG4rqx1XmPUxdW@CS5o&=zWN z7*;?c9;zp5+bFkXxf1*39w1ZEZ_5fybm;L(czirjDMFp{Th`<7dX#QiMN9;sIjV*L zui-@#wOt#nvk;U5(9?-Z2@1q-Sx*CE7u~W-6bw|F0-<#V^a6m&Br4BQAb!g#V*q-t zV4xQ%5L#zIuL0;4O2chgub2R|Ez3haqjlz4hG&s_=C&-6_smwUVCosIGtY0qb7-RS zI(5!%S)p*QZ&|P7{c$o+{I;xeP5~+bphBWjo&s=NRs{n%^E zR&@hFRU3eCrvP;TP>Xu!wyaw4Xjq%r;Mb*tkJj1X$G~%Rq7q4+b6Zw)qP}HC@)&H( zigoI~0o*4fD)p#)Zp%tY#J^-kHU_q3)w97!`tKNFf+Sn=kVA) zQTdcQ<+rTv@OqtYS)ZB+KyzIU0bawupdmo(ECjg#>XE2?O@a6=s|O&?&@Johf`NKb zAhgbaz5!7GM5QkU;&)|LcpgbT zb6eI(-ZNXZ#!$~_oq3)F&l3`ranw1tWlex{eajk$_jkxV@!PT{I|cX-0MiqdsT6?Q zvZfmVrrH3^a0)OF0CN(RSrmZVvgQ~7X4wGDcM9+W02Wa1+?KTf9t~>~8~jCd@XJ#vrqpSSV& zf>V#L!Q(4Q%1hKK|49E8mSHcM{Bs%Rp&>`>Eaa~PCpbxwC=UNfKNt{Kxkvg^!B}rl zEVRzBDgdi|l2VRhagX%No2bf}sI+RJBE>=L3?~dY)smDd6o-4HU(JM5#RjJa#X;)~ zrw(vxQ5OD@el3%0E^X>k0<_Kuyda381pFiYsDcS%C;?h$1c@N1pQO~I5ZojE`dA$M zkj0Tb(ywQt(r!sNaEj3c7^z80!z3k{l5mgoQ`v-W2m*dCC7YPEtZhm|gw|PzJ_Oqb zNlNo1r5R=8AL)N!LTb)%o0;IaL~219(K=(y0At%EC7l9tkM!G`_|i>OTF5@4IB1>W zd;*-zB&7qz;U4K{ns7SU;B=-qXr1AF3Y;#Kg?psm#pGGb=Wb3tegTi4QIFgs{mGLk^a{v*T}{E@}nmuK?Qzjwi`11T$7XRM>ZIwDCKMnU;U`Xl^{!@Oapd;xS%QZAC$@X-_t?SI8u zpX76gs{bJ4pFlcKdAL7*aURYGk?PH_YQIRmqAk4FYw&s{Nx4KF^A-CQww_%wF@R@? zS})@@{5nNJTX>W^K)FRZ_-g$Y24ob;6JxbLTJ?_C@VnGI+QNIkZ(FJ7J9DPZxn0#~DRKllS|Di2>n4bkoX`fP(qVSb@X#fl%p=Q4(SF&KF=O_}|!Xv!`q?dfk z3lxc~%3m@Oy1Or9#DFQ{|Dsst$BG{mWP!zO_lofTHucU|;%^u1y%P0~w(#C-zc8VHd-rLIq@O)0nvJd#b?y711=nc5~EEknIDG-wMSng-xX@G0>=C603O)pvpk zC!V3knZUTjNuqpc3(waCe5pRAA%){A?^F|8LlY6bSfMCQouGUGl;%FA8Aai$?&cQ^$OTJ&~K$$2z0dL4-3!lmG?zL;TX;tc(9QX@n_PuGA2FUo#@VmJUg*Tz zkMOpLdgChWMK<1+IPta;-d6aOWz->GVXt7>w9Mq2%cfN{%xDWA<_$nu=Tm;7D13#z z4gk|hs9A;mQ^80ZDH7VkBkcgvHlMPUB5@V=HWSfS6Opzl@1!Vb3y-o7D0_U$uM~x= zu=kiyezif_Pf^eo9_27l4p9!i!aihj%caQ?>K$$2z5fpH$EkO|!aiQG_mk8++QNH3 z5ASDv${7m4RoG{-=*=gK9;>j=n25A0<$@E0>p-~bQ!e|IzbFM)VP9pF_ASd}s^L7nB^U1SBi2WbN(+ zS78Sv`-jSfBmCN~g{nxhb~6EO;ZceMrD(G91V!O0?4l-=Cu~qkP!zO;AVEbSxO!uRoIczuz2U8Q`Q^ha)H~Y3 zdk=wkIav{t6%S?LD{MKLTQ*Q(i#YNFSx8ug?J1b^b;^mh@SGLESw2}QM4&$ECVba~|P8-)lKRWj!vRC+A<6uX2g^ zOS^-DUVb7lIOhj^>(uqs`qHkaeE}q@Z~5GB5++=~fFM@6n5 zyU9~wdZ|&Ka%7Ne-cBYRtQ}gMNY)9tYR|r(u-DDI3grD#SP39&Zwc}f=;c*{d__G& zOh#Cr)`szl`in1Wkkrh}JBRoB=+$_NutbL6L8_^5qf&!H;m_xe4!=dlG$!wdkPnhIw?+K2p6ddVJ*O|Ev9aEyI~JLXmyO$xVNJ&jTq$`I!i!+A z0X9xiZ)IQV>Uek}QPeO?UlG33X{C_9nszIps3!Q8|-| z6NC)srw}KF;G9ZKU~hzpX~e|;g|oGeXTdoGMogTua8Rvk$<|tksy1gX41jPB8d4~! zpD_`)qrxqhqP&@+Uhw1iJWcLbW5nEDBIUgayZS^- z2(O0OrWsm73~48gD_kff;ASb#hF4JEF2~!@>gwASL?=H0hIJ_{Oclt3K*)ZY)+O^% z2&zF^TUB_n8X(h*tRhAZ8y8R8{)9pcw5y>(X@A1o&~WwW+W)&9*jSfuV*{~KQ?;=X zZ*g*y){sAWVi7Y4Y{3~yuoZ8ytZ2a_DHBpLg)A*Npk{Dw#FD&m*Mm3&6l|B9@ylcLmOS-%s< zLn2f1>L7zwsu@qxaX8X3cbJTAV2Qd7>>^T8MkyCInUQjZnNcHT(uW*ZNtde_t)A82 zXN2=#p@n8Qn!KnKNQEWP-DnT77oCzow9M3e<2`B&vPvF=H0cUm%_CG_hcw5q2#F&FI?izg zA_QR#sPm&lSo2|=dN6a$%F%Jn5wsz3ra(uJ6$?wEPX2%(h`Bg~I#;UUqnhW5%Kv4-W*duI{OGH9{^oLl81kl&$hq|K{}ac;&<-Pq-PV^@f=z)GG5^iY@D zQ0r!|Lp@Yuyp6YcUXq~N2B{7G9pa2kLGrOMQ}7-Pfb(xO>J%iOF$MQy3N}nplGzlz zkK=g_fve3wzkJSlOiimMYM&nv(PVYf7?UczDb`g@;$KK$Z!;97`IZec8?nH)p;@9+ zAQVP``v?ZqZl@Nq+fTUFZa;=b?Kb(0Zf{1no2MwvQj~XC&!5ypi)u|Vtto*fubDb} zH8NGCr*K5gFKu`}KxefRCG$n~eUjdN3hPAkyc9%2TBcBgeo~kr<76`TOA|xQ)g|f^ zs`v~!)DjruWTNFUY|>d&d4V}!|ii0U|4d{F&umz2XXBIC-_i? zdEh|lhXnv+@mdD$Ww3LwD1>VZ3jGHzk z^*cAelY8DdZxfekNVeYvZJBs2>~qy(1?rJr36Pnjov3Kk(8{?Ng%b6g+yf{p^XJ~?-%+i5D0IjqEy4%&@a@t)rp!m`@W>99EL+7AEr=aurgP6 z;p+XQfZ&}}`&ffWSl>n?5h<(QF#8ZOIGKO1EGL|J(hic;CHZ!%xRzS_aMt8S$i?(< zwU_Fh2S}ABv8V+p%*(G3KpnX@0s1f{}v{kc^k=G#}Xp}S-zbMsJ zjfcWGJVg-c|L1J`8jFKwD-3U;7D?3ddz#;kh!;o~LN%!iEOeFOyF%hbbt`~1sx248Tr28g(lopRpAk##WS@qV!<BAF{TqdGT7*6y|D`*`ZU5&grgxLAv!9b?ZB+oa$;1KDbnx zU;OO8q{|;6{L8b;|B+2t=pHz~nw@r+I~G{$;KCr=8{< zrg_s^^SYhp1EzV;P9&g)KCqAMM2bR0i}vF+Tx~k1r?=_Sv6W$rsvzcWcaa)=Ua*mP zmU$>u!;}|K*RYIY2|Hu2GGi}UYrbIiQO3^L>&%#JZA`S&e4A;Ov(|jmPO~aBwP04V z6A5R=tNV$txmK5n)Up$aXCko$jGDIwCS9lQej^&Ej%bvf=|;?SGEujhvu<~ipEk>f zHcY#fpGX6J@^)Y%ADM@@=q{%_-KJlk7BSGtC)xA`6(vJUfwP z5YeLjqh(Sis~ultr@oGPSYytMRn|Sqvop4x8QW^Dx!LSvqn)vR%-C*gW53vG9%Y)p zS!*7&(>w)DEtn_lM9wkeXZ%FiT>FcOT(A?l%|vb#FlyHdL`Uqg?m@G9!%xbrQ}U~(8l9+ zKfBFz`L~%!IXjVR%yne|b4y7@JDoaAr)Id{ej2D&B{l3c4ednUVL4F6*bwX6E0u_3quS z&3CVjK6xK8kq5O+OUXZWT1D#Uh6CzYV0F~37o~FQQt~uDXyZ}54o{P*%RkFRO4*6L z#9WuHJ+M9Zwy1<^>nD9<>wsgNdB76S)KtE!uxZSS=;J)sCOHQ@_JJ+%)IKb?Y8owKL|5 z)bsG6wdQ@Zk9&5;o@B-zi?kffph!N~S$36Tnon747Pr$Z15GWM&)SK+%#6R_C&K2M zz(iiP6M2h?yb)L4uHdK5V)qWyZtN#A5Q^&j zPGcg?BTY+5Gdrzxrq$94YpiblBPyr5%ESk4Jlgx&9jD7@Gm%g1L_TM(y8)P6O1j$V z3RGnQwqx!mkyshzRS%-9BNW9#fRcQMWF)|x-tY3_rj z7R=ptBEK=?2mD0XTszK0j@XHuXCi+TFlwhQmy)UKh@P}FeVv)UVmD{q?n{2!Y-W~@ z(szTWqxhBjTYd7rz(k&pGA$*~+G)MUv|f&~Sm74v)@3TEE+wJ(pp8d}pWTJJe0e7F zmYqmd=DHGqxuv9nolb406CUNak|=>lh&I-=w4 zOwVJcXWPwLw|l0aHk+A0G3`};B6<4c-ONNbn1^$noz@Pf^|KY$I^FtiDyJ?b2k=1~ zkG+0&*X!~}n8+bJkyFg|3ICK8C-^`fnolAqNPjkPn~l$lN?>i!ovWX`(X4gIuPI(@{n+xm&@fTB9TKVc#r z&BNK=PU};qm2HK!SGWEJl~Y~yzz1zSzVfrXPnYk*L~`v!1~JzI0L)b-{p@r`F`eQ5 zIkZ!a;7~iw$xL&CwdOcG&6!N|TWif}cAE2<<{Ueb#Y|+OoybavXwhD7nUn|BjxV)S z-^4tuH|ND#>mIGKGxiHJw!>O;o7u-!J7b5KvHjM@_S$Lw&NPo%YaX%FJPS=Nn5XST zE;8fi{Y2PYyUIi^*@@g^B6kWHwOf`;$q{u#Z`hd*^y)j5%WJWekU8si|LdpCW@ZJZ zt$6v(>o^qE`CXlfRPma2pGtOGwV77971n*-dK8sYUB%&pHXdF-yAO2vL?#k%C(?+y zP6jZylqA{dyvKCj@%rtjzpD{!VyD@fX|}M|OtaH$&oncvHQU;0c4nHHb|T%FNEbVi z9EfPq{?cnzl{`{A{<)p{0Op~uIWKx!_bAuS*hpq5*vyVY`#wIaiBA`IuH>jKvC9T(_P|7&f_Z+3Im?LO$I&1UAf1brzPo#1NKrla9kFa*`_@B~*o z?y#&+>ZwrGf;TC_)xMqKw^l-Qky*_8cL}c628l|l?df)U3z^=0Uhh>^Z?2u*a;CS$ zN^h~9-WsO2(oSRp6Ip8~vJE0yK(-{fGP`6O`m236Ws{#~q#mc;OmmmD<_S{U3~)RFJFmn_X#_tznIbmC}p;2-`A{E>aXC+V7h^p2%h6d#ddsc6z0m-qXBZ168kt zo!*N~uZ)%6b9Qq`Qx~xOB{6yIB#WLg32q&M7k#%r@_QuV&J(;LY2`djJswbL8U^oH1p zjA0@p?L;O+M9anr)|oNRPqV8Yrx{Fhy0zw1JI(n_bB?vh(_pzUco#4^>c-F5*ry75$Iww2CsV$CE6I z{+_z^r>UG;^goLa+IW^q;%Rbq`4^bT^L8R0=K2)?b4CA4b~BC(-~STD0pYSrz?#)YPeGr{0u#NHyn0 zL+c(T+Zk)YjD29O+1%`-nVqqZn6b9j#?tLHJ2TBpYt0UJn%$tO1+$Bt$d}CcXMQ4V zuJvRhU)zZcWFq|w7`47+(wU0>0qThMwlh7NnI2&`XWi~$e%fqiUS!(m{X_=ollM9k zxnds9OLkg!nbs{UtWmo42UJd7O58quJpT2wJ6e~2jEMyL_|=Aqlz@m<+!gitEhSIb z={(1DO8fklk|ApROWJ9^$~0fH)_lQEGlXeM)|!HyW;v!AY9~^OiM(wm5)Kh9`>Xq` zmXdL5$E(_@dzptwgxT-Q6j5oc$tDKnO8ZLFc4W*XCMZmrqO zPBR^vS}xWJxsz#bv)0^dr@5bL?y=VV)lTyW(>!D+ za*~N0w-dPl5iQzhEt7J-+VL}X>Nl8&tLD78Y~7>3?2J8N#_m~b-ZlHUZD*`Vvc8uD zB>U|P+F-hp`CW)*R|%$B)LQciJI!aHsRgs7ok&?`{5d}nHrHNZA}`vByv{`AWUCE8 z8#OW6YAN|a9Z`>+>59yBd7|#Wl#n^=c9-+hX0ba4?ErURz{%uS=}vwm*_C0ui?##? zN(8tAjwic1r>iI2_`VNANV!2KxphlUoZ7NL3xs)2BR zE4j4V-p2i=z<|I2{5|Ln=^fHLcUF)7o$PASr5pJ~Kp*O#Dv^&tfhomZ?g0FCqLgCb z4-6`jg1==1G5l3(%|s>jW6_jXRqbMEaXPSg$}{A1Ur`ni6t zpP}uuRPH(Y`FZ-e43#fS+ZX8h7is$vJ^l*){3=?)@f!3Ii9ioMFVI$`auRK2dOVnZ z4xyi4*V-a)(Bq+K1Ju8(bTQeL-l1iBYwkMlg5^k^vl%IOz~y9DHXC~Usi>7CsRFKJ zD6%?MOl#GW+-xLSfm1uxQ&-`&4H%VT1Hh&Q8OyA3LT%SYFq*XtI;@Br^mzS z=NhyPr^jom<3j#gR=E`Ov~auMOtDUGcfi{z<_MGs1Y!gbNz&u*v9`|an69Q}g61|L zk+uzJn?!MZYD+Ncq|lL|f3!;-33n}9j3{8}!%u_g4v2;k!ywSP><;jzs8c*Y-tK@% zz1wuO)YTvm*eLzFjijHb) zZBzp?sp(Ey8~6!rJ8NxF7X6&9wE=td-wr-3S~=yERB_ z0|wJ}2yKUw7R&Q6`gyq8l5Xc(_OOR-5Br#VNSOOtFh5q@RaAWdfzR}^$8)v0=&T5WLBC}g_Z+h0p*_oZ1H_6EA(xQFi^fnnv zhZb4c>7AR$coUTP_~zZJRcYQZy?uI%tn}uYEkA1R>y+LxE318CMoYun@|{|@bltdK z*7f*vB?k#Zh3|w}!U^G)FhiUp&Jxec`^DeHgJO^1Q{qkWqIgBTB%YKPORJ?7(q?I^ z^oz7tx+EQww#sAV@8p~{pbRYij7Q4OEk3;Xwc@vm=XiQ~26zT~MtDYfCV3`%rh2~h z%=FCm%=Ikr{NP#cS?O8r+2Gma+2%RmIp{g>`NxwF@w;$RI3=7Gt_W8FG)kNx&H&OJ z@q6(Haf!H0TqXV_ZWOnQ`vLfycnWxz0C-c(l?F@Gq(#zVX^FHFy*QD#xP3e|&N4hKhE!~suOAn-n(jzHH?kVTWz2x3&BM+1Z$%Ew~@=$r0JX{_jkCaErqY;8}2*NCRwme6kE6Y45{EPgn zyj$KQ@0It-`{jf3Z}JiOsC+^`DW8_l$`|EJ@@4sod{e$H-;wXi_vC-%2l7L?M{uv; ze!=~N2Lyi;JScc*@UYM3sRRLbs17uAaxZ|*C2Hr zQa2!V6H>PzbsJK5Aa&PsM*7?Hhjh<#R{FYTxlpcBhl5&Jg zQV-#>)Kj=3yQ!?n(oNzokLKJ!!D; zk2FNMFAWtQNW+A6!f^bI5FSb+g@2_{!Xs(4kRy)~ddOpip7J;$R~|3)k|zkg<%vQc zd6Ljqo-Fi}rwIM!slotxn(&Q0T^J~TD-4pq69&sOgdy@wVW>Py7$(og&m3X6JXaVY z&l5(<^Mz6J_rhp-fiOm1D2$bV5XQ-igz@rXVS@alFi~D2Op=!hljUW?6nVKYRbC-X zlk@=DlT1v{%@XASK91UqYCXC3UU7rvD@z|Kb4*#tYAVP^~MY=xblVP~80oxEL` zA@2}o$~$3a7wr53JHNutZrIraJ9}YgpD;__4?727=OFAHf}P)B=P>LXft{nmZ26cl zM?Nmhl}`xsfxES7KJ=ce$Zd`nm&-^R}!VX1sqSSJ51ESK*IE98HKJo&z`Qhp$; zk{=4I<$r}W@+09VIY(S8_Yl{~J;n8MuDC(&C2o{^i<{&=;%2$8xJB+KZk79sKg$Ee zZSptbc6p$9c9xm>YM~Hjnk>Wmilz7E6TDaj|e#{82b3E)mX)ON9&KGT~2gxo}Zj zA^aug375o`!ew!la7A1#TorRY*YI;)TqE2Ne-dtrYlU0*xh<{}?uhG!yW$4nZ*ik= zPuwK@BhC-IFMc2PKwJ>^P+S=HulPgQBXLn!j5zA%^qY5-bl5vuI^rE89rcctj(NvP$GzjF6W$5Z@7{^hN$(`-ly|ap+B-!$<@to%>h zIQf3uc=GG}EZ{^#u-^q7kXW(b1 zJVl%({~Iz}eiSlC?uQj~LWOzqqL}&e;+XH{pQHC zD6g-&MBY$!sl2i3GI>+gA3sV@Cw< zkVgh%{SV$Cj}HD-9us`sGdB3JcU@0 zI}LVUbUmN5>qVFA=?HR5t9(Z5<(~w(A3Z`D?TToV-Xgnvg$hGmF8rgf@s}MT^J9{w3@$^+e~;rQ(EX^G`oZu* z7>d4Kv1)}Xl|AggidAdWs9wEF)fyGpA@xng3KgnVtLE`kst{JKT6J>h!=f(NqepI6 z>poviX_glD?~lc29G=%;{)B_e#E?cC?w1dAJyZN~7ddxG33TDwQvJ^uaB_fzyPSVG ziEv#B-^9C8MI%j5Ow#oKrSE!yw*n6|0o5RK0wq8Wk&6Xx=iTWAl2MS=sM|Ra38JTU9FGx_x`m z^E}8Da^s+NMthgi=Kp?OoT*&^H*eLsd#CKo=H#Yc^X#;i8QEFcwWu8li)!Wmy%{NSXoWhIvqQxESNcwI_dcb5{Ik?m{wQ7rlU;`F_@MRp6k z&-@==t?P`qh==9Y|3l09w*=Jt07_g|#U&ZKXSE<-n z?mt(>y`U!sq7t&>nU`{we}aGh&gClGqy*NgvTu?Vt87jY+$Tf(mik&wJBEKc2**m# z3;RF!LLaq^j;-2vX^mSMbQH5%v`Np(Zqe%F^6gwD-OGo3GNRnT6>UzHc{u;}8$y-R zUgsXPJWb?u|JRu90i}Pb?YILiGcr}%mk%c$EmOslIQ^xKpS$L) z`Kt7i2*xZTLMl7E;yY!FFt>YnuYP+r{{mz%o+rAap zwQaF4{!HIjy7GSyI-QLA=w@`p9juNm+G~@veMU>w(X=L8f=cwczd&4aP<&%@{W_)p zjCLHNR+$~!sK$Rd^R6)N!?{I!7u)H6{?4qt(n)cSjgz%SHD2~$#r@L~16RC$=jep_ zJBpqy{c=mk#=BLmP$R8to9?QET6f=gJ@w8PedotDD|_kjZ@w-a)z-0tP9L|*s;*k^ zHEY6wvs)`v=&`j?w~RqEFO{zEJT?ShHJ<%q|JyxM#y9KzX4AG=PR@vfCs z^Rwq4=~1*z;)JI<1h3zI`^mfj*U+ABS8(0BY0(jB6)Hq0B_~Bi){BmaaP@r5736kL z4R+;pdX|({0j^;N$;$QO>nGQb^EHU5D@VuTCn1Zf1QC@_sLDu#N~MIDxTM6S28j`M zE7Yw@r2~m{4wW8dkggaL)1ZE2Y(YT$nADYJo&T{>_Ea$#UFF>t923^YMmQ~tw}0j^@M zRi9;joR;iMjE{adJ}K6h#=ZsT${7M3{1^0In9G+OlhmkDVj5(DhKCM#wg+S3sQ-q- zYBASaG10!H*tGZtK5t|E)|x9P0?#z?UoqF!cEmwKbffBN>|Yo`KQ!CLTsQJh8(a_9 zPrujIms&5TVNzrRVsxZ_`1O`B`VN`hi9TOK<78lW=%oHr7p|Pqy3o3CZNwTRYXb%Y zIXYFTFXCd7Vj4y!rZs9DmD(_dSbtkrEY&EzYp1kU8J*gtcTUUb*d{YAD;wu0>gN@+ zcly;qSI!h&sOXnEVshh#$-YK0#_mtmrS^qK;p3I;% zBDzus-x&q)n0L~mBNG#&BBK+G+~4V@j(rND$mr;pMvcZuRK@l-COW81Xs7A@PSYx$I+4MPzA!lE8maH3Mn&O)u7>C#!J0%9&<{g7krnEq*6 z$1da-d+2O@1#u(KN)171tcw9ja3Na0Ik(!Dw3IRT-O>I!?R8k3!2MyJR>WO zUBSq1WrxUT>st_HHk^YLIES&Dd4?CQ&G|u$$|@YHpf1P=uVY$O@v{U@%pe#r^Pl-iiSCs zoD(tEjZCe(bm)LPQaQg+fB56F1{=gx>&#C(rnS#(fv*zoUX49Wa_(W&vxmn%G2QpkM1lg(T5Giki3jI#xL~@GJEtWe#4e$ z!|t|MKU?m7J$bRRqssByj`rztkLCA9$6_<(8@)5rKh%vyH%v6ngZ(su6SOkqALrTl7v<8vM$)qGT$Q{z{yRdcx*>wsApisP1>a=@w7Nz_YR5GY-vRU8=s(LOlL(iYw=cer`Qob5f&I z!(W&5Hqc6&NVX)8Vk1?%#s^P!nvgbm4bU02>k7n0T)ZE-(Q>-t^&WansX z9SyJ<>wCsO`k4kT)I7_-jvAv+hVJn?Ff9zUs2Ir~=vHcK;i2nYk`I49#g+5Ee)cCV zvYZ*5r>ja(7jD(f=!h?e=!KNFz#By$ z(?$3BFCT`z?QvZwRm&~1hJk}6RxT^Stssu!sgvGOLp~YP?g`z2`%5)>=_NdT)Ynt) z80vvEzq*Dce^FikjZe9n7X~u*U@gtB&;767i|gvo=3n!$ZLWlV@?idI)9~HoRM=(} z`A%&y|0`4Y7Ml_gP%a)E4dAW_H$AfSYt)?BeDH$v{@w z3_*qsQ8Vmu5;Q$W=xo;)j8eLf5}FTnsRuoEP|S7Lu<+tIU3G(8k;bC5V`gizr(0b^ zk5CbgMEVUHOdS9q{tIf!O%kpT}Z7Ni9R}KBsq6(z=O@ zuK3t@(~=__Mv}4Gtxx@4rW-+qS^d0jS zr8LX`7xZp@f-MIRZ=gpu9>9@5&7}^*e(QydMdn4_L@?Vj8>i}d5wnhabeT9~jqFuxb3s4Xw_E2jZTHQ!i86u#5_l{Q~d8@kH2=wj-!1jX9=O7w$%0ZDGe(pw}|G_OIuxZx(Z zPq~y@rjB;D1(_BM2DdESc#~8eBz8%dVodk=N=?94UGMZo%PcJBs>g<4rwl}iHoB7$q^|M9C*6AI&+d|v*Rq?RRU2Masgz13KXsbNEx&g<>dRWJrZql;# zsfMn7+;Z%hT(~ZGNZr)vE#}tvVuco7x~~;;?WG&PH$D#6`k-KS`wG7*#IVWK)U8Lc z(m=nz$I`r(F0)#@3#Q*4-l|_%1m)W|+-7F_wRQbf+NdPs$(ni#%{)AvqP10?{Fi(N$cFdC6Bsmo2(uH#Q(BBD~nsrN*10dJv?RfLeM}Mt)KiWJf=x9?pnlb}NmvI-#Iq>_iS9Lv7}X2|3i-OIC$h!;F;!t*%&Ex9VA5u|GJfab!Dt=jnz^^T{N2BW6H?N>Vju{ zSab1wxpPK~_L@&x6$O1}ksGY561ut%T@4z+Np;jUy1*;emkMmyTj+vm>gSMh(C9Q*F5N)rE*43^l@E74-IqZ63nBg%O zOSTTWO0;oBi`BmH!k(hdw!1CIGOnX;r=BtW4Fi{{3%tqhNYJn57=$|MLW$aaJ6f{P zXY9pX|0E#y)H~Spk%6J}pXj=-M3WHfZf9L+o^_85ELpnf75^+^*0Obx<#dJBp2i{Q z?3$ss^#n9zYZu+fL;ubhV7lr;zq2JMe{*4j@To4f%5Xy`4TX0-`hcsOE|5nrW$?rv z(*oZV?MUy}vu6=6TCGwBqVBq>G`~AU=smkVG|%vCTidbOO8QzOlr72Go63YEi3S*yRI8t&F}#uF$N< zBsFe;uiK@@kR^-Fo=fe>UZXy3HO%yWI(Rd__A!X`*F}1Kpq5SzV^U!EGyQ0;zSya^ zsOUom^`^oYU1Yq42u#rPMM)}>FKgmgZ19^lx*~}szNhLF5 z7Ry*mF^fTynKTi}k}XS$k|mNDkx1GkN)jz7OC@DV)_h*)KCd}5@B5l_KOUXy@q2vF zyWjo!a^zgt!}k5;RiCv>Qc|L)j)&B*XUn&@n4ez(PZ90(bJV9D zc@b!6s}5_bLz>FDEF2*R(~NTxoDhMn(cG3)4J*E7RDnQ#mMUo` zXV+fOCBigYqS~<43R5-0RCU_A7Qa<3Y+NmkRKw*~*Kp!(tV1KFnXw^^4Z>7?0t-ri zvKnZ<`kKmFvfIePG~+Y@r*W84 z*b<2r6W`?72dbBa#ImYaE1oN+*|~-z`93DUX75wG>$I}>>3v!>_F_rbX-fg7nIIm5 z*f13nrlRN=Q0$1X9kKGVvb=Ut3|{%zzR-LSxX^r1yC^EOHGx)4Gizs9JB6u^guVi( zT?O;vY-lI2L^&+#sO=Y^r`dJUK3Wfvh3ShmrMS6gfYp;G(cF6i@P*yrf|`48CS#f< zKZfM~VX7~~WpnTEUf23+4wyCsdNYpJ{%YXn! zE0Y3DGr^EBujXD7mdh|qv#_Udy2E(7qPY*ldVguZ??KHy&or?Bi6fXOn)?Wk#Ai$s zMt(Q}g{diIiRL~{Q%%uS&JBGAIhbag*T9(*re>2Pn)@7$GuwkRmmEwp&YR%8L5pne zZ)nkC+bo~}(@d}gg2fcb=Ds+zU?~NdW`dOvyc?$8Awo3wcX4stVqYBH=KhYRa+*$& zDPuhtAB3s*!_;a@M05YZ{XoADf&473)=bW>{g6w9X|_b0VEZggeG;ZN(k7exXBz1f zm%CBJiH-CHjhJS}Z(#g7Ol>7lH21GH-&RfKEZKH)FwHnWfU_%1eMgRH?z=S3cOIM{ z$-y+^{0z<>T10c-qa{20`4`i~gGk)ZMA6*$BeAUN^()U6)9hUTK=SWQmd*WlEgE~V zq<$Qx0MktH4+MXQsbgX42pzJy|1B>oXzs`G%2xYA<2Lsrp{*xr#Wb^)x1!bgFm;Yl z+1$?um&2lS+I|6gbD+87XkB1A&r>jcv1S!F_iMqr#wz2P`!!Z!{x-Wx1U2{Tn2c$b zTm#9~Eme)-vbk5ciXWg<(;b0l^HxnlFwG!!0jW)e?CiCz!h-MY-BP-B_Xn{w?=%vc+TF^3lvTerWq&} zpcqR<5hQwgjOK~bJ@{Ofv*O6XG~;vxr-P;1lOuY12aVI-gYy76m}Z=Z!Rbtk?CG8L zXlJWD!fZ^l>?CA&WwvbSUA?lCnT=_d-2>U_mP%#3=;rCT2=1zlM;3UVo~lWl7Sq!d z@E8F7E!Edjy=f4wyubUA?F)hY%=FewPQ`qji-T#lI61IoS!%GQo}^8-@+^%s*yTQ{ zK$x_(12AgK5SY1x}%*Mv^1?c%jA_>A@LI4yGAr z95`cX5q*5Dmh9~07fll0lQ`MI7Y3KT zqBpfYf-3l3po8ORy+s!0e`Q7D=U$QnKl3uOMYJktQAYnRXi=E|QyKmH*%nUo$Ml~% z2C1W4sOK0gyZ7i8#ohZk-QZlk#u9<)A29)l7b%dv`^6T81-pZL_ntuS#?hL{bWH#0 zQ(Aa+?vkLX48rsuGy|tOou?`K_H?Z7o-+FOOp~-ZNSnqC%gBI$2Qbf1@K%>0xLHUprO#hTmK-ox#?A06fSmzS+DRVLX z=Wa&sCg#dcy~!*0OXgzw&)tsPZ7tMSj23-*8!m2p*{8qK6iy5I)+Bs4!hdX`zHgy+ zGGBD*AKj1T_ehtYjh&ju>C$_+D46~iO#hVfE%C&X z4$+;@YpKqzy`ZH*+9gQ4sHIbcL~p*RW!XjO(w0sU!t{TRS0eRtrpnHIxfYAgTv81x zFdfr>`n5>ErlqRfQdOiu_T_6@@=}4mTp9oUGy8JI(6;Mn!}M>v3AUOo)s2M7u3Qrs zQP7HR1WA?|bmiTFu8gBqn2}VOcYJJnMa~! zn%D-3ty`;>43%xVwY$SwYWZS^g>%U<&6d0!IMJpEftyO1oM9Y3y<8=1mJW39x8K)aKNwmnO zouoyJZIeO)rkS7z1nCsW&Yd1w(31j8GeLg{`nFcRi4g6(FD{Np?Te%PlP0}2mD6Sh zm@=}!7~EPt*;);xMD*~%?g#ow2;^sJpk{J*Z8nz((`<>JhV7}=YFKNPOPlQCPidrK zE;m=hiH$UZMocr~C>RS{tC0kXR$i$2MrtZ&$wrfdX~r23&bZcUEIFc?kJC6~JvbA{ z!8GGc0p}%JL_2>;OLq42RMW&6NSw|@(a@(Ov8?Jfljn+QcCK@fJe$d~rO(!)u@_6~ z$Ey@znh6#{@MdfEMr$>X4%yV-l$RCs^*8X!3Hw6h{-nvg(AGt?Vwzdsh4r1*>TN=0 zbAKne92UK;?H8aA2bw#M)(WyP|10aAHfZi26*u>5!lPB?aCKF6{sahZj+X+bg^5MziUp~CiG_ej6Zwgm68TysI5cV&dPOwvNLh8gi$jh%# zR8tc`Gcm9PI9heN1ej(^&=8;o;i^7C-xh-=+n@$OoDnLO2Aou(SVx$87%GNxH_OC(!NK8)nHb<5?= zw398FJiQKnCmR2w)r!fOX2}sq4i8uNF}z&3^VxXC4i888K|GAWq3AyR_pA7z=1;F< ze@*~#?l+O90Q}2Js$IB>Cg9@IfOe$-(H?+!Q$R-mI)tnC1f1d3A+Q1+N&(t?03I*} zJOsdlOg~ck&3_Pyh4z{|*CzMPf0%DRrrDdHgygQ_stdzU@YLtoZ+=&Mqjkpr6?Kse z_Y#?G8s7u)>ESAc@p~BmrX8P-8^a>|#_+nm-*7BS@nH1y$@sGPmX!&{pm6m#8S<7j z2#&XHhkMI<9Iq_5UnzadS`oNj<7j2^&B65b=D4h3VCB*zZdtilh!rK%e-m>yE0XFHHz!KnSJ;NoyG+Tn_0U8yq3JH?8tWiL`#amWkXwVpf zFwH;{0U95!#t|fMS>sEA#)Sq=A_&tAG!39B)QDTw6b<0qvZgZ`(=2%wl4mek+_GlK zWcR8yo5`4F$@7r>TDY3SaB<6e4dKPNtU37awf5&E=$7@mDPR!*3&PcW0>mwAK`Fp| z55Qtmz&ilE9j=xTAZ}T2mjW#D04z5J6alb;>Ef2P0*R%rP41h&if=xq*_;0XlHU(k zs~IkCS?{~Itksg?ULx0-#(#qNjp6D;#*16lM%)PP)+_L__ zLVRI=6obCX`pY!&1QL&jtD_8+x2)qx{hGI|qnZGkuLDbfqxBD$0Ml#<{sri4xH?Uc zyk(sQ;v?R&PKO4aCkWFFbV*x$$F;4x0RNhm{TG+yE$gDTC7=uN-|{^YD|BgFej~Q6 zA*cdCS5PBvSyyNP=azL9lQGSfqB4>zGFjZRD#~Q{s#S%_m}befN>jqQ6O#swvt8OGf+_Gwx0^H~UsBH?k1%P^ORb2waEvsHBKwS?& z15?2505oK}xMej&VyS)azWI0X&Bru*^Y23Poo!VkhKpO)oo$Q1%4#GT?k($X(|8N< z&D*M`j2E}8=56s)|Mrc+y=67^V6^z}jJxsUuQvyN{Pjx^zF@xi!x3K~?MHjR2mSil z7Op+!e_i{M)a^*!)>eJRVEL{5ZEcIcmH(AyfM<8$&VZx!Eh(7(Dc^&#lMeZ9{GE6Q z_S^5ki>3Zx#DPFMj@A!M$Mm1Rr>)nw@JoXBG6>Uu(0-ieFFZ~0?fYM_#s}>8Ip~+p z4w$6U-w%s}~V`@h`XbXdz4yXhF08PoqVp9bY*TXljI z`7QgC0PMDxdTiirvGz%5UCF^RelTp0WB8$uB1M6W;&+- z^kk$bMyN+4)FU*=Z@(wX%Lcyv{wQ8KY+p#+Z@)hh+S!dxO#jXdID1B@?nKIOz4ru3 z6uP4B+Wr7|zg_X{qt%-vOh2Ss0}XpPNJAr3Hc9e<&`^+$+pFY05X#0Y|JbjTejs!z z&^mFno+1g;Kj|5e^63!|gYvN+rw|_eFleMn+Ve;o6`=|lC?5okLgINo2rAUlAvqs7 zbsViRJatU}r#=yw@eyhqG4dhMcmR&@A<($cm`TK7`p3Ks%(MtKg&6q&Xj&=El+c(N z#9;cz%mHRLCF0@FY%Scmi@eHIO#i8`BXurQ#e<)@GS&Us{|%;M`cGYq)P)i1O$LjH zJ_`|C{Ltr3{P)v!u?vG9`n+Wlz8vApBGgibiw8c-N`)`=2!Gckd^N&XMW~ew7Y}<@ zl?q?!5x&MGd>z8qGFd$6S&Ot%*B$rGUe7lh)Bl_O2~syks0|Dj4|z656hGwIAPMe6 zo=;7pw;+0Rg!-J(;sMWQT<8n1w@M!HeC|Qm`riq^Msz5DQ{eV<4umtz7Y}&OAnjRu zZwEc#`Il>s`Cr$(B=w?5{GIAZRW8!`N>4uExgfH*-It3DHo)^-UHfOuaI`LtbiU}s z^iR10l*{Ol4|pz%EG(E{zXPQo@JtM(<7i#UbWH#06(hYK@RS5qVi2bPpsF~{Dm+c` zfTs%9c%uD22R-1q)+Fr)q+QQ6@qp)gkF@G0X|<77D^k^9pnSkn%iT>iv~01P>TsDc z{V(&apxhFv>X9NJ@Z18xbM{iZ4|wW@CN(4p(?6*RNR1dKA(lm@XgiM1)R{ zW;&+-^!7-Pk5sV)hzC6Jxadu`FM93+o>)!fe35*=3E^Q7I!CHbk*XsV;sH-*_e0wW z>GCtvQS&%E^bsx%rvIf$g{xbnN{Uon>5>n4x@nvwm)cc>iH(y+AEtj_ANVpNRZrr? z1D*`c)>9KXOVyVYO#hT8KzTe;4Io84;CWo54Dg^lNeZTaN;W8&bchE$nOdr|cXLeA zh9NDNY2pD-F4D@XOv8DOnEuak1XA;uDj)FVX|dRMCG{bn>6rf0pGW$rNL3iAM$#Z3 z@Qjj|4Lsl}#4FS73yJ%HXJlyS7&XCJM} zBw_j?)ebc5H$a*fspgO*AMnfrX{NnO?gO4VcxATzO6dnYa{{dsM{7PwnEpv`fwYJo z@qlL$)?*IBgCFoLF-dzDY41d;w;3oO@VtY>=juAYPw}>vE-s)ecOKa`2Rz|XBl!6rf0?~n3&z*7>`fkBx5gF4|fJMuKe1D=jpp(Jkq+Dq;*4DQk3e-K>2_t$=yv|wQRAQQn<{R{+GEIC_SQ7Iw|r2PY(bV+e_^} z;7Jcn${-2TKk0Fh21KcTB#8$+12j=TP2}9o2a`2sZj=bP;yAY z^iLTM%1}Dw1D>H;tk@<`F&)!?dI8c$FkL?284)`D8Kz_UPk$ciqoPzH0pbDAC|vYb z+7~_d0Z*YOa=u6&V?uZdgo#mVe3TkTg?PX-(f!blN4osXjMF^M4xP-U!Sug0v*DT< zrCyFw)98{9cxGyxmtE>K4JJ0uEA(Od_sxgz^(Zx$IPrkzb|=VcYXus*HLOKk@5l0*TIFZXsfnA0DdR%fCoowJ4u*+NMV77eGsJm^oWMN zAK`25IuO*be`PAB|I|N``bU)dox!qU|KVPrvLQQo(;Ps=nR7}{Rf@LX`bV0iiUj-Yy64*J_j}Ia?u89 z7e(V+mq!_XVEp}6dXy;2uO#jP#4JeiI z)7PZPhFuweb@o!b4ZC7!QdN>L{gY~dR2_eYh9uFjt81can#j2+*CYkgKcyZhb@A^Z zks=y)U5!%PgHoRqO#hVIK)IC;*|2ZbV#PMOo#~kV)9*xjBc{uS-6(W=6Q*POPj8O& zd!yAo1c-)xZ!~^q*S_ev4f`HV~w*ZAXF!`BJVN{AB;yOU7SAgN-74h zs!Y9kj+p+>u|HD#GF3M0zFI8yT}gcyz;sOi=~+l0jDLMPS`DN@HtfOjvVn&EBwqQ_ zzL2;Ldthj1Hl3LMolnF06#m(0B4xvV3M5hJiiT{iNXOCY%XCct>5s*5FQnj~v$sobUad;y$|c}5 zOM)I}5T^g2K{(APc$%VNKY=ygWxvls4STRjS`N~(m?j!_mPgtUle9df4UbVn87Ld} zaCbKi)w0EIdYa3O>3^9EK^YmN3P_O+dn5qc?4@=ac0p*;b0lH~l&PRhj!~0H5e<8?Mw#S6nMMkxf66RSX3!xU_6#jnY?Ikc$Ml~* z7wNAuT{i4jL#NMUI;Q{hMMz%|qvjJJ8ukKQ^nSE2dTzs>uZf(Nve<;M0)*u;YFUh0 zN`+|H%iRy{GNjAT%u>zc?9i258chF7vktDcF=|bWdXFyIu-9swH7@l%4JJ0udipT^ z`#yv3lNhy;IMJ{_(QF$vk+W2vlY;4=@)amsV$^0*M8n>qQ8s%}z9t3JKV=6f+vyMu zd%KqE?A`B7(tbeNE~bfwy$fk&Ri+<#j+p+>aW7JLGgUV1-C8X6T}gfTndzAR(+?s2 zw-|LWM(w9THtgTzWdjZSAYR#PUr5}By+5?`4>~dZJ5RuQJVqTQQa0@4!G*5qsJ1@< z-Wh1vI9mUZgz1Nrx32h4lih$X*{^R`M$5jwU19z{yAlMo?CR~DmW^qaTpP)?+Nl~0 zmrc7?yW*x@Lvz4%AkcMjwCa$9X~ww)oO-m#wq37XVZjl5zm#sBuotDS1j zP}#mMcZW6C^2H8o#U;lyTk=S7+O|_|$dL`aEf5FnWp^8Ro6xK%vM|k9?ZJv~r(($x zEj(UR#cC?&#(h6Im}Z>L;B;!II+7!rcqfh1(S!34IhbaguHbZ`MYi!STC~_Ui4nZ!<{P1@oF#jf985FLSa6G7`(GUekE4m}ciX6Ui?#SvK~UwP@_clKL@=0!%Z(8xYKE zr(SEP=FlNq`#gDBL2G{vubi?kG;V936WThTR!lSN+psQarxp_`oBNXBa#*xj+b=*L z2{d;ctz~3k`eH3F&wq6BYp}M`Bz^*AD*$KhDiPG&w=o&hEO{rAceGR687`aq4)?mY zU30+nZ=g5hXzd~g(~PqloF8eC&HYEbInUl4)Z7biw*Qm>j@BLuFwF$}Jezw-*nWm# znuYy_(>=)370vx1*1HgA8{FJ~H%R3Zn{jB_nG*U%!H`!!m$*f!Tu zfN3VU5rP{ikj?#u(1IEiV44YThM-QYx`_zU-0Q>^7L2wpj&5_mNmDsZr=BT8fpL4R zY8a~;P$HW9?XkrVdm2I@KT8cXle23ZafvX^mZ%wQO=H#Fv8oAevbi_aNO!y3CK^s` zq~)|#)SrgD}noE%IuPCIa-V^t(MqPa(FoJbE&EIF8FocqB^ zphYzI1TERw&mBw?J0Y!N+M`jds}i?yP-xjzNgFq%Yj9|pj9yTJuD_dF(JnkA1!azU&b!Eo8!3*774 z2+aZ0gg|e`(R!8~Of$~&;EbY0Huq6@bEevRrt~xSX#oL_)))#f%>*yTdOdS52^-Ha zOtY|;aJmzDx}v#H#ClJ&-}j(r?vqUurz3GH6Gd~M>XG=eY2q9t&W=?x87iCmYtB(oZh;2Ms4S(l0b(ni&tl z_*<+xNT6u$ziGaMn#x(SKghu};~WR)Xsr5+9MRm5YMj43IDeCaX~sDX&PiHCb3dsi zJNx;JY2tY#o@1hD?&pwLR`n_u=R6(3G&|Re@aqv5#5qrDWOKhDE;t%{v7~-nOaZ2u z;A#je#HlOd)Ma$Y=3XIATvpKBufQv>*cTeNxnCCAT9H;vGix=GzUy`1HBnX>uz!|%{a}$xtA8%-0#Jkv%uanrJMW0fB;7;i~>wEL8~~g z=3Wxknqin`VQq1`ZFst(xwpZ3FSOtHpynQ7nizw`C?<;L9_5kP&NT6UBqqeEIEKpR zp5X4VI4xi7unt^uOtU3_2%HDw)C1(m=KdfMbM0k!oBIQySr3ziX~yaXR#KemN|tEu zNt&vwrgCoRDdb?9ae9H%BTl80Bbs{;jg#)d$sh;QjME>SzO=~Z-dBqj+hza-m}Y_} zAs9%3Z0-X?3kFeuX(q^pASX^`5h0p;4la&w*%wE*xo2rAr|AqeWjq5$ew=zbPCZ45 zXzuy$2l{CU_m?!^L`~%^*;H~c%{a5cnHi^ECPy^)nHuM156&y(V488}f%6(IqPf4O zB|H21b<@NJNSx0^(cI@Fv8?K~kmrhNcCJg1yqL+dxi8kDu@_6~$5IL~%>=6;SQ)3@ zjZ^Q?A)EV3d09boe;2PTvoADmbAKna^*vfK&8!<>T_2}DAXGN@^}*$^=mTxP0KFj4 z+;Ox%A`8PW^Cjjr-RU)XlA7wJ8S@KCFpNLb(87`aq3HQ2oTywy* zGSHiGv`&$OX~y{%oU^pZ=6)7$&Nh3`ly2_d1Ozx*=PAH66I>YY)!a+ME{b=)?8Y<; zyDUChT@vqn*)5v;CGmy%-`MYaP;Jo;_=6+d1 zaj&{WbHMaopf}@aT}ck6*+NtT=W1GHbH6&Fuwb9PXG%Bs{Q&`vR%Hq>%>>sbcs2Ku zuUGJ8%PeO87CW@%mg)v9MRk}HO?RpP7XPkW}M;R45dXh z_n}&{v!99f1ea};2j z3C2S(EutYg5 zngW(AP(besGi1pMP6o@y{(aZt#=cWCz;iUPhj6rhA_dbw+h)^k2JrHT9C9-x!4HKj<({^AJx{wDdz*<5Twg9MsbPG)X&#v?ELt4gH8m z+HsS#(?~nnRh?j0B7Q5*Tml@OlGGCAwt;!{;e@T(eyj-HadlBk3^M6B= zE=+VjYnc8?SAukTqPjHE`H+iNez_*P6tBqb;M}Y$kb>!-at$bz6IDf0L?f@PQ7U>+ zs*-}~pK=2z*V7@}`1M+>*e2DPj_E)BCZyM7x@_V#L#NkfI;Q{h21u`;sBR`ewD9_g zg#~Bri=NxUZ`MRkYq`~g&;*3WiAp7^+o=!@ym4ajEkGe%er9ghJkAcii%Wy)e`#94 z6_%))C90-$$@U$lahkc*rW#CaoR;)q`u9b`*EUhLAx<>!wwkStCUTZ4iWE%$lmt-X z5>-1=MC*>zDD6Bb?McD(Pk8{8|Ir~D_y4q1XYY10NqZP+otY-uc4wrORhb^)Ib!-h z$3&z)%2e63AJt;9?@H=J64NpLr}sp9_e7PJs8VQ-D}oJ%>d6c_3W?GaI{8~g6W?!4wSKU$c8-@Z^&qS zkCblM&j-?Rv|eO7rvLOwiCzu6BSO0z|{!ii_S0 z_C?Qa*k5WQr=@H&A^ZTsu0-`+qWYE!(Xe;9AKLGbEY`l^uII*;M$j{ zeoj<-=#mY4pT_ywrS8#SV&fd757WQzFZd28szbzyhJ9GG9nwV3QXL@$(?8`TC?^ut zaZ*IXKA};Ldr(f1g6W^~FDPf}5DojRmg?-?^CoE*CgDd3lAPxiqG6X$D!VdWl*At; zNHRFb%aD2rQ)R=xM2p3~E2$5cGab|a3RgjTr6hHAlBz(1Y}l2O#AO2w`)a&0!M>2V z4ZA{U=QVU<`ghiVvwD)MMx<=m)j<-4uBaMFvitx%+OBx^(W*%jrXNzLK*PQZq&w*m z4f{@nzhu{epl8^3GZoW+Y8X7Q~RD6Qy_ z4Z9WIkeT)#Dc!JV1=4Y}+Atl{e|lt+SHms|ieeC^|Daf$W(-eLH0&6x@htm&4rTksv`qs!|vqnrjA;+*i8>{nKAt@a}p?BlT;T{WW(+X zz!ZC_-G<#IG%1-RO#h^wAazetX(Wk;-CYxOnU3i{eFW0;lGJblM8nR* zMQ@IM(Q_O2a82a2lzbDy^B{~$QiVxsBo(4zk8(e>g-Dm5nUR{u*`Z^&G?@OE<|Vi$ zCaLjBY8+j%VNcXJ<6Y`F4JJ0uWco1u`)0v6BS}psPBiQpnr*r!a+Yc~DVY8#uY)o- zNxe#nXxMW#%BvofH%P(sPgw-Y0y;#)UZABqdv~!(+S^E5!ZgvammsaI%CwBCmDGooOvm(}z7FYYlhm3d^&SnfVXu{!4K(aEcx9e_A#oe_d!e1{ z>BRK!{2b0tlhnsV%7*=EaG@*uSlb@}&kQtd9IZ_xVfrCG9BA0PLHdy%(Xf9+_N6f*|2MCvEn_sndzAR({DxkEligU`^n4((^8t45G)XyC#!pt)jd>*hTYu#(B6x5`I)&#^Ef-S1(ycX z|I$Rl)iznRNmi}tk`249#%beHTWc_}aiZwM^zUmAUwpEPB~CQ#c+D28iJYanpA=00 zl+K`ZN>&|75e>VOM(OB5d59ED|CFwvbfH5u>@HfWvv(6s(o&F?%rw!klaW?dWlH5a zV){SF9!O1Rs%+TlS}gWmNqy+abWH#0k0HH(vg(_xdea~qc7J)4%gWXxI}$8c&aC*y9nt z+O7jZ4SNz(G5x1bN9xpMHJQP(VNZ3hS(7ybJnsiOE{@jAq+t4|yaLKBI%LD1g*Rk_ zy+=wn?2iKJI9hXq3s9`TONn3)n z#Y__od$C8_Qj@e5NL!w)mN8H^?B(umTBc=--L#U+jOl-w*MhPpS-nS!Y}ji6c;8-X zw_(2*n)CrlnEpwhfV44LZ6HZB?2VdegC=rr%Ab;g>7TL%l+DR%6Dgu$Z`LTAJSba9 z!Sqkr4$3wdmr+<(1olKVvduQnMADE8mKm8Y^?@d;_2@nl?FD`nY z*cUywVei&NPD|NmLO2YQN0QHqI&fF#Y?=cZ*i%lhrxmM8iI>+0JPqXQ?je<~&Tm^iR1Q zluNs*i@P}w6GX$lv|I4Ib}?R&w;6|W1u2;RDHTDviVo4RuhLSTy<5p7tt!&0FikY< zDo87=dl= zZu@->YS`%}X}yrvgK45+_wY!|Fi9JLw0_-G9|p>X-Ot@keY9+`n;zpbWBOm_Oi%`O zQ%{g08}=Xow%SYWHtZ)tld?#{^iO&Uq+#7uE=i(c57R`sn#j2m=8=NwpYkjy&vaAy zq=<(7j7G`#pcImV>7OzNl+kp^hCNz~729Mi(=q+0PeA&MOqUJ&#n9;!nU3i{eLB*o zc2koH5Dj}OE_y%P7d^LOPu4_EOL^IZFc*YZyQx>YsaaHrhW)Dhp?wAE@-s6_^Ef+n z9+w8w|I)k#*P?D}K{qv@F4?dbX`BTvb-o4@8)pf9nErh$;d{56dWSgCu;0~e?`R@t zsftL!^iTN!l=r)-)uf1q{k}$7?Lk>b3Z{R`Mo>1;AsY4uE!Ek(ADg6ojT1xTPa@T43Vu#(x zCC4;d^19&EPEobUkqx{y5Qpq#cN=)E(5#!u!Zc&u4pzey)qpI~!W(L;2Aaybao<4> zrWxmMaGIp3#^i`5-bCXx_Tbz@4yG9=44h`P$Tr?gix%6)q5#uOa32J%D3Fc3RcJvQ z3NXzCF%U$hs0boNE04m(@q~SGbX$3ZrgEB1J5xqSFgm2D_9-f!64A^%xF6{D5XjF` zyk>HC?E_pQOtU5G3R{;H^>B*nOq*=yT{P0eF1NFW6B{X!MocqfcNo)BR0@Hjp{HrS z6iwwUSr2kB%{cwQ>64-|$Pq2QkH*RH;PfX4(~R>3IFHjJn)>5fva_F`G)>Gx;$S9< zwmuk%WmT_io-3x=xei705GKpUK17SgUM#5}!zjQs6O4qQAVrNxQF(O8)?OelD`@Q_ z@XBfXLgTjfywKKXX~i_Nj)QeO>8HQ;Vwi>6qil-}@`zoyWNStkO zb6;bcxDJVHnJAk3T93r_riq^*abt?wz);!TH@Z7)gO)FL*r!}_OtU550?y_XwTT?r z+&2SpUNrYjp;=qW!Zc%j2iCVK>Kn2|bN^OTeWR(I8~RRiFwHo7!1*af{XmXr?muaq zA3QjF$-y+^8~|q@EwZ`q)1t+;IYCiokIV=3wg5u&*t z!^QDA`{L*}_amChX*wrN8Rx+`m!i(3s8f`P=6=roK%ap?ewI#YCTG`{OLd;QV45w_ z<*E2_j8t`Ts=6@MdHN%p`=zPDq>EFFpB!9>|4m+T#YVbn;8aUh*O4Qddo_)7od@Seaxl#}wZW-Hi)ik(v}9*L*D+13kHnjq zD4P4tNGz**-NJLlG&|SZkbEnXWplq(i^g6osUNpffN3VU2ZFm&)t#xT5goF*-<2vZ zD`@U_;*~M>g~n~}jY38PhDe50W!dRZoV?=APkR*LrFWn8pWsGmchYaxl#} zkApLS7TMef;LVw7@0rri+-C&@I9dZKz%&yKPW5``UJ{ncFif+sAvoP^o~~%_*;wyc z_WK_6%stmM@hKz@W1?v8!#oo6OcO^Uu^?5AV5n^F1?~Rd{Yv1P* zVVW(`$FO~rsy<9r>u8hB{UeR^q03#T;lxJzghos=;}#eac^isrsq^KH^p&XR2< z2h)tR1Dx%tY8yGCxo_7v+dMemk%MW*`4OD&X%Wr+do9`7&p(+a{*1&uOcc$14-(6& zUcc~MG0o2PAd>epSvL3mS~T`zN&Wbh0!%Z(Q3(D@Rfkj6Av$Dp|4Uw0(A*E>m3j7s z#%=D0LR*i~ifLv&3+w4rb&^oo+)oFW!=jVgegS%Bpt<8{og)kLzp`qibtoSe_<8g@ z)A0NCY0e`8(b^lO;TMGM8WGgmo1{69C@}q}HbZLDG<7$FWn*ueR{SL5Zp{GCfx8t9X{rMQWjpWa?xqe}w%AP%a+xvx zFLPH=x}>RxNs-OG3jho3rFNV7!=XuuBw_j|bq6UeO{I_|T6vl#O3_5l&AJCEnEomK zKk9wOFxDo@6?v|MYC6XEI$j@yyWaIZVg& zpPq;G;c03p0iuNu$3<_sebIAU_)tycw3eq$2%|tKOj9G%Q~?#Dffu?T+L1_?pP2&9 z{l&nl$xZnku3}w(K?XvVoTU z9$qQ3FC=cuE(-1ZfKE*R&QIa|I8A*-q-@w92N$}ckF@;(@X|oT#?ktWBuqafE6}jN z2WclgqG9hu_-eZj1U2j*n2PB?^=G8+NmD;DST^iE?ltQt%>d8)fsTu#^$RJO{wcqL za)1umun*u3*YEYE4u@6FE2K%A{cW zr&I&wx^z{Q6w$D+(7P;ylp1u%hFwF874OMSOvm(}UJvPYnJyc4-O%av znU3i{{SKtxmac9kKs4;z((%U;?2De;uy55wPD@cHgnL1_Ctcl@uI{8lH0*oQiyyMw zg>?Cuxl{8vJG2>>2Gjr2w1KO2x@wuOEV^XFZmn@zx>QSpiH#FZAEtj_EPOHPDvCJK zuwyh^lqPbPDvlIP|CElPbVyh2Nf8aZgGOoZL3w}_O#hUJLFr6~XxN>#RA=u#Vv?4K zv`3jH8up_|E2}ak@f~2~t_FYMRNMkyt|Mb2{@13rCrK=t^$cEip zUN+FMd*PK$_Jzc4*gZl!`_YN%-#Hl0C)3qHB4xvV5+qURiUw-?1KLJ)&WcMEI9>9SCaJ&oLF#f9eZJ9h0s`Ggvn4G43^Mv}S;3YoO!eXpJKU z(?4YrC==+A4SNFKkZIL#S6P0_Gt zV2yX!?{iSYo^6u$8q(%4O*HH|9%*w;(iR|Xe!6;{fwE!GcX!k4TDI6t3%Sgg{+D?f zC`;4TTcpT_y%d10_ENhI`>oKVcSyqYPg)Jqs&uuIB+;-}X`+>y$hj%6AqCSvWdkVd z)71y0h=#phqkP~&`G^!u|CG-_`GgMHus_ja#Wwkz>6rf0w;+8p(`Ccn96Eg~(=q+0 z??C$YbhV8D(XhAUqPNSw=(!DhnTpCROOLGXW-_q5=bhV!@*|2}pI0s$oehnrz&L8w)`uF_}-?4OcggDW#k7>3e zn#ftI6Qp4Jrl&vF}Ri!_`d3^q+n`(y#5VuIa8S z(;yr6wcW*K0}cBcyz-NMA#oda<Kp_C#v;UMh{j zvSD}cH8OlqXZ&ALnr49Kmq5qG(dtDCrhiI5Q2Njz8+M;w_&r#AkCblM#{%g%TK$=h z=|6p7FRzAO67&RvF#QK*;xq^GG)2Q6gf%{9zt2GpJIf?37il?66Ae4ZBWwU3yPJk<*aBE$^k4Q6U=k3im_19O?2ivrO|iJ9HJ72Gjr2dte5(PIMJ{_(`=t;B4??-AO+JuWg948^-^0%5e@q*jk3jq@(n4N z{wX^_*+GYB*gLdTXYcMZN&5+DKQK)+>>rR;R%P1FbHwz2j=vyvFH>d1-mAr8-<8yd zeN4ynpMDtWhkB{sdZ~jn$cBALUN+FMf5R)M?F)(9un&fI{z)gMf9FX!PxMm9iIffd zL~x-iIeJJ1l4B{rvIRZIL!t;P0_F$V2z){Sq3-k+f33LA?*&PiH3cLM_OZ( zw5CYAJ3}>LplsN8ySu50mMwPEyU37y`R>6rf0(~zE$p^^y@4Lb!Fz31(Vp4+gKHIdU&(oG2c zKl*EL9#UnEolxg7Qp;$|prM>}NDez6Yg{6iok= zF`$g5Lp1EsTB@^m$C{*#N7^{1iH1E6X=PQW2|Pzk|K~Uvsgsy08}=kE7W=NGK1^Xc zrvLO;kUlFz&B##GX^;(jmb`4BVb8!TqN?iJwLe6 z6}_(Q4}c5pif13Kg(PA6A?3YT{5MMe2J0A2;wMFp0WiUCUqLPV1d}n%lFuUfbcQ;~ zaM`p^yVtIhnggaufv$_Ab&ecNGtLFQqgA=y&X*gqZI|m^Sg^p}FQuPnFANB9v@Y!J zeA$6%Cb+b>SK}@TyNqF&W?>a@x>xXYMeDwzcVYfQ`+X03u6>nhVr3*&WTI%^6+IHG zm?l<3;&r`MRffv;eO>S3ujQ(0`C^CNz$M2tTk_iA)atEjkRuy-Eg&Y@%kDnot`VA5 zhb&ApRzt8F^j7uB5-q%ermC;0oE!ITASw#jj(WBN}&h4g=zE}Qs2q0>(@9n*h$`Aq!N=7ZHa0z?ZxkBi=K z_C?Qa;pa4w(^@XbG$33F!sVIj(oA)6rgQTV4gB)V;#U z(_K7AO#kP2FH-Mes%+Z#XtCILCH0{h(=q+0w?TUAOw}?|Sv1I&-8xfTHqf$L;+4bp zg~V;yR%mB9otXZead5WFRMAArhTRS%QRs@IwfzC`{y@XV(TXPt(+??cZt=76QD7C) zB%X~I0&v8x1VJr(G?OvSl3zsf3z=#R!)4Qc!M%2k(Ht-x3v^u^t?}ewnsFwBGl>@2 zwkP4u$!`$UwhJ2AKZ$~)HH899Gr`N5UX8mXYzD(H&B9*6>CWQmiq<^~>s^4e4Q}0Y zOcUoJ@iiuj=KY#S;_Ie~i;%b=Q_W|nY~Ksq9X4Of7dvb*mmJe<$(Mt(EK@BdM>gtOtqdI(Zn}sob?`@ zkIBI_<7@)wGg@RD|4fS(+vW=jFwF#CL9m4a*~qtq7JN+srkP+T1UoX-b|OS8-+_zc zv-ZW&ZROiFmD6l?nKFI>V{fL~ovD7LL^Sig?gx4|1oE@=qh@k;?LICMrr8o5hV4+M z`Ylr(q)oQ-LmKHfmwQmdiH-CpjhJS}e_;GOQyn8vH1xkU-!V<)EZIqNFwHpU!8w%lV2=H1!L!%Dy39Vw!jb5-($-XzQ0Dv8?KK zCC?Sp>|84%`6?#M#(tF+jlEb>KPpjxX(qS3s&ze)r&0A+ZI0LiPW8{eDK2YO4 z=D`_64yG9=2b?TgWOL8bqQ$luLII|k;3)`(Q6QW9u+V}$3NXzC&qDA_mdYnWH1}t4 zahz&j9Np%guc@5oUTDgA5sVkI)R-(aniA36UvNLrV<3>9rO}$n*|p=jM3`nvG#$37 zS!!~Ynnasy?o&0=WS2Wh!-vegS$?pt<8{Z6yoS7i)fTbKeWrZkj}M-wnWQyGjH# z_n(=JX_ovek`H95eGHe){eXL2+ow5TniJ^FI9k7vgK5V36P!P2kaq{mn2;v#?V*-G6wxqPhQr^uRzv%~;ogRW(~xAxkv(s+y{brgCoR*OP;3#;FBPjciq&9MRlsXq@UE zoSVqOG~?6*r!FnBx!2XA#kQ$W0j8PYHVAH|KsNVVLkn)F0Mkrx7X)`^t42hK=6+{3 zejeSvIJ(Wfk*0E*&fTVrmS9-fs(H4$mlDz3E%yW690K`Sx>qwfyS5dV2-9qdqG5~7 zR&BFY8`@-ZkJLzQU2Yox^58r|4yG9=37oF9i00l^OLq2ivT0%(5>uEcntKWo%c@@KJXcJ!bM1xX z9!!?ay@wW!y;xE|GAO__6AXmlv24{pTlJ+wHuuNmWd+T>KVDg8UufLs-Z!-M30g7D zthun}WUDMfWpmE~OO(T+EN#C4y&%xsakPe#h3Sj6skpgM2Wu)#qPb56;9a{)1U2`U znT%|4x4Ewm&H9)u zOf%M(V11FTJ|{~w_b)Wn=bFm7p>H7v(~R>iINxNeugMY3{Tq$*wFhShIhbagAHdl~ zi)`+@v}mzyexv}?Oz<-Vdnl02eNSk?FBD*!34Vv**KBow2+`bs#l`Vs`{L*}_XC>B zX*!2Y8GnOuEL$DPR)10=n)@;L1APPn`C0l?Gda8V1eXZYY>Cdpb}n0;$yTRmlg<5{ zMmpniPiZ)@k;>)p=RtA|jhE%%Z)NAGi*lR?8KSvgk`ugS7vU9oA8?lJa&j=umaGyu zSLdh-n)?k%EUS9e;JIR& zooj6**J844?zOaN?8TD$QHKIdGr?^T+?u0q$x-#_kj?$p9C2AebH4?zd~RQ8+~!^{ zwDopcG0m*^zB#m)VGuo7qz%{>8t z&32UtYVIAFjA@qK8Ofb;R7Zx(=H4l%_=#vo%>mPvKySv;dWalMGfr1QV48t@F>w(iv=jn>(o{sh2X}|A5&Aq2-Vjm=C zFi|x343EUVrilZQ_*jnW&rsRiA9HtDe=T3^uqU|Wm}X0!15Q?s8cdFC?pZ)=v6tO# z?t??KhLDA6#u@=uUXB`0mT2yInrgVFa&GAPlXr#q1ccF$88)+Ghm}bWJU@Xc}D+mvGguazt}q zr*YPLa5j*GX~y{!oR4V{&HZC7+1byZnI>*V;wC1F=DrDuWmT^)d9Ijd=lV60w=!8a z_pMqq_F_r>*hT@SncxQqcIBw=a@4nU$mYIFURKcDzr!ng>c{=3Ys2z_dTmn{l+RB?r@tQyrXYw8-XOZAf9k zaeL2{Zti~v1UOnZQh;eDxM_%2b1w<2%`i-}uzEP%x;$Oc-0Nb!|F+-vpypoRG_fHP z8!%Bc_XZw`x0xp1iNr=j)Ex|!&ApMk!|u@X#SUx2CC4;d^5)>&J4D?>j%@Dt0s8(c&=6;{1YNe^18+u!EFwHoz;KU43QRIl`9;0!hJUDUW zV486{fYY89+1%S}(PG>Dj{;0HL1zd$Q6QUpr_h3jD8MumBtg)1i0VRwXzpEcaXe{X z9Np&LMN>IVC)t$I3ydB^RQeE=N{MLhJ=_m;It22wl&YDWU7Nur!Zcf=fv`O`MD-t{ z`qCzw`(qlZzsv2b;lxIIf<{a;;}96Lhp0>fMRU*Ae3_ccS+ZPmFwHn4z{wk;hLaX(cDKPv8?JfmgkCTcCO=*JdVk- zxsTJLu@_6~#{>#6%>*w)Fl~sMGDN*ZhivZC>kL{k&8+ia zeQk)EL#S--uLYOGqB+`r0s45Lx#MWPP8Oyw*1yHg{e7@j(mLRU)XluVpf( zS@K6n{&0v|$8g!)KXk8a>of;UPv2_)WfvT+jpSgOaXts3+@A70vx?toLY~ZE$nnZko6gi947mn)?oq#9gL| zdyx3k5cLB?Wpn?@-C;jy`C^Cd<&tBXE%~qD92lbZkt3V?0U(~Xm)&jd`$DsRBMZ}v zbrh_>hN#12iRS*7raG*toE!Qvaxl#}r@=WnM4ccR(!9 zbN^S17TczLuJeQg(@by)1Q+Ex&sJn}zbH5OqbdZKQh;eDxEg{Ax#|icM02l@TUapG zzBszg{R&OxG@Xj3jA~$9m#eDgsw$L-=6+pn@xz{~5XjF`70u-A+8ek;m}W~<7q;5D zs#dP5L7QyuwKY;Lms>-_iMR1)8Zpg`x5L;lS2Z9|H1~#@uYsm=mh294FwHo3gVQ8e zH6}+i_a+*ru?OcKaxl#}Vc;~QMKt$jTC%gBEz`u-NNmYO(cD`iv8?KKAI}xj>|7&| z9L{9f+{3kK?8TD$5lI22nV>xc@wqBCSH;jFn|r*xtf0Ba;+66Cg~n~}F`=#Z(~4XYM6oPcsbDEbJMaZaz;}H1~Y0_bc}M9`ww8q-o+PBo;DJ zH1|S}#L=dSFCy`UTs4NFvbn$D?yxahzSv>ox#XB;OFk8x$+>D0IkLG=24b?k>~3?P z6q+@SEKD=j9I$5Rs+nYo=000f&D2!R4gFPeFwHn`g7ZeMnn#Xk?r&(Ec^;ev>Rh#o2+`bEzRABW-rMn>3u*NMF;4X=dC7<9E60TLMLM|4#FLtErqN`<@(3GtST8?8#L>kt3S> z9*y&p2j>@ZFwHo>f^&ct(cBMc$dC{*o!6g<2VJFW`c7NoXJ(Ea@9X{$mV`VURKcDPvMm}>8 zqt(Sj)rCWyrzf(xUpzFZ92Q+TG`K(kJv-3cakMTQ>O9fG^u?-J+}vw}Rf{Ik+-m`_ zz^)QO&AkqjG0l=2Ai4ffbu+_dbFV+N_yNkznggaqf!>Uxbt^fTW*i01?X<||emmZr zckMk>y1B0i2ynC-QGjVCxNE3ab1w-{juxO}SFjUQ_LpJwC^0I>Fz5uVhZ(nHK<~~2PbqTGQX4WED zR}59l36;%#MQ}MRTCVLEpx+HNcO0!%WMTSZyS%=iILzR+zuet`b4b zz49>UYX(fS!)0^7c35$9zeaPw^kJYk<7ibQ2h)sG6Pz1qk#5<69 z8xuuyzs)02nI_(i#3sX3V}{D+-o)KujkSES!|vgdW11~_3vj}Qsb=KJ<{k#bhxW3& z&AnM@R!g!l%~+9OwH>C~kR_UXTTRtQQ#m*EC~`2(I0@jy4O8vN5zReL3DyQkBnlk!;kugm59HzQcBAR=K`+@EWf&46W*G$f??aL*?G+UxUustzMJw8kg zpiMUSC;rdcdw@4>eR2O5Nhh?WbWyrIWLuIg+spzT5JH%NP)1t{B|r#}G6G3h1^NpF zLLltD348AuAnd*O-h1!8@;{QSLoDCJ^S&?t^s%t5@8^5ZJ@=j?ISDi5Q?ATfE;14k1&b?z$d>w+K(o*)HKOFe;?ZW8};iPnyyZFNixN}bl z3a1MZPO3i~`19?;Nr!NH`eO;WbMF~6vbLXlzwLOc4P;Mv;_wVQ7jCKdFK6|?uuBtIyhNFBD4q70A zck;?f{a#+t7^8v+PpS9Pa4dNZ1X^(Fv$qTGHkiS`^bSWYuE4u`<^8m77nB{9^S=I~ z8Vejt-oaSZXKxqF10@zMjQYj1)SK(%@AH~Wkud$&Lq5bI)n{)vibdA z7-I?8kMDv&+mGtAw@b@MU$ua7GJGefD<2eGg{vZ^pw>E&vBDxPVUx z$~j|jij*DP4{$~cPJQ-v!SP@Qe|H>?T3msj7L@mmK?H0yJI10ud%IX9H5LJ53H;ok zy#K~nTo{Y`?CoMHq{iZdqwIl$mYjgk5X!l;0wqSV>Xi=-r-Y)7WFoVA$4oA5%9JGJ~K65DNjPWW`V~ko# ztHBv9IQ7}v1@{M-!LLBWQLX_8Ex3SBAj&yoaEg>2+@Ekp3r>CZcESA(X7Crw;i$zG z@M%PO+ZcmZ7xk1F-frZE>d5tRzA!v$u<(i5f#J#t``V zM0wvB1nlA0w@^(n7WLWN#nM`hB_57)3+2!Z4%(Uoep*o!0Syd3uP8uTw;M`RTVpoW zQjVDl|HkMOK%iw(efD!bSai2TH(pm7jbaMRXCX=H-oQ6$sCl93AbSF=y;-)q|Q<7rJDFJDwBrkmKdbG6~*OuM3mAj|EJ7(Fucp0m+04j9iR^gAxFqeizu!DrrhLD z`8PG+5!K+LxNmEQmQ=GNs`ITG62*NNFqmTq6<6`VXfN`WuW728 zoDE-5KO~3dH=Cl&$*)XNg+KZ`9~T<>?fW72MX6%3v$(VMKrGvE~r=~Q28lNqbLCHhYYnaZ%rx)vX=ysyM3Iv)7;{PGFz9`PCgzkgX zehjId48h0~;owhb!6>c}oSFvjWGd&B1p13;CcHF>)0LxoK4%fB=Q0(FRYWrsMj5qm z6jwxc)!hr|?z{aub*KaI!lXvC*Wmk&u0M*BLzLtU4t){=4hZ)+#auz=VsTTeq=X!a zX!S0{#GR+eyGY(*lQ$^xDUy%a{;-6paYAft z<2Eg0a;#Ai$T`QoPvKwT2%nb-+86msFteDKGP9uB_iXap;4unNW)hk?*=BZ%EQF+& zP0AEm97rvhMJdTIXkOAF!CEVWl2Vi;5+xPiuxjN?K+(18U|7-e>WW5C*1w~54FzY_ zEXVz3pm96JA>G&@siGHeE0nYdUe0C|)fTBlR#;Va_l|y@+Dek)g|;4@4ZcyjzB@{~ zQj*>{bWaF4pq2EXn8C;lFz%tUYX19CW2 z5-rMEtFiRBu`NC@C~bWpV>-&Q&;pZWu2>}e)-9!YL??(8fdJ{ zFOmMNWZ=cCre3_?p`<{`psP=Qin1YPF3IR{wRLyFuTxuz3@^0xkPNH0z_@lui! zICL=xIG~jjp_njael2OZo`$G*B|lSSB_zwU$q0(9j${;@tU{50B3X-))I&)fO41l4 zTDD_KvhGUis2i^Vg}1^HS_JQlX6zZoQD*<5Svxk_CU}fQ$}9!VlG$eeQDi!jX>2l; zA_oAeC9^Lj8H(nE3=*uhQ79QsNhYIY!W&jCLn*qTyOO%Wd zE!zivVzrWn>c-ng;b(D#Q^EV<1baruD6{Kmc7;t|3LfJEW%dBg?y}8pQ{)RIpR&ov z6q)O1J(<~*Md5|ExeFP5 z<8^&Wl>A6Z!f@zcA>e>k@-xL$M5f%YhE~#4&0txItd3+9o2){SewaX1rn5rYS`ibXU?=UC}9&^-{E6 zMAan`%Q%vKQIlk+bqK^Afn5k*N+o|xjTKC@oswFRfn5lWw9N(x+ z(ir$XNys?^xnz~IQ(PhByev+pxZ=nar6j+gq$DLN3lc3MVPU5D zHc2_=tF@z226CdFr^-lHV3Xx2vO1DcY_bYP{(%#!X^`OZ)kE_-kk00&)Lj1Ww_7=` zHU%|CC@?J%Y!<8EA_lC6xpaj~Al|8Urj2KS}9q&vEI4cr}B zs&_KQ^+B#zAU9X#(kN~Sasydhe~KH0+;B>gfs!$lWGYCs-8hN8GbR|w)q0-hAUTsw zPN&GlNG@QL^C)sTPH3q?g3GrS%~wG>19#&}3fhX$CV&jPahnZjs#&pTJ8@H(B zIpc2JuBY%04tvw!zEhVxM)wDSyJNrVeUIX@k$VxyZB)5u6!%^kz0-%53FyTdm#a)* z563t^LheIKk`E=HP?E1fqV2{n%P@Q6=LYhKo+mSs-?7PWDAI`}&nB%D>Bb3(1_`F6 zFq-=yoq@a2LqR_wR2(3~Zal88Ur~zPgE8$a6L`~qN>9~clpH7%bko0&qD~@ptPJC( z|B~*0&aYE1{+Ho}ww@OZzL$0V4U}A^B=>RXI}mWdP5&*5d5+AJGKQP}GinAOQDkVi zUIAP7SD1tl?qM9cPf;jEkfYwEPRDaE1r% z3p;y8Hp;9BniXV|-rzB0%Ip_3E6Fx1PLUBvmSK~nDY7zFaRe}%Jd`fsT#`X^-_ht`c1-1z+irDi#u#_Y@sk?j@wSLuP~YY1R*`NkyDjV2)k;;wK`(+tL z@|o_Q*RNAI_!sa(ThDw3-_Lb@0hD}2Nh~<@_YiQvh3#945s`6}HC&!PP&3F=WFaKI zY*MDkl1To@CW}&JX(WH4B;`;NPD!eQM9X&NvaAc+SL(zoQuv=ZLapF^QG-3B-zc+& zXco;T{|+9b4rSI1&6={!8dGEUf2#8NI}oj86;1#$>S7x8OaN5@*G9pzzJP7NO1Y?qxl_3XW)hH76m;==m|iE z3!A8}-$RQ1B|^Vym5d0yM7i};l|@NdM9_t;6h&1+s(b|F!d66gkMir(4PFyoXzTf# z!MCWcuZ@!5DM@`C`fmt0;KEjiVwxfo8)3MxdDINXP-JT)Te8XK6xjjEwrnzqBL9bE zCrZ*CC0!{=ACPF-?iInhuoYJ)o<`xraD>6Z`(hw_M*S(X@n|-dO^yy8VBV~OE zt@l$k%W-=RG*;$Sq%RpHrS#&xgOZ!U%Xyum9wBv~6;^rO{kdPKwh~i0eLY?pd@Jbs zcTke6Tww1*Ngj}BKcxSloS~JxM=_rx^JzIlD+yEc{|QBYhhzaZnV%xujL0?CO=*%dSrOz{;!+pjzLtC}~(eXv@^6sAfntEzbz+FWtSB zU#AY$23~0EkznwxqwD`gNjpl?1&96*0uHz<=|nL-kx4CYXeBk(40fZ)fk^galYJ<1 zB$C6}#cM&y_Z5O#$+r~cM2fG#XeF(6 zceh`swvvMILR$}y!8bwI7eh&5O7aU1T@nHgXeGrdCIXo<6%4JUiJJe?6j>F?%51VC zMgERt4L123Mb<^KHYI6@l4wfu4@k6ZH>tpCC2iD+$5MC_j?g-IU&OO#)Pgem56wEV z$qvC|w4=;=pjkJzSyzhehh%Ry*^45F0I4N&ASD@z=EDpUthI3{8BIy1qh!h(R&A0} zbV048gSw&o2J&&qcj+ruM^TN1?{!{b+j3VE!s5j$xDjJ%QMut=j z?9n)tyhwh;CUaBdmq>m_NxntN*OY_@iI#0kMOG_GS10}hg?n%WSH+-9jL4pmlQJug zW<}X#;ova}Qf6Uj_AA@$XNs(dWH~ljmLj8o)RGxVNou0`Zw3k0T5Xj4PDx@=QvVIB zR<9zfmGo0rv@T`c0`GC6km|(> zYlQAT(63X68U`=4^%!jM9jWU_qhtgnnTSJYK)?ZaC1WXOCNk5EduWiF!6_8E2+8?u zaxO)#L^6|2E~UtINUo+NTTrr*lI#JAmhGL)O*uxL_;w0Eh9evf-WLbiGuls?T|l$5 zZ1QyQ7$+&Sn`m~8ZFYqsA0l~=P2Qo%=Rj)7d_qY~mGq0wOM?V!?H!clsuXwuLdhp6 z$y14S0nk?M!%D1HGG1NL_bKbI(fUgTH?|U`W;yP21C5pGMp`sTCIP6{cVU$HDg|AA zJQP&|sbZ|KX6o+0`gQ71;qXFRkJ1L;S-QRgN+Kvp6b>B;0SB~_N)+=4GBqn1?ky&( z8LUo`^^yFWP1d2vrbx!J$ry@kiDWZMl7y1hl%x|#v}|`^Zpyjp#M@DLDvpp6yf3=2 zXY@bHtUsFdVUy{>WAvoVMxfbHw%K5c9FOE!HaVIirvj-Za}p()h33-@60EiPD49b^ zR-k0r8&+)zvz07VS9B3&y%DX~Q8mkPYYa42<~^iu8zf8g;(dyeN5RYafTFUIdcg|o zfbJezS!>m5EBOFkXzTHA<-n$VP}hHqlH8Q!3%@1D<*RIHC3z|4J7fw}HnfsuYX0+6 zqytGCo3v1*2T2#36e+R@k_9PANtFCZNy>mk%XX>Ctn1qmb>hEJcqEQc5z=h<2~K(T zj3Owr-_fiFoBSDQ@4eFHDF^~i7Vy`<~SDEW?(IB{qm0uHzF=5TBBJ@wpnwE?0{rjHkm|`{{vD>W+zJ04b8h4Bv@-b zQIbkY2BDtXm84T3|fz*YL?@M8)&S|BX#svacP(FN7m_>jv!$nLQ&HW%e_gm0*)U29HscGK)a7GHkQb6j=qyN^G(MMb-dPOJ+4n z@+X?tGDxu2{zl1Pl%xqt8ogoF8rEgC5>q~ik*iNxw?^xh3U0hBQEHasnj2``&fSpi zVvvNuuxfp$qa-bOIa4WW08)KfVdd7{hx&EuP@~|5wjRR`zIk+g21>?IlBqcKBnUX5 zl}w%mz|R<_k&^ z`nP_$;{Fc2x?rt+fRcA9$!93Z`#0+Xpsm`+f3sT2XX=XPp{&0{>jDaHY$Zy~a$J4` zjg?s#X`eyzC4g#umqf{re+ONCic(Z*q<&$A^}X&M;n%4{Re~4VdXzW#{-EolP!dT= ze#fC}K)?a5oK>=~s}X2Z~IFq<40JVt-YECbEPu+2tM_;~%vR!1S9Aqsy#uYcQZ>tQn+-Hp=2@gq z86=`!yjM_iF?c!8Q`9Y_uCu}_sJq|y>(o~A1YT(C@zCH~NY}qa$umk4S`WK_Jwq$W zrkFg)d{EEON?dCG->VmRA;EyYKr$bj%uA8qAz6S;=BG#-l4eRGqQpT-3W7w-wx=HJ z`c_n(xSPU%!V!u?nhoD}EykWv5y~tA&C0OJ(!pc=N|{wfv&w9asFoWm$;0#f5xVU^Y0r}}m3P_y8LwjR?Bz7e{9K1$|Ll4Usb zVq+^=NHJ@W$ujPtU)2n*pvbLAZeo)gC~_~7yV&Foiad@tzS#B*=8>(@Q_hnunwPb!oNxneyd?NV@K zD^Y5e<3t0E8Hhx>qCpY`pjzKGP*N>A=;~9IqG}`cJ1eYc-MyY)rw$bZFSPZjZ}6?J z>zkq^mXgHd(9I#>fDbtTP)s{yl8k%kH#LI^6q$@eU z22hgGAknftg1ISU)QJzH@F_UL#Nd4~o;{;+l-WEqo6RO?29GhFGRs7>C2X@r6uB13 zRcvx4MQ#RCOXdbjvIEVx8YEb2dr`8Bk{n0LkvFW`A!aLSqORxx%K9Q&pQCD)=>%LUY za$Ii%jg>hC>4^qOXBbwk@7XAs5xkt!C~6^6^H^bZ*WH)-b?Q)A@IqUU4PhpG|&Akrp7eWPVRc9B6JcNU+viC=n=0QIr&Fz`6ivtLAIKY9)Qt74=Zo zrO^6k1vh@cQEHasN*ZX)dLyJ87$p4xRO`DLN}2{QXJd+LjZ{lkSYvhfwtk&DR7ZHB ztw(!JqbjFQfjqz4Y&4FV4MfYX&?`XSTXxQ7O+8SF)o!;u`qCI?Yu29jggG7BZsDaj&`XxX06+>{g4iO;3*RXD05?M1U) zY_lB{c@)V*Z1Mm_o(57&<_Su20nN`EBv@-#QF4ir+(*fsH>}z%W-FPZuILTQ`XyRF zqiUApo)~DX%z_Q|ON*yrV2_`!7jJQt6m1xEWhhKhzasThLq><2ue*o)b!scA057!l zh%opr(DhYNQi+n(#G!wKfCE}d6vfmkX^6LMghS4>+0Xie^&Q z+t7M5RkIwo(LiHmo<#bXL9$XW-U}!>8@!ySDe4+hmsw$L(A{tQb!sbl057!lxNGp; zsOz7i-`)4~Yrvv>4E*NPf&F^HAj1NPfvCKc~na zko=aC*imAoBr-^}Y)dh$RAxfetNpqCMy(HAa$IWzjfKz?=~RPcH-Kt=_eV*e;N?uGsG&#=Vuf{BcOT`~sY7MJ3vE5d z7<`ZD`pGDnKuKod(9_g`dX}&IIp^Q|uX?pv-Qf*)=wKC3uWWl-VORyU#Ye zOOdaTe9k7HQe5xU-48&b{X?Pe8YEb2AEP8UCCQJHFB-8f0NSd3)`-mL-{*h-X|<+$$*G)}L66McGrHwnzZIRMrAZi13VO@gjI4JoPxQvWnz zgmq7MPw?y1q1wRNm6j=WC%E*mHbCB>ByutG2E40P&1fHk%N&O zz$W`qlfswd2up+a#bWl17E)## z&}=Q6Tpc_{7G<^*&9<@4wov3jB=@n&JrsEyNG+L1D9IT#KWUI)tzAUPIZARHB{$x% zYS)ya3;KZbOkL3{l=V}zenizQ$2~C6Sec(S)mus4rh%>GrCz)RQ1VsNpjPq)MVXQM zt|_CHy#JZMQQ7@EwUtQlLR$}~!S@4Q??s85k`%+C3q!yGt)w8u{EEy^O%1IiTg`t7 ziY$+0SvFaQBBPLuWRsOBvKErnDM=la{7Fe-K%!;4ep6N}$pbm(xOx=c0!R2KcwaPS z&!{nF)(*{**knTR7_BI?WHjr{HtR@{X-IZwlPMJ07f3Cc>6By;n)f$Iu-1m7WC$gh zfRb@nIcIc}#wz^nHWmGrf3UqU2fdaz3G`kT|_Z zK{W^8EV*>|_x(Dxm3#y*wDtHfF0iq=b$vdRd_qaS#-YEAGqjS=DaL}#_i=_+@`alJ zZz)nj(#a<66j=yKFPoGpvN)1ODao%W`H7O01BsUH@Hkd0@v0LKqws1tLKR4};rB`^ zvu9M1GW!e7{$P`}g2$*qnZ=-4eYROWifo2tQ#RR{B3lEgC9@?ZX^ZBG1_{<$N0hXu zB;8Tc^$n|*tQ1{PD=Dn5=zo-TKeX;m)hx&LGSFC=3)<)vKetU_@fOpIHxngG+5~Nx zMHICfsg-RQt)#K;zQM0kTgg^UzgKraEzY8VXDak<`dLINFa96U2VooA+tc{_S z6j$?qgd#5?d7e$4rN~=IUT2e6De?i5cPYs;lsu*+x!UU4&ThkMCI6@se@Wqa0Qdht zLfQuHi}%_xv-nQiz)gnB`X!ou#wI@v9^(_r><2XamTgvmBArO`Y|=`RGLYKVl_*Ie zH1`@LSZhC`qzEMmL&>jg=~er=EvuEZR9CblWnCGqD=4_}dnHQEa$GqBjZ2u0beciZ z8bGza2co23@N)K{sNqNrVTF~VyN~hf)S)K83vE5d8GO6x`l%?HL`ml0&@&<6fL1b{ zVwNDY(71;Z)eO$3$kj-$WRuG&ax;<}*yK8j+==8iO0pj%dnn0qkZ9RH!rYWS)QKOW z@QXOYx!`?qhCQQGl-X@GyTK-}1&?usGJAq%57}n-DbmzVZ;vn8a9jldStM)}ZRx3$YSM)Q=nn!Dkf*V_jQnMWQgMr5B z6-T6X0w=-N%`>7eMN0H5ujAN5cC^8Aj)@(AKBL79Q9VJOdNoPuu1`;jX z-I<$mggWsQ3Ll6g^b6h>eb_Tfr_4s9*$6f{EO?9|l-Xo7o4_{9pvc)s&R~<%C~_f? zS~BNRl4WSV*dW1L%RzJ)%jJl$0DC@mwy^E?@j@x0Nu`@1pfFkWkS}BPOB?2WW3=%EdzV@u^ z+gx?x9t!^jM<@wtHhiz7ID1CLD6{ftR+dec2_B;~WmXN%s<6!}Q{5sq*_cwgLQ&*(N~X6m4~|Cem?dGHudDYFmI?A;EA>w>nJp&bIRD7d>mMe<`d znTI030#Zxn=al4IH2>Nl!CJGRz@}{X0r(bO^fo{6!|MDz^_w>Y78&5^@uU}9@F*B zP|}o=B;e5T5OBZ;oE8-GFEZ_nduWfE!8R0`f@CtA{Es5jkxXNgsT4T?$-b0i7)l0H zl5rr>vOSu)DNm{sA4%cUafB(s`(hG%MiVHrg=jX9P0k4(V-{t$63sH%W=kn@1Cndm zpcD6$fg<=JEeMOH(y3MKg+B{e8X zJ&5_?9wrqnXGy zb5djxBnz@hFGZFFQcLEKl%y1z|7?(8t(8Sd7$vESlFDybwTc~Ctt6kiqU9;;Khe6D zf*U{JC^gG*H4HRvr+B2B8zf%l?pGk^++-J zT6BFnO42CFKpeUs1RQWz(uZP3A~VdmhrUuXID{f6BALM^$5P}>B&V^-DHJ&$$vKo{ zDM}VmlGPy5vb~bIDS36`%PD*-j<6|sUu zB}&b5Tu7(DD-%|x1?le%5*L7KeG4eDcM7`t*eJ?_l#3NsG2OkeU#AXL9A0SaQPkl3 zqptr2B_%0ISsXeH0uE>;r6?v6nTnkZ*Hc-|V0ntHg=BR$S&bt9M)EH<`6orjAX%T1 z#G#}yC20*3E!!^=_QCt2Eqg{ulv#H)>&hmRgU9%fGV61?x} z6gd>hL2PmWMUDniOXdhlG9Jyx8YEb2Q&2LIlFUQN>^H31Or_|8KH&VSuIO~idO2Dz zrD~Sr78_`+%uhS(jp*aff!!udFW&qp`J!`BEBTC~zDMet&WsNCo9=G&>$I)~FSPZr z8+@zldKo1WB`JbK7leQVT8WopenzH5XG1FqSM&cPMMfZ5hE0~H$SO!yVv`jpvIdgX zC`oOU{7y+4fJDo7z0RywQcIn9T?%i8BQy=(7me97YDAf}L9+xl*(!L9mXz6lXx5Q! z)`22ZkxXHeT`00QkXkZ(Qj!5^-q#?(S{sUzL6jr|C1c*OYNM2*3u+~`)fF8GPLy_18zsmOvqg*DR0d5BuI zwLDW_YAf_uK@*#q(n3rjq3@eGQ*x|MW#^E+pk?oNeLdF@cy4GjobncXfRA&KxfNNf zq=X!S)KgdJ1DgLT2md+6=cD-_a`4|$d;yxb=isfh%#}kX(6Yj+Oj{M7B5Rxw8{4=| z%NSEysJ=E$)s%Q>lV4O5?HBJ$Dl+4aDz3cA%5yQ=w0sWJvJ_uNIbj^FG;LZfhiMhc zv@*^AnS-xI@il0^p2}8U&D9;y zj2@y>jv+c|CdTj1D18BblO@OlE5DcDBP65`Jj-L^a)pHSg=e{yPhuhc;2CrZE+ljy zJo{dG_Rb*xvyV8AOM~a8xR#A#TP6kEaHJ~lCpB!Iqr?-{NV+K}8Ybp=KTG{T7IszM zk8hKd<3!WE%7;2GS8wH1r&y+Df3i&AXqj%m7 z;l_gC2U7?ak}CtAsj=r8uRjZ!;D4sfVl+HwMmthD(Y8VJHn9P-8?L+!Bgf{5wk$-; zaYL0eLDN%aF-|=bm(;RN3&o2I4TWhWeG~$LPK8rHm~uh7r^7RC31+}EZ3$+=Gi?cG z!83Ilp|iDTxs>21!*gcv6O|K;D3xfYDd!rpllN{O(}&Q6LQN)9?u0MCxOTHjmzx{z zmCo#6v|z|TQ(C?Q?}wMHTPra(A+c`z*o64@b<4&kHcN_cRrmL}#5N6@*NSZ%C%0&j zm=v2(H==B1xnjk-?TZzuTRpaUY=gwuy73MFsTmI2Zd%W}&y%Vuf4<)CGUWshZ-rI+-?^1|}W@=Q##rd!8bCtD|4cZvJ0 z_r*)rtJas+WZP2PPTL;-Fh9UP%s$AzNE~7xEuObuvtP82m0sDqI0ic=IfgnGNy8l* z#gUF};%LWXajYXtT%yZ21%uCJ7%`468%p1&G&6mwr%#Y14%{^e&>6U($ftI0`;g&I$ z49jH8bjuRR!E(!b$iObh!9mMu%WcaO$iWMXmV=3qh3VGW)-~4s*4J5BZp*T5hFsjW zb>oNeGx#iC$;x&96=Y_ReF$V{hCR!^$9^6%a~blZdP%*dK2l$4fHXuJDh-oH zNF$|D(r9U{lp&3mrbsiTS<-B2t~6g-AT5%XO3S27X}PpQS}A2otE4s3I%&PMQQ9nR zleSAcq+QZpX`ggZIwT#Ijz~wPW72Wygmh9mC7qVeNN1&U(s}8EbWyr2U6HOz*QFcM zP3e|&Te>6NmF`LRr3cbO>5=qUdLliQp25D#mb$pQy1KbiU1_eKu3@gPlN&)bE{5H- z#Jm{x(-QMCIA+3eIUHB0`)h?c3wGHmIIf1{8aS?n<2pF5SNGm}^G4W#o8Y(^j$7ck z6^`5BxE+o=;J6cxyUZiayW!a$^CI(J(CveF_QN{|;GKi;&LMc`FuZdF-Z={I9D{d` zLtH0dypwR|6r4E?XU@R6vvBqtoI4NaE`aJHs4ju(GN`VA>ME$Nf$BP_Zh-10sBVGk zHmL4^>Mp46f$Bb}9)Rj0s2+jpF{qw^>M5w6f$F(=fcXU|UxM-#D6>JCY&qeT3$fyy)>s;UYUDZvdz6L$xw$~EWIts=05P~Yv~GAnPTa0 z>1G*V=??XoY8hndVHs>mvkZZn9ct-i83x2~AVygFSVmg z2Vw#c6M>in#AG0*05R1v$2<+F=|If@Y9>&#fSL`|9LrGiT+1-?Jj-zNe9H*)0?SDA zLU39HPK&{52{R^Pl5Ysa6bd?XTkj(xSt323*dec+%JLqWpKX&?pH1Q zEY~diE!V;Q2Dsk@_gmn88{F@J`(1Fq2k!U5{Q!f0zRVT?6h7;Eh|*`Gp)mfS=QmgZ0iVNj&-Ck*E&j=XB{ofw~i4OSjP$rt>c76 z)(l~>b-b{|Izd=!ohU4`P7*S$lZEBhDZ&ctRAHrcnvi9kF08W75LR1f3Tv#hgtgY$ z!aD05VZC*(u)#V{*l3+EY_cv8Hd_}8Tda$Ot=7fDHtP~$yLG9s!@5k^Y0VUNS(gjD ztt*5**7LT#)(f_M){8c{*4PeMFWU}Uuh* zZ`)2<@7PXR@7hjV@7c~+@7vB=AK1=WAKK1aAK5NgAKNZkpV%&0pV}^4pV_WhpWCil zU)Zi$*I2H@{rGHae?HkZfbRm2uC{@Eifs_z%{G|t zZX3d<+J^EyY{U38+i1*IpJCuL9DGKA&q&)ueiZnO2A?tDGZuWtflmhbj0c|ywn_X%+hl%{ zZ3;gbe5QcURPdPwKGVTx2KdYbpINr4{A}=<13q)XXCC;>2cHGtvk-h1*{1P}ZPWQB zwi*0V+f06$Z5E#ie#>pM`4zS~{7QJ91&>wmSPhRg@K_6vb?{gZj}7qH2#-zh*le52 zZ?Vnex7z0O+iVN??eN%PTgdOUE#h~ZQ{?`HuL9fTln*~ zt^5VsHvXb*JAcWxgTHLs$zQSU;;-6v^Vi@G?z(L+f5WzqziHdg-?A-p-L_@A?%0;Q z?%Gzk?%7tl?%T3l4{WPk4{fVmk8EpPk8NvRPi*U4Pi^a6&ukl9&utrBFKnA!FKwG$ zuWVaf*|x2&WPY2g3%}jfmEYk?;di>a@w;5z`Q5HmevhjMzt@$4d>6f zM)2odBl!!iQT#>MX#SFG41d`*mcQZ}$6s}2@Yh`9`RlF;{0-Mc{-$dZf6FzQzwMgB z-*HXluM5-oyRPZ{J=YBWzH27`z%`41=$g$xa?Rl%yXNvwT=V#+uKD~k*8={Au#kW5 zTExF_E#_akmhi7!OZjZqGCtXz$#-!t=exRB@G0(6d$`x|Y3{Xr zPxm^$mwP>*?%u%nc5meSxHs{A-JAJ-?k#+O_f~#@dmBH{y`3NA-oX!c@8pNLckx5r zyZK@6J^XO@UVemoA3XN+Bi#r1QSO8MX!jw0jQcP@)_sJZ#26Pj_GBXSgr%Gu@Z@S?(+RZ1+`uj{6!v z*L|Iz=f1(uci-d}xNq?b-M9Hg?mPTq_g#L8`yRj4eVQe&$Qom&$8cf z&$i!n&#~Wg&$Zuo&$B;p&$mBxFR(vyFSI{)FS0*zFSb8*FR?#!FSS2+FSEaJXWC!7 zm)l>tSJ<=NEA7d0mc5I-%HCC8ZBLQc*t^MV?cL>d_EdSjy@$NPo+fX!_mnr;d&!&a z>GBqPZ+WY|kG##^SKe;#C-1QLmv`C+$h+(V<=yr{@*ewOd9Qtlyw5&V-ftf!AFvOX z586k_hwLNe!}d|~5&LNQsC|rl%sy5=ZXYL~uxH38?c?QB_6hQ7`$YMSeUg0EK3P6z zpCX^PPn9p&r^y%X)8$L{8S-WOG5(7EIDgeXQ@&=OC11Bs~Sah#W@ zIxfi592e#3j!W_k$7Ok@)w%=;=A^=;b-$NcS9d^!6Nc^zj^b^!1zo z-APA3&nZWL&uPaj{tP_Mg8w|Fwa%TaL+Zz z2+wth;f7v=Z<5n=dNR%=bj_ObKf!E^T08|^UyKT^T;vD^Vl)j z^TaX5^VBib^9&x(9n(B79Me57;ql5b!;|fp=}C6Z@^o>|_H=d5@uWECdb&C1dAd92 zds3YXJUyHXJ!#HGo}SLdo?gx+o^}FlrypqhJI8tkI9GTEI#+rI zIkP;2ovS=UoU1)UoohV9oNGP9o$EX!oa;R!o#Q;CoEto&of|!4oSQsjotr)5oLf8@ z&aIyD&TXCv&h4Iw&K;gf&Yhmg@R;J<<(cZ-?V0A>zU!)=b7o;@0sO1;F;|_ z=$Yd@RI4C=2_@G?pfqK;aTiF=~?1DZM^(=Ru z^Q>^5_pEeY@MOVbmGh!!weyl^jq|c+t@Da!o%5<^z4Mx9gY&v)qw|Jmlk=u$v-6f` zi}SW;tMiU$oAa(`yYrrBhx5K?r}Kelm-C@#xAT!_kMpr-uk(p#pYy3_KRgaNpLq^C zpL-5DUw95XUwV!>UwMu?vpvV0$=>76F5VN)uHKW*6z?f#H}7d@ckdZzs`sq3hxeQ_ z&3oS2(|f_$%X`t8?!Dyf?Y->m%Hpi=e_3a@4XI>8_ogVo6dpWTkyE;9OS*@ z9PGX89OAv_9O}LA9OixC9PWMS9N~TB9O-@R9OZrD9PNGT9OHfF9P54V9Or%E%<#T+ zj`zNDPVig@)P?!q*0sxaN#Lzv-B6J~mQ3bVYugxTJ7 zVUD-AFxT5hnCI;)%=h*a7I^y$3%vt`Mc#qJV(%bfiFdHD)H_62<{c_zdWQ+iy~BkS z-Vwq|??`xz60*Fbg;m}$!fNkWVU2g3u-2O)tn-c+)_W%i8@v;RjowMZChufnvv-QH z#XD8l>YXNR^G+AGduIqcyfcNJ-dVyf?`&bWcaE^fJ6G82od=Kk!anZ;VZV2waKO7r zIOtt09P%y^4ttjhN4(2~quxy6n0L8w+`B?J;aw@5^kxaCysL!M-qpex?;7E(cdc;F zyG}UoT`yelZV)bdHwu@$n}o~W&B7J$7U8OQt8mS`O}Ose4v!shey4E5yGyv~-7Vbm z?h$T#_X>Bs`-HpR{lY!(0pY&)pzy$Z2s{o854}f(N8Y2tWA8EHiTAkh)O$jB<~=Dq z_ns17cuxy2y=R11-m^ls_neUIJ1=zcT@bqZE($5WOF}o_Wud$8ijeBND)jJO6ViOw zg`U0}LNDJ<;c4+(!n5MHh3CcZz$clz!ZOD_p;v|bLVASg+3J?35SY47N%RC z2m|@2!f5`P&?DlxkQVVm=v(2X(5J*Jp>K(7p=V&L99SVu98{sFIJiPD@o>>}aY%*U;?N3x#3M!fibsp~6Bm2?i+#)k#2fNJ z@s2!5oaY-X&i4(0$58R1dziSuH(Xrk8zC<8jT8@xqr}C&(c%){7;zIn79Qiom+lPl zfp@&P)H6ZcEKd~gcqfU6EtAE=o+)Bq^Hi~)d77B+nJ)Hs&k*~YXNm*Nv&3tj*a$G1`3>)Qm6&Ehcg7O{)4Rov&> zChqrbhsO@_K;fO@bIUIAg0LGNd&J@9z2Y?YKC!oZzj(uSK-}j(D2^~65{L1J#dY2z zVt3C`aj9@jd@dgscUw-t98QW0w9eICT5V31Mtk7gy>zhwn1Kw4}qMw=~<^N4jY4E3J0-lg63*!?^*{ zE6YH543fs12TK#oL!_?0q0&OnFsZ*hT$*SeA#HPyl(xA>!5E{Z!`?B{Dc@M>v~L_d zGNhZf@zN7{f^^0=Q9A3J1dqwmIo}lNyl*Nzrb&~`)1}Gg8PXK%JG#4c|-Yrtg(>%a<+P_9eS+`?|Q6 z%UxZ)d?~I4=5DT|uI{dd=2ZCf*2A^PoaVYB_jH|e_j29wrMvF>db{rV`nc}<`nn$Y z`newZ`nw+a2Dl#k2D+a32DzU42D_g5hPa;lhPqz(hPht)hQp(P>C5Ef1x%(-N-IC6 z_rx_?+B%fW&Ni7sOr;ygHc0aLeEm(PWbGYKqlDO)q_(l}LlyXW5NNpnl&1k-o|w4i zeB&nSd%55k!YMzY5ByR!O`5B3hQKj|%kl;)OeR$m*HV33`RPsw7bMX%@Hg_6FXbma zAzc5jl`(UEsXmDv)VJP+V+eO;bI$Y1b5#RB&r!bKgGUHg;cN9pj)M}zhu(rk3l{d7 z@vC6b5+#28u}IMpIo?xF7WDaw6)OgR7A{e|U=ih=`X8E1+1Z?_QR;u={)#UCYGIzq zM`u=7+q z83tWxQ{K`!6R+sT@FtU}tU!)0)cKRIoVo~)P0k!5c#1mz0w`zO#c-yX0-^ISf^xQL zipgZ{9T*_``4>Xb{RuyA?e$6Ek}5h#sI2VQxaP45C9UuSzG?~aO%fWkFqeaO63s&U z;>EC2V2Qfn@hw`kX&IN)q3-YDb!*1QH&3iv zr3O4LSj1E4M^B*=1q=G>HjHaow?cek(x1hPsXr8qDdcI?yt&oim%%sv1P%!NzsX|n#FlyOmd_6M3ekioJsz}R0Ixxnq>GH zV?rx96V(JBa5Ac4A(I?Y0iIPUYm&=%Fv;cOlA;>^Q%?D14FB`84U!tb^Z5TCf9mNE zF}~qHVBF~cN8{H&Syg|WDwj_zT@8o;uY%#>rccX#_xy_@ z9Q;jblc^AF-p{^CUfS9;0=9Dg-#>y*m0wc&RsQ66;CF`LPnUXhYwx|UzL#%i@&Dsl z=xY|&GNyT(M(`71{~9JXXdIiE)F7srr>Q9~x3pjDLGIqm8lU~@<*bK-rAWTAZ$E;z zOH_N`*~y{5c$2mjs`0Sm^I*ns=9l-oohR$?y|6-=PlkpXzBQA`4+ytdu&32>Rrkl`>1o>Ca#dSO>%d- z8oNJV;s5)j`%6(@-ME(UivTSfG}lVBd0azvpz*(N3jHYc`5fz_LsnsIrC;;i41ens zDaEgv=RZ{N!1&0JWzI*(N6p&);l+F_>bfUYYsDl?b`+QwC*JvNtXUdIySKmH2O8BaIQh}ZiyZkot zukO+xWAhgI;6g4_dW zmnv4;)b(9cD3>?GZc4tP`~&@_T&7mY{#dnKSk{f)E`y-^7j?F^1mKX zV6pMXR-G*gP(#RME<@9ZD4qYu+S2Aug$D3mCR&DL%Yh zB98v8VwcBnm-O1MYUv79qbi3*R1H(@YPD?8usOt@6kn=n^Y{jhN)>J8AD|fwpikvH z#Z3JN+99^Kugxl!u2Qa2rSK}MRd~||&6~%zY@%c$DIu<9li;B8D?Z=(gKGEMr*i4? z70Z^5EMKm?>Qp1HNy`RFZ4$sKc!vIT6;Q0c_gi&9s~@YCEguzL5h5z4WJ~{#mE(UA z@`YEeR<%r6h49jT9jBPv{N^1|SFloK#cE~CR;X0ERAIj|m!jnT%1)>(78y|~yjqn= zhyzx|SE#+ZIDY0mg|YjY&d3yuh^SI2tX##)5PPtDzT;p0Usn$ETA!Co<(j|BTQ9=e zxzHy|y3}cW>*FO&O;sam)(8))77?v%;^%M$PIKtColHi^6T6>OU_kwr#8En7CF=V-up|S~iZ4hTp3* zB^T1!9l-!Ye~WI2q+%^Hwu*DMoF*(TPx=0Xb3r@3yKUqn_Rk zl{?D@F~{ zmaFrU>*(v7V{`nZhdQyWa*c!Gl|B@mr1Ur~mhb%;d>#-B+)O1UM#EhR#*+a9tyJQv z9}rK=*mlt^+d$mNo{{g^9zi%DF_P^?A=^Zm%2}3e%P6{)QrN+aM`68XCQp zn{fX+wG0TOQEV)f0c;1Ha~X(bqZ&){PY_Gn__#(nE7Sw0;VZXkV!fPQB`h4$p>Kup z0YgCjN5`~i7484UZmkhi1e;CjD97ull~A*Ktr|7KBagn@R%_K;t7^sHBdXU3i^Oe> zHJlKu?bz6sYAcLwq)oJvo`lP|iB$8PDUI|eV@5!vaf#8&vcxvR#S4WncdB8|Vdg$Z zAyw6ft%qT?jcpD$_5QG``G*`DFl1uWxW=#BqXfh4Q-_;gR_$Hdq@!zwm5GdikR4}D$|YI1b^KlQWQYwK+z;?J6J0jd~PHRnjRb=|wKXQPLO z+bdn4OxWMLS$OrxoSWw_%_ekoz)JoLzXKdl(8txp#YKRNnw5%GYetlZ-jO5lx_+n1 z|CrPws8*|t()3|5upB=I$w}3zmVaNV7pkLrnQYL?19w8s1&`4O-=+3vDlD>mRP~%rO?Ax^_LAhN$v9oQS<6b9sHn(@u&VG|_-Zfs+ux!h zs)k30N5S5&s-(P`4sF!;Wx3+Uh0JaGL|Z7RJ3tEStJJGJgpCa*XVfip*QbV=<>=2X zbxm`B9W{z;0^euRcB1mH#H&#!gg0**T_vJQbfY#c;9u!8B`4`;Zv3q#|Mk6Mq#jrP za(Z0lBjDyhzf|Q6u&wU0N}G0o5JvGAWoVm#mJ-(z{&s=G5AE7fnR`){xpk>an zF736kLLUV*c;zbmy20x=9+ScHscIR|=u^0f|JB3)L0cH@rW@jp)^pH22+t8wM}I`W z1U;C`y>ZS>+*uDLs<>XT0OVNb|8zluv0!pE-v8;M``W51 zRSVO>B~8IwAC~h8xO_w#E`zvXy6D!QzrK~jzM7(+Z1cK0s@JZjR0iI*G{jSQS@+*N zg-LpWF1FGCe)HT5;m+ zdgx<(q>Z6A5QttMz!aAAQ$Wl3MoOz^-G28}hdLH!NF!Jsgh1dcv|+$*35Zp>U+$$E z%)(uOU8L2!DxceA(?W#X$BN}@M^_809##eHyX#x_EA6y)&4m-n|6>-ua+}%*Zycjo0dcpAZ-v)#<@T<(8um|kz0mG0aD(*G{aZsLf^T&~_LO!6 z_AfO1+@?tZAH(9b1%9CipUAEsoIqcFfDPESYSq+xaL$&c{0|k>bX@d*^r={*MlHB9 zhgB^bT?0}Yru60ky6ApTY6L45s{_9n=-5jGJ6-b(mSav+D4d-ZaB% z!nZog)T$Ygb16q^Mxl{8zOfKcPhW#zl$wCH45u7@bF>~(zTjK>9Fb!W&aKuM%=w;v zrxc~%#VX%s`2UDI_c)!Z_W#d~l903HkU>M#N)Bn}rpcTKX?jG=!OX~v4j$!6DwUd$ zLn1up_18lzM*o3RYrQiJ9W>{LSO&9Cwt!}-%{0Z&I>YDXgk{7b5HsXn%r`)x`VdcKJDnSMFBoebM`JBcon1m zLnnW7r!+WuD3C2F*YQ@{8$ODs!Pc)}I`_;*Xm+kWBnRc2BKM81Tq3Wz+Sw_#bGj?x zwjS2IfG6Ggc#k$E9+27ZGSvYZnB*Klzq!lyQ|}vxQn&hfG?lyAwk*IeJ%ZfbZ`P)q zZz0 zhO6>+hNXgMdg&#Pf8^7``%B+3=>eR)WiED`D0YTAu~Tdo$<hgT(@X!I)DJvz}`xbF% zDH|k*gl47O7BfV3P)vpAEzRnr`P6;=ud#*4JqvKjI zcR`h6knc#p%zn&z3jXjzgWb0>@&Q`BM6f(YDS}llL7u;goN4P%%iBHu!QNud;zuuq z`}(ua^x`G?JYt}q|0pHC#;v`|JHS%*9XDm8yvdfbD5dU3#ZF?m=FS^`yyiCCl(oyIAnDyBQV3XXJr>DE8n)B?X^f~d7oAipBB=5l=yGi4` zBP&xjxhZRCV>-|4fFZrYHU0~!RBu0V8=2*WDb?G}Zqj?D-bCc3<81^zGW*m`=tbrP zkGRog{0PAV^uR(sM_D2*Pss;A)*oT8_ib1CA2EET0OTXrzxCfp(G`z?x~Et- zJGpMgmi{zTl5Ka%&dQV8`+4D)P6~d+4}TV9NL1OX?k8~3)+f2)%ke{n_~@qWW%R=a z`1U{ewtjT9^MeG@_&I`T`5}8aI%ben@i0;vL`OS691#8RgVEMA|7hnk#%O$AWaT`9 zoI26b@>75Oh@16co7)8bb&9feqod_V`CJ6`Ly&OU<<`$9Mn~h@$MJ0l@d?B-VSMo< zz9=7qkIrKT;k%*M%aE;-T~uUs_5a)dWi%`*S0_3uBf9ACsEjt1dsm0ou76qCn4-5V zq$@U7kE)VUW^rsrsAwv_zZ3u8bZu;^csKU8jB5D$U$N^(COjNfbP1MB@w>63hmVfF ze)RBR(NR6D>um|ve+;jSjp|;ed#E{LM)kDrQQh&gWEU?6Q2r3g8)L=$B;GxC-RR-N zD@7GmwA44oLaYb=SNy)h0jA@Xq7v+D_#?tWG{gB6IG+$puEp|vbW~AIi{+Ep(IaMH zBt}fMMgrH{Krl1fBEU7gg$NMM2)>9-b><=8mA@MDTx=VOA)1MOh3$yb^@R+rvISy7-64SVss8 z(G2T2u#UxwUkGbF9RkfQs$&Y(FA9}&ESw-5L^GT-z&RZ&P7%(e(m1CToKqT{vxI|a zhVwUY&J)XYcgC)>#^$^t&6dqYB0w}FC>NJ1%EUP*!%K{yOq_SCGJ;FuoRb>SjGz(- zE{_wJ5yZW;d0SbdaCzM55i703ag}{IE{!g}OrdfPkjkbQwSiGHPE?N*Rf%LUEsj`= zq-LCZ%cu?lzL%;hOwOvkl71-4c6FSnA1CS(Tedq@?Jc;g6{PwSx2^)mrm+z* zBAPKa2V=815kr6@O7E;@3SW#uKP+t+v`kDacTS!8_SA2b`Hi&G-A z-bSp5W~@EHdS{&Y7lFPCP|FGyb+$n71Qs)g#s5;)3!rCMcG0?q?;gU=YB7+ z`VkXz?)?C;)pBqi=YAh4Bbq5c2;~8BqCbgq=RQE5YyA}tFnwhEW?aJq2?x;(XE1OE z5es+jgD^Q?SZfB;C7t^=n*i7FBSe5`M(}u?&bgO}JwalKW@1mHyF;nF%()N6cyF`j z-Q(PgOch5!aTqBw=RQoM_^heoSSXH(6Qf9!JNGeig^g15*$R7}h8)ps$R`13Vw`w^ zaJX}y2#AlYVVBPRg~(Ww2@BB-YZkC(#EEHy#hm*Lg=(5Y<=oI;CLBaFoO!^R8z<%v z4s-5v6`VO5ocV-$B9kE#+~~X1!=Ry-K4;=g|w9z5zQF?3&yYF#FqrfocmV_-RXhU4!=%WZ z`(Y^hS+Ad{uZU)S{T0ebNtrwMqlz@vVu}4YMg)jv1b>3yk2vvroH#)o+`0e3j}Mrx_ zEilr1tr_=tc44a63W_aBk$Lu(8pYP8im^~^7Zz#D_%(0^x2w9`eK4bM_88pacR!Gz01cptP_^At2_{(-fW*l?VGWD%_cH5Y2G@ z1)Pkq=t?-ur)MZQT{Sq}2nW#&rzdcF5DWL|JydCDsq`XkL^JK)(9R}p?$EP!+PS2S zXr^5V?Y?2rhvb=pPpM5d(AO1LT(N4+6et z?o*f?i#d=62hnVBhJfwSuoxT`gNTj0@<$b(anC_5{8qN(B( zC{7|p=Eo;N(a%u5M14gx>+1|CPa|dS$EPXMxXYJVi=Jwg<;Gyo|6A z|0z~7e(ojL{+XAN?Nh~w_CEf5MElXhzw`0mquM*pA2GPr1ZcOSHUH?HByq>dO|eOh~+=PnVNPC|&mgkn3o^qD?+~5e+b6 z@Bv;9h-K}?5`y3!dl{s;Us$4pSwS#}!C~G7%scJHYJy?@`W=O3waQ}Oj^85`#Na3& z0A)jav7S(vx89(jtkl_F@M~Ge5l(huin$r*|k6jtkjsB7Okk-?kU~+l#%V&%E@va$D|)I^P?6 z6&}Y+AEZG+3_d77gX>6pak#xWL|oiQA5m})OVmRun6pfd5*cD}vfn{=qP_Tyu$YHF zp-}y%ve=vU6rmsnNBIjVXWNTE35EIRvkJ9uiOAI%%Bz50}?kg@X7~l zuZ(Lrnvf9xDbg3W;Ah0oN72uSH;7La_2PZ}a=rM`!w>uT<*VbJWrAp?d<~Qv$BSqZ z=bpK7yz7~x6%MSMBer+NH5@}Yh-Nq~fO9ReaQA#|{OA$Kyzcoon*i7Fbwq$@M$j@| z=b%f(ZX_{8GqJYlZfoi;bJ49a-oN>{=$lLxmml@Twx5*BmV z846Wbh01X>-3SNK3?~yfJ>x|W!eK7Er-IW%gOf!#h-Nr>!0Ama+-dh#q}j5`Cjvw> zfK750>>88 zFk(bBV|)&bqvOR$0%Wdyw8A%1p>l?7Ea4!U;k*c(3Gre);V@@DLBScX!I?xjh-Ns` zfb$ZuFn9ivqU@~a>86S=Lvbc4GKW4BihkB>HuV+JtgmySJcpFIOP`}iV=b20kJpF* z(Tw0t5G;xp3**J>#KE2VB7UsEuP?+ar>%oV{-nw4ky)1zE20_eYOt=17b^&qJNK1d zb6C7WSucP-W;=IW!)pi&@tW8SxP#LxPl!H=##W&P-S zHT*>S@J0~+%l_%;zoLsP%Y4Q=xCcih7vlB!niJzvfziv%_wzbfD;D5!L977(F zxu)`kknfuy@=5+6$uF|x`{Ks1#JVvou+|%{#rYbHegQGIxwouGfbnpG7)TiWmh~_= zR#+VJmNgKstg>Dyeal*7pVzpCAEn7b3^X|sYbdauASQOpdIAHnres;j`FP4yaRd~H zC5R#t<+rS1P+dp2tRjT~i*%hm1h|Hur6E8x8-nKn^jv}%O+fsX^&B9U(JgCqWT0^b zglGmd89*;4hzSJ5Z&@#v0-6vRXbJ%#ngPuK&@`f9x2$OjfOE^5Ny><3%CA8AWm0Ch zte3g6JhkSKGNPIC>rkGTAm)-dyJgLTxO>Z*i?83e_KD|~wZIf$2>=!+h&Kp;-Le*! z0(e6Mu+$V_B>+|=h_?uU-Lh7c0(eUUu*wvm7yxTXo!zq5K(W->Bq#q}ntVjF$=?9w z^$B7viL+bQdU?xQ%Q55;xzSX9GvqfVh!07g-Lf{}#_)l4W01G34>cH{{&S4Ct#?^p zxVNk$z&M;Bz9$TR%Q_5>%@&8eWqprVKC@maeaqTvpVzpCf1=4j{HK${v3>*Auf)V| zS-)Z+wpv@!^DgVSsp4rUo=OlWNtEBRPC@l6x@DbI2tf0dJp{Oh|D+*6G#i4y0dzh= zoFgE9%Q_E;kLi|mE;7(X0zxzcx-=1=xF(7+_-7=nzqrJ2S>+N-fXd)&K1XbX$|uqX zv5AI2l>l@((Xd<>q5h1$2)diVVL z*>)Ox#D6;WC91oix-(JiAYuMd{?0`Aqx>BT19%SDcLrR;y9os`ILdyY>?IEVG5%i6 zz+r0!CYJhx5kK1MxQ4$Wb;RK62NQK4;g<+~PeO>ng$|>ehp3zE zk0xqIq4pE0v5)S5(y0AnqIME$#}mad667D-AD64?n4-;A)9*CQh{1>X98k_AiqnL` zKe9gqfCJW0kGCIa<9Y7s$Vh(?5@K+qvPr2Tlq4<^68pG5l;kD4s1P}K`f^E*$3P5@ zQV}Q>l0^9=$MCR^>MJNHLo$5|FFXlM|F4^10zwMr5#lY}5H{;_;31*fG%6$%(zIBkg! zF*sib@P(5^EWxpljvAB{LO~3U(ite} z#KAs_Pghi(wcEu+Edy#@NsWCB-xX?pmgx@aBVzDAc86*=Qsp1PcT;4s?n>-K4^l@A zuAU3^oFtKzBzh48|M)$J9~=1iJqxcKvknsZ@q4exoO#5F7@YH7aP~_Q1q8`IdhZ7$ zX6T9wl=T7N!?Bu0}Ue-QK>6fe?)pwWst zNG{r4$2B~Tx{esU>yrWVVv?9ZF#I9VivT!54}m5`hM7Vzh{0iI0cJ*$m_{)C0nm(6 zFw-K#yi72N!C~eCW)6|Chd*-^apx}b8mS@%S6u+r`J~Do{LJU7^1c5;Qbi1|x)iE! zCW%EP%pUr@31Ro4&mw&NOk=D<&qJSOCgQ6g{&tdBPU7r=&)cQMmutjVn~1N4_`6Bs z9TH~`d)_T2{*Fd`or(BHh`&$D>_N}_P%Cxr$jSbICL1yMWN(J*rX=wZ3A2Yho08mz zJRflc`H<&R6Y1@c{vt_yM$+s7&lfo8M__H0JmC3EgYe})NBA`msx21-BRnP98q8or#=5rYrJ70J2>JS9R^NC+{wPz`jm z8g-LB;Hj28diVruo;?qEYMQ9kfm&@+V-I+0Yt*hXQELdb2Faox3GxR#4diO7r)aa) z6ivg77<`zU0VO6`G$9oJfF}k3W2~W;4|tkHM!J@e5Q8J#2&5a5#r1^59`M|t5M8ej zId}6`gn}3xB^D^{l0{oWVGnrPDJX37#t-YC>@A{Kj7)0$g*W}E2$#}S5Jm| zBB}ESJc*Ij@sI7;e^(AMxcY5S@0={s34lG|>5M~fl6C0G2R!Ktk@F_Gs|mtgKmSHbBDs?tk9k`G>E~6CLdh6$s#9NWDysCz>}-sC zQ62@#VB%m8cm^w~&f0yI5(9t0Glm}?Q*S+0TaVHdakRo&5J2Z;_HC5aP z#XZSlH;Hohy+^LF-HJY2Vf$&w5zU7D2jCn`7T*yLci;yBG0Pfu>A=5>jCF{x5Y4cD z0oKpS;s{|e7yh$Cbwr_ZZrr~T4x$;(Dd3z;7RL#PIq{PU&T$RSAB2NwhI0-$XNZNn z@iU4vTQ+|Y0iqc}R7$G&n+Uig|2r~4D8+H)h-L(rf#A{B`Hc_#Yq@OfjkhqiTw{B1Kdp66VaSri`S2Z1D;Z@V!(?VRBY&4H_auvmvSvwz?^z zPKu~aY}}pKRgmgP+}a8pTSyIv5z&k>28>NoL?Z%Z4!w!O*GQpqhO8;!Ae!L_;9Qp? zniCFl>DMVZ%{4eT5DualP8;B~A{OSmwgho%^x17k~y*qkCZ5eakdTjYk`3&(BK>)97HpmUx9O!SeSD^swg|_`IxEVNhlsCMdsX(L($KA{Z4&F zH0$f1Q2v9IxpV(Rk;Ymqu^(rM0MU#fl#0LYnj$Wwh`)$~JNJwHSb=lDfLA`U4jSp) z|BB37Ce?XxfoR5B5v&#PLlorBxO1M@7Kh8L zvmx&UoHRUYARO-8(*UvA8g}X2QzBz^CM-lVtZu-%BURi^Sj@TKp-|nfP&qgBI|&ET z3?~aXy;8+pgu|SBF9qi=4Nf-UAe!Oi11FbQxO2}{q}j6RLj;Is1pPozKm^>m7epqw zhX@eO2p#~zzf;Bi1i_s9zi~M3untG*-0xSY9H;Z3DaK>Kcm#jSC{;W}B+R)#A~*EI zAmDrHA%)3VwL@r#5Y2{Y7}$zZ#Z&k#1!CjQy+}cNO5#4Lz_EoioEQ4s-4k6`U6|IFktn(F|ugaHbLqbM8|WWoJFl zFjbrl#aX1tock;&`dP16sIQ1-eSHneuaYu%?yoA+Sc@h0V;&J8nh`7k!Qxc$2L9n4 z;^5AGF+Wz|+~2?}yR3soI`;*US(g$kq8aNNu&%;y8xSaW?yJ1!u=s6dy#V?P+qvT! zeuuCS17Q`r&V388HWL$b?wbLy$FdS0=l&TfBbq6H3FU40kqr{(&V8Fa*S0DgVA^Z@ zW?aKN2nW#&XE$*EODx>E{}+>Uz*;kM1W{UuwU!kOT@k*F+?-5gXr#e z)LrJ>zr%PRwC3I8+`l(fJPgG{q{y86A&ugXri#Bp@hJZK0f}zz!j939 zBbp8QAHew?|F{m}aOeIzAog0rE}i>{$XKTd3(*YgZ(yCrFQyO{bMEIAs&fjJb3?yK zIEZFAm*UM$xinEG&F2pjluPptQW?C$SF3|lKFxXHf@p?Q2{@M%3wQ39E7EM)R3-vM zGlJ?Ms7eIfxmS%$P=g2%%?Rp(piY{oO%Tkv*GU^a;*fPXO6Oi%p>mu~JyVQpfYCTj zM5l?XiG(@##%b=uo@fy8y>zw0mHR&iy8ZuZ=?G3|TDUAe!Oa3Y=TgM0>(v&ixhzr@aQJBjF&L z;iLd3iCCC(Pg0bf^_*&|*cpoHq{y6mIu!k^R~PClqFG-vpxl*|xpVKTNMkLQ*pEAi z0MU#f69hfeM2|FaCvkA+-jg3IaPB?u$`R|Jk_^1=iUcc z%p4ZyDeDE$2W;n#Yq)^05CdWDb)EYJV2vjx=G?~v;HYIKJkEV0DI=OGPlfW7G%<<9 zxpSW)&$USk2bg}feKW4%X@rAlhVwFTW)cf`?lUntW14uJ`*TgK-)Y4)Jevp*%?ReE zk$F;{xtEB&Mq-F&VhhmS`P5zJ+~;GwpF?lG&V8Y&;+s%hM2gJ0FVZM3F;#pUip$f) zG7{y^eYsp=%M^XK!dB9dBbp8Qd%!796Ke>EJNIHh{K}mBn#fpd2@BB->my)&kR~<| z7IW?&C{!C1D(8m&G2tMZ;d~C9Eoovi;jm}!TNIql8l0_!gJ_1c1324>g**4{iZoj` zUl9SK8Nt^e*hK`~x$lZhu!jf`%?J*F;M+8@pCFiX{}zYiIO}kf&V9c^bhCRhp=G@DsduK3& zSNLto!MQZud5ex{hEowZ6^Mm7_X>)#vz{xNDprN!6{N_V`xQ|1vtHGxuZU)Stp(*8 zq|BXr4MiGjvBZAVCIUn=f`%YykS^+_i>ru(JNE|Z>{x+wuZLGAS_h4E?pH--jV4w^ zGuGx{ZI&)#2$VbbX24?RusB9pFMu9n*+uIbZb4Xxfv~PDLqF#}7g%$Mi8=Q<0GMn! zIFECGjg%41l;42zf^;#T#JO`{knTP}nXhnw>A3COaSbmb97HpmWx!cNEZn&-!Q{-a z)=cSV?lW!Yj%)ZWB0w}FSedSK?j>TYNDR?TtQg&0L)~T0eGSHYrZw-LXYTKsDz1m( zT2f@reXU0EeN)Acq4;6C*hr$>xqm2E*hWR4t*}ir~v`wKHApAS~wGcPdmn6e{Nqx|?ti&2YX2&i-_=~8)!=+b zIEZFAhk)}vv2f@9y&}z)&Hso1(Tw0{5F8-_?%a<=COAq2h-L&QL2x`>93u$k+>hgM zoNXPB(zzc~s2r#ByD7$bV4O=AXVS%KB4N(`oZQf7K*0CXX@$vIwHIiJ5Y2|@(oXoK zsFNtuNknyWoG5qhd!; z=G>#9=x4o}P+t+v`q~W2F{I3$dyFEDwOC?5t|bCQGlEtiXxT}KPU1S^;Lg2eCw8pB zxeL59*E(pVbH6S!YinXfG-GWK*0@gMW&-8TJq}pR92VcKtQSDfu$?=u;SPj__)oEZ z!e4LfWdHTXNAUBc5BG8o8s^#`?lpS&e9OIgT>GQFoI?aLxav@-KG91IAz|*=pXlYD zXG0VQ@GP+XGOppL2n8`X%5b1OLmb?#Khq2U45hVBO1t%?wmPoi5u}b7Tzzyeol`Fn z8bd;e!G*@5n`5b)%%zXT7%#Qv+2hj3o2b1AwF#ug9Qp)}+9VUT=}?>6OH3g_?#`#m z)ig!XW~*ri4Krf!VSW`Tuk;cx6AE|cuK-|yHPrH_VP1}mG?$PNgCi{h(!yTibwXmU ze4#@0x+4=(S1+-XxVZcNTEW>RQFkg} zY~k!9KE&XBKY;IGFYz70G3R|yVf#)Ya)#;3Y0nB)FUQFYetNfWixP&-9x%x#~7nxAF*llq7lypMlD^(?7!r+rqD#kwo8 z59di8F}V6AnfP!dQ-m_bMPlGCyKE*qHsG>Dcx9D!kVuz(F*4_+ne@p?rU7Raa8}L~ z6*C=2%N=%QATdK%TrtyYegM40cG$Rvs}d4okfG~hJM6|liY6ZBu%jXVj%5ct4!a4d zA_iA&4%KFvB8G&y!)})8I_wyQ0X*;89v9be3qnB*j?xk+f;hOt7MPF?)*318us7Q3 zxQ1^eb;RK6Z8LQayF}JjgXkb?yeAZQ;3|Ka!*1*433ful$=bFMJUW+=O`#y8k9UjK@5&k0F=9l zgFEcI698MA zh#Z$P$OPd@AUvKa9?KMu5CwDCkIPN_7}WWmc|_rHR_IU~8pPm3GZI`QGR3e=QAAwa zVUJL7hDp>S1&l46QN)KBobLtjjms2c3644JaSGd5g~%DI350?e9Azp{reumqgu)#5 z6a{6H24xzdAO=Ty87MP}gE{P(imJ1AXPcdYt%=?;C);G)%m2# z9rk=h7VECWJ}e}4#Ng`7p}s6rEXfp$iGe%pW&GHH!(M_{Hd_aYbl8g{bFLsx#NeFo zfwMSMtRYD5u#3Hhu6T{IJ}h9{VdENJOGt=8knXe{_Lo4~Mm)@6Z-e+}mL2do>>Z?v z7+m#hsP4)XJ4u*3>|OHA+Nm&rXRGaTaSiVw6vW^t-vVVnad3yd9~1JGwMI%i?47nc zuHo-U9Wl824_b#^B6Ns^5Q7UHK{pRmH<`mej4|G6&9ld0|74=}E7XpX8gtl3HEPF9 z)J{R|WTrSyg4|)Bl&k5uqRm#*A2iH}!H4-gP|jtFGlaq&_BjA-wT4@$&(E)Wu8 zaHLDJ@c1E1gtDBs^~_66r1wvsCyP|?pL4$Gy zp&$kyl^Q^)MjYH>S5su!GO0=Gh{4sbg8G%D&K>rZk=5&xI%073Mo@2U__{C_K&zy`F{!G5FBj z1g-2B|TJodGpJ%hZkf zh#0(&cR{r~sd9(iU6IAQE3pqfNgXk`dOp;1vqVmo$RY;ruygsb0f(J~SN2&4iFDXm zkvaPiCt`5U`@wl{mgq;2++p7fBxdM}`zh-Kz+c%88`p4uLP89J)YEp@PXlQv@i2!y z6yo1ncEIDXi%1nQxavr#j>r3BL-Lh1nM7?I(OI~M^@iV>WIPBw?TbtmiUYS zn8V(RL+@wn(31}PGlj@;DcemD_5fjbmiTX$_=+f)!`>}7?SG-p_smxckF!Ge($F9V zADSP)budeOmnFU-F7B`oDmdRs)Nd3pwr~y+A7XI6U%>ZsmN-Ii%whkmupLo|oT2)a zP!NNooC330^H4N3*Y|)N{xxq=_OVRzN2-C?437u33Ei*6*y9d>uQnz||4Y&G?yVMYu- z%(+0x$rf3J!X0)F0DiZIS~~2k$VhpFgcuy@9v~HFi@t=!9Co2X)K?*LZp!x(3Sw}S z2Z1smTl6Os=CB7SDE&1k0|^B&ILct43?dHhum>r!Y?(Yl>WIPBpMd%hQs)kPNM!XV zNgXk``f#W}lP#Vm0Oqit!J&7-I`pK&ep(@NT*?R&gmFL^n=Qs^BuvXYDRC zQF|L|%Snwn?B!7NvrH?gkBGth_zqN8lPY)Es})(SyAu0QOzMci)jxpxhHSAuTdXAp z?yxuTV*?I*Jzja{n$iw?ZDh_5i4!q6=jY(uk}Wn9BzM?byoRoLv$8$_eAaf@xQ4e9 z5@Haf2W*G^GmwrD4|CW@AU*;kIta+mMwlIVeYVhlV{ei3IljXUSs`D zKU~8n2?a4Y%AY{_gE+Xu{sR*-*;*r|9rhGk9oO&~Qb!D~eqQUaON1_v5MpqlP!9g# zE9xe5*cUOzQ>=ORIP5Yx25Of=tz3@thMPI;aykBL+3r zwApI9BFA~sfEaw3YXPN3j;KZ`++o)Mz({MTrNgck8L2iQAqGdf8c6kXL|sB+4!gcW zR97K#ZpsY_1u-~EQ=nXvBN`J5bJ*7?D2+8J%?JfCILh@vX+a#^VYg6Z*)kENju>3M zHPmk;b?&fljI7><)DeTLhoK&uBia!FbJ(#tqeo1$4n66x+bKkjOKER{kPL*x9MLgH z#1jQ`*okt}c7!_LGw}+KvqDp7Xb^)B&F$d2Ek|_D5$VLm9rkSsPG^alu7I(HlR

      VsSr6s)r(LNgQMgDrFV|VCKTqddn+i}8kBrOK@5&k2$a6W z!5ns9Mb%lm{Y=#EhuXcQ#vJy&Q1i1){i%C4VsMTaL=4 zep*={0G@1FJnI@BK}d)}kcz&IqQ3(860jx{6LZ;<0q}}t2|UlSr;;+Fnexj}o|z-2 zlQ?(UGv(PeUEu)JtG3t0H9VVe5Y2F21J0|&!rk_(n4AUHdMWL;7up24hUXChq8Y)$ z9NjbR60tW(4AD$%3A($Oy31VmVvP4fYu-Jsd#S173Mjrsip+VxrBQs_RIwO}YjVUY z66NlDja*@?6n(bB-lZW&G#m1bz>9oW> zrNFU;^cOKAnlYB`ohm}T#YF;S4n5S{J7gCXDrd;b^>!XcAe!M+1WtwCqI_@XVGMKW z6%?HEc!l4V9GpsogJ_0R4LDVZg*o*qin6nwtD7p;hGI=pWNy7C6#cB%mDE>6v%c1Y z@>QhF9s5;^G}dB?{isg_h-L&aAZXHCH0muH5(jtfO?tCq1+KjjURh=xG}5&e7S|CdckTjM%p4Y9r>qx1FR-0EuHhRA3o#JZ_pWnK238_5G3TBLfEAXN z@HqDrQbsgW?gHgby+s;{bLZZvxBFBxP2m93O4~Q%8orHi5Y2G@1)L0G;m$n+lk={% zW=cEv_iO@O!`+Ag(Tw1(-a6-ABG!|{5Y5E0(cMhyE_3dg81MJ2dG|Q?98<-7DCUwP zbMCns#XhEr_dv0*x9Cfv+_@LZ71meLXDjSp8gfLlA%74!1A2@8gu|Wt06?s?hFv=M z{*kc;5*DHv)?>hWq_=pOu$XgyM4@_Ep>pn^LkI`a45tVUe0_VOBuY6z~G}5_m zjm)}}SP{)wzX9vM-eM1da_7F!YYvO|DC-5#@7m5C*YLN5g%}9yyzAV{W#iS3(l4PQ<;h-Nrd zfK!=RxO1%zd-KRxHxL%08CE-Bwapc+35z-RwhC2ih03|1-%L1&W;pS{>5wbJ zgu|SB2L&gr!MT-i5Y2Fsfs;rq+_@(z(rnqJ5CNhYL1z%869ISb>5&P#5CNhYK{pWG zkt=Q|2MaK^mOL2nW#&XDD!M zMNss!Uc;%ch-Q5q1?6W+nLGDq6=|%+68kZl2oTK(CW7FFTrnFLBiaz@091+4ut_c2W-ELYj`)I zAO=U-50t&c!QJ{^Ovqttos@R#KicZJhQA?o#Ng@&wNAZ6=z9`E3@&sS-8@9yWG?*> z#`s5To;@!8M-#Q9Q2UA0m_z?bqxOr5+DWJ#&lSf=kh}Baay1=OwApIdO|{Yt3U zB6aS>YeiPCL+XgZ)f+;+L7u2b0L+Cq$ip8;uns-x!s{tSj%$fFL1+$yW_cnePc$J4 z=D?ffxesk(pw9P96NSfF7AnCt?YXIq$H-7ON0BLv;(GAO=TC21;U{=twBcbtft)9W^K^gn}3xr87{{iGw-r zbVb!!yIoAwGN9I#)R^1u3N=5=bO-ejF?b)lL$w>Ja;M!*k;S?zu@5~+9Wl6iF4S}K zL{^^YMGV|!=kQ|#E;|da9J3A*>9Tu8=FB5b#NeFwg0o+qC?H7gu=@dt8M@*EWqknn zu)19Az|6MiK{i*ds9^XRS3-+F_rw)o~4vA$7#y>f`cs&%#TD#*+|Y zaG@8`%?Z>^=CCJVjL%u~>~YwWOw^`AZ3?L|hdo83HqAtBHq>V2i5Vow9ri4_nr0~4 zY&E??!;Bbwm|q9VygV_NP`JaM2Y}zLp_UGNZe*kdgoGFzX&I1~V3+ zZzOf@us23l|A^EPgR6fA^-uG}Cj`J8_NO@XE?9@2bl9ILM2<`O+yvpjK=>+8e3>V< z5e0MDU&&4TCDi$z*{1L~D|8nP4Px-2`3_v) zaWIE{N>O#z?w=-Ve?jdmsWFFr7HWQ$={)rjF?b)N@>9j%q{-6q6GdO|JuYA8uuFu(B!n1TC?4JHK;2{xy935}oHfrLhkdJwS`yR}NR2t{1dUp< ziCSlH|ofJM00G)d!L~VsQ0Gp*}cY3?cyLum|JNn_wM!(qRu$ zh#Z&lmd^6zY7>JfZM7D|8qQ4Px-284Ip4`C?SQc$T=h z!ycpHjFPC&Dqw8kJWqUx!TBbG@5OvEf#8_Keo%8Yz5jZm1w zo}r*j)1bUeD2TyP<^p97aWIEHM^Saw?rSD$3!pZi)R@Db4>do_w2=CU7`%^fLUj?T za)-T0k;S?zu@6f~9Wl82YN)Tw7c26`Tg1Q}_DX(iz+tbzE0e8*L_WiQD>COA;zSJ2 zxdEK(^Tk?%h=V)q3I+H*SZj@xcGwGTbzH-hNF6b_des7*!!8l3MnZ_eg=(RjHK?1+Vb{PI zFSO>_nX?1pkRHBhwKYHCcwj2L{Fn**g; zfrud#?y#EyV7fKb(qYF$MruJwh{2Is1L?*BaRVVShkc_$bb~_V+?3l83Sw}SFi>I( zL_0!Z4m(ysX{SMHPbi4NQ91%8o;bL}j#p&aGD#qH#Ng_wP){ax?y!?1tEZ7VVsQ1_ zp?+I|=u802Vc&*BZ?SdgNr&B8A#z+wh6zG1Aly|Tx)+FUM8O>PU2@ZQhdSRg-4q^Y zg=W&wAO;_ryTO%TAaV;t4smgZov+~JO4J+$j4hnL#D^H1uRr+iD-ib(9CO(BDQx#B zM9xtCn@|vgqYMJde+tBdgu)#5e-xAlH7E}g3Sw}SAwYSQIGDqJR8e)-?&BtEPeJWT zQezJLNvQc*rl+Zoh{5|f9IDTdDtFk=D6&|0CH7$isUrqg9|!fZ1!7Er7)1=+VUOj< z1|0Snyt2$XNTkCa6`6B9aUurioC?k<1!59Ga)&*|Yv_t6DeD8k3v7ptYj_$VAqGKm zeoACHkd_e-dxpIX;wvmW;BnY1NEI=->N`+fT_9GHFn8Fi<(aioVF1rc+vDOIE+!Pj z;3(^XvX(fw!(NLCS!b=0(hhsQt&VH>eNsmZuKuCcVV4MfL_&zcg*Ky`o2Z-2VQ<11 zueavelR({@Fht)~CdFe3&Z=KVm~ zTOhtB6z;J10$`;z)Y4&p9U18xLP89V^gkf|P#_Kx5_8x;C`1PpBIl-jm{1Udqx=e# zqXpt8LSYX3sDkp72IUx`AO=VI9VjP=gFEaKiY!|ur$`+!xcXVB|4HiHVgDIf{T!(y z23HRi;@=1;5Elr5IqZu#^fp?Do^;q36e7o^lqobos0f4#g`#|+xTMf|%EBCWg~E{u z5BI?Tipv*z_sk`Dg&$bX3awP=Ja0h^J~Xw!RijW;D->0Ti#zNZ3QjeNT15e43#T^m zAqMBW8hrH&MO}hp4!gd>R#zc%hN>Z=ufuvv!4vS}UlvBsJ!+TSCpxGPR~YA_nhcJE*oLRqn9cDzaF2CHCQFQb!D~ z-Vy5Yg`z{D2onQ$*ztwz*nq?CfLA`Y4if3G!;v`?h!Zh5XJ>Gx7m8GZNX*a` zrz-0M!0T*>jcd3IAt44qDw^p2jgra0dXboz%YG36n=MP=aoJNy8PQC6CX}Zaim4>d zo%VEjc1=|{z_i8oy10gC5e}jm&a1$Ag;==Teg%_rz*;Y*-S$D70N3zbB0w}Fc)d{f zOuIyE0f`}+i7iHV-=OX?*Zl^@`=B-N9@qV*sp4BuTuO?}c`wx{E;m(N1I1N^;%yS; z?t7J7VQ(w?Y=yl;Lyl-Ri7aJU0s2Z$}!uuBL2USzBdgoS8^wHa8O3dKi+ z#a#F%h3X@P%DHiWN;rsSINO2qMWOhdaF`SSLc#f5gYzZfAe!Oq0?tli;ck4VBF&b~ zZX!T5BiIjuy+ptr`QFF`-w*+!8NneCd|xOI5Cn7O-{WvRWF3yul^;;39B1=CQ;cK4 z_@z+%TquqZ33KMZ$PN872>4z)qA)qD_BR?LM6)3}1GdwJ;#8qHNo?GmpH`4gN!*hP z99u|di4oC^G1L!lt_sBk0%Q*TqQZAUp>l?-Oh4z%45ArM1>ltLCobvdyvt%Py?j6K z3|@j)_-)C-xtwqi&2Xv!r!uiHr(Ri6cGh!MQ^lH4tWJu|tyhPlpY^ImeML0u>s3&` zl9ah)zfzILS}d_2b%_AcjGze!8ub$m`-uj`!CiZ!e(YF*Yj22Gj#vkcbnOiyvtC22 zh-Rz;tk?Au%?Xq{_v?Vg%wchJWxW9UfbHCI4c|ami2oF8-<27mS{b35cSa%J8P#<4 zz4-U9hKTGT_72Jj)y@bZqfSQXs*F(Gj8MI%%{#8clZuW-N2^CgHGObMkI}uK}IAp>w=35?*O? zTWiQ8>1xJX+;<3GZex)(Y&vkr^}~iAuN2j^`R(hhPDB+|v>LHftcNkTB_&3ICF*#k zrvLHpW^~j1Ax*p7kLs6WqKc|m)&I|3y{)xX1;R$f`M`cTChnmjn1aTPx9P)v!r?(f zqMF;;O{`hFrs)fJI)iW}2;^W*Zffo~bKS7=WuuDfTKqEe zWqXX9b}!o;Y8jzsP5TVdckVJw>r87NPd7%lPB%ukt}X6^Zk=xI%=*aTrz+hDoY=uu zW6fD7OC?(E%(B{wezdB%si{%IxZY=H9YDEl@Yq3 zX+h~Bssn~stiGJ|i~+68mQ4#Iq?Z~A9F|z67}w*KFs}GXF?8Hs!gfR90ay(Ehqy0> zZo(*cX^t12grXM;DlOWJ4#GgQVAZP@g2cZWSeU&tL*Txf08N)FBS*1=${lTf*9qoQscR&C(* z!>UI|T@U@J9wVb3Zu+GEfZx=;To^rXj=ps-n-OZKbRlGSVW?jhGD0_7oeViQ{5)$2 zV!M~=9%^oVSv{?LRQIBb_`kBDb+HYjLZQl`Q0U#*s6qXsMwg8$Tkf)`P*l-nRimOR zm$|fT=p&i3F*fSHg2$pphLBSZIS+?I@9V0z$f{3bqxwELU|^qz3Zq7sb6c zY^k02Cd#Jy($j7|H-C>z*`-T4Af>+nFvH!at2rWT{udiH@ZpC_4aC4p!4&#IS9wBK z9`mpKMOS%NR-X2+Jf*9=C@atFQZ9*eC$>x+pIAARm676%_T_O={T?bT>^Jyu+WalWHiRo7S}+1S`9S(Em5Z2s!O>|rgVxhYiV)VbOVQYW;D&7(G*?Ncgd#jw95VV zY$)_EPqkc5_sQyho|LZc<{c~d;DL}RlY1MXZTl6(^bxwm2>?o=jbXI%gTki zl;tvIsV=1$Db8rG_Fa^B*d1S~EB{a`Y*5$5djB4+)it(NHnzpTa?8d9Mz?qktu&fn6=-1kCK1cGkQYT zbeXVw`?;vwv!T!hPqo~cwPkgUFu!?qcQJtFE$_tn8sn$(1SDx|DuMaYnmu*w2+@+Y7Icu6&?W7@)3;{{B6>PuJMvvav_~ zD+j9@gLI7zmyH$qH};gSa;&Tz?O!=kS2+=t&R~w$rMx5?pX5oAdu^snnWjsbFH`15 zn6)|9rc+!=jy`dO>i!S5*PYtLvEUDMIB=>}H0_YIDua0-S zS1+D-ub;blV`NI>c;zUG)>U06tFDdr!Fs@L{YJ{OkCL14jkCC0d)j@_%@50zn{_D( zQaT>M>?rA=tLY?bQsX^G$-VXnChID@$;u4>%C5S~ELqvpzp{s}GGA8q)}{25DSdS* z4y?D zBr7NQSB}?JPDiCPm@ny4X3NHBdQ#+GdrhXy(WNYrDT^Y^+Cpp7DX!!Zdq!W^HN8eQ zy;8SlL!lL(YPmCOCb&mQwS=g?{T?Xw)NQz}TR9=>UiR`xyln6LdMI@UuTDbLzwa&e zpmMaE(pa|MFd?d-RK{ex?FPEK7P77xuPd_aVsv$_WnD|ZI-#qJm324iQf`qcVO>fx zQk(%vNQioH@WZA0>l{b7dMaOY$Ek~~O!u!$)m3(rl^On(U3HZ`WrwF14nX*z=dKt9?{5J?veLE9}aF-qpCu9m1!i z>=T~W*SIOq%GQVR)v?ZQyGU0zPS!og>z3JdqjhytWZjE?brW=TGiBX0UCJDp^0F>v z0aBdRIM07&%=J{h?~c<_S-IH1@(o?(Dp|S0zw#|z<-4*&Ydk4(`ZmhO*JC*OYFw); z`cxKeLXl@Reqhhvhq~IIB-3HzSC1+(>ceyU5x=g8}OSuXu&T6ck=zBKS z^i+QBj#IR(Y~Wv6PgmJYR$k*@*;rS3z3fnPPl_CtHnQ;>F`Rrg-k>XLFNRyBTLuV{j#xp{2MFORX!vuAM~#rpsRcgmCj%e)};)UjX&;5k$Y{J zOnF+D^1MtL6JgdyS({FInsuc;qtEJ^en~bxNw;T1p^2VqxigDp^=eN_U3c?tkSXib z>3mODwMkZe=!ezRZT&OKvyYPP_{N!!t)6z9x%vNp!`R{rc?c|=$Fhpas5UwK?t`IoFbqe}^;xHo{mbtx5);*9pCDSk&u3%ldx zQuv`RXQGBwsG6eOVy;N>9LUZnR?;=rKsHv_zp{?1QCrtoQ`uM(|Hc~WDsPaL*ZEgA z*HyMfr8AhVbSZJN@phgRx!2-lN_$;Ox=cxlFl$LEen-g-_KYUzn(ii>&ale89@*Nn zp-@*(wOkK_Wc5H#N-GrF`}=X3@~AqUgLPF!vTCRwRtLBBXDQE?dJf+>^D)ZP?k#Tq z3o_+-UCK*RdJ=${E19UPnJsH(de=}JdjzNJDi_GgdH$7ib(PCx<(vMMi*%K%WaSE7 z%6l^99bL+YNO4AcgYTm3Xm@wq-$)qY;320~pwb!4sk)R`WaG0uDRQsPlPRz2 zQkKe;#Sv!h4QtaWZ*cCiXLNzC>33w)t8{xd6nfiJEqCT;vU;;8CDYx!J7mf>bvn1| zs=k(0|MkPlcU%94^6aDJdwk=}$9JA~`?&c(%9KO8lw(r*sP`!ONmp}P*8J{WLs|Ct zpU_oal$GcGE6?dF%cr^bmvU*IAs#=X*dw?`SNXB5{J_6*gRXL`tlZ*Xxmj2Fm8{&ZOW7k+ zcIi?MBE=c)Z+#c#IJ@Kfb>&B;!Vz^{9QNHWe`9BL zm6xWwr+e9S&*|HE9g?H$;Pknq{zKiTc*^|r9{h=2I+n`0B6?f zrTZNv6YUwjO4oD?*>p3j+}@%H3zauIepW zwZso=hTHlo%Cn{3#W&7;tnsuv)6IWhrmWSaY?9I+0+<~o8+A2b$ePc*YiOW7f}iRt zcgxD1{*^m)mEXzA{r;7Eb(Q~?oHx|H9M;*9oj-$gmw?)WiX`30$PPF)vg z{Cjj-*I4;Z?jA1J$+L%@@h{U!S$k2P__mg7q^fMJvVUV0b(M8wWi9{88oJ7>QRxh3 zJzYu@*?6=kMeen0WlD@LrL|0H*~#xHab`_)@;gfA+B15cuIUc4={T$0dz4svHWa$q zQ!PjR(O&KpKHQ5>%zPBu`}--G@!aM_uJfR62wCn=a)~+4w0>irj1GWy)Dy%B7j^jxC$1pS4h? z-%+y4p3#fCrmM=PD_iB>qr}>?p-{z4eon}p*+f=Hds5y(p}oIb$dqQ8%25)dtGZEE z2|uh2ZtFKuo-Gx|H_m+A>}hwSn}4fJ>7YwVmC{K7W=BbauI6@G(Dhp-h-MWtOIaaPmPMGgCB8?=W_v~#>zZCGn=aPv*-&VWr&{jJ9kP0xC*?DD^X`!;yVU92 zsjK=T_%SZKa)qp{=wDeuS6Ne5R@0@_l_^*1QW_)08SREye)qTC zcE=m&%CDCS&9jtSOf&x;#poJqCmU|dFvtL%zO zXD~bKQo6~;GdwABul1BE-E}E_WJ+#?S8i%bs^|Q$4!fsn%`)X< zUCMT(IHSGQcTxUqclqZ|*?u?rA`tI3l!IoTd>@w+{OS-Q%5Wo4m% zWnW$8Kv_A!zp}rs@)21%NSE@YOc|m}8G#gMw4d=^lo#xdKdmbtFBQhB>tc+5k4EVl zn{Z#=Z2!h)=_=olm9P6(&eK&cL!~pAZ|YK3%Ep&_QsiDMmMN=s zDIdy|4H0H-z3)*H!e96fh1Tkt-YT2kqT92f&}L7y+?hvZ^$|}>Imp`k`=m_yO`XnP zbya6%)gOLXHQm-PP@XMSCdZwRi=K9Cx%uT~O1T_fc^F15$Mny#{;tgP=}SyxxtOjcgwU)fk!DP&~}T}m67a-%M#JyM+2ADiQMf2(76 zyq&H*MJgm>m_2`$xubuN;&qK>$i{B-uk5U9r0W{%B^&GE-`JhH%6wVb+rKhfSJ@Ah z&S3V{rSzAL-|I<{du^ah8K6sfT&6r4Vb%uc__>n$_KXhFH9bN${ft%abtTrG4TYZe zRLgBQRaQ^-q%=gKy}xJ6l$q*uPS;hTvw!6#UFBD@a=U-!7rM$lvT~O$B~+Rl4LcKlr z1!poZ>MASA$_oCK<$Lq{mt2?CQRxh36tcp~ zkEZDwdqXz%x_{+7Rb#HMu@$nhW&VvV(N(@HE7$l}uF_R*K&3O7>vSm}%f>(Oq{zLt zMW%eBOW7$?zKk$y+kB6bM0-ZJ>YDymHoZ@`XG5Vqo@%)>%jUWVcvLPwZ&TdOd$~+0 zpQ{`tm*}dh%Bsq_J}2CrZtJxu&pt}(;u~i^uJp9q-OX<(Q|jwdno8*=0A@!?BVEl6 zvgW#6&y6h29{=XL%9~|nTmQ<|y2@K+We5Mtu&y#iRwn9Fy2zAtUCNzEaYp-&T)+EU zPrKu{>&kmeg)DVl^z!e~UAo5Zk&PAjSKh5^tB#-&lWL8EZOvQ-JT7Frh2O7 z&fG4mw|Y`?-OamOrtDOwbBC_#8(Fp2538Ts`uCJ)A0{kM zx|BLHrIs!w8Y#|bH^}olO76EiUQbuvLMk-NQ*JRa{yl1pdv-1`Q{+OzmWT%KyVD4&$oLp&+}L7~0Bhs%^AbvmEYRgIBVBmJ<3xUG+; zJX>lKzH#Pbf~Vcb-TY}XWr{B46)8Onz|57*(A6xEHS@e{XplXEb9I$($;u`Em5X(i z@5stk{*`a*D%Z=(_jD;A$&`({l+TgkjP|F#i*l&l@lSN+yQIQb>bm&Szen42jUAAU zedAxbPu19?YwRc4*kS+14(TdS$jW2>mA~jJ|3sxTn5T3p=Vjw(Jt=aph4S6|(%-t2 ziZbQ0e7_rjGi#UT`yD0E*fUx#pWmURdM(*>b*tQalvsN<6sqc}mOJxWSsmj^8G%B3 zf47t=*XJvDpBB2Rn`BjMKdk57*29!%OWlfZocZYBX?L8PpDa@nbSYh=bUJ|9QSyJp zy$5_0)%yRx8-l37RY0*Iy1O$wE9@Q#2%0Piq$g5>0lXIOjg+8VX_tVaUN!X4d+)s$ z>7n=DdzIdMkq-HPX6Ec+&(55@zGi-}*B@RxPcnI)=kq>wo}Jxn5=1ezSxl{OLTZc7 zS`XF~Mb=}HUz$h$Qxw^VMbl?Y zi6Jg*t<7XE(?l+dn9KZJMs2R?Rx&^v(K({jt6Az5qBV<`l0%}|%FJmP*an|8kr5AJQp3A6pRTrJ%Ude22M7xMm4`HbX ziq@>%-ajOot<1SBdUlA*+`!_^W-bej!#Q6RwUR|GGs9XQ$i9yHX!Pl+P0v&bvvk(We~cUj~u zk;^0Ia$n>UmLBNs9Meg;T5I@IQFtMQ>u=wADcx|1DUcqrA?v-EKb^nwuwgCEk`*(L zEMnAnMU?D4mh2t#WN(WiJuFf-k93J52_p5WTUz8&jwLS>;=Khd#kk*R0*15E9LXa3G8B7vi!Bf!g{W!CZzKhjXwf zY8;CiZH9F+kbN@s)1+qL8+|;chU7gJ@c)Ck%o4dQX3`4)%vB}xL@}#a%<|AVv_wzZu^-m^$1E6r2J*@suwuax;$DhK=XS0Vx#g_R)5io{*^OLRR_vt?c zogb+t3d5<4ppz}tKe8Ow@F#tfu!n~uLu-3jqn~We)m?*~XrOboK#fb4oVHB$vo8wg z!~gIX3fW%P{)Cs!R8%MV&MYGAv4>rGpM*GqPBc6WAlcJVB9E^#h)PWP;J?ssl; z?sD#Mw(~r2K5;&B-c_<(9hKp(QLeeJ1+J^E_EIOghrB`FCU270DqG~a$`JQx_b_)~ z&ph`+_h$ED_g42P&vy4NWv6?evfF)2+3Vh-+;=~5KXhj*8 zdV+S0mL^Hr(l+UYbX#lF78Ny8x+qynH>JDML+PdTR{ALY zl>W*9Wsovh8LA9ZhAShKk;*7#v@%v1r;Jx7C=->*$~0xVGDDfE%vBaB3zfynQe~C0 zT3L(U+oEh!b||})eab=QkaAc#q8wBHR8A_Vlrzd%<-Br1xu{%1A74|hE4P%p%012Wc+UjSB+q2e zRL^wJEYBRzJkNa30?$IvBF|z^wr8nlnP-J(rDwHgjc2WAooBsggJ+{>lV`JMi)Wi> zhi8{(x96?Qk@;-41sJ`Bjs+OMg^tBIX5+X7$EDhME_E!&sII_qC623bT#e%z9M@`N zz1FcFBfbI0jW}+?aWjrvaNLUHHXOI(xWh5bu@hhIa?E$^hTk5X*^4v#aArTw9Ke}_ zICBVR4&%%boH+`vW6(Q}pZtlRoWM^`;%BGu)6@9b8T{-lyw1VvJiIQz>ms}^!Rs=- zuE6Umysp9PI=pVc>n6Nz!Rt1>?!fCVy#9jMJ$T)R*8_Mxgx4c@J$CeUJb~v^cs_$? z4m>lR_Z;n<_Z{t>4;&qw4;>wyj~tzxj~$(zPcYY?IoE9?nch zPds`#+hY}UaQ1O_boO<2!g}cJ?CWE7>|evh?t0oNr;&2oaLB;sHupWhN$U?nt`a9h??abQaqM9*E*IX;|gS4iHxg| zaWyioLB_St+0J#&InMRYKb#w!bDbNV^PHQIaWgV*LB_4fxD6S%BjXNa+=-04ka4%O zgJTaKd!5Uj`;d7*G9SR>AhI7q_QS}21lf-w`!Qrcj_iLT`w3(}iR`D4{WP+lLH4uA zeh%5sBl`tpzliLYoO_&?oqL^Eko_vMUqklm$bJLaZzB6GWWSBT+4R<}1Mz|hHBVCWBQLZP_XxA#|7(B+ho=W3f z&!q9L9BG0pQ=aH*Cr@&_(nF$g>xD_94%H)22=W|7o@2;!9C`jk zo)gG(5_wL!Cd;Rh=M3_kMV@oWa~^pvAkRhQx#XH6Uv^EEuehekS6$QPYpxmcb>zF@ znknCO&6027>)UwT!Q(C-f8lWtkNbE$z~dnvkMMYm#}n6V`KfD;{LJ--oa34+XG(MB zcG5h#y)<9$fJaAZf!s-2D0h|?$z7zya+Z`Wca@gN-K3>*cWIg2Ls~BPlvc>Sq?K}S zX_eeZS}pgL*2w*&wQ_%HojgEVFAtP9$b+Pf@?dF`JVe?o50$pa!=$b9aA})7LfS5m zly=CYq@D6;X_q`k+AWWj_Q>O;z4CZzv3G)$?VTts@lKMKdM8WEyi=s*-l@_G?=)$p zce=F7J40ISohhyH&XU%8XG`n6bENg&Kco%bxza}OJZY16zO>o9K-%J6C~fsFlD2sl zOWVEK(hlzuX{UFow9C6p+U;E~?eVUV_Ig)J`@E~9{od8m0q+{=pm(iw$h%HD>|HM% z@otcgdN)ePyql!s-p$gV-YwDz?^fxgcbjy|yInf%-65Uv?v&1YcS+~GyQTBqJ<8AIXbmjfy(k<_w(rxbv>5liL zbk}=I`pbJ-y5~J3-S?iA9(d15554E5N8St4)%Pz-kG+?qC*I4_Q|}e&nfI!cg{_f_3=HE`ucLDe!fh(zptG9_=@(5pdd8Dt0Jj&Noo*?(aqqjWT*GC@X>no4-^^?c>`pe^e1LO(5f$~J(AbFB+ zusqo}M4sXsDo^zdlc)KH%hP=$S0k#CB;*f&+q_Dz$Q_@>KCeKX``zM1lJ-z<5BZ??SBH%DIO`$Jys zn=7yJ&6C&q=F97R3*_~_h4Kd9B6*{4vAoHbEpPTMk+=Ak%3FQQc_xRSzdwuKVeZKYbe%}W9fN!IG(6>oGibi^<~t!@_nnk)_)f_;eW&GHzBBS|-&y&N@0@(scV7O>cR{}A zyC~oHU6LR8F3S&nSL8>&tMX&tHTj9}y8P64Lw@GFDd+fZ$(iJ~+>YFl+mpL;2lAKP zk=&Czk^6FI@<8rF9?Dtdk=&I$mb;NBa(D7n?m?c(JxPw-i)6ZclXmVtq`kW@>EP~1 zI=cIlPVNDuvwI-v;vPh@+=EG1_Yl&}J(P5J4^;r_Y^YBJ(Uc1Pa`ATN92+2qw*;CbTZmK zgN$)cmdD~T&OMWich4dd+_T9<_Z%|G{Rf%so=c{<=aH%I`DB`V0h#VzNM^Vfk(utr zWR^Rd%yus!bKFbGAMRyju6sF|=UzePyH}D0?p0)=do@{v$71&ylI>ngmbllErSA1) znR^3S?%qgNxHplN?#*PCdkb0Z-b&WEw~@8(?PQ&M2U+jlNjA85k&W)%WRrUj+3em+ zwz&6^t?vC~oBIIS?mkF%xDSz??!#o4`v}?XK1%kukCDCZ<7A)vPqN>Af*f$4BnR<0 zCT1$b z65HX?UU`<-K{*o9Q8^mX36IW7H%}L(yC+M@R=O&qUEP$v5}rqRdf+)gPbDX@my(&( zTWOcnM_HuwRZhwMl+$v5<&r!=xhxMLwtMXvwnmk15>K>|ea}QIxyN4^oBSt7W z@<=?d7^Q5-^N!&WW0bAs$12;(k5jgnAFr%%O;A?iS;zuqlF~kDveF@Gin61^RHdh5 znsSv)S8kFS%3nS_H;I^~%!`<<%#WC(>@W3)vLIrvvM^$vvO%7Y#{%W4Z=tf0EK>TE zU922*W-GlMOO)P@rAi;)GNq4Wxzg9MLh0vNsq}ZOQm#2xD;R%eOT=1bYs5M{)++-X z8`5 zeaha5{dgQuhByu?Q+$V%9=^lMRqqjHkMF25)NxE1EFV{PR`^rd={%t4nTgvf>+j!hj9^)DF6X#!e+*5|j_m$y}2g*|4LuG{Hkuq9-jB`(vk&dUz8t*e@ zr6WhlBAK4Yc((o2*&dG$o^y_lo|V2%p3#oZIN!zd%$bEpSI<~SH_tdncTXSE!!zE| z)3e3b%d^GX+cRA5dfNHMd6uZp|9lfXdz}+KQyh~#`yG=#mmE_( zQyo)17roQKGu@NpoPozo&veHu59&Y9496VLaPo&|rem&WmSdjhxOcwiyl;VLhi{>0 zm}8M=gLkoKzc<@6SYF~8>RRda4T)R9M$!^bS z-`lq0nY-V%*SsP^)GEDU>mSl_ zD*|_K;A8(y{gV6lLBl3Z<;LG?=fZHzXa8Mw<^E|t-!|3G;dw87M#`K6zR`S|G}lgt zYd+^fU38!Hw%U31&QCu3j}1e`v^*IZC1wnm+Q zAN^HYHQ&m1Td_g~Z0gTqCA;laDjnS4>M6CieW49}`Bl9i zXrHToYL8C~@vCZkwQ6v`tA4BAu-Qtf0}%9&`O&^tfAljRmoQ0!|1m$>|LV^QFR|Gg zmI(H;*_a<41NEn+<7~E;`vrb<9MqpqeaU7U_7>j|H6OZ^sMEDc)AUw;7w-4fYSrS~ zR`r`X5^yHN@qXLLk4n|6(WGIk78xxXw|3}v{v5Siw`tU*MZIznWuxlFwrJL@P4gzL zf2#L+Y`r=yS~Sh5SEDw*EL;AAavy(CE~;$VhhnN0! zT>aMd@pX&;hc`hfB5sW$aijl-iJ#wS)$Xp6#EcKief&`*npdk)lltG*Xww>VD-r79|KK~@tM)~`|J&c!V{zkCZ#5gb#(usbym05ovt08J zxZWT2Y2~6Ia% zx<>V+lv-7*M44rOz&tC|{Pff0TCpjyTK0@86(U#*Ur=*vAL|P8$1EZyzG}6k>Iv0q zC9oKcNIf)dQ>6lIvUVauBWfA}O+pWA8EU3~TfcRa zAJWxe+JZuAsQNjYYLDlz&#6g~RJ-<~X{7l>EwbJ80W zuz#_&;@VS-%D;K)q4yuXs@tM#*DRaXpiSenmaQ;(ZJq7;)j}n619-Pe_@ek+916tP zY+ru&YWRy)tJveK*sE8um#S*tmzwWjYS^LFu*0cg{}>v`)I21S`q7p<)I{y(Zo|^VzDPfT*_MR#B*{NX%Q^W73hCN6Pdz>2fEHx}A zH7xw=NLxy+_?oqAS5M3MJ}o1?HD2Gt>xf9`N4>KX8U<~u{91crYSgM-CpEcdB7Rr_ z0QgtXw$~q%oPrbI>eW#}Ta##QpGnJTofb$O%fglfytc(aE&hwN*y!rjW1?fLrLi}V z*)n(Oxx-IYWoXrt()2(6-M)a@k+#gKNVFSp;axfY#!Z?xO2g%;v--j%+}?-V9<2>y za>haG9vY>5w)xgBVw24c>3` zTQfGOb+@>o`4+8f)Z)kHX-!+y2UD0nbw)z&m?n4h`HYTFO--Y+anW_6k#ZN@@UNil z_e2e<&X=`RnD&A7@rob49N>wmo`R`v?CyfL7oKYboLMh+*CoP7aGmorUPkBU%5e?$ z+j!_{B*``F#3#n5VmdTyNk>=x=t2Aok4&+})J$v8yc~*YHVA9+!xLJLb^3UIo?ILI za6IE+YkoBy?>ez{lJR$LgLZ=r#%0aK)lc8Vzk;^x;PHt~sZooL&Z&Sy<3w$(s>Qs% zMp6Hgi!wv-_&* za*tbp>h|({0R}eQiO6?N>-lCTbDF;0*p{h&5~jxfAA?uWLc5`Rg@4Aipn02Sj7{Bx zZfbHVk%1+MjtlB*^#l1dr4DT8H2di>EakM2je?De`ni$#7rv*ax&qNh+A<^cXklt=Sbf6X z&^s|aUKeWFrga9>nSgX%HJ#0&7v7+~?`1m64stW75#Cz|hYEIe&tuw5zwP3om-{U>;rqE8dpUioT3DqHWYnB+RN_(D$xO3U9l zDZNo?EnBx@4O1Z2PZOIL7q}48{ZQ-q;F(-3ptzR14kmvU9~WBb{2Fu(2<@EkEnH9I zDFUPU6*L1t6aKRaH}jIzX}H#`Ip)J1lwSR~N{zP@UxNjamZSvN`4Mf? zEDh_u8CGJ@vxQNb>^zeu1tnyCG}9a}$W{HQJq>SgQefihMQdw$r*6! z9@0PSkpFCfli>-#m!Jbl3W$2KyoUB?y8(c`az$kDC&SHS4O^>-qYQ8$N+sNsZb( zuLUY0?IehX@8QOnR=0uW(hpvfHM9n1t00IXFlmcvWiU!i+(ro6v(*}Jik7GtTP2~F zR<@!_1-f;KJ}N1(b>dAn!GCj&3*K*v0ehOJwph;)k8Z(}fI9JU&xaPTg5jP;sx4pG z%Xp#fAil7}9#T*E@x@_$QNWFRjqVJ5cUL`4@Wlgs@q##y79w8+V4gX&cA; z?u>}G?xt-^sXuy#9~E-EAGn8C3a4`PPs;xnX3N(Z~s!>%M5?hVM}pjKC`8K zSomK>@qFf;7xTF@=cq{kSY6ciN=n#t+(XM8jPGmXzp^Ycfh>uvo>Bx~e-^pCb98H4 zW`6W^_L9h~4p|OgR)_WuTV3^7JzD*te|e;>PFNj#DcF>viFIss@ES-?P9BukLV0y0 zSxLp~L@v+j(4mkmv!JTJIuc@a@yK3j-~iLjLbhn_=wC;1V6EY72F^yx@^6);hr^cn zn#!^wa(Vj#`D~d^wY9s^-^0~$NBc4EJsj1mY2&@ms^TFi9-xXNf)x)46c1ZfJORby zk>n^9{W&nhWVM~g*$g{s(C22@N!sPG*1G%xaLz@NGZg3d0FFn+IR}WFg&^EZ>-Jub z>@&GzU8GpB*062@>v|-)O0jy;O`w!Yb=^R9)j*|h3%4i^tTmhmz_}Mm?oyoo!8rE} zIClj&4=E0;HJoR_c|uu+21d-Q_RSN6G&gN>C;_ZBg7ByW5*DTJ41+j=u&B_b$`Ry` z(sycDYXpTr@NyJ+kwSb&7jId$7haCa>NsEB92aPt<19z^iv}uv11W43qc|{Liy}p% z$g7m34V@g3D#>e6flEeF5b$g1RRfbgYu}(<1Z%B}9AJAlio6p=-ll9{2ZpMm3iqx7 z=^cjqwgHYCMki&2wZ>QqjGidsrhpxTSC+@X=QdF3T~?anz*@s83!E}hgixHW!8m0M zI7EO`j^e;t!}%CE6)4N(;LB45gR(xKBdsb{f})=)PNS{YN-sYY%}TFNXj@^ewKW>b zRjBd=b)KrV&L`?TtzwYITzp>Z#83iQYXsFmkQ_x4qewjEXdd8*RXLLRZDoNYI}v9# zsvFHJZKGM`$d1pQwK`>mwZ>W(thJ-aXB2cSK-E$(^HUYHHn6zjF#9vZd;#<@wOmw> z{?92EY@V=&1Sx0Blz)xRA=d2~~!*rrZL`&7#QnRGhEeo3VZEdjkiU z)@gM!j{cSu2i6)+8{lM67QS-Nz~Jmq=M096Rqi`A0v!E6Py$$M1V2ZKD);ANzfdt) zYhu5nxxdopa+Uk9=w^N6}v;RYZU21Mfu9TE1O|m z4Eo#*>p{C5)>@bM2TtE8(wpM&m3v=6tW&$4RqnlW#~MJfV69<|0M@W5GK6ArmHRLQ z)er-fenB5eabT_COaRWfC^ClPaFzQw1I`!$&P0j>YYk@_aHdcezH*;pkmjb%bV>kg zjbIK4W>EsZa-Wqu!5@?W)*8WL5G;%$^C<*Zxi7@#xJ%s}S>-<8K&4kY*;X;u0Ap1Y zSrJ8+Q4+3lU&R*m3J~yXX_K&j&MC^mRqm$@%KCghYgO?g6wgydu5v#QMYGcD5^XE2wYFY^@)fGgSMFB~(wK|S z%a7}n0M;78eGvQ=MeanATa<&Z-2dXY6;$qbaAvo<(Xh(>R_?41C@ZWrR=YoerNabFf zD#Kb+eh12L`^lSBoUh#9_6KgDylLdn?#=s4QV>{cATEG7CB}xEmjlkm<)$Gs3-lt-)*2H{hZfV+Fu4XTdo<5?Ecu37otSXj;Vi~H))$C;i zish^-Mndr;KPgW|`I`MBHn++f^zk|hUia}w(awgo*4b47QrS-`Q4qdbuMGJP++ zBA{pr1Zxc_89<4C5>J7+Iz7?A6K~|fy0rN}r8uzGa6SW0il5Y=I9#2cV!){(z)7Vz zu-0(?37oo=g|E}=8m0BA@&(m~wWj?qXn#$$`3n7Ok@ml-Hmo)6bZ9s9lloMitIZo? z6Flm`EeqUFuWumHtC+@C0a^f{nV)>`Cru~=SCuzoOZIyZ@N1@tfk`hhThh*fwbnU5 zf$c{>Y2zmul#Q>-e>5PqVYnGaIDOjuOzB{)(X|I%rl0&q(YSg%(?Ir{kw;t59Via0 zHJon1$?}uV6o;$FvkW+$1vuR)4y-ktKEUZkS-5(s#j{h?@9 zPz|DOg|*h!VNf1ImHB#nh(Q`x`RAp@a7qAcjbH)@#`(z@KN&?i_YmILf_-6RYGz!Pp;4?ytz3gd*If7E~uvUZP=$}ooVE-;w9Nzcx zZ|yxVohv4gjulPn?~WC-I-D@6zq?e_D}UI$tM-Iy_ll$|73OR2?iB;IcUL2WzI*ke z5U_cN=nsg#lz^|h`&P{Acrvu^KBd*&IQj=rb=bVC52+}sxt|LSr9!ZI7aECX4yVoJ z>h0m^-BTv@_9!cARZfastcQU-5t=~Ms@j`dYedh zC)I_`yY2z#?yE@lP-(87-iOWYG_9xi7%22A&kqeK_XQ|VC<<)eQS6m)$C7ezwR4U^ zRiCwCl`N>e0JZQ+dLhKs&Eb{I3!ws)^g;+W?`yfi38)nW6l z{yNl)RU$>*$_ATvw)enRvJxpl!T4IaBw)A# zExQDe_+kdN@=2{$#?kMfNU(nwX~!pckN6WCeUEs_$_b=IWs`cjMCGgw=S}M6cPs1D z1lF3e3}shk;-KPu&FrcisF@uG4$Pa2TJ4IX-%W8~t>Kgg&ij;wub$tpoYnDqX!U$U zBf!z`r3A3n2+C9zRnX7HBB&UwHL>z&ZaLaqu8J;){=Q*SMOUz@7zM?TsUlZNe=Jb+ zTUD$I#mbdQB`V5S)0No_t7OpUW>_@sa#(9!o&=nP$|R2B@O5t6x3{*7?RC+~|N^xMV;d}|4e^w@SDGpa<|I>g|SAg>s#eubk zlLnlBQ5L?^{+B_Tn>OE20$6JV=^$uG3HX}3VeSNtDFLiCf@UE2zA|Y-A-L-Mdu)!k z)y#fHR1)aMk%BgR(xKhgww}3B}=5k*m;$L(#1C z8b#X*Ypt#0pge{u^Hus7gEZ#i^YUXnC4jX?FareBDw8Rd$t23bSL)OFZ3XrE6r8!I zZZzzjCX;e!ok>|?t+6fy>-@@OE(PT)_xYj4VfI|Zd;#=zt#ZfFzldVN{#~s3RZ+RG z4^-~Oq7z7wXi_*@FW$FQ#e4l9;H~Swsc&5`f_J2Ma6rKkEy{i7phkaC}H#H?pCqUwt4<7`6`LKjlMJE*B zizX$h=pMBr)L%C3ud2QW)d5cEbtsfw(m(*30a_Q}=y%aBfVI{Ir2yoKCTF%KQKuQom4FN!^Re;X{P=~7D3LgAAP|Q;MT;H46;Qx~jKCHFD z{}+_MjwWAH@q4uClhncgTAgTh@yPy?$6#CJzpcurL%v}&`G(4$qVm&J`G&YK%v3K7 zlhyf#WA--!jK+Dy*crHF{Q!*C(WE8C;4fLN!7*3mV3(|xII}=K6MV^9r0v%@`hTQ@ z1DmJ8VOYNc>lezzU9x^bM=W|iE!cScW>v8x6x&CWOe)G>vf4v+IlW|M8VE2+mup>s zqrVgF0$6KZ&;vl-qDdA7;xAd<05O|hva)gq>PdlMtpN=HP`_x>hXV1JtbRd2eR2mH zNP%Fj0SyDt5K6;cvW6G{^h?%ostjvQc{G$qQf2OvHIi3myVe-03~Nn!5|k%IlW|m> zyJSs(c;J#X4qvZS*Gb4FYqC{f9x35fp>=CN}s>=-|Uz8~jyJUJ*@}QE~2)wSrx;mhl*Di(GA0 zeiP(3M3c2tp1Wjiz=dIrdSPIfthEA+&3_+bp870nN8plm5g6yA$!UtgU$V}FW0T6k zE?K8>W~+K8_>#3<+plr-U!sEp`*#P2$GQQmYm|w*WL-l?Y*&|J$g`}QRu%6-@oqG^ zO-1=j)?KLXrI)PR1_IFR)w%#j|9#p8u-3ZZ8GxQdlSdSYzhpfD#Cm$kdXzg*4h4d> z2J}J0C&lfg8*Ct0FPAwF91qWb?%Z?3W`DV zo(;Z_4nC~4!7m5ph#2w#73VHl5ix;hSs(Bi?2`4NRe3+;BV$MfD$iZAB4hBbfAzw^ zE?E@>7#06M#)o+OtE9dCbte$EQ+@7(Bep~BPj$YB{QB80+V`-3x9^{;9)Rk;7_x^7 z^DpJ^iwV4xzsJA;o|D>@0Z0EqiUON=lw&|SLOJ-C@sD5x&Z{HPH|PT+E@rP3DmAy zQM(Pbn=#}%735#GzsY9Pb%QoHo9@tVhRu67KLW~w7;=xI@Gsdv0KiGLt9xlTv~fT8 zUhYVbDH3enk@CeR5PK}ip-9}z_4e3Mq8tN}ex(nO)oTpcyrUEZ%1g1NK&)Qya4*%r zWI!o^GyKfdQ3_EM*u0|@0m>_sgMXR+6@x4{O^Q-=*u1O10rl6ZI{y;=>$$7HN!4NV zuKpg>OU9BC6o7kqzGQ4x$II%b$6lTaKO}hp*?_KjDxXQ+oGO>hEF8*ctvId+o43!wbxQSDq^1|%E17E1Hp1q;jdh@!N>%xn;8P8MMPf->+gzt`ip4ZQsR70z5&Hxl;p`xm)$rcqAVymNjB&c?B%5ryPmdT$IQuAs|q zWSAcSKChN|>e1hXBEjYb>3yxj{tZa~izRI-5`RPJe?Ypc_7b}x)D~y%t7n352tCxQ zP8|KeQzY2DBXt5&2g<|U4C;XXcnI;(n?aqesP%waw^))z1^F96-JqC5Zvu3Im&Wm~ns^LrJ)sKVuBy`c-5+RfWyF>SU-+q^jJFpNYIGd+tAls>0@7brw`- z#FA-Ln7ipS1HyruKGX1ZI~QhQ$W5QwR>T)Td|oX1gNk!EeC7p-{~-`xXhnP(#Fxa9 z#Z;WT*|Q`_e6c`$xfSu%5MN1^xf?wzp%%37u)$tK2OBo;gS`o=8)C^iD$L#F*$^AJ z$+M0}U^jU-Tan%c=^e3TE0yMM@a(`w-w|```3;_}0)*XvAK^-DioLCN`FR9{2UMTC z!SeuWUDUZ9a)akF?Q___+vm?!?Q!_krC9Qm3iCI3a#+dy)W86qt}gXGW;pu8;`Aq- zuz5!*0F?Z3`ZG@c22cLDtd70a5eUA)(??Us(f=Y0R2*uzBxhH&CQF;-o124IT*qUDd8;H+Y=6BPkRKHt$Fu0Ld3eN>e2629M7` zRN6qKU(L%<6xh6@d<2y8aiknY;coDhH=vXgpnObGVDpYr2`GNb!QbHV8)Ug@@(ERk z&AWOG)T>f;{svFg+|^^LI&9w6KZSZy97&)6+zp;2YHr}% zj?{`HH7NymgC~_O+FDTO*Gx?Vk3K`|(yoEcd)NFMT=n9}S8?PE%EjN{sb|3XilKgC z0OKZ38s&q{JKwk9OOGQBDI9l$C*8o-&_JYj)pryHHt#4cfYL0Ed{0rh8$8VnDBlZE zT2d6)yrZ-MN(SZNZt!FnRQ0+0gB7)(q1KkFaW{C{Ld~pX`h~U;Ht%ix9jd=lRsIIg zuLfDnyXWOYCRK;cyLwlscZnmN;z$R|z~A8M!fzY6!P5z62CEwhyTQ{Tcg}8<6E^Rh z{lVEcj`XIG{0*MIp#@!bZ^QfmaBsE5Q;+@u6bUvjNSUhx@A_E?tof9QtFq?gRb8b`9JIA3WmWqVh)fdfn@m!I`Aa zm*8r9vPOWTe;p-&wMMW>SaClW+f2n^t%+?%bGOpwa#i!;n6%Rx4U>w;`MfvLcAe&+P4f@;+J3_l0)>@aJ0?vsza-8Du75E82j8MCs zRp7^S$2v{1V696gIC7ohaFzH?1I~2; z&K-&aYYpcCaPCnSz8b%0kmjb%LrMT^jo=vwo=^h5B7c%QK@KH=wMOtlJl^gXPr~B$ zdl6h!9v+|7ahke0vZ_2R-h2Zo5N{FVRbc!ho)n5FFH;h(GXF<>XZpt$3xR-NOD`Lk z^jTXZUcXNRYpsjk2HTtQqD~vYm5>Yo$=&73dmLH zP6OY21}eSFWQqf84aWtothSZi&q2<0fM%vbDD25HR2=jBHwN&st(ARYv<@gzE)RG}Pv z)gH@lE2!F|ab}jf(Xgt$O75%)loi$*YYJFv#FJ_il&{=t0E;UQv#S~A3!o=yl{=39 zS`-U5Pgo1=^z)2b0;@S?;wty%0Qf^KB|<9q|59aGYsx=DxlKIDpyGVx-iGaK83qn8 z&C}{;9Q|!64y-ktUxD)rW#KFLUobe!)HxGexi8lUaP;Ca-U<6=BCX&N&st( zU@-_5QUbnmUzj^VHYI?yMz9J5E8@vA3c*$GE3i4PQa49dxi2$N>6OlEs~B5=u_>Nx zh$rhP30JvqVhef$2>7+M&cLM4+O4#UV6Ao0KCtbHC%fXw4$8(??t2VKyBO{c0~|Mz z_ESb!YmCRicr>0Irhr`Ke$>Es*g&Os*`E{#)*8+^;GBskrzj3rxt}rMoD$%ir#P_I zaIOI75@q2k_e%z4eLi2cs(2HM*Qp{`xnGB(S?P6)wiVV|TmORc9jeS%?sp8*n2XQL zk9(8=)*3+$2%g51$MNJL<=`v#r~I~p%Kb6UtW!4{R=GdSoz<40KP!i|#`;o10x5tu zQPAp)uiOhHgcOI_`4d75C_pdMDt8?HFHut)!Rqk&CV53?}gjDV& zsWPlJWeLhoe1;Ge=PP$-Lf{693L1& zak$F;a|2Et0nV2c2i6+SzkySavhbCAJ%cniZPF+KtTlp0AZS1d_{zOO?gZ(S0M;5o zQxN6$0~|Mz+EGSWYm8mN*ai1%C?Hq4 zcQNpFGEnJV){Wx8TEpoJoZbnfC&l3^_udAao&ubH6bIHC&S2mSq%2(JKG2}7&*vdl z6-PjE7**sd_hC>pE4@b2w!&I#>sTm{rpkQfKH4CSx%j;N7)J?Utr1KI!BqU!9sJ$` z<=`v#srGwy)|7Wbc{|>+LB;vXeLLINwi-CV zbVRG0arEz^IIz}m_5)`xW#KFLy%?O6>YNF#+)rr)IQkDz0$6JVM}(F8bFrgT4Az?1 z2{iXOZ7x^2A4h+mQpY`{azANR@hlWiQ$?lxu+gas)BX_L36bsfG))Qbo!Y`&!EUt2YWT1Lr zpwchsPbm(pHJtFo1QM1=Y>6fxOc0hB+DSH?;b*IklRr_v;R0(7=Vjo$NLl#G{Y8T` zH*E@10$6JVuY%wolz^|?|B*XE5lR4Sjo?iX6i+0tQ3$SbFP@my@vOQzvdaB61C?Is zyk!-`1q??bc{h=~LrJ*G-H{l$+4C+4__g$ofk~ex673>bYhC06Tj@mdej-sQ8(+DX zHXyyva1{d_H<1Wsgtf+40gN9elCl(#tK2^{@Rc=C>0R~_#eubk^9gV&CXy(M!&UAT z4LDH(oXQjj)*4PMaH1&-SGh+Ul=b->XH_u?iV0MatK1WyXjXb9)3(A|YikWCSEI^& z!B&&+k zpg4spa+UiOf#P(lihn?Hb|RTcMfu8oHk)BH4f@;+n@hVK)>@Zm17}epSwM04%6$U_QZ~MFziB|a&Ty|9;JAr&hcd!iV|)z8hl%7q1>`FChX%g;1}eSF zo=_ZEYdHCm@G*u-B!}W~mAgGDbOdt*IN?e9Q*>BsI4=RGK$3pDfUDdKfW_>B__9^S ze?YMiRpcu7LQpg-yQ*s9_(C@!IjT;;w*pt#(s;#w%KP9iI*C||j+ zW;1N1L7$sp>u8t5TI=$yz}cKcHc}kEa^DPyn_T6-F?XzO6bsfG);?hENg}%_7FW6N zF;ML?Q0W)+{S*h*8qP7`97!UFC=OS-A2Hw@65t%CIIz}mP6Ov8W#KFLlLl#S+MJ;T zu+|7Jg5W$Q;4Am@xf5KX1hCc!Zi3)?61hqtxXS%HHpfxw=Ey4ds|G5)a=&F2;}I|( zB$0bb|04WMe8>pQck>8o3bwz ze`s`_BYS-+`>fRJ8iiB!O|ieDeWULq+kvE=EU8qdIi@0q>XDg=&(EogFS56$1~$py zlu`TDWbcL~(@wruCx0ohrr6~ayIU!x{YluWnKO_$xT$KR?D^hP4yO9rceq)|rW~SQ z#Ku54%XYI+_C_>ewiIY?yJGh6_ieU_aYbiIKDArxcDA)v4vU+6KxI%u2(^=*I^li{ zMJaT4oqQ?w_m!%&_48=!?P|;QuEd{$2yVBQ&KY?`&0Q)aw|26$deYANH^uJN{s0uZ zIxkbLOp2YT^Pvo8(@;#cGpXcMDmjr#j;E5Nf!P+JT%Z#T($!MzWmD|sluM}}YJWPp zTvmrMg{mo6xNlSJAEwwVWS>9>FO+n@_ag78ZTct({~WqVJNdD4F;(fAqR+Bybs+Uf z%(R74b>(hg2m@oO4k2{cIRF!x%hWo+sijZR;G$13FiN#WWRX@)N#8QtXxM{R@X>+ywbnae^u_QR}p#cb-~MQ!3^!T9izxaz!j zWnT|7axL}$-ck0j za!7<}lZ*+BNvrIwME?T#D!MeaO$ob(zRO+HW)OO&I_BG$LfQe*pJrb||BNXVnA%TN zl4}0jz}3F2&VEjNSle2(hLvkyRGqdpQtUOkaiTrW#)NK0MFu*w%}9+U?aJ4PI zV5D}vsSOov2rH=F@3+^smD0}F)iw@9SJ1YRQuslN{hzq%>8o&~%A>7fH8?y>yI`CT zj7jztZ4khSUEHwf-ir)VlYOBzRr~Twx{uju8@?)q0ZXxet>pVe|NGioa-RdV$9n6YJROWai*sKKt^>_iT21VY}VFB+{1gy)7%BEnoPH zHoGnJMf|E%;jkC-+1D|b)seO)joR8e+u;)qpVoH!N>S7n7PT?b*04phmi1eu+p@v~ z+20Oi-%0&6seSmyrqS#U$y*}ef0(%(5V@RW(#HYJ;T{#mTx2olB5f^Ow+iZrmM?(G zenu2|i$z{HkGv|1e8?j2nMd9gMdq-`CnA^pQGtOCi{b~Cb!B0==)L`Nl&x{A^z_DU znl}s@qw?r;yZuE`_!~^&wJ5{9C>mwji?523Ia#uI%_HA2YP>B=%qHFn6$cQFtBN{JC{W(ir zTMai`vv&JuA<=9)HDS?>LtJVE7H>=D(#$xV-;1JtU{M)nSTzILf1!TbR+5Qt^zryL zByUQqk zWg>GKm&>S)Q5T(|DygT9=qOR@*(~)8(VDf}r-ekbmD#0YU?b{Sk>5(v0*kj7bLn2u zu$6QbMGat4eJh%5CEosw$h9nTm3ia}QRHS8xk2QzleugYxg3Ox-rM^snr$Tww28Mz z6n=^+{ArvQ$IM%FM3n3bOLoyb^1M;wtSH%Cmh6^!vKykvCoJ-zdE|XjWLTv@XXc1p z3cy9bnGjw{u+|DOmzP8?#hFX7O5#x~Qps#9X{e3pE27j6mb#=G9{L1FU9)z3iI8Zv zGT*HnXkLlReDfLy7O$JRxGEdA5{D?t%c9<|Y=YH1kUfI>Xj zo~*MdvOkOLV;Tk8MP_uqBB$_KWHO5 zNtAjKOFdt-X6^R5A<=AQz7`$WN{U3=8a8eobl0terdv4L_8oV+Gfr#kz63(`&U-W3 z*7Uoe8YeGht9^iT4c-6*|;Fk zg}*V`UqZ4k3b=G)+1vB8W4V?)Qxw;e#dYK3W@~X-qPT%9uAf<4A5q+J7B@uXGKRT~ z6uC@>i#{7Cn9q!HA(1Ns{WOb3PB)L7DvDgdBIlY%&Jjf}VGUXo;=+b+HA}t%-O10! zWulEFNRJ zH@+4Uc_`3N4i;I`JhFr+(!(NU^GKH{(#IN9D#V3#%ZDs^1iF)-jUR}DDzczR1cl7T zquTgY5XJ6dOxt7lqW{l8R~=+7`(g}5{~l4)aTawX#-!*!AIN^1`e_&c3;0GK&$A(U zF9iIrGM7stmpe@QCV;u3|GFsVF^hQ+6H@e_)OzrqC^9@YumbF{rja?K$U-dgCG*Gv zvHXy*PAJMEUlF;y$y{C+xj5jW_jbuxv!eg9*6m!OA$>N5Y#SIa~jc0LVL@ra9 z%S4gOY`EwhG9%XX!Zs}=(vJ7fXkEFGMb0yi{6iGEoJB4%k6bK@T*Df)GQ@=q-)5G4 z1GBr=&G=|z|Ngx++3cDqF!WC`QuC$ z$t!{Eg{hx5Dn;>)KAx|{@q7BK0sl9c%WEQ+cbRmFxR49mTcQ|+#Yk}>m#3Gs9(0N# z%dkkFd1Pr(d_u@FS3tKU*;R&Mfx=bMz-5m0c zuv+FVswqmA#*)=DkNnE0@r5YacPv@Dd9sG0$d)X!nR(>*qR1Z*sdr|E$mJK7ylsdJ zTWgujyaRt^bdUBCoK>i{_E%MUi({!QeqEb^YnC5O2@5xEqI5A=3;yxCS#T5EV% zJin>4ktl+2{UxJ+#2dDfLh&IRvfhg?i;|UK$=)=NEN;|zO_WS#$(-iN-V;UoSY#>l zNRKG893u6pTSnyaF-u-P#D%T3O3WonK_JSB>}ib%aPFNs`kvE$6W4+Txh_>Vbu&| zFGKw_sq*+nACIyjc~b)ZQOxBdkxNx3{Rx1%t)!wTCW*zwCxl#2le8X;6-9o=B5RsQ zRu@Hn$s#{DkE|n#Ok+<{!fBgRg$VT{5w(jk4&MpabC1CZ&6E8 zvUV)lZ|0HzGiv-SO4f}f>tdd)lPIzui|lP4*;5ob1d)1Y4iveJWXXqxxUjW0j=78$ zxy)cLQ*#-$$?BprJi+-~8_|iP)C*bad7?FIxBn3m%~s}S7QG?F<;%e0-NjtC8;5hN zDCz)<+G~dOO(6SG>ZffbC-IFw9>+uS)(`lfV=kvfE?1fKrO>V9f+*%Li@6m#hrZJK z|Ar{?DT{n$9{E5NnLjabeF;kp*}im5TOxk}V4YBqMZPFBP>~I^T_v&8j2{{M=aTg=E=&6A}h1Visq3~qR2Qz z>YW)aa!F>%6GB|rTC2%is)<~_U@moY8MWGpW?RX3+K7H8O5K2^PE*4}pWvu#)^7h- zNHm+2y;*dR5SQ-}sIBio%%#6^IQxpCMzE-%W>{SV*~d~pO==Rp(Z^$aNZxJ%|LM$S zipXUylb#J=t}2-+idn*97KP5CW?By}5Jj$Kk*mxjSBN6FvdB&5ksCyjyIJH8k;_5m zvQOl40xo)QA2XelJ++1(5rto33g?aU;;ea#PK%P=VaaZqM_xB-ToomI!je5SPj+7v z8J-l_-R(&sySqLOazv3YBU10o0!jP@fKA<3Sn@(4E^Mv6#$1YsT;63aC6df80Q#uC zm1MS+^wmc64N>a%S!%Z$9=esNYu0X;LZVso#zMRv0CQW(N>R)<7PC2Y4z<*JaHA-4 zKa1RB9=S^td7MQaF^@bXiaf(2Pl{YFF_-fqms@brd;7ZSq#UI+{HiGYF;jS8oEP`Z zTXa{HEPrxf4TmL%tYN+XZOMkY_e_-RA1qlx^JFh2^Q)cBuHr1Rn0aIoQRF*_)I0Mn zk&BZhe>cR1tu=+YNFtXA=0cLqwi12Ryvb%;$vAC9ONmnZS?Z6~@X)P9U9)z3g^+00 zciU6nv*okr%eOPNkj);JFW;`zf^g55Z+9v_3&Nf+d{64Ts?EO_HVk&Z{(blX-G&{} ztokt$TT^XKnm0;s-kMvxn^SEK+B9yOjyF21Z)R0LU_!FnH)>~t-mg1bqg;>EErZUg z@8T^SW)Ite)M~t4k1w3BaCqVT_<)LYI(!&DF(bWIE43YAcPQ6i)ZWu=zWen1hxGeL z^!q2&KBd-HTWfEao!T(Xs_i>t+P+gb`z;!$e|m<^mg&%bJ@Z7Wt$CYffz$Xg#N4HM+Hs4#`+H*zG0^yz7cjM)z-S1)>C?y=&E6tShsSgFQnR9{h*Et zi@ykt^lw!>>Zn14oyX}QKlF3H7Yf;4*4~6{vlVRh`sWl3sm`vIb2ff z4u!@P8eiyUp-e|dM>j_=M}Nma$4JK*$9Tsi#}vmj$1KMj$0ElP$1=wn$2!Mm#|6hl z$9>0BM;8coclLJna}IJ2agKD3aZYqjbuNVb66aco?|}S%=LzQx=L5(;ab~%m1Ke;u z0mKApqBKdGB2AU1OEaXI(kyAVG)I~%&6DO!3#G+UwzNcADlL4Xl_q>3O)5oyx9NJswn z%seyMXHPcQ&pF@g`t!b-2Pd=V{+#DLbIv_ymt+b0y41M@ycMRV>j_;ko z_fF!fKXKJ5Ty+{(oxxRSan(6obskq;z*QG<)g@eY8CPAwRabGD`| zaMev*bqiPB##MK4)m`UT&U?7>KCb)+S3ba%*}*rQy@PK$`vl)|_6@%6>=%5;`C0H? zXaC@PsEqs0oZx?)1A-qo2L@-ON_q!>5uEKDjISZVeNZ!fgNFw93;rtjGgMFi;Niia z2agEO2_A`x`Z{=E@F=`uG+r?#cyRF8;32`|@QU$x#RR-!B3>~Gub7Nie1lg^!7IMS zE2iQV-{BS0@QUfd^PDsAs+oAzEWBzqUNr}=nu}M>3;xe1;JyS3xmfx z7onxaXlV&rT8fsIp{3<$DHkoR2%ZtV5?`x=e{ilwi)+y0TC}(hEv`q48_?np!SjPR z27e#CDR@Ef=HP|FTY?t_Z$*ngqQz}!aXVVvffje7#a(D|H(LA&E$#{K>--sCdxKX8 z??cPKpymDe`W3DJhSm?D^@C{r5L!Qs)_+IqN6`8oX#FT!KZe$iqxBPL{Ulod6Rn>@ z>!;EB8MJ;j_~+nr!Fz+xqxB1D{UTbwgw`*k^($!oDq6pW*8f85*U|dlX#ECSzlqjw zq4nEn{SI2ci`MU<_4~p7o&VtL0aUVGr-OUD&II>yoel2mIv3o}bw2nr*9muj*Gc#1 zu0P#5u2b#-uG8*;t~2gIuCwkhT<6?_UFY3HTo>G5x-Pnhx-PlDa$R;0b6s%{cU^Ul za9wkcbp7T2+I8JM%JsK4tuDkAuu6yoDu64na@%4@C zzI%%6ANRMe2kxn^Y|nSD-kxc$KA!2WzMdJbex8}G&pfkS{XMf?pL^!Gay)Zg13dFw z13mLygFN56zVIw?4fZT_4e=~;ed$^38tPf%`pUBuU&~y>Jj-3fJ-MzCo)xZx zcm}#xdIq^ydA@M3_6&Bf@eFaV^?d1G=Nal=@A=BT!86SLgJ-yVqi2MBlV_xRv*&B~ z7SAa6R?lenkDf8^ZJx32?VfS&9iH*-ot_EqU7m^V-JVJApFES@dpzH`fA&mq@AZ7^ z9vnK=JtXuy_m`p5+-oaMci#w^;l3F%(|s#smiuF_D=Teqe^=uN_p}-t-M4FQa*vAL>>eGv#XTl=tGl1; zM^y7RRP%QC;hH<#_d<5M?}zMiFRrrNJ=lrWD|nB4i1TOnm(IQJq0W8oubjWQhdKAV zhdY0DUv&QF9^pLT9_c*j{@QuSJ<565J=*!ZdyMmldz9x7_khYr-MfR2;WfwIo1G`z ztE-&Es`n@Id&>Q{`?UKmmiv3bXYqB;J%4|*|8n0CzK*ZI-6t#EaR2GN>7L}gh4Z)F{{-K`*IoBF&U@}3oVeSZxZ9i$+#9N7 zd&XgPz3A@andtaFTK6jtlS&T*dk z&hcn@f@g(iqUU?(Bu^i#-rKQ$@5Ktf0c-eftm0Rl-+8t=r+F4Sr+XGTXLznxnu*uX z!t2X9p2|K_&fzFkU-SO2WTY+YQ6%WW0~jDj{r2f?vtFrMbtr79apsk@p6Ttf-bsf) zf)U3xL7!-UWq)32m(khNzJq=azpMe*e5zf_{^-|q=&YYBjAP-Tb!FKF_z(S>jIR3W zBKkES_+MgNlm4E5UbB*ggC1Ssf05o!=KK0-cxzmPPgnZ=(XWAF)czF1SK*+U#r6O2 zIcN-zyjrd1YgMZ|tv}UjhKAOzU881bRqK@gmugk3)~Z#@>8w_xc8#jlv{R{%I2;ci z1Ub_Be=;dCCFGw)CBHi`yV0C+`ZHQO-r^+Jv(N)~fy-}|gyAqO5@^gq4{*G_2Z ze%U{rk3421f|9OXr=@(B-*xpJkJa~0yms9xkHhhzHUd6>tm`QG+PAc({;ceC5&mjj zM+2aJH{;zP$EiTq(I9Bo^&aGK#82XYR(muM+I35wa5#RdqLoqJAMH9MRA}{@(K)@R z*M%pDCOx}#=-IZ5Ga6?yoiDr>QtQQ}Mj7pTcFXM6KFeu5OE{Zl^-9a=mQ=lJwa}!9 zZe6Y9=Dep1Vbq~_hab>Xn7s zs_OfvT1157@#yk*pR5s7tQUr%I*Rv+XS0{}a4bhDKi%?C%v4WT(dMhCvy0-n8Sy3k z__A^CVf|d`*&+YWy)eftqieg)z0&Z=Nn@DVwtaeLR@-)+Ug_v~ENI!6J%+#h#q##Y z%HE&z_Y1)_N=K?I7*(P-U-j5`MgIG0*0$=+{*F68YFnYwyZ)=(fwwcd>1|&;(D+c< z8qS7Op8erN$IR8AlwMq4x$Vv!+h%suTYt6R@pmR9Ef1^v{gS=Imwhv%^dj}vv00Yt=UMl=fhY}y1P2XGkwSS*PFbLPr*@gO_161MANR|jTdG#=y`|ZE8H1-? zD82SA<<>QPz45Ga1OD#)=Ger~s=PJvu^PosmOj$sUpF3TgtY-k!FcOJzc!f=b!JxQ z8be?HY1gIugDaN~&HO(TN`I%jrStMz``-KYce^r1 z)Wu~l;Ig^;po-S!u=tGWJdDU4 zjl<-b459fNPb%Z-n*MG|*IwEWpP(u$kL$kIfiAZ*N~~F2Oyj7g`fvc)?E5CBhozxg zPpea-(Z&KzYdX`)?A9~O;&I}dg}TmhuTMGYm9)w1b-8-T3F^dmc($0|oSkpM_#|(u zdFAmo-Hn?urBnL*M%uO+-z(CU5vHZ5qp(p5Ryx9gxkJbNy=-R22k9xObT-03zJkl~r^q*~S=_}b?YeYNp`Y$++|F^hbf@0(q1JjmH*eaaS#xB#q)}ZZ z9BYkxutnpzmQhWcg*CLw*t!#YrW+NS-c_G%)6y(~X?U+?sMm5Crfft`LFIZjQoKJACN5*5~NQrLII0BcLgMO9W5*;w; zY2DuKn$o#jTcop)alcPMFU}aFo;OiNHEo(gy@?FNkC|~~|Afo%2UQlM_qBO~4%5e+ zKH}+LJ zZ(jFMUT;h+t6T?}oe67WHWtyep>Hu>Fq$bco{j$pcw>sq7Z>%!b&NtQdRF2ZH;;w{#-n8#STAxnf?>Ax6Jpv}aqREUkh5yB#{4SD7>q z`}X*%*~lsbvU#m)a=*&g(WjXB@He6&v^l1ynULHNw9iM(cVMoWjc+p=w;HhSn+MjI z(t2&JqkoyN9iL{*QrN`G&@7p07?zq4y)>)i1L#{}*UeT2Cz%&DjcOU+AS%)~34fbc z{T*Rm71l5&zNv3ZH_U5p<)2fZo8zW==@z5g;qmbeqrw_H9GLxaQ?{YGBC2sjN<=)0 zu(6iY+vbZlnbi^1Oakhj5uH1xG>U4JlGdwB7i`RB7d5|gp^cvWypd^Wa+QrXxniPV0?akY z7qFPw${M5F>_Vu}y;YGY7`BSQ}GB4t`@&3CB=rn0>~jxT$rvg*C@_ zNbj1`4tt2%4U8-lxxuDkZSBpQhD|s09rOn3dR_CGO{@|wVd_;dM$ItH&`L2A)Jb}| z4{k~06QO#rHBf(VNtb+Iu z^M*!~K4ntMY@%WvZAJ-6Y0@;VWs0^=YPT+02r^sf>3>7|%&?D{t^8$F4ZYSXnZA}U z%1`<*)`=9q_0B5D(v+{{9*%qf^`f)ZgOOkzp=Yj4o=LQ(-X~4SUU|2wHnF3VmO0vC z)N5Sxs75&bg4y@Ctyfqcfb2;L$8f1Qefs#6saet}mbRTcbVDMu(D*+_<3)C|($p%& z>d%*`gi(5bifJh_N6?r+tPDM4YCLLa=#!j}fFsQJiKJ_{G;KY}?@?f!E_GI~rACot zlq#7yI2h(PM3DFefcR77ZC1>z51OYRuQxo$DnV-o)P5}s{*-XI4Rm^P0E}P%@Q-{TqVJucb!`Uq|f#Eax3gR;^<;|RJ@L7h#n#H2+ zcd1WfSf9Fg(>|kPxOB~RPSm^fXC@@9S;x5ReCNRmrc51cMKoNFRg_NiiXNDWu~CPi z(dJ`t+%q^zI5P8}1*{1v*lgklYhrHE++1dSXvnsU0D`QK&SOHGVnvFv`eI#G>d;u>p?=@awPbNb_6ck4+k z$M{B(A$$yaWp=b?N$nwdItHQ0VRrxYOvlr3I^GsD2kUEGH$%IwIcw{kww-(BU4*x7 z95eM1-JD+zeF~?F+4XYPg=}&2om*cruU!}Jv#o%B|6va8u6&%dkJ!s*0}ZTON1wf| zfw0Wt`-x_)hc(CEOn8gtQNAND%!b~{=Q^Kx{1x-M((^yr%T5E5@% zY;Avpp5&?;trqFWMnK#3V57NEAAqIC^B8Sv=rg6|#AB^AG;59x8tBryb0r*`jbgKA z7V9@Nzv?q2k*DFkA7i4YNwS2a z2dyHJaWQzzfP!Vij#UAFyyiF0Tk{q&X-+mBS$Sf@=jNg+ zXjke4Tl2kZErhzJ%EEYUX`sc4ERnS#`ajlk+%j>SknS_QIwvCJAh^_snS9*|>peNi6a~J}I=2+(6m{q$0!F zRlT|zJ62{LYs=PVoxFloMY_57nO!fMLXOnN91ZhBO+qJ6q$?HlZA{hszt zLsrjT=JTkvy;;xdmFAOtI`xK$nUcSX)t?6Dg=g}g$E<0)p?Tp69}kHPTN}-v8Ks3& z)>cvX{H&M{Wh1lAXZ#1(;%jVNQlv)@hiM$E>kl?oC4GshZns_{>nxAqW9WPexQQtj zoPVwRkiBVMx-_579iQu(5?)dHp`ll1+YW&q9ro(H3-X^De41}=V)W;m8$O+CK?Ilh z-QTNAN=8 z-!gku)mq1W>b{lv-5>qm1M^8tf_c$-;|W^Zszzt%Er}A2(Xr;NYizgq&SQz@YbVMV zS>@i^yyy%6%v+ZvnU^f1yWH4H1%~COJoy)zPjB0pjg0e$@#$@{dC^Lr$FG!FJb=+I zXo`73E3$8RHv?V9Cjz?C7M8WM_G!Rb&POoSY;Ue*A@kk=)c(bUUNMcVZz9<~ueSEi z@8-Wt=+phSh7jJrb!d;v-Fs!F81I9byG)~TcOOUD7MaS{iL_pM&zE(UA>2U{{P#b_zKxYo_0Foo!S35;$M5TO=)a=KKF3pirL?5 zNdH-1+EFUL(Cm=-pzKlj?`HU4rBxx(Vns;9_{Z`0H$#kHVq6sI%v}+Z(>KTYa!%hq zPW<+H92*+HHh6W2L;sz@h(5nF*oN{CP+lJ*){=Ph5c<8=B{cQ*A^1JT`Y%sjD{+A7 zN=ZkUe)Mi697HvoAAz%lSdulCFPx6-G8)U4keq&Fk%@j^X_>&WAqd7fH3A&H+lT;B zjbK+uv@s5;ru_4e=VH4_3{g#NFS@&jy8CvB@!O<>wchSQzQ<|fj{alZzi>8eppW-H zRmI<+xStfq`zr1apm;!4@ee5e9wH8r=m%znd9;51ZdKSJNuO2NQA#}zRd!k^hGlYexhIIv4mqNq^!Wu%8z>6ByC5h^SL}g41 zR|yAE4d)hcZiI;IgfrY1=Z1uHJpj&a!a-ES`3E@nh-Hj9VlQdAxhF}pvUxxRh-w5y zLZd~YP-ABJnh_KV^}kgaLD5iSrbbjFC<%f`LdC-b(UET6YFZW^3C-!ZSeqP|=#%3- zXYRuil`(-ls*3RxFv^6A(xKupBI!lN5u%Zl2{o6D(jegX(qj^nQMF|$MTlxCa)Ryo zQ1M)-C`W9q&7rEJ!96b_J!j#Tli=7e1`{Kq8sm##tQ;yT5@0{yJFBw9S5cxeQdWg< z5Y=$10q50FAqZ!HFV3qHjtGELop2DC9N zIm~@isuw_y)$F2n^tL1{L|a&+P3PVbSnY|4IrsJe*r_=vl zft-7u*oP#Bs3!I)y8AJ8mpS*3k?-BwxcfQxY*od6Q0zmB%(?dop!k`p;vgsv2o;}` zD0l7ytP1;F(q|R+1*IHOE#)Ea1!_7Vg|`&QUy8}`Cv9@Hocm&l%5XZlsu&x9 zu`X1s2^Fh|ggN(h)(yP|1pHoFB{3OQ`vav2Q7uI~z_u+^Yz-BgiH$q=Z4%N}3wN^w z#|mjDF(Rrl{sP9mp<)jKGUvWm;@cxp87bROIEZREzXRt`s5n44%()+ua1I2(IYKyy zYB(o=bBtJ+b3Z028})orRq+fIPmv;X?x&!bpY=LReMMC3>qRJ^CuQ#3&r8y%#XS3Q zi3kwY2yTMl?@;kqsJKcT+`0eFrxiH&zi?)cHqltl{c6Fiw}=%{jWx&{Egpo5`vl6J z`vZS-n0sHU7eMdQojZ=+LSAD(1<@APB-6P+39Ki)`Rutr;mzs0PqPw!&iyG;MpRRN z4$9@c;%O4+&b^%1+(3C+=E&*Wx1_^co5KhG{y6{|tLMhpZYRRq-ka}KGmq55%uLt?QY@fYuAfPY;LR15a z15k`tL=h14=`j*dl+1(s(&2rBa1hmS-ULp(S2Q9V=F{UPoJIj~ni3A88qQn5X+bR9 zr?-%$jZ$ev+K6h}ZJ^znw7ElX9Y{Nwv=P;`)1lqYE83Dg^XBa^2_AA{%L4o9Z6y-J z#k5xi=mvl;UeU=bGKhh>@-Egb+X)2xp2?7y42#*Fl7pz0ocF=@u2=N(icDhTuKZmI zsh5SDDZ?3M^8wKzs?qfUUA9+zLTJp7XG>(C$UOQD-Is6>)o=y^C&w%L6Ats^ITB9) z062pP2T=`YC~$@l3-jYcBxR$Lzfx5k3B}>0$o%+lDCTFVzNWq+s`Yg<+^?_v51_ zX{_>j)?yqHAgU2e1;G@rnCul3iG%y`DdtoHCq5Z}KdenF*gcz{e)Ung4htCNra?pG(L?;rX2 z@6YQP&L7df>R_l2sv`!FF!$br>X_bpfXrabUPA~1(LTg*Kzv06+;@LfC#T<0f8Tvf z_uV*pN02(Aef80G0(tH{p)n+cXkTaox;c)z$^7;>WcOG;etV*d+7zfwCN<`@CkIgb zRz+3ji^{j+jdj++)v&H1`X01HmjL7)1Lp zD*&^+j#x@C%wI2;SeD8x`f|LIP!R2-Yyir-I${l>FmJt1LRk|4NVr#P2!iGvejzMT=+a z<>Qy1t(VjHR6c(B`Fci~AgU>QpzNwAoFvXYv#XxznVk{`>gJ5@U2*hQBpgIFoGQS1 zfmpbEexY7Yzf1n^`La%cqxU5uKvW}mwO$|xohMe6#1PfQYM{H-sk_WYS4X}t=i{Pl zsw##;u{J3(CtW*$qE}V1J{0TK6Lm?HyXksXh1HexS%rmB$`RF49t)i4dLoi=xUY@| z#2GE^)+bFO3&x5gEJQV|H-QyjPc$Md=CI=>szwr(;b@u?4x$=P0&w1{Ct45=bJ=f6 zI4uI;BoYpy8cqsu+7JtO+HE9hRyL_bfT%{04uW<>z&&@nf(hCa0iqf~7Z7x+Co%|v zx$jPx9It7UqxDIX42jBcGhJ0N-UUXldLpx)=s_gRhxf8>=u8msd#Q)SWK`{Ylp;j6 z6!iw%r}f0g^~8t7#=ZEb64J*O?uQZ_E2KWeh^WRm5R5tXM1KNgt~^KL>n~9mDH}vM zh-x^)fHSn77(zJAnGcn4h6KPFPB@5aIHQ5{HL);v{pl^X$jBM1ZJ9Fb4#)>WLZk#5CgIPJI@iR^ZoX;LHte zqOm?{GOb|Nxx|X7#<~=&i|dJn1j?QJVt;d(yHKhZKwr|GJC5FEgoXHTu@={dbKhh- z_b0-l#p7Y((J;fjZ>x{b`rpDw*FVudy8bvmk={2L!guvgN8fekK8iE_wKI40Gk5fV z>6jC&{Yyt2y=B4-TaT!QRSsBB6VuN6#y>tBsv$kCE1{eKiGO@}%lyZO&#Ed0L$N}b zC{Ln4Yl*;z4zh=9suiF*A{csoOXilB2tYGJPXUfz7o`AEEd?(EsB)O7NI<`uK%+FE z%7Dn$fbh=%D;5k?g@6#%fT{uL)i5Cl=r99%)dxrv3{;(f5Y>Qc1E?m^Y^rbk%j7Xy zc4|rh#;OxS%7|*pb)oDfCCviuZ zac_L1iHAY_3^pTh$bB7u{}wlD-*Lg(eF6|;y@^x>cmn{jVIrCUiuwY?`T#@+0BE2J z@FoD_!$czjxJ$Exo`HBDfJOlTnyLb{1VD3Azv?^q&7qj1<=mK?tigYa1|Lyv@Y_JS zb(lyX@f+0jY1-ho)(Wi!zH$>dhBZYdtIDTCzFn9|CHZ3{KTDHuhlOFTwlGZB>J7)- z)BqUmZDQ;;m#lYykrgJo69!+hvcR!W~9KG+-;2_!>91H7X zV0}nTY{~i%iCC6b7S?!tqN>;rihaUFHi_~js}EFH(~^}f5uiv{>nXs|`x&JGQ7r{u z0BB&C$RQxUWDNwwd|I+{3I-ZXK!|EUBLFlkObjI;zGMya0UBB`&`1J8R0A3dpwUFb zmaNedfU#taBV|N202YRc?+Jh{Sqpstz7GJfL=_+x0Lw_7 zEm_N;=rcE2gTI0XA5m@a*Fkwrm{>*PY{^<mDFB(UNtiV4w#Cgs2AeP&nRk4Ht#*+cdPFxWt#N zBH?*Jh46PiMl3_c!s(6Ja7Cb!0D6RI*pl^#1Yj&#kCHN?S}Gogaw$?~OI9haY|UDw zNf}X1`DrLW6)wtbgfC>O8A1>sWI$N?{grZN~TZ8{H4L+jU;8%xo)o}3&iL)iE zYPk87^$N$ZmaNxQ<-L#(2^TdtL3eV*!msO}3FKa((jD}P_O`BwhV5(9XS>MH||-d_m? z(LTyypd2I){x<$WjKC>v1ite5ff1*5bsW9FlRBb(^<&|I-onolI!;1}_JvNNn5D`d9s|)nN(rD8j}XNo48z0TsxK~~6vG)_nFdNpLP4~T@;FdR5eI*pzLX@( z%A_=@BidIl3-u>Soxer@WWnlBlRBb(^$JigA0eJ40QUBL`G}l;=d?-BdVBs^iOASq zcB&w}2!zTJqGE(_69s!~zH)@Q1XP4Nzh~SMk5Lv?C^d-oQ}Y_Qszr!bBZMF>{E(LPEfP{JcbeL`Vx$A?QO z^#hXuNFzx8)_Z#(F+-P|Ce;UkPiYoUJ9;w+3DFMH3%bMp1V|r6i1!GIZwP$^r0ZIi ztPP>}aOS3V#&<*Lw(dG{^nOZ6i1v{_15#h&VVgmHk&oLD_umZaucGz^)CNX~91`Rk zK?9-qfHs11Bz2HH(7TSKcQADw(SFxQ0A^T(7)mgF6KEI!uF@vZ(1Kw`5)7h!nDKxa z8zDv$4Br46>jN{oV3-L6gJ>US3ScG^3ETXcEQuSd$hV}5XkT?YRKFutw(;{FSGAt~ zXOJqQebsqTof9EukuclznFC>S(`Od`-rI#L^xO2AuOhw#;)^200upB%K8t+B7X%Pr zsv^D$;wvJ=auR2oJu7^~mj@7Ets=f2;%iBnZS<^#n$Nsr4fX~aY()Emy%nmPBg94$ zW}7^lBg{>njU2(+wUxKQvpoR9o_~*UAtFBLJ$?DP z3xwOG&o+2&L+x{|w*5AE?orMW|836mR0~B$3rD2*hlKeCk0a7__y0%?;2Gf3K4XTX zw{WEK(1~atJd;6BXz#P6IQT#B&j3XS8o9IxJVI00BnON4wK$+ZPK$gcw!_X;~}}B3PKAYG>a5( zMv8c%U>iKmtef^tsPlU!Ug9w-v?Zkm(SB-Dz||&Fw2l-B#Kkvw+DJI9Ez|@Fj1^8Q z@gdsh>j=K~ks^)Y*alB~i7ibcGE$X6D2Vn^x&x(ar07g2Y=ft(gwi?e{Sos-KW5-{AQ~l11I+*@xbw zj%Z(fAk=drMgK_Aj~Ms{PY$0pu))(GXGUogiM7GguVBtW#EEF1a|AetMT(&W$v1e0 z`5U_2p;CPS_)E>=X-Dr!LPE5Il)c{k)Xy?tEg>f6vX=m0tY!)PT=sHOMpRQ?1Lakb zVg-qFr@hLWyH-dXU>dJ`T^zk@2?tRPXCrVn5DRzP8!$N2w0iM%+tYOd9KD-}08x$L z$AFGIPiz~BA*zY(LU(sicbV(nfqYNb#@)|#?^adZ3&lO8$ej0{0E+um6%Ru3w@9&{ zM7jI^&8o2dl0K`jLzHqvwUi$R&e2G5gmAb6KMIKPTG}lKexzWm6NH7RhIJlTXCuXF z!eTD`tVDHMqB0il3xtEHhVvJ2u11Q>gu|TpRSD;E0G#WDgQ$jc8#p(Kg}d>ak~Axu zJ4Aq}M(_Xx_lbZz^7{o7IHHVA2t+l4Vo}keXp|@%W$Z;TS6(zKr{64Xa=c#_z- zJAXz(Dr@0BDZ#NqdX5+o)fhcsbVUg#0Wyc~lK7kwm65WFgoCJt^D=O%M2Qy&hq?4B z63z<&a0KBXs^L@zPE}%IPQ9w6Y&iATR26GOu_h@pw_X#9`B|?J>MNpJU+Y5IOUm4_ zdnIYqVxIl@FA*TB5k!L^GD?I;iTcFBU3(;-R^Zyhab})2(O9m%e!;9U#EPiK+61hP zqeMdj<<7k^u$Vc_Z79_Xpr`519Y^n*goS7eYe^9OJfj}K>PAe=xpxD=0?kVJIrpBV zjHssk9+cmS5?Lh9o%=i1yp|<#fN7ELn{o8MPdJEbIG+ILBVyss{UZ#{Dy?RGo%?E? z07vhqM1ZJ9&^Id3UU{BaKN3S!6U#w&`%`zBbMKFQuhz!h&$$m!RU8b(L8Qo>`=9`d zLsS(Q97HvoxxkqnC1w&1bMCVxoS6Y|<`E8}8qOl% zEFc!{+!sjFtZWt&0iqf~E(n$p0e9}p3MN=V1c+(`>p`$KN~|Ub=G@m}a$KiPj+S#@ zEm0XxXM-xnc3}J%CALI~O+><+`;XQQy#)mPUfLuv8CAQ3QiQ0MqF=zaH%jb@61$0w zJNLa3(jE(Uw*Sbl&Fl9{Xsa0YB;BWb23UCCmiP7 zPf9q)1K^w{97Hvo3&1%?EX=u|la!5mzNo5r6^fThkvaFvP|VMIU8BAts`d2-l&_OA zckb6EY1Cq#{kTa4h-w6m=xFgzl(-iq?hpre?*H&<1tYxNiFAuC|iHSM)X92K9 zvl4#J{drPGR8#gq*@fR(MdIAKyQ0kv6sN=irmebf#?f1ma1hmSssQH&V&TsH1q{wE zt!8|k`)-{8NAF8SfT%|BYBb5Gn!mXD`NtfNhUjjdSXB~3R1>R#?p7x~=G?0z-@CPO z_jB$wRTV>_Seq1?bFUph(W|OhABy-XVs%NBJNJ54h1HexS%rmB$`RF49t#}&-+X6< zJNIZnY}L|kIrqqdvEm2|Q4Q-&Fva7;_>?8)+~XyxMiP~=pf@EPL^YfQ;Jk(3Uqv{~ zxxXdhv%?wv3>{;W-omUGXLs0^pmRTbl1VD!Q-CXW_9h=e)!Ue*nr2?BmE^^lm1s(p`A zgs7IH-eCI_zeOBB(uml&bN^IA`q;w#P=aHH)Q1=m)ffkYF$eoK1jw9wj>OkrqB2r8 zh;R_qaE1YAD1NUM;V|buRKgh&0B1PiAgbYv2F};S!kqiplCn|HV^kFhx5IC_620z@@}Ljj$8p4ed$LsSzxitZkv?lR|o1o=Lujk}+7 zKc=eqClpVRB6IF10w|tRRlESjbND?wB+8xpIjh3XNcyb8E>g-7)lz;PIM?vw5eSDn z_iKPSsHNRn{Fb3SlwlepjNpEm0W@`agt&sD@KCCR!AZ5kWEe z{9uB@G5$#k!Wmwz2F^n<#)b=`8cqq|6ekw$+>1-ntZYgW0iqhg;~*$S1l+loDwv=& z5g@7&JOhHVG2%&rV9vd4OisU(+T>_C_a`MP!|9Y$#c%^7I7U>65#@=5IrrcgbF-%c z2>88JUScxJ#6u}UR7;Tn+eT)_^L}(M#^dv4x$=PJ>b-h5njS!&b_XL;|+lGI^iIy;Y0!_oLHE150{jUdX7?6 zjDunfDKh6C1I7HT*BjJVM76#)hH^tv=FYvLB#m0kvmfz9fT%{$3Ir`IQQl_b4HtJEa%>|VAcd;MO0&b8?31@BAGzBb58{pGl#j!QoR8BsP5cx^tK}` zL|a$~P3Qh4um%$obMAuya9*<#e$IU;DI=;We+}gkF=7~rbLT$7n%9O&9ALVr`(_-y zqX-944QD)X#u5v6?qe}H1KfVjeV|+WH?25&ClCRm8o@U)WS*ow_dKyFB!;LaHVxgK zO5J77eJb)j5WV$x?$cEjXG3u&DKh6iGl1e8RmFu+{60p^BT??$zqcxEo}|wzY!Rg# zQ7z>wfU`VCEF~Q7+?NC5B6IFb3&vVWScqy^KLBfej95!p%(<_ZsMbnU#)7_)a1hmS zwgczK7_o(L*q-~363&(YI6DXjQ4MDgaCQ?5cka6-X;wBr69J+c!LK0rg$THF|D|Ap z--rNFjo=Ru{2n6?5d?GYzhiP7tWA!Vb3Y_e8BXV@D#lr0oQ@HH#)uO{!kqhQ>xTXl z1pHn)Au$3-_V~#|r5>F(Rrl-UH*E7;%dL znRCA*@!gWBjFjCc97HvoBC*k;P^@so8jtAAxfhD{A3+Ds@MX!sDH>}$q9dx|JOZ4D ziG?}$hb3jBo=d1ImV)A=q{y86qfpGxdOb#cMO5o+87P+~W$xTdOVX&tJp1t^5g@7& zJP(5BVnw-F@icL8=l)zQn^xf5%i+vd+C*bH_ooYHtw5}ZYOF7SwNk9`5GZ%)s(g**2-7@Vmm=Tev~l;_bI(;(Tn)vQq{y86$^eRMR24TuaYL+F zN21)hZ?GzCoutnyY!js%Q7z>=fU_-DY$Y7-+_wSZ3UlsT3&z?>Scqy^zW{4*tk^?X z%(?HCsP;%y#tOQha1hmSeh1E>SaE=Gm~%fQ;T#BnbA)gZ)o@M#=NPeY=YC9*W@U4d z2oTi>&Vt}H5pd^zx?qBHM1ZJ9a1{iXW5q>+V9xzACdY}|;&aleNxtEmq9>E#D4j3sbML39RDSHYyW#U9>!eP$6 zjD%A<08UxLK~%$e4mjnAg*o?flCn|Ho~juTaggFE+E;@GqT=l(LzOwlG9%ehx6n6($o+@!w*teJegFPXFnR@3g`XK5Av$$IP{7 zwaV%Ho#x*BT>HDNj7bF1zUs$N{jimIpM<$%|FD%gpS>?JfM>eymvQudLMVv#QThU< zH*s*c-n$ik4W(8mzHWV3LzodN16qs8Lh-LLSn9bhD0zHcSw z5ejqU-%BX-0-!7+6h!+d%Ym|#IJg^MD#@}k$t86}`|4|;zKYbj6JJ%Z`dU&)w6DGy z>Kj{$4Ftek_(n{63$#hka^V{!BEz+8Q9<|#2)kN|9j(MRqF@eumvz(bfI7ctwn;oj zh3=u$AlgsOL2&)nO6+eX_7N9%-@i#X`z_Rc5*RC-L&S$@pYH_tjT)Y001krR9g-^u3)6bgoJ1xsU?t_Cy1tm#2j{WiKwYWWGu>W5elMx zlw_bJC5S{qVGcVfC zB6URj>OG;}JwbFO0Oqi}W76BGO?sBY?kW)(E+tb1;Uge?kRaYm5bqELbJ!nPH|={+ z=l9Gz5|2@#A5&@&?Wd+cxcViCJ_#b5xVXdaC*kz5P_rd4Rydy%AEJG}FTpoBK@1`| z=CB7#Y=a~sBUM8Q1<^jrD4>i?5W@+DIqZ=V%J2XvqX`AkKFS23j3W-_u*XTNM(s{i zQJVs_$)v^{_GGB#XPLgGJ|f!h<8-KgN2=Ume<#VJ?(*!z3{pq5uf724^Ap6}1TmW! zxWk^$rwuslxj3^`n@B8&J-cAeg~W+ypK~QRa}&feg5(Z6*Wb|PE|cm*1J)fjj^0&- zglGq;neMRn0BJYzFo(Sx;@dSl;ODS^CRIfHs=q;Xe}dRY!rWo+x8|&U5(9X4>K+$I z?*T$Vw2yKGD2IuIJM6<4kiA-s_&V%;x;l>DKS&+XzWRxP4m(fiBnctf7dnG(o}z9t zhkXh;-lvVTpTj<@qIMB#=Sht@?DGNCE~%(phuXCSafJlA!@g!!(-ldZRny;;W<>jG zz6X>$3E~!^aEE;d06Vo*TMqkH!ASQB3DG`M(L`)NB#NL!=CDghD8&Py{D)8w?Pui)pgc|-++ja1$+9vjL+Xh3)t`ZS zSyJZ?yKKSg_3M21UosUW-rgclP<r^S%%=@F>?E8yq)jB2!%i%ivn_EV+UNWqI6Eea_5{ftc1IvFLzmlL zst*9~)g3mD-cE#sXb0&n-C=(Uq>qV*IqZ)ienhhaehxdER1xi~_J?Y}MA3(Yxx?;f z%~^dU2Jjr!JuZ&k&j|(5KFSwB8Au%5VGqQBoYHE<*I}R5)p7I=CUr#n>R%-W+QZHh z8b(5h_JzJiH%Cx6nZq7|9G}+4+0S8*Qc)WRwK1f|9QK$1YU5SZra*0SqL@g6++k0) zs%fI6&8q2JN;9JUG|vLcj6^YwP`JaM0f3`gsx5~-tze|tgoJ1xX%UbXB#QZj#2oel ziDy2?fzU%1WT*CW>W*!W?$4gt9CE$|^!Zw2!hLC~Jv>JM6WREGv@@q>gA` zeGAk#kvezSn+jInO6rLA)ptXEXQJ3n0L)?U#H4ploAfM)y2nT@hYohoi zQS2oO=CFUYZrWd<&hMGM5|2@#2Prj(_EU2LT*nf{ABp03;^Gebn1u6(h5EY$#tP>o z@gdshy8ym(iQ){wF^7FlVml)d8L7HRD2Vn^t^?&-qPRjR%wb=XP_6_(`I}G>?W5cQ z$}Qqx4*Qm*YSivs6}1OYyH9G&Vc&;ZewNA6+Sr{ywBN@ft?`doTN}G1++i1L?JtYE z%d-zfNgdI?`hTEavbA`mwRo5qxWg{lnoS#U*pJ}MC2by?W=zX_4i4gJM8xhR{x095$&t@g?jJS;!^@(4!budz5CjvXF2Ro zB_hM6^ix3?41__g#eml0bE04ldysY04uCqpXFivBj0zn>sX?@#no-~y*;)*5ExsZy z?yyHnIKwT}uOu*5IHQRV(LUc~@J(zj#uFTK*b^nT@e+}ds&5Dd(LTxypiFBmrVWKE$H$Z(|Yq6%aSVaunVXx!U1|0SpoaycHb=a#4=KO&;5$$vC z0Oz*WVk<#%hrP|;(B*EG>I1;Hb%%|kcPAks+Cl27JM42nIzv3nVV{9`KV-VPCf9tcwx@c=~&^pXrCA_Zp!f+DEwwl)s6CJM6zPAS1LI@pafE zb#)xQw@4k)zWTj@4m(fiJ_#Y(7Ya&>77wVK%wa!3jz?7a}rTGiO5)#D-a5zeUwT-@gxZsp)iN-kx*O# zP%0A&qJ5N?fl`GyxWld@$+9vLq>gA`y*kvZk~(+TRSQ;sjnonCt9zjyk|b&o0CU(O zNjd#SYm=Vkuxm*~hD)iVf)ELW@FY<`Nz@|>=CH%9o3=jG`8`ul;xQ^Tic*7UKQ)cP z)i6oCktAY?i#zOw63!bIYODmt3MZcU5bg851-=$Zq8Y(4huuPAYbFsHscJ5(=Vylyso9BM#=U+exZM?Y37@`ybRgk{WZ^9if(=W$HwI zM6}<>Zcyz)s@!3Bkz`SKdG?_@sUzA~e;?}aCW&52B9j=n!+w`f8*tdYaAv$Vkyv}! znFVuxK%9v7Is1aMcar#&Ai2Zt4J2mhazB;o1HdCRi>DpE{Rj!s4pR0J2mKVluYom! zn3&5R0f0%GCGgwF9!1KCYRVI!JT6I$A#v`s$60gN7>NT+-{@W!NAEaV&QIlza-7d<^T~Osu3Ik!C@lcj{I=J1b+|#q8h;|5S&aB z#|eVD@{^bxXKRzA<;sssRED!Tt%`947?+a7g(Pu~NSHIfWZlpgK)~;%a}twLwO1)c zh-xXi1GZa9;zp9VPHfzr-;$7SSh&|EI95n^i4jqav2dGc5!6OJAVB8OgWC9~?14mO zq^w9AV>1F#4W|TfinkHP+8CQL%%vBXaEjp!UzQAZK%Qqn=Bv zDn13pGNj1ddKoC@XT8c&UlG;%`Ye>6A!Y8^pOK_di+T3rIU+z*Bd7=hcN-DhMpPgU z?%LgL*t7!I9*i^dwTZ@Z?G*}UtwgMdYOJq~F??vcO>Cno0H!vU~Rvl4#JJ&KeO)s!1RIj)U}A#v{9JO*clRx`fNeWgx-qqiv$AgU3xG=HnM^qY6`#NHw?L^ZM2 z=xzdampS(YW~P6UW*1Ydw)AQ5oq zKCobd!9;+lMlb>d!`g_U1i_s9FiehXw8_zO?n5Oi!|9Av#h3_;@omJ|Hexi9Fy}tr zx}nE{fZt1_B_^Y4CsB$J)lxJAY}49^scpm*V&l$znuIjf!kr?)u|k?jjEHKC3&1$P zjhIV-%(>5(_~uGfM#>fv4x$=PE^wB$5laY%Irn7}&XNE)D+mWs4QDNIRuck!(EnGUx6{&gr{Jvl4#Jy>PPe%#Em~TpY^9l0{Jx=gz%Y zvgzE5N*rL?qWfkXy^jzMq8d&q;5)F=ks@>M&jnDdpsH9Aitc0)OrqSm zyR8Zfmh@SLRicz5s-;{2=cQ!vBH?i7{t_UzXlb{c`-=r*y+T-sYFM>^RU=tcCoJaN zYe-bpB`RY0TCdo5i|uslVs7DAeeJ+g30k$ZF01ndt-^pa5~LYF_M6hm@HZ) zi@G?Uh0_Q#$XAWr-jpf`270fz}SP|7&$ANWBvKU36+_{hOH;1{S zqgrwXNdtkM|Ho9qxV-rL9~x@7$^scgS+*E7?4w1o%p)-)4Dp2-rq?b(Z2ez zfKEM6=r{=>+7~*7Zl0uWGM9c5IXpt)g}wYG+A}IrOsu)Gnx~U4z<{WO0cE zxjVmNRnsL&n^n_alx9TxX}$xLTgl=Ep>St@3jjy8R9nvcM!`sT2?^0YQsET5L7pNW z5E66cK`H)34faj=Z>pQVeH!Wf~|Y2?f!9RvrgR zDdOO6yp$x%%A_=@BidIl3-u>SojdU-3s!%c)Di8gSAcr?6!9zpFc)4v1wR}?oAfLf z{;Wh~xE7}h!izwtoFXcw2scqM2VObF+_b3(b$-vdB_5+Js!(bW?Wg87a8*kYucin= zT-<$ElW<3a19~A=>Aw3qEg(2q8G;yuA`zh(u(h>c517XdfjKDB&rhKA|wz z9WJ5N4}cOyD2Vn^-T+E0aWKanE2$c_+dxGv9%_w9jk)bcP|MFUHK9Ht+V5j?s5T{4 z?zEdqvZ%W}`_O{a5$&rdLp>=)B&LW~#K2v45}!8UvJ-LUk~Wc8F1uC1oGHYKXrHqq zINPU)G=k&~yFHMYq03E^>I1;1bccKR|swsdIgA`eLK{DOc7fMfH~|RG3njcCOykx zZ;^-$m$E|z;TIt6O%Z!i#BQQs4tuY4)9!&fzh`z!JVu4?r_>H!Ii70yxOL$uF#27ISd#7Tl<4*QhEc2XiTQgxP45bdK}0m`Kmae+{n z!@eY;TnK=2l~54vquc<>b>d(S`?{oR)b33cwYyNeO=`?x--cR#mgye#5z&4h9jVdc zA5!HG`yWXbb(d!!f>MpW5k&jyk3jw5RPj)%D3WSyk8p?ma4MTN;IJRUncfwB9d?ma z|MW1<62ysUpR)`&OQ(v*2$DPO(m-N{F847Yaq|P<+q%QX(fcGJA=*KzqdV-%K&nVQ z%wboAct2#w-(kN%s)+VgUxDh&siF!AbBFzMs=0wtMPdL?|BCw0RH^9jzDg*F_EBm8 zr8;qNhg}^5@`Y9-z7Bh^u8yO(CaELZR}W1MaK0cuMEiUrz&9*a3?(?`u!l)(LnR_3 zRU-)n(LTy}po~owqX~sM?6DHc=m01a2nEqT$`qhXCJyGXCrheE?S8AGHXUl;ks5Q@ z-$5-u%QS=fh-kl$bD%nlRJp^RCCQ@h^6bN0Qb)9}z7*<L$*#ESP7Wdla^V#lu?Q;5#((HiW9`=KF#v>7;ebu6A_vSGf)uiqm%$japK?(yLcM@9jsO(z7Bhau8yO(B&j3XSAQ%mki*Us zdYpt1?F&7LZazWXWDffY-VVZb@0GPvWh)Hj@HtAUo`wfZ6a4GRB2(5t7GEFp3 z6HSSNIqa6!P1_vm{GMql@fa1FK&e5rpPIM9m6|4!(?k++afh8M;UrtANfH<P#qz_E9o{(j!fDBNXPadq^nV0-$6O3Zi|K_kr>* zaWIGduB2+z?guJrpFr&+QezJLBdFzPnLedHBHHg`U#RvbRqn8ROR}iDJp0g()Di8g z4~F`nG%+Aed`=A9VGrWd1|0SPoSCmpB$mVeykO2D#EEF1a}+p7ritMM$sP7ce?yl$ zT&fQMPuCqbj^5FPglGrJ_>{;3Ak8Npwue0*;tMr9;ODRxk}9Ho)#XrKnkE*LFn8EX ztvPG4!~mYfy2r)Qn@cE&_EFXVWfgI7hrJ2|vRbPVUx&R$SI5!2medjLtN#$tVdn{L zBq2omLR-c2Z*wdwT%2T`Fq(p!Rc`_=yC$!~WT- zrk^BjR!zT9ni1`%`7lrpritGOg*)tn09dT0+H%;x6^!&dAtBmF`V&Ye(!?=BVh;O+ zM089dG8W}igo0=v)vaC$5lRBb( z_1jRtN$T8T-z-@D4yhyBR}V_Z?+8c}_X&VG><5_i)@zfV<*@HdM21T#l&*kK0tm&^ zMX_{IG~L)`VGg@^djGJj7Wm37mhOMg6vY`nVHp)#GTqp3LA0NmC&BeZx_CTYlp-$f zu%D1{9=A|SNnosSo+3U(`+U!X@40kQj^LQXeokU5ClMK`sz4}+_E9PU#gi^vgu)!Q zM?!H0K&eb9i1txl21*s;U=F*Aq-xZzP*JM}wO2`vIqX-VmY-#+PJKkQ-^W@|twE~X zVb_pkQFnRvp*E=_+E=d+^?K=|Zo2Ri19#Z<(%G~Dhg}zEHfa-y<*>a4bA}NoqJ7Rc zz!{q^q6v~a>{uW%Lzf#Z)dzrA>kb=7Zv#R?w1brWmH9JDMgVIVF)^1t3;fQmZ&yLRK~*nBjF&b;rs-gUFl*6;V>t@OTyU^0A~;3AgbZ) z2hKiX;ck4NB+bg^S0X@EBRC9#gG9g``N4t-ekTG%HG-2MIG!$!5(IPQ$1ypc)FwyE zl^>O;3}^GFD#j&XTu2w^(#07fVb1)5bwi&60l$~dNK8i6UZxZws-@@_*lwhY>*?Ye zv2k~PLqfW4;a-#ASRvgeMnpBnp!RsUN*DJDkU8`R65oA^%1BwE_Qt~uq8d(d;1p{w zinceNvY1OR*4}>vi{cDlmJFOn2nSIOrxb7=B^Kt?AC;7idVWk*u?!STlOl8LrJWKE$NA-+0axeWH@I0Z>B!p;R zXgs<(mb%GY`dH+61$yc4(kG~>eFL>gq{bZjqyTDDRMcibZCXz;l?1svpJr9lR7smv z(@aV;qWv^~50rU5#T-K6&U_vKE-`05r(mQ7goJ1xDHlk~dWt24#9a9@iD-#LWUP)W z2nEqT%6g!z?I~6h3UlOZC6v_xP&N<>qJ5MtK-okb+>LLNWLcSPC3Qsm>N}ynoz%G# z-(Il#E>cIdul@_v_x2Qf2!Ofpy_odYXp^4h!uLo-hHKfcg760re(xy`^%Mt)f;sTt zt(*1`)cHMgK;khf^eCkU(SB;qg6nio@n=tQg1ET*J}u$=X`!Bwz*ym&BR)j?eAmEt zrKh+=aLjpMk=QOtL`JIqA{0dXD0hHztEad@D9m-=l2C30K)FjOi1tw&nfTX*#K9c* zKa#3ZyFr->YDJ+|IMZ0RncFU$nZIRvD3d-VtD^b{R39c)?zA74WKnl{_Mrr+Bihe! z8K{@e6pv+!{}2Or*`+htv;mj>7|yKMCKAhK|EFNiCy5i$KIik`d@fUzBS`MBp92yz zbh+h##LW+Yb2W>n9laF@3Gv?|g=WSF#p$2#J`bd`#KZQ*&q92o=DhqI_61T!w6A&% zs#h|_B@*Ti`%0$iurEmr;Mt;kTpYcB5elMxlv_Z#K^)v+-@t(Ut<{L{e)tVt9Y^nN zQb)9}em^si!_E`>hlCLA3l++W7LF`qT3`;_k(JZ;hBnTA`{0GM6x51AtthE6hg~#) z+QTYp|AAV`Eb#~la)(_q%dDnHByCnrrLv595Yc{`p8`smEK!*j78Z=D2Vn^Dg&irmT(gabJ!In6n6lW7YGH> zK8gU!OT@t)_Dhm1E0b499nrq}Yf!I7>fB*hD_Fe-sUzA~uLJeaEK!>Pn8Oau%ISAU zoAfM)U0WhDTuNOPgeV|HWQnjW@j6j3haF+vv|&)^_sr`Ok5Qq~lo~|)sfhP+UIKpzLr^{Il(c9-BMy}E)f~2N+1+O`zWbENzM{U zgu)zlvV@Wp0HrOVAlgT150o_GU=BM?QZ;I~gNj-wsAZ5EbJ!VB%g-`(ramIt?_+nU zb|qEru)9jKsJlG-(1X+w?W=zP_4l&GJ6R%&7`VfJk53zL*ze%XeQhGK9ClX0oF5V= zqJ7SO;OvtnvI&wq>^?wZhAuZ-st*AFtvhTSy`K>h;=e^YR5m`SbbQd`%^Zl$9F@8@ z`~Qgh4)7?dF6>>1q5_|YjSob2cV>1*b_W82CJRQB07)oD5mYc55Q65TN`k!v5+L-@ zd+)uM(0lK__g+HpCI6Y3JBPh9bMyRW{^$AQvvaeX_dV}>&uu5OOROP3O_d*O#^Rl? zXFmq*;llfw?O!h@W~O%)LzPZ!d}SBbS#+dshI5{ zDnP~T+g?XI?@vE1%S`X=b);n}HnePj^l+heMdkHc@y-%nXS??mrxoD>&;Oh4Xs7(> z{mk_AA`VyBi(0gj0Q3IuC#_F?jeXK65V*6qHi=Wp``u5=Iut7CNE@J_gAt(ePQ8%# zAacC3bhfh{2nQwNT}T9UA>LWW8ylrX7z`0qkIH8yHDjQ))}_3bHW7wOeO-AnHt0!F z<<;6Crs8sgB;551)N{V4q`i1dJx9H?T=**JTozWw;dB;tI-QHd94XBmnFSpMLtb(? z9ceEWb2y3?c(I^!Ekag>Ig*?H>gePIObB37oz4|3)@EdF2y--P-Lg&Nwn>i65IuTH zJ^BuUQ>FI86Nl<%mmzK`9e)TR`&p2aD18hJQ+AKAI2Vy~F3iy;wQW!$+Pny!oM%|f zo5;+uW?p46A0qRfHS-ROnTyOPEXWJt`oILQ0P``*6IA* zz{cs6jO=CxNF9Cgwn0cs^Kdq2v3^EYij}QT_2_>PoVt~y!4qvf{xZak*YO<@(t!o( zj?!JgFtwF*W^wu8Gfq;JetN$$;tfDZyfK$Z`cNcDM$5bcx{9twe?=+IW;T#BHeKDcN<(c7RxOY^*FZr!6~R4E?Pk$Wp~7+Vyf|vzqrXDW%J4*++!YORTkH4$LOx_cB2hX53{zW4RTd`>IW-~-Tgi`V2CK1{b&(lw&8)*> zHbmxE*39}WW+P;N%YrmRND~&M6+pCXH;=HIlx@|HC$s3kqCz|KyhyR`(NC;k9WdBG z*37@m8h@~Yb;Dqp*1Xw#pLjjPr1Tf^dBLQm(7vvH%!JZ+qfTl5s(K-p`C=-YJ2eT;sGo*jGC*tb}` zT;x5WdFxc(BNnevl)lr4L{WRO#w!p-@8RgPDDqxmL5d^fRTkvG0MTaSTTzyK;~NI% zK|N0{WR|vOmSQnQWb)Qb4~yx?4!vi9U|QbC;GvLCdN!70k*Xjm3`mCActjn)$}H|q z^t3ICF8Yt_sXBm=y-}v3e>aPD3|WVxEQ%i z0wHg*ATEGt*)APzRrFt0J6?)KFN+Fdv}s-l);;1_!75>}3f9c>W(}DY>>~^ounrc+ zVpd0Hlr{4c7PA&GwPeP!AfI9IItB=?wfYFD%Yq~#Bq5JcYZz@+^yjD}`ZX(bGKOxZ z(2e&Glr`&gHZ`zuQvQSNKY>kE_jgq0uhE90|318|uKP|v)smMUO&=H!bx044-Zh#! zXmZuqnJiv^H&tF1i#Hs3L#%j%SiG^w8^wZ5LdbX)WF|nggiMRJJlLifn9kQo zDi;Z9Sj^Sfp%n%Q4&NpWz8=y^A8cz`q+Lkb4kW|D76LtXI=8U6 zPtemt!-OrQr>bBzedl&mGi_kcSge^i8h|as?mFTF&$q5 zA#buEWl;JZFiah6C0QI1Ieaz4@$|BqK@W==icHy>>0>d&kXhN9`96yofy^o_NHv5+ zvLLkqqGda-n$^Mfy4vv=7X3?9_`*CdKDX{sJS$iu4EC)x^Bc2916HtP4A#s#SW_1B zCuFv=X0~84e*vbJ%v2WSPYnK>0fK9-JwpCwLAoI%Gmla0q%1nq-K@9O5zSzQ?vJ7S zu-2^8nPp((%3Or(`36Wyeete9$WrrgE@rXTA#1gjEw3JZGr_4_$qsm;jmK6)Tv5mG zMaV7|G4ug|NhpHMmsybF2ziwSDG3lQ+i%BMZ6!_Bj=#yG^QhpC zF&!~wtb0_N6|5Wv^I0?BGi!*fU>{Sz+zShrk2bo7NjNyk1;@S zt;HjxHVe`KAz$V(YV~5Qwvr#!5v|J#-2_87Qs~BCaFjLcbbe=G<$LIY0bQD*0{zB_7sCXvJUou#e5-F-`xwu8g_SW8aQI<-5uv; zVPI;>e2E1qhQW&(Ah_1vL`ZQKqzppdiM2Wav{5S=Yqgd1R!6i1EA)F9+N;owTZyt} zolf4s#te)>_DBPy9}v~`JsBYrVoj&dI2LOrvZh(t8lp#^M{ufCHayYBV}T*=P#wP< zAxl`0btt_W3{zXlN)~4uayA?1P#ZOa8(GZ#$lPPi+{I!ZN9GZ0<{=jIEHY2AAeRwx zfd#n*5G~u+Ehps&wd2=V^e3qB&^#~hTleTLE7*&1`Wh}6XIR5p{+)5AxtGfd_9_M| zVjb+2IC?|C+4VLu->_yDXE93yQ%hz^7Q}Sq%h&o4rhZMQcRUc)_5C+O{`lH7oWHSH8OUn? zwS}$edh{*?r%LsNC)#*)GsK;ttz^DBqPeWl#V~YHg>KwRlr`&g7H&ZA6Sy)tWV;NIML<;7cUgpp z4NO~!z+#0WOSZDLQjcDl;8dvqJkiGELqptEI{ssXRAoVGpma1CrnZtu7Uxss)M{YZ zN*1dbjAJpsLS{W{W?dFD5t#|r%!Vvx5;DJML7F4vM;0UnAX>KDSWe2dYR6l#=zpQY z@8)^&t96flW(Dhv!7{9w9n2bOtYBFftcP{5ZY<^?WcIga_GK|g08>lmP!?n?1|MaB z;98r6knt?Y9E8lwW7MWwZY3Ml5uM5ky%a-dv(~KBxzNDImAM<)I}DI5`rh&>h4&hoju_FpM*=I@2N>*qYi0$rMtN4Sk1<$P>tF#EGX|N}teH_PW*uN^$*jqO z)WzWO1_-XTuMkp?1!;_s@A4S6goajC$q{u#8?r(-$Iw42bYoSbtXZeCnSqVdIStu= z86d}jsIKqM2+1%HX9pIm2eP_a**dRB??Z5^)IfNmjYmI2+zUE>7(xcKAY)N_6d0ze zk`XM>>`VK7n!%LnKxL>$H3H* z`G5s+e4`&aPYn=UYcC+Az&G>(gpgMeQsf(}13(+KSH7{@N^;Z@eTfzNzZm*0g>KwR zlr`&gzF}bF%B+O!3I@ncAgb%T3PQrZF`Ygiuvn4Eim)`N;8dwv@I)JrSVP=L zI{q_+)L}usLg{*7nA%F}vN(yzN%+Q4TijMN*pS8i5t&KW%qA>m8)UY$W;SOre@12s z3-TvIeq%v00HS5Pz2&5Qs&@Pz7QH7bbTiM3F4jHj%nCLLgY~y&_BCttW(6CK!A4jI z8^&TzM&<--<~SB}CNQ;RPGdplVer`o2(Gnkge+h|)*xhM9;3G0aw~BbS2lyCtkByq z^k&wYbvid1*tjyUAp4>L5(2X7`o4vb>*nFS#$r7{)?F)GZ|KpV5}YbkAVD9GTtnP9 zb$lU&ge1`WHbVXb5bciu6;3d0B`>o$Zz1RP1jAPHqMHBLSj;lWe8-wulEoB}$y+l$ zET)XivMk8^2nl6DssKcr{b31K=UWN2;~%i-)lne|(royv%%52ID1sF%9)s1kX4W)o z#Ik~Yjlt?$2m6A>Y=q2jt(o7jn9YExC9??&(j0^TXn^2aYlD!MEXeN&`6Z80YnNbE zmAs>lXbLNI28M30(2Z4zvSyvme++C~b_0>!&j2X{M0I_SK*&(@a1Lg%#vyC8l`T<^ zKAGTDsTuG@8;_}mxRQ>ai;!6?$YPXUXxvKXvpB1fv%)xs+-e4wv6x$sxzU=rp2ggQ z%$?TE?JVXYWbS7{P9Wqc3vvMt&IN5Sb6LzH$b8wFS?F8({K9!z9GF@%Uu8kw#^7%lAh_1vLCAku z5HCWwZ>nuLphy3T;8dvuc%qF*14G;@I=(SNzGFdtMCl|jO#On>gvDutoR-Ep zR7uTXa~AVAWd3Z;Ol2|KBlB--=ASHPXJlruAUzP$l?CY!5G~t%EGK1z+VLzFeIzOj zGtY}5);$`;3N{&oO|WK;Gi!`t1)GDxW?BcE&SEY`=0a=cd=_&hFtubZV?owo@YMzg zuC>hw*}#JAMaZr^Ms0`XRuZL-=r&g9;~4q~Yt1^HhYW07nFYVoH*m*y^nP1iU%am% zq|kS!t>gt3s~ED1erK`6eW6Exli<{?q$E7i#^Y^6+-)tVV#F{>jpiUp~KkXRPv3xH_Z{_H!e^X)6O z@g6|PUh{D7X0eVT>#&urW_t9~1gCB#7vPCD9%l`4f6(z)5pszIxsB2{j9W<# zi}M&c4~%oDk(&Q|EM`cez8O0c4V#e0%w;i)AoFEwW}!rScgG|YN9L<6NC||z$%425 zqGh{uqSaRNKegkfSoE@}ASRlQ7{R(n94lBQ3|7IKS>CK6vx0qu!2;I7!dT4e$c(aP ze!^nb0;ZPCSQg|n3|_|o!L?Q&A$3`hM1&;dF=`DHt+tX@>WF^L3Z0Chn<;eTFF4AY zg+Ih)VB@6x6WPBRAU^?7UEk>lNiz@U-z-)aWOcH#^_w2OC&8&wec_2V9$ALCzw7ux z2rGj$tupA#=Jlb1I9u2$}P(nR8jp<;YyZf~-Zz zDi&lbK(uUcvYeEEsU6?IqVGqAJ?43_%eqH9Siw$Wuw&NDBW8_5tYDWg*m>(Ne5Ymzb`4u2qw%b`w$}F|xDJ*&iRQSg{FaEOb(I2c}-7#1fYi4J& zMn_h#{ur!}b+9ZJb2u`GSThH)m}7ydC36%DG6{o^H$ZT$O-INS7Gxnp=H)SJb1b)# ze(H$MVufCXp_jAPEWDL$VB^ZnZK7|3Pnyts)j)mmzSvZU6l`kRN}Np@tRl#Ixv9kt zH&KuN8o{Ys$y@M58;{owaVP2cQV1!*f_PB63>c=ilF}?rS>%XK4O_`zHU9#O`93m3 zt(oOm%qqwXvu1w4Vn!k}f(3~|NHrED9w1t_Yd5tz-=?Y^ugRh}K!q>O^P--0kLt35 zHNjwwteM}LH4<3CT41nb>tH{yn5oG8$(q@k#rz$ZS~7oOLH@zue;OdT)-n*%o(1WN zkZyU5S{G%}neLU$R7bQkEA$`?-Ji8)ozA`nHm=M$$ew9{%+VKbHbNGdhjSi_wE|g7 zt!ypRqpu}6bt~BfPqgt^Z-~2G$8Sf-78Yb5O7AvqB|BN1W5_vdoI~@}{2yd7&m;4U zHS-jUnS;zL*33&R<{f0-WI-Mw6|S1+#bxUrU1SA&h{5hzGw+x+Zn1(DXr^y+xz@p+vY4+Rvrsd`UZ_oj7n;#~ zATLPoM6lTmsC7^b$8aV*Ykg2B)!@i;=m|nmM1vT#d{X*34xr z=0;?$V?nkfWD5(jA0S$`_q4T|lo60~r*jvJei9Xqndik3>mD6q1-p#FE?6_qnKjO^ zg5AboH>`u@u$YgL`M{cakHvJR=*fJ>g1iV2t&A&}!dPpC5%LlX@+Lxxr?5w@Sc=tF z5~+^pe^{Z*VCZ)gx^XK})~wT6(!j=*c@^2043KL2;=PTK8!4u(B!|U%h^%{7w%X~@ zpAnq8l@v_X$HS3IC;Mj|{}Mu8U_o95h&E(JQVm`ZD?`p?CWYKG&LNuh=@WJ^=>mGf~ z3icTWt7FZqW!8ve1#5u8zO)WjkHu_^%07FKBJS z7opXb<5S3Ko1p)z=o@Ol$El9SK`#zhOPHbsi$W|%J4c%^2mmE$ zHYrsp5u70*@N#O=kQa+MUQz$wo(@Ohwr{?9`C6U!*Vf+pBs;5eg@XT^(CP(;!x0@w zsGpM5HYMTLq_(YpO{kWX(mb_wn}jcuQ`$9dQ9r3!vfQ$9N@`NugzD95$#HQBzkX0D zp>9%(q{b;p39Y~XUqXDFq*f^@Eovu!AM|axHch{G+`3u9QRq!iXLmPu7x!RkfqSug zk$btc#=XzI)xFcb-Q7oe;C|wM~ zH;bG33F07Oq%cGnCk+!a#ks-)VUuu3*dol5wh4#D9m08Wm(W4lBkU5d3Ujqz*jdG23O>j+eO>xa|&2lYt zEp{z+t#++-ZE{_3-FH28bq4d@+`Zg=+ymT$+{4|Y+~eJo-3y>Ai`{FWBio@X``jno z*WC}GD^J{+p64C8?s)>8nZRXpTe%b5El%muD1I(<3pxc|JHg-LI|_rKTf>Cm&^@hN zTZC=G4q=zD2Re9F$Pum!cZDZHdv9lNKko$ZB<~#WI_TII=-xALrr1^NCUzHlh&{z# zVwTuP>?`&c2Z)2j!QxPHgg8{iOlYU}?BCQW_O8cY((n0BvbXYnf9hHtr$E6d}N$HeyRyr?T zlrBmCO{*N@aLk9%THu-wi8{jErU^94%ZcMT?yA!a9s`8HR{-| zajk<9UJus|aNP*kO>o@|*DY|}3fFCL-R>IV+5z9~bj@?^0^DwRWe>cv7hc&1uk43c z4!|o1;gv)1%3*lr2>3b*ddJ`=$KfX@;3p^HXQ$w&r{QO3;Adw6bq-MH0d)aT7Xft% zP?rI91yEN3bq!ECfVvK-8-ThAs9S)#4X8VSx(ld#fVvN;2Y`AAs7HW$?CR}$0?4O; zdFwR! z-D$2K@aXC80P{ZGo#oDO_jY%L70}7u*WKCO&zmEI0AnODMge0qFvb95EHK6aV>~b>0Ar$ihHDbACIf2dkYnFSEYqoo^YmR$}Yc52Z2a)DOqy-RZAw*gPk+LDuV)rEX5_l|iuW>Ddh|3}3 z3W&H8BCdjnt0CeV_e}R%_bm51_iXoi_Z;^I_gwczh`0$NZia|kAmUbtxD6t1hlo2M z;!cRT%bo7p4UawUW$wKYc^^dH503*7{UAg?1kn#e^dk`cC`3O7(T_v)6A=9*L_Y=5 zPeb%G5dADfKL^pzL-Y#}{USuaE--qZAAo@dy{s^K!hUiZq`cro&*E4wJf=Zg_g1f!vqPv6Vk~`gV*`49J z;_m1+ZSC_3&KbdU~#My*$^rEKd&C+jE`k zoMbDtaHdB6?zJmiLX9&y7xkGT<^C)`NS zO7|#ujP^X`#(17_V?DXtI8Pcs-qW6+;OW3m^rZ8XJQ@6CPe*==rxQQb)0v;<$>gVd zy6`hRUHO@wZu~4ycYd~~2S3Ntlb`G9#n1C(@$)^s`33M;=;^~R^7Q4iJ^lE_p8ot2 z&j5a@XCS}KGl*aA8O*Qn4B=OLhVrXC!}!&n;rtrU2!5?+B)`rxieK*;&2R9G;Wt9e zO%P`@#MuIIwnCh35NA8Y+2I+>?}RwJAkJ=xvj^hrg*f{l&VGnh;zv^iNEZb%wO?L z;jen8^4C1m_#B9L-7}rP;hDkTgzs;`<2F3*z~e4F?!n_eJRZQ~Av_+z<1sv*cxLiX zJ+t^{p4oh^XAYmn&EeZ~bNLS3JU$&B8QgrnBe#I>#4Y4IbBp*)E}QSdE#|v&OZaZw zQocL4jPJoM=X-K1_+H#fK8st$_vTjfeYiDzUv4emk6Xw0=hpKBxDEV3ZX-X4+r$s% zHuFQcE&Nb!D?g0e#t-MV^CP$&{77ymKZ@JMkLGssW4Jy1SZLZ3GTM*asSW%-|Rz5TgdAAcI(*WaG+=kLJx_owp%{2BZ}e@A|h zzY{;$-x(g6{1AT^eyG1IKg{2aAMWqYkMQ^4$MHSk(TgAH&*Dem(Jo_{<)-#>w0;Gf7Z^iSd!`6u(){we%o|5Sd7e;U8kKb>FZpTRHp z&*WG5XYnijv-ws2Is9t>Tz-vz9>3NtDz3^RMUk`#10h{2Td${!RQL z|7QNMe+z%azm-4g-v*EE{4xIy{o^qPd zOKvY@$sL5=a=Oq*&Jg;_9ff{!C!xRGSr{N^3IpXX!XUY;Fj(#;43WDFL**XAFuA8N zT<#@|kh6r5a&KXj+(#HK_Z7y-{e-b{e_@T@=@Wed`vhe9~aKcCxi>~N#UY=O1LDS7B0(Y zge&q{;i`O2xF(+$a^wrbb@`%jL%t;JS#~Lpa9Y z6pr(^gcJO2;Us@YIK|%;PV@JKGyHwwEdM|_$3GO#^N)lJ{A1xF|3tXNKNT+X&x9*{ zu5gu4^IqfIdvo{>-s^n2_XeNgy~%g<-r_rXZ}XkKclb>2UA~L=9^ch_pYP^A@@jbokxL)4%T$cAS-`o3y@8f;S_w_#G`+0Nu{@yfUfVaIc(Az;6D0IZ0`{GwQi^|*SpR=4<7Tq z!-NIi;le`i2w{$|$B`o%i7M6I&2urk?*?&)ccZw| zyGh*T-7N0*ZV~r*w~Bkc+r)j|?c#p#4)K6@r+Co2OFZP=Egtsn5s!HHibuWs#ADw5 z;&JZ*@r3uFc+z`FJmozsp7tIQ&v=iDXT8V7bKc|PdG87F0{nt{(R)g~1 zc+ZMgz30Sh-t%IP_kwucyTo$?9yh%g#arG>;%)C`@s9V3c-MPXyyv|p-uLE+54_jK zhu$0FBkxV|vGb)aA^PZG)y{Du!@to9NJTG++FG%U)MJYqPBy|)oOP%1+ zS-d7?iaAmjcytwW0^P)n*zRJ-*dF5XsGj19s9s`vbe7mDwzt?hwvU(@+gI!o+fO_h z)n7anH9$NaHBg-686?j23>N2khKO4uhl(>|hKai?4;Op5Mu=DCk>U+`lz7)aTAUL) zMw}ZuR-6|)PTcq2cyWH{1aU#=L~%Vo2_BQhr~WD826?J@z&%au>6$L~a?KF4{4>QY z*DSHOYqr?OHAn30nkz00ohL2|oiApGE)W-oE)MX9x=Y*=6 z$3=0F>ykLhe_8DAhu^<_SH<1_YvN#6jyRCNF79yOfd1bU=g7Cj^{(6EW&a(qyL?w% z=)Wi4w!=)^Fgf!MQQo1RQk~aHC zOPhUTAnsV{c<4CkMCf>UOpvZ|6QyykNz!=NWNCtH3TRJ-$294NZ@Tosl9)mG|oR?x+*S^_P7^HlU$3WJ(aVieXhmQCD#&ZvTLby(YFjd zEthiLE8wwGnk1}}rn**3UHLWAG}l^bsJu>^?piO+aBYx|`8G=D{hOpw!e(i^e~UE4 zwN<(!Zj;vgwoChbJES=kcS-~KUD8N-w=~bSN1Ex{D|O=cNsIaY(k#~jsRMsd>gPWs zJ@g-zpn8z@@JFT9{4r^)d|cYWpO9|4PD^v3n^ulbnk6+(Ef*S^<#42Fuas-r zHmOPK&q;7k3vTrR#`(AME%jBdNpcIm*$?V#1>joH`HupnzEsQ)E!5Wv!nL4tDNh05 ziHb>XrM?XJUI1eXqhXSMRWZtK#e&Y{UyLXTpw2W;Dbu)D~(=p zIC68Hj;5Xd9@#K4?AhER;}1=(Gi~Vp1s?Agt9QQbbi7`qkVE;|w6~m&VnjPQ;mS)& zy8Xr;zEVs}1WCGrQ&K*~fcwNz?33WcE4UeNI2`XOBM|h3IFfwjM@pyzZwGl+{-JH-maZD`N{UPRHSB};66z#3Y1=xbb+c5Lc3;``MQXdI$*mJAhE@nqh;H4o zWxH0%slO$B8J$qCb?X)>33a}JZ!1(PSMkGg6~il32u=7txm7}J>y*^5!#+^&KsTva zu4#)F9@ksoOiul+O;Xe377n@D|NY(U*4l0BgeGl&Ym?eKp>ay93JJ*-nb-k8CguH#AAS%9-TSO*a^oNB zv`dA#6&n0iAv)UeT8+|=->l?}NrYjj2$T2qQfUi+a!i4#T;j{3uv3*NtL#@L(q4c! zDWLVKSHJe!OX_RIr-uDs_d*}Dk<^sjHe`LD@-zT?LV_!S; z>5;c9xoVFowdN1U8ui(!=6#ny4(w^e)|NEqqrKpc?aw~Y(sa4|^+7fM%{JknP`pfkp zMLRv7;hDGJBaNsTQT%X>?G!1CUkzSje}%oHYZqK3-a9gM+Ll+&6+iO!zYcD>p%ioe z8PfQE)7RFyW2?6*!gG(V{wL-uhq9PIYxjMNNPfUS#{W1%}TY-QNzxOjNs2kmq#>`0DO=SgBpYN8%E z8flAl)Yd3atNwLjbY$(?QIXNL67h5Ajp$0-y#W~0OVbw_Lx$G zO&~QT5mpl_j)G7t6valAVymQI5?i$cXL{O718${)TSoD{_5`WghFRSIY#6)dH7 z+f)>E0cN%8y<`L=3(_2%q&38LD=I+Kq@*?~3hhKel(lMtg=hn$h6PvY7N@}K@ zE{?Qv@MHK28BK+OX^_~YWt&75lo_JUhd6+)Q#@zDpT&atR`-j@;3=mid?wghuga~^ zCQbcMvkQi;RN*aXXG~VaKvh^w|h=saiZtyTlsxKaCDb!A)wset;A-ZT(BD#1^d^gQo&o z_lASqCROgp^J!kaZrwy8TP?C)B!t`vF!(C$XjMx!RjqXa#tE2P>f3n`Znlb!VJ$!cX2t>!%`HbXW`Ro3w ze*IeN5>;w2ZE0e@mTJoNKB!=Jl^qt8OEL^Wo5^-P`erRgd{oWq(e=Q5YyAgjVj#fR zl|#c5BWuUR*9{(t9Xe)%MvjV)uU$RzQwMx@N*UdCdO~W1nSK3IOV7D7`oU3m>QT=d zl!I*V(lKqLTl|<6EPATB? z0SswJO`_yh@F@=E(;wQL{}5){ewaof_oxM;>=Dlwh`uk62k-%P&LvpPIr2}79BBu2 zV+~BGpoMTqLxp@!*=yCVC3;i#h{LK}e3-sOAS*$MRQ^=Inyz%*{;Ym_6qZ_|VIgD6 zkLfYqc)k(i{60ZUZlkiJ^a2-RFK~HMby-M}(T$SHst@dGU8QK1=d%$8=_MlIhzvds zTeWVgtP-nJ>Z~etIMUD^2(=H4z*orkR6;4Q%Bgcs4KNKeij%vI^1C+h?|kW~{^e(h zpVg|~ATjy*jy(~ao>#f6gVuWF7qKAy3y~g7Nw;aOd|F96UzDx|&^=}5 z1Nn(YF6@|%bH08(ebEI^_=|cDPnwn%4%j7%qQOdD>~#m$FTkQuVx zLNchXDRmi@rWb6swoeiq{<&1SG&B1I=12(RpQ>G3rumJFtZbe^N#W3Kee2hA9JFw-P)W1~V(*^m z*_naMJ!mrwD(rG~-~x*hDQFTo;PasH74m}lfN7V~_y^W8)1Fsm@ZdP74wTIrM73JQoh8fI-T2>OC18gTm{-48}$|l-i+9yVOMO*H*o{TL3ev8{|J^9JL^twtIex zR|S#o3S>7mmZYZCPryEa>Y)zg_g1q#$P<~Ig&hTOwi^#OTp9n-d%sxAZhUmT>K1#| zca-_yZQ*sW)l0RtNQ+SY)B1Iww60gZ+VdfTd;X4Bze!6|a{2%5E51xxNC}rC-j(*u z5&wSCZ;L~*{?1DUg|u0UrT@Uc!F@Hpz|^pKXWBq`{ssK!T^d$HUL00C{x$gi^RQ)| z;2#jAy#O7~UL2O0p6T*urgv~T>MPgUk;)GP%fcM>3e|UA1ee8Fs{^PtCBCB<0ZBOZf$`b1qCiL+t#c+YuEz=fK2` zA|TvTO?yvQ_L;nGT_m=kwP))F*vbi$uM%55$tLig;ws1F>Z-|=wk_NwcA&Lq=K-9=JI}z*6XIpCK4Ly4H&0B`)U?SZ4xqK?ASAqoTp(QA z83s@e3WOV%D&^pXaBZiC)}DhR;NX>T`6XiFN3wV;C|P(VJTqgSvN_IIH^&*S?3YZg zv<;-FT^nzKjW@#O;^A^J;-np!9AS!+H^TKJqc}LA*HST)CvDcgO;QA{y%f2?+q>cN zJK=Ik;_VxKsH!OD-Zfcz2kn+LnWKi$O*}$t&*OXGQ4E&_VlX3kWr-$#g2|PZva-Yu zwD#;&06XQwWtrIN5^Sfu$&SphQ<2z#)}EaY!A@o3Wn%F0RN17g&F3(?id8`|KoqBt z-m9fo02HlCua8Jyp|#i7NKpQmD34R-sZ#5Fq|DQgP0}zIpVvB3!~wMS9Ml2_ap7`I zxLlq1Xr=pzR(!hLG9Sug6 zQZTKiV)P5JMHPqHpPS|jm>!~(i^?_dC9wrs@$7_fo)0!XQ3|f0)|3G*DBHg7b_rDEhfnt|%xib-^EB7uq!#bPvsTtOtq#Rm%Dent*dWXxsh#k6e?+qr_ zDrv{cy;t70`Vm{u+OstbYz+yQ2N7FT-KL1{*8G<>le>QsRWF+*jg)UJefEwY1da zNt?B6NQ$7fm!hrUZF9K1F7P zK5JL;A}F3Gid5x(9u%!guS=w_(Aw+kHBi1nl6E422!Is-N2+;I6RF-lkNxyIr!`>AQZ zfa&dO>+1~}pXT6+$} z0IOzyE+!E%Xzhvlp}S>Ccd44aEM)qyGUA4sUAC)O0Tjy{VHYB8eer?HP&# zLoorlIx$4m=`kih)y;ljT{;3ai5+O|+4&so#0TU$#12)b$D8cbVc4ll>_BVJ&R1Zk zKJh}=>GjRh+En?PXhUmH`&-cdhG^3j`Zp}??}#?E_Oz2gyGcN9OysHBya{ZAM_h2r z0`8|bHaXF%m}Yhjv<3q$19J0#oJ>4WRe4KXvdzH(y=Ib4p0pCP4M`5P_LB1(c>5(F zw+qNA#2a0e|6;P#4(+Cx&1uu-cj69Od+s`byR?A(H?c<5<7p;mf1CZN3p$bYgz4J5TNSVvAVYVPMkgNYEd`4<`v z-5g4~N!8m!A-kt6>g^GB)W(3?D56Hy+M^h1W9_I-2DOP*gZN1WDWjVvj8e#?7{9D-wR@M_AbX~pPEURrXn}{y7`PbbJ zx?71ZT~lvm>Fyx9(B@xvKj`kQBJU>BR6V^HHn-EHp5AS8p;aLV?1-NP@#9tGqgCX? zM4zgqkK?jD3hMOQIBfEx)zYU(QlQO$QZ9q9i&f=3ki7l#zzG-rG-RwnOw0DRVX!CF7F<5z6MZQn0Q1$aela>1nD^G|O zX!CEySrzVB5+79UoNH3mW^IA0Hq>4OwUDY>Aw<>9Ayuslp+Z%)LI~RY_pvajzD!i< zn)zjuEY!@;OM@ar9oqb>zX|HESCwC@D!)oR(Dm}`RmoNX_3~@*{TWg(znZtVw}>}r z^Y5(;cq?61E=7#dwQ^}NLltP*rN9zh%s{PtQmvKY8gLOy(EeLX+dqQOh(B?V&xn_f zs3Dh%u&9?yMP#O*x2TujjnJkEwDy#FQ1(Q~E+S6X%$^9nW_Fo;z`VJr)~;|32*eJw z_Ux1eI}-6iSI<&JW=4*&dcLkYfNQ`<96)Q&LHP()1^rwsl!!rVPplGjw<75-RYg~X zd|$VyqAS}~3Ps9mT zhquE8odOQ%we*w8lQwIAB`Jc|UW(d-w|^q!zar#6h&Q?x|HowMFSPrI$s9G2IuMW0 z+Vj{IJZ477orpoID$g|e>tu4JrK}sV1FbzfeZWpugxr(Zp(^t%lbxOnJAH{AXzke< z1a<}xFI06tz@)6r=fQRrhlAo!qDWQfLqXB1^cq3>3a!1qjsfLSM47JAN13EyE8;h!46_pF(ddP_IvdSMDhr4Sv#OLf&4d6R*(P^SS`M&Wn)e z5TkVEKF?SjX3sIr7ciZpR_<^OEF`v|{kOK}eFByHI=ym#J+g-UTBKYwQY+p!e*&NN ze*hm{|6BR!`fKos^mI1}KUO~-{n(XV6kh41yz)qW<&pX?9W&j^zjTCa;EhPFtcTW~ zt&(7?1o5=(6YU=#W+|3Rs7f%Mz$E zYCkvVr5DLAZE^r^`l%^^YrsQN0Ij_gya$HFNLe6;4(NskDuzTbk){}ee+DSzZKy0U z1g$+o6~IvWNLeO^j#7ro2N{y{HdK)qg4Uj)55Z7n;%40^+P_R5tYoLM$$)n1gb`(E z?I~9U@t2^i7Nn`(9q)C2>uk#Y@U;DulVu|WoEFbvePYv6M*5FaVm zAqF0k-9gPje2{@U3RTAQ20nPYWE6zwIh!fMSP8IgNd2ZJWMDGGzzn+v=7E7Zk@75JfI70~1R0pc zFfiY)fow3akf>8f)UHOe5 zzdll4L*%I=YdstctCfQRkE}He8=L;Ujk(HiS=;p^>mt}VA1R+EHs~YkJownC_`oCU zG`zA!c_sMB+NSQ;a1C4{g9Giq9UR)$b+C1fc%qK1YmkU-%2G7^mUY9f;yqBj6Di*! zqV$n<2UPcvBkPvQ0l3+trU0&i`y>U>+DpMRF!Ur+enbq>N7fTCv5p*BkMcH@OAJA4 z&(Moe@Q!PgTmb&Ouksg{=p!p6>bao;@I5_7REFTscB_At2U>fEih!Y4h#Tt2dc|Zw zJFN;0qV%&gA8~W21L6Cd|==`qD~!I z?}1{_yvM=!lfj49-r!dR<2mLnwVHkn)$_Vrh`hyV{ zRCTxpjuCZe^RIp?iuD%$bD`5j2-^G$ori9oCEcXnzCQ~&zMzb=;UAq{u%mVb)GiS< z>aF`r47ICv)NX;=jVL*X2-0uc-@w_FW74K((`}MwX!D=uM_}balzfj^q2IE900vGf zsqU%X(1!cD_wu&%m{@`~|CS0y*N~mjaxSq%yr{)g((zlj1}j+Wf1(4eDLgkhyR zu>x)Wt<(f7vBU@UR(z~URhzrD?5M?qS{%4s?5}(lK z-{+6uvstvlAL+*e)+z9IBbtvcZv_=i}6Hvg77f~9oghq@V*4*7Tp;>Mdno$RP} z2eq!zawZX^Zv=G(#awbDDAS}4PIA?*!!^)@bRF9KcfB8&=@Tty5i|5npgv&WCb(42hNp5i|4+pdmqK2IXyLI57il{>_X5Goy$T>gLZVlel(@j3uhj z=3jLpsE#M9)Qz9e8vZDK>4|1`e=R*J{U z#fTO922XJ?&_zi#-ry;gx1~3UC1~?+sWezB6)XRjSfXz5lrlN`ugQ^in!ih|K%0Ln z0$AZ{9EyXmG_7b`UcN?CRu8l_=!5S`B$$1>g9<#eS@cb z-s%;JI<)y$4+r%RW97=k0Cj`s!`RG>zRISDH+U+W9BIEK2kcmg1`Cm~^2f3AN5lnn zgC`Of?Z==_ubGcbezX}{jid(J{HLZ4_^K5v$HmGq#20;orf1e$| zXIiZMH!(@y;7J2ZR6&>hw`qQW;a*CKr(6T+#1gdmv6Qw-|J2WTur-!=qTWUw3kHTL zC4r&JoRx77 zaTO@8Ac|Dwy@H{*+OFb8P+T7?uO*^%^}QZv*jkf5HN!TMltXJTod$taNtpl<0K4Oci!Vj2S?K8R34(`Lm4z%{{oB}&1V&!AR z4poVtFxffAuydN&f!3a#3t;CQ@j_SQ=Se8VwX(PFc+Vf zA3ov$T6+#EfrE;1a%h}fj`*Of_KI=TwgOdqD7-R5*=Vq8FPFF1%ET+Q_Pj=b*Q#-H zfEcAK_o`rvDh{&)ruhPTmv5yThQjq)_f=Vdq#<1>s#W9s@%T?1GAM$z9IJAFF4mTaL2FO!XXtJ!=`K~dr$WA$DdTRa+<&pF_y;Kd zMii;a{Wpf8JjKx@yzL~t;kIG`){@p(I#L>xeC&%sP^ zFg;G5N=#6d`*heGS1Ow$R_;?xuCz*LmR%d!U}IsNJU>pJOPo-Z`$AmM^T7eVmgbr~ zX|r}QNfEU6QnUuVt%{RZ#L3HuH@b3PWwNva?JhH!qbAZ?;t^VV9=C$W&2jQZVvwrb zH=F!zG`Z4JwvE_<)}EccU}txnyp!0WD)-$cJ3AS6_7OYK+Ou;Q>>MOssLK7INm-lE zN9-z|0L5cOk*eH}fudFEb&~WIT6=vx3(BX7GF`c!Hc7)=d|rN>BMzXo=O70hT#b`2 z$H^Co54v){N^dJrxnG7?)+!qfR_+(`_IjOoh1Q7{Dr4%fg#Vhh@Q*;=Sq?uBc@zb2?@@yV8#Yi6czP)Z3y6!J?@0W|x=U5=F39%|W!w#wJ7-r>1Vw=;QkA>FP?YQ{ zmIFn9O}Q))r7L$o&akp3eQJi4Cn<;4UdlfJJC$n66^R|Xa<2p?HY#by%DrOVwmu}b zptWb~W3cs6O}PrOMOE$}nOs#dxzY~wPlz38?b(R|JJoB-(Zmi_xmP#YiDuY|C3c{- zXQvL>sYSfdm3u9dG&OBLB@Upq=im!)@HufnSMHzZ?VuiU0IfX--++S#HRZ2}3952$ z0Gs1(Wpl*J{VS6ztJNLB7XoBXAkTxlu$ zjo5+Ko}DzX^LI`8Phy9v-2XP&`IBL%J+T9=Jv*JiP6qKpRqh!kWo zt93J611pFfXzkfq3wBl$FLdR;8V2X2GG~G-_fx6^xCYh{2hiGcu!&i@KNs6f#Gth& zwjH{=m2{V?-2V@8?*Se~^}c^^AP5Qw(iO|@&QkTz1WA@6NeCotLJ)#{)xgpML}`+M zT_Yd{kSYq&M5K4=L69m+??n*ly$jNj_nw(&PWJ4X$@O>VcU>=BnJ3wt=iHyu@15Nw zThZUg)o~AU?mO%%?t$ViQWTu~E(^uIb`=jn@n93SpF~CHevr?w{gS>g!wyrIBiifo z6Tmsvg#AT0qH{k6h(l_(bLak7?pP-Y3(+3dMPQw8!p;(w;M~tkRA(hB{XoA&IEeOe zZUEL_-qp7_cdbqd@Qd|zriCo_k6yr{-@N z5ub6hr!WY_wNy}I(r0Zk>LNsYgH#r5Py1MDA1g_0qH}**LMqL1OGYjU!*l-d< zv?n$S%^gY26`cD>^!FgNHrTm;V^{GzD2^sY!MTsNP#kMlaS{|K`q+396`lJ;KEuXK z`oawRfw~;gUYE}R&NLsJLO7yxp9YA_f^(meJJw9XLbQkV6R_s{*j&OAocnx4Kocl5fXNd*Q3c^9OhqD?utB6H(?yDqeVcM)A0z`WRzk*;r z5s1!xeeMJsi2%_a!8Q1?-)aR3LNsYU3465M}6#wj~ym9(YYU$kdAQN!xEe@kxmdJqCLh7 zU_9qzX9!Sm?&l=FGZK~FWfutt(H_ppWqm#uw5wPIiiJs0aPEbn zXlA{NQd<%2wY3D4i;=SE+>1%ln2R~~qa+a^+9P-#1kWb2XA)T%;t-wtvx&mC0_Xk= z9+|9eG~BtD$({8DVnwvaS`n<}6PbrVMdw}~Sb{ms_DJ&u&|@{{j;ps4VIlrktiz>~ z!b&8C6>s4{#9sz#+^P|K)z9krwH1^URcVqR54RY!1w1U_+zF~84hoh zT8q0*AZxQ_DP753NW@3M*Gh`)+yduNMDOhQYqFAJ9FBY|` z%*88v-aPYJS>qY2$}029DwtPR&MLD8&#Y>m$*eLXkg0cOEvq8+c;()pB7Chy^CGWW z6-nSl;&U0b#*tWbJwFH<(Z<&5Gv zBZB8pL#_XZS!GV(nPbf}$5>@f<(ZSsGbdSP&gPjjtcv`^i_Ehsl8qvIZ!a~Sl+Cn; zFSbfw&lT3l^Wqot7Ok|ZY#Xm^vw7z4vc^WM%J%ch_Lx_;%PR9Po_W|j^AD@cQ^?di z^SD)!^StsiK}GmlyTXfHv?_9k7x^cbQM+NfmAs~n=yj{A^LUNp=aJQ#4GVi1l+9OW zDV|;2D;{3S#^QaB7kS1jojzr(vJ{@>^qTB&Zy2>#q;lF;!tjMY9+iXYebXpkgBPi4 zRV0#2zXD)kE2(Lf6UB4tdxOr?yqYViYn9oAXErv^jJ3*a&NGwDGZU>c|Hm_1S`}%- zi@ar3q!Wthz1_iU=1ShuCSE(M^qyRyn>;VxF>g_tRb?OY%HA{2>@91gTUFMNSC(mB z*{4>SgL!6_dFBAC%n``cJ9DU2k#BkBUk4T8Yi%4aGRCUNR9<9qE~7R{U38KwNzq1h zqE*%NdDU~Q)@)eVte|YZGQX^2Y()L*h+B!@SiD1dk->GOtz@88)+nAeqK?T{($=W` zJ1VDbB@^+5J|5$O>TPF~|B)A&WL0Dqm!1w_VJn$xm9voN%&%j*mCUuu{F!GiH_u#Z zmARg0t})O2#VT_X&)jHLWCt&@)vCw=6w!NoZymF(q`fxrc3Y(%=L&zx^WsnQ79Fyx z>>{u1oO$LMS>u#dWjA?c*Uc-tYL)qbXWli>yls`4r>@bNkF1L1M-lyILU>(^wN{81 zdEBZA_EM)HNFxRyHV`ugvG`8_g?QUu<3{ zWAT>bMcnnJt;A`S^&-!zSlLxoZT~+rudD@)MsPh^dctSTGKE6XykY=Bkf*F1B$ zdFD{7%YZ06%F(q;z>Uf* zqllZ={z8fTHViCD2Z$1~&1GaFfDHs_g1=9!6BnXPz(l7ouy;cLSye+%8& z)iEFs-EVh?g}q^w)QKl`KvIu(UAqR%skz$twYAE9k27Ti&&GvXX3yZ+xWwqfPr2+z zLA5V4ihRLq?<>xZRa)JdR(V5s-XJk=zLu9|mG=$L8)=p|+$wJz&l_V^WD+kj!K%n~ z6wznn6!V!eIVf|r(NFVu=4|uKnO2!gc;-U$%mr4ND|myJ1r_1Lx0YA_3%XOBjVrB^ zHu0p5ND7*b>$LG(ZvtcpC1BKmAB6>YjV zmI%r`X!MhlXFg}1S=K7E0?+iAXS%I2U*Zj_6jX$F%gem-YUoaJHde7ps>72akQ6i< z4{PIB%PMy#XWAAmn*P6xt~$Vr?2VR8|8A?SBRuO+w2A3IW7K|v%4vuHS$v_7=c%B2 z&l=?~@gnD~irnDR*8nV-{wr2F_j%5p=pfU7OzXj0R+-^3#tI0FG0l8rm05^qK5m|w zKSmr9-U-EcW)Z6*Wq6U2Rz;jBqWAW5F=nR!g4Xb|R_T?wLWLML`-&x@qw zGHP$en3?`7+KB$os_Haebtg4F`2K;qX2Zfd24(X}`5Djt7}W&^*%W&a%q;hUbkG^R8=o!>#fr@Vv2Rd1I{de&l(R ztcuLwMW$L6nU5lRhs=pFJ=kUiWrpEhH(FON<(Z4jGk>zmT*Wh2m}f4x%3Q}Av^uB= zAHGez@{Qxh7nvmw=M1Z?MLcVP8CH3t_T^MglUju@^zm2`RBr{N z{5oD_wN;T#TzX^hRl^yYe$#Rgv<%awVt;Uu!S&A{DKQ)Z#^I z#G4%e`lwZlH`_|8Xd_z1s_IvH)pgbM;H^YmvteQ0plsgjZFzRmrYn_<;8YVSqmG^zLSg+3k`LG{)%%74s@d|*|iAD7Mqu<&&IQ>&c8JSQu7 z4!x}P-~g-4Q9N^mdFC*y%<(+)JM+xZR+*D|=J!@bX7D0Yt%@u_5xuwPnoi0FTEk~s zrLW)$%j9{n#Joj|tSZ~UD_d)xxmwm(WmVZWUfE{z%6_-X+{ZI_n`iE{$~=rry)zG5 z6*$O)?=S9y_3xs2Kc)2*bTHlpXOs=mvszGby$!@_O`W%HF;sEKj3 zJl;gy;~N``w>U3Sw25>wJZY8nG|wv4#AJtSYSjKbmD9Eo1z+gn;S8!b$tYiu7b#~| zq$-zw3BbZuQrRk}HqWWqB&YwYW}f+utdV9_*$2F`KIWBW zSY>|BGe0%Y{Mah7a5bwsC}z0I_c&5*R>HH zWmWZ5UiD|zcq`d&m2;Bk91EU9Z)*MjmsRE^o_XFp^Q=|oO`dt( zJoBnm<~^Qy+p37eXPglat%?*t5xuwb`OLPGj#|U>`otrKk3=!9P{b!4F@=3W8?xSu z1+6N3mRI()d1h%@qoh@3<#=Uo^U9o7nT%&vHqWeRmH9F<_0FtjRV0E}UMr{wUu*Sv z5wBH|#=J2s^qo5-1AW>W2 zU+^M*<>Ab<${NhGvdpjs8nq9na+=gP_(C6#kwNtiGRlwTMMhf{`GHGM1hC*r##`mg z%`@j(Wv<|v%gi&ESY@u^nX9adY~)4OTNT-kB6@FcF`bk{ zw1#i8NY(ZUSywDkz**L_x2IfNjXt#_+hK`3tZu>JTFe0x9Fr*WjA?c*UdAp z${LrgDtpK)yJue69jnZIiN;dSlV~~(9Esuz=ku~4GWE_ZU{$0jue@+j5x&++@*>5o zioC#!Jez2?mFT1POrqIVGFcnZGFDYr;#HSd(}TAXb$eSl`-dKNe_3^xo{3Y~t>UOnDV zX_%V+PDYQODX*uc_iop$8IopXb8lk=?ew)3I$OH@DDHOw{A^{s1+Yl3T%YpQFeYbnH5xYk2zJH+<6 zj=HY8?m+B;E6bfDch&s>l0Pa_mFdb1Wu`JqnWM~A<|_-7pOi()Vr8kaOvzSOD(jUk z%2s8YvR&Ds>{NCsdz5|3LFEtSuyRB>s+>^HDd&|d%2nmMaznYP+*a->|0<7^Oiy1= zKhGDQ0iG{CS)PHOL7t(Wr!x=Z*O4zlTb4SPpfyXK%W=)dbp@_JYpwg)xe9Ik1=rQM zuEBLJuIq4JueE%=^H;QgBd)*U`a7s?g@PFB))eFrB0*N z8I(GUQs+?WJW5?asf#Fe38gNh)D@Jvic;55>N-mOjZ!yI>LyD4gHpFp>NZN4|855E5Ju)UC;|F9+M#hiGn1YO{$e4zV>8^Rs8OWN6 ztXasKjjTDynv1M?u5X?5U89`~Tw|O+xxRBQbd7Z`LQRWN(-PFQ6g4eFP0LYJHfmbo zn&J8xA1ht!ovTpeFQ{=fYFvXF*P_OCsByh(zH5VPf$LY-Pp*xwg|6RRi(J2>#!aYk zGiuy|8n>dxZK!cOYTSVuccR8!u71wl_}JrG<=Tsy_o3$f_&9*t52E%zQ2Qa&ei*g? ziQ12#_PPpHv38PbpuzPb*pOGs-~sS!Iy>oHE#bUir#>K^fw{ zs0?*qQii!NE5qGalo9T$%1HM$sjL-=UM9>?^)-b z;92jU=-J@@-t((_l4qm)2hVTr$)4X)=O)y%8TD*IJzG)FHq^5n_3Uu}=-G*ScA=i# zsAmuA*^7Gip`QJy=YV^P=b(G4=MVQZ&mq)v81?*#dXAu;zfjLn)N>5=9CuImoIpJ% zQO_yVa~k!WK|Nk&mz0i}XEcAS?Eb{bK7JK^P zqrbAm^M$h1GeBA9`BGW#$x^aC1CDZhHYQ8s$MRetk~R(|)4Q8szLQ#O0XDqB3`l&zle$~MmgWxHph zvcvPevePq3+2#2`+3lIE?D71l9P&(2j(esmCp^=XJD%yvUC#{Vo@b_V*fUExU2(Ru z{gpY&j#uU?k392~;}P?f6A=rPlMz2DXDTjK29{f-%!^vA%#T{4EOakb7P*%xi`~nW ztx?&^yv8e(>9u}VhB#L$2VAR^q0V2FVb0acaOWCjgmbMj(z#Cg+PPl2?A)M?a{j7( zXO$nF=a73|xvX4JzN~&xnc}>pOm$vXra7;m-mCbyrc8HU zSN6F6R%SSFDEpi@mGjPjl$p+3sPne+$aM!Fca_=Bd&(fsePxdGfil(0TR2hOiN3!Ote zi=0C}qdiz{&SxB@GG{*Ha1?2v+OjHX9hbcu9`@*w!;#m~pi^qQj4IWt4R<*3`?%Cc zs&wp?+99J)Dx491!4@6~`&9i@_*bPvT31h}&e~)61;r@ynOao%r%kjMF)Ia`&26f zQ>OmQkB_`zg&)_x2)L*WRjb#kS-Yl_|EpdrGO~8jd4#%TMVUCUiKK=epf5g9w3QhfEcH*3I`Hq}%QrIf_94!wG$_vn=2)a|;nMMm$A zX+2VERI47D64Rqwx8B{;GCoLoJtif&M~|-QDTyucY4w^_YSgY$BeHt+YANm0x~IhT zNYD6R#4DPy?@*&k$F5!7&QgG386Wga?U>fp!8-lFKS}7JKO0Et(CdSq89h?krFXBM z(y>OGzh|#19UQDAw zHS3txu5)7V49u-+f&Z$<#5kU6^xXZDHN&c?OS%RoZ}GC3%ieXg!Bj5udSPr-Wh$%N zRhi6u_%(ruFKXA9^v4Qlj}@C8@&DWkW6aXJcj(%?Bc9dK7^b)Dl$xH=uERT3x;To4 zEgSak*Drmwywma059j<-(N(ipL;DK)EYYg3c6@4hy{Z|TYqa<${^ID(d5UeXXS)II z(|TxiU;d-%;nFpo36smN|Hv_O)u+W4H?UoI*DmeSyJ)pn?SG=rgp}n`br&qz^YyYH zW)xdwzxLE#y|lVtb*A3>B&G9r?jm*ZYn7MTUw!Wn33-=SxOI5koGnkBE;g&Z z?aJS;RV~urr_%?TK;7FFDDIvqQgG%<=y7X<4y>BH6c&4R$;u#@V6oyNzG!LwrG*yN4KP>sy~U3-zAG&FYMM* zR9DdPNgBS@%oo$5w$^0r_ftADmq8By3OX`#zRlm`;mBNWe0xcIWdBcHdI?EMzLw4W zszsqXvW-G(yxNFFCpK%5+&sQ%W9Zky{Yb6;2`$vQ(jl#9m(*UEGM#$((=+h>)kf~m zvH-o)#F4qqD742L9iN1(&bo;VcPD6LqN%oseXV6|)0kL)RMR(j^QR(nz1IBEU3l}G z$Hv4r^T#)BloZ&C4Ti|;DOx+5MkU7jW1A*7e*=QkjAo=oY5PCm{YH<+@W!stu?jl2 zMnf$2fBu-LgoNm*7$0YHDk zlzEfKFj(!-60b%$x!6;S{#eUP;|ExMQw1)BDH|xm!-C!9Wr)?SO z8NJfFclKwrYu`0hAD`#-hKJu5SYQq^()~DPv2b*rNf6qk^0XCrx~IN}wW52s>}Uc6CbP{$TkYr3G7-lJCr=W(LUR!!%G zH(=svbMC0o>SyYsPcWkbhv&HQ&9SBvCZO|97$tYL>#1)F{&!M8(7WxF{=M+-0%6D0 zR4f5Z1>POez&xX29x0uk_F<|YYeK=mVLjFXTb~|j9RpWu6%@z6@E?R~vEKb1x?v~N ze~GZZ@Z(YRtXA`8eb|$mw``G&9xkNMu7Zx$`f6?2H2(G2<}IQU_%!Bgwq2S&LsPqJ z2Tf{6y>S(%(ntedY80LIU8kVfZWnRzKzrO6KxCgCr3pm#G>11 zAry36_r|{73>#_e8~&K&|KU6L4E0Sq7oJPtMuJZE(D>e)X*shUyUOda3D`c6?7*`? z{43~K)xg+Ku+|$UVdL;OYS}afMT|keE-Z=881#-k-s|q~+M^x1GmpOBC!iI5E2{M! z&e^D9n>Y9CgX?b?h2MSR$lQrynre3+KSS|wUs~+Rz4fCGhed?HS@ZbU{c3B~4U96K?du)4WW;>5|X*?uypN4i@{rWE^(! zNlgQl9y7{4meX3^Xt`wj~C|3hj@uh*juu+w!a>aTC^UF zZ<-w27~5C?_~QmpLzkpiQMU7fMZfg{39{YNdFScP|Cp=}8I@#DL6_wC9sd->c#f&m%&HFT9^%OUX{-!rO zIw>h3Hma$^k)h3(1lo9Djr=i5n59jV(WfPiq+gBc)F?t8i6Z()V1*#%Wuph)^8uT0 z8-diNjattHwJcy4FJqK>i&jO)w9dHMpiiaejc@jf>DtAg7@O$t*t=Ud+ziQd8Q(eF zPMaM$Ba>ioh5f&Yo^qtEteNrs<`aY&U!gS1|Nm z&__-8>CnO(3)FuF9dAhK0k{?Q^zhe&rt8nE^s_}hs%PpPDaORjG0A~5yt09EIp?g@ zCQM>%a$HhFFxAl8U(k^hVJv7=88A&=G^!|9N8M3^k0D29m{CK!-~}151;1p}azdXq z+7af+Kh2}p<0GUVO>Mpwf> zq|R$|DX}5BuJT479Eu7WB1r55ApV877bdgN2K5QTa;@SydrS|_9#)>Mff4f=BXc#1XliYX`H868AU-MU8YSMv zPK+C#7#ejy2FC-PqoAX``7XfQQqQR3C%!SaOg4_0K$`kS!M*g9Fup~Lmgu*rrVafq z(DPC1@zcO4bWA#1ICQj8=4#Hq!?&F7M*nZu*HSZmSom{?>UCn9HjZzqTB^^CqGc1b zZA-YdfIB6|&43HqQ_G(GS>HfCFMOytM7`6y@WVrWLcShj6#l2Myn3bLnRhB)d^DaX ze~WS()N;u}U47bh?VVEyuZ}r>)dqaASr-Sa_eMs~6yODgvoCP#ZETcX6CH311Ko1e z82MEuPCP&?&Zxl0SC+Q9^Ks%{vP&D|Ac;!G)2-;1$+3YGBVMm4JTk!A3X9l<4&SVG zK&nYi0SAH4Kq@9bTL~cNr%pj_VWZ7|8)IGHF!Ac$8hT!tNPPW;F;efr2;;p&BV4LK zJEU7I+H(Q!_2YO)wMfS8BIwe~qy-%t_1Vg|CZ5w=0BYC0V`_KdNiTn9SzOFnoc#ONvoCTOZ!&_++{{fz}!R`!k_+dhh!6zYV6}-71gv9nso1qKp2FGv}r* z>fz7UCdUCu-@^lL=LGV!F?iPNJhUywzZu(5e1eTT=mBn#cOZ>ncXd1ZDd;HN(by{k-3Xe(QQ8?z*+qAj z)6&y>*yX&{j0&g&%)X1OY6HR+k z5U{IuG`Re2wC8SouSfHa8ms*xcOu$z^MHkrYNWrD%lzV<(8(x$DQ7RxZdi0n&FIpD zHg5j(W0gMW@lmzp-6b^=9d3AAW6}pSi{Ecp<9}a$VI-qhZ{v9^-D3@ZHNl}xKJ7KC zoRiDx$ovZJKCAT`;|*6WSU|hgH;8B^)Nc;Lo1A78JYc@V@eTcLqu|K^d#VnC;de6h z*@uVtZ7RQ+%L|}<$EdSF@c47Su11l0+QzW2Ky@=q7xcYl{^QUE`c1ss--QLh- zOX>%GH@#d`xD4Jok>IHs$2h984#&?$ozhoEC zF@20ehxBLO+K%YRq}N3XItC;d8#CQT3y^=$$o)z##OLz+MxhUbd!85hz$mheR=IwU z7JbT1RB`i(7SP%cjYZ6lhGY4KJx+>&81Wy3?(% zl17Q{mb+Yl;3r1ux!gJCybP)Stvmb+&lg~u)muyIEn99(M_|qWt4+5=UIm6EK!e}9 zzhHh3GN6+_({aM%q8;j!@t(ai{Q66F#yzZ|P|L)d=fbB5r%A`&InQ3}g8Fk5Dd;FD z?j!+7eMx7xu$Jilobl9YBr58sRn*>W;|!>dHiv?aJbYscepbXcvHnJnuh1t`QcQBJ ziF0Wqv@h_CFAl6PG^_=!wPTRKih-`#YAo{QdhM}ITPETbW^$}*0r+hFFz_{cPBy?G zJI7BFy1mVde5n_~`!pRz-pb5WXUG3<|B_zF3@_t!BsnwxbtJu9xOFkSRQ+s$yyY?% zs7Oz)E#@ealxKECQds6_eBA>7%dd=R#8yP;e}?lNO=Rk@o zW+FheN3cDjkv4f*FGFN*CTF+_V}d(hln)ZF$F`rmMNsjc0G{vM}}JKB$N|H_%5 z|H<>cb`=joaX%@J4^-T5q462T6W=!eD(^Qi4S!e`iFNne;@$EeE@?REKC z;GB+NCkf{>1E+$Da~crW3PE_N*6l-`*(Yq-Q>L|8*<6R4z8U6H6R zNmTkD?Y>Spi1u*q0OwW&yGb}-2jbk4aBf=Q+$9`DdpQ3B=K-;NXN=g3YTrDNq=jko zhzJnv5rjuJVtFFqCJ8_Ab28@6(EQ%w0Ntlz3@b2R{zE7 z=D0-L9OpT+3rJM@22$8AMk!#Fh-AegSy3YCO_L)+B`FbU92vzxAg-mN5|ch_OH&si z+Up`G*q)DM&qlImi0v(7sOqS2&r3+pa@=PmIAIuF#E58*u@V?7M6z-O*gtS(Rgn0~ zNmP25RVExndpOmBQ#Fz?!WkHdQ&qxY7C1Es2hko*ZQ#@*mg#}VQ!PnZpU)9?73)IL zONz6o^_unaLeb26)uXl|+G}eRlwT#~De62`y-q!Kp1vwcV=m@+ooFIJv`63rL3|`@ z9LZvdqr1ToqjJQH+sYDWc4Iv9o4V1g(Kebj&g|ISSrdpA(H?6{u(pU~uMy}E09CDE zW)l^(1+WBjnEjeGUjRK;wTtT2`#NDEhJ-c7aPD1z)rpt{=iUhb+f)Y^?u&R|v5!a$(Vp06XznM}T*0}2g8ts2j(d=E&$O%9ABufRQE={kEfl}7 zt2h{n10&g&Bq}=hfqaI2Dd`I{>?`VWM0;KSHE>2mvSEZHI`15l*SO<(Xk?fa9wvtE$=e~w7=wCn}uBDX{lRj(LQx_rH>!Ph-+Z@S$k7OH( zO?2*?C8Xau?nVhtm`K}*5z!vwJ}~ZyWV;AZaPE5~zFiWP-evm<2hkqR5#St-WPcEj z;M@;OIDc5+{6#p3_Ha%D=Qyzl&i%Ngtk36Db`{S-@eC;n&ixD&&8*jXYAd3>wqAzv zMN$@>`$b6_b1}z$TpN}!`B^AG<7H(?Ty*Zwc#RtQR-n{oY0ztF~;s%J5C`8Zh^k(({ zL!B*wp8b&K*>UwMM1W|Ipn})Rv*(CaBr!yLVlSb&m8rRcXRnN&KBSI#kY{Ih6{|zB zDk%z{y{d&`4ZDgFP<+M9YLckv*Dm3AA_Mzp7$3hfSF){f)_ zZ{7i$;9)0jS>S$pJBdVhF`euJ^Z-CNFMG$!(uhHD<=yy_eFp^Mnn{zGbc@-OItS5S z=X?OR_q?pPm!%V%=*r)dka~06bQw;cHXjllqCL94pv&~KPYF%%CXcYI_ze`lCPl%Ie+@-5 zL-j4S713T>$3l4wDT{u5j3kXyKF3;&BLYNw1XDmT*~=z**+k+H{rF^KD}fWAgwOv} zw-wwypO`z}RN_Ol$2SjrbG&R8!HFJxPO#a_o+Zr@SiwIu500yMK4BsLSFDD3-%A_q zJud_5G-CbhnE3Dhb+Y;$HSynH*3q3mV(6+vpgOn?8%V;U_a0ow@ZJMu27UJ$N)U*l zLwpU05kw&R?h$pe`X3AS-N!ZGjjMMQsUwE2KBkV9=gtxOj)V|H7n*=(j-zG@etR5x z_qd7Qo@hsHGSnuKn&7o3S*ZPJM{Oq5rq^LpNl^6J)A>A_Dru9?o<$vu7={ z*j$1TJ@$M^i+*9Q70g0{K@1&c1z?ufVM_@{@Yl;FmZdU_b{zjqD2Sn>tOLrLI_wuh z5xn&p3FQ|Hl=Xyy7&^-DK-owfqOaa4%j#RqCelR=U3WWlx00^tskd6`?jT*n&~^7i zcW)iGo1_Ily%(F?3G&msB?{ez9IzvP4B~&)VSm z>J-G#JLLkn&edUO>abJ9CHm-d63!WpdP)Y3S#Ie_knV^4!cb#f`7g%q1?7Wc|a(Lp`(P=#T`rH5WMpvNmZY)mx5m5bfbq22Mp{5#4je`dR(21iR;}8Ue1}7l{DT9zoUmRt`Ex ztQv_S+7qjZ=GLI*3NE?^`unPhi>_r?F%pWkNl|dpwJj9Ab`={yv3`A4mqbN3U7yde zx{|&y!=k9m5$$z(9B>-dXAKEQ^wo_3aZc@a{!WvIxnso>7NR|@*MOB&pCuBO;INY< zszixOcQnlj2hkqR8^CE*pS2_$!DY9Sa9Ud6yh%8S_Hg{bX-zDm({3$E3)7}85g^(l zNCiO$A`m@yhujG|5doq-f^Hyqr#?#~2*G{7gU#`8b#vtJG)a@FbT`x8F2;Mn=v|+s z*Jtk%iQvO~^97v_0&y+9D>3P__I>IiM0;KIIoLj{&pxToJ|Z^Ji+?5|eZp}+lHi1i z)R!0$?J*7lV^)1OfB*$oo+a@Okf`)78%#Ke_Haf5XLx-!lyC%RK3u{XYJu}L;UL<> z83UYeiA8Yd-%85*eE!a^;shv;BSpcXkAtF_^_oa+MYPw}$xxm|%A!l3BuQf~=Gc!P zi2%_a!5k3Gs?TQBXVZv7bn3IjZ3TXP1|GSkZZ!OzCew0folC5U_E?vKb#Z;RkU&M} zzBt$%W-pZH3!txP&K+0pGQvXquULy4z`6fwIQQaFjo4FBtZQkl70P~2 zA^^=OtqXAVx~U5g?R7yV09A-$x*0R7a7AZ0{*%5|aaCFLtnj&?gT zC#uR`QF)vTKNF2_dh3xgqCMppC`U!HS4rFvrLT=2RPiW?pTo@vT(V!q=Rabh_8aF? z*9k!M^QNI)fF=Nli(-ukAYULrTmV2L3jm*8fY$(!6vYw=;6CjRS`Q=z03=!fG`9=z zIslSM{d(ZwCqpqy?Q?x^;)CCc1|QMh;J1eITT$!{62C=FpQaA}Tk1q>iI40zL=3(~ zwy`Up3i%FEtS!kOC;3^bd2N)SqtS4cJM^*+n z7OEWl$m)qlmZ*;e9$Cw@{Tf&Ado(zRAq@`4`UF@X5tDFaeT0r!mNPB*czkMCu|E|1 zMzKs16_2dGP+dhwR;EONNxDkw0$jacP!}ND>w>QUG$@K?5s-Lf4Fbe`I^Xn5{G-w+U@J)p4w8bdU~ku^pF(2uNfq>N}!`Fki&AZ6jm znjk9kU2764Bid7*2IVPHY%+-pN7fXG8%Ne;e7;&;CqYNnbh`j^0Wdp?%_IQf$eJAh zFw+8Ho?U>&09Y8s77&1NWGxH;SYQFL#4bQK0G5%uaAYlmV!+r|z#Nb=xTD$VULw;ivTTk-Bk+l&A!#ed~;78Va3ye+w9b=LDENi=Q zWSs-XnJ9LGFvKJ43^;yQIrx!v0*`D_9|=6NwrTq{uHN%BIEepsa73)Dz`9IK!jW|u z9kESaib2n^uGv+*1;v|D>~9hkkF1+e-9ty#-x2|6_Gn#ztM@i_0iwMw_!mGAqS!qG z5|6A0fcTY;tb4fwJt81Pdq9sx;}zFvmIr^#<0<_1CGp4#kIn(ggU`h=5_%|qG`$cT zZ4;;vfSw>4;mCSI0??1F!laC7uPdH{auHG%j;tc0GT*g|kust^Eh(pgaIP(acQ%!ja_(0B~CX zRIm&1A^<9px^QGwf?~kD=Y#(e4L+j1!LI@3YSF9;i3>+owP@p6RuvJ0A6YNkmG?qE zBAV4AdEv;4h{n7A)q{Z_S+y)M>il<%m+|&jMSJ_}4j^nJec=~JY=hcg>U=spINBLh6X2s~?ZHdI>*A=mZHNhAwml%{)cT6kfhRg+4y3j&sltot?F# zb`fglNlkd^{=9|SB|B<=L+x5LyF!BE%l6m!Y`P+83$y74bu(h<-Fy!yccR%XLJ?oG zzXO0{YF7`{ZfN6v?ycOB?h_JX=ty~E8nLh#_K1*#m+Qk~f{7kUMEXe|9;15<#L!U+ z0_E`-mOn-}Ji<%$k4q@|@rXDxb(BJcf*3l=Q$Q&~9OBFLMI>2aniL~-#L(4CL%k%a zi!afa%w4?+^YC7h}pl}TX2#HmSq zh@tb<1)n#DMG&0ulDt=9i;#%)uBt~Uh@qo21WI%aYd|Q%%kj|?N&^d&SVBPz9i<6S z;)p|dDLzh8)#t9yj#?7b5=l*X89oteW|pZLwGlD&HYP*0IjM>-!8ey=G4FEhLrYRe z3|+kq)Kg;En=$Nv#2~)>o+54=c=`QJJaR?dNchX||I3}zPn?LMb9Mn|rx@0eAjOy7 zI{`^BblDxH`2pZFs>M^U-ZVl&3eBiP#YA(vPe+85i|&jkLX5F zmZT1nM_SWy^$ww?BZl7eQGgj4!-f-#coS$O0It(bpy9d0d_ypZp~H*^%-9$!-+%q>322>U5}1B~{_Z&s0&BKlh(Os)(Vh z&V%Zl7&eQ9g_}NeAZ*<9nT5|kcViX?-SnAnM|=sy7sarjNL;w#vnW9PCkyeVcEndg zd_@dfPU6DNo)rP&%PquL*%4n0@zta(+~`>iwSawx5B545Y{bw9`*)~rjA0u{Sh&fv zF~+#bvq41QH+eSMk=_aE?J;Z%Neef4wqv93kGYj|gJ+8c!mj_0aHw%o*!$Y?bG~sS zcDAv}&ug4*oYn73b#4dU;JMIPf2N1{U;8{q^%_*KG-j7bSiHe=rLp1eFG&pG8R%Bu zV}`5uI-wwjj&chqH;F^M!E>{5R{vq@2n62X8Lp}0>b*_sh@q?BZ)|mgCr9W32_c3q zlmm(q$6SOW+~83p6qf}`c|t)99py!!R3Z-X22UkP zR+uI)kvd}N>eZoMmDI%>JXLd7uR-dFp{qwiy>=X{MF7GLp4xF){l8W>J${3ymPDjK zN%q=7hyg-W9D6m6)gubw22T`Uw68*4Tr>3~9({&3q^>~>y=xM|<%?tSajY?Mi8pwB z5>7lvZ7hKa6Q?QhA%@QPI{1>~SaX6CZtx^aY|SMiy{lRg3S#IeZGe&z$KE6q;Ra8N zgz}~Zil0yrLr3Wdl=j3S+~8?1sp@k#)s9*k)H;)zaD%5a)XXf?+tfzH(A(G@s$EG{ zyus5|lEu8su@5~+9WiwE_o3b=j%CELUc?~Y;OQf78@R!ffk#HG8wtO`(<^t*4~P>n zbk4ru%#3575~O&8Clg45q09bMnjZijrdmAp>g`8Jh@l{5t~K8EGZk1r5|i*U>W=^z zt6G8}mpzS?5$!3@f%2?4HiN`Pr#*}BT{9#OFpbx|F0S6Wgo9`gXCZJF5R2%x7hrIv zsq-b!ZBN$-aP=-C0z`WR%i^pYcaGR{5<|2nwi3-p|~-QZ6Hz6eQ)G5Y=fjP%&<+=<%ssWd?#?W$FZ%1BRcTyfEcfK zJ9pq)bI006Scvwp{s7j2IJS?l1Q&ilqS_}>=?C{A!a=l$a~wEF2|{q? zH?TR*Qa4BL%CAdQy0f`u7vm8y9>%fzaqKRU2+sT=U(okKAg-mm5|ch_9r5}zYeaip z^mu$DmOq~5i)VS`^_vT#JI@~c?LLT;#n!e5nOs138$0=PFcc1w1?va&hx|~IQ8cxWqm%o>?)Rn zqC$#-TUVfHX1&T&TM_NGwK9||lCtR7D@xLsi#hh=MIu17M^F<4HR4&dcvgitMAu#; zUf5RP+NPU3-<>S!)q1qCM97V67X^yaXyb_qxCm%we`ynlFH!ra5<9y{{4$ zVn|p^!sz!I`GM7%m;~qE8UR13RwBr`w!lyM0*79##=e}9I;*`hGgLFu`)r9ycRCB~Vq^njSv*@3&lVAh;M|w- z1-%3W;#yiHG3m2*1$7aky)If0wzctWbv#=|Y@%~tDMVIplHMnrpzTfw+F zp8ZaMf^*+2@%=7Q>0P#sa1ia`>;=y5c(#*p1n0h6!r5tovyX5P?cp2(&Ou@koclpZ zS)b2`?J6FH;t^65ocj?dnpv-7)K)}$Z9N6$6QnFU_Y;yd=3s4Y!w8we}theIXO#&62`>kMen0-^4FMwXD zId@#WcL@tIB&=nIb1&EgKTXiY#H_7Vvn`$M3oO_`r`fUnCd&&h{k=mS_aNu4*j20m#d4%5IQMcEiWTiDR)OM6O;}|T z6`lJ_e1=t)^o1E#mAV|!UYEZDoSIEo4Z;zfdrd(6u68?j?lp49s!dpk_OMN21aX^ag~3Xb-0`aAKRV7{U>pd#r>LV}TP#IEeOe5`p6*7SXx;BxzyV zG$jH=dju^&@EQ?_&i%FA36hBb(H_BDAb6t*Yef)(bAJPy<8F0xMr9$@R%guT;*r4gIx+`CCg?{M5S z2~LH*aGKs z!a=l$GXOaKiA8Yk{Uv36K7VOfaWE7IlA_?;2SU-zdVNK0MYPw};ZPn*%A#{0DoJB5 z=Gc!BM1W|IU@Qp6G-2O1VWWscbnausZ3WK#TRgH~-DtRTAC)`nIATS#$2tY9lbf(f z1S&fB$-(9@dy+I?0KHvv?znoV5*A`eSlNbiUk0ot#3bBvUjl$XR4WnW+?SIwqCMqb zpuDmPTS4NYb6?5#wG|Qvm=0;a8CUOW!a=l$vjI5kh(&bn>o7RS)HxIA+>dJnxO#sj z0z`WRn=GAsj@V`rL$oKh9nIZJ%@v&cR`mCAb=-rT`wqK`d!V?B6b0wL%R+IlUByFC zJlKToCsEP4ALKJ^zoakBu*1~li1xbt1aOWuVSf>h=-iJ1;*i?y+`0diJJw0ULbQi< z5m@J&u(O0EIQR1s)me#3KhQ4`4x&Ar8^F2Vgk2>Z!MR_TaIRY5+$0=CdpLK2bDLO1 z=YCs~7N*TTB0#i9@CXDCi9mGj4|6AQ_~@-5KAQyjeT`T?AIt00Z}14tJ)bYD|0#8I z&wK+ZU>D;lU=;DO!ai1zNCf9z#An>>DGUN}EftiQ^jTYsx(LzUAe9B%(>_+( z$4U~L=-i){kV$y|&hc zvX_)a=kArHF&A^}M?E4yv`5eg1Py&G+Q%9Yhv?iJirWgDdo&(7r*1Udxi`q2wK1_G z+GA}7)}}s|K%k;?Zwf5I9A+m-^99hyH0O@1_cg*o3<>Ly;oLs~){5zA(dnpe{$W*X1*SGtI}Q5RT~Frvc)!;M}L= zjy0385ba_81g!Z!HkYsj=RRMenk!N12l_(7L9~aH4V+~@wuEp5=e|tBSz>{+f^ZP+ z;j9MEDq<0x`zlFVm^N#O0MQ=7uOL`Y1fp|apF6=uB0#i9unh!Td~6dz2+n;AHpe0A z=E$AnummSeq!Yx5Xpiv%7|;3G83GiX`#Fj4j6|h(*+s%Zw1@LIaIX2- z6~Ymm`!xyYiUrOM!a=l$a|bxLh(&Pjw5ChX7!d>fnN$`*2c5w5R+nlt(47kt8lU_fZMP4U~}*2bivD&K+0pXu?6X zhcg~HV~Is{?qe}HW7Rnmc+Y*D=G<}hP9OqAdjvluSUL9`vB@NcXisb!nmdJ>D>(Nl z=-HXIHGf34v1@lb6=V}*3X26Xb)>Wu+}E9)r2KD_q7t$YKcle&^HhcqCK1~ zz}b|*ej^;gxo?tiezU;YN;ru2aCQM_2eF9GeTO9dQsA`NO$3Pc2o8W?9}$SoeP8Yb z2Z;dD9>Gx%97$k@2|{r0N3c0gR5wTN+z(4sy3;vk7vnrI&L*(a3G5`12+sX1U(lyP zAg-m85|ch_FHjdD+UuelV7s2ct|qX{#3nlT>k`scj(b^xdns@t-6TdtdyEgjcrSt7 zAwa>o-;?<6NK|^4JtQ1NdpO~VjaZ&U=19~Xq~P51BnFS51CNNul8%!vQTLLF_Hdp6 zP61*OoO=ODS)b1Z?J5?5VqsDgoO@v?npv-+)K)}$Z7l)iVx%lO_hOPX=3Yu;N)Ve#5;Z%j?W8wXQN-s9dOC9B_5)x8C|_D(7K zGC>SowJTKLPGMb0Saj@frx=dCi^Kq)>6%~0)!U6w5JN}l1(cq|A-eURDfly#>O2W_ z>+>{qT)pX}ju^W7dnr~v9LsQsSgd#fgp#Ye!b~S%D z%vZT1jUXh%(2>3a(&!ZS4Iv4xe6&RLjYOoMj$;W0F?5t4fbx9`n?NXnBmZ7PnP7o3 znNSczN0|dQ6`Vy!wN?|_{fZ)Ox zVbl9b-SoH%|4Aa!UCUBC2&;jxDuw-=!m^1%aNw)>qWu}_;+n~pc=Q>%hPnnZ^sd3R}1jqfCq^i%|<95_eL+vD~32yr&)XXf? z8EPY9=xw|J)pMjOI_-0kEaqK~eYi;Kh@q?Bg!{<%DLJXqI{#)EO;IgmbktOOz z!d>>2+&TXtPQ=hT{{`oR6n2jwMTh+$*wAI)ljaA2=V}fcSMMW2LJS4Tr#bAWTH_6V ztxX(uk=9xLmaBFk$YB?2tvhVQ&{fMowNz_Xf`mnfU8=R=uuDh`;8~%0TwJ|R6AEJJ zD9;1sS>g~K_Oq=qJ=8f8=&;vn>bQDeAa%sh)s@y(4m(H4Lqdq53spoj%TqH2hg}|h zyjC6OActMajv9m7i=-wv>=!N6s@PGh3AGxnSv3+A9d->qo2p6L!fdKV-HaG|H`fJ< zw>66(6wzUO0kA^tYVNQja!0C1NQj{$#R4g&HH#u7!C}WpL{SovekeC06vWU`5`p4t z&Eg3~aM(TxCEfz1DWM>Sj?w}suMvmnuwRp8g=vyZ>WHDMzXA1Dq%Jz_R=KOcN$QB9 ztG9!?zcp)30D{BzW7FH9ZhG8dx0Z->m(t!2!aG1nYt1^hW~oFWIP5gOXgfn)Tr;T> zk3K`YQr94c-Zj0!mEM}Y+nV(tF41A9OE~Xx)E*L;Fmd`2A7bcypMvk>*6c%q6CC!( z65EFok=|9G5ej1HC3nT5JN}#3Mhk!LvYxGBvpOx4zZ&) z0&2rZO>o%5pk`*7Mp7FQLvQ1^P#s08qQf2~$ztB+*oV=iju^W7B&bhp&BnK8V~Ig@ z*b~KV0}gvU9{F9}NVvlun>*(Z#EBR>=PYo}Xw9Y(r0B3`1RJ{SY0~^qfi;JXt9Ldb zA%=p~LUY(_fb##&I}qfs*ODq?=&HX#_1D&HJqe2r`&Yhat(O?UvrY53 zxO#sl6vWU`wgF`eafl9k3kGD5I!6K>_FhdLSMPRGM+{wkx240*5!ypSh@lG|Kr{DI zGX;me4}H8>9p@m2ebA2DpHMqQYJ$T)WTAG%j@n769dFH!lA!3YkMr4dRMHk^(<$m^ z#L&C>B2dn^W@iaSblB$suubi1?y%41j&zBT5JN}038cSUvulJTIPAYAqH7Y7eklJ# zD2Sn>JOIkQ*6a?U2oC$6gmT9M2Zf$NFvf*%2Rd_o&iFc zHmp<|R)Q!5hh3(Pag(JK)WtPZLgLY9Xj$qS#L&CO11@(P=4`{BCoa)pyCobaM}1xb z6DCeM;zJCbkAd&SHmnlC2@d;3iLH`Eq<2*nLO~22r4~?LZo{e*ir}zcmQbo&pu9pT zh@qp@0ZJrs2o5_^Qq|{fT{~(GpjMyM1czN8YG#%xirR=6dK+V*8bhk0!;X<;G4FEh zLnBg03|&15>WOWbuMLYQ2GLw_g&Q@($OM(;~ zb}JwWhAz9MG(P~mM|0S?dfy}@#88l0X%4$Pkh&6&;IO+w{4doG1Uc*;q>322YHz5f zw_)#+u;{SU`JVNz!~mXSn#aY}+lNpPLr3`tC?61q=&(P)fSgh1NT9<$tEuDa{g~7d zLs!piV|5QZN9c1BLJVE#3pBGIHB)fd{m{o})o~7T*aPgS4T4%0sR<4{%R+6i9kmfq z8`g#mAwkh$5970Gh@>sdrjgXmh@p4$cR(54hJ8aQqQf2yfMaS`bBFy+?nq+^2{Ck} z$v~RahD{_S!C_C5h$c!z`l0+Ip&*8iG7Bg(+OTPaA~@_B63R3Sl-Y!W7&^)Vpv)r< z(P7V%WQA$+6R9JHuD%rNi%DH{*o$*lUqm(k1hHj#+K@7cXc7tnY8@9a-+e%!b z!`><3Z0D$3B`{&)>>)nH(D@F7?~gX@0Ko|k`wxljfJCHs)t`id7&^*Hpd4?*juMLC zu#Zb9M=elJ5ej1HDCdE4mN*25eO6M{=k5hNYFD6kiPQv#eFR0Rqn4$)yV z49Hz|js!aFdzw0~-fEzz5voN(h@lHbqM5a+nS#TvjXu7oj&qR1_S#Xa z54F0aCOGW67HY5BQHzCIjGsl3py;q;_-u-jw1wH!h`Jdu^lnZBiqFsD2}N|+J^R4!gTVq`Q=KI|v^G;X^-r-_QCGh2XG1 zql^a1H-7dtp$HE98wurW3zRX0f*3l=1fYx~4#8oMlT`J&JJF8XWT;IdHNjy|f|{9S z`jOg*7tiVl0KB#U{MV;^RaI%4SRKS6!IpUw5N*~B0^?D^uh0f#*ok9_V4 zbl9_V=Uhmfh@o@-49;vnTSkzg!_E#iblJ_N=>OD>=j z5FPd@49F;Tjs!aFZ!~pWy=O@sF?98dmJT~d=n@GbhAwms&AdX*6dd*y^zk?9I0rfG z>vq)sf!YmH6CCyp3$4)-@gn}44 zN=cv;Z_Az{6v1H^mr$OvKq*Bih@qpD1TXg;3|+kv)GM@Q_|GPp=vBVhDj7fHPD%l-_Eh?#M z3>phYjV5^{NK-Jj2qNaCU_5y!YIZHt&t#4;`aj2CK{b-7(j9iBMHcEVw|$5r>M;7Ro&f4in<#Njlo;ZH?y#HE z#|CuRaq!A0^&r9buw(M~nMi!X=)cdl;ImB=r4=zrci3&f64lUUwzAX*7#^gyct=ENXSZ`tn#=z_h06YDN7rNW-2a7XRt(Uyr_B71_T*C$u2QUWaU}zK8d)m2T z!-yD+fr*WR>5d@NrMm7Bknd^gx|_Q0(Sa(C2gR{Ok?Oq1G888SsyGc4r!-L}5mCDP zo`MxN$)ZnH*mRO|7z0cBJg_sTi871Wp*!$7U}C(QcI?1sYj5wh>^AotCv%mqpmyTIH=~a80qzJ~qQgj8pU239SXri1W z-stZ9lEu;mw0q8Cjw+<9#3PJ>dAtK2Z#7Y}i9xDEzh&{4ZE>Zi>@KkbV_ zl>5XE)ulhQ*tyTJ^Mu%eF)%xh=x>$h#0%A_Kes6B_3VreQ1K;D42ss@j-k5splJKn zt6;SLrVEUL&Gj`#Whamjhd6h$pIZF9QY^sI7#lb1zSnVGK+;43sNHE1wc^x^u4-ZM;G9sl^9) zTBP;Oa1Hy6*nu%HJ70sHFNqhrbN><+XSrH4{aub9)N5^UutIYH*RU$Y0gQn;s2p|REB%I^KlW@j4M znG&r`B6g_GeTv1-B!->o#14#s*_i`&W)Uw`=RV7#tk?70Kou8);(Ve=b?);)(XRDc zMCJ-(U~^pt%1ekc-MKHZNJA~=wjY_q0gQn;SPu@?Mk}kMm6gN?-MO!&j}_?LSHmmo z)q@5*_m%m3-9Ws;7?{_c;B|YnvXvO6JNND8<}h=srCz}Fa;^Ak5N~wn-oRq% zd$b#2F-H|rBjORpz&!p69wTFvpNT=LbC0z6``O}3PgxYP17l!znu49U7$t_-p*r_C zi=7yToo2)ijDgu{0d|@bFI4B=+@h@4bIU*#e+R|ZM3L&;TZ5uq>(!Rb6~@5kngYtn zM49f~lP%Ivi@EJbd*T4bz#OE3gTG^xKVy_Xh!47R|C>HmpmYBdUdd7q8tmNv$lq&6 z;uXfgy!HUE88J#aF-mvt8DNWQ4l~m&^#Z03Xq`J;!+H{1F#fN$X2e7|D{H@xz8Wm8 zBz~x_eIi2g9W*$)=A!O{gS2**RY*L9Y+7v_cA;6T%mnL2uA;f4#6}JkZDp~`T@xC zC3T%mUHaib)Q*GNQKCk5=tmi9S%IjX0ku;x$_XM!cju?Dnod}>scJe)(hQ^jX}$th zF2yJph!wgszXS$OtEtA${6hYgt`bWy`fuqDSh^LXWD`qNSANUlDBI#lzggcUR$%ns z%44wdFh;pgtWX{KLyMLB3@cBF6&U@u;)sPGj1wPpH~!orOO=T;R{y>kM*r0df_iYQ z{yj6@i3i7;wbyfN-Xx17Jykwp1xEj^lmjbeVwF#b6{_nlW3loH z!%BH#1xEj^R0b;*i4Usdu4qx!Yd0(qwJ$;KbD~Cd+nX@?5}z>o z@3S%Z{2^9pKuppd_77l*YUnZ>Sn2}|U(`BmxQ6{mEWzlHr7*3-ZVr|bh##uMP5|-S zYCB-+uzw?}F#50hJE*pfRaz2Zy2EabXI4v#2k>)O>v7>4)|Oa-(SIxL!Ad*ggYK}~ z!Gb(eYb0-n{a90nYgj5#htYraKVw<%h35+WMTB7VU#KHY^B*!zs>A*Va{O3bXH$pW zDG;@EQ0qd}s1CaeL#5{&*^8UvO_#VR9+C91<7WpOmZ;z++Kk0n-M^xw)9ureuD znLw;i9rh%Pl?e8UzOtib5Ml~Z8lM68lUtWX{H35%61hLzLA3XJ|+xd2wq5g$~C zea@n)*Y3qY)UJZsWuiuP*q1@gu4TGL<_M$zbG!+vH;5|TVc)RGLfz%I54VUqjQ*=X z0`&*6%Dq_SF7ZHj*bnGq13K(`@JdG^Z-;$1f1i(uPZ<6885H-e;*3*X5R-I=?Tj-u zbeS(K^#O(-X&p9P!-C_;Zz06_W$81m!+skqm59^dO`$sM5^?Y!2t$U<9rim!6-Iv& zp{srXs_(}s?-60T!+t-`cmv}-iwE$NE@*#KMR0_DNUXrae|#y^$fvA-QwNRo) zb=aW{wQ_-|RR*<+aY_XuNO#y3v6?Daw5e(eBWZ@w|1?(tD__MaUl1#Fhy4{8NLN#h z9rhRbTdGPd!RWuG@4!-xIOSVniR!RxSR8$8airgrYY{6j`fsH^Sg9AM)FoD^4!fSk zN?nGP2E+=C{#*GGtTZA%=nlJ)MV2a)pNKk){;U5A>XAg9?yw{CSC1magSB(Ceojde~vdSRCnHO0z&Lv;hmP;*=I~N^|0Z>abhkrfmW0^qy&M@uOGh z?<6%a`k$IVz*lOVk`kvR6JKx6)#;C&iFYyPX|Nc6Izm9RrKg1l>VRy86 z`^Vx)PgNIU1xEj^^aLy2+8q#x z+7M71MAWDbdl0DEwM;|F9AWf-jw3;JI8miL?BNz!sJqoK!-gZUKykwB={co*!+D?AwFUB-{)NLIXh07Nlelm_H1)QmpRi?A7Hqb z+Ty9#uzAE1jQ^{pz0D$=p<0K1quIC0wPrRQ_O)giorkLJfayK#>}Gmj52OF8IiPx{ znR1H=(;fDmX6aRue}G5kEsF>6GhFL&;Tm?2Sb@=hE04j-L*j$(upc&q{|;8Ik-Q!D zG)*0@VNZxUjQ*>?XvXTWbA=oUdd6Y&Unn>M{+wQd&F^v-NPz$RS6ydQhy79@YOjLY z%S4UpuwQ1Vy%vaCF;FX-pcE#8bcbCu!KkLf7Hz7U-XLj)(f>5R3s&AvP)ZOhbcg*m z7#Oam8awO~`CEFASc1`iOK!0AQG)UTu|##)A6XoIU~#11ls&`>jQ(2*0V`61A`mN7 zhb>vG2n;J96Du(KZ{-uPq7WZ+hpkv-sWJ&A>M;7RUIEn05p}x5E|R^svLOY;mM_DPIO+Asj4JPf)5QC{>6Hs>801o3(IX++FX z9rlkFZ;dRD^i=(aSb@=hD=}cDNrLh#u|jp&O)OS^Wmt(NR$%nsN&;AEN_&O--sI3VgCkdb}dsYGDjHwpJQ84Z9`P)4!ey-7V0jyeMlneF#50lC#e6C zprj@!DZ~TaVgErN8_;2=!Ygytg9JP5l>B}EMSQ~Ozt42=*(E{gL`>2hb{DWjHFTMs zEcF3~r)nKGT*JB%OECIlN&hX8abRf-@k70bJqE-VsO^BM!yZpmVf0^hDyU9QP$m*# zy2GA~XVyfE2k^5<>v7>4HjP+;(SIwm!OBeHgYK|r!h)<)Yb0-ny;@U;YuFs34x|6- z3ldlzcCOGuA_SxVLQ7$qi^(*p_pld3j#sPeZ0fL=1){bR)Rq%9s>5E+P+Jv<+6GWt zm!Pa6f^>(y4y$R6MVqRojU>%5`k&?V3C???69}wZ)qp71f&0! z4uYlq3Cdn#iR!TTTO94RIMQ#*hlmvz{kQTjSUH}c93@t$4*R&p%29@u6T}LP{#!W< zR!$QibccP~B1@IYIie1u|LT`P{UTAPJM4@3t6w4NF#4~43)Hg{lpA=)ZZ(iI_yFgZ?D2D z^x3YbswlAnqyJXk0xNGODsK=gREPbh#mXBDD{m7kF#2!heX#N#@j-Ri?^#s!+AS4` znhVrEBx+QL{UNB?wM=d@M;QH|qX4QLQKdU<&LRtSm)kywL>)%|)jt7sB~kGvDj~!J z-C-+<)Ug2_wijO6q#h*LVTa`JGnDv*(SM(n!Dq!pr2;WYci0ud64lUURrWiO7?^{>iL8!0 zS8NCogE26%5is3hWV%$>Jq+@FMqPJP*F7>&#j&6`nkZ78_h^RVxIh)Bfa0V?WdaeU zyYER@VG}I+RE13?DTgtzl+OV>vl5jV#17qo&jJ(M)wE*=J|llybBQe&1GBXhY%NYy z77|-j7rxlyYN5rIe&b$7?7$e9oi$)*Rid(j*r7V{RTeud7>(zou6!RHj_1|G5xep| z7FT*_b1+aFC%{HlqH-)zIYOLJop}~+=wsl3-b+U;p7g3cNm2x3U@5u;-Yz66=Mt4O z#2ek6U$9s@hj!0c%u$7OnRtXTFpsyuV|Jo)ofxD#^lXd2>lRmf%5D=oFa~DlA=tT} zsN@hkRF{6=Vkd`T=Mk|3V_+=E}RoDBZc21Y1;dnE5W)q8lhMeOl|>;TrY< zu?6G*YHL?J<8PECr+lllO|kjyleQ@tov*2FgsE$9m!g*rjQ*?s7gRf>DD8)?D=_+Rr6XARhxnko^?y<_x@3x`Zhg6^{&qQB!#WXl82wjI zPhoZHxkBBD5RCo{^@M45C)1?5^zM-3b|3K7+g4*B| zWgroxyYs-)IMo?d$qO2tbs4jdx9D1wOLl3*~ zwH8Nu*Rm-P3%kL>&J<;Pin5ispgQoKxM{b8I=yGMTKwo0x`(6&M*mZD6nq^{Q4Xdk z`-v~Q`#x;3a}cfWw-}=e=NRz^qyPTSfWK2I$_ZkQ>by@`yq&N((o=PoSb@=hD_6kE zr4;1?u|jp-mn>E;Fsxi9R$%ns%1y9xgZQ92?i&_Wy>@Q}qLu?{cZeF*ZQlVkyO!x5 znInw;&+!qcJ|L=er~SYp3w4*UWXs^6TQJxVGbeHXHPaPZ3Wxs%f zWSx4DV3++Yf1kna$@e7f1Mpb{d=_f2yxLyxXz32S5SXMIy3AMGo0}gnoT;{W>NTt= zu>|A)nmW0CgtMmh``yRE(oy1vdSCn~h;LLoFH?t|MO0z*U-b;Ao@%e0Ai{KqeX70D zVV|&g06$x_9v7}*XNeUU{kL)ntXv>I=nne=EXX~zM)JNNeqU3EYuII?4x|6-*W0r? z>|CK6LJ(%Z<1+J9rjJg@qKljP49!>2}JEasO1nfs>9A)d1gq(hMVqRo=OoQA`k&^PQsLh~OI4hy`VOZ%?4VS&dO;N5`*y-Bbn+=n1yl7y z2S)!b6$ML$Q(SIv%gOw7gN^xR^>aa^#tQ2Qhd52hm z(SIwYz)DHtgYK|PT4bp;`GBay=)bxL)LlfK?yz0?t8+vhM*r1626Z`A5s3k+!aeR@yj8O}(o;@K9y>=S~qV_YW{YccP z4*N$?vum0DL*@vh|8tB2)nAAz-C_S?k%hX;Z6BHtbr}6uPXzU5sY-mR5=%VL9dcAy_W-6&?10SflEyPA>;J()t3V92~R`^*^T61O5ON>{4GVsJ#ZCq>X@I zp)sBmQ9r2-?mpDv@Mbe;h24StI6rC_90C#%PFKUAu!3LZZJ!uMq9i3gXjL@fS6q zT4-a`fI1Rp&{@=r4s<^i>$KAgZ9E0(CaM)wG4rXmyt?v7m0njxDrq9xr9dBxVMQQ!Bo&|kp9)1QXtmz$i{uNvNWO&9hR_ktub^6BeIlG+ zlP#N>1Cz+zv{k50>#9^t#a1ORk~!#pL$ohdBd_J%N8f~Kg;|{n^-<;G^!_JASEV;# z%J8)a=ePMJECf&y&T#9dtqj^n zL^vBpIDZh|?~wUc2g?!nAF*Ty(Ni1hXoBQOo1!lBJ00}BQ5-1R-oV0~s1;@p4i-O> z5ieT&tCqgcrmL|^f?^L2qFnRT){eA~DhX;DV#HD%)aS`%;ZiG1gam4@$L3ED{-~0q z(&Gp{ZJ5*H&_l=&Li<{L{vm=ssuZGc)Mny`9ZY+YJ@q_$G9kj*T-;Sl-x#xCmf~0N zZvc1c&8hz$aBnVm&OJDFll_+YAtV8|uveFD@qgMBX;WdHjUzv8Po5`u{RxmZcjC!a!|lgP%o(H?vQBEp$UzCbpkHmMG9FZ&o)7nUu;`3G6~g4(KwsIRLl z4+RwA{O|v;Dt|&ZKn~BjRMC@pXoXMA!spM$%u=u|v_E-JJFmIFw9Tvf%-y^}&Q+B@ zayXquoKENRN{*!892r55px{>=PDk1+#TYGQF^v z$|3;Kv;A6SN7J_P@lD&cip{e|HnQ8>n=P47^aSrZY<6qTpjuxn0hkLupn13_(c;0_gXeWuCX8w5ppk|Rl93@ zlzgwP=xtW$0%6AO=LKueI-SooGzEyB?btB8uH-*j;YG9PZBU`5wJv_MpHU(! z*dG|Iy*;y?RU?TNtTP5nvk&$+i`f&I8TQO{7PCJv^n z$b@`WZJfI4EL};YwxVNLq32@gS*$(lbj~obac6e>%s7a;d`2H7QO4%&gOHw|S&owK zEY=`o_5aM~C~0CuA5L)EQ8EUe=<6}k6gS$yPejN#7GwrWPX)u&Q8JmuS%93mpV=NI zvsug)$XsU6T*6{*K;~L|=4uvm8!|VuAbSw9lLa{f5Ix%mKeIbZVzk2B&!V3}g_G90 z_}6|$$63LyVX({g%!^iy^Q>Sw80@xvu$wIAQ)E7}XFgyt3w&-Q^92j?GC=e<6M{cy z?6txOd6flu8zFCg&R(@QKDRqcVzm{0ofX=Jp+8XR=5KJ+J?nJ7Z(`%l{P0U-dhdTp zPp_%5c?E=czO)=AE*8s+Ecr_tTdj=fp#-NLB^BU_Ufg9(aa$YsFoaZOL8_qimtdGW zN}T{lD_AEC_K!XDFRR9XS;2Z@unhZP=`7|zWcIUX_F*xH z15;1t5Ef(%1|MmH;9i@EkZ~-?Y=q3nXVs>uo6gdeq-ZNTg%x@!hF-+lvrgv%6B~DC zi7LiX@IkM`naQvkr^d7$?-w1i|I|6@&i=(%Hh1UVyyc?r}PQVv(96 zDHcerqg%AdQ&Y3G^=rc7wntCN=4xD^G257{aj}uYzftzTrszuzNLP&BiLQ=STI@6y zuQ&2~(7d@CFN4J!jJyGMynZa+NaPJ;LB=6uGz&5nAbK@UvagH@CgvI=Pjiqt)1En< z#axWc1@_E&Eaq~Y&{7iwmv0>gUk&M`t8pcZv<*p{fn=)2_1gMvU~#XYr;Fxl+^R9p znyYb#k-}Rjd&3lcmjQWz(R1kPIH1M8!{WU_-cy>lN#i|c@m{WKobiX-H87UVsE=+*dkRok<%go%07$de11AJ{YBXE7yY^7c#*i|NA&g_t0i zmU0+86w*moV`&!YGbB|4lBpWAwDqgN;_gLHyQr+7`0EI{!h+mI>04l!YWlNToF~Y6Sk=_@pVl&XpT!KW zX6yiGHCyHj7PBxiU$tkxT#a55OhR#FzRrTYi;%Zi5Enr7Y=2PAuIaz3P5gZp{bN*+ zs#)qnu%8jf3RWJ2m9b}jV%1Ps!M?y?VfMi)v6$77S=FBTHH%pbn0hj6upsp?cpVc2 z_u3B#sn3E$AtW-NRr|S`UDKbft>}-e(1{qjsY*A$f1vJJr!&sP#-jWO*?$6?>h5zi zW@u14Q59vP6{7`;a|>PGWIi=DyZ4MyGons-~{^<(iyBX5Kq zZy1X=5qaZSkZA~+%!14Xh@OyH)ogEUGfYh98zhxWkh##FIiJN`h0Nvl%w;U*dYsT2 z69kuU8wTGD>7;LL8(E}%NZJh~(~T_{X6$tCU~#X88^`jcaQYN|*+|uGgk*$gWjF2J#(cgf4t%m8w_6m#h7IKQ$ zFx{SB)iPL&#rzPN@7puqV=+Z!a`sF&i|IpV2n$jcA)l}yVF1y0PsJK`H?}vmiC19J zzd?m6kY>|wgneZ{qc2#&>SC~3_RN}Ajc``5#u%)jeX#m0W)w0b?U_HbnDM~WlNrN; zG{@l0Oc2~_tr60K1?hm0lzdh#xrW`1?Hz4J+p#^JvS2FPH5weB_*@n`a%}2>b z7H1!FcAIOcl$ODrEaq`!9nC~O= zU3=!+ET$WndNMy`K|~DBnIO2=yaz9S)sqe(4VVx z^HHMiS*J71#Kx>QLG~{uNEsk%`@0!J;;hRV!(z2WR&zUBpBvHJ5}YR09-ipyk!*_l zg@OMQAstwd&M2J*hN*A2|7LM|A}7OKL*=v#rn8uXklEj!*_Xu}h0Njh%%Lpi1Z0k7 zL8c*OG7B;fAbPfE+ZN^5+QetF=*v-IskJT^+s|krE7(R1w$7fp#;UQ36>Jv<+io9h zD~ovunfvXTds)mZVCu;{%7UE6;3rHF+-nyQa+U?TiID60tlCxEqvRWHMK7~LKf=)W zS$o#$%rUWXXBPg>xV60c9eu`!8=Ln{gcSSEa%U*YV!el~x4*MF;p!UEKO{KqDB<9V zz8)@9+z10NBSc_9K0#?87^aSrk6E0G$SMDw>8@Bq%YRuG^J`>&VbA=G#jJtM>h{cP zEM{F~)?z^#BIJ7(BoZKcwtxE0?*3L^n|Nauy(uchTI(X(enwHOU~Mp1OMB*TR*ghf zunrh3#XeXvi`fyGf7>(vWHGw|Q%`0W7Ni#j?{0$NUh9vLJ}k&cgbd4P)rP2>&hq2> zM%s!FVuhZJp(n8RtkXHp#KxVu4B3lKke`gry9OaEt;@Nb#oC0d^>((J7}2*AoOYD# zfhYQU>@>xVHt+`#vX2GHLg}OCqvSA)a}GJD%{BD1mj9D1=5=IVv1eXlF>{c4+n#xo z#e9s+2P}xAmT`}G#)7;85Ix&3)v`NE;oLF-w}*irfsmmr$as_<1BR)tWE6`t9XV6XHPlke;3O7v z0W#;>GiS4y%aOU%p1GLCT#L+AEXZbrY+yll14PgE4%?#atxbFzi+&Up4q5Bsfc=d2 zv4Wk&V5jVvC#)J-tYFtL*k$`*7g@}^$h>9G%w{nk0aH)reHP?727h9L;9d)=ZQKAH zwdoTaAw>}KT5Y=Eqm{gB<;1Q`TG zZGR6%$e`MmyUzd?Yc#S(*x4FkM4v!#n$%QyqOZp!Q{0gTeilNevmgsmdL9_2j*>Yn z&I;r#t8KcUw$U=UgvH#5%yst6H7w>%WNx!(ZecO^BXbW6augwlSdh~I(X)NRwkXGF z6VGDNucE>wYh7HhpV2v1upA6_+n#yTs&RuA>=_1oY#;0)i}_L=V=EV^V_OD}I`j_5 zx-0}tJ(;htAjL3v5fcRW+FJ-I&Vqb|kWzK*juL&)iT(N#TKch@muCbRbvAy*Z~Z- z*FM;87BdT(N9~!1Sx&5_|gdRvLF>ux-1x`j*?Io=L_V7{bD*wmTUR1#A1Gn%xd<`DlBGQ zWY)50)?_goBJ+C|AqGvnm7rUcmqc-thSo9XCkZ7%oX7)3RX9Y{aU`h7O z->n+0S;79nV1L>N`-8>ohRiPZ%uXz3Z(!=l?7@Nzz~FsN5Zr4+5i*Dc8IO=L`K;O~ zb<!6#l*&)xenQ@O^_YN=G}^rP1fbyz+&x2)($&c2aMR@NA@#QS~HdNSb zt&5HJGg{9Ib^wFzwP)_OYV2eM`xk>9vk!KJ#XOJ9Gxp3=Eap{U>dCysg51R5*G&-I zYdHwH&4N5f$di0l?UC(KlC7=i16Jr)qKrG#OHnpQiMnT<&Y&pz=7l?xL$=EVxeY{Z ze}9Y+Davy95m>BHWGQyG9vRUq5S%6z22b?$sA!7&*uZ~%5(<5=Qjv1gA;eh9~-ZWSio?W#I24<1GzvG(@|1T%fF)ueHf#mqR1>{&wQ1|d>ff>+B4r^F-sxyJr=}+kdIi9j{%}* zTWVr=l)S4=Twu}5qe7V`mRrmx_A^pg!M?;`pV>1jTQw@Of`wzSZ|s9rWica=S=*lZ z9gFz`F!f~CXF-0(;EhcX+-p$?iDW?%5z;iDRf}t4ca)UURy2kcItfF!QR(JyaMV5P zbha|FaU-N7yR!-M5fHWg-5Vi2tjn3fVhu!AKRa8J5q%iJX;P!%iM}2qOmSrcKLH_Q zS&-={Jp~L?UCAUCXFhV~m}|(bWpEaYxg42G?U{>N%=O4zW6xa0Vs1s|CKhBjLUynq zhXJBz`+#jxdbNq~W6@8e!U=0#WZBQ?7%SLS40g$$dBLi2juq@K2D@b+EStrAg3O2Z z%=;{+GulYza~7l^K=l92G$@+BFX3J*gpgNQkhc(0JlgICps!l7XuG526KzF{vO<4^ zp-ZWB^HHMiS*Nq4iH$q6JhID}AZ3B5?eEVJQYqSU_xY5?s)DR9?QDe^(Z3})O{x|= z(Tlr=Deh+mz8*sAupo_5x*-^*j*|K;P84z?qfK2&c`buKvzQ6UjJIdTvY2g<+0vf* z8;hBO%p?}%PlR+}LAn4$&vr-KqWn^u_&+RqA5`dRt&8sVGwQ|)HVlIewr38sYV>CX z8;`-p*asWMVopcq6no|*7IQ8z^<>UsK^9@~`6dYNwM>L8VL>(^WNkjHw%Yb6sj98$ zN>=Dy7EqmcaVM41gUOp-bV(L0wfw)!Vv5M*?3r#Bvotcj z_RJ6#vph1(upnUwsmOv<1&E&QuVU=(Z;iEyf5D>HMunP?X44-T2)Cb6byl!O7_5Ok z^LwjC1S?n+28*;0_A`sw44HBE%orB4B{215HfKTFV(```2=2A^2uWr^IwIund{*tx z7`v|IKiZ1^!3y0ILuaUTb62A7S*J7I#KxVu2H7i3kY9nQ?eEP9*7%=r@R%AiG!r-5qAh_4Q zK}Z!Aq%J~g<+ExvW9^QTR@#b&vqJxfp?^^6=A%U2vrcCN6C2CvH)JQ6Aio1q+uv;w z(%QP5Em^EoWVN%i)xn7V7r|*#o#2VS9{-r){$b#|A*2fn(g&q`f??_#obD{n5abLr z*HDs{!Tv1fSY(c}XO3Vory_HbJ#zw!IUAWXSdfJXna6^x0EnLLWwu56mp1VwEczx? zSZ}S1we~Yw%?h>$gYC3uZntV|Wd%Em!4BC6JHTR|M&=27W)_Qi5tw>1&#@raF!*H? z1ozr4gxp|39wX#IKC5=m_9*G7t>|4==-@cx4&{uqIZD($>vX;_v2ka55>OI!Y?A zI8~AJRh;R5nyzK=3l_5$GHci~zhyBSAhVu5vo4GI6EYjIAW;a3WI>t%M9+3yoLyJa zPn&oQi~c(*w6fMk3;P*0X9fE&21~VPrdTzSS;4wsu#Wb@{$VkDA+x(Zvm1*!0GN6* z`?4TIG58=81ozq~gbZgvrXXZuKC3of-E@{81`pC!bSx|MJPbXXwP)c+$tE`L%2EEJ!O1{+kJcdo2keZCH@M5b{SptCpHzca+T4Ry2hbx*LY> zqSDRZ;HZ1n>Fi`;@g{aGKOIc%rYz zVpH7J27VPnma`xmQF@*EC|See>_pBsa}6!hGPs4sJcP{s_RPI3<_TmTw`U$@G0!3M zGz)SCAs1PY+W^tCoo!o`>$HhqXVIUa!b59a+_#@m4lCG8iN-ChK%(g=*Ygke1oLtA zoE5An1}kJA?A1j2MupY&HZtF|XTHH=mI9`p%=cIjHwORE1i`%~B7|c>LJ^`Q+T8&3 zRr4m=9VMHz6%Ap94#UtDRl4~oQTMFVS;54{+;u^AM-yZ#5Vif?6CoMa`Xj54 zovqVG^dSVNNsWXj`g#mA#XV!-$01}i3o;d@CxKz=8=MI&&RpcoGS|>{ErT;y%w@=2 zY|mWCVy;EzDtqP%7IQN)H?SZ(5weX1IS3Fv+xu*b^1L?jJuLc3RLHW{#WDLC9bpB# zjKMD0GtXHy&ai^r#$eg@!LGBIkC1uao|(g9z5u44%%?0!aC76hbT+4tGTdvgBBUS- z@+LxxHMcuT^i?a`-0mp3tgUEaR_G5fbV-$NK1$R*>vXZ3;cTYe3ZY z_n!#qkYc$rv}dt8A?u$M8(Wp%B+%^p6Kh*-4r*>!1qT;9~NX7N)HCZ)KM~! z#Tkd3(J7|8Vz!pSku2tPWKOYXPGT|VBXf>Da~6xa6q$=ykW~m-&VpGL4}>xy4Y?%qphr9$1vDod*(r_#(q|?vl#4@eXtWO=2c`~vS(gkF>e7= zPv#94KRKNw}7OXDXdRH1s+$3)?eaV=>=BW(j*{aTfCfWR_$> zIE1)Z5HCRVY|E*3Mfry|agjx@fC^<(Ep-uUKcmvDU|(Ud&+VCER*g!mU^OsUb^Bn| zSj>9JtYgot#bP!Brk>0OEXaQ__>U$C?zJWe`Go~(j*w>gtXh1k-BI$FwxY4D(8(D3 zca?7LO4L2;bhb9JaU`!*eA~9#r!RH*5EwxP3X<_CA@3Y?J4o zGcBgggf*AO`}dP-pNf4!0xibro9RZmOegy!Nl8 zsxLboX`|KdE2u~?Jkw3f&u5NGf+2v^C72d};i@rnc&4068LLC>K;CMJ?m zBBM;k5HfzOk3n8C`pBqgqneO+I@l%Ttqyhxd9#BhA?oByc5o!N`Ypag9>eON&T|%c zAEFp9Vpd9ZZ~)fGp))ubGLu{c3gbgSnpiB__3tZt+8W z(?q3ZbW(DB+sNwQ)KY5Jj72L%Uf0Ik@T=-VuG*>5A z7gtwT4_7bOK-Xy3IM+ni6xTG@4A&gjJlA~JV%JjFa@R`Nde=tRHrFNB1J^TGH<(9H zcVG7a_Yn6m_h|Px_hk2U_Y#=Za`y(9({7m6A@?cwP4`2X)l+wd$C%R<&o!9WP0v%9 zTMw=m*PENdWpX>YQ`{X+o#!}yA@M|`dP#kxzEXc_fHY7V zBn_5^NJFJz(gidx1}8EvGhzzle@@W<#f55++FS|_mX?dedNA!Ke@j= zKprR$mWRs2XSbicum7mEkUk%qaa9s=6b#Pq|*9}@NY;bLYir5U-EpXim*KKg!4%Z!U-3ixSaNX@1 z;o1YA?R713?E~C?c;x`Rau8lQ1g{*1SB}6dN8y!Y@XB#`B@2B03wkHuD<|PAr{F86 z;cI8$t7qYB=iqDS0d)aT7Xft%P?rI91yEN3bq!G00d)gV*?_tUs9S)#4X8VSx(lcr zK-~k>eLy_`)I&f$0@PzbJ#qDSJq6@5Kt2cL3qYp1@4Gs>AGkWXAG$ibAGx}?AG^A` zpSaT9PhmGab7i=nySlqyxO%wLU}to6_j0GXdc&iSyA$k_&hCEhF7E#BuCQa$-2>g- z+=JX1?!mB&hPZpUhXP|5FowH(yGOYDxJLqG6fi~uV+=6H0%II7#sgylFeUmvhr1TIN4OS3q(u;EF+^Gd zk(NTFWe_P7A}x1MbFYBMO7{lWDu}omBCdgmYa!w~h`1giZg9_aZ* z=*J-XafqG;(f@_$Cm{Msh<*y9pN8mXAo^K|eh#9ahv*j|`bCI-38G(y=vUnP-B;ZQ z+}9xbb%=fgqGv<&n-KjLM86Hu??Cjs5IqN?--GD)A^HP|{t%)+g6NMS`V)x$6rw+K zr@NlR;{~Xsc`ms-dM>*=d9JuSd#<{>c&@p-dd_j_p7UHc&jl{SbCK)rxy1GGT;_Uu zu5i6PSGnGvYg`}Cb*``H2G`G%&Gq-(YVwC4#o#`BaL>sjj_2aoZdXWRtOb8e#N1vkl)#!vQipY|Q z^`6oE2G1CNqh~C?$uo}M>>1B*@l4>iLdjh;zgY2`8^UUC{duH-CJhS+0hS%n#wV@I$$+{4j1CKb+gnkKlIjBe|XYC~g-&n%m8f;r8%jxxM^2 zZXZ9M+s{wn4)7DXW!_0#rgt*8+&hI^;hoB@^iJbed8c!$y)(Eq-kIE5?<{VecQ&`) zJBQogoy%?X&f_+D=X0CA3%D)bh1^!}B5s>^F}K~jgxld=%I)+n<92y7x!vC7+#c@= zZm)MGx6iwZ+wWb?9q_K<4tm#ehrH{!!`}7W5$^`>sCOfG%)5y@?%m8~dAD%?dbe^X zyxX{w-tF8e?+)&?cPDqoyNf&P-OZiz?%~dR_i`7!`?!nV{oEz*0q(N*Aa})kh`Z`N z%w6*y;jVj+ayPukxNPrn?xr`3yXF0tyC$FDZhKF1cf6;#yWZ1Wj`s|A&wG};?>)yo z@Sf)$dM|K~ycfC0-b>td`7-y!dxd-Iy~;iFUgMs7uX8WFH@GxkHrLU2lk4QW#dY@G z=DPTx%kbUh(tSBxH{U%j!*`$S?t8%X@IB;u`W|t;e2=-_z9(EC-&3xy?-|$6_nhnR zd%+FxrSSuO9r;1NPW)hBXMTvU3qRD?l^^Cy=ZE{c!6Sno;p@(i^!4CJ`FirBeZBZG zzTW&Kz7IV5@?(Ad_;J4e{CM90eu8fxKhZacpX3|NPxcMrr}&2QQ+>nuX};n7bl(Vm zhHoT4(>IErcedG9fzVZBg-voYvZz8|YH;G^5o6IlvP2rdLrt(XD z)A(h+>3pVd2EW`llV9PR#jo_u=2!XV@T+}u`8B?I{9509ew}Xtzuvcy-{4!sZ}ctZ zH~E(En|(|9Exu*^R$nH+&9|K2?pwj{@U7%``d0C~e5?80zBT+F-&%gJZymqSx1Qhc z+rS_2ZR8L7Ht~mioB6}OE&LJRR{p4O8-L8Voj>l|!Dsn)^8fmF!DBan!ncP%>D$Yn z^6leK`}Xr^ddWSz`EK&heYf}*zT147a)-r9vV?QW zzruOtgm6JQDO^-e373@9!e!-*a78&QTvg5q*Oc?Zb>)I^L%AqqE0=_u%4Ok}az!}E zUlk7V*M!6Tb>RqqLpaK33&;4I!oU12;RJtMILY4;PVskz(|nF_hQBAAoLwvyZ6d&@v#7BH@@iE^=+{E=2H*@{OCwzbLDL+7b#t#&q z^Mk|}{9rLn7$SBQhKikpVPa=txY$J)A$Ao;iUasj;wXN!m@bSFy9r~(3}KwuT^KL+ z5GIH{g^6M>VUpNem@M`YriguosbW82n%G~ME)Ec8hy#V0;viv`I9Ql14iV;vLxs8G zFkzlJT$nG8fbR%L3Jb+e?nUreERGVEh@*w2;uv9>I9A9M#|g{D@xlsmg0NDYD6A4E z39H4)!WwakuvVNZtP`gR>%|q)263gdQCtPzSFV;ei)*AU;#z5|xK7$8u9vop8>AiL zMro(GN!lfDmUfFfxKBDJ z?w5{>2c#_Vp!BbJNID@NmQIRCq*LNi>9lxEIwKyJ&Wc&mIq_fVym&&oAfA*iil?MY z;%Vu!ct*M+o|UeO=cH@mdFi@%LAoJcl(NN3(oJ!N=N3F}i~uSxgB z>(YJkhV($pmL7^XrAOi|>9KfQdLrJDo{D#+XJU@@T$~yDLOd;}NoVAa(gnGbbW!ds zU6Q*IVxKeKkx-AL1EeX0UX-t*=(%32k zq;XXSO4(t9q*dXArPbj>q~leGN?BEhNo&G~OKZbNNbAB!O6$W%Ngb<=mO51%BW(yD zE1j-7PC8R{ymYqe1Zf37QQ8uDh0>nzMbh5z#nO@rOQhberP6g}nRH9Z zlYZ=2N5wO#7(+93^a?UV+(c1cS^cT3Ac_ehzcd!^-}`=k}2`=ynk2c%V@ z2c^}ahom*3ho!ZlN2GP3N2T?l$D|FR$EA&-S<9zReAkmneheqoIT4W1&OfF;rg750me4!{y_l zBjl{mk?3ygT&NJpmpQ<&pd(d8BKyyuvp{9_5-UkL9Pq zYt!Y?t{L)r?@W1(YnGg$%m&UJ`I&nzJm$&k%g&cCxE9E3d<*5Vu0`;*#qx9a5_l|? z$Geuv6I_{cKV`W*(X~RpEv=Nd`&P-@y{jSa8u?`CTKQDyI(V#?Z*UvrNv@6ZWY;En zifc1yZ-K{F`IdK^{LH&uz8TUku$PUkcp~k3I5K*Iv1!Z=XELw_m<49gq*W z56aVAhvY-9!}1l^5qY}nsC?Ob3_Kl|U%0d2@vl5hI3dq;os@gy|v%bz4s7@5syfyYf6&j@*gAClB)7mmm2a$UFFl@&W#lyqgpJ>z||?_n74DtLRXiNp?uenMXvOa%SyM9v%Zp!x6_uFbU0rB zT79RxbYk4n--DemUcmcoj<1`>M<< zl#Weo!8dKDy;cCOLC$|vDD|OXnzhhg3xaEqGe)EU@I=ETw$fgP_j~|j38Q1+J%05= zeJ3=?IruL#N{f@!LBkZ(Fb#WaPx4$e47}f|e!L8iAZJ1e?Ma@C>fyCd%2cTEX{ZZ7 z%2cRaxnjlg6)NX>P5ok-(9lmm{nX{ESg}HAc@5phu<+z# zGwaM6d3cFOY_NV@X{Y1O!Y@12ul=bw9mR-n-h`_!sp07RH(-wu)`h zE)ITTLe?-Tx@mk;a&+u(r4t;*oJ;%uKG4@|S<^G`Jeze-c9$>yP2dW8m1yBZ&rA;f z;*;dyWK5%2_J5?gDrZyc+e^-g(L?FsL1_^)I7s=tdb`a0m)EfS)W z613=_bUB+cI&xW+&*v>ZFmUPkX~h=?9vyzJs>S}w6@UM)$Y$Q4lxBtgyb^z)c)9;Q z>0~P!tDD#geo)pbx`n<)TO`J4LgO244la`ZWR7RiVUIlKyDy6$4-Ys+>gLyizk9gM z!SS_&mPz-sM$X#t+J)j@ME%dfS+j^wX%hug(sX={52hYD+vLHZv~PC3*iv;(@vL|J z)u9irV$Qae3N`*>^=tP(NGZ~-%*A~ri&kyyP!ElI?P6La#@5n)X8O`AuwBz$ho24i znA;iHh_Kv>n95%5AY z{cc*wkyu5m%c!K}C?jw+q%Aj4JF9|P^&g|ERjFOOYL#lWqVSiI9BIYDK70h9`5LX& zt`Qa2I=V#*N2iz77QvA=9RdvmbHUvy|4kEH#YMq!mahIR7+^BM25EEXS3}JwxN4i& zs##QWbWDqQcmj|Q^_c`eq152eNluD_-HVFjAk<)0u?eNvD!zSGt9IZlBS=r%2Y?%* z;xMi@t^dXs8OBN(D=5-8LBoU4R*;c`x}TBn#4C65 zCQ1Wk1nU#63DA*R2O{ye#1{EzaDN3Dad>p1D7($Iw(=mhs zCM6^`Re$F}*ZUYiqcy!DHMDxvWuh8Zsam^w?m`xF+zzYWs9sdPTGfAws@CvF_=;Q4 zRUyZ!uZ@y~g8C)`YA@>BAL>@iGw<8fqBVng$F*+XDyl{6XmDFVFRIaCWTIvyE4S9G z*RLN%41H6jVHF6u7hv#F$kD2nX1C!_^;DakjGgm(806pZQ?+&kYy#^-6mk^I)iA)A z-=4Ze@F*&6f52}jP*pTZGux;p=xI)B)@@ilyn1~ol$LGCx(h~%HtK8HsAhwjkXBT} z{T}sMwfaBRYZwt#zp-i=+IVe_>qrSStk$q*9d(+<(wA%Oz}0}gf~)xe(lABywb^iZh=yi&K;@Y6EZ*<@DAvj$}O@|;8=M)d7^ zjEJh=Rj<|%X4l$S#B<>g;KvG~m7}WE4v(mxcLhH-$Xj%B)rg4N)vMHXIA8}tRctac z_H8ArulBW!wNk4lZ&dXU3~Ky~CgnV~eFmm&wH66cb*k5iifh-hC46_5R@(T=OWzp+ z;nnL_uW#(xyh@=4cD3%50_Iuac2w~twu0Z1NyeRB5h`@Pw#-L9l`~xbWI^TGUFCID@b{GWR_$7%arH=A ztjXQTJx;XUQ>S{v8WG=sd-YGwYfBMP$=I2Y)I96(so|wF9<_E~{TFt4l# zD3N;;!0n;_@kRIu-bLk4ohR=9zA%p!+B{xXWelUF){VOO!cZylS#B}I6kj0=U=}aU-e)4f{#Lu<5f)41c^gn5I%xqsHLFhpxz1BYJq2A zrg6`-QQvO>eomv@gC;Te)=~gwwoc=&&vS%SX;1^C+Y{;GlysZc>Mxq*-gDOLQ&QU_ ztYEzc^6r*uMh1U}JqLX`5#Ddd=sd+vvZ#-`63;u|BxY0K8e6<7Z%7?EXYGfp38hzy>58Ty6QQ6#dz&S7~GoSg=@wOSHslCwGI3Noqk~6)4vehht5X3 zB=z?jbK9xSkdEMgse*&wOl+GN5ARqRX&VAl-lF0fQn6B^TeQms!8EJH1+2P)ow{_N7`!iuc+Y=(IsY=#gO(1&rBoPA$(i8+yq=SG+4}w&Y-cgDuy;nhcdGDDy z^JJf$nOr}2{@3;Dl{sPeoO6Gkes*?~$iJ;o*)7&{M|gav=qSESt6=-cqt?ebfryb9*_YG;Nj28z0_6KM%7)&}{7-)B4zB z`LUuc&DfE(PX5h@O7C1Wo~x{;=&U);XZw%G4(>6j-_RVF8q}2@vrYbmZ1^vrl>S&9 zkdx8f>~Q^C>6`D2hutH6x`vU@2uP& zeKToep;H5Y(O141fiuSQeuR38mV?*{CCMU#e(|7UBl3-L8$DbzwKfh;(pG_5oqN8j z$rMu>`jOL~K0;+h~RKZiF-VC_jW*an-{jyux2meZx}sn$S2IMn>6na{KB>`B#RG}ALTr^^ z&&!jg{(t)~rFLFGb%!m*k@wJ+@_eN?0#SZFTh_l$-U1ovv9*D=$|-(71gF^Z#^K)` z@PFNv!7fS&&u-0%k1Lrqlc~fTj++oXmLT33bxUgUXdZJ*I+!MGafncITCcxFbg$Q7+5$p(# zQO6-&ldlDNUTi0c!CDjBi{|d8=5`5QHK>d~Zg?L-9zkbeKfn*JhX~xAO>_VTX14+zdNPT@Gul%g+GkRIqe{ za6Z;>f@GXifVf%_!XuP!AK@rEQ8Lz9!h*Gibro2bgQbgvHG(#Q`ZCpJ9o0o0mAWll zBOF+3IJbdwGg!JoIAc6^Zq_?(3wvY4eB(V671Z zgv3aGA?nWX6-VF~;=NQkf>I&sP7P~~pdtv$he%}!q6aPBrgATo4=F5IEN_lWl+AIz zqo}NoO5H#zS;eRZj3+{*z!0elkqn^85iFBD5uzO#fgs@5QWYJOI%}VzE`qhzMGmml z3Xz@-k)9#8*R`PvmEmgXke+3@&*JVUo=gJDw@zv2$sa@89 zaA2+BGzCuM5J@7OA)YvmbvTjqEYG9irNZmt*zlueuD?WCT}!rl#OPMqbRy$)+AzuwZ_^JtQ|t6b_Du8K;=>}FF^+F z04%OJENZ8lFMysPmy7b%{W4*}`h+!JtK544s~a(Km3ub;Y?muIugX1}lwqwY_l0ur z5UD4L^ObvVwy*Wnae!%qQa9u3?ngMV)^G*@Cx=-0$~^~zvqPRU7%o=1?^FnIb-zOd zu+|9P4>7CUi^V=5F<5J2AEUV+QFFP<{Uh}EPI=tDD)&6AiUm*{M2cMHKFCDzQ>%)@ zpg1H%`iw;R%6$l%VV~*rxf%93bvdlHE*}G&Q6bV7gu_?vqX4l%?sitWe^D~lSi*v} zhV>1wCWJ`i35%=TC+Mig>!{QNeG=ioTEm$JoGBsFWWwPp_bED@$tF0{2?y31&K%&( zA{M@KpQV%Lrp*sT0Ben40SM+30bjY#FPY#cB7n6Y# z5*uH+Z_y!bVz?W1aNI=NPK>bD825v5Z-}&;0J+M2ua0lGj!Nya-w6lS8qN{m91f8V z5)N0nAJ*X)GZKA*IzcovGMNs+7EPeakD^g2gvg|*h! zOHjT*%6#R1K_`v5SX_QwCIVP%1h+u&Z-{g~M7l;CeC7TxzpbEhzm7+C%Nq@=+^?0) zdYf2bt+CqOG18+D=>dWAmHQ*_;;`s}ZoU9|hf=xY>h^Q1_fuef!un3D+@AziRky)C z_p0u~{C#pM;Z?a;BV|}?%Fjai8MjoO#QDno8Mk%=rMjL&xi{~wNg%M+KwJQE5Cvbe zJKTi@2j$t~S+gHfYIa=R0ujJkBM5Sv)$GM$^+*iXnpi_Lw*fVmtJxc%rw_>^?p3o( zRu!8TWU_Ce9is>n_JCw`gk7&@B6qzsIy_Mb#`ljgt?`b z1j1MAVUW+~?z6Wv0}3Y~SZhG>0E%@>(FDZR>9IPVXgv?srOll{IIz}m+5soUEhQ5U zSEr}waFR`M+7k|}HJn#~(~(&CI=!P_TAeDdk~XY0?KhzPI%)G2`s-%eZ<02wHSH{D zcXdk{B+u36U9kxscHou;?x$zyNYpB(n^l0m0O;+Odb*`-V&JOs-fYSC1OdNhvUN;q ziP?`j2i98Wya%@bxupSaDTmnjs{DUCqyY>!M-Qh?oA-$h)*9U)(B-+MfrQ4@<9Rx= zfqEWgLFW?=tTmjWz$tV~g9(SL#|w2hgH3RT5e}?1oRPp8K`dN7K0>Fg&g4;66~Bby z7*gcw@i9;|DyY7qw!&I#>jWr|CuP1KAFq?fDPLS#Oe6wWYXs9kFvTrRc1zz92Vaj* z(Y6v);*;_HpYpbXyXW7Q%r~9*V6E}Z2j5(`G>72$8hoyIu~#%lH%Cwk9#m>@T-`qs z7VLk;io)k!-c&yGGB`9wDhM^GzY9VO^Zz!ezds9AD}PwuRfj`$Sg16Fg!$TgSg2Ne z579HIyVnSUfb|_>3?N1k0bh5I3N0)+>RopqQ|fM9-D61|)_3*sp=LFAvC!8f1naxd zBs6m(HIu8iC!%+c8Pwa~T2Y$&@q0)2`F2Y#vS5X;Ym& zhdLP6_YVFE5I=@W^9X{kv44a#UoXrvgIP#0u)f2r0L=1GX(_>Q_4RTc%Thgyavc9m zD6qbxtOLrLQ0W&!;cDwOI+R~bP}UO)tnVnBfU=P|__}(dURK>=Hj^%_@47pnyNz`D zntGd=?oQH$^wBl12iMt9>2#=clDPOf`m7G;G($b92UDlX1tNp>o$NZu zu7yfh2#c$suj#0+=vkCSdxKD5eMh+mlslo)Ekfby=Q}!-TP7&?2?f@76njhDu_O+z zc7CK&RcEbVOABhHp%&0mErhtbIiRI+AylTNS_r}V-o^@0Ek~++&0J0=i<-H(G^j}G zu)eE53H7QirN>)Jm5G6`m#em{(8bIQU8Pv*0m0B5Bw}X&i|0~jtR``tgeH(p7yk=O8R3prwUak>Vn19-!Ual3U zP7_#b$|96qVUmNy`I^}krq#?29S7#kS*3Qx)m?{hV6EXa08Tw(;j8C*VTA>ky{qRd z3IVR}=ZFB-8bRYQvkJOctO<$1S`%xI<~F0|a#eIQ^!F8mD!PSL#SkdINQzt~{i2DY z+p1z~D29beElHHGro-3_YpK)cW>`3NIjprVj{{Cjm=r}gd|e#_h_iCHvrn2tm5dcn zSg_Wx+5syiOiCs!uEI{yQ6=lB)QYA(;lNtMc?~$Pgh?Fh!NHr<4`abhDn17kgLiIb$o+$RBD$EBOF+3IHQ3x zGE5plI9z2uQin6b1ZNE4z*@r@51g-vg{#iL(kZL+`D?3+lb|?}6uAn0A{32EuWzZX zu-4i-1!dLki_4FxL;!1zU@i#egh{i)q#4A)SL$>4Z3XrEEIe{k-e}k- zO=gtLI*(Xkt+6fz>*6qJA%XIh`(p3nuxO!fz5x2NQn};mUPf53{}pR-YgF#PYL$D{ z@EGawaH&$bTD)&*jnDeu#z)r&${$^S9G^(fcS87{^6BV%j-pC!=;)e zx<~E^`G-x%$f~uWI@Srj{E9_2bp)Upt8@XbZWna{thFwv51^oMsSW}Cp#hDPfr0>$ zCj;Tf0PB$JMV3;Q#3^V2VhHFu} z2}U;`F?MQ4);qw+4VU^627hGbf@7h~!H%qccw~wEi06^DOxdq-b^nhB2iB*-VOSpl z>jPrqj;s&R5zC6F1sjinRuv1NI4E4oBT@dy8U)ojBKw|+kI$Rn_K>U$4+5>20$v|Hc5Ue$z2>=>T zG~AIjUI(BaSrbVa)|&EnP@Y7}+>tejS7y7`WKxE;raS}6)54`GB+eaK(;%)LSyS-+ zYI&V_9a%H20?Y%z58={m0^p9UA3OkNn*hwW3a}Ue3&W)a1i&3x3q1f9m;fxX3Qz=q zWu(p>S<9g4u{W{7UqOQpYi;n?K>3$&X(fqsN7gUw$Xdx`uq|?}RryVj-xw~fCwcD3 z+K7W;oqRB`BWt}0#^(Qyu}FTEwL?3y&I03fxOAK__#^8yI5x=~?8rKfN4Cn3cph2X zmHir5_cJk}LpT_Ps#$hw4%*e)+cuUA=Dtt#Gx;*D_W9}?w{tQ%0>OGnl} zIs(w_Rk{FI_buuISZiJI5J30CrMm>gA6fSS@hcr!cS{C(L_o0CfJ#T;9oGoS55Klq z{*6ogkrfb84CIIJ`7z>ps7wUC5gTCT7jetYfZU2l&eKZPmnlwWL1N>c4R$)?+?i9#Oug<+A2V80Mv|-Y7hW-WYzQl zs9^%&unJHY0AhsXA^`5l5hDn97a{E-Vg9ZBeG%GQ`FnH>;5n+C z47j@gAQV{NQT_zVA>!cQ#y^A+I4zIBD34zlaYj+c)qRB2VSQIW7Gd@lezDMT5`y(z z=ro#nlA6iAeSZ>td`2E;uOB))V@2%()XtF__tyP66Sa$0)c%3m)d=Y_3G#2-UuCoD zvQC?uP1mWLVSVrByFj@eA>AYt{w@3405~dl^$6vLHty%%EE(w@A;J2Nj4y6np;b*3bQjt(#eMfm5 zD3ytWf1AFtPL`V{fus)WyZTd5f0ESsx9FcNS-m=`!}_jX8|pP9r5Xgly**zuvasO1 zyy>yG=WFPQ)Z5DrD+u+05ELoZiIfDQ;NF@KiqwvPI#B1=jG*IDr$qzm8d%@E=6P^6 zjg%TkN)mDLZ_78;;WTEbk`9cUIL(O<)_1;^;B!Yx!34*>CGXa;1?z~^u4+Xnu)d>2 z0VN_*YE3BI+wl=Pl-4FF(S!o)J4ymj;)sKLD?U!As?Oa+D{3iFOC~k$ZTMuU8I??J zsg1C{w=or}?Man?3%X%({hO?U)|Y+1nUb@J*C1P z2&4}qrFRL5zajJ?kZ#Dm#BK<^i$`wBk9gh?x}#K`xVk?kBv{{(J_S-f@o+bT^3fl6 zAntuLXs{Kv&!ILnQYs`t{zlMHC_bVaL4`VXkUUbFj;nh(H67OXrjG^8=tyZK!SFYM zMg!m)-2@t0GR&6*1M54?H-MQCDUBx>{szzl518>K!%QL=Sl?l$0A@0ga5sM@>%`Sl zWGbn``mQ;!CZFuY~xDNNG8Vb2ocdc!)1I5np9Rd@aORlQMUs zXEoG3_8m6Z>u9iHeIM*iP~8|QZ6IOpCeOx5?IzC#9)aED*=$967o>MYN?S>qyTP*q z8+`%hR`Css?x~~xmtnVl{fpUX5_!~SoVhantkVnAt z2G2-E9ar})Qit_j{a&ou4W445`y>SGyO1p|MtVrifuysRaRWH+Wu*D=ZizZ+h$oPYWH9`XbqF1tAg$;c?PSaZ)Ry;BN4Qvqk$7)cG~j zO2?zl&?xE}Sl_!Q8C;2RQhb~gOI-X7o0dJEd&CLrJLe#9=EX?^36j6TlLsWOpeq`vn;!uF zLN4*-t2>{NV0}T#TdRHQXF9N^5)=0}>Qn$skV^uuDtiVg!&+0G3*|X+(kv3^EA2UK z@0z9K0Mj>0t&6LB9^t@R!&wNN1;oNv+Y2x_GvxW=S#8f$2yk^TA_7=z1k2*gD(+&j z8BayMmg_RoyGl-!tWL_o}*ASyfyM#nq(9Ro<&j6xUf*+yupqanc47<*V2ot|Gj%zvwJzTUoE>q}Hp1a6@Ew5oM(%c2fp04rYd2xRTEjXBtUuzU{e;C; z;eY6;_UowBgZmKSz*@sO2Asd+q$7mGRpNi^aE_SZ948!DYdB|sbBb8_YW$Q=nwvIf zi2&9b!6gt}AOgN3zfdy4Wg>vJM({5PuE$B&2!gB1uVZtZBX5qZD!-19UYT8Yi;rBD{EM5T~sbUMk*68m5P`Ae&! z2#2fEtLt#8nc&nQ99U~O4&c-x7OqmSrBhbtv(u_#9ViN<$W`kC6pc!+y3|%!Yi(@+ z<$9#dSM2q4(wK|I<;QbG0Ben)IS87?OHJaXM#RBa?aku3Z3R_(6Ff3s-e_3W-l$~O z7Q_l`jWrCcE#oCOf%27mOJH%uVUb%mUjRKrsoZgOzeHHDK4C4f)9*7%1J)bF#8vKZ z0N^LNl<=zD(@7cDnsPTNXU0oiNSv?SGugh@MaKcAMM~X_tGhelz*@uU1)R5tg|FP- z!r-iw=Zt6NzDgm$)!my2V673n9dA~-7mM{LF<5J2@1VK4)LgD|&qaT)lE>Yva{r%I z#SftP9w~B_`+FveA6iu$1jW2~X&{O6m3tnWVFPvg+ziX7E{C<&7zK)m15e`?m zf33qAXM*z$;lNtM`5rjm5er|rf2Wh?rp**0fVD<269m(VfUn%AmrO8=2w<%d{0M@1 z@zM_j!By__usN=gH%C^v|DdB%E1d;aF^Yh(EM8g?FD)Vxu5w?-7W5Jj@M~$2j!B)h zE2xWLt##3Qu&s@kR>w=Lh>fq@*Xoc~Gu%}=IBp_sAVyegjN8DtC0^P@fL!IiMaQ>E zN2PYzcEW+RhO-Yid*Y>Cgu_+tdvrLvOmOxS4y-ktL%=yeEL`P&K&PzE=fhSN|Ayib zQsgT4BTzIdy^c~_VXd|GB$SVnGGDnL*GXe87MCBVhyd0a!DSF!jF-;GOJ|9LuiP*4 z+X^c8^LS)~ywR}A{cOpsSBMqX8tZMa-i()S5GY@{-}EjHi*D%V3!qmjl{>EPJA?)6 z6V@`Va<7nppC(8!_+(4Dgu?va^EA zJ~zV}Q+%y_HMmT)s-W(8{IuMYmJ}- z2-*<=U%9s{nIM%2V673n4uaPbq*n-ntK471=D0`R99iZ5ijGRHbUItb$O1;!1Sumy zN+S}ka_`C(bOs3cwUnk~QfF;9>LOTcUDOwBy%VIK2~sw(@s)dT9a2w*o2`T6CQ?6Q zgtf-_E*RfQka7u-tK8qw@#X5M)Gm9EaA2+BtTmj$ zz$qXWu5vHXDXa7OGpmZjpg4pSxypSA6pc!+&#A4j*4jD}$|FdbuiQuIq%jwZ%a2h+ z0Ben40tm(@NM9vLV~K;W+{g3V3M%)n@W}7-M#C!iu_d!kBvx2!tkb|cB|(}@pnT;% z#k)8xnyi~IfZm~0?zp5%Bz61aVZM+g5rS$ z>30(4EB6CzhW)P7=VsVp>T+0XU49%mM-!yK2#2rSj{@S5-0iG#|EpxI6NCk84eJ81 z&Lv1^2#c%S&*`Yn=%~~K{UYJOTEn>xoNEcv6~f^v_iH+wD<(KM2nW_0&K=;~A{M@K zzonDrrp;XO2m}v^fUn#iluTetq>q9mS|liw7$cQRl>8Ib8$4X)UMjJ$;H11c zvdY~*(Rc$XYZc>hU{p?&DkVx4h=i-$D<^6kQ5819ogIBp_6ON_AA7)3C;5+w%#a+SMF$LG*dsa;lwaA2+BGz3nA zM5!L(aFu%l9Zo$H9EosXt>H8SP7`9`D)%NjWwmmD-m2n@P;5bpT;<*ZibkbZFtrud zT3cH}*-grPxJRJv^E-7_0uI^6>2i6+SP~a323tzbx zVsM5CUX}Y$LH?OmT;0Qn0M;787l~%~+>6CVk{GNtv9W0GXlgE3xsOJF4@GOeEB7z0 zDt-;caiqvq?&C}pCsXOO%!n4p+G^ z)8Q;J!C65#u-0%^17{Vn@Rj>2oisOX)(`=#HG*G3u$~C`%6)yw1RIF})*8Wf5Nu79 zHWLI_xo^ehI9%QwS>?W2N2OLeJFH^-0gU~L(%wXAH<56a`+l~d_kw_5OS^SU>a0CL zT?A{bi;jWq??mZHqI8(p_{#ln9nukodsqj@O{C+*2y2b;JQ&X=N~Z~stK84(_)hDn z)GoU~IIz}m{sGR_MCmf&aFzR29nNJFoa=-GYYpc%aBdO{SGnKRDXa7Oj#b46P`pQq zT;+Zbibkc^LuxCmwYK^t#Yna!^>sL3x!aPwr7;(a%Mbq~^=1I9HG+yDD4!&iO_E9z z2Vc3DPvW)}RPJT*$S8TEVU>I7l36PeE37rvYG8dLNeU!TzH)y8SX^;f6bLN7fCBUo zxm=X5?xzR~)+el|{OEJ;UjS=3F>#gqZ~%;zD>$#peIzNvT2uZC%43tH(In1S?qid* z8z`f79ALVtRPMOC#}N*!HJopNGl5w6%6$R`XM#LuJny+rR4R8|-IIs_)*8Y0NoJLM zvDg$6gS93$1I?XA&E+chY3T2X^0<55bDwEd@dqf*CPl7tpKYQz*Q(+|C@x5n=94I2 zxi4TdY`#t(tuLNoi>S+Ct#$bd;4Dv)mJ$wMxi1IARjzVhS~AwpgavC2Ydx^mCP}La zi>ut%>Zn%hsMG^}1L440!`TX)%}LU4gu_+tn{_z9nc!?A99U~OyMeQlSoq3)r%t+| z=d{^F1hCc!{s6&#BH%0c{Us9|AOcux1b>6zNRo7zAh^o?2sX!W<;{^*?uT_$YNd13 zD#kfroJo>SB}pfUgsa@oumybz1pHb$p<_~K?Rn}VSZiH$9cNmy$*<$+U{Sh&i)tWH^-&lRjHR)%6FQsgT4N>DT^y{b@K zVXd|G2`C4WGGDm|>ZCCji_4EEi2&9bK`jtGn=Cz(ELA5CzH)yyncG%Sxj%zPrpOx& ztK6%X%vzgRVXd*&18d!6NhDCda<2<4t~e|bb@K(#6O_swS9g8Fg8i>ptdmWaznZ2l6IkC>Z$kA(n)D9|^A-DzG_7L)N5=r3SxUW( ztNRwA!1|7IA1HT;gRj=_rWF?aDbEwnYW;|!j;s3tsl)oNZcjI>)Qg4u($yY^^rjGBP#O{ntnVmIfzp^b_-eedPL`V{%}5>A zcl8&c-h$NmO1wqM>cONA>%00(P;Zqkg%SW)g||vCEI1}_daMc$)e)&xOKU3#@j!@8 zm!i|9NTT2>@L0BJqoK~PnMfUvIztnvYhZovnhxMf%P3F6DVEMrF25!s_rg2lyno6EJA_x z9px>c^dJtd;_jhSRp)L`D{6hA)|=G0YP&boj7p|{)J9m}+n5X0{-nxR+WmF1n0LkH z!vIo;^<8}+)IUs@-cOg_B?i9A{*d1`P-VZ5M^4Hc39GW-Et&IU;)L~`vk;tv)1?A} zE2JskW@hOIuHlG8m~w_HZu z=U-VRKW)pq{kYAR)XdYhrs`I+Zd}BwL1p}HdH3M*JgOjDM_g2$j)nOf9P(qOmB;W+ z-bDPWN$nq%werBJ^iU@%PTL3mIizv z-~)>S0RNc?_|HVvr-Ma#C@!*5bEs`<_IP=C1Qb-1`O*sgl$2tRsjoa6%gtU#uuEo%qX(%k zX(}jB#nWS+6Dpy;GFXXRs@fqUzYr+U5iDTJ;kguhQr(bO)CpdR8&piD#QN|`u_x%jsz=^tbs3l(pGyd1b5EY?b^< z``b4#m$kvR?96v^sR%k=loU z*c6)GUU_S1{s)=M?`AGXne-6=bGV1iV$QOdQ^B@=x&1vlqF-q+*-w~7USpA$jUz9b zMc!eNH;p52m_leZgEbGcja8Y}^e2A@E|E#QT1NwCJ7^CLsbGyB) zS@=^-;fWC4ya)_2?8Pc($($@%E#t^%^%~EZC2PQv1sNx+V;0$rMK(5$l*}T75vg`& z3p1BiEVR5FJaVTL$K)jz2`NevC4=>o27o4rS2ey8?9Npy`5Jy zn@-s*x|^3vvbK2pF_+%@;p}M^^$v^5F~Vx2W&eQul&vHW|4_%{Bd@$En*XQFWssT6 z=S+GCfVr*YGqaenEM}DV9Ewu<{|mFoNi1@LapZWj$muL{igDy*v&bJ<9C^?z@+2bF&OB!3a*icG?d8JO+GXZ)!OZ10bNRP~QM+!qm9$ev^qN^}Keu-L zJThCecKZXbXtpw|vFNI9{_slG7H>`F@{C(|`cyZI5?GYOZLq_=re&{3e#%xN;UDUF zH1NvXN%L>UTpF9XgfQtB0L*PA&CO!MSxlJQ>pb;Ws*;vwkqIm^);KcSEV4a|Ofim3 zHj8|fMRqiEd6T)kZsyVrE^2RgbsJSBuPYNT!z{cXQ|PUq7d?$zlx>#meU|Kh#*qW` z8aZak@>#Mx<75NPB8RcaLgUE6W|5;1sdnZFGncPe@-bd6Y^_aXF5}HyrZbl*C5+l+ zdC}>rlFrJAeruNcN0xf7*_yT6=Xgc4mHAnywh@xows=P{mtmp0tz?K<)L0fZ zD%4;rN!PM}O@7K&@-6kl=ycwGRROT|-%w-Ofo(W)XE17NL?F^>GjEOIl8+-T;qleug&bNK@~*T&gjbsx8e&?eUgITS-@CL@S%6cCgen<#6v8IP#jc+iQ45vz1vZOlw|^ zFur-+w8dM8xwyh~TZzLg>NyrwFU$a|kCwd&`6*jT3;aW!+|9i5_SO8|%;iNhmvAN> z24HS0X=xS{&thW2yta}aN)JYvMYd;=DaMh>W|5s(zjLF5Q?*S2LGB za8Y}^XPD8X?5{LD+bsNDrZ7N1FLI1q^tM^DK`hzF#*rWCH9jy)HjE`JG)^|yEOHEs z9BCXm!YuM@M5>+nm6^-8Ecrw)7q-@>GMC9_F7uenoDxQDmb~b6RmnTbh|Vxey^N(^ zY_?|Y_Jv;2Y-K(Xu5BfchugY#>*I0PEnm^C6mILmJvE9<@nLeNT zhlGdQ`VPqTXs@~*z2p@+RqLlj78z$88DkdNo<*h@M<$y^zQP)m>gB?Q?@gBcb#!Mh z+h9Ms-|n*8Uo#8p#)7&csBcEEULJF5o-%&vX0iWcOu62(aiJ2~&wDm5(YkOTll{Oe z`!dbtQgB_v&a>!LCd^c*zm1o$$vq2^0RTJSaLhcnJfEUvtnOCWQpZ07PbT-4cEEy8ebe8Ma8 zfYwhA7Fp9cvW8h?5Q`LzBVA^Z4OxTgd%3V~d7dS2g6`yJVJRWsy~>^z6f2>zsD@<2#Y!tVNmp+*0LWbKjrX0gMX;wdD1KI8O{G9 zb2(?`a-B(E1u$3iUp9-m$6{_rcoqFel^(ol78ww!tpIzZVdNvT$cikooN;8CNPb9I zCj_#{%4ROrnah)AE)KY;yLi z%#yWY$=t@tg3ThMS!9H9WNWj?L`15c8E59wmL*U2a$#$&BXenQ=90!-I+rkNog$5j z{>#dUzG{{_o2Bk1hkM^Ykk_o;p6M0MCgsO0`a?u>)%^`6^4&odS>!s_pw(V3Z1^^_#A$a<#McU1G{Jzb&Eyah&5Ow zm9^~m$xj&-dz?0&554kM(fms@7ymdOn7LGfi+TgHe4N+8R@N-$Nfr|r=XE@lQ+lw9 zS!691S;IK;X|u?>EK)FzbecsrWRdmFT$(YL#%3;VxTve=#WNqxy)QHn7Q19i`v`Q z4JTy-rQz4i!fo-|j{QJCFYXz)=#E*k@+?`Ic(1Ko?f+8oy6wt8o6On3X)-rRc%aRLTE^Mtm$6V@}xwK#|&Eky?0Cm)w#2alTjg%2> zWS06Rmb#@J?!A@BYu0XedquNePiN6@c)2u1pt8QZGnY*LaCR|^>dm6wGQw)9W$#aZ ziq!w`4|P0pz4Erw{6Aza@0q#eGwD14b1%0Cn#BxbF@@f9=y|0F2b)EXWs#$dBfl_< z{Dwt-Z5%nyEOH8q{Lai}7IT?y=CS}TYH!aooRqDVhW}s|zJe(%)6a_~#w}W8mTUt{ zw$?auwO(VDS+eac*%squo6I8jv&cQhk-N+y4&0MZ9 zmy0Eg+IhpRBuW|4vu3I9u+%rr)~wxr!z-Gt%!&!x(NZpf-{WJo#aorRR7udC43C*b zJTpK7TKCbwlasNcB0ph~1C1j;G>iNUk!oian7Mq; zk`M86VQXy^a~WagGLgBAFJaWak{6xs?fRFM5glumdOAxz#ca*m?UTKt*~(nbqL+BN zyrwPQ)y!q3emGZ{Mg7X6))`@?YuUGupR$$g#6Q&W*yfctL-XIqTy~qe9A?r7ytk6y z&0m?`h^dt5wIQp$SivmWvn<)u#*t6yHJ&s}R)-~X87Fg? zMM^BPfpKI#v&iQWsdi=)GnZhNyoHwwTWhVDi`&d4mbpZgFlrHrMq5b_Wkg$>rEbSk zw~@oWU*O1V)^1Poie~d+AdCLM%cUm*mG%88a~Y%`&OEcIVJxc92y2LzeI)rQQeWa9 z>UfOy$~#o^pTJzknYnz=q`w6)SCxEY7Bid0%x5UFW|13M&3aN?tB(tv$(H0?k}%GnZ$RjkXeX)SgK;+DfJY zmB?$>ZWq0xSr1%I)B5gG8sACN5vZ*1Tg>G~nr zAL@7nr1LaKH2;dsrJR{dRZ3~MS4sEUN**(dslj5Zr+dwzSxOI9Gm8{iq|-REwpnCD z7FpjoGRQ2l8H;Re<`T?YT9~=ChKt(Ut0Gnyt*T8MSTxc7H$oYMZS7{grPY z&j_^n;h{jh3i9{!_j@Lz7Bcwz)gb$(Rxjv0F6_1H0#Z%&G@r-y@JSScjpUw-#-}P967B6)y zL7SI4mg8E4>k3?dR{G#)$13#1FSxG8bq%g-ab1V&dZmBXJAOqkZN&9ATsPsm8P_ei zZpC#QuG?|l;h5mqiSKqf7CUysZx0^Xi%0h1k^Ok&cRcb39yx$V4&sqRc;qm+{)FBU zJo6Wx`5Vt1#dF8->~TDI0?(a<*C}|NhSwQ*orTvqc%6sW1$bSA*ClvehSwE%U4_>* zc>M#f>+re(uYcin6JEFAbsJuH;B^;X_Z*`f_u=^fo)6*q2%dS)n~qPMw;Y3xRj-k#x%$84_pF8s$!|^r3IS6wn-#OA*;2h=r z6tifsbByyd=U8W<^GnREube}j;}9_(5nnrpJ100tI42_F8$?V(#J7m}4iS?P@jW7@ zAYv*arXgZFB4!|BrgOey7NTY&Y7U})K-64B%|q0D=U0v&o#Pw}oZ}roIlp!+bWU(A zLZ-#Yv;>)!BGWQtT8>Ob$h5*a%lR|DRyx-^Rw3gr$haCA*C69sWL$@g>zzM3H#iqK ze|7%k+~{2B{LQ(@xd|CJBjXli+=`6bka0UQ?m)(!$hZp`cRTYPd+@c_xyrc@nfD{} z@A&!y*$*K5L1aIK?1z#4Ph>xW?0+Hq-^hLx*^eRnab!P%>?e`^6tbU2_A|(S7TM1^ z_c+fx_c|{i`$c5GgzT4*{R*;QMfPjR{tvQWNA?@Y{x7oMMD|#TE->zp&+b>3Ovy5RiObwU{IIw^eSIwcgkP76a^XM~}y zv%)afIpK5Hd11Kgf-u5$QTW1jNf_z6ER1qp5k|YN3S(T?gt4xFgfCs!g|A#UgmJEa zh4HSN!q=`_!UWfCVWR7f@Qv%PFv)dK_||n__|CP)IT>HyyB-KrTn~k*u1CT&SDrZC z^@%vcHAtN4$`@z33dGs2PsKT|!Qv0D&&0W|LUEpJh&bOhRQ%C3OkCjlT>Qy3TwLfH zAue)#Aue`}6qmS0iA(Xd%r#nE?iwQ&xyFhsTwjVmyS@@vy2gpCT;s)GTwjZ;T@%DL zu8HDW*Eixi*CcVh>sxVy>pSsR*JN>{>wEDx*A#IRa&AVREy%MKdA1?XcI4TCJUd-e z#a+m=8+rC1&tBx&hdld{=Xd1!!!=Dj;F>NTbj=VCA znc{KeIe|PUk>?choJO8A$a5BX&belZ=UubK3$8ihMb{7FCD&Z>GV)z<%@eP>=8M?4;z(hw zI7(P2juzI7V}uRjSm9UkOJSqsH;gMJbA1g#eK2CWgksIyiWS!bQFFKE56KWKySd(f}K zA3+<113|wD2ZJ^Vhk`Z>hl92Ve+F$8js$HJ{tDVI{2jDII2yE5I2N=^I3BcHI1#i* zI2p88I2E){I32WKI1}`{@U!a=d>s(Z1|1a61sxL32OSnJ1pO&o3_2oQ3i?a99Q3zv zCFrPdHRzadE$F!LPtXbBdeBMXM$jqYhbE_mKg2V_0r9MGP&_9bt#@8HR_}svs@_H6 zbiGT$nR=Inv-PeB=jvS*&eyw!uYZIK^{xvS>)jA8)%#btT<<2nZV6+9Zwp@r-w_sK z)h)uRTZ~orZTJJ>yYPp?d(E`B23#um1B}P&ViK{gq0RFSv+3vd+|iQDfpTy zj(1EGzjjO)$B8q<3-xD;JDszTXSTS}F-N>6{2=~<8sT4Io_G)S(0%8R_*x)N6n_#Y zIu?rGI2MWDp>~)kE)gd=mWrz#%iygLENu1%>jJ#X$wN<=Wf15bdv0c0vv_stM z+$qj->=JR>i{~7B#MzF$$h}W|G$jbKl8A!H8b~iAU@M0l{`+oicegu$J5HUiVv!3 z`M)yw^0#j+ul&Q~A~Q5@+Tw-gFF4qLO2ah1^6|6zIl@- zP34Euk?+wXyDf9@!0$Sx1wUL=ar(g@lIKqReW|N%hjr~L_}QvfEMt?Olgj(q@Us`n zf1dpT}ueBlyhm@@s9Y(%Q4%Wxu+D%@!mNfX9E#kNRGIY8Aec z>v}lhTjodoFF)HZ)ov>vWa39-AU`_>4SD?o9+2guaghC9LPuP_qxVCHO7e8g?v>Tw z?ZT_8w*C8d@1N1z5rao^9QED}exZKn>z+qqejrXigp z`}XcVpig%0d!1j7?3~)SZ?Bxr$sO=*)8>tuz1XN(NYkcGI(NzL(>bnhPVTG0FDS3b zx;AT+*{he!Ax~9Few~<^-ODC*`@g@s>#M$u>)f^fd;N0zcFxG@)3h^Q*JZuksH;uN z?3-hgI%V6WS8UC3dDSN2^MVmffdouK}5OF-{|xlhG|JCpV*O&qh6LRqV^YczaC4&zE;Q_SA#9 z|JHLh4~(*|pw1B`eUoF;16noC-O{YXzwsBwZSf0?u%5n4c3&m;rGsq_Kh@lkG^NJ+ z4{Wnn4Ge5;J-0lsmE_fbZ@TaMB>&|>HxEyoyS4nOz~=vNlIJSfAKO*2u$yo!?E25m zmps`!zDMAL&X&iuSC5RG9!mDc1;^i+)OmS$%LPmJj#>8otib!$v%lM-Nl4l|-QH6K zTHdM`lzQ{S&*sK)AEuMJ0Q|%!&I?{nn((C%<)gH+%Sui-EQz z%h_doC3)^ML;n4w-Gok`HhAURD$UEC^s^$_>n!;Qo;#$YXrbHwp zB}KPx6P?;2GQ4ecT4Z$l)U*!K?K(!ciHxT3r{wS*a(Lk3r~Y$`jW*^g_8MZ~?e3k& zj9%aG{wIfHs@8h!rMGR$rkK{Xi*2yoKfva&}7c;k>He^AhbOa97TevJ*xQoZH>1N>1ltgu%|7%S*BTz z!S+&ed6IVqInK&Cj>tKl!zo+2M-@N6J!+2kdfJQ`()wimk8zwsj`MPkw>lt4CUTU+ zFH-SarRMn1G>7~vq-}%Blmdq>5A)4-NltQDPVzRARO(U1?zc`!63{8wmeMx5O@|Ii zX*oU9a+G_kxU&j(w|w9uu7d4MCZ1}W7}?>)H1^A>ZFyIa7ynhToiBcxeH_r1cU613 z_M3=)RbFmMDJh8^+os9Yg7WK-ZF$!;r`7K84sDvIMI^WFklH@JO)T_hs+Cs-+qLAZ zclxDu&F@GQMqE ze4CgQPquqn=&Y9&`ZnRo(P`0bQro|VH1%=YS!w*jHMzSWjv=lFORknk) zob2v>xJL9*JpvlM!G<9zE=~Ob(m`e9iDb)r96t9k5CMhUSar+plbMENd9WS70v>Ml z(6R^0c=dTr>v50adZ@8Ph0BKmfct0n>7JIG(WO_G+My%Wt_g_ZSa7uF=A_|_!h}+J z$|BPvnJ10o!Ng7LGeG`rH}dbT2T)Dq%R{AF!4}t5ojo1mW7|ZxS9%&xX>EUu)5BX8 zefzUU*`W0aast%AE*^0K)oWu0xbe&vsJgUuye~9a7P4UuaYB7j?~aY!m--bo&nBNo?A&m9sTd zopxD$l-)EdQ*BHot)cZgX%j_B?%8dXsll^3((Ifxx$Cns*#HFqbEJY<#;|`qM&fZz zb{WHZC#x6AIKrw*l3#L?IX$ww$#3|mz0v@3UqUVbKZT*}7}>d5z0J+aizg-4^~=#oSio?oP8jPv6=+9Q7rH7UVSrw?5D2WQph(^$>)kvkW*h%NaWu| zpiJGz+!!ZKDIzH)GSOgCRj}3Z8cvV7{jApaJ=xyiu?^SMo~`(*HX)*4O~t7YpVG!t zsg~xKqTlt{?7Obb&q1$i$s*e)dCslcY8pRV%-f>LDTo(hX}K77R4f6l^PILk2Vxun z&7r$keoKmDjI{?R#6EEpIc@RIsg~MVcC! z8lNmrFSa=SJm*eiN^)D8IrTKCa#6}gE!S@9x@GgBO;e;gTT9Tht{nQtl zdh=JXJsYZQEGjqdYr7(!9pC)^Ng;VpH0CPU%LP zPdnp2^$=~Wxo%XO9g&if6dm5iWU$P`SrHu7%WR14amO@x?W{YX5f zjs(^TLY8U^=(#9hvkk$M`gtwu1h1BPj8b#W=U1BCnc3a(LRp%DyAR%f&t)6-iYH61AtEPt-c>B2o46rqOOZ9`1!c-m3yP4d`|;ve<4J?3qD3iiLY zT(9;S(3^Fsd?>G18ZiH5ZRQu3ub$l!rM00=u(sY2;4zD$HHWR<%h6*WjnSN%tFuX7 z^ymjRl?Jg|$SCvG;;N0kFo@MM?kHYW?O$svuP9c%Y*i;+JZ1tOmbY7F9sbNB*pW_^ zMFrbF-3;>piqkYJsNT-EOeJY?DH+$s4WJk^|teeeBpSQ)~=)HSp4(Qz* z_r3EHHI0g@hO!^waZMne6X?@7Q{MWG3h?ca3drDQ0EZ(N#XA(7AK1vUeMkO7N=je3 zR0`CO@iDKZwGD3{E_Y?B)|I>UW6oxOiq?_}9_Ltihd9Llt!*KfIvXGF@L8#9*lok# zvZ*_e{`3qO&$X{#U-_d$#dY8=rFkEERT*pwwbK9>8?OP@lJ=ToR;0FlbWGKDY0vGh zgXS1UuV>;rbm)k~H@r<0?tQe650`iEj+)b0-PX*|UeSEE6i;DwqR}i47|yqRK#u%5 zs^Zsq2jtPO!_5_ZEUJHY7Tyoix=8**cL!xZ{4}(3h$yA9dV4|b#KRbaL$XH)PVJqH zUIU8L;4KZ?VWp>g78$H9RsA?V&fmD%gHi=P27eSjf4 zez`4b`e^y?Qcrbr4Cu~H7wmt^jAlnp6Ex%>dHr@zvY|#!>yw??Onz@j+X2=f&2@#a z9P8)e*L5C~K3Ai-kt|c-ZdhFLZ5no;ZIS1>MmM?Aw1e#(EyZ%RQzPPWKiKP5Ucf-E zJ!*fZsej{7-I3~|MYk2=d$h$C-P-~S6XbzHp8kr) zr<8{t8{9yR>!(*0ezvK~&C`}|EB+FLeUoA$ITJC!?anLp)#0*~xndm~4UO(#81TWsaX}j_(^!HxJpt zn(LBakDjGP%X9nP|ViuZAm0Um@ex=Bz z>wuh$?q&sSp)&X#j2E&8$qkzt|Hdb@^iK-RM zTI|1laMJ|4yVb1CrR2=sphsy3bp|7UETbd9>t9jUm64-@$YpBw=r$dbace3y zT0V8z+&WqOPK3wg{zfBn^QV@F%OuSuAVOIo@~wrm=vUh!IlH}3gKa~2l=h$swyNr* zDA46MqSd#cF>jPlu0_3Vv-{&OIot7@2gked^eil%O~kW) zxW8N$kLP`fOiH9*Kv_JOBtM6j&1K8ry?&d2Ddopx%HYj>n}2EL?R$J~4)>JsLpb)b z{)nsMhy1dZAA$iRe_I9Lrr_H$HeCImGI^O^rt<4~c@Y2q@4uAVc>&cOwiHL+LtD!8 zmEH)%i{NL=`q#-@ATvF-Hqcf%#cxh+u)4eNbKpwK7-Gtwoc~3~0j8@JZTN%axVqO94y-ktO~BbmEN{pxpF3=MPsl7Ag9{5L zpeG7O$vuH<5(p+bWCC2>n~4C{8o~D97?zbDG$j`m~RKX)W0D&xJ^s^T9|+)s)VJr(zxC?2q?_!kua43-X&=zH1>6XkaP z$!6Fgojy0i{-!R6wbtdQfpaogI!-tPHJl(B=OiGmR)p{frQ1h1ijJ3zb%wBDtzlgO z)}>(S0$~lOO`yI^bxB8cK}V%-3s(sT)*8+&;QSjbT_>E;o;d&NaITx++$J1YYd8;p zbB|cYYa{lY+&A}h(%iIpNCdFf2>e50BzuUuGknPr*h9RRDn}3yqVCkN)(9$qpj?Pl zh9J7r;%zGTLb;H_g2nRYxJ20;=R1nZ=%~~Uq@q=fCxKBlM0z|#s!SxgG&zE0lByxv zk?}YP__b77$E42MYScxr*1D)R*lLDIHA1APiLH}1RG~6lO&wAVhWoS*jvGb?F~VA7 ztOv%rA(BXd`JOAQu8vRCQK?;4pKxHU;WPnGqY$Yf;S_q}G}7TTG{I>~IIz}mUI0#W zVwvH2JT=!TtMmCqtBRpe3?aqY)Ow}#3W1_g>D7|j3Tv&ct)U!7%2VZeD%U!#BKvW{tAZtZ@`YmCTw* ztgzNtQ^DFkL~2W*lL0E1f_VutXnSCB#bHrf-FyM`1i4(4ukMb71?v;mc&&2p4y-I< z;wtwn0Bn~lIIqgR2Pwl^Q|<%hULn$3B+ggvz1Y6?mW~5V8Hp2$%^tl-}jJh1wT9=Oo&d3mH z1mW+29{9AR;l``0?EaXKpXK>vntV6EXy1GcFTv)xOWqt=<-SNqrB*u2tzxVN#_AAhRfzO6k#Lp!YPO(Pfq-92 zKkJy(S-Xz92-aE`Z3Wxr5b3uN=~rUoEBDPhq~93suR1txB5fl^SZj>?z_=$w+C_j| z<-SM9w@XK*cG-TyfwhM7CvXmhNCyaqtK1Lia1NN@93dQ7YdFV&bCg)P%KfNLS)I=( ztSX*?;we((D)&=RG%CH$Qd?oIwe=#D&yzA=xu4fbV=fk#AD4&#)*8W05Znln{t1z; z5(i(o-{7|uRPO)ak=^n}!z%ZyC9~clR#2(7QM+y04orfZm~0 z?zp<`ZuNc&tWQ|qX_fmEzzTF5+;b0f7v}GiO9`*a{Yg@WwWeGH%1^tcr%0Ty+@E%9 zH&C9^b13)b-OmyTtThlPKxz{OU$fVC7Zx0pXNzaeen_d=ado?h0M;5oUAI}yUMv%(ELa~KgdY(l2n!N>^ zThHtC@jeRP_i+bPXTw_S?3V!2$}NQw2w$zYf_y%ApFPwJs5Jq>S_6s$P>frOA|S3# zkJ0f&>3Nhl-r@-d)*4P*;Iwf|Nrc1I>1}j4NhUb$2nW_0&db0_B^JI;Pt{ASQ{@%X zhP9^M8QPslo3GG2nQ6a4+OXENGojtZEv1t@SDSaiCV1F^TNb#Vo~|QNtC%dS0DS<^ z%Pqa-mU<8aSC#i-OZF`g@N1@rj!7*s`%>q?TI-y5!S;?@%5_WqiH)zy-_arEGTi=p zICa{*M|7~(=sp46$8PB(LgVW3k9A}p>3Ng|J&15%t>Fv-&S!4vQ^Miu@y~QPpPJwd zB^+35I9~u~II(c`_;8)FI+I6QRU8Y&(WJ=Lz!h-#;SW)=g%bUt)UOo+tk@7hJu}!u-Dt z>hHm!YUK~>yXxmq9U3YXk}zL;4-M67??OF;x_b>L2w2}CMgw9b5%6{Q$k4)qquzD* zF{SRt)jfvPVSQI07iv~>7YmIiAz0sqzCkl5P&2uDdjfj*m_fZg$%@+dQ2UP5xLW%= z6SXN;)Mi0#MyNE61o=992AfCIblOyB&!!HB^}T}^0AhZqG?yUw8hbvZ`Fdfl8O%=v z1M53X5nz^uN=pcatFM>oSeEEnl;d~>p}_i%vKA<-L#0)O!qwKRbttP$P}UI&tnVnl z0p(ZX;OpvN^|I;~vx#(Jeb?O%-L0g{*VJ3hba#+0tna$}p}RL!+D+12J-rv3+i|L= zck3wBD&%)7;(tT@NT_r;R60odTrGWsEz84D=hwzT9gkW|AEi!#^}SQhf$L1DbShLj zL0o(teMX0KilLs+gQ?TxJdwfrPWBJTu7*mN35%sgdVd!0~VeMh+ql-r@w zO+w-7=i54zn701Rcd8i-L(k`_P-)U$e$6v zZ==tM-)R*i-D+h}FW+ian19-!UcTE(ohGo>lx<;H4y~m7B+l2&4_j$9^L-r$=FM59 zcE#0g52G9RVHR;p11BI%?Fhbl4hSnOxa?g$Ur`8fb(bLmSZf_pAd+sE&vvZ&4+x2;}$6U@i?{8*jX5ZX|@Bj^0aM2G` zDl9l_Ygc8o;zoJ3_hnimKM(H+if zz$sUWy-YZQ%PuG3ysW?}PdJF~aNYn;MPd=1c11~AST=7G0irvCSP;BT1fu7DJ3K)g z5g@uFcozg!E3rg^5ZrfF9F7`wkAyxqPr=|1Y3F~mRgA=6PxJ8(FH_sOa2#SYvWz+VU??}A(d@h`;f|o1%K-{!tzrl!z-IM8PU1wSg4M!%tn&1 z=-5YB4*98(5(9Xy8-5wr;5b4-bdE9^C=-c8bn6o<7q)Nf#gv!)8IyKi{cm*Q8k|Dv zh|bk#R8~3lVxgHNgy>voHir2F4O4LGKVXjAVU*UNEt%s+tq5xKNKJ6)^Au_e+^8*u z+TzM=Aqk4^d@)~53ngt~H7%oQMsz;SYk;!4GFwR~qBCC&fa`)YUl|^0Eg>N~N7@3U zUn;YWge17~UnHW95|R0^-byHl&QbONWmjdkgHQxVzDq*cp+MP7D2UEc4guu=afojG zfFvs{lf$Hr=v@6bs2?SD(TN`ouYR1=5uL053H4Kz*+~KrT=*#*dL8sbkGt@b5|Qaz z&bUFi0))RRvx}A4d7=;;_+Na}UWB^1XUNR|+Xp|XBRW?PK>hhx_G~PRCI-=EKaan+SmM}#%YGKG zbk+|N?y{r9b28#Ybk12GoUg{RR|ryc*slUfFmy$)Nb3W@ZFP&MUxTj`5~35N{AHo{ z##4cnOiaSx!b}E0H{E?%Ty`2MBf3+r1Ldq(mOS1_YT!VE9 z2hkl)ecAaF4Sqrdi0%j)#i|^4u~=ggLv$zB6vJ&o!xdb2 z6U_G@{k~g%qPv+}#m}MGf)oYk-9n+*%B|uzQ2Z*EwI)%~eSgJQSZhgNSYd5w$`Rd7 zd3)fri)HzQBRcSQfasx5JAZFHKRi|k!a{V1)g4$}V_9dy5?pv!iK??iWj?rj5Dua{ zoPNOR6U%xNj^M=mNI1O}IQ6L2^V)elGR%Ew7mrn8ys7UM@?%!*|*V%anz5uEufzM*G; zK-^2yBqnp!&Za3sbT>td!1hxtD~e_Fh)s0oKS@YM9Cw}sCoH7J#E9sQaWxoM#tM{wyIB%E~$oL>kB(H+iq;A|xp!KrVRl+E?L z!>!^TDDEOf!L9FtqMh~HOJhZJH`aqt-cQP+W8W`HV=Wfjk3&R&=#Job5FC$X$70zL z;t*Z?aq(DzYd?lpM(PI*ckM^Qvz{bYM0czgzY>7{3KkaPAMs6&8%qt%Sw7KNe?xnUCmB`6(zr5yu`U zanZRy5f^gqk4qe28fW-sT!a5297K0Gk-+&6v53z7KXLdQNcx&7>D*@+1h@vhM1bgy zASzDf+>6DcNet1Q*z*|fvou`6xj&2fo}u4&i*t{0tN0=m87T_RohcMwa;sP#im%48 zS4dQJ?yvF{_KKu0tgzQ<$`Rd7c_rYy8OMTzBRcmt0WnUWcJADR;j!K(EJSx$Re_Zl z$KnY~aPEl`RlG!HKG5GG97K0G)q(SV97`e`!MVRL;Up<=Y7h>hJDgg;`IuNl=l-!I zEi9YbM1bgyARPp$L?Al%)bIouM1bgyAO{3><5)I92+qAO4#yw#!;w4pY>CQrI=OB! z{tJvoaqQDL_6d;)&b<-e(4T@p+)JNGOy;U>LQ{n3Zi>DD+vjntMI38JY@&1jTtaHW zahpkS!a{0IjEL?S^TGIS9Q%d<1?T>)#P^LvWlmXJ!a;P0QwW@najZSz2+qBugwtMu z)0uD(-Qn~APB&r^oO?G(*<8;(-75BhVsBCuoO^F5+F7r@G*(1+V;u<0fhv?i#ipL6^`*6H6S3hXDa~~R>bquj0x?`OR*2!^f zB7us|eX`XY7EP4a3!tYP&K=j_G{Qo3gf%bZ+?N1r5itqQeGvePbSq(T?n_A-(Vg;Y zD6foT%Sl{x?koAZwp`)>(*nac;~M;#a1h<$Yyi$WViBGDI^3M4`kE=}+?N>yxCS>8 z0irvCElTHJEVh-z5Z#IG#BjIMa0TbS9rL|RzwZ|3zRRuRJ}B-XMZvl6Q7G^R|w&i!{lEYPQ&JNM(^u}%>dqC2dM zz&ant&Jvd3+|Nr?XC*50fqsc_5Z&Qi2hQJd>JjyT_Ct4-h6LGbnbV=Teqq}a5oVkx|@RsL2!ROyO$sY=YD^D zVf&T(;mDo)y%Lq_bRKex@gy+H#Iw@z>`@{SoO_x0(3?G_K_Kp>M499(1f)j3|MvRE=7z1E@KAt^GfP!;>UgCRJqB5t95e}j| zoL7PKN<4dsa0KW6iiGo$0_QctL3D=`1WpBF5uAGkN!eV_Z@5)_8;Wm{qTt-$f})-E zs!U@=bT`%nD94eq=-lHZX{^O!`;kZli0%kJ0712Q_Fg=Dhd4y%UQIk!;N0KCD{J(F zhCBCn!n0NpXs8qb=Lxai!Q@^h_;!~v!ahHu6-*n)5n-QlzbPAg&& zoqH?XoUQtrDe2s|83ecnza#=gcLZ(XRqweMi+xLCi0;JNVYvA;T*0~LW4^cP_ub;$ z3*0Jpf?@|!6r6hpg<_#w#U4=X7SFnnsOa3g@fFrZ(ic`(PnvQ>cT?UUIDO;U_k<%l z_r8GGpiet@?%#*U8bDZx?yyDxYgjxRLRf-xA0|-^k*LfE`bfe-bcZtmIOF2k7{U>p z`#1?_i~?sO;UK!hnFgFG#3DNPDU!6XY^D+AXwk)14Aris4uizVc83@F^v_xVuSM6$= zB1Csn^b6QF#W3N zwuf*K-QgSt&cS%LpKt`{eo(^MufX}0a1h<$90$%ZViBDCF-h56&nMg}o`T{@QWTu~ zNhsP`uhTSEM0aC72jw%QEIRiyk~G$0vHdtt1c>eku7TicJi8pvE)j?5+^>qq3Y`08 zys}q6Xt;B~6rS}uu_C%-y*;4{yDfo5B$)4>h|c}C1dBN=ib${;C_ryDoI9?;I}*%y zbPye3?F~8imx1*nF$vE7MF1Sot%Sw7ze380?vyJ)xqJe9mBdBoUOpl82Fj}v2bc~S zz8TkGMZ!UJhf@hSZxV~>+~35_xvsC7lFt2xL4a%UZ6ZK)M-ZQ&a_+@q2_%N-PV5~F zw+ancaPCzw-#7I8ZgKAKx>bB1ib

      IQJxl;s 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

      wBw|I0UFVS~PD_iEOtITtGYrd}HjUqASO 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

      @|peGp49j|f2 z2@BB?){TgBUk0ot#3VTPB>FgHa2+ln!-8xCP6gb7x={G#2yTrL0I3?1}?`(+9y#!#ygCcC3l0<;$ zZbI$@K`9~-oqMUG3GOEXM0W(`Ku|WFl_3bhxtC4HFFw#ONABFqNK~fNdDtyRG%(7i zvnSHoV?-i2_wwnHZ}vPPZIj0&CUe(%X^IftP0=%8i%Dm}bfyuT=-gu@q#(!DBsgIs z#S$Z;JI3e1STUVdAV9&nSCsfFNL1#Oy+AmK?r>fK&dcfSCBhM$`^yr}OA4G<2?x;~ z&YQq_gIEOT{)VJ%?&m6Q6{|rpo)iV=9uGx3>-83m717;TYe2a=DT~g%x+IOgSYSWi zAp%5q1W6$HFrC#*XNkliI`+( z0!uK5`RUSr0rXPCx#KnNW5PoGU$OGi6FqrLBhGyfuy&=h?S$1QeQx{KYyDAqn;(pd z%HIX79r|o-@JHbnWpD83Z^t{k^mo=9@2vN~gO%N5xLCZ#?IkQkcUXskb�)r_XJ5 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%0Dd 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 z zwayOm<}0&QoPR4R5oc-Bu5-X$w_d7l(Kt&7;dCFIR@Z%5xN6BO6KCnzA>c-3uHVGL zqnD4fv<h3 z-|nzlUpI1U$DP{1sY|Pl9RudnbanjRHuC*|Gj$K1jk8tHuEDc$op(z*vM%;cUl9d zpxL-m9lupZzGpbo$>7c5$!~IlN53Y{jvZ?3t44kgxZhpT z?|0Sjwvk_hix6))_?nqNe`xQBDjqTKH>Ba@Qcq?nP((=gFy<5Te=_r_8|o_qay zvT@IHp*_nQc~<0}a%fM7k>`uNL(xGdJT29E@G3~BI2&Iwa;nXpTyP4SjR(~6t7+uB zl{0OM7mNPG{#5PZCOhMGMgMjquS48xe|(6d|D-?qak5h{{-^Ln8_yF#aZmZ}&vTPA zMkarA>B|5XivEj6K6kj!&G?|A|EQY5>qeeY3H}veO$h1vz{s-*_k1+8XQ2dfNO%%T za?fH$CS|zElSU>sm}uE9mk_GxKdW}UtdV;qu23;SH!qx_dn6eJtHFa+4eeQ3ub~(P ztILDALkDvid3w2Ld}z;DBhQBL)RLKOWRlKy-du94qx?l(mAyQ2CHGV&YE{YHlJ8)4)(p8Jh8GMUUxCK#Fg z3KK0M(-J~n*ro(|TJggZYAWY*&pDwzXBl}e;hu{^doDEcT**7MEXafp-+CT=4bmxI z*j5`kZR1Xx;S_XXi$agB){REKw>i^|pb1;ZpDL@zzjNQ$Z!UL@yb5uzC{Kt*Qp_K{ z2-&HlQUXu3@qFAP?&-z-_D^w>CyY$Wap`9~K^L|%Mm|pN*XfyJBiF>{f z+B4e7^JVT?J+x<4BhNbAGsegyo}1J+GHC!4E!#<+P#3l*)Q)?N+%vdBW28CgJHmXS zdz5Mv>@6PbjnJO2>os0A3f7(nYa2RPYa`Dt+_Ph7&v%SGd%#mmW;Y{~k9qJ9f=u{Y z`<$En&&Z@NH|bNrsP$%xPIot}v^t_ajY1FQp$8eQS*vwGkT+kM^SSq&Ad_eOi+2e( zS)?D%g+^YhxYzPfSQY%y*O8sNm2AQjZ9Fyv#jWVK-_A|87@6$j(z}DVlAT6A$GFeo z;5qcHn*W1Fo@cq|snDK(8F^mio|i&_ksibz? z>J>M2J`%;@u6<-w)T`S{3VVY#WG#!28U=fX2P+-g^GUtN6Gp)#9?TXx*mFjnFL2N2 zLwi;*@~jF^ZR);cWb!f(UOmW!ueI9T#ARgSD6I->QALi>2=M$A39 zMrLc)YHbkY&F4c`?%gTKq$(WM_5A@i>8>BnZbn|8a<7j=Vb$?R?@4y5)K_?-jYsdG zxOM&Z-*A(@MkYhK^dJBWZ?^{+`HbQ|BZB8pbv1+E8hQTAJ%0-A`J<8NH17FJXwOMT zp0l~NQN{+p5e2ClGHKQDd{-J?}T!FKXs+d_M8(Q9ln z3U-JG+aEgEUL()HxaaZEo=1&5&%skm=4m67%RKmnAQQgU{^2H9jZ7YJle-0s+U<~A ziANpLn?|7@P4r(J9!?Cgm9RBywMHe1mlnPH?bw^u0GEhc|~)t z3Zbyl{Lx<`J5{PWo@nDyB`B`XZ|~wJHH}Q_bLlz&7Pb<%kxvr$@gxRaPm|RQ#v6I2 zbI;V!o(+vWU*n$5LVGqf@_dVXzF}n2mYcLPGU*5tE!$a%p{kN5YRB6fxxdd9vi0-g zz0f`CViYWg2m3U%=O=oNkBox#<-z)d4%XYqb1?TD5Zdz_BhT;PsU>rmk;xA{`1e63 ze69V&O~x3ROywq%3mCPDY|-i7;Jl)a=+8!>=kd_9jn=HyIy1gKb#wkymoP~?V+&V_DA1OcIsAg1W&Z_I2aVSmEZmZH#ufxa*j)%4&F*m8u|Rq zeJ%&jq2_A-FB*B?<({`fd)_eej7suf1guFx+n1*Kz{vA4?pY{FyhiXm73U^JjZDhG zM9cP*Nujoqwra_r|dI<#j+y@t~$SWOX;NBn;zSdH?NdqI3SGh?>0i)I=Db!ZdK^@U_qtLB*=(m`A z@EaVqX06s1LEe1E4dC8i2bsJJM|FJ<=O#n+!#T*vYZUhy5eloXKl)g*Q>7;0i8dbN zg5vh`+fU&plZ;Geap@TV7OIkIMm~AmXMXS;>ZE3Hu94?T?zt?q=Mp2&4cv2WXwTn` zJhyVsO-3fWxycSAlfy94vV9=rr0lPDe4ml~X|C{>eqQ_;x<|*1f?egoE`|2Ipw~EO z6zmQUb~ALa>qefD$^PBlk{q{iE)ROsdvbekRsrxt&UO32vueB$*NpT~S za@^#Zk3O61RH+4cqK(Jgptz&__KUemo{`BaF1;MU!d9}>$Y&$> zSr|vYkXP=tf~I!Q^`)1 znu#accuWt9JI!xDkDJUkGFi-}^8hStB@2vvR&$>fX+cx@Q#FIjj664S&kdnH*BN>4 z;-1?>du}!IJitBo8krp9CWnno&cH;=_Q|wRlk!)!<0p*V|KWA$z(1)0l>mmGTz8% zCij^hJckyl8Jue5na4fnhxVLn$wM&FK0S{}7q>FL)*j;~g^Wx}ag!41p|%oj)QY8t+Dg`_BU;ob^m9CPS>_(R zm9RBywLTr>%~xi1?p-CwWIY_!_3h>+wbFH4NlhcKSngFf6xKF>bT8SdQVsA#o7_o3 zaku;JecYsxk;yAux+#E#t)#J$&s*H*jr5=k*+w;kuN!%`=bmjtd$u<6?7}@ehW32N z$g>Cc>}F*02{-xB$fOrcv~1^uoRquNj(=w4-k&S<)6a|C&^_v76zn@5Y*=W|A$pBL zM#0ANV536^8)f7C)KJJs%jq zb+1!nOLhPnSNIq%k=DqFFB(6GeKj(oC$+s;8xa}Vo1TA(HbVV9dmo|;?b>B$c5j)T z*(P5DNqL{Y(zew{`L95|djO7|{Sv@#p>V7bpTJJVv}(Um@Gi?v#Qz#w+P3PB%symsQp@P*)J;W!{qY^>k0f;L^Y#>$n*QgmdtM5 z)I8v~2Dk0fIaAHWI0`hL+MlVNz*^*HB0Zm^wULwQ`7hK?p>`^@GtfpL$G_6^nXHXq zfCGZ3g#<*a^_x)K)`+1z2l-X1W9_Xy-RIwsd8)J%0{$SAUt(Mx1AJT|8ej!WyxYk+#%=1x;IP z#4hzkrXTbYkPi~_AwoXPk@p96UPIg4*wVUd06+)rr#p&R9#ek=*kUQ%?a3$4UP%4o z!s@HBd4p+u~}xj zETvPc?CzP}T6jGTm6VhgAHH0pMU%{qnXR%jTXbptP77bx%+A@_9UEn}4tV%d*S4)K zSFe<@6ne7QSN5;%eeKho^X-f53+?NjtL(e%f7rL$H`^yWZ`$wLZ`;3hj&h7~%y!Ik zoOkq;j!0*uzoaqFJJNkAXD0|FOFm(fx_0kXWJr;*MJ^Y)RwT#P+t$xEz&6x2+BViU z-Zs%T**3*C!#2~lz_!S?*tXKP+P2pEH^Fk(p6ke`x#+m$xaGL*xa+tFvIWuxX}@$pIt<2R(x1`^ zaGsIQOBbYz(q-w2^tW_Px-Q+2Zb`SLJJMb7_mq3fU&>#}xpF`GYq`HXKprFymWRs2 zm1=6O8D2!0IBbF2U+D ztggW7Dy;s7)iqfC1FP$>x&f=3u(}1S+pxN08*IA^%X_fA56cIz%&}j$ePO?0>uJAf z>t(-X>utYn`_g{L*2jJq^YxxB*M8sD*Z#oP&z^(1`-S}*dycI?z6RKPVkY;p53={R z54L}aIo-!T)c%!ym_64%9P|8Jdq4Yk@E8G)@9q8VBkcq1qu}uaJVwJ~3_N~>$5?p$ z1dnm>7!Qx1;V}Uo6X7w*KEpN{UcbO=3cRMmYZ|*!Z z_L=tI?X&D_?6d7_?Q`tw5OF;sZa~D1i1-I0ZbHP(h`0q2w<6*;doSB|eC@C=vF}9W zU5LCJUwaUJFQV^5^!|Z+ml=?VMNMAYrl5!m1)Rs=^MvcslVf#G{A9Q8tAwn4RTzR20JcELmZc-p^hukFvnGCxZ`i>TgNr& zJI6oL2*-8ld&doFq~oSE%5h8j!Esv}?YJY2aom-DbS$@z#n(@cd(t?^eQCVof%LN@ zN1ovLLZ0a8DNl0rk|#TQ%fC3jl&3iQ$Wt9($qInr$T3u%tr zQ<^LH!dGu;p8TaWU+yCR(n@)Vv`QW-t(J#Lzstj=HS)L8TKPL^ojgKXFMls>kVi@z0hO24`$Ni$uOrCF|Dq}i@1(j3=R zX|8LUG|x3%n(vw+EpYuREp*M4@?5i|MXuS>Z>~AgV%J=0i)Ws+)iYn(=2;+Z_bill zc=Dv3o<-6w&u`Lh&thqhXNk1evsBvWStjlGESC;=R!9duE2Tr8RnlS4YUzmQcj>5S zjdaYjRyyukC;jPJFP-pgkpA*)lumm7kWP6vNvA!Vr8Ax_(pk?|>6~Yqbl$UFy5QL% zUG(gfE_rrImp!|sE1o^lRnK1OZ_hsInrFW>x55EwOUyy(cj=I{23PJo@)2pU^Qbh$ zc}yDWJT7gG`BT~!b3)o4^Ov;Wby7OuIwc)+ot6%{&Paz{XQjTC&fyEIPQD|A9Gzg5OYI17;{s)@3|#C@Z6SiymzEw zs0D^g_oQ!85qu{-kOtXv6K+f?F#N$DDJQ$CMqJ9{LIKvU=TX_g-iXY?=@@P~Rw>%@|+n!N4 zHwKS?#N)9z{}UdM!{hPts473p(_WY$Pk&*ee8)3MzU!GR-}C$;k8w|te{@fkH%Qau zjnZ`a4{3(Hq{6R=I1|;%EP0eXTOMwkBd@Z}mDgg{uEVTdk6DW~5A8g8kav+h*!!D2 z#JgC&S!0QOtHx6Kc8z87bIpG z)%VNaxDLquT?gg;)eoVMhvfs+kAVLu_>aj4s~?xY^!_RL@t%+mRsTyqT>Yecr1~j& zsQ0uy%zH*YTK%lt%X?1l?L99atA0T~Uj3px+)_Yn0v-%Yu#pQ z%DoPXJ- zI)AiH!@23s`}P_5`qlZ9ZKiXaZI*MqZ8rSoIL}m{>%1V%bN+0b@0?&;;5=4op>v`w z&v~}`BEReZSn{&EtyK{zZhx2%) zoz9WAUCu+E-N@G-=Um%f=dZSX&OY*f=OX!lbEfT}v!{H>In#dFxlumi+#w%zu9S~C zx5&qxS8RVe_jyh@7rXv)-nE@{&bFO$&as_FoHNeLp0mzto^y!zjOD4E3r|}t#bVj* z=a;hDE_g4>`rrZHk62>cWwz@6Qk5!$EEfDpJa*=#w%sz@bbmh+Z&&cf8fUDZv4_IH zm)c}?l-spe&!Jw1&F9Qi_@~;m@2H-O#4*y^`8mM=PgEP+c4Ggc@D*w8pgs;fs5Y4& zs;Ahyyhv-KzXD%pk5!xOkJQt68w;DsP1Pp>2h|4e<=DSM_=>c8imFcn4vgWk%2jLC ztl_fpe^qP7#MG))qoyl{pHd%Gty1OXmtVHoVyf1xu9?66n8otofz{Hs&!;~&Z|S-} zr^tkTQ&Xpn+CASetlCjZJhLlO&SH6ijX=OZZb!*yFZD&NTDAZqJmhvX0PNMSCoPucb^|*a z1orBMbo}|PM?^p#j|PI-RV{3>lzUxoha@X(zGijI?B;gh&3$^eF73Ou>SRmAnQYth zAG%(SZjqYRrdyZnF73M8w72=TrrmqA&Fa#kT9v9XEfTtP>eQoiR`-uuypqr&qf3{L z*)39=;$hVqFIB7cQni?>RjagUoz=NTa+mDxuen}UZwR!h_EOu99UZo(K&Ev6sB321 ztd16?-M_!N&_%n8(4tMZkGgj6(xO#%=c+AQwQQf+xqGLV+E|pfU9v4o^DK+eXt!>_Y$2+h(=NKe^nC_EF}`l-FdQx z6`vtkEY&c5pD3HN;62MDn9OBfDT=+SOeMBsmC1Psf2RfQ3+nMj?Hpzu&Xt_%`q#bi zk6KpeHXVDk#r+@}#q3t?GPAq4YV+<(9W2GI3kJS7^u=!$wmVk(-n4(7x7R4?HLsw} z6E%F5V-uq4R_?x`TGM}0&V9EbqU7efraRC&tBV@@!oIWvrEAz4jVrtA6U#44J}Wsl z)^zNS9a?2~P@`Awef<5=Ef&VrnK^IA&;>tDE;+}1blkvJW7oH3UjMX3`xheLZ(sO- zXEJw`tnuHIPK(h$x>=oZ8?bY$j@lyanAKVp`stN5QAPXQnc9dAhTH{gw%_Evr;XNJ~$Pk4sL7jkWZA*b-&6j&)jc{$aP$EfJO$+%CRh ztT)w@=812V9$Q~dNUTz$t=d#8uxU;~pJ72CP|&w{(CQ6Rk{cwar+8x1%AuQj{xAb|^8pJnDii=Hc)h&c&t9;8wUSFf6)CTFX zaa}`Mw$8UqNK5rJY=np(g^1WD-!8?In3U{INQrIGBUFFd=36$3Pl}6AYS<8#9Ye&- z%(qNQY>?#;3;l8pg+YVtsA8hp_CB zZ`mNdfiE#FB`!9t%ljcLv+^xd8^*<_`4W<1J(+DnSoY_ZH4;<24O8PA#>dvLnUtDA zwhyr>QizQ^=G_2p9G@QROG@#jG)Qfz&b#dTHQBtwv{TzEcu?Ix5%~ic)UScF4ar)a zquC@>o(ZwPpUi{?a-sCt#H6@{xcCH5Ync>D!dp?C~#0OsiP>(P0g9A3vLFVH*Q8$?VpuW7fx+Z5d3 zJsByf-j;1TWVU&i2l^9%2CzU!@gYP`awZhUIyJdB5&!ZGa zUIw!$pX|cn9Ym?kV9r;uHczoeHn2Yah;b}@ob%8ltWWGCo?&W`J$QB)L5d@YwFKNt z7`V4;`wn+MgPsg$?l11ep+p)Et1TUhM->Lejyl%cb*yjKwIV&WVy(&XR(C^d-G5(ncBOdS8D0Hg2qLb`HHZA9+!8d{l3_OHGV;>F+Sk4Q@*0)B-S~KwHY16I!(<26? zM+{7lhH)zDJ{CSiD{R@}j!$74?P0B+$cj@hsx7m-xAX^2;BJfjR)54p&HGx*gt$hH;^Pt;w&Xty zYRO@L5*q)aj>U4cM#(L;UyRkWP!xMD=NAMT1-Pib0)M-#&TU(w7VE=4Z-m+NF#AF6 z!;c%ThUQw-6d`z4c1xD7%(gtKQHcCAOX|0R zVRnbCcKNfq5{xFO@)JDjtkz^&X2iwgH=Xe55Mepulk0bC^|K!Ki_4qK$TP8M3OMn2Ss<7pHX^cIWgyALCPNVfs!|VKcqZQ%TTaZ<4nOrdp@2 z>ZHI5_0QMU+VH=U(liAl!Ik(%vx25aMgqG&pg;6VgeAjgX{nA-r!M&ZpNH{n5^uAi zh(_c`ioBH`(K0>a?evIN=@G5dBif`#v`vr5Opj=n9??EMqCL`Kqx(av`&Bo}yV36}vF|Bc4P8@|ewaVb5T@ZT_C& zzidr_{33M(-wm-0=@&3qa@Zf$R=e6kXBCi;I+|5fW1+*Hd$5X6>n+=Zm#A_+mw(ql zo&$!4{b6fWsTaSHgnIQLcAu6(dmA6bSbvOC`By-`UgHUJlaL)D%L75VN~J8sWc;9% zYyVX7`c;b7&Y$=g_D5*RSmFZflg?e*vQ;0dY*?#G?T-uU4npk$2>wOwsAEZJ@_KrP zuVp9v&i^j#yPC93;BRQHgL_nKA>~4ESfQ|9m6*nJ&Q}`yJ~aF*Y*`twd&MoYZvydOPV^nSZ+`wzlU{%TP3Wj!)k)_UCkNAAzw$$GW;t%a2+@FXYrD5x$+@n ze}o$UqHgmv2pznQBy3_ysHJUE*`0&7se3Tk%nSyIUFnhCfzM1<3T|OG2ZecoZ_n$N zm5C1v{C)lwc3YWUh7e1Alf{j2GuyI_8MzG>HOfM6d=7NmVO-d%T%NW4mrrW$^S4^$ zzFb2qP9rRbSkac%In1JMI=_Bu7n{I3Yc{*@eCU%ifg&@HQb zCQra)aNesX;8m|$2)z>5s2Qta{)Z&vUt!B{S`X9l_DZcp^q;PU?zG=G97>h0k5#z*2Zrojnj@^Of+ zaVrUd{$f@`1*;yNwRbrFh09jkNwxP&v@WH@)znX?%ot?Gf8p~FL%_1;MPzOfM%EWo-S~qj0jc; zNNu*?{kMR6q-8QH5_&h)-ET0RUk~!{AF*$BSCjG}6+IQ+>hKBK!yh1(2Y_t=g8ybk za=e9AWLim#@z=~ZkoxOvq5Ui@w6;C+E2BC9xxq}f3*%3MbD+fqUB%=-^$og9|koZ(6fd+{exEdh#a(zNY}2zYpKbALakT4-?>1oc!nh^Z34o zBdTE=yvV+a;Hx~oO5>|GeX(=33*qx2dGlk9NMu%dv@r+4p}%9vcNeq3ZMQU7D7Zu;o}`VM4-qh ze13z62p1WJ4`}cZLD|`l@DQQl)`Pi0fIaMphme77kM?*7vB)TV4uXe}jEuqu9e4=g z$S8c0frpTfjKW71c-S8gAF|=22s|Eu$K{>bHfOcAHr8P`KR92igwt)E*{~W2t77<= zz{W~Dn^wOTD)vTB4jYdDZ~uJdbE3-FEIwP#eT%Pp(Kk!tjpMVAL^^Y3GNi{>l(ZD{ zMND=1tU2G|c~ktau-KKTEOIsSmB8c1t|fiqy5q(KCSKkmS8lId+l#rqdfF__*s)O@ zd(pkbWyy%hutuZxl}yU8WZw&YDSl(hR-`FfUr5MXvS8nf-$VBhKEE7030>LO7Bf!zU zfe6r=BiQUp)W+d$zx;EM7sa-a7+P~;JJ8*2)ZNyuB|Qs8T5{~Hx7(2KQEc4Ne~kM# zwnh!r@!n}xaW52ilj0A7in|RI_nB2Z0>wiv*pap!w%^5g&B5~QjXSK z%1;63FPHKs;e77LsmO5t0>tGa5FVhWeSj_R&w{Z|6Bb%?SeJoy(WRUxtO2wML^G<3 zI;!(JDs5Z1LO5v6;oJnyb(eCDaE1orT-V`TGr+k;IB3n`+y~BGV)@=bVlS}V+|@}7 z)8+vYpfyJj6_cn$#ArLiw*o;#Oz=__2p)>jc51Zd2#SE)n;(d>5!h~xXfKttvP~* zAV`T(l42Auadh@`BruK?aa);Z%S*zUwQQqVu5L8TZF$~;SsM{6T63(;z}hrMX-uF$ z0hE=3ISm+SQ(y_jVP0e1d;#=GRxYxm`xU}M8y40Gf92i*SnY^OsNCBDU=yq0f-3hc zQbub|xeJs##VGHRxLCP&;``dWIu0tvQ??z{w^Sv2xGG;B01d2E)ZG z_bn;`j_&t~0IfNKk7JA~_k6KWNDQqxvCq-nPpP{?<^C!1y@ic?Q01OuR@!w3tlIjkRmH8MsSL0CfNK2k?DLPw=t&_@#vT5~u*17}=}GL~?J%6*&;XRHCv z1j0dU4rdB*CKHQTxlh(f3)5yQ5ui0kFcSnbh(N5|XB12@iwMw~BUlK6`7z2|f)FbA z`Pdw{vdxiK?sIiiTBVa`7Gotamd7YdW0b{2B2@0n`GQ^w0&y)Z)-h?bb`_-vt+^Ea z0k#b>%DNb34Y7%p`vx7-I*z+W2PaIVO~i=S9OEu9?ub#g5ui}H@6hpW(@|+D+f6uV z&EXsZ&Vd+ZAK?g<`vD!!J_DS?goD-`&Y!?JMl3?*eoUvV&F2$l6;DI)Bq<7&`$;H< zD!tB7U(uTD>jfyEBW1C2Kc|z%T+A;&E)oG+a|Aa)@K22LcZ_m{IK;~RA8}hj<^DI$ zY-1Y@uiUQ`%zBep(VAnmx)YTLG0Hsx6)X1#!Np7f(^k%hk$I%_(*6ydE4GZf> zf93upu%2*-xaa(o_9D7liMlJ) z?3Iw|{cOa8YIen}VpS+sCPkrUuWX=L&8(seiZ8pB8YC*#>@V}VRYRwb&r$HXk2{8v zjn-VUV*ygnt<)h9v0ASO`Ch_(_BuvDaRh|c98d~?lH7`yfP^|dNyp>W^I%a{`b|$pjxRq8UFVyC3un8Wp;g$vNr?=9PXjM!*vjANH(8;a5>sGReL8!_* z@g@5%2*fp$rDM`c%&wFiwC0lY5!gO(D?QvwHnE9S`3E|r9vnAY52sC=kBJVgIl7*p z%W*585t>ks=jg~j)AOhcx) zAD~m#X7XUOio>BeloW+}d?*w{6;$6+U(uTD>qsb%AZ4*0AEA@RRX)G87)1nV%@O0N*sXGKJv88hl!Cv6nYR zH%Cwk?o(@U9NoVX7TW)c<;C~Cyrq86OP|__O7Ges>hIpQb9)^LQGb6`TdVxhhOgQm zs$bVu`jW6%dw*TqUwik}GibZl0D?dpKEzN!3?>4x?jBq_xA)QDy8D<~cjM?DM(Sw8 zS07Q^sOHWW`ksW)hA%W4-5f>T6zc6!$nLQa_4XJuYU7|bmehn=d#r)lcr$9hKy6ZO zWdaF`b@n7ak0$7}sm`842}T=!f@cBZ*V@W-f)H!$Um-2l3)78YW)lqB@L?7KW?^k* zKEVj}^+FxXd_9YLIsT1M(1wq)5-7`SD@zGQsI8alP?j2?tRfV&;iIer${OMj>*_Un zS#671Pr7Ks*WC==KS)=sssAw2-9ox(!`Iyn-JP|S?IbPK(>t-b9jAJFyN*JuLiU&u zKML`~wUvXlmHnhI)Y6CfvOEZNac%6^@o2U5F-i*B@RM>DT&HU*Cu=Jwh)b-aPwQ|_ za?}%gFm0NgBQmt%ll={{E47tNgeBC_S9DaD^epP4y+$Z#!$-LTlv}lx8-ya%&$o0a zHw;kj5(?VzQLJ@v$C5aN+WCP_RhzXDbxf!|47I2_S|KFV%~5qi7ea;VXoV2k@cUR8 zs*jSYSTjGWlSR#(Um6r4b+qBDKMD0G>L?}ZD8-0Dte2mtLt6#vL_IiOstj50Y)g$^2!29EM`zEA608*9NjiTLi=BlHrK`Xh~Kr)_lTFP zm#CDj7ouJ+TQ9fQ$q@DObM>@og4Ud}3}r_>#YW;{&FrY>ubFK+4$Pa=YVC@n+etWR z&EZr6&hx|~R?pAZ%k6zJxO%>%65!~5fe6r=BdA=@sDjQHt3qOE&56}OcdJo%g(|ul z@_i{p63V#I)zRq-Gc1l$j@DetlYx_1 zPw^0rSXU zT5|-QK=5uoC5s@0>ib=6j#t^{$iLGhOGl+uGo8(1d;p9d^_1*-%6mj2)Zsn&g3bnk zxR&12F=?~*LrM`^b1C`)Y@gRtKCP#GLTq9!{<#k6Q;z$I4o;XzJ&6&mImUiq%&n*N zAwZ!j&(-nu(NSqB`}U{HAgTF1XJoM zlj|uHi9@W^r-<7M>h;MubDeE8{5wr17R)-GSkaneoe$Qz^_1BJDpu}ugNwtw*}C}x z=!lt8`A*M~S+7BNNVn}6F zB}^wk;)f4!`hWPatXV}n6wAjcR>_asrg&;*|O%Zi&;@#!pN<4&tYAGXjUa`glAZ3$@oMJ6k6J(XKZhvj7bM zkQ}EZ62L=&0LcLWi3R`-%>pzAfGDE5p~a!6FXWc7sV z61rsN=m;=Lm#8Vg(fuW*0Ij(cd;_3-=75F)Xh@tg zh=9aP){p?8K?MU1Cm^)ufJOpn1knhWtPwf@?UFT$l+l_~{t?QfNm;mLjTV*pt~HjF z(VA192<4ySlyM|3T(W+Kxc`zh4v&|ybrN*Rnq(GWIsm4|DZdbaaLJk)0Pu?ezznkh za{(|rPMJvn!X;~V0KiNGfO%#C@&K@a)P+md0w@OTO?>bd(cq&sH~7n;yfjW(Oya^N zYbn2EEfz8O7P-Q#{5r_5iBndQyl}}{gA2n-c46R`tW^dW>;F5(9QH12v;UHH8W<j**a|Lh`f zXoO4FV>$rsl2w$H(V9y|2`CpMW#N)lOjPE(R!LGuYfiZgl%I-MN|Cs5$$ARn{!3OV zJl@OJNzf(hX|n+30Z=YpDN6vtC97NjKv@F-n^}Mg0FdJq2LT9|EI9zcVE|CkEWir@ zh$eO6k`)cbfO*dc|3w;nwB`oC8kDQVD=(3_aLK9??|+x|l8C`CS=G(TyCLt2S89^H zaLIDT zHQ}TCGX`qs&8S_4+U0oVA_7q_sm`#6En$d=z=G#EI8LwO?6!9bbn*cb< zQawPup^f{w*9%6vLr7@DM~X~HRICZg140r$uD2!x6FtxoX;=EF1g*wE8$L>5pgfwO z6iUzv9^s?gAzcEi zzG8y^65xcoxMn0Bk2WnTQEJeJpPK66s+yowPEZu$57+wQ57ASFmY-SAKLKw z>VVIkptuN5_( zNhs*@+Un*9fKRd#j~(4vgoHL6r03NN`!gW@FG2Z`ki;88{{zxBmL+~e=tG>j!OjHU z5W1ySojAHbCnU7tBYg>^Uc@8Z4C;k^+=6)U&7eMJ)V_gQzXTUlm!JrKvW*lI~5{Yp0XRJ;piCiQ;ik_t2>WmPOu^$X9GHbcH+_CJBR&t}a}tzUBre?WnG+yB%Rqd-8S%vs zUzDIMByr(p&!PbFg$CkF%!sdm_%c!!ZuBgJTEM=;2YV$AHrnt9dmU8QBq*y%Sh&fv zCc%G`XSImHZ}O}+BfS;Un-i3cBrV+F*^G_8H|AFU4W5k#2;2TU!kGl0^+WaYa}x;H zNng0Za~*15vAG>|gXb3I9PNM2dA{lcsNPFZ?vSu}gXbPEneXTrz|+^kzQ+tlx5cBq z=|meo%0r$+CDNn4;}mc3M0#?24`d?{c!OtT=LWM~PZTLdP z(9NRMP2mPlQBQ8KL2R6ZZtxU0qgD!PB}q-V!Bf&e?MX9gWuf-8M=4E$;tigsJ^uHK zrFGiEYDozQiC@9)U*IsbC2?xM|p*~#2Y-#bvUna)K_$1 z!o+!#_|S&WmkGW$9;Fq*2{(A!=-686h_qC-BNVjZqjUnwyB;NrP=p&i@9I#p3{W}~ z3fk~dvVrm*aR@hf-qWdSbGN%0wGW~8KB);ec;1IvsFLX;>Lc3l`}iqTKOt4|2G1ut zSJOhIZy1f3n`2pa8ti)qS_Ygut8xB&=3jcTg%mvnLViKzC*#H>HN`jy& zdmbsHHK+U=l=D2w0umQ1?L5ABEzog*=?Ase#nHW(aL}5=Spl47#3EMP%P=?-*?bAC zwkN3sIJ#F70a|keYYZ#ye6h78hSr?eMs#;Qbyujm*CXGP*tiE(-G7)>+zQ3bq$pJ0 zn++7VnN{2a#a$j{2Z@T+_bxuecIfnl8Mc>Fj@Detj{xV8M>#+^Vg-H(5I?ZA^9uYx z!B|HL3#~b<)4)3EQBDw+P=%k=QJv6HX&3G@goD-`&Sl_S^eE>EN2tUv>Tu2*;9Mab zwB~TG1LqpCh}HNtowP7*ZV&-la|CxmaGMCkiu`uL1owyltvP}yFaCCySFw1tdl5oa z9^uXHJ%w$KyehYNLvJ7tc}-$G4vZpRJcr9&#kaZBppgo*StF`_lcXa{3?uTqWxg$ljAj<1}K zN=uo8aL}5=i3UzZui_*ep-Qi)!*LqmR3aR-=5Q(lMML4veT{)~Em9UM_F6h=%*Fij!%YNe%@HJkAkM4Q_bPRXL#*24#BBvt zdwral!8RIRwbw0})kCak&9SC}wV_u@AyBb$ZwM@*ILu4Y%@;sVR4aEJ-D!k{HY}`p zR{DKLoq^Snn1sr`BLHTxQX;5w??TFG%_;YQa<*4_kHp2wJ)7@q@98+eG)JwQadf{= zIB3n`d;*-0h()a2Kf>TFW^*R6a$lkn;OPDz5ui0kkmEJFSDr8S1&N_GC-x<}+l#s@ zRPMcy?4}1Y+er zw_t(=M1a;D!BP+`_9}}ALa5vqV{=^2Hb-8$FVazImCiD=80&zs#;dIMDl3UZsNC1^ z1-%*s;#yj%W71~rdP)&mb1B*mwyj=evsd|p*u=_xs}5;1$NfVGCrqRr#E8}$;{h=4 z^D27?P^jGZ>G<~OsI-(FBpkHnaQ+0&F|TrjaD>YJm=5QN0nQ1+L2C}@3~){ni%_|r z(kW~6`K(#Ri%>jIibCan9*Ut#uS?WdwC4KyH%KCz-T$66>cQF#d8L_yV=Sh+ux7*rhQ zMJ5IpP=H>nR_-{uA4$}17N89aYk|LVe+F1(h)Jm2%K%_4D^H(yL4F|_8ys-nA)5-RsbI;sXbD(!;qBOJ8ma9#mU2EI$5aD>V|Lxpql z&2c;19C_v5PDiCxI`5jr=njl-iAvW*r8AKTm3ue7pu2)VTuYsGOxmpNK`BCOE=8Y# z?SF~N$BD{^#3okm|I;CT%yB=|!3h)Tb7Dkmj`1rneu?`v1SnMQU+VaJ>8P}nyJ<#P0C{BK3XS@xtL#mj3olJ<_LZP!6f|9LZULBIK;|*lDMs)a-V=R zyV*v=EBEmQvrZvawB}gnfOQuBI1hn}mHVvV;xO-5-FyM`X0>w1(LI;2(1wMT=daw? z0Bbcd36=Y50PJI>L{R0vmXy(&Q{DvSjrf)g5*I7?jeK8Quj2sIezk7K(Y={)(3->9 z0i12bB3AC(FgQoqoC&PlkEsMWx_1%*T5|+@4J-G2v3(?l)|}WOboT&tSE$?%Am7K> zxCd44hs`P;hvHFE6e{?i=7lCTVvz(3-<}1UL^TY2PLyR_+f2MqDVuw0V>W(3&H790Wy( zK&;%06iiTz2+*1%cnSoil9ZAJAyn?Al5%^WV4EYa+)L`Hv`VM6SqvL6o=Z}mO;VmA z5}|T`F3Eqh=ULq}c}B;i&00I92(7skRRY`dNlJwzMJ6_}a(`ZjRDt8lIyhk>y+Dj; z%`sL7W7Q<3G64#edsQ7@WgV54vKoYg)*Mc4;KU>;wFpP3++%b&wG43T5Dr>%IB~$K zPb@;^USFrI&F6TtiiuG4kfKnzd!QJq^h%<>qBYmohEPr+WwCNk(Me-2=9eFhhyblQ zf@UCSnxr&NQhdZAR_;y3Z3UHkW1Kn7HX2^J`wC`#g;>#=V{Hl6HQyvQC!AZ(M z5*I7?!F*pEsN(?B1+{L*(LIcC(3->f9ys3-i&(jThr#J91y%0-B=$3{IJ!p?0a|ke zW0I&^(cN>;7yFUK(3%q)kM90N-4!bLpOEi<=xuQ2{h$ zae9(6l|;qLeLA0EQ+4{n44X+QM{6$S3xG2(Ntr`9V&y&$5Eq2XeNMqx3keIYIjrTt zTAHLRCM=8tfSH{=qm^ZtvQ@^z*&=|tR@_xa$lpvS#5x`o^a5b!`Td+KZr%F z-2c!?3)5x`5ui0kuoDE^i9oE}w--#XiwMw~BRB|x{YlDRf)FbA{n#A)v(1rL?t67q zTBUQyEXGM-oJdlRCn-mXM5x?P@CAJw1mapcs$^9+`HHTwO#vj8?QtlCs zP`N+Q;oLL8iAdJoqN6p3QwTT@C2Mcdh06V*1R_tH2sm~Aw? za(}X5)@O+otvOaFSfymePM~7tE&)p@4)g4~`2y&^tXyPAcLl;i8x~gS2>L$vF~ItP zn1ssx2LKFX6G$GxkA6DCq*3VnQ(Vv?~i7#~eh z3Z-b}sZhB;s^cq!GvakXOIZ=ZL2E8$PXMPxic*Ylgvz~y4yTv_PAS4cYYyjW;FKm7 zp>i*+Q`YA5GiDW^gW|KKC{*sxLNQe7Ri65a)?8mDDBDR{tlaH7Y0Sm^@lnZ@Nv)T0bQdQSwBe&X36v*@L#)=HNW-6@Wb-7j zTA!h+tLHUDmy z$^|3UASATmBh>+tJ56yBl2Dbqbwn;5k#@1JODJf=NAUn9K23=w6rm!I*P+B3pm+%d zZTKh+fRaocVl|$ulNF{(LsCZ@zIr;;(@0&c#M25^Z%pcF!&iR|>aV0J83Z6y;jduR zo5eOgUWI4qh_tHZbu$R9f$(;k@>ZJCf+&Ov{B6Ey--5chW?JZYv>DolQiC@9)N};b zJ84RXG^HJJiPiTzI-Cw1wVe)3m^ht?4{i8-J;0Zpro2aRLgk&UV|!0Wq^0V8LO~lo z%BMj2Bu)8#J z$<&wnh&KE__J``%q$*b0U+ZKs@AAus0i=#LeD&|3K0Hksnx+gU2C>Q>E^ZsBvWMc# zJhqYWDtmCjoFj-6ZTOr&f%C^SWi&yG750z81zp}~-TVOXbhX09(LIik(1wHbf?8qE z2hv>P5i0Dt5MRj3fuIU|0jZ)5Uv&voe@j#HNLZ|}f8%>ro{j-Li_{tyNB2@fK^s2G zDxj<&4za>sfdN_0=15?Ly+T#T(Y>0~(T1-+moj3B0;gj-ot0pE}gb8oAy(h(T1PqV?a5Q zrW_&^vBEwAfJH3Tyuvlgn~AFl&e6w zoTgkP6rsYttV6kIfbut?pba18CQz;uhge}>*U1XgVMTX`LkmMWQ0(1wrl0#KrTN<~5uD(q+-N<{;d7YPMz_$XC@Qkgh} z3cIpSRjaV8nNfQgYBfkrsIY55EmX-=i~5K*{65x(Y7D806?TkH7V|E@e5ga}Xv0_c zLOsE!#QBu^#2{AK3F5Ya3Of#G*0GI*SJ?Fn=1e3`wBd95z?te(8WN;fVW$E~DCqJU z>gERnRx4~A-RXpc_P-(>DDAU8>9dwXeGwV3uryesp0`-4^eoZ!MVz%TkmluMuK#=M7ygsAqLM@-K0}PA-f122Su5r3 z0peE4b%Q111$xFPS;nsw$j+k5jzKb!k>n0Kp z51+NNIy!jjvsS5a%=fPaBWb{^(gd&;L#DOCmtD76xN2%-^tT<$yHaAseR7JrdqvdYdV_x0duO9 zI;Zk`-ZqMLDyL&1i^bouSoc{LIxaebIma6~v!TS=PSA`!(UHv98(>^KNXhDtpQyPc zMMp80h5^Qp=#3j`#;MT{Gvl-XW47;IE24FqBKtJs^yos& zxN(57w(bPuCYo{6jEA)cbt|0n)j%zacjMpEp0O|>!wWXg_-PYXz zh(=hSwUsuJHNNt$#~6ESm0f+e z!oSfLXWf2R&7JzNBfr2FQe(QWBI%cdFR(b7e=U8~;ku$-y*mBdG~sGf^53TkSDO+@ z6Fhv@&MGRN`m9~Tx!QCMO3Hix0lCzFLVg0s@bFo?smOThvu2yVuym)3L4ntdrvUmd zt{G2)5T-tB50wy4eb)DBt8O`rRh-kbN4KJVdlZ=O>A?dUJFKB>1&3MR-`4^2TmJ#K%ewKHM zU6);D(=8R+*Ij~#mYh8$EEer_-bMCeRI@&DB^jFq54ux_nz1sfQ4IWi*3Z=!^DA2Q zWKItLqEJSp`*9#)RsLV*h3i=@KRG?&#nR`q=JZknMB|lc76iKoPWHx0ZQ*H4t~{5; zi(lf!XwA6~9*S6a{VNtRBEuSux;vbA0Xh8;0CD=FVOxy)94kDs0lw!UUA+Z^lV9Ui zyh+fKd4MIeTsnJCfRwQ}2EBR}v1r-T(95g+`o@pOo|a6?uw>*sz&~I4oTxH3i_eyG z-{PxY^v#misHkTjiFD@7guUhQ6(udjd=cyoO3pw$M>7D8ipHJ;?J1y1>584x4btp} zps7$H-TyvCD}Bq*#VKcK{;S#ry2AM?OLBWkmYk#Lk2+5+#VzPYPbp7A=T_U$qeD_7 zzyGj&fA&u0nBNNTRmQ6CRmQUSDmlZMS!4q(QzsA^L~52Axn7|8@GVU8?2x$a&{Ah} zDfH5J%)5Dt=6y=@&M)PwV6Lk3mGcd-Q6NZMbTo>2Nlp9+Lj@qYy4Uo~B+%*TH`&Q~bWUXRw6wP|7)=bly>1Zm% zrnBKIRSk2I&8ZpeTpT7gTW5GzeA~g!vgMLjBVZbpcQsbKF-tSA;BH76IggAq()`>_ zFg%*s9L8WoZ=isw%X^FQh$Pil?Xw5gK&MSVx)7`9(rF*~&+M75w4nZ$y zZv{iVpuM3C@q+f|l)b>xW{n66sJ%<}zpTDHR!u6j2p&ipI%MRsmXXb3M*gptDlJ#= z54coq5o2imW}y6HxFg>pe<35UJ8?c*8|hulMBHB9RCB)@FI1@8P#g7#lK+Re^8k;c z`u_fG5{eW-KtT}M-5E;MkuJ$nlWdwmHbSr<3P_PCO#;@R8VFzjX(Eash#*A}lunQi zQbdZNA|O&kdI#y{{oa`~H+y$x^61Y0d0u@oXLt6T^Znd9XJ?m$4`PZ zbfml9mFif@H+IFhH148Uy z`b$UHOMQY~s+JY}q;K$(e!)*(4}S7S&=chTn8OjCCxqs-@Mn-X-<~##^h+jbsDFA|HEFRKRv^|dTF~= zzOyTm-&nG`wHY%|%XF5(=zZzZ0HgKu=WrfF@LEv&eD6c>T@>K@N&Q}BG*0Gg0`NU8 z?fFom0$5^|*uh8=%wK?aEpN;qa3BIBa{)41Kj4%PXwka*MV!uv#5|y+TD8Rv=8mWp zsqK-+Bk^t~$lFzrcW1nh)@hknL_w~_1lLGA*9c>7Tn0I&Y*6|ryBNledzASgh3q_e z_J7!@WbxUg#O9*k`E!>y<^yyg&Y@?o7(I(qczTs_^$q4KY^P@8Dq`o!xvsJ7{erU> zwTm%jzsJs#XTQ#}zaE^um|cu1dvQBYp8W>0ql0e2STB2)^Ikb-2%q9CC8`R`+4wL0 zaO+IWSMp!xv+>jOX?yQ&)?04`_m&;2wsM3SXp_BGB=4=e1$I*@IcBKPP4`+i3pX|4 zr{PL2;ARJJrWQM{i#fd++@}1*yy%KxPWpbX?}QlDNSurAuiu%yH}7q>aw77wneoO9 z0O_0ho~yl3(4Hm#7jFy(azi~Th)BC{;sZ*w{#qfthMEoC0LQ}YNn|vp1fCSd6PRKw zIGU=d!t9FPn{ihgp8nVX)FpUFN)On5#5TDSJ`d}|9JH!OZ)q8xP~G$jI`KGrV}9J-f-M%w6EjR}NpUnmJE6Z- z?TJ19Lv(=tVo7?D-pAs_XuODq--{Qbac#uIQmhY}HPzpF7e^mxYmt?})kZRLyweUA zXJv6|lO|5yhm%@?1C^ixC(^Ydri$cpm2|mW%VMOgSEbxYDKe@k=45tJ+;%7#Q8?1I zp1Z7xkup2KDGhePCkj4&U9MGjQ9tsijWJTEUOjqu?9)ZcjWV)VG_r3eKTYZvJdre- zpF{FiGW_>&m*4DM4sz-J02Xlf*~J{^F@MKMz5DhF>WJQj!Q}eOF7g78JZl|!+Ai`s zkGx_XdD$-VE|0ur=Ta!v7}$tdabS5@mV}Gm+r?s~u6??6>DsSnr=T&ahdy_?irR&j z=L+RwP4l8mtYt5jwoB&W$sV?je8{X((Jt8|JXv+?WL51V>+r~$){&}RWDFwp&a7|e z(wHarg}Csw7SCOp+PSpgE~y2KT5>EFUGKL-Ml@L)(L}q{PxI8RS-91jb-A7jiRRNO zlSg+AacOBR-rn4$hj}<(wTpV4M`c-Ir5V}ZAwO*^$;K0XJl+k-8!-F_ahCyhE+2B~ zApjP(k`L@+KISo_L+6lR>;I8vY&j{@wT3UW3tz_-R-5O=O6wLaw@bE_C;QPla+6tOgI%)Uc(PsA$$qwr{F6uS zvyR+j7kLDcdS@Q8b2-729}RKgYwav|Ic4W^jl29)z^Gla+)AF(M)ZPR>Ik24`MGPi zW?in^A<=wgKER{P`oxP@hOu}nbC-%f)77VfU6jnD+&+sP?l~iS4f4~r5*1JM@pvR8 zZ(GB^4tJ?(=Mu}Mp8&A1mDIC~iQ_R%d?DA|9>tF3;P!bcKuF+nsz?Rmt<(#Or7m-kU4*Fwcuuty`37m+Wnx><#P4erAm< zyJR^$S+;eu_v|8v@yJ~3$ia4zqY|CaCmnj8|+GMuq zOjSucZA2&8rT&(u{>E<2x?HnDqWQ}FprNr54QwcGCGCyHJA%6mYiQa^hS)`Y%%es( zwAe~I7}-A~KW!_SgeUrVObE%_(eR(jT_)SP%;M5B04!`J)9hmA^O$cNT5ctC>>|JC zkxQ*37u!Xy|C~Um!IrhcEd&Q?Oz&NZ6z;h6K|(o_#v+Fr+Hrd zVcnv=cF9ihWXG)|kD4`(*d@EnlU=Y*cFr#H7LUAc9eLF*GNO^unRo46ioiv`nGn^; zX04UrF8A2EJiuMbHnJbJ`x;qoC7rYpEoGP5%~Mxq;h}GE*qU{@DuqPzmHBWJqj{B@ zh|TM2EZ(Zz#oNTRmALJq9_3Lrnpj}zEdjd$#l4dcmjt&1>H zxOjQ?DsfWhAdio=+?DO(9^rA-#kg!OuBu&J9UfQHDo(YFi{Wwg?OYmj7oVMrA1-=_ z#KlRy`t=QJuf82M4T+p;^iy*lnPMH8WEa_rM+U4TTiQiF!yA+l;=+gTMV|b5bZ2*I za0K0N_qtrq*#&jwL7foPt7G@>L33)3HhvxKV&C9QeM4vCd@Ztf=xkhMbm4nk_MMRI zOAMDmJo^A~cC65HXWPXM=W#>DxNo(%T)VijJnkc_xKVa-6L{P>JD17aWul$S47ljC z@hj_@F(o8&mC;XgdE{*C$gk}p7xBpX){)=YMK0qFS`y;Ihi?r}z7pLj&c@|-L7REd z1_Xu7#dojxjF*o*bJhwK01HL`S-Y5%l8_kx>c83UDP@M&7lHEWso1v5qW~APx!d zgfcv`l$}cj?sC7KiyJO_Z&yyRD*8`q4Xp7o?x06Rjpej+a;^VlhwA4tZCLz z?UFU-$$ZwyV(cOld1SnGWHYkr;PDiyLJZH<8DUw~8BQ7dMs1O}2BH$z7(| zxqJ&3y+gi9u)MI%3W;>#>)2XXF6NO7tRv^yMXunH%d8`p+C{GA4O$iA!iR4&Prd=& zDPGvt+Xem1gSH_k|(ETrYj*6wusSHlHb_5Z<{xln|4u!c~qp|Vv&?G zvKJ>mZB$C*i9Vhs{o%l5^kt&aT z#5%HuU1WV8S;soEmR)2+9vNfj631Pd*tw*_Mepq-ztx4Utk!V9U3hD*kdAH+`9@fp zb&FcqC3}G0kZ8U#7xC!%Aubh-#k-ul z;HXrktcZMQR~Pfc99o&LevfhhD?UFsnlRaP^SC?BRsOY zb!1h$$XbZhr><(}QlBTU6XL?xnvc6QuygTqm$(8(t!bjwR`R$uqK)lRr}5OyS$JrT z%+{>Sl^PPw=R+?Z-95ymHUhQv{W^EaG7sl#c2WQ1QEypcH8QgICqGSUFrMh+krR@) zvEe_AyX4xre8ivDE_!b-x15yCw1zLU3*XEYHkjwddg~UgwM({(C);5ixy`KclU=eu zc(Og#$#&aC9^sLPtRoNDMV>^Y-kHbjT+Z?2r$b!$TD#0$F4(!;;Vw4|7`5w`TZvyA z(W`c;izXQtheAmfTM1jUE>~odcxmA)vl5T45aN=IKy7_{xl5HK)77W4T~rMoRn-bB z&B(5jpC(lYPxSGq8Im_(_&4A#_3T`laOs8s7PgXDyO<;%laLg0Jx$SiFwQPAz$05& zM?Ps6`3#TDu#RkH7x@B@Y-{JziMw>Lb9ogmdT)12vZ_j2X$|jc7v7I6^fAwi-qtPZ zX_xGMp6q|tk#Czd-n2`W%aaYVPL^XAIf_RPw~icU7x@Vy_0Ak)=Q4pO9~a`n*V<(6 zGSSXu7I&FZz^F}Qi_Y{0=V@(3r`n}n$Wza=TeB|Lw;|DdWp3or>qA_gGZybQ?y|)^ zoSW^Ue&JC+TVZuDvhN{3Z7cZ`PxSHF7m~N5;r|zRIcVo{l1m>8-Aewpi@C^S&V|mQ zwp#z6v5UOPBd=LUUa^aeOg1h8QgX=lrEA`?i@b+N7ETtg5xk#DahDQyF6H5(_jb8t ztF5H7*6=cR;U2E=aI)zV^N@9mD%vG`lqaiU9a+t+q1Yv>$CK5zPFB+{vJsDrwT^6H z7a5O8y)&EIxg_)C{ty?w)>?3vR6Ccaxl8K;M(wF&tF5G)HlhK$)E#*07g%`c8yvP~ zU9RUtqWO#)&ZCEhxV(x$ZGC^tT}GRSbEI9=cpmks71j_V`xoS=NqvPU`gnX9l6R=# z|221+Zs+nHm!1P)p(>ee7qgVdEDD`NJ+vNNU>CWDN3OJvTy7V+nMZE0j$CgSxt&M; zWasiLciCy@vL7ybZ|}97l*6@#|85t4j4K>5&x^y>EjnnI>;g}A);jXES>vQ#vKu_v zRqJH`*hNO97`yvj>&V-7kwp=ycV?j!ad+oawh~96Px*AU{v+&TZgsoYZ%M%jKoA(8e{yfCxV+3mJdpdWSnqs>8d}$Z; z4UhWT3TwQPeIEH~Qj76KACCngc_$eD-*cCxb}nnV^eO-gTgeK$m>+q}#*~l>p|{q9 zKiEa?;*mS7Be&T_?&FcaTSxw87kP+B{%PlOjJq7Mb2$eWy|+(WPRdDI!%y0UU*`%} z%=6;1b&D?AC5uco*07Xn+5dOU8n^6{mEg(lu})SbRb1_Sc9r9i_gP1lvWu*UNWC-5 z+qqQX$sY=F;cHFdE*?9V$GOX+sa9KwK5EgaR$IvwZA7cvrH$C9Ct%R*vm#c0_ zH1E56(u^T2oF;bfGz4nvyEJzxnP%EbirYm!z@y5hSzygEvR5KMP0EcY`gl|h$vfBZ zugYD#b}o-`>1Y58TS;}hn0h>>c3Q|(o}u+%O}og(Jkn`~PF$gbd0xC|-J*7O$$Ic)uUJQRGi!9UOZGZX zmSvsnHM_|7c;q|Qk#E^W4n(Bhnf>ithVbNrLtOY;8^K+M*}074E@KNAwJ~hbneLS= z(nfT&UFs=3^%r()*5#TQ63tiU5+1!U#AT_mcvo_l@6E%RXBV}eN3F5KT5V+COn%x{ zvJFr4@z@fQca7n{i@WTwbJ@$KcZY5zzuLtd<}n9C=g=~(|M%NPp5l?mts{@xMPA~O z=dB~p+C^UHkyq?o?sAt~b}mH%MsG(2thSQ%TEim(;w6TU#C-_YKMcM%V7kPV2!w3N zdM_5UOIC>|t6&}ZfLWuQT{49y^H?XVVi)-skBqjCtZo-s2a)>Jt!d}dfG4jP;=BAmI9t)I^ToI9x#{HIaa*O`rojJiS3Z<4)5=Wo;VJ7n+D zc`04fDeOuw%kmeFAR9?GifkdWg~=AtZA4K$KJp&2#dI4{oNNiQCCT1PwiL7IkJ9?{ zLidp^qn|HSmY$cR=l9d|2k3cu{dwUEWFI73QMZwmV9}n4hqUMH_lWHY2;V;aQ5)jj z0jY0~pnsUP17}M{xFQY)q>k*gOaGl?>{o3SiTE?nqa%LHSYb(tlCpn?=Yc>}k%&J6 zJu-U+pWPpbaz*?Vknmke7ZT{dkSyXbR<&^AP(VUhkjIgL)GO#j$;gsXB@5yI!gz$K zauzRl?V6SOvJe${PCwnHZ*V9JL>PWaT9tHT>#Ce?YQJ_RstOOJk9bt?xroQ82UXoh zJd3CH#}O!svkt(w9=UlwF^_fJT9;E~l!^yn=sm zTTQEM2x&x^$?3+Li+GBNTaj%|HiK*%vQIOMx%Lb_f0pcXbpCmI{(@%NT=AuAech#R z`>ZaV^6|>JTrvEW&K=*%e+9pB?unq5c-XI?t7p{`S46XPse2dv!^#MnT(T>o2|~3l zr0K?Hp(`Q|XM6MxKF_+=7120d>K!sST@g(&x*hvs&aw`#rFZyFy~Fh`?@9fK-`{8K zS?{Lnd)9mD+TIiSe!8}2MfKOuM-9MvHZyXle+KF{auC_U%tk~;d_b?~((@s(h>IKw z%hup9di_Jqvi|MPnie!?^u_o}y7ZFPGWtz_>|aT;#rS%<)FWtiyCSmErIx~pUg^^7 zrY`A|E@>mgm*AV}Qdg7L+c?>t4M^}(e1i>L@QK&bLsoC^bm`?D!E4SH(Jx)E?qO#9v!p#cIneD(cfH6O>Ot) z6ZP7)>e9VS$E+^xdcE{YyFl+QJ+rd9x5#`c=;7nNJHI4dyih?Za(~GWJi|OgJU=Ll zJJPJE&nd>mG{Z}d|SRF-KX%1_EJ*N(vJZ+IPr*D-h<&uq^XcYn`S_W;i|caG<}d!Xlrdywa* zd$8vg=GAR?uIG+>i07_*s3#k9tiR_&PquqFenxl(V8-QmMtKH$MtcTf?hW>g@qFO< z*purSi~0D8XQ<~>M2thkXP)7n@tzT$35fU{5fc$H2@zi)VlpDWM8p(COhv?3h?s_m z>4=!&nd_d3sIL(<3sJKX^$nutAZo7X6Zf~CPu<^n#<}NtK6B6ajCU_UriI9~2$>cm z(-LG_icERPw9GTp^F4l+d)B#EAmd78T!oCQk#P+&u0_Umo^L(tJ>PkL@XYgU@XYsY z^epgfLdMO=_#-lILB^kuaVs)zL&ojMxC0q~_T;#C;%Ap52GO=Q1??6*CG-FNVF z7b@A_W1jxr7souI7oey*(b zPE^);Cn@W_UnoC#Co3DgUn(2DQZ`AW7tU+FI|PzJ~gl^pyGlou(3 z^<-l|NLw<(k4?aCMO4rQ|Z zv+||9Q<);~Ql`q={a?vD{L|#0{nO>0{u%Nv|4jK8|JU-b{#o*G{@LW%5z~ z_wq6Sa{0J_g?z%lQatHFYzts&|#c@FDA>^S9E-OrTa?(xcQ&je+J`*UTa zd!jPRJxLku{zCc4Jy{v!{!%&Po}zs0o~n#>f2Dllo~C^2p012@&rm*d&qTfOwK61e zma^S58!_J~OFVOw4eq(hA^*3^ibuXvF39sxGt5{1!7RRs^6Hjn5q=hXA4Y}rm-3DK zi1Lx=Z)J}As4~}mOd0P!uI%@pKp&h`7P?O<-?~quo;sr}Q_d>ixzAzL&ZADcfI8_S zYNkudcGN-_-2W(h{8yA)?yJgt_cdjK`#R!pDChk*mCOEH$Wu{zAp4&OC8<<1cEjfJ z%+5<*i*nt)i$A3*HS5}?W8cSX)fy#9_@im;%;TN=bm`Rh^)9HM@e9Fm#`PY1DE#+$ zr_An3*O#?(sK4OTpScSEX+AG^*UsTDS-_`6Wx)YYG#}gpVE;woC(<>e zN4k0+)t&?$v^-gFX=iZ50X}EagI?AiYCb63*?&dw6X~j5Tze99U<@^DH+Z6MeK-HF zcKz7c1`X=fkBQ}{vY=YG*nWlcc+MT~g=4?|#v?eaxK&C8q6} z-SV3Wzb*DwYrS?&N0(H#L=lO-HnD?C!do=$zu^96Cs=Pk7TOENO6z?^ea`&)!)I2A zUo)w6v*3Pbei4-<=}|TSLH}_->U;LmQv9e72RY#(_oM!2uln$(Xa2VHqcLE9RiBci zD(ue%1pUYJ(KxV|p2H~k+nD{(r7D}Qncche@prk}%~o4{*jX2<;NRv4p}*|Ssk zex32&pGGmOW7jTOeLHq~_3>^}Y1fjGuZ?-^!=+shmB0PXKQ%n{$|O2h(C3MkzSf~> zQH^W%{jpB#e^O6<`eQ_yZH*l_;HAu7TJAG@()N|F=Wa2j(zs|Ppx5lI=o0K_`;JAy}^4F4A z_^tLYU$%%`TK&qt3Eylf_IH_sE&p?JVM{^c_T77R>aJyPlXI!9d}zSk{r4Q7-r~XG zdm^Ot^r}spwoho*zE-V-wDh$2xRiuu&7=W^r6`wca#bn&A9h1jijZ1yzxd|O(p$#G zCHn*E&6+9+Nww;9{uib#C9TMk-le4ddD41Gsfo>7#y5{|*0g?d%M5ZZ#GKjRK4Am{ zxO04qW@*h6Qd%UXC1?a$P3toPaA=kR)isd#1MMY^G>fuVV%bYj_8gu)y;)LnTtZxY zg1=dON2KhV*`rI-`mcBF-mePfA zXrFukZYi;Op}7E}ecxW~aZh)!s}L(cviG7BM=R_B{%B$L#3ylB?dn!KBJ${TV*Y~ocTH@|#x6&@x-z{DD z-V6!MV)yC$_Q~w|GLJ5Y_K#)J8(DNUL^ovOr)#;|rn-)&y6!z=&VgIQg^Duv@(3Qs zf`{R+`elztaA^d)t|076NLa_tukf%FApVSnHNxNg%ifBx?5$F_(ow~sx~q}vMk7~; z#x69!K{HoMysJiY*Q3o{>FJTJ(j)Gbo($=V9=+SMk!{cJFzX#!2~eN2?1%Q@aDM>T z6V@W6?A=)Fl^!j`9KF#Y`QZ;E{0kOd^iLdqM|k!NY&?oIYwC(_=E?{F#nnGOVn8}> z_eVrMA0q|Q6VqC^ZqYvLReT7-et9823PY3+72jkeDlV<|X~P%aGQD+1tJJh)yvRP{ z!GFc2UB38Krtz{~9~PG~6DS(R_BJg+3?Af_JF3*G6M*(oF0k^4I8@}*s zb6B4}?fZ6ose2b7!sTJTB~dp8HC#mdX0^xFNHP>BBh^<-v4f!4v&$Rpd-m&&-*rgc zRvCWNnBNaVLR=nt_2FFO;53~%%@C4h_3G1?3%cPmLu0?*vL#zK>2a;%*j$@#^nJx9 z=tOjXaOc&~JFmEOr+k~#G<;`DlF<>xrNs?sn&DG8==KzJJ9p{QTT8-Q5fAaNHSzuB zvohai^OF)~H-zZxy)rwu=YOzA%6=T~EbW&}&fYGN_DqLr2nQxU(NQr9| zBjH0XMz~6!Wo^<@pH6JmI<5tuG&I+uW(mnNv)Z%n>cT#F(FZ#UnP;<3{X}rg>Xz9x ze^x&Nr*Aa*X?|^1>oV;#;^JE*=1+&>(u!ur^u^@!2QW|DC$&jSfD1LYxOAmFdbn;K zN$=7N!g#-ows-FJMo(PyIs!35N1O=tIhy*u{AH5Zs#SZU@WY=z0vqqjD!Qg%&RuDu)c<%$o?*q+uovujsAI_&SKeWztxuMhOosjXAd=bVUd zDQjpV=vNE0n_h{KG6GV2Z5j9Ih0j$B943WuztLl&3vf`>IB z&@!C{wXWgNIayO+@1^t&g7^Azoh##s+M&!*r)x=ZS)DR7TlekLvqhJlt?{9+KHCpq z$QEj?&Wi~eGaBxoO|QP8UnmWJ`RhG+Z9if7{HT)z;-5@R$Uq16qCG6SnZ&jO?Si29 zd^5ay55ksc3>OoS``P-nV%x{HNDj0Lo-{E=?u~lx_&}gVVjQ*)wp|pLelW%)DJHb> z#ihZ?#`ItlH8^Xmk#$Cz)})lgIDcX*Fy$Fj`JWJ^pf2$l!F>|CcWd7=v1R+t{d)Ak zU6bra#w+EL4CUm+w8U1%rV)(L#PD6IH$iYjE@OA;CoF`_p74o zO=@pkNOO?tSK1tRHIfoqJ(r#lXx{_B&bU`6etEnEt?dYpdP(SVp*8IKy+f1uhW9yN zJM4Q#+QM2Jv>(N_PJ#FvBwnMrSmvS9;QFVa|1;D7OwjM$i+!s?-+9=DZl@;y8kP^< z`Lc=(iwFw0bOjW4eEGD=Fcx<3+G%Zc^*Pfj<>Q(`<9dVlmCy?}K>8~qZJ_T>Sv^B` zr`vG&jX8`Eo6;|feaAwdzO0Pf&3yh4CQqL(crVZew|ONuz0oJL zZx`N#dl7s$T3zyVT#GiWMEW1PNn2On>x}7mzoM0PX4u{d`f5054AAD#`XOkG z?V!^}?G`3rXMFVrRKe5lkVaL)YK-`ZzhpGMys=LPDRm;HZo&X!WorwQ@0GPceMHlG zC3vr-w_1El?rKQo>HQI(nnATDI?K59y)Q`VjcTv|2~vG8sRps*n%F$QalxfsS?k>3 zg^+0|t`n}escjSe?9G3^Y;oz`pi50?=S2M|^mOp%_bzBof+hlA%T$`;o0`p<)^6HV zo5}3HHNQpCtXXWcSoVF*s3>&M3Tp3teY?{LaJS6cR_hZP6jzONRVu<~2s} z>eo|$qhTyqw#v>hw?{+vabbIOp|{S$3-34d?n;fTZ=R}MV$tiy<75ruMEfc+>A~_^jZ&UeMJcsPKQya9nIr+6K+&KDu92A@hZ~UslJL?Jm!k zv~HPeJ>i1V_cbtb#4y?i73WmH9__KI^uQMYgWjH9(PS4`G$|+{@5kj0a4Ss8 zW?#V6ww>A5xIv+B7`S6ojHRU4@xhzpn}*W_vlA~4-!hzrgf^VJyluEFq1mOseG6WM z<3bgJy7nC-{QICPrF{zO6nfY6Kf_@Tzgpzq>|tLT);i^GOSDvYOT#DRyGDYRJOO-z z5R5wuDe)4k(|Y&o+g`twVpP&s(e-!OI{Qjkj-C7EmqLvIa+kU66vm%wd}H_i2wvG$ z*;0JTY83@B(S$CJ4}FXw46O@z1N$2d{En|Ux)uf{9AG#t(}yXLkdbKKr;AGqLURP| z0Xce(s27E92;Mi#qJaa^zzAtS+cz_N{-=GjxU^J94 zGDNW-eDPQNF`jc<1Y0(H(g{B$@KXgph5UtDm-T z=nscNZrrKI;{kYFscM$HYMst*=I`SNch$~Sv*3{fk5agq?q=5rw_X(%DfN7IHlzRl z_Fte%c2oto6mVzXkpgu~zEB25??Xi+t7d=4knUYmMk*DEm>q+^q5dhJx5od~md7Ni z%VJst?!)7!V)VbwUI?R`w=5<%C)fR0Zq5KV{vbV$E%d+pz9L5dXrvoQ=ftB4hc` zEoGNuEE{8T2aZQi3>?jR0>>60nBZmvIQo7h0$67R+hUURap+*kKMZ+MY&(g;IuqN4 z=Kf60eJN(efFhB&Th3bhGx~c18+WuH#WO<0q5@+^)JGC-@vKPaQ+6w`4SKw zp>_KRcivwGV;v_fSZ7%0fps=UJxy36XcLHLRA)_8r%hD)ws3)PV4dMy1J0Eg^)lg% z3C6i%!ntgNbDeNto#EU8&Mjj3%owppS>N0;Nek2FE)l>wBZ!JkQX^vZo#7LKAR;z& zsR{&zV)dOG))_$w5EP45ixNaPTD-McFBFT-9k`Hfj*GO-ajrYBsEJD7KuS8rcmNpX zV%0LSYH1?rN0TFlk(7%yE*WJ&Ag-m-CMJE>mZvU)b=F00uss~BJ`}4~B(~>`p=!wB z9yTF8#BnQ{;DllH5F@NJ#%M5Bk5#J@;K1OORo%o_)kLLt*&~Dl>kOwhaB9Y?D&Y(X z#;Iw-QEhPQ5Du&}oCd(DPb@QnFHiMN%KChcajMt|iat`DMXlFLFCP@GO0UM$R#<0k zje~MiQvQm~Q&#IVX7jYENg8u8zt)K-0$67R%|VbFt0u>)iNw*<;7DK`sp7V>$eovr zGaK1Pvs&9|R=e{O3ubLWtgy~l+kmxotojszehE-k3T8jaKwAS#C=TG@EP`j zNne;@A5xdYI_vT=z!@E@jwBqhavu$d^{m@@m&M!kKJ?GmUUyo#D&^&P-wvEBBcuX<^#TCIVPz z1mA&RE)j^8``m&F<`Ds`GlHccSRAV^BnY8$UyRLh2iqKZ<-X8FrB^z6PBGR3V|A>$ zGFDwqBtqrBnlI>;AQ0Emaubt2Yu8a1!8+@rpTPEGthy;y-9T(&<^H1yX%olYV1g4S z(pF-Gb;kHB7XtTTeEAowR%y%einAP%u||3}-^fmPOLanHT1FE{5GR!W3a?hlYM ztTW|@pj^?XRv>Y)a zc?LLbh()Z^+nA;Gsq!po!#dM`0ou=#wpgJ*Z>RktX~R0x?gH&jKD8ss3$=MCY=ZmT zxMhL+=^afZdKJ^vDL^j(^zf;#`qWHf5UTPXe968F0&&e`nwazwvp01Pth3H}3v6%r z)P6oSi`c}f{0$RQKaQJahSR6b+e8QJjBWtvvVH1%geKJE*(S30%skqH&LJFFXE;NF zlj~Cl6OK@i=bCT^+u#f%99U;KqkuDlScH0fgh^SS$)lYrj)meFQWWa(F;KKBs6L^# z!a8f~cqoq}Ww9O~XOhNMKEJe>Km@SP2)+Wr6rVcTr%oacu^yjdY$d3~C*$!SY+J$I z^GOBsO(Q;7XMA(P_l-}TMQ~yb{!M7Hmp98aM^Fmx(Q0rUecuum?0>~d#P?oa)V}jF zxM7kyu%Si$J+NVJ&H;=1`-6shTswIYp4z(VX^ie*3hWEhnN}k-D?Cvz=jVo z1`wl(K&-n*H_RP)FtqMIq}AOx`aULg*zncIHMFa_^MyVmA=vPRCZd@WsF^~&JpsLY z$fDk!)FzXfP-{=NQJd;S?Q5vbXsAvjL9x!B!ROI5lQz}av#5h%!|&jEfcUnd zI)@;{8v9#Fi}k`BJDB+d0~^1S| zwe%tC6xi@P;T+|tN6cXQG&x0Nu;G(k0@;Oz>N&y^YUm3l zs&i%*ZP8vP6xi@lZUW_cL-i`52=()I6UtQ^lv{)X8$ODw5$;$Lhfq7;HL2>eHlmRO zwZc$~YNQuJLfstI$hr_J(nv3aV8d@?aj4!ys$$K2k4Y9abAD-1g4AKdSHBgD_J_%EuLOBKxa0I|V_&sGI&l^dy*2u!S%D+5L-(DEt)Ni1ei zD<9NqWgLBOLW2FTNZT6YJL0z_`i^+zCP`|gCKmN_r6##KM=k2*hnwir1lF0d0%dO# z)lK4J&FpPr)XZ)Z2jO5tDy76YLOVMGqHMTZXIf_P({~4f1k6cqU$?VjD=zYQWPrb1~!U5r;5#>*rbWt zh(yI|x(T0QjZFH&42z>KhjrHFDZoi;qWTF(tgDj%ah!EK|E7t*V60Taf^~-V6tDtK z)Ru%LRM-I%RZA0x`fW2wrWXW)g%@eZPv$@gmzC`8Q26O;ma{ z)6*%&8^Gw-M9pfVzD6WM9o~;G=qwP3Yw0x;lRj(Tq%MMW)O`TUtv#feayK#D?zJ^_kWrPm~CE3C7&PJ!}d zQWmT9$tG#c#r*PPDiOdsBlrdcvzn+go2b)?L#)(iiQ5Y5^_e(xg>5wanW}QQ< zu+CT)gLPpObv}WLmHWcb;xKQ%X}$pZtX8?>=vzWqu>TcnVKY?jKNyvJ*|;S2zBsjH zoL;>D*bLwGzlN`_zsJ71ejmP(p5uY=P3_y!H{E$9ab_?(b3;3GL;IJGxgPc}9dY!P zi_^<`SZ7!jfmMN+wl>rM@!=?jR6$e1bOI#)@!>V&A0Jk7s_21Yl{mFBiSA?_!Tz!7 z7^YeUsvmoxms29IvWWmRA8TEJqt8oS0PCy^q5)JrPOVBnyA7aE8BldVWHTWAGr+0^ z13f}Ou+D&L1E^-4suIv20#MB$AhlqiIs^pk45$Hs>J!Zm&Gdhn{2A+=`X&JVsuM%X zu+EelLD@&jXQ3SLm9i%>WuK@#!GnJjjTe25Ng39easrg&;?$-jF2(6<<4YzU2l3;$ z8G%DyQ#_uEg_<+L!`2Bv^y`h^DZrBeNQqOE2%u0fKuQomk_|v}rvOg@AP}dvB!HW= zJ7_%+2m)wn1JKGTz|#Q8AoUBugP#G#T-N9M-oyw085(?8XM_I&l%J1NpCj=r)b#0W z@SkTBtqp$io)ai^+Gwg<%f6Fw9`{4ad9=HW*#Q#Mo|J zvR(&9-#E25VThNkzTlY8IQS*2H_j|#XM!(TOSJtON8cMXIIv+24##>ISnm*%aLIZH z9kC>TTJZ6B&#B@-C=Q5Ivq@CEWDS7o3c6%vn+PyTS7=>;qi+y(0j#qw_z*xtS4kVFIh*yv59f;OV(kW*}~2QU$VAp`!$Zf z6Erxm|8;OgtaHFRLrlUY>kK+#D_e>o@3PK2RlEYl%W>*O5*065m!Z0gE?E~%1fbca zbpejPtJDRs&br_ZfNsU9HwZ|)WZeS94|K`8Q83V50)ll0R5%`=xW=my_)XjFH!g{n ztf=^Wpa?t`$4Ka*BJuP=Y`jCD5&$YjG{PmTm zs|+c_I#aFyQ^>Gpx zE?KqWjdxj(ix~WpRoAJ!5ArebYJHLyE?F`0_|`wWFz`!OeH)C1{~eW zgsr46{NjkMQ2Ue3_mF>nwuAZ}_P_RhzUpsK{Uu)ANy6es`M<;)ALZ{fF@Wcwc4ffP zx0_I4!$8wdx zm`#_cn_LN1XP8(xMpM%k3KCPp{{`qziaA(t9F7~ zGeK2}OZ-^Awh5;uM^#N=!o;aZe6Zp3H3FY6L5(3e;UjsUi7m!Nq<2+gLV*n*#SfJD z1hpBV2p`ACn^2nBpd=CsZ1^Zo0wskwgpcA=Ose|aZSF)Z0JWB+CVULv5^7c@Q#!Q~ zHvBebK(!UAiXXwZGRb1z<(Cg_NF6qO^%tSuEYjp#BBo~zqiGivuq>b zAHP3aFlT$>gbkmw8#ucrsGSK?{OG+akc5IRud``>0Qe{?@z~LqNl38aAl1++?Dv55 zzXbJ7LK1HX{SQc&SugP$LT}>CRdy!$hR}7b>cr9aJ|V$|k2DBKIm9E}49Y=&T!(n* z&7i?f)INmT&;&J?1jQRcL!o$=ZUp6;)IoArYdVg;;nZ~4@SFZIU_MGvM-hy86X+uV zT%emkqY8!@OE9qE!+Z{y@d@fUf)Q^3jSqquS1`;(f`JVmW(r^?6Nzy1XR=9LzluyH zRoL)VXFzotsR}oKrirTjz5h&7g$-YIE>yosP-l^_aMR}-2pczjX5n#vFJ@uLO`mU_ zh%bWpf&_IQi3>M;76ggUvk_nHM0`2KmnEo6NnE(uvn)t_sg3vwC*o@$zKWEE8$GL_ z7PRm1!Cp&)4IBPoZ-VNE1a&@biC1IFS%=y{TP(t^wf+=?gb_u0ZVrHn&4=@LZ=phyAa8p09crs<#u= znCYWFl8r#{4W3b& zI*z`=qz)UtdNIG<4W4|V;v@tczECMNvm`ZBxWQA>pPMs^jdREip3+X#%0aCRsR=iD z%Gjvg??kN<)E@M!Zu>oiExnsEcc+g^5R>p{=QFV8id4 zcHnC3SD*E(PZO7TgQu+t=UI;Wv4(84Id>7D6bKRaD(SHld3*<`#Mp36Kb!Mns9^X zb*NdDOm9&eVZ(3ZyHI_HRK*)S@0esU@AAus_edQ!eDx2YKFF`;_|^WzAl~2^ByJnH z!IOhCpR$dF-{9$AFlR1t!iLW|8k{5j>TrS-Z}5x^E$H%wo8||AN3s%+9ep1W5^Oj~ z*=vk%{VW95d}0!+?D+r~&q{)jDti$r!#Y#`9?E%sbqR@!m3AKAyOx+Z!1TFR>*DBJ zPB^g6aMl246|sob_9_g{bT(gttL+&Y0gk@4L;&lIV1sSNoiDbL#9*C?Z9#K4Q*(u? zdo%ib1{?Q~s{1FWiaVgVjTD8-dz+2o&rTJ0L-AL?x{E}`>ibtd!*-eUg&FocbvdlF zEH;fNLZen5QAx}8_x`wGT7NLaAWu#N-ks9!xoSV9$k)I@c}M5SN2PY@2Q zGo16lIqO$X6OK@cpEco}w!yhTIIzxet^nsUv53|9Ws|fpZLSgltTTdJAh#VJ@P;NlVV#VITB#pV4Uw-(A z0M;2n0tn&~)uxGRW8x62_Be4{LDk+AXXdhvhF9&43ug5bE37ltmSAn3sHPIASh+U` zmQWn#rJCjopr>nbtfjFa_Si2$uM-ZeGn{vT^A@p)mHS&5oaJoJ1Xu1WGy)ub|04oe zX9U@acK6Ej#rl&NtTVAeXl@QQSE$@`(BCWAxQA5kgPkf4g<>u#3YB}Vjp8t;ild=8 zGEp5)qGIJflFzW=CVgRseMDUj>#WN^1J0+3>R7@NEB8+Uv4C|uuiVELj5VIHV4Y!2 z0oLS1brN9-mHT89)g%*@enFo~IIzxeW&vkrqB@;$gvx!U31_+u&TPVgb%ygDaOM(= zSh>$NNek0v9udGgBUlWAg+w4$?h6YhSV9D_&Ine5V0ogtj39){eK|JA)ogR*mHRRi zm0szra*DAD7#kAR^@-|QA`vS04SYeb2Z6Yj)|!~~S-Y9K2-aB_?F8G7M0H!D`V+B< zmHQ48(l(C!lL=0kNV|v;)*0hIFz!iIcN3scx$iOY?KV;AUG@jzz&gYE3pj@o)dPeh zRPKjNI0tNSjt~y4Gn^B^IYul(<$lbhtk36@P8H8W@iZw4mHTNZT9sbssI9Qh+Ik7f z7f4yG+%K4x|$w2yP~-*AvyN#35GhH^prQmHTy^S~J>J}=?GI>V_BoT|hk zR_;|XINR8q39j6?YXms@Y7haeGlIvGNWO#dhnpWRElDlV+8pwzR?v&eIQou34qwdx}8_pqr&2cB&9C_v5)kLLNI#cqv%wifIIzxe#sX&yu?Us> z7?ZL-pFeS`I39}QNKvTV$3fAm^qN3zg>}}}FQ7b;l*P(@qDdNaF~9tnOa!pb2)+iv z4E&>oBy}orh?V;caa%#x+@}`II*V9gov|(e>pc8%9s(6B_j#ekVcxf< z`2y%|TIG(TZy{m9hJ}@9RPGyqwVs%S%6&Zm_OMbSq;lU#%COFqw?cUfzOq5$V&%St z?`xY)9AMh3)y+8iwh<1jGn`$(`I%V6%Kc{y&OtV3f-Cn!8Uc>JUx)zK8Nu(im3zL} z9uk9fCbl2V-ABz8D))Wp??Y_dLn`+_ohlxN;z3drD))mnihns(JORaHN$TGuDpu~t z_ze5oq%X{{lhoy~&bs^paL(aZKM{^txt{~XUe@iraz9fr)vuL_o#7M(PT^$zYa(Lh zUKlXqLJ_9TJwyQOjNo1nlpq4JaxYOZK`A1Dbw=<22+Ad^We7s3+{-2B4m`p(M_##? zF;VH2PI;#oZeTo|tUi>iRwNRka(_74xY_fNX_{0tG3m3`LtO;xtcxB2Ta9G3TC%DT zn^?KmFdnTn;;U(*(z~o4;lMh>X$YLyWVHd| z2$g%R38#S#P9wsBb%qlMoTkJgRPIep%KChccdD2KML#JDmAfB`R;5=mwH4M`Tbn~U zm6XNGJ=G+QxtL#mv>*alX9R6P&^lRtDp?H>hgi9{7Pl2t?oZ*&akkO$$~{mp>(j&v z>x{KMSYJq1pC?eUa(@9>LUEY)ylK7w`k+?1JX?KLX*4}mq5n1srGC;(2e zQX-^sA5O}!&XmVMd33TmlElTzeKgSW5{D)*04nV69A6mlKvyxvw-)EjLl=7xXoR1M3WD6L2;ptLq6zsN6T0 zaMs)4Y$hC7XE@t{^AoX%mHSU7X<^!ICjwY!1iye_ClQF1`_6(1ekB4}X9RzMU~jVe zJ3$DQ`(A90!`bG@EBD_`RC=Ye-zmmXU>r$S4=1Y!iA1Q}kMIS37zE;4I%s0jXYDcS zB3Nf#bRKMHlhxD7>Pcb~EBCV|q|+StqzO)#NEe6^)*0h#VK!LAewuiqEo}>x{K3SmhMeL!e^iE(1#_4)Z*w`2y%6tXyPA zUp2yl4GXJ$1bxqa60kleCZTfw8~`7)3NEB_|ALfZoheU)^3)XdOA;3=_o*qy4U{iU z9AG-HRqib6@OKaTyeslA=(#FSSwp-l^gmD6UFTSCFV!xv%0g zY=uc*m|<(F%VC{$`DWm3Oi_Oz9IkQ{0aQ-9~v2y>@BrQyvLqq`U zjNm8;ju3%ZxgRN*;206WIwLp>g3~GLNrDh6_tV%MC$Y_uSMDcGRC?up&MC$X5NG81G3{i=^u1sZhD!W8y1IOPZj))~%&z$s5GLgilGq^!^9icS?DhT=n{C{*qbLD8!8szPmrb=FoH${tb{ zD|e4c8gntf{7{Gh))|2cf=5%;=v1{jafp@sqp8BSg33J_XQr@?hF9*@3ub+sSYe&9 zHUMk=RJAUFij{kPUvmZLs+o?73*NjfGb-2?Ttm#@JVo*zK(^e zy>MD?&NNoNg;eeLr0JUoZ1}3Bpjt9bEl$E>#a=SasMw2}7{D__tCw-~l_nI}@KNpu zN?GC%tM#&J_%oDjo&;Cxb2W7weGia2Z20OG)9fnse4$Dt1RK6k6*RLlHB+e4E2EF+ zvT+Wn(%nwf6sUPgO{mblHfmL!s67g`=rpxD35wNuG@nh?P1?e2dW^amHvDd`3zXVv zYE42BEA!d_n8CW5e;cM|!ASK82{wGBMnLkVsWF5kROLPsQH+U5zgRaW6xi@l{6L9M zQ=1WrP?5)*P@37GBoYd2_$W^TC51S|YCOdxD@>E-qz)UtdOFn8NL{SN(+XC9iqv7l zSAQ1jPp7FF1Rzx5Ph-=Y$2L7)g=d(E^s41KCkQVAp+lPbVw&2HD1-{U17EZ+LS0-l z?MyuS4DCc+0~>zVbO+ZfX==ALwJULn)%PnVoNgSos|ie)I6a6DHhjK*;LA!=Un4l7 z^3F1`y=EfPyXtj9fejz!U7);^roKfeLe>3_3FR#tl=lb)Hhh#Ep!6pWq2lguQq||~ zKqqRsP#a8YLbW{@YE~uF5NacA_-z~x)nTM6R@%c%vY2=I<--V4hYer-Q>c$kQ^%yK zqlrPRvd40NU_5HBDA2(n`oLJ0G^{& z*f{#85E5)SNRMh2_F^C{Bp#u{UI_7}tQ-ibu$Pc3Z1}1xp!$89nn%K7h5bF>v+_&~ z;8~{CxH$S&5(;eiDC>Z-hB(9udkqF;HJc;B74{lU9Y^1KQily+eUoj4oiDVRgkZxL z+KOgwp=Jsd_7?Q<8aB=$74|kKYCEB}gVclydxwqME+=Yxptd_r{gnj83VS!7O~0D7 zh1s;1x*0b7ZaxH*18M4hLJ=$M0{~dYx|&zm`wK=oOh~ZdBb@}&@ig@)Aqf@saTC!| z6On#VK1C?7;iFsx%K0?)ETIS$_IVS^SsRo~gaR8r$~B-|Ar7&^zG9LUrpa|uhYer- z4%Bavx>#Y~Dp>t4sl$e^UO0e1yc|#?0{V>=p~8*|;MXj$O^;XD5drHBqDa62LTMn} z8&FFG)M7*-RM__hjGHVapf0YNVkRDahTa#@Z~efA-!&D%RUx205Kzkzmsnv}FyTDF zQOlXYgo#s$_+Z25lfmZ+s8t9~sIWaIwkjqfy{i;Lfejz!QJ_Qz)aryHRM^oblsIcon&8lQ-Ky8E#zl{x{8cV8Tg&k{> z#k|We9~zN5Z20PlP)`V`aRId{F^Cm*g1Bv86K6?W5tIg^MJHhj(iI9mqP z<^(BL*e!u16m)sbP4j~RYZW$*zH~x@{jW&-$_HHc1ze?DOR)Is_J6m;FJB6%yLGUD zt4zREHsC53aNQqpmCxG)jvwW^x&6yVRUe%5lU!?h+!nbm_Q3M)m8j7fqj56tu#u&(H|BUiVtwJx zKUt_s%q2J-MBC4o$UDM(A43mFtQ%ZWH6*FlfcttshO-g_X#u4i}9Ug8DgWQbQoVyqS7IWTt>e%)I%CY zyI4r$ppX(lA(X#~?%Xswf;l$}axQ9ij?8G2lgPMFdlA@xSIc)8OQRqtrAm+HKBzu-?ReIfFm{N0ShJtfCcE~q6~8hR)&|*k9^H91^vZyf`4@qr-k5Xx%4q#>y9wK5@qgb< z*d~jin-CFjWoW2)8gR7x56C6|6LJY4BO>5>Rzt?qfa^KOJ7QaXO%=S^ zl>+F$*zE2FAzTBl=QTn+4Y=CTB91AoPs$ha$GLEonERN^iAQiXd4T-~BkL5bCy$}{d>8U}kQ@`V=GqbikFJjh+w5ju-Jlf4rcLAqxs)46_F!0rKR) zu(8yhV?57bJfqXq>c)6x4}wFrE2%43&q>)QX{gwW30gYQ=|)dg*SZ+JbKTnl{|*!} zzDG6S!3HpU8V>MK9XQtjX3qh91;BOE)mrK5t+N@wU~6)q2=me zo?*^pk7Va!wR1+Hl|35g@*WGCELCEX^vRO_5p#bmy;_at)FY?SBQ5am>bjR@8)J@4 z)|&q@Uhp--xav>GvNXD?izayXCpd?_1xiRXjyXJ$Uado8=gL~c+Al^YMzDi7rmS;R(&~){upEJK&Y_wvZ#O7ZIkIKZP0t?TyX)uxL z3LB>8!-iXr)7FEoq_MP!ZLSGTGKBP}U*IVkgVdn=lBpVW{mbfgFI!w}BnXM zBW=9PV`Pu9ohdIS9mX4z25~rQ9W-6ntG25V1_oPe_T``@(YIPU8=3WPJ(BHZY>c#b z-q|xu>M>7I(wQu2O8kleMIxo_YrzTm{=MGKIxCKKKYNh97a_)z|3}<=z(-Ma|Npy5 zXaa(Of+DiJGXx@zbVwFNl5CnlHqvZpM2bY|1Ri~CfdB>&>4G4LAP6ELogf{gNEJ|| z3Wzl6BE9@ScjnC9y*o4cKJNTpufM*sH#>XI`MmGB?d)twO0sX7v3W2HSJ`mm+i&qL zb{R<;`r2|_h_2pL8|jELe9)kcExBooX7vNCw5cToUV+Q%sls%^*`!w^00w;( z8g;d>=h&nj&*2AsGL%+)dtRg2t<{?KXv7Mp6&5K~Fwrk*n_jcHSJe(~fHBL`J?+qZ z5o=R>VIzwo?w2oXuF-8+i~Tb0H8sR0V+ieqEi6P2Di@0&d7AhDIa-Z`wk?ZvwM6tQ zTH7oxQ;qnOF{1XuHoTDk3L78B?2uz$SM9fxJ)Qil6WR+qM0-zcJJo(C+20RzT6qYj$j}i+)QyqYr8?9bzwa33@5IYw(k9!B4seKj{(tq-W3* za2;Vm-_FSIq|QRU9;AD<`f>d`Gs+4!VtZoXrt1b5yXm^Y#kS>Ru+4v4AEgI8vHwx? zcpR6#y)pLM(?6J17Bq2waARjAzfYyzDV_SzSXa=k(%5&@P$w9TmLjd7h|#Y9iR;Mh z+d&=l_Jv|L-WO>X=_W2N21G&FM-6*26saJXI63aWh!Wg`g3N1rV&4S`T#%tt5K>ct zOJ2amX!@sdxm6?vn4+p12ps#L|?4BH2%@DcAZJZP!;z8t18}Nb2PeN##8-K6FE>tYTvM%jIHw=_>_mQshloF91gAS z>dBnc3akhJt~>v(oBmyND}T_O4{U%%)f@HNtpUddS9E`N2xGJCfIagxyIpYF)r^gz z!yWsPN`C{`>ILoC?2Nr72kS?B@fN*EXE0uj!HekgZM+bJZ5iL*Vf}9MtaewS6#C7g zJ;=)K=v*d_`vJk?Y_Gp-(8R@ixTv0(PzgFQBb_T_D?6Odl1`^{d90)N+m5_QM`Tn{ zhtrW$6gNXkMih>8Zr~)&rN={GC9hn4+B`hJ!s`~n*012>*$f)D<}~?3WLe{ zhn44L?s>u7^PH9EP40Qk-1DlH=Y8&Z$I7HooIbD-apJ)8RF;H^mhA`P9G!Y~?AWPK zxAs9}R2MmSI*VGlm*)!Q;tcbmOq^*JOIrnV^I%Vydp>T|c+4u;lRQ{e^I%o1JZp2$ z8s?sgm1itGwPe<_GI@pv_lB78wU)q5p0zS*#!b=+7`2o*EV>@=hKy*6I-*Hdq1*7# zEt$L7nsqv#5Ao*HDT{k|3NdM}FWw&9q^of_-?sAV%e{J=VWsQQ-y=J9E6KqVZ9F~* ziR;(x2Xd4CRwkct>A?UNwvvyne8zB}k)dyp`v4?m5-mbBdMc zZ0WE&p3LW9qkDvQiYu4$!8{*AZ<|Ev@tXDj|TIq|o5;u9wYdC!>Sb0g@%jGrM;a<|C zS0g)hD^c)78;>VL;=Zig*XAZQtW4s#bbSB|TS;9jpLp)m*c)=5MygdwBP-A6xMzyF zXOfj?3-0MR_iS$E`6BmhZDsNrH+jX%q!UcEY`6ECRVA;e6R(|>dk?PA)i^KSHt$iE zRj~i^VE-}q>|@mEZ51q+2g@-J_Mw&MQ0|#$?m5WHb0j>qWPWO8@)-|4I>dypwTawh zyp_pxZZfriQJcaRouMjetB&YotI+d!=$&F|bI(;)o?E!*Mk|w@++>@T$v&89+1}gGY%6&~ zop`&g+>ddEBgT1g$h=1ftb+Z;gPk__JZaQ8VHNBu4|dr+*hMSPJKXc8x#x8&&xl5P zGVfcN6oH9$Ga;&x#ab)DO^R8WJi<-NHnJYIhZ>n}CGFJ_EoBwj#Y0zO?xAmR*qU`Z zD~5RUmH9+ty?YfKi{0y_FWxHL#M9WYmAI_Ds&lVujZLt+>CtPFow}9O!xL?C*A9u> zUAOmglLl5M@m#twfQ7B3k(Eyx_epLXvXyjJGw8GOY{5PK=AO;1JYVLXFPM9_w(@+P zd%kLA(ute2w=(Gl6D`|sH#VD;z0{6pS-HQ%75W(GMQ`&S^|T7sp9lNM-17sY#(P%5 zhVo!}=D`M8d5-3uBg{QNwetKNo?0?Lvoe{?gHH@G;cIOgH<@B(GKZUdTfnHzWQ)#F zmGo6dbcR*vr9AW^t2OI%E(r1FE3;g@zLh)_?`YqtThLv%TvfMZyrZ*lc@QqE>%Jmf zwd7TZcXa6-bfYp)H}UZ3mE#>9f-J_Uu`5~mJ<0v5ihen&Ull9A+T5>(nV(|i7t8(X zS(!Y;O}thnKA30;iH~=5?~@(WUu`>jHpFw9o~NeVGu7NP*~+s8_w<{4Hn;M8fp@4? zhzTFQ*Ld((kj^fSK@oJn-Q#q=WaZR}JGF;X_jX;n1kI^A>iE5G<@+DblpQ)77pR^+ zLTBS*J%t}~+4n-CFV#&3^634=*|AcMonz%UjQb4{{pP8Dc~*X7x!))=zY$h`6S?1b zE0ZbQWRjK1H!#s=#cmxaHf-?vvITPc|3GBZq-wGiOZf3iN0Moxz3|s z6=%mDHTD%Nzx&+pj_CKJ>UYb^uSkNv(?=x;d$Hyhks$8joUp)ew3Sms z?i35BklA=p9lv^3zPmWn_5`u$Kcc5XU?}=`TX`MkUI!9PivE*&^y6fw9{#8B zL>tc&A#qRX_UE|C87q^&x%4Ff3q}70E1%ok=SD(E(SKCU;594Hs6>4QI1^1h?^}76 z;GV_IJ&PoYL&B3#hI^K>GO55#9=0-Z!9>e;r9`u$|E${aidODVa)qjihIvuNyhoB% zu(~{0EpyKrMh(R(*fTts*F0FPm1h$7OfdIsV&&Nso?0?ftxPg_@a7>Ve66+SCM~Q? zGPz0H0!HoSM6;s*f;yrvT7}Nyp*u16(EA5$%{rYOLcIB;{D^zM4{xEmzp8q^lNeI; zU&m#2-4BARmb~0V@xZvLn+)U8ha?II&3!d?o|WHN?l(&GyR7<+u=1P4{U(_Cjkoff z#{H&Pnat!S)2&SA!9+{QcZsG4+qWT}PWyjVIc8mh_2xdTHJMVQx~!%H(k_{irYGU@LFsBXb|OFXVVC zre?6Rm8ZfzpEUQZX60Frd)7AhtZC)hkbA~jnZ$FG##Sb2FwwG|>@z#q%BmgrS-H35 z3K>Xq$WMf&oA;=hRj^liu$Rp}Uo>j8u?p6S2WxL0teur-H}3hixo4J@XEr>wWcIW& zd6x(88)CxO+K1faJu8zuZZfcdQOjkE&Tu!YygH)&tU{0Cp@&6{?zP$sD_W1fiR{#^WE-AnXKu2?%H%gL{Y&Up zvd7BjDEB!WI)@%t^MBCF^9=VqY3_N#%JVY!ykPEm&dT#T_q=Lla+jOjvN9=@q-Q%K z$!sfmQth}SN!--=NR)!R_K{JEB*RwnKvKwttYxvNRj@~Sut&^2%NaGwSOxR&V3o~- zRkHGYl6zJ)_pD;&SreYx)K#oZ>ha*ULrnNu^Kz30Rwh1f5?{cmJ)2~s>RfMtbyqWT#3E z!V_&gazo-iquUSVCV5sSqqy{N01I!ohgtbd;6CF*=TIFrgJZ2cr*Y3I=AM(SJZE#y zndY7|tUTv)&$(76OS#D+E0fhQ(Xze5bW%1^JHFh?eG6CEXq*=t%zL!XD%c(#Y?ry` z4x`34t6+zCu>I!2_E~wJ;GW0KJ%6|IJPS`PnWwBwF7n{#LQMEtyUI;2TbbPBCbtV1 zwVS3}iBBET>sFzQChLbop=6V-gsoYpGcs8`TKLMW$h|9sn54i_UEdyVQaRah`c$&= zs>Z#lm|>;s(G{{&rE24eHXb!X;`(*_2Hd2sl}TeR-4MXSRuX6Blgxb*lS9taR5gR~ zR-S(D+05MYIV;Z>xMwSK&lXmmuX4|qtxVc;lh>_G-iC>m?as+&RY?oAIUMU!%r5R>AUkuz}{ma;-c^aL-}po1%+XdR6M69Q zAtrpSP2nb!tW3V;Cf^h=YSY=GGrYlRqmJk_tI&&h==oM_*6ExV;>}m)Chol<#N;J? z@$TRzTaClH#mZ|h_xjlk>vcW)ezH@yk|TJcjmN=|xb1ZNKe)+JE0eQa`c&vv@~4&0 z74CB}bPm0&=Ks8v=WXtJ!`$_VV zVWMTbT#DIN(n0Nb87p@;S9l`DaKt=r-lNB?f>r0is+oI68#QFBV0C%0TIRuOSa~+$ zo^j@$4Xiv9;Hf3^Su2wi9^4mV!q-|eZjxqY(uSL~EMU~0Pchp{I;$h(Rd?J5}myJkiGE ztB|-ubo*J{WQLW=_gs1ofQ71Lww2E^?z1>_4s}&CxX{XTE%#hy?zzIsa|`#}Xzsbe z%5x|8+-7C+3pd$qWpWrMTDA|EPRe0w$A7bOKgAVJ80W=t^Bx_w3U-+XyI}5l&Zu$L zD%dR^?7Dfdf2=$sQuW>azPaaJE6<|v)RI{!RovbA)Gf(_KM-QV*IF5FQp(EYac=Tx zs@VacjavCsv#n&LI-(C-g^uQ-CFUNwm9RDIbh<;ldH25L-d}{6jDe%NzGrZgX{mXikqCUGPwv7E!*czC*@?d<7chh zZ*qle#(8noyhm58f<>n3YuJ%yn*V!7jXPGsO7LLC%!3t46IVN*UFEpvL*|~PtUMos zr>iQCHLX>L+I&1@^tMlB}IY%7_nj%Zb@(6KypJ?0*|m9RDI zbk+&+=D91Dt`A}1bTPft;i#_f(%htEx?w9RZsqj|_bQuif;C5vUXkonDHon-<54Lj z?p)oz3ODgsnLNd%V*o5{B~`6_>T;i2=^<138#RM9tURCLo?dg$SS!yY?wMfj*~H4T zDfdjZGI^exq+6N11QRXWZPLvq<$Sf{t*qSJbA{K9^Wru09<{X!)|Cf)%iOcGQKOSp zu)aK4Z}VV1tvo;Ep6{7^zH8+<0G?Vh`&pR`=D`PrnDDjsDK{BvWipH(!}cx%Z+FlV$qiUByj)Fb-$FmDdLDwbl%4jUIgq z*{NH}4m{DuV{1s zs7sn%#AW{z?0Li$t&RE{E#gF7Wo<-cp?~Q5HEOT37V&P-^PAM(qU*Qm`5kKS()D}V z^TPN2Wm){fjts4JQX4^SB(+gm8&N1j<10*U5o(LF7X2=!JumbCwZ*mTg-X!#lJxvR zdR~g2m)4#aeu&yK)RxuS$Z}{S)Ze_d-!J_1=uhep?ejaby9WKks$IBRGQt^g)bD7= zE<3f~8ODB9R*{G!{;uutTfz!ETv3jk-(dN>KdMN?A%EAbZoyX%`=gu@fA}5vSw|-V zXunV_;y6~NaN(HW0kR6M0^{+%Y@Y zk+~JdFE}fop>I16XBhgfo+6cC!6u@lWh+9atX0w4sA#oizeTNLhNHLe+rzY9`SU0) z2c_>_O5YP14*YYq!svYk$5)OVM@~KV0y+e$>YOTuSs?@bm#$Sciw2jvaKU7YXq2I^ zmxyE{P0`wjRBF?xeU7!5S54`8GisY_*CW#DxnFx8`8+*uskW@gwKLR=cg)W0-LZWD zvy9VOlfTlT-MfKT@LS`a4(gGc{TjKa%zEUEh|O?x>4<+E89@_Faz@mLtC~uha%?6# zBkE;1dW6hFXGC0vdIn|o4jOc4L<5X*yKKx_miC%j+IMSdkEGPUNW=Xqb@nxCGpT)@ z+IG~wL2Y}rWl3oh+QC+02idA(>*pn0W(zBX#ToGmqg0c|RtC#aL|fQu8RnN>hKz|j zrb1`x0)CC4zIA42Xj^BW40TJ4?3b`ggQ8@?C2G%i4&@i1+CA_o@AWu78M@ zEsBrmdXCz%-gg34@NS{)AssRtZ>WPrzhIF4<4l%=9vP0V!U%QEa5NV#WMw$|292(| zq$0XxICy^8uOf`-$x*0sbo^Rgo{Dvz{@<-IG75UbTZiVoh6%)N}TlenRt9RRXI`-=RPFr8c-fw4j z@6onRR_{LTy0q@tDNE_vu6K6FUTu?nO_j8?w(r!h+qOl=E*;zT?%1~b8*jDs_vqNI zckeFEvfc>#_URrS-f&#GT)|P~;gTP_hq?#5x5-P~%iYV|C*}3-U)rZCDsi<$j%$Exi0f0=XxCWR zB-a$zG}jE*OxL%rxvuYBOI^!dD_rYb8(dplr(CC9*IjpAA47Dgd$@a)`!n}=_ayfe z_jLCx_Yxp1cdrM)4j}yE{@s1ieFF%0+ER0 zOLwJv(tW9)++Q9b50XEY2g^g`q4Fp4r}A)lggizbCr^|o%U{Ve<$3aad4ar8UMw$> zm&y6^a(RWkN?s?gmw%Ku$y?-Y@*a7wd_X=ZACZsB$K^ldlkyq)qI^ldEMJkY%KymM z*CAZ3>IT;ZS$71AbiEA-3w#2mzkNJ39j>jL=4F2F+i9D{t z<7zyv!Q)yyuEXPcHM{FwKO)B)@wf?(oAI~>k3ZpYD;~GuaXTJ&xF)!E;=5h0MXsM= zw;NaX;L2WH`2|;g#g%=y@*A$~$CU%Pau8gHpm!Lr9KkEUJ+R_!|DvI&cf<1Se=8_d01V5)kRocg4JbMU4hl#u(}GXe_(YDR@Y&516DU- zbqiLvT_at0V0jmo_h5M+mO1Wgu72+8uKw;Du3Yy`*8uk|*Fg7e*C6*D%&xnxJoi1< zVE2935O)q{T0i$E?i|-Je0}Qfk9n8t9^oF~9_b#4892y2+WoP6j62Ug7PIm*_Yn6u zc#Ma~=k8(d3GPqb6XEd%JSM?oGCaP7#}s&c1&^ulmVGl5OF6W?n1<$-MOya_}b%M>E4UTzaa9j_}Yi)zajd5L_dJ&2NC@cq8~=| zBZ&Sxq8~-{V~Bnn(f>g76NvsNqMtV(a*SdyU)7!xc@@*bBKN((JvtSMMS@Z z=$8@w3Znmw=vNW_A4I=~=+_bb2BP0Y^jnC28`19|`d#-R*FAjQhf0p;l)Injw7b9O zj62tJ);+-UmwTY+4{4C+g!HlJPbtrHQX1?zB@OYMmWF!HNS}DlO2a&VNuPSoNy9zo zr4gPB(n!xmX_V)ZG}?1n8soVljrII3edf6;jr05?jrUxWKKERgCU|a06FoPjFFd!T zNuJx%WX~PxOV1kj6nuT@qx?n_^La^&fre)0@YfB73vt~}E-K%V6pD1Yl2 zB+vGIEPv<8ljnE_%X2+LB5L z&uBT{Ge%zS87u$b`AlBn87HswjF(q=K9^T}Cdg|%6Xms@FXVNeN%DHnWO;+h_e-Owjs`T#Myy3J3Z6nU5N8D;_OD8J&3axaehIZUlC`Y z=WF>l&vbdeXNG(LaSkHRA;dY1I7blYcf>i0ILAES$j1@q55zfvIDaC}NyIsYIHwWk zjAy2N)-y}~%k!;#&NEv+@A*!?fOr=@bL2~&x$kMsd8)KWo+j<| zeJ$9lX9bjG(z zI_q04{pDLDo%5}g&imF$7kulbi@pugCEt(IW#2~Wif@zjw{Np_)we~$_)A~NTczHoAg7y{n9nx0qMH$ zpmf7`NE+)pEUkAPkv8F6-HelU3(nU2@^NXB{D*YYcS5@5`%}8@J1O1qos#bQPD}TE zXQcbSvrK0-4|8wN|UPIlO|WaFKv&`kw2IF$rEs5Pn2^pG6OI&1Lg0eLGm2w zW4V7)o_sTQuzV|ahTd${;|$zIX7vH zJRoVTys^$_^1!5V@}Q*g@}@eU%bV*=kUvhEDCZ@8A#bTONgf?HSsoMjrTkN!De^Ga zSMomhRQXfaGk8#hJ2PZ9%ce)qCZ;`yzy;$DpS|T6wEtOY3xlF!{8N3Sh#Xp$Aw^4@O zaj(SJD)e`?JkhmA-dbm^{Do_s{3U9SiSh<{lIur#wQD16H_3P1oAI?p{?ql7{H1Fv zu5FX=xwqqMhy0amr@Y>^OP=cbS>9G>w>-_Y2mX8I^U^Q!CfBdniT24~yMB|WyY|a7 zTn7;UAifUCquqz)Z(K*@bH3l@g6ooe*moIuxFRod{VmUPT}9pX4|;n| z{@!&Rqk2Q$iYjRj>ZEn3ly;(4y6n0u@Auu4@3`*E3tTx>7P|UX87KFza>HvO2X@Ske)W*7BZBpxH35fudkJW*|M zkAnRdg|A2_`$IS4f2vK#chrll^pA9U*`K%&{!?vwzpGxu4H4K>d0sHU6V(O9 zo*p(Y6<41GJurp`YSe1bpmuE+|F2fPxVQ!l>eh>mkl{__wPF$9R_{y<;$6|_ZF6zzJGS}?3pEH)&WX7v&)6ew;^^-9HpD69i_xGyR-@phr&i6=s#{p$!9MW!&l#s zA>wv40L-o_{sPNKR(3Q9%x;+9;rNOD8G)excsv>i_R>UT?S&MvBg_sdRoHyZ>e8{7 z*MoO_8NIr{*{fYwS2C{jc2#>Pwth_8=2`7~b?@E1Q?^Tc@8@cn-KRrV_qMfb){1MJ z*u87lKHaji-)-9_v2CmF-MjQ|+q@;dtyTBw+6|tr9apPX&9-l3b!(g2y?6GDvGvt= ziS27Y-JwetkLwYTDcSG#=-45vi$m%3zrW+`uD!Kv+rHPkJ+iyEZP&Y7t+wql-^j|w zU8<+sJCqLHdpneuvmD9`j=Few(V^gNXRjW3#s4P0@S^{X+72Zt72h@YIh2%l9ZGUm zw*QT{lG!hdr|*62hKiEh{r}+`VGfBm$Ozrx|6%CB+imqdwvy7jPVENuW6{Bk4q5Hq zY~Cju^Q&g?f3*@59SY{i_VJsnAy&K25}#BNpLNw#NI$SLGh z+v@7$Q`)tn>a{Z8#s1H|(8n#STl+43I^Z?|jbrb2ojUf;ZrA?pr#m}JJC_dcIr^zj zmUTK-{_c1GRCCuYlVo2(n<;Aen#ZO`JyRq5r`j$5N&9QuPZ4EyJY%~9Z)9~>W1ruj zez1I9SF@=V*T3hOwerIzS! z(bU+_x;kF_pzWL0Bm2Ht{QWZ>_mrvo?~_i;Q6Jr`Zn!(ttz8#wnRdx~Llyd}&Bmyb zgKp3DEc(?`ZSr%C%bZEHog%gYsKG1zT5IoD%_5goy>@WocUvF$v&_-v|2nv^sUUD> zm+tMmsL@;J{{6CatpEMP#ZJ#?_UN$v5e_Az%CpaACN{~eSu-&`BRwHLHL*z(NB_c( zD5rBu6-Ul~b|2SK=3sey6oIX+wDavHEyfS{k0!S?FZ>0!oKx`3+34t8I>I@&zVpH5_~fg0mcchKvQSZ`dJVqUnQwRe?X{eDn&DwL zd?Sm%cTXedtwzq&1ZU4QXLg!X$%uS#xM?3)w>iyCM7+f!?!uo{%Nf%g4?9`Js4wa} z%Rj@yDH+ZO#~1^>iJSPrf$kvCT^4B1Z+O5@OE~JkUOK|@;6$Tq`_3KPzs(8m!!bw3 zS4;fqw47hznDlz-NJmuLScg9&DZOROW|_U;R&$@nZU)1~i~6GKkc(p7y&(MYl zFS1WX@LzGq9&bV#&heZ#wQ8lfBP(8A^O?P~GxflU+-yU|~Vi3C@53_18 z8=&^#OCMWjpz4*??aj>Wc5ig)h$k?4LhDJ?Z9xqidUkJQzPm$LoPtmTnPNLZv0KOg zWOnPrezhN^trF}8F}ojyfY_?K_u^dRVe~OGnkfY9-Mv>f7j(fUPi4Q^ym?ylq|A)? z7V&K6%+PcHSYsp+=?_j`F)ew;9rwz&PD{s+2stoY98ui`oemv4_E4QTbpphOsA7l9 z_s;rn$4sP#ITm;1G=xas?pYl&`QM{)?7WRw!j+Py>n|EX%Eoigm6yS!ko=p`L zv8XfKckPi$fBi(WO+%DVRMFMi3~Qa9)+VV%%lKw|!q7a6nk_`j>Yd3_)scNHpbc~s zLJecG;{?OrowGWz-#)47Jqe>vRlVsxbw<;U(<(lpSyEss6nCs_qEB5+Jf9zPG&8w% zdLm5pj$alAm#xwc-T%`KyKOr#MQBWuAU9lIhbYq^yp_)Y0Bq2Hf#YZE;Y#X7%c1(hv zN`m>5l#JL159!lugEnGq(psh=d0dI_3u|daTP3!_+(m!*D;teVpNB6) zOTVXaJHtZb1Nk#@Gg^hs4<4yRfAb6)r*b-HhZJ?)vqD{4?>w(7G{RQ(YZ>X6#|Gt` zW=YTv^{^hjP&(`ai!*p3KBC+Fr0Mt*o=Zw>g+z4M2lh%LoL{V0GcGf}S&F|!@Tiv8 zoi}OD34VXGqRp}3VPIU(pBcvqZFiWEP z3NtmU8$Qcpr>VBE8elq4#_&hIOw)u$NUIz)8}OJk zZIj7QKdk4-aqIA%4OT%b(xX{LwGg_{tq=P|HLzJtQ{^&Z^|gx31tnY7m2&y+Yxe3P ztoh849fc1|v>u~e;F#bGtr|gY7qY{8!FPn=NXjggvIvvWK`Gbz;8)jGN;V8kWej9d zZAwLzf5ws6;-!pMIHd6DYOl;*9r1f`ySL{{`2_6duyJz42cP!cx_4mf)$9w)8Ez8bkFmJr?-p@VE8!TFBnj8cm)q1LVR#T~qUYU}B~XjrLyZ0pe2 z-r{KxI(QICSj3VrTqNz&n|%Z=`+|ZVRo&BSbf`d z=@T%*ttrP+wcqQ_dKWaYWA)yZ=Z3-t5xhj=blWuvL3Jc@`MaLWW_Q}KB61yiP@(v5vq9E57=l2Agz+(ju(>DQ@%}nv)1f@ zeqUR$#T`Fr6d8CordCEqoF0kVw7saOdQ0e;9<(1eqUpF#m`WY+!xq_rIl?B=N;Q)u z%?5>!U1Pm-<@HT1Nan*e`r)DH zIB1#iTIzLkL*BbIJv$M6@~iKNg15)#beolY0}0wkgX-9(y5UljN-ttQ zKE2z$X>~?zSJN`re8hvor|THGV$l{vil3ro|3zI82enVv%&hE=UGd{pLGLzpu|XSK z-;s!aU=aMKYzLP1&nnU)lkNtI@f^=KM-MV>p`(vY)#tTV;s)?W^mJi$cIXqRG#UZqAT!x5Od2Yq^}~A=UWjh1V})ZEFKLzJ3y9#uC47*RfsgwfMM}Mrlf$0=|Ms81a!ynQm&5PMx##fLDfwy{)MJkq zjjWRMJwtkMZ5c-?f5dmO`18@@@Vq7dk6sy@to#t$%>NL+ZxO5gS?WUQc>WKudAWJ6 zr}A?9yYTn7@z_lJlh>;v>9|(_EAH6>k4qAISKLKYmv1BrqPh5_ia*SnjY~Fwg$i#q=EE9Na27-w$ zMu11}Rw6)ak6>qPvNjIwbonPBFN*CVF|_u?_M*GHsk`lCSN1Owi8rXMx4V(=iEP}_ ze~kMlu4YZuzcc=eUB&%S+((L&f))2!C?2q@cod39VwFQA`kp?+WY*6ke1;t|=nFIK z7^NJoy_BB@&dFHi1mWc9I8_SVcIz2w0#n-J%U1U$x39LwljO!{hvW1kqbvx-we*mI zNt?A5C`D-PrN|Ao%5h4iIHe-7wbh5JA%m-IK&r%XD;nU0Ve}9qT6>I7g0Whh5>0>u zgI88H17Ea(N=sRF!a-{fr#5hE#wkw|&X8c7ng*PwEpX}(4qAISvB0TMEHi_Tr}_qE zZ9d1@ReT1D4M}k}^bn83>+>Q&QuUWa8+qb0jj3=frJgu`53nS2nSYW{tYhta0Th7tGq6Skc;JZ3EU; zaY_pUoeEG^3g$e=KwAMzC=T;m80HJ0C$MsnJ$hdtEVN-^jn^ypEMUD!OhV=UCIGgx z3NEB_e~XmS+EeZUtf&l(+0I}#-q0<;h?pL(-%0|#3EMi*%+K1 zY|db~c;&uRCBUQiKSY4m9>IHYR+W1|?0phLYfmf(-TjcdD^%_uBHugNxQA5k{p>0Z zgkml!3YB}Vh2kK)il0DnNSu;KqGIJfgwL=%gT64shEdAV+DrKu;Eak>Mi7ozxsL+G z29|bSxsNCqYb;@*wTCqcSQF!v&k0MY+$S2SJ~vQl2l`~fL2D0ZI&h}NDPIweP`OVt z;Cy9)GlOu@+QXR*oLR&oR_?P5(!#X)jtJ1&BbX0@c|;&q?(+&JSU?15?GfaIU}>DP zm>`78eJM7_U2JpYmHT1?l~(C2w~MhJ7;EE{)p5#7A`vS0wR}OZ27$PiRvMVJS-XK! zgw|e)wu5bJoU$cO*+gt&<-XN`w1wktGQbHFX$LW)wa54?82830y9rRJ-1i#zb{nX) zln{b`{S+@f0Zv zmHR0unw4H>sjq15_4NXj&yliNxt}vgV=e~DkBdZr)*itP5L}B>uEr@>h(oO0uZi0V zD)+0n@-y3Lc;$YjVAh+&iq;-$gg04nc$IquDpu|eZ%A>Nf6p*q0KG%4-0|p*^lEo> z(1wNerCzx|0<3aglY8#vym`5MSt$`xxtAwpwDy!MLAjz=d6dM(%Dtjjzk%|okwd*V z?|p(m(Aoo$0OBSJv1WH;SoX8o5?r$%P-}KPdSxO&YmcCs*Q#a@h{cc?T6vg3o=t zUP?Avd&!Om$g^JM83GZj^=BcUE8J&)#tJBbfY90ldJaITUL~1;ggQOdz>{p`!Mb#K zn-UIMdpIqCli^j;2}h{YGYmNC7C0>l2dzDv7lG4;Sj0NLjZs>gDld^XT6@~BLAxz! zixqlXEA33uMr%*I6SO;cl{ZLUsLeZI6Flg`EeqUFf5SkcRWWbc1?T~QZeFE}S9yyV zgsQw7U$R|5Ag-CW3`|;y*^`ok)?RY{3$}N>N?)&%O>AOS{*D2uFUQR`!fDgyJ)%Qv zk1iK<{k+OYgeKJE{S0Iu8F|zNJ%Dh~+QS(NoWWk@W5N;Y@xcb1k1cRMAsn>!a7F@W zII#%z_;7==Hj_u$Rs0N!V@Oe`$Hzd?te_f4eMM`puM?sCIVp?v_~!;`obrLv;tL`` zYmZ<$2&Q?Jue{2a#39z>)AX$bmH1cq{t(+%aQFPng860;A6k2S^T0R9tIQ@iu?C+L zTI}V|Hp~%}g8S7P9FN}b2@CDN#Y)1@y}YLW%*&vL$;yC+CiVA#hIzTao7CSQH`FSB zwBf4`gX++R%3u-}Yww{A_1b%|kwM$NJ|zgW;X{lD#7H6#>+X>a^9CFZt-Ft@bvGWp zV@Mrs`0C>uTGiYEq0dPOZTLcy(9Ma|O`+bNi0mFSskbNFQJV_2DWoRU+EXmlrrA-O z1+{M)D$_|&th2x2^Juz3o9gUuDZyyNPw;#|%xkF3AqcU?o(E~MUYKJAvw&dGh7YqG zFv}V$O9)1&ua_BEmKa&ox1G ztgAN~WwkA43+bW_Uv~#|w~?+`Q*X1<-ATG=!`J;4x_cWcyGdH8r}tuWJ5KfVZUco@ zh3vB~ELnvs&M{zbvR_+srP&?l@sA{t|qLB@?!cdE9q!mI!-5k}(ybvnVNGpWU zhTq5HP%TEPV$EF4Ad8wgP#TmVb+qBDKMeJAnLUm5n%QOGz`QxF)~I8s-Od6HAxJuJ+ZpzZf)wW zP({~9zAu_o(e>;q#zC*{1coMvg~KWXAC7%Ppi(AvX#9$5ayN^`;zDr~=js=0wmt7uvf4qAIS zF9GL;#!73#5vuGL3^=VVa9$=HwDxc^f%7V{h?VxM25Dj1yiNpY?GbbYL3<()Ywq?1 z6Lca1wDt(Pg5d4ON)|x~)%V-j9Ivp=k^iJgmVrvEX1dwM_zy7pG*)^yR(cYNP>1*7 z3%WN5#I@AZz@*LEcPK?@?WL$6*gk5ke9%~VkJ!Xo{38R>2ORf31Dr6C`V%8sdyGTC znAcbtM1Vq7o@d}2WT4VgHk5GC+QS(IoDq$cPYFk;%tsh-KDEFZO*m-n;fx2)XT%~@ z=bssrwfX$HUByXIoJfj7g+39AW~J9;>ML4%eVq#BDWoh`=~E2Sn2Uk(V;T{lwMXzB z2)=Es%xtX8AP%uo|5n^qP_NI#m1}IH;Xi3IqhQuK#ERA)>k_aoYOE|EP_c4f6j~hS zFEGp(KwnTRcRYHR5*FHji?yf;D)%4t%DrrSvhq;8QZimE-hXO>pY^|iA6@^D{pk8b z_=)sfH-vAiKOKGBm0uE92C*x*)GN2tf9aU#X8+O=kKS_eT3L_Q9@b;Psz6NJn`r;| za0ElDpekWH0TTcC@P_`64=dVLbVIRnyi$ooce6yWe{4FMsaA&S7&r8COXOEF5P)Wk zngTp}J(L2p_EHc7psMjo6$09)1C3)qRRNL1fbh=%s}v0MBmtqd2UH6{HR2V8fDQ>j zHG+VYf`Mui5L$ac4FFV+Xnt&>{mbOfS$66f0JKvlmXy)jQ*H!hFDYMua)QT^GnpxS zMdgWZ{F`XJ=zWHi(b`i^gmQem@+^rv;+|>oeHkzrrS3YkcLuBx3L_@-@5i z9UAAPC@l3xLIT0rCN`l+=YIYbg|i_9i~~%W3e@+8g{eP+k?U ztRQjW$XdmZtQ8^#-y+xAmER2cjq%EQk{6DwjW`(Av4ephS?et@w)}gHh3s9{4*keF z4UCiV%5lOFkF1m6*vvTik#!tbwz4b1N7i*rL)sa$hu-60L>mX1$gvcrxc*Imx6l$x)ZP5A|Ua| zx&w$G>BzcOFwlJhLTeAGZ~{JYO;956iEK%6!)^EkZ)}}}99fUr1*i;wN(o9u0uYX@NEdX400ippQCnz2Q5RNQ42*6_jP}MF# zbpXVWx^QI0Krv|E^TB_L1|O}x!LJSFnhDC&BrY6TH52rASx<`?{K%?fSKbTx*aW2> z$qPqTYyy7jpB)VR$f{?7(eU46)Wwg#O6rfl?gYYi(ieVl#CE71Ve>uYpP%ib+@t-s zxeuuR3e~*{%5D-CKg!>mpnsIV+rR*xqw2|kNAEsDK^s2GA)p)}4)J6B0~mpmYy?II z{lbV-syZIMhe;i6`0B?JtUkgI2puOOwBZY#L^n@RH-(SyPawyq*f@v$qq9?X)c%6n z8B!BIx<6x~cFvC46{uZGP%e<5__6&ZKASEWw1wI9H>DYE_-Vcclp6`kH9`?TvcCa< zqb${*syDQ8KlfU}NVf?IZTLu$iOGsHQMpe@!pHT_#89I91|sdGk4n^P47A~+6bDMN zM5RcgR`3WP)fY3M6u}j7W@;!U2nB8UC=UUp6mf_j)0Z;H3e%(vsiO^Fy*$((CUx;6 z`iBcvuR!W(!&k2i^-76KMFJ2$p0AXcH{dMW^!Uf~6%9n%?PZr8gcu-HO;oBRDiTo$ zAI(=y)Q^BFP#4#XWZ==J#gmj8wBe_w4!CM1Dm4-ng}B6z1SfnX?=`T+8i=%1JwqsH!$z?ZSFR;qvnTNb5avNhHnlvvyv%;`iM6CKDL5t3sMz7f^T7v#k>oY53NZZ zZTRZ1LA`CF@^Yf`A~A>`zqb{)4Sf9mGOk=;8wvmT{l$VgGl>&z_?(@=*(p)!K#<}` z@11}o6m#6xce4YH&53DkxpDtRO*-Uu23#rt$4 zD9@k{lKX1c@#q~!T}K;!*T(>6RH8D1V8ok1qX2N3ZUT)c7-lTNpba193&2cBRK^pG zcmrrc5X|_3VI~m_+VEkf0%i)42seMG7{s+xWE!cW4PW&es7@zU;l|H&QI)^GK_g^_xE5;`@Fc%)*eHKJ)B|FNXNSL}fmS3pacg28qwN5MN?P zdwD0i2UPptCHvGZf4AqT^$_5e^ zZt`qQ)Nk@^5E1xIo-KBycR_kbqOz5wg&RCOu+a~|+zQ;_*=m9C^S?(pljwK8qaHsu zfN+iUg&REAp!PAF+aWi2Zc@(C{@a`fRPRIeZlZFVgvA>?cX`Qt+rR*x!5;QAW_a{E zeA=5%wBe%^^5Iuz`?PnQ;tifiU*3S>Yy^UD@QhH^@#rl~>S)7Pf52yTgC`(VoP^MZ zFH{QMEJ@uIZt#@!<>iiG;~a8>r?efla!@NnYQhbkG8SqN+fl0swMTtQc@h+F@I30% z-z%0kXbZFHaY{4V@Y5^-#qCon6N-3)#|?nNEYDd=xKGVu?e%!4qqc6{bl; zQb!xUdK0KOCUx-!Pve5s<4GND`0A-pPxdK30uXNSBxBPX%{D!LgU4qe(%vMe*+FOl zgbbgO?o*l(g>Zu>gD={2sEcc+nSn=}p)DyjXv0rUTX4PXQ(p8bZHP;}!Sk{K=S7a% z#sDTvoL7ktZTNg0!PnlWv?Dm-22XnfTRQ`hma0yKf;N1Vu0VO)r(_X|aD(S<14@Jp!6gT;Ra7ngQ_-nv+bz81GT=SCfwlZ3pKNn>0Rn0+VK1M0aV{3Rq+PT zdj?s|yFmHyA*rJcU;SgK5A-RyKBXTqh&Ol!irWTm@Z{pkIJS}S8$A6A=FB5bwBd7( z1m|#{GK?U_8$8293%dMahWP>D;jF}CkKR#)gf<+coVEH-{VW330%8)X>;(Xrz)FIU zDtj?0qqV2}1C;Z9%2E;+EA4!~cP%w=fawdh*2SZD1>vBzhqD$qtBFOdwpU|tX0Z7Z zTy1}&65!FhjtJ1&BiLwJaRfVBUf5XN-r0U*gS8*2Vt@e2l=a~3$4 z2?wn`oNK_jN-SbEe$^l?Oq=UOfYu(t9T40i09^${X-4+Z=gS?npAT++DlOdusxEbluJ^|5Sv(?KVm>C$8pOT;Dm|vC^4e7$LI!Qpp6fcdPH2&vq=lQLR+%6*{RJ4xwD;$r3Ao9}Bq4IE%v zsMgJR^!6njwDxe`1J1j|B3AD2VsKWlITKvDuT%-}=zX6E(Ap!&NwT_E9uVtCVrcD& z4McZysk=huo{N01WaA!Exev0dI0TA$q$pJGc@~O8?JACh;_xJ87>SCN`*1$Ph8gsQ z88(Vij@DkvKL^gZBxNk&h?V;|KrCcw=au`|g0UtL7Fv5)Q-L)lNtsMoLghZiKsDJw zr5)(g2nVe_oNs|MGfA02I6~z<(||L>0%tbiptXndJ#gj{i&(kOHAoB7Wxe|C+&A(Cy#WN`T3Tmd(q`=zN)cLnDcTLTT}jH0BxM`1iIw{<1JVwTyUhS6Or$-; zh}ItCK``!5QuYy`P`U3n@a;2DX(>BIIB4zR`~jR}Ny_hpBUJ9k3^>1A;G7^FwDxe$ z0Ou632$lOOgR(ZC&)QYI0L62pC{*s}plDWlU8KIEwb$3bp?sN?#mfD%K^k*0P<~t` z0<`uB?tNO71SnH*X`0eXd6x#Q7WG+Db@fHo|wrF!N57_cf3lTf)=0Kg_zN`zGI6-gPb zJ!LnPE8}PANnEVlD<|tWP%0TXz_eMdoAK!N5Dr>POy$S|r2b(j&mHSSW z0FT~kM1a;F!Bfd3-%kI-%}P`NiVP(5d$(hhV#;h?pL(*`)L@KgGPBUJ9K z3^*+;a9$uBwDxe?0_SC75i9qX4bsB2d6fvz+9P-a1g{f;Sh>GmFhP4FKx>cSEf93Z zKM5cRp>pqx&2cx|9C_v5$v~x5I&a&>$OcBQWTglG#ukwXm3uF~pnHHoTua>yOxmpN zLn%UQFGU}M?fqoszxW$l#3okm?;DW*%W>Z^zzGxSBVt5rkMUzL4#fQ$0u(Cufd;-@ z1C^GtJiRBlwZIucIB4zRj0MhUVi79$(FSF0K7VFcaRL;_ zlcG?$kB6dJ={1r1iq>9Vzl8E6QWh)sNd{@m#X$Kng$U5vBbWt(Z}5*6@RzoTL#*7t z5w{go?$dGQSGLjc%6(eFtlttVT6?Su!8#v*oQFWg%6)!lahN~PFkb+@L#^EL=v_ou zXv4zF*DLppz}i4eLgl^z0Q*@f5mLEtB4xDpl($29D}H2y#Kp>eE8o|)7&yRmK&_kc z=-oj$Xzk(b0nX3FB3AA{V{neLITKvDA5#hN=-o>MXzdaFW?8uh#P*XIT6P6hS?i`0p|zKyC&5-NMTt&PWMUI5_i6^DXpSoz z;Dm`(ofy&DW2^(lS}95m0u(CuS_Zxv1}ZIObqNQpJ)DNXiAzx$5ROo}#~E-MSl~1w z9JKau;(_xlu?Us>vj$~tJ}1~!OopP56oty&2Su~eD~0-s)?QzmLOG3;#mYU+AdR^g zC_kDJ0a|+mtwGQ-MR`6&@e_wwxwjOz6;$reG%zwo&UjThnt=#eGeVwq-hJ|%NuiQTY)(~P6D)%7(_=}YiA(i_uQbub} zc{G$qrYOTnT&&zj@_lW%fdfqE)w&sv-Z6xO)*jC1z!^s@V&y&#gELqPsoaN1?BBHF z(K~?%(Ap!IoI=%#;huXy>`M|uYfo$%y89J%SE$^-LcWKfx1p8$*LD?WLU9Hu3YGf| z3&mM>73V>5PKq*{M8(Q|4xeGO4f?_i`<_yc)?Uh&0%viGvXF4Z%6%~)&I^_M!h*4u z5f)l|SZjc_Dn(gASVHB#%0RWkK&2h%YY7LfJ)F(J*_fhiARM7`-)O+uV1cuRaM0Sr z*#Vqw#3EMi+YHjewAo1nXzdZ~1;K725G(iH1rz*21ZeFM90I|C6y-O95GwZr*c^wk z&5>8`zZs~sO6Ra$jFZ4Pk)j+=QH~OcP`RJr3;H++#I<^BK^ z%}TG5)K|3j`uY%*OOdizxtB6XV=e~Dk1|An)*eAc5ImZyluuP2CJwQ3e>7FtR#3T@ z$CZ(6qv4hN!v(WGPONC{u~q@Al&ZK1RIJ=3U^TB`CDiHnu{v{d~D%2x&sFkMnBcRYG$ z5Dr>i&(_UeHI310-H0z_uMC{l{+52-w^>?dj#L7T2<}=vH2v1)}Gj6bax?j zSE$?S;<$no^ZG#LB&Tny{^)a*x54scfU+m3!5KS)V3WwDwpVfVEzlQinjr z%Do=2gyJy2j$yt4dV*THyW8;hpnli+l19Sc=^;q<)R>8yGS zsoIOBYnuq#@KsAewPdvUdE%hG@+mkALU`7lqC+aS}&W9 zKSRmpNpQ73S5?QO_YqP@8@~Eu=~k6`K&T=Kp$%WCGP+rbx+zrYm5}4PY@9=?beA19 z8EPI<6Do9%g<2ImYSp0@lde=HL9sfI;j^i#L0gzjPf?oDhM(p-K&h3k)F2eGGOq=I zZ&<4NPs7wG7^yBHp$#9Y5sRk_zd6l);T4(n$K1#S2!KAE7q>eUx^$e(|le$=mrx&dLJgK7%U;Ra>w@Fu8 z5r9yIx51`2pKW@)3U6f~(yEr1>>#`WgxAxR*V2`?L?Kk*uk%Iw8q~!#)7HSF&CvFg z8nof3rVF^@6kE1if-tiIne;B@AwoeW^Y#OX?WXv6301HRtrN>73lD(~I~ww?we zEmeI91#S2!9{}aObmd(_5vuO@3@GnfpnOOuXv0Uz1xi2S5Gw9|232kD4zQz^2em<@ zCRE#lpk`Jw4W>S#4Zn}WpgNRP#Y%gqK^F5aP(FN0>S)7P9|!fZ>B{JIWh60(RrXkM z+d!2)8dnyxjf7X(BMasnPn>AO=llwsU#2UQ2vV%DzYHzt@+TSQ2Y~0O6*eBdQwa%e zI7rpi3VR8V77>q7VK0LCGFA?RRM<;N6>a#cE1~*Bx{^=AVuk$!-?Q=!4B%O=*0^}| zt|An);iIev%39(OE9|uxkTq+YhyU>B=u8C|20}_-y*cpe@X%1C(a8 z;ivf+P<~HW4ik!4VgC+*hw@*9 zf;N1VD?quFu3R7#p~AjoK)GOn@;9NN4IkwOP_7Y&SYcl?$O_ZsCaI$hU;Q4`?~uA! zVc#iO{XVIq4PU*mAAfk+uSEE@8!JME9p%TbSzwzUudpNh<{Ly2zYT=aKzPuvl<+GL z5QR`-Kj_zQvXp?jxMm(O@MtsiA-{I(2W|MNc??_?{K_MKr5tgI6?O#!&LbSPoB>Rj zI2DNxZTNf=_}qS_GQkNIw%fo~*+8VFN+uMv;iFUsN{nBrN+?2w9b-VLYJu_;p`Z;P zr4~?X5Qk7<*D$DR6?SbqYW1O3m(+v`yDrqsN~Q+XN3`Mhu_09BNL8$`;|#KxcY*Su z5vijMUp)!xiGC&CuRKc(VuhV3ZX2ku<8fs(+emnY{cORU$;62^d`>?&oBNff1SwY7 z&4DBoboosU^Me7a6*eBd8H9xP-y$6>?{_}rcb0DHK#RX_pNE_42mQ)^zp_tb^E=B# zznr!b`q8Dl{z1Nx><87960KRCkiQS#U-97k3!Y}$;ynx)XW3Q}t(-CJ+cGJw z9IbNh<3E4poTv&ehu@WR&*86A^3^iVsHn$_MpnuB9>1pD@!;Arj#B;z#`TEb`7q;p z1Y8S|u%mwEhz^C9EBKv{*VF;mT**#z05Q#)?u(3#BskPM!i@m`lO#5_bcnD zIw<#QiJCC1jjyJDXXX5ptY50D9DBv@V8X5-kJ9iM#XQO|o1(>IuWB~#=s$x42h5&= znS0&$0XSyqtdEDLF}NtuoYR!#Aey38^K!RIHCg@x zrq0Nx^3b(9cyLBlb2w`DFXM{6#!^znix@HLx6!Q%d!ZPE3#|(IomHbx1mpkDaj8qy z@=xe#a~6-i&a`5X5H*deiT4Jy)ay?MOe2cN-ejiL$<(Qt-h!!m{i%RyRPor`%v2%M z2+i~kOx5d82TU<0cbRDoGL6(s@4-~PUNc}?x_In;W?G9(qcl@Th9gG3UOQmwDjw_1 zfN32vEu@)7z*N0nH(=VNcx)sytw*MXHPa}Vs@LlWOmlKD)r-d#V&)CVyohFA80PBr zIJ)joug9?KEEH2_psZgk4J>O&vft@#6%~W&<##r073uvOS22tI&PHMsT=zR0NB^PC zH*M}{IrTfA%|D9Ov`x}iQxQhjB>xXK!hz+aUQLKT+1Zgr%ug3 znd?)ShK|~J!0SoTr!A(N9w9j}pB-{+(F}DVrbLgezfxV}IXl@Nq^{Mc^7>1T)_BN2 z9kdah(!b9w(F}sA43y0I+9*Y|Y5AHpBfig<4V%0<_c1>CDt@u@8v1jsB4dE#cQ&Pt zld}%qEF@8WXLEJ)!xj|I=J&kc>1TV;^Vs~BWAiJSp%l+hie;#^u;1Atx^#v%PSC&N zK~G!yovr-N)_&&;`6V-Gn{s+$Wi5j*MwiP_J2oC2Qzw+)`I7fx)}NQrF`Yc=S0HjhTy=SkK-- z7ovNnVO+0x967r&uFcfG=%z6&YAnT-76Ap3>wmU|_^wBF8?d;l8CO z;ZPt6Z)-{Df+WDo@9ddh8d9vc{mN=50n7QN@)!(9H`Nnqi3{x@XZsS`_$9$0*35O}YoRRNj^zSkDtd!!neSD{Cg zIwjS$re<7UYwxpB)5HQN8dj}3bRS^spTgK9D}LvP$cfe|t*bG3#qU(N*Pv``$9+(8 zsJ}V=FqYA`8m;VKB+`*{$TXvY5e+&Vc^7l~BSMgpW<&kfv!9bI8bztq2kX0bMge#L zvj|>6uGkuCPX-2FAQ?o(f{)Q&9>iYO=6Aj}5_nlnQ_jZ$(ZKS7R35I!s4G8bFusjW zP0+gkdvN!)oN9AQ9U3;v)X`cAAN@&5_6^%+bA~XnVE)Q+wZt8O=v}cjF?M(jPD7b| zcA6%C9P(rX*(;uAO=DmQt50ARx(nd)FkDtQSZoU6Y_K__5dd*Up<&yR`W&0>a8$tc zGnBd+N^O0!%^9Paj@25r3r5FfTM&wR@CQf&ydf_HA!>`3FUlE=u92`UK1bl+Fr5Eu zU9gVC>nkB=DO~g?fn_lhSH%IrB$$<64(EEr8+UjC7?e7?FAnml>X`y&#=ZHqM`vwi3KI7-Y z5N9Xm3^FlK^a>g{tye)%cynWbsHs+*s)%UG-Ug{>R(?Y^lZ$Jst^`%2IqY3$OrkKY z1Bs`+`-GQ+$pWbmok9;f4xvV@9E*tP@_ez&S_o#Ly%Y2TD@LVjp@u?3F77MPx)G~@dpo7}L=M-%;gMt-`!BLp_SQ}Tk=I5lEGvfb}@}Jjb*v2E8u_3r1)ts4oUXK&o8o7cI zFjqiCO|zD(47`9B@d7)#g0zByXj)eDriD6h)Q~P76Y*9do|=D1gq8oz2!J>n(Wv=n z&yoL$$p0%D%1ar_3w#K+Xr^1yaSigXsaLfV$NL66UeC}kI!j@4HjTl>{MT4gg7n$srIGW*w)_8x zI}h+EsxI#DCIOTpf+!#&yE{WDI&>u2(2{JLglt|?R74|EB#M9#5MNs$hykU8G-)D8 z6{HA35J5x{M5Krm5fEw8MUeje@64H-y*o4cUU$Cd`QXW%?Cd$`|GRb0&TbMo zLIi5NK$mp=+j8oV*3z5*Gjie<4O&|d)S2PvrM)<%HAEYC^dHXt!W`L+E%vbZ##XrV z%cxoor?Z07>HH$f(eEWkVYnka;x32Nk$=~{4o8Ks(&5f;xXZ>UM{d`Fj-gKYM8GG{ z>HNwnYAcWWF3QoR_se}c_wD8=jL@?`sAu0neyY?SJaDKqJA?Ap(Eaywm%UalN4WGM z01LPWtzu5`nB!57K6!luI-*Z$FgcG|MPA~O=glL}T18&xkyp(l|F(*BMC+q=%gUuR zcL|Rc2bOo`J#f)_yIi!Rd*5!|y7%wZC18x2q0gPpyRE{jafSP%4fEo@XwzP-WR=Xr zlhrbhtZCG!VU_F=o~*8UvPi4QraZEdd1M2t$Y?}ro%xuROKYAyCdh@awRrB**2<+l zcX_;oQA>`-qU-Zo(1<3fBbsQH`U##olZBhDS*No@P&A)TFY@RYf?V3`i}w}o(#trU zJ*}c%VZ>^H;<;ixNC);Ti`5TWsXdb!WD)J9RYMpu1%H=dq zej><)ueI~s<&2ffHSThygi*U}x|RG#9nnixsl&bc70Tf?*-F@&bvkbcMe~(el}A_c ziWjd;1gh)%VeV4HYq8W6;DI(Cj|AoIsQWkNE{&{Qyj;2k zfQ7B3xm8RYk7?r#x}JusRY@zW$aXw3**r4QDl&sdrkh8mSw%j@BeShsa=1$;E0-7G zqV;xHuUS>{v^sU3w+erSEA%qXi=O5!deJJ`>pa;&^T+{4jXbMlLwK@5=E>f+ihQ3( z4l|E@*D7)>BDKyOW#uxFCm$c=!q?h|+-0(r%Utd ztEfkKRNdAlSiSV@jmS^kN}A(=Ho2Pwy=@-(rcvW{t7Px-WQFF*hFV3AsFxZR)}@<5Ka%pX?5M#K&aMv)nXkzdj#C5EYw{*JbSHJN7n$4@oMgx zR&n)tTpckkUyZA671xBvH8hJ;tm2}0TyrazR@}vF<>G^j)*-R6j^6$A0@|x>M{R;4 zXY2jcjz=b&MiB(a6?=*^ z9S@$3->H#DgJSTDer_E)}g@s>4N_jSs|`?u}J~B7f2Q$;BgUnn%{KimbyU zW%EdnRpg_*LG^-Mc(*j=$s3_N#o5@vDkz2rMIk6?HXcyNuenw14$kyLoLKZ9(z|Le zciA0hDEfC=Mg7X7_Q#nN{m1p}N6AmU_@BT7Z9IkAD zaM60ZX1rO^e_CyL4Xg0_T%k_9VP4cWZ;@n`tQk+%*gUeKQA4px)`}hYQtQlQE0=VhynT=hUu#+1rGu4A4tMEP!l-qOH!J$jsU!NNRq9-xx;qOG zzJI{htkc;wD4I{ow|Vp%h!(2*%WCAn_@JWyDo(5Gekek<&MSx)FBsQ!mk~Vs@Oa@u zb4SfxXcaes$Bh-^E~;^(t>UKfxG83FldR%q^SGH-F7vp{94nV4aM3zsQM~DeZ9!0^ z6CXNMyYh1$x!gSRGpopTJaUbBk8ETW z8N(x^tXyKbOKU5a6u4-;o#->Wu-&IN+-DV@!4=Zc%|V|COEYg#s#UUQc(RV>kxv>m zvaOPJ=gGR5C+ln#*^5WMWFDDo6`6-ftutS-a(Rs>9}wii*Va%TtfCTC+~)h@fb`GFS5GWkD_v>WgXBeON@bfyGF^ZC%5NB0bJ zX^cR1eGlL+{fxu;idEDbJnA(wtd@HALFA`O4aEa(JPLyHw$lCI<1U3(E@Qd$C;$sD zw?|mTOyMyTgXd6FwFf6yMb74tGtDEXTSYG9k@L(W=UPR6#v?zqa#_V)R#>^Lhl|$R zYfUF*Teab9tirc&h0Vr!vB|te8?BP<;>mWHM{YN2Y_m#skSE(`o@}pG;^<9bj#i3N9$yUPF ztkW5uC|+9l%B;bos|C3vAy8f49_~^r(Qx&tX%$tMN7XjNO4G9|;5gcOEW8%)?7LUz`|A%Z55NqW8xEouBXXr55`(W`gvrkdF10(kx%f*O!LSNR*}!} z$c|PnUAW70RxU5WMeFSziDp$v2eskdt-||rg}%ml(Z{?+y{wYG&6B-h9{FFR#z3oN zg*@3i=E(}IB1iMc5$2KaSw((;NUbx+S-DK*$tMN5@U=FRyG*lkS-@RBDPh#+utjHh zfs?I{=xnRhD|qV9tk$g4xg;o>ugq_G^rj$}r}V|Uox5x`4(ArDsNFp3Co`<)^z8e{ zPu)rm;ej?D2ZHi;*8P9yE{CmLPIKuK!CT26Rxy`&%=zFs)KTsKvsRHec;r9kkyorD z!;|!jfFmhr`_eRTTSeZ@BTFZV*9hKE6}d}!E0?Np(R#Z|lG#?$Rc&}>t8h10csR*$ ziFwGpMGsmfdxR&eYaSVC)R3)`HRH(|n^ru!@XBq}G{jtXz_Ka$k@O zUu&t{CB@1mo4aI`FlzrvGTTaes3YpPO8p#9{R|5aeu2Z*tkd~)P&A)$BY5=iAeWaA zsIKqv++~b$I7eAUP2o`!&9H{)*=LZSD)liQXyY*}DDQCHe?E7aYvr<(OD_hnP?apS zidoHLRtC?Zm(?CzZWXzKM}BD@xz;Lj3y<7v9=XXX@<$%I&B|pDciCy>@+(}l-rjFI zDMzRc|HUf&1Xnm_oEJyUTXfhe*+ri0oO$FKqsD2gWY>AJtLDl6wu%f()_3T|;e;DL49)armp37ZkCmXIlv#g>P@u>M`SX1=upOK#`^*J7B zJMIPaihpb#qaF=6NF6ZH*_4XOlNjY6@_-U)~Yh2-qab8?DZ_y>IWZ^0L8g`_Z z_Wy08#!aha<$1EZ&6AZ$5m!5(T~&BwCG*INR*?@PQtQmBRxY)8@`r+4_*#>>i`&Yj z0e5*M#cV6lMy+0o*;ewAI-+%~Qb+OB%~^QxR>Ib-)7dmAn)lt^Y5EYBP7}L#4g%Hn zeJ^*ZkY?CQ%2`D{z@zR4wDG7Jl=oBJzczRASh+mPrRxD$*h=bH z#WdqFjnjgr@+WE!HnfUt#Us7ukx^EW2|O~+JhH7-WIG<2Y~}JF?viHZ@)TUO-p)=l zo0Ola4bQX+@4^+HGtP@=&0EyTD%s0C*^B0pJ&YRNt&$Dk$@-Zmd&Mg9Egt#0dE{$W zkwXxvb><)|mtj2l&>$DS)<$xd_pDqdahC}tjM_N1=nVHtR;nX9#wztkJoOB#HS2Uv z3yS6|a}|$X5#+L3U%X#(moJRNS!5NpiAQZP!}?0kzJ>hMtzXA9OW^;1<#>1YXARg75OKRJZTr+$Fw*QH%AP zZ6)8SBihC)bvjSoo`nZjC2Y+)o$Z36`F!}5M<4JzdUoq2T*LSIg-P9%phLH^?8$q@d+0vQ~D?|1!)v{mT zbr`d&Pe9YRsa<=>@8}$GQtJ;-TL-rV-qG* zn`)DdBwL4UU1r0=!|T!G`eYv=`>1Ba8_?s1WE+uf%xoCzs|xAjY^v;ZmP;4AZ;#r2 zcc%;8w?myy&aldG4(O}h%s1@5bVt8{lUfH>N!Kb*-h20^tNl{k(dv+dqj$9b5$KyJ z>YMm&aKy=Uha`sD;~ zGf&YIta`%zd;k5X&$b_QcGIP{MWdTH4u5fOuTuC8e(~N;S^c{8?bm5wx4yjxcJg)W z_flT(KAp02`}ObKGpk$oTm?Dvy7ldp;A^L(q;wkiShG$Yy7lbVxnH+Vy`O)vlfO^5 zUj6#@OwD~h;M)d$x<2o?bg`PF%>Cuxb-(8x=3Xd&?q1_w?cOMV?cU?w=HB7n?w%|E z?w%@7^-T9H^Q`oo@eG#o+3yz)uY8|N$}1>8w*1WU7s_8QpYIyt8txkD8t0nk zn(3PDn(Lb9THyNBwbZrBwZ^s9wb8Z7wZ(P9b=7st^)BSzbB}V5b${TV7L`B z@BSR(YusN$dOO7TxPNn>cmD(No9;qSvHUsDdCw)!O<>HGilpzQt9L;6YD zDeaPWOM9ff(l63J>40=lIwbuj9g&Vo$D}``6VgfPwDhNRMmj5MV$sfrd%X8&<@P# za9o4q7izzJ;aZ2@`4Y$VIDUoW1{^oy__f++U%S3R&uzx>TO7Z`aSM*$7L>mc-g#WRQS%x`$+ zFrGVtXOH5!-|^frc>MvdM#fYw)@buN$s0uAA_@1<%{?yaUgC_Z8P5_f^+m_dl)z_chlL_jT7h z?i;S5?wgo3w_Jtp+pb~mJFemGe9WLh?)TmKt`Ybe=^l*vRNx-%9^xM3eg`vasC%6I zUH5o*p?d;m+XwF9?um$)gow%R5$-AOk?yI8_z)4(5HTGQGY~No5wj5S5h7+I;$uY2 zLBw1{eB%DpH4jnq5w!qO3lX&lQHv4vsrv)h68A*cQuid+XYR?aW$r1i<;b)GnN}jx z=g71QnN}lH5i+fD&vSo)ueI*4UF(qXOJrP+j9($+24vibj9k`Rb>AM*{>n{b!5MR>^G79mV2n{ zHoopaCEs(xJ;-y?J=k-~UEn$G9^(1a{f_5%X{hIz^seU*snBy=8s<464fmXs-t(N2 z-uIlAMtJ^|MtaUjqdaG&(VlbC7|(fWtmlF>&T~;3@3|yR@cbox;JGYK^!zPN@?4Q7 zd#*}TJpV{jJ=dfUJ=djao*UA1&rNBD=PUP2e9iLQl0Nd>mS%hINFRIhxjFZ8@CFY*-1i#@~SPd&rsC7$=>rJncY&padKWuB4pa?dDv zg=e(9(lbW>9AB$EW98MJadMGoyu8LULH@$?fxOl;QC{bnB!B6dEU))Wk-zdxl{a`k zls9^&$zOY>%bPqi%$4^e&jI8)h&;a{&mrXb4S5bD&k@fj@=@gZ z9eIu+&mYKh9C=P4&q?Gt<(Vg+_RN?6^em9icoxcMJ&WXX$amheSia!-RKAGsFX8Ji zd|k%Z-}t(MudDd_2Vd9lbsb+f@O9I(M84%&D&O{eCg1Talk=rz@*rusJXl&G7vO7% zv{HUY`dl6=t&-oBR?CG_kvvRVBM+Cpkl&Nm%I{0-3eyKv{jxeZIeHgevqe0+vVxfkMay@ zhdfjINuDL`ls}So$+M*&eIH9Zd~>9qd~>CpzE7lGzIoDa-+XD0Z-Ml)Z=tl;w@CWM zw^-We`&8QRTOu9sEtL-XK9hd+Et3xUmP^0+R!E0^E2Sg8&!wZjRnqUi)zUFvk@Sae zjda}ig>=HVRyyfhC!O+rDV_GMm;Us9C7tnYkk0xxO6PoEOXq!?qzk@pq>H}I(k0)w z(qF#sq|3f7(hcAD(oNr1>6UMsbVvRHvw1sa^N*O#JEWKPXYC4G3^sBVYb4Xh5`Au5kIV??E3hF4DWeqc)|tgy@ZR> zj;5ES_oM!jMnqkfero!+G%D(fG&<_4w6p0y()$V5q!9_%rCm*LNbe@xlnN7WNxPfg zmPRJrkwzut%X^v*l1I1(%X{4g@<`VZd6erNd9-V&JjV5|Jl0hxk8=%^&$@=o<6ZB` z-@D$IC%8t)AGk)!6J4X^Nv_fIWY-v6!NCYh~=x@;uj<@*dZE`IPG`dA@4{a&MIHxWC5NCV8Rj8+o|A zSzhG&R$lD-PX5%jMV{jNUjEg$746(6uWwvt>bx>aJ`W1N&$rpUT$(MbHk?%pr1NpyH zcQ`7xWiQZ+75=F{FZ5K;h2t3ROsOU~;DPFs+epUV#dEl`9s4^t!ap@nzt_}rxPJhj5q`k|4^$tN$n0Mke1$uwmQ^1F92i5x#x0^6 zH*)cRjhjbDw`kFF7H2%^4kYqHZrQ zKWE><_KT+e{JAGGW8=WLoR0g-mvOM?GT(GM@Kc%Uzrg-xCs=Pk8r+*@@74IJ&zT?V z@dZJCZ5{Wv4eWR3SF@(Wp|Al6_{aUI@7Yt4_m|so>hvVn?KALg<7N$-v}n*Ix^d%1ou1F_)hW4mzq}`-9#datb!pO|YtNn@*8?C^@?PuH zt!r*ihtmCjf63Ncdu`UKOW)V}RT~yngDwuGYwvyzrDLu`dBV{Q zhbJ8hUbpq_gJ=9N;0sUspKsz&5|Z&+a_wfbz!s+M2MsoF=>$ zbNB4gxnB=8d&40|2TbdGBz(XN<=!~e zZCB-H|Gv{{IqIXE+Y7f>dUfupEz_R4&#OYSvNuOm7<%JV&x)Ttb*Dexy7H-b+g-#q z05y5FpBwLCHO}$JJ)RJs=@{xP#R`V}0g%5cB@fR zLw;x3blh!sR!I+gINez%`~ zh2f>{V*QefWOrDym=ie6%5XT+fPe-$tEV~_WjXIzl;!ABLTr9*gsnY=!$+AoJb``* zzZ<=(u_VWZzn$zHoE#>nIh8agi0*ki*%2^4Ila2Qio3lU%PU|R#PXfHghL%%Q|jWE z%7yQ5=>$%TZ09|L#aQ-dG#rD=u!7T(KMi-R2eV-RWgM~)+@;68&amq(BU)rf+_R~j zpxUJ`Dr)?R6cQc+;dfZ<%_}%eMQr09_m*4u>MBoZ~C6+M>Aj=^2?FQqq#}WOLBqUqn=@rmNK!IsJ0~%ib5j`#|ui57l?o z1iQR(DQs4~pw*k@9J#UTuAS2_FGp98=egJDUfbe;l<;Iud~9lJTx@*19RBeGM}8ra zGk_y)Ie%($j`nLS2A5&_j{NyZGzL%7NuWxRz z7jp7CKi{((5RvI&YVHj|4VUD+emS_dVURS%nMm~>Q|v4#ViM%^>d$_Q9`$Wa_`T2k zz7Z1QV$-`X=b8kk5zJ|xkgQ+tzIj~G1)q^B`_+v0DeV(-(qlWswg<6O>z{It2V0{P z(fxs)H%fo)%XL8pXF( zek@CqF|U~Jh)c_Pxqr``S9|v@?(tZ(X^P5Fx|l&v#>e(O4IyHh(E0zx`&7Jh*u0;r zChC>|9+ea`IUy;b1Lo|@ebm|I$p295=5mfr+C0im$wAm0`1Sqv8nDb%dh8QH=MuPp2`Qp*wUr3c>k*%UX z@plkXK%3|4K7HeR_Q+|U&>kDi%P-^JPX0XonJS68a#BKCLI-_o3Pf0-`+li4L2wM1 zV*`YFp4$s=%d$^9Xv?+*X8J-ll2?Q^&bHCwHLhQO=D>N8I;bz1EDQSVo+E#;4%Wlq z6|j~+)x09G8|zCHP43nIWzNPn&?TzeS#LsidQN(~gr~H%*ghdM+3!Oe&(W20e@jPv zho{mr{W<@|uaoWFh40qwp|VuXkscKw6EGN`>9n4413RPBS`Xm97k<(>sS&s6HXr==v36ikBAv?jit3EFV2w zJ$m)-$~G6Xx@D~@bxIw`_P(6>%qNkB{aIrCi-;-SX7UCWPtI(JuT$gp#|HHtg7=^S zEO-|m`s5)xe17nKfc-f={43|Esx>}6D-QDl(hKz|u`yuR zjm=2LQ?C-$oi+|u7NH;e@Cn@+?fHrUO%Z_l^e(P0*j0an%JT~L2Hbi;cd{JvO{ zcq3W8`weU4L1FIUBUXKLyWyU@UPpZZzs<}qOUR{t_(ylbO<~8kD#zDmjSg6c-|3C6 z${mFbG4Oh_Mfd$GE};HL7yqVpaYR{lS#`}Fpe-x?qUJ~3_bN>)pDft30xAN2wY|?+ z#{|IAo)hto&~*07LFmSMMe9}rxz%6#ZU(@P;sBG__d};%Q2;6f={f1%Q@Z*xUvQh zK*aaLXli#nG@3U-v!8Y3Lw@#pAn>Wy5I?}4dflW+yr(53ILN%l3ts(uX)nd}iOjaN zU)5H-OXzA2en@Zl8E>}%eRBG|)a|t#wf26wTV9XeUA2`%l}kCtI<0q7Vw)RhfA?r~ zvVLXO$3I{n;l=ZF=8hccHyz2r7rXjWKJc<}Soc}SchG?AOTZ>~M0Z?eQrZVBlB1em zL@8s9(7#{j7py9U-_@S})O>ygq(7!(6o^%N0O=n@a88^;{a?<(KJ_v_EFAFS^*Eac z6CQKKf?wi>cyjT*RIBz?4+7!p?T8+Qk~M9HX&JG zW!h_=z`gmj?ljft#B1?9-Dy~GCvlfQb(d8%6SWt*#oIzT$E09|fMMvPhkp@J3*{uE z8lqRAXLJYIa`6PDJF9zt$}erj_wLvqB~=TuTP&6EVv$evb9#a_o&df93i@4*fR@|WHzpYruj7yAIg%evDV zZ6f&NGZTy#iE@t5f^!7yNPkl|2hp2V<3+#^kQs|YU zFQN(y3SEyD77TVdve+?I`@`s8MrnT$9X8-EqKBZo3CbIzl&?rUD{5U~K|y&(emSPT zF$yGE_$vC!zyYQUHV&P2`G+AditQjVSbJi-(cGQX+%8e;2A2tUwJ`Q zmasTzX@l2AkI|-&fgX|*9iyK9?l)$+#;4K z`iMQk`sS8FT9`JDXl)80zr6m@KO~BN)rLBJ%S1#C>O2VO%S=X zcpI}`C>LEgWChzCSE`%ir>>&A4OH3&a*th%s=&BETDdP;sYE0LXmUg`lKZ3eOU8X5 z5Z6*A1Cusut5Fxh+Up`W*lI;9HKUap#MVh4su%`W%YamqTRl5YF&GoJIzm1{OF?2?y35P84t+BbIrA zm#4=J%G!L6wyW3*iZP_PkXo;nUNKNKE4^A%TVd_BH4e&cNqG*Nr>xd##pY>SgEZ!1 zajg?i1hDo9QbF)|w2~aHBoaq&ogryCKHxWxlc7vO*T+z7xd|b18Waw4sd2iE3*hk zsN828aAsNH%q1LHdpHY$GoM(*%6+~;T9`JAhyd0e!Dk>?LIh&vzNBP=WkdjLkDv$y ztD=>a1R+%JtFSrlV4EYa+*cZ?v`S}aWRwfX#qUBy#S zJVA;=<$eN+W~J9@YAdY0ww{CX8B!K2_cI1*%*EpJ<2(_-+9UV}1XrS!%hAdu;t(tM zE8@0-%Kb9V{KPgIUb$Z?ne`g6!rEgE^Cl_|uX39}#me2`4JrHTcPgKG8$b`_gIu@NZ>HG3lq#in)@qoLTst28H3v1V_<=T>urKHf*c z`#xSTbvCTM&W;608?VxeK*Vaj4de@i`|Pc(fZ_-U)*jH~07~{Mi3B9n>B$D3L?aK@ zrNi5faA57>bO27eS4krrp-xXX;G|jLWDpLlJ)9?jlT9pQot|x!)~3o+qz!9N`&npr zB5kok?_{N&L)x(Rw7WyQt5lIcF5I%f{q*MzBw7{of?a?<0O;jadU}-? zi9x8!d+{aP69nR#dC|b6m6)$k=fK+Qod1GtpjR2-Rq}{UtjY%(kOpwvJR_VoZC)oj zSbKB@pc~{>-X=7m9v@^Nd)vsPF6beI18WcGJ>U%UD(@1GP>&BY;Jj;r^FHCg+QS(G zoKeIg)Z?QJ%GyjGYgh3DD2^vZp&lO(MYDoxBDEFPUR$R^c`_-B_4s6iG_LZ+rNxIt z0Bet64hUv@m04b8262e>_-uVEK_xy5-ydY#3htiID4B0A@xj{TTLQktUS%P{i8c7* z;9{?6p<#}o6x^rQ;5d4h5*F;g#Y({EUY=Dy^D;ChQ5h0rQhyJLDJ=NSr2c+4Myvc` zLsuOE)%RkQVI(Zp-tWcewf8V1gSLB(Bna5hA;tk>3=xQR_n4T%A%}zO?jvg5jiYxw zsl$e@J}Jhk<}MbROhT}s3r#~ar&2S8dV4B*_lQZoJ>8DlM^KwdYC^3&(?V^w9kuyT z`y@u0LxN(R{Ry8(a}3&4XD^@*h7G-gKLf;)7-ca*h&A>SNQ?EtVk?+s1Opp7%o@O~ zj!`}*7@@viZD9G_$f913zaSLY&`~x5<*OLwOF|K9>#qzbUs|AiO(?LTqkIRH&BP(r z)tim7+7`2gbYVl+-45Mtq$}3c+pKhdBwg6hb$^EL?igh!NelJ#ZftHxsh-|xpwOz2 zy>`S8L;O&Taxg~OPx?YFeTXm1gHRXO#(o2jR!bkDPJs=*Q%-~HWQ=k=Mma`YVjX?b zfODLq9y5Yz)8tPggAJYRFOXe~QO*;VP(xodP@OljsEhV8p}>ZYasw#WVw9_dBGk{< z3@BGEP;L?mZ0IP?mWj$8;t*=*I|fy4)`qpTp;j7d5iPYsNT{15TACL^Wm;;55Nzme zEC5MyW-cxb%9A>5=<4@F{l1n;rIt!XVi4=)`&!agfqJA~X2Yp7o zW^3FvZf#O8*Jxc>aNML`ez>(ZO_qBIjp@dPXiZ>Zj+fZx$UkY4YoOAqnO=4=UIj+~)=IzD$}2=7)ZzX4g6;O^*Az0Zy1mgNYH=9^-H@7PeM~ z5};6(7aI768mP1`dyjBn?ct0C&gj<4NWu{+^U(&Jkrp`P2nW_4&LrS`KrBLa{((VR zo6nQ&Do%sqR8kZw^r=uZE4`*uTVd_B^&=?HBxSKmpJ|ZBTr4g>W)lIdJ%U9bSkPLT z*IJoN9Ac%uK-^YPug}AoD{Q0TpEQ|UGV5Yug|)}}IapV;R+bT{Sh=qVE)I*98RiS1 z F=j^0&-1^aKYR={G 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

      p;fX4d4jLsisJb{5NILs8l zOd=%Ai$9Z0;`&)+Dp7?kxav%(PA96&3qR9YRrnUyx_CcPkgbB_zEZDYazbcr>r94%!@s%{lr(< zh_7=Zz6s(Rh%)m+&jzUZ?K^a^H*K4lM)W?tagkBvSXb1Ux!o;@}Q2N{IIu63braV}R0m&>&}l*{Od8y?`+;m_md zfmzSv{rM7wa6j~|)MZmBmz1F1c1pXwxQoklxi;8E?WR#XLOJzT4sq$YGf0q;{S71g z0ph1g9man+jpkrL-m-@OG3s)}&gB%9{tdtk?g_h?i!|n3D5u{D#6VSVRpWB~VHbIe zMqam$ylNNukVf9Kj=W6ApH+Xc8ZHWqIhb?Iat&W?6bU(%=yE376)_HT%vwv}YzKl*rl8<02J@b5`o zy4$(*r_y}@%xopS?P7-0m?434NWBw{%QeU@ay*S3YaKb-E^<1JoMIh0$u4p(jhtoY zvY5Iouye_Ui{9HSEGK1Ct>Me;!naU`jpli=-nvC=?UL=I$#z>u?lfy`w@Y?}COc%E z?4VubNg8>=I`WuZpwd>U7ik-^?>T)-qQTx+!EBQbh(OY(@ z3weyw&ojF<>vBB}h^8y^H5&bjhdp_hgxiboMD@7bVds-ea-DeQ0DaPyDp4 zM8SXb@u(1x_ano<3U#Su=i;W)H2}>}Tzk@c-3>)J&& zqmj|pk&W#l+tA3Cb}pY%myhjS+QCKd?Rbw>Rr0Ym@#5^l)2Kox^StP2-J&GBWM9){ zUs*?XHfv}3}@1d)1Y4zzO_Ns|u?aG`5$9CaCO=Q5qT zOvz`|CaH_gRF%YNBRat@^+K9@p52;tx#k2!)0Npf%-D#s!`Q7P)>ym)sY|~w(^k^Q zE^0W98WLu)m3(GoA4B}Ktz-iJqmRe9fV^>r|5WNS$U zO6J=|uAz~utRq+0MQ)*y8?7VP+ePl8k=yND4p5i9b}mQZqWAXUFsrSktv2y~vI{>= z6;7Jx#jn;aI&PQj3Qcy=I`X_(J2crX>tr|VBA?L6ht`qz?IH`+GCK2_ol6n8 z=r1M&)v{S@#i`3b?Oa}?F0a(GAGMcjS#2fp+K9ermzt-k%c5A*5xW25KUL+ zzru~?l?`W`*UnhHZ&MdB+_aVOc2WPKQRTxeuu_cdA;eGHN~+^O`sA(>kT=!v_fVIb zb}n8j9S&e-E2(7{(~!p03lG>zI%qu@Wf$3uMn+plHnxlWh(@-yj%;Zc`5BG;#LlH1 zb&0ogNr8*r+a1HLCS|(T@FctNE>xkjd0u2#x9AJIWZh}9@2w-hHEVohm#iO6mSdf) zmtEvA8adcHa-d!07)0uwInvH$0!=?`m)WgZmupEtG+mjmdX25*WiJ=sF2(Pa(H@#^2`|@ydAJuI*4BMlgzBAF#>*vl z@O#BJ$8Zs8_P4xTf}h85Eq6J)xC%5bn2pQQ;@-B4t3u-{S;Z-KaiKJ>x}8gH>f*6; ziGqvXAzm+++Bws&z4~@kCm?dF(NFKw$OhJt_3R>>(a31)$i{Y&t!aZ=1h~-Q`;;dC z7~PqS+a;6N+eMe_L%X1MG$qeH`p$29E}@o=Q4@9jJI={ z2^W1fPP3jFQvxD482z+>M$Wa4oNX7moJKCOj$C9Hxtca;Wq=DEzD+dwdUPi{8`s(e z?V>^35fm^RH*4d!#V+;|WjY@?8+U4vX98#A9-|9yQrT+(+4mVP_i6S!?CdzC<-Tnf z_l(9pVdJ)GagXfcibNVaeNZH`7wd6_BH2Bha+aWRMeSTlQkNI)TwaHZJ{w<)wA>qC z4T${3=qH{=ma~p5YZn}QCdcJjY~|LEg+HX!c> z!~ZIExn$?^CzZYlV5aE5ZWr^I#yp4&DEd!nJ$TP9GRSAF0GH1)@|j&^aT@tg>&PNL zc1UO^l%$a_+PRdWE~V^Tc(~}jUCw7!^k3E*Ue+$W0#yk1ndZgY)-96kl2xP0DqBZZ zGHWPy$!gPN9_wVGc9C^yWTbUugk9wOh}1i?ft^cJn!Is<3tek1sY^3Emssi&lh3Gq zvW|9w2Ht@~aG z)jO|;k3C^LG+YMI?0tRAiRPJ>JI5|=1dSWY#@*852HVArr*UJg;zrxWO{H;@>|AD1 zm+5vc3*n-7$UL9riEU0mr0ZqUl`ClEQtQaYc9H97B4Mb1(L58wjlL>B>!3XUAQ4U zK=LO-FL8i4TpS^e6i18W#fjo%ahf<^TqrIQmx{UKYH^+TdRB24$1R863Vt~hSMaNF z%*Amvj%zf6HT*hotjBQ!jvH~@gyUu$w`g=*_-$a^j^hp-cjCAU$K5#Y!ErB+`*7UP zkL3^Gryu!c{6YBrghvkHk;8c8XFPHQj~vA#zu=K$c;q-9IRUO;q4yh}If-X}$1|t! z+-W>}2G9M0=gz|G9K6oM>jJzk!s`;eF2m~zyspCQ8oaK<>ju1T!s`~iZo}(Oc-?{5 zU3lGt*L`?BfY(EKJ%ZO`ehB{ro=@TV7d)TAGfTL~cN6aO-Gv8y58)x7Ej;3T3Xl0- z!V`?oQ$9!di|->mfbW4qcZ^&QVX%-b3=w)_40{Q~gx=2d;JCSi0GVVsk zJ;=Bh8TTRMeq=m=j6WjdL7@l#6TS}#>x9F|{4+8i!S_*Q{{`8PA^UM;KY{GOBKvR1 zeiGS#NA^?5ej3@&Ap0N4eiqr!A^Uk`zkuu)k^PeJlWt}4P?KG z?6;8pHnRVT?01m;F0$W4_WQ{G0NEcR`y*t3jOHGZHtoF62P;0KE% z`61#ceyBK_A103Bhl>Y<5%3);Zs$jdkFg~@5ys$qtT>JzC;q_yAdct9iyQa}cy6Nj zRG5VC$>KSFia3#j6=(4C#F_kj@sO}U zoW(B`f94m7m-xlvY<>x1mx|AXW%yn$&gEB#^Z1qGe14UPJ7)^jp_T|0lM+^b5#)OIjN=M(5$zJ=GAo9J4Cc5j z{gH|Z>51`~UnXM5#iuUe0^pOh@OYp*?42*<*%(W)!+rTMf^)*dU2V`10Z zB^U?%NApQa(H;)cd`xL{pTsVjk9ry?>}vCw_8-54mM5dD_6RPH4ZeYWN-j_YCPM+QOlTjSxl)f?2G^1f(3G7#!B&z|SF&X4kZ)Spy8bg81w*QDgc zbdQL$f7A5T_UUn*_ADw8lFzjg#WjQ!`TAW%7C*z&FqAoRE|nQzfLbJI0sV zsZ-~aq|B}{t$Z;pQd5&NVj4HckCm%ctWvXL6?f&zAu(-}QeqmUW@NSrt)W#6@l`4& zBqxjfYoJgvyQU>3Bqei7yZ^oVNY%@XnE3RrX_=`piC?D0B*v!4SBve?DK0*?Q$qEM z@tl&7n!za_C2>k?t{M()I0bb`dK#XIZjWy~8Qr!Dr_^nLpBhJTO8u^!QZFepy6xxn zI;X%(|2ZlyGY&te{vTFG0jQ{(Adv8XD3Di$X{DD^Kci}unl(bv%%%xRaqSy-&csv; z@&Bsq^KmcNEBClmHP?Yw7?moR%deEpTKNU{2s67(s}k6_%2ZIduQFNB;dA1!|Iv=` z>W@9IJyvo?=>OabV+fN{;*&ckpn4=jni1D7F(WfBzGKA>+)J*NgT5H{ZvR#7PM3Z< z?{0aaTFL6p74%7?r4KnhJ*al2%-vO*-)(qh)b2thXV-SzfVN4gTJCGdnw%(Ijc+ui z?3Qo1+3UV5IXJ>`?zoJU%3AU=M=Bql+^F!X;Cm;=&D&G-T*)ad{&sS*c#Hu^N6C4L@1WI^07@{>`) zFFe2Wg>J1l|CJ1sq|DfkiCwu~uEIeaE;l;{zv9fnsVD2ZQ8*l^$#LEWF9iiHY2-TA z$d%s0)u)B)g@FM{;*-)kB&O38KOn_iHAVd~I5Y~yp}Y%8ij1t`O0Vsjt)=>=Md86M zo*U63=!Lm~*)r4dyBfinj$HH9Tx}=e5beg{1vS_6$Thx(tDcdrkD4xM1mJ?Axw@^I zGW!+YzIqN@G?z6W*%qkTHqOLh0k-!bd_cjqqm>H{)WUoXn>MK1EY{bejoK@*$%!fL zGdqALNIkJ;eUA8rh!1KN%0)M=+oXB(MzI+kV>1%fcgXNJ9&qvCq__w!#c=lUHg8fn zHnMTk<}I2vY*HUj&eYGC#kl>R$cE8)puPS;P&SjVT~bOyEH)8CwmiHRYdPzA)kzwg zk(r*9(mpmbu5EH6{)0s7C3*1`^f8ktCGo4+l+Nn=R)nq`+?J>fn8NsFq^4(b-HWJg zvvFc4 znrIO8S0FOz2SyR26C2+tEtY(6UmvE1$g&c?E^bFFIX&;xMq10|{DUhL)Fx{(m&IkN zjV|1+m1|%t*W6aFV%%zdU|Tk6*s5-`=H5nu!y7c6(ND^VRr@zFfsSVo#8;`HLm0=5 z4oU6uCQ=1B<-(~L*T}0)BwZ%9g*UQM-MkSm#$ENO^S$Z&bw5<6EuPt6jDsAd1-AIG zsT!cZAf|O|Q4hM+n7+8~gztT;{!MSeHS<+d=eD*#7_*}Tl5bMkM=|VQ;}s2N25r{R zi$_9AgTRESTOTV+t%tOc;Ig(DoE!8GZPl=OL$ochJBx8^Nr$)awP@H_Z3GR<&8PP5VG%inf2>TN2xiCT`Plq9fm{>uZ4)oHhnyOav0NsUG5v^){*>-OPU^b{N5%_29_p z=tgzDSXNjdm=+t2Ua1!v*u-L-5@mF}I{N-ucN$rL2vGLJ-evf#q2pJ-Zj-vrjJfWg zZ@1x#OD?PX9pjicRzYdZd`U{d3t@TPUlZN2N9)i5&FE}ypO_LGk6(AP{$)s%q&Rug ziG0e0%i3#ry=e0C+dlT`UO_l58A|{?mD0Hr9b9#F?pLQmdTq|v?8BxlqGLNHcES!q zJ^CTX0gd*(P`@O89r&Zc@*Um6te(A*w~NwManK0;wgqM>inUBKwYwTmJRg=fU(h>W z8&m15wh=UrBHKU}-9M;aZQ9a!yq1WLrwer`Tz*oU`U%q;YIji|^>lDZYwRg4f8H4q z+O3Jka3(%2HH~h{>Na**3vbdA9Zd(faorXTqNDsL($7Zw+WU;T+p>i*xBVTD7>Id9k0QP7(D`jbJ&OnX3k^&FyAIk5@quPny-^kYQ) zqP6bbu)0m^H*BKrPOA-#bK3bcjRKx0`TMZF)j1=t!cb537u6AoW_-SkOYV%n^(1F; z{3^{|(o{dU>MFmPcG*B#PuB#qKK)PMR}9}?>ck_Hh)%kC>`bQ}dew+3VLq$)fsh3e z^gYuowa}rfN^SZztyPb;`T=z#uWfXTJ^n?HHq`V4kl0F{QR<1RL1V8k7T_3wc!SAD zp_{kx`rgM=}_?;ZD8*M0J)vvVsZy0X3jjhCQue)hHd7e&ow7{5!@yt+Q z&1!3muKN%)^p-Xp%k-8;Hf#|a*vO!-nIs8#vjW?d{>Q$0q4jU1xviyX<29DGo<*-@ z{Ab{w2Jd?2RMPOHx>12A{w{v|YG7vsb+&+_i$?;`9RLLlWV|}3=;fDx&3#wnUZuk{ z^i~gSeKGDcH`-*J0(_)he$$?w|39*Jr0DmIrhi~PFX&nBzTtS%Z#TxM(#kx+dP|^6 z4~zthElL-^$@5V6!|zmDwNx(&zrE76+5=CjFHjcaT3U~)U!uo`UV43|rJ zOQus|W{1=SebpEn^T-;U55GG27yVfXeX5ZxuxO8;2JPWy*2I3Ue;GJQE!3R_l{Gq; zo?U9yHRiEi&H0zK&y2`OvlAUct|Zw)LIOL4y0{FNC1mpH)iW^Y&Q~W;!LQ2;>ES_x z^|5Q2hLctz9lUP=*+W(buL0d3(Imfk<9Doy%o0iHoOfEUg;kWT<@m&EX8YwL^QaiN z%JvjQ=jL-pvzP15j`p>vYq9Bkqy1_^cdA}!PcMz7V?JktpbweG;8$b1CA@;h^wttA z)phGOY1tUnZi~86{yqLt7%2yvwN`&=!Y_r|iQppLT=m~{XgP6ApA2|Oox^XLc;h%I zYZyXcaczj8m+;NG3I%07kJH@qL51+j%=3lt%F6RD^x1ru_f*75!FLP#KJo$-yr5W^m^{{P~53Qy-#9y?V^j_dEBPOo5^`rh3XeH zg#Ejh7GagwLwRkevYLoThmyMq6;svMh8h>LTW#V1)6L@Q?UZoz;F=uTP1|6d;cNxY zX2SBJ%7W{9X1%JiY!1!I9;@CEYlz?VOvh=rCB@ORjS#>(BiI#6u4$@WI!~4V7vvkM zSJ9zjyNMXAGqL?>?q1T|PeS!O=L~*4={eD%l+Rk6-3_D`dXJ!~KqoU0)SZ7^+1~{iem6HUAUT!s5 z#W@9to5dkauW@=Ze=J<1MZ0CA0F^@N`Fj>;#R_;?eQ-etI) zkcI>64Ch_oRB$Wh2@Z2f)(R$^@-{fQMv;aC>kOv~a6$;n6#vsxh)G$$7HU+cC2fUu*4A23_7LTX>O578joRuw@R+1A7xT)G+Jpes89_Y|M7fnn zw-P}(k_--?$`QqGE4VIdBp%tJZZsRUjbx z_f*g(z+#HS+(xGP0_d@71*aZ89}q0q0%46dD))F`#Stc^a*qSRKDB}isN55XGORP@ z&!ODGt+XTJY~|j8?rZH#9AMh2m9jW`a0x7J<-$6{Ndry_VPPxx6b#OObfojL-AXp$W-p% z+9+l@RqO@DY`4;#h_aP?Hl1PJP5R6X>rJ{G)>)Si1Wtdq(wE?{m3x0cY*o9RR_=ZC z$HFDiw22Sv3~LmyM!1z>1dFNMN0_LFnW*#=InFyTmZe<+7VJi3WCY*6L zIFkqttTUYHz?n)|*vfsXNt&59GYA2!GlIDwm`w=S%6)eJ1oH?1tTTe8AXw~H77_@i za$k(i@ke!Yq?P+Z6O~@+;8J$ZFxCNMja$ieD=P^JQ@O993py7B>{?oBV$x?VE|jOu zT3BanJHWQht!!~Cn+O|QxoPpQ@NjpqE+d2mb4YtSz9kc`8-i(EBEszY0SmE^5YUAfOST28w5Aq%5}GLm2j|? z`%QLRLFIlOj~rAt8d|wu&7Tz)Vbo>@tTWapV149P9uQEra(@(99OgbS%@;uL*D7}$ zJ-C9Sh6P(7tcgbD{*tGj@`A_WHTM@hIXw=mr9?pG{<23`hIOV~8p@?S$}2>it=vm_ zj2BQ|F>`3IoO*DrNv#WDoq?1CNLfO`*6d|HIoZe5+2UWbAJ=Mj96kRc1hCEsM2}s~ zo+l;|F<56}!D#N=q`6GZ{x*90xH{qiHG6rditj?P0#RgY_6jzNic`g^P^|1xDiKk( zX0J@=Rwa`@-pT2KcXDuHP;G9(I_vB(fVe$MO#;GJ>u$*RU|wghX$OSsjcP!!&VZr- z6zNeS2oO`JN1Avd%slGrbRJy9RKtOFhSLZ*?|GC41c#~9-!tJfu))EVQ8gS`XE@D( z)0D8Vb$U~?v_4gu6Kz;$+HIiSifFSHdMi8a4~aIcGwsiy{i#QZA@WRZ{wX%W6MV~@ zY`mTxVd6Wdgz*OZO=#p&*0(Q+Ln3(hu6W5&8CIzfBwoI_4 zdz3Vfl0w+nsyy91Kn|i{QXI!|4Z{K7@s-$NQL+^_kq?sp4QL4kU_9Jw6bM zRt41%(pFe!Z5;vSVMLj&$A_7uahA_3Ek+UoSZ4$iK``E+PS?AX?&VYMGcVo3>M7rcS=8U(hvoG6-J<^P9;U0p7F;z4s=dOLY$D9o-o3(%+B@6K zpzmI|IJ4Gt*n&e01Vn#Az}DUU!*a4u1=iiCwYnQe&mf`>TX6MZVRkilp3rb21Y2;S z(P-vK(oCk_9*N#PZBcKJaiTUJYU79+Q)`d2QJdgIZ5q_3gejAVAX{foq4Q{xNt@K! zxN5dGk6;Vl!SetyCrp_|AlMpv4y4(7VU`^XF2t?Dz!n^4IbfECDT@gVQ(rGNu`D*T zXs2Ub*;_+_EjY?LpsWc~atR7kTdy&p3t>&y$Zpl(F-nq0^-NQ zl%rwF&qSZ8rH|2Nc@*mG+W6VTqu0{7=(;uuU<=N54qShPDW}7f-w796NB?2MIZaW2 zH-qWZ1Xpj@$Y2Xjb{%9_!<5Sei>aZnny4a4@y=Ba^B=Yo9t%bJeP+JR@pM-TVw{R)tWZT6!B{3*N?m zKsBhAUVgDPb5N~7S=7vVr9ly*4qI^bm!SSaEv0xZr6^%w>*W_}k*xyta&i3p2dS5f z=Ff&p^lPIJTX42Fz*eS~@)`kSYvnS4VG6X|*MP(pGpLnMX|*zr9$edBLxTOgNV99> zGvZG;@)_|5wd*POYFpIH_iE?#IB!ueKdh}Q!#Y!b2IZ%{m8^uyi70W{L^>C#$5oN3C*Tan& zR@$V`%&<2}m%}>iatSy>xbhakVe4uE5Es>Mr=K)=D}OARV8J@WdKXv~!ja_H zn5fE|sPu|PAvmzkaH;{PO1Kh2aF{B)iU}vg2B$i~fpv!C0Zu4kVJq!WlQc7J!UzGZ zGlB>ZgcAa`<_^!Fz)J{Voe?wuLA`J#ia;>ccRg&5x7E#&e$ph$M5R|V4V_{%14h$u zrAfHbh>$RKcvHHdn}C2_ON~rS`mAkEx(L=;7sY_>qj057xYCNSv9kOw8a5{!7Nd$+f%sZNJl5B8N z2o9_>oDAT6L0FjT{0oz^KA$t4Dt3Y5mqd}N(7%MDRq550v=!D_Tfc?!H$<7O(!ViD zV=m^EAKwuISZ4&iLC`Z?=@G7UBOGj{-jm%{P_OsEBlpyehJMndTmG!L4Uo2OV4blJ z0qdY}WdH$XEB8Tx#bNFM(|iH+b**y8(KD1_!Tw#W!4c7}F50Wy6C?1(K!iorK0X3B zjaSQvfKQoBiqJa)w&1EWpgJu=nL>owihWvyQBO@VF@Wc>Rxjh|nMqJ!3yv}mD02u0 zTdmKD$jR;|pv(O~W71tv|E3g2&wQc|TX6No5q6b&p3o8^1Y2;S6=>!%(oCjGUxq&J zj#dVKwq&IfwKY)7C2CBCo@=AF)`{9?sBMf;))PUtI^RfV(|VIOGn=-MZiX#*H}3|@ z&In~YL18QNod9^uROZ|BN7_S>U<;0P2uKGblmi5bsmc$Uhz^*D^po{rf&yD`loLQX z7NHy^C`?6u%!G2(2IW_R0$XsD(?I#1aIn?*?EvS_vYD~3V4r*2<6HnR*Tktl@P!)+PTWO0XS&VpI z`G9*AYJ&}1aP^8%f7h#2@G9jA16yUki@#g++cr>TSHL5E)QyBz+2!-+#ElX)PS}ET zhJv$(SE)uI*$TS`keGrlx0-2w0Jxi4;;BcEn;^j!1SxBi@!I&u!1|CdF@J^mAprWT z)mK239Yd61ohi44@@HP)a0cN+S8j5_WCpXknT zs`wQYI}=5w^6qS-*u|;hcToJVSNWQVveoy0=?weYq|eN-?@5=#I_vUYz{&P1-3bm` zfoB6^pxW&NwaeBF9ckP=^|KXU9%7VuuaZmH*y?6KNx1gmuQa6O7xv z%2oo%ROs7Hd|ORadYA1YIIzxeegw{budB)K&TvHF@Pvh}-1$iS1(G^v{44i` z8UcErP>V?%{x#u68@E+-v2J z>U9IwME~L42eVMIE*MVmHRL#T9sZS zNn2r^wRJ3%M-yeXavyDy#$3!RKgJOPSZ4&&KrkgznG~r^ARKJvK84*@P`OXSBP-O6 zhF0zq@@Jh+SYe&9E&%JiNM#NIWh?i2fyH6&9MgOO^a8DN$I-KpV8Ip$Yo$@SZvxf^ z!o*bW8vu~2mJ$J#`(~mH>r8nkl($DJTZuSZxo@ZY+Ex<>m{x0bGmf5J1P9g`&VJzR zB`j>^z88bDQJpjXmHQ@*07uUOLICTG;E-+Qo+oygh`~A&`vuKCLYm7|?nltyo78a+ zsN9b^Rs0Q#Cx{|bxu396Jn2;NEELZ~DyN7jTe+X1GwhT}pP6CjNSDJp>+-9>xg4on zBsgs4ei;y})o!Pi`^EgRt`RI)XIOWE^=G7Vi(oO8`=2JNTP7;~gnp0Uz&gWu3Y^E0 z%0q&~RPK*WI1g=b{vtTA&TtC*@KFb!{>lbhxx0LU3x%0BK|cK@1z2YU{{%r1Lcmt; zMe-*oN(f+`5xfk77kx?z0>M=7FZyz_x2l^Xt=vnPsPsywq*IKtz?sWbb}f}MG3m4RP0~fM&bsJrut`2e@F{N*Hnwt?Oh^L7eai&LOr(DkMp$Qz z6~XwfPpLovnacfL6JG@rmEL8Q2o9_>oEpHX=2NN=9Hw%wX2PjrgHw~>z&gXJ1so4y zVJdfzNm-xIwVf(@p;(6~GL?HBC|Z?Xk)*A#&e~cJ%27m_t=ywb(wK{R$W-pVZ4~=DRU8b(fj*@_ z5oIg)fpmuTH|aAoYzXOcSZ7^68aN|;%5Z|iR_-GKu~+SOTDcF;A8QQ3f^~*98CVm2 z%6NjsRPGZ^RO3xl`U!ms!GU##GaEQFeadu#!&L4wO*qqSaOMykSZ6p3fis`5u$B9K zlQc7J77+qiX9UYZu#^z6mHX2C304pSSZ4(5K(NNAz!ik0LC_-vc;!tA|y=ZzKt&EEg)dm(k2s=K5KW9E`oK|MF+ulz^Cl5MdrWZ5MEZ#^!a8F-4#r=6$`Jy{RPMi+_>P#U^e#I=aA2L`oB_@$pK_AmFqQi$ z6V6E+oIeN-tTUX8z&TG?n9BXUNm-xImz*kIgW?sU$W-oEplDTkT_?D~~?9JF^ntaWo)evVoYg3!*>}l9*sLQUXRG zL_(0F5<-B`iS!;y=)D9&@4X2~7o0`9AJ^|F1v3GG}M@ob!3# zIwxbYDK0;569QOk1b>0xL9}!)TDnU(*vkC@yRD#dzlSTwQcWVxR_-Al?Ey+n0|%H+DRncB?l6J_YYis?IN^kat=z*g zI1lAH<6F7^r4ZogjwA%I)(E^FUgcgaR)>heS`+&S&Ha!xm#N%8M1TJ!kGrmN|JbTx z3=|s>MW%9Zz)@^uRWTllu^y>05oIg)SUSTR8}ykO_9^LdSZiJW1#pr)Qd5G%R_;lF zI3;&Gt=yZIjFn8VV69=b23CqkYC*7=%00zE)xtof-q61yIIz}m+5@MZM`}ZGn99AK z0jCWIC!OHHTEoc%P6lCNEB6e8G&5~F5dv6i1l>T;g%GfndzX?4z9R&%)(Conpod55 zP9T`dy$3eO$MWV#EBEdODz(zdv5GMe82vp`Uysy>kT8{df4ZRif`DC1eGE+MtQ|zU z2-aE`jRf0pk2KUHeM#2hfjdd4TcX*_21eC4Zcj$}5qHTux0_cZI<&L9!H^GAS3+v@l zUqRNW|I7{UdL0@*Aoj8aTjo zMyZ=|bT=S4u-0%I1E&#TVJr7W-rSr4@|^Ll+y@Hs=fU9UZbArPtr2|ck5PjHyZy}JSDdk#)E!GX1g(+4=c2n$=e_cBN`(q?Z&5>5_c?K%A(iveDV6 z5Wrd^I0%CMUTL3K+CwhbzP6jfOsR-%~Q{&x94$8tX~0p72V?2q;^* zpU@YFMaK;D1<(WJa#23IPZ2EGe~L9ZHpX60`SixvxH?kfIFqWqaa?ZCk#hB>d)^)w zr&jH-{;Pfl)x#L4oxjr5R9?2?txPC*u!T z?UCn+Z?(QxQOD8UoT$V4uih$-SE&~ZwI)Ka{tLB1GgC=3nJPUMeY{s5XI+)v){0s> z)Y6C=Q=zAE)V{Hz_AS&hbT(xew3*q|nRGL(|J~djDBs6P-3SU>nST#} zF>+VaXX@QbM#>^cu>K?E0;zYLltYl1s=T*>D91pg-mLo)6j=XJh5%(yoHT%-FctYA z1IhpnN*+Oh^&e#fP=*l>wi+L1kY%RHNTLqwzxp_+k0I)8B|fHP_3=a<)_?V>P@fzp z*$$Mganfdj!c^T`4JeyAC_4xWtp6x`fwG%$FctT1gQ_}r_gPUp2(|r0 zjj6WxL(QyY`kAy5*8eshh3a9V%2wKk4YHVb#pS~>q7Li7`dO%-j+0KsNxu*Vw#q)u zZX2kwPvOcTc_X1!_Ae!Ko+F&F{&QXf=ao3=5`knZ>?`_$uIQ3segJrnQeorhzD|%} z|0&Y(mt*XeW9)A>vBBb#UwXvjVN|^IeZ15yUg{FB6x=cPDwTT1S2|jMwet7QvXY*& z*^0Wv;}i#vg2%_(xUpSQ8U}J z+UPSVWpqz?o)X^8?eV-VsCUn+a?AyxJ~B#``o^k(nQ~yUU)EEB_~1$Wga2LG|CZwa zwy#UeVwYQj?;Ad`w}jx{PbQrfsw+n*zT@k-&Yuj`d^0$nAei`d?y~RZW{Z!j;{cs^ z-$j4e)!i;T9%E2L`3xKRWre!2w%Dx4_!sj=R^TfRTZ|*?Z(Gc}~ zgbqp;(~4j;fHb0E(U0*sQ`+SS869sc8X%t+UoBrsxg2AUk(+B%n>#q(Rt3H>_D?F! z^qm&IJRxJ^ZE}Me7w3BXM#wlhs)-Dz=qMCbl#6XE4IvZd2YI4UEL%XF4Af7Vipm5l zg~@^sMf7Q%&nWv$r8G5(s^kb6uky4fsfu!uF~6)MWTK3eUTH*4vP63Pck*gD1?pM0 z{>N36R2h|qlZNETnM%YY5L#<{JZ}$_TbGYyG4_s}SS$sfq|6%8Erm>`PvrqDuXLu$ zu2=nU`n1#kRpUBW>PB{&K5{SVdNaSQ{>p4Y9Y=Ylk||N#3A#O}OKhNf0;VV#@vi@y zlx}YQ6RB>ofmI+CWB)ETz&#e4WY&L=KRP!CEByaM>8!EHuZWQZ$-*VB zCS7;`HzS`lQO^3`Pwh%0;&E@uFKeUoIV)cVE*`ZkpJn^s&*`j5`qt5TtxD4Ge9e`7 zHi)drmYXzH&d{N@dWRc;nase9>e*Mc#mPt0g)YBQKV-5zeXouLR-fe>(J$|nI;Fr#rY8z;Ww#@tMNZ;4rR;VHL*+!k@4 zK=?d4SE*Qg75UVUTVvKDBtRbdmMPy+lylrBXX7?GGhUh=FBQZ~Q?%P;)?&C-nybH6 zPT}4vvz8*Ds30ELVGH6FfkIrVvQ~j#rim`c3uqUqW+hCe@!Bn8h&=Gw74UJrILI9m zA#byl7Rf81r?LX%+XJFkBdln;EG73+geznnS+Z;7d`zV@xA^AmQ|gg5v$RW$Q5(iA?e)kI`-FQvW~tVs4RTWUuB!08CGX&RNRz(W zsHCidl<2t4IKhxFj91o3_1;mLAG?bnwk%$~7?o*%Prg_M7mF6gv1^%&5Ky|Ae@efC3n;hdiD!TbVx2F=jSeY$5 zOd7okcq{ac#zn1F=v&h0l}e*`mfYyC)kY&@75FQS-c?egeX0%LskqyZMsrf_l~dKJ zt$r6WR9;vmtf!yg?6cp@QJTCT7h?l4d zVIIO|m?JR7>$99AWTO&&6qjY0$7=ZtnJVfV$K`Bm;)_-*wPbN*serfSZ-wam3dYoW z3kj4gPyLU<-_G+dt4wu}{UR$d#kTK`7P^V-BPZnstdZxx%v)Xv*{n3+l(7No8^6kF z*C?y1e0g~RLF%-e<9};WvB*=%pfoIGD^-WU)wUDz2iG899@DYDbj`vv>%zcK$ zVKT^4=XI`ZDdCgDXYVw8rS_6j#p*J0QY>wL%tnVS`c3g?-s^))?y8Og*IZmaI z0GPo&#EUsgV}1>>rFZP$(-G-Ug2{f87kQONUNVpTjTiX`jl5|d`8zN20ge2V=VA-h z2KEupiB!@MXLYTAoW^OC(r zlT|d2eA%e+A}`sSG?`$Y%)yJ4Xk=CM$jZFPcM+*}W-!ksgeHGa=R((7ZR+CYxzwdD zo)ShaDin(@y^C%{>nbA}!At!KP2ErqH(RrIdwpFroewQ(bTgex18woPp)Ow;hqDzg z>KhuBW`@;J%if9jDO*W5oT%f`S(i6P^UtC#-}7AhQ0W{1Gh0bEFJ>@}8K9p-9;N^L z@ghgj$l>OZLwS+;G;+LoT;umQM+!sm3*R%=v7|oM>O>V-kP=B@9CoH%6!hP-MpT0vv;3ZZSlTB zU0!q>?mo}+qF$#_uewckxI`_xNc@zoq%uy_@px00x2fhYQJ1Pbml{;M8i1Lt$^VFLD4P z)z0k8bIGI02kBhsS{p%KhVoqUsmu5hMs2LT=nPd!k}{&Bd8ud7)YExu)^0D*Mbnj; z9j0w1-NV?eBw1U$eW^?DFvC`o!;2bBqXvYTY$ac6*@qE7Wh)tt6LmaB=<+tx{3lSC zu{@UoDm@v%%vO@miuIIVzpe|c^ zF8kr4_V(T|v#q4LGVylv!cS0zqsDo0*t|tQ^O9Yl$@qL% zPa64$dE_l#@)ymg95O<(XRiQ7c=^Y%6J@jA$8N z>Q`y%SLAU0H#qW|wcB6PMbnjezqZ!AyR}*NR@&mVg=;R4Y8$qahrFmKX;eVC309hx z{b}N-Y$fG!qK-$oaF(XM=Kmsfslao2jY?Mx*KH*)^I}{y#u={LO1@Hh@C{z1L?f%3 zM^@%VzDFagn@0xoBEx882+t*wx`gvw>cK_r?KZq_|RYiQo0 z`n+VH(_~G}BNL1o@w{ZMXtEaO$(r#Z(`aNH^T+7HyF z8_y+|y7Vex)OyN`&QO(fQbx1~FZGW!^H->C|Ov zgkj1|=0(k=QL`dUwvrxN_C>@`*-Dn-L>-SMy1dz%|0?QI#BNNY2;7lk$ZWOCurnR^T@-z$TKwZ6wl=%bve&-xd9iox35K*Z6&>w zhF{@@KcEVK8t26w^A_FaB@2wy=Ak{(wErI)H6HPjm7~eZm?wKGlAY^xcD+a=E0{-? z=S9AXNVPLx;kh_y@_*}G=vsS|x(Ga%cc{x-k^E7s8fmtb^i@W*GB0%~Oy5^ByUSwk$ z8Dk#VfESrSBjb23Ur?9NcrLBrqV{%+D6{+9BBkNYc;V?(p`CGFv@vf{Dlb`An(SNi z$V{U~1}|Apnk>sa*$=$P{xmYzJhC@0G7phzXAa`IjG)Pf>Rjkr8%teA@mvb1%j6P9 zEni-AhHr2Rl@Xo5OFf^ap2J(ScKa+{G+mh+X!Kg0OOdvCw^Nrb#^Kz=i`q-0c9~(V z)3P5Ve#%yI6esF<9Ma`oulb*(F2{K;=c)7={Z{fTFXkGJxvZZhPssIxm19Q+S|`Yn{6eVl!lk%g}+7>Dn=V_ zF)v5!He|IIU*sjLM3af;kxrw=8@y!i&}46!C#%Yfe4j?vFpsRxi>!@EwKLs3mnfS2 z1Dy+9YjvrMhv)JMb!k|_sMU`)+e)@6Bl;09^=CA7f*h{@21j1Ac6+=on$Ea18r??c zvJ-*I`p%>-9gM@7&Wq|sqdJ>m?botr5kEz$7f#gi$kydOp!xTsE`4||c~p83fSIaf z054`VjTxbzL%Wn79L9^BOd}_nM~>%3&Z3di%_9qVkqc<#T%JoIby>`FSpyffw^y1@ z%0o)Si+JJNsKRFByx3^oqV>FF`)RVh=8?ON8asK(j?-jE%#$7BMV_URznVv$e3$V4i)Gz*-GR!Yqyv3 zus1KdGHcN2YC4x+5U8y0FzOQGG2DG>@}eSXRJa+|LoIt9;-^S`j1zS{KGfy?OY?6; zT^jIQKBdyJ0A{w5#=Mwh8k6MF-A_*`J=l~N`4x>!F^_D)i%h4H?aU+F@FF|W$PAv# zchsc|&m{*gYH#=Om{lc@m4BNh7D3M^5EM&PSx$nR9q9OK9?iIv2Xuil|E=&t)TZSy#fSt&ta<;TxO){5p!= zzKWN6H%+~Rw`T43ZMtZ>GV6G?jVRj7?lwNVR+$}1Buj~AX#6~-Iq#aQzejpikr zMUzc8k1Q~1OyMP4Op`4zPd1MixspaMH;*jjMXpDr+L>#3E?a2wjXD>))^<{tZ9JEs zsmuNnMs1(G=nPxQ3(AP@;iW!BQ=j0iS-bt1E}E{)xHxSqX&lFHB`<4>H;K9=#u>Jf zPkB+zX;gBY$yU-(%ify!DO*WfoT%fGs>>Ur`F}%Q(s(YNsdOfQnXM#)7n4O}zK_#w zCI3?TzZ);IFOBSN9+|_7%%hQm%p(WzB1h85VLX@d)MX6Mr2sB!Z%>Xh+e(@!4bSI= z&!-A=jPqiad5dQ7k`>Wph31hfzod(%D>FM@+e*5} z+fwk`T;zB4Z1V5weIIX2?WFx;o6VN>A9YdTYFe9=F4`OT)j#!(F7dV&9XtD6{v7`0 zO4&>GjJFYgyZWnw$#?_5C^#760rr4WqvKz;%;YP9*2~ z#7-jDCo5L|-NXU$wzes0w%k(W*9S$ry`PNj1E(_Q#@pIwcJ#UIP<~9lH?Ju}%$i~^ z^<%s(od~K;6w3va3&ei`r26#7X`bKhn zlWL#XOy1uT{{r;nE}MxaFu%sA{=&fYcw4g$t+i>P{0e75yscxG^c3dW6kdnTHR~|B zbL@c&F(S6!rO++%?}lcU3S1O#`wCr^EKe4tyCUT78m4sD6Xn$Z5VuAh+~P=k;A+6j zgGlC=Jc#9tNl z9a9|B95WoV9P=Ct9LpRl9IG4~9NQhgIUYEQlb?28R|Lii6NCa`wy+3NhlQiUap8pU zi*Qmn1+mkRydYc@E(w=~E5cQX-xB^1?g)2*@JRSu$P#;qJ;fZcx7bJQEA|%$hy%sJ z;t=siai};<94?L&M~mac0>I7{mxwFGwcw@n`Xncvw6t zUJx&fSH!F0b@6xchIm`NEB-0o6Yq-;#lOVA#m8cntA{Jw)yq{e>i~Z5cqv*}=va#O z6*`vVScKyW99JssUFlejR>)3CGPiZozRYj@xkDj^hp-cjCAU z$K5#Yag1^7#jAaeC61rqw;xvy;L1T<`59LZ;mToLIf5%kapf4U90%74=>39sPU4+Y zc;{EVcN*`W!Fy-%-Z^-kht~yo{RXd#@VW%A%ka7audDF72CwVz`W;?3;B^yTx8QXf zUVp&r4!rKd>rcm7@t)(Hc;9heeBihsK6Lyh{^htRK5|?V|8`u)M*>|Dvz%AO9?olG zw)48!)A_rY*CL}y=DzO$celC!^SvU7lIigTcAs&kO5z&Y48%{jz1-I?c_fv=g)A6>JY zLtV3-!(4Nm!(DToBV6;GBVF^Iqg)G|qg@M~V_b`zV_l1#<6KLe<6TRg6I_MPiLPbN zeAja4Bv+AhvTFr$u0))G)*#PXzz|v8<1xs@@zt$&B(I_dA1_YHssmv zoa)-)EO6~~PIK)-p54f^2YL1)&pzb&33>J-&jIIj*Fog@8F>yN&tc>_f;>l&=NR%F zcg}E~aL#o7;+*9=>74C4<(%XC75Pp(=eo`~=ef?}^*MZ<$JYgX{f4iL__~Cz%lNv2 zudDdFhOg_+`L5rc3tTsx3tcyzi(I$xb=$ev^@nqb>khu|I+wcsbQZeqIhVQaJD0m2 zIE!2lohw{_Iaj(KIaj&e>a19W4x&{inT!Vz&uED|{*AQW^D^J+x`ce4FHB{K|8YUcY z4Hs4hjSyA^jTBY~jS|)bjTY7hjSX~J>WbYW-E3}IK$OksD>EMc=aTi7Db5%vVl74`#h{Bn*CYu`uM#CBng=rNYlag~FkrWy0a0<-(DmBH?Jz3gKALO5u3W zD&a)XYT=ilHNwfDwZf^Ob;7Sf>xI)n8-z1K8-=q$n}l;gn}zd1TZ9WiTZP|(wh1eR z?fBXuTnySNTngGHTn^eTTnXAETn*YQTnpMKTo3w5_&sR9a3kn|a5Lzja4YC%;dam= z;g6uh!m{8a!t4)@3UfXKBEH)h`KKA}$LHKDZ(*{NSpvGvb;sy83ltO!eP| zvDI$~XWzVuuUo>=Dz}AmRsImpSGglxsB%~67x|~KtI9oLca{6Xu__OQS>i){{Uw~J z@<=#U`-rZNDzT$0X zKk>e^zxcp8K-^M&p!jo@LE;c$u$U)cM;G$Mp~8>iC}F5LS{Np-t2$g<6g)y)96VB7 z522T+;1y2<> z2N#H2f~SdFgQttzf@g@^gJz>+rQ+y!7Sx6i|@-O0r$|uF&DxVTBR{mAIRQa@cx$+r&ofWTCJ||wSd|td(`GR=8@^ARM zC{D$0Jq^3{MAsF3T}3;uiPIg|#j8QTi$6PVh?g8U#hH#<;%vulv7hS?ajxTzIL~oc z9OL*?{3GZd+H_xB;&>p=!`-sC>o0MI>yfy}@wb@mdMxgAWw{RE-njvH&%Lgmt~p|k zYmuXuYox2U>-?L2TuU7Pvb~fwzoO0dY=r#3QQuB&x$K)j`{TzpTYxR1RZ6ptZwCht zL1nLAdAntYlolO3rJxobu$#8Jq3#W4oY0~(obZzRk^Yz8J&=!y#PcI#Ap7ND1kM!7uZsWCd}JKtcQ#=#THP%6kzdJv z=wwNruBmNPI=BUt<&8SDZ{49;J4YQ{$#7Ke98$ANQiIeM9olEKZ`IME7U+&99Wz^| zwoj@aTrD&yx_!HLnQ5sVyClU&C&jjJ-!>zuK@+^JR^#pJ@4sC=6yuiEJT)!p!}b{+ z6GCb#rF@I(Z?|mQR&dA-l;m%4TBf$ONv;0-ZwuP1^?y=}4qehawogjwl%AB5+$<#{ zxkd99$;vl28DBN4{$9Cg*RiGSGP&t z5Ah2BCr_%|#U|BB?HJSi>pJphu8`NBW*wX1b^HIr?_A7@@$C(CTK*sE6o0d%e1{~} z&3L!^`!z$*+D0u?o3(C`*%1>j*!N$x=xEz>b^iVE#TxdWO)*B*F|(h4HEY>7woRDl zuf&(bF7`@Qc`th<3m;!3+y5xXx72G-Dc35*hW^*B&;~R$twr0+miQ)*3~)xXRw)@B zo3&{3_E)y@_GN>=8T!_M<*iP?{AkXd%FY@Uu7+4vP^XZRKKOJ&VC{E0?x^16PQ5E5 zca*Ad*?RissqK~A*N!$k{&EdR{mHLx>}H#}`iBZbA}pgf%SfxHB!A^lwS$xD2P_Y| zdwlGion_8fcqzf}UDiVfj+_iV5~-D(k~q<6#exlEWU#VXFq> zfX&NRP7Zq=VZr*a)Qse=c$7k8Wz4_i*nNX=_yV!dd|2MDNQUTRQ@){Lvg9KR+QzWt5L6q2RSW@d*^k8K9)m! z{D?#Rdq9mSA7Fc?QH;$S-$>cjt5pxt@9cO4^@LnmWMv_|hlm%aCgSil?uUV2;;#Qp z^%|jwC&@N z$R-V|B}X-A)FifXy@qx1=5)2-c-rFS!<}>0hOEP-VVFcjDjEwmY@aZnPnpJ}0+j$saI{e}VYG zFQ3k7nUaDWc$!Wjq9Bl~2>kMLMrzlTWHbP$$ofMVvUX~p+A^7bsF^M6ZPK)ln6&8g zovAE})m*RWo^w{erm`uZUVY{F#20+IV5r6uiiJR!FAL#n_J z7{`pSQd<=dc2zj_SM=&fDub=cB*#WZ)%O;U%G0**LgdNX=wokUa&&A0-pSKC(&bSC zV-xW+1GcO`)V4ltTkb|rXuTL!KPLKPvo7&6Y|0Y%9mSyvTG=S1Qbg)CjP=&_HpXbQ zOIP|$eWt5)eT>>+@%5V21G~Pvp0?E|9U2=QTd#qPO6T&^9%W9-g_=4^Xd~*XF|jqP z8S^y{^=TmKHlMjPTr6^5pq&1~Zh>=V3XuTy5iEq}CTGnwoWgqNOn$Jqw>2rX$p7E6 zWsTLmo;7&+EW>fCSKxyX-_@O#*^aWvOJ=;naxX-iy68-w?wOz|^`Hyg?A_msHy1il zCu*UiLW&0+P3)@8hmOh;Yv3UZtTw^L=N9^~$n9Y^x_pHS~sjlFfWHo4+rwaMq}I7M?DVVGjH zBc^ITU5ob=RT90?SbK9-h__+gdJW};Dt}tKGVe2$?K~a-Q%7B=i_|v)-)Ebcnei1J zQu)ra1Z@n&M^XB8L#JkKGx3?Aq$BW+v2Cf+5nr3N&u4@SHIy}UrZKbLcdjhceE(o4 z6YYrQn!`%tUg@Jr=3Jn}v{JssGOa998W0)cdw*5#taP8dNjaLtMn->(o+Zx@p0<6W zu3+PC^0#_hh>xrvClAGSZL-!;0~(<&Q0^7R$Zo}hh5whU4j8>@B$!P&pIv>0)-_Ab zx`y`PO3m$-w%~l$`zr0tPIR831=^f>j_FM-3uPM9r4@{Zu2y=~qqa1vUTm_yk%9O~ zPM=BD5`|yKlw|e)eX2{W64I}$!NT_}bh$kbti1|Ww3@-&Fs=cr zsaUVaw{t!Zi*B6QC^ja!@uza7jOWVA{jM|JxYY8O-X#lEE<7r>J^NW!7R>*D|Ng5# zTooINPX`|fNagSRri9j!T7;^9=l4N~`X^DIKu;C52+i%8>%iZ_$i`pDkdO7%Pf5q; z^C}-94(sy~;(jQ%h4R;-(pN#aQWmSZiY6p}Ad2bDs`X|8Rp-Zf#fe_gHz{(SD5k07rfGPb1>Pk*z8A zfMR!|==D|X&QZiiD_c{{g<|heDTj!Pa<}3yyJWfKcJ`(-EXSbF%&@+s%VDkI3<1ud zP-y_csjT4y$vA@maic7R2Pxf-KkhW3WUM@b1#1m!G_Xd7O2Y}(`=RP4P(`L1X`mWz zpi;MmF$4$J8qOr(ObnIA6P#MUI1>#x<2g8!2@b3^oaw+RAS_YZi2X))@DLabKvkhX6{xD{G&DZ;ydW?Xm*|2i6+S zG2k2tl@1Y{>b^Kf3^<24IL8SNtTmipfpe0uH1fSYoir$`^BEtxZcXt#6weaHCZzRB z>2(&0W~CQC!Ckre!&+0m4CRYNxq&=S~E0M;78A0W6DD%}W` zt`m-zHI8VR;}*NE;O_?Cz?H4?Mzc=YXx2H3u9wVuhp@t0WBnVfe}zg92;wEq}0tgx+@YKSZg@11Lrlu!dC9Dx$#$<x zdq~MxwFwriH7qZ%qTNy?!D1@+XaiNGfl9rh*C9Bt)^HjC=VP~2kKizs`^N^HdK{dF z1P9g{P7~mKLRi?!{S$*UGi_oC0jxEGL=b#R2-wQ~(~=3A5&~Fj1kFH@?3O+!5KQHs zjLmVMygAa!{c{7ATIn>miqQrbscxyYTS_4$Oy!RkZBcN>MK0{v|7ELqE7eMb(Dt8>+vk4ZgUs(8|G4+}I z8epv=Ow2R)RRB0BmlC?leJxRjwWhoo${XF%dLqtN?i=a8w%*90JUMl5At12UKz0IT zJE34}_U#y!qw;L=t=W$$H9L;(U4#JE8o@qp&0Z|_6A^>8CiXL$dw?{Tso4*pr;o`a zuB+J(Syem+#Un(Kso9Tk6pvd~JPpNDZs`{y%GT_s=-m3nppXBLf~WHCGo-U&t#$S# zfc)l`&Jz%}TK^65J(=h1=XpSv2@tF`pj!aC;g+rwAf`^gVc@xL17NgY8CUWRe)Cj@KTuc zLYP#6Ffdj5OJVdu4hYyaQ^CNbmY5Yu=fGO)906>OFzNL$={3T}R^<)@((4rWH6xrl zZA3x`YmM$dpsNxl1rao+9+wi~H16`n zrG{Ni&&xdo+6Yv`M`^&Wc(-)Fu!$rq-UoQJZ8% zZ93En!lWrgkgc-|=scQY&?W^8{=%m+k6``p;Q4@<8z#*r5NwS-7t(CKFq;RnfWW}| z53?LFg<;YX0>jkTg$9--Mi%9EjK4yv^b4&2DC>Z-CQMpIP?*|!jR9p92W34$f%P9{ z3s5!@4z{k|WRz96n5{$?)_>hy(A`0F*_wI>PZxiCRq1+I|8);ScYm0)k4Q81^nPq^ zXGlH0&p@G8A^4lE{)?Z4_=zy-SeSH#=rgtS3A!wgL7iP2M+`h_Esa0>s&oph|6CWr zbs?X*550kDDET)G3-9UBC$f7J-{GD2* zlVJTvxet^-!=yU|g{hzaG@#t!py2P}Dk!l2qdW%6Bf`Pd&W{YL>a4ZZvY-}NtBzEv zmip~4Q#Y5YWnKt9QA=$jtp9ENAE=fls%*_%+8~RXxwtgIAM{mv7}kIF=b`>wE$P`> zQaQrF*2~Y;B3lLOo-MY@byIqNSQd0u_5b{*+%ZIhogxm!E8=LM5``F?G6pkS>jKZf$7 z+R{TJ&eqJ2YHJTD9vV0>Z!RjeD~@hkxQYX74d;pQI#NKm+7WE^91xzHb6sCO|E>_= z=zfwAz*-|H6V9uki^ZNMVzAc4o<(!Zk>)a0bh+@{p1+$^(dDfwz5vAvM3JeaD{vHF zw5s?j6f1^HFB4I=nywhG&9IjZ`pgV_jdVGzwJsNd;|!PHAUJGY?F7U{x!dVan!Hgm zmWyD)TElt^SXINN$^?t4u&WxVDjTTOibf(hu-0&D0H=Dm6ijfKD!aM?Czylt9>IaN zhT{fK2w`C>?GS@BGi|~M0jxEG2oQu50=DK3FPR{c5Wrd^_z(nj!X*!ZV5;vr*c@-k zn66OVyPt!C<3#b^wSM&VM!aH&2aVe0TkbU`-+0lSv!8<^Bt+k|uxthFvm0$bB? zDIr{nCv0pj-qe7UKyl*@aLh#doG`*#V@v^Ki*TtK0c5K376!g%1}e47S`i#rYdGzI z(B{)oF-o}8F%E3t^IIz}mGJx|9VPUHCZw$)neC}vfu`?7q5k;m#?*v7&(yI$; zE3CD)eh=ktM47G9yBVZ07mLe}9|!@gHG)1M=oK#Y43~Nk4z^P7#cnI8*L&j1U3sIS zKWWmVWY%253Turu53Ga3rGW&Lt=tFei^HOUhWP^M>q_O0qx(mK1^Z92hD5~JJ1bAQ zCq~qf#z&Y`?c*bId)}AJ2;EPaYHZXwap;9m7 z=$=kcVEsp#1C&{WgRRzQMdar6aH7k7f5s%+DgQ<%j_$cc9oB#Kg%P|;y;x`w5rXw! zs1VIuLYm1`=}XYZ*=VKyXG@k@QCkVMBBI7r=tUg0RaVqCKy6)ww1x<>)%iL)o7Nb# znc1|FbTh2~-Mj-R+ajbb1cj~4w*lZGQ<-lm8EGd$g7qKi0FZu)koFQJrYir*K(yCD zq~5F#5)@efQH}%UXoPf_pfDBrQ3J|h4$29F0_#7@X`q}U9Begy${@>3lQTpe)_?Wi zpnjgHvz7SylGQH~by)w^e~0?D2AevOa=ZYU9@+g&aRo;1|D^WJ|JBK>wnh-MAnh)k<#M`=@H>#t8Y6te-`I4MSWxd zVu780H6nd&ni8d~}BrBv^ltves+Q#yp-$hDYi6~ore@ACnSA#w?!@83$hqcz_y@8Vx zDPVBqH&CfJ?jZyR)*8-8 z;0%wHh7ug65+82B8Op&KMQ~uP;fx2)Si-_q<6{ld%(R(62w<%dOaZ|pLcmt!lS(F- zN(f-B5zGd`%t&cEfncignb;i1$(tjs%BLHs)XHX#Rg9&;SR5%WjFjdR5~ea=Oc(S* z5U^`$zJW=dwS}aMV6Ao0TClB-lvYMcMTCv5&Q}|dR#My|0~|Av))7WnYmD2#xFu5B zL;#rzeT#u_lYvU@vh4&1)*8+};OvQ%b`cz=O5bC^*~P*6iQvFm!#M<;gM@{t)DIez z)%kqbs^W1d9wmxQwSE+eW~J8&(pFe&ZT%I>Cy6p!v7aJ9xPf&*&}=M&(>L`e+@4pX_u7;qYJa2gXFSZg?+ z0w<2Ju$6n9L7JI134{RF8o}ov_>2&+mHTHU6MR7kV673PfS^T`)Qmtdm3s?pj*H~Y zkyh@_3{+~R)5HxFqM0*0jD;O^gN|<$I(5XV8Qx@wM?tr*8^)UVPY!x zwE!rRO9@@&zJVyiT2tNzkhX;RHnEM;)ToCmU?#ZjaV46lU54Mw1_8h_*=ZKOiVg2-wQKbjbu| z2m!3MK6nlU&qhn-2n18PKO3E!vq|0@Y2{wdK&4hX6|7>s3XF=;(#z4(i-d%!+$%OVMF}@AP zx1y!01dyrR-!kx3HBhNt_71^;wT4p@I5ncB>I8?W+-n$cs&jDOCpfUyaB2a^O<0)9 z-EB}-=W}hVijh$KfG9GR`v*`oE4`vfTVbuWwGNa$M47GJJqBsa#p3d#E+K%mM$iZZ z4Wp&{(b7kRgRR^fvfBzO_xiZ9P2Ol|<^EC0te+58SZl0J!I}^)#S>7ra!&vjQydn> z8|I4)tyJzfx<4aWuzq0`X_b3BV6`DkOy%AN06XPULRYz`5oK6w${nHHAzDf&;%w#K zf$nSR1`aUoQtDgXU(F<}#IgHv0R3Jnp*6y_Z$RzEJE#6q(As4@a?|RmCAt926}LAfjyL zK8Vh+0S0|$hUJkihqcz_qkuCaS{g=h*vfqbAa=>!PAm6eC1Z^ySg_WxCIM?=v^1Vz zF_rs71J!r~m3l*;OmJYW;mici^k}Jo;4qc@bOTNS2WJ++fwhJ+A2@Rf3tPF*HApkl zW&t69wMMWM1d9m)Te&YTnV^smz*-|%4T6=?QW1e*D)*Jx91qExBdy$v3{+~Rv&JgM zR$y$7mNrI9>j?={xo@TmdLszfwY1*Aq|VxHq>Es!b=+SeVNFfK_3S|jKQf*u~J zJAq&-_a4|BAIqB~t=zjCsMJa)$127^VD$G$eLYeiLc&z;{po`43j%g6^)WE1vvv^a zB3Nr(G!ksXJlfHTb_O(i%?(pFe&ZCwuKLZZx8?u78EficIC6%u#G^Rq-n*w(?3Xi6~pSx1uww zr9q#WVX36cVXbv}I&jjwQd@$0u!1^@LYCMnKuh z{e-?aEIMYGFMu8(my7bzeTrbg{!^@%5@PHrG4_^CY_Ryf)QSmpq|XzS+C9eJ>RnXK zwxZ7ydPilxo0~1ZQ6?Y~FKzDR1h}_WJ{n(sS)p#MEjH^h{>8kJ75Iw77URhJ+ZOX~ zxz8)u0|Q@sD&Wnm1^D#L9tra$$I%Y zo2}?eS)Lr5%dgA%o&*%B*UFZQ!&~)LzLqjyJB3ev=?C98G4}Q{-#6eB!Ph!LO40Z_ zfLP`Gm(15%W|GB=QnXj~-^#9lkCv1V?o^p2Lt&9$`oZ#Tj6G9k`4%jd!O|{4YNN4q zW?9;41VwGMSM{G!`=q_h(M92qU;4rEeT==E%<(-qBye;{kkU1dA3)~QCml5PqIB(* zZ=ZCOS-LAM@=HHhva&Is@FxR$C?AW27xFo{g2B~EgUafOi|l0TB;!0&q!@X2+XJ5V znKzwfuB;qHDQxnoKWu%F0C{>VNO&QigY8|gb)jszxCmUIiQdJmtGX#jec`Mi$*2Ax z4MYNv^jApmLOusl2#~rbNZ(VcLAcIReJ@iLb(fF6ORR^&H5l#+mwf6E*H9z?PM(5; z7xFo{YJ)2$LCU6F!*Ct6K2t15>#d?}?UnBo>#gt&N0`DVpZdc$3JHKUQo+It`5b&v z;Omzl0=!i;LYa4?)9XNH1< z7xFo{;=na2L7JE#ji+35@D_m8N%)4`f0Gi>m&*7~q_4(nuY9ND6a{uJ5-70psXwp_ zkpPVI6-K;}&jFhR*qI5^^aQDZ!Y;yFEbL5Xbc?35rv=5UNWSZVfK+=t3)(a z`OvzS1_tmHC=cXtbf*#&SpQMdfYO$5u#W@VCgM*{%7v)!<p;FPqM$EQ2;Pn|hIMhV{Rj2LPpCqLfQe*hhc;08k)zHT|FVxg{eFBuKFSBMk@A z&_pSZATf{qh8l?S3`FXlGlHPN`j0XmC}R_)(FBEgNBA}ov5>q`lgqxK8vWs`meqa>hlw&xdecD%r_sK-bs1WqmTLK z8i>@#B8#jbtOP<)qO>egT1qIGM|?$e(Jq5JyJnUec+?rXigXRE|6Q{gTpJUm^@-A2 z!o@z`+i1X9Pf^zzz?g}%h48`p&$kDByAq`x1de&Mx68n`!$72V)n0-E>p#jNpd3t; z_7fE5vED%g%6<;YVS)ndKgtQ993vdeBfVn=Rdw$EVnyvV)J_pK=5gLBsF{^aXGj}i z{cqz1sGcLL?4!JM23gFz;_~4)q7Li7`VFXGPn51EN|y-(`xx&!yKUex-c?*VEpH_B zG2Z2pId2k9SpPX6fb(9WbeBM~kMQp43%a7ahWP>Dqsk*Z9NiBI66`-kI{q@g5ttXC zd}A;dMt(%2oZ}mVMlov9Cx6d?x87C$oGSh&^EpWV&{TF@fXhm4FQ5Ly+Fns!tST?k zl;v|MH!fCQf-8)24@G$?E-T9NX|ZyEy;bNNHoLu?-EMCYYRhP2%MGvv1U_Z6+p?Z2 zZ?lyv^<;p(9d-FS)Rx+^v#qxsK7sJ*Xt#gGi^`x;>7lk3?c1d{>yTp04b-y#OUvGw z_$gA~7)Yhs)N=mEDv=%;NR0Dl(w=d*{ zucHd9jq_rqd5em8$#&3WTg@Xk8#Olak{zJQ_L(Q!!;3slBafIz9^yrwMx@%ACwVRx zX!5f<7rNH2P?w85mpjzuRtckaLtb?0U34Q_R~gakyws0r>c4nv)^2~Gi>52Hf?L~4 zo^`WZNds;1R-`U3xeZ&%3%sZ|Xw++NldYtomfc1Cl&z!+PSo+Jq{|zl`M*tF{=;*5 zk4jeuFte2e^I~e#7`I!um3Wl?58*}Dp^?$%k&(Q}hBWeH^T>L<$XFWr3D2b|b@`O% z(i|>oZzsFWwvt9l!$0SRx1|cH#(B}&yhSOzWSwZT4D-luj2i8E$-2{I-fpQekZD|0Q4UZr!1)fVp->ax)|oa=c}yJ*yQGps}{`%lDA*-8%KL>-RE}>@Qk9(NMc$^7H_Rii^CBP8$b06IcX^TaFzp8L zH_xRsbqNe(?-8^spM{Is+hxPdwvx}3iC2afUXd!i6lT1|gy}Y9wHGV!l8H2#!#whJ zqsD8zWN*=ARm_tG@gi%`$ZF=1@9-ksh*UfCeV)q)GJrIwX-Hi@E@9N_ zg_&(7Ny>=U<)u!bspI5u{dW@bnzh@T=%VR#>P4fobuP);;vGO;`WlC`4=?IR8a3Dq z>q{;BNaCk#CF5|Sj>l+S-e#KrB*r#!-P_`*xjA3wKCMD zG|%M)>hfGIvm1aqYR}d(+e%s}BU+A^`gNN6RXJS0mB?$>Zm+0|rYrM)ZLN8CYqQO3 zr7d1txaRVxw&CvckQenNjS2`i!AjGzKTZ6Ut)x6o)X7~goTX{6`M*eAD)3xhqtX?_ zbz8~Hycidaafa*er(Y>O_y#XhqLEe2BP;VF-=mS$%_D<(kzq74gy#}TUBY=T_28oR zcAapuN!dYZxQ7?sgeo*bH|w6EH8gKgeO|K9X|kr~kqJhPcwVwrG+7JtWX*VyX*9Bp zd1NXtvLhnZ&isbw(uF4Pq;sKb?FZ`8jpvd}U3!%;YCYveXZQxElQN<`c&UG+sR#4c ztld6P7fn}YeuTD9jE`U!Zx?OxPNyzYBMeh!GB0W_jhYoUusCEb+%-@=PLNF#qTkKD_PJV7Imnnxby zMV_INr+6+Gsmpnu%MG}wy?rghY%A%dH2exL`~g+?(>O2gn78OQFIixuHV^HQrv3le zsPTxGtQ<{N#yr_mk?dTjv+G3~S;0KAJTLN9M5>+n3eUwslmA=iLf6`x)J5RAyhB~y zisX-4)kw3gq^~lfm3gT{Y3iDCxV|cp*R0)MLl;f^E{R4b>RbjOP+8wCsLPj;hOOia zUQ{ZLYGsBsO3R)`{1mASoT%fGuFE@G^Y2VuGI=iDsq}XMX10>9yqG>TCPzPq1}Qz5 z&5ImDBL|vC_UA>8qLIVRBZu-LC(y{TJeR4|WfIS24qVjUo@qKM$0-e;&I>Q33X6^N zVxf79=JS%RqsdmAN3Jw#6!DU6r^&XMC)>n}{E0^HF^}BEi#&`-wKEU$Tu#vBM|CcA zt(~SWCwVScsLRC?M(u*>R+6ub=s8~MJ2dqz-kP=BZ|I`w%6utGyBjhiBB!&dSNFG{3Qjwq8IZl0FCGVxQk5(y{jcvRKpov-;V>9i~NX2)-{jx@**44$Qbj;2E51w8X3oP`GUH9#&c-}7qz!rM48>+ z7AXyH#tToU3hj*ZqK$crQhCX`(q!M7M`ju|GI+^)(qviY$$sEP_NS4#=8?U5k$H$z zJ97}vWduz=ROdq1+F0r`isw>5T_%?>YWeb_Gkk+nsEp_YUh4TY^&H-swcBUuqUp-q zK%>{{T#B^CyPdjhF%IV@UesP1waW}^otFI|@l&>vqc~B=eNbve#+IZvg} z=(mzzc`?^$%w_!?TA}p+MPB4x8hP71@+L3xZyNc~Jn}v-GB8@Z0obG28vyO6GSsCs z&!qxf)ZTtJ+H5P?q%^!7FZ?yCP%+wYi+MR(w;`*&_#!V^C7Mh$k8~O}-ryyBhbDW= zJXuv<0lhrbY4_98r9hhYrmE~i})#0 zy>OzAN475S0nNW3b?L)%$)nPP0L)Y+19&l`Y0L=y9NMMy;4og~WEwfqJaRlQau$u8 zZXQ{{i(Eh>=ki<%smo%X%Nn?-y}iOcAO?VVxH^}FY+vn{M9`2Broz3BGt~kz;n4ylV8!f(6x4(y4>KoJfbcSN*J|! zrd!D|Wkm1tQkV8e7Jc@+p;$1u(OfH0H%5)0iZW?tXeo>A|MF z$ggN*ig{!UUSv9rY-b+Xh8Nk1MrQC_zN0Q(crH0`QG2_G$E+%OtTenkFMJSH=x>}C zea&0chnH*=O*Y&-a;Q-wkC$u`O*X+i**IS0Od2`OJaQ^8ay}x}&YZ(@SwfR9)Va{L zRzzJ2c`h5N%eoRqZH>I>4By}c;J1eD_Eo&pyJ_kjyftgLZ_`E7m08EDZA8&tcDH#F zvda2yKwUoa8n%)Tc~MPhR3op+4p&yoo}!BOkQL*jqGk7`8_W(mqzyDxeTH%{dq1U;G*{S zP_NlmQeK&OdA#s^sxaO-FUFd;Xf!X`EShY(d1Qf6V+t?XVw!A$d9r!D$dxp5xp`zE zFLFI1)y`bQbJ;?ZZ`8TawYHPGY~#87OkMVuFlzhcMQ7MbUQkAK4=?p8n)(E9&D!n9 zbkTHWCMRfH$>#~SX13m?$gkIADoeX1eYbgnt+~&;cKeqm?y1zhwcb6&#JxRrZ>M)} zW8&VCx_8jKr<=HUrtY0g-t9);?PBt75BhF*z0~(6?!Bpdj@~`n#C-sD@29x?{7O@< z;!ZCpgD{l3=jq)Co4Ajo?ql>YqgWWbeMEw-T{HaVm2TLl&=iy86xs5mu;X{G9CrIe zIfd_q@gzm@H3fP$O)*msJ)MQN+Y8JonkQ;gGdYpH%L&?jC6&6gN;KT%TJoaW)2OzI zCU?0+Eqh1er!=SwPSmZUlP+&l&Ho4L(v9cRi%Mq$n7PYk@nQzjn0|@6yWE?~){x7K z96=+8nn&jGA}7$uvF4GZd683TuG6E;Nx(j-AQp7DIGGBI;V7K-#N*XlF_DP z`}Cyv)Qrq#ZR1i}rApX9JEn9<@_Ig&>eWl?T(d?}9>dW?KrXLdQ~Y z6*`vVScKyW99JrwD;=vry9UR#IIhESJ&qf2+=$~Q95>^*1;?#8Zo_dqjyrJNiQ_ID zcjLInF~+eMul6~XIDUfPeq1?#D+h7qXIwdiD~ECA2(BE(m1DSa99$=$_Y2-RiFZ!n zonP_ZX}o&|@14ba=iqf7UKil?8@w*U>k_;!!|MvXuEOgYyspFRcX-`^*G+icg4b<$ z{Q<8#@VX1HKOJYqdyaGBeaCt6f#ZVs(D9r2m*b-N$Z<*h+i_WZ?6@LkIj@R6oY%x` z=XJ5C^LH`Fc|+{wyeal}-V*ybZ;QFkKg7PyJ7PcQU9rFOPjP_ro;c8XUmWCoAP#mu z6o)wf67!tvoIm1gsPmCH%=x!C-1%4>;mmT4boOwKa%Q_mJA1muICETMoxNP+oV{J+ zoqb#roVl)v&c3dEXFt~@XMfjZ=K$9f=Rns~=O9;sbFgcgbBJrYGtV^xUo)LQx@I|t zx@J3vx#l>ByXHDaxaK)Wy5>7axfVD_yB0dfxE49bx)wXfxt2J`yOug9xC)&UUCW&L zuI0{2t|I4T*9zoZi9G+0xc2~y;%eXjXO+C>RTGVArti*dTw)vpY7Dy=LR*xGU<3>x zh9IC45eUVoY1lFL*n2Or#xC~WyT;hNMq`O3nnYv#-!pUOuxDq6{~P9eT|c~b&X%Wq z&Ned+BYK3CdAo{I9m{BE8=WJob8CS!#2&n(>C3{ z%QnNl8*%m^&R)dXhdBEY=K$gyM4UsmnfAko^AqA6L7blv=P2SFL!9G?bHX;ue$w`X z{giFC{j_b4{fup{{Vd|0v(2-gx6QX-!2OH3UBc}$ZolAm1-GlX{fgT)+^*wx1Gk&D z1@_-;KiY5E7TRyy7TNFMcGtGp{=037{T^=jZAK0S{3d%ZezUzdzs25%-)b-Bx7qvh z+wI@+JM8`Vo%a6xF8cs}w|yYL$3BSPYah(-vk&3-+rQ@z*oX25?Zfy(_Tl`z`Xl)H z^+)mx>W|{r3#0iT>yP0V)*s6+sy~ijTz@>jr2YhcY5j@(vig(wRgTI0YR43Qjbkdm z)-jD==a|l~cg)~7IA-!29kcjNjvx5Vj@kSc#~gmEV=lkVF^}Kwn9uKUEZ}!Ke&mna z7xE|Ui}+oR#r$r^5`K?kDZfQn#%~pt^LrgD_J^A9AeW2fewL zAN=Mz{;*>`|C3__f5fqo|JkvLKkC@bA9HNsk2|*VCmh@OlaB5DDaQ`}v|}fK#<7b( z>)6eobL`>IJNEJy9Q*i-j{W>4#{vGb;~@Ww;}E}!KaAT?{1wL${;K0={#VCQ{+i<$ zf8BAMzu`E+-*lYhe{-DTZ#ho$w;gBrJC3vbUB@~8cgJ~tk>3S=vEN00iQgrDx!+}e zh2JlHiQg4|rQcP4mEW)YYQJmz8o%rOTE83oI=`FzdcWWJ4Su)yjefWJO@4Ry&3SS`YZ0wI1@jYW>acuJwrDQ|ljoZ>`7t{#r%C z%@4W>7yP>m7yWw(1FSuTLDpWv5NmH?sI`x9!&)p1v-TB+TfY-VSo;Yht^I|wz5|4F zz5|8LjzPi}$6(>S?-1dF@AtS36-HZ!2_x;pg{{^R!fov3Ywe?id(wVxA0v#ljuj@_ z$Kn2XVZ3#Mu+BPBxMZCqOtDTDrdp>6w;faQ+BD$?_WPghGlZk|nZhyqEa8&x55i^N z*}^ZrbA&6tbA_wE^Mqf0=i|0OxaRw#aNT#IaKm?zaMO1&ZcBt|)}_J>>oVk8j@t_K zr9_x%T`635tP*~*t`@FZ*9bpY*9vp2>xA#@>xFsN4Z?iuMq!L~lkmG^Gx)a%ORQUk z-u7+6O8a)9yM2eS%f3@MWZxxhwC@)7+4l&Gtb1X%4|XqeFBENhiQ}pTOTW~so0-1+ zb05p&#~fFY3vQc{T2R-|Z!pKZa#qq!o0^zzH31WAKdS8|g0dQ#UO$%igw~ z{2adF0yg6$Q|3puX_qBGhflSD&Gs6M0UpRUnc4EwKC+D_jAE0~S+Mn%h^N%8}a zgB&Nni~J1!za?z&e|f!rWE*G+>8BEI6)l^khWU{g-tiBp7vOKDKmPAJo$tNZ;N1Wx zeM-LL@8{RBVMD96VFTQgpZT;h$31>*;nI75JuxXI;Ge}+ryrZsZ0^`2%lKNc8^a%P z+_P0Hanftnzc>yT-Q*w7@s^&DM!SypFjTIti~|{S$!-*EW_#HMbJc@A$6d19h*1xf zCcxu|+L5uBUXnujyx?JkyVQ=1zx1j!`cD|ykvWj;q!~E6OuAS4L*tQokY15yA^CQx zjdV}4!;p$nxn^c%cqIEwCyo(;8b) zn4X!FT+h$nnH-kWv14I&WeWrp%Hpk32gQOexf$u1S)ADRf7iA-iik~4%j=R`kdvIzDK|MIB{d^I zC9O?bO8btfX({>bQ~m3vabkK-J|`w+a^lBa0~``K5mGlV7q7&$!woOSw5i95?k2d0 z-ztfXyKrJeW#LpnY3D)={2&Qhu&Rob!L~g*us;*=bpY>3EkyCO1E|ZAN}UYFdZ7?YZif z<%2#STBrYtw&z}aH20pbtwD|J0j4u3){DItd2Qs*3N?N;AHGdy zjvV{OvFH;oHn2ubd1cd=+z)HMsWCX%Gna5g&zDZ*X-B_w+e$ zr>p|%(+WNhB%eEy&kguI*Q9y{%gIE`)7QM++GQ|q4<)zP@#)S*O#|>NG|BB8-0ph2 zW#*@J#gzc+D`EaE`PLhQ!w>L%x=D45oDv`L#da^_bLu9MK9by0$Kr4aZdIj}caf4y z(zvAr;F4=a>10;a8jk-+j(=B z++A``oP@&{sCM( zYY`dU7%$FLWJVS4lYr337(CHVdBUe26R&M%c6ti-+urzY0x701ta{2ZBSNJ0oRVLV zmzmuzr69FURt6rxWH1TzUnWp?#uq8sg;`mY?lqY8LL{H&j9q?CUIEv=l9Y@qvcjgf zoULPkw6N1MbK7U+DQUjIVB)6=ckg}l8+}Nj7sR-tKFW(eFEX*yGcphZm(3_dC=wLQ z2~NG3pV>7d1s%XcMExcZQ9I>irl-&k*5ZollCFKogvFSrq;UYT1Li3g57(# zs&G+cK;y#VBAZF5w3e%c%QY#o@!B{&I!K1iqn3uNT=7bbn9vX1 zVR1-%P934q!3dD>uAeg{B&u;t3(w&hp*puvoI_(`qTC_T9EUPR)}IIqke*rQaNRdmoByQAGL)B^O3H(IrgRCpM}(gF5)otfm!Y+TgE)=0L7 z_b?n|X(1&D4!9biG%9E8SdZp-xm?M+KBlI=a|Zt%m}6i8Tu+3#=Z& zt-_3+)E{P}n(k@AAidu$gA^V`!YmCig%&_|y~%&d1x%__v_Qj$|1-VSq1<$?H2uYVph zyi7$|ODm13de2%}uG;?2784za6{^81?Oy4TlhmA#$n;V=#WKAtkvk9);CX(P&#ZKx zyG=P_<3hrkVr0oxgDTud$_m!*CjTg>g_a>v@zPY>REsr2acB-*AfGF=o?n(uR$4)4 zWy0u5W1U{XdF<*d)uCCcH#BqvSE*)q)CK3U-dC$HcA|BL9;h|*3^STo7IGQWrR9f? zu8~JHTBtr)vj;RuM4`#;H=hr@GkA>PZq@xh-J!tjVW2AL zW=zqh7nYvO8lhnK$OT(Puhu+b(V1OgxP{Yd*{g!Nm43y9#kqC1fl3S(-m}o<_AIdW z$yi}Z1b1|NGpMOJcev-^veBm_u%9_$-ok=pZ=8}Dd?sg^J zWxlqiE5>`QH1A$tTl2NqjNOp&TauCa>Y8s2GIlqcu^1V9JH?(PDf{&`y=jH@)Z}L> ztS=dIwC09kp zYmQ(Z2<8w1_A71Xlua<75TG?juoMJ~o#H|Q!F;XFVr-5}q|I@uygAOdmMqjzDPIk; z%q+$_V61V9tDIs9Az{ASW({4?t3bf6r4kL3Qnl;J5TP|UL_5H?%_(kiikk=<`}H>4 zG)P-0?j{W!Q%E}rBU*Ee2f?`CDefhJ%vap(*YNGtP$@%ph~S_#hjSb_N1fskg2Q~x z%~1``5d)kP1P84-oU_0=O<0((x;d@Mtkm;4vl%ZT;{}qD`MR46$fzg1E|b2ZHP_c) zk@*VA%zov~6-{c?VyXPNMhMWFBlsNzcbwuar+AZauwQ#~huv22wKuo$%r#Zd>%VxbtSkane{RganJH-bCl>O?PzrDp_$pcNj0D6oh7p0@?F~LGxF04_ia(~7Z zAy#wgDEDfv;vRb>1?Q#QYq%8Uj@De}n#lZuOMH$bXO;U4E>*cdr{Mt8W?47m=z59Z zpf!i{I&fYkEUa>W)m7YcuT(Rh%6*?qfTQaTLV(sBf#5Py?xo4>BpF(B$$Zh>TBN&- za<7H)-Y3nwmvVp0Y(^0o-zFIu<^Hxo#=2%RHbBODF42!9WtDq9T48>g{7i+tONJb+ zxgl=^9G6QBAULdYcL8FvH0)Hl2b7KVKEXn34$BR!FqarYuo&eYrlAVaP$?($2!eyw z98NRfGO>gPnq&M1j92v@ z%t}2EFq?4*G7cgc8Rb3*8TF*s_oT0A&GmHzG7lq}S>--VlNz;HDnCXN0<`7`CV^mr zOC0AC#}E!yxldrX6)5*{c;+|=^Ozj(V#aL}5=c>tV0UE+O$!|3!sH8}STa2^sIwB~TQ zzzFdl!ouqGf3&HUQn3UoS2EC=%l#kZ_6bz3p|A?wC(wIgk}|DCa-%hu`)TB^8YosK z=^1TaHL$qn2`hfti0kQ3FXVuLT{AT_Op3&O zi3|=}bA!W!%^E1a9w@#_*jQC=)gZl2abMNKDP@u4%2pJoZ zjEo*{gp7KE>I2eOwC4I6hRh)(Gpol#G^ufxFO?SIgaEBMf@UCS8Yo5vij4^etH+zF zTM3kSB<`P-wiR4GZ(KHCG~q*Qj_+ge#RrP91di3<@c?4PUP-K`Mj!=`$r>C-R|3I8 z`){$X2gF!Dk^knUCy=@m9!7t6NAfc|`nwm&injb&`yp%JK(P-=%xdqxboc6`Wl(mn z{saPT`5}e?Vh|x*S@0Mv_Em%b#d0x;dJ3 zlhNCwF}mk;^!7M2*(M>|1d@%>+7k@2O*WHlCbCTr6sMAetj?ZJ>u9PbHxV$i$N-}) z{{Sxl#JoUp4uN1b_B^C!^}-w@m>&rY+VaD!0L-#LaS4H8^z||g%MvY%d^#>6C}_)% zvK}aF1I5(@h0)e)H7KhMP&N=0wB<+H3Y5)+gVoiWwP}?tW*fgxdC`_X?_uOU7%1*1sTnT2jvR5E(eMi1I6=%i`CJWH8>Y3>Uk}gQYKdk8QSub-3Hlj zf#MB<#c1f?G*maVEb^kgLr~C`ALTEg{1GVLBPfi1{zHRu&j95CK|x!7l*d4ML^v4j z{792ksamd)iEKWNBE$-fl()Z(Zm!TsUkE+XNO|Lpw)}nkFS1r5Sy|0oNs|_uxl|fd zCfU)JKl`)D{!AmWS|jl(!ocd~XBv^M0(!X`?q48!`Khwmo+E5%%g^>2*j{NQzC^%S zt^5jL7=c#u5|CIi1Fd{k*2*}#UMEOs|1Hw5(8@)BbL4vUpYKPA_utp~OOyNW7x%cV zqnH1BUnvu`<}yD<=11>~4@q)XGe3G?y+H9$!-2ZFB5PM1U0jfYgVr3*6G0JT#UN!M zSoK^nsJQ1%Z}t3}On{^7KZF3SIfBYTMhdz#Srw8Dt+`~?(A}pgCK|yu$nulY=RI%fYuyA z6A(lMiQxo-QQr~R9Pdb*BmGO0a1E8BW+KgEv;ao)ATc^fj3OkA4sT8ubTkOqwG^dc zQmQtV3=vv$LzE1*q#!XNNNh>iSS_BUK}w*wEj4gVA+;uqXw5NZfH5sdOeKJfDo@k! zrD~{@A!|!;(3->P2%HWH73lRIc;>#e(a^s%=~gytF=0h(j&%rF2L*`(2q>%E2YHLbk^!1}0rX8-x#Q^i zo?xN$G5T3Q5c= z_G!VYo|>Xz0MA2NFXQN%Nl?(1A7w63W)lupt41k*9ZWk!f#;H>m_Y^ zRE1yD5GktVmKlV93nm$qMWfA6c}23kwHmyOkjV4*dKH3(P( zLd1Rqi&5bNG*taGRLY5aFu_4<4re5AhKGnl2@a#ghih<#8sLl~IB3n`j0etG!osTY zv6|FO*-Rh=Xw4B!1;J!Oz$)^|WfM#z1Zd3>%mKjvE|!Km^dusM#CHb<(;XKJVv zWi!_-#!_G`4iOiIhzke_qs$l61-%di>{?o&VN$Ag85tt9=7wk;*w%!It3t#Q!p5re zH5#N<6t_eJ#}v|f!id%!<90A^4G}jJKt`c&)$ncBP$@&UgW#YwhqE6zdqc$C1cy=S zdo?(_4R8(+9JJa|FMF;7W*iIYhijI9Szwh22)5+ArgoNzz6`Rr|%VS+5aR zwB}fU2kV^>@fHDPmHQoUaaeLoQ!juXB`bFvUH1qU+HzqnwUEDRc|J5kd={UE{tP|^ zkx}l?h8FjjDoF`1<^Dpb@-`o>xy-L3^UI-PO_H2d?k|U`%DtwB15DFp-HfB_HG+fI z91ag0D`8=kyEPR514*hGPvyQqCcx1p5CXL32ppkC%Dpt1FG+^hT(UaoZf(+CM!DC< zcrTFV-AlQPW;6OD<2xiHquk#y$XL&8#sFk&7%Da(Nm=FIkXBd&O@5}roMgz+nj7+9 z-~@$=jR+2_+=BoyT^e?(+#8jR6+*Dkn!}0&R^w37O|Tf{-dIEB)=()Y^bZLRT5~ub z0VgI@Y({Vxv<5*dLcl8bR%H`> zLI}{BBggFGz z>{`myFez1=ONI!oxgqKTwl6}(!cZ}vu(8Vh3k^~s#m(2iF@@BXFrqcb*d2^Tq2f0L zkWubM8oqBdRLYR`AUJ5v;d}?2;!v?S!C{npu?DBN0Zu=HgVr3*VBicSER1p=sL8C< z^ANKcha=-ql95sFLy=KWdW|4`MQg6FV~}|i$;>MEQJU1K#Zvh(mJpydM=%WpQ$oc_ zq2dI>!7BGD?6v~sJ_*k(lQtTv+$WUHI-RhhHOD$1taC%f*#wkT?sL7xVaaSwy#RW? ztlV*QEg)EE%Z0UERqh*rwT>_`%6%OGN+c=arQA1?%xKMJ-j2*$L&eP`Ijh{a(tT~S zh67A1W!;RUYX`wWYYt~GaCQ?GR=MxSf?IQ$e%@G_jRPLq84wGbP z%_TdE?j9lCWt967jQ0j<-o2FjF|!#@A>#>>kx}j^3^JZJoADwto(~nzlBBG1KTj*{ ztR_EGVVB5|qcu0=*MakEsCb3ou*&^cK&+I8ohtV$WnL$Q1LdwVwC$` z4b^Q8m2yJAPjJwh!+8XphoRzM1cy=X4>dS{8Q}awaL}5=sThVobqG_gY_Q7R66U>7 zn6mK+BY(&cW|H8)AgDwLSmj=+Y=X*!0Ij((cm@R3!o;Tt1f$%mg%$VQENzZdxj&_$ zQj|^&vly=c{puwqUfb$-~L2C}D5pZ0Dg;DMLS?~KVg zDAkOoaz7*!;OP325TG?j@NJmUHTTkFMI;$obIE$5yWL558Rgy`<9$e)cQ57M%WTHJ z$k>NuWR!a!gN)yq%{Ukt2Zo9LNm5q152O{=Uz4Ayupwl~(V83bQNS4yCJrMwta2X# zh~3h#Q{_IaY^>1)3#~b<$-tTzCXOdqjB=l-p&GBDQcmbo2o73vI6nYqW|%mg;4sR4 zrUqxa0nTiKgVr3*0^rOeEUa>$r%BC}&5wittvQ0FAXrQYSmnOBY=UKk0IfNKH6U0O zCYBHgM!B!T=6FQf9I0|I(NHN$XRTR`ZNS(PCT`&+X^{3%++7+trjQO2MzrP_kAv}On0SN$GRpm^hVO`m zN*S^f1P84-ob$jr8z!D6IE->XtHC*KfOCQ1pf!hc1vr-p3!~gGYcebKeAR5m8_0N# zWMq{4HDuJ2UN=c!(VFY)9b~>mGPBD4mL@f7u~dHCB?M^A5&R8;2Vvr$Vd8zl!7BF$ z?6v~s{wJO}E^Rbax!*6F^$}r3YmW6l;rK|}aIr$Ta{Y!??mppO;;^JbxVL};^g&s< z**n%Wwm3thm zuojy9Ooe?+h8(TAA^!w8$>CxW!C{qqG9b=K!%mfZQrTE31PiS>taiZ42p7``7NguV zG*oFCD&>UUp5UN0hm!-Gj^Sblg2O2HjvAZ}1~|C{2dz1rLg3^R7FN0EYf>|1(}@tE zHAnCz2)YmgR=Ia6o8T)#fYuyA4-j+<7r!MCjB@XW&GE6cIa1~Rt%gcbIz7!|3;;&I zaItT=*oTlX%Do?5(0xI`uBAR2CZ%czk|9ECZiq&LZFsmiG+Z1)*jVL0T!S=};ttWk zF@-dWFrqcbI0=js!o_g}kWuavG<@SURLYP|COBx#;miWgjBs%p!C{p93=PgS1DqcS z4q9_K^MNy$urSJft|qfm&kM|ET#SqhNk&GwFGNN?>9vIP6|K3xu0ZBxBr~hrmuXU? z7E9$v2_Zmhj$k7Q)`yF0!^PEvgH`V9*=+^NeJ!5p!FwwA)n&78BCKf5vF--z&Tw%% z0cDl@PH%BovRzXzfPN?|cN|@N2o~CMVZB&^{GGeojc*Bb>-?R2n7g<~Z;X_;a*uE; z?-|gV%N&KwAG*aRBsr_xKXmsd|3kHjh67CJW!;RUs~N#TYYwLcaGDbqR=GEK7x(Nh z)r_ZdAHYkW2ZN(4mJpydNAR)RNV%6LOCZV6noE|9?k17$GRi#(<2^u{cQ57M+HA&D zWK1C$8Red0kg<)~jO~%Jty@edNm=FImR4B0CO=bQnPkY(nj7+5;AFeSEP}%-_iR9% zXOw$Z*;t>9JJEj1T5|*gK+um6u*$t(*#rX#0a|ke!$C0AEe;_N zjB+1}&2g}_Ia1|5L_?)0oe^d+CIVx;TO8{aM-vi8xsRs{dMpUowKQ78q*U!BGDK+2 z4bcx^o9Py(yTz%5jaBY5HAvGb?o?;TD$>97egX(BLdHz*$9b(3-z zB*a)EgYk_sQ9DbR8kt(Uw2^@dP8KUYh6x zNrbliiO!&#r${#$m3|6iyib~EFO`1QOty>2cAjKo6#99CY?sVryM}C66U1LgLROt$ zrPcI{CO1<}*U2!WE&njz1`#;ItP+2^?Cj5w>}boMy(Y51kSIP!02meiLSk{x zL(-;4RrqrnB1N^lWCno;f;CZmJyCp>P%sMIny8)vUPpFz&Ah7NQOZIfLxZ;bLsJJ_ zwG&0(M6nj(V%2wT4UR8Gt)&5D3P&V-Xv@#{F8Jyviv9$SQQq}6Z2lS|WvChw6tv|> zc^@c&iK3IBFseIHgW@zm2_h(H%a0NUln}zfDDDtVR;6~s&17qWY!M_IqqZZEO;0jK zl0Kp>e;=D6Yg3YyRoYE8X;F8j@*$dJM_c~vA0vBwq8OVfenc2pl^xG+8&KJ?c;<+- zkx-TWQQ4dcgcEJ~Ia9%zk|?$&kgUQ^0TLtVN?L2`1HgM_g^i=D4M9TtZ;_5A##l09 zEa|ZvT72@$Nq||COa-GhQ-I{)h8>yS@a`5Ad-7}Lk+H4Oa&=thZswy zl(PeJo2Ui`5C0}Nd z?v{h)ix^9x#PS7Lu7SlbNvx}~bY@xnRDzPa>b0x=;`XB(}^p=ruM|upl`(SHC z*^2Qba6JmWk={@R$w+-+EF(z|%Y!rk0YK7ECcz!)F_0btDKtq8rc?v*JWCZUQI&*B zN6#e|E^`fnxy&U!EDzUE1OUzu83%Wy$Kc|U@KH2LqMLFJ!}Fl^D6z)sXqC9td!8j0 zDf117o6ILYEDzr(1OV1Z84Gu$$KZPce9e-?rj&0qo@e=*C850PVAMEyZ)nOqB>Pm1 z3^@kAGNkmdJdooN0BqxAHr$aO1F|w8nkkb$VY?Ea++>ssw@)#G_26j}8a#ab>tien5 z<*!r4FPSew(|jXmUW=#Y%+ka1WZs};Uaw}B9wT#fY37Z1hRNJb&b$dv%bBHzrI{;Q z+B)ChES9G%7E79w%kRJySL7=CJjq$Oq9?0!+*1|)Q_<3qntbNuGSfSAy)CfuflYzM z(%#4`pL*pwxwM>)xv6;>T(OTD{be7nWn2(+*efl?$qR4Ba^-~b#DMO zxIK-0hESh@PA<0~&to8R{{tpVeDb#bKzUO!&&so%Sx{=9zYBI;j zWEo79(O&H2+U8|sv@Og|^O&Os7;}qdp^^J~nqiH$E>`LHsKhAPP8w{RzULNgj!j0v z4$)xy^@Hs-@;pI3kLr6KG4ebIPh~Jq8<||D!7q53(6x4rnp`n5xkpXzlrd|!q(zt8 z#cM_z%QJe@DD-0*`fsB(Yq31=@}?`ZhD+T_s=3&$q?x*SU!o>2xHMbIb4FfoP_I{A zI$KG!8r@Fpf>^GZ6)FI_y-ty zMo`Z%ea{dh&uHq|RNphw$TN<5eq>~lL`^<6GHC-7WwcXVdRs|zx#O*k+_PwgOl@7X z)9+D+QLs)lSiZjJ=h_@OM!~+N!M@TD*44#vo=mzbegT?BY8&07=@lgL(ei=vlhz?FK@as*HQ1)UM6ws;@wJ3 zHfg7GgOS&6>a{};D^ZPpfY`}f$q_tI=Hrl8+$7ch1T{HoWOAOSKI6TWoHFwHmHPbR zT|*URRdUJ5^DgzgrSEyu$nzof{8QiazLBRTP(1+_VdU9>div{o zzGLL+f~PW=?-`kVK!Z2(GNEfNoSK9fnM6~Qre(}pWT4(wk}S_?W24XsG<3Y=?)^?e zTC)~Qtd}<}r(V>%yO&9dx_J9jlfK&N>|^BhJ@p!-hxMr%eI&7yw~}#qpv=c;uehnI z{bXt~!N_D5O+6jJj4GLGr`6eb3cKp4+JBW+Rh5 z)MTfT$xkp*M*E;{QMQpwXTOpA8Jgjwwl0qA_volmu&XrKWqr?!+8pPNg59CPe$x+j z!^rai_54HM^PZ6>*GL`AM@A-3z(l#2P@xgKyVJE+nVM8GGI@@gJkv<;1fa}XwMKed zNt!&PPZ@=NorZoza`)a!q%~`?yyWFgSLR>utKGZ*KHI&v>f+^sRFg;VYtB9ojlBLt zy($LjU}dY(s}MVRE2)kLN^w6G#M0!b_Rmw38b&6s($p^nd2J;x8u{3%k1fdSeA-?f z!8eRNMe12w-_zH~^Ihs$Pv6te$TN_71{j%yP?I1dlSr5-qa6{XSCn~j$HR@>V`+xw z7-p|)XwmvTiZTk;ng&bK_e{{{XlWFzEe)2YA1u|#Gn;yL(D%$V@+^R-GMJwmnRKDS zJ9(MVwe}4)`O?Uwn40t|W7c{|i%#H#PbqVkd7U%ke;&k0oAlyQ}uAsY!{E$tIe5 zJ%AZivew9F7xmd5?6sAADUbhFBhSOs^MJnRJ|oYQ)bp6W=g&r-=c(rzBadhXTt+->CfGdz{SJZxlgk_JEKWkT25Icjp+$mAL| zxl+cgUDn-7Cdo5;(J1si8v2gWnzdMNd3n>7`9i3AHh4Ca-KnRli}y8Z@^YwVE2(MZ zB~UMGsLl>IUybfd?BuOP!~#R6k z9{)y0o*z=r#`>OaBhMDpGe+ODnUQA#^^7+%`GlIZGBRlk6J@m1LiNsXi{y@{8oB4v z3>~#~(LujQnMT37(qLccdlqVQs6O2MHprPj)tyzm@wwE_unH#D1IxmwF zb@A??CR?@Bx!K5TANAU;hqYdfewf(FTgfpzQ0C)^SKJM%{b_1)!pP(jO?}>bD>-ZA zbA$T)>Rm%CUsYxXxlNvBl zM!Q;=-d3_%?)Xzi?yu4eFNJANF)xOBZOFdEKUi%e z&-bWj1AWhWMxO7(QyEN`kx3{G{(+YXU2Bc0Nw|^8N7N*`j9H5c)7wh6%QO0+QRr4Q zbb{pW{RT%`vldHBFK=3L+0?s(m&qBy@=S!se0jo zG9TT&;vQ1%zoRC7j7)~m)B^#`sFMChKBKA62=5x&Esx+ZBhM++bE3ZIcq7l*)N`i3 z=X4{_AF1a&Ba>y+WU-OST9_!Ky-K$zkH{S_F>>EdGi=e;#U}k8Z7>RUkOteQ@3}{t zW0z5|6ExUS{a{CoJTFksv-+N=jXbZyQyI+5MkY6D@M~TsbgkW`Cbx`C9#NAAWz5>2 zx?9O{c}DLWg{~B?o}qlgb+!^|%~~uK!r7A-U6~E2x4)OkDLBgOJCK?Lglo<|4UN1) zs8^64)}8F>Vg zj6B;@&kTLfG$YSk>e*4>vxAXmC+eARWbzd?>0)Hk6DG=NcMI23C6DEfe{1AEkY?zo zt&6_;J?di=Y!nSPT;Fr3HpdX7V3TRE3Hrgt8F~IdJ!j~9PBZdc08eEw=Ng$Tp}`k= znb5UXLQR$#nQWpa>&uw6wbG)~yuqo6|I=WxtTqb0hlbv1v}P@q?Oxt=Wk$HwjVR2` z?l%8HT6ujpqb47^HCss&Bd=KM)!ePK!&OzIClEV1Rcky@<|D}~?o+CL8)}kbWRgi! zw*@e>m82W_d`^9`-CkSCd3i-;8F_Z4o?qyD78-eWr=H*Hdwy-?Sxh~98JP^ECjE>| zM!-ZF?V)bHt)#kKctecbC(#V!wRJI8zel5ug3YGEX6k!R*XEdN6l^gK_M?8V`9_|r zsOJiO&t*oQ8{nx7=2|0@tu**1FB7`fc2SeTM;la>t)Dau;X@YoewuUf1u@ zt46^@8mzXyr>{0gEu&x!X|VeG!TgOpgQ#bqzNgd3GaR1EV1^i(MAG09UM6&{MN^Ze zMkWc=B)*JUi%rzqN?OV@`jJuSHZ*jK z+DPZsaQbSfcdB3=^GIsm*xTH#V;)1zo5|)L|2wj&Y)+q$C!r-ZkMlNfp<|vx&0BlJ zv|?c_mc%5kV=Dd=r`NQ%r6JO#5Z$Gsu;9OMS}m3~QV7o{J|!VapOc}pX^1Ru=+9Va z{FhLDif>2=IbOHY2UWSsa*=XemAvPl|Mf<*ZZ|gH2`(A@u7AbPW@JBs|EwG4N{-LZ z$jeXeoROE)IXOHdze7PzZgR`a{KC|%_>8uhB6?krk(cZaZz@JcCUG?_nY=dpnY%^`AZNJ+_@!R;Z{19O} zzeqUG|G|G;(JB-a_NZE9?P>kaI@CJeI>|cKI>S24I@>zm`lEHZb)|K+b)$8M^%v^{ zYiXo&wwrRavHS!cu@Lnre~drDpX5*RXZiE|Mg9_^7YTiY{=yJpm@r%zA&eA838RIv z!Z=}qFj1HyOckaH(}hLCGGV!}LRcxR5>^ZAgpI-`VY9GB*eYxjwhKFiox(0*x3E`u zsc5W)x#W_x4+tSP#JNAf7pdXAa|;pYY5PJo7W2If`eF;hE!j z<^;G-BHt;zavHCk!7FF++Bv*>9Qudc@gan`+;PIGYe> zGvaJPoUMqn4RN+3&JNo&`%c?*`!3rI`)x@6Kz&x925A> zj*0vh$0UBMV=}+ZF@@jmn9A>POyhStrt`<`Gx!tsnfxxtEPl7+2Y!!ZHorxf!*3Pl z@_QZg_v*{($30{-9$af5@?jAN1y8e(;-1_`{B+{7;T${1L};{%6Mu{-~pb zKjv7;A9t+cPdHZdCmn0}Q;xO#X~#PLjAK22*0F&<=h(=fcWmM>I5zVa9b5QIj;;J< z$2R^K$98@dzXP|O{1wM8{;Fd)|EpsUf6cL%zwX$_-*D{bZ#oX}zc~)_w;YG~+m6Hh z9mh}nUB?mrcgN5Cy!uD^`Sp+S3+f-|*9#~3AM2mw7uG+;FRFi@oW69^K1QX@az0; z^6UM6<2U%-;y3!;<~RA>;Wzu;<+u3#&TsX*$8Yny&u{npgWuuzCvJc7J8C`Pch-8y z@2d4Tzq{5Weow7`_`S6r^ZRQR2{%9JCY<%}E}Zl4Aq=qg6b4y)2}7*Cg`w6y!VPP& zFwELl7;gPe7-8)vjI{O_&iW1z&iM`$Hai9hTO5Oh^S(ob3%=juHdGjG9VU#l4;Qvt zM+mpEm#?*t67EU+xqXZ<);d<0Xdj3B{hDf1)Sw9As8!>3xnW@8P;01srF%xw8- zAK69|MzP80EZaybqoU=|B>92IL5`E(MSceV-x4QvJJF^^iv79ik8h%!~94L z@AwDQ5Ad_nAOClq&iCGH@NR&UJ|*Ar_w#Gmu%XrJ|89c@{sGccpH}9$$B!*sdhf3% zCZz=Yv$*Q?V{@9#9eZRMUn_QFjaC)7XRB7?q}OgHR^V{aP5$v5Z|MnXwCi{eL*?qq zIFK=y?7G8dwwGNnS3THs+$Fm&9Ec}PfX5HDBV#YUB!!w<+rtQVsT~=A>D5W!S-5FN zc4Q7DyEK$k_)->-#v}6}*)@KS<7T?0Dk}Yv>@c9BRIZs>8F?-q+Om0GPP@F+j@Ae~ zlW+Cy9MJHs#Tux3_ zesZ%|-1Tozx88eo>pA`X{gT^cW+ykv$uCFZv$A;W3xE*|y5wf0XJ&C? z+y7nL<|raIIW4bCZb43RMyK55jw$(>?K)-T)lK8X^qhQ7Ov>cMkGTdoByb}1ZC);3 ziD`!$UW{o|j}zTZa1Xyq5*v5n#E8s-m^Pn9NFVw^?uVxqq~dVQ8VqR>VU%%da4Fk}@=INQK?V1%9puGG%fBeJ3xMw0>d-!|wU6!xl`wWS@aX3-P)3>>s?%f~v(b5F|8)tD3TKlehNw#@9btip7>A0gA2 zpV~GfzaTZOL*4dVb<6TWpAW6me?{AKFFu-k&)3$VM!5M5N}3P1> z_~aEKjecBuXz23EvuZ3hA3Y;4PmcY8HRJx*$?e{**r{EWudZess!{*n4?0g;A_ z<85emYL>D}vohPri6*z)>ho0Zhx7R*M|j@}9|qO99%g!oQuDL@<={1s_#d7eRdI#m z{)w@3cU8VrW7Q|7gLi({&zaJxZ5KH~qd$BdareLKGq-V4&Fhu=eOu#Pn&||&9n$jO zlcV>XIrgVZ+x+~xZHw)kIbg>18tXnb9bLkggBQHq_g=S;#w7Ks{qcnA4gPzv#_7-h zb#S8@#s-{%>6Y`<`S@_>pU;2#$FQRCJ&(7AuB$OAzr1;*eO(Hjm6Mhw$BtOO=kb&8 z=Wh9?($+dRr!N1!#)%ir#HQPE8n&JDahK{^;?gSyxLzN&qE%pxr-u}9={e-Ag5G5o z;KF@HNxT&GewO3LV2>>NvjBTw1$^>i(H~rs>i_v~lTgds(UzR%mX$3m(_<}x@s`+l z%dmLMlz7Y2X&-U!md#VbGuvUWi_L789jSzTLJm0&A;(K0M}CQrt@?A^i|wmFVHr|j zdAiWkv1LYHX4@_r*9nqq!dGxT>FN5Jr>m4RA`=S|{ZNulLej~S=SyG1vo$_AvdC>| zU%ld!J7X--%`I`wDcCdZlyGD8W#Ir z3jIVbu4o2Q;HL^Vr1WL_TPm(-ruy>MPvD&(t=_1Zn5OZ~QzW4ye+Cp+G)pyF?+S^H z_D>0I);u<@MPzhi+@CL-P#1?cV%4BLe=Py zD>O0&UhNbqT7{dHPCM1Y9TwRe?DWuW{7-Z z08)xNj$yP5(%*r~UDzFpWbTBNu#l*z(2%gE$U_kqD|vk0j^<)QKTOHaOs|)pO=qDq zUR@&3!sRr1hmux8HZu?tmA4u`=Yr`}Mm0%E&q>Y7;<{Io%9<{3`r?8b$u9-}({G7Z3%43DiDml-2mq)e9g|=7i^~*sR6O@tX?Cn=yoTFP$ z9)ov4wLITCH!rhOYC%Ryhm0=DupLrf^T}oi(=#$q_ox&)9HGGcN$N^sb9onQ7M>Co zmmu4CPUB|?cSP>ZsTcDzyJn^`MaF41Lza99Vrto;_N;e_-q{$>BR>lr9qNRW0%LLimFnuILxF zlWT(2T?$)7cnr3ql!$ozZ8cY<7Qt<1CAC8lr00B*jdOo0hPQ&UO^io>ugVEelx~0S z7A;apzrsV}LJ)F4%8|db)m$h>l_xYR2K%DNdLcknxQkx(;9>Kt z+OOKw#^daAO?`D&qPm&66XI~Pi;Ri(%yeC~`%h_aR4iJ){nXBcv{r+KwTSX8&KpV? zpK(m3bj9z7=uAo5%uRXV+Pe`&9+k-GICo?0Xdd9dsX+0hCgpwT7}@71denk+GN5Jl z7zVfG=$n;A*fKIU5*0@KK$l=jU|5U9=5aA8Ek2fp9T$k?dD=kMZd_PgWHYI5sKZw6 z35=e^Z>zK=p2Zaw)2ulutvh63qM1z#dp+IP2EpR4Ony8c<03DDP&d{c|eLiBko?Y0H_FIw>BV~?`32I%Jz76nPDK%A;8>MG( zxnP>P+h zEye3RP3!GdHS}|(GMDc0ud6Q>maaYN41(NLx3!@!QQbkrQx$Hgrfxj=-cW;ARpv1@ zt6dHTp#Z_3R9^Dg!&HqliS(R02$M8Po}@}r_te2vmOkwrujY74$sun~9tpxcc3nwQ zrx)hZ?d>~E-85wI;X*v$VP)r}OQ#>bw>Hydo~v>#C>kB9+-e0J5Am7;)KAJ(#%_$u~NgvOW$-m1(3c5Kci^FrfdP_|c zNY9gs%A%E6TebKc8zwHvVg{sb6CBc?!OKICufJI7zVWsiViVmzJ|GFE$Ckc{kk92AZBq-gumLOQBV2i)J6}Fr z7E1|p6e#6#nRLC&^L=IySS^vW{VJb8bLkt}WRh|qTN8!(?P&_>TEkK)#Ytvu=Vjoc zLI!>%tBQ*euv;eC#WArurDheD8sT?_+;W*@tKOV?6moz%6)#gm=A7ucB|BBy^`RaY zZ!n_Le@McQ&pgd^(C$^h2&|Ne_UgR*@Bj)_lQgBPT0Sw*;vw?63fCn`U7sOwxJnip zALsV0)<$ZePC9lT=aBbRyBgZ}Umjfad{jl=QPArb9Im1PiBl$`3b$2}H*`Ow z;nEn^)a>+(Z07wveQW%zvT+g_jM!Fn&-_YvJn424s*dN+^1ePEN)#ErI{lfaC?S`IsVa$5LzF0!7#bNzuAzWe zmFC|vyvi7+C|?JnT$HN?;=MBQlyv32Z|N0n#G!8pmxN>gkc)_jBe`BYH@p~?XA|>o zAu`Dw?tMkzYY(MKhlI?O&rW9AJ>Thn4c7fK>&Ij@$QN`ag-mvkD%|Uzs{5R$it&`& zAE}(@$wl$Z{QN>(6vy($?=bQ*Q?rz%N6yVYU3G?#o?rwZ9R!lkP{yh-Te--mz6p|c zuR}8V8?-LuHv=AfW}M2EnXe^Y5AUjp!`<#^S7jWYa^A@6EebA}V6 zqb@47pgb7pHHZVPI!nKGDab2?M3VPddXYAWB1r1WgP^5KkfNW3&h*Es;Q;;Zg6@t9 zs^J9><%!{-SJitdb%3YH1+FSwuAYGNpiER_zT`aO6W(ewkB+8`VVJZMGU?N zKK*sVL;cH-9>bBNF#0qJ<)k<2xrKPsBmYKGy*~9NNN&mXdRY~#^8TtSjA_h?#Pd=@ zBVgW^Jzr(FE)UW?lKvpG;>aaA^nM`1J>L|{e|X^eu5bWG=N`~}K4FHzbHP6g`uj5dhD7;9Nq;YcdETv_C|4*D z?&$btxVRbTmP7)r>VBSobwE4th1!9?=oyY&XQw8e6%+jZDp##lQIS+N|IdE@r!VuJ z6M%2;Q@$P(->bJeAVORjAb)*ut&alMNM9sa^aO^pWMx2ck76sn@VUE{ivx z6>EK}rhgsj*<|}jGPLHB9YS{xknXk#Skt{yMXtyu_4WY9d#p6?=s)JYzcotvX7j^l zGag08BP8QE&x}V5G9ELV@eDGa3J_0_q+QhtvrGLvMJw!tCO=bQXUUMGH8o1K$WoL2ECDP`& zRNfrtTT7nQP$?V8Q)V$<0LF7pv4&HuPDlz#aRf*t&pFjoMhy_KYpJ@1NvYZw$q=D6 zH$+yjz3voWb&4+&wpQv?1xj$QYmi>0xG!tqm}#^TMzrP_-vXn z4V5xvwFwSdb2$FMdB-V=1gEbj&N~_$(Ez6&!9i;d=RM%OOIT)lo}S*-WLD}qz--1w z$mk*&XOrH`(#wU6deZBC(pR+R`Wk}FACSz`q&k(f&ihiGexON>S}fH%p@aafIfAAj zh;)jLouZp?WUCxu5=SJvtt_>cG{!UAq>X01ywR+;mblAijUudQ&9TOVHP$J9L_jA4 zRFZ;4A4;IHz+%K<$w!)c0rVJ2E=osNOM->ATv*EY*+aRv2Uc6c#3=W+0N5ibI4|X% zNiw4~mpKQSJ37Sbafgj_tIovl4NMjCHofL{hD-_QSM)3y!T1-?xoy|%x3I~jNM5_ zM!9!4$k@wl#(v1y*D3ZPNm=FImsVIGO@5}r@O|d;7s8`8H{?TsGsGzlA~>va9|DNY z(y&wIKB#Q0VFU}UIjnKO8sij45iCZzkI_(#(oiWU^zj4-tvQ@&z?tF{ClMS*xlhsH zOftZkPH@ng!!nHgpF11J2gn#DehJc98*Yp2qRi^j6Z?#kW)NB02$?eNW*tP zL!}Ja5rTu(9L_1=oN$WA2o9s%PiSzC8Q`2IIB3n`Tma5F!on!`bDGRbJzq4N@d`3t zCK(y!ei<3{q}Nr_SG4B(dIOoSk<6@ezotozS}c_xHwgh+a|C~Y;GR>w>lAMj4pzC} zW49G3_q%xJfV9z2<$k+t);|d=T63%xSA_W3DLx{gta5+sEe=Z_Y3c>gdu8R0qpN~T zIWM3s7uH1lULY3#YCR9EXI(ni+@Ez7_c$y`2`}aT0?CZlT;^Ai`DK?_lO$)A`^zr% z0!mFShkR|`^%?;|YYv15h?P*Vn%(Lu?s-hA7EjH7T-NM3x&%Ui)*OMuWu)0lllhWl zXw4<7gYMQQ-DNa;ZH)ABX~w-YyJ$9}KQg{UGBTR|9fOSZ%w`Ng#)dAj0ZGbg_J*{! z8ffz4_b5H^n;a(@Y_#SEI~X8AF0l~-VbyvN()VDlvo|sV3L!vf%>hLMsIg0Q6Cg&X zH`egDwLDmtoa;k^gVr3*N5F}3iOmQOqtjzFIL!=jS`Zwx=5Rg+PCQ{@b$YxuwNfex zBsW@fxmzQ5E0UX4=&g)$e?oGjHJ3XBxzk)?DoM|1^E7ONC#<++f$Qn18WKgtv^5Km z1AvY$v4cy@Bn*ry??{(y2N1ApCR4+tNX%R^IB3lcP8YC!;Svj7Vm@JGRrwbhq(X|D zuZ2^}rYoUCYmTlv=!#t8Hw2B*<3$>>Z?rt}g6=_Z(3->f4miawu{XhC^mwrbr?&x4 zKZ1kS9L`|i3?wX!9v`U5tW@$4vl)jY<4}^3(c?prQBP2fAbmw^uCHT|c@)Xa>hV#U z)HutRN{g|C0IfNKX&{*55+}LD350{y<5SeF1WJ4o?w^#l6-7iqp-hH(U%I-CgK%gx@#85yCAq1@M9uipG^Q^b- zJ}2vL99{n(ZSMl-Q?>r_&(}5K2uZmdml#niLN$G9GGlH+Q&P-*I%ZVIQDSsC-H0@D zbR=?%M4^OSqA8b1CAlP0QKB5Ta!t8J{-3?~^L=KXz4rS4f9?JMpV#mAedhc1JnQpb z&sux!&+Hi*N9u_F)hBi^dG1o7NhE~mUuY_(IfbSv{Pq-dcaMkPo)$!H2GpjLn(*4w z4QexksJ#ib*&WmyBq)9MY~Dw2Xxikn-=YR1`fu<;KrHB><`IPS*b5*n{lYvG%p!t8 z^bhksVBYJXmJ*Ec*Y9a8OLZ3ecKiXMAo@pH1C$RtsFj2wy!D3~%1Q&uM}>A7vd- zJ|Pb2t3T0Yog?Nm(na*Iy9v4*NLPC54JO^qq>JcZcRO^qbx>cDwD8m0aJcy| z!f_#A2NB;5@m(F%cOBFY(idKO7hjg&L0w)OJ2W20OYfnkAo_30A#fe&p!Ri8dx=Z> z=mQ$gK1SWEgE`yeXCg!NPxdRwj(1Q;2}^kB;~LdboyERrPZA2Ef0RFfa;AeiMJU2Q zpV3fG8Bop<3Zj3MP)9tmBo5)7FKDXHt}WLwfLbM}Rp{s#A>o@Vbo4etl{-2{2+{u> zt3tI3sY=gWMU#bRF0}^LNFC9?dL5|O?x<>ZR5ge}`sLak>8OBTu8FUIBEMWCI@@K$ zhUlNI5!f1bRP_l=dgX?I5eBWKK9HoDfmhybdu6Tns(0ZWy1U z>c@Nd<@)i(!}fXj<-f-}+XOL~ax*A5jaQ9HTzclF@e$A5SmVIHIbeHNyoQ?-4q`Bz zR=~N6SfqQtD!zF55x09jY7^i!d^Hgu1|w)4Z*tJ3Vr@taF_>6;Ot&pfSGef5==V_% z7kzzD#hajbBPj|eeWO7!98|Fr6yxJnM-r88I-Yk}M@?Vsumoy3Vz8E{0VgG1B@vGF z)hU2DV6~lp(^=EYfM`XwqWaTzO|Ui@hd=}E?YT!RxE=^0`~495687>nc82m%zYyjbHKp;0+4 z8$~#X!EnX`XH2|$fpCN~AEV*CV8D5aa1evxOa#u$#3J1J%bK#YpC<)XoC?J$q$nKv z6exOGuW2+_#9(us0p;nWEM59^O&WW#)PBq)0>oehZ-d~icr_(C}}X%!mRi?sa$=p(js$7^^QVIlritRrYv~x?U5%kv^;mg#WOAJNl2tCDrlC2L2*q@hLtnsIgu@EUGPEkF#`f|dYkk)WCr z(AN>52^LTbKn$^f@YevFM+a&}K#0MBt^-i(1f>Y*I|0~^ zC?_PSTSz=6!MQeGv&0i1egF?6@KSOMzMhE-b=Z_9)^!39=YEqE6yR0>q$Q{n0;pIP zAgv5QiUFW&P=GrCke;Br6TlyII@ldZF9Xos0MH{Sz}*1oN$SVTE`Coa7F#`c&L&>` zUbOg#!4^LU%2^32gT#NQsn4<&Kg-%^cj5m_G9(5ck-0(T3nAYpLFJSD9+H2{lJA2X z!#wN8Fx%R1crD2{VD$Bgu{mIpGiM%=O{Y5>kHYYHhN22*|&%2P>M+_I)hWj?j0lQLp3axWi6K&d_=Ae zD!&f$pCqV{NM78sKEaJ)jdf$-Th>PgjL-f$#$xNctWA+y)&XGbOHe-&hP-9%1IIdx zgKt?s;*-yvB*4gMl7YGP3 z7*M4|{KPd;mBW9Yq$d6*h`eQ0NGt^^hp*)ti4Ijxq#wj41_Y`Gpo@t{+_Em#0GwM^ zby7wQ){2@?u0hJ;mQ_P4^Ql#flo5j|Uk>HV64j+7E^b+uK|FHHx)fi3V_he%ThjQmZ+K%fVgEfD+AEf0MH^Rz|{a~N$TR3)e?$j z_B}8DHMIDM!4|(Ql-ne#Ye`((vf3m@zRS8+V(=}iT~PTj4>H+cGIuaW<>vOJ`0r7iRyPkkw3CO4S?NNt6#7mXybYA z@6nO|AS6WpNaZ`Hs8DBhfsn+H>qDL0L>Dw7=T2Xtv*R%k{i9R`N|ny4a%aczh#%Eg z(NHSm6S*@Tlxl>6=pUsfP-+l|{4sqEO;&7^TBMHXU%f8W>yWzq5q+KL>X(x`qJQ;9 zP;b~-)h7V)2trFBwCJpwcUD&th4|5Yi_Vc-Ky#?e zYvxLg$JrLGs5OZGThk6)*L7B{J1a$8^2hSmX*jJJRcT;iE4*Mw}J<(Y`N=Wj7&=Wv9X?2Mo2tA5VPFbIneIRtkcAa<)KTSx8 z{*j&q(lFu?4}*rGA7>!$ei$?&h}wUk_IzhmOoH-3(DP8dKo5e7HFc0&u&0jK@MxMk zqW`In1I*aYY7D{1hd^TiaGV|jjfoC3o?sCD!@L5R$(_|if{_n^CYOPk7#(IR!65pF znE{yTL?RykOxMJnyU0vZMf9&a8>(-Rs(A48hE(P6{pXM>qJP!-P<^|zdW(d`L!Y-H z9C_&T7QPN$BrYEIykAEA zJ%jj)AmXbbzKWE^gPv7TD|7DfVy~gaM)bef>!A8cXSJ4u#Y3J?I!7Mztd$7-kms`? z(qBM&Q)l%#Ns9+On{dz%$KEP^!1K8QVas1f_@#4t=u!Lj^9K;lkiK}pa|UY9S$o^{ zfae_b9PzLAyi~PZQi_U6Qh$=Le83Zv6mj=|Y7F2R+0^Pe;tJf%W^BOyfpLbWi>OK6(n0na5# z#lyx}>+E{KQ#*)SU8vO|HSvI_jzR76AZmYyT7x82j|Aldo(8;|>S@|yH#MR*Bl>T1 zEKr&ysiuS?AMi8-z(}jr{D7xvbfgx9gy}&GIo~9A3xaSL5bjJ;cO-y~H) zaN+?^UyZFmBXU}GKcOJ{M;QQ=2a?pk2t_>Lc|b$?mjUG=LP7M8@-R?}h(kQ!DbiG( zz57TIwa20M7^#T|JdZ)m%Q8Jdb42t%$01OCid5wTo~JZf?7LF?FqG60{i{C@_2MKo zB1sJ=2Kj)eSRNaAz%v4$Ot20Te!w$4I_D_jMD))&4xD3?)EI)44|vA94PD6?ZGQmx zzm~~{e$*|G#Km;D|oBL-7m3FYNU>U|QIPJ20@ zUGHlgV0y*&x_Aw*A{@kEIBS8khFGNAUW3J%W$l-;ZhN*(fYnFlO42JbHuns1v{e&f4_(6?o zzeeTUxPKuW#9%nT0_S*=I!ZXgi67T+jv8=I5)NW8oHM{VMJ&>dpVFkowmC}#h`|Uh zfZ#k4NJoA?Izddb^AG|t7(wOa6jd=}3F}Zm7Th`&ouDpD*_W^QIP>h(n{?+_Xh?M# zw~huUHc|s(L=48*42(^aRbv7a4!xMFt!F1?k8bCm%{ z5e{N7oVLJeLoC9nx6zaxr`|58;*C(eo)m>!zaENS)+>(YiWqFJ9ibd1W$D<%nl$!e zsr|T_2oQr2q<|nPStTZ`PQ)Qydy+g>;Mx=M$$aaeVb|U%I%_JiA_il<9jvz{t8N4; zo%?OT66Ua^o3>v7JeXY>%T9wa8=+#dwMLd#0HoclmhMhvF> zD3l*gRz)N(o%_Rlt`%tUCw=EP{q+u97T%4xsNg^z7SM# z92CbUt1%=ho%>kcVPiCXvBSnw%MpXM{1xC#PF52MM>_Y(fLLs`ot^u{=vY$;3o#hh z8^D^GtX?B5;oN6xRIh1N&JBGQ;UEUXnFpM?$?8qQ5zc+ChV!NYXFlN|2E$nloQ1?9 zo%=#fT5OvoM1UBKpacZVh(J2`Wzh-VCj!J^1gk-?Dp{={2;tmU;c)!WIvm-#uh6I* zr?Vy~#^=EJELnY;tUe|Z;oLvt3;I(K$ZP3ijmg=y8>mHy!CLec*tRCCEy-##u}SB? zRYTgsxSKUNv5~eDBVsVdU10n!S?wS|;oQH|_;zSiPRo8E9K>Ka`+&1IS^Y>j!nyC& zaDFu4>?a(=U^u@3=Mb?7=YB|2cJ}k(po+(#c$5@{b3Y12FY9%J=870>uD?V1Bq>Yh zeo~XhUM#gAr-%SC7(q-*iuyBIol90{i94A$~A;Nbrv zKUtB^Jp~Z!thTdrPl}G!g|HBVVch|ybo??tbxAn)bd9RJM&;bldk_v{Fq{nF^um9? zig1K;@1^0~Wx&ZK9K>KadBDjb7U|q`G-kRgcz(vL&5em{ww16Cyj_rI`^kFq$e5oaScvvq-Tf`F&N|XU@XS-8Uhr~y;$QL zp;0+48$~#X!EnX`XAJ(kR)iy*`xp)91q04Ygo79iXCiQ3CKln`U)GeJ{X8kC;#4S3 zAw}Wbr$EumdQGFbA_kl53@A@0W$E0fYtq<@rS@Yc5g-O5cpC(7;lC!HqGl0?bnb7- zV+GEA4nEm#9W?CRXGLe7N34j!SeJrz3I0JM0+r5viQ62OEYkK1pf}mh9k1bKgoWq} zt0dywKLggM#3Y>irvUiYvJx)mzMhm3gDHOj&-(wTtHT*RZAO<7YX>{(TV&9P%Vlc7YnC>o`u5j+V z(CG@9j2Be25b3A z;GDoek3cxmxt{>U4y*0#+>b@a`i-yD z#&`o5+o!6w1Sp()dyTKHM&-2ZM#4c1h7%8*j;Sh4IKsJi)NsNEoLdM7F&It~a1x0{ zIQK+N+1by@K^40|F_jdBb5Dh$m-V`p=870>uD3zC8!1cY-c6InUM#gA=|q4SjG#9N z?oL%bQ&kV*kk0*Xd91*>_rxa$tb>M~dynX>8N`YhjP)O2%}-Ui1S*|-KCpy2EXmdO z3!rz~&K%8L#09go79i=M~^gCKl=3Cu4C&Ug>h~&tGZ%omRYtrxF2TFoM@o$vkP# z+)Kq~kQibxv00ez>oi^A++Rn(pT}(7&V6=J#ko*?lN5z>f777&c2LDdP<$s<%_mXm z+~46HHeb^hJ8Utv95GnS-v`cnscI?VNay|@APx)XzBD@42ZV(f4C^Cctxi>|2unEk z)f&|*jmo*9uO%GBU^t%x=d)DxDdC7`?w@HmpBivB5DsE6oGrlFOf1s5Z`P#6w)v6> z5Q7nX4T7(TKsxuYq7!^W1c<>1egMJuscI)d2QMBuUYF2Z5rfV3QYhCV zW$D~&Y0}t>rS_u^5g-O5_&W$1q^Wvo>T=?c&b>jJI9A}?>*13Zt%HW0`{mJD8xbpF zFxIQU8k?q?5vX+TvA`1Mu%wx`UjRMQvWwPhxFumB`ogMPj(*SmHDJ9;Ov1Up3V?Bz zgL66e8KjIDOnDBJXQipvNnASjS!t06D6eZAU^-?ycf5w*Bpk$GIP-z?HnB+O{x%k8 zvbAT*K69U9J9oT>7Z3qrFoMNtCg)x%wuHnGgNeO|=`N+|3g^BQ{hng2yX%>INl?WV zQ2c-tg>(PFptv%q;#w%KNmCz^sC4dYc!zzc>5CoqF|`~qSj#s6XMLJlM>x{CuLs02 z;oR3n$J$6(h{3SF0@l_vwS};RbKj~_ZPBQlJLq=8K@5iTJ#coWsc#8KIQN|z&bJ1f zU4(-e4Cg1{>>(EE-1lhGV%zK`0>oeh2SKo(2&8l0AD!S35g-O5I1YlNY3eXR2abp)TqIu}SA%zKa_v)FpC#sutl0=YFY%Q_Fx;mv9h+;WPkFJz^2gy`HA*?B|9-6`Me@ z5h)7i-Uy0b)~hMa6*1UcW1-xPl%;cTrb%NjmfDXNM1UBKpbZGF?V_&fqFND$bne%7 z5yuLg`!)DvhIP=eb8i)$^*Ulj48|G;Yg`v~1A$8C9tSL84ohy(_6wjV+s+-Y;SPj_ z_*b!3^-2$QvH$hPhkN56KI-jU$HKK2^)4RvhUMN|uKkhT&LM*6U-e0-KHghBM#9pu zKi)fXo;{{9fM>Stm+=~Yick>!qYMMeP~wnoeQ0m|XDF?GQr4}{x7G0)9!~0r{?&_n zo1A*7&`1(O^e;3T(;P+96fS)fdOY7+XO~NVA&A;osEr{t;n2qz)LsgrHVJAIdaLmy zDBbx4-c92*ZLymsQ=1X}xA`@oyxLn$B^2q*Uj@KytJVD5FjJ!=%^)O1|445EX-;o7 zi;#pXpQ91Y(uka!^;|+h^pCO#DDU)E^9e;b@^>_p`3985go5ZFc2egn!c zgo5ZFSRY4l;<^?@&8QYQk-wgqoLSIz@9t^gqWxpn8T>rPDs6$ztD? z+J|$bj_6;#Vg|k|%}}8Xb%7Y9%PyZGjt#i%5I%X=I!M@MUx?0GDTBT{%?Q9*1Dw?} zRMiZ}(MpG19Z15^l~m1en;!trvmG{G!AWYwIx(rWT@sOEFE@>jEKW-t}%e;ecR*WHQb6&5dEXH28tpM>97?RUIP8uF zwOfLyB}1)qhDsno>99NVZc5O!#coQWHY56Pb9bP0%}`wkMLO)R0C?YOH9PDs(UEQ= zBt-v6cLS+shU!5`!eRH+hpQP3x`ftq$a1GB;&t#|} z#3dc}a1G}fMjfJoiH-9d@ge%>`!D!LXQ)vGCmi-@jct@hA{7_8Xck_Fbucm_zD_{?!*keL;qrm!akogLK#n{0*-c83eZLynvqc$V@Z}T~zoXt?D2}L^WvjEs=wVECF>F7x3 z2?^0ZQpHR>e#lgzOy}Er;jqhRx`{&gL~aM?rd%nLo-kwvK&cLts+p<^p$LavRYR#_ zK=~V?Ao}l0ZJ^X74(YIKYO-RRTuSPQ{?)I5dR;hE|g5|$2oIGT|FJqeHXqv)dk3*05TkGs{ z*b{=NO@Z1ZQWFk)l0og2AZjz9Ha$~KBSGn~r}J)_rfG}aG?Utl=)cWx0cB36nnftm zVb1};ZmZSouxCX_noCHC{*e{~XXKuE%2FVu(@XhhCUc?qE)`bYTyC?%O{8KDS= zU812ZGoUOd6h!|htAVnLIHbc~rOAqIvWC^8?_0w!_A2 z_zFTo^n-Md?XcSc={n*O4*NQYAGhp)%VD=CRYd=)VW`GssT)XGI_$Wt$ODWUGzRee zYI|I~hC2`nqJNZ5K#3;~>9FImAZM&SQr2Ogwbk(&P9Swe|LVzECWl=rltMy?{)KME zG}CCB!eOVO$7ii|b~)^>LDbTr)}7RZ!|rZSyFG~7-B9b9rFxK{bl5$4H}%l8#ct|F zZASFp=3Jm;XQ@m=kq$c>0KZzTW`~^_9Vw5H5d9kuceHhe-W~rwMKsfB7IP}h2haNlZr!^wSr3?>(Fd7J>ved{d^&C+Mhdqif z+L2I~*UWPokF!Hxpw=MzZ_Na7jn7gqWvLg5OFHcF8qQ0M`l1FVHqJ!iL-fx#9emTW z)GGuh9QHJg?G=s4Y1M0lg6JP*4p3%gsn-cbIP6&(%IgM{HwgvNKgxWdyiFX!VZW`Z zI(v6P5VgfnTS#icVK0Q5mt|T)b42t%$M>MRlvJg|UaHAr-<8^j5>iL>uf7KAA7-hQ zS!y{kNQeEQJT~C4SK^bQ&B{9L<Aqa z@fzMpNQi!r9@L#tUXfJVUM@f@fto&>WKc;&lw$dsnB^6Li8^b z%1%)iXqv)dUqFw?TkGs{*yXYVs8xbmg>2^=ZsD*iWP7Vs4x&~aYE`pU6%v#VyJ~ji z`?V^Xw%AR7%XXeLAo_1}9iY_CRy7GlI_%m27-6-V9d^y=NS6^3qJN~n1F1o_sz*q| zVK>l->S;vIO}P=FAo@p%1xmAQ)s#?#!)~UbG&P{KAQVLZDAxd`6>&(1-Aa=c+eDE% zqJQ@Rz^+Jz{JK$ zCq6{~e7(STSGKy7;Dp1zOJloJBXU~Rn@|w_qvQc4CtGC^ig4ID8cLP{C7)0b{i75D zr4Mlkhuue0b@p!GAZq`F+I^%Z9QJ)s^Ri6+XpV^f=lCF0`;)44*!?wG?7LF?Fo4t% z{i{C)^+&SR;A}OB7^K5~L>?P(*n{!OE7n26&#(tY=lnNuBKqeX2F{_`>S=oq)_kP!VK4cQe#{|eyCz#2zP!ex&Gz^j%ea6QMKK+1^0l&3;@ zO17Fr;?ikP;j?R!#sQ|+Y_E&g@HE0f42ClkIIj_lblb0Cab{clrL5bYV-w&t{5laJ z1|yi0ZF;6%D)uIcAqEqhhw09x=?d397yX`Nt-H&0&kw4&2#W8JqHx~t7!(%=RV;zx zvTXG(iAwjqjCa_(n!ea!?^DYWgSC7$a8_lj6@()l_$olWX0@Fi_=@OQYX}Q57}k1V zt;<%Q5SDP^>olrQG%DxD{W;+v2E+LhIA3I|O@t$y_!k<^CIik^!a)p%^9^ve6N_}? z+cjyiZN4P}#9#!wK=2(ANJsu%bb=p<05KTBJ`n89RzDJiaOHb(IL@^WM|R~uYE+K1 z*&h_+7%+}xt6#F!AtDjZ{0LvrzkonqONTTjXV)I579j>}(OIya&Q`x?tCPeg-T7$^ z>37CGslkbj^an8_24gIrlcGX7>H+}@haSptx9oyO<+Q9qj`J`AF&Iu&;8e*`m2;ej zF~X%+(Qqo`6M0*5aHMF3lA& z*j(#F`3h2&j{OQv8hf$Sel#Eg#9#!?L2zY`YLcTG5r=f`SLTRg1+KjbK3QNLH0;_N zMQ4pAR>WYet--2t)YSwkox1{-Foz{qYx@Pzvu)>&*KixcLiC08W5l^90V|Q1gmX^> zz#_{^xSV@3DI*3`?h55DIVzRJrE~9+6M3qcs&Rm6iS3*58tz6oh{15~08TowNavo8 z#d+V_Gi9Co2Q~p-!##)qF&M$!k^ic;_Fvv973)P}h{43NFx?EAu5j)d==TTKy1Sfv zc2LE9DCUx)aPGMV#e0G(-V4RT9My+JrE@Rj9o9$F7dz}eYB^%CmOlub{yC~2;YjD+ z9}r8dwzG5Z7aeN=VIc;?dK6d>=cppW63+c$jjBkaa_*py5e{N7oFTw@Dn~s*IKsI< zrQtkbz!^$7h{1410B1O{NasFWlNQ_NIU+y|M(`gHJWmADxj!GBU^EdR1|t{;g0VSj z3_%FzJ{E`LO6zcB=RQWGa-7cipcvDD@k)-GoTDZZiE!?(@C7{?1oB#%s4+Ra_El;T zVz3s?0o$w`^?Ht)L2S~w&(e@yXWSVYoY+Wj5+ha8?kDaPBKKWoJKs7*ugB6xWcVaPDiM z=w-b=rnw>po9ky#{*;uZbN^J6#$GJ7AM1$#F&M#C5Nyd&n{(7g;*idLi#%4~+&ANs zHP%7H&V6Ha)@{U!7>xCMuF?mOM)u;g29zX1Au+qvU4yo<09ePNx8IQMe7 zDJmw{`La znyzr}b)M`6B_mDjL^$_MzMy-9 zKwe9CYfR3r&7l?{25V7YuodL0f8?rsVw29jKtuWmN zg>&z(@%7WFoR$qB9K>Kaj{s+It{Ox*!nqIDa0VH09wi*aU^q_#=W${Y&i!#s+1bxe z1yy_oibF_IIQJn?^s-*VXs(FC=K36zpCx7K+@IB?u@_72M==o~1|xV81pm!dqjS|L z;*ie$zw%gtb03XQc3KAwJNHr1S;rD9VldVzV4ak!CJ?A}?vvc+uw;U^UjV(;cJ6o$ zzd~4ue--P4-1N{*_V1%_2GU025w3kB#CKUX!sXh(AXP;Fs@tKuEmwU>!qTyCDG5(LH1euq^w)tZ>!@q{5`27`d8m$bn2x-Kavol zf1!Pt=3bhnaOr!|NpDAJjq2EcBs)$GiFkB;;QAtCxlDxZfRkmsojgd|*fD9=rF zK_hZ*))n&T2jqDHP^to@N}j5m=R744j=YM7QW>Afo#~)dBNRmcU8xC_8pI*pcnwWf zY?E4~j_6;#F4XIgx^&`oqN`s{>WKc;8$rEco~lm(!i6`?!#|E-9eV7->uW@gYiS$= zp(PMnPn&z4!lKPm8or;95d9#9ZHN6hkRBr*;jkZr_;Je)xE%Hqq>AWY^%Z?gzI_%Za)z^|bqJQaijwIxq&CJN!OxAH~11?uve*{tz6J9Im>2GM_OegN0^d1_~#`j)t)!~R~w z*~zHiYG7jH>?S@$|9l6)w=YlaB{<=*_i1cLdQ z3@FD51<^ms??5?89KvCr)Ks0ldn$<9A5c3(YQkZkftr_PI!ALv^gqX#{1o*ksY-|a zrzVSiS85+Z`OdQuME~j+L;a$BRViOp$afx(NQZq`2oT4!a|IJla}km&3j# zh+1c;C6JnM*a-%;q#$ayLM<&{rI4U>*lE0*QZ#L`o4Qh)5&gHh2T*R$SGN(0blA58 zV1(6bcG$N?N4k@c5d9-%0VyM2^&%wUuroBGUK){eQ_dz7ME@v#fO1d1$|DrvutOB~W+->b=rZSqf2NA$1$Ak_Plx^&q6qpJ@fbwvN_k3fBJz8XXT z!eI}_p*O}l^w?n!(uf?F@@No*p+I;#Up<+x9w!Rnu%G6O_DQJAYvyr{$JwFJP-_tV zw`LT$M&_&M^3}7%B^~xi4d*#VeO3b#8|Od7hv=Vg9QelOt1$#89QIg^ZHz|bv}!z| zAo@pn1t^pA)kH!O4tuhOGSPrCl~54g87k*ajqZ)vjFccu1W9;qYxS6>SCCHZPmzIulkq{Ch!j}18NMfhZ# zb&&8g?02GbE+bAv|C}F!b7j6-PLR@JuXG!_lI7a|0Pue-i)X!tR}&KAUq#x}Cq2~0 zcG!RRNm1wec>Henxjx0iCRldB^$hz$ALm;lME|N43-I6DD^Q^VM_4-S@&yrx9V&1$ zfM=5Jaq$|iRN$Z>`bVh>lq$p_9d?xh{5@D}kCb)Tb8L0IhO3b}qJQ;E3QP{WRH!Bi zA^I1pgK5^LX$ps38$F(5t+UHvUlv5I9@H);HQ}%?H>lMQqSgdzjS5sl5|j?R5$~pk znzqP=-8?!{D?&o_kJJ`OZ3@)2gd`kx8;$5% zjmWtvw<8op|0rRg#1*I;2t_#TI1S|n14;)%LG+K(2`KTzAsu$SCM&i{0;wbVS5JX@ z5~)jvofKU?mDCaatKSCoZUyRA0uT)}hA^`&Ny}aVhCR5PAdQ?gG`bK=mLB z;jr)Ki?%1!oxS_-AZkxR?Fmv74*LnHd0D2XX^x2g=Qs?iLrGOS?4g=0_Fbuc7*6Vl{?$iA zeN=%OS)iUH2I;Uz$zuZ!dn7(tU>zjvu%C<0`2ukw`sbVg&hZ86C4!U=d%WAwmAs_w z4*<`$9X4LW6A1~?50dj+A`5}EfOy0+>;({CWZ40i!(K$Hi2haIgX+=(wSKbwvN_ zXP|zH)TP5d6fkP+AZQqJNZYfYORMgu`y7sXBXC1yQ>WYOP64IPBI?^Ri5BX^x2g=Xe8D+motv z*zGl0?7LF?a3iTB`d9A+_4q>7u~3DHK|1XCLUC-sVRytQA6o|rJM3_D&IIB_^v`)K zIMWJM3PDPTodzUf=t@$w{Q=+=w!_A2xGNzc`av4oeh-+^EU5lBbABRawNM1UBKU@r)MEL6J*Lb&oDaX9X^ z4o7z7yEQ7u+59gk#t~rrQm76UssltKocS+&K_3Evyp|4VOwO)7N-aVR)}qs3`@K+| zEL10mO}g{nHKdb_dqRT~8|e%&A_ij&^~E<=h3Y&33Wt6{<2$cWIV~&K*ZF1!F&Iu2 z;8gCbD)x20%MvcVa$olfR>UXrw&dVkOgMK$vDALlBLc)=1XqHfNnh2duWCpf(zQ3~D~=Vo z_D1;RfOXKYYi}5xwHdJ@24huVy}GYzNubiXUkxl_4og~U`vuUuZRd{H@U?`6_*b!Z zJ(M2mV*mEZn1Lzkg@GQwee%M<;$c5qHp1oFUmWOMwTS*zCqQ-lK=l#{OUFKbVC2Eb zOBw@sj@W(~ui=S=g6JP*Do~~nhji;x1{M#W9_w=Juf-@Eq2oqYBQq$Hh%z=l7VU&p-5+50)QjJnJ{)Hwhw#imf zNA$1$4b-=jx^&{(qpN>Q>WKc;cSC*GK=mB~2p7H!hu$03p~o)#JB`S3Eqj6>90J0D zfok7CwU;P_13$nQ?LMf>Yi6&;I}gN=lzGqc19y|TJwijWZhD$?{p>7hj1VebagF5(f-#dkq` zuI0R34to!&BKlX|57qw-Qa_QfblCqJ6mi%;X$;_*XM0?{h7S-5qJNabK>3+Cq{IFh z3$obSBW0h5FR|6}8a_hmi2l`23^Fnx=5rzoExVtaWxh2R|J| z?Htt3lA3VXXANrSgQ%4+!oPD@q%M%4bl9Py$ZoozX^Y)dp~yMw5&gHhDp0Bvsmevp zZAUunDn-`rg(yG!u8dD)^952hLPGS9bSaQ(6{$-INjU6U8qp;hk#i@kLnw&;Q5pcH zUXi+-P=v#-r=eVKKxs%Qi2hNU0;Mr=NQd26lND=nC8;C&SHBACv7{~?c5HO@mZXm8 zU%d^~uPsv75P)#l*A^8IUuGS8?69xVh#Z%4T@ZvY5aNo|4MnOwQ3!_}#~1AlP?y(C zdyU80p&h6-i2hrX1g^v))u~9u6PI+@i5gBPMvd3N#KuV`K1Ba~-NDzjNOd7N;jp`E zY+W=Wr&YHR3Zj3MyMS_Mk-CFW#B=RCHIzFHD0dSIqJNYupkxq-aM&4|sFd_WjX02M{Nsf6m9i`ACr(OpwxHKLR9S=t>4_`vbs>ZHJB5@V^NO z@vkE7teYOHlOC#dXAI(gsx}@zZBz~6Jv{FTG}7hHx&-89RuK97Vr@O53OCH z#fV|MW82J1_#xIBs6y47UMY&Pn$WOhB&b$mlFqEAIv@W%J=7@njXPIZqC<)>k=U1u z0DiKXn1s#LEN+?w*f@4%QSAFYF!zQ@76Ys8SQR%Cx} zy?L$7n@ZNF-MXfSn%lM9#`I7ulp&HHYSFWNOY|f?)UxEi7HQmcN4nMjxyM6>K+*ai zTK{Kkn>oYJ$HvWY2Dv)OAkHE@Y4y2z7-0RkKu8}itX@97^ ztDT)b0?TZ-a|q_r7OgD9Elckv7m@v8xa2vUGwWjG=2|Ho=$-eFbT-br+7TD` zwk375MHAvHzNP(PeC&g_I}1PDYDw8c+Bps}tCf*U3|~JR+wG=#)@Zl5=4OA`NlK)L z5_*>F8ET1R+RyDNIX%?bI+>Gkd+Kus{yI>RT2iDI6{&ZM)cnZ3DFt^fX9CZaJrGNl zmfm7Ymf-8it!I&a$UC!o$6g40y)L$7KE8g|x;5Ya|xV&*pdgCE~#-z8ao>MDSp+bX;$~PbK4mL{6-&WU(sgYjJy1(MMz>kR$F@eFD z!0IBksz|LUQXdqllE?(QX%nz_Udd_z(LJ(c6~2y4Ux$GTMQUvXy+`clMfNtZui)4XW!|KR?u^}7 zRI=8Favh4!u1*j2EZK-ZwtU3@VGDodoNRZMe1e+k)o$8uP3~^<2#?}a9N7Z*p5hkH z_9(XYx5Hzva>+UjG_xAMo>`3s#n;oT(UABW_YY?$tj9@W>-8!#p-XUp&8XI9L}F8` z1w&%W#l%#N``V)FjZXak4Q6*d{0+ct$qZ|iGGjLt#deOEu2H4)b@ktwT4WWnN;cW6 zaMQOIdv=-2+M2fgVU9H+C(C24{CCvwZQWGMX5ebdgGa%f(?j_s z8!T(W%ab0u2ZucNNP6fW|EJc+?XYtD&;|}U?c9k8+n*PTjolKTr-%B|CW-sb*@^e2 zhwh90BC_QZ2Ltc^|F`Y2%PIY5$>+AQ+HH;7&uXscb@KmduRRsYv_8BCledBT11R=M zx+}bZU4&U8@waNRn~QL>oNnJNah;U8mb%&fYl$J!Ll59K{sYFMxjq=Xr6~5c+u?to zg&Q7&;Vi%VY%JO}pkxbnp7m{oNdiu^GhEuXI;~=|C(Efv>GQ(@#!+ z2gUZh-PuHAt#n7lNr9}hWM#I_;GPv*qB1@7Fs;j8>&+w9xz+fu1gtJS{DqF9(p`#Q=Y(;g;h%rJ?Zq|ru{`R&NX(^J^oJC_^#q-u5@u1|MvRpU!HdE^Xuxdpz1rQ5!n>7&rU@?vrq3K(;2CZWLcgA6m83M6d(n87hE zL5UBn#}r_ccbijmxA{%nZOQ=9sfJ-N#H-er<->oXosnitw?;i$Yd>=cq%%YY-GAyd6j$G8YY~*kSEGj60J=bCUzbtAQ z09sTGgCX9whKSm|d6sJVmRNSA&&M05Q8!f@98>bUbsgMP5kPo{KVD${vHfA`!s1Wy zC)PJ?vGeHmRo>d?r}*||Z$G|$IeQ-azU2S7=UECe3oTgd%)^!{bLN!~t%z$B6AD!i zg+lMg#SH2fQ(Qi#e1(f*LNP-wx+Es1dbvvFLu)x@bzIE-1&_vz2qC8ea*9HsRi>)- zT=i*OOrHn)54dMwVN7v_$msPVqi?1>TWTBL#Mm@jT;tY{^~Hly02TCCaL$ z-h_*8z+zMTC`RS$F3 zATO-jBBMV}dG=8<1aF-6c+xd)dL;i@PI<qeVB2}Ht=@xeF;(v3%AMYo-3b^*l=MuvhfBY3Op{$nEEX>6#6N&bzAl%DjxLYlr2{t7qimZOAG0 z!rI;Ea#PinT-7-2al&OpM!$;k?4v~Cjk6xDT;pa&^4oGsYg5WiEPVrj#Zl7URFl9p z@nP5fw7l&~I+`kP<;qm=%4Abz53Wr2uIz5A?9G*TnNo5&CCil37b#A+`-Ht*NtV6w z?lF}QV1@qrzUb#Yqx(&R{hJ4S#Jh5^t})0o*f1V!i1%PmnJPzdWwCeV2vg;YsC1h7 zf+^)?9{eR&3SVneIAx+K6#6N-f~s*mHAwU z$U!u`gFH&|A{XxqoHD9|c9e`XRgL4S7dvDd4lN68zennhf*po8a8GS5``0aw1~UAfd$`4Lxs=v}$eRQVZKequ`5%qbg8 zDPJSS>Grk`UPsA4?2Y%OseBJB?9%teciuDFVH)gb9_)a3sI#HB3V{ z=Aj!}>+#0f+-+UsJ{ZXlbIOgTlmwQJ2e3FwI+|*_a7{|Q>nOR;?qHIsvIkeDdslWh zRc3N!FYn5`OqKaunPW=n%PD2|+(uT447p7{Ny@<&-=u)Z$_dC%w}(_qi= zU{8BjKB;RwZW?S94_53w*a%bQOI$g|yYdB7EoH>J$u zl((X++8pbm(_G2J_KMCj4ZVzqUShgtL!m{kYQ8crO^6&NH4|d`^nIYrQ@3HZZuNwi z`^3j1@UeZ}*GH+-yvq|}{&ioO2bINXfN2j_a;BrQFOZVN*&HQk;e)B*Z*8xTws0o#W^hSLMt|pSp5ons;T2sj>%G zrh8X*H&yoH3H5ZP@bcyI;8|$rzhXv|qv!2SL!k^)QC}|VgQ5rT`PaY7?5TP7`sJHy zA7Q2<_ikKdR}OIR#&;tve2Qfsca6R*lJYE%{*2rmE9|j{nCeDz-Se_;fn8T@svFOB zW4-FenChl*-9%H$bWWLSN|}umXE(m?y)$OGDpy7NG@mQydRM+_s(hC#7kO8{W2$_g zC$!9!!ppas2VaSH%H6o!RP-4aeS#v_Zd_xp-$$m}gUqzgy&Korl|Q<7lfFWtIE$USa*6T`XU^(ecd;p@ z7N^uOrCfm&XE$D!=y^6?>Z<%E(x=8;+0eVPzNxYWS2pvmY-*~!h9}h0mBMXl$Ah;) zJLPV?)>PDii{en^+KoHy^}F6w`vo&?Oq8a7SEN;6bIP_v&Gdh1s`{R*b|iY3{(X_r zf22J7=D#0rob}x68h3vr{})ag-v0!Bkm|E30@{R_-j9gqu){D{GiiF6Wdwrj*7=ak|~GvzO^VWKX=lsk{{{wCJqu zi{{=ly3#aQdmijM@5L*Yw-2F+r z^3l#N(|-yd+t>XFlse5D)>+;#&O}m1^XSia7B`v;_SnUyy762$R@NQ2>&BSsrgGh6 zueyn*x|v)z-IOwiQ{FJ8EI^9WkheQ~-q_x9RfcL(E0=QRV(-d@rpgsu`M!7Md#1`Y zJfT&t6kfj1c<@iqPI+TnYbx5pMVnCMy0KNjj65OZ`R*tl)d{X4(j!DuE zus=;zRk*5BlE+0-BQpBmD9_&DweiMT&r6cznSMzm|8h>LV@hen(hUGCZfx~TH7&TN zS(5AaRK@OKQ&VLdu2kNYSDPy1xbk}M%66v8c&_YVN=f3B1XD^kq&VH~lH_$`t8Gs_ z)l_~rE8MB?i#xn$lx`Xq@B?xp-G`%5r@<-#1l#%vEc=uwo;luctiwDA|lR&U$QcjoTuUzl~G2m{NAK^f&IK zWV@;6C$8D;-a`%S{_iqX{=$_9y({;dDo=9daqr5brpmKidCHU$lN`ALoHwOhgcPUS z6_dS=l2-P_%O}f2omZk3E7VBVZZXx9T?ew$#j2*k8t`COcvsfdHR_lKYtDl;^&YIT zsZw!eEAPsyOqK0W=`^#ADJ6~vzuuL?*V@gT5;moza!OK^RZC3vI!dm!SG1F9=sS4m z+pKc8N4BonP^g=$n)ky%u71#!avcio>-#ZId01c0B2(4VT=j$(R>#Qb!zs^}8i_Z~ zdW>+5dvhfJ1x^`dN*T}6V*xB&$rw}3RIZuq-b3x|4o);x&f?0M-j%PJD(7?MT<^*^ zO_fWya-k{ZeNI_sN?C&xr`xMMH)SV#;wwz$8(85peP4X)J)@6JgKg)*wt81?(KR-k z2K#{r`_6l?9j40tT)Ee~@<&tUVN^QJJY-5a!Gj-lrSP?Oic?OSQbH+_d&HknR_&bU zQIce@=vmXyRe9)(Qap|l>zWOPDy7I<3tyRk=j!^dlvEVj*LQPHX_}(leHxppuI8$% zys&PIjNXRwY^m$<##xWHu5r^N`C(4E(Ug+F((wQmM@dIhO&6|7Npamz)9el=nJRm5 zWx97|cT;61SN8I*yvtOX&y_i*l)jwO$CUB_Qk-u0OYw3gJ?x3!Zz_M36$b13VvzTY z9x@H~3=j6Scjc41#^a{JM)6?9-h+)WRldZPW4tS0FjY=MrPIupO)1lO@F}hozSd@P z%5+o8JWhEl%Bsz=E;{WSoV)E6on;z&84tb0bj{+&^{#5ZGS_qUr>>NY$i=&bQ#R?# zxxrNRHCJu(!pe_~{vGAnN68+%an@s(YutMx`TIEKCsWE{mOkV@N)DK6e&d=G?md)g z_y3rw@=vb(!@Kf~sj^aP_#4}z4u^kO_jHBWk>JIu&FW` zl}=o@{8oCb;oo|)9zrnGt*-$9g zRn41n3|EhKrSwCgeSJ^hlyUlUjx|+H<*LbESR*5&&!9Y8YBt_D>+!m4+~*_tZ*$6< zrj*4j{SJVIE17Sq`G9NQbMK-4b_bW5D%W!5YVXQbrpgUm`I&d+r>4p;xpK29 zifNJ4yba%EvOqx91d0$pVrPIudOevS};MH9ze67{tlv<{gMx4?h&Fco>tXjP^ zucPEedqpod4c(H5jYvmWgH6a>-$YknU$v9eO@^zbWMeQk-rd_1u)x?1>*Xm7imUGy1+b=7k7~d0`IQ6TzRQ?Wi3->LsUA=tY=DT z%7Zs@rSP@Zf>WBAQm*5aYrA+ICC;i{)5Ys3nPIPJE7Q;&c<4B*+lWe%B7~1 zRh+Wil=3N3oNlk}?X@Wv+7n-6D&N8ioAiCL!FxvQO@r;^!M^dX+^%bEGYz(v2ixO4 z*bk=4U%2w1cjbOliI+A}2r*t%>q_A{n0E?p}!Ble_*L2Nr9VPGE9qeMN?8TKmy(@c| zD)YE9+q*K;R9VQC|1hQWldSM>eP2B4J)?(BgFVNC z4fn2mM%Nf(8f**?HrjizQKrg?Tshvm@+DK{G*mjxoMK9u$%9XKrSP>jhg04#r7Yr< z1yNRQp65}r&R)^ErlFVf&?Tm8HWXUss^%;6ORnDRO8Go;@qWuG+x6w#W~%yutG@HX z+8P;sFXh=s$w9nv)?=S*+-;HkBb@THDdjhoKH)w}j+tuCbIn=z9@=R4|Fo&HQYPOe zGF^v|QyI#X$2d>rZ(Lc`yRwR@@=~s>X-cWbDRoULO_AbsyHTds{q1Xe;tfsZ*RVp% zOzjra!h1%|O@rOQgSGRnyiV6>Z5r$r9;~DHU|~~bDpw|XS0`X6LveRDCOw-W)c}ucPFMy`mSHhQ5M_zRW6j zA0^f`8wy?Os^%-RJy&1nN;!@~`}*#{DREia-RA~VRRUMVdtsf4jGjVywp3TVan>Wv zHSXC+{_UL7-IUUcrF#Nc93?$WHF;cD&OSFS>Bben<^Ke(rM<~rj#W-_(E3-Uuz|tvecCF5vP0@Wz|-C9wj0C zM<7C><))!G^3dx|*K8=X&Q;A<=FePxz?D(~vi9|Tf>Vy_%X!#Tb(*Vw^TN6`GWvPS zv!%*qN7mzlYuq}K{K}kCAzPl?oborMIR6Mx)oj;MQpHqr8Q0X#b{!>^?Ecp@RW{q0NR(9@obBaG8rUm3$TakD9(t%%?sg^CH5&>&?W*R>ZUR@2bEPywp?!T% z-W)0V@ za_^xgb_Z9ODnIASb>5Yqm@2n&$V<8=dYR;@{n*HO~iUeQLTq1*7#$|`ps zCDt_?3SI50<_;utb)qY!Eeh@HyBnu;$0_!Hz%~8dd#JtL!G5O7$GGxg@5&-m_!v|9tE}*fzAq+w&uF4)us3Bbe>l!mmgDv90 z7I+Uf&s6z7S1$9eeAiU@Au63_t}vy1%!99SrSP@3o>M+GrEKGrEm2l&v*%HgXs_r- z)6lzk=$)o(HWd2SRn1ps`P|3>9+NB2+vLc_doia}&ee{Ril(YdxT<=t#|d|5Wb`_e zXCEc?@Wxq>x~_41M)DhRN&{0$EK6SrU~!Z*G1XklHCN}lZe*!;|67_WZ{*7M-j!`l zmA7zZNAJq8sWO=>6HO^yIVH`Mawk%pZr`5kb${z+Py9Ahc@8UN>ieR%_l)i~4R$XN zR^VOv4_zbQG}r(htiShQ{Y;gQa^+y}%0Z^er%>rM^KnzkFdlq}D}}GMVorJ1lrol6 z{u^c0Mq3x1_IGfy>=hkl8u}F;dXnjy4TUDSs`<+Nf~z;WQgR~~@7J8NO<&G0O;z7> z)ebMLzLC*?q&)j5*^f8QdhB(Ldv7HF7fv~7O8J$gkGYSMBc_@^xaPEb59Qna|J_ts zAun^m>X|RJl*go&U_L?e>bLA25 z%3n;Cr%>rM^Q0-|91niRmBQCrC_i#v`qPwBl~XRt_qqW%t5zxB>nIs&uV{sQd52>4 zIy`hOtK5B*Sl4VQbcw5)ugt5sy16T5I126SyEUg=lds)K43l)}y0q+|iNzBu+^%rF3QKGysdEB*j#7C)eDb@A4KS><->$s?6rf4DZTbrpf}Y zyvMsT&s6zOuDsWjGJsS1n^GP{iqq}Eo||%vJ@G-N@@H7#X?r*h?F@5+g$%9*HinmOH+GKU9$!Q<6+6=}2+9-L1gu{x;X1_^qb$3|6>X z-xoc-XVk+qSRWoN-@7tb*T^;v_Aegne(%BVHB}aIjoKuFHQeNPcQBhWHq;=70&q@~9EBc&i=!rb^c+)i-3ccj2<|}g%S1)j-EQ(yb zC7iNUU(O|_s#RRI+zV?(Wc0O^XCEb>;f=E%pSZ?d8Oh(oDW98CzGCSw-ABn6rkd}$ zW`}zZEwTImjj3`USN`N(xyMv_ge!mct~_X}Jjs>EO(|zN<&-I^rl|tGSSas2ysVe;V731r;@$(iiDP^Jmux4bKoSV4ghbM= zw2Q4FhLFS-;NWgAm>>?(S%; z(Q5tNXn)W1hevzt)tq@hbLPzK(Mq-hdzRK~ylm9jd#tl}0(bVdk*CBw#lW5pBToWP zEp@|iSdGb&BHd{{lx@ zvsP=8pEsMr{>;0NUy}`RRM+<~)?~1LItLngjbUCR17V%;_CAreQ>CWi8*M%&`}KR$ z+kQ4{GQ+6JA|^c_z+6=_*T`oD^U3$mp-pN8ml%0&WS;8+d#*9^+{rw*1@_!xfPiD19$es$nyo}S)!@mUZ|zPGfnxukmcno@YI4?%Baa}tn)H{P1ss{n>BgEsENp$ z*qa90O0-#fuW6vI_saxx=W*LDpoSQInHsqDA{y zn?OnFM9i($BS!9*nZgBqUYrX&qBBOF-C>>G4D5MbuTfys*;Cfpqrja#F!Fph)4Lo( zGXti9HIrW@EH6vKQw!$vMomhy&R_Ct!q(dBtjViJO>C@5`Ap+kE0-B)E0NV1eaoop zaMrb?xchG<%9^!Woqpad0wy@b-R-wo|u~ z`}jtik2`+-R`Irf!kRoZY7&;^%?E3i-&Rs+Aul_^9a%zhu7|0wW? zsu*>a$U2J)>{&yv5o6TZXRNbN19w)_$n#6)SvRof7e=0G@YI6&jZu?Etn-F`P1ss% z%9=DbYSNlDX;I9q{hSqOE2*l^Xfva(|HHceRdM&^cC2Q@#?kM`Q#*m$iS+qN^!v%0 z4VgmiRBESDJ6*M zl?qdyR36WUS{JctSztgpFA(J%1Ik$jlrsWT0$?=*SZM&TJP<&>0l*RifILHhO*FOk zYEv1ykJ|mz9?)#qLCuC7qV_PgN2ooj+0bLu9@lKx32IMLdy3lA)SjXCtY$;cQF~so zA)%oc==T??y`_Nrn-loZ^6Rn+Xq<{9{d#i974w9i?rmTci!WqqwvpJ|if z`{#FU>N9Hs$HyA7wJ4xgt*h%w@`h|iS4!g1ys}!dtRY*nENbQ}iG~we4sJsZ(hT+K zpj2o`==Lm2izb$K&mu8vAThHCstFysLpiO`<4@{pDcct5ifrDAId9QAo$pLd_h;0M zMw8v3@^FF%!eOM{W3gD`J!$nbGumXP{g%Qu5a$eenDdBh zu5*ENqw}D1vvaw;)p=6d?mRE;bas<>I}b}&oP%B0oLgM&U29!SUDsWcrEStuDMvma z6-wDJTP>E*R~tgF`8*UqA8*7_jn`E0}n_-(} zTWDKsTWVWnTVva3J8!#Zdt&Q^fpoR^wD++Oun)2iw~w-qw@s&APjSub2x^p z4Rf<|t8=?^r*k(3e8pMdyym>_yy?8zM1f>xAoq>yqm-LUPM>+jYlv*LC0Z!1c)W*!9Hq)Ris$CFMx% zrH)c3DOc(&b&KOs9qF!gPkJCdlpae@ zFey252f3r1D|eH7%Dv^ja({V%JV+ia50Qt-Bjl0t73#95>*&5ywq9ZpLv7j$3iuW*cJLj<0su z=Gk_l-7cKjjWc_2W-rd{!;nOISj5N&^wA}j^UZ(c;*D2JBepc;knaz z?hIO;MXPgYbsnuQpw&gRx`bAj(dr6XT}7(`w7P~?*U{<*THQpeTWEC~t?r=JU9`G~ zR`=2B0a`sot4Frpw#R7s1TCMUWg%K-+wa=`vfs0{v){Mn*dN&1+aKCG*dN(C+8<+` zJhA24pV~Ux3vFHO*;q4w*}K`ZZQb$cVQ+^Olw1+^t2E?EkaLu z=xMQil6?stOYN&|`RH*OdR&ekSD?q0=y4T#Ty39eUt^zTUu&OjUuU0VUvHml-+&%B zqQ_0>aWi_{f*!Y`$8G3wJ9^xK9(USvY`gH-ZO^ywLC<^9^FBQGqxS>o{UCZjgx(LM z_ao^2D0)AJ-jAdA6X^XUdOwBUPowuU=>05uKZoAWqxTEw{i1!B{gQpR{W5yLg5Iy9 z_X6~O4ZUAS?>ErXz28RfchLJ?^nMS$-$(Bc(ECI5{s_H4M(v5XXIC zsN;b!%<)hd?sz1Oa6A@9I#$?6;W66rL>S|EDvWg$3gaBv;&{hj;si%KaiSwfoaAUP zPIhzF6rXa&!}CJGzT=96iLjj-KK?M=x={qqn#K zkA;pt;vz?1G0)LYT zi+=W@pZ$(;;sM8a@t|XZcnJL*Mn6Z;&r$Sq4E-EOKPS-7NykL-6#6-he$Jquv*_m> z`Z z!{a_45Ab-1$0Ix*J7$Vc9J9oyj@e?NV~&_D%n|<*=8Elvd14M8?S=Vb2VsHOQCKK; z5*CTMLY~-JSS)rCmWW-2rD8WBU+gX{6MG2D#h$_nv6rw?>@BPk`v|MWzQP)@pRiW! zFRT*>2-im*Ils<0wrny@lry09u@hOjzfrm!Yr zmasNrwy-W@j<7yruCO6up0F`uzOX4`fv`DZp|B-lk+3x)PuLc*SlAx1MA#9rRM;7j zFYJm~ChU$_F6@a|A?%G)E} zBpi>}ES!kgBAkraDx8YgCY+AgE}V(jA)JlaDV&SgC7h4gEnJA$BV3HwD_n}$CtQx$ zFIU^g$EJmgohF5g)8y};Zejz;c>(z;Yq}0;c3Jbp)lgAknJuI{&HUv+PSX_Iqn-m zdp9Z(_bs8L`?k=@eMiW3-xWH$?+IPp_l2(R2SPXZL!rC-k@2f90mgWMg(!R}6YfPV zT^uL&z@w))(%nlO_dIcpd%n2V zy+B;&UMQ}2FA_Jn^Tdtr#o{LS5^=M8skp_RFK%@&6SujSi`(5R#2xOH;!gJ}ahH3w zxZAx(+~Zy=?scyd_qo@L``sJF1MZFDLH8!{kbARu*u6zO;@*nKHu0!?yLimKLp<)@ zDV}ie5>L8!i>KUs#MAD*;u-fo@vM8lc+P!5JnudzUT_~0FS-wlm)u9h%kHD%756dm zs{6QD;65Qv$=PfofF6)=R`8tIf)E$P9{U0Q^+vqA#u3#usFgwm5g*wBcq%X#nE_-aZV>=oioTd z=S(u*Ig3ni&L$I`bI2s;Tr$}?k4$mSCsUmZ$Ta6dGTpg|%y8zBna;&zmU9W2?OaOc zIP=L|=Q1+Sxtz>*t{@AXE6GAU7CBduJm+e%*tv!*ajqpxo$E-xb3Iw++(4E)H5_A) zblI7YmqyE^tIp+8fpdj)&AC##?p!6^aIThaI@d_IoNJ}q&UMlq=X&X`bAxoxxly|B z+$244Zk8T8w@8niTcyX&wZaqUI^n5vn^frBE@iuRNPoF@O6^>`q#W07slBVGvxBRb zv!iQ|)XBA1%609NI=l8uU0esGuC9YpH`gJlyX&yj!*xXJ={hR)avhU;yN*kJTqmTy zu9H$f*D0yL>$Eh$bw(QKIx7uwos$N;&PzjFOB_S-80NYl4R>9XMz}6XBVCuJQLZb} zXxCL~jH^Hz>$)b5b6uClyKYDmTsNhOu3OS1*KKLC>sIwCuG`h8y6#k;=DJ&by6ax` z8Ls=)XSyC#pXGX3eYWdS^*OG`)#tjNRG;U1T7AB&u=)a5cFaQ8UoneZ?PBs=IWdb} z?PHd>I>an>jSJ6rjSpYunh?I+bwXa@Iw`Mo%?n@UnjgN}wIFpCazbDfv>yDrEFTo>hou1oSEJPy0A%12xU@=-jFxw=$6?iwVVa19ntx;BNMa%~Pj z?b;H4#?>eCtgCP2Iaj~P^R6Y~7hFrjFS_!>FS(Y5Uv@1IzvAj2dDS%_vcNSk@|tT< zr8J4jpNJ4##QJ4xH(bEWO^ouwV| zU8FuSU8TM;-K2%#-K9n0J*2$wp3?U4Ueb>6-qP0aKGL@EzS8vYe$tHa{?g3w0n)Va zfzpcbLDJ6n!P2hyA=0(VL#1`m!=&}m!=>w$N5F5Sv^##3v?qSFbffYZX>a^kX1O5eQg_<~=?a-BT_=;IJMPKSoX9EC+{mfYyvS+N-U`#D`H?fE1(7qQb>b{MW=l`p zbENfTuC(7iPa5QyFZHl3kb2q{O1<2Rq+Yf>skd#h)W^0&>T6pnEsV^U7DXb7~?JJl5ku4E9Qcp@zzPo)Eqh0?*uZ24g1Uvk&*cJioCa^%sU zw8x`^yiDvU-w`^=haz+3!;ziw=pyeSUF9Q@-Q=T@-SOxlKf(>4$M#-$^p=N;edM9G zzVZ@xKY5s~zdTYLfO7-o;kH5Ys))hza@!C&mkfo^F!_mnI36S9v$m1)a`z~Cq-`|L zkCC6+$Ko+g-cWJ8JlZxv9%Gv*_ac+zv9`(b4QYzJ$vsux6fq6`PM42G&XA8s&ctJu zd{vl@#~gW5rMYt7O7r9bVZJ=hwm=?lTPRPkEdom(9*gD4m6piYBbLffBJ$;j5zFLr zk;~=tkt^_6DNnSmlK*nAmdCl*$XBGb@^1S&d6I3tyw|otzG&MhPquB6FGOqx=N7rp zz7>yc@>JV)xr?|%o@U!A4<)9*bS4BH<0XvALmoO_?V&Ane9Vmlz;mJZ76A`Z!W zBM!?w!;i=V#iQ~_a!j6QJ1%#KIU&!qos>I@r{u-rX?d3IjQk+-tlUmKC--xommjz< z$eYEB@^0~xyh^+*k0n>+?c!DWN%aExhV7cXm|T}1+iu8nY&YeD5x3;Iw%h3cj(kJ7 zi~jG)7s!42l>2SV>)DgvvRGcOp}enCv00Oa{|d7f7UDLVrAE_?Mp+djBYRma+1i$@ooequl5WwT|lI-%9N#^WSQlXVo^1F(Ce*+6K2Xm47Ah z2(>1cRlo5$C=BmcimLKal#TtX^kH=L#~)YuFe;jzQopDa8TrviAK7eCl`DT#Nj>xZ z3l>XZq1Do);~yixO^~gu~y5gB}-V8=StVGT3(^LzVTL0 zDbaTO5AcOov^db1EA5nsPw{J4!}3ZE-?%I7nqcDH$^`iQW9?|{m8X=hdcEV*2w$>x zH2%u71zRna-bU@{94PG~{$a8F_mc8e(LdH7od@NaA78{cs_+9*+99MwN!Mo0Gun6@ zxV`;(n^r%zY1G1&gfp2o`M0Q#Dx}qJ*0@cp%vMdaY}$=(TivX-O`5ezs~lM=IxW6c zixzELHp}{V+L!TZ^;)%Ro|#s=F21Z(rDEleD^`xKR4Fp;hh{C)Qd(tZeI50YdP}@< z<%&(3H+R@x2N_Y`=WEiexrH?S-*2zC((a?DHE#3o)>*C6GJa{D*1APT)=%j_wyfCL zLYlP7w2*I`S;$wGDmZ*?A-KifrZt{P{Sgm5nfgOz3rS4DSG5x?B>CSKlGH3K^@o2Z zwQY%3+Sdtv{6Flv=&c3y{REPn`9bB6KZ?QtKX1~k(T}y; zW+A;Ieg9R8kGGUgD*x!UD%SE1F%y-Mzps|dUidG|_sHfqzbu8l>dkOv$9gmS8N7K0 z8=)TE+PUY{b7iJR{m-NDPFu5kIX8dGld@0Q8=f0mh7!*t)xe`=KZliK_H?N9wOJZ({IwOR9b_gy%8Qkl8td(UXo zM(z6(TgKf#(teBx{pH6O|Ljwk9`TQuGMD2`hp16z%SvkJZ|O{(Q^tAI1&Zdf~g5 zuGF_Ae))O&=bt8ilis=!Hs>ERT7m?hG3jW1M!A?~Pb+P)j1=+3Z}~XXNwQcHe|p7g zO^LI^DB=xVMnQc%i%W_e!u+mN=Rr*Txeol>!)?CFWvU>#%DJI3XfJgShNa< zs>wdW4|J}a>=@N+4ZQG&LoGjPvLRIVsgG}by|2?VGqTbf|6plXLMcrw*&?vVEB@2g zSahaGR*Oxi;XC2Dj(Ff5mEf=|KZaR+~mG zGZl%B*3dAE&5~UjZ6_&hM=EWz(bk>v3f@Nl%KB1#1B;Rh%4b<9Si0)oyiryLLkx%i zRK@@JMjVd9{}l`|(H7ypKI?&&J;?pwY z*Yp;R8mDU?tiVc$hrQa?}p ztZv;}>6t$(W5N6Lc*7np9@I^9(7}tA6`t6-pH)hatNnT1dUa}khPlfA5ZQ)*FIskc z;%cVi#E)8)^`fO&th!mHXJ(~)JC0{=i@mM3#6d0b>-6~8TD9V0<3CMjKXPWt{s83o z7k07+L#vgN-lSEd=FJh?Fy*=I$>?Yv;KDj{{7sv+Y?6*^Tu0^85@;r)*?e^jqZ5=3 z0#t39wfr$XtI-e5Gw==CDiD^XTvI<|DCI0{`YP!zxC6qV4oYzs1P*vg~b zLZ#hWu0!mxt&~rMXk3HPXpz!rBG*}Ft2S9o(1td7D*M|p2o}QZ8zc`6QcJFbCK(y{ zR0w{0kKx3jmnCX1N8iY7_MeP&j9EZvUc^#GufMcv)+D`Yn~aR6O3`DCIa;!k9v| zF%1Xq3bnt(MJpn)PMvg$oe*0u7G3T@GyHqe^50~2Q1!m~Tp3I|@A`V#gIV(O#MMg0 zQVB3!HT*`VWFAtyq&Vy>Z+lH4dW)^Klqdj3zCwPtJIEuOazxo zT=TPfiOGp|kajIv(=3YDlJiB&8Z9%vtXa1vCW$Gr-Q&0??z8md#Lwd6FywNQhz0~wNUnv8|D@Zj$D`}e5i?3I+wh|<7dL`B^+Ve4THtaBTxJIR2r{8WEtn%B& z)c*5)=RH2P_UClgle`U@CaZgh@?u5XJJ>8O)zIpFR7pR^yeOX;q?7Nn+a-H@-=y`C z8uyRH_<9&!D{l(ijz=CT{bidt)&DfXTKFStdXxQ@j znhs+t7e8+6?1^z4RL4<5k@14kT=(XM^4s>*tSnWvD48+D=d>Y)Sz>)J_bppBQ5IRC ztME}(>Y^I5+6n2}9zhq`V{e;lMXAZM za<4bom8vFwmR$2QWivkOJ$K1dR2pL&$_~+b3hTiSzHR1DY#}IR+8HH4N4O-zr*qph z%fJm%?{#bd+MQL})#Lj5rBU;?MU8L=&vH%;<=Q}T@L3%{ddK({YshUtzU%BKZ`&1d zK4mM0cibEGPg&lmE0jf&UOvJ;^|?xMsaFDBUsQq1=r8s@xOAz9wdV$}l)PLZFR5KE z@c7odYNgArx+#pbZaviA7=*<;h;`aN%rc+(>{pi+EuWj4wfw&3g}h#rVfY}h210AR z7cGMVtskG-q`7w@H~QBEK6`fytx?#1E+3oVQ@nV6=bMcM>KIA}nm3jJt-OkFc(+#{ zrPkgjFSB*#vu1wcrWzZDx{O&ABN34sD#1T}H(vUBi|y~qFUM22uRJZ*aW(7FDil(5 zhQt2LNohk(Z=KbK4c7&+JF3{+1n-5NZt?2G`L32w3*^6BGE_?M2HUKG!Y( zkcDmH;_qAA{Q;VLpb7g=0B*)Cpw)e)RbQ@E+m_l(3vUIX>^~3Gq2+75HDf>2=V3-P zhV8w$d1LIeK3OG~9=IVJo$}k*)cF_@I9FMr@w?VAtgc^q-#DvHbGGK+Mx)0n{BpL9 z`Rw~XssD#pcR_%X)F&tZq_WTGugGmP8~tc>T`p81W(7_TpYF507#;Wu)Q9vhN>ISh zf7=%6&9X9D;O82AUSzd%Dp%%$qCG)*6QETSx<7fZN^=7Y*+-B~$@IYZK23AH_ybeC z%RsByeP02!_cj`?Z^WjzgSSyv|3I)N9lcE!(!|tWY!$8B7cE2l6?{V7$?Lwvr*KJ6 zLFqzY+vIv1OlQ}GqPsN-SQcuY)@Dy)#6I17?-r!QS(Kuyb=$0T?LLQho4=0mcgFmL zjpNo|leR^bPc?{iQJU=H=9<>{-o3UDT6I+?`iDS^%ZG_3?~9gK*=q2=sI!IG%{%(V zT69z6>m>%*8XI!(zPr$?!0N7IEz){O{H%U$yws_em{2rDc(c;-@^{(UN-Y0>`UmLv00YvXE5Nr#ZkFAxi)uhPCJ{WzH+P;t32t+kFwMYsb{SKn_4Eho~0h% zE-EYxLU}cmS4NTLRJ>kPer`@qNlW&Niu%eZh}FjGOxH_VV%4K(4aI>qhqDnl z>nTe^g{7O#l3i9|Ss#_#eh4DbzPAzy9BYAKs7)cj(X)vXz?vi27L}yU!}nhKcOlP< zZKq)|cr=O}rlSAxW|*jq^C-)(!#aH~!%onU!p(@Z(UC~i#+rkZs18WZFK5*_v zk=qofuP@GB9nNh7oCg#K)*Q}L;5?=*gS|5rp~U8~PMS-bLP`K@jvy>LiG)OJJHr5u zASBv`Ab25~JVzmZqKmhZ5``C{bKB2THpltu<~YNa_neMO+dxX0 z#dsYUWur-%Xz~grX-ktMN+Bs5?Y(4_0Rg|3UePgWS^EYJ5v;io*}(R0GkN10Wu21O55oI*#hmR=qx1}eR( z)3L&u8*40-KcULwlsr{xo$5-Sexj2`E*8}~ag+eo9Koj`s2NR?qe&v=XzAsMS2$|& z+sb@fUNX+CS2mgz>PEA|mX}yOYc0wOYmT)(SnEcUFDU3}fGVY6_CFNRy1?R!!@Mta z`2y%6O1Y>UJzr8R*r2cmc`NsyfYp>Tag}>h0Blt%IKRrh8C8Zgr`!t4EuzWKRGhEe zTd;lYXB`Ka)~Izej-J*O2i6=;Ti|3;7QS-N#N=#Kat71ID);Rw0gj$uC;_ZFg8xJt zRqjP%zf&<-b7KF+aQ~pg}|boyL|b)zANH5c-}!08=LdQu#|a_i7<=(S+tbP;=)*RL_U=4{T zgD4hPxew7%4bo9*7xdv22i6?UIN*$lCZi}0SGkYT;fylC8BcLw&EZS|&LqmhSMHN^ z(p=h1r3A3%2xfs`1|{Gt_Zh_#%%%je<_H#nU_msQM-+&Afv zHZa_EIyf$owo*n|bBuezxI3Ecq<~!IzFWt)Q%9wRY#+seHHUK)IESOjL5jmw?uT_a z2MutJQ5;xvIH!SglCp4>`$?U$md|I*Dqeu%IjYE2?&qKwsPwu>#|mq1tXH9YnJV*@ z`(>RpacS4HM`A|+y0=E zExtATA+=`5(IZd-SaSrD$Eap65|gPItT{0^h8s?Y%hl}Ri1Z<4#{Ft`Vpg#d6yK+c zT+RNzfnsH|icwJf$U~}7QNCvXh~-uloj%@2!TUa*Xc}x-bHT0wkQfiCMnU*$JqGeQ z+O#mf(NFoK|>hxqCPoka&>(b)+2gQLkhw}w+Qaz+L#o_AoR2@!j z1DrY(2i6?USHP)HS@=4=zFt~Om9MEbtU2ul(Eg5U^A-AcM%oRjHmo`A3}`p@kVaIV ztIZo@6Fh9gEeqUFZ=@s9s+gu`0a^i|g@^p?A(k3=-PoU+e7}OXk0y>tt0zW&!aBr z9Et;L4yOxnay_IY#o_AlTpdnF1DviD2i6=;FW~f`EL=U_L#M1|a&NPW{h`>GDsuIB zUnmADs0Prn!kQcF5GW6#%6vUONGFY}d{JpJloG(2BNzvQF&;9?Lq<>zz8)Xr-AYi2 zkHXhSlx+of&qox`H=gprn&X=RzG)sZg~IVQ_%#1wFK>!2M^FkLRBLb?Ju@j5?BB&o zz~^2Xs-Jo3ST%{XuNt8KZeKMw=XiknyHi!I@`nvxwL4V1RwbROFkgFjt?I44JL?&= z-Kz(MfDIm^FCcnT0>19p5CRS(5jIAX2efG{8&|Tq$)W?^|@O57+aP{ zpw6$2LpmO?0vmi#E`jSpRdTK>IYYVlI{JbR=Nv;lqX*N{Q7Wx_S@-a!ITugv^xm-+c&ba{f^1Crw zn!uV<7NP8jAvP+`*UXL>Z_RAeaUgFlsI@DO9w)_tHHQ-p9GSB4)w3Lv+rGfRdcLL- z;OL2<1hD1^-j6Y=po_#JsTiy|u__pDWjb80imr@!Ukgx0e`r=Q8j2rNMXr+m*g(-^ zRGZh_i=`olH5c*};3UP61d7Ag)k%Q3poE=$(j=jHteO-H z)*RLsz)FoFwJ8=?VW;Y-YU`-9ilz?5fi;Ko4RF4SA@wN^S7m>t!>Mn8^DV`JHHVW9 zoCcJIue2NJq`9>Do)W;CBggMJTXi5oS%@MQ!!OtF&?#&AJlL$_a3~I?id=<06pDdLuMu>t zu;#`(2FjzTGGC>S(n%v1i^`9&lmONo!88y|i6N6>$OOv4SL##vZ3XrEB%HacY&7hX zCKHNholaR{&9N>3>%15;hl28z`#k^RFmH}7UjSX8R_-`@7E&zOzl$}m1}gWp-pc*e z*d$UqmXwOsiuX-5@LB)+_~`nd%175r;}hvQb_hRGKOOzZmRAaAIx1%#s%IXmKk1lj zSANnFM^D*Ut*nPNhxInF-lR-hYiK`w*h@irQ&mDb0TMrac;EZOhvm#F+M)PfEGbV# zcPW8Te%Q3HqWT_G``MwFQ!=l-jsP_M)DYn4anKOJnhQY%07fs168I#u;ze12GEC;W^E1aCzA&&(fLpZ zpj~yMs4}cM#VIC_4ilLH&nF!nb3pw7)F+noqCos5tB(&*ui}CFQy^G#KtljD zh|+MEtU)>e?UFT=D#Myn9tq{)RGGVE4d<2Ft~H7(!er)nrIeaIsm4|lF1Z+yJSuE0hnw6FvBdsJOIpzC9^01cgdRL12D?~V7^&^ zJOC`D>f9x3AryV~CN}wt>Ey$joBS0}UKUH1QgQB*wTxY|mhu>Ei(F||egov!#gf%j zp1WkN!-Zj$a$#VXtknh>8~;AWT;)~PHt!|t0x-_Sl2a6ezhs>Q#|DLiU9wK$%x2|` z?aPI@{j`Ym#oKtSW7Qi4~qvXq(HFdfS!%RJFamg z1i$22`Hf5bB`Ykh2q*+!^K-;Ss6-rnBR0+?P)Pv2Kxw#3)(biS?UGfBD#Mx!MQJF% zOqIDy*2}yy+qKG2Wmt2{Z$kO?I8v61bC;~wA@03omBrTwly%~F$$HByzxH zRq*jwLH+pab|7q}`rI#$*b22{O1}I3_}LB`d)U7l`y$nSP~8(pc2Qyet^7T4-na61 z=@`IsLcKEJ=-E$EV1q|F0+d6PgMSax7DGL9V{e1wOP(s~9y`hc!xp#|4dPI?6gGUOD zPa@WMQb>`wx9hF({zQd3BJD~a7O&M9u)(9e2$bjJNr`x^;Njk?e_n@D0%!Ql)KE%N z6xiTVN(1F(%E7-)|FTY&OOrBG9X5FNH=zC+Rp;NLf30}+H>o;o@apeDy?i_=M*+CE z=gY_Ew!frodhG4_aylaI_Oi_kLIog5@x&QV1WLiZH7~_`F9A-d^J_-X@n~rgPD2A5 zd}uxZSEYFJemo(Ri+@|bk`Cv6hDvl`T;f!re6YduRRf^aL@uUVt;ogpq)1lNbKuM%1u)(AJ11Kq!gL^AJMW?Fe?x$wdQlVCxs&Q|_ z*M?f4lIe3gM%duTSP!aos4D*!d>x%E@~)_Ss87{lgI8||^|W~MZ9Ms!GVpJ|r}5hc z-hTfUX9|>!guVU#b@80(loK|1&Y!^9G@dk}ko;TkO@YJ}ba_p5`2pZ_N{Oc&J9!Ijc0=eloVll*@x3ARK&?7)^!%41!3K}i0Z2KN zhr1b+gLpiExc|+dj%L)lL9I(X$)$q)ji4@2ETlJra&_t;DO87!qo+F^I&APm?+2JZ z@uU}p;co)<0l*D<6R215F#RbEZ16C{05c?>45Bdn4WJ=DFoTMR8BSqfgNGRdm{F93 zyZJLpC$3#Z#!^+-;8iC=bv#w&Zv2erRoQF*NmLa!c-0wDofc1~P+{(-&ol^oZ~9EZ z*MB*Xg?=}EW||S75AnJ2WHuG&Zurdg5ua@!zQBz5Qiv~(CyS^!ce7`)kN6@3@q9Dl zDg!@#VyTNlGYMqqa_PfFJh{hcD z@5a1H)tZ1GU5Y19s4#znr;wG*Pjn36>FiKGV}_$ABtd)82^&0037|ZapuOVcZ}2>m zklVheG6TLhczUVoIC`F=>afA9mrO9a!BZquiVDF7FH{=Ce3=fDyTS8vLT*kkWuE6^29LdXBo{@34IZf?klYC*oFZ{Ic-%Uoa2=6$HGiL?zy^=<5m2fm zkjfN=yTMaMhf>)9hV+^ zHhA@aKs_aaBvAnF22Tn$y}rt($8PW>>4@lyWHSi$fKVrae4ao)qZHf?o;qyNehzhh z&3vZg(K56?4GnDYp=k)Nv;^{P0{NP9@i%zVbU5EK)US15T;iltKG@*-egt1e0%=U) zxEnkfI=03-A}v%uQ54wVQCb0|MFRPmqHs5OTIf)IHb7}jQDB2dX$zE0%E8^>$<(Q8 zx%-P5wf{ivH>$?n;Q0+|fl8*|=@?;yALD*99VNWtAVqUvhdaRN=(iKC0~52?TIP@j-EA?0M;DA2E&TG zNNgh&gEc3%6~o<3hs#ynn-TAc%Dnqk-P_D6?toH|I}8+en^imr#r+9nFBRph z@BJ*p_UiPx3_Cb6Y+7sL=uvy-HYI=^036*_EVJ2kyYg(iGeqe z5{V`;UIE5SiKJvAd4ZB}mHA7F9qAuiEC~XBExn*)(z3R6qIRDK)?A3*2HTs7`DpyN>TY9hDX`k>bFb!-)V+g+wAz z9Ii^Qpu>?2aNHCJ)*MbH;Ji;+xJvzfow8P`S2nBo5frOXMXp+}0>wb3*T;0Mu;#{E z70S_6nXlNRb<)ViqVl5}C4eN?8P9&dFP`+}n4J@uW%==WAFMyt)R_-`@KBri)L1E3e(%)y)8dxnU6IZ#n z1i);il<=$E|3#Hy%_;v1<+h0=lZx||dt0`zW$HM_Qc}%Dsz$Vt2EOeWBPpk@TdZeC6JoWmr$0K9^zrXvksBg?uP*1}Bn%6o;?e z2LocR5_VR(4=f&Q7{!7$hcymZV-m?Iip5p#V{}xbbX3{}eLTg1HHR||I8zeIB#OgT z?o)I)lMHaCQyf@xICFqAi?Z;Q`z)O_mo{@L0jxQKMIcx}3HZu=LGc86lmONo!3q#8 zOC(Dv1XsB)!{)d`*&JErzEnr0RXQupVr&A&hD5S1k*uL4T;;xjE$DS1;MdX`9g~)| zn`ww(&4p+W*mfn79f@QcW#cRNT{@&440oFjj!UGylo8e(<54gkP9z5@AXm8`*6|(G zQE4GNMsZ-x;hY7|=|pmp;&7GwX&uf<1Dtad2i6?UW#C+-EL`P&QKzis^A)p-*P&QI z6}ig20E&T1uN!o%u;#{k2gWr`4OC=tUaD5^ zIC@^7Sg=81E%a9I?*Qv<%EVRfZv$YxQcCz$?&Ya6tT|-?%69w?Au7&S?)D__4V3qE z9AMg@*3CG2M2Z7z4yOWeB+9~9?h+E^7mt-fv0%+%eGaV8 zl1MFz#Z~T~>8NVysI&|E7ZeB99M0Fk`4Yb{h~jXS`W`zs9*tho?ngY8fJh(Z$i4`t&k z_dj(=|Hp9uql4oT=`YF%YmTuq7(3y94F%*X_f9mv6=WL+o@tT~+C!0DMpx>Fpk za__0b>2842hvLAR!x;#i{*;BQ-23a4wR|3AR&f{i zs>oIDrwkO&npM0E#fwSgJQd|D_lqpU&g=BK47)-@4r?ytw}5jaiCm*NeC2)v5Qmho zv&#Ki@mRMh7OXj}$H01sA55WGT;={yM|EFErCrdUP#jouIAO_2BqW(wk^}r=f{Vu7l88|W#KFL=XBCs+Pp{!V9gP{0)m$)0bjYlR6IdxN&st) z;7t&`o=nP82(EH}Jvq1i8D(>1m3vtol~(DzWfsE$3|lgJH<`RcNw~`0mh8RR^DYSZ zwe*gTNlO!fh6vVNh}>WcPbP9QaZxtDau3%b$qd(}gX0p3P)1mDj30vWgJe>P0&A5k1wb2!z3Q#F}HQyi{xud2g|Ho%FYII!k$;(-%OS-8qQR;R4xbAnmL z6euQ9MXqvBf?}Z3t0o;Qthuq)hVrLWnXlYG)kz~4i^`ABC;_ZFg0DbOKbh1`CSOnv zzH+b6Z!4(W>*CA>Wusx0`xnKteoa|n&9OEDYkD$iKtcJ+JsntFahTUYmoI=mp;qoV zdVZi-ut8xR@>cFWfYpsMag}>F09;l|3BSs{Csl?ur`#XPeUnLVD$ZB#ec8U&TgL&W zt7_ehqh|ocfi;IS6gYz^3tzbp#^iJs{3`b@g7P!1IC_Rr0$6hdqmpUyq`T){BsQ9g z!I~2rkKvA`!{sXXv50pUjMl$$pI}yT3KS<%MXqw6WS}_Jtm14a&P*oLsVHB$&tw@k zU8m1w*c=*iSaTuI1J1%^GN0n`mHR?KT;(eF`Nd-`rdY7%uvP(UMKW1NvAD{8g^p^O zj!L_ruckP#=5RIvXG1bsM{&4&?i+MC>kM!pG+YhI>T^$0gD& z$_Q(Y@evpwB$Im-kgMDu==kpGsI-thrZ}+Xa6(h?YYbCJA;sY;cWa9O3>F&Tgr#UN z(P7QuJP(`_DcbD!gv3Mde3XN&st)pgai5rI5E$$QzV{uiVR}aN7zh_qTASx3bZ&%KeSvS>L6su;y4L zusTzSKtcJ+-3ctNILs4t`2y(9O1Y>UJu=0D4GQax5c)ayQNS8OnYhY*1OWOe6`Wt? zKAI}Snp2(#l+lD6UK)%c&?|xvyjywp^#rW!M@Ta#(XA-wd3MDP%px;VbuzfVj?8 z?(2)k+Cs5l&0*~U)~*z?gJN-&`z{^T4jq+tLElSpV9nti0nVWma)9D+mHQzb&H)3Q zqZ9|$9L_1=oS-ax<$gjZ&85w0N&st)-~tHFQ3AelKUX}#MM?l`j^H{73R1`w3c*$G z1=t)%D4Qdz+^^`Uw95U4S&WCkxSvAqrjXl|gsa@|vju$@1pHdMtz*)%_7M#ctho?{ z)xS0{mIC98HOccewepm!++Wo3 zJ&!Z|bwCT*OB4szT*zJn&Z{*^X^O*D?yu@_N*mz3PH|w(;gkc;Ta<;X+~3kEYx(?+ zSw$NZ-=&IN<^C=d1C?HOI#yV7V|7AVpvrvZF6g9@i$&#!ixR+^BX}PKq$Y`|Nh(kd zzH%ouxoriNdj!smQ8pS@xmPHjHIlNznq!Ry>&G?8hZK~r+&=~uR~+VjsLK~X4^b<3 z96cV21^aigu6>tkt*QR@#?fi`xKo<8j=8FRWLj>{c%^#ttJ=q;X`2Xa@T!xbIw6gW zqr!Z}J|WG!pN-QofM=3gFXQN$Oi^HiN0|YXX_SMn)~BWAwm+ieiEp)jR8_~(Gn1;r z2CqKX`}tYjJ@z7@c~l5Cc%elY<^noQu1a5k7#~&U*{@2^GozLdwIx)ItI(Gis4X+2 zwgzge(#Q%b$XDm9ST?QDX>-}MmWCNN_%Lq)%BD23fuiu0`6d8NQbNr>4YQ$mq^%SQ zHh84HK-!%~c2Xp+D&MUm+NmSbF4p@f3T*HwM}cxUjU1#XTt$9ZhjP#WUi~7}&r@~25XndaxabCp%h#N{(vpodr;@s%pDz%mZ6VnXkdd6%`**>NN59M zZ9obs7hipcHt@%>Ht=4p3Uy#y;yl|xyKuq=&-W7eN;V)bGzd_6m(;PnfHVBwu7&Dl ziUJ!v%IiQW+kljzC|uQDR)W5@ z??Ek4$>gA8gbjX-E~tuBm9Ml#oh#Df3{bnO0||vwZ4`&2ijAFs6`Dd^ve%&|9aIT<>p)wB9%?X z_!*_4jD`h5O$hHz%hg{+4>q z8k=%1djNi|q83j!T;1pKAbJtH!)1w9K)L; z)S?{k=FL|&W<|kbk6NtAz307@MgHjF3Si{2Jc`nqMJqv-fytJ~6<>k~6W&TC=Zy>^A{%>IZ^Ba&Q z-V|`AT3vZdv=rEg6wto(PXWVc{8L~9QUHyW6p(^QfqsEfpn^{dELQ>;jue1Us@3g- zt3@)B#yZ3nwMoMu{~N|YALZ7kyLA?ynF=kwxDJAdr_N}la=}A z71WbeXiF@td93*srTK^S8CPQ6eC0_?_A_PhgT#+Mz$eyz3(98?&=$j0Wie=L^sn!G~qZ6@y zZe#sy_b#5KRBLkHc5U(O#p2Pv^j|!N&nOL}eD=>hSUhN~NTvKw^U3d@eSK1x?Vtbf zSv)(H*nEm0K`7N)%Llh;8w#WQR&AeW{iZw8XaC%%^z@mcLHAE+R8UW*x^^}ApZf6G zKehOA8S;7FE}sn9ugHDj(`^wr-9Ob9bu=e!{?$>}Rp(#%GKl&AGSymNnUpUv{|_+# zhZ>Lr-W2#M)%s1|0WAg2A_cTB{Zqj38UGYGgYcoTqV{bNDbOcS3Z(g@z!4>Y4Uhs5 zO0_oh!R7bQFk93)4I}-3!{GMMfEeHV>@F%sBVa%z)!I1k5VwDxS57wJn^#azHl;1O z{qus-{73ps;Qdo=@>3w^i;8nIKP~m-&#t2leB$G`2z=J9&z`4^!)MRa(t*q9=6Oeb zGWwDhFvT^|GFRJpj;FSNZ{z0Eq>%XCF#cvt7?v?#d z-gQ6ONJS5yAGv@U`KA(t-&JAd%OHlForBerYRzs3qYPdBURm;}Su1of&?Xe)=X zFd1!bDQQ8s-|UXXdRdFS?)Z9j;=Pn4?F=mhNK4WS%7s~D(Q;BtmxoI1vUB0A#!vY+ znD})?2k55@j2b`Xd&Dmu@q5~UJZ8b`hV!l)UuoC)*Ob6LRl@_MoRSDPUi`0cPKJg@;P+lSVc>AQ1rsU=lilc(J@?uL39Uz06-y!G#{S1Op=U4e2q5B=%!^;gx zsfOgmhU9q`z@d27Ri+^;(X`btOgUS&=q##RbU9pW>#9*dUx}|32tJ^K??Mpq0_JTYP!I2@J&gDEpnW?5-&Vi~5ZQ@JXG!(7wKm6p z+)C^xp+#O<3~3&=Qg767elpIh>4G5oq)VtZKk7Y;)mqAGwJwgbWd3Z)4Yh=ZJ!i36 zvY&g!Vks5!Y^Ze&YqB!R(yYmEmX21m2}7GKt97}N*Cyt*KFZR#Rg2b*+GJRA!@Rw} z?d^R#ZKq1@!8aC_W~X1j<-F|=vL^eCnw((LM*+;?9yap1z!)R0T1&TAwp=e}gHMjn?HwndpE~e8s3UJL~M-z@G2uHQqMrESz;F1@6pgzW ztn0dpd!RLIwSM8}&C;nE^KR_ycIV7;>AS2K5%yUd& z&rwF6Q<>)^qb9RilNm-$^3X(!_JV*(`MEmqc}DK5nZgQvUMvedqNPTiZDpNp3hcQ- zud&Xkvwf_y-GMvXY2fu+DxB?AcbYk!jRf4(lvCaA$uSd3I%l8n4wlX_a^=?G% ztMXe(x_9yRU`@JK)omr6jlB9XuijMyY$e}&dml{Osaweie51|BP``c~dE1X=O-30t znZl$e0+`!M#vA#}VLmgf2HZ-f8+k5ao{Iu|E-><3%{*5G_FQJe|M-F0Z)zzraz}tkqi1&zr5xcVoQ6D;L8Luc>$OI$0A(jBYEj8F@u8FF7UvR!eX1 zk+hw~f!vw=~QrmRV0qb4oUM2q&%F@ch@jXLmVM()2cg|_;<$P7H9 ze;IYwj&=6mz@C5THGVhhtSjp*H*jYijXe7@&t8E&dl-2RhNl+H0Y*(mu+E42HDPOQ zENe2#sL6EJWJ)o!Hc44@x~k+Cbw(!`b-j>vJZyxGbu8|&RlO2=9nH*M*2 z*DXiYEfs6|i96j9r`2^|4z618-i)<0|H4CR#vZV=b-PX8DX)+m1f*^Bn7q)2GZc zC9r3bk!Ky|nHt!$wvp#oY(Vw=ny~3>$U6TH;cRZ{7((y2JFM1kjGUS>r^aw<)u?%M zpPZVm&foV&zP~c2EdOkrqk6XX&&K)Q5dO(zfA{Nsp|?o~)_XfXJMz`OvyJ?^Grump z-%Qmn*T}Cw^Xn7Hua}YEQ06ztsL3eSWVlh2iD;r_wT-Y$vxKlZ9Y48t9{=z@+)M1k9ohfs^3E+zY=lYojxp%+lw{7 zkT`x1XPl*&-wQ@f%CIIc8#Q?gO|)!$JucwhSk}+;fHzJy=20+8W0f{l~na+RvKoiPIJR zyNtY!GOt5%0gC=}-ri5qcIw6dJigK9^Ne4==e_N(uqGFcn%rX2*8$8G{RKuokC@N> zIKQI*gc`xSMxJ5u-W6bt59nEF_abu;=@F4Pw+;b=H|DaA#3Qo{7veF0f|} zBhOFasRc8|sLAK7^V)t**jlU4n$$6BlFpi>6*Ft!#s@0;3)C6?+NkShtm~$VyZ`+I zWzAZxP5iuBQvR2D{~x@$>i)Ls`P=_T+Bsq#C zm-?jyDM}EGlpy&^lYpXr)kqB>O;9O<6zRPadXpm3n=~mRy@T}f|IF^}WM_9LU%dUj zUVnY%Cb#!I&*wce&&)ix7m}c<=)Z-_>bma@S8ecm1o;Ewj&3r5Mei5n4w^@5>@1Pr zcg*iw-tVgFH(2C1n)!{i^BXSmo51|WicF?3lZhge*)Y)tWJb{TV4G(0bmPZm)S+C& zJm=ec&J}sCV4h3uJ(q|)*Rl?+GMTXH+suM*z;N;h+j^1HPUf@?PNst`96ffsw}^c2 zF{az5gw3Z9RamUPb3d|fE)PUrPcpB(u{MjOupYe-wNq!MD4uBZSvZ#8)1T4ppJOJ) zL?$mW>5{RggY9{dPif{O#hQ+%r_>Sjiag6R&sXg|%ZWUzGSABPo|QzNHJE2WWD;a1 zwL~VhVM6!fSi6JmS+(QwBKO8jp#g^3^b=wA?R!*D6fBhmYi94+)T+@$6s#=^mS!KU zmB_Ob^K5VL`Ju@3V|Z$VnISUyoCWV@GGS{ilbL)WGU>-m`s6Zey~v`o+|7DUozWhm z(8E~hA)+;k>`2ldB)!Jl*scs^Som3c}e7X zhk4!i{m$SHWNkQu6<3d-_G5mEftRZh4VORTjLm$%L)7>dYicWD?Iz zg1O9Ebe!E*@|rrMZ;C?KXQAs7cXN$Q)~wrI+vLsi;UnhV!DLbqj_UgE#!R|er!zz3 z^(FKA+zzX{9=!*(Q>C)-M4OLZrnoh9`vJ_PpU7kwlO6(K?(OyR-}IiGpX5t(E&lSLwvH89aed!=ns)>1pZT;#rmDQvRl z#RmHxtrrE`%YyB)_uOIC*d_}02Mcz{KG*?~=PBm-r@iNKk>>??YJ+)JWO9`Szhp9D zYwad8xh^ts#p^rxgIs3qp6yl=tIp^hQRw_EbiR0-t%R&uw>xh#`#A*Q)WEC|ExhtdD)LULwzLndcyT&jBLO z;qcT3^E;8rXcl~=$%L)7@yz5Wk;x2ZGBuZ3n@kp+Woelg7mJDAB<>vV1rdF^9fyX~;v*P|bzcIsAg3{SNAIAV(1Lbv~mnVb-r zTwu~?&0EQ7k$@vS!`x<|c2Jl!KV}Hzt!0;i#_f@0rO^>vRqgdHu+|M%ZEX)uWH2 zcB<4QJkjQ3f+=o4-F`YVnIbZo$E0Tin5#-=ihPzbpT*`JYOjvqLXqb>=DFJ5bEU|0 z3-jD$@3}$bxs!Qr6PfI1CVNCCM`5Ck_F>zk9H4gmpve6!Q#fVKi<9;}Iw1;nodvsM z?|I3paX}R9J_~loKG-dhXLzE%ySo!jyStVKk3^pN;i(N~zC`{2V5wV}1utkaVQZ}z zGbti6d5M{nOtd=yv{`#T(QYdlqR!}ZqR?en=m_F&-b%=tb-N{#H|yRw<~_z_G7OID z`kul}CMH@=p9vzbS$-Rf7U{AAP1?+=8mBg=hmR-e} z=d<>nMMR!2!c!Z}=S3!77W^fX30rHWnTaGaslZH>B)hFdo3&Sx?6#8e>Wr2Zg$}UL zRf)TKD9qjnwvyE%pRLU2*Jh?vo}!N6CXwep=DFM6bEnAj z59WEu-t&OS^Ca^;E;2dCOiqhTuE9hb?aR&VlJdCP@rxq&`%K}EH7{=2_vmj?uqT@9 zd6=iU?fAQ!TXOG_C|F?@te}0c{LT4XXW8`}^DJiXSybd%3ZB|vz92I3vEVP8OxRlU zGZR^4QjwXw)?7SmuQs>aN=~XXT22(Y8Vems+|64FS+j2U8zyfyb_?L0$DJo^ar2j8 zmM3fp+OV)ZVcGQgQne+&ab_N(cj;#Mas6qCTqw*Pwy?RYb6OX&V)0v0$?usdln1|u zW)%&*i3ZwC1OG~&Z=vmPwB1VEZE8ydS70(beVF#CLGp&$nPno9)mD;1dC33Z*-3f! zP@TPKNk{k5=lhxNc2W3U*6;{?m5y=rN z3GL=(&}bQb5zZ|Q|Ehre0y4MzynRUY;~G4*&vvf}ZSFFgTg_b`knrpm5Ea00OLDva zZtiNy?cLX#yIL47kbJqv!n?KKT|^QI0Iv6R^oPuX{&pi`;dbB0WwWGu0_BA#N#ZBo z(~>wJZJ#7<7#ZR`?^!k?_j|Va43HuS7lv^7HBRl*I(Jq>KTkuxK--eEeNkb zNY-{~9Sq&Yc&b+or?p8}+PBE)lGeFdTx@M6DXCevH!3%4 zkk&4(MMhe)jxGPwEV)x!hm4GNb<$fJzJ0Az>z1x-S4+6^{i|>vZ+~xJ?;&}Scd2)Y z_qx2!yVv`hcZYYIcb|OQd*6H4`%ezQE! zN?m#syi)K+!Awt2Pe0F4&uGtB&jimT&lJxz&n(Xz&tlI~&vMUN&w9^h&uPys&jU{% zNcQ&*@_y_6-aFho+B?=e(L2?<2mnjH>ma`k0DHYhy_dbW0dU`&<;y|1?7OdGOaaC; zX@)dYnk&r%4t{^Gv>I@KNvEVU0K6bwlrBkEq^r_3>AG}7`WwJKTX_;&GWeR?9pqFk&n5xC)P}@wf($ zYw@^F9mjQ^Uoe^*@VF6=oA9_9kH6w^3m$*N<5oOw^NjRt$9FqC3p_hvw+mNxwVLldw%*>M-ag)8-YoBT$iVNt{k%WGV>moUcn5e# zdIx$(!Q)4GjE2V;c>Dy9vG5oNkMZ!B0FR&HF%ce<;4#@d%QFRDQ{goYUen<<170)X zHOu?GXSVkT&m8Y?&s^^a&phu)&wNB$fJh4wX%QkVMx-T(l#NJBy;Ho)@U`5#&a(m$ zS0dsnL|l!CYY=fQBChk!_OAEN@&4kS>)qg;=iTU?@7;umn-TF>MBIXizaipQMBIjm z+YxaGBJT9|@a)3ZZtn{39z@=Y$oufMAJKnD^aF@~5YZ1I`e8&rg6MxB`cXtbhUmu; z{RE=_iRdR0{Vzm6h3Kad{S2a?_3rYX^X~SZNAwGbei6|xA^K%Rzk=vj5&asXUq|#C zi2gUC-$e9Vh<+QnG3l^_S=PzLDqp2FUY#1LgU?LGl9MV0oc$h`b12i+$h9OMFA+Y~L_>sqZ^^ zneTgfx$g&gg>SgL(lYcLsoYOmCij}Mq)qa0X|p^+ z`c)n&ZIMSwzsWyJTjkNxHhGM+UH(bhA&-@I%HyP6@_1>tJV9FK|5;k@pD3;HPm)&p zCrhjRQ>4}YsnQz%G-<7Wy0p$eLt5{jDgEM~C2jD}mNxq5NSpj~rOp0%(y#vc(m{EF zbVyz(ZSgOXe)BJuw)&Syzu@fJAT5=)`IkxC{mZ2t{uRf0eY`zgij;u|^sk zu~ypSUnlMLub1}uf06e4H%PzxH%bTmo1}yO&C((NuhL=v7U_upH|Y=mR_UmJn{>>- zT{`aHA)WB=l>YSZl1}<}OMm(INT>XJrPKa>(lXzEeElw+@gI=R`VUIy{D-9T{=?D* z{}Jh;{}1Vs|EP4?e@wdKKQ3MMpOCKk|CFx#Pf9oZe@Vy6oRW^0IgP%aL0`{GC(4|Y z{w#AIUl*i))h_AMz2xsA zd&_+z`pEqvvgG~|edRro{p2B)`^(=}{zjf%d4RmI@<4fBaF9Hp>R|c%%0uKIDt{{v zuRK(qUwN3kpz?R}{NVTUg5VGG!r*XuQE-I3HFBi9Epn8+J@Q9+ad5P}BsfOS4*n$X zt29>LUum5Dd!_O6fl3qPrNN)&Wxi zR|IFuD}%G-Bb8>$tAcan)xo*)AC>0G13dHP{oV!gK+i&XkY|xR*t1w3;#nep>&cdf zdX~x;JlUO*H+8JJ!|BnmDb85JnK-Wte4N1{YBpH-2mT> zGR}YbDl&K_YLmZ_!S_(G-S=+A*EUo$+vQQ79rBN!o$^npS+M@)(Vji>D$icn?UNsP z_v7n#`7h4_`6tgoTstH`^d8375qX^F4|%-js657hOrGF5E@S@T|EGLWIw}9``AeSY zIVDf>oJQO;_&O_JD0@zx>^U!w_Fs@M_%F)4y_e)Ep3CxH&lUNs=c+u_a}DvY%a6P_ z@b$Mm-E$LF*e!X6=e9i4b4Q-#xhs$K+>>wk@5_VAJwQJn$_qS?|6K?3Q~+td;vjY?relu6p`L-1qd0nCIyqG2in|#1Ha-hy|V(T*Wh6 zJnwQ9u0`H&zn0#5@kinAM~_glx@xsaYtiMk3Ka&sT=+{NN z75A6qTkgNtTBWy>+kBv2Lk$O;?!=V)Pqq1=oq8<~9`m?c1A+ffwMp-wUJS=$9=9co zOSMVsrrMA<0(sn*wyIAI52{VZr|K2_<}%p4@^8b->bI&5%6;-*K78eIe^5YuVt617 z`O8;~tWxC-5BslTm8htyRV!DCjAED6Zz@)(@Wvaki;SvLse*dt{roQ1qepI6>)v1d z)HF5n;rxOV4@|E+W7NJyzS0fX4sPytJzFrJi@esZncIbb0HywC9B^`h4EL+%amfFS zHV|~si5(g8X(qc`u4ihg9i;g1=@$7$*=BXqTXpW3(XmYzkM>T`)38g|*6AIaRjN=is#&mO`}SQsq<8tW+1tTp zjXHL0m(i?lLwsAY@@ti$sgbgFDAFF*w~WxO{|`gwy!Te$a4QKJuUD%2MkG2|zjbfXO9yBjpcOjJVtK3g(#@kg#b$mSAn7s6&$q8!<>N@V7BtL-c5~~W4CMDBBQMuy?oCTACGRfB)a;Xg}a9?9yg`veCN?|FH4R6rYG&@7tKC+CC|qn z6!`DiwB1E3|MNkot5Kib^bWXH)S*Q?ZI!l5Z>b86dwWB8q2Bjq`4;T+l^OHznnlkC z9S>29j1Cpm;3f7|+%v9Do+bX9heplVlK-!wtKRv?!9~5mCX3>DP7~;kBLRx+#=}VjU~|0R>dWbl zCvNTc;-N-uJaE%|kn`=F{&AYMyAz0i@Bkj3t7DKoYIV&>>yp|jEv++?UxeZQnYjOS z2oIg$o_P&f7M3?LCU0UxckPDmj~lu(k#46f!B~vn5Mv^VG4})>N|I`)7h>e0nHrwh zFlTLa?S!Oh16O?F1iM>sodnnLcOzZN_2cR_Y*;5XN^Je#1r$lIkHhGpoQK{}piU4#XrSqwp6$J zEe2|FO;Ur=b?U@K2WzLYA9;3Vmca)j_%Hl;ErwPnF;)BL-`(>Od{^dF1e!|t`*Qqk z(mS+H#Zj(zvkc6pseKq1OZGufbx!Z_L28#4E!(Bx2_n6u^(6crr-lQ!OGYYAE|;!2 z7NMpS#rHYI4r!mHcIZle8xj3#rzGCFqd!UR3A znWeJ7P!ofNVKxp@c{)fPxB#uw(mJVD3?~Lr=BQDQJeQIFSz0RkEMWu-V8J2k#~ssK zr?S6|;L3ar=J+ps92b^kZ>#p5Qt7YT*YYC?rgPQEtF-)RTrcVExCRZQ>#*sjSrR^t zinhi%dLd_$?@jYjl(KfwJPCk}{(R^Z*X-I2Ag+IN~0`)CEnqdLSAL?14 zvQ3Uvb5}!3Z4@0-CoX5w3%ITZ*y#~$)C8}b(-V6|Ej@jae6h*M)71FJ^@1?b$LK0I z!5?6ZT6g@ULu$K@Ezq+tZK6j5dZ7w(C}&;7HE57ZfnuZaYtmeqJ79+Y3b?*XP;ncj z)F+tTb(q2d%$3d)Qzsb<#yV*QTuqa^$rO2cNd!MZCj)kvD~9~)-BeR@U)S_U=HGF_M(AuueNJx#5uizx z3Q?)ibrO;r7$>y4?z~ZRj!90g6Bk|2<-+1clKi3%V0@&ND=R^tI+8@js5SJcw@k_g z?3%hw=U}_GsdeM(rnc_dzWt}*uBE?HJYE+_h^rUZKws`gr5N3IrAEpb=1h2aS1uRR zJK*D0QoCtOrz#S5ojQYO8?#0FL0X4Ye59>ab{LHCo7^HK8&%FC)VJ=5h_qgf)ZQkq z=|8n`Wya~$|FKvZ7F)b#75)~--l1!I22OUfjjG(moZUrTOm*WLB__v${;r+`$&va( z#h@DIAyH@P!FFl8R}W*sr<%4CHe>(RV-(9dKiG1rL%Xq+8$Z%dwjB&YKenp<$VX&! zP@3y{UL@-(g{tKwGrIVs*2QpFwDA=0(6KdHWOj$^PF3oxI%IWYQ?>1QwLVY>qfOm} z#9jcB9B9c+1=k01i0)DY&tN0X)(rW}NBFORYpr36h;B$q-%n`h5nSj_9Xqjul^jRA z)yN+F~Y4y*8z1Xf3X_}L*h5p`}jOFR}-^=|%$JDVbXg4ivep~2@&*>YZL8+zw;(4}=Fgp5@ zXv@tc_5*d5vMsX$2>w(F{$t!S=^G%nGpFeq+1gmgBsHQ1A*AR8hJVFLXy5E3V^C4pJmTGUv zde=@LoeuW7%1VUxy5TCe{}?uGLsECp4HwyziH28Eo z+7019qT!1gb~5rVkZnKYKEO3KSTDYAH1s8d2D!w~eb@G>>0Q#=<4u?0z0M6a)}@^N zfPC=Ku{GU#^etw-&7c?r*>udb@1Vi7t3J*@B8)PABH^*0X$ zGwG(AET&1Ry*J8Pvjtou%?gIe_*8daW+*pO6H#!`cO;+b1~b`qpL6Sk{B1S0SgFfi zM2`*O^|z&oF)mUnb?VwBRlDh+m%&#s{P!?F;XiY0uXWd)qNX}T?h}(;++5SjTtC#m zh1COfqFdT6ECUlw?*gu8*?KXb*K84fsrP=VHoD2dMsYUV;(HvtaR+)9SdUb!C0c~I zdX4Mi4N9Z9*qkZC2c)jT?`CF_vHbt`U-HYD;Uzq-WKZTpSMuwHnis`eo)@3Y6OlQG zAU(aNsH<>t*z`#JVN>#_${UhDT)R9nURfHc{=whUZ$)Z<8a6LFoV_$Mt4Edxf8e#d z2Y-ebk9D-a#JeI=`-`Y(4Sx|e1m$&5UK6RTqT-Dr@n>)G$7C}L5cM^Y^iSPpud;A} z=}JKt{!S|%1M4XcT4y+$fwPgayhm8R@whUJ5tfaSSv^N$Bzg`ZBZ0>{AQDF|^LacB8vHX?I&jYJVEnOM1H#<2{PZJNl1#|Hf0N zw)z)v_c&Gj9g6#?;*UnfeFDV;P8E+r@kpd{h>CuuXP8X-d4y%yA&WkjVaMo@qjfgq zr-AcVr1B@l`AWy}6P&*Qait)H2dcw9(3AaV?pS9i7FuUmSAcaXQn^5}2GUKSETOt& zp}Jt9(zb=G6bG#{oZG;;8L8Z$I75v%H!V0f1UPpn4q9h84}o)^vW(DY>=iOL_bt*~ z+B~8JXq^#+N5v~)QQFS%Jx350WnQWrLEb3(r_Q4s5)=eM{wU>13elD>-il-t@<(O$ zTtGI*h3e)w%ai@2g-Y8%3OU6n4vb<^O3^6g8A{TXCPyS8DHf$48AUD9dEy@l?g4tmSj0 zQ^o2~3{b^swD)T16@a2$=~aXF6|J+rMnm~cs{Av_Q&Q{HAbI+xMH;!7Q|rV~0<_Ku zYJ(stN=b-P;wVQ4og+v%lK5?9p(i^5S2mK3X0^J}toCHb<<44%vZ8gy+8C@2qm;KO z=s19qQZV!11hgTrxZ*JTEla)tdL$_q$z$MciiI{Ltl@g)-WFJGC=*w?w*kObQo)%j z_jIa^)|qlgD7TMNKBVG&<=&p{Yad!Tz_ebioADUvL~+nM!|4i~49db+?irYzZ6s$f zU9587t`gue@G&Jo>x|&DC{g8}BlbBJL+ecJD|Gh@+Fh=4{{rK^oy@zba?ftoU9GVB{Vzcl6bG#{oN2(BLRt9AeTqezOPlGG0If5EIUtxt3HZu=R_+9IDFIq%1WQ1$C`wsC zA-KwY5jMviWOHPd`vMD z$o5ejw9asj0OwGYa)9D+mHQzJ&H(|=9~1|zGn_wxbDXkpmHTmvvX;*$ohqJz;wh@g zRqm&tXjgijrF})~tgjcLe4Z-vmHT;%G;%Sg{J2C3&^jZy1%kh$l{Jc?2tP*A>de`GEWvmaRU1<>2n${mk^uz+?y z1#L)JKk1eGzku~@z~-L&vw^H0dq^o^s@#iHWwg$eUxe}t0i^^L=PUOY0{RV<5>^iN z-h7}G1wrc!#0L-$rQmCJPav!30g^4on*E?!v*R%!Q3ABi2>bz2&7LDxhKiweCiW`2 zTaI>@tJ%w8qz{rAH`VNlQ^kr~5Dov<1T4&nL zq5Uq^<}37fMcVICZM4p`)1cidptPX!Ty5S8o8Tc2Zdu@ddJ7AQR>ib&3eXV%?E}h( z0VSO>a8-GGwq!p90l#L_ElgU8*@+GgT4#gvDcC*_amweE z7NaNuT4w}5gJ66>85>Z>P!7HxAFppEsKm$O`@>{g!QJyQx${k=d}y8V%>v(yfHIB3 z@iq7ibFr5_&5|Q11rMk-I35GDDHhs)iWQ5WdwEa&nU~(x;+3A&Z0hfx)v|gVwW+`R zRMRSdw4tjGfNKA0N?$6>*WUfB>9u!XD}%Os4WtlgLx&g&h#{1Kue*m-%j$W|Tz4N= z>ux*-hEa92p{ozCCaSq}gho&yw4n=)MmI;%ZgTbZD2(oLn|gbU6SeVB8%x!=T6?TO zZGscEsZg6-O_@jq`8sT$e`qM!{OWi3!vS5sC}6t1>jZ9!QnKv_po(1wn( z2`C#V2VYlju*zy%%x0>KHgw%>(EW|-@-_8uBHis&7j5Xe`=Gn0nzD;ZbM^EdY;GrL zJ-y39p;aOKoroWU_#f4j!_}07RG+J*|6t4VFx2_AanQn})zZi5pr8$XP|kttOf}_H zHRUAb;_K)$7MxQI^`sR{OOx}I3~lIS*Fko*nsS+9aW(W+3)N*Si@IoUP!zPGquc|^ zoodQ0io(^;cPuEk1St0@3fj<7+|_Z%l5%jh^COF@mbGEk9jHA4wead%A;i_q;nnR6 zp?uY~LI`c>eJlXgr>H7lGe2dKMa`U38Wg1JXhT>37u27vt`w=R6s8P(z5Hx-x>cZF zE`sm>r1f&)+}Vm#HngF$y$rTe)s>PIjIWhT0fsBkvP%MqFJ@3HA5&{(JO(@z3GF{c z+ExQUBYxjSe@47i&3L6`O`CeTWX-G|r)=uwmuhNhg4UU`3}s(U#Y4sUn%P%VubDj- z4&==lwRXj0AcEqcb%s+8IAtgcUp<$pnbq@>xq7~=65uiL3MD}6jG%l?Q3ahNR)LD4 zbtYCB-K|8s%T>{pFy5DKs^}_C6{Db7l`3+TbX9?3z^P&_DAug0RHveRHC>ZsSapj& zmtoO#$k93*@FP67V&5tK13NPy)2h2-<_-!FuK-M zGHNOxQ4+2W@5&Z*1_=1I^pS;0%i3;qh|oG4qOZaBRZZoKn#$*tjjzSOvLJoIa6h-e zaf#HOGNN_H*bj_ZHI?2JkgLkGEPTB!RN9dBr#NVx;d~36!8MhE6o;$K2U~Ck3UG!} z9JJ1Gh6Cq&%EDFW-&>Tmd>-LcaWoW1QAMso9|c9b(rXOuD_UoL9S`NPRGF{R$6BP3 zi#g@T1WJI`8Nmz?OslC(si{n&9DJodjo(&KuTR01n`EP5KWQ>4ch;Gd6|FPYMPOY} zQ<+CW`O1BPxj4+8XUP{pUs5Y~JO&n1EVTa=Ye6kk?!V}j`?JyUN|9)#P_$OO|5^(_ z>wg!33#wT?ZT%k~mUODdR0a z=7nC5g4v}k1fUtF4gnqmJ~{+woee=*0QsYp2nw`c2l{~k`2mqhfbh=%BXS2SM}g2f z1F8t1^3jSyfev#( zHUQKW05ot4@HPM%QT40F$!`S3EHdWW-oz&V9Xk1FolSmoD8C!6q)_pjwCj_|20o#agEpkeVOU=P>vPJ)9a*1aAQtDO z1)GmAohtT(V)tkzlZx_3R(Ghbphs4wg#byqLLCA;271vUKz5!6bXeEmR@kdra zK+L8`R#xsn11Jz$XF$UM^lh{!M&#PuUx~b2g6!&Ft8(Q zod9F=KgXC)-eqmmkE}DmI2Em&pcwp-bqXAt2nRc|PTaOLZB_ScJO<9v$wB*1 zCx^$n46KWki950`Vj#AXrD%GWb;YUTO(@=oR<2P|{>Zuk)!p>Sx@I8&&2DuF@EEv7 zhXAd!A$SO&`_al>3dA2-_W|(>J+kiR4)llup>+oIL<~N0jZwnzyOxXKw=eNWR(MPf zP#C`F=ZG7jd@=Nc*cgXE1p$q z)|qk%C>M`WicxXy$SMwT{m3eY?|&!j#B^jm?-bx=0F;VRN>Tvs$SP$3C@BE&I0YyT z069kSQ2_49k_`Yp0f65rz$*YKOVzm}t1J`^dCw;QRXX`-olSlvC|8J4UZdjNkyRl^ zf0y+dkHLS#k(KOQ6c2tP;Y1QkLXy3i?f^Cayi z_woHnjPYqQ&!&HLcG`*Bd8nPGYTQTnX9a2(oTy!c+LajP5*6e>w!gx%>5@g8%ckpe zn9+tl%y)ruJ4U%lQTUJSZv)^M8R~)R4Q<@dy_q}GJ&J@jbfi4Nc*Px59#JIj<9c_{ zO!UY?q@DEPL9NC>8#+n>pga{+@&&bmhx@4hDGN$IT;VfQLn%m6(1wmu1So|m2mdjB zVT&x6CPk?_+R)XXgZjUyI{y*Xm^ZuZI1VlicUo(=0M@x%xbZF3qJ~Xd`t71?oA5;{| z#eXbc(SlQ+p(++IE^#VTKD43pRR>=ns6qWm(ig@<{DE9s>ht*U^UF^-tW`c0noJOaDPv)PIC4oGhcDqE;DcY|jeHu|2( zt(+S?TLcI@|2e|>V6wZLdi>l4!fmS0-Qc+mwLT=bO*eS%(J@E+Pscn*)g6m}x)f9% zP+|TC&m&ecKd>->r>~Fvj2RvSVX@kqPPCz; z8$90JkxEk}w4o!t2BcSGm2wn`yTS9Sg{Yi`NIT8TQxvqJqr3r>%CSl%io)ICscb>1 zBtWT3QP75tQXMD(%E8~@30P#gG^s(=(T1)b1NB-|oxj0TD|huERYx1T`oE!`7^}on z0PY4)A~wCDWYc3ec;YQY^i8r8ghoJU5UbRWRq9a+?gmc-wrJ}^onJHcEIe9lZ_OrO&}q7A)|UqST?s>>wR-w9bb7IB<@}Dn}>|Ux6P5#E)dySp|M1cdQc>3#~J(bHF+itDK@(Tor!CLUqbQ zr5)VoDGpj^IM;x4C04maakxtSiUsGA0OvZzLF)|XHgIlI7QPz4X_4mA<_;x5>x|$b z2<}q?z9PS$JHaDLfYuqo6LI))zc?i2*VR7~wNWM6S7|#IX z={TieoRXiCaFzMfalNCvG{#qUK@jk3DZhnD%i1Dw+Ivj$ zm#`oeXSl^Ia9kplq>N~tF-l33soU-th`{$UP zscT?q_9I$a^J)j^ac>{YiYfONz2+T zbcoP88=^g6+ZCtmh*P#vHokJ-WkK4(aJO0DxJ24Z8PPgpJOai;amoP-$W`u#EPMwn zRN9dJL2=MJ!}$w1f5s`tDGpb;|7pQFF2FfOanL%$IS-t(l!dF@&svnVe7@jR@d^|# zQAMtDzXV0Q((5YiD_UoL{Ts^HsWM-=U$;mj7jw#wo0I^pGlEATco3)Di&O4U4!&}K zz;7$4-0$Jada}{5%Kc96tgd+NT{&83tWU+qEBWw46tp_yEBAcyrs6O=Z@jsH0`zjV za>rvJKgB{D64qk9a(@w6FHk0~a(@8;8%Zf)s@zLaWwg$eB`ACGJA|k>U%7kZ^&2QJ zTR6b9Nv)gl7?3FrT4y+Af#atveC6)PC41GqKmv-HKF?tK2JMytk8iH&yPHohn8`@eQiTRqk&H6r-Ffz6r$| z@rwQ@68Or!2FtK&7JV+mYSAG_>uksqfP)PyNXLM$+~WYTi3~fd+=IDeB~mQ3&amnO zt6scPhhlM+dp!$P9SfCqpua_N&^p6u0-U$;3xg;QSGm7!!D%GGNufAso#DI(oMx1T zuiTqiq`9<7r37f55wr$DOG?03?k#gCNTUR3oe{JH!GGeFwiJS^-2a2kaTnPfS>@i= zLZwwY?VVzL42&-EO6Pc`6D8p)_bzNfcLo8!mO5FOw5sLzD@&FY!+l;+4-R z8(+D9X+iog!~M(x$0gF&lo72n#=cb{*y%-xtLRajHd)>oe@k2!BqU!9sIim%E4FeQ~7NLmHT8|*+(`SR=H2i zoplCfMeB@pAz0_fD|0C*U%AgW7l+w%E%^fIZEEF?$G{?rg*GItY`t>d1gs5|iL2Z< z0N?;AB}|q3W~z+VneuihZ^e&nP;tI;-^%v2Efx+i9aQUPJO*}99JJ1G_5x=&W#KFL z-I$zXBxj73`*D>3kAZ!Z0If5EgTl%^N9+(4L+ecJD7t%uc9*N%k6^rylX*8)?#G-e zo`m8Fs>oIDCj^RrIaNFl#k29sX)4NB?q^wsown$68FqmVIa+5!ejPYhDx&K>Ip#X{>0>prmV;vc3^EUt3DYoWSrq0$cY2NVabGo0{*cqJ@BaV6ON zVuG*)^B}o!h0j(ECvSpw!v(D~oczFflCtoX`;!)FE^P`>0<_Kuo&mwrlz^|?pU$12 z2qi%4jGzPviYF+=CqC#VPJpXrLIV0}ZGxXS$-0GubKgsE~LM3vDxQ~nOhLlcxCRGhEe zhq8Tbh=l`87uC8MkAd$g4q9h8qkuDlvhbDr2ux02$yB-blgPhm#be+{N`TfG!Po>^ zJX!9!=ZKA?VrZR-O+kMlxuvRB1 zD=8LNxv#cRt+Y^S2l_gSgVq_&ufW-qplqNx+&%YA7Mu+NoGlawtuve*z}ZGw_{x2o zMVd>SosOhUgmDt|Taz5|j&+jj!CV zSdcC;+zS>sE|IQNMzqct?}717f^v%ja+UiX3*RjZl{RGeDGpj^IC&EBYYY>WM-+#v z+}(-h8GIzb2~X7CqN8<&^AvFMC2F?|xXL{rSnLkO{7x00hGIdg$W`tIp=ein6{dYf z>#VQOLb(W4<}3Fi7HQ;SPWe%c5}+#`U+6^Gf9C0_vDmz0a-F;IqLp$!S^xiI>3?qh*9 zhB9%L`xpQWBNd#favw*P(K=I}4CRT5$^%vBl`_LfT!fa$kt? z9!2KebkBW>Q^n;_TuK$W%6+LoafMUGbx>TBsH~!*eC57|W!Nf5!v!Hso7? zvpG@ONOAbeeKR1gaFzSU+_8S6SZJML?E%)VL}drX;wtxD7OEWWoB+--%EDLf$1KuZ+Wbig&^jYH1AM4Dl0(Kq zU@VZNJe8!Cr(ES;z{2+wuJGr8He^pz9JJ1c>|elnHc2T$ak$F;Sqn}P0Zws>gVq^N zN#HzBS-8smd5f}^&o4Sv^g!_?s>oIDFG10+^zzcaqIK5S2q;TbnXlX>i!^dEr~D{Q z3D7ztC=UW9NqHqnDN8x{%3Vp~wiQ(Fui(mfveB^0y=?BR6(}oOXRJ|Rt(v4%p`d)_ zUKLneahP4jk}rTBsaEcI3YZeFlKR^lKWY-MbZnxnW3FoN*d(jRL{hz( zs`k!Jv`qwU=&IeI`f(Gb3l-)o_K%zB`&kzY19+yW^)embr=zFPlp zldPVHNuC(1^&_e}9s^%db+nWv4`Re>zmQ8~#+FUk$M~4}0=)?RYP)0UUhEo*2 zG9L+mDP*YGPs0q)9ceU0LK`~LL?BIQqKuVdJ|CDWIHeqMV>8T-ANjf^tHDa+;!`4ISkIP|i^fuHrstQPpzy zq7${NP`gakxN7?{)a**8YqXDOL+|5FsNSHee5HNEB8$AsDIac8b+nV3^4kWg?EAQKl58Zb%D$UBr#nR}EYXI}nID`_rYKLOXcaAAVLzE-D(JGG zNHG^b06wf%*mw*Sph#%{Dbk_mlHIcUH}KHnZ*LB3jK8m~Q6;-0lHH}VyF+`L6q%Lc zqTjxr_4TtZe^!qRQU$W-iC-axi7>n*RhZKAq7>C9#Z?wz8oH9*{?dstE4t^)QGj-sHizHqGWfa zMq!QIWyt^(O=#q5l=%q%CBK{*Uc%!__GCVECBI&%c~N(G_=`{GiO8ITfpk5+rl_lM zau}Kas>$xkWKybP{(r*!4^2^qq$q<@lmRJ9e?1o>v-@j_FdB)VeQQnx;Vb4u_z{T! zW1<-qLLz))mk8AiiSQj6#_C7}2qn8~7;v@mtUyQnNl)Y$4Ws7cVfiSuRS6HZvxldkd7V6eIdZHT=dsq>g#XbuHAPv+8ikid?Cb%^iLnKv z#u1t9L3lEupr)^)5Er^`Fcxru9kr?eKF!h>IsWk>NBvVs#Kr_*IFsEmhVe5^fMJ)? zhWjEJ?xAEL8xznW=vg)y>1>Je<9l>f>ps38TaX6F_gLI)n3CN=b!C!N2w`Q$C%faw zDv3ujjK|8Hps&V+WOrir1Z_c1#h_~6nir(-6=K)~Db!EKHrH2$?Vgec_JDAI+zFuCA;eyaC0`eXXuVt&+w{gn(7;N=4m8SvLVBuQC7WJ zzx1S($BJRtnYHoLCXaHwl|9L@GfyXS4Gdv(!0FDcS~S$0wE0(i-AJ8(@@)w7pOWl; zn@may=6@#Ue?f{eFGZP?qRdKBX6U)lG<$}Y2uqO&+PCIJ5WZqgglr5VjEUyEAtb^; zyF_SiNQ6aX7~ex8Kq%RrYQW`p=4U*S%QTGl9}k1unQbvz5DdCAs~9bT0g+^PD+7ip z;|z;L%a*5#Vq;jqHimhIjbRSEI?HfXn-Jr+po+Iv(}H{(LRx%~>~2G*=mVt19Hhl^ zJr&v}yVJ9mYuT_C*`R%E&IaKt#IP;am|n20K{mjcNd4#Wrh(fQhS+68J3}_CB%|LR z(*U7lcLxJ*&g$~e<=D~is%etmH*5>*NTg1NZ2=l()r%jMUX}7#F$~*+Hh$c;&^ddR zVOv;Fir?%>QS}?oY_1e1`d7hWX!`qHIY~Hm4{X zQ|TaKZY$fFx1e`=A*b~eiyPh5h5+BA zkkcl}xMOR%(3|7}d7DL^hOlZg`yv2(kcEbDvwHm(^YviWf>B zOZi7J4JUv$?%WBGISe7Qj~PyZzf^?p$mN`Q%IP3I2{bD*mYTD+47HIW`;(em-?ZmilI5F<2asKg%VeX^hv_R)@ zS|D!r8RQI3i~B?(`y8HN`&6~fr-kMMJ8Gq#7OJH$^1L-TQTkXWqhCw?qvg1B=$gTazt-?)}LQRzdO_isbD*2kK zA5p+^6%4ZTHB~>u?dt z1wr&?J)Ri4U_LRBV4lbqDAq5Jjb%JBY_K*^EP7&SSQ|AghyiO8k7dd{>xog4AeJuH zl)q7&Gc~!L7{!|6-X^_K{GuA?AD-{qpm3O90_s|tNLZOlDBC_+tFmd ztS#sW47&EMc|i+bQ5Q7XoXCIJUcVtXll#k2G8QzPRQVlv>7Os?%#m=jF6v#lYFN}> zb{dl3Y zuc<-#f5$YO7}~h=C&urD(Pua@{3^l$aye(7aym#)49)5wbJmukHd2RhRn0B(G?d)> z0|79|N6@H~OP(XQjv}|pHC4*6^g6299n+czliSb!|risch~}tI;*`A2MYiN&W$HRAo59Q5~N@@lpuMZ`{6e-eCWQV20#>RZWLe zxQOJ3DCXrfo}f94#xTg{gAMDz6IqoTJhKVjj{h$c^>{=SwV&sp_;~#^9*>#!{k(u+ zq@VPN)cSc57tv1$qJx)-oYK_LNAqf14GZ#L&b(-=tq{3+Uk<6Lerno7{eb|s&xDZ; zhX&=>;#GvoRt#$~QsubDE^Dg{sAaWRZm?HKPr_b~j8Yx`#%06)LF}~`ZV~&ObzwNO zqXKk{Z^PvA#@M)b3dZ;j1>wf{E-qq>A&4=)FC@|yF8Of^@+mqUP5z=MvKpm+@VL}z z`fe{EerQMhNF#15M9mn z{6yxl$|Q0t=70360D@U^y&x`P9sms8r-@wchT4zHlpx$WX;K2|&HW4jeyk<4FdQs4 zbe1ZS#3x2YNYwwc739`?DPBR(5-Q^gszDQ^m>sV6Q$URNU(A`UGxVW2u40%F2v17j zN$Eu6k4msrj-QPnU49-G{My6C7f1|JZIN9jloPQO0wB(dXw>W=&v7E2!igBuRH@Ze zsmTt-m+(?{P3;)0gY8%QR$DkZKT9QiMLpGQimlq%MBt>VzYK}T%T4a>xiL|5&Koa+ zkpZKh;K!=t?88M2Iz-WHDW^w-&U}if2TfgyCO+vCtNAzPsA~x~^!-+{K zlj|g8T9a8jqzjN;PU{=S8XeR+jqmZ-%jmRsXch&QfYRY;+E9y4=|H`B9miG`UrqI+(ROt zGtB3&NLQyWoecxg=?O5o{}g#%WuBMpJuiqn?=a7s_MSIHo{yO4eUVAtD1BnXqWFnr zLs2D6IDqy`HfFqyEm7Q;;56q(dvCP}%>T0#^S zU8he?Gn$~zXq+hY+bncL;%>KQ-R`$c-YlKcnRgqLNnL&Mc48*&t<(9T$m?U~m0^cf zPmlgNwNtl}Ogz!%;|o*VWZk|OGwCie`G!gN1u(aj^bz?CV?IO7ITWjo{~(d)Xy!T6 z-gCIfb0YH`Z|^x)?-G^N_vg0g>lPcxr=rTx4>V1wUmnVQcLYGdV9Z zxy?-e&SloF+ioRqsWW<26gn)RA3u*oYu4?4VDe@wvpDm9HozZVjr7G^ikZ9+u$(?6 zL|zi}@&s&lxD-8l8EU6)B?_Ks^HI(ex2bMliJ6oanM5(^Hvr6SC6z@!(afi2z;vGG zQLB>bBF}#_&jfqVIFV-q=9z5oSy$xQgn2d=nY_nL-W8d&fr&QStpavc$-8RewGg>? zVhZi8dGVorkJ3fKK4ZZ?vG?q1)yNP9>%oF$+6VhmwO8SbthB2=p)oiws_x0!_sGYi%jKLFaK1P}1w$SY-Fq5$&lW9zP zGJv_QWTMDt9`l)9&2}r9De_##JeSyeE)sdJW1g$+Jy(i6H#5%-B9raRUyj>#q<4oZXYhE0-@6ka~u=6a~8GFxDR*jRQU^iH>tM zw?v*{)%C%ABr?ed6YXX~cy+;AE67Zq5}6cdCeKzE&sve{c3Vj+bw&$|LVH-~QpDZ- z28XO!x4Wdto2|^3YUYzujK<(76qzayB z$z915x1(+!U?x>XCeci~CV;uEq`Jr_iTT9WG;Jkq)e(#pc{X64$@ZRgMV?KW=R5YE zjYXdCGtcHClQztxmB^$6OtjJdu%=y7c2+x{E^_b26uMgTBE!B%ABlo>XTiR*_x!@D z@wq5ie-YA7wIOYi$BE87nfG$xNo@GHX-F zqO(*bAFDGuNfdf93%x+JX5H?2CU3Sfi$&{ONs(w*t2P}BcinoZx`m=$ZMn<6aampW zCE=u@Q^ywV+8J_craFJ`i+n#}OkK>`I8XKL zWX{Hg`VfA}WIs1WU#y$-V$r+v*|9>6ohkAg!2J60ezR4-ERo-L%q9MSl5W^qoFDhTDrZzpxm74`-Z(m|uR8Nl|7}SY+}%Otfq) z9%H*V7BhMNu8)(4d6u&GEGhEzGf&yx(nwN$3@4wBuZf(hF{em4 znX>VaI)7C}zB?Gx))>C%|3e?D{mf)fjHT$`CGtALybi|L6#b|4=qIS1dibBl6Ky_E zn&O_;?JqEsvm%r0O!^9dxuXA)$mbsOxgBFF`j4q2cvIvV9@JNWJ80|qNaR_Nc|K+D znJ>ss2^)l>%(Jk_qy#hhm&n8e6K%9h1?`Idb85#+irmXF1%J?z7ZLV7l0?BOvtSkN zJ1kZ6XSt&O)~#?&kXkWX-zWtxeu6DZgUg|AjYK-QQ3>y9G@}|1Dfr*L`oe zYJ=A!$R8MYbdv!rdcPod&^%IOXNmm2V}9TAepgk$!6LuW%x|Qf-*A!N1m-tZWHN=B zOca^ShKV*HGlI4U+ccA>y9gc1Ma*-)z2{t!=L+Vz)ZTN6$a5|0&?=J&o4(B~_y!Co zf3U3=IqhUl+u&q6*uv3cw|k4o_a0-qZA#dD`cQ?%>O1!%>*n%65|b_&YdYAT7x|QCK2ogdczQ}5L9fWOJo9|j z-m{#@vnunfZ0}h~QOJQX3|8FOIc4*q&889xrll%oG}6m`y(sR^Pry z^+dr^S+HjIo=vS9O+>-kvS4ZU!CHwtJ2B7p_MRV#JU@n~HkcVAlh0Z3ZYC49)-svN z7b25>%%o2)v(}3&I?LUx=hPYPAqqW=g&rbWvu^hwlQ&zLi<$QVlgSJE;$6v1mRYAW zTjaH#d9AU-Dy>J~OzqUIWE-An^RdMg*RR{}W+ppCCI^}He)CqcSLAbo`5ZOp(2MH$ z9}#(;XP#&5Jx_@|uQSgp_MVqSo_Cn%O_9kXW^!L-k}pml?eI9et)!gV@vu04Q)e?# z1n$~LMo-6CwvvKzrVUve#r&dRC0Vc%_MXM98pTAxWERY8AM9n3=c~-Kti7jSwP`? zA!?^?CCBhYn~x)=xGi-1znIAhk;w%neb&5{oEG`qU_MvPIn-1g|H~rJ2h8)Xz2|L_ zXWj(;dOo==KQiZGL>MJCU~L>ukm33gjaYqjIWMD7w(@FZA{ zn3wE(^r9%3!h)5v_bg-8C@l*11`GDOeXxom&zj7$n!RU~$TJq6+F(YDOp;jec#{cR zYxS5(ZIMY6X3{v9S!vr_S5aBGm|MIlX*;f_WvX9JiwzU z;{Jb^L_tFnEGU+{+r@yoQlumYBFUvH5F`Of2n2)xQ6QKE1Z(I4q)7)sdhb2--kbC$ zz4zYB|2w@VES%=a_1Q@%U9mjIY^B{RL{S*qn(?B0i3%PqLj zTh4V_&efiCuJo33o0fC4=bRh8<@`s>xzk&cgIbb(-jbX^5~a0|dF+&Z~Z zaNgK2&U&uVX>Wzy(F(iiIp=kw##L{HJ=F?(l z&Lf_49`cs+jF$7Hw+ZcSRt*jK+lD}62p&nt#`etSI|d`3%qE83|QU72NfpGw%6wOT8><<{CR zy}o)1)9UlhI}sV>@!e5N(!RdobY^XfJCim&jNeY>Wx#n>-4d9Kk0Z-pJu3ft>B=RZb` zUET^ip%r$_b74ok<-DNfJnK2U2NA*a%qm%SyqtrdR5Er~YP9%xDKdP`zWP)F?Z zJkHuvHs}m{C1>R``q*31fm+e|6TFOBtM%msexA@qW>@6)xBC0_NO&JJj=x_vqMx6? zUr+jfFFCT`IMW%WXLis%u0Ks4-B!PD36}JfOg3WiC)wEVnJMUx-$OH)3jT`<8bt+< zrvLw~ME@}q$5I?8Mexwq%)6!d5Rtp39iEN#EfNc{=F1;-EdlEn)Kuz#rAM5@~qh1qW^ zB5Sm1^#AEv9macBvHDH&*l3HW;2bJwDHXg-D{z6wMw#ciQRd_}imnA`xi^T?f-^j$ zvgSaQR}$G8B3nyj>*)XMHNxed%dz^c@>u0vRPX^R=pYq*i2i?AiT+0@9;J9pj;x>T z@L0=jo@==U5ct%Ir;f5odCSmKHh8X(+Ee!A)l*JT?M^GyerFI_PdQ8fKd05=U(YI5 zzmp!D?IsocfC_p@1wW$yKUSju6N*nMK9eJBw(AL&)Hd#;>neLu*8)n{xSYTq+Vj+A z7v*HRVUBPfCjZ7k4d?=kZeB03{=!(l+df2`ZdWzaq&ROcIDS z>HoEq=pRe5HpQ>y$dJNV6Q^|a)Xl3WTJVnHoK^D-tDdtc@8_(5Sm;*XC!qQ!bQ~P84YH_4vv}2xQ zq2sEfvoJ~6FH99K3-g5@Vix;5H2%ee%q|7S6c}INW`Vl}vTR*#y=((*qikbr<86~{ zQ*6_0vuty0i)~A7%WZ3I>upPed2!cfOteaDjpY4h^NHU;yLl6cvZY6UKekO zx5PW*J@LNyKzt}Z5+94t#kaG*!mk!yh;~?HTZooeWLtt`4vtH4Tqd{7GTREY&q^Fu z;kX*dH8`%tah=?1>uej)b{lcrgyUu$x8S%H$89)n$8iUaJ8dIuyYSO)+XCA^NVf;C z?8Phl@XCI?asaO!#4CsJ%3-{61g{(g*D>h*i+7IWofCNHB;GrPcTeNJGkEVTQk_Gp z^GJ08sV*YbC8WBHR9BGdDpFlTs_RH~1F3Ez)h(pDjZ}A#>Ml~uG;s>t)YEAL?ZP!=7d9gYUlf&gfBH?EURs?E~!H(6_qV2ikks2iddjgVEoH*n8QB zBF8Y~7;f)lA7SrnABh})A;&1>7>yi%BgYuz7>gX^kYhY@OhAr_$T0~yCfjG(rXbf; z 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 z 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

      a2^+l#%D)X0jw@pF1*F1+1Q|L~aUd0K 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

      ubL)UUs)C%`?N6GSm*EjgCF;h-Gl_;- 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

        NO|^AG8JDq z^YO8(?^V(KPdR0}DW#aD=eUoOS*DuLx#lzX8meHA;6hX78m?UFUAe+kxrr+`cvr47 zResBrUz<{Pamsd6%3h>6qy3ZTqP)hw@gGg)hgspEzAk?CzN7u7W+%DXaqr4Mb&Wqv z&B|m)pCxhGuIGX?nP*Lv<+!q}cjblI^7+N<@(NTsgL#=LOL>5q-gh+lxIt2;tOX!9&`1*KANA)DcPo!0+wzEVDSx3zNzL(u6e?} zhHBU&*wIw^99I^4S9Ug4zRHy^c~`z*s(hU*dze!CaY~UXWiV2l(H`izC~vfHe1NHZ z6f2C-*Trz}I~rzcHi4UcfLOzsd64y&i1aHX{!7TmCj%;Fr_Tx z=1W{Dyw_H7$_i7;CQjK9W7gJr9wqhc8U51KdIz`u&a`Jkp>JH(yfcq;^)XjU{pjXB z%PFVy={#YoI=@Zy$q;Jeal+jh?S3)k*+nt3CeJOqDlqWs-Mgf~m4TSJv~ctZS;ggDY<{rQFRa4NWN-NO49x zt&P|7?QZ+VQ%vO#vcmlsX4f}3&AspF9#gX{Zq~}X@=;ym5mU3rxmmt9(ry~HWcn^JmnO3xUx_L{Znw09+`_Kd!2YCVu!_c!g? zP^h1)ns??juAb~lX%gMMvpMBceL6oeRW0DEd0tqLM!PSeJo_kFfiIl-SnBHgSTuhP zr>r!kY-H*6?xSR_spdPb+3H?HP3`gDVyfKDmEU_;?le^%;L3g8l|P#*4|C-~Q_5eQ z@`owqEK;1&KIOS6GwmBcVJa`16Ma}*kfR+XWpZ2xvNMXI9QlOcX|2f3DtK3x*EPzS znpNdyS9>?R%2ZjCE91Q@uQOF%k4k4S6HF;}x%myQ6y9s~Ii;Q{i*s zI!3#9qC8vb8GPZ)$CIwU|BdE%<&-X_l$Tlh1pte0aJrdlUgw$~?lsiT9>MOW$^l&2 z&%3gZsd5-s4)(5m+f+G{E8jJxjNz0IOer5D#To4ho{RE-_KlA-mCs^@8Tz`I?tMp7 zP0c>zW(&M4i*=2;re-U-*>dk@OHGvqwWrS| zrm9L@RWaA&gnKF4y$a>oM@e;j;mpUiuD&lv^J{TR*pzYuOD6$X93=^+n)+N*FW2=v z?P`yIT~lR4uDrv$@^({Y8doNJSKe)^yoW0@Oeqg=%6+DkR!DJ1yJfD|^R2sm;}4t4 z+pAq>{)Ks*}K`(rplMO@&)h8Zl=nfsB{LiyD6oJ zo4@W#;l0+MQ~H`x-rKWv-Mr zqMLUer>xPZbCs!TGgp1(g*7zV{aebjkCL7E!kLe4uD-*f`MWvgdsE7Omfq_=O7@s) zj&RNI?lsiM9{=A=l_$CKxOe5Brpoj3qR03-@5(c#%CcN}L7sd7@Hkz@DdkKlS0Tk2 z?JM)Vj*@rn8^6L-9?uHZ^0Y@x)jZdM?2O_yre<}xS)zAkZC#_Lsabt)R?oXxT~ptTl$Mfl7AkXV48D-Dt{ifEr+&bGT zcYlLp?b%Q$(^btYZZKC5bft_&p}oIHaLPOSbPhFDjpnLRURV>O-N#X$E%hDl(L;uzBQ%%gcN7AfACzCQ|uexWhy_&3J3Ic@r(Bz?KL$!&drW_S02?h4x5_A zwatM9^Seio;+GNrU->0AJdqoj?g=D%Fi!M%oN z+auWCRM~|qpZ2bN(p32(S9bHR>}slfjVoU%K4~t26L_{WidBj z=t|+ewwzNwH>IrSlrLk<+G@|EWSKpqD^0Dx<571vzZ*7Z1AWsmzE2LnUT|W$N?0rX#OwC$wv*zBF_vji;P0d z^Rd;{_m^n?E>78QO8J?kcLP|sk{?Vp2f5}zd)HC2-5$YTOqG9ee`32Eg3l+#&<8iu#Q!X;4R78q1+7$}Cj*?&P8!vAvzm^rQDbUtMZWElakCq}o7FK@-p-Y`cvs$Rs=N!8&R|ANDJk6iZdVHLwG2*4Go?Jp zDfh>iwdMt0N68_3M(;7T&f?astaA5JV(r;b=uuZSuefKqy0a_gC<^WU{Sv1g!^S_Z_V=HT#a6ZS}6)qHAn2HQUY2zV~jn(^PqYEBAR<{%oo|j7n!P51LZ`{X2%K07mG19^70pQHqInSfy0((Z!m|9=Pt;==rI7+NN8wy?AK|Z{AXSU+% zmadetkhS-BE~jL7(4Ib-rmFT_)z%9uKHB}ilxIslg)f}>=;Z1fj^-C~$}^^v7g@R+ zfW=YL)l}1yYr1!EJx?#O$Nv>m<(pjD$Gh?kQ{@n@eA~P7EmP$Pu6)OoGMZCHnNlVq z#To5!o{O@UedA+I<)5;`bbVb+^}eIYre+JdS+RHJTwPw?mu3Y0? zxyn?z8I{gpeq~DemYaX=O5we>lT)^tQucAmo*1*X+uC&64}+8J8U4Z3`UtoF-Lz*z zq2FB9yff!?iJoyYyU5e#hUn&9#3}Q;Xh+FBQ`IuATGGYigsUIzzKZhfqhuYvaOPu; ztM4t*{7sy)!IbhHOK%0RI7+sdYJTLJU0qy9iL%FkhpF-aSMKw!{Ml4_lq(N;R~|G~ z{>_ztno`bk$|+OIg@w`4E>r0Be7oJg@lc^$7d#V}quhBVRlZPL7v%~)NAY4)vnt%I zvUg=AUE@kqvzpv2-n-d#rpg<*GReC#!BqKgR60wyt|{d6vyu5+bI z2M*r%+QH>V8y63}_1|UwJO0TF;^N{`BiSvxwC~&{yIcFtPj$;qYv1LG!l$0jezaqk zXY)I?Y+uk({V%^uVf)V6>1p?>X3es@-F8d%L+v}Y&+pPc`>D47&2I5@`zO0}>D0Vq z+fu)*`}E^&8$UmOVf@ng`d5|@O{D$2|p(6PWUNdPr}a$ zza;EWIFN8K;c&tq3C9xtPB@p)J+WtEQDVQu{)ulTzMVKE@!iCciK7!gOdOLqHgR0y z$B9!CrzL)pI5Tlp;_SpZiE}Yh3lkS5E>2vQ_(kHX#5IX)6W1kvmAEl+Q{tAyt%=_x zZcE&gcp&lD#NQGRCLT&WlK5BRYe{b;6(#ja>YMat(txBPNkfy~NgAFsBI&)PkxB0- zjZXR~>EonNl4c~$Oq!E4H)&qd{G^3RpCv6$T9ULhX<5>Wq%V?ICw-Z;Hfep*hNQ2O zHYa_Z^i9&YN!yZkC4HZCP4^qlkBgg)`I!?x8#6Q~ejcvHxX#CQfjwgj;um4wKErh} zu1j$J9M`3|F0*HIS^Nsj=@+=J#B~*}t8ra}>zBB$#dRI7>*GhnZ@{mN z$!2`A1)qG4PqyNdZ}7>t_~bi$vJIbX2iFeh?ZkiCh5zzB{>u;eZ$IL{?#6%n3IA;m zvVKO^US#b<)-TA~kE{d8`W0EfA?qNren-|JWF1D<5o8@j)*r|^hO9r4^%t^^BkONu zoj}$}WSxqCJN`5>&mi+GGS4Bid-$*T*TTo+dxZav?-@Q3-z$7F{`K&w_}<~uSkGtT zi^6B)`-IQM_YHT)+I}tkX1IHNfBb(yxCd5x&+x!-ukhR9*Rke%hX;q>2oDJtg@xgw|C_^$!duY!Yjoa<|9^w--=h0>=)Miz zx1;+Gbl-{YyU_i6bpHX}e?<4)=>8MB??LyU(S0wv??d-r(0zY+Q}{r5bNE+u{|(&_ zqWkaYehA$Uqx%tbKZ@>up!+d&|MUNddk^p^sy6O>7owuzgQ7nApy=+**`3whBMXWq z3r5lic?6>f3W_2^(7e*5SRPw|5JC^Vgx-5^q4(Z<@4fd9`TjF=_9SO#C)aD{y{<1h zb0@p^egA)_&b_lsg6y}E{SLC5SY-IxBaU&dFV*^Kw_|g4|8ID0i1G$yw56 zxrcN`?kQcBdr8;i-qLlsk90%sE8Ud)Nw?(w(rtNwbVnX2-IcSYd-5RZzC2iZAPv#!KzV1Sx||lsb?}QYM)! zbtF@yPGqXonM{+qkm*uaGDGS{W=h@3EGdi3mU@smIOa+{$vmkS$&q@K`BERUK_(nF(kQZ58cp^|W5|BwIe?Qd z97dia$a55Vj!9$5apXCHJSUOo6!M%#o-@dE7J1G|oEAQz>Hbt z(qwW~nnJGO`|CJv;JAt77LMCE?%=qK;~tLtI3D15C`~1gq-o@_G@ay1Gf0{|gS3%n zlD6_J(hf(uJe#za=a39}F6ki8Bbjmz=_t=9o#X|iv%HXWkr$D!@?z3WUP8LdOG%cz zjP#I~lb-Sl(o0@RddsUwA9*$DE3YB_*a&W2KkV(Q9i6}l8-2x<)g|L`Ixd*KCWz&Pbk~vlgbYHl(JJkt?ZJ|D7)na z(jFXp<+I8@`JA#}KCc{*FDM7)i^?JSl5$wStQ?WAC`aY1$}#zxa$LTyoRDuQC*_;U zDS4jvw4CETBhUAql^1x=$qT*bXjrW$k)_YrC=e;AZ_uiE^c<;#@z4zr!-Usq#??ZWu_mRBS`&i!Q&6T%% z)5s2Q8?w{emhAGjBfGunWRJH!+3U?9`@9{Pi=6QGASb;&$tiCya@yOQobmP{XT5#NId4C5-rJvC@D3msy#vW5Z#KE? z9Yn5p2a~JbA>@K*D7oexMy`8@lN;U<VFvp!gMFC6KFnYrX0Q)4*tdm@B3p56BSU@L$uQpzGTgV5jPUIu zBYnHcDBm73+P9aC@$DmHef!Bc-vKh-caTi*9U>Ebhsh-05i;3#luYp*BU63H$u!>y zGTnEQ%V0-ze8L-)Pr$-x${o z-&og8-#FJT-+0$;-vrkk-$d74-z3*P-(=T)-xSva-&EH_-!#`F-*new-wao-Z>B4a z&T_S(vt4cJ99KI!*OgA^x!ThlR|cK$>OdE`GU-BBN4m(>i7s|^rb}F1=u%f#y3Ey$ zE_ZdOD_mK0rK<;BPy$V`q2%p{&b^j0NvyoNH@E(=@!=@ zy45w9ZgUNx+g(HH4%aZc(>0v#a*d$7T_fop*C@KzHJa{ojiLKpW9b3cIC{`Eo*r^d zpod)(=@Hi?dek+R9K&(kHJP4pO`#`UQ|T$!Gsn6lxmM8o zu9ftGYZZOyT1_9h*3ieUwKUhYj;6WS(>Cr6w5@w1ZRg%Z)7_hCd-oQa;oeF+xVOd<32+B zx{uO+IQqMf(E;w`bRdpw_X#@4eUc7#pQ1zDr|D4l89K~;mJWBHqa)ns=}7klI?8>K zj&@(7W89bNSoak=&V7}RcaMsm;2s@4(LE-5l6!3QWcRq}Dem#nQ{5Ayr@1FaPj^p> zp5dMxJ<~lUdX{@?^lbOE=sE7`(R1B1qUX71M(4O^MbCH7j$YuN6TQ$q!@tNq)4$j~ z%fG~({ozvgpbwY12Y2 zUh3cIUgqEAUhd!QUg6*3Ug_WJUgh8BUhUuRUgO{4UhCiKUgzJ1W4HVAhkM))V)nZ4 zd-l0ky}92#rSbvyO1ui|Dj#y^;FZ`sycS!ES7QtCdTaw;k;Jo{m?}B^Rn-|@){g>Qx{FmLU$rT(|-H&|N++F?G-BbKG+-vAf z_a5gh_kgmu-Q65_+}#~_-C4eS?kvZBcMrz{cfYa^-Gjlnu0v zGR)srS?_PBZ1AV!Xs`5kWGH;x~CuOt0v$DnC1xHt9lCPW6*U??s zLbH^u{vOIUe@`5}lzxuh%27`r<(Q|hvQp`%tWx?b$2|j-6P|%MvX$-rLCOyQU>rk~ z{*Ix_K>sjhoNu_&#WzB^=pCtS_l;5pI7Tb|$QUKN>{un!KTa7~cD&NVKS9~zoTv=- zPf~g~CM#>oPElsisY+-6G-b78x-!*2L)lVxrgGjlOX)&qD|3Bwlxy-_We%OE?Dgj; z`~359EKrV?Tc|81imBNOfV(=m&fz#lc)I&XdL}wXc{-8No-zJ0o^JlJo=J{zo>gVXd$Rl!JlS-j zC&NF5 zb5qIjtS&p>v)a4B)5gEhv&*~4Gts};(~m6i45dpwvmDDjQyt4a8DxcLK3VCR=2+!v zOICY&`__0)lw0drQFfi@o^QP;+rPoHfo$~bAe%gs{F^etW76n*?Xe;_!$)-$zBHfj8*7gh#kr_`;yZ!^e$aeUn`#f^o(g;% zYC7Rd^GW$tdrZ9}Sk#`~HdIXWY5AMx^Q7ieva|L>zLVyI`+n-zQ#gv+o8vyE_@y#D zQ?^`Gg{UY8|0;){-hcny3X%C9Q=cs7_rLevdk)9@??t^Asd<0ch8aBpDoYy*=;YBc*>?e*U)RX;jg`GU->&+eL(GQxQbuTJg0XS z>vZ)=waX`j_*J$&S6OQ)>v+}gKQG&C9(4rreQ`h5`RY@Zam18XzsvjLery2LXP#MN zv$ZkvV}qdjl})tSI`31z%lqQ_*g&YyOhB*AcZdy9{m`XUov*2lQ(6Qh+z9@pMYHc) z)NkUbf=609JikW1_h#MdsSR2*YuT((D~End*zsAb)(ume)h+KY7gaZ|S(7HMo2It< zt?uV>b!#?j*0^Qe>Yw4;a__!f{{6ShN0lq*ulrqU)4ElgwQN;8@;&Y5af9-2H*DNk za{L=)wAF9TQyQi=w$Voa_cx-O>35v#HfZr%^H$C3ru^KzZc4qTts6IfyMc{1Y}V37 zzf85!FKqAPRNF>zE4oE(W|EEgprts3g zkFVdVKE7}E|M2EGL&Pm}ByRZsFmc`ucFs2`S;(8MDsprm|Fk)>aAO0YWeej zm5YnBJzu5FgO}d5PpgAbD37`O!mDX>f3m%Vnf%J<&tju`o-bi*{XhnAK(7L_MClg_n&(Cy3A{I?Bz$3 zZh4&VmWsEopidGlz5m$gh!4uPT3`ONTS*uCtuIn)^9Pn2@Lg&%E%&8;A0K%6T}QPM zudevrHh$4xrDj#OoV)Q4^;`a+WiOk4{O7@S=fzZ-HhV{}xx>emnrS_IN{bd+?hhR) zxBsmBy|?Jk-xvSmT*{78@BH&lXDcx{x~Wa^eo@o@>tE$-*b+Yf zq+UwX2HNIk%PjgtF)Y@!T>O6QG=k&TML5-{VzWhj`<%_*yN>-|o$A=seGs&%t?K=l z@|!KgUNpkyu%%r|zM`X`^& ztdaCFu2N|gkP%YyrqD=0Qi`6W1)wIKfw3tBk8Z>EM zPjkwQ(7PlFu3fdvOZ1sk>*J))6KZ@GQ;kmyHlHFU2-#9w)>FGAr6KRQ2&C$!c3fY< zvE>h`jq+yhTX5>G>5YrmX09$%uVzdv{;E44^5V8@0d+-w@=-#adT}*t>|E5rc$o z`yW0cAk4S^8te}V(9=jTeG(EAYG9%?Y0k!7{iVhl>`HwsKTrBB3Ej$-_|CA5jdjhq znn~5w_V8y`8y7!MUpkmRC;tevTBRTfJ32`+6-z+#7x8jhXb_IV_y_jl=$u;tiM44dl8a+5RIk{Rw z4Avi35=M7butTau8o4?q2K!tc{rp*94`#g^qMQ%=ji679xW+%!tDaE3Uc=T+n&9PK znlt#!%T@tHoE> z_bE;5;a@u0(k8Lp_O`Hk)LkQQ^#u3$(a1Df%hWW?gk+!Qv!%I%)IS=$@~sj@_lo#b zU~k&G2?tlVmT{U~a%6D*pv&_0@|!`Wc6>t&_v}He!+IgBoR5b$nB&E~otsa7${;rh zy`#2*uhQ7Q}Di3v);{MM>|HHBP1*Kgc9&k6TdZ0oeHTpg|-@-2%029Zm1M`2gVzq~#Q`Yw&lR~e$+ zM}ocn5uYyF!sI>4uL-4$SIT@aZ2d;03r$mNMxmQFYAu@+$X_sOr6Rw8RplI?)kN_M zL|YJXwZ3)o>C9tpXvNrj?*@yiJ=)q~^=L!fpU{VrEuZ4HFB7yY@aHkrYN=!YM{qtY z&;>q0A+FUkMy2L)`eeNlWV)I+T^h9dRoCH_&JW=hL%!>M_28(i3%zRR+g(3q6L60( zxf#vdMku0Z_<|u@u9`jpZTsmpkw2d`m5;7Cv6cCwbO>%()3J4 zI@PiFs$(y1n-iv%%r{ll-++s+h$oB}+tw}Xe{XilJ)(8&^zd^gU;1x@jm;2C$9&CE ze?g~8a9Nxdt((+KZI#lbrSLlCxF&l!Z>wmM(&~q14cV@w?>-TI-m}HwHDmRZCVa{~ z!c!--*qLFvBOeSO#VO&Nmd~|euxb6P23L+=i06MHk`i;+3|&|xyaYUJGziN{L9S8-c){v=wQ zFMaT3_9$UNHf)_&*Hl7^^B91L?ZPOtvOIWQ?+LF9+Aw_=Znfo8WYe~|?M1#=LND2T zWi}4BZNA=j$#FFk!t9mb2=Mv0r5Av8NyD0_XGr+CR&~5OshJR;e*o%LjH^-SlbXr( zYJ8!-{Kb1wTBlv&*8u(HDzBa*buPS5V#89#XX_)>!_KVDUL?X+ECTD;R;&nanH96+ zK85;Ru?X!u^(XZxTFmxT$*t<7V(P1mh4D-Y)gLU*{@6C7Se0Qin`LK zsYw4?R?1c~xyZ!GWP4ga{QMdIb1#gnLgzr&iu&Cc9{-e zX1lfyTP^imEk=DZuqe`2vq(+*o3P2H5^LIO;;n+*+(Ia?fbz0Px`c_>j9ir2u3ZUR zT5(lZnVCKiJ(1o+ z?FpQ#fgszV65t$I&j?_x5p0gEqL0J3LHXAqFN$qpVzAc4cA&Z2SaZLNT-5fdqImtU zwssr(J6j!hv>)T%#Zm1eZM=6{Ron~3-Ar*%e#PA;iu(s&KCxkY3}sr44YxFgh6{ ztTo0r!Kg%07XwVszp@kqpUXg{ciCGE2i6)+IpCCyqLkru%#TynfJ04i$}=2TYdG%% zrvhUcoB#4u!Jw?q=SZuHm7o}4iW6AtwbCm9#c-w92du5I*4i2a%=kwSZf3yfgmZ0CPvW&#?ds$5vOt_iQCF-M@}LhS)*<=OSO$=sUs($ zVAg7k71kPSEwFwTML%Vr!vU(6f@%L%K|ceQP#orbYM3v89;lX!>N)T^!-6doR{vn- z{sXWYF(#pMZv=o%Y6TZkxu-H^SZm77pxh*i{>a3|%DoBS*M2l`fN7;xH{%>=&TwF@ z;j{)$OU5Er?kzDmo7Fjk;o_D17L5Ssz|V{T)*8Y8qRcAyJh9)I7_2q1ztP-3S#yQT z{ZI7w7IoZ1D)%(2is?{n%M^vmy{(C2d#j3_q1Z8sc3`4n<=&Ccunq=&VTN^KT@Gul z%X~P+um%BZU=;1ou!PEepnF&43MA7_vjrp-h~0Ben48VIH^0*qOMA2CcLa5y5U~}B6ZjQWipJkxZE1evx7|VgNG>R^cq6-;`P`NMV z3wkjK#I>~0z@*RG6|9S3t##2xu&s}xYoq9D#wJ$o>kUY2Iqqr$oG_6#F-BNxjJv?N zBZ_WgfI{WI!@#%AK&5xtZiWME4d)PW4n)y?3`eNk4;XOvncy5|IIz}mP5|c^V-YI% zV+Lh?KA*IzcovGMnW9j+pN3+%((4>+E3CD)UV`!krYu(O7Yx#vi+Sb8WkvvNjo=Ol zZbi`>QS=()5G(gv;s`hQYmL<&s6un2=pzOyR_?i>#bM4P z!+ZhsX039^IZz~^-%o)p6xPsS<^B?|UI>J_=l((NVL-6ffRX@| z7@!FZNT|~j4Lk`(9;{1S;J*w9)*8;Iz)23!>I_Gy(~}K2)lG0}FdSHGI9~v#7Gn|X z^jbz~eX7)E+OXENzlQc#Ok1qbzcSPQhH1lE(@ueQg8;417=)_4316~5fP{xb4t3%VV{fwhLy2{@Snn!#{{ zdOXvBlVO6>nc=`%!^r|pH^w5=c?+Z5;^Z z{!Ce{$NL+kah1<2EwUK_tTlpBAQ%y#!vb^&;}Gld5y7nlmH04xe^A|4aQA#j!F;0` zAFMULDd3wFpc5FJSc6XrE%tII80H8{!F^f{j&oot!-D;%Sn>GW%QxC*UNS0Hq3IRF z)Zgh9Gus^rQ-61;s8{~5g;(tg)y@@ZM6Bn0XcH90nuQ*YgZ4bBrw7<#+)@fh|1Ba-b}&NEb5{p|)OX zKv`^pvVx(&79M3SP*yVzv94Zil-0MGbxaqw@Vc9!yOHUNHT6a_-7QQPw(z>Up}Vsp z-Oi+idU_`|x8tmy-fp1KtB^fb#E(M!a7B8sBHhpQgI;!u5>sfso8(*{}8%z33j38oHPc=eZ{{z4`Cd?i|v zF^Ki@3zgVbfqMCQe1C$~%OwkD`!{2QEj-&BU@KFJzRJMFTDc5hgaR$+RUnDQ3~J@0 zTCI$8z`>AU|0&Yu5AYfBhc@;Z@iNg>=&R9T>g89XGuxdGQ!l?BtxpqJYsv)5QZ#ii zaj|BWqJuTF!@z-gb5^TeaSpf`4y-ktw}9heEMoQSiOx*F99lhJ(Fkx3co_k#HG;Cy zW)*avn4gKkS`&L0%`MNGD^$_t(cf3XRM8czDn>!^eWoZ>((jun2COPphGKLyt;9sd zYC4+Fuu2AfVTQ%9E{C<&vh0*JF}xARY$#21W}#IRtkVSNg$vVp3)fl9AvYA_sFYdCd)^F=hR#c+fw`wIh3EfbtC84j#9oO;0dnz4wL_SXh! zVcLAl2w<%dq=29SBM@uu1_cu|Vg#_(2%3Q4$7q_$AcX4sM{JJQ)yFcDh6R9m@gtf-l35=Q1G=l*ORe7d?FT+5kcUfnK18WVZCvdW&X*Y%=ROVR* zoNgvKy%-LxHJtvy>C0Gz>b$Q(S)b1XtSSzMVm4D0D)ek9hAX{>u(rZlYwHLo4`a$= zl|IZMjk%atevD)Uu+|7BfnY*39T!cm0Doil#Fds93qr3M~$EW*FuRpf78cJI;Z*3=8(3V$G_I%6(O^a(^MF3Vl9?J{zMK z@9Qh$v;KGS(e=O7kFGzDPo%eVLimC9>F5WJoM-V!hWf~T?UDQ1zjVxWs{hgv=fI0G zdRY%^4XZS;USUj|D(nCFFiS;xMN`6b0wn(N;oaarK77@xq7#a5#LzNKbi3LS>OVH^ zrK-LG)!t6%wJVWR#y|j?-dY#n9FSNSz*_5qHvy!?P!|K*69np~0x5t;E!&fZ9713;_C7Cz2_{ zT2rnBOa+hX*!F7no!JC`&{3f_~3uR1|Qbi;C~I}uVQE&CVrbW zeT+KzU#SzV7LJ@cA_m_gzp*Nx0{I3p^jju>jLA<>7Yj8*3w&N<(jU^FTu z#+KkE>t|rJilNOJhIq+p1&$di2ft)B$0M`VNAh2?=4$&j&VgUp;J_AYa5&bV!1|pr z374$j(Ghd=rUf65zpN^zL$PfPO=F_sC95q|7qLrLnt=e5bdlBtI0xFZE`YVx1ziBt zDTZb;An}sb2@q4+B`dRFpsoxE)*4W60QHQaSqwM`ZF5g zlGWb;pkK1GnKG<3<)Kg>%#?*o)?iVY?^?r{GORV_F;E^ALq{-i;gU59;=xPS2zW9V^)AzrdhgJZ4A!7o|I@yG`Ck^Gme zP1=5qbKo2s9N2$4I3m^+U|nKN!X@hxI%1Q$6hmHRUA3xs8;Un$=yfJ4Ub1dNbqBj- zT{jSbW{1`VI0x>qE`YVx1&;yrFoxb|K;k9qAs|+fH z%&h*#CGnCK5t|281mBBeB=pczvFwf5Sc^a<0Q3x_5iVKJ7y$H3*0W3*)>>CQ59N|f zS-51C6qWg|Rf;LYT2p=n%Kwg~FEVlAlJ#$h2QOJK;`_boItjUC{l_Z68vrO1OJ8LG z!X>LrK7dzE0322U+yEf4RAKHKA-;{jA0u#D9f2PCeqqEJO&#aJA*K#nc=cnkW^du= z2_0ubu!R>ojb@%?%@p3gKZ!m*qmFaPKRP>OMePFA&M`INt^0E(Y8S1jU5DD$SbCWW zif`Lr<+JIsL0gzjH&{2r7QUPB1LbZkz0FX>x9sl%;HcWw-LxCpxSxBwV5A2O3AXS^ zMdPYadmPPWNW$Co_P9`@TmzAQrH_cyYYf=JqZ9|q({c2vIKAKz-l~7vfbtX`5oe~3 zQi7qt79Qn!pp;}B;@k8k4YI;CDaF)b3$Ok%)Lξ#>4D6|DXWQ->|Q`WsL$6GvZV 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%0D3t9^wk9z0DyE-KOMOE=};^)a&DbXa`A7c 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 z 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 z zO_eWj|MYcH?meTW zroq=H zpDE>6PWd^?RXbvBy29IBSM*BzivDOC`X3(pZ_}O)h5mF^^UkarjvOVm!}2J(CbD@O zaY}=*c9hgJRh`FGjl&*CN&m>`Ehx`EN?PL!=X$hqjhh_FZ^tPYno=%f=}Q1Cj*^Q_ zHE~?iIqW)067Bw9VX92z%3j`;JxrDTxbiCR$}3Hk*KuXCDJ7j#QcNi~BE{);PT1=x zxz?U|mZ^LgD-6-s#bECl6_^Ga&4U$rSB}&*ZZ!>dCl7YJ_h92qm6N%0qIYG9sq%hQ zI?XIIr98-kKj2E?z4j=lJY-6l!zoWixoWemO{X0t1MDmMglXuPc<2{Qdo~n$-c`*z za|Kr~bEOQ7Y~IzJvP!?4D@|4Fx#~kNtc=L$n<&pdO19t&=X!kR8aFeNzl~GAG^Olj z>7DMQWQVEd0N3nwuc4~8E7@bJJj#_vyeoe+RsO}5zk636Ggbb}l_yLo)#4)eh$?aN z9>J}wjTEQbr^k66C0X{ut6?f{#0m}K^jl1v>p*t8Sl2XIa~`azcjdXdMq|@pZF#WP z-h*9Ws_ej(?Y%3Nsj@RFon~HcO6kUfhg~VW*Wx*)hbg5Wr(6}~s$Ci9b(Cb=S2W2q zbSe*hy;bi1PQu!=q0j(VH7}=9t}bz<+z{Ek_i@U-`sJK#s(O&C9`M4tF*5q2lxH6$ zv+;#or!wQk-so>bWTM?WOaHseC6ZY}ePtR__^oX&P)l5B9xx<#)Qq zZqr~t^I(U)2Rme{{F5tx^RE2WRCyAWPBV|2QmS^1obEAQ<>}6Qtp=x5Go{qylry?| z-2j}cR=ca$QBq)E(VC{A&*h=dvC7>?iM3}#p+>H1-kE=Ni%joWH#xnVBAfRlryTF5 z-F^NtRh`m3GH|H72iAzl=%-PheU#L}7tZyl*A@*oO(|C*#p!lpcdtb` z%AR<NOqIjAa;SIZ5L4wS zR65NZX-XN#gO7Hl@Ls!vQ*JY*OyQK$C|B(sYtw1p;Ec7e=-sBFALOAQFzwk;=zdo< z@62a}-TEwXv%bINl)wIwsxRP_p1E$HcSl-v^;{dLN-kCM0Xg>yaLbd5VP zlD~{omYPylvGltD7OrHuspccDS=-ZfluUqhD74yCxtS|Bc~@>URc`0Xue>Y2Fjem6 z%AKZ^eVnq#lyU?qPPY&B^g2o=+Y>)%D*uxee$&^*uii5{Y8tFcugE(5*Sqo`UE{cE zu$nwrjb5G?vwAPN)_HZ+=gPX?m32&&=b+MQWQBBwwL*; zwdv(`luWg+Xsl`IPCRr+tK98MtUVhFb#PU4?=rbM&6P3@h4%i=Sj*@@%OheBoS=5w3A(Me@gTO0g;BPL{qMz~U$wZ>pKhH51)yXu93O5>w@L zuDsv7a;mBFF|K^ryK<(f@+q#IWlDLDQ|6dbUPg-3?H4^4==bOqGv%(wtx>)2r zqgPFXy~~6B&%3f**H~&A>_Z-GwfA7}n<_VP<;UKY>rItkpwemPW>d;`9{ej;3h%XV zIOS_o%0W)q7v-vb?|GEWwXf)RrlEi3p?@~**-+?+tD1LagZRkZ;LLb=QqPNQ-X@%K zcD#0!G&EH;=c=ah9w*#ukrE-yoRVQm8H5z4+j;R`_qR9g ziQix%Fkvi;TXR^6aDJD}3Qxk1eioS4Hx_=9F!wlszoH z+kKSmGSwX7ngi}Nw9M}RK2zl}t~}~p`ID*g1Xup$UHONpvPwea2Jo*br3R-|OOW>n zZe?AhINh$D;B}O&wkKZGRNj~s8YO7An6naG2eQ+}`li8J@nFrpE6>+8&NB_Bc(AtK zgS9bLUe1*ryels;RmP#xX=Z0rN>3iVn=6I)S`w$kn^KZFrC*e*c6EZ+QL@gyqJ2z5 zXYkOeR=N8d9Ba>pLIYjZyqtz}^-x#J1{B)+yO>i7^~*WJRCOCyjrGFX92xyC%Cn_P z@r83eN?hZ99?37`l*y))87w^wz`~W>XR3LeYaVg0p^xnjK4hw#%au=iS3YT~T)>s{ zy({OLDqrKuS4=63Ipqyg%5tPQ-7fcBlwaBtUur5}%L*Up>tdDnj8>Wk`;-UU=v}!% z*Z9aZ*ft*QOYgz9m@2>J%3a=-Uz;lTqta>S_okE|dGLd-6y9q`Ipv5c6vR65Ok*_84o55CBi z!h3Bgrz|$5tm2e+qg=J+)~3_G!Kr$tbr>u&4ZVSfUT4~~q0m}aHSf&Cq{udYh^Sa8>^#j}xv|Wb{ya9UE|h{+& zJu}JcD5+~NycwqQXISA$eO=7*p3&o`!4~jf^SvwQ=^D?P277}Cd(C^Wg{I1Ku3X|> zx!6>>5|vIfmzz>n^WdvoDZJM{;*_ z<2H-rr*XhkI8JGgXe`%F*7HqfC`| za^>x&lu}M9F{Rv(6sOx|DPBiOOMBu|Oy!TV!bAGHc+h)B(@lfT;lZBruAHrFJYgDa z0S`9cd$4(?%GbH_Rqx7IOqEMe=``~#Q_BB%@ONA(yw~32loh6w^_=oyl&iMJ+H~4c z(%QbFADD*T!b5*%+Owh1CRa7@%>7*by(^_{Wb+>3ltcREJZP#q##KkXusTFW|BLeM zqvRyMaIVL3*SMEO@~fssQesl&*~clTBgOeEil?T!j*@DontEJwMyl&5X=nGpwyClS zSDx)%+0azkk}I2eS2i_OUdWZPrj+)a($1992`NsuJEnRaC0E!J?_etL#R}cgX4kK% zb@iT6*fdyQ9;}adWp7<0(KOgV9&CX3V9BP+Y_81ku1qsk=A+VS<_)HlAw2jXR|@a7 z;hZwmlrol6ilbb$qExS=By3;Nk*1+bc<4K=a`$6bYtM#46I|82?H=Rmhg~V%P-yS( zr#WS|emS2oRn6n7xn5XFk@@V_(sxrlH&O(Cw^p z_fcZ)*-)shtC~BI$kn}EDc7RV-rs#WrB9l6_vvk_8o*Wky|B_Fqo-1yEtQ2Yoa>S9 z8aE@7e

        lm{NwY^dJC>Z*cNWH6yuZxO)vGJd+9?5UODQB8eny~cQ>8_)sp{b@N*ECCa-N**p{cmcjY{!)sdRMkK zRd(dcOT8=Gn<~Rx*~ygBlT*5xQu-jp>2^}O*ZpmzJ@Eun`E{(2j5fQz!MVnJMtx0# zW%FPe-j!*(Mv7^$!8};L_h2`gDsSb=VcwNDn<|S@=`^#@lro+NALB~ly>=(3+-^#_ zms2K1xoQ)wO{YC8DYma@iD~GWJoI$ao(+YjxvF_*F5>Eiu9UHn&AWtC-qJ7U8>Xt| zTvhIcH6=3oD$28ulC}84xgH<5#=SR^zkyTMnNl{h^d|RFve8ttool{wuc7gF|GzL* z?%~Sa-j%ydm4~?UfOq9SQ{_>vJYq`ugHw)~QvOAX)9n+Ui}F5u;(wdUPs@nhEUIT{ zN69G}t^?WWVwDVehv3Uvp9ib!U0FxhsAU@LTpsKk@4*_GDqC@7bMMOYO_gm?=`^#o zDWyFR-p-Z6d#xjes&&cmI!dP7SG1F9=srAjl2z{h2FKd7p-_UW znlE7%SEsvDW}?vE-}#(!gMK-4OjS2?)nG5IS&`9ir94||6uxk-$4J+>vm^QAIAydc zIfE;wc~{SI#!2%;S`~ zrj%EZ;&gj~=c0Vtp7;x<^0!&xO?_Rw?meT|OoOfD!IpbhF4HyMF%7nk2V3Jk*axP{ zPq}iVcjX3C<(H^*n)$gYWd{$w)s@0~Z8xXvG^PB&Df^>bwY{E4$+Pwq-D4X17!Q5a zv}Z%1pIp_vGf&IpTT7cHWEZ}0uE!47xN9T%dpKpcDdh*2-tRt2_L^#b;hLY^YpC4r|6x<*ajyK+yYhEa zW!0?6F&>lUI=&pulcvhkxUzbdya8~Z&ft_X}-?KC)IRS z{vGL4Bd%=VU0Kgm*_11rcvqfds%*&1(E{a;{o}Wv(6BtshfTtMa|D zIz>hwMtQc>NPOX3kKwLyJ4f~=Dlm$p}x;@`>QO4O5pJyt6lNA=}>*7`K8NFf} zY&j2B?p?W5*Ld4B*cu+}eec2EGgWTn%Jtrr>r9oOqta>Sr>2yxJop!`6y9q)Ic2*k zWk08UALXij=XsR$u&?ND)6hqG=p&{*8w&mCs^*<}N^a!V63Ufle0*f{*5s5Lx!T>Q zx~b|+uBwykal&048NDIp*+)qeeBoS=vt8r%jpR4ul=Dm}ty#JifW=YL!c^0qYue?y z?x%@%|J#}>J9Fjb-j$b`DtmHeH}A?gQ)O?iOfaSNbbCOq*Zr-(J@I5y zc`hqt>FXlHdq!!d!EWZk276Z)=o)#Z!HRgW5#EChH&x!om1DgtN1H0|My1otJ4`8) zc<_5%DZJOFa>^7_%EO%UV3eyi-P&~8bL8vnD>}_I^wT`_Y}1|%g`RL#^UmCn7dc9{ z=EMwrgk_q$RGQE2b)M>*vo{c=8Ns(O;Ep76q&5E*?g<=Im6 z@r83eo^y?RM8X9GHaIvZKeXd;TUAe+kxt=RO z^sZcEs{E8IH=0tu7d0an zb&W%&!H)A_e|iu0yQ#8jLFA4SQ{cLzILqLqsq!>bI?b$JAa6RnbnEcoHC-vZ*Xnah zT~o?=oYJ_!>jvOlwX+Mnj*?RQiZ(P2-I|APWtF>+5^K+fLM>d?JiQ{W#y?sq{^ims zD75$YcupBppxu3nO;vYs)dVlBXCkAQQl2eUhA*7!G1)cloJjryoN}KjGr#x zi}E>p;>%6t8(3kTzAn~!&uF!2urGM9&EA!t>KdPz2HVAh?eHFKo2haiSMKqy{MJ1iT(#q#N68EJ75&RJ^yxhGse?R@5^K+f zLe&PzbAoqf)xro^Orh)Ni3{z@6C+(ePh5nz?R|ebN}cANS}1=c{6-|@Odh>Xq4;^? zQhV%Lrn+;uuA!`Z$*yZ)s%y@5O}*;QHPyA|x>lx?cARpdDdjSxI1Ra^(DSF;7rQE# zNBR`z%1+*umzyekabY%Y$LU3`8(R%i%~@PiugGPNR@)t{YpQI@l})@W&oNcTa%D^J%I2oZ zc3gR(DWwCav^S-Mk>c#0PDNgB>l1t8mz&BHS)mu&?D{KiJ-lbs%`{kl9;~l-cw;!5GYHj-0@n^JD$l(A8++UO!L zkG$EwqN7Yhm-5ghR=L|FTYEMXy319~+in(DKZa`Y`&nD<%7=G$}QfNn@yEp^Mtm!Quy-i;lX#Ko$|)E z%T#oTiw>a3bz?hVU%$Pk+9jhRH-WcC$@|2iNUK(G%Cb?~0rrlm>I1HNZ2}p(uN&J1=y@mO17JGK_G}B;>d9X&_m1pT1^-Y7d_AU-p$s8AREB%+yDK%n3F(vKsU#eFP70?)id5jw| z#>g=v@Ef_-Z?IaqEkmK)aWRAPM(0%;xsLt0w%I1ZK_XoUAnt5mstTukxJd6$m9wJ>I4^_b8p z4Pu(dl;l}!qDqzV<6;W)2JwHo#QIP9_HwB*!LvbCs@#V62VKr3b*+*Ds|3s7QS{C_ zT5waS6?3}H786r*)LCc!aQK>g4zK>DXZeGdUs`q83nQw<#Ka_ovr~!(k1Ea{KX}y0 z@!5%ki*Fe{vM@V!Xz`f5;VFY}8mey1D;_;~RCZEgUv<@0+2gP1n0?*g;e+#v2WOAW zAC{e5ICw;H@$h~_^DF)F;=)1sF~1x=JLc50TK?T^Tk8j!KiK^F<}Wti^?$^@2Y3@# z+WtKPXTt{AB&6|%WivAxX#~~*LnyXP9Ar}yh!aYZO#p{r173;=HmRG$!30e2V7lqO zgTa7l2Ge`*z4zYnchAhxSVyDbd*gYp>n|?NF{9^s?%(N;W@K5oD?AXNi%ab*?aS;_ zBw;Pb}W|rI#$d5 z9mnK>j=AzwN48_0W07Nl}(Q9lafW9sL~xQP-)c)dJKj+mY+o<2b6+ z%W>6l!*Scu&H1NugmZ>-mUFgqj&m+*I3M-QaxQgdJC~uhtDS3|xz2T{^JeE3=Qihd z=T7G?=N{)?=YHn_=OO1|=TYY|=LzRY=PBoD=NYujdFMsvb+pd|=VRv+=To%PA96SO zPr19?Q|>R1mnX`Tx)!+>yRuwMTuWWc zT{*6mu2rtpt~IW;u3XnT*Lv3m*GAW7*H+hd*ACbJr2bC`$1O%*X7P*Bn_2u)9J6s; zhU0RzcbD@y=;M_*uEKFOj%#pSi({_Z^SS(b^nV_X8*to+<0c$8aSY3tHHCSDT)eTtPgw-ur-G84x9r`8+x8y99ecWP*WOdOXYVE4xAztv*!u_%?R|wu_I|=+dw=1HeSq-PK2TUK z48n7;@XS6$cy1pm(~5X_WA%G+O8`jS+fCV}*2SoX}Is z6naVHh2GKxp^r3C=qpVU`bm=otO&vYX{s<#nuh0eVURRK7%a^chDfu7q0($&m^4Qi zF3lA(qQ=b2;LyK%5-J zS&2BS5N9>wtPv(kYY`_Gan>Qudc?^?oDGPx5pgyNlcdeUWNC{qMcRru+Yo0v;_N`2 zortpwadsol9$~7q7jgC>&VIx>fH(&c=Mdr?Mw}zUH0h`?T{L%t&e~Rm*?&5l>hnOd&iyNe#;zp^LxJl|QZkGCpTcp0?R;i!3P3kXh zmj;MCq=Dj2X^^-}8Z7RXhKPHlq2kieVPbaZaB*2^hPXU*gt#Jfq?i*rN?aK_T3i)6 zMqC{_R$LQ0PFx$BDdvWb7uSVO5Z8xJ6!StSi5o&EiyK3yh?_#Eikm~HiCaRai(5ly zh}%MEirYhHi914Pi#tQ-h`U1Pin~MSiF-oli+e*Ci2Fhpiu*$si3dU#iw8rq#6zJ= z#KWOW#Ur8F;?dA$;<3=>;_=WG;)&24@nq;q@l@z4@pR~F@l5C%@oeZ?@my%Gcs_KU zcp-GXcri3jycD`Yyd1hwyb`)eyc)V$ycW7eydJt$yb-!hycxP(yyDs+-U{6*-VWU* z-U;0;-VNO&-V5C;-Vfa;J_y|}J`6n|J_EeMRi! zzAE;0UlaSeuZ#WNH^c$%o8mzCEpd?hwm8^*M;zk5D-Lzv6NkC)i^JUy#0>XCafJI3 zo{z}%bV?YZtL_I2*5_Vw;*_B{7=`v&(6`$qRn`zH4+`)2oS`xf^c z`&Rc{`!@GH`*!zy`wsU4`%d>l`!4q)`)>DQ`yO|eeXo0oeV==&eZM=~e!#uVe$c(# ze#pJTe%PI3KjL0#Kk8nE=W6>g_Zs_g_gec2cdq@Ud!7B1d%gX%JI{W`y}^Fgz0rQo zy~%#wz1e=jy~Tdfz14onz0H2vz1@DD-(kPO@3i0KciC_8yX^z{J@(uDUi%$>pZzYs z-+qrjV872Fv_IevVHG}%Rrm;2;iFiEk6{%)j#c;sR^gLag->A>K8;oQj6D^rbt+ct zuEKe&#uu;}U&LyB39IpCtj1Tc8ehd~d=0Ddb*#oWuo~aQYJ3Z;@olWecd#1Y#cF)d zJ_xJzV64_duv!nrYCR0A^>D1#8Cb1HV3i(;ReBDeZy$wKdNfw)F<7O?VwE0;RXP)^ z^f11=G@S1tW$@|J2)?H@lK=l(r3Yc99xUbZL$F#8#cDkatMzcK))`o>M_{!cDP3`o zlCHW(OV`|Er0edn(hc`G>83kVy5$}(-F8oq?zksPcioeud+y27efJdUfqSa-&^=9h ze5os0Af=IoQa7?l`jae{x|1xa z2U#MelciEmk}dTj%cS09xzvZOkouAwsUKM>^(U*O0c5o_kgSmgk+srbk}C}%>!hJ% zy)=yENyEtoDT8d3MvzU?NU~WPMYc$z$yR9$*(Qx8+of@2hm=WnO5@2cX#&|TO(c7y zNo21yne3CMkp0qBazL6!4ocI>A!!CVD$OLvq*>&+G*vo*=SgWcIVH^@r=_{%j5Lp& zmFAOk(gJc`T1YNPi^xT3F}WmVk;~E&az$E7u1eYDnzW2umzI+o(h71@$|1L;mE^Xx zirkS_le^Lyau3h@(pvIB$|Vn_b>xw>o;;TF$P;M;c`9ur&!kP{xwM(&OIt{)V=MW? zv5jFL-o`REIS!Nl zjw57%<0u*EI7S9Jj+4QT6J&_vBpHh5Fvlq}+;N&@;5ou^hKzKaC8HeY$Y{rTGRAR% zjCEWj;~bYrrsFah@3=xHIIfb3j%#F+<2sq_xIv~kZjz~vxxzHZJYl+HzA(eFK$z)R zD9my!5@tIV3v(P~icEb~_FTdmIOay^ce| zKF48UzvGB-z;RSK=r|@EavT>9J5C5k94CdNj#I)h$7$iX zSS#Oh*PC*_3~Xuo_x=-LB8+UC_iv)k{>!Y%a0seQ{h1@r z{@k%$&UfsPQ=L2IKb*VduFlq^=V7_8^N8Hfc~tK2JSGot9+w9?PsoFuC*{G;Q}Ph!X?dvgj6BSFRvzv=Cuca% z%Oji@r~I?t8McAhV{%-PGk+_|;f3g@gMFtNcOd0P&D> zpm^9hNIc@)T>hwYOZj8Yt>uq92a6}18RALj2=SEje!0`m@u6p&`^uelPAY%SIl26K z=aljnoP)wHItPbcat;Z*?93^D#ksQlRp+Ym*PKJct~-Z?-Ea;MyXnjbyX71ab{o$- z&NX3ooomDHIdjAAJGX>AaHfVobZ!lMR%B@f_x%LDm7@?v{mc@W=E z9?bWbmxK+Fmxc|Lv%?0-%fbfB%fp7qE5e4#Ibp-(m0`o>Rbd(O>aY>=ny``b+OSb_ zZrEsfUDz0Teb`tzFKnE=AuLng7&czs6gC0RiSjjmlDvgXmbZmXkvE4;mA8aV!*jYk zgr6aA=4Z-7`C0PTu-SNhj=Vi=uDl~`9-i~%S?&e$Fn*!DgDjGFhAozNg=OKnL>|sB zl~1~|Mr(HSn8P`fYSIN7>R?B^!Ecm@OPk~!!e-Qci@bnrm62`8dHixOd67?7QVGvPV7`wpTtB zwhzz!@=ED|e9wMRJ{)#PJ`#2q&m;0)a#TJVc1%7Nb{x+W@)O~t{8TuF=V^JAbVeS< zpOu%p&&i|t^YS?90?uK!@R#JZp_k=V{1rK!T!qgy`I&GX&l~bN{-(UjeM=t4-^Ten z@^j%Xp7-SO{C#;V|3IF=Ka>ZMNAg7ev3v{fyEnU^%9}%tEcOdtC#Dtt2dr~T-WfP{kp3kp8Z{u z_yMlT{6NHw8}Naz1sE2y~edgTI<>)<+|2N>s%Abde;sq z&o#@w!F7w@=vqcLxfbx7U57%qxEAtT5qBG6Zg*WIJ6xyT?{aUaeo~s_UahHI^R18= zzvR0RTYf&SGjTOrC$vnd5EeFo<5IOV72-Q5v`YCt0hgh0EfzMm-;^JjM}=02?WNXj z)N@5}ENa6A#(;-v)26+8wy0{;)Dd99sWyon)zi2Zf;druCYnvckLr2lYG6^@e>(?? zsd18jQf+WG7dEfwT#RHN3PZ)pVc`+gdHqqTYD7f!>Q$2A1Z}~RjXEw=iiU0UPXK9n^!n4Ki|g1cmH+VS8?Ib7nYcOXlBD%qxNTs&c&NhF<(f52Y}Gj_IjMCD zuU!r18>e)MPfTi7IjmAdvzVj~9lCT(O!=wV=P}KiBqg;^Zq~3deymibLgnfeDo0eR z6xQt9#E#ACB_*eP8D34jZrrMJh4}XEMgDD2kd&V~CB!GT=Sb`S{Wa($?P7DYR-J$9 zl#i0ZsX{A`#3vi&dAg+`nZ2bRW*n;cs>cw_aH~Ia_ z)vJZ0a-YU0wrta|OA3ZnnE#_vObqvWow85fs$#>R!sWQi7`JbfNnP?CCtwtp{=6jC zsM6(?m8x{=OSq|oGE_afwR6SPbERg6|F3J|>#oF(t=e~q$Nd7@eaS6bCnTq|Y}Kwp zTkbX6lK$TfcK2D@`qVqmX5DiMRZ7*euAmJNHGJ5q$sr$9Oxawy@xA(2hHoxXYWoM4 zEAVY%k{bKkp-+yyQ-yCZp-k>C-1MB^N-e5sId=QDEtA`-(JOX4{r#9`OT9JbE#5PD z$@pod7Fv&<(7Cf3`$InA{;$p2gckk2P4WL;O4w8C{lDJmbQb!0H?bpb6LoCaUYnim z6Tel3#($m{QnLG#IpU)IqHF9&Q6XQ4bFrV+{-kl^264&l;*t}TZwtbmNocVQ7&uVKlBG&#gF2>uSL9{pK z<2e2I3c1w3;VXym2su?#mv2xnPW!w^*O!&OiA$Z1Ks^8u(vx9qo!Bux4zsDdEkv

        ^+%BAJ9Vx2T={@BjDt^#W2EQemqyg8Ri3L1mPg6;fw~(C}LrL ze3YbYRPv{)isPX;mK2#E9}C5T4Ap1URz$V7PJ;48Qs#bqq9lz~KHpkQCIUn?f*Bx~ z?iN$s;!EP-etfz)mB5Kl#orHW(+YOazbu?@Ch;Mv@ht@3e7BfOaNL8>_cnWZbEO)A z6+EDOa2(x>2n+GwVnyI{FDd$GUWPS^5<{C5;J=49$sO`X0si~LCWiAzw68i6sw0|+ z;Uvtx_lPE@_Z}`Y7_-+Xf0P@76>%xh2eq4u?k+BZ;}-9*eJLGH6> zTXi&3(k7ohmlBL-7@KS|2Ds5DKDwl&wJ7OdQ--ZGH_%RTiDU%I6LFCA znU_9l4a>t&=VRlb#AA5rC=Lp`Mb#j54`EWQg|3 z{sP&xCgKWVF%NxBqPilp=!5nKp&;5vxd)UxO~friVgC7!gmTLV%6&pXw2$J~6g!s0 z!MyWBN!6&@B25+49)+5JQ^N=`-|XMCU?WtlsbPc=?YFTcR7;R5_sk_ES$O7rYfy^R z5$&r#1@$MIipQIZGQ`0B@)J#Is(@d99DhGaez{EHY)=y#qJ6e1V5{6zJWF8QD^~^# zGiZ6w0*RX$c;#cdSH{sDKuC!H7HQW@_>A~{2Yp7oa7$qYmGoJKg;L59)lwb5oCa%GZApl-MMgrE<}K+M$i)k-J6L_f?)2uJ0{2L+T>_`(j-%& zGTclrRg3|^=-*6aH4|?V3G?CotpS|{0zQ`Bl$eaFeT!0rsFtEZV0*urc(<8&o7lJ) ze_uj+*TQ{Uf@6g=m>3b&7(W7IZZk2A0GTV#mH389R7T215Duam&KTf~ZYD+%4s+(C zC7e+{aK;i2q8iRb;Cx0b%$c`7M$ zmp)aJMlI&skFSXUQH@|e2pbu;=jdO+8oaPN7K1K5gH{P4;7_D4fDRe zIX>%u8y{VNPy6Wl4Skg5>Ar++&7UO--HyfRFC<*xq9UHvB=bE|4U>4>BI$xy@A zBdTFl1XcxN+S%Or;lt4yQUzTJiT*E(0U@dZy$GO2MDt^F<0q3p*Rs<{0x(vcU{Xd@Q*H`n zHz{9+a#%I|x?4@z&6Out#m_|Jo9>rL8Bt9+9Lk}g;$;$dgc@UGnkF6!@w3>Bz#;Et z{QYYT)FG3rYU2bT#(EQ>3h)X5VnRg}0X*Uf5aR(5uKZ0nl0%pdA3>N&T8<=f^`aSIfCEH(8zEo;n{ zi?6%{j$uuaDXQ`rknbES(n$U|$Nn%_S=v82v&; zAHv{ERzGko);O#ss}EjTroH01WUbKWYaHDJsB;i)b&iGgF0kGvCbnd~jYO=-FAJ+b z-cwZ^3dO;pB8Nozk~J8rYiP;JkqA(vYxET0=>C9GfT)&&j{)>isK_NCzGQs_h()wy z;{i0faG>!7gs28I2|yExhAmkWB>-c|noP=wYRX?h z`3q8JOV$@$*_ySck}{&2@+>IN2o=*woGn>1AZ{*M)A9Fp+BorAvSzCSEC9f~Q1J}` zuqA7r2f#Nz02ZnOECs;gQ1LARuqA7;2f(*J0G6o&sk0?(1r$BzCad#TQs*P8 zb^dxNuMHKeNt`WNYpo?~HOH`~$PKFUTOq$WRQy2lY{}Y;g<+$%Fj!004?Zxq{dohpFY8=**bpo&aq`l&~WbM@FYaHF@sB;kiZRc>TE5N!$ zOl--zghcGrhN9O~)>T!-n^3$FDz1|#U$SmMbuTSh*Chhb?A23%qx%-608uRk{{ZNI zsJKf&e95{Gh#zUmx?4EVLjpon19~(J@3@AEBKWr_wBNYImn{FVe4rxuJMSZwp<-e5 zMr@cOP$>XCMl@{6dQ1W^maNjGjHs51$Dv$?l-ZJ1hAUgMRyk5eR8y`1<)_2MlO)cT ztfwJvE?H0F@4su~#B0fVMirn604j%xX9<8US(QBip7j9`pbFpwK#ed_jR4q^Rl@_I znhyY%DnK0o)FO4ZWYvPAN8MYUUza)`QLXbEKshK(JWt|m$qEWHpR%6k7}k>Yf~ve5 z^1)%E5y`V9D>w|F`qvf)YsqTl1Ea~m$9MrBf32>6{B<`Fc9K5(#SuH9c2ui(uOC1A znR1W#Z*!lox*w|h!o)8m%-_o27iPYd|BJ)`o@4sTfTR02LP4~Tau_HFiG#n5e-J%z zTI+#NJ$_-t8C@Mm_YqP@w6A_V%-37^`9dd12+_XKX*BZ`HIu!4e+oH1qxG}b51pM+ zQM&-ObEL-Jxb*Nnp6PHPlziofjs;0}5Hmjz;D9woW(|i{wx5LCuLg8=O z-v+=jE!Cs+4Q=e_-YgvH9w8yxM=BZ~CH%t0LqcM2*ZYNg6FroOjFsL$-0&EP_EAa# zr9`+W7H$|G_Evof38ffb;gxBilp+*F`zVhCr3`WKx9Q7BvaC$XkvgJ%_3}`Eiq!dA z^iLJ8UV+pR?WV*qIT>NeM`Vvk(3sp#9tZ*6jji(rCdZ^^qQwqS|KNYzV(f@mKl0w`hOqB)_kx8uVkl;%EAA_)c2KFTXVi6IX5 zR(y=4YSiwlDr#|1Ye{PCZTOZ@E66gvMr}m2-^O^TwkB2n7JO?-7Il|zAKH>SqJ8xg zs3(Vu#BkAp82H=o$$Z+t+wX~Z<+3)BSZ}{~D4a8uI1%l0b^~XZaFI@s{H^ycKw^e2 zFI}n+0H4+@o_2I+5)z^vq(I$azXzmu!o^#J#5aWA0n!aEOV)h`% z;^=;#kPz)7eE_5(#KSg&h9DnzAnv^xG)zV9W2k);E^4^55J`ONr!o_HU;hR8X0C0^qfkqb&GoD}&?ZZp~%%pHJkzn`+&?FC-iG{;_ zK`@B+VWtCSDv_|wpQ)0#v5I_6s)+VgXG3)+sj`iqnOxO+_Mbzli1t+%LUn$)m`lQJ z(`P<}%}t-V`1_!0s6wwzpG7L-%OJiaTzp63Y{O@Xhxm6s#FwjxuZH-_aPd8fv(28B z9^&8o5MQGrz5(LvNSST)tb>}zykm9tM(S)t`<=ZNs++^bCK6_wJe$MKO`c60!P?~6 zrXu|_q<4jjpGcZ*@a)1wKNPi$Hgz4`8kr==;yqfkIGaTJTBaDYmMEfYkf%0gC z@x;kDcpi<&9r}sZ1D+c^qjhy0-6cpJ(Y|`=2wxjK`9l98Aw>H^<DQv(3QwNzUhJk<(EauE`ueWZFo5)q;fA+Ze}AraM)h>X=dh)@viqr3=| zMiJr#LSY*`jU<#8e4qpq3Zi|Kmw?iQIQRxn6G@hpNi$MMw67ix^-xmh8$6+ft4EMJ zqJ8yOp&lC{q6vU)@Wf)$8>>xv)&@_sL}WZ9w@^W73xqZi;`Im-M-*&>r;RmeUxzv$ zGjS4+QK9W9HHh|8lM1em5h5uJ3vM4 zZKw?-HMYSs5NZWkrgx}~i1yo<1J(CPm2dF8C&{Aj^6kSQQb)9}{t?u3BgC)>F_aki z22U=ZHn71n46jVkCK79dXK3M^BZw2xKIb@aj)@SX36gK{jPW*fd84KJ0PrW8#nX=N z@q~nE2PtQR`Kg~3z*;JXCg)UNbwZ0ad-ZVgjC+beM*93g;a?c z5!D!LfU#Pn2p~Y_(5p#&0TPvwvYLd0sD@J)IJF~1AmK2VUR%Nm^noJ?2T={D0dRtd zg*o*gN!f7fFQ_WM2*pOE$lQ7(C>CVBf~l>DYHe)_Wj85v$L^M-QH%NZ<0T?MR3nH2 zK}4hoixka?gS++!KCQsDhvAil+C*cy_U47NMiVQd8tZFdZ51h65GZ%;@r7s zTk~2!i33babl;4ldm!N;s^Po`oOg(YJNI|cIjgmr@pSHMbOIdR?-K!{8o`iAUwh^G zVnay`QB5ot%^gO~WzKyV^1VjucQ5BYTvc%-6i1LEbM7O2D2`H990$cQkzzE7a_2tA zs<6?LKC7_tlyXG1lurT9q)0K5aJX}y1c)VC+AZfkv2d&}2n$gSYbLP1jug`fi#hkN zC8}u>m9e1DA{<0DoCUy{7b(6W9Om5TNjTs5z*$H*h-x@Xfb$)(aOeJ=B+bfZDG?y5 z5#)hj1rc!PzM^n~l|+E3Mz8?{>mtP(f?&>l9VW;1+T>_C_caog;dC~tV*CV*ZINP2 zr1+6Ym~-D|4d^W(;A81WiOHzi9h4$OwG{mdw!M*JPo&sQY}~o;m5}yWxVt4dR!IAa z5mAltC>Re%ih~5mocm#k@1R6wr0fsEK~%#z4V+Vv;soI^=YC4UIpG864B;TE;amjH zd17JC{k)`X)bk}(#cNQ!LW<0}Ux8vl*6TX86;Z9NH=%rkl(}=iAxWba^XGNO6}qxO4x9Pb+Zl_wmXmZKAQ9``yA>{i2MG3q&>6$G}<~AEF?4#+`fd zC@*uE_h^*2fdceu-MQoFE=gF3wy;*1&b>0Qo+T#c+@A%&7R^d{IrryC8BtBS29&Ge z->f2W?%bb@CAcTK`URKuwaoIqmX&OH#FvrDTPPv^c{C&1BNhX@eW z2u|ekvaDl zeJHwB6`Mm5zeTJmiE`)O%&M@al0K`jP)a$XTFPU9ga4cFtZ?TZ1&FO$+AZfEQ8-pC zVIitvy$+^0d>Egy#GHGaMAcHFG8XjKgoCJtlK`Cd`1h*_hdKB55>8tmIEjRVsD_gY zoQ}l8oqI<~nw3o&5g@7&WPqSE5pd_;xp0CmM1ZJ9&=UmRqeLb_Fz4PKljASiv+_}%?(+ZsX9K5n$n`kWOKC5un1;mP| z#=0D=OYsYd2$VbbrQYT+Z?RM_fZnA$cO2a-2n*2`R-WnHw*hMlF)`=91po&$E8*qb zx05oWn)1(3-i42BkT`elyR3O_hr|JD=?h4wD$7n%FTk_b4@&IrpQ;_i?S?y`1}TRmDG{c#;&Eb3f@r z@wBSqMJS%fzq3Q4+_|5(D(tMJ&noN^r5sT$jALt;RjO)i#hju64f1v%2?32}zojO(`NkR3msC1Z9YTJNGh$6O3L#ARAX!m#)i?N0Rb}S-caIeAW<19dy#Mu z)o_{tr)jis6Ap9kO(h(+51f|?2T=_t0ytsB!kl}Uq-@l4q^e>p6r)LzIrnHN7G%9% zp|&EbwY3$LTaYq$?kyx~)MCE5}f7adb~097HvoDZrUTEZn(I zLgx&x?&aJ+s;>P^D~|3jhyYQIU|KYpCuz?;Uu-&wA*zYZLUU(ObD49WfqZ|2)_Obl z*{X{3p!f|bGUxt{55@Vaii@H6ZM0ZOqTIQEYgO1nNuO2N5=uFuTFO@f=lf`}oN%~v z{~i#Rm~&rVIMyn{LR7>00azQN#X7=b&V7SKwN9ck7W7SogQ$k{6L7Xgi!Fr1_T0Bg zI9q(+>>wOOHJm-b*-b3mx$l;wS=szT1c+(`zk%RaBH+&b*TM;YCjvw@frB>K9){OOh(n7rxYQo zrRXoPU5gf1qQxa*gmlHiy(Gc0Lb^eWh-!@Y!FV@X+$KQg-0wTM8^S?U!&wNN`NYDV`+RiHB&}vV_uMDz&K*bhA|gOkBUlpS%em)^EhRBTHL>r} z+~w3<=G>Pf-;=d|_u6yMQ&n68#Z{!pock&tifdIBH$ib@j95>i+_`VGDr~)^&noOk zN;#rh%69-~dyLphINZ5!2gFt8+_x5vwUe+A)v$gA*4`Mghp?D)-z!n=k*JInbU)!B zs^J^~&Y>7_fN+>|KP2HC@PTuba1hmSP6FpRv2f>pT#{yGbBYKM)dFSW_ha_*NTD#PhqSH-voj5{&nR*d+YNSJfKV-4tA zAmC%^Z;8pM+WV9uM70z>5{q|=VufFV$F)Qs&ORh9r$z%(ovdB0y9l z2m-{WO^@$Zxjnxg-;8@X^K)G`d1{O1i zd5xud0rVu@x#Q?=LRg6Z7HeJmIKNo^w>M^Yz%M@PV2oqt+WU3L9WqmMZ(go_KnG(I zLA0;>E>z#{AO?~!ckFL>Fz2&@5(9W<>wXzW_j`nbXdh(=PzDhPck6>X;Gdz?>crEn zFVxj>bPpwUMEmNw9eg?Ue4*haglJ!AB$_#bn#o-H2;_L7*3VupeUysY7^saVHRjMq z`%oLJqV_q|CUg+vNsznq305_Ym$X?mO`ZskNFC9>`evwa>L4}}0CVA+FzJ1# zO?s9K-zX6ou4Rh~!p}h1)j{m&Ahr_)bKtwILAwL$e9UZ@c#I0&L#aWupPGZ<`n`kL z-$CpnF7Cd6mvHu5sQV-^Ryc=<579o~N$?%-ApRgY=Dd$fY=1~ZMygH`3Zi|K3qU#7 zL7X8J=DN>GC}(`2TqG1k`zY6da)mgU-*RJqf>Bgvxf^6kTYQb)9}{zw9zN)v=%f_O*_++`O{VABR%wjW+urcET4%YIlm z=c5Vqbef>RSq7Y?6GX`b!_jhwT^dNt(B+j(@HRgHUZ6W{9NlFJ3DHjKUez6TH6R5L z4|CW75dU7Y16~fhI;kSsSFHtASAwWX!rWoI5=@6(Q(^$mO5Nk)=&nsDi1tzH0Ywl8 zch~|QvR|_Zg z(FaN@p&;5vNe9Xs#K9f*8 z!|sDgZ<99ZSq{6GL}a*>EER-zfbhQr@m7M!CJN@T|7Q)_x1i3)Ot!>hROq{u8btf4 z83wMQ31V=9$RRH7u!l-GgDun?35*rahs1|ypYId!jZ6?D2#z`IkrLYoiO5LRXhK1> zk1_!$;}gVKLSYVjyo55=2g*c3L9~zZ1yCjv2XokyB~_z#zf@714z;PI#vJxks1;VnKqKM-1FyFXGb%9QFddvQ?W% zEQdX>aL&cViD;j56*%(}#0rAs4m;1=(B-X=>O%w89X5{c)r5p-2dRzju=fCIH}Nos zy&K{`X?DQNVgEv^i1t-~hwAwHons*!y&K9NmAAI--5`lRh1GzR)QWLbNY*7R@|O&14SyG;+L8>t`>AeNIK~ z64Wk`8gtkee5hSkQM&=P>j~m2337*h-KwUmk~XWRzbVa#_S1YHD0dUYZ9?G=`z`=> zYN@sy_U*!v9uN|ueWXVcvHg%J{1T1Fdgic;CVCV3;T2vE#-jXaBJD6FDxj1GO36e~ zf>4;lE-9gu@PYClLP4~jl_!AmIB{@?{kSB{%H&B>N3^g04Aje$I(OLR3sWKE$ zt3tg>qNq#&%wbna%pLlhHtAUoyRt-NxRh!t2z7u^D^a)-MNOh$4!c&Oxyj;!Iv+DN zB_5+f>r!eE?Wd*@xL!yU^%F%s;^Geb1qr9Vg<4MnV};Y0_z>;$H3MJMMByel=CGSe zY;K9jNY%@Pf@mKl3MdhYB8*U&!;X+p!hE1a6AGezlomjFg*ceQennC>YPY3|+Urn@ zBQ@r*WKE$)1aP`D3TLJA~A4>ox-OL zIP7G+a!8vms}6(e&_pqqgt@~WYRy@LB?j;u(>*SZ?hgqC z(LTz@K>3I`xWoPk9dcT$5l@GGMpwttJ(AQB?W=#9=xYxt`>AJwZinGSogNHRiBC_n|gLMQu9NrY4FnNsv42sa7?8DQUB6`kK;=Xg|$! zfifpi%pw%-u;&2an3ihGVb3ZYX&xaV+DBRfr0){NB0^#g`#Xtfkwj!H%1a3a(LTy5 zpyVZr6@XTh=V)qb&@PAlZ~W~XkUE`)PE#(?y!F>TzxC4 zBidKr4fUOg;wJ)N4tpmiz4O|nXF2SjBqGD5{H%g-00_S&ieD4OUZP+Q`!{RQ{t9(I zX7)-vMui@v)F9eV%}H<_PZWP7iX+6u9rkev=MM|@hy=z8=M?cF+UL6nzVnIVEWt5{ zeO_WaD-ju~xUzbp>`at=cP!R2-+y%;Q;$RN@wxnv*?mZQ? zhfsS!YRq9jfLcM8$&qC2P9WNEqkj^9h&9RBCE*UcNRqcK>Mq|tJVNS-_SOFb^-@XV zu_RHP7`VeOmBgkEIPAyp%4KaLu^e{s!a2(jC!&4M3gCP?NjyoA++jZrBxdOHo&*v% zKL9?hJ8T@?&kz!#9i&dW!+rrs^@)c$?D`PDrr7~6hux4=5$&tGp&Fbd8j~=0*uhEW z21a9v0X%={9v4S<6GB0>kJ20{&4`0L>}KeYJ6er+I_$f;I*#s8Qb)9}9+~9JVdo1) zkr1MNp;yq%7-}YS*fGfQU9F$J9QLa!YH?6&NovetxAdX*nu=OGsKqCV)+ERscDz+h zttD+%P3kl4Mz#WRp6gef77Y zK9JP8!yZ_;`a7hKXkUE@)CVPr_X&VG>_M3H9%z%E<*?tEhzyr9R0Uxq5Jn`4;Ys2{ zqF@etgf(b~L!FPA4<#O>LPt?*5bdXC0=UK}iLpuIQ{v(dd%T1*)C85mlf$|NZAlgS+2$cE6 z!5sE{N!6&`MJj4bp!OZ9F^Byf)C#gpOR0^B_S^V9RF{(~ci77%S=3#=eaItqMEmL+ zp}syztW6TDiGe%p^?cfZ!(NM52G#I%*sBZY{DC+T?Q`w`=k_GAl_0sp-tKMa^0rF# z0pL5j!^Y9QlaLVYAobE6_IV(kB_8Im&q91CGUV;BFOVvtebsAFy^VKubh>4&5HI-wxiN4W)*zlno8?7z_=FYTMqm2!jYaPBt-j2&jG1Y zvZzQ%%wboOh$>1%#-dz>P!R2-IDt|lSyUqw=CEr>DAjzRxCjN&K1yAn)Fuw@uxm@Q ztV{%{BidJQ0QDeJ=MFolaP=2R9nrqJ8|uNyqA>w5haH@pJ9MHp=~)iDu|#CJlqM<& z5kLq_7R{4IGooM)JIori&7sc6Of!kcsL)7C4Wj+jv;tR)WbsO}h#@ZSuv9*(S1UR~9 z5CNhZ!JK4Yd)oP8-;fxhn%Dv~cOEsDx$b$$_Z+R?y#NCyR^8;yjTsXMWil&=*0#$I^L;$*9_Elp;j66x{{e?PPH?S==Bt?#^#Z zNH;Cq8xkBVq|0ZbLf5@y;Js3qB2tE-_h8NKvcsi37irgMX`>? zW(;%bB_y0;c!e)Z22Lr$K~%$e95`i&g*o*ylCn|Hoc_&}2J&7Tzi6x=A3DjKX+!K)RRa(D$Irn5$ z#WX0UkRo&LDLxcCsVa7bVn#>NnMApB&#)@2v!u@|tQ(~qQ7z@Yfzz|2=uSA?x%ULb zQZ4P4bMIa_Rv*GbRKt1;SlJy#Kf+?pJzJvcCs7$I=s?0jRKv*u&U+ojJA}iW`+E}3 zJ3ep*5e}jn&M@E%B^K`7hf30{Y(69cL^XnsLGTd~aOeI};RGXz08x!#90^teUZesK%z2IwwQ1b z)o}8Fv!bI|MmWs5uaIz-`M_C8IEZRE>wvR{SeSEPBPkp8yk1pt6BIX+B6IE=p;(ah z`jOg-sMgkPP~Jky+_`U&q*06c_G3E{AgU4U1;L(Wl%ba_8 zE`mDm7lyXG1lndb0 zNfEUOhdcK=fY_p?-E!`=3dee$un^U-8Uw3gifBMs%(*v|s2WIA#)AGL;UKEvGy_i4 z6yYWu=G>b~IBp*}FB1-;8cqao!ia@C_b^GCl}#iOAgU3(0)iMK;Lbg!aDrEf08x#g zH3(iy5v>SN{onVjJ?6wGevYKK<3^er-&@VVa~n3gp=h1=PklPRKs}}IBydRbM9|T%0@lEr>Zy@iaDgn zoO=!w3$k8AsI7=Zd2?WZW`{&-~FmHlXFM!^wJ9ix2QwR(3-(syw ziSrB5Kaai}NIQv#x%Qn9KdRXXFW3GvsUq4}-4E4$DdHCr=8k=zHJ|+=F@Wco?w4_N z|3)Z?_E8Q4Ea$2hsPq%(XSI5zPgwzr3s~`92)boW-kPxDMq0?yQDQYHj z>8Ft6Gg?1;x%4wCY8Rk(j?|b#Kj%a3qKeves9jAFmr0Pj^Q%@hU6!<2HT^|tMzo*i zyFj^}B5o22cjmVNa7;_J<;-suj&zTZ5bYxsO~o7Jsp26aF<0)F>P_@eA~F_h|5SQ| zJXHauBv4AEiejn8E&+4oB_xz$c!gJ{fl`W45bbB>aiEkT4(`UwNV2R<%8@#vef9EC ze~Q$(6Mw33^$MhpXkWbw)GMcoX9rqH)U!~91jY)dA@L#F z=W7Z+cd7^`IOe?F5?ioDWTfgPLP4~T5&@L3RMDJJnClLcP@4Ndi6j(6`zWsfC5AYd z{WQ-4%8XPoolv;Lo&kWrv{YLTdwStWvk3{&KGGr}El3sf2#GoD1rpIb ziO5)#zaPUTe_qfjS>EyCoi@LibZ@5bdYt4{#kx6^ByA0pj8g`-p^d$U;3Jfw96lMtq3& z`ObpxbgDQ-aLi$!me@{7L`JI45elMxl&e6woGLC73Uk<(C6tRkP_7XQqJ5N`K)FF2 z%wgYFKcj)4bEeI7<>IqJ7RM!C5X%lqE>+ zu*(678M?f(K;q^Hz;|?qjidW1LPE5I)I@jKE+Ew;9_FxXLVPGPhn;o zn)65Nw+7bhJhSk)6r%FwSyB?t++DB;!lm^7X9d-kB$j4fZcslHnx;l>T zMx>5tUp*wvm&48%a+46EeW7M(W>ab=bJ$IhFYTMoNb;Ye)=3DG`M z5|9$oM0-MF4m&|2YA+EPi*hodAlgUi43ti3B9%~>!|o)Zr20TfClo~cD49U%N*vr_ zca>yWnf#a35$&t@hI&s@=MKAP;p%-z9nrq}0I2s*6Ilen9Cm+9dZV>T&vMvV5|QCj z-cmsr1cdj~#Jg$YZK7Zf`+aNBz6*6eX5N-~j0zo0sX?@#ni1d{o+ds_6CV&4ci6)v zoDVJ34hjBHC}`e5lSPRqn9o zO0uZCeEYC~)Di8gFNgZlG_g2Md`k@6VK3#=1|0TcyfRLkNUS~VZwu#KL7a&8IoE@8 zZJJn3klbOf^)_^QtEKt?@W-0P(~j;9goOBSk&btc^9#})_CKAY#Qn|%e75_3=iDI^ zG&|t6hyAd#@koSdU-gl6{Cj)p!Y|zr<_^1Py6Ld}(!CkL^SSPEadbbLZlECAM=1%E z62!qBc8PTS9IRF&o(_ACu8yO-6saTHS1+6H%VFmWJx)T1_Jy88GoPSlGKc*Hay&=t zXD^5Sw2E3qs8t{}=CCXHPIWV$Q^bStC}iH+N_$YQJN9$r@0nTTT)o0>I~5sx60Ivv8!^goJ1xsR59J(#7+H#2j{zMD)BwWGu=r5DKDw6gNEaavU=F(lCcSyuq-QzoS0p0CrNpTqbO1uTbP=B}S`!6x*zK%A8xM6pW?D-;MujF& zY7p(G<_&PArHhnwkxX3NVW&wrDHdw71jY)dGw~tX=j#r>%yiL};F!bCl-RmTL`JH5 z5DKDwlq{gUnJ#)03Uk!oW++i=b=B%X>19+C|9v4S<9-$!GM_CJ$ z)x^Oa_G)y<8m&e=9rjvX9Y^;%Qb)9}{)114oiDVBgb?iuZACLTQ!|;v-i#ct)%w}X zVQ*7W+X=OwNR2t{pM0q8Qc>FnwO`W3&m_nl_Agd7{VZv-YWkJZjA%d2hkPavI47sm;SIqZ`X(Q%2$Sd>o_3Zi|KOF+4hF3u4O zbJ!Oolyg2%E)xo(eU!g|a*a5+!@efTvNE|r>WKE$??C+)sdI;Yt8n$Zq>gA`-7f?G zMnJlFKmg2PKg6WBL7Vg}hy6ezGF(cL3?b6g$1T({5*RC-r-={IKHqcT ztCS%s5*%~bl_a)`5|NRrDujY)AH@lj8X2M*p)iMCLqe(M1I0xsi1tzH0;M)_Fo#`R zQZ;HMq|tyh!SZ_SKt1y;+86 znjzf8z#Vq83^r}RVK>DqKWY<+<*?m_bA}QpqJ7R+z!{Svq6m^Z>=+<1LzfpN)dzsr z=nfl4_p5}2Xa_0hQ}cI}j04sfVqz|P3;?!jmcYwpk0)hBHRZ`r{yalWAaU-rKey(t z2@(gGw(DLONB0!MK~%$;2Ar>mg}d#q&^gDndhvAI$8`c6-P4HxQH@|$hOa&Ce6iUi zhNvbs56%6Cn#)}GH^}#Kt>3*|_k2~wZ=tx56q)m0=tJ>4RmBxhT$Ul0kSKTG%d84p zBI&aV`<_ycsFw0|z*&gY9O9xRD{Q6B~EuHzlMS7VdQkjup}!VnkG9 z^y`9$s|@jg0GUI7DDgdzsEm{q>0&(0AgbY%08X(k;*l=KQx`lnAKvhkC~*#&(1BrH33$OX+t zc)9k-Y-7|S+E;xQs; zr#ijd`ZTBZ>2e(1tw|lxzIwatC?ogM?*Y#jYEMFl_Jxwr%mivCbLk1l@ies3+odO~ zsHH(Ih18fsPw}DFNky$I)H1R~XAH;FWLcSfNa~38)jx*%N2Jc3_(z4Sk0f;$eFwfp*5k?6{QWBx zFIqF_TWrlc{)KS#GxWmtpQ@pIhQM$;ZMg2Ber)&szWTwC6 z80Lp_{Bce{KfiUpuG(&0wI$fmxp&V#o%&`ta{bM_S2XXwo6ggv_TfJqI?W!h`#x)) zf519rzpqn{S<*)U%y19+y5_8P&7Z-JKK=T7B%;rwVDdZZ>&k1^m6r>?@}jRR?^svf zEcnVBzOH;|U3uTvDUXDh9a|)XcdV7l(m2J)_G2NAE`2jHy7ceW*`tpdBIka7#eH2~ z-coonM5>E&Aq8f!tgo9@wQlxY!B;jkPfAl$U*-(!x3=wvb+n4#A-7GtjF?qxBw*^mXfY)~(xUmlrf< z{rq0{y4otIOzY|{UZ=D)2X7zil%8^TcK3BvwslojL0GNKyT486=~GD#{=?{xcfIZ# zXP*Cob;@90r+jQl4+k)tN;%{c3tPrYj>LeKvvzOMYjx^hy%S5EYG=ao z)z_8ttSjgEI^{d-l!d-d$-^l|wwD)Jl&|RxU+U}fA1sCSa$T$~xJ9dd-E60Iv+V_6 zxmDKK?CWOxt()yF_-1>2U3t{H@=(E79`JSLDO_nJ^SG~5&RI7U%cYY!CTonrJ`F} zeJc36s=9SmfV+ShF2THeAf2aAB?A9p^ha&4`zD&_H?U5r=j)UZOS&uFKll{EErFdhY)|GJuU)j>vl^v`r+xj{s#X2R)*C}0aijnQk z?t)xNl3sY7d|lqhQs^ny#s4AhJ)oPow(nsHNJs)a5)u*~gvT^#1k!*Y6k8An+tdU? zLJ5R8m|`3JFqmLNNH<`N>82Y@F}-)NvFW|{-h1!8l#JV#C}JyU#*$l%rW9vKogN#D) z;RXnfwKRmJ(je0iGWjj7mM#xE)2<{;Y0(KZ=>;e~mo{eY_SptDj?BK*wTURPx_&AN z*9Pxkgbb)|no9c7SR;@%w7SJq(ppm=LvYGeG67zw?U82CZKL6*AS9gznT?@mfMMNK zGL6PrjGP74EvJ%sH0BCqF1Kc8(3l&Lxz?Jwn#SCQ%*`~&9)#?qL5=`K&Gy0SR#Qn^ zrQ_|V(a&Lo)8>A0(z-^+X<|1}?5Z{MvN^^@n%F}WyJszShsJz~%xBijCp2ch8d@@Q zXpn*cQEw&`s6iQPg%R>T4e}{MKCVG;wU268O(pG=7A;DXW>C7cOgDbOk;kmvUdq76 zk@=q>t$L+`^wo>f2CoAlT##uhVQ4HjvRpwHwmNI-UV>Amk}B{*?c9|Ny0IGGhmdMC zNHB&D0>iqgqy~*sA31e`3{y!5C4;qS%*M!UWX)_yW41(Qb8BWZ8nZPrf2KjA5YmnY z=?oAx+Z}_fI%QX-;?XpE4~)>w+%Mv+YxE0EtQU&?W6k`_9ODm~*Z>quwiZjGF^3~F z#hN*o#vB7oHJPJmkO?TBW`N*Wn}U#Z8e|?qX1}G?X3B%kv@7YZwCHr2bS6qKrHxs; zeX)U!BlDABZ7TUF*w!wpbFRB?y_L8{f^8jimy_VKGVV(ORZU)rU|URwTsJC{H3*05 zWrA%Hxey~1?b0+}Ipm3YUV_4N(0G-QSHX%W(RcyKt3rc(i4Y$RQVSqzLV|;BvEAZx z)mNR4zA`YUXnFbunf0uhb!g1S$ZTZIY)E4^#|kwyK(P5*q4-ab&KO%#K61aEv)g~9 zk)n{)4oIhjhBPGmwMhNh4-AsD;T29^aVn6bFs?H z7owlT(Pt6leL#a0Lr75?Jr7bxz9bn1I!c^auYk^+Ea=#3|o_NzkU?nO_#LiC&d(^{&IAmm_(Y16--#yW+p z;~^HC{>z&Bd4f|G|10o9ZO@Aa-76aYCPJ>!AP+F~T`;WM^xvj&ULfabh+)%zR>|OF z8nZyCHUjLSmdqR)voJE>w`LX$)i((yp%^lY(jX-eQk({10HS8Qbg0#)|GHA~QZ#xw zj39=Z`h~-~Mm$ZdGKy8SW>zrAkZ59GqL|NGEP%$Wjm!{hW=$IN8(^x*tVe@e zD$E|ChE4wyxU7u(B%rFv>m90JFrI0UL8#t8RJYLNDB8(1-bmyP)AQ~ryc8O5Jo3g` z@lt8LDacEwL1rRk8V#}lAZkM9hFUIcvkgr9Mv#UrU?0ZM94j*lQZ= zePq2`%VLle)ztq*a7qXN7+$FD`C%>noc^JPFM*KaG)Nf?{W%!cEo>!e91%G}EyMEk zzLG(X#`GdnvSzwz%m8Fov1WcjV+J9!It@|_A;C0A1AwU6u3yV)Vf$FAcwHL(2aM3f z+%LYju2CbJSZfsf*_!#2ImVAPv1k;FvKEV=F@Hg3XKQ8*jrl7u)nvxgAb+CxZw3gC zwVnw1n+6$xkmR?tT9Q2IOn0+BQ(82UCOs0RhtbBY-JW7#}3W>Np0}1LC8vT zb7s?6n~=5M%9c}8-%fDKRI&$NsO_=Spet(lg9zD2gPg$7M~zd-VH)QGa?Tq2(C142 zPt%w;k$KIUd4hA8@*Y6cY`;_6YAPwGR6Kue{iKd9 zQ4Av#t!-Ljiqtkt$Z8e~(ZoJSv42}LKQqTDP7`yW7-ucU(3lc3%ULsBH0Bq;RFmnY zK>|>`iUERS?MsCCXpp)Hsr8mt3#n~2m6TUnv?fjZdzAiGrW^Oj@|d;T8yMKwAG#tt z)&QvpL}h&chLG;&=8UJY{z2BCR<>$r>WKuWgz5(`)b>a+=zgi;2P0$v4Kfl#4+F!x zT}cX!Gafl(jeY0~C4;Fn=5%CEv1U%9G3O(5jx}=@jky$=i)fH+gk;hn>j9!>dyQqM ztf^Fd6^*_VBWyGGi!IhQ+C&pOjA93@nfuH!_Rz%6px8-kvEwx66=YttW}c@pZvj(H z=5-q6K8oKlKya)*LC8ZI#9l{RBVNCy)m~aoCAE|meNK}ugwpTTv6xEaF>ANKTSvdN z;K=+BvP&5tb%CgiZwErSI;Pc!p|RY^a#`8>R#W#9oD!-EyinVtl0mnThW8<)8VwSR zp@YD%ZYrrk@Af@5t8LegoFc?g;PmR6f74?5EaoF9}HolcX^MCqlpF$-VU z8`wB9wx4AiY(pX23bx`ydXjcKo|UjQ%(g^~F_ z4N?ptMQMv*yMx|+DW zu}U=NSIDek&GgZjwSlQ7GlT~D8pZ1xAUM_ z+>gvXG{{ke9HK$a0z}RBDa%edNU8V<8vQy(xMJ=Xm#k}afhP74#qL=%@0erUqKUmi zvFFxePif3|>S?okzIuk)UF`<8divQN`(+_us>yth2Kf-hix?m{)`}yf7!6VeA)nW? zS^(5mD_PHKDjBM@XbGBhS(J9lbmLSak6F82Ft9NLlaW2q02u*9Wqi*<$n<)q)n_V= zwE$Ujt!$0e)Rz*R5-JN`sO^zq&`s0us}Zt-2HAw6*Mni*RI--F*@c|##y-?V$>3HR z^Dr_GSTpz0n5U6>!kT%E#=MBkb2P|xgj}IP?gK>4_8rSkIYFuTEgJnLMtElK7f-Bf z^oS<*ZhdVG=dW)V!)pHR^-X;*hbC4O#R^-CeNbONAz<(N44I!;GmFufrGcp?vm_0| zp?Dbs1jm|)5P=4%h>-I2t)>#S)jajBrjp4@izG6GY^|%9Hfa|M6q+$VrOW~o5;Lo z&AdWm-UlX`muZkEDE`m@!LjxdAJ4QO%&c zPQ!nNkQy{d9Sj``hILa(Fpcvqa=!V|FqLF08LUrZHb-VtYi45_GaQ*=*36bPW+XD( z(jXlX(t!qv1BjaKE|#5gqf+tCH2Pl{;dgVt=wV%>?liH!D3)l=>}8ITKod(ru|d{i z18B@tWRA3E4yQ3E08>q78Vxc9#nTNC9BVTXGK~gVjF1IyX|;KlQ^{7PMd#3@SE6(l zZOq#3nFcnF%>BsTV}R_?2JbP195y%SK^p4}vQAprI-sdvBsgU%xdt!P_PA`&J*eSt zBjg4R@(4rUH%=vYX`ENcd2Z}OyOjJtr7_=aiK|3Q!z83K?Jf1wI9BCf$Sh>de4obr z1eqVvASDs<84bb#M9p@YmR9TA5vAg#X><=pDBIGs#E8~4a?r%8qSzPK%!=k16=-5# zp;!%TF&~Xt7n!xJnISZ0Ltv`O{F(-7jN*+95FBgG5z>?fX@ihfZ)vr#mR7rx6H1G= zq)B%~=?*g8xGRyztlb`EU}JYqK=xk-$Y~%d(*jdY0O8+yl>6COJlwOrkc#BG>GjdZP9sUfZ$kr2O;@>(l0;=DTJfsG@xGO{ZgAoqZ%jPL3Q3HZsh`c$Q{ zf{_(uW$T%yUWee6P~X4{wLR(?bf0VZ?-0_E25F9=n}T88RMMEn2}e%YPlmn410{nk zY0M7DjI?I9qcOW6vy(NmBaPV|nQ=78p9uMl21x{nn(dyJo${4Z@qcLa!5CqHxnK0N zu2El_SSpH*v}O)B#~4Zzn}lK$ti{IBn6r>M-I_U-##{hQHJNj1kfkWT$N<5ymW7ZE z8e{`P*1o0HR$ERb_G0p6u#zUd3#GTy#;o1G)xgG)c>~#34Uhs5RvF*-5pu`eoVRGK zr^tF_W$P17{T0C}q4I@k?U7^9Ew14UBBVf=e%?mNzW}2CPk;)A8K#o=X`D}y^KqDA zDtTAQ|3@@t8DxHL%`8b{ipUhKnH-HNA+sC}@&!V?G)Q%TsJ%ZR%xZlrp;Wvojb0lg zgg}}N|5xUk)-?*Ei8Vs82G-24%`xiH#9E+OGi$LXG-hjL{%pJCbt=28fYFF~P(xP!R=|q(7DbtO+5_!zp?f)3qIP69vdxQZ} z28hb|o`8@vb90WNv8Ezxl9eq{Q=dg}N~rnpLT!&Z23?niUxJW@G)Ojv&NNOX%V?bS z$XR3TL#&d)RW#-fWNx))Zl*C0Aak!Zb2p8744H>%kTVE5NrPMgh??z-mYveARQx=R zeh(wuHusC0)-}3L6MKPTPpz4c%`qO*#0vbZttIxK4eNs1m^n0NVPw8<%`Et{e*MCJ zSqzwJGK7p5O}A!FHOH7t6I+a83#`TF(U{rD z%(P}MqcPV4Q%&Y78e|iSuQxz&tZhfg78>LrLiW9-)%I9UB_T?S?xIPbM(Go@F>ALU zGq7=F=5M7<;I>x!`L?z;ct1c$!B(cJbS8HSJ{Z)vqb@}M*Q8=Rk%79Bv7 z9*5FnXk*rHA8lac$lQzUT?R-iZSWpJ$U$>+?x(R%A?vu6ttd_XJi#eb$rX5^w#P+- zZhH-X6Cu}VkOvt0u5l{4P2;>k&QoI_YOUn|F^yRuT$_yT;f6^_W#-VBg^~HbHM3y2 zes;$s6hmfF8l(h5iqjwrK-6rP4!4?0{;O2H6pdaEBZ%RqCB|W0Bc3K!8O17EGb@;5 zNHno8QOsv87C>XxMrMdLvnGxC4KUSY)}ukbL-B?N2#&R82x&}%gd-&EEv?ov+-fT6 zth8tgnshWuN6B>K2ON3K!vBcNz{XDbC$fJtKz;$DGQN8wB*EOAf74j~kdo-k( zFu^IIhQkZBJyHz1ziaqZgp8y?CSvGuU|6>+8B62LK+aTSABs~lIGM&=h|GD`%sDjX za%3*EW-g&IS0i%;4YCm->u8Xj08z8O&9YPerBr+ijeZy-95DBbebzPFLlZlTVyCQ` zC(JR9(ZsHy*kx<6i!|mvWZt%B-lQ>~08>roLmK2Iia#?zaID!|YwOZ$8l(_H-fL~O z0I03@ZfmQlq^HuN1zPJ@D2!elrHjdQ<5VJ#S-bs10~<%C3)v0>BoTE~M{8zt8Z!c!ZLFE$H0FPi*`5aJf{;!$NDqLh+3sf9DN~e+$IuaZ zIbwuiDjB2X-$7%3flRM8vpkJi9hm{v%&IhIFfxN^kh%z|MT0Z~h??yN5mxKl9Hru4 z)9629gdfcPqN#O_8q>tup;&8cW-D`yFq&8libY$CwWl%Tk@<@?GnU5u9hhn|f2BeG zLGeEg5FBfX2xft0C43Ndz z;LSovhPgSH(pYPdwbIJgDouSO!6{S8Hh7`7$7X}>Y7M^|AvZF7p$4*Xw2KlykX6}Mq@ri<~qhJFd?g1d?!-B@?f)mieevIGe0uNC`uD6gJPdsiZqCs()?{Q&w6b+pQ=dU_N~pQ;LT!&(2HkTSei1_E z(;&++^fEB4+m$S#an>Sdm9YacdCc1FWesf1K<(~Y)kSYbYugdBg$6l@ zkbQ4ywLS8nGkw5uDJ{B-CVd*EPte9J{I0~n#*x|lS8Xb3`m3#7e2-jz^Y0yP^oAoQ z3^1|XI>TQEl>d_6dp5g`x7%C(YKv$S-zFFHU&#>aLE`yo26Tbr0>kx|i7r#5l%kzK=T*ZM}PUq7rz)yiRwBV!`l#6^b1 zw*7Bdqb`x106gCSxg{?x8xLr8sOm$3jjCGt8$2qQx zOB@-FZH{A(9gauhF2`_jk7I(k&#^*0;20#{bc}J{aioc}oXec6o%@_8oe5%paj}?i z0&1F{kMCVLz3|<_2}~l>pBc;yXT~$>%oJuiGn1Lk%x4xdnM^jbl3CAeWVSI^m?z9D zrZ0FOzz$)Dv7^{jc08NTPGe`W8BmjKb_3L7H`L@1dxpKkK82dRWRtl!^|-^mgt|=U zv-q9-8UDUft8`%r)NHG;9cp(*xG(f^q(aTcLH*Qv?QraJ>~ZXK9Do|$blh>=cO*Ld zILA0=IcGcPI_EhTI2Sn=L+!Gh+0K>DRZz>d&h^es&aF_}!_H&QvPVF&P&eA z&TG!wkbz!eZ!rn-Fi0FC4i$%sqr^0Ef;d^6B2E>ji8I8R;w*8tI7gf-&J*X03&e$x zv8CcNF;iS2t`^sd>&1=YCUJ|nRoo`-5O;~Y#eL!-@rZa-JSH9&Pl~6-Gvamej(AtR zC*Btyh>ygl;&btZ_)>f==7>FAy4)c^#bB!+C?!k{g&!(4L#&yamo%;k*sb+u^(e&O70}3(mWlvCJNL zwwGDT>;v3>xN-ol9E2-};L2gRas;j%g)7J4%5k`I0(_l>c&Ff<)9}t2c;_sI$H)0_qx|t^?`@pl$-{7NBke>JFgp0_q;1?gQ!ppdJG15uhFe z>ItBp0_qu{o&)LyGn9D=$X9@T4agioCa{m0p6nB*7yFdy%|2ri+2>3j_63u~zJ$K~ zib-Z)GyT{crazki{kkVRkWF9)!7-Ta1--mCo5CitL)kvi-;>zkFm^|<$?QlN1Ebjf z>}X)50%Ht2h#kugX48N%4jAKsF##A8fsqc3Nx+y4j48mF3XEyMm=25??0jY>ux0^k zHn8RZYc8GC(O4l$L{17AR%2Guahz ztYkMZt3YuzD6Rp;wV=2T6xV~|26h3vkzL4cVi&QS*~RP@b_u%`6t{umc2L{_iaSAZ z7bxxq#XX?77Zmrgy_x-R9AHfciyHzXa-+LH!D-Uj_AR?0)t-dw{(G>Ni3C7O39_^*f+`7u4^8`h8G; z0O}7x{Sl}?2K6VP{uI=of%egt=)AIUx7M{y7N(cB|Gm3z#O;hykgxu<*@_lzIMJ?F=BFZc=EOMW7^mQ9Ca z68DOq%)REPa5?-`Ea^%SOay@VNDZ($~vD9qye2(!5)VGh?598ckR2FG(aUcm8^TOhpR77DMqMM4g@SV-U(3qAQI zLN9))&>N0KewomR&k&OMOrbBoTuA1#gnoRs(4Su+4B%G^1Nl|LAbzzlm|r6d;nxZ& z{5oMMzg`%|ZxDv_8-)@4CSfGMSs2A{5k~V{g;aiB7U=bF~7yVgx~63%5QTo{<`}xf5Ux*zv({8-*O-0Z@Z84ciboVyY7?x4c96Dp8GU^-+hLE;6BSgbf4oN zxzF>D-52;L?u-0W_a*+B`!fIBeTBd2y2`(BU*li8uk)|mH~81?n|zM@7N6j`&G+=& z;d^=R^1VIx_(Tuv7CaC5B+o;>ujdh;?0L-h^E~1Ed!F(GJkR)np6C1^&kKIA=OsVH z^NLULyyk~`a`<7M1Yx+Rr!d0POBm_tEsXLc3Zp%Jgj7$GFvimtj$~o1r=O7K=`W1) z3=qb91_~2AgM_KVU^s>d6Fn(Hx@V{`$umrt>=`ah@r)3rdPWMxv z^i=38Jrk0p=R!Z}h0tGmDGZQa2?M3q!XPO}7%U|?hDbdfDN--TP^q_Ln3U)kF7>Vs1~|q_108A7Ajddquw%S5#4$liaZHqkI?|v$E{u1a5GFY0NE01%rF6#( zVGkF3opj zNedj=(n7}yX^~^4wAisqTH;tOEp@DsmO0i+8IE;QCLGHh>!mEm1}WRIQCi{HB&~F8 zmR32oNUI%Nr8SOi(ptxMX`N$-wBE5(+ThqFZFKCGHaYf4n;myv6o8y4A z-EmOb;W#AibR3p;IgUuX9Y>`-j$_hZ$8l+& z9Ce(NjycXt$Kg2PxFDT$T$D~ZE=i{ym!&g~E7DoVRq34LnsnZAUAo}7AzgIblrA}L zNtYeBr7Mm*(pAS@=^A`mx$amg-f*mfPb{m&TaGp2ZO2;ij$@s8*Rfu_=hz_LcWe|N zI5vq79h=2RjxFM2$5!!)W1INYv0Z%T*dac5>=a)(c8MXVxn`1qmMJik>orm_H`Z-lbwgfe$FFef9Fwgfb*C*(0N=O0< zma?;*Tg%RIZYw+2xxMT>=Z>=Toh!;MaIP%3&^gh&$e9?t*x4s|iF0S!rOsVtmpONr z&2UcUGvQe7+*3BoxwmY#b6?pN&i!RqIuDdx^{DJ?&iTJ>xu7_N;T6_nb4sd)~QOxB$mR=PS=8=N9R*^9XyzIheWX9Ku|4rg*M9 zQAmAz?!D{G^4@c1d+$3}cpo@ddLKGhc^^4fdmlU3c%L}e zdY^))XW;2MczWU7=zZzj~ex^(KhhyglLQCEj9si#w!5ahJD`xZRs1 z?(p`7BUv25^bC_uv#!zNIaext790bg2FHr$U1{P4*El%Fi~GG3!~@=maHNaV_(@_aGg+MJnIaDK zOcigsr-}PL)5S5&3~{tDQ{2PO5{ELg#l_MbaWgYlyzZGN4wUALnVtpWJ$|8>AuSS* zdKZhwyi4F%Dy|lmiI4aU@whirJmFmqN0xX{$`((0SBR&)E8$orzJPlOFWEJ4tQBGZ zC#Es$#TA|n;y7lb2>U;{wpkp{Y!TPHw~A|+ZDO*t9XLD0SL{wWc8Qmm-QpV09&sYG z7q0IUU$gt+I3P}94vLeRLt=__Se(KffzP)`#qFMB;&%6O&^#fY_MQ~acu&D`TD--d z5swIG#iPPG@tAO4yyUtdUUpp+uedIWS6!FIYpyHeb=Ormu8Fr?*Tvhe8*tndr!u$1 zY0PbLI&%lS-i70yc-MVjeC2*1K6gJ9FMA(}SGzd0XyV9h7u6ay< z*L-Gx>y&$->#}E%Yqw{xYb-Ow^-xT4ZFUcJ9dZwIjTVNxCQ2h*OPP_b1o;24p&p6i%e!OdkFu`>|nCMzBq`Rg_lU#d*$*z0M6j!!1)wP(J z<~rt{?pngk0L_`8H_LTZn(aF8DQWvOp=k-5t!Pd8=6?C;h|FIK*mH8=PK~W*RAig@ z@?LL>&6c2EDId`_vR!=lNVt&$chmr5|66{ldz5b%9V0}wSFYuQbAJ1uGF10aFzsWM zYjAG?Fc)|o0A47V=+4UJ0t)6UBSghS_E4_N_tEm(4|X&LQ*`2fQ!sGP4lr?jl^3~A z3I^_$$&Z3?Gl|F_`!#2B1qC@oSgF623$?shc$C2UdB0!*lbR@1#&$QN0KkUB};vy znIc%kkp_@2w`gs%HK5^0BgnYt(A-nI$j{z9P>(c({7xja>Vy$*F!D1Q2Pu{0{u&(< z+11Cv?bGkN#KuEa5}9syO$hBb_C*EKdSHY%P`Z=^C!;=4se$A(q%RtyXa zjqTK_Tj%Kb-@<+f4Qm=38xt4Sun9b^Sh;+qYUL{hR;=g^Ya87;tX^zfe2ajp$}QJ+ zmC8rN#Bj`~;6jT3txIG?bc{`k`oG`4jaBc{hPCVZTbKCQu*mLR!a9X_il|h+olS~} zjk8HDqis@iTV*)4ut{+Lwrdx7r%`)2;LS#DE7_#l_25~|E<%l zGoaMxwdDKTQk~fUhj)}!hj5!2bR+&B>b|*Yt=y@W>c)Lhsan+lsNHuF(QVo{>=q9l z%bWXAF*MZnQJvB+idVK@3xzhQ1U>iTQVE&A*jVVtC4MLZ(^QFa@?=#a;T^kDx|Op> zz4o4Rt=OD^|8p(028-_8E~Z-q+-xTe7}q8$GA_PNyN=~M*gmvp4*6xcXW;UvbDzDM z`^d#sE>_F`2x=EmwX3526%+aR zudw#+{N39Z`tw@kfns0$?@1@)P;1@j&hQ;e=Qc6w_>75es|1?#!{!1-l3vW`mLBF@ z6TS{A@Kb=T(Ra1KZPKJccwEQuxJdYtN&bonR!JXBeSJ9ip2v2;7gE0wTxqXPhJ|d= z!Ae@fI()6^wW8aitZc{4x=f_UO>hrxB!+c!(QmLphw5Yg+te{ zX?p1Z>?Z?T>-0KD{u^zt**a`=T)1pIG6E}C0DvhnaFh-h*C9IUP5&qd zprMMdRW-F<0Bu;S5j1yroo3&{q=x41=`z_K%tgfh+BrNXwhaW$r?%sG&>N=cop{r| zYBz2iuJ)|(TER_&L2@s^;8Dm{)Cbwn0*5qc1RczrmO{37--u~o?5YD)tpek8)%+d4 zx74-aaK+VTb9e64g*3t^YFievW#vvqXrqSTkwg?nKtL|nq-MFs#itssYiLY|@P@S; zhDUVk)Co3x2_;B(>8A4<-5I`WjmL(o1{E4BH{4@g!sXuZCgIw6mb(avxrwtGfg@sRz=(66rBI=`OKda6XX7-AqOK7w99fI?2;8^b{b! zB;>(*a<{k+*rM`mISbeYPU`a6H8Q?ybR>Kj(q{irfSWDjn(DN=w~6WY1_YaR+Z@Hp z+K^lmJvcd|Iw@rP25YbM8*Ek_5XH>H*xZ2%Bz;<2zVI4(*zd#@Z1Pc6a5eiW}pfY9Da2={!XLX^; zy}&P5+(ZWEnmo1IM@$SLB*4!t23&K^7PJPe#L|kZm3gfH&K*T99Pr z&4&0UBr#VVwGG5nT_Z$vdo$zI0EyLdmGEwFUHnP zJ~s%K-}J2turA!0+JKQLM9T2%9((3 z18|VW$PVD_+fE!n>7Rq$0d>@NXsw0+4}{kT+e3mu>0ht|P~Cl`x@`ki^(vU(mcYuj z-3R$jliMBY5A8mXY4DBG-Ut1ScoZTYCK1Qwj(C_7@tD66&p^ae0n!N)^mna?335G8 zVGlcDim&ToXGzMT^e^RCz|N%r=>oCyk7h@d?OXyAcMC({!AjZ(Gg%kjZtE(s1*Lzs z?t-n`0n$xkYcQDv%F3>8n_S&Axl*Tvd&CZu{@Hm7b{+>v4~d=Ox$QhQ*?CB@^NiSm z(my+|!OlzKWsKHhZaFtEO`&z&CWknH(mw|U0_#Zm0@ayel+HoEK;ux=Id~^fovESp z&p}~u@Ij#T9x>5@4Bm=z7Cs0}PFyNaj?0wEaXypvp2?LuffVuA#;0K8lR&9hp!6Ye z(v5VE0NKeWf!dN$3>@gk(uXEbYOno_qzFp?QpA9_{{%{(2TCQ0x1Y48sxF)RkIB;K zXt$)voUR#J;t@*!JeCEIVxZ(81`~6SEYal8VREIWtQ@ferGIuRf}IM1l0@wE%WbEE z$&N&^Q;FDt(my-Zz)lt7Wk&AhsfsDG+MfgbjaUOB`bfmtr1r|z%Lfsywq9S7xu0}kp3N_7LJ+Qdg^%}1#0qrQGx zS;l15g)3X+iDs=b(X3^%YQNoU1L74*|GYK>uT27_?}^b#U{u};CVVX$Z34D*o5QT{ zP5lK-kCnHJ^4a$Tu?1zGY^7>D_YPnyig?oP+@rw2E_nxM*ttiO$WZzhITj*!3Y0pM z;QF0=C!E(hntXt#jmo|m&b}_h4wU}c=>~S^;BUl4h}ern)a~4RQ6l#7 zH{t+@*e_7(OM>cm?)|Wb^)jmt5lOKbwM9b>_F+CovC1Fa-ft>?C5sxlTCKgDR!n2 zJ5c&(XExZGNxbNH?lVoHb=_tTaR8-%4iaX{j+lc?3^QBbUXKRrpRi4zUXhn zs}S)riKyGTUxtWQTd!-Ru2A|{*IN+z28pcSx!*8_hQ9b_`*E8%fYLt)Pr$*WKaq{u$xG2t!=x_w0->Iq{g>TXOH&k1Kn2IQw|w080NH zh(6k${Y@|z2?nKq!8}mia-_PtJ$pIG^l`bx4SROU--s0 zs!ys+g6j9|Rk3eXHpPeUQQ&(YUm!^~l>Q~VCKw6wNi~QO{cb%7!uQtQXRkps6if_3 z>7SwcV5qK7s!a^(_UUy^erlWjz__&ez9x2{^v}-sV5gB!YDnzp_UVmGb{bObG$wYS z^v_Onu+xlq(eKlnnM12xr3Hx%rGK%1hS)!m*!ms%Pqf&rNNgzmiyaBE+xet6B)o2K z-VP?g6Aaw4fcxofOit8YOq9O{V!=QspVZMOMH3IYU3n)QvK_&Je#}IhJgHmEE+jcn z`j?#Fz}v4rshdxVBi{78@?TAsx}n`TvpKcf{7&3K>7Tn^;4Z-@{Y|Xt_TvdAXMdah zC+-lcKU;zWS^8o?CAF6$tF8V6gvZm9Vq>?lLB@I6EC{`_+V3HwI>htH{wW$ zIGjY(?Z<~hM5_(eC{kA_{j2L(h@46y>-XcSrqHm;zu8)(5eHEE=U^&0nCz3%ebNNt zL%$!NtW71b6HkZdC*^4c?w(J0yT56~AC&(2n-Bix`lQ*!oPG~J*SOisnr-SMuoXO} z?7`veTR?0<`M=t#1;2Y~rTpe4sd^nLvAV_nJF$9l?=u$r@4nU5oj;U$k2(mV4yZ2m zBZ2jM?*Y}dy>~ye2X*!uOiVzTcN4?G#8BcuzwaJeJvs5Lao>GT*>}U)H-bcmGVjq- ztJC(}Zvu@WfuPKLpz%=6G*V67emf1ad(L9NJ;9%7lOb9rt*@3UuMKbmHWP4?NdNrIuwdx95%i3QcAdBlW%kG%jw>-P)uXl51@Gf?K;Og5NV zUR}x{W_0`Ox|cpjk^*JklX4w=U9B!% zt}b09zV!R(t0p^_(dtFBF}0iAAkLu7yR!%2>|S;04zZ=%L*FyGx?}dD4BCgp3Y2-b z@&c?pt1dkuR&@L4XC^C8C{|t)D^TX$ioFKhu_Qipd*>WeRJGUUtKmnqcOhDV8tO(! zw{I>`!+IlBu!g!3f->)QECf;CCsFl#=J!ouVbA<#YfzX(hcfTci$nB}Ye*l}kctuy z`u+09HON!}`{j?|`316HF8X$FpAv6S=G|Kv@K(BpREikW@0Ck~8Qlggs}xw$Z)RYx zd{)^j!`a6WOHlr=mUe#$zY%|FBfk+Z9aKju6=bnrE)|sA`?AG;`9DEwH-XZ>$O1&> zf+U6n*YBCRAZ^dgn0!FLxvK14;p}q|J5c&(rySUE5ik1Pvnwb$@wRdId`EErXP=um zfYLt)6@q9x=r_T{0cU@1xay1(l5k`ZXeza2Xq`b(2u2GOrF$U+k>PC zO8-*S6TJNsB>fd6{Xx9x_u~JUEd7Oc|1g=;b);UzBb5Gm><=E3gQO&4P`4{jHu+03 zxl&U$fY^c3KRd&~PD+q8nAp+n%u`Hu22<<|Cw8Fp&rT}X8AZJ4cITr^k=6b@#@~qJ zAz~VdsN12ZK}4&q*91~mDE+JJWQd$jBI|eQ>88-o7vF3@rVs~E`sZLSIG7zI%?y&J z6Ce7W`fUBQ0{iuuaOJT)(cmvlroY|mJmM8f|GZ{^*QG(yVq#Rkb6;xQ9A+&x^%pRG zTiLn8*_TOdLHWPhT3Qo!?whoo`^Uj`q>qB7BEjnBeS1y#t^ZT_>H6RDPuD+!U!?bD zA@B?3*U>MStRiqFNxt%2x$<23myXG-{4X8h?E55G-PS|tpRJN$s|4}1tET#o4^w1I zC6q|eoxmjgdM26D8$Tc9ck3_x=kwZ9J z!UQ?8Paiprg?|$bZ~DF@k)iZ2awtR&4wk+m!EM3n*q9^-4~F1Z;bsJ!vc7`nQ(&O> zPGjY90!GyJrk1}3z6JyJf~7jdz&p7O)XQa{4#mJX{u=lm3^WRs8WIC9$n2nGpiwRZ z4Jig1`)l9_Fwm4lzn8o5n?l57Ip^x!gpJ>vG(MF6HU7^K`KMs%M-u!osrq!e@qdy# zS~EDZe$?B*DYBKn;Ugh@yI`p`34e}+pDl-P2MfbId106#_cu6awWipJ%A<`v+LF~B zY{UmkU5E|+k`)g=7Rx?x$?5`EmdRIgFIkz&d<|#cucUFH%v0l_t-rw5AH6ffwxeTSe-Oxy42ulA9jRixg#Eovr zN;Mf!m#j1r8A|^mPlU+hNo3uUHC`VXXRUM+8A|^mPlw1;gQdwNxNgas3cs!S!(iz?394VR z9zxUuWXZa3asX})C@Fxm?+Hl(l>VjQH5hssEIlWN^h?%DFtLd&SFLDWp{Aq~v2??%SvOb02+LHANJU=Rr6T_1A zZ+{Jx0RyE&q*BCyZpkX0%RniL0mfegPB0*ZNE|VsTe5^)1~`fV(O&~@Fi@66*DYCP zA!4q6kB#pkjSr=Njb8~Odqbr1B)D$L@`h-ivdZgi;F9%)zu|olJ|IM@Lc;5otbh>s z)xW$j;F48^Vx#*1ZsQC1`75vd{B;jl*hS*&{>Kr!AlhlUzZ?Gf*;H+cX*XO)!!&b}kW3Y2-bauTc@CqDFF;~$3>xGcB8&|Lq+ zh$~8TIQveK=uqZ8`neF=SNLxNohN~y%zL2AP|b^^n!2y=FG7y5$n9+SM`u_3iFN~` zT_e$SU)^7$M7!xvwEGb4ZisZ71k`_Re;0exZBuMrZ+bw|3}xQa{2Z)24UrxbEBdeO zpMrt2a;gU_H?-k??&G&xdO<8fnRiS1L+eQPP$`F4(tTZT4>dZGL-Bmx1V|L#0y0fbQ%0(xJ(T*X2nMzn(8;a-`l~X8f^G z7A%ONk|R{&i3{CV^J1vB1UMkNe$4PDKWeuqM^Xc2-c$1h_^KExRS1neP~9aLz(yJtsr_>sMIo4YC$~czkUzXPaE*{drP=-Tb@Yp z>-QFK_Zd!nLYa4;9l&Q)s1!j=>c4uA0!z9LT~>ste}Li3@)l1%`=W^@DDz^;rR=c( z21|d2NVn%-hXlyPssc$zko|u6$?`9^0nRMbr zck?IR6kJ_JrjV#m<~`~Rh&qi#)!q1+rjLrB{b!P>Q06`Ae26+XRGLi!>u&nYg}~ZP zpV{!dCkMUIaMNdjKf#wl@Fk(rA`)D8!)HmZ;EO21GyDm@5`t%kO3O)b-OZltT)~%9 zg0J!?_&Nx_hD6rg=vf2Na?Lx~*y~ASLz(x+-U?AShe{hsVBJlg&7s;&o{f47c#~(F zKcV+R=-r{x4iZ{-gJ(BP^oh{7-rV5XL9wt;XCc3RRX`b=-Co3Qw`T{~;yS_~rm)F> z{0jcE+I#T*e35+b=C^M|$hrVqbcFn8rvOs`F!6T#8X9XmvbF@+0=0(C7pQMoOl1*(sM-D?(1w4U;!PV>hMe2& z@6qU=VT4ZtP5q)+pk)?6q=~U8_8)8J=jIqCX=3G2Otcnr(3q8wS;3kq(U<|iRFheS z2Kf@jeFg}QwGf1SMT0azNd338THQbxbX|TUfBa1A%5{|%txc2u0i~PBbgMCIw|{S7 zV|R*1c9a3qP#e5m5YoxqoE>Sb?#PO>vh}T|{s+M+Q%M56P}}1#gKi@Y-v=SRXpn&z zx*r(UO(lJ4oDs+wYV1SuU!t+whtQbgkvZ0ynMz|$L*`^_W;%^I2bnWzkVOcYPlIFu zM9p@FWvBd3srXVFeFH{VYwj1Tt!uQBCbkR3wp%l|nqzFHi5*6<1J+{uXw1{dJYmf| zMq^$Crkc!iG{`j+zifcuSi6mo8#KsMggkmnt39xsO1@WG^d3z*pHEwUa%f}LZhvK9 zxH0cE>J(o6S z?e^IQHjd1`)wPKzvATXL3D*YiV1x{)ZkkH^(O4spHMF|LRMJ{gA471;R5AfxsO^zv z&~2mPrywMq2APeaXMkbdR5FdmS&WQ+-pTczXer_s-0gwy7Jania*$7y0WQ0%HT^RhX{MVi<{6uW0F zc8A7%iOgr#%qKKvz8YFGb7+u)08wuy6sSQNYlRW=J`M6ILO!lRZ?%tVSWPAElol;Y zlV(u5v`jaCz>&wS-CoMT#*z7-Agy|(g7npk(gv>sAzYAYDq(0WH?mwo7PdNT>Ry6V zrjjb~Lham@47#xz-iMHCG)ORp4g$lvsiX#tQy)2Xf(%nh2PK2GXw1gQY-G)BNMp7{ zW^-$1Ga9osGJmE)q7c%K2I&kCHQOD7tU6^^rQ*>vdJl}y&D<~ItZVcOO{^D+{bSAi z%N*kmn%DpoOSTqEqA`afGsT)Yn8q9fOf{LKXpjjgo@RjHSet^7bQ)wHLT10E)n>|r z&a^A(uC(ZMnsg>gFQtuHyM3{NjU)4uU~MY-DA?96s&lS8qrH{5MS^V|beEIhvNG;V z0aZ<2iC|kyhg^4TlQjs3>Scm$5xEc}6z$S9UOD86dR~IUbI^E|kXONqC((ET$g4tw ze2EYr4N?mrYC?j8ZL!_rbJbU!j=nN5r)YWl2ATD&nRRH)#>i}B&1^_xHpdDzH9)ZW zTA}z)kj@zRbIIg>J7>55NFzldsU47F+r-4=>QnQS_G?Y!{)(RBjlFTP!t7$~jmxwY z{*7V(FsNs0kUps1OW!+IDcT7%-XP@l*Yg%Aykr`0B=Uw?@lt5KG~}hyAn6DhPlL<= zh}s*cTK9~}2Id+qPxFyE$C^2d#$1NX#n#M)G-ftdDANGJ=39s2t0A5G-nf!R+J>af zKr-~k^-B9~pmDFEr_09PxK&}EH}=LIS_DTa`uG|0aJqV~p5LoDaUPYleXTAmnW zmbPY=qA^8e3f4@H#`Iu?${HY;mM>7;3+dGN#_}{$btDA<$xHvN}1_45R$EdE#Eh1#AM4Z2q}{7r;hqd^{E=(}K8 zx9Pu4*+zC; zW7ckuFtD*x{)6m4fvwx!KUA1KLJgb#CvaIA_enrilh->`zhFGmAcIi7f2eMu$x*bE zX}poh8>Z*oQ+O#f-gxAVwc@4HcvFyf+eR8`ACh(h$*`~$fEwHFJFK~dZ67Ef zDr~kwU5gjLeyd^6TO04!%u1$3cYX){1#+k_tXW)S*SN4AkzHeZgw=|S>lh!~ zCG3ajxNdD?nngxMOP$)p#Yc7xt6l3Gseb*i9#t!cHI9slY!eq57Tfl}VU4;(c8-gS zX%O8u*VFP{BHG&S-z#A&Sp5CI>;SeOJC(~|v)SeB5^e)~h~3HVWp}d^xu@()_Bor% zeRa2R0+Yz}XNEK5nRI3fGo6{q%x2~@3z45=aOF5$IRU;-LcCM(&S`k(47_s|-a7~Ho`?4?zPXYA|P|pGNf*H!Z1mr6~ zz6N9tAQRZfOi%U+(~Et|^k$ziiR^Qx5Bq{iVqZf0yke5s*GxY)hw0BIKwI@>2eJvw zAUFoIy`bfKvngyMJCyAMZJ5LkXZx}v*kpDjwCgCgKRX&2slXV+4r0f$gV{7-j047a zU`znUL|~)?V-heX17iv>rUGLcFs1`z20Ndb39MPbnhmTuz?uuJdBB>_j$#(DqnU+l zDzk_k!z^aUGD|>dDJU%ir3_HY1f}Jmlm$xJ>`ZnA94pxk%qmb^4T@_(aV;pW1I6{A zxPe{3Ze$m-o7hF{W_B^Vg_JdI1j>iuI0EWNLH!u09|!dlpnek6Pl5VrP(K6eXF>fOsGkS*3!r`x)GvYhWl+BY z>Q_Pi8oQsp&K_WIfci~PzXj^ILH!P>-v#x1pnf0JAAtHpP=5sKk3szjs6PeuXQ2KZ z)L(%5OHhBsCNZz!$bl#c+!eMbca`nMU1NK5*V#nw2HS@l#3XS?*uLCgCYc+;^y5;P z{@hSz05^;o$PH%(akrSk+z4g}HBVMcI!*pYx8#cgIrb1z^@ zc*%}|V=R}(q;cbzaol)jJhz6K0PjuYUa{$LOyVvvlevk^6u35(d(BRRV>&m9nZZqF zW^z-QS=>}+HaCr#!%b)Aax<8D+yQnzH%3Fl; z(Gi)y6tL&y*lhW2HKQWi#FzJaQ*5>b^-B4Ou95BHyGO!|3%{rYjQwxGw`i@r z$aPY5;(k-Ez|Rl>^PJE1w(?ZLM6^|&7gR8jvYhTAd-$M2rHWrvs>I-e@$!|9`Jfe;c3U_G@P4uID>OG zS>Mx>&-QWQf;RcRpWXRvu$xgHxf3p5kkjok=HY`6)kKh_D>%T+HsEU7KCGEL@iNW@ zsc^|Hkn4dsl6?8CYH)n#%msp{h$9Ukzgw-N-PV_eBaI;A;`-WbtB2|hq8@1o8Rscx zvsL`J+>PEmWE><^lKX3POk`Id2dn>gU1QsKZPSUV16Sf0SC4?IWy2aqx9b`k7aJAN zsQUn>Nqo16=-9AI-im=?p|PDhb?Y1*|6AA(pU zVQr&3ht-RXi*FH7RoOALt5iNBCWd1^1v66oZ(SlIqGN1Q)c<|=5vy)9!rFEHtxJ4t zSY-DuVV%M|cZ-QB-_9mQ#KzgAmeDq;xvessTG%Ame{}5v?=)%;2fW#+Z6%vjyB<7i zSj#5W{mmxTiH>j7_P=$ybq19ByjGj|Ht;<5|KW~^ScH8N2uJ)s6n?YoQnp%B-MB9* zRjV2R)%z|Yx=s6r-QuBZd2>H1hKAZcs#E$!@yhn)anK5tpznTMDk1Y1n*cqz#1BPa zqAF2No~}wHyaT@rhtjQ_J?gdhlxxN21pJ?Cp*2}_=XNpOB4D>jnlP?SRAgLyn|2+` zcd&hE&m8j0aL>TyQRhB;HTRK=tz4{@{}I$qqR4yCO)Kzah4}52nmnq1WAyfX#dd$` zcLmx;$12*lj(vOLv&u|^$)z^@VVkw;?_x`9`mG()p-o%|MZH4e`R?PxmIv2Zxa`32 z%t-TAw>FZAcN$OFZ`_}`OGMxxfb(VgK#LgzLy>IjXA zZmR^E^uy)?MUr03=awGkTob+yDt0r}?-aF(>s(P0FLAiy!ATABFBc!5NSnLkgG&HYxF?JMH(CHp<<`Tf|IeabbT@L}cmFBUuf%l|A+Yhjpt!=bsA zIG*MQdmK66`pJldTDx+#gsdrc;9Z(ljHtB z;?6zJrt1Iy=P+&|a!I*FBBfTO6o)2rpD9eaWyUa5X2e%68M=JBP55Z!Lvkt6MJkC9 ziAL@zl1m~L5+%2aNEcFmuf6wsuQ~6%_BxM8d;Rh2@%ij`j`d!z=UVH%)_$FRra7Sj zxb1|-gv-W-@JonA%}{6!?wCc-4Zzv7Y)mLru0!>3=)$>$p%Fv#?;c(tTed{YwN}f& zt(JSxvO5o2j$zh z9DMRvt|E@mq9in5Z#Ca(HSdS!aroJi@Z!R7T(35v%sWy#ckS9Sw{T!?VS)8=CH{jO zw2i=_e1xRRp$T}eoqNaaNnLNwmH$~rs3;Yk;-AW)XG{NDer_EqN^}4E<37mlX_afo z%*@-n-;rzG)$RWfAXJp@Hd+%&=-T=E+{8|IbnVt9qjMVcTjP0w-T%T&Ya#m%7}~#J z7}m4jkle!I`1{Uo?q*ehK0OZ=-RU;k5lPI*MAp5I@2VV{lP?F=B_%22j@*pSshQDi zUEI`rd)oA!6FQ~jrgZMsB@5lmcHssj*e4;7a@~1Ml0#VTifvAWSW3^_q=b$g6BCkd zhmJ(->gpWoYwx+-!U6XVW+QzC7772v9q1s}s$+Vt^L%Aw1Ur3?ZRcQ8wy{Mv>yDU*_+QVg;m290}7}c-=gYV59e)m216*#kgnKSUX zzZeT{lfw&halZ+0&PjfZefw z#Po1~7&1%_Y8v|Z+R}QHX%!9`HeB*FLYv*T&UcZhalV8>x9^~#x%6M#I1`Gi!e5B-wm?I~HgN!@zlZ=Q112NsmpEzXA? zDIIYTpuy8_gOwfJlL5OnITJ@fZff_=Noe9O-$_>7_hR|-hdekq_r4)_V`9oUJNG4! z{?8`eQ+nj2bm@{y#K{Tx0gh17XK03hP%mlrc)DfTFeBabs#*kPw{GLH~Sd zqF3NKxARR-=dyz#ZpodOi$}LudFy-L&3!T7Iau)QX@KR~+z~^xrBiPHh(Uw!Jgw+0_iujcZBKsb z%5-$O>ZH0{X(_mGySI&Kz z*6EUUhqY~_zqm*KmAuQ+O}=tyvQiaMd?jw@Rh(72`@VaJU=pxbi)J~06}N@egtbKS z4)P3^V7a{n6|CX8lk4nUIl2|DMpZ|{K3$>&LinA!^iB&tVDON9>mc{D&8uvwqqgDb zluULb&h347f@gXm@dW_!PuxAMir5$||GV1m_-$Do^60UCr2zh^9J<0mhyTk+&C0za zp-Vz1bpKzslz*_9@Mb9;cNxb9^>Vo$Qfo?Xk~MClby2sugs$o6`$0l~fuRo_GE`b( z%c8Bd$)6sEdX~GoQ%bk=%;e~EW}Pe3PTp}GyC93~L$}5KIO*^J3oBrqci=eZa8wQz z`tLG1mi2BIAIgKTdpGwOkEZ#^ZTJJdvB~J#wL9i5p>uL>S4?n%b-ZtI8=X?lZVCN~ z+vY^62XzLI4lZ^7^7?iuozpTpTh?Qw``R)4tpja?onGN&)&zI$+f!C>|tO}6|=d+|YL;_t1INcW&i={NA10 zFYSYoo><_q+TG6iPG@7~(EW7tNX|%ue}{s!JqP3)8TW0gtb~JZ@7XD~_v(?*vAea! z9(5Py183xS;GvcMo>85Gp-IjObHbghUrKjn-{Ckmt-FwXH~Ey`85dPbKe#}jc;8k; zxr#$hqqr~G9?r*4!{A|K^bS63FM1Wfs+3c3#8s^0-nFBYj=F#Oqdc218aihxhYr(C z46j+$h=1bxvogd%Z*M4huWgB0I%ZRC^xeb~>ql34ai(=kpqmo875QxN|Dtc$^k7cj zv43{Ez!zTGPaiY7(YtBzx~B9A#_P;suJaptoChmcg7}0@JS*RM8&>)}5&g)wFiVng zme@LE9PE0DKG=S7c|K%5IU_qI+54vQu_zZNr-W82ZWCK}JaUt3{uo$K+N^icZm^%W zC4-YrlggpX^4v2o+6F`$%~LMtcl5+^Kw;qsJh8;~#uMaW1Ma@hDQdd8#r?-;3MJAN zK>8I(ag$lA5rdrvHLm@)?n|d_@`kc5Y#SVPe*Wfi4b8USt;jPQ!~53Vu;-*Vu-}bF z)$;Fd`buZ|GZI>>ySbn(X2IRk!R_m|sb zjl7*lnWU)W?3~;1a{sD}lKtCly42@^L{z(foOW^LRKGo<@a}tcuKT=QT#NiSX;k;2 zTJ||sIW&g9A&(kV*l7}XobSUCgK`H9FBnwF9_fv|%JSW{ox7h^&{&BQw^omr-YEtZ z4DUaLZv4{oz3Vd*Q5>>L7Wj`Us%cqwR4wJbFsi8I+`s+A`%z2O#FTRz{ph@Lw4Rk> zF!bcRa%ft*d;U3(h@wxF@^0?SY9m?872HPu^Ul0%QqgU)jJB}zoDUe%ku>oyw5ZWm zayyyfg^3#N1#Y7cqTbTvrsGWwJ-MswHt0zf2oKFMWPJKOm>#>xr$O_ju`2!O$okbx z_@{EHll)6eUlf3RRQs3zv#O{8RdG=c+4Y1^2W`*c-jQEt2XFp}(zjmi0Wsb#(E5C< zM{!)}bRPFPD|UK#<9dxr=;#@{qkH^Lwy5rC_f`(ok|&4vjetC5s=MP_?yPoZQnwVJ zJ9r;9zUbRwO<+B1W3A1y?-=q?H7aJay9?iUdQa)xy%U~qbxX1Cma?42MSu7y$!fS{ zXXH^&&pu_7nr@Tac1hNAj?COHcUh0);o0qV|5+L;$27=ye4Cu}4L@uag7e3ZRO444 zy8kZ|7b=5~pDUKZXUi4Kyn{;^CdK~0)1+d>iWRE$Dk`#)|G)i{*{~??l18D-Mn(UG zGHVq5o~Rv z`(BSyv27%VXePD;!`)89W#8?w9rHcIT6fQPd+an-{0fS@NRfTN$1aWH*QSc!Lh+k6 zVh@S(@A&veR@fdzpH)oo1pj=z$q((F&r~-lu+KP$4#At}r=O zTZg6y(QJwuf$g%kqJCRZm)Q7sfLx{^)t9(+6*#txmlGqR8ROMpY}QsZB|!E)Ak7rM zrV5oaWz7i((G2H$;IwEf1mUpn0%@V(2n|jv!a+2{xfwXEiG_V1NNYvespmGPitV8o zAw~9`AQ33~S+84YtcYe~O@Q*Pq|Cn;{Y_JZRHTFTXrcp^sY}Ss%ifG2#9jsm3iaQCEe?Lf9U@>!8a;H)+fSzvI zMe7>rL0E`^u%@}ry+5$}5fgLn{Q$7Va&R8!K7f=F&6I~gc~Dz1ki@xjA0*GUfeHth z*4w@r*T_)9K{Ue|0h~f&;m*Afi?h|LnP}&}%_hJ#@&FMani2e`t zV7QObaG7&|4D-FsT6d3gFEUje4aJe9$ejB~jpBbz6~{qwY+LaZiE`&YR#wa(+G<>_vs4NG=<8! zp}#~ph-Nsi17}uSF_UnZbDyQ)%+%n#K{$wJICFtBhgi6CpQA{#vYAH&h-L)ufM5X; zaOb`tHo+nyKr|zG9|TL=iX{ZWocmH7j-OeFqjc^|6e`E*l$c_y1IC)RVpUtQf=HNi zUn4j4DiH9!v_fHWs`f*gB1E$(+6=Z$ZNI@lFD7L~Gv)eFt{V}TkT`el zbtCQrluJ~O;!&gUw7mg=AewV5g?ioG>hmw zd#Tt}B!*}vb}fe6oQBIhdvnb6ZfnIoo?VzKUJu0}W`M%vSj?d`If!PH^Dx*RjEE5tQAljul|QH;jgYv7Dx6a` z{~i!5K$5h-Nqw zfir-{@C_9z>tf}HuC{89t=Eo;P(a%slM`J}a8|!o^Pa|dS$EPXMxXYJXiy1_K zXh!fl2xdjZ%!qiIIJh65jYF_+-D2Y=gZ z_Dbd|H3BR6we7)ijVvTA#D9yGjGueyWB<&{n0BdRbUPpaJ-S`-sBeAz_fzd0=Z_d% zbv#tZwG(4Wn0xPW?Og9YR%LKbuL%T!7#w0UAf6=x?z^9DS3G*Z*LNSVeK)R=DWr}V zTzy(Qo#!qUdVz!xgA2WcVa}joGQT|ovwOhDZ@+A!HVbMqNsW2!nHsg%Ow`_j+MDgf z8zjhm_M5Vf-cYp3XV0YxMhrf|ivY2(otRG$++#0sH?ZlyW;vjKxAALl@IV4dJs$fo; z{77Vo!O4CF*~xa|1Yt1`eNv%1p|aSU_B5d&21oe|C}-Mp3sT3ma_2r=Ir*WTXb0R>v%R>ey{JYE+%MN`Pe%p(@D!zF1 zaj$zmVH4mQxrPW3%?Mh=>l}2cSW6N^G!wfK!)-;wWiGlE=KF+?i*9YI*cOU6lOl7{ zH)|9lrivY)7#}a%lPGu7@v_3&EBdU$5@^a1&89pZIH~a>nQ*wTP6fmfYue>cnk2`@ z${;L6Gpsv-l^HKO5f*dUnF>`Wh01X>T?hx!3?~aXcg2hDgu`6+T?$Tj4Nf-UAe!Oi z0;e~zaHri{k!EF+M+Asw1O*`IO9b3=_l-@^j|dRW2nK;*V7wSW5X^lK#Nl|#IvnLs znha2=95*xA6yrf)jEEP7@#20WVLp6>+|Y#};CtzQg~_SfhiHlr&8Fx{ussnk9*Y-` z5F7X6Pbf%_N!&*iI95m_i4oC^@o6v?$BQup$Xt1`!Z${ta;9t?;UJpfOajitcrk%+ zm@}WK;7riqOeP#eGn{F_d5&0^JAY15cIx>BQ^l8{ID-_KL!SXfKkM}}jTO;sth1mz zla#qjpQ%Wr7EA5NYeax(M({QW=EjRT@nSY{aHl?(A1mVglvPeTml`mMm841<=QB=ZY-4{Mfi#IQI|vbFZ(Cz|7uiH6|ao3UO8*Oa<)-NtZeb+)_>`U zYou0!W9t#ku<8Qq5@OoYVdcmQWkW?1Eu>3qC5QsDyLIj8?4x?7ikCyNVS;EtqMut6 zfgd_3nrx{ygzA*bp*N~ZNdtudG*j#;z%|mCrU21w3a$oFvjowUfWCBrp0|LS0iwtP zn$W1EX>6e81cYb?bUlDtBnUx3dl^uRC?F9Vs1*SrngQJmpw>k5QHPb*ZM1M56qbH4>^T>6TTb5THm`+EajQUV?aw0N5>SUKGGv8h{0+080R{I6=Ha0PL2vI11n$4ZwS*03`re zM(XUAwG4_;XOmp~<+S*SW{bZD%BvE@3KD0xtX1-swSr^FBXX^&{6@%soFG0Vd3MYC z7&nG>){Q~lvOd&ceDd!x-nHIkZFO&1M}ToCL3~FT{FZeH92+eTdCU3^uY78~5`D|s zVxQNzMvl_rApYCM;aDet^)oTCTh`B*h%MGu^t{XZ#Z>WkD4tFbr%06FvQ9&F2i>wx zDFmR|VNU_Bkw0h(5Y49G9{`<85N8R9-?GjD;v>3cosA82o`4X|fXXN06W2sh244_y zQPDlUR@HBx4` ztZH0Yo?10X8PQDn5-4AsC~A>7yJcMrarc&03;+I=wNE^^tV>M+8Umm}qNqmz?3UFa z3ZR|_pphxSl>lgxC>j$0yJaT6{#a#cu`W zmWkpz5@)xpmWl4Wtm`<2yk*^BDj$J-n?%u?B&O(K5k-?}l#TUKigM!SEHaRYw* z^$PpPU$+5a3+c089I*vz`>cBR{O4z%(cB~c+qo}Q-38U1iQ;n-<{#znOmsiW|6E}J z&wl&PfNSJSLO~3UvKJ`3iGzQPzZ)xX$XbDC?FXRG+7Cbv+v>PRz9DtQ;OYkwbsyoE z3VlaHh{1&pVVDPLnC#>GgP7yP);fFsqqD;%YCl5lD5kk zAKU*TtLeC+&8q2Fnr6h{(|i^venTLeT%qtdWzn3b1~K^5 z+yJiYlSGRoA&85AEPuU%(?X&O1&kHWjl_o-oUc9jB1xhR!Lg6zBMMs^g~*wzTL=X) zI7%{55|cy+LSY}rCn_i%G$<*Af*2g-HlU;v2m2^KT~T#v_jVJtOsI7tHTE%lC#d;Z zraNeih{4C$4XRy8m45`^MUh3_mD-2yq>dO|y${rLl0%F4<`O4jaL)eV?3X0+36g*G-VaF3(3RvX^#R~Rmc_HKkpYB+7zF7m+hIQr zq(_s)LxjX12t5j<)7C7>2SN|wl|QUkq8|vIv0W#wktYZVF*wqHfi#ME*u$Vvn2$3M z_dX07W1{vys6Cw|ib;?^2znZd=jlOEv7!!=^Y+kjjf|(EBL*M(6u?YM5)%oAKLnZt zfRpqPXku)bsRV-<9Ogy9OivQi2!=lZnjQr+EjG+c1cMkHW)@&(5(#_wGgA?F?jo;| zDq?WeH=+6lsj>$@Z*W!l-hU3MA_iAo0M)mX#9R_)4}IQ-u=~(wF8=+=#;8KiL!X5v z;_pHH-6XMy#MuL%cca7?X~dVBh_8V7@+9#-iL-}2%cI2K*NCq)5nl`O)uhZG^sI(j z)VU)UdmSw{V(`V@2-T01#Cj5D4|zULav$=n=Lqs4&nG6*pFw(SlK7OQ*#n-fIOs>C zwn`uHe5yg%{_hcfO3DmBWZ!=N0>T;6XAgMJKCN=he zr?y7z5)-w{pjJOw)FnawfTzB!rn-tYtEPrD&4|IL`AVQPNfwO>g+JhF0)VmBRLciE zjbkGW)(XlE8k9DK zf*2g-7NE2v4*r0rog&N1B%ag}gR3V&J%QBu1D=G~>dB;z7+n2!sAnXLGy-4`crtM4 zO|}j_`G6-)A#&a%cQirh4ur1B;?87|Nfhh>Pgl8V?}R$vGnopHQ=vU*Y7m1@O)j{4 zCyQRmB8#~A1D@UrPA`d?rGT-*$s<0*;C%hT*DqP*6C8WM(@$Z`SBRXc8bBzB!BK_+ zWpJ{%k5JeHp1}&reHxVe2?a4Y$^$?dP8{q3&u~T6soe)n)El6#IH~dnJdZ1~sJl}8@Fb}t23LO?>cz=oOtKhF4EzC4F+Vo&fM*O|dEPom zL^H9i817~oE_2+W&g z+e{UAKyf=MGUvTrqqx&laW@pdN*23Fl)LY*WQFZg^jU@Np(#f+oAU2~vp-qvBOLC) z_XFZZYucp)-xnL}d%{9A!}<|eN0Y^2!eTD`s6usEp>l5AKM@Y18P2c3Ihia@5Ds(V zCl#C%8l2OFgJ_0x1~`8Z3wPsxDAKHK&JqEl8NqoF{7nShk^dc=Ae7=fgg`VSsF0E> z%B6_1DbBM9=E}>Z6px;39gfnKmre0MKq{JITm+12DWYnMs7xfxnO930lQ6tH{$ElR z1bi=5R+yZstwB?SXf{Rlz;6mb>dFqht3!MRFMa#z$En|7 zs(3RLTazMl>#d>aXT93cSP{*}+8)XgQs$05qDZ3_OYO%kM1W{UkP3q26p@%BIuHkU z?aBODfoo61D+{cHM!NP6v02lI7150K4zPAk5giGXJNM4OV&<@ zhK9?W`xwmkN^9Lc&V8(@;&>>IBSq%i$7vKNm?}Qixxc1Ry{b?-H}u(r zgJ^~`A2{<;#9M^JoclZl=PeD+0>VKw!+94ti-?6g_eF{{E1M-mfM`Zg0)k~kz@7WD z*aXXo0MU$KEeKYph?NAvocn4Vj%%#LQ9AdP3YFt@)|p~_3XD%u#D)~{5s@(G{)ybs z8$iJK(nkuDQ?;9EiV)4F=nJszNDHEa1hOKngi!5V&TsHDlE=ct7f8|`!<^Z*T^+QfM`b0B9-Lx+TeF7 z!8jLPRy`E5eqmIpSW6N^G!wfK!)--+%(=J1d~dVX-Q(O_n<}=2;?1PUocqlh#fYh5 z2PopVh_xqC?%d;Lg|%1oS%oFglp~r=c{*_LKlhUr?%Y!WvC*1#>D-fJV`UH)q8Zkm zV9LY~>3?K;R+y~-t{M8h z8nswzKVBmOL^Fc7K`D*_>W}Q#0h-R!y!MX&$ zkcdFJb6?^$hb4=ZdI9uS+qvT!Sw>ihfv`$k=l%(>HV_kY?i&E`wPhtd&V3UpBbq6H z2IZ~zkqr{(&V8#q*ETC0VA^f_W?UoN2?x;(XBTjG5({_kJFz(Xt(u8;?gwlFTq9o+ z0iqef9<6gP728W+W&x2TT=zfa3S0$ejE48pT7Via$Z| z7`|tRM7eW6CM)cSqR%SqXPR|j% z>o5F=DTKwG`(Fyx8HLKZq5nfTh-NtD(o#j)G!aho`Naff)4Y=u#w)y99h~xM&I1=j zGn~r6sYEQ?xmQx8S=m$}0z@-{i$G9~2)J{v7Mq|35g?ioTnd6ZX`(hkFy~$;t$6f7 z>u{9Ly|zN-IGwtt7*_z}@-)#fO*9}9=G-q&b079J1OeYm4HPD)Oq$RXA(~B*0NXWb z;_5WfjM%tyzeYj2TH-cS;8-DDM~sMOj5mSt#x&820GV^YQQ>Q)P&rd}GvOeb;lu-{ zeVT|64s-796`Y6$=T^c&G{Z>-P9m`|=bor2JN2Ams+a-AG*V>FJq?O}*6TJJE27z0 zJ43l6DRbxEQISS1mfDX@B0w}F=m~-zX`)-2=t3Oax%c453Y>d4ymG`kXry!R5}P%P zSP{)w?*VIGn&?BI+_~ogi-`Z2M+hBhM2Kq8ZMMz?n`g+__K3;*7n* zmbf?&@5 z8yt?~t;10|_dN=g<8=0$VjKm=;WY6>n)sebm~%fYH}nr6;CtzNg~_SfV>CsGW>fSl z*iNR26KUdSV&l&Jq=Ixp;{L3_u|hgcjEH88=fHS2P5eoK%(ONfIz_xkDV zSb=k|i&vht4jSp)FNw|CkXRATSg!)>mFc1hfpX`5C9s$|ENP5cU&V2i2%`z;N5hcb1xNJLSl$!V((+P zOKG^wxi7_h&#>0r^US@(RB*cwHjRoF)~ z<%niez8N^1(#1x?;m&;%Abw%aePe8_Erf+=hV=!ocBG5#gvFfu4uxvFLgm~+cM%Sv z8O}Gr*^@55CLHG6_b51DYjE}v4x$;(_rN(oEZn&tP^4Me93%onGlHWaI7|fGxgU;A zaEu5L%?M6{;6%FknIM>RKY_#XW$SR1&i!YF%5gfUOfmif#+h{SN4ofpNSJd!BRBLP zAmDrHH-*Wm+H*8Th-On%E(4zwWr%QwI8SWcxtGoGB84;DJKT8%jule*4Ep#e!;tYp zFjmPB7i2hAnK}0=3f~2Ih2IC9DXT^}h-OoEF>q>Sh#G{$oO>+=r-lZn4&fl0;nW9C zU1DL*y{@9{)N=z<#mk}CkQAA7ZwN&{>(!XXifA_0E1}$kl(}gnub=Guq%EFSfS<=#B5{lT8j zA%YlO^)aYE(o;N4!rZYx($hW99#$B@^QP^Wag97qD2TyPMgiqX;^1!m$)5NcN~=zy z-TDGs9oNWcQb!D~UffgX)JuiNk`Q8Wq45~zI2tB%>EkfR3#@haxbz7oYLlQgk<^$& zpQurrY@+r8)SmAtrjj6c=g-S(nyP5CYMM^dj2L{HUj@o5J;h6e!kzgm0C>}yYWdSJ zFU3ZhMM#Ljk>&zvPERqLkeDlG;T)+W23Ieag?FV{BAg}869aeIWwY3^0hb-dEALqciFDcL zV{?|zqIaiR2AtKvSv5;k&T41#w?w~E){A`LWseI+G3bD(=eICz8Q18)>>ze z!;YA!#Y3$B&#Vw(Pq_@O4E!Oe40A}<@PL*K`7i| z-wuG~)>KP}oe>+UGa(@cN9qBjZdsxWAu)&DO(E){5IHyHy9fm_I7%O&i-Az{-n+wcK_Jw14$h*xcV@t56u#T z34l55p*Zx`TZf)>*n<@!$E6gSAUq0$|73}Wvcv;K!5sE~U_^Upzt^q`WQ_O zV(_UM1Fq3oVq}&mA};Q*M=LlZC2ElZ#tP>t;zJD1_YC;PXNhqH#~k)}g>9Td zLO~3U@;p$cW{Js!!W{Ng1!b}ZWg4L%21j`bC^LwIIqVsVs#Ci!o2bo#+DuYo4tpll z{4CRJG)BbWV|){;Z;&c?*l#GZsJl}8Fo)C;gR3us`ob(RKTFIb2JWyI@?!%Idp=&- zXdNWdVb6=rxtKT+gL8fW&XO##j3BwgF7X<=l4VMLSirW!#x=5nkPw3)b+sM#b|7sd z9_FyOLHtw84tN~)=cI}lT=grc?#dE7NtiqAUGmJ@sW5#$3O4w4XJaG@g@<{=s;bJ&M4$2+Zc_BiaL zCTc%J?MG5$4*N%q+Hn)L(@;B=C4M16?yyhEYWhXdX4Ui?O*3NfX+8&(vsvO#Lg5bk zEC9AxQ!O3#pRtktCM3k*NaeEe_#s<_vz@o~%wd0o87#${lt$MHY2eY9H<*b;RK6c~I|@EpoC&HZgFA z-G?6=aM(F`Wsh}`NQa#roAYksL=4XPf8gw&E&358ci8=b#0*_YKczkZyu)_bxJCvN z5@HafyKIO31dtvh9_FwggZMtn4tN}P5vd{uR~-Y@(b-}o33G=%TAo=W6$bF^w>>Vd zk*5d+F*wTqfbukPaEJXg7UYmsBhe1~u&s`3WIU-O23LPJTlWmRRA>?jAqE$E4#S*6 z!(=FfKnFeJAp&$lFSqqfa#K9f*YDJcn$vRR;46eQb>K~Chci11r zR^LeKh{4sjL48ZM_>=&c!`^~J@0fMyNr(NZLgcuV&rA@$2Ev!w;)`stgD9B8{!(t* zFQCr%%npUesnFdtHHg8d=6i4*$QIvbi*JaFJM04r&bJcv8wHFN&Ozcs49@ox_>N_Z zBLv4B_A!O+h(hE{)z5^27#!s^P)=owUkHUc>{ANLFB+8J2n8`X%2}ZNNgT{!|EZ`t zwfmQe+Igt`O=`?x{|z-i%M|M6Je@!cKE}9S_>Wk7IZsKr!!FayD~q}-wGZV;9Wl82 zg;1~3OI*-PR3rxOu&eZ9#|9ks1$gDSb&yDhT`@LiHR41J&UpzqFYYC35hQom7XyhI zx{_Kz;^qgyhir$9YvfWwLJWd*x9zZR0Mhlu!yNYY5IU{?;@}QD9t(2Ds*z}ieb!dTHIhK;h{4rU zdg&Z?sZc5jAqE$^4Z}>QVKRrEjyXPSt+U5r-)^Fo3AIk7#vFDhjoKY1YCWLVt(WLR zg4|(ulhxEk(Pq_j7fmx_@M-P?l$>57n^3sJ&H=!$)>KP}ogEt~myi&HBi#$6f?lF8 zAu)$tpb+&{h@6{pe?mbFjxq!&gL;X9gu)#5AO&Th24yIrAO=Sn0hB`G;10V`k!5A_ z0I4GeSAPWR50g4~*bm26f0Wb_gR75%`jfrH69m8<_LDgD{9C(rh#Z$P+5}-d z5XSWqV|$6Gh=MunadOj+g*x9ePboZ3g-)QUK@2`M&x31fFEP27c$T=h!=9?(OqQt6 zDqyT|rV$@vaK4$~d%2f*k>Hraepz9AQ6X}s>QzEP4307fD6@Ns*9nC=?AZ#+>l&1| z2n8`X$^xLgO&rW&zpbb`wY$(n?OmuXA~oi)7eUR>GA*GoA_gDh`%qmxUUSd@*v4R-5!(PLW4LIyoc;(3^(GGh>Y|amf6EQgFW^iumB{mWy zci5Y}hOT6zQXc?5V>@hIBU=awF$mIN+hHFA(h=fe4*LkiM`MP(4*N$^MGUTb5~?S9 ziJwWBJM0tk%=%ej0MD2v*6;MgHFAnj5QC%q0hHf}gFEcsupm>c8i{t;Q*CuzBY%=Q zVsQ0yT8CXK^fw711{VtFq>A%2Oy;o9V~(d<>+EsZWpWJE%0n$K$9coe9Cloezgh(o zwW?67oFgicAa~f6bKLi9l@x7OO&8`kPZ|(|PjhXc)XWhV5ej$MH32Zjnri8=FN%$H zF(DxaN4gA1^>ajBLShcPzCu)2A#!fY4G9G?ILehkX_6xv6AE+KO%#;I8kA;)f*2g- zTA(y14(_m363UEu4UBf1hCbJ*P#wyp}1GgUna1u-~EE>L>sh+c%k z9CmL7rI!XJk5CYUqZ9z8FL5x3-B(d{YPX+>+W$eVKdCW?-5+XxmT4f35i$4}hd^}@ zsd9%sNRdU|mD-1)q>dO|{b8s-m?K8yh(coE4*NlVY`|fUz$-6W2Z?-!T^O75Kg5X` zoO2X7pUe?Y5F~flPXdVwr$Y?@B41!d&FGRlu@Ht>jAtvUsrvTs; z%My5=V?R&Ih-S(!L3u`wc!9*Z)1D#Et``&zFuiJfU0fqC6Aq#o&TGJVl~}mjeie)J zrd2P|ZhMYRfNSJ+B0w}Fn3JP>rd=xb7KtI6iOt7w=h1MP>z;@Co@1@M$8|3-Ra^|k zcSw;r?{_qc@0u!>Kyg`)c#lN6`(7q1>^()FRoHTxazwK!UkjYoIbtQ@a0k8`5U*O( zE*<#F*jVcb3(*W~6Rr=2x$un&)yE2zbL0M$a1hOKJ_pWcIbti}Fem<*g0oeF zvx9ID&2YW~&Mso%ZhV&_&C2F$B0w}F*aw2WM8F;S-q-}+5&@za!66VF%n{!a1asvF zaX8Mi4oB(Azf-6jXLHyT;}>8Y&k;Z6h+{;;ocVFNp??Aa-%H07CZ}po(i9<@P0?Af z{h1?v&k?7Ijl1(d6{O!K?r8;%71CeCh-k)Gws)!s_ZH^~kU8{lZ|{_ySE!sRi|g$? zj6gKQsSKP-y+wuI&chhy(km%A74QnbEjc(<2nW#&=OW-#BNpb=t0~G(J=ZW*ycmkL zNRheqT2S<}UUg`!h-PE02jxpinLGAN6=~FBsr{%=1c+t?O+j!)Z*h5V(U3T}Yrmp5 zJ67P@FUKnjt%F9o_J*-puOwDPGu9Sh6}`nZ1j?Pe02VWcCD$nR0_Znw=Z=2 zgo9{?b0=^ziG@4&Of1fFt7f8|`v*1wu8}T8fM`b0!~Irm<(qd(#qJ_8L^H8o7;Y8~ zmpS(=%=ZV@x_g{^j;UfE6#I}ObMAdKig%kT-V4Qo-l8vwa_3$kE3B`g&nm1xO*x|3 zln(*Upx$C2;c(|Z2oOuGX_wA@U~H_RgoS8^^$@Tg=q-j57IW?oC{)80D(4RRFySDY z;S>Sq@!sN5!eP$+aRuj54bGEeG(4GRo3Aso%=+E%5geVO)*{u#*4kh^xk3`kuc}}qTJBa zLBRLYG=<5j+E-|b5Y47&4%lY*7O(dfvxtp5_t^^4>k@aC0>=vJEn-A8V_XErg}udm z0%Xp8p~5#`p>n2dG2tMZ;gkSpS#R+k;V|dEOu>0igR`7)5Y2E_17{_%Fz3EfQFiKi zjj7^#D6S(#=G@mo(a(B)L}NuX8|x=f-ayLSxo=RUQH!PaV-pb|ni1>(!S>!_TW_(2 zIJk4)&W{y1_icD(opsPi=e{L2>rP@tG-Le+tb2NkuL+bp_dQ;7Sn{<}FMwWdJ9k_o z`v?m$5Y{=@xtHmaDnfmnx4q1{hx!zc`pB{p9_L=RkMo`z(M-7#lq>WRSn z=Uz_X0MiEBH{%+)fN&7aaH;{PDzR|qUbPSYn^>!6qMiFrn*i5Hbs|7CBdFC!_sqRi ztTu@unu%SC;ntzyGUr|g^S#qrcaL+gYpQq|6zh{BbMEyuiVaN_n?mu5KH_o`<<9*I zSz(te`mDmPq$x)gvFfu zjS5vOh03|1-%L1&W;pS{Y2Qag2!}cM_6kl!gL5n4Ae!MM11FJKxN}cbq*>Xd5CNhY z!EGQ&Cj#!=(_<6dP6UW%1YJOIM<3CdAeeK%1Bc_6*5N3fduN5paXMX1F>-*B-ADB7 zBYF@CbMD!4L-zy$-%C9dCZ}q9(-a|^O;JCv<@XWy^bvW)#+`e%~Rl5A>B)i zh-QpKz&NOn7)XH3xerqK1}ap}lno^uL^GTRfit3yC?p)_+(#%lg&LfP2nW#&=P}?s zLM+U=KcXl*_58T0;z%eKks@>MMNss!UZZHNh-PDb3d;W_W$xVnt4O03OYKK75g?io zJPU$n`iSv;#5m&M&ixsFtiZXC$18iRgGM^{aj{t^5i6n@>kP2I&__H^pxn8?;5COO z&nxu;=pD9m$2IaIVIlrotPlERhTGadkG>5^TZo6b_AL%eY3qBoxHpD0_jjn>e^z-;D)1WYtNuTR&{8;~M#f)DeTL zAJ97WQlali2r;t*l$g>bmqUuM*5485Q8I?&BX`g zx#Bz_F;^bW^%9*|h@6{sTrPb;o@;J4&5Jpy1Zyg@F0If8ZQ zNf%yEA#z+xBNK$HfzT{hG|d%P5CwDK&2rs`Hcg?<_skUvk5d-SX=)IIPt6VBx;|I5 z$Q6RPxck0d!D%5;g#yM3=SJc~49?dce34wyhTxdGp*yJ~23PL`^_*Ohohy1019#au{MdlY&c-Xpt%F3m?4GeXbBPl% zIA?!w_RAId1j!wCKOiwfSCX&P2Y?UR4jb3V0760xf)ueG_9H-gn0T1Oei-5>Ej!?G z*pHGbVsO=wP%X+8kCQNW*hTWpdR$=u&#$(}#WgaDP!NNo6a!@pad3w{1`Be=s*z}i zeb!dTH8Pge5reCb&(%E(FBO_VLWseICSjNpX_(AmPsALbwbt3=uqT_SJrA|1q{bZf zRE^p+6SbG2_F}G>PJ-NFzbLC|x}wdh=@pu0#Ng9B8z`^midlrh9ro)0_|=+f>9A+T zMtYNw5Q8Hv1k(ImF^`a#!=A4Y%~Ob+oANt^f*2fS8BpHK74H%XbJ*`GDDP@e-X|2q z;3zAB@&R#hhy8&f%gSUGsUrqg{}AeHNu4|FwXxOLlR9E>^-rPxNv_yH0L)>3f(G-9dxJvcxRlK%2wwnUN3PhOE4C2@bJ#oNrri#8zGt>6JWhq~qNza)J~iKh>ziD$ zCs%w;T-;%Qqu}h3s9!5!tZ?=dA7XI6Bj7ufD-IGIbJ&Lzwu1_hGgU_k1u;0vFF-k- zD}Evr=CF?|C_iaXP7(@YaFpMHa+)}p!#=I3I<@g5`UOz0m?z5TiMTxH@d$U=74z7!0f${4uRPf_ z+F{4#d8dbQRwhow;GDI zKx#@n%wac$_-M?K*I{2ps))f=uY>Bfd7?Q9bBBFxp8Ei!xxxURF-`5?snRqQX+bE6 z!BK7mN-N^v4!ac=~vX8sfsqMrrT+n5ra>27ogmc zCpr@fci49TV2m}@(qVUwjntKp5Q8K20#a6WIPB zAB6gdJW)sh%wdnfp*PVw^rXWsREQjx@{kF_lR$VPPdt_<9w7?mu%D2d_A#jQJ@bgd z<5cKKni|C5Q!@@+WAnsQdE&ps#U1uo1?MS=`d3636!1;T6B7xJIqXRa z+eC%PnX0LTf*2g-MW9U26VnKVIqc~Q$}|niON4?L9Ay?zW)cT;*fSMXr*>a6QF{|= zZ;%>u*l$41&oa%SF(L*ZSCC3#|To_L2CxWit; zj}18N#du|kb&$ws*zd&VTt=LT!8zA}b5)*LL6F>GuksqYk`+pQ0Qi5F#j~!FwSJ7i)*BOzJr1o9HlZ)DiH^F*p>3}-@#fn678_(*y^}Os*pNjaP{i> zI)_~nri8=o5n_JPDqHsky-(%WxlwM zkeI`6sSsVK5IHyH8wdq4I7$R4ZSuuUgu)zl8wKSi4N5ygK@5)40Vwgr!5wzIBFoAo zfz%O$tEWOenbf(%PL8dfM(T*c)jLDIW4^eJ0GPw>h(m9lb?8ZleVan$xRgv2gq}d? zkuSRCi!MaL9Ci=6X}dw4@0l(Nk5i#pG&P99r{*4T<>iY$`67q7xWmp?y$%4V*?I*EM8e?9VF6WKNXvE0&yY+=X@TVQ}e}Sg5(Z+ zs@Kq!Ojhaxz;D_P8`sD*LP89Jq!VPxX?xn^J5w&bJ!naj#pXh>~Ywin5b=m+NY$(9QLOgwXG&0NBRLs-{*@1 zgv1>7_X^Pgg~+)nA0iaQ;3z)><;Q$+lu($%{!u|WszEtUD2TyPeg(=&;@}SZq$118 z0RJM2GVtDhxx#Ng`T0(?h6zWAE}n8QAgLvO8h=t+nDw?gE&lrjYd z2$g|QsX$aH5akM-r!352S1K5jFuXhdUs9pKyJyPb6@Fkj6363W#Fq{AnFnvbJ+D2wz>+DGgS=<1u;0vl|X4y zAQ}@2bJ$H3l*SsAW`u$m9OYV|G$#(`u$wEYPVEX4wdK&jSUm)5ShzK!ohaF$Qjtw~M_ITwZ>mZR1I})2S zfjAL^bKVBd^a7DeklbOX1Bn^Bl2oNW0KC$6*tkY+CnUrmNJY=OzoTRduqF``bJ>#s zu+g#v9+y3plo8F8XF&Od0`WYFbEo}+JiDG(IKZ^Y_PV%6UL+huGn`j}^9r$WxBUth zXTMc1(Qf;IO@M1;77-wt5zH>oJ<~1~dy~Wv&BW$mxNp&Lnd^QF^L@ZtcaQ6S+f?x# zC@vsH=DZhZ6c?E)E`#EG1>#*2=HARO+%R{~;_ zHSN-Ye-ImM4PhagVQmD~#|2_NVKEo}u|l<8p>l5ApAZhB8O~?G*;*hr6Ap9YTNRwm z8l3HfgJ_1c3phK8g}d>ciZm;mFNpxrj9@Pab`t@2nJwa21Xf{QE zg6;PLak@a9A~x>Me^-!BOWacm94n+V#E59d819ERR|Vp40%Q*Tyu$alLgh?ZnSRcj z8ALOjO2DbmPn7HDyvt%Py+S|l3YNnw{I=xaTtGO8W;oS=QouV0XT56ESP{*}dMT9akTQ4dbrfmTVyXS8O9Y5!1XqCI@_wRWKhc0VxNE<> zA3Ijy+8g4PBi2D9U3-JrtWAg&(Tr7q^_qU-Y69iX{Tg5~b69e?*T6rdX0n-gA2WhVZK4bWG?*;%<-!jrPrm;F;ROPYI8}AIrO<2wfQD$??P?S zFtLyXxjSDZt7)O4&8le$O*3NfY5o8xCBwurLgCK51OUgGGhY@PX$2u621i;Cq;+Ujvo;UVsMnrK-n}*Y$O!s$Tuk{8#O3f2n8`X%I84&j5xR(|4fl( zWwL|R5reCL1@&E|&Yk$K*y>-CI%073{ZQXGOzb59=EC>k(0ju=^rQ>ls}MP^<$wvo zF(4cnCJqe~2Z@3?@FQ~59)ddGGY1tOr$T?EsX+`rHK)OKYMA(Cm^e;c+>$#iWiHT)iRG8x)Fqh2m0T;4ZsCAv-qUvg_fMIo3fUUG}B1IU5lt zVsOr@!P%@(G$lyxu$uvi8M>0DN__x$re*Q0Yos|LA^uyWJ#{j}H8R5&bqyhQ4P7}4 zU^5-6%y7*c;Bdpv26zp9hii2!(=B|p^{+M3x`nzGoyR|!4U6I~X%xzARP;|M^MQ^k=wCEi?aSvU%wnnI0W*JKc|GU_dsRNn0keO2`W*3UrU9n4|#O7IIm)c_1 zzXlMipBb)aiPeYLI}lq?DBgCJ8bm2AvXm~fm8^dapwuEWe4VA#0!od#I5rtSGk@jc zLKyIQSe<2-#Pzm>^{=H8Wy34mGz^8qRm0)%@;0HufuZ8Ep|WumL*Y6@_uhwO4l35$tg!&E{H1zIa1)<_NxA(ek@7t)IEwvMW z2-!5-J^j{m+kY*a?9w&aFQvZ$FvH!W%Q+%*erOXKI(%5vL<}ttrttT=%#$+nxPRtP zy38{&^LPKu)4I&_GV`3SNx8P}!j@^v7gkPXRWxyC`+~Nie!~h1`i&UeH)@S;#GHr2 z6?N%#q(ZH>N?p`w>pP3pb)8)Lzy zPqr+l0W!Ovr%5Mw^A43w2C2(AP?z<9%qsN5>g@LZ2(`11k|O-US&zp&{bsuD|0|n} z)HV5^lpYIUc9cA&%b6l`p7qvHvOWLL=rUiDnbZ9cwOcFE3m_;-KCo{I@4t?#zp2cFhRCd3AF)Zv)w+ZbZ5JT%yamLS{9J_?&QAZtqu7JNqaR z_=B?^%{~2QyX{-aCM|SL+Dhr00L+e(8+ADeGABObxu2G`T}gXg=4~=F%|A0mm)S*T zX8LD#(q;CPnca0w`p71|bWQr9i8I@MBYv)=mtA;w>(Ylxg+Xdv4D=t-09|MQk)1v0 zpE*L+DAaW}N_JM{-`V53%yBZa*gtcOF7sJrI+Hm;*W@|b`D9NMxz}dMCew6H-jGdZ z#aOkO)}~WjNshguFYCHqD7$`Jw`arQxt?sfGoNbb9z>(t@uMWy-MkZIlX2~oqhzcu zYl_Tzww=#WlIQmR0=2V`l9%xZXFX?nCdm$O*rENtg{ zl+4#EGE2UFJENdB#8U4_#)N_U>e!*EOkt zCeFizxb~X8Rz)_cq-%1qY*Mqme$_5&?{}2+wO6#7uIom!>jqZ3_YIDZPWH6dIvpq20uPBGv10SGEe@H5fQ0t=5e?<4|IvXiFd%{2SF;(LcU1#HDXT|=V zjnQRJmYEa%GbiXWUqGfana}B(yevDP;b|iG+H11OOkI=tvdP>St2W2lbc!o^z+TbW zx~`YWu9xWcY&g8wlPz~*tip3K+WdAeO@ru%26>N2~?%uN5xPP)vyAWvArVKrAZyXM1>5}@%q`pWRa`%1rMb*@Nd;RisxerRF;ofRoY-bMjR^xl_ z6h1CxAMy0Q%x&^t+51Rd9V_j=i*$M8W!}>~Z=s!6tjn7!^CtP_P1NPhka^Q|O=ij_ zFX@`Ri6%}pzV2Tcvpkur-FaFdGw1ndzNO22Pi8Lm&wNLhxm*rtnWu?dzO}ORRhUj* zjVp9XpU9+-k>shyb@uvwsLMSnnGSiYaig92owpi4b*JzbDf_dh_bqOdKVvT!&WKtU> zd8%=by?(8Axt~dOW9;+qGI|#*JXVpvvw!?nEpd<@83~7`{sWbe{k0G zpr_x%Zu_5PlcTyOze?#}0L)DPab3<|GUv}kkLllU&*1O6%(x_X2ZWP+GtcWXtH{hs z{+Sh$_>#y;s39|}>6%<3o7C1dX@n-uY&S^qGyTWxf!EWeH{l9ak=>OZ0@be-KO zJGt)<&0^A~O^HGdt)qZ%3vxnd!PFcgW5=d78+*)?GH~qHB^X zo8-h;wd^E6(|_Dv(Vn`l2gt7bS?S*A2iBeqhx0wzvM8UB*^eTdx%<<0=0iyy)Bguv zw)g!Qq&kx~Dv94P&bUp+%if<(VmF%ecHhOiys0v863;tn=S|e*y(IId`{hm3<-I2J zX6l;EkxkyvHCc!z&V;<3&XmXL{qs`X1?p6xk#6}Qf4mq&wO8(xlRsfwWo<( zzE5Q5A7eWCjcvUyX}e6?iX_jCEe<0NhdT zR{3O~O;XM6{X%MI7kEwl!CBAh$^1;O?zX=~HmR*^(ojm*2Qa&_)z#%RlQ~V2J-4Sy z_6#=GWww-=!awsGU1l4Z+1fwz23=;n%xtG?k}R7f=$dpy6KA$FlKpOMHSK|?>C$^h zg|2E{-044}OkHPrva{a)nY~nvEL~>SJImK)-Y+u;`)A&#%X|=-&SVbPHF;Ea z{;;Qs+-pzDCXefyjFU}@W31X3Ytt!Dv+CF@I$GEDRN3_;-JT7HCwj8w&U{~HzvpRE z*WJ9UWs?=^axT|peI&Ei`C(n@_P&YQ*+f7_bPnY?V%slF!d03ZuT4tW~&pe^aJS#K*&@~CAxHo{mbxkUwi8I^f zQv8mR=JvqLrtm{uu0#!~P%TBd#Z*o49LUZrR@QY^Uv_q>e`Xz3qqeTIrn0lf{+%__ zWeSvUh?fw0*Z1RA*oWpflPsprC{jl1*y^p4Lw$xbs z!C8+no_=p}+fR^9#_5_&mC};{%v{MtUCv7~XS%nBZm?%?nl5v;%zVv1^Hp8u0+~6_ zKl3eJ<`S8?NY`Y!Y_d$(WF49~v%T84C_C5#U#UyqEEPUc>tcidh(6MFwo7)l!#{Jo zsnhUbvYR_CpFb`KTWr1 zFj<$`MP_FDXLizMX3NaG{4=}jGV^3+Z(WmqvPoZElfh`>%=W-kKUdPl9{2!V`a@D- zgjyGc{v*0y*V#zf*%SVmkEt4u=sFuGJ1h3@Y>X~*vdo<5pE*I7`2sSX$$U=NVF^srZSwyx`Cvg;+fJ&TX)J=t<+Zj#v>JWaCP z&AVMT*{Uw*W?j~oGHa(FR-W7YUTS9_B?s^aXFc|L`n}t2e@Hg@Uf1MjDSga)lpN9J z{3dfwd21-!p8sETng7Vlzx*@L=rYTvx%Zc{X`bWD(F~{Y8-SdIDl)T@u1O8qq?)ct zT{LlKyH1+lQIc;DytXdAiBz~eO}WK1^dC_JU1!(H&aUy#yjs<0rt9ox+1ZW$owd?s z-YPTO`)5XUnJLJ0CNojj%Ow< zJS*M%2FKd7;cy>Mwk*ntGJCwI$v`C9`}=v>WQw|+lXO`x$*k#qSYzGZXHh#_>P`H? zS&!E}{XXrse_J+rOV{LGDg6$BnJZbK%lSa&yzi}{LG}zT)n%@inQQ$sSL-r2%gj&w zGdJimKbM)?bWOgJO}@}I*^eg9Y=7fhl;iDz@6n|nlM08`y7<9=MBnQ=J1sjq>7RK* z)%aQ0+269Wv;Lj^smm;v?w;;t(mkiUQwE`Qe!9!Ltc*-&GArtuRF|Ds^)!)tt+s4Z zL)WCCY*Ihn?*`zkTHSQNqvTn8MK95HeYNcRN-N!alvsN<9B$&tmNPI*X20TTG6jkD z{(eg~nVqiOeO}jPEtFYr`(aIYdtXBBY^f6b!C8-`o_=Sz?N`YrALyEVB&F8@m>nf+ zbU9mO&L(dS4Yg-*qb_ro%-rFhxm}mJPiF4%&-_}Kc~E8^&^0+Gn;h0PIfW+9Y@hHg z%9rhd|ExG3(p23%Nne$}k z9RJMOy3BWF<~#nG3v`(!GIOb}$!ghTg|5j4G;wBoeNVrlTx1V?oi2U5RM@K4#b*Bz zZPInNM|Sp=f95V#W2dgOgR-*&{+)fR%lt`Z9`(;Wtjj!wOgfi!P5zLbpY}A7d+nTT zaz@vre3rXo%Vz0UEu7_dl)PuJ=y_e&)n(UJt#t2EV(r;*xN;UhC*;n&LS{GeG5Q(j*_Ojtd=rM_+hPadv8tcY^ezT;H<~Zo_^Q5?QfM$+UuI6O6ep3v!f(I zm(yA1+@9q*N|xI*n4!zOOJ;WS&+MYh%$1or{+Zdj%mSHtkFLo;*`&X&NgZNBeOve91AdAhDw$gWFtdo~N6xH7T z2BN6or()xZTxVuycOuyX0a23;Mv?&HRc=&7y&4TA0dgrplGsat0HJpXz4zV;z4uJ7s>E4ZAx6_=^m3P6WBZq^|~VC6`5< z2aIz!cn)ne@_$>zeDZ5{mH0Yn6Ec}0U-R2I>&pKyW^sGw(<0_ejQN5H@*0D@DuO70 znAv{gYrE^)ZlmL6M06ihc=Kz^B}TLFkw+Bl9Tw~@du9czMtM=N_gS#Y_QCuj<_C;f z)t(tAV%7xHOy<8tkk44~gdhl8YhNN3Wo` zrvmta4AM^o8NsB7!Z25r3>I-FFwWTEIds^_;AjzZCSy*sXHF3@7cgd?J#&tTxr{Lv ziy&(lWTgnQ1rRga8*L}$S)=3YMfAN)VYhW&?6mLEc2Th7EZ7ly<{_)b0a36EEZAB5 zV5ddQ8;p6?o_Sfsya%S4%-bS}>zlwu=RpvJt+gi@q{uh?1&BeOV~`Tx*j)h3QG4ba zyRGD+F``e2LjQw>enqDTZzcMg4GDQEh|N}JCC0801i1pDvA&}jB=Q@})#n`%E0(ch z>}=f$M6XV9hSW#+!5ohoL2>T}@SiY9O%dcvCjB`Kb6d%0B2E(HBz_ZATU;|T__c`H zh%r;_ne|1?=8W0Yp4nK${DCpkMUdYZ|1Eb@Ais)UKLPzVoXm8)6 zcA{XpELd-QW>2d|cTuomEZAWCU;{NJ)J&SRe|$k%e9-TC*V`Yl7HpWu9Z~(?O6>$QtYWDuZ0I4(A0C z>o#NEu(S12Ao>G}Go*?n2F4>lDDKMvd@%+IP2~4&2KgUA%r^llo*1;1JT2n9!ZU$+SZO^=E)wnJS7W!@AS`zYY&~?Ea%zP2E1Y_Mi2GZ+3xGLl^0#(dNqJ*L-w=h4 zV4;al58g`jH5(EV9>iuDsK(fFL6C|d8teOG2Kn$?%hl%t5$iL?O0cu#4@Ccx;tZ)o z{9um9e}dvh2k>bk_BHD1Yv7!9fPbEL3S|6*2j$6X4|bK z&KS{+qRh^NjWEcQ!j* ztw8jbDbCnRUc(ROc)S`E_wxY$4F-8#1o1LyHw<%Ii7eujW1R5sf-Ynq82Nuw#C(@A zE7>zEikR;+W@US(U&O4&m~kS=M+{O!1gQmxne9)$v%9{1X>|PGBKo&X;cM%>_{zRV zUx;^?HVoj;Gsqbc$^3BWLbyv4-u<9W3{!j^>ZM47m72adg2FjJh}zN{Uw0UWsu$?$Pgwy z5Qe#`q`!zWhH*v)&!Kc9gTqD4sf;Xb5T14N)6t-LE#a8=6Y!!-Ac(4|ZI{yuz3l?V0CA z%v)fZ$-FLt+-Je>1VPwZ3#k*hEuzeHe*$^v(+gO-A{3b)cg3s z9FNLDaXSa_RT(5!1o?IBsmZH)~6Tf|Ic%>URkzZ5Z(8MCfE zGfBk!FJm?oL7Fp2QxW7RK+J4s+D^)DM#s}d^j1vaPwTw+-M&Y^ih^}w!P?t1+gUZ* zh=TQI!Ft#S>n36jV$A;b%v=$31ej(rhl(I$S@2Oo5VqDPG01okWDbMOe9Wj#x7|v5 z86!GX6nZHOy-2iX@ltXSo2|_J`hjimetmwg>Kj_zhZr`KN zM8WE_V0G-7-&r*hMZub|V5#=O8j6@1jQPDiGfl+&1xz!UKZ+oKvf#f3LD*W$W{{R5 zNEZg__?S^^uP-{wy^<-$h_(}j&Sjx{i`HyNNY5ZPTba`tdrA;wdSLP9G01G|aLyF5 z7BkiYJ6j6_(N|EMv6ZaF59WBR3W~cZfZxO*>qU^AOnO`JRJNfNuWz&eJKD zOH8qppbgo~;u9(Sm4^-MD=gTH_RJTo8qbM>y}^RLZXfJ55mRGK)t;${m;_97>XsEj zDzf0^gCK0Jy~`k#M37hpiAk}$0GOjzImK=(S!s-@UljTy7P^K`5B>#5U$Y@0)q~h< z2zxVjk08hz5RLUckU{!chqJGUHJq`A*x5Q9h(3nm45^9u!5oiqL2-`+@Y5J%vIsJl zNzZ~|t}2-!;w)jDg~4-Zosq%$BIa7gTxHK(A!2T2%uV*p4I<`l#@r!-9AJ>WBFG6q z%xoXEos`Fojvp4$FENGl)_HN(zDK7;!S1kNH|?3%tr}NF!HP5pY;yVb!5)a1&oE}O z20?qFISrm@!0&}@UOo?|napQJke6BTl0gu*)?Q zK@hgqUSW_IMG%QW%A|`&t#rEGRuX26=s!fE%d*g#P7mHn^fen2;t68242)pxpd^So^rWd?vRkt>8|9u8FdRV|Ht^ilaa!J(^$aC z>8_^ia}}W}86U$rxSlaS&Clg3-s0t#&t9n6^1_O%Rr0#MU7_fIM>l%{ z-s1g{j^?UV+oq-ovsjFc9M)vA6(KKwB8 zr*|qPewNZCrEYpkVp_fbCMGmbX_lVeoUJh`6h>XlNiVlPYW~Gi@Zsmt=*RI%Xj5*T8=VY8=wqUrYp0Q^GYjs8?}?VO5LEYQLlQ} zshhmHo*|z8p4Hkw&rWTIXSQdpXOCyS=diZXlkeT^>7Z@(jMlb$?s(68`gt#T+G*pw zi@a;S7rZyUgS4zo=w(rN#?TU%OJqseQU|Gv)KeNH4V6YnqouLZcxkdURhlEslNLzJ zq!rRy>6CO!dH~<;;k>KdL+&Hz%7f&g@+f(nJR5zOCoe}2HlYtYdE%D@%HnM^G@(i@=o>6K%bU-S9w=^*Pw5kyj#87yxYCIy!+74OWw=gtLW_= z?>+AWZ@#yc)=ul7b=JCQUA1mn53Q%xOY5!m(fVq+T0gD7Hb5Js4bg^b!?n@cIBkM9 zNt>cg)uwARw3*s$ZLXH5Ezp)|%e3X%3T>sfT3f5F({^fmwSC%t?SOVrJFFekj%z2h zliF$RjCM}Dpk3CkYB#i-+AZz2c1OFb-P7)C5449`R#?lh)?wLUZNl1ywF}D$YaiAj ztYcWGur6WU!g_@D4Esmcp`tF=ER4ZyX%?c6fs`XZl-kSrQU^H;^S7nkNzRfw z3r0V=v)o_qA`bv#AQ*$d z7!1Y`FouFL4279!0?q&bK*7m@N1X`Vb*o{z@@dAYO@5f>riVnkemh)WT186qy1 zr^qYhsq#vBn!HM$F0Ynn$ZHUBEh4T%#Px`{0TDMM;wD7gjEGwhajV=~+J?t=d7-=m zk#{2UEgpF;H0 zh<--iCZCnJ%jXdNJfdGf^oxjo3DGYj`V~aKis;u6{W_xGK=hl4ehblWBl;agzl-Si z5dA))Kakr>5An!{N|tg;ZmFD>TPbJc*2-BqTRA7UQI5IWD#zXJloRe8<)pj4a?0I7 zIqmMKoN;$j&bm7*=iFVC^X{(71$Q^)qPx3t$=yS_?Cz;taraWLx_c|v+S(2vI!0-&j#aYNaY`F?ywX;kptMsbDmm&TrM)^?>7Y(gI;vBZPUMW(ZIvbBUN)L6e(o@Y-da3i2-s*g%kGeqVt1eV>)kR7_b+OW4U7`$7mns9* zWy&CRxiVN?p$t)1Dnr#($}n}cGF)AQm}?Pd9pbD_VK~%1HGuWt6%{8LjR`oPCJ1A8`&K&OyXEggA#0=ZG>!J&HKT5a&4J zoIsqDh;s^YP9x44WvqHu8K<68#;fO*3F-x9qIwbWE-91L%gSW+3ckOJ$2B~z<8cFz zn|R#9<2D|5@VJY|Jv{C!Q`85_RP~`UP0d%Pt6A>pYD@PFwUv9O+8U2+_bj!Id$!uv zJx6Wlo~!1#^VIh4d1?pue6^!{f!fKvQ0?qqq;_#HR=c{FsNLL4)$Z!Pj{~lpW$8;KGVH6e3pA%_-yz3@Hy@c;d9*^!}Hvm!sod+ zhtGF!318se8otoIEqsxCd-!7aj_@V!o#9K}yTX^bcZV-`{}sN%y(fI7dvEwE_rCDe z?)~9w+y}zfx(|l0a~}#{?>-#9!F?orqx)$1Cik)M&FniyYGdcao-O=>wXY^&iyd_ygNVq zf;-E1(cRK_$=%9#+1=WA#hvX#Rp7hkZtJ`5Zs)t<&hg!JxA)z0cktbIcl6zHckOfydb&#)#h#-^-zcVda5IQz0{Gu-s&h{ zA9b{^uR6w;tB&>cQ^)!GtK)qG)CsO|ilb&_weI@vcwo#Gp+PW25_r}>7f(|se< z8NQL~Oy4MVmT$B=+c!p?;~T5a^^H^WeB;%5z6t7l-$ZqRZ<4yuH(6ceo1!lEO;wlp zrm0JP)753Z8R~N1Om&5Cmb%h6TV3UwqptSNRoD3P)V02O>N?+ib-izay1}071l@~u{P`_`y``PQm?eCyP`zV+%p z-v)KRZzCR?)C0cF>OtQY^^k9?df2y3J>uK09`)@|kNI}0$9=oh6TaQ*N#9@UDc>IT zv~RC^#)WrM^Bqvn`wprXe23JFzQgJz-x2k)@2GmkcTBzNJFZ^yolvj)PO3M2 zr_`Ii)9NkX8TGdBta`_HPQB|puio=rQ1AOLstt6}hgq zCO6bLAZPb+Bgw z8RD5phI+=R!|)jHnM6i-CXsdzfJj=;E&k8c% zvyv?EtRf3NtH~nI8nW24mMrnCBTGH&$uiFdvfQ(gtnh3iD?OXZD$f?O+Ow6c@oXb& zJ=@7T&knNQvy*J_>>?XIyU8ZcUu3gq582|`OSXFUk!_y+WV`18+2J`zc6ttxU7o{a zHy(d^j*vZ`qhv20`#i_Ue$R1oz;l8e^qeGzJg3NE&uMbRbA}xCoF&IR=g4u-d2+&Y zft>VQB&R%=$Z5}Ia>g@XJL_4Xo%1Zz&U+SV7d(r#i=HLgCC^grvS*og#j{+y>RF*( z^Q_dadsb;T@Vm`T&l>HPXRUVIvrfC?S+CvoY|!p`Hfr}hE8Pz~tK1Jgo3wn-W-ZIR zMQiEZsoA;pB-Fryu;XSPN^d8ZAd5>zny~ngZ-s4(d?+Go}ds6G?J*D;c&Q}KD zG0=Nj8{|Es4fdYZhIr3uL%rv@@G}veUgiB4&7dM$Gi~ikRh{ zUv{>4LD@Opg=Ob@7nRNPE-pLI+dE>uw@<_ZZ{LW8-rR^q-hL5_@mS(r8nM*7EMl2= zdBk#WR^$rriinlo&eAIHd9vDjnXK{N@U8Vuk67oO5wYGoGh%~x=bIb7vm!QmXGd)I zu2Q$)vDN#)x6QknZ1?V#cX+!&X@Gx`?aZ^%2+bxbE#G-SGC7ZhALF-12UWxb58( zamTwk;w~Qdyc2!*y?vwy-p%BpcS}URcWXqJwl$)q)>mq!9S&=)9SO_E?`UoCTUuM~ zXjnV#SXd4o?X_(Y9klHc9r5U-<)OL_j+Wv^q+JT5Mc#PHV;WzsG@_0NZXam%V+5l;iHs3c{8z@cDhNx39DQZnXqlz*|6<+?9eWR?bI%Y?ZRWXHd6Xa8zt@0MoW9)bsrx4waeiLvXw)RU1IAX_KVu+GOd5b|CzwcG7oC+vK~g^_T8w*YP{_ zs_=W-&hYyfrw7^)@=%*8#$a8c33Z8o3J~+wqfhlc46Dq zoUmnT`>+wDL)d1uW7rj`Q`kJxIc&PrC2UW4*RUBq+kopAh3NNH zLjKUd<-W?*Pi>+$XlR@(f+H|Gl>0I;4VxI}@cTb7VQvn99}G-tGvjoqfq6F=Vq#K$ zGS2IFvxfTxRTrcHstH1$cHmZ zjM_7y=EMQJW-H!W%d`P5*NY{Jx%B6X_IJ5(bI|xIm~j1so^D@o51)D7Oax83j{6Om z@jGBmf`3C=%>G`<8pm0!qGv{ad$D? zBb)2rJ^Ett=s@Vtq+nDB_j-iUzteF@DbeR^YLk=}eg!u%KWUNHutnXbQgxh3m%@IE zeCN%?nyK|$q@|}d$dJt2nNqEc%;eOx#EKCWq7viNnl{aBmYVT%;urCWpQoiYNl&a< z3*T0#RIcK?jkNTPuOiY2@eGQY2?-(@D%)BX?d>zWR6vlnrb z{}1Cnx^-;aFD4(Pzg6+wcOucdPm)vXHmsSMfr%AS@T)?6yz7PPW$wLPDdbE%#-Ji* z?u(_f=6vsxF^@}q@hrBfQf2kcs#Mk!Ax0Z+9DU}wr;KwYCq(|Qdl4A0)MoXYWG3U5 zHyyzAx(!m&GwRlFT&|Jp`H(qXzwhbmG`GQ#S07Bg5hhnES=G6MIYo@{5l2RazE?hD zUBy~AK0McVU6GQT-gDf6dZ}qf>yGf(E>5Yu& z<+G3eFeq_uY~`u5w)dPfY;4IH&ZDQaXko;DUrM?8dt$@zqCYe&{@a<9?Iqv(`$?zk zFfh8Q&G1S`v${>p_1Pq~o*^{si&de|w!Jr5nYl{|8~m@B&~GAL37=H^cdc39N{J?0BNS$=GNZ4|uP;@a+y`!E65&4%V?SlpEwYosM9JtHYVj<5CkXCMCi1EA&w zP#fY9vD#Nj@v$F&92Xn^Q4;%OK3CS0FX+3UEA&VeCjW7bB=dvVTNTqUPp+(S2-FS+ zLfdm58>BW%PQq$x8xpGHvcdq%(P8(vSeVfn=}DLxu0Xt@0JhhGb+~xVQhrQomf55U z>v$R9I_S8STtJLfS_`I{3s6TLG=>Y7p4K9R2};0p0;ag@wHTxVNi3LxXK4zWaRHK3 zQkokmW+x6&x)@Qiq7mhXwAAFJ1}#!j8t6NvE2|uy##iVtE(``TseaSuNd_n<)OhJG z>q9`h>Ym4Q*wpkS-F8Yc>s%;+-E?3d4w&93wZWtLQ5K-?hOdQH0PSTzB|om9Q{ zzp<$?b62=bHiWt4v>%%#HA$-r(IVzJ4nn*hM!bEGrdPGkK1(uZR#Mg2&tnmC3t;#v z?t0FTYy^bkK2E>{v!&ZvK0$?^(JDRaV2Xfu~1+N}*W7yMhwaPl3n>MF|@RB)} z#a(#?QxTs~^Anngml+_kfNR>b0_)I`*ES0r!{B$fxhm>8j-)p9KqE|--a<$K)z4OU3hY4dLuTX`ffQ6?9lyO zK3k+@v`9_CFGGRdzYlQZb=>D%tRLz&$$SJtvF@5+SXmNRV55hVL#C7Bu8&ynjd{a{ zl`V*p)@5v+K%v>33;hzn^=P7Dq6X8d^*OFLut9(KDDK*AjAA-E*{orb{?`jg8lI;E zS=`k;-pt^ofbX@ztG&S9Lg-A|&809Ie@T$>C^vcnCmXg(*!7SlqI_WTzZ#hQ1(YJF zQX{VWm<`5O#}+^Yw5Aza|1G!x=rx(GGyU_g@fG?f7tQpY)I6gF8+gKK0BFBlTtHMnx=Ety9GwKX4sg} ze<7q77iM;Tf!!jh2KEbjanV1x8DGU+lh^`yRE||el8q;8vL}(m0(}e=5F@!kNX~q; z<5Wh7MS7REab2Rk+6 z$-Kyq6JEggpGGch8=HYYuR@>l=0)bT&XIgMty@X1+WPV1Sp7-=!bsQWMLrLC6Kz7t z4?cH&j^F$8^9!N89Lh^0$zm%0dE~;J)~!ppvWn~KOCupx8;`uj79a3*xr8g$IQmym zJ7}HRSqnR>sh96`FP$V;)=RpV)sZ>b{gH|6?s_J0{1^@fNV)?Y{p+X$w9XuCimYyq zL!E&9KOxVHZKh&qor!Hncem2+){9)&s#sB1maO-7EAl-+A9wU0&(tW*tt)=^b3qwxSpH)7HMwU{I+c+{eZhZ@W-xUw{h zKaa(gnX6_66;fx7Z;9I~A!Nw9f3j3p;O9FJlT`p5C@7oAWu+ zsbXa)`l;f0+Iyq)@o>6|J+r#zOghsytGkr+TgPo<2|Cw@70yKB{%%r~|al z9DD=^A4ZW6qDVFBqglX5yzb*eep{I(<$ZuNtM!d$iLucvk@BiN-s{KID_Un>Yr|`; zDDo*aIt)hjQZVaZy3ty&#TAEnpIYV%O!wEzMg8dig4#k`C|kLK%DoY6HK3lj%Dn*$ zY}6~bpvpa!Dx-C#oCf8lQKT^y=PUQ7Y+q|^@c~aOjJg>|e{*UFtus5Bu#--`@RfTy z24|B#XE0o>a^Gw?z|sE$b%55HgI}UVmHQ*HU#S>cXJUV%yT8-!a+Uk<$oFP_+=D9j zET@XuP;5mNxyrqjK(UQe#g0&HA4S?xQND6-&t_OVi#|8QI?GtkBcWD)+9Bx7CZAn>G`u1GLT@OofBV)B#_)Pky|EY19E) zXAb7V!R#n9lbYZv_u1GSx9FQAtK4T=T$zLpkU}H%XSrkPUP$yjFzJx94MR35c zr3DsG=B!;#Q-s!8iZ;O8x+t2=&5M?nf-j z=6pWxRPi(vPf|s$az6=0yVC0n?JHVmeZ2tXb5xnH+|OC0F&7_|9~Y?uw9Xvdf`c1T zJ_asuOa^GBtMEgpho%1JwLcO%zI#& zFEG8ysN8Y%7xA0-Q_vR5){sEu{xWR6=(oA&{-Qsp^$xw12&&v)p~`5TDZdWo*Ziau z73VAW*ZhGSD5b1EjC=F`GSmoKXGRnlk*Ev4W|#aq*?aWaQm|&ice$FqEHb@UAMv1?oj6sj0LAiDk*nFu3lu9lRg8qnzz-U?j#*DpMnTwH^cc*4%ye$|6It)DT){hCYO$ z5B#JWHN@5FA6WcUv--ihbou{9?VxpL=Tq28@ROR<4p*lqSnSjk*!hgwLF>%Um#|Zt zdg1Hz+E!_Es(eMY(K^%q7TVuXZN5VPMx^~6)kf<~I|bVH{iH6H=W6r%*aY`UxMhL+ z>2)nm%qpgVQv+!*(9};F`$;PGz*Xf<*^+Gx2mG2zwRkd1%;q#XXq_eJXL$S3Pcr=^ zoqFS|@*gdhGMU|Ut2uMp{6gKKb>^-W+-3R6AJiIGk7rq&{bBWEEa=wM4q9h+I>1hj zpR}cRxOzOtVyCUZPDg47tus5_V5bZ9!qwwlEXw9g?(S5vHxzqPMXnz22}Qetst@fe zT4#Oj59M5{%-7?&7HM4NAC(pZr~|al9E^m6;eImIPX<#Td_6uqu$7<^AByky>)Q(M zo)3P!zfsg5T4(+y!{0IQpkhTWJ5Tt*ZFDm+y?f zd1)J6on%Mb)Zf|BIjs-b)Zgu*&B`Bb;Z-|BwPQ4CPlfr~yJK{q_HJ+WVD4UBs0p-% zH_;O&x>E;y-Q7JpC;M=4-F?KUyK(gQqUvZ1ubvw%s<|Ht^`k;)3okSX-5fx>$<^Bf zkliCT_4Z&VYQv#6l&W#H_E3S^2q$Xepf)C&jG}^kojr!lqfr)ZT4#@^2}WD^1W$vB zDbZvSHNn@|Qy|UP3zI}4@v#A-bzMgCGGTZ9KxE#-?R?rsS$}(74 z5=|CSD_m{8#A0QUz{+xJ1#RK2tbvtP)CXTzud>RTTg+Oji?;B(o1nXa>hd-929fS& zs*ASpy1SseBbscZ(p){g1Do4XT2F7YxG<}b-A=?0L;PSg*&j{zQhlzLKFF5keyHT#s`54S(-v9O%#TWg5>y>+ z;niP;`iqsx3zf-p)B|5HzgU@W6{weA!1u>!z5Lwcy}d%cp)I_(H{h*IWm1|N<7?$I zFvAsSd8J{AFJ@3HA2w=b9Q_itg!b=R+Vmd&M*O~u{*8EiLr407ri~b%55HgYq$=3i^>)1QkQ;Oso>RTak8`tD-9+-oH+ z?+O(CP8F*_F(!sorlNc`9m8f=Ws5#H!(wU5(K<_c4cMt3L#k3cd|h1~CQj>VXMbr@ z_3^eoq_)sHv-K%#CB%@L)D~A^CsVyCvi z&ezlqT4#2WVCP%vg|D=~wMcW*rVe$0)|rD8IH*q@@HKb+$2(|19iVmQpeYnbk})r#60sjm#L59z(vTPPjTelP&0UIN;aP_ZCm)to@0m z2(7aewS>1nW619@EOzM^&3*WpkeN|pI4eW*nmbMaC6F@ick>&(GKI2a#8#>SA*)CXUw zkLR}))azq$=BB>Uu)j1J{dljFs8_Vkyv~N#nK5KKHOg1+GlPr6yy=$t0@D|b${k1l z9BK>g-?cTf3M%)Nfy({G*y`kkSn_PFS-h{Sg1_~@jXz!gL;utD7w{M9tz`(`GyXdI zo|N}2&a~Cf+%?YJHU6h#j;#MrM;!ex#hPV3T4%OigRN53)5a?1e?IJ{TPkHJVLHJi z{`2AOz<)k0?Nm{Q;v2D~3>Dp`Cqnixv{>SyhIR)G_0;|*1$ zhR`}Q^ezm&P2H@lV*bzMetLG^wiqz4I+0Wvtuy7yQ1(;hi%^bJTv>y4Wk0VxK*s-x z#*_Z{s4`k-%JEQ+jV13>aaXLlHiqfqu@FCvn-MtVy^rrlV4=1iAnWS{M$GF?Ri_62 z1p_r=Np))AiGl`d6fjU-VBjOC20n#>gjiCO8n{Py2O|Rs1q{>_82HSofiGa-bEFx2hwhI&&&Xq_4A4@0@s4R^`PwHPojSp%ptT4%~bpgf2w zbC;|^yfWLhhEip;&Xh+(d1NdZPQ|%P)<}p4E?L9z{bGHc1YNSmI5jW{1}4Okant~J z$(m5Wz&L?{$xaQ-gn{X?WGXelU9zSZFfdhMV3tz@c`z`Cs&kjDIZ!OHH?hH=M+YCR zv%y~i1SywF%;AXp#0v!FfXbR9e zOTj}Jx*tpKQbYVD>po1Zq?fF_k2jQ04WV^r=*c*|;u=Sa;9Vf~cUCrm z{1|Z=Di%jyh>de-s00i>L)~zftY<6+%uCj@R2i+aRJ;J?=cqDw$$E}gX1i8Ns*Ki| zaw#ak5=UO5;@l&)BtzMQVSSR1O_yx2Et+BO{&gavfhMZfqBmc-$w@@t+T``H$nd$fNy_m5O}L3KwQ*+zx=m-2VS1zyVEX7K<&hm9)(j{e=$ z3fjV3*$*pwsSo~T{Jj`~lllmBFYtyDrwnx*{RgNz+QO?Ji4(nq|48U46+&Bhp_Az5 zaoSDp<@@8v@hN?rgZ|UmDJN>@pmv6;aWCDU5vZMaqIMN(m*dDqD#*WVf0@muixzEe zHeI7>MqBta--VUiapWeo!oOsH8wL*RsqSLj(8m4Tn~%42k6J=ocuPg&tCNs;l20vh zFV}~}2Rq8QI5MyFq48#ofwu5gio?p&@uXP1S@3W#)jw^qQVeJKnQ2-nL9L)IypX*Sg;#$S>Mv7u{w4aCAFp1Ds-rEu`WsL$6HiK01Ki8=W#V(P z&+3~VdwIUJ#gTb?S#o0GO<2(4i6@@8sSEC`FKL8FaBlu3Kl!%nN?yj#!Z|`)F0Zy`>PCp{&*5e&2cZu`z_ugEso4oy+^H} zExeVguo4$fs!%K3%kgm*D^&zms!=Ow3vcCLuu_Bi;9iQaVNo^b?nh445};O-s&OyF z*Myo~$@B^BBih3E@pGttMpgNj;6Jm-V%|L}A8J!|w1rpy4(f^V(1;IlzINv03XJpJfT zrIyeZ#!{G3VgCV3zr~ZEs3rb}&~LDGUC$D`A@mc@+|th!ydiYQs5)`<|4A*OExe^R zu+*CR;cf=CMn3L9Josi%TPJFrpw=OtXQ61w!pJvVAtBF(goMnCbfq`O2UEE8 z55K}Et38F+=btU|WYLfn46-!Rm71)7>=ZDez+{AkEEciWG1lrxm;O->bz9(*K|%x3 zUkgOvOmT+P4*cLU+-wbsTRMQ>!yvmvki$&+01R_>_lY>C8RtZ#%lsgafK~mYYC=Me ziI`Uy^P)ZTyoh;+F>l&4uZx)ZjCo%Kc_Jz>utlQyfn}+D77#Pr&qTS{hf_Qnqe{qm zNXSzn`m0Rgr6|k1C>dp&#pgxAWESk7_RQC<8n20hm1V&+`(Pdsvm#@bw`UR&GZIWQ znQx0A@3G+iAP8G)aSZal2=Xz5eE67A`ydL7uKCaO!_NX!`2%A_tBFE?!9v&4>2_;2 zB;?Z|Hk(eVjNKpzQZul4n=?pL>u@#}v3_8zbUR!B4n+Tz;*6~%3qP3S@q19*gaEz` zgR~MsIx*??FwAWw?L?ejjMF`M4(Xpn6B5!@#2mz!{q32#BIYQ@9B$7XDq>Dx%&{WK zGzOV0g5&{WW_z~nr2NF__)HOfIa63-ofnJjd$d3lY$FS{&Yro(s z5%VBp?z3m^5iyU0X(scC2y%u6KN$pJYwaR~oD)HAGsum{jM_EZt>jZ_je%Q!LqpzCQ-qbjK^V*ZOUKd@(36EQzy%mjO8 zO%d}e#;h%Ze8(W)h#(CBF|%FYZ&#IkV@$ldB6@SC(9}9F8r%0MRTS(O7VJlRW~Nmm zT@<+Guw)o-N7`I*+m5D!-Dq=g0QtVfI)IakWmaW{4t|8R9|$K zswB}E(ZQn7Q&{MUqBR>5GCqjSR%W~Cz($lE&2J@1fyLW}K{`fTwvzTDRxift9&NLg z)ColIM{&khG8jLY<1rv8ZruQW1cM9}LB=!bF)+++C8I=~>5MZa+IB0MBx25I%(?c= z*&^n0#$000TqI(yWz1C~$YuuFAcE`$#LV`NXuGYXo-y&ZiRed|!a?i2*l*vXy`o^} zSg_Of%#&7)JS~E} z!XPhJ7LVEsmF>2Y`o@SpCkidG&}DRb@Gm&}nhgml9mHlU^Pe$+?v;+=yVoGFcs&fF z#8|cxNyG|gtgsjxTg?K|BPh<;O5Vl~=H#vz6gMq^_cO@5B1kNgj)7rrE2%8ve8@P} zV}iDlMn(p!ikP1GnPPUKFeq3-+fy^LMMpucBZbS+E@YU~NUro{ZVep4mmj><6Zq%swK> zU>1Bp5QMF@5eza^1ewGj;~z6>WA#O6sY-q@Ms&0&^c)s?rfAKEgiH@&vz7T$Y+x&S zA=XvDL9+sPMq3-Y&&IkMai`njw6X3>gK8$PRIIB>qXKtqa{>^BMSmmKm0SSP%ZOb@ z#4F2q8qdozcpee2BIA{};}H=rlJVXaLEd8!zX(zl5HlgMv97eti~{{Nx1;xim?Hvt z`iL=W*fXn(n4d9bf<3dQi1{V!(C0xAHhkZ);NKvfP4IEa^nSY%67nArsR1L^2Pv&? zlO_e`)Ffm4>WH{MGEW)7vvIn?Y#uxtX9ZID2b29ZDEgcLqz#MSik}?|jo4WtUT4PZ z!1JaUyc`j)H{491~6W(2r`sG28keJ05NCdNc)*FJczkCkf+IvIl-PePQ;wW znA7cZ!(7pSQN+2&IJe`1ivGh!25*X( zq49wg5E5_8%oj0BFy_u<-)74b$e-cS)_EQ5>^L8bs=CS+o~?S*Z85HsWjn#$RXIm4bgO~hQtnDgwJb4AQ$ ztV4@~AZ+;7vf!(bPX5BSLPXliNSi?YSjf<Z{xLn0sy!`Un3pHC_ zSaG#VUbnX^6#eh$W>4UMAjkU?Yp18QNKgDJrA69LiB(h58)u|7Py8Y^J+p3;+9?fE zNz=ON87VCit5yAoeE4DFPw!Mp{4AwOO5OC7#I$<(kwl_$;YYn3Vd6xd2&71 z)hnf3#a@28o!n7wFOO7a%k$*9@(g9Uyi?vFZ;?02LzLU{efh4OtGs`?M3$5-b&z^W zgQTI-2x+u5RvIr&mZnN`qS_S}UEBZb=WMb_mx|?ke|?`^dTSAbF@fN**WA zM(}y^a)jQ5;5+3*@+J8;g5Q_hDxH;HN^hl)lB*0-hA6|7k;)`xiZWH1q2wv^l!eMa zvPy)wT(h7zTbc#M+0tAb^KhJp<9x%xd}$$kEW&Xyj!SS{isLdImmBVuODo}V6^^TM zT!Z6U9M|Ev9>)zhZp3ku)L+_+@3u%YrLDki!<3b*^M)Q;mjVK*^4v# z;A=nh4&a%Cc;*nEIgICy;Mt>i?iijs4%7*tP6BlbsMA250qQJJ=YTp7)CHg}0(A+f z%RpTL>MBszfVvLU4WMoUbqlE5K-~fAE>QQR?$UiA9{~9f$b2BP_+sz5Pc7#??v=| zh`t}u4iAnj%!04BOq9I?^F@7j;Fyf^DY@ETLApmpNUEpcs zTLY6^&-lKWfl1NBabLQJXUbQsP$}vyiG5XgJ1XkkcPqUe8Ocr=-&BZ*c;}sWB;(%SV6>qI&Zw_#|UMx|}r9byXf0ql@ zjPX@4;razRSG6v$LVPg(?_7d7sJuy>rd&SY6eVE zEW^*Z;(=;1|QuLC~MmhhTK`f+&}Z;pjl<&+5Z4w3ii!BolqUrZ!1w;a70= z|D;7)!xnX$O4V^DT?+dt@|`ymYo^w3k(Qp;AVV_i0I60+W^!s;V#SCGQHk+sO`B#m zOU?K>@r(Gx&(qSHq$k#_g>NfVDp&E{auuU0RES8dm)b0`Mp}BtSCQ`+6+``s<&v8; zQKVO3h-CcSJS91`iHkJ&-&Y@LW|@&#zs1kZGtv@MerTSUl2jj+NxAwilAMpvY;Aa=9o|=(R@4wYEn*n8hU$t&V zU3{PRe^?Pwi>Q+jIQjoD@T02BD7DB3>2Fnh_nk;|?~~-zx(#b)W?*VX6#S|XAMbjh zdYOAKR|+{3k5QT(V8~LN)o+rSjB1e%VS3#LDd`z?>o+df$n|{4oUY&Z^mUrs;K-{FCf*2>E0wJ3 zT)~_qM)-&$qe9;+pRulDts5Vn>$|Q<$xZJ$?m)fNG$ZzfJ^$YKY9;C8;iZ@V>KeE3 zkCHR1IF8+Z~gtG)0G$)-PC6IC81f}Cguull3LFY8urDi&}ZA;o2<;-rGyRsS4`+P zk*Br{RM!_#CuI>J~4-;^vp}8FvccsP}X-P`Y zND7eSYkmINhyVTnsCfa@hB!p5_El1R?8hI+#m0Y>#9r-lWj%>slJFIJqzaS&xJHus zt5mCE`UT3BH4cH=!9Zwx&SQhrX30rdO>IN)pCJGX11v{}-Q!|mMrWiaVQRPn@rDA} zUI*6U;x$Y8F{xRm{<;nAcp2b2=(v?!K#Wyd3#OV2P)8j!h6|RS)*^!mO2Bjirnu|1 z7^DJ8ESQ34X$qQg0g_Wvnj0u)Ck|1%7*VpK5#@)p)Z`@gzXn`cJ6Pe~505=!bxI)jf~ru&L=uy6u!?*11psyXn9_95B66YJ*4fqbxw(4POhZ1ZDxo zuxbK^JE?l@e`8Z)=B{v=YzTA7X+JhgYLZqLqD9Pc9E5m1jClJVO|NR7eU@a-tfZ>3 zc;(KOwFNMI6?Z-7M>Yb&cxMDmFl$Ruy)21l- zvP#kElF4~ZZH9XV8EoL*MTh$919y{4xIP;mB|NYmMgcrP2YNe*wc~0)|_&$!YiOevCp=&|tEzy%C7<(xYX3 z2^gi>4J1&dfn0dcFS_Glx;9HoPQgBAw^xidLhg+XvW>CW2|;{?*5eY#dD7SZ7$d+$ zmN_=>^#9s~ui~y{1*S`Etr`gZBMse;3*9`eIol8PbvM?C{5|Ffu1@+kjF|%ReM;`a zlQYvBu@TjG%W+_b?&tE^A|<0mY6^ZG3T%RXfE%ylKIdZnP`63uBM{1U*961LlDGmJ zJ)9geofLO{#CmVc8#b(LL6o#EW9tM8&E{O_mjJFu6AcqJm{zUNalL^J`rAiw*KT7J z)6vOh4U>{lSR!e7o(^PjSMzu?gO>un*9Ncl0(%RgGif)M!ercp%XpL;UH4D_zRY+<`+l0A_1AS#gb**4p8f&BYv#-6b58JX#I8;W+0`Ff`=^4ZC3nv|N6 z(lnjB-Yqb?HN(b){wpE9xG=Nx3+xt2HLzdMi_3d~-b`W(;88iI|KBHLuc^tNL=p@1 zF;GB^Dan-}Wj%Byy!Gt2B~f_3{!~#<)>Pfn|12%(dM=^J1iT$v zR$u&VykW$GNcoROzj3no&E$%JbE?Qijx41I5g)7t!T4#1{ z!_Lh}a-G`Y-nQ+g#m;qsojcSHT4#11!p?o_g@5a|`xa?#+T>FQXq`C-jjB$HM43A@ z|MqP~qJozy=irGbbEih@%s~k_cqWQGMNM#T;r2{aPWDWFb7XJf_LRky`8HV3I<@f% zY`hdjN=A|AsT1yP++Kw|FvV?W;6JXq}}%UyRh>%^}@Za+uIgpb3R8pRjdp}KUL)3+RYC|yVC1D+E=vB`Wg%6 z_o*`f_HOT6q%jvCl^=1`0a|AcK7xY}qsRwQq#E_Xzs1{!{I-I(c>4fnR_hzh5~B)R zBIQ+kyw{JZSG3N&)`r(wQRGusH$GtvNBa zXLd4SC!KoXEBAB^&L(}%6s+7g8xC;v|3Dp}b>`rgC{gA9NbFZChSr(bpXl!Iw7Xp8 z{yXx$Ss(YH%00`eVm1_8QAMtDZzWJ{<5aOD6x&CUc2tzF+}pDm*3P2O&9F{1E9lmn!4ihW%w6n^+>*H;k&1nK~-GY3=QU@~>U zSMHM^?_e5rfYzCVxo|K$ip-=YxXOJtHpeac=Ey4dnHE=OrIY8>#xmGg5=9n8kp&(tE z*f~PIaFzQJi?TVNk2_U74aJjGk*nNKLeZ}DIz#)4)>&UKK=~Y1<}3Ge7HQ1IN9D&w z>Hw`X2e;thMijXgMXpdEeC2+F-&Rn$U&EQL`bNVl_bZS0dYgJh>&$D2zdFf}A`hrh zzH-kGE)Me^Smp~%Z!#)(9Q{T7=KU13g|amyP`SShTQB-;?zz9{&uP6wFC~I1_gAPg zT4&0yL-{p7DMiKk%KbHe;08)5s}JKti~VJ&5wy;XC@>;X7ktew`E#=O=(D9@&A!*D z*>Uu{sROjm9B6(~&HhL%jEbRkCgwwT%hK+0HG5fPdapj>K{Y#Zs#pPv<*6c9vzHer zR&=Tu3B`B(q!Jb7YxZ~8+^S^J$16GbKx}^$O*UF*$*uw;F@92+8sV$;7|6Hg?z2}G z8H%Nb&^j~pAq;)sC)KDSu1^2J;-{L`kMY9Wzo;Fw&g^^&I|+VLliK0x^aP8YngTnY zQ9Edz+4&N7YEv(KonG52ZBCW1s5V+>+TTL^8>-D$=--I6zoXh{ooS~)yS|^)rSe>D zULTv_K78VKHvTU`U5gX5ifQ1~KpG4*^^?Yal1e>rRe4jkWE;Z)zh+V`p3D-nIZX~) zXUX{)-hT9xOg~Ad-uSBgM~kIQW;fkx&YU*CP`PHvN@BxJ5}rr#hz4= ztH*mn(XOECL;H%>Szr4@IhQK)^?0sD8dv#8rNsd10If3zBjI4UpA7Yr!PEy|j}H%Q zC8)%Q;`{yjwt~CogCFm26!nMJnZL>KH_=bVQ*(R`J~6o1%NuW*BPa#;7&SPK{wdTJ z+P`b7D*o=}JL7L&+D2C=+0i!jcXo76>q9p6ce`k_@<&^E)y`1u7){z!VZQe67#*m+ z+gm-DyH^)#0&U?<^n{7-)B#_2caP4=J{(+kA2I4~9R0nhI@-dk=SGWa?ngrXs1Vx1 z3k^ay2heVE_4WW{_lQlsJ=lrbaHtKXYFw>7RG>D(iP|`*jfp0ss32cwk74s@ltr7? z+2d(~(H1_z(_mssG?_$A@HO@nNb~i=B$1iv)C}6fo0$hQbEC;@YKE(?=UTkXwt6ux z$MdNbw1u~_3|5vzlSR}DS6eT!SXm^nvYc8$TX-vLU}Y8c!PnKRtg_}7vzF?jExhg~ z=x(68d`-PUq`R5wqAk4cF6i!vCfleqS5NQ2=600U)7vaA%qnEJ6Y;|kKNwB+N0Yr& zpR1)0vSqm+>ipW+Yw=^&(nn}g&=x)^XW{E~G&vbfj#FQJ9evtj=OnXw+-l66Cg-R# zw1sze4bHAalS|YVS3_U1xVmKZVl3M0)C$_dTe$}-ccRHHYK5zx?^vwd5?HxUt)MNu zm5|D~V@Z8*wR65j)tt3ODmzen5^AB9%|eK)n?ozx7ed7g5;k{V`fEKlgZVuTXDj3-9d> zcq>zxl%~e`TDc6&a0OakX;|Wm8Pv*$janH;zeFve{kxVny@$UMzwe@dBVHz^Iw>7v zQ!kf}$!UGkre6MMj5$rvI#X7mti%wBit{zI5)-JIC5sQto6|<^ilg5{?VxpLr!4G* zQ7?S;92SEQpbV~_FBuMS^oLUiXq`DIA0w)uABja!F|^LaDxtd-X?M9Qx+3y@$)<{a z+o@s{6yK$aTqXUkK+*41u?iGpVn}5w%2(4dY=%{~=yNkHmZlu7vy|6>o$4{9Dz(Gc z)zx9*w4QeMmnKyoZ|g&93#~I-pTbr`45>+NaTRug#Z^s@O{LY76XqP3@p{W+w@DzNKFHO8Z-jG&gPPPzPw8IY@zn`qTkmbJu^og9g+A zT4xTL!a?I0l1fc*)puiTj#u@~k^QAfs>PLA%`|gr<44%Yj3MbU6Pk{2oJorQY~j{7;Le-&#;Zc+80* zZK*-7D$lX_Yin_3rmQ2igVvdy96R% z4~TZRB8nE9ESX7+%uK?f#2||zL?dK@JU|jjg7_#J0Wp9gn;1bbvdF&39%K^~K?Ot* zAHfY&1Q!HFcFp(i?%S2A>8_lY>Gzy3=cI4abMO8Cx~jVBPIodb!I?}ru0u?LwRguME z*$Ufu0rUx@a>v%cmat$i7i(2}RPG;GmHV}U4y;aq)e4x!yZAWpI(YE-Na1ndwXkP& z#r9u%X(OMSPg(xpO}P4g4f42%3_B{f;V)ls6z4P0Bb~|;$y*YhUyf0 zEO;Xu0S5OJqY1F}Yt#g=?wa5Z05u7)#snlj8oUW0is;ecjVlLgNrOcy%6?K79uw{tmHCsS?;&Ma zcgi6s2LkL~5*Hp79)P&@sPKF7^KAV*nXYf0{ndXwlD;64C!3a}0YAUrO-Qy4%8 z3Bdhs0UiWEN`NI3fbhuhlrVr~2|zcu01pA62dN8>4etTPu(^qM{=?Myu$xhpTI6EWqH`MTHkZQ*mFVYg0o_+F<)crf08-}Hmc6y zSi^z!G%*QF*3)Q+wfd=e&iH?M-XG7pRU8Gy5dl_2qT-S@0;(Hn$ttoDfM%o71lamt zpeBHI*90#CXl#HL6Og!MjRnLqTC$2O2YQ)+VBG;t0nnrXn?OL~k~Jv|XhP*cuM!Zf zJD_O*Dj^zS$ttk{m`m1lQigS>{3euVkg~93%@CFOtW`?NuTnk~Ih7 z){->~KX2C0lZYj2o?Cz=09X`Y3kX11vKEB_ERX;!bqlZx04oA)IROYu)`~EIwu$I(?C2K7d!{#R5`Rl3kVcm897AS8Duni?5Itss-srY|tf8O#od@G{TZ~wGF^rvTBhsth=VD1LfMJ zEG${IMP)u~)g@(Ecgpple0`ABBXMELx*p=zl2s2s|5raxB9^Rwxdpfx0F8pIAprI6xHZT$0uYw0Tf+b}2|yFK0Cxi54pJAEtUI6>Htu=n-$k7d>#p-# zLAgbcH6w9h$!Za_-eoltG5C^ow_ABXH(`|IEe! zp6`s60bBnUgaR8q%2z-+NF3sA{DbI$qk0d7|MS^ThB~(XuSp#?diBFW*)9AEp(7*& z8@>HQq>PiH^5QTqjI$4O1Nb$?u<_NyDUKcIFp$WD-;c-#IY zA5AB0+QMl1lbRVe`ewcWlygCLhET*?_U8cbo!->rjjIFWm9jIHBV8mU*yxd}hB`2B zh?NtPaJ$|ciXa#W7jMyDSGjt9QiqLR{br~)3bBR+Al#mB6e=F| zvp(tZ+w%==MCRpX#SOw8Kxh(TjYI4fq7ZJ)HwjrwKx3$j=gciO9&=bUrKW+6zG?0T zSIZD<9%78R#M|;MZ8*(2DzkwJ1E)3d!A8#)4?cg0#S)xwOWto|i?tD%O?3~Uz($Xf z2$W!mwI>wec6`u=(q4j+L@2P)qud9SPQ)SHitl7oHOKD#Zq!nsmP~5GZTMuUIh9OZ z=@?<7KgJ$V?MABNE%^Y%N zB>eV!ugW>oh!Zw?&H>=e3b71=6mPv}0ZAz6$}()@1Hec15>Mayvk3_{8l>Be3j0|g zJriQX2uZvk^bC+r>#f8u2o1xYv-+O!3qt3OsuNrPbA$vNJ<6kU#3HcjsDQ50A^B%O&}QYBG4oN zoT7_B6Do&!m0)0_hj{}q(?YC-V8jbR)52g%Du zc)j1tB2V$i6V8#p$|BG6$TQB7r)81lJo1vv&$S?TxmV`Wg}ZdFq}Mw7oE|dY(df}6S?Y&)>h5}YkY}7cv^SH}kdv^|$MGfUq`A%5+BT9|zPm`bVOA&rC`(t=S-W1FK z1@1CJ=JFDk9s^)uDtS>BGlj=Yj2uJylW4r&S7ebhc;qza$P!uPTpl^gIkHq1xrj&3 zm$|&dU6#sR%HU$Q_8P}Q+0{7kRkHAHTw#lSTx@baq7AZSyLhsXoFjMGHMYx=9pK6K zIVamIi~NR19&(QSQWp6GBF)A;EOR-|lOK(6;pf^3?(&PwJ7>M#zayggnRz{rzSb`;UOlXnw-I+~;J2+l^<`1F@F>OaFvC4!Wxt*L zjH!g-7qdT_M&#{n`M2UO&1Eh=F5MQu!c@{)78Bqx3I2%nw5m~+#LFV@v2 z-FRe*b7ZnCvKNo+DRX&@yY!K{WWmL3?R39WRno^8cztEzd0b(zeOwH5KB8<{vj6a8 zPdY~y+BNcJ$wu;IMb62dl|_!@k;TrDqh*m35otE&c$v#oo_unI3qRMUbC(jC%Utd< ztCC(T)la&-r|6NaD9fwkVdO=rMvu;vrC!EUFP5FNUhl$)XntnC7-vmHqvFJ=B+WW` z$8(o)aki;sj4WyjkD3_gFqJ%RWq+OgjHzTMelh!FdPLs7mj7(-QYv#<$ff52SeQ!Y z%3@aVm}PN}Q^^up!ezxy3nhlPq#4kK8VE*~48vk-2;U7qhkZ$2mop zpR-9(`MudM!`AN_NhAy(=Q3`I%WSU`-`;0-p4&98YnKRSk_abZZ4X1BBh9vD-NB z8zR(fy!rvppaFQ4uoYQsxoAB5%>hqFn8y?&cOzL`Qy$kuj4LwY8q4BZ@wnzraZDB$ z%j4R}T<+m6ewj-mT+9Xu1U$Kg1!2c)PDl4fM9#L_>3$yB$vLuvEV3JqOmU7(mPJ0y z52#0k3-7+ic=A4I&OvxwGF`ydyxvD-L0LQ~9YMK$2Mr1vQ%j8gdt4U#Bxfp!9E~fC z$h^qWxY}yMXSwXt5!u&TE-&!xBgE0M(a2pSi+h>JjTPgT8F9t3xL0}HB&WCuvbgCy zu0-Zi%3Ws2T;{>W9F23FN5-s($jw$eE#;AmoFf;=B3JXs70!{%Ws&Ro0j-U2;obKh zPreDwDUQYsvY?$jXgh);M&nka|F+3uk8`G@k)v^k5qTtXG=6L~;Ylw0TSWF>qSKV*J>w)M>cYfY$%It!Xs~Wj?`q4cku(dBf^C@%iTPA3pA%V8k@<2 z;&@Ojf+9xaA*27=$YMX`OuK?&(f^IrR9|qH{XtvN|Cuc6YaVql=uq?@wXz=}KV$L# z3BQ>A`9nnBpDh1hxyx~x%b#5OB!GpY|AZ{&B9A#2j41lQGg|PBEHWl!odMpEV`RB3 zvL=tb$~m%HNbC~c2z7a6ZJA4b?sA>XMS+Xi+Koa^MgPynfj5+eH{}XVLbh?y*!hTV zktJ)*leKh?Y;MVWEhk z|15SJ=ly7envFLyBrX`|Eti*h_OT&hp(!_V7t7*a<#Ch5xKl>l1Xc&Xmf-M z@4lTp`F1p?xUju13);(rb|WZaVT-{Ld%Yh!$JX>*ZM>=Qcxnu}?z*3UOMd>h_y1^L zHla<+s{ejF=L-A>a>$?BGe2`ke(JEyA-Tg+6EpJ%7UbroK9rqb*mqFR%&crSxNm+z z=8)8+#QRz2&Z)!NwodJqIViJler9TJzkjEuBKU8kP<$YzR@{@8_`CEAr>BgzAsFT#GYKb~SEmh~L3)D48zFysi z)Vq=VbM;&Gcl8{SUs6YFFKbh@SGB2Hi8e!fQ+rFBqb<>vY0I^hTA8+9+o=7ksHWHB zSq;54%4#UCQPyEwhV6Q6-!%x{RW^cS6SkYN-Gc3V*lxvkn?bit`2dXDvHcL+9oX)~ z_9JXR#`Y6zcVW9*nWpT)PoFBQl)do#414xr&wlLr9D5F6&llM9U+no3dk$jHA#i;K zy|3}gH+bb+yz(7hJB(M4;I;4Z+7Iyh5ne~(^%J~~!Rt7@eumdC@cI>AzrpJSynct* zNqC)t*B|iu6JDp`^%uO(!0Rl$&cW+Eye`1&qB2pr1kbOaaDwOkpi7NM`6S6@<#l$Y^6ULAp+8>voEN2wFl z7tn{J)ye9M>J+tDeHHyWRUNCohKLeGyso~iPE*IL(-H9oB4!|BCL-QML@6TPLc}aY z%tpi-3uY5}4aB5Dz$79(m2qL!*tm1XK{%5t?tc}IO+S)oo-RwC0X zWLk|(YmjLzGOa_VGGtn>&R5^X_Xc&FvJn|KA>(Fb+=7hnA>&qL+@>y5-&dEbAE@uB z+tn57hw4go2QuzN#*dKkV`TgU8FwM$Ze-kpjGrRoUUj7M8NTt zY1(vUy7q?hhBiZ)p>0-X;_<0YsZy$v<1ov#IDrJ)m8Xjtu0d4Xp5D# z+7e}*h9_rf)0FkvD&<{mnX*A!u58p!DVwwv%4Th)vIYAac&;yMTi@fU-Ci#dnq_CK zeImwNUheT!^|a5*>|4;RMT-d@Pm#H&S;mme^n#(8m~nA06h7W(^&f?=X6f03Zq4d% z?5lz;d~{dg%kb$x$k0|7zLB=WExlb(`2& zzRUQbWs4SV+qPAdyM682v^4fSeznI_Uhef|jDF_L-f6M_tgJcr%SFkHryp3O-PV0; zlj$DMwKc1G^w+9R^LS9r7+>KHuJ6#B`>x1#xcVBiA*j)Hzh~gHFv73B=bHB64X^v@ z&3>ES17Tm>j~ZWpNl$gZ1x3Exk2*l#tv7!cnICn6?x%OboIL%fiZ7mzIzoR%?}nLE zDtz>xbU!pH)5mM}pv)nD4Xc0GA-VmB^c}2pz@B{N_F=JY??_F~P9Kt+pPN;nn00{C zy`V57J2$meiL9f`hM#Yfcs#(UML7H+sC|JQ$d6^m6gFGzje_ws%nq@|6`jDsc3UX63hvubb zrVT;bbPvnO&G)e0*&g<=r!_XcJPhT>kUYGS(jVV=F{NKC4@>HVpOOK1FmFZ8WfWShWB%Q(+O>_v(RIzp?%O}P zumA(AMfg|CP{>oKL!*n=we}tlp$}SN{G@x((03&-PQjl3 z=44pIlN~UcB`v=o%?b{6@6oOE10CVD-tzh+h>S_S(n5hQU4nto{b~GOpQq?byhXxS z%;EN2zDuVx^NrMqYWnizDO!L;F9INDjKG+cos*GfrNQl159l}*h;51HmnkOX7&mB_0 z1r_+b1fLq71_@{iG-7xY)S@QH5fWr%X66}Q94Ck@H#;LOYe;6M@wZ%_ zqGos*Uome9Y0!~r>4Wpq=nuZk9_&&qcrhvo}i(&y^L)EN4Dc$C%!TuG-T6TwWlrH> zo=+bLZx~0P5^J>{_``r3S->Ot;Byz?-Gtk?`hsg zuYhuvL0L_gu|TPHtp>c65_#~6Uo_)kxaQ<$WMUq3nk(KmQXULMV52WShakRU`Uwpu zFzM(1JR`wk-g120>HpY-uNt1MVZ$ZRy%SPDNvU5KQs?F7@%cbM@8%nspTHQw>ZDJ@ z7%2$8M8V_5;KKX?yhrufasi@az7pDVNM^y1>`c5FvL?Z)@LQ<+^$>Cm?K`Nj!U@H? zXOV%jB^Wl*gXCM2q=x5ye)Pt;;oZtlh`RRE*gk+_MhO)95+EGWVgsTR*XrH_>kTmI zy+;kt7e+7U;~;bTr)8k7M5Ez#>c|?NypY*~zgyfpBhU7*xrNb4`a)>J3|xXMsAwC# z0hbzBHJy%-H$-!5@ZVq!{xGE$q%=S{e2fNTs^cd>3uwJ#X#G3<1fVsUpJ#Vdw&#Rw zCU;t1!4Tg0w;|tZBj50_vpNzv<|EDmQu+JHV`F;D#W{!9DgE}F$ zPT}CR?1Id}`NDd)!8ojy4iNeqLRwrn?7LyJMOr7!7qqzCV;#*BegagKWBPwS8FNiC ze-Vusc8pd5F-PcxjKYc;Cmty_>4)^0a7eWFSTn{Xcx^V0r=L^nhbdaE`k0^?K7Ou6 zt}V!g>kOXSeTs_oBl!RJm2z`YOnt?Zq7?n(Nx8e$qjgbu-dMeA?cd>UbVdejJ|i}`Q(8)MB+W`e!k|B)7z zw?X;6ShktO#SdkBFV^}*p3OE6FrBQ4&&<%b{`Uz7)*a4H;Cx6d;s>*R7+XAQn*L;u ziN?o#Pc%N}d%E#_HEjJK5do|_g59yQ4`-_o+e2co?!@-taQD*T3Lnt67wtV=@AsFC zet$`!kN4m2R`I`3JV1)VhqN7#D1PZy@mnZ<9m@`psQ5u`U-J=m$fhrhuTHr@4gCI!4|wZ{Js;{5%@(5y+oF^uRnFRl zSYh3<_5^EpAA68M#SeMw4lJQKEPK#4UI0DKc)l98{)Y$)HY%(Vt8yOztSn*@K1w+Y z0K4=GE~0YJCS_Q6%DGS;>|+B-T&&y&^LcHcjRQ>Y8+9|b{yf5gb%#?3oP1&tEBAbK z&Tf6ogjeo+3<7NZLx}*^9l?KmvdX}e8%btm>54tF>mu28uTM|dymEh~a;zzY1?vv$4PZ_4u@b@(D)(tNsuCNOxuDM=99VZabAU6;$4UuDsN84S za7raOa|s959nM1F%qJGHa-VOL7KY6tB7k*Aup9(Si9oE}msU>j4iUh*BUlH5H9oeA zAcV?&4JOA=^~sS}?yGE6W~Ec+7Go#m7D0ozADw!_D^6PsAMe`G`2!Ev|S;Dmv+ix^?uF@6rleLl9A0ENnZpN(&?jmm7Y z1B3(X4(Ds&9P+U*2}h{h57}_Ol;C_rII!+;z6Z`>Vi79$!!~7eJpbTU@fZ}3lA=(# zABCb*>2;ir71rIc{s!e=NLj4hf3ZnpELM~sCx`&n9l==;{N-bR`q(Mr5G(h;#AyYU z`=8jeSD$Ej<$kJi)^o%P>yFjy@4(7^>~8`UEBErq;;`&*+js%=ZliL?)?dYMUQdCI z3hPa)a=#8(*ZLiq!~bo$`%PZs2G2NnEVl8~CjYDD~|e#Un@J zYI`FBfprI>0Yo7Rv1V8N#iPE|M@x9ke$c4dvGw0V1hDQ1n)qckdxhBTBnInF>@FN` zQ#xFsW^am?KB)J2M9t3JDz=1Tb5ay)_U01BR&Etzq1e{XT9c?)v$y4AtF=uZcXITx z<)g-ib=TPK0g~Wn@dP4P>j{t_DO_idmjML`2-Y1?X8?8dvm^o%>hz8_o+LXD&P$K~ zKEi=@hw~tCQv58LaD+NN#fFnC!Rbagu2{^dfCociN9ayANrL z6?z|;_G6?C>rOip+Ub7Qm*j=oJROtZAq7u6#(xs@wUL-rOqN@KTmTIAvw?n=O$w$Va3%m}Jh2G% z_;{PLIg%&3ReTkSlSxsi$0tM4si2xl#|rE2Sf@d`gp|d4yu>DrRlcIMm`((+?g-|9 zV3wbi`q@n45bN<-)>MK@yc9owrB5rkdOovqzPZE)>yB?J_!j%wLV^=(@WqkEUfDw1 z7(prcrBQ=p>t9A#u$POKh`)Pz%=nv^(QzHvs5poEdsJNU$Zs9$?-%3D${#j*)t8|< zE{=^MVX^ie7iZPpW9$s(>@}VsV55ha42X$DAlBUzPMkuh+qwE06cH$80>g{$}bBftX zy0Fpf?uPCsq$}3cpU8CgkS=WWx(A@UKaPDy(n3AGACub=s;57*QJ7W87jDGAgZMXb z?5j9-ko1LG`Wt>)eg$>$+&F0CF>C3=)F`mgH_Ff8Iu^%{#<3rWORS@h*>H|>)F13% z<}mq%$Y7%<`x9iR;@IzmCDhQTY*fG7S&WnRG@-yok8%+x=i}H}LJ{ic^EQ;T5|m4X z0vkPwHy&3ki9@KJ%WbOWsI3z3LhVYZ#l)M1kWe?r#5)&4)#A-U2sZj-tO3=lNL8$v zud>OaX09j=YLYr^^y=3^{n~g|C!WIQ*RGuHdSZi(p6zC^ zHHv2q2~4b&8v#Zr(8?MDNi1eiD}QIy%Gml9LV~?qq}})6Z^SQo=x@XuC3Ij76CCR0 zh6%+Zk2=)LHzkYP)UMe28xsz!JDjG#xt&iPBrJbp5=dj8!Yz}9~!5x}}5Xr3Uepew{$kQl5xvDP@;R&=;R72OK${kuaI-Nvn= z4~p$bQK+QbNfiBV7288GA%Vq{s8~%W@DUbo(-%fqfSMfEU6XeLPKN}RNH}6$-2o8C z^k(OOX_8nuR%gP3b%*sJuu>9OGGPf7c8ZNE*+yknG~EaX)*a3xze2WP%`_2*jE@y>fyqB7k*AFc<^_6IeDu z2-WvMOpbr(lOz92lWZH6SAN<{+tbIILCe31}6-p5yS}Vj&Up)ixb#r0u-w9VjJIR8I=4y-$z65vcF7NI(yYEw4H^XqOEXFzc}DGC+( zbSOHNUNh-fVci|;EGU}}!@EA@rqw1Rql zKK7i^CmQ~jCT~~Hx`bF^-Lb9#>#78{f|9tz&bMu5RR#b^R-{Tej^th*+- z13*mztT6$J4+d`nh$4D0c;m`}ni3GKJD`>TY93&WfW(J`HxC11l>@aRAXs-m?Eut< zXoLrZx3K}3t4=H_!@5(Bhq9lPg@=UuMP>fn=zB;R)}3+)%7Fm8m&An!g$E#RJt+KM z{5)GfPo}G$p8A&lNjK3gzN0z3$SlmJU60O5h*DPaJ~ z5`b=Q0UiQC4^kH%8r}nnVRIAj{D-OYVcm89qfqV>V2_Zv@Zj)10qeoxkBAuj!Qqd& zmCuBHdVoDn^1{Qz)3Got(HDk!`gp^(>~RT3R+JcftR-tGFbV=Jk1)g~s{kA;bdHP0 zKY?9T%JQ&hwZ7+qvFC#E&-rVO`5IgQlhiq|QFRW-8V;8g)lbE9#{bLn z{&?1{;wUJN2(Tg&6_>0LP~AvNR*{VWG#ia3z}Ei)H36)keoNfF=dl1OgJ5tVv-&6DkLKm4IN~0Zju?3DF2kR*4P3T(YK#p;+KzUPuZ6I-B$=bx1tPLUtpCaFLE58Hs+XHMH$qP%?b}S5A^@V{iS=%HSJ1-w& zrT#8!x3y#)1IEz+J3<)Zl64duJ9G}dWF5htkM%v_OV%!9zQ)#noH_^gayv)F`W;xm z5tFcF{f36vrJsrsOV&xZif5pBI>7!QQE|yS4b^?LWc^_y0L?z539$8_r6z!N*989n z=u&`PARuwcx&(+1Xvw-zIZ!zP!MX#wGKf2_K~@Ey0$HcK=QeT4iV0Q#Rl(0<9|w~Nw zi3>~C^$@p~ta|wQzxsI+v1I+rEx^qHXcS}(2|!q~8ifHglmIAh0d51ptwE*{fUsoU z8U~Jkfy~X(R*F8YkMf$=AN9=;yH~M&w z`1i9cY;t+4+ zA4Crv)q5cPpU-|W)Uow{P3o}Gs~--^ZsAu59U&pu=!K5rFn^%K6mH-DfHwX~@8^hr zI{V3u+AmN$PHMuf`{NR|U)`wv0kxAsc7g=O+x92#C^rjwfTpbv%l%1&@=^`P)MvqiA)PZ?JtelX9+x6a1BvHAI$Xw}TLS~Ht z8$C)5pj;JV)k0>$BiyRL%7#)6d&H4xqSPc5*yvH}0Hro@h_~r$+hm1dQkT?WqgTHH z>erFFc#HnJ%GK+WI&AdnH$%Nqh&3bt;r4u^Q1Pgr^+}K4o^NO)GH+)pZV>JOLX!|{ z9AdW+g>Y-WNyu6P8be(?XKu0an8TteH4SX^O>;N6T83Ej5M#t8-j;7^!)eY@nGH-B zIIW2fHhR8z@cBb5mf(b2@_rjztc}QQs(T0pHhPpqpaes#J)sD<30#O-QiOAl+_M*v|s#nGhRBNa6*dXMl8CZzX;~Xc+dK z)%S#75IS#Eo!I)HBP7`9kzN4ONa7JL28~2}oQHVi#h}q{)Lw$x*bplwLGeP+SSXg$ zg`i@aI!MZmL&w(tG95Z>^oKqLFq1-T0>OwEfhGaq6kPf#VvNW#KJpT!WiF8VCQ&(CWZg%KBhmbnpM4e^yB_6~^)7kpNRiN7NeU*kr6 z1H{*d*g6syF7~Vs6JIA0-{?mCJ&126W#K~4W~hbDJG`^EQfI?P-`P8$x;@0+Ct=|t z&-RdYk>`C8fnVg==|=ifNbe4@k4aj%z_S|@{V0sBiVHj+OAz)72vxlsW330Iua6a< zXI}jpdT8-}C9d5TA#aE|;{7I~gWo^g&m zEsHGYk(XpHSNN=st>P0qmN#WBxR|Ydwa@7h^R3b5UT<|-_zhg4p3gQe>iQg8@fuk& zl_$H&Ir2ukMgv*0raV~_=VXm#k*#=SbLU7Vi;P92*_dr)F8A={{si%Us^!E=y%DWpFWDdyV6u>}nkNDp~k8 zuCT>EE;czI(FR$vT|C)G&XGIp8rx;b4)A3AoRjU9MSjC04>?DEDU198k!E8ambo0~ z$&W_3@N?}1clkx;a*n(FRY|Y?={S`yv$`PPd+)qg`aEFxl4)6WiEG_RY|Xv>L*>^Q}jqyl;zd&DDt9Iqeo}T zQZM7F7t79BuXkZYG(R(6jI$=9QE}o_l4hN};!HPQ24pl5X^9ZCPrCr*5Q&N4~+)&sndxVMH`PGjB?;4zFQ?cz9XX$=jH_ zXbHBdM3F_^$)j#haKOs3vbP{VV=8HbU(CVXDk5*LTnJ!>!UhgBa zpe!Dgj-cGWg9e3-sU=4LJuZuVk~0-Vj>Z*6WM1TGTx~Vsvt0J+i0o@Emlt^U5#s3B zXyh)E#l6hq#)@&vjJRT1+^alpl2hCSS=@9US0ZyMb98BV$%XvdH!PfYwI1@a}t$C*OqT6i4F*Sibaqj9Uzf7@iS z$2rr{$kDjNh&&QG8b7w0@FbW0Eh76a%jGQ3ep(zI`;6Rw$l}U*+$AyY10(K&EUsG6 zn(1SL!dz^|RSAl7IOnXz01aXcs%K@p?zkkNl_WU-%erd>g?=>NuQ zsxP?9{-CYs|4bJ3HIF(NbSV0dTG@|~pRxG=gkQ}5{2?OmPnQ3$+~v5;k;j}1Mil+u87+8578w(=&H!)7F|u41S(8Uz(z#GcKn{tIFA=|iU?0iJG$da|@$yz!`Hn(dqS+aY0GQV@OSXpEe zj|@6TwwFcTk4UpIJIP$S^5n@8F8o~U$z8h1T++BpY9+naJLFXKpD=o~mn?NQPo1TQ zM_xbB&sncGBO;m)%IA3WGl&+d`_o3`uuw$Ne-^uq^L{i!&BhxU5*Li~mdndL``D1M z(3Bgwi)C@I^0-N2+$ke&f-G(ZkDKNcS0am>&EraCF7vs|T$#%J4ddQMQ-H>v^m0sci&E)d^?&`T-e^11?}ZQyAc$zu*Kkr zz21+VV{3Y@Hr`ZtJT-<~ciqpwB|rb$`+u}Ao6x3Z)qlU8a|QkbIpk06nV&f%KXq8< zklbOZiJAEW3v%;PAIi=z>^rDuW>z*E+&8}u*9F*BNKQlGA z-@j8+@-lPs^9Oaw?icoBv%HLcoKJv7wnkmAu2WZP+tkn1Pt;G< z-Rhg#IrWlyK`qhlJz29z8KsO>CMz?PQf0RCwlZH?s4P{MD{GbY$_8bt^1iZD`AIpe z{H?r*bmP=l)Jf`8wM3nvma22r1?n0kU$1UM>fK2Gx%#d8yLt}EFR7!om$fO{tJ+kp zM4O?#slBDm(Uxe-wB_1LtxQ|5ZPfl%RMYG6tcKniWi=GnDC@8-!*)Hk?-~T}DjUJE z3ER!sZo&3FY`0>&&7j++d;rGn*nWuZ4s3T~`w_MuWBUoVyRhA@OjGvYr%#nt%3k<= zhCTbRXFv9Qjy(sk=L_ulFZO(iJqNMp5V*dA-q(2L8@%!@Uil8M9mcCi@Y?ry?FV@M z2(P2?`Uzgg;B_2cKf~)6c>M~m-{5ruUcbZZB)m?+>koMS39r-e`U_rX;B^*W=iqf7 zUKikXQJJV*g6H4x{0E-p@GMf#D9@{Bl@aPWWu$su8KquOUQjP8qt#33pTCu2^&e%7 zTCR*$i_llkt1qcV%FFm3uZ}>^jZ`P7qtuD&3+Thq>SXmrb&6W7zKVXGs*Y7(LqrK8 zURPgMr>W!B>4^~s;kH~%$*?&UzW5|A7{Y?E?-KYM7?7t%WZ^(WE*?&j&lgNGw+5bTH zKau@3vj2tbXOR6YvY$it^T>Vy*)JmdC1n3w9j*L>?{cUVX+NpYYsb_P+HrNH_Om)l z`$c_0ds!K+eWAXnjaQ1bSClc@1ZAu?Q5mOAQeM&~D=%xmDdV*%$}8Hd$^>nyGEsX? znWU8{leO2CDcTMDG%))pyiw8hF=ZHcl@!;`bLY07$SmGZ8(Oxd6w7%4+v_Dlv+RtuPsDi3%RQc|p7vRpeG8hkXfeU#DKhso z%NUZGUNAHhGcN9h!pHlp{-f~KEIoVBty%qzeO0in>U~Cc6}}9g{)3EtRk5w=ZCp!m zz%PbRc8;+-#_+MFF?}+J89w?lP}SS(apRY;jgcq+DPs@*3;{kDZV7wY_|fpm=x6*~ z&G5<8(+OWX!`01OwQSqAwZgwzw(>$$dOHIM#UZY!?`)r|2K-r)KU zy}9p-Y=^6_F&ly!UH2OSpM?>A?LF7D4{vzgPx}}0={*qk#r>%9^_M!}`+*z7obV&} zqYlttJ+#&1nIiL}PSE}Obo6*~ztw-L_~QAfBlK71*6?^fx=lO~-49L5^zoWKD07Hk z!|LC4NN)cjeFrNYuqR)+eOPSUJ5rOg(}(2d=VlcsW*wk(FDT5&&P{FAqNOi2lskBE zVNQ0zQ>hPyQhVg)4$4nW?v5W@wrqYL+o* zkfvM@GFI?ZUS>x2AP>v>-&Y^GW|@(iKIEyqg51>1p?Rs9X~WX{rKe>yOZTvh+x&MbX5r;&rgwz@Thp8(nFQeRI9rN#Q)vj$U4zO!RcHjQVg#{R1EyBNAhC-e? z9U5J{uC@1Heb5uFFn+IXShV&D&rKN3^&hH*$*O)+eafm|bOrum1NKg1dzZPdy0NeB zqS*iSQCQuUos&MOFas4Mbz^?ttjzp^zUc#-4e(s!UHi%tlka+IUDn|n{$Bjo?P}|~ ziS8B5fnua@ad>XbJYI6`zEh_Yku98?z3kO8DiwVSIImxJhlIw zRfqPk@yzkeeRc1?{6?p<(dymo9K2D;={v|gO9y55GlbrHXnRbp(HEC$s}5+l&%7_8 z?yn)&P1H9(r=^j+{(+YJ-|A9zU6V71rZ4{Z>L2TFe)zJJ%Z>t*Od1Z!(7Eg3{lmUE z^7z>)MTxu0KMZcJd+3H}bt2}jYrF>*^;rD#yD#2&%gIgeO{nLc{Xf0Bd6FLLnwF87 zKP(MX9PV^oQ5~mi(QS1-o_V+8hhZDB>4v2x27k-oJ<{9zKl^%nEO#(x7o-i$e9AN0 zTQ$a`c#3|(Tg3T#+#x+K4RH^2x+bRTt8J^a=~{IbqQ44@PS4I8kU50MoyseVl6s|u0$sWU1EKrV`0ZU!(Vb{2BlqFniAmkz6AY!@pY#YsYMHOZ9B$8{yL3u3 z-&K#O7NbWMEr7&gV8@IRjw~xXCnF7$>S%9_?pJg>+?E(eH!D#ek>DMYozp+9pl`oH znfL`RH<`y6b5T&k)K`$7hB?GzDV8GDQeE+JK`|%u$+Vn8{U#qZXe0P7)BQdW65^!J z)%(okDuL5--D#eXEI)Th0T)!@^NzuO#IFx@v)fJR3s%Q8NI(mtZ^B!)mDRHU+|aZ0 z13ez_c=Vz$CP$FU$jn4a+->LJLFlbC^uE3!Kl?wKX=oiiu!g574kANyvoq4NhGb?M ze>CVRY6f>b?OQ@x46U^E!Fg%)mxbmS>kQXbM&`}t80+~!=ZBKIbq{pmLxx6L%t9es zc7B@PB$*k!;bM?#wcc=31;_jW*;y51x+$F27<%&)jWKP?r1b~{yChX~c@57gzkU{X z#jr~Y_2`9H;;p9J*xnk}7i*?+mgzoK+pp zTv?%EIrH`%XG+ApAvD{6a79TNZ<`I+0ZGs^NHBboIwp0)KpC7z{odYcqW8_de5iBx z&S+My#OI9nsIPm3dUQ_KkB7gq-99bw^Z_esB`JWj73Uqs!UtCKb%>2T ziW;6V9jzYH$4YqC4p!E45z1lM9W9?Bp+N)El9Q6tG71L|ehS>3tyga7U`BbFqJB4pvp9SWI*C8R1;h z=a`Cf&6=O*BGWD-Q;x&%rN1ij6g^;3543rOol_~MSImO~drskC4z5o`pBi#0vDVp! zCJSrj2Q8(MeEM{H^(&mUX%TY*?~m?Qj(QdIJU>->66B8V;bU5#iHs8?d#DMkc#2M= z9S;CDW|z>A`T_IP{}mk27sdfq(}}EOqCsyBkVh<_T5%Pl8a-8=ddh>(PozQv6K76t zhJJ23Ev1JHspG~3oSaD0?-uK{IT(m&5lDOvKzzmY6Z%9r27Sr=%1FGJcM3mw^nV}4 zR}IgPhG@kUfZWF{;jLk_PM~`yy!50gTf;N@5!5MZ1M{)3KDGSo0!m(P9$!rLCFpB| zWMD503qG`ylX`SYNen-Y9h{Pf4g;vXr;+ld)$HYc>c^k!Gd%!*Wry?H$Gpp>e^TG zFc_LKVnzvvrq{GWGo3Mx?1e|tb8|3O^g)^4Z%}UfK#)9XA+GU}LZChK#;uprLOLewBX3QZ#XKxKp?O8n_*TH z?u@Kb!q$hUOsAMHgu$ADyKV&)qfj5J7xbaJO_-qd<;!V;zG!r7O{WpU2huYZ+zr-x z5C%2edhr*2ilc$8b8mn!s4!OO=>t)MTMKPf z$dntb{|;X$=0mvm{&LH z-FWepo|u?kMQ?eEJVpAuGjzIlM|bbO-rlczdt?6NaGX5rEyy|=Sz{&(UWGa4yBg~~ zqdr5vsJrcb#ONX8+A3AAymM|w8x$Muwb5*Z&Ve@eGbYoAwzSr1tK-5ZB3{>~IXm(u z8)G$jj`LZ?%dWAOD(pQM!ggA@}2d8BhWDd?3-W*OaWKUGgSA#PP2IOYY zlu4`dt8G0Yyirfi9L$GILugDiVplpeM;Hw6pry`-7Unw1I<%5b)|qC$p9z2WH`#KU zX?NnCJ;ic*DYB8c%d3{lS{kP28_kNTp@wIAq(WFXOtr$_4XfAEI-z2tcZsiA4omow zR&jkw|L=dJ5=`bV;)ui2Tkr83*y^F|p(tvNg_rlmt&l1)`eK|}A?j5RCe4h(L76xn zt5%#NoZK0O6}4hKa9%eOj5HE-NzpI96@oD4GhqzTdnc?F8PhGUFH=CUZeIixp1q|gV`5_9;s#K4u zf~&06tKed3b-bke6it9T_G1aIUIlNI%>7lXd#cs$Q&gnq`v3Noa&u8keZ`Za6#e5# zxx3b*b#ZO*#_ClY7cJM3{^z~Ap4ur@7U4ski(bR;#>dWWh{Xpz#X3Bvd3`J%U8Fxa zc7*XMv?G)*=Er$$j5R;u74~vJYe`hz2Ico+*=7KqNbEbxMM^F<4SNm9Xf)G9k`f6YC zs8#ypxZ0Q;@fTFpZB*um>DF?KaXm2V`B+^ayM{=F4}-4fvzCmyAP~=`YivyBsJ(%j z2-aN_DPX(F$8Pko2E-p<{)0cdP*@-%HBkheY3Nlg3!AC_jQk0PBw6eh_r_v5r2LL>%G=MRyjb z6?{;1N9_4fpJ=ui6U`Q-EU9wVF2oA!j zy>Hab*!uGb2i6@~;wUJNAVr~aA0bhE!L8yrD30;57fDpC+{f?{_M%N+ z7-26_lf$}e^2xxN=wq)Cj##-*1jPG#v-8URmCCWE5EiUEtT%u)&BsazOQ_tZ*{Div zROW&{gK%Ko;miTfEFUW+9HDZbWy2|z;LIf)Sa&!Jfis_2#L9iXOi--W$9l>%C zEF}W5a$j0G!8=3%>yBU@2-f)6DuNIy_cfRtKh-BkUb(NbQJIxanOlslz}Vtrn|y2o zkqDLh7Jfo+0)cogZLl$!qjnoL5v;o=`UGqr`PdF0+fHm^<^GWkX$QyMZi5pB(k^0z zb;tNQ829tUH{qfpf^mz9bx>azA9l`BH-O4dKAL!}%UK zhlxd~+z;E7&GGz$Tg78gJW7f}<$e^3PNmmzI#yVB$NC$Te<5YDa{t99jj>o!ew-iz zSa$?xLGYK4{pn+;h(oO0{}QJaRPKLb&t83^;g$QT%3045E37+KufGE;_p!eTRIJ>~ zBa6ebzis0M(7TPw9b11Dzj-|cHY%()t;+p6U|s8XxaNMXzj)++y_ATk+^;8PSa-@d zLb-vT)hBVWa&O?bE}+!6a}$Ci&88`fQ8w+BdqpT!f1Sgj{Oexz`nJzfSBARt(G zK%D{9(a(|yNT}00+IW)eJUA~s{`&|A)*a4+z)A75WWo{Z^b{LTvIM6a;lR4Xc^Ei7 ziAAi_d)lSVq0)=AVclsz3hh3mEmr7#WZI9BHmp1COlYV3SznSDYV&kVf`^oz#iMXN zy|0bLtYWg<0^|Zb%!$nIOB;$sK>|Kl+BSm(XHaEP@GJPLOnhiicSU9R615zcgH#n z$|a;M*5f5MX{_=UrNwk2fOSVO2L!YHtklnD5{Foi&$6ZxRN|%h`73=|!PWDbmGjLd zK3I2rOTo9;&lVD#Sc5N)EcVJ4+QtYbuCg`>;`WW9y$n>afwPm&D0x?h2vTNeDK2p&2;L>2#Pvy*(YRd)T4gp6Nzy z7Su{fO{ld?C2F(Xs4alnyf`+O1jRag9v??@ZQ4|4FQf*BjlO~30mQO6wuB(W8haU} z#d=|h3}ywvz(xg#njmNj-3V>y18P++4+*$R{`acmQz2(|SV8_FgL z$~HoQjUHtOP_`3?SXXbi%bHWnPSS;qUUxTiKOtSQrv5~xyN7gPqt`tE-TiUwGm;kS z>HV18j!-@QnT^7%LcVY#{vE`>iDO^Iv4f;9)Y9MZ)AB2*i|58c8;@B_AEriujlNNS z2G_ATb~KLtKwM%Seawb)l%xJ&2Q!DsFGL0#J=vciI~B)%CoG|cK4qi&-Ogg1w5JIL zHhPqcKsg`B&Jv1HKcBauoRy$lA{5x@QM~cEVo4lA?ObkCHAiigco%9{LM6&3u(j7BzE4X;72YVWU^S4(iv&vpVstHZh3x^0o0a zRiIw3gP*^rdbxJxY}XSTZ1ik5gRN0KYe-;Xt=tGOLV;G+5J+M%gIf7JqgKY&uMiUK zmm9(mNEUcM>8944^tly8NymcSGe7i(rM!K#@R z8wbYCF{5_H*581_8GIJBa|+9YOO1Sp{7o)`G-f z-HElv;kKf~6{_e~Xz$-0s^~Uu6@5@_M~Xrv-Aa3 z!UELfu*@}GIHor{|4Wm^%CR~V7OXq02Z5E6z>*0|sIXIPRLM3f zv!dxnII!+;9s$n739KjK2vzpOHk_UkoZf^3>kcOkIFAyGSZP0MlNN@}<3s@Kjvx~R z=|mvb-077QWDx$`3dX^ zA`$BFLViN$gFrl&p0F{QqjnfI5v;o=dLC@gC9vTM>}g^XYw_o7NW(eq(>6F^AdMhK zSa*zL!C0KYMiZb=l^5IiM%$>&CL2dMu+`Yaj6TuuzchKfa@Hlp3hRz_4OmwtuoVOtIYXcovodBy9FpKw(+HWi#c~0>ZJ$sGE zQ&uNXJZhv0;fuy!)L&G}YGKc4ea{7B&jsT@9g9`{e=V`~*9(|sJ*+#d2EeLMOuO1| z98s;Rr)YwXRNqj-Z~|mcecQ!6j~cpFRH1ltfHfk~&-8}C9~~4;)>UtY>J$}vBWsp5 zvJrr0iqQnv`Za0-Sa(fu2Y{LcSYrbE!UB3t2WkR{A{}VFQr5U~pr!-_>kg2f z3-AyCdXW05@Xqf6#bUk9&AEwp{=?Myu3S0~=N6aIE3LdYYJoCF^N4#M+8s!TaM`w~C{n zI3mD`NK{<1MnH8VEm=i20u0iPMiXG`e}S3+)?E|41fa12R!l(Rk~J0(%V^0et{muP z0)ll1GzCDD0&D^SiA&a`FrW#Q1HDQ>uZVaZw) z2CzT^u+%NUDgdkqu;m0GELkhU0G3MtR=Wi#1Hf8R7nZEGPz;-!c;~OD&WCl^`CFj8 zDZn<6xUghx;!D;B5ra>W@41!V0r~9#wvFV4C2KnthOPR-z?ZCT5{#XfkFipJm$lnk zvW@}cXn-9d3~|Xi3XUB*2Vb&|V9&?;p714WmoZ;s>pxDN1ADohBVzpytlx-9Sh9XY zL+sK|#fW!VC*3NZf#T@^`-4QqCF?X)_tBE|hm8O<`-~>Q)_<0o0M=a-`~#p%0d|3a z#3kzzAU>ca>q6x~ z+*-2g;phMA=Sjqp^)I&oHv^zikToO#VaaL~2GCFfptuFN4FI(?}vPB zkhLLsVabXO;;;Vog@G?wZ6p|RmydBb{`~b8oWh<`f! z$&K1CP&-a)!maz`61895sQm%8lRl5o4;8;T?-l^;g+Ys$q{fGEJ14gaR8qN*$ooCJym7eQlepFih%_I&AdnH$eS5 zQWtO0Ust($eNu;wUj1gMHwv+a1R&g=ZxkvX^|LIV!V(2?M7! z@xeyV7Y{yvh{Y0|a7*5AV~e#BnN4*Mp}Id#}nl(})u`dd>mh%nGp#f)sDP zX8}nl=*lu|;{(7)^%76t`m+fMHX5YcjSBl&AUzXe!w5;dAoL87PV242F9;38p0oO% z@C!ocjj9t{|8s-{8$HqsKpIIr!o{GGXpi#{kGvQ(+Kt*vP#YU!#Uvle@boQ<|;CqRAHl6od?yqq$*tanJcRD_x|%q6*hX+ zrBGcQVhc%FxahMO!q!Efh4}e-4WlsPqR%on;;SLPGQ{2?ap8i`$}sVFB;sq_h;M-S z`Vd=3;=;wA^?`=-CXluz81f_Ezd_*yuZZ2UNF**!v_bT;$mv zvM%zxFCy@ZJUiV;e+uc{A@(sz3m15HW1=60u~l(_=VJ-N-pfb$HI(8VW-LD!fpDJm zg$q3Aq4uIawj(a^T%tCIz1%jhP_2^Kfq4?yKO`((;PE6{)%`y<2Jnp0^uIB~)?YQz zeA5XVJxX<;T$yOT;}kFOT$xxr>J_~Q!Y}YlFx0X2Uq$M$(W}==lwIJd5c(eyf{k9N zE)Me=I!xgL&ozm~BPZzn9C3l?S~qGpKzDd>c@1O=KFOh!=Qn1;7}+srdySt#YI$gajKsQga}&M0O`32^V;n zjp$Ark-3_;AQaf>QQ85eO(MISP=pISZEPraOHg771vYw=dw>#09O4C@IGe06OcF>P zHhT3C)B~h0Uf>B-uAWHhu+gjE5B1K8tRn#k7kD~j(wnSLdi(-UM;np(Cb^3ngq}d? zp2!|dWGO@;T;S=>Pud5eE}k!$xE_RW_l(MvsyQl$=C1h){$JJUKR$K@yZF z2n9BJl%YT=AP(UIPk~L<9J^1tQF|I{Pm!8%f#)fxIh9P$&@sYBe~d*?eU?#rMi)@8$1Jw<{V6%h@o?i1n2O0 zC66Ha8$82<4PAboX?_6s3)SMOSKlZ?LJS2dd#&-VpQXTBOiY~1UJQV-swD_=*~>^7 zQA~Lilvl(n%SoJf+AG-JwcNx3rmr=xi>q%n;UJ3PYyi$WV&UEPIt#fG9?=#ny2biftt^L@}}LXzn&@F6X+pp}(iA;~wO?cZe$Pg5pk6CX13v_auhnj64*X!zSVsv9 zQ4H%WuujJ-Ckcyl;ipYhCrwoP!F`T!5XEr*2F~Sp%_vl@#`jOZra=;0z@%_0ubCK0^X6|EtKyYnYZNEH}vc@rErk)9+*L@`Dgj2^$@B0$cedrW*T6P4a&;e>-I zhVv|Ns{55{gu}V?>L#3OHaH65Ad2DC22KRAa85nKq^vvjI--gVpjeL-Ik#R9idNPu zlG=(W*49Q)_K`C0*nK8x%*8_c@jMYAiV-A$Al|RU`jy7S!MpZ&ep`WSkHsVN)QyI@ z_QplCCK4;680*VmZRS^+5Ge25n*ob6hxtuR^99h;H0O@1?-jyA3<+zolYXDkJHYBe zOq_G?0f70cl?Za~y+|2ROt~+V`}mbC66c+JAGWV$nK;0-Q1i{W`racPL@}I?fb#*d z@Xq}M49*I5&ICI5l^OxAzK@9jQH-F!-|k*{q1XTtLlhIsMRRkgxtw#)L4U7Q$34io z4-{1#0>#0k$T|1HHi|<<6-PpGxL?U5QQo-^XEQ9%q|eQ;QPky#VqN|qIer0>&1c;|kP-&Ww< z@8FRQ>PEwy`>mo`oeBDl3qhrn6_Z=xV~#yj^C2|?yC|Newv0|n?6nsdk1SCX(0 zL&92WIQJ^Rs!U9rbFU15&8n3Ma_&!&GNPEW3}p}gW)+F^&fSw>+(2=eIKcFy=9_W# zg%b{<7*2KIR3jGNxmUyBY**(@pmX1$5#Z{pK?I0m1T_;#zI`NqmlBL~_ETjYjwWbs zp;!coA&QCBMRRMD9_QR^qrZ2k;~wPP>xn8xL9qcTa?ZVhjiOIfu`v|!Tf`cXDDT{( z*$iuB(&uJa40So8SeGXO2mc$dtnkh~0T4f`-OikQe9>6RgoP-E^$M6$@Me7KCC<60 zn5deXsPqH9IpH9R;j{+MYxw(Bgu^-a*GxDqZE)HU4x$)N8gO1G7T&qPZj$DvO?x6h z6eCCnK}RCsoqNZk2|5!2q8LFp5WJnBWDo@B+~3CL_^Y}(GUuLQqSBpCcTtRYfzca( zm^?vwhe$Z*-kUAxOc3yE=^Yc3K5P3@7a@vu(I;U07=J|^ztV`uT{f6-5XEqY11ArE*NSjB=bmT68ES(wf^ZPU zaK->3DvpQZI8x-C`#30CS+5DyRz$J3PKNSCQs$leM3Xe;Vxj$* zLIj9n1am+z3x7>KL77GzymOz$Z!2)_Gw{eBb)#X~2NSa|2Y8-sI5oil;X{jf%WtM7LrKold` zZ|mF(#SV}dqL|nrH1{Aimvin1(cg#FaSw9theZ{SL-8mna?bszjp7MW#dAu)?#R#4NL4`!6JV9{Iy+UH{fMe?B z$eeq56P50CDv4r9z;GujRTGseM8Y|DccO8#rz!~ewN%B#q)!u>x(HFMixjZcNK~Fl zRJ_E-JNFtUq-Pke*96B+r00kcQH-%Z80#h~wF!`O?sZLkwM|rdmo*?9L@}Ib;5159 ze1yX}_eLfhpAF6ngo7xC6AzqNV&R;7tVvm)&wf$GWGE(*BIn!_p=f2jUZl1ninX;F zl$($;@7$Z1q%ju@?MDg`Ac_&R0>P_^N@}9goH%&r{wlw%z`3X5kyGkM!<>8bqFGxL zE20?dn_z99sJua-ymN04EY2L}zhRm$fIg%-cU*lP2@5eKtbK-a{{mP;h>3IVLjZ7A zwGu(jJ&%+T#gs=wd1Rt8oWyzOK9cQg!%ZAuI4x$*&*T5M|EWC3ci@_Nv z1v&RYlKL~PxcbHu0iqbeq(m}LrhD#%Vv|V>QA}(an)@v^mviplqQ3{BwZYDPx~Sr8 zD9$8B&biODQJf>HxB!aZCo1zuly~mmvl%weq|eQ;h1BJUVqLx*ILi{1C4|E}_ho=M z&pG!cMPvOyScqa+>w&d4QCUq`oO54mqFQaD(hu|vgo7xC^Am8kBr2N;hr8###e}oj z24@@LAd2Da1kMg(;hp;qlQcJNekB4#F@oPg@EZ~E&i%Kd3H~4gL@|QDK=5axvY#M0 z=l&-)$06$G$ejCr6P50C4vAu%2FA%m<#?iUlt?(|ev&Qd;~?PI(oqwWK5NfV7a@vu z(cfUZoTyw(RL&C{@7yn&kS;RZ^CmcMB3&g$L@~xYV7!&6+#o>Cx!*GJ-7rz(fb!OrX4Te;QbvIn0+$^99fYRlBHO zea{dUVn|pOiqZSrCjsjlV&a_pHvkx^I=CR`KADse#gu12d0LY4Es68aeOi)n1La#2 z2beBt&K+0ZOu|7F!?3`J##|q4)zSa?bq+8^u+kiW{J~E=gHKqP%lo$7a|X zlRh`YHd2=(igo!m;A~A&ek2^;xo-u;CC<73STxqpgoP-E^&7BuB`G@zi*xR~OjJ8f zRQd_Jhj0+ZaQ+0&{v>5D;c(7D&6T^5yiL-jGIZy^(5sV zBH^6-O}3z~gMeR4|CpHcS$l`N2vMwy?n}liMahaYSt%ek-nkb~4n}e&8z)?W367gc z_b1cKN6CVW4}-B(vhq-}Zk0LbUdqJx5FX*r0lmx05DubPmpu-g$C8zDgu^-a$4ofo zY;Y_Jd-vzn?_MLBZl71Ujt=qD`gC! z@XmZJ0A{FN&E5?&rf8(`goGG6(o`T#X{AgeB+ivjF%eBN5$T8ZG(tfP9c3<1X17vi z5(?+YXPZ!F+MvuM6vWU`76N5Haqw<@zDbswCW}ZNF?98Os4pdT-ia?QT75aGBZjWN z7V4{8DJuzpbK$G8=^a)#J?6q!nuv7QvQ7lyCm?KTrEG4cY$OWKfp1}pb~DuZHM7yg zqtDQ7)HR5qcg=6$+SN+g*-F_#T)g|VGImG4a!MEK@1(`98k^>2j{rYm{j$-dtOBC zGSn`T8t1kzLe0uDU7>{~^1I$P_;5;1hnhrn5)wQ_%J-O=(6yF}|CLzjPl>tOQ( z-~*b&#?@DnkP!bZ(*6o5&WIFe%@z(s{O!$F&2^)f;;i-bkv4d%#!1wFstvwdJGEG< z^BMKia*3&q)a(NMOR1V2R?+21ab@3gq|_<>dO2rU*pnrShi89}-v{Y&Jk#JgSncF`{R)5HHue)JYLoq0&D4CO4V-ozt%1rnDyUk=jzf$YCm5GPgb1zwt86|&S-5o)lWkh&e#-Z zV|6%VF`Nf5oCR%^yKR))ZIqkFaK=4TtgR!zpbffK?c;19HdZmE$l`4sYHIw`J6r3+ z>QaaGzL!@5(2?y?NA+gFsH(q#EocY=zg;-!*#X@!MIHPC>A%a%R=MyGLucewQYYC& zOtNqe=d`3wGR#fXe)qqtJzy$g1j=PYr!ksTF8?;#II$Eenpi6TE{K{r_F} z>#ctleeWoG0G`o0=#_v4<5YXBxwc@`PYV}Jap%g&st%{KwA1Na9_h$@+mTz`Q9P`K z!|BK_QP$xoUF`ni&JC={+DJ!6r@oFHC(4AOOqSER+AeD=%i0|2=-8uM&knuP9l2pf z?Ujt$cThP^YB#=cXf!*6>aA>)-^+^Zu`6NT z&ZBmjms#co>&$a@nKxPHHS5f)c9{h%^NwAS`=X42Ef&QOEbGeBD5CfFLs5>-z0%V= z_wL>?V2tXb&z;T^cIg$E!eddUc~LIPvKPzRRpw@uJ!PHwq*-nTlOzBr^5RtY=r`c~-eEs0dqYv8>1oc14=7BFROJT4EFyUC;M|Ml?|yQNLZ) zud=FJsOeT~*6DmDD4R{E43^zFs7O;|@%Cgzx|xUbZM&>KEGyFrtC>;z`&3TbO0w~V zJ{}(i)th3J|CAN!XIJENCOr_q+*b0LUCv0BGc0%x#cTclg-7DR%D)Ck$e=vR&4d?X=50$TIg^XYRGjJcdlYGY{JpIn63R5mbb&wF|7sS-T=PSdo8< z7`4AGw~|-15xs0zbupiD{1n)&S*P=EP&QkckF)GYef;5-YAoI=tVkuF>GY{+mnE?* zm(OB{Yi-nCjml|TiGnZm@u(hDZyTe0ZC0eFU6CjzT_3>QR#Mk4Cx+!j`-0BX;+iXI zWS99O%S^P+^xI`NXPGJ1nN967Td~ZRc17M`McUdG>5L+JZ+G-rxstZp#Oq*}-jgYG zGtY~+ty`2~SJ{79W$#*N_BLx|+Evz{RhDgC*++JngIQ*-b!LuT<}hUHojKI5$Y@si zh@c{Dt&L+v#@H2^%8E=bV$>$8i_YXq+G!&?!LI7>Sk-gv)~wSxD=3?-%+DGc8_|G< z{8o}?EZ(84$l!*itz@8G)<~8$tf9qL(%z{3D=MdLB@^(4J|5$O>g`~ZpTdevv@0@; zNlynbx0Ot_%UQs3zH4Z?mCUuv{DEaIv(8*%m${y0uCdNsWtX{yWp1)7vV#@bW>@5Q z6w!NocSEbK2TbWNq8_la6%{Q;Jv3SE-5l^&fD{=S8MP2>I*6Cajl+9M=V==~7@<@!MW9RMxcisAH zx}{?rUATvH@UXV-DSFy{h&hor`UbdDO zZkJb^<<+#xQ|$60SzbN6BG0oTKD#3ED57^rOpK#P@2r6K>f6x^L77vGetL;zCRt}D z*kv|nnJLzpP3+a+~oNga{YqeIuO0ds1u zHh%5xa^Gc4S;4b$ftJ}bcs4FJy6__=`+iXEON}C*vfBIcvty-JceY*L5SBNH&-+fx z%eBiJ#qx$*<>lGsjbnLZ?21feMaJ6|nT{g*Z2Z=GW=sysTy6BzJeE1zI&-F7=3wfE z-@_SaX_ohpU6FFENEy2#PoRiC8y}Cg+#4SY%KXFVCl|}CVx3vpF4N00W$R3jUFNf_ zLC*vgVck-PRUU!vp&42v^XfHTfAv%oI16w7?jI`e@zen?m+lw+A??21%mMatV1aiNIb+g0MM zO#d0J;g#*ut1|^}oM~Q!TenEEtE?`otd@0VO|yn#SK0HdGM{y2k#?DWmKkfE+1M`g zC1mQInPgYwWmb99pdxIowPZz_+Z9P;McNfHYHi}IO#cOKL|fTaox!T^tfmLwKTy}K z)7dE~n@!4(S@s9W=G^^NEwgW2kmu!W(;PUlZ{ zxpx@T&7cYUfYDXOE)5{v= zE3zWx?TS=o(oX`IJJ>4O<#<_+93ON%J*f4d$1XF1Wh&O0HS97YS!O-!%sO_N(JZr} zU6FWJB*v~t6BN;VJ2~F!V0%<+c%ohUt4yJVd0xC?-J%q`%G$HaUboI{Yu0FOS6K$D zth04xo$NB-VVT{nGrQVlzKcw~Gqdc9e84JyFQ^DxYoD+pAK4Wd%!=d|F={#LqBGsi zs-TVN0K2M3v8spLty!ltFDRR>%w;TlaZr&;#^PPgimWgX=W@HOjVx=O71q;6?OUmw zww3I_7y5W?3#!*^l;6#Y?6fPgpGp4_yp`;+%Q?z&4h7GlC$;`RXqS18WuCUqJZYDC zm1SPG&b(-sd5dLUw=3fC8wbE$yCNk}MDOkU{8n2@b*3DC0LBF{S-M z8?xSuCG9GEl2!JEb!G*#MtQr+!dYb=>&jeqnF`CSZk<`pF0&3Y_0Ej2D-y{nuNPE= zt+nS_5uaU=L{=oeh*696TWuxJX(QU$uIg7<)y>rOV2`Y>S*No}P&S(ny;ydSpdz)9 zsIBk!Sdl*F;moqj`j};XV1?DlsC@vH)1(IC3w=Ctg6e(VC_j`H8EjW%6q6nfV9u4~ z+2xF9Ib(z8P#vuY$Jk{~W0_N|Gbh<)&SROgtutrZWiDcw^X-Z(XGNCU6lSUat85ReY?pQBPP4`iyUPAzl^w9IY@c1`NtSucI`fEK z=6Pi5oq5Kt$Q4%k#h@Z=tzBnDuG$rGCKzYLy&^{Kj^$PouZ`#}yQ)jFs!JqTY$fWN zbvo});ExuzGM{4Em4k{TB2io4;jD-!!F2k#?6PXGtZG(R&5YV3sGKHM4`1lxQ9G#K z6r;S46=`5sB!)>x1DM-N8rkI}vz&y4pz}0I>%n-t%;qdJ#X7U8U1l4W`I>cROS{bW zEc11{BAr>0j&?=5qln(yZzou}lIB{&Gwjm)GKJped68+|qIc{n>&Ghl*gEq=v&Q>& zl?`T<(s0dqYQ&^FSc17m0BD0DZwHfN7 zGd;n1RU6T1c2zHBRWGtzvv|2aD4VU!tt@+UP?6Tg;@!!LY&Q?*HoL6fS=MeVtoBCj z2dJF3l^n(w`gj}+s<(qt{sb#>)UL>RCVeJ&D>-GC^AF3p56*?&{s3T|P>N+fXjh~hD^kX;NF@}}d%HrS)mG9;Yj}CPbeSo* z6HP}MP6i; zCk7Q^Yb}KpX<}ETH7oLJ5u=uxXtkAe(MGhnUDX{~)$P^v;3qihnsqwg2+C%YGLK~s z2`ch761DaHB`Y%0Jeftut5KWo~1cTdXrT+hzXBGI!V&`GXbt&92BH z6w!P8Ps>R;L~HndyYw?m;iP$99Jg-KQM<~nvdS)7XI?aGoVTm&F01U8b!9i~GVe<= zcK2dQLA$#?4ID}Q?#||ANo4AsS;DSJSyp-JpdxIom1jlD*%hhEiaeQQbpYt2Rw>D9 zD;cJZXhplKpJ7!$t)>TWCF+`WI_02j)&rAS_BTOAMj}yL-!oZ}X-THj=Ucn1?^xCx zE3C0b?Te_KCY6sb^zm2{RPQ*W{3=%D2fHF0ne;jUb6d$8yPTg{&eq^L)KlxhAMG;t zu*_Z7nLF(=53d!_V8L-(dwr=F04k?R4a67vc;p1t z`=?QUC@V79uE;1RJsiN?R+49zGoIy)Z51??XJ|b*#x8Rj%ba4JIms?_9?P6&t4VoSYxqjL^leOGi+Nsbwrf}XKQ1{-Ya6% z?x>5-bg$%?HlnxesxHZ@F45X%&EmFeYkr?#EAvzv9ZXxvm+1?q^I{uEI)1wd{q7it z`nzM!w{c|jG2X53aAfCeSZCWf-cEndco@HkMt}Hp8%M{iz5x%PM(NVUoW-uRadb-0 zq!g$AyKC;^d-%;Y&bBH_@nXf=mU1|Y6)#r2ZAtCxifx}lRDbDB0T8<5o$~5C?A70T zBjJbA)rSIfbotwDg5G81(tiH>rZrXR;`f(wJfyvA-{C0Pt9Dv_i9FF?+#sCrgzRzx^>9RO7GRq zAODh)oZPN&{krX%r*}>7keS}D$D9AtE~RIB_sq<$O)}mL`1HA+o!)d@xm?llK>2c? zxd*!ky7$UU+{@j|+@FN6cmL+z=KjUK-Mve`;lAU(<=!HX^Gxt8@GSP6^YoLZNxw-m zr4{l*>7smGx+P`HW8^{d5IK7^Xp5J7RLbhzztqH1mr7;32Dk>fhPp<$#=9oErnsiL zX1Hd#=DEIiEp;t-t#GY#ZE$UIopfDy-F1Bigu(7F+{4|Y-DBM2-4oqY-80=w0JPk_ z9yr?p^qc!H_eJ*&0NrutdJ2&)dhTdgGo?AwLMdNb1Hj|bN$HeyS~@FTkgfvqu2cZf zPvrjc069m_l?MWOFrf1QKTiHy9xs0*Pn0LgljSM$xAIhZnmk)xATO0y$ZO=a@;Z5g zyiwjHZnKgrwW9r8|jm;9T&S3W5JB_EQH$QR|S@;~x*`G$N`z9Zk2KM5ZYJ}`Vx z_~7u*!-s}{5k5S8MEJrc3D!}Vuex4Xu=cHpyL zT#H;gQSMhfvI~#w#v{Mskv(|icRcb39@&dW_TiEJ;5q=kKk=P|_|9MW&LMp7Fur>P z-#d!$9Yd+(D0Kp*PNLK)lsb)4XHe=aN}WTg^C)!zr7oh>C6v01QddywZb~vD zao@q*x$DYx-*XLg7q|wwvoVi8aewa4b`8PDPZMNzUqc#cV*d5%lDo)gkQ&q-;J=ae+q zb6Wb`b4D8CIV%nIoRhxroR{)E7o=gHi_&n@TDt+nsM;ha~ zCVl0(E{*lvkj8m#N?&_!N#i}Yr3s!p(l?$p?uq!A~iu?=e z*@=37MLoMv&u-N78|vAEdVcqOEC1n{D)047llP&X{ix>v>iHA(97H{Tp`Jsi=dfqG zd<69zMLow*&vDdq0`;6kJ*QC5Y0nJ#jAy2N)-y{!=b0^^_so$mpuUTqx$-5?Joz#{ zzk-jy@o^O&|KQ^qKCa{A20m`$;}$+{TplF-AP>gj^trTB9wM!hhf1sEFQhecp0rjT zCasf)OY7wk(gt~?v{4=R1ALTL97Wpe_t2|cvNggL{lfRaJmd8umB&OY0@h1bZNDBhP1{zQ(EhtC9U($mezac zNE^I!rH$Ts(kAbB(q`}X(vRNx(iZOmX{&dkv`=0n?UxrzKY5o(+q_GqpS{bZjX1eB zNz0|}-XEkL-WAd>-j&i$?<(n6?`mn6ca8K#_*yA1e4Vu0yI%UuyFuFH-6;L;-6Z|t z-7M|({wVG9ZjttTw@L@RKS_Ujw@C-RKTCgkw@Zh-JEX(jU!)`6ozhY7uhKE^F6p>; zw{*h$n{?8oAr@i~6Gv58uS?>YqocB-Zy!W7V!TXnV(R)a`Y{JVTq{zE$*I)`VIM< z_olqdeM_Flze()jK%+OZoHgMXn*?-?@f{=g41#FPHPezjqA_-|iY7-cKG8 z{*yd1e3v{be4RWxe24sH_+{6a@ToPw3SZzF8@|vr4*6drzmnte?8X%xjxvqa8zs+W zbXxjOn6sb&CfCupb9#rY=OQBV@O(sn zTiRpre<;&WEz14V%DmN8d#pIF#hsofxB~b>D}!er>c2326n7?Qp9fyFGUd?)VfJZW2)%r%(f2Lj2jE=o}WcKKs z<{uQ?v&A^UG0ckQSIV-bnDi;dq&oK?Ou&*m)fI8*UWZJTj0}Lb)T!<;JMmS zwQ5DQdo!bZyQChOS*;@LYtJ}4)_$&2*RCGdHOb6d+nh=O>Nh) z*Lyv)dbCUL)3aTAT4s8Br{_94lukV|9ZH)Fhw_@EE-tMc3ZB3A>WS~9yoC>ZGv&?N z4#l5@&zi`aHfvRtJ3EGY*gIoe`Cdk&)T)8 z>Pli}o!SlRN1}NzcgpDSR@2^Dm|78m|7yj>IUY%gsk?G5bE;FF~xKU7yt-E1^B+bPS7-JN53?O}n*HEUZMf+mWsP61ia! zPOMYRy9h@ye3W>gOxx^i^@0Cu|BAkMqAsETa|5E^J8?MsmwLjXo)b$d{2x6hJ__2f zXz%9EiH@d$(6%)0oG@+O`u5136WP}FaOZ@nh+YqOPN*9c|4$tf^_+;T6L2Q{FVBg( z4I0#Hpq>;(pA*L$7h~td+82rmpA#Sam*>Qpr}2B;?e_J6b3z@#veo$xVf%W(IdS@3 zr{fX3aslT=@j(v9tx5d6VD$x@6B{0NIPTU^?MC50wH!M1|0Cx__YU3CGyh+GOz4FF zFFPgbWMM)So)RZ8kN?|KqTKAr|9WdR4)%=h9lQ4KgnQC-&}Vk&oSvE0q2t@nb#at+ zF8$)25zl_Utn=Xtcjx?5&0V)#ytsmHCA8`z4o?kxzGl|e+AaP`KKtd?V&%3!FWi7P zGkR!spWoYTe}%fPCX*|#f8Q~4s$92tk zQxlr>>ZY*LIk)F|7VYs=oA6?ExpQ&CUDP47do8Wo>gh!KcBoZw#}#2Uzq3Wp4-`LU1IulZ}UKrN)dU%89j{kbR>C!;f9WtZkS9QC@Cbrvt)tXQ>X z&Kk{}4=*ZA?UeBrHXoKc45`D_)CzAS^%hcl>ZxJXniZ?jtk}a#_0+f0vq<&L_f$r_ z{&!yqReJ;~7^zlpz8fm&@)@>LR8Z`r=bd+&Iv-wMn5_#3WsgGkXf^wn?#P}Uls!4q zp>}mgyrkE?x7Ov3eh;Wm=^fesgTyb@#DzVOcmau3@Vm^4muyyiL^EgoROiEgWa8)j z)9_oq2s;hGPD1@7Lk^cC`(q@JQIp^AiR9Zzj!r6D%<=GMoi;A{5f|19oi4SEVu>grW@?l-HX?!s5H^7~!CT#AFgtUPiZs{!N!xw@wgHhEACaD$t z(FYaG52ygBs35Fuq$A~Jf3p@XnxtjEjVG+?@0G)A#K`dBPQ_%TmUIlmYqn`GzZBP^ zK^pt}8IJ5Js2cxDIz|?Lo4pF}$o|&&_Leu0-Adh%nxv$>)biyt_1V4l7aJVeQ;kAv zd@(JW)k=$P`f`iZ=E=qqz(cDOMc$|gyeN$M}h>-T`Vw>YwAg5*0? z6E=_=@6H+BJEg(A=io1bsl}?H*!P-RL|bFj0)~9P(Iu1P)#D3|?v>H~t+cETZ+69< z1a(lJ()%UsHpc>=l$DtV!@+naLTG`?)1Kq$p8jrH_ulF+^`qujLAix$xvF~aXoEmo z0$Y`O6Z-*fky^C8sVI|G%PiK~ccr5~p<5&;Hp4cd4nFXyD@!_#Hig?wQ};-{UGM2F z58KGK3r3`ex`FGRHwLUrRDkJRn^a5&;6jz^vB#E}Aq(==>Px4D25GgEcH$ z-7lAE*_EO(Jebje6DeQMFX@GPPNp)~yr9W{?4Wu&uTpQ=7MJk&4Gl>C?ZYW3|4Av}~6As=s-Q zm?mr)vYn)Ny1s<)79I6AU3w?I$?J`p&#+0aRUX*68>w4nar_yX#)fN5f-t~u(%|P? zjzYk~-)zWsU|4<9yW;r;VQnGF(VS#vmyFJZn{;)^{iMllp}rzl;mGb~R6iqL+gtVS zNK1{0#gC=4m0Hqq*{2$kmtXR?PK!%zh41V%61%4tt`Y2fulk!{i$j6kMuC-$jXe(= zPJ9YBx3q+o&EinR81Bp5dQtsHrylQiPwU#FLnr*gPkr5tM;rENZP;J9nfjYIPb1>^ znA8|l`3s8SALdu0)}GYX8caW9Cobc|v@>{Oo1|cu4Vdx-RMK%WXp95O{BE>MVPyi& zsy~eHZf|XDjs8}tI69M4nguHDHOk#z*ct1{aVL$@uL>4SCX5h`V+CC1%MwgfLhT!({`J^#4bd76jm9T8OHNH|;ZIG)`Q8Hcq!~r>1E*13O4FBV z5*;)Oyp^aOH|l+PeZ{gtztIs5FPx>clLxl`FQbwbdOK3<*D|-UN<(c+!TIZtQ}>i! zM(5;5qJE+&@FAn}t$O9Gf*!`KEXK?U`3rXLA2xEo>7?&UcmXa$^~Z+6Sza`!ryo95;$? z)|(xhlG4N<(+qES)D~!a+Bf{o;?m+$Fd>_%eR|SJ+GtFugh=y9l+i~5ivcNhj2;-6 z2yC|M1F26NwcZG7S->crG0OCy1)x8R(WlZSTjB+zkJ}x{@eJ@#n-jY zFC3XB23LgygDcSw8)2L|fq?%QwXD*c%@sr&X*GrQ=GJ*ecf4m(eS)WNkqxlYuW2iN zglU)q#^t)M6;?990nzg=wrO-hnH#7o?4#$IUCh9%Woi2JWG2}W~a(BK2s#t8w&fWvqfiQy;io?ina4k;d9bLcokFFbebzUYY^>uH!K} zu&(Lzhdd^mJpGwZva0z2PLH&pQ;|3}Fo40;B67&%4>svi~=_~0Rjlj>`oKS~|O};NM1Uc2zL;L}?c}C~b z#%e6Q5{5=;T|?WdKyL^*V%W@u@95s6lX@yxJ;NBJNuAaV4xU`=_9o02yL~Z1-3y7| z0EmBKZ*sGUYlC{~4%RB3!)6ED$JD=~iGL*>l8z21nw-!&?d6!}F-=kZr^Zx1t})R) z3Z3g&gX?|soMMZll+iWo0?y2s7D=f4T|zG&u=sJCiB10))IS8=VPA1=>)E3x^Yp5l z9I7>KNH0uyw(OhwQi*0XK4WvX##1k#i<3Z9~8b;&JSw1gLkX%-K|(L6auJxm@m3SBXs6b$-tqs+xZ zQ>-^06+B@KP_2gkW{Ju8y-$wpZN_6~w5M}D+0!VGUQ^gmzO#F0c3}geKH2_O9gqXu zg6WlxXVvL=CywzPcr?mQRm-Jvb@l1cwRd45yi>$6O&hvRR-F~Fg1tr?E3tyynH0Fs zRWr)2i4C}Wfp-68jNwiTGaMlHj8VZ$Y^`WJDeH0O@jhr{?8z~yxCIp3GSweA#MO<8 z-m@qdu<6z?%9S%e9SGoJ8+b`=ouWlo49C{oaLMX@7J4eC=(UCo;6^~bd%}(8ciI3f z@de%-(abip%t@>pTBPDW5Of_zPj1rv0ozJgPG=6NL-$VU-MQz9?CIE}`kq7n4|ThY z?dD_4PGbu#!sxW$wJniu>vY2VP4u0ecEys8EIKyglN0ew0Se@v!s@4Lx3yo6^&2;O z*`BZ7w3x4T%rW+~%6NLsra^6kpp9R%d9TJaX{oNS4~$XyLGPWHadS|625au7o^ks2 za?$9}ONC1kKU1T(ggv(%WVOKs%%eI6(3apQIRT!du3jkYcWwc9!cVVc6|PKm`7YMl zU&?AqvM#7^D4uGn-Un2j2|9poJe71*Fi!da{RT$LS+-pvg|;3%)un?EkG-z%Q(;}W z35>m8TVrgjBEY&#WBti;T{GAyLwP}pdP>kiMh=JFnf;%@L!NGnG7rdS&o%H8{g?Dq&ZuT5%Q9QO6ZEEQn`hAeVy)N3| zSX7%AB#?9kP;x* z0y1m_SE_e+{l=5=j6^-W)@g0=u$iKn>3~f(&LGWfqdkFQ8#@~Om$9%5n1RrqAP3Cu zcq4tKJ|M|4^@8U|Nk@7V`pfW<#uN)+V9(HZx9zLG29edPH;jn3DYF}gF$_Vy2NOWx zHweB!Y*1|DKJXfmyAQUGO=QRkDvBfuDN5)x?loVsQ&4pj=Z@yw7avduMid z%g)+w*D&T=uj+v6Qw)q8{uV+&n_nh^3;e?E-7PI6E4^DLcb{^nCR<)VXlaX9e{@pw z{1*xjoNnn^U3!ptV7_soMNb59ut_w}x>W&1n;WgF!;aK|Ip4zg?lyMwiC%gO=$KTa z&;|Y3sd@t#vyN{6mvoFtGB!;8rdHq<)Y8bEU@pX_`m08v&x3oO6?x4lvXoZ1e)AF- z%=~z*Ct5&jTN#y%3x)}3ZEK^@4*}1c(vtAZiS9MFF$%OLw}saT&}6(Fq&saFbpI;s zPE&1ZXqz2wXtRy8GmhB(+Vq&qOkUwjf$HBx*Ct6*_D%F}03o|Ueb4&#TR@B38LTI? z35VC1wf)REit(VJE~ zV?cGZyh}PBV>?gqvkkUOwKv+eT%QgpajAX_Pw)oUzQ6TP8@cF9#d+Y zu}qigwfmd3Y>HcUsebkRW%F%l;EUOe>`jC04m&F7b}lQ@(I}GEFiySOl9JZ^HT6XZ z{K$be?&q0B(`^WQT3NwJ{JTO+nA`ew_1DqVH!J^Ne~WTT)$Fi}E=P(h`<^4EPU+Xn z;eOy@& z@zltbx&8Z>a%7iO)z?NstR+73SDQG%bg7ghM!Whp5Duak&KBToCYCo;md{tL^-g&9MC@eQt&wqAo`i>++MpIUcDTC7h299IuLV91xdEL3pUv?L%GpM~lWf zMOcVpSeJlxAyPR9{v0#}yT#20R&(z~oW;UJ3P)B;Y;C`BQhfq^(RO*o1TPHnsjY}&ZHYTxFG3UNRBf!ugg=iCd$-X}3cF|m))+z+X_oOAyW z{k=mS_aNtMqF08xzKdl1Yc0^YgLE1F{YECa!kC}j~raL#=RHpgGo&5=3xMJ6iU>Ew%ItOLfHC}mZYvVurB=e~w5=v5%# z*U}0TlRj(LQx_qMbIRKYwLL^pCx79xt}#jV=fljj|)VAC`ND{1ph=Se@7{o ziGz3U|M1%iocrH+WT(2(Fz0@`Xx1CViYUhF^d%?-QOaEc<(+#$usO`XYnm^B-mW=! zTz$oS`u!Bdkg&cnoO^j-J?gW#=l-ZKxBqU{N(4Fg$4MDcO!-MDSMn(pNt}1?m3+nx zl!|5!?cThv3V|Ssfp`GoA`0HKyL`C=_Nucb(6jH;JUgyFi3kwI2)sT!&t522jl>Ye z#GXZSt5b71&t4rpy-ywSAkVIdD%OHxO;Y4Mdrcd~+MXIn$+3T~pRoA4C z*HQ4gk1vWk8&RyY8v`WTr!*oE-mOPNzCU-Ly^$SI3;`jE0VM+{(Wm$ci1X=*CLX_; z2kX+|dy#Mu#c*B$PKr-yN;sTPPch*%wZUmlIEZ36uK}kevG6{KxQB3=F zXtyP8-l4a((|&`r5yiCAq21A^bRc=on|H(}xZj0a7Pz0@!9=3Fn9iaAJpjnUzLz(&_q^mZOi%_iwD8{p8s_%@%ff$u)=+o;h@qZP-3?l;GcMofrJK#{T?>?;gZd`pMNgXkC z^)U_YJa?hcS0scOy3lwua~w63^V{RlyN50O_5=~N$xxd}YMj@eXrneoL~SP2rZ-fk zk|6K1r?Yu9)uc^6dlq#tV(1+_9}wR)ROS){@3FswH18MY+QBR!7{t(FmIG#4LuCoU zaQ=FkiDikIMLUjvAQZ&VQPu%vO+#fBp>W=MjR|Fy4a#~#K@1(`N1$vX4&GO9GRx{) z%ofr`3|)6SbhnW%@2R)h>Fyw1#L#v3KzDaTYZb!&Z|7xPpUC8eu;)fu9 zu%U9Gp|X$kIWK*XEz1K?=hwzQ6OZnt4^yWghTbV>z;&vja-yMfjJS9oeaeJ$f}tKW zgXz=cERi9GPWCs*E;m#z5*Fv7FPo??npw0(dzDZSLr1v{l$#Be>x9Dj=bI*!>ozEN z2n8{86lWvcu_O-8I~SN#^;ui2k$~F$Pz!6M8zIg&hc&V`LJu_3jSyn!Z7d1Z2T7Ip z%nzDm;h77qK`By43|+lE)E{l6Jkm%hLkzrMezXy774XZC;Pa#8m&+8*_BgR2hR#+M zY*iX5l?jaZ%2fcv8MOS$K;q2|yz(K0Q;Zz4sHDcl2 zbG7K)0T+VZ^F@sSS6>YxKoldW8ExmF3&kQx3{gz1E}C1Ln#;N9+UW0#7B0G;sA3cp z8;~OBq#M{M`a~5QLoqs9X+)yDn~r8PtdU8dn_)53<%nWko&=nPXeFL-cwe0Wh*N5} zvv-=r7mbxnScqa+uK+70T4_pHoWo8rQ8hJD>5is3;UJ3PvCY+Ww zIBf_AQ4A*yIIj~6@3dbxNpsVtJrN*^5u}5lBN6bPyJOJ=orwTZjG!9`-i}r>2!eCp zZ)0=3qHd1tohBJ3D&5U=7sYrN7`>yF%xL8uBH?^^Z?>Q_LBOx2cT7zBtnEu(gecZU zpMdS-XywCb<$Yq~z4*r_qz@VH`zAPUBK0FiL@~xeV9bqHatM%f<+&!l921q^WrGO^ zQ4D7|aPp#+p@hRZ^E?yIP#c^Pgo7xCGX^-LiG_3LqfN^CeEv#QaXb{qks{~N$3fA` zdQG6VB8s(jGL$EhGVjtSnxruo3+=}gB0v-)m;-`Y(aMZyWg2ntPJI@?t-!C(z$4ex zjfTC`WLnXzbBPsEjCBcE7ey-z2$Xm3i-OHz{sPl{0rUmUx#Q|vN?3^h7Hd&sIQNZ) zbAL1@L3t!bDIKGm_pOcbUjG|->-tCPTh|}KJJS2RA$(hVcl2#nerY_Cqdsy=d*qh( zla9G=^(P&1^*t7&+j>MXtV+PDNK8LB)_?dgPerPzDPcMR57)2qV0~}Dz03fAkpxOk4CA^+5_iPt zYh#is9s}`HxEX;<{tNhg3KnYrac*^;07O4;;za>o1VB=Zl0X3W1p*`m03_G|yd(V-!VpMPx6OJewHfV5eLIu^D-`Tz#KX7a)pt z!RG)P6rpQ8WaSnOG=zW<#ehZvXn2g0M?n0MH9P<)uV|oA1cWFCG!{T( zh=x0|#+U%~BWoNfBZ?`11Lg6g%pFn|4qS)ZCf%2*tWd(_IN7gEKWUb&a*cQ1~RQ^ZEZ;DaYlRS51 zZNkB@PCXddk+t3iW6QtCSg1bB+HM?Kr+{%HMma(l{E>A696zcY?8rKTM}ATt2|TiX z*7j>$eWz(~5dZDq@K_gtb)J~GBkMdm;%9X!20hEVB&v7~idSQlDAx|;u@35e;`_J!AsVkF3(9j40L>k3hK$DRW0w z8D5#~TIEO?QB1ialpl{(9wTw?$a);&#*y_HKL0~qCqYNn6QTfB0Z=7YsZ0RekyRxC zpt22sOBCQ~0LZb5hXA-EOAY|=*Z_D%0crr?8B*tttY@GYFz?ymKTCs;C^q=Dp&Svb zJV)Z(krfeZJj;5H$6!ZR9Z`873-vwXzwP@%)jd$%9jp9G!u(75yJL-)@_#ikfaj2Q zGT`d_olp=%M>znLeZ;}PjK2>fa6%n{VFAA|;-sdItM5-zM+{y4aID=+_=Q48NC+`> zp%ZB4F={6F^8GRN@kw=@gMR4jq=?#CsGTM??xp+FHfrZY)UH77Qmk@;1o@ZkFR|Hl z!KBU2roXA15kv3hTR^!Ht6U=#{w4bx063&}^-%4GHty$MD;nuGAt8p2R6H(0amFbH zgv7mE?~Ds3Dlif0Cw*9)?lBNUM=1%E2ji3n;&j8qy;T383FQGi!p}?{r4*qchK}+G zP|6So|1y0UlPot)%8@!^=;{@qUY^wXm*~qEtzMDT5kpt63iT>+N@W7zUY@TKmpkB$ zy6Lf(=PR3t^xMlW5rk)e;Ehwl;}nS~xR>U=amEo44t0LbNG2YAT2!a5K@7cX>VT_O zoKiDRQHYCwS-zGDrzS&HOkmu^sY`r_q4PBYpD#{{BslIRd7p_b(nO?p)$@dc7&=Nk zP-5eh#)QJX93N{!X>5byClticQCfO@+)rA?gDiWvBp-`nxq23~$|gGVl? z8wq>)y;aeiX~c;bI%gMfc8*gz5hVZ8duJeVhAzL8X?_6sglh5Bt1p9)5JN$#raA17 zfb>C}(wC6<8$urd>8jdG?1oTZJaS!qB=CmNP0e-U>id|G5JN}$6iEGvhr1cnAN_F? z;=wnAazxZVhuWYxC6@&G8$pAhSU@*|a!u+WDbSjZt8WN39WnH#j|9x{I3>r`JDNfly!rV=sO>xFeo(((#yUDXfMEVy(4m(8$9>N=MMNn9f80b zJb9WruD%CJ9WiwE((!gTcnXCcCLzSoh039sWvQ9m4W6>`x&8ChaSpn{^Qeeg1*nxL zHSPvac^kEgB5F@T?a6qh5()A*c%Edlsgg;Xn@v@zn-N3r=BI%o$15H};cxKB02rut zHM_y%DH_R3NQj{$)dZ3fuhbwU?go!yBC25`(ogdULO~22r2$at#Vd6Pg}cF1&xBIP z1|^bE5JN|K9w-fogTKMk&?L)ElW0;$3|&1A>M^9w-{6TUT0NfB5kpsh3F^u5N+JPp zH+Yh<>5Wh~J$8d9(L|&_Np2#7&=LqO;+0q8l@y}jZt%2Vi}n?$^J^x>#G}v9SE*|d zL+_e2aJ?R{w2fC<6BmDj=XDcKTZY=&1jbFA_QZ!6I$sy?b&gj$5gd1er?ZKzlZi<0 zstiIw3>~E>P`bw}T?vJ|!PDJ@($xm#9YR429iX0ksh^^fqQg^&?W{Z}5C%lEu6$v=5(3upn>fJqwdQqk z^{plxL@}HVz*$EuyxU%f!I`Gcmq52YT_eENw~+`C#R#_8I_^TTtt5shCbk{T-A2vj zT=zEg_jGmKgIxCxQN>+Q+)0X@^WJHrxLZ_l9~A$HSN4!7@4o+FGi;AZpPOO(sml?? zy8H-m4#g`635R#!hXC=l+U?ANA1oT{C}AOrVVwom>3HQNVR0_}w2A7ZiAq1X&k+uy z7|!3oxg4)tBpl9(UpC=fw86PbIEZ36H-U4VSa>&n-6YLTn_EPHC`M2Kg1bb(JMz0l z6FB_(O$bCWf(QHw%6)#NxL>~)!MXDL{J8^WshcBn<;DHh8%POJj7NY`#;=t2Dxe2gfMPvTsJ~R2k+YB`E3QRJr%hl2LR@)RwBr`_abFPG3CBc?&DXoNSt@> zeb~O1W#RzSLd`eh>U)oH5XEpl0?r4-!aMg5FgPpJITPsIS84>f`aUKCL@|Q?e!F|+ zg<=Cp3{gxh7tPI~=5o$G2mQTL9rqyTK2TI~2owjCBIn!(+b9kdRU8S$;eI8LM0w{v zoXxO2lRh`YMp2g|igo$dz!~dT#t;tg+{Xf9q1x@txsNFtYdm2gieXI!))c=oiLf~5 zKE*^e$wZ|e=+g)XQ4D7;aAy0JnS{eR_t_?#nKn4{2nSINXCZLr6ASO$=bNOtX|sq3 z5XA`cL9mnvc;~*fXoBTLfG9?=76hyP%1VOZocn5Qj%(D-kvaF3CMwe=Xj@aOwBpgIB zoO8fALoA$gKVwqX=ks|{#mi8ve_NiYV6BYf!#Q%Di*GYLdoWEVLij zi2zZIz>$!k-194U{K_rj;GO$Dep`Wazk^3Ms2dG)?zf6&btdRHE)d079|CI$yorL` z8SmUnBm|km{QDDv4HTePXwDs1UrEA33<+zg;oPeLt1>Zh&b=}KHmg=5$hkj7%7|jh zGL${|n^h#vJ9kflaRbF=;sDc+ns3I{7fv{cVmQ@-Q;k@7=Uxqivt6AtfzEx0Mu4lY z1`!~N5!6f|`S!*iZhoq)!_frIEfk9&F+?%3x@c}~(&LLNt3F8Ty) zALFlx<5wCH8}HmdHX(h;aNjq+|_5QN{6497l?ra~}sqE9*6Z z+KMRF*2z$wNXoo(pJmvL@A_C=|`=VfTn7_a@UjV&bbMCnMmJ$|XNLcxXbKe52&BVkx z_ssy%5M6oWv3Y;tW^$3K+JNGMq z*r#?obMBXl#`=e_5XG?W0_!$@Fom!<=YHEnb<;$pAL#c82T=^?zQhEjc%tG=wD`pY z#S?=&$%#k!*{b8*pQzt(K@`I&37iLsg?H``nxwgDQ;G->#Rwh&K^Y?8oqL(03Ca-x zq8PywAgGY2lqU$zxmQTc9dJzD9GP=3Z=%wjP9;$c2^j7~rD~#5g-AH(?oKpr_EZG{ zzm}?)nDl8PQx_qMb&&$L8i~p?iHeulc;{Zjg!Bx<^_t+giS!&XB8oBA2V>ntr8WU_ z&b_XQueOOw@3IDjgD8d*4V*@aijQzO=ibPKazODvpok2NXl^Vu(| zm<+{4QskU_A{4Ex*NfCvM6tFugK`s6=AC;JlQiaHq5Vi90z@%_Rv>saQAtfyniB`_ z++XFl6*%`)JaS6iXqaqd zBVi$igtgCb?q2|F2r+TaeFy-~s#YS%x#y8GqL}jkL)v-3M^UZsKMRP6D2k|vBD*`Y zGYi=x5gP_kQ0hgE4JD1BCfK=L!nIwmh8_@*PUyY&PD1a!_udJ;BOU(F%$z;RnKLK< z-<`dmPxigpywCf5Pn|a_VsAM2tV6m}bG~!$$?mo80tcARnSC=}WBX7X#K>?40H+^i z;XC(!Sey=ut#j|F82?TyUSkJR0>sD&hSs6Ylkk~)p4l*Jh8UUIC=7Q59WK|okHCC) z#AxlE`{+m=$HQ?fb>uqtu@c7#kvdL;7C5Wx zkd+jN`^7Ao zjEvwQ2=><@dnp9hx$np2*x9%oS?9i2pt3rhLy=;f0!D5fa=Z>XN=dlRJ(nHm;~?PA z(ouoQ+O?u6+fg@DBf2vTz=#YyFCj7#U7+ z;1r`QT<2a)aJKgI!;w0cgySRBk?Y(afumFF^%xy1Vq{}24d+tSneW_73D($)dF{uO zlmIa@g6Bc-TwPMOE-6Df_|E;gy41JFstaC3@Fl%|riWnJd5Ug5VqEb-4 zbJu{yHHX=%uwMY(!Dtta*Vqaa3(*zU(}n1ta~}$oGLmyDq1eCIx@ZukR~5dsI8E}ES?USr2n9K^_QCIM#xW#K#b30Rzd#-7RlnR|b; zbH{7!WJ-V-8Nu|rvd%rvYz8$$jLd8fhC7Q6m+RbTVZQqt>u&qZJv&mz`EZ;|9l6eZ zuEcRcq>jtrxTG#wL{0h5eF@uPiv)jehb^a5ju_dLuLI7Sx?~l_;XC&=fVjwY?yCyM zT2HYMBg5JbtgUs)W{Smi?pp<_%>tG61l>V#5F^9c51hSq$!?0nb?$owoZS+f0~7}_ zGMuBpIZRpj&i$}p&25`wlmIa@f>R*Kr38HEo?9@%X-a??8NnqGT&PRVQ3$Sczkthe zka0P(&i$M~Wpz52BgME4jGJ}I^}6I5CE+^vo9sYe2LXSUt_e)muDwI22r;rLdY~Tu zNl`uGsYmWpHokK&T+fc=sTY32-521vja0NA{l`c3B4m6Nj3w%k;`OXnnd{t32zwj>WX1@p~K|5^e&j=Nya+cy7X?5xb=ct59-Es=shHEy(4iO z0JnY(NftHayYqf*H)RRl+-@33ry0@xG>-tvu!dv^Md3U1VE`CyOf~z{FhdGP8cC55 z-6Kr|()fmCEJfnF^6>)ESb@lTSWluTi0)Bl0%dwbGL@om9r<(tWvT>a7DYjHk1`i1 z*_4Ct#}SO1eN13GA`n?ql}k|&-J_fb%GrkG zG)3XM?y~~QX$i^&ih}4K9wM@6@7!lo% z@g7|7P*=Xwz9ZOT-{rLr_o+Lgd-r1T_}4SzNs)L`DBfxo`7XO?Ja=uN%PxX z>#_^Q+oy-)d??;(ED_yvmICKv@#Iko$#>X~0f}qqvL6K!-~0f0qS;~NHTDULgy;sT zzS&_1fTU0!uESPfKF4SWY#p{nT@l^8hTvK;o&>2e-(gpb4|mu>fdM=@W{->4SVB<{ z-J?_nN(|-TJM0)N$RcBpx7zWfCN<dJoy&|;5zJdTzbolOOJKf{}PC-F6GBa5dHwdf8)u2;>j+A`GE0vNY(I#NDF_k7*K z*EODWp>SM>-Bn=gA`n?q)q|oSx<}~;l&pBto1$AEMnv~x90%7i)RphB#|XCAcX{o@c-{IOoNa916*I*z@cSU3QMJ zKMY{A!^UguLW+dw2I*t7!`=p@EtH4ru(!Z`tG94*MV$WUH}9@^{$VOn1D-9-;1t?%hvFJM288 zTxx{q-slX5d5R8`>#$E@j<*@>Z0oSkM&fo6Zs(~R*I}QRxLu0G?K<49#gi-4kngas zvE6h<@aA^Y4LZ$;?x*=aQ0~T)+Z2WGuqL3x~_Ai76+3Mi#1 z2j5|r7Hqj~@-%fvbnpHg+{;pTzQZnCuzNY`j_BT9g}Xn2cqstaVfzy@+w3$hJ=S4+ z1tP0U2}FYM0uVw8q+$XIQVOoa4kd&?WT^;u{>%gg9&3kIqEmzDerl?K>(vDEassJL zx%dwIRRQN^hFVzw<2KIgln>E8Uk&iRl|ZUdIIhEfOJJ)e5Lr|8Hbp^nk5UgPbrMJ| zio$i+bp(`J5|n>X6h!wZaX@*Ga&R5?dxERAcRz^4?Gw0tMBTU!`y;qHwM-4@7!lo% zF&?g;QCGgh{!FmNzRPPL5~w?(d-pHl{&@mPNg&CTf$y+C=dTTP*eQ5tuW^yE4m-JE z&Q!{Y=$`WjaDJCSzM+tOhy5LpxP~tK8)1I{c&piA<2AM^MM89g^qJXVw*pcI<>5N) z445A<+5uaK-I}^0x_9jW*Y*jdEj8vl?Dp)=YAY~+=aAXs;x)D-ML~3r@)uA#Qx3kv z?u-RFVeFCo9d@qij@Q_()E&{id(Q;fXV`g0y{HkQd!xP>W*<6CuEXwwInFiK+16qA zi^OdZ+y+oLuEQQ6aT^?o+eo+#Pas37A>UySXS->r;LYu(QFNLS-B0sGpo~u-V<`&X zVUGvEA!Djphds7nq)8MB(LK^EAk9c1(idDO}O+<8iqm+~RH=eq#Da|z@Oh2uKxa{}8L zfykPwixdUXJ<4^UTuUHVC<@nMUlUNSNKkH26h!wZcY$)7a&R5?ZNb&ryZ0h-E0kE9 zL?v3ES8yG6RHAdsR5;Q4pajwV7$1b|1Jsr8upba?vG4NQhho$n(Y^cQa4(ri9!Vq* zQwF}nE}6((8|bhf!8_-Ti-dL94;Rc?igF^l=X@5N&m@wkDJ0)vKLaGLq04?6NPP1H z;1gztjn~-cC=#L@q|eO``&A&lOnJBt`(>D4GTH%Khy5CLMRf044X#xa$?MdZ@35;T zhCje~U0?vu6|=|1YwVj81<^gqJ3y&HIrt8{1{UO|u}AWE*tbk~yvEj~?uhQ)>n6%N z>^!4-)CkeN(R&zXeL768!>*4xzGbYlt;2pl61R`w_5pR{I_wW5ZXZYD77w@25=jGU z$amPEvE9@_@aA??0-a_=_tX42P*M^}GDYD#>=Xc8F{YYz*vSPWeL;~B-6MSqq^}c6 z6N-8C*f)?v32h^#K9 zeIy87fzTz9bV?*0DFxSIcVUON6WsYT(^25Dc4#*`HHhw~rXRSn5=rkw(vx!W9d?$0 z)0?686u`KR)1UGoy5}1XzM+X^Fookf?4bhNV1dY*su2_g(LKs|po~oC{uwlnR0L)_GH1;+Pl*tahnCV8PtvIuxG%{sb!i?$B5{DjC0|dOWI)(Y<>$xK~Xg zuTuc7!>*c?*(S@l^jL@ex;=6c&r^- zmrf0$`>FX5TyaU{y(Chfa`7E@oPhHlL#;1>aU16&%7^HlF9CcFlgOtOj_a@+3T&SW zMAlR#QWQk@C|>}jaS~}nQMeAfv4GM@g7PIrL3EGuHBg#R4z9y)BDh+6_nS!Eet_F| z)Q#(~zk{1o%hZ&P5z+k^o5Qskb>%zkW`ZsDU0(Z;PTdjRyZ;9FUz5nsN#sY$z<1cc z^4A7B?4R+@0OKNIpJD%4Fz0_MC!%}KcHnH2L|RcuzQb+zCS_0eW*!`$8Vr0%k;5;aa44~$Gr#*<>T>}IT zFby?(UA)E)r8tO@;fw;#2+G2D+as_zqmBKNzuO*T65us@)2=vkBA; zF*36$815uGT(0Y$g!vw0th=r2o*Jp+OgK)bj$G$GUE(+^Qpb64%t<11s43rl=dc|% zNATx%*nB$Wh>=bCGTv67aCT4}#K>^=0%td6;k)tOf;G2o_E7@F z$OsOD;2;PT0zqyPIZh$Ct~?i)<9Oq8WL^1jfy(M^PDhGy1sIo- z$b}?wj*@Vl`6YIsFMxnQOXmb8Yu8?-Q-m1V6x{{e?IdzDiCm{_e0P3ZK)T6ruM2S8 zM!H8C5hG(Pnp~R{NhXDotNZFoD#{TIK|<* z^b!J2aS2XIih~##PHEtjqAXmeUP^Gb_VbgGIz9u(r>P^?tv?M%r`D@19V=pFV|^aZ z&rxT-V}DMt#$L>8Kgv@A#K;JOAkdPDnoRtZgYVk4WbRr)*RJB7$;L&)x^{oTtQ9CL zVq~n9!5WiHUZ9|S=NO>j0}3W#T&bS^$`4 zv=X+?y)Jb|jLi9cIKP`r{z1+8&i&ow@TZ#p5IDdz!|a>!8XHG(5F^9+1UMg27QS=; z2#b?r?3w(X`&^R%udxj%0b*nX@!|ifw(wux$umo!W{8oQHNtR{=y18tJqhzY*I0L3 z=bjR&bc%%-8Pv;6AV!AM8aOSJ z$sZJl>)cxkIDbfR+E5(C$Z$FUr#)riJNNd2HMea#QUb)t2>t>=XG*|#?wt!J=t>C? zBO~Yof?mm_2Zi7|_g=Uh7Z{f#>)d+?R92^x6)DD0U<^(s1CvRAO2T#SgV})|2m<~r z^%t0|T|10U5n^OhG#+eYlga30GLo|Ko%>h;X*9zfDZp_XX#!^w0VgM!%%M13=bj_r%#q;Cr#Og_;Vc2pBFe&b?u!IxYdidZw|Bf3Ht@mIcDdM z*Vw}p3(*zUop9&=KqLGo0~%Ssg>#*I;YOLQmm95wt#dEh$oicdF*4^8a4z166r<*R z=U%)~xN|QiaDZv0**D`g_7RGM7#U6};5nIa-Dm5iK9PK#~>WF zMnt8ieCMvQ9i|HY+zzWiryMb|DUSip3ynyK;_#jO3xHT@Ogrn`Lj_~KNU;zj!+IT9 zuQejCP%N%Pb?(gszNP||HD&1(2Qf07UxD*;Bl07~ z;X3!91)LuxIRBwIh>_uB0Oxng!gcPy3(nSlZW*a#TR66+j$G&78jen_S35dZ#K^|l z5zd*^neW^)1#9fZy!PWyN`M#{K~E5LZ$!E_B3&p4-??|^uN8FeUGdId`M=jD3>7ThBG!@fv%Gx+A)GKPK(e^NfyDBSiN`r!dT1I!vxh&&3?)8tZK9 z(oaX?b{=kLsTh{Ww0+^#etm#87%onK+Q>5|~h?WVu!G$Xp7=DR?--H6Em!a-_ zCtjvt_h+d)qI-8g+`TE}c?!UF;ocPd5$GY(61tP0!Q6fPI0ij|F38oN@Qg9u3 z#gy=eHbJ=aXGRlvtQ|_|)F8T_npeT~atf)OLSiTv-+jL<;8bR)F#;I3abBZ*i0=8` z0$;ThQkBASop&{Xt*Ss|O;vS@g6JNl4p3^Pkas8w*LBwtP~MTC)TJnh?or+YN`1<~ zb=>s@S8MOSABo#XaQlF|aozR@aC2&zKBi+tbU((=;M#z?@||`A!4~^2uYG7p-4Wfp ze-8JQ6q1}m5-9`UWvB4h2DxX^qf^L8io$o;qXBTmm}=Hxk1QBz97RHOk2DQP zQ&Pwzio|u;Qv{+(0+IDlo=#B^-J|3HWljp2MNzm8dyarIOM)_&q9D3QSp<{?l!NcE z7YMf8Hd##F5#775fcrA)&Ue_$3U*&f-4WfpZ-D!{6tac_a2@tKTzYqnOOJKfYXl;z zOW7C+!Y&}}NFm!&$QDY$b=W)Dq1^^|{>*F8nsu0tv0KnmGMx%dwI zkbrZ5q3#pFxQ%m^@*%qCI|IH`DI}M|aUJ$4fh|`cvZm@RML~3ras?=tQpg30!gbh} z1e6OBl&cg4(LKsdpj@XMT!(#KaJBaCtw`MN!R-!p<2vj+aC2&z?$a?Mx*ucV#puyy$84YjY&Of$amQF*>0*QcyqhyeLBsE?x(o{ zP(E%I2{;`YYNi0jZJfU-AEJA{KH%%s znDn40<>E?#3Fq9};&Q62?K3Ch8D*deT}JR9d@u_ zBtnr8-6OpMq?c03ixi3LuwN30UKEI|hw`fw1<^f9HK0^YC9hKyuEVY>pu8?Yd6S|b zx<`2jC^aYt-(lAfY`JYxle#0icdrNcI@F!-u205^jG`H?G6}18z<& zQ!6?~ME7HC2iG>#mG7|I2)5XFdF?}c>W=8%y(`?iq>@glq$6eEJM1p}wSf-16W*C@ zTqLZ+?pQEqH_D0Vp0gh~vr&1eT~9rjG>is;^TE?l!y$!u!Oci7qN&YCSSfMTRVK2mj%s2K({tkPA>5kXfCDa|!z55Djhn;7%k{ThpH(HBfuBOA}I_%Y$;|0b# z+dAxZk+^Mw+Xm{!b=VsuZkr=<+X=VrsbniPMn> zFGb-y?EL_kVN5mau=f^>bciA$x<@(*q!X#+7)9bb>=OdfF@eZ>D4(Jzi0)A?0_A)v zIZIKv4*R@-a#n(JiJ~C7NBJ8lS1AYIVP6$&xovWtx+A)GzXSJM)Sd6JZx!r*m%1am zcQ2BL|3*L>iAu9R-{3mzLTQ<878{oy>#(EJoG*w6(jq{36bL2KNbxjMj8bqNc8Roh zHCi;lS9Wo@^Jk`*z+>&ul4;gQKZx$9rVO~AN+YGyNGZz2ci2w}IHehCDFKYzIL}Z% zME86?@Rd&^dWDV=(ft@-hwE$9mG7`$6Kt{X^4f=3>W=8% z{T;a1NF#5hk!qBI@33p|*9JQ5xA4w#<04@lcC~^zYf?@`_nhy6vwj+>M8Ae(7ZhIIO=a8{q@^{;ZO#-~ej-&*L zkr9kdlYOS0XEu(SAx3643B#R0hs$-{6ENS0jdizm-IF7AoDRpS)RF7Fr%D`WMCzCW z$2nTIT%@X{%9X6LvIbvi}z63an(#Qge!*}3|0I|lHcGiI}C>U!g#X^h> zYb~%=r;(Kui|fKy3sfrwD(k_$j^ZFjhO-qoo72cfio>zr(n%(n>~~OF*1UKAlOd{_>O#k!32jW0b*nXxga>6MvhVlt}8!|%kh|TIkK+& zs6b_PHYX#+xCD#~Y2;iQIYUXf&in#9(C0wFpQSSbleKFv(IA!?PeOeo<^=w zHoiN*DIi^ExYq_ux08a5Hq!`8Fy7b}#PB972BNPWQGMrMtd5p4fo%&;fv$da}h}7|EI6g@oxo-VQ zI6AdnW$0KDBOB{;a4t)o`HsD;V2!<)*M5|v1c;FlXdqCV5PuWmr5t?Mt~TMW6?E-> zymQjHXjs?oEtplOtca1Z#(?#OCL}~b`Of_XU~$c1c1YMSfIeh)?s$!TkzyhKuULow z73ZmE{^^q*&1;ix%^m*qNw?;ita=gY4rS6FC-A6XBZOy&# z_kiaajiN?~?v2J_m}BTLxh{PS=6EPZY46gWsu_-B0rZpv-GdawrPlna=~jd9E|hDHv%XMM89sv=T_mo0Fv! ziR;Rj3q(r=BI{wjilQL8N7)FJ_07pzio$i|>jjjx5|m981<^gqcA#vf9DFyvRj}o@ z$qwp{=-z!V+;>xVz7yYFu=_shj_BU~DBKS>CkH72*M%R(r8m;J^jH^uP$06pmSd41 zoCCs{=Hyg!l1nML4*U!|w5QC_;)pPK97y4IXrX-+OtF24J|Cg5CQ zsFwsVZsXjbe2DJ(qS9-Vd(Fum3deQc_XM^(0+BUUo^BLGtq9)XA2SxpLlgzkJ<6j%DM2~7j=O~5YVF;Uk+?kpx5ud)*KI!zH>Z}VG#w+N z`!SY*>r>Q~@3fy1Y_ae1+J|STJED7cKis|P4vy^r(D4$+yGuy_+xJYY2?hh!IAXZ<-8%3{OT>l*4v*#1OZ0Wo}%v zjB&kW8<+X!%l~%{+5F}kp2+d)Cxt6u$Z?+6EFf!FV}av5Rm@#&{NGY_K8gAy<39cu zS3aXi8E;gaH{)JZ+)Ixnm+}-T@?5dPfs85mCu~uVE-n>SGOmzutyGQk;Lo)oVpq?` zuAUv<)o;Xk-qe1tX5AF2xB#rn1&e-I!vvHn(jc>y^6u*k41%|;pW%1e@wn)+vFpsY zYiK#?+MW04CGwR~0}Eo_E!ng4ZD#Ct=x`>+Yd8~cXXoH&IGA=Zxb z)G~%x8$-;&5Eq7rSO=e56g0$Q)(}@1L;MFD;u;KbF@|Wq{jRpeVTjgwUC0j+It+1* zF~s+>m*8h>j3Lr$ah~_hA)>IGA$}O=`M?W zf$`eA^nSazBd2z{3yg1F{JpV4}C|S1!mh30(T)Oc@v?e0^B)X`JT4mz}Km3{g&{~e{(^x-q zv0InG4}Z~~q+6{u77v-`N@1Iz%gWHvyWo}GFUH>d)g0_ucZ2;S&hwiw*gr7XZ5Zs$ zbaFjB*bF>T@S}{@2>+)+XS6jk@8lo&b#CAp?eY@n;BRt+&uDKXl+Ql_cmBT-?@@f~;>n&d00mH|FM_#v z#`oCGhq0T>w;<)%;tjO&h9DHQo2{pzv8=<4On-~K70WKy!dNpL<4kkihvy~G-CRDr zG0dZ!F~UgTjOm{98kSQxOWhG}NktwS{X-(!UvXpA9c&sgjowc`F%3HFOcUelk z0#>cg>o|1HezC1+9dku%$x469N`Gv~ozASs^Px@6w$nFE-NcsiUik1fV<|s~%lVy5 z^&?ZIJ7K*auKpjIXI>>4_{Lg~|Jv%th4b68lvc8oPRzOkfVr!ry-d@SX}a0>P)&3G z|B@*OGG#w!WtL1ik|~EdD~HIG^$2TM9dC z=UK`bS;`HTa;<<>yW)72d}yxdC0Xf0vEj$hec74yc<$QN>|{R0)KA3n53f(chqoL{ zDH|(1eagsG3R8Jw9d5YzaP=U~Gp`bYZ>;sGXseqL&acc;D#=n_XV$L*n7c||mT77* z&6}~d=V@WHD|thv{0CFkaaPunDL-P$IA`U1GG#-iY#>W%#8MJvDNT@K&GwhEPF+c& zx$!=i$(u2UAH;p}o%4vkkrn%u75m9q`ESu9T~@3$E0*D0?01>+Po~UtR<@HVyFqD9 zW*1pXZ&tjAErp%6{wyU+mNJs13@c#Oh8TxV=t`2z6&)liJ(-oBAUm@j&p4Z!oy_)C z!xvGTs{B=w5a?!N*af&_oaE}RWbR`>I8{&1Eu zM3yp+S&s%Vca@BkX{IsFq5NR?dP5M4X3N*OLIj_%1V1# z>2ikL{tJ$AW<8!~ZEAKhpMNtvyl3C!hu0*0cmpiO|E6%2cx9?+rV764fYmfyJ%;9) zSIH~*#@gJKZFT<{&W~j&ugOwsFzYt~%v~jK$TansruLh*tK@5Q25ZWcA2DT|v+_Ne zGJz>Sb5=HxDH}6ovMi+uOZifk(iADyY=8Hr)23{04*VOL{AcFyZ*gCwJCEpJvSO`R zu|J%Z{}ny{BP;eNE0*b8tes5RgDJZ@E4#>)eWA1_v$rf|5G&r_mcq{3aF#MemNJp0 zj4NQ(#u$fA=t_PxS9FxD^lVmohV0CGJkxAyb}~!X2wx?S*NFPENz;6vy0tcaAE^=b zHTQNqyltNQXCbvFuS|`o@4wFXL1kt*#m}mjuMw4+FQcbfyPQl{k?C|^mtpDxGF@e+ ztK_63GF=s>dqtK~jitoOQfeZ_nvfbbqW<~s7Wu|&T}N-(l*7aGRG%s9IxB0-lpir= zoU`&hnesC>pigWmZ220o;)$5f@1xokqMx_>J)U@(s0kB&3DG}4|Ni@YdupP&evM_? zpBPgM`)-_ODx2ANwxEOp-;Ha-Q+Sctp0ib7 zA5OW>s$b=I$5ylUWtr|i)7{~9%T3)aneM^2!#91Ax4FC6(iM7}zrz{lBTQFZmQsqP zl$51BgA{8wKJ~Wa-B{YD+!dZDFH@FtRz53J>P)FREB!KMhz+QMErm_XORRVdrjy@| zFUUkynWzdxw%xebT)$Uj+D(jU{o8!ge;_(Da`OS3g4Y z%!hw2zOmNxn5}MZIR7k5IVDTE!mKX>m}~ma%QUx{=EmE$rvH#RgMZ7EMcxUY0M9#) z%KI{938s9=S^3~Q{F1OqD8-Z|WhrG?%9FAbFH)@8F87X8(|_6=__H#3MdqNtBkYTS z^N18#v6oq~7oC-rL=Pe>R*e;lbuLy#rmV%3Z#yfi%arw@v?jBzEad}M{5@L=J8KPC z%15%46qb@yz^Wy@vmQ^XP0cptA58rl)LeIe)l~lc zj;-mxj;*cKQL~FQ#!Ni9pB*|H22NgnKE53rt8k@E}6QnGTlI?>*u7) zlIeys-4I#I7?v_pmNFSB)`U!W$ML~7&ZhJ{PN#AfQ%-kQPL(O=Gi8pma*j;7gbiq+ zErl)LYF2y&rjviLEt82hGtmZ!Y!9{~7_rB*R;Infm~PrO?1SN{DqJ&sb4S$_F0gwt z)k92Gw5G!$DH*Q*D9tlB_!IcXTF=L7@^|`U;rucz8nveF z@$`^6gMOJZhAD}&GFqmr!j!K#D_@c+-(utVvSj`WM^ff=n*d~_6;l6#JO0iO!+USZ0fB1UZ(sBN^3G($Wne| z#ecD-u(Q^ZrTi{S`IDt&7O-mVj6)}Un)S4~qHScQd$H2pWoOpo>1tE6lR1Z}XWCNA zh7a#TmNHLV&K#L)Ia4ih!qURk*U&ukD%pr{to2xDtE-3ex3QGXvXs5ddYAnw*&)*$ zWtv0wJ@lM8{|98svrKu)S(z(SUS-Nl&dLii|kC;bl*)C*j79W-sdyW-*###Ba=<%eiSb!DtI~ViHl!PfO zIxB-RMVWeHNO*UZtFjbN?eH_=UID9i$MGtuX|Cuk zS?Pya>0-4Vt`g(SdOSsI^N$vGGM{JaXKg8UAT-Z+fTj3r3r`=fOcl*kK_{&D!_{MG zo@w<8zOmM$vaN1hI6s!9ye3Pj!K~i|Fn5)_A=A`jn%cE(&(pf*4Azt>KVr%_XXSe` zWdc)v=B#WWQ#NMGWLZiRmhz=6r72RZ+5WD!Q&;klIq+{}@}HT*zr}r#?mVJ@$%?gN z#r|+s{#W$)kF40AtXQUVv34?L52ozutn4CF_Jz`#%-*t;L9BRxTM9dC!&%A@S;|C~ zGOmDC8)FJe+@mr5u%|oMYCf?N`Z3ndTbPT(<9_1atl`%9Qt* z^0u?`rc7D1PWbs!xQ^}mvOGO?_y+)+gc3~okSwJXODQQ!DT@?qwx6!!bd{u<1AkH` zSDAyaj_`;n?>wS%vSKf=V$sgZ3ZjQDEA|>I_Of%a$};6!O!`jM>km#lPSLvH^C$2hYdPa~U}ZOX1p z-PxA%9faoj?!!`gip$wurW(jp{hY8mgsTsud8XB9d}FQ02wUBb;rt0KWvnb^IbbY?q}RLW(up z`yDrBXLI0tW%AR^Ay?cN$DK!XR95UND|X3Qc|r6zCo6WB6}#nJ?1oJFK;7`|UZ}3^ zcDJ@cR9*gdXZ!MDD6PpXCQEsY6@SE*!p_>0ETxnzr94Y{uCCJqz*@Dkb)Bw~Zsv-X zk(I8%N^6GPew7$!*5graYBmGIn0l}+r6+{u`5wzsM%5LbJ|kqR$xJoD39DbY`V5+9 zT4m!KYdvP!>h=%kFJLKiWhu*<^%4McSIHuoWqZpuOCz|YC#cbLOXabH|_9?>;fv7+_DXSi@Z z+Zndz-&0T6d-r9V|Ku_2^=&J1Lyso2B%Sr3_@&{Q%5e zC0R1fNTwOq(6*IFn=?2>rkuo-QBl-aVBB`js3EM*N+tl3`K z&}manH3z<2Cf~*!HjDdWqw|Q?%ZeRf#r8TYcZ(i7WyNw?v187~j>wc3nDVT%^0Z8O z4N7Y=FUwMHvEtWlDeSD>XDN4NDG$YmPi)b6`KlF(ce+Yunk!l;UUJf(V5J{3Q!i-X;ls1SnCmMtGhUy z|29i`OO{fPS=RNsc*#@5+=3O!=9!vVlzb1yiOtE0bl)ubDDU zmeQ1^d?!o!5h>Per#o)SW#+*DC6i|`hyRNE;y=zK`bAc(BP-V4S=mg z$V$(Xomu?NQ#Lg_ncJCqi!Ehs`0(yyDZ9nx+$mEXVXA{pSX;x@b7`J=m7K*l)_R<> z)!i1(zr<3`%TjJI>udI_WzhuNC1fd!B=8RbHk8Mi z@=<4H37PU~rYtQ>DaTUE%2EPIv1Z$!;PiakX%5^glUHI6p#=yZ{0CFkaaPunDL;VHn#}iPDGgZhk8COItR=9N&txg7Eame8 zRxKsLsVmuQu4uBXbW>LPJ40^oN{ln>@qA-bv+dlPsWWUT2Ou=hcSn}eUR=($GF4Zm z>gg~;Tvl``q=8`hVuurlmW7oQOtTcfVr+@s7y17X~x_4&>?dM$I6tm znR14+a+*xJkSXUmD|2MZ+mtdgZ{MT#}sn;bXgX>;HkWb*yYVUM^kb~%q| zhpbpGD|XCTc|`O$BrA526+7o#?2Jr#gDI~$E3e3u_n@>U^R_IdaANpz6_v<8UD#PG z#!?=TrIcbRB@>+<0M@EKlIV1moHtkWVOi%TzU)s)iHR&2aU4G|#kpAKzH(QQubgRyhA-mhyotC4pIg24Ll!89p}w%+23IfKbE<#$Z^wX?E`OqtG<&774@Wy)We@<&<9A1viJSxS4PShL;6 zaZ}zk2i{61@5UUui2I_G^N2diiuGs3vYeH@MUS4cVk20wq0Yqy%ajwCa;&p*v`je- zN^3GF%Ti{u;xlY1?5xdWDcQ1=6)a_G0jsvy@hb6@GA@IKveKJa>GiTRi+=~lre-Je zJX4>sr4)g!dA_f)l*{6BUX-bBGt~_ztkU7?QAyTSZCX8mZ>;qwl*HfLPlof0vy=yA zDUZ{V_=qUUc9oQnX`W%4r;=<}Nl|nDOUsmgrY!HQEGJV|WJ=vx8IUPsn3Bj+US%mS z$x_}#iZ$C+lboJ!Wz2!UE|b?~4z)1Nw!fA69p@3%kQMug6^nCLz9)LrmlaE7#Tq&n z`&6dkr-N%+v9zyec4`nHX#N`|yQ;lY-5l&coxcUT|XIf3g zH`aPgvegZS^JlS?>9Umh%sR(@mCTW8mNU%~`yTR{Gq^~m+`yD;ot3L)${kF()mgb& zrrgJryJaaySjs_J%4wunvz_a>DWlDSAD79mGKWjzzPR8#qI0rh_gJyp&dQsj$8}k; z2b06UNfb%8Jr}ISER@VYsMzi*$&@9WmBnSsC!w?^vy?2QEGz!BErp%6@+{>!SxN<# zq9r>$0IXG0lbx=TO6H3CWu;$YrDF`a{VFletjF_$P0i-6E>qXCrBsH{Jl}CF<=tfA z>GKbnssU4du+%GsyWSVrQX=dL; zFPk&iRHpomDSvTR{v=bjVak@y%0Fbvj!fBJmeQ4_be5%LA;p^QUXGjcO>^KqWb$Fm zVX(L_20D+ZzpU5lu!*c6#^K2zp6E9c0ROQEzTbCE1%6)V2n zmcq{3dX}zjY%5^Zwm4oTZ<{N+NmlwWD}6wAW<8#LHZ?n$MH_`L@WPGwo4Qu` z@IJy)iZ>Fjl43H|6HN73BZnLA<8bvdG|#+B%HbPpJ<8hZeiF|2vy}3(lnTsR12A`$ zs4~rqO!Gn`+k>o*IsYMH{Ptf@@-AEx}-S^1+( z*%C@?GJlt)v}46v+fvwB`;(<)%2Ill()A+_(k6c^bufq8kSjt&h z%HPcTiv23NB-7kun%nk0)YzQ=n=<8tDdEewNQ&(evXq5V_&b^nr6g09a8?$VDW7D@ zQnHk1SxOmMih>ktw!JA%SIM{Lz@L}N33I5JB0OS(&Lh%f#a?5@UUpVi7CmBQ#j3Mn z)trk}l_~2oWi4mrJ2K__P+F5&UzYMQEB=8kg`KsAETw@gcG^+Cz<|{nWbkGE`fJBRb@u#}pzl=qo+eE@S;Nj;h7Q>OX2 zv8}ggXU^bfH z$=foAR^q@QP}g3_AI;j)zR ztoRsP3Oj34Sjt3MN)AhzUBIf%bi7J>nkzb8R(csLy;yc;@sE;iYIZUUrG~G;`(N_c zU?13;=lda+QZ!Y#N{XaPR3(|JM5@CLH#%IsG|e-up20WPdOT&TJ0_g}JWF|2mJ(pr zegJbCUOne&Jm$ci;##lCb_elB{X$cp`w75m<~*tas}PfXdu zS=n5s{4bQ&Wd15kX~l~FVM}3WtvyR=BTMPVQo0ndYMqQjCwx{i*<8_%veNxo=`7iq z^>}*Q)a+!=Wa??Qlxg9^JCCJgi_1A%rdq;O3!Sj$hpVrodFEBJ4&PYovD#L5K{$Ui zOW7bx*~P54+pm(XGR+~T*>B%NGtBwlD^s3g$`j7YV>0C>rabSgJS$UPXUeOxl)EhD zmMrCgwD4>fN^`nO7MlZ)O5-0EY$ZxUZv8jBN~8&onBr-+3)z~*VzOe-uwqX+D@%(W zrDVnYtXO&HV&!DYicG0HD+4lR43yT^C9;%PSnPrv(ohqx&0R$@FiEMiS0(S7Bi{|e?79@^$1fIcUBgYDW8DSn#{*!DP>skCv7S0 ztd(OaWo0QkOHrFRJpim#^EYw2N=}+9>Xns#k(GYIklU{kS?|`I zpWZVNn&-PeOUY_3Jbil0R706+P;&xwCSqOu30E*E=iM%9J~pa;q$5A4}OSOF4!V zYqk$JciNNz%(=&NP$oam9L|XQ;*|4=UnWLO!*K~ z7EO2D21U~OQ^NLTNhqz!EFnuN&5A#6OJQg28J6;tEJa}{-gNn@J)iD$l?2TdeNI-I zu+kL`x&10J&aB51w5iz)jD)(dr*NTh>CYpraG~*Le8l7N3`ezm{{_Hk^DKJ`jY^Md zZk$d}ks?u^s1`*FdnVBm(`ktrG|ogU~{ zDN+n&Gip8t>OzxwuSW{QEgNpAT4({QIy+BYI8XgZAy1(k453-Rs>T>lVlgeTf|Xb( zEwRK_!azoeRVZO>9PgAh*j#kAOR`CVriXlnG7o97Xh$?RW*CnH(9&Y~Rlc&$U*Ye!5%hj{HzVc$> zZ$~vP5)~EoPHa+x^t9&bNk6AG|L4z1HPh0+Yw^!!NuPd`{_oGfZ;;mH8}h^F=`GTl zC)KK1pVX_D^z*APCw-LmecI>gX-WV5;@hOSW@$~+)4zZBn=kVH-xr#tei3!~Qkkd+ zpH$lW{`7V5Wd>*Ya(r`qbAwBL+kNYNn|vF5t%5gvcYL>eSM*H(S-ro1kbjzgrvI$J zmC{!2q^?lcsjJj^`WkhNo)s7z=ojc291s{5oF14JSRL3MSR0raTpw7iZwzeHHwP~2 zTLVk=vw^%H#1>urxw{OSA4*WK6K zm*pGi8{!-38|#~eG3EG{VniD-rtQ9iz6-t^7}FhJrax~)7yNfHs!>X|vQ9auTsFry zM4gT?u2R=voCnp*YTG~-#y9{YwMMu$us*OcusN_5V?7(V5V#y@qxIFsYU8yD7~NuR ziMC8zuC35kVx(&@)`Qw%?WlH4JE7%jC$&@BY3&Tge@?q-&cSue!X53dc3;cTTj{O! zHhNn<6SLAu@1l3pd+5FNe)?d2xIRK3sgKde>l5^e`cyqz&(Y^$=9cQq^_BW+eVx8p z-=^=>cj>$JJ^DUqqpX`Z4`D=J=F;T0g5_)UW8*^y~U<{f>T5zprNm zTLs$$+Xgd(oq~S_y9T=jy9av)dk6ajhXqFm#{|a)#|6g+CkCekrv;}6X9Q;jX9u%` zbAt7>w_DEn}S<{TZ7wz+k-oTJA=D|yMudz`+^68 zhk{3fM}yB~RKo6_iM5>Nor%?)<(-4qY`o^+b*{O(bG`Gi#tZPe5U-2yx)`rZ@VeAo z`K8|FSpOAxU5VFKcwLRxHF#Z%*L8SZkJk;}e%_7vf1A8Byql4?1@COdJKONicD%C# z@9e}oyYS9#yt4=I>;>08`0d9}4&WyT@smUN*gO*{Oc>*i~V^U==N!`I%|)0gS%g)`IJ*U{GpiYzGl`a1ji`MUV} zLoon~flv&BVlWg#pco3pFervYF#?K_P>h0Nv~QAk3{+#G8VA*Qs3t%)5vobP-rmW+ zKHe$5EbmlbU+*+uKksx@nt@6)QE3(`%|@j;sFaOLIleKzx%isrTk4&UiVIM2Au29H z#l@(&1QnP1Ci|B8rudforutU+rukO-ru$Z*;%Zb}gNkcWaUCkIN5u`OxDgdMq2gv= zYws3(ZS~FfZA0blsJsJTJ5hZXs_#biJ*d7H)%T(LepEkz>IYH%5UL+W^&_Z$6xENR z`f*f0f$F)aeiGGB`L_5@`?mVdp!!)RKJGmf1~ z{l}F|{|TjoKUeAKKdJobKc#f?pH@2i&nR8|XO+MF=ajDg^GY}W1*NN?-qVrJw(X(%*km8Q{OA4D{bt2KnzOgZ+zqL+~}!e^(ji zzo!iM-&aQXGt`m(mg*>fD|NKLwK~S%Mjh*KtB&)xQ^)(;s}ua0>O_ABb&|iMI@$lH zI>p~fo$BwbPV;wBr~Cg>XZX9SGyUDvS@@dm@2<}A_fWI_J=Gk4FLkcJw>rSF%@b%}qVy3{{NUFILGF82>nSNMmjEB(XNRj9cdb=IKHTGUyG zI_ptq1L|z_4_7y#&Suovf;wAKXB+BlN1Yw0v(rC9-Q^#t?)HyT_n^*R)Y*qR`%&ir z>KsI!L#T7uKUzJ4I!96G80s8HofD{&i#jJ!=ahepdfGo$J>wszp7oDc&-o{)=TYy1 zf1-NPKS{lW|9=@@SMYTeU)S*UH@>dp>ju7V;_DW^ZsY5Yf3kYlKSjOgpQ_&XPg66L zX=+Ply4p&ap|-|X8)c^2R+*)?Q)a8}l{sprlC5@7a@3B>T=h?7p4v&7uXa`zs9ltW z>R-wtwX3pN?WQbIyDLl89?CMcr?On_rL0hUD=XDL$|^NWS*`X})~NlIwQ7H5ojO2S zuMSi;sDqS^>R@G)Iz-v54pp|O!<4P+aAi*P2qimuq>>XoN|_ryTA3F;MwuTyR#^}| zPFWZ|URe}9L0KFi6MOhv_Rap@|O<5T|U0D@9Ls=a?Q&|%|OIaH| zTUi%9M_C`8t!#+SQ8q@;RW?P>Q#MD>SGGhiP_{-dRJKJgQnp7gR(3=$QFcZzRdz)$ zQ+7u$SN24&Q1(WzRQ5%$Quar$Rt`k3Q4U70RSre3Qw~S3SB^w)P>x1#RE|Y&QjSM& zR!&53QF5cVDkr12DW{^hE2pD(C}*N~Drcj2Dd(bhE9ay4C>NslDi@>oDQANFl}phF zl*`cvl`GMQl&jH)m21&Ql)s~oD%YcrDL0~zD>tK0D7T_>m9xQ<%I)Y=%AM%b%H8NQ z%Dw2b%KhkbN=E3s(lT^GX%)Jtv<_WT+Jw+ugsv#flgUbx5e2IyBT>9Tw`L4iEKI zM}&H*BSXE_QK3HS=unnACe&9Q8|tTy3-wpWhX$wb%fIb$)1)x*#-J zT^O38E(%Rm7l)>)OG4AtrJ)(>vd~O*d1#ipA~aiF8JeT63T3OSLpkc2&|GzGXr8(* zG+$jGTA*$SEmSv#7O9&;i`C7cCF+*YQgv%+nYt~sT-_d8q3#H+RCk6}sk=g})!m^r z>YmVAb#G{$x-YaIUmMi@p^fT+&?fa@XtR1Kv_(A}+NvH2ZBvhiwyVcNJJjQ$o$86u zE;To_TRj=tqn--wRZoZZsb@m_)w7`k>bcNC^?c}%dLeXJy%;*8UJ4ymFNcn)S3<|t ztDzI>wNS45cj%;gJ#fx)C(U(8JQbcPUZzxkokd?WIkoAF`WJ6#V*%;VOHU;*O&4ImSOJE<_8rV;^1rCty zfrDg6;1Jn~uU&z|WOv{Q*@LgWfum$!;27B-I8F`(PLP9vTyiLIk{k}4B1ZzJ$dumgtx8 zJJ998GW|+mxqdaULcbPRss9~VrC-PINjCy(^qYaT`mMk^{dQozekZV8xf@ua+zV{b z?*}&O8QLbjrM6jbrESq$Yg_d;+FyaTTGv23ZJXX++pcG7JM<3PPQ9bHOaD{bt#{J) z=$*B_dKYb<{+G62@2VZpyJ-jY?%E-}hjv)+sU6XKX-D zGfP_>Gh15{Ge=t*ldUa_$!h#HvXqrtUuBgxqT*_8WW_bwsETW~H5J!sYb&nT)>Yh~&8WChn^|#_ zHml-ht$WNCtw+pOt!KgTj+)z53wt6$J&RKKXrtbR$GRsFIyyZRMvN2ROU&Pvy`4%**ZNA0@y zr*=cj!ta26wOiU<-)(%|(dJaYs~z&+(|T06ul1~uq4%oLQlDI*l|H3HYkg{kHhOmT zwt7zWcKY1v?e%%pGxhn^JLn6lchnbF|5M*psgu5_dS|`=TV3=4Z~dk3uGCeZSh1Tv zsbY71Po*CE;_5y1y_I_D^Iq$%&#BNyKjP2Q_f_hvFR9*7Us}DtzQ57{{XnIG`oT(r z^kvlt>&vST(GOJ`svoX2Oz-R+uAe0%^owMqel0Xg-(F#~J~L*FJ}YLdzCs;`ukrfb z&;)%YnW*pdP13Xcll3m%Df(aDse0GYG`*{Ly57w@L+`K5)U%XXdUx+^y@z*>e%+U? zpY!JEYsp-FP0T!fZOnXpEzo;<7wWydi}ZCdi}m#}OY{vfOZAO0%kZ^apAcH1_x7&T zHFS_I&az@`1b5`FQa}HnU^=;&WzAxsYzCY#?zAo#x z@rlYE-&K5F)BCG`>;1jg^|_%N`XJ?|e#?7HAK<;M4_5EsXaA46H-V3$c>4cmlOWL` zL=Z*&D&dM7VK5-zW+6x}4he^lKnOYH2pC0z5D*W(hD#$NhoFd{qJZFu3W`CHQaLlcp4nYw=Xw6mA75_o&U9D3yQ;dore}8Z_mz(){Bz}orl+r5 zn^57c)W>^IVOQqw1{3lBB<~jqlf7%3-Rpfa;XWL%^#0S}e*8bh`&7aM-lr3$dS~bl zdS^G9=3SUD-TUK}GrU`y&Gc?<`jB^C<5}KMlV^JmB|nV+AMt+IXpVPZ<43(8HJy{8+j#{X-)&nLX)ozi%%_l1OY z-g)|Z?~4f=ye}ne^d4-w$$PBX+urw@ZT3Ev@Q(MFE8q2QZo0+0x9L{zoW|R{a~p2= zKB@2Uu1I*#yDVX+_uj_udsj97!25E-F7JfKyS=lU?eYH6Y_E4);}5;N8}IXOX#A0P zp}ya{v+>8?9}_{9KbilY~6 zTCEPWf8M-w@XFg_Jf}}%|4QpHq+~#O^W@|inpPo?G#@;&WKj8-5^Qf_ry6xU|E0Ie zzvhEVhczBDR2+-KYqaNXs;c}Gb%qWT$D;8X?fE)UselinPU&!Qn064OJq|IlPRUqN zr<$nq)$R6LLe8i=M4fX)o#-jzgXKlk!CoT$tB(JpJ)5vms{SK}^R8~$BBkXu3Ff~R zty5C2y|z_rpU*rb-n2+gZquesLPCp{ty{EiO^0qgPt#7H_Gp9ez5B`hV&6Z@Yb@UX ze76_oefWCA#NHb=9`|T>8=G~5CZ|Evb517z-I_8y)WFAc#)r+Q@a=WO*l zXz?AahNpTzwAQpl@_^-^S&xlRr&@r%Zi=N6-kSB;0d%&n&!ctB2vLunKxg~qYue*? zseq2HY5<(?zUhK?L?YeGjH8I|B2>uZx#(5-aP z$g)voL&_86HgiJn^3j7!%L-a1w@4|-D7*F6(Zfs2?HmqU7MIh75?-)@sxOAAN5Bc|-+huYW zyI|1BJ4Te36_kt_QBYDmpk!3@L7G0eY?P+wmuh-ntrcGKG#$I!BS+v&kD>Ss=y_ZWC{$I-)4OTNz>P(A?f%l-%V+a)13;URbM|DfE!mcH1> z*E@~6rscJ5eCS=z!KDL+b{k!ez)H6MYmt$mUC{CJQ*~Q;zAT0hS|W1mTvoC2Htie4 zalJn0W16aW6-`$4Dyrd58p@{PwV6B?D~{D(ajCiUv_tu1^1+U1)$ zTcc_(Np&rLU}>3<{oVfVpIqE3A^YjeHr}N@yXL>Or*&{Gd%&pSErjrTAGX-@RCe?m zSDyT2-V58#`=a*19M{5!-85j-O+xzBla7peyx@(rb}zrSd)CUQmewBNUV6#MkwW%$ z2_+}T6%1_}J!WX!-CvdLu3fk9S(Ec1H$ta$IBstZA25tYeK9@=JiB#=%7tFM~m@z7BtZ+O6b86t@bAuyJFx8E#7n9*Pa!Be*egYn>{&M zOFl?jU$eYG!(@lfmzEdbQgVlOuO~W2OVBD#VV3{239^hoUdPKOtREGXTIcwf^PbA~ zEXwx0oE^0<+jBD4Gp>(kQXkI)eLN5K@ht5VRr5h9Z_vO&#e+&m+*Cq0=cUAdAn_1M ze0~*Pre$hcDdb`K_bkbdTAdvYdA0j_>i6^1d|b*X88k4MjL%5M^fh=%%EC=d$iS52 zc`@4q0X3J&re#BdHa$#DZ(oa-uh6s|npRt#?b(p+c}KMF3EiuiKe&J+B;eBZB&DOK zr4#>>Y>!pO0LZ}aNs&zl4H@VQ)`6oWaSLvF~9en*(Iu$yOMzv!Ajv!wEo!32Flf+lUj%dMR?Z77LZogK9{JIXXm zaz9TRfX?ZmW%cPvkyPBGB|0{c9u24#i#fmI7=rXmlGA!SUgElFTFi~{n&-~~Pt6#$ z6@03+I!>)-P^)@ItLQ>c&6;W}xKnBM6}9??S~W3R)j+EnYAe_upi0B9sbR+*cxh=g ztc!-R&W1{}Z>ZT*)a*K=*%fGZo}-zn?OSU07d6W^nq7%z@wR5=BNb)eQLDc1;iaF^ zDjBV=u(V2P=`jEI)aq4gHN!@gTiMP31GPGTCtgMwt6{|Rb!6Sb-^ zT6IOM#%ik|=KqlzZls0}8Vz&MFu~bSvB*!Rfblr0)fd$26Qk7>wDPO1f|&nzYS>{HUXB|LXQ5#mXG6vOe^9e|)a+NI z*?ctfIhv{F|C5@Xq-Igq^MtS%&Dz_V+01{6THUZ4FSU$TFQHXcp_o#K4!X5?5S~C8 zK6-??u6Qu{{6(!^pjQ7ut7|&Pd#e51&Xbu+Q!|!@b%jwiH{w^0%15?og{5wgHlaG! z4AiD?!~acf2kyno5VUR5A>O0a+-*@;K603;t2*lcL-k+!5HGt>zvB5QOqn(2w29r` zE($uAWLH~GD?-fL?CSfnqqO{}r2fz!y%C+LTV!@3=z4paB;WEiUOvml%Um(1&uN3j zmO6oz7R&4({XCFaGdUotd>ED*%TkM$wA5DM>b;`P4|rM84KGbRgb9m`NTv05tymzI zcK1}z_r&LWF3I;a&i7oM?@5L18v?SeaucN7@g%qDZ+L0c123^8H%>^TjKC(Y4N3GQ z7kO%47;rnS9&n@*V-rZ~cx-W0Jl~Upr3|f_Sz2Mzv$vW^t$wFgZy2q{pjCRH6^&JU zt4Y+Vj2`QI+h{cot)|Luk1dBe?LMDOO^#8MU1(B(F2f^HH5Ub%1a;`W)GRdy&EC8L z?`D%jV}(OwWMGc#6D6{zC}dAH-wH?zV)y$<)>OJ&x~G?>^@pTtB6UKnk>Tg%dum=3 z=r`FIJyC32NfKtpLBch?*~VMY@613evX;Ho{nYAPYSqDL^#NKPmav0pK-#S}g_?A# zfhOJ1q~azDk#pv>i5BUJXKnU5u-#Pf#uv*x2{MA3?*WoC?qbOKAxG10f|TlVG#JLC z0nrVDngj%e7!6ZN)C-qF)RVb*SA&ph&S?{64hWg^z>t0NJ%#z6A^D!Ne9xWvp2_*1 zsTdP!0S!TX^B_q--T=~{>w|X+Rkjo?1{Q4Z0bCdHnbwF52?sg-STOe680rVw8( zj~$nfR##bCQAS{EHJw_GrB=0#Rs+$hL!gyd$ZV}HtJl?4(hH z872l|AOqJN5A?x!iCUWPc`e_wA>Xqz-=ibbtQY7Q8Ie$x@SjCuA8ZY=aoFh+3F<58 zS#wJ>SkcjJHZ_ZBgJ$)NW~{Y3a3SioZc4o9;!^&Vi-|tfT3p)bulInr$@wwAd5# za<<6&GrIKboYkv1BPWlp5{rkG3?Ev46P86hb&Y11U|F1t_Axm=tw+zS?!9|w7mvE7 zcvML_I)-PUQN4v)#JcuK3#D$aw(sPY2O;{~2L?c!Xq z=}|nYyx8b)hN(Ue%P;=L;1B+ASFr?9AIb*|HM=aBO z%{Z*3*wr#=+Jj~h(ezVjhL_x4JbW~$jbOPP@)o0>M=J~X13lL&ZMGqQ{7nA1rGTzY z$+y6#Fa^~slG~%zU?J$0$fbh_SyteQ8Kux;+o_B;FJy$b0r@k6=w|6HbMCYW3wSGL zfzruQWh2W?LnNSsOUMw*9mA`1Ot8_llq!$351rtH=ULQ^(?0Rjrk0#urI#pxg&%)T z#o)xiC^o;ou2ozmgDFn?=i=Nh-E+EYS|il;Xk&`Z;1qe3t-CQ*g`VAop1MVz8;U$J zLzNy6E-3*3z9Db=H67i4UeF!9cvR_~CB+CHQWK}$(H2N!%1Q?p4;fifGK6-|wTk94 ztUTIw9wBfbO#*W6vXMlMFZMi4W29O?j3Q%BZ`Hd${0DLbb+=P z0q4D z8El3hzAvG@L?JL;sW|GU(jkE<_9|3bCaimXnwS!$n&Oy;_S0bL*)^*l zkCbcJN*f%}IDGW2CIrp$uL=3L{o#^78d1F27!-d*5RlgkLBMGpUQdSy(kHQ>T3p>JRQXp9lq zv8^F{6$fcfMoyP*WMP(yNtovV48Jq?_9=y7$glxJN0}b~9rjxT^)dK+oN5x#B4`@$ zmOve9jkb&)-FkAYU1yL_><`(nF#|=VMd~2 zEJN?Xe;c97qg@eL(I?sd{gx69H{b+ZPDr3J=mm@R+Rw77ukcWNitAytp8?$%>v@ zYmlhSOcsbq3`mEzOIyZQYr?yH1d)?shtlKYVBmLAhMA$LTtR2xQnW%H3zfN$SzY$}Wq% zDck`3E|7nkOI*Iu-Ous{;&$mRMgrHL-8a=9VRS83$rppKp&JLtKX)n7MNwc*bvlCT zpy=vrSmDh?fM;o=FU1DNIc)<|9Qt^toT1~iw0xeL2bJOG@mRY0;p?NAmlWm0%Ldaz z6YLV`u)sJXvaoKMoP(7bnm@=NjqxY);+V`-^U_XidyfkArz86OjSy6sYx4}4M)APh z-p&ZvTX9)fMz`!_wmTHfza^9PSH^{6GP+9nPN-OH2B|r5k2pt!Vx0D==tp3K0NQ!h zj?qk~@v4G2EFELIWCR$#7xG6~miV;ZxDQ!TS9ZXobq&nw;V$0RI#%j|qlXj^FN2$K ziE8w^0W|(Vy?#jP^@uXsDw2kwEc%3iTHhBV(wy_UW#x44k!hW;Z<8MLXrHQsG5qC8 zNrthI<>nacpj9e;B^v)?cAB=Mp&)lZq-4tu$j<__z`Xd)%fSV(xcHrep5mWJiw?{~ zVRtlUJ61(=Y?d3Lc|368Ak6_sy}*&S&*1>d`uX~EFg*fgSeX8z@2}*9pUvP@!fp`I zPttk(ZCIXd$pnEbKZ^l=qk4VJdOS8|m>Fvi{fyG@!cbSW&FbE%OLt0c_cL}{h#8%B zwXbPuhU&GD@rRIcROBfmXctWEecZ?Xx=)R$(W3&}W3;<+|CIopqRbE@OR$krf+sf( z!?Xg^6x55;e5Oa`y#FiHE|t?c?!6n+xg<=$tpRX6NJ_dXAY%p$8y(Pq#}c(^Lc>kL z!q77HPv>sMo3`a4Y^->Obty5NAw;e=mtiGyu`X&eS?bkxsb=yatZvBuFJwO?WM`Ta zkXR+n&@`_B;+$7^mfo0)soysm&-t`yLpu)*Xqb&ttVR1`=BiI_n?)8~YSJ2UXs$f8 z4LMs7F7sPA$3$qD7f@3I3uCxBEUCZNE3JEG@xVLEOK{P|IpnQS@vuR2y7bOmTd!_Z{IpIS{!oN7J&CfIdX&GHHAo=;)IBl)We$9o3tr(~MEV^&5jrfD&MlL23 zSW3K&JdA!<=@If>Pjh_3^5i}vevO(}q2?T6-UsuM>Qj}#(!SW}+GMfD^3EsCW^(Ww z%WQp93x+0%FfN}AEr}5HsL=A4+?(l>mYqxU(Dw*3;gc1z+dZ*`EjDbN{r@U3^Oz3j zof}+R1zW5vTL^P`R#WSS~i~!4fl8iBQ}dFj+4{c&-$zxAmdBH0B!2mqju7 zv#r=W9Wh{Jc`35pJBrK3l#CoUV8jUPZq0re`wb!FyMCC%Xs`xubrj3-9y2P4*-VT^ zFj*BO#7tFcjUFzyV-2s;^05llJldZHau1!RmeAKlG4D7sD7tK;D^+6_(Si4-V1HfO zxJz1V`#ce|w7dO|9p9jrmwfaH%W8qOmxE2YnHc;!GEOT>L3G%Mh-HQ4y{(wq_Lx^45~_o5}{umD;#WnbStgz%8k6CG`A}yyCkVq4q9C zWE(RgdAdeASZc}R#crPH*b70tW$B$6bv=U{)lzkY&YoyQEMQK0)ADgC zqOR1Ona9jC$1ErB#(HBc!wX=geL~&qA+Jx(`1nY=-=h`s5X0IS?)FNYwp<2skBpqG zAPL}$4i|{c&0@OwZC>EfebxPBw!VsGt(i|9SoUL7!Ly%%3=zww!%2b158|{}BwAMY z+-|txkdu{Z9cFoL`QoWpU%C~F?^lXoJZ9$B@@AyD&2y);%y|^Ee-_}k8DlCIdH{r< z@-zRBim8YKXlx7~%g|z@@Kuml@ymgzi{}<`TztZ$E6V6ttvYt6gs7)gQTVOJml~$T+1`WO~az-&JQp^%*9}0ka!rUTCm`P>OmW;5mcptO5Xk%$htmEsU6d z698pW%>97?Flf#y0LDr&&j-Ag5NQD5&tX%?=$p|(geQhXMHB#2q^K99D2i^A>TCl5 ze+ZkXUJN4YYy)7v6g4&AIfLq~0swyin~0`|5%X^X;3X+$N+19XnzIT3{N3wl59aT( zB0+UeKpf2mHE8}Gb73+~y7aKusa@Tcog=s<3$K=4}^xsGImIKx`DA;5X;adTKB6?E>!Q2U6BU z0a+aY7MZO4Vqvk0fGpGew@dTm8T;5MJiTsmh&)x=g)tsYT}d_6oBbMU!0{!4t# z*HK^Y%kFUj-e2!qb8lKXzI=hyuWGrka$;pdv&xAR60}@;%}%3}{?~n4PE?L331yGk zopQ7s{L;bc(-CN14b7{3`Wvjgn{Q3!#ECWVr3KQy$_Hh+_`m862M3r=)X>tztA7pS zpmc|`0XXZJr7y8eP0%VXB$jo)%1MvG5|d_4$!X z`YWJbRrW3`L+MW0c64_ucelT94Si3rq5<`GE9^aw{Eq&^?^6@9y9$5raI5hHXxzyf zAGT`T8A9VOw;Df!#t(h^9#%Tah_J@g&kxNA+vCu$MA&{dIZAgX{|q>v`t$>gGuFVl zl5jo+#EBYEJWZH=T0+%<@K}c#3#B`(uYmQXPyd3k?&C=yiKxDGP<`Q`lGDQ1jDyl0 z&X2(P!KZ)6I8&`SKR9r{3xV?!Jk1z-h`jDBa;C1E)E&EU+$5%^jNMg4n{X#@5hy4QpJ;y%(w1HP9F= z^=iX?Md_}uerWcw=Eo^cDc4D*IQ2PHBNhX>PFp5G>5d>11nDVyhZMa%a||^&GKeEx zomO5;sOo?t@6bfEPE0iG5~|vVXU$?(lVd<2Y!%i!~~l`&}V4{@1O>NzgbUMXz9` zYUVz{jIauaekH;tv&m7qGx=2DOi9rz8Ar|BrvPFTncd9XE5lub0a25jRDP~bK_op1H zm9SaF1Ss7RJPU#)OrU1&OTrU8#{?+d5xfF|WhwfL454K1%P={nJ ztv7MkI^dK*+RTh7-7&rg#_cKkRt8iu_w5e8tqv+_vYm{B(jCr+z}b_c?_wM!bKm2@ z*%bn3ALF2OhjRcpA2W-Rxqs}?EaUm0TaAaI@epfNGWSE!7%cTV!hJ>QuCK?S`E%B+ zX6~OmR3jDx>BpB$fYKeo2@rgrqJNvBf6W|f=Kj4ptsry%7DqmyiN?&_zYfp(BeSA( z$NDE&e^1d*GN_ul|87qXt4=!N1<>z_%pI@(Q;dZ&BCIEk%)O?+qh7-wWY4{ZzjERp zN+oQWdo91*ra(IL3A)>eyQ}2vjbQ1I$>X-1J<+Yk ztDw=#8kL;g8$x4Kw;EeOD`^GWvJZ1x>35*-3PjJSht#?=Y-PTmvy6br@IKc z3;cRMt5GB_E#(jlmMC>D*V8?)o|lnrE_RH6NepP>oeSkXp=U0+j9u9tXiZzdqNm&tVQV zAD?GTCCJ3*;{5@dRJwP8ntM-b zYvkS&oD6dIx{o1HMh-C*5L1{y&AX?xt(^3kJ?}m&@@~BPA7t$)BiBB&ZK#|(py(l1 zgfenPkD!~gxtmJ9JsZ|N93Jj0-j9A-ISUTLc@V;CjBe#ODE z%*i5_;}wj8GIEqRfl}30U&$y+Ze8U-Ss4OlHKU-69A!OF)-s2hSFd%dl~c?H){8Q7 zz3)Kp+pJg3soxHz_g&VDGIG5;p?61HeH*J*^64Fz+>UTQz0E-(vyk`QDBlm|``YSz z+v>YnzmiMuGl%6~XjjL^ZU>Ldr9Wn)pp4uoN5OTtt$wJjevrA;Jo>N$=a7kd&3wX zP)3gOCs2N84kdT~-Jw-R?I}0fPD9(@tWC+A|Aw|;iICP#CPFA9?_*56j(Su(nSQA` zb5uLKTI9@u)Swz`M;W>Hn$TXOoqk?BJ(d~Ne7QzDo+^+ppNIEHIbV(q&sK}sP)5#H z4{R5;(=TK&HCMg}FiL_}bs><{WCpqNXCha|tN#*4LV31GOH%QS_+J`7BYrZqqy9^3 zkbL=<)XIs+g5=A;rOGft=}zlfLDJ^dub4q?g(PrhsvM>%FbnFDBUSLAKi`P?kZVy zT>Hw2KLp95Yr54~8ye$TqmoI-htOEZt;S2B@#6M+T~?}Q(-*flBCM`MzY<}WvdK}p zGkF8x)Nij}&NymbT^|s~$?WEnCYOiDYRFh9-C37ZrqKM9ZWK6Z(tLlbZ4S`u;sPa`?S|{m`%;a^BhQhOxzp?oDxX=nGvNs#z9~l z&|WWQKqV_5;NUBEP)U;wW*n66aBcxkX?uMr<0zSVsRL(d2%KSzgVG(&ZNMpG79~3` zb7+?FJkqVkG0<4f8kG#a92$eAUbk~!QM&8vUC?|7YgV)LI~=MJi-GjxZYDtKj$kqf zCbrkdx7Y7s4mDGss7@=$*T>_?Nt$TPCr$1N&w4MjqIAbP9jp(w*B@X|HFJN^o*Y&^ z;D{GMe=jn3y!vM_7Rs~5n%1F*XRO%ee!K&240H&Rwa@ENIq?rlBWzEZJkdcWsVF1Y zx(HgI?w~JV#cIa>bO$4!THs&+&nb~FGKZS2FYQn{X?z2i-1>~k zga-7DPQ3b`XYD8>*S@Sns7yVe=w()fGIB*L(9Ku5n@X1cDr`Ify|h1D@|qiMRnWGQ zwJ90;$`IOCxzV-`+TQA*uV#g6cK((bO{*Qcm1tVeW=0vgncoG<<_`KMMo}~K%>X#1 zWagW~BW+@L^~Wra7akb z07@4A4JN(GH0haH_*V`hnYDcH2H`g#{MtePxr6>AQz#kuujZir8QRq`^P_`DM(FQs z8kCWn#*@}jKixt9yMum;xzz0Yv;*gF6ZMn>ObMK*G`Vo1jGXU0@WrO-=cLIMTgkj* zu`sEoI!7#3*127pDvnW5MvhV&DDi1}O-50&?sx}E%@8Pc7zJhIDD{AH5pyUR_eBn^ zGIlRmCk!&n3Uxp6I^Kt;W&NIEpnYnfIs=8ppWRcsDfO znWm3rrE2zlrx{^m9r~3B8^CWVnfHNUYuV5TC1D^nhX=HYDZ@eNr)?~&)=??2b zU_Fqg-_KY|7XE;P>V5~6T)3w(4oY`84+Cdbnm&_pluUe<17~IkoJSZ3r8}H?z?sV| zYBoOCp;`%>`AmS)9l=u|c#;X!jQq*)1Wz*oN_Pa$f?!FSzL+7Dtb7S3$N4llnpyc` z2bIiho^y+_92l>p>C4je7nwxK%wI7F^fC~rW9dZ)lZ@IGY$BBIOtc1UZ>H&0Y5GcL zQ?v6o9Y|Fs?n(!o5=d_`BT9FSo58p#P2a$PN`}74!MDLdB~A7YBZ2d6|#Wo#soSxn8<{5i3_S_j>6@=6;cb15ArW-i%lOWsHN; z9Zmvpu3#25bH5@T-$0_6v1abe1OZJAx+Zp)&V?vP4#f(w(xa&|NQgSIOMH zu=g_ZyDf8X>Q>{`(5SOUC3Dw9XiRpiu?;k~O4nPmQZ;jLWky&_hkhl(u4R*>bZ7GR zz-gDR`x!^g+}i-rJ#C37bAlfYKd7e-QLz0yT5*7oMPi z2~fHt7zBa=>3T6kD4F{JOpdS8R1};V3JWgoK1w%or!J-+vs$CRJwi}v#FW;Xa~|L6ZbX;oDxW5nGvNs#tJb0H(kG* z0hP@CzYe~;9aPd};~58~JDf`3+?%dXVjLxNzt@2?DFn{_jDyl0&NSdmWfmoKpX$&o z<9WJUjkBO}CTmnO_nFWbEcKereMRZ6ua83WBdl4?+#hkMMl1%>kGV{M(jCFmAXt#D zKasA_XAU)UU!YDa$lRa6k=JRWF*Eo1;aL|lD@u2)FM##AbbTp&JBc2gXt| z_a7ZpKRBr5g8mERpmc|G3OIkH>%TFMlDYrk!1*l%&R>j!(jAT`1CKf|i<-HgcBodu zCMts;WXNzyP#px-GUVQhnz>iYun$#*AeISGy0bwo5S*W($1#MGxu2g=IcXD3j%MZ_ z=b)0APP|);OMr24hF&*Aufrrt=6-R8vDs4>1nO9-<6x3ednua;r8^Tf0$YO&y?%y% zIkTymdjkhjeG~U`2b|)@#>|M)9b+>vUX`JH8BodGuX6Bt9aPd}I^&>phtmo;Ei?3F z#!)i&mJXcc5IC(F2chib%PApOW<0+j9ux`QA)L%%*l@5~%(=ANxiE6Cih$B}nwqA@e~&f!^m zFe^%Tta)JVlcDD@sG7O=0hW>+R^>S2g`h>|j#qy_#zGkpR+W*t-vX>sW>PZuQUGkD zRKk|I4`a$HHWcKy2E-BSdVAu^B7CX+#h#P&2v!61$_bIpmc|`1UQQ`^o5M0WbTU{ zI15AIEM**&?r>fN&hyNoX70~BR4ZZg5)+_wN3a|OuP}j{xxW&gU6?L-yR2* zG}(T}LFo?XGvIuhp&wuzC3FAOfpZ`P&SAzu=?>=@a6V@iC3FAWp;^ZBmu@wF1C3v? zMkRCq3L1l@Uf*(GQM&8v326SFHLIEX_YT#F#X$P;BNL!>NAM>Ie$UWPX6U~#hnl(n zu1+h++)v`j$28HHnfou{Sx+%5N_VU=nfP^_OkK;AyC-Vq9+hcJ4y&|GdjbXMT_SVG ztG`;N+|fZ95!S~>=H3EWS2L56xnB){gOp0xGWV9O8KpbTK4@-}skdU~YUbW1)7U_1 z<=_C*A(1!Z)t|yRDBa<-2TnU?Q8V{;aLy@;8EfYLmmt8a|2if>>5d>HGgRgtP?pKc zP`Xpr8Qty3-BmL8jrPZqV43H7c2V*AN=JyVaNjjlDAUo~%^O+awb6O zj^GXu+|C4Q=6-v4f;*W2r8|Q0Ah;(}AIA_%=6(+*$I~=9nwk4J2bIipCb-3T02udY z>i1>plbJ-x-0wFB^nD;u$I@g6lZ@J_Y$BBIO!P3=W@YL#Gxh1rre^N597r=w-02QD zC6FFrMwIRtp8(_hO#LwiR5JJZ4!*}6RMKQmG7d_2IL`oQQKtSh<0zT?A_vaXA#j#3 z4oY`8F97E`W>GTt=Ny`4Jiq8x<15g(j5R8m`!Z+@mU_L)eMRZ6udhS%3f8PPt26ag%%NuPZ>iG?GWXRuGO?jGb6*vnbv?79bjP|CtnX&( zn;BHi+~2h)hgF*$@dD^mB6G*9e;Z?=j0o%ED1Od8BdepHmKEeV_q43aiTA=%_RKvq zOI|aebf@`xXzrY)cVy*i=H5B$UjBw^M+XO(j)=S&ul}x#gVG&NPvCTC7BzG4o>e(% zD#eU7bAPZQ{T>Wn{WmZHN_PagS)nrbfU-WU45d3|`RHyQcUQ^W^I-1>$?vwzy}w(H z#n4#D8kNkwFoeb%-D(^Hjf1oFfvi-`+y|QxHqfD8iLjw;a+K~&J{&m1vhsbCzG?riFy>|HbF=h0Orm7&^UMJ~7X<29n&V)SQTqg& z2&Fp{Edkr&EPY{?{uHyRnfqb~(n1sWDF>VqNK2U!r8~x#!T3^^{sIFknfpr)z84%+ z(qykN4oY`8Zvf}@EPVyzD4F}~4xAMsaH<#wr8}IrfU}xel+1m#L$i$MwQe&IF8M+~ZF?jPHe!>W%Q@dD_nlrGY%{~%+b zJX@@RIr!c6w~gPHS)YTy;E|)hnIn_;u{mohCqB|ptN70anpU+or*hI$WUaXkHT*@V zxecq{#F0gG@y;Z#jAfqj!f%Oy2E-GSeu#YuADU!sz+-T%?W994(WqZ zK<3hGwj4)W+-lqjjXQGmZLG9{41qrxSyi|RM_v>k#REco{5IIhMatrV~ z08ZxUzc9dZE5Jz$z%L;H{%{L$8UTOi=%*OqSu4Qb7JySB0JL0}E{Ms+-P2q-Up{Gd zeiTe^nVU@KSIgxaq;56GLG!t}dUaO5h`XLi&ObL7fkyvVRaY_0DYAxJ^>v{Bf?T~O ztDny5JCphgus&>~h2d?nFudKcs%8j`3nRqXX)IZdfzdEmzk)H;B@1)nr1y!#T(Yjf zk==B}x@7GY^EF=mP1rdoBN~||R#RXlF_W@nCBYDTX(-y3tY&UCwuHvyT)jCfRhO(} zX#IqjtmX~^(0n3HfLH%DYyy<-OyCEQFIR8FKlUCt0Q%+XeHlPmviey7`i1}~a0@UH z05|69MGT-USvOh$ib4PkatkmN041zlS+Yu?(K0ug&cBJBkJ6pWNNt}I!@ z%q8n)6~kPz%G|0S1NG&(`faRUS+dHpFnmS}gSlkg76Rk;v&R@fS6S~FOV%U6n4PQ7 zU<`H1nhlO)#9=O3GjQZ9I$~Y2z7g{^Uj1{}IVjK8IV#rUz?#QQ%91q?hWLhtqHW1~ z!mY+d(D-z&zJQggOV-oS`Xet{3mgQX`B9hvul~hs0+jAd@B)CI%hi`Mkh)|&2Z*D* zWGxL3^dbYHbO*EoK(FTNFEfz3WW8zudO1AMYYc?a9ndNOy}>lflJ$lIKrUHtvSyU- zG_Qr`HLO`#veu}Y%~@+5Yewl#^JZw?l&f!G<;s$^3CfKnYXjb&q;XuZq*-$`eV8JQC6=kS;w$2{6PzYxnvy; zf$`PZW7O^2!_!6lS(kVE;?L{$4RSmG?Y?*dgW}!xAnv<;wD0;y|2EN z6|1-MxA!$}(gfenPpQ4)wxSPuD`vb7?3iQ%``~Hv{ZAYQ)Fl$q8-5(C2 z?Q=KUzJ|8ref49kP`zz`+>EAU4&6#LeZyu(8M&E%0?LWL`uB{Y-m*UdfYUUj%!h5i z50CUSBcY5O=@gLu=&S$6NXqT{KO98AIf&#+{}-d6j2tC84}b79Pe08l%B^}&p4~X7 zL!iXu$r%V`*pCuz~zpx zxXi&LBeWr#24&=?X$r2SJpIZ%y$N%vx8;)@I9HmeO&nlK;51`Cl#%nb0$a$a+GwSbYKqUR(uDCRvEh) zZnSlRwk+1B+=kDBwqPk!XYM1)$orTLt=F?w^%nf~4z-B8K>E;)wWEw&dmm`e$045{oXS?XJ6(-89C>T;4I413m8(p^qL%=SN}{#K^Zy9BS4wW9BPI=yMN`R%@iZn4Er6S9k2d5 ztQ}?K+UNBTm0<@I&1Xd@BUiKl-F$+(sbttsz{c;8pKTAwKIKN+VrW~)+LR1?VF+!{ zxY70kv_02fU&;#A4Es4VnwC0rE79~Kn;B)~W?li5SNrQPGm4sFzY2hLWNI_RemOkS zYm9_4a-=mtdb7V?#Yjqq{icJc%0VO-<+m6GW#lMt17%}>eLbTn8TLj8%K8u}n;8XV zxcU52bn_2un(Jq_7JqIW9FcPM@H!9Y#Nl2o8~)k zebZn6s=xjvbEz5jHx8VyOw=zOU`pV8&wMB&=Q|0$U;67mF`SZN|Kec#$w4Gd^&6w0 zj2z`3p#0Te|C3Ra4Erw!%AX-nPBRM1$WdYn@E}ZqOk$J_JE|b~;#RG|g|>5{tvYK{ zGVJQm7A$2tuRx|uC?oG^7$gnTOk@sjKF*EGi;W;m1PLz>zHUwuvfqn%;su^|ykd%b3>Iz4E0C=;=u<`0| z#7HR57U`3VaoaU6M$=H7i=sEZq0haw#BxB6EYL?3=)(*2VGE1@zWB;HLJ?VO+k=Bx4yP{n!YH)i&;#1l3`M*C+u`8-;wY0dFct>L5rTPm{RNY>HgH**+KV@Qp<#SYh-}nM8iH?n=Iw|-h zy4C{C#G95xGo~PMQXlyoWNp$v7W79NT~j%}j&^0`#958OFuif&%K)ZFB`>ujlIGZ$ z+-K6JHLeiDQiT&>H$CaRl6g6Nx8tS$`yfW_0|om11^Rsj`ebv&j>g%<>Gq*IIrLDy9Sy3cn}eZ3aYr(R zns27)-Pki!T+mqBIRSP~Tw)zZR_$cY#MLwtEWiWg4QZH}r}s9>hDR3Eu;9@6Swv$K z&vHLdP&omkZbGA~`+&QkhOB$PWiWR2KZGG5aql8Sgv9X85`DUxD%I{M!LKA3izSpH z3`=|s<#_pDq@N9X33d;G)&KtsSQ3H3vRTI^H z0(C9X__7F{Cvi}?h(1O#6c<7Ogg=EsxQIT(MXTYWRR#JR1^Vj+`U=xUi*PpaExU_W zgm%$0)L@;>Mb`R;i>_2pw@MYu&bpuuG^?2o3@EZXaFyx6*DVfw z!{)%}2wQRBI@5txP2|AmQP<+YHNt@};Gl3IeT>9`FGB!?zl1_KkUqnKTj0QV3iP)N z^o<4jdeecg;B4YHy93vUcHnYqu*2p+Ykk9kE2!c~s{^;4r30-}g#&j4b)Z?zbYMV{ z)q(Gr4%}#Q;M+C_t|V;5fjdkGS~Zaa-#}f91GfqXR^gyM|KCk7utdAs6k;jd7aY=1B-f4p(V%!xXRkn_Z277 z>#5DhHm6%_8cyFp6(?Gq{?S=F-6~Z${o|lcH>;UW4=A!aeUIt%_bpD}Wpn!5gsnLJ zW7FwYP2}{=sB3ZhKH>Cta1hrcuor4M zI=Rbna)xNR3ny`L41XlS_NcuZ2c&C!U$ZmzkbvX=!Wnz1;{U8Oj=OP2AjGga0aI0l z^TkI5ulVA4NMGznT?8}?1dDxw4~~#OKsD&XmPSA%^W0|;0O6ma5c3>;#ys~k=D8mW z^dAcJ?+Wy9%z5rG&L;k9bI~`JX|CnH>7ywaj!?yu_6gBi)0Q=Ujs{gH1Jjh{3i!3g zxb8dA$oIQ2!xtnujVCuBr6gfn;cD?jBOoKY`?W^mTIHJ8#4)BXTUO~fZ&78P-hMQv zx9=>|+Yi?1&Ho1?Uv}VY>OeAgpslR~_KOT7?fpORKoU9tzkW~fO7#9(0GEr@*lI3{ zfge!U60pAr0Vi-!1T1}wBw&An0P%#vIX(Cm`JV-NwiR2N{-{DJ8l^kYF^1^qLKYpz zqEWgNUDFU{AbPYpvT|@NcEE=Ud(Xoc;D-6+zEE=Ud(dQYWuQWto&7x7d z6CH1ePBujQSTxFrME`6A-xY@F6hm|xi$>{A^nVP|>4xa*Su{#_q7x0#T@BH_Su{#_ zq8l5ca}3c1EE=Ud(Fum=LPK;3i$>{AbVEb*5JU8E7LC%KXs;o<%n*G$i$)od=wFQB zYh{QYYlyC3(J0-CZfS@fZ-~C1MWb{lx}70{AbQ?qT zd_(ji7LC%KXrCc^u_5|J7LC%K==O%_mkiObvuKnNiT(}2hc*4Ah(Wxe&&U(23Onj6 z3&kCF9Q+*z6W=Vf-J)DssNAAl)0l2iu4zmu!XIc*^(M}*X)JFB)%U#xKu^V=I6=9C zChy{`D%6tXiBqH^Gga=*b)pMry0WX}J9i@cHsp=3W4({Eg>GO>tRXh|{<5k?wMzU< zDE-5Ij>AYcaY19t1kElWQ%vx!6^MTm$I(P3EOG!BYni9SY>EJarnUW-B@vU~aruWf|a)|+07!NJ703(4HE#uh>~*|0i_ zq%DQAacrQTCmxl_f#=e(&4pF#;X~Xrdb<$Eo6+rDx!vv6wB!l36I$Ybs(qfUeGNW( zYVol+91GLDYIC7QKnwj^Apm{20EMt6eTFS}!N^Yd9fkTf)2MZDHgT_gC~ONo6fQ)AsvTs%wjUJ= z1$A*G=}Q5B5uM!2;{?%UUMAd&y>Ky3498t;tNE9VZ0$-%&3d+)GmJq%H4~Rxckiv( zhN4Ss&6P1^8$M=x3?GbrxnFRpO~7oce(KX{L)B%rnvdFRYDUff*lNzV*ED5bj+&%| z$J-uZ=K468bX>emAW1vP9m2c~d|!#f4Y(Q4OK6rPPc%~M$2azUjTjW|t$tH%oDAWj zp73^K5@2z$V$Wc6lGUgQzHbCx69_rOoD^1tF(*lBiQ$kEx3^m(e}L?!pmU$-JI%)d zk6#&1p6H^n2z)Dg<3)X8eYpsbvE_**oXCkuf{8I8ud+#1Y%E=1ghx{rs5o86!KCkm zsOBWf;`Eds3?~vsd}I2o-p)3ifX8oq-vbaez;rb$vV;jv;zTk|B+hBWmb->8X$iLN3R9QduHdz-1u3%C5OgbUpTH`Gk+mJ-7 z6@Ic=0iVNIfog~1p^z6IZRqnl8$;L`yRf+}L z;$YIxLSri42D*N_zV8=a``SBEEPYf$j`|qXomQ(jM>h{Wbo)Ajut;}IcOE02JD?_+ zQ|V3`4q|YC9I`r+EYp`U4O334-f@u2%F!e>wxRD=I0-Evs1vKQI0+|lqO+;N_nSD- z1qZ@`L;Ngj$|_zau!4`pX+D!)bh3G=%D{*uJvVbCO82 zSTY-VBVRl&r!^p@Aj<}si0;6AB~Nt22`fivk9KDfibs3mVA3B##SP&knWL+I$|=>& zO1==N=KB-=MOCo(V#OB!;v`P=#)(8NU#7XYoynkL3JYsV#QBUyR%2LpdPR=@Zex+7 z=TJ}0$kiI8{B6ua*2WHxHun96KA|qqa|wNCVc7a&C?%l{>i41gVJGLXJqxSH8aj?( ziWbv-U|jHQ)t`7a7E05X+e{xMMlEy>yIA#8ZXQcI7s$(@0y4Fwu_I?RC!9jmbWAwK zIGFU0u;7h&3quaD2~^@e5Pm6Ik)k(5lv1@Y1O7DpjT%rpkm)QjjFUJq2q(fj)?6sg zG$mQ>6xPT=oy?9MOg#SwW2(gFm(Y$L!lqQ_p__0p$s=lKb~C~^1}Zf5a- zJTVL>{TZzCDv`VTk(TrtsII4;qyNoCf7lx4^=u=d*WytV#Y%{EiBK~8~ z{Z}$Pp=8uB?vst8UK}pOEfijHqlF#IaoDz!$P=Sw4@Bj7zSnj;9SgZ2rol5klX#?%r(s;D?iIJLC)44h z_AB`#NYgFP-CH-c?nMJ@WL6j#p|}M}yGs*m_^Pu{?mJ^uiy+#b`mJ$-FIHezqNy!J zk;6JZOOOk>fgdpLeX<;Rv;eymMS2!ka^*VKWI5o<3YMkik4Ai%|LY|n36Si3| z97W)&!BR`Hnous21&fD+R^e&#At1o5FecnOi$RrHeKysgf$|96B-IcV=WxZ-)-f}e zDn|SFi6!+yd`SGLupI^#nuy+~Vy}wc#HM0k(VKHqv6n(`;!|;fNpCJl#f3J#shx@o zE_zcZ6^SjqxhNGY3%#kAid-TaJfts4YI}@S)8-xa03zDFdjbL=ay|+XN%R?;cXf+8 z>UE0r3ySnwMf&+g#y<9wIGcEJk!>IQ{GyOUegPU(U4Zj58l^NqQd7%(3#CutBz26f zei7mtb#UToY9*`s8uE;=5XX`(;}4suCH=HKZJxf159(J)E`}C4$Z0GG{q~HNnHY?3 z&q%Ez7Z=&~RucXPKa_AMQq4r;DD^&v@-<~4SR8pFx~s0t;Mp$yZ93NYF}>emHD)~e3Y zf;kXRDJ97k9|d&zny?@ClN2Riv#1U_nJ}#|uvK}8i=B^2sYRyJ9T7W5F7pX$!bl)P z?+)0SDG9XF>>xFZ_BVn_jYvBbuCXv-qEPY~>izF^-hU;Kq@p9FNWJ{Bn8ab`z-%ca zLr#m97EVW_3Qdbi&p&gKU67pRFF5U?{89K#3U1v!gi;N#$z zRD-56`WVSQou428a!#NSQyG26RF;gXta*{%tVqAANcWmk+0Qte*wQ|gc|%WSzfgl# zMZ|4xmY>8isQe8@)m3PUJ3YK3u(qK0n-vW2pT*Y6~f{_bqS& zCvoC$DeW|h#HHQkPE9Ob-Ad8INz^b_Jb9`lwpMPcQiopZ(f9Gh7LIuuSp=QI&P+R@ zQacB?iCTj|evHD$#OnD{_1&bpr8$*WC>Ihm4k$UW<+)Zxa*SI91R3MLRDls=V91Z> z5Js~iaXF61DCLuq)#>0>=0SO{B$f^~$3fWGco_3sIu_D8zVigqN)vr1-2RRKqLo^I3n*1@)u!b7|E)E z6WAa+gFVxQJ^uqZ;a2(aa(v8*@u$JhMwhN2{A<-NT}8*@xl0qMOCo@)u66K=BLOTk z>}A!!i8J$N2;OD}ul%SB-X!p1R5T~5tBQ=lL|+y%AFWNMbE&)sHyOkf-0>F6A_f5$ z-e#0Tv>-vPOeGT<#YRy~#YY*-OG`qE_Fo4R8UfS_hpeKVPWNSU0JSFZKGoW3bnNPg z0?6lZh&U3kd%z*K6K8fvM`83Vz=;5oA3NeB0w@c;H@eh`@Ke+-^`>K&I0Gof!7Gjg zH^p*SiQeXN2JE&8`W z0OXXS5VoSvSoCkeqTi!P?^dLDEz-M~i~ca2P3&!7^t*&!^oOHCRqwzWs3elK2Bzc- zOW4L}DQq)vkDN ze8t$L$J!pyF6EWmv@4Dj_yt1mXeYirF@^+4&AvjO%xq9v*_+>z}eg>PprWSxU&>? zFgo`Zb)=u#x%cRpvII+a_H&SnBf-dRC(cZMiy(jBNiI)(Ajp$I4tMUN4>3vPPK;k1 z*o^~nmNO?W9Nk0JqWwjvW=uPKaVYdyPZ`D@|B&Qa9I8C_VNSRWeYXnj`%v3vZh7J( zoB+qiq_hoZG~$9NoM@V-ZL7OEAIWD^&S*@r93=RL3%XC7bn?UjoUnFMnb(B~V~Ib= zBKXD=7AExSQyhd7U^09-gb)8JJ+gHL>5;`2K_)25t3R`WD&8Q_cmwo^t!C&h9Ysyi zM{B@*j)O>L5HQesj6Tp-0(Cc%t%UC(0CK)VA+iekjI829dU{wM?r{M=mlg51U`7kI zR70=~ne4KF zsj1u4CiDpP)Fu>qzo9|Zy_9fLu*BB)J zNJ0a&j>So9=M+cF6xd`r*H%~QimmQ>tW-gb!$C2uh&+;ERSN@0To|VGyJ8QEah*##jC((Qso~Q!$bHLM zRvr$iw}S$LL*5Ruc9=R4!#}1bk;O%qxE+*l1Jx{`jm=v_<`1d$M|C8xD_{o$uYmBB z-+KEW#48Gm=lGqsVu61b)%|T9w?#hPyV%; z!M4uChPU+)TXkiWT7t_q9}XoOL?8 zG|Oyt3!1BUbHq-gxW<>7U;;ejto{s{X*8Kf@@~&C2@f(ja5z4wgAWJGs0O7%7>f~2 zC!-($a&AK*rW5*%>Eta;C##F}RYm$6Mf&UJbW)D9iR zLN;QSvD8q^Eo!7}fWJ@+m}4N$vc#;#37o`<+eyzG(6gY1?`;TNg|{;riMOli(n$EA zp>Go!;4~VHbxOiXoVdeAtjtxoZ}4yv-)2$q&NEb;-$XvZI3K%)HgB5-Gp`!L8UO+F zP!p?-oK}=oL{~+mNmJk`(s*eLycfT-^$tuRJ1`C%NSwzPKTi>*a#zKK#8!*A%XCKR zXVXhd7Zx@F+Y{IqeOK5OzrtzvF-|0b8{QeuCwT=z0N~&R92A3qK1Q;pPJsaN-TI4+ z?+v-4XQq&wYTlDA~842#F3;QgvlSGlSk2bsZ5TQ zjZ-l~jSIh7wwj?Y{ASx~#v0kG@f9xfTY3-MYSysV#B+x7dwP%9YMR%vhD>v-dycJU zj9sQ#^HE#PczaEAQ+zIJTBhtH!gTX+FzJMN`#4EDXk5eKY0@9X;U~BmU(};nl05Mw zPN-{(Y#n$c;1FCA{981pr*y#@&kQ3yQfKm z%dkKBNZ+g!Po&mpIjLa-x)ywfdU3o6p8`*+HuU`@jJX8oEK3F%Q=V8VyFuq-<5|#i zbWE8AO(e{MDL-?H@Vu(eYCt6vX+Nr=?-#-Gf|Em@cu{hM6=Lwcgt~aD4IJq8GHR$k zhicNo$)TNKHdXIDqTMAniRu%nuMjjnXtx}1!gf>c_{d@M8Y(CKDmuE7+L^;7 zCc$@79DW0bZJw1UR^i0IA0}!dX0;%eB~HZNWL3QENWwKZnDm=Kd5bh26kD~mBx$rU zY}Qe&-$kwUcpK&6`+; z0=*drlTHay?~o`{y(cc^Zz~SIGo^gSS3Ca#9*%+HT^4Pbp>Pr>w%|nQ0p$A!8srp3 zZ&81%Q;6oSOj>+8ozQzv1P#>uh9gTdVd=C<_2>}#P@3es^gI;yQ z`>0BeRGhF22a~j7615v|!x${8ICPK24L(n?mV`=>w1+iWe1elWv6oa#&0m8wSgUv) zd7dN;VhbdT7W39K*0susD=9@=-XuFET1foRsY;&MhZ9y24iA}&=ts7iq0@r>wwj?A z=8qXmvGoBQOo|cM2k};{V4vbm;Jw^I9bc*yD8d$sAIbbnki?CX; zRC)M}RV{+(8g?zV2+tANN6^$Z7swMwN#=KfBur6nIU&WFdsv^N85R+cAvnHZ;fl?U zQ4N~0kK;{Jby4vvuE<+xati#0Dn|Ri5Tk+;#>8Vq^k_7i2;x*^i}WTo6&|2B=cZ!9 zq&M-Yh<|!>K`Le=dQ&?Uvpv1JFcs4!y}2kAX%g+olbR%{TA?gKG%4XvF^{%ZP^QOV6@tt( zl-6AUGOL`Pf#J0=ux+?ZT&>i$)pcBum}^5F)WnX^g&d+OFmh5|{4ec(A<2>c^Zkd- zUl+&J)r9O>%Zlc(0looce6w9jgV`LrKBkM5octnNR~%EL*_DfBSHKBt)x!rhxNz_i zszJjAu@=#Axf}u@=Q0#xxX@<|mnIl4jf(XK#d`f>{c>}-T!FKRSK5cm<)Md5eQJ=x&lO5AVA5JH{M!H(tLmc`)~E(3W;9Ajxf zS=J=rgFx_@JE5=Zl|F*J8vcG#rTz4{D~BV7Q)QxBHy(f zrB$3lMo{K(1kwG+DYLPNvhcm0wAX=3gHm? zjI}cjYv*;vdTO!WwpdRw*Us)Zo0wr=J5w-OTE1^H5*x+mD4X9|X zrQ}B9DzdZaa4*!em?RwoMV`p932;oj)JkjQ>mtPD5?7OA%Tun`(IPEkAXO~ga>{Cp z_r_DMW;d})N`I4fDX*_hyOIwH{Og6@JSV<9kxxL%yltwZUA?YIBP=#lu33e6RDc`% zJH^Wr1;i&ilakHDqmYit&ZczZV?~6aEUl(p$bPk~5dUgvHG3gb3oNZ!FsZq;b{E(; zIYaTFsOenFL6s0w?fr#LbUM?~LG^aG|Tr(T2{Bfj3;+0i!XK^9CU zx3O5zSykpX0qv6GT`SpDwn%Mmz%q$-KW8KtWCNR(Mqd|?M#t@%fu=*=Y3)3I23SZt{$ z$rF=t0_g{M(8qh}Lrju1z^C7>XRAeKNxisp)d6w9@R z9(wOZdhb2--h1!8_uk9%(Ii?saAq5iKu61T*X>}VU3e6%88N~Vb#f3V$>4_pqw5s>VQ$skr)-#K9QE~~QN=(3rrtm380DyR98 z?W+`wubEKQ@Pl#=*#u2ixva|mSC{=!l~ue{S>-f8vLls(@ns9D8h%jDA=?7k=U*A} z9~ts*8S<|z`y7R5y{*Et&tH*Ggk+yv)sF{kRd2|QMnKLVYC0F!4tx7=>_=#g!ISD@ zsg0qQSPkKWC&nsKnrmz}&FFE8G`IDH%Eq==1IH^)+%3>n5ZtPM`oQuQXlOYKj(!VN z15ncl{N=e0pwmPqDI(m5_x^8*yaf?de~MClYP62(m8r^=T$Rudl^tbY6oEAP!?!g5 zY4FEHMBAab>AA(lcB0mtfouGoDgHZcL)#?x9;L>F7BSqTWd7Ve%9(j#hkXtxv;^GG z)9$6r(&_M!F#&pJ$lWvKt{HM? zHUSpkS#RI)3DDVk0xZ;uU#!Fp$lx0}G)$>j)SLR7vP+z!xhDc-nZ+6 z(WpJKLUHY>ymX2iu6nK{Ps;fePwk1-c!Hlnp#X6sFg?|Bv`@jsjSM}1vQR9Ze+$>p zR%?t3coI*nQ&fDRwjs=8a15|Iy#j9gdHVD`hGznKeG-B=>LVZX(3oh6eX$T*Q2WAWpX6gh1lP z5W-dkfm@wI+ctJAxouZM)dq?kua>n#iR+n>+wf1Szj9u%fO?}iO8uUJw=~yXN-XQ3 zf)U!HiS7l`ZajyN7>`32=~4%I_sCH9L#q2*a7XN6x7rCxh`xuM^2EG9rnl$0yxVh%8h4&*FgCOX z{5x*{ueaw^Kx;IYh-OwO&Hu;k2^zHL6}3IzLVM!mDo%3xD@&htWFPB#th|N`9q`wb zFlCoerb~X(q==`~UBU^Y?h?v5c8OQ$<(471g@#F%4vRNgD3!MajF`AP|hLi z&y_8WE8d;D>_Jtw46doN%4vRNE1&?VrKxK8K{D=p!`^^ z_#~_F1xz8wI4z7$$Zb}U2N9_? z<~}QzW32GQVJ>X0on|g4tX!@#mrHr{+6B|4Hx5A>?%zP%O zZ!Lv`{O(gtpS&+Im*<0q-RC*0sQ<92e+NxgxG(h5-Q=e(C0?9p{UL;v`=##xHghRv zvWC?i)J%3tF*q9{85@;N;34x+m5-kE^Sy!T3SVQW>FnVn=B!tS~ zKXobTixaIsdWDr+TlXKtT>4wNj9}730n9BWL#$#Zu$Zx>O_!3BmCG9DveL?B3tY6;-dNgfDfvbncG%wDDO|?7*Pbq8wv^OSd$gcc(f?*ezodkRzra!Etkd~ISTviNx6A6)yHS>Budh$u zN6h7ZS;JCt*D5M1UN6`gZ-UiOFa0UuMk;Tj-y;hO$vPi#qWC^RtI2QSyl}kD1QpU<94K7-1 zr^K5L$|h>XldQr&VG19inZxd(RWh&92UdlB#R~h}Jn}Q6Mm4L#>axOWn-`X071@AA zW|~KSYZci9ky>LmvU2&E72Yh&h0V3!nai(ME^V1ht2}zGg)-?3S;0DtIxs63`HjmtB6}gW^ z?lzCyX%%^dMIN+rImKL#Te)0&9HfqJsT7}l=8^xhiu^YswZ?qO%H<7K_-kP7_RyKUL~SoM`>gFs$7Ey8lnirKy$6A58jx0OppGU#w!< zu$Y$NW2lSTf>~CPU07sC^T_sAk$qTXPxHv`R*{2PWPdA{;mqZ4E0^(b(OP?q>7X2> zR(zCI_)MlS%{VTmnAd2MRbh)*Ve`!+bBr2utO{Gr3R_`b*fOig%`9?*dE`2)$eoDP z8grYK%RW~4?l2cN*A6q616D3)naim>dhLYiQZiKS(PLIcUuQ*Mv6{0^=cTY{HZxyH z(szUBlK7Q+gg$v+V=k{G8J3cltfJg3>Ww6m6>hR#x|jUarQ~g#X#G(vtlTNOzn{6t zRxa-|>5>5EmXd%~OgR=)CMj$q8>O~?&?>S5i%d0-#79iHciCB0K4y`X%_Bdwiu{a4 zern~C&Ro8*a;Xa!t+i_>neA`W)rx0Wg*Rjh-y6q8rg@FNwJPivR#& z!3z7+ys+P`BHOdbw&szots=W3QftgkRxZ6*;oZYr*j($+T>4nKj9@N9^XRo9%A_;A zz?rS~=pd`2C$XZ(Tg_Rgb8J{N8_r8u^ujQg9DVYxW-cp?-MP#vY9otUXNI*zFMS*N zsY}UjoM`>ABdpw|y8i*@ve(MxIFmjSzLXrYiaF0>&V-Mld20KgvWmRHBCnc9Ubc#S zz#{LON8YxIj7ZiufX7xY1({2MWPT}QP5CTbwALd;V*EMIqP&*3yWsMsR4`540BnJ zKy`jMWiE}4-PzD8>Q@%^lNr`Fz4SlHPnBwg6Rkh8!phyQ`)4zkHdZcOnRF)rb6H6T ztC+qlrdRkF+Mu>z539(bEOM}Uffar>%!SRhtIXw+mCJqRawm^oyJfnR>{EO6hE>r8QuG}vBE@7WQRb}E z=}6&sCN?tzEIK;OZ4SX6|S&e`e)>)N_~YBtv@~wE4PU5|21=|Y31@QldcP3ZYlZ3Dy9*OX^;tz3G+MQiQusb)*bv+BU>Y85_& zDGW4@i~i;{>T6ZlSXS65^T-iKjbT=WO=E>kHZN?VRb&o}oNXRC(<*W?BDKa`VCAxc z6}~jgh0V3K%w?68%Xa3nC68X)q)a-)Qu2b@qZ_P>KFEsRXEkS?&OKq#Y-TR2rY|Ln zt2ye_Zy53`7;aT}el^E;++|Up)N2u{HQuUfjt1X_{ML$BciF;9-&oC2H^d{Lmc8C8 zZV!vw$;Z8+#%;HXJHp})n#Jw6iaW*Pj$65$XD(-~T&}@IYmm#;9F3Yc3#qU6*_4Z6 zk%@Xc-DQ!t%p-4DMLMeMnh(t*?^{I{K&197G!fM;y00)R{Hf}Wx(ys{Bj}f}JWl76 zRzWYYpyv?OsCI(}A!F)8wg3KQ6)Q0&PxY|T_^}%KM)k1K_^IB6?=ac7!b-2MyS&Rv z_k%2?cfL}~E@2f{n#INPah27$_pIWQSzLlyT)b6WMHW}y%H<>G@}ZSWb+~Awv1)bG z(fDy#WKF%D(plse=8-k5BI~fougxQCSw()wDpW7bg>_#eR(Jz6CqEkhYZde}3u=a- zu+jLn+J8S<#r9=Py~0OheKoRM_-M@3n{Wt|9T-;n_qxj{R{C&$bo{86J=7|05{nzp z$JJ5e##+VAVsX>W;-*@~&1Z3Qtz4EcmxWd?tKp)J#uerxV_8__PkK9TVv+03BiC9* z?qreM%pcibv=O$~j$URi@r z`hVA(YBO`$P{WY)ud|BU$)dK^FiHAn=%w!?KQ-w;j1#Rt4}_IFQ};i?T#j0~oM+N! z0L&%*r>tVGvzRM2!jk^K)E2yC75RWg-ZhWBZ50{yx!(59&rLNSTSY$2BA@)6?={v= z&oY-HRxYo=MQiOBKQ~MI=c*Nd-YVR~6yE&YFfLveeNf4`0 zA{IH{JTk{BauthQZXUVRDslshTx;dBjk#>La@hwLt+jW5Www;8Q!BpHD*OafIBFah zhs|qr(5kRYtg!Ruk!Ot>r>zRR%?i6=Uf4CO$j2=5fqCRTtH=WBdSgbU^Am{;-KXKA zz07(t%!SRhXP8T2E0=#WmzUD5d+mjEv!!H{+M`9SiWXSWE+ssCDN*LE)A>eNG^<{7 zL`OIyBU+@tq1u+PPMo(=Y(!*4YxP|Dj*lkkj(YfthtMzZXq@iI{7HWu=5S(sgk0VU?;;V-h@aCPKQyXaPbt|+UkwuROS+?OZS@7XQ~O4d zV@lBxKczdG)N2;vStPPZ6dsZIs*x^gJ48lwryBGi+mmcBR+EnDjt2E`r$l)*tbARG z;B>Y}O>l*Mfr*CPE1sv|v>{p}M~+A@tTbxm$n-)=BS((HH#94a zJ({5nG@|u4MeA#h*4qm0?{vpEcp)EwCf2GPG0Y6s88H-cA%1GpPGv)El96wMDc?AA zzA;vO)68jRq&pfm|3U9?x1*WzoidDOo{?s*Da~winweHKi_B@3n9!_aG^>p?D@|#Z zo6{_{qFHZFv(bcRw>Huu_G=?8;(#{NBF@qzILAiX4kPV0Q`#-&w41DG_n6TZiF8Kp z3+GiX9yYspCj26L{f64kkr8*OCU;p)t{Q7{*|a7X&1-VrswTJ0YT}HzNp#9wigLIe z%|RDYQ`;rfgs4#H$qS(;uZNy^Lrq+aMr!_bqTLr=0o zPuho`^awo}7k^M=jpg?H=NANPd^-{IcSQa<0(zt91PutWy4Ux_*PM-z0lWv3UMAo!@~~ zIPQ}FJ-U9M{2tKxLppy%evj$8qn5_utfkc_0_WI(q9VygX|_NC%|xDEMS-92=*wKB#%TJ0kQY6Vfd9x2hem#j~RpK zC|`#5T&<8?iX~0Y)H2Pbiqx{mrCzROHjAi*lq@Mmt5ZZN5Hx9`4)&mi7g1WVNcqap zd0DdYWXowbGJ$NOW}}kGCe!s4vZ-{vJlQn5UO}}=GnA-hNW|VjGZ+)G;)(;hr0f4B z`@Lo(8_@GVkZq`1rBA9D`=qjIpL}TECl#&wLS>Q8c3*u@G<5kuBbK`Y* ze__0eK0`k=M?Wa9;?({5_t2A8p(mZGyLxNQ646Jqk$tI|`q6oRIv=3fh=HnAny*7G z({(SqR_MB?PWZO9jO$)&G@i-c*rk@^7k+Q-guPKopSo+$ge`5#v(CtFtb;*AW3=EUAL_7}I%^p*EmthouN8E@5*C|o#40*pO?HiH74`+ju|Cgqtj}dl z$*n)Lt=N~CvV(a`=xEy$dUA|vbF!9}dYr1Ir5=}QtG+_^s#c4rYhyMc3%`vnATpIA71b(drt}CiB>G;gP+c0$Og#1tJ%ns zWJ{5KPqR_)YqmhFYL$8k8HWAajd~gP?>93{_wU!O>g6-7mowrm<@yiG3Q3(aL+flT z@)1#ThND^SZyhb4z?0A7by?Pa<(`q6$t6)!RM4srQIYHiWIu#ex~`IT9$8tlQ6JHH z6?*<-?L6WWx?YveKP6j@u2(1fnP#JEXtu!Tbo~p}Dot3<*o0+Go3ONb6UJFJVX{RN zrdl+idK*pIQp#uWxs%egY1U0!8%@i0*38h8A45-C;zViTcBr{xv#BN8lkGsZqh=#I zsa9#Bzl@XT57Wu>oB8DV)vASBWjKE3C(l+IO_)4=z^hE2VZ<|>>^RLvji=`)kex`+Pa->+>=d$7Rjbs$r!pME?^kv=9V1=M$4FxN|1%1u{oCsz03oY1~r7J9Ni^khfq$-&T*Q@JOF9Z##T z4jqm{ONRQfOL|JZrr$Sf z)HwaK%%;t2H>h5(ey03G?WVX5ke-_Ip!mmP=D+Dx8rN&s zv}uD%ncsx`SfX*=ZyeXIzT$ZD#n(E!ySYcY$G8u0!qBTbVgN(-bd(k|(kcakrw5dL~}1FcvL(to)Axpr^PekIq|%BQM@Ex5wD8Z#T(*H@wRwZyeHllABc~{ z$6^bqrPNw#Bej#-OC6++QYSQY52-gAe1J4i8YB&ohDyVv5o+U)MdMFF7tD}mNwcLn z=!nJAQfZmATv{oulGaFTrS;MVX_K@W9kdl)v{%|E9gq%6r=%g?VczlHiQXCBx!(ES z#oi^}W!_cZ)!sGUb>1!Bt=^s9J>GrZ{ocdgW8SmgtKMtg8{T`~cD_!&uD^u z>v7zG<3=1exdym4!`@wYpdI#~$ zAv|*!&m6&XNAc`2Ja-(=oq*R#c%6dRX?UH1*I9U-gV%X@U4Yj`cwK_mWq4hI*Hw63 zgV%L<-GJ9kc-?~6ZP#((j_ZVQ*L703=Q<_acbyg>Nj&gSuN4vX;W8B@vv3QJg_YlXs zdx{g>y~K&`-r^*8A91p~uQz#>K-93LpjS)&I**X66LHyIjd358kDov zJyKlf9wn}Kj}|weoQ)`F6Uy0)a<-tHtte+3%GvH7Bkn*sJ5kOql(QS<>_ItuQO-V; zv)?^dJm4ND9(0cv54k6Zhuss!BPj2vdy;s}Jy|@CpHJX%5|2}OoW|n}9%u15hsSw5 zF5qzyk4x?;;$`<#@rrwzc-1{!yoSeh_YCodd!~33k6Z3p;%)bA@s4|rc-K8wyywml z@4M%T58U&`hwcU9Blkk_v3rr2chtFPyZtDonptG}naYk=pPYoO=4Ymn!LYq000Yl!ET>u=9(*HF(L*D%jr*Kp50 z*9gyj*GSI;*C@|J*J#fp*BH-Z*H}-Mdz`0*d%P#hH35%_o|f)Oo>uP3p4RRuo;L2O zp0@63o_6l(o^1CFPkZ-FPY3rbPe=D`Pbc>rPiOaBPZxKNr>lFOr<;4er@MQBr-yr? zr>A?7r}dNr=NSdr@woJXMlU9XR>RRXP|qvXOMf1XRv#%XNY^9 z=Wq9V&rtUUPaoGtPhZz2Pe0dYPk+}I&j8m}&oK8k&v5s4&j|Mp&q()9&nWjU&uI5< z&lvX}&sg_fJob5(yY_p=xes{8yAOIMxDRRIT% z=2_&v?pf@ zv#`O}McC-;Dy+l~xJu|QZ1VLGHv4)CTYSBQt-jvEHeVlMJ2v*NQa_=a)L+=)8zAiT z4HS0y1_`@;gM~f5A;MnY-@-oMP+`Asm~g;1TsY_(Asq6J6b}1F2}gXRg`>VP!ZF`i z;ka*{aKblUIO&@pobpW+PWvVa^F5RCm?E6CfqH% zT)0b*@O5s7-Rl>uvtA$5p*9ecxt`)N4*9k4+*9$GwwU) z_(5T4xkJLRa)*T_C63^6RM?nsOxTogTv!)#LfD*eQrMDkN;n^VTDTB>MmP|2RyY`Q zPB;{EUbq>!AlwRE6mADD3Ecvhh3U#q}}W#LY3?#Vs*C z#H}$s#hnSg#0@dM#f>q2#7!}M#Ys{>Jo<}M%MB2xl^ZC|3Jel=B@7m)dxnTJJb#Nb zJwwIYfnnm_a>K=a6sN76(ak*LI-h|m=@4y_fPhhUNFCjI5Dt892wXt zjtcA&Ck1wklLLFiDS^G>O3a>Bm_1Vi2gGTCgW~kSA#q0FusAbt1dpT0#ExOLJ&x7( z1XkOV;v&x}tjedcDxblsd{!LbIVTSEoEHaqE{GFjE{c<4E{T(4E{kgeSH#VMtK!jw zYhvfXb+Jp}hS)W5Q#|6ig|@tnw!9;52;3Dn2JVTQ0{6vrfd}IHz(a9M;E}jB0M&#n zX?dW9v?9<_S{Z01Z40!Pwg=is#}nF0*WB%->+WpnuDiW-&)q><73e6PNa!S;Oz13a zPUs?SN$4tFjqWD3f494|EvARGJ*KC0DxsHjI-$38CZUgXHleR{E}@@vExNz7J7Ivd zCt;v;K4B1^8!UBrcZk&S-M^*2?+%svy*o_0kT6`jm@q=RlrU22^zJCB^Sh(*7$aRy z7%N>#7ze%a(3>D#kDe&)4NQ`b1}00#0#l^pfvM8fglW>Xgz3_a=o!+!z)b0SV3u?v zFk8BwFh{zPFjv|i$dL{N=HW44Iv7|W9SSVOV-c7ZgK3F$Hn3DW7g#3UOjs`6N?0MC z53H0f1XfA66IM$X18by9fwj_|gmu!@zS4Qn}O8xH3{}n0Qe^qMlzb19?Uza-iZ%Cc|H>J-0TT&PQZK$JJKo>R zJHg-EJJH|AJIUYIJK5jQJH_AMyCZslx3g=YcZD>_yG0u8-5E2)yDR2z?{sOXw*_7u z^au?1c5#jHc6E*Pc5{vLc6W{T_Hd2y_H>Q)wuv6+T`7(CUUW_H_Hs@19uG|N_I6G7 z_Hj+|_H|A5uJBFsuJld!9xFD(d%W08JZ5?Sj-Ku9=bGc~@0#oFE9Q9HM$hvO56t(D z2rR&3p|@T1BJV0`F?5!ATf{H*4voeu64!EXckc@CU1_EFp|r|-Raos^B(Cw^6xMq0 zOY6J?#r58St_|L4(nfDD?0RvF<((q! z_TG2nrLKD~9{ao}UHiR&*5?2yTNtAyWDlrJKS~2dr!LTo$9~h9pSp_z3RIL zhU=ie;k_u_^bU`{pddf^X?Y!d-sSBynDrm-jl^1c~2F4>^)s9 z%Xg+&3*XsdEq&*TwZfyd?|iW~z6-_L`Ysl0=etxa8;|zBk**HDQLc`@V==kFSfjuWymm&zB?h_g(M}@Qrm1 z^zC#F@||@J_Vx4*@vSTVw{Ly%p}q~phxvN=hx>Z^NBDaANBZU$ALUz6e6(+2@iD$d z#mD*<7a!;A?H}*!!0ZB=bz;3@1Kmv6yG@4RNsB~G~Z+QbUbGGZU<)i9!ax& z6I`=>9mF}liLSZ6yCrgblU(zBlU?(DBcm7iT1GGQ&65`SI(ZlS2Dp~^Zs7G~UvZgl zrfa#cP5cVq6xT{$TXB_ds%y1xp18)h$+gy((zG?n_DF0Q*OId+e9FAua zlusL$$gDf($0+CH$GC~%NT^@0cC!+Ge>Z#>P`gs1Zj*X-n*CG{cWrP79zM=Ll^?l( zCF*205bJ-dUW>pn()qjM%KcM)zHOjh!)s&sTrR~q;6(Mo-Dl;Wa+?V6c0aA2gd9|# zdcUYw3aCCcV#CE$pQgX6KDfn?a=!RdJqbCeKDc3|{KMM;@EM1@&HO)w;pyl=!0(TB zv41h8;^N+azhtS{kZa15F@FDh@4e@8z5o9E{!*&<*MNWg*y*U-_V>TP%!qw7qwuJ` z6Dm&}xNEk@`{}aGXs6@(!cRJs=Tb{J9r%4|^)I1@>DxKzIrXh2|qGF>Hy{0ON$+jV^)6D35s9I zG>2o$e&wg!f2=&}2<4f?Lg;*fuZZG@CY6=(n%SUUlb{E85I=6x=-Vc>e{hw@m8Py@ zzr?=xR(j>kI!ziiZB)OROS_lo`m|Z|x|xmA1OAw}^yEfA{Ls8%X0u<@KTA%p)~Hc~ zrs2*)Y9Aqo&P1k9|+Q>sTjHqHco*9@k4Cla-IT)Xi+* zkn8`S-@$C8-KtEl)8yC2%^IcG`>Anyy^JPxN|vbOkn1*T>X5(8bjURvC2{!NA>$Ti zlg4k^B5>S#y4L#9$o1@>vlqQ?C?P7OPjX3gA;Wuy3o!ceHB-)oVp3#Qq=GLhrE5 zhIJY=uZ#Q5)PYTF*RR*KS?xOCm-x={taDD+AA7#jX>R?aFF%}kvzWVN(G>d%+7MBT z_a7YvE&t6iZsDIrXC~M# zyTNz0n|`O39^LxbPlMCvCYG5xYkSW*!^Re!VZU^I&`B-3oU7igKhnQ_JMyP*3;lk! z-u9yJ{_{qsd8qeprt)dShP4}L^Rq$bH>%LE&sIehX?uUNXXY+Xu^}JC7rl^dyNPNy zZ5X2#{>rYH9m6U`&h_2eKXBsur%x8$UE?1YZdD5`FBzzks`E~b9lz{8_Vw*vSt%PI zuTENAbpOlw)d^j-o^>9n->z5Jo&URkZ=SbWH+=5@U+GmHsh@qUtZH~?w*dZbt|RMZ zyc5??#1FqL#Gz_=tm$7r>u^r_!uhXS%sZo`p9|=(1ngG=GW3Ai2pIK+14W}=nawhk zUrcC=4?H?tj;!<8um>n1@r!V1fRNWKJR24HuaBLjK6Y-b;r!QREwD~zk(6SxGipAUvhA;*$n;-??QWF%Go_|s}t zD}ID+Fsqc7Y7}y84<=Qtf(zejyMG}^W}-TkGMYBa& zSgBG{V)BO>>{}}wS#N+1|Duj2Ftkb)GPK`yZTX~v@5ma5g8o+c+jIQ&GaJ^;zzVEa zvl!fls&yEiq6}Y9HOXxFZAP=&-!!O)6O^QU9|ZnI;d|kAUZ`Q6Y}Pab3ywoq9Ezfb zDT-fniVf@ioYAnk@(l&lY_G#_IQ*QB*1wT?l&>itp{S1GRGT(x(u|S0;4>0Fg&fC%%Jk9XwAv{;_*cmB zYCIYoT@~8U5;b%~uI#$?>Y)sLi3qDw5(Gx80ta7in)$za8E7{_Ej6n&O8u!(X59?- z2Us0hCE$*KQNy@mF|;!3{Lnaq{-&ok#wx;fj9T(yZH!g_sN!d-RXxnV|wM#{V25gP4afJ{?C_UBHw)T&i82q-17S|WajSjtv4YuB9~937(S5pDQl%=GhbH~Fv4%rwPo)Eu#Y>+Mk5S5WmEnn82E8!W zeH}G~s6kw_{txe(vx1cIJ3}q#yHxO~q!mA^mYRm;OUakj5#z`zsW;&YZK!-!@zaWE zcBaIZq@^^JswG#eSXrqrduEk!)nUb#(u>at?V;ozi!oB=#D=srbyLWq_r6~GI<1T@Ej3Or^-h>_2zF5SX_DOFyNt@I zl{4x#|KSI`aLp>CKl5^VT_7#>qtvSU)DBgO*L@dhq?}`J2SzpL22o~1d;&xHRXlA@ zypLhDSRF=ZtFzhnZM}vWb?_QFYogYSQMb6+rHtv^*`<$cg2Z2)(Fw2#Dz#vD-};<}XOi???<4 zXoz3BwAgAlYCWm0qm@%=6;*zvS{>2*62qzqiJbt%zo>7xhUV&^tTda{f+w<;W-~(h zL+SWe$Z=8?&CQ=s_8DDxS;*p$_-O?^^)t!#=VTi<ZhhT&*|5% z874Cu1yyyQ%emW^2B|bJ^?NyfS*=FW)60T&b~@p zp4pUPh3!`7BPG|$AkYRKP02!zFH_ZB{j(WD+<3L`$2F?CHQaXf=n;A*t*|X z*T~V@I;mnc$`T<(9T@c&C#6+2qj59kw-~iV-3zg6s@TjFeLJV6U+uWiInY#BT+Z$0 z6~9bP2~WuW2-(lVn=EP_*Zz2+#c2Kj%?;2*{m+D(c?s~ksd)9|yqY)El6pOFP^QZ* zwQ37B-inE(jN`Cg9ICAk2fd9$<|WJDGRz%W?S9r*%|W$DE)y5sSX{Rn-=UeYaL z%TdTy5Hi?*)eD$yl6r=W!vAT0Q3Z^9bMvOPzqQ(-@2hP#&3rh76#u)9(U#9NLrDK1 zf=hglH~%3cvst|#nsP6D9;vdIa#w*L>NWeWQC(Va^o3=HNtHtcStm?3#}9G+OUGYP zBllG$+fDmb&}V~|u!p{2$%;@67s#Txn}vLN0SoUIm7n~G41`lm%a^Ho-sG64R6`&Z@7tf*I9jw-IK zM~*7*7O7bjFZcdaFjC5zsv!MqX;H^BRU#(DR&i$a#rdcB&$}SDygV zUJm7@vGQUPuNJ#7yH%^gxC^DIFO7v*bv$ww8#usprLZGWJqA}04y-+#wZK_TEVUGt zPA*5*3ku8X*zDE=&=Re?D=mRzB@hgBDFiqM*AW4%J%UZK<+XnJT9NBz<7om`bZRQr2}UBx|6+(n9mLKSyeDDJhZ zco>QYW99uM`agYyiAp^WvJtl5pwEr4Bh=)u_L}@Oa8Aa`#|h^z9ml8OoCL&`!VvDF zHhULW&hfml&JY%?J*+Fhx)dv4AgnI52)w0GT{2KzFi>gB!d1e7wTE*DIJaWu8-&v{ z6z7%!=Y|E&UBZF2hw}(H4~V6|-eYeoZS%k&%?+E!L;!1#AS$lB91*9j41G9)h`8{n z$`KTZ(^hI&djy3+@N}G9kRZOJ$s41z!qaitt!FBW<1BS?ob1XeXrR&-kRo<5UINAo zadOc(`B@@qPJ<&>A$cKA-!h7VfS*gx8kn?E`!Y2Vti2|3f$fbr`9E>;tHkz|-c_X) zxHk+)|6#bV8sNBYbQ2@2J;t}d=!=sj0&E>RvwQ|V$v~wwS#iRFwTBY}oai`NCY<)6 zIMD_i*#aj(II#9`-Um)8Vi^;1O|y~4(pu6=Ld z0MiOJZ^kj$m~de2;WP(MQ)1yW_onEaP0E--cd^WUvr2$t@FyaGwMX#3IIGM(SL`K`=W`o=Ff~<~|#X;}&IcWSRR+1C^HPT-mGWYEUzO4o-t;u!~4y-+#gTUDzC+{U3E_2^+z}ahobBJ(Y z?cp2;&QW6FGWVkfWov(Jb{kOLc{{SJ#VBK2OSg=6>EFjj@=U zeq15~SbGGwL2xrpz8)uEB@RAwzsWBv$lR~v%2s8eVVV2YyjkxME37?MXRy5dI8J^@ zpnT^3I6OJbd1x3ffZn8L?l=Y`g4+EQ*nDCAt!M5p0_*vp$vyYygW0WiD5*qP=Kc~X z!`f5+50qaG%CC?(pSiyp)Ni1?V&qWo%?Dp65LkO49)P%rg3sAq!R*$1mC+KKv+q-L zb{vBO5y09b@CB`M_FS=IBnE3w>>X6MI8~R+*^8s4_bELdmb1%t6=R?nO^RI39&Mo* zu&Wpg#rJ}8NfPCA_V?J>DrwNi`zUzdCm2VK4QsEl695t)l*V^@h%2sZ6tTMtJoWgJxP(v$9qE2ETQT{ zb%nK8*8x!ON6LIY-p?S7T|PIp7)S)L_6SCTV0cg-8kC0+2cM4**OwAx;zRNC0cBai z-SZ)N^Nk`tSbKbv!8b7|k0&@j2cH<8?B$F%j1i=Qd(|8q$KVvgg8iphDfrw=E%h@m zZA+JzTbDM;zgw5iZgtos|87@W%lu*Uui6=^9ZSpYNtn;QJC@dS@AgIpZT0Fx5U}}& z=n07KM8N0W-AiY;J`$dHA64^i9D}_`9X9{!{YqQq+_^&iNeDLoLW5DwfmBT{-yVq8 zJ!+C~53!>*9BM;Jjmx!%TBwb%qc#p|V@k`TNRZF7$FOlU%Aieo_IPSw*!(x}G(b!# zEl(l{KF6K{X+B?=WCb&wU|{nPGY>FxOUttfhRd(#8dzo2ZH9vD6siQxet`PrRCd%!sX9*4JfxQP#zEpZ2nQ4WpKxmIJn&Tu|ZWEwGm}( zs67F-s4`k2#O2LVWy}+yC(CGw5N!VISO}_5kt&}vKV^_b&YYVX6ee}p{HwnR_2>%`%jTJmBnYoA2{eU;;+Y-mtTuF$(LV?&u(?fBwv0bUK=K`_LM~^ zd*WpmiSs$LCtlB)T?P(}n=@+eiepeB99Vle#eq|dSorL@SbTQtOX1n`Wt9NO;M+t1 zYmXp0-YSF674wrAtUa-ksBVC&%Vp64wD)C`EV`6k#W*OwPl{Y7{l0}_(5_+v6yxLN zG9=1p)A4MCl`-gZBP@}c9M)cwR{&1=csYe|_`JG2AkHYw&OT|9k~daG!h*Gj^$D=5 z#LJZli_5U97^o^6sI-ixD&fG|!}$U@HR9#!gu`XoH4He_EpWah99Vle8NjJYEPSS2 z(;&?ao3Dug)*eAU5Y!<8KIg8JH$is4moo{1%f7$I;&@G29N8yLG7VH( zHq+29#?QcL9xpeImwzM@E)Q?cCUjE}@N?-$1Custf1xIVwbw)~!1hn;-B|t7K&o=P2HBf0y){$^v?cwwQPPcfu3*m5? zc{c-27Ym%8gad02ryp?o5DS-`_c17IdLKZgh-PJi_M6H5mDVX`0MK@w zSWjnuD(c78P|W-D#3txc@+Yf$II+Uxw9Q2r`W{({7B zQPoE)o&S|G(5mB+^97H=mdILmjbV&3-f+zM+5)3~ zJ~1}yTh>p&XqG59CJcVdY6gz!3J2S=8so|=X9gSBOrdu>Jb9eEpMRS1O#gjXaIov5e>Ix z^)moyTh>5QhP9{sH$@ur2EtuB=zCgl<_I)%6<3 z;92S%*niqNJl17kT_h%M%esh$*r-g!uvb}E>?+=Z;*CW48j12-)(xm`r!DK6fdDky z)h56(c$=C4)?O1l0?>m*`5poBTh;?WtfVdLUfw{D2?*96&=W~`$2Ccgz!yj>-?+qY zSy4&3KoR(v?<1~-o=l=QVv}qF6$a4LM8j=aPa6QVEvpDA!`f?#=b-!yDRW!aGrTfe zwThB5tUcvdp!`yj`~rz{Th>bu*SD+}@beyJo`h{#|F#S8CIDVfl3ybLZp(T-1mHCb z0GC|=F95_O*+T%_mL-M&cq{;Xb^+c7z+0rwZCP(YF=X7c&VPqGAJ$&y2cYavl1q>{ zw`KX0^jBFWcnr2>y=zxK2>I9~xfIEBTUKlmKJ~9`3~b9PWr0!ppJTj>kG~4)$6q%C zVI%2tUmUR!YKN5Z9`@^JTd3_}|7qLjs_ug7jwE>-3G;8|??}?$%HL*S0M8M1XTUMI zn^0i$k8%Jg`-p>o8-E{q;FQt>-9x@G;~$kxVP@lTBu#Hqjn8ySCZsQB*?#Qe}#>vO9pLj zG+n1=hRuI7-vi2>B>5Jh@Ne1Q0l*QZsk^8*v~fT8R^CYW2?;j;NRi3qWoNSdn2@-) z>z&ErM2`(b+D;#ptmPQ6`9~=Pl&6yACzG{=hkL93DFe!rxWbQ24W%%lz~&$2IiNg4 z9Q@n#&lqI6VN#UTVe_y4GSpurb^a~-7xPwsh16m5ul^>~Ur&}_BLMF0`PY-PTc1-F zJ@)qeYX&0i_OiED#0v*1RuS-vT74^K(Wp@My!LI5iDy{+s4qaK$9c z(aEw*T>RVeF$SDyhAJDtxPeoW_+azTR|b5+WI2}LxVPkk2DVrOk=9gY2?aL)C@DZm zN|qA{g?l?b$$*kzfs#rnu=z*%04NoRgL^B!fgmbym&x+y#K6D(p3W~Dc>DcJT)Cty zB<$_?&-3QYAWqo)bAAWT`pI%#g5=+NuMZ?Hq06aj7#{#WrKEVuF_=k6u=znMre@fG z0_pc;`4>XsZwUPkq#H^ru^U3a;L2^~O6U!tyK2^nWAHCRg3Uit8z8kJ9`0sPE40U5 zh=<<{YHLTW6Vy5+%h@Ez-w5ge#m96bDBGY8lE-S*aSV2*s>9~L>b(HdBU$c7F#JuR z9ssyXH-Wn44bz)oVDk?%2rvVZ<$eUi-vAmA0@E*Vn85@Cn}3+$fEh|8+|8e%261f{ z89}PB`BxnS)lsC%-S`>BtFqVrV@VY@|EiOrIx$%uPr}?ypNSCGZ~BbK&n-L{g<&^+ zrq~gm1@Rfl@-!0XZuray5uauuKHHA?0*KE`mgkZ=*j5-@O|DC-Cs;iRa6(r2vK_`m3xC{y#>P7e~xe=xr*}_b^EywguA5A-Qc+kwRXzb4!gngfZ81PpSF3fYD7wT z*^weYB4Pdpk0V9T?jIQ#z|-ENe8vpNU}TE+q7yd%CIP4)(7#9sHvd9JQO#$mn%oVZXH&9UbyNB|>;}*CcGO;m z+KZ&d-QaoALhThhYHvX8KPmF7B*@?3`41aSuNt(u(ex%YGi?5w*$WggMfMO1e}hK^ zKzpUB*$o~~-bg+|g3UitG?3&J`E5etZt%zkqPGo1+HUSA6xjTuybqL8De}97!rkC0 zWk7k?0wtDEVDpbs7AU2OgTKL3+91mflXy~x&A)mw)DuaazrmB3w|WYx!{%T8L#S6w zk<$o(yTMZti(XG<(PKAw(hNk}i{wgn5UK;=(-irW6uAmfa5s29Ws~+3sPl8Cih)NP zp`TIHz~;YcGQd?cMgA&9{(`vp8$2})IA1Z;FAQMZ!1XlVV%+7X4=qR?Hvj4!pq`x~w@r~- z69a#PC!1e3aD%5UuJlzF5_W^9b>5sEi4!*eoV~!=BSr2;ko*mv9^naHPB+8&0B~0& z#Z!*K-h>33AEd0M`lo*80BaU8aar~(01Qx4g0L)mE-Ay>Q(gq+1u61866Z7R1#In_ zXW#(SAT`&;F}Rp;VC~_o0M0UE;j`^!=$z5YcnQt6$EXB223HaRtUZFYmKk@h*g6t} zwI{X-)!jhV<+AP#XzwvfzlUYro9!xYhvHUJu z8T7dkwx60D)?Skz1J02Y`4Hjo8Tb)E3{sk%W#EVM#yU<|u=cRd1M6&xe44PhEc~p2 z>a>AM+qf?f4y-+#>%h61B3~vPE)&0Mz`1OJbAxbT?cv-7&TV4hv+>&oX>QouBLY}^ z1dl=RkO=sU{9)b%j#TX?1gt%RCsWJI1ybe6RP9~_mz5Vt&2BwjSsYnb9+_&sfE2Wg z@fb95)I_lMn&>sK{X12DIaPj<*!b-H z-v*?Y8SaY)IBp>QhZte)F^XXHq{=P=P|srwDeTBiQ4UB&mISc(+6Y`qi|%~G#esw=F$x|V@*kd*n1 zJ!p`|Sj4RsxfzM`nfp&{U2A6G0MiULZ^kkBE8)P}!}$|9zY`0ex&MyNS)h!W z(9C_IN`PbVFCu`oN6;$O>Rx%SSZfl4wI`O1>b9loa+!NuwD&@#-@`KZ_I4FJL$M<% za+!Na3&k#W6?;LkN2=V7MET6U2ODAC4Eo#%>rG7#Yp=-%0cSv}+>dbh%zXeLW+=_h zGWULYV+|%OSbJEbfHfjj9!6MP=03teHOxSzZRn#32i6|WB;ZU)mB$edm$^?c;Ec1t znM^pa_HbqZXBx5anfo+@G&gK!5&^6|f*cUcAp$;gpOZJiJR*R#N3awGi&N!=1i@wQ zi?KK^Q5Hv*xi2(OX_?M4yBO<%u{Kp+ohq*+5-xLJ%O><{5b$$prGZHswHv63VC^;0 zPOxoHmA9tKn~9Cj+_xK$wldt!1~_gY?IK24dyI#`cpz2YM}S=Be!#%D&p@R$*` z$_iznVVV2Ayjh*)wHp_(_E?_=Ye9U7g0eF{b1zsvEIG`1qI`G)1?UB8=8j{q5MjaQ z3u}&^xxWsq*NBPB++PF0Y9*Bj%iP}}WmtR4B9uM&n^h#vXYQWz`VAD9fdfoy)VvwT zphP&Z_Hc>=rx>yDnR_vG&L(Bdgl6uWRRSD?ZxaEmJ%Z@+B>%PkhnwGc*5Rmx>gJ01 zNetGWSV>ejKzdx}9zc6+h`anR|IatWlbsW$r0?V^t(9SbJEXfT;>Tj8Cn^W$slB zRFw@>+J;`0aA57>d;y#q`1@6a!)5L@3^>&-aK0oQSbI1bz^O?reCA%$Ak7V%uZaNG z9zi`2)FA>sbFY&(L46{CwMXy+2)-{bXA%ULxqpwvahtL@vdlfxK&53m4eet5428<#q>b8NsEJ_hHBk$&{e{0Gj;}N#Ha>Iz%YgI;!~M+w z#|@;G#0YDTu>%;haleKDxy(J=z}MD5r8QYc!hyAi(*ro&@OP~Uhs)f%8F0E-;PfOM zSbI4AfYXOqxXiteL0KEm{p~6ahT=d{s>%p<$W(=)74c5i6`c*4bd4i7zA~ zP(E{?8J-;GOgD@dKyOkrcN~Lr2n#k}SUGy;z7|-kiHXbHR|8@0J?k~h{(!h*Gj z^$=M1@rx;h#bxgI4ODjxRN99Ah;U%-;S@+KFGr@y&NP!RCWuT6ZzLzK@S|13c_K}_ z;R0(9rx0+SA{IV#f65@u4V%J50BeunIS@QU1bpWHOx^@Vi2&9f!M{Q9a+>@iL2#M- z%W2uIPbiBc%iLcyP-&UYt9CI2V7SxdH`C;}P3BH%Okop}@N zAp%%?1cyOzFiqZ15M1Vd5Q}4HWpQMg`+ftJmgyX^i*Xhhr_ z`OMu5EG{|B5e?%7(Cw9UQ8@lx`KWKWu$=vOjp#*9mn7}!hyAiGZ{D&iG|PHC!%u(C}Sq{p8G&G zbH_0_g$Q8n5zMGymAU7N%_K2cdt!4@-Pu%KE_0ua_8zG8d)Phq9J`7Op*Wuuxy*gO zh2kQ+iYuVFtb)9RMET5p85?0s4Eo#%TS-k0Yp=;S0B2nVc@5$4nfp3GT;VeJHF;xg zBrI5aSUZ8Wy@I@zu(-^9yMbz}flAv!cM%S(J)DEU*? z8ViUbyE_8`bR>XavJ^>A6bRBxBp4Bb=1UcVy{v#3K#`^*2vP(A5s)5w??s9rReJ9t zU3fls=FH9BotgM`=l6g8p4an_?%ZT^&iTCWx$W$1NI-BtMLkOpLgjuQo8w5fIr7T= ztcgmmbS^o?xCxBwDeBb}^)Dh3D);MrL0<)dxR(AhG3m4R7NrQSvlJCg#XCi*sw-8! zLu_K@UL-Xb$(3rHaCb~_!bG|&mEJx|b;x)h7)z$A_oV8jvQW8~H1XYoXT)kQ{{;FKj6p>i*4Qr72lIj4#qD3&Khp>i(| zMXS=wOMOM_tgjWJtdO!;xhp1V%*BH8Ba#TvIwObz!PBYgQ>khd;t(tMr&EP(1(o|# zcxDXSXn5sbrEu12#ERA#s}HQvscJ0(6)X2>UvzIo3POSTdbWg zrMXhI-`?0KJxTp6U0=sS)&5y}Ue9r?dJC%B`=;xg2-?t92SBxdy81Z@ixqqSbYnmJ z+{6H$30l33t8XBopbZ`6YoH7v4zXGvlAhOVFPkTU)%re79arBsq>eUp_2KDum3o2D zcO-;1bfHn`=1A(MP^FJVj`y)~4yw{eJ5d`4wXvioROn-E)W$nen+&x{>FNX$6sz+| zd^SxmX$!OIXG$~L(9=8vQf;M!Nl|WgZt}Z1Mp(0;yLRo5qvWig9hK{lxC~JvBtj5=xWQA$6 zfz;84uD%88n@L@)#5WhNzLnI`hOWK~>O0fb-v~gc!gpfRJIFRYUWNZ=BGRjt-A)h= z1L0u0`bWCDk0^u+{2*Vne?VPaGy6&nT|G`*V)cF6gmaRk z9yfsr6XzW9p$(ny3ivLktCt8)sJt(m*e;of^i*9X6ttnE+y=_6boB5ohGSmoS5UcD*GK6gdRrW)8<_OzJc$FPdIOn6p zi8gdjFF4&9>JtPhR@iPJ2?bsL6Q=nA;JsRfjjK;4B((n)X;0}iSDiFh?WPi1{O!%m zCVHWl=Bit9D*LPI#}R)K;=1ZJ3v1@8%s!1sZYDMJ-@!*(d4G5rx0L4g-#9!i7ec)DWE#tZX$_ADv+iv@ohGq{f;)yVtgK`F9#&;AOW{+1iOfLARw z;ONq~v9+vk&ue{SpN7!4Mrp1FtZ$9bw<+k`mJD@shPp9BU2pU)t>O;q+aru|Bf2oE zBxpvJ%->wl&-^VJc|Fjx9&%8h)(3Riwoi=%`m~Mp=|!zi?9+li6>%+$E-$%U_qtrJ zdC^k0_EKIEsYrNn$tC%V-!Dn`hTT=fwSt>0jh1rSz9aQ^!6qCwxh~gYJFj)zYjw2L zrgO(Gt-EGRdErL%vPSgHWT#1O#}|@Dvn43*V}|`MZnDG9XO?vAQ4^e0+Z{oo##dFdCuDNjGgCo?s>)9^Rk`i9qxI{&ZKCJF|c7V;=uA$-U|~w z+xNss?Yd@Xx9i@iO~4pEgPglu#qHcnbA^XuO!Fcl#xjfd+XeIRU{6?kK5o`1YZt5v z4;E=1tb(0qb?#Z!+EcajjE1M4%$jy4b$M`KkO^OFaoprNJCg?7B(;!HOOC;!>+){U zh$d?znrIig1rObnxm&GSm+QqKZ$6!JxOclClZM9P?ZQnunuoK!o!493tD6;8BP06z zWT$N|2(+vAhxk(Q@lh3(y9{>wm$!B&xL%7et;5n3_<^M}N&k@{nn6>9n zJI`_4bBwj;C_B%exaR~rlV7;W6g!iAnCRJ_Z8<3$YaO3y=f0dPEHTfEMb9s7 z54O(QbB$SJm0hqMJlHntU|Z}w_jAuZ)}FiUJdeOrPv${8laoC7u^vqm?&U_E&-zjd&W>^%E%&pd0--gce?;i)IHzn#g~ zJow-s6Ta4lbCaQVCgZrtm_kNv6kBwrsw7hz(UEqcr}EH~?bfWzH7UrOuguSC8yiut z+TvD{Wh~zQ+@xP^(^k^Q&T9zw8d%$6D|yw3{w>*QTgga#p^wM#pt!9K`?1_)l%2^W zF8w2bg{@?qozHacGqtwmR`Ro*=X~xt*V=Qoo#%4yxy0IYk)7vS?zzg&WHUF}U}v%u zCVIBF*S6Y9UehMtRy+5DTw%X?UhK8*(Qdn7r+Kgw)}F`A8b|DcUFN|qS_eCC=Xr~J zUbptVYUdeN$4KTKJCkBC(QhV%*Rfe^CArDnb|#N-lLzbAkJkJS^q*UnhH6}XAFo@py_+j%|7y(-nS!0Kc~k0Lv5 zE2)Vu^vPX4C~jxN-p5UzwKIw3()9o=Y$bKv)cx`#W5ryLn!8v+mKGcENh^ zU>{q1erVQs-!51`9xTr~SZ_Pe!Q69zwP$}j&u`(WC-ZANlaW05@E{Yu*2Z#^QFbOj zbCXGhjM@aY=uB0~TiS?@w+lUohn{J-W?io7LEe02J``(gB@e_(ZQ6ATxa-za)4exV zdP8`+H=fqk{bO*|lUF8I>hMOujmkX3#LJ_XkCoa6SPao(m$UP$!u=veKfmTz!OpKb z_p55Y`M zZ*!*H;Mq7`^Xw8l8)q3Q{D{lG9~6C#Ve%=D-b0)n3$@sOJHIcuUtiI0s^*tx=l2!& z8)W4-z|L%>K_-0omh#|>kWO(nF0gZ2%bixiDQGq>)5dSPo$pD`bS!u_uF*UX1<%IyMhY)* z*|R~>HyS2adGyQT?AWHozGUZjhx^?U{Z?vzH|+e1#Th$&c$}~o>waNz;vUX9@8y2? z*qKCdlTvmjkHSQsjgQ1x?u`!xdH!zX$;~~>S$jTa=NZX86>Cqgo##`$LzRO}cv@=k z;894YI2)g~bE?gqqTv)Y8~14ASJTe-SI)FCPAvNO8>!mKO}59GivF#3Ui-M$?l_C0 z|CkZ|5ZP&m|8abwkLQt~xW^6qGu-5)oynhE`T~H3qW_$o&rR-gEiS0&KcHpsik)Y8 zys-jY@s^%<>^w_y&%3QXi^YpW!jlleJxke{l;I{1+nKmwqG!8Yyj9VEO6&MzcJ5WU zLS(#YUR1E|k!%<286K>fwP#hchH4kAE)V9j4i;_anaDlktUc@7dA-Xy~UZX2Tj;wMyiS= z7(2I=VA{ZL+j-s1z3xh|SR|#4==YJGHo+gn7y5YKpCIn(_Z#+QxXHtICgr*G;{X;8 zwz76Uk=#c~2s)nb)-vd|^Nix2sj+ItgtE?(btikwv}wg7y5W?2#OnN*l*`1 zTkK5saOvNJw~`%pK8Lx_f#5mxxR(F@cAjUr=SgeN<942xx#vY|&+~SkH@N3jI}<6< zH~{{(Gbs)eJ=;YSt+tXXTE~kdikmtgi3qMxD$#Vr+?yD*A?sNzVHfOi9_&$T&(da% zhwXw@;K97s!Q6J9D)+2n?ODmrvj#l%WJcMUMDyS^gG~5ZtIJJ%b|%T(B%zQ|i%YcH zN}kq6w7y;F7kTJL%sse9W^2~vY7pej=R;TS-8sml8XUFt{Vq3o%RHR9c3vNIuMe!S z>KM^`k)0;h2Vdyp(K{$^UBkXVH|b|*@)egJ1Yn^m8DQr#g8K{$oPR^PIvxf3o(RXy-YTd;Vf)GLM_gu`^i)6Fu9DEhlAtt>X*r+&6HAwdQ%T+PX(8 z?Sk##!M0g@ZZT_YwhQ(L54P7j*ls(|1WYi|GMQ3_}(?T23@phr-@X#~u)-2wx5Ax;ZS^zqmq6t}fue~gy;pHJ}C!q?=ON(+QU&>-`{YPA?D#6Wal-4dkwR~>SIJ7 zLw1_fkN83#j~{~K_BHG$bCZd7CNsG7Gyn@#$rL-E`P^r2@Eq!>WpK8g=L+t*)Y@~g zo#zJbxz^fqwVmfy?z!2{_S)Op(`@?;H`wMS(i%*^5z*B!@a)` zG8qC#ZGBJVCgW2~r_T>|UQ@Z(WGk#;M)a9vr%C1G3w=Ch2gMz3*e~KH^X*Jla_MCN z7PgWlc0L=q&${3_)J4nS8avM&+;f|?=N3E9{oHepwdXE7&m-LPpqK5jUoIjT}UPIC? zu=X0!zau+MYBavk$75tr+doH!}+`v88+L>(SCY$X{cEd!^_Re&xNqJD~_-}UZN4Ua4^St=O zx<~u$f}P{RPFs7PG;18U3wD(UyKEiolAY%r?s?1F^M;*g(F`M*VHx5=;#2n?nCSmX zs#uT-Uu&hfNl81CN4d!(8TO<0P=?i3azq=^2)ocS5A9~|!CMJivo6;YLEgN3i^yAB z$x8yiSj*$C&XBV4t48P-$w=%M$*jzfa^5n2bYGJE`I^e|45@wgyT;S_tu*@6OTm@< zPQcSAVXX;n;~HBKuoHd=p8fDV`-L{L%e9$372u@@+n5pb14M4^pH{E8(I_e1qy0F( zB$ep;@WZFhHvHu5ic9tL2h^-qOvvumKDTq1 z%oaJ_y0`AoJiA?v+Oc)F-0ZHIi3u;Lsi~Ro)OsefNp^?q*4?r*JHPgy%(O1qow{}F z&>-ivfKQ+9()Km!(#0}Tv4N2cz*S4@~l#>d2V@b zcorzby(7KTy|cV$yglUc@^A7)d8#r)KByd(Z^*agfl8jzPx1EwZIK7%+@2*zmAp{W z@9yR9>mKYL;U484>mKi(;GX23;-2Q7x_=9VYVTYz)kdrL!_C{LDW$ocXTz#Wy3 z%O~WM@@e^;hWEF8NA@c{lwQiGN^j*e!1e)de`TQZmGZUnjWSXhr%Y0&Dl?T?%4}th zGFQo0<|zx5MaoiTnX*DzrL0lbE59mRlk<)Cs*Ij)>kPAO-Uv&seKPvxp|O}Vbz zP;M!ID|Zxsg-D~gn zt$1b|p4pCPe#0|6@XSs;^E;l|g=co-nLXgz3%z~#&VGF74}9kUzIPDcJ%sNa#`liE z>L{#^!Rk1yPQdCUtWLq|G_20R>MX3z!RkD$F2L#{tS-UoPgq@s)nBl>0;{XAx(2K3 zu(|=Oo9=<`Td@2ambYPf2bO-%7568etL`42Ywn(&>+W8j8}3g%H{HEGw=hrscISC+ zyZd zd;^c6@c7pAg=d(jzh^i+zJtdIc#MR{_wX16kJ0cL1CO!r_yHc{;4vN^KYFIPC%|hW zye7fxCwNVU*U#{p;`!P=)$@&enrEo{7tgou>7HTk8Hh9!k!B&%Y($!aNOKV>ACcyH zCV1xKvB0z3y$}%>A>v|0T!M&85pfwJF856Jtnf_ptn~ciS>>7TS?!tOS%Zjc5pf+N zu1CZTh`13EHzDF?MEn&Iw|IKGx8kwQv(U30k$*$v9eC_S^xqME7ozV*^gW2a7t!}2 z`hGcZ9_hU$fA3x58HLAa@89wm?`?Uk_m2F7*RPE8exi)`_E3KG_EaW#dnpsWpDL5Q zy_KK5pDB~QdCJe;KFSntUuCMdpEAw+x$=wm3uU^uzcR!7r83hyK$+zosLaM=j(3nU z*E?9r_YP6!dB0NTd%so|c)w8=dWR~Dyx%H|y~C6x-r>qp?{~^F?+9hNcciky`@OQ# zJ4#vQ9j&bPj#1Vi=32yAhdApIX9MDFM4U~Cv)MaV`4w@tAkJ3A*@igV5$89=*?~Aa zy+0_wd&eoeyyKPKh_eTA_9D(c#MzHHe<02Q#5w5wQ8|P-hY{xp;v7YsV~BGcaZVu4 zN$&*Zly{z%BeL%j3epOp*VDau8BehH61@wkk~UwB-><0>B4@VJi0 z4Lok*amzbZ`P(~9x$XT$x#OL#_~q%!C-MxXhdfj1iAOJamh!1QTj?#&Q9hIBDtU6g z(np@B^p)o;{p1D8=kh}33we>!UtX+yDKAk5$V-)h@-k(Ryj&S9uTX}_E0wS0Rm#`$ zYULYwjWSeTt9&c3Q-;awmErORGHbB8S-vrro2a)C9jX1EpLdNBX5kHE3d>UwMw2RZ;G5RZ;o6b{~Eba-V(V; z-Ws`B-WIt;{<6YSc|e6_^7hE(@^6tVBznEnaF+e*~tC!xyV1{^N|PS3y}xqi;;)qOOc1=KO>LGmm`nL z)1!{bGop^mGowz(bD~blbE8hl`BA6kc~NKN`B7)(1ySeZg;D3_MNt>z#ZedKB~h2; zrBQ#%%c3sJ%cK61S43TrS4LfxS4CZuS4Ul!*F@cr*GApMA4=tb_JY{wLKFXT zt;$)<;4xLVD?63nl;4#d$}W6%w9@a&u}Zs?94pH`Ue?p6+WJBlhZ+I_qz5RYBtz>z)Xb?&F1wE+H*y4E#j(KMliq^nhjnTun$(g z7jb>2eI9txY_i|co+_%@oLe0DefGI#)9qdDX}p3!9K5d<^r6|HkY^vo@F?PnEuno8 zaA6GhRIOe;DyD{;e^jd(6Z7n|&(w^L=1*y#REvtLRjZcUU9DzyvVQd*NxE~#CAIDS z!S^p`Mc3bLy&-CtkpC?%fRwZS8bjX=N$x1;2tIvy9c8$Ase!Xk!j_xEp)6HG!o#Dswl=XSYn{WYGuX>RwnIh`}BM^%f-jPKmBWA{!ux$kDSh|g@+xpRkZnGKub(`wH= zUH#dotH)HU7M1y0PN&S2&fRj;qiboe2HRABx^0IJUiTxQQgh$!lHE3^gQT|m?_XJV z)?Y$qw(0tAm)y>o*>82p%+6}lx?^^S4mqu#ZX>B}J9m@RmvbcbCFvPl(j^tIFS~ZZ zchX+R1K&)0t-7Qprr@)N36h%puB0aA(?80&&3pr3jC-RA1^(SRPN@(&$tFfVKk~^ z&OP{;f6kjy7QQOe;$Cc6WvZ}ktBk)W?oXh7QoBB-KUZ9P&Ls_uQrdR!*ipNc5f)zD z?~(l4Z*UtJ<-&T!{EL#p@F-raR7<~~J@LQx@xOn6Lvr;j`KZLsiwXbVo)>KM5PSkn@)2!f} zn2(wK-<}f@KSlr7r=4-c=X7e*p?h20Ii@4OTkCe&-Ev#EY5(*a(*3SEU%ol`sn6%O zJ6QVf$$wSyJQI=NTtP1?wD3^}$A#Cen!B!g)4x(rf3q$uVpCnm9e6FLvljd8u10%G zKjUsN=CS4POA{A<6fv{Dv{~B*&lx=-VuthR*Ze^(TwG^?Hd9PG)b5sPXTUPL-Q6x;dTjhC!#+9rTK>L(XfO(C8Mc!td>U zbBcH74sWHA&)17M6Yn@ht-E!qrUfsvquTb-4T{W-ys~Hb&sjl(K54y)Ptt`}bpyDzICOqJ zbtq)0K5&{fkrG=pW@D)h7qWym1&bEPw(b86H%E(8(s(D-O9poO&%puH0J%Nk6u_VPZ!TTB)$$PoTMXZflLNA5> zeZ~C#a|)Lo@Y7~An=R3TM-9Q{Yvyv0xg0iJ*brQ6W$bb_vbuMAyKCz%Iw0)W7WWPF zNZUDsN#*AYX@r22|0{JzH8juM~RI3=-3R(!K`HdnGbWOsT!_YEW{oV`Z# zM3B}@P9 zBRz_-o=X0S2s9FK;e7=Db~&BeX5m$tk&#L;`(EqAm;_dLfU0Xwr`NM`Tff#J8($#O z6M9d=ZwhKCaC5t5p;D9##Zd?~iYdM-D0a$zJF8Q7_RA0{ZRKD$n%S)s0-|*5%uZ{4 zq=v$13^V#s2-dB0*IX{>hRs-w{g989Gx~wAL$g7|M+vEHJ>(H15SYIojBnm9-8{8X zGwd8PY{NSVQf;%d5fcB*iG#;MZ=9yLuXMMZ_p-B)9p+d<^4EsQTb*;-X7NAbBl(|( zIX+y{!GgJ_?atP7tq$heXn_E8Evrq(E?M*^Wb{dwim2lO;gTL`WlUlHNSE@013#=y z;?bF|64GLQhBj}M+9I(@)7S=l!qGeppCm}8? zQ3Xa5vEL6i@KK(i{B(F`G18OJ}@1Uwaz!o zXv{j@!`KN*`7lcip11~SSkzY2s&UjcNG8`k@?W}(|N+b6GrSk{74kf z6k9^SXgzx)5pWtdRzzYl_E2`yU7LE6f4Z??R_N2HMQYPjj3`&4N#v654q(?x3TyO8 z%=IwSNK?UX>=O|XouRQUrODeYzFBHRmQudCt}^eE9D1e!ogX*};?o*7rYSJXFnFOQ z`mRmLxJ1my27$ve+c0`PS=%4kdja|u!^d@jj@PVKwcv!H=nbCE_^CVgjsW&pVOG!4 zI+`CHFhgi^1?>BC4VHDfVp`nuiSf;lkIu#v`zsy+(rZS=WW_c}PHPg_k$l5>weB33 zmewFK7JDCdG0fSOMvjxBgL_dzIuf|Q;^+SK1Uza)?2~NF9X90yMdukN*Mh(TdNtp$ z=^EeRjjV==4YTz7^pby}{+;j__0^6Sb~UoFgW{DCWs%S06j&}s3d3_-NljB?Sxu^M zm!0vAC0cGvCmE2*iH#DQ7+YW> zc(OU)wzu!o0!-$k#g{hwlZyBV zlg_tNSc#p5AN}pYHf!yTvHj3?VN*D&Q5PJ>5ax@1S-`Fu+cX8=dRu2IAr;AFhjU^= zVipc~e51DB+Y(am4EBxo-SAu@Wng%Qc9P?;s9{>w6=3rROZK-yFS~T^!q+#eI1a$X zC8@8la;OHqU)sS9ZvW)?5;4oW_=}JqRrJKTY)U+91jsjXT(zi-KE&1NU ztFu3~mshw)M=z6hY8x57!ekRzpJud|m5^Re)C$lRu??ChLf`|Vs_CU|8^PHsAqg-_g$2a9bOTl2%iT&%ir|Vrk>z3hf z2s0G>sJ3tMBPR+}gYZ^v_?Uv1S8OxD&zroF-KITW4H~7%tKb?8%M#Lm0?$~wkHL@f zhe=lzwqqXo>@2Q@CW8NIv$Kg}qYbdj$Qy0aRz&lk~O^0NCj9}9ie^Pi>v zU17a6tcczY)g)&o7^NW<3EFH5+(RBUQoUTL3{ziDObC8S@?k*b6FiRL>x4;xTO)jf z{17z5SnmI7DdE*OUeV^};7>@ro7EWwNQc&4x&*#r_yE}&4r7<(3V6X~d2>Ne2)nuP zo<%~qybSs8nEYVDs(UB>1-@}xhV5e`m{|qW*~DsCR!$mIq#+nb!nB06P|sOvY)$h5 z&5l9pjS|h6J^_0xf60?&ZOAiR-WZ`y){B^z%WlK)a6oZ`IYxJk!pjEERlIu>{8FPS z`ZZeX*AjmA1QY@R+lALqnr-p2E?^zYx}8h99yq)8Hvp{X_ebmiXcYXaH6U$@9x}YB zxk~Nct@Z16wdy#nU%yx{hXCS=M$dYSulxc!A4vq~#2MecV^&UXc1N5_0ryrWXtL)D zw&sr6xo>oCOQ!=>LtoXB;&C^wVRlD8Y1?2ZCThMjEHWGb!zafS>#hZuRxt)+7at7v zh8cUKDR?aO!&n=Op((}=qQ52&ym|5@Wn#W*$>4O(&1%=7_3H(PbOyRKS?khBb4Wgi zRU`kO2j`!gJZ+fFq1C6~)hXCaOGv|m6#_=Ms^Okuo@IQ^MHxo(16~VcrQp>7-C?O_ z7{s*35Hfz2{?O zak`epV@9c?6-dT8Sk^QYId5fk>a0~}e0DvLATzWe{q&bDtSrVs*tUCzY;?hR0rP{f zVYcmF@YdY1-zuyMx`SX;^Ml|wOY?ipYSRly1nnFpq=)!c z6kG=L!K!79#XNmNq{TN&G#|0yuL#`hh4U0;@`D~KZ!?iJnq-puyB7EOp1qx;myF} zVR&!7IKIv7{CO_+y!I8I3B#Lq#a%^;OU0yJTAVttaRtUH5)cP(uK#nKgIb(=!EwR^ z;^0RH{yEM`Esh&;jDATj^ozY;XY>m{yztL)E^2X}qBv!=wje)vzw^J$&vh+MUFsK) zL;2C-{8#yLwPNG&TyPx9j~3^@%Fo?e9FNu?S2*Jd%#Rl5zsk=8S{(nNFqB66*jx4u zKMe8DxqeiSHTWN5;pZX#Io5f^3UfV=$38s9;PDh5@8WR+4-Xzii{SPAl&ZFXNWd+<5;vt;W5rBJi%>tT`U}i%lG0x=>Pz)vmr3goD-@&RXECCYDzi%ja&~qG2qnqw{(VLne9+WSPLV z0SJb>83C@obwq&H8NsILBz+uSHRPXwyePJr#Lzku+lKCLq3*sGy|72IB9h<3dbPhYQC#L0D*=VO;>$xoGta zVfCj?pfaO6XQDb|qSCj8i-d#L8O}A}T!~gM6VBj3oGT`r%QiUI2?wn+oZG;;MJ(SM zBlaZA%`KC(Fm3J-0a|AS;W0^SSd6|id@T@!#RM-^fuLxNzEh)hMo5dm6f1nXJQ|tyB|__h06Uyn!Difio~h{gQCR z%6%XpR;N zgvx!431^fI&N#wB>kMZSa3&CoSh-IyNek2FCn7-Wj9?lFrVxQxxlbva;1?o5>x^J7 z2xiBqGYLYd+-GBR{FQBvymFsuqS7m!e5V-8fUzV-T@<4(AQGW+U&0skA`pmcX@QAJ zpS8;=MQEL+Xam^R#i(my)K$bLR_^OeNNYImDifSAkv0+|T4#*EfpJ@mx`hCR%6*%O zZ;OdaPuUK_LF)`>A8_`>sJjS9sNDCMaCX_?>?a(w&TtL`=OD2NmHR=HvOb@WI8{6W z#bcx>RPM*1XjOWhq`snc*4ML8K26GE<$l^Ejk#D*ew-r$w9W{wg5a+h_0JgfB5{b7 z`(NU=g3A3*JhO#uG`w=ZSUBr7VnyqW)#Xc4@5HEo6R23Z-w7@b^Zz!@7eH^)DtBCc zVLttS3fhpczBelOhk^B=&*Gl@gTB0;+gT|QRJlJw%4nS_KMv)xKD7*qipK$}F zjG05bH}5M)AZVR|cmd)j3bAH)`|^72VzVW%X5X#V?6~@5B0%emAkt@7vloa}A~Cei z#GXQTt5A1^n!O4#y_=1AP|dD7RjdZZs-!5?>{V?Pt2kKFrK*>Hek${9cJ=w&Q zXy(DXlzh(<4q9h8F9Ijcr#2)Up-xXT;WV_tX+k(?o#DI$oaV$L*6Gd7()v_MCvCLO zv|B;DC25NldP_U)S4bPJGwp0>xACd1NnWVU+h7yiKWy&^p8E3!FTk+M95MdOXjB)7u88AK{>N zhBE*-{fR}W$NQU<^_e`-sp3~q988KrJw6zURt449)K|35`Z^5CLrGbz$A_Avamp8z z7Q=}EtuuljKrqIqj`FD^i9@W%#~51)D)CYHd@tKpaQA#<;e6wW53Mu4Dd3yzQzsFe zSc6XvF81;#ndS&e!ChJnj;n7fVWIuESPA&Kmshl(dFfp{N$pkJqW+XYE z-Hoen2&tnDU43Y6yPCT|=vxv(8@kX4baOa$Q>eFxBfAGJ>g|zE)W$$<6sZZd_9z>* zu};(`LhZ-e>NpY<>+B!-JQ`=xraF5PB^Yh!3H}8TQ){a~6NFe}PldEtFZ^r=Go4`2 zh7L0iFmr3Gvk6A1ujiUrW}8{G<9I%ypbZ^m8BmtgRu>V9P+KoCp)9gNSxzWuLq}Ny zlvTtb*43-bvicUYmUPjEuDc1k8%S5IsW;f^ZYEu{q3iB|?)KX1R+1L#>FwCu4pBY5 z)kL9JAv>LjAAtD&+Unlg>Tc2(YU%xaS?-0pxHfj1c=THOASDHD=t(&Rt`oJ@W3|;I z#3k0zCrmiUIO-8Im_AKT6B*jj$^Hb{#oFq5!V+reizce`W)^MHUM3W@p`+Xc%Jtgn zRYDQ!=j$evt2QXN2nB8ED6TrVV@VuB?R>|is?XZ6Iu6wCf?9YTy$}-W=I}b!g;23N zdLe{1^gfn=>fNL&*35UCWKlC0lm;b99c}394@3RII_d*;)KbJC*2@ppp{)Y-@&ow% zFxAVY3TJzS*wBW~Rvv8S>Zp$qm{=>91B_6hu7WNQiy|?!&cvQU zcdJu(g(|u_@_pW-imvHYF$RjylA=&aKWn4tbE;S$iuLNLbx2gKrt9$;R>!0-%&=HW zIa+5aPXSI+JvD)F#JV~O5GPpL`A?c86pocjSZJMLy$GzddTK+$5-RL86IDYKm0r;_ zAsn>Ma58}NQa!af;RsdsOD3G=HaIU64q9h8S-@#UEMleI$|NmJn^%bdtuumb5VRoz zvF2`5I6*riKe<85Gcucvmar@l!f zLLJ_nFX(O{5ZBV1CMJE>zC$TO>nuf|fbHXY>WB5z_lZrc#XmM7eaLa&H^B)LsRuEl zb;j5ijCu9c-UKLA<#{H)-XTtuvfKz!^|a?N2yDWj?@!)87VXFyWwehBFj6 zUlWT^oqugo*5~uLP8CN$aX2Xo75Z=}T9sZSsjq0A^>qxCN0G8vrH?X6V=fkyA7hCC ztuunjAedB7ols95PaI;UK1tkGP_IwGGgsI~!++9beBrD=6DwM0th2#7vz|JgK*h>^ zW^i$sKixE60DVrY+;R2IAuP227HejGRPHN{%KgFEB=vz<_1;*$cwbi^KkI)DKf3-A z`_c6W@Du4hJrKUB{dDwAcmBP2rZ;=$hW5-2?O!_PdDy>n#MSputX|fmb%s?ISY?Q5 zV}1P}9}ZwhWi%yBCqUvKA6_&5@!?}m6+KWaAFGxl(XA{I>>ryBW~$|(I>ZCLo+b0k znFv5LL`wm#J};#Jt+NzV22fegst^!bXF$~eR5eyr z323hXR5budEgYyi0iksU^eljC63xo``oB#6mSv}=2|zz}qDdL8Gvzu^_L1^AD93s6 zrvjL=PgEZ6!M};dH+^+U8Lczrcqqrls?U+Q6sxa|(M&uR;wNx30+;;f@cCFQ)SkmV zY@Gl^KW`G80z40Zlvp*10Ez|zqyzvY*#NxY6yQYwq{XTY3E(E}4q67%0stD?05ow5 z&;kI>Nd02q;5UO}9?QADH}S!Li3T67v%zl#<(9E(28myxu8(Jf-;zzV=6K|1h!}i} ze8s7JHsssHs;`p#L6V=u)+plr;y-kCIHl)GfSRVrGePR-htoM#kH<$&6?;Lk zN37~6QSr#?0o8?cWcf`5n4}A}6yWOnlv04!SqeS}P~TWJkATD@t1lp?(vg){IM5da zgw`3*5C9E|RR<7|cw`L<02)v@&{qV6))~++01YJ?;m8_l0??1F;iQb#nez8g9zn{& zku^e8=DXG?Qby}cc|4SVh*igsxNv0s0CD5U8iUUlvvm@5Wc}zA;Aa5*6st}o0O82` zDF9%i4Zswq05btFJyxAY0K$u4Ztj?0QmrzL+ZkjH3y0TdlMi0c{KQFoelmH zC@+dt7m&DcWG&)H)&dcOZ;?x#%CCX^s#tY7$qPr;DjW>U*ulV$tmQTsYyUmQ4E8E( zlW}C70LHOc^$=l*N7gZLtYIAd$U1~)*0W~*rL)_Gu^B_`p> zI*UYXWJ@vVRn`TkidUd`Iaa+yqT-Qt8LHdp$hu@A0L?Zn1-SaIQVP&IOTldb-HKIj z5RiCe-2%i)I*C z&LL1q0Nq10!jW~42|z!x?j>ck&QkFJluMDaaAcJdmHDm}LCR>IDVKrrBXR0OBrY6T zk3ifwvL3?czq54`bYwm16rel+%EhUV5rA-Hl?woP%m%>i6rdsilsMH(0K$=_1ORw# z03w|NJPClxq%Is;m7y3g@A=?AMT3vl+2B`)a#Wo9G>HpGR#cqvD(h(xgCAKnoXYzk zA04OGBzfV;ijKoi{j-CCA6YeRFlzsMj2igyS6Tb<*UdoKNczGrj@Ssb{cOGm{qwV5 zDfejqZSD(HcR+P}oVt~S#kcae#~E+sZ#6N1=YV!H;Og5+C}=}R*$b52#38Zb7a{SoB&I2-4ne{^=- ziP~wXog_8kt^1QUYG<6NU4q($IQ1L}if`Lr;IrwRNn4mre^Q#!hMwjdK)DvDULh3m zE&FQ#IKWcfU%R1=`?*&NN4iN!XhTOT5}%~H;?+BZB)nbkiVr5bVCe`NvE|`t4=66NJh@h>TY& z#H%t<2ye|t#v4aK1*nT_MmF*2)1nHc25so6sR6EP@oLq0RV6O*ZTV^@oT?mEHGv5e z=NaNd8#-Sd@cH7^Xo3^olJ}X|qD@44s_GI7+R#xFfD#w4)+ZFS#k(e+BB9@#@R*YC189Z@*`X+Xmi#e;Lo5V;c#7`#rsI&Me|Y8#?D3;A|JK zwk1gMt@n075(>Kfwx;<3;A5=BV^?1eA)yTgsghPktpV8PwZ}+UHQ~8?WY(pm-yw zFBI?4ji5Y}I!NwlUB}h;1$7;5=v^NIm_hOC0D=*30u2JdMY;(zpm3P42nKEFFy8@Y zSiCxvV8k0h!vbK277jClV9aFMKSFgJsR}oK#)+!@ zwf_WCMH{;66sS&)S0|CMaMNcpgpHd%lkoW`Ud+Ovn?6&Wh|hxfjCl1I5*Kdx%m@(w z#YTL#6Y&KQpBJyrC2`?q&%6Nfxi;bporo`m_+nBPZuBgMTEM=;2YVR}Hrmh!dks`q z#j7hwSh&fvD&DxsvqD7RH+j}Nk^U9Zo8r~=BrV+F*@TV07v@&M4W9Kj2wVO=!kPFq z*E`zra}x;HNng0Za~*1*vAG>|gXb3I9PPi&d4XzJLXs*asJBU2yul+S7}fo469ahq zc-haG;p!`rpugxu8#+pHpxl+9zv2{c@Z6P<*Xv6*0)aPp259QI`tBxmw4tltn_zc? zr$FdF5<(lgPz1VpKXp^M!E=8?Ue5t+oP%!gJm^HNG}Im@HQ@%&!!~MVoTxnkwZ{|G zvLq;3s+Adb+nJYRd#QgSf;S zJgrPPEjen22~3zcuM!{H(D~i~U%LdgEx`#lc-ooR+M0;;ROJu~+R#zD0Hsrc+JR7n z8$6v%C>?B2-Xs*Xp`*M7lw9HvZt&!qRQ0+0wiC7Yq4qAR2{(A&g_>2#^a1q|ZRmaU zL-iw46>so-WRk_aD<~g6A$7E&tM`R^UV_>?LG48h;tifWaofNRp5A!o8@7?~8$7)V z=j=zEXhY{50?t7R>HvZiZ}1EXF6ijMka*A}B9NQ0I}jSZOcdd)GV@2bjLoYF%7?iwOsOP96WfIDZlLZ8Rrdzu`$snJK~?u= zr;6L4xP=sj%6p5A;&!KsyP^1dg1Uo5#p?TaKErmH^o1F=hf}tuvfIfpalIJx@47 zC4SL_bKVB$GU1?ghI1V_SBXWe#;=;Bg=uqx2+%qsxC4T}i9oE#|1O+BO4M&cpmj!2 zEHOzfny3~@)bB+IRe90Gyk3*o=E$q^B8k=;NO7ka4*;W7qIz$lT7pP~%Dhx!Z~9}4 z_kuuNOC?N9`mBwh6rpvNqQ}7YXrfv=QGJ-$#OnM}6H;l8`>+X4m`INkBU)#S3K+eK zs+$0X3f*hsbDOC2lvN-cw9asz0#21gwG!b7ReBW@P9+;0m2l8H!>JCOC}I&R^(d3F zUa8k`s`xAvYm%Z+t=EL2Rp}K?eMRf6uXUj8BW1B-_nD+I7YoXdxV5)#$8 zM72I~h*f)nxUHaSkHa%l*ha&v_WFghCKD@KXRM9E+9*+NK%ipf-UwJiahTu0G+zKc zUaQ=3^}R?~XhXu9<)Ytb^d_)66O&N6cLu;Otdt0<+`E!8T4&1dK>4jiHJ8N2%Ka_A zujQIJz%)avn{oBMOE_qq;d}&~4~Rvq+&{qJEMRjcuyS9h5#Z|kmn!Ep0cTjEI+Sq4%6%9hX0WvL%6(|zSR)7vtuw4~z#5yVjwURj zavy7=8f~J|5A^YbgVq_&&%pU9QJqLQLgoIG31^}W&J@By>kMZGaDE{cv2y>#BrQyv znM8or89_b><`98cxz8z_U>*^mbw;oh1d9{Zg#;l~?u)TGE@7J^uiO`!sPsx_nNy7Q zz*w88u1-`}5{Xc`ujLDRH3-DDw9>?+&)N-?BDBs@^c&c=C8}Ez)y>2vR_@zONLx7W zW)qw+k#-OxT4#*=!MHb3-A#Z(<-XU%x7$Rer|b{HLF)|X7;ugxs)qnRPN`YXjOV$qQ0Va*4HagzD&wu<$l>D zjk#D*eq1F2w9W{mq$KrrqIxS)y+Ise<$hb-R#3U$!ZRz_M#C%j8-=sFlJpxFXq~a% z1J>gBAquL_#LB&RQc!W2e^*j)0R`vsZRPK)fU^Ocx zf-3hXNExj&Wd+J!{LLy77b|yfl5qpYZQ=ma8m(@|)mMRV&^p7Z0-Q?3B3AB|FgTmo zoC&PlH){mA`ko{Lw9W{sCXxKB#vg8e;(keLfbJHEMUfaq8O0MXU~qij{jkKEvvm^o1D~ODRX|EafS{!T-iP zD`MrI1c)^(?YweNC>$%5u+TcgdJ#-%_+fm?l2Ey)nW!3?sPqH93E`l1hLZuDm+<$i z2uG;gUozn|x50UtaL_u#$pTI*Vi7C%Rwij-+Pq2xXq^#cgP;u&h?RSr!U@_D0a|AS z9YN4ONzEY$p>l7J&2cN+9C_uQW1`Y4olZ_M-Udc@{9*DW^-UrXD);VuL3aazxR%~D zG3m4R9ZC^eXDRvwY#-yVh~rlp5t~@Ke{4efkmJ5@f)gfE4`M{?jIl2m^Kie00ENmu z&&1c;M5U*!AK{>NhBF8_1MqjP2uG;g2bggB+u#f)9JJ1Gh63knVi79$uT9GOeE!y{ z;s_`XCq(9iB)*0(;u+GFUBqC6;a-SJo9Oh3q%@;s#(kgdc zeRBv4ZAe)8M&-U1SgVOisN7crU>7STf-3iQq>R>?@~=?dgdf=;aj|mW#P_ugCJr#| z*6L0-orxVl zclT3wh01+D@_mqvdr;+m(5d24C>|z7p>jWLqj=1z;u$EO!r$2;QL%DA#b?+FlfE#+ z&Qi+JI!pOw;9SD5M<5)ra=!$K-7M|Aa=%bG)?b8$)*05{z`BWlm_k@W<$lvdb=^dz zALzFU2dy)lqRB~Wk!01CZ1IZ;iX;ao$%SXc*{b8*m8{=zLF){s1aR&q7O`@_+axVa zo03F;))~PAASguyV&z_{aDoUTKi*soY(6J+Z=i2{;-KkuXM^f z#gKvFNmk1ztL2D9sN6lt#?7AcAQ0D5ITMpUO%zHIT4yOz!S-abS~*#bBsQ^ff6|0h znd3&9;Dm|vG%=!e##jrC&m^nW2~eoqpE2=OH&N*+dzNs}I>V_4oI1&>k8p&_y^aaT zXM^(`;h=SflK`AJVi79$IFqtIpA(%brb0296otw?8H!e=*Yng@w9fk42+9peS*+X} zn4~cm3(Ai)B0%emARPoPlGSF(Y7^oREB6-Swt~vN8J;=8HX2^JHz}MogILizV|@** zuO_Rn5U5zWzX~j&ILv>=G+zLHK&#ww^|c`^v>{>bHY)cof%OG336=X7065J`iJ;1T z04bw&ru;ROha{_mNL;Mkhwy!Ekck6KXSKQ+SKl{;gVq_&cfc7&EMnz841?204yxSy z%Ix2?;_4eg1ZbTRj83NF$#l=XKx_<&p>-xU9^L(cx+_%fKOotA)P8Fv^aayuEg+#^5eHx!(Q%w5844XkIN9!!*^MErqS)ENdV&y&;5NCzT zeRknk^9c*BGpyynTAHjbCM=3}*{)HWQ0jxon((8WeD_UoLeF(}Cq%2nM5hiKO#e(wVVIn~5jNl0nJf5PKO;O7b zhgi8ko+4~3sNBoqnSpGh;gx%t!dc4`D_Uo)mB3mtMO6q?tlTRCODGQW71MkHbRSkO zva7E$VWABPt8^Isocm~CeNRk6<^DYYhOi1QsB#}e%4nS_Pk{3H6!ixZ7c2MiDaH+y zA50uzx}a6=xcVj%4q9h8Q-Cv>Sj5VGG6rWDn=^s;+=pwGJFdQ|M1a;A!Hg8U%Dq5r zCW)bSCN>w{olV^pD)-sQ_i#4uLHFGAohmMb;(SsRD);#|ii?~ou7KjQ6mrIQxLJCq>;wI6~#V$Aq)X24_Fvpmm0G7&r%sMXcNpnxutkbA$-c zIwLp_ezlcPr+^_QmeH8@aTKdbxq|e%0lp?gwQdBe*?-Zq~u2l67v5A#?k(~uESaj_ld6}>Lgil4#CH##5zhfVWu*uQt+SLp0-T3Z)d<27 zD))y>I1x5Dr3nYEGn~hPQfS)b44oGN;tSe_Jx%Dp@ktx7L1^%bqNzE*^? zLds(0u9&1T7YoXdNFqS%j35dGPp7I+rK(kkL#*7NP8GHlRPImVnK5jm;gx%p!da^k zD_Uo)KCnios`?_EMc z8#>BIK>2_;#A^M6^t@hs**poX*7s@ZxcWXOb+n<>+eKu2-F6ps{=?-tj-7V*)+hUEzG8`D9va? zPxE&`8J4aNB^0qT9|nL4EYTZG)D(}4}w%sNoJym}Y3fj<7jsfLJx_XFEgsS_93FVLt%5g$L8#>AvpqwHO zq2fMeQq||~Stn{2p?03sglhXd)T~OTOVmfSq4)6$R4>Gu1x-#^_5^d<5_kgo_hI&_qUeSsb zcJYj$f-e8AjNsx2z=#?&-;lMmsIb#o;;*Q%av-R} zZqiau1lrJ5)1lg;rP_>y#R|JcOQXVWW?}%(Nv+1k)t5miXhTPN1t^)sAy(L#E%SPv zXLBU5!oHxX~{)B`jC*&hK}?pkb1UMKOrQc!tQAz`ou(}AIiN61#RdkUjU_FOSKQ72o-ie z6G|T&l>UT*HguH1Kp99JVud}>Br8mlA*7BrboFnc{tc;%74|oUs}Cb}w4tkyhWhs{ z)e!_BRM_8R)BBTcdc49OVItD2lrc^aegeY8mgwqWux-;+h#};?Za5 zWJ(R%&{H!DTr*m#zqC}R5|>zE&oJTq!cnK1z=Vl2oA}U%&bJ7B3tFo42u`T57ns=Q znTYgMEhZGSp`)w<%8HiiGC~n5>=h=IWi}|Q2?cHFC>wyXjyQx0d!0#DpSv5KsBMAT zW>OO>?9EWKDw(!YAJK;1#~o1JPO4&sz1<{>c~?+A>?C!xp{pN&`u>*c-j?caVh}6r z{o=NP3VSb}xym*YUSaPpobw=Yq79w%6gW?`RF4s)SYe+CF6i=)ndS$8&ubMnuD;WR zg!bPe?J1q+!XF`uZ7QL~U$>9UOj0Xks&c04$yCc{Y6W+iE1_bQ%!*-+7v}Z6Axr)T zBP1!md}dzHTXJ*!hI^$!jl54D43F&HbA%E#KK47MdR`Cth5QPcX!5JDt2eqvrc?vf zvP)mrl`^Huc&1{7O#S=!GY5!Q&SXZC=I>Ks^dyWblTj&VR2k3aSJonH@jcN`Wr94h z;_!@xJ&F~P{1w4gv1sFkERMfYFlci;U9l$XN6(Uyze@18F&`%@66=i=iC>PRu+PHS z#qY;&kY^v^l_Uv$9;^JzD6apJC>olXCEtUw7*$fw3lnmMhoLK@6^1%m$(Ql%d^z~r z-)rCgUTN@x4{5Hf&1#M zzN}AyR5k_TGST{3sBAaZL2&sbIOBH>Y z!suvgHqDh@FQflpzWrGFah*Tk`IY&X_zniZ*x0ZDVU4cH0lvL~{&oq&BBk=#sb=D&lF zwDSJ&GHxl&?Y}Lh)ws7+geyG!@!~})_@}W&eBaUtsZ?4RJ7#jyT(7g`oP(Vp3p+up zOtodEnvto#Wb6e0sn|L*Xf3`Ju+sIlSeNt&GE?3Fcw?S zlKCx-#n#`=7F*|le7?%^*#(&fV4ACI<+j)ZwIISOlcTeB{%#e^()QMjK?)}vXT*M` zopAPD2-x%j67r9you#eK24-pdUu{!7bJ(VM=Jajq?TW3$-GsKEcPh3NpEtIjcPnO? zzM*YD?_v8vt}7$2X|DJ6lt*`GUwrWYWQz437VHnUNv^CVL8~r;r>XxFEG=#6vsoL$ z()WLg0BJ6NPc&=`(7wht@Da9w4>HyFGSzo7)whgoz~38YmHk){A6OIxpXdw1{~3%b z_6j;K-U`?*s4(#7F+-JB&r7D&6X>F?o?ey*3O6gXbl_HwN{4@nVzcssw$6Ww@?WjV zcZ}T(Yw|r~H`CXo{|lB_p?v7Yj}$JBbYbW7_h+^rh)a^zu>VW;z5hercgIIjt?$n! zQBmNk*tl}JOxpyaLjnRO3xpJ^f>E%W5CaL2D{unR%b*ea?H{bI!Z7N%m9gHFF;4^&=NMJ1**T zIj=u1Vm>2Psvs@kW&lnYSravs=E*=pFyKGPlR?DrzsQpT|9|I+5$2+WrMOHPMnY@J zlmXmK84g=)ix@tP=Lj75twvwzCx0Lo~pCut*- zv=K?#Ft!>^G^{5X%@j1D%jlbtcd?ofd3l0}_l2Zv9_F_IMbFmdP9=!ZdIpzz92LUL zRgCk~a2{UA`@iX(f=r%-H@!FsOONrM7bgqG>+g9-lV>?XLFBdFx+Lw<%220vU{?@k_w$qOMNUJ$BxDJPOCJcD?P zrR!+2V;%MHxl0woE*HCgGOK{r&wt1ApRJ$&j)lK|=6Dc*a(dqCk(ii-x(jbY^#T$D zhNA+79MOezE+ShnLSJe9Mx$uhin|tx(P1O1@7{hC4?f>LK390;Z>2*g+Oot6EA7OU zF^7IW1il{PLuOV%?va}Wc?)TZ&|5m=^i*F&?8wX{hb5VrOF;ngC1~`SNsci`mSAQs zO41f2Y4eh_Ic#Pw!__KFF*_Ey)CtSzBv}rlV$ybw--LBZTXwnFv}INSrR~3C`Onh! z-?8x1w&;!lN!?N;8U^$8tTf*FEYKI0qO@H@BD+Xmsq*kL77xMP)7Rp4=mP6Cwx_Qn z7w0)H8hiSBT*RJ^VXcB8L^5o^31ft#cIhWJ5;%V$@(;lO&m(HYjBU{W!I)Mt;`<}w zt1n*0-P!^@=-bG!kf}`$OER^0fdHeq1C2hl$uXw(>&@|-1;**b$8o$n3IBlucbR=Z z>u!ma?v@<>58c+cxjksQJ!W-F4*!R4U$MD8Zn`~VbxRKahi-i~w`Wbam#uEeVM*K` zFvj*Lb8N{m#_~tR=4Evf9ST3&F#ac+sCYK$ze&{9wwvb$vdbIDPE9cjBR7XEjg`^?c=7~^154M zrH?H+EQ#A+39%>d7u_3PkYl)g$#6?f>u&#Ux)pV|#7cKd4ol+p1R?h19oN0#1v!S> zGAKa8k~MF#rX*`pGW}RA?5D%@ zV&N*Xb^XY$YZ<+7x8THYZ>yqb&2602vxXd&Bx~-20D-%UM&H}WF|y_RE zjCcl(o)P328SzhKMEztfK3R)R)?!#jJd3NLjgkxMBf?$FuodJVI9(8%j5@q_lVqKy zBFCNIzkedkvF? zD#itoc*v(~%)iJQ(@4(%aEvup3W->7-4fErl&Ge<7nwsw?oE^mqLft(Tjk%9lGww2v`b!`2I1zmY~qF+yQDS>+Y|Wo3H3kOczQtKcNwjx^RS$bf`4Nv?yA0YbPQ ztc%eg1uU_vVpxR}2q~3`hms_Z1_Dq%k47JLa*X7uMfN__$hcG$XF^#O_o^-~0_SwM ztmNI1|bWjOM!A8aSuBC5I((8v_D(tD}3v3vvv%HROlF=dQ(vQkutj;L=TdMvmIXk2fA>&{KA6xqB&FC}AFH-B-~_F>{>b57!B z0y3U%NsS0wN|G^=gUF7EPU&O?*8nIWzhqOOgx)5^=1rsme=4$PH!JE3MOBJ=prw&M zuQ=ouMX6M~S&q^c9+>Q1qtdV}!(Sl9T-w}XGYjVy2pw_ZBD zX~&uVyC_Eg{NVl_)4^}q!K^ceTJwHj@fkD5C}Q5RN5-zC$o;>G@w;}WB3XLAF8hx80$5_fAYuQlyTT87>OYM=CTB(-iCf32Q&O}r2NK5}^`0skx zvdD$MwWRC$V?l=0$6E?jjO!obx^)>gto2@(0inKhVl6Yt>FP$;-E0E4CT+Qv{%fr6 z+Db;#HOJvu|DZ+B5}m``0H|xT7ey--DNU%3Tta3~Pb1@WE=v-9OpN`jK4ZcnBWx>2 zDfC}|$6)L=SUHF#ioR#{*meewo<~JNH7cObWn29(C=3apKWs`~vxQGjVa3S=s_l$M@3oN|` zvHpgnlHUxis84@{2EQm36;A7xz69Jj-q@(~=(??c%*sZ1y-3{ZpX3rw{eXNbY92gD zUg#U}cT}QaL>3YuuOCjLet|c*=S_o~2Pj_6I_Kun-(lO7IAIr5+Q6 zvOy09d)70PHBmxFT4$lV2R0$F$?m>AK1BwA?GDLuVSZf0x0F{*)>dpxCh z@MoBZC!-yCQ7+mwijVQgBu4g6cjP~uKAz=~g)_1+cQP*zS)Cyx+>sg&83m*f%$hut zx{TasGhuTro|)9+nKWf4O^O+{M$wpb9Y3*+Xd`_@8}O*#WYjGP+-=T!Jg?c%ES)kK zx{b}GnK^koGLsI@;rxJy`iP;j-DJIDvVTVH^ra*Z2gZ1OVdG6S?Z06rU3ezFnd=@9 zY*|Xahm>AJs zK$LegRf&ARy*@zrF)N-^T@U{vaRmO%}yU1d1U(;*!sgmVW^$fqa+8_-Rm`aU>AIA>rjO_q9(9n<++7}0L+bE`_;(-SY12k*!{ba3Xy2kt$};E{dG$Ub&Q<~n_3^T@g~vOIUPFL}sb z44Lna?9M~>2hs>;U!KVjMn2GH!sgltW-^p#GLe~#D`wQjkV)sLN|N*u9mS)b&8TPa z=B&pv&4y+(^V{0yLe#Ccbty?PCvRV7(yO*(De1vO4PvPNwOy8y_f7U;)J|VYM&ZC1 zj}bQBRMUPuGa17(nZ{gChG5H5GLeUw$1t;NyDlX&dB|l9xx^j0h=*LqkgMI1D|yH* z47rhKvXhx?a#*(DzGE<@gON8aEegX);UEaaIy1QX+CLP#CXTr0y&9_E=m%}k!C!ymQB>$oi? zt@ROolt(Qx>WTzze}hBjtjANqhGsMKpD||lD#Td3*T$T@US=Z4IF=HThkA~oD#y6U z$~4&{shz%*)Wm_2+|_NoS*E>@nY_p|iDRx~AlR~$)Zt;8FigW3+fvd_k6?WsvN=O0 zx+9zMknb|&Tkgm=c*yq|GMQ)6hMBbHnPkGmi1r6DZb{im?|23e-kEvGb>>C3dyhWk zk#%8YU%4Z{aQgU+N7jpx<-3!0=OG6&WIuOgUmkK8kVY_v@JvQA@)0%@HrK{8lQBG# znapHbF{3txOgcwZ@{vBGlX%pN8TA6*ob`C-+0bleJ{e~&C6C7mt=nY!-F54#`z;$M zw6mPFu!`Qo6vtxzMoyWuVVYr@F+-x0}&%+I7xB+gsemvX= zh8xN=8N*CQ@=PYf#K^`8?wK*phFoRFX%<6HcSla;Ar~^_Ja^`zUG(&iqxxHXx-)@@RVC>hd z*|AsWzRJTDGTdD&Zi9}y&BHwuZ?5zq@s_pNzy-xy*Knq@EWV+7|)Y7 z-qWW2AI#(|&*V?$`Z5GtivEi{%pHcg8E-54kLeM-&O?SIm@~kW;EF8dA4ejALW^pXC_baOhlL%(XN=_R`j3KJ6?eY4`&|25*&Hqb?=eFBdfv4s<|U0 zoIW%jSzSivb0>@9AsaAcygM?MhkO}GBbbeOCa*H`W;PQx*WO?z&3Ps%%p|FpQF}MR zt?0j~kLcSx>I_ERhQRIj56GPLc+zZWmXu#H^yffZs{3m?vU7s1=)Zx}`n>NBs1dxb z3DyncmTA(5vG+`{Y&3;BcRmj{nBfLkaaVL)KOSx*!wq-C4dvm+Gu#-S$rNTXk!La+ zCPqMJB)D#D(`-o3<200u7;?TlaxM?Kf+3f>BbV@yYgva@*-Y5*ZDHga5l-vIww?#t z%|JTk?aMQhr+6lnnCpK)uw`R=mWK&r7`47_dwN)ppv*%?GNk5?e2#~V zV#u2A$QO9X7>2CPGpWx^;&>)aVPZtPNqx7C?Fqf(jd<`knTHn6ym-yMM~OVL_ZeBT zJMulJk9T-v8H}urJ6ReJ`5{AQx+B~3kRJnS1T%+c@;M{_#Ad?g+SknFOP)zDW|Cjb zsC6fk&T%*E8GS^%@u&wg>H)kt>+$rnq1nt_!q5wCCeNCacNH^P?i|jgJk$n;TI(h& z)MVdE?ewK&Ck~A9*kYat>z>5A_v8eeNc!j>+DQ+Uc%(;J_GE9l+@Qp^fr&WG@~xn&}AthbJpW|u%UHpVKeie z3|+xy(g;9(etVgT+|aT6h&9B)x?1@9@TBUiKe}enY_p|iDRx~ zAlR~$)Zt;8FigXSw*9oR9>MxNWOIg0bVoMhA>U=lx7?9$@R08_WHQgB4Kr!YGs%RB z5$z8ex>Y63^^Rxo;GLO=TxVWnyZ7ir9$6Pg_LV#G3#X6Icx1g8S-v}2cOG&eL-un= z_T?dm0ciwt2+w2`BOhTiVRLOfGa17(naND16*Fp6$fR?;!Ff|3(Mde&#f*9ZZ_eW5 zdK;R}%&iQ)$!7A7IeB+8lO4|C+{Qy4V5og=vfek@k5D^(DLIYma&%E+E`M^oH^IXYvj+d9#>Nd%cm{QqoQz z(dInr){Odn0=K`xA#>K_X=y{Vr0mDgeQYKl0I1LJ@0rOU=Wq_-p++*)a5q^!O!jfq zPIomK2gZ0zu<`aZ?PoBPsXUYU%=H`ywp1mvc$j4jv&5c59rOq;;vv^FC!WbMm>ALi#WgAW=p8@IgP&s_PCN7BclREh;E`QpWLMmg zmz+K>@W}2lvfJ)tH+jeh8k?(oP-ENbZlr&i%0fg6LSs+H?hrOBmSNyj@&Eckv+=D%D9s~(!{zTuG3zimt9DS8Bl@{p4la=bfoEDt%0A*Z_| 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 z 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%0D$ROeca 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%0D|u;u~dTK-1qmG9IvaBqy9;g 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

        U1YwD0}sfi8_q_s}~3L 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®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 `4GPt<1slXZi;C?otsRxGnvb! zKLN0?l+3jAS(Rs=wN5;Jg;%j z%b`90vGWXzGLu0iZqnY)#K)y$04yveQFcCExKGEJprvGhp1}k=&tBX!F|=oQJI}|t z=Odv#``URv%{`yAGs)m4sdgqgFfp<{FecQb%+oubY3KetS17d3i~P_%de$!3P#)}+ z(4IrA8ZX%e8^wbag$_2t&T|6y92?qmw4LYs@HCS7uARw;Jow}w6Mn8u=O$C_Oy+Zw zxn+#nY#A|1g023o2KA)6ZSP;-(V>x;t$aA`xr>@+yb7;?wcAmYsXJTm2 z?slG!@DB9}GU3Db6c7Fc(wQZV2&3oQRhR2AJEsiplnSTZl&q|PIW=D&zo+edpW{pg z!LxC(?l~xUHZC($_%fG$DJc31)8sWCeW*A)*66YQc7AVhzmcNfLfx;(&hH)WH$If# zSUbPT+;5_t$y9DK#m?jtm>9EhM(CL_Ey#1NnWqKZ^V86tbL>2qanHq}Jr~(|uHqe9 z5oE%LZ#@tG1=1*Lqf&UZU!+7c%g{Rhod{m4yr#aW8}AMCt-=3e{aLKOW+ z&FH_9oxb@W!!O2o{uUJXm}!5KoBUyC@;8@03t*w>KW*o8mHS+Z3o7~#=^4Ce=NTSv zo&m1-ke(%Wo>jSLmC&A*;>981NvOp=tJ|5><0iM-naD6PvfVH~RMG#Z-th)@?)Pwo zCh?Ye(I|9}?y?Kkh6igE+OvgKL$eDO&4YPE2XotbcHo|Ip*>^mJiEfvNM>g{lb$?y z_aGB~uJz?6z3fbqxk*wPqxN`wsG|S0KBAA>h0f%mGnjku^9Sslb-B`ly!oVjg?s-O z-a>VMUiW-HKB(yb2Y2h|{Rp@k$r~0gZWxzMlec*Ek@3PtQ=-Q%vh#a~`;8a<&gp(* z?fj;2ze%C|CffN;=YCV|OlEVFnRX@%VPYg?UVO-nZEldK3-6WDQ@NabE(z`VnVshv z?zt+o=Sn-z4ZK5ZgG~7FZRWu@A)VsJ_NATE4(_xSPC*-6IC|`IeP`zzlVD^}Pf9F) zVb9!E3v-3}5~RHJ0=6r-jCc9qJwP4sc$lj~SjU7rbUT+TK0(S(F9`hev$mPx&Scz8 zH?9!Yot#+kE(uaW_Ml|b)n&ZbNO!FOokSg~LRc@jgb`2AQl$WM7(YVBkCCy<)i*)P zDa;l&wB89)zru`wzX@;APZ(F&qjq7Rrm+2Z*ryVt^qhh`JVziERiyV)_*||etJ>ps zYAJSV{V7?QTrJ%iHZ?e`j933yItSQ=9Y|rb0}`1P+PJE8v;Oy`Bt_)idh4I3y1#nr z%fDia$F^-%;h9-E;dtj*yf>+DetKSh((~zgxz8shq~{MT$Q_jQaAtmCN><9^tD6OCL*SUI9 zrCV=)T^Xgkq5P&US5_%2mA}=E%5LR*WxKLfIjCMzt|?cPAJuW{hw8uzwS5JJ!>UfL zdba9?s(yL6JW?JlPmrg`Q|0OMEP1v(S6(15l2^#9^|@|W^v`I!8Vd|iGW@kc3R zl<~^D%0y*~GF6$W%u$v@ZI!YST3eyETlqyfqg;a8HRUyRg!;N#q`sk!RNqwJQpc!c zK`=p`2#Sx@Y3g)!hB{OIM4he9QRk|ks`J$O>H>A4x=8&@U92uqm#VAO&()3Ucj^!7 zPIZ_1qk2F+s2)~-Q%|X9)U)c}>J{~>dPDt>zq?D4mVtV?ybRpS<&`)VUUTjh1D@w9f#E)u=*2LCt!6FR;OTf8dhgubrx3VVD%TQ{)W|gSY3eCMOgg< zt4pxD467@!x+;&8ufg&8Lo^|Uc*cnp-fO-SKd~Nly@*Y-c?2_ z@4;gtJl6i@R$yd8St11k6G~eL|GuuhSwZ; z&4t&e@R|p&`S4nxyeltM-jf$86Xnm8_vOXPBzXxUEk&edh_oD$Rv^+!L@Gw4RmyB- zHU59DY?Rj^;unax77^DW;(A2ffQTEFh02%8BIPUPGi8&qSovC6qI`phn-TF_MEnjB zzemI^h`1FIw;|$oMBJealYhYfoyr^wK`gzCy&87IaXbRGx_`I z@#>-I3F_hKx79UK@2Fd&-&MCozo*V?HBp`4>V0)Vt4ZqBHj~xu(I2QgqNk`oM1QF6 zjQ&WS+I%Yhf2?kao~9m*p055HJwrVbJyZQHdY1Zo^e5`k=-KMA=sD_qd9J!Z{!~34 zJx~23dcOK+^aAxn^g{Jy^dj|C^k?en=*8-p=q2je=%wnp=w<5k=F8O?%~zb(rYISw<&(&*f)~G)=`9giO(OUJ-d)BEJ<@M@Y@&@%Ed87KH@})Xj{z@Gq zZ&Js~U#sKfZ`4cjW_7&$tvW&ePCX@muf8pBQQwibs_)9%)c54=>O^^m`o8>wx=q;$ z`(5fLdAE95-lJZ{Dtk@&3IF%1ljVKt2l9S(ihMxD`H#mAs@IiY@c)oHv-x55cllTK zBl!sK|4qH2{Eq)e)sN+4>NNSdI$i!logx3J&XiB6v*eTNC-NzEr*c}IEuT?$%V*U; z|PDRy-T-Dk+hq3Q}xFdP+g_mMzCh5zJwV z!x&n$zQ0}Dwle=|)z;%_-@Z*-x0~Ok-)PmcWxICmWVub7c5OZSJx|{(NhKvNDQ(1m zKYBdbePc=0nR`F&K5z1#u#R6v#$}CHF2UOv}toYTdGxCn-KRJG(F^v*3lKhvSp_7q%gR#a+d!ceyf7#|Ei+5f zGXD3vF4rjFl2Y?t7*vp(l$Vl|rXMmu-8@y&(sJ`9?eR=Wdqir3!=sXh;x2Cx9!czv z|9CL5Uu#M0&>6Sz@hz>>3zF6`vmmkGGaU4X@tX#^q1IP_)JbuHC@D z;#sK?rgOcAt6{OKcMn^#>iH|;6Buak)sOcX_f^*Kt2NjCKlj2Mx6GW>tim)D<1~)> zDH-Yc1u3Zmn-7p`xK@mLcEWvcuFN=G_xijGO_esa;+-oPGer;I^6<>?=oSUvw(fnQ z%Zc~C4Xd>!+HnW^W#;O!Pwnloziu13+q4E7Uy|mmdAZh-SjVxm2BhQ<(4)5){_Ef= zNh^I(ijJE ze}mlhc;BlfwFh6UWvo!GJ4gPju+I>q+#^+@R0 zrCSFIT!jUeDe!aLzD=jjojUgH)FVE&b7FVXwj#4t$oAz@+wL9lg)0xnJsA5yo4lMf z3M?4E!i`&X?VixJN5@V*VjpNlmSHR``$(iqsaSMHLe`~fw>ZmQvS)pffb zjCLK1cQr`BQ!Qb)+(j{-%gZcC7lSlM7Z$Q02U2mUiqhiQ0X1AV-5L<2dV=dI1Zhe^ z7(;SSN;W=zRiR>K2Esl?x0uCff@;SfhCR(cP6A4mQ!T?AN_Hb$B#6-q)>L zoG-p>GJmIrLf;|lev!*ax$;_?@v9OL7CYwS z6tdUlDQ^v7w~E<)DFnm{k(Mo2g6_U+Q6PY={VET7qeQd)ZYAl->`$3bqb9`xtB`I#@K zCl?rw5z;G>5E-1CiHV<=p00oRNb)y_ISV^g2#X1noQh`x=@UxEaCL#{Iz95Wy78TT zz1)&Ch`G)YTr=~NS@+Y^c#^{5x1J^79l(mZ2l!gvca?kR*co=Z03u_?Ay=jq`##|6C%=vJbE z6(J4fXF;e(_hWpMgQf}Z+C$W}TX7=mi$Bk913a=**RNfACiBtjLw?^2on_ODPmD3> zz-~RjO^m?o0}YRv+eau+i4Z6!H!U3tb*P1IFH75l(R_7H#nZkR2`*a`0r%;$dwoH@ z#!&7C6n?@}guDyfY;oJK2l$jHo}Uoxv$^<*kk$vxT3_$Z2>l#|o+yMKlsky8V{Ab< zphq5rDTbnt?M0YqaK1*)Z;8%@`2+X_W81;ctn>SYRN&cEx*0CA5y}TA6|86xA{OtR6toUKXMm+{wm=&5ix9G2;EH$NO)< z8WM~gzFFu$>Iy#Dh9JNR1PHH-1tc{q7bl{*Al3oIN%qhSAt-o&yAa?Mvl=g073LUw zsTqt-{?j^WnkQhbH#;6M?`W})ke&){$UB!yNoqioFC{IF=lK>qc2<{L7Gi4&7`JCB zNI1TipGrb(@%r*rn4i+$ZV~&7_4t&S)xzv#6yMpH{{j2`-#WzN5D@HH9okCGp4?Zu zzu^SPN@Xt}2GphJ^;oL{7Ov#ZSh{GtEi`%(A=JGZkR+sdiq=Xva048&6 zo)i=VXK!u9x{O$O%2AR!BuEu11-pYZ!xtpBs0|LOaw=Hi>!{qKQM|FW*t?v7fq+xT|mo`DxvFLvX4 zVY$}IGc#&NyhS~Ecxp&mQC)W;gi^9J;w!nEBj=2waj5SdN&gRT4w}X-1NO^ z$)@}rkY`tNFBRKLVrZR-{ebRnr|zb>jjwQ0SZ}u@-;>$6qyPA-n>X<-NBUQ}>~yO5 zBNTU&;^aWZ-8PCpIaNFe#RG0_ABnzT&ak^#KM(L3w$Gw3%&=c5lk67b%u2YSf||D3Br1d7J+7r>Xe1*goVoZ!lSc< zgVq_&Kft-**8V1(@qsuOEI5DL;9Mdcw9as@1LrESOf*OAUY47y7HMJH+#mw9&Il@a zI%+PDu|mHi5V$Z~@?lD$sw9W`3Kv2b_RU(M~bn>=hS*YSE8orb*j?47Lae-W1 z$wFl;AXS}W+zO1^9<8QFt4<^ZG&$Uiq_)T0GHQZAJeR6ln2cF_8>I-XvlQJ4wuT<9 zfk*ofu{~}MRV0IJXhCYgasOk16NXVHMzqctn}V^iN4uK!&+y;H?VD0)b74)wkw zn=BqEhAO?HsIO?9^)(jCF{C`5%~MwEL^J6ai!|n9Y5CzJ0<_Ku9t1&WkJiznB@jop z$q~;uI*ZE+zTLee?)jQ6H0$(*W}RG|P&R8Ov~K_@qjjd7 z1LZ7__6&)Om3tOn*PgL(fay!UZpP7@OE_qq;S>NTk66UYJr9GkmCYFp7rtWGxSrBB zod8E~ArYW;M(~2iu5vFGdy&M@Ium;t-Tg0hSE$_oi+pcm;~rGGzv5JJ7!+S6MWJ$k z)kbl+Q^k=`Eb?e0NK~xci}(y1VbK?6*eFUlT4yOA51g?cZ8YJCmHSvge96+zEBDc5 zV@)6|w9c?51M7W{_8wsgmHYb^s`o5Z#)kd@;h=SfGaWb|d$f-TN2uICw%~kZgEND0 z&^p7J1DsEYMXcOEu}BNkW-bw+bw;od1oMeNtla09O|Xav&^jYn0fJ>7Z3#gLmHRR* zj@#Md$Se0H7Am9CS?LsGJuudKv^5@WHIWFF`&xcNuK|I0F0HmO8MAf+r3kIF6nzJ_ z%^vM*kM=;^JqU2j!?Ppv*7$>gYz@tpmm1xD{u}Gi%_{AvM3w#`G`}+V^I8^6otzDcPNG` zy^d2~(K_qvNhtqG%3|gIr$ribv9$a+MFeP_5nKepd5`v&M>|U#VbTvkxI|Al*Y zu!V+K?q|zp{fAi5I%Ac*9km-C?HYlKmHUn0;;{IdWxfDB z8XMMGV|M{aXRnb;AZoVW8S)d9`|PQ9KwSw4))`QD0A+cN00Aj^dX|MJVCBKQ)Vw_i z2i6%*Z{YOu8rg)S}K?x){wArVFb05*cI-?s0 zx`(~SgM_B!;}2WN9<=iC2|b>0V4dMi0nTKvF^O=Le0;J6XOa!hql5$N3}+f}o*)(_ zAAiE4EJpH^P8FYq;!~uka;)8X@_Zs+K^%}1boSK8b8ky{c zUa^c3q=LJ64vwRDIbp$`FP0yld%2B&=4DbUevC9VO8z||wPM2eQS$FcQbpzu8@uY` zP<=Gjs32iA_kJ|h%)KkD3}W?qf*@dHhj!BX-o20K-8gz@kUDJa z>d&Rx<=mA*Gf4eb=4`5_l5fvO>+Xw^Z_jh0wh(IbNlnSM=i8_)a-#M!)Lu+A z7L%ZwXTK=N(PE1><=L-L1H;DNz^?;hd8)CDAk-XtIi%HmVVNDw8w3LzJ4^^L@1`2> z5R8&vziVN6$I8ODayQh~xv|T_BXa4z)F`mAH_Ff8I+$u4NHz8omzqZ(wBQ_& zsQay8Vwn6wWU#T5{SLBYsm2k)QgY~H7OEpw7CveJAQafxQT_(XU#Z4PLQ(SPzbq&x zZBWh-3T*5sS{m+H5{HsIpS7rpQR~8|zAJxW?|=FjZe=1=4QlaeA`w#Z=J>SeiBR=4 zkqE)Yu38hSHAq#>nQK^Nkuz7O2DL~XHg@%fP_Lh6)Jrq!5QCa8*H5FR0{L=1Jl;?F za-FK#E+ID9*x9ZETaz@SF@dSMaudKP30kNzkkn)bx$<6~E92;GN=UHhi?qEnJ|q5* zMxPOHlAdKWPLGl=H%_mZ@Kcn0`O0)LOkkZUH-oY#-DpbUYR>FQH*@Bu77mP?Lp*oI z(c7GGV4dM40p}WGQM2c3(kmt&iOimlasnK^*AW4%GlG`sb{TY~SSu2Pbtcvh)onx7 zRkG+dXz!y@vgr0s6_cUZkrb6ox}%L^ic`fdQ0$y;q>`wbO?Q?fEY+f~jIgfMkQ{M;PfXJHPh~IkyeIH5fQ*TBNz;VfkdF@+ykp7 zC?*0}X9UARaA&$PlpvJs`%Wy5zq7?re$r&9g-T>IBb;K40Y+K6F*@BCMI=fdUM45> zXb`A#X_SRYjM{ssiC~>IQ4nkor5g{V8)J!0&BY(GAUz;)$6DZ&fi#X7VVyBf0psL! zV-f)>S@~oO-y{o_XtGBM2i6(Rbl^-&H=ZCIB{QF9!Fj?4=PAO0b%ygCaGoI+B|Cq{ zqAbSqOs9%-p*Wiql?;706r-hH^Qf+{&g!}l%JWHC&C=&vq%jsN(~m_&0PBq4RS>+A zZoHIkEFlgxQ-4KWR*A60=nvm!Y))4s6L2w3By$Y&Nd!RR=cBqMk05nhYCcx3_ zp(cQJ)&$oADA8v$C!nuPpywD+A|QecXsSEZylS8%0)ll0)EYo7eMSoc+N}V!3eQS>~>FZ7HggM767s9bRuO~XUeHiP9f#PP|nb`;PXs5MOB{T z!CzM3MQ<7@!#Y#WfO1!#kxt_0Xl^WI;$0zr2sa~e2&Lok3z(=A=6KjV0f^Xd{7wOS z0HB-C$RvOSpO~B+pj#L~rVYRiP62uYpqJ0cCV;=gTcB4MK(-CQjZOjj0iZ9b9}DmN zzEG@SZ7$X(+4=d@`LND9zdw|3_8EmFeuAq0BJ2E{*+A=u|3ZZ-hFl_Vbt*p?@&kQF z5y|f*`K3&LAU1~A*v9Y@8*eyohtZ`6X zLtECv76J^?HM|LM^iHHEfOXacj{#_k&zMX=>XtPH5G!cQnp`!|;{*ij3}^;`ru&R( z1f*_R)5CzKRSons0l_*0ngyWeh(_76p0famEo(L@!#Y!b9?Ek`S=qAYs>*WJnor8G z&Xkux`30Y`ki?ZO>jj9LTh>B6{(#Msh%M_yrvS?Uu+(R~OaRK3wKNRiWgCFkoC3TB zfH!=`3Ib5JtT(~{R@eZ%?G)fW0IVc+Wy@L##jv$Wc7BLDAJ$pte*on*K4TS$D_hnY zxn-?VG2{}t&Z+!Ikl*YxHjuosWo^dBuz_t1a?9FagR$lOG2UcXS)ZC))?;+|O*z@fi73&DFej_Gj%lZusu^j-BS6N4$ zDxQGiA3ozaiK<)HA5h&%Th?(40cdveCcx2ql9~Y4SrhyVpff(>Gy$nw))_!-rY-Aq z)j($n2-X=;wG6!Dnqj!`g`5}n)e_Y$D?XzV$c4vhA1N(VJ%iqe&2R`*3qThVjk0B3 zXaNvgR&7#-b=DO1pj?NPl`X4|sw`Kni%A*QnQ|j2Uy@-oAaP~Ox&-3pmel}{zhUzv zV#~VBDZo_#Xp&(xCIDs2Y7z#}*ao1fQ-G@h&@9975P-5}H46jq*Z?Ft1-K3X*OI!j zWnBx!uyHRt|9a|tSZAHz2Fk5641>g#Evr?Ad6i|T7;?*M>r_4k@|`k__9U-tS)DTQ zseiUH$SteA4TkspF`jIl>uSb7{`x5pwvoQ_#Sz<}_Fp#MBmVsCGirO-^KJV|)i0sC zGsD*rKhBrr)WVVPkLR(?B_uVVoco^)35T0NBf#dMdx6 zjr+MLsz&;okYHm+it}d~n%_7}NXpywnm>~0tc6JI^znX?W5C9aQWGdO{6=-ZNO+XD z>T6g~s^g40G6hO4LV=APr5;e~5Qq9UeI1LeGE6Qeb=cU|FNJzTQdi%iZ&i!u(6}`07^IFP~M8~W>FPm z_Xa0wy`Yv&YRcR2*-(p?GUZYoVPmgjU#Q+ls_I+tH(F#d?kdxVJW_{^UHw+5-{LoJ z@*4%jpuYWni@I#!?f08-<_KFzRa!{KvELA&>+kB z0Ps&N#bZbBP(p%@1?gIzVLu3@`~Ai}grwdOx*te?vR0BegzmwaQ|wIm4WZLK>%`If z5Fx?Fjx-TS#&lO@ZP$x)C(lq7IUCyy`f5 zAE&Cr#$NRqfSK+$rV)&K6KFaBj?+z`X;s5KO)#*r!^{E9EWhy_!KgQYW`)5#S2fIB zf`N@4W+7na6Nz&3XTC*T>>`Uu6*hL&7oobCRFxY)i&a&5?f(*~!p5%p8dP8P8?TVC za?|Hk2%9&3UcuvWI!0l{O`qjX#NUSan||YU5?5~cycs6`x{dfdPQ+J1JmfdtC2{3u zPbf_MT^sS$PQ=$id@U&}H+t4WEo|M9oxPqq8#eaN{s^j@{l-QTR&Mfa_M10(HmV5n zCeIcp(w{+kyWiMK(#j28>~56nD#>->Cz4=sZ`mEdr}qO! zs{p_9%5|0Jy6#Kt7-+{nNYfUFp1H2EiOGR>{DV+!D<(|Rapr+gs{s27HgUFTvOj=m z4{{%|0<;TgN&Mu)p*Dd>eD(QDO_Kwx9RKx$P)D3Dt1K*D8ISi$AeMO0PanLhfnS73 z%nabeE1TS;$scE%B*6)A2_=JOl5Wyuag~X9!J7sS@$`BAHjK9mPISh9u&f1w?Aw;Y z5Su4=LplP~z-h#Cas}Vox&%lpnvWD_@M_l2)NVv-~{PiTf4#gMP zYaIfK_3#C;Jx zmFCUsN$$Y~mf*BE9W3JMOHA*IfcS(?T_(m|T2xH(A>JgPc-jw9gp7F$A{+f2e3?0S z42UvyQHGs-h3QsyYxCqAs4=QOA6Z?ieL6rAdfxL)W8eAp3|Aq&}-spoC{F-9F)%#bKJ(`d|%Dm9|dp5f3Um(5?JvY1EG9#M02O+ zvZKWda=M|`_&r)h07H%s(CX}b-GKNo;N`4eZ{%}|jq%=WDlOnsX+iC5nmD&}{0o?y zXjqq+vEn>_;+BCWUP3dr35zJ&Q_NTqU74|5MouNO<`*K8U?JfFRQH-pBD{l9yIMHs zy@iw2#zV{wl*ajsL|GBXoRf8Mva;ngPx3%swl2j;5>M-~I0;_X>IlpyR(%#tnFC=p z<7+?zR>FSj@tVrDiA}wRa7e;1z{5-MFx1!V&~u?a>>=wyvGV8gLYJZtpGxfMdH$6u zpGub_0K_hX;UkGX$5gr&Q>i#$43e{{G0rCrt(+ytYBSs`*x5VzFcsa7bDi0_>@+cg zu0nr{k>XAsO&ykA>11w`!7ezL7w;`a>zc*7vSLF6iLKbzmg9$Lg6x;463fI4W1E;j z@S#{}DCXO-+O&zKj0u=$T93bYl-zQ(rpe`qk5_q3GooPlqiWt0sTn}Ayo4k~Lwz&Z zllUZ{<4HE2C^YWmdlee?l*{KZsS$z1!>z?$mWbMk`HGJNvW1z#V4A$3qq^gpu?Ej& z@$Y0KA$cs~jtH=sga2G{pxOV)-BWb)_fq;h04uoP+W8!m zK0hXF;%E6xRQ5ZQF4qrsp2wu;;pm>f+IjvZJx@gU{KL-ktn@r%S0o|D>{wTd+Oe`J zYomy0?F&=bZwHGX?XB#i_GojL>jFFXOQk}C6wA1{I3;Q;*0l@fmcg!!?sr)bRfc16-;@RW!ma<2Jgk#xHvJ!O&ZRrFd`3MSpC z`{);z&7s_l_h`T_bUzuo4|9(;XI-w|5#Dk*4VB)-5k+#$$y*|e47YaYopxU3(ra`y ztX^jHu~d#PB@g3?=#K{?;^vy=C(0t@?20@lr7HleEG3WF`OJ_$PezU*_S=mv*Hk;t zxzcl1bkFDPJQqvPh0#6d+j%aPo-f%Id0iHH&92CMC?Z<>ov4GdH?R0xcJ3Rb!UxuI zu_k(rR@nvHCWCz(-SZ=>#%8-%#L=X14o#!6u`E7L1Z|pqx!&5ZoUb`ZPWbgwK zMdVyNEQ|bNSLBo|@@Eyj_IuQ&nIP%b9tJ^set!H?KT% z@-~r0F85k?pGJ0Gy7X%5jk3bsWJbS+%JHS71)hlhNQ#Jivsu24EYi}hNV1gf0AOV) zX=mrtRr+-HM(n5ThuvMSR6EZe(laZ%XTZ+$M(Norx@WeXXMyz0vnz6|EON75kzy1P ztv%2iEi1W&54_v$+)JdwaO=3ZGkT4N+6B8$1{)LIv&^b7+Ai358SLTc!5*~pd{lZ) zj_x_h&htrlipG4xuE;Yo_)`%@%r&nBHEE9uXBbe>)4(}F%TiKd=QTrmJ((J1DY@N@K9kDvrDPtS zi2j%z5qE%DevvFP->%3jQu;*zD@(~@JD)eC&+^o$OUW`j&-bP0yU{)0vGd#@JwJ%< zxyH_Oi}c)VSL9P!|k`y z16GawcESFT!Hz`_cErx}jP(2~y5~tdPgk1Rm}l*ZR7VkUGa)|BX0FweMQYd;xkMJJ zpJv}{_0pm(C4+d6*0BrSREBQC+#@e=*qn8_8b^4`nR#WpS-r;TYW40gCvS6E#FK7W zN}AevT_?S+Nsodx(v04U%JHS7J)Vfc-6kS#iCI2H7U^hLq^p$f3}9s`NwxFoE`2i7 zBbJh(yaoMso;OO*UeP_X?L2Rip83%|^Xxo}q-TG-BE_=EK)WI%P(-x$o$1jA?TRduMP8|**Ir_i&XSdk;XS&vFvj;Voxo z1E0B+)bnYB?id+%XLJJBt?ko>DyJX8X+G~8!&Nk1BcC>WXxJUw3bTkuM!(9Z4Gt^u zG>_fH&M!&&C8~Zw?$_MTuZ{F;8O^VSonI&E*WRv3nkKjo+cHgZs_|0g};o2i{biZA9xeD!^ zilx&)IF$?-K0Itpy~g{m$j*0+WGamujc;<#lE~5cj@g6{O4+dy(cd+TOq9{bsiR{J zkNvQn-{aD6it4w5`%SjIFt`gXI(Ng4eQb#(0Hv5(vNot1uPRKLyK@3fs? z^$c^RkIzunV&Uh?P}gwDSzG#DXjkN7S)`6#k;_m-jK)hcqOOe%B0Rq_+o`GaY!cnG zv7Kk4^lTR0(_`m(y{yo+5k+LPw3WeIp*hvjXxKSYE z|9{P<`brkrnPEx#ci4G-C%txML`nL8GNbRKa(wgu2~R|S?vIFj&@BI}EON-M$nR46 zD1eou|FE6U-_qw)MnuxTm$%>vJI{E(IRi9*RL`?^p0%WBjp&}${c4xUMz~md*0C$n zNET^mSEMP5h}Lf6kCycR!Ykg`&OJ#gB>FAmqIvWh>2|@|$zZLcd$zP{w6F`7CWEC! z57x=fGax;E(LKA^dENj|(U{%risZ`R*%3wLT+5S1ZnP_Mn=Eom6}@(oKU&g%g!gEH zUFe}QbTM;}ynn#vtjjeh!dni?hotxY@K&<>Ke^{U{)nXi6i)MbKMAg)@y7er4db*~ zc zP{bd&irWC$EMXJ6k?l^l2iY5ht=3c6xNL6Ohm6_;w1M}P6_-}-IrUwxRsrpfVZ-t1 zAo_Bc=jdN@(*Sm_!x&u<7&*9z;f2@q#>lqFk8F!Rk!>MsJp{Ez zXUB~e=y9dO#+Q>F!)#o9+`X`@+icCbH&{m(8^1Ti&*veUy|z}9Up8x6tG14f1H&G+95r~L_WSY6vp4XP#$)XNl((&q`>$@7V~Y zPoedt=X=jl&tK5`$1_QvtXJq$^vCqa^{M(aeY*aX{y=j!wH=k@ve z0)3(Wg1$t5QGZ!~MPI5f)0gXS=y6AJ)zhZsc{_=-$k0xY_*? z>bV8Sk8#|J<0m+7!*M%~pSoweKf|NX-EX^hpxhTYvlD0jgEL>^%vU(`HO_p4GrMr+ zTb$VquJ53?2e14WuY8YJ_TsgDc=ZRowjZzkh*Aeo>L-*sh*F18>SvVt1*LvPsozlQ zFiIUksiP=$45f~v)bA+u2TJ{kQYTRABubq^slQO_G)n!AQfJ)L-T$EEzbJVYCC{N` z&~wr~&U4B=-t(7xg6Fh*qUUe-B+nW5Bc6ZIxBt2;JZIfgJm=hxdV=WZah}ILLH85* zZ>ncJdVPZDNzX*jbk8L8|0A9mp2?o4Jr$m3FeaY$JnDH49y8%F%kzY1wr8qm4m{?< zV;(%7hsS()EP%&Ccr1d)3-DMBk0tPU5gspjmb+hu*DLT^3a?k;wG3Xb!E3qaS@#Oh zbMDtYGu>}^X1U+=%yz$pNN*$3JBYLrk={k5_Yf(BNbh@I_N>Bxt34atYY=fQB7T5~ z>kx50B5pv$jh+>rO`g|1n>}xMKJ>il`N;E@XA2^JjEGwi@e@SchKSn{@l!rUz6a6&i|F4Y`d&oehv+{b z`hGcKjay&|LmEd|Kgdb|B5-f zSARr5b?s#R-?R$-Y}yokP2!{axwOahVCTp6ah;#g&$OSa|I>b&{%`vy^%iPPI z?gjd$#D)43%@*m;xL?pWx)5q1PO+RQX*Z)aep&v3{*B|TrhW>cxH}#*5xAZ66Z|lDp@91B9R_bqf-qokN-_xhL zL;92M_x0)SRr*uz)%pzg8vR#et$x`3f&R369dy_0&$>70&$&11Gu@l?S?^-npWwf3`W*LmeXjdceV+R>{R8*scx{LNujdQ=w^RSk_>X?T z{iQzN{T0rCt)KOLga3Bv3*F!9+uXbLMegtP7u~vJz{@<%iYosYL(Nug+jVN+&Mp77>5!7r zsZ;w7$;t8*f6%6N>y8~ey4{_U+qLe*&)i;9)6Si9X@ehmVE)ZT$!FiHy=2#`Im_mJ zwNg*)yJ2G+m)4;61sZ#8eruP89FzYGZ*X>kHFt~1=B!yyRFWEmfTV17HN~aZ&~@^VI}?Bwr-Qs-(NCfMES^JW%u>Z_xH~$DH&ecKc_Dq zwrSt8ZKsxPQ`)p?-GAV)k^Q@ul$I4HcjO7yptdas4JD8JXSj2)Vn_?LN)O8djD&@XoCAktih|2L_Z4z~hqthbg4Vh|Cg^2me2eT$!ix z)KB@4>?c49O`k!{}-q{;!SSuU(vV<(W&`yIv|pN3_N8ZE!{K-Mh6b zF_oWG&fy`ddk1fPG{3##K)qgelf3AhuYr{qk8eTpa`8D-o>3}}&MzvJ=;O+Sm6xR}kZbhi|=aNkZpVWn0_!J<;RW z=eEYx@00Gh0t1JY@YsiU_1fL2y*qo+6&vr@URm={{S=?$*aJ#Ow&B4q`>M@<7G}r4 zcg@M&bC!Kl^FaL-{Tv4$K6F6oP#(S2#2?1Y>;IlF?e%wd&Ukm>%k`H#kB%!?9=nUX z_~e8Ahg=^&W=O3EelFe_r@FR$d=#!b3->7xSATb-^KRMbD^Weyp09^39eDb!C&$eD_?4!E?$}o6NC9r* z@Rh1)c*&rI_J}Ky#htl2Ds?1 zR)hKOg73G?cf>**y2CdCAC__*g68%DaZh3pE{sQ(k5Wi?GndbqOFy{yAXjTdYFy9G zajObks|#Ff3S4UoTptv~tt)V?F93sU69Vp{fCB~(7VK^IM>y^ zUVP(cI=Tj@x`w32-I*HyRA<+c&aS1MU2}3=3v*nnb6gv9s&CC<-?gx+AYpYu^)&?v zYYXB&D2QKI5VxTq0TuqR!1YmqYYT6^BhdbWv`aBCr1)fr?_uIA@aOZv6`hgDb*~ra z+J*9asl0hpOSJTtaQH8CxCMV=AN&ap!NNGuHV5q$$#FwcVLI;>WEQLBSyE0hf=D`)rWP%U_{ z0koHS%vp;=COk^eqxG%r&nxB1Nq6yn1ue!_0&nX0Ed_Ccv(6_ZGW4FJ%GO5Q523P; zsT^L9!zWOw))jwHUFWraVw|D;y(ObD%vdt21^1))kF5Amq(#A_toZHq;5EG50uB2J32s=Sh!;uX zPbgALTj%xl?bW6zBd2%Yygog8b;FA6~Y() zT-v6B=KOA9*@#gB26x@!5^4moIkUeW&=S7uC+nTvy-3_YHXElKqWsJnXNuA|cMM~< zAKBl4ih5m(TKvL6kNVhl1f~x`I0N#>x%{3+?1m}}DI|iaz!_6AY;ckM z^G$3D)ZPn~uo%@vgD?>2F9OBz?t!Ae^T;2F;oYxSkNnI&_{AMLn#@7IREajMw1~A3 zUnIpqNI!RQzSPuKb^#POR?eO07=jQaLzWYlQNSKqOW#;!T$_W(t^9qYF!R1h&hZ3iGt=|st z<%C@Uie*H$|7wAp*Rf4xEnV7{g63=q;49EjmeUPm-4A;9=j!FP@clGleMj9MHkJPt zfG%xSL36f16=UTY!QNUB%Vsl{Ek)Z_!mBVIG0yNRY!#rn88>A5^Uyx~#0W~bB3WZA zgIt0(z~dk8k>LYgVTaZ!_}!;&xqZUN)xQF*miCc|nvt8Eo$143BNmsnN482W z?W=$}g4kFNk9yXOni-)S)+pyh8JBj5_LC9CW%$@>bu>!r;6g2^1)oBRYTFB3U+_HS zK!NLEfh%E2=ZKbKlX6h`=+PKeMZ8?fi1U_xm<3tIUmt_Vck~4 zRJtIQr}R0QdEN2NFQT{j+@BzK535_kMlnYN!-nAcyWgn6m<&?)T+a^bp2yy((Cq){cWcxb`~J=h%+wkS=nq;Cc&rgDlnMq#!B z&1w^(o(XYLYURWN+*q27XB2^vC4<>=6D>7)3Q}>}2L;V>qh?S^`ACc>HU)S(wGJo= z7{Nb#E7vt>%)x2=OXyiS&iGYQX=M)jEQ-wFmG}}HZ{$`~N&yBc<3MQzmYY1y11ysR zL9PJool^X(rL75Dk$ru;gN=O;7yc#8QbLa^870?Zwpl;JE4_wRLw0c;mk?}_07nnr zh)2`9YH3?|o-<|uZZ!vYh^V!+dUDC>muD_X;S;%$*)3fx3y&Nkmx(e73zh9csr?%0 z&EmChlbYG9TaR9B3tK@|TOB@xd$4Qiu*CIE6q*gsgsEx+l$Q>b-9|6e0^`~S7_Q{Kp`Bn*yBFIWy^y^>sv zXbE2^gK{uFn1CfZd`K=qDVMg|Ol8m)82@3(Of9W;v_6$xpJ># zB8v;$hZPXfL`CA;eZ&P&B2bpG##~UKvE>){oY;qJN=6s4p}~o}qGH=nvDY}UOK#f& zMO?as@4GEc?2Sr_(&OgLfSO|0(jE-kfFoNyVYAY`;Th%?pjp9b(v!=FjV$Zf-n=4A z7#pR+a!fQsWnX8NouQN}A1N-<%+!LddT;RXYeWrt_&P+kdo8Uv1?z;l=bBv?wjjt< z`lEv8BCq1ZnBUzrcX*`a8t#Kd9_DbEthO9u?G%N15~+OuqHvs~te?}D8u{LgA%myamI z4Wtpc^A>jH`W}zDQ&xjr$C8o!F7YnqqPe(QM`=g3HC$}kr5wvb<}bfe0V4)Hr-<`vAx2(bYn5*91V!(iOg zHwRK0h&Hk!+m!)J*H>n#)(EtTvkZ(jU&EMadezbf*yb~G%4V8P^}gt~Tz_7sbwfzl z8lLoJ4I4RNczD+LKF~g76}U~QWBBUY0CoI`)4wN#GJEyQ!PRJ9W}tG2;4O0vHwo~; z$Qs%O*kb9y2YBGZtp@ye0dAmZF8=NbD~spr#fukU%hFu&%x{zV;6pr!V?H054-OS* zadIG8sI=7` z1MY4)v~0w1?Si_u1cSU*|9>5Fn+6jub8ETo;8`uV-9@+7$24eCBmQdseZ*Rw_4T#7 zxpA*1`4~7K5zB3i1wT9%Y{*zXO0JkV8!a($I%^3Wvq3P&%?NPxZY2U(X9S-n(~qv* zZpvQ;c~$H)5`%RnwiDIeLDe0YEWX*=!)m(&?LCL}JL-?`9DUrKEqS{-{Fhna(AePg-R?S z7dgea6c`OtjQS}?Jt8Tm!I8{J8m5?AMtu;dbE%$%NsQV?)I_k(n#c{dt5S?6DMn*r zyT$CPR0emI1*wU|ZES&4y3s?7u+A8hz<5oHaWw%>44+xoSop5CP>CkHj&NX|;j{rx zs}#c^oGIZrtt>c(4NhCafpvz{2{;{y<)!fLse?sXjOS#hifK^vlHyXTJx{&7P>hy( zb*8$)I;*P>%3Vl#F&n2W*Xhj0X%~w$#$sizlR*Tq&Io#fpht?)Eyc(rj*%vZpK

        lHOrmP$ zK1GhO$rgQOggs784(qJRX8>nLN(JuB{uYVgahjgXEAUVr5FncN6Fk5S#TEE;4C2=SZ6p(f%7u4sG0lA7HMVJ zyh;SH&In!y!Ez!{Gxz0H6TCqLu+9kH1HsA^<86XaGWV5O96x7^qs-jjwor*oC*%}k z12ER57;96E)kLCX?(5`)UJC+sF0HmOiBY?enh4fe6Kw56M;lMh>*#n&2DaJ0sQ8M@47Mxu+ zIR7OaSZ6r5g5po4sATRxK`~nD^)uBK)>&N-L-|)yRx|fs zEz%f^mFdS3B7k*9a0&z`Qj9-RjN`ATKZeo;}JQ#;Z(5=6kCy^ zlC!t6QEcl}F&T;-y+(TyRde=^a%{D?=;M79yzk>pp~i-F*4SMElI}Iq2t>`+(;+`W zxzCz0MyNEWD<~)r+2gPWLkMJFE#HCgahjg=SJYy= zP9MU7b%s*_oPNZj=IQ;c(qgC-k~XX}?OUOJ3u&tv`Ym?aw~;oiGwot%5AqrVNM6a! z2VoK1?Zzz&+)p21ArV>39ZmsC05HO9+~qZf5rdMIkC0RLE)b}5W|)OZq?n_qabTS_ z&V69J$7_^(jZ$J$v+{c^NaYf@)Cwnt%~+y?bw)QHbV0B25TPmgc+f)jkd=o|=m~@a z>kQ{n;8b{xM+isB$15y2kJ#WmMmVs}aGnItRAN!`@u?PNF_Nb{ReT1DGe}X%$7et> zT0-?K)fLuRU1vjiCMm1=_)Lp5cKOQGVh$0&IwM#Nf<<0qf!BDRIMjT6k-3y06JLPG z-?3!{ch8@%nr{j5!8+qx4!&hxV=2L@Iry^3WG}STGDeUJ?&3K(j@}i71$(|ðob zHvXBHM^dwliK$WY?}@1u6TXjkB*x1!)rrPD)l|r*f2sU=1d8pCjlF^2 z0K|$^<28a%bL|ov`7}(fh-UrNksm4lzQS$5eEG#RnEPOj&MJTYbqig`m zx>RE=p(wfaIt$8L8mh_ce`oD5oeg}1R zZhULu5xMj}Y82Sm8|4>p9ZEHRN;Q5YE;WxnWWo7KqW)+F6T{?JB7=>c><^F~Pc@Db zmXbpsw@@9mvhYd!C!xT`j&cSlr&Enngrelnr!6R_Y*79o6xi5NTxqytNgPVf)=_0 zNNO^JTzN0gm2vdC2?_Rmk@}?LGve%<_jta%Fg?qdpB^P&o}XSZ;ioA1@}hJxOkkZU zzYOIU(~ZR>uI9`yrkgqQVhabx%^{w<;^@V%T;;{(xsqU=;VcKvGGbA)=Vj>?6OTk@ z&qp}{j@}hS0PBq4t#rE#x>D?I5`%Rn_8zLclB%m@(JRs3N26rXA*YIKpty<@l}vh- zjpACTikqOgA>CL7JX%eZKfuNb=KtDfU`B-*g`mJUcD6%hgh@APnvA0 z8f!aY!8*hG5?DLajU9xgWY{|`R68tG^aeEHeB~5p4{&y;8@mWc$+CA_aCX_?{FiWG zowd$>;Orw7HPhZ_kyeJyk3<0LjNoSw93%oY=RR09!7oGr>x|$y2#%&3hY3Q-zK>#Y z{GBb1@{=ZqEmR_#`Q0hT8DN}FH%_G+Cx}GJ!%xczeF_BXTsmQ45~KDXY9d%?O;oK* zmJ#2@aCI@x5u2Ke$9IWDa&<9xxN{abWgu1WB6c`fXN+~gSi6f+vy0g6m8`tBg|8;g zsQZ9uvbux=>kQ{o;56)F)F&JzGjC|Ysc(bRh;U$?;WPnGV`5RV^TrlsF`lnIG|Z7o#JAs+oH-u$1I5)X_3t0DXjK?l^i= z2@Cdou~K}wu6udb-rbjFWci|G?OC`Hc$%dV5uY;Y;S-ApZ0xGJP|fifJxN&2*mKzO z!2hbVr-cDLXL!DhqqjGqz{ZZ!4=DJ~zTAuZYKdyL-WQ+6ALl`nhkwRoyodcoCyw5H zQiqLQ{brwCrd}y@3kku-E>whS-b&R}vh-VdbEEbtl6`;56np=96-gt@CYvB-cAgra2Kt1KuX8RwLO zRkH5O(cZIIzei-<_`Psvif$-gMT$!1eU*(Oeo)+*;x$mbI>Ts2qH6YiwH#s1Ec(g_ z!;hBpEeX~cPAlLT8OHU5qh{a+Af~crm-oi6uNtd0VZl1XN(NTP45K|^DOq?&3srjy zmDspb2nW^~PFLWhXBcUOqh#Xg7MwI293SDpI>X5VPJmd{Y&>9*R)$SCB7k*9kPU(x zh(OKAZ>X9ehX`Pu5#)iOPlnN(Ae5}U4;II{Y;lxXd2b7q$ZYyK#kdU^{WFZ4GmJta zQ8M%Xazft>0(CAGTA0MBEutoZb=E{f!FET6F*w5*NNj3$euo8Vu*4l`fl~(3Fk*yt z#&|avOEQcR1gK=_B^JIB7AnzXqX`Gr8P0vcxhKOYCmbb9zsG`8Zi6$HaA2L`JPe!% ziABlOAG9co@f>ujI1!5DNm0qx$3rn%>NSb#3hS({Q=mMVl+}!VvPBwWu`>O5ln7v* z5zGL=^bBKKhVcY(s9F1Tby-2yJ`HCUu!Tlu?N3zA`ZTe^I%Ay&);Sr*ECN+C_c@Wt zVQ7|Rya0M8&)jkJK2KP%F=4&qqEEG~1=ea}QZo0|0C<6=5)t>uKOkjTXUdzQyfMRA zPvUCkzEQ4g>n$8$TEg>Y9K9bB4y-erPk{3=v8b8*$LO5pY|Mmb?khL}j^1rV0PBq4 zbKA_lQfvo_!8#NB64l*F)m1Y0ooMeBtluLt_ph8PehbBKNKwh$zp+u=?No6e6u-|f z_K>KWxqmN5*dB|%GQxhKCWm#_jLU#=so!YmH|i6KlDS{%H*fYd1c5r2>RXt^sJ)z;2-aB>>0opF zjjQ}d6Jk>{cee%UDv8^~0;hCiGh&2w#&|s#ll;at1gK>0Nfy3qEL5V&S`ZGbGn{t7 zY2!Cq5ss3%x3S=~vcYLjIIzxeQh?KmSd`4YlSNsKXRlMmbSS2gqLR6%K`~nD)rIN` z>#VMRDEmlR&D?z!X^h3n^dmq7u+9i_K+w}~^za+qh(pcXd#cL{GWQ-hvyv?|GIQ@% zH7kA*kl%5Gb;eo%)_#7YFM+C=dp}?)$ziCkWxN1-InUg2^cE5pY)n}1nwk5Zz#2+S zO6EQk03nu2L}c!Fkut0^<-4I=;x|T+xSF|_$aQUmg#%3Q^Sl{H?`Xn-b%t{faLS2A z&D_h;IqTS%3D4Zua{?T__YwiDGlB>FcK6&X#U3OvSZ8A6P~C^Ax=QB$Fxq=P>-UJv zeY{h}N1!;76qU?wFn&2%WfOSUj zJ_z3P8!HJy$=u(=;<$+|jxuv!X`vFC&MK!En}D&wZ>;khYl%e3+&9Pxy$%HGTv}^k z5~FrAH4&_{Ci)a?+x*5>zp;hb)XaUG1!=3q-C}`L2GVE5256E;lMh>`5riX{Kjs=Q8M>E7M$HSIC}{P))~$L;Or+BC3D|zQ5NI*C#Q

        PeFASPz?l^iA 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

        Qg@^8rYBDKVz2-eEj|? zp1G(kB=qC=j~}nI714>d;5w6_vz<>(BqG_5-rGSEQ_$rlTJi&ePirNfcJzKhB%v*c zqzZb4{XHao>r=ZBN$d%sZz1Wr7A1N@s0*ICr9I<+LgisFB9hP+Tv84sWfMKj z$)Ie+;||CJPX_gH!qyjTy?ts=Ldc#7>J7$6W@SWdje>bpO_yXFJ=r8gSOyeCPK`3 zqJ%m5Gu}dO>>`s0E82pyP6O){!pfZZnZmNt_x{rfE82py&IRjipE{EeGbep!gV;Rj zGZXi_%E-cilRopDkS_-LLZ3RHkTWNI7W$FT=a4UPLcS8@%YAAdA!knZEcYYNh*z3t)qb>MgZw2dSpSqC{GbedA`^=L(8(9hTB+oV{)O$g_ z+o$dz)XWK<-B{?ekz4sEcy@3k{K7~GcC8M3RdDGSH(wDZq<6p-FK~78!npWhR$+WT zUn~gMLEl78)`tm63EHK!U=sqH43}#y54D4$wuTAXH6r5Ea1oLa)B8)N_r1hUr}`BS z1YOO(0KYGr_J^s-L7vHJ1GjfmcFy|@eOqgI?bHtRYT~Ej5I>kd?qsYtl$csGW zJ&L?-kG#o4x;*BnJ>;1bq9!38c3^2JpM{AL?V=umUaTU2jH)B%F4xmM_=}X`1&<{! zp7+>Bu>{YVLY;~B$Z}SWvOH&%sI!Xp&dT$U)hRO69$AHl^a5!FvnJ2v9qK$Hz=Y1V z7-|y5Gigjs-h0fbHSl24b?TyDm?eKi>**s}kLUU$>bkiGx0|yrSJMDAO{WeN-9Esi zkvVzOs7b1II6LxCUsF`3ovg;D_iu@vzLa#s17keC5AYjn+V`L)**ueel)5(rGfPQN z9%dND3=Yg8?GiUG*FYX}EJglgj~vNEPNm36_Q(l5yQJkKAVE*urymkUBeH?`$6rd7L7T*dq_~kf(t( zf_ai>@;7yUHo%0=wae7x0?*_wHM#YeQM+NglzgC%=rx|}5U;sIxx6+@i8g0lu15iA zIy1{qbSW>pc{Kx2pWm-ild@jR?(-54^%_OVcCtP;y}v>1bgC+NV2nql0KcD@_SLCL zD9vy{}}VSE%*+Z(W-2J2NxBoEn;A{*Ev>+z7yDDne)WGoN)2}OR$GigOl zKI56RhlvsGM6X>{@~NIWZFulB%8+W!i;ng^>cDgM4RzMV9@*K-k;!xR19jHT-dPq8 z*_R@F*&}m#$iYAw!5qLd89|*74KSf|Z8S9*$upTsO(s2N)Fxf}Kb-b)SNXaWdh_024abo}ng1cqV12NvR0_ zsFjScTT0sKBl;ZAwM<>Vs=))_;AnH!<$5ImO}i&Xn%#RPl8r!HbMls_ChkbfQX=zE zDn-2!X(KDe^j?kF=}SpXJTQ{GdVt?l(>{Wlcz7m0N?jX*nWZF>hk1`;>PH4FCGGVH z*5x6aQRD~q$XFh-B}IO0kNl8_Y)z4IJd^g+B#~#*2_{CgJ4V_iWt!gc4m|jOC_`s! zUS!($D4pjln>y=ikNn=s@h#6;U+S!vy|Y{%awtU(vPTZ!Ax8me1akz>WE^!qI>3a^ zwaL_E0?%YFHJSC8QJbMnI!jgZl|G`=c&_uP>&3h|>vAm&K+~D|LX^3bl#CMEv`z6l zGumC}eKtyH&pe%jr}cUN3ZO>tUWyWu+xwld%{5Kj)VmZVB=}hj(S5(l!&RcViYzWm z$Cc;ds#9F39j*!w=cTxsJd<~*Nd(WNE=-Jo_@ac=%nZN&8p}~s0CJ)kr$!X{u066o z57~?&Kd?u}@{k|X4z&m{p~KgTI{yseOvZJX$@zBK<@%HdYEMCl0Hww!C;R2pY<>J% z^RQj0rmq6CalVdB3(UqvW(cz=?Y9BmmzX9!sP}9(J67txyYX=SDXtHTo2%n`@o>W_ zZipRj5Dzz+;zsgJCQy^HJd^1#F|u)reP&DwK(039G>;-@+aqW4kV`0Xp*?aw54nPN zC@;W-4&Qp}d=0|MX5%UzXgdXM0Vp6F*XiT8k%v7`HJu5}#w|MXWMDRKH$!-Z(q0Vk zzSA_hO}*b>vtys``x*}?M4K!20~WVY$KB)M3RBz@(ac(G;DV#sHJs{vhT@9wOiEId z;yja=U}9ur>1f-vu~Y!^pcyBLBFot$%kq#FDDpLXq{2h0v_o$Mn9#6Pr_MtWPBt5> z@IVn1Wi*CTj~hkU|k&YU2hEmH8Y zfu&t3Mv+h3BMbA8B`LBv&*VjF@&eC9f{79Baz4AF|GeJuvOM^kl%aypk{7Sr_sGq2 z_BM4^%^q3R%2Ao;ERs44w|C~@A?s44&mI}YLpB7`2xbGG$p_SV;{X#n*IH1MraY5Y z)a0|rjM}F@yQ2T1KB6DvAOqplLd1QS`S!Gu8cd9ofYfQ1suz z)B3#c0jLqYY#+N}+%Zl1QSZHd%trG__uZ3+8%A-1S=<#JH;{)LLvf?*a6j^JlPGRH z&ty6^nZh%f2NNS8vwgN3+spu@>p2q2B^0^P9yyzQ(J%0GPYAFXf0g5Qbs6Ls^}T9zuZIW zE%lV<$&00B(o*TLyk0sW?U43JyQG=&ZRx&rSDGZ}$Xn#T@-K3|VC8brEHPW`B@Pxx zi{r$J;uLY3I76Hx&J&l2%fuDpI&p)zRXii!5+8^?;JCNcUm7G0lSW9RrE$_^X}Yu+ zG|Qy*AlU_)1JW_+l5`t1_oW<=^p^+8Kg#3e@$v+Dl003WDbJSYf&Lfyfc%?$P(Cc5 zkpGlV$!Fvjv)*diPuizwZC9>3Rb6Kbp}>vVRa5x=VA3X ztp0)31z25#)g@S6hSe2VU4_*(SY3zJ4OrcT)h$@vhSeQd-G$XXaiDk~mJeY05SEW% znI+v6yGpmjZqjYByL3m)mhOr_NcY4X=|0BlftV{j6njdK#9mSs#;vQ=N6HfW;?_^< zhEeP;4Un>>fzl5c&m3v6)I%B~_#>1pu(r_R~0P&;LR~jkxlSTpY6A+_;7z4yu zAjSbP9*7A*Oax*Q5R-wJ0>o5ljyMgd=|If@Y9>&#fSL`|9BG(1R~jzPlSYU?OFxS9 zrIF$Scv=Wgi{NQ7JS~BzrSOyoPs^lf(sJBZNbALw@VE*dSHt5Pcw7sQ>)>&{G*{Xn z&674tKTDgW`O;=-fwTo4x5DE#c-#(;JK%9AJnn+W-SD^v9`{P!#b0pSC#{tB!}9@n z{uQ_1;Qb)HAA!XWq7{=?^ogd8oXbJ_Z#qj6W(vZ`)zo?1Mhd?{T{sE zhxZ3kj`$F_M_|d4&q!V6vr;$toYY-DFJ;SrOFzhc#T?Lmu z?=5c%?;~#x?<=pC`^j6v`^#Iy2gpM!4a9Ab{F^jb?k5hB`-?;60pc)upg3F}B#w{= zi$BU2#F6q4ag;n%{7D`rj+TduW8@LySoueBoV;5a58DayCUK&C4-3nEX)BRGv{jPwwkkCin9!m-~BG$h*Q<%Dcl?$$P?A%k#^xk@tqLm2ZZvlW&Es zmv4t{kbeo^DDMm3B<~O3EFTEpBL5n`RUTex8*ba>3E~cUqPSC@B<_+Yi@W71;vRXb zxL4kdwP=sLPd+5>$L)Z;Px@7!CjKTL5D&`d#6$9Q@pouFEI*R|!0m`UQ#>lq5|7EV z#pCiE@q|25{8L^io|NZ`f64R2Q}Pw@v^-xt15Ib;1>!lp_LA^I)?Y6O!n3ut0;h6P z!jdmTT#p_JLaz<*HQ&2tt4$6!~sX3G5OHtmx2=YnwzcHJq)7~p|!la!)At!+@jE{hw(Ch=?C<_X>AqgMI@ zzk}{4y^H<~zC-~(cNM>v^}D)FLTmkgA>BsNOqoAT!_!r&RS&IMQ>1^PZ+kp7YgT_d zEQ~&--wCZ+wMLB^qF5s|w0c$jnO08=!lOqnAtC3Rv7f|+JzP+9@}ZfHW{vuFvHW_| zbqg;FLdl|q1nso}7X$&dnEvMW>VB z_R0~A#)4D%HrhSS4k1;wd`(JDO!La9UEWViZI>3`QLKw+(!~m2ht;UqvQbi-wAA#} zwi%*P#fVKaG82+gTUM(Y>S^gq?btChB`Kpz%ND+t%~Dg7(_1!bio2oJD_5&oxtb?5 zv}()NNhvMsr>19o6jnp8ciL2|oRFL>iSm_E%D5jBpAnDyssD!sov9IZ9y}-fA9~KO8ue09t(X2*wVE};(7*Q+ zlH%Jn%FIA=RrUW1#T(J*>b`QXRCU+ZIv9s)$lj7KXD#_sh(IovX;BPIRhc)m1*=Tf z6Zl>`+BfxMCF8lm`g0{_hyBmJFb6FurA=~X0;*jyi0Scd6Vo%|+jOYhUMTKb(*MiB zmHI4gd!qD%SvM+3)l1ZM&S0d8?!M}Y$sx6>WNfR}^hSffhi?livAdSz4rpnoNxyKY z@!`_d#fB4JUjJWV`pWN0EUN9;cXIpq^!B>U zHM{4LL1Wt0d}ixA0tCkC%MCs>d!jIAPgZl#{wCv&wsB@@J7WmG7UB9d#`VlwF#<9q zE+w(EkmCvt5kw)Y6s!+w*2^{PLT*8j>KAtf9gc9N!~{K4!vJXiwSYk!(hwWsai|YO zC=kK-B7#1N(LuEgP+DSq0tFQV&F>nhVjCO=0+h8|s9!udcxVmR;aaX!wOr4PB;qt& zRUy|EtoJ4wz{48wxg;Epy(S3l>lY6S0-zQ;G}8}5A@2e5hX#2WjZB6ANsKid74O5$pG@L~s<5UtNk89@FQ1@hAhI!U_ zSN-B4Pu+`fHHZ%SFvg`vU+d+}7|qK+aMZ+b)G0F~ojNKGM<+B#3v+PDsw4={YXSYI zsw)PF4-G`e_zsD2TG|^h7}f{uPYw264;+>QrVn6H@cxLP2GPMXR|O%qc5#>Rj9gpKU}U7WWtx;vglL#VP@dK>_4?y*0+_7s zLi^$&Aw}K^dgh&=7ViXa#hsmzx(6*-aqSW_;`H%}YnK_H7LR$4|FINgOpA8#c2@IN zYcLLXDx*GbU)<$t@s8`6JpnGX42(-l{4x_gVescP{6!7_N)W#U=uQhKu8XoAdTm;1{yU2huT$Hp4t8&hUkih@s7k{8Zg!Ji9$XL z6Jp=5)3|BVhH>c~;t&z6PWVr0nmH2TDsV-F{a&nHcqSC=_;U%L#<)8sX0%UD(ATq0 zLM|5EkoU93V`65NgHfTkVq7(1w0VzAZ4~2b665+jCa8$;MU=iZ#ieJ&nWVm^&6+f5 zTo2xtfe(L0gq_h)Qs<*MUsS_}(NVtl;^;RRC}d5C zqw5eJ(wpg9+oY6)I8-z_F8qf&m{ow;4bAL6;|oH)Zre@fh@u$s%luYfj ze-f})V0TNiD?-Kri?{h&Q|P{}y|#%V!(N)I&0Is#2spT-8BJ%1(o@qi1XGL%o4c?n zBD@@lFln2LUwHm&gr|t`uypeVjhi(V1Z*loNDD&{S*8p!ZJD~Sk#%Co5)uHr3j6>=Z}-la!HR z4Pg3E_k6#!uYOdMFhS^~L1!`0r1Ur~0*TrdWk?SJ?vW;a1Y?-qKB;Yf`o009Ea)sE ztg3A$8&V|(ze?ROu5NRD>XEPYDl;hB+LVymIVCPRRofSX4ARl?*H!oTM}8L9Y0@Ol zNZ`1bsAf@cxd&$WDW0-FK2j_^Hbm*q5 zY8CEl^6~r4V&j^8sFC5lwk~6{buxAAq>lpDXfs=u`A5hX+vt4~pKQY*5A*9T35j1~=9pCJzU20Cjp{UtOUUflQQIJM2}ft9 zlSwH!AD%%+ye1;i3p^pWn32-5Du1NRDKZ(xy*1;ejLVeFj?|x)L47on!?ldM4363+ z$G1zTfsKHyzPd$(Kmz+8e9-|zbs%d?=?o33DVqAAh#r8%P zcx_4fN%x$FEXI2*Z6iZ21AL!=@6jGHn!+G^G>{8%btob{Z(ZuFc^;C($kldZrt9N%weM1{rp>VRLxy1Ly{2zz zHL9Dt&p|!0P{Agpw2Mo?i5EjQ$*m&7d*Q~LGwk_(FHa;1^o+43>Z4@tD_Yq%MVApD zqeVlz>7l4#fQkrT`i$YeWQy7rxV&l($?`gtP#t8(GXbC5;Vq5-Xin2PpRtP~4fb?X zLK$-%@MEe$n7&{_jMUY)9J;1eh3XkPR|o%jPD(Jk$abdx+FM$)^WVb3T-`xbSSH^5*Qjn57a`x+kW-uj+&thyhB8)}DMkrk zj;A)Ge%9T$^Z4yfW`F&1lx|P)_J*`i^UYycYO~+@jmQEL!zZnaWoCMOJKmDHQ0vqs zHeQ(>30l0;2MCm(S>XNK#5$yi;$DC1n{I zoPA87Ny%a6<{-eA>+l4-obcsqVA>Z&WkjGwk-e!q4_7_QKwT_3ZX{$rcnL|mQ+R}J#64l{np679eJNg0-T zBbe8RscQ*2`y00F!^|HrTx-z*O_z&mm(jw}yNSp_>rBpe$k|G?u)kxwH7qxKq;?^+ zfquVZJ4(MCEsowDL;+f73igEYe#x}FGy1S2bm-#*0eTercZQT3lpYQ#)|srUkaamsy+~v+zi)flqUxeWm9Z>bBXZC> zlXDkxZilHii5%uPZf{%U+~ml)N93S&CP(npRUZ;9?C;z@v`{l?v3N zx1vQ-IV!iTMI1AX3ekwxnZ`Gvv7$#UPXsc*eOu9@ue?Q-5wc1|4q9h&-h!M^k6MMu zVSfKM)FP(}M^1Gj2dy(X9>}Rlv@pMcThqd9r6o-D0t7KHt?wRhz|DmaNlE>75pA<13a@?TWHqk z3(XoauioReHYQrpI@9_gv^MvsO^HzUH*uRo7E>JNHMQgmM32-jM~kEPBO(iJfn?$H zCZlry0uAvdO&j#O8Aop# zk%QKmoX(JwNwlz)dnN{FmzFdBmHTd80gm3Ui2}6F6nx|1Rqpv@-x4yk&d9o=yWf-U zGL`%Hi1%)7+yg52ZcZ6hh|O zh)}k2cXs4PO&{Y8yh& z)aHp;1P_bNbF*6GmV1?-&ZV9{ihm}w+9 zXq^S;ztGmjt9JIPnM4~~m3Og7>P+QkTE!V@^9@ml)|t9&sO#ocvxqdN9`9yRmSxqW zPv{?r9JJ2l^nsjSUNx7oBI2Q@Z9dlZ0hgaaHH}^TX5EXVC@sG_9Db=?cFEb zti5|#H5jW`euwyqLkT;IYb0oW6uLMTQAJviCI9zpe?wVt}Y>BnEE=;qGgFy zi@qJNAX3m4T*`V#SsSjdCQ_K%daXsuYL1i*L<-u1OW6u3n~4s#uHI~=HI|rdgcohW zd3S?%C*fsl>YY5^J%kr+!FhiJ?}2c2AE9RI=>u5Y{v`GEK8p&Y3OVS6`~=94g{w!x z)x(6Jsilw6X?XX~r$6w$@j(dR63&QPhRtip^m z`G+V&TX1F9q3mk7dYQ;#YUryLRhO+=^htYzNI_e0Dfc1eZn%1zNMY*dyA~<8IZ_@F zDQF8WB`BhurYP>6JWC|gbGI(g%H|;_pvBgpC+tq z&HS{57BzEzX;6%?qb)f53t)dfLM;)Y7AG3mdinVXvQ(g6E`j?eNxfYB@!CogZDUt1yRtr1*rb(U0%X*i{LhDRc6Ucf$Qf*9RF%|av7FCTcs*H-JDUpNLnVe4`=c7oq z1(Cy4*&kWtwBX43l*mErOinAv`J8BBEA7uM)J)pM69s6UDQF7?2}A)~b0<7rK|7)V ztuqBFP>>v{enCVq)ps%$$E(`nNWW?Fg+-N7gQq%`@ik<86{%)Ks%bD7N?Eo+MtmEQ)Y( zMd$7q;v^tW;D}O%J^_e!rPpNMSIFr4IvvPUIkH@(PqjcJ7sKVp49);DItB~D zV1BYOH`$oYdB~Oee0f{$SIFqNt^(H;$;L8HRIc1tL>7m^ zWtMya>9e$Q$I-i*(}Mh~v{p1m<-Rpkx&Oo8#Hipm?((zZeOKdkMZK@8_>WZO@h7*8zNFXkYjT;k19utr~^^;8&x>y0TKv&=%8>oK~;e|LIYm!vcW1A24FLS zh5$#en}+~0x)9U^p&EW8o)bD0A~c#1ssR#(gwP;07+*Z0M>!$L=m^yZp}KyfHYapM zB2?EzsCMy$9^-@{qa)-2p@y8zXN}j9+dYM2Npu=o2(Vozkt0J!hujFrK8}12$SJx~ zIEf(pWaRN0{w5k1y~!LIGCJf`AgB0^#vI(`XLDmJ0Z#$=Dcp>}A=ntNr(>e_9P}lJ-tEYtll5`yn0gm`s4BNFKqYJ@65E|e&`f)-@8^|;L#&ixYZCNt`9@?^|2`F z{Iz`WA)_1oPl3F_Z>;0s(w4PBY+37M8e)mu6fOJ?z;E*#TR6P5Wo^U8u!(F8V$0g% zKx5}$r?H&8%i0s#vVI1QlYZkEry*}yC&6Po;UTuHV`$k$TFhJ4=XAZs(R-Q?4&+}Q z9GTX6&^pUGNn6%g1mbft6(indU5FO(3J@>(jf)&q-m)$M^#I?pE?O9X%>fz$9KBb0 z2q2>i!EF$_8aZNE|@qb9~X{p4^Th<*Z zVM4KZEsv2Dp;DX>WORheflwLFM%uEn@HA869#3AeZOJ(w0?TMi#49MUD&^ z9r6P}zAwe7#KEO4>pp;owya8ceTdAHh%M{EXbGqwP$k8v%n3+aRuvP0$_@myXbDsY zfk#pdHzy!%S&x_qxE%=8h?YPt5U9z~r7f!_5KVb62H)U=4;kIyKL+G_DMlR*E^S%$ zQbO;t>c}+2men9ycpu;sQ;dcjUfQw}Q}C&OvN4D)tDyspq`yuh4Ih7X(~rOI1BE>t zU;4)pdw}*m$@hpqKikh^5BXPPA4dHes0UMw0~}a>lz%WK^eF#;g#-8;r8@(T-b0)U zWXY)<0hPm?hx{1-Fh<}68G)hn2Ix?F1N0{K*pzXI(vN0T1ipLRey6Aju$pj}8Y&T&BbvHb;+P3J7w zQa1h0!wgySFy8=`YbnMRPDOrXe+>kVl28w#H?(m-_e$}UZgNVHC8rb@Xkx?!3?;y- z4C!%wOdyhxf)+U)*iL^(fE7KEC8tsrR7wYoQk;tPsJ^s?N+|~_EwISDaQW~eM~5sqdIr#64;Zfnj8`}Z`SJVf^0I-)@2{cd zELljz22B$R5< z3j2Lf>Jc!yb4v0Jp&p?0JBgCGA=Di$S4fNbhR`)yb>iqP__2GP^n?ZdL zk81#ryczUiG-v~XHXva1NG9b~3*CeqEH zsTOdyi_GAtkR?Z*1Jqd@Rl4yrOGXv%{pWI2$daQj2I|6qF`olVH+>cYICRrzK3@0K zk%bXAeU?N6z7pWe1IAJgF5U21ZUSHG0KO_3@O1!R8!&<#T)Nq_)&w4O0AC*s_$GjF z}+L#fapDL6?yz3Iep%7)JyV?fxd6arqRM4{(Iy6qHo_C1btoT<`*~f&)x6g22 z^kYKJpH83}?c#4FF^xpKQ878M0q1Lo^Ydllp?BHlh+6wUWi8ZmOhHC3(_L@UAd{CR z$hJ=Du8t(goe<-R-Oa7>8>v6uDtl;jaY{p@ebcj z(lGcg9TXm$bXTZ>B+UKQ`}Y35Y+Yz277^B6O@q|~gGC$PjW0~)PQpnh4OX{wSNC++ zzvFwR1`F+m%)#tG>8|(EUH=XC6gDJ*S&E0!n|`-Qusbx)m*vwXv45%({BJ7KpUf=e zSwApE8y-&f#KXymF5n_A^u`4fPI-z`H|%0SD*nAN^!mtpr9^x@A5lLaSOB~OfzB@C zds3MfeDkRie>h?={%$uIg+&CAcE&`H&2&Of^9-W6{fJs*oR}TW0qNa19J3=)nfV9#$=u9OL&pJ zz~scV{Fqw9uF33i#l>I(<3=i*31ZzToC^$-6$>weDGwN|WQFtWR7i4phV!V-mo*qP zb8uix`aNoF-RKe zG&RqUHN=io6=b@UV4W}A4hJB$4T3H|<8b<8sYVXZwAwNP9J6tzlXpc%05Va z7vC3Mv^<+k%Cqxjc^BFK=nsVfqw)hxkri-=lOKtnNvS4oVdVNSB1!rabW952d0=V` zPwU{MRM^Gnp6L|ee-?oMhdovtz$P&3itysf{BcIf%;x@cz6UI5bU3i&(r_=Tw)-D!5+B3g@5gA2u!`V&*~HUV8E zELftm-h@_6d<(Z#h3+Y<`TTRq8hlToAqnj%F;GE(W9>BQo)YE|o(okyYiMNR?5s?C z3e&m+TCHNeL4*y&0QR^4hZ!`XRf=d)t|IJc{X20+mV1msiITi59KcT*2%6;N97&#v zB;Sx~tV=c4iX<t>)QJjUOdUkXzxfhxwWsO_r=oW7c(u z_2yKDPA`B@Jv2hphe+7LJNy`HYrsT9COi=FJI&bP?Zy^6CIpcP%ivCum?ph2aku9S z+BvTUAgn`IuLP#oDC}-CaT;UmRr4I6UXzK}U8zB;N*Q^-MEbLfetyw5o|G|vcK{Ov zDL~Zaw*|Wh1Nydr%|)aFYW=W3^F~b_l3C2&6R_JAg=wTaVFNaHLFzZO+%|;@;F}S6 zj32!gTF?JU8rShg<{Y*67L{b<)3}Dj+eXPZ#|euBNpK zm*li0)$uEE0Q{FB=yFNUv0Q$G3t8h>rw`?q!7dkaq3S`+FVxOPM%h8#dR>5LPIE)XWh;nl&^7@lfXJwI`lZ^O=E z-HRNEJg8c@;0`3Z5@+9~+CrKd!{pe^gXKHK@`%~ewD5!nB5WxZo_ApxJVFd*maxElj;9asD;ZD*OiE zIQ7#je8Cha^SVNv@pXk){LHjBOcB5jhzH78Oarv`MJt`;m=z_Ob=ew2p)d|KWtyIa>IiXNCV|>TCpuqK&NZXBS2a1JVr? z{#U5}DACNKeFmi2mC?l0+0-CICq{OQ&KPK+4`Yd&vtpTH+0FQcwuNy_a{|$%#04Pi zC!&=OFYrq=yi=I>$q;mS$vK9%1%~&JRO4o4f||w{&4ooS3msHj?oMpJykD^~E%G|Vj3Q;joSPOOW6pb`$VX<5Nc;T6gX8H(w!0-Y^4 z2-!+mhtXkFLX1~IrPUn?;068FgcS?BD-`x1QHV<*T}SAlv<3~{So-o4yi9n6zFfyl zZ988JBc+7=tq+@TBToMDFn7gU13h5ZwuP@TS_!y@o^3~at2n&affu}syYMn0fnMH6%%sO; zW?Yh@`-z4b6m4IGeSJxM)ug_@!An!DOcN>ezR^IAhf}~*t~`o<;38aq8-`>3@YcdL zT*tNV*fo=ja5B>IsD*qqBZPPASUOY*@C83d;D?9e2fR$EOynMH%VA$v ziLZLp*L9{T-9blCk}#Qo#c{oQzJ8gZ&ZWsy)l zULG)w_`EO8N!h-paT6m~TJS!xpNH1~DY>gb5j(FBiwgh|&PSLfi#OSx6L1af@o48E zt$~*bNwhTqFHOvB#=Q~MtI52YRPFe9lR<+S)M5rE8n^};2HH7|I(V7zByFvSmvoD% zPs|>&Y%!0a8ODz@(U2%rP76Lnw;89J=?SKs$b=6fSXo4qZ@1wA46neU-8TsqbjL}? zi^!ehNwo29`0+BKG3`c*jb?Qnu2MQJ}EqXni8K?{$lzxBkrq+-iF7D zKRHUp1{S_-+Q4uDasDU4H1Cz(Gz=`e);xTTZ_u~~n-*wCA_kxsqW(-+RcsXLR4oB& zuz40IJc`fbWkM6$+A?e=7KB#BESBq%GB`diEeVqr7Id;U!ZJo)#56*D$%|5rux5}K ze{X~(fV?Q(2s4+wDANd|MP8I`gzO_P$~D4lATQ`=6dIwPrYGc+2#rue(Ubn<1O*X2 z89+`@dC-%O$O%dZdNPolU?Zj{p&zKqXg6_OAnu-fhgybQY1FuQRRs)FKGXxv^TF(Nmi$Z3ggLcsxmUWTBP z@fG?a{&~ECX_jU*P2-;fD|{90xRcKwG?u}>8UJhDb);k|d=4j+xKduh|B=D{%VtQz zE##jX?a`Z)!am%v1z+$@CoroG+3mEaX-{4Q0PP7mElE%Q1qbNK>$C%SLC*13>?QOh zJ5H+^J&2rl%3P^l1;Q)rUlcB)oKr|;PX%+pMaCzl<|Ev@n4vV zEsIg`yp9y-rxjsq4}pG;tvJFCL&$n z#1fIW(TE}iK!`}5Ovt9{$(J>3s-6PkFg5|9gTr@-dU)JzLY&Ea_^zGi|0~2{&rTuk zX6IH4aT`vcJ2ayX@xS5365{`$5g`T;BJ!S0$R@-+WDT1T|Ccz7O+e`2u#l)n&OJU~ zk!kGBYfo7z{1!#jguP^qy4J^by@^IR;%qbL%ZC8!BP-beeIRSt0DVX_!pjnSwn?H& zwpUuf77>l`l4PUN9~#ueJo^WrkuJDoF(}D`I|vRC@_`U^p(5v4a9_oO+g7Z$gV7k@ zE-l!$*d=o)w1VyUib$T*s-8|f6NeE89n!>AX+af{9zh&*;26w7XYODmaqwoExN2W~ zkA@aHGlq$A#NC?_D>Pe%1mt+46M_sqbf)PZ8kh;p*+kiyO_EQNHEfc63egA!C=`MS zLQ{!OIL_fb5NSOP8tCM7*_jQY8M1~Ap_$OYG)9o&a27dF^3#mB(~Mk^U<+|IzFV3(7V-aFoKK z*~gc85+7tdr7DH3NO7}+oE7Ox;fpwHj%uYyCp#5eKbFEI*v*t|RXs(t>&tM#`#$z= zcDkIn{&(76alL}L{p!_$wu@-U`Hj}y7CUp?h~4Kz!!i-}pcO#^JXH4KB$$h2TcLAUk>dNw zrF?dYc@~$xAeU%g*lzMJ^>u(aCbOQLmSi{i3J$>OAOxNDPI9!sLA_B|OGNm=1!< z5@Q^t{SzEg+T^q(v`@nU*#1n};srSe?Qu`ypChIj69n^LnBEzP-~>vEy!#4&7A$cF zpL1uS@uzCrZlrspN8*E3Drupgr#c5G+nH1%B&Vx1zF5X$#gqXr*VM|wcp^^X< zu)KoHba+S)N-{jx;Q)TFLC|?i&M`bwF+B6rjJavXY%xMNnCdNv;B31Q`k0TabOGgMm;2eXK_(c&TG&ej#!TDsx#;CBcllwPxh!}S^M4>H{ z))KLB7+fTl`D&h}6eo@}hdcZ%eK*1M=yM19s5*h^-XUDDkz%y}hE_UCEHga1~q~F^N8*C>1#m(bB(rcg=P znkErc5}*Q>_u?`g9@2x749^2_06+Ib(BUEH7@ma~o=s`S#x!HS7@-H5YGsJvdb<(Y z#z*L3X#BMi5>Mg7lc)-um_}#|?QT^xVuSz$&KiN)8Zkl}!y^>jBuyf6tCLP5#$5~% zoj*E!1-F{!&vpvoCe7i#zRczi)icc>rdv(8VDpDDegv&_fXHchfMQ)6JXIB!tDMW_ z`oyE;zoit#DzR~;6qiz13U@Qh#r!SS^_fuF>``*Ex+(ZfP;6WrbP8OqPo1oG3#%O- zrEPAfE}41RN>NRv>5z4!v z!lGR^QE8W#o!zc$=eDLXYJix#T&11N9}o!lCR+01ABnb6tl;F#Eu5+LmQ}16m7Sc` z63!CromF?TY#=P_*<03evh>1|1@j3fl_!PsqzDx;*HVRw-$~^eq4IPwqt+}Dldenm zh!Jf{N3^Mv>z9S=7l^stoOQWcMp%n4lgcuovcyScEmT;vSKB7#v$W$Yoy@ligiY4G*l6FQ^-j+A z3TM0REq7WmwmUgHB%B?zcXq(Z@~E&pVsCla$?^m&Sul?|sr(|GpNdcsbM3rPIpd^q zU8r0sX4Ed(E+x;=5xwZ-I?fx~pF;DUQdkZ1*{pDHguIXAdUPq7j1x8<6C(U(hV*9$m8niD z^9A%A5SEsbSxz>~gv}D4?NYMH$?_9n8ML=t4=th za;*v1Rfu`y8yqrcU9QRz)}nh=lSAFBoGeG6U1;*g3l(>=Whv2|tZE6Xgk&39okQO1 zaXq?}G{gx@?#Ckh=7#irLdD~xk|Lm=1Yv0@Y2;+{PhrzEIbtd4KqHvuWZ6UcTBcR$~@ZfH=WG83xs#9c~M~BqdX^P zy@j(vd&~b?G2U}>_K|Sb&)(UGPL?Bt*OD3JADtU*F=xis~tA*}blVg>?Kfoou@a zPF*9jaVfQYJ2D$rghKeffPF8*`>K#iU*WyCoE__^@19O}gM{4x*={kl>*r)QO4tpz zvm5GUH$m8qbyArsR3ij(CXfzZr} z3D{aH0XeXuE9Hb`X?x33PL>sgWqBu+2ZYMKPAVEyShTAI?27)=wBwbX%pVm9H3F8r zh_~-iH793}3upE1E$dn_YCAbg7S4S3&Jvw0n+VH*y`|sDvNhM(wqLUD1D*j_4~+uHO`{+Y|H1`v+vsx?I^2)*_t?g>?^DOV$1F z)UtaZqUgVZW;*XbgeePNpMbn!TnniT65a;{q>bh__1(|OZj`VaF56w8c0--)CJDRo zc6MW(>}CkNsZJ_$g~}`^l_gMN0a+NZ-Pq1I^qIpcCn8M#RCN&63XKax>5(RG4BXRU7Q@{+dAq2N3mei zJM~V`kB#Y*N*;8@#(a=^hvJHfjVa;){kZH;B-#hC^VpBL9LQwcAT9?p88d`mAIjx0 zE{AhDg2}j%RFV%y{U=q)&-r(DhO|$12l=k;OyOal5_;FEvxU~qx?*~!DqXU(^D-ji z>56$jRmscF$6MJL9%r{J=D&=GsjXaWxwvu&R^L>mZHKO%@#!t0jtg-Zmhn8AQ(3QK zrg1r)%Ne4VVYrlT($fuAMq{S9+0V zm!c_Mz9n9c2S&9?8~OsD=WwCmp@ z$NnuzRWjen%;}ifrXxP)CVJ_LS#0e%`uHgymu)=DxAQFD!L$5x-nTuFG05({{Cppm z`e^Fc8u<|%vHC!A=X$1>0*v#p$EXYKf&<9tOn zf~%57R{hwR*t80CnT<=kN5NTa)wGIa1Bg}A$OaG_t8uAw>1Hyn8b5!8>&G)0SDjz4 z!LKLq>ovK2l(*O7(jXGJwfXfrT-N2X9+&mGe2mKmTt3caL+RSF$y`3k+Z%J~=Q4#~4=@>*3W+$yrSbMAY5zd{Nc#POwL$vaDEoxQO*RN(8dh+* zt|Rd~Wl7t~Rj1L8Nwe&>t{7Juc83Duz(qfYTY+u_Sn*wPccv+wv)|1i8c=cJX)!?sgyy%UL3zlVB^A zlWgyrVDHiuGc}^4SOLIyA#g|)|1tN!RQR8dWdY@vScUM({kis#vz;IpML-r%$W^>+ zYdPd6T&@$)E9`NWIpM61z+qk6!n?MO``<47Z?bl6qdnw$C&;Z4kfdv6mD2R7i=vdt zt5oUqnHD|IZ27HmaLD8JV&9zAISzlt5%9KtAwN4Wzje3lyxeZBQ?v8mD#-29`o*05 zu9+QQ$ZnTobjr*x$j)n>min~OtXb=B4I8w6KD%RfW`1_-+%|8vPVbW4IX}N+^PD!O zm$kcOwNZY%aKCbArE(|LkM$3=0a`z8w0ottMq8~daBtQQYP+?4+8%AF`>J+RyRH?v z`|6YQnfe@ku|D1X-`ENj-CYWLmz`ereA(a27OH*J{^}rgxH?gtqE1(5sdLnM>LPWC zx=LN6exhztx2QYRlj0rG5yo0oq_~m^MlqqfOMNXfw6B+DbsL(KZ8k51t_QQxF**0<`P>D%=k`YwI9zDM7u@7E9LU+M?-uk_>kN&Of7tbS3yq4#$8 zarbo>xd*$4x`(?*yQjNnyXU$WxR<(@xmUT@xF0A)&8@6J&sM4{(6^Q9Y8-<&uEB9F z?dw`~9eTVT#|=1c#PL%cH{rOM#$mI%718(%$89)n$8iUaJ8|5F<8B;3$8nE3PTh-F z`_$#?e&~IHmIG+{5-kVO@)cUXM#~|ze1n#6(Q+8Pz60J7T=^bXe!!KZxb`Ei{)B7C zaP5E4Iu5N9&^igNQ_%VuTBo7)3$%WP)){D>h1NM}orl&1X#EDQi_rQVT9=@88CqAM zbro9IpmiNuH`Jl(O=#YN<{!|!4b4LBvf5L-qW03Rs=c*qY9H;o`hj*s?W^5H7Ti*c zv_I5-+HJMJR)~z~sePmsssr&mNb80C=&cRW`e;M750EK+wc*-_+6b*k8;R^0rS;cF z!(t39#%cq#aoQklJS--_Vj?Ui!D2Ejrodt)(bnSk z6K%7)4j$LT;|6%#2#=q_<0g3AtS#2IXiK!M+Q-^w+EQ(swoKa&k2~OTCp_+g$KCMw zIXv!x$Gz~l4<7exz11)9dq7*KeF@J8;rT24ehu%3;QbqT{}$d4!~1veegxjXhxZ@g z{V2Tu2=70^`!RU`AG{xj_Y?4b65db2`_I}J+G*{8_6xlK3h!s&{VcqngZK0BegWQp zgZGQ@{yV&1g7?eteg)pI!uvINzYgy=;Qc1N-_rW3f8h5vPzv>vT2K9y)=U3c>#d*G z`slx4HgAdVt8emssBiWa>05mL^j*IG`flF<{d3<(`kd+m^|{pt>GP@&)(0jI(FY|C z)dwdI)A#s>>wA48^nJdO`qJv7^!>ik`en};{fcL-e$_Kh|H3z3Kj537f9ad3AM{Pq zzw%AiN7tHy->G^}tP{PkQuM}Ju^y|%w@I_~!%4IC?~>-|N0R318;yDTr^bB!2X%qI z)wfXp%(qD2=39)_V~M`q_p!diw^SclYZ-o*>qoJ|{Ont)|E#XkKg3E?gtew0R+}Pi zt^T|36aA8JoqpN3ULObR@mPH(=%4D}CvDPyNZPC)P1>R_#agrstI=|On|{H!UH>s@ zhyGL2PW@QYF8zN=yY=HqpX(#lJ^E&KufEN_Pv7p|ukUbwp`Y;`(9in5)X(`2>Wh-T z(ibOvt#2|8>6?vj^ex7>`c~tx{+aQezRftIZ#TZzcNjnDJB_3IF5^dixABwyxp7S2 zWBgA)k%Sd5>4d)5IH?yUoznLiKkNIA)A|?2FZ!vZU-bjV8U5#^v-;_zbNZLYdHtYq zLI2A5O&_RU)W6n#*9WPW^ug+7eTaHRAF5u}$JM%~4^yw}!_^!58TF>Vq}DBcg!%{i za9bax7P?2PJ>6r}Uhc7KZ}(oUk9(;4fqRwK*ZrCLq5B55m77{W{PuT`R|mK!s2{l} zssr7#Y7KI4Q3ty>s6(JL)O|}EhTq}tprN?bI(=h!{-9`ZEYcb7rE!Fi`@&YyQa9$md%3#Yy;xo0UZSpa?@?E| zFQ}{CH`Snfsk+8}#k1DEO#K8p4=VQ-etoZ^+})VmyRV&-wd(CS*X`R1{wTU}yX?$@ z+I8y=Q55_UENQ8om6zSN;GJyj^!QUpw7C9DUP?c;+vaqv)~-Em!(UrNr;w;hKUAlE zN7{zJ!h}xaN|FLjs7_92+DuA|SXawP6{eHjjke!Gbq56U9)m>Ti35!FR^tX zw^OICopTDhw|+6ux>as&$NbhUTH8Kd({(RA!%c|SfZS%T!DaeI?{O0Fpbj)pEyRBkm<>o8K zt2v7ClF|T&mlXqbZ(bK%NpFu|TujINZ6oa|ylRoE7)`q?Mw6U^^fqrcA%COFU#Dgk zWa4%1|6wH_;)ntrp0oZBJ%`JETH_l{^B=4KL_-hy_iR>9X8RUh3y@rO%|G?0X2eEvIwaj$O0xHiZvjer7v7jmT{KR_zW-dDp7JZx65a(du?T-gj%kr5aj;3QeL% zU}-|#*Zpy3T%$S#JL|W+)a;khJ7X&BYZP?{kbcznnQxvsd|v~#`Lu^N|3{g-?!OgQ zHjdhN#}1kK9jNy@eSUgpV(ZoZq$Mj33|}>MPK6cGd&f;1>ibDG`*M%g?H`SOr+u0C ze$GBnA@J9O&gWuibaOi6-D&5{j%<#0%xOb`roQ-DT)DnC7U|2s(rZlmXL8)@9wq(R zv}anjY@U(-RtCL`PoAn^<@I9i{y@h&WaXeYrCB;!?q&;O8RacM4NFFTK}N_p(6ZI@ z&7Nrrtu<`TFQa^(0*`4gX9WDso2U2#PiKhF;VOj{n5(#BjRk!3r!v?>&R%zt9ZD&j z3rE92AZ~!fv0YB*tPISizU1~O)M`L&1W~&s`9ek)A%9b#IFcx~k^GT6s-3%% zPgL@bKMcK5L~onq5Mz}~ZZZe+Fovn=819TF zFW^HSVR9FxNVW&LtlW1yW537*Xbc0L2!E5Pzwg57mG=De87#9hQvI#`aJdg^_$i~@ z<3%(=z$wkskzm%alu=5BorRP|st#bj;wDMm{5S6SNMksevdZ)Yo`2=pR_PhfzeK=L zTTvR@tXbZv3k|zcsD>uYT62T~=`Eh+@zI2W$J80#VbgTcLwfmvjvX>uq_xOkk5-jJ zUZljmD|I2KGwxlHX9z5`PoST($ar3r#(^YBcpO4mI}^&YiE>NHCA-5I&W|}XD9?F9 zK?Q#k;e-(34@Az|T|I)q$%q(Z(X~fIKJE?A9uZoDU5wi+^@t>Z7`nme$Rf(}?*t}9 zlt(udz`EQ~jNiNxb*_F@HE{`J?9~Ju$hrn z8yN)So7{MaY}_@!gUB4RxPA`nxbLMn;{jD(PBz{?g-}L8Zx7LXQS$XpX2-5!CDixI zUP|TD6w|%{COz7j#Q znMj@8NBR9zV6|+8oeMPhJDD=dAv*AQn3dDHeMS~)R7O*beRCh%h_OYPE`Yc;b8`1wRY7nG3>EC87U{vcAhM03uE=g(y4_nocI9mpRg#Qgo0< zbWIggsxGj;p;#TwQ;Ki?V&=Zaz4es5G2R*MIVwxec=$U){k?BmCn71w?UwqF4O`@0 z4>x{qoFx5^Qupl>O$&6W zzozsOD|Dv4qUcj*Xc$)8EcvDpX~Sc9r*&QGnxEO;X>~eAI(1%-SJzG%_>@Mcd}*uw zAMMr(8xrLGDBr*Y*>$FsC*vusJ$wVp4)tcSm@(l>kUZn1>sGqBh#;E!$ZHqO?a=kfefiVfc= zL(AAOn4hBNS$4x{q8=KaHzX?N)T{_!KT}^9?|Y%yGp!mnV2O$QC(7Ng6&8}v{Qvfo zUbQgpepN|V3;$5kA1n8I1yl-^OT|7?xP(x;>(dI#-RUt4J@^l3qjBDn{JXaGo+id8 z9{P<5@hv^D`0vH|FWQA=2>NCZ`!9wC!A~tb!0CKheDNnadOzcIAfuzR3v_mHE^iPnAF23% z#DvQZPf?$7h(w>EBoa6_2ZQk{VSuA|H)jAD9fN(ICTtwqgy5?HUIyFG!62gpJBaQc z;N8vguoMc8kV(cokT_o!z=LSm@m0ge zi>Gy((}IkS)^DJ7-ea8Qw1)6SAc3$tZ(()T!ip^m7dais=;&MrovR+>GN&`rOy{bF z&SeKWH#i;0=;$bk_*P8LWqfGF9wo8)!vZa(jVqC@laSFd_!}6+C9;)ajKm-=F>{ac`pW zk3^#aXYwvj4i8~+Z(?Z6_y-usbE$%b6U*8Mc!(gQ3y}_PYNAmk(WuP1y&f7WA0ek& zC{+=3D_h7(!|3K5A*18?C^#l08r3<$zUG;gVBuHY!it5g7N-Ll9i7KOr(U8_htnBg zrc=*Cr;Y=i2AmFLbaWCy=Lybbu6cWU!h+25*&8ilG7ytE;sV}#T6!e`(XRA*lJ^xd zy1oX0?B~d{NS=~frxD3hzXck(7_N0vIRnV(7_oc4yWOQ6#0@oK3jh39~bPy$_VBtRr(HB5VDh`7!E%^e{ z<4Czkj^39!Eyxnl8WXDA-vq4=oRd_!cL0IUNd*^CxxdAcA)`Zn8_2ndMkfv~SMIrD zUF&4w0ZvGl`_STPjpDQ*qoXwmv?e4P z<2Ws;a-U#fHO|6{ZRnFZ9mweD%mSSmiN-WeN2=UsSm;c1pfj7(fsBsM0??VqxyY6K zJPWjxHVZie$mkd>1%oA=fn2#SDW1VH&Hyqx25Z1zb)vD7laMO+)mR+&k;PF|?kg>< zSf#TzS{hqGV^gBBG0|AhnMjrUCNZHmf`L4j)>}BStli2(1Q}h3_JG^&L}O>7v7K|1 zEBDtjG!AfrQssWo!ta2E6${xRP6skNIzNEUkwoJ# zrz2JFM=W#>JJ31G=|DzD=Q!vb<6NZ5{g?%r<@1SX5l;j06i1XQ_ftT$E4_ZiOQ9`%NtP~25(#P1*G@T${j~qKG3S< zwYleB$y?O>OHxWiRPOh4WXR}{s{pyO*LaYF%awa&Z|DZfgH|5&-n_ReCjuEAk!m2K za~5*Vu47ofA=zTC*}tVVJC5E*I0MM&7$kU|YW6T#O%4Vb9awF2w-)cNRI}GYq`xI2 z9#ON`i5BrOAlBoEQq5k^0kJ`}h+ZIiyhcL~D%b2Dky{Nd_;`+j=RRH^4>n|U!A=2@ z#$F?t6OpU+#(?iF-DgjBA{5|+AfqGnGzc~G8cjJNsZMWZ;nUR0hkRj_w>hT+86BOL zp!1y9Nau8^C?zWOUf=ft~F&+H!cQHqXW)cv!_P3*1j{Yhl8wm=4hrcpC(Ay+$Xm@fPPGRpq&2 z%60++dCt6L;lxVJJRTg#=z{YfaO>_h-t`(?IXAf~?{1;=uAtl1N{*$?dz>9)bnNy8bzFrRFC(!&?$1DGmz7PjE>GQ&>6zH zNcH#-3o^^(;n5;)HCas;K|H?#)F(fcu{1^HKLHNodz{zX6YQsir5^!3@)-+g^Wy??N&zx(-ENSLufGjzQksvXgGmz`<;l83iMx0Q_4HR*+R7}h7fiBOD?<{;+Eq#m!1+wHp`4zlQ`;1dQ;{@j= z*U_gfbWRDXC#=L+nw;UxAWP2d5|~}|85cM$sfNC2VRgaEg-+VboC;*gsoVmU8$RP2 zry|wQH!M`HIZ*k7Q-LfwmDnWQu}os6iBvnglI%CGxTGl1N&)R}98Id5{{}R>Lg?>F ztPp}Mc^}IGwG2m$R4q0;a`+#04$*7oQ+`~D@^>U>ozEq%Iu87yi zc)fg2@!am`+#pNNO#`>8NyfvRm|QDY1sSP83qEYg3Dn9*X|0T-SLc)<|0<<@jqn-q zn+pGoc-7=4#>2@r_432XMZHhh)XQozOB2ZGkmG?|E!ogHxLh+=OAgh{x`hYw<`k`6 zar9Q_bReUnQwwxzaxQZ9Tr;_-&)LZ8`5a|{BW^~rfIvpapkA_51sw*f&%q$018a!x zHsIZrs^|uY_c@y?`iW=}eLzg)h*Bk;=zy3MEn*4~8z&pd98|8R8;cA}w%|({7T_U= zj4tH=1f8dnjV7FqTvtB@5~oPm#V1Xg6i@4EP75+RS}j5Axnv`q(~>Ie=Paz!Ev#5Y z(~8r9jE>H0pz}(y@e-#aRoSmt=)B}Wr!}Vo86BNW(8=Ij@p9n;|(rXIuD`a$iodM)&99gc?r&*wp zi{bKPCT9Q{9fL(+uprr(mu$@8JmgA!fxN7sUZ01S%VePupEQ|MJlDmXD`a$BSA*-y zWMereDp&3+Ba6e}a!bB|^jTWD1H+_#1*_e%aIMn%7Ix1Sa7yBp)P z{#WtQ_5YHOu2;k-(tB$FzCk}7eM1f2jh4QoxP~_BLjJd^m(qdXOR^oj?+Qe0VkV$A=F`i|7WT<~OQx&@V|K$RC>yC#V`wM`*z7 zT{c+N!T@YW&=BD0t;RzD8C?h-1)&7LQJoX|CPZj7A(Q|Tg@h3P46u6fglcg@kkJu( z420_WjXIpr_Y$FcCPHhzlp|0?~@!EGCJfmAP4-0pM%Hv+1!{)zykn3g_{vL1pRnD z9TThdjY?}*JK)EiF_kk`1XL$_8VwJtZtz3j^D`RG~_Mo9q?F6c!(`44=pQ5i+RghMb~Q_z1{iXK$d851g-Z$s|V*K zZCO1Kh*jaV5aUr8En;6F_VF9NIH)^8 zwybd$0&L5g$dMtVL!Juc$sAeQvL?&OV%3_)ks+f)o&)4req#m)m$s}~01s_hGw^x? znI{oj*4$_bECzvveq%l-AZ=L-O$6pU5Lgl|ft4Vz+;1%91f(r%xrxA12Lh|2C9oC* zf*f7ivVuS~txaO^KjDK98QtJ-0`f+`v7UoVTh>OgWv!QKh$V7!wD3Ctzuj+ahI) z)Abrh?`b|bkbiY>WLoDz>n!IaZCPg#h|kGXjChxIAzH*MK)mEPE^<(L%en;A1ANQ6 zXkh?02WSXz^j_s5fQ&8#w?XKZ-?+gE$y?Sfkl4z%tQ*A>Qc~DEU&!bP-I>zFxFf}g z#ecRW<*mGB-H{R|6pPpL7)cQ-#R)-1N2nYKmEmlpEvt-$0Nb+e;>eKEAy)u$d5$b? zS>UtQjE%+fV5>* zF%hWjKtPL@Ky?s!B*k!Z0@9ZCh>3vPfk2ID3Dg3CnjBr)vT6d+l=our4LofxR z_^X?K{B<8F?BV#*KaSV~wC_p2NBsHOejaeoO$m|`5@!1AN~gDIg$`3Ec< zz~?C48F2I-;#43@PUQ%w9OgXa$M}aa0w>4_3^o13h?5i@NALF>9kS%;KczT5!Vd!- z<3Nxl2Reyv9_QVZ9^W5Fj8Bqrj`*XqQ_-OP3bfN4O?q^H+5zoMG-wxrb|J+$#{uQX z_7_ApowHy|+4MUPGi1rbd;?Ujr5IN@75S0YPY6Oh{2)utuMzn90!AVyCq0t)S-2%y7_m?# zb1IM}r;-LLfq>!XRHVo80Sgts1C=J63S`NtJPj(%I1lMjd@~Cw%iZSDpgjw;XE>Vl z82%Zc*_BMs@jgP9ypJycwIxTDAHlb@z#{L$<->~{9kS%;89;wMV7wMEUf~?%$M3Jp z%LX35zlN5xWFZlc-(M-7=Np_SWXXBvfM@%Fkb% zIVH%FP^v*I?Ds*bN5JULDakj4dVtdJBue6jP$ZvqVmfeZX5(9q(^jN)Vuc52GDpDnX$!_nZ(IJmYmFV zkeSMvNH>3`TEN*ZGJ~T+mK=2sP-k&e>Bi428CAUZpUY7pOOCo2s0#zed=4z#^jQet z&`qEDc->P+7Dn9kSrQHSN`Nm97)v?0bi-%434Eyo_^N2Y*8zNOzzA}1>1NMb6L`=8 ze0?NR-Qd}ag}x7RD|~}zw*!SQBnq*v4W6os%SFD&{S%Lp{}#US0^f993SWF! zSPIYQ%aLzB|4gWC_9!`7!d~^7xPFA~x)eetBz9S+t4_`tO7xMmK$oqb- zN1?vLi9*>Ni17PRNdK@=8!9Z?WfK+gWfkEuYJix#T&11N z9}o!lCR+01ABnb6tl;F#Eu5+LmQ}16m7Sc`63!CromF?TY#=P_*<03evh>1|1@j3f zl_!PsqzDx;*HVRw-$~^eq4IPwqt+}Dldem5{)KL#RBlQ~w5gNpmxb#Wh`HUIb-7wb zSc`OeOIUY^P-zjGym>+;*E*b?oUFPDtFCsmo(XyH!S(1;(hDbSJl>D+n;z2tP^k2A zQW+$m2Y|4&l=O4586|9nN9GXuiW`?}sFUSnVL8Fxa-5UpY+*UW-g26g$yPl}_ec1;Qq4UTn1Q(RwFmdxf*z_Le)X7~7qk9TLtC+B-Yo zWO-Cr9|}WYmMoaZoK$`h&QC?Ch`DxNsGM<9xh_<$6fi%#}Eddtb#d%{_F zd&_sN7+sy5eIT6mvUgVKWI0e+_P4hzaqh$^rpB7lfsyWVVyda$)na&vq$U z>}0u4Sgx_RTx-ke#OG&bm&C|l>spN>Iqyvp$6DP}7!tyzL%XBBp*23}?d&`%cEZYdn3@4Qi zLM7Wtr3+M8v^yo+C1oD%_*+iq{}u@ETJxf-eUI{;ob?gTdfHpQZ^h{0}VL8m+a)^`Vcv!Mvj&V|%BAic*P!V%&rcjyYq_SA3EGTBw=8;KfsY>3VBRa>) zbx^oo=`?3uuH_NdVrJg!4=p7X{Yu+*olSQ}dsE!I{YnR^xi6aOynh&`EO-z4m5v=u zcWjG7D%FH{&97vcG)7S0Rh{f=3A+T@u8`VQcd~0B?CROs)p4@(3cDwqRGt(nNlq$F zpuz$Y@GH4p3rziG%aK3Aa(XCEErjJi?Jb{jvTP+RpR>12cd~p%bm+wh6)}8o2;?W)ULmi-DqJq!p?4(lifsNH_l0AnoybSq%s#O zEE{LpXU2>O%MGD8EfJOr?Jeg!S*{Y6%k3?fI$3@qIuwjh5yQ7xINykH%GtQy$!M1_ z+76?LY}`c0Z>y8-X~F4aWHxT6md7HqaaSmW7X<9t2=AYVRIUo|m*ng?Kz(0yvQtt* zEA}nfZY#CB;bd1z*xivLt;NhPHbq{;1<$*LT^T2pibAEllgfioVcB?JitXB1DZ=tl zC{CKNtYU9j*~zkouzbYc((Pnvhz`|^P!VBiAe`4jIOS}t<7AX1j1plKk&TDx_%(F0 z-7h%pNs){G??a(FBvcNjSc?7wPFCLwtHUWaMgNJA_hVd-ZvLlm!p8G>gx`}P{WC)4 zw3Ev30{Q|7OGW=VC!3qX=2}Wb(SMXi@QRb=9f8oyi3!+RDgimLqATTuWodiMQcji? zg=Kjsl?Q~%y-q3`R9LjD1ni3b)3oE2oy;E<2sHwhyok5&Q8g!Lj|*q@?JetCF={(G zOBT+2_RbQWESm_+fW4*P$+9^tSumS9sXQl~KNF!M=Gu!wrKOX~8$#vvVn*$?fL+ml zmX7EvPOje+uGjpmsx@>?R4j@pg7&o$O`^yQxkpbA`$*CzT~o zVF6hfu-(|^M_9V<;h|h5ESK9`E_Je8FD%#ETLzshH;WE!j8GB7w^KOZhH%Oo+g2x| zFND!v7)5Msap+HJkOSV< zFXU(E<+tvZotN9Kb!vA0TLrmYTECc+-!-%23)$^*j82*P1=)G6(^8){nl)?Ptzm=K z&u4ec&dkqlo!jQk*6CfcJLl(jY@XA`^s;uBtTxJT7w%W?tW@@-I#~Zu8=&>mmgp_wc3qpH_tm%S1NATTrm^nxWee3lYJYXOI#HdXPFH8C zbJTh2B6W$nN?oIVqHa>Rs5{h?>J{~t`XL+-&<1P6v{Bj^ZK5_so2kv!Rsv>?wizIM z0CQ0LK|7~i1p$v0>Bsex z`U8cJyA)*wuve-pfWA^)jbjkUH8`%NY}Tslz-c{>8*to+?-{zMtW^ z4ae;`?!a*;j=ON&jpOGy?or37d+} z4ujWsz&nB~-{Z;;xN;QNe#F(EaP1hb{SR8lp>+aUC!uu;T0cYUG_-z!*00by1Ff^r zItQ)u(7FJv-=K97TE9c<60|Nu>k724LhBl|u0!jFI#j(0&0Em?1Ddy?S*TrBdumtI zUfNZ)w{}hKqg_`&&~B)GwVN2LTWXQ^huTlOt@hUnF>XDzkF-K{AbtmFy)cTswINy` zZK(DE#DTPp%rN(F~*~`{@Q3*jDf{iZJ;(z8>Eeg#ROPPgvBISOoqi2SWJb* zG+0cB#SB=?gvBga%+?mEb6_X8>4=#ja8RwcvRz|%^2S_Mz5;VB4DYqUAqTKs;ZZC2O8<9c}90FN8t@l$x*1dp4w#o88aiMCby zSo=&{s%_JjY1`p(2R!bC$6fHa8y-K0$35`47asS)<9@BT`UQRuXzR2u;rSpue}&(# z;r$T2e*^E|!uw%({|?@d!29>`{sX)ph4&xf{U>-o2Jioa_v7$>0^U!;`zd(;S^Gje ztsT&Qf%jkG{S3UHh4*vtejeU0!256Tei7b(hxbeHei`1c!24BrzXtEu;r#}@--P#D zT3_`K{N4sip?*^9sh`q%=|5||_0w7({TJ;6eW2P`-{kvH-|Q>WxA^+$KdAlnt-b;J zXTFd0ZN7o}27Qpe-8Wd@;TxiltThzB!}PDU;rbwTgg#gusSi;{=|k1g`Y?5jK3pBE zpHau@Bh>NwNOgifN}Z^WRwwCW)XDl-b&9@Mn+n}&`e*8N{RS46o7znL&eF%Lv-Jt; z9DSlXSKpw{!?pSPEo}jQ7wX5=MfzlQG1`{se`p`$cd0&AU8e8yE!TJZR_LGmR_b%A zuhQpMU#-up9@GaWuF(f2uGI%8exmR3t<(4V*6aIx8}y~sH|qO+pX!%AoAfK5&H7c( z7X1s~R{enQGyO~7HvOP)yZ)7Lhd#R2PWVR3>FVeD40Vq_Q{Ai2Qupbz)&2Tj ztVR3u1Nt}Wm-s!XAJD$i=cr%n2h~IR&+0e&T=iRUJ*?l>zQgYkeZKm=zCis!U#K3{ z7pXt$4H`aPH<7lyQCd-M-*zckeczk>YKG^JWo2i6Grz@x@n5af<6CYTxI$4X zmc3IU*K(FC3TiR>V-7fJAmOeR8Hdv4Ss-}Oi5?00ya>IlQg}^K$cZ+ZCv+icwn@bj`}i zZC$@^y~Ngm+)kakcFrm2-ulHr>sGnB9rIhaXo;8g8q}`;MD6;C_3G7a-6p4V>!)(_ z3tsj#r1ehQ`n9t;KSmxN4-OqR}+}vHDLm^q_ywX60nIZ_%{?$yL|< zQx9)M?`iVzjYLYtAK2*5sZDl!f`TiHnVX3;mCRwoVFT4YvYlnQ49&53- zQnanYLeHP>MQG4+I=AiEH4D`)AH@93cG>v_nQh;y-9ahuS~d9X;k7N%ROTO{n|2KhBJ6RHtC)|3}=JfJaefeZM-1!T>75fXkp%RS-leAQ&Ot9Rr;X zn*tF5(J{OcNPtKnm_=kp#sCq*D*KKgBKsz?1!R#$5RgR{L1a;eMHB>)O}6iUt4`na z?W)T2+Vwuq2T$sDs?Rz9-`!7Fce?7ex!U}f2|FSx?0vy;1=z4-=ogN(I{HYg++yZG zHve0ix9&d`RyJ}RJF{EIoNjvbIt4$yGc9GcFMjEY{bN>rJh#FM=h4%%v-Q{w<@9TP zQ@TDI`A*le@BN&g-H#*J5K<{Ss#EYDs9W#wNnwil_7y9_suc96pcx$n`{E+(e zM=vHsNDGsmYS=K<-zc?iV#`MU=FMJCe)*-wje2JFZ0PQknbo;_M$fJdpKqSr@cCQ} zl7`QB$;d?9MpFO#r6^Yw`6(&?KK6PoLR!h=)b+P|xmBXCnZFU4xn{tu8Z(nB9DU?3 zcZua9Q{FYz+x3C*|4sb4$D42W`u9uKPd#{`p_JG>In`K)QW-AZQoFA-=2m_ah;LKz zfNiV!Y~PH+hbCMLl3Wi?O_JEU1+Vnp(m+>alq5^}m0-V}*{@~xrK(}GYF6GA@k6|8 zWm3e0(*rK-j}HW&ubI!E9dT#|pQoA6ZRX>8upr=*o!&8x`#b=h9n9yc&NyVlr$e*y zk@x-Zg6qr+uGogI>Wy6O;oLXi+&eoXw^*?ZymvD1sYqn<>pg`-KdIP1k^4^y_;=3D z#!GanWJS2|V(zswaHv*YlA1It9~BAZ_6;MT{NQZvhPUN9VSz{${Qm*}Z*=+Y@ZS!9 z72>Y{Y3O=zWWcj)dTtIEWVPMR94hv}p&7Q$$C!f`4ub;@z4C$_%EMs~b9e~basEee zsNAf4gsW*oS5${MDf#8bt=hC{k($#zH7A|*HU0nyW*+1md*M`8I_SZ8z?m3?!N0On zcb`6;Q*&}t1J3?7ZC`2Lswu427`aMW>6=7EZ2VfP-`Ao=qR;X=D%=tOz7|vI#oxn|CQHYZkwF?N_!@TR~b6SHuIF|(MxZ3 zDgRAlJd~Bz2Dgwux#i2$J{`G1Tu^1G!a)P8lVRtQ79>^ck)GQvD=kM)DZ5C8*leO+ z&i`1-m-3&4)!+IixeAh8gOgk%lU$RMTvL-=)014YlUxgvBBElAaY^f}(d>=jbV{#a zjz6@f_U)Q~aAo2O?WM&;tAfOmZ_=9Z{-#G&f_90s1cfBTmV<>^j&IKY)0$bc#Hg4N2ISJ?4*uuZ4G@;`JR<<@?*8?x+ta>tx#$Mk<_dlXLY(`e4J5 zvwKyD^-jmkykaA~pqK8zsI2s5V$g<)8lAv1dP_wmV5>_traLNJ+zDl+mb`)WVa-P! zUr+vSUL4KiJ8GZ+$aZ0&vUgb}+9ye`_*x~UcItz)kw5(c+UuT<{~||e(-s*4D5XFJ z4(sD92hG#7Yib%^vl_LaAr_TrtVV&v%~+0-5I7&(U0JDx*T`;>7z8=@H^yOE>21F; z0Dd#nqM91fC`mGcu_WmOJ=l)WRXS*^7-)oyIwEvy8s7LoLK)ntgAgjpYv@q+X6Uf& ztx(sQpVW#?o3@SHv_(Ch4!}NW)g8Ro1_#U@3oIl-bcsawme5z29r|v^2Y6jH!w?-I zGkBq(9FDJ9!zfxmA(~OwRO64Nja;ER;*HSby&tqfnvv%uv6l$?OA4cRsm@Wmgw|xQ zAOcO<7ok7YLpO}e!)vknv4IpP>OBiA?iUTek?@NeCs^h6H1d)_^1`O+C}#FQMo)DP z$uht3+2zEJ*QWFllE@(YYZH5(@Qj-aR+AQG{y!ZtH z`>R)djY{TEq7j4YNLeXXszBC+MUFB!K7|i>*wE2eHhLWrHCyP~w7lXyARdwv^_o4T z?@SpzyJV$y?u1!3iQ4mk&^DB&1P0w`xKGyI)2zBN2tCj}Zwe^E1Gpk$P0?drd8A$Q zR&DFY8W}n+|4PWv@D^=Ue)$MVDjgNEFi9#Mf!C;|Bk(G>bOc_@m5#tGz|s+T-B~&U zFR)8T;3aeEh}k%l!UYE@vI?#*Xo1TMa`R-Fy;_%zYYS2-TuZ>!ZK>2lZ{+7Qwf}Gb zlB?!NJt|Ada{gT@`MC!=RKQDzDy1Wz%3sQm9{jR`^iXodB7Bi({sjE4f7Q|YxF*^c zamM!y3STDrMI3II!ERRAU;pOA{xa^B;>(ph8{&*_6-4=0zu!Yt-U{W-aoU$8E`Fit z=D5JO$$e?!0Mn&%?4CwAdcGnYl+JK=0_SUD5x-RQ>$t*#$?UFFqk_Ivbc%j&P#itG zhybNCg1vEeUo2WIwvWV6IukpH>h7oN3STa|AMHJb_4_cr--iWm;dIEU;`dNIOp3x6 zj2^a8JnB^OM<||%(~gm-_$8w!_y{{@(icY9Pt@cnoi+K-z&RVIohBUdi$>1^;!-&X z^Di1bT{6~r!b0f`>vv#XiqkFY%BI5*<7YlI_w;phz$ z&NUmHTZDts8II&`qTMAH@k>YVnxutc<8mA8BuZxl_k$qHZLHAZ7mr4{L#L`hP>Kjp zIwN=x1m)aX8G;bLe6*aquwXe`99QUz<6^m}jETzl0>_7(Vmu0r%5LrNZmj~52wy;2 z*&Wz2{tg0hE>$ow8Kd?wY9f@*nn(qk?AD%iYgLF%{1Q^xg!ClGtzv=`x-ps;oUL!1&VPQ=SWbSVPs~a&1nR_&Tx7ICy!Xf%smgCvzv{X;LLrGPJpB5 zT_Ql~jNm=DUFKda)|bRkIuq-M>b_6a6*Bkt(cXJlzlUV*{hcZfgkk|H3YmL>jp87u zio>Be)U6FBQ89BL%178>lfE#*Mo^QZbk^kKfHTIejUpT|a~}hUEv(sj=02)qtnq|} z(izrAz?$mTCKHyBxlc7wO*T;(8~Sv@LFo)Vsug2oImo1Jw zb6;tqGBTaDPBFFsW0PCk=+@Q~iIBN(;uCr!2*kOx-o#{#+O5@eY=bcS;RILF-D zQNj^2_hTlUqc%7v2?wP!oYTNLMJz(*e#)e5jOQ~>70*NQ94QK!`#C6DrCz^KT~Ru# z>u*rLK+0m~e!(P-u~?jbTp|LL&IoRT;JRD8>ej9hhnTrv7nc=e?pJYUA6sa6=6EIa}*93fUE6Q2?V7xkZJ%? zi9*cTRdmY{Hd=yn_V4wa9Y@boM1ay6K~0Zc&R#6`42hw1CRQ8Otwq%pa`swi>F-&O zhve*aoGLyC#TZf)a`qS-#aO3`9w^3nwE83}=In8NY}GgE zv;+bXv-L)hA0S+3Pp|{>6A(&gKraEPxkqbCKti70+{Dw=%%i{Y)`DTuLoYo#K znQ(+Wy|oD^*#@UA;h=Pe^EzL{0L*<{OjnbKRDzrP0wwR%Ju+x5%v{5?K z?h5U6kJg#wh1@(Hi{MeYU10&Pr*}4y7+Fj=rvPsQAj_lm@MztMLCDIp_>}Dd0&&iC zH!&G0W;QhrN@tDpZ?N_8XuUmJ9SsrbsN1H($ zVm>}Au#_MZpNYpmuw?~T&u5g(H;4F8I^$akzQrDGA;F0`_~OuHuV|rZj35;}qUYc^ zdOjm8lz$bg2|oAoKl*203cXFVfnJOJd!V;)zzK`|d$8BY{85Il`XN+@d$pk?Eau+B zy@A|&sF}f7y+#rQ%J3n^0b&dhhVHWHHCb88d~>9i+p>A6SY}Tn@MUyu07L6?NcXe3!pa7tIZ)nG0&dI$I%>< zHs#q1sew_3-@u;(;xn(dgdoHm`!h(3`N9%AnB@e6GJKdX0JFxcttJ>Dzg}ZvS#4&~ zx8rq$f--!REkN1i)ix4}kXvsup=`84*-9uV!$;WxlQ}LhkH}x8As-;vJ}!hT8q4CgjccL(M7?`dhq_2%!wWjt@Y!EUAh)b6Jxta^~XH z;6YMH8NT`>P_GoPRgBjjCI&HIt`tv81@h&JczlZT<%dgVdz9EvhR>#et!ljX1c8aU za#g?x30lz;rZItB`J|pJZ5=dL(c&!ag)BN2?fsiY7Tv(9q8Ey8QWP?2 zw~b=FQ^iCmHcHSENL0+G8}SjAVA2;xn4g*)rL!h~5jf2fv?hcj=GDyragH@R|D;Ki zlCfSQER@c$+5oF{f|g8JLWbSiM3ro!GBTRBgoDx<&KtmaJwa-peUQA7J!O(DD+r93m0&@ZNkv=Yc?+OF1ScW7PhOnh2${CK>>? zehJ$930hxb6Lax?CZzW{ZeJ6eFpvs}5v4Q6VPG7RpcN9Jkd+TH@fDh=j3ygSI4GUr zj0Mi<1Z^bY2$}h46V6B*oNRFQZ~l(6sL;Qp*W2cg$#Wf6s=OP z8B|x4&gwb~$}>q>%+hC?q%jtY(~nPy0Hrg6#UNOipv_Ov<`RdPsV@|l73AylapoFZ zX!s{h=9bL5gji8JV_gl_l?mE%0u?j&m7&RD(Q?yx0rW*ZbH~wBL|7>QD%Q$I$lSLE zGWSZpCR#^c5BiP#}Cu|3v*Qx#%IB8OYB3sh{~% zZh@XHRM_8I;^?XDGqPBe&akQg>v3Y*(`a4)Qjt>rNQU&dt^`p)wqwT@#yon$sbVw~ z6`xj>L=Uirz=sa<$1qg|s$&)C4JcPs)kFZAv3e8W=&43cfYMnLJPV+jKCK1;9SHzU zU_dnikI&3qUbJKy^w6iX|YF&VbwiYCtsG8m(iO zd-5l-)@fh@Fm@deDWi0zoB-u`QoaP`L=|7=#gyYk$cM+DV4@C~qOf@a5M!P+aSG4^05AHqW&}_w7~sVqfMzxT zEu8|i0YGb?hVQFNez=WP{SK`TdJD7;0!X$2z}HbZ>w?z+@G7Za3GVz?p;*Y;+*q4< z=f6&!kJ6cPDwI3;v^Pln2337F>--LEptZwK(HkNLUn1XhD&H0I={~I!$)6(m`Aj|? z8^a>DG0b7(4acHRHW=N)#Ml$qvfc&8J3cL&FvKnE9dImT9DK{l#+eoDOz@VqN?)&W z^z@<5K^a!(aIE)%)t8urEvqjYVpZ|5;Qf*BRB<2_3w&CC5*4?s0;sN|EvvtY0E2X$ z-UK*$22m5Bbk+nT05r^}4IvNdEHIAP1)Hx{sYUhYpmwhrDcYN9{0ur~ZJAl|qTh^_Tfuuy^l`l$X zK&29!X!j**k@#vv5+5G60@T z)T$7Guw^|N1W?5WKyeCC0{~AYYS9EBY*|kQ0YuvXJna;q766_hbz#eT28u!Bo_D@R zosZI4=RXJKm_)4(i3?j+Ok&_wRvi(8Z&|TU<-L%1Cu;RcUf8nSiTKn%+ZgzkRo@09 z{;y;B@$uJa{o}8Dfv}tOg)ffS4YlKJyodbx**cK>9KM9L(vFZ_%{Ag^uQU`1Ecf{priB)pl5Y;96iTL9cB3H zKPB3|g8^6O?d16yp7rgCu&!q zb~#b|jReKF?Jx7u^qWar7)^grGouW@nQsB*W}#oDqkEvD4q@HdTl= zO5313Kqx4~N2vgm^28y&O<&$5D-4s0q>eIt^+%yznbgI%=qs13{ursF3}0P_`jdXG z3IPaj&p+ueEI7{=J^uE56%&zhd0BCS@C*>1_G{JsS~a2&-kN{fAJ_t_LtUIR)l59b z2z{2C24(n76AP|-eyy%wt4&D8ol-3>3d#^AU>hcD&z&;GG{8*pYm*2@yZ|&M2xd~rFdq>N%J5-6 z0nEolB3%6W*d%W3BC|*pW%#Odp*ovXg$qBkMOFUVe;%o#3}1B#R2TWR1tct7^jQSq zz(t=0c-&9LC=9viv($ma_?uN9HFaIt4?ka&@e z_UBcGbFoWsxL^w z_3c7@Qe|-xo~_q5qOGeYdsv}qTd6H>)p_sU|LWEOOyc=uS1glw9uiZNnrKUs^cR`Q zuKLNYxa!N2s{asApRJ0th_1p2r=YkqowJ?tpsB>LbO*H<1axGBV zCZ^|&J_s~M)1c>z8$+VTXcqLW%$q9kZ1bR|0&cSFMZKxm!!Sl#%Vbvz)>JLgR0U|N zFO#$lN!q$VgSD!@#b_QvOHOvZoa}m~Xakz@Qn|pu`kG<132Mg8Xh!{H+oE-RaKvG7 ztX9!b3;2lK!5rI#IO-?cS3mQD(f(d)|A*KJr*QfQv{*yGR=s_a@u{^0GIQw@;VU)~ zW|V88hgRZtGM(4iFZYZw#sKw`|E#_>spzYu{uSg}cvhcErOHxeQ;NP!Vwzjov0B_N z7NkS9p+l;1dst=Ct5>HFAhCNbiEUd`x9HL~ zvL%ue-GL9h0bVU7?l@Ww=aOC7dOZ!?LpX^il3h7PdrKOPCz*}W zK*f&w$-L^{B?b8!%bY&tvB=F<*&;Vv#c=FxGinW4K5F|EeFqMtNM{7OEc=uf194vYfR6+hf(wss!hTA+Dw!0#c6ViHNbyZ9GWJq<@A&9Gn((M zr-^<)9*h&{;SKx#c*EZ4lAb|nVTx8bgDM0f4mKiIPo(+On2maU_~;Rgp@m+;6=chS zBFv}!A&6FVm=8WR?ks^1WirCd3S}F{TtmlzK|&pvKO81)qiP~18g&HwC9)>!f?qyl z&blrir8qm1nXr@teHPA)%pZdQh%*`mo0Z;DnZiN(>krgD*C3K4M1pB7-qVuc~y?-R>x|49G<~7}GG9KE@C_|IasQf9+ z^m0=5_N;3wNcn$fU3(E=v?~|=3XKZr<_d>#=4OTYk(eZ|IgY4a@&?@=uD@X5k^Gf&s}|y!szW@n~`Y zuuduW0+`u@^cT?XEl_LbP}4B~6c39ov&O?{GrA52vspwo+R&3>jkb9RfH-qe=)KN< z$7q|4(RL?EyOpHf-B-L=#hma+MID|e!G*5&c zco`m|BaB}dLiNbTtRo=Hnw>pe(|Gc8JS>tL^JWJ*43;y0*6i%pFtWY;RS1AMD^ci` zX1}A^N21xwG}cNt*6wdiuQc*kk)`VqHpIp7!N+a$imM>o_XRTp0p|QXrB$(GCoL+bKYdCdZj{u0X4uxKK_B-l6 z7n*y+7MS2_t|^E<#K%yC*^dUmBkxe<0%iNY_`~ zWOJO9k;ZN>4x1?0lPI^?vAiiCf{D@E<=hg#b7OHI#iGq!t}=G+k8y>{ZqvB?_pJ{M<)(U%Hnj`=8V}u$xm(Rym#a;PHy=*jxp%h^la_(W zo6SwK%-z|;&g)(7m1l+3DiFOd+38D3fBa(f$NM31lLPjHxJiMX$p|hz6u`n#GT6>% zJogzBI)>Q&UR|zHcAnF@=TvLY$#$M|xaTZu&zW|fi@4`}JCo13$x=I$wJMpuKFYl-dBn}DEgbdvU6q?u@tAg>$L+kH;$Es1*6V@j&ybxiRR_Nq{ZT6z1{R`$UU4Z&4NTsV++?`dw3H0B^BT{+#&|7OxHkjQ zr;we#l+3^{Mt@8TiQ6$?|0y?_X=k#KOV0zau$0WP^I6V)KJ!{GB}?o)*KyA^)}E{F zJhyVsP1c?p?L2pK&+T?5`?$$&JCh?YF&0qz}9UcJ8OR!b$VEIBs2|AMAo% z;K9yYd!93EoUsdbjR(789qh85=Uwi3%i8m%oo7^hpfO$X;zZ&@_ir#UE+*U`V#4Rz zgWRO7oynuzq*As9jT1r$qFO7RWlVE|>GZ4KV+38D31N>qP?%0sHSpoZaZsN8x@pI`$02Y># z1UsLXxKFc$kfo%X-hxf+Jlk^5*4CcMcAhER^L1;__I93~xM!-JNjGkiZfDX9CPr)b zNU$1|*?Psh+qwUXEA%#xi#+QZ<=6!);KBM?d%kbh=xY~jI1e_&I#{8d=Q!>;+S+rZ zo#zyI8jU&8&SVA;J}tzA&$Umv$xJ(wCER3T3B5L-O*&In@{Zo4bL~PG@z5*n=B&%L zJj9#N%*wvNQc}?;b?(wL=*s8-UH2iM)J-@&5U2Hd{{&o(#(Uf+Wp)d?Vp|w6sm7x# zJ}E88Vyqs!s-0gg?pIUv%h&yC*!jhBzZfgOI(B{@?$^N1q#-wnw=-!16Qe==J}E0N zH>keGa^wr~{3Os$ExG55)}GDmJlk^5*4CcMcAl^E3cVU)!n^NH9=rpZGgBHELD$<= zm+K8Xr*7OS9Zp#tGc$w6)FQqAI@$U5;Y{y@j>cuWXLjglToGu(d@kEJB>Jj=$siuR zKpY+G^w|CF{66GMK+;9pRjYswVt8eGKk2CE~ z6qEkrfu=glO%5iSlK%a6UdOrD(L{@+|4bnIDYDZy|8w}o=+Dz3anAB|5XlK$W9d~S1}n~5Pw|4F?CuiJUv=MT)B2*0JL z;3N?1QcG>wZPBNBdy-_~HFA=WDh!sgs(iOZVNm8ebke5;qM7ScBB}qN? zmsl?2V?x!Tf)5E5QGhRafK^FSN0UD+H^VX#QeW$qkr6wn+)3pwD!-v}w^2s!(M$G8 zr7x3MkE4l#K8LhHKNqBDd}?PMY7umjy&hzh_zIPf`bS8vD3_#2vMXXMPUQ7q5nc4j zrid*`Qg(W7(5VL^ABY71A>uzyd?#2L5gBoke*clmpNul{6#f2RDo;~+hMqsGm#kg~ zlBA5DVzs_yr-CYAe1KrDb*;V+t<@28tqzCQ$`$b)tU`N~)m8r=g&JR?zP*xELGQUg zk{*^KQRAyrgKJ3@+2D!1PUVfHzvFpUql-x)8@}Bds0ye>igX^hhQaT-Ycqj$zIMax&DsFirs zhY>Y5JIK};5f52MC?}QCFC9oy+3ZS{&R=NR@4}Yf8x@UwJ|^<5**&B1p+LVUrCm;X zc23H>>DgKDrX;23bkEJ|mGWvvPF}~%cIjO*v>qLEa?`U@8YjJ^HE*8sZvEJlSJE@n zJLaUPWOaHgCAn96&zzjh78#v_9@g%a)=B#P@}p9zN)McsKT`)OLzThGAL>eFjj~!9 z7QIJ8<#@~3iI9jJb!eyYw@m#F=tvm+~1l%sP8l$%lRQn^3M<;w-~ z5P5_=MxG|mkUx=U%X8)V@?v?Zyh>gpe<5#@x5!`1XXSJ9W%;^%M;-*Rp~{EKXl1-I zQJJR9P(D@WDJvnpM%fJE-H<-0oKSvKZb16B@&UvP)gkI|b%Z)n9i@&@$ExGhN$M1J zDxhYnpQy8dHXCpYfcKfYTwSTIQdg^M)V1n5b-lV#{ZieeZc(?YU#a`l!|F-(NA)N5 zwEC-hQN5)8feHXM`tsKH8k1?sR;UX5cBj%#pStJi6* zybd*6kK+a$H{$puj+=1Ytk-w5ycMMn369K$Il3*KgPiTWu#J|j8ZsRqlnL@uWup9MxkJyQ&XVH+cuCo4tkV7Vltnr+0|D%R5y4#yd=%TVuF7uf_;+;qH;@2=^%U zL-%NPw|9)X$2(Tt>m8>qt1({P=bfNli<_ukkDH|4h?}f_>z$(R_fAz0c&Dicy&tKE zywlYQwPxVwW3?aFg8o~0FI2aB z7pY%)7pvR6OVkbOQgyrcGxcllGId<7&+)SyYs3n55Y~}GtR#c6mi+83QvdL-QLlQ} zs@J?I!YAx>DPvuF}3yS8Kb~B5jYlM%$|nm-ngPDc`CiGBd!|Db3h`O}a_v%>rs5(ymK^-q2QzyvB)rs;6b&`Bi-J|>n`=8XW)Yb5Xsc{Dz-P>S_71I;+<2 z>U8-E&i|p_Rj%Uan)ZkG@b+&w0og?2C1R5^cbWl4Id5qptWJ0oq?+flB2_arG&YSbmYV{Yxbbw^4P{tBC­Uc-Z}T3 zbnK@1OgzrG{=*&$|7v&6$gI|-t9~v5$4FN`GZp^nHeECIbCEbkx>i>Z4DgF?gN%^< zW7~J6tDF8f_@LXQzpJ0RPq(>iI0PB#HaUItGx#7G;+(7z^tAp^w@K@yKQ5))_*fzQ zV+>{L)QgRME>7nEVxD)q8#IW0J}&4SdoreO-TL+G%W`a8Sm@SomXV};_gqri!1t#A zGd1q+=jA>>5es8|f9LhG%v+A3!|T13~||9W_3CiiLU#*<S4{N3dt2(PQt9E4E>em>rr_W8*a=Gd)RT9tk zl(a7Y`^+-SNFh@?XZPuqn}zuJ$;nCW*tu73?aq>xmX#xE|ICoI_EIbkuSpuR%j{lw zCb=tq@MLnQdXm<-86LGvlC-9MB&|tCZgQu$n&kC_mGL;KV{S)0&iX&hcR3{TV1!Ql zKMY-*RqLs=)->n2dJXEwp@J``WpwP?GA|dyt8VbW7+j8fxXBZ@D#f~DlF$?NFn%lk zBY)M~(p8M+M_+vai`ApguqEr!{QL0NJt&{mkF|_*rS)?a7RCLqYZ2(SjGmn{^V0BY zfVwfKW0&-t+>V{Q*X|~jcdh#H?J>26t?u&UBX<^FeOigF(8RfdF;MjIb$|Rc>V-PF zJL*U{hYqPg8#2KI?cvF z?`HJGi@=^8GmTlAnbAoX`uNqaq8=D{Yq7fgkoxpTFD68Fh?A0EZrrL(n--}#-BWYY z*>we6C&FIo!Rq~iiWj2NK~G}yWSn`(SQ5)h-F1fRa024F;@Mu z(l?2S*!Zb zGJ2+^Vm1wA7k*&&G|a{_vpYg8jOg5)R16I%5N`$y$1%fBLcE^oy;FPUv3K98;!nVC zJhR&-1VmqDWpmYuFq*)O<_W=ava)lzpbVRduqi85NkCJe5rdn6UBS~sc_%9)EtUW6my}-{PqQ$e2w~8XshxZDN~J$1GJ3Q*Os6pBg@SEH zPAbDrXBTsfCXIsORAx9)FwE(e(WQ8NJOiU?I@g9qfl+`yOu}u2TBJ5tGgbeF(W1X82cDdf0>32ngeg zVKKnW%~Dn>T^uZ6%!lewBUaQ$LN)(|3oAk&PS>eAdi}4w{&L&o)K}UwF{EHR#y0aP z@6k(db}3&DOqjL7E#yyb`7*VS!VThrDnk_xnl5U(z9v0OOKq5 zv4hQwt=bqtaK25>BSq)DoNj#Nu*LNoct;%<+8Ni`voq513M!y79(KE#-K#>ZcRFU~ z6&oSLm-gr=UnU0a3m`dRkd&3860l;Y_DIj|mX!w3;>Ig0wd4(>4>dj#_#FDXc|kCb zxu}5xAlpoY%I?+qUgTPB+G6Jd2ECRkD;?H59+z}8dUj1sLy~G>^1g53H8x^wQ9)0? z5*W*G`;E5$El}efq3cJ`BG!%u&Jm&U({MF6x42bV(;w2QAGB%!-cIcU2#*D(Q;^bY zr1X~1Iv7X#n#!kCU1%NAwK9XJ6m9-|=DtDE`U%kt?o{J%wT;199r2Fo@!k(wCqj{< zb_w;zhRw%aUj#U=2WS|Vhm@y&Y$^r~UY1Ew?^%d*zi9ZKfM3)&!78t(vBw1#PB#2c z>fyV(gBIvOeS?M=>KxiAh7oN3b(k}kM^Fz`hA$*@52H&5k7l&;Wk2+QS5sD|`v|}VH-s<86 zA7RH#`oakNiJBaxvnKx;IA`Ou(}W}5?&2&UE|r5Yzum>@lCjPc7D{JWzXR)1oOY40 zgj-%*GErSLQ5nm^6~aO34Chba+=$bz5sq-%iyJ1KYc@Ey2nVGz9Le28yGtzMtuOAH zq=jMQavSR;N@oQ3gCNRntkB}^FQVL`Q&k`+MFc3F5j+Tja&D~*K?t|NDCaILSk4y5 z75d`1SS~7KqB3qH@Q_oCM}bkZsn##k&)Kaz+5r89z-Ab82GHFs-Gi9@_a#!KR|f?H%X z$C+(xq1mV}G#lljrX{nsB36{nSlffOom*=|pyF*Z+5t;Q4vX5D#tWb)vviRiJ+BcK z%CNB5H$Cc^`&+>3ModEH-VFfXunaCFbMH>dD4i+44dpDi)`P^w%sq>*YduUHVA`VR z%{Y3p2?wP!oZi66BNj1p&qL?zW@9EebKj#A;OKdm2v9mBc+YK@xfhG|B{7uF#QLGS z?^AV!%>8||_a4^oA(?xBr-}oiSU`$G=3ZcD!rnVU_oLO#dCgBK~`z#aAOdFgzgoDx<&O+eKCl)btpKp>DhRq@(KjV zfta~3Et%kRB0%YkU=0XXyS0@BA!P2Wu{iE!izCn6SDL7dOlPfAj4i;}_I zWbT{zgx&}OaW1VlF&U$FD>V^HXHB#lY`fgr4!5?Q*u>0zmkDVH$K7s%69&>AVnpeT z@jEacbZh$wP{`a5n)vpcsEj5%OgJc=;hX@@F}HSeLm^8{!kQk)+#dl}C6C25_e!3^0S8zr5t6w-O3EmmDL)D2 zDjw}|5*IV~DxSavl*i2+`mH%URS5*8GmvTkQHes#*;RDQ5jI+abN27`oE=BcQ$&E$ z89_~tUCv%C_6&)kbS73C)vZO<6>|1kXzA}+kB8*!b(|_b2gMjt6ms?$8^u_siXJG& zd9?Z@D(38Qd~DS>>EnGA+_%Z&rN&0-tg#aT(#WGF5QvzqH-h{C;W~SQ9gv@ZP&xy8 z2|&#~T2lfN^7Q5=o~C9V{f)O4goDx1-PEx z*+gPwG2NU3ybXXXkJiJZbteWPE6?Inwg(8rIn&+5WTcqc)Ho=eHO{}m*2kmu_Go#; zCT8V*Oh~;sZk`#=7&h+_9ZF|(1)%Hi(eepR$jAGe$nwoR`h@;~a8NqK83vpo9<7jY zgnWF638&BoXE@=YbcQn;I3tNg$j3*Tl#P)*#;M{2D2^jVAs-(HMXQ8rBGnb8v${@& z@?=sL^YO_hY3%aFsl_xRK3=xQV z_ZV+s!O76P`$s+R#?dpL)KP}7KG|!Ra~BIuAt99E3r$Bgr%^S9e0v&N_eYC-dxjIW zSx}ovYC^6((?;!6Cu$3zHqWcgAwe zg?#!D7Pp@$pFUusFtU&%PQ-tL_(`vJ+^hXS`a&*!l26OyP#5RM4<;TXmp(;}f-?L@ z`4wE}z1lgic80jbJo>x|=Nv~pV+J#Z$ps=q89v!nkX`X=mkCSAp|6;zE}L2ONqdb@ zP==3k2Pn6^+D$?c^5z<%)QGit^=$OJ;kN*ieSgrhu(#y!HfviMeuBzz7Li(G#XIfn52do-5<%Q3(m< zUq#yc0zM;tTcS^zR8452J&|CMFF%n`IN*#$zAPsg!vv)>-*f^TaWT?p5R}dcViN2!=wh*Y zB!<$NSbbDCmZ~dc(XnXn-z>7|22K^dP;`@`kV(636yu#LCPJ}Mf|fv{Vm94~kFW%j zzA(c4)Z{3gHTjFcX_lZhAsjKUZU%^Rtl9Y|O`4R9^%7yBbcWRiSgjMZWWo|M?A9i# zWD}K<(X=HTl+JM80M6?PT6@9~vh3GQIPGn4QV0j7Gn|gVNhKCB(@r%>3&W-p5ukKN z&=myfL?Gte=_M0%BLbAp2(m!XBSGs<5JL9d1B>JDY;okDH0f@lGIH=B-(B4nb`VyO%i}y1jz0Yy`n&5J)^=?rHqa7HI+BMC>y%txDWM%v(vBOH{@ za3%w1BC!bB`9zblF`lP5Rh$mRX{0D*=+mHRm3qyfx}tPe*I7`WNy=iDKGP(Pu~?jb zd`bi;oe?Ys!NLS>eu6faIK)hSp}4FdU!RXN*VsbCKWQ?zWY#6biqaYDYOt)!ngEK)ZfBg%yDKQJM*W0=1;i=dbUtuf9Z&$r?St;Vo^H7ssgOX ziD^%xb^S|4O8Fxh(&M@kL;;Drr{4(t@!=Cr6{Df3__V4ddVnjhN&u09jicZ zK)Ir-CIZlm)tdlEPc>=+l+K#qSpe1aX*CGwNC0R81F8v#dna<_6CXHpsLSi zo!@~Cw08I@dPBtEOXQnQ<-0;Y-KTXT`BNl6pUJ0VV_3vChB<7!;aJqk2BTY;7<&R+ z*1N!X$ERfzhPY+D1CC{kgKt^cIJ1JC3Er|+>FYI)o<7t$D8uR;j`cpU`Vy0{W%Wfv ztSTNByg%}tDh`BVflupCqT-fS0M&K0W%V}^V34lUn*c}8AZh}X&YEBZfQI?BAp|6D zS;GLagtn|9B?Em(Kq#F7jR(+JpEjC+#4T%V5YXt7fhG_TN@qY*0W_Itge_~b3BcI0 zrjasAXUZQ#c{(WzTh??@nXg(iNg1Ux<+)Iv?bBwFxUgl-hInAhnuW(3*gOf@vgSDj zSOS1WK5YR32wT>oAb-&|DXB>RXI)yVk*_q%i>l=N&#?f=0ItS%n z?Hm#760j~3ldxr7L_>VTreesetjkUnuS4;wPrE{*;+Az4s{3inx?&;#&3?TJaP-`u zCP3+|3GM;tj!(NqK;o8l2M}9n%eqxEkd$b=@2J`@c$`XyRWtBAn7+cnZq>R#;as?=tCuL#FDlaPYRjVQ?qjaYH z7?dAL)GCpCq*E^JxPKrv|C^Ul|(^HDnM{O6z?lc?1pabe4fNesNo zsv~0XEi2ZkychEBM6Eu_3tN^u5uf^J8w206>f2z%|8)#MKK>f5fBbbX5O$Nk@Wm0k zp>~{&_mDq7+edAW@~^givFdkFJ(#HNCt>le{DX;sxAOO!7{GH<-x+Z993~W$;iDV_ z%2DDF-^M?R9yr5#V3d9Vbd-Jp^sKIqqvtrOqYPjDr$oEA@QZ~`kr2x8h0dayr>UC4 z+xMr@#%EbShy2mmIVWnrLhU@M32)t>w^6&`MC}UHE+=Zgk)Zgt{bfFyeluwcqv;Q7 zW|ZMK^DUsOweHjx4NGo;bv}>C2mB zg<(>W)KP}7{wUNdle+j8edUtXA0u^?;j7C~f6}j2Apqg+`6vB_1?SnK$KRf>Vj?mw zFDp(Eo&mzseyzG+t40*UTk}u*16x3KsEc!^nu*64q0ds&pbWohV!>6#dh_1+aoLPA%RZWf-=2#;=Vc81W*|7yw+Ri$J4F zh8a&VD8q-D2AC;+Z4$wV7l5V&!AvR{<|BeZ89vM>fccn6go{5Po5YP>WEQES3}1CF zRA-Z_aN%dRsLEga&m&co;j1oz>LS0kfP{sMK8qk6xahM0kNc?@g&`MxmO2q%3GwBA zZ5fFR7krini7&GeU*$x69mLoAwIUK1F7~Vq5-+k5U++YG6T~-?vT&hiBh-S{9p2fS zsk2dr-`QV7b(>$?O2WcLo^AfXMV_r90>8+!!-@1hNbm7$yGUBNz_SMneF4T+@dch; zHVEGe2$8N0amHQZU9K{eR(O{ZN_ zF7DNC=e3J_eH|yUdqi~1#!X0~0?{82MBhhty3`^3BDvVzwfBd_{YSw5C^tE5XYv!5 zJ^^3>_n4i}dG2#IF65r(#yz}G+j(B$o|mjWFWPzD;+{9GJ+Ik$y4-`WT+;PD|Qe6A&N6Q7+)D{k^q3BA_bjY-$5 z58co$FzcG?J=)YR^lLnHJLYaRXI-u~A>MpAb?4sQLQGl)CT})3$uf6m4?C}SxmTVQ zR;xhtzGSB_CH?V>(I4-J#7z#^58@^Tb|xdZ^iTi`OUYn6pYhyhOz0S5x43b+M%j5z z=blroJty0F&f%W3tUYJic`o9f^X*JN=O#<-OxD80XzkUOgYsp);w$akw{nF|=5evn zx<>2mg6-kKc3FGwFl%hL3wD?XJ7^tjzn$kv?s?4G^QfKY8F(6vdCJb@7asgvhzXx- zm$=CVJCi@T$@LO??W*Nc(pvA)D|VryJb@j`<*`^w*qn8_?uB^snfWO9uH+FnueNa1 z=XX_ZQpIE1eIB>-dWw6gR#>kGqCZ1+x>OzfV)RF?khuR0*vE2{7&{X$myQFlu$0ud z^YL?^MxK!UG!l3DbGZ`iJX>(j=GLA~?L6CZ&(_wS$#$OqGPxaeVBqwaRW-s8dgSbO$1YvkDl`+x`QZyhY(&T}~T9AfQR zXy-WwocP5onaUHGah=e-JEr~ z7KV89nK{@SScnFC#ib-QFnLFEli^;|QZm%eYdrTFh zZpVQAr`%+woykHjJrBUbQZmQRXF2!z%xk%nEV1)k$353rd#<+g+{!&SS$l4@^W4cj zx7(TQ<0iZ9Opd_BXzfE@tEHrqKJX6Mxu4<+C(YyHxOI(wunTs92Rm==dCshH#xB@3 z9_)&Bu*-Iyce&>+YtNf@o>B3E#&pGt6NwMqzrn<%zkI(x#Dvea2f0aEJCjGbNu_xE zUaJ^ywUl($d-P$u&?*mImAQw$z+rRN<$5B-n^#Xx2vqNh1hECW1SW3{Zc;75w3MiJ zUK;m$Ccy%$XCQh#veTE62KdDo+_52XvjX<<+{A5X;^)$h04yve33fg&ai3-hAxlX& zy#<@tdA8-At*t$i?L1Ss=j+yfEJg(3Q~vy6!_hshelb?p2++^>P1NkeWDZ)eg3CPst!eNt9lZcu%V<;WM}`AMLi zT5``9tv#FBdA8-At*t$i?L1%S6?!$qgm>SYJa`8*XD05$OxN30m+K8Xr*7OS9Zp#t zGc$w6)FQqAI@$U5;Y{y@j>cuWXLjglToGu(d@kEJB>Jj=$siuRKpY+G^w|CF{66G< z!$iL&y5A5xzX{xLtd-wrJHKh%Z?c`qOl~sW&SV};jL|sTdSuKB@!Sw-r={F;k+tUn zJI__zbGfzWGCR*Nc!i2WOnCQg=D|0jImOYq-p*+!ciIl8kkPnF@4u~fzUMj9+0fCr zUH3c{IvRHdn(#80y%-Yxn}Ep;9{s8~I`-?auh{uXiGdaSj_9{l_q%21SDO3Xmnf{o zhF@f&xQ27i2f1HaJClmsq`aNU<1jHs<0FZdYh$Gl&%=RsQn=@n)}B@DJfG&CPg#3L z+j(ldLeGSl@MekS!DG;z;%Ka6=M>MK+;9pRjYswVt8eGKk2CE~6qEkrfu=glO%5iS zlK%a6UdOrD(L{@+|4bnIDYDZy|8w}o=+Dz3anAB|5XlK$W9d~S1} zn~5Pw|4F?CuiJUv=MT)B2*0JL|TeEvc;V+Q=o|JYu>Df6c@1|#Gy_=Gh zp3^-yt5?da898|!Gux$i$D}SgCQidvnm8I%RWsS00IjU|}4l28py~=K7 zfqFx^t^BFXQU|Kr)#2*5YSYN*OXc$A0(po$MxG|mkUx=U%X8)V@?v?Zyh>gpe<5#@ zx5!`1XXWei9eEG}4^=)?Ml0i$iOMu(hVrR0Pgx0>HOgj)?1s!i<%IH^asx8Am4OiX zP#vvKQfH_it25PE>O6IUx=39L`ES*O>UZj4^{D!z`jdKEJ*z&J|GZ0*RzQ2DyaMVg z<<&SA;kX9JwK~mOc^#P6!h3It>FC%$89)n$MI_%ci^}a$6Yvn zgX3;_vb+b6_R7oUeX#o$XZGXF0h~FAGly{IJDfR;Ge>addz?86t{p8W~Wox*efh1F?Toq^R^Se=8_&#*cVt6yOCE37WS>LRRugViNiU53@~u(|@P zKVWqgR@Y#49acABbrV*9!s?bhO1=%tJFvV9%X_fQSFXwZl!xhWSYf65;y zx8#A!ZS>V0xlp+)4_5BULzH~UeI zD2wH}@R|p&`S4l*uZ8eh1h2))czKC3L0+m%ls{7@$;*_<^5=-O9FbNa(n>^Hg-ELr zsR)tQD07vy`1wNFEU!bv^@z9u5jP^@mx#Ct5jQJKlr73qWvlX;@|Cho*`|E1Y)8be z5pf41?nK00i1-a6?ncBth`1LK_bCJ9Z}GEVS*IL8`hOAqG@_qD^s|V54$*&BzE#dE`;}i1{Z~Z4fan(y z{WnCvgy@$M{dYvag6MxB`c*`~hUnK3{RX1nMD#xq{T8C%M)W(%K>03y?m;DAJ*)In z&nf-YpOpdXd8I)8MfpG-E)P^Uc?YSRy@l!)?_l+WJVf2<9jboi9j0#c4p%p*Bh>BQ z57n=|Bh_)WM&W0)`kgXH9U+fZKa|I*BjxexD0zZ9TArwmkteAaPU}nes066Zso;mb_d2RNkY`miMZ2USw5o9lfMV+QT3kk1AdOF3*_VKLivQcNIt19mVZH?`LudjKBF#^&w}Zk`nmiwo_k!XoWHKJBt6uKB{;P+(pJ44<+^uIk|L!>UD7+| z)~;K3q$K4VXKJTqr+3bMCms6*J~Ij%*MHbU;a}~}8JX3(bk)yA;27!Z&rF4Xx=q(i z{ahrDk*=E$2nP5?x5?ut|Scx4BQZdF@U8m!N|lC#R2o1|On8oIj(3 zp4K1gHff#o$E9?eXl5$>V+>{L)Qf$-UVWMWi+SGdZqOk1`M5ZKN`DYjw{HFVu#2r5 z^LzvS%$sE->E1n;ls53a>HkcPyZd>$Pme5Uxp2y%m1^}io7PR0q>ANAN$j~vQzQww znEo%g!PyDc+_gg6p-g$BA*j)rT|R8)huAfe$~OvbcxK0%{TbE+LI1cNH9mWag^EUk z5&VzaQ3tT+So2r2v!hO6cB~8Ddz(Ef{>S4{N3dsDH@q{h*oHk~c4$(Kjn|CK^lXoc z+~wu$tghJ|d&o_2CP#ky-MIQSQ(9(p&d$oo>XIuPS&ZB!H!m$CE2UoD7k41`lImYu9T~yPi8Hrfy27jGigYvT|}?i>t5aJDuy*PRq7UJXQ{}Fd4&{33G->;T9G6n=e5E;;_ zLIsfmf)Uc)G16%Wpg_cc=n&pEkcLFEU=|QZUL!;dAp0tdEVAz+0s%n;QDnymg20pRTH$*VLTz<($;hslNCAf6snXom2&KvwQYw*0`sjq-N&|%0JTu zrK=E)!^?t#^eLw=-bw6@Z@ihgwd8UGDY{yMa|L~v zXyKdwG&kazCVAVNC0%a!>!j^>RonZF;|gH-X|c~8>Uj9UXtDk5e{A`euyDiwR$JZD zaqNt=l-x8edXvJR`%Ox*6SY00=XvldkQ)Oqw^PL3A)SuuEJU~=y#EA;Cf`PMJN zl4`B~dZW`^Gp^r~%mOyS^z;N~_b$+p3 z$2PE9r?2^u!mfBkZ2fY;?`z*a-sgWlz&@=M3aaU$B2Khq^6lFO^j`%B-J@<%Lcu}= z8V7)g;T&VH^sLkXX44Q?glbpN0A}M=vs+v&jOe`F0EUKO#G47j394ZaE?!o!e;_Mg z{oIKvUKe%~RlBdbfat629Hu%MMw3*dgNN_SLKyPCTMa(V`6UB1*sP^wa?RuLq%^G2X^k#7A5hbY!4sX5Rq)A-&$C?O-}p zWnRMBrsrbm&dCd=vdTrkaGGj3nKR5yOYc=WJ{rPky2kZ+OJfwE4_o0@rR@U=U2rL^ z6z&q&lDz?!n%zGukdd7N(Yy41oQ`-OYVm$79bTaT__NZ39~-5h5U&fUZD1om_bZPWvId-(?vGya{U=;fex)Z1XA-eGm#4x zP?8eSpQ}Q87A}G0vHomL4lY2VIT3cdRlAqCSp8Bm z@=J}7-wS&*lrQ2#_63j}(@7$Qh&Zg+fy`iDT6QWxOB*jz=)f9A8)|GMusQUAc|kCb zxriYgpt_lGmEEiHJ;$_?I%DSo2K^=zDIC-~J{R@R>K#Z$j;dp_zHjf^*T&>J2ZB@1D4`|f)Sv3G_r>+LVL&kIpQF@t_ zUgKH^<49Xm*_3JutwWktM(C8H&7aNOZWQeuE}G6A=$n_rhRx%McSMW#cE~yrjvTR* zt3Nhu7GNL(9MuA}jLApJ(>ywWL4#k)gow8+#F<|`_#J~^#01VNKTF@^LUW7bTKL}X zkOkVPZ^-asD|CvrA*)l0(G6=Ymi&+&=|OFHk9l3n&rRuVw>q6rD|LZyul&qFdR{Oy zm)mOptySw&3kdc1QQE*5?1qq)C(ssa4{cyUqc+Rgj490o)qfk))~!VLCK@rMj+DD# zZX0_mmId19*^K$lqb>>BT0jYC#5}IkQu9k!yI4q`(rQ*kTZ7ZHdSwTC_P_-0P3`#| z*EY0K8q3&NxS!G7Q?0r&1l{PKS2>i>p;;ZVe$irGdaz5oj-8uF>jM+lPlPJn3JTPw z`TzEn_((xSEm24m3vLUEPgU+-4asz!iWMF!SfL`__eC|KO5$Bhaf`fyN%&d2iO0s6 z1m&|B{SI2(ZSp>g!HwY6$8ZhO?&&p1#8Uw9a01WgG5Yu#V)`6qvE5bqP3}**$z9AO=c6r~#6ctWUpSLn5lJ zxm)KQv{5|lRPiS$9*a?qkSKrqykl&H9Wm*1BkX5ta+J=R{1@Pyj!{k$4u1>1(}1{8 z3Bv3adMC@qI!jn6onieBtP3&9dBWmuqj$kXb>2j!FAJ9l2cCM!7;b+^zJk znQ*Sy;M^b_l+JJjcY<=8SoquN-8M;c!^Y*-*GZJl2>u3w2)DjM^S9KCaEDJ-j^G|5 zKf*?5t9P%7O20K(6{i@rfKk(}Jm6NU5eau|y_#-g z%Xk0;{9LMLV$w(LL)1hloi&jRHqos->{jX!8-IH}(S-Cc!>wb2BwCN?_F|!Em3lo(bw%l{u6`){NSVLop3fwWu~?dZv?2nO&Imey z;CZ*w&aJc|4*s@#&-2R)ZoAhGXTDY!noU|3wn;2*Q#NZyVnykUwJTV=xRoRVuQI>YG?oP1*8GxvOS&Te(ggl6u0Gy)twZx8`W zX9RD#?K1aLv4JFp(wW#hsP5ZTT`qHf8|}SE?f0`^bY^;fdh0+<; zhrpWVR;CaZm$^?fQB5&X=^OeC!a?Z_XC83oxRu$2!)5MsOgOV`aOM*ZN@qArfU}5L z_{@EgNtzorONjubGlG>MSV07Q=DwnAf=`G5r89zcAXw{GRucr5xv$0IxK~{qS?0dl zM5Sjs>z!hJ35?BdWs_UkNF-e5zL`zvO(5Xs(nb@LK5Dm86QOk0M7zPZ)2(cGE8B>T z&)j#KkhU}2Z6-KwAnhSWl+GBx2jhOXQbK@S=Dy#=S7M^lo9rOrpmc_F3^+&J%3;Fc zGWR1UoWnLa#|a0eGn|vaIYBI3=6=GYtdHkYP8H8W@eC<)nfnpoeq0~|l+FmQgW#%Lx$IUh5eJ{SU*(q-WbT)7W}mvyu+05Z*{pvO zD@tdq6+8)w%cI;OP(E{adBT#z;yb4C0_fdZ=8mH$!lPf&L0K-W8Aj&*Ah2q9EUvlN z@DvUHPE94kGWS}fjMAC%!%(i{QEHPopSjoZ7#C1#n>n-xNqZh45R}e99tDU@6nxGu zqgxKCqa`$F|3S;yar8V!1Sp*mJmIm+*-OP5k{C*7VvSMVMpRucXK#d-{z2{Wu$;Y# zQ^lvC7)6R)&K_l>80}Qi1H~AR(ws#3oIQq(t>z|ue3FBQlzY6?*eIPfc052@dXzW< z;j{IYkRQxlXOFW3@)HnBXF$&bsGUb?LqJ@f-p<6+#>}IA@YbGiP&&g&0!}B7l1MmQ zp5DoXlW2p}nQ%}#!+8ZbU5SOy)4Q6b^`Y`l(nje_I{@wOq|ImO-R-nrC2f?>w0lE4 z=uvu-JeQjXu?QZ|PKP&#Xze}Qd)N9pfT@`;Vl$_JQ``ZL^oGn_tb-Xc1b&gcq3H^`$D5E_?{4>FMz zn0d4b{Vw64bcXXjaE5u5BEsSF@nI&MA{(3$goDx<&RF1#CKfIqA8k_BNAftQij$x? zffTuXd;%1$5~|5mSCr1`It|KGNSV*ar_nB!4qdz6{P!RO<1 zjHLvb_-wrXQC(JW^?YX8eDjG9r8B-2;9KTVmJl4DgD(qD_KKI7#t2fuLs|}wqvvD7 zLity*67Y8~|D*lQOOZE08RE6bzlV5>1|PG?zlVDD%pYa>RYyT}gjX3(!hG&M!fWK- z!_5r(>NT1mP?jHJ0wBf_0iSn|^A;5z56`=Q((-N`JrhYCW%<>ocUxR8215o{rZ2$s*sL=|pV~)Mk?!mut_qQJd>TZ86jqdX@Pk$miJ$**KbS(xyCn z2{kav@;C4&fcV&}EGGy)$Nm`7e7>;U4rUd>pe#SkXMkDfRn`&=mtU_lv8*+-Xxs4y zLP1%6lrMp@*{f_K6fU>kY(m*&gR+%SP?jHMJ5aU}2cK7OGt25r%ns5;S$^HU(A`bC zd``XFPIn*aqAb7eLFgXvD&LVbmrozS;`TG;)8CmW^ep6%6Y-xRe%z}Z^(sG-K9@@$ zXVda1)cLvbqlrh)rB6_!pe%o*{0CfTy~-J{a*DY4Jo>B&=L|zVWd_rS$vGlJS$?w1 zAiLyME)o`(LtipcT{N?3llBUspe#SiEuh@+D%S~x%b#zUP_Emc+$I#1*Y zBXyMJSAP)dHDZ~Vri*BzFZxzPf)&mf7xuchz(`=*(9(%606iDFg{m) z1Tb8JR$SLKCXg#1*K%bXJu)Go{HsWNpTXaV-xTO?#2<-EQ0m56&JR~$X{2?wP!oJPQDNGyEz+%OIg1r5)h zf71wX#KlOxK~Op)h>Ekzpi9M?kr+y6V$D(AXsRxkMMtB(f3wJ{?+vg}t(I9+XUk_iW; zGn^FQ1c-&tv;!t-ZrJo70+h}OdV?TH1bogNESn&W2v9mB$Ob`XoYIFNxa>OiBeq>qV8&%ygT#TWpL{&7lvoRUirtGI%}fAV0$M{ zc{@%SNNjvA{*DRhZH7D01jh}eLSjVejPZRi4vSNY2$0Llhne__OjLT4jUXJ9&Tz&9 zXKb7@nsB(xe5?s)v<=P#!a?Z_X9{p86APD}Pc|v*<9Vu6#TihXPKsQHJ{^iysn<-Z zD@tc|odf0Bq|9gOvrW<%i>2wuTp~c}j9?iEmc%KG;*Xyjdw;Gvy z4PSy%-KSLX>B&3)i1zAu82n)F5$#oQW=QxW+KaU3l;h~B>C>}Vl+Li~0IN1JagS-Q zjcb%e7LRGK>r}BG6eXYX2#NBKYL}ooo*vcyh=~A$d%V^JIC>tXCP3+|37!Pd6F#Lr z0r8J(e*zE%^tkr=Wdk)LAe7F4o&r#mPiaCx{3F|=LV%i-4HQj4D4hYh0n~zMxW~4) zFahYhj)#;{I#Z5=ax5uxk8Y3UmD$t0pCx6K&Xik2+3!<)B+fm)-4Ai&@$Ejm{z#oC zVUKT5a0<{K0MGf9wgkXE!u`1rfVMUO9h?Fr0icsl!R>|;?@tmQ=N{wUDFh(V1^{;x za@GYe1K=f6=N{$$5)?z$Cf50{Q0Jp`rW}BBcc0RY#JR`0clQ~ObMMAuu*bQ->Qufr zsyGCSg+65viSk=kAyhZemNm#k0GbV26X581kD36bvnCh`p!a>sFaqMYtoH%2 zoVKiCWdn^OAe7F4CIV=@PZ>)<{FXI71ZZs8K$8dvr8A&u0GdKH+?F-P1fXwO(@7bn zGv!%Oo$E?`II>%&TU!qAZ~0~bMX3eb)JN6Sqq&4EC;|+ zpR$+$xGigG2*6?+fE7*wRs&#_PgzL-+?KT}1Yo5Nz#69j>j6+q>fDx948@SOiFN*G z)cGi#b^c~3Z}KS{Nu1lVHnA;hBagwB$SqFgw?lrLPuWWH+?KTs8^dOGV_;j>RvU~R ze;wmf^|!3u#+LO9Fi!iF6NJHUS*O9VP32%))(M>1p`HodvUX|fHIAOM)Hx{sYUl7+ z7l3u1n7A$LJQ`w`Iu*mVtcy++uR`&%Pq{>*{FZeYswK2#T{01XrbKH396i^l2~av~ zf;#}ZoC@vTl?OB*g2#`J!|NbWePOa(BE^0e7}k(_4Pax;wrUr~+Q| zeZ;j;MFK+U45%`IB8i6EvLa0Y`j&McDWi0zTn)-qNtxTSs`AQg)v8X)D4i)k1my?g zl^P_@ZCMXO+}N^e;PpXuo`h{#wVeWp0C+fFsY3wVmi2H5Kph(Z$tgg606Z42)FS|H z%X%yXpq>pt1E&Cu0ML-sxh<<96hp>6>wJYeAEmR-e+tS`@k$dC=eDei&48goOEz^7qFZALW;r7{GH}+Zk~593&K!?bnkYl;uaM1eAOIN<~89KB~Xhgi_H4r81$QEI&#$pj0Ie{$u*8CRuKnR3~+m zY~R!p08sf(m&3WoFFs= zLIc0@xL zgOWffD9exXJW$#Z2lr8YJCmwDcH28qdjV=4Nsap$z9ZDEQl?H+N0jBSV;86&NSZy<3AU2)JfJ^*}5P4U#D=QTn?SstVYT88~LkOumd0ffX~5E=-i zKh#!Y7la1j%vJSF=mnwcTGol9r+|=9mLF*dkP3;1yBJi6_P7r5@QXq3IZ+z{wc&nc zC<*cxf`&u!4qXTuYElQu9j)p(dPY*!QI@~z696;LuZ$rW{vyyg09>StKx4{=nMg1w z%MUXhFjM`?2L!`k0Gb*C^Fi4#9}*18^22-tm{~-^UHqA464!T;Ii!lR{HhC}I*(Mj z3qSLCRrb68LQ+Lpe%0krUFugBlQ4JDXDNh@i$06-`W+dgFzlkw3Mb;LA->A5tR!*n zg3qcD@s&2>Yn+I0fcSd9QcU99#h&#c;>9-N8=Z)6hWI8@<}UPXf?CMB!#aBlbvDZK zclI|>{o1c=C1LI&&)0tABF|PHfnDU;?nHVYr1$uhog~d&;Ms$Pz7S)p^a9UL8-#B; zgbJ?DV~oeve-^_(pT1&MdX)56%w$W9=>hLw*m><_Uf;x6JVd;<5q%%oX%7HDfFJbd zU6+K#{fA+Hn3){3Gx?cG9|JI+*P=ZG+9l+s~wehnPZ5w`p8F;I?eVYIecuv0$RL=fh@=I(EStv0zVF2di)A8O=PStUa69 zd3xZfH)abvlV@4**f0||*IF?XpPflZX7YR)z1Gf+N!ND(JP6~W9K=8c}}zToMPuW zpLx!)_MC0!xs-V>vNQRFnXIrgSq~Gvwbxn>$``bXueNjF$`m%6$HgY=8f~--wuc4V zY3;e)tg+25*g+O-zjd$@JI~|H^N6+QVLQ)L@YEaggq_K+Eclr)6E@c_Fq3n3CVw)M zt7Y`sWy__clh&h`>_SI)j2+75u~ok7 z)VA|_jCsjcSg#n-8+XX0hjF#zV4lIC_ke&*BC6SkjL z(6W*^JJ0savz@hP8#~X=%(IiVXQG|wKbdD&JCj$LNq0MwG??hE9rRdbCEc{4)6>p9 zhbd&6$3>=fjr!OHdy54dVC~u8tdVaQ>|GXYkae&EJI@i!bC|Vfk)7u_ck5nJi(_ z3jxe6CG+ikRxzKCy_QSKay!or%yXT!=UO|@t;}cG1rBHuJn; z?RnkKGa}Y#Ojj&Fk=W4vJ4{@z$}X4dZ($~EuHDB>BJE6SF_Rjx_Ptg;)@mu~srBgn zcA;e!`VrMV{1+T`&bnN6!@ODb#5kjRb>sLJ=w(da`po3fIMY%h+j%L>t6`i4R+bUH z8QEz|Neld-5ANu&xY>q%EHiQ2nfRG>O8|3ANt~U}^USAhT-Z{QrnO*#oo8p}*~!{7 z(atlOdA?%p+11Xo2lEWrnWQn3pq)uynCPvY8D}*pbF_;0v2%ZuDfBmwi+t-E<=O=+ zWWnCC_I%r{G0-m92o`LZb+95k&k4+PthMK8JI|@`)EjfMoyklVe0rD(n`?8K$!t55 z<;-MB8NIehoph$Gq@UKK3+zG{v(T&U=B&%LD$JYB%$h!9DXH!gdiKf+xymwF)2-qY z(zw$@a9W%9b>XTvUTvR{k%ng!8&`LV43kG$bjc^AhFFZ(Vn1T%*NFK&!TS|xe)aAA zqM2Wmm0uG(KM(V3VQ2CzGl{h`Nq~voAby{aou3y{Uwt|9g?WBtv{MJ>`JA<9TRYFr z%(IiVXQG|wE385zavkH#HF z6JBJp=fk4!GEAtsf3x$s$$YNIhb8^TwHCZ; z=Xtl^m^pX(Ej|GIm6_+g)}9sZJgYO$s&*z1F_W5hCK62a)_&M;mGqz0DqhFV z{Yj?Kz;7BCk6YL1QM+JIvtZ4vJ)4>}8rubnW5K-E!Q6J93Cz=P?dh}gY!6SpG27Xh zbYj6fhMBOr_7XEmvNL&=nRG9s*Sh(wlK%5rkG^6T`ZX51x9T2#{Xm_wE>|$jn+@jz z<~H!W2UorE3jO?saosQ($)XSUa~sVaE%s15zlqFm9Pf8g z^BZI5_aXC}YUTHVo!=bhH_OgsAv2k0XR-n&dV?(WTW)NN!#rL0Q&X;Co~x`qSK4`Q zWS;A-J&Wx;x3CIr3NvBdx19z58qLXXY+LP|zGY5(;1ss8MWDtm*G_BSO2WO`FBO6i znNy?2*>fG>JF=&CO_^-Xr8? z9jaXeoq=M4V6~NtEF|)TIsO7McOazl=e!yrN#0!>8A9jG)EpH zZ<9yJ-^y(&)VolrKr9r8iQ~lS;!N=)ah|w9TqG_NSBPuGb>e5@X7Nk$8}YPwRlFs> zhrq+7QPNmxqBL2WF3ptYN(-gckXa{ffyi#i?3a#7ze(31b5j}ukx}wk`2%^TJWHM} z&yg3(i{+*A3dnye@0Y)q56Xw-pX8tAlk#c#p@OGfg77J{SBsxQeYLn2$6_4U;kaI- zSubt?(?%RW$8i&mU*NbI$1NJ^7I7}^RbsAP@VD$^E&cfgO0<12=>UUUOg4G|ex(ur;u(}GX zYp}Wwt3P3NLmVUCgyk(*-iGBJSQbcE#CN2t;vngoI9R$a7D|7L?@BksA<|9s)h)3| zx-AZs?uf&r0`%KE()&_@I0D}zr9tS$!P01{P#Pn>i~bxUjg#J!#!E%g1oZJlX_zz# z9+TnmfiyyzB8`-$!ebgdro-byc+7yuOnA(K$830f1dloJmucPxE&F9AmUC$ z+=Ym{5pfS9?nT6X(qQphe3wWYr0)=UKO!H%_xFf?5YZ1I`VWYH7}0-3^dpFV6w!|% z`f)`63DJK>^b?5wZ$v+d=%*0*4q4F_tn7q|HT>i@YzWlX!g#5WYQr_krC4b``El+4P z2H#`l@1=3_NO8P8N}M2%7AMMM#7Xj4ak4y4{6Ib@PLaopQ{@TbG zhu@|Bp)^3|9v^0k;R@e)i$~=p;xT!tcwAm4{v=Nkf0kE?C*WZrXITAQb3l z8mHz2d*<~EV!y!kDcHFFSAEHSHSU?7@o2B!+PS-Mtl%n8O}Q`4rgw&Rt^$q~T-Pge z2KYgH6MRFnxm&Y&`Bm+Qkb@Q{cYt;Ve?);ef7T0mTYIV5r1sEW z-=o>oQ%$)qmEqnd&7zw}JteZQsHffT7A>Nmj%mS8X)mIhHf`R#xhO_Aje7cN?aZt9 z3c{T`E+KWuzh?Y15Oe#JN^=h_?yzL)fz|TkNt@SC6NKuO?h(}YCQTIt-iT@bL~@7po;lgM*}d{aJ&O^O^72#Dvy+=OjdCaZvokaEv(obhB){ZO z?wp;Sk(=Bh2`{6f8#imwxS2aDs%dhM^sMBz*|~Wy$28aSou17ar)FfxBBqO= zOij-alwSY$+$md6l9GGo4CtGejrjNu?x-& z-bw6@Z@ihpn5N)rl<7oke`R4)im@g3crTlpHTNkjc8X?EA&D$jNR)0 zC|L8la2X@H)=QPKP}ORvE?2b*?#3T;qkK|3Hqy^k)Xr5~8uNdyh0$f{Sv@oIQ<3XZ z7v`q)3g+gepzG3vs;)JoULV)!{k6S*dhphg%MGOHY6;F2^g*J9Z~D{Rh-aGQZEu!z zx!tdmw%=84?=y}ofWfE5K6j|&;RmC|_Ot)7Ny`QYmuXp5IzXVIFwfgIgPBYQy-SjN{ zij$R+q0i8a^d6efte3uus66DxGI`Yjxxt6e#YJ?F5fWc$-7zVteIU0_AUCLf2!;P1 zz&`20%Kfg4U$cb$p7?f&I8#Mm4kLv=KCM{-xp@J@*`L(;#daOrz-pbo;ztU*;t{d+ z%K^WyefxNy|M>v>tWqebriY3+(UQrxZyV5m5gc@nx03wESjJ?vcQUjPx zLtOZ131$soHeNNm#l^yi&dUv8Xb48UnJ}E78usAgWd-{OvhvkWov7kpj{Irc+hsC7f+~E*9>bykIJ; zTm%fKsfLp|!`!s=UZvxsA&jPLT%WfzMgjV;6>e18K9JA_7s5*6E^#f{8*r)F{j&lY z*(ngcOYg_&i1(ou@5j>N)%wL31Nz7cwDNWKA>>||;VV+O--FgLgmJ403@~%EL<$v4 zgBiwbs1Da-MSRFr^G#ef;QDZeMwR0Azxc`vof88uc2&iYerXtAn@4$OU#;1N0@0W- z>qA?}pV;9AY9C5OB8BxaA(f#DhfEhrL?VS;e@0rML+cKK)cnj$WP$~c(kSZBRUthK z7eMk@f3`q9=c)a9jq3+>kd*d=F-_*ec)n_!#D&bt&t&n`@v%T_luj{5qk=yK_z9!t z@3Jv#_3jaLP9Ut0S=F92V$>|1J*;UJs`nnQM(O}yT{jAp%QVWrt1<>CwXV^CO)1b_ zxU(89gc!wH*{MM+Z&pjlN-gAJUl=y}Vm}16F>!aCI@de2?%XyJTYEuUl1Swmlw(zw ziXB?uWvoTnFjfDLON;wu$T0FHwMFRux@5#uE_C1QzHIqWr|C{Dat_80HZyhA#t4G* zO>!R1JLl)7v7S~J*In?AILftiPB1SgJ&50)j5Tv2>~^bmFLAN@rDWun8X>zE_GlYvp+kct#l$7Frq-m7oK*rGz-e$g1qulx13|IMiJ z_VD#1WD)B^1LqLe_^G&7nOEAXYSSOksPD6C0M<@j4TOh`=@g>$GAX^rwGPISwx+Tv z)f8HXG_8!#DMgzhLDvf&=zYCZD2v8Hp|(JDa{1ce;U))twi=F8Zo4fl)GSV8+$931={D? zjQP%^E(zLNKnZBXJg(DH^GjE|SV*4IYF0&CgVVEmWe0lpzy$71?fD(oHndS1%h*`B zpV8b?t-3J;-RPcIIh4?$Ssk%{(PCYCuuHp+otsDN0~1$Igeu(%3e=|g|Mr#mNI^s` zQAiXEZVQP|RqkF5$#k8H6&@>Cp(5S)MKz&H;$2H|gS>)C_*uJ!$Htfh<+B+5{#o2j z@;-~fZQ#|1a1GM#=ru@euiqNs^BDbZSt$SN|E=@NTcNxqM)`uo`5WbJi81by^o5B7 zOcyHQJ|^nX^A+KsbcVA7INuNpf3v)AVu}iABmxKCbl2dEurdiH_a?rL!jg1vsZ;l#_(R-$3s)ATCsbFuQ@? z$+EG|5*A8lSib}7LX2{ru(+G(T`*CdH&N-!!X?5%=?v#j;9QGQt`H7)BfV=ToGUgs zHwXu%GaSL4pxh=F{$_f&P14-3ak=$%5~VYOzkwjat*_Ah4fP`2;Zv0(xQ7T(IwQCb z1eM&%y#&GCRIie|sBo3KII^4S-D{%K7mzAWF=_#$rdxTytyCit?#6mG-Nu&j00{WG zRL#VskJ^W*iBLLgA{lI=TY1>6)FC$h=6a$D>0yRj#{|c9V?AO->5TD7Fh1c{>JuP$ zgS{tAeDzIKdXqIG9F)#*o&rvkTWLZ#+)ehPOgK$!aH0tZr868ia9R)xccZ-)CS`p* zdz>o9K{1vTxts09LeVPqdY0;n(pg>oQ1+2Bf5SbWNg89ZH2r8r1Sp*mbO6EgZl#@D zX+s?RP4}MXmlfP}uN}^Otu8d1v@C3sSlp&;){exA(iv-4uy%1PNd(H@c&`hvxa6=n z$uwR7JwPw-20F+N@vQiLpj^6WRf_a zxo5L=Ez`sSrZ2U;8AneJ;h=Pe(;qnb#KLFp`RJV8>X-@5-1le%IC|b70+h}O-g4Vz z?xkV_Nerbkv3F42x2d{Z=KeO?dym@hVVV0Nr;08r>McD+O5CKYO1nWSs)~&222rhG9i^XxTx;V1TeYJ^7&ve#1 z#rP5!o88JLx3ZB)xXgVso6ws;z|W8y!%gKei<+3r@h5gVVm?=&H8 zXSmx;aNI!JLyRb$F@6um{cfd%0J+S4zlpEJM5Q;`LBc`l4Cfedj<}V>gu`X-M@%?} zZE%hg4oYV@CxLT6-N)$mwcbFbkk8vLD_ zN`z(ZwMZGIGv$Y&T*sr-CUHJV6b&AXtL={v2uf!lj{-y{3O;9-(JhD6 z(Gr@o|DfgUIC>r<0+h}Op77Y^?4@E2NerbkvBs!wBdRW!vo}IZ|Dg7GSkB(Wsp3;m zj3PxYXOFT`jCQK%fntnDX-=Yi&K|?YR&$d+KFLwXmX{hErL)G42S`hg5=S6>w%!u* zgSqSMadtp{0z&Bw=y?FO^C)cyh|AO4nRwcmc`z>pPkX{a=?o_cIGsF7BH?g(dM6W3 zq76=G!a?Z_=M~^|B^EwU?`oFThsr-m8>KVt0JOW4HlLw)x6^)=v{5?K?hWmrN9jrO zTy7r3B6wKD6R4Mo#XU_VdKQ!B6yS9LWP6lMkJ5)2xU4*zP1#Hk@N=e*iAhf}bEt7p zI%}MNfo*_C>F-hUiH*<72bhrhGu(VLoIY&cB07}L=n6qM$fFbx8kdg`GLaRSd9(@r zF5#ebhVwpfhIy1C!r}7qVJ4g+8=Mh@gVGt!Sm2B%7A_wjZBo`p@;Il8lb|?(6uEqS z0u-$hs>xJWl+Nlp4a!qUna{_kn541Gm!=lei2$WDf_WgA<56aNl$pfA=i_sXr39Jy zY`p$aT~=`Qd}i5v^NA0oGrkqzTjo)g5FDR_FAGohikFzi2vWgAS`Ln*=VQV``B$+L z@OLl&qy5cGkvBmZ;3&%1xp@@^bG6Gm#2K4*?J$s%ViO%3iNb(G~- ze-P?5VwLK#%KgN^=gT!>X{kWITph1ZP`-SB*=)6l4Q2V+B(OaatJEbhK39GOFkFIG zT-P)vkSib8a%CJnG9jV-t4MpF!QY7A6zFfnABjs)>c&~*%XQ<52A{IXm&G`Jn4ol~ z{5X^!jZp=b!s1N&+z9hilcRLjjl8gvDjpolI1TCMrFn=}b5%o#Au?&MR?BSHj`4>{m=UU2SlZ2?wP!oD|>$ zh=tFz114#1*z_O*l+FlxgCIx*e9j##n;?w{P&y;X20><=(uW|p>^l>StJ+sfkcJYoftmdnZnLJ5Cu$ zYMjtS{)hC9#%#|@-HVnpeT@qI83i&KgSkju)4nfQuKRC<$*ARLs=aK-~?Y@9Nh zaJbBTtO;kd4bB9@LFo)<3UDS93zwZwHYw}ld8$*z8Bm-~id=?19g0?|*G#G_N@sPQ z1LfJI%xCGdP0|>PrRm39B0%YkU>OLO#3_s7lm*1WXX;D%Wd-^ABAmIRE;Q^fO%{~R zx|~>1I%8c6*41&!Dgxy*_toLaVeu-{cmeczEpx}wQ%qPW|0>q%mdM<<8ku_yUxHHI zr&RIj$vgjm_Ud>P{9x_@?NxAQNcaQVi?pYdm!LYH9@PGbi2#Fpyw(IbdLE@FKNXPZA#I9^&391R&7{0Cy8|)&(yE z;3ZP$9_0QK6hqb~*7>hc=c9C{9Ds6npVE!Qxre!T_Zbg!@5W=Whq=G%RK7RlgFdAP z$#V~M4`O3js%{MPB>^8F&zFjO*kGiU6Jw9DWxWB6em*6KF!(L2A2?R395=Lo0=pp= z=itnz>X|>aGkzbgKs3Y}bt+!d{$HN;M}bqt zAy6#zDT7Fq-?9p!x`DQ=K_&vwY|xqjN6&lI1Sp*~!AJnT?^A{m5Wi);4~XToWeqDE zXcPgVbOtmLK;wPNSOVg=tnnd0W6K7bL_jE=0ZjwY6r$m_tSKe{eao6o$|#*F&w}y{ zQs%a-8N4!EwPuqtN@vOopghl~%pq}Z%bEvqW6PR@*PpBNBy7uC=oDZ%0G9fc#RR}@ zSxZ9z7TW-p)Ko@i2yVuS`*;txkgQZ(peMS0nja< za)W^QE$bE_w$he$qii4{UjNM(r8A&=;uDm+|y3@uff&@S5)rnzaMnvgiRWktmszhyPyG1!(B?Nr_i zd3U_hoaDJJ%N>uu`d2pwwq-T9!HE6q7_IQZt8HJZ`aM+l$15cy%zu=>Ki>E#zr@4f2?b^OQK|u@Dsk{1(^oaga>JxLsiQ2vdM&8e zBz68H`kG~{KSb&%%daj%{b9dShXA;b=O6YL6`oZWJ@)Z@9TSoMai-)1p&<|&_?5@~ z%A-WVeKg;|Z)^dNL!F;9kD7S&5&9%G4a)L2O*FWg`IV-Ar7>~wAImp0;WTBajZI+O zzl&#L0Nv3)i%u>H(;C_bc7}$}7acfBfE^UpDaZdpDdpuP!9)sZXKp_30wi3G_ zGyrF=s%Jtk2wm5*P8>Z2goLvENJD^BNIcxdphC3Ab%=*w40_Lr+6br(_bWq5kiQT# z9Ex}7LeNl?I!NwlRmagYlB$lf{8gU-m~nn(48iahfyM#gB3%R;Q#Q;*fQ_D>82$p#)DV~t%7*!nU{IDH<|Dw&A`#a2q{?0Rna8WL z-~AVoD$4S!E{Ez;zp|Kwxr;taA#7aqS&Y~3$QXrT7kySZ5nm1QReoh9iE|fxR)vVK zv=Lw9M0^9p*ZY-X66Y@VtPc?{wh`axM0_*EH<2=Tp=T4+Le?GD*;}ZyQI@~6zk%x4 zeq}2Oa~FBO_8S*@w(5g9xU{Q7+a+mcy`(#e9IwJaD5(Q zJhc9^82;(>6|2&Nq`zV&TVhO)cmKl9YbW#iCdT3s;A6RkZTHfz+e3)YAQd%`+ceLK%+<{4$}*~HG%15dp% zTiBUA%Yw&-nXtLmikbNAOgb`?=ga7|c5Y0%z60oiZbpx`(R#FvUFert=q{>zX5W+? zJUEDr2X)T6TuEWxY&i8{-f3Yb9gNAF!%VWx-I;0U^#=3Gx5DaZL?1|Y+EOwIKj{7O zc39j*!~Q*HQfOx~l1UE-Ft?Npwey+Ce8z>3A@vbAF4q`4&l${fnziQ?JJ0#dbB?v= zY&*}T%yW^Q$tTQYg`LTInCPv&)^bq3pjCXeo%>d%u-QB=Hd)tbqg}8)EZ9zK&+TT7 zZFa#9vS9nIgO%8M9%r6MtUV9gd7gr&-k2xsOnzm-&xDzoU=3elbKvCqt`B5 zE+w6`9=&82I>KY@P%e+fQlidTm+MZLH=CKYn0E~izj<|rqc*=EVJ3AvrroEuo!4W` zOSZy##faXJ>@=w+_(AWFMqzRPY1l_IlPEhAFO!Y|Ft?O6xAXBcpO&7m{j`FXmBiV3 zwr8I0tUcS#RN3+Ieneo|~;bH`#gaV4mCTO!hI8-F7C2V4}D70k73k z(nA|~-`TmJU<$|0vo0hVI{C;&N4XxmGhuV>K4ubWXHtuq)QGk3wd%1}OG!_yNAI@_Ewj*% zsP5sv;HY!f<*FOz&8jEH8P%&B$G1Q)WAfH#CXdFMmJ->{OJQCO<1DbUjOfkCPFqS^ z;0JwhM~B7DHtb`WiQCS^&!k%dm|IHX?0lYQK5gT|mXb8B1rzK%J2THt)}D!Wp2^Jf z6>HC~cAh<$XTZ)RjhO`PO!~q^Z|%%Dt3jEgRlJX#`GJxAMlPKBr5n3L^HX0qVZ!%Wy*o6AgQ+nFq9CQHib zwMFWrGi4?Hv>shx7rK~*UTrsLU9MGO-fU*p^chP@b)V3)S60YXmcg2C6`zpCogRYI z+Ptp|SH1CS`-F@%JfqmSx>IDBJj$X=J|Q*4V!Rgn5j(#|%d3I)=ovb|* z?L1#$6?!SmgmvGmEO>V`X9k|bj2@1_rD)mZ>SpJZ#+-t1%1+712pLmLwf^g2=R1Hg z^$Q=3D>cuY@X`3G(S!v|c3@caHHOK1EP5e7IyPvr2if_JVt()Qe#&v2XEyTQ$EMc77F^-`(-tTCDq3i09XE#(5v}i?lPT z&P=M>nbd}fJ{lj4w_F=*gn1q`+DT%b4_kZIvGZ)eJRh_6tY_z`unIK{GhxjV&4Ndv zIr-7p#Lg*}Il18!HX09W{ny;icOPTg9nUBIM~$XB$V~Rfo09$#JFlb6>u|h9(tpZ` zeuC_@&HoI3(EIabSlrWw{W)fG*3RS)CVdgWT+;uWozG3?b3HyR=|8Tu;8i=%yZy$@ zxyx_qDfsz@WmT!nJnyyktZ3(1oq1NZGkJ)a)U-2^V4}D7!+xuz|EyN=I(F_)GKB_y z)3|utx<-%M1$&wWYi8}))U46iE?683=Cuyyw)0G2o_=djpPgrWcYR1Cf??ilI2SPQf$-+C z`#&_#0sgS0|0+&v^Zq@!>Wx?E=QoV&hRH}4eYl_7XzpmShuZl~WPam#zl)mR7(2fY zncq|^zYpyE<}klmb|wp%$viug6)@2oWU1eBV_O{N>AIhqat-rbW$n4r&T}L4TyO1J zZ0EU!RcKR~3G2S?Ecn-GPJUzCYUlJVbJ_!^u#GJOHFmjnTKiTK?$v&&5QNB_8a2+I z>+sIGFMn@YJo@RV3a`z}ioky$`#s5Ba)UX!$!`R6vfoH<70m6Em)$q{rS#nVl#DLH zUg=6^N^V{-C%JX2=aqKtlHX_^o%~`jBbbsKOwR7{T5@9FU{-E!M*H+0Auk*EP3rbWHk9x(1n>(h!J@lE=y)$TQ_x@@#pIyii^& zFO^q7{#$v!{JnfoJ}mzv|16)BPsYZ89CzZl3&-8!6mbt;?G;yv`(XDi z&XnNHcQ~^jXAa=Z_c(J9XAa@a4>)reTt7nZ2;Mo0caGtm<9P2Uy!$iWJAwE94Xcx| zIt8oKusQ>)Uto0>R=>jPKd?FntMjn>4OSOmbrDv-!|D>O{(#kGSY3hDRajkv)pc0? z39B3881W`7Z^805EbqXwK)NEnBV82-N!P@|(si*=`cr&Yx*-mcZlbSliABwFq8|;k5)_ zOX0OlnkX)pCW$Mg$>PV-2jWU;iueg4twN+v5ot9dtwE%!bzJdVGH-Z4oyh z;zmUL91%Am;unax84 z{xhPVK=gkj`bk7Th3Kad{S2c2B7G~Jl}e;v5&b`ieh$&kBl>TMegV-hBKq%$ehJb4 zK=jLqeg)C5BKkE%zmDjCBKi$PzlrF#q#@#MeBXgefqYteM?NDBl7Eo~%V(uR`B&*( zd4xDb-t2u(-r_Bizw{23kBP(Nt={4CSKjyKue~GW&*hQwHt#6;8}Dd&LZdPG9xHz@ zjgv=; zk!Hbmw)~a&k$eLS%S~x6zURqP#rg6yae+KtTqu7oF2Z|@Woh#`j8jmiURh!@Ek}>HSpR0U37a(^c8_HK~( zcsI&>y`Re~>u-|xdB2da#B7$Y#%z(V#e6A$>)k4sc)yar^L{Pw_imF9c)yV+HQJ8v z9rA2(r~Hw)OP(X{mgkCl*vLd}9XH3gwcOEtl1oSwSo^$6FUJAzO_XxS^6lGnIt)6s%Zpr2`+niK4q z*Dr|u0@tTtw7etda5b+ zr83;xq*-)xw_9XiQBS+wEm}lB9TUS&X)mIhHf`R#xhO_Aje7cN?aZt93c{T`E+KWu zTQmL{h`IeqrMZU|cUUs@z-syNq|NK62}1Qs_Xz5Hlcov+axv{Iw87OAYI8RVZ-;xU z>J34SuGzt6QJ7szp=!&}hF9&>W^bVOK*$%fqsCX?QbS2dFhakW9d&^Ep4$AfogH<8 zYNvL=o3E>{O21e<>In56wHxv#l-j7TR68`OqK?<}j9`vOM(*-LPIm8{luR)JXL7{` zZ^SfzBDq6)&z$Vs>|S}Ip2dhsdHJd7*~!hCM!A#y*_oO7S?PHLl3(&Cch1hv$W88$ zgqKm#jhnS-+{_&n)ik+BdRB7V?A*MUW14IEPS0kIQ!_GT5z|Fb@&@z`rlw~IO0WNW z?v$-3Ny$BP2K3F#Mtpn+Qc_cM8ut{G)a+bA`DePIbQPj;cv(=8J>~SpJBhvVjW-i} zG!vB8ZSkr@D?w>9Ku{9W^AdZ!mXMzXEB$q=l)MzY&i*gvbA*U24}nwvi-AjXMlDfP z+T=dftVQz}RPTk<^pxHm^7AmXnudNw;n&dn6YAcm5$$T)3cb(_W4HQ03f8@Zkr1pW_K7rhz`XLnldjR{S2P^lx zGJeexN<8uH5^<)Az8pph={~Jl0=ans!`YwI`Neh}+rVm_zT!s;JL3_t^~(XjuYLP? zpa1y)`>awZsHTUC_^Bn6Z{Iec{~|c(9(98f3Kk;JH~>Tpn5Pg-M!&E23 zXp(9)p9_|oos-7|Mc7P+O{7pe4o!hZ3~hpks0p&T0I9)XU(Jf)#3RZSElPnGQTk=4 zrv}*nJO~Ai@ix99W^rNAk%69>eFOAo^m>oBgXvV2c@bxuo*PiHgQ=`?5ip#l8cyU4 zbJNm$m5z^wFq*D$ZD?tX0`y@k+^DpDAfXE`gq6ZwsGmP0#9j?cU zn8sD}Ooszqdc>(*6c!oXiS*m&=&G1c6fo> zhZ2!Up*SX_GF0J^=|YJ}q>$s!NDFjm-64>gpP7kFu;5V|MfqG6(z9>@B#-rH3)FL- z+MidreozNVX+Id#WG;;7tHzzUkXiYeES@?(7HEx<7-KXl_(Oo7Fls)SjajRAe?;d5 z!upt1?MWlX1EsTvHLXJR-o@2O9RRHBMuBpfMtP4aV}MfY8V%T#0tvXY8ZCqv#aY>@ zK`d`pOUOzsEE7#0OmHzS(`*@}W-Com%AAF?O(-sjD_d5S(w4^GMz~KR1o_ zw7R(Nf_KD^Ts!9k^K#OI`0dG9Gbh4sw`$j!i`6eBBfr!L*}bqwL)jD`vM+$-m`)NY z+!covJCGU7OUq6LXldg`3eU5K(S{lu32Y8kGcO3{F&9zD0jiq`SJ}N9Ut6Y?)EPS$ zFzEM~Na1^}<8x8}tloiCq^LS3>-*=t`bLZ`D&*}Kjj`O1N#3c>O0coh<8MbH!x(K2uF_C&eb0qHXC;X5#Xp6ATA~!DNpn0 z00vDx%$A5ZEyS5$J@_4iU&J`hDnCo#<3e+b<68KjJ7j@2>Kih=*a{u6He_{5F}h*3 z#gZS=BR!}M?>4VX`MD{*?N+A~YNgKe?UkPyNY4vq=5kx@zqM+8VgaH4HcA^9gIyo8 z@&wvq?V$}UXw+sYn=z%Cp!!c^+Pc+&y@^H)sUzhsnA^tQie-WJc{XFd^{7jNwiZwV z8Zn3KwAB34)h-s2r?i??*4E(ktX|oHo;@&udsBOU%e4({l*TeP7Vc*>_a0W=7=mte z&;M{Jp+mDeV*R4Uy7XX|b{#u6kJbk!uAT^0x)l_tP4oZlEAf$nh+3kMC>Gon5}&Hv zy&96~Iu$ECRLY2h37UKqa1(Wczb_TV)mt<$u{|V)(wSHZs=JS>+aqSfpnEC^1(I6Z zeQ58gYQLlYUDRWH{k}rqIaNFe#RH@`EmZM`}FzN7x8E zY|`gO*l}udl+K#`G;mJFC?^Q#Z3CyiigOYW7b-!R-9Ya|*;r=?3#Bux3&1)bqx^@k zM$#higi3YZMD-sNmA))oBpj5^aIOL8N{sRc;fxE#xnjck!v^O%;h=Pea~n7}iRA;M z$DUN%=B7!S8#Z@{0Hrg62sdtW=+;;0i5$UQ?(nI~5!~&j`x?3(5>x`gy>6uTuJoTrIpe(3h} zv`JYX&oNFFW1;9F#YI$mE%ow1(JJ+NhU$vaSzUclewLKysN+=4b)Hej>9ZzjjK$LQ zBc2FQIwN=<1nt~P8@JM$II;{5zsk{$UsiC_y*4=WwYt!3(iWOcVsY!TS=$pUN@uKH zz?$S%IuYnBfU2or!E-8T60o@Bu(*?Hya0NN_RKpRJueX!%5q^%HZu1#VD%yt%I4GUr90AT@w{nPZxXk^q3FnXv&QZca=?v!taDE~dE_46Mq^ytUe>+t? z1I1IM$Yt)QplFqP{X%s`>8!5jp!_Q-^O^gvCTWbt()8mz5ukKNa1{iX-O44ma*;Ur z%>6RItRQp0gfsipg@$GB7t3b7Myx2EvAR47${n|Ii$M9z{Z4ptSbWPgUI4vY%iMAF z+~v`)r=Tns)(j(auK}#;9*b-4)jdUnzf)6*u*|(CDWi0zTnEavJxVPS=QH=(9^(Q^ zEi;F9ZQfItKu|gZkpUtS1)sBvo}$7->Szhg*?-V-b{swRhybNCg8Cl2oV`@60g0h> zCe{emZAjJSa`uL3=^xY{56jsVr;1TfY(k1$&fdgEv6)lF7$`RPDA6R!=j_ed*orpk zcZ zKp;pHH5x(^AQ}=#LF`Kr0!Z(@_bNRgB1I68B1KRT1eIn%Q0d73xifce_U`QDeck!~ zKR@_n?q>Ep=XvhA=iYmEcC!QSRELs6>ABiG6^r005tl4*Jw3&sM5|)DTNRKE0lgf` zn+_#|YT&B!UTn&~2?hL|$uMZrO3dCgIB2Z}=WS?v%c0~ulw7Kfugc#tNXln&bB*G( zw0VcBLu*al0I2gilnVJmH2EtK24StTs@yzyuJlgA6jerRzlx$ zhq9E4<7@Ec{>5J5QbUfQ6#Q1L!Etn~qO#EbTUq25jjyYpc^T})Jz|^z>hD3$f`MlP z)Zas#TIG*6c-9eM9qv?yQewXL9`4j@@1aHw+Uhluia;B@h;a}xhAQCe?lI1SK|lD{ z-RIQ08%M`@%8oX8_Q_7On!AW-3ME1tJkbnva~ka?S8q>4bk7B-w`W>mn+vwtl#Q#k zXPdCiv%S-A0!ql&*^5{nEiiD?I(sP%Fxub){0T&?aw;pR2)@Q%1!}%tSYak+ z4HbhncrlwHW|LFdK*ezN^(KRs4Mr{McD#j3K^wf39gy<5Q~8Wa;cDy84N^Wck+PFY zK^wf3FCk?&)xp=*yN$Hk60?``q79z+Ab7u`ynIdll^O3L%8NF5-fzHr%&8oq)LcD% z42#=&T2CJ_sL-mA6IRH70QniGa@whUNBOy0`V5gU@ADK|}|+@n&^1~0`HgDaL)2Uj~kFtBP_8xmuI?IEy*#b|{P zS2u^n1TKV1#%P5Q+Ti;b4%UY$D_=7|Y@kKWTvQsArtD~gXRieI3NgxKG0LM<179y! zh@ndb>gC7q_(xhVKU%!D$Eh~7!E1X8+N#AURjDw(R;~syT!B_t6_WU32DS1JYORc; zL!^?>{#!{0o8mL#_XPSG@oKRNO4Zl^^>WqNf`JzT)XUXlwKPF%jrnOX%dv_`$@!XD zj@4^s(Vzo)b4jgTadgz6a?o0nQwMTtQ7wG+Tq_p01of|;uc``gbUZ^9ptYvpxmdFb zx`-@_lA*Om))3vTPrJ)i(e)AUs{yL$MphZ4!PtZ{a+P!w6Gn$s#yBv>#wszCl&_{^ zS%$?J__+*o(U7CH7V;L5lMt(Ts2skoPJoC@B<$>yCZ6JDwWPApT9fr6WF^KbZKy1+ z!cH`(YGY8PRW$9X9JJQtybL)n#VVbs9IncK$snhbiJVuc9JJQtBtyHsRFdt6!e0EH)E9yDuS!N-^Aj0oh***lO`DkRa!NZ zWmU#okdYs&b2bw1I+tmX3*tBf9Ti<#S&!D5tp7k( z6{_h#oc70uqlu&{xJFqJ;3n-=tujhre9EO%qohYjAn>6B?>NHx6j;a88?{$6C_r+L zS3`iKL#81>Yb^w|A*iNHsX+yu&;?B*f@(s9m)@+sM)88`P(f&|391J{&$$$Z3OdaR zdd^3XQoNx0R1jKgf|@{3BdX?$IPEW!r;zA0G6>Li9Xn-4YmGSu%nr)@JDB5T!8?;M zJ9uVxFYl(58Lc&DH<(>6r5Pm`T-w~2L&#kq*Kgk543FoLdE$5Tc8^s7tstOyiX4r&AveFU^I5zyYMfX)!mk+NU&9sG`9^jVwO z;J-u%AFZ{)e+|s9x|EkG`3>6jg=Fwwb?G;Af0>uTZsz{FRr++$r@EA`l>Qv0UrOjx zu`#S58^a<=z}v@*q{6NyGP(yT9zFI6B^p8g9#)Y!IMrS<@&pT5HU+z&wL8 zb6eI7o|&y$vnexLYs?G5Jm00vrR3a}H6P^qmNgfTw~=|`w`DD|DqsZ!EORMKr~q!u zTIM5QiHU%fRt2nsfHf{S%env^UlJW`%Q}xU`^g#KE$e`~UgPMvOa}+;za1Q2)>X** zjcVeytltob17s@tZCQUYWhgURYoT}y%#TuLZp(UQfT!aX znF`>xtfzeh$R+}6S{3jN1k|SN+?G`vj6QkK2LD+)_-L&Setj@U#Vd6wIk#m+#p|!K z>hdz!mes&2y#w_2c%>1g=e8_+JU;bLHU_q3H8PRm{P!~A@$uIP_2aLHAmISz=e{`N z0NBoueE0kFv%@s@X#Z{Oi&(z_>#=y{2qos<%0CvbzmH+u`ei0C{eLK{5M1$6T#+D-25 z`=1cwi)5Vr{^;zY6}Df%cA2tqZ{1%uVf)nz+jX%05wHAC3Hi6}|6tklyMdd_rax(z z(FPypJCJfKUb#V~@Ne1Qf`A`Ls7I<-2S$p8H;R{Zmr6n#yrfWff?{(k52z&W?RuNr zU(o}DB5kJ+b89sQ+Tf*xL(0Q$rKDRcc(}LfA2vuSi8Fj=YEnv5DQJV2@))E%N_FsW z(?4pU<}7HQh=Lw-P~BaBt1mbn9C{4Y2cbCc>acON%-*G-!hlO#|qv=T@F` zD+<-czb#+SAm=$IRWS(T5~m^6hc$K7pj4O`#p(YHt_cQD>(Bz zSxDI1?_G-5nM`$}4PIwY=lO;0vV0BS%LDm4r4JNww4p z`vXXN&#m;MlK2Zk??KXEBueapP(PfxNzV9Q5W1~aoj5u^q>|7EFXfL7nw&{(FV`D2&@YzD|g{%0nf@_`!A-fXoF{63D)IqWho`*F8VA7v3}8KDIWKi zk%fL2eO6f^Uk~!NZsik7&Ry_X>qGvD3Hb&q9j$+?R?n|;VPnUHU_LcSg3 z+bA=4p=TS|eAXQ{*gNQ8qYZwrzXa=Ux3Y^8a~FAbyY-7ayLbugBF|nc)Q3TR(5>vJ z)Z7K0gIMSXA-9Sy@a#8{@HHnP)V9^G-?VfvR z&gw8{H3K`VVTP>Fkk181DrQJKkXkSsnVB?Y&K-UxY_7#KlV)Znt(i&7Vn*%xXiU1^ zZ_^vP=_C5QI-pb4$q(Gt78~8RMTr zS42GN<7&+Mtxqu<(21d>{LoQ>;#bzd-Fq4&LCWSE3qP-ztQnph&zRnE3 zlQDd5%!|(g_vlkIX9t+GeSwi*8aZ~GIs1k=I~v&8*Jj8w40$Rr@>?_HPe5wHJZENd znK{4UXTs*%@66;EGm~4))vZoJ9Q~h@QXGcb^QFkqTAPJCeN9fL^JBf z5X>zl4b3nvhKY6f?Wdt?RT5){Y{ihz2SzqGL$+tg#K6clX2>oK*~!f0b!PIanMrq; zXwgn}1gc72RTD484BneD^fKnfn}K_jVdm@|=IpJ&$b2J5u9>re%$YZ^vk%OW!x^$5 zFmkXNatx4KFh`o1Ok~c-`I)e}HjSA~HZxhkOy(9dYO~3tGgKu>>WI!XbG?eWUT!vL zZMLO;Xf`v4IQ4~Skdt3ZlJ&_ul9>#58kUlwW~lKDHO3iWDe0^M6Ir}g$@_i%6yJpUYGiL>Xoeefaj$_EtfsrH4kW+xvf;rL5WF~Vy&Ci6* zwRy~BwwcKaX0o)HQCmzVouMk}tB&YGGuIoL>vd*x)@EDdhh{UgqDx;&9&-t)-LrhI zvJ6yt%eaJ|-08tMt94jNHSP^K4RVn@Y%6d_3bsojbON8JZ_bW zD=@=NV7Re?aHGv|(->~DnaONsGQ-Sd5lpmfoF6zd=K3MG>2X@gkjnximzW{fGvu1U z$kk@Z&8$Nk{Y=>KZD-CuLpb?t{L~Dzmw|Qzpg=KU`|JC3Tpubbf>Fx)*J_l1hPV}>gkudnoB@!VRh;X>m1HJs@z z!*Gw7nUrTHkD8f00TV47ACC{XHdgdQp48(cGGw*D$f{<@nhg1LV5Dq@e3o^nwx03Fm{EJh9jNI4T^-RbX09`s>+S^ZfBk^WS(`1*56zPDLxz42 zXs){dOGWl``xX5+aax`Cg8|ioH_***7`Jtk5zPBAH@DF|P<(@ z&0x5xfpC+}aPt^$wwcLdX0pJ{WED)bfGl?h+}M`-A#IP*P;OwzwSkeJm?5_^X)9A-7m?Lp8IBAcJHLl8M*l>nVr(R zXDGc=a`V!2lA3#7P+GQ3>eskoQv3AG^pxE6r0i~QBqjDv&&tisY@N}~=V9I6Y2AeD z*Qy95E0w+|j*^E+!=<6pYI%dSS=uC>l6OkSrLUyJ(m`pNd`r3~-I3iF?J1;!W|sI0TM|OQWQ* z(nM*pG((y#Es&N-8$h#J+6j__pgAs`m99#+KyyzT43bguSb2&(Tb?7&mFLS#- zc{S*d$j9Xq@=5uWd`>YZ89CxZpcZy#??`|CT;P@qudvV-{<9-~!!tnr(2gRx4Av`)Pt`on8-4UEQ ziZjP><~YuLgEJ>^<|NL1i!YgVipjyftUltTp;EFF&~HpKr94ek+f1=4Ac^!mIAd5sO3Pd0BWT) zQCuZW5?4!;#ZROu;u>kHxE7w)!P9zp+5k@*;b{{*6~fbIX|c2gKc7lF#jWu889Z)- z$Isz$J3Q`y$DPtDX_vHG`a=3d+AXb-_DE}`FX3@7Jnno#?!OsbJKMC*O!uxmdehS`C!~6H}eg@vp!ut>Keh%Kx!~2i$ z{u8|a4DT1<{UW?yg7?eP5$TF_RQd(pe}(to;Qe=azY6bv!230LzYgzz!uwzF{x`he zfcKm5ehc1j!}}e0zYFj8;QhWdSo{Y+55VG;FG~I8OVR-OvNTY>A`Oy%kv@_~h=b)F z&LQ$nXMw!SIaEF?4wJud4wrX3KbH46N66dck@A<$QSx5rXnDf3WAHOpJ|T^hM~dU+ zQQ`!7v^Y^7BTkaXij(DW;uQHeajHCCoF-2Yr^^$?8S*4?raW1kB~KA&%ZH>nu$?RK z7U#)#v9R2e7T{;0JWX6APZt-hv$%mcW z#gp=7@mqO`_#L#K zk{?K?@$=Kg-v|3-TKAA~ao+*NT_% z+<%0}y^9_fgh%5@fm1glZDXG>+k*#!5GurVPfy9K8x=KL5WL!%x@kG-sd;_Vv0vc& z6l`oCkcZsAx~UnNPj~O3o(sVdHpGC#pG#pj^<$$eWrgAY-_&z%ULr`3n5OmP?l%4vb1L09cyv((Qn zPAC`W8+c;3y1XFNA|v4QkJ-`Slc#dTK(*eYbUkI zNX^O4&F-EjYE_KbAum5IBRi>nRK4gVcXqE{`B@oxZzpwjCw0uu&dg0}(*Y0bHLP2| zN!|L<_3A|>b<4;~YLT6r*Tvpgt#?xE*G1i36g3|qeubr~BA}J{~ z=k4Bk+3=5_T?7TyQ%-L@lh^}4crvkDeL-p70*~5w z1m*d+1tlRPFR|Mj3He#D(jI$K@>1|P`~R?>qY_c&!ExIEq2r>OQ7sge=W`p>Z_?O~ z?zKzHNa@igKM$!D<@>Lm+buknQ0;D|hPK5Xj6!|nZiTAejeUgW$mA-W%V43ZQim*8 zRlFteVQ#d~sK;lubEVXC<(J$4=U(VTmXVd3nV*JQmkwcWO84~Kyp+^8>-H4N**1>q zGw#`sH+4T(`Tp|1Ye@~uH@D89C5h@j>fC~`rqAW=tKZ@8mcLBe7gGLEQ_CGd@~OUm z`?l?=$_>TVbF1!rS6H(3gYxU+Ec?#vnUdR6_5R$T^L=L|ZF0q|UVn7l#yN}2ue0tw zJts%?-Aqis@qSW|XF~h-2!HQ#`qA?7|32t+ChDV`k%gBySt*&?49(2wrV`ERygRJS z;JYj3b>GOfX10nA5qf!QG;5aZj!TYe($>}7ozUv}HgV0Kb|*wN?ANSOv*>1x;)DSY z31PNUvug<6isY4<5F+$upayL{&0UFYTeXXWHU3lUFk)SaTK8erjoT$AxDpc++iDc` z`w^y8iYZAjk5fzz!_NbS9twP<-WtLIyw(Z)+yIQ#8sGW`2HKum+m|cSwEnBr~^?afh zLG-t!+Kal?eYe z$~L{Rt!|91QOra3xX@mnklvnuM$AX{#33K%<$IP34Y}0J_MXR9_TeH# zvL>AY;{e=FfDJQn_#D7W=x_)+On?ws8Cg9T&JElyg1bm?5-Nv2=I?V?7mhhF z7&xQAEB=KGZ@ARe3arUG*xjLH`<88=ht+1S5DOO$#KU9rF3E0J>(=ou_Y2AFBLsps zL30(>2sg;l>GN_jQ&YenqVYcplRe-MJ0HhvTDM5nuHg(QNfJWvE&#Aq1TkM4+L zGB(1&HoPkgvsy6QOU&+ZzOWhP<*Ea#`2#uZY3vlYU{=z>)p7{4M`7ZP0M~O zD>*Ye1*9QbLd<}_W2(Q?MY-I(efwlBjgvhteD*-_9)=nIg$v~zh?`D~?{+~p8v__F zlq_?^`D0Mk?@pgQbaiL}*KcW*VN*HRy|a6>1&7S@0jlR5_JwLZ6O9iqI3?eq)a|4l+j_orY*J$+ReIo2WB6giPUwu=%q zOvcF&Q)EzovUxq4r@g!XMQ?+c|P~R_3s)?gj7s+XO zovihO=1!PPtGd(ziSf!9hys=O1*cZ;VJr3l57QDXTa?)g_-z*eGy~QMumqov^eJ zV(Y><>dnh}({v|me@3nCpONr4LG|~6&no0EIcz`Ie-tJxY2Sx~iK>HGdp=g=#trp- zKkVHARsLfel%ors%`4F~EM~ zGa^%I3?DMCdil92JiU(ez29aV zC@EQIsJ=e+S^JV(VD+PW@JzkOE7=?@s+`H+zN!6ZeY{$i`Ls1P|i{nmsNLxjI8e2*If9*MPC6I3xv>8HE?M_R79a9E(74LSX{uw!#;RevPM+> zel=3@TMm8;RnO;|CfgEFs`$19g7ONG|(t|pSoZZ9u9ni#SiUnJ_Cgx}S# zI@)SaP`22$FZXM2*Y46%0zoX?V#n<=$ju4|sNZ}zKy0mjh0JGm?OO%W{@d^O;F))U zd52y3oRW94(_8w46ZRc;{oCX|H|T(-KT6~Kp2*Sh1(k!=nw))*^Ci`iOtj$3HN6#y zmM`rEgQk+ZQjPKXQqgJZy+Ltw?57IQT2pYyPQO?*MW?S0`qt#DY#7;LN`}@N*)eqY z2<>jFUAs+iBU)=3>p)|zXeE*g{K$7^)iUUdG^o--_6(JS)|#C9kP{WH)TMHU`O1kh z$f;{0rva6N)|wnUZMia-U{UHN~Jx+t6oHIcTlPSpYfnqLn#R4p+I)Gsu}^B4;6$gVvgyWstLkYT+yQ zB?f9PZI)97Xss#u1PWGB1$^bcs(1x!r~k?QBACg93goZ8d1pvUV2@5n5{@Isk3^qm{kU${wnX zuiW<=B<*E#_ZY-+iFA-^L~BjsH_&)2S~)@ma+UirgT5mMRa(eSP&sI=$vFc#r=ykc zs2r|xKW&inor#>YR1R8ea(;rG^Hd90xt}*MYx(@MRmRI;yhs_j%Kai31C?G^XkXD< z>+A1e{*^NGmHV#-YUE;3`EivhKx<9GEhxAVt^5_OT&Ftt%KZkvte|rL3unG23k|E> zuNSZNHr0yOn${3Uf+9GSf2dHtau*za#bMz;hJ1nOgKFiDqa)OzUC}`sl&o2L<^DKi zRdfWn=3dcJFz^^DCHyM)%9I(cHRftyuIf;ppyYhzUe%#rKzYKbqhR1bTy3vTg`l-2 zBmzPts)DcCB@D~ABwKuI_V3i19Y@F0Q~_FR3TipbYW5o8& zBs1=0%8k|xVmeiT z)|!F^P%zJ-%yB5Qs1Cj!pQkS+sKn>s@oBQG;OhCT;`J@0`p{a_w+i}JIFw~n9AAU4 z@GtfXml<*drQo+}4UVH@HI;?--^yx^&%L~^e&%I}GeP;t8KD0D$XPJ(Y=HW^z^PUK zXoF`R3D%FD$}mdI*WMpH_1b%wQG>R6jiMsZ1}|bfM2w{h__}+nvtZB<{&n{`weH5z zF@dt94W509)2!w$BAQBx&<0O56WyFnyUEqt(-GZs0qX5pR@ml&Z4PDQYVA2DZ1b(K zEd|?Rr?QX|@^$uNmPZQ>+_cVKMgxpC_yDhgh}BMIB^ANf*sDR!*9$An#H^)a&;~DN z3&a#Um5o#kS6>$zv}`nLQMcnysT8!qOW6r2+nvfbDut`9w;QBvGm)~3NODqUZHd`OdC>;XdkDM-C@)`AA28!ROnK1;&wB#A$DPViO3l^N$FaDbr}gwv zg9@z*IcbIb9LUc)mG7O(Day~)(r4MU{2uK5+&E>>qt(*qX;9DxACzC9>#|e1=v02D zy7)T!vO&&8CiQ2dFfC1frOMC-uk0@w#rl++TgW`&{jQ0d6Ej_Yvt+?!xdahvRld%En@T} ztGq|G@wK?uAn5}p_dSC+E|CUOjcBcD91e{`W0fIPAXk+SHRu~+P^E?JV=4!&H96xT zXH2Xzipt?C^DzcFqfF$Cr*hC*lQRW!CQ&V1bw0_!tmX4mtBf4jG{}a zPDziFK;T0M-f@Ig1nYPSd;?1tRyQbsn(=A~aCAh_5TLadf;tdX%cVq8K__)VlZc>N z5aA_)Mv8@z#S40d3PNj5P<;rBaw&DGpzk?BQ9gp|7B8p)6@=EBAUgy#rfPP_X@8kK zg+!;ZL4daFL{nz8)|i`u*-4qNf;nCmyfX>2lV_eL;cuexq$8FxqqWBD0du@diKFB; zmo_)%5b}7CU&6%*917#`cpfI|z-bbhClI3TH_fdIcmV=hx|HXsfQNhqwDb}1yorF; zRt2<&fOamWEfsK&t`2Gh+W81*Ya*b7RRJ$SKqtz6-FNUifw6$ZTw9yi;CG>ekJj4Y zzYgXkm+}fFze&5kkPLnjNwiM*DSU;O!IsEmtMuJLpXO3hDE)a#zm(9YVPjZ9Hiktc z-*7BUF_F0MLjSd+NiGAI6C^#!9g3; z;4oPqK-POy6Srl(hd^vBN((j~A6jMn2#f<=N`FeqZ&?Gux|MEO{S69`q+8Vx;E0dK zXuCFAYati`LBn0jP%4PuvW7#%D!OG2End(_DhRDLK@%WooJ$!)1@T+fI3Gb{iWfAI z3PNj5&@>2|Le+3v))a#PZOfWYnbBHfo(<-il$qPIX7bEz)tW<@(OP3(1m*=UWgaEx zwyXsp*SD;Bc)X3wlWF{xwb-hFl@PGpr7WcaxGihBkAS5n0#;cSupR=|x|C0-0B*}# z>m%S369F5n3fK$*n8`(Q$zY-@n_&Fg zrTj@r`7P^jupXsb)}ICiP;*ob0gjGaGz4g^h2Q}M-FGQ>sUUvKx(^Xw&@Jn3@q&bS zZ4X6jO;E{ryyF_LgyP#jAL}4Q@>^Dk_##1}c+8Ix7ok#A5L#=3%0N&!Rl{vr;RXTP zmQ|KAqqW9d9?az^Gq+`x_2wZ{Aem@CICl_)v4WmN{bzGYRyfa>welT-k=WmWeP@T7?V$*O>w5KtptiJ$_wEvtr)fCv)-wX6zw76R%}c5ch6 z14f^`XM?ZM!AEOt@Ed@+UcB-gCFi!RdhzM4?TlJ3^q?9s|Qie)F8@!bAkW!B7;NPY%XQ1WMqyl9}8$5dzus=@O`M2mFFP{Ag z%8oX8b`k8=-O7_x0QdHMb$7v_D`e4QZ_htzP^4X6maIsq0|~XRQLRWpa66IFvQeFJp^7RdJqL|dW24P&{G@|;@2CuIv z^f}#1G!@6aCGRw7i#90ILKRD;pbcIMZn&ek-HMA!;ogpS8>F~Qq$E%&XoHvX0;II0 zI=HvuTN+rk+-+@ztsU6fQa0{w__kmRR5HCt`-nF9K6V0Y2g=I71>eCyi@Yl;A39TZ zw866{gZ(wP@~T^TnQGwQet(T$Ht_cQt2pyJSxDI1?=Kgxvn$n!Hh7&G(AmSSq*Ian zTkky}i7V&|(+&9n!52u0M~;p+s3f$(NUEh)*dIdD`)=iJDv7@!^gbm0MWVzm2)&In zH^~{_3qrTmsuM?tmr6n#yrjX9G>GcqE(Q%kJZ^*B|6DVkS~CXoD9s17fDR zl_^vVe*tKkkC-XNiJ z?Z1Swq79yP6JxXhj(#oT>@F)qofkxux_{`Chu)*HspM!u}-E~gn5Nqp#O(!GbY6YhB2#*6$O8bXd?B|>Rbl*pGng{?_2 z3STD267+oC!k3CphG`bEJ(H+<4iMtR)(D3eYOCj>FcO`7;^%nXBh*gv=qITuP8N1j z-Kx%I`)gWY>qXX$*-GN!Ek^={M_$Q>x5@CYC_?!1S2epL+mm?VCJy-RkJ2Pw^&{=- z2fgCF6#%CUYHz|i4HohudwEnK@mo>#*MXeSuni&`6-(WLkeO3AM87-x_B#drPDa1A zleFJBS=hNKoU*;E*6&7~R?Q?ti*PH=xKE(`+^S|`^zYI%E$C9exQnmLLH(ApRpk)K9HXD zJ5yI5#mKy3hOPB~iSK_Iwl)|o1hqC|K}M_XfAN-YHd-C9^cN=~v;}&k*!oeJBlA0U40B+CtBobBV`!qS zQ{jtbf@}3|J2Ir5)g6vJ3}T0SBhi*YwwyPRckg);ly^KzKabK^-`n1dbkXfNg7mDP z2TPl}ANNHcN0Ptw(v~b-IDSX%HO}Bq8qudq`VD#BCmJ(VjpShv8nY8^xPfD$EgKqz zIJ{2uC<8o-SJ&7ZrGys!`b6U(5*}6K0Cf>km*he(9;+qvz|!a^N}M4i@K-3 z!yqKTlW6NlB)?T>9hd)__=meYx4 zG#=q2E(7pXWF5LEH^S&g&SiVH@JH#wv07lUHP6$gaN%e@sL0P3YHMBw`Fkmx2&>tp zHBz5l3KdZlx3kO-1%$FT!bH{u?{MN#4WoS_3lkpUsgDi5|6Q0gFC+ZD=wT|#htT4Jwa6q`BjJ}% zAV?mClWJ-spL|j~)b^SEDZyqdW3$<|*oE9Taf3hH_pB7|qwXz*PXd<-c_`HO1vA-U z7c$bw9g<-a2Ae#a?Q=8KeunzeE|6Q|rR3nAi($I=|LEQiQ#+OFIDQdSHAnpXR@Lpl zVmA#Vmo{%wX7 zqV-X`Z)WlkGYO662bP7hEKIa$her$SzI#Pu)DSVZ*&a57S78j5q78XbAv$0bA2V|% zGiOf)MpiR&R5f$<40Bd1u(L=rWCMnb3XH64hKvSM3ua?8lUU~5>1V>`nwy!#nVGa< zCasDYwHDEsbiLoEciYxe`FV9j6UL-+7AX`@fxKFlP` zIGmYgsJ9p@FOaOZy7%{}ow}6t$1mD=eBkFdQMVt=Oa_{nj9}EmAedW93d}GQ7-p=0 z4w1Wc+H9lEkTV%_T43Z9Gvq>soEI25#|*igA(xn$tYIdr%uF`JM2q&ufJxa-?f7~# z_%6n<-Iy2K0{3XEnX`k;+5W)Dy+)2bX3kD9XU76NJ7R`B%aEr7Bfm34{tToR%=2a@ zSD5pQekN?LU1cV}nwi{YCO3*1wZ8%`B`>NYdfm)*s6*eO1V@0Sgv?o+?H@lho0*jv zx}t;MygCA?&hP5Xq^iTP`#fQWdYYl6K(b!ez1OC8Dpg(lqK(Hhetuuk?He$YC^HiW zqizDh+)~oW3=_{V%^ZIFX{cJ2G&MuMz>qBhBNNP!9T>7*U}Re}}-ZiVaV6bOnNYrG&7TIm}t??j182OIcmq>FoVC% z82TFXA}?@{a?G3!WX`;Sksla2-ZOLdF>^LFu(Kg%$ngw0CNOf88FDI+S}-S>napC& zr~8?(xi+7f%rP@r$xN0NGipo7q%%|{ebo_NWafGkbG_bd&f08i{m^V?R&wb}NqLu$ z+C9tX%IH9qx2#L($(PF8Pq>84o<3J>3v`nR=3R6NX+9R?Ro~UkaL+JY zEgt7pagk=Y1`HP!2v^q(7tL^u%}ipMiPOxaIZU*G#Jhy-{5+rjYRgfaA99`^r`8PF zGBEOaGh_#bY!?{W)(qK&b*Ph{2^+p-<~#}E%oGNP(Ch88&Gw2Js0Rb30hFDRndy^L zE7b8zF~jy_n)3a#agB=Xo@Xy5bmzEL+B%)Afevtz63yT2K3B*P8oajR6^ zP&3>_h8q_MH^vM%o#CdKnap7(GtEpE!$ix*1%WeTo*#0X9;a0dxjZm(sTpzuL#_>s z{KO2og>`6?p9vej9nASQgp<$4t!AKo473Lzziiy0j^8db>=mZzqJK7isUm;$&&K_F z2(K~P-~GHF&`oYJ?|<{zaa8sFrx{L&*H`TOJnjn>ch?M8is4Gcb8E4N3ytU3aHg{? z!-bofRA46M%uN0R6D=Dn#|K;+EBPT$>T!}7vU*_TlV-?T3|S*EGQte0unyJnGhtzA z$ehLX7Fbi zLoK%0$OMLT2S&Qgkgb8#g4xo{Mp;U*deZX&~t<8jwi+!!<5 zOop2l2sgzHH=p6=n3*hLCJW6>R>MRK$O?DBjcu79(uR*SsiEA+km~{?*O(zcW5_Lm zk%eZ+ovcHj`dGuwusYl36&*HWL zr$@;3c^##_ZyoIs@_kNf??5&22&vtCUTTn!Y^rf?r}_^KP4bi$Y$2hcuX(~DCp7eR z4?bRG3oVhXoiEWIc({MfncIn#rkPJ_Cf(v;=YeV0pzh`RgLs_)Vrfsg; zl210Z^#~bRY3W&cTo+p#d)+EfuUiD_bwa>ihlF(S2zkAF3j-b!Y+)4zN$^%DgAfwZ z-XnC&@2;KKJ|mCko>B)WYe;nMp|A^?wQUW;SKIY zC-jax(FNLi3Ijsm4ITwCB%~wym6t==$>;xwGErlH5$x$|WGH!=Q2Y-oQ=-g6WlG{d zT6_lVeU>cmpeMZzSDefl-@l<>6Mb3m!6Z<-1CCcvSm`g#toC&r)Q?8-J9TCS1Q(MJQRR^hI%nJVY8U4V5m*8>G$BCTU#6PU*Pxm2_A-DE%nklI}@&q|@?z z`5$?iJS?J5XazB%cizC#vrGR`+A9tchlwM_apDAVhB#ZCCoU8hi%Z3o;%afDxLN#E z+#&7~_lg(AOX5xOzBmLl!=+KuSZSg(S(+iumKI1$qzxe5EbRp4L69Do&PrFMTOhqB z4VH(oXj;;rKa@+i~21<4(1=JH;>1 z=iNB&!SPER_u{w@$Ne~dh2sGn4~kR8LwIypTqk}FyCXPr6lad%%yFFg24_y-%t@U2 z7H7W0nN!ep8hqd5nKO9iES~uR&z-}w=keT+cNi;Z4y&uM`U6(iV09fc z8)ARyrZ_;lB@UEsi-V*);z!b5ajBP|JZ@0n|!qqPR+$B(9bwi=RkS#5K}X zaVU&7;Fc-#k%`{D5`csu})2jTG$JRXL}ucd+F5&RsLwo1p~`8Yg( zgP#-deiGilh4=5^{S>^PhWGE`{S3UHh4&xe{T#fXhxZ@h{U><;8Qw3z`$c%a1n-xn zBhnS=sPqfG{|fKF!TayF z!TWt_u=o#t9)QIwUzGaGm!tvmWoe*%MH(dkB7G$9i5V<^88bxQ8&e?fiy12Kj~OO^ z6*C+&_+xnt=JHs1q`WU;l)OJ;wER`X7i6Xo@hljN7h4L=vBKfSiSpLGfMBeROD(`VFlefvszK9jZTmX;j(xp+*SvRPiDY>}5LpUV54Tjj5upUKOVZSs+r z&*h^r+vVlT4*6KjPWgDuE_sFWg*-ysEuWC~$e&1G$|J?S@+fhiJX+i@j}gC;$BGB! zapFPwH}Q}>UOX)C6Te3Pj>r?mqw*y2m^@iLE>97^kq=2HV1H8HD19sM7Qd6X);T5L z#X@{f`W`=Lw;+^185YM%upyt+|QqXhxC?IUOE zrsbrk=Jib{r5O2x$xzz|*>6?6~!GwfPVAnlAP9BH0Qmf4b~N_nsSfyQi6rs;$LwhQ$#a+R zM;z15?C2N}yQ9wt!k`7@QPDr7I-iSl#QU3QAgbuAsbRNd|w?X|TjqT`PyR?jy9&PgTkX%u||LWoL-D3&W?pA7OYuy~JvxMx4!)csuL`^*2XB{eLcV4Xor6V-jxxdmZOpUc}< zzr)`xf0?u|r2OHgmOFs-Q+@yTZQE0o8;Y&xR^9oouw?58Z6;H zh1Z2yDVf?F&CKYg63ywnJFLv$yDQ~&-^jIQwu%iAx_N3eYnJSeOO9&XBC$ogwyj#b zy_cCYMQ<;I@7lUCFzd$^ep-!d^-TWr#EaB-tVDa;=4i(oz?<3X3MINXU4 zgfM)V%$DM@mBj@ctwYIK>2C>xafv_>1#cw)juOBY0x0>kAbi-OoGt8lOvvdN+r603 zUY?R=aS@0j$scEN&|?I8Bo&9(0Br?mhzbfV8_PgB=_zRpM83)5I04N^(czsAkoU6C zqFiX$gvPcDO>GUEg+#`Ml*Pq7%J^1JMqUvm`SOr&RJCsc_(csIYT7h(2+;8w8W+DP zIyEl`S1@T;$(K8vAm9zTIFv%s;5{DFqFmS`pgtZGdM_sILer4=X114_mCRBdwT!os z?sqM6hfgzf!wQki`K=1SCyC##LvXlQTM%SOvc2BSRu&iXsFEJ(dF0BP7IYGXZwcZA z{yfy%qYe(+NDxBR2-qUyY-QaH**o6{Nxt9WJA$l^o!L7T+it}c`=z9nV8_sF$jtip6*b@emi+(Vx1+z26>^|oU>vCRhG8Q;N_ct4cXNh4q&L2`c zIV+!h=7e^<8ti@`c6&I7SaGs*80%yhog+p|IA^)pIeCmwgw1)_gbPo`A{1oy`Gg=< zkLEv>JGE@vv8^Cr>Iq>lY15RZi`GSwhCdOq-W*w4dU|iwBa;&iuvxn0M^e;fzH$v{jHtlG9GIfK>9+GGY$?=^M5}LP9c6aPTCW-cJ*soE7D>pSG zqeEU!R_klHvT%)-T*24yO%TLCfe*XI4Khi{qCwWD^8y(EMT|ReF0=A` zF@Gfa{w5};V+0!Ucd#C3r?LqnL)Hyd@r!nSOwoOx{=TIN4;MaSGbqrr-y=7Y{Zfo| z{%zgI<3;NL8`*bhWG*yS_vchxgU(6ro|)1kmt~FvCih4`4smf&w^ltIqtMs;YEK>} zQuNNy0n~@#LrNBc`&H0o9}_JrJ1rfHd7uTeKNh8M;grj-YZ%evAjCiH`+9798Dont zSOUC6EJ?{W%{#V8^Z-fTSR%+YZs54ykfn2=ie1UZh0QhcSMB&0F6{D|3$6|=;QB31 zlubzSJl!ijuV;1|_5ige6ADn0g|+j}5xkm$hq3*|dTefwt(C{t!DH*}vAyiEb@kY~ zc|yXbangEcledkui9*(@L8`JG9L4J=$Br;ALNqjIDg;T%0WV}n2^EMmJ zJ}~VUi$Z>sF5T3#0`O&9APrq{&)D(P2DA2Qge|!v;v5I4rN(f>hDC zx*BIt*kDc|+2py-4pa5DVq6_MqN0EdL09;vx{Ee$sBd^D)s)41hZ$KtlF7SynruC5 zmlLLOKH@0{op+(Ka~WAF16u8AGekk zS9OW|{MUD%O=dKm6W?;cu} z$FejEs>i8ZnZD}@t@GH@Hi3HU&w0~yCu?6uq0O5}_?x8q`_N}0^_Lv>71w|AvP19u z`*1K>b02DZqtI;H>hqv>L>BMolGVSz2a*L9f}hCCV)MM{b%h7xsIEnc>`4UJr~i62+cI7tyA@spC2KXi zzD2fz`+2I+HhKYu<&GAEY;GTOkh!g{ar6aG*g`II((;RTgBXaKuey9x-QzN{x@RZj zLnVTD0UeEFTx4m%qv!Nkz!$3Uv_MJV(>Z-`yK+)|=SKzjS_EIX$}C{}!v{{nybp&6 zLaDHjZXTgj2wotU3c*Y4QXzPuSSkdsGfR=re3S~otNc>rQyZm1@Upd3NnFIlwB$eG>UU)Py zWCd;=8(ZQ~LF<1#isqj-fZjeg8vTT6*1!V*DFDTn)*S={8 ztc zUaF-l(SqBlcq88_H2R%>r zH6=r9jqEtOdz5xJ&92>;SR%bWig-^WVn)LH5%dqba{9J~ery)oC{}J~l@KF_6`*3#>kP%P>aT|p0 z8w>=wvPI}61UlVeQ6Ms)h=5@Wi!8waB94q<5d#Rai!2I=AhL=Gv?wBrAR_1>4h}Ai zyaF;Kf~bI~{GX~ix4NtEy&3KMzTXGG^y#j9&Uv0Xb*k!g^-bDY$iD%dlRo`xqBGW@ zQ-{$x2@+>30a$*u%-3bpI!&}7ozeOpw9fkUGem1TEdrU0)mam(GbUEz580h3I*`uj z{0ur5efm#CXHGnwizYfh+0eO6bReD4ars;6zY&)O#)#d{V)L5`T1gwXU#ydm&KQ&j zgEYTbq30C_=ZoW7PxNXN zE3trF>y*Y#pmBp=zuvD`B_^XNIed)C4Sr+GxE>7Dxm4A}No4KK6e37xA=1Fj)q!bjI;^aLn}Ub%@}^_?eYy;#bGSN`$OF(SdYE zrwQmZ^6L$V&XjmMjZAbJ*wD!$I*`uj_(7)`aakF^JvB2Si+m0^Ma%(WHX*L2-t*Ec z8;Dk=R}1PZq_e(;fgB>_93!1X=@#lTx`40D%u!1(#5{4hI@1m>)VKlQn~Mt6M8!ssB>wXiId3M-4r57XCXQOZu|ZEKEJ+~ zxT%%*Exr--M4c#05}%Ka1&txB(dQ(qyS z_4PX-e@n<}<^HV+8o3xNKh6>ZNM{T#fx!j8{-a+%PdwDh{errzpmP5aEg!LkMpo|U z%jWtsafNioH8s#mcL($68$qjj zz~aokdZ2Xt$E=h{sN8QNWJqVoHGy0spx;8^YUN%dU>u;_V&=iW3M){Hh(J0cQX51x zVxiXT8iwUlmM!r$`#*Wjj>o`l!~oJ6gUor;1?n!P?E{ZBUH z2{n5Ir-)5}*oY97n!S+?VwO|H01$lvy(xjJHM>vdR#Ou`K1ac~_ymF!Y)EIp&IOT{ z0X>I^sMUH)z>inX*>mg&g^3WPGeUQRP}_jsng}U%dRr5p)@DAKm##oNq66uSPAAam z7|`>Hj#8(0G||boq0^b@Ksuw-6?D1~7qw3BVulu}@&I8&I>Rmib`Qc64TJ_N7S=7m@Uk9u%qf%Eh}CMKea8Q_$_!yr%;(1!%{LBv6+%8TTb9RddG zoEc=|BudO;3J#>R;QSTbMhEm!0evKKQ>*gPCQ73u-H~Q;B5fWgc9724O#r)b0lkE% zDfRd`6SERCA3mX?ad=`jv2vMoW=K#^FpqfX0g>=@}g+QK9$Z9=4-vo_aK2};RA_kDo7%T^aWdVI@ zKwnHe)OviGv6P?^UyA3Sv1J9P=Znkcw}SXVI^(w<{MH8a)kIFM!Ph1hd(qXV96>4g zDX+ot7)Ns6Zx9Wf!RI2G4B&D zWb(Kl0`~ynsx|ciJKT>57czO=Bf$M6sDDh*Ngdi89*TDE>2aZu~!>e;kZpkA(q=f|mDzOHO;HxW0;vD-ly`~O*w&D`53R2@fgsE667DH^kH+{BmRqv?h&t*(@MWJ$D&@o zHK%m^35$B!lOxgu(iw6FkZb4Y8iA`dbL||XX4XtRkT>{ZZB#sX4Adbykk07T2c3Gv zMXjFe<&;i1lUO}}#~I)ehmj&6kj@x1%CW1UV_=O54AL1`Q*<|rx~o*tS%~*{7FBdJ zr-(ry`Uz2~r2RIC*-jC2f!H!f&mmB?nr$*v^s%S#~eMMXekwTM-!`j6Dv{CbS65G&ggUlovt~07oww7 z*=IBr4=wpbRT8oc0QF=ns9b+P=B+>-p2x7D z#IMxEN`!1G(SdYEXEx}}%+aS49i=j#X`(aThRz(K1L=&;e9)OkT$Jj3o(Wmx^8%-c zF92~7Au1L6A|P6oUW=)(kk0zL49H6fS*_BSnxK)3vGU_3VgTuk!CEj_ouj{!qrXf% z)JlD|x~!mHe+4Z+v4uw7Y4UQ}T-Om-NM~HPfa|6leIpT7EB8%_#bI=#DPKVP46oer z7>E)r$UjPJQ%h9tyN$}ddZ?9NEu>!?62<%emblmdB5qy(8@qMA8tzCR?*;H>es}a` zPxM-}Ok^!T^Om3aZ#tHGSsjhXzzrc$#X>rxRRgqcAx;NdieEmQ&M4i&k&sRxiC;dv zX#Dcwtxgfsf#?nCwFvZM76{yQP%?|5dVxCI3%v1_qP0v6z-BfN0UiUjDFl$tLU20> zWrp-RMCen4(6fwCCPC&%8L`>ZQv7D}b1XW|Oa#QP6Ch+rXUI7~&L-ruK+e@%CC@YDY!!Kdw_S)`474C* zNN31-Kn{oW5P_$J#N1fIz{3DPg~JFuL_>J~A|~qi1zt8!Kt${}t(+2Q2LgA6^fpA` zs(1o-#Sv&@L!iA=0-ZphV@StewaUM)lPlv_S{--r&mw;_N(TIFmA?gxSU2>pEg z;NJ(tQWkTuHp#*7N`nvS47mWvJwkdn0>4OIU(N=<2TQbj@e}Q)(vVAJPp9zx0bdx> zdlUR|f`5g<7h+>r!#0K$EZ^`L?QKJ2K$0{L8e7(*pz%mZFD4r5mh}jDY+yX(mQ{?F z*I7&ambIC$*LVz!ron+sYH%d2CqQcqaZx(zkdB@ECZCLICM31k*t1>5x8|2&r4v(;%^qwyeoz6MBXSK{_Ke7ldYq z^qE9R-LhuK5t>;xp=XH@q%%SbL1;d)QMRo4CIVv1T13c@&XAV?`2|8&wyYOaWVvcB zC1glv$S(tVc}QPI;L4V@9N@;5wG7YSX7eOr%UbD_z&a3E6Vg`^0cFct6Gvc`4T1Ge z32Xv^jUjyl5m2_Qjd27v*bvz4l)zRHh!VQ8WkrD)w>HVaf0G6u(%Ine0P^;bzKy_@ zEo-~nvbL!-uNz5$Js zA^kYfP`9j;;IWtSkXzPqw7kz+;6eL+x@G+e z61!>3x?DCPSFU*H3+ar|Rk^M7a=Cgc{(vegZ`CcUTyBg|DxRxjq(rC!5rT9^s4@su zBsR*HRnbI1Y+2V3GNd!)sz9zn$jX*gMMajYRy9I~bcTF0kZ;V@s}s1gW!(sHW6P?J z=SSE)N!YS(aZ11g0yT5>8bmy$tp5V$Q@PbUJ(mUUYkfpi-Jb)6EZ z4+8ZFUD>kg0WmJ`<>2cy_>j&9zX^~VrZzOP|2T~>ZhuYZx4(V}3I_;Z`NI(hfc6E;_k>?R`-ox>`A1_P zL;VL(59jKK2w43n|8TDHQT`zl2k<$@cLqELjt~{do_kgbtZJ`d7JjAK}Mv%181+6F0w!kqA`|QGraJN*<_$!+MCQC?Cg%O;kcQR9X=g$mFTq4JvJk zhw@Q;TNA3t-F8mU?g3f{LQ_75?*KHblBpy05ihq`RwcBlLX;qrr!*0iCJ-OxFlYkeaS7mwhe1y{L7NJ+DPesQ0jdWZg>)2Qo^$#;DY$jl1sGl-0O2s8@>&e0*zjIznhB{Go7lUW2Z3&Q$yL`FRT zS`bI(xw6STPh=pIC-Wl6EFmV!;m;BixY$LO5h`Tzs4oL`IiV^CKg(5A`QCpep+Y8) zx(=vo!ul!#Rt|mE0N6P6S%v3gHDqDJq0f3J;F|!xF|2POaOJ>fV;uMf8}Q9ez~2J+ z*03HWaOJRPYaDpg27H?n@Eri(PRPnZ&vu~2tvhnCchX=(CO_Ek0d-GU-%Y^EAM}Hr-g2j<0rT!hS`I{Sp6+AraiAvdhz?bXM8j^ug6zv z2d8(cUCMVi?VOqkSNZN{ad2st{qn_W+?0I3{3bU_zlMo^1%6k*nv{;MCPK`8$ZiII zm$g*SPK-)(LvY~xEIkX+;0NQUCn zJkp7aoa8cax6HD9cbHELBwRAnqE)^-kL5)xOpC6V77rWKqIJHzZS-O440yR}`5t9G zyeqEn!;$2?@$QTf5ve@3n&=xs%ztBaxyE|Nr%k*666X;#sjNq-{qMFG>86fxhyP-2 z^i`oRhdkfZJu$J2F}o-3dTij0G3yw2)jXnqi5pRbG~eBck0^VZ#6ovpzWZJ_qW57$ zb1C-W(0-8Z8oBKeH1R)x=~hL}VYfqv1F2wrhukM9|=p7a-u(J|~& zZQpd}XaIA>8@OdAZycC0rz!0nIUpm<>SM3K4QJ!h<8b5Fow(NPC7b$KGF)ukaHrLE zvAZL2=qkoVCgDRSLjiX!IHJFU;x3C`ipy2R<-v%eqCZ4*Mzq!P&0u{T8Xe1eES48G z?!2`qV+@&+uVEQ~rG_}#*Rmu6kB6}uB8>U&(F9;5gRuj$;Mexe6p?P2y{kP3vuskh((o0osV%`NUT#z3_p$SeP0@Rky-P% zI1|k`oAu)f5ftvFwsVf0a_4i(0-p%tgsq+;x!{TXAI^u5>P+335;y zj~9vKR5F3t@(>8ewS05A@{<-m#g&Q7O&LQ}g6}4FB@Su{zJA!%xm#pa~k+e zVoj-;7%RM(%8U|+#%gf+NX0J1r9RK)-!X6{(|{EhMz8N#F?c1}RlMp56a#Acg)+)lDtmbKK1==_WSv;>v7XL99R&v6{owVj&RooC8y8mdsT(;%BU( z@*GqGd=V>|&zz@pc4uNzCbKP+EP?~@S_r}B7=Mi|q8YY`=Og;Uh(6!gB1)czPR3GY zn`cV}Mt|Uvvozo(N&OZzHAoYKEk4Ej-AvtwoFiXkw!< z;=`&=_6~xVK5?xv?6}4l%apiPTx>p~{4ZI<_{E$H3qh4OoszXoWofJnDRQt8<#o7- zDS=Mm#Re;9EJ!>@Jigbd>#s3A9uzTAeVgdQMqEgU30M37HYTq#77HVSVO-#_{q6E# z`zzVR6rLxAD(D|;+{_x6Qlk;OEod}{m-op~i9)4wS|&mOCtL9X+vOUh_bU8A@~QkL z^SvaJkxN@<9^2LuM~wxVugkFu|1DSIIwwmK%Xuf}ijmaYSg&H^=k;wSo^Lar%F>-U z)!tD}HQyHA?;Wg}=a|R{$~TS?+k@HqBJ_8vZfg0W+|4fOM&@XyxWaz(40|w$BFgVF zwOEwI+z}lzMrDtxLi2+2F$R3Em5R*vTD~_p)_c$jtOjxMavxq|2WEqdM!o~T&ze#* zF*!i(L)EFE#$#dx{}41X*BVQ5TsP9>@{{gcM+5RPlue1lml>WZ@hi;l827`BT>Q9i zC74ebOqt{U57kujy~(?Kgf;)JaTofZs%~oe-r{clDc!`zU0gYeE0|p%ir{{R7p5ut zIcqFywtvAC5@-9DXpGwwYx%Zugk!9k_a{a~T=^HSbWROm;4(2dAaeo@0kP?vWY^f% zj|5L@>pu+#aQO`cUoY5eZ2g_E_3w`8J0to#5&dns`~O>L|3`>#Au{&yT7Vs6RAp<~ z8FA@5AWX##Qn-`QY#NO46W(Y&sBEF9tqE5dIM{ z8r^rYO)wLU(F43th>dRS-MHpELd!)tIE=oJIGwE&2OWE-ESx0NEDgt9Hw@hz!H44N zTE5G?SLJ1|sxlH)@6HtMSD_v2EGT9Im9MiE&_q%F6P{-N!W~>K9K`XkiE2eCM)$D+ z<+)JH_bc_L61!kIs>admZyc#I^b*oYT)0M1_+L+>YvC7bA9!L)SHTPF{dIVnd4;!D z70_|LkByg-Q`MlT^xl;xmYVC?g))2Z&SUu1p_kBmap49*;eWmNH^MJ^51v532`{Mk zH{)q$3U9pyPosQ}#s$D7x6#_ZRO;lPp@@0%UykjCE1sju!F@>$h9mObNQpE~;8t7+ z97B$Zmo*to*~j;>i4`|f`C`Kk#7b&0q(mKpmh;&IB}4|DgN0YMuvm;WRfFEf^04u~ z8ih$Z^b(5qm{P2Qm+K?m)g&@i4|GdvGmi;d(`{&@k<7r;%yPUJb?}r{UJ+rBuRM)i zUFPIqgs$Qs{s(>#{{uV7D#>Ja2eA_UP${l*t3ampnCXX+xN$Z5dON%FQT)OgtG*1K z`q04=^rt*mrs41oav1A(EZYpT2IM*xJL5`2?l2P$!MqWBkrucL-i@9%Chum;CbmAa zxSLG4fzLac+JD^+nli2Z@qLebn<0~|8MLAwvdw_adj4@(ZQs>-)D}1Lu?TqBbzUs^ z1d(Lto1bB;^Q|K9U;r2Rd=oE&c!`MsRCGR@8GV#MxDp8Swm8DEk@om-ofB>jW5gs` z!Z{3kKi?3I1)?%}Zow{@_R6@)@9|y3`L|>g%3eH#8(J+gg;@w@EF_3PE}nKSmkDIN z2(uSyndl&1MDQXm0&(a>&Evb4_~t?NztD(ff1IP(8rI4REO8BMttwe8TWwSgiyE@6 zsv#0l>I-J)oD+ zcX8oC<{&mJ#30H2$m^?4SyceN|BH_IgkS1bFFeIi0}(^r2QP3M^*sudv-pAJi(Owv z!}?@3F<^yIweMMN-wo8We$3?u2?tzO5#ev4Vi)43P8^Jw2P}YA2V9m}DzeK+_yLSg znVB$>c|41r4L z@_`$%^&9aUYGtKN^CDHlVyPGgjlem+6FkfjGJycNV)mk3fMo!#^0!jM(e!_jh$9#U z@y2%~o@U<62|U8k_Qq9kr#$S2gH!x0b`-lfl-_{1!5eVi>x48BOFK&lT;T8DMskh4 z*mCLqx^})l=b0V36C8=vv1~{FTQD$ihR}^>p#|HZI80l!4I1W$2{CB}%I@??A*$wpk!14hZ+97jCtNosQ( zTCgWqH^)0o_M~EStd{IarREq`_M~!iyai`Z3Y%jSVNXUh$5{n?GO{`9diLb8=6I{t z4k2T}nF4k!o{IOPa(+Q!98(a5%y>M_XqzkUAh0P-Xn`AHoPfs#6@D}@92c?yEBrR+7%R(j&3PRr9hd3wz}x^1mw z5-w%jmd7~AgSjbai`L9zS*>+<`8N~WPD zvmUp422X*Q@gPm78tgnv%PXDmoQ6NH^PDCO`INBaAQw@7iZvbH0(H3K8F-4U5ib~p zjJkO&YXHl}mR-&i7iZ#W^fvITD#8xtP?*K+*#RkgnZzwKC3E2be&#^%u(Q_)`&|fo zgFIc&({Gnye^#i@gUD#Yqi@{gQ}Ud+w18b|oEN=aj)U!eG9?R{ZUZrhP0?evelKEe z*88V$87p;OfGT$20LIUUA4pDrF`A=|0nctwjKAZBk9loh4(TmnNKNzNRO2e{xYpRw zo4R4jLUSo|bf+4P7df|#thm-dbC3*T9TkmqEQrQv7E8G}#Mm*D=F67X8!#>2z`MDO zq3U`3o|!xOX<<|J8Ha}4n@W`(4>raR3-C*@i7Daz9qRQjRbE1|n1X^h0fnCqkbRJ87)d<|Hti1^{$Lzyb z`!(YI+JIJkb_NIN(QE8Qxj+keGqUV;G$BUn4Lz~!R5suE9Ei(BWIX=HVQfOhEo^d8 z;d5sbW5|b}6ZiVU)TPaggi^94&ZRBP)S}Z-)urZ(@Q%L0nt3cZQf={EV8=d^M1(Sh z{#MmZEngmY^QLqoLz*eByoD{I%Zewb(n9(5{@2F9fzOAZQyye}_JeJGE*udjE z>_u9DEgODhV=9_rq8&G$i2J)L zVi(EyPs6v^EpsLJ&~D5Rg!m0~ZIFh$JQ(E2nPqdrKVMIxm_g{s<>R0Q_82h-<2vmeXfChA9YQ1 zLnjS7Bi!zH?5y@ntM`1aK1D-@^(roOm8KcqZ!x@oM0yb<+S<eQe}dj$}|Z*1%#EQWRjiDTxl~a zF^3{N{xj?>Uyzmytu5!*@h@^Xd#kKEG>8l^Oxl?sJQs)os#Bv!d12@LrGfI8+0?5aUrl!S4fxewI{eWTz68 z&^{1WmXfA+HeqSgGLW#Jrt+#J$Ih~yv}|i_+1k#sv$X7JZJBRp`GB8P9Hn-Vu?^>&Wj<|JsM=^>~ZOAw6*0ZGsZ|eXHQCJ3mLtikxeUq{@6dl@(HDSsA0YlubHQRnnc0=wdt9uS(Zz z?dGi8y*j~K&dfI8^)$RMAU(d6EXE5l z9*YwE_A>Nek}6B>R8~vql_0DvB`fS~HcFdUgO*FlIy=j^q~#mdmRsyBcT3A1)|T7t zEZ>)wd+k&{k}3!6R6d1@i1sHztEHqjPrQ%q%#TZiW9Gd0!n#MF**W`GIy-G`dCH7& z!p_-G(%E@yXXorJf0LG%tt~IvS*B$h!E|S<6G^7-pP(WR6Ury3$hmfnRH2iciF zCJ{!N^J1iRkA~Yhn;@NywYGf1j4{T}*;MIlvbD2PJIguJa;CNAbUVuhuoS_ZXQ#4Q zI$xBaBInvmQe~-~$~vjCx{OhKg-tqBRq_ZQ(Up~ z+Dps3tS#HvS$39|9jz_%?JT>>4&9faB8RW1blwBu9PFByLg($8+uhC1Xn-^-gi%qi z!Gq&+Y7HO1-gdU5C8tLcvvC8rEKbbE*NqUCNZ2t6-ZvX6Pf70+)a-bR`yOX!_l&fA zTD4op?IzpVJuB^ITiMODvs)zX=G&<(l`1dTsjP&G$j0T?nXxRv@@*qd>!sxyYs*!3 zmYb#JMr+Frc9w6-4n-4G)VP{!aTHa=DnQmvP z%MR5`P?2HDlFl0;oN6{Uurtb*Mt&G2WaCjjeogIcKa!jdS(S-(SO45ew_69=6?z=#CU$4;P<4V|E*LxZKv{sggyttO40wFoy{-O=2C7# z(SM9b@PeIXxv(*FQo@#&uCN+d*_F!D@@i|#3U-#&q-7O5m7Ar?4R$JCsEBCS3|kfb zr+LR~*qPrh5$c9bd68k=quO@P?v&0NTU$0XW87iqEJr#ET08UGS+% zieR?2Q|Tz3cSul?bL~E<(#cMxr&Q@t#;A1*TNV9h_=tA3bN!HX-Jh8!o*%F|>vk6= zSj%)Sk=A2ityK3vaLdu*grfffn)$qc3Z^1>6T<3-ami4bCcRGyD;v!f?t7A*-CSum zOSL=4?Pl27JumGRSlK;iXSYn+EwNKsDOHx+sjP>J2*{eS<;J!u!P1QzX?Q3%OUsSc zmK*FWw@J&b)|OE_%bl`A+Y?me@a>b%_aL0=#t0pdMIul8cqG9TdUaHQWm?Ch}eDIbT?JXIICc~Q^rPILq`r_K%~jy zTRE+Axyt2voEKA|@YfMyfm%g@T8%&$3t4^($tbnIA!O=SA=BO@`4+Wr#xFGua=>Gf4~y#mQUQTx@9;FVU9URR>mmBs6F*HHVlB&(3Tj{H}p*VX9t z_4K;BkmYV5d83f!Z=&lrlm0FA`p-dJ?5Q&t~bP!F$;+CWl?Bn*7y%AU6-UEx`+W84n z%KPBiD6W;y`ji8S`MDozjZJDFL|nxRoqcF191&}(>P~sjDzj+~NW)6N{+Gjl<5{e& zeC6^;@7j4{C9acKm9NNk@fVR0>Xb|xf_gmkEaY0As~d*m)1hat6B;YlAK*cch9{ zv6U6w@|9dy^V33?t738W>ZiYLKla;Q-?xlTzq3*5L(7Mz;Wv=Nf$sMXFDxG3{n5hW zqDQ+&3WpCGQ8cXkeFKM&>^1n_!hQqwA-#r=C@k)t7r9$++qV0oO|!cHrEqXzui=H= zi+VrQJ%3o?(BZ=ew;R|y?&%%F`u28xf9@vNRn;q>^t`S;<(=Z4Pe z(|g#v-}|BWfcKJi(ff<{XYV;}qV~M@lJ>Ipnl?54(bTHd(ua*0U+HY6A1al2CU_=$ zrg>(07I_wXUi2*YyzF_!v(~fTv)S{8=S|NJ&o0kOoTB^OMEd#CPAht?dqpj7}f#B=fW^If1hPG9EOWUSx*WS@~XuGuC+8%AMwoiLs z`#?LWeW-n;eWo4P{;mB-JENV`E@+pu%i0xmZhHF6^f~E^(w|RXn*LJy%_YNeH}>o3 z&nD07=+P$67Cc7r_y!)g@*ZyWyoG*l!{gg{+>Xb0@VEnyJ9+PSdUhiQ@8WR}9{1w$ zJv{EinCVkfYwE5U4qun(7NoI;rRucze4jjXkLM4iT5YZSnmbT zIPXQzc<&|81nUG(L2lgly|nb)H??`GuJ!W`z$Qx!QwgZRPTK6H17gfEQG}(SUeAl7htg% z7E55U6c#VSVi_!6g2i%JtnjY&ybP9j);rg;&ikxqy?37HRqu12 z4c_^l*WhU*JiQK2o8W0PJZ*ueC_KI4ec8JeKW}<>dftM^ZSeRuJZ^`_ci?dcJnrV4O{!Mn%%ns+Zez6X!{;PHKU+z*c*z~cdUJP3~;!sAEY@t(iq=aBa; z@5k_b7@j}D&p+V(2)us^@Bf7NqwxM2ynhbwU%>m9@O}*5{{`<~!TWJ|{~vh&8s1O9 z`$>2|1@GT@|L#5QJ>>m2y#EK@zlHZR@ctdVpN02x@cuo#pNID!;QdE<{|VkN!23mb zzXb0;!~11;{{`NE^-lEshMy}yDbY@P$7-j%wU_Hm)mGM-roB?<8EvY6x;D)}Lwm+QQ#%lxr5y~;);PSeuI)l~(Fqtv!X6qZDh$B&;4^de&>Z zgRg4u1~+JXg0E?BYa6w_!Pm9-f}8NOSv!W6<(pts`yu#-_G56X_EYdpZ9dkS1wdH{ z?Qz-Lwei{SXuGp_Xy15tYVT+5()MTV);`F3SDTQ%M|(1Rul8>Cd)fx9M6Y2j+NkZ< z=6F8Pc6ttId(sbTd(%JE-b?>TTbuoNZMuF)o1uTK&D0NTv-D52+4?`UIriJCjhxc=Bn&%7c8PAv6bk8wuhUZ_}OwU)^EYEQbGh16<|7&fw=LB$0 zYI8lOv}ZlvX!AU$wdXwl)((3A1O0Ec&E7NGyPof~HTBPGm$BUc;{6^!=d}f%AGC#@ zAGJlEpR`?`3) zD1E-?`SgvR7t+^x7N@WGEJ;7$S(<*%^J4lho@MD9JTIkR@GVb&&9eeJx43R7S#pER zb!|&_CUnQZzMCITb6>gQa;3Uj_ABf);*N$5r@LJEdIr{VN8jSYJ|i9}#7>M~p+SrL zZ|te^?~XnL2iNY`pSPvpG1XndRF!{Rr~hEymWszzcdcrQ0$y+(yrE+M*w&xw?!=$R zKX9GGM|o2@u5*h0sbS?G*BL&Vx1kV*pF_7R3V6YFPz11lSK%ksJ%$P8ALG!VahCs1 zpGW>{bf@3ntXbBbzPL7au~EZ@O`A6Lc(Sq@W;Np4J+F4Tu3T}u`c8cOg$D|Jzr9xJ zrB7G2U%lXyOMZ11tG_S5A_*2Z89*a2p z4aN9>EnQVw@_tg>*)<;u-1qcLE5 zD>GcK`^T_nv47GZjRU)~3j^j}7SmzRm>xo^vveIexUe{&p(wnkxTt?|uOXgRXc_LQ z`>3yJX7~03`xF-qFX}hKBg#Whrx7Fj4lL^4xM3rI_i)jWAtQ$l95K54ec|q%i;4yh z@7}%>o;J$5qj9r48v7eHYS_K^z@gpS6b&D7zpp7TB>ObJqwnCsng_GRrH>drtg!FE z!7jbu?=MP=MD^LdPx0tsBZ}Z3Km7`ZjvPGrjy^8EZ_#j<{=h(&-o=%Lhx=VR>eAw2 zxRT!=Ke(9RyRl2pYlCO)BQCx5XqVn<;E4R*54B>y`$W$py+-uH^P>O7O4;Cu0vewC z{x5otmE*hy*IN&7(zsbuANqGs-+{gQw;wqI$<;9aUn3mdU)So^%hj{oI5Bd$8Y6qF z{kdfG!>%mk@=fSoIln#{gFq_vU9Fo>l+pE&cv=sv7>|L8rNB zjPAgpc=tH8*I+S62M_GcftK9&Zd&Dum)B|=Khf$we^*Y5>%quvEm{ZLX4X>>Q%%(HsA8SS=TdD(()q?wj#o z?RVb$qFlFue_MNC&@~5IxN_U(7l^e4X9MLbU}}`y3D`{ zDjqn3ol6M2t6{f=+1=h752Ik$l(U~H!95_&a9r6NQ>{R;|1<30VD@jIASsz~o6DsE*8N}$_ceDJmi-Gyu=BE5|F$xN zAN%3qI&4BWGlL)u!iK@Hk#Po9fbb?WIE;Fxq(2O9Xj3J{-MWQ4t%uK*e@|YAPMz8n z3?Ec5ypY|xmBzy!!0!DPj4HYg2QVrytOGarSJ5>n#3x3<@DT-uakx|GzqIYp8d`6N zUB9C1gIsvbyT2eDYS%6|6u!Ga-r?seVP8vve`&{CO89nd3dF}Jv{G?4ya=C>7=Rw=?1D~3SB)Hmf~9s`2-qJ)$G@~LBIzk5 zM4wnnz0150Q@r;rEF8vNNUphn*ux>l1p)C$(ZIe1^4Ex6C3oO5!+23~gHbN%Gh|o+ z{bs5d?zT|f%OF=Px&wz7us#*C*(JE8LGeANI8RX=K44(KSn||^(mu}X?UqK0V1Og} z$c2Jd_u{kV7`gLGn33togHb~Z1{bj@ogzRN!QcDb-)FJh%lpe;3Pjo!L_(cIaQPwB z@UNolx&WeK0OQ-lk$vW{RCHB{IWv@H9#0Xz(wB7KJdUG0k%u`^kj1aBis{z7J>l>QAIigQVJ@Gb0{AqXGCKJB71NGyY5 zgJk6UOHe+{lshRd#phF6^ej?TsPri;<*CuKrgUHu#*SCEhZvTI!pA2-D2 zos4@o>i3D}e6#6;Q`O=Ec5Xaej%x#`e8xI*Q0X{-&lN-0Kf$^8P!XuHEgAJ!Z3>`WY3vxwQ zdl^8U?=l_bEWh5oWSJ8`ZK6Vu?S)EbPjP;CNvuwtvGIb2%V2nfCkQ^v7&x?lL0`Pd z5;Q4C(sIQbV$?-q(l$Y&e8U~L3yM+>`){1_AdyHFT@Q!F2!1Ef(pn2|REr2_tQI-L zo$X6p9OG8#BFfEAm2vBfk3dkb#gE!qxJnBO94e9o4l4rBahz+c0xRQRY>>a%SS#Xa zG$I-gDN#or^W8+IVng)zJjWUwzZOtUB$uU;iZ9Mmx~GGpN2B6rZjHxlm!nr0Os8BsaA(jK<}mv-r}y9B$mIf~ZEp<;J8b_F)A zer9S9ioo|tsB6Utu)6j#C(+*@w}BZ^iA!$U!793XSu4t(KW+@x7K<%0ZrsLDq^~kB zyCaA9>TkFB{>J)rR*mY&Aq9AkFa*_iTq$yeck6Wv66`pKHh4+)t+@5Epbb_?+Tcr! z-mH`JHC9Hm4;cBHk}oeJh;e-C6~HLlh=e3f_ZNxC(D~U8$AW+gp!#ck8<9+HNH!%;*1a|9;n(1+VepPgp$* zj-A-wuG;2nrN8Ope{(UTlTZA`s&WWe^i3bWnb?EB7eCI!zN~Sar=9o%RB!vlU!H=D z`^!^FAnyk9PM`h`f#2t&Z<(yf(0BUq2iW+Z!+OWWLwuPmzBn0QDI0i~=s-H7^FHXj zM_hU`E>C;#jV6rCd%n^M^AU*&Ggu_>*bWR9cwAtB$H0DK0O^duhd%Me&>6iA_?m!M z!9F4|NM~S&(cMGT-M&8Yr$W7~w}%k#1#H~We~kOn_@+_*m&QJEiug|;9wEf%;}MV8 zARcv!_%9%S>C-0*;hxoc|TBnH?q%&IIgVtG}euijGr$r!>u{vvFb;iU>EDPs}4x}?WKZDLi zpZ*iknG;XvqKVE=Hgql%9Y|+%T>e)2Z^UJRF=Dr~*!*UKR?^1p7waUXGX~|sAk8mU z=y?i*G=Jh$RTx}F3?Q8`xCRU=`Sq)b#6vWB8?h)<@|RB7$QH-f`Qo_N6TRBRN-QAP zI;C+FXx!k}ulMU!iODER4j*H3gWuRPt_K5kE>$&g5?OmQg$UAFh%|8X`1P88y#{gX zVGLD}k@J`+)s%E=n8+!^m`)raopHP!95elT9U?d}er9Ew_|-A75+SQkbReD4X#zTp z{CWeTGbNr*BNLqlHgvLx4x}?We$Z(~Tvo8!6|AcqKfIm=U4>ojM18Ztp67h|5OX^aJ|>BcOs%Mf+#BmOYUMs?*%QTIE;2O z5V%^o z7s+*Ph=~U{?c#Ma9s|Wh2htgxQJ^!DxTux;NDR&amNOVGS-BtN4Dc9ulo&udWAM1& zu5yoojUg~dXJBK|-6yEKO6C3p;(d^fdqU+t&MD$VAWk4erE;HOgZPwF#Hm1>;@2k; zs9L#Ckr_70gs)`SGzvMSvyjgLomqZ;2GLO~_gNsZi-lcQ?la1!HJ4~XI-~VGXf5>X z^NE&Hxi2)anr~tyHuM*W4x}?W%Ry(EUtdael*)aXiOy0RIxC0{q%%6JLFX0XqE_y& zn4p!kSwjpUoiW$|2J4A|TDh+;o55?u0MZ$QH^5+vU*AL|l*)Yz7RL|S;wUTkO(s^N z(%I^i#xBs<;n%nO^=-sNsoZzS3B4T*)VZ|H#7SiBZVC~kvk)BsxBY&7pI_fg+|=%#vn6bSF^{!>Jb>EGq5|*-TKsBrDm^>NdJ?KctXwI zz$s!AAT}aIrDktrgP7$MF#tqgKyON*YR&GGxz*H!kIzw9ZUrgWkj{dg3nDE8dJYj$ ztM!(EAFrIV=hzVn6Cp@vgzg5RwgJ605mM^(wkAHU&3yQm5w#;akk06I0-cTlJ)h_( zb$Uk=oqQWQorw;lGdf*CrwegW>+~*WXpt%p5H_SU>;ho-AZ)cl?_r1CldvJ3VfP1i zVL5Sb3up1Z9ONg3MkB>7k zD>3uo6Z%P_1L=&;)1WgspqCOIr5>MbqEl)^XDZQwbVg?;=u9UrNWn%R&aX0xNLqah##age(S++Z9rd5S;RoCyJrPUCmc(xyZ^=OZafC&5;|n^=<|biHFpeX0RcfK z5A*`Mxrn-{)Z2>?-G5os+l!r`Ed$z8LQ`t(r8a0UIYCjKH)+pkNY8T z4-l?eQy;Ly{fKZOlgB**+)sk~#{{j^)1P2*`-r{xzwSLeoOCO)E;K2AY_Og(>znwO+2CO-lvpg8K=O2?nD zsFyuCB26HjA!h)&c8;zQxLPyU&M|6c&BOzFbBfolcns7bI*`uj)CZk<#6_*1>*bVA zIFndCf5#c%5r>f?Adt=&G|I87pkrW-2@KL1SW|R2i@K{+(OHQ1cNSH2GpC3_Ao>YW zsigfjh}ljNbAi}0N6#TpwVG}zGc3o1uVh%5LJsLHvGYpJ*u+c1IJdd=o2C(R3y{kk06I1D&opdKaRjRM}lkbh_Bk z=}vSYozdw9It9cSjKNwkSe>K4lB2&&Jk&~kwYsdJ zUVjBGKe2^I-f8l3*<9BVS4d}Ew}9)W9DO4ZRV(*RiN#@bqbXlN`V6n!@fe5_EyzDg zYg0>9?z@f3y?UsXUM-|w8xqC){+77c{~~T({~Nn?y&CRFAMXY5Wqx<`Wl!{4v`l0z zKl7HK`ENRwdf9I};xTYTNK~wp%7{mN2o#BgtCYbq%%T(5Nbwj z_Oukgnfx4!PBRk$vFii~8PXYY4v@16`7DrgHCM^=3^`jxUf{*=MB`$h1tCK^L(T(o zIHZRNJS8ON#u5e|2KXr)M&KbD!t)m~QO7UvvUvg`V!vtSlt4QWxGSW$Ap%#$6Symm zKpPtZ?VS?n1OgpHI{vm({&o2E^j~Rp;1TE;MD>tYB6WQ^8~h$D(eA}hw3|vpE|EQ*!uJP!VMy;y@W%=M z6$W33jbRPj7*?=+!(+6!4UGXw(l}^rS&xFoBO$$*XsBD(BjB-t@sL|qFgJb#|NFYW6SymG){)}<3vN< zvQC1>UdBUiS;x`xK5L2JvOeJJH68<}X>cI_=-{Zd&Vtq%;-qX@XAp=F*i=k-mvzo5 z;sqf77}C!ZsJdnS2-HKgWt}%M0GmTR1b7Twq!2(l3&9l-`Zc6qCPM0#^(#p1rY-Ao z*@RrV;+-#~GeTG8w$jVx>Z$lMqO81Cx2$rxF+!<$u8xrsp$bF@(ix%3AXJgqC|g!V z69KVhT|>x_&XB7Dxe6gGTUHenS*}{u2pQ5D^36cLF;}ln;L4VDBfyO_(w4UC)fzgi2H*PCpkJE z178q2Wb)`=<=TCO9|Jm0K#<7;okTakrfw=9-+zr5pJd~l@JnZ>oS^*&Xr~EH`RM+% z4cfO((9Q$xT(15d0jeL{pOe}2oe5jXrXMKGkjaPnGN@e2)h`eg^&|UBAaIO@dKy2_ z#(D0AvMK#SlpvF*looEKr-XG^SX3Fx$Mq@UL`E*OsOcbf`f_1W^gt$0r4p!I9o8!l z73HJ)t4&lY*iflVR3MY5QWaFH5D)cZ`YI+^B~7XkI%M+bHv#|!fCeX$&cr2m>7xUWv>$o^+2I+SkDOSwTXrD(R|&ou?1uR zU7a(vO?*U#-cF%`Og=PO;MF*+Hw^1{5HIy(`Nk$X4JFk(OvIGLxs&)oCeN=q_yxnd zpU5d6$p=l`{3b>sR5?TiGI=U_pb`%2A)=yu93M7O3E5C-MN}Y@r*b!_v?U(ONAYb< zs3LdUIYGMzXdMVm`53+f(5y@n~VQG!f{Qe9qQKLJW(!un{Uq#g*30i_>Ul;nZXXtZ2lE%66Jmw45Q z$3O{Df=r&$L{OSQe3ZkW35drffF~XXJ>>*#D$u5c^+^P%9t2GR;uSgwnq)!;lPkRI zcnnOVu0tl@^*JCjE3D5TGU_4FED$(Hhd?vRCNr1FKqgOS5y&hE>(3Dx^#Eu=9GU0J zCi6UzflQvviy*Uvm?(!oOHANm7gsvP_*S5f7A|CNLanLO$`psoq) zs|Z**^jQO7z#ma0{F(TzJb7%1D}m?;2UhfH#-4;3*cMBdX&JG z!=9~i;87d!ZBD><0DLffl#!$id!8gAJMdV7~{{Jz;$}0V{_*d&0&c&u*21 zJmlHu1o|UD9}MgJ30gVeIf#XR0&**Mz_Z_m!r%Wmg`+p-yX)k;Gdj5-akhM*g*a!( zch}A67Qy*;DehG18Nt;|{s-OJ)2gjIyE@|wA+KEdU4OuzLDbK8-_9WF10pAaTLvO} zpNQTo!ryA!?tFKHXrBoCYs^jf{Z_SngBXE^Tth4={UfeS-q&{FdWPb8z&g@#wLKw$Z8?(5YqAO64Anl@m@lJi(9)a z-Shit+7a2Tj1$ep9XAc(hGAXHzk@(n3RU#!&WsGYIf8ws3(=NWn??sPc-gyrcQYPu zbTpZG2lCy17ViM!-3;-5IHDIt^dUyPgBc@~csGw0A&R>YMRtE%E&rntSM*`Vheyuq z8-;MAE#I9J7s}yi#D#o!i|CND#$YtlX_;Wi8$+OxkxOI1zIIfA^5_Xdh!0LbEZr+( zkZUsr!cs;#td2p#)kt(iYz)x5e0Lrn1NJnDoNtrwZq3G^4aT4o#-Jpk|1F|F9?>5& zhM{e~`|jvtWyS6(#-g1OyQ;3hI0T(HwvRr}$Ob1y7)FQ8Ql^=269$1H!*EZ=_((<< z7Wb<7wh9*a5|9{Q2@1HG@o(^36=P6UAn?(!Bq>LrD$={78rlTJzXYCS{5oY$Vxlwf z(Wk0xx-;8*#nt;VC$pQh0PJbcKPo6Gda<& z(eW$_n2sXm`R)gJDj@vHq(YB;cXu{SJ&+0yAQhg8=u;#56eABF%$UiiqnqN@@ekM{n;W-VrWId+|13t!< zn93Lz24*vd{SZw4q<6*~9!$U>bp0}UWB=&PSm?kk-#vhbjy+9c77faGKg2>e2%) z`xYS)D>dBZyNh`L*wZBXSDf#DnDwt1{R^XiFGlnwM(2h{mz34H6%1S~(SprO=p1hx znbDd$cOC28i}13G-2}SJW9>1%OK_6!euQ_4J&koK)%~`w7QXkWvfJ%`)8`sK2w&Re zVqd0*Z-TCX`~51XluvcPD^+&-Tm$>EFG+X`CRM^ta=sWOV-j1 z@3$D{Pyz&|iYELick!o72+fq|YV3HqD^QzLL=G z{@Tv+ytF)PZF$Dd^0KtNXl?nEou%7vjM{H@DpyIBG`~8qGL+XsMMS%j-zC3ED>g=1 zh`HN+wVnCR65$5FDKD<~TSl>}owIc5%wug?(~MEW&RKowEYsRq9Xrb`Y1zoyvVomt z0G1+{&FoZKNaxuJDsrwxq)Nz6rGr$tyNpq5>&K)UHk!VT*GT2od_-H@xxQbzzL%L> z%~`j*Q-ZZjr$N$sK!QqpWAYYDl_K+S4zaU(R9cO+qSe9hK8E!8QZf!N#CSZB;5XmU ze@d!Muv3{Pp{IbbvXo4+vzaSxW+mnj`~E$*dxo9m3(|6-wdH&}%N5dcnYHCoJIgiF z@)bLk*QCmNJC&_a5z*danUweNj&HIv-z^b#nDb)0b&s~$IXftw?YFkvXU5oT=j@1d zcG%k4Av?=s((-d_%cFLdCtxXpdE8Fr-_rT11Qj{g&PtVU?Nol2Di_KawI3~)l8$^t z&)d093m7|;J7BStusQ2?UrDf*GxH{CT|J;~UY%jc=XWisQX^p6eQvR{x=mVXR{Nmh+6ThQQqt7UCM<1Q1`_tuR9={NP6l^%8~1E30@VJED?&#c`?MgM}zE~ zJuaP%wzeE)#u#bm>`CctoVBwOJIkrka7k#lX4RGDw5 zvO=mXD`V7_vPoyEO1kqAU2Nz2Rq1-I-JEs1S0`A@nK>zFEJPE7>QYi*Oy22IWopp0 zluWU+nk%hl1ua&%o`&}Yq{o+%#dsmcV^MkdWQCp0MrreE z&~hnRXJ`4Aw0y(ba*LhiZfUv0+H$*{<@?fdubs+AQssc1%BN5f(f%Z8wUqSciTAOc z`EiMG%$yfrSoi2NJ7?cYXQ!<#Pnj`J*g5-2Iy-Oe?3|tDZ_@IzwdEx{%d~7GnC@(K zBFWVK6I8@uLiq$0IoGa{Di!TiZjvh1v+YN%TDH|v(ua@eb#|^b>ADs(Pke*J=B(R& zYl5}xo+roX-mN)m1o|11w~kb)onu-`G&?I@TGh+3pf%L+-k9|GQql}BL~>^(_$@N@ zv!#mPP9-d%TY|8%l;qgi+%0X|{J#@=Zg|l`O z`m&wtsC2!_ZqB;h8xySM%)B9FEG5-Ku0H*S#+{6g=eXB~TmzKmiD>5Y{#KZZ;N22( z4IU78Vq0pc)Rx}8Ay?lxjoI9HEjzpV(k@fAE8%u^?Ci3nT_Y>I26lDZ6%mkd$W=6QL|lKxauiCie9?$gdue%>wPhPS%g)lWqqSweon=?qq5Be4UbcyL@!t>NR>+s<~h z2|Fgi`({JsDd~NJnjLR(-{b7;o{@G>t9I+S-DEqvXQkb2E4!I?c8jFld^?q;Qso6Z zm6cEt*|^*~GnOS-zHP*5y|i3oZMn+Ma`F4a;&BkqZ zM(<0by)a71#vOe8cH7yWmYhx|X5(INc|0*2-#0>dPQso^@cx0Ja#4E!QO%A+-1m7q zJ6Eo;V*jez?dEou?d&Q@yK=e8S}g2RbJaCm^1MdcRkTy7CRM7~soVk;k&QRzTCR=N z6D*Gyaq>#bn%0&z>@4d_%iF9i)9oyE*`ay~Dl#lt(s?69nG~U`cD|%kCPtX{7>P97|*X0{GK%Q zzm+Pd?Nok{(C0u{Df+*&v-w5ZT*^%-`j7DlUa+$)7dB>2O4!oU6;=Z)yHZ(NUTtkz z!OpUpw5(#MaRsdneM-3&Xs=cU~OE4%0H?3PKpC3Y$+rOI+U zmGw{&0a+8a+}KtnSh{i73=idIX}Qtba)X`aHfg!l+A?Zqxl?v%dxDA_zJ1d99)wff z*mm0){aqRzgi*rAmWCd?-TUoqdq%{v%!AS&FH+s9DT5+4VUwCNm`iqBP+^3H7kuJw z`su^l;@)S8TV#4gT)pEO*_*G*Deja35m#~H2r9 z#5HiJ3R}dQ;sC^_=|ikhM_8ba18NF-_hh6h@9o6Mb*@yPJ|$SBmPV?v>#37SPL5oU z>nsW-k%XN~eEjyeh->J`A+gw0b-N#rxcUs~8*9QnQjb|P9G}3jYUNZ!W(IMb4UUZK z9O5{aI6f;mJri;D8y5E_?`A&UQ_c8Otnp`B;y+LLi{(fxjJSpme5_FE(tNla*)MJ^ zL$V3XDS1*y*71HaA@H(P6PFIZP5^E2YTvzk=z%EzC;_B5;f7^cSx4XV? z8J&J-qtu6%|3Bi+1UiZ;ef!lCM+Z<521Ez-)&&KT0)i3J-I++IF@ORQLEPdO18E?V z1=ESZ%rFLs5cYlFk$smvAdBq#VgNy8A6AD=WZ%B0s&3!(?W)QdyXKsKpVM_a)$jX0 zzq{1EZ>o~2j0oI-$LmV`!0*fQCwBH_Wp++%;PZFL&g_`jD%GEpoc4jQZK{%>j1B zmd+)4qz@TDhLZ7Q68V-)Co{=xGM_9Y%gIXeJy}mSl5ON1IZv*UTjT-h1&zM)KzWEf zLLMcLmnX^7B65CZ8`zo>;HCTh~T5Q*0`vbP?vE886YXjMY+HJ;m z3$|Oa-G=RUYwMmXLk0`w@Ezv1dQ_9KfD~*z*(i9KxQ%*z+^? z90Aua&^wB6j^Uf*_~rz@JBe>k;k(oL?%%LF1FN&JItQ!su(|-Ni?I3?R{w$3C0JdC z)fHG>h1E4!{RXS+u=*WVH(+%WR<~ev8&-E_tC2lNWT1#^p+oyK5{O4xSQNh&L#cv9w2u|fA^3F$$9c% z`5W|nPkE@^OCBcY%fm4mM#z2Sk?{WzkZK=hM{ehSe~Bl^D){S2a?Mf7usejd>;$Un*#UqbZDh<*jpuOj+2ME?!ZuOs^Jh<*dnZzB3FM8A#bcM$z9qTfUG`-uKP?nxfv z{Rk?#^qky{o|n7R3vv&7QO={k;^$2uX{LMRCNU1=N?IKMvtPmqDRx)(PQY3 z?y?lE&|kC=IMQ_Ot&yL$n>;a*5@y1%0r$RfHUYBAjzwS?}9T1w}~ETf~9 z<#dd)f{s-R=s0C19j~mS6O`}iL}fMYPu9?%1eWx?vZ!Heh=MD_R@JZ_R)KoMeoanc<-lU z$pJc!9HisPPjoFggzpa12lCH&AE7w1>C_rW=|pl2`;XIy@(H|8(#hl$okC92Z^^&u zni^;5RC1P1Bj@OJa-Pm07wF2W7cuYsO83(L(8J^s-k0g->Q`u?e3i~5*XT0Lf(OWT zI*a^{xHsq{`6k}C=p1sJ&Lwx~JaU)LC->-gHSW_f*=(+Mdr# zO46f84k@MQKPG;X6#Z~<>1l`OG@U#4;4=DZi}h>ANm9AePe|%_W5-Goa#QUU+~DdC zwYh7AHfPB)dL>z-t9IRCGdsktzEq~ZR#DdQs@hnsLPk?r=k~+$2vm&rZT#r^Y9`Y^^e4Yg6Y=r(`;*#aW@OZCBPl7Feo6TxRZ>2bqOkc$ zQjp+fb;LIb?eNBz39ai$%G-_bsc8dAY1lgtqLG52x&rwGc|wQUW3-;>(Dvh$+<>skc5Ej6P} zT22ZQa@LLhU#G_h9agYI0QBc>42R|n&qa|YQ~tW)AJVMV|0=tzzU|m)?UViO zwdl3-PJJ~#afK&l;nKpP%O}q)yVQPkUsjeD`z_+T*)_4<>m|NwSL&Y^e1&Dbf4tGz z(HQ96)C~L{mXVyMAEjxjtu>*^tu{wI)$`tby5u0OHsPJvh|i*>g!kTV)}lp|B!7n_ zzfZlei+@eRTIs^<{SC$Mg3DL|${(?!Q4-UKb)FGa)a?f2hL(nnTO15Zm2LhgkbUZtdGU1*Jf zFm4Bj0cLELQqq$}!2-s7sP@%kMNAN?`FEV#5c+VUMwRULzW?!iEfbR7|4DFtO{-+Z$i`eSo_G_AUdcrtinNu3k}%$y=m=}n!epMDJ3U89ob-R z75$rtPC^w@GjNthJsYSuZ9UX;y4s(&g?>;6Nl`xp4wGpxo}n7I5JKvw;EKk_Os!Fx zM+X`e{6WC41%SWdW7h23qv)KZkUr*Bdp!`NLebH~n^wK^0A3M$gc_*>fOp+MRAjzJ z`Daxo0Lof7(17Z_2h>21;qJ$5BE%@p$V~BJdNZ3s7HJ`mctWtz7YFp=R7!e0Rz236 zzTL7>0+#mNMoc0_Xi$Mwoho){f#>rU<-=4x?T1$>X=BhZ^0a7#(4BP2h_OQGj+yHD zLH(dt57V7meloSz*89OQ6m)$-y1)xQZS4wKi8%7&y zd?fH==r6_z!8qn3dJ2H*Vj@&_ug3Qd*J{xcD;F@>?=q#NLt4kKin?_zazFZpiDD9O#A>CR2V;kF;iO_=Is@%JC<+ zvznbwtChMcwpUJiQfjs@-7hS)|JJIt)C5BPjg&259Cmfk%#+jza}Qg&77TK=*tupac)ia)@<7i*^0E z4;nXXSvN`_m^gzXJ@aX9uG%#JXRrV221N646YJcOVAO82w+hp+ zwr=T0&HD7839Ur1bd^cZfad5 zwvUOSv?q1|)h%Sz6>e-@i1r?<_Ip3A-}?m~A9&EN;?Gb##1w^_TOYDeJYrYzBovQF zD@U2Ac!TTXe1sh}=nEt46l-#n_L}?xaLz?5XBdunlk0PUxLO**{3h3DipRRhuu$5= z`VClDqm|1HOSsYXRRh&!1C>54TxU2a?cv-7&h2RBCc_bKc75A`bJGIn9>YOt4@Yvw zD-Riqc*E<525Di~IGp-CiP9dypFj}d)Mse%rq>b9&_h)qc!Ck2v`6qX2ueGZk_V5r&5&x3OB)i&A?aH zK&3ZX4Tgi#9?l!UiF7Kp7>;lw>_`JnEeo6|hJ(@`juSZb7>jT-?0N=eeLTDDD#k)F zhA9d+#EyZYS?cu`t1C)-b@f8o!<5CFVtWkI7>h;eM*~KH(jGxm5WMSD8atJSj6=LJ z_PgS=f*WHu#-1(eM6*uI!q$<3hQ+fsW2`9cv3>~F51dL11}feh`vYJJ$zeeY!*~Jo z7&To~x2}&E7Rs=&Mg=nWFM!paF$tM_djRZGGq{kY+aoh0ZMxW|8!bq?nPo< znHWlYV%<>PuUU14%>8S$_a3$1Lo)a7b`^U`sq|)|V&>kL zkFeebePM(RU`>wFUXu?8&QPZ^nBj<-`%pk^RGXb=?t_cR8o{to+QXUvtZ`0d48syK z_i+ZQF$OAqL7&KQP};+p4xFh@WeUR)GWV$loGBJKGZ+p^dpL7}Gn=u9nfq*mv@mSu zF#?qK2o`~0AtMko_l3n1EM^2K?Gda5!3w9cj6n#Q`wC2sd)3L2XYR`kRC=bf$}Yx6 zV61m4>zv9OMj~YH>-hn_4g}({w8p@skJ?SFiBQ^WqTOKI=~T8mm930T%-nYxkhXK& ztp+$@Anjp{DD5%+1jYkSrH}y%nfn0)U!j3YZ?Z!S2chz@B~TM8h-p>&3I)WvnRev6gVf zD-M_Ph=GckyTcWd92Pt>j2A%f)-rc&T@fz*j1J1MuqFmF_ve6B-eq#my}T>G$9^@H z2+7-XQ$|v!|G@W z&e?y~a&~N8uP_3X_6S~cS>^0SV%3=#N_%28QQaD>xuTdxoK z9>RI{SSuhe143yJ=v@Fcb}0=RkdUW0Ht;kw@@N;{nlK!c_HbGNr@2c>U^qga-rRtb zV1d(;;h?mK^D%HfWGrHy{-IG?A1a?PZIt%3lc4<>(-t%I&#bgRXWA(3X}5#6&!x0s z@CbRb+QS(FoI#95$j1j6l=YE3)UM)4C=O?e zLOwnmie?GbC{|aL_Ubwg%43+an2(P!NMn^RN-f4S0+jX$rh{OrOPS(QCNT~%ADiLZmV;yK`i^0t z{G(X$_`8??r~S=KzB^v&={Cu~d%E*`95>0od%N|_A7%Ke1EJdAt@LHWV(#7F9mu`= z8X5H2YY>A#89u~tKn!IBV%|N}ou79iH19sC<=xo2Mlf}h;j52vTjktELSvZ_%J79I zqMGAbHHCb8JX-gpNxnVFj@neHO<`(6u06#brMr*mq6}a65Ofc^mHkXw$fpltay!NH>HP)@JqtN(NBk7TPq>w1ZsixIFXYlE z_+fbr>f*8Si-AYarBAa)K^cCd{0CeY-O72la+Yz4dGtjC&Uub{)(EB#lS_;YW%y(_ zKz7}&Tw_>54t?D~bx%g+|iR*|ux44+K~+siS^iwsQ6 zm0t#okf0U3Xc!a7l}~87GPW+tkWl_nq`iN`--zFr*x!i192>8^7;BO*zZjd}Fsw-sCQE2ZgCRubnyNYfoI+>!7 zNjohRW9%x%L9u?U63axzY`Q)lVX+2%VT5^ElcTiP7U|2$i-P}NxV4%`7nwAU)r9GTaf%9>!@*%?!vh0ryI3HTz zBr+V7_HdGclf+oWOgqUSEexC1i~yxQf_5PAF#<8?_7zXio)Mt5N014E^jM_>gAlUs zbWD!FsgooBOOp-;Dm@49XcwakFgnF5IkAeLkqCKsCw@TZfIvK!{01g{)c&0{5lVYa z)B|kYVwJCBm9C6U%*DGIkiO=)T@7%;K+0o`DD5%!17n|9C7%HbS$Q7=U%r7#Z?gUj z2cvsGLvzLnfhFDT0y=( z8+&f56Ak}MlbOY{E?}%E?Xj)^>#|s72?G@~_hq5UVZjo^cmecfEpx}#Rlu-N{!y%D z^^v)63S{o(J@HC8kMfL1Pu_RdU!C9MHj#4wh5uqLD2KmD?;%6@p7s~@_ejAr*wa(p zb64AQmo!1o=F94TI%4ap;L)>Kl=iSH0qX_Ew5R^+?oX7EatEnMFK9{-1tgxreLL{a zhcDVytPDljqrA*S_p1$oKRU=As;bIR9VSDsN9lr>4FsSWrZoY!t}3hvP}*yP*8%jJ zN2$ty4hMinsz9#+B3A_(KnkiB4^)Ezp|l6|27n?xN-YL-OaO`u0;*L!P!t0~X%EN= zpn8mEOa0aA>7LxtYU|W90O+fZiz%bDryL9A7^Zv`%5hZ6ouDemh{|JS{7*E#biKut zQQA{}8_Hgf;$h;CdGuprvMTO{_<5X+z^1^1&)?!e?J-tXj}w6C>rK2}fF=NV$D=f2 z08a!1yb}b_$O53LU4Rw^6en+ z^C+#E{AngXTb1`=VVI{b3^Ua6hHXJ>3yk(*V(bYlS)GCLl}E{97~+!k6*v~D9DK>j z!k(q-p5P^Gxi(*8>*~Tf2W42D!?C^wR#(O(ELmOA5X*~(1@DhsyNW%bnCDTtGf{EL z%7f}^wq$iT5MYq5)|voYS1;BCDD5@D008y#D18`^xMcMM!~(Wt^(h``AOk{a4`>8{ zhIy1B3`ktEh6Mo)DIRDf143yJXdHmXFdAXW8e;&^m#pzj8Kpht$xxoil!Ya0qNvPg zttm_yr9I`DP@e8lrZRD1$(j!Fz>+l;pVz9#Nyw5l%PznI0L=3!a~OcIWX%f#m}3F3 z&@R9-04(t+ix_~gWGx8-SY!dP+%CW>02DBFVaY0hV$j^gJO6vu`6%sm{(2~{^C)YW zxUgic<4e{W5ra>W8|=z&hx}HLvWdwHOV(B_4C~c}fiGE`EHHNbag3$vZ&|woOV$No zobxEB8HTuIodd^Km4h!?r?F>;x+i$a+NI6c*t#yV&O!M{J4eL23arbFNm#Njqak*w zhhoTYS=a0;-h$!{k8+)fic8iFs1~v%>$-seG=*9dVC%ZgngFG}CU^v(2Oi}f0}_|4 z2Y}ebmaKcl14(iEZ@wt)0X-2HuRI>7l)#-W)$~?evL25s0xE&eVjl@D^dtj9X%FZr z0F`1i!je_W0H7~fPcvnd_LR#)xeQYlmaHN0s@$#TZwum07AfiGEgEihvKIEEL0{#sf4^VhvV*v<5X8%OMh+A(#!hy455KGyaq z|7hD6ss04j193_r6BaM!ABYQF$}co9faip^GGOaE#86O%k8%_!M;M2A8UF}+;H=sM zgS8W&gS8W&=QMR}UB{R@%J9`s#aUg#FA_STDIOP^Y z5ii-_0l*2hsRw8$v~fQ7R`E#p84}9yks`eD%41$d^6FWJaJl|5Zzz$3J>qcCSNg}j zdeVb3e3a5aDd|<7WGKR=`jQ5eCoNE(VkjuXM=1-GGK@pKOkc(zD-4rzOdVzT>J_10 zfvJm^=qnVj{ybAh8NND!`b%D=5(5w}&%fl&&%3Bjdi?TyB?FOudRexEP#p->yvnOy zr3#}EF3nf-29|(Vp)MXXRSZ1(2z{M34a)GFCJJ12yh?4aQj>9sm*wjiaB6eZng%do z;JnHBP=?Rm^^f--!Rw}ImIDjtR+T#ok|P&^hW@eBoJ z_$coJr7`0WF2y%CsOn?4i5<1~pw^73376rULCq{>YR>A2GW!XS%r zSCl@qV(KWvS5JcaXI|w~uktZt5HG)fCQci;{QfESTvjI%e);|5;yFKOoG8QROa*5< zui|5n;-&X?KoSzV0-s@g0Qjt$;;CEL7YqqyI7rpB4Et*!b@eJ;7?OBGs4I|uS6hjn z5bAMlcwZ;lqpv z%vi57n!$)CfW`*Fj4mE#0)s&rKFqg(naoIplRuLU;`%Bwm8qf(Uv(x_r!!UI#Lsk5 zmH+NPi>aavUv&Xg=XsSmOjtPSGY`UnlRk6sxf{hO3_0nu(2n>rh%fOfid4 z_#zAO<#xnZLwuE2DPZEl$(~g~;sqAsYwU=xhxj_CES%_B2eqJihj;b{*4Ze-@9b?* z-Qra?F=62(&lYdsB+n)hfuH2rZby0_r1yB0olIId!LtVweICYE(FvZN76?BI2qheA zqxC0_I~?CfOa2ac;su`R{3ITInENEI&uh;i-^@)mL`$hD>Z7!@=RP|mJV*NnE3cj0 zYg@FWJ|iMI3lAZQ2th zea=OPJXTzPjP@BT&+FXts=4Q7E6;n}^R~I?O)F1_Gtg@ftxTTaCJ|1tV|i0P0~5Wq zOFJe0u!^ESib9(^93`#XpXUk{oQ84n7pG|}mbD62nFk~0o-Y|SDp>`q!GpbK9;~XB zXB790H217!<>`W_-k9~QOy1(bV?s>$vDSc_c&tpCag%q8>9xjA9CYmYc||?iQ0vi# zR-r%Qp+8XF&5l`zqeX}}A5I;(cl!{Nrh$Vui<@K`yEEO&t26h?F~e#Wh~AaiX;Vpe z{Gj*8*CBBe0`|SQNuHI-0507Zz`|70+sbDI_Zb>GhSW#gI2?nmJSTF`aps<5tUPCM z&#C5~Q>;AaanIRSCX2brLMxM1Fwt9kh3TMtPpkMcEB8%YVZCu&tTV6C8mnM?c(9%3 zp4*KYTdjf};=vA>2P?GlJi$GWntL9x@;nPqy)jQ)nf%IwpARwN$J$kHa>>f%E;qSV zOt0NAol2T(J$l_Lbc8FgLOEO}Q;B-aIvkHey!nw?k$abSiHlcDIBLiD%iN@r%dq;q zVCD4+_o8N49|xjWXLg!YE&QPOM~#rUp9JiqxJjgyiJMDD16Y_!>RS1Dxlesp$a-1= zPx*5=Vy!%zaL>l(o(-)$TXN6l=AH>wo}X~f53Ni-=O&+7nY4$A-r7EwSyu9?Hgwup zxo2^OOyjsnH?L6#t6=}+!Md1xb~0+@SOxor2kUMgEZ54jKlkio?wN1pITW6HV-B)1 z8O4JS4>94#+IVg<#>!*{HZ zv>tudDm3MxUsl~if5B0YS%>4r5N}>R5*w)Ai?L!0v<)1*Rk=x(Si@98t-KWORXx@O zD2L zjr>-@@_4Xr=AK_0HM&{_>(7JrF%On+-F#$B4e?wXXs3nTbDp{994pV|+;fS! z=OQc5?|Fp^LQHt~ZQ#Mzp*h9TxW>w92Y1>Er;yROUhBV2R=yWG)49;mxK;B!9Xc9! z1e)*~m%SVkeOJKbHjjQo936#P?CVy3Qe0rhejxg7(){jO`8~<~9*+~|V%@JqoH&Pb z&ZoIwDJzq5+@y?^$qO*iN8@vGrgLNY5YIz_c9Oa0OXi-HtURl6&sWSnD_eOgyh7DO zOn9?I@!*kYPH{BWvT};yPEI(5jK(8c|JAkf-N%`B$B9Y*u|QKD;wA^;3`u{XmDe%u zbtKLt=|3BYewx{7i~o82p!esQkhtdp_LsQHMJtovx%4#v3rYVKE1&z^=T2Nm(tkp0 z!CO|Ik9z}0&SPFvPsuAbEU(H_+_R*)=aW{R<+x`VE0gEBNd+qt876vbzvMMb`Y&n~ zuVm%^I#;OXHH?c_&1+P}D%hJmSRHfE+D465LRyr7d&)3)jjn5fqKk39KH~5 zKAdy8cUO1|+5PXDXBTfs(tiuPwd1}QT=mAw^NI_`oq)*z9=)$uSZE$;v3pzjjo^Mm zMZasB-(V}h3EXe2ncrwDzp31BvX#j!ZZh4&a#DsU>b{>2Snp0fZHd#6S$es4UDP&=bK#d)ao#wu!rIOk& z6_Qjct9<#3mzs9FwDGt41%uv!~$}8j}bc1|A-YM^ucgu6=ZTY@@SDs3H z(yg>V{gE~-QTb}=T#`rnkfCHenMA%N)5%OSo6IK*$#Sxid{5Ssjbs}+M{bb^q!$AB zl?Td0`V?KW(;W4i;}o!IWeb~hPA_TbZAvV`n|-H+H) zh&}tU=K%H`#Gaq9=MeTB#-5+C=Loodf!Ni+jht=<}x&f=3u(}1S+pxL=tGlqe zM+TGouzUc^hp>DE%Ut;;=_cPI-R0Y)hkS?R$#=;&@;%a1zK_0oK=S2>q__Nt^pSJX zZ{6g6axUqQ_W-#&da;K*NY0Z7%io|sd&)!QUh*(GUmlJ=9wGOUN5W$iJVwj?K%|xOOnDXF-^&}wYD8Rvh-(pX z9U}gKi0ct?gSz?<4vHxhHvu_ams}(sOb*dS32MFUURUMLCcDDt|-!lb&?FyBFQy z&ZisQz3Fk%hi-EBrJLRT=oWW>x|R;0TipZcHuoSpyvAU>htQwop>zNlMhBANbPyRq z2a}O>2pL6(lF{@M8AFGWv2-{YM@NwHbR?NTN0EtiG?_&A$dh3^g>EL_(tDU#?#t8g zo=(S-8FU<(Nyn2}bS;^U@8-}4@?5;<(KBQ|ok$j7-$MFO{toX&bTU~?cet0(o$jS{ zmwOqVS#>#`RdofOUA2Jrcdn!ZoU7N7mSm_YOLR?4;k4U34nhO{bAPbUN8fXOMk# z59Xr1w2&Sq`|&-BxmR~a+WS4=fHHHE+!Z7-3wBM+yNCN>6!X!f>Sd!W%-v8jz^Cq zsf1L&tuHydX6@R8Bq>+lQ!^#Y*CzWbAJz-}%_wXf|585+ubORA)2g&>r|o+T+Y*lM zs;ThOY}%!1`$}M2!g1#*!2myKHmMofZgqhw;V^{JZG4?Io5wYqk3QFa2-;|I{9Uv? z_#+C$xm!8tYwe?ElhRuI{DfvxSv3`2DnrRyb>578;|;=Jk#9Pk_3A~v8C{R>(mq7i zu3fioT|%O2!$RBhc}Yon^vEHl^!&%fPm-b^E-pRo@SLV|#~xfpUv05|?Knv)SNaJ_ z{ch}7NkT5By@DHD-Jv#jjnH-|Sw?RN*66C8+T^oC?CMKp>IXNxYNs}P4Ydb?Ufhl~ zzWS9K>J=my!7pydIzatSZT?rS>{utLc4`;=>r3@h(Tm4p9ie`sc0=dkMKSK1S{fxdTqGsCOGjTyYMP|9{qJ+9Og%|TY?IZcV|FIu^O2+=f6D5JZxY(!jV}{g*O8RB8{t#a29naSi=@P-W+$}%B0eVrR{G}# z$=S*HocTY@=r|-YJ%mpAABHZ<8?|InY3P5WPQAL(sNj1ksmbk{=44}d)ee3|;#bjU z<6pd2KFSf<06kF$?$MKi#C|}pMHS~Q?YWvF0 zi~g@`5$Lwmj5cXGDadzOH~N#?`uy3+=)Cq)8OQR0Uk)?R8q*X#DHQ?T?k+`#0MazyQ=@Upn0E$a7Jo$&|lt_=hxW^}ot4 zt8Y7YTKi;wdo6mcyi;F|Ph8=NS-7-t=<>-k%PzGa-ItZ6#eR$UZgx#<_j-x1+Lij} z1z%xV?;me;b~FZhH#Gyl=42$N=|^c=YHLksa;wb|PxZVvpDsB_t4(+(HsZ5rDdD}h zo3&`sB+1_)$?sDyMB!g4uvWS-dw)amtCn=Y71uZcd!Es!#8OfRkJc${)BABe;!V)v{Zcf%-hTi6BzTCMnt#Ws1ECKmYE;Q?@B1IW*D@jL z{SQ?!q+lAx7UL*S@2EAqluH5!%&OoP@+LHWkF}4?4Wff8!zvtfxX^%|-<#Gxsp;EI zlTvch(~%A4R?)wS=pvUz{jLp`Uf{drsH2X&AX^+Vt=nFiw-s&NY;WJXRp zkEf20nOdVXj}9~{_=A973jlw^$E?}6N6|S+A$`oN_Ie;jg`%T}H?6|zy+^2#Iskar z4Fu(Ujq=Z`OaPR%ZlD2cvp|pG?rLlz#3;_lOz~lQGn+ydX(5kzLa@;n2Oy}8iN|Br zW4-CyEgL0ZY0quMBvOP16ISXS4i0luGD3zg?a@$vhznX5Kyq9sDJ4b3V#ZEN_hq-wOaW+7_Pb0e>5$g(e$+psT~Z2?R2`G| zeG|975Mzl7`uhFASpL$hxBZnsjkkx+A3>AY2W;RR78*YV=PR>|T2*cOgBtbIW(~mG z>B9iR^MS)DNa-V{^o7tm7)RQi$`7g9&^oMXr3D{SZ1Lwu?x!qTHzAtNozyWqiw~Pu z5$~uL@9Us>A{04dr%-<^*gQa21URMzcq=*wDNo&~Bn%q-S|&yO(?p#6RfgYj_(cpC zta38+H7+=}IH84a=M0*l1N99WUVMg5HaFyTN)B|x3X>^6s7G3}HhjW3FXi}?+gZ&{ zr`1Yb727K(Jt;NYm+lvq+J9@+T51BJ{zl3cFb=yqXy!?3gt><;V7@?Y7VsmcC=*ow zaZH=H68M*B#GpE|+y%#WU~R>;z}9(w#O!yeQ-U@Zumm(>y3lDUIYqNw3?$ELHG4*z zgHtowW+t_1jRUwHYtQ{c+pvW)FpUj?`+3bh#jG2H&;#A`xquQpG|M5@1ufR~=RRoM ztYzIOePH4YiuBB$X zCgHJpxJh2_Nc^nb#$!!%yz+gteh)3-MtR>y<5uwMgSfhDclGK{@EiaTEAl! z%0K$Q>!R`|C~t^XeqiF_&GI%x2kw;ggMkA~S4*qU>%i8vnc<+chqD7X+Zc;@!@O;S4;$f_&cIIj@xJyz}a zep9DBfYBzs>=o{eOkEA za8TOAxeJ`z(aKGRBiu~ywgKm+1(3+K&9WD>>0Zl z6@gK~sr<#Mlw~Bs&Gjlc153tVKp-AVWerUFsC}L_5lVYaM8QU!%1chA5@Qo@uty9? zFLB&T1~{P`D>Fuv_84CW<7-Z(DgzX5viF*Sud0DcZ?YN;2cog<=d-6mGZ|14Xmc>n&DSl=kZCg|de! zi#Of#7^E>4i_(tm@-Ox%3ne`)2XC0aWQkx)n zn7QYmb9Sp^COC87qY+^1>dXjG+9UX<(<*Z>66?yuP}&pghU$LJsw-sfU!%SEsQn(2 zxp%j#*b|C*Oi{?(^DGp5*;VWh#lB9ZHxm^z_r83D^)~1WBWwU`a+LO(d^m81I+ei; zN6g%Z0%D`u>^yTHTs+nYhK14|)&yXUb1GvPmXNuRGf<5&Q0WW$M23UX9?o>&Om!+# z7>oHM{V%~*uY{j@<@AJ1p) zDqe)*d8R02?&qOsmU{il>Wb1{U9Uj-5>pm4_e%z8jK!k#<0>OSX^-Fz2yQu*8&2gq z;}A3VTjI2W%>4%T>{BNip1EHyp7kzcMQM+RLtBRu8`!g;E`dx0D8BU zxnt{!aOr1sP=7Uge56RhU*;RZ4ijhoF$k`(;6r=1ax}X^CQtC2MF=vnF zW2>$~A6Ihlm~xk!H8x6njU5M&`Yt7wfr#09eaQC^&a=l_0eKk^N_#->0;sV|X~=+t zJiW1jr=gKYyYSY8;h?mK(*iinT}lGO5%Tor2Al*7oR$m+r9GUFf%73_5%cs9jnev1 z`Gjesw5Oc}?a!FDn4y1WrTsb6MrlvG9khKer45r8a&sRh!6SGMdft3e(8fTbXEE*V z0(=R8OqY`GQaUgOAuG@1hip0s#ABv|fk{s>vsmMxwAVQQ09zNA(#fUdFg7tO?_xme z#BpEeT>^G=PnW&%Y;ydFEkO=9M7sL7crhTpb1MrNgqUN02Wc^1 zSYQRSgu$Q;ALe_&taK|Y7>tl#uQaf%FtTXN@oI*GGJKScKw0lr)-eQOeM}c+__~Lnd(f@yXVOAG zeGrq|DV9&~H&EzV$YDF;ryzd9tsHYJzc76vmp;J{%VSU%kBwgpJbEsDnl%c_@Ehen z;JWBm&byVfj7!X;FB)*pbJVj&FnyR@Vq_@8C%XZ%>u%*5!xD1n>jtW8Mi%X$y~$8e zhL7?9DEHjT9fl(0&-V-{cPvmIG8B~Iqm+oj8Os8t&m_V+4Ld%u0by0?d z@{c0z{Tu#9{JzBgM*QX2c;&@dlYIHb*!&)6P4ZD_LN_Ra+O$xGI23yt`Zx_ znW=#TIwB>WoFqo~y^=v7n*Z^A(K%Tbzv48w902g2-5_47y0H z4iiIZPpmGg8^x+CWYJM*?<*!*bUnL@ZYVmLqL4{DEfizyD#k&veykG9M8#~nJ|AJR z27O_Kd0CUAwAbYC0H;x`63=kNyt)w}&a2JN|I#GBc&v9B7D{_qEr8WLR!Lx3LWbSk zK$T#i(leTt3oKJ!Cajfzo!x6IVj}15_$sjEZo7Ri~ zr9FanAn-8)G3WLbPtcwbptMJj34-)kr2~TyvhQ?Ej=!msBmYa24hAYc2k&SXqYE%P z#VR?mil31Pd3Yy&K<9u!JeK?hCVkZYoi!0kdri~>Y~5m&uVa<2j7`kNyBUza=D1xA zaKb>!V~i;6G4=yvpI9ZI0SZ}p9|K>$fl6<({tO4DJ)B{{84{}uVmLx(KE!}C$O30L z!$D~eXAE#gF%}^^A7xP1$MaabiW8wYo+%0$`gkasrCyU*T~XSr>r^ODVaj5bKE)u7 zu~?LTOk)Hn?Gele!Q5D7cC0d!afq4vTya`KzCIg!ZmJUv|4WmZ#j`G8tSIfVt^n(@ zSY-(V6*Ko`p~+#v62o`_^kpq`$JSNAuu%R{tY!6)xo-+&?&Ur4N;!}6j7Lx2#fP+) z!{gw42oGt0277vjKBPTgdr~>Jt_mJKi$!S-)fXHPJY_D28 zPz?rz(jL$o0E+Y|wHT22(Duk6pjyQPMKK_h_JEuKs>f)A2e;QV0O+fZiz%bDryL9A z7^W;dygf!#=Fjtfiz%bDr~EdQy&lEG#DxdAdm$cpfV&5uzg3TukO#QO+XZL>fOkAf zBL*Nm#QmKhfJPPoP3;1-06=q(g4+!xJljHgRd|ql^B{l(3jo|r$X*wG1b|jdU3i## zD<}rdO}z6zW}T1Ho^leDKl3P`GI8O7?w@%A4|M-j#NZEf|J<&8JIMPyN^2%BJk;HX zg<+n$FwBr8Tt1#57qqs(XdfoVp1_jT85m!Alq`lJE?HlJW0A^nPx~jZd!!%>dzPwu z?rMAPk|sDRmTU7hwyrL$b5MrWIUMV2V0C3o!jjb$4Y6E36mM()FVFiU*REnuDCT*T z?o3o%vhtw1nk`w~4FsTBtu+C*u3oGOP}*yP0RZafQTi|-amnfjhy`rP>Qg+>Kn8@; z9?%E?4f7~N7?8MR4GRJqQasQ|287Zc&^Q2%VKl;$HO2s-FInT6GD>^Olc7A3DGN*1 zL{XW~T2q)ZN_)yPp*-EAOl9K2k~JOTfhB7yKCe}elaM8AmR*1a0GQ`d<}d(Z$(k1g zFvkL5pnxm|!&04QMU!je@0#h|%~cmDUR^HJLC{Pj>? z=TX)$abd|?$Cs=%A_ku#H`tZm4*9JfWfPMZmaMH<7}l!`17ET>Szzq=;}}cT-?DZG zmaGfFIOkDLGYoObItPxeDhFS(PGipwbx-h;wM(0?v2|T!orCg^c8-X36zZA~TTr~=QLZylaml&?)k3ypT{jSbrci4FY+bim6QH!$1djmpz@yw_ zK;n}101%tll69|mASq7&%@?ITpeN$umB-_h61cOan%;^_*5h$SKqc^5>?5Ito@78M z?EyUnpi+!RSh7kP0Q4p6X{L0=W#Dyj6 zIfw_Atn&DLNIgzMmaG@-0uTVa6sJ^T0K$^>QV>8T3joN)SM0 z3xH~N0crrCI#U;xtm;q<8uz^O71sGE?REYeP>zgKYB6zP$%>2%{FYTq#NbO-lwEl@ z%`Gp1s@SM9IAPSRa3Zpe+F%QPVMKAe>yvF zN9{jQyU5gpOZOKo)GpakyAHK$amp1YC| zUb4RffD>v{575pI3?K!!ibuN7kWhw?6yc3m9`h=aSI;tp%k__WLy08p5r>1m(m(Fi zlOB}eqm%|pNw4xGLlG|3mo%U}X@T+-LqQonN?D+kVI1OR`Z5MtVVIO->L|lkuL$)D zOkKQ0U!i#Q=b1Xn@YM;_U-BxI7=Unj{v~gI-bHoNOiRGRbKTf zRTzbEX}+2_umrpcb@7;~V&Kt7=cnv6@lEMLcfQ=6mKG=K>M z=S{|kGJL+jfzRz#oD5F5B=0t`ISoX5Q^hhAl;NYi4HU0e@h}wOa=h1o;;}%9XDBGc zM|l@0jTwh^D3Wum5&*Nc=`P^aoWJ;_fN6svO1CQ%kLi-&-ppyL>WG3DmdGD z6(55XFTJ+|l9139_zdF%z-QGIPu;q{U`Qy#L8_)@*k1#wt5@m5ki-*0U4itw+DiO{ zP#5gErS1tnA#_K}IlewYpsb9wxn+n{0?SJmUQaE3cj0Yg@F*W5izwMBm5kv`2s+#1HxtuM0!s z{xx8Kgqs|)GC9Sij{_LbYtfzp?U1q^j-ysS7rD>5Xi0zO2)v%eGaz%-=jk{cXRJK0 zbI+^ho|mmW?{UxD=AJjLJRQzJuRXLfd4iinIK__TP5BH=^wuuzl=#Cc@*@Hjk3yR} z93`#XpXUk{oQ84n7pG|}mbD62nFk~0o-Y|SDp>`q!GpbK9;~XBXB790H217!<>`W_ z-k9~QOy1(bV?s>$vDSc_c&tpCag%q8>9xjA9CRJKum`#YdbFX|qYbS>f5bz7pt`4b zOwPiCgZOw*k6DMKMTj>aP93;+`w)|+frB@Tn`9chGu_IoGxy3d!)g|Y-j&&DQ%QIH zp!dhuA#oD|_Pw}Co|VY}F5MTv!c@}R%4Y=k85%l<)JNPn9D}VqCvwkm=AL7$JZEsv zspg(jtUTv&&)HTci@C`{E0a|)(OY|k>7aa1tN1c2_f1@3y>VQuGq2Gat6+P0u$|_f z+l?Aqt%4om!48-QE41=F!9994#+Es3H$;#v|H@Q_z zuiY@6N}6judfh5?ge$N@Ib0@FiF(XB9FIc0`H@+XdzW{Ki&slHYRC7>+@zAru=>1U z<@E~pqGnhh2clPJcA8Wz{Gj(ojgYvX1ni@@Nu-sDn@dLnSeQ!cTKRanPkmR&dRjuu zN@A@%n{dy@=AI3$JX>wo{umz;H#uNGjhjrdGMUSz zX8~B4N@iI3Ea5)ixlN~%1y-J`x#voA&lOglo4DtCbI)~Fo;$ebRx6Wz++??v$zho2 zt$omKHkGv22Ht)v_tRYAgmGLPGq2GvR>3auU>D6j&l@$)S_QkwgIzZdcFoH3A@{sz z?s><`Ga@F?n2s3nK;lF9&oFT~o^m)Ge+n_-$J*1}q?DCOMQ&0)#=6(a#h6VcZL}VJ z)+#jRpvA#pPU_A%VVX=UQ&()9r>OeL{aKJRj$MzJANNqemY?mBrB8l+{9;P(h(+lYp2JW4azL7;vKBq|IQUU8OKGAd5!#5 z!SZ;pZswj}8#TIG1?$g)^)U~YZ{<0hdk!)89AxD=7M^-zjpmL8h! zGajkEu)8OAYsdYIaMc^{1&@^09?vKaoZZO}m{j4>Wsj5+WHC&O{j!x`4es}v=$EVc zRkiYq;(n24ezmOpT->jomC0M&B*w}l9wvH&cs){PPIgdz_36kH;`wc$otkpbcg#H- zS$VePp3TiY6RbQx<`rrcV#2%ca~}LNG-n!~!;Bt|z^Q2JaC~az)Sf%};FOu1mKHRo z=4t)c+RC>JXZk91G%nISvqDGX(m)gDa@npS(U%8IdhzIa;^tfPMC{zzY=lc z9L_nP=6Do=6GlIEUIT6vb^o@J~|p64bNtW0E>=&k*d*DUG3 zs8zg@mHX>lp_@@xW6 zy)heGnKb9Yn}wM0W33f8X<=pZIXC&Nm|pwTYnJq1)_U|~tI%KY(Ct+B(DMiCG3#*n zLcIBK&gI@+;VoqMziXadydg>dE$r5g`(AL>8!yi*E*N(LCIfi%zFuLWd8EbeZRIzD z`wbQSu4#UQt^6i%zp-Y1qpkd=a=*z|CbPK7bSsmEFwq-ip4W6?n-k*cc$PKga_+gr z+;fqY=Nj(0%G|TS%5wv+(7F&4-hJD7@GWRgabeqJ<@6(W+5@MMg)IU#b~tvL`<9kU zYQI!SQmL%+E+OS0BtEF>E9_d4dlJR5``Iby4Gs$c+pDZNH$x8A)Sx+{SZR8xeMIMk| z2;5g5C=ZcG$fM-(@+5hhJWE~%nU(Sei0p>U0r|LmMZOK0`*Kf+45UNoXgY~brc>xt zI*ZPs^XNjz|40wepXecagr20Q=oxyBKA-!hLz0$4dl^{@^<`uQwguR(#CDZNvx=++ z(;95oV!IC8AFy4I?FNl>1K9-L&Dd_ib}P2qu-%UB4s3T~y9?XhWDMDZPkYG{vJZAY zVoxFV?8lx1*mDqje!`wZ*mD?re#V|7;Q9r6NAb-ud~+P%oWOS{@$D&mcN*XQ8&+pv zbrx3VV09i=7hrV}R=>jPKd`z4tIM#u0;{XAx(2J?V09fJF^# z!s;FwOzy+-0W2TF@)0a^<(s6Ne2a9KZ<8MK9g-*CCEv*RNKg4b`sxA6mmiYe@*~nm z&PBgm+(#Y>k5TX#E%%ql z$OGiD@E8Y=@$i@ckBRV@1dqw^m;#S);V~5+)8H{39y8?mWG1|3!D}|W=D=$%yyn4c zzC3~~kVle*@+k71Jen+$$B@N{v;>isBGNKMT8>C75UBu>R?0KwRd|0dZy>7?aSbA_ zMZ|T8_yZ!YN5l>C0(qmnP~IeeCvTP)$y?;b@>WFLhKSn{aR(yqM8sW)xEm4oAmUy` z+$Z-SKjK{|ua@^C@&QCXi1$y3ehASIBl^#Xegx5fLG+`Dehkr%Bl-zMKZ)q45dAcw z{~OWIAo^KEKZoe&5&eSvqkK^=lz&C^{~-D$M8AyaR}lRwqF+Pw-w^#eqW_NQHxT_M zqTfRF+lYP#(eEPqJw(5c=nv$cBr4ed{Q()I3M zbb~veZglsi$4MW$$=#Q3cK4%O-2LfVI)H9<52V}NgXr)YgYh0hf0BpN0c02*NQTov zWCR^dM$#c<6dg)N(@SIw9Y)5|;ba^gLB`XOWC9&UCeqPl65S(DhV2x(nS4v{VPd&2 zPs4jU9ZP1=abzYPPiE1zWH!E=Lm$X<@t#M|koj~XS%7^D=|lNDycf~QWHH_0UP5=e zm(pGCWprlM<#bln6?Ash0@~lXk`8dLq63}Z)7|dXbdP%t-RoXU7gb$H_ql(dH>20n zThSZn?dXm4NB1UL=-y2CySLB-?ydBodm9~DV>{kE=oGS(eoJ=Isbn{uM)uI@WG|gT z_R&3T)=lPNELGXRgk1->Z=J(&D50TUq(0{ zJ(8pnQvJ5R&YI2Rn$1U_Yd-{Sv^f4Q z+8+E71>)ST9Q3vJQL{;Dt$lt%v#G3_3NMwRWUV@H)~ORo_$%^Fr?XzYs5hhQ@m<=7 z$lA5*)~!oORGl}S(b}HROG?tCM-C~a=RYQXk`(=Lap`G?=QN!=_TV!5YK!&p(i&8(Hnv_x@xC3`Row8`cj$t!40q4sTaFys67z$ z;&!a@)vw;eyMMVLBYfm`tOL|uUKsa9($Xlw;UX#7T{`+wQqv@*?SG#;W$H;%VwSK+Bq_+BvO40Mgm!r2%Y@c-B<1Z!_|&w4q%`azDe3=`roKiuWmFd_+CnCa=WHE*%)56 zgI|&ORrJ~T7w?sia-=mtPt?KqE%(>lH z`o1T%eP!oG|JSt$bX#gho3xx1L!eBugE%)+IGLzhpUS$3)Y=)SBhE%sZ)ce86^ zyVpy6)vnY(FZc?}djEK%v!gN4yQvxYH76rEO+QN0Qd?_6lUr?$c&g{U`ETS?yfNwu5Rf5+4CT~B<2`tgmMy#3aj9W%8U^`-8Ak|G>WkyoVLXVu@% z${u;{4>zm%R8hu}y!go9c28Y4=`YQW=C+rX{^RL-4J36QN$Ql9n(dQ%I!Z)HM9M7( z-PsfixVkXrsw>|U^~;oyo_>p2XZe!(U#GA5Ci5aXl7cn^#GGBxg%pNrSPl(`O!mlES{ zJ#nc0lps`!trj6veT^Dt2l_MHy0BeFY)=r|0kEwQTg@R<^;28&e-51Sa$@{SFC0E% z#u2TBxb}&DZ6U_{i4`hgSt*P}=oQ5JAhF&E>j->e#E}~BsQNd}0U+wy&0M13vWmDo zpN7M3xIEAUZ4%KvT1f2Nrc+W<2Y+5)e_nvRX^HfHPGQ13#68 zzFu_-`SbGqy0b4S`Nj5~+QMob{8X#2;}EgUD}JB1Lx(u8?*%`5Z(AsArG<((6U*c~ zwDW5h4hC0@AOQ*&AkbO>M2zGZduL>)`LXg2b>OW?m^Fl12{F6J#lq^BpXbLiBIxmE zz;GQg?8(I=O_g0h-le1!e*$*viQNt^Am(*WE>oQhqtA)a0xnoyPHsLE6k)RgHkE}s z9yA5%$eI5#`OCj5I&{9~q&r37*DJ#3x)Bbfmvm zRzE-ew+pRD+rxA-VP4GHX5{$^c7V(_tw|$b_ysYX%o*mTXY?)|AB|wNMdjKQtB(To zVLWbZ+rgjE6&FrR;jVKniTQ`F?w{??%pp^}oF+OA@wTe*zAqhKZC-rQuZ=8!yf@j4 zko#eVpUT1`F0_U&j9ZgnfEk;mvQVism~PC5>PRhC#K&AU|Aos;Tpw;zsZ!m(7rS*% zPV~R{G7&?%u43#kj`FO2YO`aV(kION;1=>FcI-^sCxID62UUhvIB2Z2)$Q_pnd$zH zZ94kX3bL~B%Av5m_Dn>7t_m61xL}sg`m+`4xtsLoZLS~4ASvw!eVWXH@g8EF#D&Z* z$YSxx`1o3FlrGVFqk=yOxRVb2E*rCE&z?Z%_(S@bRjsogqgLtcVNLrYt@l2zM(UcX zSLA(A9#kp+Mr3qQ+PZoJcBO&J;ZA&XA;c)o&PfYkc{5u=zEwjW_l97jFAhUc9TOEi zWUhB?liV&b9_JfSi8QW3Iaab%9907^Wi85vDfz!YHSV^cVdPC}htT~s$%v_3=zcl< z*z!T9=`l5OF2)WLAF^s=1i|?a>O6*bF33w~JxvzZ@8BJAl56MOKz?pU0I#<7HFF~D zjuX3=xL9wdW)_qh;nkqJt1NsG7qq9K7N@jYR2CvUSnd57YBtbzB;*iz5dM?zS^3byc$lVC|HqBRsB8 z#UP~sReGIk9gIPBJ!UIuGfevRwrANDghoipDjqATPC#)yj62RO%|< zUIkfxB<)#9u7kGeYihMtnLv;$A9V9$up5F_Eq^<#TXgfw)oZhi&6v_GlKg|By5=Ra zC((#Ob)tLt}0cJCa2 zub!B|`LsO`acx64S$#N-gZmBDJA|4{56v2gbyJOX{n4)NJ0-V_(gr53 z)ZxllJl;)J9=As8H~9L(zyYSKRd5R)a&&!3aZuXB*$tep zC<}j|$FHJ`i>8n-3L2|^Yrt6bTLY%5U)PAEYY!zrX^&ukwAH;HOT`XQF_iYi4x_pU zX?3~#Jsw1RPbK{xa=*tTb``&a;!&!|-ShFNh2n9$ia$W{RJ3w}it_h;JjF)X34=a2 z!hWPpj?!L}{{)=#(aKqh!{7VyJRq)CfiS!GbL%_ON~h*41d`GR5NV|9I6v zb=g3rEeqEv4oZ7CzXRuXv~rW;aQA?`ZNRx{fpeGQptOf0I1`jVDGPre$UhCz+^}&t zwRIAuJ%R^75aHBTX#QT15zf%5$`Mqg1SsthR0Tm5r}7|$;O+-m#aUdmk}Qtwevl6u zsI+_PJ!}`_F<{hkDt~t>)hP*gPsmzMearYe2>7{F-N2-c+Q(@Vp|saTGT20?QrD@} zp=|tpAw>gHU4~o70LOJ>J<5pE9^-z(BAQeMtPizpX`wp!xm$|=# z_TESOJtT7GIF;iRhs)eg7;uhT;GCv7DDB~#1t|Y5l=kX+1?3qiIB|wF{+Hxo^o9%*KsMe zsW_jx*Kz3=P-+`FiiZrr)%GVT2ugb(^#LMN3O;9-(JjZwXbH~Qzf*H|99>UQ0+jX$ zo^e^_?4@Fjs2ECnVogxp#**QiY2`a zBw7}eZWrJU0OYuoESJ)kGH_XW4x6%BAmHarUjvhtV&>AuL20jX{tdPPE~URqDWGh8 zRzARh)SuxN7~!;G^ERbJX^*Z5bc0<=Aw}cz@xcbNLL-klq2HxADDC0A2b>WurI_My z`S=I}PO$~fD2jv99?m%6jG-)CK0d~vtc~RHb`>Wi>h(C_ACpvId;?*L2ZFsnMVcrJbM8fNAnEYG|yg48yIEy4g47(K6NY0C+mAG#K4hTKvXEnT#D9eNX}5CHt$a`Qxm@}*o0cb`&d-hS4Ln*deTFs) z%J3WI7jRv4D;M0#Im*T7(H9Lk7Z~a}BbYW!E>SX+;gj6}*>$&ajbd>*^mPN(H6x2U zX>U>#l;NY?1Ik^ua)+XD`SV=^${h=oKPd{z@KMUg;EH98mYQ(6vm?fQVzfjEW%zY`2&$E-DxWh~Hpn7pE=>)pQgxK!t3L|$nlVa^808Vl zz~{>~W9U+We7Oc5pP~8kBW1HaM%hq?&nAKG$r$Ac3dZNkPXdNZ&`O>#j0xn*r`22; zN0&^IQ2te<{r|*g#QzZJXT+cMBq&dKO!DO?JjFxKndHl&M;j(6?I}ME<@z2)rs90g zT;HST%(8(4Yx|Ll;Hx!*zk;|l=7K$-;72}{7>rp&Zl+UJP z*$DF(^tln{qfL&|UXwo$oOT{1f#UFabvr;@AkEG`X_8Pj)(aF1r9G@9V0G~*i4=>= zu)7$j5)D*ZMw3i&P};+J4LIFA%F7go%d)!}a9*~+Nuf9>?ct;X$4^=KOxtge=7vpA zN`TTHK_3tVC;^{y2g)W$rvxbN5#)d%%cJzA5M1`1g~jn#vN*C&n)EeLX*qa5yBGt2 z(chyKc$7R!!sX%p*@P|t0Y8`W3{2Xn{TFQ_l=hlv2-pUBly^MJK+4AF;)4uG?=akf z1~_gY6;Vc%_88v-;|PyZOaZy9e1w6o*g&N<*(i#G(jLwSz!~RJ#!wtCGaqNb8DoJn zf#RUFhcg8@lPL?AoliC>YvXyUUB&58oJJM741F3D%~G!!w5}-a)pa(MXHjK7OP^(s z##k&(Kju&Zl=cXgf?%;nS?E#bQw}~;U(7En$k!L*%uTY;uuq!IFPn84WkqR^buCy| zdz6(Fl+WB(hbD(5D-GiX(3jQB9Y6`Cm&MUA4Sg7K_pz zRvlo~rcC={Hw>;=UML(xkZP++7*2rfN{$`0dGv%`#d=VbyvmbQ^blzXeCVKXJW-XP z`hf(!AyrDAG!TI11GNcobk(O#fYM$QJPV*_yh;NKbW8`DM1Yle_ zLTL}E1%M*GN>d7Sk^_ni0%}?|P!t71X%EN=pjMP-N9+c2xu@_$(mJgS0NSqOqRJ@k zDSMzCLzS;WIZhS|KPJjCyfXV5`qoq#r9I^~Q1*EhFBLE6)#k=bBJP9u1ze24p~Q>F zpJ1X6nJSTa0uXJUB-jP$0D$McN;?WrF&N1lzH9wx>< zeam_a7;k!&T#CVOS#N@41>s;@RxZx0B4>iPtTpO-jiYM-?HrV0bq>RN2Ur6s6Srjz zL_@489Tu!V3hgQmg<_Fc8B9g_EvpEs8|aob*g$|mxv(` zf%q-!JwPm@Th@rOf!?P;DD44F1keXwWgG?Kx2z9>fX0;#G>HPCv{8Do=%myEo(Zj%vP;gR2ii`<@r#a>s4k`ac;|+3vqqRnvKVs$UF(z zvKH6{SO$P4US$yl;I^zKK>&*^0G8VYSPg)cUS$OZ;I^!lK>#Z(0M^(ASPy^_s?Kd$ zB~T1nn^@<6PCFl^z0ThP<;`AYBNgYitj%o8+Q?(DC334>`CX9T=~cEmZDhF7^xMfol322>ByE$h0005k{H zCcx2kn>GPTdrfd3K=-`LT?)i+S@!_3oo-oo%LWqSv{$|;?EzJcOHeArDdlmKO_JX7 zTULd*QlRp9%=Z!3LX{{GN_#*L0jM&i;kK;G1^{i#s!Ekn+EcC$ZCNcXFk=2Xh7TWqt*3tcbw3dH zQhn~m5qqI_l8pC|e?L1w+aBd#ZTnKyZ=rfPPB}=0`M2^9$LVk7A2cw4=d`*r;OII^ zQBa1DasnvFDF^>H{&DocIno1T)eE57t=`V7>NvViQgxK!tN$2h^%j1q&>1R(GJK)) zsODK(P44acvuNYFk0XwO^oik*aZT-Cwj&yJSc0I@GSkDOac<|F-=#Hkz&& zw7Jpr8*OHk;WzVLpxlX5Zc!BeE&DqFI8B;*w0c1s*K==`jr0daLK!|%gfBrU=Tiiq zmSu2n*O&8!5(zlN4+m|hui(>?9+csuQ~}C^KBW>x;oho$(123O0_7o!f--!R>OiSR zIrz8fs~KduVN!#tqYPjDF{sy~>ik>uwaQk1oT{S?UtNTHU7u2i0&s87*Yy<_T_lSh zdwaf)fk?Z&EZIS51cZh@m!fcQ$NLN@UJH~2ih?qHlox=~o^o(+#kV)8YGb#99ktF->qOPKx8XZM%`9c= zLhFb!{5p1pY7$lD--1sv$YR`;rVlSsb(G<&`=Q?5r@ZDX~ zcYrj|rwpJ-`~{(bK>Cfe61yNY0B3HIGr<>x?x3O2S?InQ0K$ zc9Gds6=nFU^PxJIs&W^8=JKlSwf_RDiZXoFWl&w>Qx;KS?xN2U2w47=Tr7jY3>5g zJ}mS_7+a+mc=lKzeDl{4jz5a`B=Q`BfFc(~5_v%W#&zaa@d?Uv@k)z$B{E)pO^B!R z@l*@s-1oJq9UV{X3ve>IT(aXC@@Mt7$wD%|S@Hh;|LKbbRDk{nfH-fex_ChT20&{7 z{4-v0$16?-@D`p50*F-s2H>O$K>iE|;NJ)U-G8aNctHLJKpOz~;uSAbe;en6)Du+o zfjFtElRv{ze+K~|`X5yk56It8?+Eo5;+6LCN?Qg{h^GjEptXM|6<`ofssQBAZ~%rN z0CWedx_ChT2EfYz=o+si#VcLnl|;r+glBbz>bN(p%J42ustn}Ma2SRm0HlYi(s)4r z2E%J$=*FaraZ;DY-EC4->ESr3N|QgsksgTvP#mEu;sN;^(tb#HXVUNCWRP?ZReBUo zs?y}oaHOXp02Dt`74d-l4e5y1+T}i+`50%OPL0P~O~Yit6;NfT{tQQU76Ksl zOjQjJ$ls9tTWj1MI9}<^D*Xx0w@^Ry2z~NjQLn4|vvFG0Cx4demv?N6eiGk}@{q&f z_&i$3>x-}K5y+SN;cHbZ;S)g*m3yGP<4b0;HCo6>Bi|zkn+VwCI~-qFdF^3dUquV# zOKwtg@hwUbdi2_Q^aIpRl{$hy1eNAsNZfzu_Q#pYQ7e-lne-_DbGRq0d@eGd^U;F# zrAay}`7$ww?~1-1D-P=UwJ`+uZY}m8Zk0_u8LUCKZ`Ugp==B)|3y!L~HFT zPJw;fPH7)Sq0JqR2d&&6X9~5PhH>$Cr)euzw+dE|1ryCZ>l!ucSOsg$f<0p%tbvth z6!VNU_iSqA>4K-$n60c#TC?CWAtr3D#WNGHl}RUN@_A-E7V}97!SGY&i90-svGG9rekZ%S>{N-I-d@(B<(|tF za*X35%e+Q?t%AMHf(~GX4unP7r3pUt1SfQ2YDCRlB+_Tuqb38n?#vEg1GMNRR z5MsjS+B9Y|#mZzJGnrjRugxNp&XAR)s69HvD)gr;^ir!i>u@X%@n$n~xLaR{hPwHs z#IH}@G0bF?+pv_3wDOwByvDmtR=6H|^r_TNT}o!)53N6@g~UzO?dLF)Sym>Cne+kx zb4$rQE1#9j=To=oQnJj-a|82SXYRSy%5yvO++yyz*~)V_^W14=a)6oawK6#d6Row6 zxXqT5p6b9mWaWN_DV#Qri<9Ox`razoB^Kyx(uGpX+}EG4p)m%_Xnc}%df_2|v1ow}5? z!XMh;jtYsJqua+Y6Q`Alk4eV@m|IFbRz5EJm>Ho`nuv6bfp<~h#XbBvYeRCsEQIoZl&1`9qd#DvYYIm~31mB}(@vbc<1 zTSz9IAuD-P?a}#Gp-Wik)mC%X;aC~s&1PmTufCMj@Cv=n|v(?fAu zo%c_`RcpN3ULi9*=!$KzZc?8`m%Kt+ki`dT>?f`K8Z*CVc)vo`uYr|c6!VKT^J{A5 z=VE@XtV~)nlNc+L1ejhK#DsO< zRu+6Snv)-m8?BsnGpC(!3K@-C)c)IU<$IAaoev$2J5|p!p`&rP-h|hf?B$T?U+X5f zS@awH=s2jxzHa3w#OW*cJ>GA->UY=5uM+dC5XY^>nqT=iehp`wRheI9E0Y?`q?(mU zZJ21I@zFTbwXtT1=TW_#B<5My+_R3AXG7-sl(}a;D^G=0s8NUsYnCV$JQB^xkH)4} zPBF~M38#?JcwFtjmR7z87}MT3KIuQHH`P&QayZVA^dGeHI?23_$C)Jk=k(}jsGYj` zU%($)f1VAAdtSG{#7r()nf%72uK}1#`mb2|{K0(g#DygNr_~m`W#w7Hr_Y>nK2uM@ z$2Tmi%0tZaL37VaR-QGOXEiI6$C*hjD-#JOT5H$!nI-)f)r!}#a(|X7H1rw9#na|B zs&5tSITozBxo0z@MiZ-G9u~}P9?WUwnZP`K=AK?F&kpd^8neBXNf#EpQ-}$hYcDaA zBrB61%%po6z4n^VEa|_j_GmY&(66)5eTaML^#d|z9gaYVHyh4{%zGfbx$OQo)pLL^ zB7zzF|)L;1sg4MWDtG#~v%+=y-iuelA|f$cCc!u^xeZtfvJz zrN598ghK6&>&SSaXV6LV>Pj7*u`JX-<4I@mvE1spAV2K`HBO6Q2`rc|UdYSO4RX{d zym0Inbe3UsVxBL+Gvi+Yu1f9UR?s`hPs3~? z(lsxTo0sxdAUEf&l=whi-~60@DKBN@6{Kc%4fM`XvQqQ%1Gy<};$KkOw@-PiWmL+G zfy_W^ULYl>=j$nn{Q}u}d6^wDdImjg(l4#2@awh5go-t*oEJyS!=#bYaOtqTT3RQq zl`hCzrNh!5X}`2r+ArUh{*Zo`zLMXS=gIHMr{v`F)$8RCsdBYSp;#o25XXzt#2Mlz z;#_gQxKLawE*IB`>%`B+E#fxuEAhN|LA)j26Ne%ENa=lPoHS9IEKQSUNOPnG(rSpU zleR(%LXbQqU6F1>><{T(c^Je-%VXv7@&{0hfiIPS)A4~}2sxL2Ga?!%+~;!5!V?7qR7 zgE(^tXAa}c5uEuJXO7~`F`W4hXO4sGd+43OGbi!PDLiu;&;5XBf5dZV@Z5i4brx3V zV09i=7hv@htS-XpXIT9Lt4pxD467@!x(cgnu=*8N*J1S=tZu;SCaiA3>Nc$I!0LBc z-4(}*f57q{EdPY%eOMMsH^o8HEpf1PTO12EPZT4bmY*K8(mm@cS*IA4T+Ii2fa-A4l}>5&Z6;+V-{|4 z50$sNhsoRA#qud}xV+sxLjKY{Qr_WyPu?Vtl6SgC%U`+QmnSqHgWs|8=BLNWyWQjE zJ?;m`3)w@3mQz47dDtIk8*w}k9JOx-*--x_qsol_qnIZ``sVQD;i9f54dN@ zH=}3Dx1wjsx1&Fizj4o&54z{bhum}J!|r+V5%+v~QsV{qT__hSi{wGdVtKH#L>{6n zm5Y>R^1I4%d8qQKyfkKoJWTmazSVH0yg6o-T&%2?M~Q3XZ>6;|{y|)RUtA}T5!cIO z#n0t&;s$xVxKX|&ZjwI`H_H>mFXV~h7I~7mRh}$vlRp%<%lo7+VY@@d{Fm=y5&T2i zh2P!sRB?~|k@&SdP24MQ68GV`{qjBO0Dixb&x!}->Ea=rJ1qYx9l`In@=WolJWD(# zef<%7~0dA|5x`LK9a{z*J1FA&co z)&=>#^b>wB%8SIG<;CJJ@)Gfqyi~j_PZ6)kE5)nwGVz+cT>MqOCSI3Uh`*sNZ^)mC zH}PC;p;qCDT7vL!EJ>f6WTdTmBf@e2z95trVtWTt^P4nlHU|5ZcBV;MZlG8Gn*r=S z__Q%>9RDE?xt}JzGBWG;?xUV7hhuriU}DPss5X5v)pO->Ebk!i>G40R4RRjxLpHne zj?U`i;Dc%tcuPH1LABYH7W_PUtlH!aP*39{I*3!{Y4wkwgKCr3Q$15rwaFo-+z(-B z+Wff|&730piG0rKY}G32x#(8xl=>jDS+kZcTZ&>-WV5K})H6LE6omWt9YWgBe@}na zAN}WNRpuO9)N%3DBdg`7leRoJLlA0IsVI==9+@r(dSe8)H-RCo-8i&0AFQU;k+!*N z2b+Z42agW=GqeJVin!R1Y%3LuNfH%a(d^BT0$fy(lIeGc7M7LB^r(VsQq-AExB4&%AKh>O5 zX`9!gd8?Mus9xu^jMP3I3-U3vng#zv;u^;z2~XUu8RfwLDG5SzjNKalC|vV~P#Yup zv6mjgI`vp1vRXY>SONbsf$~}P*jPJPNj+D6N%a3*3%$!SvU_C~q#`wH41QNuU;VNS$9o96Foo^+%A&y#kQ ztG@rAwkv?ar^dc?tkdyFqr?ug{;~Dn!h#L|slGbacI?db)Vy>xdefpG-<+1R)*G{Y z)xq&=X3np^%6{}fZmt@;wHUZLFs0A4<=^a6`R$(q2dn%3dZW{ssP}G0HeM}dr)Fw1 zG&7^8Dm3$@FC!irdUvV3@`&8<YXRQ;~CYTY}{pPiHK z?~SRS=|}72iX`wiD4kT1f2Nrc+W<2Y+5)e_nvR4UB(e zf{hDLuYgBo;jjy}#hI#zfuG7kU#~iL{CW9)-PxCv{9^k~ZDF-e+ZHPeU&kS0n^*ik zZ-)+XUf&CT_GtmsQ41AuCYH%}Xy?~1#SE@U8bv5vfIuq&5HXTt?46OF=EssV)PaAd zf>}eDts-XkxLBC>`FVcKA3={d1BR=KVNWg|>BZ~<^1d&v_!F>OL+o~N0rf7^R42n| zEiqca1d=NI#P=j z@iAA;f8jC>*N2-`s#Le{#crLG6a6o~OvI3)su(+rqdcph+U!E1SD!HJgIma#*s(Kh zpEza^9aI@w;h?eN)9vznnd$zHZ94kX3bL}0Ef==Yo{8wsRUsoA7o750f3`wBcaZ+P z&GiErB&GeJPm?(?-bsv;xRBa4yVCLTmD(s>qV+}ve-QBVI`F$}%$hxW0-fUz>0?&4 z4tk7QrL%`MZ6{jqeO!&m0AOABJ}RJ8Y11}cZUsnUfIqc|Ja0kOQ9 zEg=WhkjK3t*yxMH+Hk5YRPd0w-my(`J6y&T3ZJGDXZ30 zYukc`kvFLwLig7sBc^hp`{j@ez1pNF)AXQG}Nfz6@68y5uQn2Q+70g}yxtL!nA?|G(`l#HDV7=liC zRPA_NV9&_z<4?n8u3@si@8H&w2y9V7Prs&*O34{@AeDxEqK7=hXnMqYIE1wv6&)&>-~^ zBHlI;XMXkIcL9D86F94aY;BLzH$pP}e^SHuaRx2WdVPb27h9oI%?(+dUe~)}t;v!f z)FXXq8&))~O9gqUeXLfeUr42{^6gcS<RLb((1^KQ zr==B?u68kyyrS0ZVRa48$nKrv@6{6%xF2oLLtNX?jZ$C6#=-rX>YirSjX~&o_w?XU zf`?`e#QIf@b^Xzs6jM4@sE-?uYzgAdCn&$tvpa1EWB};Hq+`>s`~fx z;#3}_5ZsM)t2m2`R+7bWmAW`C6-yp8P-!W5B58RQ~Q%s#6l~X1cYU`j+u` z5b$%Ux`9a>wU5&#LTRswWUz@&rLI${L)rKn>WT)Wx(v6D0gmg&dXy2RJ;rCj_>5C& zKmoa%>ON!OYha+#nyfL!L1_=C1#lvrN>hr%-B>r$fYa0hCyL^rw1?vaPAkg7-CVbo zL0KEmF1v~zD8^7l?gqOtP&7-uTGP6sv{zRjl)Y4$zsauGAdRtDntsGn0+jX$I)dN@ zr_$c3w51&Ujdow)mlfP-w>{46APdcAb)nfTmb5LKwG(AUX^-_~uy%DSNfea7*=|>0 zamisxl3~06dW!lzw>Y|9p;#!x!Xod;s+s%iz)Gh~T;`q*fUijg7m~U6rOGJnDZc^b z9H){+#re!VhplT_1`aT7Q}bpVUAYtor9GVfz$u_CeCA$&&e==GOmODDPbI+7^%f;S zX^-G-r&Z=&DmIXcp|mG92-SUuR+r1%-$8rtBmEwdxevChI24LSRFTWvi!2m}*;O0` z#gR^BI2GkH_mOOb4L9g>BWyHna+LO(d;)OBJC(5%htJ%{17aI#c9yx1EgNeh#X@Nh z>tkSj`)1nWSs)~T$f5M1WI7K`J4vN*EL zeYJr~%XHS;#n=XnEly>#Q`tyKxXgVEo6wsyS?cvOtt(1< zb-e=ROH`T9+%FlVF&0bHkE@gbr9FZ>Ah_jJZa9_el!MRQZ}H0tGWQ!ebAT)~EOWnJ zHtX+{6{S7a@~#BM;Zp8XP(E{axI&V{lKY170_eSJ=8mH)!lhl&K^YbnK3l3~?vDbi zrpx4-drepIkV7Pu2+7qL++UG>OgT&+QUf# zP8XMwNO8D4y^8@S(E=x#;-IvL(+xN;Qx-l?f7vLl4V71^HcETierR{6+I)uI-AcO$ z)kbMgyAQMjE~OWh=W_D^7Qy3U*Ww~vPw!Hs*p$rz z0Y7K@8kn>cGnY0FN_&m-Z?Fw;Dg9ka0cGQ}@&N{<{tUOk2&WC3w<#S;dvryh8|+dF zDH@lL4>ph$8hO+S{Vv5pX%FW;;EZr7#T19j$43}&iY;(PQ5=-^aK-^=3}xZ+@i7Kv zZ6uGkt2haY6R0AWk57Q2Swc0L))l3_x_$)ZDO8!y$EO&ivCEgH7SkvJN_zxzK``5; z%yKC+CL|A| zk_z*=_b9iXdyh0SXsg#43V||whzWogPYL+Ed%U~2=yYh_{ezl!7_%lF!>QU!b@xMeFV*F9>b+LF2dFN}@O6(u_lR3LM5VcW`Un=cA89^)$UvcGA;;{9{|NEZ zZsnv~`JU=?x%6o^El)z7pBvvBc(h#l3~dyY;Wx@J;JWBmF1VF*l#9=!FB)(zFw}EK zFm0GzqGTw;C%XZ%>u%*5#o}`4>jtW8MizC_-lQlf!$-LXl)G-_4n^Ve=eq`!I~FK^ zQWTWoqm+-q70VbcHQ{n+M~wN#6%k`YtrFB8plV#+`~cL<5~07vXo(QY@ay;xR4Y?e zK4-3MkVVd1ni^E4>L|lke-!F9W0V>($|ID4&zEb)(4_+Tat%B_L-XZF%4U0vvY`y0 zO#<7KG0GDZjL(&y1Pqs;l{{e>6UdcMtGP0cE}0^s{HsX&|B26t{~^%p)lYg7lqWnU z`SKH<;vwfu@@3JZ4HK01l%IxjeUBnjaXx3R@6mH+*}#EugYWyJ-}={p;-IvL(-=67 zC<~uGH}c?Xz(cd=D=GnwxEQH52ugbdkshlIx>T$=6+>xHtR<=&MXSqY(NSpcD<)ZV zE4zwrC_1Skmq|M<6l3fv#z8UGqj;z&pH0WI5#}-Ib0f@0n;fORCVw6{?L0~X#o_bn zc7V7*nw@>pB%y4q7bq4=dss=p>f%unDHfMucQH^U8mP34CYj=(w1@K=aJqSvmnjaH zWp^{+yljD!LUB;q!$}2>pR(|ow%;Jl4V#{n0Hr;GJ|GBC0zT&slueLM2~gT2$N@o? zN9ju;xa>O%i{r0kab%w~>1&|Ua`1k3F$Msmzeg$XD0!5G%ftJ#30(jJelF!1n6y#* zFWN*X?KRO5unqDk?|77fl#S2D2N{swVYmYgaNIyDqKqi*F}?@J5gw(O0&-dT2m@cS zfl6z#Q4|NIJ)94KGtQ%op*UP-KF)wM#sX&o#X)HgX9{p8Qx+~epKMUp#`9FWiqoMu zjVf{(`ZOq-rCu{=T~XSr>ue~`qRM=hKFc7Du~?dZ%%KD*?GY>m!D5fH(4)+!9DJs} zm|s?quP?-zn`EJ3pEQ|YHtRCViqanITClG6C@U!_pSiCNO%6*|8paEtFRPh5j;<1l zh4Qart&T;;iQP~<@XR zhjC^oIrF=E=6A6JdbU_1c{Gl$T3#)SMQIPK4zOxdrhTy+23IUE6pkTCwN)jE0!|W5>>w* z-1#p-v6!^Ewl=ZO??yWxr9EXol)HPC*QoeyTJ^c4^ShIQ))l`cukjdciR@ulz7OOB zUZp3MKSSjg68Qi&h9zWUm`BDNjwL-UFw(=s*r#t?uaZkK_$}*AaI7F4Y|F~U znN{RW@RqekU9WL;4WONaGOW&FSnmL9AZ6mVtbu5VHKoIX^+%yy#i39v@+yO=D8FSD zL3IP&vIZLnFi1D3O@O0o7;OTS_L^WcfZp>eBPbBRWxWT8Wpv9LQ8v)~6bPj~poswb zz^ja-K>U{VK@iZmvVkU1Ae8oiJ_67bO2chgQw#vwmNktkqqL_y6Ux)6GPh+-=at#2 zHH#{vw5L2D%5%NSY%0!eS#u$-Z&|bPcoUf?AzRi0y8z1ou*9n@q5#~MwIm2&kp;kV zy8x>Ju+ponpa9&KwK51`g$2MGy8!C}P(szYEvp2IL2DE1{Lg9UqqNugTcEtzt8Ap= z+?KVOZCM+647NmWwJX01@;klCb}G+pSv#>YY#|#1+p@M>VC??u7^}#utiAe{^%F48 zdzCX3gWs~wgJUP*U|ZH1oY_sz1aDbitLrt6u8XvDQ2y1<;jyj)>oR5Hwyeu&h_A_1 z40)Ax&934tDBkcY*QqGKW!-@4LAqsKHxPj4pxOjDx^B}ZKxwZD?gQwaSGh}p_$})m zAhy#j>u%XVLY(%>7o|O*ig5`_g*c@=?rcfYTYk%`5LXIR9*_Ax;##N@1wv^L=pg`A zrZn7^RoMWbZCO>RGD>^O)uCLCDsx*_HC~ymS~aLLN_)zWL;2A-r6v{UwyZ}Xu5Vd2 z@%Sj2Cm~x_ZMy&>0P4mmbtnM0Wz`J=sAB;j*#&3-fT!Y=dK7@$vYrY8sAmDt&@Mn@ z05qcN+?Le{ib3O^b-qG7AEmv{Zvo}VIHf5S=eDfKIQ>;tQyznDSy6W7-H><2DJ`iy zw`Dow@Tq^YF|aMGr3FUJU&rv_o~6~~-o8JJHa<`KIpm+tF4$4~ z1!@54&{8%@8_W=0u)Gv5WuojBzdMd9DF zzXO2Nq^U=%7qoFb_g2|Re^4Zp;Uh)(5|na2Meu1^2KRP-IbSG|fHVAX(02L?J}v1% z89quCpgibPDp3^ft@;NID3vTw9-=5H!$+wOlxmcNf1AFVL6#dPHK;nu@YNrKdM&EX zzeQiGZ1u;fI?C|XMX1;HDRn3S_x5~UUvbezvgon5=j#}Vw9Ctq9fU?eXy{X(_9^u# z1^3o`L!Z6{JPmbz&eS*XXe0Dl+B7J`Z<;7@HTNmad`c6_#lJ1z+1P3io!r&w%2!KuMq|D8om2 z0VwS$2lrNddxNSrc01Tn>kPF{RE>KZz7y2UQl>7njwr*gV^^pqQC0pe_#}fY#$9Rp z@Df!=8NRw7>fL?HYd)nLW#Hd_@6In9c>Db|oViRE6883cx3W2VP)?NLb7p|Ek536u zNdB$&K0x9Ux{`old;s_yN%6?h^*TjD84glIHN$=fNCSP!0E)z45E=-i-$*O53qk{M z<`y{3?Jqbz|5p1+{K@n261f{nN3wuhOasws&lC-cj0F)ugYHg zFQBR@!&hAf)g?Y<5f$bx`YeI4e$i(U9uJZ+3PUdXEVm=R8saN`$_gsZUGP~MB)-Bz ze2pFP4G>@NQ%a~fcd=)Eka&rO_(nV8TOhufDsvZlHbX6F-C>=*m3B7D@H_h}sP6D7 z+o>>jk!OcbzsR$lM_?CucG;0W0O@@`We=6+F7WKbLSKZjReFJEj|IXve;wiYqlu2c zCpu~*2`F)Gxpr)V(js1oj8|U-COT@iP(Sj73*Gq72p7KQJke1rxm>d28S=1t+hidb zU)gv6{{M6*f1>qxqT?~5^*FS?YmLw9=t8wykk9I93kJT|JkjwFRfaqaL#A$`;|U^D z7c$>M#-+R9Y`mD`{;bT4?qVklgLLQc? zly_{3*1tdg^JpQjFTRlkUmsox-`!bQ37?-(zmfb)X0kO}$Vek!b*6sBxPyGf{1;YU zdzjZ((E|AnkJMazNlb(uy|y0x0JT%4j^Gc$@sPveI2aQ5AG-Z_$hz4oV-NkwK7;p97( zHRZ!F(OSETQ(#{vQrbsRXmf|-K`ZyinL;h6VO;#(Y1)d_t%B8K!9;V2yx zV9%HbYhdLW#XKX;J)2s2y5OlbW-BX`)+~5ThzXl(@yx_)Wzvb6yii83wRd9D^&3FH za8I9gZPgxaYZdwx7P>2OH=DB#M^cD48%}+hcY26PM}6|IosTGmX+rc=DECqceJ5{PF{?PiPaY)=(b^9o05@}`PX426B=9ZF{Rz5!F z6YC1uPs`(57#$9em1hU$+1}i276`4il}l11__y zuBVRLO7Gnry#GLMbDwonaOFQxeX63nod9E|}Tx;dIoq29C_uOpdxtn?Jv@$us zO!iut9D|A0+DF`GOG!_4;2pAZKf@GG8^^^-^BR3`73>lVcG2APf>Gm~Rj`{Z*md(@ z*Q`AMWS)1;J?~g~M#Sii>4@Pc5*xaIgNZ|Z`TjtN37czGnMq|UlgF4z%^2%ms}WtDfl5tM`P5Z-L(WU#`JiEQPiFt0`) z6Rd1KdUI;0E+wt-hc>vQLgMD=_A$)FX=UPL(y;*MmJ*MZ&kM|_ohM`|NmpAi!OAn4 zd3G`POtkV$VV>R0Jzuu+?8!X+Rwn7pBw%II4<=e`XL-y9Wv*KBzE%EVRLN` zGnr*&vW%H5E~D2Ll1XRCO5Rj^biP&S5*B*3)tq%WR)%=9nOV!LFC{g+La*N0L03kH zsJah(g>>%pP@Goh{S$E28n3oj$V?BqVq2`6)MwEpuaFjG@qrrqNh`m`%ylCCR&5|yh2Vveo%e2<;WZ2`H9|69hv9z=AP}W zJd>Gc7jw@GgKm;dsr;DV;e5;FOb^nHe;umZ<&L z)5>=MV|p`mG_FuRb3;etD!mB{ne4!j=xcP7VJvzPKRPz3u?JiEz0dsK zCNaMc%>2e#`AuVfQ>;v8F_Y<5CJSJqjmEj=BV%@m=O(?KmNU;K=AMhJJl8PKmFAu+ ztUNzw6)FiaVcoZt1>cP3|F&ECUSv$?Lr3FI)$>f~Xxyzg z;WZ|EIVAemy2))8{RTfe4yv)QTloob`igyz_uH=e-L>+o#QZA6aci;WS3Ztk!x?8) z=2zLuqy{soW@SuQ(+Zq6k@`f zC5i=)M04_^v8k0)40CeADP%MrSNpG}mG1$@v^S1V`cLXjb(EPLjx!|v2d%tLGOy!t zCQ1J}J^C4Hr*8fi@Q2o)XG7wi*X=JclZ#d+zcJ}+0OpeZD^@;#FrPbdAxZyfwFPfk zc~B4a=(X5c7P{+_RFEXAS0A&C29)W>U+_M1qOd+I4+qN&iK);&rUt zpJfUSeTH%Iw0Vu{TLpWL1#52Z+03ZX#44DF1#_DRb6R;OFi)Skr`O7}13b0HY;R@K zg$3^vV#4OyOUxw6%A^M~>0U;!z2-AZ`Y)?J+RZBT>nwC1;vRbafXrEkBM{=vhI1kF z9tdwPyZ=q~9N-H{`fuU1I`41G~BJ&&1`(0E0 z##;G(%>1UB`F&{RH=Fs*v@%)1Oy*jdEQg8KAWM9v8{47~Psby)Dc3O1mFAu+tUNa| z&-Lb>C03qWS%o%-n6U2K#e(lZbMhP8b}OfEnA1Kug=}mQsIkMb$IAD)czs!J5ij)0 z%*hM*duOKh(RTxZe7YwxUg(_`bVePEPUhGuUI^sohCUy|o_EEU?k`=DEo7ug}enz<;UxTq#}i0=ao9Zv}F5-b#rN6h|SMqWW`X4gRP3?(ZyFF%l*(kA`|rG5L9w^~M}ycoy~q~--ua(cd=lGrbhotKx{ zA){x|!zTUGdJ4Z@drYWUv&wmKv^-22DGiqn$g8Dw(pu@i@>c1vv`5-6?UnY(x1~R% z-=*#HyYgK5J^8rYseHZsAyuwcDHMyu5#o4pnm9xJM4T(m7Z-|4#pU7}ah>?NxJBG1 zekGn4FNn9qd*U!eA1S>rjguxylcj0W3~7$EKw1s0b<$QS?S6COux(%&Aq<7_E z&>9WJh4K=4x%`>DPX0pPB5#$q%e&+~@?QA>NKVS9*LraS=r-cG3CGPieu3i_9Ji{>TgB}l{}RU?IPS#pD;#&> zxEsekIDU=eUU7=J50CbXE5!q_`vzwY;>;nOIgB$$aOPW_If^sKaOOLlIS#Jxp?3n$ zoWwJy@XTpE_XD2&5zn2$bN_|aSy-Ke)p=N5fYnd1x(KVEVf72FF2U+DtggW7Dy*)- z>Q`7@ht+Sex&f=3u(}1S+pxL=tKVUDR~#$;0n2-^{1cYSafozB zERuc~-<9r)L#02^XZOTn=}&REbYC1H6{7zJN$*L8;wb!%mIk9Yhe%_jB5ADjF8Xz- zG+r7eeIOM}6VTTar4iC3cua=Jhteo%iZoi93XhNAF%2Fc!(%!;X24@6JZ8b;6L`#q z#~gUfg~vQ;sW=~A3*fa7UW?$h7+y=@wN#oYE|VsS%caTUr_zVw3TcY?86vGjq*aKt z8j;o@(pp3+L8Nukd}%#?KbN+O8xV0LB5p#&&4~B~B5py%tIu)>1Ra$ z1<@}d`ej7Fg6LNf{TibGis;u7{WnCvf#^38{T8C%M)W&~{yU=IMf5)q{hl;b{1d1?hoYo4JOD78cdWIHkc%ja!!^&oYu{<5?!3=q+e7*59`M1W)<)ty7$~PLXkVlE1$=^yV<hEh#TaI;zoIrxJjNYZk9h3zmWGyTVT6Y z{!-i~-^EJzhx8?WcgR!4o$^QGSMoG*m%K^bjpz2r_oT1!yH`Fd?vtmB`*H4o{HOE{ zehCC{Gc8mRE|u$jih_@^bOAd`-L} zuMn@I{jSNMiNE5x+Cr_u{dJ0CsRFF9>?;Ix({;( z_(QeH$W~929j&~>5Js~JyrtSyP;G9fs(%C>)Hrzq)HC?x2jQt7^tAd=wMpx#KCYp6cL8wusqClSe_7g!s0;&E4H#j*#n!9mm zJ3LrTYY5ut#BMNb7KYfx3e{qR8=lzx4ML4c4+Q-%JKFf51Ae90P<|T zG(q^cl^yK_Vz>1vLHM{oc~ttt;?a&E&%B9lNS#({Lmm-3G_pd*Yer@u*Civ_>71L> zCpR@qOu(5uvEf_MEuTs0n9(aYCoiXWzNn==Vp4uVT1HMv^JbCG6kkqORzY?~{(zL1 zd@0E}IhlDW9h2}dGO9`QR!y2aBO{xo^vuXkX_u3i|4MXAH9_jtyh&PSrYvH*2ul8d zeu1=%OhM`Wzb9KcT2__PD|bM@{2au`Z(g21yC5^ONiRW3%gGazS2G0VWg!ZOR|EwK zS8hK%lh_BpcrvkPb3tj-4v#v<3rgDof|8JtpV;&Dgo12XX^-Pm^HcFS=l?JTWROS= z5jySvFm!36sb-f-+q@RdTeXZv1v{r@r1t4pkdNWjEcho9ub&@Dc;ar&D96xv^h9%v z-x~iYT=Rxd0i*e`mmb1m^;jdaWIa|`0iQxg`K)?utevZ*o~ynj`hTv4-fbD#y)p~Z zkRa1;%uDSZ$jeXd)wfByP|dOC{Wr!pes68>A0EB8_(nr1s(ONb1#O_H;hX(1C*q$? z^LI5*y3zjUNxRBb-~UhB6~F*gV_!Pf>G-2jVuxA(*!pi_!G`}-Uma^Zc4m5NUb-5+ zY0-~wPD@$qjak0x;P^E&=T~24KRRALsj*v&ftv$U`aE0y%|4ai{wZ*+yI-QMr z?`CA@e zbZ!^hscVN0vBKa7ga}6k@hPFO0(l`>{rIDQxiQTbh-!{LZSS;5+411)RsFo%p6M)o zT6IrrA+CL*Ut2@){#}Jim=T3dp}SnhgI9Xs@OwQ$h`=W_9Le#Hs`xh+vfTJ{1F7Wo zY55326bc`L{ino!J+ZG?Ul1zBRx2-5#miLHxPNX&et=m&2*5TKCG& z#j9`{x(19tBgPYn@pKrAvDG4ks?Ss7K7sr^W=uF%5@Vqk4lS@rXdFIj+^-L zrUAm>r?Sx3s}5OzUcO&<_9Z31*uGO+Sgq4`?EPMoYsR140fpU>!X9JOPeHU zthLjn@_d=;{*G-r`qK)svXJQ)K2J6JbCt}<#uc%A*5j?v5__N%ahvNYGO9{@N}pzP zVEi>PPU1pl7i6(`WCZP1xw}N`%?|z`;6xqxT{g(go;`u?^M{NAR<$mAj9R6$k2QW0 zt@l2zMr4Sv&V3)0hg8bH5g8qnwyxfQFVR5da63l2kYb!?=cEO&Jen;*N7azWy&>4> zi^C99M@kwi94lFBj;Vo{vKD0nnf!C18h2aJK=UTGL+JjR zWW-c1bibT_Y`q~9`8zdoF2)WL6|(AM1i|?a>O6*bF33w~JxvzpB`zjRZQ&Dhq!%E*Zu#7crCrB%2Xe*^?^Y^Gqu#89N^^1fB4@y4tsl(w6(m z!clb~P?ki=UNNnN?nE76l(_R^Qu;6@D!uT1e?hj zG}<68n#S$#m!HenpGLf&5ziqc$JbZ$F>NRa#Yi+GIv37FN2t^3fmZPjPrSny?|44m zkreNECB9r`;hmthCbXInd$=}3(!fLqLi88460M^PkP^3y@?+qsoB7)&z|5~6{4T*S zVghGXkge^c`gTjE&}B7zA7{`aueVXq5M`@;s<|PnQ;yzsYfZL|pkC}p+r6T3Z7ax2 z?PImVT_csc%C}cRmLG|6782N?4gFWOTB}ST$Q28^O)}X3kGMAhkD|)rzN?cUD2oV! z%OF%$5R6i?h>-4tNT)jp3PuJ{QG6pySY!#45RsW-Y!)GaD2pJ12qJ>WDk9KqBAciP zG6>?}f-(Z4Y@!09^8N3vQ@8teRplMK-sk!Bp>B8eIp_bo`|0XV^~Si>tDr5`FWM$c ztlBIWvo4m6vcHDpYhS*25sesEM@pEmK3F?AmKMq;#4P(Hz?K!ho=_5;wm|B%UZt@W zGaHgW@tR%D*YSRXdKVS+?14p~l-lzXscmSpwdUUxxc|c4dpUJu9JW*p!M_KN5+sSpUEM_dnf%VJU9s8F>MW{DwoDGTRs%GR?dFNw@Uekcl6y zU_Ti+lHY%Dq>5iG!Oa;0?_`?y_CpzWAA=;6w?lbrrtvO`%eVF1nrYqB?OhuOn9fvT zzbu4fU_&C$;_MS1Z zy(EUxo7jF-cOO+(y2a-{wD&C5?+Lf~Jm6LFKTteKiqdU954tEG@~ZeX6u-(ez93Qg zR-a#q5%z^mUm9WGP?Mwd*5uy-=UArkE#b(w`#c7SGgTlgZuj|Z`B*0i3#B)#AAxly z(>O&~(k(yF*r-m~sLW;I9O0n!hVv_ME@T?N5RP=)&kHu3UtDl55e`akIEufG@dvTU zxBmRYCM^vcpWj?3QFB<1>JXcJD^S&jR9E2EvB62*m`;o+y)oVf#tgsFkN~CIfo9nF8rrDLCTm1E zD81p_0i33OqcPz~w*+l!!)fe-)0}Wndc*MprzNpSw*_r!Q#QwQz^h^o6thWDx;1Dv z6rED9yQr=xz11}YYw($b!nfwGPs1yy+0|V^rrkbC>QySfg~9(r z;}|F=9F*R0h61OQSmeyT6rHo1jhXn&eGezVG4Lc2p!7!YPrqB{9upf*Vko_djX-su zqUuVS`%`G|J*?joGWU^Q6~{nvG$~4%`)C)%v0fD?LUDrM7)PRV<~~7;uyHnhX@osX zO^(uAlTQQARKGEqaOBK=Dj>G8W*3?JtaEKHr8j&jn{8;h^+}vjjMA5R06-zhRS>hRsqUKyk7`i<2DA!Y7su{eIr7Dth}ueMQ{na+Bz7~6oc#cyo(8=Htk z%G|ez3B4Hv@?6?vV=_nWc4{J&-kNAP*mn7i5B$bXVv{rXT{ff-1ny27oHUU35F<)& zjGuyWzu(wLfKukZ-^RDkMrAhHLBc`l4d*N1eBn0^5ss9(e__Kp6oG)e1OVbFURB8}$iGB@#0C>q!}{b#(=}qi*RJRdTSIXHNp{4)BdORU#Z|qg^4k$JyMJZ=*>Y~`(t6~6( znE|5(iOM;9rWji-Z2I^lXB0lk$)d(a>8-JI0n$2P<40B<1PtY&>_{dH4r!?Fk2^H=Itu=@>Bb2}jD)JKAvaU2r-R4oYu0U4io; zvB-J)gLY|is60&CD7|SHK>JbBmNWE6-LxMgZIs@$`#`%eVDuz;DK{^~B6vvcQZ{;- z8trK#F|(MyUIG3FfTDmgFktj21}Q5q5>s{{2;@1_-^OI7n8nmMD7`h#KfpFDU^yuzKTS9&z2Q6qobdsp zjBuoUe7p^(%mrs6;h^+}GX*%4h(*fBC)t$Ekv!F_;tNomMv78CJ`IXa3Dpd$D@t#5 zeF@4lNm)h8kn{2R)>48@d>$Tu&XyHiJ)c`X z-$LR;>5Xp%_?88XB?Kqu;L8$|z339#7(pud8PCCS47^ELDE};08+`BO|M2g;lx4Ls z#$-9<-(#}MMt$Xwe~-&DGk=uHt3C(SiCM-35|(rCiCI?eJ;Baku3nP}0%h_L(*QA* z2;{tbYF63k!-;wK*F5jWF)*FfQ6{fGGs`XKjtR{oA(Y7r%|SJ1Q#GZ0dp274YlnP$ zt{1iWP@6|;Qm#GEMeQ{&YKx(^D9cz#f^wd{NQ|R}Hf_qYmrw(vOum8N0>qnH#&Uv? zbL=-EE$0i%-C$M`49etTHUMT_ma&##r2KlFjb*K!g>T0j2?b^HDBFOtCCk`MC{k{{ z#fGxk1!X&-piCa+1EB0A4mq#hX_qyZm=8%8W%9ZoLw7gn$~pCJH{HFYi!yoLgU~&Y zWqd-?Qa*hEi`zGpPk&;gFtd=)yoi4T@xxihms!T=q%Y;thsCt~66*5Y_}s>0=F&%~ zQBWq|C_jMfM3!+p%Q#A0avpuchI3q?9<_s+!{j89p-i6aXONxCGR_i~ltZ7hQJuB3 z@Jag%p`c72<#(W5$}%nzij+TJvY}jbLHUDFP$rL(nvE-#*=A}Y<<7or=Zz~Z+k;vq zs9iy7Qr>(8)SMEbE3?f+2xanhtP0i2q$=mkm2I-fnPaIzHBv{Jy!v%eua#}o%r>qe z2034@l}$?p^5vR%e1!7lYszQ4p4d<(&!&N`Ubb-)fyudYJ-|o_TJ$E{m_V+4nCHqk z26RF~`Dc+nZiVlN|EAD)#Ovj>F>cCn$d_-*DI0avAzxN=%wdAkn{opv*UvF@5|?x4 z`Z-q4tlKy+Ztz=$^oxZJ2?wP&oJPR8m00BL`PLl#fN^5>e3}#Bh>MYCgP`EBH% zz!;iil;#*EL?Y$kL&bzH1%W)5N^DH#sQo)N5lU}OGzx4Za*U^PjN!y4=i(!5NKXme z;WjvFAdMzQl-?Mh0ps`_ql^HhtbDwUugpeeHrYhNLFoWpg~w@~SuoinB>k%Ft&+(JA$sOLax*t*-N-Jdc#+EPb9$ z8e=h*e!NBmD7_IZ1HqCUfgS^(FGMf_(iAocV<rO5|Vo)7NOtVA<$V8iX(LZ`5B>qgUh17yMm-Y!gf#@dbP$=!R5hqR zuR(8Am1sR10cf7*O@L#dJ~aVKZ%uF;fHHzcLjwBD0(yY~WdI_=fSy&O4a)~=L_jFL z0o?(hra_}I0evX}HH`ymTs}~90z&Bx$Pb{FMDt$jjqGwyR#=avqdJK_f`wDM52?yu!po5I>HK5jaGH zc>F3R>Zn;7njKchD?ldzbPO7}6H@*)os8EbQMZ4#Z|l{z1#H{}8-KN>V1A@K`T z^#!c+A7ulr3;snPkuk&)`IuMvK9DaA8a+t<2+6;}pef}8y+A-Hy#c)hpqWG?ZCNvI z0Opo8o0L&{Q+@@?b4Xd*vgXLjV%3^Q$|$`lzYgUEL1R9NOIy|gh+A9Md^~=K&69*J zYmrxgAv+Ok%~0jzWZSmPC7JpiJlE^S#+ zD8{W#qVqRU=cDx2`CFj8IcRJmacRriEVisoGKN?pw|bTT0P;J7#&(jIwyd4l7`CvD zL2OyuT`)fU^B8ZlcUilwE$cgA919vp2t(eoj)7w*;}Bcc5uEvuor&MFKH}>&j)4=@ zIVk^Z=g3%RfOU$Pq%G?d8sZ~16%*cNo%O1C9*RE)jdLU_Z&^P>bsue6=WGO^*~gmz z$G`<@0+imG;4*-I4;q&UNZzu32gG*TvM!Ymq~x0Kd{KG>s+ilxsE})<;-;G{y_L7D z3b`?$R6LgZNNS-<1ccHXP*ng`CK_qWs%!%=x2$TUjMAHO4JcP9WogT*E-Q;wt0pO< z^rn0Rl&{M*YLU3KWnBkxYs;#I#|POwN!YS(^a`K?pl+^FhXAB4t8N@X9Tx!2D?md4 z+?;Eq6M(d3-5dvy?gDU&SAa$UxRunUE$db&#*KT?`37}9N^hNi2b7!U8jVR@+OnGF zTJN$N%NSzIYVK7&3-bP4qXo%JTb4f;-}+}8gV?fKxL{=ed5jRg{+iCe{`xTxc9Xtz z4W}{#@&${CzeC@Eqnl1CD`%gn}}8 zlrMmCh&ber@eiQ~jM=GP$rL311QyrL;je) zx=mIZCN)VNW%BCRL%lYs%OBC#E?@lyQb(D*x(fBWA)^ifNFUGF4V8^P!4^I7@q8T{ zk$HJp^MY_I5N-(>4MIkJqL4nCza?aC0S%xo&zbr*9&?1=Mooh<`KD&c(rDt5E(VQ8dt8Kg;>Dn` zUeqQ+Z9>QxM}qQ&pb1dCOc#R2+0;RDnO7ahz_V0!l*w0p8epb|jL8HeUj&*8fU|TF zXma^5(+LJ;@-VXjGb?1gNHFpRpjmM+FP0DUGQprs9_CfRyh0?>#h+Jf;^rht1gG?(vY#3gr$ovQLA~VO-xX!#7nP4&&AOol`pdGT6f! zcXw7g-0J4UJnctlmrHr9PzOQAz50~5g`MyBD zFDt<(J5a)`T4g-Jiky7kUHQJ&`MzMjFE`&8B4dRF!lrRv=T!4S^9Do0*-(Tp=V%2* z_8`T2klKn~O0&*Xu+CJn9$aa?bd`0cvUR44^`I(yseQgLFN4#zi58=xHPF&El)&E@ z_}#pv*~27S`ks7WJJw?Npr!9YOaCKm3=11Wt!BPAZV(M;V(qyYdzge+e!lNMCYBGe z5X2&3<6oB2{n1F6-E!~_{&m25nNKsdj&brM!%7A}`PT+NG}%}-G9ACnh94?n7W`+6 zy5JPWz!$L=>+~xbaLe~~;?(S6j5^i#PG&v))JRpI&$l5{Dd~@2yiwSX3i^~tC4AMU zYRVOvwF$8g9YTMKIObv#wpEj$5!sB3OoVu!e4)&4p)EXV1oNo&k88joH%8`v@Uy-zi^4+{g?{*9QkOL$jcq$=ozGXjFn2dHac~(eI z0I;-_jC1puE_|jYjv@9FS3cilH_ti3^Cf4`nQop7h39-{&v|a1ONHkfZYFODlND|z z>tSNH_FBh5c|WiCYB%@oLSc)2Tx@o((I&TGdql8Z&YmCGHFmlMJ1BzfcMi7C&GWGE z{KDDukelaGc$$rQ#LeV;5&U?9iI{6=gvm)alV63&`Eq*gXUC&iZ_p6THRDyk2JOtOS@CV-`-q=lPLNcgl4BnpSSS?P$HhSB8ufPz_D>OPn6u|l zyGE&7u%|_^kbGz`|;_SKE&GSRyxzo*LuQ1u|X7U+K%+@}T<+POa-~;ayH}@k#;jn#N zeCb@H&)tHZ6v0k7dmguI9CZu!iwJhkIoMe@&p(9cC1=lzZk}n`R%80I<%uMQ?v*ex zFD6`(U?S#PHDOZO&E$GvQY+iN*J@@vEhRm9k6z;zS{I?~G55qbIBd@Pd^aU{i|VO4 zR`qVmkz1g*HF+BfllnQfr9^l0GKANyISyEZtmw_ijxQxG@x&b5%@g7lS@zk&#P4Pj z64I>!EG;EDZa()4pSC#(OG#hef^FP9I}6W_&Yt;hp526JS7*-$-8_2;&jL4-zQUx? z&15i4%+?;5<1{FXdByv?x&K`#47HDoQs)|#xCI+6f{k$Ye9Epd+%4Ed5p2A3urfE# zX~J`gv*#o?&sp#^8*_%6$y^b9c7lnRYp)5Dd2S}lg~^g~dhHE1>1^&&%%IGMrdv#FhE1e#L(|q3F1Xr{1ZVV~|`o>+c zEwfDOi|ATV=@n=3Jda(^&99O0%aHvd+^?aVUvuHt)XA^0n_ocqwRAJNOPFN4nY4k4 z*&v~yQdBx5uD<4S6io1Z)oP~>!t)+y&$e!!orPydXU}{$&#t0E4yI+liw6KzuCfXrklw;VKT?fWD!iv z(YU~QWXw-C4oUw}EBX<#dO(@(FvW<%d&NZs<7VJ(DteLZC6T8Ok zZozUyuq@|bemBoH!ZYOT8Fce(4^Oi(+qs!^6v6LHFcEX@0b$a~&Ezp*@@P4|_DIMn z=|9DLw5wa_$3^Hq%suh?0h_ZvUtxl`7|s#lJsjRrcK;Li92QDQ`p@GupZ8-}limDY7Jjpw{9bhPn=kxcaWh#YOcuDA ztbmExAWK7z8{6UpPanP~!<%xA@Lc8Wxzf#Zlki;c>=||Q+$t)xIl)A9-v=W2duUF1 zW83cL^l#y`2TlnaTN-NY^X+o;eK>3`%e+y#(-WVsAk3N*`sSB>6!s;bNBKGHeU+j_ z%&){e5>|S|on&vec(A@ASnsgXZ;*(^zcAE`or?1^KN9cZ66$X}RBB2|xQ3GIOHCOP zzD7w+Nlh&c*JRIApI~JQ`}$H*IDT&dqxk{Zz_2o?bYQGDHGIDQVWsE5Ue+lN)z3-Z zmr@*7iVKG@OCSHfQ;n*r_&(HdQN4eJm6CpcFSJ7Owi<>|rM=@SXtvc*oE{u^Ry5W~ zL`y-d`)5hu6(*g87t&Zeo4 zFBp`DyF!El-MW+%7MFB;vaq=5$!_7olKw-A26ua)UrA~A0bL4v_cI1|FBwu;+$}GB zuhFhuw`>k;?x_QAb+C_kRPUa45C$}x4J zK31EcjnfY3tF?97TJ1Z1tF~X;rG2dJ*7oWbwBNK}wGZ?$`pf!j`eFTn)Eeo7hm5Ln zrbZ|Gk^>y_Pb(y+CU8Am3H>g|GZR-2#G4;55Uj1Dii}(|?=d>x> zbZv$l5`!`c$sGP+zPs)tBkZ z^)>n?eY?Ix->H9~@6q?_`}70gI--B8AJxCpPwQv&bNbKv4Uv#fQQij8YV~a}tyb6K z7{zfNj_Wz&dUYd6H{tjWj+=3O7so9)Zsq)2)$ORo4jkXZaVL)Nb-u=){J=V0{{ ztbT^oFR(ffs|&EY2&-RVbxED9{szn6VfhCvFT*mT{i2T0&Z{G}3+gECqB>gpRef5! zq>j;kL;wA*mT7;ea`lYfqz($7oZvvD))m znKljmK3yBHy#S9H@OV+1sLj-#)n>utC3wt+$II}T1CP1zcm*Ew;PEOv=ELJPcr1X& zLT#D)I=mLa>kW7N+ zMWiSqtZL7Kw5jP>?JBYX$5#L3`Er_^PTdr->R%qL`H?AmWFJxC;?KLd4yOxCaqGM#R0^DD~g?w@=%seS*mQ5%~cAeTwJ@5&bhn{|}-c zLiEoO{R>3@64Adx^uvh$HKKom=tmI!zli=Vq8~-{V~Bnn(ZAFFt)0;JY2PFI4~Tve z(N7`zX+%GR=w}iAM?^n|=szL)&xrmDqMt|f3y6LZ(SJqsONjm(qW`XqQUAcd%TS5v z$Fvdpac!jjoi<88p^etR$2^>vK1Sb?HCEr6Rilyv^h7|_Wy9(E-mDk&UovOt=QCf_FJ#Wt z|D82U-O!SL!@{d)BM^j;#6mds(mP@8}EkommU@ z_p@Htr!`uHe{bm1)W!N%b&397`ci#o`ZE3f^yT`p>=pWjMsMmD8?DrTZSPCI4x=BB&zN0^{Zbsa9_37#s z{RMTaK11E6zo>54_h>s{`<}i=+o|tR-`6i;E&NUU5dU`Rv(%6Dm(<<*Y;}+Rj`}fP z+pGVs{Tu)G>EEiK=yTNlICnt*L;Do}4(hL{pXu|||LCu(hxGaC=lW~v7y1JAOMRjG z6;`st`p5d$`e*7l_;*C#r~OxdUHw+yuVPhGkLiolPda6 zdP-lWp4MloXY^I-S$(6Do z-hKGF6dY51Bbll6AGhfaRkY@T_CD*kJFr{CYQ zW%D~TTZ&WsLDMEpTC`}Ps&_VPeuw$eV^=B4<;y;$*O-6IdAK0+kGHD4_SxbNOJ*Hd ztvBejP~dS}WCC^NLc# zGrJ+zD$1>_2jcz{cGURnr4{)1@^x`Wcqr_s1K6wcBZ_k0_3TmXKVe6mz+QR&Rz>-7 zM$Cpi5_Z%P>|EtaiZW&^dldVR*`bjQHeUM;C@c=>NQdq(F6vXe=k}UIPZ`DyEBK3>h}KuvfnUiqZRj zPsfVPysKN!;$ee_6d^wTm6Q|=EF5@yPsQj}RH7IU_fw1qmF74+q!`G^iU;GB{66@H z7xQ~GQ;fW}c+?@R7(M;GmPGve~GO5 zn=%+<`T7T{VyU|RR<>YWAE|&$8|7{M*vLFriJz;nH1mJ1h1F^O2K5|J+6xIZbz({P z-i0MYy7%mVdtarxZ_RUmo7(7^wY|T-?)N1>-=a0I(Z;)iIZSx?CSSjn)~fN451MuQ zx!w0Ke2`M(<5r$4fZ@kupZx5;L)SG|+t2&U)_*9AHvX%|>eilP59r&yq%V)&c=R_< z%-mTAVsZaE&{Lk+S_tgmf`9`O?X!UNt zL3rOZsQUnOjt=P8gA2X#z>c)4V=gVzR~^uAdHJ546s1r2=DY4H2(>O~lHWSqF0b9a zd2MoAVFSln6}d4-bZtES$pL@Ka%?kURS!Yj8;>$`K?x6Qq$eY@5r zg*{7)3-7wq(Y+RPzru8%BHWvV?z{iK++f>KYf|yeh1tE#OsR3`x#=Cs&a(&e%gcau24{N(J#+S;r?Z^Z0`=0sj>xsjg@GEIsJ*C3u*(twe zr$k%%Hnj3h30J80fawZl(^FL_UGb)#SE?Y<;Usgo z4JlA0C*Gl(8J_)FjuihCGvCI{yIbbn5x=`>j`|nGTwv4{NT-?0qkVB01(%0WnN-w- zS0kkwuE$Wr6_gCa#$dGqtIHYY80e3K+CWhXSzV^J@Kwt(U5X34v#Tg*G*yXIgZWuz zeq29I+rj9EE{*fJ1|B~%k3~=6&;r>=9kgKz22#tgFYVDxCI9}s z`#N=MUr^G&prnv}{{VkM2g?8wvtQunQ~HMMQ|}Kf9MZQ4U&+8+PrE^w!80c zSgnI5xB4g-G~|>^wz?rD1=uqbE8bif{>lt{Nb%Uj9aPG`tU!%+ z6YMTAyDDO4i`SZi`#1L5dy*Iy_@ZJ#Gy?&CXGV)8p^~EFAp%B)%^$F-tklUtGqFV~ zu6draTKbRcy0p8m^L>hfMM_BwU_4gNJ#Q3kW9OC;BRB?YYhg>1f>{gwv5QA}foWLVO-U+>rez7C7}U*8CF5B(t!i<<~H&SX%CfJrQaZ2CT9Df*;_5qbk9OR?Sj;`Y#7G6 z)|%e0!T335+(`;)UVD!Xxk=3A^HyeBfIz(mbnjCldgA{8YcjXUR;VZbjxRD5^%Qfg z9W186qO#I4)9P!qO9Bet|JlkTCQ_^Gvg1)Q+tVqQ_q_Urak{)}kja zlovbHV+N~76gK9FVB0=hH?3u^1ERdhO!i2P%lB@pO`k)X&g7N7lF?fAr2$~|m~KA z#L8CGIXv(((J^8YvX4OUUu9)m+*}BDYKzcAP06$!v6kvnTr{+RH7hK}r*c_p0n)aI*aZ2Ur&U%uhz{X1MGRzGfGR83+Lu}Tlt~*S0kS+m zs_X*JcZu(q*o0Kx-}eaVPMwj109dhr&vDBZ&8_ZjQ{#%HKj}U!S((e~`Fn$L$=8X*_=>^-V8)=7roezGs&3N>y`eAJL3U zErc7a#Uf5=87Xau4R2|Db;9e*S@%CKwJrv>nZ{d7K@(JK1&0|BzZ6j3Cl;=iBsW5e zW>&1gysLpZTN)tVDjx5txMec2PHDTO24e4AtkxNh0B`dEcV(91ZE%a`R=Sh+PX}?~ zmkz(xtisbItI|Pc=3(tUZ2GL>;rsaG_CBk=al=z=e%+l7MV;1K{j}C$H;wDED79fl z`+8bh(!Gz{s=AI<>Wti8rFdsKq;MeKd&DI`>v`>4C?S01JU;8|2Hg$3%5OUWvg?IrH1%;Fix#yUNlk@!%o3# zKBeN-k3=Gj`v158{-^srEyYcYA}@fE-_>waW*cKerg=+Y>Av9`GI4V$_PfL*`Av>T zs&o^acQVZz2&0U<15Ogk+o8NQ(|DJ}<$H&3&BVQUy5L{*T^k3O&QxJPUx;I12jQUf zhVvnC-X|9M{^9RumW`gtet>dv-2KC6@t*<5F|dmWP)|PQC2;{j`!^UKe+8d~ePv6 zsIDlz)ing=ASuiDAP?H4F&1O#N09@dD_X{Aa*%3_L_wD3iis zU*O@H`{TgsOH5Mc-WLELu?#LDbMH^eD7`8F4a!A+V<3sknR}5~*9O`+z_g9$%{T^% z2?wP&oT0!eB^EhzFGc6MG8 z=Kd7gdk^dPgv@=USH&?<98HQ+=04g*ajaLxiBO#2H^z~uoViaBBW#>aUm9W0Qj??f z*5uQGGu3ZQCLB3)p9+X=tl358KDm6X>4b&S8`jIfddY9hBrGX&f5}EQ(?(@(=yM1M zr8k@fz?tti<`IsRxzD%Z%yYq6NH{3H;Vc2p8^j`K?r+$nrD3y_2vB+>SP6m^L?CDG zE6OK$iwID9BUlH5wSHqYK}ebVS}cwqv&B(l?yGH7W~Q^=E5b-iDfRlE>Wb1^T~9;#Bq__8`$?NL#$qh}I70*|y%Agl z!Fj*&v)?#J9CGGj|NJtK& zmu=$((7So&j$D|5dNShWHU*W7Cb%0_*{Qi+7j{d!VH=}oyVlw0ZDm!I~&j4b{@=2CD5L5Pa*>b^){>C2cuFf7DI;G15lqO}h`Y3j;<^l9zJxLM(!Z)GlSCaXr1K zjl|4i`g#TU8vu#|#=wBlpBSX9yhu#hfgq6QOn)1bnPL`Gq4Z4v5BSL6WK0eY$7P0g23H>zTp!A0G3~&_Iwe#ysIDlz)%7JP z&m?6zAD?NH#x5UAEoKt|N^b-UKrlaG%nKNEi9^oE=UYn&GVytM{5e}zaP@p{`FsnB z52ZK072sPIFqROUoP#e*O!lHnY-0qe;AcDs$1(6GVWIr9SZ(mVm;b}BoR?*_F~(#$ zny-19sg*I)B>3vZa3Y%q>D0n-Gk6QkY#*A z(o#Ns0E^oqM4uJj*yrTyh?L!iIBPpdPh@nZx8Hk)ceU>}Qaj%QDUqmXt%Evr(P3v+zm# z3!$J)9_4qST*@*o5{i^RU$UWGbV2!pP*5h1lA4Vxmf2=%BIVA$Z0C(DE!%@yC8%9N zYEs^O1=O4pp)0e^LRlr7XHR+WWLa7TwaTVipwrq$p+5eiy}TuZp=)Y@K7|kf@wZw-zHT z$EGihun;vlN^ebm4{+M%7;Okg&a2x3;y7z|@lBI9G zjVj+pWo9&;2?wP&oJWAuHOF|6aHK4|s}1Kt7o2W{gVGyLciP0qzf*pQwQxWjF5 z(m)zbj3~V^J_E+_IYt=)N?G}M8(*1?%51WUgoDx>&hx;Tl4DFF94RxOV#Ar_f-{Y9 zP4ismTqLiV}hN4sIHJ9p&(pz2ULwO!4%USw7n>5B^ zEd6+m2vB+>SO$V6ImR0~#_Pl(XX;DjWd-^A8#wa|TWG{LO8_Pyr zP?gBP@JF`Mn!&QsqcjL#;@_yhq(-mCnKA6lul&rfYJ2o-na2Ls630O8pqa&@^oCUj zST_>Wp4J;jR!mhQlNi#CTnVCp?81)i&3SZ_SH*NFYC)qOiGIQw0$)0aOl7JXRG-(N zH>ygso{a!B&+{h0F;JhH0HwDkxD7xVL8Bo7eP#i@z<@FU5n({MO>V>Tff^AIN^d}S z0H|ruXiPv~NvKH_>=8a2F|~^roB#=~~25ya&e@!Q)!SA#> z@D}J82axXqfIDA#>w<>>@Bpcwi|_mgpjgJ*++3SP=Xa&fN9j$u0LqUBjYmlQ0#$th z>-}r9Ae8V#+kR-nfNVh4PUQu3=E^rL77zN2&|`oHJq5FEo(R$ zVohvVi2jIpRU8Aw(LrM*iOO5nXsB+aEo-EW0E2WRZvq?xW2p&HdTWAb0rX7J7*9a* zmh}uEmeZCszI>qP2neM&py>d5K4?rKAbHDrJ`QL~`9Loa5K3=AF9B#K(MVg?OdEi? zWz8mKl-`tIf$|(umbR=pva(pU=8-Z=Z_2Mjc|p*aPvX*+wE*JQmNg%b-(mA4VarRdE0-T>#d21y~P&D5*4j9LR#u37hx2$8}*vUA=mURSYK4fR&x2%u&dW~b?1a%I| zKifGn))`=(A|`3eI)#S#h)uDxQbp&q3oHiOO5n&rsb*Th=)n0ciH|CcrUp zftmoNw3mro>zolwQ zAK!nAHa^DsIpL4aj(bu20cs~mP5S8mgp1lqFKXwYb~e{IO@i{r_GiUtI&IUIM$=E! z%qWv@=1V}im}{IT6!|0jivT#xn)+FOK^xa|&zFz%8zG@g9w{x<#z+YnO32JIq>t-U zLWx8Q&d9^T-03TX%%lfp@+eh+a#hHvL@3fn^;g+YD!HIkB@~p&qtpOOb>fgermt?3 zm4-=8Qb(D*`t?w+P3rPT^tH=Zzk$?ICa7^;Ljcmp^L0aIqff9!PkcOI$3|pc zUe>%I+zNzSLPmp-QJ*NJkLGU)SzAB@sLOMvzKzEmp|?@fpiI7LnuDuZ$Y>HWZYM7J zWBFz_oF)SGb{m*9aPA~Nl*#k80$*0h@DrT$k$jeo&2J+zn<|G;P$rL(2b56A2oj3) zaeT;z5_CanLntVdN4Xa$?TADAD88Ld)f~I+y{O#}wfjg-`WXH`s5zxf9jT5eldoeJ zsCFV%`6KvFHd&0jSo-h)siRC@y#VTuhKxr-Mpt5xKYo8yUN-RY`y)7WiY+AKYbgoH8~q+57~{S=Ufhm2u_ zBwr934y2!0D~St2!*J$2I}?9F=pxTLaSTKV31#v~V}LZ8c%+L#qtPB0A)a_KXsj2t ziBOvmGRBdhd?9E86fe_-pm8>JkX+_f$1(6MRUKvWRi6f!sUc%B!N?bZrUKwBT?Cq3 zKFoB2L76+5iFEPj6`Q!Zi_9lgl*y~U z4%G#uDqZ+lAghY^{)4MLyIPsM(;%mH!Z-n^zkP#(u>0;0NIPs{9_$DvnTOhufl%)$jo1qrB?ugFb zN}Y`|`ObbHs_%u2?IbK+Fmp34{O}r zS?P?QYrTB=f4YG`lgP{Wg_%SiB;FAcZ5s5oB#N2D-CTk_OhV$Gd|x{zaStT6-G!Tb zhK-Uie=D2syEot0KHt|N-*;cW@BU~>n7y;UgMXK+Ugpzb+!;0B*ResnT=RP~_3`5s zcd#!Gv0oA}t?+G`Z7Mrg!q4HszpMu;d(a*Ne>F|fWbCg;hO+u}>YSQ^@cF*Z4gL|1 zmWEk8{8RJ>KQ!4`HZom_G$Sqk(>z^pir^r)TyJl>G-8&aT>OA89zdu|gD1lcs@#R| zqCqHfCnBKN@C-c_X^Cg;;XF=n-;BL(RdNiYcp#B5gP(q|!QaEtC($O%d_>JA4a-KY z)tj)^!Fsk%hb)fJeW<~(aP;r6Tcp>4*qf_y!@U{)j=S9 zZw_W>s=(}#I5QUI)hf|{gi$xDU$?lItJ`0GG>(CZ5JTMAII<>XSKzneoAD!*|4&>! z)rMn6{ZxhZM?^_clpF8>7LUbQ+#)QLX6CEi>DBm7?!gBw>+d86ZDGEz7aM(r7_<|@ zZH#eYW2`l3dpDREZt!_Fedq9=_)*zlO4uBdXtnBW*s$K_ozyovk$Q-=c)iT2tmFIf zQD<((&xDl>e)4f)Y4v4;Xe)^Az%aTGV$pG7TJl)%4d_%e;`8Qw>EGbDY;(SJbRwhR zpd3|&&5i*wLcVVx<_1FL`v%2vnEm-bR2tuCGb);gn)BcRdk(N}0DDP*jm60Z z-Kn)6ruhXh{IbnUHn5jDSQ%V67<-xw*aQRs&v?#*2kbe(x&!Q$urWulJ%jVnIW%I; zC1D9Cn1~nRCdjK;Xv`O$jrSN)(;VYXP?^l7=A4Z@CtH}~oLejl$Hb()$y|=qOc=1y z7MX+)C?=z5urMqDB_DY|i%eyz3sDocp|P5%nae5K^DNAQuy|EkJ}__ib{Cn(0$5Ek zqNcf{Fl^Qgd{?QQxq`RNbY{5#Qt_LkDT-*=6*Ejb_6tk$0%kgi6)VE-MyY;6*ACzcrqJL;#$RActl@4DN*pfH(_K@X^AaV{rGv z;9e<4_UkwqT^TpB)y#Dme%6^0HDlwFkMqQr<1!~}Ji(vqEkfu9Yr=7{;*1l9g+Wz0#55wjc- zF;LNlc(Q^$NzFi~;>nwM61Uu~;wM)!3pP;M(_{wf+X#T*t5EQP!=7WH=3t<14jY@o z#s)E5SL3AyTf>aO+VCT5*tu=t=mr|a{!-u_3JpEZiG51rZ0cvgQrYj0|cU* z5avu3Yl3}<3A$D2)z8Fp-fkNii#*u58Ast`I))S1@8%#jC1S&L6Vr{^)3}VqtB#s5 zzIS9h8gFEWErbnPU)t4t!H4-~n0HPM?7~LLs*xzb+UE}ZLl*xL)#_b%pv&XB*G&4@ zoC=I z>}fLN{e1*L^qnYpzp>{S?=3Oj_l1qUVPlUN?;qf$1_$Kv{-No zTzXOJdL7$j5`%umEOy|nCc6OAgIRpaCUA5gJErit8PkhfqJf2XZ8Rgk=2iI*Lb0~a zFrOY`k>yFxgT^Mk+3)5ocN9t3Jx#Pm>~e=WdBI2TXd|CP&ADab&c^X4yzPs8!DtVJ z&3aq2_e-42Fh|cEpy+R5stE#PKKl3{121vnCbEzis*k?m9ozA>w%FI zIFpf*$B4dX@lJ=MC&gfkYdo>c}fP%cw3#8#c3mm(NyP`tKu_~Gw|qKAy5H95Qqmki&G6=vhuJ(On^H^*1#8i zaEPl|EEJy+F%5aQGOw;gesluk*@=}Jo#P-G06|m##LQ#u95<=s&c?NV;?Vt>1xw37 zOC#7XcoI0n2j_V_%&5rEUcf`SH{(=9Z(d|p--qMsZMJD_??Wn3gI#{(Bk$Lk)FmcW ziA%9t4#jn}xg|!AVwlz7iG($`evf(o!Mv~J-k0(4{|>77+(9Ko9}J_%F+N9$9OWwN z_!Ji7hcLa0tp7cJarHfR=`@0$0#>3wzz-Kq9Xp#Zx8@>r3%eG~-ZjE64SwhfXy8c& zJfW_*0uM7P^RpH4&~`Ne*IuyZn$sh;;8%iaTvM8F)g7AhN@f=uK;}@PiUDl{uhLbr zQC$DqT=`|W#8FmRhB4nUkt;;Zcal|LL{+YehZ$9Pm8&sVxfiNZFIOl0CZaQu8eAkD57AKd%_wYP6T8vPF^2}sp(b}|Xgb_t78xka+6)nE$*nj? zjeZ**A`v&&Ft$fEI2+D}210SER@k7}gOpZS+t`EDR#-dOgDYB*O-1WLrB>)Y_R^KD z&=2gvRjtra>_O#Ls0@2h#d=V+6qvfgd)}>+^ul@O`P#I_$BYc{3k70g4c3z#TKpm$R5NcVNznmf3(- zmTdMyZOG#7DSM^a$ZH0(CAt;P^AlzscOw_c!AZO~fG;fW!jlGdIuQmDAzGIcng(&1EjE=V0OmU; zqrIwLWHv4soHt_q%v-q7eeAU9>r|Im4`i73`HbSGJk!>SeLo9w z6KksYzUhdwd^WMJN@g~7MgUa26AC_?*mLw;2(#(7JR?I)r7ou3gD4u@o>$JN!ndK% zwz1nd;8S6X{UPSnI1lfY&1S8_n)P;87v8MGWt$q!fIEFvMYul<_h{o-)eYXNkKin? zI(r(cdaCc8%zBE?SJmh9ZOBwg`YUCrN@`jqq(zZR)fJ^`$`z@;9l~U5rqZw1lgbz$ zY|>ye#OHh0&1;wNdOuU?Su}8P_u@jOEX|63qZNHG*>R}@c%pEceF<^@V%Z-OCI{V2 zz7f)20a(KQ!p-M|@Hv*L3?5P(*ARoR0F&=qH_vmz^Nh3SDL2nc!t;W&=Pz!aKEKs# zf4G@c6eekYxno6BUJVnowX67*-o=H5y-Nr6jO(N3Xmg+MDmV8VghFkipurLX_ zncOE#?k%U++W9f*1`kW<(Ytw%-t89pArZO@b9b7vK3}H9wC7my(XWN6)#1P77E&lrP}0l(0GL^IcBx7BlmD z;aw{rZ(g0@$me%GVNxex+kI|y^SW7h=}uT(t?0Ls9hYj1CuV;%N{IWgW#3$wG<7q{ z64IFfmX?whZayL5(>jo_pQiGxB*)FOz3^=3?0L7FXJ_Hr(b+TK>X5`JkK0W5VQ7 zHzH}_(pP-Gt$1D$Ks-!0fbMX+Jco#rEbBV7Qse32aC9Q zP86QwojuFkJg36bY|Ke+CNo6vX$dA`uFV!EGu=!U3X}Qe^x8Z&>1fGDJiff?<8R|G0V1;OmOp>F1)5@IjnGxSa9bZc3 z;)&TGvlHTWx9ndNCiC1(mI&!Z0G5`Lg>F8pgwLBWVf5iXD~5a`#_e{QqqGDyieTRj|hds_Hps0bB#WC3wBZjJK^kk z+^%udE!Zz2*g5B5XWcyi5T2KuJukX>re#}=>C2WUk{G&I!o<9oa7BWNm}}L9No6;a z>xD_JZ1-NPneDWc^yEEyjaz74gs#Wj6W`#lIqUP?l;AC@r{-AIyD3L*f!@~SZ759Y z=h&7K-ObAoUbp5rU=6aOHzPZ~l(fVXb8t6Lh+AaYXA2X*n@LDWw+67Zl;pVi+$((A z<|Hg7eR&JEar5jfJUcpj=DT@z6P{h2Js))Q>>)f0+)VlklR`I>!7wpfdti>!pe*JU z@9*aRccC!UJ}yd~YgFPEY_teA!rAjFyT)+0U=u~K@y@}@+&rfV&neEHliWOK!P9Ka z8Ez(XMex}PCStC=CQRnJnJgD3OUmiBH`t`JWhGDW9(~;{bX0_1?KWq9zEug{VrJG3 zT1!dIpwhGVpt!4Uqqy$XL8Y&BdJInUd4CgJ&BnVis0`>EccHS(GN~`3YeA(~oW=7z zc0D)0M#3*c_KR@8hHie%g>F1}0{Mgn~*@>5#bkn#)lz z!ShwCojM55dz?Mnx_NdMo*kV%^W8kViV8iDU?RHjF%kSxH0JQ{4P!3%{9eCi8^J95<6iFfm8t0_Tx2Kf&`ItDRN| z&!x_ui`_ie2+vi{o-5rvH;4*F6HG++Z56>cqdDc#xXI1wL*cX&P6?xN3-7<}ZoVf3 z)3L~n5@O0KnH|1SG&=YE&m{3;2* z3c1o+Z2G0<%4@jbtS0;_yP4D!Ce__cZiIFqS5zW$E1aFGwlt*J@H>YgjSme?9Xo#;vTc?PYRP0ZYDno>9YWqlK#_f zKEDZ{i@6C&|6$&O=iNLjgshp95_0rZLUO~3s#F!8S2=rDa`UVyJgd8z+#pP9yP0S( zFgUJ4LW&&Yn%|8n?Rz%Mrn{oP+t@JlhD* zkh5pd&9gl`&Bko!X3|jvzc0Z=%(VxENhddx$ArnF<@DMkA*ZDO6z|clZlNC+q5ClR z#Onua&iZ_X3EpBjM}+rqcuU#+Puz1@C?V-TkJEhKkAsEfmitY1^LttN&2sX4(amqZ@O#D0WRWmg;AXM{CT4>y4LNRXixWJ3 z_!{9W!^(idLDGg%5>|SY_Kthc zRgDiwU&=qiO3B}qvJ}O~zfY9zOBn`JW@w&>v|)THPllD^LjInOPV@I{DSwA;ym5ea zUn;(h^bEmGCAjCQoF*X0g_Yg|y7wuO-Zza!ynb<%Or>gyFJ+>m4p*8%ZQ}DycXS5K zEMfAZo5{<<Eo6EOaAr*Kd&J}JH;=EGEeEtvO(m41U{A`X1$6B>CoVVAs9?nXq*~Igu)Xh_P45~ekoKh!Gd7Kf5 zA@!F$^PPY=aZ?^&m}53m4>|QdYu((@Z_+F!3yKYamXx{Cwg#!w^mlSp@>hXBD{K18T zN=gQ_@7E*l;q8Na^-z91d%aSzR<&d5VtuSOK^v#Nl)hS9r>)girf=2uYrC|MwcXmZ z^b6W=+OOI(>0|Xd`Xc@H^r*f`U$1Y~`CUI!Yt&Tr^ua?$Re80_nJPb3iKwI1@#?ec zRCTsGSAA7opuVoYp)ONbsB6@9>IQX-x=npwJ*FO4&#S+yV<9?0drq68P1j~Z3KwA0!JApE91t&h>i>f`hY`ZM~o`g8hZ{ds-5{sO>W)#n3l zvA$e?Q(vjC(%;rs>udD2dQ@Kr*bP8_7sxyG_w@Jm5A+Z9kM!O8$NFAt+# zO#hGmx&DRzrT&%vwf>F%U;SJCJN>+VSs$BTmOeiHne?gY)6!o^e<}U-^u_5*)0d^M zOkbNGP2ZTlIsJynv-raC+o_mE{Nj}p2wwXytiFZSQCJ;=)p1yT z2dfjX`W{w4!0IHdPQmIltj@sdEUbQn)j3%G1goE6^$V=d!|DR8F2d?pSY1*ltG~hW zcUb-b%geBgXuqf+C*)p_N+Dw z9xuUTHauR2#~gUfg~u!Km1{+>jYw+{X)Pi}5ow+Fy0#wwHfUSbjfl7j5#K?? z&4~CeB5py%t=e*Jo3=vRuDz-4&{k^iX>Vye5%K>c?mgh6sMi1gSqP$nih#&P(V1BR z(F{#Wwh*#OXjdRgv4Mt=1c*WcDTs3ME=h#YJ5mMd9i)eKP?lJ*(uX=agLaPaNCBo&D9dRR^e> zJ$dRD&p>snXOQ}xXR!LcXNbDXGgO^hZJ0W*+HiG#wGrx2*GP4kYm_?NHCo;68Kds; zj8*q~#;MDyeWvd7j90HmOi*t`OjK`1Oj3XFOjh@MrlMZq`JX`(7Ge_O#nX7L1%u_e1^VM%X3)CH+h3eSwMR+b&$I468E%H)z zyYox+Tjw%$hjY1l!LvfW=vk>=@~l!9dsnMVyld3sn0c0Z*Q#H7*Qpm9tXD5J*q|=+ zZd8|hH>oGWzfyk-|5{z)-K<`1utmMrV5|Cd^>6Up2D|NQp7O2Q5A#$uW~v;_RU6gs z)ped->Uz&^b)|O?X288_9_Frr>JRD$&wh2I=YYD(dr)2NJ*2Mj{;1}Ae^Re{4y$Xu zN7QxRqv}M=Y?CmzO~&kY&2vn>?m4cm_MA{Rd45yZdrzt(Fx!p9d^buxt)2}3L;XGc zjJm;lR^8}5r=AM`Q#~DiUi~Bdf_f(WqIx#`l6o%uvifKE74>}hU+RVMztxN3SJg}5 z*VN15*VUo&4fRLmraDZ%r4E;Gt0Uw)Dvp13V)#9Elzd+uEf=U4WWRHa+|RjF&UTKK zbDZPkT<2%=PRk8*C6M>{vkV_-AZc~2RK=V#7S@_6UW@CnZT;S-%x-SP(K6?vocuDr>)O#aGwBjRi4a(OdsDoGXmJu67k6H(+8OO2GI)jh);1qG5+ zT#D+PoRC?gR;>||gez5&JvEZjlM^$0B_l7uU!-7<;}h~yc+^Nt>GneBE_5HR2?!fM zF%=%vrb{=vuQ;~F9hv0?1N?{DAfYD@l86*{ETyjlH`FG%H{Df&+RXIR{{(EPO~yxb z4}QjpIAdN4c$>bYHb_axqa>ci9i<+o{|VR-hDU4GsaLN-Etx-R*K@fVG^krIq5L`^!tuI=rCe!byi#sa4x-zKjde zlq+3QBJX{V>($@`GkpX$IN3p(oBZ{n@OZS0-dL>B$$QzbnIB{qC6$Sy6=e-i>@K6( z!$}VWJh&ZeeDYRpJfE!?V1$?4j&%TecVKr(YH4N1I)T_#z+cK8`josXeDHXzBgi|) z(HrN<6^;TP#12iWk@1?+Ejit-B1e5KJ*`W6LU*|d_GHK}_Kv7uy+g~C#Pqa`w9c8b zo~_DlGP9CW(mK?sRom4eCart-tkjguk2<^&)1hrzTDOc2E!*H_?YcGUG^kO>Rl9br z4xLg`J2Xqn$b2iJKFw(of<)=iahxJX*&M?I30Qo2c6=l?xNPSca&4vFa>^~g*^ zeEN*XwbQub>YU8ot(vSz!%pX6~%h=34VVKigTX?CyrPD}a8bu`e8M zb@b`Fa*OHDZ0RG-+we)*6;ZZhck7yv(UnH8nfqI>DIM1Myh~T^AHDjExn-BzkDi>K zPGdKcldt#f(B^x^lnNjKF+2lbkmR0ZYiCp&=+rP3wx~p zoyF>kL+Xp4|2wjn)GD@0qek&DQSr5E#k6{@RkW{JOjMMV{g4#qa7?Qr`N@TQ98%e% zPygel3_U%Racp?;v5buEB|bjVpquOd^AmbL-XInyqT|WYNoJ$?6wGJwY524qFJ+g+ zQ6WqIM*y)&#RC3TM{I68CFzl7Wu#(tV;%Kk9go*F`%C?C78FO7zXUwLBA#oAXUP{N zsWkCS@Hn*CVviqeC`C7qi|>-08K0W`A(WGFnD%#+psvwy-9lWW60j)`*OzfJ<>6i) z$Eb#mX3+@Xs6zo7#5y7otZ@_#My5d$4d-A=kmc9k7;(0dI3qh@lYlr4yOt?d;)vIA z&g;1CC81iyhCSXaz@40;Mde8{Ao-iYe+Tiek%Y}w_&?XRjHB3XZ?RTTZ57}~>hWQE zN+$WMSzVi4EBHI&`y{d*|KIR^xMLZI^!OVAUK!lWsCi3x?IvD>h*!lbXta)Hib;=m z2=F3W>B$NBsTh-rgVSE(^i*eT-h`7bl@#Daq^Ogj)EZ9viPJFR^dGL265vFXdSqp0 za3yj%--E>IU&zn=Yq?U704JhEoeU*%rP-f|(+ zqfVa$I1wf4WGIn39U)HRh*LD2^w#?{z=f zYDT>#2e=WnB&;UsX&>>b5xG;uulfhrG=ZN!Fs29i5jn#zQ13MHTSfdn;Cgcd{Alg) zT}CG?Ut)uHf$ACJ{WcPG{{pVMG{BoyQt&pk--q{~#QQYy-fL)wwU3bEUTfT{O`8_+ z86U*MA4fU9tAdRi$?kc0l#=$lF{fZp7GmI0N*dHKruEyewT+99YZcR2lCtQ|6dzq$ z;xjVijfgRA+O}@qswrI8>X~yX>HBENG=3{S#@C`nv@hn>c>b$X$=_R#A9f;&Gqq?I zuYaYNT{4Vl`{yChEl`CG6u>)Uri-Uj9lpDO*^4l{P0a2Hv5*yHW{`;)bCDiz8Vv6c z!;V5cGI^$Ek>3xp)~F1-yTtArAt2Vfv~*0cy6Sis-6KYGgkTwI>6u(mhRuE0l#(h% zqAAF19nb{-WlfMO1V~Cw?m?|MPBfzUv1*i(etDXlNRQ8yB>Wfu_j?evS6WI^JpXHU zOtdh^BkT(yEFCS~d&ILpkk-4sIZXQ@RM>pMHYFpTR3n*u387au42HPOofI}sFwE$h z(z$RDy#%8i%DExR7!~N#*f?~5e3N$gi9;dW6`^J6ftU7SYJ9ge%*p+W>7r8*FPFwU zS~%Pqw{9J;kF@w$Ut1qS?u8j1rKBg^XbnRcHzdS>GdD{q>7l}4hA|(ygY{SrsZQ(* z!jewDTLqS1!2u99S!jfhaZ+CB@lPppyoVh(t=}Xl_&`e`x0#QL?mcLyNdErDF_$0M zelc+^Ut_H|fEz>vRFySHz{tvDBP+opF^IO!S~vE^qJ1&b=*zo40!qSiAmvSu>DD#A zW#g9dNm<>ya~fx%8yh4tcxdqQSf_msr=grvd%WznM3X@DQ;@IjiBlG-Ic31=$w%J32N zZ;$@r2WxD=+cWinfLp>?0aG=yh z@HrH2NAUa@Fon<65yE~H`a22Vbdvm#jXBcW^Ju8jq1v2x&3rvrDd}nB2oF$Nz?8ZQ z9fF}vR}?MOjF29P6eISrre3Rr-Q z`UZ?>V+9)3(3r;A3Y4Ce8lRS$NPZ2V&-mnWPb+B5_|P$V^;a4_wkpKx7tndDSaX*! z&#GA&30K=~|q}|C+s|s_HH86BYk+Cl{BJ)9FT2^XiRHNFB8ks(f zM@6}!T*eWh&?91b2y}81m1O{|iVjJ`k2Q=_3S`knPvKV=592hxpZstH$JV-l`8d8A zW@MHly4Sh$O=68y?|OrLq0~=u9VcyXx2`c*w!=OAB0|EDTr~v zkAnLK>fR~T01Bv_F)-c}Py&yia)`B&#`^o|cFkM0tzTD9wI3y|hCXo=e;8j*)WM5l zVR%swFC64WBz@uc!>S}sO5w{3spJ#w>Hmr6|C`7EbXT(l5xBq`xm^dncjx+uCfeEv z{l?j^N9fmMD}gr2UmKB^lPBZipV{Vy{z5=yNW+S@eos-9H@B6Lh-O&#bZ$XB|qqtgR#yqER^=J zE(7aggm#``4P%o)bwYK~M0MUorC)#Y3d2EZ59cOuu19EB8P4cHoa-i>s}?x77!FE% zIQM~bm$6JRdhBJ=Hg`?Z!mue|1Ssthgt?k%#a#LfJx(Af<_bPk1%eVTeWpffkDxRN z9(8FCGl;J2;H^zs;Zav!?g}zFuB4OWVmbd|6O}%JJZ2Z80x-(Ew6ZR(3?s>6gCl~F zly@0RMp+Pu$5I&+lRj#nW=(|BUK7b+d(Ndj>(VMQw)RF>c?jHdCZuOMZY2|((2WXX zL}`z)IvA_Dv?>fRH}J@+X5y=2qSBk}C5D629!_oG)O2YY!xV)RI4JGm zGyqOL#xf^xd8%hp*2i;%T}3Yx-Ar*lt36G<+)xaadNpKqMQN|DJ}5V0$}`D0CAm&R zGEN(rq%jr?bDd~LfYKhps~~9Z(we%o#*8D?;D{j{&BbYDrJUasd$yB_<|{hUd?n{M zelTkb#){G&Ydf&EacQqJ&@TW=QbGT}31}N&3CUsp>!$Gn=!qm_xu-B?l=hUjZHyJbNE}psXp#<2vdoco(_6R<9S!M2pVttqxN_%4eMRohK>I#{A zU$plg((gf;yWg&2E)=twqL8^~TPS{NS8*^D2fDNYOjOL=2l5d%z@#sXupz9;QQB+r z(ZCt$(uOk}F>@aYh^?gAdFDR+!B}G$7D{_qlYuqSrHyA;LgqfvL^a+-r7!4H7!FE% zI5UAW-K9-qI6~$=-GnpE0%sP(L1_qV%(jLK55G-Z{V&=a1 z!31A20+jX$)_`D@OIyJpgv@;vCda*Ga^#u&3KNx{>EzqR*bI!XT-rvLww{p)nfq7# zfZhlK@mN}KV$w(L7S=>4?KRQ&VB6`^zIAEa7@L^6?=&HO%W=1v;Dmv+i!q|K$9NEo z`(4^T1}J3i`%QfNOjLT49bz~r?cw|aoTD!7FvAft_oF79!xlKdG8~lla83f}1Y;30 z_Y)>%eLVkeSMdxKPcua!b3YBmP^s5hR#%kv>Usgne==n;bN|yMjj>pmeq3Y(DD4s4 z0Kqkv_P0yB!Z^gt{hBzfAanm4d-jouhG*_q9?W`^v7)rc>ToyF3S8Pf1}bLm1;NQ- z{yo!p0rYN~xnt`t=GM=rpez#BR3meL3RvabArSZ(1d*4ZzB7|%tH_89EO9^9?l@(!e+I$8l=HLs1lfC@;rZIw4@G#B6v2`zDSSbG~RxEz^@*e%oOMg!j zE!Ptw|IYQ~U9Av)3>NfwJfjqX99J z5r}#BNKanw@!-7s1kJm#b&p}{D2uK>-eZ+>7Ya>aLMV$aGzHb1#HuOe+mq0`Cqm@g zpW9KJ4z+1aO~|#US*Xphqc#s}b3EECCMf3FbND!#WzuGO_I%dBD2v{}Ujkx@M_a@o z#2kAGq{Vz;krm7`27|KbFlzy`#-pubFhYL4#>BG9%tDvrbqob%(NQ)7wSDeq;Ic4<-sd3;EHG_;HB;>d}7oXh)d7kW2r{56hpSE*=|4Ogwrn zeS$R#%Az;QIdGlvXs12e?~F^#qtBRdPIJ`X&0zX4`IC{MEIQfWAiLtxE-@@2hrVK> zx@2ad2kljcg0ko+cYt!squpRALjHWqgmS|I)S@b%Vg6bnoRm_EylkpKzWgL!pJe&+6Axyqz}Qe0o$YzBRrYGnFfcJ!t_&C2wMcUmEzY)JHvEPVSj%=bm6B#03ekL+6=X8jC`MF4an4q+$`~sBK zNKIzqV$Q5a8acCU;=s5$LvvSb-BlP4N_#jj0p~@=B4*DoM&{*S49=b}Q37n;FEav^ z_6TZ5T4m6MVzrnUN_%2;QQbPMx67ouA&Qy4Va>kNjI=iblX*of?{N( z=4GN{HXX@FnAfB)j4&T-a+LO(ycuwsL~5}NN6f360OAa3cK%C~*au@ZXILohVZ9El zxJa!f!xA#=I1^P%6P2FPv}QOc?cux)oHrx2b__?zvfnh}w6nl@hvA^KhZ7H+cNvSA zX}@cd7KTknMu5^DK{5yu8G)E{Cq9^0Rr(@>Sv1&WiHqL86af?}xD>vL9Dl=kX6 z9m>;~vY4e$Gf87C7N#FF7y(Lq1PehhKT?|;sm*2_Vx~S{oK}#p&&8hWWTN4}G@1Qi z)K4Vu=f#UN%tuhn+fiwhu zbl@LNRG)|H7zKJcrSmJB2tYH2HUYM7l{EoMdreRsK-GL&6$bR90rVLGss;!@0m7dF zR(UYcOAH95J)qhEs_D}-2K2K4R5JibdoWNP287ZcPy+zfV>I7H>3^9#fwWFN6M(+z zL@;HP_LRL)b~ELRP>xn{5iz3d7L_L{EqvrncSEL((w=e*lzl#}5fhhu`myl^5%)p- z3{FO1livuhXW&51nWT{81R(l)6KfaX-vDUl)0!}V5`h5C0sxv=0K94!;B^4R`Lvb{ z;0~J|XbZ#z0JO9KXl)nZ4FI%d>Q@3gzbzE=NSo_(6Yu;tS?8m)*ZJ>4xxG(&n~7g% zRi8~dzdadf?eNThTg2c~7IlOdnz(>gNw6HI@k+CUckuoX+0Q*xMXF5V;SM#OI8o;SxNQ;E?KMTe2uO9L)JMci_|$Bt1qznFeYKi z>Vt+@T{tXwe|%zBF&B#2KF!ZW#U(2nsvFpn3fW|W#VaXbA z0??PNNlY1~J>{uTp2C!cC2NYP%xA4>Oc|v;<=If4>C>h&abd}t32|e|nvU0-$Z-<1 zWX-V)um}JPeA+w)AS_u60s!V&04%l(umS+feA-e5AS_wS0sxj;0IakNkPm>>OkG&A zRzophZsMK4mUTW#d!7FklsEdc^-Nq?vNrN1YrTlUr^v7E%6|*_Z9Z)alNXk(ZCDsK zlZAmVSz9bHcKmaU<>XV=Zez(h1B}x??Kg%YE?K9+@h#!tOV)4L^Bvg}xMc03^EI~a zv#fJa{?pD8u`U7Y0%H=EtP5y}UF1*<`jmCquHtnlUiE2zF;Q{Jx(e0(Y{~k|L;#xo zvT?kYRuf;wRTBu|+`yw{lCQxYrJ<4c=CF@ZWfWBls#*|UoYls1jR~PF zy3lD<^LJKF;p_X~(Z+v}eh&Jhvp?*p{Ry?ROilRe{;Y-Cc{^%9@9i~ z#ApQ!N%*?n5fe;QU?S32`mh*1$3R(hlu|%>Bt|P4qbEGVSM`sWP)cHtI5KsV(hLP< z(NUfR$`g!3{F?p=ldLdI$})A7MOS|s>Q6Cs@hkeL9;{xGsiQ2q`twk)9HTwM0EDmS zE63#Jo+FbU|9buz6On#;S+;{v9SGH8v??*0lTip?%~y*tmVhcy7mpdIiANt6FR`XU zS@foP1zfdbw3;!R#<;|<(B&tY#s`2;lN66^ z-6;$SWl@k`q#5=nK>AON)|(-TCxre3q^qQr_z9uj*mHyI2|OWmi)NkJy8p|NP!=8O zQy}Fq9^qtA4%*`u#Dh-;^|zxo1Zsm~v^*v#o(LKQ#R7IBD9@x0k^)+FY~4dy)ln9` z>SF*iDn=W@V8oL^qX2M)odg>3V3@HC24&G(n5Td9r5)LUmK&XVdBEcp0xqu zYb?Y!*b)C4;+vSVaH3}u)B@%m-r1X3XQM27XMYRTZ86$bCM=xf*%o7*1B@RK|{ z>`3p0^zIn#J0>lh;Mt9dJ{M!F@C46y76|+PIl|GW;~Zt^^3x!eonfdKTeWVi{>zz% zaASoQb&z7~*-%96KW<$T|4Ax=66db#GL<+-*{WJ>)dUawN!7ztiTs%A)i_7Fd@Yu| ze1&WzS)WDR5OD%py9i@loR+;Sc(S3N)*?1w77cEfV%H;h5y_#N9&F9({ua4kxj_0fP z^5|IQ5Sld$LgtjN+K511Elpe-LdDH*j0juFkDj*5 zB=luAke-jgt*)vgAYp!~>TR#yX%Qh~=oGZ6Nf*8R&-&Ou3SaY?`Z-*$6uvc@fZu;L zCEcW4mzh9I_GtxXI{yFJ)niOc78%E5w1fv z7)sIfkkyaDM1m4SQOL_8pfrhdG$trbfYJddNd`yL{3Om%5pA%Rw82!;22;@nDMYv# z6(%o>AlxF(@oysB0>ViUPK(vvH?&*kzaONXpN2M=O4?v5X@gb)ZP1gT#8DLTvIr=x z;~cLOl-58=0ZO{T(I!8gbI53eb)*fZlQx)+Ht0o!+frfjvIxR&#W~&}!f!#i2ZZ~? zY9AWfZ|8p)q@CXfZ7`j*!F19F?*z0#UxLz}qL7zGKzT3D@h(BZ#Y(F70?H=_M|}P# zoa05)ILINw9jP#RSp?yvI7cTUoCM)dAUrTu%Qdu<^K*l=^9Ks!pmRVQ3??XDC<=L5 z1eEvV94Q3leV}{_lpzMk2l+!dM=i9$dNK}Xk#R5!<6smK?nZ^l%OVK(h;yV8;T{kk z2H^>@+Gs<&Xa49Q?feO7gIQ!8%p&6;J)jLH5tIyyLS7aDrB|FIi=gxZ$|#^rHaI@a zpUgQT&;}bw8_XeXFb8cgl?eBy!sKNUg!{xfJ|@C_AUqzzGh(%AhW3B*rv+)}&p;c@ zA#E^+v_ap1Hkd_FKA|Y&Wf4&P{jmDtw>EzITN}I}{|DA&V9hp|{Mp!lkmw39y%MgeWLgdz^a zPKrqWTNK102mrFdC`cFj$^U^k7l=za-%#w#U&{HKp}jVeF|>$`p+y)&D=Ew{m{Az= z-=e^bMgTC3pbU6H{tuX?fLRx-t>Qdmus?rQ5KsO(wAUgst`?DT9fcDxz5yxRC zMI`?%L@e&u5b-?j)b^Oe;aD3XWzf6nk=sQ&B>%(sLGxq99xCqG%1yqGkW!L*ll%4+ z$4&omCrgK8la<#_?zKHaA~*6&NGJENhbN6*$%wv(*-@zj_>V+s_65a##;`xkO%7R^ z9Ou%%09e31YUOi=`<#l9^gB-)sN_bk4#!C=&nw*XVrb9vR-U)G=k?H@SFJn?xaVCf zlM*hYV~e@Oj^$1H7);N zXwPTO8kMYqy~Kl63mvSAm1iC9Su?b!X5|?HPrWhgS(!BC!QDY7{8)?TCXK92T5yx* z59qa~E*x|{K4LdDH->Uk+M|uFLchU7w;}GKj#-D}^&oFPoKm=V=OB}o#=+Zzn{+pK z=Lc3^y|`CKD6CdS^ghgvP9=W)NAHimL2=^@`%k$^ww1{cE7hNRS$Qtto^!2CzT_s0txWP^qPO;{kc09yTJaTD z?pwIRSLSiCF?5aATLs(2gY69M`K?)Fn^mwwJlOuw!S-2s{>nX%hW0#c<@q~2^~OA5 zWpb7WKOJPkkF|^3X>yn<_CH6BXfYqn22&c;#3lE9K6H0$zYFZDj8_yHHLeQ^n{p7IvUX@FgrSx ze2)L<{V^#hZh~PygPTmVGMUe%=KxrkN@iL4EaN^)JRzr&MOL2cxaXSCo~x`pw{Xv| zLVIqs^4!5aw^^C&;U?c(nfwS7y|oW`LQN%|=)n8I%KZda_|-fvehyuuBUZuw1z%RF>t;vW0~ha9sG$1_3R{K$MR(x~1ukz(~a8wYO{ZlXq- zrV`o8>t*isVq^%cR3myVW=E%zdiak%xa$PPO*8D>+@yh(iH}Q10$7+zyjDKVxlfbG zpsA!QZNXS8&(_>CF0^M$E6;bh=bNED+gW*bWGM!dD z#mc=mSI9Dti;U1U>S+}$n+N-EXwSZ8jXqYv2J>Kfp@a3e@*K@QM}+nqX5~2no_b@B zvoiUd2cHyV!jH8X++>=S$s%qt{{g)=mmGAatfUw1(b-m^SM$&-td3cSV_A?lKQhbv zjH%>FpOn}+HQ>x>4%L0kCv_Ee_s4E}+&=?Xz40pgq;6fMyyC{$ojk)t<yWziOhNpZZm?@~gxBYKHRDto$OlUp*_6hTOz$WfBV$y+M3FDJ?5ApuYNa z)F{YvhS5&1a?fU=J)2m0w&tF3p*>q#dA`Xj)HcY3ci($FczZNwH>rOy^e{Q!t~wlV zTRC;+PKj_zOX$`uU`#Ed{nydT_e0K<89W-7QO_R1qj9Ctgr9KPK0(n}8z!If=-J}v z*g#|Zt^9^^zd@qk66%*{vF=waTAaf<=VRROQ7elYhZPAB`2FL(YxmgFJsS+DYb~l|y?z zW93F8=M}0RWWt-}6&}16no}H&HLRRG+$jQ1L8I{~?Z0|fzI!>-u4pmo z|J7)!AGyhaXj9VvgO%4W-0Mhmh@}6t5&bu2M;HG;@E^TDe-DcLhhcx7o1C>W`I}2$ z2C$IyU$pYM!+mZ>2POT-X$xMr@(hbHjsQnYNY4T*&(hrUkPVbMU~Jsa#{te%Y)Sp?OD^Tp;-lM$b-2< z2aB-sY|K5QLwiP9dAw+u4j$67mX(%Q--o||-dK(Dc`~Gm%8!snDTrh4K zCPR7jK{3KYQ$S z7!z_~n;+!qz;B*uQ?BBk%R_s9Y2~?rd#(-bxyH(KGq2F5AQRqwJ9zMIXijlq+iK;s zk2~##Q_#W|h8jB@-&y%a#Of_b8^w+PkTZAmKVJN&xTAP6U+i<(S-e;@Ey>PNIq<1OkupmbYZ%)pB`rQNEh{yX?8olR$XMyI;`sGYQv@r9AaN|%Yoshj zesI(np%S{|M?w4ptp4?QOstgoQIBL}S(2noBHS!if<|{@?a+Th^e@t*M4}C?N%3Os z7$<(CP-x74Z$yoYQSB$Y~k>Zx-VTK2oJ^{=S>5%p>pe}8sr7=B6^pYdeN}7TyhHE$bvv|9?v|X8k=!Az)B7Fb zdL*Z2WOQqh(kb9&jUGvzq`$6IluABT`VaYJs&Db*8g#@p8`0ten!9OJ6O0t+Zdxl?TbAQHsKIzk<#j#kI2ZVx=vlMZcsO>o7HdBZ`GaZE_ILkgL**yQ9Y{usvcKQs(+~GP@ik+ zO|?Mn?;POFa}IWnbdGk8b&hw=bk23ocP?-)cCK`;a^^eNJOAY$o*%L2C+s!e$cQF?3$$83sd7x4t4^sRX7yXnWieDaz=P)H3qa;Teq2wwfl}|BV`YWTA0m>L9 zPZ^6bG)@_$dUeI zD2wH}@R|p&`S4l*uZ8eh1h2))IC+WknY>gPFMp{_ke4YF<>iR90+CiC(ket+jYw+{ zDIby6Dsz=}c&=Br$QuxGBO-1>#IF$XYed|Ph+C8;%2s8m@{RJPvQ1g0Y*&^m-y-4; zMBIsp-y!1nh`0+8cO&8+MBIyr`;;8{2R!#H8}tMhPNFU67lC64XO${_WMG8o6~5FE8baoi5Wkvv>oj-!2r zI#S*29Hnk?j#h^>7^C*Xv7e2jKL^MEM$7=4JrmTC-ihjWo=NKWp2_Mi&lGiTwa?Xg z)uyWRt4&jfy1r0{xu&bbT{G0(o|)<%&n$JXXSTYm+8lMCXRdlZVxD>-usO@!Mjb}6~0}a z=>1lmph_! z4*yM^=RK*;_x`RP2|uMC4L_~^9R7#8zHQW|7Tb(nlx9WLKdN62^8 zk@7utlzd+uEf=U4WWRHa+|M~y&UTKIbDW>axz6$Or_Kp-f9D=$fODjr=iDX_bl#E& zIqzU~xvLDpbEtEYJj^*+9`2kXk8p04M>;pjqwxM{=RIW%o@1S-1t>?}~0;JMVfK>pIXP+sO-BrkU^mRC6M$Sa)_ zzy|uHaM5d8}WW6se->_1xb1$ihOddk&?8! zXPBd)K$40}QJs~VZTUJ8#Ii7DM)=-h?w zD~4@xM>a7P9@M5wH@dGlw#6Nn%L@kh54A~2rMpRXQQT2G*hIHU?oIcXpf&@$2OH5i z86VNz_;noORCqC@4e|`~D2Zor$8k~!55iEhPQCi|B4qxkUC-re(4cO;hz5KYeNnqs zt@`!r%knF))NW9R?&jyeF|;J zD`JNx)yQy7>6V=CR*`qUmY&unJ)yhY1bZ^%7kfw4uil|$N@99iMq1}gSn=0_dgi0RNaEv;Kdhn8*dvUc4XbsE&DBni=_YBN|M$E%O;2z;B&L7VBQp*0=`%h#J-tSv zq$Qv4XJN>54;oC1y8&g*Qt)AHExDiEn_9E=|_^*BqcMh)B8=b zQemaPj!no+!0WXC!(^O%iYJW7(GfZ6|1ff4#!u6Ht!c(9bsE%c1zN=fL_GAk2< zt5)Enc1(=)WRuEwo~rAZ7>$0YgV9^=8UN~@(kB?p72kLaGgZZx$b41NUjl!xgz{y& z4cGTQO!t*-?fRcEvu zFBk9CrPP1UChsqM^yz<09`aZ$<5=?e?mcCDwAfzBH{p#5%oLj;_uf{hz*{|b*%(z_9eh&^5OdB2nt?V}9{k$A&7rcK+{&095v)mq&uY;6>e z+@e{$ex5J8B!Q9q^I&rfvBPQ!@|{yslj3nm^(W`(VD=)+juW#3LM#mH%#3)956Or( z4TdL(VM!q#PWr{CW|1EiusT(S-EYM1b0Hu)EG?a@j)&1nV$@0qmXVg8$pvND{0^H^ z($$7&H`3z#*Eo{@6yC)n>?t8YQgU(+YQ=G)VTbFIAxd8lqV!5jNs8xx(kA(9urSSp zFzBQB#O^)f*2O2c!Hgr#48sD!!yLNp*7-xzQ^g_gvbG<5ZcsdOOXHz0aHPC>kLG~SBBkwb>7K4{`& zefU|4uj~-FZCHlb0#}^@sq~04(xd2yIV4A6=o|U5P%459*Ehq^$1Uk(B!X zHey^X9OvD8(6J}^ujy}w%@%4zMlf&W;V`*QDUYMKc&D;9G*oV~K!=4uscA{cm}5d6 z?6+yi<-Qx+36O(TJWw%StK zCHm?UpM+!&9T?CnONBZo;p{3oXU%43QsaJ9V0kE3UZr9<6HLXf7-KSE(k!mO8TN!w z5p)urLio6>1+84F6+?!<(OGO629*y^Lz`+)b95zF! zKh`H+`MwA+5COuJ5K`RA2`gOhN(#dt;~LBuU|Fg91a8bVWQ+}_G^GPu(x_cPzq6^U zl=M(&LtcZ@Mx(zQVlE75e{x+eJi>kzYf28~tc-*%RtNMjQmO5tPgeJMe1p{;Nld^x zGMrZHoe&V@6BnD9IP92!gE+n!4r4a6lPiGXQA%pdXMn;CCKjzn-@MAlIodd&j>g*e zs?Z5ZS%njU7a>NHDlHJI#FhkOz>k8}C|aLKLbZN?qS2})1jWGdQx364BNjf$OHZ`- z`$-M{pFRGkYrVC0;ldA}fstO&72~(`!|rw1?9JIH`=KgbOUVkiWk?VM%r6Vqz%miG7Uf_GZ<6#HC;AO(C`IjrN{I`W^Mh1<8gOw~Os# zSMk44?8_8m0u}pODEjRx_J?AwOUq`W3TakygW4BJJ#+a8%Qoo?BWwU`a+LO(d>C+s zxU@kGr>cQdjo=Ic#O2Zu9!8rTH#HdaU@Tl1fDU|=_OLz!)>xM|nqk#*>61WpLN(Sz zHQGd_PYbx(0L4LR4`(WHrnt08496XaGsT26$pQzLFrYXn?cvM<&J4y9W%Ss~q-|!H zq=jKKn-QS2N3Z|{^B6%xfneT)2^KN}l=cXggWyY-wuC`E!4BTqq!qrzv;z#MRv^wH6V3q(99$TKwhl^rIKKktXU5VhaC!RKq^ytU zV|Eo!Lh%Gse4W*vrd}tY7%KJpoz)eky}F)(@@c00DjBCF*J((`>1mTR#$sXmah4IF zv`6q42rj#{i!SXv<9N#8h#?%8#c2gMLb!-M+sQ=p6`g3llJn0$m=%{Ip(6vOJ=VKm zz3tL&GSFrKC8?nQ-vsn_aB`S`(==WHJ&|N^Wb4LtOehx0B4Ld;GWRFkO|-|{Au{*J z+_>Ev$>4%A_cCr>8Kpht3Q#WZ*2*$*F>^2PHZu3JCJr!drKv2o?xz_JN_#lZ0;dvV z5i|En?!4UHWXzzuaINZ*GD)WQPy%e-l^Fp_djyKxDswLsQ<)e_dty~l-4|GOh0Og0 zwD%s;??IV+HM@#0L$Nwj6f*bf7K-6^73)B;mRqaAM8(X#79U|XO!~qIdxbSQN_$Q2 z22O-qtIu%6%sm1STS>F?%)S1Du{;b5r9G?|VENoyBZehp?miP$BNLUrpvN*Cl=g65 z1x|Cf)|BB0nR{~+PE!k<77PcaJ)GBp6USJ@%stK|EexC1i~yxQf;U0XjuD8Nd%Fh{ zyu}Dm+9QYu!Mkp)J%bQ3_jfTl?j@5W&)nOasPs&yqg{*?V03Y7$!;x?kqDW47k)q| zgFrl%5=~6{sC}O`5lVYalmWJ$ZY|BNb!Tj1=HAnUl*Vzpo8W|jl*t%T+GG3=7(aGv zy&0g8xqocp>usXao2)OxL1_;s7dY8&&ChUz%stzLN*C>qnNUoxsNhQV=NY?A7dE-N_zyKgJ7~- zo9NcYGY&CxpDa!*$lNDl&ptBI@XUSugIT9CR+RQw=Yn;%Tbs#1#ms$naB`SG(==WH zy_;t4*t+L2ER;pUnrdY3>w&eFF$w3~*8<=GNhN|Z_YF)Lr9I^>Q2yGjZDQhL=KeLG z*EX3s=$TXZRtAF79>@-WY-bc=&b}Spa+r*kz?}UE&DpVa?_>lh?Gfy@%-IXY_AoJ& z_Qdw1y8Bplg`9mKTKWj-@t~ajfL+C(pm>NW3OV~B3&q2B6^}vj7q@nliHbS)|o4>NfoH-FTFyVm0tO}RLq z{;-Ke&te|43s3<7lHWbk#vn>senXs69=keLAznMXwy>Pu@`o#gtqC<=T#4tu6 z=H0{46~}|~?h`cc#@3DN7E^VUMOPo|u{uv)C^U`&@9&I`k6!Ywvd>lc%iw?6IFe^RUat0&h*DFmd%growImQL6DGJJ>qih1o z29LImp$NJ41{2CU3lv-do1&mBI?6Xd*}^!)yn2gSR-a;U{cNg>vgo?sL3an!6?5tx zR=T(-H`PU1blv^X-RIHvFliy5-iOKUHt$e7kJPF$EFr_LZlbDYqS7;( zaE61@9?mPksU4}+WH>^WUE73H(*mb1!$D~e#|4}Qj77|}8mBilOzA7NsNg~&t{t0#dsYUagkcfNbOZd zBIMz5{D5u=0`XXS)x@Na+SaUzP}*yv_F#KEQhPH}Ysc8cT>Nbl(wiK&oe54DNF5j> zN_&h+VC)pBb!31-R^G|P*U?0!H(4^nL1_=C8*tu_)VeYpAv1s9gwxdmr#r(zX%8nI zI6WAPke&B1DeL1IcWbey_#qUtn4*xOXF)Mk>eZXo6{S7p|3LX;rYvUZADg5x77No4 z+)#$Dg(&S2^anw1q?R42`5A|psppE*3i9=A?72=R8vaWY|AScvFjkcISVw?$Sfn?u;An{e~4+k0Qw@$+_80!WLPNwDb~;^WbWS>nfrO%75rS3b~;MWS!YDyxBfTr z)AditPuI^y<>lrm5WYiy9eqd6KaD;8$)4ME&u#j9={$w}r6acP3sHK{qO^zgH?XcS zrrA;YA0Lh&NLQkW5{45X@yCZZjXyrTYFF_#6mLdp*O}-7(h%fN0Y?+nn@}C2Krg3s z{&f=pXvWYcz}9_-H33R{O;F6&M3a2leFn7D0Q!sokp}k@Ap9BN{RaaT_vw9t(jL&G z0D9P`J>=7e%1Qy~;Q*kA=x7M+BcX*#F(8!ofXV>qaYplbl>SGF6G-bkZUWF(9o!v> zPCO{>DL)0}a!h$Ul%rM2|2a`ECn`@;@Hf$T(_MinqqL{|ER-wxw2DmpFgrHBAmWuE zeg-Eau*t88*E7g*GD#uF2|)Dqrm|fCCjbF#w>d1;ER80crw3W9mBtJ70rhz}&<;zZUC!l=eEmK9uYFv^q?D53BlY()o4C zKx>C*ejO2mPmvAm%11)p>(g9Jel3%qPvpJ$u; zK}*(~b`{@+Vtb$VHWL+>toBgdz?Q7HO$4CXK$`$t_j{}fP}*yPWB?`lv;+nuE?J3y zSi+X9ga-q4W7R$K1^I#vid^YShD)y^(Jzh1T9&9y8!(G zkn7X38Gx{4CfSl=eD*0+c`VX=9nVuw;G4m#ncO24Au!+LiwT@>6}U$Q1! zU`+q#7_X4;M|K-a*4Mz;-~UDDLuU-!V~f$=U_g{cOql&O`v3{j>?Nb?;?O zfYM$Q{0N|fK5ah(5|^xlfcS3nSyTHVS zCF>HzjV0>>UjIanlb|IF_kFYna1#L6ecDw9AS_we0|2gC0Nk<*Pym2?KJ5+z5SFZa z0RVR_0HkP}Ef5xsZ&GoI(I@e9Okv3?7A?$8yz@&$>%$JEy|ym}C8vyFrj ztv)15|0X%k(f1X6%jwXM?g8 zh1_JGmB|X2=&k*wE7Z*`>!QsajwM#^8@a+d^SH$ac?_Oo3l{ytaeVjdUC zp=*?A6)ckn>lxZJ&8*SgDp+40?BmeEdRuvZ%006~d-|un?Y9%e_Uk^}gU-XHsd;=W_pALb^9tW1t`>0g4UlA~5WXSmO) z;4xI3W+f-BJg;!ii=jQwTY28%p4UTrUbXTp;GTD_OiFl+HKLeDTqAf>J_ZxLwIB6_ zno8Q!f%mYL`_o*ZyvMx6c!DNmy%oz?1ygvi=R$ivYu2b_73?J*tXk+`RjfSgaL<~d zJvA%O2zcs^S$N#sCir*4qc-kt%9B5!A^ztJZaWAVHNBO4|Xwh zu=7@)x47r^(4JSVJPY8dH|AX{lQ6F_yF0w%?9Pw1N4UvDRwm`RNf~db1wik$$GxGZ zl0@30rL96&=AkPQ_u#379J3Bb#UO8fWZrCORPS0tv3i}2gSUX2+-+!DeQsNMm54L~ z7mEymm1;zPl-bd#IWlNH?Mhql zIV;a_?pZywXEiI&y44gCX$BL$wHrr<8kFg@;xSh4t+_%R znmLKwm8w z8AtrNC@HaXYQSCKbExj=D5|t|->TuMta%#k#yl_fOAUEm@GumMh?LU{5?`xc?r7vhSE~B2!eL) z(N`NL@A2sE#nG{W#(vw%uQT^c6#bS^zXU74RPOgdD8CddzfA7e)5_!{Zqm!j#19jF zH1-WWGWrC0ZZg_w0Qbxd?U`-mIgEP_4(&P6%5yZY(1;)t-hC5!@Xyek;%FRe{SwOWsFmMo?swA4(U`nCPSNQs|L!A;|M5qn&PX&+DN* zuUdIZ(T3)|(4Kd!JWIgS;dsp9a1@Icmki#0rFrm2qJu|cNh_!F-04X;1&zj|wErHr z@}0n#u=bY5{lJRT`%jiif9k1o7h3kau=TH~{1NqP7k__tY8ZYv^grK`wsGvMTJz@g zPSdS%-@b$l+-tbg`yC4JksR=n-Y)sCD;1@ZPn8^?3|0mzH!h`&l+358Yi8f^2iU5o8Hs<=+x0Nst)Zo>8}Y`?~KGqzhO%@+9^Fm1zjJGS3q zy93*u*nWrY_t@^jcDFoH-h)?r{SEJ(#CyNP>J+R_!|D%Moq^R^Se=8_pRhU)s|&EY2&+r5 zx(ur;u=)#Df5Yl3tggZ8I;?KM>L#pi!Rj`w?#LtMyRf_m%loh_fTdr#F85Pz$l1zG zIY+rA=PI}5PnA1zf8{RvNpD+81jst zW92ib=ULSA9P0Te>Ukb^7nE)CMP-tFNtrBPR;I{Tluhzq${idJ_mr!6UQ^*-^7jy#{sb z$^22fp3Bt$dm$+;`Z*|0NAPWi{Qd0juQ{Rb?xWBygtiuah zE}V2|m0GpU=2w^CuJol#O60w2izNxm34H{%H`zg2J3P1VuLZ;+;)0k=p-^D3>`eltY0|P4ihu}Gt%VjSloq-mxE5Nm zEP@Dvh^VL_hzlx+QE`PAMHUrt!womwL0nJ}`G4=7GdH=JOkd6Xp68E`bCbzE=li+m zZYPs8V^NR#fxUVZ9oFL^b3FuEW5cziw79~fV#gd>Q9hxfaEdbrXDXfTXQcN`%^zGc zuA;oMe0-I2WJzUpVX1R?RdrEGd4AWlF7AAP`IITuWhGTJ^GEvgN0gVBR^|^Lj)z^k zckbG&b60nlE@}B=OUm;5mseJeO7F>c*>PPv7nPQ(P8JBQYUb49qLNZY8~@LD?DDC_ zWtEks`4RV!A2+u1I7KTeuT-=vN)+vKr8^Fz6m4qJ*ovumC2s=$$BTJmyDD0Ce>@r- zP_%wC6)mTvDsSwhoa!>v(jNzKhhID{|3Azka9{TVAR@Pbp%nWofXB%e333D&9e zI5YsAkbJ(B*9TVZrrN!hs4>LO%V)P~WJjPgI&Y zwk(>qq|<_D#vg2X@{!-#ySgW3+gH#B33s1%a7{v=OR9Eu9sb*Z@0ah4OWNDVb_39> z-1m`rgzo$_YBO4Q!Wj(?c2A&pIMOR&Ko?S|ImRsnOOt!`nJi*?c2tmGZhbp^zGKS zN2W6SbS1%Y=6!8(!&uzl*rCKJBZO&gX3l`X;K6|*S(!PwLwnyIeckvU_LY5ml4T;Z zOe4!t!ZK@MX4cTW0oeny2WD0j7Z$;205dG=o5qULY8(fK`|B|tbpk{5I)?M}ne%Ss ze00cpAakI9Xx`w!KXYw(YtFoNCvR7Vyba3C>F3Y&jlhv5AuFh z$a{9?ph1KB4<4N7`-k2Q+;f=2p5*Xq;c!Ui(CncDv$6;0WlpWGsw7w`mWGEW%tJ5o zFjjcT@?{S4_w(oZbFwlg6blzoI>m6*j5$gtM@8X|@_hY=4)Oa3WR9zYehB%*(>fhvxM24e-OB2l5}; zPZjolw0~%>FE6KGZYEaEzCFg_!su8m{rU{6E}L9dehs3@G6Eh`eSFgtR#{BEJSIs8 zTK?;$HCn3B%u#;P-s>*=?}_BoTaDhb_FyMZ(`WlCSbz$OipN$@C@}bxIgZm<)>_jK z@~`1mEZXfuPkPl%kl96+ag379byrJ1ch7Zpz2;JfRSv})TRCZ_K&hFWx3jDs@+$^7eP=WYV1-Dhy zT_t=j-NIeJ7Bl+{)>5TrJsiCOfP{Gxha0^YlvT6qb_g~2&_Nwvv$CMHybz*sdatj7zjwL6k3xend)Tmo;Uk6(7}BpG;KK(H zO3j<7hJT4lGY^7e2;=WEFdWTMN>t7WIWsEj4&iIQ?ki!H)XZy(D?&qz_4s?7>T0il z*yy1n@(PAs&cyIOlw<5L&xt8hc`sl_8w29m@CfBK)xtbdYloO%JOQ20YdP zt`mbi+N&R<`wAjPfoNKh;iE-pHj3bnr*`j=TEvEkn9hqpd5BXsVloCOMb`*m2|04$ z&$no8#5gZ2FDk}z8Er}Wp1VBYi@-)-?1vy9H3=DP?HHUrqJLfh=R1C&C{(^=3eKl;L`G)t0>uYq$gu5iyQ_H7{^@mO5AGzlWjGe;DiEJ0Z2!ion zWSpMKcd*K`sTIh=$MbH^#OtSn`zM$tERwxfS56c|fvx6;S)GrijzF4IQBsVnRmLK{ z4E2t%dY4JQrWcl0hbrN6it;mOeK{*^BLd2&I%=X4pTXV}PbsdNSYCvd;3bM~qLM2j zhvCXDQP4c4X_%-qH?Jw?L78x~1ju$Tsj){n-vFUCd<3>iU?>LRFMNCG+1*&?-{&Kx z67eXTP*8+x1UfbimIR-kKJWxx2xTDhzi^>JUOf%L4jN`$t&gZgWtv~_%EN~G&d3ET zY}K4W5%@`;kuw2RFdMEbbsP zy&7|&XLn<}PPi_LxUfrx-E7z;ER||im+70Tu@1AzQp??scZaR_Mtj2sqge2-j$To; zsm|zzEm3xmupYUYVu&wuL@smHm4y?m7P~pDQHSMtRZl6vo5?Aa(%yaxZ`P(L5MeV> zz&;tOUkpjzxqL3o&E%dDsHN zR}RXL6V^zbR#Y8YJbOcOE^k>=zND9wjb|6+Fv{jpJoiblp?%j_^lpdwd~QB2S~rHF z8{JbNp@a|3=J2%uzHl*H!9@@y{!HvKW77x4AS!t^RsILBOp*^wt>IA6xjGu?>uQ*mC!*l-%};Sex-gXv`NFP(@+D!|VgQ&YqG;Q!mdyo+lR&T}ex z&YHiKylzddOu`$hR*mA@)@)=*Og#8%Cay%c7|5CQ5=V;HR>wnojEM5QE zw$m`6g3qPn_p{iq7tiLu?Kj(rA5ZgDDV`V7^}p;!8TR+aF(_|?@+;}uOC)|-I{n69 zB2#}Q-S{czmrNXBI?|Z^<{plo?SzBU9?nkSyhbbqj0LxNtT~6Vyp~>HcNhDa%EkO= z7WLcGujD@#j-%%dB0y=6U~fA8Sa_i!-x~6{><0~m*qbDV(w^8mXztt8+;QppZ#ueI zYu`q^SF(POxW(muyNVw`@jX&p6|VT6h2n>H6+eUGC+XTpBzm1O!rHKQej-NLM<#t~ zgdL=iqqG&?z9lS__ON~i*5P#RN5Wb}i$E%) zI&7l)(L|*$3r7hDr9GTKfpaWf`;BmxhT|MF;rwQSbDVHc+QT^ooRh?Im(gP#S!_<4 zq@`h_xb<}sr9Fbv+&NmjTVJ7f&3tjh4KV*>qSAltvZ-B+mcVG?)|$Juvx#In4UTk1(!ypRC>rd5)MjxI9-90=GHnB&b)A(G!sr|3!H9*gVG*OI&gXt%ewIGsi#R4 z80gmeyR{tRC^tC#jANj@tl-DO`{T?Gw$Qx97aH6WGpAwJ!NiKv9_vW3j&N(k2=sn{ zvQ)5UAOjr%EGan*4l|7xK;OlGEF4GA<%ESYCagP+%)JCy6NpL5+$R8FH_PB6GWSWO zjMAR+R4A9ZwNet7GxsvFu9ccNz_g90vN(FC5e`awIMabsMJ#gWUWLxt!^RA{3%`S_ zXYPAB0gj$)hybNMg6rH?nR`g=dJ;ovPpk&by^)$LW$rg3-g{ZUM`Z4^>?+<2#adF7 zGWS{w#W{8r7eH~ITdOBgIdh*UMp(T`Um9VzQpi!-3;9yu-0s$HBOEz%za0?USlAb` zL55@SwuZ6rYf}6dyHMK0S_Q0?Zfyl&Ntydf6V(b6mA;|hLpUhy;j97918!|K;YgYL z116l+7C37O2c4nVZR+RSI`V*9YAZ0mo|G^}Uu^37}4if=Ndjx-g;CHw7t6Mut z9CGIVyS%I*bN>}*-eL=l$lQ-M%=#y>qO`{v=gH9&kM=i#%9*?3iAWBEf1Ab&p!e|1 z9Y;^RN1x6pW5T-E$lT8b);XRi*WAzX)YrblQi+Jny(KB5w5NO#lrQvX=aaacxnJlp zE})!m=Fo2?+?qg8+5<@jh>IxXoZW?P`GAd<@SOcap0nfV!EgTYH5H{jg7zM(oINCl zUk~JBDD8=9Xl_Spu9UNPM5I4tJsy#><2MNHDRzZo8YxOSdzyt}H@k{%DE9JbJxEl} z*?Wnx)x)HZPjYZ?Cy$4MjnZDzeE{j}(fSaGoUQkTynI9NK2|_k1ccHa&_Dq7_h>l; zB<1P-O*}bf9{$1GAi_au4`&!~hI+Iigd^qYLrpkCEO3Ss4oZ7CqkuD#SmZo?q*+=Y zDx*mor9JJdpq)?Ja)zF7rCmVUDD7#Fhjx)i8%y$1ZeD~%@PHGSEO0%2tcgU=VkX!H zm_m6wSrTM7bs&P*~f=_w|Dmy<7;DD4I3TCmOVXwyAf6|u=#`3w`% zbb(uChSP`5bwr2K9$hWyW_h%m2u;ezXPL-uGV|~WT}L=5?cvM^&Rman3*kul_*@gt zEfzQn2nVG-oW;OdL@ZK1zR0Akk7WFesXfJIP+UriQa-*EiqR6P<0-M{HTa)$@BB=37gA zDDCk*4!%b{+6ID?bMQwalfB>u(-=W2_yNzsarA5?ER_EiD;wW?xr%@1v} z-|nri`z$i=KFITK96fiCI?CA9S9q;*?vT)3B!n_{p?lEGyQ!H{zI`{MdoW7AeXkw0 z2cWi^)TCT{wT0S)cGMn*+B&bcmIUQIdz~0ZYfajeXK$bYql`VkPXc12S9^>g+f--iLSAp`fS9_6Aq}=*t z6UvJgDBB1HW$Y-g17!zs$a(b+v#h?v>?B>3vFq-I?rzeRbL!nzx^I#$%Gh<^gYJH> zwvVKxe0o0?x6dh`-e;oFvyk`gh#!Rbr(W%2uXcd+rCj<`F)crax;!@yn0WMD`f~~j z%GiVQJ-EL0YKOeqSHvaf(chYI4hht+%wYO3!Eey=NsBUevR^@V)T5;(Oar zI|FK`k(!h@p9ZyPiBO~7de5Vby^W2bdM2sLIrEt&S>(*2)SwBeql{hsT&SPZTTAM# zH6sQ&Up}WdEfvU@lkoTp%9oop%+`|FP{z*Y1Y7IgS}OvRbLG~6krK3EE7O=juKXF# zm2vdA2nprCMcUg3-x2>yq3?*d&dAYPWkkuBTV>SOejO!WzBof4CMfMGw}oi38*28=kx3=t&_Ql=g5s0w$qrUE^$n5zrC&1Cui3m{IBS_1z z%AiAH_#I`wJfpNH)&tG$M$MJ7=x&Jj;V4;jPrHg9D5jI5lu4&sD0=NG`k>f1L+eAL zayH#pjIcf?eQAVcQOHr+3;6)x^vlq)2}jPW`vKw`7IyJXlkA4E1`-xZdsxGOH8evT zLReCUJ=8=s#6+cMG{Xr8r9GT0fHNvX8%a1)mOaXZGtvTQ4B?=(hjTS>t|AsW)4s|i zEe)GOB0y=6U_1zlh(OM{iy9`FKm;i55tMTic*GtHx#3#UiVU4QQB+k15jQ~ z%5s*z+9Zv!7)n1LBm$K72p$E&h74_ehV~F~$eH>Ed09cez8+_OXA6z^rpZGMvpzPfH=7_YI)s45&RIYUozyDGdX4Bp{Ub zfVu)G&8KxHppPY>v@oE~4Fh!}Ae8oi(gD4I#;wk;kTJv(SzuRwJmiaf zS|Q1QPVx^k`66r#kFt&7As5zV9D{`x7!zW|*lTQA*8rp1r%fXadCRH>$CHdhY+2KA zW-~hzzGZFU>oty^8Pqu_W9l4%btAB@Cnjmjx*mbp!lq)xmUWX|#ham6>(geDsJvy> zLUk)`S+h(8pxMepfFr&Zqc4jn?SmFHI ztXiu{8KphthoHR1r#(R8(w4Ob;>MQs03N@{=E+L7gy5K~zeQSS7vM1fJmS+HCID&6 zdL#_sVGDrA?E-8Dz*9c$2?CI|tf#^Np0EIT+AhGe0Cst?J>5jZ-H^hr+q;f@|JZ79Ir7Bv1NUMGjFgn;ak>jzFy<#`HngV<-hG58S4nJ zej+Am%lZj{*v+P5#Fq85UBzQi{LQERLZb4P^&3?8(U$d#i2yYFcnEOx{6Qf=X)gq) z0Cdu)ogg52%Q^{&?X+c`Xc$Pz(kBc`dq8Jo;S<*^EgrvHdNzK2N#3$f%L)O-l$(*Vv}HAumBp&noRm@8Q$8QcEwi*1 zBra`PEg^1fSuODReKt=bwyX>60yqKCI!kLs0MeG#It-wd1%S&gKsx}m&C-$yK-#j} zh5;m70JOIY&6fFsPj?U>-=s|?vkZlLgLbv)g{Y#mvxDZA-1gU zcICa0cV}rmNnYBr+*$b6Kie3@metb&qxZkZ2;l3l$^7fDZvtTt=}SKxu?K3Ou<;)8 z=VxzG>{0&P*oRc#gX;b)Z668CALZ}QGCs=RXJP=)XMAVC(epl`po|^mW1t)$4*6sJ z1L%RTSr07c7eMtNj5x&AarAsb>L_DZ|2)g;Bm9ui7bJu-cA-OP=2z5A>Erva5aUCv zpCkV0>>E33KS1p}Qj}f2K<(!&?Jx<-AKU*dM$=)Fwltc4r7)w6J6`D6NKCRu5iG$(bG zv8$g4^>ayG{)qnEhSkp}b(FEIJE7j%ueBlo>Erp<{`$J_*rF#so^NF$(%-AQ>>zXi zLVLfK;@8>`h4j&Ud%v*-q(EJsGi^*f`Uvevp+OmYXu5-|t6xj=Yn_Qp{#d@N2`5dU zb~b@Y1E&Y^p^Tlc5BR)(%}sF9NAg}1o7+UBhbn_mP{xju4HUm$^AU>lalGGz; zArzFcqYMJd0OF87iXUK7)yHnG9kroQ8$xQ*$M8d-7AJj2>^bki$IGThFL~1C}W3N z1(=n7Z3V%|7l2lV!K`Q)<{pAU89U4afLTo>(#4!s%uGAy704B zRu%94*OMyB*i|2g>Z5*b0|`qPeIA9danWZ39?w!S3L`H1Y_uc(G{iUgwI@kjy5O@Z zO#Dd;@hx`5w?h0mzZN8M>0-}wVd6mx@fYlfzXI`>NLjkj^Agm;)*aE=uTp2DjJ>m8 zhw2W$ww;8fi#$90#zmg(GJ?3sv(t|BTae!C*LIP#bb)6t7Wz7jth4eS?>uMiU(Za{nlo5Ih zgZ==#v!(?z5rrd-_2xk?)sxKxI;394ijEYdD6W-ub84Sd)7JW)Pb+@07LoM5Pi8Ok10Mm5|#&*cFnl_REEA^wj5{$rBS z4U?pTB+t=R4|ccIE7-H{VeN{*h#u@Q%&Lb~OXSd4`;Ix-S2o;4PdNqAF zb*YOoi~mQ+Q;PnVY>qD5FSVG-_Lp1B*I>-pq?Gah%g+Ga&%o3P%+DYzKNJ6#pIqI~ z;M5Z4XNZ-bN&m}Fp6+L8>SX5UQY$~D|I5!X-OupUDa_9ZD?erb%g<%HpOLBM%+KYr zAHMmqB{gO0|MD|R_cMA#y#631B`44ui!0o+W!%vR`wM#z*9RK_dl26TixYd0&<7KT zJvgloMmBqJdLN86_Mm1qw#q&j0sKiVdxCD{PwLnc#E?I^nLR zr~Ht%6}y{K6TlNLr{Md6w3lPce;GRoJLX;neC*LUC9Zty&hhd$&fGz%-1*p`kEIiM zbCINY`Y^e1{EI2#|!BfD-K5!hr{t)x>7kAcUM!`Enacs_(qU# z5_fvMW4oyGO1e@~#O^AKIti##<#4=YW%Y)zdM#aH_aiH;zzy#b4DS~h-ruBpTxvg_ zD4gc)2)`E^^*q1s->fVZx6x}St*V?Zs>HkHjuoM7iYj`v6WxlqFcQ-3RV70> z_eN9^bImWRWLi}jEUFA_px64lG3lnxq?;ETL%ARC(Htw+mkZY;n0d50>u?N-cG zdLDqKrKH}<<_=+Vd*m2mw^MXDZnLtyM_8_mZn?tBa;>m@AiCvhE6YcO<$9|sPl_s! zTUB`$RrF|Yi8?5U@`i7=GT$Z?UN(=57o)dmtCh1o!r2?qEnhcl?67k7o^bX~bZ2i{ zS$--kKZ9kW(o)jH$|g(L^z}sSr|~>1>0@O%NLcodZkc0c zIb2u{jcz%_%5t=@9BEahKvc=Msxkpp^k^4(qGcsx_|O?^Wj;+Pl$pmxY4jFNvT}Bv za5f{l<#e+~m6fwP;cQlPXE#|{E)bS;qg&o$WqCU+^2&~>mXftrHcttg zjozqB$zxWQ&kM_7bjvMPmfM8o%h4@gw6feOEO%H{c~ex`ZB^xcRMDfo-y3Zy8OsOW zJ}dLjg~F%iaq)5V79Fs1_JeTtZFI{+W{t0`oc$)89gXhnh?V6@VR<~d%9&PGT8b*?^tSG`q~6h%l5xC8n_0Pb3D>QedE^@$ zHfJ4pB&FrV z-wLLB@Xq%sr4z%h*w!0Wl7)AtPbmtkv6TC6ZDrR{*tM7KYPemBm0dSsmln;gvz47& z*!8rkk|C;it*T_BiXMs-LjvR<#1s+G`i&wE6Y)$ zL6=2T5#3iHoaZB)rOKQ*y56oj99LKwO%O&!Fe)!BEe#t}kMjO2w6dKcn5rX37)6Z6S9t$zv$Fk8Fdd2ndZvVBW1?a7jp{!ffhy)UZl&oU+b`>d=!5mpDXq9pxa8{WU5 zdVKT$22b?<{3^olA*23}qRMwxRelxHKLc1w`VU*#{3UGu%!)|*KjRTRW@UMr-6+9}-bT z%(aoC%5bYHSBolFHqdKh{LzyBpLmaswsJj5xSqhwBd;H@IqPr~M_7yDTqCS+fVGs} z|H>_A`XiG5V>r#{{Vg!ngIDL5H;g}xDhq}8`F?4mImLa?wX$0#?3T!OKXbdqR(AIY zyOq)GR#@3RDC|~SRaq~pthK7L5moenJnE0Sv2BR3bl__>Jd|66<)-MCPg+^NAS|DY zZW*+)d{s2)rHCq``*sTFI}lEJW7}?J^tLeC3!{jQEdecdICfdt_6e|MIX*5skfg+; z%)u9r;^X4uh6Y;m^TYHqet4j{66c7Izl_R}bpCQGub}f|=y^Vs1$4fU%5hW{Q#pak z5-KNCIfcsdz&V^}8u!P(q2vuH6~$Gd?JCLPa0isaiV298{*@#}!MR@ioV=~|;OC|q zZw(cE&5DoiZUJT7lp@2Nf1{~OKp9(7Zq&pVq1cha3#({ZYXeVyWY&{9(nV#f6o{ z`Q>9L<>yT;E~~68%`F)l_OSERqOr=+pU+dyXwmqPbFq4hYrbo)>s$3{*R!r?Tz{*t zy7s$vx!!c`aeb-&;rh#U-1V_quWnEmslTa{YvUScopYXZp>v6I zmGeI51J1S1bY15KJR?Rxy|{y^N{l!=P~C==Pgi~?^@)#-L=ehr)!n# zKGz!8de_s?eAe|U6!$=Lzw1-iVb>qf{L3{*y#>1Spu1RIs@?&D$JEEwjp`HXlj>9I zCUvv=w7NxoMh&XZs?VvJD|M`j+~>`hj{t{aF26{Zjo}{TBRx zsK?b4>fdTz^3BQh$@7xWuNj4Y-VElaotr`ZwDTDpgE&5m<8!K;P@(U;j7N=Xy<=%+=1h3IKGbKP8{FBaTkueaopp)%efbi-gItqzJ+>kKcUuP)H;G%Kcm)B)cOUrenqX{Q0sTpI)++*pw^$L zbsV)$I2SwrLd}z?`8R5wLd_c2@6K7SW6s&GKb*C$Kb>{1doolh{W{iS4t|hKpTuWW`t~)R?mbvD+ zmc!ysSgdf}>blFd(6tg4cf(>8Ebf8Dy|B0s7OP=#KP(=A#e=X|1Bs37$5?)6?*@1)iRPryx8% z>sse}4*x&zdeylV9$$dR7vb?GczhWiUxCM0U5~rAxi-4CyPk0U*Y%`phwCZVYw-9w zJnn?YH{fv>Jnn|aJ@B{}9^Zt=w_LT(xAFfz*H+g%@Vpf08zjeLs`p&h_^*y}*0PjD- z`%mzG7~YS-`_J%x6yAS<_g~@tH+cUY-jBiiAMpMsydQ`66Y%~Qyq|Q;6De&d?0e(S1LzjM{8-@9&B?`}6oUDfUu^`3V1>MP#4>Z{&)>Nf9u^;72pb-VXg z^}pVQ>JINB%+TA^*Sw3>*S)u^cXV2!F6*>Z-IQ{Ny3@N%eZ#w4-Q~Sg-R)hWu4{Lf zy1v~?_2G7RtGBvWsSDlrsEge9s(ZZmse8Sv)i=HOt53FjKz+;mp!$3I8ueKETJ?|g zht#*d>(qVT_3As`ht>Vw4eGnzN7Ut=9#!w`^qBga^Ktce=SKB~lqb|Xlb=*qBtNCT zk+MmBEoHO1JLPHh<&-VzODWH&J5z${D=E*a+f$xX_oO_p*1NW(b=illn*D3s8lf1z>EBO)U?BqwCwaJe;>yqzs z-kiM2IVbsX=Pk(_o%P8-JLe`p>718*EPa0RQ_cl=?E>Z8nttah%2}B#%kErKv}Ia? zM@X8Z(xE)GZ3 zVcWIzkJmvm!T!aw{~h(s`IE2%uTxUS&#?X0(ogXWUgtDk=kgN%B<#TbRLx_hrENdNn(#%n&?=j41dLOLQ$GGK0{%z zef+1QAQ9sK!UN7uuyA*Z4Ck566y5*|I;&TMIuA$G%T$_W@_H0_R`1*k6r}^}fv|s~ z9tEGhl!X5?FAA%~o*VwC1K6wA+@~nRtm;uGuzEFJ73KA<>`~~S@JAiNURnAdMHz4; zREIrc^$=2xjn|UW;tG$7RBUKP`GktXDb5_6sdToVk=`>ke{jjTit@_x@l{SeDRU05 zsxB%i&+nSn#hvdjpE9MotfXpY{z!lRi1PB%%KX8@@vuwx&Ru(T?&|K+B`tq!Nm+jX z^2(}F={5l`2RfTw5{(qRCf|D~MZH4Ee|3lBAB$#KuTEEI}U3>LRNBf2rl@v}GTwR61 zl@|W53$BKoopaHN7Tq1^=Aa+CV)Qn@ux86NB?)8sypc_?RGrs>Em-H(oQC%lC_D0F zC;eO_elBTk`af=k(P<@R<4UWGki1hTRu+yguB<8?H@WjfrI};PqG?MyEqG@9!Imc< z`K`UHds27%3i>eN?$ZvgN$7J))y}TNe;e@q@||%>Z}zd>0CX$&{o@Bi4z%p<%)S4@ zSFcmnZ@n?;=}g}i?>+jFZWbaQC9FF_i;*WaRds8J&>6~rU>*CKH!3$nMw&S;d35UeGglNOPwq5kW1s6Mk80YuuaY$&ub`~> z8oW(Dtr2ETO$kI#s(3K!Y8;Lyu3q86Y=@zWF%@PZkL6a#s+%F7%*9};AkHe?w zW3i;-6Lo!@-U^Y0%w`3%`2aS0m!AlU2pc0}x4~vHvq?erSaU+?#Aooo9IUf1kikVTxSttpxE_b+m_e;j7@`}Llob`1vFna{Gai7+gUlpQ zgTv?!ilU+sasB!_I%mfFE;9`>8(H=C^Kr;R^`5Lhnap&mUd}G5>b0Lh z?I&67lM8To0=07usQG$rHlJ}7xngDkHXmWP33i*AUDhHT;yNozN2YSHkE7|rNIQ(_ z%5rucIJDb5%}kHqhQn%@>ho-gZpY@eu19vpdcd}UEzIub#W-w-oxV`rsN0Rls4L)8 z&1l;*FbFb(vv0@Y6b!oYwQ!bhP*yyHef236hi6&c9!qi9a0y>GF_Y(npm==)<~jI& zp4I=I)!&c$I?POh!S-6fzEWh=XUqRqR=@5J9L`GPb3kAIm+2-&SpUaOEX2FDaHbcS z&0EWGsD@3=eVA&F(--x2H13P7BMzNf+1D`>U7M1rZwdHX9ukBZ6hcYgn1D}(%1 zSZ!lg&Q&M3K3E6~wc?u-et9ajHkRcci*iBL7&TfNjEpFT6KiV>UhR#UT$i&Df|%s?)TIZpQZ3 zvg)ZKfUiSkC$sp7SyaNJ2|l2RLyFWn5SK8~tN4eF9y%hgU_}36*}gzQY5BOxTpA7% zc#@O_2XDYZ!pL+bZ)o5B2^+eC@L<-G{!6xI9c%W z9{2Kb%gT~#iwm$b<0-se=Y`klZteIb*S|zXV{b;)@F)J*bw`S+~r4I zUi9~Yx=Sx=9^@`7{iPEN24@d0D5{<^1(!=}z91)4rJ$6Q;X_ZBqUoL03z7Q@_6dJT zJp zv;E``R_7C`A6QCRQjE_$jBR2W>ix;;LTmU4?CHRu zPahJdiPfX9s(ebxxPro>kc0k+=wIBy`+WFRB1&Zwcn*kOffq4?vc39sDq{xfFZa?1 zQlc`=ulL|#BQ8557t*lR{3H#(52P+C!q+PBUN*dg{^n?BL<^IM<|zZ=d}C6EDOHlv zI4Oo0jdFID2I`tNte;E6CnhCNV*bY^@nN5Et>jJTF3^7jM<3!T@K?wE%?MkSB9Rkz zN$n3`&~Jc)o4JF`^lDtp?AhJO8xpFch>M^l!)^}j5*A9es>}4vK75kg!rfo(4%>o^ z_J$2Y+Jh36E238vZEB>)CQ*4J%BB|9Bmbcoo?%|ysw)d8SgmpMSfh@}@v5FufQuhf zaB(6m=a|o%^;i@L_DK`%^@nmM zG3j=D*xJMADZK|sxL4|Tynhfwqc@-ya+hcE&7h=ge0jmRu^9O50uBBpyd#B|QUqf< z-VXCc-2BRDBO$DDMh}mcP{K!dbNITA`}(EjWdnwc=-FM*iO*yh_>Ne-LpcMN-0^ib zr*g(wV`^&H`TuYK@-D7PIM1o%Icxq_^13y-G6_jjt48r{aj6~un!cQ*oRt^17B{u2 zS&rxYXScVc<0jnc`aLgl)Ab)MI}MEvZcfLoTiGv?&gOUFnC;Bff6n-sbo~w&D8qhk zEC%Hlp!|Hg_AH6#rPJ-D6Pfz+>G&-)_Iqf-XH6VnI?@=wJi*3;E~3`7B-ggmA7kaN04P z&j7)HTW}!{J8pXONyAuQ5Ee>%SlF z^K-g(m~a+`k9)75Swox3Oh30f9W15=~6{s7;~}p|lsG3&D22TWjgoS`gbv zqpQ3O?tBwcOM%X+X9%CCYs&36mfH#HDEY-y4G*RgxYfCsN?csC+P6xNv zo^a~IaXOfA+FRgggoDx^PFLWh5ex2z655{9Ov?I(*v+nDFDUjPMck?eqZi*XV1uOx z6r-hH>C{$~_S)JT${td_myJ`F>-1sL9+Nc2VkpW*j|}2?wP;oTX3&k3{igTb?=hkME zsGPaii4iv2q%V!ITPWlx?S*_Ha2B|=d4wZp?h631jfGug?(-VPT0~eV?O`nk)*Wtb z31LZ@`yD2#B_=9;L%)-7P};+}7dWfj+DgKaGWS&`oRtQi7IbS{h(yZVpA!>02m*O7Z80(FqxJ;~5lVX@+5xuhZtYdK_A;@_nfrDV z(yIdZWfPnGr9GTafb$WtNSXUbCS`p*e`;6p3n(5WMJaPX2*qfr*O$~*l=j;C4V1qo zWjS;I+9Zv!7)n3BB?6T82#$i_h+F%~t^Gh8a^`+SURIE~|AaGdv4uut?msll`U|n5 zw8#1vSdY84KL}LL+>b{lhrvHg;|0)rc;=3y=OkgFj0p?h$I`F4H}m9ZO+8Vrxi|IH z*S^D2iHOYoY>$2=2cqM}FVA@dg3=zyMF6>wDCC^| zLQj3&2W+&2=j_Hc56Gti^; zCmbnHA85kqZ-FzIa8TOA83vr8#3JYEL(S6qP#I3zDD7#Fg7!$#mNWE`R@$RU8>Kz% ztD$|BN6RO9DL20gi{Jq#E?MAudcKK7&teMg0!#wHM2|M!qZJW@l$B2uQ+7NE(OQrj+Bqrns8=W;LIT$l=g7u17|L=Ncs3&ld?XN7uZ$2 z4T=j%QOd^`LNQuGwV2w9(q3EdfbtSjmhbhDM2Q_5|2M(%L=ZZuV|R>KH@`Zk8eHr9`a~w2u{wyABs%&f@@4;1gYQ$JO{_o z^Dtqd{I^)$@x7O;_;+4rd2_UzyixM+o4ob4pGL{QXM6Sh8)fXO^-!JT)#^xC&b{Y& zjoiD=%%HDca|r@v><|k9v49BVynBJSzV5Tgy!#-}yK(d^B6XCpt1t0d<=i2mr6hzh zcA-1b%w^O}Dc@d(=pKxcZ?CYUwhC%1NlnVNS6ZmuV@K^lsNL_??ju1t&%R%bqx($S zlxMG@0HcgOz>fgpVXwB1AmkkTVMxpQ!a6IMM+pXH>@b@F^ORS6f?%Zl`Y9936J{2^ z9Y0MdC}T(23Y6!(T98nr-1<2aO3(u31wug?JIbp-d6_umy!vIctiHr-BVClS>%I=% z9i%Jg)H|$ncakp3*md86?q099o1~?DdM_5Y&nchYZKBY#khkrKAAtA=UhO@vwx9H+ zT>1ksE#HH>JU8~6c=TNQBMJ)2*n{#FxW4de2ff;-#3kp^Uzl(X3e-={VEQomn#fSb zPWBVXe(-AF5tfug|6ro}&dkCm?O{Se89U1FK>5|H9VHYgfBw~ka?}Fl7@?qy9px{e z948JbcRp@X)kp0~J8F*JIoc^wlk(Yrb#r4(`A(XMV@pPyr^w!faIcHAj9Vv^P zIg}clLFy=DS8oROroFYsy|pumLC%+(_NJu*`Ep}C{(|!5GaF_*o7hms&UOLV&g-q6 zOJH)Yd>&w=1TA`0atf5&WN0dh%Q|TY zYu7mqV+|rKl=iTO1MAWZEswCI4Es_ORi24T&uB&v4oZ7CV}LU{L%W=Cq%3>13FmSP zoP5GTX%D9mI0eKaXW9iOX=&JuB?6T82qu7_mretW72|~)g zr(khB$`(iQO_RwcDm|N-Y8PWBFs{kasx!1oB9Zd&Ys7@E27x@6DosrKsJ)g#gwkG! zYQZ)uL%S(MyMfr`Tzr-Z=_Y}Dg9%O=NOi=B(jMaiFwV=+>IqQF%IBH*>P=L7$ZjPZ zl=g6z0_XM&?KZ-ZGV|L_IJa5g+(9@f?cv-7oI8m{%FgdJDeL2TrCr5)p}2|^r3`%) z6r-hH_fcC>+H32BP`;m(^>JcFX^-_8us)rkZ6Z)PbALKAISg(xjTb=w#4~psJwd`k`ERkF z&P3+E-N@Wq_;R%7KJ6@@p1kkM#CPofz*pCAWM5rxj&G#bx*&Xle>?hwGk6xx%wcDa z^E1c!Upm&i*k3y0=sDM?r}Zf9VYLF*1;n&BQ~z6w+ZfUXTnWPokoe=nKa4*VjTveuK;Lydq>R#@at4%plkyQLXQ@ifJxsZ`th~~Nzlp|+p1!1v(w=fQl>I)< zN8)ileQvB~;(myKgNqS31buk?048efN*9|a0MYlG9J>Iy02t`g`V+tz;Q#}}0Qy@1 z47Lj}8~~U4H2juR-r2*Il#{eN@CaNQ29Rd~fS+oz*9D^hFp|`N3Ge)oP^@P$*ViV| z`J<`xQQA{3fbx|-Z48P3K}}!FI{!*G&@RLO!7(z1SR${sD?b79#XfB;$$vre4>S2< zYz&XGjo~3S-f#?#wZNDdBgS51%bEd<={~K3Fyt+3IyjzW9Ae9=z?seLO!$_yg|F8* zdS+7Rpp2<=1lCQ!x`CLaE$apZVoPXPi2kUtt2hUWbv|u2iOO469aOi{mNnZ%fI+&I zhX6;Yl=gt`2GCtZBW+oCnE>=HYZWP@w5Plp%J-78v}N5ZD~na@eo{thPk9}b*ZQ;v zNnF~p)FQVkWc%9Fyt-k5IA0A z9AeA*0%zV}XTrCv-F&^q(eoX34$6PqIWpD}VEsf)(w6lT0vyX=WN6#M=0+jYba0);tecA~ElDDjrfY?r3)`^CJlq~(7 zFG_nrXJp~0G_tgK{A?&oZ{;oPw5$+NJRZw^Bt@tZ0im=9)C53@L?dlki6#Jj%W6u> zDD5dHLAe~PE+%ijRLE_Su)e_>ymem4}-)HkAV#~U~E`SpN zt+TXN1R!l$t-}CXSpc}~0<;4_+bk`a0HiIeZ5TkZ1webd0G$BPfz+ifs{<6n#=Yo# zjXEEtz0U6jcUhOn7-GxnZdcw5d3To9ljNl>%bkU9{j-fhY*{@m zFna%cj7Ra2elq|1>zhE>L;BJWN9=*xCv3b&{Q22i6nm8aHufRa_n^8zOWQ}n@<;jm zvy6}O_n8>L^BLb6aP+)SC@5n``4}h%h(rDu{{VX6Yt{pc!+tR05Ld_1^9iY=j9vZn zEUS<3LqcDW5X#tv4xyP}Q8T5F@4rHf53zoZ_@lFL?5Ocv~fN6Si?wv z5faMSkrMnlTAW`~{CbuleOw>sk0erXMjj6OPJfzTPkK>-yMfy12Z$j}|pyUt=%Ggl`0c8MjNFT)yFsbTeH`k8ZP^b+d zHR)scAyA8!GF?h-L>YSzb#H_Ul8aiWZ!vjm(I{8}+V${)Q?0Fso@1&dAN1HfOi6ptM} zlL!fAEJ*EnhJ6!|Zt!a}2}!;nbOVrnWl<6rgl6K*F?J^Wg3zBl>%`GhLr5rNN16kq zI^vNo2Gt=Re?mO+V$dyi)NX~^e7`oA1mz1s^PzZ(E(Farse|McZ#s^ih17JEu{Zq= zz%21=iwQ=)2($zMKhs5^#SOzOBN&vi!>j_#O24*(VB`xxE5l$`Gz@bO!Jv#C<^jO0 zCKBo5&uWvnzKc9aswiVuT?f^*q$*wbSu3lG_x|fi6=m$Ik3;oQzqWydrHej~LfE+I zvjLB1sThS37kxI`5q}!uoBZ07BraX>*%T)Jq=onvJK|d*{+wS6lDKrS=eaQPpoRDg zcEn$S_)DZLUFdlUYGLb+=a9e(2?&vqF>T;$nlNBS*D z@AYfDNLsqUvlk0}9mZDZ0?#fBgtz}a!hx1~j03`{;5G`~*xygFU)WFS8^BjcwmG}i&rY6t84kH!*=!h;=Qt+Fu(p5l2@X@alzOul6^+dQnP! zZ~coz-9a8!^=c?>R>A&+N@wx7mV0i@sog#X*V>aFP*V9rXPEUwSU;<#XYT&9X?+%?5COOL5)H>Sxc%X;gblJPH_2F5n5U3reS=mhZOIoeUoyVcKXo{q-7 zq^7N_dr{T9&6(~GDA6nEvF#fIKoq}m=DK0P22T5b)W{rTyqE`0s+~r5NSWx>BjgVO zvKH#y$9skMIvb)L^@wyrL;#=X(4sfkm>B_9r*l|OpBFLqQhALusu4c&yQcEkcT4$= z`Y#7`rpZZ$g0H)I3iaT(X<)M{sow}?1a3rs>eN5FEeBgT@Y@KzSQn*Z;W!HmN4BwW zxbqy|V79aj;J#dWj@}$m&kFisQt*=*Dbu|A7#P4pY?zrtoYJ4IIr`K+#riv}Zhs88 zoop`t+BlbsxYCC*#l8`W{G>0>krnJ8fCv6+oAgUrRX=;;2*L4_fjmccm`o$cyrHJm z*DVs`dRRaKSoAt*RuXQ9s`pKj1I$SfNn$G~d!R3+dZz##t0^N0YZ*>1P;)!6nrx}! zCa!cS<~jQ54G7`#vjf67^o0;3biQC6jyV{LuT)`H^Gx%cMg2U-z<*>CHj8xyuwxbv zO65Ls*^ry*sBLVl`J=e2wA>nVKHGppEibd@ReMcJ&a)uxH`{Kz=W@ca4QI370~hx?ZRNb(AL+s z;8kqa(Y8C5>s}q3ZgHNYi0KwX_hRT48lvNag%P4@kkos49Bb|bF3TRq(A-IRjuIw2 z39@YyTu2~kF=FB|D45m2~ni@3A z4b5xw9M{WxMY(8t!9u~GBOG7%!Pi^^T9pxz8r-2> z308?HIC%mQoX!}Vw!{G|T+J;8%#0Xea9?)DfZMw3Fzh*C4g%)7fHqUW;D+o7-{Z<1NhN@#ug9QbI`=&PoGu?kHO>c@3z}x2c}oqh zz=kIcWYyZ0;5)YjHAox9BK_vJV|q`!+fX zAd2T6-cb*s8i!#|W9g`e;Q$QlIRhTB=YVO1(A+CvHsECNUID{$w*3s|9VB(Lnm1~< zE{ts(-WaduY>&W-v$3bKusse3KzfWL;Q@ONwnVVqFW5HXWbl3~Hl^KKWB%(C|3QxS z1dKQudm0PcCO81mQ=AA7*mIzD$5ydEpgk1O)(F7Odex`(;u#ddHNX`YC)_U~AvVq! zmkz=*=8GGuFsu1_=#2N+6n>X7?2FT1#J&Nie9;a-^yg33WT*opUV7Q3MTT0d?LSqTEV92725YS`5bA~qQuX5d;>~u(UD8|$SjrDq+a9vF~3x`3edfi>DuH1>+ zxRc!kufG=ROY#%;o>PDG84X*1`^j?`>s}p{stdBOF-LSLVz?J)`P^p1G?uyjHXOju zTPXMxV$U(RvoN<`4`@3A+IBIw_vuyN(TjIc1hbXeo%j`Z@)N=9uZ8+j*TZ@&t~b%#kBZH>YHH!ix>pCK>Vk(EiQJ)x z;SrqWbDzaGmbw269Kg>}6nt{9=a~EbF!#R+XkUwo|Epf_H@!H9BKURq#CM;nqv34hsmG%Cor<-0CgoL2Q#A$JPGBPKTsuHuDID&1SuBBC9L+ zTs(Kun2`0?LLI2MBHE&Fkos6`inDw&v!}64=Ck1d9ncH~ zpEm3{CbJilxly)udbXC3O&>DWBqQF`!G!GaB)xTZ=uFi4+(3m{&D&!>MM6i#5PO@;RvxrY}8@Btxss4q(=!2 zlJxM17)g2x1R{FC#g*HUvfewPj?e>Uo|o3$!7t`ncgdhsU9dePk$VFHNX1z`G1(Z4 zWny-M1NiBPf{%ap920X0CT2>u)+Sq1#l+O`Qm_ph4}6hP(>wA=bjInFHrf0f4_m5! z{t{6=n8J+Oq<7-=)AaiKN!>typ$lF}O~v@uojH2KD7^!>>B?;S(G_MF*5s7V*%-Rp zoI#Z@4f-%<2o7hu#!b4xgfr=bw><_gUhu$ws_wHpRiKafPyuo1fs;I*>}f3VOos#b z>4k#FlRZZ~%Mi~V*;==3txL9ci3q7%ukA&VlAayx!Qx~Lz5hqtd4NYzt^a>E34&4u z3l~LaW)Va)G!e49A!ZXoxq=bFc11%V0iuv#3bu}zn)yA?KRnFYoq5aWyr;c8J3A9icD_yOjPDF9kvc~u;EE!ga6)Zy zlbM$wTo(PNY<^9mMte~8plG1pWhHN2TCIApMXN>L7N%OUI_N7XXtl_DR4WzLib>F- z6ErWclOKmF`xEr9F^w;?0`X+8P#eEcn;2f3XkHs{P;F>aDp3ivI`v_Ue|Js3w~9r} zHbBejha2E?aJ(vxqhT827>xvW6)F<{h5^`VjDkjjyhkM7MkJahXs;${ zjT5wnJQ%O)(oOW@H5B;`X{~hpXQMu#REaoXbXGK4B5?Hs&4M*77rRzi4Goha0{Rz= zM@aH|m?y7Eunir`{syf7PqQ>%?AnoTMo0@jZ#HM_WU2U!1SgN1*776(j6#?J-}_z|CU?8Jb9L%iukTz#AnglaWl zG9i`!u`pn|V8DEsz;+gN6+U2S*l3qYHO5Qjc4QvLBpNbe^e~x53_JiZo4Ee4V8oC% z(2sN`=s@^iqO1e9CL^XDsxcMU>tK`5(U_3}1~N`QHP`w}%JdoYtVg7v@;WD}^#4?Q z`W-4AD4`K}wW{vub93dv^#%6QfkN7|FiUKA7=WE_C}@8p?=eu;<13c0_z=m(PGK44 zR}1ME$&evV>-h++!dG=61Ay&G8S#R=2ka)mcIU9Y zu=9U{ElFX!n_$1Du)Sf1!jiXzf$a|iVC+X3@q)YuY!;@VUI|)H&O1Pt8-yair!esh zrXYjKfnM|gyZEjT`n`T^2#!_mo51vt_Rx!814FU9YJbc+eVIM|TF7I#W(=2d>5V5x z4WQ<~VJ0j^b&Fn@s;Wy5BQT+&j1Izm>9;(?iI7fg_!>fejR-!VU+Z;DW#)A4s=DAv z0u`LMF(LG+kRGQmw0hk19!G}jDB?)pSr9Yq{|@_UqauWbYSghX06Sw)(BVSfqftAf zQHSyt{XrKRk0O7l(4ybdFigM!JunPz7~-oRnutS{hbM3~q2YM@P9{=9cyu@B@D!ze zoF66E!U2D3FqzQ~Lf;reL8m=H&LFczMPI0@oB2^R6NMEoq$`f4?xsIL&Y%o(7h7P5 zbspW!Oe-^bym=R$CCccgLS$wWnc=|$5AB5L{e=Cr6Op%tnHlE60PM^~K|2w7k51GF zooIZ5_5<%n^L4p}C@N1%s606#{|8D#`vLC^i>S7D8v4)_{6|TR<`bP8<$wKw&YSvA;mQH zh&~%NlR8;uIMLrO$J-VWUIGozEy59!6-0GB@Nj)CO%LR#SyXjp!GZkA6rXsn#LwyK zpXhbjRYX=7V&iKfwXvG`3v1!3O5PTx-PXbYAlIOvAtvw9ZvD}2vw5Sf!_NHK7Kr*8 zfjJaqJ%lIe1lx1Nd zS$>59AZ()uctPHS`E{ zq5A6y7=WGQDCp23@6kuPqK|Ch9pof-=5G;t#&4AB6b=Yf+W@Q|IvuQItVwh!V=;#) z9G`(0tpIsjm;rYV24Lqb3R(g39u??;3hYYIcJMl!$Nu~se8B0=kiU!WKtt#W(gg@n zn%@gaa~TFebBRLW1$hse&p@+>qx`K4UD1ncD5@Sn)9(oiupD)eb>izdTzOvtJIcGv z4YGTGLjFEpBmJjIPVt)7`~x zFEFd>Z|~u4i*PS$QWZN<_xofA>6?EPGMHguG?*?Fv}wtE1alaId4vZu96Ku?D>%Q1 zM7#0{;Vn>#=$fYz@{bq|4ms~xu%5wZWb8l1<7gV7RUyWY>l4*qtZ^P9&QB-ccX9Zc z7JhgZ_>g>hEwB~z^#j7$N7a7@r;nItqpr{}6@?A&1(4`(i{WklX-=bm(ho8ze)QKb z!+coOA(tcI>c|2NeFp|#(8ZFEh&t>7`~sbVuVszyR9w_x*RU68=sSWtUuCSdJ|N^OH8f$5Ad=GhhF0X-&G+YtWUa)7qFYoOyq50799-+fE|f~HWYb}nW=It zZrj9XrfS%U3(j@C&cHKe{iSKvf0GaPps5FSz=wdK;{}zf4!ijUN_wsxv?IuhMJ^8P z8Zbbsf4h*?e+dR)rxprYeexdF--pvZQUmQ?f_8@op*9Xx9?eF^XQYj!2IK<-s)MuP z_sF6`D|v?pA!uaaR`~dk;yuA!dl$yLPOru4?0PNJIuy{eg8^_vQ$D;P z?*V!gpv5?440h%hqcl;)soz%$_7J|;G4G5oQ3I#>^izG0G?1$5g0T>!b0R+gCw}at z)Q~F_b$u9sop=JS>PTd4M#h)maF?R#}%v;|}yLQ2(PR{Ezg#n6L zwvd>w!vO3gQaZdK?}1seK4*Ljd&FNtR>Or`Y@pGTOK%g2YW4N`5c59$DS6->?4@Xr z325Q2MN!X6E>}sH%QZhr%KAvk3zxzpib*ahP^^q3l?;0*+_jvG{2V2vrF<&&a6u*l zGTAQIVmqxhTx(U7)Fz{2r{v63DKEmXUcs=wk;ze4+wexBG@C>0K4r-7&lcQ6~7kHz$$EP876Ak$Q7wKXr(v!Q+1+XxcbhFbLz;*hD_M!ST z{=MxqM{vz=tTl(&X^!QZqpdYZ*=bJVn&a(6rgM?0b|Uj2qDT8D%TD<^t@tcE^<~_{ z5_7-Ex31AbJ7ep)u{GA3tIa-E+8NuU zF?h>!k;lEJ)u)`D)-zn|DX+y0_pV{x&E)7*@;u(??eScQ-TxT!8W(xNPNX(>T@%2< zR8rkeCz|VcydmppIL%7x+G!?m%{Xh#SUb(8T=U=7nvLuW-mLDLEL!%5D`AshH;T0b|PcB$mj>O+9)#UOj$`w+M?gunV!Z?PqrJg zF4x2mZ9X!)`HZRLE1x)(BpHLZ7Z>T_GfgGAc3K0tR$rgRRMN_@K9tGPspMO{(c5EK zh}~pE{(CMm%1&e=cRdck!c;QWPG<(!ndY;cN~YLpF5sGTtu=qL(_F?imso4&+iCv7 zHCNh+Y~&*A>_mQph#u{2KC7vuHSKs??9}&j4|~o1;&M!{wi%9(a*&K1twlpI>pX(J~zFQT_3GM*yuwAI?L-+-;W->kAE$p4@t_*gKX|+uiK+25`N;qTVd3 z*V|5SIM*9$r8n44Z#35%X(uv{i;S@onF9C5_fw(#QGLP9*6Fm2|E!5B6_r+iMLAn&(MlL zZKwVs_wanYsb5sKu2CgBV=r@KwX8L3n0-{UGZw>*`K*n3>@*v2&3J1~znx|iXzIai zY$wu;8-FcCgpakixJYw5kyc#f{Rgz#d+}CD|9RS?@7kIEkehBt)I-l7kTL6WrG{wp z?i}FSU7#&w_gARqXYnCP|8?x9{q-X~sIXzo+nz3lXcalIj; z-X*Fx$WHHjt~bg`?^`>)30&_7JCUheWRji8Y>4OqnGtWfu>BaK>B1FWG?WXu<~(c7 zId+=MxaJaT&3rq})x1J0LPU7;ZREz+A)MmEw#H8BH?Fh|N+And1ZwPZZMM^Wss6K4 zxGOvi4-rVs%%m@4>pw#-_z3f}GLDt;D8sP7K7CIv7OGia>X@3{J|pZiZX}wRpRX=2*(Z4NgVPy%5??F+&2g zaJ$Ji679L&w)Lf~_W1A`d~sEZjn+rpZkmlmI=9=wM&e^gkT_@2xRW?%SV_9VGEH&* zlpF6{UuxSSxm}h(osIT4wHKn?g;RfFrS_SqmSxOq-MF`amD-o08trT3sX(WQw^96_BYh`IaHJoci z30z{Fjl_?TAme&D8&E6AKne>FTS*60c-Shoe>E$Ap(W`6Q|ptN6jM*o^?j4+zMv}V zBWa@OT#t<_Y_1VVHuA}>WL;s?gL)7y8e|i}CdPS)aU5pl5mJKpPn4vC9%cKFvGO=A z3GW6n6h+*1WLFSvDY}NOv8LT&NxRvS_6(!F$0+WjBvF+TbV?UWGIfTrGMtu#@>B?t zehttGYoyDTNPk%(J(8d|bVcU!8I%O+SyBQ;X8RRd5|m;Irhq*}b_E4Y@4*oX7DLz- zRyKi+6QOyF!vyIwWFjtT-seF_D5@rupw0P0LU9_P7a3I~D>Y76IYH`}EM8q&iO{8_ zri;^}YDI@3Ul%U*Y5ZmAk&zkPlV3`ZItcs9Vi`k)I;IF>)vb)X!lHsIsjoJ%tbz%w zA`N&&Vk|sGn>~50J^2%)PNYFdj1?(B#vAIE$Qt_t<}Hbptw@PRPew_?-J0$vjolP> z#Mwz7y02Q$H8#^Vw5EI8vJ1SPAZ4b~M$$V$S-RAxG3L)1>ldv2FDb#?1tnqrlI|zW z?GmK6sJuQAqw-bhM4W1-Yhz9Ku_fJymULZtZ}|$w^n`_7`pl>LuenTjTbVwPA+_kw zI{ES!mb)2hZEv_91u-py z!HKkv;o(zs{_v^bM}5MlCEzk}S9rt>-9f}m=4cjoG@e*Y&dLa$KeFj%Nk3TClq7AF z7+X-CTw#+*kIbUy?SuAXnTP=19Nq-8t&KuvA!PK#Z$3u~9{O`_HGhUCSu9s36omyW zjtPW6JZyDB5!yx9>6H#&&w{Xll^gZ4$R_rFGc8FMUYsChf7U5gm{S&6`*(#cBU2u( zx-XbLU13YHFK8%{3wjr-cdq8Zw4f9LVol^~_3ero;UV`2U%x0%zf^$tIK{8`nEz<_AxI)tD+`H^_qmAVO{PoeaM8L)w^66e)z>cl0;l# z0lv!0YplG^${VyKfj>glilCLu$VpCd;2;cF*l7}(Pm;`^R9s=ltVW6}>;$MXaD9B} z=Nhz*{tq>~%_D!)CcFl$xHE)uBmR>!6p_I;FIh zE?+7y6@9$KNqMl^Q|Y7hQZBm}D2tUvO1Da@m0ika66nUCFQ=Tm^lo!iC%d6yH zIikTI#&Hb9j{JMC#sXwsp^kl{7Idw&Qs@ubg{Zb z{aIbAE>oAQE7Vo$YITjeR$Z@dP&cZZ)XnM^b*s8f{Z-wr{-*9wcdEP8-Rke^AL>4J zzj{DDs2)-et4Gv7)uZY$^@Ms-J*}Qm&#LFu3+g5Hvii4rRlTO(P;aWY)jMjy-Ob(4 zJzY&T)M8QU$`Zk0#M+wkgFd7iu-a=&5E z4(!>9J-e`HH}?FFJ$tZcFZTR_J^R45AN~&D$Uz)Agd>M>>=>kuL+S*i zPD1Jwq)tQX45a>o)LBTKgVcFQU4Ya@NL_-|Wk~%EsVk7W3aM+5x(=xukh%$}Tadaf z50dXd@-8IrLGnH%1IjhIt8!iLrreObD>vm_<(B-la$D}9+(BQvE9WWqRRVH9{O_-HLoe*E3{-NJLCV+Yk3EzjN>62|lBaxwJ~~Y4tqh082xxq(^ixJE z{gqMB_zoJQq47O5#z12%G=6}_IB1NA#sp|ggvKOjOjc&fQ=l~!TGOEQBebSNYX-Dt zD#PSi%5ZtMGD7}I`Bt8zjFjiX(mYt24@(PRX(22vf~9;|TC7Y_mf-)-%4&HjEG~n^ z<*>K{7FWXJDp*{t%u;?)W-DuypOm%A9A%v{S6L5>8(?uGEN+6u&9Jxy7PrFUHdy=> z7Pl+i<=^mshq6@J3Cp`+c{l$54(oeheJ`y40qgrz85uZ&<$q>sMj@ z8mwQ3^&7B$6V@>gDYs$$4y@l*ddTKb2vb**oJy3RKcGsGZuy>GC(!8b(xCUPkL zf1}R9EHfAL%sk9A8-3rZn|veH&Aw6U7Tsob%wlJohkoT34}wQt>xYQMUh)IWTi zVP}gv!o5}f*1b*L=lfON@7u2CDZi;#cgz+`&&INUs134uBumk z*VJpi>zHqEs24HMUQ%yi9=?s4_>Ou?y{nFlyr+(eysuvO1>84$UESYBc5~nKb$5@B z%yoYs`L%mYWDob)$e!*WBJVNA`A4i0tE@7}?i7DYBpYmao5ia^wK_ZQnrm z9p51Ll*qyEyS^drd%mIWsgd8f@B479Hun|z zS9gDTyL*8An|q+V!#zme=^iZaau1PryU)qLyNAkq+~3H1-NWQR+{5L4?h*2S_qXx^ z_crAqWDmKo%7@)+c}Xm*jqx?#TTs&5;LGnkx^)u?o@?fyPfrQt4Roy;ilf zl!YHhxbELat|P^^O-;_OR-?v1Ny4*%$)0K{nW=5EJEtNQ!YLo@aeYZ%3V+qwq;;s& zwjJGvUmrszKtzQsqC?SgA}bttbmT zk^8!YBx$4tg8sN13qCnSOwB1BB!rh-jx_)|y6-hfnrkP=8iB}Ft0+nRKOnCP{nUl;?V9Ffqkq*1{;P>g5FTw%@%H1jT|dX6DQckumwPI(@MEbfx^wxr zN@BJu{{oq_$_I+zjs_@Sq}xb+UopC`>>Hl{xfVvdrKPv&kduN>n5-SMlG~Ur1Azep$9(tYh>J?US?GQ|r}p|Li=vtxL;xFNSw+SNy-HQ+Jfz_vAk&w;PUST-}O3fBE95ZfRYA z?!KW`<%)lm%8!#0-gqOaLq>8+Qrw#jlCrWh)6(e|p+(375!jEJ`+$NMpI{~oD46CV z$gfKx!aP#q>j|$lZ{8#+>!YMBoHWlPr*t6W#o>d{C@#Gp71uZsd)n!M3eyt&-7VA`Q^;IEudr+z=wjKuT(ACo08p z;vjc|TIu40mChMyDM|dk7gC@aGt)>ggEmTP)3H+$yOo08SdAfik}x+DWYe;e2zDy@ zN=XlC1O!hJ!FqyVR{ONJ1x^0~gicegVX;O9(1!IB{Y{!AHFy&jLlwYn6e8IUa48v| zq|=Uw3&nM(qhaq1wKuPz=aBBIcbcU7{uX|i{1syOD=sbYA{vI{xF(75uUdqqxO6Di z)D3wr?4#R?h!?8)IZoOMZTJ_Z8XR29_{65KvpSwNfLeKifEaX8d!J*@o)(;?rQ<{) zIdiTDp)Q2Z!(GHSA!4LC3nFIpuZa-8K!k5Z1$UwJoQ~WcX~~Ne|5}t0D^Lbukqf41 zJOjLUSsk5^Hc1L;jii*EjvbMk2L3i|oG<9-9Xrv!Ck3wR2O}m4H6lHj2YCQQu2IUv zXf58TEQW@c8_dvN!BBceN-E|UtHFMYnw;wo!3OXyX6j*~Ed(YqcyCh!%{@lsc*h}M zIMbkw3hEU8=8a(b6J{FsD>2j%@J<=z>rs6el7VvvmLqUOm0*#atoFR!$fS0c$jlci zi|;El(^Byf#;`REa`%YbZJ`TvPVSIXAcPcKx=*WeS?mP7jd&lLBQ`XrIB6VQM`tukAva|%w3XBSk4)VM2kFxQHe zS1AnN!cu3Kj6NAOX@=_uBXAF(;1sKQTV>YvwF>2F-&j1A( zOnpR;_OC0vpCiUWbu<>{SA|AM$tjo!qG4hXsnU-^mDrMC4DrE`8cgf+uvPSfJQ`8O zjj@ah0V%lul!L7yu!WEFQt9^s0aAniZ-0r;1|rJKQlcEVCndgA^8K<{1D`Gy{#;-- zK`OPftW-KN>G!EGf;#0Vd-A&H$+)p&h zrkl*}&zR!T?;wZrpWcH{^!y<_xA$mmne*FGxT`Mis~9Lwytnrl_h4*m;?QsQin}o4 zacJI;7!FEjIGuo#&RB|gz|vQi0*?`vbWdLHNJJuc5Qzk~O+YY8mOy~5_hUwY(iuUH zN58*c<)ViBXW(9R)|oj&>CD;ZsP3n%x(|Ew+m{%H5Ucvc0yW8fD~ zJ$?m`U6{xCV2@pFJO-S4>;aFt9<3X5s*tdf9#)CeGneTr2^{{b|_y%lW+@j5UB^p>&2d99Z9Yv>^=ZWsg1yR3%j3n5c%B zsPx;mj$k+_o#BiD&S;M|is5*JaYmbPM%mzuWjH9E;YEy6 z5ukKN@FNJOGJ<*n!PEy6OlJfroe|6h!A~A-7K13w25(Igg`Y4v&LflKd^$PKl=Ekq zsPqYBo>Ppaz*yqZ@;%x@M)EZ498rX12_Mk;AP~pWLKBnTYnQPQp>!6abzocL(N=r3 zm5eRSXeu9pTVq06&2d+n;DnB}o-v|y#`r53w|cbA4DiL^k+s#tx7kFchip5;LFo)< z4{&ySw4Ds6MljB96V6T>oV^SOr8As^z}e4OUJG8H_M1HG{rQknk4NG02=myC)t;ta zN8r&a^*YAtiqctKPr>sE=J{39Pf4y*kMz?MCfDeT1-Z^?Mu5^8!DSF!^l0Zj+F8c& zxWN%mI4+9Q%6vKhJoc<36U_=b(X5d3&pw#-Z^nw!8S5Re-tuTS7-%Dal2kD8ZvuKN zG&#(_Vd^h{9!b(gvi06&SSSmHHNwc;OM4q=CA}7zdr5Cz_bnuY3(4Hec=gO3r8Cb@ z!1H5Xtt@jcX6}!9jm*8Qi33c((7YL2?~@D%r8AtTfm4C8h?#o@Z(i?Ia*l+Hr#1x}P#tHW@_%smPazmTx=%)QQo zv3v{*r8BH}VEMh;D-27>-2Eo1S4>p;f?l8Dpmc`wDsUQmwT28w$lM#7a2nd+G+{U> zo#8YCP9kFwGxtQ3YoXh`!3a<~BX}DGZ!!WgbAR)}1n)2cl+Fl}K=8g-dyhc~nfv>g z9DgN~BhTF5Gg0Z8PAjJvX~1ab)l$7$8%82z?(O)1P6dHDmfDz@^j`ZR3lU0ZA<6>V z$6hVNt94{-V&?v_2`Pi)b~M2W9VweJqIAaiUod{|)jnl_LgxOtiSJVrl^(J#3oUa)UN@qB|fs@Brgv>q9IrI|an-l+@=WudUf7@7Oe zz*@|hgmdnT0kD+RxUQsx<@GtaBxd8Jod&YX*x`$|5qEjM$}GpF8P7zj#dAR7R( zj!}p?`#LnsUea5FbM`-I&W^2jBO^fRj9{y6&R*bb8*_%znX?_J?sisPA!px?NdG}v zJS1n|>D1#Mc-+lA3OW038;^UPdOQS=2fW%o=2Xnt5AeRV&*YyyPwOxXHcDr~J_(TH zUhOCY5wrEVxE4->{_3O?la#go%xRNHPFI*`Z*LaLl5(X z4oucfi}>`jC@7uzE&<<<__Sioy^xzf;>*k3C*za_&ZieMk?2`WNv8l$0N^p7R@SGL zVGKf6{+N%S$N_;kX3ChD^c3?+795n$f+K_N8K3sFPpiP##H{=o6VlThw}Kf??=}jf zL+OmJD(I^CwC5O_kdId}kv(VTp#%B_hJ(@>PEFuc_h}l#5%TfsCLGNMrxwFO=?teX za9(CCLO%Yo$+O;*qnvt-hDR^+DCFZ_c(h8W>an__bXHeCJio#`i~0B~Cf8Wy3sQ?X zMu5^8!K)x>?9&?hv;@W>=HrcxsRWsLL%iNkrWKq$Pk1n26UK+q8Q+`WYwpvUF*q>? zZw??K*~@Qc>LW-6_tG33Tkl&83*|q>Iun)X`hZ^Z(j7=$8IO>EcZKsq7WsEB^NOm>Klhs}F-fS$K$nfauQ%#Jsydn&NP1-hG7T-Pn2uG4Ch~ z@BJH}-Ffl?M|dC#z1{?6;T?@cHAk>&3i1!E(|y`B1|jCy)8Sgo7pB?4%wjMo z3lFmpF!O!dTm~cL*Yiy*bImMtIbOt2P!=9#IZ&4Rv?UBh$gP)}P?p%BtY9c83y-n} zD61KVm{+ehyVa+dwahQd!u#C>zZ;leF{j>O=XW#ni?Z;3cfjvy_bdeGSOP8XsrZe5cB0S(QK+f zzFZ2gkFtEZ#Dm$&F*cNiXL}lK6{5BB3{1?GD*#4F(DKUzNla#tD<7u0GPd4|3<>2w zMLLCCIdDf}*N9)Q*Fd{k&*DmxtM&4_pRmZ6Z`9Mf2})<4@4@q(dfF}KT+Es8)H6;{ z+%j>X-<+bkE4JSI3$?JZ>B8x8V)MGh#e3W?zJz?@M^suK`$Wb~Axe6RPMtg?ghHE#AxvhLdd=oFgac(lOw;< zB;G`&XES(^pfikSz(|bIn#O3aG7=#VPvir-DG0=|^s0$T@3n8R5TSI&_8!>YjnUqY z(cWZiVlMu!3F&Q)`=$v_=twOYBT8qCDPU|JqqSmyLRQ||#MjD1rH3q);h=Pe(*Zai z#%S#sj*yvuXu@f4gM&vk(oT-j8BQi}Ix!X@JMU!jtoLU;yV04)Pv9|!c@#4A9C)-! zy*_1iMd{4*f8qIa=2^_rKR3BXUo1#J@Q6toZIsRkdVnA|M(Y-%1sI2zsppE*3i9=C z*mI3cH2g}Fz=K(PGFFt%SO%>8U^1MN(#b|O~KS;xoXTK^lkbp1H3-2yxi^z9N(r_N8gt7Phd|Evga1v zbBq4cF;5}Cbi~$sE>>?@l+LjJ2G%9UG$~g9@!>#%bSaj2LU#fretdYt`0?Qtryg&? z2&FTi zG5{*YXugltf0XzwiB2gKfWGQH$~>cV=J|1WF2_8tgXcI^3VcsImlHjYQt+E-9P~cH zJfn2x`Du8r;MdAC=X=@M_<=aD0OzN0G6I|Y@_0R-jFV9c87BbI*PDt?0o(vk{Mxe& z;9xL-5(Mz94L~KQ051UGdB0Yf0qhJ0cs>ZAvJJqCP64U|Kx5uF1~1{@jt(oh{2~wJUZ8z`xv;7_G=#Ielc@Djku4- zkC$eUg<&%3Z`kI0Y%pFaB*r#l$w~x9Q@_@jVTemsQ*g{79DK=Yj6L(op5P^GA)T+W z^}fy;2W6q6!?E51Rtv@?ELklOh=pV*hAdfcJN5WJJih1G-epe3CF?zSUCNfMcTEJK zSxQ5It@i^K0+h}|kP4tSel3{+iAz=+K+IxGR`P>^+A<)N&VV`s=p(!To` zv4mU{1rTR z@oQf&=faZJ1kGVIPR2>dk`-_Y&;tOueytk=5SFamAb@T*06m=o^aDU2zt)QZ z2uoI|+{7Dy2y1+l&Kmz)cpmQ8zG2RVC2Kfevc3^9 z_>zU^YddrQ1Kf}CYu_>V!jd%x3&Se1Fz_YoI~$B~{~Y5b^8LtGW64?xjOBi93BwSV ztmWWXPdNCJwFG-Mkv+jn))qQnW9wbT8VBV+jgE-59$0G`ldxp1MIg42p%}7cZE)&w z8$53DYnzx;amm^OuRGY1waG*PnjJI**m{3uAwcOY1iu4lmtWh#fW#$h7a-QKC2Pln zf%Y&Ul+J(-0qB5V+sA;!CF?*C(7p!)9cDl%odF#O&{0MsELlfQ0Q!=3f_X;i%<~y| zKE*r>OV%mTGoQ8oVxCbt^Lz=OFZi`{%(<{+U4V0A$vTJEd&oEmS+XuW1-Jo#Ykutt z0}z(1Ye4{4YyfUL1-K7@yMFC90}z(1yFmcAZ2+V=hfNR>hi_7Gi_u4M3o>EJ3X2ow zCf@i(;`H+zD4jKaad>_>PAkfs3rp6+amJ^tq9O)gvPw90Uk>gcjnhgo_rj9(XdJHk zCkq2#vP#)tJoe8q_C1;Cawodf<`POoJwHzWCOOgd;!F6J)1{B@B{1xYq~~wR%d!ny zNG))~?ECk_T`3;piB-uS@j>my@DY(dQ~4t<(%xfw3RPP>t&h1@y2s*a+7%4zotYeU z^#$JOPnh~N#O_mue1MB|u@mXZUFQNAx7?(Up~BNEU9N6+Is>>)Ur)&6h4rUq_O{a; z!8O0J)*ND|IhJdVw$>bFr#Xphj<*w;&PAr$iOhqD9_^nz62CuU!IN@pBjzsGEIajO z+`|%czsR?)(Ly_8>$$Nt)|#u$K33Wp+s=(`wKlfdPIE8U+-4~ z%|~V#uQ8RB^omnSQ)BQx$weOXnx>Mnc3Ks=Rt2xcRPvf(U1f4~Dyf1udV5p~v72bf zM{<#>b|Nov*EIkvOeNLqbbMSV${RA3kei{pTy^X;>vK)NwdN~!noYQ7V{6TZcA9T+ z%|ttqceu!#b|S4HqDT9EuhmrYI<5G7cIqE;5ADqTBGtM^ZS0I?b7LP{Yi5{zbhI

        `tPx>8agE@iEC~@k+K>3Grjqw)$17&1{v`MCn9sb#_(CRR zJ&I-Qj49mMGuE0ER>j)bb9S1wxMp>0P0da-3YvN_U$zse$BlbKMEF>X z<07xvi8SFNjUUiz4SiNqNlV(I33jI6;-;Gu^^SP(Ic{^WKSmrm4H>g8SF;dp-kox} zcGnP*BxCUQ;UanF=ImjoHHd5Vx58>=SRcmZ=u|QaZ}j#U5n?ylkRQuMM%#%@=B_6I zSjbAo+3C#UI@7KD&@?;EMO<^fwdPzq%@tg8skP=3JI%FRbG4nwW-hY9PGl!U*u-tw zDO=O7v&~NZAosA(+%NW8*XVaUW2d;WN+G;9kLtC_jo#~3)bOoXw zI+c(y>vEM3(dHxbMm?i?SL=z@YikVN`&{HsJ=5xQ%TB9EjA1w|#sVwdu>J^>qf<#~ zywTgEM2tw2VaPwmMIN;id5XI(9}_Z_JYlEf<~njr$a>nIM(`Os%}B0U)mpQPon~#W zS<_mxx}Bz%Yu2?BiRB{o>_i$tM2~htj8&)1q!o|1Q-6bdNJN-J9su9ex<;?s8EeUn zy=$%cw%NySkP+lln# zBDoJ}wQgk4nLgljrY#z z&!Fw+vD1B>Gd1;x^u{?wRn|@);NDY$pDT5I06(<}l_m#d`9Py_6fu0%ftXNa>-jR(2_ym0y*u%HK*<_QetbIals250OX9W99MkBzcNF zO`a*wmKVy4<)7tM@-OlR`J{YZzAN{Hoj%F{Ww0_#8KI0;#wrt)sj#~UmRG~(R#@Go z>{pH}XO(lxCD^|TzunaCY7e!q+D{#*{wr_@Rh|#~3*`Cmus~jfZ9cY(v0XwvE|HhQ z?=ozcW4i*|mDsMrb~UA0Ew2I7T5Q*0yB^yO*lxsj6SkYN-Gc2_d8E7zuYQ&1$=f0K z8}{tLo}JjU3ww5B&+pi?2YdEn&mY*c4_y1Muy0h15Anorlx~NL_@~B}iR{)ZdW00;#Kzx(2E1kh%e>n~=H% zsoU}(`3@xSLh>FY??W=6T$8&h*X3@?4Y|8=Q_fXx$zLnCpkNtI}5q$o=rYztRmY)m<5=Kw}&<#zSKQG$ul05;P_&Gvz7JnhLFH(E1Tt)1fs3 zS~Hbl@+@VzJX;wd|D=2?&rwFob75&7EX{|d1+cUbmKMQMJ}fO(rYKAB|7T^jyc8Cf z!QygQTmg$KVR02Ku2yC#zbLbnHOf!QT4j#1PMNE$hs6!BxDggN!Qy6E+yaYRVR0KQ z{tAoRmG1Iy_`gG0s_ca2U9h|x|9^+|J+QtP*8hO@eXzb?xuzUY21OoJ`pJis{_m&P?}l z6XpBLBsri?mb z?x)U^`>V6$0qSgdpn6Fjq|T8Ct8?Wc*k3_89MI~~q z|6EDJazg)t<4tyuXh(*I0gs%e{4C}~t}A4wg~-K9Wn!rui#w6~7oNKLB58o2KQ6~& zPYykd|MedW62eO^$Kp?prhP0)P3`1Z8xXk~RU~P_*W^{fAGgQafgG8F20JmmK!&^` zatNtLx@%g8)J(6674!AXjCPsH9pwhtlO;d@X;hu6Et{sb$;`;gXqzp+m6ny0+(B-h zos*K5(Xv*Jnx2;N867+3q^D(n*7B|RmMt*Y@L?g zvQb7>_B&B^=qlT$R<)E49aI^kMbffA>y(<3)WLt9`cLV8UKfgMC+Wk1QF>445$1b8ZJmyXojLS%zCL--8xaI-s>r8$?clv zWTSW02>z=XA1^)HpyKVvYr7KbqakXc`<8nuu<&E)adhVLZbeeP1!Uuk4Re|8p&jR!d87(;+7XNfv9xtmL+-co=q@kE*qo%D5H|_;^TU-$iYY zJb8Ee)#sJkW$Qclp!XAMzQ&P>5%sEPZ>-h)YU96#ZwxEDwVvY&v`)*Qw$JT-ZQql% z(a8_i{YKy760$))E#AC`sYDsgVAW+wDj!M%=Bb7NIRsprjCAiYi&fy9=B(z^LDGx zfB)~8FzIUibFaLT6d#*ZqelE|ufG=OZxkOJD|LHFig3BcJ|_jp1C3o$*?mv`<51en z4rN@2D|Ku3l5(ocof7*!U_*l8Q55;eSNC8pXM;#)p+!T%bp; z^TPw>$%-olYC!QPqWEHKY|^0UhpUKN(XQ}%uIPHu4KEc@U&=~tlY|pW8Euj>Q)vm$ z;gnT{fjPv$zBbs*fPwf%Wx^u9spEQ%83-%2yuf+8%nUrFJ4~g zo1dljWx|SlS0}7QJ)nnOjdw-Vca{1@G?3H=ADD2)G|0?+Vy4K4*eoJuerIOFpA0s$ zNjH;;=fY=Z6~v$}FcuMgUj{bGmGN-iR%ODai1&mi#b>3G^NRZ8$-P+O^Py2(+To3B zoCvLU`l4T4O2hNdle606IqjiOL5I|0Luzvzo;RKFPEx$TNs~A{^F4{5ewG4W;NUOf z2!4zHdcteXn>R_q)3)^wt=)=7kYj2Lk%Avw{xcCHziThBg?TSK zD+v<_x`A$QEbJ{Mf~^F5q+h1zkQ0fl;uRscjL5AK3}QrQWOA<~AhetaO%{x0Wn^Y^ zhcaYVK&H4BibxmirKF~IqDq`D4n|i|qX(YM zO8Y!DDO*=8j;4i^&KYSbR?i*(u8!0^HM?nQM{ej@_+L$G@PptHT_CAV$4*J?no7Md zG=|e(i0m{$HZ3cOR5&$-hb01nYlz@5K~R6xyb<6RAhecNVQKKQ*6Sytqa?AXtsBov z$Jzg&Mr{YUl#EZ(lR9K1!)een-q%rk`wBW{!W(ZSHE;1oXHgH9t?yEa+~e_19CXwdR4qA3NXJ z=mq(~p@>gx`Z^25zqvpZnpXq~?oO{7a)-Uhg_1g^cEs=mX)$AeW_*YCbRtg4>DUn; zHUdrcBN5Nllj7fa_w^QuNtgk1GE#f+gi5yIPva5KSVdQL~7C;di5{)jg4J~wmifJAXAG0KPwLKHO1v@q)4oevGG zqx;d&Ng@3u$%xWhhKswAWeYs9j1JX zH@v_^J`o-vA&BO&V*OSRnIQZGg#V;&j(Axj0uO9VM3mqb3RZkQ&Xu5dlsM@x)*vUV zJ@28h38dhIk)nSl3PUKn$wmK(w$SDxQM`Y;)1ziyrv}OYKkRFcW z(yP1)XfNlTkk1fh&GVYMyGP^-6l66OYIKr9+@@<%lqAWtg&T3#&0An42bE+{{Y@q7 z)HYV3-)T?FLJZQ|C8gklo<0q+&Q@IN6tB1P1;fCG(AkkRAYFZ=KzlR;{vv)CBAkMA z$=L;=Bk?^=sY_S|fXC@W-B@wyNn<1jdHRTXYA-|wJ(eyFd`YhXUuUVW4}(W@e8_N4 zXV$(Ftm)iIow74|->3|G7pc82K~q#Ha>PcV{>WIkfi5s`2?ioQw{XR!+>p9Vq=pDm zIqCYsY|P=LNB>P}QawS7jZwRx&cs)nBx^xlgKQ({3oMqep!nyoh!ru&(wQvxV(Q+RM9)tU6IoP@f zTR6ce;ZrHjT}nkuzZVFQxBuV%5}yr3l$WJMIdD%(e5vI7WnB>wPZtY+E-;%Qm0DR= zDxDbiBl)fTaJ;9_-uO8R&%TS&fB4xfO24a95!5Yzag_B#&zDB&Km0@)^mD{QcwP<9 zE2FgK%z29_b_=lL#QVx9<4&*3O&s_E@Wm43mR#6+e_=Q%o#AW%&N{~O0bwD}V1JCT ztcxN~3dhet2L(N~dKA5vFt*-}i~yxGf~`^PUc#*m_s_t66Y_g!?ra-#hSHg{9jNYh zR^8T7`YqoSQrqo__b75x+t4TAIrX>)9(Oa3-vxWzZR2sTQ;&z>@j#Tek2(F^=wX#e zJrD36w$J2W=wXLh$Wb~A`AOg$kJ64ZoUaU=Dg@^^ATEl}!Fw>)DTam88P-K$osZJa zGOYe=5~xb3&YP&tnyB<2DqmtaD4pTl0M4~2?Fz#g5{z@rgmc9P=O)8J=?v!{aPBac zZ;cjvk;LYX$+ggJ?lS_E&Ilqr_-VdJpP`2d1Yw@gp(+p*@vxuhdmIv!0Kp?3tr&x7 z&jxQz5`{-RdAak1dkGgaQR(->E9n&D31B?t(aL(XGK?gLb&e=P@|ee1GRlHL97|

        dU@e7k1WC6=v`O4$+)ehKU?zFV|7L8tge1|eua6SK>8`k zb?T9R`ijXlFbdL-I7Wcd8NsU{XzbA%db9+_k#2Cr6OP8>v_hVhhdt}aM6-fsVdRN< z4`yw`SW!A-eG{zBJz6sc`U5~oDj4`T0c{Q}Avw%%X6i419!WAdvh}{juuv8XYlM-x zw+B{R#w29!Z2@5Q(DO9r8KpDN8SvcEqkY7jieg{HFDdOI;3l+JK+ zfRn{o#LPVljkA^X88jDelR1dqKY1G^z}DND5ukKN@VUn>b1!iA1#^bdnX|7@-7c)U zLgwBD@!m$JjgZVe;M8L-Ja%Iqh0ML1jmNK@dh7#_y*ye^=2Xnwd+{FD)8t?1VSQQ1 zQ929x5a0~*Xag9In7I!E#4jZ5{poCtTSO0dFxF6ph0+<;cfcCy(MB*VA#)#Tq8eeM z(pMGS!G_*n2&FTe3BVcW(Z(_yA#)#R!WnCWGm+t-bcQnxI8zvln7L0exfZ(3kBk7N zGlJP5n8^sl%zfsA32;*%+9W8Q5iA110*^M2K?s@q0!)s-lF4yCogDFG>v<+BJ=4J* zft+Ei0>%oDw#=jb%t(aHeFY!T%RnHGrJqeqdauPzg=mOSI%C@mwv8Tby+>Qi*u>0z zqX}s}$6afJ6FSls#)#4x<1R4n@Mzl^ppd!mF!60SQRyMu&2UgU!#Mz)eI9Ku!x1v~ zeI}f}HaG_v4oYV@M}c#Mu?U&_5tC=VKOb}I@f19sU>=3c{RBK(rCz65T~Ru#>p6J- zi+L6^_rFZ8(H9HS58PFXju({92(E+Rsz>|Vqg`SgV&;BToK}#z|BXG{$wb35_e&3E z#eJ$MD@tdqE^hr#Ce5B$#>V*`I$i9F)#*ngJ)#t2JdfLY|&z z!f9%Q^9I8~=?v#>;JnFL#60~?vunMpyu*B>bmseg_}LCDHG@*(>X2*fdyW@6G) z%uXygD4hl8Gq8Q))pERA7Go2$@=r`iIUG0345xP++y{^jXq3+Ax`8g>)xKnCLOvca zk$q|Ap#!=*!$Ii`r#Eo&yjl;2Bjn?GCY&BNIDHrnN@q9&fzzL{2>Ez_lV`mr4|3}9 z8+aVTJPP^v5O~~4me-Io>BCrEQ97&ZNO&H>Jd64G2$O3ej~T@XP&y-+0D^H|ZLC-O zo^goz_&8%KK_)&HulJK_1!vE{e=y%f#)r}w-%RjL_iED^oS1`84^8&+r7Ir}biv z#oW7(&&a)dnHlui3-_v{vlq(3Lkt1LAVwhO-Gh7~k25EE_Ysl!lSGL$_k&hjG+j*^$HWpG8+`!Igz5EEIi73psZya zVqU%0>{g#*a63lo7iHo7ZiU~?%&(YJZ?^M``#4g+C=2g*H~jAOX}>YoLO#6{liQyx zpZ?86p-%z0|6}2uABOXTK5f5G`-Axxa_NJ7Snh{+aculy;?Z;IBP=K=3(s{1T&H~6 z37>Y1afx~KDHF~Kj(W@trgxLS7#YgKll={{OFr!a!xD1nOD3udW)?bVanDQIb5Ir@ zuMab?V$S@q$*qus;O3w-!YB*x{c(6N7p*-St(9gBV!m81 znoSkRmmkIJqby%8{b05y7#qsMvpoy8iqYCr3{1?GD+1;)IgM^y%#i;Ski=vLM-S6n z8C$Q+kWl_pq^+?v#DRWuisr7^dY@xBD4pTF0G#I;iANojfl09Fb1lW3CWCSRk5mb+{ z%b*LK)nLw0I&)SV)vd*aQ+VFY5%-R8jrZ5aVdX9OKV@KKDG#vp|3`y)(_m&wY-uQW+B zQRx#%x>Jl#fRPiUWyNS8GZG;W&*1|)3k2d=`q;#z_u5Zch)_BUQCF~i6{B^D(Y|18 zVlMub38@Rm{lWw%bR^sdnRX;3s#ryfVc<0$4)$k0c@;|YsXmEW_v zqI6c*aqv8rc^0$uu_o8(iv{V&ct(KI8NqZAOpDQ`#AuTkhnT5P6Q>pA>r=4j8kuPL zl_rxO%sPXyqIAZ(0Ic(3v^fk^%-rXNCWrZRO#KDW=V|7St#={ALitaz=EWj&Ut?tM z}MnbY4$ zAaKz^UY7FEg4ovHCBQza`Om*#w}k zI#J9sN@t#<;n~YPpNHo-RSJAhJbOjY{9(BDm}ivEJjcVc-><#GoJ)RvZ2Ul+`{CSp z67nl}J)Vq{kS8J6cM9-t05tMz4H!U?V1PzJ01a#aUUdr43;>CKttkVz&1MH0fy5wy zrZxa?I0bkM04Y`veb#z9%A#^G39fb|7q5|*ql5Qv3jD26Oq zUpn=e3y;0OA0Hw1K^aW6Fzm~^<#3idYAZD>8 zEAPQT{TL8RXFx*%G}x~VWI*DQH8==p;DdqiECjk_p>zf`5rd?2MD_$PSzG9Qjji`IYaEpS zv~fhN3&1+Zn1m(k90IY048@Qo>!MSS*WmGrU%Sklic8iNc-_I4tji_>(CnZgz}9=6 zg#e|q5ZnXM9lv&q0f|f29YCyMOV+Ii1KnppD4hX46o+qI~um;m%8t0eP`(wXN+;kh*PEG${2MbCWJD$6{h zbmqA{JUnws7629Fw5J$=uw+#X0(i;>Kz0gH z832{yG?f7eOID>I0M!Pdic^3W0Z^5B7nZE5@EFwZdE-a2#z*O_@oT|zjX13ub1p1d zHR6mD>Z{vT+86Ql(O(G#Hh4I@rc@7Q_|Fz+Y}@BK)e-BL?``3d+Kx zJPMT3j6?jIzO>1$&`ruR?bLPoDJM-kd?%e09Q-RuO5 zhMv+FJ@)o|H5-xncBbqGp*9d63Th7qwVFi1y*2+((AokXggQTGYT9_rVNr*g24&<; z(-2(sgW4lOO(QP;ZTb2(oJSa{W&`5}P9x$&8984(_2OKj`A2#S`!ENR(xxlsyTKaccYdJwRWV&y$#Bz@>Y>L?>ue;Vp3LG8()){PkWx8GCvWdm=& zKZ!G^^@W7J{obu~&Q#(=89C>(;OrUH(g~7(>%AwCxP-1a-8Mb|{F9#I=|^8CA)$-} zsg{vp4+7FlL2V!*@fU<%0@8WCmDmNLfjDzfKNEUE=(3S@;^=#YkWfaBGz>_E#KT<- zDnxr+hIshJpy6)R#z1XUP%9!q{zA|wDBhq8K}9xoklZk;j-&5YsyfQZt3DYp6NB1# zg5fU$O$5MMx(GDBbePu&24&uwk$3j{P<=0`?IvOFBF}q4>mtu?9)Vrt+3QC7Lr5PCYWqo= zyTEf03;j@xt&$5o`vnLe{e6UEcO`r7O!idmB%#E$<&Dkog50D?_TagDVtx(AtZRl3 zJ`Km`St{VB3T+$cj~`F=+*|xBIEJeYjSof1ai^i~sm4wYu5$N7!wctEC_bq-T?70+ zUfVFKPA0f`j+nk*bhrDAw^H?om0NX|I^#}|H*Wk_cL&h<A5bl@oTuqhGIA-O|PzW2)W9uRr)`Oe%2W`<@F{UZi`ggt74|R^Jjqu5yTBI5J zWNo8Kbh`+eysch(#CZ-4OCb zh&qG&TAQ4H-#) z#V33GdVj^EzoL`y)$K`|lw@4|NcP~bsveEGDJkYbeHQ8;KXe?(#buJH3H6cudj*WR z=EYKyIYAx!vV4*;umi<6!K$Q-E10JfV_s`QdiSCFA)zF`!yGlxD!6K824*c3{J)He zl1Trhggz#cJxL*K=9n=@tJMrGI!D(=rII}@(X*&@vZoc1VY=ye11YPYYi)F&{xE{+ z28ze@?t2{Fw+++nwj`~h)qQP~J?)Y`$;A~}UzF6Y_%^-MYQ|MJ+q{F#$TVmGBS`$y z{9ge7lYF=9&>c}D_$GTgg?N@sC@cJZX86t_Mj?~Sn%gz>KwV;HTHP+|qkc$bT!O^G z3>6Zfq!Llaye+9-NN7jhCSv>9%D%#n>`J+Wgp`B0shorvkC}#%SWr`+X;rL=OwMSg;VMmPpOPfiHXOU_juosW;X%h0 zDm;?j@*%xrw!b+|Y9ny6r$=$+khS3cIMr;#bhnL|5p!FT(T>zEJv&GFYN93-zgI{z znS8`yP2p!l49wwewi1QQ{QrN@CVP5^FqxBq8?et|n4pTuo-EtQ?PDx8`UH+(sp*^S z${BJ37cw@vl@O|^`$)Y~wYk;MPpv;n zhxuEt1{_*{v>qgeTNMk&;2c)QcvRccdR4~=XC^Ldbu1Xm8_^1BGzN{ff^oW>U~B*X zauyVf=h+-)cfkahV9cS~X!nV_y+IT*-3un^CS^K%YU`skf>pC%3IZVdYbf;9)A&DD z(EV6J14-JWNm?^&5jE~|2Mhg{8O4uc04!DG+ELF>!?~DdNyPzu)apCEC(4}ow-pu6 z)l=?*>4rc|Qb@=8TA@E%BuV;7-K8-OkJrY@;v_wc8BC39X;goPsbEBHq6dw66kbS} z8tWjj^D8e=8z3Ef+=qa*;nF!8qBG%yanl~BEYevxg=c1)h5jYNF|Ct|o1r>$D_Hn? z8iuR|MHGgT$v+pCXcvyZE#f{F&X1F!{CdsGlvU#%rCTl*HT#O~Tz(npQZ<{nQuk^5at;SR5DTvYZtwqhkwFogxH;p|!6 zu5qs@SREGZA?IKZiaZ-I&qtg+HIZi=Jk7>zEHY`vg8RZu*j!6wCXb3t+A@E zJ}%yIuF>0~UTf$v=%AJu3=b#%FCmH$-#R!@$pTi3GgcZFO*%?cThX0uTQ70_!la_r0X7Y&0#LJ|c0GL}! z8i{-Y%qPJYwx32BSxLOe^D*Yx%GtAp$g?B!Om_BcC-UsZJiCZYo@ORbiA;LJ#BA*z zKBuhYDP!QJiQM}#g+BIi@tkvwGDX4u!-75U?AhP0ktYgP$buC(2OA{v9L+q7oIQt& zJSV`@Y|ODDlPN6tq%adU*Jd!2*F`1^naTW8dTp*g>1x{jBl6tKJl_+U z9AYLPh)h0(iP_p8`<<4O?#947EOP&jDST}o7hgKp=nGM>Us$l8ojrfDYy2PzcAf=0 z>m2Ni$nzTWyzK0GQRG=B-fGMnB9oh8VqQ#$ju*_e3e4mmB9l9rNtJkUuiYN+w3PHP zdh|9?Xqkn+Pj?T0fuqk^kEdFgH=CI?60GV~OW>>5)0(^wG7~kywv@;sue!{uR)Pao zwiP{=?2M(PG5%u??gn9Tb1ZuwGifR^2{7pd0CP)8yvU~w^J$q7wv;?;v|y6Rvm^6N zcJ^#1@_dqc{>$03i^%gC=J{`tNl#|dLu8T-6SK9SOK=*Lxkkk^MeYNcLVx?X$aAhy zKT)tDEZ8f~o-f-qUK9lz&4Lv<2OBQ(oWwlGJ9~~5c}|0;*_cyACbL=a8DS=Dt}S3D zb44aAn90&odTp^j>13I|9~Ha(h7P(K9>b%4ngX zTQML#%bgyM)5g5723NE3?hZ&<&xTyFEwW5h7XAK!lpbO+*@%6g$gd9bdx-ZdF#H}A z`88mEk2v{hBELB1*H~oIjG6dECP^?c8zc~ra{A|o)Yn{&9u4zcV71fZ%(Jz#XG@W1 zN9LLA?AcD_`7c(X&S563`<`aOpF(qHNyE#~^>)?cc|zpWlR5Q(Q%+h|R>+uIVf5cK zBH!m3Q-1hpTw{3l4Iho`ttK4AWM2%6zR@xn#-b15N5@tpc7e$6RpvK}_giK76^Z;_ zV}28z{Kkv?W-!0kMJ98Z$t;n{n=mm);~UN+V}6+DHmjXhGS6kso=ZfY>zU^oXV29l z&&{kt8^cUk_w8W8-$8Toqw#H#(_ZHE9-P8P<4&Xhc8PpXGNzxxN8|g3=kf5-xZi5R z-QiR&aiT5hKP>Y4ig|sJ z=#cdPWJNztcE;v^0{=1l^M|mwCoKD4naN3!$sbJmcK~xq|7nrWRpxUkF)Zo-)@Z>$ zMV`??YX*3Nj-EF}o)wtqKb$>p4)R^X8lf`tyiH_sH#4a!GLd0ow)TBNr=o!;W40EV zbYQ{Tg_*Fq)`gjL6q%$llax|=?a821(tq0M(Qcy9nJjcq-97yJfj(zFp7bzpHYi_V z-Y>zM%kIw`o&$qnN&iKhHs<|sxSEYu800sM%a+NjEc&P*x6#}%Vi$@0USoa}dB3xU z-*}PVEao@e$?tWM-vZ`0S7fr7nJg5Utb&QzAj^Y}8{5(_PY*sGXEfyo=DF6{^DU9* zR_3|c*>jV~b0@3NwlEXceS2B(_t2dD#_s)AAKA6_bx zBxPmbRkZ#}N&oaxO^-)PlJfF%ZGk*xZb}NPkNyFlicuA#L3ukAqM%USR48*FDb=9= z-%q7Xr9!1jWlf{hiEgtKRTL3bNsOF)vBj{Yd83}-RGJY zk8fN*s`sMoXne>n=u7F6myw&7GB6`IXJATFM&5JzIek;QX6E%z%j%NRGgIr6mY1KA zo6;ibaji|8lz~kerF6{5%1F!0NXhBmJ0-bqMs{9aR@=<(ArI^IP46z9JA1cubJbf$ zD5I5;$}x3=vRT=roK|-!N0kqh50!(;C+a2TnsP-spbk@u)ZS55WVL4B{K5)zE6lI3 zpu+DJ3gn^kD0!?rNuDLol^4j1b%FYZx=?*nU92uqm#WLv)#_Sxqqc{FQ z>SyXP^=I{z`ipv6J+EF+FRS+ywDw5SdeCl=*MoP1ya~r*95>^*#o*r}Z$&NM!Eqao z+i~21<4zoR8Fkwwzl$2ahvOa`-^Xz;j{9)jkK+e89>DRSJY7D7M<2@T) z%*Qx$6lXrcnNM-%Go1MxXTHFhW8nG{dSBt0ukp+`c;;I?_Z^-+j_1C|b3ef9M_By? zs}r#L8CEA@bqZF$!0K06{RXSkusQ>)-(htYR_9>#2dvJ+>H@6(gw;h@U4qqRSY3hD zRe6GZ4VKqo`4=p2z_LL3Qy#2bl!qvnUd!OM99}En zwNjZPuTrMUtCiQ~x0Gq}8fCh?7LnE=(t1SNfJhq=X%iw9BhqGNv9blfZ!5dxt%&#z zB5p&(?TEMo5qBcuE@hRnTUo8VtGuPWr>s%-C~KAX5pgdf?nA`=i1+~_9zeu{hU%YpsayQZ)wlgC)Zq`WR7X6#O5N&Tt-j-bOD%eMjXLt-wdywi zI(5{;>($W@Z&0`UH>x}Qo76E67pt$zo7GR1E$UeLZFQWyRUI#bR^Fygl((ysMZ$)x?BEO-6kJ}%_r)0K^&H`ib(r`mX$g`iA_Yx={W}T_m4S-;{rb#z}Rtd`dkk|Dv9he^r;r zzaiFX^@ef=zrU-?`JB2!{zF|UpI4{L7u0p~pXw_4qPkkXq#l$nt7qja>ihCl z^_qN5T_ayt*UEpv=3eQ}f?MyDq}!V7uTAP@rf=*Q?YVJ7lA@&MJu}ks>&3>7mn8ft zxqhZzdTvIK`~ex*w6MS7jAxMkko&3EBQxuPp1q87WpIr04AxD#AH$|smT@i$$0*M| z*o65X!v-6*{-f`bQJ#Mok3$cJO~yduR9V9&vtQ`*`eVZ;?*-#DHfh9(eaQGv$ic8l z?{1vA*|1rxn{q!o!y^rv#Cq$??5BQXueWK_Mvdc|vQx%``mwQ1nlzE+hTf))8yjby zxkZw0-0(>0!(W{9WNO@BYbz}Ld|A8YGd|g%#&p_Q7k{u&rNYgU{@l&@;|IKoGJZna zTR)+<_QT<=c}pd;j@0J5T>)&ChS@cjDm6FiN$sxNJy=na>gXL1^26+??e(YhQ2Gb$ zLVuVYwZHycw`U|t|JY{e53{2_(4V_fQ<4_<4YiUaW=H*?KbwJ0oj=)bhbGnZ;hLG1 zk?T{DKXu5>>6M$-M{bETd2+3RaZPHcw9D*~o0FH*Gha3{DY;XA|Mbk9lm@Z&y(z(* zK7IOUXXd|<(lwaUIVUG8FQr{4JgncSUW2Cf8hGp1k4@>GnVr%)CojKSToWVb>d~NH zdRCSyW41_I{tJCG(lfIpt>=HAzvY;TT1t=H7y9Psq@?E=zo`TIIF$_nVFy5y?4w0*|0JnC#B`5 z;c?FYFsTHm!H8TFk<3v`HN5*C9PKtyjDL`50WWp+EJ5LFx9E z_g$^p$di|ZerSNvTcujT#(t85v3z&eidd=cuA{G4cNdh!U!y?xSbq<{Ggdl{5Z)Ii*+Kr~$po zzjQL=NaaRt6B~D82 z(4u{(PHj{3o=eTk&@Xl1A_7)kAC|viDqieKANvy9B;!mkb3rUG^$r-#lA4#FYB>ix zb?(@veJfaPwyX{$B4UefslhzLh@nkT zk(wZf3y_|X(buqIIEjcd)`&9Lk0=9jGSgGp-z!N4_3$))qUUpA(2=P<`t(huKY=lO zv<*zh>CDSG+swRF9XlhPRW2Ha<8{NSoMGOxnLSI!M;#bVFu2}nZjA!;VNx=>JGEt( z_CfTG1$T~X$zFg<&v`yOH7h3#qGil}oP~H3jd)*{46ha)JEoc=D>W&A&kRTfAHobj z<)unKw1y>&FR8@E@DPmN6Tuqs>^+v$$&h2Ny56KAdDw?XeH%K7Eb$l?v`K z`?9>WIkYK)$?ZB&LsVr3aUs-Hvygdlr)8HH%z8GpU5j?9>HYikLC#ljHw~8o9BXDa zuD9f~j%$hvP1if_BG=&hXeeoLYd$Q5@eJL#BNsBee;*c49|$vz+INVvS`Yjo!1|ZL z7~L_H4Nj+Lzd|phhIJ;Z+Wl6HswLBeHLXJRKFHNb?`hUY<3Kszpe(1$SfJFpRs%jj zfjqeV04e$5p> z<)vLA!zIwEH9|j6p{H}9`{wjz>w!M+78{XsF-EXE>B}%i3Y@Qz^ElqQf8MjKNA=Zm z3B04f;@T6}xN|cz@OsEv1gF4msczSWi!~rEtAB|R5_V~sfwChpWT6MiHzrAWsV%F$ zF>YA5vI$YeK8@`ID0&!2p>F|Pjg}h_ZJ1W4&e(5&L9ai`OP?9Nh)d#`*}YQJky)bA z@H};7d8uE}Y{4@Y_rCDi9wF?<7Z1sG` z*^t%1Yc={thvhh={e9G8H`&*W{&{J=L@UP@y;5iR*6H6TH8Ve>kN*Br$$s~?QLS|j z5c-Qk+FTgy+aaq(YHO?)w7E31YO|6}fRc1f|Eo)5t!dAmL?edO(b}UIa-ERgzhuRU zM~HXyDjngfM0=05VoZe9Hlsd0oLWCb(Q4IHPBC=+R6(rmh=pqn(rr%_6zDbhfA;fV zeevLO+!@38stDt|d$-25)V9Q#-&Wr-&b;ktS=6a`OC0Y1=y1p7cjC-%C_wplzt4hK z-VNoQaoTng?-EB}+E!jy-x-ImBH;8aiFS&GLkhyJXDJ?_OMpqi;VEpmaxYD30!wk!H!)fP7p1yIGmoha`s5 zo!G~y?qRBKk2v$&0u{Zshtb|M^nOSE@$E8WEf%8+G_5gsKC-6qWq8_8>~lPKL0l=ZgMqP*q`J(VMf z@`g`Uj^HLDKA-1gBxO`5<}#+=FII)$|&6__l0t{SIZ)CK6B4z z>spqL15CS(R2D~HKf*!j4rc&x@`;7d-1E^n2lX+7?!tZC&HLLOG6-<=Jx>HE-4VR# z6=m)vVlR;xN_S!fsO})DE|<9vLVF+5`#mgkAM93f7!(Uhk;~i*1&YJnDvp8TD6dvT zqI~8)ijA-$n?5(fUZo~S>8{Bq181UF8&5cV<~|V+yY*&gnfv(Cv0fuAl2cN6j)(`C*yz>P69kvJZ^YvGp}sh>%zeF$%FJ{& zyT#ZAj2&KWn^)UPBwXgcgH7mdAmHcHRvVK!YIjo;p>)?o2f()9tL^n_dx(wC-1pm% z_A=Z(HaKn|9VAAS?ifD-+>Bku&KR#?@_kUQ=F{#WaXxde=CdxK++*i3Zs6jpK_DpIfz$+uLKJ+?uAo~! z*GEfe&i;jwv*YM{fCx~!BdFyQxm9cc z#aL40a`sq(VnerzUMM#8X^lyg&)J)@vDMh7kM~ha~K=^F^ zQOFl^*V&tifD#D^r8}U<0My#2wIm=ePj7AGX=&%dyp(*86AnsuI30o0!Kbw+94=4q zV8dxI!0ALdDBa<715Q_B;q&yac4>2{JVDwh-Dy7!?G)1HGxQXZb}DJ3bf?`D+UY*6 zJIQmoc{&!sW4OE9(3Ns=cN>YB#q@Fu&=&yNJ}t|q^(F=`E6-+AHVXv&oat?2GE>Zc z)Ho>JHO_y)HqfUH@M-zP#%JXNZAb$cZoVDP95yc!9ZGj}g`gYk(_SGoE*~FkBYVZp zV@&9wgoDx@&S>C_^l2jqhs(!D+Hgh)aK;c0N_RLDfHRI*xO{w^P1zjD6WuCKf#PIR zS0B0iMv_*Q{$g-=^XaC{EFB0SkEUS=C3NCiJPa&R1ds|gF` z-^FTy&%HctTsa@%Z>bIQJLKQP{6&S|ION|&elzn&8M*3MsE+Y#qez&~y~p^i+eIj^=W=l&RrrjorF+EE;Jj} zoJrN>^6i;u-R~Uo?Ky7L7C>ztsd2gXJb~I9Zq$}SZLwclM1p*ty_k)oMK*29vzJi= zql~u(tN(KQUtS>U{FR5vjs54er+ScaQStyjb)>q#n_JDCKQyB zqwE684!^dIP`KQBhYe+$0A)9!po|=4FHrUn2cK8(vCEoE%s$dZ8M*Eu=pGVaYeJRDjf9q3^#q4}xq3oT;ZF|v^8E?sFhS`~ z`9UbxOwbe(=X2(o30BUm*f=n5el~Jf9DOl_gVG&NUEtIv7Cw8folrFNba?iB#vs7a z_b?HlbVm@IAj+Ui#Ojk6N_S$7QQd}AT`r4mi1t3?kVQ9ftLTGb94T^{beurZ?^ZDY z#YYpgW+cjI(~q(d*372Qjj%*&a+L0xybW+#C1@=OhtI290pe%9+1V#eT9l6U7-6Aw zht&~S9TK$mgvDjp9c)zXZB%AP(}{3Uy2E)AINcJou7ty7+1+e7T?IH#5e`asIL`p* zX=33s?Wb+h+^|U_0+j9udV(OG2>6^ky>xT0SQ`uf|g4pTpm7vP3U|O@N+5G#$=A#7pRF)x@)2#U@J(_1|?`O z5gVV27ub*nG2EAIaNIyDBu13(7)OI~WP&z=0J*Guq>XQcjmm7YF@%HC9nK`+Oi0ki z5e}D`Pq5*P6W~lH9F*>GrU7Rvv2fY>RGYFno~OH2oDId9q{wCHGok2|dd;D_qI6f+ z1yG(x%6yhS&nAtrSdxCcK?Eq>5v%~gvIK2Og7zkH@R|BDepx}jz659f)E64|Ns~8A zXI)9GDBZDc1nc?)Z7qTFnfvbw2`^v=-WhCDE}_j`sT>o-?cLLI|41W z$^q@xfSJ7SZ;sFUU&2S%2k9SOuZ&Nm7b+0GYJ58Ss$6_4&J5SjTrtjEk@Y`5EK>Bp zbi~nDHDIRoDBWRI1J*snbg;Sk$A{x}qACN_S0A2SBv~S_}bwW&usrfocJwKnKE~ z0mhULRF{BIx&vwepxA&`kAS}7fMP>{>Xi=EkbqFS1BwGs6QX&qx%rpL)AZJ9VgoRD z9WN=Pbf?@5%6?Kl1LZ_jDwwS+`+4OV3jVSJPx=x_8KpbrBq%2awB{u437B(Zo-UpU z@t<)q0*B(}c)S1;wQz=_&l7-{`%MeC0FMKpO+af!05^pKv-sa7N8>lIs~-# z1aOU32crc#gaEV`0CaK-@Gk&#A@y^io!kCXgTT|ONf!wP+4cvBy5I2NY~FnUFZ zamd=To(D$%fYy&N_${kHIM(PKY|HA0Gwby;pX zte4Ob8%u@->yKC5Dh`8UVL%&9qWqRs2-U5$Wev6wV32M#ngB<9EXLfmQMzk_R{=CS zpp7ITe#;sSh*h*@jVv8#ECHc(2lN_%CIz$!1jKJylR|(dlnyk7fKa*vngO6`M8j=a z(`*3dmNk==s}p0G0=|r3AojS<6EJmI?q?xdm7cfVBbbEdt=SthFHkZwUZ4xCPh@fK8;% zZCRV37_v68&fh|vkJ4S|?||~QfVP#yxh-oO+p@Ou7;K5$=~jL(m)Ev1hnr7gWs}Ffa86ggKb&guTvhQlhzsqI3szb0XexP1K_BEs(c& zl4AHRt88KkP!t~XeZ;j;IRZlI4yYo4$`cK@WtF!9m|NDZq>R#?a%Cu2B4uvNs>Ca^ zRjUdqqjaZy50vjp)T)v=w`JW0acj$}ipQVn^CWD`y4Nj$41gMmT6F^8wyYW<0M!Km zid%q(0PtXZbj z1j0em=e{`NAk@Cr$9veHpM6AakMi%feTnL)P(7Nc9U)=II^&Qmj^jJ%nz0_Ad|c9Br{x9l$i;9I?^#~K&3aXt59=}6ZI31#F+(ZQBlnV=>G z%`Ag^yS_{?oJhhMemIyrec7Oy^q`C!r2RVe4Qx2E47HvOj2k$Oi4SGue9ge;4{Bb5YMg|K^tsy#4+Z&Yad4 z6884{6Qy%LL!2lh=gb6Wub`Geko;Tky@13ebj2CA@d4nU^b}7&`g#)*%1DrE85#B~ zKzcc-y+BC(1)-OLbY5>Ic0uR`oVlo<3B4e6*~mI^^c4^i%E*z118FGna2JDyqCGA{ zJp5wN2sdi4LTz+V8%cuvg`m+;yg?U&M%vUta>J-Pj=r%}b(E1;{WZW$3ThJwhQA0j z2>@s5BG81=VWtoa%E)160cJ)}n?^AF1)v!rFw;thnN2V#BZpZ4n0Z9PUHqA66E}B} zH%Jv_Yi1NG>r{7XrzYp}5I4SQr+?ayypj}W7@6Q`IOn;Y|?2MB#)Aid< z88<=pNckSmc9GY9=JkG@q~FRREf;qNiMFEOYeoN%>Xy4_rqavt6BD6Fq2P3 zCf_mXuK~>Aekt-f$$Wl_lgt}|Sg87~YCN7FM4soE=NV_u-$b5QnCC@j&kG_?$!qo6 zb&<(U%p}UocPwklTVZ0hc6qPFZcb6sM~%?t9?w5S?sqeVs$Sc;sN!{O#oI-}R2J-h zXV3fW8r4L>>at+9oP))PJR364SZB|AB2O;{b43-t_7J%bCF3qX7X4m zz1G@`N!RxUy7`$klv^1++ENtyUo3QI-Q8)vNM*F!T68aAA`c;>Nh_%OolU)LXpX4vzg}%XU}OO&qd60fwSj4k>_&exkO~LhMBAqnQVrM+1eW&2c>=^S&wJE z$bC0c*kK<0ML|zXtFU1M#2`hSSvNNRW;Xh`7)D4UKq-EcbnZ$}r zd`!A2fVrilvB)Qp`8?_i+fSp6tfZO9^Ks_c+S#+E$g>mk?BML#UgY@%^Xw`zNo6J} zB9mS)FbiXU`EL&x!Cf8*`kU#F?w{4DD-L; zdWC4tdOXX*yxGhw@>>hhFh9SPq*{}A95Wf?w=E^3L|(5kuZez#748`;`gF20mXbO6 zkJ%qH!{Vk{_HQtgc_Nc#OnNbZxus;0$Y(9{S?zaRN>++I-)5f0&Yl}Zp1Yan4rkA8 zBF}xybC1a6LuPV7WbzqI%+@~YcUnri8w2l%$o)7|_{KgizH+Y7F;TEzS+JANo+s=Y zKZ=4~V8PBg2m4**d7XJ)arV3<@{EeN8dHkrClVXF!sc2A>fN7URj+yi-vT|Y$s5B=Y9`p0 z5=G?oF!QRN;DD8FMXyhG#!}J*|1k%5!?3tHmc5^u#EDE2ne?Lo=9ZFXBA>^YPpgEm zrQ}(o1zU(bJ2B4=&YtZ>o=-8)ZqA-vMV@KQ^J$SuFJ_W1GRc97+1gnNPJ=SnsCaLY z`wL8AfPGx#JJ%>z6s(X1D{%H4WY>5}6l@F&HqtrR2$APx<~hOHbDYR?Iy}wBoGLPz z!-CHYGhuV>4Q4V=WU`W(EGwngmgtktmX!=Jdh|_E=uIs2deNNqc-Dq_vzb{nU@aw; z15%Hk*&$a(3k}^{1JbkH>ESqS%=_waH5>1qfRy!Y$Q9cn%cLfYE(fIa5R1u1>>47! zy3DT@?^j^>#fbbGGQU_Szj`7+FY{|6GD%=2evwHFn3xTc7?5)M=ZDnST#lNDc`mTp zsV(zt3X~B@jNMV>cyPW;gpk> zl@&6kRv7)4Ch{G~nEHp0#x;g#zwptx-fF^EnCweo(KlKq!&&q~espX#Vh~_32Toz5ai`ILyG6dI7}JUH(fGdM z`F;3k+;27EStffrEcyY<!{#lFt_y=(Yg75SB8eq|H6wb=BF zO61pY#(69AD=#vs!b~cOOzwq=IU4UubX*&&hIxKwwUfd;YdCvW7kSoVo)0>E))aYa ztU`6dOjxrtV!`X9Ir-7}h{!3PIeFm}HX4r^{ntd~`w?S0n8+vnUt3M}88bPWXiNH! zh`hdLUdIw0lK!8p=--o_vHAau|Cs&xV_4i1mi=$czTEqGDnSvF|RoH9X2PbtVZEUQXI=6Q>=XE~8)73NtLT~LOrciLHZEeEYxIC9SYsBffwO0?cMj$idA4MpL1)i^$g?dx z&BkmaGWjP9-agEP&9$z~q?5?x8D{eDQhM#Fpi|O++UU_IM4@}L(7kl`@aqTqob`Az z!o1mVE@0j-!<)rxGS79+ zo@+#&?=a6T&Ys00&t0rS+rvy)_w8fB_nGQ4UjMYLE*U*DwLWQi`5Cz>Es`GB+O$a-*rZWP$Be9uw7iUzobJ6-lKW<4=jCO! z&FmiXuwLKv?$WulcS|={{l^Gpv@%k8L*1ZkRyHYX)m_R_oveNCOBzOK$v=cx14H`EpC zDs{EGRxMUHt6SB33MzOcX+88d$m^lFLEeO8F^-#Y++q-Hk+*{59UQmexE;qGIPS!8 zmqE8neiw}I;kXCK_i@~d<31esIAHQhSf<} zor2Xbu=*8NzrpG>tj@sdcUYZ;)j3%G0ju+{x&W&`VRaE!mtb`nR##wkRh}SUgXMKt z{sqe$uq;silm{yps!ULZp$~^Elavw4WTi-X4gESr8Kq2x$LsKzro5_5SH>zc;4u>( zv*0ls9&_L^7asHAF&`ca;PD1L7Q$l@Jl<4R%8TK(1YS$wwG3X%;k5!@E0rnoDrKs? zT6tZ5OPMCGQKrjl5osMFtw*E{h_n%rHX%|mB5hU{D_ijUwz5m!iiqzZ;x1thUi}+`d5hlHKKom=-(pxcZhx*(Z5IZ9}xXV zME?oVPayiwh<;KztejGgD8C^3uZaE|qMt_eGl>2>qMt?dbBO*2qMt|f3yA(FqF+Sx zONf3M(XSx-RYbpr=+~9u@?ZG90hI#vgfdwDSs9|9R0`Eo%24$eWtjS^JY4-$8KI7q zi_~%QNOinCN}V8&Rwv41)JgKI>TmK`b+SB8eN7&(PLU_5Q{{>3>+&RZnmk!Oq`U^( zDe8OjRP`#Bgloz){7zSA$TQTL@=SG>JWJgs&&G3e)a%Mz{LWK^!2EJ?6 z8_GKTu2+}I8`S0UMs zD0`uR>q~r;#}>x4 z$rxzZlr?O+J!AYQ8xIYe^zO#vn+=-`JskI=Gu-k>gC_Nx z#>wobeq*n!Torj5PEnP+a1q#HLpQu^>0=RBDj_t)AA z3qN1hZuyK)HmEV3c0MvglB!g=S<;^?KV6cL%@{wS4X&TioBQGLcDSXI*$~v|y4_IN zEDf`3E>&tC+VHxa-t6`C9tinicGUR#Q+lXQ78KbsJL&-awBG#sJMp1E%#J!ie@^d$ z<$Xh~B#GHkN9fP$-LPn~-40Ev>EkssDdt&iLiXY%A)1LK<1PHC6f zBR3~6r)R!w<^gi2{Ql{gIVlZd>w8mzIeq%{&(6$$A*E|DrE^YBR$fZGPIy?qQN0FD z>oxG!uOFMzJu^F{bxvM>x40%o#?Yfdz4WXsRmOCYwEP$PW~66kNm|eUKKsZq(~OiJ zxi9q1&q+zoGk#N_&&+Pvpk5D2OV7!Zv?ntq?O#$O9J)ywQjpxfcqX|Qe(_{-_Xd*I zqBS11OOmu!FGyO;%>3l;y<7IrhL!m^DJ?$@k8}QqNfAhi64?@Br~eOQm*ieX!lkv! zYuKP^lQ`6{LwaUfuXg?OF~DL&f9m7q-0dyzyIQr8Coc(o(Eua3O0|NG{UinB`R=Y2 zv0U9S z?uO93uJ1)x9Da4By6zLT*6ha;qEq6eVfwpZE1Hs2r z*?WFc!A*FngrDf+&6#}L)~V(Tsv$S)+muwW1c62XAbJ$X*fTRbJr%QQxF=e-E2sst zBHip77YidgKQ9$SL$cz{h2couFpZ0so$-8Xc7Ofd8>;wyup6b@y~hPaU*+U7)z@J( zS~ptE1{FXmR)c`sRZsE*OI*em!9){c4}5m8br&O{WuHp zCK~a+EE!%cI(AGoM^hD;3;f_GNi#b7)fpliPKmhN#L6;zFpYW+C(9PRlMY znDuOGyB6(I)BE@7gT$}kZW=BFIM&Q;TrtRJ9oG~Unyz=;MXtg1(NNOh)_hn9;~Bbf zM=oS`|2{09J`iRaweJvTwI29GfbX+_hqA%x^z2vYh19UlWL3N0icz&>ny{u-sNM&; z8tFaF`e+;|=NpvebQuejTGwj82PlvSUqwbM9)@dnPI?B`F{ia+krDD(APgIQaTJ31 ziSEHQ9LJ>3{WpyOD_G01ai{-*6Mo7|yF!Lbpi^svex5>4=R)_*>C4swecmlLBIja^ zV0Y4&VT=?wUnA#nymSA&XIYQxtK|}SM}Nh&XKqG*Ze|8v6j_Vl6xc1*?YeNW2Bc;6 zFEK*WE-f=qb|i)@^dR}hBq=YoWwkfP4eM4mA*$G?v3&qV5928GEr6@has#3b)9Tb2 z`wcMYHAs2sGou&tP|56Gsp-fq(P(&{I zn;T8&2EWOm>FEtwJgwS=j25V~bv? zGkojx?~|IDpV23e+wa~ssL+v<+`>bt=!&i^%H+~voe2df&8Q(h}$d`QY#F^jFg!1qH ztu(K^8_GN5wCyC$e>vOEIP05vw%a(s^m_&U{t!6&-X$EA?r`=2=Y3+~zo6~?xT2xc z^*ek_2>F7x8OD9qaP;jb0+j9u4#kPSq^(5kLlQ&jPV8e;_b^qL`=YkPXzv+%zmGBc zeT;QGjH7N9KZoL{q{w|)+ouA>FWf4A3&pSFv@c1N|H8Jf*$Dg6rq7MA@2JU9x@+>E zf%8+G_5L&U*2}nhI2uHbA@nFy2H5voa@BGe}UU|n>06UBrkn^uh%6(S#L`% z%4@FB{Fk^zdBdkFM{pAnpmf&;6+uwmtNnu@xG!=m?=2d-PG20^7rFhzMrD2()~#+a z?gB5j1u7;Aa87y{(J)UB3{FUCe?Hd$T5LFo>s0dQiyT0O$yzSu3+ zhEq>~(~xjby2FVBP7`9`zTB;eP1zjJUbl+Ppy($>?hD@hP;^SY5~!{y-PJV_%FRic z|B|=nHffB-lJp};1Ss7Rv<1OqUahrPYe^jZ7ri~kFDv+>x7IkbM_*{R8(G+PxwvKN ztnG*ur90NHVD0SHIua=VWpAB<#U+Qu9c|+U(9@0ktl{YU7h$1{2>5a8&0o(NF7BY4p(%G^uDULrA+?!*dE-9c1cE^{A*_CBQddsyZ^ z*sbC)C>D|;m$?@T6o&?zG_wl7;y+&9l-C@lF)(o#Ujj*`PeTI!{nvKfb&}S14N_RL5fwRD?%_AHx zb6;S?nJ2(mL^vqj;Vc8r5@O*q_a!!IZrCg*0+j9u-U7iYBH%OkRizWGAp(@{2#P_l z(W|W|2rhHqh{f?keQ{)&`+6IdndxkHi?ItBJG|O9ueOy)xXgVAo6y@pz|W8^Q^2 zo*+dob3Xw^r_}2d)fJ_?x}JveucXXp?!VfkF&0bGk26Go(jCDi5d7)Y&U>|U#KC9o zfAY%;GWYX1^O3&Lu+05j>8zKD6{S1YGQO6Y>S3ei+wc+1f@HWngCIVg3s9%bj#=ZXbH{Pzc6xk9DNTE0ZMlSwS1zSy+o`w ziJ^2SrlGoZsk&UwUKcI>h2G;~IeR^~iVdI`ONw019xG66=vL7S#il;3F^Tdyds8;H z8r$^oP7ZF1?ekG%qjcBU0f0Q})0zsBXBzSwDyF<<>?)4IPC>Eod^e|JDhI7=}Ihop5E0iZ4Q+u zNE@X)?WdugLfU+Wo+8ptC2f@Mw0lB3-KTXYc`i3k$0B$P_uU?fzbNQ#BQdj>UTy*U z0wCL`W%;z;#K2|c*=)*Yfq5i@tbc21`D}=`7P`bkz4V;laZ3N+P`S?g1&Ikd{ z7{Wp64rc;z#t{pbkB_q{n85vqQ7Y9x8ZsB zcShcgqwh6RM;W>LG`}e4E)kkeLMS5_nvH7Cq-t{c_DrOXy%cy}-M&7_{0I}Mytt1FO$6gI-K3`ZVf>}#2 zC?kj20+?dIwvk}C{JPl2veC|BY{zdC3d+b)b^&FFU)x3~TyDL?hO$k7vYSv)Mvk%< zD0_&5&#U*?Wz8jKAL*iuT=x)k50EaOQy&oNen`3~BiH>Dx<~!m5t8Qe>7!WOj#EB; z#71FeA)mPs{|@5c__eS6+A-4Sa_Mi_wEPO{{M}C>vqTZ2H^?OQa@8>8{D! z0H;-g)`D>Oyt)-2e%70vebS^w=~#~u7D{(m9f8#$L2FM~T!!7jM%CU%Wo9&;2nVG* zoF{?PEkWx_I9!(9&4$xefb$gLpmc}x3~-(%7CzH{+9u5nn=~Ro>5iZ$2-1mw&$-h} zC+I~4DBTfcgCHwG>rD_`_ML^r@tnRmvQL`ywo#cmc#d0)fxsA$pyelMxkSR{;RD!& z&IbWMmvU`P=BRyvnh2%4CK>{^f&^_)g7y-z@ws?`4QUX=eaQyL4WvS1MCp!kG#E!F zXd?)a%gRUE_(s^M%qAN{I4IrWOajh?1Z^DQaGCi88_qZZ&Sb(t=?-TaaHbLqmz__w zDVyVYx?9EBP@GAMT!uaqicYE59I7iycXeF=<$0vcXX*27(in>+>Bk#HfYKeo3J@$y z(3T`>mFj_ZVY}8u2B{_+!(yNTSXO$azLv=qWsOlWvEW3n}gS| z5nymnHktrOUrlNPl7ZxCJ!5CwFD@R-tp>Jku2cR&pQ6dTa$5fFcq z@YoQbdZhz3Bp{UTfZ_nuglM=Mg*UMQn7fXblu^1$#XXmPshfvLf;tPR3yB8{H9WzCcx+wA;uwV%X%Id z{R3J*!r-^8{@_@nb6hq42<)m{+z)5g>u0VQXRgR?F)KD2>otzPfz&xDBkCN6H3(QQ z5fis%y@ZC?s87X9#^1}c{&>Z$;xH%{2DHH>%5PbPP~A#f)?ga}Xto+nfFnK@WA550 z-8I3h02&?8MiLOeWsL^JD%!F}mJT$QfKa*vdJRC60@?%u;VL)3z;@pGNcUzJ%b|)_jSy*e$?H04xt^O9_D6vX+McEENE(atp8?0BZx*0Gmji+p;!6F=TCGoxg=TAEmp_-vQ-q0c|UZb6eInwq^5nb0lkfU#cV=sQK7gYxfo4v+Oauuc;bw`HA1LmbejV%U~-)~(`2C|(F?e~>7@ zWnF;k5!$l;un~afh|vT%`Yurupmf&+Hvn`!pj{;(e#^QJh<9nrx>`DrlxXguDBS_w zoQQW^6SXLO3*_ycq!@n7Dw|jW6otopA8{>Ij(||Q1F8t1@_0Z@n3xh<;>6hp>6>wJwm zAEmp_ZwTf3iP|G1&TU!s6RlTSkMJ05%WC9S-Vb?iqSl1uxh>0^h)@0N8w1<2ng}rB z|2{?|eEhYh@$uIWfpC!Yxi5}52(_>E@gDZ)XCG19qx`#VU!wXcRF5WVM@X1|EB|Ps z^;Z578v}U0HFgFZeV-8u%E(c^0?IMs;NQkSh93Ay?}5-iK09Hk@(Z(nAeh&Miv!C6l{R*{Hq{h87Kp;l0f32F}z1^3o`t)R69#6X>&GY{B!%n@3b zng(U$P16Wm4T4&1P^(8={M+&kY&fwDwVn-(8#s-L4`t+h&A{gmYF>il-jes**t|9( zv#AmY1!d$YEr1dXY5_vw-i{C2Pyzy!mV|;ba+Jq`(uO#=x8mE_RL!y5){R;RsI@0G z?rr$?P;*L|{z-L28F?MMK(!O8@^8U+vdLoHm81_{NgZY6>ZwrwcTjsOs69ap{M+yU z=9dk;{r(iroYof-_V)V|rE@+*oG2sb%minzpq4?9{9Et6fW#$q#TmBo0pOqX6i+|; zdJ_`LNRVn78TKncdO4`QKuG)rp_hSlUT-CKLFfgXxu~BBy&!bi$U1TK6%Z22$dQHv zX(;h<7lVePJuX8${9@1uH)^j!ZFEo@NrL=^pwUpgK^KBX+SEaE!>BrrzOhtwl#y5c zHNZ>?Y7+>CzX&u50B7kU(1g-qrVtFu$YEvyW=2q(Mlk#Zpcx@B(@KY#O)w}Uhgkra zc|^ip{F!GHH+PXYNEKz|s*9nzh*Y@?KZ|%(_S%05siKTrbrn=s1hr)(%w6~UG!P)MtlRr*9EmTB+gy%Sr;O{Mj*b?jrdlGZwYF}B+gyz*%BgNED(Rk zjrdN8ZzpB$LeF-ng{(WQvv*Nvql~<>_d<0~P5m|N zD5!lv(%c1}Ls;mCVr-RM;Q2s+aF|1g^1Ksg-6(xa9Dhgja+T=j#qTncopH8Xife~8@gW(rlkwsBF#>)497i-M^v*!|9)_t`b7iGtN-!D=}N zixGJ?WS+6kp7lhYUU-^~*+gWLz=He3OxRotGLz;alXlGHu~K@iwb$uZ^R0{?Z7B-< zFBZD9?jC-td40}$JRQTl*>LL3ynBV2w6i8}KW36`@6Ifd*YnIP-wCU|75yc$GnSIU z_>b8igTmq_TlT}5NukK(RVF?`j zxxm?Tp2%}K^IRe_S;I_LiA*-b#BA-2j)Ss;QStR6_uWikhkaaZbFR@=QLuw7*nVfv zy>^W~qF|r0U>`dNJ1p}2hIxMJ?D>Vr^GA4^jd@&Ta*72%5oW^X+8Ji@tH|UsGx@WW zUOVr&l>F1^(Q~5EQ9f&jl6($Ji9TmNp1;Dp+049)dEepVH!uCJ#K!!t!Az?8Y`f1r zBCiLSm*Rx=gcZFu*%?yx@E@~3>W0OA(z0*JOkzbQJ|^81z}!;OSmcw)d>-|M?Wa*j zR?G0bzMv*!qr=R|m#jX6$aGL;3N z9A?7i+Dv9LO=Pl&nJg%!*XHSyuI~$UOID=i<#0>#f)t}i=ZHeDW}#Pz=B&rFEX~L z2Sg^H!NhFsqkgBQq`NWjj)>fkGlg&LFjyJuJNNN*aa5soO7_> zMV{B0=M`tqOCryxc&jm`czz_nQ>_hLJ$O5 z1ldIdK~~uVA_^!9vIwFmih?47B8wuseE(Z@>ZWg3S6=9PpXbZ-q;9ABob&(P{d9Gw zntL@)2!oYtMsH4b`ce{yKa9cMG9+%EY47DG@pdMOT)G{Ag{7peozH{Zr(;6MQZi6) z!DKtnp4_v0c+YNjo{w_RzTrLl*ml%zu+es&Q@H2E@SYRwJZHeuXv}GLCUbf4 zSs^BTuD!`k=GmDn=O#SVS10gWfyt_553lI&bnNyL%jLStm!kClIlLG z|A1VnINHpHigewoK53wEdK6CU^S&NjjmE3vlX3>)tAtI@V$-A{k1qS9j3A3CdhGgk zeoeSvBhfFQ`^DJ#wd8)W;ryD~`MJ4YoSjJmH}Tq;B*VmLkVK!9H?%OQzQ%IYKE!jr z*-l-!XXo&q9ql}Oa?kGJJ-gX?_T?4o9b&?}FO3IJMRVrh>yqgLw(4>{V&{~_oigB* zm!6XoG^Up6{g-a%`!r`78af(R>7Gx9j>ffS6F$#np9zV+-ZUA-qZf&zW3wK6gq`1b z?l)HSTcP`nvGbeC{U(R=n`q}Zi~CKtGnvOt=Gd7mf{8I27la=f^FuthnC-NJdoB&{ z`L>3IaHr&Y#r;yQjSnt0$JKxVZ)1E{z=|5sN)gf+j zFwv6qAF%T}!o3bBhDrK=GNb=McKYW3GyX98^LR+y6Q=!XZgR@bGp=q%Z&hweGtACmN6#A$urkA|z!cq9GdhH=?68PB7S^$Q!# z4L$Z4JHM&iZ?fojPWPK==QoG@%?#%^-Ole#?l;fQWHC2cXlJq#CPsrS^M~EomV|h^ z?x3bz&pp?K_grP?`5yP&6yCGM&T|{D(EA}Ky!&?Y;5*Qq;>Px&ozs5qv=>ex8(TDL z>~eh?-nWWWNqxk3a&$lmmrFHYDK?`%E@gK;3PipUi%>07Xr!({O zo=#25EO??YZ%AsN?1G``IlVInWNU-d3koyyQbjj`)^swoWjDFJjbG4-kHUBnR8LNy@-c;8q8pYIU1(Q2A8Zr|ePY zs+W{&$`$1`wcXh&0ePhSk~~?SEx#_$mlw*5+P>YM5^b%nZ8U9Fa=8`aHfoj?_rB&~(sI(aP=*U1}jEWvRjj+=CXP4Z@Nyoci! z9N)+B101*FxJ{?qCVvRVk8s?9J+Sgfz_|DIt{DeV08voXJK^?R_9^$JFNbI)dg7n39E~+x&*7su(|@P ztMWwo8Z58F@-JB4fMr1WQy!sQlwVLT$wkU#d8Beheo?t9k5aCof3C~L%3tyr<%ax{ z5y8nednekJ<2;1CP1zcpV<|;PD1L=ELJncr1X&LU_ETESDF-YcaguhSw5!Err)I zcr90^$}5y<@=E13`5k4tyh@oNuSTRbh_n`w)*;e*MB0EzC5W_9S)^>j@4L!2c{3uu zhlpDc@qI-601>w$;x=W4vRzrJe5kyme59;Wb||Zrj}h?`MBIspyAbhHMBI&tdk}Fi zBJM-P&y*s0KYkA=o0ZQI`5+>Hf!{9?{Scymh3H=+`e8)>2GPGo^dpG=9io4a=tmL# z7^44x=szO*aYX+K(N7@y&xn3f*{_^Z4k*7M`mcz78qt44^fQQl7SYck`guhE9nt?l z^b3goC!$|O^h=0-8PTsG`c*`~hUnLoQSx8-y#bYgdO{hY{;a&9o>Yp|Q_4v77v)9u zWqFkPr7~I_FBhv5R#nl*iKbHlBcOxu_RnmrsH>pI#Zsh&XQ-Tv*p?97I_Yyo2y<|UdQh|^|<_o zI#-^Lb8o7DDGTtsP@N~grM@9AQs>Ky)i>q0)dlhrb)mdeeM?@Z9#EF6i{usRL3yQm zQhrBWEU$v^YW0S)2ES|7CGt9Tsk~lYCT~#j%~|RUd84{U-lVRO-&I%2o7Hpjd+I8A zi@I8VALsue-4&>Imn8kYJxdXqW@oH_GTL?Hh9pHv?FVG07dDNJeMOQ2#+jxW`I-F- zhh<{L#e1Q!aXrT#3O`NzXXo5AAWJ`24#z0hNMLSVUzi^Zc|>j>HE0;N6CJQJ0 zFosIaTEw-8dqCzt&0D+O4?NJSb$rk{_GI(e*tobjS#A{@*Sdvn{dgrwx^crLWsLgo z+(**l|5{yT!BRH|k) z1T{LdD~8S6A$IMhYVCs?p4m0~yCk(>JrMN6?WpnDQ_b+3UOmVN54jz60DE@R zogH-ov#W5ABt2BX9+m#^c+?T>nK<-Vk7=bg>=Cm=lWJ_dX6Iz)dsOWH-ShLZ^3w;) z9dM>VZuE3~T;tTP+5PkL3i1XN%0?a__beQmk)4;?BDT3Z)t@(b@X*}s!r`fX{HeY2 z@^T7NyY|Gx=B=8xc%W$uck|}4sr|BZQ#<7q6!wje(=&$tEt+QJGONz2G9khDj#CGB5QD;)Yt8j_IwA$TSw z3%__WrC$q4OYVe6U6UlO<8VpqkX@M4Z%~J!xv(-GC#4sr<8j{qVOj)M&WVf((KG%J zqnGAideWtJENI!{fw*|ov3o{#dREt=g&1V9!9UIMlJ1TUcVDg9%Jozd`h$()8g&Ef zpOl(lOxNynJC>~4_pybmcAz{yw}G;We!Sl}S5ZG#eQEqn*TU?)?A-o2Lo<*!QfC&V z56CPiOz;0h(}7Yo*ZK)hPQHKKh5<)wU0-^kk^wd8>94vSuGLEJ@(Wo|&Jo$8INQ{`qWbR+Fe3nS)iqzJjpjUwCWn;3`ORMW@C~DczI1_3YUtt>B5Yf=u>y6+Q+9GY@vC1#qe?eeOx@ zoPsl1#-3GK8syVEJ*}WH&2;wn?A4=lw~nydXj<(~M8xF2X?|aqE{Q(>Luve7O(_rq zBK$-jYtQAobV@T`GQLoOZNySwF#^2>fasS5#sS&68EIH6M!BMyU7!)n7BRDHLM+VJ z!h$pme94UWIt&*x!*n5DZst>IxkK6eQ&jQ0VfQw(`$!0gk(igyRbPYA5@xhW2v(4n zU&sYz*er!jWvOlgngWd&+yojmL7osGBQtY|ZpCpD5oNg^WrP<|hUH~vqz%Z=%+x=% zCIy<}Y5YXLA%sCkru82@B#l1WX7p%hn66;VO9b2Of;5JmnZYX;4a1epaGGFPFfe;S z>G-%0M(^lc@3l8a0s1g01>K$2p*Jp>mBO7DS~3f88F^3Trsd?NL$sXHkFybPl^*Y# z(&3fdqeq%CveJ@#y?h9{4`%qOELHQMHB4dLlmY|H+ANi&3Z=nJV?I>J8nL2h3)TD& zE-(mvxLT+B-OpxNH(%G}G=ECBKFK|LCHFAv*~;k4%F+(&m>)cZdaAW)v@y87{3%_# zQ)|U>gZQATQT2l+&jY62Sslrk^k^E{JpUUzj}spAM1enNAQp$NX&FNY4@ROKXlpzZ zJxr*1b}p{46!Ky40GekD8wMAJ?qg%CwEN82wE)KNGvgjY$lRfWc|10(KG55;d%W2f zsAy2l5>4Qde5i+e_FMF6TFB7gRZB8s)GVEJybn4UPr9UnqIqW1_DXTysRj0vdB4!trJ8I4&V>MgUKJ5xKmaECWqW-&){^D;8Ac!pb` zcIhDx`$B4mE;|T8{6zN`+E-v=3(lu{fMvXa`Cw=NH-?|e(zc-C=j+)Cp`W7AGlbAX z@`mt5h)wq0dgOczC2aU??Z<$E^EGmwAUY2%7|1)GEzx`69sRA)p81)D`PrFxt!b{j zQ(?E4+4UA;4NK1%T55#XLef4R<%7ha-327y86=gZF1+^o@Z!DCCs+;Z+F>1M(Ju-V zY~K-T^qCHEk>+5Jj-|^%4|521<{&+LVFv`GWHKJoySM-?keij3fovWvisz}9D@(uX zaoNg{*6ZQ!$#|-#8TBErks4qZ4D#%4KK-QM=$JF6)XvaFDQKPSO9S+f&@&mha9UW} zO{gD&!0M8=8Q3QzoZx|_V)eu(4nAH@)YG|&p zX$B`NKj<_A+(B!+S-YS?$QSv?!yED%WSEV9+Rs)reH8J9e|?ypB&bg^sTFUtE>A-X z(zEOqsh?Oy&xkEHbZ}aBVdmfhVLv~iS9MJo2=>yR_C;QScY_wDv`$!>XkQ#?)^ItW zPNnH4`yV!aS?k81M8gKvkrE`V3SNJYhr9PmVL2%!6EtU{7YLn}F|>5yYlHA7S#=Kx z)uo-%T(~B|>XcsB{^5Enh=y9cvUEo8Eq(vdyNovP=rjQ(cp%n*$S=Cc<7Q2I{EOv1 zxZ;Htz||)S+nQ9aFiEOdv3mu)ZjqwuvX?2c@hU~87b&vw8bzw`_eTQ(=JfyVC#69k zy0$E($brA4l$N*uyE;<(dKIJY4Xk8HRX?aM{XM1JQryrlz%CH!w;b6VkAL!y5Az*; zo8ocXdiJGZFX(q5dqM7E+{)p-c;oI~C~x)u>_z46P~IA^y-(uejs3R9n|F13-@*Z= zvsG~46?XJ|NH{2+;p_y?$HXGu-0$P~;*m4hx5G@-ZxugLzg7H9{X6<_^z0%6l+FnD z#@pTCuT*RwiJ^2R_BpD%pQI4CgX%F2-vY2uHZ_-$e_~1sj|zgoDx< z&JEyPCl>MMf7dP2!myFtbn9ogLxS?|4qBAkSfRxm07kh(r>a138xf#%)&{qOpt4*0 z8$k#+0j%sU9=V1sj{GKof3r{-H&UzW6r&a}YPz)=ZtV^t5pD!n(`{}UH9#QFr8_K4 z#;C1LO@z`}6DeS8;MVSTYjufDycu8v3)0;jx2^?F=th+oQ95J14~&i6S_}aSHw0{C z;ft|Q8BNxNa8NqKX#t#Ax7L(!gqs4!T5y`$;It$hl+JMCffGk8!i@prEXu}sb~{yU z3q>y}3O5JzLNQ$Gl|Xex>8!4aP;O7k;tc}ZTcj}-OVbZO5ukKN&;si?Qa!H4>S-TP|N@uKnz}m~L^&n93MuEM6B_xL>JuKq| z&@=S!=)=+TFTz3@5!P#F=AI3#EMgLF$DIX$-7JF($=nB#GD>I4L!g}N)^bQ(%-nPN zx|U<%0Mm9oZ^qH{B;lZRhBFK}g~TFe?uF=_J#5SbXYPA-0vtV05dlhP1pjs0W$vY7 z&yW~OXJP?V_c^MrkhwpH_TJ0-JtT7<;Z*TOC>D{TkhvGxD2{TfI1Y+0xwT>v6*Kpj z_y{Yu=nEt4WomMi&YFA*a3;C6R|rSU+$RBIJ8O2HxxZ32)~ket(izrlV9j)E(+Nw+ z+-F*-rdz0t4Sf#bpmc__066pA+C0J$GWYowoOw1l3ke6MGn^&BSxhWq=Dye>EexBb zM1ay6!8;&WK?GvvzM^b`RYZW&89@mM*1NT}1R-SZ>#;cQV~Zot+}B#Dj7(>vQ;coE z_`t1gaci52M9ADf;1hZa2*kOx*}`Ou+U?XtD4jLYZm{igYoEBa9mFPP?z=2VpK#nA z7C2!b?IA{#&KSP{t$-X2Ul+JLD0OuRG_BG)Mnfo^uoUd(g zz9Srz&TxJN&M{&UGWTN^Wn(-acdB?2iYG`>$lOmrF|0_Xz8z6kB8*!O`R&X zfMP5u3OReMjbcluif$-A;L%!>sF<@qz{gf=i$31TVPnffjg8V-WBUNo&ZD&@5HVYC z2l*o5I(u6?phN;f=?v&W0CnqysI#_uyCne8AgoDxrAQk*d&%tr@tRyUy zw~CdF&%HdRf97Shw}bYgH%$KhqPMu{yD<58vDe7_QAVyh9;)NK+DjxX=HBDHX72rx zmBCoOCJ+S5$RVZxViFOEdG{o5@yPE(^X{X1-i@Q@RZ>S8x%zakUCv!9G=qdtMlLi5 z)tp7u6!Ps^Xx*b>^6j}!)aFBN9;per_B{4SxO zj2vYfP(JW#TL?wStv|4!Y_UPvPADiNNBIOOJBUNft9MvsjU{F$>7tBWcQ15zldhOk z@3zz3N4h8@*ZmT@2ff+>k{0smgIL^-Q9gaZLSbYfhn$EXh4^<~?OU&QnDm8Q`a3=? zzlFLuHx65Pj9mH{H44he8|4>po%CuayxMW%67%Sj7Mv3t^|%$x7$(0G8Oq4X{s7r| zuXdKOgdF<3h3c%8MW3`62nA*2DA#~;#j9N+6d`}UVnMlNgL0ivP)3eYt_`kOwlPu@ zA$OMAgx|QL+Bi_F0JZX@CgjcKp%yL?s@TRzgiuCa$0|^*M5FzOxN2708#Xu6LO(AhHXKt8a=FEzP1LNjrJ$J>?6GJ#Co#8YAPGe#bv**SM_zKg|?D>pN zfTQPrB0%YkAU44+gDw?oPGTsXiM2*`TT*p}EV?Dy`%IWDI?k!02a55eC}h&{Hi}-S ziasc|OVHYqsF+Q+<0GuCMPC?UiPYpMoi%x9;B-vTk_ku5t2+YXXV&celP1Y!V?9V% zD4k*T09N+|ts7wp8FqIIRW}Qjk17lc%R+ymW6N!+A591TM5Cq~}%C|5Xqjoqo5lUxG^a9ud3EFcB z+B3u^=HdYh(sLa584H{+kcx;Ar8CB{U>uX6jV3@LD<5Ow8*QO7nrs~5pmc^a88{OY zvpoe!NKpD4h{31HqC6ZE=G37IBD~`Vw(jLB75iXZ~ah4gaLc zTV=B@CsvfsSl5GfZGyI%K*h{`ZD?{>vf46U0R5Yux#Q^BKv*bm6>DvKWbPlDnfsl- z4qA1eR@G-D@8TEASI1Y^7YSb|UlnIYg?^!YvHq>O9Dda3@9EzaYQ40$$Xpz zz}R)%q>R#;a$6{SNm=-!d9SFYoC5R!KzEePW5Szkht*W^Qk`b%jX{vG5D9yr#Y1$0Qn4`mQM1* z7tm*5V_3#EhPM<6Zy&#)6E_9S75Th>r;tYREj^?w4pDwjNo zGi%wIEBcu$`akEd*Vk(tJx^2Tpp2+9ZStr2pG2`G{)(<$di=7GHvUcn1HIANB)Hx_`wR1$Q zv%va|n1n6sH#Edptx&0f}4IbwGSbTh`UGfuuxZ4@Kz=s6ry%aZS{saDUA^dP*_kmQ_Bn6etRh z#Xb^Rs3HNObOv-gfGQJ>uw_-Y02o_VRZ>RjOu0IgtC6y>WmOZE`KncelumN=5WB}Ap)ans{uw~T`0;p#Lpg0BiCjjnE)EW|i zuw~sF1klh1ppjF6`vGttsS8`yeNYS<_q_8p>U@;WI=>~9nvdJYi^%E(c^1j2`%j^+51HpPkUvar7J^b(E2-A4{}*3%^w82NFUVxzGtz^Eg#gc>Df1+V}+P z=a7Fo``L-wuTVQhYQkIhr)<j;bd8WuMvfHi@1T|QYm(o{GK9D5%lSizB%Be4 zgR#?>_ZvwM%E(cw0Hu;&t4JuqTlJMJC>3o`ZYLC!k)u=xN;TpT-=?o-krjqX4N^xL zxq5A=-$m-;Tl9C8tzL)JQAVyVL%qIVt49FB+w=AP#UoF#MUTHdU(Z5hyjEA7AlwIp zMt&{EuiZlw!dvr={N@%A19frE++*P}Mradi8kCVYO)GG<@N2PtttoMdZ_Br^;KXv& zrWP<^;It+_l#%nb1)tZixd~2qOWtc?b6bdvrb-|bl#!z(1I6#xe1syr9q+fG_-s%* z5DLo3Q62(HXW|gvitlVuHO6iiCu-fH){WGJx8b`%EnLdE(-+Ipil914qWLm}tfPZ2s9y@vl5faKskQ(V3_VYk`)~^jGB=LgKvq1WT zwGzJ|G#qCxvNORKgf8n@Cyt%~A)$;MX%vt~5|3~(Xe8R>GQ>kK290*2_A=DQ`n546 zC|(E}3&k6BA!v+69V9pOs^jPxPgO@5dDUM9%w)edkzmA&K$8J*jxGXCEE{Gj!Jv#B zW;S4E`nBl6B*Mj?c@}YF7kQIZQAV!12&xN7Rk-l8 zP*mlw{TGue%E(n$Ky{g4TSCIZMW1C5HZS@t!Q&AsMq$WBpOsF;*Fk)ZUt2}u!Udl- zLE@`y#Me6!-wg3heyxPWg^N9#g2YQ~#NTrwz7^u{ld^E3=Y6OJtvkH4w^3)KjJ&fy zf$9#w_8|!i7kPI0&5JxAiU|B7&rT=OpFw)BU;C7#g$q1;vCxmi*eboi^QjHO{#!>l zTr0&@BgIv{r-TyMmYXFR*BMe=cg7SX;rjMyRq_l=!m~AdmFwkd%pO+n*h}h#FZ#Q2 zBg*w&d;@%+^zAN}Yg4>b@C3ez1K%KB5noyws924@Tl+(9vNhiFjrZ@{dF|p}AIFFJ zR`q|F(f5&^{*CAd@rUsR;QK@3)-~crrR2b#)kK7YUk;Or_q>kb|witxHrUv&ow_cX>VuJm76?RMz3{pW6}*7PTyQ- z_Gm}FM?2Vs{udA3i@6UTg0E$iO2-46vo2SU5N|%5266AK5RXJhb0PPfAKr7Go##^Sx!BHR6*pO7XR;9{Mr*GRJ1D#B6<=%TzMU(4 zU>z4*!q;fCU9deo*sk!NpI9|^*aiEN2m3sHu>E$P-*L}x!h3#g=Xo5SMq?hcGdabB zp9nGGbL|W_`PI(kGB^3Nj9&XA>{9YSdXJvB3mxS#cPPmdW+`EF*5&#u#GB8|THO0i zkGOgDf}=ja>vNO39?R}i$Ij~>?xlpodf1HKnCx_^ruf6?k0v2;A2ID)a+6p)6Azbu z0Kmdh(%Q}^k^8jsgzTqLdREfb&hsJe*(tnd2RqN6+_QUl&u(^}4|C5xb|z`uB-PF& z3noTuXL!P8C6DSur=OkslUyO!Ixcd;*JzMku>bO4Plxv$X4NRP3pSDm8xcO(^LC!& zxaXMgo}=wNC&ANb%n5cT(|GVHAtrpT&Eh80?MxPOllf)z+B`PtELlma-lKEvLa*eZ zm)Xr(mupFgH=misUUMOO(JL+`Y3Agez)i+^ElbHuc3!V?uSwo8E8OE|^ciHQFC}yF zhtVIiLgJ>I_HS~Nd3GjCxbz|b3ropDJD=6uXQemnQnK96^Ih&)65eyYo#%G$`9XNk zEq0zex#tc$lYQJ|x1Gr$m>8{n&>L8B6819tAmxWaeVaq(^V8XdL^_A3u|GQ8&r ztHyD=U>A6>^WlS?we!5rJ+FlKykzGY)y8a0sf{?1_|UBg6XRk+`4AI6*KX$~mF!Gv zag#gS*!NoXHsO|%{(6sAvkR^8(Dj*n=nEV+XI-v(A>O=t4HC@i)k_dtV1PM!W4KAf z1j|yQ*m>R0y&5Nk!OAtGHzzxNDT%`$#^7!l5;xDZ_i~eXJCj5%-44LQQqtDW=Rxk% zF(G6r8K}2lvYls7?%6%OXE!^~N4aO;@Sc6_Jkz=7V|FH4+$6)!Bo8J=Yv&|{8`az(lO<*J+F~~8ELq7gy+_}&3%!AdUTZgJU9Qz3-h5`( z^qEUZb)VFKKyJ`gmLgrZs!tjyoF0YK`n<0PSEKRj_@tbHL04>xO_PQ^y6lrOf-I)! zvFqFUHQ|1ZM8AOU7h~twlKaJm^J{A7=jMKKb|wkj#A|1g3=^Y45`9wM(88el8p~1p z5YPE$J9Xinox^)}wDauAJ-dhZ>}KcLmshBFhzak$G#)$^&6$Jmf~E`Ds>}6=ol_Qf z%79Z|dQMKzm|CXyU%H*|)0}B&=xAJ}dp;RD8rPal_&k?=CM5cL(_|EnUL=l=&3fz+ zc7Efz-&oOah3+@T&TlIBn;gz>qMhF??l;}eWF9w}V`s7mCdO!75PoFL5Aob$w$lpk zxiq}z+jgGoxaaEdp6}RsZsHZ%5Msi+Zz~VJ1GaoOKOqVG0MF7fCW#L;m;kNvxypOk2>*w;nB4|Tt*c77GP zU-?8~EjIk362&!~b5`YkmF-MwaFc3wCjWqmF&b+nhFu$LhIk$_+ezV`^}~DCv-51k zJ?{6`!0_`~SW;~{ZRnD(c+$tgRNKe+Tc01HX~ z89SeA+~;y)NYekk-hvnHJj?sdnN!Xm)>HC}4a=)?JNK*<-m{{eXASOI&Ca9_H@VBs zM1hIX+V%b6lKxYA#p~I*H{lA6{FZSM6TU|G*ad6NgS80n8Ee&OY8Nbl2lIvx=C~}oBX?sUVGFZF6sYG@6m_tLJ#7h zvzUA6^#e9%U9QX!Z$6v@-1}L03)%f2y613zNYZ~1r}cS18m>m;jr5Bf#%0rFJdZxs zFKje7^w?wU{HAih$)evm-EX3u-yH5YGo0UaJHI!%-#j~$#oT0}oykg=7!9(_A9iC~ z65{E)gPL+Z_goX+bCsRvd)#wVc+V0$&uzRy?}wQ1?%T2~kq=&T5ol~EVYn9p~ zGbb~>ATu?u-=Nf#A(^=a1vy=^`vpC0IwYf?bpBjzsY1;vqm{AB808anow8Bcpd3-R zDF>BLm3_({WxIMwxu#rEHmjr5*VSTmqq;#osCJ1uTO}ZmlwXo3%d_Rz<@xeLd6E3K zyj)%>ua`H<@5)={?eZt`3HhRYT^^0tW0eWYBxS1dnlf8?U0I+kR@Omjqp}S;d!Tes z`A#{bT!PXy_XTaNLUHHl2E# z{2|ys!f^+VALIB5jyrMOh2y6+nXhr?Fu1;f-nV$>2%h;4&wP*Pj^f#4cjPG^~Du)frfwh1EG&orl%$u=)d57hv@#tS-Xp609!6>I$r`$`j>lu)Ge-zhHR- zmI38Yd4zINenGh;7b%zJk;)bMMdhkIO1Xx9yDk?if5~H%8}ds^0DU+@8K(r~m+?DZ zc>z6Iq`abxR3<7fqHjkjlac+m;qjKTTwVmP#qfF?UQ6J$6kf~VwOpAhuTZARE0x#e zca-V!DrJVe8j;o@(pp4Xhe+!YX#*maAks!U=cUsI=gr>oPvGt}3-Gu7$dS?Ub$Y;~r0jylUbSDo#BU7h2dr~caH4fS-B z`RZKno9b^(7N{@F3)L@`x76|SB6WhiSbar)Tb(E`Q76eu)yeWQ^|ZWPog%MLUzJy? zQ{{KmY4R%dHF>oK1t$p4+ZoS3bn=N9u8ThdNjO80S7w|5A41cb7U({#1QK-mT7; z_o#2md({QOuLidQ$#I zT`Yf#m`Btb%6ItvUR@#|RhP=g)MfGy>T>xctE9IZnbMi@bm3&HF zE&qb^|B&tqoU18Ge{atcpr+Xw>z|Bv-MAr1QBwN>ndya1V`E>DBz(M-ooSkppV_}~ zSSGd*e5MpYiyr}PKSV`Jmu;$*pX%Ligx>t`OXBuO`JxTK6x|DF3tTKr$D zt1S3xN!O(_zgVZn^xV4mGfApZrGmtsdvTv6Ayw0Vg4>&&V6A_ENR>!R^lM%H1hR_puHL`r&re_Ux(Z_`SbYkP#koJ8FOSY~CnIO0ct|K45k~ z-6u)QX0u17KRh1w1AFE?I%D$3r8evlvqO_=Y`A9UWafKRWHa6K^Rn{O2g@CBra*4= zbbMUn)UMh6^YaSw1{BIhUL*G`9Ga1xm)at>xjWULH+b;S-0Z^PseSyZz4G#M3R1iF z#KY#TnzneLX$yDr=CP^$vU5{Av;jAt zP30MBQ)>VG;X?}ZQZowl-?W_UeogyJT1H-hq&<=?Y5$U1;m}vokWl3h!80jY_{Ebc z{aQ#`awk0Mnj~o*hf7+A?820OgE|b&g_ZF*DZMZqkMsTyQ#^3$jL7^DIphB@a%mo^ zCy!dkf|e~Fh>J)4x@TmkXLTJ~h`|*b{L>t-Q}5_-_tl!MTzSdphZY#UHR=Y|KPmlH zLy~Iuxg9H2?fckzRXb1~AA3jHL_gkdoU5pxtG+b;rfXq#T6S*#oS_-Wf2k7-(g$P~ z6sGroqUk`Xnrr=pCnw)OZo`11wXQF{&`4=jJ=wW}F--LEu}2p~w{2FqvqjGfoqw6O zvt0GPZ5>yjUv{1z`}9}c4%ccWcX^}kw*N|tH$PW>ZF|SDa|Wgt4Ai4H8+mNl?9>gu zHY?X2n7n@8qUvj$N6*a9*JHPnGyi-xHLFR~u&m0@oXk8>z16KZI?YA1ce8WxvL`n^ z$C#sRX0qO$*XN_?+eckpuCDn)Z8Yb>gmTj8q)tKV*U8_$z4XFu zQnbtU`n^)%pX}9|RQ+(RTW-p*i$gWnhYR}7?_aywT|eD_?aJ)>#h0s2XP@jy8TV0^v?UGcXQ#Hwz9`C9;r__!8kAU<-1%3Sw zc;NCCb9v-m9P;2&xl=Wlt3ODCPI4qOk zR;i!YHQno)<8>Wws+av{M1(4@BR`5z->^`_GjJFP z?uvN3&-GN2tLinwTE`vbD$h3JKqZ)e%gldg=0jl~cvBi!&2?L@*Y%XHe6>wf=frZO zlcK8LApe~7tO6-Gz!4VU#y}jtM}Vr2S93{K%Ndm&IwUPWbAVv|9kYHp8;58#Q7pvD zL8)`1t7;>|CnqnRHH}f9UI6@_dHgvDhlg0B?f_tP`Ob+I&=!@GTs4yP+G&O}Hk*tz z`h33;;qQoWltp-U2o8_NNYcLsRx1a=sH&9>pZb^e_`Ft5JxAKtJ=WuADo$=RjOADjz2NSKL5cXu8}159at?&*Q-sn%F7*= znI8uAPPm?6uD?Hn!!fu9UPhCai-M{y>8cuMgcy=uII!RF^o)#r-aP++^Uut=(g+;J zHcbxBTaNZ5t)I;*v1X%2iD; z{IhcM`laWj<>ci(F?0xT=z56pD~s{{NF1giMpHDj01%z)mHa&(?%pdUtyiZW$-X4S z=>J3-%~P1du>-=KMwsZ-cqyfOa<`s6yQE_Wj1!uC1 zgtD?U$fvK&X$6I8rnA3iuO6Mdb%fPM(`t7jA}04u^ZUAVN%Z+2O5>lWz{&u9{6rsX z&*i&xN;582y->kmT#P_x8RJU=;{Z0qv7wK0MKilVBbc3IX4iyR*i;J((y%*WZ8GA$ z4#V@zFkOfjwCoubzZ-VHGrNz3fY>hb*g!B;UxU#f%xIAitROGHkPFJNxd5BWQr!eJ z1sXB935HP<6YpqoSQ*dWqFxiC~*ukjAQ!nZYX?4a3XKaGGFPFfe;S>3F#hMptys z_u8AI0)3j4g6>c2&>I);OX1E7Ez4GvjJ&6EF;21cjVfof@NC4ps>l1Lbhst==#gfO zw6r8&FCRkggBgA*OVvDR4O19*;K6{iHcMrxLTND5m=E2tMy%-BLN)(`tD8cfUel?5 z_p|M+o3Cqfnm?smpX46Bl6#o-eAejO%F^Rrnu$IB#fb2_QD@y@of?CO=*u>iLeqC+ za5MT-x^|~Ve4YkQGh?0Tn%t{XN>UmnlziBzunJ(DRF*cz2Q>^eUeHt=LE-v^T{SQ} zc*qA}`GOwutX_9R88Quw5S69h*m<0|&pc7!&l#B3HMwhA#?Zlo@#;A+lGKI?O`M&J z>&S(Cygh(^7zLr|i^4czgSd2@nA3Uzj7Kx$9zw|6p@VrmHhznl$>BEU%J?6A7ACJh zuiCx98lzXOd%QU;&}u==^paVnk$l#Ld-hulue6X+$}2z4j8U_6J>dO5o?2#)P-kJ) zo`8Bx&?zf2855NH)NJC36v%~JX42A*d6=7*k%L1mcdtbiDkTP`IKY-M~k1z(zc+{?(5kJ;!lzI3?cN8JhmAc3m98+ zrs|RNG0yN>f$c~bZE(Iu&R03Pz|<0LG>vgj5Q7gb7|2Hr+gM&>Hs1<8lAl?apPh-T zS0=?&*iC14y@goA(sPEE8sYMaG($)IATel91nGAMX=SMkZykN)@qt0}y|Prpy24q9 zVDyUu1=}r!8qL%pF46?<(Xn*Vnq`j8&K#s?FYMc3q)SQBPw_P(y)bWZcK_8(zTulp5c^T@rC4ViWU%}8Qf{cKdKwe z5QBJ2^?1((EnA_;(Yu8D2e0|hBET{Pa7hJ8_he)aNFSP0n8r3f_8JaTKq?nq5!VR= zw=tsV|Ayh=^Q0j{Ek~&6DT39|TqBP#Gb=XjR_MqB+(8?c*#to&o^~$mvf&MRHCLKF zbK1|YLg|B%Z&B;RY>z=5_YO7nZPwLvXhC|G-I}_JRrHM5tV0KY!cBga(TkWneTpqZbI>8ax@>0AL+!kOM-4(5`Q;qmy8@UKi;f zu0Ml#sZT0PXY~GLL(%9|N<^a51eDzY!%#Piyb{55)MjdI6Hy!F|mlZa{V~Ic;pQBU0@USF9w;Ye=*2R{To?v z^z0%6l+FnD#@pS_wNz{$iJ^2R_BpD%pQ;XL7>bcS;oI2Yr!3xp%w z=Jlcl=YkE+6~aO34Ce-Lt`m!RtJmumX<^t%Zo1LG+aW=DcLy!XZLHAZ?OvnYp;J{L zxQz%Aqj3}Kk z-Ur4;ZY_oYh1W$|{f?Jd$6i>2v@p9oMo zBj^Hx2i;mHx7L9;#9P8XC@w3wC2S|0*})c?_w_97eYvDV*{ofO6{R!QK49(T)_M@A zcw5+Bz!H+fk{*`v0_Yj~H?rdB`4?fKj0o#BGjq=dRu(Y{U%rq9fZZ&E3(4FEkupkW z%0r->>(+8eT+G~a`MQ>4;Q-TiJ#WU*^CaP*bcQnwIEBO_X6}XPoIPyJ1ZVDhbpjkc zPZ0r1X9WLs+hy*hV$YBmN@rpLRQEZmu8_GuhxXpf`aL9bAK_H-MJN`LqL8^4*(i>3 zsyGgcFS)g15*0J|m-q-Pw&)8Z>}6_ll+K!b3UDU5wO0s7%-kmdVmoVgp1HqLHrA_z zh0+<;Y+%iFYtso!$lPaIsHR(}j17Gb;h=Pevj8~r-P%0D5ilI-(iuSs2-dr`wFDt#?(4BQ?qiE1 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¸y#^BzDDy931VjuY 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:+*VMzpT{Gg=o<~M+xCo;{?{vlAYa@YJ} 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

        u_`)2Is(x`}EqgCDsmU`5q0)5# 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

        Pj+vmgJJCY$j8Z`-Z-r% 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ℑ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 z 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⁣W~Qi-DXJ3*bM7@W?T0-z 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

        unj|R-BCTb+X$d^E)0C1RI0*#CfGlpOg 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� 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�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⪤TbaEg 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 ~1r1_Ru*%@ID@1V6$kElpt_QCh~ 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 YF4{M^<+HBQirdyL&Rg?KqX6+@p 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 z zX>0Ado3(j6UpD%UKTH6p`yoT^3Z|A0hvyj2b82lr?yR?HORCDXwSC#(@Z_;j*YQyN zVFz=ljF3<|ha5_yQ28uWA`itMdfe`G{aanF7?E&&PR;ZT3G(6VMT5KBkd+fwe83HS zVcfhBYS=|YNg4nd2?G(fx~E>PHmq7Vv1a50R}vV++*1()N&U{J#vw#=-xxjWE^5wTX%Mj9_i?kmv~- z;r#3vHV{tI7`=`yCn390UH4-r2pPL|k3$xhM`>7;GBJLyBR(|rr(^MT2zP&DF)_BV zs&VXeKVw{o)79*BRrpE1!OhSVcGo}$?t_IdQeG6(Al9)}m~8ea#Rcq!udu|$loT?F@rnTWaO7bYoICN~L_-u3iah8L4= zQt~LC=>733|J!QPMT`JP#0n^mygBG_kWz88%H*gBemKlT z%(Y{}XSFGY-94a z5++ypOuJ7DD=$@ewf03=;chpgw<9~glytxoy+0Dd;tn?KI|-9SD-(~9z5&3}Qj%ol zlPY|A_`>$nSe}(6TX_bBXGUbtbSuxBg=fFWo|#sjw+hc}E0a5g$zUs!LYU~So$rg3 zmE6Gx-rZL2WkR9EJT8Vuu2GRyum?o2(UCnX%^Kxa!N!STk46smh?VCP!gFF|&&RAh zr@&Kh%t=-z&x+vF!c4?mn=MRcSeYyqCJXB6wfSt)nX-}`-lOxZLa!E~S6ae z`-Q?}zLm*xA-xp9(o(Y6%I9U_vpPBAQu3me=NrOvePqvdR-Rjg=cdS>8?8LI3(sv< zCLarv53Nl0z(jBDUCEJ_l6*e!KDBZ`AQZkdkBj}0YqZxY*!LpXk;tBh%^HWSg8d?b zoroOlM=Q@W!t?jYp1)anI=UN;dDhCL0ZjCZ39;QR=32ZkX=r8AT$nWNZry85x<^_{ zhVUM3Y!$k-2;GXghrhvLbJpQ#8Rji!=2a<1^;)LL)f;L|-nPQTm10^-T3dNtE46sF?loat63|M*I zEIj)~_RO^Myj^$>itL$f<(VrybF54Xg-O1Z$q1O}tvx&?(x5Eo6)&=KzfUMsn#V7VS!6rry_L!CDG~qcpvgaf#&zbPl8}nH!lX)We>@X8C z*A@zs`Bo+`3X|pa^x85u=}cM4Xx^hstU|vgLa()&vku40Vcue9HuD=xNfW;^WN2x~ zmCorGUvB)<+;e%*v$7b}zQ!o+K35`c-`AgO+(Y*b}Pef8xiCCqb?(N2AYXRpYf zJ*_-%7M}egduCdB4iXg_5N0B}?@keXFq*SOnGi$Q+f|3-HY=w>;gk=jvb>U#kTJE2 z_g}7+?`XkP5k4AU;htsTqj82g9PTH%!Kh=ws#4v607q)XMKE;rF=g_Y(J; zXyx~e@S7URZ?cu&Y~eS<%4EJUnQLXT6ejv;Toid^EC}=5WVF*N;khER=L=SzuL{qX zBYVDNF!lLgmOnwv5f00MWE*|?QE5EbC?~LrXjr*Op@@tT0tn{&I(ps$hInv}c zTyQoLeivAoTp~;wTbW!A6MZx`Pm8!VHVgCo+-RrP!n0Lm&z4r6ZsFM`vZu?+^Ey$X z_F*QXSvrg0*P}V*(WqHD`Giw9IE9VI{k;FWSowY;m_ACAlm34jO|?gu>`F5w{hwNS zeIdN|rbS5lzcr#CBs;$Oe~Tx2e;x{pd&IE+L6{u1GWl6Z9|y3M^dGbG`9t`eN()Q+ z5AYT|Y2_IkFlK-fi0FCN$}?VgHjM1qARu>%XoO3IXJadq7Q*CGE0fkR(ObJ!AX3u* zJ+F96EB6GU;0~C^Mcc?VQmuj|iC`TgdnTGSI#>nkE`oU@2kU0#nJzs2kv(s;^6Udo zy)k=PnPiFJnPDbku4N08o2^Xl5+--l(`&Z}A|?Gl@*cg_Ds+(uUC7+SuOF~E>u?MS z^A>}0jPQO4-cok|EBCxF5SH|x!f8J5AA_sjc;f={hH=_3c}hfoJRof}=XmUiR({V2 zzp1j{Puy>^mET<9H!G6g3@g8d!f(En$ueQG*ve!zO!Nj>8Hl*CEf4c_;EP1ODc1?l zS0a0^vGROVc-BVtTyN$1wy4lsVJ4#cwu|7~(46wdw$;jMr*PTQ+ zu#w`3iH#W)jOT%GqvyBl&tnJc&tvbP*Y75PJSy|4971IQN+wZA&xcYujLIUtj4h^e zIF8@|6h<6la`L)d7~b1mherHwE=A*+E~iis=_r z{9(S1n7(N5@^aQi!Y(tYlowWpoVqABAKR==Wp$%PjZQTB zwNaIGyz>d?bmu(h^Ug)irOp?eE1avHYn6+}C z=6cRG(>2faylaVTx$8AZz2Vvlp^qW8+x3;}xa)UF{pos4odB_?)ThQr@_I$eE6 zeNLUJ&Qj;7bJcn3eD!&Cp}I(2qApdJsV}H2)RpRs>S}eZ`i8ni-KxH$zNdbqeyo0` z?p6<~htzM>BkGUparGDVimHG^QPzR;HRn2zzUF)#$66fUz;Od7-{9N`{_XTaQqO*k8s?9nNm%^`t5dN09ag7d^#`oZ zIHx-QgymnbJPXTnu&i?Z<{axf<|=;N`jr(9LeN%;4)YaDvK+BL;B-Zjls&#>sgG4=Uh*?X24@6 zJZ8Bjxn{ebcFlpuTzJfb$3NgPA0E%cV*xxC!ebFU7Q;`%K*SFb z@gqdsfruX?;wOl>6A?dkRXab!zg@14u74u(ZbaULfB!=C&k=nuqVGfW{fPbrqJN3# z|3>t$5d8q6A4K%85&aONe}m|U5&c_4KZ58-5&b*YXRhyEyIemY`hO7p7^44(=*JQL z1fu_h=szR+FNpptqMteKBes-5eI@kH3I?wr$y2-f%uYIik<@yBwcBwag$hl8F;@+<=X!nJ>*!iWp#QAS^ zsq-uKd-nl#ne(8!%k{PTg7c8N+xd<9o%67|-1#ly98u4?j^f{U>PqML>Wj`F)K$*^ zsH>gF(6&FSvz^D)SDh!+mz+PT$K5}xYn;ERKRJI@UvZvP*E)a0Yp2wc?v~1BRcD$h z%EhTHb51NSSbuMvt#iB(dE7UoqZcI-GsQL6Mai3R0_Ln=oXVo$;sjbY;$!yZaM zi9?D@+72DY&&A*v>v)uzN3->54R~U!x*kl>eRVQ7pM5?bc5I1ty`BH zJYB^p{-9IGj$OOr+zp*>=-iQ?x%)yzId{&X6ij$<{@`5C*|m+9>|NRS#W{OkQ{4l$ zINw*4W{u8Q*lT~jrzl2agtj+>VXfUEyfrUuqPGLJIkOuJn-yVpsY;X7&~|5bf#!;G z9qWLQA7Mvr&tAF!|4J_pF~UP(NA1sE{rO=TK8}W``!#*l;Z_DJ=J?NRRrLmkle=8{y2rnF?q7`#oI~a{3kzDKD!i8(Qhq z6D8+>%25TyWjUQYcJk%~%0`SBRa#v6K+d2*PIg&YNkvZI0eIM{OJe74iJiTjI(5v+ zFD}jLT~<+fo2M&JsfKh;EGQ{aotJ?^t9)Q&VL@?;q7D7;)3Y)?56c-+{=mq}vYh-< z{GXd&Qe0Y)I7HD3$|@9XaIvD@s&v8OHbp~*Rz4E1WDUbVyqJ~WSpb4^!x{_9#8y;fX0q-0b9GHU9@ioBtP6_t5I?nx|CnmE=^zIS?u zr(Pd=u*F|5o^0>x(llUSK_4ePe8+=J;(Ae~@6TKH)0JhXw`~u$8d!QfDMq)$WU-#d_+s*G!(#5o+#U!zp9-(YnpP4~C32Vg8aO&pEakJS4Ae(g4O+vZ&z zt{JqZ@zD$=tzT|hX0Ts+uwSp-(!%@jM)y1{#Y)v(5dTiagJ<$^NNtP5T&1W~)X0Lo%0gv=<2<%2SM@=JA6SG-k#x#Kl4Up>*gwPGmS5pOy8C&GILB1mrtapCba7Zw&dy zvb^pXs@@;!KQZ5;G929P6eS4t7`^I^F9~z6$Q?4Oyu7fqGPkm*yfCjoRH7VVeqmvj z-;2ZR2-5_;5VN?4V|fop<4ff*6@``IaYB3ZR~F~Cavb&{P9wx|AWq{Ja*&d;A@@k~ zCz;!K%2yt_6s87SS+Wl)x>w_s`DC&F+0mPk(wYYo%P8Xv|cp^1=2TvmNYF zvikSzH()?!ZpA&hs2<>OWsI31^Q>wElcC|^?kg`wRjBE8?OPFVER5ro&wOdYEO-vn z6W6$SKH3XLv8!u(;Ok+FUjm11k)Q7kxfPYU21H;$_AOXx5a10xK)mu{8pwLymK*SA zW~TWAH|2`&0x4D1h=rfH1F51KnZ0xM3$5eM*Xz0*fyT3n)JSz5id;*dJbD${!|X9; z_JY<_TtVJix|C=wQ{+yP&zAgh9M=MG6`fJr&xR zPw9;ruRPg99zVf!MZpMF;zmf?1%-tpxxc7#8UQBo_+PfDD1NXo7jptnq4#Jq^hTEz z7w~b&f9p-DN`yHJ`@9sEuP7r%=F+dm>4PQ+)2CV0mP@w96}hYh3fbbNw^JMpCv${- zKD0sKtbWcc!Y-Jk78$el35PrTCDhh{Q_@z*vn z+QsjE3gvj^yt-h9v6wec>apVHNY#80my4xwG7VI52YV^V=nL;3iPfaD=*328sOcQ~ zu4Ebrx7^BD@Q#^NZZprw5hJNjpD_l}>!A%8$m-jln(tX*;0dWKwMWR*evZ29?(o^e zS2H~m(Z|L$u$;lF^AKMeSqxE^zIbgWugkrGlA_$cJ^SVsj2bZl*8r+!lfdF0Vap}! zN@Hs*uItNzu%F9hDy5b!F2(hDmOkh`-VMz^k6A71$>!jQGPcN!6fdVE$UoT2E_{lB ztryMDO!!`2f#1KTwPP5}<}ZgB8#XUQM=dqtH>+E;#CUr_e=+VOsi7p9$*BBtF4KU?7`3AzXAFmx6zH53 zsI;u05c^Z4Jzy0Nxz`_tjRx5bLHxw!N&O))v88%753o`+x0u507uuQsuY4H~Nmgi# zbq4B7-1+U0N#-BW8`}4g_Do58WLe$*%htFx+)n1^9FjZ=gck{&kKVAE|Lf8`kQ< z;+4ycNg1N_1}P1bS`LFy&O$qadIQ%g4xN~k1B&^-k)n-}qUqeZ`k#W(Hv%`}ZQ}7B z4q1u9k>lQ%>L0q3Jc0n55g_hfzLSK$bT=U0W-mPufkL!i8wA+Gtfom;qe}HO!x$HA zB5dWL1>TTN(5QIG7^Gb=Ub!o>p{U$DMt|&KtFxZ*u)hO_pLk`LFTZ#g_5*$NG&D}H zi?9QS^x`(%E-nr?DWUfW$c6ZdII1FVnAN)YF021Bxs4%>_Y5Q0`>ndf=sn&7uS9@g z7j$XRih8{fvef1F#$reL#CD@LFN!Hv_a=hA%A8k3gs>EfWWrPBdb7z{SzGm2gnn!`Tj;cZo&51;x9bn(?#QJ&dP@+=5~byESk% zj=uMa0Hr;G9UiOOP}GTiOkybQiG7CZ?xgBUx1!jI_MXG~J?vH#yX-3d3yQl*QMw() zZVScF?JE8oieGrNeIzR1lHv<7!uFZ;r4jZOH91OqP5v!#zVT>Z6OMdaif;gMq7j6j zHf~Gtb^TaJ2n(e>tmD8s=Fxs2Ea}!1$4pc|n5gt+;RNBJw1;yFI43>YFN7oAp5mkl z=NAi{-w6k$J)FOQbB0*tTU4AeNlU}#ED@lzM-c1H&>UWUg_dtq;qZn}Rf!2-i6)#57C4;<2cVlouHq$u6O!VASnsaJQZD@uEHO@(p_Da*I9NHIxcEY_tTej-3= zkDw0-dV94Dua-_6@~td-%gYLGWs!k1@3DnuGhb*nJ8RSHXT6D7QQBk82J064EQ1Tn+>1yVr9I_R zD3^G(;Uq3+?j>Sf8*btN(>pwG#?e7$ z1Qct$+5{4nGxr)X!X}vXr4jZdH91OqO+F1cQ@q;Kgd=C}QvmS}Yj%;jKV3i8bizVu z4{HvvW_h(4ge7I}vrJSoOjP=YK9_J%+QV4{oCRKOKH*52`vMcrd<&e#goDx^&T`-^ zBNjPxUuKe)hRq5hKxvQQB@nD40y%SERX@QRB0y=6U_A)dd9}3!A!Y9CusH5yi=)Wg z*P5vGOy_mG7;gh(lULj5)iw}`l(}yb6M7>E1u?X%FWM;Oz5i zpA(Lhx$iUKd~SjBCE=j7hx0XX4iJl!xgRho>*M*5UBx3%JWPsG=6)E8ky5XtR9BSt z>iQoje^1JC=Kj4&8e_38{WwMhDD4sa27+I`+Rt9?1aZij`>*n{g3SGAocWY3G$M09 zQ9tV`Vnu0>Rq1<)V!%pFIc!>3Uu#M1ayBf!k-5v)75WBQccr#I8ei6R5gU&Ypml-p6`8 zENAavSFs}$6G>6Z*%K`kJK0t22E`kES`vxMIr|M_Y$ciW@i_`^lH~JHW23a!*f#>C zhfhl;5II}#0r_g_I(xDeP$~hTvKz%9B2$NTpLRFNOSySI7Qy|_fi>fCJ^gMIiJrw2+65>DK#5Nq?$e5hLCVTY#FQNl0(s69 znV9qxvy2)CrMuAa}UpKmeop|r=h3VbVl+H!)EbMTen$zJVp(-=W2xR>YP zIQmu-7RtYi6~Omi?&9Bhc`P|Yt4@xPe^)2hRDTsA|DKSnXZ|RoSA7bqPb6zKBrNCN zPb3?;ca51rU%e&~1j^_krU7CK5y*M>l;oQ62g392gFNrX(KnscQAV#mBiSnFt`nL` zLMWpbnu}`ArfN$0_H4B7!3g>GJUeO&pf;b>q+ENxh1xT1i5DLoZQQij1retj+p-8#)CKJj=3zRK{f--uP_kgmEIOM!~n^{(0Vz!em%II}> zK=(t^m2>J3t#m&oU6j%5?uPEJWbIRumh$OcSlqs*eEL%pg`S1%u_OK!#J^0|_9tt5 zNngsPzZBDQKh)*9vDd_-=h6qLQBX$TDBpqWNV0Y~Svy2ravpuegmYM+9x{XJ!{mD+ zLm55U&mcRIto=w>QVxB>MD?SYg-_aF2nA*ID1QLu_hjuiLXq<4-%TjLS)iOD6qM1U zDBW?zk~pN?`K(D*AGMC|Hq_38T5NYc5t8!e*zS=Np$6UcLA@IxoLM=Dv&QX!Q(@eFE_5AtvRuwjGpaku(j&0 zwInb(S8fFuDM71k2_!k0L9Tp&=gK(xS`!k=zl*e^2ficzr$XNmZbSFSkso zss1)XzI;`RK1@*BQ*HxgSBln}#O0jXm15+~txX&lH%EEyileVB;h?mKlK`A{#3E-%RIBviK(RaeTQJE6UgN64bP*j4mE zu`4M`nRHhRMXz1O8==@EMN1}8Ih*bwMp&{*Um9Vl)Z{4bHF+=K^i0tLgd^wGJppl) zHM{txNuYkL-h_qH9#(%~^-Iw*2}{bb`GXL5=*iEyOMe6k5=k_FB*!a->dX9jSdB^D_=f7Ya|kLQ_o73V^6HYrLO z`fMmhO1jEgxCuKQHpKp@JSgcDw77_tUdju;%uslUumZB{o4mnd_E-x#{ z*O%eUZ)~9v-!xfLKkJLciqanIIffD8)tDxVQriUINUwH5_zeF>{TXL%Bb=GQ z&iuj8{Nc<*&(^ruZ#v@WYv$L}dX)CCt^igGV)`g`;dE zXx>TP$S(I(&0?+7#RQ=5I^9Sar9I_jD0@ly7?jggrRpC{*()p0ap8BO@uIIgDWkNf zoCf7ozm`Jc=V)#$VB)C|KZ=VHIMk-#@ghvr>NzepPXMCNlYm`-AOL##wVnhJ=hr7E z2j~?7(9;5-k6nQN0O;q}G6~?1&=%+y0+49|aI;;2fdCjl>L)@we*hF~Sexr>lj!_G z)cGjwb$$+%2m7_#Nc<#KeJShw!EB%n#J}3xWDK!H-f3690P^{MEtljEko*cJpO1}U z726n=vGImuZLS4IVU!r37+cmTU{v_EGQyCztO{_v!Z^g1RfaR`*qP8RYdv4DarBL* z&OsSf=LoEaf%PCUNn6%~Xo&T7!$S1OBX$+5p*YsBJxZeTmNgct8)?gW)I@+mx{)^l zj=u5K1Sst_!IJ=b+^R#@@;{(Fmz1R~Yp$#;R;~G@jMAR+5-2b7YYRwR z+Oifw+}N@f;PEClPr|mWrFH>c1i%Wv_5uM&Th@vYfEO$PR@ntu3xJpX+Dil=ZCNje z0K8-Y@Ty&a*8%VvsY_edYfubXn?&c=Qs<+z*ZG^EywR_1AaQBS+9mbg2$j*drSv&Z8jic`nE+c`4UkHGp5F-cq2f6x#+01*Bz>$qLTlTiG{ul+=# z@|N`rRCm#q^^=JJG`n~c;OP5}ngFG}Cin|LXZ+e}0+P3^Gl1AeTh{6NfzA>TN_#-( zrQs9TG|hp(OnS)x#Vv1Hv1xTc4m_6oNNS-5Y4kyCnoXd109`;d(w23B2|(Yn8j&(e zdri><%8f}`+OitU%3{^Jgp^U*Q*Hs}=4o0p5|_5D<`6fwtY&!pIh!Y8Th`@v0j>r> zt2C`80Z3a`s}O*e767g70$c-tHffrR0HiIeO$dO?0>Et-;93B*Cv|DdY7fPbaW6Xm zI_i9s_By{4l&??IG!mD#tn1T^cUhW@A-1f}cICa0@0O-@A$e)b>XwFY{j-fhY*}3_ zFnoU>V`|4NM;re2*N=hl5$Q{RIN~Fy{hN*VuwOs>gxVhE-);Lk)!k6tm8N}4!tzJ? zyV8u0@;@~(fad_;8F2LNArzF+qwELDUgD5H#@~w`_?Gp+RDJ<;D!%}FgsbD|`-0R_ zMz4M#&FUlkI-!Fkgfe=e!>HyVs;2bu{UNmR5!TOPzjXGk9kuVFc9hhlkM56JsQq9^ z?I)-mPt%T(p!~7@aWR^XnY5+R^fNUx%IKTc6m01mLGewts<#`WBj z^&|a3NGPL6iV0+BN0<+Wj)5|Ilna563iOyAffD-DxNNF8PL>X$+NQc{;cqQA6$^%kU#GJ5r^ zq24N>wIl%P+ySj^KvRiA`e@!AFt&iUP?zV7 zYU0s{MFKSq%IKS>Gq^eiw8Vhcfw<(4WDJ>Iu3y9&7>-S1b?$h7UQlieaI$tl+ml-3H3Vy+U)`D zR$`Dpe!oLrHt_NL?KtxzTS&ym@3+>^c^7e_jGl8CI12;X5Q3CHdM^Z$l+e`C%nlDHsrAI_X&XF@Lso#t65j=nL3 zgfe=h@jx0!JkrIWacGaz5D&i?^q3vBC!zLuK$}Q{@`a$sp?Hoi1Wh!lgXA2qI*z`l zsOl)AuljVrObuw02}ZsMG!+0p(M6!i^}{?vFesyknFE+v0c{4s$QOWSg}}_HA7(DW zpo|`70bu46iFEO2zDZo)MHZ4O%IH;>LUl2zN*8_>%c|nN|1wfV8NKQ%sIClX%Sl+e z=(7^S#zmjycsy3cC=9#kv)YdMs}O%BpsgWs>4MKIA>wN+#Mjvo-vII2fVQ5*rHeha zA>!*T#NV_dz8T_gk+O85=Pjs(tUIE!-=@w+8GUEJ2i0u>Z7T^&7kRb?jEg*5Wdw1N zXS*HgPawS`pnX8n(gmI!Sm?)NY}H-h`M?5U=if&-8o*}~i((W7#X=MV*aP+)*O_k& z;#=-PEjh^Fh2i{SoUiQ>M9Q6ne^r~$oqM#cCoRZamf)o%{_QAS6Q6)@x1XB^L50sW9oUe$w6kGR5P|&qjnRje{Iwer(K=^kNE;~)D1#{>aVT9Ywm-+@P#ah zRb7M|K-7WB68wGudK7%=WrE7S144k{UWqu_G1-m;@c!MAv%f`_qji?!YSw10(OyS0 zGPJvbT24?KY&4nEofp)brE^X7Wc8*jhnnSRi<9oX-Ra9@t-;P3Lt&uqdxL;{$C*?! zu1)WOIAn4^Jw$8I$RO{aYuvrk^sm^o33b-3bbrM1vw$q}P~$-?dyokTx9F=_Xw3i;L147k#PF9&`=i0%j_;gepp%ka5 zLa#tlNHrC-$12qwpF!iUBMYN@0bshy+J=p07NE7Kl4*AF-GiCHAKm~C1kG}EtId&= zM(IkP5T%BZlyt8MN~2j+FIVCZeNaNsEJu%!ke5dac^9955klU_+*5c+{xH@3Ye4@x zT@rOe92-rwp#k_Xc6#n-u73CNfZo=+6Z577?%6wpxh-E5Sln}+ zaX>Hip;s}B#n{bEKpST{`nrF}u=Lgh2KodwG29GedY~Mo|2K?b5_n4kKriTq5!+2~neRPF3NS5PP zD`S0t$i}x>88_iwFB{)(Wo+)3EXQDXNwUtIEHmpX1R_^ALMQ4|@Q(ju#_BZ|<~h6< z&^*!fLN5RF99fQB^uh`BLRC;3V|2vb?&=^Pk~DPkYsXN>NNr8i)%$c%2{8z1Ut>N` zLJz`-b^4J1YE`?(Sa^pS55x*w;G4*XMIk0C!e%*!g-Gjzp6!Hu;J5ZnW)?*zi@Lfc zaEsv)EgTn9AZKgO6sd|Kqe8EuGt8hpX5T_=$!RK+ii!8aKg)3sYk(1M58He(1*=ln z{N_s@x^yb7e)zuMOtrQO?fop9-Oq~CVtvHf=_(Q9G1g%3G#0*;wM+tkSe6~@n~Eng zwoK)S_fFUQWTd-&Pkn{z$;N1ic1XL(gIfTw1Vo;G(Y=IK%=-+h#l5^1{9(CGu8@%! z+GY&-zkZ2vJ+YB=$0KY6j=_vSg&995sLcv$GmJ_9sJlTgeH8R& zqhLs>WA+5N90!#t$B_=YVd| zD??in)D{J`1wn1T!Cf^Tuex903zpFdRTK0GH7IHqar&@H70hQLCCNm1J5dS zG>lloRXxs>{+kR^tX~DD^{eU$1mQicH`y}YWKZHGMis;$GfAeFhtIjzo|m}Q#k6A0H-<7+FY%ahy~-tLnYi@xb8x=)g}OCwk)ZPwin}XU#!M;?tenBr*ps3vhvbr}C zA8@Lbc)|T{Q10@rA+>y)*D_+4>+$qjZ!~I+J{FJB0(_wPKEwdm^VijD z96q9fznUTbt%ae`yfD0kAR)7E8?XEtoXn0(fDqdCWhN74OGK>4f6*|IeT6Z^CZL7z zTRMy}XCMo@KK! zze9`wCo->-Eb|(LU*8zzUJR?WQA*VySY@&^G~Peqb=iPG9G5+f2KOxlKx1s=lz70N z1NTzk?i9G2aI$u17@^bmS0&kDNdmks= z#i4k6{x7`GIo=0w zE=}97vTtB3zWtnq{U!@%VNauB`3wPo@F_>Y1NIy&t-0-#V(vx{SzjfD0I}>(Yuj&xa)*hr9=O*;qXcOUgP!_Oy_P`jx+% ze3$l767)dd>VZf^zo3|am!WZ#iJy_goAVdG!wWtKLg-I_2(^>m^61K~J(u;V3uG9$ z?=_O4JhlKy7r9^${r?y;`qN{wOoT0`g(RaJ)F%Ub$oy!?=ub~DnM0^`-ClcnA9N`! zf5J=h1rDQi#x@Ii-;13CTPGV`Kg-CvP1uz_U5f8EdLuB$U*L#s1;TjpYosXrx{J}i zS8%(Nu;bmLKRw0VP6pX~X5G%|Y02$=m*aV`tbMJLWoKr7Q-W@Ini-x#Qy6c+ot`Us zgg@j69TDM>N|xxzsfeH(vOnCE(1@DvFFZkY&Z2PVrt3>=Ase=Jt!Tt2%cQkH+V z;wLX zeemYg)0$45$C&i_?&wMvPH-vLMK3pCFaI|g(!EAv#NS35PsHV)s)h)}ngWe{0Ul;I zNPq;MT*#iB=W}Al0tqML$uI$@@U#(oJ7DX_mdD@%!nn@jHoVsh;_W_X{|UM7dae`T8~n3k5Ut>#Ktwm zf>714iK1K-(;(KdRhVq{D8&W$66ZBK*5Q>qRy1WJnCPv2fmaz?URXGEROyhAKI(!t zcR0?sa=%O{H1nFq#UwK|wesvFJQE{(cChm7 z22Z^)yI7fY7s0(@CStDng-ME)$xXtfcRjt9;l-pI`9N5Y_ToL7ZWVf<2z?84A2Bko zyf9=uusQ2+^bhkE!>LGk7lxViH70MFFex#2=Wr{pQNpV{5>`JW`h#T0my$>EMDLG> z!{TNc_Tz=gSSyn!g>(&orKMzomCtnHGbMZsrSlei+RAgT@SGLdbB2}YV&SJVY14~PT%_F3d$JFPsw6rTGcdwy=^c?h0*V;-f&kA$$egAMym!X(kk#3Q6{0I;-_Bw6{S3ZEXnu>CZaXC=v2ooM!8k6aU$5Gk%K*A<@tp0oEX{jF)Pn0@YEY~l9kD`BKWj06EW9j z3zHdECX0p1f_i#wKAUu=tR#o`=sc^?t3~LQR&&jzh=N93)DYEBAE6?r1bDNdP$HL@8E0aAi(OY|0a-^js zpAWoGt=ta?g)hzHVt?cs?X?Q_y$E(Bvgcv5#v!XEfEw_@($Z*bV0 zbvRmvd5f8ORf%!56AG2)aZw(*MkB3)jTOPhMD~2xtnr{# zuqQ;YiIIanX5~3ecutP&Imya%COq}VeAdcjo(MiW%tXw!g~DXMmC1|3WO+Tkwv0_W zQ&uvX_vjL<(65QmYpv$2!|`&Mx0spD{Kit!#IFn)S{ibdrJCzD@+(Es=?OT^=Y31K z>W$aJuap#pT&S!uOk5)R)&BoS+?jw!QEYv`hXgl}iy)$i(p|%wfYJygfy@MBl3|Mm zf&wlW%?%_%FeI1+6t7|+ECJaU*^TV`z6Ol!0YB>b^mN{9 z`hA`+N>|cz&iVi9RCU!!&tyhP^|2VsV%N0tt1J9MWWPM-SKG?3q4298$giH2UlZXM zZe`L`n7FJ=JTNg55)-Rr_009@udy6O`+3gr=IMFi*)p(ab1Tmmg=d?5)-Bdq);3BU1H zCWXReij~Q1m>9EhM&Ow-&Chd#H&2U%=lsB)bFDmA3eRPMJ(pN{7Ksk6_A?Q~w^0Ny zMmpu$xZcWXhj7{kC%@UanT_9OE8nw%>6HI$+`&9g_|L{&-V|OCvcLO9-{Up8Dx&`> z&yE8u_9ZL7JHqdl?6-~i-LUezC(gUl2gONivEk>4lh<&;SyA}iZ)Nh3FsWo^@+eG< z*;p+u;M!Q#&+~h4o@xotnt?rQSb2sBPiJ6H&C2s>(V;qiCL%43MDS;jPI)%!R!(l= z)C5j`v+*b!zi=zxuLaZYIJxNm(VMD6!sI}lsp#Kt<#kMW9gYi7^q=-dKf&$T=6@PL z7~^@;FYXzy{cpnLtd+@SA$;iOv*mO`#CBv+I5UT#e-Q^T-><4X?>i5q+>n+Gy^w*n_P6#tOetvfm}~#}2Tpz)TQGX;aC~Lu8xvnk333FLi;I5}WXFKAo-^mBdIm)HPE7@u6cR`2odZvF-uT5&Y+oXlYJI89xV&=I6)o zpU3ic96$dFYiXDB;+4+1@A=4AW1Z`Rq3}6rFgeQQ8=b=ou^h$=u|&6~GFTdMa^Q#) z%@G}r@$m|7L5P=riP4?IM|TnDT})f_cM1P_DQ}nYcDd08t>8beWG$tc6_{p5Aew3N zKp2Bx7zoi(Zf>AVV9?f!JQM|1UK2=pRUi>W+lFZ6Fs@(me(mD@+%5XIC9uk-Kq?#L z{u$G_IFPiX+?N6R7Yw4WMgR7gCD=Om4J?cma-W68K@sDCg~j*6;*f>KQDJddw&+MN zH+uOT7aTvvD{p0_biu;nb3@~p>?W?d8*rm3$Ll7&SKR~8--{jvm8>EVtY8oGwi<6AK}$na=k25X{A0YW!Q01;HmD|VpWyA2MjKpTsOI>g03Mm{cbMCD&2zCYw~*y^}j<^~}so%cd(mUq~F~ZW%KUtAXFb=?Hr8c_q7- z*H}|>9}Ir5{Db%KwWp%;0J}}4C>64+RXcaSb>H(_FUJ&(jA$6tZFXi5UUBYmCw0h4 z%g#x9FD*Oky`*MoIdA7?^+-)>SA@Nx<*~6ey(m-x2ikUGwL<sFKGsHPqqR@83EEWcGi{bO zPg@P?b=npP?}hY1?I-Pmb{*2UwE<)x#D_wD1ms7NF=Q+mMKYU6*90|U5jH8j_Yt-&oZ)JEk<6x zz;OeP8*$u(<7OPUuxxEnw;^X=;hym1RnhvkDbJ0zrgAg ztWLw~46M$=>Q`8ugVk@a`W;s1Vf6>BF2L#{tS-UoGOYfD)nBl>0;{XAx(2K3u(|=O zo3Og2j#6*K@^4t)f#qFT=4n^ezS=dlpLSi%*KVl&wVUby?Up)FyN&tsw_2dxQ3q>x z)gf9Q=1yO2sFtS=!@uELKg^_jZKT#;8>J1voEoT&(FSQ_wE}G%=GiCO5N$j>CctB& zHcXqO4c8{aV+uT`!sAnT6vE>(cua%Gba>2w$4q$4g2!xl%+VIBbKx})Ui0C#0A35> zwFq8|wNKO~+IV%THbGscO;nd_lhhT6v=Wh4A<}9@T7yVy5vd4~)@gIK_4xO>wnZ&Q z#4iwW10rrj#7&5}84u5H&=Xgd&bCnA1@h`SJRHzMvq#J!04 zH6rdq#Qj>n`VIaa(2BKh5&0k@AHu)y5dC{ZKaA){5dA2kA4BvX5dB9){|V8LBl-zM z{~6IwBKj|gehSe~Bl;OcKa1$UYTsz*v;*32i2ggGpGWjR5d8w8Uqtjvh<+K-|3vh^ z5d8|GUq$q5h<+W>Zy@?jM8AdTw-NnsZJ>Gw|L#I1kDSr^lCxSr@~f6l&T0M0Z@BJ< zg$^XcLkE$GVFhGT*kH0MWC;F!OeTj7B~!wNk*Q(B$=HYyWL(5ZvO8=P*%LOJj13(_ z#)Xb0>%zv7^gnx zlzb7sjI0S;PS%F4AVpy-$=vW&&qm5*L*e3E#*k=6OLJoy(CEtZ@Bj1O8Nj{C(P6{J-kk2A^l4%iNk?9e; z$c%{HWK-B4vN>!o*%J0OnHjN<%!=4gW=DKOHaZWGP0nx0oQQ*DwDS-dS&snI> z$GHX0JK940TjZRkE_O~=mpD&{EOpLMmpQkq%bhdT70y}eO6P2Km2-}|+WC9P8s`CR zt#htgZ>6Q=)^E^Yq@v)Bq3D_Vso80rb9<#>_r_nL;EbaW{Z{&_-#I;__FG-pIlQ$T zZ2D4D>5JKP$zbPbffD5KRFe$w1G7obWT%6f&Her+hE3Xg?0k7Jsem>pXXqD7UD&j|kNx0tpbXE1H4F=Dq>8VG5iVDgCgBm0jm0VUO~VEa8aKwd z@WxG=M6xsgen3&~-gPLc1K%&~m>hX$Ma5Z%7qnhD`Os<-(r)u4{JnkEiuWq?v0nI# zeB1zHU%vUKCup|o`DgQi%0?b|&Z*r;u$k{?7o${;@y$E6qff}zr32veCG2?a=|eQs zZcGy2FJZ^?Pao@_qbPf%14)xNcJG^v>B?IazPzsz#x!w#)6Anx2)^s6j(l zk|(Qs_nw*QxxJHK_9V5>%F4(|YTXXsHVm)ds7d`su7(X8By~#9Olp;tlly99V^$J( zZd5-tBZH`qfJV>l-6JhEJwwso`tQr@ETfK2>YUxXM{ZV9r%e2x{BBluYW>cNo|=`T z=pEA){S_q~hgTIH1$K51Jd)T2|L|a9r$&n2ycND{-AvJ2_Ez*3>A8uWy0xHxJ;c9n zmXe!-@3a07OMWjSeiK0C)c?cCCBIj&UncaHIbn^OG>%07+NP$bbZOl)7jvtD?^i>Q zM|r5l6St~`J8(ZmQ5s?LR((8g%{xjVrt+gNKZu3u(WmHg^=Mvs{4E{Yr`fTdaSnfU zigQ)wNB-Bn@Qzt}X6KBasrY?}k6}*ATWLADDV^W0-&LvXSTo|CG4+P7ed|Q^zZYJq zqlH)T*jF%S2@Bug#H`?FpUM5IQM)Vgzm5N@T$Me~+U`K7^eh(p{NXl7tB0!z(;wgR zA7x%~pDHV2Y{$;%nv&C%MSrIM&%LH5t&MHEbk%_|Yo^VuvfO@j+?HUmpHtJWewftd z>7ZU+Dtz#3+JPz~8~kH(ekpoKH=X`go|%$iT%sB2otV(Hm%j{taNw=QWaS}J=hNq- ztDNOIJdAh^p(YLZ(N$}0s6dYn|D@tb9%H@KRn>+e6cT{NM zsFck7Qqy~}g-ZB648K*>FD?~_U*MNFRiU2UnmL9vcSN>wR7z)_DXFQ3=Rik!x`pP^ z_b^>eJ-;e94_1 zKQ?ouGyh7dMqhhon4Q;B=Zf#(;J_Z#h7yN2ql!9NQjH|ynvfS{55e(9(}J#d<7qm5o8Iil8q-E z`rS+OspQQ=pwFQfTp;1Um7Ym&ZYcxl4JMe?fmty%yD7!O8kU=rjKx6l#`_G0Ur@tj zDPCsUyUCe7>8qP~Kc9fz25Pre3W%#Si{98WR42e_BQ=^W13)Z;W)`Kr)&CK^a&6n+EXz4k{S(RvogbY z)SDj-z1z;HKacUw5sYxNL`;U{79HAnFmhh>i&CDu06jJ9-OS{StP~)XGx9wZYCBlG zBPEls`AaV)8}lx?S#0}Qgxm)+d{s~?xsfZcFh2JP)6bl=3QGBsU|wS}kv}$K1y7ce z@IG!eN+Z0J=HNt2dfOGZTvIYr8;KNEL=wJY(A&({LiZkQaFjgyhIfp4t#770iLKl6 zJS7N&NS{vej{96xt-W^dcrv;sw{G4Vmv8s(_zfX1(Rd^{SL#Z7CT^bQicxQZ{_dxp zxgw1Rok}I+;k}q&JK%B9qa5y;OEOyC~c32%z{xO#_mV(JwXcHBdcVKp=-)7EOHM_Vbof5i@`*O^KI@N&hkJ9 zl5PUt=}0HUDVl*{a_pWtUB!H)8^vjAb5zO_p481wPs8v2-i7TG*qxzv?W9<}QZjm$ z7~z*wzV+O@}4 z3k?3db_L}S8{`~xGP6r^Dt?VZPVu;RoS$mNo-pDyMGgufV|k}Le*~Aul zF*6!K>jKkC_r1z^y&{&1cX+fuQZ$1**?9X7BQGI{_a}?@fzP7lj~u*H>OX1>F}*%S zfWHtRxOV_4VdaF?6>2qFvg(;BZ?kkxU!`V0vde<5)tPBsQgYKVpS{<{)9BhYMx5&M z*+0A)@R@Ra0||~~bHZC2m&}R(L8R*}(wl)Ji8S;!(pf<{;O>;(g|1p`(%t7hy(+*? z<}sim7lrC1Q+AW%i^K#}Pot~T4ojylgQc2uqomd_Kg5G`M z`?Bc6I-iv+xfRwjzAu01?ae}Q^_7&t%`h@-9ZV1pBKbaj2z!TibHCJ0zLk5Iu+gx(%leoSXrO#3yqSJOQuLj#RS_%Cso=?2+)RBv zFOT->|J&Dp^&bB7Bk{&Xr~wDxdz z0Ow22B7e;7myreiCm|F4NBMlr?PQe_;OO4T3DDXj*b`~>QMV;xd$|}|dt%?9yZd-| zrH{MahkQ?_<35y)`%pE(_(Z@1b``&a;z6z`edO&y3&rp4D*gz?W0Cq1E-HWQ?J+UK zj+peN8TJ!TIa+%uKMkB;BK4m+j{MQLzX0N5MF#ekNc}gC zC4Kzuc@x!dCMx3{W-oFawDxeW0q07j{wK$gJ_7fO3Fl7>oa-D1tv#H-fpd$q$RC4y z%OovLn>(BUtv!MuR}0RLoWSaoJ9Ia+^R0`mhlh>2ZPkmCY*W}I1M=tT6;K+ffLSIq>soAHz^zQxrtrHC@8wP zqVzGjE+_^ny_)jAqP5r87$`?`W%;9WqfOG7izVepEGIx~kKlO_v~uY!TzWIkA%9$M zD|uPL$K|%bneB9;*~k`}jcQS|(pg{NtZ41Awg>A=F1;-Wl|M4~C16R#VNqMtd;#<% zS}xL~y938UTPCat-paiTu+lh_RJo@CU=OX}{3`dZTp6uBa0Qvr!j=Nvw{*hh9d?@ziic;m?*Fv$sUBw|#EO6-qxu{&Z7l;`) z(4;TTu#b7l(b`M-XyA-=>BBjWT)B?~#8#SiQMnH<9cv87LTe9eGO#AP^zj@^s@x}< zsK%S9j17GX$3bfkX9jSlx%5JgBUSFxOgM!WI5Rm8T6;M2fHQ})$d&sXle9E#=5qqH z_6U}MU=b&fEB8gE6D;KfXzdZK0l_MlzJfzYmHR3zj{E51C@S|ACMu)SS!)+#6EHTo z^kSF3o|8zG`v!4A7lS~)me!k?j9I&xrwFaR6zu}rPM5yjrElYGa^=3$gtT4YZZpA2 z6KOYRL~D=nTQGj(()V#dsdE3u#JA5xWu)vN$3bfk=NNE~xb*Kij#RlHG2wh~f%5~$ zL2D1^XW$&?EK=ou+@x&G=aY67&p`1MSClIEQ&0?4dY$EcMQg9GzeD*PSC%XHb0%rb z#gg*lJSRYFkKif@{&MM;UHV1NAy@8y$;%2V_scl5pDr|_a=%zQ>ov}b)*h?kZlT|C z>9;wkT)E%zFAj@to8}9k_p-_zN4LXm+)qJUCagkl<^C|Rs<;E(bFbnq$p4m>5`L9? zHLi@-p7P^Re$1^`=i+kZ{+Qc)1Eso|gMIv*yCw%gYY#*NNG(nw*X*_21^o}x+2UKX zA7M2+j&8yU(Apyiaa+~wC1Rmm46Qw}r_tTIyt`7(UKg1@LPy-MX0K;gu>ln8b496U zuWzB)(5_+=C`P#TFfJ=9yag_-p6JPJPA&>hK>jn-bWp99FVZas>F$kqC@kk6Oy zvqxD0#c&|B_JCResD)c^#(|_dy@iRVnVARIrQ(j~IB4zRv;|HZx1PXpq&mHg2`9k< z=S7Z#)*jBwz-iA}UNdRNXMRplAtlI;cp`I_l!Vlqn1ES?;+ z_LB1+*m}A3T(_Rh+2pFcmkB9X;AWfQjA_%G)1kFT*B5jjx%Ce@npBT}WFq^}%)>6| zejEp_J)FV78RXUna2%-~A7sKAV1YA)KtnGkK(4#j#Kv%@w73 zd^8jT6;$JRU(wp@>qIDz=gM+DKHemaUB0BWn8XRt+9Q|&f@yBO(5+A99CAHA&AXJK z5--H}$LO+xyXR9&=bOp-(Awi$1il4seIAFCYw!jB#a_`o(;Pu5c$n4TIJy^eEVTa= z%Y)awyvbhkG9apjo*xyU{?3mo$p0xo{XHT5NOK|F&YpfIe}bvkBlnlf84+BKEdj49NlBMI@+?UkB_pdxl4p5a3Qp17n*`@ zPU78^>g`F$?uh{P_EbA+)1X$!)udXx&_Zpx9ksbon;oUk&sXV2pa zMqBm-F9pQnD19M^kZbJ4ke2I(g;p@jI1Jjd!xRB#O_aWh!$|e@8WYPZGYi{}*KriI zWk=ZrlnqgOF-MVV>kTH9Vhfbb90hIJQMLnR8|RSg>TPCOV~N?pb$RRu8KSBJ5DE(-Zewgb^we%0- zvOEfP`Pw*a;xTIJ<2)&7%bt{9!F47|KNY2)Jq9X#eCWXv>ar6DZfC^s5|2s-Lf$P_9~_+~O!`%Z{Qn#T`q| zA=S=zOsdALbu_i1Rvv0WO^rfGs+)tF1}=o|X=)TgXv^Nm2cUW%SCwn#`%JQ^nM+E8 z3S1p++0`G0dX=Vn<)(Ti&LG#zRhsgp0`+obe1DSH%auxJtH#;TmYwZMu+?m;*Wh4s zty~i@Qh`=f14wc)gIf7GtCewd*WyTM|0&X*XYm?w`oY+&UalG4Laz}WpkA&KU66k| zK)w7#v@uQ4+EaEyS&PJ3LP|hM(&!N!; z{r~WPK5u&?REea51#@#KO?shP=B{72Oc|z7U{_4!5fq3B|@- zQL3aHTPV8hDn19rXQTBfE-F{k&x#oqWzv^sSPV}&T6-yP37qE9x`*S)b#-$k>?GY>h!MtdFPP9IYbI6tYJb76` zy*>wLuF{1@ywYS=>8uMmD_VQ3tH8PCd42F#t3{RZiu8O9!nfEf>Tjt<6>(-D zJ#&+txv3^#WD7LFu7pi8MRmCIDmCX~LD!+Eb2#vWqL9hjJWI@;;@?E?If9hQEo%gYKqW8Ld6# zI4H-&>d{>MF26RWQSlgvpT*4x9Ezgx{R~{F`I9wzodCqxZ#;GZ;sMYyR&UM$f@6(~ zlL55!0cdUk@Vs4swg6}ot0!=Po4y%n;{%Xj0q~+-fDQm?$JH>oM<&Sgu`Bc6W zHikuXW0*td8;(WE78q$|#Q55~W%UF`POP5AG2|^P2OP^OhuE^RaAp-f~%Th{wX#F~<6A;#lFyNdZx>>I0p#6{&Tt1ncG`IhyOi2#$d zn56(mcYmG&wDwZ)F@Ofg>Vr6tyk!jr#1g(`4JsXICX4M#btQIFP($jq(8+ zQ996A4usYo&_n=@=QPrmHQoeZY*~}IGFp4epF(*GSC+P{DYCLywFqE^S$>q3E+ViNP=8gOAqU;BSC(ajd?ci%VNpvDmWK%NSyb z+-O&RJLI>;>YKT|v}J9>#;}=g3}VaLY=N=kpJObizh&+9Zdqr5aVl0n!7=15>l8S4 zP!6$Woxqu0^o;M8wTG?OIJ(dB!9n{^2S>*G16aRvCTYw19f{Zj0RP{zF4$GP0>wXL z^-Ek--m?CL>H)rGT{01X<^W3pj_#{G1!(Q1;BNrkiq&s$AbHEW1&D2Y%eqlI&>aqh z)*ev#I6UJTr#tYTn-8^9LgXzgD6Ry^f$!xpk}`Bp9DgD<&L&U=0Nu}Nq%G@y6M(U0 zRpiQO?WLkJlq+#%Y0Ii4D~na@A+C(po^o|4SBulDa&c+Pss?fImQ@wse^0Lyzb)%g zy8urDpk|z2g9AugR!tv(8WsSx>;n7`0Gx5U#sQ=)%jpB4SpbCC1$YVob-22;Wz~VA z&%76d|1=+bwDtzSA(Wqq({(N`ZCTI6d4J2&Wel-pHL@%3f_#%WJ)Fx+TUL`eyy~BB z3}VX)x4>}!bBvJ<5*<$VbpBo-?B@E?8%OMh+K+U;`~CUZ*F5)V|7q?^R1ZS+K%Bmx z3(HUCABgilmA~J_0G{J)XTZ^Yh@+q_JIYa@9OfMI)A)xm0;lN+jAA!HN3k2AXP7#U z?qggXZQ0e2$5}mvUm|pZ3!yE$&?$8DB=4s5^!-WX_zWFqzdt%VZAa}K)Xs7>>8bm( z7HYrQQM&}S3vv2+E+{{3e?iQq^CoR+HeKdvMqBnY-vG+BIQ?jWa;A-H}>wENioJ)RMzJUp+zCf*K0+S|A80SMScUx|kpAP*-{na14Wa)4=`WfkaYN``oViBN z_}&n@!KzLi-F-L`+Oi|{2U0)IBi#(@hkV?Cxc|+d0d~|rhT33{K8Op-H-ZL3@h-m+ zG{~e5lDn+yIJ$@OuA?n`*T(>6lt&-IVdR@YqX2M;-vk;_I?PxOgSPB2lL0f)qmSn> z@(rMgJ}~1;hnd1*(3Tx$8ej@JiFEU)&?Ii`BGb7l+On(8hU!eND&6>*DXWU#{pWC1 zv}IRa1l0u|eI6H5q_^jU02d?mz}d-SDTT)N@2+(&$=h4?Bv z;_D$^VjZ-?qOkG_Qq zOE-D8dAv7yw#W$LCeIE#(qBV*k4OKCOG`I+_F$p!kGWNHgXb#?gnj=U;j9PGNz5px zC}^gmX-B`IKjS|0bMbhUd%PYM&wdNT`I$Ih^lUsz?lAnz+j#fxN3|p4;;G9lJQT)W z9ff=11M%vXn0TeG@z5N}E2bRvbp+94O!=aycxoP2(6?&E(1H1XRcwIMTBL`?oJ$=I z1D~MAWApJ?$cdJCK^DaF9>k|clz_<+?DGJOD0tD!Ktf*w!U4g(0CC!vYwxHF-hVoC zj#f`}R7!L_NOM*R`Rdpl@7NNrH}mGJa!7nU?WWSGpr7-FM90I4jz@}G#N&rB{8MU0 zwx`{!PJg%?OV7AlA!+R7lO=X}c*2N%sA}!V4)JV!YK63p52?_C_q_`3do!eQ1VR5s zkc39Ge~?p)TJz-67p>Kbe3`0geroKb6QCi<&5J2RUNstzQFg%3Jcf}u-jCWLeVQAu z@OhNl8Y+ebWJ8MLX%|I@5*?xKgX#i3(eYHGmhH?$8&!Az<(OkC&&*HM%PfMPxm&@|!GKj}vqLKY>h_NlQCOgi`QTA&erEblBC%hljw*`ba+Bu zlg6ug(Q9;cU2oCxZ0R$ZUI#Qg*{bLjaZS^~G_GlyRm{OI)Xk7FCJ1$7Clf;6Wanc- zx-~OiwpWWzE~Z8&VnPs`2#Jo?AS!y3j(RFfW(WyIosuVS(y19j0!I$2-y3F9~NwIkD!n39R%t5R}Sc5(!nQ$mLe z(+I&59UXn*8J<2%1G9LYrl4f1JYpm!$>c{j9alFR^9`TJDznMUCN7(Lb(zJRiH_tV zmTWPB6CM9%7bWI$SuV=XiH=V6qU?-mmyV0Fd%XU(_o7TqbfhIZx+FTfhIE&%!?%mN zv+J-IrOsd-H;U~nj0ZcJ84|)Tq&jrYyv;63b{!-{zDvEbLUQ;e^At5;@z_)nrgXEU z*R7idWj^olICT0L`JuUse9xHW*``NJvX|({33(?zB=dil`kCgbi9Y`zrz^t?Dt31m?dc^Pr(EQ?jA2Y^ytf&W_Dz(`p zVFTic!>3^z7sG#W38R;F0ZK374-AjU_emPWp^SlDXZivx*j3%Uy zbiwBh$GM_D?4lpQxJTfG4{#nv(Rg4K^_DLF4}35FfyUV7jizROnPCqe_1)D}**h#RU{Y&>*~Iqo_M5vwwIX2!k)^VT&+2Ua zVrEz^gB6UIqcP2y6*$QjR(kPQY1v+B&wktbuRalw{@$Ip+6cZ14Vz5#XDqC#SXf8I z>%+vty2h|8GMaU0LPp37>w26k8W!MpmdLSunte_!M$n~~=V~0wLNN^%&X+y*tFRG; z|0?YM1jAxjegR8Hxq-Tjjt_Z?m-7v2<;5biH8&6iTSiMB@VVxpvzYjh%MZ<{=>1I~ zZzEKTMpORC@w`i$D2TjymuUD6yRmuu_RYI_Phff2j9Bb?HRHU;@xTS8N|#7fHqsU(z3f>SDm~!*=|DW(OLdc?T?< z+(`}ThE9JhnRh{s&m(Io4#$HIhodM`$$1+e8mrI`Wq05MMDe#Q50<+p$gxG3Y>ZUW zQ{PhtI$#qFn_P$E3oEak!t2XOg?VH`p7!hBx|NZpWk!;0J}#?DLEJxYz!B zVRF#QA048RiZ5i6fF!snMr#rTk3FDm^QYKP-zE6->f{Z3(qToJ^!@w zydyksS(ya8yaVfS$pb4=SrH~iw(oZ-;)7gE#wZ*)cR22~a(_f9RCSr=#Y3)uS^Sq( zFjWM5BCzMS#c(A7QuD~_S|mP*k%>%pa}L&;9&c#Jbw_LM*@3(Z{>Ls zo<=f{TbY~{!B6>_h->YQ-Jvc-3+TSm9ptMi1q7Y$>USAB^#+>le49*S?`J zsc&TxDWoF+EG;ErRz5Mp=UKPkej3E8k|-9aji`fCgZJ4W(t#OrHoo3z35C;NfH~; zsaByEi_iB6MY%4D99o(*7WDVb^IvrPCbjtaPxEVS}mCp^~#_FQG< zxmkE_2<%yG<+($6ZnHAkD@=A-nH++Nk?jLfftHd^Y~t;=az8Et<7ProQ;Tb@f-t$y z%A}ewsnXPX)G9X(w3KvaBU;HSbS)9OCUy7!1&3a<4o3|?Z*gTl5$)|>jcB=hZ+S1? z+QLMOHZ3K!th}BQUZK$eurj^TpW$|FDGA39#^i437dOjm?-C}BtxRHs^s@k#mXatd zpH{-Bd9>eB(v@Y6m~^r-=?)Vk+ufoA zP0DQ6@vc_x?+S%n^SsCo+@l^=!TO3|eFA%aVAgowD%cPaY*64}1FSqp3(paOJ%?F& zPJpM8%yCvGQ$_GeekS5tn=VWWtxOgQlX<0#+8lb(nW~arY(!^SgSf2rtm`{`@UcFHC~hcB6?qW zb`-PNA6fYg6@G(dza`9Xkd@z9;WsLf-v}$eNy2Zul}Vv6nPO!!8z#nVoDq0tO!M>H z;LXz_;Wqi;+%wHmwu8Qb?%CqADi+#z;?~d@hCHrk-emAWA z?uqlR^g(gbT5R|^;^Z}4a8?w4_gk4fBupwVWc3%E8`_4EARo2OdBvu0q= z8djbm!qXYpQ?v4XT6Cz6pNU9IBN6-=q*I=ax|Ne#I5mNj-)ua}#xLB;_iMqlJ5Db8 zfAps6kT5wAXDa&lTX`K5UWelX6#b{Y(NAzYw)vmN55{<&^ox7OYyX=tIcsHdSx8?1 zuvGM)xAM6ue6Gd$75&Fq2CrCo26?K0cnvG}xvE0Z^c$?K(z+H0ObMgJdcL|?HA z-BpB6qwfCq59l@PaCG+b7L&4%@cs|HrRx4K=J~G2ujs#q)9kt*09PY<{XFu9al>me zR74-_kv5vUEcPHPzp=t^lRI5pQi&aIbx|?B|Mi0_FQV^`MK~c3hcSY%5#(G&=-CtV)%B5;Mo<>KO>gjrBI4{PZwfu4<5I;H34Nc%!myprPci`6~e zY_>9@1htK?s5r_61-%$wfkq2@DIPB(Le%y=dIzHodReHnh*#cK3h1vk^yNlQhohM+ z@h>LfDEEB4u|+xfOODFL$1B-s_${xT;xJqvL^oQ;E4kf!P(tHm9wQ8TFc>djdYv<- zaK=uYu`_3Ui!*lNZCBo=qb-L%bYnl$%)I8${EEzMq{UJ0&3L67O`l+X!@m;skn=#e0*@dy|9SfHEkT_of%8f0wuK8EsH+{`322sr`T0 z&$L(F{d@Ix;9kAs--#YF?Sn!1FZjVAK<07CejGBNr@TLh9Kc})8g0-Z{&N9u2crdK z@DStY;E(zFq3k?`?&A;rL15^E)V$dXdVGA+dyT`B zUP{YIOUX$~%IefDDX~XdW=>8C)8Rm@ZSt3%W=>QwbJb%r`y zovY4Q7pqIvHR?L`b9J-2Ro$tcQLm|gtAh~yV{L>sTKhzspiR|2(`IS&wAGMWr)`1I zUPv9(e$p;z*CBOV8$bp^Y$zErDPddLDrMaWEa^@_K>g1x8yr=l>9_~Bj?E<PmG#?7qR7132?7&K$&J+R_!|DvI&cfLRQz!Rj)s{)E+Eu(|@PtFXETtLw130jry^x}}a%Z^QC$Sl)rHzJQI#9cf5&l~((C(;%wY%yNEf1sJR~xG3sl)JZxYiG2pRbM7`fH=K z0hk2?wK3WtZLC(Hjl<0NL>r=whsOkXOw@*HleFR5WOz)0$5eQH3Xei~dfU)0Syp zYRk3l+6rw4BJM=QuMlw;BJM`SJ&3p$5x+*neTcYU%U8d_zXMva_AMeGMC3#G_Z^~t zkLZUH{RpBTMf78c{sW@_i0D5d`f)@*f#^RY`bk9p1<_9-`e{TzgXm`w{a5W9?VNT% z`wh{5NA&ZE{s*F8K=g}Qj>qmao^2s@^Klu$;>afs(WO(QxGBK=xObQ!JR)q|~zmLh}u%Tp1 z*f26RY&aPkI)aP~9Z4pJjv|HOqsbTHW5|fmvE<9}ab$b=C!{cRJozki0+|*%kxXz- zA`_jH$;_}RWLDTztO1{rALhM`)P55lGHhd1* z8a9_~3!6tqhR!FWLKl#^;S0&t@I_?$(~HTBrw zRx(cAMm|x$B;(cXSb27k3F=NVQT>Xn57|Y&)^@{Z5BXBvOKxH5yshoSzx`yg`VE<) z9w1ZIZ^;JrAX!2V;qmXt-`e;1cbNPVa)f*ya+Khz#ya)`DO7*N<3Eu*+Hw3lL2ifq zOs1(P$#nG>GDAH@ehoQIW~yh%EcGmzt^P{psOQM^(BH@b?RPR)Jx>m*e~@3*3uK;p z5pgb&yV_;^`;#nC{~`<3D`b&+l`K}TA!pagjL;iol6sS@RBw?b>TR-A{hM4;?~vu{ zU9v*WbFNftD39cwuBs^iilM*g)K5=c^G>ki?p;L*QexgpOUbR@putE*!JjYCGxbxm z(>mw&O2h7jVh(2<6C%v&rer&fvvVh?5)Y^Dz6C*`#)2-`~q@mQhpb zi!wYD)-b%GOBG)YBV4W~O~NB08;euyn}!VhX$Ma5Z%7qnhD`Os<-(r)u2{C!8&iuWq?vBCJG4{tJj^G#uBw(I$);epCV9(c~F zU0>MD_p^&pD#x&X^1M?!6+%zb0r2?}c0Bj=AsXrhOcLKOVaM}NAB#cu6Rhm`7*M+< zcsGKf1L=1qUm_kK2l_}Gj6xLsn;)MqYKN5Sbh@Tzq-DDa3aPf)SzWSIx~na4CP%IF zUS#9CNv+d6XJ_SPy_KsPC6(GPw`Xd4R#Kw|4P8l|tnS@=W~S%%PI}ps)IKXKBPXeK zJAB(Pyndr5^&7bwHf)g8DLpf(RaQ>!tC5Xa@zuFe{nU&MqCNr|J-2s{wAAzrMSttR zFXXa}iY=*gcJCg!SxKET@qcno*Yvk?>vvZ4)T|su@0hOWuPEU-ysGG^<+6L=k;E?e zhX)foHB$8Et?*szW{Tdjx1zU5&rR&qtwqmFSQ+0pOUX^a_gVjk)un($)rrul|A(PV zYFJjd>Me7^8Z~Jgi4L|+O;734x@RtCR|DU#h8~adP>UySRSS14ipM}S!t|~Bc;1?K zl$w~#kG}jMma0deq6^ledFAoJ+pI0&s5ajd=zt1 z-b%~KP3io0{jN%7$C?rEjHx$t?OP|R|Gn@^9WA_y$G(CwPgwW{CuRjd`%LavjoMv_ z|84wN<*Mv?)^-OvrDw6&=MT3zT0LA%nEv>d|0wf{`&3yGV>@<6*OZ*DEc!G3f9^Fk zX>DxNrK=8%Su<^JmF4!Mr)6ie*w3kHS3gYZ@^nzIE)_obHSIu^kq!PaIlmaaqnnLWWdnt=9J)U)A z+m85}9WpP3RXJMSUSRKXQrYp^dvE3+>oNQ1YlGVU_)>WPc9ljnSK`_vXE2L~%0NeX zx~1jOcNCdH@Xgp19AawY&{yeNxt!xz%W{>Lg+#bF-&D=6Q%ri-!3R#3Xe zvdNm9lbh^y_OxsNQhb}1uv+J}+7*Y0&0kIS#3m%f#d=;y7Oy2y^5{EE;4AoejF3-g zm2BLo>vu2BvXVCsfffKDxIkijD?Kwc8Ef1?dJhR^bzruTn%$IQVV%j%NyY`Mc;kHr z!$s6ES&EmL_HJ@!PkKXwcl-(1Ev9x`rGU7Cva*Hh1Q;!$Mzf`0Ia%4cLXg%9OJP$% zc`O>KKoWgZK>ySeUlo)))jPzuY2QXsocJ-gyA&@qEv*N05_EA0x|{|5p?XgG`)SF! zhGPZgqbP{<%1Td77Jss)L5VhT|kdb~Om)r(m?2b>Z_E@BG2&H%r7sNp8`h zjR&LZ<-RD5K^MTKX1$x4oRO6R(Q?KNn2LC7SiB=86SMhCFC`muGPzl7`&fkB2Qz$C zP%62RD6cTy-5OKVoUsZ@`I2B>V=>7;Hev-&mb&>qZc9m{zm}%rL`wzrK-zmfQZiE; zi6m4+`imI!HuH7Ty$4G_E<*1lS?ilAPh#t~JWo-=AkwE(yyHF>TvM;zJD!ZL$*r5W zPEPIFy*q0BylCT*;9RLI>6y6EmMg}!3HrN{cIJvS9(1yljEDC^n+4-d)VQq_GP7rQ z5s%K3&8+urBE884zYnm-3*1jk>p+hl#ULg7jkV}nbKbR(W^_%)Y-I!FT{s@WquVLw zF*ZQ&8Y3hP&<=)JwdCp*0~60f@0RjGr;(TdBhbgMSb%#dq_>-VY`p1D;DPQ+fikmF z)3Ce-TEh0SkcVUaI*pM$2tj-Wr$}j+nCO!9H4Csni`)Y<45bX+9Wc+}e49J}!t&fXE1UjGoQylSB2|we3H#w3 z9L`3H4ijDCy%UN){0)70m@MBjr>mGzbQ?H8ZH`Kb#1kUf>1p`=+spY0?7pRT?W9<} zQZjm$7~vO0!E@b};niC!;SFl;=hM*t``JLtKy#nO7O}1P;!ZDCpiM_2>|T zxW#seNc{H6hNq>FZr2|BDyS4M)t}6=akzI+IK-w&4swv$B{>zp=wMV}&u2;nCCg(B z(FJdS9sY}v&&v1;pQ?wX45#7-du~bUXnwzE)D;3HK;-E)BUlCH5%1OIqtuZrb&;}z z>BbgnF)tcG>nPJo_r1b+Eh3hIH+Zx@QZ$1*+4z%oV-ANP-cKyv2R@6AKXUL+ssE@S z#N_%A0gfX;aPI(8!paG&6Vz(7WYsg%*e1Q}6P?jNGn!PF&)V+oozG+vi~E~_4Mh(+ zdy{^^-6_2b7Gz^O+~+;LD!?YXiPWF}sKo#DmDK zPanO7N6R>cuCP6N<|Z4JpLa2;iSTC`=(nhgTej&ympGom;2F}0ruHmZADcq>SDJ|Z zQX=?1>s_5j!|EIho)Ty%eK@^i(S@y;bSU{#(?(51H@DxY+#3>+?_{kCt>0mS`)ta; zUeC*;dHMhL^+@D0Wl-J><&Ba07hGKa6rzohc-Ip4CM{o>IKXtVBK;tA9Nk+u4qAIS zJAm^gXOTaN=*!50{*&lO*^l!1B%;YGCBV_WlM|q|N3bW->eGly#P)JAwD!clL3j7@ z?n<9Xv=8~7OvimF8~35!&wW2&SMfV29^{JBrxG2sQ2gGm;*U@~7O5ZMqVgvb9TPL` zh)G|XVL$PdqqUdv)4=&9QvaFb$e&L13m`65gz#|hrxX2LI@TGEh1MR{1z??z)PLhx z(kB$1H&Oj&qB7o}=px5KYY*odaIQq^e{vk@Q;M#baQ?Kwxz2IW+Qa!9IJY>9{7FT( zOw!V{xx)$2+9L>Zwa^_dV}+JKt;pf>zf>iHV3)B{qqRp+0R;EE^m{pk^od3Hy9)ZR zq>JM!wm2?Ui|#d18K3%6(Jn?cU{rPK54rSzaT4iMi>kW3TgF2mkguhGnV5`O`v^}F zT6-y~1-2(#`r|JBG0rA`a?ukeq{jvBV?=@X3Vn{et`;56hoXzk%N22MC9VW1t+(mE}(}iZ)4OE|!!Zv77*{J%Z;!(8{H^aOurBhx~~~ zt>k3|pJ>zqXSUOYW+Pi@HmXImw+V|hed5o^99h8 zXt_v_?hYIaZJDs>o4B&dy$i6?IFnSlrvYFOt>FAB_pV$Stv%&TC}+6zZd_ch+%v?w z*3HBLrmd`Q#?hU{anRbs$pua}XOS!SYz)p`I%j+<_pccNj_#hE0IfZO-Y%=ky+rJN zE{4{gSRZuv1KwS!a{mDN{+f=vU*-OhUB!GT_T`FF<=)pqvAxf_T)7vB z88*3Lr9hTDlCrs=;A0U_Z228qtaPx7h@AJ zHn{X+m%g5pNR|5raX}Y@K)#mNo0yDQyP2m5t-TcO0^3fPzTKs7<7{%}zSD%XUEppr z!ATQoH)lj^kMUbDe&f>jaX_hZ|Hj0(&qQUU>>$TMYY*obaE`e2?>UZCxgRm%d~bpC z1IIyY59ep#9Oo=j<$m0xY|Q7Ab`{S+@f25-D)&=R3{-lZ<$XnKudlyD`5af4EBA9I zY0Slv^5Z-wKx>cSDhU2^>6cylMb05t?tjV43M%)@IJ2KFG@^39SUT%9&WhF^tKx2< z-*M@;IjCH@-|;UFi*B3d3!wM1${k0y!)@G8L0cxQLT}~%FtDn)1Ke}3;x5SlmX;EJ zm3uX=jMkp=<4}Igtykyba^?P*+j|40x|xH03Z1(q2SIBOL<2}IP9fLqwcG{$57XJ= zTeBZwH9L-O!U@pYBM5O@)$Ao=pPF zm+rGiSpmgxAhh;?S^=nqTW`jJq&mHYiKm&F2iK+Ij^{XN?cuZqP8+wLz;UEHy^RSc z!2;(+j)T@7&db1Q&spR;y}eo5m@2PuZM62Zlc3#^Ys(dSM=R|&xHejQ+Nsd)+Jf5_3Kdi*03*@tEx zc0u>!IB4zR3gbL)j}eJbaW>+xyc zr396DA-+FGmlfPSpISQKOwNba9^WGHEpY4eIGkLAFYqt+isqT-2ui`jtOm!?y_jR6 z{ij$Syzb>qcISLRR0};nDnR|6A61b5Q-Jz=V3bk$qbKy)yD8P%laSpL0qX6kcGRXpt&popwRWL}+H^Z=bD=gnN}tIEgzQomQ`jJwjHnI zC}_)$vI!^~qV!^pBGuL#Oen<`D4RJ7+Onf;2g)|iA=lO0%(BK3vxDoRExYa>=z_zzL~(J1{e*OzMP zAH-#O6zcM|aoEIT)Y8X!QqYz?DZhg2Oq6~qN{`2;I}vD1^|Ky^jw-^**jD*Ua~sWKlDh zlm->JI@+?UKMeIMP4&u6^-7#Uu9vGcPedEj1g$+~CzQ2ly%rajYi2FlTQk=(abVt@Wwk4g?%Es&tv#H&zzO9na`hY< zUC{pz|LXYyBf!!96emDykDz|ERRvul_6!$8Yfmf;-EGLbD^<}Ak?#uus_1aLijh!k z%oU|dy0L|#%dX;cP<%F8kK&?oHT|rZVNoW1X@mNkx?{hY}7Vl$1`as~mZ-SF1QeV!9)*j- zsY0Iw#XzOkRNhy#_WC*v%7t86uF?xl(wK`S<;QeRfYu(t0uaoL*5^d)vp9!bsn3&_ z71ZlZJ}3=)host#rw{f;)49^s*=|Sf3;dv8Lvps*C2e0y`uh>T2v8d z2GTP(*_oSa0!Fq#qkrj$qq}OXQP!iihxHh+s&l5@F~$Av4Z?f#P^9Wi38H}PK#vK= zbyUNyq6)<)WA&O`bU#f5UUZN*hN?aZ)v+4%@+%hAG!cMiEK327ZjGk^t-Tb~0Z>S+ zUYi3Q@&b*gKp}w0qd>#eqS~bc)#X5F?Ey6aQ2kiF9tS!q0oC^bs#iKtLk@)29#CTd zg>#y%F~#(DPu@hDop2L?vFkM9%4qE=M?u-emCr*tjwpGbQe~H{JXyovMB_nsQ?88G zo^l+NV`BAaE`FC^8`G$G48+gkW&{pJ(fED_F4X+V8of>cVq7O4y8!V3Xc?L41TKWJqw*YwFE_&W*K6 z4F1b}@X^{E{3IxMjMZP|;#YXrXVby&NGDnc{407@#t=*78+PSWA>S!hPv-K+x%_-8 z-w7MTBDyimq4N#LqGStOWE`p86p zNm|TOfTO!VPXStcDfk#bgJbnU97x`>1_NRV-?9dk4m6Ylp|uAz20)`?^${FM-m*sd z0F5XeXe^fKJcTPuTh1;8S^04o5nELLB_ z0i-Q!nGe7c3xJh&0oDRwHCLCmtkqETS)0V*7xBSIYj5y3K)E=*zwOXmeb#|_IkIhGr%|%tDoQ)@|JZ9 z96Kn7*s@OG%r1Jycgxzt)@vNyXZhfu{ilN?WBmcF-#L@CW&Mss>;ZuPZ&?@YDqex& zpRxKSE-G(Xe?s*D-?A>52tadyr2t3wRh|O0_EPXSfNsU=H#m^IW!(bAHoj%uC>`hy z2SRHPsC*oragEa*c*D$x+9@IOmK79N0_4E=@)$`Ox+ji55gTU{r~-iQ=QPrmb-xL~ z*s>~eWwiEEQ5njWxU#fmRg#s(s`U_8Mr%*GI+Ux$=~cP7v}IL;xOdB{itoRt*NNYj z^{8EdCjn41POrfMq%Eta4?qnIfLe9|{s#cgI9=la(w61)0njV}LhJ%O1%NtSUD~qh zK+$L3i@|@I4?bFZgWnL!&&26E7nioIXX3oSW$7}8*s>bgm3KkDNt_d$DinqiOAULgFHr!fwt@@4*=ypkA9EG zD0rl&>hCk5+=Dan%rsCca1^vzrRvC=bM}pZP_`yfHTdbcjl1t zQ}1a&k_x(_&ZhYR;M26kqepjFj)b->NOf3+{UMP4wcpPq#SKsd6+e)VnF+R59JUrnLn&=jmV_k;#kE?x0hQ9$ zE`ocYP|CjVAZ6e8H3*0x2&lNAxZs96DkzG`rv0CL=gw^=$?((Wd!9d7hn!eJW+wlPk1G$S-#2pR*%Ds~}g zbPzj~RMDp6=ortMjE7l9^STg-GO24&5~%!8OYPIVR& zW4r(~$4|_xYm1rB#GtIXm_-n?kSQ@-{8<=8uB{@A87s<~vn~hgQpRey@Uzs&%HR91 zV5}%>&bkh)Yng$4Hk|NntT{PBruzC`K zdNcyeLa&&jv|64tS!si~boYo2BR@5?S@TA0ZvdFt(g0g%yERg+-CFlFwLd_DdnYjx zwE4Lkx{6l*$4?CLcfO9F7(W6grctWZ(GOVGl*a!9Z4VM{cLivpl}%Eu(IE4P|BZCH z{A3AH6=l#5>K0OD4;LkAQ!&B@gpA(n$!bWT z9evQO-Y&gTY)dMmQR(YRvfq#1FDi=teyvZH$nGwPq`lIX(6#~#W3oY8^$A~h7f#Xs zy3yBzJg-AeR@G+K&7hOn;G7p99g=_E+7v+>;7rD^isBp^ad&Ej1Dd0uBGu{tC{u{k}#)5Rm+M+XfurzV4@rAKT* z22D$Zy;c{zVQ{Gr>w^XtoLhUu7>^k15!*#Zrf9eDH6#Q4Q95*x%#)NJ_FS!5?IUAT zw7bn35tE1MAk*?4A+h_(evC9F4s8O`BRV28UCd#?=wZp-A@Xs5gAi#JADQLyWzu|j zoQ76=K`E{Gp&KzFVq8Yx=YvTC#NZ(|wKDe|897rd*`LtblMpb7vWR~=l>M8g59Pt6 zDV+!-8_H;8G_6czj)?>|uV~@ZD~$6>65;{{9x*vG-Q@=jF?O7h{arq-!H6MkZ9NDG zZZJ!-l*kO1uRqOm5`o$z4qlqa$Yk?iG;JNwl9N@UDjgvziDxIOrp>n4V@mbhhON~ z1WXfvB~8zu(`31f8$zJH{LX0|P6I%Z(bU4@5qne7+AyZ$;eI-d$Q-xIg0C82- zKl)W3vi7BV#J*%0r(zh7#oAZoQVU&bzCM!sdBg`i;)5RXVUPHTM@;h-={pBOv6pMz z@>pcoWNr91!SJPuNwRDCjbZ$nMCyjpIy~`CLE`8ytmH`#jPl1RPHR;OiA6fH83Z0N zBl0O%HEm)o7RSthK~_j77CKt1S5ew8)o zSkR7k zsPvWc46)f?Bp&m0jkGhg^A@8f-!ob(DAst2ue%PgMZ+P++88{eV)Or@*fIcy2Z}|d zLF@=EoeLtLb^Q}P9E~%BNj(4XvhA*K_Y{3M16evgaet6Z_v`=K0Fm7`Vm1|?qGeJS99`SjP_yXP=kW~uBaIGjq;hV@4RIxAC`rJDbC;sI$HWiSdY0Ntc zwWOtNEuTy}#aoU_^bpAKqJmIOb5+aWQ<`@SIW@!ols<)c$C6Xi*)%f4e;VJVli@wJ$*u!G;9XJDw03_G4rHrcCsucLFT@I#X-nL{y@Q@C1uV z#K#m@fFj02*O7%DpcU6PkW3byl&i(Z1pso$i}TdW70LUP7DaW7?hKzeb?aM}1Nc zl6?VENa&0R`(=D2*b>BLS0!X|b$H+z@;A4-;!^ZpI?&7rTb6CL(7G`6c?>R}@8` zT__%mUwakEPa})?aZvmnN?pr!R`CEg*=HAWv&nDR!zKbYC8D_340VK~4%r3rL#P== z__^H(-FqY5`!QxmsgC1?K-Ihx;J2}E{}DI&z|7qa8{~dshWVajzOf71uj}ek z$q!76;#X$KUpewjXyi|3$cr5LM`+~lX2`!e@`{;BM4aBSVw|yKc_{0^M2q%~aRUF5 z*6KcrMa)Ism^qWUvnHXDje|M2{4?>k@}SSNJsj_2KFs?Mizz#msd- z?z#_whZ?h@*gF8t(`gV#=LDGa)CX??H^~d`&L_-Jr5sfhN>(r3`!mdrP9-nmh1MU> z1^D&o_9MB;a5Ix}oVo&n4O2`m_MNND8i!5jz8 zoPEHZy%*ZqJ7&nwIP#Ow$dAmBUjwNH^Gh?6AGq^x15Ef>JHt(WG&A{=o1DK!ul*Ks zD!HHb=&xq3MTfrp{B1U7Me%9?nvcxeIl8{XxOk=NgZD0O@*hXg>eJ8+rEpYJM~E5j zVcmNav!heVeR!euM|6PSM|Atv+@yt>iJeoognw z5*nFehPekQba6PlRsK zATwuAb7xP5MwSF~6qz|2!JWMr+S&7F$gvzbIy7>W8FDg^S}-S=natqMrv{ktu{M{R z%rY}s%1stsqt_OaK^L?uNuxcwz|8e}?s|>cm=(oU0cbul%RA^3QCSD$RFbX_-U-}f zY=@w!q{0j}jiV-a2r-rP*S*hXc62IPfEQYS%nk6Hq1!L!CJW6>R&na(5Nw!AmYQKU zam@M-A*YhHX2@L}xg#`kn;CLHN4^poxyKB7m?ICGnH=LLZz&3mn0e5k1;i}vWvX0DrZ*LM+k;2Rt=W<{}4 z0Gf}?CJB1;8YLK;H$We}&A5r25HyuEHACIYQBesYWaaDLTQWO3mBiwOmfWoa{1)i; zaonVxnMoq2?g+t#sicD$rW?m}P6(Jv2GIyQ&5-wVWUtW39%jggIr4$f$W$|AI!C6N zndESjOf!=qFwvs@L_(;fETRn`WCkC~8A^ilq9}BW3eB7i=gwXTjeIVc;~6t&W4W`@ zp`DE~Lr&$$NuiMw%#gEz)Pgy~%wz#~J~zOGkF~|zWTBbKT5huH8ojoH47#9Q$y2mP zmzlZV&RuUY8?&OgDFDq!W`iVsDyf$wWDUsoyE0lvdFvzzgACQ>sHWq-5ujS|8YT&O zgZ!@8R_G=&_x|4`A=}SlI`w^*87`XRB8@mN#Wgd-wdS}Mp>X$^;o5UtteHtXH;FSd zal%9kNMe#uP+H>GUTr!`2tY2; z;mi}tE$n)`B8m^0fpRz~6QF{Oyga|0T1WdY-3@d6 zeTQx`l6xO+%#J@0y`L<*1L7Lu~rL)4iW!c69Oo4llI+{5rtz_qzR0+~fx{ zlixV?FA!|l^q(=qT;`ZRlLI#WU(yKvVTQCi^${RALn8k+L)PZV8$u(ma~ivZ2jNzZ zyxGj8Avd|r%%mwyv}oVu47KV1kv6=M89bUZL^^}=qFLw`DQ3=MxU*KFku8Eb?lW^1 z&z;4EcGlhunZl7tp^=@;kZvHgV0JY#@o?uo0!;W=OXVi_o0&Y$O&+~QuRZJxwdp@g zd-Opw*Mqq090Cu#en7^oC}stqc~ZW>(a!>H*xjF}$f3@FP5+;$rsIATpjz-oIE@R& zCEa8^_ddpHSZJ!K@6l$s=^Qu3h&xAdlgx1QIc`oU+$=NPVvbvAX0n2tEHyJ(4-+jQ zYn&k$wp9U05%*=%P;TSM&7qMS&5*k}(ia-J!wmT~Ftb{mv?O-|b#w`txh2Jhb)kbx$nbk(b)6o~ zZkiWsZ&w{bv{^(ii)D2P_H z^mJ*3Hqqh+u#h0N8n2CfTxM~BBe=G^OTe2(4z6pZ|3%cb z;^wEvSd<26?XwKj+GojS`k!F!8O&biv2qA4NxL2m)vkv_w=2sfJVCqP5tRzHH(m$A+*XN?`r$_iGF;f*hH3HgRR zDhw5k{Ls;O3gDrJa13<`d6|ZqXI#R7pl*H^W_}$iT1o@MI1G$NM^Dq(81h9=1Vm`E z7NLmwS|lPCXpx9`NsC0pLRMeN>KCyHEoKo}!pfzjv{)_6*z4t5XR+=U)kSe7m(sF5~v|3s( zZIpIMyQJOHe(5#oi1fYmr}URJ8s5jrljN!LOnJ7vK(3UR$*bh;;Myf00MjvWeIS1! z{~})m*Hw9xQVzE9$^>PSGFh3TOjV{S)0LUZEM<-|SDCLYP!=kc%3@`?vRc`s>{4D< zb}M_81Ij_=i1McLq4KfviSn89wepSfz49NgT@-|EP_|v#25sA=ojCe%+=b)IRO`#q z9w^?6<10As!|_!d_v3hgw&Q?w5Un|c(T zy$iedP;(qL@1y1e)SN)ghp71oH6Nqq6V#l9u1~@D8P0r;Ghg7$mpFF{XTQR^uW{}h zSbYnt?_l*ktbTyiX;}RTtDj)?Gpx?Q>MX2&fz_|DItQ!YVD&q!&co^tSY3eCpRl?J zt4pxD467^B6zM7~|AOV;u&jcmSH2((m;aPT$QPwD`I0nJzATNBuSn(cRrKUvQic4t zG)AtH#>!sw>Tr3y?3E_qF;O0YJ}#3d%Om9}@+kCnxjaoCEl-y#N+1>iu^5OYKr97f84$~XSRt>MRsyvOsMSEN0ctH! z>wsD>&y+UEv!spkY-y7`N7^jUmA1gsR(RS5Put;X2R!YBCm%fRl2^(veqG)oABM*x@OTs+-+;$A;qfhaJO+<% z!{a;f_^wwEUj@qkLTc3EqE(_cQQ*7T$k>_g~@t9K8Pq@4v(Q zd3gT=-Y>xWpYVPW-Y>!XWq7{=?^ogdFS%U$8;>fmc$M$v;mQy42<5a~ru-<6RDQyU zoDfy6OpF?>%!#Q`=EjUswndJ`W1KQCX1p>#W`eRHW}-4ZYLYS|YO*rhHbt3Zo2o30 znWij@nXb%eK0}!kHB)&lW|nd=X1200YK~GFHCI^_HBZ@$@w^2idaLph#`;2x_DYQR zMaru&i!OO;bm%aoZ>%avJCE0i_LO5j#06QtG3hw>U_qO?|-B&|~>OY4;> z(gtO!v{9KRZBouio0aL(7Uih4Rhc1eQ)Wurm08jbWwx|anIrj>mm_y6=q+G&D~F^# z$`#CUSLIjm*r&{sURCBx`;`UK0p%6xHJm%B{3Rd4<8|em$ivF+$Ro0<@s zUpXzER8~o!!pCPymHas#Unpy&FO{{@DP^7Xm4flF%$2@Two2bB8>H`)jnelDMz(TQ zI<0J$epI$dKPl%Uf5!Pn!X4hP8wkQJiR2Aji`?uTPezDURf1p@5(ngDl(cBoYBK)3 zR;y`|U6hkm@>C9%7ToU+8}SA5)bOuGR&HLi0Rw3rz7hd8!-=WkAGH~nN9)KsWfdj7 zyE6WxHo5tL>cB~VKUG3(Au$26@mft__k97n&)#3(0*x>Us!c$_0kg6nKbMtbF916BMy^9J4 z7G(^Px}c_5x@VZZU36N{+^nL4;(`GslD6TI`j(Vt=N6>3Y1KL|%~>#HNNIj<$kCY26BnOCGYfqg$h_HZ8LA@)U_QP%U}7 zFef`VPf!Q^^KDjvwx3GNDtfxGq#!LbAOEKpW#nhK$P(1-f?`2^Bv()$6k>6BNKmoS zDk{Vo&p-BhYwi(}ffZ)ZpQdS~Zm4D4B2g4}B5|F5;vDcstn$(7q<#W&sPhBipv z293Qto)m^5mG69@E@rAb?G3|T?gm;{e~tYgw?gl;-2AM((roOD zSsxZ>49F=i$;cYqVvtZz+%f6NY4?raIp9>ozt;Y7j~rXSbNCEemQeStPA!Y**s|nk zo4$XzewuaEQvX=Tup5w>TR?rE`MB4~hOttQ#f=X|@@-yUcGxICv|fsCJH026Cy;h@@~O<8@Ui9)IZrU zJOOOdsV6>rR{i}YN2~U=K7HuZ$;vmEZf@-sGV{r4pcU)^73UN2zsTaZYJ=K``hS0!qlmVYxr(L{~zQi5@F1@dLq(F#SqE zKN8UOQGQI%lIBrsau}GyTbT&VIf9w_1P+6M@xCT>t7pBjTe3AOMMV4hq==8Eh=WqZ zZ7G)LI!BD`Y`M8VZzcDJwgOrVZ|8}(oI)H{W5;pxpn4YZS+q4Lu&p7We-LQhCvo`J zAG(dUcwkO`PEkflPI`86MtXiheimtjMmrR=7YTM7!Aj9MSj9p0uDf|gJInlbq_-}| zi`_|wk#?ZN&X7J6Z+45fyCWL8(Q_8Gi-a||I2~6#(~EOT;2hT#;i)~GUxM?9N9}^A zcjsPx`}RmL9!yOt$X`jq#DR^=Wth|!jysZF9@GrfwlcMa+$1_Fq@%BNu(NM!A6Kug zu-c_ty_pP;ogYefCiUo%oaF4D&TmB$yw8Fk{~}H$a{3+X19c735~8^S_W3ye(i(+|F+&^vx;hnKOhtazW21AR`tT7?D-! zSwjlb+27-7x#NPDa$>vMV2eZ~0mvcqk(P%MFdR(`XBrHP2jvbRcROj`?uAhWjA{#e z67_sTwxoEFSm|B*^>U&=nC{xbg@y=LOdA%RbA~P&2(8%#L-W(~3NoOVl=bq`=r9+0`Et+=;bsJ<4`q| z3ijCbZb8fanmS9UFzrt)x;GE!5z-Lo}PmuuW0eQruGnYjtimo6S z7_{^CVG)b7^Qn{Ds%Hk?s|y(REkn#m4)W}oggCrJ9b8XT=q+U(t9MbQ=BT#thl@>g z&eVs{bq_HD0l!hi76**C{DSNpO!=Xv)y1HS=-!cAXW_atI-1MLg~KIO&L>F$5dqx? z5Q~2i$KwTOpND&=deVpBCcgrF?8PR4`hYJb6q$yOH?){crpqYBTHdjIypcb2$G_Ub ze!p>$)VCYRhcfax2G@lJ1R3h{3LQ5n_;rxUVtAaP0m;sNiZ>(+ja^Fw zjx-1)t2wtJja^6eU7>59UBF%wkijmYPg1Xx^vtKRKjhX;;c-2+?#4y;O~pn7?O|74 zY74(pN9|(u)$>D|f5nJi{=jq$+zfOk>{$xd77CqO&;FtZNnSKfC8fLLqp$W z<5L$*2>v~@k;<$SDs();n>1&&g@*c&_hZ`3mfs>+2)K- zKHHeL7Y*Jt-Ras_L};lW34c4NzvulX!$8RqM-A=AhKe`-c{tb!2NBPNpyF0GSow(6 zG=o)XzP1n0XGM}8yQrF+IKS0OZ=GKnvgN9_kRIBQx8P+x=pQ<;QPyU^{wzB9NS0<@ zMs_w2@Lf2!n@V`!k(oOXOOKX6H|T!0hge7b`f(5QT`PEIEiKL%Xg0s@CBZpsj54Tm zOLB%_JoxQnULl4v+6hkF_3yuVO9Agbs(VWaf#mWV+cB_!L_9~|IbdVQhnoW~UM23g z(Xm}zN+h-im+Fe`tiLEqb9U-m7*wa@VYe#+hC(B2X zF|(uK;5ACIjt}(z**hP2EstzH}AL41e=(qH>sC@L(sprQa8e@`P z?0yw3&}3h5n9xQ!4|4!ID3SgecYhee>^sTlA|!e6>I_5CvbIKxc-($ zy2;HEhB1}0(<8@#Pa6mE*E z7`c^9j@#(uxL)$z5Tr``v8TG>%D4kEZi`dv$Eo$0l2Vo&cB16AIDN^e4+X}tR4+)A zmbDF8h){+XA_?058>ikCr#52R9@V?50}=P%AW3&|xs8Iv8M;ws8c~L)F&Y}9;?%pD zz>)qVD=J9e-9f6fkloAVpbSq=YshICr>acO7=Jk}gXE|ta@sICD8rM}9&*|;Ei3$& zr?x@NT0YyuWsC=-gE6jVt*2Wr2N*+by*jeCq71LCNnq~8n3s|~C3~HYBu_g9Q6m?t z_d3Z;0m|?cbcX_0oZ2-`?aXxK>pGl7hs!vv;D^k*qULon(d?rW%|6N3`Py20Fs&%V z)7lSO`^KsFGogzhlxzjPZX&cVWEnPxzWamn1)}GY?IJlk9$>Oi)=1WDedj(1vIa0s zhMoHW2zZO^-~x8;xr`ZQc+3T09ulVxX5_}5`w%{_4Gz))O|Q{?GmefzCI@ABa!Mhm zm}xQY+>6mU$4JhgyZFxiZK?oA$5TuJ%J39C6KA$_uO@qzk)aHa>_s&9dDdLR&i#4B z`)$(i0XuhZxQrvgID#=6cJ3og7)OQ6I1Y?s;?&WM)VOmW!!vAj5WgYA#7cTP_UjU zFz(#fUt7T@rT}Gl3U)%l_BeGb6Jgl7Z^z{L4w)SJ&V6f;Ds89Z3s=T|$k-RB?u}D- zGbM(d`#wIP_di4*F`>qtdsX1((DzqRzCiRbx^u_TVR2~JQ&84O)r6UH{-GTOn|&Y{LKQsbVz9nY=UAbxy~Qie}*;#jazh8OHa2uX0L z@l1$ux1Ip{GQ)NDcr!ssOc2WO1i2unt3&O~1R3_}U4!&=4%S0Icylv3D8rL;Kje5E zYELG|uut~{$?0h#rw@~ZGCVmCLQX%X#kf!J7fh|C%0rABWq90=f%{R$ZQP+hYR3II z<3<@CcMiC-9BKxmH|))`FbSTNaLEGK(=&pUXuFsJ;R+~#fFTZbutUvd8VtMgA$-UV zh63Z5$qmw^Z7~a3a8QO9oTs5}s6#DvsKrd1aaTSxNKz@6TO2G-OPgnyI+Wq58v%7* zhx!7OX4sE=gOt4xtcMQhGA0LQcyh)Om;#jH zDOd^xiydmELw$+qFz&|}>r)AK;+1&*DVbJq_57u4>s!Y3p$t#odgxp0P**c?#y$Aj zz|Ed-bx@9AEBG`+nmMTq_P=nmS> zA7#y1CxCTa2Xzc1HtxO0b0%grbOoNCiOo4IVJ*7j%$S(u;-KXfj z8%M`<#*VV)?6W(V?YXOo<}f0ZH78ntX3k^HH0-zMA-bnR?6+SEhix&~DjAz$uU%=v zwj><3RbX4uL0!fOjr;5sJdc(IakG8)Y8GIWH4pG6h}h6UUB^Ti_t+aiZQL)cGZV9! zi9uO&F}omUX9smV6Jyw4?+ntiJy;7}j$dX{P}W?^en{EZLEX!w81~ltf~4#4*8cL|Gb0xX$SQa#&6h5f6j;Hr(idZjZcE~XnW~XEGQ^z z9+V%U>xT~NcOBGkm@eZ!`iCGn-*Ktm1PjyBaFqWElh)PzuX|6O%>QL--_p7v;Fcd*Vc9i(}uF<+L}UJlX$f;6K32iH-Q+#2F=$P zl8l=f?3KTydu1FQ5|f1T-%2{x5%-8+71%xEO%l4OjT1ubmm4QklzkUszx>|>Elp5{ z$J`9eN`fjea^s#^NznJqQjiYh%@1_%ilgIhCI@ABa_)tkdzcpE?)jdCijijnchA32 z1vomIGX*HaQ_wQOYzJLU){2p#438`p&27V)YuH7%LA-wnv5RgSE@K=R+cQSPPP)Ab zqa$3#L@*{KsPT-{xSLMk85SSJZ^*DD7IKu~g}fW&bV*QCm>lE2x(h`7K*G-NG)cL( zEEki7GCW!LLzX8&?a5>rcG#XERXu}LX*-%eOb*KMk0{`@tYN{Y>OM z!sMU~Pfj}IJjS#bciN8yQ5({xKU07*JOw#Wki`@j_uN_6Rxp4mKpCEbAy6hp2lOw;=BsWNvwwuWhSH@7tC{0j{6VxY}62m^cln>})C@_wtCxbL;Sv!n{ z2xWL78V+qQCaBLRsLwKO#=ZE9L6V;5a-R(nXGo+GOe4zhG>(PFiUhTs2{i1=D}wZu z2dUCRHjc?b8J?V}kTW?!oyg=EcIK0VX6?deU$soQ$ z?~cAA`RbykoYY*VHJ9mMI#$T!FCB4o+?J$m>rsX$s}W?~$uzx{sQvNbWFqNK%7k=+ zNc{2PMg5Nt8;8p%gRyCn+Juq5M*@MH4!qL{Yg4dJm%&$7$JZoC0n|*VA;8h0un?dO zF9gvL6qTgj%>;d@3z|g)ML~p@2*RHM-hFLB_cB2!!xPjRf?6i2DiidnK~PISLF%;y zwPAu#h9{^!1hr*q4kl`UnLLL?r)`h`ZPl?eW|ZME$Aj6yn9qVaSrNQ15oU*xd7g~F ziN;AsN5+gYJZ2}DlakaOH-o&@qAa4`Z0Une|Yf`M8#PbT98LbUZJC0qe+ z2xYN$VWSK_MLr%beGcfe zlGOf;{uHBMP3W_*FsvgB!wQmbIQsgV$QV#V8E@-L)>DvClB5pz}43j-jk`P}Zn(xUA

        shABuw*@pKv&AO%R$Jv0P3I!3V&pbRer;~{8ll3Kw88JDcF5V3(RSryk7G=T|18J?i& z5HvMOoy-Iom#nFNf+k;E&%$eW6#_OVsT-L9!;-bxPrybK0o%eA;Ddl2jNPzg?Es_S+{8P77wdeK;dTB# zFz-!LcQbOslC_sFS-Xug_!RkSxb%lXe<(>kz~~K2)*&nm`^mzPZk1{;f3ID z2)df2US@)fOV(A0ILMZ)%hwiE#RQ=YPtbMA_{23?wcy)MZ|y5Y8kekyRAy8M|T0iUy-!-t*4Ck99uE@H)Q@m|G>QEf~3B$!e9X zzsqW2l);y*m~iPGptmQhZ5h2`$+9Qou79#H@FlCQiHr{aUPdf#f3?xuU*Cp=w-~?S zizD6w+vgf6K zS#v3$Ldqvhhw)?lPtXJ3ksg@h_k|JPQ+6C3pD}inHD^DSZ1xd;HPKg$2xZNQzC$y= zVa+sreE$t%{5|RCfIm9>J{-26z;>Fk89ur{ZNm0*IBdUx?bl@WEF(02Z2v3Irn5oZ zhHUzsg&Aed!+aT1E+(rNm=xnj_7@@GOA_jd^ny07=U%wBq$^Ak%9=~EI=iT%Q>|i> z3?J8v&Ok*~L5j4MKEkQ(F;LcAN^MBF(WzeV)HXbZkLqs>l5#z2jG3uPsl%k8thtn1 zA>|gP!}u}%EkU$~G^x+nQP!NjA=qzc?8cAiZ@)JCos1o2&DooRy@^w8%mf%do^Rr; z82KZa^!Uf~je`_vmzSk*Bt%0(lvBOisoIzd!$EAqKTBwObW`HOL0R=H>ShzQGB-`RxNkChr{LpTTjMj z_!zz?*g|cYdb2j7ta%$#!PPGL>fPO9{@>)4V^DLC_f+i zM@KG`gt8`*?x8#E7a-|5r#g&DGF}jR4wBB3DDewI!%*`lsqw!cbcyadadf=MB%!Ri zq*0Jm#`G9229+Tmmp~qPF{nHow((#a>r^Wkq47e{STI(x3qch@>`+ogn~tMn0&6$lIC~MBT9;|Df>S{)8 zxahMM#QH^_)p$N!K^6vF^w|&&`8JSmajKgbx#5D(7C-V$Cgj`0A>R%1T~2i;BR5>^ z+2u#R(}a9aIOMN_{1wJ*xX|+o*!<=l-r4(EXQQlnXCDUZA*cEpBQ{**IpowY^1No0 zz%TL~35WU}P#<%uZ!l`Z1)gJ==tm;AsxR=oVItw(e=p&*6Q4;eu?PZ+#VGocC*(D* zGbg%mm%B@ichPrYs9%bDUxEu;?if70`>Lv5Y-V@52xJ*f#n8K>a80}%cefyBQq7>QQT@AXP z_VW$3SOewAc77+d?!VzWc2bG7(`b0{W7&eQo!&yxaw9Wnh5$w$k7u{vH9*5?m`K+~ zy4+~pYm%=$f%U5xVe6p>`EFkfT3=a53w=|&TZ?IAWVd83LJj>LX;#!1ah^n+lP53g zPpsrg4+JsF(UG+G9)u1qJ!137#_Wrj8^K{@91(QB4zav1a;QtAYC@;2?U(J{34cqXCz?KO?TgZ* zXK8Bhp*6UzM{MU2?a0sszoc^{1C;32E5){;=pKzqUjlKV@hbKt%}1O;6k!*s?oOn! z)p~joJr1geKJDP^l)L+K{?t2w`Z^DycaAtHv^=N+XhaYO+DZo#vV(&xzB>o?M zXf{({(Xfvu{-DhxCZ*PLAnwtKY-)r@Ohy`^qda1Y-w3nW`)YCTtX0}mwU=G0M~BeV z{(x55l?frysty^A5~cTu-TW*>9#mpMJLEqka30YGVGlwWbL;j48Qof|RfyIb8M=FF zt!SVl6#uE5j8iugI=i-(ZG2`4g1Vm~01Nm`#pwUVbb&^o{)<`As|p!HE` z&2_5--D-|o&C<0FG-}P|x(4!RIs93cQ7fGdnbyHX>maI?JgtG&!5;AmqIEE|p6J>| zEpn@cZZ+Sn=IL7Vj9QDhu0sASpFhhpYPFCKU|LIv)*)0Yd0GRlPkO{cqV-8=eHJ^Q zr`_sMw_2(TEs7lO_LUMTh&qzQnT(&B$5)gom~cuwVrgUT(XXoM8&Bjg$V318ix_8TG3 zk?1^w=?DZK@wvzm?#MxAB3J|Hgz6hX8cZBv?=*>Ey~DBW8@Fadt9zwKcgJKjL9-k| zEJt?M+G;0l<=!k*rJ?O{QxKWZ*4EJ0Bud`VAc-EWh0I%l7rx#ffg#pI_~T}? zV9X&W{>k?BNj~7v zs6d+1#H&PA^f>lnF<$)R#G@%_NVz$bWC@%Eq?~qQ8BQ3YIG52bCnv&<;))ye1q~W5roYTq5yMY*! zH?-ts4W@JNX3hB~6tu(0YfSC^v1BfAtMl}E-Ma<#nDDg;BZ-X51$5@7Q?hSf_2fqT zhIAfVau(7yYz3U^Brj{Ca|awC2-~SVJRz^4GY2{syVXjrb0_MJIv4xttTgKMU&fbG zoj$;+PV%xQIuF4C{Fc|Tciz3*x+-qVWX#M3Unw}i0xfYkZ^&o|pU z+{C5f-M04xpgtdjRKMdsL__!?PB?ZWd$pIJ5Q^=%ATq*sgKrfTPTrE-P`%pUhf_jC zoATsRBKjopyWNdfw4UJlH?zOa#_}oR?VpV0Qhi4Bjt4}4!IypSSEwZ_!T2?vV!(j{ zFTNoJGup9h51mP(SBoJL@N0t*RZ;f3(rRVdA#%xOq7=E)jcdaAlR>_@_kK&<&DY(z z;Vx!Geca}O18td~b1U%<7kU+ccW0?~_dVQ^Y|?uXA#)r+s9(hcrEeRFn@{U5#lD{f z?FS;l|0)BaP9!mj+(HyrQpN0Ty(rla(@2~KiuR-S@<-z2W;OwM(2&T@+dRZP7MjhT!;{{~XG^KMMd9>36~yKxYC$zIAS}&`w!{#9GXH!Jp`C zAVzCCi8O6`NTOc|s1a*Sx?fWxw;IAl8h(!0Zg;boYaL+KbNM%%)Vh<5%*1B)BQ&zV zYZzKbO{2B?^Q8V-xu@~#n%U^nIQ=ec_~pwV#N#%WQn#=Xb^(=m(@t^*8Io#6D=rc{ z<6Glph$y?1$QnlyhH;`t$$R6Yv^kdmrir4xyi9zZVLP~NM9;SYu1=B8Ii>jgrY;|+ z*r-%LCzprW7{bPm#0VMr1|_n3(AZ7aUr8v&&-+3o&7g7@~&WxMrO|L<<6o) zJG!i zqf?0&FSP!6KESU>w;#n#Mwpq5=hR~$*f5ohHp5Kkm??odM1G@Q6epP>7jWd<(8$?l z$YmV4I5e`-47r9QSDKk@;wJ0OOnflWqP;z2Qud||-)aUwz!~-h=f&R8E!u77>@Du> zXlUf&V2(p(&Q5S=$3r`N*9`eNN1hCg{MZcn4Uk$ePnnsV=FYzhFyUkEEI0Yd%;X|B z`QsYB_It>wbOVQR@k-SPZxe3P$Pu*q+-Zig zag^i;F~dEqd%uU-(Wykm3#~uy4e=b}G5{u8w6h$cb|sI}#LF;)7jlLn z!Fe$_bc=G$oIS&x4GoPf4dy5|b5_Qkc|$vU!3;T$BP&89%gvBefYgFH(adBfcRnq^ zgpaj(++?`OQDf} znjtOmdN8ZZOsd19i2+r;)Ryn zZ36rj==Kh7(%#G@iBl&)uwg2RH^aC%rb|M=R5FN0FvSenha)|qkv+|jk8tFJp^^Q} zko`IGF*B0^+$77)Bp)VPv2yRuS4+xfyaAM@|lnoM?ue1EdzrnPw(0ap&^_O!!z^!c8j8OxAIe)z|2?m1NKb z?Mj}aJ-Xb?^$zZOtJ#YM%P4Q%Bw>)Dx*XMX+&2bP z3*MbcLf#<1E4CH7iNd`%O%k&GET&W6P0Voja$J-V=cTy2&2Vivu4O2kYKF6OTw61f zj@-myW|9IEEg(rrLP2SXUwgIbs8axPi5{o!9N8^2vWpqA4@Y`JBYT=5ALI>64KU%| z_c(X{D8iX1lv~*Kc108)HUkadpe%q2GV=2La%vszzy4;}p%y2U}ZfYppWHa16j+<>}Qprsg zn3=4AiI$B^Luba~0OTuroYr&Xn$XBqX2@+Exj8g)qZx7+Z_tha6W)EVa_4&yPGdIi zHUk~uphEx!WaEC?e+SI4r@5x@0<-ZjMSc~Sjc@27{FT$53Gn`wZt^Ghe%_cJ$Eok% z%y3m4ch!hHNO70VaMvg6Gkrv|A&WJfCD}NKbDecL?j|#n`rPCeGn4u}_ap^?`+ zja|ZnP@f}jF*CW7o7`?@BEdw9b`xi)P5+Oy;f>AU_i~0PXHZ_;9lAv}GiR~fS?kcq zmcbmVnX``EnIp6_yBV@GM<$0xCYm9;1E~eGo0&;(?!0G!2_I|yxJe%~lXPy9c8y+p z#2ISSf0p*>LuRgXx$6N09(etLj9F344nXsye37G{1KO~=KTnavoB^BuKT%D`eL0|7 z@XDOV1>=%#GJ$&^>ohDhRn&Kd8Eyv0O*P`qQQTxR+yai98wxku47Y^iD$Pt*a+76d zCL3U)1!S!=}$!^?VL8q92R95!W z%7_P8`Jh%>9%ALgv?Kv(=@v2zN=gcb7($|wCKnp2n!_+Ka?x&~DBu6>3yGa5M!AK; z;+)d#f}#wZt-htIu0^!Oz)k4@5^hnu7fT`^_F3$1VMqq<(Sota?!U6Mql|{C_NaQg zB!~7Nw~K?=T&kZ`$+&gP(iXyUO8lU8t>iz^+Q}_s2_q~Z5n(Bb)&#e%RTL9UQ60gCmtjbsKZ+kx-GMV|Fkn$PGy_Fqj}G1VNT5K?x@) z3Q15HOpqUfAkUQGIc=O+N4c*@S6Z#*ZqlVz>u7f^lJwRwtbQ!3AE(t@Ca`3jNJGgvv3m9yCS*{qzy%DJ>8$^JCjkdZ$SH|z0R0b9|G z9f}ivm0B8?>S-L1!ez*zg3^5d^b#$@5wiSrn((+MiRCu=Gau11!Y$+nrlOW$G|`Y` z3wakUFjF`$SRqZHr5w803|eUd-9({Q3vS+I^O^NkZ9cQ^*XA?p0XCl<(n4u@orUx; zE03`HqpW;`mL$|05Tue}elg9UfnJAko>N?$F)$}RF9(+f$>kq%OQuZ}*YHz*D21X{ zp(l!RpYp5Mx^0D7lb5*z7EWza7cHCJLh&HX_IIF*ydU9yRbi3f6}%6D#$ws2(PWh5 zq-(Rxi0fe19}|UlFx6r4xrM>(oN)%TShl)_?A(Dl#U%noB@$GghT4Wx1^GGTVwW~U zm0B!YsPycDA^ueUpj|L9OktvB2NJ1tNV=|oxx@Xe$%MzUoebpc0-Z(_O6jZ@aa|qZ zCVG`k5Na3Qe*2GSdJaGH+HZ-z$!%L(pIDx6MG%~hw0^}oMa5~ua*7IurKRK)561kT z_CRiNX+~bZoB_EiX6KTeqO{H_-Bp(>ZCJb5v_3g`IT^({X$6^2q!Eqmsuj05L#{)D*2c(0D z)FB*S$MGiQ`*19+T!uZ{yiJ(pKqR*u96EPJ}p1goE6 zbp}>vVf72FeudRJSp5d8-(htgR)4_i0<8Xo)kRocg4JbMU6H0pS7G@VEdPdO6)e5- z1!=har!+#oD3!^Vq>=JvX_S0LDwnS!Oa7878e84o^GaX(v4S;AxkfaKPr>_F@cuQte*^E|!uxmd{yn_^0Pm;e z_v9bt zlzB1ZmH9Cflm#&pm4#80l**{d%A%+#%5cmIBQP(NVP@E?%)q#xscgXvu~nI^T#TKg zT#B8mT#lWmT#22pT#a3z{1y9>vbOa?WnJq^Wqs>K%0b&=<&bTOvLtq?vNU#?@^|cV zWh7>knV3&zDXWyK*wu=+?HXlx+qKGww(FF#w(FIVZ8s>>qc$otqBbeBZJU)jwk^t> zsIAItG24`bG24|LF_?E^b}GIYpYl@7E@ffN%SvU;Ze>x-9%XUNUS&zlE6S+0`;_vw zuPUS4?pHpFJb?M^HDw;=rumqimd3oUEQ>je8SjWP1@qKY%v2Mazo|@Y{+9Am^JB`w z=5H&N&EHWbHGfx`-26Rd)xF1+Db3$krZ)dT*=#$3$A`+a<{v53n}3YQC(6v`Czbil zKUEeq|4fQt67#ikHRc=Tub6L@(U|)xF#C;Ben3=D zBZ@y_w*5(|X#2CW@7^=Yv8c1k+flzL??nBoyc=~+c`xcW<<*$qmEE!DmE%!=DDOvI zP{y?VQyJU#qVhr1CFNw~Wo3eNMfp&^s!WvrQYJ}%E0d)vWs2mrjchjDHdPv7nw7dlE&C(OJi+wq;a;FBgfm`mM7SzNE2;`q)E0DQIl;~ zur6Jdr{XcqHcy&vn=j3uf8e^|tYMZ?GMgH`-Q8n`|FQn{B71Ew)wCR`}dztCF|lvBS1T+G$%W`E2W?UAFbo z%eJ}FZrg`Zdu&^!y|xX~E4Gc&KHD+rRonQe{kC0^2W;o0*KCKSgSM;EA=_r@b=wx{ zuw42jpawv}o08vLN8=D@aX? z?4q2klBaUW1`2Bu-V47#o*MqO$jZ%YHeevFv*2hIUnHi6f7E7R9<3w$5UcncBpClu zo7{X_8G)l!ywPZYSJWnF7_F~GZ7vKAG@>@ePt$6=L4lvz%|qH?*FyeXkB3!kaRYtf zcOV*WY8lhIZCtFx|KU|!`}VPI?d^CKebTyBt9I>B*S1Zo_HneP|4o8WRV519<*}ww|KnEZy_TDwl~J3+PusC*W&N$;d&h+f>bsMabK&{4fz7Q?4Xpj#>73*B+y48Yv%#qME(T*xQGQ0A zHc0bwGbz!c2M$HlEx)o}*?K~`=OuSS{U4qGIz)z1pO=+K9Ssf=dSvyYA|j z|4WQTNORrYsZ+W$F}+nQXRqG9l9ReQ6BEhRg$Plsyj$?zLEiNX7U3~&*Sc$R*Q8!O zdZ#3|VuluCNWO-T7>?tHv0a=lcbDG1x+ivO=IoM}SIW$55%YVQ`FL*L-sSAvJvpg! z7ix}Kvl?*&L6EPWA_UjDb;YgSo}`{Vx_Nphc8Uun`tw;qM6gp&^HmD6v|WoWW(@6u1~b}#HOux9KWnQTle$!TZd${D0}GUBz!)QpPnE%rnUbz{j*5x-6mGdhdj&SKpzVwx*roXavEUZbd2$ZC^Gu0GZx z+ZJypC_75L4j+uefk+&Fg)+AS9Cl1se#KI#Lq0)4zee8d#t z@XS3poFG1K_@X^?Frc$Im3V{|BmgE-X7xQ@b2KZe9 z?t!h7cL25>4RHruggsHb*=?=ow%*~kScH1+W}ULJY$kSU-KkTxlf=Zh#5gkWED`kt zS@4qYs1PF_vkRWyoqP4|+atYraC$MW)m4ydnegtwuI)W=)fV1&B)dGQ8K~{!BI;@Z zEiL4>&*M{<(0dpf_p zQ}Cw37yd89r-Rocl~pdI<(Rf>K);-T{nH735~8^FJvUye;4g|00$cD3K58Swjlb z*zK#2Q)#Jvf46vg&F+>-?43L=8IBFuDfAW9>fI5WXWGAs@P zK>_tD8i51|0znAkf;uch0NF)k6Io6&G1X)B>7DW`r1w{l=1W^P*<$J5@bfs&0 zI=}1m|9L*{wa-lTIp=-r)Tyd7-IJdDqQU+0`V@5qXo>)x4S(Nqe_xiSV#_=3$P-zZ z*CHEV>(rvVp@x4IwM#;Xh6#)xwLvl_2ulw>llu24$knyua6bDVAVnbWsFA091QAkwCy_NFzG;oNo| zD2_c$g>?Z-rztR&Daf9B!Gkj}+^1JwyO!I8Gm%q(x)P`Pa|ad+s~#&`8cx#kVC_6(wyL~zrq;j#if#r%m9i^U9-=8e69Wc zoja*sI^X5M4IxmA7ty=Bld;uZ-zTl!R?Pb{U$ZGru@TU2Oxn_xwGvE zX$;SQk>?-yJnLRGfL#L0V_y?6vyF}SdFH<z{XHcmUE~scvL#d+nPL5^I1(k0o7+rbR=NCRKR=1KAF~Zk^=|~u+Xssf( zZ)Gt+)t+`q6ve|Robte9J2|X;w#kf^E6t_$y8>!G|+qe>n63)Jj#Ol}yH3Rt5 zg{6wxKAyk>5uJWL^H}YJ0mpeWhqG_tLos+jVR7ja#BMi^=8hiQ>m3-SFla zS;1_6Bf$=A8QB>^FRi?NAs@uQcaV5FpUL`qT#Y-Rk@kJ@O&&{yG>i9kO#%|^IwU1B z^&#y+zC3iz&$kypv*E|1RmLZdLR@`J_=y8wh5~RD52HeS-?A+AdADM*r^@67GcK>n zNnZM~p#_Eq|0-&^@+3yd5-qbnjO1u+BkMn?I8T)1=AvB_?&t6>e~QmCt=o5ITLFzl z+Cn8atnq-nID|+65Qi8;vrw|KI-o zPtO^D1wTO>WtZUjk7T_aXl1+=5I+mqk$!cd96}d+D^N1L#ET~d4&%R>Im}B>8^u%7 z_|w-QEl*!d0(mQtHwTP&2>i|fJrS}ZL*E?0Q{VXG@ZPcU0H+g`@JnIr7=yrHsq=K*@+1h{T9VED|`j1%sJh#sJ6Ahr|HV9fREg`bk>+Oss&f z33wF@&ywTOhja(F7v0@M-OUe(NBH?zZ}%YHGugPK|9EcSGx!M&j`*ot#4mujj}Tw5 zBJOiQ!~^c!_3>LEeiJahBG4gbhSg^M{6=QjS2lbl!@i@CL%O5$Bj_9s7>9_?P?Js_ zM&~d{oTvm~`RvI@HlItf}Q0>&>yYa%TI8I08l8>?Szti-b!eGO6QD?&L0kR&Ji6*cXYI1E8`#HGSeKf>sf66u|X?o;|YqH3h9nPc`!%| ziWT~Kg+W>{eyS=AE+7Vw?if@CgGxc;LL$+dCT~L)g-XGa5v$qaxP~u|%e}D+ZLGus za$}pxAM@V-ZuLsABpizeij&{XHdZ2J^@t9nJ35U) zr(w{zf#{62(rIX;bAtn&CPW9)9i1TP+(cZKShuH}Y{(*?@!(5$h*>~vMu;y{?|JFf z42X$JFFZ$+Z^e-Aki$UECgg=IPg$*VGt1L#8#HpUwAN`s3?SVxXa@$j1&v71XiYr& zn>@md$8GAef}gdGpk*6dXg2bNW}`ROx@@lPi7TW#u6KcJ=b+J%h|UL5RtiSjFruA7 zODPUx9c}pn(lc1O$c~}Ai56s1w4OIB_uin@i#REjdoK{!!78}8${i0S<>>?I4*4M< z7X^*J1g=)@MRHy1YvTbPR_?nv0~|w- z5Ccee42A@qD)&+_Ji3)fAJQGzP;~bx>aJ3`KZSVjV&fiHx#Nkj?hr=;aRebMmHP+> z#8GY$#{qF{&=^giYUMswX4q&OzLH_%Dddpu0x%VHrUZ>iL`SXMr+~y37Is;=Pb!<% zb3_Z$9jzBYYgW*hL9~?0eU^>Y3>z!4q0b>YknZR#1f2yzV;<2_D)$98I`bUpEFwCP z?&!P>I!lR*TDdQ^K`UwV3Ne6m$6zHGtRMzz<-Ve92CIkxq&o(0g25X><8>mTRPJwJ zaoo)oM_IYQZet}Xopo+$Yypi;L1Sakc$=6gmHQ?+p*MnoI+xzIaS~a(l|lsRE<`)Q z?Zcq)e$aT2xT%%nh67am*9H-AWX$j5hTGc}duDMqal??xcl@f84JDvf~(+AQWa!nxD2pLxqxLUc_2$>g9uCnvs zzZes$MMNOo5vdI#IMbAOAH|0F~|rx)$FBUct$#pJES|X z`si*w>aJ3=*F&VgU?Uz^v*Xe0?hqRTu^}NUHG4w`L_E0N9byQGfsoOZK-HQ(Aakp! z4IlSW@UuUmObRxnJ0dwC(mZ5j5fQaoZw~n3%60ZECqiK&1nG{@Z6Fj08Lf$sQm033 zd|KQ2U|wpWwnPWg9i5J#b9>0hB|1u-e!GoMt^=J;LJAZ$o?*gb(=5Hh+Gyi%JNU=iH!#U%?|Pw#GHBC42PZV5aD z0!1OCZ^(F%I4D(lk({!9!9ble586115_13r2hv?|9tXEaL&o5cF^IUSRr#YfN`occ zL3VN?ZH5p#NO$Z;fZec=5hZF$JwD9FENbV&C-l=q2hts#XFz96$S5H?N5k51(3wbFlzM!k4OwI|eyqVA;xr&mB}Anjp9;i81r>h#fp6@P?vQ5zc?Kb? z_4o`MGN_?R&e$F#j^P=B7TtW z_^klHXC|n> zpUx~9{!N1VyChSj3uN-BgPqX0uDAK;ZBu_Du0P9)SCdj+7? zdSST}nN>svGI=uVKqi)HtR*r^eI2uLS!?IQx8t{n3S{zBHiODLnZ^d9qSV&!*r;r9 zpt6OiKqgORJE&|U9%@~^%?>M;nD+@6GI`uxz}-Q(YE8Yv33oT)LMD&<8F2Sz8hZ#@ zsi*g1ar=(y={+_Uq6*pP2K-xqf0Jo^m1*oJe5IEDMo!DGfUeGs{Wd{$vzf*jqN3E#XKhr@I8gbUs6Zx9C8b#_Lu)2V6Qy?6nkC-2Qt`F^(jP(o zpT34$S_oYLv~q-|)Xn99mZ%V_&`cCUkjbM~0_uf?s@BXG+F(&LmzD+>5jte@=$8Tg z(q=~0W=0j_pw`QmHlw8i^>S6bK1lU)m9n{APTU}q=jH{sn$3(FL`J!fQ;25e$ z3?SVxXprSpL6?FxBrr&KU^k+>jj6jz72O!|KAxb8Zt4~>1jGO#DwTA=0Ws4pVm1(O z$ue#xP_>%AMP}H|Hhd++awz1G?m`{`oz_`KOQNIJ)vZC|2n)OXrb)}PX|*9*knU*R z0a_ihjP^uJsjxfPShcsY5*1BHq66uU&OM-Wcb0J{(NU`GyKQvtbf9xD(SdYF=K;{U zpSY-%_Wd?!C2hJA14wradVoPbF;Hvn{IVJJBnFV~81w^!K3PU@BB4~@eXuy5WQ(Kx zrb%xbD^Y_Nxux+4Xgr){6lWO&h>22%KP)G7F&L>{6^VWiI6=*bRgZ)nF2bK zvWy8tN2$yw+2~Agpz|!zfpkY_I_OLzE=qMi&4w)Ud4^lW7l1g65S0pj77!DaUUR6g zknZ|AAINhFS*_CN+Mtn(rRB#0VgTum!7E^}EX!DuWh^2dYNftRT~<)9FG0&6Y@w0g zG+9(O*X6_&(jC{e;JPNuSVctD%6(0IaTr@=%NLOTg;(x4hTb4rkpGs}n&zn7x0;pv zrP-~Fs@X>6Y*D;_&>Y|OKZCEXKgqtjUKQU+AMOM2IsWbFbKY2Gw2WjeXL-w6{+Es= zKK7T6IEJcci?SZl9j&WD>q_FZv$^==!-&P=jovJ`ws#A=JP^sD9am8WSN%cZ32U)Rfq~+k8E{+!LM7 zqSMqyKY8$cn-ji;9>+0vF3O^9}{)>Odp#kAR_jgmTn2$1_F_6qcssIZzT}15NPc{psia1 zcYr{LY@dj4eIXnCE-cYHoEqbtFGNAOD-d_FdYSJ=j|h~*oO zv91m@dL~I@m$_vP28}`4#zRCy-LeLO$4bUSZdnhZWesbwZdq&jdW~b~5gHuGqy|UQ zdJ?pT5GQ5J8iGKqElmqK9#6SNd>V+uvyGtys%}}sfx4cytf4jrNYeE@1UTYrF=E$- zbQgkgAT&1H7)^xKEo&@Dyh>Zv=&}ioCqj_!2u%f{DcQy(BBX9vQ!Iogl}+e5A_VD< z&`c1TPHdDdYr2hq*s^93GNe1?7lHf&AuC(f3o5c)wdN8sq&wtAKz=FPm`~u!mh}?A z%`Iy_UTLoSh<+`?}M z{I+ak3&AT});4Smo7l!6x2!D=G~WOBG*+`uSv$=w>qpQyoNXK=8tRsH7(Cu%Jmi*j z5G^0D7VDO^gRj>(hK|zUK>pjoQE8n3tzU?fvSs~(KsG44~=uWk`f1MyV0@f(4v zTh=L{?x8K~HyZ=6*~3GCW9STp0McCu&V$h3*~U2{q;6S%gTz+avd)!FNXrp>D5N_= z7v$iMYmSkM$ERM>QS+-?R=J!~LaBJIj*$|f3PcFf9ifXrs3NgZwycUa0%FUmOvsS# zkgEc@3Lz_7RuvUlu3FUy8PXl{l|a5c$EZ%=%9eFGz|AeII$rN%^CWJ|y2>p9F9_7k zF=`M2Wy`8*AyC7CfX^*~Iv{Xuj*(6Tlr8I83xRY80(IRIs0RYq5xTNvT?a%<-pj!^ zXz(H34Sr)FH_S0^AaG^NYM5hw%DO?NA-Ak1Zs9WlAIveD61=iy1#|GNf3`8mEvu;m zjb{Iz#*O&;YdXK3zZ(>G629`_h@C+Dn&o@kpPzk1v4{M(u`fma45)i^j6DRb-pb#b zW8TW&W8(lm2l&o_V`v{yflQvtSD><=c&NAW_hSTpU?VWe^1z709398d*Mtt4JoS9?Ps7JB{b#M{ZR+BV{XuX1KO`S z#&H5vZ`=PWv+1}ETgj&1Da??`hxr_+{F!5%CMxPJ`#(Y801NeaenA`8b5EB|=`W%L znLMSma4RDvY-nLoWhl4nQ^N6#G_{qXrRB zZqL^Ymy9^d7Cm`;zJ`sFxV-FhL*Y75s2eu?VWT#&P;SlF4VznlAL#0wscqvUGW2>1 z4P^46X#!r2!bXFzQJ;9Jx8)nz=roX2>)VJaiE|_IgG`>^&ES_AHiAS>xh0=z;}*0r z5~0c>Dv-%jX$dOfu#rtvl-u!P82c?H1c zMW1DOJyb^)#$EJT;RgJ5fUgc4D+ye=;IrBSzS04FtsC(50ACk2Vg#;S>{(|4k2!$9 z?FM`kz&8@Ia-nA<&@AhY9PG_B*pSH&_I99d3maPrSh>ivEo@%o*{V{I7kS=y1N{-8 zcZH1)30k?pvkMFT2;^4j1)dKbD17|yDI5*sp2YkVO@o*R(UHAi?{S?uJA!YyM~s^z z`~xA{7oa_MO9Ul%WBeE0c>erTwF508%;Y7UYRtbKg=^v?@$HtJh?XHvEmEwSr!ZSj zDmykW7rQya)Ek!!tyZbd$lCKMi&JrKDbD#1w#FB-02aLnzwA&- zOoiaT2OzxQOD`k!wxzzndl~%jKk5hHf15e`FVFQ<&-Gl&VpbjTs?`c#!#9I`9=w6ZQxyoO+h4@lZRYtirdOtx2tqFSDz`d-~SNnfzhECx}3Zm7a!9B1Z z_`5`)w#DnePe|4a_Dcp4gqa)G@VAfnKVi1)8){c2vL!ec>EWN?P?3p@)sF22v zDdL#Yxnx*++eXYkcwZB150WP;iNUQExIe;kq^3WTBfe%-%L*m5I8){^n^9*k3e6X( z>_uDntrfb1_1D`eH3KelJwAVKgrH1l-9orZDd9jK(@%#!>xt(^&JJFUM#C=Ye_IAW zTN}gCCStLV>#!%44@;;s!q+jvbQw!eQygx~Kx3?pndMq~pp)qGweWcx*9!>ayJ37M zj74LGD%=>2vD+-hcM0P<{oGc&4@P zELWr$>m@O0kipZVA*DoVw&!{p@%f6xPiDS0&Gp>K0@D)b}dRbSF;0UB?U$o4ZYsqlr09x62wE1`INiW-aa$9H+ z%e1ywPvAD!(+;EKzo->$5b12SwZ|%YV?CI|@n(<9)Zy z6D@@N>^&KSu|g@Ej@3o*5kd6cSP>r?>S8J*oqA!6asx|KdSEmI>%xP?U*1P1{;n<8 zv+Rlb*+zg@QB6BCIxT(M7?w#fiH4oG5gITl?k7vO$}xlUwE|<9^E~dHzkC4U=BpuA zcOLAnSTfL)4DikMbTiL3rL(>K0sdXz=Fto`(4sHQediJ_-9J`rnWeKNHHGJUtT)e3 zO4C%{mdZ(s6WGR1RAPHoVaDUgUD4P8n@nH`W6@g){B0rVWbhLYW;_9PC7|BGlOoW4 z;;Hv7lln7msrSo>s?>)v>P2zXp_9Q+^hcOMJ_BrXJr7|nAro^w186xk*Y$xJe6AJy z&ovV@Kz(ZsV3sPBONiod9>qcaXiK5qkPVVGF%aX2V?EhI6d1<<2h*6)vY!t|y#0~? z15qqE67f+n!Arg5dLHAO2OK7|c|4Kp8NwE;C$M?c!R9eBVvINUk0^cHv)ES z#n;3q?a4TSlQ=Q5)S+r_)C#N+sTdsv9pYn-Y_x>6O_Yn)7B7Y-IvS101=!)uSiC|1 zr(60FnhV@HSZ73|=SDEPEd!0Q>E^~1J%9duEnnb8C>^{>RKQJG7Kk1Sy#$3tyesGE<;G1N0D}*nb&lV)a9GJQ_=(v|7QHHt5=c*I_^m)EB=8kXm7d+ zabV?k>3;M&hhV?i5I45s#B`j%Cb0%RFrCg2PKheV*x}uIxAu(CC80D&(N_sP8K zHM_kGYO$HJD|+A!9VeL~Rv8fTZOTt;&e}pyPrYg}^8hw?iiC}uz z2N3SZ7l=`hRxnU8Tx>gKA3N6RNRRoIDB66k%Fgi*9|F<@cnuyx%Q)4Qc-g6Z27IH} ztJs@zAr?NI?UaV5)o8+K^KsxGhS0W#silT6j2Rd@G`x-m3nTWq?DtBsX)G>gq}DP& zKeR3*VPnjRn3m*AX8W5s1(>%I!LW-9JV4&So1DygRf~Pd1R1^rh_MiAZ!MkC*`u(Bt!V@2PE1Naet z+lLqIJy!2}*uCD47;l-oS9BZN{qMx>VA1zj>t>pkw2N(LZCli-`aas={6mP?+sZEX zDdw+eQMV!NVtbJjI1RfUu(Nc1BTnEXPOvY_CN#$`_8F!4F6a;+xr^;)ZEwfzVjrOq zyBO@?c@N$o4qGk#2z>zD?bx71Bkf{njBPb%E$w3OL+KmqE+%>?^yFkJT`4TP7)*iw z3D84;V*h2JiSJ^cqOlYTyV&P8=-PpOFhDzee8zn2z*{uo?dN#w-xd)LVp|wvxr=?l zJin#vVqb8h{p`dxrYn+;MP8iww$wz)==~J+?-<-WW$t2MafpLZj2l~V;(MIH%J3y1 zO{a&1Q=+QwVn48R$}aX!+%9&QJIsJXgySevS9dWvinNPa?af{6Yi|4#jCp9q+hfev zyF62>l@3s~^5Pm2z|HZSs?`d7!`&P&wG+EhhG;**+T&)`uV~BoxHS3XTAm)* zLm@v&W|)T;UP6=cH_?`Gjx-RTXf7tz-HoJRjnGp!yi z#rAeHwm197JZmrm-=QB5TGV5k*(Sz6Sy}ah-(u{c3xqR3;1Nd?-u}q|<05pHwF#?2lmwso_sX_Rd-aZc_d_}OLVBL#v^@z0}t zhp_A;2RTxzszv(wt z1!$=g4vznWM!t_=h9|X;RDuKesR+SKCH5ZcXG82Gha<)zxsP0gcK^{x>@eR25KZw3 z;$k$%j`B8jAHYKX6YpFVVaS5aF6qK7L!78uYRXF(t|2d2%8x}2Y6X7AdMPltj)UUe zwSvF=Pl}Ilj~P(rJ+8(G)@dasL32z33swrQe1UT85MN{QdX3&Tc%1j^QkYqW<40tt zI8hxZkgmtj0OB0tG6qr44w1n53GV!IyK`~k3hq1u&M|0L;SCLlE%?786oNG+oVYh2 zZp3ij-T-vqz8Yu{$l%8{hz< zJ_L^zdyf=6*|L@Kd&D>?Q?LQr{bwy3JB%8#wsUG*W3M&dHSP$7pAAk8a7z}(N^Cax(=5Jem)*FBkkea}2=r0VaczYuQRxZB@M0jEMd@gVV z;`ezH1HlMDO-&&2_9nbVG)_k>U2?eTaUSgc#u9y+$AfNqpfPsZ+`@3V?;py^fbe^U z>o()7StzBAmZ5>UXiVd^eg+z2XDkjpZNxBzSOosG(z4$C;E=LpD!uu^J;mMpxY)e$ z5zU0p*jWY^{10INl(61F1#m+f&yZ#eI`KH-P6)S>(7al69NPK>%%(qhYfI*b%_jCXnb~wJ9Kd^P2p%i;9{Ce$A--phQxT!jMu@f$vC3^&$g5L$ z+o8!{xeZT$e#r+$cd$0=#aMQ>dFPQD|KP=6_%CB~h+XI!mR^Mw1^z0mL0oE$c7_8~ z>A--uJDImCZRi4CCEj)yQ(!%3Z%ccg>e&#erFlFTc|4xC0@}a_wUSgVHLU{n@o0rA zns!l2`BcxlQe|^ME6jgH8|i^g8gz<1o_CzAK9pA516uc@zWuunD9}pMOz&5j-ajHe z4)rPCXq?TSIKNk$`unBIJ|~s$B=k2RtkC_+$>ylEIULaX7Z0!mqJMdC@*Hxq{7qV( zNNo9wljS*Sc_y*tA5NB@pgC&)IH_D9Rnmg$z{*fw3>6XWN$^1%*a9Pln7ncSTMzN}svvldqo7l3Z9ixVmvwG55Mq+1moGhD2%Z7<9Z*Z~< z!BPbCCMT6!r1NHRDsry1kSf_uD($7pZDovFB#24Z|IxS+ZOuotwUg_+rR&bjJkgx> zcsj;e%XE5BTK9@mX=hH}0aB&NKAe4>tR9h8gA&ndZ+d@%^!QRT3~$7EJQe3R*VG>+ zRYo|ejF-@3L0DNzMmyO&CvB$0=THkC|4B}kbEM_0#FjIhEEh@31&J-^Ia$6UEtfi} ztdc4#oK)69MMV3Jgh|oH^Q{tLlRYmsChpPOPR@2oXCEfEeBX}oo|ChE(%Ig` z&h|K29*~w_CAQq}WcdRuMKBLKsr)3JABj_ubM1swIp(BtR;rvXW7JM1TuN@|Bl??@ z>$H%$LwQ08mJ&8+J)ZM%)^cWEA+4*2)Xl3C4Eg-7B~@yKY`f1@PFB}SD?Jgd|C-*f zBRvjv1Kx=7s2At=9#g-GRB7m>k}07BAgnAUO`UAQ(x!PRZa+=sRY{hUWm{<(No?8L z$+DBQygjjHu9M|G((*1Rl?SBCeNHO9pdzAO5K2^)+{;s^yOa3{r#b8Kyc}mOXJ$#Jxez^_sV*gX=H#6qRi4ST zEhS@|tfoq<$(adOxCcz{Gf0mwC3EmbjK{1vzga*rDUO#%_?cL zA~WGqvfRn?Eom7`Y`NCSa*MQlC$Z%QC(HMxQ@jz$-8jx~ zk*S|4RRT^bITHF75LT9wo1JXhNSoGKaZ5=r9>JDQmK~*Khs2icohS(x0Cs!65(NcUKA(p(EulB!=1mk}kb_v$cGS#y56pPJoh*m^^`{WFe>WWr;jD4Ug6`{)yeh|$!So0Hm>BB55;HW z8Z(4XN!THA-q)HcBc=D@YIdyWzK1&5jhA*~Rl8TY-DoGf=cL_~M0S&$>}E;3=}szh zrOFFVDvO~avhk(FnK3`ka)TMCSEc34i7l5pS-vhUS0%Q5&B=0|?9dx=DsuQXN#`37 zPBk0XI~lz%jkdukE*m%T@!R5LdsK2d9G{Kvam$18+4zAO!e1rqFLB;?m?~$a_fu+i z?BTwDbF$NN%oY1@)ov@dJLhCqLE4qeQPyH%mztxl;gV-%X;;xnrJ7W!;-qpFR75sj zo|ABGtR82%&y15#TGmW#S;NV)uC%;1v1PiGr6D_XU7U&xOB3n5A;PI<;|)$m&7@Hf zMseA=pO0TtC)s(n&rZ;q|#-{WNUwY1uwlc4DT!SsHR^!Vm~1aHK6 z9*XmO*wjBJRgOBT{4Sw?1!1M=Kkj7nm$dmaC$8u}z$19t$+BG7oH;4sgqB)Z4Xo_S zMbh%Z#FiDDEUQV&Do!d_N|no;RD4ho(XJUzRP-O^9k1bJe!WDf8@Ao=`1s`v!Ih@D`^={Y?T%I;lJ$ zRqiWe)b0%@D*AunBl=$_*S)3dp3FS{`T?7>9#27>wM^%zw0;8CN_GD`w|q1lSM;Ao zGoSaPU@C$)BCKv0f0`=erT4L6WurOIeUEmsdrsO-QSE-^c9Wd!UXXS(6WL97vRfeS z<~pe?ktz$FR8~Mm1mu-)!i{ZNoTUffNaLYgD=k+iwp{6C`L?uNm)J7qWVu;(Xk(m; z9KQFZ^KA&Hy0L9_GWu8=?SfI<#+HU2dpsXH+2%xQX{nynlopYiP)ki|$tC+H&@Btsi~bJ75V$l5qzJ>lUnXh z(O&K@(O&Lu(VlWI5xAdZo{;4qAla446h^GIO5$Qp!jsZ2qCLjQdgx0@DQzR#!%9PY z^k`5I#@{2p+{C}rlad?J`r8_Bi)g(S<2DhoN0R%CQt`jEi^^S8{-O);?WlYTz#tI- zL^O3U1>g}1z~l6O2)%!T-ajecr$xp4w4vgC%5VzA2;TA3l&9(aNRp$3Of3;IZ8XU- zbbcI{EMVOd2dr1(aP&?Tj-C;%=s_hOMG>u!HEikZPGm}f8YNH4gAt8?6sL%@jPa!O z2Xeo>{I11a^ZE_ytGMkePg#aU`0f$WRBb*6Y!uQk0+U4|r_MnbQ;>HrB8*7M)VY*j z_-iAUnk-8fi%6#|p~x?#$S2MvYlKXFo!+k% zvfLXaW7Pg8$#q<^k(#KEl=z~^coq`NthsgLX#%llQJ!$^-_GyjvpCM%9MyUpdfzaX~5*v!LV(lVcSl__C5{U z2Q&sd0=-&M|Rr|@`Af-_&Z=o_x=>fl8wo|Lok`^TU0`^TC1;W`~ZT<644lxCQ+%4 z=zDb{cu~p)DHpXV>{nRKW)rrp;>vBb3sNp_!&XLZSb42Vnig#d(pB1c5WGs-h5QO2 zo?XN-5a+xMdHCEpU?>%e`}w;8BA zfxFlDjqkYc3~>MQJ*|%f@-zB4eS$topR7NtPt~8(r|Hx68Tw3pmi~f1M}JYDtIyNt z>o4gG^~L%UeW|`oe??!euh3u9SLv(uHTvuNT0N$}sjt)D(%0)7^o{x^eY3tr->PrZ zcj~+KPxSrzA^ivau>PZdTtBIw($DCl(#NKcOCO&;DSdkSjPw`MuZ$Mqi`Hw36 z0gfNyxC6(X-WlFqc(vQR+WQgoK1RzPw0we=y=eIqEuW!fA6h;~%NJvw3Kg4Q3@VEmWcf#W?c-#$-ANhuRKgNH1eCvIm!1G>s z{uKXx2Jide{d0K#0^aw-`{|fIX;r%yw{~g{>!TTTZej47-!26%@eiq)( z!TVqE{Kmc|g!w$K&PaWHol*Mq#wGfU#-sH$ z{xSG(tUj~xGy1H?%cIq1jDfwJfA*GpPoKjUx_tg6;_4SSQi#Fo~ysqc%D9|$$b6oCJXcl zbzainZL(0`)?|@BtIlG5cAX{q3w4(2yzrdt-se~ zgTB4VM*aOJ@8};i*`$BiWV61b$rgRJf2;n!|6To@f15s|&U^aGI@_@-y|1sT^MSs) z&WHM%Iy>~8O?K+Ln(WeFud`d<-Q**EZJm$xao#=pusWaUpZWIcx@Z%**7+QkMEiE#olr0d%fe+ zfAmgBU*esZeh$0QdEaFGHzj?U_u2H9y;IZQ(4R|x#XBv1rSJLl+8v)BdsYk(Q zr_le@qV{ zHCVnD_9++;(oqa{7*N!6K-a$BR%jXMt@}uzX-1cJh1~}f4J_(W>=k99w`1|3{KBFx zjT$rzb_o~t?K=qd=%Zck40q{NRMcl+mv$ZTvSE|@jc%&nDA=%JgD%|)`*pdsXkhW( zfu_8G?B1w;exE+Nmvzu6ezbobGVSP*#Q8mMH{{KVAr8PJ&yp7fa8#lVCX#m~pkYCufXS+eg$gBp| ze+_XB{*qSLoU7i%gQr2@={-o@YF9_sKBOH&B42UmMOdeSFk^rXYzV}tS8zk z@V2T;1OIa`%n>W>*S*i6e0+AG5ggdHN5R12uH7H3-%G3FSv%pODfOOtqsOv+E9YD=gx^kA2>L|K&}*ZRcIR z`EhN@`X{TdYVO*1pI%)D_Tt`e81dc1v%9>J-E760JyX`sU0ijgd+)fm#eLu6E%@V! zE{4{t3TE2 zzR)JC>XC4=Kw`%C>E4Gs9{NbvSAM;^=+CY1MQU{Jcf4`c{g=CQES8cgo=)>ue*4Mn zkLS%hIU{Z2Wlz||XKPYG;J>}S57OjDg+Z%Mec(yAJ&1-Agb-k+Kqq*i; z-NLiIh3DrMp2}KFW(TXhuKA^w*|6NiEWgK=8C?a-YkE~Fmjatpu=$VGChws^h27bu zI)T{&mRp(S*WGbwe66O{24?EI7M@KlJXKnGDqkv%2M+2c%^2Xj%veIu$mzqI>0YT6kKv z@Z8$M^KlE$=K{H*v>*7;0BO$xyPetJSBOJ#9ZjprFk!<&8j?1B2KFlKQQT0md!O0m z^~T{F*j>f!(8UQYJ(aWL?c#cR1yDa=*6kj|p-o*)^YyBdnu?x2-jX|L8|Ogcwu9wP zW*J3A7F`I-*642NHJ;h>`SK@PxL-klfDZre5| zJA7N7{0gKNy#v1RFYQ2c$*k?IdE)-kunX91(V|P>Xbqjw?8|J_&ugIfDbw4;=kOpg5d|0< z^Uv71EeaS`$Rd`GLg{%p*vFI>DnJ8^1{6y&Ug&%dor>C(SqKwiZw=2q6rR3{gZzSm z{#;8^&4HKw+{;s$@bYj`VSb+cGixncAE)sz?M1~6#y_un-~M^@m%CzcBT)U4abBY6 z77ol~v>8k1G0xvwo|&nLil)7P&~2 zyjGoYXTFsB2_?=wK|Q}{aKF4hMO{HDMNpazv;*AV7o~~W@{T+5L{8?l$nKO4m%E{c ze-*XLA;iiA#xK1gHSIyGsFf>qW-7}hA1i#N%~XQ$7%q(}Bm6Ck!MCm19jSsx`giS@ z-$;h25`yp@C%x4^Px|)fgQG>ei$tiXy>*y(EtXP_r zj+HqHUxM;aOu2*NQrvti&9I-D%IBP`Sm?#6I^c7RQ*9qG#{}KB^s}E}Tu~b)CxrcM z+LJsj*`UkeY7E2U-1UBpdtO}n$cQ{d5oyV}g*)Ayhn$q5tc|n3aVOPEXSE#6VzT{E ziIc)&0>X2OJ1Easn0=)2G>2s{IXbU6>Q|IsfF(K6viB!<`FVC+uQ0-UDUrJ>!=Z3u zOVwHKV3`cMoCxeTH=k7RSQ0e5|mhC9WKN$Z- z##Q(>GzjaJ%s2MS27kdSZJg?O&_H(QP$UZ56#iy9`;`#kw&8%n0$ffp*ZSw6_Yc$S zsQ7xgYo9@-O8B_1o#!++6Ktt`j?jsGtM`wo^pY*>clHMvbScOb42}X*n{L zFnE?NLWhT;+`}dI1uH>P|IGd57qTxV2oBZY0gnLJ(uOO&V>_tSVUZfnQCdr$9XnyW z27S6JQc?SqXU;$buU}7bZ+&1f&YQ_I!LrJ;>Pnzr2lNr#b5U3f>TwaSirRbeOP*!@ zeHv!?m-eYLa{0KGR9reFY}`h2-xU+ZM#gxQa8^;f%$$!Fq!L2vsYC|}%C`f#GBg0z zXpU8Aos(4Y$dzF%dE3s1K^6^OEy_}192}%QsQ`&C<%vhZh+WtZsPPG|T+EJJQjm6+irW2& z6=e@5o8$3m2-PK)Ph?RQvu#hPTVYS^1Xu;oT)}K!lVE4FjN%lbmzIX#m!~2Z#ROjr z2Mz4n(`iY3mi7NuIrZ2LV{?yU6K^UzeN2rrm=zWm^u^bfEQQB&JU}ZGaAcRuXd9<) zr#;RmO8jCrjbW|kROAXmY4bey{-$MZ&ASz=D{cPM%@DmTr*3H-&Tfq3Uq!90Jc&WH z1kS7uTjywOU+6!mI8W5EW*pcPlV@-OpWwqm>-L@5!c4=GHeX2{>*s`K0G`RZ^pO%i zsv69dcQUkQapzqV<&1@=Ilw)6gjjyicgMss!=BSUo59_uFtW~yYQTDdseH^`h>xDa zntgPfgHyOztX+I>G|EEu|J%RZTG6yCyjrdo&&bSee9?VXv69xPka}%&1*25?ovPZ! zxhYHW+uzY?c+Y>Ga9yC45etZ)2JR3LkH#y9?#5z)lHny@{Pfu{{$s_%ylusE%J2{_ z{+KRE%VWBdK;8u8jRE6r0>_V!i{Ch^$j~K#}FPK#u-4mW3VGYzXhJhLc!o` z0=_N#^*IT)lfWR|fqjhb?xyZ`4TxuQ`&e&xBi=LFxPt&5-}a2Rt@z1QJnqaL;%7kI zONjWz3DknZUG z06O0XjPHoflO~-yjL!EUaiS7{$Mdk`36bBGP3thxf^5k56&^Z+_ej_@Qt#nS===|nD2al`cbRgZ)`5Sc35f}BBy3g65 zm9)WQ?>GZUcMMX4tqf04tkC$ybg@WY&ql`+jGw9sgS4Pv0O^iFMKJhJ(71p|^rXq# zka74=uw=w)wm7cgi{o-{>;fArv4G$Se(q>g2aRe$`haS0fx zbLnCmCy}*yEFd2wNO#<7f!j4fw=>{Xw)Wx!>u#RZ{t_n#!7??&nx6~Al=bv06O)9Mm?faVx?2xMyH+w9Xte)(}8qH zrzz+(AujlR?b7Y3i49rgGajPo4lxsmK|;i@mLq$$C@;N&KulD6;hBuQuaNGLn*%wE zkl9aU^J3#>mZw=ZXyjsP`GH41at4s@7_#j__lS4ekUJAvyRL8Ai^eGx=iDHv_Th~5EON^uzLV9OVfp1~?O zb`0UUm7Er2Qna2oEBBtDRY07S%Dn&tcCZRAu5!mSFF7)#JLG;q?h`b66S!Kr_mS&b zZyOJA+QLg&97A}%CZ_}Gj!rS?3?MFQvSNA{XMkg95HWys$KcVR zQ{`R?_85Udx&wO>-5o;RRVw!(i1#iw?s1hno-XPRaX1i%5~5PM4|PBs;TCZW5KDr_ zNCH(W_Y#?5BW?IfhT(yzJi{Q}1z zEFvyy<-W)Ut)vZ}GRp%3>5jpxVDJhtP%HOW%4UFv*m4Gt?ij2EgEc{86_HRX_cd4? zceBM&R_?28tVE@Q2j;q?@eXKg2pa2y#yVo6RPGz(gkBE@>Rei9<0P^cPvPYuf^^62 z1900OG`0net;9{O+_&2(ZIg7j+Q=!1gopcbj*#v+egcjk2aVlCP^sKMw(;9-VhyXq+G( zYUTdBx~!mbKZ%x)*g_*K_Y-Av#iO1%S4ekUwNNYLpP=y<5mhVqf8vY7*k87M0qLE* za>p@*$3$~lkV(;+V^;2$f>zZ~f@|(oLnXsMVWmV|<&H;8b7V+&$X5gT%8+q6fvc7K zl_B#2%H?(*{IXLB53=S&Al(u1fk-W4q1NoRLM0PpAeOry}kn?o(k>`@g^YN z7&00Ys9Lk%D08c^4IlSW@N?}UJae3nETlUkw}8maAtRHBsMY$-fFG`0XU}vZga?{) zLXhqV-3mgjLPiTBq}1uHYD$A)x=oe%78A>#pp zS8DTaSOoWbamfPL(;u)g5mgMHJ@1Y{KM?2>GJ1!MUc^DE%KOME+ZznjIn&F=NtBp) zpgj)`q&sepfZM|%qc~&?AZ}_^{;-Wwv7|e|PEMo^o{-PkLAql%6zrY~8BY*3r5=CE z#_S0@A3mXn5gkZ(bVh^DsF3kA(NXI0Q8qeHJJ7*{`+0OA-O-rCPt;gq@O9?9RIe7ggTUK!Oe0JIV@EZx7AEY~euYljOkg(a{!N1Vdt|0Sg-jmx z8K92IG)f3qt-Z%&nzeU{or74t#t{j~uwxFQwSY0 zdGu+SPBnKa(DMWYnLN-ebaMuEQ>nLSAiCcssJCakL7NM-IfSOv+H)Mx=D9&z477!r z#sUIV>+FRxj~3Xlsm@+P0ftOIz$-vvd8Y9)kx*;w<$zY}g_oVkyhdaolP41cnYEe5 z8X}|A*K2KD*4Vl5?f6Zi0+~FOcR*!Brm>!=D7Ezl8hipJ{wf_)0DPm7JFQfv(Pt&ux4}Eq#E30-1bJegv<>nZ}_^;~?=;>*&Ka zI)^0HgLYyfO^y;X$mE%w1hW&F#xF!msi9BUSp8z>!YA!-L(nxj-uiwA5yz5K`*q)Mkkbq4Lc{Aq1Ix zA1?%I1wvJ8<_b1g)Xb%&K}AA`OdkDGpjT~XRB2{ZCJt)7T(uc36{wf1;PpYOmn)ae ztvYdoOrBd!aI4YGxQd9WwQ>!RQ3|x!RiLC6GpLmh@LCziP%WYa`EM!hxEbFO|4XCq zh}Xz!Wn7h&pkBTzt7P~O3F_r*vP7CdxV5rgbaPf^ntr6CFr* zbnXV7JF|>VL`SKz@3hhBTlyDvUV_q2-01MqTu#qmN6vDc#OEIwfK`ZN<$>w$86-3L>fvQA>DBt z4UVI-jHij9Qk9Rg@q60FN`!0-(SdYFXA^Yd;IX8~~rAu1L63?L>dy=GHiA>H+LE|BLCvRb9ju|XpjOUsXW!~oJA zgJoc_B+FQoWxPZ@)JlDcx~!mHUxb!F*g_+}Y4TFpTwf-xknXsy0oPSo#%n}Wt=w0| z7l*OeZ21DxzwpW($I$CU3-aI6TGbqt`&P4ZubSP;sFH0|$`-}@_U8Dm{~3IB{Ym!K z^(y#A`fwkB&+%_ZpYz5lp=Bg%Im=tl^6yKR_}E`M;uxxyEy{XGceJhqt;>niht0*` zT1;e=F6T%{Cy>M+AD%J)`0y&Xh+ZJp%r7|Y-uk3JZ3tJP7@mevFqGK$dK-kGl3i=%w^!s0e%D*BXEdi;q`n>)ZsIIY@UFK z*l)sa2}D4kb+*xx2&83;$;k<{wh(CPK%k9V0v$l0eYVk-2%NP>puL4aTL%KSyCu*W z1UeG>3G3i@1Y!w`xmcUz;NMAu59x03y8!u~Y~yYMKSf<%$Oiu&mS~;vU+iv`hFl`= za|@pj_-@%o9>E_V_@xZK8#abl*v7Dk&DNz&M5ZdrpsV_>#XL^RYbYan>6 zWIW`SRfLu`ti`%zt>x=Aj-iKXa3GT!97$^kXgx-plr8Hq1Y&JzTFCKu!Y$%(AP&to zo+40n%Nh#Q^|WO@Wn+LOUC%>+V`v100McCu#)8o3Y-1D=Qn#$pAn__~S)cZ8;c&@^JBY+2K61jLp#gODNJA-@3RS%j=? zS+i7RxoXWJWJq_&F9CUewlSB$l`U&Nz|AddE?#e7^CWJ|TIiO*%OJ2c+gMBllr3wi zg}`D50Bq`Sf2 z0Oa-A#ySF5wygDX%UY+>kW1u7xA5Blzct&~MDWU%wG|t~CbluiEo+kljraaNjg{qi*?J|!PjdXLq}+EAph;)sI-0ot)GdL zvSs~@K;&0i;uLP=YS-$~w4{ce$+8BV%9v%W5Lw`^RAl-%FZxA|{ zZTv}u)Gg~ANNlAo>(8Kx-4QC6gFCJ{h6hg#y`-b&SGTOxoKiv_yjI6ZiBS0* zx)Gb>l2Anu`VX;Dwygiy2#77K5+Osn3q=(mS0-d-%c`s*%T?DfMe)Wq5_#bmHnXdIq^_$ z`_XiQ$#`OrgWAlK_*WrCEUu;!p1*DNx5CGh2t6hV`C(C`qZ$f zF(8wtav`Wx2pi?YqTo?()mN}lDUTL4GX<53L!yW8w#yJikov3xC+A(wcZEx8hsdP(|*xaf8+#Xl)5ixeebIXo*UuTu$>r5dMLccr>cP8>r|5+%swDUAT7VZ=wd7&Hv=_!Hpq7lWR5gEkguqr=81 z0#q*qjRxX*x)3zVh7Km@dDn3aJwsiGOup+=KxR_dm_TIIi$Ie=;8(f`G@)!V&k`BP zi08O`$nN~KLSwsdhc`|cBW)3k?F8<81fs0*a9-%@ekGc@33kX%Y z@UuWgm7o0=5h`TzsILHZS=d-Yz{*9RWdJrW`Ygfgp*pfK?xN3fH{h!QzA|jAAaLb^ z&q@pU3J35tZot<8JQgj3_i8}N+)f18k%3q5ZG&9d&u!G4DZ8#4L9 z-UigIVPi7^D;IgThRusSn^g+(BF}qnpmza!N7#6upp^?eJFw7?KyH;@;CbJH!tQ@h z;Yb+wB<81R8pJ$^j_d_{kL%30MDQ*5h>;oLpTf|-0PV4xBPh8WZHu8EJtw_BP=vT0L{KY znEPDJ426QlsW`V3=ltKc#uu^x7QG0+r%*~vh2XyjAiUs9FC%sK9S|Z2-pk;J|7|$< z{@cvie|fH_a<1nh7PHET*Qpk*j5ZPD)`-z6Vze-$cB%j87UFwImok=Z(BVlsm`u`R zx8n5#_IiRIYh`)ef(M1O6)_dWgY8*Zs zb;7T+oLn+YeaC-EVo_1+Pc4tirGa3mC6@mTu>x z+q}{6S7{}>?PcBWmdL{dy)8FQ5AigGO2{@RVXMo%+pHzKDk$?~A3pM{p!J*`n2z^FB~MC~DT zfH&TxCQA{l%w*}C$QzQy>RE&X-f}$w-gEXciJmvl^<=T0H%HH}LC+tJ7=t6mpolTh z>~^-=?ZFmugDkHH;0E7?uD(n#eoCU_}yP zVBWchmX@qQW3Hzaj}3d7L~L%$^+Z@~ZbNM9A~qu<#)yb9EMi0>#*=1v+U9!N`Nu?f zUmIcVf>Ca+r$esi_FPX#e@+YW4aRgfGe)9AG{$YA*2zCQ;&0i4cAjhFH5##aidDN- zU>xgA=g>3gD1UipEXt!38^%Sg!1xH?aqsefP9dxt=Z_4;9x)nLac-*FAU>^`}}oKE>ME*^F1AWk$`!2=T@T)w00q zZCWC42&2WbwJZ=3fa6?GA07erGKmNj<$C(D2oxa#Aw*z7#F!T`UW^zom=WmjpU_gw z^y^ugzG&h3g0nY~FWiONH z?c=$g$5?M4M{l#y+m|E8(ulFx?CKD;t4l4+7F)aeDkJiQrK`))Ro?hyuIDNL;}kEx z#lD=#N$D25g1O?q1*R_D4rVbc4-plHExZiHw~QDmk30d_!_de>2EAlL799x(@H2vc zg$Xa%dxWno!WWAeYa_;*h_NbSyk-V5ItmK@w<022`O1g|G+H9ujA190(kq4lnYpmm z60B90*RSEVTmv`qkd1{S%LuGP6vT;fI1v+$%#Dlc+`v0x;f;=GB;JbnE4HEqy*|rq z3wT>edjj+J7Kb<2_e~ssq8(qHm}Ipu3v>9QN@=rK2E|@R!H7Y<8X)2rpgZ+e?|H+nOduvh(0C!Mkqr-kGBKCIa z(u#1Rbvjyk?y$E>OtRM?xGC#{P!S;!R-!-VIDO3fFdv4NJox~5B2Fy835)^&Kx`r2WbBA& zv2ErDU9EOtCt)wbN$4zv@b8NFd(svgU?jG4o}5Hm^^By1$)0Ks$Sd#>+a)pdz#hU_ z&YZW-5kr&-&zv(GWVz~Z@v^plybUh~n=ew?3qFdk!im~f&|ZPYPH7nc!kd*6U-Yzg z;1k}yiox%Sh(=B}L!4M64FY?K>g!B*45e!p3j*&DV?m>5ACur`9A+&{Re~Af#2d`# zwutal1)f+^#?aU)E%Ygd%*1|^=_&h>CCsJh>_gB#j=0W_C{Da35E&bf3AmmEW&jZA z?=S^rDYuMuDOBlF{yD{G6EjpkemEGGI$?aj;HaBn92X&RVvFDg5O8CEwTH?N37df= zMZ>#jfOwCrX$L^Eqj5V^PU+;yU~fxjajNI7KrPMVxya-3!~)vD2l1P&8v9*(4}N(Q zf5~xCO8HdJW~s6{byE38LVpRu3f(W9Yz|AC?*p3nja-u|`^{;O=Q}6M6Vmcn zV#}YLEYC>GQ;98qbF%zLTAp)KNeh|->j|m@D??ccDk9qd32O2eP)oT-Xf{e$3C3Bova2)s{x54wr_#9$ClI-z}ce0!%EvF~8oaSV?Kw8dCY&plta;dajAgx1U7CPWq)Jf%rAu!j2>*9xXXoCzyUVB9-}C&hX3yQ( zbI$wDnKLuz?kzZ}92L$Fg{X+Rc2cMucT%}5R4&|P)Xv#1B`>fMJ>%rs<2ARR>rQjl zO84BPPV} ztEPSxp;FOFB~CzB2VrR`iFLB6BW!AWL-x~fR+ZFrvh)kfdiIvdPL?kS%f|MW4V^4s z5|%BTR9+V;-p zbr#M(wRiThlVx{d`MJI2XHJ%VVQB=jmy^mM;kMq3ui~{Ee}~SesgkmUN}2r@9dP5LDmuZ2R<`NA64zr(Nj01p$z3JHZ;q)SFH~wcsnikBwLw@~ zN@_aUG!Qm*6GE1fb}WKEC(9RvWn+8GhEA5R2+J4kEn7HQrV7gxCzTAL(#lDtJyeWn zzm;H@l)0?q?VQZt6A1a%yvVihQ3oeyorJSb>@7dCVtnA_th;dbxxKT`oGkkb%Rcs& zy__tEz|sijASaa(!uhZe6*1Sw2$hjeD$|6@5|wsRb2l`zdH)bhjo>|ysARPZx?@{ps%XOd zqlrp-kj6mf`(Y=$7-1JB+Z8gq$DHh{2)l}Qc27ImJtOR@IjPhVD)CM#KByQ0sgtPW z6yyi>*I14cLM+Fcae7Wz*0;B;>ty+YuxxB^+0e=IMbV+=Au3|{UKh?^ML4sRZejd> zJMnm4b~4HkMy+6!la`eglvC5$_@z48zAHH8g=XVyW|Srwa<*v zA(qR{I87IpQ|v7#Ia$sXmfzT0&UCUY79E-&q9TTGg>b$U;gqv+v6Im{VYCKDA=$W+ zjo(Tq+oOWhq0nqx$1D$oX5;r}2u};xKSI23G*vDM@8{+0*v5RHb+WrI?5@goYna^? zC%apc%#}VoNm`2yJ5Q3lh6|o$gx!CfRPGTfcRHy&2o)n6?@O{>8_R`Q{$$3fg0Otp z-tr+Q%P3(PX>X}HSw1B?^hAh?2uoGryb{7GXQS?90EGT#s%3hjC(z=Wii?kC^%=gvwDTm2(36 zGzd#Y|4ApCzl6=@q>!S2Ka1c+C(Cf3IRg}*t>twm%hJN~HharkeDaWpAlxG??{rdm zK&ag7q*4JYMzkOH*%kfAS;rr8GLI1mQ9esvJZ9e`;^Zt=IIC=LS<#B|w3D-1!dbk% zvuB(vlZ9oXz2&n`me0Y`2xfgJl_tV@!w?lQ*IEdb7o1ey5Gt?TWYk{q*%ke#*oeO5 z+!S>u@*`BiLm|<)>3tUfmy!i3n}_9qnXY7&tPfnGctWp;g>?7k9qL+$Lobg~;G>_$4NOcW~PoK$8&#R$k$ zpY6srImFU~4=J%w&J&ii?JZ|HSuPQl#rBp9oGiZ;9aet3bpVsACvTxK(+l!tIYg7XA{Yq|7qkw!BkYOPFnt*!Q z9_mFquPxBIAg=~gGr4z0V^atGbl&9*-sLueM=LwPH|+r5umenS0DOmcI9CAW*mt;Ur|0E+-fQxabW$jHrQS=x(Z_vW&X zA;bG}*^jsPXOd=dH~ScMwWHkGj&h+LT7a6sp(YBbarRJS?4U;3L4EB2HG^l# zOg<8`1mrY3-&5>-Pjc|RnEPJAeSd4n@Rb6i*uGl}?4alQm27Eon`6i28#^wZuqDuK zm6ytvD`~WsK|f@)F#z9l<{SNGkP+cwoBX9&YX8W4u$9YgTyE!b2bVhy8L^AYpLqLj ze!hoEn(yoFy82ycSJ&8eb(LLLX|j64H^XaM$JD%bnQf#@j<|#UcS{-Nc6M`0QA+3D zci-`ojXIrNeXdS%-|AJu-Hu|wI!Ya@PEaSQQ`8yiEOmjpNL`|?R9CC()g$U<^>6iacTKf|?*R;<_Hz4&SeMn!@j|?CK$sjVA z3?W0wF!B`{K}M2MWDFTg#*y)4BAG;{kf~%knL%ceZ^#@nm&_yc$pW&FEFz1^QnHME zOIDMOWGmT2ej~q=L*ytqMb457KgQXEso#exDLnlIBvl4dmMkj zaU+hK)M4soJlmqqReyxuR_W>=XxWXHJ!shrUi*OeGp_uCE5G8( zeq1|%s|RuIH(dK2T8E%@7+Oc5brf31pmiKtC!qBQv`#|n6tqr5>kPEcLhBr~&O_@0 zv@SyH60|Nu>rZH1f!1Hpx~le5uR-%~XkLfr4QLi>m()($Wwo>Rr`kokqIT8(Qa{tK zs@=3}81=u^BJH~Rg?2;jt`#B!I%z$%LbVtEdTX7L4_&mrT34-~_8Bsxn>IlETpOqr zX@ih0gSGD3m#`QDi=kRCZJ5?u8xD)FU@-y~U&CS~EJnd%G%UuzVk|7i!D2itCct8% zHbb2RtI4pM0;{R8ng*-su$rL_R%dEosNna@b+$H4odZvE;b|T`&4;H2@U#$~ zis5OIHc4BIza`o#btyb9gU99YxB?!(g~yffxJsL;t=48~YqW2)wc2d$J8h1(4j$LT z;|6&A9v**y$Bpo~2_84Y;}&@QQR|{^#osn$c;6522jKl6y#EI8zr*_>cs~s9N8tS^ydTrHYR9#0+6j371Kv-<`zd%o z4ew{*{VcqngZK0BegWPu!uut7zYOnx!uu6?{|nx)!uvIN|6A*(UdP`JpcIlLS|@T; z>r9SmUC42*D>;GL+bg;o=^gz!85&zehQ)qC=0$bKUk@@owkP>2wig)@+nWrG?n4Ge z_a%#B`;o=5{mIqX0pwcjK=OC&ATlI!Fc}*8B^ez%gp7$DO2)89>_qZi>?E=-b~5=kb_!Wi zZ7Nw>Z5kOGJ)MlKHiImyHj^x`HjAvN_6_;A+H5j1dJY*CJ(rA*o<~;3&L^v47m(Gl z3(1<;Vlo>m$sDXDbIB4iIC?4hGI|*q61|*Uj9Ni<#(qn7#jYe1qF0fX)mD>L)z*-S z(QC=1=8I`@3!{D_{ng!MfVzjARQHmB>OL|^{h16_e<5G0zhc$fPll)m z$WZklSse8n*{uBzyF+BHdYJ5wIzp~u&Az4`!{2c-Ts=X)QvV<$)RW{u)G4xDJxykk zGtfCp{?^Xn?>spab%7jGFOre!CA42A*R?9=Ss;iae%%5jk1y9(fge$_=e2 z{(40&i0U0VRqYcwP3;>wUF{b+L+u|qOdSw8R~;BRQymm}I%;s_EcMICp3y@h7ex(? zJgW|iyrvG1oUMKpIY%84c_Hd+=#GrM6!nmDf8jUf6y>fu^gcqx%=88CM0jr8P?T_` zPMeIh{EC$;_f-`9h5~J=n4X)_I{)1aY^V6z1zJ3x(5KR)V(ZMT$J(@IZDBZudp@SB z(u3)=&0=kIZw~hyD=R7Bgz02vv*rkkdbbZozM2|$eNLJ2yQemqHhkxN64iWV+K-A-uFS0py;ggRqTrSX zdjtoZHqdZC9U6z*?=}L#gHH8m$ftzp)lu%Q6C8M|_Z@(u=?DZpgdPt*y+mD|LY4$S zgdQINdaW$JQ+e7+j}HRX>-7|TeodbR9>O0V2zq5EMyxme(ooQY>LH{$&DYGVj9f24 zY1cG2r)_Rpd$k@~^3*3f#?^>PX_VPIHzzNrO}=Urd1~|gg7nOsl&Y1h#HaXj+P5#r z&dh&5iuA&=fB?}BRw-q(cAp<(lW=WAyZoCzTY7~C#6+3{!eXRkX5m@qNnHNDf+9KivE&P z4TqN%9kpd{2V7~=7Jsd(;EQ))oqF&|x>`M0SPI`AgM5k|pElZVV{K)p#{J`7m?M^% z-8!ov9j^rV2Xj^hd`swv~PRlYTXjWz`1~mG`wGnr8yE=o+-ASJK`niO%$9(@fMAD4UYMsR# zcj}ln{cQQ1D{I#IA8wg_I=1ZI2i!R}mXf9IklU-CfG_d;`y&HyTjO zwDfc*%URTNGxqYrCQ&%_38R)tu-ulcBsHe1o6^lwite6;RRJ`Is#o|Jho7FnVX)Hf z?ugr}CwqL!o_fh1f3oMJWY5p_J%{RhK7@}C89IEVX6NL#Ps>s|-%9s+rI5hYTpB_C&lEr!;9= zw{i344O8>pPR+}px72V$4QgI2GYer^TG{4J@;5^ZdaXY>9tu%s4;bb^k z1OgFXNF3W_W~ZlOwd_Xk@Imbfs4b>yS0!IqvGVg$G4&Bg!`~<aCF+VlL+73e+J`T1J&7O3w0fa`OeC3Z3Q9DXlz|fKVWa!6B%_Ly#>w zNYBXVz_bLNBzXCjc`2+3FYo4Lrl*Q;jv}LR8IOq3k{b+UYU}nLQu&t=jS=-jbtUCI zMbgd8OQp0k(naSYpty=E4we*+J5pwto`lkB#%pOEGYc?=$xSfasr6bm_F-&Ha%ZJT zwgtKLocFR*vvSe^8fJ{+2>4sW{Ot{-SKVgKQjN??O-^i)2$x%+hDT}TE-#{C0^@ho zkzm%alvZvDI5U++s`fB^MSLZ7^8?&8lg4l@4aLFwbaBY&*dZ-Dy{Z_TG8n|~80odv zY;WIzgr8qcJz9x;D@;Ld0LR?U%c*ldL&2v0wK4R+)y&#y-A2a%%G0F91 zwM%VOw^3?(LHqW2F;LiuTNOy%%*@6uLVAPI2>&yP#b(;kOVU`;L<)?RIhDpkc?(s3 zL2{X0&|dhXIrJmr(QA?qH8U9*Xpr=_*%T2isTY8 zser3HDb1hR;Js&zp14d0Zx^F@Z(x3kL3^3I-YCU`rkF^MKIr3a=HOOJ((EQ5H#7XN zaYqXNX(GPVVxDB@q-S6OwOgcqW-j+6hIASuxdVWBM6{B^E^(rZ&M(ZtG!b`^@br82 zc$8LF1|?!*^9FGJ9(O%da@`@Pg9sO$@V_$8?;yia_R#eoc?RQa-1rcSbL*U3`r0`a z_nbwj9z+oK!#JWk8!0-+=pt?=6uo?aUhXZ!7v!}Q8ATWRgH&gqG$MEhAU87uFVxM2 zX)yGDqk1hQU+<=66$F&hfXcs(~QWyao1B@Z>L?ODnrrqU0e8*=}A2x|RhktnFZiN5n2^5YqAPL4F{*bO??y z-(~DVAVT?;;jFasfH?t!klyAS_RqW`#yo{ z<~(DQ5g)WQn7s>1C%!k7R#NR1MGx}LpzrdcXvLa|WTC(9iAQN=ySG(lTdd0b@_^d@x;qe#aILC$~z4gMkaUQq`B4$(?UMt8QrnBlQbGA5W ziA`;QMV9aN9~nI@txOkFI#4_(BP-ZAG!hpv>Opbh6;)|v2a59gja$;y*BqsBQYNJr z1eWevaQion#a1a6yaX^8&i>H4&bYU-OQ9eZ=4ibkAqG!^a`1HnzHlp0x$CvULfWhU zZ;yZUi?~zc@S{ESC%f1`5U?b!p1vr~_$P5*h%rzH3EKSkBjl&Nov7dZeZs7q=XUgDT zNuWpXYEB2z9i8={^Bw2%2IbOIRSNH=T)vAd>N*UO=-Q7)0>_5*H`!In07vfz&H&OK zgH3V#pW}Mdgntz9GT3Gg2I&rL8@l@=?{2F&<9ER{+S?xy@8NXZ(SQ8VR!^1xgYMhi zBK`!#ogDG2V8opch`Ze){tCpOSp8vP zW&9fCSxyJi9i2Zx=Te-0fzuffOy`n?&IJcLS2!I=cXY0U&Na?us5xR!(b!zGKuc+J zgEN41#~>oUo*ou&tk8oc24V4`Q&nP6D&APBA>A=30|vLp>$hhg%x=gT}q_df9mWZqB5DCr2D*a&Nr3Wt0U2c`n^;;bdg( z13W~K?n0!3+oSRN!}0nM zGb`G{?{Nz&BVtJyo|L z8~GgP7O@r(y&Q20?>#HMyg;-oy=wEmLb~f~B9Ncu$m3|9(pslB&C_Qs(8$F=t&_wV zK)Pe_JQ(=n_4@I8UCtxh|ZYNOxeLqPrjS?n;&W$B6f4I_@Er zd!bvzu0ZU}5v9t#vjgI1ZV`I`@r!uI+HjTxpJRmftJ!{DrW%cj=?N2n86vymHUjFGx&xx zfON-TAsEb$*XME)Qsq7$i{lo$IEu=Bu7#CR=@h%Au@W>^#OurA^(CB%RJpGZ6M7jK z$a86lg_DuBt9XbY-G%4}aN7{CuZ!2$a&B_vzQICiouIqcLQYDgjhrK-JB~ZRaa+9p zBPS?T?%OQH-$B#=*VWVv!bVSz?22Fj09oB^ae2A9F$ zV!VDnUO&ru$d&s=d09c_ejY79(uGD;?q_e#^-s*F14wra zqP}hoON#0$lW`7cq-a|(`q-NLMB31!nC5|Z7?3El4tGY#u17Z!Y zUX6pwHG2(_Th%Q1cpnAt`*`Ddup!+AyAFsXc=cMGh+M5F0KSWKpS_k7p+rsy(j6f` z2-WxMbvYraPOop_Q`gD|^HT9X$LT=2qw@mjH1X<wpM z>Uo@-T$R6Pp;RE~=2^)ZY4ZVR2kDMoXRs^u>Ys3GQaxU1VfKlY51Y_kI2}lLbh?91 zkyr1==}7f>k%dk-2Rc1C9Y}X{`hrex&PA%nds~o=Oz!6vaS#v(a73vd9{@zVf@(1D zE2O)=4g>NKjx5*XLoCqP?MX(i)xFK@6r z=iO@7)4SHRslU6{Eb8*BP5u3OO{4OMEIDc~p!TS#f5Cy}+PgHg%a^2mpW>MGup>_8GR(Ip*9mvrkOO8IIrc=!w02<1HAWIH30^J`}x6{iAOaw_XUWi96+*VSvSu*MRzp5sE69Cs6Nf8e-sP5pxt z?q-e)S#sQ+z};R`-^!t-dU`t+w}ZT%-fCfCR3W?EfbR$RFE#ajHT69lU#g{l5z}%X z(B-+Y$HK>`r4R6+K$bix$HD7pP5p39{ddkwuA`4y=o}VQf434d(&PkZ23c}u=fUi3 zP5m^dCDqVpEv!ykxv)ulfm4AjIhCuRa;2tznNyMK=PMQ}mmR2F<5VC^PQ_CTcPu#% zsdm0$K{c{AtdEEO{SG1NA=~Rj!%;V}V7@94HOS zaCFF$qu&Sga<%k(YUy`z4syL*t`=V^P%qzu=fClK`L3IDyPtD|EIGFd;Pyx@y*wu- z*UFE8j8vc%mj@-em_e<)pVi7ZdR0yd^50V0R2!cWzozg{nmm$FPcNTfQ!kfKDC%<9 zre1zD!AKKGcgT+cnIz~c2bXJRl3>=%s)Yyg<|wOOar8dU=|H-p^Cajz!MVuQ^Aib0 zT~CEp&!-s!9KBC*29WL;R7!BFpaWo)IT)lnuxjXTRo-2ximr-ypSG!@tGh*v2jVjv zQL3b$aX|FCMXUqFgao}72bHVo1d(C2EcjA}CGwC%x(j&&(5aW8Cv!S-U0n|(j?%D; zPnsm(oR*){f^Qqzb!hJn zk%tJ7dJ z0C6}+lq&S$K(s5pzUF;}bl2B0Kpw@B29WL;Oap@{3Hqc2eFEnp zSL##bWd-&6B(z+j3yt`s$%LD8ozA&Jy5l+@T<0d}vpG?@a-SPo92U>EOK z5C1g3d|2Ksq6WkYiTWcPbSn)6{j%u*idq4v12y1vDO3E2g#p+MWFf%OOLzz%-Gv|q zgrXDm$2p;0CZR7Wp=gjOq=fJ_z{hV+=t)ip(jB2HAXF()*Eykm5}`^#g!G#es>%sL zx+C-q2vz57*3>b+nLLz6r@DoJvFpTfWJq_&wSes9$ftmuM3lm>DY92a9cZ2^rkY7vGU*X`Fc-JS;!GDb=T1)&DzarBROXM4F;WGf=I#GX< z!yn-AQz(3EYz))s#xRlQ8;-?qI?!lSLK>URE$dy-$WPQea2oQKl@A`XDG#w_bwJBJ z+7i5FEnw?4j^6k9;6RpWa0IQ7LF+@#N!qeLL?9Lf(n5^KCvFkD0&6-(jB2;AT)%tk+!TM76QhWHJl?uxv~ zIGm^-o9n%qddfxbr3Dz)0W^ZYa?5)ar7SJg9G_*2S=uL8njMwPSTcj5`oxA zr((#ftTS#AF9GpFqJEBp%3Ib2pl;(^);S9Uu-V2!fTQ;^4*{gR5L^eLYl-?_oRGX_ zT?2_Ve9QXl=7er=LXhqV-I9cNT$A)L{Ep{6&6Oy5%Zf+}5DLR{d5ok8-I~PTh)r@y zs0;|*&e=#?*6kJo#+G#lM}~A4ihF>37e|)1th;1nv1*m&$dK-k9|ZFKN&3AUT-vhk z2e`Rq-HYcx(RmWGW&PJJfeIk-NRnQj6Ogv7M}i2HcOam;B@hJyk0t4Z6Ogv7$ASnD z2LjP<2|NV?F&tgmvSNT3l=ourpXP%P>2C0=0=aUMUXg=KTUO;H^Ho+wnTFW1V%@@f z0Uwv7SLg83mKB$TPyN%4L2Oyo9ca}2_cUVh@z+T9@z>3uu#w|SKOC_UXur^W5Bd7p z79M-Ze;fM%>Q10;Ptvz?VEL{5?Mdca`CBa?=oj>Z5l0w0j^3X+I%LVw4wwm&1X>68Uq%BJ%?%#bAy^IxFyXOe!2 zQ<2}Y{}TlE(@^(jH?(m-_tMQNUFDP@OHL`=S5No&^c$R#^me_+7s}{{g^{t-NBE2y z1G3~)N`uOOeEO|Equ`O=s{fCL%B^UTGt;0_hEstoIhA`rT)WOC8zQns5Ia_q_^T5SWu1JeclaP6QDKXXwuv8jeurXGBxFWge-XeFB59OSp(Q{-g>Z@<5amQ!>g5pTc0d~=?u zoF`<-dA0-3Hac13yFL(P`up_0oQ!-Es6PmteRlN3}#8DwjjyeOV(|r0A4lLdDnFe6<1#y#Sy&LE)fZpWOzvs}>4W3O{=({4f z0ylWRccAd&zo&4_hxa7LhA9ff7>MTd2|dSs<~n|S%H6Nm^0QZAXdj36;sifR?pXX4 zuDEgI)5qd`erhrvmtxtcqi|2W8$R8V=vQKlOA{rlI$_k-6HbqHN)^}gQ}x)QPUXr( zck6PYOl34{ammc*Bx-0V1UWUXO~JLOgZ1%&EPxf>fqyk3Kum^U{~mzh1s{6pMj8fu zf%jDSX%W`K69c~gHgonq(8Tj-6Hj>>vqurH+Yzrue*Jkr{?&NBzF)6v2ChOAkJiLP zqMG`no^P2>A6O#r1=p*TwU(WzashOv9=$e7=e2vEoMN z2q+ceUZ;_Iytt_!7Za&xZxaNbwMIwP^&1dRBfJ=$PUUWkxQn`imnWj?+g|KLa4{yz z?|kv8Abb+{hM%R()6Erc3jjC6A0&;49`%C1*ytC9=J@!h{wh!E+?(*uR4g`nC~L&h zjugK@`xI_;Eu1RcD9x=Z8P}Ma8uum*L1hG&B^FbOVQp2S8X0YOAGvxjtjbp8Ap8G=3_k0?YR2Fi*?|HaDJcQOZjb8A;M2qKT(ri*Ro$PI;;~ifZXM zra)Ds6lP1~m>2zuk*0Ak8M)ttM#7lK)U$o=Hw}tJK*Q*$UDm%K#h@MSRx=(0#mIWr z*4&K2-DcKnahX)Pg%|8%*wYtfeu110o|`WP@e61;^Ltt1_ZEeGMdruaUbW%(HdTI& z@ncV4m-z*HCa@zb?GHzt?5$qR}=PzD7iMxZe`aQQYp%%lDa zyf1?xd-`5XK5gk3gb zyhr_g$`II7_U}HmxP>+}@w^lDioX`Zixakw)kXyAld#(8D18!M8+;m~WGTcaNMe{x zVJAEd9ofRpv@v8!E9`>C7Nue^Xzq`w9vxW3yhSM_0{z#$kQEqyoX~$Tphb8L_C1^o#fh;ai4qg7!>9@^ol$X? zq;xJE1qbjm0)k~0Jx3XRqd`6WGr!)&uXpn6pZfKW%`&=hv|%vT5aS@Ciu_SY!6kJU zQBrpbDx*IQdj7Gsq%NEQSH+(NmDR&pzbDe>qCjc=Iih7;nM|=i_7^iaoASDF3RU>j zR)MX*g;S|Qr<*8Dr{DojBJUaZt{2yxMRmXM8?D7g zNNg$+mf@njF8qdC75R(5pj|g?&4RsfHm(&LF_aw{+Pp$9oI_oFW+}hFW^tX1i(XKS zF;3@GT^o`i(>sLZ0&3+zav`n-kqkJJNfuKVR+1wb$wj!xNE)Y0sICpkki{W{4hGwW?}P)#Es=w=!Y;36XSY#%|5JdDWsp=j~U0@ZlOAXL=VcLz%&XpN=x>SFtv%s zc;YsoB2HjecF2f92@yaHG)jm&?GYz3zq?FC<8(JgoW!o|kr9JNH-H#u zlo0pYBTi<1_nC;s>CZUDW`j;+xM=L7`mkCD4Mwelh#R#I0%6oT;74m6Y8hkL{X*?R zGvrs=7@8sb(TG|HgAES{=t)Ejasnp@aU!M46rK>j;R0%%{uq|N_=99S((hD1kOM)l z(gN`bG)nO~1XG(Fn96t@#zk*G02!x8WSBr!1+CbDMhWJqJPLInlfm8~D z2{cMDC+uOSGnhY27~}M$3=_zoAeca-1arzBW(I>fZNeC*XQ^&zKAfYCq4{tgjYvN_ zu!uRUbuQ4Rh!_k%vf?5=3HOe`b#srsMEwj1*<&xGF=n9HV+Zjh`IG8)_ZJ&QhP)}V z-WfY6i)>(zy+W<9=ytc+WBMy5KuQ(2M<6x)RBd zgt8@hgIYO|R6G*NfIFj0CP@#}Y)H;xB*So#ku**tsIEjZBpq!@mZDY;ByYjBphyPX z$s}*3F07IKhLOAt7a2+8^meK%kqk*@Tau-zl>^B#xE4e*;7%ra2X$d3Ih&EZ6Bijt z2c52k2WocvRj46jk?6Ju87^D!U$h~L?S~wqzo5Pd;K6+t5V2^z) zZZ5xaf5?^anqL}w>;t$EGmp7_km>~1*Pt85)p%(z{!(1ky2$bPl%^*0ekE)49gJwL9#veX{sN{fxvd^yr7zEiw;wp99Y75 zRK!K^PyiXHm1LMeRt3QX8l_>VY!9=P!BjC}jMJ(zOdyqlU;>R2OsqZ3G6qx4gfUL5 z%P@ib34#eUN-#C-VU{zPXG|F5G@j~)=7X0uhUP;}G$Q@zz#`^skF7OtEKU+|Vyu$J{RF(OM(eXwh2Bq~r)BH6P+An;z~dkNBjNO|xI$kzyPuE*!7_`U z<9@=nWW25G*H`=Xm41DNxS5cQt5NIOD^$gN6IDjl#0I(+;oWFhSK7Pz|;Q1I_#--8p($CVH!W(Ej z*;}j|gW_c({>042n25&dSezCc+UD?HC{xTFnb8_Yfj(?tj7B8w6dN~&6Bu(Px~R)| zQh8FBaWsr$%NT)YN`dULC0V1_d`} zpT{IL6KydVd1%kVQ;2V**i|r~MqXvZaL1f|4vH^9}rY5G<4FIhK+S zaclCRU*GT7fAQ=4{Q4fTnk+C3iXn=Bp>&E5(j$rcgU^LUhQeY)EQN?V>^D@+{x74A zzxWMHvvE0XJm@bzOx>A{D`?{pfAK!#^w=_(1IDe9Z)x*BfAM~~c_nS$?=Lwnq}NcLL;m7DOvm6AbYBy1;tG_tP&GKxWdhl0`UhRqG~w-3disV$r55CnlUVF!3}!tb(-01!bRGH7~^!aOgd0y zM3JCi1(6PD{3Ft|p8*pioMwr%#h&LG#`8y$r*XPf<{2ncoOlK_{xQ#hiOh4GJ%$(}xF@7>FKyf((zp+ecmYT={y56Ha7=`sX%j8a=+rF9nz|nj;OAEe zHihUp*3^AiQ?K~-%YOZ$Uq3Gv)C0IGPwLAy(_X~s3SA!A0&|h6AsSd<&YREi@hQ5r z{Kg=?*U_zO_=99jey3PhER*>L8`ML%=)DSUBm{R|kPQWBU=cGNIFh=K; zNyj)neG@u?ne&h71WW>S&QOT+A=Bq9ZM+=Pcn*!2Q#A4Z=5y*iZK87u`4u#$!aYml zDkvV$9UhNoQJj+Zwo(+Xgh$+lTW*E7-K{8hgxwPESuIq)jZ-qyJ1X5g(20OfzQ?oN z$!deJ`YujsozuQUT5g6?6k&RQ$n?IM>oKV9I8hjzA4B|>H}!W5m7Pv1`vvsRAS}_{ z>tu6O*c^&eI^^dD1){?(;N`{Bm zhpiY7IXQb$IE%J-_PCQ}Rbg4l-con6jDw{S%<4`mwS{wUh>DnNNkZjWCzXam#eb7g zs~?X^*Wvw;5v|Wgw62ru7lrHQ)ZA{)dOR#{3(cWq7XLm@ zmLr7aFnh}(PL|_^_;cdUxejed&}KUmcPT&2<8DNm1DyB;Sd!u z*G>tQ6HY3B3YCjD8MX7aOUVmtM9(_84)dDZ&kd(J>+$>@Vl8Io{ldDOSKho@n3MMr zq4JQ|vim&fWECl_RIkkn_loKL39iSM5*;VTcsv>6_f=EBs!*xqq!KTnYk;t{lvH!F zNfb5--jMw?oK+>YoGhOcmi6r|>pEFB6P8WvEgLymzAP+TI;p%NR9v71}%d#L2RUuq?8-?B-F06JtDvhxko1 z^~Va8QBEpT1oT7@mX?z7PBycJ&CHs%OUZO6%f-TSp}pmNC(BjBa)rI+GAGOR!g8&X z%4VVRgOkcGs2I`SUej(VX~hz6tCRTwf$)npFZS8@XpfV#6T;b1d&|RCjNhG{T@cRB z+B-Y#WO+?kUa_~l>|_~M%M9iXCzV^FV%$uKsO2!%$_SPJIH}w(RLa$I9<_UF*)1il z*@)id%l3GqSeqmEDA!I3O$0C^QWZ6tu zHnF#C%1ww%}FY@er z^p2CW&cfNJ_Ld)8F+Oy1)}zk?+sSe$ERA3ec2fCTI3FIOBIepy zp)$%zWx7zAa+6V;L?@l4DtVWU=maO%3xw;rPIK1dnH^#+X6C(#=2CJ`qSCrecFNL12;GzK!?k2u*qDeR(UyFzC7 zxRYH~VOPn{PIt146L!^|RB8(quainLRE&TmCMr1v`9b|PmZN7wEXSI0dR|yIu(zz| zWZ6tuHnF#C&nIjb$4dF`FWIa$^fmPz)Ob(}1phouqB22LtX zh4V%sDq^m+6e`V}R8oaX%1uV?Ri9nae~OLh%TBH{h3hudJoNqnowFWKdWf}1%1?#$ zN3fQv`wPsnqc5cBzl>%!@4La&2woSTykT51ReA~U-F?zVbA$OVaTaw~XV%HJ+bO;O7(h z`6PZm**FiM!rP~EIgQKdT+T3L#7r({arq6Gvke(Oho8?io=Y1PG&R-Nq9>QlS4`q)0LzVIu!{UEZ)6IK+OXWc{d z%oE<@e`gp?!~y?X4T-qUNW?IF%OfKS!R1b)J$x5G|B1`p zkYVgYiEGh|{Ek5rt~{G?tL1Rr%Nke8;W8Rm$l)?pQBT+pa1cDLJYnC%T5j10Q#ON* zsai;FJz*OV#+(j8Gtv{b9*P@U47TxjMytt5*qsYeF_Yz^nMY zDJ}Cda`RF;X5{8{Oi9kjdmE#l@?vIQL0VSJj5e8i`?S3LjNFvE$my68rQf6$KGi5H6DO9_v-PHl=2z8V?R-K?u zQm3dh)LH5Rb&!bD825UpK5!xtiyf#^z52!`jDgbQ) z)DG=e?X>nMpss13k!}F%NqUjqqz~yw`jdfV5E)E{kfCH48BRu!ugORl{l_qy<4TOK_A!R_#KYxa9oe$ z1{}Y~@dq3?;_p2hwETpY-Duf^mc8J$4|qT0 z$}hO`E3WLvwF9_%5Z8Xgwcnw22wI1sbp%>Rp>+&e$DwrsT7N+6B(zRJ>ol~^KoTk{ROS7YCrWFH2;R?b!gszW}$XT?WA2+J8OTcU9>A| zSM4wLGwrI{O}mEi{aY>4uB%^YH`MN0A;!9s)>A7~d*QFQ))^z;MeD0|)%t0lAqTo? z1GLYzfm)F^2zfDB>#ltXiy^QWs`b)_X}z`Ku=olVBVh40EJng&6f8!=Vhk+C!eSgO z#=~L)EGB9*)Jd?K467-ynhL9Fu$m658QNfVruL;eOB*b;PG2{TnUe>w3*s!ZI-r1`$k)<&DOrt z=4k8SaXmb4fXDCQ@dtR^2#=fKaWgz_fyW=UF6vhNZPS)&+u?Z!JnzKcE_nY5-gm?M z9(dmi@B85WXL$bw-hYMn{qTMO-Veh2Z}9#*ydQ%1!|;9t-jBljF>R}MT-&CdfcHP( z{Up4fg7?$#eg@vp!uvURKM(I0;Qb=JUxN3`@ct*fUxD|(;QcDRUxW9*wQlNl{M`Ub zAvvOTB1g5(=$HSRCoOKAj4yOlCNTWkrA=I z$(X15kg-qoB@<%%k%_VW$)wl;WMDLAbo3xHByunr8u=v|89juIiXKWvM-L;5VuzE( zv0srTu_MUR*ssa5*pXy;>?pD#b~NcxeGKVYeJtr!eHoj?XXHIaN9JBh4} zolI86P9eqBrjkX~rjf)XOKSCXOcb9v&i1)Z^-)C*8&m%ebgnSuey}T)tbT|rK&-;#mqN-{`YMFy*@ z$(QOHGDKZVhN|C@#Zl|XW^Fz6H;}dJ_hf(659BHq&1>2w{B0(~)h*;J^+z&7-Ab0L z+i-0=`CHq8zn$bz)Go3l>L+qY-AzWSdvI+pxvuTQ-_K;U`U@GO{z}HG`^nL$1LRoL zK{8JLjf_`+Clk~|K|mXdJ?`)ksI1+{GB0F z)w5)pdX7w2&yyMI1u{&%NR~xiBFm#Lley}jWTtwBoR0d7%u=tCU!t#(v+CbuwtAh+ zQE%Y-L(2Vy`^zcHU3KXFkBXV;3*L$F+_<4A;Yyu08EN?yD_8ETDELA>ZK;@^o6$P| z-3;tq___#MJfF~~(xYPQ%&f=Sv}JAhjcn+AOjV@^(`lQ<+UQ0Y?)eTkC*%jy$;@Vr z5jci>EN&F0lhKjslwvw%>CZn(52lm%K5IkW0zbW;k`!>lbkbX~=3AN0OsXn9D2LlC z#a4-{UQHE`D%IoTpLwQQ^|%_Mi9M-OxpIvfXsZ@qy;>F4^5*S|a^r?aN$>W-$X8S2 zuFokme)rTy(}wSyPokQy%=lJO%9XiQq1O^uD2f@4;DA#$G~D!eFQmuqcN-nxL8sSf z$ftzp)lu%Q!#c_XPxaC;^3ikzf*wMT2cKU05B`eo4^qNYp~nY+ULA}$_jA(YgFyAV z;meHC$gALo@W%&&UK@zfm`;C`FX%z_5K^7yYi3qPu9u*WYMPtVHaD%kS`RIG>JuH~ zYQ&^8%50sRlb6#bUo|Q!wRwI)dS*^a)yh@kQ+zq?+ZSYK=D(lvqA#UIPEJ-{N~7j@ zTBTaWs?Suc8egSK<&;*L*(nWj^73DftHElo)>SK}XJrwUc2LiMze7fPW|pG2`R8?9 zj#03sw9b9MLw-(5t8DzAikBc2TPu2cPM)H_nyKh7Db;XzS)iqIq<;W(=I-tRV(Xrk6`2ob6@$u_=wt-@;6j%e$jv8%MD>= zH`aFDfmWG0%=gLNjrTrKO>H=){HhO?$xA;eJEx9o-&yU_^4c-)mAW2$cSOp<#9FiF zZ5yy)^rW)0-FwIDf9CsHHRIC9DQ%w$f46PvkB((*E8Dm7zh=%SqB**m*?6^;ot9-x z(5%c>3~2O=Ya{OHc6A1syOTWe^>YbjkNQdqWX$-i)>+JPr;cgU&z8@*vSywC;g;E_ zW5bjJ|Kra-o9e5RTDh{Xanr_0i4A;p>L{IWQ6fB^QI9Ky_t3ipO4+>+xFcXJId^;7 z{G6f`T%28ePshd^-rwJ;`<>ooC8=?$uf@x$*%|NQ^>(S-Fv|)n0d*_ElYwbC)Oig5 z6azkqQ)+iDPyHm%3x3a=eouiv?9N)kI4`4hL2ib{$2RKY;np~0!$&#z@OYCwcRnlZ z=$96i&bQL7Tq$e`)ScAgBDEL>3$5MVo`@^8Jk9-{Rus~6XOb|*WX#Q%Yt|&GqVj2Wgb_Qcxv;C-_sU0b%jma4Em8IBQmdm;~r|0 z+YW~m*gOlHaNtx+_PhwQH~loA&08e;o=?rhb^|oF-4@bcK-o(zyS;_OH?X|7&fOm6 z&Q?JNZD5htPBPg?P3pgm!*-ZF&;SGx5E_b%Aj1v?Fzbff_B4*wf%G#qD~E!s@G{Ku z8{8chF}Q|jYb_5m4!g5$ura*>gR!(mbk5qZZ&Pvq@moa z3ef+R>d(o+VFdIaX8O$o`XQa77W=8is17(RhsAT~R5*COo6P$4V!+ghd^pR=+ORu7 z?KbA(@N6^=OBLELbn3Lvlhc41zY;LcHEx`UXnNt`AaxLd`myi<6eN}F+#RMwyc(x8 zXCo|_D*FuS0L zNAPOcAk}ztsPnCKl$65BaC8XFB8nvP2z7cY_Rwzh_CC~}fZAcI_Lt-fQzt(!6&nI# zWB3~d#UoTPRq}^5AvL>zeiDs-ryLF+f!+-04L$Okn&wz(`^71$2R2S}7H9W-5!x z(8KT*FmTl7ME(dB!R^cmk$o=4Z4Ao9FmUIZ$6g&6?4%Lt1uvRS}{xxO#yZ zud&Xy_8s^L7MPi|FgT9BCXJf%D84Hc;)1%&!xA)Y-!t{z@nyA3ZB(~WYI;HY_IP ziJ!0Bpu*R!h~2dmU$a-5wrG<20X}G&gSQZQUePxjuT#%C4QNdH4i=b1H<-)Dapq_u zBtbDKG-J?NOcuMVdyy5XA;~48)!Fn>E->%KXm#bG{6PwmG}Zf{o~oT<%T`p^cdC03aUNhs>C^x5l(P%p=mI(UMrxOz*)U zri$2#nL>ZS0*}(lw?R3Y*t`M2-{aszB-b6Vqnjg2SBjp@a|a|Q>U6p_Aw6MyjT={E z%O;(9bn`HijINozDD5kvV-n@6xZayNZeV6us=ozuY);HxGApA<32aS$sQ10n2;iNs z+{_Hza5Cu+2FJcsues#w-L$NNfD&$qDE%0f3xrN zMYGG@H)vm3c?a)0&!R38H@XXpc}Tb5{)}3E!N4?EOmgShE>@$Ox!3GuX_kjjWVcOC z$18k{8Q^%Pl~!_m#sHo+9jpso;er<90i5JcDbVStj`9N$q+uS&XqL8%g9z6k!&zzN zesgvPAr0n8ZKZG^8RgBmGO)g6SUbGDtfKGAq9!w)X9mw)UOtHhVkk%XL_#t8lWP3( zi?K&W0cSYF`6y^P3hhe7dMPf(%OJzS$8hi!97Mct10^yv5?UjuR)0yWAluln%>|w& z!q<#VdVJ7EV)ia5*ThcphP|Tb!ALV+JH1Fsyod{q;Wjh2EOl-(Rp;64VnIVViU&6$ zF}V0->taD(T3e^paWw7!NjZ?Hmgzo?k0Axs7-Oj7;2Me#-`8n`P28O3$-o`UqBGlu zAieX)_iNGTSIvq5xkK0N*7P+JpOB@MML{cNY6Gm5d^aCw#$lS6je+u<{<;TSXB&!( z7^$G>m=#t1B!%t+9SZVOjnda#GwJ6E#|>$So{diwwE z@sEDMcS;<7Y3xgIWd9WQ;<$QxaUA<+N28j?Eu}v*Sy&2vD=v;J>QbcQ-`VY~D)O6rHoQonxe0WGk;`mnS}>9ohgHV z51byot2iAN*UO=-Q7)0>_5*UmsQ}1022UIRi*{ z3^vBqGsYp+gntz9GT0^#2I&rLE4sUdcQ-B0_+?s+_I3;6J)Dj^`j2t%sWyC`{chSe zw}`udxPv1O4@TVKfcTSJ#9x58FHYaXLEkqs>@nKUeImp5Sn#C``;~_r(p|_8gU;`9 z`aw?T6O&FfrSm&ToGAm~-Yo3B)#8IUr*(wWf^C27-dL$2-7zQ)2LFlIZ{;M~^2u9;M&Up4MP298 z#c>{69A~J-w^~>k3rHEaH0}e9a`E~-@%mkyNj^`GILf44yt!rE0|xS3y34}J$lCjP zh#=jCr~60et!*Z<48y=o3sO-k+&3#Iac?td-hq+wJ!M@V-Zp8&_Gc>OU>uuJgF zin8!~%)-hDSq!HG>5fii(5V=&Kh5bB1=Fc$q4Tr@ohqCTq&qq_K&Kk#G9h?-s%Akp z^7$FJh&6#2&k-l{-m}sx9*B0OS1sOGNOyg$1LOpbJeKAut#xYCJWa4bBNqd;P9kRj z>5jp3V9+35uNSW;a~|zY9zM#WfxN8DQ;X}N1l8VFPrj~pG>0z{7q(^T{P7AU`w1$|Kdt1=T;GCq&Jp%+b z(h4r5a&O0xA>AQo134>Re~W|5m3x+0*WR-50H@WgZpP7@!|6b}qmvIhxtxn!x#wbV zHqo5HaEZ!&Gh=|Gw}3N%bjRTRc&Exe0QLa~gLDV>3A+0c@2*t2e}s5%rsEz`xqs>w zu?rA8aYU(d@8p2k)h%LoAQr{z-8iURxfh8H>t?~1GOPy=Ii$Og_XnN6@p^AgN3Pua zg2ZYXc2T+azB#P{oED@zTEjtWXuSRJ9FEaap_`hjzVbjNW!IBt#Cw{U_| z<-XOzZ;OSM5wabe4x~Fe`#@(;y#5oXBUSEuEOdTypz|}Q1L=;=LD1RHxk#1!ehadZ z&%e1vJOac+98s#=4*}7x^g7D>3hAz|e*pP7N0ux1;}&S-Vxasu$r(VpV{i!!F2w8S z;`K9}hg`W|ke3xy?&r|*BVA}j<$mVoTrYF3knXrD-g^4=c>NkDDp&5;LyN=WYnFTg z=}oM1$IOeji7Mbcb9X$p7`~4{&g~ za{sT_yn*t7l?S^w?|qmPfpkYi1Ca`xgaiSD zuGy=L+={i}<9!so@8gZ*!G?4f>}NrwwpXvoiOAJ@ZNPVt?z7i)B2dBmtRHxUo@JY7vq3_Ch{hSV@J3384r?FRW$mvLRdSeTnh7NRI;B+9}(RmScT5v9M zo!-Il_=>9d856=H1?mfVxsJ{2{-6S9i zB7%wv%I*XMQ3fdiHk%NWENw%TVnrh*Kokg)P^^R=npCArZvrYR!lD!@ic&1t5L7?~ ztcVIIDE!}Z@147IcXsmqu=9JKzmLq>xpU5W-+S)4_nw{E>_R#V&QNe0?AMF@`ar== zt;z>mC>2S%1FhtE+B_lHK{{hM9PEbq^=AY%r5+z0K zbvBS^3S_k&pJ{={E*~x}<_HFm&KN8KgGGLQfnT35c&PRGB4a5*CB6W!57V-OyXW&u z=eJbwgLKAkE%>eW>#GDgwFX}uS?q;YS#kuW;6YY{hFk#?e1rphL!vJ~Pd(<_-hR5=ZJ19_4XV@_h^)Q zd%hF2ML=61(3DzxfeqSXCul2ywmeN=Dgf0wd%4V`r50>aXRi_ghKxPHuY$zOY5E#L zLani12DDl)tg$1rPLP3&olFR1Hl*q61sSEj-eBRf-pYk-$D0Hd$k?g811ek7^v!~b zQd@7eP}yulWxJpP89SBtKxLQUq1M&Atgw8E*)4D(W5?YG+&uzUt*Q6e;qDi>kg?-_ z2HXQ_`o{uVsizNMaXTjJ>5nZecop)w6Yy^V{&kvuC`~^o@ReHnYdI|s0bQLN2Q7Sf zEqz1;1v2)a{0Lqr()1tF^zQ^OwT?bvq4R^J`kj>+Pm`YnGsxJP{Q+jbr|G{5T1pN5 zyM@(nRxWJP{wb(H#!lrtsQjI#pA}S;`uT4Qm9sWfE(j`+u~TuS*dPnVyQsATnVqg6ZLY%(z#tPxIxCw?N)HBp03|4h^e)5b&ydCw9w6< zq!u%%m5;Dm8ApE&K?(A5DeY^D&xrr)5}y&Tp3y?TIU`EFd~-(0$m3D!hUjj6(OspAu8(-1ic&?VI7RdUv9Ul@D(S{Hh^bBy z?*d}e3_VSNs?~H;nPF)bd?mv&MaUtYg}f!`G|$ijf{t2OHwTH66n6PZlR)XTS_xW^ z&S-T2t#%oD8$nB{u-jQ!wXv|`70um(4x}?W_kqqm8G2_yN2#*!vC!#kL+5@$2htgx zhe4;S;G$OAT`kZ`+T;obkj@zN1cUB^fm(BSFP%Z2U;yciL0>RS6xff@P$!9=OUi{ykJ2nOn08erkXvv!CG5u~#a6@%Ne z8T!*1`jdj2T8lqxq4cz*`=o`Ol1Re^M@VNJ$ARP641Kg9s8r=+E&N7XSn-gJ7jz(< z(U}T5lQZ;5f{s#|PqxsRWJ70~pabcQ&P>pGUT{&W^XDzdJfCMdMVtr3IRa6s(B}X# zTIn@k^cB)sUl##+fk0NP^aU1ZC$Df`?kEuTqy4)axtI za+Vev`AL&yrE^^)xI#MPx*l9#&(PNiqH5*-dSr1JT4%`@kp7KT?l}726to~Om)7f< zsN8oMm3!r^7J8*Dy+Rf*-rvu}XZ`=iN7tXFkFHn3C(=iH0epddI{JbqQ~@nxsO3Cs zInVymvBXP%>4>AhN)|8cA)V2>3ACyTPJ1)?A0JL3N>v#W(g`H-$A^C#e|&heQ$!CC zZ_U!H3($`#5cJ2U(+Txfpw93DZ)Al~bqfQqnZZJUqu(n+0O>3QwLvH;ORp&ieQpq% zNraL>qL>Kb&j4$dPAFLrf^h1nG=WV-QLaY<6by zzf7J@(Mhoo;JZ!}feh&kISt6E0{K@UXKSwF7YR94MV{-$-$di0KV2Y0Iz!F|a%PsE zA;2$*xv_}AGXZ`QHzRNeW#IJ^Ow^Hcy);iigzq;2rv!o^&@xMJE(j!K@yW>uv@{WD zZbKl)DS-|k&@M}FBM6)~N1&aFKpPtZcRMA}1q32eS101o#=z_2o494^X0Y!N1UbDh;_rKI9a>C*Zqh>A3>_h=6~I;JagESW6qj z3d%PeL%B9I@?xa%p|NER0*%5fy+F`Vx2!_&c#U|-Evo=6>#4=OWo=;VHIDwlVsId1 z8XQUMY0!F7a8kCcClQDZ;k1zB@r+Z%kw6@tr4JLJ>XtPesGG%>HO#^QNxGSZ07w5Q z5duhOA(#L{>Y!I3$*eF}pObY?NWz7-Dkj{`_1oAwAtZZ5HRAjkoEfC0%&XAV@c}bSONPsI_ z))IglTh=1H-b(W%V#`|Yl)xGgcqvO?DF`TA)=MS=D{Tm@bxPoM5LlO`zaj`ITh=-g zfmdt@yy29*!coo61mMO z{Cj}km8EYN@XD683me0B+8E@PwcUos?#rj~8okTfZ){m7K;wrj{ivX!ZdpHo$8O>w zx2&UR*+VVnEo&cJuW|IB6oUhKxr3w9`VF*x5uB7Q>lXxK9|%Og%R1#0@eC0E%+gN_ zP<6}t6Q~EomUY^~0BjDh5a8%PD?$M2ECm07(1k4hA3;dnvMzwcF0p0(Q#zrGf)J!L zLS?e?#5G%Y;~PJ(?c_>Qx2*W=Fd;Wyt7D`@sBE@)5S#6gPO`d3SNIn^CV)+y3r|t zTS1_Dwtll9pln&yO$2VXAyC69f!jbJFXXA&}&h!0jMVTc9gjR&5}f z@?H-99b)hyoeh3{Am5p->jGTavhK__-eu`34Y_4Ca0;Ia_$JwUihx(PtR~s`)IV(u za?47wq2a%L8dK`EcPFxszwQTxy#inP;)uOK`-bv8;?K`M6tRcA+}MXvKLhH4Z2e;a ztUk&=kZnB5|JcF-e2%c40Z0Gmf(m5pR1Sg4LBT_PjDHX#aGXY9s_6?OPB3&F{f7lQ zWbEiivh5z>hk=d?AjsH(en2LdGeAaI02{T#cYjr+N0 zN~d&QP=bt|Qe2>g?h5D^1tsNiy(F8AjI%MqV zw*tL-K)+cKP#(`$50s4hi55Nic>ZP!BYu0ih7$_4K_Mxi*9_>IV4*ykPYM`YKuw^l zb4Ii9;c1a9LIW9lXc~Z5y?|afpw|(+)W`DmEOhEhs&y>Hl*DN$_(8_bFAe-s19}rd zPI)AsYT?$z!ia||T~L9Hok{>yvI6>Df{OAuKFdPoE*mP%1Qp2GsRTi#rQo4Fif?H_ z<++>V1g#y=+6Xk|F?<`KMJt)wi#|fe-p5Wry<4EFkKpgNz#{L$$L|lS%LX35-;b8xXd#i0-|sD*=fi?0Wb8b9gJ)hq?;%L4kKXe@Nh#<; zJuLYF!pEt^qoco%padBUrP{2*eg>4D3g|-wCH02TQ=s%0MM>Te8iJN{)MCCN^be~# zar8ecC_%pG79iK6R}v3Gqs$V?6BlLZ;|CeTz6I4y1hO)j0x3_%7mb~1B8W_CcIDafcdfM%P> z%q*SEJV6FBb~1}VW`SU$-27Q!0q48OVu1=7JL+;(J`fWH>dUlriW4WHLc;IG<%uXh6e7QjOR zeS-j3ZuW#s;2Uhf-*y7N4d7b@vT~zm3(!pKjvVZF#9%|lKG^R8byq;&A%K;eJi7wM zO`aVp1$mQaw-e|O0lhDve;}Zh8$A24(2qiHg>UeDU_;@f%cpQMfM*g*;#@9>#Soq7 z1)bwQ^IbuF$~~y31=+hWv@b<_sA&)-cSHOu-gfEIu$sQ?Aek(~rH1U&QMe~Q2A^)p z47!r}r4@=*W*phNY>@|3oxH6$&f3Uobqcg;abws zmiRyxz>2TN4?u*8sSsV@QFy_JUdCwj84y7byjQ~y`=)yEz1++>R22@!;&~3l81`64 zoFjJrX8e8)T1vPE{bF*`fMC+Wbnz*&N+3;9a1q0#K|!$F>1kLpA~CZI4s9BgjGT_Z z&KPm zTwxr-;L`{^uCqItxKwW0+0_}pAbaW3|MUwHY#g441Mr>!!E%_+F%IeBad-hONkfAe z8VmrCi|c_Z4>LuDz9Kg?RCJP}?(sdzLNVKXVR)5vmZucjat&~3oy@i7gtbJ+hA`{7 zXlEUx(^xw8A{>C;d*H<59AFWPlB294PmOagnZxtpQD<@Hg|-PP`oKKCz<=(N3fBA+}vPBA1O1b@H}Oc zj4eXo{t+}Vj0glyKE?^eC)7qmI6lT9{EYkg6oL&Qonr`_V+be9A^e;xeaXc^h|uIH zBbho2Q!RYKG}UHe@Nf}?zk;#cnrN4vic7eRONVeNX<9Jpo}k$DGbr$3e|%l0`hg~a z>4G`p*i@<7;G61fG1rc$jKi^Y8?ik~*q1dM83`Jn@Ju`gCy{+azrI5=#tmd}@&f^- zG~?@N7IknMA~}XOP*g6IqQ{|O>KsqEhR882Mm&j6Km&>=Ns(KNiU+Yo`;Ta6IYFnf zY)HRz|EC~WPS81W;t^Dfb7W4OMq_9WxUY~U!*&sPjKP@-)RjL}opNk}G#ODvc&36# z^6WvzRQMBStON66?7&$#0Q?yU)&V+42fCvJFUk&_L*xIkqrDi>y?WHK@CNrcJcJ^3 zcml`}`~w}E`iHnN;gpkrJaI(h=x_*HO`nsMZ9WiaWJ|FZ^82(6%HxDF~|SAtOw z^R$VFlh8_Z1-T(+@*0-e3An(rh2M5qj-`WNC_@&}I`3P{49gO&7aEJYyg8;FmEj3d zO~Q;!muZRFt{LNx=XIQ($c1E%as{E3UL%D$svbqjR8H*&*AZAUrLI(!_@MG=8pCiE zRIub=jFB|aU=P%17zZQ+5mt~ThyAp0Sb)^!^FmqQZ`SA(FK`#HREI5_n zk@2R}SQg8h-~haDWOVU@&cXX`@Lnf*-;Bo4I`Ez^7t41wQ$snVm(oy)HORGOiH6Y^ z2U=LGss3){3u_pldh~_0I?PySUyre~HQ)g7w?eQ%qH}b%6FR$IcGkm{yj&zgByU1t zus)*um`qDF-&wZV46^x6sg@K9Mz=BEq3)%ijM194_HV&L@OIDz3%Yh=BWiA) zjMgObCw5M9TuJk7X2X6P;6foV;cw3w zYegP{x1V@#H}2V$E6*m7$M-Sgo<`=U0^GaYVVw}@|EOAW(#aApNr*^ZDW<=O3NiP>SuA51^;UVTZ%iI|?z$dInS<&=N zhGOQ0J#k{93*lvyC%*pxy2>4A!!gU#fQn%1n04lc-SS>Ei)I^E;+fW5RT7MOjOBc6 z0j16f$>4`UXsKF+m-kB7V0okLZKZ1PX(QJ@(#Ro=@IX?4Ki0$>2V^ufS`%b^GG-J` z+D3CoQ!e#WcD2UXXC!y81Rl(MiU z!(B2cplf$Wb16L#@x7WUqatF-Im!a*#)LQ}h#ldaEt?e6SPF_RZ~&5>Ay_)nIo6o_ zv1}d;>R-rZ^B%M(9S(-Rh_Y4^M}7ysQdy&HyAS#n<?(;Qx*saZUt>Kw$hXbL zX!m_1R-y-R5xgEGH;2he4AZybdRJTkA8NhEz7Q-XT@C`CR!uhvN6=p_2feBDZ^soz?r&>Rq3Ueq_7b zK>Q?pg5mvU!~1@r$Dj`2#KqWr6ydj;q5q{+`OHq`TM2y_gcZ79+1Z?sHsAYP{FmMh zssqY`llz#R^#cS-Gd8D&jqFYw8V%%isELl2BitenYon?J# zSvR_69Xrb=u;jr^u~SKx&Ql{)=Dj9Yvt))tLac5B2?NMlea*s^tBG>qjpwp*DH(TU-OhZwMA&N0i_Ot{^p>5oz0%qH(JkMz zV(hYW_L+3{Npxo)*;#%qEx(Fx`K6uZcd+EaJYuJEQab-3LPgHCU!}@Vb}Hwj%3r07 z+8ZR{-Xm6o0DR34Hl57?>XL4`-VyFXf0@*qpRN9@cCBtl@3Gi%dycdN84FWfh7;-Bs-PorSoYK zDsryPkt#FoRF+DWMWu||0-AJ|s-!C$(fM|+UzV;{+s#?GdsT$BoS9?NjD=`qn!1$a z8k2XDR2iRUSxQRmtfot=DQQubl1B{hvxFX7O6KE)kH?${zugS|#ZqN~oysZ+y&Qy< zrDUm{%{poGa$3}-WR0EWCTY1Ly5)L1%k9!~Yjn%ac9y%P;n6;j z7Hui%&JyoqJM$wF;cIJN9E#qfgLck-lFm*BU;hUbq(pdI+;hl z!J#?pcHbOfEobH}8AkVR&QQD8%b2`1rHVJhvXs=Yv$|bc)yjxMtH0s>PNBz^k`$cq zAI*rClml7E``DQekqAZBycih0M+5Af4VTWIjc)n0 z72`=eXXB-_vC*B4wzHfjEhk5}oMdM?3zj^X&)ccYm(J%zsK~jtSgI_rQ&}TbR+Tbp zD`?VLs*=HMM3>pQep9-B-EPjh-RmN(<;<*-Wh^C?vRplS^*7xa9m#MjWV!k%&12Ba z=Kaku<-x0({QaFN~)bo04h8nnOUxaK}Dwi^5rNa!g7fbryOb7GP-4RJIlMJWxME>ZR{-X zksaz3p(2OxA?f@9gtM<}Oq{siuDRX!*%{?YqwX*&=+?KdDW}%5@yoTd9V|H&MrPw{ z%(5Ud8`m2ld`7}P8R30{p)yK(AFgJ{X6AdCo!vxfH%_&Ch1rd@vzsC9rbe@yY-cw| z+Re06Ss+#B*{Ljt3eUzR(KBOFgymKvPHUy*OVKS?+F8CKE!Rc2e8tW(Bs=tGgo+%# zZPNK>gj3DNx9p5|OQT&dipa+8Z2Y#{*`Ab~eu&J*-OTc6WH#BT{u1GRpP_PA zdjC_+jswj1X*;`%((Zz4w~N{RV`o=3+gR!2vz4`&+qtvVHC*znAnmTSQ@K{ERJ2pM z5h^?zug{LUHdcwS{L+Y14QW|Dy5-GwmPyhwF}kJK&hie~q1q8DGAs?G^E(kvH5+w1 zBfm6i0;7m*JjBK?#m@Fa$!Tx4TJ(Qogz9stav}Yl~ z?d%pyy9IVCE2PR&JC&EA!UM885Orf)6=CVd2me?o*GtRSqFcUdXZg0Y3`MuxU}yP` z?9i476*+vnrSn|~r@FE2urvBd8tsEo#Kx9@9=qKi*x6YiUzsO$@AL031^8>_NLGz;J*4%S7&`sz4$+<>5KU>bduJr#8IC>m;F!Ti!kltw_;1;3-1ZhYKmA;*x6i;o*CeH2Ic z!Pt!#UM33bNnFN1C#_5DtljYwg05Zz=&hQYeKcwiSWSgLittR~Zx%_gnJxWIj_%JL zH!U(KEZ`Kvd5k0t)108I(EMh%mN6y^rOJzTD$Ail!?v1Ji(ez;T1jnbkZ)PWd(S~` z_u{DDu0|JE1YP~}h7{&MnP-ZCJANf=&M(UAS4g8KvSAROT%sedf&#x;{Bl&kPRqO_b%T<2h_1FLO zYun+!?))P&G^J7f_(zxbkH-hC1OBdE3iAdQb{(2GuwZD{W_g8=6%`EVdQX1gpl*G; zE6nR!(EZV_?FZ!bFD&faCcnGsW!(Wi zySx54eWUA&>no1+PVkQNj!k^iyUDxJJ3DcQ_cQNa??>MK-Vup^d;j&G_x_`e)=IQ# z+DvVRwoH3oTdOVBKG256S4k`yG_t~y3cpwQtHPNI#hy`~@t)^A(>?P&3q4Cb%RMVS zFL_?}yz1HD+2ncKv)!}P^SxJo2*UIrh>_IFnJz)=4$h_`Pu?)p|%K|mVn&~ZI$+t zwi+B?(O%VF(_YusYj0{Bw2j&(?JaGywnf{fy`yc{c51t{ceUN<$6jrpwqN^D`$+p( z`%F8ieXsqZozc!}=d^#c;=~b&qY}p^PEUM3@rA_Mi3<`JCN539skjKADP51gz3Ewx z-o5GBh+_!HO*p>Adi$1VGy1#*$E`SS!|@#)x8t~jMPi3%7vk|Qj_={P8^`x?`~b&2 zIPS%9ACCJyb37m7)kmH;JRd{v6SN#a%cp4h3@x9d2(^3R=HI>om0f zfYzVT`U_fTpmi2n=b-gBwEltCd1zhmO!fQ=&Htcz5t^5vS?oRQ8SXvj8R7lgGt&Ey zXO#E6XSDZ%XN>n>@RoR=M-IK<9q*k9i&?Ok?VaSE<9*IM7Z&qiF&`E$!eRj|7Q$i?EEdCJ z2`rYvVi_!!!(xT^WzR}jt%B7{uv!hPHLzL>tCzhmcwX_&^t|ew#}D9f4?OOL$9?d)A09u1$B*FgWA8}MC-`^3yV?6GJbwny zpX1*b@ct#dAB6X>;QbK1ABOj@;r$zU{}$el!23~nKL+pL!Ta~{{sX)phxZfkeiGh) z^nT*~$$P;2Gra!-@4v$PZ}5H!-hYSp)A0TWy#ERBf5H11cs~p8=ivQsc>f39&%^r# zc>fpP|MQOVT*SXiKq=Nvc!z5zy(6?Ay(6`syrZNZz*qUr&2a+zo%@`PN!_u z7S!6NEv)s9wy4&2t@!pG+8nGtbFu!+!wU3A%6r2@N;cvtuM5nlD^bVB^}hZ zHvCHaA?c8|tJY!d-CAF3@74N7+g)%MgnrtPiuoi@qyz4nFo2kkk} zac#2agf_)=pQTL7VIOSDWYgPn++#sO|Jz(k>+xCvNo& zPrQH~t)Z5>JqPCXC>oqc ze+q@Y0EN)A^iuh+Zjb!FHGB1DZTJ=<=sZKJ%709!cVE^i>`f)KV-xkarU1%;M73jt`ix~t19t8h@g`m zh5V%my-Zi7Ox95mc+%@p4S&-{BVhVZ>WSdfr8@XG{#KI`UP?VN0Ccs_yDrz8c6wqE zNN;wU%XKS#D}?Dk=}!yzUuz zrT6;Zi`4>Nm3Hkh@QDFM1zo%M$N#x~^SjsW;nI5+6uR^W@?HA9t`r>ZbLps72M)lM z_Py~B7u$Dl;L@A7!mGB;TzbnVTzZTAqW0Y%Z84}nwD{|0-HN*5b;19``dLs!RSm~I z{~tOI*XXP;*IO1gY|x~!58dm~GrwE!wu6e0S@q2S)ei(**S5Ij!u2WcMXfOi4UoE3 zsugc|+?9(&zVV)`u}y=kn)UC&3b^Ev~xi?IHe0rUU8+#qC`rn!}wY@2on>$C~Il|o6JGv~P>77L% zH0X3D`18yU;wtZN>bL{l^9z{oUk|oBR5iuZW^uJ0Pq|iYezx)(nT~z;?bEHW5A%NK zsAGfYciotk{_6Sz(>E+yS^0J6-tz_yWWMk6O$=$4a`)_7ccy`CEGJ(m74}70lF_Ug6(5*jxiX^@qCRuR>fF9HE z;=V_4IG^ZpCAO**=RVfbU9m|sS9ZJH!QJ`}%F8Y2k3aW|FT+fFz~p-}nb8f0%$hD& z0zPUN*D4s76O60)7_-7ngj~Aom^-9kU{BW=cNyAYi>t!&2eSN+EJwkz_>k)nd@n}D zK8lqzxDE!#$zTr3lHx-!xUEkmcU-Mz?#G(BE8fpKM1Sg*+tW4T3bxf1(|xlOWU{Xp z4maEelU9}73Fp(@4V${p1l$h=<0}qfXgzR8VPGzq!HYNq|Co+5CF&vJ< ztQ_Lu9)v&+nlUV_7e2&QUXaLAx$?#qjYsG_LSe)QSf|LPhou5j%C6tY{P!XpKB(n#-PNa3Tzu=M6p}HBWQ7(K$)1Dgb|BBL0+{?x zCS`}<&;aF}PD6kwf^AVV_tVYX!r(d;;Qx2%*zIpx-y;U|br&bU-(nhw*G4HihX$ zGOam|Oi=*d->Oo4+`Pu_KFEj}9L;3KXD?Y@BCACca99N^BvHKkrW|+0NhT9Hd51$E zUxnlh}=&sB7QzE5=`*;HD9!<(?VgLU8+W`NtMkFjM~p*4y0pIwMUwFbBuYhZlK!b<(< zpVzxvQ9j-Y8q4ByK$%QdFD%Ak8my|46_(+OOW2x*NU>z5r%Ze(GGQ`>0WE>aXE5pf zNTqmJ#WhkNe?rb@K-g#+jHZ*(mSs3R+tB68=~F4ey`+`9;)6VB1^o+)it_vAQT$5>c>t2|P;Zb(G04(N`#Rz<(XYoU@(3t;P%mUg3 zAp=HR-8|AR+K9spXkW$r-)?Br7HmY9l;@Lj*$@tILit)+jA~*)?lkl*TwWxDjb!j8 z46dgUB!dQqK|#;(PE7y{NPj54NwoMHpUZUvV{^<6jEI9vn*uWJP z%aukD30-}z_8pqH>(r@DF4iwv?n>xeETH4Zy_1cwDDOJp z&knXnOK*NRrMxRYi@h_+EiB44j02rIcMP^`39U_r*4}J*Y<^#EAgfKA?5sfRT=`LP z^bvIMU&7H$3E!qwE`JU`;tJY0vFpLnCPv^JKgy=wdHs8I2PCdMB&^3PY6cD`IM6HasZHNsAS_s9rNwJ&a4@F&W|3UO=U=fj9ptqUyb}0_= zKB{1#M4bhtEu^$kaaLF`kSb9Q=z-2w=#+QeoPii2y5`ty&VKuwCbNc$+|> zDp36O%*z|Vj3m2kIDLmX{kkeWPtHZ8$gn(CP=E|B$nVL@X!gYhm@-f&xAPjiI^`9$ zWe+sPzyp6fEE5(hh%_;1?-5^&z;%Q0vV(M2E4o;4sl$1+$nn8QfZ|TZ?vNjgP22YE zI_CyD--lspCkAt-;-Roley?yY-VWQ7>nm7@YPZo-Yli(JK6fDu`DtDw8Q>s{+q>^DHL-)*E@$Q;^0`?eiKVBa?s zHu+3Z5Ro#?=?@IOfq}k#a@#gzA(C-K?-f*x|l(09>)%;Md_ zXN(tmXzJ1@Mwdp)DP+Bxu#s)M{R(>K_8Zh!-Ftc0a^U6w13HWh$&E-f8K%z+wClpF zf*htV_{D^MN_4~~%9oYN2+EfX<_dx_x+F%*7>uukBNu*lSgib*O8pCZqR@-FG#;iP zwr(o5>Af0;POfG(;qYq)`&Cv%*D&^l}6uu#d9?DQEJ);HlTL!UKj+C5P z^esbdmTosCa8{>Q03Ra2=P0fRU|%%WbXr-CFwc)8YjL}cHZ|lfjQCtgU;sV?HP;h$K$Oa{Jr_QJ(z{+K?`jcrkPBAvSuc%g_ z`ZpJ!c;n@Q*kQ`MzF_%Ti1_sHoy!J_l@lUG%ew{y_{g6!oWCErZkks86Jj2Hp+vtY zK08yS#{MMh(bds{BV+g@cUIn2)tLGwq@M&*z7jcPv2k0BPyc#g{WHUQ)I9w~WhPgd zUxl|~#T)0H%fG*i@9jzOcZ&IY#ojT2 zP_zd1=Ouu#Jy5p)L23;nr=w-!{K-i7N;U0PMi5N-D7ULeqASXd{$-5K7qlz$qNSzL z_Nl*nes8)1%QA^}T$ZpKqHL9>5j`Wupp1159#q(^x7|v7miqsj8gD@Jj|rMPpQ=oVy8=%t@RZzj#WfEW7n8;RZ~y&IKc%zAhi^oj z36AU+2{-#%=x_P>Z}4{X@n1D5gYJjk@|BD%@!;pqMz9|!9^q-jzw8@ddC0y>5%O}s z+)_o}3FPfQeVYL9;uGJ^UY^jm`|u@_>`Q95S$Kfc?-lT~jCAzx5_BM)(fI&$b_*`K z#ATw#ReT+B+3hPCH3yLxHI*WPV;lMrI1e$v(Z5G9fON*-L!bElZ~P`Vhrbo@Dj2>P zl0_fV8Q7=j?kA$VJ$(GzfxXn*PZ009H16m>zG8Tyrw#v^RD9p0GsJ^H{6ZkkHzR&w zgNSddbcT2Yh~N11!vgdvBg1M^KfjR~cG!ZiWY|#=a!6-%PJ+&HpZ>j|Q*6+wMRbmX z#P1aV{2U8AeqZ4G(rNuDXhAxobsDrz`Sf1}t;u2$NG4XNEUbRDu;R+NRlg-w zuO_&4HHIpU$knh=x<%5hW+A5xqb4{)I^%ddIMzz#u18Z4e?fJd5;#FZET_0<_WbZooidc719~kd%(4Gs@_o$T@0dB3Kr)O z(axZy6o;XXmV5!}IaDsv(SNU?1sM~qSw`ia4_dtiC#7=l4Fdb9f{Uo!@eRW)eIT77 z4*+uiRK2eNS1b4aa$W0d;Q>xNS>24I|8YSF(ixq>pi?BcsFiyW24_Fz42DZq?jJG+ zIQoYO29VAeJe6u!xrf25R?{(3zI1PZ4y~%6%G0?4+>E z%6&@dw4N8VAf3^g4_b3m_1S`!Qn}Byu$paQ#W(a91szCdbe4h6l2m<>prcgoODuF2 z+0a=o=s-H7vl?_(2`*~ozRCivq|F+^0MZ$Qbzty{V4zm+uawTtogx1Qp0?v-E*zm4gW(4cSll6PjdVs*pSYMWP!+Ce!Zz6qE_p70e+-%pS`Iap=?12 z(ix!~5NhSuTL?l*o!-jAr-hXd=B3NuTF`-XMyDg_bnxr#1RbSL?_iGPe)99i%gMBf)OCUmqr@DfRep3$tNXK5Rmd5_BM) z(U|}`*aL%fsw5FJsbL=%do2)Ze4hN=AMgrT!k9#?u8dcGO8gosg!F6ToWiJt57gy~kNO z@YU-%K>{*%64OCqs$ihj-BZ&_MjeT)yN|NE8%O^Pfeslv`m8j&nmY`HZ^K|y6Eb$7 z`RL|c(M_e^o{Q)njZ$yF=mc#s&=v|brPf|(gSNy8+A5%}NYj@IK()?ZA@gXN1zXhF zFNpv{#vb5xAn{6?zE+S>YwTA5t=0=`?Z~_)$Uw$UW)sM4Ow->KWR&`PqlL?xRxWHi zeoIh+jGfAMP}!EIZxK|K+IpLX$`%_cI|LQT*s1IWm3IXXwXS~G3d@(6_XRFw?6~`Z zyI0_Di^zQ{PwT?b%p>teP{oYE9r^(NP z8D#9t{sgnrY5FNaOR1qxTUed4a$%G9FF^$|b}AP@<)1YDoS>rA&;MAcoU@_wub=`M zI~8|&3;mMdq14WoET}wd(>YlYQ0<~T`U!-m#@X^??kslq5tJY=m(u>G_>B0!E^)v5mJHlA&WKVk zSIa0Fc|1zJd}{_z6G&&sHG!;U=pF&C*34RlQ8RliJdighS?!9W|29Df(ixrGL8rFh zqE^qfGfGDN7Fj)?VhnKf-ys-4I%9BWhFt|62CFB)Af17wpt}u3cag6tp0n(YhP7+Gpr(1udn*Zf{}L*20QcG#v#UNN05J2c3H}^e%#q zQf1$3q0_~N&I5uDq%%6Xp!1O6qE^}uS)i4)c|lY9#+Ud{A(N@ECU49d_8GxWy=6QvFxBqwws7^rjU zaSJD&wL?XSAf1J1IJgbV(4WcBpAy{ET6~y=(le6oQxr|pGY6+ z1@Hy->F5id(A8)eLoMf7%X#*fjwN3DOGh02*Jbgt9?}`Dn?dVF!D(M6|Kr0cMCnF` zgmeN){PE%6#vdP6bBgE%VvQ{Q76JMR1p*&BD4tHJHGn$93%rpPLbq5LfXxgR0v!FC z2mz$C5F~?8tt|aELFfyE&`cs!3nYq(5dIACw$cgRE(k$7BUB%R?#$A4LFlkT=uQ(M zy>vni1R+Rggqna*Bf(}@CjZOi*%X~d76N?N@d;!|XUOS5_6y|SfSj%2+tUcyuOiR& z;%}mH(ce@cLpnna068m5ze|9-viRIsMBrHfKZ%m`_|Bj1YzVY=O5kn~XrHCG6$CDb)qzEzy@^0u8v-4j61WEhIt%pE z=E3g_#1e`*Uz_CM-zx?m(%IlY1mp*^^!o+)S<&_7H24ovqIJQ)(ETb6xkNtf6h05| zJ+kyi1pH9}{}RFXz{aqaHii|HZ#ae?v7yl`Mj9U)Th?IED9X|Y2pZ~^RRkWd5f8a# z4M59!YB6tF8`ye{qko7P9LSgkN78x*w4M^2lr8Hi1Y$!tE#!DS>lASm5JzO`#R62_ zvPJ-Pv)HnVEew#Pn^_2O^p6%HfOHmui6AsSOD_?G)Gcc~NW3Dptdi0RO%jA4oe`P= zLesMJDT0u?Wlb{?no>HU=LI21XN2Z}&@915*|KI?2=Fayu0V!#hP(jC^98c9WzAQS z<*Kz%AVWGsUJm4?S^8oDu54LL0d8zri}89Z&69{NYlTw+Ye8UjmcB|5P`0eqCIYK$ z2)yi+z#Aa&T9*E*AfRknubBwEYC~YXQvx9n*dWlAEo%c1O>2`J{7qu;A)O8WHXv`w z(%%-~%9gc7Zdq@uG~^Qbj#K#EfPXhj-yz_YE$dxu4BKgAkXzOc8yfFlK8@GuUDkeM z%Q^`f$FuZff`+Jg+4&>zyj!NqkX#FZUDO=XB z2*f^`iV^R!es_v^7Kndk>3;}Nb<6q-s0YNB^@oK4*c@OXz|ntBgaFc62rh!qzghZu zK}g-Q{soC$V#_*TI-yH~5Tr9gWwY_bHCvCv_m5uN$(5vTSqa%;LUDMlj*$|fE3(Cd z*ldS{DuB>cf{n6eU1cG_x2&rLGNiLmTnprD1hTSaU85q)RjaZO{II=udp=1Ihsb(2#9H9+8&Y`vNwpln&UmeUJAPEF&X6u?Dpln$+ zO$0O>0=1kHxB~=|1-i0jB?Hlv_j2&-h{1<+Huw#ITrXR%E5Ma4t6sM8E~~CeLvC3O zox=M8@5|O333z48@@3;w|Fkj4Evu0YjkL?Bk%EuECbEyeeh3Qt1itdc5&MAl4dr{p zpPzjsVh?$_u@9qu4%APx^-lz_`Y8X?Y~xY>Cl(IibA;^-IQqX3R3Kxgau`&;5gU)EZQRd2TRNo+f)Zrxl;Q&|baz0%Bq%A5>)nA!Mwcv%_)eb? z;57zh>{QBw%9R2AiU2Qolt=YfTBuxs7Bw?Dl?s9iWb9O~1(j~TUN z85C*-^xFb@qF|vsny(cwwt(A!uFjc63m={qw~Np~#vYo6;8j1M-x<(#!ApHCU*AIK zPDxd_5K|H-Meu`+onJcm`2)I7kW(JX`z_pj7DhZ&O$8Om*r_xFmF$3?DX1uq4D$m{4PSDx|t*t;)9>ccgXkkR3>xDEZ6eUd z2lNsFsNM(~55!C2Mo@_b9ZW8Rz)S*4SiFUUZ~PG&L4EEG(Xn?DOJ;CvTZB2Xb?M_mEb zWdc>X@v}@tmGAvm3RKA0QC|k?nt=Y209J1LtO2lb)8{3;9z+VsO z>jb!R!{>Dq_&OW#H=TgL4e(6?eWL(ZZuV?4fp4?{-|PhZ9e{5Y$jXhLtw1xaJ94nM zi@}DBeXw@}_1%EJQvfSBdEN~eH+god6y!~w_nkn01nB(%eUE@vZt(2KLO%+*6~4i< z$A-ekmrvox0G>%KiF3Ii7DIHR7j%yM%$Y%a$~~y32idzYv@b<_C?klHyCMD+Z@YA9 zSWRCbNG8j0sUiDx6z++S!KYiYg05tKX@z2y8ArD6csgd538e=~y2TNZ$yNNsSxb<0Js-?=w*!7ChQBmSHlnc z%VF@n+{`&twY~f9_U;Z8v%3+mCe8Rgn)dFF?cJT)yYETL2?A^~qS1mnbT0#-B9J2I;*v0bK zaGV}VZGzkvCvmm7d?Ux}rO>Ek(C96ZqR{9gFGit}FKAR!X*^mwjlK$vat4il5-AFe z{_RfRcOQ+G@g)1QD{6V zFGiv9l%Nr((s;Ub8qX>;+y;$d5-AD|_H!vxAqth^;dsU>=(trn`0Z(|6nE1S#%q&y zY^526RyH~5G=|ApJQfbHnv8*9D=3{~qV~Z=?PyHY;u16_bqR(#V$GY(*1U39^QLL_ zmS;`X_^K#oZZUo_n*8A>pj}C|n(>b@UQdf0x5Yv>S!?6FhmptcKD)@;#e38l3opMg z2^T_LjO98r0qX|$bYs{PO@3Fcl96+?dMiiH*0_2dYNRXW5^B3#^)QXQ;9r|K2>@!( z!8r>V@L~$tR5*a2DG)4VbdHeSk4@)Z8M0|;OgaS#H(q~FVS4iSk5StO>D zcEhIppxdY(L;Pmk48GCZMg z_z`O!qX%M)(HuB{pV<&BMs$uC4MAExEMqj6E8*v?U7?4?c1j;puHoy+SiFb}{zuR? zeo9{`2%ihh>O2QTH25~|@#O_M=ptw)wH8sm4N;XS=1sc}G6Xp@BC%WoC5uUi(n}3A z;1`qA$bpSx1Izos2R5}A>%tP!zCXx^qjs1Al(3<P9om*PEfOB-_&SMRto)Et#9Gf*G4c7@n9W(Hb}a zpVbg7LFgO_GOT$Ey^lpl+iRxp$fS<)CrEL(Q z$JtPX1_j5B8Lc&-1Ce@%Yix&LbP8jnLx08rcRL|iK=_|^Bn_0sY4N*UV>d+7&|uP6 z>Eh2C?ufQx%1O`$;iF2OFD*}t#o>K&(kh$J%(`X=Tobvn(?f%tMe~kcJZ`**rx$Ig z>mR@gR~NPU5H>P<(2QXM6m<6DBs5ecv5`S6dyM(J4;oOU4_FCB#T$Jnmj#xb$Fj$N z!u@{?!2(O?80VsJU=N@rX;=`k7Vk^yAs{?%)Xh(EIW){P4?Vu&tZ$#0FPQsQ?k0q& zbu!obJgg-;_AImh0`070bQ(*?4#NTH9fDvTqjPj@40hsCL4AbG;jhu2G!E|oC3dP+%=ftXKjq9oBUOePFTy$V1Dwd5S%Pl@9m|4o z9L>lXK%qw`2q^j{GXldfS>r32Z-F3o@_!|kZ}5pi?8oTDe&WOc1!6x(BgV@bh1f!- z{R?T23nrBWlj<}rZLac&N9@Fue@iOx;qouSg2|o!7Is?t0`Px2O@>qS=@cA>N)Xm1 z75KQ+@GTZ`{hhEbYmtZ&*VAwkWx)SHGX@+`;Bbb3CImw~h(?tsYFmV09b0M7K`S%? zOxKC!%;Q@knEs7RNd1Xs7ZF7|-Ye0h^v^^npAV8QTZI~<5hFyHo@*!w%|OIBTc|G{>xVm8uq|7Mg2T zD-X5KW&9YDWJI=e0@9%ZS%z~VVj$zor_B$t1@CI;B`;+eR8a*paWWESc$IKtJ#)A# zk(Xu6%eAT(QvkwV!i|cTD&%E3^KzZ)1=%k~`Tx$58_3HF=H*7bL@aKC=$zo6$J!_` zN%Mp0$XPT{{<@k%nhconv+$Yl%Pc4eBf9#-ww-J0U_Z(F_Z%1e?g)iZy+& zh#6N8ib-pO*x|66f^Ts{?9<$m7ItCHHwU@T)hF+3SuayxW&Lh|7P%tPJqGD+b+j?3NpY z)tYREH8;Is=Ahv`XcGkxqth167)kiSNjscCw1*HdVk8kPw09s~8c8~hWh6Us{~aON zNYXh*@@d@O*cQ~c$ieK)^}29z4;S}w@c=|<3yWxI8yn~vzKKp(I*VzA-GYph!FUtM+jkOP*5YcrU@(ORyWex6%@=3 zt;m9E}1udW#7sp#l2=ln+>iPDef~X+U%#jNpZhfF}(FF(0!m7+6jVGd724^ z_LvKVd{r$>FSOUJ_Nb~BCKuXgR(niU3sVd2H>>r98n#^wNirhaIUXVHPnJ=$jqSGO z(>~%=Ndfed53oENpn{n=g~uh_s03#qdHIxiDOA0f0uc5RZdAMsA}^mYFN0Mtrm7_D zCETcZ8A@J0XI`Gb%g*us57`MtB9GiXeB?tg?VqBGV;w*w`7|q- z3KM227t0{nyg3x(yjjWptbkzihR!i>u0%n2Oir3rTZ$e#106iz@Gwx zC>nR7k;Rx!V|fek9(VpO1dB19BgQ4z^UeqLzk~W&8Rp$w^?fcr;9?I%k~@b_Uimg_ zA6i4_#VqG>1*Pc!7h}dReT+*$IRMeg zIA^tZ9D;-26YI6n*C8?}0iD{s*1P)@J` zsX>?E`ct^}!zuksMiZ+jKSN{Er6BjzU`+NP8n(~T7`hb1nQ%}khlltJx?ltcca&J= z!*q-l=*zH%sBq9lxIBnzL_a%EVO#2GXWk=jM8T3JKkFe#{S z#r`AKtnX~{aIWg)xmI-MYqD0}=(=<0%{JGjID7+*$l*fsw`fLR;0Gs1aAFBbh|w@& za#U4`G98aWBgvJ+BZ+m0z`sLVas}kTB@BD^Aa`RNd{+zZ-*bbID+k&zt6c6%C0BR~ z(29oJ_uStPWO6a=i-FbfRTdtP+f^$+janb{;ESH?(=3or^*&A}DAdZ~s_V`2E0d{xZ}Rii6R*PnG7QBB`%V(8ttk~FWecs!IwyU&Qq`13&=%m(qST45h*xE`Ha zXnghszT?Ql^*IsRVk2=U;GxDs_Vhd+dYCx?hEW1el4~HrtFgpKg5xt09>J*$d90oj z;^AXkd3a~%9iX0;E2Cy4?ea!GmgS_#mKM;36++d;Y$+;d@=!M6syftNxnLGw!jqix z4bVo}b_JvC2hU`1Lqj<<@Q%tTqxDKsqvS)-V@kdXZ~#B$Az1R!Ig)P%cC*`a^x8Rk zl1#pdjnKW%*KY`j~UaLl^l)2QxhczRJa=&7nB^$aNZCd+o+MrC1%Gy_7_=zKoLxm0OSV* z{Yyp@D?n-yy>vm(*dl79F_fNz4TmAs@U<1oLNZ-2Vi~mnxjn2Qb_YZR;CG-MOAj33 zqz+D!{5fHW=mm&QYH3zAS%B0f1+@V26YFpR!nvviNITJ)JIPupKr&dCgbR>*(1;ve z(65hX^aXx!(f}uxkc1cwV~=U5szfP3QlOF4R4qUnp)EOxj7UejQGnzK?v2U7oGP?d zHsM}EO~X}*$d4%Xh>w)h!mh#-aqj${FJILjz6;};%k;6r6h@^WX>X8nn#gjr4S&y`VQK&Pm6`_0SsQDgd zacGNn(!a!ahIcy)3P+=*$Tit0b>%x}Y&6 zI&fdO%wTpjFpE*Fn*(H$ZwFDLW}OC^c}y%7|5yhGiiwZ_uAnIVSLETD_r#&e~C@adLB}{=OjaC~_z- zoI|aX(P-kH=zB~gRUbm{l@scNt}m&;Rb&Fo55gO3P(Eq*&I#rJPuh<{JJgFZD%6{f z9$$YJvBx6XYclq9xI}kg!eQj~T1N zp8*go!RQ<@e;Rkb9?#JWWP%OkdWBpRaWNPoR3H+F-F!(Mj+j4gZt)eP4`^lHheR59 zd?Q$RhT;MX1`k9bs*aJc;}@SGE3;FNZxpk7QdqgeR-<9XFFq|Uig>|gGF^mQ^!FKD z#Fh+hI2nc$h+-~AK*&zhYrAB$O<>;rGt$vxy==|a+wgh+)%Dk--LDN!g%{NJB* z&U5BDGxJD0zt`*E_iN5`&iP#4pU?T6b3V^`o|&aOhU+S9c4GtjXt@^6=5%vVgvQF@ z(0tRGA#>4e!ZseTdB=QoBuxl}Sz5|dodwi2(cFc527V^KkhF}(ipF0u<7cS!m@+hh zRJ(mML=Y?@8S2diqhL|Rzf{4+sCO4HG0?AoIRZ5AcoiM+!Ha>I7#K+ZRG2s!vHBv9 z)msU<7mcA82_eVHQE0v?Oxdpn#*4LAmjZHIoS@j?W9=W?+sgnP!U&2ZuC zAjAR&M`3i|RJqKmnY$uXBc|=4iDbvc*Wj8G__rVd#S#?EDjtIvXEZJ)RTP6%tw<98 z4i~-*1&cwd!~eArgR=wrOc{gAIbDbsD^P@Hn?i8`L$eaircs>(=kbnJ=t!Cy2(yGk z@qOx=XYP`rxSF)gj1`J=c_=PqT0e-^$~)Go{ASlP0kK>^kGZ~jE#dohgig7=;&{UM zz#j_jVjF|a7?$;DWWz$$iVVv}2!NcAP_SX4I)-H^(v(*N`XV_jA9K1-d9eva=vC9O zEMaIiquDepi!m&`V+%TxUJry>!o%_zb-iKklEbowm;iNL=*%?q1_{1|o>bebveOGb31AAmv>o!8x2akYZ+{5^kh22?^ETDt?O)*S zcLMs`(%WBgx}CiE21V!{lebqgG`rAj^7gy%Ht+Zj9Z4$!VV1DBcT-o$+$FuehqSC9 zEupt#Oa+hcJ*IVUv{v4+kN86pWnJGYM!%n$BL#9je35-0xH;+fAZ2d(!J3CHOn5TJ z_mCe|Li5C9mZ$?vcWCE0#Ea#`I{*<_LxBPVa}X7E7INg_S$GH(3Ek|ht`mfeIH_9Qoh!_nhhF|;%m)m=!Lvr ziJZ5S?cwt-o@x5m!}XlZSWa#SITBeILk}H;UNoAFsptDaNT^MscSITEh!Kf~F+VX(b--v^F3A|)aUD8f3=nvs zgc)-^H95UN4P)w}f^~sEtIMEgb!_<9GcfK|taMljI4E|FzX?UJ|3C-$T_lV`jj9z1 zwVNOSa=a*5s8JnGychZEv4H+-K>sD6AC{qZGpDZ4iw3;7g%^!@(U=!0ytoxb(&0ep zFs(5x-C#fGa~n@Rj9-f>Yf5Ct1EF8w`>6Y*Ut=^@V-KgfSmOt2%6yO#B_ed3R9{Ww z4m;C`BvPPCl1U`TD3sIx2r!>yp~YJ}NPf!3CERm@O%3t&zP~WIeR{pHE-#REh6M7XA8r=0P1RH-;X-tn z$nh-cAH!sr<2}m;I)|*gju{%DOGog0W6o^6KtnH5=q}LEFp~+nwV^S|VW=%A#unyy z?aaC$S$93VY)6-s{?*VbiUHOjRJsc^G|Y5ChQ=g^p-#h4nBz@g*0m?=>axoYba~Og z8d~`R4OQtb(9kf`1sNKX9EMgl423z~D$KfEvd+aWJJMyJqy1sbZ-U7(?1rVBDO zCOHhf*f134crRhr-A>lI*<~lXtp2ZtCS0JQD%}Md8fLm6Lt~P|&_u&fnB%R+tm{nH zY3#BKU0(LDhK9eS#EuJMZaw4+mF@x!4KrPkp)tu}=%t3CFvnYiS$79n=V6y!>GFzy zHPrN7D9b&T3{~ka(9kf`1sNKX9ER33423z~%b9g|l6Cdit78ueO>FkhN^TI zXlR(}f((sG4nwar423z~tC)3nlXW++%X{eZ+J7|^Z_wZn?cWmymF@x!4KrPkp)tu} z=+%ayFvoihv+iD4hc^OFvh0C!(4;>C^sRg3o$St{Ih;Tjj^-G4x^Ol}pwmS{b4+cz zsMH*b8C_Ivj^&#!sx-%jMHd$}#}-W&7dJ;zLKl}bM;b<7jw8ihuJ%5{Kz9?rSMYA4 z2LwQ5cN8phraDsH{y5;dF{md6jrVDLa=Kn9LP zf0BQr;YYkw+>|vxM9nu-Grwgd0la4bX{{d&^El+AtP*0XZ^-JX`Fu=PDVig&@Q#6! zo~!ckf{O^hngHDZ`Y?!DfKjy~x2umq0OUN1f(01W5n#6>z|v%NJ&wjuT2Q@}WZ;>H z!T*Fx5k4{G!2*gWLBWuwR}kql5CAz(qhLs>4y5&fv_(*FCc&1WJ=6?fV}Ez5uBngi z-7LTC6lxKq^Od@F#05W~FteK;o-=3Ety7!FMN2j|g8+nCOx22v%}@w{#Y32(xS%>L zPKL!9(%fg!7|O6R*H)J!%3_FyftDenYDEwYhX4R6XFza4bs)M4h_WT35opA)@FSRP z@m(zY9pubVHUr8Jn?;3o7m640PRF%%IO5g}@$-0Gi=^*ZHPBU!mlmx2O0h`5XMFd z{Ou(831|$pvy6dyroQurJb!#84CufNm;n?Tu>bb?1url(ts&w z4CP7#OyR&LmWzkP?F`XW&@x0+tq7u*AOJw7Ga$I2IuNbF3Ef>my=zeK64X0MXfx59 z^lob&%|SX)ybCxt(zl#8YN4*U-aywIjBA!GVO`lut)sP27iJZ|?u2XO`%&DadzeYH zpo5u2)ry!j2LfQp%ghp7P#q?n!B3m#1@-%a`n}Sgx#$Yr%YYD6etZ?WkD)Xg!ast+ zf3$I)$|GJZ2=ka0LSsXiud;}5Mu%CbA>up!3se@qhnSF=qQcO!P-PL{feu?2{^mW! z5xx=~20&c`0QH@%nn;BsF_cGJwfvU#tI)uPrh5g4=5+|bh%83Iwk@h-Xexz&y6_E7 z@fM1tUcsd87yg@&+cf@idtF~&%HpAB2?_a6KlfHP8fh6FkCXY~-}qY!LGsP{ZTNwu zo-9(|Ml;UZp$^L4K_%1+k+V(1i`!wMV8cEbz(7_9fu;eQaR8LzHF^hk(`Voe*04dvY(%XjCCMkSO!!O%LWL5ob?O>E~pMHCxK;PP%n{K zK0k;PTjUZ;Is9KRB-V6Z%^C<&^3#tQEO$_lfLH((q{-^}D z1zkylgP}*+SmTxDZR~3|pP@N4Sd2d{WW$D>WOEn~srlD%x2hBuVO8Fvg`NS+5c*NZ zA?z!4pQ}VQK(tp2Jryh;x&uG^hYxznu? zLIus;0|791HwtDh)nRU3m^(@ux)+V1QPLug7e5LJjKjze#pgm)Te3uYXtroSaYWZNi&IL-x~>f(Wt1I zF4P<)j8lRvUBY+ec%pHPKurPaIf-;kO8F?BZ_i{N{0)76aC>?6cU18p82Y?uWY5Bm z6L+M|T)B}joFFdzMlF+gG8R4gh_y`1V#P+?R~k$l?vCM(12 zw7>7GYqQ&{+3og~K3mCyHrzrv6E3pZZDkkLu-U3PDm(4#CCOT!t)SPVHvHI-Ga&&q zrFQ!VR$QM-u8lrh&*FalyAQ~>l_wa|uQjA^6?9D14peLm&9(@+wGH}jB*|A+B>SZ5 z-2kk>{nm=-C&_cbXX{@&z~qSjm4V6rgB9oRlJjV6&LdWwrzPi~u{lp#aoW<1QTxY= zq_QM&rl|ufU0EF@+}l;tY`q8M=l331)YCLZsqneoez6t%)l$QiX;E=;d0I>_US=gs zlfvr8=DaRiM{O%%H%nnR#uk=j#hD^G8^-2rV8xjRPVUSmRwON?@bm~0IoGlzNlPn| z_L3xUo>6O?hDq1|v4|0E!$!2VmFPRA=q|(_YtGv3og%npI6WY_`$UkmHzw~xlB6hl zI18<~9+6z7v0!yDq(3R>*iteG6+RwMN65`J=!Z#?AyyO23X>87qqjh{_CG0CH?2FjKwpnrRk(}Sg=KRKr^G9%UXYRKm zIV^=Aj3AM7?WiRA#fs!FN%F^eM(sq*rQ~)tqQ6^-cKVGS%I1%;l+c{D+s{UD%b8hA za$n(BH?J;WWb^xaNmAP%wfkIS#Z^yoxnse)+mP-RbWBwPRQPz@93l4}gFZ!)G_)e| zOVv#QSXoMLwc^Q?Jh%BH_ERUzN}5}71|?_P*qp7cI6F(ujK#sR&&;Fe>H+z&dlf1jfH4vy1JC)8IyOEBzZnPYAG3R#Wg{4jZKfS!rgC3pCahk zQt}cid_1N_$n9>>&yggvtVmvwsuuvTvXsoT;#nej-bjzRlq|O5Tq!x1bv+^PCk)6_D`5goI`mb1hMlTx>;h zl_a^mnf0h$)-2Xi(vyworB&!Vz9fQM z&de(^jHTqV3|r6MMW$1?Axv+z3|n8Nc^I16ysr&b?!2orY=wPI2bJXpi6*7j&9L<{ zQA}X6ue0L2N%AGDd}WO91}nbClJAySe7Y5%Px9SrMbcc7_^n8?LBbu9kzp$ySZcDD zFGsgUaLzIO6qKB8V{^8);_M_jb7OP1x8l508q_6%L=NBor0{#;&O#f0@P(hZYj*qH zR!qGmQ%^7zcP}h7#nfUpe)n7PJ|Z!dMn>Zj#@RnI8kZR^d|Ik~B0~CdgXCE$eXtrG ztC;LEE54DEZ-mPC2IDKY;+rV>#>L_rW5qX3@=dlPnI%bPSdlCM36I9Pu_NQ<2+q}p zpI(=oug2zFWW~8maxRI@`KA@;3Te>t2ogDbYoze^;Z8Lg-?L)+STbz@Q$#ebW#hNb ziuWgp=|E&OZe*PMBct(C!-dDB+9MItHyb2>O6e!m=-AF=|8B*1PV${m`PMVO(^h;{ zGL4l!AyZk4IiDj_UBe~LYLf2~E0UU$6R2Jydm7FMq>jjrgX{V15-pa?qcJ2s}=87iD`4Dn)L5B zT=kVC`64qa>EC9>^_}GUCNoCTf54EwU(m75{~#)SJb#Fgd(fc&MUwnvMRHuKJ_f)_ z(*LU!&)<^gRAxldzn6LN4=c`uEMo@Pvtn|dv*JvYoEOLDtdgY;iF86u$$6<2$<>nN zN-GiC z6y2NHBhL?L&f4w0BDiHxJ|nrG1h9`NpYyzcIcsR(vxg-_%%qldbsXNWNKCBnu_UJS&nnK*AmJT2{=B z?Ue{lJ6@4yu6##wE{)CkmKEnJ$+;pn=et&%Yo$S}BS_@%eJq7naWFq#AK4Gs5n;BZqH-LKax>0jmwH_X^*1lOpa^MMyu~&unlydI^qvUOIb= zdLJp_f3YOk9obDKxAP#iFU=D9tG zo+#&waseyJ7ejMwj}#B+rN;PRgq11AjqrFr$CgRW!s14V8oOh-aHeSV(9>AQ3+fo! z9pyQ;3==C+Rdb5}B~+_quQUx}QcPiMuQU}cjg^)uXlbOhOh!vXQ%ki3IQ2C#TyJnE zINucITdX9bUx{V(Le*#<(A6+Hi=iYEJL!3w51wNsm+yE_l&hqkC4y7DNND(RS&l7c z37?`x8Bm&0yWkhT#qCt_ z6I8qXEAW`2)xiI4j;(iL_dX?g#f81{y3-mim&kn>fPVe+it_s?&3kxrX>ot0c{gun z$A?Ok?-d>Wy0ce7rTFj6ntPaJ!ImGGEl$S)86^8-!3X6}BD@ZZQT|z!zevu5Dkl#w zaQ+5PTCYw@%A*K)nkHg9vD=TRtlVc{J;RkcD+dy74u{iOB~X|K@114_Ue%R-$<w;V1=@r2Ku-+V9#9%4L?NV6oWqeh76=3jrRLd@nrFt= zJTFqwTvZX2EEY@EK-#itL__-N?wmr@~%*_QYd*(l&eJfzEt{7q|&!l zrG`&K6i4QaWJLfQbhv>n^y{FO?!7*Qc-qd_OEqf*yWBEY$5I3LY~skBTg6QJT+F0x zB09En3lhGNqCbhWV51uHEa|szQ1wwG-4tzBU1xV}0UdHPT1?q}tljY$#9_ISEn>=l z$AKp76=A$jgzSAt^hkkFva=KfUPHv6-+H( z#jiNrf9!hv|l0GuN3W9iS}Be{c6#EjcC7CwAT(^ zL3g~)Ize^^>%2~s*Nd{QC|#m-i&7J%N0jwMc>^nH4L^qQioWIjRSf~2oc^MQ0B<~u z@F_0pRZv<`jO!8Gc5`GuS)Ig@(9JH0>_cTtwyVOw_R+BInFS6pO%Pop(!?-DH#UpETc%wNWn zzU>Yz-1~V!e#dJXO1u3&jF?F=Pw(yx+Ir=em=#NLJt2;Eo4z7kC>VM{wQ|_ii57gi z8F`SI=yddx!BqfL%?cSQeS30%#MwVc3AJhcEmAQ`ERQhh6tV*&SxQtE88U;UmS+e^ zUiSfgOxE-73Ot1#ycW`>2yRl`lXe=;-4nJ_KLPba4b z*VJf#zJ$Dg1Xrk>Bb~1oJ zSUcd#D-R!OKj_GZzqbsHxwVn=f%!%FGOsPm-|dc)`~fB19?c(6{AjoA{E`PDsaw~A zl7Za|@5t|6pySxQG=D(1R@p&4C#Tz^O;Wpc$}i0CUXtIfxW@zCa{K2Om6Q~=E9ham zY|y_~58Lm*U2Us!W#V)0=iS5I-+10}uW-NXKH^#D-r?Tl-s;}s-r+grKI1;^-sE{! zE7#U*TeQ!$@3gWRK;^7?xyw^Ja7f~;#5sw_5>F(aOe}K^b&YV1cg=9ka?NqgcP(_i z;(Fcnrfa!th3h@nTGxlJk6i~{f4cs0JqLZyyGOgnxnFcocF%Cna?f)wa=!!ZE8Od# zdkeJhaPM&+b)SOvGwx@#VbK4AHc}g{jnT$xZH0x~v>n>luyc>LSKFt3uN~EnYkz2eX=k)So?)Kho>880o{65xo|irI zJPSOpc;4_V@x1K`c|P!L^nC33#Iwn>&9lSvmFFAJLC;T~!=59a6P}ZvQ=V(e=&#r> zgHPUZErVCyalMPr5I$Gnb0zcAO4lm*>V15!#^(q4T!YWG_*}<4xX!g6e%yf1kMOw> zpC9A%6MTM(&rSH;jL$8usjkm(wbk{u>vPa;L(6uwe1Vo7X!#N?U!mn|wCqI7H)z=f zT;D?9cj(!To;~Q7iA8C1W3>IkTQ1=Ued z9Rt;Gp!ywD$3b-hR3}082dMr8)hST@1*+4a`r9?ubq19GfbuLT&w;Yc{fBFi`%l+k z_bJy9_g}7|?$fSk-G94=xz8Ym{&AJN&$@=Y&$&jp%Mee4+%LGxTqE&slzT9uYlwS{ zd#HP?`&q=67Pwz`EdSqSHblfxE6!!b@z*|H{6q4Z@MSD-f~ZI zEpbnEErq1FA!!*Ty#q--pE2koW;4u7Sk0khsqM zhWkVJo9^}Qx7-`tOWYs1m%2AX;>VEq2_$|BiJKsCGbC<-#LpmcDDAMehSk6 zg7njn{x_tbf%Jde!(3 zQ&Wa(%aTUm-}BnElozz=DI>KRDWkLr$)mN2$z!yaZyu{n_Kee}c*bi}k|$^%rcBh< zr@V-jWRmvXjgz&ZsZ+GMDO0t1Dbuv&DbuxgQ)XzPl$W&Uu%eV>O&N|=<$bIx6K|fQ zjmPRT8SBdwZN4@$d4V=7d7(Btd66~$OcO8??z$c5Qs>7utl>9oodyFSQp_ztSe9eyvST z-KkAU{YIObx=Z^j>051D>UY}o)ZN(#9m8#wz`{HYfFrHaGPjZCLVI?YZQ0T6uDr zXI|^ODD0Q6YmDKT`amf=rucl7)yq5Z+XMFM`PZ`$mL7pj| z3CUAEKP64`OiZ5c`5|eB=U~!Ho)?p6dcIAX<(ZT`+w)7x%bp`Cb3DhB=AwO`XL0I$ z&*bC21KkhH_?<>!buCF~aT|3eCjpwX; z7yfl&^vri1@GNj0^lWz@ z@+@@yTb=Psv4)+PqRM$z* z+pa%6Z@B*Syy-gS`OWp0=Zx#LXNl`?&r;VJ^j&Mas%+NfHru5w>9v~%1-+I(lwd!1 z4jG57W$*m%r41T39AmSU@s?*ze>Da) zPZ6o|AEW70$l569a@u>=RtQjGGzCSh89(<5n);C>oF@NK)?SIx^xY6i#N?Db#+oZL znknfqX^^4Oe>neuu4^x571IY{xa5|U#tj=camoK0-I|uxv}x+CK2sZYHfq?gNfWd+ zy|rnRhK&0DOKi4t=j^s#!ycb`PoD4W(!_Z?Uv2-|v@hS$k~**5nrydSo>;|3eXk|i zZFob7{bzPKHITdON4oQp8r%`W=|o2^eW%Q9rz}?SkkS1XIwT)ZP2)BgT`r%8a3?JqoAl;+v1YayL?Spn%}c= zgIk8htAv{jct0Xwzz7aZPVL4X46|2l;-w$pf&xvjJVFm z%Rsm;{y)5n5fE{21Hrxi4+V$sl-TW&-lim_anmL~nAfpaLH9oG2bLnT8k+xWl$B+> zto3z&Uzut@5X2xfM(AE%yKMPGwzdf5tGiaiI(79;v|3$VRtZ0~gz{$gS)aFE#M)}U z;=5ogj1em+>RC9j7w+)H2$pp3jROzd@i*vet6^V0`l0dlUwF6ozFPmhcJfAdYR#

        PN*W_&%N{3f$< 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

        *H49HfcC845T>9LpZ7#MlYlMGnVFvbJM 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 z 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%0D;}Sz5x>ybO#UsgAJIWpa*~e7-B%wgHAbh({tK) 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 z⪻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

        H+kROodacFqq)}zE38+H=o83JTS}(l8@)d! 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 literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.c new file mode 100644 index 0000000..4f46eca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.c @@ -0,0 +1,1243 @@ +/** @file + Provides interface to shell console logger. + + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett-Packard Development Company, L.P.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "Shell.h" + +/** + Install our intermediate ConOut into the system table to + keep a log of all the info that is displayed to the user. + + @param[in] ScreensToSave Sets how many screen-worths of data to save. + @param[out] ConsoleInfo The object to pass into later functions. + + @retval EFI_SUCCESS The operation was successful. + @return other The operation failed. + + @sa ConsoleLoggerResetBuffers + @sa InstallProtocolInterface +**/ +EFI_STATUS +ConsoleLoggerInstall( + IN CONST UINTN ScreensToSave, + OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo + ) +{ + EFI_STATUS Status; + ASSERT(ConsoleInfo != NULL); + + (*ConsoleInfo) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA)); + if ((*ConsoleInfo) == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + (*ConsoleInfo)->Signature = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE; + (*ConsoleInfo)->OldConOut = gST->ConOut; + (*ConsoleInfo)->OldConHandle = gST->ConsoleOutHandle; + (*ConsoleInfo)->Buffer = NULL; + (*ConsoleInfo)->BufferSize = 0; + (*ConsoleInfo)->OriginalStartRow = 0; + (*ConsoleInfo)->CurrentStartRow = 0; + (*ConsoleInfo)->RowsPerScreen = 0; + (*ConsoleInfo)->ColsPerScreen = 0; + (*ConsoleInfo)->Attributes = NULL; + (*ConsoleInfo)->AttribSize = 0; + (*ConsoleInfo)->ScreenCount = ScreensToSave; + (*ConsoleInfo)->HistoryMode.MaxMode = 1; + (*ConsoleInfo)->HistoryMode.Mode = 0; + (*ConsoleInfo)->HistoryMode.Attribute = 0; + (*ConsoleInfo)->HistoryMode.CursorColumn = 0; + (*ConsoleInfo)->HistoryMode.CursorRow = 0; + (*ConsoleInfo)->HistoryMode.CursorVisible = FALSE; + (*ConsoleInfo)->OurConOut.Reset = ConsoleLoggerReset; + (*ConsoleInfo)->OurConOut.OutputString = ConsoleLoggerOutputString; + (*ConsoleInfo)->OurConOut.TestString = ConsoleLoggerTestString; + (*ConsoleInfo)->OurConOut.QueryMode = ConsoleLoggerQueryMode; + (*ConsoleInfo)->OurConOut.SetMode = ConsoleLoggerSetMode; + (*ConsoleInfo)->OurConOut.SetAttribute = ConsoleLoggerSetAttribute; + (*ConsoleInfo)->OurConOut.ClearScreen = ConsoleLoggerClearScreen; + (*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition; + (*ConsoleInfo)->OurConOut.EnableCursor = ConsoleLoggerEnableCursor; + (*ConsoleInfo)->OurConOut.Mode = gST->ConOut->Mode; + (*ConsoleInfo)->Enabled = TRUE; + + Status = ConsoleLoggerResetBuffers(*ConsoleInfo); + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL((*ConsoleInfo)); + *ConsoleInfo = NULL; + return (Status); + } + + Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut)); + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL((*ConsoleInfo)->Buffer); + SHELL_FREE_NON_NULL((*ConsoleInfo)->Attributes); + SHELL_FREE_NON_NULL((*ConsoleInfo)); + *ConsoleInfo = NULL; + return (Status); + } + + gST->ConsoleOutHandle = gImageHandle; + gST->ConOut = &(*ConsoleInfo)->OurConOut; + + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *)&gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + return (Status); +} + +/** + Return the system to the state it was before InstallConsoleLogger + was installed. + + @param[in] ConsoleInfo The object from the install function. + + @retval EFI_SUCCESS The operation was successful + @return other The operation failed. This was from UninstallProtocolInterface. +**/ +EFI_STATUS +ConsoleLoggerUninstall( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + ASSERT(ConsoleInfo != NULL); + ASSERT(ConsoleInfo->OldConOut != NULL); + + if (ConsoleInfo->Buffer != NULL) { + FreePool(ConsoleInfo->Buffer); + DEBUG_CODE(ConsoleInfo->Buffer = NULL;); + DEBUG_CODE(ConsoleInfo->BufferSize = 0;); + } + if (ConsoleInfo->Attributes != NULL) { + FreePool(ConsoleInfo->Attributes); + DEBUG_CODE(ConsoleInfo->Attributes = NULL;); + DEBUG_CODE(ConsoleInfo->AttribSize = 0;); + } + + gST->ConsoleOutHandle = ConsoleInfo->OldConHandle; + gST->ConOut = ConsoleInfo->OldConOut; + + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *)&gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + + return (gBS->UninstallProtocolInterface(gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID*)&ConsoleInfo->OurConOut)); +} + +/** + Displays previously logged output back to the screen. + + This will scroll the screen forwards and backwards through the log of previous + output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows + is (UINTN)(-1) then the size of the screen will be scrolled. + + @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer). + If FALSE then the log will be displayed backwards (scroll to older). + @param[in] Rows Determines how many rows the log should scroll. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. +**/ +EFI_STATUS +ConsoleLoggerDisplayHistory( + IN CONST BOOLEAN Forward, + IN CONST UINTN Rows, + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + UINTN RowChange; + + ASSERT(ConsoleInfo != NULL); + + // + // Calculate the row number change + // + switch (Rows) { + case ((UINTN)(-1)): + RowChange = ConsoleInfo->RowsPerScreen; + break; + case (0): + RowChange = ConsoleInfo->RowsPerScreen / 2; + break; + default: + RowChange = Rows; + break; + } + + // + // Do the math for direction + // + if (Forward) { + if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) { + RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow; + } + } else { + if (ConsoleInfo->CurrentStartRow < RowChange) { + RowChange = ConsoleInfo->CurrentStartRow; + } + } + + // + // If we are already at one end or the other + // + if (RowChange == 0) { + return (EFI_SUCCESS); + } + + // + // Clear the screen + // + ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut); + + // + // Set the new start row + // + if (Forward) { + ConsoleInfo->CurrentStartRow += RowChange; + } else { + ConsoleInfo->CurrentStartRow -= RowChange; + } + + // + // Change the screen + // + return (UpdateDisplayFromHistory(ConsoleInfo)); +} + +/** + Function to return to normal output whent he scrolling is complete. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + @retval EFI_SUCCESS The operation was successful. + @return other The operation failed. See UpdateDisplayFromHistory. + + @sa UpdateDisplayFromHistory +**/ +EFI_STATUS +ConsoleLoggerStopHistory( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + ASSERT(ConsoleInfo != NULL); + if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) { + return (EFI_SUCCESS); + } + + // + // Clear the screen + // + ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut); + + ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow; + return (UpdateDisplayFromHistory(ConsoleInfo)); +} + +/** + Updates the hidden ConOut to be displaying the correct stuff. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + @retval EFI_SUCCESS The operation was successful. + @return other The operation failed. +**/ +EFI_STATUS +UpdateDisplayFromHistory( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + EFI_STATUS Status; + EFI_STATUS RetVal; + CHAR16 *Screen; + INT32 *Attributes; + UINTN CurrentRow; + CHAR16 TempCharHolder; + UINTN Column; + INT32 CurrentAttrib; + UINTN CurrentColumn; + CHAR16 *StringSegment; + CHAR16 *StringSegmentEnd; + CHAR16 StringSegmentEndChar; + INT32 OrigAttribute; + + ASSERT(ConsoleInfo != NULL); + TempCharHolder = CHAR_NULL; + RetVal = EFI_SUCCESS; + OrigAttribute = ConsoleInfo->OldConOut->Mode->Attribute; + + // + // Disable cursor visibility and move it to the top left corner + // + ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, FALSE); + ConsoleInfo->OldConOut->SetCursorPosition (ConsoleInfo->OldConOut, 0, 0); + + Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow]; + Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow]; + for ( CurrentRow = 0 + ; CurrentRow < ConsoleInfo->RowsPerScreen + ; CurrentRow++ + , Screen += (ConsoleInfo->ColsPerScreen + 2) + , Attributes += ConsoleInfo->ColsPerScreen + ){ + // + // dont use the last char - prevents screen scroll + // + if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)){ + TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1]; + Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL; + } + + for ( Column = 0 + ; Column < ConsoleInfo->ColsPerScreen + ; Column++ + ){ + if (Screen[Column] != CHAR_NULL) { + CurrentAttrib = Attributes[Column]; + CurrentColumn = Column; + StringSegment = &Screen[Column]; + + // + // Find the first char with a different arrribute and make that temporarily NULL + // so we can do fewer printout statements. (later) restore that one and we will + // start at that collumn on the next loop. + // + StringSegmentEndChar = CHAR_NULL; + for ( StringSegmentEnd = StringSegment + ; *StringSegmentEnd != CHAR_NULL + ; StringSegmentEnd++ + , Column++ + ){ + if (Attributes[Column] != CurrentAttrib) { + StringSegmentEndChar = *StringSegmentEnd; + *StringSegmentEnd = CHAR_NULL; + break; + } + } // StringSegmentEnd loop + + // + // Now write out as much as had the same Attributes + // + + ConsoleInfo->OldConOut->SetAttribute(ConsoleInfo->OldConOut, CurrentAttrib); + ConsoleInfo->OldConOut->SetCursorPosition(ConsoleInfo->OldConOut, CurrentColumn, CurrentRow); + Status = ConsoleInfo->OldConOut->OutputString(ConsoleInfo->OldConOut, StringSegment); + + if (EFI_ERROR(Status)) { + ASSERT(FALSE); + RetVal = Status; + } + + // + // If we found a change in attribute put the character back and decrement the column + // so when it increments it will point at that character and we will start printing + // a segment with that new attribute + // + if (StringSegmentEndChar != CHAR_NULL) { + *StringSegmentEnd = StringSegmentEndChar; + StringSegmentEndChar = CHAR_NULL; + Column--; + } + } + } // column for loop + + // + // If we removed the last char and this was the last row put it back + // + if (TempCharHolder != CHAR_NULL) { + Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder; + TempCharHolder = CHAR_NULL; + } + } // row for loop + + // + // If we are setting the screen back to original turn on the cursor and make it visible + // and set the attributes back to what they were + // + if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) { + ConsoleInfo->OldConOut->SetAttribute ( + ConsoleInfo->OldConOut, + ConsoleInfo->HistoryMode.Attribute + ); + ConsoleInfo->OldConOut->SetCursorPosition ( + ConsoleInfo->OldConOut, + ConsoleInfo->HistoryMode.CursorColumn, + ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow + ); + + Status = ConsoleInfo->OldConOut->EnableCursor ( + ConsoleInfo->OldConOut, + ConsoleInfo->HistoryMode.CursorVisible + ); + if (EFI_ERROR (Status)) { + RetVal = Status; + } + } else { + ConsoleInfo->OldConOut->SetAttribute ( + ConsoleInfo->OldConOut, + OrigAttribute + ); + } + + return (RetVal); +} + +/** + Reset the text output device hardware and optionaly run diagnostics + + @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + @param ExtendedVerification Indicates that a more extensive test may be performed + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and + could not be reset. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification); + + // + // Check that the buffers are still correct for logging + // + if (!EFI_ERROR (Status)) { + ConsoleLoggerResetBuffers(ConsoleInfo); + if (ExtendedVerification) { + ConsoleInfo->OriginalStartRow = 0; + ConsoleInfo->CurrentStartRow = 0; + } + } + + return Status; +} + +/** + Appends a string to the history buffer. If the buffer is full then the oldest + information in the buffer will be dropped. Information is added in a line by + line manner such that an empty line takes up just as much space as a full line. + + @param[in] String String pointer to add. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. +**/ +EFI_STATUS +AppendStringToHistory( + IN CONST CHAR16 *String, + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + CONST CHAR16 *Walker; + UINTN CopySize; + UINTN PrintIndex; + UINTN Index; + + ASSERT(ConsoleInfo != NULL); + + for ( Walker = String + ; Walker != NULL && *Walker != CHAR_NULL + ; Walker++ + ){ + switch (*Walker) { + case (CHAR_BACKSPACE): + if (ConsoleInfo->HistoryMode.CursorColumn > 0) { + ConsoleInfo->HistoryMode.CursorColumn--; + } + break; + case (CHAR_LINEFEED): + if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) { + // + // Should never be bigger + // + ASSERT(ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)); + + // + // scroll history attributes 'up' 1 row and set the last row to default attribute + // + CopySize = ConsoleInfo->ColsPerScreen + * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1) + * sizeof(ConsoleInfo->Attributes[0]); + ASSERT(CopySize < ConsoleInfo->AttribSize); + CopyMem( + ConsoleInfo->Attributes, + ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen, + CopySize + ); + + for ( Index = 0 + ; Index < ConsoleInfo->ColsPerScreen + ; Index++ + ){ + *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute; + } + + // + // scroll history buffer 'up' 1 row and set the last row to spaces (L' ') + // + CopySize = (ConsoleInfo->ColsPerScreen + 2) + * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1) + * sizeof(ConsoleInfo->Buffer[0]); + ASSERT(CopySize < ConsoleInfo->BufferSize); + CopyMem( + ConsoleInfo->Buffer, + ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2), + CopySize + ); + + // + // Set that last row of chars to spaces + // + SetMem16(((UINT8*)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof(CHAR16), L' '); + } else { + // + // we are not on the last row + // + + // + // We should not be scrolling history + // + ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow); + // + // are we at the end of a row? + // + if (ConsoleInfo->HistoryMode.CursorRow == (INT32) (ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) { + ConsoleInfo->OriginalStartRow++; + ConsoleInfo->CurrentStartRow++; + } + ConsoleInfo->HistoryMode.CursorRow++; + } + break; + case (CHAR_CARRIAGE_RETURN): + // + // Move the cursor to the beginning of the current row. + // + ConsoleInfo->HistoryMode.CursorColumn = 0; + break; + default: + // + // Acrtually print characters into the history buffer + // + + PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn; + + for ( // no initializer needed + ; ConsoleInfo->HistoryMode.CursorColumn < (INT32) ConsoleInfo->ColsPerScreen + ; ConsoleInfo->HistoryMode.CursorColumn++ + , PrintIndex++ + , Walker++ + ){ + if (*Walker == CHAR_NULL + ||*Walker == CHAR_BACKSPACE + ||*Walker == CHAR_LINEFEED + ||*Walker == CHAR_CARRIAGE_RETURN + ){ + Walker--; + break; + } + // + // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row. + // + + ASSERT(PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize); + ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker; + ASSERT(PrintIndex < ConsoleInfo->AttribSize); + ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute; + } // for loop + + // + // Add the carriage return and line feed at the end of the lines + // + if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) { + AppendStringToHistory(L"\r\n", ConsoleInfo); + Walker--; + } + + break; + } // switch for character + } // for loop + + return (EFI_SUCCESS); +} + +/** + Worker function to handle printing the output to the screen + and the history buffer + + @param[in] String The string to output + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + @retval EFI_SUCCESS The string was printed + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. +**/ +EFI_STATUS +ConsoleLoggerOutputStringSplit( + IN CONST CHAR16 *String, + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + EFI_STATUS Status; + + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16*)String); + + if (EFI_ERROR(Status)) { + return (Status); + } + + return (AppendStringToHistory(String, ConsoleInfo)); +} + +/** + Function to handle page break mode. + + This function will prompt for continue or break. + + @retval EFI_SUCCESS Continue was choosen + @return other Break was choosen +**/ +EFI_STATUS +ConsoleLoggerDoPageBreak( + VOID + ) +{ + SHELL_PROMPT_RESPONSE *Resp; + EFI_STATUS Status; + + Resp = NULL; + ASSERT(ShellInfoObject.PageBreakEnabled); + ShellInfoObject.PageBreakEnabled = FALSE; + Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN(STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID**)&Resp); + ShellInfoObject.PageBreakEnabled = TRUE; + ASSERT(Resp != NULL); + if (Resp == NULL) { + return (EFI_NOT_FOUND); + } + if (EFI_ERROR(Status)) { + if (Resp != NULL) { + FreePool(Resp); + } + return (Status); + } + if (*Resp == ShellPromptResponseContinue) { + FreePool(Resp); + ShellInfoObject.ConsoleInfo->RowCounter = 0; +// ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0; +// ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0; + + return (EFI_SUCCESS); + } else if (*Resp == ShellPromptResponseQuit) { + FreePool(Resp); + ShellInfoObject.ConsoleInfo->Enabled = FALSE; + // + // When user wants to quit, the shell should stop running the command. + // + gBS->SignalEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak); + return (EFI_DEVICE_ERROR); + } else { + ASSERT(FALSE); + } + return (EFI_SUCCESS); +} +/** + Worker function to handle printing the output with page breaks. + + @param[in] String The string to output + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + @retval EFI_SUCCESS The string was printed + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. +**/ +EFI_STATUS +ConsoleLoggerPrintWithPageBreak( + IN CONST CHAR16 *String, + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + CONST CHAR16 *Walker; + CONST CHAR16 *LineStart; + CHAR16 *StringCopy; + CHAR16 TempChar; + + StringCopy = NULL; + StringCopy = StrnCatGrow(&StringCopy, NULL, String, 0); + if (StringCopy == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + for ( Walker = StringCopy + , LineStart = StringCopy + ; Walker != NULL && *Walker != CHAR_NULL + ; Walker++ + ){ + switch (*Walker) { + case (CHAR_BACKSPACE): + if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) { + ConsoleInfo->OurConOut.Mode->CursorColumn--; + } + break; + case (CHAR_LINEFEED): + // + // add a temp NULL terminator + // + TempChar = *(Walker + 1); + *((CHAR16*)(Walker+1)) = CHAR_NULL; + + // + // output the string + // + ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo); + + // + // restore the temp NULL terminator to it's original character + // + *((CHAR16*)(Walker+1)) = TempChar; + + // + // Update LineStart Variable + // + LineStart = Walker + 1; + + // + // increment row count + // + ShellInfoObject.ConsoleInfo->RowCounter++; + ConsoleInfo->OurConOut.Mode->CursorRow++; + + break; + case (CHAR_CARRIAGE_RETURN): + // + // Move the cursor to the beginning of the current row. + // + ConsoleInfo->OurConOut.Mode->CursorColumn = 0; + break; + default: + // + // increment column count + // + ConsoleInfo->OurConOut.Mode->CursorColumn++; + // + // check if that is the last column + // + if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn + 1) { + // + // output a line similar to the linefeed character. + // + + // + // add a temp NULL terminator + // + TempChar = *(Walker + 1); + *((CHAR16*)(Walker+1)) = CHAR_NULL; + + // + // output the string + // + ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo); + + // + // restore the temp NULL terminator to it's original character + // + *((CHAR16*)(Walker+1)) = TempChar; + + // + // Update LineStart Variable + // + LineStart = Walker + 1; + + // + // increment row count and zero the column + // + ShellInfoObject.ConsoleInfo->RowCounter++; + ConsoleInfo->OurConOut.Mode->CursorRow++; + ConsoleInfo->OurConOut.Mode->CursorColumn = 0; + } // last column on line + break; + } // switch for character + + // + // check if that was the last printable row. If yes handle PageBreak mode + // + if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) { + if (EFI_ERROR(ConsoleLoggerDoPageBreak())) { + // + // We got an error which means 'break' and halt the printing + // + SHELL_FREE_NON_NULL(StringCopy); + return (EFI_DEVICE_ERROR); + } + } + } // for loop + + if (LineStart != NULL && *LineStart != CHAR_NULL) { + ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo); + } + + SHELL_FREE_NON_NULL(StringCopy); + return (EFI_SUCCESS); +} + +/** + Write a Unicode string to the output device. + + @param[in] This Protocol instance pointer. + @param[in] WString The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx; + EFI_KEY_DATA KeyData; + UINTN EventIndex; + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { + return (EFI_UNSUPPORTED); + } + ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo); + + Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx); + if (!EFI_ERROR (Status)) { + while (ShellInfoObject.HaltOutput) { + + ShellInfoObject.HaltOutput = FALSE; + // + // just get some key + // + Status = gBS->WaitForEvent (1, &TxtInEx->WaitForKeyEx, &EventIndex); + ASSERT_EFI_ERROR (Status); + Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData); + if (EFI_ERROR(Status)) { + break; + } + + if ((KeyData.Key.UnicodeChar == L's') && (KeyData.Key.ScanCode == SCAN_NULL) && + ((KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED)) || + (KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED)) + ) + ) { + ShellInfoObject.HaltOutput = TRUE; + } + } + } + + if (!ShellInfoObject.ConsoleInfo->Enabled) { + return (EFI_DEVICE_ERROR); + } else if (ShellInfoObject.PageBreakEnabled) { + return (ConsoleLoggerPrintWithPageBreak(WString, ConsoleInfo)); + } else { + return (ConsoleLoggerOutputStringSplit(WString, ConsoleInfo)); + } +} + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + @param[in] This Protocol instance pointer. + @param[in] WString The NULL-terminated Unicode string to be examined for the output + device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + // + // Forward the request to the original ConOut + // + return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString)); +} + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param[in] This Protocol instance pointer. + @param[in] ModeNumber The mode number to return information on. + @param[out] Columns Upon return, the number of columns in the selected geometry + @param[out] Rows Upon return, the number of rows in the selected geometry + + @retval EFI_SUCCESS The requested mode information was returned. + @retval EFI_DEVICE_ERROR The device had an error and could not + complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + // + // Forward the request to the original ConOut + // + return (ConsoleInfo->OldConOut->QueryMode ( + ConsoleInfo->OldConOut, + ModeNumber, + Columns, + Rows + )); +} + +/** + Sets the output device(s) to a specified mode. + + @param[in] This Protocol instance pointer. + @param[in] ModeNumber The mode number to set. + + + @retval EFI_SUCCESS The requested text mode was set. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + EFI_STATUS Status; + + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber); + + // + // Check that the buffers are still correct for logging + // + if (!EFI_ERROR (Status)) { + ConsoleInfo->OurConOut.Mode = ConsoleInfo->OldConOut->Mode; + ConsoleLoggerResetBuffers(ConsoleInfo); + ConsoleInfo->OriginalStartRow = 0; + ConsoleInfo->CurrentStartRow = 0; + ConsoleInfo->OurConOut.ClearScreen (&ConsoleInfo->OurConOut); + } + + return Status; +} + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param[in] This Protocol instance pointer. + @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + @retval EFI_SUCCESS The attribute was set. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + EFI_STATUS Status; + + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute); + + // + // Record console output history + // + if (!EFI_ERROR (Status)) { + ConsoleInfo->HistoryMode.Attribute = (INT32) Attribute; + } + + return Status; +} + +/** + Clears the output device(s) display to the currently selected background + color. + + @param[in] This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + EFI_STATUS Status; + CHAR16 *Screen; + INT32 *Attributes; + UINTN Row; + UINTN Column; + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { + return (EFI_UNSUPPORTED); + } + + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut); + + // + // Record console output history + // + if (!EFI_ERROR (Status)) { + Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow]; + Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow]; + for ( Row = ConsoleInfo->OriginalStartRow + ; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) + ; Row++ + ){ + for ( Column = 0 + ; Column < ConsoleInfo->ColsPerScreen + ; Column++ + , Screen++ + , Attributes++ + ){ + *Screen = L' '; + *Attributes = ConsoleInfo->OldConOut->Mode->Attribute; + } + // + // Skip the NULL on each column end in text buffer only + // + Screen += 2; + } + ConsoleInfo->HistoryMode.CursorColumn = 0; + ConsoleInfo->HistoryMode.CursorRow = 0; + } + + return Status; +} + +/** + Sets the current coordinates of the cursor position + + @param[in] This Protocol instance pointer. + @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode + @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + EFI_STATUS Status; + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { + return (EFI_UNSUPPORTED); + } + + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->SetCursorPosition ( + ConsoleInfo->OldConOut, + Column, + Row + ); + + // + // Record console output history + // + if (!EFI_ERROR (Status)) { + ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column; + ConsoleInfo->HistoryMode.CursorRow = (INT32)(ConsoleInfo->OriginalStartRow + Row); + } + + return Status; +} + +/** + Makes the cursor visible or invisible + + @param[in] This Protocol instance pointer. + @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the + request, or the device does not support changing + the cursor mode. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +{ + EFI_STATUS Status; + + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; + ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This); + // + // Forward the request to the original ConOut + // + Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible); + + // + // Record console output history + // + if (!EFI_ERROR (Status)) { + ConsoleInfo->HistoryMode.CursorVisible = Visible; + } + + return Status; +} + +/** + Function to update and verify that the current buffers are correct. + + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + This will be used when a mode has changed or a reset ocurred to verify all + history buffers. +**/ +EFI_STATUS +ConsoleLoggerResetBuffers( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ) +{ + EFI_STATUS Status; + + if (ConsoleInfo->Buffer != NULL) { + FreePool(ConsoleInfo->Buffer); + ConsoleInfo->Buffer = NULL; + ConsoleInfo->BufferSize = 0; + } + if (ConsoleInfo->Attributes != NULL) { + FreePool(ConsoleInfo->Attributes); + ConsoleInfo->Attributes = NULL; + ConsoleInfo->AttribSize = 0; + } + + Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen); + if (EFI_ERROR(Status)){ + return (Status); + } + + ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Buffer[0]); + ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Attributes[0]); + + ConsoleInfo->Buffer = (CHAR16*)AllocateZeroPool(ConsoleInfo->BufferSize); + + if (ConsoleInfo->Buffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + ConsoleInfo->Attributes = (INT32*)AllocateZeroPool(ConsoleInfo->AttribSize); + if (ConsoleInfo->Attributes == NULL) { + FreePool(ConsoleInfo->Buffer); + ConsoleInfo->Buffer = NULL; + return (EFI_OUT_OF_RESOURCES); + } + + CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE)); + + return (EFI_SUCCESS); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.h new file mode 100644 index 0000000..b69fd99 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleLogger.h @@ -0,0 +1,323 @@ +/** @file + Provides interface to shell console logger. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef _CONSOLE_LOGGER_HEADER_ +#define _CONSOLE_LOGGER_HEADER_ + +#include "Shell.h" + +#define CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('c', 'o', 'P', 'D') + +typedef struct _CONSOLE_LOGGER_PRIVATE_DATA{ + UINTN Signature; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL OurConOut; ///< the protocol we installed onto the system table + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OldConOut; ///< old protocol to reinstall upon exiting + EFI_HANDLE OldConHandle; ///< old protocol handle + UINTN ScreenCount; ///< How many screens worth of data to save + CHAR16 *Buffer; ///< Buffer to save data + UINTN BufferSize; ///< size of buffer in bytes + + // start row is the top of the screen + UINTN OriginalStartRow; ///< What the originally visible start row was + UINTN CurrentStartRow; ///< what the currently visible start row is + + UINTN RowsPerScreen; ///< how many rows the screen can display + UINTN ColsPerScreen; ///< how many columns the screen can display + + INT32 *Attributes; ///< Buffer for Attribute to be saved for each character + UINTN AttribSize; ///< Size of Attributes in bytes + + EFI_SIMPLE_TEXT_OUTPUT_MODE HistoryMode; ///< mode of the history log + BOOLEAN Enabled; ///< Set to FALSE when a break is requested. + UINTN RowCounter; ///< Initial row of each print job. +} CONSOLE_LOGGER_PRIVATE_DATA; + +#define CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(a) CR (a, CONSOLE_LOGGER_PRIVATE_DATA, OurConOut, CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE) + +/** + Install our intermediate ConOut into the system table to + keep a log of all the info that is displayed to the user. + + @param[in] ScreensToSave Sets how many screen-worths of data to save. + @param[out] ConsoleInfo The object to pass into later functions. + + @retval EFI_SUCCESS The operation was successful. + @return other The operation failed. + + @sa ConsoleLoggerResetBuffers + @sa InstallProtocolInterface +**/ +EFI_STATUS +ConsoleLoggerInstall( + IN CONST UINTN ScreensToSave, + OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo + ); + +/** + Return the system to the state it was before InstallConsoleLogger + was installed. + + @param[in, out] ConsoleInfo The object from the install function. + + @retval EFI_SUCCESS The operation was successful + @return other The operation failed. This was from UninstallProtocolInterface. +**/ +EFI_STATUS +ConsoleLoggerUninstall( + IN OUT CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ); + +/** + Displays previously logged output back to the screen. + + This will scroll the screen forwards and backwards through the log of previous + output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows + is (UINTN)(-1) then the size of the screen will be scrolled. + + @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer). + If FALSE then the log will be displayed backwards (scroll to older). + @param[in] Rows Determines how many rows the log should scroll. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. +**/ +EFI_STATUS +ConsoleLoggerDisplayHistory( + IN CONST BOOLEAN Forward, + IN CONST UINTN Rows, + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ); + +/** + Function to return to normal output whent he scrolling is complete. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + @retval EFI_SUCCESS The operation was successful. + @return other The operation failed. See UpdateDisplayFromHistory. + + @sa UpdateDisplayFromHistory +**/ +EFI_STATUS +ConsoleLoggerStopHistory( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ); + +/** + Updates the hidden ConOut to be displaying the correct stuff. + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + @retval EFI_SUCCESS The operation was successful. + @return other The operation failed. +**/ +EFI_STATUS +UpdateDisplayFromHistory( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ); + +/** + Reset the text output device hardware and optionaly run diagnostics + + @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + @param ExtendedVerification Indicates that a more extensive test may be performed + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and + could not be reset. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Write a Unicode string to the output device. + + @param[in] This Protocol instance pointer. + @param[in] WString The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerOutputString( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + @param[in] This Protocol instance pointer. + @param[in] WString The NULL-terminated Unicode string to be examined for the output + device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param[in] This Protocol instance pointer. + @param[in] ModeNumber The mode number to return information on. + @param[out] Columns Upon return, the number of columns in the selected geometry + @param[out] Rows Upon return, the number of rows in the selected geometry + + @retval EFI_SUCCESS The requested mode information was returned. + @retval EFI_DEVICE_ERROR The device had an error and could not + complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + +/** + Sets the output device(s) to a specified mode. + + @param[in] This Protocol instance pointer. + @param[in] ModeNumber The mode number to set. + + + @retval EFI_SUCCESS The requested text mode was set. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param[in] This Protocol instance pointer. + @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + @retval EFI_SUCCESS The attribute was set. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +/** + Clears the output device(s) display to the currently selected background + color. + + @param[in] This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +/** + Sets the current coordinates of the cursor position. + + @param[in] This Protocol instance pointer. + @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode + @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and + could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + +/** + Makes the cursor visible or invisible + + @param[in] This Protocol instance pointer. + @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the + request, or the device does not support changing + the cursor mode. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +ConsoleLoggerEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +/** + Function to update and verify that the current buffers are correct. + + @param[in] ConsoleInfo The pointer to the instance of the console logger information. + + This will be used when a mode has changed or a reset ocurred to verify all + history buffers. +**/ +EFI_STATUS +ConsoleLoggerResetBuffers( + IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo + ); + +#endif //_CONSOLE_LOGGER_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c new file mode 100644 index 0000000..4f0e535 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c @@ -0,0 +1,514 @@ +/** @file + Function definitions for shell simple text in and out on top of file handles. + + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" + +extern BOOLEAN AsciiRedirection; + +typedef struct { + EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; + SHELL_FILE_HANDLE FileHandle; + EFI_HANDLE TheHandle; + UINT64 RemainingBytesOfInputFile; +} SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL; + +typedef struct { + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut; + SHELL_FILE_HANDLE FileHandle; + EFI_HANDLE TheHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalSimpleTextOut; +} SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; + +/** + Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event + Signal the event if there is key available + + @param Event Indicates the event that invoke this function. + @param Context Indicates the calling context. + +**/ +VOID +EFIAPI +ConInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + gBS->SignalEvent (Event); +} + +/** + Reset function for the fake simple text input. + + @param[in] This A pointer to the SimpleTextIn structure. + @param[in] ExtendedVerification TRUE for extra validation, FALSE otherwise. + + @retval EFI_SUCCESS The reset was successful. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextInReset( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return (EFI_SUCCESS); +} + +/** + ReadKeyStroke function for the fake simple text input. + + @param[in] This A pointer to the SimpleTextIn structure. + @param[in, out] Key A pointer to the Key structure to fill. + + @retval EFI_SUCCESS The read was successful. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextInReadKeyStroke( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + IN OUT EFI_INPUT_KEY *Key + ) +{ + UINTN Size; + UINTN CharSize; + + // + // Verify the parameters + // + if (Key == NULL || This == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Check if we have any characters left in the stream. + // + if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile == 0) { + return (EFI_NOT_READY); + } + + Size = sizeof(CHAR16); + + if(!AsciiRedirection) { + CharSize = sizeof(CHAR16); + } else { + CharSize = sizeof(CHAR8); + } + // + // Decrement the amount of free space by Size or set to zero (for odd length files) + // + if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile > CharSize) { + ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile -= CharSize; + } else { + ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile = 0; + } + + Key->ScanCode = 0; + return (ShellInfoObject.NewEfiShellProtocol->ReadFile( + ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->FileHandle, + &Size, + &Key->UnicodeChar)); +} + +/** + Function to create a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting input from a file. + + @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. + @param[in] HandleLocation The pointer of a location to copy handle with protocol to. + + @retval NULL There was insufficient memory available. + @return A pointer to the allocated protocol structure; +**/ +EFI_SIMPLE_TEXT_INPUT_PROTOCOL* +CreateSimpleTextInOnFile( + IN SHELL_FILE_HANDLE FileHandleToUse, + IN EFI_HANDLE *HandleLocation + ) +{ + SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ProtocolToReturn; + EFI_STATUS Status; + UINT64 CurrentPosition; + UINT64 FileSize; + + if (HandleLocation == NULL || FileHandleToUse == NULL) { + return (NULL); + } + + ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL)); + if (ProtocolToReturn == NULL) { + return (NULL); + } + + ShellGetFileSize (FileHandleToUse, &FileSize); + ShellGetFilePosition(FileHandleToUse, &CurrentPosition); + + // + // Initialize the protocol members + // + ProtocolToReturn->RemainingBytesOfInputFile = FileSize - CurrentPosition; + ProtocolToReturn->FileHandle = FileHandleToUse; + ProtocolToReturn->SimpleTextIn.Reset = FileBasedSimpleTextInReset; + ProtocolToReturn->SimpleTextIn.ReadKeyStroke = FileBasedSimpleTextInReadKeyStroke; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + ConInWaitForKey, + &ProtocolToReturn->SimpleTextIn, + &ProtocolToReturn->SimpleTextIn.WaitForKey + ); + + if (EFI_ERROR(Status)) { + FreePool(ProtocolToReturn); + return (NULL); + } + ///@todo possibly also install SimpleTextInputEx on the handle at this point. + Status = gBS->InstallProtocolInterface( + &(ProtocolToReturn->TheHandle), + &gEfiSimpleTextInProtocolGuid, + EFI_NATIVE_INTERFACE, + &(ProtocolToReturn->SimpleTextIn)); + if (!EFI_ERROR(Status)) { + *HandleLocation = ProtocolToReturn->TheHandle; + return ((EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)ProtocolToReturn); + } else { + FreePool(ProtocolToReturn); + return (NULL); + } +} + +/** + Function to close a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting input from a file. + + @param[in] SimpleTextIn The pointer to the SimpleTextIn to close. + + @retval EFI_SUCCESS The object was closed. +**/ +EFI_STATUS +CloseSimpleTextInOnFile( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + + if (SimpleTextIn == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Status = gBS->CloseEvent(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)SimpleTextIn)->SimpleTextIn.WaitForKey); + + Status1 = gBS->UninstallProtocolInterface( + ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)SimpleTextIn)->TheHandle, + &gEfiSimpleTextInProtocolGuid, + &(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)SimpleTextIn)->SimpleTextIn)); + + FreePool(SimpleTextIn); + if (!EFI_ERROR(Status)) { + return (Status1); + } else { + return (Status); + } +} + +/** + Reset the text output device hardware and optionaly run diagnostics. + + @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + @param ExtendedVerification Indicates that a more extensive test may be performed + + @retval EFI_SUCCESS The text output device was reset. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return (EFI_SUCCESS); +} + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + @param[in] This Protocol instance pointer. + @param[in] WString The NULL-terminated Unicode string to be examined. + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + return (EFI_SUCCESS); +} + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param[in] This Protocol instance pointer. + @param[in] ModeNumber The mode number to return information on. + @param[out] Columns Upon return, the number of columns in the selected geometry + @param[out] Rows Upon return, the number of rows in the selected geometry + + @retval EFI_UNSUPPORTED The mode number was not valid. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *PassThruProtocol; + + PassThruProtocol = ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->OriginalSimpleTextOut; + + // Pass the QueryMode call thru to the original SimpleTextOutProtocol + return (PassThruProtocol->QueryMode( + PassThruProtocol, + ModeNumber, + Columns, + Rows)); +} + +/** + Sets the output device(s) to a specified mode. + + @param[in] This Protocol instance pointer. + @param[in] ModeNumber The mode number to set. + + @retval EFI_UNSUPPORTED The mode number was not valid. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param[in] This Protocol instance pointer. + @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + @retval EFI_SUCCESS The attribute was set. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + return (EFI_SUCCESS); +} + +/** + Clears the output device(s) display to the currently selected background + color. + + @param[in] This Protocol instance pointer. + + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + return (EFI_SUCCESS); +} + +/** + Sets the current coordinates of the cursor position + + @param[in] This Protocol instance pointer. + @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode + @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode + + @retval EFI_SUCCESS The operation completed successfully. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + return (EFI_SUCCESS); +} + +/** + Makes the cursor visible or invisible + + @param[in] This Protocol instance pointer. + @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +{ + return (EFI_SUCCESS); +} + +/** + Write a Unicode string to the output device. + + @param[in] This Protocol instance pointer. + @param[in] WString The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. +**/ +EFI_STATUS +EFIAPI +FileBasedSimpleTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + UINTN Size; + Size = StrLen(WString) * sizeof(CHAR16); + return (ShellInfoObject.NewEfiShellProtocol->WriteFile( + ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->FileHandle, + &Size, + WString)); +} + +/** + Function to create a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting output from a file. + + @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. + @param[in] HandleLocation The pointer of a location to copy handle with protocol to. + @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions. + + @retval NULL There was insufficient memory available. + @return A pointer to the allocated protocol structure; +**/ +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* +CreateSimpleTextOutOnFile( + IN SHELL_FILE_HANDLE FileHandleToUse, + IN EFI_HANDLE *HandleLocation, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol + ) +{ + SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ProtocolToReturn; + EFI_STATUS Status; + + if (HandleLocation == NULL || FileHandleToUse == NULL) { + return (NULL); + } + + ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)); + if (ProtocolToReturn == NULL) { + return (NULL); + } + ProtocolToReturn->FileHandle = FileHandleToUse; + ProtocolToReturn->OriginalSimpleTextOut = OriginalProtocol; + ProtocolToReturn->SimpleTextOut.Reset = FileBasedSimpleTextOutReset; + ProtocolToReturn->SimpleTextOut.TestString = FileBasedSimpleTextOutTestString; + ProtocolToReturn->SimpleTextOut.QueryMode = FileBasedSimpleTextOutQueryMode; + ProtocolToReturn->SimpleTextOut.SetMode = FileBasedSimpleTextOutSetMode; + ProtocolToReturn->SimpleTextOut.SetAttribute = FileBasedSimpleTextOutSetAttribute; + ProtocolToReturn->SimpleTextOut.ClearScreen = FileBasedSimpleTextOutClearScreen; + ProtocolToReturn->SimpleTextOut.SetCursorPosition = FileBasedSimpleTextOutSetCursorPosition; + ProtocolToReturn->SimpleTextOut.EnableCursor = FileBasedSimpleTextOutEnableCursor; + ProtocolToReturn->SimpleTextOut.OutputString = FileBasedSimpleTextOutOutputString; + ProtocolToReturn->SimpleTextOut.Mode = AllocateZeroPool(sizeof(EFI_SIMPLE_TEXT_OUTPUT_MODE)); + if (ProtocolToReturn->SimpleTextOut.Mode == NULL) { + FreePool(ProtocolToReturn); + return (NULL); + } + ProtocolToReturn->SimpleTextOut.Mode->MaxMode = OriginalProtocol->Mode->MaxMode; + ProtocolToReturn->SimpleTextOut.Mode->Mode = OriginalProtocol->Mode->Mode; + ProtocolToReturn->SimpleTextOut.Mode->Attribute = OriginalProtocol->Mode->Attribute; + ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = OriginalProtocol->Mode->CursorColumn; + ProtocolToReturn->SimpleTextOut.Mode->CursorRow = OriginalProtocol->Mode->CursorRow; + ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = OriginalProtocol->Mode->CursorVisible; + + Status = gBS->InstallProtocolInterface( + &(ProtocolToReturn->TheHandle), + &gEfiSimpleTextOutProtocolGuid, + EFI_NATIVE_INTERFACE, + &(ProtocolToReturn->SimpleTextOut)); + if (!EFI_ERROR(Status)) { + *HandleLocation = ProtocolToReturn->TheHandle; + return ((EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)ProtocolToReturn); + } else { + SHELL_FREE_NON_NULL(ProtocolToReturn->SimpleTextOut.Mode); + SHELL_FREE_NON_NULL(ProtocolToReturn); + return (NULL); + } +} + +/** + Function to close a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting output from a file. + + @param[in] SimpleTextOut The pointer to the SimpleTextOUT to close. + + @retval EFI_SUCCESS The object was closed. +**/ +EFI_STATUS +CloseSimpleTextOutOnFile( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut + ) +{ + EFI_STATUS Status; + if (SimpleTextOut == NULL) { + return (EFI_INVALID_PARAMETER); + } + Status = gBS->UninstallProtocolInterface( + ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)SimpleTextOut)->TheHandle, + &gEfiSimpleTextOutProtocolGuid, + &(((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)SimpleTextOut)->SimpleTextOut)); + FreePool(SimpleTextOut->Mode); + FreePool(SimpleTextOut); + return (Status); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h new file mode 100644 index 0000000..57b3fd9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h @@ -0,0 +1,80 @@ +/** @file + Function definitions for shell simple text in and out on top of file handles. + + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_CONSOLE_WRAPPERS_HEADER_ +#define _SHELL_CONSOLE_WRAPPERS_HEADER_ + +/** + Function to create a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting input from a file. + + @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. + @param[in] HandleLocation The pointer of a location to copy handle with protocol to. + + @retval NULL There was insufficient memory available. + @return A pointer to the allocated protocol structure; +**/ +EFI_SIMPLE_TEXT_INPUT_PROTOCOL* +CreateSimpleTextInOnFile( + IN SHELL_FILE_HANDLE FileHandleToUse, + IN EFI_HANDLE *HandleLocation + ); + +/** + Function to close a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting input from a file. + + @param[in] SimpleTextIn The pointer to the SimpleTextIn to close. + + @retval EFI_SUCCESS The object was closed. +**/ +EFI_STATUS +CloseSimpleTextInOnFile( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn + ); + +/** + Function to create a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting output from a file. + + @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. + @param[in] HandleLocation The pointer of a location to copy handle with protocol to. + @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions. + + @retval NULL There was insufficient memory available. + @return A pointer to the allocated protocol structure; +**/ +EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* +CreateSimpleTextOutOnFile( + IN SHELL_FILE_HANDLE FileHandleToUse, + IN EFI_HANDLE *HandleLocation, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol + ); + +/** + Function to close a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a + SHELL_FILE_HANDLE to support redirecting output from a file. + + @param[in] SimpleTextOut The pointer to the SimpleTextOUT to close. + + @retval EFI_SUCCESS The object was closed. +**/ +EFI_STATUS +CloseSimpleTextOutOnFile( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut + ); + +#endif //_SHELL_CONSOLE_WRAPPERS_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleInternal.h new file mode 100644 index 0000000..bdf182e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleInternal.h @@ -0,0 +1,65 @@ +/** @file + internal worker functions for FileHandleWrappers to use + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _FILE_HANDLE_INTERNAL_HEADER_ +#define _FILE_HANDLE_INTERNAL_HEADER_ + +/** + Move the cursor position one character backward. + + @param[in] LineLength Length of a line. Get it by calling QueryMode + @param[in, out] Column Current column of the cursor position + @param[in, out] Row Current row of the cursor position +**/ +VOID +MoveCursorBackward ( + IN UINTN LineLength, + IN OUT UINTN *Column, + IN OUT UINTN *Row + ); + +/** + Move the cursor position one character forward. + + @param[in] LineLength Length of a line. + @param[in] TotalRow Total row of a screen + @param[in, out] Column Current column of the cursor position + @param[in, out] Row Current row of the cursor position +**/ +VOID +MoveCursorForward ( + IN UINTN LineLength, + IN UINTN TotalRow, + IN OUT UINTN *Column, + IN OUT UINTN *Row + ); + +/** + Prints out each previously typed command in the command list history log. + + When each screen is full it will pause for a key before continuing. + + @param[in] TotalCols How many columns are on the screen + @param[in] TotalRows How many rows are on the screen + @param[in] StartColumn which column to start at +**/ +VOID +PrintCommandHistory ( + IN CONST UINTN TotalCols, + IN CONST UINTN TotalRows, + IN CONST UINTN StartColumn + ); + +#endif //_FILE_HANDLE_INTERNAL_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.c new file mode 100644 index 0000000..f4c9e81 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.c @@ -0,0 +1,2153 @@ +/** @file + EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables, + StdIn, StdOut, StdErr, etc...). + + Copyright 2016 Dell Inc. + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" +#include "FileHandleInternal.h" + +#define MEM_WRITE_REALLOC_OVERHEAD 1024 + +/** + File style interface for console (Open). + + @param[in] This Ignored. + @param[out] NewHandle Ignored. + @param[in] FileName Ignored. + @param[in] OpenMode Ignored. + @param[in] Attributes Ignored. + + @retval EFI_NOT_FOUND +**/ +EFI_STATUS +EFIAPI +FileInterfaceOpenNotFound( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + return (EFI_NOT_FOUND); +} + +/** + File style interface for console (Close, Delete, & Flush) + + @param[in] This Ignored. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopGeneric( + IN EFI_FILE_PROTOCOL *This + ) +{ + return (EFI_SUCCESS); +} + +/** + File style interface for console (GetPosition). + + @param[in] This Ignored. + @param[out] Position Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopGetPosition( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console (SetPosition). + + @param[in] This Ignored. + @param[in] Position Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopSetPosition( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console (GetInfo). + + @param[in] This Ignored. + @param[in] InformationType Ignored. + @param[in, out] BufferSize Ignored. + @param[out] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopGetInfo( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console (SetInfo). + + @param[in] This Ignored. + @param[in] InformationType Ignored. + @param[in] BufferSize Ignored. + @param[in] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceNopSetInfo( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for StdOut (Write). + + Writes data to the screen. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_UNSUPPORTED No output console is supported. + @return A return value from gST->ConOut->OutputString. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdOutWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) { + return (EFI_UNSUPPORTED); + } + if (*((CHAR16 *)Buffer) == gUnicodeFileTag) { + return (gST->ConOut->OutputString(gST->ConOut, (CHAR16 *)Buffer + 1)); + } + return (gST->ConOut->OutputString(gST->ConOut, Buffer)); +} + +/** + File style interface for StdIn (Write). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[in] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdInWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console StdErr (Write). + + Writes error to the error output. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @return A return value from gST->StdErr->OutputString. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdErrWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (gST->StdErr->OutputString(gST->StdErr, Buffer)); +} + +/** + File style interface for console StdOut (Read). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[out] Buffer Ignored. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdOutRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for console StdErr (Read). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[out] Buffer Ignored. + + @retval EFI_UNSUPPORTED Always. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdErrRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (EFI_UNSUPPORTED); +} + +/** + File style interface for NUL file (Read). + + @param[in] This Ignored. + @param[in, out] BufferSize Poiner to 0 upon return. + @param[out] Buffer Ignored. + + @retval EFI_SUCCESS Always. +**/ +EFI_STATUS +EFIAPI +FileInterfaceNulRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + *BufferSize = 0; + return (EFI_SUCCESS); +} + +/** + File style interface for NUL file (Write). + + @param[in] This Ignored. + @param[in, out] BufferSize Ignored. + @param[in] Buffer Ignored. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FileInterfaceNulWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (EFI_SUCCESS); +} + +/** + Create the TAB completion list. + + @param[in] InputString The command line to expand. + @param[in] StringLen Length of the command line. + @param[in] BufferSize Buffer size. + @param[in, out] TabCompletionList Return the TAB completion list. + @param[in, out] TabUpdatePos Return the TAB update position. +**/ +EFI_STATUS +CreateTabCompletionList ( + IN CONST CHAR16 *InputString, + IN CONST UINTN StringLen, + IN CONST UINTN BufferSize, + IN OUT EFI_SHELL_FILE_INFO **TabCompletionList, + IN OUT UINTN *TabUpdatePos +) +{ + BOOLEAN InQuotation; + UINTN TabPos; + UINTN Index; + CONST CHAR16 *Cwd; + EFI_STATUS Status; + CHAR16 *TabStr; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *FileInfo; + EFI_SHELL_FILE_INFO *TempFileInfo; + + // + // Allocate buffers + // + TabStr = AllocateZeroPool (BufferSize); + if (TabStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // handle auto complete of file and directory names... + // E.g.: cd fs0:\EFI\Bo + // ^ ^ + // TabPos TabUpdatePos + // + TabPos = 0; + *TabUpdatePos = 0; + FileList = NULL; + InQuotation = FALSE; + for (Index = 0; Index < StringLen; Index++) { + switch (InputString[Index]) { + case L'\"': + InQuotation = (BOOLEAN) (!InQuotation); + break; + + case L' ': + if (!InQuotation) { + TabPos = Index + 1; + *TabUpdatePos = TabPos; + } + break; + + case L':': + // + // handle the case "fs0:" + // Update the TabUpdatePos as well. + // + case L'\\': + *TabUpdatePos = Index + 1; + break; + + default: + break; + } + } + + if (StrStr (InputString + TabPos, L":") == NULL) { + // + // If file path doesn't contain ":", ... + // + Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL); + if (Cwd != NULL) { + if (InputString[TabPos] != L'\\') { + // + // and it doesn't begin with "\\", it's a path relative to current directory. + // TabStr = "\\" + // + StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1); + StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\"); + } else { + // + // and it begins with "\\", it's a path pointing to root directory of current map. + // TabStr = "fsx:" + // + Index = StrStr (Cwd, L":") - Cwd + 1; + StrnCpyS (TabStr, BufferSize / sizeof (CHAR16), Cwd, Index); + } + } + } + StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos); + StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr)); + Status = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FileList); + + // + // Filter out the non-directory for "CD" command + // Filter "." and ".." for all + // + if (!EFI_ERROR (Status) && FileList != NULL) { + // + // Skip the spaces in the beginning + // + while (*InputString == L' ') { + InputString++; + } + + for (FileInfo = (EFI_SHELL_FILE_INFO *) GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) { + if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) || + (((InputString[0] == L'c' || InputString[0] == L'C') && (InputString[1] == L'd' || InputString[1] == L'D')) && + (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) { + TempFileInfo = FileInfo; + FileInfo = (EFI_SHELL_FILE_INFO *) RemoveEntryList (&FileInfo->Link); + InternalFreeShellFileInfoNode (TempFileInfo); + } else { + FileInfo = (EFI_SHELL_FILE_INFO *) GetNextNode (&FileList->Link, &FileInfo->Link); + } + } + } + + if (FileList != NULL && !IsListEmpty (&FileList->Link)) { + Status = EFI_SUCCESS; + } else { + ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList); + Status = EFI_NOT_FOUND; + } + + FreePool (TabStr); + + *TabCompletionList = FileList; + return Status; +} + +/** + File style interface for console (Read). + + This will return a single line of input from the console. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the + file handle to read data from. Not used. + @param BufferSize On input, the size of the Buffer. On output, the amount + of data returned in Buffer. In both cases, the size is + measured in bytes. + @param Buffer The buffer into which the data is read. + + + @retval EFI_SUCCESS The data was read. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file. + @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory + entry. BufferSize has been updated with the size + needed to complete the request. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceStdInRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + CHAR16 *CurrentString; + BOOLEAN Done; + UINTN TabUpdatePos; // Start index of the string updated by TAB stroke + UINTN Column; // Column of current cursor + UINTN Row; // Row of current cursor + UINTN StartColumn; // Column at the beginning of the line + UINTN Update; // Line index for update + UINTN Delete; // Num of chars to delete from console after update + UINTN StringLen; // Total length of the line + UINTN StringCurPos; // Line index corresponding to the cursor + UINTN MaxStr; // Maximum possible line length + UINTN TotalColumn; // Num of columns in the console + UINTN TotalRow; // Num of rows in the console + UINTN SkipLength; + UINTN OutputLength; // Length of the update string + UINTN TailRow; // Row of end of line + UINTN TailColumn; // Column of end of line + EFI_INPUT_KEY Key; + + BUFFER_LIST *LinePos; + BUFFER_LIST *NewPos; + BOOLEAN InScrolling; + EFI_STATUS Status; + BOOLEAN InTabScrolling; // Whether in TAB-completion state + EFI_SHELL_FILE_INFO *TabCompleteList; + EFI_SHELL_FILE_INFO *TabCurrent; + UINTN EventIndex; + CHAR16 *TabOutputStr; + + // + // If buffer is not large enough to hold a CHAR16, return minimum buffer size + // + if (*BufferSize < sizeof (CHAR16) * 2) { + *BufferSize = sizeof (CHAR16) * 2; + return (EFI_BUFFER_TOO_SMALL); + } + + Done = FALSE; + CurrentString = Buffer; + StringLen = 0; + StringCurPos = 0; + OutputLength = 0; + Update = 0; + Delete = 0; + LinePos = NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory); + InScrolling = FALSE; + InTabScrolling = FALSE; + Status = EFI_SUCCESS; + TabOutputStr = NULL; + TabUpdatePos = 0; + TabCompleteList = NULL; + TabCurrent = NULL; + + // + // Get the screen setting and the current cursor location + // + Column = StartColumn = gST->ConOut->Mode->CursorColumn; + Row = gST->ConOut->Mode->CursorRow; + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow); + + // + // Limit the line length to the buffer size or the minimun size of the + // screen. (The smaller takes effect) + // + MaxStr = TotalColumn * (TotalRow - 1) - StartColumn; + if (MaxStr > *BufferSize / sizeof (CHAR16)) { + MaxStr = *BufferSize / sizeof (CHAR16); + } + ZeroMem (CurrentString, MaxStr * sizeof (CHAR16)); + do { + // + // Read a key + // + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + + if (Status == EFI_NOT_READY) + continue; + + ZeroMem (CurrentString, MaxStr * sizeof(CHAR16)); + StringLen = 0; + break; + } + + // + // Press PageUp or PageDown to scroll the history screen up or down. + // Press any other key to quit scrolling. + // + if (Key.UnicodeChar == 0 && (Key.ScanCode == SCAN_PAGE_UP || Key.ScanCode == SCAN_PAGE_DOWN)) { + if (Key.ScanCode == SCAN_PAGE_UP) { + ConsoleLoggerDisplayHistory(FALSE, 0, ShellInfoObject.ConsoleInfo); + } else if (Key.ScanCode == SCAN_PAGE_DOWN) { + ConsoleLoggerDisplayHistory(TRUE, 0, ShellInfoObject.ConsoleInfo); + } + + InScrolling = TRUE; + } else { + if (InScrolling) { + ConsoleLoggerStopHistory(ShellInfoObject.ConsoleInfo); + InScrolling = FALSE; + } + } + + // + // If we are quitting TAB scrolling... + // + if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) { + if (TabCompleteList != NULL) { + ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList); + DEBUG_CODE(TabCompleteList = NULL;); + } + InTabScrolling = FALSE; + } + + switch (Key.UnicodeChar) { + case CHAR_CARRIAGE_RETURN: + // + // All done, print a newline at the end of the string + // + TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn; + TailColumn = (StringLen - StringCurPos + Column) % TotalColumn; + ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n"); + Done = TRUE; + break; + + case CHAR_BACKSPACE: + if (StringCurPos != 0) { + // + // If not move back beyond string beginning, move all characters behind + // the current position one character forward + // + StringCurPos--; + Update = StringCurPos; + Delete = 1; + CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos)); + + // + // Adjust the current column and row + // + MoveCursorBackward (TotalColumn, &Column, &Row); + } + break; + + case CHAR_TAB: + if (!InTabScrolling) { + TabCurrent = NULL; + // + // Initialize a tab complete operation. + // + Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos); + if (!EFI_ERROR(Status)) { + InTabScrolling = TRUE; + } + + // + // We do not set up the replacement. + // The next section will do that. + // + } + + if (InTabScrolling) { + // + // We are in a tab complete operation. + // set up the next replacement. + // + ASSERT(TabCompleteList != NULL); + if (TabCurrent == NULL) { + TabCurrent = (EFI_SHELL_FILE_INFO*) GetFirstNode (&TabCompleteList->Link); + } else { + TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link); + } + + // + // Skip over the empty list beginning node + // + if (IsNull(&TabCompleteList->Link, &TabCurrent->Link)) { + TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link); + } + } + break; + + default: + if (Key.UnicodeChar >= ' ') { + // + // If we are at the buffer's end, drop the key + // + if (StringLen == MaxStr - 1 && (ShellInfoObject.ViewingSettings.InsertMode || StringCurPos == StringLen)) { + break; + } + // + // If in insert mode, make space by moving each other character 1 + // space higher in the array + // + if (ShellInfoObject.ViewingSettings.InsertMode) { + CopyMem(CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof(CurrentString[0])); + } + + CurrentString[StringCurPos] = Key.UnicodeChar; + Update = StringCurPos; + + StringCurPos += 1; + OutputLength = 1; + } + break; + + case 0: + switch (Key.ScanCode) { + case SCAN_DELETE: + // + // Move characters behind current position one character forward + // + if (StringLen != 0) { + Update = StringCurPos; + Delete = 1; + CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos)); + } + break; + + case SCAN_UP: + // + // Prepare to print the previous command + // + NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + if (IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) { + NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + } + break; + + case SCAN_DOWN: + // + // Prepare to print the next command + // + NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + if (NewPos == (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) { + NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link); + } + break; + + case SCAN_LEFT: + // + // Adjust current cursor position + // + if (StringCurPos != 0) { + --StringCurPos; + MoveCursorBackward (TotalColumn, &Column, &Row); + } + break; + + case SCAN_RIGHT: + // + // Adjust current cursor position + // + if (StringCurPos < StringLen) { + ++StringCurPos; + MoveCursorForward (TotalColumn, TotalRow, &Column, &Row); + } + break; + + case SCAN_HOME: + // + // Move current cursor position to the beginning of the command line + // + Row -= (StringCurPos + StartColumn) / TotalColumn; + Column = StartColumn; + StringCurPos = 0; + break; + + case SCAN_END: + // + // Move current cursor position to the end of the command line + // + TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn; + TailColumn = (StringLen - StringCurPos + Column) % TotalColumn; + Row = TailRow; + Column = TailColumn; + StringCurPos = StringLen; + break; + + case SCAN_ESC: + // + // Prepare to clear the current command line + // + CurrentString[0] = 0; + Update = 0; + Delete = StringLen; + Row -= (StringCurPos + StartColumn) / TotalColumn; + Column = StartColumn; + OutputLength = 0; + break; + + case SCAN_INSERT: + // + // Toggle the SEnvInsertMode flag + // + ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN)!ShellInfoObject.ViewingSettings.InsertMode; + break; + + case SCAN_F7: + // + // Print command history + // + PrintCommandHistory (TotalColumn, TotalRow, 4); + *CurrentString = CHAR_NULL; + Done = TRUE; + break; + } + } + + if (Done) { + break; + } + + // + // If we are in auto-complete mode, we are preparing to print + // the next file or directory name + // + if (InTabScrolling) { + TabOutputStr = AllocateZeroPool (*BufferSize); + if (TabOutputStr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } + } + + if (InTabScrolling && TabOutputStr != NULL) { + + // + // Adjust the column and row to the start of TAB-completion string. + // + Column = (StartColumn + TabUpdatePos) % TotalColumn; + Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn; + OutputLength = StrLen (TabCurrent->FileName); + // + // if the output string contains blank space, quotation marks L'\"' + // should be added to the output. + // + if (StrStr(TabCurrent->FileName, L" ") != NULL){ + TabOutputStr[0] = L'\"'; + CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16)); + TabOutputStr[OutputLength + 1] = L'\"'; + TabOutputStr[OutputLength + 2] = CHAR_NULL; + } else { + CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16)); + TabOutputStr[OutputLength] = CHAR_NULL; + } + OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1; + CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16)); + CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL; + StringCurPos = TabUpdatePos + OutputLength; + Update = TabUpdatePos; + if (StringLen > TabUpdatePos + OutputLength) { + Delete = StringLen - TabUpdatePos - OutputLength; + } + + FreePool(TabOutputStr); + } + + // + // If we have a new position, we are preparing to print a previous or + // next command. + // + if (NewPos != (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) { + Column = StartColumn; + Row -= (StringCurPos + StartColumn) / TotalColumn; + + LinePos = NewPos; + NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory); + + OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1; + CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16)); + CurrentString[OutputLength] = CHAR_NULL; + + StringCurPos = OutputLength; + + // + // Draw new input string + // + Update = 0; + if (StringLen > OutputLength) { + // + // If old string was longer, blank its tail + // + Delete = StringLen - OutputLength; + } + } + // + // If we need to update the output do so now + // + if (Update != (UINTN) -1) { + ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L""); + StringLen = StrLen (CurrentString); + + if (Delete != 0) { + SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL); + } + + if (StringCurPos > StringLen) { + StringCurPos = StringLen; + } + + Update = (UINTN) -1; + + // + // After using print to reflect newly updates, if we're not using + // BACKSPACE and DELETE, we need to move the cursor position forward, + // so adjust row and column here. + // + if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) { + // + // Calulate row and column of the tail of current string + // + TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn; + TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn; + + // + // If the tail of string reaches screen end, screen rolls up, so if + // Row does not equal TailRow, Row should be decremented + // + // (if we are recalling commands using UPPER and DOWN key, and if the + // old command is too long to fit the screen, TailColumn must be 79. + // + if (TailColumn == 0 && TailRow >= TotalRow && Row != TailRow) { + Row--; + } + // + // Calculate the cursor position after current operation. If cursor + // reaches line end, update both row and column, otherwise, only + // column will be changed. + // + if (Column + OutputLength >= TotalColumn) { + SkipLength = OutputLength - (TotalColumn - Column); + + Row += SkipLength / TotalColumn + 1; + if (Row > TotalRow - 1) { + Row = TotalRow - 1; + } + + Column = SkipLength % TotalColumn; + } else { + Column += OutputLength; + } + } + + Delete = 0; + } + // + // Set the cursor position for this key + // + gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row); + } while (!Done); + + if (CurrentString != NULL && StrLen(CurrentString) > 0) { + // + // add the line to the history buffer + // + AddLineToCommandHistory(CurrentString); + } + + // + // Return the data to the caller + // + *BufferSize = StringLen * sizeof (CHAR16); + + // + // if this was used it should be deallocated by now... + // prevent memory leaks... + // + if (TabCompleteList != NULL) { + ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList); + } + ASSERT(TabCompleteList == NULL); + + return Status; +} + +// +// FILE sytle interfaces for StdIn/StdOut/StdErr +// +EFI_FILE_PROTOCOL FileInterfaceStdIn = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceStdInRead, + FileInterfaceStdInWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +EFI_FILE_PROTOCOL FileInterfaceStdOut = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceStdOutRead, + FileInterfaceStdOutWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +EFI_FILE_PROTOCOL FileInterfaceStdErr = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceStdErrRead, + FileInterfaceStdErrWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + +EFI_FILE_PROTOCOL FileInterfaceNulFile = { + EFI_FILE_REVISION, + FileInterfaceOpenNotFound, + FileInterfaceNopGeneric, + FileInterfaceNopGeneric, + FileInterfaceNulRead, + FileInterfaceNulWrite, + FileInterfaceNopGetPosition, + FileInterfaceNopSetPosition, + FileInterfaceNopGetInfo, + FileInterfaceNopSetInfo, + FileInterfaceNopGeneric +}; + + + + +// +// This is identical to EFI_FILE_PROTOCOL except for the additional member +// for the name. +// + +typedef struct { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + CHAR16 Name[1]; +} EFI_FILE_PROTOCOL_ENVIRONMENT; +//ANSI compliance helper to get size of the struct. +#define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name) + +/** + File style interface for Environment Variable (Close). + + Frees the memory for this object. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvClose( + IN EFI_FILE_PROTOCOL *This + ) +{ + VOID* NewBuffer; + UINTN NewSize; + EFI_STATUS Status; + BOOLEAN Volatile; + UINTN TotalSize; + + // + // Most if not all UEFI commands will have an '\r\n' at the end of any output. + // Since the output was redirected to a variable, it does not make sense to + // keep this. So, before closing, strip the trailing '\r\n' from the variable + // if it exists. + // + NewBuffer = NULL; + NewSize = 0; + TotalSize = 0; + + Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &Volatile); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize = NewSize + sizeof (CHAR16); + NewBuffer = AllocateZeroPool (TotalSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); + } + + if (!EFI_ERROR(Status) && NewBuffer != NULL) { + + if (TotalSize / sizeof (CHAR16) >= 3) { + if ( (((CHAR16*)NewBuffer)[TotalSize / sizeof (CHAR16) - 2] == CHAR_LINEFEED) && + (((CHAR16*)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] == CHAR_CARRIAGE_RETURN) + ) { + ((CHAR16*)NewBuffer)[TotalSize / sizeof (CHAR16) - 3] = CHAR_NULL; + // + // If the NewBuffer end with \r\n\0, We will repace '\r' by '\0' and then update TotalSize. + // + TotalSize -= sizeof(CHAR16) * 2; + } + + if (Volatile) { + Status = SHELL_SET_ENVIRONMENT_VARIABLE_V ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + + if (!EFI_ERROR(Status)) { + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + } + } else { + Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + + if (!EFI_ERROR(Status)) { + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + } + } + } + } + + SHELL_FREE_NON_NULL(NewBuffer); + FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This); + return (Status); +} + +/** + File style interface for Environment Variable (Delete). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval The return value from FileInterfaceEnvClose(). +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvDelete( + IN EFI_FILE_PROTOCOL *This + ) +{ + SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name); + return (FileInterfaceEnvClose(This)); +} + +/** + File style interface for Environment Variable (Read). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[out] Buffer The pointer to the buffer to fill. + + @retval EFI_SUCCESS The data was read. +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + *BufferSize = *BufferSize / sizeof (CHAR16) * sizeof (CHAR16); + if (*BufferSize != 0) { + // + // Make sure the first unicode character is \xFEFF + // + *(CHAR16 *)Buffer = gUnicodeFileTag; + Buffer = (CHAR16 *)Buffer + 1; + *BufferSize -= sizeof (gUnicodeFileTag); + } + + Status = SHELL_GET_ENVIRONMENT_VARIABLE ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + BufferSize, + Buffer + ); + if (!EFI_ERROR (Status) || (Status == EFI_BUFFER_TOO_SMALL)) { + // + // BufferSize is valid and needs update when Status is Success or BufferTooSmall. + // + *BufferSize += sizeof (gUnicodeFileTag); + } + return Status; +} + +/** + File style interface for Volatile Environment Variable (Write). + This function also caches the environment variable into gShellEnvVarList. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_SUCCESS The data was successfully write to variable. + @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvVolWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + VOID* NewBuffer; + UINTN NewSize; + EFI_STATUS Status; + UINTN TotalSize; + + NewBuffer = NULL; + NewSize = 0; + TotalSize = 0; + + Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize = NewSize + *BufferSize + sizeof (CHAR16); + } else if (Status == EFI_NOT_FOUND) { + TotalSize = *BufferSize + sizeof(CHAR16); + } else { + return Status; + } + + NewBuffer = AllocateZeroPool (TotalSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); + } + + if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { + FreePool (NewBuffer); + return Status; + } + + CopyMem ((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize); + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR(Status)) { + FreePool (NewBuffer); + return Status; + } + + Status = SHELL_SET_ENVIRONMENT_VARIABLE_V ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + if (EFI_ERROR(Status)) { + ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name); + } + + FreePool (NewBuffer); + return Status; +} + + +/** + File style interface for Non Volatile Environment Variable (Write). + This function also caches the environment variable into gShellEnvVarList. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_SUCCESS The data was successfully write to variable. + @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceEnvNonVolWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + VOID* NewBuffer; + UINTN NewSize; + EFI_STATUS Status; + UINTN TotalSize; + + NewBuffer = NULL; + NewSize = 0; + TotalSize = 0; + + Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize = NewSize + *BufferSize + sizeof (CHAR16); + } else if (Status == EFI_NOT_FOUND) { + TotalSize = *BufferSize + sizeof (CHAR16); + } else { + return Status; + } + + NewBuffer = AllocateZeroPool (TotalSize); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer); + } + + if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { + FreePool (NewBuffer); + return Status; + } + + CopyMem ((UINT8*) NewBuffer + NewSize, Buffer, *BufferSize); + Status = ShellAddEnvVarToList ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + NewBuffer, + TotalSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + ); + if (EFI_ERROR (Status)) { + FreePool (NewBuffer); + return Status; + } + + Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV ( + ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, + TotalSize - sizeof (CHAR16), + NewBuffer + ); + if (EFI_ERROR (Status)) { + ShellRemvoeEnvVarFromList (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name); + } + + FreePool (NewBuffer); + return Status; +} + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + environment variables through file operations. + + @param EnvName The name of the Environment Variable to be operated on. + + @retval NULL Memory could not be allocated. + @return other a pointer to an EFI_FILE_PROTOCOL structure +**/ +EFI_FILE_PROTOCOL* +CreateFileInterfaceEnv( + IN CONST CHAR16 *EnvName + ) +{ + EFI_STATUS Status; + EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface; + UINTN EnvNameSize; + BOOLEAN Volatile; + + if (EnvName == NULL) { + return (NULL); + } + + Status = IsVolatileEnv (EnvName, &Volatile); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Get some memory + // + EnvNameSize = StrSize(EnvName); + EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize); + if (EnvFileInterface == NULL){ + return (NULL); + } + + // + // Assign the generic members + // + EnvFileInterface->Revision = EFI_FILE_REVISION; + EnvFileInterface->Open = FileInterfaceOpenNotFound; + EnvFileInterface->Close = FileInterfaceEnvClose; + EnvFileInterface->GetPosition = FileInterfaceNopGetPosition; + EnvFileInterface->SetPosition = FileInterfaceNopSetPosition; + EnvFileInterface->GetInfo = FileInterfaceNopGetInfo; + EnvFileInterface->SetInfo = FileInterfaceNopSetInfo; + EnvFileInterface->Flush = FileInterfaceNopGeneric; + EnvFileInterface->Delete = FileInterfaceEnvDelete; + EnvFileInterface->Read = FileInterfaceEnvRead; + + CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize); + + // + // Assign the different members for Volatile and Non-Volatile variables + // + if (Volatile) { + EnvFileInterface->Write = FileInterfaceEnvVolWrite; + } else { + EnvFileInterface->Write = FileInterfaceEnvNonVolWrite; + } + return ((EFI_FILE_PROTOCOL *)EnvFileInterface); +} + +/** + Move the cursor position one character backward. + + @param[in] LineLength Length of a line. Get it by calling QueryMode + @param[in, out] Column Current column of the cursor position + @param[in, out] Row Current row of the cursor position +**/ +VOID +MoveCursorBackward ( + IN UINTN LineLength, + IN OUT UINTN *Column, + IN OUT UINTN *Row + ) +{ + // + // If current column is 0, move to the last column of the previous line, + // otherwise, just decrement column. + // + if (*Column == 0) { + *Column = LineLength - 1; + if (*Row > 0) { + (*Row)--; + } + return; + } + (*Column)--; +} + +/** + Move the cursor position one character forward. + + @param[in] LineLength Length of a line. + @param[in] TotalRow Total row of a screen + @param[in, out] Column Current column of the cursor position + @param[in, out] Row Current row of the cursor position +**/ +VOID +MoveCursorForward ( + IN UINTN LineLength, + IN UINTN TotalRow, + IN OUT UINTN *Column, + IN OUT UINTN *Row + ) +{ + // + // Increment Column. + // If this puts column past the end of the line, move to first column + // of the next row. + // + (*Column)++; + if (*Column >= LineLength) { + (*Column) = 0; + if ((*Row) < TotalRow - 1) { + (*Row)++; + } + } +} + +/** + Prints out each previously typed command in the command list history log. + + When each screen is full it will pause for a key before continuing. + + @param[in] TotalCols How many columns are on the screen + @param[in] TotalRows How many rows are on the screen + @param[in] StartColumn which column to start at +**/ +VOID +PrintCommandHistory ( + IN CONST UINTN TotalCols, + IN CONST UINTN TotalRows, + IN CONST UINTN StartColumn + ) +{ + BUFFER_LIST *Node; + UINTN Index; + UINTN LineNumber; + UINTN LineCount; + + ShellPrintEx (-1, -1, L"\n"); + Index = 0; + LineNumber = 0; + // + // go through history list... + // + for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link) + ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link) + ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link) + ){ + Index++; + LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1; + + if (LineNumber + LineCount >= TotalRows) { + ShellPromptForResponseHii( + ShellPromptResponseTypeEnterContinue, + STRING_TOKEN (STR_SHELL_ENTER_TO_CONT), + ShellInfoObject.HiiHandle, + NULL + ); + LineNumber = 0; + } + ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer); + LineNumber += LineCount; + } +} + + + + + + +// +// This is identical to EFI_FILE_PROTOCOL except for the additional members +// for the buffer, size, and position. +// + +typedef struct { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + VOID *Buffer; + UINT64 Position; + UINT64 BufferSize; + BOOLEAN Unicode; + UINT64 FileSize; +} EFI_FILE_PROTOCOL_MEM; + +/** + File style interface for Mem (SetPosition). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[out] Position The position to set. + + @retval EFI_SUCCESS The position was successfully changed. + @retval EFI_INVALID_PARAMETER The Position was invalid. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemSetPosition( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 Position + ) +{ + if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) { + ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position; + return (EFI_SUCCESS); + } else { + return (EFI_INVALID_PARAMETER); + } +} + +/** + File style interface for Mem (GetPosition). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[out] Position The pointer to the position. + + @retval EFI_SUCCESS The position was retrieved. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemGetPosition( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position; + return (EFI_SUCCESS); +} + +/** + File style interface for Mem (GetInfo). + + @param This Protocol instance pointer. + @param InformationType Type of information to return in Buffer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer to return data. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is 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_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemGetInfo( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_FILE_INFO *FileInfo; + + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { + if (*BufferSize < sizeof (EFI_FILE_INFO)) { + *BufferSize = sizeof (EFI_FILE_INFO); + return EFI_BUFFER_TOO_SMALL; + } + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + FileInfo = (EFI_FILE_INFO *)Buffer; + FileInfo->Size = sizeof (*FileInfo); + ZeroMem (FileInfo, sizeof (*FileInfo)); + FileInfo->FileSize = ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize; + FileInfo->PhysicalSize = FileInfo->FileSize; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +/** + File style interface for Mem (Write). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources. + @retval EFI_SUCCESS The data was written. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + CHAR8 *AsciiBuffer; + EFI_FILE_PROTOCOL_MEM *MemFile; + + MemFile = (EFI_FILE_PROTOCOL_MEM *) This; + if (MemFile->Unicode) { + // + // Unicode + // + if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) { + MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer); + MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD; + } + CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize); + MemFile->Position += (*BufferSize); + MemFile->FileSize = MemFile->Position; + return (EFI_SUCCESS); + } else { + // + // Ascii + // + AsciiBuffer = AllocateZeroPool(*BufferSize); + if (AsciiBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer); + if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) { + MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer); + MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD; + } + CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer)); + MemFile->Position += (*BufferSize / sizeof(CHAR16)); + MemFile->FileSize = MemFile->Position; + FreePool(AsciiBuffer); + return (EFI_SUCCESS); + } +} + +/** + File style interface for Mem (Read). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to fill. + + @retval EFI_SUCCESS The data was read. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + EFI_FILE_PROTOCOL_MEM *MemFile; + + MemFile = (EFI_FILE_PROTOCOL_MEM *) This; + if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) { + (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position)); + } + CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize)); + MemFile->Position = MemFile->Position + (*BufferSize); + return (EFI_SUCCESS); +} + +/** + File style interface for Mem (Close). + + Frees all memory associated with this object. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval EFI_SUCCESS The 'file' was closed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceMemClose( + IN EFI_FILE_PROTOCOL *This + ) +{ + SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer); + SHELL_FREE_NON_NULL(This); + return (EFI_SUCCESS); +} + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + a file entirely in memory through file operations. + + @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii. + + @retval NULL Memory could not be allocated. + @return other A pointer to an EFI_FILE_PROTOCOL structure. +**/ +EFI_FILE_PROTOCOL* +CreateFileInterfaceMem( + IN CONST BOOLEAN Unicode + ) +{ + EFI_FILE_PROTOCOL_MEM *FileInterface; + + // + // Get some memory + // + FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM)); + if (FileInterface == NULL){ + return (NULL); + } + + // + // Assign the generic members + // + FileInterface->Revision = EFI_FILE_REVISION; + FileInterface->Open = FileInterfaceOpenNotFound; + FileInterface->Close = FileInterfaceMemClose; + FileInterface->GetPosition = FileInterfaceMemGetPosition; + FileInterface->SetPosition = FileInterfaceMemSetPosition; + FileInterface->GetInfo = FileInterfaceMemGetInfo; + FileInterface->SetInfo = FileInterfaceNopSetInfo; + FileInterface->Flush = FileInterfaceNopGeneric; + FileInterface->Delete = FileInterfaceNopGeneric; + FileInterface->Read = FileInterfaceMemRead; + FileInterface->Write = FileInterfaceMemWrite; + FileInterface->Unicode = Unicode; + + ASSERT(FileInterface->Buffer == NULL); + ASSERT(FileInterface->BufferSize == 0); + ASSERT(FileInterface->Position == 0); + + if (Unicode) { + FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag)); + if (FileInterface->Buffer == NULL) { + FreePool (FileInterface); + return NULL; + } + *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK; + FileInterface->BufferSize = 2; + FileInterface->Position = 2; + } + + return ((EFI_FILE_PROTOCOL *)FileInterface); +} + +typedef struct { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + BOOLEAN Unicode; + EFI_FILE_PROTOCOL *Orig; +} EFI_FILE_PROTOCOL_FILE; + +/** + Set a files current position + + @param This Protocol instance pointer. + @param Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileSetPosition( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position); +} + +/** + Get a file's current position + + @param This Protocol instance pointer. + @param Position Byte position from the start of the file. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileGetPosition( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position); +} + +/** + Get information about a file. + + @param This Protocol instance pointer. + @param InformationType Type of information to return in Buffer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer to return data. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is 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_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileGetInfo( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer); +} + +/** + Set information about a file + + @param This Protocol instance pointer. + @param InformationType Type of information in Buffer. + @param BufferSize Size of buffer. + @param Buffer The data to write. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is 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. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileSetInfo( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer); +} + +/** + Flush data back for the file handle. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORT Writes to 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 +FileInterfaceFileFlush( + IN EFI_FILE_PROTOCOL *This + ) +{ + return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Flush(((EFI_FILE_PROTOCOL_FILE*)This)->Orig); +} + +/** + Read data from the file. + + @param This Protocol instance pointer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer in which data is read. + + @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 BufferSize is too small. BufferSize contains required size. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileRead( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT64 Position; + CHAR8 *AsciiStrBuffer; + CHAR16 *UscStrBuffer; + UINTN Size; + if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) { + // + // Unicode + // There might be different file tag for the Unicode file. We cannot unconditionally insert the \xFEFF. + // So we choose to leave the file content as is. + // + return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer)); + } else { + // + // Ascii + // + *BufferSize = *BufferSize / sizeof (CHAR16) * sizeof (CHAR16); + if (*BufferSize == 0) { + return EFI_SUCCESS; + } + Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition (((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Position); + if (EFI_ERROR (Status)) { + return Status; + } + if (Position == 0) { + // + // First two bytes in Buffer is for the Unicode file tag. + // + *(CHAR16 *)Buffer = gUnicodeFileTag; + Buffer = (CHAR16 *)Buffer + 1; + Size = *BufferSize / sizeof (CHAR16) - 1; + } else { + Size = *BufferSize / sizeof (CHAR16); + } + AsciiStrBuffer = AllocateZeroPool (Size + 1); + if (AsciiStrBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + UscStrBuffer = AllocateZeroPool ((Size + 1) * sizeof(CHAR16)); + if (UscStrBuffer== NULL) { + SHELL_FREE_NON_NULL(AsciiStrBuffer); + return EFI_OUT_OF_RESOURCES; + } + Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read (((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer); + if (!EFI_ERROR(Status)) { + AsciiStrToUnicodeStrS (AsciiStrBuffer, UscStrBuffer, Size + 1); + *BufferSize = Size * sizeof (CHAR16); + CopyMem (Buffer, UscStrBuffer, *BufferSize); + } + SHELL_FREE_NON_NULL (AsciiStrBuffer); + SHELL_FREE_NON_NULL (UscStrBuffer); + return Status; + } +} + +/** + Opens a new file relative to the source file's location. + + @param[in] This The protocol instance pointer. + @param[out] NewHandle Returns File Handle for FileName. + @param[in] FileName Null terminated string. "\", ".", and ".." are supported. + @param[in] OpenMode Open mode for file. + @param[in] Attributes Only used for EFI_FILE_MODE_CREATE. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_MEDIA_CHANGED The media has changed. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileOpen ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Open(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, NewHandle, FileName, OpenMode, Attributes); +} + +/** + Close and delete the file handle. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. + +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileDelete( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Delete(((EFI_FILE_PROTOCOL_FILE*)This)->Orig); + FreePool(This); + return (Status); +} + +/** + File style interface for File (Close). + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + + @retval EFI_SUCCESS The file was closed. +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileClose( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig); + FreePool(This); + return (Status); +} + +/** + File style interface for File (Write). + + If the file was opened with ASCII mode the data will be processed through + AsciiSPrint before writing. + + @param[in] This The pointer to the EFI_FILE_PROTOCOL object. + @param[in, out] BufferSize Size in bytes of Buffer. + @param[in] Buffer The pointer to the buffer to write. + + @retval EFI_SUCCESS The data was written. +**/ +EFI_STATUS +EFIAPI +FileInterfaceFileWrite( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + CHAR8 *AsciiBuffer; + UINTN Size; + EFI_STATUS Status; + if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) { + // + // Unicode + // + return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer)); + } else { + // + // Ascii + // + AsciiBuffer = AllocateZeroPool(*BufferSize); + AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer); + Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator) + Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer)); + FreePool(AsciiBuffer); + return (Status); + } +} + +/** + Create a file interface with unicode information. + + This will create a new EFI_FILE_PROTOCOL identical to the Templace + except that the new one has Unicode and Ascii knowledge. + + @param[in] Template A pointer to the EFI_FILE_PROTOCOL object. + @param[in] Unicode TRUE for UCS-2, FALSE for ASCII. + + @return a new EFI_FILE_PROTOCOL object to be used instead of the template. +**/ +EFI_FILE_PROTOCOL* +CreateFileInterfaceFile( + IN CONST EFI_FILE_PROTOCOL *Template, + IN CONST BOOLEAN Unicode + ) +{ + EFI_FILE_PROTOCOL_FILE *NewOne; + + NewOne = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE)); + if (NewOne == NULL) { + return (NULL); + } + CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE)); + NewOne->Orig = (EFI_FILE_PROTOCOL *)Template; + NewOne->Unicode = Unicode; + NewOne->Open = FileInterfaceFileOpen; + NewOne->Close = FileInterfaceFileClose; + NewOne->Delete = FileInterfaceFileDelete; + NewOne->Read = FileInterfaceFileRead; + NewOne->Write = FileInterfaceFileWrite; + NewOne->GetPosition = FileInterfaceFileGetPosition; + NewOne->SetPosition = FileInterfaceFileSetPosition; + NewOne->GetInfo = FileInterfaceFileGetInfo; + NewOne->SetInfo = FileInterfaceFileSetInfo; + NewOne->Flush = FileInterfaceFileFlush; + + return ((EFI_FILE_PROTOCOL *)NewOne); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.h new file mode 100644 index 0000000..b1bf7cd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/FileHandleWrappers.h @@ -0,0 +1,93 @@ +/** @file + EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables, StdIn, StdOut, StdErr, etc...) + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_FILE_HANDLE_WRAPPERS_HEADER_ +#define _SHELL_FILE_HANDLE_WRAPPERS_HEADER_ + +typedef struct { + LIST_ENTRY Link; + CHAR16* Buffer; +} SHELL_LINE_LIST; + +typedef struct { + UINTN LogCount; + SHELL_LINE_LIST *Log; +} SHELL_LINE_LOG; + +/// +/// FILE sytle interfaces for StdIn. +/// +extern EFI_FILE_PROTOCOL FileInterfaceStdIn; + +/// +/// FILE sytle interfaces for StdOut. +/// +extern EFI_FILE_PROTOCOL FileInterfaceStdOut; + +/// +/// FILE sytle interfaces for StdErr. +/// +extern EFI_FILE_PROTOCOL FileInterfaceStdErr; + +/// +/// FILE style interface for NUL file. +/// +extern EFI_FILE_PROTOCOL FileInterfaceNulFile; + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + environment variables through file operations. + + @param EnvName The name of the Environment Variable to be operated on. + + @retval NULL Memory could not be allocated. + @return other a pointer to an EFI_FILE_PROTOCOL structure +**/ +EFI_FILE_PROTOCOL* +CreateFileInterfaceEnv( + CONST CHAR16 *EnvName + ); + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + a file entirely in memory through file operations. + + @param[in] Unicode TRUE if the data is UNICODE, FALSE otherwise. + + @retval NULL Memory could not be allocated. + @return other a pointer to an EFI_FILE_PROTOCOL structure +**/ +EFI_FILE_PROTOCOL* +CreateFileInterfaceMem( + IN CONST BOOLEAN Unicode + ); + +/** + Creates a EFI_FILE_PROTOCOL (almost) object for using to access + a file entirely with unicode awareness through file operations. + + @param[in] Template The pointer to the handle to start with. + @param[in] Unicode TRUE if the data is UNICODE, FALSE otherwise. + + @retval NULL Memory could not be allocated. + @return other a pointer to an EFI_FILE_PROTOCOL structure +**/ +EFI_FILE_PROTOCOL* +CreateFileInterfaceFile( + IN CONST EFI_FILE_PROTOCOL *Template, + IN CONST BOOLEAN Unicode + ); + +#endif //_SHELL_FILE_HANDLE_WRAPPERS_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.c new file mode 100644 index 0000000..23e6b9c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.c @@ -0,0 +1,3189 @@ +/** @file + This is THE shell (application) + + Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
        + (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.
        + Copyright 2015-2018 Dell Technologies.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" + +// +// Initialize the global structure +// +SHELL_INFO ShellInfoObject = { + NULL, + NULL, + FALSE, + FALSE, + { + {{ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }}, + 0, + NULL, + NULL + }, + {{NULL, NULL}, NULL}, + { + {{NULL, NULL}, NULL}, + 0, + 0, + TRUE + }, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + {{NULL, NULL}, NULL, NULL}, + {{NULL, NULL}, NULL, NULL}, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE +}; + +STATIC CONST CHAR16 mScriptExtension[] = L".NSH"; +STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI"; +STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh"; +CONST CHAR16 mNoNestingEnvVarName[] = L"nonesting"; +CONST CHAR16 mNoNestingTrue[] = L"True"; +CONST CHAR16 mNoNestingFalse[] = L"False"; + +/** + Cleans off leading and trailing spaces and tabs. + + @param[in] String pointer to the string to trim them off. +**/ +EFI_STATUS +TrimSpaces( + IN CHAR16 **String + ) +{ + ASSERT(String != NULL); + ASSERT(*String!= NULL); + // + // Remove any spaces and tabs at the beginning of the (*String). + // + while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) { + CopyMem((*String), (*String)+1, StrSize((*String)) - sizeof((*String)[0])); + } + + // + // Remove any spaces and tabs at the end of the (*String). + // + while ((StrLen (*String) > 0) && (((*String)[StrLen((*String))-1] == L' ') || ((*String)[StrLen((*String))-1] == L'\t'))) { + (*String)[StrLen((*String))-1] = CHAR_NULL; + } + + return (EFI_SUCCESS); +} + +/** + Parse for the next instance of one string within another string. Can optionally make sure that + the string was not escaped (^ character) per the shell specification. + + @param[in] SourceString The string to search within + @param[in] FindString The string to look for + @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances +**/ +CHAR16* +FindNextInstance( + IN CONST CHAR16 *SourceString, + IN CONST CHAR16 *FindString, + IN CONST BOOLEAN CheckForEscapeCharacter + ) +{ + CHAR16 *Temp; + if (SourceString == NULL) { + return (NULL); + } + Temp = StrStr(SourceString, FindString); + + // + // If nothing found, or we don't care about escape characters + // + if (Temp == NULL || !CheckForEscapeCharacter) { + return (Temp); + } + + // + // If we found an escaped character, try again on the remainder of the string + // + if ((Temp > (SourceString)) && *(Temp-1) == L'^') { + return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter); + } + + // + // we found the right character + // + return (Temp); +} + +/** + Check whether the string between a pair of % is a valid environment variable name. + + @param[in] BeginPercent pointer to the first percent. + @param[in] EndPercent pointer to the last percent. + + @retval TRUE is a valid environment variable name. + @retval FALSE is NOT a valid environment variable name. +**/ +BOOLEAN +IsValidEnvironmentVariableName( + IN CONST CHAR16 *BeginPercent, + IN CONST CHAR16 *EndPercent + ) +{ + CONST CHAR16 *Walker; + + Walker = NULL; + + ASSERT (BeginPercent != NULL); + ASSERT (EndPercent != NULL); + ASSERT (BeginPercent < EndPercent); + + if ((BeginPercent + 1) == EndPercent) { + return FALSE; + } + + for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) { + if ( + (*Walker >= L'0' && *Walker <= L'9') || + (*Walker >= L'A' && *Walker <= L'Z') || + (*Walker >= L'a' && *Walker <= L'z') || + (*Walker == L'_') + ) { + if (Walker == BeginPercent + 1 && (*Walker >= L'0' && *Walker <= L'9')) { + return FALSE; + } else { + continue; + } + } else { + return FALSE; + } + } + + return TRUE; +} + +/** + Determine if a command line contains a split operation + + @param[in] CmdLine The command line to parse. + + @retval TRUE CmdLine has a valid split. + @retval FALSE CmdLine does not have a valid split. +**/ +BOOLEAN +ContainsSplit( + IN CONST CHAR16 *CmdLine + ) +{ + CONST CHAR16 *TempSpot; + CONST CHAR16 *FirstQuote; + CONST CHAR16 *SecondQuote; + + FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE); + SecondQuote = NULL; + TempSpot = FindFirstCharacter(CmdLine, L"|", L'^'); + + if (FirstQuote == NULL || + TempSpot == NULL || + TempSpot == CHAR_NULL || + FirstQuote > TempSpot + ) { + return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)); + } + + while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) { + if (FirstQuote == NULL || FirstQuote > TempSpot) { + break; + } + SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE); + if (SecondQuote == NULL) { + break; + } + if (SecondQuote < TempSpot) { + FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE); + continue; + } else { + FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE); + TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^'); + continue; + } + } + + return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)); +} + +/** + Function to start monitoring for CTRL-S using SimpleTextInputEx. This + feature's enabled state was not known when the shell initially launched. + + @retval EFI_SUCCESS The feature is enabled. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available. +**/ +EFI_STATUS +InternalEfiShellStartCtrlSMonitor( + VOID + ) +{ + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx; + EFI_KEY_DATA KeyData; + EFI_STATUS Status; + + Status = gBS->OpenProtocol( + gST->ConsoleInHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID**)&SimpleEx, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SHELL_NO_IN_EX), + ShellInfoObject.HiiHandle); + return (EFI_SUCCESS); + } + + KeyData.KeyState.KeyToggleState = 0; + KeyData.Key.ScanCode = 0; + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED; + KeyData.Key.UnicodeChar = L's'; + + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlSNotifyHandle1); + + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED; + if (!EFI_ERROR(Status)) { + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlSNotifyHandle2); + } + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED; + KeyData.Key.UnicodeChar = 19; + + if (!EFI_ERROR(Status)) { + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlSNotifyHandle3); + } + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED; + if (!EFI_ERROR(Status)) { + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlSNotifyHandle4); + } + return (Status); +} + + + +/** + The entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CHAR16 *TempString; + UINTN Size; + EFI_HANDLE ConInHandle; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *OldConIn; + SPLIT_LIST *Split; + + if (PcdGet8(PcdShellSupportLevel) > 3) { + return (EFI_UNSUPPORTED); + } + + // + // Clear the screen + // + Status = gST->ConOut->ClearScreen(gST->ConOut); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Populate the global structure from PCDs + // + ShellInfoObject.ImageDevPath = NULL; + ShellInfoObject.FileDevPath = NULL; + ShellInfoObject.PageBreakEnabled = PcdGetBool(PcdShellPageBreakDefault); + ShellInfoObject.ViewingSettings.InsertMode = PcdGetBool(PcdShellInsertModeDefault); + ShellInfoObject.LogScreenCount = PcdGet8 (PcdShellScreenLogCount ); + + // + // verify we dont allow for spec violation + // + ASSERT(ShellInfoObject.LogScreenCount >= 3); + + // + // Initialize the LIST ENTRY objects... + // + InitializeListHead(&ShellInfoObject.BufferToFreeList.Link); + InitializeListHead(&ShellInfoObject.ViewingSettings.CommandHistory.Link); + InitializeListHead(&ShellInfoObject.SplitList.Link); + + // + // Check PCDs for optional features that are not implemented yet. + // + if ( PcdGetBool(PcdShellSupportOldProtocols) + || !FeaturePcdGet(PcdShellRequireHiiPlatform) + || FeaturePcdGet(PcdShellSupportFrameworkHii) + ) { + return (EFI_UNSUPPORTED); + } + + // + // turn off the watchdog timer + // + gBS->SetWatchdogTimer (0, 0, 0, NULL); + + // + // install our console logger. This will keep a log of the output for back-browsing + // + Status = ConsoleLoggerInstall(ShellInfoObject.LogScreenCount, &ShellInfoObject.ConsoleInfo); + if (!EFI_ERROR(Status)) { + // + // Enable the cursor to be visible + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + // + // If supporting EFI 1.1 we need to install HII protocol + // only do this if PcdShellRequireHiiPlatform == FALSE + // + // remove EFI_UNSUPPORTED check above when complete. + ///@todo add support for Framework HII + + // + // install our (solitary) HII package + // + ShellInfoObject.HiiHandle = HiiAddPackages (&gEfiCallerIdGuid, gImageHandle, ShellStrings, NULL); + if (ShellInfoObject.HiiHandle == NULL) { + if (PcdGetBool(PcdShellSupportFrameworkHii)) { + ///@todo Add our package into Framework HII + } + if (ShellInfoObject.HiiHandle == NULL) { + Status = EFI_NOT_STARTED; + goto FreeResources; + } + } + + // + // create and install the EfiShellParametersProtocol + // + Status = CreatePopulateInstallShellParametersProtocol(&ShellInfoObject.NewShellParametersProtocol, &ShellInfoObject.RootShellInstance); + ASSERT_EFI_ERROR(Status); + ASSERT(ShellInfoObject.NewShellParametersProtocol != NULL); + + // + // create and install the EfiShellProtocol + // + Status = CreatePopulateInstallShellProtocol(&ShellInfoObject.NewEfiShellProtocol); + ASSERT_EFI_ERROR(Status); + ASSERT(ShellInfoObject.NewEfiShellProtocol != NULL); + + // + // Now initialize the shell library (it requires Shell Parameters protocol) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + Status = ShellInitEnvVarList (); + + // + // Check the command line + // + Status = ProcessCommandLine (); + if (EFI_ERROR (Status)) { + goto FreeResources; + } + + // + // If shell support level is >= 1 create the mappings and paths + // + if (PcdGet8(PcdShellSupportLevel) >= 1) { + Status = ShellCommandCreateInitialMappingsAndPaths(); + } + + // + // Set the environment variable for nesting support + // + Size = 0; + TempString = NULL; + if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) { + // + // No change. require nesting in Shell Protocol Execute() + // + StrnCatGrow(&TempString, + &Size, + L"False", + 0); + } else { + StrnCatGrow(&TempString, + &Size, + mNoNestingTrue, + 0); + } + Status = InternalEfiShellSetEnv(mNoNestingEnvVarName, TempString, TRUE); + SHELL_FREE_NON_NULL(TempString); + Size = 0; + + // + // save the device path for the loaded image and the device path for the filepath (under loaded image) + // These are where to look for the startup.nsh file + // + Status = GetDevicePathsForImageAndFile(&ShellInfoObject.ImageDevPath, &ShellInfoObject.FileDevPath); + ASSERT_EFI_ERROR(Status); + + // + // Display the version + // + if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion) { + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL), + ShellInfoObject.HiiHandle, + SupportLevel[PcdGet8(PcdShellSupportLevel)], + gEfiShellProtocol->MajorVersion, + gEfiShellProtocol->MinorVersion + ); + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER), + ShellInfoObject.HiiHandle, + (CHAR16 *) PcdGetPtr (PcdShellSupplier) + ); + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI), + ShellInfoObject.HiiHandle, + (gST->Hdr.Revision&0xffff0000)>>16, + (gST->Hdr.Revision&0x0000ffff), + gST->FirmwareVendor, + gST->FirmwareRevision + ); + } + + // + // Display the mapping + // + if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) { + Status = RunCommand(L"map"); + ASSERT_EFI_ERROR(Status); + } + + // + // init all the built in alias' + // + Status = SetBuiltInAlias(); + ASSERT_EFI_ERROR(Status); + + // + // Initialize environment variables + // + if (ShellCommandGetProfileList() != NULL) { + Status = InternalEfiShellSetEnv(L"profiles", ShellCommandGetProfileList(), TRUE); + ASSERT_EFI_ERROR(Status); + } + + Size = 100; + TempString = AllocateZeroPool(Size); + + UnicodeSPrint(TempString, Size, L"%d", PcdGet8(PcdShellSupportLevel)); + Status = InternalEfiShellSetEnv(L"uefishellsupport", TempString, TRUE); + ASSERT_EFI_ERROR(Status); + + UnicodeSPrint(TempString, Size, L"%d.%d", ShellInfoObject.NewEfiShellProtocol->MajorVersion, ShellInfoObject.NewEfiShellProtocol->MinorVersion); + Status = InternalEfiShellSetEnv(L"uefishellversion", TempString, TRUE); + ASSERT_EFI_ERROR(Status); + + UnicodeSPrint(TempString, Size, L"%d.%d", (gST->Hdr.Revision & 0xFFFF0000) >> 16, gST->Hdr.Revision & 0x0000FFFF); + Status = InternalEfiShellSetEnv(L"uefiversion", TempString, TRUE); + ASSERT_EFI_ERROR(Status); + + FreePool(TempString); + + if (!EFI_ERROR(Status)) { + if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) { + // + // Set up the event for CTRL-C monitoring... + // + Status = InernalEfiShellStartMonitor(); + } + + if (!EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { + // + // Set up the event for CTRL-S monitoring... + // + Status = InternalEfiShellStartCtrlSMonitor(); + } + + if (!EFI_ERROR(Status) && ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { + // + // close off the gST->ConIn + // + OldConIn = gST->ConIn; + ConInHandle = gST->ConsoleInHandle; + gST->ConIn = CreateSimpleTextInOnFile((SHELL_FILE_HANDLE)&FileInterfaceNulFile, &gST->ConsoleInHandle); + } else { + OldConIn = NULL; + ConInHandle = NULL; + } + + if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) { + // + // process the startup script or launch the called app. + // + Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath); + } + + if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { + // + // begin the UI waiting loop + // + do { + // + // clean out all the memory allocated for CONST * return values + // between each shell prompt presentation + // + if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){ + FreeBufferList(&ShellInfoObject.BufferToFreeList); + } + + // + // Reset page break back to default. + // + ShellInfoObject.PageBreakEnabled = PcdGetBool(PcdShellPageBreakDefault); + ASSERT (ShellInfoObject.ConsoleInfo != NULL); + ShellInfoObject.ConsoleInfo->Enabled = TRUE; + ShellInfoObject.ConsoleInfo->RowCounter = 0; + + // + // Display Prompt + // + Status = DoShellPrompt(); + } while (!ShellCommandGetExit()); + } + if (OldConIn != NULL && ConInHandle != NULL) { + CloseSimpleTextInOnFile (gST->ConIn); + gST->ConIn = OldConIn; + gST->ConsoleInHandle = ConInHandle; + } + } + } + +FreeResources: + // + // uninstall protocols / free memory / etc... + // + if (ShellInfoObject.UserBreakTimer != NULL) { + gBS->CloseEvent(ShellInfoObject.UserBreakTimer); + DEBUG_CODE(ShellInfoObject.UserBreakTimer = NULL;); + } + if (ShellInfoObject.ImageDevPath != NULL) { + FreePool(ShellInfoObject.ImageDevPath); + DEBUG_CODE(ShellInfoObject.ImageDevPath = NULL;); + } + if (ShellInfoObject.FileDevPath != NULL) { + FreePool(ShellInfoObject.FileDevPath); + DEBUG_CODE(ShellInfoObject.FileDevPath = NULL;); + } + if (ShellInfoObject.NewShellParametersProtocol != NULL) { + CleanUpShellParametersProtocol(ShellInfoObject.NewShellParametersProtocol); + DEBUG_CODE(ShellInfoObject.NewShellParametersProtocol = NULL;); + } + if (ShellInfoObject.NewEfiShellProtocol != NULL){ + if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){ + InternalEfiShellSetEnv(L"cwd", NULL, TRUE); + } + CleanUpShellEnvironment (ShellInfoObject.NewEfiShellProtocol); + DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;); + } + + if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){ + FreeBufferList(&ShellInfoObject.BufferToFreeList); + } + + if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){ + ASSERT(FALSE); ///@todo finish this de-allocation (free SplitStdIn/Out when needed). + + for ( Split = (SPLIT_LIST*)GetFirstNode (&ShellInfoObject.SplitList.Link) + ; !IsNull (&ShellInfoObject.SplitList.Link, &Split->Link) + ; Split = (SPLIT_LIST *)GetNextNode (&ShellInfoObject.SplitList.Link, &Split->Link) + ) { + RemoveEntryList (&Split->Link); + FreePool (Split); + } + + DEBUG_CODE (InitializeListHead (&ShellInfoObject.SplitList.Link);); + } + + if (ShellInfoObject.ShellInitSettings.FileName != NULL) { + FreePool(ShellInfoObject.ShellInitSettings.FileName); + DEBUG_CODE(ShellInfoObject.ShellInitSettings.FileName = NULL;); + } + + if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) { + FreePool(ShellInfoObject.ShellInitSettings.FileOptions); + DEBUG_CODE(ShellInfoObject.ShellInitSettings.FileOptions = NULL;); + } + + if (ShellInfoObject.HiiHandle != NULL) { + HiiRemovePackages(ShellInfoObject.HiiHandle); + DEBUG_CODE(ShellInfoObject.HiiHandle = NULL;); + } + + if (!IsListEmpty(&ShellInfoObject.ViewingSettings.CommandHistory.Link)){ + FreeBufferList(&ShellInfoObject.ViewingSettings.CommandHistory); + } + + ASSERT(ShellInfoObject.ConsoleInfo != NULL); + if (ShellInfoObject.ConsoleInfo != NULL) { + ConsoleLoggerUninstall(ShellInfoObject.ConsoleInfo); + FreePool(ShellInfoObject.ConsoleInfo); + DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;); + } + + ShellFreeEnvVarList (); + + if (ShellCommandGetExit()) { + return ((EFI_STATUS)ShellCommandGetExitCode()); + } + return (Status); +} + +/** + Sets all the alias' that were registered with the ShellCommandLib library. + + @retval EFI_SUCCESS all init commands were run successfully. +**/ +EFI_STATUS +SetBuiltInAlias( + VOID + ) +{ + EFI_STATUS Status; + CONST ALIAS_LIST *List; + ALIAS_LIST *Node; + + // + // Get all the commands we want to run + // + List = ShellCommandGetInitAliasList(); + + // + // for each command in the List + // + for ( Node = (ALIAS_LIST*)GetFirstNode(&List->Link) + ; !IsNull (&List->Link, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(&List->Link, &Node->Link) + ){ + // + // install the alias' + // + Status = InternalSetAlias(Node->CommandString, Node->Alias, TRUE); + ASSERT_EFI_ERROR(Status); + } + return (EFI_SUCCESS); +} + +/** + Internal function to determine if 2 command names are really the same. + + @param[in] Command1 The pointer to the first command name. + @param[in] Command2 The pointer to the second command name. + + @retval TRUE The 2 command names are the same. + @retval FALSE The 2 command names are not the same. +**/ +BOOLEAN +IsCommand( + IN CONST CHAR16 *Command1, + IN CONST CHAR16 *Command2 + ) +{ + if (StringNoCaseCompare(&Command1, &Command2) == 0) { + return (TRUE); + } + return (FALSE); +} + +/** + Internal function to determine if a command is a script only command. + + @param[in] CommandName The pointer to the command name. + + @retval TRUE The command is a script only command. + @retval FALSE The command is not a script only command. +**/ +BOOLEAN +IsScriptOnlyCommand( + IN CONST CHAR16 *CommandName + ) +{ + if (IsCommand(CommandName, L"for") + ||IsCommand(CommandName, L"endfor") + ||IsCommand(CommandName, L"if") + ||IsCommand(CommandName, L"else") + ||IsCommand(CommandName, L"endif") + ||IsCommand(CommandName, L"goto")) { + return (TRUE); + } + return (FALSE); +} + +/** + This function will populate the 2 device path protocol parameters based on the + global gImageHandle. The DevPath will point to the device path for the handle that has + loaded image protocol installed on it. The FilePath will point to the device path + for the file that was loaded. + + @param[in, out] DevPath On a successful return the device path to the loaded image. + @param[in, out] FilePath On a successful return the device path to the file. + + @retval EFI_SUCCESS The 2 device paths were successfully returned. + @retval other A error from gBS->HandleProtocol. + + @sa HandleProtocol +**/ +EFI_STATUS +GetDevicePathsForImageAndFile ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath, + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + + ASSERT(DevPath != NULL); + ASSERT(FilePath != NULL); + + Status = gBS->OpenProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&ImageDevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + *DevPath = DuplicateDevicePath (ImageDevicePath); + *FilePath = DuplicateDevicePath (LoadedImage->FilePath); + gBS->CloseProtocol( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + gImageHandle, + NULL); + } + gBS->CloseProtocol( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + gImageHandle, + NULL); + } + return (Status); +} + +/** + Process all Uefi Shell 2.0 command line options. + + see Uefi Shell 2.0 section 3.2 for full details. + + the command line must resemble the following: + + shell.efi [ShellOpt-options] [options] [file-name [file-name-options]] + + ShellOpt-options Options which control the initialization behavior of the shell. + These options are read from the EFI global variable "ShellOpt" + and are processed before options or file-name. + + options Options which control the initialization behavior of the shell. + + file-name The name of a UEFI shell application or script to be executed + after initialization is complete. By default, if file-name is + specified, then -nostartup is implied. Scripts are not supported + by level 0. + + file-name-options The command-line options that are passed to file-name when it + is invoked. + + This will initialize the ShellInfoObject.ShellInitSettings global variable. + + @retval EFI_SUCCESS The variable is initialized. +**/ +EFI_STATUS +ProcessCommandLine( + VOID + ) +{ + UINTN Size; + UINTN LoopVar; + CHAR16 *CurrentArg; + CHAR16 *DelayValueStr; + UINT64 DelayValue; + EFI_STATUS Status; + EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation; + + // `file-name-options` will contain arguments to `file-name` that we don't + // know about. This would cause ShellCommandLineParse to error, so we parse + // arguments manually, ignoring those after the first thing that doesn't look + // like a shell option (which is assumed to be `file-name`). + + Status = gBS->LocateProtocol ( + &gEfiUnicodeCollation2ProtocolGuid, + NULL, + (VOID **) &UnicodeCollation + ); + if (EFI_ERROR (Status)) { + Status = gBS->LocateProtocol ( + &gEfiUnicodeCollationProtocolGuid, + NULL, + (VOID **) &UnicodeCollation + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // Set default options + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = FALSE; + ShellInfoObject.ShellInitSettings.Delay = 5; + + // + // Start LoopVar at 0 to parse only optional arguments at Argv[0] + // and parse other parameters from Argv[1]. This is for use case that + // UEFI Shell boot option is created, and OptionalData is provided + // that starts with shell command-line options. + // + for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + CurrentArg = gEfiShellParametersProtocol->Argv[LoopVar]; + if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-startup", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nostartup", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-noconsoleout", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-noconsolein", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nointerrupt", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nomap", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-noversion", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nonest", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-delay", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = TRUE; + // Check for optional delay value following "-delay" + if ((LoopVar + 1) >= gEfiShellParametersProtocol->Argc) { + DelayValueStr = NULL; + } else { + DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1]; + } + if (DelayValueStr != NULL){ + if (*DelayValueStr == L':') { + DelayValueStr++; + } + if (!EFI_ERROR(ShellConvertStringToUint64 ( + DelayValueStr, + &DelayValue, + FALSE, + FALSE + ))) { + ShellInfoObject.ShellInitSettings.Delay = (UINTN)DelayValue; + LoopVar++; + } + } + } else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-exit", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE; + } else if (StrnCmp (L"-", CurrentArg, 1) == 0) { + // Unrecognized option + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_GEN_PROBLEM), + ShellInfoObject.HiiHandle, + CurrentArg + ); + return EFI_INVALID_PARAMETER; + } else { + // + // First argument should be Shell.efi image name + // + if (LoopVar == 0) { + continue; + } + + ShellInfoObject.ShellInitSettings.FileName = NULL; + Size = 0; + // + // If first argument contains a space, then add double quotes before the argument + // + if (StrStr (CurrentArg, L" ") != NULL) { + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0); + if (ShellInfoObject.ShellInitSettings.FileName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + } + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, CurrentArg, 0); + if (ShellInfoObject.ShellInitSettings.FileName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + // + // If first argument contains a space, then add double quotes after the argument + // + if (StrStr (CurrentArg, L" ") != NULL) { + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0); + if (ShellInfoObject.ShellInitSettings.FileName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + } + // + // We found `file-name`. + // + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; + LoopVar++; + + // Add `file-name-options` + for (Size = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL)); + // + // Add a space between arguments + // + if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) { + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, &Size, L" ", 0); + if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { + SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); + return (EFI_OUT_OF_RESOURCES); + } + } + // + // If an argumnent contains a space, then add double quotes before the argument + // + if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) { + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, + &Size, + L"\"", + 0); + if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { + SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); + return (EFI_OUT_OF_RESOURCES); + } + } + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, + &Size, + gEfiShellParametersProtocol->Argv[LoopVar], + 0); + if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { + SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); + return (EFI_OUT_OF_RESOURCES); + } + // + // If an argumnent contains a space, then add double quotes after the argument + // + if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) { + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, + &Size, + L"\"", + 0); + if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { + SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); + return (EFI_OUT_OF_RESOURCES); + } + } + } + } + } + + // "-nointerrupt" overrides "-delay" + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) { + ShellInfoObject.ShellInitSettings.Delay = 0; + } + + return EFI_SUCCESS; +} + +/** + Function try to find location of the Startup.nsh file. + + The buffer is callee allocated and should be freed by the caller. + + @param ImageDevicePath The path to the image for shell. first place to look for the startup script + @param FileDevicePath The path to the file for shell. second place to look for the startup script. + + @retval NULL No Startup.nsh file was found. + @return !=NULL Pointer to NULL-terminated path. +**/ +CHAR16 * +LocateStartupScript ( + IN EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *FileDevicePath + ) +{ + CHAR16 *StartupScriptPath; + CHAR16 *TempSpot; + CONST CHAR16 *MapName; + UINTN Size; + + StartupScriptPath = NULL; + Size = 0; + + // + // Try to find 'Startup.nsh' in the directory where the shell itself was launched. + // + MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath (&ImageDevicePath); + if (MapName != NULL) { + StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, MapName, 0); + if (StartupScriptPath == NULL) { + // + // Do not locate the startup script in sys path when out of resource. + // + return NULL; + } + TempSpot = StrStr (StartupScriptPath, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + + InternalEfiShellSetEnv(L"homefilesystem", StartupScriptPath, TRUE); + + StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, ((FILEPATH_DEVICE_PATH *)FileDevicePath)->PathName, 0); + PathRemoveLastItem (StartupScriptPath); + StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, mStartupScript, 0); + } + + // + // Try to find 'Startup.nsh' in the execution path defined by the envrionment variable PATH. + // + if ((StartupScriptPath == NULL) || EFI_ERROR (ShellIsFile (StartupScriptPath))) { + SHELL_FREE_NON_NULL (StartupScriptPath); + StartupScriptPath = ShellFindFilePath (mStartupScript); + } + + return StartupScriptPath; +} + +/** + Handles all interaction with the default startup script. + + this will check that the correct command line parameters were passed, handle the delay, and then start running the script. + + @param ImagePath the path to the image for shell. first place to look for the startup script + @param FilePath the path to the file for shell. second place to look for the startup script. + + @retval EFI_SUCCESS the variable is initialized. +**/ +EFI_STATUS +DoStartupScript( + IN EFI_DEVICE_PATH_PROTOCOL *ImagePath, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + EFI_STATUS Status; + EFI_STATUS CalleeStatus; + UINTN Delay; + EFI_INPUT_KEY Key; + CHAR16 *FileStringPath; + CHAR16 *FullFileStringPath; + UINTN NewSize; + + Key.UnicodeChar = CHAR_NULL; + Key.ScanCode = 0; + + if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && ShellInfoObject.ShellInitSettings.FileName != NULL) { + // + // launch something else instead + // + NewSize = StrSize(ShellInfoObject.ShellInitSettings.FileName); + if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) { + NewSize += StrSize(ShellInfoObject.ShellInitSettings.FileOptions) + sizeof(CHAR16); + } + FileStringPath = AllocateZeroPool(NewSize); + if (FileStringPath == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + StrCpyS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileName); + if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) { + StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1); + StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1); + } + Status = RunShellCommand(FileStringPath, &CalleeStatus); + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) { + ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (UINT64)CalleeStatus); + } + FreePool(FileStringPath); + return (Status); + + } + + // + // for shell level 0 we do no scripts + // Without the Startup bit overriding we allow for nostartup to prevent scripts + // + if ( (PcdGet8(PcdShellSupportLevel) < 1) + || (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup) + ){ + return (EFI_SUCCESS); + } + + gST->ConOut->EnableCursor(gST->ConOut, FALSE); + // + // print out our warning and see if they press a key + // + for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay + ; Delay != 0 && EFI_ERROR(Status) + ; Delay-- + ){ + ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay); + gBS->Stall (1000000); + if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + } + } + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle); + gST->ConOut->EnableCursor(gST->ConOut, TRUE); + + // + // ESC was pressed + // + if (Status == EFI_SUCCESS && Key.UnicodeChar == 0 && Key.ScanCode == SCAN_ESC) { + return (EFI_SUCCESS); + } + + FileStringPath = LocateStartupScript (ImagePath, FilePath); + if (FileStringPath != NULL) { + FullFileStringPath = FullyQualifyPath(FileStringPath); + if (FullFileStringPath == NULL) { + Status = RunScriptFile (FileStringPath, NULL, FileStringPath, ShellInfoObject.NewShellParametersProtocol); + } else { + Status = RunScriptFile (FullFileStringPath, NULL, FullFileStringPath, ShellInfoObject.NewShellParametersProtocol); + FreePool(FullFileStringPath); + } + FreePool (FileStringPath); + } else { + // + // we return success since startup script is not mandatory. + // + Status = EFI_SUCCESS; + } + + return (Status); +} + +/** + Function to perform the shell prompt looping. It will do a single prompt, + dispatch the result, and then return. It is expected that the caller will + call this function in a loop many times. + + @retval EFI_SUCCESS + @retval RETURN_ABORTED +**/ +EFI_STATUS +DoShellPrompt ( + VOID + ) +{ + UINTN Column; + UINTN Row; + CHAR16 *CmdLine; + CONST CHAR16 *CurDir; + UINTN BufferSize; + EFI_STATUS Status; + LIST_ENTRY OldBufferList; + + CurDir = NULL; + + // + // Get screen setting to decide size of the command line buffer + // + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Column, &Row); + BufferSize = Column * Row * sizeof (CHAR16); + CmdLine = AllocateZeroPool (BufferSize); + if (CmdLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SaveBufferList(&OldBufferList); + CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd"); + + // + // Prompt for input + // + gST->ConOut->SetCursorPosition (gST->ConOut, 0, gST->ConOut->Mode->CursorRow); + + if (CurDir != NULL && StrLen(CurDir) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle); + } + + // + // Read a line from the console + // + Status = ShellInfoObject.NewEfiShellProtocol->ReadFile(ShellInfoObject.NewShellParametersProtocol->StdIn, &BufferSize, CmdLine); + + // + // Null terminate the string and parse it + // + if (!EFI_ERROR (Status)) { + // + // Reset the CTRL-C event just before running the command (yes we ignore the return values) + // + Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak); + + CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL; + Status = RunCommand(CmdLine); + } + + // + // Done with this command + // + RestoreBufferList(&OldBufferList); + FreePool (CmdLine); + return Status; +} + +/** + Add a buffer to the Buffer To Free List for safely returning buffers to other + places without risking letting them modify internal shell information. + + @param Buffer Something to pass to FreePool when the shell is exiting. +**/ +VOID* +AddBufferToFreeList ( + VOID *Buffer + ) +{ + BUFFER_LIST *BufferListEntry; + + if (Buffer == NULL) { + return (NULL); + } + + BufferListEntry = AllocateZeroPool (sizeof (BUFFER_LIST)); + if (BufferListEntry == NULL) { + return NULL; + } + + BufferListEntry->Buffer = Buffer; + InsertTailList (&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link); + return (Buffer); +} + + +/** + Create a new buffer list and stores the old one to OldBufferList + + @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList. +**/ +VOID +SaveBufferList ( + OUT LIST_ENTRY *OldBufferList + ) +{ + CopyMem (OldBufferList, &ShellInfoObject.BufferToFreeList.Link, sizeof (LIST_ENTRY)); + InitializeListHead (&ShellInfoObject.BufferToFreeList.Link); +} + +/** + Restore previous nodes into BufferToFreeList . + + @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList. +**/ +VOID +RestoreBufferList ( + IN OUT LIST_ENTRY *OldBufferList + ) +{ + FreeBufferList (&ShellInfoObject.BufferToFreeList); + CopyMem (&ShellInfoObject.BufferToFreeList.Link, OldBufferList, sizeof (LIST_ENTRY)); +} + + +/** + Add a buffer to the Line History List + + @param Buffer The line buffer to add. +**/ +VOID +AddLineToCommandHistory( + IN CONST CHAR16 *Buffer + ) +{ + BUFFER_LIST *Node; + BUFFER_LIST *Walker; + UINT16 MaxHistoryCmdCount; + UINT16 Count; + + Count = 0; + MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount); + + if (MaxHistoryCmdCount == 0) { + return ; + } + + + Node = AllocateZeroPool(sizeof(BUFFER_LIST)); + if (Node == NULL) { + return; + } + + Node->Buffer = AllocateCopyPool (StrSize (Buffer), Buffer); + if (Node->Buffer == NULL) { + FreePool (Node); + return; + } + + for ( Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link) + ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link) + ; Walker = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link) + ){ + Count++; + } + if (Count < MaxHistoryCmdCount){ + InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link); + } else { + Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link); + RemoveEntryList(&Walker->Link); + if (Walker->Buffer != NULL) { + FreePool(Walker->Buffer); + } + FreePool(Walker); + InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link); + } +} + +/** + Checks if a string is an alias for another command. If yes, then it replaces the alias name + with the correct command name. + + @param[in, out] CommandString Upon entry the potential alias. Upon return the + command name if it was an alias. If it was not + an alias it will be unchanged. This function may + change the buffer to fit the command name. + + @retval EFI_SUCCESS The name was changed. + @retval EFI_SUCCESS The name was not an alias. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +ShellConvertAlias( + IN OUT CHAR16 **CommandString + ) +{ + CONST CHAR16 *NewString; + + NewString = ShellInfoObject.NewEfiShellProtocol->GetAlias(*CommandString, NULL); + if (NewString == NULL) { + return (EFI_SUCCESS); + } + FreePool(*CommandString); + *CommandString = AllocateCopyPool(StrSize(NewString), NewString); + if (*CommandString == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + return (EFI_SUCCESS); +} + +/** + This function will eliminate unreplaced (and therefore non-found) environment variables. + + @param[in,out] CmdLine The command line to update. +**/ +EFI_STATUS +StripUnreplacedEnvironmentVariables( + IN OUT CHAR16 *CmdLine + ) +{ + CHAR16 *FirstPercent; + CHAR16 *FirstQuote; + CHAR16 *SecondPercent; + CHAR16 *SecondQuote; + CHAR16 *CurrentLocator; + + for (CurrentLocator = CmdLine ; CurrentLocator != NULL ; ) { + FirstQuote = FindNextInstance(CurrentLocator, L"\"", TRUE); + FirstPercent = FindNextInstance(CurrentLocator, L"%", TRUE); + SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL; + if (FirstPercent == NULL || SecondPercent == NULL) { + // + // If we ever don't have 2 % we are done. + // + break; + } + + if (FirstQuote!= NULL && FirstQuote < FirstPercent) { + SecondQuote = FindNextInstance(FirstQuote+1, L"\"", TRUE); + // + // Quote is first found + // + + if (SecondQuote < FirstPercent) { + // + // restart after the pair of " + // + CurrentLocator = SecondQuote + 1; + } else /* FirstPercent < SecondQuote */{ + // + // Restart on the first percent + // + CurrentLocator = FirstPercent; + } + continue; + } + + if (FirstQuote == NULL || SecondPercent < FirstQuote) { + if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) { + // + // We need to remove from FirstPercent to SecondPercent + // + CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1)); + // + // don't need to update the locator. both % characters are gone. + // + } else { + CurrentLocator = SecondPercent + 1; + } + continue; + } + CurrentLocator = FirstQuote; + } + return (EFI_SUCCESS); +} + +/** + Function allocates a new command line and replaces all instances of environment + variable names that are correctly preset to their values. + + If the return value is not NULL the memory must be caller freed. + + @param[in] OriginalCommandLine The original command line + + @retval NULL An error occurred. + @return The new command line with no environment variables present. +**/ +CHAR16* +ShellConvertVariables ( + IN CONST CHAR16 *OriginalCommandLine + ) +{ + CONST CHAR16 *MasterEnvList; + UINTN NewSize; + CHAR16 *NewCommandLine1; + CHAR16 *NewCommandLine2; + CHAR16 *Temp; + UINTN ItemSize; + CHAR16 *ItemTemp; + SCRIPT_FILE *CurrentScriptFile; + ALIAS_LIST *AliasListNode; + + ASSERT(OriginalCommandLine != NULL); + + ItemSize = 0; + NewSize = StrSize(OriginalCommandLine); + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + Temp = NULL; + + ///@todo update this to handle the %0 - %9 for scripting only (borrow from line 1256 area) ? ? ? + + // + // calculate the size required for the post-conversion string... + // + if (CurrentScriptFile != NULL) { + for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList) + ; !IsNull(&CurrentScriptFile->SubstList, &AliasListNode->Link) + ; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link) + ){ + for (Temp = StrStr(OriginalCommandLine, AliasListNode->Alias) + ; Temp != NULL + ; Temp = StrStr(Temp+1, AliasListNode->Alias) + ){ + // + // we need a preceding and if there is space no ^ preceding (if no space ignore) + // + if ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2)) { + NewSize += StrSize(AliasListNode->CommandString); + } + } + } + } + + for (MasterEnvList = EfiShellGetEnv(NULL) + ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL + ; MasterEnvList += StrLen(MasterEnvList) + 1 + ){ + if (StrSize(MasterEnvList) > ItemSize) { + ItemSize = StrSize(MasterEnvList); + } + for (Temp = StrStr(OriginalCommandLine, MasterEnvList) + ; Temp != NULL + ; Temp = StrStr(Temp+1, MasterEnvList) + ){ + // + // we need a preceding and following % and if there is space no ^ preceding (if no space ignore) + // + if (*(Temp-1) == L'%' && *(Temp+StrLen(MasterEnvList)) == L'%' && + ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2))) { + NewSize+=StrSize(EfiShellGetEnv(MasterEnvList)); + } + } + } + + // + // now do the replacements... + // + NewCommandLine1 = AllocateZeroPool (NewSize); + NewCommandLine2 = AllocateZeroPool(NewSize); + ItemTemp = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16))); + if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) { + SHELL_FREE_NON_NULL(NewCommandLine1); + SHELL_FREE_NON_NULL(NewCommandLine2); + SHELL_FREE_NON_NULL(ItemTemp); + return (NULL); + } + CopyMem (NewCommandLine1, OriginalCommandLine, StrSize (OriginalCommandLine)); + + for (MasterEnvList = EfiShellGetEnv(NULL) + ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL + ; MasterEnvList += StrLen(MasterEnvList) + 1 + ){ + StrCpyS( ItemTemp, + ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), + L"%" + ); + StrCatS( ItemTemp, + ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), + MasterEnvList + ); + StrCatS( ItemTemp, + ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), + L"%" + ); + ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE); + StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2); + } + if (CurrentScriptFile != NULL) { + for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList) + ; !IsNull(&CurrentScriptFile->SubstList, &AliasListNode->Link) + ; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link) + ){ + ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE); + StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2); + } + } + + // + // Remove non-existent environment variables + // + StripUnreplacedEnvironmentVariables(NewCommandLine1); + + // + // Now cleanup any straggler intentionally ignored "%" characters + // + ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE); + StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2); + + FreePool(NewCommandLine2); + FreePool(ItemTemp); + + return (NewCommandLine1); +} + +/** + Internal function to run a command line with pipe usage. + + @param[in] CmdLine The pointer to the command line. + @param[in] StdIn The pointer to the Standard input. + @param[in] StdOut The pointer to the Standard output. + + @retval EFI_SUCCESS The split command is executed successfully. + @retval other Some error occurs when executing the split command. +**/ +EFI_STATUS +RunSplitCommand( + IN CONST CHAR16 *CmdLine, + IN SHELL_FILE_HANDLE StdIn, + IN SHELL_FILE_HANDLE StdOut + ) +{ + EFI_STATUS Status; + CHAR16 *NextCommandLine; + CHAR16 *OurCommandLine; + UINTN Size1; + UINTN Size2; + SPLIT_LIST *Split; + SHELL_FILE_HANDLE TempFileHandle; + BOOLEAN Unicode; + + ASSERT(StdOut == NULL); + + ASSERT(StrStr(CmdLine, L"|") != NULL); + + Status = EFI_SUCCESS; + NextCommandLine = NULL; + OurCommandLine = NULL; + Size1 = 0; + Size2 = 0; + + NextCommandLine = StrnCatGrow(&NextCommandLine, &Size1, StrStr(CmdLine, L"|")+1, 0); + OurCommandLine = StrnCatGrow(&OurCommandLine , &Size2, CmdLine , StrStr(CmdLine, L"|") - CmdLine); + + if (NextCommandLine == NULL || OurCommandLine == NULL) { + SHELL_FREE_NON_NULL(OurCommandLine); + SHELL_FREE_NON_NULL(NextCommandLine); + return (EFI_OUT_OF_RESOURCES); + } else if (StrStr(OurCommandLine, L"|") != NULL || Size1 == 0 || Size2 == 0) { + SHELL_FREE_NON_NULL(OurCommandLine); + SHELL_FREE_NON_NULL(NextCommandLine); + return (EFI_INVALID_PARAMETER); + } else if (NextCommandLine[0] == L'a' && + (NextCommandLine[1] == L' ' || NextCommandLine[1] == CHAR_NULL) + ){ + CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0])); + while (NextCommandLine[0] == L' ') { + CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0])); + } + if (NextCommandLine[0] == CHAR_NULL) { + SHELL_FREE_NON_NULL(OurCommandLine); + SHELL_FREE_NON_NULL(NextCommandLine); + return (EFI_INVALID_PARAMETER); + } + Unicode = FALSE; + } else { + Unicode = TRUE; + } + + + // + // make a SPLIT_LIST item and add to list + // + Split = AllocateZeroPool(sizeof(SPLIT_LIST)); + if (Split == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Split->SplitStdIn = StdIn; + Split->SplitStdOut = ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode), NULL); + ASSERT(Split->SplitStdOut != NULL); + InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link); + + Status = RunCommand(OurCommandLine); + + // + // move the output from the first to the in to the second. + // + TempFileHandle = Split->SplitStdOut; + if (Split->SplitStdIn == StdIn) { + Split->SplitStdOut = NULL; + } else { + Split->SplitStdOut = Split->SplitStdIn; + } + Split->SplitStdIn = TempFileHandle; + ShellInfoObject.NewEfiShellProtocol->SetFilePosition (Split->SplitStdIn, 0); + + if (!EFI_ERROR(Status)) { + Status = RunCommand(NextCommandLine); + } + + // + // remove the top level from the ScriptList + // + ASSERT((SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link) == Split); + RemoveEntryList(&Split->Link); + + // + // Note that the original StdIn is now the StdOut... + // + if (Split->SplitStdOut != NULL) { + ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdOut); + } + if (Split->SplitStdIn != NULL) { + ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdIn); + } + + FreePool(Split); + FreePool(NextCommandLine); + FreePool(OurCommandLine); + + return (Status); +} + +/** + Take the original command line, substitute any variables, free + the original string, return the modified copy. + + @param[in] CmdLine pointer to the command line to update. + + @retval EFI_SUCCESS the function was successful. + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. +**/ +EFI_STATUS +ShellSubstituteVariables( + IN CHAR16 **CmdLine + ) +{ + CHAR16 *NewCmdLine; + NewCmdLine = ShellConvertVariables(*CmdLine); + SHELL_FREE_NON_NULL(*CmdLine); + if (NewCmdLine == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + *CmdLine = NewCmdLine; + return (EFI_SUCCESS); +} + +/** + Take the original command line, substitute any alias in the first group of space delimited characters, free + the original string, return the modified copy. + + @param[in] CmdLine pointer to the command line to update. + + @retval EFI_SUCCESS the function was successful. + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. +**/ +EFI_STATUS +ShellSubstituteAliases( + IN CHAR16 **CmdLine + ) +{ + CHAR16 *NewCmdLine; + CHAR16 *CommandName; + EFI_STATUS Status; + UINTN PostAliasSize; + ASSERT(CmdLine != NULL); + ASSERT(*CmdLine!= NULL); + + + CommandName = NULL; + if (StrStr((*CmdLine), L" ") == NULL){ + StrnCatGrow(&CommandName, NULL, (*CmdLine), 0); + } else { + StrnCatGrow(&CommandName, NULL, (*CmdLine), StrStr((*CmdLine), L" ") - (*CmdLine)); + } + + // + // This cannot happen 'inline' since the CmdLine can need extra space. + // + NewCmdLine = NULL; + if (!ShellCommandIsCommandOnList(CommandName)) { + // + // Convert via alias + // + Status = ShellConvertAlias(&CommandName); + if (EFI_ERROR(Status)){ + return (Status); + } + PostAliasSize = 0; + NewCmdLine = StrnCatGrow(&NewCmdLine, &PostAliasSize, CommandName, 0); + if (NewCmdLine == NULL) { + SHELL_FREE_NON_NULL(CommandName); + SHELL_FREE_NON_NULL(*CmdLine); + return (EFI_OUT_OF_RESOURCES); + } + NewCmdLine = StrnCatGrow(&NewCmdLine, &PostAliasSize, StrStr((*CmdLine), L" "), 0); + if (NewCmdLine == NULL) { + SHELL_FREE_NON_NULL(CommandName); + SHELL_FREE_NON_NULL(*CmdLine); + return (EFI_OUT_OF_RESOURCES); + } + } else { + NewCmdLine = StrnCatGrow(&NewCmdLine, NULL, (*CmdLine), 0); + } + + SHELL_FREE_NON_NULL(*CmdLine); + SHELL_FREE_NON_NULL(CommandName); + + // + // re-assign the passed in double pointer to point to our newly allocated buffer + // + *CmdLine = NewCmdLine; + + return (EFI_SUCCESS); +} + +/** + Takes the Argv[0] part of the command line and determine the meaning of it. + + @param[in] CmdName pointer to the command line to update. + + @retval Internal_Command The name is an internal command. + @retval File_Sys_Change the name is a file system change. + @retval Script_File_Name the name is a NSH script file. + @retval Unknown_Invalid the name is unknown. + @retval Efi_Application the name is an application (.EFI). +**/ +SHELL_OPERATION_TYPES +GetOperationType( + IN CONST CHAR16 *CmdName + ) +{ + CHAR16* FileWithPath; + CONST CHAR16* TempLocation; + CONST CHAR16* TempLocation2; + + FileWithPath = NULL; + // + // test for an internal command. + // + if (ShellCommandIsCommandOnList(CmdName)) { + return (Internal_Command); + } + + // + // Test for file system change request. anything ending with first : and cant have spaces. + // + if (CmdName[(StrLen(CmdName)-1)] == L':') { + if ( StrStr(CmdName, L" ") != NULL + || StrLen(StrStr(CmdName, L":")) > 1 + ) { + return (Unknown_Invalid); + } + return (File_Sys_Change); + } + + // + // Test for a file + // + if ((FileWithPath = ShellFindFilePathEx(CmdName, mExecutableExtensions)) != NULL) { + // + // See if that file has a script file extension + // + if (StrLen(FileWithPath) > 4) { + TempLocation = FileWithPath+StrLen(FileWithPath)-4; + TempLocation2 = mScriptExtension; + if (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0) { + SHELL_FREE_NON_NULL(FileWithPath); + return (Script_File_Name); + } + } + + // + // Was a file, but not a script. we treat this as an application. + // + SHELL_FREE_NON_NULL(FileWithPath); + return (Efi_Application); + } + + SHELL_FREE_NON_NULL(FileWithPath); + // + // No clue what this is... return invalid flag... + // + return (Unknown_Invalid); +} + +/** + Determine if the first item in a command line is valid. + + @param[in] CmdLine The command line to parse. + + @retval EFI_SUCCESS The item is valid. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_NOT_FOUND The operation type is unknown or invalid. +**/ +EFI_STATUS +IsValidSplit( + IN CONST CHAR16 *CmdLine + ) +{ + CHAR16 *Temp; + CHAR16 *FirstParameter; + CHAR16 *TempWalker; + EFI_STATUS Status; + + Temp = NULL; + + Temp = StrnCatGrow(&Temp, NULL, CmdLine, 0); + if (Temp == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + FirstParameter = StrStr(Temp, L"|"); + if (FirstParameter != NULL) { + *FirstParameter = CHAR_NULL; + } + + FirstParameter = NULL; + + // + // Process the command line + // + Status = ProcessCommandLineToFinal(&Temp); + + if (!EFI_ERROR(Status)) { + FirstParameter = AllocateZeroPool(StrSize(CmdLine)); + if (FirstParameter == NULL) { + SHELL_FREE_NON_NULL(Temp); + return (EFI_OUT_OF_RESOURCES); + } + TempWalker = (CHAR16*)Temp; + if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine), TRUE))) { + if (GetOperationType(FirstParameter) == Unknown_Invalid) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); + Status = EFI_NOT_FOUND; + } + } + } + + SHELL_FREE_NON_NULL(Temp); + SHELL_FREE_NON_NULL(FirstParameter); + return Status; +} + +/** + Determine if a command line contains with a split contains only valid commands. + + @param[in] CmdLine The command line to parse. + + @retval EFI_SUCCESS CmdLine has only valid commands, application, or has no split. + @retval EFI_ABORTED CmdLine has at least one invalid command or application. +**/ +EFI_STATUS +VerifySplit( + IN CONST CHAR16 *CmdLine + ) +{ + CONST CHAR16 *TempSpot; + EFI_STATUS Status; + + // + // If this was the only item, then get out + // + if (!ContainsSplit(CmdLine)) { + return (EFI_SUCCESS); + } + + // + // Verify up to the pipe or end character + // + Status = IsValidSplit(CmdLine); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // recurse to verify the next item + // + TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1; + if (*TempSpot == L'a' && + (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL) + ) { + // If it's an ASCII pipe '|a' + TempSpot += 1; + } + + return (VerifySplit(TempSpot)); +} + +/** + Process a split based operation. + + @param[in] CmdLine pointer to the command line to process + + @retval EFI_SUCCESS The operation was successful + @return an error occurred. +**/ +EFI_STATUS +ProcessNewSplitCommandLine( + IN CONST CHAR16 *CmdLine + ) +{ + SPLIT_LIST *Split; + EFI_STATUS Status; + + Status = VerifySplit(CmdLine); + if (EFI_ERROR(Status)) { + return (Status); + } + + Split = NULL; + + // + // are we in an existing split??? + // + if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { + Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); + } + + if (Split == NULL) { + Status = RunSplitCommand(CmdLine, NULL, NULL); + } else { + Status = RunSplitCommand(CmdLine, Split->SplitStdIn, Split->SplitStdOut); + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine); + } + return (Status); +} + +/** + Handle a request to change the current file system. + + @param[in] CmdLine The passed in command line. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ChangeMappedDrive( + IN CONST CHAR16 *CmdLine + ) +{ + EFI_STATUS Status; + Status = EFI_SUCCESS; + + // + // make sure we are the right operation + // + ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL); + + // + // Call the protocol API to do the work + // + Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, CmdLine); + + // + // Report any errors + // + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, CmdLine); + } + + return (Status); +} + +/** + Reprocess the command line to direct all -? to the help command. + + if found, will add "help" as argv[0], and move the rest later. + + @param[in,out] CmdLine pointer to the command line to update +**/ +EFI_STATUS +DoHelpUpdate( + IN OUT CHAR16 **CmdLine + ) +{ + CHAR16 *CurrentParameter; + CHAR16 *Walker; + CHAR16 *NewCommandLine; + EFI_STATUS Status; + UINTN NewCmdLineSize; + + Status = EFI_SUCCESS; + + CurrentParameter = AllocateZeroPool(StrSize(*CmdLine)); + if (CurrentParameter == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + Walker = *CmdLine; + while(Walker != NULL && *Walker != CHAR_NULL) { + if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine), TRUE))) { + if (StrStr(CurrentParameter, L"-?") == CurrentParameter) { + CurrentParameter[0] = L' '; + CurrentParameter[1] = L' '; + NewCmdLineSize = StrSize(L"help ") + StrSize(*CmdLine); + NewCommandLine = AllocateZeroPool(NewCmdLineSize); + if (NewCommandLine == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + // + // We know the space is sufficient since we just calculated it. + // + StrnCpyS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), L"help ", 5); + StrnCatS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), *CmdLine, StrLen(*CmdLine)); + SHELL_FREE_NON_NULL(*CmdLine); + *CmdLine = NewCommandLine; + break; + } + } + } + + SHELL_FREE_NON_NULL(CurrentParameter); + + return (Status); +} + +/** + Function to update the shell variable "lasterror". + + @param[in] ErrorCode the error code to put into lasterror. +**/ +EFI_STATUS +SetLastError( + IN CONST SHELL_STATUS ErrorCode + ) +{ + CHAR16 LeString[19]; + if (sizeof(EFI_STATUS) == sizeof(UINT64)) { + UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ErrorCode); + } else { + UnicodeSPrint(LeString, sizeof(LeString), L"0x%x", ErrorCode); + } + DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE);); + InternalEfiShellSetEnv(L"lasterror", LeString, TRUE); + + return (EFI_SUCCESS); +} + +/** + Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec. + + @param[in,out] CmdLine pointer to the command line to update + + @retval EFI_SUCCESS The operation was successful + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @return some other error occurred +**/ +EFI_STATUS +ProcessCommandLineToFinal( + IN OUT CHAR16 **CmdLine + ) +{ + EFI_STATUS Status; + TrimSpaces(CmdLine); + + Status = ShellSubstituteAliases(CmdLine); + if (EFI_ERROR(Status)) { + return (Status); + } + + TrimSpaces(CmdLine); + + Status = ShellSubstituteVariables(CmdLine); + if (EFI_ERROR(Status)) { + return (Status); + } + ASSERT (*CmdLine != NULL); + + TrimSpaces(CmdLine); + + // + // update for help parsing + // + if (StrStr(*CmdLine, L"?") != NULL) { + // + // This may do nothing if the ? does not indicate help. + // Save all the details for in the API below. + // + Status = DoHelpUpdate(CmdLine); + } + + TrimSpaces(CmdLine); + + return (EFI_SUCCESS); +} + +/** + Run an internal shell command. + + This API will update the shell's environment since these commands are libraries. + + @param[in] CmdLine the command line to run. + @param[in] FirstParameter the first parameter on the command line + @param[in] ParamProtocol the shell parameters protocol pointer + @param[out] CommandStatus the status from the command line. + + @retval EFI_SUCCESS The command was completed. + @retval EFI_ABORTED The command's operation was aborted. +**/ +EFI_STATUS +RunInternalCommand( + IN CONST CHAR16 *CmdLine, + IN CHAR16 *FirstParameter, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, + OUT EFI_STATUS *CommandStatus +) +{ + EFI_STATUS Status; + UINTN Argc; + CHAR16 **Argv; + SHELL_STATUS CommandReturnedStatus; + BOOLEAN LastError; + CHAR16 *Walker; + CHAR16 *NewCmdLine; + + NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine); + if (NewCmdLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { + if (*Walker == L'^' && *(Walker+1) == L'#') { + CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + // + // get the argc and argv updated for internal commands + // + Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc); + if (!EFI_ERROR(Status)) { + // + // Run the internal command. + // + Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError); + + if (!EFI_ERROR(Status)) { + if (CommandStatus != NULL) { + if (CommandReturnedStatus != SHELL_SUCCESS) { + *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT); + } else { + *CommandStatus = EFI_SUCCESS; + } + } + + // + // Update last error status. + // some commands do not update last error. + // + if (LastError) { + SetLastError(CommandReturnedStatus); + } + + // + // Pass thru the exitcode from the app. + // + if (ShellCommandGetExit()) { + // + // An Exit was requested ("exit" command), pass its value up. + // + Status = CommandReturnedStatus; + } else if (CommandReturnedStatus != SHELL_SUCCESS && IsScriptOnlyCommand(FirstParameter)) { + // + // Always abort when a script only command fails for any reason + // + Status = EFI_ABORTED; + } else if (ShellCommandGetCurrentScriptFile() != NULL && CommandReturnedStatus == SHELL_ABORTED) { + // + // Abort when in a script and a command aborted + // + Status = EFI_ABORTED; + } + } + } + + // + // This is guaranteed to be called after UpdateArgcArgv no matter what else happened. + // This is safe even if the update API failed. In this case, it may be a no-op. + // + RestoreArgcArgv(ParamProtocol, &Argv, &Argc); + + // + // If a script is running and the command is not a script only command, then + // change return value to success so the script won't halt (unless aborted). + // + // Script only commands have to be able halt the script since the script will + // not operate if they are failing. + // + if ( ShellCommandGetCurrentScriptFile() != NULL + && !IsScriptOnlyCommand(FirstParameter) + && Status != EFI_ABORTED + ) { + Status = EFI_SUCCESS; + } + + FreePool (NewCmdLine); + return (Status); +} + +/** + Function to run the command or file. + + @param[in] Type the type of operation being run. + @param[in] CmdLine the command line to run. + @param[in] FirstParameter the first parameter on the command line + @param[in] ParamProtocol the shell parameters protocol pointer + @param[out] CommandStatus the status from the command line. + + @retval EFI_SUCCESS The command was completed. + @retval EFI_ABORTED The command's operation was aborted. +**/ +EFI_STATUS +RunCommandOrFile( + IN SHELL_OPERATION_TYPES Type, + IN CONST CHAR16 *CmdLine, + IN CHAR16 *FirstParameter, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, + OUT EFI_STATUS *CommandStatus +) +{ + EFI_STATUS Status; + EFI_STATUS StartStatus; + CHAR16 *CommandWithPath; + CHAR16 *FullCommandWithPath; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + SHELL_STATUS CalleeExitStatus; + + Status = EFI_SUCCESS; + CommandWithPath = NULL; + DevPath = NULL; + CalleeExitStatus = SHELL_INVALID_PARAMETER; + + switch (Type) { + case Internal_Command: + Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus); + break; + case Script_File_Name: + case Efi_Application: + // + // Process a fully qualified path + // + if (StrStr(FirstParameter, L":") != NULL) { + ASSERT (CommandWithPath == NULL); + if (ShellIsFile(FirstParameter) == EFI_SUCCESS) { + CommandWithPath = StrnCatGrow(&CommandWithPath, NULL, FirstParameter, 0); + } + } + + // + // Process a relative path and also check in the path environment variable + // + if (CommandWithPath == NULL) { + CommandWithPath = ShellFindFilePathEx(FirstParameter, mExecutableExtensions); + } + + // + // This should be impossible now. + // + ASSERT(CommandWithPath != NULL); + + // + // Make sure that path is not just a directory (or not found) + // + if (!EFI_ERROR(ShellIsDirectory(CommandWithPath))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); + } + switch (Type) { + case Script_File_Name: + FullCommandWithPath = FullyQualifyPath(CommandWithPath); + if (FullCommandWithPath == NULL) { + Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol); + } else { + Status = RunScriptFile (FullCommandWithPath, NULL, CmdLine, ParamProtocol); + FreePool(FullCommandWithPath); + } + break; + case Efi_Application: + // + // Get the device path of the application image + // + DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CommandWithPath); + if (DevPath == NULL){ + Status = EFI_OUT_OF_RESOURCES; + break; + } + + // + // Execute the device path + // + Status = InternalShellExecuteDevicePath( + &gImageHandle, + DevPath, + CmdLine, + NULL, + &StartStatus + ); + + SHELL_FREE_NON_NULL(DevPath); + + if(EFI_ERROR (Status)) { + CalleeExitStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + } else { + CalleeExitStatus = (SHELL_STATUS) StartStatus; + } + + if (CommandStatus != NULL) { + *CommandStatus = CalleeExitStatus; + } + + // + // Update last error status. + // + // Status is an EFI_STATUS. Clear top bit to convert to SHELL_STATUS + SetLastError(CalleeExitStatus); + break; + default: + // + // Do nothing. + // + break; + } + break; + default: + // + // Do nothing. + // + break; + } + + SHELL_FREE_NON_NULL(CommandWithPath); + + return (Status); +} + +/** + Function to setup StdIn, StdErr, StdOut, and then run the command or file. + + @param[in] Type the type of operation being run. + @param[in] CmdLine the command line to run. + @param[in] FirstParameter the first parameter on the command line. + @param[in] ParamProtocol the shell parameters protocol pointer + @param[out] CommandStatus the status from the command line. + + @retval EFI_SUCCESS The command was completed. + @retval EFI_ABORTED The command's operation was aborted. +**/ +EFI_STATUS +SetupAndRunCommandOrFile( + IN SHELL_OPERATION_TYPES Type, + IN CHAR16 *CmdLine, + IN CHAR16 *FirstParameter, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, + OUT EFI_STATUS *CommandStatus +) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE OriginalStdIn; + SHELL_FILE_HANDLE OriginalStdOut; + SHELL_FILE_HANDLE OriginalStdErr; + SYSTEM_TABLE_INFO OriginalSystemTableInfo; + CONST SCRIPT_FILE *ConstScriptFile; + + // + // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII + // + Status = UpdateStdInStdOutStdErr(ParamProtocol, CmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo); + + // + // The StdIn, StdOut, and StdErr are set up. + // Now run the command, script, or application + // + if (!EFI_ERROR(Status)) { + TrimSpaces(&CmdLine); + Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus); + } + + // + // Now print errors + // + if (EFI_ERROR(Status)) { + ConstScriptFile = ShellCommandGetCurrentScriptFile(); + if (ConstScriptFile == NULL || ConstScriptFile->CurrentCommand == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status)); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR_SCRIPT), ShellInfoObject.HiiHandle, (VOID*)(Status), ConstScriptFile->CurrentCommand->Line); + } + } + + // + // put back the original StdIn, StdOut, and StdErr + // + RestoreStdInStdOutStdErr(ParamProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo); + + return (Status); +} + +/** + Function will process and run a command line. + + This will determine if the command line represents an internal shell + command or dispatch an external application. + + @param[in] CmdLine The command line to parse. + @param[out] CommandStatus The status from the command line. + + @retval EFI_SUCCESS The command was completed. + @retval EFI_ABORTED The command's operation was aborted. +**/ +EFI_STATUS +RunShellCommand( + IN CONST CHAR16 *CmdLine, + OUT EFI_STATUS *CommandStatus + ) +{ + EFI_STATUS Status; + CHAR16 *CleanOriginal; + CHAR16 *FirstParameter; + CHAR16 *TempWalker; + SHELL_OPERATION_TYPES Type; + CONST CHAR16 *CurDir; + + ASSERT(CmdLine != NULL); + if (StrLen(CmdLine) == 0) { + return (EFI_SUCCESS); + } + + Status = EFI_SUCCESS; + CleanOriginal = NULL; + + CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0); + if (CleanOriginal == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + TrimSpaces(&CleanOriginal); + + // + // NULL out comments (leveraged from RunScriptFileHandle() ). + // The # character on a line is used to denote that all characters on the same line + // and to the right of the # are to be ignored by the shell. + // Afterwards, again remove spaces, in case any were between the last command-parameter and '#'. + // + for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) { + if (*TempWalker == L'^') { + if (*(TempWalker + 1) == L'#') { + TempWalker++; + } + } else if (*TempWalker == L'#') { + *TempWalker = CHAR_NULL; + } + } + + TrimSpaces(&CleanOriginal); + + // + // Handle case that passed in command line is just 1 or more " " characters. + // + if (StrLen (CleanOriginal) == 0) { + SHELL_FREE_NON_NULL(CleanOriginal); + return (EFI_SUCCESS); + } + + Status = ProcessCommandLineToFinal(&CleanOriginal); + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(CleanOriginal); + return (Status); + } + + // + // We don't do normal processing with a split command line (output from one command input to another) + // + if (ContainsSplit(CleanOriginal)) { + Status = ProcessNewSplitCommandLine(CleanOriginal); + SHELL_FREE_NON_NULL(CleanOriginal); + return (Status); + } + + // + // We need the first parameter information so we can determine the operation type + // + FirstParameter = AllocateZeroPool(StrSize(CleanOriginal)); + if (FirstParameter == NULL) { + SHELL_FREE_NON_NULL(CleanOriginal); + return (EFI_OUT_OF_RESOURCES); + } + TempWalker = CleanOriginal; + if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal), TRUE))) { + // + // Depending on the first parameter we change the behavior + // + switch (Type = GetOperationType(FirstParameter)) { + case File_Sys_Change: + Status = ChangeMappedDrive (FirstParameter); + break; + case Internal_Command: + case Script_File_Name: + case Efi_Application: + Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus); + break; + default: + // + // Whatever was typed, it was invalid. + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); + break; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); + } + // + // Check whether the current file system still exists. If not exist, we need update "cwd" and gShellCurMapping. + // + CurDir = EfiShellGetCurDir (NULL); + if (CurDir != NULL) { + if (EFI_ERROR(ShellFileExists (CurDir))) { + // + // EfiShellSetCurDir() cannot set current directory to NULL. + // EfiShellSetEnv() is not allowed to set the "cwd" variable. + // Only InternalEfiShellSetEnv () is allowed setting the "cwd" variable. + // + InternalEfiShellSetEnv (L"cwd", NULL, TRUE); + gShellCurMapping = NULL; + } + } + + SHELL_FREE_NON_NULL(CleanOriginal); + SHELL_FREE_NON_NULL(FirstParameter); + + return (Status); +} + +/** + Function will process and run a command line. + + This will determine if the command line represents an internal shell + command or dispatch an external application. + + @param[in] CmdLine The command line to parse. + + @retval EFI_SUCCESS The command was completed. + @retval EFI_ABORTED The command's operation was aborted. +**/ +EFI_STATUS +RunCommand( + IN CONST CHAR16 *CmdLine + ) +{ + return (RunShellCommand(CmdLine, NULL)); +} + +/** + Function to process a NSH script file via SHELL_FILE_HANDLE. + + @param[in] Handle The handle to the already opened file. + @param[in] Name The name of the script file. + + @retval EFI_SUCCESS the script completed successfully +**/ +EFI_STATUS +RunScriptFileHandle ( + IN SHELL_FILE_HANDLE Handle, + IN CONST CHAR16 *Name + ) +{ + EFI_STATUS Status; + SCRIPT_FILE *NewScriptFile; + UINTN LoopVar; + UINTN PrintBuffSize; + CHAR16 *CommandLine; + CHAR16 *CommandLine2; + CHAR16 *CommandLine3; + SCRIPT_COMMAND_LIST *LastCommand; + BOOLEAN Ascii; + BOOLEAN PreScriptEchoState; + BOOLEAN PreCommandEchoState; + CONST CHAR16 *CurDir; + UINTN LineCount; + CHAR16 LeString[50]; + LIST_ENTRY OldBufferList; + + ASSERT(!ShellCommandGetScriptExit()); + + PreScriptEchoState = ShellCommandGetEchoState(); + PrintBuffSize = PcdGet16(PcdShellPrintBufferSize); + + NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE)); + if (NewScriptFile == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // Set up the name + // + ASSERT(NewScriptFile->ScriptName == NULL); + NewScriptFile->ScriptName = StrnCatGrow(&NewScriptFile->ScriptName, NULL, Name, 0); + if (NewScriptFile->ScriptName == NULL) { + DeleteScriptFileStruct(NewScriptFile); + return (EFI_OUT_OF_RESOURCES); + } + + // + // Save the parameters (used to replace %0 to %9 later on) + // + NewScriptFile->Argc = ShellInfoObject.NewShellParametersProtocol->Argc; + if (NewScriptFile->Argc != 0) { + NewScriptFile->Argv = (CHAR16**)AllocateZeroPool(NewScriptFile->Argc * sizeof(CHAR16*)); + if (NewScriptFile->Argv == NULL) { + DeleteScriptFileStruct(NewScriptFile); + return (EFI_OUT_OF_RESOURCES); + } + // + // Put the full path of the script file into Argv[0] as required by section + // 3.6.2 of version 2.2 of the shell specification. + // + NewScriptFile->Argv[0] = StrnCatGrow(&NewScriptFile->Argv[0], NULL, NewScriptFile->ScriptName, 0); + for (LoopVar = 1 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) { + ASSERT(NewScriptFile->Argv[LoopVar] == NULL); + NewScriptFile->Argv[LoopVar] = StrnCatGrow(&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0); + if (NewScriptFile->Argv[LoopVar] == NULL) { + DeleteScriptFileStruct(NewScriptFile); + return (EFI_OUT_OF_RESOURCES); + } + } + } else { + NewScriptFile->Argv = NULL; + } + + InitializeListHead(&NewScriptFile->CommandList); + InitializeListHead(&NewScriptFile->SubstList); + + // + // Now build the list of all script commands. + // + LineCount = 0; + while(!ShellFileHandleEof(Handle)) { + CommandLine = ShellFileHandleReturnLine(Handle, &Ascii); + LineCount++; + if (CommandLine == NULL || StrLen(CommandLine) == 0 || CommandLine[0] == '#') { + SHELL_FREE_NON_NULL(CommandLine); + continue; + } + NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST)); + if (NewScriptFile->CurrentCommand == NULL) { + SHELL_FREE_NON_NULL(CommandLine); + DeleteScriptFileStruct(NewScriptFile); + return (EFI_OUT_OF_RESOURCES); + } + + NewScriptFile->CurrentCommand->Cl = CommandLine; + NewScriptFile->CurrentCommand->Data = NULL; + NewScriptFile->CurrentCommand->Line = LineCount; + + InsertTailList(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link); + } + + // + // Add this as the topmost script file + // + ShellCommandSetNewScript (NewScriptFile); + + // + // Now enumerate through the commands and run each one. + // + CommandLine = AllocateZeroPool(PrintBuffSize); + if (CommandLine == NULL) { + DeleteScriptFileStruct(NewScriptFile); + return (EFI_OUT_OF_RESOURCES); + } + CommandLine2 = AllocateZeroPool(PrintBuffSize); + if (CommandLine2 == NULL) { + FreePool(CommandLine); + DeleteScriptFileStruct(NewScriptFile); + return (EFI_OUT_OF_RESOURCES); + } + + for ( NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode(&NewScriptFile->CommandList) + ; !IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link) + ; // conditional increment in the body of the loop + ){ + ASSERT(CommandLine2 != NULL); + StrnCpyS( CommandLine2, + PrintBuffSize/sizeof(CHAR16), + NewScriptFile->CurrentCommand->Cl, + PrintBuffSize/sizeof(CHAR16) - 1 + ); + + SaveBufferList(&OldBufferList); + + // + // NULL out comments + // + for (CommandLine3 = CommandLine2 ; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL ; CommandLine3++) { + if (*CommandLine3 == L'^') { + if ( *(CommandLine3+1) == L':') { + CopyMem(CommandLine3, CommandLine3+1, StrSize(CommandLine3) - sizeof(CommandLine3[0])); + } else if (*(CommandLine3+1) == L'#') { + CommandLine3++; + } + } else if (*CommandLine3 == L'#') { + *CommandLine3 = CHAR_NULL; + } + } + + if (CommandLine2 != NULL && StrLen(CommandLine2) >= 1) { + // + // Due to variability in starting the find and replace action we need to have both buffers the same. + // + StrnCpyS( CommandLine, + PrintBuffSize/sizeof(CHAR16), + CommandLine2, + PrintBuffSize/sizeof(CHAR16) - 1 + ); + + // + // Remove the %0 to %9 from the command line (if we have some arguments) + // + if (NewScriptFile->Argv != NULL) { + switch (NewScriptFile->Argc) { + default: + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 9: + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 8: + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 7: + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 6: + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 5: + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 4: + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 3: + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 2: + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + case 1: + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + break; + case 0: + break; + } + } + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE); + + StrnCpyS( CommandLine2, + PrintBuffSize/sizeof(CHAR16), + CommandLine, + PrintBuffSize/sizeof(CHAR16) - 1 + ); + + LastCommand = NewScriptFile->CurrentCommand; + + for (CommandLine3 = CommandLine2 ; CommandLine3[0] == L' ' ; CommandLine3++); + + if (CommandLine3 != NULL && CommandLine3[0] == L':' ) { + // + // This line is a goto target / label + // + } else { + if (CommandLine3 != NULL && StrLen(CommandLine3) > 0) { + if (CommandLine3[0] == L'@') { + // + // We need to save the current echo state + // and disable echo for just this command. + // + PreCommandEchoState = ShellCommandGetEchoState(); + ShellCommandSetEchoState(FALSE); + Status = RunCommand(CommandLine3+1); + + // + // If command was "@echo -off" or "@echo -on" then don't restore echo state + // + if (StrCmp (L"@echo -off", CommandLine3) != 0 && + StrCmp (L"@echo -on", CommandLine3) != 0) { + // + // Now restore the pre-'@' echo state. + // + ShellCommandSetEchoState(PreCommandEchoState); + } + } else { + if (ShellCommandGetEchoState()) { + CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd"); + if (CurDir != NULL && StrLen(CurDir) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle); + } + ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2); + } + Status = RunCommand(CommandLine3); + } + } + + if (ShellCommandGetScriptExit()) { + // + // ShellCommandGetExitCode() always returns a UINT64 + // + UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellCommandGetExitCode()); + DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE);); + InternalEfiShellSetEnv(L"lasterror", LeString, TRUE); + + ShellCommandRegisterExit(FALSE, 0); + Status = EFI_SUCCESS; + RestoreBufferList(&OldBufferList); + break; + } + if (ShellGetExecutionBreakFlag()) { + RestoreBufferList(&OldBufferList); + break; + } + if (EFI_ERROR(Status)) { + RestoreBufferList(&OldBufferList); + break; + } + if (ShellCommandGetExit()) { + RestoreBufferList(&OldBufferList); + break; + } + } + // + // If that commend did not update the CurrentCommand then we need to advance it... + // + if (LastCommand == NewScriptFile->CurrentCommand) { + NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link); + if (!IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) { + NewScriptFile->CurrentCommand->Reset = TRUE; + } + } + } else { + NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link); + if (!IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) { + NewScriptFile->CurrentCommand->Reset = TRUE; + } + } + RestoreBufferList(&OldBufferList); + } + + + FreePool(CommandLine); + FreePool(CommandLine2); + ShellCommandSetNewScript (NULL); + + // + // Only if this was the last script reset the state. + // + if (ShellCommandGetCurrentScriptFile()==NULL) { + ShellCommandSetEchoState(PreScriptEchoState); + } + return (EFI_SUCCESS); +} + +/** + Function to process a NSH script file. + + @param[in] ScriptPath Pointer to the script file name (including file system path). + @param[in] Handle the handle of the script file already opened. + @param[in] CmdLine the command line to run. + @param[in] ParamProtocol the shell parameters protocol pointer + + @retval EFI_SUCCESS the script completed successfully +**/ +EFI_STATUS +RunScriptFile ( + IN CONST CHAR16 *ScriptPath, + IN SHELL_FILE_HANDLE Handle OPTIONAL, + IN CONST CHAR16 *CmdLine, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol + ) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE FileHandle; + UINTN Argc; + CHAR16 **Argv; + + if (ShellIsFile(ScriptPath) != EFI_SUCCESS) { + return (EFI_INVALID_PARAMETER); + } + + // + // get the argc and argv updated for scripts + // + Status = UpdateArgcArgv(ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc); + if (!EFI_ERROR(Status)) { + + if (Handle == NULL) { + // + // open the file + // + Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR(Status)) { + // + // run it + // + Status = RunScriptFileHandle(FileHandle, ScriptPath); + + // + // now close the file + // + ShellCloseFile(&FileHandle); + } + } else { + Status = RunScriptFileHandle(Handle, ScriptPath); + } + } + + // + // This is guaranteed to be called after UpdateArgcArgv no matter what else happened. + // This is safe even if the update API failed. In this case, it may be a no-op. + // + RestoreArgcArgv(ParamProtocol, &Argv, &Argc); + + return (Status); +} + +/** + Return the pointer to the first occurrence of any character from a list of characters. + + @param[in] String the string to parse + @param[in] CharacterList the list of character to look for + @param[in] EscapeCharacter An escape character to skip + + @return the location of the first character in the string + @retval CHAR_NULL no instance of any character in CharacterList was found in String +**/ +CONST CHAR16* +FindFirstCharacter( + IN CONST CHAR16 *String, + IN CONST CHAR16 *CharacterList, + IN CONST CHAR16 EscapeCharacter + ) +{ + UINT32 WalkChar; + UINT32 WalkStr; + + for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) { + if (String[WalkStr] == EscapeCharacter) { + WalkStr++; + continue; + } + for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) { + if (String[WalkStr] == CharacterList[WalkChar]) { + return (&String[WalkStr]); + } + } + } + return (String + StrLen(String)); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.h new file mode 100644 index 0000000..a12a1ba --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.h @@ -0,0 +1,396 @@ +/** @file + function definitions for internal to shell functions. + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_INTERNAL_HEADER_ +#define _SHELL_INTERNAL_HEADER_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ShellParametersProtocol.h" +#include "ShellProtocol.h" +#include "ShellEnvVar.h" +#include "ConsoleLogger.h" +#include "ShellManParser.h" +#include "ConsoleWrappers.h" +#include "FileHandleWrappers.h" + +extern CONST CHAR16 mNoNestingEnvVarName[]; +extern CONST CHAR16 mNoNestingTrue[]; +extern CONST CHAR16 mNoNestingFalse[]; + +typedef struct { + LIST_ENTRY Link; ///< Standard linked list handler. + SHELL_FILE_HANDLE SplitStdOut; ///< ConsoleOut for use in the split. + SHELL_FILE_HANDLE SplitStdIn; ///< ConsoleIn for use in the split. +} SPLIT_LIST; + +typedef struct { + UINT32 Startup:1; ///< Was "-startup" found on command line. + UINT32 NoStartup:1; ///< Was "-nostartup" found on command line. + UINT32 NoConsoleOut:1; ///< Was "-noconsoleout" found on command line. + UINT32 NoConsoleIn:1; ///< Was "-noconsolein" found on command line. + UINT32 NoInterrupt:1; ///< Was "-nointerrupt" found on command line. + UINT32 NoMap:1; ///< Was "-nomap" found on command line. + UINT32 NoVersion:1; ///< Was "-noversion" found on command line. + UINT32 Delay:1; ///< Was "-delay[:n] found on command line + UINT32 Exit:1; ///< Was "-_exit" found on command line + UINT32 NoNest:1; ///< Was "-nonest" found on command line + UINT32 Reserved:7; ///< Extra bits +} SHELL_BITS; + +typedef union { + SHELL_BITS Bits; + UINT16 AllBits; +} SHELL_BIT_UNION; + +typedef struct { + SHELL_BIT_UNION BitUnion; + UINTN Delay; ///< Seconds of delay default:5. + CHAR16 *FileName; ///< Filename to run upon successful initialization. + CHAR16 *FileOptions; ///< Options to pass to FileName. +} SHELL_INIT_SETTINGS; + +typedef struct { + BUFFER_LIST CommandHistory; + UINTN VisibleRowNumber; + UINTN OriginalVisibleRowNumber; + BOOLEAN InsertMode; ///< Is the current typing mode insert (FALSE = overwrite). +} SHELL_VIEWING_SETTINGS; + +typedef struct { + EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParametersProtocol; + EFI_SHELL_PROTOCOL *NewEfiShellProtocol; + BOOLEAN PageBreakEnabled; + BOOLEAN RootShellInstance; + SHELL_INIT_SETTINGS ShellInitSettings; + BUFFER_LIST BufferToFreeList; ///< List of buffers that were returned to the user to free. + SHELL_VIEWING_SETTINGS ViewingSettings; + EFI_HII_HANDLE HiiHandle; ///< Handle from HiiLib. + UINTN LogScreenCount; ///< How many screens of log information to save. + EFI_EVENT UserBreakTimer; ///< Timer event for polling for CTRL-C. + EFI_DEVICE_PATH_PROTOCOL *ImageDevPath; ///< DevicePath for ourselves. + EFI_DEVICE_PATH_PROTOCOL *FileDevPath; ///< DevicePath for ourselves. + CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; ///< Pointer for ConsoleInformation. + EFI_SHELL_PARAMETERS_PROTOCOL *OldShellParameters; ///< old shell parameters to reinstall upon exiting. + SHELL_PROTOCOL_HANDLE_LIST OldShellList; ///< List of other instances to reinstall when closing. + SPLIT_LIST SplitList; ///< List of Splits in FILO stack. + VOID *CtrlCNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlCNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlCNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlCNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlSNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlSNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlSNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + VOID *CtrlSNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify. + BOOLEAN HaltOutput; ///< TRUE to start a CTRL-S halt. +} SHELL_INFO; + +#pragma pack(1) +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} SHELL_MAN_HII_VENDOR_DEVICE_PATH; +#pragma pack() + +extern SHELL_INFO ShellInfoObject; + +/** + Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec. + + @param[in,out] CmdLine pointer to the command line to update + + @retval EFI_SUCCESS The operation was successful + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @return some other error occurred +**/ +EFI_STATUS +ProcessCommandLineToFinal( + IN OUT CHAR16 **CmdLine + ); + +/** + Function to update the shell variable "lasterror". + + @param[in] ErrorCode the error code to put into lasterror +**/ +EFI_STATUS +SetLastError( + IN CONST SHELL_STATUS ErrorCode + ); + +/** + Sets all the alias' that were registered with the ShellCommandLib library. + + @retval EFI_SUCCESS all init commands were run successfully. +**/ +EFI_STATUS +SetBuiltInAlias( + VOID + ); + +/** + This function will populate the 2 device path protocol parameters based on the + global gImageHandle. the DevPath will point to the device path for the handle that has + loaded image protocol installed on it. the FilePath will point to the device path + for the file that was loaded. + + @param[in, out] DevPath on a successful return the device path to the loaded image + @param[in, out] FilePath on a successful return the device path to the file + + @retval EFI_SUCCESS the 2 device paths were successfully returned. + @return other a error from gBS->HandleProtocol + + @sa HandleProtocol +**/ +EFI_STATUS +GetDevicePathsForImageAndFile ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath, + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath + ); + +/** + Process all Uefi Shell 2.0 command line options. + + see Uefi Shell 2.0 section 3.2 for full details. + + the command line should resemble the following: + + shell.efi [ShellOpt-options] [options] [file-name [file-name-options]] + + ShellOpt options Options which control the initialization behavior of the shell. + These options are read from the EFI global variable "ShellOpt" + and are processed before options or file-name. + + options Options which control the initialization behavior of the shell. + + file-name The name of a UEFI shell application or script to be executed + after initialization is complete. By default, if file-name is + specified, then -nostartup is implied. Scripts are not supported + by level 0. + + file-nameoptions The command-line options that are passed to file-name when it + is invoked. + + This will initialize the ShellInitSettings global variable. + + @retval EFI_SUCCESS the variable is initialized. +**/ +EFI_STATUS +ProcessCommandLine( + VOID + ); + +/** + Handles all interaction with the default startup script. + + this will check that the correct command line parameters were passed, handle the delay, and then start running the script. + + @param[in] ImagePath The path to the image for shell. The first place to look for the startup script. + @param[in] FilePath The path to the file for shell. The second place to look for the startup script. + + @retval EFI_SUCCESS The variable is initialized. +**/ +EFI_STATUS +DoStartupScript( + IN EFI_DEVICE_PATH_PROTOCOL *ImagePath, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ); + +/** + Function to perform the shell prompt looping. It will do a single prompt, + dispatch the result, and then return. It is expected that the caller will + call this function in a loop many times. + + @retval EFI_SUCCESS + @retval RETURN_ABORTED +**/ +EFI_STATUS +DoShellPrompt ( + VOID + ); + +/** + Add a buffer to the Buffer To Free List for safely returning buffers to other + places without risking letting them modify internal shell information. + + @param Buffer Something to pass to FreePool when the shell is exiting. +**/ +VOID* +AddBufferToFreeList( + VOID *Buffer + ); + +/** + Add a buffer to the Command History List. + + @param Buffer[in] The line buffer to add. +**/ +VOID +AddLineToCommandHistory( + IN CONST CHAR16 *Buffer + ); + +/** + Function will process and run a command line. + + This will determine if the command line represents an internal shell command or dispatch an external application. + + @param[in] CmdLine the command line to parse + + @retval EFI_SUCCESS the command was completed + @retval EFI_ABORTED the command's operation was aborted +**/ +EFI_STATUS +RunCommand( + IN CONST CHAR16 *CmdLine + ); + +/** + Function will process and run a command line. + + This will determine if the command line represents an internal shell + command or dispatch an external application. + + @param[in] CmdLine The command line to parse. + @param[out] CommandStatus The status from the command line. + + @retval EFI_SUCCESS The command was completed. + @retval EFI_ABORTED The command's operation was aborted. +**/ +EFI_STATUS +RunShellCommand( + IN CONST CHAR16 *CmdLine, + OUT EFI_STATUS *CommandStatus + ); + + +/** + Function to process a NSH script file via SHELL_FILE_HANDLE. + + @param[in] Handle The handle to the already opened file. + @param[in] Name The name of the script file. + + @retval EFI_SUCCESS the script completed successfully +**/ +EFI_STATUS +RunScriptFileHandle ( + IN SHELL_FILE_HANDLE Handle, + IN CONST CHAR16 *Name + ); + +/** + Function to process a NSH script file. + + @param[in] ScriptPath Pointer to the script file name (including file system path). + @param[in] Handle the handle of the script file already opened. + @param[in] CmdLine the command line to run. + @param[in] ParamProtocol the shell parameters protocol pointer + + @retval EFI_SUCCESS the script completed successfully +**/ +EFI_STATUS +RunScriptFile ( + IN CONST CHAR16 *ScriptPath, + IN SHELL_FILE_HANDLE Handle OPTIONAL, + IN CONST CHAR16 *CmdLine, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol + ); + +/** + Return the pointer to the first occurrence of any character from a list of characters. + + @param[in] String the string to parse + @param[in] CharacterList the list of character to look for + @param[in] EscapeCharacter An escape character to skip + + @return the location of the first character in the string + @retval CHAR_NULL no instance of any character in CharacterList was found in String +**/ +CONST CHAR16* +FindFirstCharacter( + IN CONST CHAR16 *String, + IN CONST CHAR16 *CharacterList, + IN CONST CHAR16 EscapeCharacter + ); + +/** + Cleans off leading and trailing spaces and tabs. + + @param[in] String pointer to the string to trim them off. +**/ +EFI_STATUS +TrimSpaces( + IN CHAR16 **String + ); + +/** + + Create a new buffer list and stores the old one to OldBufferList + + @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList. +**/ +VOID +SaveBufferList ( + OUT LIST_ENTRY *OldBufferList + ); + +/** + Restore previous nodes into BufferToFreeList . + + @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList. +**/ +VOID +RestoreBufferList ( + IN OUT LIST_ENTRY *OldBufferList + ); + + + +#endif //_SHELL_INTERNAL_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.inf new file mode 100644 index 0000000..ea4204d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.inf @@ -0,0 +1,110 @@ +## @file +# This is the shell application +# +# (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = Shell + FILE_GUID = 7C04A583-9E3E-4f1c-AD65-E05268D0B4D1 # gUefiShellFileGuid + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + Shell.c + Shell.h + ShellParametersProtocol.c + ShellParametersProtocol.h + ShellProtocol.c + ShellProtocol.h + FileHandleWrappers.c + FileHandleWrappers.h + FileHandleInternal.h + ShellEnvVar.c + ShellEnvVar.h + ShellManParser.c + ShellManParser.h + Shell.uni + ConsoleLogger.c + ConsoleLogger.h + ConsoleWrappers.c + ConsoleWrappers.h + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + UefiApplicationEntryPoint + UefiLib + DebugLib + MemoryAllocationLib + ShellCommandLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + DevicePathLib + BaseMemoryLib + PcdLib + FileHandleLib + PrintLib + HiiLib + SortLib + HandleParsingLib + UefiHiiServicesLib + +[Guids] + gShellVariableGuid ## SOMETIMES_CONSUMES ## GUID + gShellAliasGuid ## SOMETIMES_CONSUMES ## GUID + gShellAliasGuid ## SOMETIMES_PRODUCES ## GUID + +[Protocols] + gEfiShellProtocolGuid ## PRODUCES + ## SOMETIMES_CONSUMES + gEfiShellParametersProtocolGuid ## PRODUCES + ## SOMETIMES_CONSUMES + +# gEfiShellEnvironment2Guid ## SOMETIMES_PRODUCES +# gEfiShellInterfaceGuid ## SOMETIMES_PRODUCES + + gEfiSimpleTextInputExProtocolGuid ## CONSUMES + gEfiSimpleTextInProtocolGuid ## CONSUMES + gEfiSimpleTextOutProtocolGuid ## CONSUMES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiUnicodeCollation2ProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiHiiPackageListProtocolGuid ## SOMETIMES_PRODUCES + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellSupplier ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellMaxHistoryCommandCount ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.uni new file mode 100644 index 0000000..6660951 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/Shell.uni @@ -0,0 +1,58 @@ +// *++ +// +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// ShellStrings.uni +// +// Abstract: +// +// String definitions for the main UEFI Shell 2.0 application +// +// Revision History: +// +// --*/ + +/=# + +#langdef en-US "English" + +#string STR_SHELL_CURDIR #language en-US "%E%s\> %N" +#string STR_GEN_PROBLEM #language en-US "The argument '%B%s%N' is incorrect.\r\n" +#string STR_SHELL_SHELL #language en-US "%EShell> %N" + +#string STR_SHELL_STARTUP_QUESTION #language en-US "%NPress %HESC%N in %d seconds to skip %Estartup.nsh%N or any other key to continue." + +#string STR_SHELL_ENTER_TO_CONT #language en-US "%NPress ENTER to continue:%E" +#string STR_SHELL_QUIT_CONT #language en-US "%NPress ENTER to continue or 'Q' break:%E" + +#string STR_SHELL_NOT_FOUND #language en-US "%N'%E%s%N' is not recognized as an internal or external command, operable program, or script file.\r\n" + +#string STR_SHELL_CRLF #language en-US "\r\n" + +#string STR_SHELL_ERROR #language en-US "%NCommand Error Status: %r\r\n" +#string STR_SHELL_ERROR_SCRIPT #language en-US "%NScript Error Status: %r (line number %d)\r\n" + +#string STR_SHELL_INVALID_MAPPING #language en-US "%N'%B%s%N' is not a valid mapping.\r\n" +#string STR_SHELL_INVALID_SPLIT #language en-US "Invalid use of pipe (%B|%N).\r\n" + +#string STR_SHELL_INVALID_REDIR #language en-US "Unable to redirect file.\r\n" +#string STR_SHELL_REDUNDA_REDIR #language en-US "Redundant redirection specified.\r\n" + +#string STR_VER_OUTPUT_MAIN_SHELL #language en-US "UEFI %s Shell v%d.%d\r\n" +#string STR_VER_OUTPUT_MAIN_SUPPLIER #language en-US "%s\r\n" +#string STR_VER_OUTPUT_MAIN_UEFI #language en-US "UEFI v%d.%02d (%s, 0x%08x)\r\n" + +#string STR_SHELL_NO_IN_EX #language en-US "No SimpleTextInputEx was found. CTRL-based features are not usable.\r\n" + +#string STR_SHELL_IMAGE_NOT_APP #language en-US "The image is not an application.\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.c new file mode 100644 index 0000000..5993540 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.c @@ -0,0 +1,578 @@ +/** @file + function declarations for shell environment functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" + +#define INIT_NAME_BUFFER_SIZE 128 +#define INIT_DATA_BUFFER_SIZE 1024 + +// +// The list is used to cache the environment variables. +// +ENV_VAR_LIST gShellEnvVarList; + +/** + Reports whether an environment variable is Volatile or Non-Volatile. + + @param EnvVarName The name of the environment variable in question + @param Volatile Return TRUE if the environment variable is volatile + + @retval EFI_SUCCESS The volatile attribute is returned successfully + @retval others Some errors happened. +**/ +EFI_STATUS +IsVolatileEnv ( + IN CONST CHAR16 *EnvVarName, + OUT BOOLEAN *Volatile + ) +{ + EFI_STATUS Status; + UINTN Size; + VOID *Buffer; + UINT32 Attribs; + + ASSERT (Volatile != NULL); + + Size = 0; + Buffer = NULL; + + // + // get the variable + // + Status = gRT->GetVariable((CHAR16*)EnvVarName, + &gShellVariableGuid, + &Attribs, + &Size, + Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool(Size); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = gRT->GetVariable((CHAR16*)EnvVarName, + &gShellVariableGuid, + &Attribs, + &Size, + Buffer); + FreePool(Buffer); + } + // + // not found means volatile + // + if (Status == EFI_NOT_FOUND) { + *Volatile = TRUE; + return EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // check for the Non Volatile bit + // + *Volatile = !(BOOLEAN) ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE); + return EFI_SUCCESS; +} + +/** + free function for ENV_VAR_LIST objects. + + @param[in] List The pointer to pointer to list. +**/ +VOID +FreeEnvironmentVariableList( + IN LIST_ENTRY *List + ) +{ + ENV_VAR_LIST *Node; + + ASSERT (List != NULL); + if (List == NULL) { + return; + } + + for ( Node = (ENV_VAR_LIST*)GetFirstNode(List) + ; !IsListEmpty(List) + ; Node = (ENV_VAR_LIST*)GetFirstNode(List) + ){ + ASSERT(Node != NULL); + RemoveEntryList(&Node->Link); + if (Node->Key != NULL) { + FreePool(Node->Key); + } + if (Node->Val != NULL) { + FreePool(Node->Val); + } + FreePool(Node); + } +} + +/** + Creates a list of all Shell-Guid-based environment variables. + + @param[in, out] ListHead The pointer to pointer to LIST ENTRY object for + storing this list. + + @retval EFI_SUCCESS the list was created sucessfully. +**/ +EFI_STATUS +GetEnvironmentVariableList( + IN OUT LIST_ENTRY *ListHead + ) +{ + CHAR16 *VariableName; + UINTN NameSize; + UINTN NameBufferSize; + EFI_STATUS Status; + EFI_GUID Guid; + UINTN ValSize; + UINTN ValBufferSize; + ENV_VAR_LIST *VarList; + + if (ListHead == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Status = EFI_SUCCESS; + + ValBufferSize = INIT_DATA_BUFFER_SIZE; + NameBufferSize = INIT_NAME_BUFFER_SIZE; + VariableName = AllocateZeroPool(NameBufferSize); + if (VariableName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + *VariableName = CHAR_NULL; + + while (!EFI_ERROR(Status)) { + NameSize = NameBufferSize; + Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); + if (Status == EFI_NOT_FOUND){ + Status = EFI_SUCCESS; + break; + } else if (Status == EFI_BUFFER_TOO_SMALL) { + NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2; + SHELL_FREE_NON_NULL(VariableName); + VariableName = AllocateZeroPool(NameBufferSize); + if (VariableName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + NameSize = NameBufferSize; + Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); + } + + if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){ + VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST)); + if (VarList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + ValSize = ValBufferSize; + // + // We need another CHAR16 to save '\0' in VarList->Val. + // + VarList->Val = AllocateZeroPool (ValSize + sizeof (CHAR16)); + if (VarList->Val == NULL) { + SHELL_FREE_NON_NULL(VarList); + Status = EFI_OUT_OF_RESOURCES; + break; + } + Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val); + if (Status == EFI_BUFFER_TOO_SMALL){ + ValBufferSize = ValSize > ValBufferSize * 2 ? ValSize : ValBufferSize * 2; + SHELL_FREE_NON_NULL (VarList->Val); + // + // We need another CHAR16 to save '\0' in VarList->Val. + // + VarList->Val = AllocateZeroPool (ValBufferSize + sizeof (CHAR16)); + if (VarList->Val == NULL) { + SHELL_FREE_NON_NULL(VarList); + Status = EFI_OUT_OF_RESOURCES; + break; + } + + ValSize = ValBufferSize; + Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val); + } + if (!EFI_ERROR(Status)) { + VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName); + if (VarList->Key == NULL) { + SHELL_FREE_NON_NULL(VarList->Val); + SHELL_FREE_NON_NULL(VarList); + Status = EFI_OUT_OF_RESOURCES; + } else { + InsertTailList(ListHead, &VarList->Link); + } + } else { + SHELL_FREE_NON_NULL(VarList->Val); + SHELL_FREE_NON_NULL(VarList); + } + } // if (VarList == NULL) ... else ... + } // compare guid + } // while + SHELL_FREE_NON_NULL (VariableName); + + if (EFI_ERROR(Status)) { + FreeEnvironmentVariableList(ListHead); + } + + return (Status); +} + +/** + Sets a list of all Shell-Guid-based environment variables. this will + also eliminate all existing shell environment variables (even if they + are not on the list). + + This function will also deallocate the memory from List. + + @param[in] ListHead The pointer to LIST_ENTRY from + GetShellEnvVarList(). + + @retval EFI_SUCCESS the list was Set sucessfully. +**/ +EFI_STATUS +SetEnvironmentVariableList( + IN LIST_ENTRY *ListHead + ) +{ + ENV_VAR_LIST VarList; + ENV_VAR_LIST *Node; + EFI_STATUS Status; + UINTN Size; + + InitializeListHead(&VarList.Link); + + // + // Delete all the current environment variables + // + Status = GetEnvironmentVariableList(&VarList.Link); + ASSERT_EFI_ERROR(Status); + + for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link) + ; !IsNull(&VarList.Link, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link) + ){ + if (Node->Key != NULL) { + Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key); + } + ASSERT_EFI_ERROR(Status); + } + + FreeEnvironmentVariableList(&VarList.Link); + + // + // set all the variables fron the list + // + for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead) + ; !IsNull(ListHead, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link) + ){ + Size = StrSize (Node->Val) - sizeof (CHAR16); + if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) { + Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val); + } else { + Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val); + } + ASSERT_EFI_ERROR(Status); + } + FreeEnvironmentVariableList(ListHead); + + return (Status); +} + +/** + sets a list of all Shell-Guid-based environment variables. + + @param Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. + + @retval EFI_SUCCESS The command executed successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + + @sa SetEnvironmentVariableList +**/ +EFI_STATUS +SetEnvironmentVariables( + IN CONST CHAR16 **Environment + ) +{ + CONST CHAR16 *CurrentString; + UINTN CurrentCount; + ENV_VAR_LIST *VarList; + ENV_VAR_LIST *Node; + + VarList = NULL; + + if (Environment == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Build a list identical to the ones used for get/set list functions above + // + for ( CurrentCount = 0 + ; + ; CurrentCount++ + ){ + CurrentString = Environment[CurrentCount]; + if (CurrentString == NULL) { + break; + } + ASSERT(StrStr(CurrentString, L"=") != NULL); + Node = AllocateZeroPool(sizeof(ENV_VAR_LIST)); + if (Node == NULL) { + SetEnvironmentVariableList(&VarList->Link); + return (EFI_OUT_OF_RESOURCES); + } + + Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16)); + if (Node->Key == NULL) { + SHELL_FREE_NON_NULL(Node); + SetEnvironmentVariableList(&VarList->Link); + return (EFI_OUT_OF_RESOURCES); + } + + // + // Copy the string into the Key, leaving the last character allocated as NULL to terminate + // + StrnCpyS( Node->Key, + StrStr(CurrentString, L"=") - CurrentString + 1, + CurrentString, + StrStr(CurrentString, L"=") - CurrentString + ); + + // + // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other) + // + Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1); + if (Node->Val == NULL) { + SHELL_FREE_NON_NULL(Node->Key); + SHELL_FREE_NON_NULL(Node); + SetEnvironmentVariableList(&VarList->Link); + return (EFI_OUT_OF_RESOURCES); + } + + Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS; + + if (VarList == NULL) { + VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST)); + if (VarList == NULL) { + SHELL_FREE_NON_NULL(Node->Key); + SHELL_FREE_NON_NULL(Node->Val); + SHELL_FREE_NON_NULL(Node); + return (EFI_OUT_OF_RESOURCES); + } + InitializeListHead(&VarList->Link); + } + InsertTailList(&VarList->Link, &Node->Link); + + } // for loop + + // + // set this new list as the set of all environment variables. + // this function also frees the memory and deletes all pre-existing + // shell-guid based environment variables. + // + return (SetEnvironmentVariableList(&VarList->Link)); +} + +/** + Find an environment variable in the gShellEnvVarList. + + @param Key The name of the environment variable. + @param Value The value of the environment variable, the buffer + shoule be freed by the caller. + @param ValueSize The size in bytes of the environment variable + including the tailing CHAR_NELL. + @param Atts The attributes of the variable. + + @retval EFI_SUCCESS The command executed successfully. + @retval EFI_NOT_FOUND The environment variable is not found in + gShellEnvVarList. + +**/ +EFI_STATUS +ShellFindEnvVarInList ( + IN CONST CHAR16 *Key, + OUT CHAR16 **Value, + OUT UINTN *ValueSize, + OUT UINT32 *Atts OPTIONAL + ) +{ + ENV_VAR_LIST *Node; + + if (Key == NULL || Value == NULL || ValueSize == NULL) { + return SHELL_INVALID_PARAMETER; + } + + for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link) + ; !IsNull(&gShellEnvVarList.Link, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link) + ){ + if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) { + *Value = AllocateCopyPool(StrSize(Node->Val), Node->Val); + *ValueSize = StrSize(Node->Val); + if (Atts != NULL) { + *Atts = Node->Atts; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Add an environment variable into gShellEnvVarList. + + @param Key The name of the environment variable. + @param Value The value of environment variable. + @param ValueSize The size in bytes of the environment variable + including the tailing CHAR_NULL + @param Atts The attributes of the variable. + + @retval EFI_SUCCESS The environment variable was added to list successfully. + @retval others Some errors happened. + +**/ +EFI_STATUS +ShellAddEnvVarToList ( + IN CONST CHAR16 *Key, + IN CONST CHAR16 *Value, + IN UINTN ValueSize, + IN UINT32 Atts + ) +{ + ENV_VAR_LIST *Node; + CHAR16 *LocalKey; + CHAR16 *LocalValue; + + if (Key == NULL || Value == NULL || ValueSize == 0) { + return EFI_INVALID_PARAMETER; + } + + LocalValue = AllocateCopyPool (ValueSize, Value); + if (LocalValue == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Update the variable value if it exists in gShellEnvVarList. + // + for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link) + ; !IsNull(&gShellEnvVarList.Link, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link) + ){ + if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) { + Node->Atts = Atts; + SHELL_FREE_NON_NULL(Node->Val); + Node->Val = LocalValue; + return EFI_SUCCESS; + } + } + + // + // If the environment varialbe key doesn't exist in list just insert + // a new node. + // + LocalKey = AllocateCopyPool (StrSize(Key), Key); + if (LocalKey == NULL) { + FreePool (LocalValue); + return EFI_OUT_OF_RESOURCES; + } + Node = (ENV_VAR_LIST*)AllocateZeroPool (sizeof(ENV_VAR_LIST)); + if (Node == NULL) { + FreePool (LocalKey); + FreePool (LocalValue); + return EFI_OUT_OF_RESOURCES; + } + Node->Key = LocalKey; + Node->Val = LocalValue; + Node->Atts = Atts; + InsertTailList(&gShellEnvVarList.Link, &Node->Link); + + return EFI_SUCCESS; +} + +/** + Remove a specified environment variable in gShellEnvVarList. + + @param Key The name of the environment variable. + + @retval EFI_SUCCESS The command executed successfully. + @retval EFI_NOT_FOUND The environment variable is not found in + gShellEnvVarList. +**/ +EFI_STATUS +ShellRemvoeEnvVarFromList ( + IN CONST CHAR16 *Key + ) +{ + ENV_VAR_LIST *Node; + + if (Key == NULL) { + return EFI_INVALID_PARAMETER; + } + + for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link) + ; !IsNull(&gShellEnvVarList.Link, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link) + ){ + if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) { + SHELL_FREE_NON_NULL(Node->Key); + SHELL_FREE_NON_NULL(Node->Val); + RemoveEntryList(&Node->Link); + SHELL_FREE_NON_NULL(Node); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Initialize the gShellEnvVarList and cache all Shell-Guid-based environment + variables. + +**/ +EFI_STATUS +ShellInitEnvVarList ( + VOID + ) +{ + EFI_STATUS Status; + + InitializeListHead(&gShellEnvVarList.Link); + Status = GetEnvironmentVariableList (&gShellEnvVarList.Link); + + return Status; +} + +/** + Destructe the gShellEnvVarList. + +**/ +VOID +ShellFreeEnvVarList ( + VOID + ) +{ + FreeEnvironmentVariableList (&gShellEnvVarList.Link); + InitializeListHead(&gShellEnvVarList.Link); + + return; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.h new file mode 100644 index 0000000..a1ede0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellEnvVar.h @@ -0,0 +1,288 @@ +/** @file + function definitions for shell environment functions. + + the following includes are required: +//#include +//#include + + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_ENVIRONMENT_VARIABLE_HEADER_ +#define _SHELL_ENVIRONMENT_VARIABLE_HEADER_ + +typedef struct { + LIST_ENTRY Link; + CHAR16 *Key; + CHAR16 *Val; + UINT32 Atts; +} ENV_VAR_LIST; + +// +// The list is used to cache the environment variables. +// +extern ENV_VAR_LIST gShellEnvVarList; + + +/** + Reports whether an environment variable is Volatile or Non-Volatile. + + @param EnvVarName The name of the environment variable in question + @param Volatile Return TRUE if the environment variable is volatile + + @retval EFI_SUCCESS The volatile attribute is returned successfully + @retval others Some errors happened. +**/ +EFI_STATUS +IsVolatileEnv ( + IN CONST CHAR16 *EnvVarName, + OUT BOOLEAN *Volatile + ); + +/** + Delete a Non-Violatile environment variable. + + This will use the Runtime Services call SetVariable to remove a non-violatile variable. + + @param EnvVarName The name of the environment variable in question + + @retval EFI_SUCCESS The variable was deleted sucessfully + @retval other An error ocurred + @sa SetVariable +**/ +#define SHELL_DELETE_ENVIRONMENT_VARIABLE(EnvVarName) \ + (gRT->SetVariable((CHAR16*)EnvVarName, \ + &gShellVariableGuid, \ + 0, \ + 0, \ + NULL)) + +/** + Set a Non-Violatile environment variable. + + This will use the Runtime Services call SetVariable to set a non-violatile variable. + + @param EnvVarName The name of the environment variable in question + @param BufferSize UINTN size of Buffer + @param Buffer Pointer to value to set variable to + + @retval EFI_SUCCESS The variable was changed sucessfully + @retval other An error ocurred + @sa SetVariable +**/ +#define SHELL_SET_ENVIRONMENT_VARIABLE_NV(EnvVarName,BufferSize,Buffer) \ + (gRT->SetVariable((CHAR16*)EnvVarName, \ + &gShellVariableGuid, \ + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, \ + BufferSize, \ + (VOID*)Buffer)) + +/** + Get an environment variable. + + This will use the Runtime Services call GetVariable to get a variable. + + @param EnvVarName The name of the environment variable in question + @param BufferSize Pointer to the UINTN size of Buffer + @param Buffer Pointer buffer to get variable value into + + @retval EFI_SUCCESS The variable's value was retrieved sucessfully + @retval other An error ocurred + @sa SetVariable +**/ +#define SHELL_GET_ENVIRONMENT_VARIABLE(EnvVarName,BufferSize,Buffer) \ + (gRT->GetVariable((CHAR16*)EnvVarName, \ + &gShellVariableGuid, \ + 0, \ + BufferSize, \ + Buffer)) + +/** + Get an environment variable. + + This will use the Runtime Services call GetVariable to get a variable. + + @param EnvVarName The name of the environment variable in question + @param Atts Pointer to the UINT32 for attributes (or NULL) + @param BufferSize Pointer to the UINTN size of Buffer + @param Buffer Pointer buffer to get variable value into + + @retval EFI_SUCCESS The variable's value was retrieved sucessfully + @retval other An error ocurred + @sa SetVariable +**/ +#define SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(EnvVarName,Atts,BufferSize,Buffer) \ + (gRT->GetVariable((CHAR16*)EnvVarName, \ + &gShellVariableGuid, \ + Atts, \ + BufferSize, \ + Buffer)) + +/** + Set a Violatile environment variable. + + This will use the Runtime Services call SetVariable to set a violatile variable. + + @param EnvVarName The name of the environment variable in question + @param BufferSize UINTN size of Buffer + @param Buffer Pointer to value to set variable to + + @retval EFI_SUCCESS The variable was changed sucessfully + @retval other An error ocurred + @sa SetVariable +**/ +#define SHELL_SET_ENVIRONMENT_VARIABLE_V(EnvVarName,BufferSize,Buffer) \ + (gRT->SetVariable((CHAR16*)EnvVarName, \ + &gShellVariableGuid, \ + EFI_VARIABLE_BOOTSERVICE_ACCESS, \ + BufferSize, \ + (VOID*)Buffer)) + +/** + Creates a list of all Shell-Guid-based environment variables. + + @param[in, out] List The pointer to pointer to LIST_ENTRY object for + storing this list. + + @retval EFI_SUCCESS the list was created sucessfully. +**/ +EFI_STATUS +GetEnvironmentVariableList( + IN OUT LIST_ENTRY *List + ); + +/** + Sets a list of all Shell-Guid-based environment variables. this will + also eliminate all pre-existing shell environment variables (even if they + are not on the list). + + This function will also deallocate the memory from List. + + @param[in] List The pointer to LIST_ENTRY from + GetShellEnvVarList(). + + @retval EFI_SUCCESS The list was Set sucessfully. +**/ +EFI_STATUS +SetEnvironmentVariableList( + IN LIST_ENTRY *List + ); + +/** + sets all Shell-Guid-based environment variables. this will + also eliminate all pre-existing shell environment variables (even if they + are not on the list). + + @param[in] Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. + + @retval EFI_SUCCESS The command executed successfully. + @retval EFI_INVALID_PARAMETER The parameter is invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + + @sa SetEnvironmentVariableList +**/ +EFI_STATUS +SetEnvironmentVariables( + IN CONST CHAR16 **Environment + ); + +/** + free function for ENV_VAR_LIST objects. + + @param[in] List The pointer to pointer to list. +**/ +VOID +FreeEnvironmentVariableList( + IN LIST_ENTRY *List + ); + +/** + Find an environment variable in the gShellEnvVarList. + + @param Key The name of the environment variable. + @param Value The value of the environment variable, the buffer + shoule be freed by the caller. + @param ValueSize The size in bytes of the environment variable + including the tailing CHAR_NULL. + @param Atts The attributes of the variable. + + @retval EFI_SUCCESS The command executed successfully. + @retval EFI_NOT_FOUND The environment variable is not found in + gShellEnvVarList. + +**/ +EFI_STATUS +ShellFindEnvVarInList ( + IN CONST CHAR16 *Key, + OUT CHAR16 **Value, + OUT UINTN *ValueSize, + OUT UINT32 *Atts OPTIONAL + ); + +/** + Add an environment variable into gShellEnvVarList. + + @param Key The name of the environment variable. + @param Value The value of environment variable. + @param ValueSize The size in bytes of the environment variable + including the tailing CHAR_NULL + @param Atts The attributes of the variable. + + @retval EFI_SUCCESS The environment variable was added to list successfully. + @retval others Some errors happened. + +**/ +EFI_STATUS +ShellAddEnvVarToList ( + IN CONST CHAR16 *Key, + IN CONST CHAR16 *Value, + IN UINTN ValueSize, + IN UINT32 Atts + ); + +/** + Remove a specified environment variable in gShellEnvVarList. + + @param Key The name of the environment variable. + + @retval EFI_SUCCESS The command executed successfully. + @retval EFI_NOT_FOUND The environment variable is not found in + gShellEnvVarList. +**/ +EFI_STATUS +ShellRemvoeEnvVarFromList ( + IN CONST CHAR16 *Key + ); + +/** + Initialize the gShellEnvVarList and cache all Shell-Guid-based environment + variables. + +**/ +EFI_STATUS +ShellInitEnvVarList ( + VOID + ); + +/** + Destructe the gShellEnvVarList. + +**/ +VOID +ShellFreeEnvVarList ( + VOID + ); + +#endif //_SHELL_ENVIRONMENT_VARIABLE_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.c new file mode 100644 index 0000000..874b10f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.c @@ -0,0 +1,754 @@ +/** @file + Provides interface to shell MAN file parser. + + Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
        + Copyright 2015 Dell Inc. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" + +#define SHELL_MAN_HII_GUID \ +{ \ + 0xf62ccd0c, 0x2449, 0x453c, { 0x8a, 0xcb, 0x8c, 0xc5, 0x7c, 0xf0, 0x2a, 0x97 } \ +} + +EFI_HII_HANDLE mShellManHiiHandle = NULL; +EFI_HANDLE mShellManDriverHandle = NULL; + + +SHELL_MAN_HII_VENDOR_DEVICE_PATH mShellManHiiDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + SHELL_MAN_HII_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + Verifies that the filename has .EFI on the end. + + allocates a new buffer and copies the name (appending .EFI if necessary). + Caller to free the buffer. + + @param[in] NameString original name string + + @return the new filename with .efi as the extension. +**/ +CHAR16 * +GetExecuatableFileName ( + IN CONST CHAR16 *NameString + ) +{ + CHAR16 *Buffer; + CHAR16 *SuffixStr; + if (NameString == NULL) { + return (NULL); + } + + // + // Fix the file name + // + if (StrnCmp(NameString+StrLen(NameString)-StrLen(L".efi"), L".efi", StrLen(L".efi"))==0) { + Buffer = AllocateCopyPool(StrSize(NameString), NameString); + } else if (StrnCmp(NameString+StrLen(NameString)-StrLen(L".man"), L".man", StrLen(L".man"))==0) { + Buffer = AllocateCopyPool(StrSize(NameString), NameString); + if (Buffer != NULL) { + SuffixStr = Buffer+StrLen(Buffer)-StrLen(L".man"); + StrnCpyS (SuffixStr, StrSize(L".man")/sizeof(CHAR16), L".efi", StrLen(L".efi")); + } + } else { + Buffer = AllocateZeroPool(StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16)); + if (Buffer != NULL) { + StrnCpyS( Buffer, + (StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16))/sizeof(CHAR16), + NameString, + StrLen(NameString) + ); + StrnCatS( Buffer, + (StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16))/sizeof(CHAR16), + L".efi", + StrLen(L".efi") + ); + } + } + return (Buffer); + +} + +/** + Verifies that the filename has .MAN on the end. + + allocates a new buffer and copies the name (appending .MAN if necessary) + + ASSERT if ManFileName is NULL + + @param[in] ManFileName original filename + + @return the new filename with .man as the extension. +**/ +CHAR16 * +GetManFileName( + IN CONST CHAR16 *ManFileName + ) +{ + CHAR16 *Buffer; + if (ManFileName == NULL) { + return (NULL); + } + // + // Fix the file name + // + if (StrnCmp(ManFileName+StrLen(ManFileName)-4, L".man", 4)==0) { + Buffer = AllocateCopyPool(StrSize(ManFileName), ManFileName); + } else { + Buffer = AllocateZeroPool(StrSize(ManFileName) + 4*sizeof(CHAR16)); + if (Buffer != NULL) { + StrnCpyS( Buffer, + (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16), + ManFileName, + StrLen(ManFileName) + ); + StrnCatS( Buffer, + (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16), + L".man", + 4 + ); + } + } + return (Buffer); +} + +/** + Search the path environment variable for possible locations and test for + which one contains a man file with the name specified. If a valid file is found + stop searching and return the (opened) SHELL_FILE_HANDLE for that file. + + @param[in] FileName Name of the file to find and open. + @param[out] Handle Pointer to the handle of the found file. The + value of this is undefined for return values + except EFI_SUCCESS. + + @retval EFI_SUCCESS The file was found. Handle is a valid SHELL_FILE_HANDLE + @retval EFI_INVALID_PARAMETER A parameter had an invalid value. + @retval EFI_NOT_FOUND The file was not found. +**/ +EFI_STATUS +SearchPathForFile( + IN CONST CHAR16 *FileName, + OUT SHELL_FILE_HANDLE *Handle + ) +{ + CHAR16 *FullFileName; + EFI_STATUS Status; + + if ( FileName == NULL + || Handle == NULL + || StrLen(FileName) == 0 + ){ + return (EFI_INVALID_PARAMETER); + } + + FullFileName = ShellFindFilePath(FileName); + if (FullFileName == NULL) { + return (EFI_NOT_FOUND); + } + + // + // now open that file + // + Status = EfiShellOpenFileByName(FullFileName, Handle, EFI_FILE_MODE_READ); + FreePool(FullFileName); + + return (Status); +} + +/** + parses through the MAN file specified by SHELL_FILE_HANDLE and returns the + detailed help for any sub section specified in the comma seperated list of + sections provided. If the end of the file or a .TH section is found then + return. + + Upon a sucessful return the caller is responsible to free the memory in *HelpText + + @param[in] Handle FileHandle to read from + @param[in] Sections name of command's sub sections to find + @param[out] HelpText pointer to pointer to string where text goes. + @param[out] HelpSize pointer to size of allocated HelpText (may be updated) + @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise. + + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. + @retval EFI_SUCCESS the section was found and its description sotred in + an alloceted buffer. +**/ +EFI_STATUS +ManFileFindSections( + IN SHELL_FILE_HANDLE Handle, + IN CONST CHAR16 *Sections, + OUT CHAR16 **HelpText, + OUT UINTN *HelpSize, + IN BOOLEAN Ascii + ) +{ + EFI_STATUS Status; + CHAR16 *ReadLine; + UINTN Size; + BOOLEAN CurrentlyReading; + CHAR16 *SectionName; + UINTN SectionLen; + BOOLEAN Found; + + if ( Handle == NULL + || HelpText == NULL + || HelpSize == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + + Status = EFI_SUCCESS; + CurrentlyReading = FALSE; + Size = 1024; + Found = FALSE; + + ReadLine = AllocateZeroPool(Size); + if (ReadLine == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + for (;!ShellFileHandleEof(Handle);Size = 1024) { + Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, &Ascii); + if (ReadLine[0] == L'#') { + // + // Skip comment lines + // + continue; + } + // + // ignore too small of buffer... + // + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR(Status)) { + break; + } else if (StrnCmp(ReadLine, L".TH", 3) == 0) { + // + // we hit the end of this commands section so stop. + // + break; + } else if (StrnCmp(ReadLine, L".SH", 3) == 0) { + if (Sections == NULL) { + CurrentlyReading = TRUE; + continue; + } + // + // we found a section + // + if (CurrentlyReading) { + CurrentlyReading = FALSE; + } + // + // is this a section we want to read in? + // + for ( SectionName = ReadLine + 3 + ; *SectionName == L' ' + ; SectionName++); + SectionLen = StrLen(SectionName); + SectionName = StrStr(Sections, SectionName); + if (SectionName == NULL) { + continue; + } + if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') { + CurrentlyReading = TRUE; + } + } else if (CurrentlyReading) { + Found = TRUE; + // + // copy and save the current line. + // + ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL)); + StrnCatGrow (HelpText, HelpSize, ReadLine, 0); + StrnCatGrow (HelpText, HelpSize, L"\r\n", 0); + } + } + FreePool(ReadLine); + if (!Found && !EFI_ERROR(Status)) { + return (EFI_NOT_FOUND); + } + return (Status); +} + +/** + Parses a line from a MAN file to see if it is the Title Header. If it is, then + if the "Brief Description" is desired, allocate a buffer for it and return a + copy. Upon a sucessful return the caller is responsible to free the memory in + *BriefDesc + + Uses a simple state machine that allows "unlimited" whitespace before and after the + ".TH", compares Command and the MAN file commnd name without respect to case, and + allows "unlimited" whitespace and '0' and '1' characters before the Short Description. + The PCRE regex describing this functionality is: ^\s*\.TH\s+(\S)\s[\s01]*(.*)$ + where group 1 is the Command Name and group 2 is the Short Description. + + @param[in] Command name of command whose MAN file we think Line came from + @param[in] Line Pointer to a line from the MAN file + @param[out] BriefDesc pointer to pointer to string where description goes. + @param[out] BriefSize pointer to size of allocated BriefDesc + @param[out] Found TRUE if the Title Header was found and it belongs to Command + + @retval TRUE Line contained the Title Header + @retval FALSE Line did not contain the Title Header +**/ +BOOLEAN +IsTitleHeader( + IN CONST CHAR16 *Command, + IN CHAR16 *Line, + OUT CHAR16 **BriefDesc OPTIONAL, + OUT UINTN *BriefSize OPTIONAL, + OUT BOOLEAN *Found + ) +{ + // The states of a simple state machine used to recognize a title header line + // and to extract the Short Description, if desired. + typedef enum { + LookForThMacro, LookForCommandName, CompareCommands, GetBriefDescription, Final + } STATEVALUES; + + STATEVALUES State; + UINTN CommandIndex; // Indexes Command as we compare its chars to the MAN file. + BOOLEAN ReturnValue; // TRUE if this the Title Header line of *some* MAN file. + BOOLEAN ReturnFound; // TRUE if this the Title Header line of *the desired* MAN file. + + ReturnValue = FALSE; + ReturnFound = FALSE; + CommandIndex = 0; + State = LookForThMacro; + + do { + + if (*Line == L'\0') { + break; + } + + switch (State) { + + // Handle "^\s*.TH\s" + // Go to state LookForCommandName if the title header macro is present; otherwise, + // eat white space. If we see something other than white space, this is not a + // title header line. + case LookForThMacro: + if (StrnCmp (L".TH ", Line, 4) == 0 || StrnCmp (L".TH\t", Line, 4) == 0) { + Line += 4; + State = LookForCommandName; + } + else if (*Line == L' ' || *Line == L'\t') { + Line++; + } + else { + State = Final; + } + break; + + // Handle "\s*" + // Eat any "extra" whitespace after the title header macro (we have already seen + // at least one white space character). Go to state CompareCommands when a + // non-white space is seen. + case LookForCommandName: + if (*Line == L' ' || *Line == L'\t') { + Line++; + } + else { + ReturnValue = TRUE; // This is *some* command's title header line. + State = CompareCommands; + // Do not increment Line; it points to the first character of the command + // name on the title header line. + } + break; + + // Handle "(\S)\s" + // Compare Command to the title header command name, ignoring case. When we + // reach the end of the command (i.e. we see white space), the next state + // depends on whether the caller wants a copy of the Brief Description. + case CompareCommands: + if (*Line == L' ' || *Line == L'\t') { + ReturnFound = TRUE; // This is the desired command's title header line. + State = (BriefDesc == NULL) ? Final : GetBriefDescription; + } + else if (CharToUpper (*Line) != CharToUpper (*(Command + CommandIndex++))) { + State = Final; + } + Line++; + break; + + // Handle "[\s01]*(.*)$" + // Skip whitespace, '0', and '1' characters, if any, prior to the brief description. + // Return the description to the caller. + case GetBriefDescription: + if (*Line != L' ' && *Line != L'\t' && *Line != L'0' && *Line != L'1') { + *BriefSize = StrSize(Line); + *BriefDesc = AllocateZeroPool(*BriefSize); + if (*BriefDesc != NULL) { + StrCpyS(*BriefDesc, (*BriefSize)/sizeof(CHAR16), Line); + } + State = Final; + } + Line++; + break; + + default: + break; + } + + } while (State < Final); + + *Found = ReturnFound; + return ReturnValue; +} + +/** + parses through the MAN file specified by SHELL_FILE_HANDLE and returns the + "Brief Description" for the .TH section as specified by Command. If the + command section is not found return EFI_NOT_FOUND. + + Upon a sucessful return the caller is responsible to free the memory in *BriefDesc + + @param[in] Handle FileHandle to read from + @param[in] Command name of command's section to find as entered on the + command line (may be a relative or absolute path or + be in any case: upper, lower, or mixed in numerous ways!). + @param[out] BriefDesc pointer to pointer to string where description goes. + @param[out] BriefSize pointer to size of allocated BriefDesc + @param[in, out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be + set if the file handle is at the 0 position. + + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. + @retval EFI_SUCCESS the section was found and its description stored in + an allocated buffer if requested. +**/ +EFI_STATUS +ManFileFindTitleSection( + IN SHELL_FILE_HANDLE Handle, + IN CONST CHAR16 *Command, + OUT CHAR16 **BriefDesc OPTIONAL, + OUT UINTN *BriefSize OPTIONAL, + IN OUT BOOLEAN *Ascii + ) +{ + EFI_STATUS Status; + CHAR16 *ReadLine; + UINTN Size; + BOOLEAN Found; + UINTN Start; + + if ( Handle == NULL + || Command == NULL + || (BriefDesc != NULL && BriefSize == NULL) + ){ + return (EFI_INVALID_PARAMETER); + } + + Status = EFI_SUCCESS; + Size = 1024; + Found = FALSE; + + ReadLine = AllocateZeroPool(Size); + if (ReadLine == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // Do not pass any leading path information that may be present to IsTitleHeader(). + // + Start = StrLen(Command); + while ((Start != 0) + && (*(Command + Start - 1) != L'\\') + && (*(Command + Start - 1) != L'/') + && (*(Command + Start - 1) != L':')) { + --Start; + } + + for (;!ShellFileHandleEof(Handle);Size = 1024) { + Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, Ascii); + // + // ignore too small of buffer... + // + if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { + break; + } + + Status = EFI_NOT_FOUND; + if (IsTitleHeader (Command+Start, ReadLine, BriefDesc, BriefSize, &Found)) { + Status = Found ? EFI_SUCCESS : EFI_NOT_FOUND; + break; + } + } + + FreePool(ReadLine); + return (Status); +} + +/** + This function returns the help information for the specified command. The help text + will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B) + + If Sections is specified, then each section name listed will be compared in a casesensitive + manner, to the section names described in Appendix B. If the section exists, + it will be appended to the returned help text. If the section does not exist, no + information will be returned. If Sections is NULL, then all help text information + available will be returned. + + if BriefDesc is NULL, then the breif description will not be savedd seperatly, + but placed first in the main HelpText. + + @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name. + @param[in] Command Points to the NULL-terminated UEFI Shell command name. + @param[in] Sections Points to the NULL-terminated comma-delimited + section names to return. If NULL, then all + sections will be returned. + @param[out] BriefDesc On return, points to a callee-allocated buffer + containing brief description text. + @param[out] HelpText On return, points to a callee-allocated buffer + containing all specified help text. + + @retval EFI_SUCCESS The help text was returned. + @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the + returned help text. + @retval EFI_INVALID_PARAMETER HelpText is NULL. + @retval EFI_INVALID_PARAMETER ManFileName is invalid. + @retval EFI_NOT_FOUND There is no help text available for Command. +**/ +EFI_STATUS +ProcessManFile( + IN CONST CHAR16 *ManFileName, + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Sections OPTIONAL, + OUT CHAR16 **BriefDesc OPTIONAL, + OUT CHAR16 **HelpText + ) +{ + CHAR16 *TempString; + SHELL_FILE_HANDLE FileHandle; + EFI_HANDLE CmdFileImgHandle; + EFI_STATUS Status; + UINTN HelpSize; + UINTN BriefSize; + UINTN StringIdWalker; + BOOLEAN Ascii; + CHAR16 *CmdFileName; + CHAR16 *CmdFilePathName; + EFI_DEVICE_PATH_PROTOCOL *FileDevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + + if ( ManFileName == NULL + || Command == NULL + || HelpText == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + + HelpSize = 0; + BriefSize = 0; + StringIdWalker = 0; + TempString = NULL; + Ascii = FALSE; + CmdFileName = NULL; + CmdFilePathName = NULL; + CmdFileImgHandle = NULL; + PackageListHeader = NULL; + FileDevPath = NULL; + DevPath = NULL; + + // + // See if it's in HII first + // + TempString = ShellCommandGetCommandHelp(Command); + if (TempString != NULL) { + FileHandle = ConvertEfiFileProtocolToShellHandle (CreateFileInterfaceMem (TRUE), NULL); + HelpSize = StrLen (TempString) * sizeof (CHAR16); + ShellWriteFile (FileHandle, &HelpSize, TempString); + ShellSetFilePosition (FileHandle, 0); + HelpSize = 0; + BriefSize = 0; + Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii); + if (!EFI_ERROR(Status) && HelpText != NULL){ + Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii); + } + ShellCloseFile (&FileHandle); + } else { + // + // If the image is a external app, check .MAN file first. + // + FileHandle = NULL; + TempString = GetManFileName(ManFileName); + if (TempString == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Status = SearchPathForFile(TempString, &FileHandle); + if (EFI_ERROR(Status)) { + FileDevPath = FileDevicePath(NULL, TempString); + DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, FileDevPath); + Status = InternalOpenFileDevicePath(DevPath, &FileHandle, EFI_FILE_MODE_READ, 0); + SHELL_FREE_NON_NULL(FileDevPath); + SHELL_FREE_NON_NULL(DevPath); + } + + if (!EFI_ERROR(Status)) { + HelpSize = 0; + BriefSize = 0; + Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii); + if (!EFI_ERROR(Status) && HelpText != NULL){ + Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii); + } + ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle); + if (!EFI_ERROR(Status)) { + // + // Get help text from .MAN file success. + // + goto Done; + } + } + + // + // Load the app image to check EFI_HII_PACKAGE_LIST_PROTOCOL. + // + CmdFileName = GetExecuatableFileName(TempString); + if (CmdFileName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + // + // If the file in CWD then use the file name, else use the full + // path name. + // + CmdFilePathName = ShellFindFilePath(CmdFileName); + if (CmdFilePathName == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CmdFilePathName); + Status = gBS->LoadImage(FALSE, gImageHandle, DevPath, NULL, 0, &CmdFileImgHandle); + if(EFI_ERROR(Status)) { + *HelpText = NULL; + goto Done; + } + Status = gBS->OpenProtocol( + CmdFileImgHandle, + &gEfiHiiPackageListProtocolGuid, + (VOID**)&PackageListHeader, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if(EFI_ERROR(Status)) { + *HelpText = NULL; + goto Done; + } + + // + // If get package list on image handle, install it on HiiDatabase. + // + Status = gBS->InstallProtocolInterface ( + &mShellManDriverHandle, + &gEfiDevicePathProtocolGuid, + EFI_NATIVE_INTERFACE, + &mShellManHiiDevicePath + ); + if (EFI_ERROR(Status)) { + goto Done; + } + + Status = gHiiDatabase->NewPackageList ( + gHiiDatabase, + PackageListHeader, + mShellManDriverHandle, + &mShellManHiiHandle + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + StringIdWalker = 1; + do { + SHELL_FREE_NON_NULL(TempString); + if (BriefDesc != NULL) { + SHELL_FREE_NON_NULL(*BriefDesc); + } + TempString = HiiGetString (mShellManHiiHandle, (EFI_STRING_ID)StringIdWalker, NULL); + if (TempString == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + FileHandle = ConvertEfiFileProtocolToShellHandle (CreateFileInterfaceMem (TRUE), NULL); + HelpSize = StrLen (TempString) * sizeof (CHAR16); + ShellWriteFile (FileHandle, &HelpSize, TempString); + ShellSetFilePosition (FileHandle, 0); + HelpSize = 0; + BriefSize = 0; + Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii); + if (!EFI_ERROR(Status) && HelpText != NULL){ + Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii); + } + ShellCloseFile (&FileHandle); + if (!EFI_ERROR(Status)){ + // + // Found what we need and return + // + goto Done; + } + + StringIdWalker += 1; + } while (StringIdWalker < 0xFFFF && TempString != NULL); + + } + +Done: + if (mShellManDriverHandle != NULL) { + gBS->UninstallProtocolInterface ( + mShellManDriverHandle, + &gEfiDevicePathProtocolGuid, + &mShellManHiiDevicePath + ); + mShellManDriverHandle = NULL; + } + + if (mShellManHiiHandle != NULL) { + HiiRemovePackages (mShellManHiiHandle); + mShellManHiiHandle = NULL; + } + + if (CmdFileImgHandle != NULL) { + Status = gBS->UnloadImage (CmdFileImgHandle); + } + + SHELL_FREE_NON_NULL(TempString); + SHELL_FREE_NON_NULL(CmdFileName); + SHELL_FREE_NON_NULL(CmdFilePathName); + SHELL_FREE_NON_NULL(FileDevPath); + SHELL_FREE_NON_NULL(DevPath); + + return (Status); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.h new file mode 100644 index 0000000..7d9074d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellManParser.h @@ -0,0 +1,84 @@ +/** @file + Provides interface to shell MAN file parser. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_MAN_FILE_PARSER_HEADER_ +#define _SHELL_MAN_FILE_PARSER_HEADER_ + +/** + This function returns the help information for the specified command. The help text + will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B) + + If Sections is specified, then each section name listed will be compared in a casesensitive + manner, to the section names described in Appendix B. If the section exists, + it will be appended to the returned help text. If the section does not exist, no + information will be returned. If Sections is NULL, then all help text information + available will be returned. + + if BriefDesc is NULL, then the breif description will not be savedd seperatly, + but placed first in the main HelpText. + + @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name. + @param[in] Command Points to the NULL-terminated UEFI Shell command name. + @param[in] Sections Points to the NULL-terminated comma-delimited + section names to return. If NULL, then all + sections will be returned. + @param[out] BriefDesc On return, points to a callee-allocated buffer + containing brief description text. + @param[out] HelpText On return, points to a callee-allocated buffer + containing all specified help text. + + @retval EFI_SUCCESS The help text was returned. + @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the + returned help text. + @retval EFI_INVALID_PARAMETER HelpText is NULL + @retval EFI_NOT_FOUND There is no help text available for Command. +**/ +EFI_STATUS +ProcessManFile( + IN CONST CHAR16 *ManFileName, + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Sections OPTIONAL, + OUT CHAR16 **BriefDesc, + OUT CHAR16 **HelpText + ); + +/** + parses through the MAN file specified by SHELL_FILE_HANDLE and returns the + detailed help for any sub section specified in the comma seperated list of + sections provided. If the end of the file or a .TH section is found then + return. + + Upon a sucessful return the caller is responsible to free the memory in *HelpText + + @param[in] Handle FileHandle to read from + @param[in] Sections name of command's sub sections to find + @param[out] HelpText pointer to pointer to string where text goes. + @param[out] HelpSize pointer to size of allocated HelpText (may be updated) + @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise. + + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. + @retval EFI_SUCCESS the section was found and its description sotred in + an alloceted buffer. +**/ +EFI_STATUS +ManFileFindSections( + IN SHELL_FILE_HANDLE Handle, + IN CONST CHAR16 *Sections, + OUT CHAR16 **HelpText, + OUT UINTN *HelpSize, + IN BOOLEAN Ascii + ); + +#endif //_SHELL_MAN_FILE_PARSER_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c new file mode 100644 index 0000000..fb2783a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c @@ -0,0 +1,1417 @@ +/** @file + Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation, + manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + Copyright (C) 2014, Red Hat, Inc. + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" + +BOOLEAN AsciiRedirection = FALSE; + +/** + Return the next parameter's end from a command line string. + + @param[in] String the string to parse +**/ +CONST CHAR16* +FindEndOfParameter( + IN CONST CHAR16 *String + ) +{ + CONST CHAR16 *First; + CONST CHAR16 *CloseQuote; + + First = FindFirstCharacter(String, L" \"", L'^'); + + // + // nothing, all one parameter remaining + // + if (*First == CHAR_NULL) { + return (First); + } + + // + // If space before a quote (or neither found, i.e. both CHAR_NULL), + // then that's the end. + // + if (*First == L' ') { + return (First); + } + + CloseQuote = FindFirstCharacter (First+1, L"\"", L'^'); + + // + // We did not find a terminator... + // + if (*CloseQuote == CHAR_NULL) { + return (NULL); + } + + return (FindEndOfParameter (CloseQuote+1)); +} + +/** + Return the next parameter from a command line string. + + This function moves the next parameter from Walker into TempParameter and moves + Walker up past that parameter for recursive calling. When the final parameter + is moved *Walker will be set to NULL; + + Temp Parameter must be large enough to hold the parameter before calling this + function. + + This will also remove all remaining ^ characters after processing. + + @param[in, out] Walker pointer to string of command line. Adjusted to + reminaing command line on return + @param[in, out] TempParameter pointer to string of command line item extracted. + @param[in] Length buffer size of TempParameter. + @param[in] StripQuotation if TRUE then strip the quotation marks surrounding + the parameters. + + @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. + @return EFI_NOT_FOUND A closing " could not be found on the specified string +**/ +EFI_STATUS +GetNextParameter( + IN OUT CHAR16 **Walker, + IN OUT CHAR16 **TempParameter, + IN CONST UINTN Length, + IN BOOLEAN StripQuotation + ) +{ + CONST CHAR16 *NextDelim; + + if (Walker == NULL + ||*Walker == NULL + ||TempParameter == NULL + ||*TempParameter == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + + + // + // make sure we dont have any leading spaces + // + while ((*Walker)[0] == L' ') { + (*Walker)++; + } + + // + // make sure we still have some params now... + // + if (StrLen(*Walker) == 0) { +DEBUG_CODE_BEGIN(); + *Walker = NULL; +DEBUG_CODE_END(); + return (EFI_INVALID_PARAMETER); + } + + NextDelim = FindEndOfParameter(*Walker); + + if (NextDelim == NULL){ +DEBUG_CODE_BEGIN(); + *Walker = NULL; +DEBUG_CODE_END(); + return (EFI_NOT_FOUND); + } + + StrnCpyS(*TempParameter, Length / sizeof(CHAR16), (*Walker), NextDelim - *Walker); + + // + // Add a CHAR_NULL if we didnt get one via the copy + // + if (*NextDelim != CHAR_NULL) { + (*TempParameter)[NextDelim - *Walker] = CHAR_NULL; + } + + // + // Update Walker for the next iteration through the function + // + *Walker = (CHAR16*)NextDelim; + + // + // Remove any non-escaped quotes in the string + // Remove any remaining escape characters in the string + // + for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL) + ; *NextDelim != CHAR_NULL + ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL) + ) { + if (*NextDelim == L'^') { + + // + // eliminate the escape ^ + // + CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); + NextDelim++; + } else if (*NextDelim == L'\"') { + + // + // eliminate the unescaped quote + // + if (StripQuotation) { + CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); + } else{ + NextDelim++; + } + } + } + + return EFI_SUCCESS; +} + +/** + Function to populate Argc and Argv. + + This function parses the CommandLine and divides it into standard C style Argc/Argv + parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space + delimited and quote surrounded parameter definition. + + All special character processing (alias, environment variable, redirection, + etc... must be complete before calling this API. + + @param[in] CommandLine String of command line to parse + @param[in] StripQuotation if TRUE then strip the quotation marks surrounding + the parameters. + @param[in, out] Argv pointer to array of strings; one for each parameter + @param[in, out] Argc pointer to number of strings in Argv array + + @return EFI_SUCCESS the operation was sucessful + @return EFI_OUT_OF_RESOURCES a memory allocation failed. +**/ +EFI_STATUS +ParseCommandLineToArgs( + IN CONST CHAR16 *CommandLine, + IN BOOLEAN StripQuotation, + IN OUT CHAR16 ***Argv, + IN OUT UINTN *Argc + ) +{ + UINTN Count; + CHAR16 *TempParameter; + CHAR16 *Walker; + CHAR16 *NewParam; + CHAR16 *NewCommandLine; + UINTN Size; + EFI_STATUS Status; + + ASSERT(Argc != NULL); + ASSERT(Argv != NULL); + + if (CommandLine == NULL || StrLen(CommandLine)==0) { + (*Argc) = 0; + (*Argv) = NULL; + return (EFI_SUCCESS); + } + + NewCommandLine = AllocateCopyPool(StrSize(CommandLine), CommandLine); + if (NewCommandLine == NULL){ + return (EFI_OUT_OF_RESOURCES); + } + + TrimSpaces(&NewCommandLine); + Size = StrSize(NewCommandLine); + TempParameter = AllocateZeroPool(Size); + if (TempParameter == NULL) { + SHELL_FREE_NON_NULL(NewCommandLine); + return (EFI_OUT_OF_RESOURCES); + } + + for ( Count = 0 + , Walker = (CHAR16*)NewCommandLine + ; Walker != NULL && *Walker != CHAR_NULL + ; Count++ + ) { + if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, TRUE))) { + break; + } + } + + // + // lets allocate the pointer array + // + (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*)); + if (*Argv == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + *Argc = 0; + Walker = (CHAR16*)NewCommandLine; + while(Walker != NULL && *Walker != CHAR_NULL) { + SetMem16(TempParameter, Size, CHAR_NULL); + if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, StripQuotation))) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter); + if (NewParam == NULL){ + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + ((CHAR16**)(*Argv))[(*Argc)] = NewParam; + (*Argc)++; + } + ASSERT(Count >= (*Argc)); + Status = EFI_SUCCESS; + +Done: + SHELL_FREE_NON_NULL(TempParameter); + SHELL_FREE_NON_NULL(NewCommandLine); + return (Status); +} + +/** + creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then + installs it on our handle and if there is an existing version of the protocol + that one is cached for removal later. + + @param[in, out] NewShellParameters on a successful return, a pointer to pointer + to the newly installed interface. + @param[in, out] RootShellInstance on a successful return, pointer to boolean. + TRUE if this is the root shell instance. + + @retval EFI_SUCCESS the operation completed successfully. + @return other the operation failed. + @sa ReinstallProtocolInterface + @sa InstallProtocolInterface + @sa ParseCommandLineToArgs +**/ +EFI_STATUS +CreatePopulateInstallShellParametersProtocol ( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters, + IN OUT BOOLEAN *RootShellInstance + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + CHAR16 *FullCommandLine; + UINTN Size; + + Size = 0; + FullCommandLine = NULL; + LoadedImage = NULL; + + // + // Assert for valid parameters + // + ASSERT(NewShellParameters != NULL); + ASSERT(RootShellInstance != NULL); + + // + // See if we have a shell parameters placed on us + // + Status = gBS->OpenProtocol ( + gImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **) &ShellInfoObject.OldShellParameters, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + // + // if we don't then we must be the root shell (error is expected) + // + if (EFI_ERROR (Status)) { + *RootShellInstance = TRUE; + } + + // + // Allocate the new structure + // + *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL)); + if ((*NewShellParameters) == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // get loaded image protocol + // + Status = gBS->OpenProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR(Status); + // + // Build the full command line + // + Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine); + if (Status == EFI_BUFFER_TOO_SMALL) { + FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize); + Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine); + } + if (Status == EFI_NOT_FOUND) { + // + // no parameters via environment... ok + // + } else { + if (EFI_ERROR(Status)) { + return (Status); + } + } + if (Size == 0 && LoadedImage->LoadOptionsSize != 0) { + ASSERT(FullCommandLine == NULL); + // + // Now we need to include a NULL terminator in the size. + // + Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]); + FullCommandLine = AllocateZeroPool(Size); + } + if (FullCommandLine != NULL) { + CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize); + // + // Populate Argc and Argv + // + Status = ParseCommandLineToArgs(FullCommandLine, + TRUE, + &(*NewShellParameters)->Argv, + &(*NewShellParameters)->Argc); + + FreePool(FullCommandLine); + + ASSERT_EFI_ERROR(Status); + } else { + (*NewShellParameters)->Argv = NULL; + (*NewShellParameters)->Argc = 0; + } + + // + // Populate the 3 faked file systems... + // + if (*RootShellInstance) { + (*NewShellParameters)->StdIn = &FileInterfaceStdIn; + (*NewShellParameters)->StdOut = &FileInterfaceStdOut; + (*NewShellParameters)->StdErr = &FileInterfaceStdErr; + Status = gBS->InstallProtocolInterface(&gImageHandle, + &gEfiShellParametersProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID*)(*NewShellParameters)); + } else { + // + // copy from the existing ones + // + (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn; + (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut; + (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr; + Status = gBS->ReinstallProtocolInterface(gImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID*)ShellInfoObject.OldShellParameters, + (VOID*)(*NewShellParameters)); + } + + return (Status); +} + +/** + frees all memory used by createion and installation of shell parameters protocol + and if there was an old version installed it will restore that one. + + @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is + being cleaned up. + + @retval EFI_SUCCESS the cleanup was successful + @return other the cleanup failed + @sa ReinstallProtocolInterface + @sa UninstallProtocolInterface +**/ +EFI_STATUS +CleanUpShellParametersProtocol ( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters + ) +{ + EFI_STATUS Status; + UINTN LoopCounter; + + // + // If the old exists we need to restore it + // + if (ShellInfoObject.OldShellParameters != NULL) { + Status = gBS->ReinstallProtocolInterface(gImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID*)NewShellParameters, + (VOID*)ShellInfoObject.OldShellParameters); + DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;); + } else { + // + // No old one, just uninstall us... + // + Status = gBS->UninstallProtocolInterface(gImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID*)NewShellParameters); + } + if (NewShellParameters->Argv != NULL) { + for ( LoopCounter = 0 + ; LoopCounter < NewShellParameters->Argc + ; LoopCounter++ + ){ + FreePool(NewShellParameters->Argv[LoopCounter]); + } + FreePool(NewShellParameters->Argv); + } + FreePool(NewShellParameters); + return (Status); +} + +/** + Determin if a file name represents a unicode file. + + @param[in] FileName Pointer to the filename to open. + + @retval EFI_SUCCESS The file is a unicode file. + @return An error upon failure. +**/ +EFI_STATUS +IsUnicodeFile( + IN CONST CHAR16 *FileName + ) +{ + SHELL_FILE_HANDLE Handle; + EFI_STATUS Status; + UINT64 OriginalFilePosition; + UINTN CharSize; + CHAR16 CharBuffer; + + Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ); + if (EFI_ERROR(Status)) { + return (Status); + } + gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition); + gEfiShellProtocol->SetFilePosition(Handle, 0); + CharSize = sizeof(CHAR16); + Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer); + if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) { + Status = EFI_BUFFER_TOO_SMALL; + } + gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition); + gEfiShellProtocol->CloseFile(Handle); + return (Status); +} + +/** + Strips out quotes sections of a string. + + All of the characters between quotes is replaced with spaces. + + @param[in, out] TheString A pointer to the string to update. +**/ +VOID +StripQuotes ( + IN OUT CHAR16 *TheString + ) +{ + BOOLEAN RemoveNow; + + for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) { + if (*TheString == L'^' && *(TheString + 1) == L'\"') { + TheString++; + } else if (*TheString == L'\"') { + RemoveNow = (BOOLEAN)!RemoveNow; + } else if (RemoveNow) { + *TheString = L' '; + } + } +} + +/** + Calcualte the 32-bit CRC in a EFI table using the service provided by the + gRuntime service. + + @param Hdr Pointer to an EFI standard header + +**/ +VOID +CalculateEfiHdrCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + UINT32 Crc; + + Hdr->CRC32 = 0; + + // + // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then + // Crc will come back as zero if we set it to zero here + // + Crc = 0; + gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc); + Hdr->CRC32 = Crc; +} + +/** + Fix a string to only have the file name, removing starting at the first space of whatever is quoted. + + @param[in] FileName The filename to start with. + + @retval NULL FileName was invalid. + @return The modified FileName. +**/ +CHAR16* +FixFileName ( + IN CHAR16 *FileName + ) +{ + CHAR16 *Copy; + CHAR16 *TempLocation; + + if (FileName == NULL) { + return (NULL); + } + + if (FileName[0] == L'\"') { + Copy = FileName+1; + if ((TempLocation = StrStr(Copy , L"\"")) != NULL) { + TempLocation[0] = CHAR_NULL; + } + } else { + Copy = FileName; + while(Copy[0] == L' ') { + Copy++; + } + if ((TempLocation = StrStr(Copy , L" ")) != NULL) { + TempLocation[0] = CHAR_NULL; + } + } + + if (Copy[0] == CHAR_NULL) { + return (NULL); + } + + return (Copy); +} + +/** + Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %. + + @param[in] FileName The filename to start with. + + @retval NULL FileName was invalid. + @return The modified FileName. +**/ +CHAR16* +FixVarName ( + IN CHAR16 *FileName + ) +{ + CHAR16 *Copy; + CHAR16 *TempLocation; + + Copy = FileName; + + if (FileName[0] == L'%') { + Copy = FileName+1; + if ((TempLocation = StrStr(Copy , L"%")) != NULL) { + TempLocation[0] = CHAR_NULL; + } + } + + return (FixFileName(Copy)); +} + + +/** + Write the unicode file tag to the specified file. + + It is the caller's responsibility to ensure that + ShellInfoObject.NewEfiShellProtocol has been initialized before calling this + function. + + @param[in] FileHandle The file to write the unicode file tag to. + + @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile. +**/ +EFI_STATUS +WriteFileTag ( + IN SHELL_FILE_HANDLE FileHandle + ) +{ + CHAR16 FileTag; + UINTN Size; + EFI_STATUS Status; + + FileTag = gUnicodeFileTag; + Size = sizeof FileTag; + Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size, + &FileTag); + ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag); + return Status; +} + + +/** + Funcion will replace the current StdIn and StdOut in the ShellParameters protocol + structure by parsing NewCommandLine. The current values are returned to the + user. + + This will also update the system table. + + @param[in, out] ShellParameters Pointer to parameter structure to modify. + @param[in] NewCommandLine The new command line to parse and use. + @param[out] OldStdIn Pointer to old StdIn. + @param[out] OldStdOut Pointer to old StdOut. + @param[out] OldStdErr Pointer to old StdErr. + @param[out] SystemTableInfo Pointer to old system table information. + + @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +UpdateStdInStdOutStdErr( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN CHAR16 *NewCommandLine, + OUT SHELL_FILE_HANDLE *OldStdIn, + OUT SHELL_FILE_HANDLE *OldStdOut, + OUT SHELL_FILE_HANDLE *OldStdErr, + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ) +{ + CHAR16 *CommandLineCopy; + CHAR16 *CommandLineWalker; + CHAR16 *StdErrFileName; + CHAR16 *StdOutFileName; + CHAR16 *StdInFileName; + CHAR16 *StdInVarName; + CHAR16 *StdOutVarName; + CHAR16 *StdErrVarName; + EFI_STATUS Status; + SHELL_FILE_HANDLE TempHandle; + UINT64 FileSize; + BOOLEAN OutUnicode; + BOOLEAN InUnicode; + BOOLEAN ErrUnicode; + BOOLEAN OutAppend; + BOOLEAN ErrAppend; + UINTN Size; + SPLIT_LIST *Split; + CHAR16 *FirstLocation; + BOOLEAN Volatile; + + OutUnicode = TRUE; + InUnicode = TRUE; + AsciiRedirection = FALSE; + ErrUnicode = TRUE; + StdInVarName = NULL; + StdOutVarName = NULL; + StdErrVarName = NULL; + StdErrFileName = NULL; + StdInFileName = NULL; + StdOutFileName = NULL; + ErrAppend = FALSE; + OutAppend = FALSE; + CommandLineCopy = NULL; + FirstLocation = NULL; + + if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) { + return (EFI_INVALID_PARAMETER); + } + + SystemTableInfo->ConIn = gST->ConIn; + SystemTableInfo->ConInHandle = gST->ConsoleInHandle; + SystemTableInfo->ConOut = gST->ConOut; + SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle; + SystemTableInfo->ErrOut = gST->StdErr; + SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle; + *OldStdIn = ShellParameters->StdIn; + *OldStdOut = ShellParameters->StdOut; + *OldStdErr = ShellParameters->StdErr; + + if (NewCommandLine == NULL) { + return (EFI_SUCCESS); + } + + CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0); + if (CommandLineCopy == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = EFI_SUCCESS; + Split = NULL; + FirstLocation = CommandLineCopy + StrLen(CommandLineCopy); + + StripQuotes(CommandLineCopy); + + if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { + Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); + if (Split != NULL && Split->SplitStdIn != NULL) { + ShellParameters->StdIn = Split->SplitStdIn; + } + if (Split != NULL && Split->SplitStdOut != NULL) { + ShellParameters->StdOut = Split->SplitStdOut; + } + } + + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 12, L' '); + StdErrVarName = CommandLineWalker += 6; + ErrAppend = TRUE; + if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 12, L' '); + StdOutVarName = CommandLineWalker += 6; + OutAppend = TRUE; + if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) { + Status = EFI_NOT_FOUND; + } + } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + StdOutVarName = CommandLineWalker += 5; + OutAppend = TRUE; + if (StrStr(CommandLineWalker, L" >>v ") != NULL) { + Status = EFI_NOT_FOUND; + } + } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 8, L' '); + StdOutVarName = CommandLineWalker += 4; + OutAppend = FALSE; + if (StrStr(CommandLineWalker, L" >v ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 12, L' '); + StdOutFileName = CommandLineWalker += 6; + OutAppend = TRUE; + OutUnicode = FALSE; + if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 5; + OutAppend = TRUE; + } + if (StrStr(CommandLineWalker, L" 1>> ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 8, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 4; + OutAppend = TRUE; + } + if (StrStr(CommandLineWalker, L" >> ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 5; + OutAppend = TRUE; + OutUnicode = FALSE; + } + if (StrStr(CommandLineWalker, L" >>a ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 5; + OutAppend = FALSE; + OutUnicode = FALSE; + } + if (StrStr(CommandLineWalker, L" 1>a ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 8, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 4; + OutAppend = FALSE; + OutUnicode = FALSE; + } + if (StrStr(CommandLineWalker, L" >a ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdErrFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdErrFileName = CommandLineWalker += 5; + ErrAppend = TRUE; + } + if (StrStr(CommandLineWalker, L" 2>> ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdErrVarName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdErrVarName = CommandLineWalker += 5; + ErrAppend = FALSE; + } + if (StrStr(CommandLineWalker, L" 2>v ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdOutVarName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutVarName = CommandLineWalker += 5; + OutAppend = FALSE; + } + if (StrStr(CommandLineWalker, L" 1>v ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 10, L' '); + if (StdErrFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdErrFileName = CommandLineWalker += 5; + ErrAppend = FALSE; + ErrUnicode = FALSE; + } + if (StrStr(CommandLineWalker, L" 2>a ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 8, L' '); + if (StdErrFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdErrFileName = CommandLineWalker += 4; + ErrAppend = FALSE; + } + if (StrStr(CommandLineWalker, L" 2> ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 8, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 4; + OutAppend = FALSE; + } + if (StrStr(CommandLineWalker, L" 1> ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 6, L' '); + if (StdOutFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdOutFileName = CommandLineWalker += 3; + OutAppend = FALSE; + } + if (StrStr(CommandLineWalker, L" > ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) { + FirstLocation = MIN(CommandLineWalker, FirstLocation); + SetMem16(CommandLineWalker, 6, L' '); + if (StdInFileName != NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + StdInFileName = CommandLineWalker += 3; + } + if (StrStr(CommandLineWalker, L" < ") != NULL) { + Status = EFI_NOT_FOUND; + } + } + if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L"
        SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL)) + ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL)) + // + // Check that nothing is trying to be output to 2 locations. + // + ||(StdErrFileName != NULL && StdErrVarName != NULL) + ||(StdOutFileName != NULL && StdOutVarName != NULL) + ||(StdInFileName != NULL && StdInVarName != NULL) + // + // Check for no volatile environment variables + // + ||(StdErrVarName != NULL && !EFI_ERROR (IsVolatileEnv (StdErrVarName, &Volatile)) && !Volatile) + ||(StdOutVarName != NULL && !EFI_ERROR (IsVolatileEnv (StdOutVarName, &Volatile)) && !Volatile) + // + // Cant redirect during a reconnect operation. + // + ||(StrStr(NewCommandLine, L"connect -r") != NULL + && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL)) + // + // Check that filetypes (Unicode/Ascii) do not change during an append + // + ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName)))) + ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName)))) + ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName)))) + ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName)))) + ){ + Status = EFI_INVALID_PARAMETER; + ShellParameters->StdIn = *OldStdIn; + ShellParameters->StdOut = *OldStdOut; + ShellParameters->StdErr = *OldStdErr; + } else if (!EFI_ERROR(Status)){ + // + // Open the Std and we should not have conflicts here... + // + + // + // StdErr to a file + // + if (StdErrFileName != NULL) { + if (!ErrAppend) { + // + // delete existing file. + // + ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName); + } + Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0); + if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) { + Status = WriteFileTag (TempHandle); + } + if (!ErrUnicode && !EFI_ERROR(Status)) { + TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); + ASSERT(TempHandle != NULL); + } + if (!EFI_ERROR(Status)) { + ShellParameters->StdErr = TempHandle; + gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr); + } + } + + // + // StdOut to a file + // + if (!EFI_ERROR(Status) && StdOutFileName != NULL) { + if (!OutAppend) { + // + // delete existing file. + // + ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName); + } + Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0); + if (TempHandle == NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + if (gUnicodeCollation->MetaiMatch (gUnicodeCollation, StdOutFileName, L"NUL")) { + //no-op + } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) { + Status = WriteFileTag (TempHandle); + } else if (OutAppend) { + Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize); + if (!EFI_ERROR(Status)) { + // + // When appending to a new unicode file, write the file tag. + // Otherwise (ie. when appending to a new ASCII file, or an + // existent file with any encoding), just seek to the end. + // + Status = (FileSize == 0 && OutUnicode) ? + WriteFileTag (TempHandle) : + ShellInfoObject.NewEfiShellProtocol->SetFilePosition ( + TempHandle, + FileSize); + } + } + if (!OutUnicode && !EFI_ERROR(Status)) { + TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); + ASSERT(TempHandle != NULL); + } + if (!EFI_ERROR(Status)) { + ShellParameters->StdOut = TempHandle; + gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut); + } + } + } + + // + // StdOut to a var + // + if (!EFI_ERROR(Status) && StdOutVarName != NULL) { + if (!OutAppend) { + // + // delete existing variable. + // + SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L""); + } + TempHandle = CreateFileInterfaceEnv(StdOutVarName); + ASSERT(TempHandle != NULL); + ShellParameters->StdOut = TempHandle; + gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut); + } + + // + // StdErr to a var + // + if (!EFI_ERROR(Status) && StdErrVarName != NULL) { + if (!ErrAppend) { + // + // delete existing variable. + // + SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L""); + } + TempHandle = CreateFileInterfaceEnv(StdErrVarName); + ASSERT(TempHandle != NULL); + ShellParameters->StdErr = TempHandle; + gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr); + } + + // + // StdIn from a var + // + if (!EFI_ERROR(Status) && StdInVarName != NULL) { + TempHandle = CreateFileInterfaceEnv(StdInVarName); + if (TempHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + if (!InUnicode) { + TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); + } + Size = 0; + if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) { + Status = EFI_INVALID_PARAMETER; + } else { + ShellParameters->StdIn = TempHandle; + gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle); + } + } + } + + // + // StdIn from a file + // + if (!EFI_ERROR(Status) && StdInFileName != NULL) { + Status = ShellOpenFileByName( + StdInFileName, + &TempHandle, + EFI_FILE_MODE_READ, + 0); + if (!EFI_ERROR(Status)) { + if (!InUnicode) { + // + // Create the ASCII->Unicode conversion layer + // + TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); + } + ShellParameters->StdIn = TempHandle; + gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle); + } + } + } + } + FreePool(CommandLineCopy); + + CalculateEfiHdrCrc(&gST->Hdr); + + if (gST->ConIn == NULL ||gST->ConOut == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } + + if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle); + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle); + } + + return (Status); +} + +/** + Funcion will replace the current StdIn and StdOut in the ShellParameters protocol + structure with StdIn and StdOut. The current values are de-allocated. + + @param[in, out] ShellParameters Pointer to parameter structure to modify. + @param[in] OldStdIn Pointer to old StdIn. + @param[in] OldStdOut Pointer to old StdOut. + @param[in] OldStdErr Pointer to old StdErr. + @param[in] SystemTableInfo Pointer to old system table information. +**/ +EFI_STATUS +RestoreStdInStdOutStdErr ( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN SHELL_FILE_HANDLE *OldStdIn, + IN SHELL_FILE_HANDLE *OldStdOut, + IN SHELL_FILE_HANDLE *OldStdErr, + IN SYSTEM_TABLE_INFO *SystemTableInfo + ) +{ + SPLIT_LIST *Split; + + if (ShellParameters == NULL + ||OldStdIn == NULL + ||OldStdOut == NULL + ||OldStdErr == NULL + ||SystemTableInfo == NULL) { + return (EFI_INVALID_PARAMETER); + } + if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { + Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); + } else { + Split = NULL; + } + if (ShellParameters->StdIn != *OldStdIn) { + if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) { + gEfiShellProtocol->CloseFile(ShellParameters->StdIn); + } + ShellParameters->StdIn = *OldStdIn; + } + if (ShellParameters->StdOut != *OldStdOut) { + if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) { + gEfiShellProtocol->CloseFile(ShellParameters->StdOut); + } + ShellParameters->StdOut = *OldStdOut; + } + if (ShellParameters->StdErr != *OldStdErr) { + gEfiShellProtocol->CloseFile(ShellParameters->StdErr); + ShellParameters->StdErr = *OldStdErr; + } + + if (gST->ConIn != SystemTableInfo->ConIn) { + CloseSimpleTextInOnFile(gST->ConIn); + gST->ConIn = SystemTableInfo->ConIn; + gST->ConsoleInHandle = SystemTableInfo->ConInHandle; + } + if (gST->ConOut != SystemTableInfo->ConOut) { + CloseSimpleTextOutOnFile(gST->ConOut); + gST->ConOut = SystemTableInfo->ConOut; + gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle; + } + if (gST->StdErr != SystemTableInfo->ErrOut) { + CloseSimpleTextOutOnFile(gST->StdErr); + gST->StdErr = SystemTableInfo->ErrOut; + gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle; + } + + CalculateEfiHdrCrc(&gST->Hdr); + + return (EFI_SUCCESS); +} +/** + Funcion will replace the current Argc and Argv in the ShellParameters protocol + structure by parsing NewCommandLine. The current values are returned to the + user. + + If OldArgv or OldArgc is NULL then that value is not returned. + + @param[in, out] ShellParameters Pointer to parameter structure to modify. + @param[in] NewCommandLine The new command line to parse and use. + @param[in] Type The type of operation. + @param[out] OldArgv Pointer to old list of parameters. + @param[out] OldArgc Pointer to old number of items in Argv list. + + @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +UpdateArgcArgv( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN CONST CHAR16 *NewCommandLine, + IN SHELL_OPERATION_TYPES Type, + OUT CHAR16 ***OldArgv OPTIONAL, + OUT UINTN *OldArgc OPTIONAL + ) +{ + BOOLEAN StripParamQuotation; + + ASSERT(ShellParameters != NULL); + StripParamQuotation = TRUE; + + if (OldArgc != NULL) { + *OldArgc = ShellParameters->Argc; + } + if (OldArgc != NULL) { + *OldArgv = ShellParameters->Argv; + } + + if (Type == Script_File_Name) { + StripParamQuotation = FALSE; + } + + return ParseCommandLineToArgs( NewCommandLine, + StripParamQuotation, + &(ShellParameters->Argv), + &(ShellParameters->Argc) + ); +} + +/** + Funcion will replace the current Argc and Argv in the ShellParameters protocol + structure with Argv and Argc. The current values are de-allocated and the + OldArgv must not be deallocated by the caller. + + @param[in, out] ShellParameters pointer to parameter structure to modify + @param[in] OldArgv pointer to old list of parameters + @param[in] OldArgc pointer to old number of items in Argv list +**/ +VOID +RestoreArgcArgv( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN CHAR16 ***OldArgv, + IN UINTN *OldArgc + ) +{ + UINTN LoopCounter; + ASSERT(ShellParameters != NULL); + ASSERT(OldArgv != NULL); + ASSERT(OldArgc != NULL); + + if (ShellParameters->Argv != NULL) { + for ( LoopCounter = 0 + ; LoopCounter < ShellParameters->Argc + ; LoopCounter++ + ){ + FreePool(ShellParameters->Argv[LoopCounter]); + } + FreePool(ShellParameters->Argv); + } + ShellParameters->Argv = *OldArgv; + *OldArgv = NULL; + ShellParameters->Argc = *OldArgc; + *OldArgc = 0; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h new file mode 100644 index 0000000..2024c71 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h @@ -0,0 +1,215 @@ +/** @file + Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation, + manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL. + + Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_ +#define _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_ + +#include "Shell.h" + +typedef enum { + Internal_Command, + Script_File_Name, + Efi_Application, + File_Sys_Change, + Unknown_Invalid +} SHELL_OPERATION_TYPES; + +/** + creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then + installs it on our handle and if there is an existing version of the protocol + that one is cached for removal later. + + @param[in, out] NewShellParameters on a successful return, a pointer to pointer + to the newly installed interface. + @param[in, out] RootShellInstance on a successful return, pointer to boolean. + TRUE if this is the root shell instance. + + @retval EFI_SUCCESS the operation completed successfully. + @return other the operation failed. + @sa ReinstallProtocolInterface + @sa InstallProtocolInterface + @sa ParseCommandLineToArgs +**/ +EFI_STATUS +CreatePopulateInstallShellParametersProtocol ( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters, + IN OUT BOOLEAN *RootShellInstance + ); + +/** + frees all memory used by createion and installation of shell parameters protocol + and if there was an old version installed it will restore that one. + + @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is + being cleaned up. + + @retval EFI_SUCCESS the cleanup was successful + @return other the cleanup failed + @sa ReinstallProtocolInterface + @sa UninstallProtocolInterface +**/ +EFI_STATUS +CleanUpShellParametersProtocol ( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters + ); + +/** + Funcion will replace the current Argc and Argv in the ShellParameters protocol + structure by parsing NewCommandLine. The current values are returned to the + user. + + @param[in, out] ShellParameters pointer to parameter structure to modify + @param[in] NewCommandLine the new command line to parse and use + @param[in] Type the type of operation. + @param[out] OldArgv pointer to old list of parameters + @param[out] OldArgc pointer to old number of items in Argv list + + @retval EFI_SUCCESS operation was sucessful, Argv and Argc are valid + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. +**/ +EFI_STATUS +UpdateArgcArgv( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN CONST CHAR16 *NewCommandLine, + IN SHELL_OPERATION_TYPES Type, + OUT CHAR16 ***OldArgv, + OUT UINTN *OldArgc + ); + +/** + Funcion will replace the current Argc and Argv in the ShellParameters protocol + structure with Argv and Argc. The current values are de-allocated and the + OldArgv must not be deallocated by the caller. + + @param[in, out] ShellParameters pointer to parameter structure to modify + @param[in] OldArgv pointer to old list of parameters + @param[in] OldArgc pointer to old number of items in Argv list +**/ +VOID +RestoreArgcArgv( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN CHAR16 ***OldArgv, + IN UINTN *OldArgc + ); + +typedef struct { + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; + EFI_HANDLE ConInHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; + EFI_HANDLE ConOutHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ErrOut; + EFI_HANDLE ErrOutHandle; +} SYSTEM_TABLE_INFO; + +/** + Funcion will replace the current StdIn and StdOut in the ShellParameters protocol + structure by parsing NewCommandLine. The current values are returned to the + user. + + This will also update the system table. + + @param[in, out] ShellParameters Pointer to parameter structure to modify. + @param[in] NewCommandLine The new command line to parse and use. + @param[out] OldStdIn Pointer to old StdIn. + @param[out] OldStdOut Pointer to old StdOut. + @param[out] OldStdErr Pointer to old StdErr. + @param[out] SystemTableInfo Pointer to old system table information. + + @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +UpdateStdInStdOutStdErr( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN CHAR16 *NewCommandLine, + OUT SHELL_FILE_HANDLE *OldStdIn, + OUT SHELL_FILE_HANDLE *OldStdOut, + OUT SHELL_FILE_HANDLE *OldStdErr, + OUT SYSTEM_TABLE_INFO *SystemTableInfo + ); + +/** + Funcion will replace the current StdIn and StdOut in the ShellParameters protocol + structure with StdIn and StdOut. The current values are de-allocated. + + @param[in, out] ShellParameters Pointer to parameter structure to modify. + @param[in] OldStdIn Pointer to old StdIn. + @param[in] OldStdOut Pointer to old StdOut. + @param[in] OldStdErr Pointer to old StdErr. + @param[in] SystemTableInfo Pointer to old system table information. +**/ +EFI_STATUS +RestoreStdInStdOutStdErr ( + IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN SHELL_FILE_HANDLE *OldStdIn, + IN SHELL_FILE_HANDLE *OldStdOut, + IN SHELL_FILE_HANDLE *OldStdErr, + IN SYSTEM_TABLE_INFO *SystemTableInfo + ); + +/** + function to populate Argc and Argv. + + This function parses the CommandLine and divides it into standard C style Argc/Argv + parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space + delimited and quote surrounded parameter definition. + + @param[in] CommandLine String of command line to parse + @param[in] StripQuotation if TRUE then strip the quotation marks surrounding + the parameters. + @param[in, out] Argv pointer to array of strings; one for each parameter + @param[in, out] Argc pointer to number of strings in Argv array + + @return EFI_SUCCESS the operation was sucessful + @return EFI_OUT_OF_RESOURCES a memory allocation failed. +**/ +EFI_STATUS +ParseCommandLineToArgs( + IN CONST CHAR16 *CommandLine, + IN BOOLEAN StripQuotation, + IN OUT CHAR16 ***Argv, + IN OUT UINTN *Argc + ); + +/** + return the next parameter from a command line string; + + This function moves the next parameter from Walker into TempParameter and moves + Walker up past that parameter for recursive calling. When the final parameter + is moved *Walker will be set to NULL; + + Temp Parameter must be large enough to hold the parameter before calling this + function. + + @param[in, out] Walker pointer to string of command line. Adjusted to + reminaing command line on return + @param[in, out] TempParameter pointer to string of command line item extracted. + @param[in] Length Length of (*TempParameter) in bytes + @param[in] StripQuotation if TRUE then strip the quotation marks surrounding + the parameters. + + @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. + @return EFI_NOT_FOUND A closing " could not be found on the specified string +**/ +EFI_STATUS +GetNextParameter( + IN OUT CHAR16 **Walker, + IN OUT CHAR16 **TempParameter, + IN CONST UINTN Length, + IN BOOLEAN StripQuotation + ); + +#endif //_SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.c new file mode 100644 index 0000000..7af6504 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.c @@ -0,0 +1,3835 @@ +/** @file + Member functions of EFI_SHELL_PROTOCOL and functions for creation, + manipulation, and initialization of EFI_SHELL_PROTOCOL. + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Shell.h" + +#define INIT_NAME_BUFFER_SIZE 128 + +/** + Close an open file handle. + + This function closes a specified file handle. All "dirty" cached file data is + flushed to the device, and the file is closed. In all cases the handle is + closed. + + @param[in] FileHandle The file handle to close. + + @retval EFI_SUCCESS The file handle was closed successfully. +**/ +EFI_STATUS +EFIAPI +EfiShellClose ( + IN SHELL_FILE_HANDLE FileHandle + ) +{ + ShellFileHandleRemove(FileHandle); + return (FileHandleClose(ConvertShellHandleToEfiFileProtocol(FileHandle))); +} + +/** + Internal worker to determine whether there is a BlockIo somewhere + upon the device path specified. + + @param[in] DevicePath The device path to test. + + @retval TRUE gEfiBlockIoProtocolGuid was installed on a handle with this device path + @retval FALSE gEfiBlockIoProtocolGuid was not found. +**/ +BOOLEAN +InternalShellProtocolIsBlockIoPresent( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy; + EFI_STATUS Status; + EFI_HANDLE Handle; + + Handle = NULL; + + DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)DevicePath; + Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &DevicePathCopy, &Handle); + + if ((Handle != NULL) && (!EFI_ERROR(Status))) { + return (TRUE); + } + return (FALSE); +} + +/** + Internal worker to determine whether there is a file system somewhere + upon the device path specified. + + @param[in] DevicePath The device path to test. + + @retval TRUE gEfiSimpleFileSystemProtocolGuid was installed on a handle with this device path + @retval FALSE gEfiSimpleFileSystemProtocolGuid was not found. +**/ +BOOLEAN +InternalShellProtocolIsSimpleFileSystemPresent( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy; + EFI_STATUS Status; + EFI_HANDLE Handle; + + Handle = NULL; + + DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)DevicePath; + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &Handle); + + if ((Handle != NULL) && (!EFI_ERROR(Status))) { + return (TRUE); + } + return (FALSE); +} + + +/** + This function creates a mapping for a device path. + + If both DeviecPath and Mapping are NULL, this will reset the mapping to default values. + + @param DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping, + then the mapping will be deleted. + @param Mapping Points to the NULL-terminated mapping for the device path. Must end with a ':' + + @retval EFI_SUCCESS Mapping created or deleted successfully. + @retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath. See the + boot service function LocateDevicePath(). + @retval EFI_ACCESS_DENIED The mapping is a built-in alias. + @retval EFI_INVALID_PARAMETER Mapping was NULL + @retval EFI_INVALID_PARAMETER Mapping did not end with a ':' + @retval EFI_INVALID_PARAMETER DevicePath was not pointing at a device that had a SIMPLE_FILE_SYSTEM_PROTOCOL installed. + @retval EFI_NOT_FOUND There was no mapping found to delete + @retval EFI_OUT_OF_RESOURCES Memory allocation failed +**/ +EFI_STATUS +EFIAPI +EfiShellSetMap( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, + IN CONST CHAR16 *Mapping + ) +{ + EFI_STATUS Status; + SHELL_MAP_LIST *MapListNode; + + if (Mapping == NULL){ + return (EFI_INVALID_PARAMETER); + } + + if (Mapping[StrLen(Mapping)-1] != ':') { + return (EFI_INVALID_PARAMETER); + } + + // + // Delete the mapping + // + if (DevicePath == NULL) { + if (IsListEmpty(&gShellMapList.Link)) { + return (EFI_NOT_FOUND); + } + for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsNull(&gShellMapList.Link, &MapListNode->Link) + ; MapListNode = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListNode->Link) + ){ + if (StringNoCaseCompare(&MapListNode->MapName, &Mapping) == 0) { + RemoveEntryList(&MapListNode->Link); + SHELL_FREE_NON_NULL(MapListNode->DevicePath); + SHELL_FREE_NON_NULL(MapListNode->MapName); + SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath); + FreePool(MapListNode); + return (EFI_SUCCESS); + } + } // for loop + + // + // We didnt find one to delete + // + return (EFI_NOT_FOUND); + } + + // + // make sure this is a valid to add device path + // + ///@todo add BlockIo to this test... + if (!InternalShellProtocolIsSimpleFileSystemPresent(DevicePath) + && !InternalShellProtocolIsBlockIoPresent(DevicePath)) { + return (EFI_INVALID_PARAMETER); + } + + // + // First make sure there is no old mapping + // + Status = EfiShellSetMap(NULL, Mapping); + if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_FOUND)) { + return (Status); + } + + // + // now add the new one. + // + Status = ShellCommandAddMapItemAndUpdatePath(Mapping, DevicePath, 0, FALSE); + + return(Status); +} + +/** + Gets the device path from the mapping. + + This function gets the device path associated with a mapping. + + @param Mapping A pointer to the mapping + + @retval !=NULL Pointer to the device path that corresponds to the + device mapping. The returned pointer does not need + to be freed. + @retval NULL There is no device path associated with the + specified mapping. +**/ +CONST EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +EfiShellGetDevicePathFromMap( + IN CONST CHAR16 *Mapping + ) +{ + SHELL_MAP_LIST *MapListItem; + CHAR16 *NewName; + UINTN Size; + + NewName = NULL; + Size = 0; + + StrnCatGrow(&NewName, &Size, Mapping, 0); + if (Mapping[StrLen(Mapping)-1] != L':') { + StrnCatGrow(&NewName, &Size, L":", 0); + } + + MapListItem = ShellCommandFindMapItem(NewName); + + FreePool(NewName); + + if (MapListItem != NULL) { + return (MapListItem->DevicePath); + } + return(NULL); +} + +/** + Gets the mapping(s) that most closely matches the device path. + + This function gets the mapping which corresponds to the device path *DevicePath. If + there is no exact match, then the mapping which most closely matches *DevicePath + is returned, and *DevicePath is updated to point to the remaining portion of the + device path. If there is an exact match, the mapping is returned and *DevicePath + points to the end-of-device-path node. + + If there are multiple map names they will be semi-colon seperated in the + NULL-terminated string. + + @param DevicePath On entry, points to a device path pointer. On + exit, updates the pointer to point to the + portion of the device path after the mapping. + + @retval NULL No mapping was found. + @return !=NULL Pointer to NULL-terminated mapping. The buffer + is callee allocated and should be freed by the caller. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetMapFromDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + SHELL_MAP_LIST *Node; + CHAR16 *PathForReturn; + UINTN PathSize; +// EFI_HANDLE PathHandle; +// EFI_HANDLE MapHandle; +// EFI_STATUS Status; +// EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy; +// EFI_DEVICE_PATH_PROTOCOL *MapPathCopy; + + if (DevicePath == NULL || *DevicePath == NULL) { + return (NULL); + } + + PathForReturn = NULL; + PathSize = 0; + + for ( Node = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsNull(&gShellMapList.Link, &Node->Link) + ; Node = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &Node->Link) + ){ + // + // check for exact match + // + if (DevicePathCompare(DevicePath, &Node->DevicePath) == 0) { + ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL)); + if (PathSize != 0) { + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L";", 0); + } + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, Node->MapName, 0); + } + } + if (PathForReturn != NULL) { + while (!IsDevicePathEndType (*DevicePath)) { + *DevicePath = NextDevicePathNode (*DevicePath); + } + SetDevicePathEndNode (*DevicePath); + } +/* + ///@todo finish code for inexact matches. + if (PathForReturn == NULL) { + PathSize = 0; + + DevicePathCopy = DuplicateDevicePath(*DevicePath); + ASSERT(DevicePathCopy != NULL); + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &PathHandle); + ASSERT_EFI_ERROR(Status); + // + // check each of the device paths we have to get the root of the path for consist mappings + // + for ( Node = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsNull(&gShellMapList.Link, &Node->Link) + ; Node = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &Node->Link) + ){ + if ((Node->Flags & SHELL_MAP_FLAGS_CONSIST) == 0) { + continue; + } + MapPathCopy = DuplicateDevicePath(Node->DevicePath); + ASSERT(MapPathCopy != NULL); + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &MapPathCopy, &MapHandle); + if (MapHandle == PathHandle) { + + *DevicePath = DevicePathCopy; + + MapPathCopy = NULL; + DevicePathCopy = NULL; + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, Node->MapName, 0); + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L";", 0); + break; + } + } + // + // now add on the non-consistent mappings + // + for ( Node = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsNull(&gShellMapList.Link, &Node->Link) + ; Node = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &Node->Link) + ){ + if ((Node->Flags & SHELL_MAP_FLAGS_CONSIST) != 0) { + continue; + } + MapPathCopy = Node->DevicePath; + ASSERT(MapPathCopy != NULL); + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &MapPathCopy, &MapHandle); + if (MapHandle == PathHandle) { + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, Node->MapName, 0); + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L";", 0); + break; + } + } + } +*/ + + return (AddBufferToFreeList(PathForReturn)); +} + +/** + Converts a device path to a file system-style path. + + This function converts a device path to a file system path by replacing part, or all, of + the device path with the file-system mapping. If there are more than one application + file system mappings, the one that most closely matches Path will be used. + + @param Path The pointer to the device path + + @retval NULL the device path could not be found. + @return all The pointer of the NULL-terminated file path. The path + is callee-allocated and should be freed by the caller. +**/ +CHAR16 * +EFIAPI +EfiShellGetFilePathFromDevicePath( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Path + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy; + EFI_DEVICE_PATH_PROTOCOL *MapPathCopy; + SHELL_MAP_LIST *MapListItem; + CHAR16 *PathForReturn; + UINTN PathSize; + EFI_HANDLE PathHandle; + EFI_HANDLE MapHandle; + EFI_STATUS Status; + FILEPATH_DEVICE_PATH *FilePath; + FILEPATH_DEVICE_PATH *AlignedNode; + + PathForReturn = NULL; + PathSize = 0; + + DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)Path; + ASSERT(DevicePathCopy != NULL); + if (DevicePathCopy == NULL) { + return (NULL); + } + ///@todo BlockIo? + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &PathHandle); + + if (EFI_ERROR(Status)) { + return (NULL); + } + // + // check each of the device paths we have to get the root of the path + // + for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsNull(&gShellMapList.Link, &MapListItem->Link) + ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link) + ){ + MapPathCopy = (EFI_DEVICE_PATH_PROTOCOL*)MapListItem->DevicePath; + ASSERT(MapPathCopy != NULL); + ///@todo BlockIo? + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &MapPathCopy, &MapHandle); + if (MapHandle == PathHandle) { + ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL)); + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, MapListItem->MapName, 0); + // + // go through all the remaining nodes in the device path + // + for ( FilePath = (FILEPATH_DEVICE_PATH*)DevicePathCopy + ; !IsDevicePathEnd (&FilePath->Header) + ; FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode (&FilePath->Header) + ){ + // + // If any node is not a file path node, then the conversion can not be completed + // + if ((DevicePathType(&FilePath->Header) != MEDIA_DEVICE_PATH) || + (DevicePathSubType(&FilePath->Header) != MEDIA_FILEPATH_DP)) { + FreePool(PathForReturn); + return NULL; + } + + // + // append the path part onto the filepath. + // + ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL)); + + AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath); + if (AlignedNode == NULL) { + FreePool (PathForReturn); + return NULL; + } + + // File Path Device Path Nodes 'can optionally add a "\" separator to + // the beginning and/or the end of the Path Name string.' + // (UEFI Spec 2.4 section 9.3.6.4). + // If necessary, add a "\", but otherwise don't + // (This is specified in the above section, and also implied by the + // UEFI Shell spec section 3.7) + if ((PathSize != 0) && + (PathForReturn != NULL) && + (PathForReturn[PathSize / sizeof (CHAR16) - 1] != L'\\') && + (AlignedNode->PathName[0] != L'\\')) { + PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1); + } + + PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0); + FreePool(AlignedNode); + } // for loop of remaining nodes + } + if (PathForReturn != NULL) { + break; + } + } // for loop of paths to check + return(PathForReturn); +} + +/** + Converts a file system style name to a device path. + + This function converts a file system style name to a device path, by replacing any + mapping references to the associated device path. + + @param[in] Path The pointer to the path. + + @return The pointer of the file path. The file path is callee + allocated and should be freed by the caller. + @retval NULL The path could not be found. + @retval NULL There was not enough available memory. +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +EfiShellGetDevicePathFromFilePath( + IN CONST CHAR16 *Path + ) +{ + CHAR16 *MapName; + CHAR16 *NewPath; + CONST CHAR16 *Cwd; + UINTN Size; + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy; + EFI_DEVICE_PATH_PROTOCOL *DevicePathCopyForFree; + EFI_DEVICE_PATH_PROTOCOL *DevicePathForReturn; + EFI_HANDLE Handle; + EFI_STATUS Status; + + if (Path == NULL) { + return (NULL); + } + + MapName = NULL; + NewPath = NULL; + + if (StrStr(Path, L":") == NULL) { + Cwd = EfiShellGetCurDir(NULL); + if (Cwd == NULL) { + return (NULL); + } + Size = StrSize(Cwd) + StrSize(Path); + NewPath = AllocateZeroPool(Size); + if (NewPath == NULL) { + return (NULL); + } + StrCpyS(NewPath, Size/sizeof(CHAR16), Cwd); + StrCatS(NewPath, Size/sizeof(CHAR16), L"\\"); + if (*Path == L'\\') { + Path++; + while (PathRemoveLastItem(NewPath)) ; + } + StrCatS(NewPath, Size/sizeof(CHAR16), Path); + DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath); + FreePool(NewPath); + return (DevicePathForReturn); + } + + Size = 0; + // + // find the part before (but including) the : for the map name + // + ASSERT((MapName == NULL && Size == 0) || (MapName != NULL)); + MapName = StrnCatGrow(&MapName, &Size, Path, (StrStr(Path, L":")-Path+1)); + if (MapName == NULL || MapName[StrLen(MapName)-1] != L':') { + return (NULL); + } + + // + // look up the device path in the map + // + DevicePath = EfiShellGetDevicePathFromMap(MapName); + if (DevicePath == NULL) { + // + // Must have been a bad Mapname + // + return (NULL); + } + + // + // make a copy for LocateDevicePath to modify (also save a pointer to call FreePool with) + // + DevicePathCopyForFree = DevicePathCopy = DuplicateDevicePath(DevicePath); + if (DevicePathCopy == NULL) { + FreePool(MapName); + return (NULL); + } + + // + // get the handle + // + ///@todo BlockIo? + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &Handle); + if (EFI_ERROR(Status)) { + if (DevicePathCopyForFree != NULL) { + FreePool(DevicePathCopyForFree); + } + FreePool(MapName); + return (NULL); + } + + // + // build the full device path + // + if ((*(Path+StrLen(MapName)) != CHAR_NULL) && + (*(Path+StrLen(MapName)+1) == CHAR_NULL)) { + DevicePathForReturn = FileDevicePath(Handle, L"\\"); + } else { + DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName)); + } + + FreePool(MapName); + if (DevicePathCopyForFree != NULL) { + FreePool(DevicePathCopyForFree); + } + + return (DevicePathForReturn); +} + +/** + Gets the name of the device specified by the device handle. + + This function gets the user-readable name of the device specified by the device + handle. If no user-readable name could be generated, then *BestDeviceName will be + NULL and EFI_NOT_FOUND will be returned. + + If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the + device's name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on + DeviceHandle. + + If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the + device's name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle. + If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and + EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then + EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority. + + @param DeviceHandle The handle of the device. + @param Flags Determines the possible sources of component names. + Valid bits are: + EFI_DEVICE_NAME_USE_COMPONENT_NAME + EFI_DEVICE_NAME_USE_DEVICE_PATH + @param Language A pointer to the language specified for the device + name, in the same format as described in the UEFI + specification, Appendix M + @param BestDeviceName On return, points to the callee-allocated NULL- + terminated name of the device. If no device name + could be found, points to NULL. The name must be + freed by the caller... + + @retval EFI_SUCCESS Get the name successfully. + @retval EFI_NOT_FOUND Fail to get the device name. + @retval EFI_INVALID_PARAMETER Flags did not have a valid bit set. + @retval EFI_INVALID_PARAMETER BestDeviceName was NULL + @retval EFI_INVALID_PARAMETER DeviceHandle was NULL +**/ +EFI_STATUS +EFIAPI +EfiShellGetDeviceName( + IN EFI_HANDLE DeviceHandle, + IN EFI_SHELL_DEVICE_NAME_FLAGS Flags, + IN CHAR8 *Language, + OUT CHAR16 **BestDeviceName + ) +{ + EFI_STATUS Status; + EFI_COMPONENT_NAME2_PROTOCOL *CompName2; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE *HandleList; + UINTN HandleCount; + UINTN LoopVar; + CHAR16 *DeviceNameToReturn; + CHAR8 *Lang; + UINTN ParentControllerCount; + EFI_HANDLE *ParentControllerBuffer; + UINTN ParentDriverCount; + EFI_HANDLE *ParentDriverBuffer; + + if (BestDeviceName == NULL || + DeviceHandle == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + + // + // make sure one of the 2 supported bits is on + // + if (((Flags & EFI_DEVICE_NAME_USE_COMPONENT_NAME) == 0) && + ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) == 0)) { + return (EFI_INVALID_PARAMETER); + } + + DeviceNameToReturn = NULL; + *BestDeviceName = NULL; + HandleList = NULL; + HandleCount = 0; + Lang = NULL; + + if ((Flags & EFI_DEVICE_NAME_USE_COMPONENT_NAME) != 0) { + Status = ParseHandleDatabaseByRelationship( + NULL, + DeviceHandle, + HR_DRIVER_BINDING_HANDLE|HR_DEVICE_DRIVER, + &HandleCount, + &HandleList); + for (LoopVar = 0; LoopVar < HandleCount ; LoopVar++){ + // + // Go through those handles until we get one that passes for GetComponentName + // + Status = gBS->OpenProtocol( + HandleList[LoopVar], + &gEfiComponentName2ProtocolGuid, + (VOID**)&CompName2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + Status = gBS->OpenProtocol( + HandleList[LoopVar], + &gEfiComponentNameProtocolGuid, + (VOID**)&CompName2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + } + + if (EFI_ERROR(Status)) { + continue; + } + Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE); + Status = CompName2->GetControllerName(CompName2, DeviceHandle, NULL, Lang, &DeviceNameToReturn); + FreePool(Lang); + Lang = NULL; + if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) { + break; + } + } + if (HandleList != NULL) { + FreePool(HandleList); + } + + // + // Now check the parent controller using this as the child. + // + if (DeviceNameToReturn == NULL){ + PARSE_HANDLE_DATABASE_PARENTS(DeviceHandle, &ParentControllerCount, &ParentControllerBuffer); + for (LoopVar = 0 ; LoopVar < ParentControllerCount ; LoopVar++) { + PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ParentControllerBuffer[LoopVar], &ParentDriverCount, &ParentDriverBuffer); + for (HandleCount = 0 ; HandleCount < ParentDriverCount ; HandleCount++) { + // + // try using that driver's component name with controller and our driver as the child. + // + Status = gBS->OpenProtocol( + ParentDriverBuffer[HandleCount], + &gEfiComponentName2ProtocolGuid, + (VOID**)&CompName2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + Status = gBS->OpenProtocol( + ParentDriverBuffer[HandleCount], + &gEfiComponentNameProtocolGuid, + (VOID**)&CompName2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + } + + if (EFI_ERROR(Status)) { + continue; + } + Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE); + Status = CompName2->GetControllerName(CompName2, ParentControllerBuffer[LoopVar], DeviceHandle, Lang, &DeviceNameToReturn); + FreePool(Lang); + Lang = NULL; + if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) { + break; + } + + + + } + SHELL_FREE_NON_NULL(ParentDriverBuffer); + if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) { + break; + } + } + SHELL_FREE_NON_NULL(ParentControllerBuffer); + } + // + // dont return on fail since we will try device path if that bit is on + // + if (DeviceNameToReturn != NULL){ + ASSERT(BestDeviceName != NULL); + StrnCatGrow(BestDeviceName, NULL, DeviceNameToReturn, 0); + return (EFI_SUCCESS); + } + } + if ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) != 0) { + Status = gBS->OpenProtocol( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&DevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status)) { + // + // use device path to text on the device path + // + *BestDeviceName = ConvertDevicePathToText(DevicePath, TRUE, TRUE); + return (EFI_SUCCESS); + } + } + // + // none of the selected bits worked. + // + return (EFI_NOT_FOUND); +} + +/** + Opens the root directory of a device on a handle + + This function opens the root directory of a device and returns a file handle to it. + + @param DeviceHandle The handle of the device that contains the volume. + @param FileHandle On exit, points to the file handle corresponding to the root directory on the + device. + + @retval EFI_SUCCESS Root opened successfully. + @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory + could not be opened. + @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted. + @retval EFI_DEVICE_ERROR The device had an error. + @retval Others Error status returned from EFI_SIMPLE_FILE_SYSTEM_PROTOCOL->OpenVolume(). +**/ +EFI_STATUS +EFIAPI +EfiShellOpenRootByHandle( + IN EFI_HANDLE DeviceHandle, + OUT SHELL_FILE_HANDLE *FileHandle + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + EFI_FILE_PROTOCOL *RealFileHandle; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + // + // get the simple file system interface + // + Status = gBS->OpenProtocol(DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**)&SimpleFileSystem, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + return (EFI_NOT_FOUND); + } + + Status = gBS->OpenProtocol(DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&DevPath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + return (EFI_NOT_FOUND); + } + // + // Open the root volume now... + // + Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &RealFileHandle); + if (EFI_ERROR(Status)) { + return Status; + } + + *FileHandle = ConvertEfiFileProtocolToShellHandle(RealFileHandle, EfiShellGetMapFromDevicePath(&DevPath)); + return (EFI_SUCCESS); +} + +/** + Opens the root directory of a device. + + This function opens the root directory of a device and returns a file handle to it. + + @param DevicePath Points to the device path corresponding to the device where the + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed. + @param FileHandle On exit, points to the file handle corresponding to the root directory on the + device. + + @retval EFI_SUCCESS Root opened successfully. + @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory + could not be opened. + @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted. + @retval EFI_DEVICE_ERROR The device had an error + @retval EFI_INVALID_PARAMETER FileHandle is NULL. +**/ +EFI_STATUS +EFIAPI +EfiShellOpenRoot( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT SHELL_FILE_HANDLE *FileHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // find the handle of the device with that device handle and the file system + // + ///@todo BlockIo? + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, + &DevicePath, + &Handle); + if (EFI_ERROR(Status)) { + return (EFI_NOT_FOUND); + } + + return (EfiShellOpenRootByHandle(Handle, FileHandle)); +} + +/** + Returns whether any script files are currently being processed. + + @retval TRUE There is at least one script file active. + @retval FALSE No script files are active now. + +**/ +BOOLEAN +EFIAPI +EfiShellBatchIsActive ( + VOID + ) +{ + if (ShellCommandGetCurrentScriptFile() == NULL) { + return (FALSE); + } + return (TRUE); +} + +/** + Worker function to open a file based on a device path. this will open the root + of the volume and then traverse down to the file itself. + + @param DevicePath Device Path of the file. + @param FileHandle Pointer to the file upon a successful return. + @param OpenMode mode to open file in. + @param Attributes the File Attributes to use when creating a new file. + + @retval EFI_SUCCESS the file is open and FileHandle is valid + @retval EFI_UNSUPPORTED the device path cotained non-path elements + @retval other an error ocurred. +**/ +EFI_STATUS +InternalOpenFileDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes OPTIONAL + ) +{ + EFI_STATUS Status; + FILEPATH_DEVICE_PATH *FilePathNode; + EFI_HANDLE Handle; + SHELL_FILE_HANDLE ShellHandle; + EFI_FILE_PROTOCOL *Handle1; + EFI_FILE_PROTOCOL *Handle2; + FILEPATH_DEVICE_PATH *AlignedNode; + + if (FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + *FileHandle = NULL; + Handle1 = NULL; + Handle2 = NULL; + Handle = NULL; + ShellHandle = NULL; + FilePathNode = NULL; + AlignedNode = NULL; + + Status = EfiShellOpenRoot(DevicePath, &ShellHandle); + + if (!EFI_ERROR(Status)) { + Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle); + if (Handle1 != NULL) { + // + // chop off the begining part before the file system part... + // + ///@todo BlockIo? + Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, + &DevicePath, + &Handle); + if (!EFI_ERROR(Status)) { + // + // To access as a file system, the file path should only + // contain file path components. Follow the file path nodes + // and find the target file + // + for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath + ; !IsDevicePathEnd (&FilePathNode->Header) + ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header) + ){ + SHELL_FREE_NON_NULL(AlignedNode); + AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode); + // + // For file system access each node should be a file path component + // + if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH || + DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP + ) { + Status = EFI_UNSUPPORTED; + break; + } + + // + // Open this file path node + // + Handle2 = Handle1; + Handle1 = NULL; + + // + // if this is the last node in the DevicePath always create (if that was requested). + // + if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) { + Status = Handle2->Open ( + Handle2, + &Handle1, + AlignedNode->PathName, + OpenMode, + Attributes + ); + } else { + + // + // This is not the last node and we dont want to 'create' existing + // directory entries... + // + + // + // open without letting it create + // prevents error on existing files/directories + // + Status = Handle2->Open ( + Handle2, + &Handle1, + AlignedNode->PathName, + OpenMode &~EFI_FILE_MODE_CREATE, + Attributes + ); + // + // if above failed now open and create the 'item' + // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above) + // + if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) { + Status = Handle2->Open ( + Handle2, + &Handle1, + AlignedNode->PathName, + OpenMode, + Attributes + ); + } + } + // + // Close the last node + // + ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2); + + // + // If there's been an error, stop + // + if (EFI_ERROR (Status)) { + break; + } + } // for loop + } + } + } + SHELL_FREE_NON_NULL(AlignedNode); + if (EFI_ERROR(Status)) { + if (Handle1 != NULL) { + ShellInfoObject.NewEfiShellProtocol->CloseFile(Handle1); + } + } else { + *FileHandle = ConvertEfiFileProtocolToShellHandle(Handle1, ShellFileHandleGetPath(ShellHandle)); + } + return (Status); +} + +/** + Creates a file or directory by name. + + This function creates an empty new file or directory with the specified attributes and + returns the new file's handle. If the file already exists and is read-only, then + EFI_INVALID_PARAMETER will be returned. + + If the file already existed, it is truncated and its attributes updated. If the file is + created successfully, the FileHandle is the file's handle, else, the FileHandle is NULL. + + If the file name begins with >v, then the file handle which is returned refers to the + shell environment variable with the specified name. If the shell environment variable + already exists and is non-volatile then EFI_INVALID_PARAMETER is returned. + + @param FileName Pointer to NULL-terminated file path + @param FileAttribs The new file's attrbiutes. the different attributes are + described in EFI_FILE_PROTOCOL.Open(). + @param FileHandle On return, points to the created file handle or directory's handle + + @retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED could not open the file path + @retval EFI_NOT_FOUND the specified file could not be found on the devide, or could not + file the file system on the device. + @retval EFI_NO_MEDIA the device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according + the DirName. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +EfiShellCreateFile( + IN CONST CHAR16 *FileName, + IN UINT64 FileAttribs, + OUT SHELL_FILE_HANDLE *FileHandle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + BOOLEAN Volatile; + + // + // Is this for an environment variable + // do we start with >v + // + if (StrStr(FileName, L">v") == FileName) { + Status = IsVolatileEnv (FileName + 2, &Volatile); + if (EFI_ERROR (Status)) { + return Status; + } + if (!Volatile) { + return (EFI_INVALID_PARAMETER); + } + *FileHandle = CreateFileInterfaceEnv(FileName+2); + return (EFI_SUCCESS); + } + + // + // We are opening a regular file. + // + DevicePath = EfiShellGetDevicePathFromFilePath(FileName); + if (DevicePath == NULL) { + return (EFI_NOT_FOUND); + } + + Status = InternalOpenFileDevicePath(DevicePath, FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, FileAttribs); + FreePool(DevicePath); + + return(Status); +} + +/** + Register a GUID and a localized human readable name for it. + + If Guid is not assigned a name, then assign GuidName to Guid. This list of GUID + names must be used whenever a shell command outputs GUID information. + + This function is only available when the major and minor versions in the + EfiShellProtocol are greater than or equal to 2 and 1, respectively. + + @param[in] Guid A pointer to the GUID being registered. + @param[in] GuidName A pointer to the localized name for the GUID being registered. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Guid was NULL. + @retval EFI_INVALID_PARAMETER GuidName was NULL. + @retval EFI_ACCESS_DENIED Guid already is assigned a name. +**/ +EFI_STATUS +EFIAPI +EfiShellRegisterGuidName( + IN CONST EFI_GUID *Guid, + IN CONST CHAR16 *GuidName + ) +{ + return (AddNewGuidNameMapping(Guid, GuidName, NULL)); +} + +/** + Opens a file or a directory by file name. + + This function opens the specified file in the specified OpenMode and returns a file + handle. + If the file name begins with >v, then the file handle which is returned refers to the + shell environment variable with the specified name. If the shell environment variable + exists, is non-volatile and the OpenMode indicates EFI_FILE_MODE_WRITE, then + EFI_INVALID_PARAMETER is returned. + + If the file name is >i, then the file handle which is returned refers to the standard + input. If the OpenMode indicates EFI_FILE_MODE_WRITE, then EFI_INVALID_PARAMETER + is returned. + + If the file name is >o, then the file handle which is returned refers to the standard + output. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER + is returned. + + If the file name is >e, then the file handle which is returned refers to the standard + error. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER + is returned. + + If the file name is NUL, then the file handle that is returned refers to the standard NUL + file. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER is + returned. + + If return EFI_SUCCESS, the FileHandle is the opened file's handle, else, the + FileHandle is NULL. + + @param FileName Points to the NULL-terminated UCS-2 encoded file name. + @param FileHandle On return, points to the file handle. + @param OpenMode File open mode. Either EFI_FILE_MODE_READ or + EFI_FILE_MODE_WRITE from section 12.4 of the UEFI + Specification. + @retval EFI_SUCCESS The file was opened. FileHandle has the opened file's handle. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. FileHandle is NULL. + @retval EFI_UNSUPPORTED Could not open the file path. FileHandle is NULL. + @retval EFI_NOT_FOUND The specified file could not be found on the device or the file + system could not be found on the device. FileHandle is NULL. + @retval EFI_NO_MEDIA The device has no medium. FileHandle is NULL. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. FileHandle is NULL. + @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according + the FileName. FileHandle is NULL. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. FileHandle is NULL. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. FileHandle is NULL. + @retval EFI_ACCESS_DENIED The service denied access to the file. FileHandle is NULL. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. FileHandle + is NULL. + @retval EFI_VOLUME_FULL The volume is full. FileHandle is NULL. +**/ +EFI_STATUS +EFIAPI +EfiShellOpenFileByName( + IN CONST CHAR16 *FileName, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + BOOLEAN Volatile; + + *FileHandle = NULL; + + // + // Is this for StdIn + // + if (StrCmp(FileName, L">i") == 0) { + // + // make sure not writing to StdIn + // + if ((OpenMode & EFI_FILE_MODE_WRITE) != 0) { + return (EFI_INVALID_PARAMETER); + } + *FileHandle = ShellInfoObject.NewShellParametersProtocol->StdIn; + ASSERT(*FileHandle != NULL); + return (EFI_SUCCESS); + } + + // + // Is this for StdOut + // + if (StrCmp(FileName, L">o") == 0) { + // + // make sure not writing to StdIn + // + if ((OpenMode & EFI_FILE_MODE_READ) != 0) { + return (EFI_INVALID_PARAMETER); + } + *FileHandle = &FileInterfaceStdOut; + return (EFI_SUCCESS); + } + + // + // Is this for NUL / NULL file + // + if ((gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NUL") == 0) || + (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NULL") == 0)) { + *FileHandle = &FileInterfaceNulFile; + return (EFI_SUCCESS); + } + + // + // Is this for StdErr + // + if (StrCmp(FileName, L">e") == 0) { + // + // make sure not writing to StdIn + // + if ((OpenMode & EFI_FILE_MODE_READ) != 0) { + return (EFI_INVALID_PARAMETER); + } + *FileHandle = &FileInterfaceStdErr; + return (EFI_SUCCESS); + } + + // + // Is this for an environment variable + // do we start with >v + // + if (StrStr(FileName, L">v") == FileName) { + Status = IsVolatileEnv (FileName + 2, &Volatile); + if (EFI_ERROR (Status)) { + return Status; + } + if (!Volatile && + ((OpenMode & EFI_FILE_MODE_WRITE) != 0)) { + return (EFI_INVALID_PARAMETER); + } + *FileHandle = CreateFileInterfaceEnv(FileName+2); + return (EFI_SUCCESS); + } + + // + // We are opening a regular file. + // + DevicePath = EfiShellGetDevicePathFromFilePath(FileName); + + if (DevicePath == NULL) { + return (EFI_NOT_FOUND); + } + + // + // Copy the device path, open the file, then free the memory + // + Status = InternalOpenFileDevicePath(DevicePath, FileHandle, OpenMode, 0); // 0 = no specific file attributes + FreePool(DevicePath); + + return(Status); +} + +/** + Deletes the file specified by the file name. + + This function deletes a file. + + @param FileName Points to the NULL-terminated file name. + + @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. + @sa EfiShellCreateFile +**/ +EFI_STATUS +EFIAPI +EfiShellDeleteFileByName( + IN CONST CHAR16 *FileName + ) +{ + SHELL_FILE_HANDLE FileHandle; + EFI_STATUS Status; + + FileHandle = NULL; + + // + // get a handle to the file + // + Status = EfiShellCreateFile(FileName, + 0, + &FileHandle); + if (EFI_ERROR(Status)) { + return (Status); + } + // + // now delete the file + // + ShellFileHandleRemove(FileHandle); + return (ShellInfoObject.NewEfiShellProtocol->DeleteFile(FileHandle)); +} + +/** + Disables the page break output mode. +**/ +VOID +EFIAPI +EfiShellDisablePageBreak ( + VOID + ) +{ + ShellInfoObject.PageBreakEnabled = FALSE; +} + +/** + Enables the page break output mode. +**/ +VOID +EFIAPI +EfiShellEnablePageBreak ( + VOID + ) +{ + ShellInfoObject.PageBreakEnabled = TRUE; +} + +/** + internal worker function to load and run an image via device path. + + @param ParentImageHandle A handle of the image that is executing the specified + command line. + @param DevicePath device path of the file to execute + @param CommandLine Points to the NULL-terminated UCS-2 encoded string + containing the command line. If NULL then the command- + line will be empty. + @param Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. If this + is NULL, then the current shell environment is used. + + @param[out] StartImageStatus Returned status from gBS->StartImage. + + @retval EFI_SUCCESS The command executed successfully. The status code + returned by the command is pointed to by StatusCode. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Nested shell invocations are not allowed. +**/ +EFI_STATUS +InternalShellExecuteDevicePath( + IN CONST EFI_HANDLE *ParentImageHandle, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST CHAR16 *CommandLine OPTIONAL, + IN CONST CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StartImageStatus OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_STATUS StartStatus; + EFI_STATUS CleanupStatus; + EFI_HANDLE NewHandle; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + LIST_ENTRY OrigEnvs; + EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol; + CHAR16 *ImagePath; + UINTN Index; + CHAR16 *Walker; + CHAR16 *NewCmdLine; + + if (ParentImageHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + InitializeListHead(&OrigEnvs); + ZeroMem(&ShellParamsProtocol, sizeof(EFI_SHELL_PARAMETERS_PROTOCOL)); + + NewHandle = NULL; + + NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine); + if (NewCmdLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { + if (*Walker == L'^' && *(Walker+1) == L'#') { + CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + // + // Load the image with: + // FALSE - not from boot manager and NULL, 0 being not already in memory + // + Status = gBS->LoadImage( + FALSE, + *ParentImageHandle, + (EFI_DEVICE_PATH_PROTOCOL*)DevicePath, + NULL, + 0, + &NewHandle); + + if (EFI_ERROR(Status)) { + if (NewHandle != NULL) { + gBS->UnloadImage(NewHandle); + } + FreePool (NewCmdLine); + return (Status); + } + Status = gBS->OpenProtocol( + NewHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!EFI_ERROR(Status)) { + // + // If the image is not an app abort it. + // + if (LoadedImage->ImageCodeType != EfiLoaderCode){ + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SHELL_IMAGE_NOT_APP), + ShellInfoObject.HiiHandle + ); + goto UnloadImage; + } + + ASSERT(LoadedImage->LoadOptionsSize == 0); + if (NewCmdLine != NULL) { + LoadedImage->LoadOptionsSize = (UINT32)StrSize(NewCmdLine); + LoadedImage->LoadOptions = (VOID*)NewCmdLine; + } + + // + // Save our current environment settings for later restoration if necessary + // + if (Environment != NULL) { + Status = GetEnvironmentVariableList(&OrigEnvs); + if (!EFI_ERROR(Status)) { + Status = SetEnvironmentVariables(Environment); + } + } + + // + // Initialize and install a shell parameters protocol on the image. + // + ShellParamsProtocol.StdIn = ShellInfoObject.NewShellParametersProtocol->StdIn; + ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut; + ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr; + Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL); + ASSERT_EFI_ERROR(Status); + // + // Replace Argv[0] with the full path of the binary we're executing: + // If the command line was "foo", the binary might be called "foo.efi". + // "The first entry in [Argv] is always the full file path of the + // executable" - UEFI Shell Spec section 2.3 + // + ImagePath = EfiShellGetFilePathFromDevicePath (DevicePath); + // The image we're executing isn't necessarily in a filesystem - it might + // be memory mapped. In this case EfiShellGetFilePathFromDevicePath will + // return NULL, and we'll leave Argv[0] as UpdateArgcArgv set it. + if (ImagePath != NULL) { + if (ShellParamsProtocol.Argv == NULL) { + // Command line was empty or null. + // (UpdateArgcArgv sets Argv to NULL when CommandLine is "" or NULL) + ShellParamsProtocol.Argv = AllocatePool (sizeof (CHAR16 *)); + if (ShellParamsProtocol.Argv == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto UnloadImage; + } + ShellParamsProtocol.Argc = 1; + } else { + // Free the string UpdateArgcArgv put in Argv[0]; + FreePool (ShellParamsProtocol.Argv[0]); + } + ShellParamsProtocol.Argv[0] = ImagePath; + } + + Status = gBS->InstallProtocolInterface(&NewHandle, &gEfiShellParametersProtocolGuid, EFI_NATIVE_INTERFACE, &ShellParamsProtocol); + ASSERT_EFI_ERROR(Status); + + ///@todo initialize and install ShellInterface protocol on the new image for compatibility if - PcdGetBool(PcdShellSupportOldProtocols) + + // + // now start the image and if the caller wanted the return code pass it to them... + // + if (!EFI_ERROR(Status)) { + StartStatus = gBS->StartImage( + NewHandle, + 0, + NULL + ); + if (StartImageStatus != NULL) { + *StartImageStatus = StartStatus; + } + + CleanupStatus = gBS->UninstallProtocolInterface( + NewHandle, + &gEfiShellParametersProtocolGuid, + &ShellParamsProtocol + ); + ASSERT_EFI_ERROR(CleanupStatus); + + goto FreeAlloc; + } + +UnloadImage: + // Unload image - We should only get here if we didn't call StartImage + gBS->UnloadImage (NewHandle); + +FreeAlloc: + // Free Argv (Allocated in UpdateArgcArgv) + if (ShellParamsProtocol.Argv != NULL) { + for (Index = 0; Index < ShellParamsProtocol.Argc; Index++) { + if (ShellParamsProtocol.Argv[Index] != NULL) { + FreePool (ShellParamsProtocol.Argv[Index]); + } + } + FreePool (ShellParamsProtocol.Argv); + } + } + + // Restore environment variables + if (!IsListEmpty(&OrigEnvs)) { + CleanupStatus = SetEnvironmentVariableList(&OrigEnvs); + ASSERT_EFI_ERROR (CleanupStatus); + } + + FreePool (NewCmdLine); + + return(Status); +} + +/** + internal worker function to load and run an image in the current shell. + + @param CommandLine Points to the NULL-terminated UCS-2 encoded string + containing the command line. If NULL then the command- + line will be empty. + @param Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. If this + is NULL, then the current shell environment is used. + + @param[out] StartImageStatus Returned status from the command line. + + @retval EFI_SUCCESS The command executed successfully. The status code + returned by the command is pointed to by StatusCode. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Nested shell invocations are not allowed. +**/ +EFI_STATUS +InternalShellExecute( + IN CONST CHAR16 *CommandLine OPTIONAL, + IN CONST CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StartImageStatus OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_STATUS CleanupStatus; + LIST_ENTRY OrigEnvs; + + InitializeListHead(&OrigEnvs); + + // + // Save our current environment settings for later restoration if necessary + // + if (Environment != NULL) { + Status = GetEnvironmentVariableList(&OrigEnvs); + if (!EFI_ERROR(Status)) { + Status = SetEnvironmentVariables(Environment); + } else { + return Status; + } + } + + Status = RunShellCommand(CommandLine, StartImageStatus); + + // Restore environment variables + if (!IsListEmpty(&OrigEnvs)) { + CleanupStatus = SetEnvironmentVariableList(&OrigEnvs); + ASSERT_EFI_ERROR (CleanupStatus); + } + + return(Status); +} + +/** + Determine if the UEFI Shell is currently running with nesting enabled or disabled. + + @retval FALSE nesting is required + @retval other nesting is enabled +**/ +STATIC +BOOLEAN +NestingEnabled( + VOID +) +{ + EFI_STATUS Status; + CHAR16 *Temp; + CHAR16 *Temp2; + UINTN TempSize; + BOOLEAN RetVal; + + RetVal = TRUE; + Temp = NULL; + Temp2 = NULL; + + if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) { + TempSize = 0; + Temp = NULL; + Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp); + if (Status == EFI_BUFFER_TOO_SMALL) { + Temp = AllocateZeroPool(TempSize + sizeof(CHAR16)); + if (Temp != NULL) { + Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp); + } + } + Temp2 = StrnCatGrow(&Temp2, NULL, mNoNestingTrue, 0); + if (Temp != NULL && Temp2 != NULL && StringNoCaseCompare(&Temp, &Temp2) == 0) { + // + // Use the no nesting method. + // + RetVal = FALSE; + } + } + + SHELL_FREE_NON_NULL(Temp); + SHELL_FREE_NON_NULL(Temp2); + return (RetVal); +} + +/** + Execute the command line. + + This function creates a nested instance of the shell and executes the specified + command (CommandLine) with the specified environment (Environment). Upon return, + the status code returned by the specified command is placed in StatusCode. + + If Environment is NULL, then the current environment is used and all changes made + by the commands executed will be reflected in the current environment. If the + Environment is non-NULL, then the changes made will be discarded. + + The CommandLine is executed from the current working directory on the current + device. + + @param ParentImageHandle A handle of the image that is executing the specified + command line. + @param CommandLine Points to the NULL-terminated UCS-2 encoded string + containing the command line. If NULL then the command- + line will be empty. + @param Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. If this + is NULL, then the current shell environment is used. + @param StatusCode Points to the status code returned by the CommandLine. + + @retval EFI_SUCCESS The command executed successfully. The status code + returned by the command is pointed to by StatusCode. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Nested shell invocations are not allowed. + @retval EFI_UNSUPPORTED The support level required for this function is not present. + + @sa InternalShellExecuteDevicePath +**/ +EFI_STATUS +EFIAPI +EfiShellExecute( + IN EFI_HANDLE *ParentImageHandle, + IN CHAR16 *CommandLine OPTIONAL, + IN CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StatusCode OPTIONAL + ) +{ + EFI_STATUS Status; + CHAR16 *Temp; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + UINTN Size; + + if ((PcdGet8(PcdShellSupportLevel) < 1)) { + return (EFI_UNSUPPORTED); + } + + if (NestingEnabled()) { + DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath); + + DEBUG_CODE_BEGIN(); + Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE); + FreePool(Temp); + Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE); + FreePool(Temp); + Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE); + FreePool(Temp); + DEBUG_CODE_END(); + + Temp = NULL; + Size = 0; + ASSERT((Temp == NULL && Size == 0) || (Temp != NULL)); + StrnCatGrow(&Temp, &Size, L"Shell.efi -exit ", 0); + StrnCatGrow(&Temp, &Size, CommandLine, 0); + + Status = InternalShellExecuteDevicePath( + ParentImageHandle, + DevPath, + Temp, + (CONST CHAR16**)Environment, + StatusCode); + + // + // de-allocate and return + // + FreePool(DevPath); + FreePool(Temp); + } else { + Status = InternalShellExecute( + (CONST CHAR16*)CommandLine, + (CONST CHAR16**)Environment, + StatusCode); + } + + return(Status); +} + +/** + Utility cleanup function for EFI_SHELL_FILE_INFO objects. + + 1) frees all pointers (non-NULL) + 2) Closes the SHELL_FILE_HANDLE + + @param FileListNode pointer to the list node to free +**/ +VOID +InternalFreeShellFileInfoNode( + IN EFI_SHELL_FILE_INFO *FileListNode + ) +{ + if (FileListNode->Info != NULL) { + FreePool((VOID*)FileListNode->Info); + } + if (FileListNode->FileName != NULL) { + FreePool((VOID*)FileListNode->FileName); + } + if (FileListNode->FullName != NULL) { + FreePool((VOID*)FileListNode->FullName); + } + if (FileListNode->Handle != NULL) { + ShellInfoObject.NewEfiShellProtocol->CloseFile(FileListNode->Handle); + } + FreePool(FileListNode); +} +/** + Frees the file list. + + This function cleans up the file list and any related data structures. It has no + impact on the files themselves. + + @param FileList The file list to free. Type EFI_SHELL_FILE_INFO is + defined in OpenFileList() + + @retval EFI_SUCCESS Free the file list successfully. + @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL; +**/ +EFI_STATUS +EFIAPI +EfiShellFreeFileList( + IN EFI_SHELL_FILE_INFO **FileList + ) +{ + EFI_SHELL_FILE_INFO *ShellFileListItem; + + if (FileList == NULL || *FileList == NULL) { + return (EFI_INVALID_PARAMETER); + } + + for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link) + ; !IsListEmpty(&(*FileList)->Link) + ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link) + ){ + RemoveEntryList(&ShellFileListItem->Link); + InternalFreeShellFileInfoNode(ShellFileListItem); + } + InternalFreeShellFileInfoNode(*FileList); + *FileList = NULL; + return(EFI_SUCCESS); +} + +/** + Deletes the duplicate file names files in the given file list. + + This function deletes the reduplicate files in the given file list. + + @param FileList A pointer to the first entry in the file list. + + @retval EFI_SUCCESS Always success. + @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL; +**/ +EFI_STATUS +EFIAPI +EfiShellRemoveDupInFileList( + IN EFI_SHELL_FILE_INFO **FileList + ) +{ + EFI_SHELL_FILE_INFO *ShellFileListItem; + EFI_SHELL_FILE_INFO *ShellFileListItem2; + EFI_SHELL_FILE_INFO *TempNode; + + if (FileList == NULL || *FileList == NULL) { + return (EFI_INVALID_PARAMETER); + } + for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link) + ; !IsNull(&(*FileList)->Link, &ShellFileListItem->Link) + ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link) + ){ + for ( ShellFileListItem2 = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link) + ; !IsNull(&(*FileList)->Link, &ShellFileListItem2->Link) + ; ShellFileListItem2 = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem2->Link) + ){ + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)ShellFileListItem->FullName, + (CHAR16*)ShellFileListItem2->FullName) == 0 + ){ + TempNode = (EFI_SHELL_FILE_INFO *)GetPreviousNode( + &(*FileList)->Link, + &ShellFileListItem2->Link + ); + RemoveEntryList(&ShellFileListItem2->Link); + InternalFreeShellFileInfoNode(ShellFileListItem2); + // Set ShellFileListItem2 to PreviousNode so we don't access Freed + // memory in GetNextNode in the loop expression above. + ShellFileListItem2 = TempNode; + } + } + } + return (EFI_SUCCESS); +} + +// +// This is the same structure as the external version, but it has no CONST qualifiers. +// +typedef struct { + LIST_ENTRY Link; ///< Linked list members. + EFI_STATUS Status; ///< Status of opening the file. Valid only if Handle != NULL. + CHAR16 *FullName; ///< Fully qualified filename. + CHAR16 *FileName; ///< name of this file. + SHELL_FILE_HANDLE Handle; ///< Handle for interacting with the opened file or NULL if closed. + EFI_FILE_INFO *Info; ///< Pointer to the FileInfo struct for this file or NULL. +} EFI_SHELL_FILE_INFO_NO_CONST; + +/** + Allocates and duplicates a EFI_SHELL_FILE_INFO node. + + @param[in] Node The node to copy from. + @param[in] Save TRUE to set Node->Handle to NULL, FALSE otherwise. + + @retval NULL a memory allocation error ocurred + @return != NULL a pointer to the new node +**/ +EFI_SHELL_FILE_INFO* +InternalDuplicateShellFileInfo( + IN EFI_SHELL_FILE_INFO *Node, + IN BOOLEAN Save + ) +{ + EFI_SHELL_FILE_INFO_NO_CONST *NewNode; + + // + // try to confirm that the objects are in sync + // + ASSERT(sizeof(EFI_SHELL_FILE_INFO_NO_CONST) == sizeof(EFI_SHELL_FILE_INFO)); + + NewNode = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + if (NewNode == NULL) { + return (NULL); + } + NewNode->FullName = AllocateCopyPool(StrSize(Node->FullName), Node->FullName); + NewNode->FileName = AllocateCopyPool(StrSize(Node->FileName), Node->FileName); + NewNode->Info = AllocateCopyPool((UINTN)Node->Info->Size, Node->Info); + if ( NewNode->FullName == NULL + || NewNode->FileName == NULL + || NewNode->Info == NULL + ){ + SHELL_FREE_NON_NULL(NewNode->FullName); + SHELL_FREE_NON_NULL(NewNode->FileName); + SHELL_FREE_NON_NULL(NewNode->Info); + SHELL_FREE_NON_NULL(NewNode); + return(NULL); + } + NewNode->Status = Node->Status; + NewNode->Handle = Node->Handle; + if (!Save) { + Node->Handle = NULL; + } + + return((EFI_SHELL_FILE_INFO*)NewNode); +} + +/** + Allocates and populates a EFI_SHELL_FILE_INFO structure. if any memory operation + failed it will return NULL. + + @param[in] BasePath the Path to prepend onto filename for FullPath + @param[in] Status Status member initial value. + @param[in] FileName FileName member initial value. + @param[in] Handle Handle member initial value. + @param[in] Info Info struct to copy. + + @retval NULL An error ocurred. + @return a pointer to the newly allocated structure. +**/ +EFI_SHELL_FILE_INFO * +CreateAndPopulateShellFileInfo( + IN CONST CHAR16 *BasePath, + IN CONST EFI_STATUS Status, + IN CONST CHAR16 *FileName, + IN CONST SHELL_FILE_HANDLE Handle, + IN CONST EFI_FILE_INFO *Info + ) +{ + EFI_SHELL_FILE_INFO *ShellFileListItem; + CHAR16 *TempString; + UINTN Size; + + TempString = NULL; + Size = 0; + + ShellFileListItem = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + if (ShellFileListItem == NULL) { + return (NULL); + } + if (Info != NULL && Info->Size != 0) { + ShellFileListItem->Info = AllocateZeroPool((UINTN)Info->Size); + if (ShellFileListItem->Info == NULL) { + FreePool(ShellFileListItem); + return (NULL); + } + CopyMem(ShellFileListItem->Info, Info, (UINTN)Info->Size); + } else { + ShellFileListItem->Info = NULL; + } + if (FileName != NULL) { + ASSERT(TempString == NULL); + ShellFileListItem->FileName = StrnCatGrow(&TempString, 0, FileName, 0); + if (ShellFileListItem->FileName == NULL) { + FreePool(ShellFileListItem->Info); + FreePool(ShellFileListItem); + return (NULL); + } + } else { + ShellFileListItem->FileName = NULL; + } + Size = 0; + TempString = NULL; + if (BasePath != NULL) { + ASSERT((TempString == NULL && Size == 0) || (TempString != NULL)); + TempString = StrnCatGrow(&TempString, &Size, BasePath, 0); + if (TempString == NULL) { + FreePool((VOID*)ShellFileListItem->FileName); + SHELL_FREE_NON_NULL(ShellFileListItem->Info); + FreePool(ShellFileListItem); + return (NULL); + } + } + if (ShellFileListItem->FileName != NULL) { + ASSERT((TempString == NULL && Size == 0) || (TempString != NULL)); + TempString = StrnCatGrow(&TempString, &Size, ShellFileListItem->FileName, 0); + if (TempString == NULL) { + FreePool((VOID*)ShellFileListItem->FileName); + FreePool(ShellFileListItem->Info); + FreePool(ShellFileListItem); + return (NULL); + } + } + + TempString = PathCleanUpDirectories(TempString); + + ShellFileListItem->FullName = TempString; + ShellFileListItem->Status = Status; + ShellFileListItem->Handle = Handle; + + return (ShellFileListItem); +} + +/** + Find all files in a specified directory. + + @param FileDirHandle Handle of the directory to search. + @param FileList On return, points to the list of files in the directory + or NULL if there are no files in the directory. + + @retval EFI_SUCCESS File information was returned successfully. + @retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_NO_MEDIA The device media is not present. + @retval EFI_INVALID_PARAMETER The FileDirHandle was not a directory. + @return An error from FileHandleGetFileName(). +**/ +EFI_STATUS +EFIAPI +EfiShellFindFilesInDir( + IN SHELL_FILE_HANDLE FileDirHandle, + OUT EFI_SHELL_FILE_INFO **FileList + ) +{ + EFI_SHELL_FILE_INFO *ShellFileList; + EFI_SHELL_FILE_INFO *ShellFileListItem; + EFI_FILE_INFO *FileInfo; + EFI_STATUS Status; + BOOLEAN NoFile; + CHAR16 *TempString; + CHAR16 *BasePath; + UINTN Size; + CHAR16 *TempSpot; + + BasePath = NULL; + Status = FileHandleGetFileName(FileDirHandle, &BasePath); + if (EFI_ERROR(Status)) { + return (Status); + } + + if (ShellFileHandleGetPath(FileDirHandle) != NULL) { + TempString = NULL; + Size = 0; + TempString = StrnCatGrow(&TempString, &Size, ShellFileHandleGetPath(FileDirHandle), 0); + if (TempString == NULL) { + SHELL_FREE_NON_NULL(BasePath); + return (EFI_OUT_OF_RESOURCES); + } + TempSpot = StrStr(TempString, L";"); + + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + + TempString = StrnCatGrow(&TempString, &Size, BasePath, 0); + if (TempString == NULL) { + SHELL_FREE_NON_NULL(BasePath); + return (EFI_OUT_OF_RESOURCES); + } + SHELL_FREE_NON_NULL(BasePath); + BasePath = TempString; + } + + NoFile = FALSE; + ShellFileList = NULL; + ShellFileListItem = NULL; + FileInfo = NULL; + Status = EFI_SUCCESS; + + + for ( Status = FileHandleFindFirstFile(FileDirHandle, &FileInfo) + ; !EFI_ERROR(Status) && !NoFile + ; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile) + ){ + if (ShellFileList == NULL) { + ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + if (ShellFileList == NULL) { + SHELL_FREE_NON_NULL (BasePath); + return EFI_OUT_OF_RESOURCES; + } + InitializeListHead(&ShellFileList->Link); + } + // + // allocate a new EFI_SHELL_FILE_INFO and populate it... + // + ShellFileListItem = CreateAndPopulateShellFileInfo( + BasePath, + EFI_SUCCESS, // success since we didnt fail to open it... + FileInfo->FileName, + NULL, // no handle since not open + FileInfo); + if (ShellFileListItem == NULL) { + Status = EFI_OUT_OF_RESOURCES; + // + // Free resources outside the loop. + // + break; + } + InsertTailList(&ShellFileList->Link, &ShellFileListItem->Link); + } + if (EFI_ERROR(Status)) { + EfiShellFreeFileList(&ShellFileList); + *FileList = NULL; + } else { + *FileList = ShellFileList; + } + SHELL_FREE_NON_NULL(BasePath); + return(Status); +} + +/** + Get the GUID value from a human readable name. + + If GuidName is a known GUID name, then update Guid to have the correct value for + that GUID. + + This function is only available when the major and minor versions in the + EfiShellProtocol are greater than or equal to 2 and 1, respectively. + + @param[in] GuidName A pointer to the localized name for the GUID being queried. + @param[out] Guid A pointer to the GUID structure to be filled in. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Guid was NULL. + @retval EFI_INVALID_PARAMETER GuidName was NULL. + @retval EFI_NOT_FOUND GuidName is not a known GUID Name. +**/ +EFI_STATUS +EFIAPI +EfiShellGetGuidFromName( + IN CONST CHAR16 *GuidName, + OUT EFI_GUID *Guid + ) +{ + EFI_GUID *NewGuid; + EFI_STATUS Status; + + if (Guid == NULL || GuidName == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Status = GetGuidFromStringName(GuidName, NULL, &NewGuid); + + if (!EFI_ERROR(Status)) { + CopyGuid(Guid, NewGuid); + } + + return (Status); +} + +/** + Get the human readable name for a GUID from the value. + + If Guid is assigned a name, then update *GuidName to point to the name. The callee + should not modify the value. + + This function is only available when the major and minor versions in the + EfiShellProtocol are greater than or equal to 2 and 1, respectively. + + @param[in] Guid A pointer to the GUID being queried. + @param[out] GuidName A pointer to a pointer the localized to name for the GUID being requested + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER Guid was NULL. + @retval EFI_INVALID_PARAMETER GuidName was NULL. + @retval EFI_NOT_FOUND Guid is not assigned a name. +**/ +EFI_STATUS +EFIAPI +EfiShellGetGuidName( + IN CONST EFI_GUID *Guid, + OUT CONST CHAR16 **GuidName + ) +{ + CHAR16 *Name; + + if (Guid == NULL || GuidName == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Name = GetStringNameFromGuid(Guid, NULL); + if (Name == NULL || StrLen(Name) == 0) { + SHELL_FREE_NON_NULL(Name); + return (EFI_NOT_FOUND); + } + + *GuidName = AddBufferToFreeList(Name); + + return (EFI_SUCCESS); +} + + + +/** + If FileHandle is a directory then the function reads from FileHandle and reads in + each of the FileInfo structures. If one of them matches the Pattern's first + "level" then it opens that handle and calls itself on that handle. + + If FileHandle is a file and matches all of the remaining Pattern (which would be + on its last node), then add a EFI_SHELL_FILE_INFO object for this file to fileList. + + Upon a EFI_SUCCESS return fromt he function any the caller is responsible to call + FreeFileList with FileList. + + @param[in] FilePattern The FilePattern to check against. + @param[in] UnicodeCollation The pointer to EFI_UNICODE_COLLATION_PROTOCOL structure + @param[in] FileHandle The FileHandle to start with + @param[in, out] FileList pointer to pointer to list of found files. + @param[in] ParentNode The node for the parent. Same file as identified by HANDLE. + @param[in] MapName The file system name this file is on. + + @retval EFI_SUCCESS all files were found and the FileList contains a list. + @retval EFI_NOT_FOUND no files were found + @retval EFI_OUT_OF_RESOURCES a memory allocation failed +**/ +EFI_STATUS +ShellSearchHandle( + IN CONST CHAR16 *FilePattern, + IN EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation, + IN SHELL_FILE_HANDLE FileHandle, + IN OUT EFI_SHELL_FILE_INFO **FileList, + IN CONST EFI_SHELL_FILE_INFO *ParentNode OPTIONAL, + IN CONST CHAR16 *MapName + ) +{ + EFI_STATUS Status; + CONST CHAR16 *NextFilePatternStart; + CHAR16 *CurrentFilePattern; + EFI_SHELL_FILE_INFO *ShellInfo; + EFI_SHELL_FILE_INFO *ShellInfoNode; + EFI_SHELL_FILE_INFO *NewShellNode; + EFI_FILE_INFO *FileInfo; + BOOLEAN Directory; + CHAR16 *NewFullName; + UINTN Size; + + if ( FilePattern == NULL + || UnicodeCollation == NULL + || FileList == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + ShellInfo = NULL; + CurrentFilePattern = NULL; + + if (*FilePattern == L'\\') { + FilePattern++; + } + + for( NextFilePatternStart = FilePattern + ; *NextFilePatternStart != CHAR_NULL && *NextFilePatternStart != L'\\' + ; NextFilePatternStart++); + + CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16)); + if (CurrentFilePattern == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StrnCpyS(CurrentFilePattern, NextFilePatternStart-FilePattern+1, FilePattern, NextFilePatternStart-FilePattern); + + if (CurrentFilePattern[0] == CHAR_NULL + &&NextFilePatternStart[0] == CHAR_NULL + ){ + // + // we want the parent or root node (if no parent) + // + if (ParentNode == NULL) { + // + // We want the root node. create the node. + // + FileInfo = FileHandleGetInfo(FileHandle); + NewShellNode = CreateAndPopulateShellFileInfo( + MapName, + EFI_SUCCESS, + L"\\", + FileHandle, + FileInfo + ); + SHELL_FREE_NON_NULL(FileInfo); + } else { + // + // Add the current parameter FileHandle to the list, then end... + // + NewShellNode = InternalDuplicateShellFileInfo((EFI_SHELL_FILE_INFO*)ParentNode, TRUE); + } + if (NewShellNode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + NewShellNode->Handle = NULL; + if (*FileList == NULL) { + *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + InitializeListHead(&((*FileList)->Link)); + } + + // + // Add to the returning to use list + // + InsertTailList(&(*FileList)->Link, &NewShellNode->Link); + + Status = EFI_SUCCESS; + } + } else { + Status = EfiShellFindFilesInDir(FileHandle, &ShellInfo); + + if (!EFI_ERROR(Status)){ + if (StrStr(NextFilePatternStart, L"\\") != NULL){ + Directory = TRUE; + } else { + Directory = FALSE; + } + for ( ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ShellInfo->Link) + ; !IsNull (&ShellInfo->Link, &ShellInfoNode->Link) + ; ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ShellInfo->Link, &ShellInfoNode->Link) + ){ + if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){ + if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) { + Size = StrSize (ShellInfoNode->FullName) + StrSize (MapName); + NewFullName = AllocateZeroPool(Size); + if (NewFullName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + StrCpyS(NewFullName, Size / sizeof(CHAR16), MapName); + StrCatS(NewFullName, Size / sizeof(CHAR16), ShellInfoNode->FullName); + FreePool ((VOID *) ShellInfoNode->FullName); + ShellInfoNode->FullName = NewFullName; + } + } + if (Directory && !EFI_ERROR(Status) && ShellInfoNode->FullName != NULL && ShellInfoNode->FileName != NULL){ + // + // should be a directory + // + + // + // don't open the . and .. directories + // + if ( (StrCmp(ShellInfoNode->FileName, L".") != 0) + && (StrCmp(ShellInfoNode->FileName, L"..") != 0) + ){ + // + // + // + if (EFI_ERROR(Status)) { + break; + } + // + // Open the directory since we need that handle in the next recursion. + // + ShellInfoNode->Status = EfiShellOpenFileByName (ShellInfoNode->FullName, &ShellInfoNode->Handle, EFI_FILE_MODE_READ); + + // + // recurse with the next part of the pattern + // + Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName); + EfiShellClose(ShellInfoNode->Handle); + ShellInfoNode->Handle = NULL; + } + } else if (!EFI_ERROR(Status)) { + // + // should be a file + // + + // + // copy the information we need into a new Node + // + NewShellNode = InternalDuplicateShellFileInfo(ShellInfoNode, FALSE); + if (NewShellNode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } + if (*FileList == NULL) { + *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + InitializeListHead(&((*FileList)->Link)); + } + + // + // Add to the returning to use list + // + InsertTailList(&(*FileList)->Link, &NewShellNode->Link); + } + } + if (EFI_ERROR(Status)) { + break; + } + } + if (EFI_ERROR(Status)) { + EfiShellFreeFileList(&ShellInfo); + } else { + Status = EfiShellFreeFileList(&ShellInfo); + } + } + } + + if (*FileList == NULL || (*FileList != NULL && IsListEmpty(&(*FileList)->Link))) { + Status = EFI_NOT_FOUND; + } + + FreePool(CurrentFilePattern); + return (Status); +} + +/** + Find files that match a specified pattern. + + This function searches for all files and directories that match the specified + FilePattern. The FilePattern can contain wild-card characters. The resulting file + information is placed in the file list FileList. + + Wildcards are processed + according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. + + The files in the file list are not opened. The OpenMode field is set to 0 and the FileInfo + field is set to NULL. + + if *FileList is not NULL then it must be a pre-existing and properly initialized list. + + @param FilePattern Points to a NULL-terminated shell file path, including wildcards. + @param FileList On return, points to the start of a file list containing the names + of all matching files or else points to NULL if no matching files + were found. only on a EFI_SUCCESS return will; this be non-NULL. + + @retval EFI_SUCCESS Files found. FileList is a valid list. + @retval EFI_NOT_FOUND No files found. + @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 +EfiShellFindFiles( + IN CONST CHAR16 *FilePattern, + OUT EFI_SHELL_FILE_INFO **FileList + ) +{ + EFI_STATUS Status; + CHAR16 *PatternCopy; + CHAR16 *PatternCurrentLocation; + EFI_DEVICE_PATH_PROTOCOL *RootDevicePath; + SHELL_FILE_HANDLE RootFileHandle; + CHAR16 *MapName; + UINTN Count; + + if ( FilePattern == NULL + || FileList == NULL + || StrStr(FilePattern, L":") == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + Status = EFI_SUCCESS; + RootDevicePath = NULL; + RootFileHandle = NULL; + MapName = NULL; + PatternCopy = AllocateCopyPool(StrSize(FilePattern), FilePattern); + if (PatternCopy == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + PatternCopy = PathCleanUpDirectories(PatternCopy); + + Count = StrStr(PatternCopy, L":") - PatternCopy + 1; + ASSERT (Count <= StrLen (PatternCopy)); + + ASSERT(MapName == NULL); + MapName = StrnCatGrow(&MapName, NULL, PatternCopy, Count); + if (MapName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + RootDevicePath = EfiShellGetDevicePathFromFilePath(PatternCopy); + if (RootDevicePath == NULL) { + Status = EFI_INVALID_PARAMETER; + } else { + Status = EfiShellOpenRoot(RootDevicePath, &RootFileHandle); + if (!EFI_ERROR(Status)) { + for ( PatternCurrentLocation = PatternCopy + ; *PatternCurrentLocation != ':' + ; PatternCurrentLocation++); + PatternCurrentLocation++; + Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName); + EfiShellClose(RootFileHandle); + } + FreePool(RootDevicePath); + } + } + + SHELL_FREE_NON_NULL(PatternCopy); + SHELL_FREE_NON_NULL(MapName); + + return(Status); +} + +/** + Opens the files that match the path specified. + + This function opens all of the files specified by Path. Wildcards are processed + according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. Each + matching file has an EFI_SHELL_FILE_INFO structure created in a linked list. + + @param Path A pointer to the path string. + @param OpenMode Specifies the mode used to open each file, EFI_FILE_MODE_READ or + EFI_FILE_MODE_WRITE. + @param FileList Points to the start of a list of files opened. + + @retval EFI_SUCCESS Create the file list successfully. + @return Others Can't create the file list. +**/ +EFI_STATUS +EFIAPI +EfiShellOpenFileList( + IN CHAR16 *Path, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **FileList + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *ShellFileListItem; + CHAR16 *Path2; + UINTN Path2Size; + CONST CHAR16 *CurDir; + BOOLEAN Found; + + PathCleanUpDirectories(Path); + + Path2Size = 0; + Path2 = NULL; + + if (FileList == NULL || *FileList == NULL) { + return (EFI_INVALID_PARAMETER); + } + + if (*Path == L'.' && *(Path+1) == L'\\') { + Path+=2; + } + + // + // convert a local path to an absolute path + // + if (StrStr(Path, L":") == NULL) { + CurDir = EfiShellGetCurDir(NULL); + ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL)); + StrnCatGrow(&Path2, &Path2Size, CurDir, 0); + StrnCatGrow(&Path2, &Path2Size, L"\\", 0); + if (*Path == L'\\') { + Path++; + while (PathRemoveLastItem(Path2)) ; + } + ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL)); + StrnCatGrow(&Path2, &Path2Size, Path, 0); + } else { + ASSERT(Path2 == NULL); + StrnCatGrow(&Path2, NULL, Path, 0); + } + + PathCleanUpDirectories (Path2); + + // + // do the search + // + Status = EfiShellFindFiles(Path2, FileList); + + FreePool(Path2); + + if (EFI_ERROR(Status)) { + return (Status); + } + + Found = FALSE; + // + // We had no errors so open all the files (that are not already opened...) + // + for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link) + ; !IsNull(&(*FileList)->Link, &ShellFileListItem->Link) + ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link) + ){ + if (ShellFileListItem->Status == 0 && ShellFileListItem->Handle == NULL) { + ShellFileListItem->Status = EfiShellOpenFileByName (ShellFileListItem->FullName, &ShellFileListItem->Handle, OpenMode); + Found = TRUE; + } + } + + if (!Found) { + return (EFI_NOT_FOUND); + } + return(EFI_SUCCESS); +} + +/** + Gets the environment variable and Attributes, or list of environment variables. Can be + used instead of GetEnv(). + + This function returns the current value of the specified environment variable and + the Attributes. If no variable name was specified, then all of the known + variables will be returned. + + @param[in] Name A pointer to the environment variable name. If Name is NULL, + then the function will return all of the defined shell + environment variables. In the case where multiple environment + variables are being returned, each variable will be terminated + by a NULL, and the list will be terminated by a double NULL. + @param[out] Attributes If not NULL, a pointer to the returned attributes bitmask for + the environment variable. In the case where Name is NULL, and + multiple environment variables are being returned, Attributes + is undefined. + + @retval NULL The environment variable doesn't exist. + @return A non-NULL value points to the variable's value. The returned + pointer does not need to be freed by the caller. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetEnvEx( + IN CONST CHAR16 *Name, + OUT UINT32 *Attributes OPTIONAL + ) +{ + EFI_STATUS Status; + VOID *Buffer; + UINTN Size; + ENV_VAR_LIST *Node; + CHAR16 *CurrentWriteLocation; + + Size = 0; + Buffer = NULL; + + if (Name == NULL) { + + // + // Build the semi-colon delimited list. (2 passes) + // + for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link) + ; !IsNull(&gShellEnvVarList.Link, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link) + ){ + ASSERT(Node->Key != NULL); + Size += StrSize(Node->Key); + } + + Size += 2*sizeof(CHAR16); + + Buffer = AllocateZeroPool(Size); + if (Buffer == NULL) { + return (NULL); + } + CurrentWriteLocation = (CHAR16*)Buffer; + + for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link) + ; !IsNull(&gShellEnvVarList.Link, &Node->Link) + ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link) + ){ + ASSERT(Node->Key != NULL); + StrCpyS( CurrentWriteLocation, + (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)), + Node->Key + ); + CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1; + } + + } else { + // + // We are doing a specific environment variable + // + Status = ShellFindEnvVarInList(Name, (CHAR16**)&Buffer, &Size, Attributes); + + if (EFI_ERROR(Status)){ + // + // get the size we need for this EnvVariable + // + Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the space and recall the get function + // + Buffer = AllocateZeroPool(Size); + Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer); + } + // + // we didnt get it (might not exist) + // free the memory if we allocated any and return NULL + // + if (EFI_ERROR(Status)) { + if (Buffer != NULL) { + FreePool(Buffer); + } + return (NULL); + } else { + // + // If we did not find the environment variable in the gShellEnvVarList + // but get it from UEFI variable storage successfully then we need update + // the gShellEnvVarList. + // + ShellFreeEnvVarList (); + Status = ShellInitEnvVarList (); + ASSERT (Status == EFI_SUCCESS); + } + } + } + + // + // return the buffer + // + return (AddBufferToFreeList(Buffer)); +} + +/** + Gets either a single or list of environment variables. + + If name is not NULL then this function returns the current value of the specified + environment variable. + + If Name is NULL, then a list of all environment variable names is returned. Each is a + NULL terminated string with a double NULL terminating the list. + + @param Name A pointer to the environment variable name. If + Name is NULL, then the function will return all + of the defined shell environment variables. In + the case where multiple environment variables are + being returned, each variable will be terminated by + a NULL, and the list will be terminated by a double + NULL. + + @retval !=NULL A pointer to the returned string. + The returned pointer does not need to be freed by the caller. + + @retval NULL The environment variable doesn't exist or there are + no environment variables. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetEnv( + IN CONST CHAR16 *Name + ) +{ + return (EfiShellGetEnvEx(Name, NULL)); +} + +/** + Internal variable setting function. Allows for setting of the read only variables. + + @param Name Points to the NULL-terminated environment variable name. + @param Value Points to the NULL-terminated environment variable value. If the value is an + empty string then the environment variable is deleted. + @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS The environment variable was successfully updated. +**/ +EFI_STATUS +InternalEfiShellSetEnv( + IN CONST CHAR16 *Name, + IN CONST CHAR16 *Value, + IN BOOLEAN Volatile + ) +{ + EFI_STATUS Status; + + if (Value == NULL || StrLen(Value) == 0) { + Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Name); + if (!EFI_ERROR(Status)) { + ShellRemvoeEnvVarFromList(Name); + } + } else { + SHELL_DELETE_ENVIRONMENT_VARIABLE(Name); + Status = ShellAddEnvVarToList( + Name, Value, StrSize(Value), + EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE) + ); + if (!EFI_ERROR (Status)) { + Status = Volatile + ? SHELL_SET_ENVIRONMENT_VARIABLE_V (Name, StrSize (Value) - sizeof (CHAR16), Value) + : SHELL_SET_ENVIRONMENT_VARIABLE_NV (Name, StrSize (Value) - sizeof (CHAR16), Value); + if (EFI_ERROR (Status)) { + ShellRemvoeEnvVarFromList(Name); + } + } + } + return Status; +} + +/** + Sets the environment variable. + + This function changes the current value of the specified environment variable. If the + environment variable exists and the Value is an empty string, then the environment + variable is deleted. If the environment variable exists and the Value is not an empty + string, then the value of the environment variable is changed. If the environment + variable does not exist and the Value is an empty string, there is no action. If the + environment variable does not exist and the Value is a non-empty string, then the + environment variable is created and assigned the specified value. + + For a description of volatile and non-volatile environment variables, see UEFI Shell + 2.0 specification section 3.6.1. + + @param Name Points to the NULL-terminated environment variable name. + @param Value Points to the NULL-terminated environment variable value. If the value is an + empty string then the environment variable is deleted. + @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS The environment variable was successfully updated. +**/ +EFI_STATUS +EFIAPI +EfiShellSetEnv( + IN CONST CHAR16 *Name, + IN CONST CHAR16 *Value, + IN BOOLEAN Volatile + ) +{ + if (Name == NULL || *Name == CHAR_NULL) { + return (EFI_INVALID_PARAMETER); + } + // + // Make sure we dont 'set' a predefined read only variable + // + if ((StrCmp (Name, L"cwd") == 0) || + (StrCmp (Name, L"lasterror") == 0) || + (StrCmp (Name, L"profiles") == 0) || + (StrCmp (Name, L"uefishellsupport") == 0) || + (StrCmp (Name, L"uefishellversion") == 0) || + (StrCmp (Name, L"uefiversion") == 0) || + (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest && + StrCmp (Name, mNoNestingEnvVarName) == 0) + ) { + return (EFI_INVALID_PARAMETER); + } + return (InternalEfiShellSetEnv(Name, Value, Volatile)); +} + +/** + Returns the current directory on the specified device. + + If FileSystemMapping is NULL, it returns the current working directory. If the + FileSystemMapping is not NULL, it returns the current directory associated with the + FileSystemMapping. In both cases, the returned name includes the file system + mapping (i.e. fs0:\current-dir). + + Note that the current directory string should exclude the tailing backslash character. + + @param FileSystemMapping A pointer to the file system mapping. If NULL, + then the current working directory is returned. + + @retval !=NULL The current directory. + @retval NULL Current directory does not exist. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetCurDir( + IN CONST CHAR16 *FileSystemMapping OPTIONAL + ) +{ + CHAR16 *PathToReturn; + UINTN Size; + SHELL_MAP_LIST *MapListItem; + if (!IsListEmpty(&gShellMapList.Link)) { + // + // if parameter is NULL, use current + // + if (FileSystemMapping == NULL) { + return (EfiShellGetEnv(L"cwd")); + } else { + Size = 0; + PathToReturn = NULL; + MapListItem = ShellCommandFindMapItem(FileSystemMapping); + if (MapListItem != NULL) { + ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL)); + PathToReturn = StrnCatGrow(&PathToReturn, &Size, MapListItem->MapName, 0); + PathToReturn = StrnCatGrow(&PathToReturn, &Size, MapListItem->CurrentDirectoryPath, 0); + } + } + return (AddBufferToFreeList(PathToReturn)); + } else { + return (NULL); + } +} + +/** + Changes the current directory on the specified device. + + If the FileSystem is NULL, and the directory Dir does not contain a file system's + mapped name, this function changes the current working directory. + + If the FileSystem is NULL and the directory Dir contains a mapped name, then the + current file system and the current directory on that file system are changed. + + If FileSystem is NULL, and Dir is not NULL, then this changes the current working file + system. + + If FileSystem is not NULL and Dir is not NULL, then this function changes the current + directory on the specified file system. + + If the current working directory or the current working file system is changed then the + %cwd% environment variable will be updated + + Note that the current directory string should exclude the tailing backslash character. + + @param FileSystem A pointer to the file system's mapped name. If NULL, then the current working + directory is changed. + @param Dir Points to the NULL-terminated directory on the device specified by FileSystem. + + @retval EFI_SUCCESS The operation was sucessful + @retval EFI_NOT_FOUND The file system could not be found +**/ +EFI_STATUS +EFIAPI +EfiShellSetCurDir( + IN CONST CHAR16 *FileSystem OPTIONAL, + IN CONST CHAR16 *Dir + ) +{ + CHAR16 *MapName; + SHELL_MAP_LIST *MapListItem; + UINTN Size; + EFI_STATUS Status; + CHAR16 *TempString; + CHAR16 *DirectoryName; + UINTN TempLen; + + Size = 0; + MapName = NULL; + MapListItem = NULL; + TempString = NULL; + DirectoryName = NULL; + + if ((FileSystem == NULL && Dir == NULL) || Dir == NULL) { + return (EFI_INVALID_PARAMETER); + } + + if (IsListEmpty(&gShellMapList.Link)){ + return (EFI_NOT_FOUND); + } + + DirectoryName = StrnCatGrow(&DirectoryName, NULL, Dir, 0); + ASSERT(DirectoryName != NULL); + + PathCleanUpDirectories(DirectoryName); + + if (FileSystem == NULL) { + // + // determine the file system mapping to use + // + if (StrStr(DirectoryName, L":") != NULL) { + ASSERT(MapName == NULL); + MapName = StrnCatGrow(&MapName, NULL, DirectoryName, (StrStr(DirectoryName, L":")-DirectoryName+1)); + } + // + // find the file system mapping's entry in the list + // or use current + // + if (MapName != NULL) { + MapListItem = ShellCommandFindMapItem(MapName); + + // + // make that the current file system mapping + // + if (MapListItem != NULL) { + gShellCurMapping = MapListItem; + } + } else { + MapListItem = gShellCurMapping; + } + + if (MapListItem == NULL) { + FreePool (DirectoryName); + SHELL_FREE_NON_NULL(MapName); + return (EFI_NOT_FOUND); + } + + // + // now update the MapListItem's current directory + // + if (MapListItem->CurrentDirectoryPath != NULL && DirectoryName[StrLen(DirectoryName) - 1] != L':') { + FreePool(MapListItem->CurrentDirectoryPath); + MapListItem->CurrentDirectoryPath = NULL; + } + if (MapName != NULL) { + TempLen = StrLen(MapName); + if (TempLen != StrLen(DirectoryName)) { + ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); + MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName+StrLen(MapName), 0); + } + FreePool (MapName); + } else { + ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); + MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0); + } + if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) { + ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); + if (MapListItem->CurrentDirectoryPath != NULL) { + MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL; + } + } + } else { + // + // cant have a mapping in the directory... + // + if (StrStr(DirectoryName, L":") != NULL) { + FreePool (DirectoryName); + return (EFI_INVALID_PARAMETER); + } + // + // FileSystem != NULL + // + MapListItem = ShellCommandFindMapItem(FileSystem); + if (MapListItem == NULL) { + FreePool (DirectoryName); + return (EFI_INVALID_PARAMETER); + } +// gShellCurMapping = MapListItem; + if (DirectoryName != NULL) { + // + // change current dir on that file system + // + + if (MapListItem->CurrentDirectoryPath != NULL) { + FreePool(MapListItem->CurrentDirectoryPath); + DEBUG_CODE(MapListItem->CurrentDirectoryPath = NULL;); + } +// ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); +// MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, FileSystem, 0); + ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); + MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0); + ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); + MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0); + if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') { + ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL)); + MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL; + } + } + } + FreePool (DirectoryName); + // + // if updated the current directory then update the environment variable + // + if (MapListItem == gShellCurMapping) { + Size = 0; + ASSERT((TempString == NULL && Size == 0) || (TempString != NULL)); + StrnCatGrow(&TempString, &Size, MapListItem->MapName, 0); + ASSERT((TempString == NULL && Size == 0) || (TempString != NULL)); + StrnCatGrow(&TempString, &Size, MapListItem->CurrentDirectoryPath, 0); + Status = InternalEfiShellSetEnv(L"cwd", TempString, TRUE); + FreePool(TempString); + return (Status); + } + return(EFI_SUCCESS); +} + +/** + Return help information about a specific command. + + This function returns the help information for the specified command. The help text + can be internal to the shell or can be from a UEFI Shell manual page. + + If Sections is specified, then each section name listed will be compared in a casesensitive + manner, to the section names described in Appendix B. If the section exists, + it will be appended to the returned help text. If the section does not exist, no + information will be returned. If Sections is NULL, then all help text information + available will be returned. + + @param Command Points to the NULL-terminated UEFI Shell command name. + @param Sections Points to the NULL-terminated comma-delimited + section names to return. If NULL, then all + sections will be returned. + @param HelpText On return, points to a callee-allocated buffer + containing all specified help text. + + @retval EFI_SUCCESS The help text was returned. + @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the + returned help text. + @retval EFI_INVALID_PARAMETER HelpText is NULL + @retval EFI_NOT_FOUND There is no help text available for Command. +**/ +EFI_STATUS +EFIAPI +EfiShellGetHelpText( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Sections OPTIONAL, + OUT CHAR16 **HelpText + ) +{ + CONST CHAR16 *ManFileName; + CHAR16 *FixCommand; + EFI_STATUS Status; + + ASSERT(HelpText != NULL); + FixCommand = NULL; + + ManFileName = ShellCommandGetManFileNameHandler(Command); + + if (ManFileName != NULL) { + return (ProcessManFile(ManFileName, Command, Sections, NULL, HelpText)); + } else { + if ((StrLen(Command)> 4) + && (Command[StrLen(Command)-1] == L'i' || Command[StrLen(Command)-1] == L'I') + && (Command[StrLen(Command)-2] == L'f' || Command[StrLen(Command)-2] == L'F') + && (Command[StrLen(Command)-3] == L'e' || Command[StrLen(Command)-3] == L'E') + && (Command[StrLen(Command)-4] == L'.') + ) { + FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16)); + if (FixCommand == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StrnCpyS( FixCommand, + (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16), + Command, + StrLen(Command)-4 + ); + Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText); + FreePool(FixCommand); + return Status; + } else { + return (ProcessManFile(Command, Command, Sections, NULL, HelpText)); + } + } +} + +/** + Gets the enable status of the page break output mode. + + User can use this function to determine current page break mode. + + @retval TRUE The page break output mode is enabled. + @retval FALSE The page break output mode is disabled. +**/ +BOOLEAN +EFIAPI +EfiShellGetPageBreak( + VOID + ) +{ + return(ShellInfoObject.PageBreakEnabled); +} + +/** + Judges whether the active shell is the root shell. + + This function makes the user to know that whether the active Shell is the root shell. + + @retval TRUE The active Shell is the root Shell. + @retval FALSE The active Shell is NOT the root Shell. +**/ +BOOLEAN +EFIAPI +EfiShellIsRootShell( + VOID + ) +{ + return(ShellInfoObject.RootShellInstance); +} + +/** + function to return a semi-colon delimeted list of all alias' in the current shell + + up to caller to free the memory. + + @retval NULL No alias' were found + @retval NULL An error ocurred getting alias' + @return !NULL a list of all alias' +**/ +CHAR16 * +InternalEfiShellGetListAlias( + VOID + ) +{ + + EFI_STATUS Status; + EFI_GUID Guid; + CHAR16 *VariableName; + UINTN NameSize; + UINTN NameBufferSize; + CHAR16 *RetVal; + UINTN RetSize; + + NameBufferSize = INIT_NAME_BUFFER_SIZE; + VariableName = AllocateZeroPool(NameBufferSize); + RetSize = 0; + RetVal = NULL; + + if (VariableName == NULL) { + return (NULL); + } + + VariableName[0] = CHAR_NULL; + + while (TRUE) { + NameSize = NameBufferSize; + Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); + if (Status == EFI_NOT_FOUND){ + break; + } else if (Status == EFI_BUFFER_TOO_SMALL) { + NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2; + SHELL_FREE_NON_NULL(VariableName); + VariableName = AllocateZeroPool(NameBufferSize); + if (VariableName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + SHELL_FREE_NON_NULL(RetVal); + RetVal = NULL; + break; + } + + NameSize = NameBufferSize; + Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid); + } + + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL(RetVal); + RetVal = NULL; + break; + } + + if (CompareGuid(&Guid, &gShellAliasGuid)){ + ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL)); + RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0); + RetVal = StrnCatGrow(&RetVal, &RetSize, L";", 0); + } // compare guid + } // while + SHELL_FREE_NON_NULL(VariableName); + + return (RetVal); +} + +/** + Convert a null-terminated unicode string, in-place, to all lowercase. + Then return it. + + @param Str The null-terminated string to be converted to all lowercase. + + @return The null-terminated string converted into all lowercase. +**/ +CHAR16 * +ToLower ( + CHAR16 *Str + ) +{ + UINTN Index; + + for (Index = 0; Str[Index] != L'\0'; Index++) { + if (Str[Index] >= L'A' && Str[Index] <= L'Z') { + Str[Index] -= (CHAR16)(L'A' - L'a'); + } + } + return Str; +} + +/** + This function returns the command associated with a alias or a list of all + alias'. + + @param[in] Alias Points to the NULL-terminated shell alias. + If this parameter is NULL, then all + aliases will be returned in ReturnedData. + @param[out] Volatile upon return of a single command if TRUE indicates + this is stored in a volatile fashion. FALSE otherwise. + + @return If Alias is not NULL, it will return a pointer to + the NULL-terminated command for that alias. + If Alias is NULL, ReturnedData points to a ';' + delimited list of alias (e.g. + ReturnedData = "dir;del;copy;mfp") that is NULL-terminated. + @retval NULL an error ocurred + @retval NULL Alias was not a valid Alias +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetAlias( + IN CONST CHAR16 *Alias, + OUT BOOLEAN *Volatile OPTIONAL + ) +{ + CHAR16 *RetVal; + UINTN RetSize; + UINT32 Attribs; + EFI_STATUS Status; + CHAR16 *AliasLower; + CHAR16 *AliasVal; + + // Convert to lowercase to make aliases case-insensitive + if (Alias != NULL) { + AliasLower = AllocateCopyPool (StrSize (Alias), Alias); + if (AliasLower == NULL) { + return NULL; + } + ToLower (AliasLower); + + if (Volatile == NULL) { + GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL); + FreePool(AliasLower); + return (AddBufferToFreeList(AliasVal)); + } + RetSize = 0; + RetVal = NULL; + Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal); + if (Status == EFI_BUFFER_TOO_SMALL) { + RetVal = AllocateZeroPool(RetSize); + Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal); + } + if (EFI_ERROR(Status)) { + if (RetVal != NULL) { + FreePool(RetVal); + } + FreePool(AliasLower); + return (NULL); + } + if ((EFI_VARIABLE_NON_VOLATILE & Attribs) == EFI_VARIABLE_NON_VOLATILE) { + *Volatile = FALSE; + } else { + *Volatile = TRUE; + } + + FreePool (AliasLower); + return (AddBufferToFreeList(RetVal)); + } + return (AddBufferToFreeList(InternalEfiShellGetListAlias())); +} + +/** + Changes a shell command alias. + + This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias. + + this function does not check for built in alias'. + + @param[in] Command Points to the NULL-terminated shell command or existing alias. + @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and + Command refers to an alias, that alias will be deleted. + @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the + Alias being set will be stored in a non-volatile fashion. + + @retval EFI_SUCCESS Alias created or deleted successfully. + @retval EFI_NOT_FOUND the Alias intended to be deleted was not found +**/ +EFI_STATUS +InternalSetAlias( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias, + IN BOOLEAN Volatile + ) +{ + EFI_STATUS Status; + CHAR16 *AliasLower; + BOOLEAN DeleteAlias; + + DeleteAlias = FALSE; + if (Alias == NULL) { + // + // We must be trying to remove one if Alias is NULL + // remove an alias (but passed in COMMAND parameter) + // + Alias = Command; + DeleteAlias = TRUE; + } + ASSERT (Alias != NULL); + + // + // Convert to lowercase to make aliases case-insensitive + // + AliasLower = AllocateCopyPool (StrSize (Alias), Alias); + if (AliasLower == NULL) { + return EFI_OUT_OF_RESOURCES; + } + ToLower (AliasLower); + + if (DeleteAlias) { + Status = gRT->SetVariable (AliasLower, &gShellAliasGuid, 0, 0, NULL); + } else { + Status = gRT->SetVariable ( + AliasLower, &gShellAliasGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE), + StrSize (Command), (VOID *) Command + ); + } + + FreePool (AliasLower); + + return Status; +} + +/** + Changes a shell command alias. + + This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias. + + + @param[in] Command Points to the NULL-terminated shell command or existing alias. + @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and + Command refers to an alias, that alias will be deleted. + @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If + FALSE and the alias already exists, then the existing alias is unchanged and + EFI_ACCESS_DENIED is returned. + @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the + Alias being set will be stored in a non-volatile fashion. + + @retval EFI_SUCCESS Alias created or deleted successfully. + @retval EFI_NOT_FOUND the Alias intended to be deleted was not found + @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to + FALSE. + @retval EFI_INVALID_PARAMETER Command is null or the empty string. +**/ +EFI_STATUS +EFIAPI +EfiShellSetAlias( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias, + IN BOOLEAN Replace, + IN BOOLEAN Volatile + ) +{ + if (ShellCommandIsOnAliasList(Alias==NULL?Command:Alias)) { + // + // cant set over a built in alias + // + return (EFI_ACCESS_DENIED); + } else if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) { + // + // Command is null or empty + // + return (EFI_INVALID_PARAMETER); + } else if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) { + // + // Alias already exists, Replace not set + // + return (EFI_ACCESS_DENIED); + } else { + return (InternalSetAlias(Command, Alias, Volatile)); + } +} + +// Pure FILE_HANDLE operations are passed to FileHandleLib +// these functions are indicated by the * +EFI_SHELL_PROTOCOL mShellProtocol = { + EfiShellExecute, + EfiShellGetEnv, + EfiShellSetEnv, + EfiShellGetAlias, + EfiShellSetAlias, + EfiShellGetHelpText, + EfiShellGetDevicePathFromMap, + EfiShellGetMapFromDevicePath, + EfiShellGetDevicePathFromFilePath, + EfiShellGetFilePathFromDevicePath, + EfiShellSetMap, + EfiShellGetCurDir, + EfiShellSetCurDir, + EfiShellOpenFileList, + EfiShellFreeFileList, + EfiShellRemoveDupInFileList, + EfiShellBatchIsActive, + EfiShellIsRootShell, + EfiShellEnablePageBreak, + EfiShellDisablePageBreak, + EfiShellGetPageBreak, + EfiShellGetDeviceName, + (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo, //* + (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo, //* + EfiShellOpenFileByName, + EfiShellClose, + EfiShellCreateFile, + (EFI_SHELL_READ_FILE)FileHandleRead, //* + (EFI_SHELL_WRITE_FILE)FileHandleWrite, //* + (EFI_SHELL_DELETE_FILE)FileHandleDelete, //* + EfiShellDeleteFileByName, + (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition, //* + (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition, //* + (EFI_SHELL_FLUSH_FILE)FileHandleFlush, //* + EfiShellFindFiles, + EfiShellFindFilesInDir, + (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize, //* + EfiShellOpenRoot, + EfiShellOpenRootByHandle, + NULL, + SHELL_MAJOR_VERSION, + SHELL_MINOR_VERSION, + + // New for UEFI Shell 2.1 + EfiShellRegisterGuidName, + EfiShellGetGuidName, + EfiShellGetGuidFromName, + EfiShellGetEnvEx +}; + +/** + Function to create and install on the current handle. + + Will overwrite any existing ShellProtocols in the system to be sure that + the current shell is in control. + + This must be removed via calling CleanUpShellProtocol(). + + @param[in, out] NewShell The pointer to the pointer to the structure + to install. + + @retval EFI_SUCCESS The operation was successful. + @return An error from LocateHandle, CreateEvent, or other core function. +**/ +EFI_STATUS +CreatePopulateInstallShellProtocol ( + IN OUT EFI_SHELL_PROTOCOL **NewShell + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE *Buffer; + UINTN HandleCounter; + SHELL_PROTOCOL_HANDLE_LIST *OldProtocolNode; + EFI_SHELL_PROTOCOL *OldShell; + + if (NewShell == NULL) { + return (EFI_INVALID_PARAMETER); + } + + BufferSize = 0; + Buffer = NULL; + OldProtocolNode = NULL; + InitializeListHead(&ShellInfoObject.OldShellList.Link); + + // + // Initialize EfiShellProtocol object... + // + Status = gBS->CreateEvent(0, + 0, + NULL, + NULL, + &mShellProtocol.ExecutionBreak); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // Get the size of the buffer we need. + // + Status = gBS->LocateHandle(ByProtocol, + &gEfiShellProtocolGuid, + NULL, + &BufferSize, + Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate and recall with buffer of correct size + // + Buffer = AllocateZeroPool(BufferSize); + if (Buffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle(ByProtocol, + &gEfiShellProtocolGuid, + NULL, + &BufferSize, + Buffer); + if (EFI_ERROR(Status)) { + FreePool(Buffer); + return (Status); + } + // + // now overwrite each of them, but save the info to restore when we end. + // + for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++) { + Status = gBS->OpenProtocol(Buffer[HandleCounter], + &gEfiShellProtocolGuid, + (VOID **) &OldShell, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) { + OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST)); + if (OldProtocolNode == NULL) { + if (!IsListEmpty (&ShellInfoObject.OldShellList.Link)) { + CleanUpShellProtocol (&mShellProtocol); + } + Status = EFI_OUT_OF_RESOURCES; + break; + } + // + // reinstall over the old one... + // + OldProtocolNode->Handle = Buffer[HandleCounter]; + OldProtocolNode->Interface = OldShell; + Status = gBS->ReinstallProtocolInterface( + OldProtocolNode->Handle, + &gEfiShellProtocolGuid, + OldProtocolNode->Interface, + (VOID*)(&mShellProtocol)); + if (!EFI_ERROR(Status)) { + // + // we reinstalled sucessfully. log this so we can reverse it later. + // + + // + // add to the list for subsequent... + // + InsertTailList(&ShellInfoObject.OldShellList.Link, &OldProtocolNode->Link); + } + } + } + FreePool(Buffer); + } else if (Status == EFI_NOT_FOUND) { + ASSERT(IsListEmpty(&ShellInfoObject.OldShellList.Link)); + // + // no one else published yet. just publish it ourselves. + // + Status = gBS->InstallProtocolInterface ( + &gImageHandle, + &gEfiShellProtocolGuid, + EFI_NATIVE_INTERFACE, + (VOID*)(&mShellProtocol)); + } + + if (PcdGetBool(PcdShellSupportOldProtocols)){ + ///@todo support ShellEnvironment2 + ///@todo do we need to support ShellEnvironment (not ShellEnvironment2) also? + } + + if (!EFI_ERROR(Status)) { + *NewShell = &mShellProtocol; + } + return (Status); +} + +/** + Opposite of CreatePopulateInstallShellProtocol. + + Free all memory and restore the system to the state it was in before calling + CreatePopulateInstallShellProtocol. + + @param[in, out] NewShell The pointer to the new shell protocol structure. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +CleanUpShellProtocol ( + IN OUT EFI_SHELL_PROTOCOL *NewShell + ) +{ + SHELL_PROTOCOL_HANDLE_LIST *Node2; + + // + // if we need to restore old protocols... + // + if (!IsListEmpty(&ShellInfoObject.OldShellList.Link)) { + for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link) + ; !IsListEmpty (&ShellInfoObject.OldShellList.Link) + ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link) + ) { + RemoveEntryList (&Node2->Link); + gBS->ReinstallProtocolInterface (Node2->Handle, &gEfiShellProtocolGuid, NewShell, Node2->Interface); + FreePool (Node2); + } + } else { + // + // no need to restore + // + gBS->UninstallProtocolInterface (gImageHandle, &gEfiShellProtocolGuid, NewShell); + } + return EFI_SUCCESS; +} + +/** + Cleanup the shell environment. + + @param[in, out] NewShell The pointer to the new shell protocol structure. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +CleanUpShellEnvironment ( + IN OUT EFI_SHELL_PROTOCOL *NewShell + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx; + + CleanUpShellProtocol (NewShell); + + Status = gBS->CloseEvent(NewShell->ExecutionBreak); + NewShell->ExecutionBreak = NULL; + + Status = gBS->OpenProtocol( + gST->ConsoleInHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID**)&SimpleEx, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!EFI_ERROR (Status)) { + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle1); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle2); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle3); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle4); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle1); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle2); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle3); + Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle4); + } + return (Status); +} + +/** + Notification function for keystrokes. + + @param[in] KeyData The key that was pressed. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +NotificationFunction( + IN EFI_KEY_DATA *KeyData + ) +{ + if ( ((KeyData->Key.UnicodeChar == L'c') && + (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))) || + (KeyData->Key.UnicodeChar == 3) + ){ + if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) { + return (EFI_UNSUPPORTED); + } + return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak)); + } else if ((KeyData->Key.UnicodeChar == L's') && + (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED)) + ){ + ShellInfoObject.HaltOutput = TRUE; + } + return (EFI_SUCCESS); +} + +/** + Function to start monitoring for CTRL-C using SimpleTextInputEx. This + feature's enabled state was not known when the shell initially launched. + + @retval EFI_SUCCESS The feature is enabled. + @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available. +**/ +EFI_STATUS +InernalEfiShellStartMonitor( + VOID + ) +{ + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx; + EFI_KEY_DATA KeyData; + EFI_STATUS Status; + + Status = gBS->OpenProtocol( + gST->ConsoleInHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID**)&SimpleEx, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SHELL_NO_IN_EX), + ShellInfoObject.HiiHandle); + return (EFI_SUCCESS); + } + + if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) { + return (EFI_UNSUPPORTED); + } + + KeyData.KeyState.KeyToggleState = 0; + KeyData.Key.ScanCode = 0; + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED; + KeyData.Key.UnicodeChar = L'c'; + + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlCNotifyHandle1); + + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED; + if (!EFI_ERROR(Status)) { + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlCNotifyHandle2); + } + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED; + KeyData.Key.UnicodeChar = 3; + if (!EFI_ERROR(Status)) { + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlCNotifyHandle3); + } + KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED; + if (!EFI_ERROR(Status)) { + Status = SimpleEx->RegisterKeyNotify( + SimpleEx, + &KeyData, + NotificationFunction, + &ShellInfoObject.CtrlCNotifyHandle4); + } + return (Status); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.h new file mode 100644 index 0000000..745f0b4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/Shell/ShellProtocol.h @@ -0,0 +1,944 @@ +/** @file + Member functions of EFI_SHELL_PROTOCOL and functions for creation, + manipulation, and initialization of EFI_SHELL_PROTOCOL. + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_PROTOCOL_HEADER_ +#define _SHELL_PROTOCOL_HEADER_ + +#include "Shell.h" + +typedef struct { + LIST_ENTRY Link; + EFI_SHELL_PROTOCOL *Interface; + EFI_HANDLE Handle; +} SHELL_PROTOCOL_HANDLE_LIST; + +// flags values... +#define SHELL_MAP_FLAGS_CONSIST BIT1 + +/** + Function to create and install on the current handle. + + Will overwrite any existing ShellProtocols in the system to be sure that + the current shell is in control. + + This must be removed via calling CleanUpShellProtocol(). + + @param[in, out] NewShell The pointer to the pointer to the structure + to install. + + @retval EFI_SUCCESS The operation was successful. + @return An error from LocateHandle, CreateEvent, or other core function. +**/ +EFI_STATUS +CreatePopulateInstallShellProtocol ( + IN OUT EFI_SHELL_PROTOCOL **NewShell + ); + +/** + Opposite of CreatePopulateInstallShellProtocol. + + Free all memory and restore the system to the state it was in before calling + CreatePopulateInstallShellProtocol. + + @param[in, out] NewShell The pointer to the new shell protocol structure. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +CleanUpShellProtocol ( + IN OUT EFI_SHELL_PROTOCOL *NewShell + ); + +/** + Cleanup the shell environment. + + @param[in, out] NewShell The pointer to the new shell protocol structure. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +CleanUpShellEnvironment ( + IN OUT EFI_SHELL_PROTOCOL *NewShell + ); + +/** + This function creates a mapping for a device path. + + @param DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping, + then the mapping will be deleted. + @param Mapping Points to the NULL-terminated mapping for the device path. Must end with a ':' + + @retval EFI_SUCCESS Mapping created or deleted successfully. + @retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath. See the + boot service function LocateDevicePath(). + @retval EFI_ACCESS_DENIED The mapping is a built-in alias. + @retval EFI_INVALID_PARAMETER Mapping was NULL + @retval EFI_INVALID_PARAMETER Mapping did not end with a ':' + @retval EFI_INVALID_PARAMETER DevicePath was not pointing at a device that had a SIMPLE_FILE_SYSTEM_PROTOCOL installed. + @retval EFI_NOT_FOUND There was no mapping found to delete + @retval EFI_OUT_OF_RESOURCES Memory allocation failed +**/ +EFI_STATUS +EFIAPI +EfiShellSetMap( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, + IN CONST CHAR16 *Mapping + ); + +/** + Gets the device path from the mapping. + + This function gets the device path associated with a mapping. + + @param Mapping A pointer to the mapping + + @retval !=NULL Pointer to the device path that corresponds to the + device mapping. The returned pointer does not need + to be freed. + @retval NULL There is no device path associated with the + specified mapping. +**/ +CONST EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +EfiShellGetDevicePathFromMap( + IN CONST CHAR16 *Mapping + ); + +/** + Gets the mapping that most closely matches the device path. + + This function gets the mapping which corresponds to the device path *DevicePath. If + there is no exact match, then the mapping which most closely matches *DevicePath + is returned, and *DevicePath is updated to point to the remaining portion of the + device path. If there is an exact match, the mapping is returned and *DevicePath + points to the end-of-device-path node. + + @param DevicePath On entry, points to a device path pointer. On + exit, updates the pointer to point to the + portion of the device path after the mapping. + + @retval NULL No mapping was found. + @return !=NULL Pointer to NULL-terminated mapping. The buffer + is callee allocated and should be freed by the caller. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetMapFromDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +/** + Converts a device path to a file system-style path. + + This function converts a device path to a file system path by replacing part, or all, of + the device path with the file-system mapping. If there are more than one application + file system mappings, the one that most closely matches Path will be used. + + @param Path The pointer to the device path + + @retval NULL the device path could not be found. + @return all The pointer of the NULL-terminated file path. The path + is callee-allocated and should be freed by the caller. +**/ +CHAR16 * +EFIAPI +EfiShellGetFilePathFromDevicePath( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Path + ); + +/** + Converts a file system style name to a device path. + + This function converts a file system style name to a device path, by replacing any + mapping references to the associated device path. + + @param Path the pointer to the path + + @return all The pointer of the file path. The file path is callee + allocated and should be freed by the caller. +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +EfiShellGetDevicePathFromFilePath( + IN CONST CHAR16 *Path + ); + +/** + Gets the name of the device specified by the device handle. + + This function gets the user-readable name of the device specified by the device + handle. If no user-readable name could be generated, then *BestDeviceName will be + NULL and EFI_NOT_FOUND will be returned. + + If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the + device's name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on + DeviceHandle. + + If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the + device's name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle. + If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and + EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then + EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority. + + @param DeviceHandle The handle of the device. + @param Flags Determines the possible sources of component names. + Valid bits are: + EFI_DEVICE_NAME_USE_COMPONENT_NAME + EFI_DEVICE_NAME_USE_DEVICE_PATH + @param Language A pointer to the language specified for the device + name, in the same format as described in the UEFI + specification, Appendix M + @param BestDeviceName On return, points to the callee-allocated NULL- + terminated name of the device. If no device name + could be found, points to NULL. The name must be + freed by the caller... + + @retval EFI_SUCCESS Get the name successfully. + @retval EFI_NOT_FOUND Fail to get the device name. + @retval EFI_INVALID_PARAMETER Flags did not have a valid bit set. + @retval EFI_INVALID_PARAMETER BestDeviceName was NULL + @retval EFI_INVALID_PARAMETER DeviceHandle was NULL +**/ +EFI_STATUS +EFIAPI +EfiShellGetDeviceName( + IN EFI_HANDLE DeviceHandle, + IN EFI_SHELL_DEVICE_NAME_FLAGS Flags, + IN CHAR8 *Language, + OUT CHAR16 **BestDeviceName + ); + +/** + Opens the root directory of a device on a handle + + This function opens the root directory of a device and returns a file handle to it. + + @param DeviceHandle The handle of the device that contains the volume. + @param FileHandle On exit, points to the file handle corresponding to the root directory on the + device. + + @retval EFI_SUCCESS Root opened successfully. + @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory + could not be opened. + @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted. + @retval EFI_DEVICE_ERROR The device had an error +**/ +EFI_STATUS +EFIAPI +EfiShellOpenRootByHandle( + IN EFI_HANDLE DeviceHandle, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + Opens the root directory of a device. + + This function opens the root directory of a device and returns a file handle to it. + + @param DevicePath Points to the device path corresponding to the device where the + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed. + @param FileHandle On exit, points to the file handle corresponding to the root directory on the + device. + + @retval EFI_SUCCESS Root opened successfully. + @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory + could not be opened. + @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted. + @retval EFI_DEVICE_ERROR The device had an error +**/ +EFI_STATUS +EFIAPI +EfiShellOpenRoot( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + Returns whether any script files are currently being processed. + + @retval TRUE There is at least one script file active. + @retval FALSE No script files are active now. + +**/ +BOOLEAN +EFIAPI +EfiShellBatchIsActive ( + VOID + ); + +/** + Worker function to open a file based on a device path. this will open the root + of the volume and then traverse down to the file itself. + + @param DevicePath2 Device Path of the file + @param FileHandle Pointer to the file upon a successful return + @param OpenMode mode to open file in. + @param Attributes the File Attributes to use when creating a new file + + @retval EFI_SUCCESS the file is open and FileHandle is valid + @retval EFI_UNSUPPORTED the device path cotained non-path elements + @retval other an error ocurred. +**/ +EFI_STATUS +InternalOpenFileDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath2, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes OPTIONAL + ); + +/** + Creates a file or directory by name. + + This function creates an empty new file or directory with the specified attributes and + returns the new file's handle. If the file already exists and is read-only, then + EFI_INVALID_PARAMETER will be returned. + + If the file already existed, it is truncated and its attributes updated. If the file is + created successfully, the FileHandle is the file's handle, else, the FileHandle is NULL. + + If the file name begins with >v, then the file handle which is returned refers to the + shell environment variable with the specified name. If the shell environment variable + already exists and is non-volatile then EFI_INVALID_PARAMETER is returned. + + @param FileName Pointer to NULL-terminated file path + @param FileAttribs The new file's attrbiutes. the different attributes are + described in EFI_FILE_PROTOCOL.Open(). + @param FileHandle On return, points to the created file handle or directory's handle + + @retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED could not open the file path + @retval EFI_NOT_FOUND the specified file could not be found on the devide, or could not + file the file system on the device. + @retval EFI_NO_MEDIA the device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according + the DirName. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +EfiShellCreateFile( + IN CONST CHAR16 *FileName, + IN UINT64 FileAttribs, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + Opens a file or a directory by file name. + + This function opens the specified file in the specified OpenMode and returns a file + handle. + If the file name begins with >v, then the file handle which is returned refers to the + shell environment variable with the specified name. If the shell environment variable + exists, is non-volatile and the OpenMode indicates EFI_FILE_MODE_WRITE, then + EFI_INVALID_PARAMETER is returned. + + If the file name is >i, then the file handle which is returned refers to the standard + input. If the OpenMode indicates EFI_FILE_MODE_WRITE, then EFI_INVALID_PARAMETER + is returned. + + If the file name is >o, then the file handle which is returned refers to the standard + output. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER + is returned. + + If the file name is >e, then the file handle which is returned refers to the standard + error. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER + is returned. + + If the file name is NUL, then the file handle that is returned refers to the standard NUL + file. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER is + returned. + + If return EFI_SUCCESS, the FileHandle is the opened file's handle, else, the + FileHandle is NULL. + + @param FileName Points to the NULL-terminated UCS-2 encoded file name. + @param FileHandle On return, points to the file handle. + @param OpenMode File open mode. Either EFI_FILE_MODE_READ or + EFI_FILE_MODE_WRITE from section 12.4 of the UEFI + Specification. + @retval EFI_SUCCESS The file was opened. FileHandle has the opened file's handle. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. FileHandle is NULL. + @retval EFI_UNSUPPORTED Could not open the file path. FileHandle is NULL. + @retval EFI_NOT_FOUND The specified file could not be found on the device or the file + system could not be found on the device. FileHandle is NULL. + @retval EFI_NO_MEDIA The device has no medium. FileHandle is NULL. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. FileHandle is NULL. + @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according + the FileName. FileHandle is NULL. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. FileHandle is NULL. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. FileHandle is NULL. + @retval EFI_ACCESS_DENIED The service denied access to the file. FileHandle is NULL. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. FileHandle + is NULL. + @retval EFI_VOLUME_FULL The volume is full. FileHandle is NULL. +**/ +EFI_STATUS +EFIAPI +EfiShellOpenFileByName( + IN CONST CHAR16 *FileName, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode + ); + +/** + Deletes the file specified by the file name. + + This function deletes a file. + + @param FileName Points to the NULL-terminated file name. + + @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted. + @sa EfiShellCreateFile + @sa FileHandleDelete +**/ +EFI_STATUS +EFIAPI +EfiShellDeleteFileByName( + IN CONST CHAR16 *FileName + ); + +/** + Disables the page break output mode. +**/ +VOID +EFIAPI +EfiShellDisablePageBreak ( + VOID + ); + +/** + Enables the page break output mode. +**/ +VOID +EFIAPI +EfiShellEnablePageBreak ( + VOID + ); + +/** + internal worker function to run a command via Device Path + + @param ParentImageHandle A handle of the image that is executing the specified + command line. + @param DevicePath device path of the file to execute + @param CommandLine Points to the NULL-terminated UCS-2 encoded string + containing the command line. If NULL then the command- + line will be empty. + @param Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. If this + is NULL, then the current shell environment is used. + @param[out] StartImageStatus Returned status from gBS->StartImage. + + @retval EFI_SUCCESS The command executed successfully. The status code + returned by the command is pointed to by StatusCode. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Nested shell invocations are not allowed. +**/ +EFI_STATUS +InternalShellExecuteDevicePath( + IN CONST EFI_HANDLE *ParentImageHandle, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST CHAR16 *CommandLine OPTIONAL, + IN CONST CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StartImageStatus OPTIONAL + ); + +/** + Execute the command line. + + This function creates a nested instance of the shell and executes the specified + command (CommandLine) with the specified environment (Environment). Upon return, + the status code returned by the specified command is placed in StatusCode. + + If Environment is NULL, then the current environment is used and all changes made + by the commands executed will be reflected in the current environment. If the + Environment is non-NULL, then the changes made will be discarded. + + The CommandLine is executed from the current working directory on the current + device. + + @param ParentImageHandle A handle of the image that is executing the specified + command line. + @param CommandLine Points to the NULL-terminated UCS-2 encoded string + containing the command line. If NULL then the command- + line will be empty. + @param Environment Points to a NULL-terminated array of environment + variables with the format 'x=y', where x is the + environment variable name and y is the value. If this + is NULL, then the current shell environment is used. + @param StatusCode Points to the status code returned by the command. + + @retval EFI_SUCCESS The command executed successfully. The status code + returned by the command is pointed to by StatusCode. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED Nested shell invocations are not allowed. +**/ +EFI_STATUS +EFIAPI +EfiShellExecute( + IN EFI_HANDLE *ParentImageHandle, + IN CHAR16 *CommandLine OPTIONAL, + IN CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StatusCode OPTIONAL + ); + +/** + Utility cleanup function for EFI_SHELL_FILE_INFO objects. + + 1) frees all pointers (non-NULL) + 2) Closes the SHELL_FILE_HANDLE + + @param FileListNode pointer to the list node to free +**/ +VOID +FreeShellFileInfoNode( + IN EFI_SHELL_FILE_INFO *FileListNode + ); + +/** + Frees the file list. + + This function cleans up the file list and any related data structures. It has no + impact on the files themselves. + + @param FileList The file list to free. Type EFI_SHELL_FILE_INFO is + defined in OpenFileList() + + @retval EFI_SUCCESS Free the file list successfully. + @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL; +**/ +EFI_STATUS +EFIAPI +EfiShellFreeFileList( + IN EFI_SHELL_FILE_INFO **FileList + ); + +/** + Deletes the duplicate file names files in the given file list. + + This function deletes the reduplicate files in the given file list. + + @param FileList A pointer to the first entry in the file list. + + @retval EFI_SUCCESS Always success. + @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL; +**/ +EFI_STATUS +EFIAPI +EfiShellRemoveDupInFileList( + IN EFI_SHELL_FILE_INFO **FileList + ); + +/** + Allocates and populates a EFI_SHELL_FILE_INFO structure. if any memory operation + failed it will return NULL. + + @param[in] BasePath the Path to prepend onto filename for FullPath + @param[in] Status Status member initial value. + @param[in] FileName FileName member initial value. + @param[in] Handle Handle member initial value. + @param[in] Info Info struct to copy. + +**/ +EFI_SHELL_FILE_INFO * +CreateAndPopulateShellFileInfo( + IN CONST CHAR16 *BasePath, + IN CONST EFI_STATUS Status, + IN CONST CHAR16 *FileName, + IN CONST SHELL_FILE_HANDLE Handle, + IN CONST EFI_FILE_INFO *Info + ); + +/** + Find all files in a specified directory. + + @param FileDirHandle Handle of the directory to search. + @param FileList On return, points to the list of files in the directory + or NULL if there are no files in the directory. + + @retval EFI_SUCCESS File information was returned successfully. + @retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_NO_MEDIA The device media is not present. + @retval EFI_INVALID_PARAMETER The FileDirHandle was not a directory. +**/ +EFI_STATUS +EFIAPI +EfiShellFindFilesInDir( + IN SHELL_FILE_HANDLE FileDirHandle, + OUT EFI_SHELL_FILE_INFO **FileList + ); + +/** + Find files that match a specified pattern. + + This function searches for all files and directories that match the specified + FilePattern. The FilePattern can contain wild-card characters. The resulting file + information is placed in the file list FileList. + + Wildcards are processed + according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. + + The files in the file list are not opened. The OpenMode field is set to 0 and the FileInfo + field is set to NULL. + + if *FileList is not NULL then it must be a pre-existing and properly initialized list. + + @param FilePattern Points to a NULL-terminated shell file path, including wildcards. + @param FileList On return, points to the start of a file list containing the names + of all matching files or else points to NULL if no matching files + were found. only on a EFI_SUCCESS return will; this be non-NULL. + + @retval EFI_SUCCESS Files found. FileList is a valid list. + @retval EFI_NOT_FOUND No files found. + @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 +EfiShellFindFiles( + IN CONST CHAR16 *FilePattern, + OUT EFI_SHELL_FILE_INFO **FileList + ); + +/** + Opens the files that match the path specified. + + This function opens all of the files specified by Path. Wildcards are processed + according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. Each + matching file has an EFI_SHELL_FILE_INFO structure created in a linked list. + + @param Path A pointer to the path string. + @param OpenMode Specifies the mode used to open each file, EFI_FILE_MODE_READ or + EFI_FILE_MODE_WRITE. + @param FileList Points to the start of a list of files opened. + + @retval EFI_SUCCESS Create the file list successfully. + @return Others Can't create the file list. +**/ +EFI_STATUS +EFIAPI +EfiShellOpenFileList( + IN CHAR16 *Path, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **FileList + ); + +/** + Gets the environment variable. + + This function returns the current value of the specified environment variable. + + @param Name A pointer to the environment variable name + + @retval !=NULL The environment variable's value. The returned + pointer does not need to be freed by the caller. + @retval NULL The environment variable doesn't exist. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetEnv( + IN CONST CHAR16 *Name + ); + +/** + Sets the environment variable. + + This function changes the current value of the specified environment variable. If the + environment variable exists and the Value is an empty string, then the environment + variable is deleted. If the environment variable exists and the Value is not an empty + string, then the value of the environment variable is changed. If the environment + variable does not exist and the Value is an empty string, there is no action. If the + environment variable does not exist and the Value is a non-empty string, then the + environment variable is created and assigned the specified value. + + For a description of volatile and non-volatile environment variables, see UEFI Shell + 2.0 specification section 3.6.1. + + @param Name Points to the NULL-terminated environment variable name. + @param Value Points to the NULL-terminated environment variable value. If the value is an + empty string then the environment variable is deleted. + @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS The environment variable was successfully updated. +**/ +EFI_STATUS +EFIAPI +EfiShellSetEnv( + IN CONST CHAR16 *Name, + IN CONST CHAR16 *Value, + IN BOOLEAN Volatile + ); + +/** + Returns the current directory on the specified device. + + If FileSystemMapping is NULL, it returns the current working directory. If the + FileSystemMapping is not NULL, it returns the current directory associated with the + FileSystemMapping. In both cases, the returned name includes the file system + mapping (i.e. fs0:\current-dir). + + @param FileSystemMapping A pointer to the file system mapping. If NULL, + then the current working directory is returned. + + @retval !=NULL The current directory. + @retval NULL Current directory does not exist. +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetCurDir( + IN CONST CHAR16 *FileSystemMapping OPTIONAL + ); + +/** + Changes the current directory on the specified device. + + If the FileSystem is NULL, and the directory Dir does not contain a file system's + mapped name, this function changes the current working directory. If FileSystem is + NULL and the directory Dir contains a mapped name, then the current file system and + the current directory on that file system are changed. + + If FileSystem is not NULL, and Dir is NULL, then this changes the current working file + system. + + If FileSystem is not NULL and Dir is not NULL, then this function changes the current + directory on the specified file system. + + If the current working directory or the current working file system is changed then the + %cwd% environment variable will be updated + + @param FileSystem A pointer to the file system's mapped name. If NULL, then the current working + directory is changed. + @param Dir Points to the NULL-terminated directory on the device specified by FileSystem. + + @retval EFI_SUCCESS The operation was sucessful +**/ +EFI_STATUS +EFIAPI +EfiShellSetCurDir( + IN CONST CHAR16 *FileSystem OPTIONAL, + IN CONST CHAR16 *Dir + ); + +/** + Return help information about a specific command. + + This function returns the help information for the specified command. The help text + can be internal to the shell or can be from a UEFI Shell manual page. + + If Sections is specified, then each section name listed will be compared in a casesensitive + manner, to the section names described in Appendix B. If the section exists, + it will be appended to the returned help text. If the section does not exist, no + information will be returned. If Sections is NULL, then all help text information + available will be returned. + + @param Command Points to the NULL-terminated UEFI Shell command name. + @param Sections Points to the NULL-terminated comma-delimited + section names to return. If NULL, then all + sections will be returned. + @param HelpText On return, points to a callee-allocated buffer + containing all specified help text. + + @retval EFI_SUCCESS The help text was returned. + @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the + returned help text. + @retval EFI_INVALID_PARAMETER HelpText is NULL + @retval EFI_NOT_FOUND There is no help text available for Command. +**/ +EFI_STATUS +EFIAPI +EfiShellGetHelpText( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Sections OPTIONAL, + OUT CHAR16 **HelpText + ); + +/** + Gets the enable status of the page break output mode. + + User can use this function to determine current page break mode. + + @retval TRUE The page break output mode is enabled + @retval FALSE The page break output mode is disabled +**/ +BOOLEAN +EFIAPI +EfiShellGetPageBreak( + VOID + ); + +/** + Judges whether the active shell is the root shell. + + This function makes the user to know that whether the active Shell is the root shell. + + @retval TRUE The active Shell is the root Shell. + @retval FALSE The active Shell is NOT the root Shell. +**/ +BOOLEAN +EFIAPI +EfiShellIsRootShell( + VOID + ); + +/** + This function returns the command associated with a alias or a list of all + alias'. + + @param[in] Command Points to the NULL-terminated shell alias. + If this parameter is NULL, then all + aliases will be returned in ReturnedData. + @param[out] Volatile upon return of a single command if TRUE indicates + this is stored in a volatile fashion. FALSE otherwise. + @return If Alias is not NULL, it will return a pointer to + the NULL-terminated command for that alias. + If Alias is NULL, ReturnedData points to a ';' + delimited list of alias (e.g. + ReturnedData = "dir;del;copy;mfp") that is NULL-terminated. + @retval NULL an error ocurred + @retval NULL Alias was not a valid Alias +**/ +CONST CHAR16 * +EFIAPI +EfiShellGetAlias( + IN CONST CHAR16 *Command, + OUT BOOLEAN *Volatile OPTIONAL + ); + +/** + Changes a shell command alias. + + This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias. + + this function does not check for built in alias'. + + @param[in] Command Points to the NULL-terminated shell command or existing alias. + @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and + Command refers to an alias, that alias will be deleted. + @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the + Alias being set will be stored in a non-volatile fashion. + + @retval EFI_SUCCESS Alias created or deleted successfully. + @retval EFI_NOT_FOUND the Alias intended to be deleted was not found +**/ +EFI_STATUS +InternalSetAlias( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias OPTIONAL, + IN BOOLEAN Volatile + ); + +/** + Changes a shell command alias. + + This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias. + + + @param[in] Command Points to the NULL-terminated shell command or existing alias. + @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and + Command refers to an alias, that alias will be deleted. + @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If + FALSE and the alias already exists, then the existing alias is unchanged and + EFI_ACCESS_DENIED is returned. + @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the + Alias being set will be stored in a non-volatile fashion. + + @retval EFI_SUCCESS Alias created or deleted successfully. + @retval EFI_NOT_FOUND the Alias intended to be deleted was not found + @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to + FALSE. +**/ +EFI_STATUS +EFIAPI +EfiShellSetAlias( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias OPTIONAL, + IN BOOLEAN Replace, + IN BOOLEAN Volatile + ); + +/** + Utility cleanup function for EFI_SHELL_FILE_INFO objects. + + 1) frees all pointers (non-NULL) + 2) Closes the SHELL_FILE_HANDLE + + @param FileListNode pointer to the list node to free +**/ +VOID +InternalFreeShellFileInfoNode( + IN EFI_SHELL_FILE_INFO *FileListNode + ); + +/** + Internal variable setting function. Allows for setting of the read only variables. + + @param Name Points to the NULL-terminated environment variable name. + @param Value Points to the NULL-terminated environment variable value. If the value is an + empty string then the environment variable is deleted. + @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS The environment variable was successfully updated. +**/ +EFI_STATUS +InternalEfiShellSetEnv( + IN CONST CHAR16 *Name, + IN CONST CHAR16 *Value, + IN BOOLEAN Volatile + ); + +/** + Function to start monitoring for CTRL-C using SimpleTextInputEx. This + feature's enabled state was not known when the shell initially launched. + + @retval EFI_SUCCESS The feature is enabled. + @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available. +**/ +EFI_STATUS +InernalEfiShellStartMonitor( + VOID + ); + +/** + Notification function for keystrokes. + + @param[in] KeyData The key that was pressed. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +NotificationFunction( + IN EFI_KEY_DATA *KeyData + ); +#endif //_SHELL_PROTOCOL_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/README.txt b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/README.txt new file mode 100644 index 0000000..75aa175 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/README.txt @@ -0,0 +1,5 @@ +TestArgv.nsh is a very simple shell script to test how the interpreter parses +the parameters. It uses ShellCTestApp.efi to dump the parameters passed from the +intepreter. + +TestArgv.log is the desired output created using "TestArgv.nsh > TestArgv.log". diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c new file mode 100644 index 0000000..f2fe8fb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c @@ -0,0 +1,51 @@ +/** @file + This is a test application that demonstrates how to use the C-style entry point + for a shell application. + + Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +/** + UEFI application entry point which has an interface similar to a + standard C main function. + + The ShellCEntryLib library instance wrappers the actual UEFI application + entry point and calls this ShellAppMain function. + + @param[in] Argc The number of items in Argv. + @param[in] Argv Array of pointers to strings. + + @retval 0 The application exited normally. + @retval Other An error occurred. + +**/ +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + UINTN Index; + if (Argc == 1) { + Print (L"Argv[1] = NULL\n"); + } + for (Index = 1; Index < Argc; Index++) { + Print(L"Argv[%d]: \"%s\"\n", Index, Argv[Index]); + } + + return 0; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf new file mode 100644 index 0000000..474584d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf @@ -0,0 +1,39 @@ +## @file +# This is the shell application +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = ShellCTestApp + FILE_GUID = 7a6ca3b8-ee1b-489c-b300-24544a7bd418 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + ShellCTestApp.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/TestArgv.log b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellCTestApp/TestArgv.log new file mode 100644 index 0000000000000000000000000000000000000000..e76781ea0e4387cf97ad42d5ccbb8a72f99c8d61 GIT binary patch literal 3320 zcmcha-EPxB5QWcmCEmeumCH&=6Q>ChNOt0IgFvXzn?fx_-5;r<5dp;01K+G=wZUFT z4t8bPp6txdIXgS!+5Gvv(y4}eu8(@DK)Jr?M)ycZJiqFh4zz8t!R9;qGkw-KWlGU6 zxW|e#<(=u6YsOfniB5PQBgI;RVq;?^SS}e^XwK6tSG z6wbzGjsFynkz~r3x3bglzc99*ns>FZui6^ z$5YB|TUqKjByMDk?-*&K5xNLzj@B?UxXl@z5|O#n4|!TFACSWa^b?g9C`41Yx6R&)JgoC}xQDkv=M_BguC@=X z_VFub)Wt8{BYpw9>Dyh?wdWUj{k8Yy=e7?s%VdA_OxK=ax7AVIi9j!?v^V;o*Iex? zci_HvU3V0JeYCINP<_-?Kz|&lkDlgVdws7rCUrUWuxkIe(mHWBeXox7|KwFjS1x)? zS%r09qknC-&tLv^TVGjo`)hx_$9HL)bB_OC+-1c#^Us}awf4$0 +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ +echo -on +set Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA ValueOfGuid +set Sharp_E8528E46_A008_4221_8DE0_D5AB42A9C580 ^# +set Quote_E95DEE8B_E3AA_4155_9ED5_6916394104FC ^" +set Var_ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE +alias ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE ShellCTestApp + +# +# '^' should escape all special characters (including space) +# but has no impact to non-special characters +# +ShellCTestApp ^^ +ShellCTestApp ^# +ShellCTestApp ^%Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA% +ShellCTestApp ^" +ShellCTestApp ^ 1 +ShellCTestApp ^ +ShellCTestApp ^1 +ShellCTestApp ^^^" +ShellCTestApp ^^^ + +# +# '#' should be processed before %% replacement, and inside '"' +# +ShellCTestApp #%Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA% +#ShellCTestApp "#" +ShellCTestApp %Sharp_E8528E46_A008_4221_8DE0_D5AB42A9C580% + +# +# '%' should be processed before grouping parameters +# +ShellCTestApp "%Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA% 2%Quote_E95DEE8B_E3AA_4155_9ED5_6916394104FC% + +# +# alias should be processed after %% replacement +# +%Var_ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE% + +# +# '"' should be stripped, space inside '"' should be kept, +# +ShellCTestApp "p 1" +ShellCTestApp "p"1 +ShellCTestApp "p 1"e"x""" + +set -d Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA +set -d Sharp_E8528E46_A008_4221_8DE0_D5AB42A9C580 +set -d Quote_E95DEE8B_E3AA_4155_9ED5_6916394104FC +set -d Var_ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE +alias -d ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE +echo -off \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.c new file mode 100644 index 0000000..5ab6a0c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.c @@ -0,0 +1,38 @@ +/** @file + This is a simple shell application + + Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include + +/** + as the real entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + Print(L"ShellExecute - Pass"); + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.inf new file mode 100644 index 0000000..8e4a642 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellExecTestApp/SA.inf @@ -0,0 +1,41 @@ +## @file +# Sample UEFI Application Reference EDKII Module +# +# This is a simple shell application +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EmptyApplication + FILE_GUID = 8F7D7B1D-0E1C-4c98-B12E-4EC99C4081AC + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + SA.c + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c new file mode 100644 index 0000000..cea2f1c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c @@ -0,0 +1,83 @@ +/** @file + This is a test application that demonstrates how to use the sorting functions. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + +/** + Test comparator. + + @param[in] b1 The first INTN + @param[in] b2 The other INTN + + @retval 0 They are the same. + @retval -1 b1 is less than b2 + @retval 1 b1 is greater then b2 +**/ +INTN +EFIAPI +Test(CONST VOID *b1, CONST VOID *b2) +{ + if (*(INTN*)b1 == *(INTN*)b2) { + return (0); + } + if (*(INTN*)b1 < *(INTN*)b2) { + return(-1); + } + return (1); +} + +/** + UEFI application entry point which has an interface similar to a + standard C main function. + + The ShellCEntryLib library instance wrappers the actual UEFI application + entry point and calls this ShellAppMain function. + + @param Argc Argument count + @param Argv The parsed arguments + + @retval 0 The application exited normally. + @retval Other An error occurred. + +**/ +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + INTN Array[10]; + + Array[0] = 2; + Array[1] = 3; + Array[2] = 4; + Array[3] = 1; + Array[4] = 5; + Array[5] = 6; + Array[6] = 7; + Array[7] = 8; + Array[8] = 1; + Array[9] = 5; + + Print(L"Array = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\r\n", Array[0],Array[1],Array[2],Array[3],Array[4],Array[5],Array[6],Array[7],Array[8],Array[9]); + PerformQuickSort(Array, 10, sizeof(INTN), Test); + Print(L"POST-SORT\r\n"); + Print(L"Array = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\r\n", Array[0],Array[1],Array[2],Array[3],Array[4],Array[5],Array[6],Array[7],Array[8],Array[9]); + return 0; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf new file mode 100644 index 0000000..77be188 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf @@ -0,0 +1,42 @@ +## @file +# This is the shell sorting testing application +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = ShellSortTestApp + FILE_GUID = 079E8E98-AE93-4b9a-8A71-1DC869F23E09 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources] + ShellSortTestApp.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + ShellCEntryLib + UefiLib + SortLib + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c new file mode 100644 index 0000000..0e13e62 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.c @@ -0,0 +1,972 @@ +/** @file + Shell command for Displaying Performance Metrics. + + The Dp command reads performance data and presents it in several + different formats depending upon the needs of the user. Both + Trace and Measured Profiling information is processed and presented. + + Dp uses the "PerformanceLib" to read the measurement records. + The "TimerLib" provides information about the timer, such as frequency, + beginning, and ending counter values. + Measurement records contain identifying information (Handle, Token, Module) + and start and end time values. + Dp uses this information to group records in different ways. It also uses + timer information to calculate elapsed time for each measurement. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +#pragma pack(1) + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Entry; +} RSDT_TABLE; + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 Entry; +} XSDT_TABLE; + +#pragma pack() + +EFI_HANDLE mDpHiiHandle; + +typedef struct { + EFI_HANDLE Handle; + EFI_GUID ModuleGuid; +} HANDLE_GUID_MAP; + +HANDLE_GUID_MAP *mCacheHandleGuidTable; +UINTN mCachePairCount = 0; + +// +/// Module-Global Variables +///@{ +CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1]; +CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE]; +UINT64 mInterestThreshold; +BOOLEAN mShowId = FALSE; +UINT8 *mBootPerformanceTable; +UINTN mBootPerformanceTableSize; +BOOLEAN mPeiPhase = FALSE; +BOOLEAN mDxePhase = FALSE; + +PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO. +MEASUREMENT_RECORD *mMeasurementList = NULL; +UINTN mMeasurementNum = 0; + +/// Items for which to gather cumulative statistics. +PERF_CUM_DATA CumData[] = { + PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK), + PERF_INIT_CUM_DATA (START_IMAGE_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK), + PERF_INIT_CUM_DATA (DRIVERBINDING_STOP_TOK) +}; + +/// Number of items for which we are gathering cumulative statistics. +UINT32 const NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA); + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-v", TypeFlag}, // -v Verbose Mode + {L"-A", TypeFlag}, // -A All, Cooked + {L"-R", TypeFlag}, // -R RAW All + {L"-s", TypeFlag}, // -s Summary + {L"-x", TypeFlag}, // -x eXclude Cumulative Items + {L"-i", TypeFlag}, // -i Display Identifier + {L"-c", TypeValue}, // -c Display cumulative data. + {L"-n", TypeValue}, // -n # Number of records to display for A and R + {L"-t", TypeValue}, // -t # Threshold of interest + {NULL, TypeMax} + }; + +///@} + +/** + Display the trailing Verbose information. +**/ +VOID +DumpStatistics( void ) +{ + EFI_STRING StringPtr; + EFI_STRING StringPtrUnknown; + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL); + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), mDpHiiHandle, SummaryData.NumTrace); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), mDpHiiHandle, SummaryData.NumIncomplete); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), mDpHiiHandle, SummaryData.NumSummary); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), mDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), mDpHiiHandle, SummaryData.NumPEIMs); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), mDpHiiHandle, SummaryData.NumGlobal); + SHELL_FREE_NON_NULL (StringPtr); + SHELL_FREE_NON_NULL (StringPtrUnknown); +} + +/** + Get Boot performance table form Acpi table. + +**/ +EFI_STATUS +GetBootPerformanceTable ( + ) +{ + FIRMWARE_PERFORMANCE_TABLE *FirmwarePerformanceTable; + + FirmwarePerformanceTable = (FIRMWARE_PERFORMANCE_TABLE *) EfiLocateFirstAcpiTable ( + EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE + ); + if (FirmwarePerformanceTable == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GET_ACPI_FPDT_FAIL), mDpHiiHandle); + return EFI_NOT_FOUND; + } + + mBootPerformanceTable = (UINT8*) (UINTN)FirmwarePerformanceTable->BootPointerRecord.BootPerformanceTablePointer; + mBootPerformanceTableSize = ((BOOT_PERFORMANCE_TABLE *) mBootPerformanceTable)->Header.Length; + + return EFI_SUCCESS; +} + +/** + Get Handle form Module Guid. + + @param ModuleGuid Module Guid. + @param Handle The handle to be returned. + +**/ +VOID +GetHandleFormModuleGuid ( + IN EFI_GUID *ModuleGuid, + IN OUT EFI_HANDLE *Handle + ) +{ + UINTN Index; + + if (IsZeroGuid (ModuleGuid)) { + *Handle = NULL; + } + // + // Try to get the Handle form the caached array. + // + for (Index = 0; Index < mCachePairCount; Index++) { + if (CompareGuid (ModuleGuid, &mCacheHandleGuidTable[Index].ModuleGuid)) { + *Handle = mCacheHandleGuidTable[Index].Handle; + break; + } + } + if (Index >= mCachePairCount) { + *Handle = NULL; + } +} + +/** +Cache the GUID and handle mapping pairs. In order to save time for searching. + +**/ +EFI_STATUS +BuildCachedGuidHandleTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_GUID *TempGuid; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; + + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status); + return Status; + } + + mCacheHandleGuidTable = AllocateZeroPool (HandleCount * sizeof (HANDLE_GUID_MAP)); + if (mCacheHandleGuidTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < HandleCount; Index++) { + // + // Try Handle as ImageHandle. + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiLoadedImageProtocolGuid, + (VOID**) &LoadedImage + ); + if (EFI_ERROR (Status)) { + // + // Try Handle as Controller Handle + // + Status = gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // Get Image protocol from ImageHandle + // + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**) &LoadedImage + ); + } + } + + if (!EFI_ERROR (Status) && LoadedImage != NULL) { + // + // Get Module Guid from DevicePath. + // + if (LoadedImage->FilePath != NULL && + LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH && + LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP + ) { + FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LoadedImage->FilePath; + TempGuid = &FvFilePath->FvFileName; + + mCacheHandleGuidTable[mCachePairCount].Handle = HandleBuffer[Index]; + CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, TempGuid); + mCachePairCount ++; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + HandleBuffer = NULL; + } + return EFI_SUCCESS; +} + +/** + Get Measurement form Fpdt records. + + @param RecordHeader Pointer to the start record. + @param IsStart Is start record or End record. + @param Measurement Pointer to the measurement which need to be filled. + +**/ +VOID +GetMeasurementInfo ( + IN EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader, + IN BOOLEAN IsStart, + IN OUT MEASUREMENT_RECORD *Measurement + ) +{ + VOID *ModuleGuid; + EFI_HANDLE StartHandle; + + switch (RecordHeader->Type) { + case FPDT_GUID_EVENT_TYPE: + ModuleGuid = &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_GUID_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp; + } + switch (Measurement->Identifier) { + case MODULE_START_ID: + case MODULE_END_ID: + if (mPeiPhase) { + Measurement->Token = ALit_PEIM; + Measurement->Module = ALit_PEIM; + } else if (mDxePhase) { + Measurement->Token = ALit_START_IMAGE; + Measurement->Module = ALit_START_IMAGE; + } + break; + default: + ASSERT(FALSE); + } + + if (Measurement->Token != NULL && AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) { + Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid); + } else { + GetHandleFormModuleGuid(ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + // + // When no perf entry to record the PEI and DXE phase, + // For start image, we need detect the PEIM and non PEIM here. + // + if (Measurement->Token == NULL) { + if (StartHandle == NULL && !IsZeroGuid (ModuleGuid)) { + Measurement->Token = ALit_PEIM; + Measurement->Module = ALit_PEIM; + Measurement->Handle = ModuleGuid; + } else { + Measurement->Token = ALit_START_IMAGE; + Measurement->Module = ALit_START_IMAGE; + } + } + } + break; + + case FPDT_DYNAMIC_STRING_EVENT_TYPE: + ModuleGuid = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } + switch (Measurement->Identifier) { + case MODULE_START_ID: + case MODULE_END_ID: + if (mPeiPhase) { + Measurement->Token = ALit_PEIM; + } else if (mDxePhase) { + Measurement->Token = ALit_START_IMAGE; + } + break; + + case MODULE_LOADIMAGE_START_ID: + case MODULE_LOADIMAGE_END_ID: + Measurement->Token = ALit_LOAD_IMAGE; + break; + + case MODULE_DB_START_ID: + case MODULE_DB_END_ID: + Measurement->Token = ALit_DB_START; + break; + + case MODULE_DB_SUPPORT_START_ID: + case MODULE_DB_SUPPORT_END_ID: + Measurement->Token = ALit_DB_SUPPORT; + break; + + case MODULE_DB_STOP_START_ID: + case MODULE_DB_STOP_END_ID: + Measurement->Token = ALit_DB_STOP; + break; + + default: + Measurement->Token = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String; + break; + } + + Measurement->Module = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String; + + if (Measurement->Token != NULL && AsciiStrCmp (Measurement->Token, ALit_PEIM) == 0) { + Measurement->Handle = &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid); + } else { + GetHandleFormModuleGuid(ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + // + // When no perf entry to record the PEI and DXE phase, + // For start image, we need detect the PEIM and non PEIM here. + // + if (Measurement->Token == NULL && (Measurement->Identifier == MODULE_START_ID || Measurement->Identifier == MODULE_END_ID)) { + if (StartHandle == NULL && !IsZeroGuid (ModuleGuid)) { + Measurement->Token = ALit_PEIM; + Measurement->Handle = ModuleGuid; + } else { + Measurement->Token = ALit_START_IMAGE; + } + } + } + break; + + case FPDT_GUID_QWORD_EVENT_TYPE: + ModuleGuid = &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp; + } + switch (Measurement->Identifier) { + case MODULE_DB_START_ID: + Measurement->Token = ALit_DB_START; + Measurement->Module = ALit_DB_START; + break; + + case MODULE_DB_SUPPORT_START_ID: + case MODULE_DB_SUPPORT_END_ID: + Measurement->Token = ALit_DB_SUPPORT; + Measurement->Module = ALit_DB_SUPPORT; + break; + + case MODULE_DB_STOP_START_ID: + case MODULE_DB_STOP_END_ID: + Measurement->Token = ALit_DB_STOP; + Measurement->Module = ALit_DB_STOP; + break; + + case MODULE_LOADIMAGE_START_ID: + case MODULE_LOADIMAGE_END_ID: + Measurement->Token = ALit_LOAD_IMAGE; + Measurement->Module = ALit_LOAD_IMAGE; + break; + + default: + ASSERT(FALSE); + } + GetHandleFormModuleGuid(ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + break; + + case FPDT_GUID_QWORD_STRING_EVENT_TYPE: + ModuleGuid = &(((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Guid); + Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD*)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } + // + // Currently only "DB:Start:" end record with FPDT_GUID_QWORD_STRING_EVENT_TYPE. + // + switch (Measurement->Identifier) { + case MODULE_DB_END_ID: + Measurement->Token = ALit_DB_START; + Measurement->Module = ALit_DB_START; + break; + default: + ASSERT(FALSE); + } + GetHandleFormModuleGuid(ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + break; + + case FPDT_DUAL_GUID_STRING_EVENT_TYPE: + ModuleGuid = &(((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Guid1); + Measurement->Identifier = ((UINT32)((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->ProgressID); + if (IsStart) { + Measurement->StartTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } else { + Measurement->EndTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp; + } + Measurement->Token = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String; + Measurement->Module = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String; + GetHandleFormModuleGuid(ModuleGuid, &StartHandle); + Measurement->Handle = StartHandle; + break; + + default: + break; + } +} + +/** + Search the start measurement in the mMeasurementList for the end measurement. + + @param EndMeasureMent Measurement for end record. + +**/ +VOID +SearchMeasurement ( + IN MEASUREMENT_RECORD *EndMeasureMent + ) +{ + INTN Index; + + for (Index = mMeasurementNum - 1; Index >= 0; Index--) { + if (AsciiStrCmp (EndMeasureMent->Token, ALit_PEIM) == 0) { + if (mMeasurementList[Index].EndTimeStamp == 0 && EndMeasureMent->Handle!= NULL && mMeasurementList[Index].Handle != NULL&& + CompareGuid(mMeasurementList[Index].Handle, EndMeasureMent->Handle) && + (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) && + (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) { + mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp; + break; + } + } else if (EndMeasureMent->Identifier == PERF_CROSSMODULE_END_ID) { + if (mMeasurementList[Index].EndTimeStamp == 0 && + (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) && + (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0) && + mMeasurementList[Index].Identifier == PERF_CROSSMODULE_START_ID) { + mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp; + break; + } + } else { + if (mMeasurementList[Index].EndTimeStamp == 0 && mMeasurementList[Index].Handle == EndMeasureMent->Handle && + (AsciiStrCmp (mMeasurementList[Index].Token, EndMeasureMent->Token) == 0) && + (AsciiStrCmp (mMeasurementList[Index].Module, EndMeasureMent->Module) == 0)) { + mMeasurementList[Index].EndTimeStamp = EndMeasureMent->EndTimeStamp; + break; + } + } + } +} + +/** + Generate the measure record array. + +**/ +EFI_STATUS +BuildMeasurementList ( + ) +{ + EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader; + UINT8 *PerformanceTablePtr; + UINT16 StartProgressId; + UINTN TableLength; + UINT8 *StartRecordEvent; + MEASUREMENT_RECORD MeasureMent; + + mMeasurementList = AllocateZeroPool (mBootPerformanceTableSize); + if (mMeasurementList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TableLength = sizeof (BOOT_PERFORMANCE_TABLE); + PerformanceTablePtr = (mBootPerformanceTable + TableLength); + + while (TableLength < mBootPerformanceTableSize) { + RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER*) PerformanceTablePtr; + StartRecordEvent = (UINT8 *)RecordHeader; + StartProgressId = ((FPDT_GUID_EVENT_RECORD *)StartRecordEvent)->ProgressID; + + // + // If the record with ProgressId 0, the record doesn't appear in pairs. The timestamp in the record is the EndTimeStamp, its StartTimeStamp is 0. + // If the record is the start record, fill the info to the measurement in the mMeasurementList. + // If the record is the end record, find the related start measurement in the mMeasurementList and fill the EndTimeStamp. + // + if (StartProgressId == 0) { + GetMeasurementInfo (RecordHeader, FALSE, &(mMeasurementList[mMeasurementNum])); + mMeasurementNum ++; + } else if (((StartProgressId >= PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x000F) == 0)) || + (StartProgressId < PERF_EVENTSIGNAL_START_ID && ((StartProgressId & 0x0001) != 0)))) { + // + // Since PEIM and StartImage has same Type and ID when PCD PcdEdkiiFpdtStringRecordEnableOnly = FALSE + // So we need to identify these two kinds of record through different phase. + // + if(StartProgressId == PERF_CROSSMODULE_START_ID ){ + if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_PEI) == 0) { + mPeiPhase = TRUE; + } else if (AsciiStrCmp (((FPDT_DYNAMIC_STRING_EVENT_RECORD *)StartRecordEvent)->String, ALit_DXE) == 0) { + mDxePhase = TRUE; + mPeiPhase = FALSE; + } + } + // Get measurement info form the start record to the mMeasurementList. + GetMeasurementInfo (RecordHeader, TRUE, &(mMeasurementList[mMeasurementNum])); + mMeasurementNum ++; + } else { + ZeroMem(&MeasureMent, sizeof(MEASUREMENT_RECORD)); + GetMeasurementInfo (RecordHeader, FALSE, &MeasureMent); + SearchMeasurement (&MeasureMent); + } + TableLength += RecordHeader->Length; + PerformanceTablePtr += RecordHeader->Length; + } + return EFI_SUCCESS; +} + +/** + Initialize the cumulative data. + +**/ +VOID +InitCumulativeData ( + VOID + ) +{ + UINTN Index; + + for (Index = 0; Index < NumCum; ++Index) { + CumData[Index].Count = 0; + CumData[Index].MinDur = PERF_MAXDUR; + CumData[Index].MaxDur = 0; + CumData[Index].Duration = 0; + } +} + +/** + Initialize the Summary data. + +**/ +VOID +InitSummaryData ( + VOID + ) +{ + SummaryData.NumTrace = 0; + SummaryData.NumIncomplete = 0; + SummaryData.NumSummary = 0; + SummaryData.NumHandles = 0; + SummaryData.NumPEIMs = 0; + SummaryData.NumGlobal = 0; +} + +/** + Dump performance data. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval SHELL_SUCCESS Command completed successfully. + @retval SHELL_INVALID_PARAMETER Command usage error. + @retval SHELL_ABORTED The user aborts the operation. + @retval value Unknown error. +**/ +SHELL_STATUS +RunDp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + LIST_ENTRY *ParamPackage; + CONST CHAR16 *CmdLineArg; + EFI_STATUS Status; + + PERFORMANCE_PROPERTY *PerformanceProperty; + UINTN Number2Display; + + EFI_STRING StringPtr; + BOOLEAN SummaryMode; + BOOLEAN VerboseMode; + BOOLEAN AllMode; + BOOLEAN RawMode; + BOOLEAN ExcludeMode; + BOOLEAN CumulativeMode; + CONST CHAR16 *CustomCumulativeToken; + PERF_CUM_DATA *CustomCumulativeData; + UINTN NameSize; + SHELL_STATUS ShellStatus; + TIMER_INFO TimerInfo; + UINT64 Intermediate; + + StringPtr = NULL; + SummaryMode = FALSE; + VerboseMode = FALSE; + AllMode = FALSE; + RawMode = FALSE; + ExcludeMode = FALSE; + CumulativeMode = FALSE; + CustomCumulativeData = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // Process Command Line arguments + // + Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(ParamPackage) > 1){ + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_MANY), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } + + // + // Boolean options + // + VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v"); + SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s")); + AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A"); + RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R"); + ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x"); + mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i"); + CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c"); + + if (AllMode && RawMode) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CONFLICT_ARG), mDpHiiHandle, L"-A", L"-R"); + return SHELL_INVALID_PARAMETER; + } + + // Options with Values + if (ShellCommandLineGetFlag (ParamPackage, L"-n")) { + CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n"); + if (CmdLineArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else { + if (!(RawMode || AllMode)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_NO_RAW_ALL), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } + Status = ShellConvertStringToUint64(CmdLineArg, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-n"); + return SHELL_INVALID_PARAMETER; + } else { + Number2Display = (UINTN)Intermediate; + if (Number2Display == 0 || Number2Display > MAXIMUM_DISPLAYCOUNT) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_RANGE), mDpHiiHandle, L"-n", 0, MAXIMUM_DISPLAYCOUNT); + return SHELL_INVALID_PARAMETER; + } + } + } + } else { + Number2Display = DEFAULT_DISPLAYCOUNT; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-t")) { + CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t"); + if (CmdLineArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CmdLineArg, &Intermediate, FALSE, TRUE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_NUM_ARG), mDpHiiHandle, L"-t"); + return SHELL_INVALID_PARAMETER; + } else { + mInterestThreshold = Intermediate; + } + } + } else { + mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-c")) { + CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c"); + if (CustomCumulativeToken == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOO_FEW), mDpHiiHandle); + return SHELL_INVALID_PARAMETER; + } else { + CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA)); + if (CustomCumulativeData == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + CustomCumulativeData->MinDur = PERF_MAXDUR; + CustomCumulativeData->MaxDur = 0; + CustomCumulativeData->Count = 0; + CustomCumulativeData->Duration = 0; + NameSize = StrLen (CustomCumulativeToken) + 1; + CustomCumulativeData->Name = AllocateZeroPool (NameSize); + if (CustomCumulativeData->Name == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize); + } + } + + // + // DP dump performance data by parsing FPDT table in ACPI table. + // Folloing 3 steps are to get the measurement form the FPDT table. + // + + // + //1. Get FPDT from ACPI table. + // + Status = GetBootPerformanceTable (); + if (EFI_ERROR (Status)) { + ShellStatus = Status; + goto Done; + } + + // + //2. Cache the ModuleGuid and hanlde mapping table. + // + Status = BuildCachedGuidHandleTable(); + if (EFI_ERROR (Status)) { + ShellStatus = Status; + goto Done; + } + + // + //3. Build the measurement array form the FPDT records. + // + Status = BuildMeasurementList (); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize the pre-defined cumulative data. + // + InitCumulativeData (); + + // + // Initialize the Summary data. + // + InitSummaryData (); + + // + // Timer specific processing + // + // Get the Performance counter characteristics: + // Freq = Frequency in Hz + // StartCount = Value loaded into the counter when it starts counting + // EndCount = Value counter counts to before it needs to be reset + // + Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty); + if (EFI_ERROR (Status) || (PerformanceProperty == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PERF_PROPERTY_NOT_FOUND), mDpHiiHandle); + goto Done; + } + + TimerInfo.Frequency = (UINT32)DivU64x32 (PerformanceProperty->Frequency, 1000); + TimerInfo.StartCount = 0; + TimerInfo.EndCount = 0xFFFF; + TimerInfo.CountUp = TRUE; + + // + // Print header + // + // print DP's build version + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), mDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION); + + // print performance timer characteristics + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), mDpHiiHandle, TimerInfo.Frequency); + + if (VerboseMode && !RawMode) { + StringPtr = HiiGetString (mDpHiiHandle, + (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL); + ASSERT (StringPtr != NULL); + // Print Timer count range and direction + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), mDpHiiHandle, + StringPtr, + TimerInfo.StartCount, + TimerInfo.EndCount + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mDpHiiHandle, mInterestThreshold); + } + +/**************************************************************************** +**** Print Sections based on command line options +**** +**** Option modes have the following priority: +**** v Verbose -- Valid in combination with any other options +**** t Threshold -- Modifies All, Raw, and Cooked output +**** Default is 0 for All and Raw mode +**** Default is DEFAULT_THRESHOLD for "Cooked" mode +**** n Number2Display Used by All and Raw mode. Otherwise ignored. +**** A All -- R and S options are ignored +**** R Raw -- S option is ignored +**** s Summary -- Modifies "Cooked" output only +**** Cooked (Default) +****************************************************************************/ + GatherStatistics (CustomCumulativeData); + if (CumulativeMode) { + ProcessCumulative (CustomCumulativeData); + } else if (AllMode) { + Status = DumpAllTrace( Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + } else if (RawMode) { + Status = DumpRawTrace( Number2Display, ExcludeMode); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + } else { + //------------- Begin Cooked Mode Processing + ProcessPhases (); + if ( ! SummaryMode) { + Status = ProcessHandles ( ExcludeMode); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + + Status = ProcessPeims (); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + + Status = ProcessGlobal (); + if (Status == EFI_ABORTED) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + + ProcessCumulative (NULL); + } + } //------------- End of Cooked Mode Processing + if ( VerboseMode || SummaryMode) { + DumpStatistics(); + } + +Done: + if (ParamPackage != NULL) { + ShellCommandLineFreeVarList (ParamPackage); + } + SHELL_FREE_NON_NULL (StringPtr); + if (CustomCumulativeData != NULL) { + SHELL_FREE_NON_NULL (CustomCumulativeData->Name); + } + SHELL_FREE_NON_NULL (CustomCumulativeData); + + SHELL_FREE_NON_NULL (mMeasurementList); + + SHELL_FREE_NON_NULL (mCacheHandleGuidTable); + + mMeasurementNum = 0; + mCachePairCount = 0; + return ShellStatus; +} + + +/** + Retrive HII package list from ImageHandle and publish to HII database. + + @param ImageHandle The image handle of the process. + + @return HII handle. +**/ +EFI_HANDLE +InitializeHiiPackage ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + EFI_HANDLE HiiHandle; + + // + // Retrieve HII package list from ImageHandle + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiHiiPackageListProtocolGuid, + (VOID **)&PackageList, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Publish HII package list to HII Database. + // + Status = gHiiDatabase->NewPackageList ( + gHiiDatabase, + PackageList, + NULL, + &HiiHandle + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return NULL; + } + return HiiHandle; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h new file mode 100644 index 0000000..12c78ab --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.h @@ -0,0 +1,146 @@ +/** @file + Header file for 'dp' command functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _DP_H_ +#define _DP_H_ + + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE mDpHiiHandle; + +#define DP_MAJOR_VERSION 2 +#define DP_MINOR_VERSION 5 + +/** + * The value assigned to DP_DEBUG controls which debug output + * is generated. Set it to ZERO to disable. +**/ +#define DP_DEBUG 0 + +#define DEFAULT_THRESHOLD 1000 ///< One millisecond. +#define DEFAULT_DISPLAYCOUNT 50 +#define MAXIMUM_DISPLAYCOUNT 999999 ///< Arbitrary maximum reasonable number. + +#define PERF_MAXDUR 0xFFFFFFFFFFFFFFFFULL + +/// Determine whether 0 <= C < L. If L == 0, return true regardless of C. +#define WITHIN_LIMIT( C, L) ( ((L) == 0) || ((C) < (L)) ) + +/// Structure for storing Timer specific information. +typedef struct { + UINT64 StartCount; ///< Value timer is initialized with. + UINT64 EndCount; ///< Value timer has just before it wraps. + UINT32 Frequency; ///< Timer count frequency in KHz. + BOOLEAN CountUp; ///< TRUE if the counter counts up. +} TIMER_INFO; + +/** Initialize one PERF_CUM_DATA structure instance for token t. + * + * This parameterized macro takes a single argument, t, which is expected + * to resolve to a pointer to an ASCII string literal. This parameter may + * take any one of the following forms: + * - PERF_INIT_CUM_DATA("Token") A string literal + * - PERF_INIT_CUM_DATA(pointer) A pointer -- CHAR8 *pointer; + * - PERF_INIT_CUM_DATA(array) Address of an array -- CHAR8 array[N]; +**/ +#define PERF_INIT_CUM_DATA(t) { 0ULL, PERF_MAXDUR, 0ULL, (t), 0U } + +typedef struct { + UINT64 Duration; ///< Cumulative duration for this item. + UINT64 MinDur; ///< Smallest duration encountered. + UINT64 MaxDur; ///< Largest duration encountered. + CHAR8 *Name; ///< ASCII name of this item. + UINT32 Count; ///< Total number of measurements accumulated. +} PERF_CUM_DATA; + +typedef struct { + UINT32 NumTrace; ///< Number of recorded TRACE performance measurements. + UINT32 NumIncomplete; ///< Number of measurements with no END value. + UINT32 NumSummary; ///< Number of summary section measurements. + UINT32 NumHandles; ///< Number of measurements with handles. + UINT32 NumPEIMs; ///< Number of measurements of PEIMs. + UINT32 NumGlobal; ///< Number of measurements with END value and NULL handle. +} PERF_SUMMARY_DATA; + +typedef struct { + CONST VOID *Handle; + CONST CHAR8 *Token; ///< Measured token string name. + CONST CHAR8 *Module; ///< Module string name. + UINT64 StartTimeStamp; ///< Start time point. + UINT64 EndTimeStamp; ///< End time point. + UINT32 Identifier; ///< Identifier. +} MEASUREMENT_RECORD; + +typedef struct { + CHAR8 *Name; ///< Measured token string name. + UINT64 CumulativeTime; ///< Accumulated Elapsed Time. + UINT64 MinTime; ///< Minimum Elapsed Time. + UINT64 MaxTime; ///< Maximum Elapsed Time. + UINT32 Count; ///< Number of measurements accumulated. +} PROFILE_RECORD; + +/** + Dump performance data. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval SHELL_SUCCESS Command completed successfully. + @retval SHELL_INVALID_PARAMETER Command usage error. + @retval SHELL_ABORTED The user aborts the operation. + @retval value Unknown error. +**/ +SHELL_STATUS +RunDp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Retrive HII package list from ImageHandle and publish to HII database. + + @param ImageHandle The image handle of the process. + + @return HII handle. +**/ +EFI_HANDLE +InitializeHiiPackage ( + EFI_HANDLE ImageHandle + ); +#endif // _DP_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni new file mode 100644 index 0000000..0b593b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Dp.uni @@ -0,0 +1,134 @@ +// *++ +// +// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +// (C) Copyright 2015 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// +// Module Name: +// +// DpStrings.uni +// +// Abstract: +// +// String definitions for the Shell dp command +// +// Revision History: +// +// --*/ + +/=# + +#langdef en-US "English" + +#string STR_DP_UP #language en-US "UP" +#string STR_DP_DOWN #language en-US "DOWN" +#string STR_DP_DASHES #language en-US "-------------------------------------------------------------------------------\n" +#string STR_DP_SECTION_HEADER #language en-US "\n==[ %s ]========\n" +#string STR_DP_INVALID_ARG #language en-US "Invalid argument(s)\n" +#string STR_DP_TOO_MANY #language en-US "Too many arguments\n" +#string STR_DP_TOO_FEW #language en-US "Too few arguments\n" +#string STR_DP_INVALID_NUM_ARG #language en-US "Invalid argument(s), the value of %H%s%N must be numbers\n" +#string STR_DP_INVALID_RANGE #language en-US "Invalid argument(s), the value of %H%s%N must be between %H%d%N and %H%d%N\n" +#string STR_DP_CONFLICT_ARG #language en-US "Invalid argument(s), %H%s%N can not be used together with %H%s%N\n" +#string STR_DP_NO_RAW_ALL #language en-US "Invalid argument(s), -n flag must use with -A or -R\n" +#string STR_DP_HANDLES_ERROR #language en-US "Locate all handles error - %r\n" +#string STR_DP_ERROR_NAME #language en-US "Unknown driver name" +#string STR_PERF_PROPERTY_NOT_FOUND #language en-US "Performance property not found\n" +#string STR_DP_BUILD_REVISION #language en-US "\nDP Build Version: %d.%d\n" +#string STR_DP_KHZ #language en-US "System Performance Timer Frequency: %,8d (KHz)\n" +#string STR_DP_TIMER_PROPERTIES #language en-US "System Performance Timer counts %s from 0x%Lx to 0x%Lx\n" +#string STR_DP_VERBOSE_THRESHOLD #language en-US "Measurements less than %,Ld microseconds are not displayed.\n" +#string STR_DP_SECTION_PHASES #language en-US "Major Phases" +#string STR_DP_SEC_PHASE #language en-US " SEC Phase Duration: %L8d (us)\n" +#string STR_DP_PHASE_BDSTO #language en-US " BDS Timeout: %L8d (ms) included in BDS Duration\n" +#string STR_DP_PHASE_DURATION #language en-US "%5a Phase Duration: %L8d (ms)\n" +#string STR_DP_TOTAL_DURATION #language en-US "Total Duration: %L8d (ms)\n" +#string STR_DP_SECTION_DRIVERS #language en-US "Drivers by Handle" +#string STR_DP_HANDLE_SECTION #language en-US "Index: Handle Driver Name Description Time(us)\n" +#string STR_DP_HANDLE_VARS #language en-US "%5d: [%3x] %36s %11s %L8d\n" +#string STR_DP_HANDLE_SECTION2 #language en-US "Index: Handle Driver Name Description Time(us) ID\n" +#string STR_DP_HANDLE_VARS2 #language en-US "%5d: [%3x] %36s %11s %L8d %5d\n" +#string STR_DP_SECTION_PEIMS #language en-US "PEIMs" +#string STR_DP_PEIM_SECTION #language en-US "Index: Instance GUID Token Time(us)\n" +#string STR_DP_PEIM_VARS #language en-US "%5d: %g PEIM %L8d\n" +#string STR_DP_PEIM_SECTION2 #language en-US "Index: Instance GUID Token Time(us) ID\n" +#string STR_DP_PEIM_VARS2 #language en-US "%5d: %g PEIM %L8d %5d\n" +#string STR_DP_SECTION_GENERAL #language en-US "General" +#string STR_DP_GLOBAL_SECTION #language en-US "Index Name Description Time(us)\n" +#string STR_DP_GLOBAL_VARS #language en-US "%5d:%25s %31s %L8d\n" +#string STR_DP_GLOBAL_SECTION2 #language en-US "Index Name Description Time(us) ID\n" +#string STR_DP_GLOBAL_VARS2 #language en-US "%5d:%25s %31s %L8d %5d\n" +#string STR_DP_SECTION_CUMULATIVE #language en-US "Cumulative" +#string STR_DP_CUMULATIVE_SECT_1 #language en-US "(Times in microsec.) Cumulative Average Shortest Longest\n" +#string STR_DP_CUMULATIVE_SECT_2 #language en-US " Name Count Duration Duration Duration Duration\n" +#string STR_DP_CUMULATIVE_STATS #language en-US "%11a %8d %L10d %L10d %L10d %L10d\n" +#string STR_DP_SECTION_STATISTICS #language en-US "Statistics" +#string STR_DP_STATS_NUMTRACE #language en-US "There were %d measurements taken, of which:\n" +#string STR_DP_STATS_NUMINCOMPLETE #language en-US "%,8d are incomplete.\n" +#string STR_DP_STATS_NUMPHASES #language en-US "%,8d are major execution phases.\n" +#string STR_DP_STATS_NUMHANDLES #language en-US "%,8d have non-NULL handles, %d are NULL.\n" +#string STR_DP_STATS_NUMPEIMS #language en-US "%,8d are PEIMs.\n" +#string STR_DP_STATS_NUMGLOBALS #language en-US "%,8d are general measurements.\n" +#string STR_DP_STATS_NUMPROFILE #language en-US "%,8d are profiling records.\n" +#string STR_DP_SECTION_ALL #language en-US "Sequential Trace Records" +#string STR_DP_ALL_HEADR #language en-US "\nIndex Handle Module Token Time(us)\n" +#string STR_DP_ALL_VARS #language en-US "%5d:%3s0x%08p %36s %13s %L8d\n" +#string STR_DP_ALL_DASHES2 #language en-US "-------------------------------------------------------------------------------------\n" +#string STR_DP_ALL_HEADR2 #language en-US "\nIndex Handle Module Token Time(us) ID\n" +#string STR_DP_ALL_VARS2 #language en-US "%5d:%3s0x%08p %36s %13s %L8d %5d\n" +#string STR_DP_SECTION_RAWTRACE #language en-US "RAW Trace" +#string STR_DP_RAW_DASHES #language en-US "---------------------------------------------------------------------------------------------------------------------------\n" +#string STR_DP_RAW_VARS #language en-US "%5d: %16LX %16LX %16LX %31a %31a\n" +#string STR_DP_RAW_HEADR #language en-US "\nIndex Handle Start Count End Count Token Module\n" +#string STR_DP_RAW_DASHES2 #language en-US "---------------------------------------------------------------------------------------------------------------------------------\n" +#string STR_DP_RAW_VARS2 #language en-US "%5d: %16LX %16LX %16LX %31a %31a %5d\n" +#string STR_DP_RAW_HEADR2 #language en-US "\nIndex Handle Start Count End Count Token Module ID\n" +#string STR_DP_INCOMPLETE #language en-US " I " +#string STR_DP_COMPLETE #language en-US " " +#string STR_ALIT_UNKNOWN #language en-US "Unknown" +#string STR_DP_GET_ACPI_FPDT_FAIL #language en-US "Fail to get Firmware Performance Data Table (FPDT) in ACPI Table\n" + +#string STR_GET_HELP_DP #language en-US "" +".TH dp 0 "Display performance metrics"\r\n" +".SH NAME\r\n" +"Displays performance metrics that are stored in memory.\r\n" +".SH SYNOPSIS\r\n" +"DP [-b] [-v] [-x] [-s | -A | -R] [-t value] [-n count] [-c [token]][-i] [-?]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays on multiple pages\r\n" +" -v - Displays additional information\r\n" +" -x - Prevents display of individual measurements for cumulative items\r\n" +" -s - Displays summary information only\r\n" +" -A - Displays all measurements in a list\r\n" +" -R - Displays all measurements in raw format\r\n" +" -t VALUE - Sets display threshold to VALUE microseconds\r\n" +" -n COUNT - Limits display to COUNT lines in All and Raw modes\r\n" +" -i - Displays identifier\r\n" +" -c TOKEN - Display pre-defined and custom cumulative data\r\n" +" Pre-defined cumulative token are:\r\n" +" 1. LoadImage:\r\n" +" 2. StartImage:\r\n" +" 3. DB:Start:\r\n" +" 4. DB:Support:\r\n" +" -? - Displays DP help information\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. Displays Performance metrics that are stored in memory.\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_NOT_FOUND The requested option was not found.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly formatted or its value was out of bounds.\r\n" +" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient free space for the request to be completed.\r\n" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c new file mode 100644 index 0000000..4bd9281 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.c @@ -0,0 +1,53 @@ +/** @file + Entrypoint of "dp" shell standalone application. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "Dp.h" + +// +// String token ID of help message text. +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes +// that the help string is consumed by user and then build tool will add the string into +// the resource section. Thus the application can use '-?' option to show help message in +// Shell. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_GET_HELP_DP); + +/** + Entry point of Tftp standalone application. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Tftp command is executed sucessfully. + @retval EFI_ABORTED HII package was failed to initialize. + @retval others Other errors when executing tftp command. +**/ +EFI_STATUS +EFIAPI +DpAppInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + mDpHiiHandle = InitializeHiiPackage (ImageHandle); + if (mDpHiiHandle == NULL) { + return EFI_ABORTED; + } + + Status = (EFI_STATUS)RunDp (ImageHandle, SystemTable); + HiiRemovePackages (mDpHiiHandle); + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf new file mode 100644 index 0000000..ffbc54a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf @@ -0,0 +1,69 @@ +## @file +# Provides Shell 'dp' standalone application. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = dp + FILE_GUID = 1831A379-2D48-45BD-9744-D4059D93815D + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = DpAppInitialize +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +[Sources.common] + Dp.uni + Dp.c + Dp.h + Literals.h + Literals.c + DpInternal.h + DpUtilities.c + DpTrace.c + DpApp.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiApplicationEntryPoint + SortLib + PrintLib + DevicePathLib + PerformanceLib + DxeServicesLib + PeCoffGetEntryPointLib + +[Guids] + gPerformanceProtocolGuid ## CONSUMES ## SystemTable + +[Protocols] + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c new file mode 100644 index 0000000..032acfc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.c @@ -0,0 +1,131 @@ +/** @file + Produce "dp" shell dynamic command. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "Dp.h" +#include + +/** + This is the shell command handler function pointer callback type. This + function handles the command when it is invoked in the shell. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the context + of processing this command. + + @return EFI_SUCCESS the operation was sucessful + @return other the operation failed. +**/ +SHELL_STATUS +EFIAPI +DpCommandHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ) +{ + gEfiShellParametersProtocol = ShellParameters; + gEfiShellProtocol = Shell; + return RunDp (gImageHandle, SystemTable); +} + +/** + This is the command help handler function pointer callback type. This + function is responsible for displaying help information for the associated + command. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return string Pool allocated help string, must be freed by caller +**/ +CHAR16 * +EFIAPI +DpCommandGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ) +{ + return HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_GET_HELP_DP), Language); +} + +EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mDpDynamicCommand = { + L"dp", + DpCommandHandler, + DpCommandGetHelp +}; + +/** + Entry point of Tftp Dynamic Command. + + Produce the DynamicCommand protocol to handle "tftp" command. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Tftp command is executed sucessfully. + @retval EFI_ABORTED HII package was failed to initialize. + @retval others Other errors when executing tftp command. +**/ +EFI_STATUS +EFIAPI +DpCommandInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + mDpHiiHandle = InitializeHiiPackage (ImageHandle); + if (mDpHiiHandle == NULL) { + return EFI_ABORTED; + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDpDynamicCommand + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + Tftp driver unload handler. + + @param ImageHandle The image handle of the process. + + @retval EFI_SUCCESS The image is unloaded. + @retval Others Failed to unload the image. +**/ +EFI_STATUS +EFIAPI +DpUnload ( + IN EFI_HANDLE ImageHandle +) +{ + EFI_STATUS Status; + Status = gBS->UninstallProtocolInterface ( + ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + &mDpDynamicCommand + ); + if (EFI_ERROR (Status)) { + return Status; + } + HiiRemovePackages (mDpHiiHandle); + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf new file mode 100644 index 0000000..c6de1ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf @@ -0,0 +1,73 @@ +## @file +# Provides Shell 'dp' dynamic command. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = dpDynamicCommand + FILE_GUID = 0253F9FA-129A-4A8D-B12E-7DC2B6376302 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DpCommandInitialize + UNLOAD_IMAGE = DpUnload +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +[Sources.common] + Dp.uni + Dp.c + Dp.h + Literals.h + Literals.c + DpInternal.h + DpUtilities.c + DpTrace.c + DpDynamicCommand.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + SortLib + PrintLib + DevicePathLib + PerformanceLib + DxeServicesLib + PeCoffGetEntryPointLib + +[Guids] + gPerformanceProtocolGuid ## CONSUMES ## SystemTable + +[Protocols] + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES + gEfiShellDynamicCommandProtocolGuid ## PRODUCES + +[DEPEX] + TRUE diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h new file mode 100644 index 0000000..0b35ddb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpInternal.h @@ -0,0 +1,321 @@ +/** @file + Declarations of objects defined internally to the Dp Application. + + Declarations of data and functions which are private to the Dp application. + This file should never be referenced by anything other than components of the + Dp application. In addition to global data, function declarations for + DpUtilities.c, DpTrace.c, and DpProfile.c are included here. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#ifndef _DP_INTELNAL_H_ +#define _DP_INTELNAL_H_ + +#define DP_GAUGE_STRING_LENGTH 36 + +// +/// Module-Global Variables +///@{ +extern EFI_HII_HANDLE mDpHiiHandle; +extern CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1]; +extern CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE]; +extern UINT64 mInterestThreshold; +extern BOOLEAN mShowId; +extern UINT8 *mBootPerformanceTable; +extern UINTN mBootPerformanceTableLength; +extern MEASUREMENT_RECORD *mMeasurementList; +extern UINTN mMeasurementNum; + +extern PERF_SUMMARY_DATA SummaryData; ///< Create the SummaryData structure and init. to ZERO. + +/// Items for which to gather cumulative statistics. +extern PERF_CUM_DATA CumData[]; + +/// Number of items for which we are gathering cumulative statistics. +extern UINT32 const NumCum; + +///@} + +/** + Calculate an event's duration in timer ticks. + + Given the count direction and the event's start and end timer values, + calculate the duration of the event in timer ticks. Information for + the current measurement is pointed to by the parameter. + + If the measurement's start time is 1, it indicates that the developer + is indicating that the measurement began at the release of reset. + The start time is adjusted to the timer's starting count before performing + the elapsed time calculation. + + The calculated duration, in ticks, is the absolute difference between + the measurement's ending and starting counts. + + @param Measurement Pointer to a MEASUREMENT_RECORD structure containing + data for the current measurement. + + @return The 64-bit duration of the event. +**/ +UINT64 +GetDuration ( + IN OUT MEASUREMENT_RECORD *Measurement + ); + +/** + Determine whether the Measurement record is for an EFI Phase. + + The Token and Module members of the measurement record are checked. + Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is for an EFI Phase. + @retval FALSE The measurement record is NOT for an EFI Phase. +**/ +BOOLEAN +IsPhase( + IN MEASUREMENT_RECORD *Measurement + ); + +/** + Determine whether the Measurement record is for core code. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is used for core. + @retval FALSE The measurement record is NOT used for core. + +**/ +BOOLEAN +IsCorePerf( + IN MEASUREMENT_RECORD *Measurement + ); + +/** + Get the file name portion of the Pdb File Name. + + The portion of the Pdb File Name between the last backslash and + either a following period or the end of the string is converted + to Unicode and copied into UnicodeBuffer. The name is truncated, + if necessary, to ensure that UnicodeBuffer is not overrun. + + @param[in] PdbFileName Pdb file name. + @param[out] UnicodeBuffer The resultant Unicode File Name. + +**/ +VOID +DpGetShortPdbFileName ( + IN CHAR8 *PdbFileName, + OUT CHAR16 *UnicodeBuffer + ); + +/** + Get a human readable name for an image handle. + The following methods will be tried orderly: + 1. Image PDB + 2. ComponentName2 protocol + 3. FFS UI section + 4. Image GUID + 5. Image DevicePath + 6. Unknown Driver Name + + @param[in] Handle + + @post The resulting Unicode name string is stored in the + mGaugeString global array. + +**/ +VOID +DpGetNameFromHandle ( + IN EFI_HANDLE Handle + ); + +/** + Calculate the Duration in microseconds. + + Duration is multiplied by 1000, instead of Frequency being divided by 1000 or + multiplying the result by 1000, in order to maintain precision. Since Duration is + a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow. + + The time is calculated as (Duration * 1000) / Timer_Frequency. + + @param[in] Duration The event duration in timer ticks. + + @return A 64-bit value which is the Elapsed time in microseconds. +**/ +UINT64 +DurationInMicroSeconds ( + IN UINT64 Duration + ); + +/** + Get index of Measurement Record's match in the CumData array. + + If the Measurement's Token value matches a Token in one of the CumData + records, the index of the matching record is returned. The returned + index is a signed value so that negative values can indicate that + the Measurement didn't match any entry in the CumData array. + + @param[in] Measurement A pointer to a Measurement Record to match against the CumData array. + + @retval <0 Token is not in the CumData array. + @retval >=0 Return value is the index into CumData where Token is found. +**/ +INTN +GetCumulativeItem( + IN MEASUREMENT_RECORD *Measurement + ); + +/** + Collect verbose statistics about the logged performance measurements. + + General Summary information for all Trace measurements is gathered and + stored within the SummaryData structure. This information is both + used internally by subsequent reporting functions, and displayed + at the end of verbose reports. + + @pre The SummaryData and CumData structures must be initialized + prior to calling this function. + + @post The SummaryData and CumData structures contain statistics for the + current performance logs. + + @param[in, out] CustomCumulativeData The pointer to the custom cumulative data. + +**/ +VOID +GatherStatistics( + IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ); + +/** + Gather and print ALL Trace Records. + + Displays all "interesting" Trace measurements in order.
        + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + They must not be in use by a calling function. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +DumpAllTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ); + +/** + Gather and print Raw Trace Records. + + All Trace measurements with a duration greater than or equal to + mInterestThreshold are printed without interpretation. + + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ); + +/** + Gather and print Major Phase metrics. + +**/ +VOID +ProcessPhases( + VOID + ); + + +/** + Gather and print Handle data. + + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag + ); + + +/** + Gather and print PEIM data. + + Only prints complete PEIM records + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessPeims( + VOID + ); + +/** + Gather and print global data. + + Strips out incomplete or "Execution Phase" records + Only prints records where Handle is NULL + Increment TIndex for every record, even skipped ones, so that we have an + indication of every measurement record taken. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessGlobal( + VOID + ); + +/** + Gather and print cumulative data. + + Traverse the measurement records and:
        + For each record with a Token listed in the CumData array:
        + - Update the instance count and the total, minimum, and maximum durations. + Finally, print the gathered cumulative statistics. + + @param[in] CustomCumulativeData The pointer to the custom cumulative data. + +**/ +VOID +ProcessCumulative( + IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c new file mode 100644 index 0000000..392f629 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpTrace.c @@ -0,0 +1,910 @@ +/** @file + Trace reporting for the Dp utility. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** + Attempts to retrieve a performance measurement log entry from the performance measurement log. + + + @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 log 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 when the measurement + was ended. + + @return The key for the next performance log entry (in general case). + +**/ +UINTN +GetPerformanceMeasurementRecord ( + IN UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp, + OUT UINT32 *Identifier + ) +{ + if (LogEntryKey == mMeasurementNum) { + return 0; + } + + *Handle = (VOID *) (UINTN) mMeasurementList[LogEntryKey].Handle; + *Token = mMeasurementList[LogEntryKey].Token; + *Module = mMeasurementList[LogEntryKey].Module; + *StartTimeStamp = mMeasurementList[LogEntryKey].StartTimeStamp; + *EndTimeStamp = mMeasurementList[LogEntryKey].EndTimeStamp; + *Identifier = mMeasurementList[LogEntryKey].Identifier; + + LogEntryKey ++; + + return LogEntryKey; +} + +/** + Collect verbose statistics about the logged performance measurements. + + General Summary information for all Trace measurements is gathered and + stored within the SummaryData structure. This information is both + used internally by subsequent reporting functions, and displayed + at the end of verbose reports. + + @pre The SummaryData and CumData structures must be initialized + prior to calling this function. + + @post The SummaryData and CumData structures contain statistics for the + current performance logs. + + @param[in, out] CustomCumulativeData A pointer to the cumtom cumulative data. + +**/ +VOID +GatherStatistics( + IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINTN LogEntryKey; + INTN TIndex; + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + ++SummaryData.NumTrace; // Count the number of TRACE Measurement records + if (Measurement.EndTimeStamp == 0) { + ++SummaryData.NumIncomplete; // Count the incomplete records + continue; + } + + if (Measurement.Handle != NULL) { + ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles + } + + if (IsPhase( &Measurement)) { + ++SummaryData.NumSummary; // Count the number of major phases + } + else { // !IsPhase + if(Measurement.Handle == NULL) { + ++SummaryData.NumGlobal; + } + } + + if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) { + ++SummaryData.NumPEIMs; // Count PEIM measurements + } + + Duration = GetDuration (&Measurement); + TIndex = GetCumulativeItem (&Measurement); + if (TIndex >= 0) { + CumData[TIndex].Duration += Duration; + CumData[TIndex].Count++; + if ( Duration < CumData[TIndex].MinDur ) { + CumData[TIndex].MinDur = Duration; + } + if ( Duration > CumData[TIndex].MaxDur ) { + CumData[TIndex].MaxDur = Duration; + } + } + + // + // Collect the data for custom cumulative data. + // + if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) { + CustomCumulativeData->Duration += Duration; + CustomCumulativeData->Count++; + if (Duration < CustomCumulativeData->MinDur) { + CustomCumulativeData->MinDur = Duration; + } + if (Duration > CustomCumulativeData->MaxDur) { + CustomCumulativeData->MaxDur = Duration; + } + } + } +} + +/** + Gather and print ALL Trace Records. + + Displays all "interesting" Trace measurements in order.
        + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + The mGaugeString and mUnicodeToken global arrays are used for temporary string storage. + They must not be in use by a calling function. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +DumpAllTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + CHAR16 *IncFlag; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + UINTN TIndex; + + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + EFI_STATUS Status; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (IncFlag == NULL) ? StringPtrUnknown : IncFlag); + FreePool (StringPtrUnknown); + + // Get Handle information + // + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status); + } + else { + // We have successfully populated the HandleBuffer + // Display ALL Measurement Records + // Up to Limit lines displayed + // Display only records with Elapsed times >= mInterestThreshold + // Display driver names in Module field for records with Handles. + // + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + } + + LogEntryKey = 0; + Count = 0; + Index = 0; + while ( WITHIN_LIMIT(Count, Limit) && + ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + SHELL_FREE_NON_NULL (IncFlag); + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL); + } + else { + IncFlag = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records + } + if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + ++Count; // Count the number of records printed + + // If Handle is non-zero, see if we can determine a name for the driver + AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); // Use Module by default + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + if (Measurement.Handle != NULL) { + // See if the Handle is in the HandleBuffer + for (TIndex = 0; TIndex < HandleCount; TIndex++) { + if (Measurement.Handle == HandleBuffer[TIndex]) { + DpGetNameFromHandle (HandleBuffer[TIndex]); + break; + } + } + } + + if (AsciiStrCmp (Measurement.Token, ALit_PEIM) == 0) { + UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle); + } + + // Ensure that the argument strings are not too long. + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + mUnicodeToken[13] = 0; + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + IncFlag, + Measurement.Handle, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + SHELL_FREE_NON_NULL (IncFlag); + + return Status; +} + +/** + Gather and print Raw Trace Records. + + All Trace measurements with a duration greater than or equal to + mInterestThreshold are printed without interpretation. + + The number of records displayed is controlled by: + - records with a duration less than mInterestThreshold microseconds are not displayed. + - No more than Limit records are displayed. A Limit of zero will not limit the output. + - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not + displayed. + + @pre The mInterestThreshold global variable is set to the shortest duration to be printed. + + @param[in] Limit The number of records to print. Zero is ALL. + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +DumpRawTrace( + IN UINTN Limit, + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + UINTN LogEntryKey; + UINTN Count; + UINTN Index; + + EFI_STRING StringPtr; + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), mDpHiiHandle); + } + + LogEntryKey = 0; + Count = 0; + Index = 0; + while ( WITHIN_LIMIT(Count, Limit) && + ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + ) + { + ++Index; // Count every record. First record is 1. + ElapsedTime = 0; + if (Measurement.EndTimeStamp != 0) { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + } + if ((ElapsedTime < mInterestThreshold) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or Excluded records + continue; + } + ++Count; // Count the number of records printed + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + Measurement.Handle, + Measurement.StartTimeStamp, + Measurement.EndTimeStamp, + Measurement.Token, + Measurement.Module, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), mDpHiiHandle, + Index, // 1 based, Which measurement record is being printed + Measurement.Handle, + Measurement.StartTimeStamp, + Measurement.EndTimeStamp, + Measurement.Token, + Measurement.Module + ); + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + return Status; +} + +/** + Gather and print Major Phase metrics. + +**/ +VOID +ProcessPhases( + VOID + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 BdsTimeoutValue; + UINT64 SecTime; + UINT64 PeiTime; + UINT64 DxeTime; + UINT64 BdsTime; + UINT64 ElapsedTime; + UINT64 Duration; + UINT64 Total; + EFI_STRING StringPtr; + UINTN LogEntryKey; + EFI_STRING StringPtrUnknown; + + BdsTimeoutValue = 0; + SecTime = 0; + PeiTime = 0; + DxeTime = 0; + BdsTime = 0; + // + // Get Execution Phase Statistics + // + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records + continue; + } + Duration = GetDuration (&Measurement); + if ( Measurement.Handle != NULL + && (AsciiStrCmp (Measurement.Token, ALit_BdsTO) == 0) + ) + { + BdsTimeoutValue = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_SEC) == 0) { + SecTime = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_PEI) == 0) { + PeiTime = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_DXE) == 0) { + DxeTime = Duration; + } else if (AsciiStrCmp (Measurement.Token, ALit_BDS) == 0) { + BdsTime = Duration; + } + } + + Total = 0; + + // print SEC phase duration time + // + if (SecTime > 0) { + ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds + Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), mDpHiiHandle, ElapsedTime); + } + + // print PEI phase duration time + // + if (PeiTime > 0) { + ElapsedTime = DivU64x32 (PeiTime, 1000000); + Total += ElapsedTime; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_PEI, ElapsedTime); + } + + // print DXE phase duration time + // + if (DxeTime > 0) { + ElapsedTime = DivU64x32 (DxeTime, 1000000); + Total += ElapsedTime; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_DXE, ElapsedTime); + } + + // print BDS phase duration time + // + if (BdsTime > 0) { + ElapsedTime = DivU64x32 (BdsTime, 1000000); + Total += ElapsedTime; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), mDpHiiHandle, ALit_BDS, ElapsedTime); + } + + if (BdsTimeoutValue > 0) { + ElapsedTime = DivU64x32 (BdsTimeoutValue, 1000000); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), mDpHiiHandle, ALit_BdsTO, ElapsedTime); + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), mDpHiiHandle, Total); +} + +/** + Gather and print Handle data. + + @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. + @return Others from a call to gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +ProcessHandles( + IN BOOLEAN ExcludeFlag + ) +{ + MEASUREMENT_RECORD Measurement; + UINT64 ElapsedTime; + UINT64 Duration; + EFI_HANDLE *HandleBuffer; + EFI_STRING StringPtr; + UINTN Index; + UINTN LogEntryKey; + UINTN Count; + UINTN HandleCount; + EFI_STATUS Status; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), mDpHiiHandle, Status); + } + else { +#if DP_DEBUG == 2 + Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0]))); +#endif + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), mDpHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + + LogEntryKey = 0; + Count = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + Count++; + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if ((ElapsedTime < mInterestThreshold) || + (Measurement.EndTimeStamp == 0) || + (!IsCorePerf (&Measurement)) || + ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0)) + ) { // Ignore "uninteresting" or excluded records + continue; + } + mGaugeString[0] = 0; // Empty driver name by default + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + // See if the Handle is in the HandleBuffer + for (Index = 0; Index < HandleCount; Index++) { + if (Measurement.Handle == HandleBuffer[Index]) { + DpGetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString + break; + } + } + // Ensure that the argument strings are not too long. + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + mUnicodeToken[11] = 0; + if (mGaugeString[0] != 0) { + // Display the record if it has a valid handle. + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), mDpHiiHandle, + Count, // 1 based, Which measurement record is being printed + Index + 1, // 1 based, Which handle is being printed + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), mDpHiiHandle, + Count, // 1 based, Which measurement record is being printed + Index + 1, // 1 based, Which handle is being printed + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return Status; +} + +/** + Gather and print PEIM data. + + Only prints complete PEIM records + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessPeims( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN TIndex; + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown : StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), mDpHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + TIndex = 0; + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + TIndex++; + if ((Measurement.EndTimeStamp == 0) || + (AsciiStrCmp (Measurement.Token, ALit_PEIM) != 0) + ) { + continue; + } + + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds + if (ElapsedTime >= mInterestThreshold) { + // PEIM FILE Handle is the start address of its FFS file that contains its file guid. + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), mDpHiiHandle, + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, // file guid + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), mDpHiiHandle, + TIndex, // 1 based, Which measurement record is being printed + Measurement.Handle, // file guid + ElapsedTime + ); + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + } + return Status; +} + +/** + Gather and print global data. + + Strips out incomplete or "Execution Phase" records + Only prints records where Handle is NULL + Increment TIndex for every record, even skipped ones, so that we have an + indication of every measurement record taken. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The user aborts the operation. +**/ +EFI_STATUS +ProcessGlobal( + VOID +) +{ + MEASUREMENT_RECORD Measurement; + UINT64 Duration; + UINT64 ElapsedTime; + EFI_STRING StringPtr; + UINTN LogEntryKey; + UINTN Index; // Index, or number, of the measurement record being processed + EFI_STRING StringPtrUnknown; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), mDpHiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), mDpHiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + + Index = 1; + LogEntryKey = 0; + + while ((LogEntryKey = GetPerformanceMeasurementRecord ( + LogEntryKey, + &Measurement.Handle, + &Measurement.Token, + &Measurement.Module, + &Measurement.StartTimeStamp, + &Measurement.EndTimeStamp, + &Measurement.Identifier)) != 0) + { + AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, ARRAY_SIZE (mGaugeString)); + AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, ARRAY_SIZE (mUnicodeToken)); + mGaugeString[25] = 0; + mUnicodeToken[31] = 0; + if ( ! ( IsPhase( &Measurement) || + IsCorePerf (&Measurement) || + (Measurement.EndTimeStamp == 0) + )) + { + Duration = GetDuration (&Measurement); + ElapsedTime = DurationInMicroSeconds ( Duration ); + if (ElapsedTime >= mInterestThreshold) { + if (mShowId) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), mDpHiiHandle, + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime, + Measurement.Identifier + ); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), mDpHiiHandle, + Index, + mGaugeString, + mUnicodeToken, + ElapsedTime + ); + } + } + } + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + Index++; + } + return Status; +} + +/** + Gather and print cumulative data. + + Traverse the measurement records and:
        + For each record with a Token listed in the CumData array:
        + - Update the instance count and the total, minimum, and maximum durations. + Finally, print the gathered cumulative statistics. + + @param[in] CustomCumulativeData A pointer to the cumtom cumulative data. + +**/ +VOID +ProcessCumulative( + IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL + ) +{ + UINT64 AvgDur; // the computed average duration + UINT64 Dur; + UINT64 MinDur; + UINT64 MaxDur; + EFI_STRING StringPtr; + UINTN TIndex; + EFI_STRING StringPtrUnknown; + + StringPtrUnknown = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL); + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), mDpHiiHandle, + (StringPtr == NULL) ? StringPtrUnknown: StringPtr); + FreePool (StringPtr); + FreePool (StringPtrUnknown); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), mDpHiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), mDpHiiHandle); + + for ( TIndex = 0; TIndex < NumCum; ++TIndex) { + if (CumData[TIndex].Count != 0) { + AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count); + AvgDur = DurationInMicroSeconds(AvgDur); + Dur = DurationInMicroSeconds(CumData[TIndex].Duration); + MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur); + MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle, + CumData[TIndex].Name, + CumData[TIndex].Count, + Dur, + AvgDur, + MinDur, + MaxDur + ); + } + } + + // + // Print the custom cumulative data. + // + if (CustomCumulativeData != NULL) { + if (CustomCumulativeData->Count != 0) { + AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count); + AvgDur = DurationInMicroSeconds (AvgDur); + Dur = DurationInMicroSeconds (CustomCumulativeData->Duration); + MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur); + MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur); + } else { + AvgDur = 0; + Dur = 0; + MaxDur = 0; + MinDur = 0; + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), mDpHiiHandle, + CustomCumulativeData->Name, + CustomCumulativeData->Count, + Dur, + AvgDur, + MinDur, + MaxDur + ); + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c new file mode 100644 index 0000000..0b6c5d9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/DpUtilities.c @@ -0,0 +1,428 @@ +/** @file + Utility functions used by the Dp application. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved. + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include "Dp.h" +#include "Literals.h" +#include "DpInternal.h" + +/** + Calculate an event's duration in timer ticks. + + Given the count direction and the event's start and end timer values, + calculate the duration of the event in timer ticks. Information for + the current measurement is pointed to by the parameter. + + If the measurement's start time is 1, it indicates that the developer + is indicating that the measurement began at the release of reset. + The start time is adjusted to the timer's starting count before performing + the elapsed time calculation. + + The calculated duration, in ticks, is the absolute difference between + the measurement's ending and starting counts. + + @param Measurement Pointer to a MEASUREMENT_RECORD structure containing + data for the current measurement. + + @return The 64-bit duration of the event. +**/ +UINT64 +GetDuration ( + IN OUT MEASUREMENT_RECORD *Measurement + ) +{ + UINT64 Duration; + BOOLEAN Error; + + if (Measurement->EndTimeStamp == 0) { + return 0; + } + + Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp; + Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp); + + if (Error) { + DEBUG ((EFI_D_ERROR, ALit_TimerLibError)); + Duration = 0; + } + return Duration; +} + +/** + Determine whether the Measurement record is for an EFI Phase. + + The Token and Module members of the measurement record are checked. + Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is for an EFI Phase. + @retval FALSE The measurement record is NOT for an EFI Phase. +**/ +BOOLEAN +IsPhase( + IN MEASUREMENT_RECORD *Measurement + ) +{ + BOOLEAN RetVal; + + RetVal = (BOOLEAN)( + ((AsciiStrCmp (Measurement->Token, ALit_SEC) == 0) || + (AsciiStrCmp (Measurement->Token, ALit_PEI) == 0) || + (AsciiStrCmp (Measurement->Token, ALit_DXE) == 0) || + (AsciiStrCmp (Measurement->Token, ALit_BDS) == 0)) + ); + return RetVal; +} + +/** + Determine whether the Measurement record is for core code. + + @param[in] Measurement A pointer to the Measurement record to test. + + @retval TRUE The measurement record is used for core. + @retval FALSE The measurement record is NOT used for core. + +**/ +BOOLEAN +IsCorePerf( + IN MEASUREMENT_RECORD *Measurement + ) +{ + BOOLEAN RetVal; + + RetVal = (BOOLEAN)( + ((Measurement->Identifier == MODULE_START_ID) || + (Measurement->Identifier == MODULE_END_ID) || + (Measurement->Identifier == MODULE_LOADIMAGE_START_ID) || + (Measurement->Identifier == MODULE_LOADIMAGE_END_ID) || + (Measurement->Identifier == MODULE_DB_START_ID) || + (Measurement->Identifier == MODULE_DB_END_ID) || + (Measurement->Identifier == MODULE_DB_SUPPORT_START_ID) || + (Measurement->Identifier == MODULE_DB_SUPPORT_END_ID) || + (Measurement->Identifier == MODULE_DB_STOP_START_ID) || + (Measurement->Identifier == MODULE_DB_STOP_START_ID)) + ); + return RetVal; +} + +/** + Get the file name portion of the Pdb File Name. + + The portion of the Pdb File Name between the last backslash and + either a following period or the end of the string is converted + to Unicode and copied into UnicodeBuffer. The name is truncated, + if necessary, to ensure that UnicodeBuffer is not overrun. + + @param[in] PdbFileName Pdb file name. + @param[out] UnicodeBuffer The resultant Unicode File Name. + +**/ +VOID +DpGetShortPdbFileName ( + IN CHAR8 *PdbFileName, + OUT CHAR16 *UnicodeBuffer + ) +{ + UINTN IndexA; // Current work location within an ASCII string. + UINTN IndexU; // Current work location within a Unicode string. + UINTN StartIndex; + UINTN EndIndex; + + ZeroMem (UnicodeBuffer, (DP_GAUGE_STRING_LENGTH + 1) * sizeof (CHAR16)); + + if (PdbFileName == NULL) { + StrnCpyS (UnicodeBuffer, DP_GAUGE_STRING_LENGTH + 1, L" ", 1); + } else { + StartIndex = 0; + for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) + ; + for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) { + if ((PdbFileName[IndexA] == '\\') || (PdbFileName[IndexA] == '/')) { + StartIndex = IndexA + 1; + } + + if (PdbFileName[IndexA] == '.') { + EndIndex = IndexA; + } + } + + IndexU = 0; + for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) { + UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA]; + IndexU++; + if (IndexU >= DP_GAUGE_STRING_LENGTH) { + UnicodeBuffer[DP_GAUGE_STRING_LENGTH] = 0; + break; + } + } + } +} + +/** + Get a human readable name for an image handle. + The following methods will be tried orderly: + 1. Image PDB + 2. ComponentName2 protocol + 3. FFS UI section + 4. Image GUID + 5. Image DevicePath + 6. Unknown Driver Name + + @param[in] Handle + + @post The resulting Unicode name string is stored in the + mGaugeString global array. + +**/ +VOID +DpGetNameFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *Image; + CHAR8 *PdbFileName; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_STRING StringPtr; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_GUID *NameGuid; + CHAR16 *NameString; + UINTN StringSize; + CHAR8 *PlatformLanguage; + CHAR8 *BestLanguage; + EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; + + Image = NULL; + LoadedImageDevicePath = NULL; + DevicePath = NULL; + + // + // Method 1: Get the name string from image PDB + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &Image + ); + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &Image + ); + } + } + + if (!EFI_ERROR (Status)) { + PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); + + if (PdbFileName != NULL) { + DpGetShortPdbFileName (PdbFileName, mGaugeString); + return; + } + } + + // + // Method 2: Get the name string from ComponentName2 protocol + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiComponentName2ProtocolGuid, + (VOID **) &ComponentName2 + ); + if (!EFI_ERROR (Status)) { + // + // Firstly use platform language setting, secondly use driver's first supported language. + // + GetVariable2 (L"PlatformLang", &gEfiGlobalVariableGuid, (VOID**)&PlatformLanguage, NULL); + BestLanguage = GetBestLanguage( + ComponentName2->SupportedLanguages, + FALSE, + (PlatformLanguage != NULL) ? PlatformLanguage : "", + ComponentName2->SupportedLanguages, + NULL + ); + SHELL_FREE_NON_NULL (PlatformLanguage); + + Status = ComponentName2->GetDriverName ( + ComponentName2, + BestLanguage != NULL ? BestLanguage : "en-US", + &StringPtr + ); + if (!EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (BestLanguage); + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH); + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + return; + } + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) { + DevicePath = LoadedImageDevicePath; + } else if (Image != NULL) { + DevicePath = Image->FilePath; + } + + if (DevicePath != NULL) { + // + // Try to get image GUID from image DevicePath + // + NameGuid = NULL; + while (!IsDevicePathEndType (DevicePath)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath); + if (NameGuid != NULL) { + break; + } + DevicePath = NextDevicePathNode (DevicePath); + } + + if (NameGuid != NULL) { + // + // Try to get the image's FFS UI section by image GUID + // + NameString = NULL; + StringSize = 0; + Status = GetSectionFromAnyFv ( + NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **) &NameString, + &StringSize + ); + + if (!EFI_ERROR (Status)) { + // + // Method 3. Get the name string from FFS UI section + // + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH); + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + FreePool (NameString); + } else { + // + // Method 4: Get the name string from image GUID + // + UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid); + } + return; + } else { + // + // Method 5: Get the name string from image DevicePath + // + NameString = ConvertDevicePathToText (DevicePath, TRUE, FALSE); + if (NameString != NULL) { + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH); + mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; + FreePool (NameString); + return; + } + } + } + + // + // Method 6: Unknown Driver Name + // + StringPtr = HiiGetString (mDpHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL); + ASSERT (StringPtr != NULL); + StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH); + FreePool (StringPtr); +} + +/** + Calculate the Duration in microseconds. + + Duration is multiplied by 1000, instead of Frequency being divided by 1000 or + multiplying the result by 1000, in order to maintain precision. Since Duration is + a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow. + + The time is calculated as (Duration * 1000) / Timer_Frequency. + + @param[in] Duration The event duration in timer ticks. + + @return A 64-bit value which is the Elapsed time in microseconds. +**/ +UINT64 +DurationInMicroSeconds ( + IN UINT64 Duration + ) +{ + return DivU64x32 (Duration, 1000); +} + +/** + Get index of Measurement Record's match in the CumData array. + + If the Measurement's Token value matches a Token in one of the CumData + records, the index of the matching record is returned. The returned + index is a signed value so that negative values can indicate that + the Measurement didn't match any entry in the CumData array. + + @param[in] Measurement A pointer to a Measurement Record to match against the CumData array. + + @retval <0 Token is not in the CumData array. + @retval >=0 Return value is the index into CumData where Token is found. +**/ +INTN +GetCumulativeItem( + IN MEASUREMENT_RECORD *Measurement + ) +{ + INTN Index; + + for( Index = 0; Index < (INTN)NumCum; ++Index) { + if (AsciiStrCmp (Measurement->Token, CumData[Index].Name) == 0) { + return Index; // Exit, we found a match + } + } + // If the for loop exits, Token was not found. + return -1; // Indicate failure +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c new file mode 100644 index 0000000..ea8f1a0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.c @@ -0,0 +1,28 @@ +/** @file + Definitions of ASCII string literals used by DP. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#include + +// ASCII String literals which probably don't need translation +CHAR8 const ALit_TimerLibError[] = "Timer library instance error!\n"; +CHAR8 const ALit_SEC[] = SEC_TOK; +CHAR8 const ALit_DXE[] = DXE_TOK; +CHAR8 const ALit_PEI[] = PEI_TOK; +CHAR8 const ALit_BDS[] = BDS_TOK; +CHAR8 const ALit_START_IMAGE[] = START_IMAGE_TOK; +CHAR8 const ALit_LOAD_IMAGE[] = LOAD_IMAGE_TOK; +CHAR8 const ALit_DB_START[] = DRIVERBINDING_START_TOK; +CHAR8 const ALit_DB_SUPPORT[] = DRIVERBINDING_SUPPORT_TOK; +CHAR8 const ALit_DB_STOP[] = DRIVERBINDING_STOP_TOK; + +CHAR8 const ALit_BdsTO[] = "BdsTimeOut"; +CHAR8 const ALit_PEIM[] = "PEIM"; diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h new file mode 100644 index 0000000..a46304d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/DpDynamicCommand/Literals.h @@ -0,0 +1,32 @@ +/** @file + Declarations of ASCII string literals used by DP. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ +#ifndef _LITERALS_H_ +#define _LITERALS_H_ + +// ASCII String literals which probably don't need translation +extern CHAR8 const ALit_TimerLibError[]; +extern CHAR8 const ALit_SEC[]; +extern CHAR8 const ALit_DXE[]; +extern CHAR8 const ALit_SHELL[]; +extern CHAR8 const ALit_PEI[]; +extern CHAR8 const ALit_BDS[]; +extern CHAR8 const ALit_PEIM[]; +extern CHAR8 const ALit_START_IMAGE[]; +extern CHAR8 const ALit_LOAD_IMAGE[]; +extern CHAR8 const ALit_DB_START[]; +extern CHAR8 const ALit_DB_SUPPORT[]; +extern CHAR8 const ALit_DB_STOP[]; +extern CHAR8 const ALit_BdsTO[]; +extern CHAR8 const ALit_PEIM[]; + +#endif // _LITERALS_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c new file mode 100644 index 0000000..bc29249 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.c @@ -0,0 +1,1135 @@ +/** @file + The implementation for the 'tftp' Shell command. + + Copyright (c) 2015, ARM Ltd. All rights reserved.
        + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "Tftp.h" + +#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32 +EFI_HANDLE mTftpHiiHandle; + +/* + Constant strings and definitions related to the message indicating the amount of + progress in the dowloading of a TFTP file. +*/ + +// Frame for the progression slider +STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]"; + +// Number of steps in the progression slider +#define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3) + +// Size in number of characters plus one (final zero) of the message to +// indicate the progress of a TFTP download. The format is "[(progress slider: +// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There +// are thus the number of characters in mTftpProgressFrame[] plus 11 characters +// (2 // spaces, "Kb" and seven characters for the number of KBytes). +#define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12) + +// String to delete the TFTP progress message to be able to update it : +// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b' +STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; + +// Local File Handle +SHELL_FILE_HANDLE mFileHandle; + +// Path of the local file, Unicode encoded +CONST CHAR16 *mLocalFilePath; + +/** + Check and convert the UINT16 option values of the 'tftp' command + + @param[in] ValueStr Value as an Unicode encoded string + @param[out] Value UINT16 value + + @return TRUE The value was returned. + @return FALSE A parsing error occured. +**/ +STATIC +BOOLEAN +StringToUint16 ( + IN CONST CHAR16 *ValueStr, + OUT UINT16 *Value + ); + +/** + Get the name of the NIC. + + @param[in] ControllerHandle The network physical device handle. + @param[in] NicNumber The network physical device number. + @param[out] NicName Address where to store the NIC name. + The memory area has to be at least + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH + double byte wide. + + @return EFI_SUCCESS The name of the NIC was returned. + @return Others The creation of the child for the Managed + Network Service failed or the opening of + the Managed Network Protocol failed or + the operational parameters for the + Managed Network Protocol could not be + read. +**/ +STATIC +EFI_STATUS +GetNicName ( + IN EFI_HANDLE ControllerHandle, + IN UINTN NicNumber, + OUT CHAR16 *NicName + ); + +/** + Create a child for the service identified by its service binding protocol GUID + and get from the child the interface of the protocol identified by its GUID. + + @param[in] ControllerHandle Controller handle. + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the + service to be created. + @param[in] ProtocolGuid GUID of the protocol to be open. + @param[out] ChildHandle Address where the handler of the + created child is returned. NULL is + returned in case of error. + @param[out] Interface Address where a pointer to the + protocol interface is returned in + case of success. + + @return EFI_SUCCESS The child was created and the protocol opened. + @return Others Either the creation of the child or the opening + of the protocol failed. +**/ +STATIC +EFI_STATUS +CreateServiceChildAndOpenProtocol ( + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *ServiceBindingProtocolGuid, + IN EFI_GUID *ProtocolGuid, + OUT EFI_HANDLE *ChildHandle, + OUT VOID **Interface + ); + +/** + Close the protocol identified by its GUID on the child handle of the service + identified by its service binding protocol GUID, then destroy the child + handle. + + @param[in] ControllerHandle Controller handle. + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the + service to be destroyed. + @param[in] ProtocolGuid GUID of the protocol to be closed. + @param[in] ChildHandle Handle of the child to be destroyed. + +**/ +STATIC +VOID +CloseProtocolAndDestroyServiceChild ( + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *ServiceBindingProtocolGuid, + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE ChildHandle + ); + +/** + Worker function that gets the size in numbers of bytes of a file from a TFTP + server before to download the file. + + @param[in] Mtftp4 MTFTP4 protocol interface + @param[in] FilePath Path of the file, ASCII encoded + @param[out] FileSize Address where to store the file size in number of + bytes. + + @retval EFI_SUCCESS The size of the file was returned. + @retval EFI_UNSUPPORTED The server does not support the "tsize" option. + @retval Others Error when retrieving the information from the server + (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes) + or error when parsing the response of the server. +**/ +STATIC +EFI_STATUS +GetFileSize ( + IN EFI_MTFTP4_PROTOCOL *Mtftp4, + IN CONST CHAR8 *FilePath, + OUT UINTN *FileSize + ); + +/** + Worker function that download the data of a file from a TFTP server given + the path of the file and its size. + + @param[in] Mtftp4 MTFTP4 protocol interface + @param[in] FilePath Path of the file, Unicode encoded + @param[in] AsciiFilePath Path of the file, ASCII encoded + @param[in] FileSize Size of the file in number of bytes + @param[in] BlockSize Value of the TFTP blksize option + @param[in] WindowSize Value of the TFTP window size option + + @retval EFI_SUCCESS The file was downloaded. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval Others The downloading of the file from the server failed + (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes). + +**/ +STATIC +EFI_STATUS +DownloadFile ( + IN EFI_MTFTP4_PROTOCOL *Mtftp4, + IN CONST CHAR16 *FilePath, + IN CONST CHAR8 *AsciiFilePath, + IN UINTN FileSize, + IN UINT16 BlockSize, + IN UINT16 WindowSize + ); + +/** + Update the progress of a file download + This procedure is called each time a new TFTP packet is received. + + @param[in] This MTFTP4 protocol interface + @param[in] Token Parameters for the download of the file + @param[in] PacketLen Length of the packet + @param[in] Packet Address of the packet + + @retval EFI_SUCCESS All packets are accepted. + +**/ +STATIC +EFI_STATUS +EFIAPI +CheckPacket ( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN UINT16 PacketLen, + IN EFI_MTFTP4_PACKET *Packet + ); + +EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = { + TRUE, // Use default setting + { { 0, 0, 0, 0 } }, // StationIp - Not relevant as UseDefaultSetting=TRUE + { { 0, 0, 0, 0 } }, // SubnetMask - Not relevant as UseDefaultSetting=TRUE + 0, // LocalPort - Automatically assigned port number. + { { 0, 0, 0, 0 } }, // GatewayIp - Not relevant as UseDefaultSetting=TRUE + { { 0, 0, 0, 0 } }, // ServerIp - Not known yet + 69, // InitialServerPort - Standard TFTP server port + 6, // TryCount - The number of times to transmit request packets and wait for a response. + 4 // TimeoutValue - Retransmission timeout in seconds. +}; + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-i", TypeValue}, + {L"-l", TypeValue}, + {L"-r", TypeValue}, + {L"-c", TypeValue}, + {L"-t", TypeValue}, + {L"-s", TypeValue}, + {L"-w", TypeValue}, + {NULL , TypeMax} + }; + +/// +/// The default block size (512) of tftp is defined in the RFC1350. +/// +#define MTFTP_DEFAULT_BLKSIZE 512 +/// +/// The valid range of block size option is defined in the RFC2348. +/// +#define MTFTP_MIN_BLKSIZE 8 +#define MTFTP_MAX_BLKSIZE 65464 +/// +/// The default windowsize (1) of tftp. +/// +#define MTFTP_DEFAULT_WINDOWSIZE 1 +/// +/// The valid range of window size option. +/// Note that: RFC 7440 does not mention max window size value, but for the +/// stability reason, the value is limited to 64. +/// +#define MTFTP_MIN_WINDOWSIZE 1 +#define MTFTP_MAX_WINDOWSIZE 64 + +/** + Function for 'tftp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @return SHELL_SUCCESS The 'tftp' command completed successfully. + @return SHELL_ABORTED The Shell Library initialization failed. + @return SHELL_INVALID_PARAMETER At least one of the command's arguments is + not valid. + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. + @return SHELL_NOT_FOUND Network Interface Card not found or server + error or file error. + +**/ +SHELL_STATUS +RunTftp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + LIST_ENTRY *CheckPackage; + CHAR16 *ProblemParam; + UINTN ParamCount; + CONST CHAR16 *UserNicName; + BOOLEAN NicFound; + CONST CHAR16 *ValueStr; + CONST CHAR16 *RemoteFilePath; + CHAR8 *AsciiRemoteFilePath; + UINTN FilePathSize; + CONST CHAR16 *Walker; + EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData; + EFI_HANDLE *Handles; + UINTN HandleCount; + UINTN NicNumber; + CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH]; + EFI_HANDLE ControllerHandle; + EFI_HANDLE Mtftp4ChildHandle; + EFI_MTFTP4_PROTOCOL *Mtftp4; + UINTN FileSize; + UINT16 BlockSize; + UINT16 WindowSize; + + ShellStatus = SHELL_INVALID_PARAMETER; + ProblemParam = NULL; + NicFound = FALSE; + AsciiRemoteFilePath = NULL; + Handles = NULL; + FileSize = 0; + BlockSize = MTFTP_DEFAULT_BLKSIZE; + WindowSize = MTFTP_DEFAULT_WINDOWSIZE; + + // + // Initialize the Shell library (we must be in non-auto-init...) + // + Status = ShellInitialize (); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return SHELL_ABORTED; + } + + // + // Parse the command line. + // + Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE); + if (EFI_ERROR (Status)) { + if ((Status == EFI_VOLUME_CORRUPTED) && + (ProblemParam != NULL) ) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mTftpHiiHandle, + L"tftp", ProblemParam + ); + FreePool (ProblemParam); + } else { + ASSERT (FALSE); + } + goto Error; + } + + // + // Check the number of parameters + // + ParamCount = ShellCommandLineGetCount (CheckPackage); + if (ParamCount > 4) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), + mTftpHiiHandle, L"tftp" + ); + goto Error; + } + if (ParamCount < 3) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), + mTftpHiiHandle, L"tftp" + ); + goto Error; + } + + CopyMem (&Mtftp4ConfigData, &DefaultMtftp4ConfigData, sizeof (EFI_MTFTP4_CONFIG_DATA)); + + // + // Check the host IPv4 address + // + ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1); + Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, L"tftp", ValueStr + ); + goto Error; + } + + RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2); + ASSERT(RemoteFilePath != NULL); + FilePathSize = StrLen (RemoteFilePath) + 1; + AsciiRemoteFilePath = AllocatePool (FilePathSize); + if (AsciiRemoteFilePath == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Error; + } + UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize); + + if (ParamCount == 4) { + mLocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3); + } else { + Walker = RemoteFilePath + StrLen (RemoteFilePath); + while ((--Walker) >= RemoteFilePath) { + if ((*Walker == L'\\') || + (*Walker == L'/' ) ) { + break; + } + } + mLocalFilePath = Walker + 1; + } + + // + // Get the name of the Network Interface Card to be used if any. + // + UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i"); + + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l"); + if (ValueStr != NULL) { + if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) { + goto Error; + } + } + + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r"); + if (ValueStr != NULL) { + if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) { + goto Error; + } + } + + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c"); + if (ValueStr != NULL) { + if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) { + goto Error; + } + + if (Mtftp4ConfigData.TryCount == 0) { + Mtftp4ConfigData.TryCount = 6; + } + } + + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t"); + if (ValueStr != NULL) { + if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) { + goto Error; + } + if (Mtftp4ConfigData.TimeoutValue == 0) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, L"tftp", ValueStr + ); + goto Error; + } + } + + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s"); + if (ValueStr != NULL) { + if (!StringToUint16 (ValueStr, &BlockSize)) { + goto Error; + } + if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, L"tftp", ValueStr + ); + goto Error; + } + } + + ValueStr = ShellCommandLineGetValue (CheckPackage, L"-w"); + if (ValueStr != NULL) { + if (!StringToUint16 (ValueStr, &WindowSize)) { + goto Error; + } + if (WindowSize < MTFTP_MIN_WINDOWSIZE || WindowSize > MTFTP_MAX_WINDOWSIZE) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, L"tftp", ValueStr + ); + goto Error; + } + } + + // + // Locate all MTFTP4 Service Binding protocols + // + ShellStatus = SHELL_NOT_FOUND; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiManagedNetworkServiceBindingProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status) || (HandleCount == 0)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC), + mTftpHiiHandle + ); + goto Error; + } + + for (NicNumber = 0; + (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS); + NicNumber++) { + ControllerHandle = Handles[NicNumber]; + + Status = GetNicName (ControllerHandle, NicNumber, NicName); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME), + mTftpHiiHandle, NicNumber, Status + ); + continue; + } + + if (UserNicName != NULL) { + if (StrCmp (NicName, UserNicName) != 0) { + continue; + } + NicFound = TRUE; + } + + Status = CreateServiceChildAndOpenProtocol ( + ControllerHandle, + &gEfiMtftp4ServiceBindingProtocolGuid, + &gEfiMtftp4ProtocolGuid, + &Mtftp4ChildHandle, + (VOID**)&Mtftp4 + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL), + mTftpHiiHandle, NicName, Status + ); + continue; + } + + Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE), + mTftpHiiHandle, NicName, Status + ); + goto NextHandle; + } + + Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE), + mTftpHiiHandle, RemoteFilePath, NicName, Status + ); + goto NextHandle; + } + + Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD), + mTftpHiiHandle, RemoteFilePath, NicName, Status + ); + goto NextHandle; + } + + ShellStatus = SHELL_SUCCESS; + + NextHandle: + + CloseProtocolAndDestroyServiceChild ( + ControllerHandle, + &gEfiMtftp4ServiceBindingProtocolGuid, + &gEfiMtftp4ProtocolGuid, + Mtftp4ChildHandle + ); + } + + if ((UserNicName != NULL) && (!NicFound)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND), + mTftpHiiHandle, UserNicName + ); + } + + Error: + + ShellCommandLineFreeVarList (CheckPackage); + if (AsciiRemoteFilePath != NULL) { + FreePool (AsciiRemoteFilePath); + } + if (Handles != NULL) { + FreePool (Handles); + } + + if ((ShellStatus != SHELL_SUCCESS) && (EFI_ERROR(Status))) { + ShellStatus = Status & ~MAX_BIT; + } + + return ShellStatus; +} + +/** + Check and convert the UINT16 option values of the 'tftp' command + + @param[in] ValueStr Value as an Unicode encoded string + @param[out] Value UINT16 value + + @return TRUE The value was returned. + @return FALSE A parsing error occured. +**/ +STATIC +BOOLEAN +StringToUint16 ( + IN CONST CHAR16 *ValueStr, + OUT UINT16 *Value + ) +{ + UINTN Val; + + Val = ShellStrToUintn (ValueStr); + if (Val > MAX_UINT16) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), + mTftpHiiHandle, L"tftp", ValueStr + ); + return FALSE; + } + + *Value = (UINT16)Val; + return TRUE; +} + +/** + Get the name of the NIC. + + @param[in] ControllerHandle The network physical device handle. + @param[in] NicNumber The network physical device number. + @param[out] NicName Address where to store the NIC name. + The memory area has to be at least + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH + double byte wide. + + @return EFI_SUCCESS The name of the NIC was returned. + @return Others The creation of the child for the Managed + Network Service failed or the opening of + the Managed Network Protocol failed or + the operational parameters for the + Managed Network Protocol could not be + read. +**/ +STATIC +EFI_STATUS +GetNicName ( + IN EFI_HANDLE ControllerHandle, + IN UINTN NicNumber, + OUT CHAR16 *NicName + ) +{ + EFI_STATUS Status; + EFI_HANDLE MnpHandle; + EFI_MANAGED_NETWORK_PROTOCOL *Mnp; + EFI_SIMPLE_NETWORK_MODE SnpMode; + + Status = CreateServiceChildAndOpenProtocol ( + ControllerHandle, + &gEfiManagedNetworkServiceBindingProtocolGuid, + &gEfiManagedNetworkProtocolGuid, + &MnpHandle, + (VOID**)&Mnp + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = Mnp->GetModeData (Mnp, NULL, &SnpMode); + if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) { + goto Error; + } + + UnicodeSPrint ( + NicName, + IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH, + SnpMode.IfType == NET_IFTYPE_ETHERNET ? + L"eth%d" : + L"unk%d" , + NicNumber + ); + + Status = EFI_SUCCESS; + +Error: + + if (MnpHandle != NULL) { + CloseProtocolAndDestroyServiceChild ( + ControllerHandle, + &gEfiManagedNetworkServiceBindingProtocolGuid, + &gEfiManagedNetworkProtocolGuid, + MnpHandle + ); + } + + return Status; +} + +/** + Create a child for the service identified by its service binding protocol GUID + and get from the child the interface of the protocol identified by its GUID. + + @param[in] ControllerHandle Controller handle. + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the + service to be created. + @param[in] ProtocolGuid GUID of the protocol to be open. + @param[out] ChildHandle Address where the handler of the + created child is returned. NULL is + returned in case of error. + @param[out] Interface Address where a pointer to the + protocol interface is returned in + case of success. + + @return EFI_SUCCESS The child was created and the protocol opened. + @return Others Either the creation of the child or the opening + of the protocol failed. +**/ +STATIC +EFI_STATUS +CreateServiceChildAndOpenProtocol ( + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *ServiceBindingProtocolGuid, + IN EFI_GUID *ProtocolGuid, + OUT EFI_HANDLE *ChildHandle, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + + *ChildHandle = NULL; + Status = NetLibCreateServiceChild ( + ControllerHandle, + gImageHandle, + ServiceBindingProtocolGuid, + ChildHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + *ChildHandle, + ProtocolGuid, + Interface, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + NetLibDestroyServiceChild ( + ControllerHandle, + gImageHandle, + ServiceBindingProtocolGuid, + *ChildHandle + ); + *ChildHandle = NULL; + } + } + + return Status; +} + +/** + Close the protocol identified by its GUID on the child handle of the service + identified by its service binding protocol GUID, then destroy the child + handle. + + @param[in] ControllerHandle Controller handle. + @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the + service to be destroyed. + @param[in] ProtocolGuid GUID of the protocol to be closed. + @param[in] ChildHandle Handle of the child to be destroyed. + +**/ +STATIC +VOID +CloseProtocolAndDestroyServiceChild ( + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *ServiceBindingProtocolGuid, + IN EFI_GUID *ProtocolGuid, + IN EFI_HANDLE ChildHandle + ) +{ + gBS->CloseProtocol ( + ChildHandle, + ProtocolGuid, + gImageHandle, + ControllerHandle + ); + + NetLibDestroyServiceChild ( + ControllerHandle, + gImageHandle, + ServiceBindingProtocolGuid, + ChildHandle + ); +} + +/** + Worker function that gets the size in numbers of bytes of a file from a TFTP + server before to download the file. + + @param[in] Mtftp4 MTFTP4 protocol interface + @param[in] FilePath Path of the file, ASCII encoded + @param[out] FileSize Address where to store the file size in number of + bytes. + + @retval EFI_SUCCESS The size of the file was returned. + @retval EFI_UNSUPPORTED The server does not support the "tsize" option. + @retval Others Error when retrieving the information from the server + (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes) + or error when parsing the response of the server. +**/ +STATIC +EFI_STATUS +GetFileSize ( + IN EFI_MTFTP4_PROTOCOL *Mtftp4, + IN CONST CHAR8 *FilePath, + OUT UINTN *FileSize + ) +{ + EFI_STATUS Status; + EFI_MTFTP4_OPTION ReqOpt[1]; + EFI_MTFTP4_PACKET *Packet; + UINT32 PktLen; + EFI_MTFTP4_OPTION *TableOfOptions; + EFI_MTFTP4_OPTION *Option; + UINT32 OptCnt; + UINT8 OptBuf[128]; + + ReqOpt[0].OptionStr = (UINT8*)"tsize"; + OptBuf[0] = '0'; + OptBuf[1] = 0; + ReqOpt[0].ValueStr = OptBuf; + + Status = Mtftp4->GetInfo ( + Mtftp4, + NULL, + (UINT8*)FilePath, + NULL, + 1, + ReqOpt, + &PktLen, + &Packet + ); + + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = Mtftp4->ParseOptions ( + Mtftp4, + PktLen, + Packet, + (UINT32 *) &OptCnt, + &TableOfOptions + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Option = TableOfOptions; + while (OptCnt != 0) { + if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) { + *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr); + break; + } + OptCnt--; + Option++; + } + FreePool (TableOfOptions); + + if (OptCnt == 0) { + Status = EFI_UNSUPPORTED; + } + +Error : + + return Status; +} + +/** + Worker function that download the data of a file from a TFTP server given + the path of the file and its size. + + @param[in] Mtftp4 MTFTP4 protocol interface + @param[in] FilePath Path of the file, Unicode encoded + @param[in] AsciiFilePath Path of the file, ASCII encoded + @param[in] FileSize Size of the file in number of bytes + @param[in] BlockSize Value of the TFTP blksize option + @param[in] WindowSize Value of the TFTP window size option + + @retval EFI_SUCCESS The file was downloaded. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval Others The downloading of the file from the server failed + (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes). + +**/ +STATIC +EFI_STATUS +DownloadFile ( + IN EFI_MTFTP4_PROTOCOL *Mtftp4, + IN CONST CHAR16 *FilePath, + IN CONST CHAR8 *AsciiFilePath, + IN UINTN FileSize, + IN UINT16 BlockSize, + IN UINT16 WindowSize + ) +{ + EFI_STATUS Status; + DOWNLOAD_CONTEXT *TftpContext; + EFI_MTFTP4_TOKEN Mtftp4Token; + UINT8 BlksizeBuf[10]; + UINT8 WindowsizeBuf[10]; + + ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN)); + + TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT)); + if (TftpContext == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + TftpContext->FileSize = FileSize; + TftpContext->DownloadedNbOfBytes = 0; + TftpContext->LastReportedNbOfBytes = 0; + + Mtftp4Token.Filename = (UINT8*)AsciiFilePath; + Mtftp4Token.CheckPacket = CheckPacket; + Mtftp4Token.Context = (VOID*)TftpContext; + Mtftp4Token.OptionCount = 0; + Mtftp4Token.OptionList = AllocatePool (sizeof (EFI_MTFTP4_OPTION) * 2); + if (Mtftp4Token.OptionList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + if (BlockSize != MTFTP_DEFAULT_BLKSIZE) { + Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "blksize"; + AsciiSPrint ((CHAR8 *) BlksizeBuf, sizeof (BlksizeBuf), "%d", BlockSize); + Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = BlksizeBuf; + Mtftp4Token.OptionCount ++; + } + + if (WindowSize != MTFTP_DEFAULT_WINDOWSIZE) { + Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "windowsize"; + AsciiSPrint ((CHAR8 *) WindowsizeBuf, sizeof (WindowsizeBuf), "%d", WindowSize); + Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = WindowsizeBuf; + Mtftp4Token.OptionCount ++; + } + + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING), + mTftpHiiHandle, FilePath + ); + + // + // OPEN FILE + // + if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) { + ShellDeleteFileByName (mLocalFilePath); + } + + Status = ShellOpenFileByName ( + mLocalFilePath, + &mFileHandle, + EFI_FILE_MODE_CREATE | + EFI_FILE_MODE_WRITE | + EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), + mTftpHiiHandle, L"tftp", mLocalFilePath + ); + goto Error; + } + + Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token); + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), + mTftpHiiHandle + ); + + // + // CLOSE FILE + // + ShellCloseFile (&mFileHandle); + +Error : + if (TftpContext != NULL) { + FreePool (TftpContext); + } + + if (Mtftp4Token.OptionList != NULL) { + FreePool (Mtftp4Token.OptionList); + } + + return Status; +} + +/** + Update the progress of a file download + This procedure is called each time a new TFTP packet is received. + + @param[in] This MTFTP4 protocol interface + @param[in] Token Parameters for the download of the file + @param[in] PacketLen Length of the packet + @param[in] Packet Address of the packet + + @retval EFI_SUCCESS All packets are accepted. + +**/ +STATIC +EFI_STATUS +EFIAPI +CheckPacket ( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN UINT16 PacketLen, + IN EFI_MTFTP4_PACKET *Packet + ) +{ + DOWNLOAD_CONTEXT *Context; + CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE]; + UINTN NbOfKb; + UINTN Index; + UINTN LastStep; + UINTN Step; + UINTN DownloadLen; + EFI_STATUS Status; + + if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) { + return EFI_SUCCESS; + } + + Context = (DOWNLOAD_CONTEXT*)Token->Context; + + // + // The data in the packet are prepended with two UINT16 : + // . OpCode = EFI_MTFTP4_OPCODE_DATA + // . Block = the number of this block of data + // + DownloadLen = (UINTN)PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block); + + ShellSetFilePosition(mFileHandle, Context->DownloadedNbOfBytes); + Status = ShellWriteFile (mFileHandle, &DownloadLen, Packet->Data.Data); + if (EFI_ERROR (Status)) { + if (Context->DownloadedNbOfBytes > 0) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), + mTftpHiiHandle + ); + } + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE), + mTftpHiiHandle, mLocalFilePath, Status + ); + return Status; + } + + if (Context->DownloadedNbOfBytes == 0) { + ShellPrintEx (-1, -1, L"%s 0 Kb", mTftpProgressFrame); + } + + Context->DownloadedNbOfBytes += DownloadLen; + NbOfKb = Context->DownloadedNbOfBytes / 1024; + + Progress[0] = L'\0'; + LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize; + Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize; + + if (Step <= LastStep) { + return EFI_SUCCESS; + } + + ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete); + + Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame); + if (EFI_ERROR(Status)) { + return Status; + } + for (Index = 1; Index < Step; Index++) { + Progress[Index] = L'='; + } + Progress[Step] = L'>'; + + UnicodeSPrint ( + Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1, + sizeof (Progress) - sizeof (mTftpProgressFrame), + L" %7d Kb", + NbOfKb + ); + Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes; + + ShellPrintEx (-1, -1, L"%s", Progress); + + return EFI_SUCCESS; +} + +/** + Retrive HII package list from ImageHandle and publish to HII database. + + @param ImageHandle The image handle of the process. + + @return HII handle. +**/ +EFI_HANDLE +InitializeHiiPackage ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + EFI_HANDLE HiiHandle; + + // + // Retrieve HII package list from ImageHandle + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiHiiPackageListProtocolGuid, + (VOID **)&PackageList, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Publish HII package list to HII Database. + // + Status = gHiiDatabase->NewPackageList ( + gHiiDatabase, + PackageList, + NULL, + &HiiHandle + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return NULL; + } + return HiiHandle; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.h new file mode 100644 index 0000000..700b99f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.h @@ -0,0 +1,75 @@ +/** @file + Header file for 'tftp' command functions. + + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        + Copyright (c) 2015, ARM Ltd. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _TFTP_H_ +#define _TFTP_H_ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE mTftpHiiHandle; + +typedef struct { + UINTN FileSize; + UINTN DownloadedNbOfBytes; + UINTN LastReportedNbOfBytes; +} DOWNLOAD_CONTEXT; + +/** + Function for 'tftp' command. + + @param[in] ImageHandle The image handle. + @param[in] SystemTable The system table. + + @retval SHELL_SUCCESS Command completed successfully. + @retval SHELL_INVALID_PARAMETER Command usage error. + @retval SHELL_ABORTED The user aborts the operation. + @retval value Unknown error. +**/ +SHELL_STATUS +RunTftp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Retrive HII package list from ImageHandle and publish to HII database. + + @param ImageHandle The image handle of the process. + + @return HII handle. +**/ +EFI_HANDLE +InitializeHiiPackage ( + EFI_HANDLE ImageHandle + ); +#endif // _TFTP_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.uni new file mode 100644 index 0000000..a7c5883 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/Tftp.uni @@ -0,0 +1,100 @@ +// /** +// +// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// Tftp.uni +// +// Abstract: +// +// String definitions for UEFI Shell TFTP command +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_CRLF #language en-US "\r\n" + +#string STR_TFTP_ERR_NO_NIC #language en-US "No network interface card found.\r\n" +#string STR_TFTP_ERR_NIC_NAME #language en-US "Failed to get the name of the network interface card number %d - %r\r\n" +#string STR_TFTP_ERR_OPEN_PROTOCOL #language en-US "Unable to open MTFTP4 protocol on '%H%s%N' - %r\r\n" +#string STR_TFTP_ERR_CONFIGURE #language en-US "Unable to configure MTFTP4 protocol on '%H%s%N' - %r\r\n" +#string STR_TFTP_ERR_FILE_SIZE #language en-US "Unable to get the size of the file '%H%s%N' on '%H%s%N' - %r\r\n" +#string STR_TFTP_ERR_DOWNLOAD #language en-US "Unable to download the file '%H%s%N' on '%H%s%N' - %r\r\n" +#string STR_TFTP_ERR_WRITE #language en-US "Unable to write into file '%H%s%N' - %r\r\n" +#string STR_TFTP_ERR_NIC_NOT_FOUND #language en-US "Network Interface Card '%H%s%N' not found.\r\n" +#string STR_TFTP_DOWNLOADING #language en-US "Downloading the file '%H%s%N'\r\n" +#string STR_TFTP_STRING #language en-US "%s" + +#string STR_GET_HELP_TFTP #language en-US "" +".TH tftp 0 "Download a file from TFTP server."\r\n" +".SH NAME\r\n" +"Download a file from TFTP server.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TFTP [-i interface] [-l ] [-r ] [-c ] [-t ]\r\n" +" [-s ] [-w ] host remotefilepath [localfilepath]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -i interface - Specifies an adapter name, i.e., eth0.\r\n" +" -l port - Specifies the local port number. Default value is 0\r\n" +" and the port number is automatically assigned.\r\n" +" -r port - Specifies the remote port number. Default value is 69.\r\n" +" -c - The number of times to transmit request packets and\r\n" +" wait for a response. The default value is 6. Set to zero\r\n" +" also means to use the default value.\r\n" +" -t - The number of seconds to wait for a response after\r\n" +" sending a request packet. Default value is 4s.\r\n" +" -s - Specifies the TFTP blksize option as defined in RFC 2348.\r\n" +" Valid range is between 8 and 65464, default value is 512.\r\n" +" -w - Specifies the TFTP windowsize option as defined in RFC 7440.\r\n" +" Valid range is between 1 and 64, default value is 1.\r\n" +" host - Specify TFTP Server IPv4 address.\r\n" +" remotefilepath - TFTP server file path to download the file.\r\n" +" localfilepath - Local destination file path.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The TFTP command allows to get the file specified by its 'remotefilepath'\r\n" +" path from the TFTP server specified by its 'host' IPv4 address. If the\r\n" +" optional 'localfilepath' parameter is provided, the downloaded file is\r\n" +" stored locally using the provided file path. If the local file path is\r\n" +" not specified, the file is stored in the current directory using the file\r\n" +" server's name.\r\n" +" 2. Before using the TFTP command, the network interface intended to be\r\n" +" used to retrieve the file must be configured. This configuration may be\r\n" +" done by means of the 'ifconfig' command.\r\n" +" 3. If a network interface is defined with the '-i' option then only this\r\n" +" interface will be used to retrieve the remote file. Otherwise, all network\r\n" +" interfaces are tried in the order they have been discovered during the\r\n" +" DXE phase.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To get the file "dir1/file1.dat" from the TFTP server 192.168.1.1 and\r\n" +" store it as file2.dat in the current directory :\r\n" +" fs0:\> tftp 192.168.1.1 dir1/file1.dat file2.dat\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.c new file mode 100644 index 0000000..32c854c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.c @@ -0,0 +1,54 @@ +/** @file + Entrypoint of "tftp" shell standalone application. + + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        + Copyright (c) 2015, ARM Ltd. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "Tftp.h" + +// +// String token ID of help message text. +// Shell supports to find help message in the resource section of an application image if +// .MAN file is not found. This global variable is added to make build tool recognizes +// that the help string is consumed by user and then build tool will add the string into +// the resource section. Thus the application can use '-?' option to show help message in +// Shell. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_GET_HELP_TFTP); + +/** + Entry point of Tftp standalone application. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Tftp command is executed sucessfully. + @retval EFI_ABORTED HII package was failed to initialize. + @retval others Other errors when executing tftp command. +**/ +EFI_STATUS +EFIAPI +TftpAppInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + mTftpHiiHandle = InitializeHiiPackage (ImageHandle); + if (mTftpHiiHandle == NULL) { + return EFI_ABORTED; + } + + Status = (EFI_STATUS)RunTftp (ImageHandle, SystemTable); + HiiRemovePackages (mTftpHiiHandle); + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf new file mode 100644 index 0000000..c768b77 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf @@ -0,0 +1,59 @@ +## @file +# Provides Shell 'tftp' standalone application. +# +# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        +# Copyright (c) 2015, ARM Ltd. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = tftp + FILE_GUID = 8DC58D0D-67F5-4B97-9DFC-E442BB9A5648 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = TftpAppInitialize +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +[Sources.common] + Tftp.uni + Tftp.h + Tftp.c + TftpApp.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiApplicationEntryPoint + UefiHiiServicesLib + HiiLib + FileHandleLib + NetLib + +[Protocols] + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES + gEfiMtftp4ServiceBindingProtocolGuid ## CONSUMES + gEfiMtftp4ProtocolGuid ## CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.c new file mode 100644 index 0000000..8b96901 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.c @@ -0,0 +1,132 @@ +/** @file + Produce "tftp" shell dynamic command. + + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        + Copyright (c) 2015, ARM Ltd. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "Tftp.h" +#include + +/** + This is the shell command handler function pointer callback type. This + function handles the command when it is invoked in the shell. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the context + of processing this command. + + @return EFI_SUCCESS the operation was sucessful + @return other the operation failed. +**/ +SHELL_STATUS +EFIAPI +TftpCommandHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ) +{ + gEfiShellParametersProtocol = ShellParameters; + gEfiShellProtocol = Shell; + return RunTftp (gImageHandle, SystemTable); +} + +/** + This is the command help handler function pointer callback type. This + function is responsible for displaying help information for the associated + command. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return string Pool allocated help string, must be freed by caller +**/ +CHAR16 * +EFIAPI +TftpCommandGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ) +{ + return HiiGetString (mTftpHiiHandle, STRING_TOKEN (STR_GET_HELP_TFTP), Language); +} + +EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mTftpDynamicCommand = { + L"tftp", + TftpCommandHandler, + TftpCommandGetHelp +}; + +/** + Entry point of Tftp Dynamic Command. + + Produce the DynamicCommand protocol to handle "tftp" command. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Tftp command is executed sucessfully. + @retval EFI_ABORTED HII package was failed to initialize. + @retval others Other errors when executing tftp command. +**/ +EFI_STATUS +EFIAPI +TftpCommandInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + mTftpHiiHandle = InitializeHiiPackage (ImageHandle); + if (mTftpHiiHandle == NULL) { + return EFI_ABORTED; + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + EFI_NATIVE_INTERFACE, + &mTftpDynamicCommand + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + Tftp driver unload handler. + + @param ImageHandle The image handle of the process. + + @retval EFI_SUCCESS The image is unloaded. + @retval Others Failed to unload the image. +**/ +EFI_STATUS +EFIAPI +TftpUnload ( + IN EFI_HANDLE ImageHandle +) +{ + EFI_STATUS Status; + Status = gBS->UninstallProtocolInterface ( + ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + &mTftpDynamicCommand + ); + if (EFI_ERROR (Status)) { + return Status; + } + HiiRemovePackages (mTftpHiiHandle); + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf new file mode 100644 index 0000000..594a056 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf @@ -0,0 +1,64 @@ +## @file +# Provides Shell 'tftp' dynamic command. +# +# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        +# Copyright (c) 2015, ARM Ltd. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = tftpDynamicCommand + FILE_GUID = A487A478-51EF-48AA-8794-7BEE2A0562F1 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = TftpCommandInitialize + UNLOAD_IMAGE = TftpUnload +# +# This flag specifies whether HII resource section is generated into PE image. +# + UEFI_HII_RESOURCE_SECTION = TRUE + +[Sources.common] + Tftp.uni + Tftp.h + Tftp.c + TftpDynamicCommand.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiHiiServicesLib + HiiLib + FileHandleLib + NetLib + +[Protocols] + gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES + gEfiMtftp4ServiceBindingProtocolGuid ## CONSUMES + gEfiMtftp4ProtocolGuid ## CONSUMES + gEfiHiiPackageListProtocolGuid ## CONSUMES + gEfiShellDynamicCommandProtocolGuid ## PRODUCES + +[DEPEX] + TRUE diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellAliasGuid.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellAliasGuid.h new file mode 100644 index 0000000..08d2e6f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellAliasGuid.h @@ -0,0 +1,25 @@ +/** @file + GUID for Shell Variable for Get/Set via runtime services. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_ALIAS_VARIABLE_GUID_H_ +#define _SHELL_ALIAS_VARIABLE_GUID_H_ + +#define SHELL_ALIAS_VARIABLE_GUID \ +{ \ + 0x0053d9d6, 0x2659, 0x4599, { 0xa2, 0x6b, 0xef, 0x45, 0x36, 0xe6, 0x31, 0xa9 } \ +} + +extern EFI_GUID gShellAliasGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellEnvironment2Ext.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellEnvironment2Ext.h new file mode 100644 index 0000000..a05dd68 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellEnvironment2Ext.h @@ -0,0 +1,25 @@ +/** @file + GUID for EFI shell Environment2 Extension. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELLPKG_SHELL_ENV2_EXT_GUID_H_ +#define _SHELLPKG_SHELL_ENV2_EXT_GUID_H_ + +#define SHELLPKG_SHELL_ENV2_EXT_GUID \ +{ \ + 0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87} \ +} + +extern EFI_GUID gEfiShellEnvironment2ExtGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellLibHiiGuid.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellLibHiiGuid.h new file mode 100644 index 0000000..49cac4e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellLibHiiGuid.h @@ -0,0 +1,86 @@ +/** @file + GUIDs for HII package list installed by Shell libraries. + + Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELLLIB_HII_GUID_H_ +#define _SHELLLIB_HII_GUID_H_ + +#define HANDLE_PARSING_HII_GUID \ + { \ + 0xb8969637, 0x81de, 0x43af, { 0xbc, 0x9a, 0x24, 0xd9, 0x89, 0x13, 0xf2, 0xf6 } \ + } + +#define SHELL_DEBUG1_HII_GUID \ + { \ + 0x25f200aa, 0xd3cb, 0x470a, { 0xbf, 0x51, 0xe7, 0xd1, 0x62, 0xd2, 0x2e, 0x6f } \ + } + +#define SHELL_DRIVER1_HII_GUID \ + { \ + 0xaf0b742, 0x63ec, 0x45bd, {0x8d, 0xb6, 0x71, 0xad, 0x7f, 0x2f, 0xe8, 0xe8} \ + } + +#define SHELL_INSTALL1_HII_GUID \ + { \ + 0x7d574d54, 0xd364, 0x4d4a, { 0x95, 0xe3, 0x49, 0x45, 0xdb, 0x7a, 0xd3, 0xee } \ + } + +#define SHELL_LEVEL1_HII_GUID \ + { \ + 0xdec5daa4, 0x6781, 0x4820, { 0x9c, 0x63, 0xa7, 0xb0, 0xe4, 0xf1, 0xdb, 0x31 } \ + } + +#define SHELL_LEVEL2_HII_GUID \ + { \ + 0xf95a7ccc, 0x4c55, 0x4426, { 0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae } \ + } + +#define SHELL_LEVEL3_HII_GUID \ + { \ + 0x4344558d, 0x4ef9, 0x4725, { 0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f } \ + } + +#define SHELL_NETWORK1_HII_GUID \ + { \ + 0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \ + } + +#define SHELL_NETWORK2_HII_GUID \ + { \ + 0x174b2b5, 0xf505, 0x4b12, { 0xaa, 0x60, 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37 } \ + } + +#define SHELL_TFTP_HII_GUID \ + { \ + 0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4 } \ + } + + +#define SHELL_BCFG_HII_GUID \ + { \ + 0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6 } \ + } + +extern EFI_GUID gHandleParsingHiiGuid; +extern EFI_GUID gShellDebug1HiiGuid; +extern EFI_GUID gShellDriver1HiiGuid; +extern EFI_GUID gShellInstall1HiiGuid; +extern EFI_GUID gShellLevel1HiiGuid; +extern EFI_GUID gShellLevel2HiiGuid; +extern EFI_GUID gShellLevel3HiiGuid; +extern EFI_GUID gShellNetwork1HiiGuid; +extern EFI_GUID gShellNetwork2HiiGuid; +extern EFI_GUID gShellTftpHiiGuid; +extern EFI_GUID gShellBcfgHiiGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellMapGuid.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellMapGuid.h new file mode 100644 index 0000000..b599cca --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellMapGuid.h @@ -0,0 +1,25 @@ +/** @file + GUID for Shell Map for Get/Set via runtime services. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_MAP_GUID_H_ +#define _SHELL_MAP_GUID_H_ + +#define SHELL_MAP_GUID \ +{ \ + 0x51271e13, 0x7de3, 0x43af, { 0x8b, 0xc2, 0x71, 0xad, 0x3b, 0x82, 0x43, 0x25 } \ +} + +extern EFI_GUID gShellMapGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellPkgTokenSpace.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellPkgTokenSpace.h new file mode 100644 index 0000000..55bb04b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellPkgTokenSpace.h @@ -0,0 +1,25 @@ +/** @file + GUID for ShellPkg PCD Token Space. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELLPKG_TOKEN_SPACE_GUID_H_ +#define _SHELLPKG_TOKEN_SPACE_GUID_H_ + +#define EFI_SHELLPKG_TOKEN_SPACE_GUID \ +{ \ + 0x171e9188, 0x31d3, 0x40f5, { 0xb1, 0xc, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd } \ +} + +extern EFI_GUID gEfiShellPkgTokenSpaceGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellVariableGuid.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellVariableGuid.h new file mode 100644 index 0000000..e70fdf9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Guid/ShellVariableGuid.h @@ -0,0 +1,25 @@ +/** @file + GUID for Shell Variable for Get/Set via runtime services. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_VARIABLE_GUID_H_ +#define _SHELL_VARIABLE_GUID_H_ + +#define SHELL_VARIABLE_GUID \ +{ \ + 0x158def5a, 0xf656, 0x419c, { 0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2 } \ +} + +extern EFI_GUID gShellVariableGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/BcfgCommandLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/BcfgCommandLib.h new file mode 100644 index 0000000..2792d43 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/BcfgCommandLib.h @@ -0,0 +1,52 @@ +/** @file + Header file for BCFG command library. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BCFG_COMMAND_LIB_H_ +#define _BCFG_COMMAND_LIB_H_ + +/** + "Constructor" for the library. + + This will register the handler for the bcfg command. + + @param[in] ImageHandle the image handle of the process + @param[in] SystemTable the EFI System Table pointer + @param[in] Name the profile name to use + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +BcfgLibraryRegisterBcfgCommand ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN CONST CHAR16 *Name + ); + +/** + "Destructor" for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +BcfgLibraryUnregisterBcfgCommand ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/HandleParsingLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/HandleParsingLib.h new file mode 100644 index 0000000..403a2f7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/HandleParsingLib.h @@ -0,0 +1,410 @@ +/** @file + Provides interface to advanced shell functionality for parsing both handle and protocol database. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __HANDLE_PARSING_LIB__ +#define __HANDLE_PARSING_LIB__ + +#include + +/** + Function to add a new GUID/Name mapping. + + This cannot overwrite an existing mapping. + + @param[in] Guid The Guid + @param[in] TheName The Guid's name + @param[in] Lang RFC4646 language code list or NULL + + @retval EFI_SUCCESS The operation was sucessful + @retval EFI_ACCESS_DENIED There was a duplicate + @retval EFI_OUT_OF_RESOURCES A memory allocation failed +**/ +EFI_STATUS +EFIAPI +AddNewGuidNameMapping( + IN CONST EFI_GUID *Guid, + IN CONST CHAR16 *TheName, + IN CONST CHAR8 *Lang OPTIONAL + ); + +/** + Function to get the name of a protocol or struct from it's GUID. + + If Guid is NULL, then ASSERT. + + @param[in] Guid The GUID to look for the name of. + @param[in] Lang The language to use. + + @return The pointer to a string of the name. The caller + is responsible to free this memory. +**/ +CHAR16* +EFIAPI +GetStringNameFromGuid( + IN CONST EFI_GUID *Guid, + IN CONST CHAR8 *Lang OPTIONAL + ); + +/** + Function to get the Guid for a protocol or struct based on it's string name. + + Do not free or modify the returned GUID. + + @param[in] Name The pointer to the string name. + @param[in] Lang The pointer to the language code (string). + @param[out] Guid The pointer to the pointer to the Guid. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +GetGuidFromStringName( + IN CONST CHAR16 *Name, + IN CONST CHAR8 *Lang OPTIONAL, + OUT EFI_GUID **Guid + ); + +/** + Function to dump protocol information from a handle. + + This function will return a allocated string buffer containing the + information. The caller is responsible for freeing the memory. + + If Guid is NULL, ASSERT(). + If TheHandle is NULL, ASSERT(). + + @param[in] TheHandle The handle to dump information from. + @param[in] Guid The GUID of the protocol to dump. + @param[in] Verbose TRUE for extra info. FALSE otherwise. + + @return The pointer to string. + @retval NULL An error was encountered. +**/ +CHAR16* +EFIAPI +GetProtocolInformationDump( + IN CONST EFI_HANDLE TheHandle, + IN CONST EFI_GUID *Guid, + IN CONST BOOLEAN Verbose + ); + +/** + Function to retrieve the driver name (if possible) from the ComponentName or + ComponentName2 protocol. + + The string returned must be callee freed. + + @param[in] TheHandle The driver handle to get the name of. + @param[in] Language The language to use. + + @retval NULL The name could not be found. + @return A pointer to the string name. Do not de-allocate the memory. +**/ +CONST CHAR16* +EFIAPI +GetStringNameFromHandle( + IN CONST EFI_HANDLE TheHandle, + IN CONST CHAR8 *Language + ); + +/** + Get best support language for this driver. + + First base on the user input language to search, second base on the current + platform used language to search, third get the first language from the + support language list. The caller need to free the buffer of the best language. + + @param[in] SupportedLanguages The support languages for this driver. + @param[in] InputLanguage The user input language. + @param[in] Iso639Language Whether get language for ISO639. + + @return The best support language for this driver. +**/ +CHAR8 * +EFIAPI +GetBestLanguageForDriver ( + IN CONST CHAR8 *SupportedLanguages, + IN CONST CHAR8 *InputLanguage, + IN BOOLEAN Iso639Language + ); + +#define HR_UNKNOWN 0 +#define HR_IMAGE_HANDLE BIT1 +#define HR_DRIVER_BINDING_HANDLE BIT2 // has driver binding +#define HR_DEVICE_DRIVER BIT3 // device driver (hybrid?) +#define HR_BUS_DRIVER BIT4 // a bus driver (hybrid?) +#define HR_DRIVER_CONFIGURATION_HANDLE BIT5 +#define HR_DRIVER_DIAGNOSTICS_HANDLE BIT6 +#define HR_COMPONENT_NAME_HANDLE BIT7 +#define HR_DEVICE_HANDLE BIT8 +#define HR_PARENT_HANDLE BIT9 +#define HR_CONTROLLER_HANDLE BIT10 +#define HR_CHILD_HANDLE BIT11 +#define HR_VALID_MASK (BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7|BIT8|BIT9|BIT10|BIT11) + +/** + Gets all the related EFI_HANDLEs based on the mask supplied. + + This function will scan all EFI_HANDLES in the UEFI environment's handle database + and return all the ones with the specified relationship (Mask) to the specified + controller handle. + + If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT. + If MatchingHandleCount is NULL, then ASSERT. + + If MatchingHandleBuffer is not NULL upon a successful return, the memory must be + caller freed. + + @param[in] DriverBindingHandle The handle with Driver Binding protocol on it. + @param[in] ControllerHandle The handle with Device Path protocol on it. + @param[in] Mask The mask of what relationship(s) is desired. + @param[in] MatchingHandleCount The pointer to UINTN specifying number of HANDLES in + MatchingHandleBuffer. + @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount + EFI_HANDLEs with a terminating NULL EFI_HANDLE. + + @retval EFI_SUCCESS The operation was successful, and any related handles + are in MatchingHandleBuffer. + @retval EFI_NOT_FOUND No matching handles were found. + @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range. + @sa ParseHandleDatabaseByRelationshipWithType +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseByRelationship ( + IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL, + IN CONST EFI_HANDLE ControllerHandle OPTIONAL, + IN CONST UINTN Mask, + IN UINTN *MatchingHandleCount, + OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL + ); + +/** + Gets all the related EFI_HANDLEs based on the mask supplied. + + This function scans all EFI_HANDLES in the UEFI environment's handle database + and returns the ones with the specified relationship (Mask) to the specified + controller handle. + + If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT. + If MatchingHandleCount is NULL, then ASSERT. + + If MatchingHandleBuffer is not NULL upon a successful return the memory must be + caller freed. + + @param[in] DriverBindingHandle The handle with Driver Binding protocol on it. + @param[in] ControllerHandle The handle with Device Path protocol on it. + @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in + MatchingHandleBuffer. + @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount + EFI_HANDLEs with a terminating NULL EFI_HANDLE. + @param[out] HandleType An array of type information. + + @retval EFI_SUCCESS The operation was successful, and any related handles + are in MatchingHandleBuffer. + @retval EFI_NOT_FOUND No matching handles were found. + @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range. +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseByRelationshipWithType ( + IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL, + IN CONST EFI_HANDLE ControllerHandle OPTIONAL, + IN UINTN *HandleCount, + OUT EFI_HANDLE **HandleBuffer, + OUT UINTN **HandleType + ); + +/** + Gets handles for any parents of the passed in controller. + + @param[in] ControllerHandle The handle of the controller. + @param[in] Count The pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] Buffer The buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was successful. + @sa ParseHandleDatabaseByRelationship +**/ +#define PARSE_HANDLE_DATABASE_PARENTS(ControllerHandle, Count, Buffer) \ + ParseHandleDatabaseByRelationship(NULL, ControllerHandle, HR_PARENT_HANDLE, Count, Buffer) + +/** + Gets handles for any UEFI drivers of the passed in controller. + + @param[in] ControllerHandle The handle of the controller. + @param[in] Count The pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] Buffer The buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was successful. + @sa ParseHandleDatabaseByRelationship +**/ +#define PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ControllerHandle, Count, Buffer) \ + ParseHandleDatabaseByRelationship(NULL, ControllerHandle, HR_DRIVER_BINDING_HANDLE|HR_DEVICE_DRIVER, Count, Buffer) + +/** + Gets handles for any children of the passed in controller by the passed in driver handle. + + @param[in] DriverHandle The handle of the driver. + @param[in] ControllerHandle The handle of the controller. + @param[in] Count The pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] Buffer The buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was successful. + @sa ParseHandleDatabaseByRelationship +**/ +#define PARSE_HANDLE_DATABASE_MANAGED_CHILDREN(DriverHandle, ControllerHandle, Count, Buffer) \ + ParseHandleDatabaseByRelationship(DriverHandle, ControllerHandle, HR_CHILD_HANDLE|HR_DEVICE_HANDLE, Count, Buffer) + +/** + Gets handles for any devices managed by the passed in driver. + + @param[in] DriverHandle The handle of the driver. + @param[in] Count The pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] Buffer The buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was successful. + @sa ParseHandleDatabaseByRelationship +**/ +#define PARSE_HANDLE_DATABASE_DEVICES(DriverHandle, Count, Buffer) \ + ParseHandleDatabaseByRelationship(DriverHandle, NULL, HR_CONTROLLER_HANDLE|HR_DEVICE_HANDLE, Count, Buffer) + +/** + Gets handles for any child devices produced by the passed in driver. + + @param[in] DriverHandle The handle of the driver. + @param[in] MatchingHandleCount The pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] MatchingHandleBuffer The buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was successful. + @sa ParseHandleDatabaseByRelationship +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseForChildDevices( + IN CONST EFI_HANDLE DriverHandle, + IN UINTN *MatchingHandleCount, + OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL + ); + +/** + Gets handles for any child controllers of the passed in controller. + + @param[in] ControllerHandle The handle of the "parent controller". + @param[out] MatchingHandleCount The pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] MatchingHandleBuffer The buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was successful. + @sa ParseHandleDatabaseByRelationship +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseForChildControllers( + IN CONST EFI_HANDLE ControllerHandle, + OUT UINTN *MatchingHandleCount, + OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL + ); + + +/** + Function to retrieve the human-friendly index of a given handle. If the handle + does not have a index one will be automatically assigned. The index value is valid + until the termination of the shell application. + + @param[in] TheHandle The handle to retrieve an index for. + + @retval 0 A memory allocation failed. + @return The index of the handle. + +**/ +UINTN +EFIAPI +ConvertHandleToHandleIndex( + IN CONST EFI_HANDLE TheHandle + ); + +/** + Function to retrieve the EFI_HANDLE from the human-friendly index. + + @param[in] TheIndex The index to retrieve the EFI_HANDLE for. + + @retval NULL The index was invalid. + @return The EFI_HANDLE that index represents. + +**/ +EFI_HANDLE +EFIAPI +ConvertHandleIndexToHandle( + IN CONST UINTN TheIndex + ); + +/** + Function to get all handles that support a given protocol or all handles. + + The caller is responsible to free this memory. + + @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL + then the function will return all handles. + + @retval NULL A memory allocation failed. + @return A NULL terminated list of handles. +**/ +EFI_HANDLE* +EFIAPI +GetHandleListByProtocol ( + IN CONST EFI_GUID *ProtocolGuid OPTIONAL + ); + +/** + Function to get all handles that support some protocols. + + The caller is responsible to free this memory. + + @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs. + + @retval NULL A memory allocation failed. + @retval NULL ProtocolGuids was NULL. + @return A NULL terminated list of EFI_HANDLEs. +**/ +EFI_HANDLE* +EFIAPI +GetHandleListByProtocolList ( + IN CONST EFI_GUID **ProtocolGuids + ); + + +/** + Return all supported GUIDs. + + @param[out] Guids The buffer to return all supported GUIDs. + @param[in, out] Count On input, the count of GUIDs the buffer can hold, + On output, the count of GUIDs to return. + + @retval EFI_INVALID_PARAMETER Count is NULL. + @retval EFI_BUFFER_TOO_SMALL Buffer is not enough to hold all GUIDs. + @retval EFI_SUCCESS GUIDs are returned successfully. +**/ +EFI_STATUS +EFIAPI +GetAllMappingGuids ( + OUT EFI_GUID *Guids, + IN OUT UINTN *Count + ); + +#endif // __HANDLE_PARSING_LIB__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCEntryLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCEntryLib.h new file mode 100644 index 0000000..08e127b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCEntryLib.h @@ -0,0 +1,40 @@ +/** @file + Provides application point extension for "C" style main function. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_C_ENTRY_LIB_ +#define _SHELL_C_ENTRY_LIB_ + +/** + UEFI application entry point which has an interface similar to a + standard C main function. + + The ShellCEntryLib library instance wrappers the actual UEFI application + entry point and calls this ShellAppMain function. + + @param[in] Argc The number of parameters. + @param[in] Argv The array of pointers to parameters. + + @retval 0 The application exited normally. + @retval Other An error occurred. + +**/ +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCommandLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCommandLib.h new file mode 100644 index 0000000..d0def0b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellCommandLib.h @@ -0,0 +1,723 @@ +/** @file + Provides interface to shell internal functions for shell commands. + + This library is for use ONLY by shell commands linked into the shell application. + This library will not function if it is used for UEFI Shell 2.0 Applications. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELL_COMMAND_LIB_ +#define _SHELL_COMMAND_LIB_ + +#include + +#include +#include +#include +#include + +#include + +// +// The extern global protocol poionters. +// +extern EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation; +extern CONST CHAR16* SupportLevel[]; + +// +// The map list objects. +// +typedef struct { + LIST_ENTRY Link; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 *MapName; + CHAR16 *CurrentDirectoryPath; + UINT64 Flags; +} SHELL_MAP_LIST; +/// List of Mappings - DeviceName and Drive Letter(ism). +extern SHELL_MAP_LIST gShellMapList; +/// Pointer to node of current directory in the mMapList. +extern SHELL_MAP_LIST *gShellCurMapping; + +/** + Returns the help MAN fileName for a given shell command. + + @retval !NULL The unicode string of the MAN filename. + @retval NULL An error ocurred. + +**/ +typedef +CONST CHAR16 * +(EFIAPI *SHELL_GET_MAN_FILENAME)( + VOID + ); + +/** + Runs a shell command on a given command line. + + The specific operation of a given shell command is specified in the UEFI Shell + Specification 2.0, or in the source of the given command. + + Upon completion of the command run the shell protocol and environment variables + may have been updated due to the operation. + + @param[in] ImageHandle The ImageHandle to the app, or NULL if + the command built into shell. + @param[in] SystemTable The pointer to the system table. + + @retval RETURN_SUCCESS The shell command was sucessful. + @retval RETURN_UNSUPPORTED The command is not supported. +**/ +typedef +SHELL_STATUS +(EFIAPI *SHELL_RUN_COMMAND)( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Registers the handlers of type SHELL_RUN_COMMAND and + SHELL_GET_MAN_FILENAME for each shell command. + + If the ShellSupportLevel is greater than the value of + PcdShellSupportLevel, then return RETURN_UNSUPPORTED. + + Registers the the handlers specified by GetHelpInfoHandler and CommandHandler + with the command specified by CommandString. If the command named by + CommandString 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 CommandString is NULL, then ASSERT(). + If GetHelpInfoHandler is NULL, then ASSERT(). + If CommandHandler is NULL, then ASSERT(). + If ProfileName is NULL, then ASSERT(). + + @param[in] CommandString The pointer to the command name. This is the + name to look for on the command line in + the shell. + @param[in] CommandHandler The pointer to a function that runs the + specified command. + @param[in] GetManFileName The pointer to a function that provides man + filename. + @param[in] ShellMinSupportLevel The minimum Shell Support Level which has this + function. + @param[in] ProfileName The profile name to require for support of this + function. + @param[in] CanAffectLE Indicates whether this command's return value + can change the LASTERROR environment variable. + @param[in] HiiHandle The handle of this command's HII entry. + @param[in] ManFormatHelp The HII locator for the help text. + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + register the shell command. + @retval RETURN_UNSUPPORTED The ShellMinSupportLevel was higher than the + currently allowed support level. + @retval RETURN_ALREADY_STARTED The CommandString represents a command that + is already registered. Only one handler set for + a given command is allowed. + @sa SHELL_GET_MAN_FILENAME + @sa SHELL_RUN_COMMAND +**/ +RETURN_STATUS +EFIAPI +ShellCommandRegisterCommandName ( + IN CONST CHAR16 *CommandString, + IN SHELL_RUN_COMMAND CommandHandler, + IN SHELL_GET_MAN_FILENAME GetManFileName, + IN UINT32 ShellMinSupportLevel, + IN CONST CHAR16 *ProfileName, + IN CONST BOOLEAN CanAffectLE, + IN CONST EFI_HANDLE HiiHandle, + IN CONST EFI_STRING_ID ManFormatHelp + ); + +/** + Checks if a command string has been registered for CommandString, and if so, it runs + the previously registered handler for that command with the command line. + + If CommandString is NULL, then ASSERT(). + + If Sections is specified, then each section name listed will be compared in a case sensitive + manner to the section names described in Appendix B UEFI Shell 2.0 Specification. If the section exists, + it is appended to the returned help text. If the section does not exist, no + information is returned. If Sections is NULL, then all help text information + available is returned. + + @param[in] CommandString The pointer to the command name. This is the name + found on the command line in the shell. + @param[in, out] RetVal The pointer to the return value from the command handler. + + @param[in, out] CanAffectLE Indicates whether this command's return value + needs to be placed into LASTERROR environment variable. + + @retval RETURN_SUCCESS The handler was run. + @retval RETURN_NOT_FOUND The CommandString did not match a registered + command name. + @sa SHELL_RUN_COMMAND +**/ +RETURN_STATUS +EFIAPI +ShellCommandRunCommandHandler ( + IN CONST CHAR16 *CommandString, + IN OUT SHELL_STATUS *RetVal, + IN OUT BOOLEAN *CanAffectLE OPTIONAL + ); + +/** + Checks if a command string has been registered for CommandString, and if so, it + returns the MAN filename specified for that command. + + If CommandString is NULL, then ASSERT(). + + @param[in] CommandString The pointer to the command name. This is the name + found on the command line in the shell. + + @retval NULL The CommandString was not a registered command. + @retval other The name of the MAN file. + @sa SHELL_GET_MAN_FILENAME +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameHandler ( + IN CONST CHAR16 *CommandString + ); + + +typedef struct { + LIST_ENTRY Link; + CHAR16 *CommandString; +} COMMAND_LIST; + +/** + Get the list of all available shell internal commands. This is a linked list, + via the LIST_ENTRY structure. Enumerate through it using the BaseLib linked + list functions. Do not modify the values. + + @param[in] Sort TRUE to alphabetically sort the values first. FALSE otherwise. + + @return A linked list of all available shell commands. +**/ +CONST COMMAND_LIST* +EFIAPI +ShellCommandGetCommandList ( + IN CONST BOOLEAN Sort + ); + +typedef struct { + LIST_ENTRY Link; + CHAR16 *CommandString; + CHAR16 *Alias; +} ALIAS_LIST; + +/** + Registers aliases to be set as part of the initialization of the shell application. + + If Command is NULL, then ASSERT(). + If Alias is NULL, then ASSERT(). + + @param[in] Command The pointer to the Command. + @param[in] Alias The pointer to Alias. + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + register the shell command. +**/ +RETURN_STATUS +EFIAPI +ShellCommandRegisterAlias ( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias + ); + +/** + Get the list of all shell alias commands. This is a linked list, + via LIST_ENTRY structure. Enumerate through it using the BaseLib linked + list functions. Do not modify the values. + + @return A linked list of all requested shell aliases. +**/ +CONST ALIAS_LIST* +EFIAPI +ShellCommandGetInitAliasList ( + VOID + ); + +/** + Determine if a given alias is on the list of built in aliases. + + @param[in] Alias The alias to test for. + + @retval TRUE The alias is a built in alias. + @retval FALSE The alias is not a built in alias. +**/ +BOOLEAN +EFIAPI +ShellCommandIsOnAliasList ( + IN CONST CHAR16 *Alias + ); + +/** + Checks if a command is already on the list. + + @param[in] CommandString The command string to check for on the list. + + @retval TRUE CommandString represents a registered command. + @retval FALSE CommandString does not represent a registered command. +**/ +BOOLEAN +EFIAPI +ShellCommandIsCommandOnList ( + IN CONST CHAR16 *CommandString + ); + +/** + Get the help text for a command. + + @param[in] CommandString The command name. + + @retval NULL No help text was found. + @return The string of the help text. The caller required to free. +**/ +CHAR16* +EFIAPI +ShellCommandGetCommandHelp ( + IN CONST CHAR16 *CommandString + ); + +/** + Function to make sure that the above pointers are valid. +**/ +EFI_STATUS +EFIAPI +CommandInit ( + VOID + ); + +/** + Function to determine current state of ECHO. Echo determines if lines from scripts + and ECHO commands are enabled. + + @retval TRUE Echo is currently enabled. + @retval FALSE Echo is currently disabled. +**/ +BOOLEAN +EFIAPI +ShellCommandGetEchoState ( + VOID + ); + +/** + Function to set current state of ECHO. Echo determines if lines from scripts + and ECHO commands are enabled. + + @param[in] State TRUE to enable Echo, FALSE otherwise. +**/ +VOID +EFIAPI +ShellCommandSetEchoState ( + IN BOOLEAN State + ); + + + +/** + Indicate that the current shell or script should exit. + + @param[in] ScriptOnly TRUE if exiting a script; FALSE otherwise. + @param[in] ErrorCode The 64 bit error code to return. +**/ +VOID +EFIAPI +ShellCommandRegisterExit ( + IN BOOLEAN ScriptOnly, + IN CONST UINT64 ErrorCode + ); + +/** + Retrieve the Exit code. + + @return the value passed into RegisterExit. +**/ +UINT64 +EFIAPI +ShellCommandGetExitCode ( + VOID + ); + +/** + Retrieve the Exit indicator. + + @retval TRUE Exit was indicated. + @retval FALSE Exit was not indicated. +**/ +BOOLEAN +EFIAPI +ShellCommandGetExit ( + VOID + ); + +/** + Retrieve the Exit script indicator. + + If ShellCommandGetExit returns FALSE, then the return from this is undefined. + + @retval TRUE ScriptOnly was indicated. + @retval FALSE ScriptOnly was not indicated. +**/ +BOOLEAN +EFIAPI +ShellCommandGetScriptExit ( + VOID + ); + +typedef struct { + LIST_ENTRY Link; ///< List enumerator items. + UINTN Line; ///< What line of the script file this was on. + CHAR16 *Cl; ///< The original command line. + VOID *Data; ///< The data structure format dependant upon Command. (not always used) + BOOLEAN Reset; ///< Reset the command (it must be treated like a initial run (but it may have data already)) +} SCRIPT_COMMAND_LIST; + +typedef struct { + CHAR16 *ScriptName; ///< The filename of this script. + CHAR16 **Argv; ///< The parmameters to the script file. + UINTN Argc; ///< The count of parameters. + LIST_ENTRY CommandList; ///< The script converted to a list of commands (SCRIPT_COMMAND_LIST objects). + SCRIPT_COMMAND_LIST *CurrentCommand; ///< The command currently being operated. If !=NULL must be a member of CommandList. + LIST_ENTRY SubstList; ///< A list of current script loop alias' (ALIAS_LIST objects) (Used for the for %-based replacement). +} SCRIPT_FILE; + +/** + Function to return a pointer to the currently running script file object. + + @retval NULL A script file is not currently running. + @return A pointer to the current script file object. +**/ +SCRIPT_FILE* +EFIAPI +ShellCommandGetCurrentScriptFile ( + VOID + ); + +/** + Function to set a new script as the currently running one. + + This function will correctly stack and unstack nested scripts. + + @param[in] Script The pointer to new script information structure. If NULL, + it removes and de-allocates the topmost Script structure. + + @return A pointer to the current running script file after this + change. It is NULL if removing the final script. +**/ +SCRIPT_FILE* +EFIAPI +ShellCommandSetNewScript ( + IN SCRIPT_FILE *Script OPTIONAL + ); + +/** + Function to cleanup all memory from a SCRIPT_FILE structure. + + @param[in] Script The pointer to the structure to cleanup. +**/ +VOID +EFIAPI +DeleteScriptFileStruct ( + IN SCRIPT_FILE *Script + ); + +/** + Function to get the current Profile string. + + This is used to retrieve what profiles were installed. + + @retval NULL There are no installed profiles. + @return A semicolon-delimited list of profiles. +**/ +CONST CHAR16 * +EFIAPI +ShellCommandGetProfileList ( + VOID + ); + +typedef enum { + MappingTypeFileSystem, + MappingTypeBlockIo, + MappingTypeMax +} SHELL_MAPPING_TYPE; + +/** + Function to generate the next default mapping name. + + If the return value is not NULL then it must be callee freed. + + @param Type What kind of mapping name to make. + + @retval NULL a memory allocation failed. + @return a new map name string +**/ +CHAR16* +EFIAPI +ShellCommandCreateNewMappingName( + IN CONST SHELL_MAPPING_TYPE Type + ); + +/** + Function to initialize the table for creating consistent map names. + + @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object. + + @retval EFI_SUCCESS The table was created successfully. +**/ +EFI_STATUS +EFIAPI +ShellCommandConsistMappingInitialize ( + EFI_DEVICE_PATH_PROTOCOL ***Table + ); + +/** + Function to uninitialize the table for creating consistent map names. + + The parameter must have been received from ShellCommandConsistMappingInitialize. + + @param[out] Table The pointer to pointer to DevicePathProtocol object. + + @retval EFI_SUCCESS The table was deleted successfully. +**/ +EFI_STATUS +EFIAPI +ShellCommandConsistMappingUnInitialize ( + EFI_DEVICE_PATH_PROTOCOL **Table + ); + +/** + Create a consistent mapped name for the device specified by DevicePath + based on the Table. + + This must be called after ShellCommandConsistMappingInitialize() and + before ShellCommandConsistMappingUnInitialize() is called. + + @param[in] DevicePath The pointer to the dev path for the device. + @param[in] Table The Table of mapping information. + + @retval NULL A consistent mapped name could not be created. + @return A pointer to a string allocated from pool with the device name. +**/ +CHAR16* +EFIAPI +ShellCommandConsistMappingGenMappingName ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_DEVICE_PATH_PROTOCOL **Table + ); + +/** + Function to search the list of mappings for the first matching node on the + list based on the MapKey. + + @param[in] MapKey The pointer to the string key to search for in the map. + + @return the node on the list. +**/ +SHELL_MAP_LIST* +EFIAPI +ShellCommandFindMapItem ( + IN CONST CHAR16 *MapKey + ); + +/** + Function to add a map node to the list of map items and update the "path" environment variable (optionally). + + If Path is TRUE (during initialization only), the path environment variable will also be updated to include + default paths on the new map name... + + Path should be FALSE when this function is called from the protocol SetMap function. + + @param[in] Name The human readable mapped name. + @param[in] DevicePath The Device Path for this map. + @param[in] Flags The Flags attribute for this map item. + @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization). + + @retval EFI_SUCCESS The addition was sucessful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +EFIAPI +ShellCommandAddMapItemAndUpdatePath( + IN CONST CHAR16 *Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST UINT64 Flags, + IN CONST BOOLEAN Path + ); + +/** + Creates the default map names for each device path in the system with + a protocol depending on the Type. + + Also sets up the default path environment variable if Type is FileSystem. + + @retval EFI_SUCCESS All map names were created sucessfully. + @retval EFI_NOT_FOUND No protocols were found in the system. + @return Error returned from gBS->LocateHandle(). + + @sa LocateHandle +**/ +EFI_STATUS +EFIAPI +ShellCommandCreateInitialMappingsAndPaths( + VOID + ); + +/** + Add mappings for any devices without one. Do not change any existing maps. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +ShellCommandUpdateMapping ( + VOID + ); + +/** + Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*. + + @param[in] Handle The SHELL_FILE_HANDLE to convert. + + @return a EFI_FILE_PROTOCOL* representing the same file. +**/ +EFI_FILE_PROTOCOL* +EFIAPI +ConvertShellHandleToEfiFileProtocol( + IN CONST SHELL_FILE_HANDLE Handle + ); + +/** + Remove a SHELL_FILE_HANDLE frmo the list of SHELL_FILE_HANDLES. + + @param[in] Handle The SHELL_FILE_HANDLE to remove. + + @retval TRUE The item was removed. + @retval FALSE The item was not found. +**/ +BOOLEAN +EFIAPI +ShellFileHandleRemove( + IN CONST SHELL_FILE_HANDLE Handle + ); + +/** + Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE. + + @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert. + @param[in] Path The path to the file for verification. + + @return a SHELL_FILE_HANDLE representing the same file. +**/ +SHELL_FILE_HANDLE +EFIAPI +ConvertEfiFileProtocolToShellHandle( + IN CONST EFI_FILE_PROTOCOL *Handle, + IN CONST CHAR16 *Path + ); + +/** + Find the path that was logged with the specified SHELL_FILE_HANDLE. + + @param[in] Handle The SHELL_FILE_HANDLE to query on. + + @return A pointer to the path for the file. +**/ +CONST CHAR16* +EFIAPI +ShellFileHandleGetPath( + IN CONST SHELL_FILE_HANDLE Handle + ); + + +/** + Function to determine if a SHELL_FILE_HANDLE is at the end of the file. + + This will NOT work on directories. + + If Handle is NULL, then ASSERT. + + @param[in] Handle the file handle + + @retval TRUE the position is at the end of the file + @retval FALSE the position is not at the end of the file +**/ +BOOLEAN +EFIAPI +ShellFileHandleEof( + IN SHELL_FILE_HANDLE Handle + ); + +typedef struct { + LIST_ENTRY Link; + void *Buffer; +} BUFFER_LIST; + +/** + Frees any BUFFER_LIST defined type. + + @param[in] List The pointer to the list head. +**/ +VOID +EFIAPI +FreeBufferList ( + IN BUFFER_LIST *List + ); + +/** + Function printing hex output to the console. + + @param[in] Indent Number of spaces to indent. + @param[in] Offset Offset to start with. + @param[in] DataSize Length of data. + @param[in] UserData Pointer to some data. +**/ +VOID +EFIAPI +DumpHex ( + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID *UserData + ); + +/** + Dump HEX data into buffer. + + @param[in] Buffer HEX data to be dumped in Buffer. + @param[in] Indent How many spaces to indent the output. + @param[in] Offset The offset of the printing. + @param[in] DataSize The size in bytes of UserData. + @param[in] UserData The data to print out. +**/ +CHAR16* +EFIAPI +CatSDumpHex ( + IN CHAR16 *Buffer, + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID *UserData + ); +#endif //_SHELL_COMMAND_LIB_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellLib.h new file mode 100644 index 0000000..ef2e40d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Library/ShellLib.h @@ -0,0 +1,1438 @@ +/** @file + Provides interface to shell functionality for shell commands and applications. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        + Copyright 2018 Dell Technologies.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SHELL_LIB__ +#define __SHELL_LIB__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHELL_FREE_NON_NULL(Pointer) \ + do { \ + if ((Pointer) != NULL) { \ + FreePool((Pointer)); \ + (Pointer) = NULL; \ + } \ + } while(FALSE) + +extern EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol; +extern EFI_SHELL_PROTOCOL *gEfiShellProtocol; + +/** + Return a clean, fully-qualified version of an input path. If the return value + is non-NULL the caller must free the memory when it is no longer needed. + + If asserts are disabled, and if the input parameter is NULL, NULL is returned. + + If there is not enough memory available to create the fully-qualified path or + a copy of the input path, NULL is returned. + + If there is no working directory, a clean copy of Path is returned. + + Otherwise, the current file system or working directory (as appropriate) is + prepended to Path and the resulting path is cleaned and returned. + + NOTE: If the input path is an empty string, then the current working directory + (if it exists) is returned. In other words, an empty input path is treated + exactly the same as ".". + + @param[in] Path A pointer to some file or directory path. + + @retval NULL The input path is NULL or out of memory. + + @retval non-NULL A pointer to a clean, fully-qualified version of Path. + If there is no working directory, then a pointer to a + clean, but not necessarily fully-qualified version of + Path. The caller must free this memory when it is no + longer needed. +**/ +CHAR16* +EFIAPI +FullyQualifyPath( + IN CONST CHAR16 *Path + ); + +/** + 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[in] 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 +ShellGetFileInfo ( + IN SHELL_FILE_HANDLE FileHandle + ); + +/** + This function sets the information about the file for the opened handle + specified. + + @param[in] FileHandle The file handle of the file for which information + is being set. + + @param[in] FileInfo The information to set. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid. + @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellSetFileInfo ( + IN SHELL_FILE_HANDLE FileHandle, + IN EFI_FILE_INFO *FileInfo + ); + +/** + This function will open a file or directory referenced by DevicePath. + + This function opens a file with the open mode according to the file path. The + Attributes is valid only for EFI_FILE_MODE_CREATE. + + @param[in, out] FilePath On input, the device path to the file. On output, + the remaining device path. + @param[out] FileHandle Pointer to the file handle. + @param[in] OpenMode The mode to open the file with. + @param[in] Attributes The file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found on + the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellOpenFileByDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +/** + This function will open a file or directory referenced by filename. + + If return is EFI_SUCCESS, the Filehandle is the opened file's handle; + otherwise, the Filehandle is NULL. Attributes is valid only for + EFI_FILE_MODE_CREATE. + + @param[in] FileName The pointer to file name. + @param[out] FileHandle The pointer to the file handle. + @param[in] OpenMode The mode to open the file with. + @param[in] Attributes The file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellOpenFileByName( + IN CONST CHAR16 *FileName, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +/** + This function creates a directory. + + If return is EFI_SUCCESS, the Filehandle is the opened directory's handle; + otherwise, the Filehandle is NULL. If the directory already existed, this + function opens the existing directory. + + @param[in] DirectoryName The pointer to Directory name. + @param[out] FileHandle The pointer to the file handle. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device, or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellCreateDirectory( + IN CONST CHAR16 *DirectoryName, + OUT SHELL_FILE_HANDLE *FileHandle + ); + +/** + This function reads information from an opened file. + + If FileHandle is not a directory, the function reads the requested number of + bytes from the file at the file's current position and returns them in Buffer. + If the read goes beyond the end of the file, the read length is truncated to the + end of the file. The file's current position is increased by the number of bytes + returned. If FileHandle is a directory, the function reads the directory entry + at the file's current position and returns the entry in Buffer. If the Buffer + is not large enough to hold the current directory entry, then + EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated. + BufferSize is set to be the size of the buffer needed to read the entry. On + success, the current position is updated to the next directory entry. If there + are no more directory entries, the read returns a zero-length buffer. + EFI_FILE_INFO is the structure returned as the directory entry. + + @param[in] FileHandle The opened file handle. + @param[in, out] ReadSize On input the size of buffer in bytes. On return + the number of bytes written. + @param[out] Buffer The buffer to put read data into. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required + size. + +**/ +EFI_STATUS +EFIAPI +ShellReadFile( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ); + +/** + Write data to a file. + + This function writes the specified number of bytes to the file at the current + file position. The current file position is advanced the actual number of bytes + written, which is returned in BufferSize. Partial writes only occur when there + has been a data error during the write attempt (such as "volume space full"). + The file is automatically grown to hold the data if required. Direct writes to + opened directories are not supported. + + @param[in] FileHandle The opened file for writing. + + @param[in, out] BufferSize On input the number of bytes in Buffer. On output + the number of bytes written. + + @param[in] Buffer The buffer containing data to write is stored. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to an open directory are not supported. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The device is write-protected. + @retval EFI_ACCESS_DENIED The file was open for read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellWriteFile( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Close an open file handle. + + This function closes a specified file handle. All "dirty" cached file data is + flushed to the device, and the file is closed. In all cases the handle is + closed. + + @param[in] FileHandle The file handle to close. + + @retval EFI_SUCCESS The file handle was closed sucessfully. + @retval INVALID_PARAMETER One of the parameters has an invalid value. +**/ +EFI_STATUS +EFIAPI +ShellCloseFile ( + IN SHELL_FILE_HANDLE *FileHandle + ); + +/** + Delete a file and close the handle + + This function closes and deletes a file. In all cases the file handle is closed. + If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is + returned, but the handle is still closed. + + @param[in] FileHandle The file handle to delete. + + @retval EFI_SUCCESS The file was closed sucessfully. + @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 +ShellDeleteFile ( + IN SHELL_FILE_HANDLE *FileHandle + ); + +/** + Set the current position in a file. + + This function sets the current file position for the handle to the position + supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only + absolute positioning is supported, and moving past the end of the file is + allowed (a subsequent write would grow the file). Moving to position + 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file. + If FileHandle is a directory, the only position that may be set is zero. This + has the effect of starting the read process of the directory entries over. + + @param[in] FileHandle The file handle on which the position is being set. + + @param[in] Position The byte position from the begining of the file. + + @retval EFI_SUCCESS Operation completed sucessfully. + @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 +ShellSetFilePosition ( + IN SHELL_FILE_HANDLE FileHandle, + IN UINT64 Position + ); + +/** + Gets a file's current position + + This function retrieves the current file position for the file handle. For + directories, the current file position has no meaning outside of the file + system driver and as such the operation is not supported. An error is returned + if FileHandle is a directory. + + @param[in] FileHandle The open file handle on which to get the position. + @param[out] Position The byte position from the begining of the file. + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED The request is not valid on directories. +**/ +EFI_STATUS +EFIAPI +ShellGetFilePosition ( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ); + +/** + Flushes data on a file + + This function flushes all modified data associated with a file to a device. + + @param[in] FileHandle The file handle on which to flush data. + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened for read only. +**/ +EFI_STATUS +EFIAPI +ShellFlushFile ( + IN SHELL_FILE_HANDLE FileHandle + ); + +/** 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 ShellFindNextFile() to get subsequent directory entries. + + The buffer will be freed by ShellFindNextFile() 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 the buffer for the 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 ShellGetFileInfo, ShellSetFilePosition, + or ShellReadFile. + + @sa ShellReadFile +**/ +EFI_STATUS +EFIAPI +ShellFindFirstFile ( + IN SHELL_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ); + +/** Retrieve next entries from a directory. + + To use this function, the caller must first call the ShellFindFirstFile() + function to get the first directory entry. Subsequent directory entries are + retrieved by using the ShellFindNextFile() function. This function can + be called several times to get each entry from the directory. If the call of + ShellFindNextFile() 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[in, out] Buffer The pointer to buffer for file's information. + @param[in, out] NoFile The pointer to boolean when last file is found. + + @retval EFI_SUCCESS Found the next 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. + + @sa ShellReadFile +**/ +EFI_STATUS +EFIAPI +ShellFindNextFile( + IN SHELL_FILE_HANDLE DirHandle, + IN OUT EFI_FILE_INFO *Buffer, + IN OUT BOOLEAN *NoFile + ); + +/** + 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 The operation was completed sucessfully. + @retval EFI_DEVICE_ERROR Cannot access the file. +**/ +EFI_STATUS +EFIAPI +ShellGetFileSize ( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ); + +/** + Retrieves the status of the break execution flag + + This function is useful to check whether the application is being asked to halt by the shell. + + @retval TRUE The execution break is enabled. + @retval FALSE The execution break is not enabled. +**/ +BOOLEAN +EFIAPI +ShellGetExecutionBreakFlag( + VOID + ); + +/** + Return the value of an environment variable. + + This function gets the value of the environment variable set by the + ShellSetEnvironmentVariable function. + + @param[in] EnvKey The key name of the environment variable. + + @retval NULL The named environment variable does not exist. + @return != NULL The pointer to the value of the environment variable. +**/ +CONST CHAR16* +EFIAPI +ShellGetEnvironmentVariable ( + IN CONST CHAR16 *EnvKey + ); + +/** + Set the value of an environment variable. + + This function changes the current value of the specified environment variable. If the + environment variable exists and the Value is an empty string, then the environment + variable is deleted. If the environment variable exists and the Value is not an empty + string, then the value of the environment variable is changed. If the environment + variable does not exist and the Value is an empty string, there is no action. If the + environment variable does not exist and the Value is a non-empty string, then the + environment variable is created and assigned the specified value. + + This is not supported pre-UEFI Shell 2.0. + + @param[in] EnvKey The key name of the environment variable. + @param[in] EnvVal The Value of the environment variable + @param[in] Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS The operation completed sucessfully + @retval EFI_UNSUPPORTED This operation is not allowed in pre-UEFI 2.0 Shell environments. +**/ +EFI_STATUS +EFIAPI +ShellSetEnvironmentVariable ( + IN CONST CHAR16 *EnvKey, + IN CONST CHAR16 *EnvVal, + IN BOOLEAN Volatile + ); + +/** + Cause the shell to parse and execute a command line. + + This function creates a nested instance of the shell and executes the specified + command (CommandLine) with the specified environment (Environment). Upon return, + the status code returned by the specified command is placed in StatusCode. + If Environment is NULL, then the current environment is used and all changes made + by the commands executed will be reflected in the current environment. If the + Environment is non-NULL, then the changes made will be discarded. + The CommandLine is executed from the current working directory on the current + device. + + The EnvironmentVariables and Status parameters are ignored in a pre-UEFI Shell 2.0 + environment. The values pointed to by the parameters will be unchanged by the + ShellExecute() function. The Output parameter has no effect in a + UEFI Shell 2.0 environment. + + @param[in] ParentHandle The parent image starting the operation. + @param[in] CommandLine The pointer to a NULL terminated command line. + @param[in] Output True to display debug output. False to hide it. + @param[in] EnvironmentVariables Optional pointer to array of environment variables + in the form "x=y". If NULL, the current set is used. + @param[out] Status The status of the run command line. + + @retval EFI_SUCCESS The operation completed sucessfully. Status + contains the status code returned. + @retval EFI_INVALID_PARAMETER A parameter contains an invalid value. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED The operation is not allowed. +**/ +EFI_STATUS +EFIAPI +ShellExecute ( + IN EFI_HANDLE *ParentHandle, + IN CHAR16 *CommandLine, + IN BOOLEAN Output, + IN CHAR16 **EnvironmentVariables, + OUT EFI_STATUS *Status + ); + +/** + Retreives the current directory path. + + If the DeviceName is NULL, it returns the current device's current directory + name. If the DeviceName is not NULL, it returns the current directory name + on specified drive. + + Note that the current directory string should exclude the tailing backslash character. + + @param[in] DeviceName The name of the file system to get directory on. + + @retval NULL The directory does not exist. + @retval != NULL The directory. +**/ +CONST CHAR16* +EFIAPI +ShellGetCurrentDir ( + IN CHAR16 * CONST DeviceName OPTIONAL + ); + +/** + Sets (enabled or disabled) the page break mode. + + When page break mode is enabled the screen will stop scrolling + and wait for operator input before scrolling a subsequent screen. + + @param[in] CurrentState TRUE to enable and FALSE to disable. +**/ +VOID +EFIAPI +ShellSetPageBreakMode ( + IN BOOLEAN CurrentState + ); + +/** + Opens a group of files based on a path. + + This function uses the Arg to open all the matching files. Each matched + file has a SHELL_FILE_ARG structure to record the file information. These + structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG + structures from ListHead to access each file. This function supports wildcards + and will process '?' and '*' as such. The list must be freed with a call to + ShellCloseFileMetaArg(). + + If you are NOT appending to an existing list *ListHead must be NULL. If + *ListHead is NULL then it must be callee freed. + + @param[in] Arg The pointer to path string. + @param[in] OpenMode Mode to open files with. + @param[in, out] ListHead Head of linked list of results. + + @retval EFI_SUCCESS The operation was sucessful and the list head + contains the list of opened files. + @retval != EFI_SUCCESS The operation failed. + + @sa InternalShellConvertFileListType +**/ +EFI_STATUS +EFIAPI +ShellOpenFileMetaArg ( + IN CHAR16 *Arg, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **ListHead + ); + +/** + Free the linked list returned from ShellOpenFileMetaArg. + + @param[in, out] ListHead The pointer to free. + + @retval EFI_SUCCESS The operation was sucessful. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +EFIAPI +ShellCloseFileMetaArg ( + IN OUT EFI_SHELL_FILE_INFO **ListHead + ); + +/** + Find a file by searching the CWD and then the path. + + If FileName is NULL, then ASSERT. + + If the return value is not NULL then the memory must be caller freed. + + @param[in] FileName Filename string. + + @retval NULL The file was not found. + @retval !NULL The path to the file. +**/ +CHAR16 * +EFIAPI +ShellFindFilePath ( + IN CONST CHAR16 *FileName + ); + +/** + Find a file by searching the CWD and then the path with a variable set of file + extensions. If the file is not found it will append each extension in the list + in the order provided and return the first one that is successful. + + If FileName is NULL, then ASSERT. + If FileExtension is NULL, then the behavior is identical to ShellFindFilePath. + + If the return value is not NULL then the memory must be caller freed. + + @param[in] FileName The filename string. + @param[in] FileExtension Semicolon delimited list of possible extensions. + + @retval NULL The file was not found. + @retval !NULL The path to the file. +**/ +CHAR16 * +EFIAPI +ShellFindFilePathEx ( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *FileExtension + ); + +typedef enum { + TypeFlag = 0, ///< A flag that is present or not present only (IE "-a"). + TypeValue, ///< A flag that has some data following it with a space (IE "-a 1"). + TypePosition, ///< Some data that did not follow a parameter (IE "filename.txt"). + TypeStart, ///< A flag that has variable value appended to the end (IE "-ad", "-afd", "-adf", etc...). + TypeDoubleValue, ///< A flag that has 2 space seperated value data following it (IE "-a 1 2"). + TypeMaxValue, ///< A flag followed by all the command line data before the next flag. + TypeTimeValue, ///< A flag that has a time value following it (IE "-a -5:00"). + TypeMax, +} SHELL_PARAM_TYPE; + +typedef struct { + CHAR16 *Name; + SHELL_PARAM_TYPE Type; +} SHELL_PARAM_ITEM; + + +/// Helper structure for no parameters (besides -? and -b) +extern SHELL_PARAM_ITEM EmptyParamList[]; + +/// Helper structure for -sfo only (besides -? and -b) +extern SHELL_PARAM_ITEM SfoParamList[]; + +/** + Checks the command line arguments passed against the list of valid ones. + Optionally removes NULL values first. + + If no initialization is required, then return RETURN_SUCCESS. + + @param[in] CheckList The pointer to list of parameters to check. + @param[out] CheckPackage The package of checked values. + @param[out] ProblemParam Optional pointer to pointer to unicode string for + the paramater that caused failure. + @param[in] AutoPageBreak Will automatically set PageBreakEnabled. + @param[in] AlwaysAllowNumbers Will never fail for number based flags. + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_VOLUME_CORRUPTED The command line was corrupt. + @retval EFI_DEVICE_ERROR The commands contained 2 opposing arguments. One + of the command line arguments was returned in + ProblemParam if provided. + @retval EFI_NOT_FOUND A argument required a value that was missing. + The invalid command line argument was returned in + ProblemParam if provided. +**/ +EFI_STATUS +EFIAPI +ShellCommandLineParseEx ( + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT LIST_ENTRY **CheckPackage, + OUT CHAR16 **ProblemParam OPTIONAL, + IN BOOLEAN AutoPageBreak, + IN BOOLEAN AlwaysAllowNumbers + ); + +/// Make it easy to upgrade from older versions of the shell library. +#define ShellCommandLineParse(CheckList,CheckPackage,ProblemParam,AutoPageBreak) ShellCommandLineParseEx(CheckList,CheckPackage,ProblemParam,AutoPageBreak,FALSE) + +/** + Frees shell variable list that was returned from ShellCommandLineParse. + + This function will free all the memory that was used for the CheckPackage + list of postprocessed shell arguments. + + If CheckPackage is NULL, then return. + + @param[in] CheckPackage The list to de-allocate. + **/ +VOID +EFIAPI +ShellCommandLineFreeVarList ( + IN LIST_ENTRY *CheckPackage + ); + +/** + Checks for presence of a flag parameter. + + Flag arguments are in the form of "-" or "/", but do not have a value following the key. + + If CheckPackage is NULL then return FALSE. + If KeyString is NULL then ASSERT(). + + @param[in] CheckPackage The package of parsed command line arguments. + @param[in] KeyString The Key of the command line argument to check for. + + @retval TRUE The flag is on the command line. + @retval FALSE The flag is not on the command line. +**/ +BOOLEAN +EFIAPI +ShellCommandLineGetFlag ( + IN CONST LIST_ENTRY * CONST CheckPackage, + IN CONST CHAR16 * CONST KeyString + ); + +/** + Returns value from command line argument. + + Value parameters are in the form of "- value" or "/ value". + + If CheckPackage is NULL, then return NULL. + + @param[in] CheckPackage The package of parsed command line arguments. + @param[in] KeyString The Key of the command line argument to check for. + + @retval NULL The flag is not on the command line. + @retval !=NULL The pointer to unicode string of the value. +**/ +CONST CHAR16* +EFIAPI +ShellCommandLineGetValue ( + IN CONST LIST_ENTRY *CheckPackage, + IN CHAR16 *KeyString + ); + +/** + Returns raw value from command line argument. + + Raw value parameters are in the form of "value" in a specific position in the list. + + If CheckPackage is NULL, then return NULL. + + @param[in] CheckPackage The package of parsed command line arguments. + @param[in] Position The position of the value. + + @retval NULL The flag is not on the command line. + @retval !=NULL The pointer to unicode string of the value. +**/ +CONST CHAR16* +EFIAPI +ShellCommandLineGetRawValue ( + IN CONST LIST_ENTRY * CONST CheckPackage, + IN UINTN Position + ); + +/** + Returns the number of command line value parameters that were parsed. + + This will not include flags. + + @param[in] CheckPackage The package of parsed command line arguments. + + @retval (UINTN)-1 No parsing has occurred. + @retval other The number of value parameters found. +**/ +UINTN +EFIAPI +ShellCommandLineGetCount( + IN CONST LIST_ENTRY *CheckPackage + ); + +/** + Determines if a parameter is duplicated. + + If Param is not NULL, then it will point to a callee-allocated string buffer + with the parameter value, if a duplicate is found. + + If CheckPackage is NULL, then ASSERT. + + @param[in] CheckPackage The package of parsed command line arguments. + @param[out] Param Upon finding one, a pointer to the duplicated parameter. + + @retval EFI_SUCCESS No parameters were duplicated. + @retval EFI_DEVICE_ERROR A duplicate was found. + **/ +EFI_STATUS +EFIAPI +ShellCommandLineCheckDuplicate ( + IN CONST LIST_ENTRY *CheckPackage, + OUT CHAR16 **Param + ); + +/** + This function causes the shell library to initialize itself. If the shell library + is already initialized it will de-initialize all the current protocol pointers and + re-populate them again. + + When the library is used with PcdShellLibAutoInitialize set to true this function + will return EFI_SUCCESS and perform no actions. + + This function is intended for internal access for shell commands only. + + @retval EFI_SUCCESS The initialization was complete sucessfully. + +**/ +EFI_STATUS +EFIAPI +ShellInitialize ( + VOID + ); + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string. + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + If either Row or Col is out of range for the current console, then ASSERT. + If Format is NULL, then ASSERT. + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col The column to print at. + @param[in] Row The row to print at. + @param[in] Format The format string. + @param[in] ... The variable argument list. + + @return EFI_SUCCESS The printing was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +ShellPrintEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + ... + ); + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string. + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + If either Row or Col is out of range for the current console, then ASSERT. + If Format is NULL, then ASSERT. + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal. + %H - Set output attribute to highlight. + %E - Set output attribute to error. + %B - Set output attribute to blue color. + %V - Set output attribute to green color. + + Note: The background color is controlled by the shell command cls. + + @param[in] Col The column to print at. + @param[in] Row The row to print at. + @param[in] Language The language of the string to retrieve. If this parameter + is NULL, then the current platform language is used. + @param[in] HiiFormatStringId The format string Id for getting from Hii. + @param[in] HiiFormatHandle The format string Handle for getting from Hii. + @param[in] ... The variable argument list. + + @return EFI_SUCCESS The printing was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +ShellPrintHiiEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR8 *Language OPTIONAL, + IN CONST EFI_STRING_ID HiiFormatStringId, + IN CONST EFI_HANDLE HiiFormatHandle, + ... + ); + +/** + Function to determine if a given filename represents a directory. + + If DirName is NULL, then ASSERT. + + @param[in] DirName Path to directory to test. + + @retval EFI_SUCCESS The Path represents a directory. + @retval EFI_NOT_FOUND The Path does not represent a directory. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellIsDirectory( + IN CONST CHAR16 *DirName + ); + +/** + Function to determine if a given filename represents a file. + + This will search the CWD only. + + If Name is NULL, then ASSERT. + + @param[in] Name Path to file to test. + + @retval EFI_SUCCESS The Path represents a file. + @retval EFI_NOT_FOUND The Path does not represent a file. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellIsFile( + IN CONST CHAR16 *Name + ); + +/** + Function to determine if a given filename represents a file. + + This will search the CWD and then the Path. + + If Name is NULL, then ASSERT. + + @param[in] Name Path to file to test. + + @retval EFI_SUCCESS The Path represents a file. + @retval EFI_NOT_FOUND The Path does not represent a file. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellIsFileInPath( + IN CONST CHAR16 *Name + ); + +/** + Function to determine whether a string is decimal or hex representation of a number + and return the number converted from the string. + + Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid + result. Use ShellConvertStringToUint64 instead. + + @param[in] String String representation of a number. + + @return The unsigned integer result of the conversion. + @retval (UINTN)(-1) An error occured. +**/ +UINTN +EFIAPI +ShellStrToUintn( + IN CONST CHAR16 *String + ); + +/** + Function return the number converted from a hex representation of a number. + + Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid + result. Use ShellConvertStringToUint64 instead. + + @param[in] String String representation of a number. + + @return The unsigned integer result of the conversion. + @retval (UINTN)(-1) An error occured. +**/ +UINTN +EFIAPI +ShellHexStrToUintn( + IN CONST CHAR16 *String + ); + +/** + Safely append 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, so return the current buffer in + Destination. + + If Destination is NULL, then ASSERT(). + If Destination's current length (including NULL terminator) is already more than + 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 The maximum number of characters to append. If 0, then + all are appended. + + @return The Destination after appending the Source. +**/ +CHAR16* +EFIAPI +StrnCatGrow ( + IN OUT CHAR16 **Destination, + IN OUT UINTN *CurrentSize, + IN CONST CHAR16 *Source, + IN UINTN Count + ); + +/** + This is a find and replace function. Upon successful return the NewString is a copy of + SourceString with each instance of FindTarget replaced with ReplaceWith. + + If SourceString and NewString overlap the behavior is undefined. + + If the string would grow bigger than NewSize it will halt and return error. + + @param[in] SourceString The string with source buffer. + @param[in, out] NewString The string with resultant buffer. + @param[in] NewSize The size in bytes of NewString. + @param[in] FindTarget The string to look for. + @param[in] ReplaceWith The string to replace FindTarget with. + @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^' + immediately before it. + @param[in] ParameterReplacing If TRUE will add "" around items with spaces. + + @retval EFI_INVALID_PARAMETER SourceString was NULL. + @retval EFI_INVALID_PARAMETER NewString was NULL. + @retval EFI_INVALID_PARAMETER FindTarget was NULL. + @retval EFI_INVALID_PARAMETER ReplaceWith was NULL. + @retval EFI_INVALID_PARAMETER FindTarget had length < 1. + @retval EFI_INVALID_PARAMETER SourceString had length < 1. + @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold + the new string (truncation occurred). + @retval EFI_SUCCESS The string was successfully copied with replacement. +**/ +EFI_STATUS +EFIAPI +ShellCopySearchAndReplace( + IN CHAR16 CONST *SourceString, + IN OUT CHAR16 *NewString, + IN UINTN NewSize, + IN CONST CHAR16 *FindTarget, + IN CONST CHAR16 *ReplaceWith, + IN CONST BOOLEAN SkipPreCarrot, + IN CONST BOOLEAN ParameterReplacing + ); + +/** + Check if a Unicode character is a hexadecimal character. + + This internal function checks if a Unicode character is a + numeric character. The valid hexadecimal characters are + 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 The Char is a hexadecmial character. + @retval FALSE The Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +ShellIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ); + +/** + Check if a Unicode character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid characters are + L'0' to L'9'. + + + @param Char The character to check against. + + @retval TRUE The Char is a hexadecmial character. + @retval FALSE The Char is not a hexadecmial character. + +**/ +BOOLEAN +EFIAPI +ShellIsDecimalDigitCharacter ( + IN CHAR16 Char + ); + +/// +/// What type of answer is requested. +/// +typedef enum { + ShellPromptResponseTypeYesNo, + ShellPromptResponseTypeYesNoCancel, + ShellPromptResponseTypeFreeform, + ShellPromptResponseTypeQuitContinue, + ShellPromptResponseTypeYesNoAllCancel, + ShellPromptResponseTypeEnterContinue, + ShellPromptResponseTypeAnyKeyContinue, + ShellPromptResponseTypeMax +} SHELL_PROMPT_REQUEST_TYPE; + +/// +/// What answer was given. +/// +typedef enum { + ShellPromptResponseYes, + ShellPromptResponseNo, + ShellPromptResponseCancel, + ShellPromptResponseQuit, + ShellPromptResponseContinue, + ShellPromptResponseAll, + ShellPromptResponseMax +} SHELL_PROMPT_RESPONSE; + +/** + Prompt the user and return the resultant answer to the requestor. + + This function will display the requested question on the shell prompt and then + wait for an appropriate answer to be input from the console. + + If the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue + or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE. + + If the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type + CHAR16*. + + In either case *Response must be callee freed if Response was not NULL; + + @param Type What type of question is asked. This is used to filter the input + to prevent invalid answers to question. + @param Prompt The pointer to a string prompt used to request input. + @param Response The pointer to Response, which will be populated upon return. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_UNSUPPORTED The operation is not supported as requested. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @return other The operation failed. +**/ +EFI_STATUS +EFIAPI +ShellPromptForResponse ( + IN SHELL_PROMPT_REQUEST_TYPE Type, + IN CHAR16 *Prompt OPTIONAL, + IN OUT VOID **Response OPTIONAL + ); + +/** + Prompt the user and return the resultant answer to the requestor. + + This function is the same as ShellPromptForResponse, except that the prompt is + automatically pulled from HII. + + @param[in] Type What type of question is asked. This is used to filter the input + to prevent invalid answers to question. + @param[in] HiiFormatStringId The format string Id for getting from Hii. + @param[in] HiiFormatHandle The format string Handle for getting from Hii. + @param[in, out] Response The pointer to Response, which will be populated upon return. + + @retval EFI_SUCCESS The operation was sucessful. + @return other The operation failed. + + @sa ShellPromptForResponse +**/ +EFI_STATUS +EFIAPI +ShellPromptForResponseHii ( + IN SHELL_PROMPT_REQUEST_TYPE Type, + IN CONST EFI_STRING_ID HiiFormatStringId, + IN CONST EFI_HANDLE HiiFormatHandle, + IN OUT VOID **Response + ); + +/** + Function to determin if an entire string is a valid number. + + If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE. + + @param[in] String The string to evaluate. + @param[in] ForceHex TRUE - always assume hex. + @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going. + + @retval TRUE It is all numeric (dec/hex) characters. + @retval FALSE There is a non-numeric character. +**/ +BOOLEAN +EFIAPI +ShellIsHexOrDecimalNumber ( + IN CONST CHAR16 *String, + IN CONST BOOLEAN ForceHex, + IN CONST BOOLEAN StopAtSpace + ); + +/** + Function to verify and convert a string to its numerical 64 bit representation. + + If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE. + + @param[in] String The string to evaluate. + @param[out] Value Upon a successful return the value of the conversion. + @param[in] ForceHex TRUE - always assume hex. + @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to + process the entire String. + + @retval EFI_SUCCESS The conversion was successful. + @retval EFI_INVALID_PARAMETER String contained an invalid character. + @retval EFI_NOT_FOUND String was a number, but Value was NULL. +**/ +EFI_STATUS +EFIAPI +ShellConvertStringToUint64( + IN CONST CHAR16 *String, + OUT UINT64 *Value, + IN CONST BOOLEAN ForceHex, + IN CONST BOOLEAN StopAtSpace + ); + +/** + Function to determine if a given filename exists. + + @param[in] Name Path to test. + + @retval EFI_SUCCESS The Path represents a file. + @retval EFI_NOT_FOUND The Path does not represent a file. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellFileExists( + IN CONST CHAR16 *Name + ); + +/** + Function to read a single line from a SHELL_FILE_HANDLE. 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 SHELL_FILE_HANDLE 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 ShellFileHandleReadLine +**/ +CHAR16* +EFIAPI +ShellFileHandleReturnLine( + IN SHELL_FILE_HANDLE Handle, + IN OUT BOOLEAN *Ascii + ); + +/** + Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE. + + 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 SHELL_FILE_HANDLE 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_END_OF_FILE There are no more lines in the file. + @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. +**/ +EFI_STATUS +EFIAPI +ShellFileHandleReadLine( + IN SHELL_FILE_HANDLE Handle, + IN OUT CHAR16 *Buffer, + IN OUT UINTN *Size, + IN BOOLEAN Truncate, + IN OUT BOOLEAN *Ascii + ); + +/** + Function to delete a file by name + + @param[in] FileName Pointer to file name to delete. + + @retval EFI_SUCCESS the file was deleted sucessfully + @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not + deleted + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval other The file failed to open +**/ +EFI_STATUS +EFIAPI +ShellDeleteFileByName( + IN CONST CHAR16 *FileName + ); + +/** + Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function. + + @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed. + @param[in] SectionToGetHelpOn Pointer to the section specifier(s). + @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints + the help content only. + @retval EFI_DEVICE_ERROR The help data format was incorrect. + @retval EFI_NOT_FOUND The help data could not be found. + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +ShellPrintHelp ( + IN CONST CHAR16 *CommandToGetHelpOn, + IN CONST CHAR16 *SectionToGetHelpOn, + IN BOOLEAN PrintCommandText + ); + +#endif // __SHELL_LIB__ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellEnvironment2.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellEnvironment2.h new file mode 100644 index 0000000..e54457c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellEnvironment2.h @@ -0,0 +1,975 @@ +/** @file + Defines for EFI shell environment 2 ported to EDK II build environment. (no spec) + + Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#ifndef _SHELL_ENVIRONMENT_2_PROTOCOL_H_ +#define _SHELL_ENVIRONMENT_2_PROTOCOL_H_ + +#define DEFAULT_INIT_ROW 1 +#define DEFAULT_AUTO_LF FALSE + +/** + This function is a prototype for a function that dumps information on a protocol + to a given location. The location is dependant on the implementation. This is + used when programatically adding shell commands. + + @param[in] Handle The handle the protocol is on. + @param[in] Interface The interface to the protocol. + +**/ +typedef +VOID +(EFIAPI *SHELLENV_DUMP_PROTOCOL_INFO) ( + IN EFI_HANDLE Handle, + IN VOID *Interface + ); + +/** + This function is a prototype for each command internal to the EFI shell + implementation. The specific command depends on the implementation. This is + used when programatically adding shell commands. + + @param[in] ImageHandle The handle to the binary shell. + @param[in] SystemTable The pointer to the system table. + + @retval EFI_SUCCESS The command completed. + @retval other An error occurred. Any error is possible + depending on the implementation of the shell + command. + +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_INTERNAL_COMMAND) ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + This function is a prototype for one that gets a help string for a given command. + This is used when programatically adding shell commands. Upon successful return + the memory allocated is up to the caller to free. + + @param[in, out] Str Pointer to pointer to string to display for help. + + @retval EFI_SUCCESS The help string is in the parameter Str. + +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLCMD_GET_LINE_HELP) ( + IN OUT CHAR16 **Str + ); + +/** +Structure returned from functions that open multiple files. +**/ +typedef struct { + UINT32 Signature; ///< SHELL_FILE_ARG_SIGNATURE. + LIST_ENTRY Link; ///< Linked list helper. + EFI_STATUS Status; ///< File's status. + + EFI_FILE_HANDLE Parent; ///< What is the Parent file of this file. + UINT64 OpenMode; ///< How was the file opened. + CHAR16 *ParentName; ///< String representation of parent. + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; ///< DevicePath for Parent. + + CHAR16 *FullName; ///< Path and file name for this file. + CHAR16 *FileName; ///< File name for this file. + + EFI_FILE_HANDLE Handle; ///< Handle to this file. + EFI_FILE_INFO *Info; ///< Pointer to file info for this file. +} SHELL_FILE_ARG; + +/// Signature for SHELL_FILE_ARG. +#define SHELL_FILE_ARG_SIGNATURE SIGNATURE_32 ('g', 'r', 'a', 'f') + +/** +GUID for the shell environment2 and shell environment. +**/ +#define SHELL_ENVIRONMENT_PROTOCOL_GUID \ + { \ + 0x47c7b221, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \ + } + +/** +GUID for the shell environment2 extension (main GUID above). +**/ +#define EFI_SE_EXT_SIGNATURE_GUID \ + { \ + 0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87} \ + } + +#define EFI_SHELL_MAJOR_VER 0x00000001 ///< Major version of the EFI_SHELL_ENVIRONMENT2. +#define EFI_SHELL_MINOR_VER 0x00000000 ///< Minor version of the EFI_SHELL_ENVIRONMENT2. + +/** + Execute a command line. + + This function will run the CommandLine. This includes loading any required images, + parsing any requires scripts, and if DebugOutput is TRUE printing errors + encountered directly to the screen. + + @param[in] ParentImageHandle Handle of the image executing this operation. + @param[in] CommandLine The string command line to execute. + @param[in] DebugOutput TRUE indicates that errors should be printed directly. + FALSE suppresses error messages. + + @retval EFI_SUCCESS The command line executed and completed. + @retval EFI_ABORTED The operation aborted. + @retval EFI_INVALID_PARAMETER A parameter did not have a valid value. + @retval EFI_OUT_OF_RESOURCES A required memory allocation failed. + +@sa HandleProtocol +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_EXECUTE) ( + IN EFI_HANDLE *ParentImageHandle, + IN CHAR16 *CommandLine, + IN BOOLEAN DebugOutput + ); + +/** + This function returns a shell environment variable value. + + @param[in] Name The pointer to the string with the shell environment + variable name. + + @retval NULL The shell environment variable's value could not be found. + @retval !=NULL The value of the shell environment variable Name. + +**/ +typedef +CHAR16 * +(EFIAPI *SHELLENV_GET_ENV) ( + IN CHAR16 *Name + ); + +/** + This function returns a shell environment map value. + + @param[in] Name The pointer to the string with the shell environment + map name. + + @retval NULL The shell environment map's value could not be found. + @retval !=NULL The value of the shell environment map Name. + +**/ +typedef +CHAR16 * +(EFIAPI *SHELLENV_GET_MAP) ( + IN CHAR16 *Name + ); + +/** + This function will add an internal command to the shell interface. + + This will allocate all required memory, put the new command on the command + list in the correct location. + + @param[in] Handler The handler function to call when the command gets called. + @param[in] Cmd The command name. + @param[in] GetLineHelp The function to call of type "get help" for this command. + + @retval EFI_SUCCESS The command is now part of the command list. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @sa SHELLENV_INTERNAL_COMMAND + @sa SHELLCMD_GET_LINE_HELP +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_ADD_CMD) ( + IN SHELLENV_INTERNAL_COMMAND Handler, + IN CHAR16 *Cmd, + IN SHELLCMD_GET_LINE_HELP GetLineHelp + ); + +/** + Internal interface to add protocol handlers. + + This function is for internal shell use only. This is how protocol handlers are added. + This will get the current protocol info and add the new info or update existing info + and then resave the info. + + @param[in] Protocol The pointer to the protocol's GUID. + @param[in] DumpToken The function pointer to dump token function or + NULL. + @param[in] DumpInfo The function pointer to dump infomation function + or NULL. + @param[in] IdString The English name of the protocol. +**/ +typedef +VOID +(EFIAPI *SHELLENV_ADD_PROT) ( + IN EFI_GUID *Protocol, + IN SHELLENV_DUMP_PROTOCOL_INFO DumpToken OPTIONAL, + IN SHELLENV_DUMP_PROTOCOL_INFO DumpInfo OPTIONAL, + IN CHAR16 *IdString + ); + +/** + This function finds a protocol handle by a GUID. + + This function will check for already known protocols by GUID and if one is + found it will return the name of that protocol. If no name is found and + GenId is TRUE it will generate ths string. + + @param[in] Protocol The GUID of the protocol to look for. + @param[in] GenId Whether to generate a name string if it is not found. + + @return !NULL The Name of the protocol. + @retval NULL The Name was not found, and GenId was not TRUE. +**/ +typedef +CHAR16* +(EFIAPI *SHELLENV_GET_PROT) ( + IN EFI_GUID *Protocol, + IN BOOLEAN GenId + ); + +/** + This function returns a string array containing the current directory on + a given device. + + If DeviceName is specified, then return the current shell directory on that + device. If DeviceName is NULL, then return the current directory on the + current device. The caller us responsible to free the returned string when + no longer required. + + @param[in] DeviceName The name of the device to get the current + directory on, or NULL for current device. + + @return String array with the current directory on the current or specified device. + +**/ +typedef +CHAR16* +(EFIAPI *SHELLENV_CUR_DIR) ( + IN CHAR16 *DeviceName OPTIONAL + ); + +/** + This function will open a group of files that match the Arg path, including + support for wildcard characters ('?' and '*') in the Arg path. If there are + any wildcard characters in the path this function will find any and all files + that match the wildcards. It returns a double linked list based on the + LIST_ENTRY linked list structure. Use this in conjunction with the + SHELL_FILE_ARG_SIGNATURE to get the SHELL_FILE_ARG structures that are returned. + The memory allocated by the callee for this list is freed by making a call to + SHELLENV_FREE_FILE_LIST. + + @param[in] Arg The pointer Path to files to open. + @param[in, out] ListHead The pointer to the allocated and initialized list head + upon which to append all opened file structures. + + @retval EFI_SUCCESS One or more files was opened and a struct of each file's + information was appended to ListHead. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_NOT_FOUND No matching files could be found. + @sa SHELLENV_FREE_FILE_LIST +**/typedef +EFI_STATUS +(EFIAPI *SHELLENV_FILE_META_ARG) ( + IN CHAR16 *Arg, + IN OUT LIST_ENTRY *ListHead + ); + +/** + This frees all of the nodes under the ListHead, but not ListHead itself. + + @param[in, out] ListHead Pointer to list to free all nodes of. + + @retval EFI_SUCCESS This function always returns EFI_SUCCESS. +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_FREE_FILE_LIST) ( + IN OUT LIST_ENTRY *ListHead + ); + +/** + This function creates a new instance of the ShellInterface protocol for use on + the ImageHandle. + + This function is for internal shell usage. This will allocate and then populate + EFI_SHELL_INTERFACE protocol. It is the caller's responsibility to free the + memory. + + @param[in] ImageHandle The handle which will use the new ShellInterface + protocol. + + @return The newly allocated shell interface protocol. + +**/ +typedef +EFI_SHELL_INTERFACE* +(EFIAPI *SHELLENV_NEW_SHELL) ( + IN EFI_HANDLE ImageHandle + ); + +/** + This function determines whether a script file is currently being processed. + + A script file (.nsh file) can contain a series of commands and this is useful to + know for some shell commands whether they are being run manually or as part of a + script. + + @retval TRUE A script file is being processed. + @retval FALSE A script file is not being processed. +**/ +typedef +BOOLEAN +(EFIAPI *SHELLENV_BATCH_IS_ACTIVE) ( + VOID + ); + +/** + This is an internal shell function to free any and all allocated resources. + This should be called immediately prior to closing the shell. +**/ +typedef +VOID +(EFIAPI *SHELLENV_FREE_RESOURCES) ( + VOID + ); + +/** + This function enables the page break mode. + + This mode causes the output to pause after each complete screen to enable a + user to more easily read it. If AutoWrap is TRUE, then rows with too many + characters will be chopped and divided into 2 rows. If FALSE, then rows with + too many characters may not be fully visible to the user on the screen. + + @param[in] StartRow The row number to start this on. + @param[in] AutoWrap Whether to auto wrap rows that are too long. +**/ +typedef +VOID +(EFIAPI *SHELLENV_ENABLE_PAGE_BREAK) ( + IN INT32 StartRow, + IN BOOLEAN AutoWrap + ); + +/** + This function disables the page break mode. + + Disabling this causes the output to print out exactly as coded, with no breaks + for readability. +**/ +typedef +VOID +(EFIAPI *SHELLENV_DISABLE_PAGE_BREAK) ( + VOID + ); + +/** + Get the status of the page break output mode. + + @retval FALSE Page break output mode is not enabled. + @retval TRUE Page break output mode is enabled. +**/ +typedef +BOOLEAN +(EFIAPI *SHELLENV_GET_PAGE_BREAK) ( + VOID + ); + +/** + This function sets the keys to filter for for the console in. The valid + values to set are: + + #define EFI_OUTPUT_SCROLL 0x00000001 + #define EFI_OUTPUT_PAUSE 0x00000002 + #define EFI_EXECUTION_BREAK 0x00000004 + + @param[in] KeyFilter The new key filter to use. +**/ +typedef +VOID +(EFIAPI *SHELLENV_SET_KEY_FILTER) ( + IN UINT32 KeyFilter + ); + +/** + This function gets the keys to filter for for the console in. + + The valid values to get are: + #define EFI_OUTPUT_SCROLL 0x00000001 + #define EFI_OUTPUT_PAUSE 0x00000002 + #define EFI_EXECUTION_BREAK 0x00000004 + + @retval The current filter mask. +**/ +typedef +UINT32 +(EFIAPI *SHELLENV_GET_KEY_FILTER) ( + VOID + ); + +/** + This function determines if the shell application should break. + + This is used to inform a shell application that a break condition has been + initiated. Long loops should check this to prevent delays to the break. + + @retval TRUE A break has been signaled. The application + should exit with EFI_ABORTED as soon as possible. + @retval FALSE Continue as normal. +**/ +typedef +BOOLEAN +(EFIAPI *SHELLENV_GET_EXECUTION_BREAK) ( + VOID + ); + +/** + This is an internal shell function used to increment the shell nesting level. + +**/ +typedef +VOID +(EFIAPI *SHELLENV_INCREMENT_SHELL_NESTING_LEVEL) ( + VOID + ); + +/** + This is an internal shell function used to decrement the shell nesting level. +**/ +typedef +VOID +(EFIAPI *SHELLENV_DECREMENT_SHELL_NESTING_LEVEL) ( + VOID + ); + +/** + This function determines if the caller is running under the root shell. + + @retval TRUE The caller is running under the root shell. + @retval FALSE The caller is not running under the root shell. + +**/ +typedef +BOOLEAN +(EFIAPI *SHELLENV_IS_ROOT_SHELL) ( + VOID + ); + +/** + Close the console proxy to restore the original console. + + This is an internal shell function to handle shell cascading. It restores the + original set of console protocols. + + @param[in] ConInHandle The handle of ConIn. + @param[in, out] ConIn The pointer to the location to return the pointer to + the original console input. + @param[in] ConOutHandle The handle of ConOut + @param[in, out] ConOut The pointer to the location to return the pointer to + the original console output. +**/ +typedef +VOID +(EFIAPI *SHELLENV_CLOSE_CONSOLE_PROXY) ( + IN EFI_HANDLE ConInHandle, + IN OUT EFI_SIMPLE_TEXT_INPUT_PROTOCOL **ConIn, + IN EFI_HANDLE ConOutHandle, + IN OUT EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **ConOut + ); + +// +// declarations of handle enumerator +// +/** + For ease of use the shell maps handle #'s to short numbers. + This is only done on request for various internal commands and the references + are immediately freed when the internal command completes. +**/ +typedef +VOID +(EFIAPI *INIT_HANDLE_ENUMERATOR) ( + VOID + ); + +/** + This is an internal shell function to enumerate the handle database. + + This function gets the next handle in the handle database. If no handles are + found, EFI_NOT_FOUND is returned. If the previous Handle was the last handle, + it is set to NULL before returning. + + This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR. + + @param[in, out] Handle The pointer to pointer to Handle. It is set + on a sucessful return. + + @retval EFI_SUCCESS The next handle in the handle database is *Handle. + @retval EFI_NOT_FOUND There is not another handle. +**/ +typedef +EFI_STATUS +(EFIAPI *NEXT_HANDLE) ( + IN OUT EFI_HANDLE **Handle + ); + +/** + This is an internal shell function to enumerate the handle database. + + This function skips the next SkipNum handles in the handle database. If there + are not enough handles left to skip that many EFI_ACCESS_DENIED is returned and + no skip is performed. + + This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR. + + @param[in] SkipNum How many handles to skip + + @retval EFI_SUCCESS The next handle in the handle database is *Handle + @retval EFI_ACCESS_DENIED There are not SkipNum handles left in the database +**/ +typedef +EFI_STATUS +(EFIAPI *SKIP_HANDLE) ( + IN UINTN SkipNum + ); + +/** + This is an internal shell function to enumerate the handle database. + + This function resets the the handle database so that NEXT_HANDLE and SKIP_HANDLE + will start from EnumIndex on the next call. + + This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR. + + @param[in] EnumIndex Where to start. + + @return The number of handles either read out or skipped before this reset. +**/ +typedef +UINTN +(EFIAPI *RESET_HANDLE_ENUMERATOR) ( + IN UINTN EnumIndex + ); + +/** + This is an internal shell function to enumerate the handle database. + + This must be called after INIT_HANDLE_ENUMERATOR. + + This function releases all memory and resources associated with the handle database. + After this no other handle enumerator functions except INIT_HANDLE_ENUMERATOR will + function properly. +**/ +typedef +VOID +(EFIAPI *CLOSE_HANDLE_ENUMERATOR) ( + VOID + ); + +/** + This is an internal shell function to enumerate the handle database. + + This function returns the number of handles in the handle database. + + This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR. + + @return The number of handles in the handle database. +**/ +typedef +UINTN +(EFIAPI *GET_NUM) ( + VOID + ); + +/** +Handle Enumerator structure. +**/ +typedef struct { + INIT_HANDLE_ENUMERATOR Init; ///< The pointer to INIT_HANDLE_ENUMERATOR function. + NEXT_HANDLE Next; ///< The pointer to NEXT_HANDLE function. + SKIP_HANDLE Skip; ///< The pointer to SKIP_HANDLE function. + RESET_HANDLE_ENUMERATOR Reset; ///< The pointer to RESET_HANDLE_ENUMERATOR function. + CLOSE_HANDLE_ENUMERATOR Close; ///< The pointer to CLOSE_HANDLE_ENUMERATOR function. + GET_NUM GetNum; ///< The pointer to GET_NUM function. +} HANDLE_ENUMERATOR; + +/** + Signature for the PROTOCOL_INFO structure. +**/ +#define PROTOCOL_INFO_SIGNATURE SIGNATURE_32 ('s', 'p', 'i', 'n') + +/** + PROTOCOL_INFO structure for protocol enumerator functions. +**/ +typedef struct { + UINTN Signature; ///< PROTOCOL_INFO_SIGNATURE. + LIST_ENTRY Link; ///< Standard linked list helper member. + // + // The parsing info for the protocol. + // + EFI_GUID ProtocolId; ///< The GUID for the protocol. + CHAR16 *IdString; ///< The name of the protocol. + SHELLENV_DUMP_PROTOCOL_INFO DumpToken; ///< The pointer to DumpToken function for the protocol. + SHELLENV_DUMP_PROTOCOL_INFO DumpInfo; ///< The pointer to DumpInfo function for the protocol. + // + // Patabase info on which handles are supporting this protocol. + // + UINTN NoHandles; ///< The number of handles producing this protocol. + EFI_HANDLE *Handles; ///< The array of handles. + +} PROTOCOL_INFO; + +// +// Declarations of protocol info enumerator. +// +/** + This is an internal shell function to initialize the protocol enumerator. + + This must be called before NEXT_PROTOCOL_INFO, SKIP_PROTOCOL_INFO, + RESET_PROTOCOL_INFO_ENUMERATOR, and CLOSE_PROTOCOL_INFO_ENUMERATOR are + called. +**/ +typedef +VOID +(EFIAPI *INIT_PROTOCOL_INFO_ENUMERATOR) ( + VOID + ); + +/** + This function is an internal shell function for enumeration of protocols. + + This function returns the next protocol on the list. If this is called + immediately after initialization, it will return the first protocol on the list. + If this is called immediately after reset, it will return the first protocol again. + + This cannot be called after CLOSE_PROTOCOL_INFO_ENUMERATOR, but it must be + called after INIT_PROTOCOL_INFO_ENUMERATOR. + + @param[in, out] ProtocolInfo The pointer to pointer to protocol information structure. + + @retval EFI_SUCCESS The next protocol's information was sucessfully returned. + @retval NULL There are no more protocols. +**/ +typedef +EFI_STATUS +(EFIAPI *NEXT_PROTOCOL_INFO) ( + IN OUT PROTOCOL_INFO **ProtocolInfo + ); + +/** + This function is an internal shell function for enumeration of protocols. + + This cannot be called after CLOSE_PROTOCOL_INFO_ENUMERATOR, but it must be + called after INIT_PROTOCOL_INFO_ENUMERATOR. + + This function does nothing and always returns EFI_SUCCESS. + + @retval EFI_SUCCESS Always returned (see above). +**/ +typedef +EFI_STATUS +(EFIAPI *SKIP_PROTOCOL_INFO) ( + IN UINTN SkipNum + ); + +/** + This function is an internal shell function for enumeration of protocols. + + This cannot be called after CLOSE_PROTOCOL_INFO_ENUMERATOR, but it must be + called after INIT_PROTOCOL_INFO_ENUMERATOR. + + This function resets the list of protocols such that the next one in the + list is the begining of the list. +**/ +typedef +VOID +(EFIAPI *RESET_PROTOCOL_INFO_ENUMERATOR) ( + VOID + ); + + +/** + This function is an internal shell function for enumeration of protocols. + + This must be called after INIT_PROTOCOL_INFO_ENUMERATOR. After this call + no protocol enumerator calls except INIT_PROTOCOL_INFO_ENUMERATOR may be made. + + This function frees any memory or resources associated with the protocol + enumerator. +**/ +typedef +VOID +(EFIAPI *CLOSE_PROTOCOL_INFO_ENUMERATOR) ( + VOID + ); + +/** + Protocol enumerator structure of function pointers. +**/ +typedef struct { + INIT_PROTOCOL_INFO_ENUMERATOR Init; ///< The pointer to INIT_PROTOCOL_INFO_ENUMERATOR function. + NEXT_PROTOCOL_INFO Next; ///< The pointer to NEXT_PROTOCOL_INFO function. + SKIP_PROTOCOL_INFO Skip; ///< The pointer to SKIP_PROTOCOL_INFO function. + RESET_PROTOCOL_INFO_ENUMERATOR Reset; ///< The pointer to RESET_PROTOCOL_INFO_ENUMERATOR function. + CLOSE_PROTOCOL_INFO_ENUMERATOR Close; ///< The pointer to CLOSE_PROTOCOL_INFO_ENUMERATOR function. +} PROTOCOL_INFO_ENUMERATOR; + +/** + This function is used to retrieve a user-friendly display name for a handle. + + If UseComponentName is TRUE then the component name protocol for this device + or it's parent device (if required) will be used to obtain the name of the + device. If UseDevicePath is TRUE it will get the human readable device path + and return that. If both are TRUE it will try to use component name first + and device path if that fails. + + It will use either ComponentName or ComponentName2 protocol, depending on + what is present. + + This function will furthur verify whether the handle in question produced either + EFI_DRIVER_CONFIGRATION_PROTOCOL or EFI_DRIVER_CONFIGURATION2_PROTOCOL and also + whether the handle in question produced either EFI_DRIVER_DIAGNOSTICS_PROTOCOL or + EFI_DRIVER_DIAGNOSTICS2_PROTOCOL. + + Upon successful return, the memory for *BestDeviceName is up to the caller to free. + + @param[in] DeviceHandle The device handle whose name is desired. + @param[in] UseComponentName Whether to use the ComponentName protocol at all. + @param[in] UseDevicePath Whether to use the DevicePath protocol at all. + @param[in] Language The pointer to the language string to use. + @param[in, out] BestDeviceName The pointer to pointer to string allocated with the name. + @param[out] ConfigurationStatus The pointer to status for opening a Configuration protocol. + @param[out] DiagnosticsStatus The pointer to status for opening a Diagnostics protocol. + @param[in] Display Whether to Print this out to default Print location. + @param[in] Indent How many characters to indent the printing. + + @retval EFI_SUCCESS This function always returns EFI_SUCCESS. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_DEVICE_NAME) ( + IN EFI_HANDLE DeviceHandle, + IN BOOLEAN UseComponentName, + IN BOOLEAN UseDevicePath, + IN CHAR8 *Language, + IN OUT CHAR16 **BestDeviceName, + OUT EFI_STATUS *ConfigurationStatus, + OUT EFI_STATUS *DiagnosticsStatus, + IN BOOLEAN Display, + IN UINTN Indent + ); + +#define EFI_SHELL_COMPATIBLE_MODE_VER L"1.1.1" ///< The string for lowest version this shell supports. +#define EFI_SHELL_ENHANCED_MODE_VER L"1.1.2" ///< The string for highest version this shell supports. + +/** + This function gets the shell mode as stored in the shell environment + "efishellmode". It will not fail. + + @param[out] Mode Returns a string representing one of the + 2 supported modes of the shell. + + @retval EFI_SUCCESS This function always returns success. +**/ +typedef +EFI_STATUS +(EFIAPI *GET_SHELL_MODE) ( + OUT CHAR16 **Mode + ); + +/** + Convert a file system style name to a device path. + + This function will convert a shell path name to a Device Path Protocol path. + This function will allocate any required memory for this operation and it + is the responsibility of the caller to free that memory when no longer required. + + If anything prevents the complete conversion free any allocated memory and + return NULL. + + @param[in] Path The path to convert. + + @retval !NULL A pointer to the callee allocated Device Path. + @retval NULL The operation could not be completed. +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *SHELLENV_NAME_TO_PATH) ( + IN CHAR16 *Path + ); + +/** + Converts a device path into a file system map name. + + If DevPath is NULL, then ASSERT. + + This function looks through the shell environment map for a map whose device + path matches the DevPath parameter. If one is found the Name is returned via + Name parameter. If sucessful the caller must free the memory allocated for + Name. + + This function will use the internal lock to prevent changes to the map during + the lookup operation. + + @param[in] DevPath The device path to search for a name for. + @param[in] ConsistMapping What state to verify map flag VAR_ID_CONSIST. + @param[out] Name On sucessful return the name of that device path. + + @retval EFI_SUCCESS The DevPath was found and the name returned + in Name. + @retval EFI_OUT_OF_RESOURCES A required memory allocation failed. + @retval EFI_UNSUPPORTED The DevPath was not found in the map. +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_GET_FS_NAME) ( + IN EFI_DEVICE_PATH_PROTOCOL * DevPath, + IN BOOLEAN ConsistMapping, + OUT CHAR16 **Name + ); + +/** + This function will open a group of files that match the Arg path, but will not + support the wildcard characters ('?' and '*') in the Arg path. If there are + any wildcard characters in the path this function will return + EFI_INVALID_PARAMETER. The return is a double linked list based on the + LIST_ENTRY linked list structure. Use this in conjunction with the + SHELL_FILE_ARG_SIGNATURE to get the SHELL_FILE_ARG structures that are returned. + The memory allocated by the callee for this list is freed by making a call to + SHELLENV_FREE_FILE_LIST. + + @param[in] Arg The pointer to the path of the files to be opened. + @param[in, out] ListHead The pointer to allocated and initialized list head + upon which to append all the opened file structures. + + @retval EFI_SUCCESS One or more files was opened and a struct of each file's + information was appended to ListHead. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_NOT_FOUND No matching files could be found. + @sa SHELLENV_FREE_FILE_LIST +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_FILE_META_ARG_NO_WILDCARD) ( + IN CHAR16 *Arg, + IN OUT LIST_ENTRY *ListHead + ); + +/** + This function removes duplicate file listings from lists. + + This is a function for use with SHELLENV_FILE_META_ARG_NO_WILDCARD and + SHELLENV_FILE_META_ARG. This function will verify that there are no duplicate + files in the list of returned files. Any file listed twice will have one of its + instances removed. + + @param[in] ListHead The pointer to linked list head that was returned from + SHELLENV_FILE_META_ARG_NO_WILDCARD or + SHELLENV_FILE_META_ARG. + + @retval EFI_SUCCESS This function always returns success. + +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_DEL_DUP_FILE) ( + IN LIST_ENTRY * ListHead + ); + +/** + Converts a File System map name to a device path. + + If DevPath is NULL, then ASSERT(). + + This function looks through the shell environment map for a map whose Name + matches the Name parameter. If one is found, the device path pointer is + updated to point to that file systems device path. The caller should not + free the memory from that device path. + + This function will use the internal lock to prevent changes to the map during + the lookup operation. + + @param[in] Name The pointer to the NULL terminated UNICODE string of the + file system name. + @param[out] DevPath The pointer to pointer to DevicePath. Only valid on + successful return. + + @retval EFI_SUCCESS The conversion was successful, and the device + path was returned. + @retval EFI_NOT_FOUND The file system could not be found in the map. +**/ +typedef +EFI_STATUS +(EFIAPI *SHELLENV_GET_FS_DEVICE_PATH) ( + IN CHAR16 *Name, + OUT EFI_DEVICE_PATH_PROTOCOL **DevPath + ); + +/// EFI_SHELL_ENVIRONMENT2 protocol structure. +typedef struct { + SHELLENV_EXECUTE Execute; + SHELLENV_GET_ENV GetEnv; + SHELLENV_GET_MAP GetMap; + SHELLENV_ADD_CMD AddCmd; + SHELLENV_ADD_PROT AddProt; + SHELLENV_GET_PROT GetProt; + SHELLENV_CUR_DIR CurDir; + SHELLENV_FILE_META_ARG FileMetaArg; + SHELLENV_FREE_FILE_LIST FreeFileList; + + // + // The following services are only used by the shell itself. + // + SHELLENV_NEW_SHELL NewShell; + SHELLENV_BATCH_IS_ACTIVE BatchIsActive; + + SHELLENV_FREE_RESOURCES FreeResources; + + // + // GUID to differentiate ShellEnvironment2 from ShellEnvironment. + // + EFI_GUID SESGuid; + // + // Major Version grows if shell environment interface has been changes. + // + UINT32 MajorVersion; + UINT32 MinorVersion; + SHELLENV_ENABLE_PAGE_BREAK EnablePageBreak; + SHELLENV_DISABLE_PAGE_BREAK DisablePageBreak; + SHELLENV_GET_PAGE_BREAK GetPageBreak; + + SHELLENV_SET_KEY_FILTER SetKeyFilter; + SHELLENV_GET_KEY_FILTER GetKeyFilter; + + SHELLENV_GET_EXECUTION_BREAK GetExecutionBreak; + SHELLENV_INCREMENT_SHELL_NESTING_LEVEL IncrementShellNestingLevel; + SHELLENV_DECREMENT_SHELL_NESTING_LEVEL DecrementShellNestingLevel; + SHELLENV_IS_ROOT_SHELL IsRootShell; + + SHELLENV_CLOSE_CONSOLE_PROXY CloseConsoleProxy; + HANDLE_ENUMERATOR HandleEnumerator; + PROTOCOL_INFO_ENUMERATOR ProtocolInfoEnumerator; + GET_DEVICE_NAME GetDeviceName; + GET_SHELL_MODE GetShellMode; + SHELLENV_NAME_TO_PATH NameToPath; + SHELLENV_GET_FS_NAME GetFsName; + SHELLENV_FILE_META_ARG_NO_WILDCARD FileMetaArgNoWildCard; + SHELLENV_DEL_DUP_FILE DelDupFileArg; + SHELLENV_GET_FS_DEVICE_PATH GetFsDevicePath; +} EFI_SHELL_ENVIRONMENT2; + +extern EFI_GUID gEfiShellEnvironment2Guid; +extern EFI_GUID gEfiShellEnvironment2ExtGuid; + +#endif // _SHELL_ENVIRONMENT_2_PROTOCOL_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellInterface.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellInterface.h new file mode 100644 index 0000000..38fd7a3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Include/Protocol/EfiShellInterface.h @@ -0,0 +1,94 @@ +/** @file + EFI Shell Interface protocol from EDK shell (no spec). + + Shell Interface - additional information (over image_info) provided + to an application started by the shell. + + ConIo provides a file-style interface to the console. + + The shell interface's and data (including ConIo) are only valid during + the applications Entry Point. Once the application returns from it's + entry point the data is freed by the invoking shell. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SHELLINTERFACE_H_ +#define _SHELLINTERFACE_H_ + +#include + +#define SHELL_INTERFACE_PROTOCOL_GUID \ + { \ + 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \ + } + +/// +/// Bit definitions for EFI_SHELL_ARG_INFO +/// +typedef enum { + ARG_NO_ATTRIB = 0x0, + ARG_IS_QUOTED = BIT0, + ARG_PARTIALLY_QUOTED = BIT1, + ARG_FIRST_HALF_QUOTED = BIT2, + ARG_FIRST_CHAR_IS_ESC = BIT3 +} EFI_SHELL_ARG_INFO_TYPES; + +/// +/// Attributes for an argument. +/// +typedef struct _EFI_SHELL_ARG_INFO { + UINT32 Attributes; +} EFI_SHELL_ARG_INFO; + +/// +/// This protocol provides access to additional information about a shell application. +/// +typedef struct { + /// + /// Handle back to original image handle & image information. + /// + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *Info; + + /// + /// Parsed arg list converted more C-like format. + /// + CHAR16 **Argv; + UINTN Argc; + + /// + /// Storage for file redirection args after parsing. + /// + CHAR16 **RedirArgv; + UINTN RedirArgc; + + /// + /// A file style handle for console io. + /// + EFI_FILE_PROTOCOL *StdIn; + EFI_FILE_PROTOCOL *StdOut; + EFI_FILE_PROTOCOL *StdErr; + + /// + /// List of attributes for each argument. + /// + EFI_SHELL_ARG_INFO *ArgInfo; + + /// + /// Whether we are echoing. + /// + BOOLEAN EchoOn; +} EFI_SHELL_INTERFACE; + +extern EFI_GUID gEfiShellInterfaceGuid; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c new file mode 100644 index 0000000..9be6211 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c @@ -0,0 +1,3745 @@ +/** @file + Provides interface to advanced shell functionality for parsing both handle and protocol database. + + Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiHandleParsingLib.h" +#include "IndustryStandard/Acpi10.h" +#include "IndustryStandard/Pci.h" +#include +#include + +EFI_HANDLE mHandleParsingHiiHandle = NULL; +HANDLE_INDEX_LIST mHandleList = {{{NULL,NULL},0,0},0}; +GUID_INFO_BLOCK *mGuidList; +UINTN mGuidListCount; + +/** + Function to find the file name associated with a LoadedImageProtocol. + + @param[in] LoadedImage An instance of LoadedImageProtocol. + + @retval A string representation of the file name associated + with LoadedImage, or NULL if no name can be found. +**/ +CHAR16* +FindLoadedImageFileName ( + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage + ) +{ + EFI_GUID *NameGuid; + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + VOID *Buffer; + UINTN BufferSize; + UINT32 AuthenticationStatus; + + if ((LoadedImage == NULL) || (LoadedImage->FilePath == NULL)) { + return NULL; + } + + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath); + + if (NameGuid == NULL) { + return NULL; + } + + // + // Get the FirmwareVolume2Protocol of the device handle that this image was loaded from. + // + Status = gBS->HandleProtocol (LoadedImage->DeviceHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID**) &Fv); + + // + // FirmwareVolume2Protocol is PI, and is not required to be available. + // + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Read the user interface section of the image. + // + Buffer = NULL; + Status = Fv->ReadSection(Fv, NameGuid, EFI_SECTION_USER_INTERFACE, 0, &Buffer, &BufferSize, &AuthenticationStatus); + + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // ReadSection returns just the section data, without any section header. For + // a user interface section, the only data is the file name. + // + return Buffer; +} + +/** + Function to translate the EFI_MEMORY_TYPE into a string. + + @param[in] Memory The memory type. + + @retval A string representation of the type allocated from BS Pool. +**/ +CHAR16* +ConvertMemoryType ( + IN CONST EFI_MEMORY_TYPE Memory + ) +{ + CHAR16 *RetVal; + RetVal = NULL; + + switch (Memory) { + case EfiReservedMemoryType: StrnCatGrow(&RetVal, NULL, L"EfiReservedMemoryType", 0); break; + case EfiLoaderCode: StrnCatGrow(&RetVal, NULL, L"EfiLoaderCode", 0); break; + case EfiLoaderData: StrnCatGrow(&RetVal, NULL, L"EfiLoaderData", 0); break; + case EfiBootServicesCode: StrnCatGrow(&RetVal, NULL, L"EfiBootServicesCode", 0); break; + case EfiBootServicesData: StrnCatGrow(&RetVal, NULL, L"EfiBootServicesData", 0); break; + case EfiRuntimeServicesCode: StrnCatGrow(&RetVal, NULL, L"EfiRuntimeServicesCode", 0); break; + case EfiRuntimeServicesData: StrnCatGrow(&RetVal, NULL, L"EfiRuntimeServicesData", 0); break; + case EfiConventionalMemory: StrnCatGrow(&RetVal, NULL, L"EfiConventionalMemory", 0); break; + case EfiUnusableMemory: StrnCatGrow(&RetVal, NULL, L"EfiUnusableMemory", 0); break; + case EfiACPIReclaimMemory: StrnCatGrow(&RetVal, NULL, L"EfiACPIReclaimMemory", 0); break; + case EfiACPIMemoryNVS: StrnCatGrow(&RetVal, NULL, L"EfiACPIMemoryNVS", 0); break; + case EfiMemoryMappedIO: StrnCatGrow(&RetVal, NULL, L"EfiMemoryMappedIO", 0); break; + case EfiMemoryMappedIOPortSpace: StrnCatGrow(&RetVal, NULL, L"EfiMemoryMappedIOPortSpace", 0); break; + case EfiPalCode: StrnCatGrow(&RetVal, NULL, L"EfiPalCode", 0); break; + case EfiMaxMemoryType: StrnCatGrow(&RetVal, NULL, L"EfiMaxMemoryType", 0); break; + default: ASSERT(FALSE); + } + return (RetVal); +} + +/** + Function to translate the EFI_GRAPHICS_PIXEL_FORMAT into a string. + + @param[in] Fmt The format type. + + @retval A string representation of the type allocated from BS Pool. +**/ +CHAR16* +ConvertPixelFormat ( + IN CONST EFI_GRAPHICS_PIXEL_FORMAT Fmt + ) +{ + CHAR16 *RetVal; + RetVal = NULL; + + switch (Fmt) { + case PixelRedGreenBlueReserved8BitPerColor: StrnCatGrow(&RetVal, NULL, L"PixelRedGreenBlueReserved8BitPerColor", 0); break; + case PixelBlueGreenRedReserved8BitPerColor: StrnCatGrow(&RetVal, NULL, L"PixelBlueGreenRedReserved8BitPerColor", 0); break; + case PixelBitMask: StrnCatGrow(&RetVal, NULL, L"PixelBitMask", 0); break; + case PixelBltOnly: StrnCatGrow(&RetVal, NULL, L"PixelBltOnly", 0); break; + case PixelFormatMax: StrnCatGrow(&RetVal, NULL, L"PixelFormatMax", 0); break; + default: ASSERT(FALSE); + } + return (RetVal); +} + +/** + Constructor for the library. + + @param[in] ImageHandle Ignored. + @param[in] SystemTable Ignored. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +HandleParsingLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mGuidListCount = 0; + mGuidList = NULL; + + // + // Do nothing with mHandleParsingHiiHandle. Initialize HII as needed. + // + return (EFI_SUCCESS); +} + +/** + Initialization function for HII packages. + +**/ +VOID +HandleParsingHiiInit (VOID) +{ + if (mHandleParsingHiiHandle == NULL) { + mHandleParsingHiiHandle = HiiAddPackages (&gHandleParsingHiiGuid, gImageHandle, UefiHandleParsingLibStrings, NULL); + ASSERT (mHandleParsingHiiHandle != NULL); + } +} + +/** + Destructor for the library. free any resources. + + @param[in] ImageHandle Ignored. + @param[in] SystemTable Ignored. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +HandleParsingLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN LoopCount; + + for (LoopCount = 0; mGuidList != NULL && LoopCount < mGuidListCount; LoopCount++) { + SHELL_FREE_NON_NULL(mGuidList[LoopCount].GuidId); + } + + SHELL_FREE_NON_NULL(mGuidList); + if (mHandleParsingHiiHandle != NULL) { + HiiRemovePackages(mHandleParsingHiiHandle); + } + return (EFI_SUCCESS); +} + +/** + Function to dump information about LoadedImage. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has LoadedImage installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +LoadedImageProtocolDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_STATUS Status; + CHAR16 *RetVal; + CHAR16 *Temp; + CHAR16 *FileName; + CHAR8 *PdbFileName; + CHAR16 *FilePath; + CHAR16 *CodeType; + CHAR16 *DataType; + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + FileName = FindLoadedImageFileName(LoadedImage); + FilePath = ConvertDevicePathToText(LoadedImage->FilePath, TRUE, TRUE); + if (!Verbose) { + if (FileName == NULL) { + FileName = FilePath; + } else { + SHELL_FREE_NON_NULL(FilePath); + } + return FileName; + } + + HandleParsingHiiInit(); + RetVal = NULL; + if (FileName != NULL) { + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_LI_DUMP_NAME), NULL); + + if (Temp != NULL) { + RetVal = CatSPrint(NULL, Temp, FileName); + } + + SHELL_FREE_NON_NULL(Temp); + SHELL_FREE_NON_NULL(FileName); + } + + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_LI_DUMP_MAIN), NULL); + if (Temp == NULL) { + return NULL; + } + PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase); + DataType = ConvertMemoryType(LoadedImage->ImageDataType); + CodeType = ConvertMemoryType(LoadedImage->ImageCodeType); + + RetVal = CatSPrint( + RetVal, + Temp, + LoadedImage->Revision, + LoadedImage->ParentHandle, + LoadedImage->SystemTable, + LoadedImage->DeviceHandle, + FilePath, + PdbFileName, + LoadedImage->LoadOptionsSize, + LoadedImage->LoadOptions, + LoadedImage->ImageBase, + LoadedImage->ImageSize, + CodeType, + DataType, + LoadedImage->Unload + ); + + + SHELL_FREE_NON_NULL(Temp); + SHELL_FREE_NON_NULL(FilePath); + SHELL_FREE_NON_NULL(CodeType); + SHELL_FREE_NON_NULL(DataType); + + return RetVal; +} + +/** + Function to dump information about GOP. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has LoadedImage installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +GraphicsOutputProtocolDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_STATUS Status; + CHAR16 *RetVal; + CHAR16 *Temp; + CHAR16 *Fmt; + CHAR16 *TempRetVal; + UINTN GopInfoSize; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopInfo; + + if (!Verbose) { + return (CatSPrint(NULL, L"GraphicsOutput")); + } + + HandleParsingHiiInit(); + + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_GOP_DUMP_MAIN), NULL); + if (Temp == NULL) { + return NULL; + } + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiGraphicsOutputProtocolGuid, + (VOID**)&GraphicsOutput, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (Temp); + return NULL; + } + + Fmt = ConvertPixelFormat(GraphicsOutput->Mode->Info->PixelFormat); + + RetVal = CatSPrint( + NULL, + Temp, + GraphicsOutput->Mode->MaxMode, + GraphicsOutput->Mode->Mode, + GraphicsOutput->Mode->FrameBufferBase, + (UINT64)GraphicsOutput->Mode->FrameBufferSize, + (UINT64)GraphicsOutput->Mode->SizeOfInfo, + GraphicsOutput->Mode->Info->Version, + GraphicsOutput->Mode->Info->HorizontalResolution, + GraphicsOutput->Mode->Info->VerticalResolution, + Fmt, + GraphicsOutput->Mode->Info->PixelsPerScanLine, + GraphicsOutput->Mode->Info->PixelFormat!=PixelBitMask?0:GraphicsOutput->Mode->Info->PixelInformation.RedMask, + GraphicsOutput->Mode->Info->PixelFormat!=PixelBitMask?0:GraphicsOutput->Mode->Info->PixelInformation.GreenMask, + GraphicsOutput->Mode->Info->PixelFormat!=PixelBitMask?0:GraphicsOutput->Mode->Info->PixelInformation.BlueMask + ); + + SHELL_FREE_NON_NULL (Temp); + + Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_GOP_RES_LIST_MAIN), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL (RetVal); + goto EXIT; + } + + TempRetVal = CatSPrint (RetVal, Temp); + SHELL_FREE_NON_NULL (RetVal); + if (TempRetVal == NULL) { + goto EXIT; + } + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (Temp); + + Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_GOP_RES_LIST_ENTRY), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL (RetVal); + goto EXIT; + } + + + for (Mode = 0; Mode < GraphicsOutput->Mode->MaxMode; Mode++) { + Status = GraphicsOutput->QueryMode ( + GraphicsOutput, + Mode, + &GopInfoSize, + &GopInfo + ); + if (EFI_ERROR (Status)) { + continue; + } + + TempRetVal = CatSPrint ( + RetVal, + Temp, + Mode, + GopInfo->HorizontalResolution, + GopInfo->VerticalResolution + ); + + SHELL_FREE_NON_NULL (GopInfo); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } + + +EXIT: + SHELL_FREE_NON_NULL(Temp); + SHELL_FREE_NON_NULL(Fmt); + + return RetVal; +} + +/** + Function to dump information about EDID Discovered Protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has LoadedImage installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +EdidDiscoveredProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_EDID_DISCOVERED_PROTOCOL *EdidDiscovered; + EFI_STATUS Status; + CHAR16 *RetVal; + CHAR16 *Temp; + CHAR16 *TempRetVal; + + if (!Verbose) { + return (CatSPrint (NULL, L"EDIDDiscovered")); + } + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiEdidDiscoveredProtocolGuid, + (VOID**)&EdidDiscovered, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_DISCOVERED_MAIN), NULL); + if (Temp == NULL) { + return NULL; + } + + RetVal = CatSPrint (NULL, Temp, EdidDiscovered->SizeOfEdid); + SHELL_FREE_NON_NULL (Temp); + + if (EdidDiscovered->SizeOfEdid != 0) { + Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_DISCOVERED_DATA), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL (RetVal); + return NULL; + } + TempRetVal = CatSPrint (RetVal, Temp); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + + TempRetVal = CatSDumpHex (RetVal, 4, 0, EdidDiscovered->SizeOfEdid, EdidDiscovered->Edid); + RetVal = TempRetVal; + } + return RetVal; +} + +/** + Function to dump information about EDID Active Protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has LoadedImage installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +EdidActiveProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_EDID_ACTIVE_PROTOCOL *EdidActive; + EFI_STATUS Status; + CHAR16 *RetVal; + CHAR16 *Temp; + CHAR16 *TempRetVal; + + if (!Verbose) { + return (CatSPrint (NULL, L"EDIDActive")); + } + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiEdidActiveProtocolGuid, + (VOID**)&EdidActive, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_ACTIVE_MAIN), NULL); + if (Temp == NULL) { + return NULL; + } + + RetVal = CatSPrint (NULL, Temp, EdidActive->SizeOfEdid); + SHELL_FREE_NON_NULL (Temp); + + if (EdidActive->SizeOfEdid != 0) { + Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_ACTIVE_DATA), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL (RetVal); + return NULL; + } + TempRetVal = CatSPrint (RetVal, Temp); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + + TempRetVal = CatSDumpHex (RetVal, 4, 0, EdidActive->SizeOfEdid, EdidActive->Edid); + RetVal = TempRetVal; + } + return RetVal; +} + +/** + Function to dump information about PciRootBridgeIo. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has PciRootBridgeIo installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +PciRootBridgeIoDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; + UINT64 Supports; + UINT64 Attributes; + CHAR16 *Temp; + CHAR16 *Temp2; + CHAR16 *RetVal; + EFI_STATUS Status; + + RetVal = NULL; + + if (!Verbose) { + return (CatSPrint(NULL, L"PciRootBridgeIo")); + } + + HandleParsingHiiInit(); + + Status = gBS->HandleProtocol( + TheHandle, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID**)&PciRootBridgeIo); + + if (EFI_ERROR(Status)) { + return NULL; + } + + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_PH), NULL); + if (Temp == NULL) { + return NULL; + } + Temp2 = CatSPrint(NULL, Temp, PciRootBridgeIo->ParentHandle); + FreePool(Temp); + RetVal = Temp2; + Temp2 = NULL; + + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_SEG), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL(RetVal); + return NULL; + } + Temp2 = CatSPrint(RetVal, Temp, PciRootBridgeIo->SegmentNumber); + FreePool(Temp); + FreePool(RetVal); + RetVal = Temp2; + Temp2 = NULL; + + Supports = 0; + Attributes = 0; + Status = PciRootBridgeIo->GetAttributes (PciRootBridgeIo, &Supports, &Attributes); + if (!EFI_ERROR(Status)) { + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_ATT), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL(RetVal); + return NULL; + } + Temp2 = CatSPrint(RetVal, Temp, Attributes); + FreePool(Temp); + FreePool(RetVal); + RetVal = Temp2; + Temp2 = NULL; + + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_SUPPORTS), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL(RetVal); + return NULL; + } + Temp2 = CatSPrint(RetVal, Temp, Supports); + FreePool(Temp); + FreePool(RetVal); + RetVal = Temp2; + Temp2 = NULL; + } + + Configuration = NULL; + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Configuration); + if (!EFI_ERROR(Status) && Configuration != NULL) { + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_TITLE), NULL); + if (Temp == NULL) { + SHELL_FREE_NON_NULL(RetVal); + return NULL; + } + Temp2 = CatSPrint(RetVal, Temp, Supports); + FreePool(Temp); + FreePool(RetVal); + RetVal = Temp2; + Temp2 = NULL; + while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) { + Temp = NULL; + switch (Configuration->ResType) { + case ACPI_ADDRESS_SPACE_TYPE_MEM: + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_MEM), NULL); + break; + case ACPI_ADDRESS_SPACE_TYPE_IO: + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_IO), NULL); + break; + case ACPI_ADDRESS_SPACE_TYPE_BUS: + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_BUS), NULL); + break; + } + if (Temp != NULL) { + Temp2 = CatSPrint(RetVal, L"\r\n%s", Temp); + FreePool(Temp); + FreePool(RetVal); + RetVal = Temp2; + Temp2 = NULL; + } + + Temp2 = CatSPrint(RetVal, + L"%%H%02x %016lx %016lx %02x%%N", + Configuration->SpecificFlag, + Configuration->AddrRangeMin, + Configuration->AddrRangeMax, + Configuration->AddrSpaceGranularity + ); + FreePool(RetVal); + RetVal = Temp2; + Temp2 = NULL; + Configuration++; + } + } + return (RetVal); +} + +/** + Function to dump information about SimpleTextOut. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has SimpleTextOut installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +TxtOutProtocolDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Dev; + INTN Index; + UINTN Col; + UINTN Row; + EFI_STATUS Status; + CHAR16 *RetVal; + UINTN Size; + CHAR16 *Temp; + UINTN NewSize; + + if (!Verbose) { + return (NULL); + } + + HandleParsingHiiInit(); + + RetVal = NULL; + Size = 0; + + Status = gBS->HandleProtocol( + TheHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID**)&Dev); + + ASSERT_EFI_ERROR(Status); + ASSERT (Dev != NULL && Dev->Mode != NULL); + + Size = (Dev->Mode->MaxMode + 1) * 80; + RetVal = AllocateZeroPool(Size); + + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_HEADER), NULL); + if (Temp != NULL) { + UnicodeSPrint(RetVal, Size, Temp, Dev, Dev->Mode->Attribute); + FreePool(Temp); + } + + // + // Dump TextOut Info + // + Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_LINE), NULL); + for (Index = 0; Index < Dev->Mode->MaxMode; Index++) { + Status = Dev->QueryMode (Dev, Index, &Col, &Row); + NewSize = Size - StrSize(RetVal); + UnicodeSPrint( + RetVal + StrLen(RetVal), + NewSize, + Temp == NULL?L"":Temp, + Index == Dev->Mode->Mode ? L'*' : L' ', + Index, + !EFI_ERROR(Status)?(INTN)Col:-1, + !EFI_ERROR(Status)?(INTN)Row:-1 + ); + } + FreePool(Temp); + return (RetVal); +} + +STATIC CONST UINTN VersionStringSize = 60; + +/** + Function to dump information about EfiDriverSupportedEfiVersion protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +DriverEfiVersionProtocolDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL *DriverEfiVersion; + EFI_STATUS Status; + CHAR16 *RetVal; + + Status = gBS->HandleProtocol( + TheHandle, + &gEfiDriverSupportedEfiVersionProtocolGuid, + (VOID**)&DriverEfiVersion); + + ASSERT_EFI_ERROR(Status); + + RetVal = AllocateZeroPool(VersionStringSize); + if (RetVal != NULL) { + UnicodeSPrint (RetVal, VersionStringSize, L"0x%08x", DriverEfiVersion->FirmwareVersion); + } + return (RetVal); +} +/** + Function to convert device path to string. + + This will allocate the return buffer from boot services pool. + + @param[in] DevPath Pointer to device path instance. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + @param[in] Length Maximum allowed text length of the device path. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +ConvertDevicePathToShortText( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath, + IN CONST BOOLEAN Verbose, + IN CONST UINTN Length + ) +{ + CHAR16 *Temp; + CHAR16 *Temp2; + UINTN Size; + + // + // I cannot decide whether to allow shortcuts here (the second BOOLEAN on the next line) + // + Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE); + if (!Verbose && Temp != NULL && StrLen(Temp) > Length) { + Temp2 = NULL; + Size = 0; + Temp2 = StrnCatGrow(&Temp2, &Size, L"..", 0); + Temp2 = StrnCatGrow(&Temp2, &Size, Temp+(StrLen(Temp) - (Length - 2)), 0); + FreePool(Temp); + Temp = Temp2; + } + return (Temp); +} + +/** + Function to dump protocol information. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + @param[in] Protocol The protocol is needed to dump. + + @retval A pointer to a string containing the information. +**/ +STATIC CHAR16* +EFIAPI +DevicePathProtocolDumpInformationEx ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose, + IN EFI_GUID *Protocol +) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + CHAR16 *DevPathStr; + CHAR16 *DevPathStrTemp; + UINTN Size; + EFI_STATUS Status; + DevPathStr = NULL; + DevPathStrTemp = NULL; + Status = gBS->OpenProtocol(TheHandle, Protocol, (VOID**)&DevPath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status)) { + DevPathStr = ConvertDevicePathToShortText (DevPath, Verbose, 30); + if (Verbose) { + Size = StrSize(DevPathStr) + sizeof(CHAR16) * 2; + DevPathStrTemp = AllocateZeroPool (Size); + if (DevPathStrTemp != NULL) { + StrnCatS (DevPathStrTemp, Size/sizeof(CHAR16), L" ", 2); + StrnCatS (DevPathStrTemp, Size/sizeof(CHAR16), DevPathStr, StrLen (DevPathStr)); + } + FreePool (DevPathStr); + DevPathStr = DevPathStrTemp; + } + gBS->CloseProtocol(TheHandle, Protocol, gImageHandle, NULL); + } + return DevPathStr; +} + +/** + Function to dump information about DevicePath protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +DevicePathProtocolDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + return DevicePathProtocolDumpInformationEx (TheHandle, Verbose, &gEfiDevicePathProtocolGuid); +} + +/** + Function to dump information about LoadedImageDevicePath protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +LoadedImageDevicePathProtocolDumpInformation( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + return DevicePathProtocolDumpInformationEx (TheHandle, Verbose, &gEfiLoadedImageDevicePathProtocolGuid); +} + +/** + Function to dump information about BusSpecificDriverOverride protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +BusSpecificDriverOverrideProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + CHAR16 *GetString; + CHAR16 *RetVal; + CHAR16 *TempRetVal; + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_HANDLE ImageHandle; + UINTN Size; + + if (!Verbose) { + return NULL; + } + Size = 0; + GetString = NULL; + RetVal = NULL; + TempRetVal = NULL; + ImageHandle = 0; + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiBusSpecificDriverOverrideProtocolGuid, + (VOID**)&BusSpecificDriverOverride, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + HandleParsingHiiInit (); + GetString = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_BSDO_DUMP_MAIN), NULL); + if (GetString == NULL) { + return NULL; + } + do { + Status = BusSpecificDriverOverride->GetDriver ( + BusSpecificDriverOverride, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + if(!EFI_ERROR (Status)) { + TempRetVal = CatSPrint ( + TempRetVal, + GetString, + ConvertHandleToHandleIndex (ImageHandle), + ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE) + ); + StrnCatGrow (&RetVal, &Size, TempRetVal, 0); + SHELL_FREE_NON_NULL (TempRetVal); + } + } + } while (!EFI_ERROR (Status)); + + SHELL_FREE_NON_NULL (GetString); + return RetVal; +} + +/** + Function to dump information about BlockIo protocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +BlockIoProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *BlockMedia; + CHAR16 *GetString; + CHAR16 *RetVal; + + if (!Verbose) { + return NULL; + } + GetString = NULL; + RetVal = NULL; + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiBlockIoProtocolGuid, + (VOID**)&BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + BlockMedia = BlockIo->Media; + // + // Per spec: + // The function (ReadBlocks) must return EFI_NO_MEDIA or + // EFI_MEDIA_CHANGED even if LBA, BufferSize, or Buffer are invalid so the caller can probe + // for changes in media state. + // + BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + 0, + NULL + ); + + HandleParsingHiiInit (); + GetString = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_BLOCKIO_INFO), NULL); + if (GetString == NULL) { + return NULL; + } + RetVal = CatSPrint ( + RetVal, + GetString, + BlockMedia->RemovableMedia ? L"Removable " : L"Fixed ", + BlockMedia->MediaPresent ? L"" : L"not-present ", + BlockMedia->MediaId, + BlockMedia->BlockSize, + BlockMedia->LastBlock, + MultU64x32 (BlockMedia->LastBlock + 1, BlockMedia->BlockSize), + BlockMedia->LogicalPartition ? L"partition" : L"raw", + BlockMedia->ReadOnly ? L"ro" : L"rw", + BlockMedia->WriteCaching ? L"cached" : L"!cached" + ); + + SHELL_FREE_NON_NULL (GetString); + return RetVal; +} + +/** + Function to dump information about DebugSupport Protocol. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +DebugSupportProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupport; + CHAR16 *GetString; + CHAR16 *RetVal; + + if (!Verbose) { + return NULL; + } + GetString = NULL; + RetVal = NULL; + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiDebugSupportProtocolGuid, + (VOID**)&DebugSupport, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + HandleParsingHiiInit (); + GetString = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_DEBUGSUPPORT_INFO), NULL); + if (GetString == NULL) { + return NULL; + } + // + // Dump Debug support info + // + switch (DebugSupport->Isa) { + case (IsaIa32): + RetVal = CatSPrint (RetVal, GetString, L"IA-32"); + break; + case (IsaIpf): + RetVal = CatSPrint (RetVal, GetString, L"IPF"); + break; + case (IsaEbc): + RetVal = CatSPrint (RetVal, GetString, L"EBC"); + break; + default: + SHELL_FREE_NON_NULL (GetString); + GetString = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_DEBUGSUPPORT_UNKNOWN), NULL); + RetVal = GetString != NULL ? CatSPrint (RetVal, GetString, DebugSupport->Isa) : NULL; + break; + } + + SHELL_FREE_NON_NULL (GetString); + return RetVal; +} + +/** + Function to dump information about PciIoProtocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has PciRootBridgeIo installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +PciIoProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINTN Index; + CHAR16 *GetString; + CHAR16 *TempRetVal; + CHAR16 *RetVal; + + if (!Verbose) { + return (NULL); + } + RetVal = NULL; + GetString = NULL; + TempRetVal = NULL; + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiPciIoProtocolGuid, + (VOID**)&PciIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) { + return NULL; + } + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); + PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); + HandleParsingHiiInit (); + GetString = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIIO_DUMP_MAIN), NULL); + if (GetString == NULL) { + return NULL; + } + RetVal = CatSPrint ( + NULL, + GetString, + Segment, + Bus, + Device, + Function, + PciIo->RomSize, + PciIo->RomImage, + Pci.Hdr.VendorId, + Pci.Hdr.DeviceId, + Pci.Hdr.ClassCode[0], + Pci.Hdr.ClassCode[1], + Pci.Hdr.ClassCode[2] + ); + for (Index = 0; Index < sizeof (Pci); Index ++) { + if ((Index % 0x10) == 0) { + TempRetVal = CatSPrint (RetVal, L"\r\n %02x", *((UINT8 *) (&Pci) + Index)); + } else { + TempRetVal = CatSPrint (RetVal, L"%02x", *((UINT8 *) (&Pci) + Index)); + } + FreePool (RetVal); + RetVal = TempRetVal; + TempRetVal = NULL; + } + + FreePool(GetString); + return RetVal; +} + +/** + Function to dump information about UsbIoProtocol. + + This will allocate the return buffer from boot services pool. + + @param[in] TheHandle The handle that has PciRootBridgeIo installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A poitner to a string containing the information. +**/ +CHAR16* +EFIAPI +UsbIoProtocolDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDesc; + CHAR16 *GetString; + CHAR16 *RetVal; + + if (!Verbose) { + return (NULL); + } + RetVal = NULL; + GetString = NULL; + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiUsbIoProtocolGuid, + (VOID**)&UsbIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR(Status)) { + return NULL; + } + UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDesc); + HandleParsingHiiInit (); + GetString = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_USBIO_DUMP_MAIN), NULL); + if (GetString == NULL) { + return NULL; + } + RetVal = CatSPrint ( + NULL, + GetString, + InterfaceDesc.InterfaceNumber, + InterfaceDesc.InterfaceClass, + InterfaceDesc.InterfaceSubClass, + InterfaceDesc.InterfaceProtocol + ); + + FreePool (GetString); + return RetVal; +} + +/** + Function to dump information about EfiAdapterInformation Protocol. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +AdapterInformationDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + EFI_ADAPTER_INFORMATION_PROTOCOL *EfiAdptrInfoProtocol; + UINTN InfoTypesBufferCount; + UINTN GuidIndex; + EFI_GUID *InfoTypesBuffer; + CHAR16 *GuidStr; + CHAR16 *TempStr; + CHAR16 *RetVal; + CHAR16 *TempRetVal; + VOID *InformationBlock; + UINTN InformationBlockSize; + + if (!Verbose) { + return (CatSPrint(NULL, L"AdapterInfo")); + } + + InfoTypesBuffer = NULL; + InformationBlock = NULL; + + + Status = gBS->OpenProtocol ( + (EFI_HANDLE) (TheHandle), + &gEfiAdapterInformationProtocolGuid, + (VOID **) &EfiAdptrInfoProtocol, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Get a list of supported information types for this instance of the protocol. + // + Status = EfiAdptrInfoProtocol->GetSupportedTypes ( + EfiAdptrInfoProtocol, + &InfoTypesBuffer, + &InfoTypesBufferCount + ); + RetVal = NULL; + if (EFI_ERROR (Status)) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GET_SUPP_TYPES_FAILED), NULL); + if (TempStr != NULL) { + RetVal = CatSPrint (NULL, TempStr, Status); + } else { + goto ERROR_EXIT; + } + } else { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_SUPP_TYPE_HEADER), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + RetVal = CatSPrint (NULL, TempStr); + SHELL_FREE_NON_NULL (TempStr); + + for (GuidIndex = 0; GuidIndex < InfoTypesBufferCount; GuidIndex++) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GUID_NUMBER), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, (GuidIndex + 1), &InfoTypesBuffer[GuidIndex]); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GUID_STRING), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + + if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoMediaStateGuid)) { + TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoMediaStateGuid"); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoNetworkBootGuid)) { + TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoNetworkBootGuid"); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoSanMacAddressGuid)) { + TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoSanMacAddressGuid"); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) { + TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoUndiIpv6SupportGuid"); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else { + + GuidStr = GetStringNameFromGuid (&InfoTypesBuffer[GuidIndex], NULL); + if (GuidStr == NULL) { + TempRetVal = CatSPrint (RetVal, TempStr, L"UnknownInfoType"); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + + SHELL_FREE_NON_NULL (TempStr); + SHELL_FREE_NON_NULL(GuidStr); + // + // So that we never have to pass this UnknownInfoType to the parsing function "GetInformation" service of AIP + // + continue; + } else { + TempRetVal = CatSPrint (RetVal, TempStr, GuidStr); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL(GuidStr); + } + } + + SHELL_FREE_NON_NULL (TempStr); + + Status = EfiAdptrInfoProtocol->GetInformation ( + EfiAdptrInfoProtocol, + &InfoTypesBuffer[GuidIndex], + &InformationBlock, + &InformationBlockSize + ); + + if (EFI_ERROR (Status)) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GETINFO_FAILED), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, Status); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else { + if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoMediaStateGuid)) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_MEDIA_STATE), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint ( + RetVal, + TempStr, + ((EFI_ADAPTER_INFO_MEDIA_STATE *)InformationBlock)->MediaState, + ((EFI_ADAPTER_INFO_MEDIA_STATE *)InformationBlock)->MediaState + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoNetworkBootGuid)) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_NETWORK_BOOT_INFO), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint ( + RetVal, + TempStr, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv4BootCapablity, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv6BootCapablity, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->FCoeBootCapablity, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->OffloadCapability, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiMpioCapability, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv4Boot, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv6Boot, + ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->FCoeBoot + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoSanMacAddressGuid) == TRUE) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_SAN_MAC_ADDRESS_INFO), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint ( + RetVal, + TempStr, + ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[0], + ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[1], + ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[2], + ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[3], + ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[4], + ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[5] + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoUndiIpv6SupportGuid) == TRUE) { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_UNDI_IPV6_INFO), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + + TempRetVal = CatSPrint ( + RetVal, + TempStr, + ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *)InformationBlock)->Ipv6Support + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } else { + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_UNKNOWN_INFO_TYPE), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, &InfoTypesBuffer[GuidIndex]); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + } + } + SHELL_FREE_NON_NULL (TempStr); + SHELL_FREE_NON_NULL (InformationBlock); + } + } + + SHELL_FREE_NON_NULL (InfoTypesBuffer); + return RetVal; + +ERROR_EXIT: + SHELL_FREE_NON_NULL (RetVal); + SHELL_FREE_NON_NULL (InfoTypesBuffer); + SHELL_FREE_NON_NULL (InformationBlock); + return NULL; +} + +/** + Function to dump information about EFI_FIRMWARE_MANAGEMENT_PROTOCOL Protocol. + + @param[in] TheHandle The handle that has the protocol installed. + @param[in] Verbose TRUE for additional information, FALSE otherwise. + + @retval A pointer to a string containing the information. +**/ +CHAR16* +EFIAPI +FirmwareManagementDumpInformation ( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *EfiFwMgmtProtocol; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo; + EFI_FIRMWARE_IMAGE_DESCRIPTOR_V1 *ImageInfoV1; + EFI_FIRMWARE_IMAGE_DESCRIPTOR_V2 *ImageInfoV2; + UINT64 AttributeSetting; + UINTN ImageInfoSize; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINT32 PackageVersion; + UINT8 DescriptorCount; + UINT8 Index; + UINT8 Index1; + UINT8 ImageCount; + CHAR16 *PackageVersionName; + CHAR16 *TempStr; + CHAR16 *RetVal; + CHAR16 *TempRetVal; + CHAR16 *AttributeSettingStr; + BOOLEAN Found; + BOOLEAN AttributeSupported; + + // + // Initialize local variables + // + ImageCount = 0; + ImageInfoSize = 1; + AttributeSetting = 0; + Found = FALSE; + AttributeSupported = FALSE; + ImageInfo = NULL; + ImageInfoV1 = NULL; + ImageInfoV2 = NULL; + PackageVersionName = NULL; + RetVal = NULL; + TempRetVal = NULL; + TempStr = NULL; + AttributeSettingStr = NULL; + + if (!Verbose) { + return (CatSPrint(NULL, L"FirmwareManagement")); + } + + Status = gBS->OpenProtocol ( + (EFI_HANDLE) (TheHandle), + &gEfiFirmwareManagementProtocolGuid, + (VOID **) &EfiFwMgmtProtocol, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + Status = EfiFwMgmtProtocol->GetImageInfo ( + EfiFwMgmtProtocol, + &ImageInfoSize, + ImageInfo, + &DescriptorVersion, + &DescriptorCount, + &DescriptorSize, + &PackageVersion, + &PackageVersionName + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + ImageInfo = AllocateZeroPool (ImageInfoSize); + + if (ImageInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = EfiFwMgmtProtocol->GetImageInfo ( + EfiFwMgmtProtocol, + &ImageInfoSize, + ImageInfo, + &DescriptorVersion, + &DescriptorCount, + &DescriptorSize, + &PackageVersion, + &PackageVersionName + ); + } + } + + if (EFI_ERROR (Status)) { + goto ERROR_EXIT; + } + + // + // Decode Image Descriptor data only if its version is supported + // + if (DescriptorVersion <= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) { + + if (ImageInfo == NULL) { + goto ERROR_EXIT; + } + + ImageInfoV1 = (EFI_FIRMWARE_IMAGE_DESCRIPTOR_V1 *)ImageInfo; + ImageInfoV2 = (EFI_FIRMWARE_IMAGE_DESCRIPTOR_V2 *)ImageInfo; + + // + // Set ImageInfoSize in return buffer + // + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_INFO_SIZE), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + RetVal = CatSPrint (NULL, TempStr, ImageInfoSize); + SHELL_FREE_NON_NULL (TempStr); + + // + // Set DescriptorVersion in return buffer + // + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_DESCRIPTOR_VERSION), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, DescriptorVersion); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + + // + // Set DescriptorCount in return buffer + // + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_DESCRIPTOR_COUNT), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, DescriptorCount); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + + + // + // Set DescriptorSize in return buffer + // + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_DESCRIPTOR_SIZE), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, DescriptorSize); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + + // + // Set PackageVersion in return buffer + // + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_PACKAGE_VERSION), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, PackageVersion); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + + // + // Set PackageVersionName in return buffer + // + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_PACKAGE_VERSION_NAME), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint (RetVal, TempStr, PackageVersionName); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + + for (Index = 0; Index < DescriptorCount; Index++) { + // + // First check if Attribute is supported + // and generate a string for AttributeSetting field + // + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSupported = FALSE; + AttributeSetting = 0; + if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1) { + if (ImageInfoV1[Index].AttributesSupported != 0x0) { + AttributeSupported = TRUE; + AttributeSetting = ImageInfoV1[Index].AttributesSetting; + } + } else if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2) { + if (ImageInfoV2[Index].AttributesSupported != 0x0) { + AttributeSupported = TRUE; + AttributeSetting = ImageInfoV2[Index].AttributesSetting; + } + } else { + if (ImageInfo[Index].AttributesSupported != 0x0) { + AttributeSupported = TRUE; + AttributeSetting = ImageInfo[Index].AttributesSetting; + } + } + + if (!AttributeSupported) { + AttributeSettingStr = CatSPrint (NULL, L"None"); + } else { + AttributeSettingStr = CatSPrint (NULL, L"("); + + if ((AttributeSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE) != 0x0) { + TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_IMAGE_UPDATABLE"); + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSettingStr = TempRetVal; + } + if ((AttributeSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0x0) { + TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_RESET_REQUIRED"); + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSettingStr = TempRetVal; + } + if ((AttributeSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED) != 0x0) { + TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED"); + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSettingStr = TempRetVal; + } + if ((AttributeSetting & IMAGE_ATTRIBUTE_IN_USE) != 0x0) { + TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_IN_USE"); + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSettingStr = TempRetVal; + } + if ((AttributeSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE) != 0x0) { + TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_UEFI_IMAGE"); + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSettingStr = TempRetVal; + } + TempRetVal = CatSPrint (AttributeSettingStr, L" )"); + SHELL_FREE_NON_NULL (AttributeSettingStr); + AttributeSettingStr = TempRetVal; + } + + if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1) { + if (ImageInfoV1[Index].ImageIndex != 0x0) { + ImageCount++; + } + + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_DESCRIPTOR_INFO_V1), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint ( + RetVal, + TempStr, + Index, + ImageInfoV1[Index].ImageIndex, + &ImageInfoV1[Index].ImageTypeId, + ImageInfoV1[Index].ImageId, + ImageInfoV1[Index].ImageIdName, + ImageInfoV1[Index].Version, + ImageInfoV1[Index].VersionName, + ImageInfoV1[Index].Size, + ImageInfoV1[Index].AttributesSupported, + AttributeSettingStr, + ImageInfoV1[Index].Compatibilities + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + } else if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2) { + if (ImageInfoV2[Index].ImageIndex != 0x0) { + ImageCount++; + } + + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_DESCRIPTOR_INFO_V2), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint ( + RetVal, + TempStr, + Index, + ImageInfoV2[Index].ImageIndex, + &ImageInfoV2[Index].ImageTypeId, + ImageInfoV2[Index].ImageId, + ImageInfoV2[Index].ImageIdName, + ImageInfoV2[Index].Version, + ImageInfoV2[Index].VersionName, + ImageInfoV2[Index].Size, + ImageInfoV2[Index].AttributesSupported, + AttributeSettingStr, + ImageInfoV2[Index].Compatibilities, + ImageInfoV2[Index].LowestSupportedImageVersion + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + } else { + if (ImageInfo[Index].ImageIndex != 0x0) { + ImageCount++; + } + + TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_DESCRIPTOR_INFO), NULL); + if (TempStr == NULL) { + goto ERROR_EXIT; + } + TempRetVal = CatSPrint ( + RetVal, + TempStr, + Index, + ImageInfo[Index].ImageIndex, + &ImageInfo[Index].ImageTypeId, + ImageInfo[Index].ImageId, + ImageInfo[Index].ImageIdName, + ImageInfo[Index].Version, + ImageInfo[Index].VersionName, + ImageInfo[Index].Size, + ImageInfo[Index].AttributesSupported, + AttributeSettingStr, + ImageInfo[Index].Compatibilities, + ImageInfo[Index].LowestSupportedImageVersion, + ImageInfo[Index].LastAttemptVersion, + ImageInfo[Index].LastAttemptStatus, + ImageInfo[Index].HardwareInstance + ); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + SHELL_FREE_NON_NULL (TempStr); + } + } + } + + if (ImageCount > 0) { + for (Index=0; IndexOpenProtocol ( + TheHandle, + &gEfiPartitionInfoProtocolGuid, + (VOID**)&PartitionInfo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + HandleParsingHiiInit (); + + switch (PartitionInfo->Type) { + case PARTITION_TYPE_OTHER: + PartitionType = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_PARTINFO_DUMP_TYPE_OTHER), NULL); + break; + case PARTITION_TYPE_MBR: + PartitionType = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_PARTINFO_DUMP_TYPE_MBR), NULL); + break; + case PARTITION_TYPE_GPT: + PartitionType = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_PARTINFO_DUMP_TYPE_GPT), NULL); + break; + default: + PartitionType = NULL; + break; + } + if (PartitionType == NULL) { + return NULL; + } + + if (PartitionInfo->System == 1) { + EfiSystemPartition = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_PARTINFO_DUMP_EFI_SYS_PART), NULL); + } else { + EfiSystemPartition = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_PARTINFO_DUMP_NOT_EFI_SYS_PART), NULL); + } + if (EfiSystemPartition == NULL) { + SHELL_FREE_NON_NULL (PartitionType); + return NULL; + } + + RetVal = CatSPrint ( + NULL, + L"%s\r\n%s", + PartitionType, + EfiSystemPartition + ); + + SHELL_FREE_NON_NULL (EfiSystemPartition); + SHELL_FREE_NON_NULL (PartitionType); + return RetVal; +} + +// +// Put the information on the NT32 protocol GUIDs here so we are not dependant on the Nt32Pkg +// +#define LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID \ + { \ + 0x58c518b1, 0x76f3, 0x11d4, { 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID \ + { \ + 0x96eb4ad6, 0xa32a, 0x11d4, { 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID \ + { \ + 0xc95a93d, 0xa006, 0x11d4, { 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } +STATIC CONST EFI_GUID WinNtThunkProtocolGuid = LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID; +STATIC CONST EFI_GUID WinNtIoProtocolGuid = LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID; +STATIC CONST EFI_GUID WinNtSerialPortGuid = LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID; + +// +// Deprecated protocols we dont want to link from IntelFrameworkModulePkg +// +#define LOCAL_EFI_ISA_IO_PROTOCOL_GUID \ + { \ + 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } +#define LOCAL_EFI_ISA_ACPI_PROTOCOL_GUID \ + { \ + 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 } \ + } +STATIC CONST EFI_GUID EfiIsaIoProtocolGuid = LOCAL_EFI_ISA_IO_PROTOCOL_GUID; +STATIC CONST EFI_GUID EfiIsaAcpiProtocolGuid = LOCAL_EFI_ISA_ACPI_PROTOCOL_GUID; + + +STATIC CONST GUID_INFO_BLOCK mGuidStringListNT[] = { + {STRING_TOKEN(STR_WINNT_THUNK), (EFI_GUID*)&WinNtThunkProtocolGuid, NULL}, + {STRING_TOKEN(STR_WINNT_DRIVER_IO), (EFI_GUID*)&WinNtIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_WINNT_SERIAL_PORT), (EFI_GUID*)&WinNtSerialPortGuid, NULL}, + {0, NULL, NULL}, +}; + +STATIC CONST GUID_INFO_BLOCK mGuidStringList[] = { + {STRING_TOKEN(STR_LOADED_IMAGE), &gEfiLoadedImageProtocolGuid, LoadedImageProtocolDumpInformation}, + {STRING_TOKEN(STR_DEVICE_PATH), &gEfiDevicePathProtocolGuid, DevicePathProtocolDumpInformation}, + {STRING_TOKEN(STR_IMAGE_PATH), &gEfiLoadedImageDevicePathProtocolGuid, LoadedImageDevicePathProtocolDumpInformation}, + {STRING_TOKEN(STR_DEVICE_PATH_UTIL), &gEfiDevicePathUtilitiesProtocolGuid, NULL}, + {STRING_TOKEN(STR_DEVICE_PATH_TXT), &gEfiDevicePathToTextProtocolGuid, NULL}, + {STRING_TOKEN(STR_DEVICE_PATH_FTXT), &gEfiDevicePathFromTextProtocolGuid, NULL}, + {STRING_TOKEN(STR_DEVICE_PATH_PC), &gEfiPcAnsiGuid, NULL}, + {STRING_TOKEN(STR_DEVICE_PATH_VT100), &gEfiVT100Guid, NULL}, + {STRING_TOKEN(STR_DEVICE_PATH_VT100P), &gEfiVT100PlusGuid, NULL}, + {STRING_TOKEN(STR_DEVICE_PATH_VTUTF8), &gEfiVTUTF8Guid, NULL}, + {STRING_TOKEN(STR_DRIVER_BINDING), &gEfiDriverBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_PLATFORM_OVERRIDE), &gEfiPlatformDriverOverrideProtocolGuid, NULL}, + {STRING_TOKEN(STR_BUS_OVERRIDE), &gEfiBusSpecificDriverOverrideProtocolGuid, BusSpecificDriverOverrideProtocolDumpInformation}, + {STRING_TOKEN(STR_DRIVER_DIAG), &gEfiDriverDiagnosticsProtocolGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_DIAG2), &gEfiDriverDiagnostics2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_CN), &gEfiComponentNameProtocolGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_CN2), &gEfiComponentName2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_PLAT_DRV_CFG), &gEfiPlatformToDriverConfigurationProtocolGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_VERSION), &gEfiDriverSupportedEfiVersionProtocolGuid, DriverEfiVersionProtocolDumpInformation}, + {STRING_TOKEN(STR_TXT_IN), &gEfiSimpleTextInProtocolGuid, NULL}, + {STRING_TOKEN(STR_TXT_IN_EX), &gEfiSimpleTextInputExProtocolGuid, NULL}, + {STRING_TOKEN(STR_TXT_OUT), &gEfiSimpleTextOutProtocolGuid, TxtOutProtocolDumpInformation}, + {STRING_TOKEN(STR_SIM_POINTER), &gEfiSimplePointerProtocolGuid, NULL}, + {STRING_TOKEN(STR_ABS_POINTER), &gEfiAbsolutePointerProtocolGuid, NULL}, + {STRING_TOKEN(STR_SERIAL_IO), &gEfiSerialIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_GRAPHICS_OUTPUT), &gEfiGraphicsOutputProtocolGuid, GraphicsOutputProtocolDumpInformation}, + {STRING_TOKEN(STR_EDID_DISCOVERED), &gEfiEdidDiscoveredProtocolGuid, EdidDiscoveredProtocolDumpInformation}, + {STRING_TOKEN(STR_EDID_ACTIVE), &gEfiEdidActiveProtocolGuid, EdidActiveProtocolDumpInformation}, + {STRING_TOKEN(STR_EDID_OVERRIDE), &gEfiEdidOverrideProtocolGuid, NULL}, + {STRING_TOKEN(STR_CON_IN), &gEfiConsoleInDeviceGuid, NULL}, + {STRING_TOKEN(STR_CON_OUT), &gEfiConsoleOutDeviceGuid, NULL}, + {STRING_TOKEN(STR_STD_ERR), &gEfiStandardErrorDeviceGuid, NULL}, + {STRING_TOKEN(STR_LOAD_FILE), &gEfiLoadFileProtocolGuid, NULL}, + {STRING_TOKEN(STR_LOAD_FILE2), &gEfiLoadFile2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_SIMPLE_FILE_SYS), &gEfiSimpleFileSystemProtocolGuid, NULL}, + {STRING_TOKEN(STR_TAPE_IO), &gEfiTapeIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_DISK_IO), &gEfiDiskIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_BLK_IO), &gEfiBlockIoProtocolGuid, BlockIoProtocolDumpInformation}, + {STRING_TOKEN(STR_UC), &gEfiUnicodeCollationProtocolGuid, NULL}, + {STRING_TOKEN(STR_UC2), &gEfiUnicodeCollation2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCIRB_IO), &gEfiPciRootBridgeIoProtocolGuid, PciRootBridgeIoDumpInformation}, + {STRING_TOKEN(STR_PCI_IO), &gEfiPciIoProtocolGuid, PciIoProtocolDumpInformation}, + {STRING_TOKEN(STR_SCSI_PT), &gEfiScsiPassThruProtocolGuid, NULL}, + {STRING_TOKEN(STR_SCSI_IO), &gEfiScsiIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_SCSI_PT_EXT), &gEfiExtScsiPassThruProtocolGuid, NULL}, + {STRING_TOKEN(STR_ISCSI), &gEfiIScsiInitiatorNameProtocolGuid, NULL}, + {STRING_TOKEN(STR_USB_IO), &gEfiUsbIoProtocolGuid, UsbIoProtocolDumpInformation}, + {STRING_TOKEN(STR_USB_HC), &gEfiUsbHcProtocolGuid, NULL}, + {STRING_TOKEN(STR_USB_HC2), &gEfiUsb2HcProtocolGuid, NULL}, + {STRING_TOKEN(STR_DEBUG_SUPPORT), &gEfiDebugSupportProtocolGuid, DebugSupportProtocolDumpInformation}, + {STRING_TOKEN(STR_DEBUG_PORT), &gEfiDebugPortProtocolGuid, NULL}, + {STRING_TOKEN(STR_DECOMPRESS), &gEfiDecompressProtocolGuid, NULL}, + {STRING_TOKEN(STR_ACPI_TABLE), &gEfiAcpiTableProtocolGuid, NULL}, + {STRING_TOKEN(STR_EBC_INTERPRETER), &gEfiEbcProtocolGuid, NULL}, + {STRING_TOKEN(STR_SNP), &gEfiSimpleNetworkProtocolGuid, NULL}, + {STRING_TOKEN(STR_NII), &gEfiNetworkInterfaceIdentifierProtocolGuid, NULL}, + {STRING_TOKEN(STR_NII_31), &gEfiNetworkInterfaceIdentifierProtocolGuid_31, NULL}, + {STRING_TOKEN(STR_PXE_BC), &gEfiPxeBaseCodeProtocolGuid, NULL}, + {STRING_TOKEN(STR_PXE_CB), &gEfiPxeBaseCodeCallbackProtocolGuid, NULL}, + {STRING_TOKEN(STR_BIS), &gEfiBisProtocolGuid, NULL}, + {STRING_TOKEN(STR_MNP_SB), &gEfiManagedNetworkServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_MNP), &gEfiManagedNetworkProtocolGuid, NULL}, + {STRING_TOKEN(STR_ARP_SB), &gEfiArpServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_ARP), &gEfiArpProtocolGuid, NULL}, + {STRING_TOKEN(STR_DHCPV4_SB), &gEfiDhcp4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_DHCPV4), &gEfiDhcp4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_TCPV4_SB), &gEfiTcp4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_TCPV4), &gEfiTcp4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_IPV4_SB), &gEfiIp4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_IPV4), &gEfiIp4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_IPV4_CFG), &gEfiIp4ConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_IPV4_CFG2), &gEfiIp4Config2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_UDPV4_SB), &gEfiUdp4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_UDPV4), &gEfiUdp4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_MTFTPV4_SB), &gEfiMtftp4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_MTFTPV4), &gEfiMtftp4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_AUTH_INFO), &gEfiAuthenticationInfoProtocolGuid, NULL}, + {STRING_TOKEN(STR_HASH_SB), &gEfiHashServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_HASH), &gEfiHashProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_FONT), &gEfiHiiFontProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_STRING), &gEfiHiiStringProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_IMAGE), &gEfiHiiImageProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_DATABASE), &gEfiHiiDatabaseProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_CONFIG_ROUT), &gEfiHiiConfigRoutingProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_CONFIG_ACC), &gEfiHiiConfigAccessProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_FORM_BROWSER2), &gEfiFormBrowser2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_FAM_OVERRIDE), &gEfiDriverFamilyOverrideProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCD), &gPcdProtocolGuid, NULL}, + {STRING_TOKEN(STR_TCG), &gEfiTcgProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_PACKAGE_LIST), &gEfiHiiPackageListProtocolGuid, NULL}, + +// +// the ones under this are deprecated by the current UEFI Spec, but may be found anyways... +// + {STRING_TOKEN(STR_SHELL_INTERFACE), &gEfiShellInterfaceGuid, NULL}, + {STRING_TOKEN(STR_SHELL_ENV2), &gEfiShellEnvironment2Guid, NULL}, + {STRING_TOKEN(STR_SHELL_ENV), &gEfiShellEnvironment2Guid, NULL}, + {STRING_TOKEN(STR_DEVICE_IO), &gEfiDeviceIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_UGA_DRAW), &gEfiUgaDrawProtocolGuid, NULL}, + {STRING_TOKEN(STR_UGA_IO), &gEfiUgaIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_ESP), &gEfiPartTypeSystemPartGuid, NULL}, + {STRING_TOKEN(STR_GPT_NBR), &gEfiPartTypeLegacyMbrGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_CONFIG), &gEfiDriverConfigurationProtocolGuid, NULL}, + {STRING_TOKEN(STR_DRIVER_CONFIG2), &gEfiDriverConfiguration2ProtocolGuid, NULL}, + +// +// these are using local (non-global) definitions to reduce package dependancy. +// + {STRING_TOKEN(STR_ISA_IO), (EFI_GUID*)&EfiIsaIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_ISA_ACPI), (EFI_GUID*)&EfiIsaAcpiProtocolGuid, NULL}, + +// +// the ones under this are GUID identified structs, not protocols +// + {STRING_TOKEN(STR_FILE_INFO), &gEfiFileInfoGuid, NULL}, + {STRING_TOKEN(STR_FILE_SYS_INFO), &gEfiFileSystemInfoGuid, NULL}, + +// +// the ones under this are misc GUIDS. +// + {STRING_TOKEN(STR_EFI_GLOBAL_VARIABLE), &gEfiGlobalVariableGuid, NULL}, + +// +// UEFI 2.2 +// + {STRING_TOKEN(STR_IP6_SB), &gEfiIp6ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_IP6), &gEfiIp6ProtocolGuid, NULL}, + {STRING_TOKEN(STR_IP6_CONFIG), &gEfiIp6ConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_MTFTP6_SB), &gEfiMtftp6ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_MTFTP6), &gEfiMtftp6ProtocolGuid, NULL}, + {STRING_TOKEN(STR_DHCP6_SB), &gEfiDhcp6ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_DHCP6), &gEfiDhcp6ProtocolGuid, NULL}, + {STRING_TOKEN(STR_UDP6_SB), &gEfiUdp6ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_UDP6), &gEfiUdp6ProtocolGuid, NULL}, + {STRING_TOKEN(STR_TCP6_SB), &gEfiTcp6ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_TCP6), &gEfiTcp6ProtocolGuid, NULL}, + {STRING_TOKEN(STR_VLAN_CONFIG), &gEfiVlanConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_EAP), &gEfiEapProtocolGuid, NULL}, + {STRING_TOKEN(STR_EAP_MGMT), &gEfiEapManagementProtocolGuid, NULL}, + {STRING_TOKEN(STR_FTP4_SB), &gEfiFtp4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_FTP4), &gEfiFtp4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_IP_SEC_CONFIG), &gEfiIpSecConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_DH), &gEfiDriverHealthProtocolGuid, NULL}, + {STRING_TOKEN(STR_DEF_IMG_LOAD), &gEfiDeferredImageLoadProtocolGuid, NULL}, + {STRING_TOKEN(STR_USER_CRED), &gEfiUserCredentialProtocolGuid, NULL}, + {STRING_TOKEN(STR_USER_MNGR), &gEfiUserManagerProtocolGuid, NULL}, + {STRING_TOKEN(STR_ATA_PASS_THRU), &gEfiAtaPassThruProtocolGuid, NULL}, + +// +// UEFI 2.3 +// + {STRING_TOKEN(STR_FW_MGMT), &gEfiFirmwareManagementProtocolGuid, FirmwareManagementDumpInformation}, + {STRING_TOKEN(STR_IP_SEC), &gEfiIpSecProtocolGuid, NULL}, + {STRING_TOKEN(STR_IP_SEC2), &gEfiIpSec2ProtocolGuid, NULL}, + +// +// UEFI 2.3.1 +// + {STRING_TOKEN(STR_KMS), &gEfiKmsProtocolGuid, NULL}, + {STRING_TOKEN(STR_BLK_IO2), &gEfiBlockIo2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_SSC), &gEfiStorageSecurityCommandProtocolGuid, NULL}, + {STRING_TOKEN(STR_UCRED2), &gEfiUserCredential2ProtocolGuid, NULL}, + +// +// UEFI 2.4 +// + {STRING_TOKEN(STR_DISK_IO2), &gEfiDiskIo2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_ADAPTER_INFO), &gEfiAdapterInformationProtocolGuid, AdapterInformationDumpInformation}, + +// +// UEFI2.5 +// + {STRING_TOKEN(STR_TLS_SB), &gEfiTlsServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_TLS), &gEfiTlsProtocolGuid, NULL}, + {STRING_TOKEN(STR_TLS_CONFIG), &gEfiTlsConfigurationProtocolGuid, NULL}, + {STRING_TOKEN(STR_SUPPLICANT_SB), &gEfiSupplicantServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_SUPPLICANT), &gEfiSupplicantProtocolGuid, NULL}, + +// +// UEFI2.6 +// + {STRING_TOKEN(STR_WIFI2), &gEfiWiFi2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_RAMDISK), &gEfiRamDiskProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_ID), &gEfiHiiImageDecoderProtocolGuid, NULL}, + {STRING_TOKEN(STR_HII_IE), &gEfiHiiImageExProtocolGuid, NULL}, + {STRING_TOKEN(STR_SD_MPT), &gEfiSdMmcPassThruProtocolGuid, NULL}, + {STRING_TOKEN(STR_ERASE_BLOCK), &gEfiEraseBlockProtocolGuid, NULL}, + +// +// UEFI2.7 +// + {STRING_TOKEN(STR_BLUETOOTH_ATTR), &gEfiBluetoothAttributeProtocolGuid, NULL}, + {STRING_TOKEN(STR_BLUETOOTH_ATTR_SB), &gEfiBluetoothAttributeServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_BLUETOOTH_LE_CONFIG), &gEfiBluetoothLeConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_UFS_DEV_CONFIG), &gEfiUfsDeviceConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_HTTP_BOOT_CALL), &gEfiHttpBootCallbackProtocolGuid, NULL}, + {STRING_TOKEN(STR_RESET_NOTI), &gEfiResetNotificationProtocolGuid, NULL}, + {STRING_TOKEN(STR_PARTITION_INFO), &gEfiPartitionInfoProtocolGuid, PartitionInfoProtocolDumpInformation}, + {STRING_TOKEN(STR_HII_POPUP), &gEfiHiiPopupProtocolGuid, NULL}, + +// +// PI Spec ones +// + {STRING_TOKEN(STR_IDE_CONT_INIT), &gEfiIdeControllerInitProtocolGuid, NULL}, + {STRING_TOKEN(STR_DISK_INFO), &gEfiDiskInfoProtocolGuid, NULL}, + +// +// PI Spec 1.0 +// + {STRING_TOKEN(STR_BDS_ARCH), &gEfiBdsArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_CPU_ARCH), &gEfiCpuArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MET_ARCH), &gEfiMetronomeArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MON_ARCH), &gEfiMonotonicCounterArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_RTC_ARCH), &gEfiRealTimeClockArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_RESET_ARCH), &gEfiResetArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_RT_ARCH), &gEfiRuntimeArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_SEC_ARCH), &gEfiSecurityArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_TIMER_ARCH), &gEfiTimerArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_VAR_ARCH), &gEfiVariableWriteArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_V_ARCH), &gEfiVariableArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_SECP), &gEfiSecurityPolicyProtocolGuid, NULL}, + {STRING_TOKEN(STR_WDT_ARCH), &gEfiWatchdogTimerArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_SCR), &gEfiStatusCodeRuntimeProtocolGuid, NULL}, + {STRING_TOKEN(STR_SMB_HC), &gEfiSmbusHcProtocolGuid, NULL}, + {STRING_TOKEN(STR_FV_2), &gEfiFirmwareVolume2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_FV_BLOCK), &gEfiFirmwareVolumeBlockProtocolGuid, NULL}, + {STRING_TOKEN(STR_CAP_ARCH), &gEfiCapsuleArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MP_SERVICE), &gEfiMpServiceProtocolGuid, NULL}, + {STRING_TOKEN(STR_HBRAP), &gEfiPciHostBridgeResourceAllocationProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCIP), &gEfiPciPlatformProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCIO), &gEfiPciOverrideProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCIE), &gEfiPciEnumerationCompleteProtocolGuid, NULL}, + {STRING_TOKEN(STR_IPCID), &gEfiIncompatiblePciDeviceSupportProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCIHPI), &gEfiPciHotPlugInitProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCIHPR), &gEfiPciHotPlugRequestProtocolGuid, NULL}, + {STRING_TOKEN(STR_SMBIOS), &gEfiSmbiosProtocolGuid, NULL}, + {STRING_TOKEN(STR_S3_SAVE), &gEfiS3SaveStateProtocolGuid, NULL}, + {STRING_TOKEN(STR_S3_S_SMM), &gEfiS3SmmSaveStateProtocolGuid, NULL}, + {STRING_TOKEN(STR_RSC), &gEfiRscHandlerProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_RSC), &gEfiSmmRscHandlerProtocolGuid, NULL}, + {STRING_TOKEN(STR_ACPI_SDT), &gEfiAcpiSdtProtocolGuid, NULL}, + {STRING_TOKEN(STR_SIO), &gEfiSioProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_CPU2), &gEfiSmmCpuIo2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_BASE2), &gEfiSmmBase2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_ACC_2), &gEfiSmmAccess2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_CON_2), &gEfiSmmControl2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_CONFIG), &gEfiSmmConfigurationProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_RTL), &gEfiSmmReadyToLockProtocolGuid, NULL}, + {STRING_TOKEN(STR_DS_RTL), &gEfiDxeSmmReadyToLockProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_COMM), &gEfiSmmCommunicationProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_STAT), &gEfiSmmStatusCodeProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_CPU), &gEfiSmmCpuProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_PCIRBIO), &gEfiSmmPciRootBridgeIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_SWD), &gEfiSmmSwDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_SXD), &gEfiSmmSxDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_PTD2), &gEfiSmmPeriodicTimerDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_UD2), &gEfiSmmUsbDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_GD2), &gEfiSmmGpiDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_SBD2), &gEfiSmmStandbyButtonDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_PBD2), &gEfiSmmPowerButtonDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_S_ITD2), &gEfiSmmIoTrapDispatch2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_PCD), &gEfiPcdProtocolGuid, NULL}, + {STRING_TOKEN(STR_FVB2), &gEfiFirmwareVolumeBlock2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_CPUIO2), &gEfiCpuIo2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_LEGACY_R2), &gEfiLegacyRegion2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_SAL_MIP), &gEfiSalMcaInitPmiProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_BS), &gEfiExtendedSalBootServiceProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_BIO), &gEfiExtendedSalBaseIoServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_STALL), &gEfiExtendedSalStallServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_RTC), &gEfiExtendedSalRtcServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_VS), &gEfiExtendedSalVariableServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_MTC), &gEfiExtendedSalMtcServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_RESET), &gEfiExtendedSalResetServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_SC), &gEfiExtendedSalStatusCodeServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_FBS), &gEfiExtendedSalFvBlockServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_MP), &gEfiExtendedSalMpServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_PAL), &gEfiExtendedSalPalServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_BASE), &gEfiExtendedSalBaseServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_MCA), &gEfiExtendedSalMcaServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_PCI), &gEfiExtendedSalPciServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_CACHE), &gEfiExtendedSalCacheServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_ES_MCA_LOG), &gEfiExtendedSalMcaLogServicesProtocolGuid, NULL}, + {STRING_TOKEN(STR_S2ARCH), &gEfiSecurity2ArchProtocolGuid, NULL}, + {STRING_TOKEN(STR_EODXE), &gEfiSmmEndOfDxeProtocolGuid, NULL}, + {STRING_TOKEN(STR_ISAHC), &gEfiIsaHcProtocolGuid, NULL}, + {STRING_TOKEN(STR_ISAHC_B), &gEfiIsaHcServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_SIO_C), &gEfiSioControlProtocolGuid, NULL}, + {STRING_TOKEN(STR_GET_PCD), &gEfiGetPcdInfoProtocolGuid, NULL}, + {STRING_TOKEN(STR_I2C_M), &gEfiI2cMasterProtocolGuid, NULL}, + {STRING_TOKEN(STR_I2CIO), &gEfiI2cIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_I2CEN), &gEfiI2cEnumerateProtocolGuid, NULL}, + {STRING_TOKEN(STR_I2C_H), &gEfiI2cHostProtocolGuid, NULL}, + {STRING_TOKEN(STR_I2C_BCM), &gEfiI2cBusConfigurationManagementProtocolGuid, NULL}, + {STRING_TOKEN(STR_TCG2), &gEfiTcg2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_TIMESTAMP), &gEfiTimestampProtocolGuid, NULL}, + {STRING_TOKEN(STR_RNG), &gEfiRngProtocolGuid, NULL}, + {STRING_TOKEN(STR_NVMEPT), &gEfiNvmExpressPassThruProtocolGuid, NULL}, + {STRING_TOKEN(STR_H2_SB), &gEfiHash2ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_HASH2), &gEfiHash2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_BIO_C), &gEfiBlockIoCryptoProtocolGuid, NULL}, + {STRING_TOKEN(STR_SCR), &gEfiSmartCardReaderProtocolGuid, NULL}, + {STRING_TOKEN(STR_SCE), &gEfiSmartCardEdgeProtocolGuid, NULL}, + {STRING_TOKEN(STR_USB_FIO), &gEfiUsbFunctionIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_BC_HC), &gEfiBluetoothHcProtocolGuid, NULL}, + {STRING_TOKEN(STR_BC_IO_SB), &gEfiBluetoothIoServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_BC_IO), &gEfiBluetoothIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_BC_C), &gEfiBluetoothConfigProtocolGuid, NULL}, + {STRING_TOKEN(STR_REG_EXP), &gEfiRegularExpressionProtocolGuid, NULL}, + {STRING_TOKEN(STR_B_MGR_P), &gEfiBootManagerPolicyProtocolGuid, NULL}, + {STRING_TOKEN(STR_CKH), &gEfiConfigKeywordHandlerProtocolGuid, NULL}, + {STRING_TOKEN(STR_WIFI), &gEfiWiFiProtocolGuid, NULL}, + {STRING_TOKEN(STR_EAP_M), &gEfiEapManagement2ProtocolGuid, NULL}, + {STRING_TOKEN(STR_EAP_C), &gEfiEapConfigurationProtocolGuid, NULL}, + {STRING_TOKEN(STR_PKCS7), &gEfiPkcs7VerifyProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_DNS4_SB), &gEfiDns4ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_DNS4), &gEfiDns4ProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_DNS6_SB), &gEfiDns6ServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_DNS6), &gEfiDns6ProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_HTTP_SB), &gEfiHttpServiceBindingProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_HTTP), &gEfiHttpProtocolGuid, NULL}, + {STRING_TOKEN(STR_NET_HTTP_U), &gEfiHttpUtilitiesProtocolGuid, NULL}, + {STRING_TOKEN(STR_REST), &gEfiRestProtocolGuid, NULL}, + +// +// PI 1.5 +// + {STRING_TOKEN(STR_MM_EOD), &gEfiMmEndOfDxeProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_ITD), &gEfiMmIoTrapDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_PBD), &gEfiMmPowerButtonDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_SBD), &gEfiMmStandbyButtonDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_GD), &gEfiMmGpiDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_UD), &gEfiMmUsbDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_PTD), &gEfiMmPeriodicTimerDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_SXD), &gEfiMmSxDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_SWD), &gEfiMmSwDispatchProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_PRBI), &gEfiMmPciRootBridgeIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_CPU), &gEfiMmCpuProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_STACODE), &gEfiMmStatusCodeProtocolGuid, NULL}, + {STRING_TOKEN(STR_DXEMM_RTL), &gEfiDxeMmReadyToLockProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_CONFIG), &gEfiMmConfigurationProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_RTL), &gEfiMmReadyToLockProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_CONTROL), &gEfiMmControlProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_ACCESS), &gEfiMmAccessProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_BASE), &gEfiMmBaseProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_CPUIO), &gEfiMmCpuIoProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_RH), &gEfiMmRscHandlerProtocolGuid, NULL}, + {STRING_TOKEN(STR_MM_COM), &gEfiMmCommunicationProtocolGuid, NULL}, + +// +// UEFI Shell Spec 2.0 +// + {STRING_TOKEN(STR_SHELL_PARAMETERS), &gEfiShellParametersProtocolGuid, NULL}, + {STRING_TOKEN(STR_SHELL), &gEfiShellProtocolGuid, NULL}, + +// +// UEFI Shell Spec 2.1 +// + {STRING_TOKEN(STR_SHELL_DYNAMIC), &gEfiShellDynamicCommandProtocolGuid, NULL}, + +// +// Misc +// + {STRING_TOKEN(STR_PCDINFOPROT), &gGetPcdInfoProtocolGuid, NULL}, + +// +// terminator +// + {0, NULL, NULL}, +}; + +/** + Function to get the node for a protocol or struct from it's GUID. + + if Guid is NULL, then ASSERT. + + @param[in] Guid The GUID to look for the name of. + + @return The node. +**/ +CONST GUID_INFO_BLOCK * +InternalShellGetNodeFromGuid( + IN CONST EFI_GUID* Guid + ) +{ + CONST GUID_INFO_BLOCK *ListWalker; + UINTN LoopCount; + + ASSERT(Guid != NULL); + + for (LoopCount = 0, ListWalker = mGuidList; mGuidList != NULL && LoopCount < mGuidListCount; LoopCount++, ListWalker++) { + if (CompareGuid(ListWalker->GuidId, Guid)) { + return (ListWalker); + } + } + + if (PcdGetBool(PcdShellIncludeNtGuids)) { + for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) { + if (CompareGuid(ListWalker->GuidId, Guid)) { + return (ListWalker); + } + } + } + for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) { + if (CompareGuid(ListWalker->GuidId, Guid)) { + return (ListWalker); + } + } + return (NULL); +} + +/** +Function to add a new GUID/Name mapping. + +@param[in] Guid The Guid +@param[in] NameID The STRING id of the HII string to use +@param[in] DumpFunc The pointer to the dump function + + +@retval EFI_SUCCESS The operation was sucessful +@retval EFI_OUT_OF_RESOURCES A memory allocation failed +@retval EFI_INVALID_PARAMETER Guid NameId was invalid +**/ +EFI_STATUS +InsertNewGuidNameMapping( + IN CONST EFI_GUID *Guid, + IN CONST EFI_STRING_ID NameID, + IN CONST DUMP_PROTOCOL_INFO DumpFunc OPTIONAL + ) +{ + ASSERT(Guid != NULL); + ASSERT(NameID != 0); + + mGuidList = ReallocatePool(mGuidListCount * sizeof(GUID_INFO_BLOCK), mGuidListCount+1 * sizeof(GUID_INFO_BLOCK), mGuidList); + if (mGuidList == NULL) { + mGuidListCount = 0; + return (EFI_OUT_OF_RESOURCES); + } + mGuidListCount++; + + mGuidList[mGuidListCount - 1].GuidId = AllocateCopyPool(sizeof(EFI_GUID), Guid); + mGuidList[mGuidListCount - 1].StringId = NameID; + mGuidList[mGuidListCount - 1].DumpInfo = DumpFunc; + + if (mGuidList[mGuidListCount - 1].GuidId == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + return (EFI_SUCCESS); +} + +/** + Function to add a new GUID/Name mapping. + + This cannot overwrite an existing mapping. + + @param[in] Guid The Guid + @param[in] TheName The Guid's name + @param[in] Lang RFC4646 language code list or NULL + + @retval EFI_SUCCESS The operation was sucessful + @retval EFI_ACCESS_DENIED There was a duplicate + @retval EFI_OUT_OF_RESOURCES A memory allocation failed + @retval EFI_INVALID_PARAMETER Guid or TheName was NULL +**/ +EFI_STATUS +EFIAPI +AddNewGuidNameMapping( + IN CONST EFI_GUID *Guid, + IN CONST CHAR16 *TheName, + IN CONST CHAR8 *Lang OPTIONAL + ) +{ + EFI_STRING_ID NameID; + + HandleParsingHiiInit(); + + if (Guid == NULL || TheName == NULL){ + return (EFI_INVALID_PARAMETER); + } + + if ((InternalShellGetNodeFromGuid(Guid)) != NULL) { + return (EFI_ACCESS_DENIED); + } + + NameID = HiiSetString(mHandleParsingHiiHandle, 0, (CHAR16*)TheName, Lang); + if (NameID == 0) { + return (EFI_OUT_OF_RESOURCES); + } + + return (InsertNewGuidNameMapping(Guid, NameID, NULL)); +} + +/** + Function to get the name of a protocol or struct from it's GUID. + + if Guid is NULL, then ASSERT. + + @param[in] Guid The GUID to look for the name of. + @param[in] Lang The language to use. + + @return pointer to string of the name. The caller + is responsible to free this memory. +**/ +CHAR16* +EFIAPI +GetStringNameFromGuid( + IN CONST EFI_GUID *Guid, + IN CONST CHAR8 *Lang OPTIONAL + ) +{ + CONST GUID_INFO_BLOCK *Id; + + HandleParsingHiiInit(); + + Id = InternalShellGetNodeFromGuid(Guid); + if (Id == NULL) { + return NULL; + } + return HiiGetString (mHandleParsingHiiHandle, Id->StringId, Lang); +} + +/** + Function to dump protocol information from a handle. + + This function will return a allocated string buffer containing the + information. The caller is responsible for freeing the memory. + + If Guid is NULL, ASSERT(). + If TheHandle is NULL, ASSERT(). + + @param[in] TheHandle The handle to dump information from. + @param[in] Guid The GUID of the protocol to dump. + @param[in] Verbose TRUE for extra info. FALSE otherwise. + + @return The pointer to string. + @retval NULL An error was encountered. +**/ +CHAR16* +EFIAPI +GetProtocolInformationDump( + IN CONST EFI_HANDLE TheHandle, + IN CONST EFI_GUID *Guid, + IN CONST BOOLEAN Verbose + ) +{ + CONST GUID_INFO_BLOCK *Id; + + ASSERT(TheHandle != NULL); + ASSERT(Guid != NULL); + + if (TheHandle == NULL || Guid == NULL) { + return (NULL); + } + + Id = InternalShellGetNodeFromGuid(Guid); + if (Id != NULL && Id->DumpInfo != NULL) { + return (Id->DumpInfo(TheHandle, Verbose)); + } + return (NULL); +} + +/** + Function to get the Guid for a protocol or struct based on it's string name. + + do not modify the returned Guid. + + @param[in] Name The pointer to the string name. + @param[in] Lang The pointer to the language code. + @param[out] Guid The pointer to the Guid. + + @retval EFI_SUCCESS The operation was sucessful. +**/ +EFI_STATUS +EFIAPI +GetGuidFromStringName( + IN CONST CHAR16 *Name, + IN CONST CHAR8 *Lang OPTIONAL, + OUT EFI_GUID **Guid + ) +{ + CONST GUID_INFO_BLOCK *ListWalker; + CHAR16 *String; + UINTN LoopCount; + + HandleParsingHiiInit(); + + ASSERT(Guid != NULL); + if (Guid == NULL) { + return (EFI_INVALID_PARAMETER); + } + *Guid = NULL; + + if (PcdGetBool(PcdShellIncludeNtGuids)) { + for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) { + String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang); + if (Name != NULL && String != NULL && StringNoCaseCompare (&Name, &String) == 0) { + *Guid = ListWalker->GuidId; + } + SHELL_FREE_NON_NULL(String); + if (*Guid != NULL) { + return (EFI_SUCCESS); + } + } + } + for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) { + String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang); + if (Name != NULL && String != NULL && StringNoCaseCompare (&Name, &String) == 0) { + *Guid = ListWalker->GuidId; + } + SHELL_FREE_NON_NULL(String); + if (*Guid != NULL) { + return (EFI_SUCCESS); + } + } + + for (LoopCount = 0, ListWalker = mGuidList; mGuidList != NULL && LoopCount < mGuidListCount; LoopCount++, ListWalker++) { + String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang); + if (Name != NULL && String != NULL && StringNoCaseCompare (&Name, &String) == 0) { + *Guid = ListWalker->GuidId; + } + SHELL_FREE_NON_NULL(String); + if (*Guid != NULL) { + return (EFI_SUCCESS); + } + } + + return (EFI_NOT_FOUND); +} + +/** + Get best support language for this driver. + + First base on the user input language to search, second base on the current + platform used language to search, third get the first language from the + support language list. The caller need to free the buffer of the best language. + + @param[in] SupportedLanguages The support languages for this driver. + @param[in] InputLanguage The user input language. + @param[in] Iso639Language Whether get language for ISO639. + + @return The best support language for this driver. +**/ +CHAR8 * +EFIAPI +GetBestLanguageForDriver ( + IN CONST CHAR8 *SupportedLanguages, + IN CONST CHAR8 *InputLanguage, + IN BOOLEAN Iso639Language + ) +{ + CHAR8 *LanguageVariable; + CHAR8 *BestLanguage; + + GetVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", &gEfiGlobalVariableGuid, (VOID**)&LanguageVariable, NULL); + + BestLanguage = GetBestLanguage( + SupportedLanguages, + Iso639Language, + (InputLanguage != NULL) ? InputLanguage : "", + (LanguageVariable != NULL) ? LanguageVariable : "", + SupportedLanguages, + NULL + ); + + if (LanguageVariable != NULL) { + FreePool (LanguageVariable); + } + + return BestLanguage; +} + +/** + Function to retrieve the driver name (if possible) from the ComponentName or + ComponentName2 protocol + + @param[in] TheHandle The driver handle to get the name of. + @param[in] Language The language to use. + + @retval NULL The name could not be found. + @return A pointer to the string name. Do not de-allocate the memory. +**/ +CONST CHAR16* +EFIAPI +GetStringNameFromHandle( + IN CONST EFI_HANDLE TheHandle, + IN CONST CHAR8 *Language + ) +{ + EFI_COMPONENT_NAME2_PROTOCOL *CompNameStruct; + EFI_STATUS Status; + CHAR16 *RetVal; + CHAR8 *BestLang; + + BestLang = NULL; + + Status = gBS->OpenProtocol( + TheHandle, + &gEfiComponentName2ProtocolGuid, + (VOID**)&CompNameStruct, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status)) { + BestLang = GetBestLanguageForDriver (CompNameStruct->SupportedLanguages, Language, FALSE); + Status = CompNameStruct->GetDriverName(CompNameStruct, BestLang, &RetVal); + if (BestLang != NULL) { + FreePool (BestLang); + BestLang = NULL; + } + if (!EFI_ERROR(Status)) { + return (RetVal); + } + } + Status = gBS->OpenProtocol( + TheHandle, + &gEfiComponentNameProtocolGuid, + (VOID**)&CompNameStruct, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status)) { + BestLang = GetBestLanguageForDriver (CompNameStruct->SupportedLanguages, Language, FALSE); + Status = CompNameStruct->GetDriverName(CompNameStruct, BestLang, &RetVal); + if (BestLang != NULL) { + FreePool (BestLang); + } + if (!EFI_ERROR(Status)) { + return (RetVal); + } + } + return (NULL); +} + +/** + Function to initialize the file global mHandleList object for use in + vonverting handles to index and index to handle. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +InternalShellInitHandleList( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + HANDLE_LIST *ListWalker; + + if (mHandleList.NextIndex != 0) { + return EFI_SUCCESS; + } + InitializeListHead(&mHandleList.List.Link); + mHandleList.NextIndex = 1; + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + return (Status); + } + for (mHandleList.NextIndex = 1 ; mHandleList.NextIndex <= HandleCount ; mHandleList.NextIndex++){ + ListWalker = AllocateZeroPool(sizeof(HANDLE_LIST)); + if (ListWalker != NULL) { + ListWalker->TheHandle = HandleBuffer[mHandleList.NextIndex - 1]; + ListWalker->TheIndex = mHandleList.NextIndex; + InsertTailList (&mHandleList.List.Link, &ListWalker->Link); + } + } + FreePool(HandleBuffer); + return (EFI_SUCCESS); +} + +/** + Function to retrieve the human-friendly index of a given handle. If the handle + does not have a index one will be automatically assigned. The index value is valid + until the termination of the shell application. + + @param[in] TheHandle The handle to retrieve an index for. + + @retval 0 A memory allocation failed. + @return The index of the handle. + +**/ +UINTN +EFIAPI +ConvertHandleToHandleIndex( + IN CONST EFI_HANDLE TheHandle + ) +{ + EFI_STATUS Status; + EFI_GUID **ProtocolBuffer; + UINTN ProtocolCount; + HANDLE_LIST *ListWalker; + + if (TheHandle == NULL) { + return 0; + } + + InternalShellInitHandleList(); + + for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link) + ; !IsNull(&mHandleList.List.Link,&ListWalker->Link) + ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link) + ){ + if (ListWalker->TheHandle == TheHandle) { + // + // Verify that TheHandle is still present in the Handle Database + // + Status = gBS->ProtocolsPerHandle(TheHandle, &ProtocolBuffer, &ProtocolCount); + if (EFI_ERROR (Status)) { + // + // TheHandle is not present in the Handle Database, so delete from the handle list + // + RemoveEntryList (&ListWalker->Link); + return 0; + } + FreePool (ProtocolBuffer); + return (ListWalker->TheIndex); + } + } + + // + // Verify that TheHandle is valid handle + // + Status = gBS->ProtocolsPerHandle(TheHandle, &ProtocolBuffer, &ProtocolCount); + if (EFI_ERROR (Status)) { + // + // TheHandle is not valid, so do not add to handle list + // + return 0; + } + FreePool (ProtocolBuffer); + + ListWalker = AllocateZeroPool(sizeof(HANDLE_LIST)); + if (ListWalker == NULL) { + return 0; + } + ListWalker->TheHandle = TheHandle; + ListWalker->TheIndex = mHandleList.NextIndex++; + InsertTailList(&mHandleList.List.Link,&ListWalker->Link); + return (ListWalker->TheIndex); +} + + + +/** + Function to retrieve the EFI_HANDLE from the human-friendly index. + + @param[in] TheIndex The index to retrieve the EFI_HANDLE for. + + @retval NULL The index was invalid. + @return The EFI_HANDLE that index represents. + +**/ +EFI_HANDLE +EFIAPI +ConvertHandleIndexToHandle( + IN CONST UINTN TheIndex + ) +{ + EFI_STATUS Status; + EFI_GUID **ProtocolBuffer; + UINTN ProtocolCount; + HANDLE_LIST *ListWalker; + + InternalShellInitHandleList(); + + if (TheIndex >= mHandleList.NextIndex) { + return NULL; + } + + for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link) + ; !IsNull(&mHandleList.List.Link,&ListWalker->Link) + ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link) + ){ + if (ListWalker->TheIndex == TheIndex && ListWalker->TheHandle != NULL) { + // + // Verify that LinkWalker->TheHandle is valid handle + // + Status = gBS->ProtocolsPerHandle(ListWalker->TheHandle, &ProtocolBuffer, &ProtocolCount); + if (!EFI_ERROR (Status)) { + FreePool (ProtocolBuffer); + } else { + // + // TheHandle is not valid, so do not add to handle list + // + ListWalker->TheHandle = NULL; + } + return (ListWalker->TheHandle); + } + } + return NULL; +} + +/** + Gets all the related EFI_HANDLEs based on the mask supplied. + + This function scans all EFI_HANDLES in the UEFI environment's handle database + and returns the ones with the specified relationship (Mask) to the specified + controller handle. + + If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT. + If MatchingHandleCount is NULL, then ASSERT. + + If MatchingHandleBuffer is not NULL upon a successful return the memory must be + caller freed. + + @param[in] DriverBindingHandle The handle with Driver Binding protocol on it. + @param[in] ControllerHandle The handle with Device Path protocol on it. + @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in + MatchingHandleBuffer. + @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount + EFI_HANDLEs with a terminating NULL EFI_HANDLE. + @param[out] HandleType An array of type information. + + @retval EFI_SUCCESS The operation was successful, and any related handles + are in MatchingHandleBuffer. + @retval EFI_NOT_FOUND No matching handles were found. + @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range. +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseByRelationshipWithType ( + IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL, + IN CONST EFI_HANDLE ControllerHandle OPTIONAL, + IN UINTN *HandleCount, + OUT EFI_HANDLE **HandleBuffer, + OUT UINTN **HandleType + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + UINTN ProtocolIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + UINTN ChildIndex; + INTN DriverBindingHandleIndex; + + ASSERT(HandleCount != NULL); + ASSERT(HandleBuffer != NULL); + ASSERT(HandleType != NULL); + ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL); + + *HandleCount = 0; + *HandleBuffer = NULL; + *HandleType = NULL; + + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + HandleCount, + HandleBuffer + ); + if (EFI_ERROR (Status)) { + return (Status); + } + + *HandleType = AllocateZeroPool (*HandleCount * sizeof (UINTN)); + if (*HandleType == NULL) { + SHELL_FREE_NON_NULL (*HandleBuffer); + *HandleCount = 0; + return EFI_OUT_OF_RESOURCES; + } + + DriverBindingHandleIndex = -1; + for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) { + if (DriverBindingHandle != NULL && (*HandleBuffer)[HandleIndex] == DriverBindingHandle) { + DriverBindingHandleIndex = (INTN)HandleIndex; + } + } + + for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) { + // + // Retrieve the list of all the protocols on each handle + // + Status = gBS->ProtocolsPerHandle ( + (*HandleBuffer)[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (EFI_ERROR (Status)) { + continue; + } + + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + + // + // Set the bit describing what this handle has + // + if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_IMAGE_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_BINDING_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfiguration2ProtocolGuid)) { + (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_CONFIGURATION_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_CONFIGURATION_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnostics2ProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_DIAGNOSTICS_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_DIAGNOSTICS_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE; + } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) ) { + (*HandleType)[HandleIndex] |= (UINTN)HR_DEVICE_HANDLE; + } + // + // Retrieve the list of agents that have opened each protocol + // + Status = gBS->OpenProtocolInformation ( + (*HandleBuffer)[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (ControllerHandle == NULL) { + // + // ControllerHandle == NULL and DriverBindingHandle != NULL. + // Return information on all the controller handles that the driver specified by DriverBindingHandle is managing + // + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle && (OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE); + if (DriverBindingHandleIndex != -1) { + (*HandleType)[DriverBindingHandleIndex] |= (UINTN)HR_DEVICE_DRIVER; + } + } + if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle && (OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE); + if (DriverBindingHandleIndex != -1) { + (*HandleType)[DriverBindingHandleIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER); + } + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) { + (*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE); + } + } + } + } + } + if (DriverBindingHandle == NULL && ControllerHandle != NULL) { + if (ControllerHandle == (*HandleBuffer)[HandleIndex]) { + (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE); + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) { + (*HandleType)[ChildIndex] |= (UINTN)HR_DEVICE_DRIVER; + } + } + } + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) { + (*HandleType)[ChildIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER); + } + if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) { + (*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE); + } + } + } + } + } else { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) { + (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_PARENT_HANDLE); + } + } + } + } + } + if (DriverBindingHandle != NULL && ControllerHandle != NULL) { + if (ControllerHandle == (*HandleBuffer)[HandleIndex]) { + (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE); + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) { + if (DriverBindingHandleIndex != -1) { + (*HandleType)[DriverBindingHandleIndex] |= (UINTN)HR_DEVICE_DRIVER; + } + } + } + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) { + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) { + (*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE); + } + } + } + + for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) { + if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) { + (*HandleType)[ChildIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER); + } + } + } + } + } else { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) { + (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_PARENT_HANDLE); + } + } + } + } + } + FreePool (OpenInfo); + } + FreePool (ProtocolGuidArray); + } + return EFI_SUCCESS; +} + +/** + Gets all the related EFI_HANDLEs based on the single EFI_HANDLE and the mask + supplied. + + This function will scan all EFI_HANDLES in the UEFI environment's handle database + and return all the ones with the specified relationship (Mask) to the specified + controller handle. + + If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT. + If MatchingHandleCount is NULL, then ASSERT. + + If MatchingHandleBuffer is not NULL upon a sucessful return the memory must be + caller freed. + + @param[in] DriverBindingHandle Handle to a object with Driver Binding protocol + on it. + @param[in] ControllerHandle Handle to a device with Device Path protocol on it. + @param[in] Mask Mask of what relationship(s) is desired. + @param[in] MatchingHandleCount Poitner to UINTN specifying number of HANDLES in + MatchingHandleBuffer. + @param[out] MatchingHandleBuffer On a sucessful return a buffer of MatchingHandleCount + EFI_HANDLEs and a terminating NULL EFI_HANDLE. + + @retval EFI_SUCCESS The operation was sucessful and any related handles + are in MatchingHandleBuffer; + @retval EFI_NOT_FOUND No matching handles were found. + @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range. +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseByRelationship ( + IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL, + IN CONST EFI_HANDLE ControllerHandle OPTIONAL, + IN CONST UINTN Mask, + IN UINTN *MatchingHandleCount, + OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN *HandleType; + UINTN HandleIndex; + + ASSERT(MatchingHandleCount != NULL); + ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL); + + if ((Mask & HR_VALID_MASK) != Mask) { + return (EFI_INVALID_PARAMETER); + } + + if ((Mask & HR_CHILD_HANDLE) != 0 && DriverBindingHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + *MatchingHandleCount = 0; + if (MatchingHandleBuffer != NULL) { + *MatchingHandleBuffer = NULL; + } + + HandleBuffer = NULL; + HandleType = NULL; + + Status = ParseHandleDatabaseByRelationshipWithType ( + DriverBindingHandle, + ControllerHandle, + &HandleCount, + &HandleBuffer, + &HandleType + ); + if (!EFI_ERROR (Status)) { + // + // Count the number of handles that match the attributes in Mask + // + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + if ((HandleType[HandleIndex] & Mask) == Mask) { + (*MatchingHandleCount)++; + } + } + // + // If no handles match the attributes in Mask then return EFI_NOT_FOUND + // + if (*MatchingHandleCount == 0) { + Status = EFI_NOT_FOUND; + } else { + + if (MatchingHandleBuffer == NULL) { + // + // Someone just wanted the count... + // + Status = EFI_SUCCESS; + } else { + // + // Allocate a handle buffer for the number of handles that matched the attributes in Mask + // + *MatchingHandleBuffer = AllocateZeroPool ((*MatchingHandleCount +1)* sizeof (EFI_HANDLE)); + if (*MatchingHandleBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + for (HandleIndex = 0, *MatchingHandleCount = 0 + ; HandleIndex < HandleCount + ; HandleIndex++ + ) { + // + // Fill the allocated buffer with the handles that matched the attributes in Mask + // + if ((HandleType[HandleIndex] & Mask) == Mask) { + (*MatchingHandleBuffer)[(*MatchingHandleCount)++] = HandleBuffer[HandleIndex]; + } + } + + // + // Make the last one NULL + // + (*MatchingHandleBuffer)[*MatchingHandleCount] = NULL; + + Status = EFI_SUCCESS; + } // *MatchingHandleBuffer == NULL (ELSE) + } // MacthingHandleBuffer == NULL (ELSE) + } // *MatchingHandleCount == 0 (ELSE) + } // no error on ParseHandleDatabaseByRelationshipWithType + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + if (HandleType != NULL) { + FreePool (HandleType); + } + + ASSERT ((MatchingHandleBuffer == NULL) || + (*MatchingHandleCount == 0 && *MatchingHandleBuffer == NULL) || + (*MatchingHandleCount != 0 && *MatchingHandleBuffer != NULL)); + return Status; +} + +/** + Gets handles for any child controllers of the passed in controller. + + @param[in] ControllerHandle The handle of the "parent controller" + @param[out] MatchingHandleCount Pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] MatchingHandleBuffer Buffer containing handles on a successful + return. + + + @retval EFI_SUCCESS The operation was sucessful. +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseForChildControllers( + IN CONST EFI_HANDLE ControllerHandle, + OUT UINTN *MatchingHandleCount, + OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + UINTN DriverBindingHandleIndex; + UINTN ChildControllerHandleCount; + EFI_HANDLE *ChildControllerHandleBuffer; + UINTN ChildControllerHandleIndex; + EFI_HANDLE *HandleBufferForReturn; + + if (MatchingHandleCount == NULL) { + return (EFI_INVALID_PARAMETER); + } + *MatchingHandleCount = 0; + + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( + ControllerHandle, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get a buffer big enough for all the controllers. + // + HandleBufferForReturn = GetHandleListByProtocol(NULL); + if (HandleBufferForReturn == NULL) { + FreePool (DriverBindingHandleBuffer); + return (EFI_NOT_FOUND); + } + + for (DriverBindingHandleIndex = 0; DriverBindingHandleIndex < DriverBindingHandleCount; DriverBindingHandleIndex++) { + Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN ( + DriverBindingHandleBuffer[DriverBindingHandleIndex], + ControllerHandle, + &ChildControllerHandleCount, + &ChildControllerHandleBuffer + ); + if (EFI_ERROR (Status)) { + continue; + } + + for (ChildControllerHandleIndex = 0; + ChildControllerHandleIndex < ChildControllerHandleCount; + ChildControllerHandleIndex++ + ) { + for (HandleIndex = 0; HandleIndex < *MatchingHandleCount; HandleIndex++) { + if (HandleBufferForReturn[HandleIndex] == ChildControllerHandleBuffer[ChildControllerHandleIndex]) { + break; + } + } + if (HandleIndex >= *MatchingHandleCount) { + HandleBufferForReturn[(*MatchingHandleCount)++] = ChildControllerHandleBuffer[ChildControllerHandleIndex]; + } + } + + FreePool (ChildControllerHandleBuffer); + } + + FreePool (DriverBindingHandleBuffer); + + if (MatchingHandleBuffer == NULL || *MatchingHandleCount == 0) { + // + // The caller is not interested in the actual handles, or we've found none. + // + FreePool (HandleBufferForReturn); + HandleBufferForReturn = NULL; + } + + if (MatchingHandleBuffer != NULL) { + *MatchingHandleBuffer = HandleBufferForReturn; + } + + ASSERT ((MatchingHandleBuffer == NULL) || + (*MatchingHandleCount == 0 && *MatchingHandleBuffer == NULL) || + (*MatchingHandleCount != 0 && *MatchingHandleBuffer != NULL)); + + return (EFI_SUCCESS); +} + +/** + Appends 1 buffer to another buffer. This will re-allocate the destination buffer + if necessary to fit all of the data. + + If DestinationBuffer is NULL, then ASSERT(). + + @param[in, out] DestinationBuffer The pointer to the pointer to the buffer to append onto. + @param[in, out] DestinationSize The pointer to the size of DestinationBuffer. + @param[in] SourceBuffer The pointer to the buffer to append onto DestinationBuffer. + @param[in] SourceSize The number of bytes of SourceBuffer to append. + + @retval NULL A memory allocation failed. + @retval NULL A parameter was invalid. + @return A pointer to (*DestinationBuffer). +**/ +VOID* +BuffernCatGrow ( + IN OUT VOID **DestinationBuffer, + IN OUT UINTN *DestinationSize, + IN VOID *SourceBuffer, + IN UINTN SourceSize + ) +{ + UINTN LocalDestinationSize; + UINTN LocalDestinationFinalSize; + + ASSERT(DestinationBuffer != NULL); + + if (SourceSize == 0 || SourceBuffer == NULL) { + return (*DestinationBuffer); + } + + if (DestinationSize == NULL) { + LocalDestinationSize = 0; + } else { + LocalDestinationSize = *DestinationSize; + } + + LocalDestinationFinalSize = LocalDestinationSize + SourceSize; + + if (DestinationSize != NULL) { + *DestinationSize = LocalDestinationSize; + } + + if (LocalDestinationSize == 0) { + // allcoate + *DestinationBuffer = AllocateZeroPool(LocalDestinationFinalSize); + } else { + // reallocate + *DestinationBuffer = ReallocatePool(LocalDestinationSize, LocalDestinationFinalSize, *DestinationBuffer); + } + + ASSERT(*DestinationBuffer != NULL); + + // copy + return (CopyMem(((UINT8*)(*DestinationBuffer)) + LocalDestinationSize, SourceBuffer, SourceSize)); +} + +/** + Gets handles for any child devices produced by the passed in driver. + + @param[in] DriverHandle The handle of the driver. + @param[in] MatchingHandleCount Pointer to the number of handles in + MatchingHandleBuffer on return. + @param[out] MatchingHandleBuffer Buffer containing handles on a successful + return. + @retval EFI_SUCCESS The operation was sucessful. + @sa ParseHandleDatabaseByRelationship +**/ +EFI_STATUS +EFIAPI +ParseHandleDatabaseForChildDevices( + IN CONST EFI_HANDLE DriverHandle, + IN UINTN *MatchingHandleCount, + OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL + ) +{ + EFI_HANDLE *Buffer; + EFI_HANDLE *Buffer2; + UINTN Count1; + UINTN Count2; + UINTN HandleIndex; + EFI_STATUS Status; + UINTN HandleBufferSize; + + ASSERT(MatchingHandleCount != NULL); + + HandleBufferSize = 0; + Buffer = NULL; + Buffer2 = NULL; + *MatchingHandleCount = 0; + + Status = PARSE_HANDLE_DATABASE_DEVICES ( + DriverHandle, + &Count1, + &Buffer + ); + if (!EFI_ERROR (Status)) { + for (HandleIndex = 0; HandleIndex < Count1; HandleIndex++) { + // + // now find the children + // + Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN ( + DriverHandle, + Buffer[HandleIndex], + &Count2, + &Buffer2 + ); + if (EFI_ERROR(Status)) { + break; + } + // + // save out required and optional data elements + // + *MatchingHandleCount += Count2; + if (MatchingHandleBuffer != NULL) { + *MatchingHandleBuffer = BuffernCatGrow((VOID**)MatchingHandleBuffer, &HandleBufferSize, Buffer2, Count2 * sizeof(Buffer2[0])); + } + + // + // free the memory + // + if (Buffer2 != NULL) { + FreePool(Buffer2); + } + } + } + + if (Buffer != NULL) { + FreePool(Buffer); + } + return (Status); +} + +/** + Function to get all handles that support a given protocol or all handles. + + @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL + then the function will return all handles. + + @retval NULL A memory allocation failed. + @return A NULL terminated list of handles. +**/ +EFI_HANDLE* +EFIAPI +GetHandleListByProtocol ( + IN CONST EFI_GUID *ProtocolGuid OPTIONAL + ) +{ + EFI_HANDLE *HandleList; + UINTN Size; + EFI_STATUS Status; + + Size = 0; + HandleList = NULL; + + // + // We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list! + // + if (ProtocolGuid == NULL) { + Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleList = AllocateZeroPool(Size + sizeof(EFI_HANDLE)); + if (HandleList == NULL) { + return (NULL); + } + Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList); + HandleList[Size/sizeof(EFI_HANDLE)] = NULL; + } + } else { + Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleList = AllocateZeroPool(Size + sizeof(EFI_HANDLE)); + if (HandleList == NULL) { + return (NULL); + } + Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList); + HandleList[Size/sizeof(EFI_HANDLE)] = NULL; + } + } + if (EFI_ERROR(Status)) { + if (HandleList != NULL) { + FreePool(HandleList); + } + return (NULL); + } + return (HandleList); +} + +/** + Function to get all handles that support some protocols. + + @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs. + + @retval NULL A memory allocation failed. + @retval NULL ProtocolGuids was NULL. + @return A NULL terminated list of EFI_HANDLEs. +**/ +EFI_HANDLE* +EFIAPI +GetHandleListByProtocolList ( + IN CONST EFI_GUID **ProtocolGuids + ) +{ + EFI_HANDLE *HandleList; + UINTN Size; + UINTN TotalSize; + UINTN TempSize; + EFI_STATUS Status; + CONST EFI_GUID **GuidWalker; + EFI_HANDLE *HandleWalker1; + EFI_HANDLE *HandleWalker2; + + Size = 0; + HandleList = NULL; + TotalSize = sizeof(EFI_HANDLE); + + for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++,Size = 0){ + Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &Size, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + TotalSize += Size; + } + } + + // + // No handles were found... + // + if (TotalSize == sizeof(EFI_HANDLE)) { + return (NULL); + } + + HandleList = AllocateZeroPool(TotalSize); + if (HandleList == NULL) { + return (NULL); + } + + Size = 0; + for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++){ + TempSize = TotalSize - Size; + Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &TempSize, HandleList+(Size/sizeof(EFI_HANDLE))); + + // + // Allow for missing protocols... Only update the 'used' size upon success. + // + if (!EFI_ERROR(Status)) { + Size += TempSize; + } + } + ASSERT(HandleList[(TotalSize/sizeof(EFI_HANDLE))-1] == NULL); + + for (HandleWalker1 = HandleList ; HandleWalker1 != NULL && *HandleWalker1 != NULL ; HandleWalker1++) { + for (HandleWalker2 = HandleWalker1 + 1; HandleWalker2 != NULL && *HandleWalker2 != NULL ; HandleWalker2++) { + if (*HandleWalker1 == *HandleWalker2) { + // + // copy memory back 1 handle width. + // + CopyMem(HandleWalker2, HandleWalker2 + 1, TotalSize - ((HandleWalker2-HandleList+1)*sizeof(EFI_HANDLE))); + } + } + } + + return (HandleList); +} + +/** + Return all supported GUIDs. + + @param[out] Guids The buffer to return all supported GUIDs. + @param[in, out] Count On input, the count of GUIDs the buffer can hold, + On output, the count of GUIDs to return. + + @retval EFI_INVALID_PARAMETER Count is NULL. + @retval EFI_BUFFER_TOO_SMALL Buffer is not enough to hold all GUIDs. + @retval EFI_SUCCESS GUIDs are returned successfully. +**/ +EFI_STATUS +EFIAPI +GetAllMappingGuids ( + OUT EFI_GUID *Guids, + IN OUT UINTN *Count + ) +{ + UINTN GuidCount; + UINTN NtGuidCount; + UINTN Index; + + if (Count == NULL) { + return EFI_INVALID_PARAMETER; + } + + NtGuidCount = 0; + if (PcdGetBool (PcdShellIncludeNtGuids)) { + NtGuidCount = ARRAY_SIZE (mGuidStringListNT) - 1; + } + GuidCount = ARRAY_SIZE (mGuidStringList) - 1; + + if (*Count < NtGuidCount + GuidCount + mGuidListCount) { + *Count = NtGuidCount + GuidCount + mGuidListCount; + return EFI_BUFFER_TOO_SMALL; + } + + for (Index = 0; Index < NtGuidCount; Index++) { + CopyGuid (&Guids[Index], mGuidStringListNT[Index].GuidId); + } + + for (Index = 0; Index < GuidCount; Index++) { + CopyGuid (&Guids[NtGuidCount + Index], mGuidStringList[Index].GuidId); + } + + for (Index = 0; Index < mGuidListCount; Index++) { + CopyGuid (&Guids[NtGuidCount + GuidCount + Index], mGuidList[Index].GuidId); + } + + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h new file mode 100644 index 0000000..8f0b9ae --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h @@ -0,0 +1,300 @@ +/** @file + Provides interface to advanced shell functionality for parsing both handle and protocol database. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2013-2016 Hewlett-Packard Development Company, L.P.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_HANDLE_PARSING_LIB_INTERNAL_H_ +#define _UEFI_HANDLE_PARSING_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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1 1 +#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2 2 + +/// +/// EFI_FIRMWARE_IMAGE_DESCRIPTOR in UEFI spec < 2.4a +/// +typedef struct { + /// + /// A unique number identifying the firmware image within the device. The number is + /// between 1 and DescriptorCount. + /// + UINT8 ImageIndex; + /// + /// A unique number identifying the firmware image type. + /// + EFI_GUID ImageTypeId; + /// + /// A unique number identifying the firmware image. + /// + UINT64 ImageId; + /// + /// A pointer to a null-terminated string representing the firmware image name. + /// + CHAR16 *ImageIdName; + /// + /// Identifies the version of the device firmware. The format is vendor specific and new + /// version must have a greater value than an old version. + /// + UINT32 Version; + /// + /// A pointer to a null-terminated string representing the firmware image version name. + /// + CHAR16 *VersionName; + /// + /// Size of the image in bytes. If size=0, then only ImageIndex and ImageTypeId are valid. + /// + UINTN Size; + /// + /// Image attributes that are supported by this device. See 'Image Attribute Definitions' + /// for possible returned values of this parameter. A value of 1 indicates the attribute is + /// supported and the current setting value is indicated in AttributesSetting. A + /// value of 0 indicates the attribute is not supported and the current setting value in + /// AttributesSetting is meaningless. + /// + UINT64 AttributesSupported; + /// + /// Image attributes. See 'Image Attribute Definitions' for possible returned values of + /// this parameter. + /// + UINT64 AttributesSetting; + /// + /// Image compatibilities. See 'Image Compatibility Definitions' for possible returned + /// values of this parameter. + /// + UINT64 Compatibilities; +} EFI_FIRMWARE_IMAGE_DESCRIPTOR_V1; + + +/// +/// EFI_FIRMWARE_IMAGE_DESCRIPTOR in UEFI spec > 2.4a and < 2.5 +/// +typedef struct { + /// + /// A unique number identifying the firmware image within the device. The number is + /// between 1 and DescriptorCount. + /// + UINT8 ImageIndex; + /// + /// A unique number identifying the firmware image type. + /// + EFI_GUID ImageTypeId; + /// + /// A unique number identifying the firmware image. + /// + UINT64 ImageId; + /// + /// A pointer to a null-terminated string representing the firmware image name. + /// + CHAR16 *ImageIdName; + /// + /// Identifies the version of the device firmware. The format is vendor specific and new + /// version must have a greater value than an old version. + /// + UINT32 Version; + /// + /// A pointer to a null-terminated string representing the firmware image version name. + /// + CHAR16 *VersionName; + /// + /// Size of the image in bytes. If size=0, then only ImageIndex and ImageTypeId are valid. + /// + UINTN Size; + /// + /// Image attributes that are supported by this device. See 'Image Attribute Definitions' + /// for possible returned values of this parameter. A value of 1 indicates the attribute is + /// supported and the current setting value is indicated in AttributesSetting. A + /// value of 0 indicates the attribute is not supported and the current setting value in + /// AttributesSetting is meaningless. + /// + UINT64 AttributesSupported; + /// + /// Image attributes. See 'Image Attribute Definitions' for possible returned values of + /// this parameter. + /// + UINT64 AttributesSetting; + /// + /// Image compatibilities. See 'Image Compatibility Definitions' for possible returned + /// values of this parameter. + /// + UINT64 Compatibilities; + /// + /// Describes the lowest ImageDescriptor version that the device will accept. Only + /// present in version 2 or higher. + UINT32 LowestSupportedImageVersion; +} EFI_FIRMWARE_IMAGE_DESCRIPTOR_V2; + +typedef struct { + LIST_ENTRY Link; + EFI_HANDLE TheHandle; + UINTN TheIndex; +}HANDLE_LIST; + +typedef struct { + HANDLE_LIST List; + UINTN NextIndex; +} HANDLE_INDEX_LIST; + +typedef +CHAR16 * +(EFIAPI *DUMP_PROTOCOL_INFO)( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose + ); + +typedef struct _GUID_INFO_BLOCK{ + EFI_STRING_ID StringId; + EFI_GUID *GuidId; + DUMP_PROTOCOL_INFO DumpInfo; +} GUID_INFO_BLOCK; + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf new file mode 100644 index 0000000..b4b5eda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf @@ -0,0 +1,356 @@ +## @file +# Provides interface to advanced shell functionality for parsing both handle and protocol database. +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +# (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +# (C) Copyright 2015 Hewlett Packard Enterprise Development LP
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiHandleParsingLib + FILE_GUID = 3CDC7177-CC2A-4678-BA8F-1A936A093FA4 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = HandleParsingLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER + CONSTRUCTOR = HandleParsingLibConstructor + DESTRUCTOR = HandleParsingLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + UefiHandleParsingLib.c + UefiHandleParsingLib.h + UefiHandleParsingLib.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + DevicePathLib + BaseLib + BaseMemoryLib + DebugLib + FileHandleLib + PrintLib + UefiLib + HiiLib + SortLib + PeCoffGetEntryPointLib + +[Protocols] + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + + # shell 2.0 + gEfiShellProtocolGuid ## SOMETIMES_CONSUMES + gEfiShellParametersProtocolGuid ## SOMETIMES_CONSUMES + + # 'old' shell + gEfiShellEnvironment2Guid ## SOMETIMES_CONSUMES + gEfiShellInterfaceGuid ## SOMETIMES_CONSUMES + + gEfiUnicodeCollation2ProtocolGuid ## UNDEFINED + gEfiDevicePathToTextProtocolGuid ## UNDEFINED + gEfiBusSpecificDriverOverrideProtocolGuid ## UNDEFINED + gEfiDevicePathUtilitiesProtocolGuid ## UNDEFINED + gEfiDevicePathFromTextProtocolGuid ## UNDEFINED + gEfiPlatformDriverOverrideProtocolGuid ## UNDEFINED + gEfiSimpleTextInProtocolGuid ## UNDEFINED + gEfiPlatformToDriverConfigurationProtocolGuid ## UNDEFINED + gEfiDriverSupportedEfiVersionProtocolGuid ## UNDEFINED + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiLoadedImageDevicePathProtocolGuid ## UNDEFINED + gEfiSimpleTextOutProtocolGuid ## UNDEFINED + gEfiSimplePointerProtocolGuid ## UNDEFINED + gEfiAbsolutePointerProtocolGuid ## UNDEFINED + gEfiSerialIoProtocolGuid ## UNDEFINED + gEfiEdidDiscoveredProtocolGuid ## UNDEFINED + gEfiEdidActiveProtocolGuid ## UNDEFINED + gEfiEdidOverrideProtocolGuid ## UNDEFINED + gEfiLoadFileProtocolGuid ## UNDEFINED + gEfiLoadFile2ProtocolGuid ## UNDEFINED + gEfiTapeIoProtocolGuid ## UNDEFINED + gEfiDiskIoProtocolGuid ## UNDEFINED + gEfiBlockIoProtocolGuid ## UNDEFINED + gEfiUnicodeCollationProtocolGuid ## UNDEFINED + gEfiPciRootBridgeIoProtocolGuid ## UNDEFINED + gEfiPciIoProtocolGuid ## UNDEFINED + gEfiScsiPassThruProtocolGuid ## UNDEFINED + gEfiScsiIoProtocolGuid ## UNDEFINED + gEfiExtScsiPassThruProtocolGuid ## UNDEFINED + gEfiIScsiInitiatorNameProtocolGuid ## UNDEFINED + gEfiUsbIoProtocolGuid ## UNDEFINED + gEfiUsbHcProtocolGuid ## UNDEFINED + gEfiUsb2HcProtocolGuid ## UNDEFINED + gEfiDebugSupportProtocolGuid ## UNDEFINED + gEfiDebugPortProtocolGuid ## UNDEFINED + gEfiDecompressProtocolGuid ## UNDEFINED + gEfiAcpiTableProtocolGuid ## UNDEFINED + gEfiEbcProtocolGuid ## UNDEFINED + gEfiSimpleNetworkProtocolGuid ## UNDEFINED + gEfiNetworkInterfaceIdentifierProtocolGuid ## UNDEFINED + gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## UNDEFINED + gEfiPxeBaseCodeProtocolGuid ## UNDEFINED + gEfiPxeBaseCodeCallbackProtocolGuid ## UNDEFINED + gEfiBisProtocolGuid ## UNDEFINED + gEfiManagedNetworkServiceBindingProtocolGuid ## UNDEFINED + gEfiManagedNetworkProtocolGuid ## UNDEFINED + gEfiArpServiceBindingProtocolGuid ## UNDEFINED + gEfiArpProtocolGuid ## UNDEFINED + gEfiDhcp4ServiceBindingProtocolGuid ## UNDEFINED + gEfiDhcp4ProtocolGuid ## UNDEFINED + gEfiTcp4ServiceBindingProtocolGuid ## UNDEFINED + gEfiTcp4ProtocolGuid ## UNDEFINED + gEfiIp4ServiceBindingProtocolGuid ## UNDEFINED + gEfiIp4ProtocolGuid ## UNDEFINED + gEfiIp4ConfigProtocolGuid ## UNDEFINED + gEfiIp4Config2ProtocolGuid ## UNDEFINED + gEfiUdp4ServiceBindingProtocolGuid ## UNDEFINED + gEfiUdp4ProtocolGuid ## UNDEFINED + gEfiMtftp4ServiceBindingProtocolGuid ## UNDEFINED + gEfiMtftp4ProtocolGuid ## UNDEFINED + gEfiAuthenticationInfoProtocolGuid ## UNDEFINED + gEfiHashServiceBindingProtocolGuid ## UNDEFINED + gEfiHashProtocolGuid ## UNDEFINED + gEfiHiiFontProtocolGuid ## UNDEFINED + gEfiHiiStringProtocolGuid ## UNDEFINED + gEfiHiiImageProtocolGuid ## UNDEFINED + gEfiHiiConfigRoutingProtocolGuid ## UNDEFINED + gEfiHiiConfigAccessProtocolGuid ## UNDEFINED + gEfiFormBrowser2ProtocolGuid ## UNDEFINED + gEfiDeviceIoProtocolGuid ## UNDEFINED + gEfiUgaDrawProtocolGuid ## UNDEFINED + gEfiUgaIoProtocolGuid ## UNDEFINED + gEfiDriverConfigurationProtocolGuid ## UNDEFINED + gEfiDriverConfiguration2ProtocolGuid ## UNDEFINED + gEfiSimpleTextInputExProtocolGuid ## UNDEFINED + gEfiIp6ServiceBindingProtocolGuid ## UNDEFINED + gEfiIp6ProtocolGuid ## UNDEFINED + gEfiIp6ConfigProtocolGuid ## UNDEFINED + gEfiMtftp6ServiceBindingProtocolGuid ## UNDEFINED + gEfiMtftp6ProtocolGuid ## UNDEFINED + gEfiDhcp6ServiceBindingProtocolGuid ## UNDEFINED + gEfiDhcp6ProtocolGuid ## UNDEFINED + gEfiUdp6ServiceBindingProtocolGuid ## UNDEFINED + gEfiUdp6ProtocolGuid ## UNDEFINED + gEfiTcp6ServiceBindingProtocolGuid ## UNDEFINED + gEfiTcp6ProtocolGuid ## UNDEFINED + gEfiVlanConfigProtocolGuid ## UNDEFINED + gEfiEapProtocolGuid ## UNDEFINED + gEfiEapManagementProtocolGuid ## UNDEFINED + gEfiFtp4ServiceBindingProtocolGuid ## UNDEFINED + gEfiFtp4ProtocolGuid ## UNDEFINED + gEfiIpSecConfigProtocolGuid ## UNDEFINED + gEfiDriverHealthProtocolGuid ## UNDEFINED + gEfiDeferredImageLoadProtocolGuid ## UNDEFINED + gEfiUserCredentialProtocolGuid ## UNDEFINED + gEfiUserManagerProtocolGuid ## UNDEFINED + gEfiAtaPassThruProtocolGuid ## UNDEFINED + gEfiFirmwareManagementProtocolGuid ## UNDEFINED + gEfiIpSecProtocolGuid ## UNDEFINED + gEfiIpSec2ProtocolGuid ## UNDEFINED + gEfiKmsProtocolGuid ## UNDEFINED + gEfiBlockIo2ProtocolGuid ## UNDEFINED + gEfiStorageSecurityCommandProtocolGuid ## UNDEFINED + gEfiUserCredential2ProtocolGuid ## UNDEFINED + gPcdProtocolGuid ## UNDEFINED + gEfiTcgProtocolGuid ## UNDEFINED + gEfiHiiPackageListProtocolGuid ## UNDEFINED + gEfiDriverFamilyOverrideProtocolGuid ## UNDEFINED + gEfiIdeControllerInitProtocolGuid ## UNDEFINED + gEfiDiskIo2ProtocolGuid ## UNDEFINED + gEfiAdapterInformationProtocolGuid ## UNDEFINED + gEfiShellDynamicCommandProtocolGuid ## UNDEFINED + gEfiDiskInfoProtocolGuid ## UNDEFINED + gGetPcdInfoProtocolGuid ## UNDEFINED + gEfiBdsArchProtocolGuid ## UNDEFINED + gEfiCpuArchProtocolGuid ## UNDEFINED + gEfiMetronomeArchProtocolGuid ## UNDEFINED + gEfiMonotonicCounterArchProtocolGuid ## UNDEFINED + gEfiRealTimeClockArchProtocolGuid ## UNDEFINED + gEfiResetArchProtocolGuid ## UNDEFINED + gEfiRuntimeArchProtocolGuid ## UNDEFINED + gEfiSecurityArchProtocolGuid ## UNDEFINED + gEfiTimerArchProtocolGuid ## UNDEFINED + gEfiVariableWriteArchProtocolGuid ## UNDEFINED + gEfiVariableArchProtocolGuid ## UNDEFINED + gEfiSecurityPolicyProtocolGuid ## UNDEFINED + gEfiWatchdogTimerArchProtocolGuid ## UNDEFINED + gEfiStatusCodeRuntimeProtocolGuid ## UNDEFINED + gEfiSmbusHcProtocolGuid ## UNDEFINED + gEfiFirmwareVolume2ProtocolGuid ## UNDEFINED + gEfiFirmwareVolumeBlockProtocolGuid ## UNDEFINED + gEfiCapsuleArchProtocolGuid ## UNDEFINED + gEfiMpServiceProtocolGuid ## UNDEFINED + gEfiPciHostBridgeResourceAllocationProtocolGuid ## UNDEFINED + gEfiPciPlatformProtocolGuid ## UNDEFINED + gEfiPciOverrideProtocolGuid ## UNDEFINED + gEfiPciEnumerationCompleteProtocolGuid ## UNDEFINED + gEfiIncompatiblePciDeviceSupportProtocolGuid ## UNDEFINED + gEfiPciHotPlugInitProtocolGuid ## UNDEFINED + gEfiPciHotPlugRequestProtocolGuid ## UNDEFINED + gEfiSmbiosProtocolGuid ## UNDEFINED + gEfiS3SaveStateProtocolGuid ## UNDEFINED + gEfiS3SmmSaveStateProtocolGuid ## UNDEFINED + gEfiRscHandlerProtocolGuid ## UNDEFINED + gEfiSmmRscHandlerProtocolGuid ## UNDEFINED + gEfiAcpiSdtProtocolGuid ## UNDEFINED + gEfiSioProtocolGuid ## UNDEFINED + gEfiSmmCpuIo2ProtocolGuid ## UNDEFINED + gEfiSmmBase2ProtocolGuid ## UNDEFINED + gEfiSmmAccess2ProtocolGuid ## UNDEFINED + gEfiSmmControl2ProtocolGuid ## UNDEFINED + gEfiSmmConfigurationProtocolGuid ## UNDEFINED + gEfiSmmReadyToLockProtocolGuid ## UNDEFINED + gEfiDxeSmmReadyToLockProtocolGuid ## UNDEFINED + gEfiSmmCommunicationProtocolGuid ## UNDEFINED + gEfiSmmStatusCodeProtocolGuid ## UNDEFINED + gEfiSmmCpuProtocolGuid ## UNDEFINED + gEfiSmmPciRootBridgeIoProtocolGuid ## UNDEFINED + gEfiSmmSwDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmSxDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmUsbDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmGpiDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmStandbyButtonDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmPowerButtonDispatch2ProtocolGuid ## UNDEFINED + gEfiSmmIoTrapDispatch2ProtocolGuid ## UNDEFINED + gEfiPcdProtocolGuid ## UNDEFINED + gEfiFirmwareVolumeBlock2ProtocolGuid ## UNDEFINED + gEfiCpuIo2ProtocolGuid ## UNDEFINED + gEfiLegacyRegion2ProtocolGuid ## UNDEFINED + gEfiSalMcaInitPmiProtocolGuid ## UNDEFINED + gEfiExtendedSalBootServiceProtocolGuid ## UNDEFINED + gEfiExtendedSalBaseIoServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalStallServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalRtcServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalVariableServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalMtcServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalResetServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalStatusCodeServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalFvBlockServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalMpServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalPalServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalBaseServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalMcaServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalPciServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalCacheServicesProtocolGuid ## UNDEFINED + gEfiExtendedSalMcaLogServicesProtocolGuid ## UNDEFINED + gEfiSecurity2ArchProtocolGuid ## UNDEFINED + gEfiSmmEndOfDxeProtocolGuid ## UNDEFINED + gEfiIsaHcProtocolGuid ## UNDEFINED + gEfiIsaHcServiceBindingProtocolGuid ## UNDEFINED + gEfiSioControlProtocolGuid ## UNDEFINED + gEfiGetPcdInfoProtocolGuid ## UNDEFINED + gEfiI2cMasterProtocolGuid ## UNDEFINED + gEfiI2cIoProtocolGuid ## UNDEFINED + gEfiI2cEnumerateProtocolGuid ## UNDEFINED + gEfiI2cHostProtocolGuid ## UNDEFINED + gEfiI2cBusConfigurationManagementProtocolGuid ## UNDEFINED + gEfiTcg2ProtocolGuid ## UNDEFINED + gEfiTimestampProtocolGuid ## UNDEFINED + gEfiRngProtocolGuid ## UNDEFINED + gEfiNvmExpressPassThruProtocolGuid ## UNDEFINED + gEfiHash2ServiceBindingProtocolGuid ## UNDEFINED + gEfiHash2ProtocolGuid ## UNDEFINED + gEfiBlockIoCryptoProtocolGuid ## UNDEFINED + gEfiSmartCardReaderProtocolGuid ## UNDEFINED + gEfiSmartCardEdgeProtocolGuid ## UNDEFINED + gEfiUsbFunctionIoProtocolGuid ## UNDEFINED + gEfiBluetoothHcProtocolGuid ## UNDEFINED + gEfiBluetoothIoServiceBindingProtocolGuid ## UNDEFINED + gEfiBluetoothIoProtocolGuid ## UNDEFINED + gEfiBluetoothConfigProtocolGuid ## UNDEFINED + gEfiRegularExpressionProtocolGuid ## UNDEFINED + gEfiBootManagerPolicyProtocolGuid ## UNDEFINED + gEfiConfigKeywordHandlerProtocolGuid ## UNDEFINED + gEfiWiFiProtocolGuid ## UNDEFINED + gEfiEapManagement2ProtocolGuid ## UNDEFINED + gEfiEapConfigurationProtocolGuid ## UNDEFINED + gEfiPkcs7VerifyProtocolGuid ## UNDEFINED + gEfiDns4ServiceBindingProtocolGuid ## UNDEFINED + gEfiDns4ProtocolGuid ## UNDEFINED + gEfiDns6ServiceBindingProtocolGuid ## UNDEFINED + gEfiDns6ProtocolGuid ## UNDEFINED + gEfiHttpServiceBindingProtocolGuid ## UNDEFINED + gEfiHttpProtocolGuid ## UNDEFINED + gEfiHttpUtilitiesProtocolGuid ## UNDEFINED + gEfiRestProtocolGuid ## UNDEFINED + gEfiMmEndOfDxeProtocolGuid ## UNDEFINED + gEfiMmIoTrapDispatchProtocolGuid ## UNDEFINED + gEfiMmPowerButtonDispatchProtocolGuid ## UNDEFINED + gEfiMmStandbyButtonDispatchProtocolGuid ## UNDEFINED + gEfiMmGpiDispatchProtocolGuid ## UNDEFINED + gEfiMmUsbDispatchProtocolGuid ## UNDEFINED + gEfiMmPeriodicTimerDispatchProtocolGuid ## UNDEFINED + gEfiMmSxDispatchProtocolGuid ## UNDEFINED + gEfiMmSwDispatchProtocolGuid ## UNDEFINED + gEfiMmPciRootBridgeIoProtocolGuid ## UNDEFINED + gEfiMmCpuProtocolGuid ## UNDEFINED + gEfiMmStatusCodeProtocolGuid ## UNDEFINED + gEfiDxeMmReadyToLockProtocolGuid ## UNDEFINED + gEfiMmConfigurationProtocolGuid ## UNDEFINED + gEfiMmReadyToLockProtocolGuid ## UNDEFINED + gEfiMmControlProtocolGuid ## UNDEFINED + gEfiMmAccessProtocolGuid ## UNDEFINED + gEfiMmBaseProtocolGuid ## UNDEFINED + gEfiMmCpuIoProtocolGuid ## UNDEFINED + gEfiMmRscHandlerProtocolGuid ## UNDEFINED + gEfiMmCommunicationProtocolGuid ## UNDEFINED + gEfiTlsServiceBindingProtocolGuid ## UNDEFINED + gEfiTlsProtocolGuid ## UNDEFINED + gEfiTlsConfigurationProtocolGuid ## UNDEFINED + gEfiSupplicantServiceBindingProtocolGuid ## UNDEFINED + gEfiSupplicantProtocolGuid ## UNDEFINED + gEfiWiFi2ProtocolGuid ## UNDEFINED + gEfiRamDiskProtocolGuid ## UNDEFINED + gEfiHiiImageDecoderProtocolGuid ## UNDEFINED + gEfiHiiImageExProtocolGuid ## UNDEFINED + gEfiSdMmcPassThruProtocolGuid ## UNDEFINED + gEfiEraseBlockProtocolGuid ## UNDEFINED + gEfiBluetoothAttributeProtocolGuid ## UNDEFINED + gEfiBluetoothAttributeServiceBindingProtocolGuid ## UNDEFINED + gEfiBluetoothLeConfigProtocolGuid ## UNDEFINED + gEfiUfsDeviceConfigProtocolGuid ## UNDEFINED + gEfiHttpBootCallbackProtocolGuid ## UNDEFINED + gEfiResetNotificationProtocolGuid ## UNDEFINED + gEfiPartitionInfoProtocolGuid ## UNDEFINED + gEfiHiiPopupProtocolGuid ## UNDEFINED + +[Guids] + gEfiFileInfoGuid ## UNDEFINED + gEfiShellEnvironment2ExtGuid ## SOMETIMES_CONSUMES ## GUID + gEfiPcAnsiGuid ## UNDEFINED + gEfiVT100Guid ## UNDEFINED + gEfiVT100PlusGuid ## UNDEFINED + gEfiVTUTF8Guid ## UNDEFINED + gEfiStandardErrorDeviceGuid ## UNDEFINED + gEfiConsoleInDeviceGuid ## UNDEFINED + gEfiConsoleOutDeviceGuid ## UNDEFINED + gEfiFileSystemInfoGuid ## UNDEFINED + gEfiGlobalVariableGuid ## UNDEFINED + gEfiPartTypeSystemPartGuid ## UNDEFINED + gEfiPartTypeLegacyMbrGuid ## UNDEFINED + gHandleParsingHiiGuid ## UNDEFINED + gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES ## GUID + gEfiAdapterInfoNetworkBootGuid ## SOMETIMES_CONSUMES ## GUID + gEfiAdapterInfoSanMacAddressGuid ## SOMETIMES_CONSUMES ## GUID + gEfiAdapterInfoUndiIpv6SupportGuid ## SOMETIMES_CONSUMES ## GUID + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellIncludeNtGuids ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni new file mode 100644 index 0000000..8e1f48c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni @@ -0,0 +1,529 @@ +// /** +// +// Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiHandleParsingLib.uni +// +// Abstract: +// +// +// +// **/ + +/=# + +#langdef en-US "english" + +// +// Protocol names used making the GUID <-> Name bi-directional list +// + +// basics Images & Device Path +#string STR_LOADED_IMAGE #language en-US "LoadedImage" +#string STR_DEVICE_PATH #language en-US "DevicePath" +#string STR_IMAGE_PATH #language en-US "ImageDevicePath" +#string STR_DEVICE_PATH_UTIL #language en-US "DevicePathUtilities" +#string STR_DEVICE_PATH_TXT #language en-US "DevicePathToText" +#string STR_DEVICE_PATH_FTXT #language en-US "DevicePathFromText" +#string STR_DEVICE_PATH_PC #language en-US "DevicePathPCAnsi" +#string STR_DEVICE_PATH_VT100 #language en-US "DevicePathVT100" +#string STR_DEVICE_PATH_VT100P #language en-US "DevicePathVT100+" +#string STR_DEVICE_PATH_VTUTF8 #language en-US "DevicePathVTUTF8" + +// Drivers +#string STR_DRIVER_BINDING #language en-US "DriverBinding" +#string STR_PLATFORM_OVERRIDE #language en-US "PlatformOverride" +#string STR_BUS_OVERRIDE #language en-US "BusSpecificDriverOverride" +#string STR_DRIVER_DIAG #language en-US "DriverDiagnostics" +#string STR_DRIVER_DIAG2 #language en-US "DriverDiagnostics2" +#string STR_DRIVER_CN #language en-US "ComponentName" +#string STR_DRIVER_CN2 #language en-US "ComponentName2" +#string STR_PLAT_DRV_CFG #language en-US "PlatformtoDriverConfiguration" +#string STR_DRIVER_VERSION #language en-US "SupportedEfiSpecVersion" + +// Console +#string STR_TXT_IN #language en-US "SimpleTextIn" +#string STR_TXT_IN_EX #language en-US "SimpleTextInEx" +#string STR_TXT_OUT #language en-US "SimpleTextOut" +#string STR_SIM_POINTER #language en-US "SimplePointer" +#string STR_ABS_POINTER #language en-US "AbsolutePointer" +#string STR_SERIAL_IO #language en-US "SerialIO" +#string STR_GRAPHICS_OUTPUT #language en-US "GraphicsOutput" +#string STR_EDID_DISCOVERED #language en-US "EDIDDiscovered" +#string STR_EDID_ACTIVE #language en-US "EDIDActive" +#string STR_EDID_OVERRIDE #language en-US "EDIDOverride" +#string STR_CON_IN #language en-US "ConsoleIn" +#string STR_CON_OUT #language en-US "ConsoleOut" +#string STR_STD_ERR #language en-US "StdErr" + +// Media +#string STR_LOAD_FILE #language en-US "LoadFile" +#string STR_LOAD_FILE2 #language en-US "LoadFile2" +#string STR_SIMPLE_FILE_SYS #language en-US "SimpleFileSystem" +#string STR_FILE_INFO #language en-US "FileInfo" +#string STR_FILE_SYS_INFO #language en-US "FileSystemInfo" +#string STR_TAPE_IO #language en-US "TapeIO" +#string STR_DISK_IO #language en-US "DiskIO" +#string STR_DISK_IO2 #language en-US "DiskIO2" +#string STR_BLK_IO #language en-US "BlockIO" +#string STR_UC #language en-US "UnicodeCollation" +#string STR_UC2 #language en-US "UnicodeCollation2" +#string STR_ADAPTER_INFO #language en-US "AdapterInfo" + +// PCI +#string STR_PCIRB_IO #language en-US "PCIRootBridgeIO" +#string STR_PCI_IO #language en-US "PCIIO" + +// SCSI +#string STR_SCSI_PT #language en-US "SCSIPassThru" +#string STR_SCSI_IO #language en-US "SCSIIO" +#string STR_SCSI_PT_EXT #language en-US "ExtendedSCSIPassThru" + +// iSCSI +#string STR_ISCSI #language en-US "iSCSIInitiatorName" + +// USB +#string STR_USB_IO #language en-US "USBIO" +#string STR_USB_HC #language en-US "USBHostControler" +#string STR_USB_HC2 #language en-US "USBHostController2" + +// Debug +#string STR_DEBUG_SUPPORT #language en-US "DebugSupport" +#string STR_DEBUG_PORT #language en-US "DebugPort" + +#string STR_DECOMPRESS #language en-US "Decompress" + +#string STR_ACPI_TABLE #language en-US "AcpiTable" + +#string STR_EBC_INTERPRETER #language en-US "EBCInterpreter" + +// Network +#string STR_SNP #language en-US "SimpleNetwork" +#string STR_NII #language en-US "NetworkInterfaceIdentifier" +#string STR_NII_31 #language en-US "NetworkInterfaceIdentifier31" +#string STR_PXE_BC #language en-US "PXEBaseCode" +#string STR_PXE_CB #language en-US "PXECallback" +#string STR_BIS #language en-US "BIS" +#string STR_MNP_SB #language en-US "ManagedNetworkServiceBinding" +#string STR_MNP #language en-US "ManagedNetwork" + +#string STR_ARP_SB #language en-US "ARPServiceBinding" +#string STR_ARP #language en-US "ARP" +#string STR_DHCPV4_SB #language en-US "DHCPv4ServiceBinding" +#string STR_DHCPV4 #language en-US "DHCPv4" +#string STR_TCPV4_SB #language en-US "TCPv4ServiceBinding" +#string STR_TCPV4 #language en-US "TCPv4" +#string STR_IPV4_SB #language en-US "IPv4ServiceBinding" +#string STR_IPV4 #language en-US "IPv4" +#string STR_IPV4_CFG #language en-US "IPv4Config" +#string STR_IPV4_CFG2 #language en-US "IPv4Config2" +#string STR_UDPV4_SB #language en-US "UDPv4ServiceBinding" +#string STR_UDPV4 #language en-US "UDPv4" +#string STR_MTFTPV4_SB #language en-US "MTFTPv4ServiceBinding" +#string STR_MTFTPV4 #language en-US "MTFTPv4" + +// Security +#string STR_HASH_SB #language en-US "HashServiceBinding" +#string STR_HASH #language en-US "Hash" +#string STR_AUTH_INFO #language en-US "AuthenticationInfo" + +// HII +#string STR_HII_FONT #language en-US "HIIFont" +#string STR_HII_STRING #language en-US "HIIString" +#string STR_HII_IMAGE #language en-US "HIIImage" +#string STR_HII_DATABASE #language en-US "HIIDatabase" +#string STR_HII_CONFIG_ROUT #language en-US "HIIConfigRouting" +#string STR_HII_CONFIG_ACC #language en-US "HIIConfigAccess" +#string STR_HII_FORM_BROWSER2 #language en-US "HIIFormBrowser2" + +// Shell +#string STR_SHELL_PARAMETERS #language en-US "ShellParameters" +#string STR_SHELL #language en-US "Shell" +#string STR_SHELL_DYNAMIC #language en-US "ShellDynamicCommand" + +#string STR_EFI_GLOBAL_VARIABLE #language en-US "EFIGlobalVariable" + +// NT32 emulation +#string STR_WINNT_THUNK #language en-US "WinNTThunk" +#string STR_WINNT_DRIVER_IO #language en-US "WinNTDriverIO" +#string STR_WINNT_SERIAL_PORT #language en-US "WinNTSerialPort" + +// deprecated protocols +#string STR_SHELL_INTERFACE #language en-US "ShellInterface" +#string STR_SHELL_ENV #language en-US "ShellEnvironment" +#string STR_SHELL_ENV2 #language en-US "ShellEnvironment2" +#string STR_SHELL_DP_MAP #language en-US "ShellDevicePathMap" +#string STR_SHELL_ALIAS #language en-US "ShellAlias" +#string STR_DEVICE_IO #language en-US "DeviceIO" +#string STR_TCP #language en-US "TCP" +#string STR_UGA_DRAW #language en-US "UGADraw" +#string STR_UGA_IO #language en-US "UGAIO" +#string STR_ESP #language en-US "EFISystemPartition" +#string STR_GPT_NBR #language en-US "LegacyMBR" +#string STR_DRIVER_CONFIG #language en-US "DriverConfiguration" +#string STR_DRIVER_CONFIG2 #language en-US "DriverConfiguration2" +#string STR_ISA_IO #language en-US "ISAIO" +#string STR_ISA_ACPI #language en-US "ISAACPI" +#string STR_HII_FORM_BROWSER #language en-US "HIIFormBrowser" +#string STR_HII #language en-US "HII" +#string STR_HII_FORM_CALLBACK #language en-US "HIICallback" + +#string STR_TXT_OUT_DUMP_HEADER #language en-US " Address: %%H%X%%N Attrib %02x" +#string STR_TXT_OUT_DUMP_LINE #language en-US "\r\n %c mode %d: Col %d Row %d" + +#string STR_DRIVER_FAM_OVERRIDE #language en-US "DriverFamilyOverride" +#string STR_PCD #language en-US "Pcd" +#string STR_TCG #language en-US "Tcg" +#string STR_HII_PACKAGE_LIST #language en-US "HiiPackageList" + +#string STR_IP6_SB #language en-US "Ip6ServiceBinding" +#string STR_IP6 #language en-US "Ip6" +#string STR_IP6_CONFIG #language en-US "Ip6Config" +#string STR_MTFTP6_SB #language en-US "Mtftp6ServiceBinding" +#string STR_MTFTP6 #language en-US "Mtftp6" +#string STR_DHCP6_SB #language en-US "Dhcp6ServiceBinding" +#string STR_DHCP6 #language en-US "Dhcp6" +#string STR_UDP6_SB #language en-US "Udp6ServiceBinding" +#string STR_UDP6 #language en-US "Udp6" +#string STR_TCP6_SB #language en-US "Tcp6ServiceBinding" +#string STR_TCP6 #language en-US "Tcp6" +#string STR_VLAN_CONFIG #language en-US "VlanConfig" +#string STR_EAP #language en-US "Eap" +#string STR_EAP_MGMT #language en-US "EapManagement" +#string STR_FTP4_SB #language en-US "Ftp4ServiceBinding" +#string STR_FTP4 #language en-US "Ftp4" +#string STR_IP_SEC_CONFIG #language en-US "IpSecConfig" +#string STR_DH #language en-US "DriverHealth" +#string STR_DEF_IMG_LOAD #language en-US "DeferredImageLoad" +#string STR_USER_CRED #language en-US "UserCredential" +#string STR_USER_MNGR #language en-US "UserManager" +#string STR_ATA_PASS_THRU #language en-US "AtaPassThru" +#string STR_FW_MGMT #language en-US "FirmwareManagement" +#string STR_IP_SEC #language en-US "IpSec" +#string STR_IP_SEC2 #language en-US "IpSec2" +#string STR_KMS #language en-US "Kms" +#string STR_BLK_IO2 #language en-US "BlockIo2" +#string STR_SSC #language en-US "StorageSecurityCommand" +#string STR_UCRED2 #language en-US "UserCredential2" + +#string STR_PCDINFOPROT #language en-US "GetPcdInfoProtocol" +#string STR_BDS_ARCH #language en-US "BdsArch" +#string STR_CPU_ARCH #language en-US "CpuArch" +#string STR_MET_ARCH #language en-US "MetronomeArch" +#string STR_MON_ARCH #language en-US "MonotonicCounterArch" +#string STR_RTC_ARCH #language en-US "RealTimeClockArch" +#string STR_RESET_ARCH #language en-US "ResetArch" +#string STR_RT_ARCH #language en-US "RuntimeArch" +#string STR_SEC_ARCH #language en-US "SecurityArch" +#string STR_TIMER_ARCH #language en-US "TimerArch" +#string STR_VAR_ARCH #language en-US "VariableWriteArch" +#string STR_V_ARCH #language en-US "VariableArch" +#string STR_SECP #language en-US "SecurityPolicy" +#string STR_WDT_ARCH #language en-US "WatchdogTimerArch" +#string STR_SCR #language en-US "StatusCodeRuntime" +#string STR_SMB_HC #language en-US "SmbusHc" +#string STR_FV_2 #language en-US "FirmwareVolume2" +#string STR_FV_BLOCK #language en-US "FirmwareVolumeBlock" +#string STR_CAP_ARCH #language en-US "CapsuleArch" +#string STR_MP_SERVICE #language en-US "MpService" +#string STR_HBRAP #language en-US "PciHostBridgeResourceAllocation" +#string STR_PCIP #language en-US "PciPlatform" +#string STR_PCIO #language en-US "PciOverride" +#string STR_PCIE #language en-US "PciEnumerationComplete" +#string STR_IPCID #language en-US "IncompatiblePciDeviceSupport" +#string STR_PCIHPI #language en-US "PciHotPlugInit" +#string STR_PCIHPR #language en-US "PciHotPlugRequest" +#string STR_SMBIOS #language en-US "Smbios" +#string STR_S3_SAVE #language en-US "S3SaveState" +#string STR_S3_S_SMM #language en-US "S3SmmSaveState" +#string STR_RSC #language en-US "RscHandler" +#string STR_S_RSC #language en-US "SmmRscHandler" +#string STR_ACPI_SDT #language en-US "AcpiSdt" +#string STR_SIO #language en-US "Sio" +#string STR_S_CPU2 #language en-US "SmmCpuIo2" +#string STR_S_BASE2 #language en-US "SmmBase2" +#string STR_S_ACC_2 #language en-US "SmmAccess2" +#string STR_S_CON_2 #language en-US "SmmControl2" +#string STR_S_CONFIG #language en-US "SmmConfig" +#string STR_S_RTL #language en-US "SmmReadyToLock" +#string STR_DS_RTL #language en-US "DxeSmmReadyToLock" +#string STR_S_COMM #language en-US "SmmCommunication" +#string STR_S_STAT #language en-US "SmmStatusCode" +#string STR_S_CPU #language en-US "SmmCpu" +#string STR_S_PCIRBIO #language en-US "SmmPCIRootBridgeIO" +#string STR_S_SWD #language en-US "SmmSwDispatch2" +#string STR_S_SXD #language en-US "SmmSxDispatch2" +#string STR_S_PTD2 #language en-US "SmmPeriodicTimerDispatch2" +#string STR_S_UD2 #language en-US "SmmUsbDispatch2" +#string STR_S_GD2 #language en-US "SmmGpiDispatch2" +#string STR_S_SBD2 #language en-US "SmmStandbyButtonDispatch2" +#string STR_S_PBD2 #language en-US "SmmPowerButtonDispatch2" +#string STR_S_ITD2 #language en-US "SmmIoTrapDispatch2" +#string STR_PCD #language en-US "Pcd" +#string STR_FVB2 #language en-US "FirmwareVolumeBlock2" +#string STR_CPUIO2 #language en-US "CpuIo2" +#string STR_LEGACY_R2 #language en-US "LegacyRegion2" +#string STR_SAL_MIP #language en-US "SalMcaInitPmi" +#string STR_ES_BS #language en-US "ExtendedSalBootService" +#string STR_ES_BIO #language en-US "ExtendedSalBaseIoServices" +#string STR_ES_STALL #language en-US "ExtendedSalStallServices" +#string STR_ES_RTC #language en-US "ExtendedSalRtcServices" +#string STR_ES_VS #language en-US "ExtendedSalVariableServices" +#string STR_ES_MTC #language en-US "ExtendedSalMtcServices" +#string STR_ES_RESET #language en-US "ExtendedSalResetServices" +#string STR_ES_SC #language en-US "ExtendedSalStatusCodeServices" +#string STR_ES_FBS #language en-US "ExtendedSalFvBlockServices" +#string STR_ES_MP #language en-US "ExtendedSalMpServices" +#string STR_ES_PAL #language en-US "ExtendedSalPalServices" +#string STR_ES_BASE #language en-US "ExtendedSalBaseServices" +#string STR_ES_MCA #language en-US "ExtendedSalMcaServices" +#string STR_ES_PCI #language en-US "ExtendedSalPciServices" +#string STR_ES_CACHE #language en-US "ExtendedSalCacheServices" +#string STR_ES_MCA_LOG #language en-US "ExtendedSalMcaLogServices" +#string STR_S2ARCH #language en-US "Security2Arch" +#string STR_EODXE #language en-US "SmmEndOfDxe" +#string STR_ISAHC #language en-US "IsaHc" +#string STR_ISAHC_B #language en-US "IsaHcServiceBinding" +#string STR_SIO_C #language en-US "SioControl" +#string STR_GET_PCD #language en-US "GetPcdInfo" +#string STR_I2C_M #language en-US "I2cMaster" +#string STR_I2CIO #language en-US "I2cIo" +#string STR_I2CEN #language en-US "I2cEnumerate" +#string STR_I2C_H #language en-US "I2cHost" +#string STR_I2C_BCM #language en-US "I2cBusConfigurationManagement" +#string STR_TCG2 #language en-US "Tcg2" +#string STR_TIMESTAMP #language en-US "Timestamp" +#string STR_RNG #language en-US "Rng" +#string STR_NVMEPT #language en-US "NvmExpressPassThru" +#string STR_H2_SB #language en-US "Hash2ServiceBinding" +#string STR_HASH2 #language en-US "Hash2" +#string STR_BIO_C #language en-US "BlockIoCrypto" +#string STR_SCR #language en-US "SmartCardReader" +#string STR_SCE #language en-US "SmartCardEdge" +#string STR_USB_FIO #language en-US "UsbFunctionIo" +#string STR_BC_HC #language en-US "BluetoothHc" +#string STR_BC_IO_SB #language en-US "BluetoothIoServiceBinding" +#string STR_BC_IO #language en-US "BluetoothIo" +#string STR_BC_C #language en-US "BluetoothConfig" +#string STR_REG_EXP #language en-US "RegularExpression" +#string STR_B_MGR_P #language en-US "BootManagerPolicy" +#string STR_CKH #language en-US "ConfigKeywordHandler" +#string STR_WIFI #language en-US "WiFi" +#string STR_EAP_M #language en-US "EapManagement2" +#string STR_EAP_C #language en-US "EapConfiguration" +#string STR_PKCS7 #language en-US "Pkcs7Verify" +#string STR_NET_DNS4_SB #language en-US "Dns4ServiceBinding" +#string STR_NET_DNS4 #language en-US "Dns4" +#string STR_NET_DNS6_SB #language en-US "Dns6ServiceBinding" +#string STR_NET_DNS6 #language en-US "Dns6" +#string STR_NET_HTTP_SB #language en-US "HttpServiceBinding" +#string STR_NET_HTTP #language en-US "Http" +#string STR_NET_HTTP_U #language en-US "HttpUtilities" +#string STR_REST #language en-US "Rest" + +#string STR_MM_EOD #language en-US "MmEndOfDxe" +#string STR_MM_ITD #language en-US "MmIoTrapDispatch" +#string STR_MM_PBD #language en-US "MmPowerButtonDispatch" +#string STR_MM_SBD #language en-US "MmStandbyButtonDispatch" +#string STR_MM_GD #language en-US "MmGpiDispatch" +#string STR_MM_UD #language en-US "MmUsbDispatch" +#string STR_MM_PTD #language en-US "MmPeriodicTimerDispatch" +#string STR_MM_SXD #language en-US "MmSxDispatch" +#string STR_MM_SWD #language en-US "MmSwDispatch" +#string STR_MM_PRBI #language en-US "MmPciRootBridgeIo" +#string STR_MM_CPU #language en-US "MmCpu" +#string STR_MM_STACODE #language en-US "MmStatusCode" +#string STR_DXEMM_RTL #language en-US "DxeMmReadyToLock" +#string STR_MM_CONFIG #language en-US "MmConfiguration" +#string STR_MM_RTL #language en-US "MmReadyToLock" +#string STR_MM_CONTROL #language en-US "MmControl" +#string STR_MM_ACCESS #language en-US "MmAccess" +#string STR_MM_BASE #language en-US "MmBase" +#string STR_MM_CPUIO #language en-US "MmCpuIo" +#string STR_MM_RH #language en-US "MmRscHandler" +#string STR_MM_COM #language en-US "MmCommunication" + +#string STR_TLS_SB #language en-US "TlsServiceBinding" +#string STR_TLS #language en-US "Tls" +#string STR_TLS_CONFIG #language en-US "TlsConfiguration" +#string STR_SUPPLICANT_SB #language en-US "SupplicantServiceBinding" +#string STR_SUPPLICANT #language en-US "Supplicant" + +#string STR_WIFI2 #language en-US "WiFi2" +#string STR_RAMDISK #language en-US "RamDisk" +#string STR_HII_ID #language en-US "HiiImageDecoder" +#string STR_HII_IE #language en-US "HiiImageEx" +#string STR_SD_MPT #language en-US "SdMmcPassThru" +#string STR_ERASE_BLOCK #language en-US "EraseBlock" + +#string STR_BLUETOOTH_ATTR #language en-US "BluetoothAttribute" +#string STR_BLUETOOTH_ATTR_SB #language en-US "BluetoothAttributeServiceBinding" +#string STR_BLUETOOTH_LE_CONFIG #language en-US "BluetoothLeConfig" +#string STR_UFS_DEV_CONFIG #language en-US "UfsDeviceConfig" +#string STR_HTTP_BOOT_CALL #language en-US "HttpBootCallback" +#string STR_RESET_NOTI #language en-US "ResetNotification" +#string STR_PARTITION_INFO #language en-US "PartitionInfo" +#string STR_HII_POPUP #language en-US "HiiPopup" + +#string STR_IDE_CONT_INIT #language en-US "IdeControllerInit" +#string STR_DISK_INFO #language en-US "DiskInfo" +#string STR_BLOCKIO_INFO #language en-US " %s%sMId:%%H%x%%N bsize %%H%x%%N, lblock %lx (%,ld), %s %s %s" +#string STR_DEBUGSUPPORT_INFO #language en-US " Isa = %s" +#string STR_DEBUGSUPPORT_UNKNOWN #language en-US " Unknown (%%H%s%%N)" + +#string STR_PCIRB_DUMP_PH #language en-US " ParentHandle..: %%H%x%%N\r\n" +#string STR_PCIRB_DUMP_SEG #language en-US " Segment #.....: %%H%x%%N\r\n" +#string STR_PCIRB_DUMP_ATT #language en-US " Attributes....: %%H%x%%N\r\n" +#string STR_PCIRB_DUMP_SUPPORTS #language en-US " Supports......: %%H%x%%N\r\n" +#string STR_PCIRB_DUMP_BUS #language en-US " BUS : " +#string STR_PCIRB_DUMP_MEM #language en-US " MEM : " +#string STR_PCIRB_DUMP_IO #language en-US " IO : " +#string STR_PCIRB_DUMP_TITLE #language en-US " Type Flag Base Limit Gran\r\n" + " ==== ==== ================ ================ ====" +#string STR_PCIIO_DUMP_MAIN #language en-US " Segment #.....: %02x\r\n" + " Bus #.........: %02x\r\n" + " Device #......: %02x\r\n" + " Function #....: %02x\r\n" + " ROM Size......: %lx\r\n" + " ROM Location..: %08x\r\n" + " Vendor ID.....: %04x\r\n" + " Device ID.....: %04x\r\n" + " Class Code....: %02x %02x %02x\r\n" + " Configuration Header :" +#string STR_USBIO_DUMP_MAIN #language en-US " Interface Number #.....: %02x\r\n" + " Interface Class #......: %02x\r\n" + " Interface Subclass #...: %02x\r\n" + " Interface Protocol #...: %02x" + +#string STR_LI_DUMP_NAME #language en-US " Name..........: %%H%s%%N\r\n" + +#string STR_LI_DUMP_MAIN #language en-US " Revision......: %%H0x%08x%%N\r\n" + " ParentHandle..: %%H%x%%N\r\n" + " SystemTable...: %%H%x%%N\r\n" + " DeviceHandle..: %%H%x%%N\r\n" + " FilePath......: %%H%s%%N\r\n" + " PdbFileName...: %%H%a%%N\r\n" + " OptionsSize...: %%H%x%%N\r\n" + " LoadOptions...: %%H%x%%N\r\n" + " ImageBase.....: %%H%x%%N\r\n" + " ImageSize.....: %%H%Lx%%N\r\n" + " CodeType......: %%H%s%%N\r\n" + " DataType......: %%H%s%%N\r\n" + " Unload........: %%H%x%%N" + +#string STR_GOP_DUMP_MAIN #language en-US " Max Mode..............: %%H0x%08x%%N\r\n" + " Current Mode..........: %%H0x%08x%%N\r\n" + " Frame Buffer Base.....: %%H0x%L016x%%N\r\n" + " Frame Buffer Size.....: %%H0x%L016x%%N\r\n" + " Mode Info Size........: %%H0x%L016x%%N\r\n" + " Information\r\n" + " Version.............: %%H0x%08x%%N\r\n" + " HorizontalResolution: %%H%d%%N\r\n" + " VerticalResolution..: %%H%d%%N\r\n" + " Pixel Format........: %%H%s%%N\r\n" + " Pixels / Scan Line..: %%H%d%%N\r\n" + " Pixel Info\r\n" + " RedMask...........: %%H0x%08x%%N\r\n" + " GreenMask.........: %%H0x%08x%%N\r\n" + " BlueMask..........: %%H0x%08x%%N\r\n" + +#string STR_GOP_RES_LIST_MAIN #language en-US " Supported Resolution List" +#string STR_GOP_RES_LIST_ENTRY #language en-US "\r\n" + " Resolution[%%H%d%%N]:\r\n" + " Horizontal........: %%H%d%%N\r\n" + " Vertical..........: %%H%d%%N" +#string STR_BSDO_DUMP_MAIN #language en-US " Drv[%02x] File:%%H%s%%N" +#string STR_EDID_DISCOVERED_MAIN #language en-US " EDID Discovered Size : %%H0x%08x%%N\r\n" +#string STR_EDID_DISCOVERED_DATA #language en-US " EDID Discovered Data :\r\n" +#string STR_EDID_ACTIVE_MAIN #language en-US " EDID Active Size : %%H0x%08x%%N\r\n" +#string STR_EDID_ACTIVE_DATA #language en-US " EDID Active Data :\r\n" + +#string STR_GET_SUPP_TYPES_FAILED #language en-US "Unable to get supported types - %%H%r%%N\r\n" +#string STR_SUPP_TYPE_HEADER #language en-US " Supported Information Types: \r\n" +#string STR_GUID_NUMBER #language en-US " Guid[%%H%d%%N] : %g" +#string STR_GUID_STRING #language en-US " - %%B%s%%N\r\n" +#string STR_GETINFO_FAILED #language en-US " Unable to get information - %%H%r%%N\r\n" +#string STR_MEDIA_STATE #language en-US " MediaState: %%H0x%08x - %r%%N\r\n" +#string STR_NETWORK_BOOT_INFO #language en-US "" + " iSsciIpv4BootCapablity : %%H%d%%N\r\n" + " iScsiIpv6BootCapablity : %%H%d%%N\r\n" + " FCoeBootCapablity : %%H%d%%N\r\n" + " OffloadCapability : %%H%d%%N\r\n" + " iScsiMpioCapability : %%H%d%%N\r\n" + " iScsiIpv4Boot : %%H%d%%N\r\n" + " iScsiIpv6Boot : %%H%d%%N\r\n" + " FCoeBoot : %%H%d%%N\r\n" +#string STR_SAN_MAC_ADDRESS_INFO #language en-US " SanMacAddress: %%H%02x-%02x-%02x-%02x-%02x-%02x%%N \r\n" +#string STR_UNDI_IPV6_INFO #language en-US " UNDI IPv6 Supported: %%H%d%%N \r\n" +#string STR_UNKNOWN_INFO_TYPE #language en-US " The 'InformationType' - %%H%g%%N can't be recongnized\r\n" + +#string STR_FMP_IMAGEID_NON_UNIQUE #language en-US " The ImageId value for each Firmware Image is not unique.\r\n" +#string STR_FMP_IMAGE_INFO_SIZE #language en-US " ImageInfoSize: %%H0x%L016x%%N\r\n" +#string STR_FMP_DESCRIPTOR_VERSION #language en-US " DescriptorVersion: %%H%d%%N\r\n" +#string STR_FMP_DESCRIPTOR_COUNT #language en-US " DescriptorCount : %%H%d%%N\r\n" +#string STR_FMP_DESCRIPTOR_SIZE #language en-US " DescriptorSize : %%H0x%Lx%%N\r\n" +#string STR_FMP_PACKAGE_VERSION #language en-US " PackageVersion : %%H0x%08x%%N\r\n" +#string STR_FMP_PACKAGE_VERSION_NAME #language en-US " PackageVersionName : %%H%s%%N\r\n" +#string STR_FMP_IMAGE_DESCRIPTOR_INFO #language en-US "" + " ImageInfo[%%H%d%%N]:\r\n" + " =============\r\n" + " ImageIndex : %%H%d%%N\r\n" + " ImageTypeId : %%H%g%%N\r\n" + " ImageId : %%H%L016x%%N\r\n" + " ImageIdName : %%H%s%%N\r\n" + " Version : %%H0x%08x%%N\r\n" + " VersionName : %%H%s%%N\r\n" + " Size : %%H0x%L016x%%N\r\n" + " AttributesSupported : %%H0x%L016x%%N\r\n" + " AttributesSetting : %%H%s%%N\r\n" + " Compatibilities : %%H0x%L016x%%N\r\n" + " LowestSupportedImageVersion : %%H0x%08x%%N\r\n" + " LastAttemptVersion : %%H0x%08x%%N\r\n" + " LastAttemptStatus : %%H0x%08x%%N\r\n" + " HardwareInstance : %%H0x%08x%%N\r\n" + +#string STR_FMP_IMAGE_DESCRIPTOR_INFO_V1 #language en-US "" + " ImageInfo[%%H%d%%N]:\r\n" + " =============\r\n" + " ImageIndex : %%H%d%%N\r\n" + " ImageTypeId : %%H%g%%N\r\n" + " ImageId : %%H%L016x%%N\r\n" + " ImageIdName : %%H%s%%N\r\n" + " Version : %%H0x%08x%%N\r\n" + " VersionName : %%H%s%%N\r\n" + " Size : %%H0x%L016x%%N\r\n" + " AttributesSupported : %%H0x%L016x%%N\r\n" + " AttributesSetting : %%H%s%%N\r\n" + " Compatibilities : %%H0x%L016x%%N\r\n" + +#string STR_FMP_IMAGE_DESCRIPTOR_INFO_V2 #language en-US "" + " ImageInfo[%%H%d%%N]:\r\n" + " =============\r\n" + " ImageIndex : %%H%d%%N\r\n" + " ImageTypeId : %%H%g%%N\r\n" + " ImageId : %%H%L016x%%N\r\n" + " ImageIdName : %%H%s%%N\r\n" + " Version : %%H0x%08x%%N\r\n" + " VersionName : %%H%s%%N\r\n" + " Size : %%H0x%L016x%%N\r\n" + " AttributesSupported : %%H0x%L016x%%N\r\n" + " AttributesSetting : %%H%s%%N\r\n" + " Compatibilities : %%H0x%L016x%%N\r\n" + " LowestSupportedImageVersion : %%H0x%08x%%N\r\n" + +#string STR_PARTINFO_DUMP_TYPE_OTHER #language en-US " Partition Type : Other" +#string STR_PARTINFO_DUMP_TYPE_MBR #language en-US " Partition Type : MBR" +#string STR_PARTINFO_DUMP_TYPE_GPT #language en-US " Partition Type : GPT" +#string STR_PARTINFO_DUMP_EFI_SYS_PART #language en-US " EFI System Partition : Yes" +#string STR_PARTINFO_DUMP_NOT_EFI_SYS_PART #language en-US " EFI System Partition : No" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c new file mode 100644 index 0000000..1e504e7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c @@ -0,0 +1,692 @@ +/** @file + ACPI parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiView.h" + +STATIC UINT32 gIndent; +STATIC UINT32 mTableErrorCount; +STATIC UINT32 mTableWarningCount; + +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + An ACPI_PARSER array describing the ACPI header. +**/ +STATIC CONST ACPI_PARSER AcpiHeaderParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) +}; + +/** + This function resets the ACPI table error counter to Zero. +**/ +VOID +ResetErrorCount ( + VOID + ) +{ + mTableErrorCount = 0; +} + +/** + This function returns the ACPI table error count. + + @retval Returns the count of errors detected in the ACPI tables. +**/ +UINT32 +GetErrorCount ( + VOID + ) +{ + return mTableErrorCount; +} + +/** + This function resets the ACPI table warning counter to Zero. +**/ +VOID +ResetWarningCount ( + VOID + ) +{ + mTableWarningCount = 0; +} + +/** + This function returns the ACPI table warning count. + + @retval Returns the count of warning detected in the ACPI tables. +**/ +UINT32 +GetWarningCount ( + VOID + ) +{ + return mTableWarningCount; +} + +/** + This function increments the ACPI table error counter. +**/ +VOID +EFIAPI +IncrementErrorCount ( + VOID + ) +{ + mTableErrorCount++; +} + +/** + This function increments the ACPI table warning counter. +**/ +VOID +EFIAPI +IncrementWarningCount ( + VOID + ) +{ + mTableWarningCount++; +} + +/** + This function verifies the ACPI table checksum. + + This function verifies the checksum for the ACPI table and optionally + prints the status. + + @param [in] Log If TRUE log the status of the checksum. + @param [in] Ptr Pointer to the start of the table buffer. + @param [in] Length The length of the buffer. + + @retval TRUE The checksum is OK. + @retval FALSE The checksum failed. +**/ +BOOLEAN +EFIAPI +VerifyChecksum ( + IN BOOLEAN Log, + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + UINTN ByteCount; + UINT8 Checksum; + UINTN OriginalAttribute; + + ByteCount = 0; + Checksum = 0; + + while (ByteCount < Length) { + Checksum += *(Ptr++); + ByteCount++; + } + + if (Log) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + if (Checksum == 0) { + if (GetColourHighlighting ()) { + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR (EFI_GREEN, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print (L"\n\nTable Checksum : OK\n\n"); + } else { + IncrementErrorCount (); + if (GetColourHighlighting ()) { + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR (EFI_RED, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print (L"\n\nTable Checksum : FAILED (0x%X)\n\n", Checksum); + } + if (GetColourHighlighting ()) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + + return (Checksum == 0); +} + +/** + This function performs a raw data dump of the ACPI table. + + @param [in] Ptr Pointer to the start of the table buffer. + @param [in] Length The length of the buffer. +**/ +VOID +EFIAPI +DumpRaw ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + UINTN ByteCount; + UINTN PartLineChars; + UINTN AsciiBufferIndex; + CHAR8 AsciiBuffer[17]; + + ByteCount = 0; + AsciiBufferIndex = 0; + + Print (L"Address : 0x%p\n", Ptr); + Print (L"Length : %d\n", Length); + + while (ByteCount < Length) { + if ((ByteCount & 0x0F) == 0) { + AsciiBuffer[AsciiBufferIndex] = '\0'; + Print (L" %a\n%08X : ", AsciiBuffer, ByteCount); + AsciiBufferIndex = 0; + } else if ((ByteCount & 0x07) == 0) { + Print (L"- "); + } + + if ((*Ptr >= ' ') && (*Ptr < 0x7F)) { + AsciiBuffer[AsciiBufferIndex++] = *Ptr; + } else { + AsciiBuffer[AsciiBufferIndex++] = '.'; + } + + Print (L"%02X ", *Ptr++); + + ByteCount++; + } + + // Justify the final line using spaces before printing + // the ASCII data. + PartLineChars = (Length & 0x0F); + if (PartLineChars != 0) { + PartLineChars = 48 - (PartLineChars * 3); + if ((Length & 0x0F) <= 8) { + PartLineChars += 2; + } + while (PartLineChars > 0) { + Print (L" "); + PartLineChars--; + } + } + + // Print ASCII data for the final line. + AsciiBuffer[AsciiBufferIndex] = '\0'; + Print (L" %a", AsciiBuffer); +} + +/** + This function traces 1 byte of data as specified in the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint8 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ) +{ + Print (Format, *Ptr); +} + +/** + This function traces 2 bytes of data as specified in the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint16 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ) +{ + Print (Format, *(UINT16*)Ptr); +} + +/** + This function traces 4 bytes of data as specified in the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint32 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ) +{ + Print (Format, *(UINT32*)Ptr); +} + +/** + This function traces 8 bytes of data as specified by the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint64 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ) +{ + // Some fields are not aligned and this causes alignment faults + // on ARM platforms if the compiler generates LDRD instructions. + // Perform word access so that LDRD instructions are not generated. + UINT64 Val; + + Val = *(UINT32*)(Ptr + sizeof (UINT32)); + + Val <<= 32; + Val |= (UINT64)*(UINT32*)Ptr; + + Print (Format, Val); +} + +/** + This function traces 3 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump3Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ) +{ + Print ( + (Format != NULL) ? Format : L"%c%c%c", + Ptr[0], + Ptr[1], + Ptr[2] + ); +} + +/** + This function traces 4 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump4Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ) +{ + Print ( + (Format != NULL) ? Format : L"%c%c%c%c", + Ptr[0], + Ptr[1], + Ptr[2], + Ptr[3] + ); +} + +/** + This function traces 6 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump6Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ) +{ + Print ( + (Format != NULL) ? Format : L"%c%c%c%c%c%c", + Ptr[0], + Ptr[1], + Ptr[2], + Ptr[3], + Ptr[4], + Ptr[5] + ); +} + +/** + This function traces 8 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump8Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ) +{ + Print ( + (Format != NULL) ? Format : L"%c%c%c%c%c%c%c%c", + Ptr[0], + Ptr[1], + Ptr[2], + Ptr[3], + Ptr[4], + Ptr[5], + Ptr[6], + Ptr[7] + ); +} + +/** + This function indents and prints the ACPI table Field Name. + + @param [in] Indent Number of spaces to add to the global table indent. + The global table indent is 0 by default; however + this value is updated on entry to the ParseAcpi() + by adding the indent value provided to ParseAcpi() + and restored back on exit. + Therefore the total indent in the output is + dependent on from where this function is called. + @param [in] FieldName Pointer to the Field Name. +**/ +VOID +EFIAPI +PrintFieldName ( + IN UINT32 Indent, + IN CONST CHAR16* FieldName +) +{ + Print ( + L"%*a%-*s : ", + gIndent + Indent, + "", + (OUTPUT_FIELD_COLUMN_WIDTH - gIndent - Indent), + FieldName + ); +} + +/** + This function is used to parse an ACPI table buffer. + + The ACPI table buffer is parsed using the ACPI table parser information + specified by a pointer to an array of ACPI_PARSER elements. This parser + function iterates through each item on the ACPI_PARSER array and logs the + ACPI table fields. + + This function can optionally be used to parse ACPI tables and fetch specific + field values. The ItemPtr member of the ACPI_PARSER structure (where used) + is updated by this parser function to point to the selected field data + (e.g. useful for variable length nested fields). + + @param [in] Trace Trace the ACPI fields TRUE else only parse the + table. + @param [in] Indent Number of spaces to indent the output. + @param [in] AsciiName Optional pointer to an ASCII string that describes + the table being parsed. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer pointed by Ptr. + @param [in] Parser Pointer to an array of ACPI_PARSER structure that + describes the table being parsed. + @param [in] ParserItems Number of items in the ACPI_PARSER array. + + @retval Number of bytes parsed. +**/ +UINT32 +EFIAPI +ParseAcpi ( + IN BOOLEAN Trace, + IN UINT32 Indent, + IN CONST CHAR8* AsciiName OPTIONAL, + IN UINT8* Ptr, + IN UINT32 Length, + IN CONST ACPI_PARSER* Parser, + IN UINT32 ParserItems +) +{ + UINT32 Index; + UINT32 Offset; + BOOLEAN HighLight; + UINTN OriginalAttribute; + + Offset = 0; + + // Increment the Indent + gIndent += Indent; + + if (Trace && (AsciiName != NULL)){ + HighLight = GetColourHighlighting (); + + if (HighLight) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR(EFI_YELLOW, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print ( + L"%*a%-*a :\n", + gIndent, + "", + (OUTPUT_FIELD_COLUMN_WIDTH - gIndent), + AsciiName + ); + if (HighLight) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + + for (Index = 0; Index < ParserItems; Index++) { + if ((Offset + Parser[Index].Length) > Length) { + // We don't parse past the end of the max length specified + break; + } + + if (Offset != Parser[Index].Offset) { + IncrementErrorCount (); + Print ( + L"\nERROR: %a: Offset Mismatch for %s\n" + L"CurrentOffset = %d FieldOffset = %d\n", + AsciiName, + Parser[Index].NameStr, + Offset, + Parser[Index].Offset + ); + } + + if (Trace) { + // if there is a Formatter function let the function handle + // the printing else if a Format is specified in the table use + // the Format for printing + PrintFieldName (2, Parser[Index].NameStr); + if (Parser[Index].PrintFormatter != NULL) { + Parser[Index].PrintFormatter (Parser[Index].Format, Ptr); + } else if (Parser[Index].Format != NULL) { + switch (Parser[Index].Length) { + case 1: + DumpUint8 (Parser[Index].Format, Ptr); + break; + case 2: + DumpUint16 (Parser[Index].Format, Ptr); + break; + case 4: + DumpUint32 (Parser[Index].Format, Ptr); + break; + case 8: + DumpUint64 (Parser[Index].Format, Ptr); + break; + default: + Print ( + L"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n", + AsciiName, + Parser[Index].Length + ); + } // switch + + // Validating only makes sense if we are tracing + // the parsed table entries, to report by table name. + if (Parser[Index].FieldValidator != NULL) { + Parser[Index].FieldValidator (Ptr, Parser[Index].Context); + } + } + Print (L"\n"); + } // if (Trace) + + if (Parser[Index].ItemPtr != NULL) { + *Parser[Index].ItemPtr = (VOID*)Ptr; + } + + Ptr += Parser[Index].Length; + Offset += Parser[Index].Length; + } // for + + // Decrement the Indent + gIndent -= Indent; + return Offset; +} + +/** + An array describing the ACPI Generic Address Structure. + The GasParser array is used by the ParseAcpi function to parse and/or trace + the GAS structure. +**/ +STATIC CONST ACPI_PARSER GasParser[] = { + {L"Address Space ID", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Register Bit Width", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Register Bit Offset", 1, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Address Size", 1, 3, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL} +}; + +/** + This function indents and traces the GAS structure as described by the GasParser. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Indent Number of spaces to indent the output. +**/ +VOID +EFIAPI +DumpGasStruct ( + IN UINT8* Ptr, + IN UINT32 Indent + ) +{ + Print (L"\n"); + ParseAcpi ( + TRUE, + Indent, + NULL, + Ptr, + GAS_LENGTH, + PARSER_PARAMS (GasParser) + ); +} + +/** + This function traces the GAS structure as described by the GasParser. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpGas ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ) +{ + DumpGasStruct (Ptr, 2); +} + +/** + This function traces the ACPI header as described by the AcpiHeaderParser. + + @param [in] Ptr Pointer to the start of the buffer. + + @retval Number of bytes parsed. +**/ +UINT32 +EFIAPI +DumpAcpiHeader ( + IN UINT8* Ptr + ) +{ + return ParseAcpi ( + TRUE, + 0, + "ACPI Table Header", + Ptr, + ACPI_DESCRIPTION_HEADER_LENGTH, + PARSER_PARAMS (AcpiHeaderParser) + ); +} + +/** + This function parses the ACPI header as described by the AcpiHeaderParser. + + This function optionally returns the signature, length and revision of the + ACPI table. + + @param [in] Ptr Pointer to the start of the buffer. + @param [out] Signature Gets location of the ACPI table signature. + @param [out] Length Gets location of the length of the ACPI table. + @param [out] Revision Gets location of the revision of the ACPI table. + + @retval Number of bytes parsed. +**/ +UINT32 +EFIAPI +ParseAcpiHeader ( + IN UINT8* Ptr, + OUT CONST UINT32** Signature, + OUT CONST UINT32** Length, + OUT CONST UINT8** Revision + ) +{ + UINT32 BytesParsed; + + BytesParsed = ParseAcpi ( + FALSE, + 0, + NULL, + Ptr, + ACPI_DESCRIPTION_HEADER_LENGTH, + PARSER_PARAMS (AcpiHeaderParser) + ); + + *Signature = AcpiHdrInfo.Signature; + *Length = AcpiHdrInfo.Length; + *Revision = AcpiHdrInfo.Revision; + + return BytesParsed; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h new file mode 100644 index 0000000..ea17c54 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h @@ -0,0 +1,815 @@ +/** @file + Header file for ACPI parser + + Copyright (c) 2016 - 2019, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef ACPIPARSER_H_ +#define ACPIPARSER_H_ + +#define OUTPUT_FIELD_COLUMN_WIDTH 36 + +/// The RSDP table signature is "RSD PTR " (8 bytes) +/// However The signature for ACPI tables is 4 bytes. +/// To work around this oddity define a signature type +/// that allows us to process the log options. +#define RSDP_TABLE_INFO SIGNATURE_32('R', 'S', 'D', 'P') + +/** + This function increments the ACPI table error counter. +**/ +VOID +EFIAPI +IncrementErrorCount ( + VOID + ); + +/** + This function increments the ACPI table warning counter. +**/ +VOID +EFIAPI +IncrementWarningCount ( + VOID + ); + +/** + This function verifies the ACPI table checksum. + + This function verifies the checksum for the ACPI table and optionally + prints the status. + + @param [in] Log If TRUE log the status of the checksum. + @param [in] Ptr Pointer to the start of the table buffer. + @param [in] Length The length of the buffer. + + @retval TRUE The checksum is OK. + @retval FALSE The checksum failed. +**/ +BOOLEAN +EFIAPI +VerifyChecksum ( + IN BOOLEAN Log, + IN UINT8* Ptr, + IN UINT32 Length + ); + +/** + This function performs a raw data dump of the ACPI table. + + @param [in] Ptr Pointer to the start of the table buffer. + @param [in] Length The length of the buffer. +**/ +VOID +EFIAPI +DumpRaw ( + IN UINT8* Ptr, + IN UINT32 Length + ); + +/** + This function traces 1 byte of datum as specified in the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint8 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ); + +/** + This function traces 2 bytes of data as specified in the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint16 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ); + +/** + This function traces 4 bytes of data as specified in the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint32 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ); + +/** + This function traces 8 bytes of data as specified by the format string. + + @param [in] Format The format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpUint64 ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ); + +/** + This function traces 3 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump3Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ); + +/** + This function traces 4 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump4Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ); + +/** + This function traces 6 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump6Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ); + +/** + This function traces 8 characters which can be optionally + formated using the format string if specified. + + If no format string is specified the Format must be NULL. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +Dump8Chars ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ); + +/** + This function indents and prints the ACPI table Field Name. + + @param [in] Indent Number of spaces to add to the global table + indent. The global table indent is 0 by default; + however this value is updated on entry to the + ParseAcpi() by adding the indent value provided to + ParseAcpi() and restored back on exit. Therefore + the total indent in the output is dependent on from + where this function is called. + @param [in] FieldName Pointer to the Field Name. +**/ +VOID +EFIAPI +PrintFieldName ( + IN UINT32 Indent, + IN CONST CHAR16* FieldName + ); + +/** + This function pointer is the template for customizing the trace output + + @param [in] Format Format string for tracing the data as specified by + the 'Format' member of ACPI_PARSER. + @param [in] Ptr Pointer to the start of the buffer. +**/ +typedef VOID (EFIAPI *FNPTR_PRINT_FORMATTER)(CONST CHAR16* Format, UINT8* Ptr); + +/** + This function pointer is the template for validating an ACPI table field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information as specified by + the 'Context' member of the ACPI_PARSER. + e.g. this could be a pointer to the ACPI table header. +**/ +typedef VOID (EFIAPI *FNPTR_FIELD_VALIDATOR)(UINT8* Ptr, VOID* Context); + +/** + The ACPI_PARSER structure describes the fields of an ACPI table and + provides means for the parser to interpret and trace appropriately. + + The first three members are populated based on information present in + in the ACPI table specifications. The remaining members describe how + the parser should report the field information, validate the field data + and/or update an external pointer to the field (ItemPtr). + + ParseAcpi() uses the format string specified by 'Format' for tracing + the field data. If the field is more complex and requires additional + processing for formatting and representation a print formatter function + can be specified in 'PrintFormatter'. + The PrintFormatter function may choose to use the format string + specified by 'Format' or use its own internal format string. + + The 'Format' and 'PrintFormatter' members allow flexibility for + representing the field data. +**/ +typedef struct AcpiParser { + + /// String describing the ACPI table field + /// (Field column from ACPI table spec) + CONST CHAR16* NameStr; + + /// The length of the field. + /// (Byte Length column from ACPI table spec) + UINT32 Length; + + /// The offset of the field from the start of the table. + /// (Byte Offset column from ACPI table spec) + UINT32 Offset; + + /// Optional Print() style format string for tracing the data. If not + /// used this must be set to NULL. + CONST CHAR16* Format; + + /// Optional pointer to a print formatter function which + /// is typically used to trace complex field information. + /// If not used this must be set to NULL. + /// The Format string is passed to the PrintFormatter function + /// but may be ignored by the implementation code. + FNPTR_PRINT_FORMATTER PrintFormatter; + + /// Optional pointer which may be set to request the parser to update + /// a pointer to the field data. If unused this must be set to NULL. + VOID** ItemPtr; + + /// Optional pointer to a field validator function. + /// The function should directly report any appropriate error or warning + /// and invoke the appropriate counter update function. + /// If not used this parameter must be set to NULL. + FNPTR_FIELD_VALIDATOR FieldValidator; + + /// Optional pointer to context specific information, + /// which the Field Validator function can use to determine + /// additional information about the ACPI table and make + /// decisions about the field being validated. + /// e.g. this could be a pointer to the ACPI table header + VOID* Context; +} ACPI_PARSER; + +/** + A structure used to store the pointers to the members of the + ACPI description header structure that was parsed. +**/ +typedef struct AcpiDescriptionHeaderInfo { + /// ACPI table signature + UINT32* Signature; + /// Length of the ACPI table + UINT32* Length; + /// Revision + UINT8* Revision; + /// Checksum + UINT8* Checksum; + /// OEM Id - length is 6 bytes + UINT8* OemId; + /// OEM table Id + UINT64* OemTableId; + /// OEM revision Id + UINT32* OemRevision; + /// Creator Id + UINT32* CreatorId; + /// Creator revision + UINT32* CreatorRevision; +} ACPI_DESCRIPTION_HEADER_INFO; + +/** + This function is used to parse an ACPI table buffer. + + The ACPI table buffer is parsed using the ACPI table parser information + specified by a pointer to an array of ACPI_PARSER elements. This parser + function iterates through each item on the ACPI_PARSER array and logs the + ACPI table fields. + + This function can optionally be used to parse ACPI tables and fetch specific + field values. The ItemPtr member of the ACPI_PARSER structure (where used) + is updated by this parser function to point to the selected field data + (e.g. useful for variable length nested fields). + + @param [in] Trace Trace the ACPI fields TRUE else only parse the + table. + @param [in] Indent Number of spaces to indent the output. + @param [in] AsciiName Optional pointer to an ASCII string that describes + the table being parsed. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer pointed by Ptr. + @param [in] Parser Pointer to an array of ACPI_PARSER structure that + describes the table being parsed. + @param [in] ParserItems Number of items in the ACPI_PARSER array. + + @retval Number of bytes parsed. +**/ +UINT32 +EFIAPI +ParseAcpi ( + IN BOOLEAN Trace, + IN UINT32 Indent, + IN CONST CHAR8* AsciiName OPTIONAL, + IN UINT8* Ptr, + IN UINT32 Length, + IN CONST ACPI_PARSER* Parser, + IN UINT32 ParserItems + ); + +/** + This is a helper macro to pass parameters to the Parser functions. + + @param [in] Parser The name of the ACPI_PARSER array describing the + ACPI table fields. +**/ +#define PARSER_PARAMS(Parser) Parser, sizeof (Parser) / sizeof (Parser[0]) + +/** + This is a helper macro for describing the ACPI header fields. + + @param [out] Info Pointer to retrieve the ACPI table header information. +**/ +#define PARSE_ACPI_HEADER(Info) \ + { L"Signature", 4, 0, NULL, Dump4Chars, \ + (VOID**)&(Info)->Signature , NULL, NULL }, \ + { L"Length", 4, 4, L"%d", NULL, \ + (VOID**)&(Info)->Length, NULL, NULL }, \ + { L"Revision", 1, 8, L"%d", NULL, \ + (VOID**)&(Info)->Revision, NULL, NULL }, \ + { L"Checksum", 1, 9, L"0x%X", NULL, \ + (VOID**)&(Info)->Checksum, NULL, NULL }, \ + { L"Oem ID", 6, 10, NULL, Dump6Chars, \ + (VOID**)&(Info)->OemId, NULL, NULL }, \ + { L"Oem Table ID", 8, 16, NULL, Dump8Chars, \ + (VOID**)&(Info)->OemTableId, NULL, NULL }, \ + { L"Oem Revision", 4, 24, L"0x%X", NULL, \ + (VOID**)&(Info)->OemRevision, NULL, NULL }, \ + { L"Creator ID", 4, 28, NULL, Dump4Chars, \ + (VOID**)&(Info)->CreatorId, NULL, NULL }, \ + { L"Creator Revision", 4, 32, L"0x%X", NULL, \ + (VOID**)&(Info)->CreatorRevision, NULL, NULL } + +/** + Length of the ACPI GAS structure. + + NOTE: This might normally be defined as + sizeof (EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE). + However, we deliberately minimise any reference to the EDK2 ACPI + headers in an attempt to provide cross checking. +**/ +#define GAS_LENGTH 12 + +/** + Length of the ACPI Header structure. + + NOTE: This might normally be defined as + sizeof (EFI_ACPI_DESCRIPTION_HEADER). + However, we deliberately minimise any reference to the EDK2 ACPI + headers in an attempt to provide cross checking. +**/ +#define ACPI_DESCRIPTION_HEADER_LENGTH 36 + +/** + This function indents and traces the GAS structure as described by the GasParser. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Indent Number of spaces to indent the output. +**/ +VOID +EFIAPI +DumpGasStruct ( + IN UINT8* Ptr, + IN UINT32 Indent + ); + +/** + This function traces the GAS structure as described by the GasParser. + + @param [in] Format Optional format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +VOID +EFIAPI +DumpGas ( + IN CONST CHAR16* Format OPTIONAL, + IN UINT8* Ptr + ); + +/** + This function traces the ACPI header as described by the AcpiHeaderParser. + + @param [in] Ptr Pointer to the start of the buffer. + + @retval Number of bytes parsed. +**/ +UINT32 +EFIAPI +DumpAcpiHeader ( + IN UINT8* Ptr + ); + +/** + This function parses the ACPI header as described by the AcpiHeaderParser. + + This function optionally returns the Signature, Length and revision of the + ACPI table. + + @param [in] Ptr Pointer to the start of the buffer. + @param [out] Signature Gets location of the ACPI table signature. + @param [out] Length Gets location of the length of the ACPI table. + @param [out] Revision Gets location of the revision of the ACPI table. + + @retval Number of bytes parsed. +**/ +UINT32 +EFIAPI +ParseAcpiHeader ( + IN UINT8* Ptr, + OUT CONST UINT32** Signature, + OUT CONST UINT32** Length, + OUT CONST UINT8** Revision + ); + +/** + This function parses the ACPI BGRT table. + When trace is enabled this function parses the BGRT table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiBgrt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI DBG2 table. + When trace is enabled this function parses the DBG2 table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiDbg2 ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI DSDT table. + When trace is enabled this function parses the DSDT table and + traces the ACPI table fields. + For the DSDT table only the ACPI header fields are parsed and + traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiDsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI FADT table. + This function parses the FADT table and optionally traces the ACPI + table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiFadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI GTDT table. + When trace is enabled this function parses the GTDT table and + traces the ACPI table fields. + + This function also parses the following platform timer structures: + - GT Block timer + - Watchdog timer + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiGtdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI IORT table. + When trace is enabled this function parses the IORT table and + traces the ACPI fields. + + This function also parses the following nodes: + - ITS Group + - Named Component + - Root Complex + - SMMUv1/2 + - SMMUv3 + - PMCG + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiIort ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI MADT table. + When trace is enabled this function parses the MADT table and + traces the ACPI table fields. + + This function currently parses the following Interrupt Controller + Structures: + - GICC + - GICD + - GIC MSI Frame + - GICR + - GIC ITS + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiMadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI MCFG table. + When trace is enabled this function parses the MCFG table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiMcfg ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI PPTT table. + When trace is enabled this function parses the PPTT table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiPptt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI RSDP table. + + This function invokes the parser for the XSDT table. + * Note - This function does not support parsing of RSDT table. + + This function also performs a RAW dump of the ACPI table and + validates the checksum. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiRsdp ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI SLIT table. + When trace is enabled this function parses the SLIT table and + traces the ACPI table fields. + + This function also validates System Localities for the following: + - Diagonal elements have a normalized value of 10 + - Relative distance from System Locality at i*N+j is same as + j*N+i + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSlit ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI SPCR table. + When trace is enabled this function parses the SPCR table and + traces the ACPI table fields. + + This function also performs validations of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSpcr ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI SRAT table. + When trace is enabled this function parses the SRAT table and + traces the ACPI table fields. + + This function parses the following Resource Allocation Structures: + - Processor Local APIC/SAPIC Affinity Structure + - Memory Affinity Structure + - Processor Local x2APIC Affinity Structure + - GICC Affinity Structure + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSrat ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI SSDT table. + When trace is enabled this function parses the SSDT table and + traces the ACPI table fields. + For the SSDT table only the ACPI header fields are + parsed and traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + This function parses the ACPI XSDT table + and optionally traces the ACPI table fields. + + This function also performs validation of the XSDT table. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiXsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +#endif // ACPIPARSER_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c new file mode 100644 index 0000000..934fda3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c @@ -0,0 +1,220 @@ +/** @file + ACPI table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" +#include "AcpiView.h" + +/** + A list of registered ACPI table parsers. +**/ +STATIC ACPI_TABLE_PARSER mTableParserList[MAX_ACPI_TABLE_PARSERS]; + +/** + Register the ACPI table Parser + + This function registers the ACPI table parser. + + @param [in] Signature The ACPI table signature. + @param [in] ParserProc The ACPI table parser. + + @retval EFI_SUCCESS The parser is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The parser for the Table + was already registered. + @retval EFI_OUT_OF_RESOURCES No space to register the + parser. +**/ +EFI_STATUS +EFIAPI +RegisterParser ( + IN UINT32 Signature, + IN PARSE_ACPI_TABLE_PROC ParserProc + ) +{ + UINT32 Index; + + if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Search if a parser is already installed + for (Index = 0; + Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + Index++) + { + if (Signature == mTableParserList[Index].Signature) { + if (mTableParserList[Index].Parser != NULL) { + return EFI_ALREADY_STARTED; + } + } + } + + // Find the first free slot and register the parser + for (Index = 0; + Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + Index++) + { + if (mTableParserList[Index].Signature == ACPI_PARSER_SIGNATURE_NULL) { + mTableParserList[Index].Signature = Signature; + mTableParserList[Index].Parser = ParserProc; + return EFI_SUCCESS; + } + } + + // No free slot found + return EFI_OUT_OF_RESOURCES; +} + +/** + Deregister the ACPI table Parser + + This function deregisters the ACPI table parser. + + @param [in] Signature The ACPI table signature. + + @retval EFI_SUCCESS The parser was deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +**/ +EFI_STATUS +EFIAPI +DeregisterParser ( + IN UINT32 Signature + ) +{ + UINT32 Index; + + if (Signature == ACPI_PARSER_SIGNATURE_NULL) { + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; + Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + Index++) + { + if (Signature == mTableParserList[Index].Signature) { + mTableParserList[Index].Signature = ACPI_PARSER_SIGNATURE_NULL; + mTableParserList[Index].Parser = NULL; + return EFI_SUCCESS; + } + } + + // No matching registered parser found. + return EFI_NOT_FOUND; +} + +/** + Get the ACPI table Parser + + This function returns the ACPI table parser proc from the list of + registered parsers. + + @param [in] Signature The ACPI table signature. + @param [out] ParserProc Pointer to a ACPI table parser proc. + + @retval EFI_SUCCESS The parser was returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +**/ +EFI_STATUS +EFIAPI +GetParser ( + IN UINT32 Signature, + OUT PARSE_ACPI_TABLE_PROC * ParserProc + ) +{ + UINT32 Index; + + if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) { + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; + Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); + Index++) + { + if (Signature == mTableParserList[Index].Signature) { + *ParserProc = mTableParserList[Index].Parser; + return EFI_SUCCESS; + } + } + + // No matching registered parser found. + return EFI_NOT_FOUND; +} + +/** + This function processes the ACPI tables. + This function calls ProcessTableReportOptions() to list the ACPI + tables, perform binary dump of the tables and determine if the + ACPI fields should be traced. + + This function also invokes the parser for the ACPI tables. + + This function also performs a RAW dump of the ACPI table including + the unknown/unparsed ACPI tables and validates the checksum. + + @param [in] Ptr Pointer to the start of the ACPI + table data buffer. +**/ +VOID +EFIAPI +ProcessAcpiTable ( + IN UINT8* Ptr + ) +{ + EFI_STATUS Status; + BOOLEAN Trace; + CONST UINT32* AcpiTableSignature; + CONST UINT32* AcpiTableLength; + CONST UINT8* AcpiTableRevision; + PARSE_ACPI_TABLE_PROC ParserProc; + + ParseAcpiHeader ( + Ptr, + &AcpiTableSignature, + &AcpiTableLength, + &AcpiTableRevision + ); + + Trace = ProcessTableReportOptions ( + *AcpiTableSignature, + Ptr, + *AcpiTableLength + ); + + if (Trace) { + DumpRaw (Ptr, *AcpiTableLength); + VerifyChecksum (TRUE, Ptr, *AcpiTableLength); + } + + Status = GetParser (*AcpiTableSignature, &ParserProc); + if (EFI_ERROR (Status)) { + // No registered parser found, do default handling. + if (Trace) { + DumpAcpiHeader (Ptr); + } + return; + } + + ParserProc ( + Trace, + Ptr, + *AcpiTableLength, + *AcpiTableRevision + ); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h new file mode 100644 index 0000000..0d9d78c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h @@ -0,0 +1,133 @@ +/** @file + Header file for ACPI table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef ACPITABLEPARSER_H_ +#define ACPITABLEPARSER_H_ + +/** + The maximum number of ACPI table parsers. +*/ +#define MAX_ACPI_TABLE_PARSERS 16 + +/** An invalid/NULL signature value. +*/ +#define ACPI_PARSER_SIGNATURE_NULL 0 + +/** + A function that parses the ACPI table. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +typedef +VOID +(EFIAPI * PARSE_ACPI_TABLE_PROC) ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ); + +/** + The ACPI table parser information +**/ +typedef struct AcpiTableParser { + /// ACPI table signature + UINT32 Signature; + + /// The ACPI table parser function. + PARSE_ACPI_TABLE_PROC Parser; +} ACPI_TABLE_PARSER; + +/** + Register the ACPI table Parser + + This function registers the ACPI table parser. + + @param [in] Signature The ACPI table signature. + @param [in] ParserProc The ACPI table parser. + + @retval EFI_SUCCESS The parser is registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_ALREADY_STARTED The parser for the Table + was already registered. + @retval EFI_OUT_OF_RESOURCES No space to register the + parser. +**/ +EFI_STATUS +EFIAPI +RegisterParser ( + IN UINT32 Signature, + IN PARSE_ACPI_TABLE_PROC ParserProc + ); + +/** + Deregister the ACPI table Parser + + This function deregisters the ACPI table parser. + + @param [in] Signature The ACPI table signature. + + @retval EFI_SUCCESS The parser was deregistered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +**/ +EFI_STATUS +EFIAPI +DeregisterParser ( + IN UINT32 Signature + ); + +/** + This function processes the ACPI tables. + This function calls ProcessTableReportOptions() to list the ACPI + tables, perform binary dump of the tables and determine if the + ACPI fields should be traced. + + This function also invokes the parser for the ACPI tables. + + This function also performs a RAW dump of the ACPI table including + the unknown/unparsed ACPI tables and validates the checksum. + + @param [in] Ptr Pointer to the start of the ACPI + table data buffer. +**/ +VOID +EFIAPI +ProcessAcpiTable ( + IN UINT8* Ptr + ); + +/** + Get the ACPI table Parser + + This function returns the ACPI table parser proc from the list of + registered parsers. + + @param [in] Signature The ACPI table signature. + @param [out] ParserProc Pointer to a ACPI table parser proc. + + @retval EFI_SUCCESS The parser was returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND A registered parser was not found. +**/ +EFI_STATUS +EFIAPI +GetParser ( + IN UINT32 Signature, + OUT PARSE_ACPI_TABLE_PROC * ParserProc + ); + +#endif // ACPITABLEPARSER_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c new file mode 100644 index 0000000..ad65e6b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c @@ -0,0 +1,627 @@ +/** @file + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" +#include "AcpiView.h" +#include "UefiShellAcpiViewCommandLib.h" + +EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL; + +// Report variables +STATIC UINT32 mSelectedAcpiTable; +STATIC CONST CHAR16* mSelectedAcpiTableName; +STATIC BOOLEAN mSelectedAcpiTableFound; +STATIC EREPORT_OPTION mReportType; +STATIC UINT32 mTableCount; +STATIC UINT32 mBinTableCount; +STATIC BOOLEAN mVerbose; +STATIC BOOLEAN mConsistencyCheck; +STATIC BOOLEAN mColourHighlighting; + +/** + An array of acpiview command line parameters. +**/ +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"/?", TypeFlag}, + {L"-c", TypeFlag}, + {L"-d", TypeFlag}, + {L"-h", TypeValue}, + {L"-l", TypeFlag}, + {L"-s", TypeValue}, + {L"-v", TypeFlag}, + {NULL, TypeMax} +}; + +/** + This function returns the colour highlighting status. + + @retval TRUE if colour highlighting is enabled. +**/ +BOOLEAN +GetColourHighlighting ( + VOID + ) +{ + return mColourHighlighting; +} + +/** + This function sets the colour highlighting status. + + @param Highlight The Highlight status. + +**/ +VOID +SetColourHighlighting ( + BOOLEAN Highlight + ) +{ + mColourHighlighting = Highlight; +} + +/** + This function returns the report options. + + @retval Returns the report option. +**/ +STATIC +EREPORT_OPTION +GetReportOption ( + VOID + ) +{ + return mReportType; +} + +/** + This function returns the selected ACPI table. + + @retval Returns signature of the selected ACPI table. +**/ +STATIC +UINT32 +GetSelectedAcpiTable ( + VOID + ) +{ + return mSelectedAcpiTable; +} + +/** + This function dumps the ACPI table to a file. + + @param [in] Ptr Pointer to the ACPI table data. + @param [in] Length The length of the ACPI table. + + @retval TRUE Success. + @retval FALSE Failure. +**/ +STATIC +BOOLEAN +DumpAcpiTableToFile ( + IN CONST UINT8* Ptr, + IN CONST UINTN Length + ) +{ + EFI_STATUS Status; + CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; + SHELL_FILE_HANDLE DumpFileHandle; + UINTN TransferBytes; + + DumpFileHandle = NULL; + TransferBytes = Length; + + UnicodeSPrint ( + FileNameBuffer, + sizeof (FileNameBuffer), + L".\\%s%04d.bin", + mSelectedAcpiTableName, + mBinTableCount++ + ); + + Status = ShellOpenFileByName ( + FileNameBuffer, + &DumpFileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + 0 + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_READONLY_MEDIA), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + return FALSE; + } + + Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer); + + Status = ShellWriteFile ( + DumpFileHandle, + &TransferBytes, + (VOID*)Ptr + ); + if (EFI_ERROR (Status)) { + Print (L"ERROR: Failed to dump table to binary file.\n"); + TransferBytes = 0; + } else { + Print (L"DONE.\n"); + } + + ShellCloseFile (&DumpFileHandle); + return (Length == TransferBytes); +} + +/** + This function processes the table reporting options for the ACPI table. + + @param [in] Signature The ACPI table Signature. + @param [in] TablePtr Pointer to the ACPI table data. + @param [in] Length The length fo the ACPI table. + + @retval Returns TRUE if the ACPI table should be traced. +**/ +BOOLEAN +ProcessTableReportOptions ( + IN CONST UINT32 Signature, + IN CONST UINT8* TablePtr, + IN CONST UINT32 Length + ) +{ + UINTN OriginalAttribute; + UINT8* SignaturePtr; + BOOLEAN Log; + BOOLEAN HighLight; + + SignaturePtr = (UINT8*)(UINTN)&Signature; + Log = FALSE; + HighLight = GetColourHighlighting (); + + switch (GetReportOption ()) { + case ReportAll: + Log = TRUE; + break; + case ReportSelected: + if (Signature == GetSelectedAcpiTable ()) { + Log = TRUE; + mSelectedAcpiTableFound = TRUE; + } + break; + case ReportTableList: + if (mTableCount == 0) { + if (HighLight) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR(EFI_CYAN, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print (L"\nInstalled Table(s):\n"); + if (HighLight) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + Print ( + L"\t%4d. %c%c%c%c\n", + ++mTableCount, + SignaturePtr[0], + SignaturePtr[1], + SignaturePtr[2], + SignaturePtr[3] + ); + break; + case ReportDumpBinFile: + if (Signature == GetSelectedAcpiTable ()) { + mSelectedAcpiTableFound = TRUE; + DumpAcpiTableToFile (TablePtr, Length); + } + break; + case ReportMax: + // We should never be here. + // This case is only present to prevent compiler warning. + break; + } // switch + + if (Log) { + if (HighLight) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR(EFI_LIGHTBLUE, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) + ); + } + Print ( + L"\n\n --------------- %c%c%c%c Table --------------- \n\n", + SignaturePtr[0], + SignaturePtr[1], + SignaturePtr[2], + SignaturePtr[3] + ); + if (HighLight) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + + return Log; +} + +/** + This function converts a string to ACPI table signature. + + @param [in] Str Pointer to the string to be converted to the + ACPI table signature. + + @retval The ACPI table signature. +**/ +STATIC +UINT32 +ConvertStrToAcpiSignature ( + IN CONST CHAR16* Str + ) +{ + UINT8 Index; + CHAR8 Ptr[4]; + + ZeroMem (Ptr, sizeof (Ptr)); + Index = 0; + + // Convert to Upper case and convert to ASCII + while ((Index < 4) && (Str[Index] != 0)) { + if (Str[Index] >= L'a' && Str[Index] <= L'z') { + Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A')); + } else { + Ptr[Index] = (CHAR8)Str[Index]; + } + Index++; + } + return *(UINT32*)Ptr; +} + +/** + This function iterates the configuration table entries in the + system table, retrieves the RSDP pointer and starts parsing the ACPI tables. + + @param [in] SystemTable Pointer to the EFI system table. + + @retval Returns EFI_NOT_FOUND if the RSDP pointer is not found. + Returns EFI_UNSUPPORTED if the RSDP version is less than 2. + Returns EFI_SUCCESS if successful. +**/ +STATIC +EFI_STATUS +EFIAPI +AcpiView ( + IN EFI_SYSTEM_TABLE* SystemTable + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_CONFIGURATION_TABLE* EfiConfigurationTable; + BOOLEAN FoundAcpiTable; + UINTN OriginalAttribute; + UINTN PrintAttribute; + EREPORT_OPTION ReportOption; + UINT8* RsdpPtr; + UINT32 RsdpLength; + UINT8 RsdpRevision; + PARSE_ACPI_TABLE_PROC RsdpParserProc; + BOOLEAN Trace; + + // Search the table for an entry that matches the ACPI Table Guid + FoundAcpiTable = FALSE; + for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) { + if (CompareGuid (&gEfiAcpiTableGuid, + &(SystemTable->ConfigurationTable[Index].VendorGuid))) { + EfiConfigurationTable = &SystemTable->ConfigurationTable[Index]; + FoundAcpiTable = TRUE; + break; + } + } + + if (FoundAcpiTable) { + RsdpPtr = (UINT8*)EfiConfigurationTable->VendorTable; + + // The RSDP revision is 1 byte starting at offset 15 + RsdpRevision = *(RsdpPtr + RSDP_REVISION_OFFSET); + + if (RsdpRevision < 2) { + Print ( + L"ERROR: RSDP version less than 2 is not supported.\n" + ); + return EFI_UNSUPPORTED; + } + + // The RSDP length is 4 bytes starting at offset 20 + RsdpLength = *(UINT32*)(RsdpPtr + RSDP_LENGTH_OFFSET); + + Trace = ProcessTableReportOptions (RSDP_TABLE_INFO, RsdpPtr, RsdpLength); + + Status = GetParser (RSDP_TABLE_INFO, &RsdpParserProc); + if (EFI_ERROR (Status)) { + Print ( + L"ERROR: No registered parser found for RSDP.\n" + ); + return Status; + } + + RsdpParserProc ( + Trace, + RsdpPtr, + RsdpLength, + RsdpRevision + ); + + } else { + IncrementErrorCount (); + Print ( + L"ERROR: Failed to find ACPI Table Guid in System Configuration Table.\n" + ); + return EFI_NOT_FOUND; + } + + ReportOption = GetReportOption (); + if (ReportTableList != ReportOption) { + if (((ReportSelected == ReportOption) || + (ReportDumpBinFile == ReportOption)) && + (!mSelectedAcpiTableFound)) { + Print (L"\nRequested ACPI Table not found.\n"); + } else if (ReportDumpBinFile != ReportOption) { + OriginalAttribute = gST->ConOut->Mode->Attribute; + + Print (L"\nTable Statistics:\n"); + + if (GetColourHighlighting ()) { + PrintAttribute = (GetErrorCount () > 0) ? + EFI_TEXT_ATTR ( + EFI_RED, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) + ) : + OriginalAttribute; + gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); + } + Print (L"\t%d Error(s)\n", GetErrorCount ()); + + if (GetColourHighlighting ()) { + PrintAttribute = (GetWarningCount () > 0) ? + EFI_TEXT_ATTR ( + EFI_RED, + ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) + ) : + OriginalAttribute; + + gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); + } + Print (L"\t%d Warning(s)\n", GetWarningCount ()); + + if (GetColourHighlighting ()) { + gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); + } + } + } + return EFI_SUCCESS; +} + +/** + Function for 'acpiview' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAcpiView ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + LIST_ENTRY* Package; + CHAR16* ProblemParam; + CONST CHAR16* Temp; + CHAR8 ColourOption[8]; + SHELL_FILE_HANDLE TmpDumpFileHandle; + + // Set Defaults + mReportType = ReportAll; + mTableCount = 0; + mBinTableCount = 0; + mSelectedAcpiTable = 0; + mSelectedAcpiTableName = NULL; + mSelectedAcpiTableFound = FALSE; + mVerbose = TRUE; + mConsistencyCheck = TRUE; + + ShellStatus = SHELL_SUCCESS; + Package = NULL; + TmpDumpFileHandle = NULL; + + // Reset The error/warning counters + ResetErrorCount (); + ResetWarningCount (); + + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM), + gShellAcpiViewHiiHandle, + L"acpiview", + ProblemParam + ); + FreePool (ProblemParam); + } else { + Print (L"acpiview: Error processing input parameter(s)\n"); + } + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetCount (Package) > 1) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_TOO_MANY), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag (Package, L"-?")) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GET_HELP_ACPIVIEW), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + } else if (ShellCommandLineGetFlag (Package, L"-s") && + ShellCommandLineGetValue (Package, L"-s") == NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_NO_VALUE), + gShellAcpiViewHiiHandle, + L"acpiview", + L"-s" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((ShellCommandLineGetFlag (Package, L"-s") && + ShellCommandLineGetFlag (Package, L"-l"))) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_TOO_MANY), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag (Package, L"-h") && + ShellCommandLineGetValue (Package, L"-h") == NULL) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_NO_VALUE), + gShellAcpiViewHiiHandle, + L"acpiview", + L"-h" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag (Package, L"-d") && + !ShellCommandLineGetFlag (Package, L"-s")) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_MISSING_OPTION), + gShellAcpiViewHiiHandle, + L"acpiview", + L"-s", + L"-d" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // Check if the colour option is set + Temp = ShellCommandLineGetValue (Package, L"-h"); + if (Temp != NULL) { + UnicodeStrToAsciiStrS (Temp, ColourOption, sizeof (ColourOption)); + if ((AsciiStriCmp (ColourOption, "ON") == 0) || + (AsciiStriCmp (ColourOption, "TRUE") == 0)) { + SetColourHighlighting (TRUE); + } else if ((AsciiStriCmp (ColourOption, "OFF") == 0) || + (AsciiStriCmp (ColourOption, "FALSE") == 0)) { + SetColourHighlighting (FALSE); + } + } + + if (ShellCommandLineGetFlag (Package, L"-l")) { + mReportType = ReportTableList; + } else { + mSelectedAcpiTableName = ShellCommandLineGetValue (Package, L"-s"); + if (mSelectedAcpiTableName != NULL) { + mSelectedAcpiTable = (UINT32)ConvertStrToAcpiSignature ( + mSelectedAcpiTableName + ); + mReportType = ReportSelected; + + if (ShellCommandLineGetFlag (Package, L"-d")) { + // Create a temporary file to check if the media is writable. + CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; + mReportType = ReportDumpBinFile; + + UnicodeSPrint ( + FileNameBuffer, + sizeof (FileNameBuffer), + L".\\%s%04d.tmp", + mSelectedAcpiTableName, + mBinTableCount + ); + + Status = ShellOpenFileByName ( + FileNameBuffer, + &TmpDumpFileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | + EFI_FILE_MODE_CREATE, + 0 + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + TmpDumpFileHandle = NULL; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_READONLY_MEDIA), + gShellAcpiViewHiiHandle, + L"acpiview" + ); + goto Done; + } + // Delete Temporary file. + ShellDeleteFile (&TmpDumpFileHandle); + } // -d + } // -s + } + + // Parse ACPI Table information + Status = AcpiView (SystemTable); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + } + } + +Done: + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h new file mode 100644 index 0000000..f32c903 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h @@ -0,0 +1,116 @@ +/** @file + Header file for AcpiView + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef ACPIVIEW_H_ +#define ACPIVIEW_H_ + +/** + A macro to define the max file name length +**/ +#define MAX_FILE_NAME_LEN 128 + +/** + Offset to the RSDP revision from the start of the RSDP +**/ +#define RSDP_REVISION_OFFSET 15 + +/** + Offset to the RSDP length from the start of the RSDP +**/ +#define RSDP_LENGTH_OFFSET 20 + +/** + The EREPORT_OPTION enum describes ACPI table Reporting options. +**/ +typedef enum ReportOption { + ReportAll, ///< Report All tables. + ReportSelected, ///< Report Selected table. + ReportTableList, ///< Report List of tables. + ReportDumpBinFile, ///< Dump selected table to a file. + ReportMax, +} EREPORT_OPTION; + +/** + This function resets the ACPI table error counter to Zero. +**/ +VOID +ResetErrorCount ( + VOID + ); + +/** + This function returns the ACPI table error count. + + @retval Returns the count of errors detected in the ACPI tables. +**/ +UINT32 +GetErrorCount ( + VOID + ); + +/** + This function resets the ACPI table warning counter to Zero. +**/ +VOID +ResetWarningCount ( + VOID + ); + +/** + This function returns the ACPI table warning count. + + @retval Returns the count of warning detected in the ACPI tables. +**/ +UINT32 +GetWarningCount ( + VOID + ); + +/** + This function returns the colour highlighting status. + + @retval TRUE if colour highlighting is enabled. +**/ +BOOLEAN +GetColourHighlighting ( + VOID + ); + +/** + This function sets the colour highlighting status. + + @param Highlight The Highlight status. + +**/ +VOID +SetColourHighlighting ( + BOOLEAN Highlight + ); + +/** + This function processes the table reporting options for the ACPI table. + + @param [in] Signature The ACPI table Signature. + @param [in] TablePtr Pointer to the ACPI table data. + @param [in] Length The length fo the ACPI table. + + @retval Returns TRUE if the ACPI table should be traced. +**/ +BOOLEAN +ProcessTableReportOptions ( + IN CONST UINT32 Signature, + IN CONST UINT8* TablePtr, + IN CONST UINT32 Length + ); + +#endif // ACPIVIEW_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c new file mode 100644 index 0000000..c9c8a6e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c @@ -0,0 +1,71 @@ +/** @file + BGRT table parser + + Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + An ACPI_PARSER array describing the ACPI BDRT Table. +**/ +STATIC CONST ACPI_PARSER BgrtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Version", 2, 36, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Status", 1, 38, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Image Type", 1, 39, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Image Address", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Image Offset X", 4, 48, L"%d", NULL, NULL, NULL, NULL}, + {L"Image Offset Y", 4, 52, L"%d", NULL, NULL, NULL, NULL} +}; + +/** + This function parses the ACPI BGRT table. + When trace is enabled this function parses the BGRT table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiBgrt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + ParseAcpi ( + Trace, + 0, + "BGRT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (BgrtParser) + ); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c new file mode 100644 index 0000000..e6ad8e9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c @@ -0,0 +1,250 @@ +/** @file + DBG2 table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015. +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables pointing to the table fields +STATIC CONST UINT32* OffsetDbgDeviceInfo; +STATIC CONST UINT32* NumberDbgDeviceInfo; +STATIC CONST UINT16* DbgDevInfoLen; +STATIC CONST UINT8* GasCount; +STATIC CONST UINT16* NameSpaceStringLength; +STATIC CONST UINT16* NameSpaceStringOffset; +STATIC CONST UINT16* OEMDataLength; +STATIC CONST UINT16* OEMDataOffset; +STATIC CONST UINT16* BaseAddrRegOffset; +STATIC CONST UINT16* AddrSizeOffset; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + This function Validates the NameSpace string length. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateNameSpaceStrLen ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function parses the debug device information structure. + + @param [in] Ptr Pointer to the start of the buffer. + @param [out] Length Pointer in which the length of the debug + device information is returned. +**/ +STATIC +VOID +EFIAPI +DumpDbgDeviceInfo ( + IN UINT8* Ptr, + OUT UINT32* Length + ); + +/// An ACPI_PARSER array describing the ACPI DBG2 table. +STATIC CONST ACPI_PARSER Dbg2Parser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"OffsetDbgDeviceInfo", 4, 36, L"0x%x", NULL, + (VOID**)&OffsetDbgDeviceInfo, NULL, NULL}, + {L"NumberDbgDeviceInfo", 4, 40, L"%d", NULL, + (VOID**)&NumberDbgDeviceInfo, NULL, NULL} +}; + +/// An ACPI_PARSER array describing the debug device information. +STATIC CONST ACPI_PARSER DbgDevInfoParser[] = { + {L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, (VOID**)&DbgDevInfoLen, NULL, NULL}, + + {L"Generic Address Registers Count", 1, 3, L"0x%x", NULL, + (VOID**)&GasCount, NULL, NULL}, + {L"NameSpace String Length", 2, 4, L"%d", NULL, + (VOID**)&NameSpaceStringLength, ValidateNameSpaceStrLen, NULL}, + {L"NameSpace String Offset", 2, 6, L"0x%x", NULL, + (VOID**)&NameSpaceStringOffset, NULL, NULL}, + {L"OEM Data Length", 2, 8, L"%d", NULL, (VOID**)&OEMDataLength, + NULL, NULL}, + {L"OEM Data Offset", 2, 10, L"0x%x", NULL, (VOID**)&OEMDataOffset, + NULL, NULL}, + + {L"Port Type", 2, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Port SubType", 2, 14, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 16, L"%x", NULL, NULL, NULL, NULL}, + + {L"Base Address Register Offset", 2, 18, L"0x%x", NULL, + (VOID**)&BaseAddrRegOffset, NULL, NULL}, + {L"Address Size Offset", 2, 20, L"0x%x", NULL, + (VOID**)&AddrSizeOffset, NULL, NULL} +}; + +/** + This function validates the NameSpace string length. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateNameSpaceStrLen ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + UINT16 NameSpaceStrLen; + + NameSpaceStrLen = *(UINT16*)Ptr; + + if (NameSpaceStrLen < 2) { + IncrementErrorCount (); + Print ( + L"\nERROR: NamespaceString Length = %d. If no Namespace device exists,\n" + L" then NamespaceString[] must contain a period '.'", + NameSpaceStrLen + ); + } +} + +/** + This function parses the debug device information structure. + + @param [in] Ptr Pointer to the start of the buffer. + @param [out] Length Pointer in which the length of the debug + device information is returned. +**/ +STATIC +VOID +EFIAPI +DumpDbgDeviceInfo ( + IN UINT8* Ptr, + OUT UINT32* Length + ) +{ + UINT16 Index; + UINT8* DataPtr; + UINT32* AddrSize; + + // Parse the debug device info to get the Length + ParseAcpi ( + FALSE, + 0, + "Debug Device Info", + Ptr, + 3, // Length is 2 bytes starting at offset 1 + PARSER_PARAMS (DbgDevInfoParser) + ); + + ParseAcpi ( + TRUE, + 2, + "Debug Device Info", + Ptr, + *DbgDevInfoLen, + PARSER_PARAMS (DbgDevInfoParser) + ); + + // GAS and Address Size + Index = 0; + DataPtr = Ptr + (*BaseAddrRegOffset); + AddrSize = (UINT32*)(Ptr + (*AddrSizeOffset)); + while (Index < (*GasCount)) { + PrintFieldName (4, L"BaseAddressRegister"); + DumpGasStruct (DataPtr, 4); + PrintFieldName (4, L"Address Size"); + Print (L"0x%x\n", AddrSize[Index]); + DataPtr += GAS_LENGTH; + Index++; + } + + // NameSpace String + Index = 0; + DataPtr = Ptr + (*NameSpaceStringOffset); + PrintFieldName (4, L"NameSpace String"); + while (Index < (*NameSpaceStringLength)) { + Print (L"%c", DataPtr[Index++]); + } + Print (L"\n"); + + // OEM Data + Index = 0; + DataPtr = Ptr + (*OEMDataOffset); + PrintFieldName (4, L"OEM Data"); + while (Index < (*OEMDataLength)) { + Print (L"%x ", DataPtr[Index++]); + if ((Index & 7) == 0) { + Print (L"\n%-*s ", OUTPUT_FIELD_COLUMN_WIDTH, L""); + } + } + + *Length = *DbgDevInfoLen; +} + +/** + This function parses the ACPI DBG2 table. + When trace is enabled this function parses the DBG2 table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiDbg2 ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 DbgDeviceInfoLength; + UINT8* DevInfoPtr; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "DBG2", + Ptr, + AcpiTableLength, + PARSER_PARAMS (Dbg2Parser) + ); + DevInfoPtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + DumpDbgDeviceInfo ( + DevInfoPtr, + &DbgDeviceInfoLength + ); + Offset += DbgDeviceInfoLength; + DevInfoPtr += DbgDeviceInfoLength; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c new file mode 100644 index 0000000..59ea63e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c @@ -0,0 +1,48 @@ +/** @file + DSDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +/** + This function parses the ACPI DSDT table. + When trace is enabled this function parses the DSDT table and + traces the ACPI table fields. + For the DSDT table only the ACPI header fields are parsed and + traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiDsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + DumpAcpiHeader (Ptr); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c new file mode 100644 index 0000000..ee843ec --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c @@ -0,0 +1,289 @@ +/** @file + FADT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC CONST UINT32* DsdtAddress; +STATIC CONST UINT64* X_DsdtAddress; +STATIC CONST UINT8* FadtMinorRevision; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + A macro defining the Hardware reduced ACPI flag +**/ +#define HW_REDUCED_ACPI BIT20 + +/** + Get the ACPI XSDT header info. +**/ +CONST ACPI_DESCRIPTION_HEADER_INFO * +EFIAPI +GetAcpiXsdtHeaderInfo ( + VOID + ); + +/** + This function validates the Firmware Control Field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function validates the X_Firmware Control Field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateXFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function validates the flags. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateFlags ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + An ACPI_PARSER array describing the ACPI FADT Table. +**/ +STATIC CONST ACPI_PARSER FadtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"FIRMWARE_CTRL", 4, 36, L"0x%x", NULL, NULL, ValidateFirmwareCtrl, NULL}, + {L"DSDT", 4, 40, L"0x%x", NULL, (VOID**)&DsdtAddress, NULL, NULL}, + {L"Reserved", 1, 44, L"%x", NULL, NULL, NULL, NULL}, + {L"Preferred_PM_Profile", 1, 45, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SCI_INT", 2, 46, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMI_CMD", 4, 48, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI_ENABLE", 1, 52, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI_DISABLE", 1, 53, L"0x%x", NULL, NULL, NULL, NULL}, + {L"S4BIOS_REQ", 1, 54, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PSTATE_CNT", 1, 55, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1a_EVT_BLK", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1b_EVT_BLK", 4, 60, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1a_CNT_BLK", 4, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1b_CNT_BLK", 4, 68, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM2_CNT_BLK", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM_TMR_BLK", 4, 76, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE0_BLK", 4, 80, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE1_BLK", 4, 84, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1_EVT_LEN", 1, 88, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM1_CNT_LEN", 1, 89, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM2_CNT_LEN", 1, 90, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PM_TMR_LEN", 1, 91, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE0_BLK_LEN", 1, 92, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE1_BLK_LEN", 1, 93, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GPE1_BASE", 1, 94, L"0x%x", NULL, NULL, NULL, NULL}, + {L"CST_CNT", 1, 95, L"0x%x", NULL, NULL, NULL, NULL}, + {L"P_LVL2_LAT", 2, 96, L"0x%x", NULL, NULL, NULL, NULL}, + {L"P_LVL3_LAT", 2, 98, L"0x%x", NULL, NULL, NULL, NULL}, + {L"FLUSH_SIZE", 2, 100, L"0x%x", NULL, NULL, NULL, NULL}, + {L"FLUSH_STRIDE", 2, 102, L"0x%x", NULL, NULL, NULL, NULL}, + {L"DUTY_OFFSET", 1, 104, L"0x%x", NULL, NULL, NULL, NULL}, + {L"DUTY_WIDTH", 1, 105, L"0x%x", NULL, NULL, NULL, NULL}, + {L"DAY_ALRM", 1, 106, L"0x%x", NULL, NULL, NULL, NULL}, + {L"MON_ALRM", 1, 107, L"0x%x", NULL, NULL, NULL, NULL}, + {L"CENTURY", 1, 108, L"0x%x", NULL, NULL, NULL, NULL}, + {L"IAPC_BOOT_ARCH", 2, 109, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 1, 111, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 112, L"0x%x", NULL, NULL, ValidateFlags, NULL}, + {L"RESET_REG", 12, 116, NULL, DumpGas, NULL, NULL, NULL}, + {L"RESET_VALUE", 1, 128, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ARM_BOOT_ARCH", 2, 129, L"0x%x", NULL, NULL, NULL, NULL}, + {L"FADT Minor Version", 1, 131, L"0x%x", NULL, (VOID**)&FadtMinorRevision, + NULL, NULL}, + {L"X_FIRMWARE_CTRL", 8, 132, L"0x%lx", NULL, NULL, + ValidateXFirmwareCtrl, NULL}, + {L"X_DSDT", 8, 140, L"0x%lx", NULL, (VOID**)&X_DsdtAddress, NULL, NULL}, + {L"X_PM1a_EVT_BLK", 12, 148, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM1b_EVT_BLK", 12, 160, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM1a_CNT_BLK", 12, 172, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM1b_CNT_BLK", 12, 184, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM2_CNT_BLK", 12, 196, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_PM_TMR_BLK", 12, 208, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_GPE0_BLK", 12, 220, NULL, DumpGas, NULL, NULL, NULL}, + {L"X_GPE1_BLK", 12, 232, NULL, DumpGas, NULL, NULL, NULL}, + {L"SLEEP_CONTROL_REG", 12, 244, NULL, DumpGas, NULL, NULL, NULL}, + {L"SLEEP_STATUS_REG", 12, 256, NULL, DumpGas, NULL, NULL, NULL}, + {L"Hypervisor VendorIdentity", 8, 268, L"%lx", NULL, NULL, NULL, NULL} +}; + +/** + This function validates the Firmware Control Field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context +) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Firmware Control must be zero for ARM platforms." + ); + } +#endif +} + +/** + This function validates the X_Firmware Control Field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateXFirmwareCtrl ( + IN UINT8* Ptr, + IN VOID* Context +) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (*(UINT64*)Ptr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: X Firmware Control must be zero for ARM platforms." + ); + } +#endif +} + +/** + This function validates the flags. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateFlags ( + IN UINT8* Ptr, + IN VOID* Context +) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (((*(UINT32*)Ptr) & HW_REDUCED_ACPI) == 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms." + ); + } +#endif +} + +/** + This function parses the ACPI FADT table. + This function parses the FADT table and optionally traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiFadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT8* DsdtPtr; + + ParseAcpi ( + Trace, + 0, + "FADT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (FadtParser) + ); + + if (Trace) { + Print (L"\nSummary:\n"); + PrintFieldName (2, L"FADT Version"); + Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision); + + if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) { + IncrementErrorCount (); + Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n"); + } + } + + // If X_DSDT is not zero then use X_DSDT and ignore DSDT, + // else use DSDT. + if (*X_DsdtAddress != 0) { + DsdtPtr = (UINT8*)(UINTN)(*X_DsdtAddress); + } else if (*DsdtAddress != 0) { + DsdtPtr = (UINT8*)(UINTN)(*DsdtAddress); + } else { + // Both DSDT and X_DSDT cannot be zero. +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + if (Trace) { + // The DSDT Table is mandatory for ARM systems + // as the CPU information MUST be presented in + // the DSDT. + IncrementErrorCount (); + Print (L"ERROR: Both X_DSDT and DSDT are NULL.\n"); + } +#endif + return; + } + + ProcessAcpiTable (DsdtPtr); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c new file mode 100644 index 0000000..3e92ec6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c @@ -0,0 +1,306 @@ +/** @file + GTDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 + **/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC CONST UINT32* GtdtPlatformTimerCount; +STATIC CONST UINT32* GtdtPlatformTimerOffset; +STATIC CONST UINT8* PlatformTimerType; +STATIC CONST UINT16* PlatformTimerLength; +STATIC CONST UINT32* GtBlockTimerCount; +STATIC CONST UINT32* GtBlockTimerOffset; +STATIC CONST UINT16* GtBlockLength; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + This function validates the GT Block timer count. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateGtBlockTimerCount ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + An ACPI_PARSER array describing the ACPI GTDT Table. +**/ +STATIC CONST ACPI_PARSER GtdtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"CntControlBase Physical Address", 8, 36, L"0x%lx", NULL, NULL, + NULL, NULL}, + {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Platform Timer Count", 4, 88, L"%d", NULL, + (VOID**)&GtdtPlatformTimerCount, NULL, NULL}, + {L"Platform Timer Offset", 4, 92, L"0x%x", NULL, + (VOID**)&GtdtPlatformTimerOffset, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Platform timer header. +**/ +STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = { + {L"Type", 1, 0, NULL, NULL, (VOID**)&PlatformTimerType, NULL, NULL}, + {L"Length", 2, 1, NULL, NULL, (VOID**)&PlatformTimerLength, NULL, NULL}, + {L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Platform GT Block. +**/ +STATIC CONST ACPI_PARSER GtBlockParser[] = { + {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, (VOID**)&GtBlockLength, NULL, NULL}, + {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL}, + {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount, + ValidateGtBlockTimerCount, NULL}, + {L"Timer Offset", 4, 16, L"%d", NULL, (VOID**)&GtBlockTimerOffset, NULL, + NULL} +}; + +/** + An ACPI_PARSER array describing the GT Block timer. +**/ +STATIC CONST ACPI_PARSER GtBlockTimerParser[] = { + {L"Frame Number", 1, 0, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}, + {L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL, + NULL}, + {L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Platform Watchdog. +**/ +STATIC CONST ACPI_PARSER SBSAGenericWatchdogParser[] = { + {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL}, + {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL}, + {L"RefreshFrame Physical address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"ControlFrame Physical address", 8, 12, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Watchdog Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Watchdog Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + This function validates the GT Block timer count. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateGtBlockTimerCount ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + UINT32 BlockTimerCount; + + BlockTimerCount = *(UINT32*)Ptr; + + if (BlockTimerCount > 8) { + IncrementErrorCount (); + Print ( + L"\nERROR: Timer Count = %d. Max Timer Count is 8.", + BlockTimerCount + ); + } +} + +/** + This function parses the Platform GT Block. + + @param [in] Ptr Pointer to the start of the GT Block data. + @param [in] Length Length of the GT Block structure. +**/ +STATIC +VOID +DumpGTBlock ( + IN UINT8* Ptr, + IN UINT32 Length + ) +{ + UINT32 Index; + UINT32 Offset; + UINT32 GTBlockTimerLength; + + Offset = ParseAcpi ( + TRUE, + 2, + "GT Block", + Ptr, + Length, + PARSER_PARAMS (GtBlockParser) + ); + GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount); + Length -= Offset; + + if (*GtBlockTimerCount != 0) { + Ptr += (*GtBlockTimerOffset); + Index = 0; + while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) { + Offset = ParseAcpi ( + TRUE, + 2, + "GT Block Timer", + Ptr, + GTBlockTimerLength, + PARSER_PARAMS (GtBlockTimerParser) + ); + // Increment by GT Block Timer structure size + Ptr += Offset; + Length -= Offset; + Index++; + } + + if (Length != 0) { + IncrementErrorCount (); + Print ( + L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n", + Length + ); + } + } +} + +/** + This function parses the Platform Watchdog timer. + + @param [in] Ptr Pointer to the start of the watchdog timer data. + @param [in] Length Length of the watchdog timer structure. +**/ +STATIC +VOID +DumpWatchdogTimer ( + IN UINT8* Ptr, + IN UINT16 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "SBSA Generic Watchdog", + Ptr, + Length, + PARSER_PARAMS (SBSAGenericWatchdogParser) + ); +} + +/** + This function parses the ACPI GTDT table. + When trace is enabled this function parses the GTDT table and + traces the ACPI table fields. + + This function also parses the following platform timer structures: + - GT Block timer + - Watchdog timer + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiGtdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Index; + UINT8* TimerPtr; + + if (!Trace) { + return; + } + + ParseAcpi ( + TRUE, + 0, + "GTDT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (GtdtParser) + ); + + if (*GtdtPlatformTimerCount != 0) { + TimerPtr = Ptr + (*GtdtPlatformTimerOffset); + Index = 0; + do { + // Parse the Platform Timer Header + ParseAcpi ( + FALSE, + 0, + NULL, + TimerPtr, + 4, // GT Platform Timer structure header length. + PARSER_PARAMS (GtPlatformTimerHeaderParser) + ); + switch (*PlatformTimerType) { + case EFI_ACPI_6_2_GTDT_GT_BLOCK: + DumpGTBlock (TimerPtr, *PlatformTimerLength); + break; + case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG: + DumpWatchdogTimer (TimerPtr, *PlatformTimerLength); + break; + default: + IncrementErrorCount (); + Print ( + L"ERROR: INVALID Platform Timer Type = %d\n", + *PlatformTimerType + ); + break; + } // switch + TimerPtr += (*PlatformTimerLength); + Index++; + } while (Index < *GtdtPlatformTimerCount); + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c new file mode 100644 index 0000000..43ea1df --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c @@ -0,0 +1,723 @@ +/** @file + IORT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - IO Remapping Table, Platform Design Document, Revision C, 15 May 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + The EIORT_NODE enum describes the IORT Node types. +**/ +typedef enum IortNode { + Iort_Node_ITS_Group, ///< ITS Group node + Iort_Node_Named_Component, ///< Named Component node + Iort_Node_Root_Complex, ///< Root Complex node + Iort_Node_SMMUV1_V2, ///< SMMU v1/v2 node + Iort_Node_SMMUV3, ///< SMMU v3 node + Iort_Node_PMCG, ///< PMC group node + Iort_Node_Max +} EIORT_NODE; + +// Local Variables +STATIC CONST UINT32* IortNodeCount; +STATIC CONST UINT32* IortNodeOffset; + +STATIC CONST UINT8* IortNodeType; +STATIC CONST UINT16* IortNodeLength; +STATIC CONST UINT32* IortIdMappingCount; +STATIC CONST UINT32* IortIdMappingOffset; + +STATIC CONST UINT32* InterruptContextCount; +STATIC CONST UINT32* InterruptContextOffset; +STATIC CONST UINT32* PmuInterruptCount; +STATIC CONST UINT32* PmuInterruptOffset; + +STATIC CONST UINT32* ItsCount; + +/** + This function validates the ID Mapping array count for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateItsIdMappingCount ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function validates the ID Mapping array offset for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateItsIdArrayReference ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + Helper Macro for populating the IORT Node header in the ACPI_PARSER array. + + @param [out] ValidateIdMappingCount Optional pointer to a function for + validating the ID Mapping count. + @param [out] ValidateIdArrayReference Optional pointer to a function for + validating the ID Array reference. +**/ +#define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \ + ValidateIdArrayReference) \ + { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \ + { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \ + { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \ + { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \ + { L"Number of ID mappings", 4, 8, L"%d", NULL, \ + (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \ + { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \ + (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL } + +/** + An ACPI_PARSER array describing the ACPI IORT Table +**/ +STATIC CONST ACPI_PARSER IortParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Number of IORT Nodes", 4, 36, L"%d", NULL, + (VOID**)&IortNodeCount, NULL, NULL}, + {L"Offset to Array of IORT Nodes", 4, 40, L"0x%x", NULL, + (VOID**)&IortNodeOffset, NULL, NULL}, + {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the IORT node header structure. +**/ +STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL) +}; + +/** + An ACPI_PARSER array describing the IORT SMMUv1/2 node. +**/ +STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reference to Global Interrupt Array", 4, 40, L"0x%x", NULL, NULL, NULL, + NULL}, + {L"Number of context interrupts", 4, 44, L"%d", NULL, + (VOID**)&InterruptContextCount, NULL, NULL}, + {L"Reference to Context Interrupt Array", 4, 48, L"0x%x", NULL, + (VOID**)&InterruptContextOffset, NULL, NULL}, + {L"Number of PMU Interrupts", 4, 52, L"%d", NULL, + (VOID**)&PmuInterruptCount, NULL, NULL}, + {L"Reference to PMU Interrupt Array", 4, 56, L"0x%x", NULL, + (VOID**)&PmuInterruptOffset, NULL, NULL}, + + // Interrupt Array + {L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array. +**/ +STATIC CONST ACPI_PARSER InterruptArrayParser[] = { + {L" Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the IORT ID Mapping. +**/ +STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = { + {L" Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L" Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the IORT SMMUv3 node. +**/ +STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, + {L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL}, + {L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the IORT ITS node. +**/ +STATIC CONST ACPI_PARSER IortNodeItsParser[] = { + PARSE_IORT_NODE_HEADER ( + ValidateItsIdMappingCount, + ValidateItsIdArrayReference + ), + {L" Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL} +}; + +/** + An ACPI_PARSER array describing the ITS ID. +**/ +STATIC CONST ACPI_PARSER ItsIdParser[] = { + { L" GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL } +}; + +/** + An ACPI_PARSER array describing the IORT Names Component node. +**/ +STATIC CONST ACPI_PARSER IortNodeNamedComponentParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Node Flags", 4, 16, L"%d", NULL, NULL, NULL, NULL}, + {L"Memory access properties", 8, 20, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Device memory address size limit", 1, 28, L"%d", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the IORT Root Complex node. +**/ +STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Memory access properties", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"ATS Attribute", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Segment number", 4, 28, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the IORT PMCG node. +**/ +STATIC CONST ACPI_PARSER IortNodePmcgParser[] = { + PARSE_IORT_NODE_HEADER (NULL, NULL), + {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Overflow interrupt GSIV", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Node reference", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, +}; + +/** + This function validates the ID Mapping array count for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateItsIdMappingCount ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print (L"\nERROR: IORT ID Mapping count must be zero."); + } +} + +/** + This function validates the ID Mapping array offset for the ITS node. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateItsIdArrayReference ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print (L"\nERROR: IORT ID Mapping offset must be zero."); + } +} + +/** + This function parses the IORT Node Id Mapping array. + + @param [in] Ptr Pointer to the start of the IORT Table. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +**/ +STATIC +VOID +DumpIortNodeIdMappings ( + IN UINT8* Ptr, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + UINT8* IdMappingPtr; + UINT32 Index; + UINT32 Offset; + CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi + + IdMappingPtr = Ptr + MappingOffset; + Index = 0; + while (Index < MappingCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "ID Mapping [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + IdMappingPtr, + 20, + PARSER_PARAMS (IortNodeIdMappingParser) + ); + IdMappingPtr += Offset; + Index++; + } +} + +/** + This function parses the IORT SMMUv1/2 node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +**/ +STATIC +VOID +DumpIortNodeSmmuV1V2 ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + UINT32 Index; + UINT32 Offset; + CHAR8 Buffer[50]; // Used for AsciiName param of ParseAcpi + + UINT8* ArrayPtr; + + ParseAcpi ( + TRUE, + 2, + "SMMUv1 or SMMUv2 Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeSmmuV1V2Parser) + ); + + ArrayPtr = Ptr + *InterruptContextOffset; + Index = 0; + while (Index < *InterruptContextCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "Context Interrupts Array [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + ArrayPtr, + 8, + PARSER_PARAMS (InterruptArrayParser) + ); + ArrayPtr += Offset; + Index++; + } + + ArrayPtr = Ptr + *PmuInterruptOffset; + Index = 0; + while (Index < *PmuInterruptCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "PMU Interrupts Array [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + ArrayPtr, + 8, + PARSER_PARAMS (InterruptArrayParser) + ); + ArrayPtr += Offset; + Index++; + } + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** + This function parses the IORT SMMUv3 node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +**/ +STATIC +VOID +DumpIortNodeSmmuV3 ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + ParseAcpi ( + TRUE, + 2, + "SMMUV3 Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeSmmuV3Parser) + ); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** + This function parses the IORT ITS node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. +**/ +STATIC +VOID +DumpIortNodeIts ( + IN UINT8* Ptr, + IN UINT16 Length + ) +{ + UINT32 Offset; + UINT32 Index; + UINT8* ItsIdPtr; + CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi + + Offset = ParseAcpi ( + TRUE, + 2, + "ITS Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeItsParser) + ); + + ItsIdPtr = Ptr + Offset; + Index = 0; + while (Index < *ItsCount) { + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "GIC ITS Identifier Array [%d]", + Index + ); + Offset = ParseAcpi ( + TRUE, + 4, + Buffer, + ItsIdPtr, + 4, + PARSER_PARAMS (ItsIdParser) + ); + ItsIdPtr += Offset; + Index++; + } + + // Note: ITS does not have the ID Mappings Array +} + +/** + This function parses the IORT Named Component node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +**/ +STATIC +VOID +DumpIortNodeNamedComponent ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + UINT32 Offset; + UINT32 Index; + UINT8* DeviceNamePtr; + UINT32 DeviceNameLength; + + Offset = ParseAcpi ( + TRUE, + 2, + "Named Component Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeNamedComponentParser) + ); + + DeviceNamePtr = Ptr + Offset; + // Estimate the Device Name length + DeviceNameLength = Length - Offset - (MappingCount * 20); + PrintFieldName (2, L"Device Object Name"); + Index = 0; + while ((Index < DeviceNameLength) && (DeviceNamePtr[Index] != 0)) { + Print (L"%c", DeviceNamePtr[Index++]); + } + Print (L"\n"); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** + This function parses the IORT Root Complex node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +**/ +STATIC +VOID +DumpIortNodeRootComplex ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset + ) +{ + ParseAcpi ( + TRUE, + 2, + "Root Complex Node", + Ptr, + Length, + PARSER_PARAMS (IortNodeRootComplexParser) + ); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } +} + +/** + This function parses the IORT PMCG node. + + @param [in] Ptr Pointer to the start of the buffer. + @param [in] Length Length of the buffer. + @param [in] MappingCount The ID Mapping count. + @param [in] MappingOffset The offset of the ID Mapping array + from the start of the IORT table. +**/ +STATIC +VOID +DumpIortNodePmcg ( + IN UINT8* Ptr, + IN UINT16 Length, + IN UINT32 MappingCount, + IN UINT32 MappingOffset +) +{ + ParseAcpi ( + TRUE, + 2, + "PMCG Node", + Ptr, + Length, + PARSER_PARAMS (IortNodePmcgParser) + ); + + if (*IortIdMappingCount != 0) { + DumpIortNodeIdMappings (Ptr, MappingCount, MappingOffset); + } + + if (*IortIdMappingCount > 1) { + IncrementErrorCount (); + Print ( + L"ERROR: ID mapping must not be greater than 1. Id Mapping Count =%d\n", + *IortIdMappingCount + ); + } +} + +/** + This function parses the ACPI IORT table. + When trace is enabled this function parses the IORT table and traces the ACPI fields. + + This function also parses the following nodes: + - ITS Group + - Named Component + - Root Complex + - SMMUv1/2 + - SMMUv3 + - PMCG + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiIort ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 Index; + UINT8* NodePtr; + + if (!Trace) { + return; + } + + ParseAcpi ( + TRUE, + 0, + "IORT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (IortParser) + ); + Offset = *IortNodeOffset; + NodePtr = Ptr + Offset; + Index = 0; + + while ((Index < *IortNodeCount) && (Offset < AcpiTableLength)) { + // Parse the IORT Node Header + ParseAcpi ( + FALSE, + 0, + "IORT Node Header", + NodePtr, + 16, + PARSER_PARAMS (IortNodeHeaderParser) + ); + if (*IortNodeLength == 0) { + IncrementErrorCount (); + Print (L"ERROR: Parser error. Invalid table data.\n"); + return; + } + + PrintFieldName (2, L"* Node Offset *"); + Print (L"0x%x\n", Offset); + + switch (*IortNodeType) { + case Iort_Node_ITS_Group: + DumpIortNodeIts ( + NodePtr, + *IortNodeLength + ); + break; + case Iort_Node_Named_Component: + DumpIortNodeNamedComponent ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case Iort_Node_Root_Complex: + DumpIortNodeRootComplex ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case Iort_Node_SMMUV1_V2: + DumpIortNodeSmmuV1V2 ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case Iort_Node_SMMUV3: + DumpIortNodeSmmuV3 ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + case Iort_Node_PMCG: + DumpIortNodePmcg ( + NodePtr, + *IortNodeLength, + *IortIdMappingCount, + *IortIdMappingOffset + ); + break; + + default: + IncrementErrorCount (); + Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType); + } // switch + + NodePtr += (*IortNodeLength); + Offset += (*IortNodeLength); + } // while +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c new file mode 100644 index 0000000..3aa775f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c @@ -0,0 +1,324 @@ +/** @file + MADT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT8* MadtInterruptControllerType; +STATIC CONST UINT8* MadtInterruptControllerLength; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + This function validates the System Vector Base in the GICD. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateGICDSystemVectorBase ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + An ACPI_PARSER array describing the GICC Interrupt Controller Structure. +**/ +STATIC CONST ACPI_PARSER GicCParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"CPU Interface Number", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI Processor UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Parking Protocol Version", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Performance Interrupt GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Parked Address", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"GICV", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"GICH", 8, 48, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"VGIC Maintenance interrupt", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}, + {L"GICR Base Address", 8, 60, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"MPIDR", 8, 68, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Processor Power Efficiency Class", 1, 76, L"0x%x", NULL, NULL, NULL, + NULL}, + {L"Reserved", 3, 77, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the GICD Interrupt Controller Structure. +**/ +STATIC CONST ACPI_PARSER GicDParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"GIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"System Vector Base", 4, 16, L"0x%x", NULL, NULL, + ValidateGICDSystemVectorBase, NULL}, + {L"GIC Version", 1, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 21, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure. +**/ +STATIC CONST ACPI_PARSER GicMSIFrameParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"MSI Frame ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"SPI Count", 2, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"SPI Base", 2, 22, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the GICR Interrupt Controller Structure. +**/ +STATIC CONST ACPI_PARSER GicRParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Discovery Range Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL, + NULL}, + {L"Discovery Range Length", 4, 12, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure. +**/ +STATIC CONST ACPI_PARSER GicITSParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"GIC ITS ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the ACPI MADT Table. +**/ +STATIC CONST ACPI_PARSER MadtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Local Interrupt Controller Address", 4, 36, L"0x%x", NULL, NULL, NULL, + NULL}, + {L"Flags", 4, 40, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure. +**/ +STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = { + {NULL, 1, 0, NULL, NULL, (VOID**)&MadtInterruptControllerType, NULL, NULL}, + {L"Length", 1, 1, NULL, NULL, (VOID**)&MadtInterruptControllerLength, NULL, + NULL}, + {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL} +}; + +/** + This function validates the System Vector Base in the GICD. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateGICDSystemVectorBase ( + IN UINT8* Ptr, + IN VOID* Context +) +{ + if (*(UINT32*)Ptr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: System Vector Base must be zero." + ); + } +} + +/** + This function parses the ACPI MADT table. + When trace is enabled this function parses the MADT table and + traces the ACPI table fields. + + This function currently parses the following Interrupt Controller + Structures: + - GICC + - GICD + - GIC MSI Frame + - GICR + - GIC ITS + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiMadt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT8* InterruptContollerPtr; + UINT32 GICDCount; + + GICDCount = 0; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "MADT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (MadtParser) + ); + InterruptContollerPtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + // Parse Interrupt Controller Structure to obtain Length. + ParseAcpi ( + FALSE, + 0, + NULL, + InterruptContollerPtr, + 2, // Length is 1 byte at offset 1 + PARSER_PARAMS (MadtInterruptControllerHeaderParser) + ); + + if (((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength) || + (*MadtInterruptControllerLength < 4)) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid Interrupt Controller Length," + L" Type = %d, Length = %d\n", + *MadtInterruptControllerType, + *MadtInterruptControllerLength + ); + break; + } + + switch (*MadtInterruptControllerType) { + case EFI_ACPI_6_2_GIC: { + ParseAcpi ( + TRUE, + 2, + "GICC", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicCParser) + ); + break; + } + + case EFI_ACPI_6_2_GICD: { + if (++GICDCount > 1) { + IncrementErrorCount (); + Print ( + L"ERROR: Only one GICD must be present," + L" GICDCount = %d\n", + GICDCount + ); + } + ParseAcpi ( + TRUE, + 2, + "GICD", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicDParser) + ); + break; + } + + case EFI_ACPI_6_2_GIC_MSI_FRAME: { + ParseAcpi ( + TRUE, + 2, + "GIC MSI Frame", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicMSIFrameParser) + ); + break; + } + + case EFI_ACPI_6_2_GICR: { + ParseAcpi ( + TRUE, + 2, + "GICR", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicRParser) + ); + break; + } + + case EFI_ACPI_6_2_GIC_ITS: { + ParseAcpi ( + TRUE, + 2, + "GIC ITS", + InterruptContollerPtr, + *MadtInterruptControllerLength, + PARSER_PARAMS (GicITSParser) + ); + break; + } + + default: { + IncrementErrorCount (); + Print ( + L"ERROR: Unknown Interrupt Controller Structure," + L" Type = %d, Length = %d\n", + *MadtInterruptControllerType, + *MadtInterruptControllerLength + ); + } + } // switch + + InterruptContollerPtr += *MadtInterruptControllerLength; + Offset += *MadtInterruptControllerLength; + } // while +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c new file mode 100644 index 0000000..c41e122 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c @@ -0,0 +1,96 @@ +/** @file + MCFG table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - PCI Firmware Specification - Revision 3.2, January 26, 2015. +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + An ACPI_PARSER array describing the ACPI MCFG Table. +**/ +STATIC CONST ACPI_PARSER McfgParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Reserved", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL}, +}; + +/** + An ACPI_PARSER array describing the PCI configuration Space Base Address structure. +**/ +STATIC CONST ACPI_PARSER PciCfgSpaceBaseAddrParser[] = { + {L"Base Address", 8, 0, L"0x%lx", NULL, NULL, NULL, NULL}, + {L"PCI Segment Group No.", 2, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Start Bus No.", 1, 10, L"0x%x", NULL, NULL, NULL, NULL}, + {L"End Bus No.", 1, 11, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + This function parses the ACPI MCFG table. + When trace is enabled this function parses the MCFG table and + traces the ACPI table fields. + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiMcfg ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 PciCfgOffset; + UINT8* PciCfgSpacePtr; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "MCFG", + Ptr, + AcpiTableLength, + PARSER_PARAMS (McfgParser) + ); + + PciCfgSpacePtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + PciCfgOffset = ParseAcpi ( + TRUE, + 2, + "PCI Configuration Space", + PciCfgSpacePtr, + (AcpiTableLength - Offset), + PARSER_PARAMS (PciCfgSpaceBaseAddrParser) + ); + PciCfgSpacePtr += PciCfgOffset; + Offset += PciCfgOffset; + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c new file mode 100644 index 0000000..e009d68 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c @@ -0,0 +1,362 @@ +/** @file + PPTT table parser + + Copyright (c) 2019, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" + +// Local variables +STATIC CONST UINT8* ProcessorTopologyStructureType; +STATIC CONST UINT8* ProcessorTopologyStructureLength; +STATIC CONST UINT32* NumberOfPrivateResources; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + An ACPI_PARSER array describing the ACPI PPTT Table. +**/ +STATIC CONST ACPI_PARSER PpttParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) +}; + +/** + This function validates the Cache Type Structure (Type 1) Line size field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateCacheLineSize ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + // Reference: ARM Architecture Reference Manual ARMv8 (D.a) + // Section D12.2.25: CCSIDR_EL1, Current Cache Size ID Register + // LineSize, bits [2:0] + // (Log2(Number of bytes in cache line)) - 4. + + UINT16 LineSize; + LineSize = *(UINT16*)Ptr; + + if ((LineSize < 16) || (LineSize > 2048)) { + IncrementErrorCount (); + Print ( + L"\nERROR: The cache line size must be between 16 and 2048 bytes" + L" on ARM Platforms." + ); + return; + } + + if ((LineSize & (LineSize - 1)) != 0) { + IncrementErrorCount (); + Print (L"\nERROR: The cache line size is not a power of 2."); + } +#endif +} + +/** + This function validates the Cache Type Structure (Type 1) Attributes field. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateCacheAttributes ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + // Reference: Advanced Configuration and Power Interface (ACPI) Specification + // Version 6.2 Errata A, September 2017 + // Table 5-153: Cache Type Structure + + UINT8 Attributes; + Attributes = *(UINT8*)Ptr; + + if ((Attributes & 0xE0) != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Attributes bits [7:5] are reserved and must be zero.", + Attributes + ); + return; + } +#endif +} + +/** + An ACPI_PARSER array describing the processor topology structure header. +**/ +STATIC CONST ACPI_PARSER ProcessorTopologyStructureHeaderParser[] = { + {L"Type", 1, 0, NULL, NULL, (VOID**)&ProcessorTopologyStructureType, + NULL, NULL}, + {L"Length", 1, 1, NULL, NULL, (VOID**)&ProcessorTopologyStructureLength, + NULL, NULL}, + {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Processor Hierarchy Node Structure - Type 0. +**/ +STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Parent", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI Processor ID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Number of private resources", 4, 16, L"%d", NULL, + (VOID**)&NumberOfPrivateResources, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Cache Type Structure - Type 1. +**/ +STATIC CONST ACPI_PARSER CacheTypeStructureParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Next Level of Cache", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Size", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Number of sets", 4, 16, L"%d", NULL, NULL, NULL, NULL}, + {L"Associativity", 1, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"Attributes", 1, 21, L"0x%x", NULL, NULL, ValidateCacheAttributes, NULL}, + {L"Line size", 2, 22, L"%d", NULL, NULL, ValidateCacheLineSize, NULL} +}; + +/** + An ACPI_PARSER array describing the ID Type Structure - Type 2. +**/ +STATIC CONST ACPI_PARSER IdStructureParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"VENDOR_ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"LEVEL_1_ID", 8, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"LEVEL_2_ID", 8, 16, L"0x%x", NULL, NULL, NULL, NULL}, + {L"MAJOR_REV", 2, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"MINOR_REV", 2, 26, L"0x%x", NULL, NULL, NULL, NULL}, + {L"SPIN_REV", 2, 28, L"0x%x", NULL, NULL, NULL, NULL}, +}; + +/** + This function parses the Processor Hierarchy Node Structure (Type 0). + + @param [in] Ptr Pointer to the start of the Processor Hierarchy Node + Structure data. + @param [in] Length Length of the Processor Hierarchy Node Structure. +**/ +STATIC +VOID +DumpProcessorHierarchyNodeStructure ( + IN UINT8* Ptr, + IN UINT8 Length + ) +{ + UINT32 Offset; + UINT8* PrivateResourcePtr; + UINT32 Index; + CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH]; + + Offset = ParseAcpi ( + TRUE, + 2, + "Processor Hierarchy Node Structure", + Ptr, + Length, + PARSER_PARAMS (ProcessorHierarchyNodeStructureParser) + ); + + PrivateResourcePtr = Ptr + Offset; + Index = 0; + while (Index < *NumberOfPrivateResources) { + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Private resources [%d]", + Index + ); + + PrintFieldName (4, Buffer); + Print ( + L"0x%x\n", + *((UINT32*) PrivateResourcePtr) + ); + + PrivateResourcePtr += sizeof(UINT32); + Index++; + } +} + +/** + This function parses the Cache Type Structure (Type 1). + + @param [in] Ptr Pointer to the start of the Cache Type Structure data. + @param [in] Length Length of the Cache Type Structure. +**/ +STATIC +VOID +DumpCacheTypeStructure ( + IN UINT8* Ptr, + IN UINT8 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "Cache Type Structure", + Ptr, + Length, + PARSER_PARAMS (CacheTypeStructureParser) + ); +} + +/** + This function parses the ID Structure (Type 2). + + @param [in] Ptr Pointer to the start of the ID Structure data. + @param [in] Length Length of the ID Structure. +**/ +STATIC +VOID +DumpIDStructure ( + IN UINT8* Ptr, + IN UINT8 Length + ) +{ + ParseAcpi ( + TRUE, + 2, + "ID Structure", + Ptr, + Length, + PARSER_PARAMS (IdStructureParser) + ); +} + +/** + This function parses the ACPI PPTT table. + When trace is enabled this function parses the PPTT table and + traces the ACPI table fields. + + This function parses the following processor topology structures: + - Processor hierarchy node structure (Type 0) + - Cache Type Structure (Type 1) + - ID structure (Type 2) + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiPptt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT8* ProcessorTopologyStructurePtr; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "PPTT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (PpttParser) + ); + ProcessorTopologyStructurePtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + // Parse Processor Hierarchy Node Structure to obtain Type and Length. + ParseAcpi ( + FALSE, + 0, + NULL, + ProcessorTopologyStructurePtr, + 4, // Length of the processor topology structure header is 4 bytes + PARSER_PARAMS (ProcessorTopologyStructureHeaderParser) + ); + + if ((Offset + (*ProcessorTopologyStructureLength)) > AcpiTableLength) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid processor topology structure length:" + L" Type = %d, Length = %d\n", + *ProcessorTopologyStructureType, + *ProcessorTopologyStructureLength + ); + break; + } + + PrintFieldName (2, L"* Structure Offset *"); + Print (L"0x%x\n", Offset); + + switch (*ProcessorTopologyStructureType) { + case EFI_ACPI_6_2_PPTT_TYPE_PROCESSOR: + DumpProcessorHierarchyNodeStructure ( + ProcessorTopologyStructurePtr, + *ProcessorTopologyStructureLength + ); + break; + case EFI_ACPI_6_2_PPTT_TYPE_CACHE: + DumpCacheTypeStructure ( + ProcessorTopologyStructurePtr, + *ProcessorTopologyStructureLength + ); + break; + case EFI_ACPI_6_2_PPTT_TYPE_ID: + DumpIDStructure ( + ProcessorTopologyStructurePtr, + *ProcessorTopologyStructureLength + ); + break; + default: + IncrementErrorCount (); + Print ( + L"ERROR: Unknown processor topology structure:" + L" Type = %d, Length = %d\n", + *ProcessorTopologyStructureType, + *ProcessorTopologyStructureLength + ); + } + + ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength; + Offset += *ProcessorTopologyStructureLength; + } // while +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c new file mode 100644 index 0000000..c73e5b7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c @@ -0,0 +1,181 @@ +/** @file + RSDP table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT64* XsdtAddress; + +/** + This function validates the RSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateRsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function validates the XSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateXsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + An array describing the ACPI RSDP Table. +**/ +STATIC CONST ACPI_PARSER RsdpParser[] = { + {L"Signature", 8, 0, NULL, Dump8Chars, NULL, NULL, NULL}, + {L"Checksum", 1, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Oem ID", 6, 9, NULL, Dump6Chars, NULL, NULL, NULL}, + {L"Revision", 1, 15, L"%d", NULL, NULL, NULL, NULL}, + {L"RSDT Address", 4, 16, L"0x%x", NULL, NULL, ValidateRsdtAddress, NULL}, + {L"Length", 4, 20, L"%d", NULL, NULL, NULL, NULL}, + {L"XSDT Address", 8, 24, L"0x%lx", NULL, (VOID**)&XsdtAddress, + ValidateXsdtAddress, NULL}, + {L"Extended Checksum", 1, 32, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL} +}; + +/** + This function validates the RSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateRsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + // Reference: Server Base Boot Requirements System Software on ARM Platforms + // Section: 4.2.1.1 RSDP + // Root System Description Pointer (RSDP), ACPI ? 5.2.5. + // - Within the RSDP, the RsdtAddress field must be null (zero) and the + // XsdtAddresss MUST be a valid, non-null, 64-bit value. + UINT32 RsdtAddr; + + RsdtAddr = *(UINT32*)Ptr; + + if (RsdtAddr != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Rsdt Address = 0x%p. This must be NULL on ARM Platforms.", + RsdtAddr + ); + } +#endif +} + +/** + This function validates the XSDT Address. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateXsdtAddress ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + // Reference: Server Base Boot Requirements System Software on ARM Platforms + // Section: 4.2.1.1 RSDP + // Root System Description Pointer (RSDP), ACPI ? 5.2.5. + // - Within the RSDP, the RsdtAddress field must be null (zero) and the + // XsdtAddresss MUST be a valid, non-null, 64-bit value. + UINT64 XsdtAddr; + + XsdtAddr = *(UINT64*)Ptr; + + if (XsdtAddr == 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Xsdt Address = 0x%p. This must not be NULL on ARM Platforms.", + XsdtAddr + ); + } +#endif +} + +/** + This function parses the ACPI RSDP table. + + This function invokes the parser for the XSDT table. + * Note - This function does not support parsing of RSDT table. + + This function also performs a RAW dump of the ACPI table and + validates the checksum. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiRsdp ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (Trace) { + DumpRaw (Ptr, AcpiTableLength); + VerifyChecksum (TRUE, Ptr, AcpiTableLength); + } + + ParseAcpi (Trace, 0, "RSDP", Ptr, AcpiTableLength, PARSER_PARAMS (RsdpParser)); + + // This code currently supports parsing of XSDT table only + // and does not parse the RSDT table. Platforms provide the + // RSDT to enable compatibility with ACPI 1.0 operating systems. + // Therefore the RSDT should not be used on ARM platforms. + if ((*XsdtAddress) == 0) { + IncrementErrorCount (); + Print (L"ERROR: XSDT Pointer is not set.\n"); + return; + } + + ProcessAcpiTable ((UINT8*)(UINTN)(*XsdtAddress)); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c new file mode 100644 index 0000000..908ad82 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c @@ -0,0 +1,145 @@ +/** @file + SLIT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT64* SlitSystemLocalityCount; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + An ACPI_PARSER array describing the ACPI SLIT table. +**/ +STATIC CONST ACPI_PARSER SlitParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Number of System Localities", 8, 36, L"0x%lx", NULL, + (VOID**)&SlitSystemLocalityCount, NULL, NULL} +}; + +/** + Macro to get the value of a System Locality +**/ +#define SLIT_ELEMENT(Ptr, i, j) *(Ptr + (i * LocalityCount) + j) + +/** + This function parses the ACPI SLIT table. + When trace is enabled this function parses the SLIT table and + traces the ACPI table fields. + + This function also validates System Localities for the following: + - Diagonal elements have a normalized value of 10 + - Relative distance from System Locality at i*N+j is same as + j*N+i + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSlit ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT64 Count; + UINT64 Index; + UINT64 LocalityCount; + UINT8* LocalityPtr; + CHAR16 Buffer[80]; // Used for AsciiName param of ParseAcpi + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "SLIT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (SlitParser) + ); + LocalityPtr = Ptr + Offset; + + LocalityCount = *SlitSystemLocalityCount; + // We only print the Localities if the count is less than 16 + // If the locality count is more than 16 then refer to the + // raw data dump. + if (LocalityCount < 16) { + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Entry[0x%lx][0x%lx]", + LocalityCount, + LocalityCount + ); + PrintFieldName (0, Buffer); + Print (L"\n"); + Print (L" "); + for (Index = 0; Index < LocalityCount; Index++) { + Print (L" (%3d) ", Index); + } + Print (L"\n"); + for (Count = 0; Count< LocalityCount; Count++) { + Print (L" (%3d) ", Count); + for (Index = 0; Index < LocalityCount; Index++) { + Print (L" %3d ", SLIT_ELEMENT (LocalityPtr, Count, Index)); + } + Print (L"\n"); + } + } + + // Validate + for (Count = 0; Count < LocalityCount; Count++) { + for (Index = 0; Index < LocalityCount; Index++) { + // Element[x][x] must be equal to 10 + if ((Count == Index) && (SLIT_ELEMENT (LocalityPtr, Count,Index) != 10)) { + IncrementErrorCount (); + Print ( + L"ERROR: Diagonal Element[0x%lx][0x%lx] (%3d)." + L" Normalized Value is not 10\n", + Count, + Index, + SLIT_ELEMENT (LocalityPtr, Count, Index) + ); + } + // Element[i][j] must be equal to Element[j][i] + if (SLIT_ELEMENT (LocalityPtr, Count, Index) != + SLIT_ELEMENT (LocalityPtr, Index, Count)) { + IncrementErrorCount (); + Print ( + L"ERROR: Relative distances for Element[0x%lx][0x%lx] (%3d) and \n" + L"Element[0x%lx][0x%lx] (%3d) do not match.\n", + Count, + Index, + SLIT_ELEMENT (LocalityPtr, Count, Index), + Index, + Count, + SLIT_ELEMENT (LocalityPtr, Index, Count) + ); + } + } + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c new file mode 100644 index 0000000..9dc1b15 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c @@ -0,0 +1,180 @@ +/** @file + SPCR table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - Microsoft Serial Port Console Redirection Table + Specification - Version 1.03 - August 10, 2015. +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + This function validates the Interrupt Type. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateInterruptType ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function validates the Irq. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateIrq ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + An ACPI_PARSER array describing the ACPI SPCR Table. +**/ +STATIC CONST ACPI_PARSER SpcrParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Interface Type", 1, 36, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 3, 37, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}, + {L"Base Address", 12, 40, NULL, DumpGas, NULL, NULL, NULL}, + {L"Interrupt Type", 1, 52, L"%d", NULL, NULL, ValidateInterruptType, NULL}, + {L"IRQ", 1, 53, L"%d", NULL, NULL, ValidateIrq, NULL}, + {L"Global System Interrupt", 4, 54, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Baud Rate", 1, 58, L"%d", NULL, NULL, NULL, NULL}, + {L"Parity", 1, 59, L"%d", NULL, NULL, NULL, NULL}, + {L"Stop Bits", 1, 60, L"%d", NULL, NULL, NULL, NULL}, + {L"Flow Control", 1, 61, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Terminal Type", 1, 62, L"%d", NULL, NULL, NULL, NULL}, + {L"Reserved", 1, 63, L"%x", NULL, NULL, NULL, NULL}, + + {L"PCI Device ID", 2, 64, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Vendor ID", 2, 66, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Bus Number", 1, 68, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Device Number", 1, 69, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Function Number", 1, 70, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Flags", 4, 71, L"0x%x", NULL, NULL, NULL, NULL}, + {L"PCI Segment", 1, 75, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 76, L"%x", NULL, NULL, NULL, NULL} +}; + +/** + This function validates the Interrupt Type. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateInterruptType ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + UINT8 InterruptType; + + InterruptType = *Ptr; + + if (InterruptType != + EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC) { + IncrementErrorCount (); + Print ( + L"\nERROR: InterruptType = %d. This must be 8 on ARM Platforms", + InterruptType + ); + } +#endif +} + +/** + This function validates the Irq. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateIrq ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) + UINT8 Irq; + + Irq = *Ptr; + + if (Irq != 0) { + IncrementErrorCount (); + Print ( + L"\nERROR: Irq = %d. This must be zero on ARM Platforms\n", + Irq + ); + } +#endif +} + +/** + This function parses the ACPI SPCR table. + When trace is enabled this function parses the SPCR table and + traces the ACPI table fields. + + This function also performs validations of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSpcr ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + // Dump the SPCR + ParseAcpi ( + TRUE, + 0, + "SPCR", + Ptr, + AcpiTableLength, + PARSER_PARAMS (SpcrParser) + ); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c new file mode 100644 index 0000000..c7858ee --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c @@ -0,0 +1,350 @@ +/** @file + SRAT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local Variables +STATIC CONST UINT8* SratRAType; +STATIC CONST UINT8* SratRALength; +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** + This function validates the Reserved field in the SRAT table header. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateSratReserved ( + IN UINT8* Ptr, + IN VOID* Context + ); + +/** + This function traces the APIC Proximity Domain field. + + @param [in] Format Format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +STATIC +VOID +EFIAPI +DumpSratApicProximity ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ); + +/** + An ACPI_PARSER array describing the SRAT Table. +**/ +STATIC CONST ACPI_PARSER SratParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo), + {L"Reserved", 4, 36, L"0x%x", NULL, NULL, ValidateSratReserved, NULL}, + {L"Reserved", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Resource Allocation structure header. +**/ +STATIC CONST ACPI_PARSER SratResourceAllocationParser[] = { + {L"Type", 1, 0, NULL, NULL, (VOID**)&SratRAType, NULL, NULL}, + {L"Length", 1, 1, NULL, NULL, (VOID**)&SratRALength, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the GICC Affinity structure. +**/ +STATIC CONST ACPI_PARSER SratGicCAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ACPI Processor UID", 4, 6, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 10, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Clock Domain", 4, 14, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the GIC ITS Affinity structure. +**/ +STATIC CONST ACPI_PARSER SratGicITSAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL}, + {L"ITS Id", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, +}; + +/** + An ACPI_PARSER array describing the Memory Affinity structure. +**/ +STATIC CONST ACPI_PARSER SratMemAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Base Address Low", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Base Address High", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length Low", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length High", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the APIC/SAPIC Affinity structure. +**/ +STATIC CONST ACPI_PARSER SratApciSapicAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Proximity Domain [7:0]", 1, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Local SAPIC EID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Proximity Domain [31:8]", 3, 9, L"0x%x", DumpSratApicProximity, + NULL, NULL, NULL}, + {L"Clock Domain", 4, 12, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** + An ACPI_PARSER array describing the Processor Local x2APIC Affinity structure. +**/ +STATIC CONST ACPI_PARSER SratX2ApciAffinityParser[] = { + {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL}, + + {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}, + {L"X2APIC ID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Clock Domain", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}, + {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL} +}; + +/** This function validates the Reserved field in the SRAT table header. + + @param [in] Ptr Pointer to the start of the field data. + @param [in] Context Pointer to context specific information e.g. this + could be a pointer to the ACPI table header. +**/ +STATIC +VOID +EFIAPI +ValidateSratReserved ( + IN UINT8* Ptr, + IN VOID* Context + ) +{ + if (*(UINT32*)Ptr != 1) { + IncrementErrorCount (); + Print (L"\nERROR: Reserved should be 1 for backward compatibility.\n"); + } +} + +/** + This function traces the APIC Proximity Domain field. + + @param [in] Format Format string for tracing the data. + @param [in] Ptr Pointer to the start of the buffer. +**/ +STATIC +VOID +EFIAPI +DumpSratApicProximity ( + IN CONST CHAR16* Format, + IN UINT8* Ptr + ) +{ + UINT32 ProximityDomain; + + ProximityDomain = Ptr[0] | (Ptr[1] << 8) | (Ptr[2] << 16); + + Print (Format, ProximityDomain); +} + +/** + This function parses the ACPI SRAT table. + When trace is enabled this function parses the SRAT table and + traces the ACPI table fields. + + This function parses the following Resource Allocation Structures: + - Processor Local APIC/SAPIC Affinity Structure + - Memory Affinity Structure + - Processor Local x2APIC Affinity Structure + - GICC Affinity Structure + + This function also performs validation of the ACPI table fields. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSrat ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT8* ResourcePtr; + UINT32 GicCAffinityIndex; + UINT32 GicITSAffinityIndex; + UINT32 MemoryAffinityIndex; + UINT32 ApicSapicAffinityIndex; + UINT32 X2ApicAffinityIndex; + CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi + + GicCAffinityIndex = 0; + GicITSAffinityIndex = 0; + MemoryAffinityIndex = 0; + ApicSapicAffinityIndex = 0; + X2ApicAffinityIndex = 0; + + if (!Trace) { + return; + } + + Offset = ParseAcpi ( + TRUE, + 0, + "SRAT", + Ptr, + AcpiTableLength, + PARSER_PARAMS (SratParser) + ); + ResourcePtr = Ptr + Offset; + + while (Offset < AcpiTableLength) { + ParseAcpi ( + FALSE, + 0, + NULL, + ResourcePtr, + 2, // The length is 1 byte at offset 1 + PARSER_PARAMS (SratResourceAllocationParser) + ); + + switch (*SratRAType) { + case EFI_ACPI_6_2_GICC_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "GICC Affinity Structure [%d]", + GicCAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratGicCAffinityParser) + ); + break; + + case EFI_ACPI_6_2_GIC_ITS_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "GIC ITS Affinity Structure [%d]", + GicITSAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratGicITSAffinityParser) + ); + break; + + case EFI_ACPI_6_2_MEMORY_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "Memory Affinity Structure [%d]", + MemoryAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratMemAffinityParser) + ); + break; + + case EFI_ACPI_6_2_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "APIC/SAPIC Affinity Structure [%d]", + ApicSapicAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratApciSapicAffinityParser) + ); + break; + + case EFI_ACPI_6_2_PROCESSOR_LOCAL_X2APIC_AFFINITY: + AsciiSPrint ( + Buffer, + sizeof (Buffer), + "X2APIC Affinity Structure [%d]", + X2ApicAffinityIndex++ + ); + ParseAcpi ( + TRUE, + 2, + Buffer, + ResourcePtr, + *SratRALength, + PARSER_PARAMS (SratX2ApciAffinityParser) + ); + break; + + default: + IncrementErrorCount (); + Print (L"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType); + break; + } + + ResourcePtr += (*SratRALength); + Offset += (*SratRALength); + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c new file mode 100644 index 0000000..fa8868e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c @@ -0,0 +1,48 @@ +/** @file + SSDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +/** + This function parses the ACPI SSDT table. + When trace is enabled this function parses the SSDT table and + traces the ACPI table fields. + For the SSDT table only the ACPI header fields are + parsed and traced. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiSsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + if (!Trace) { + return; + } + + DumpAcpiHeader (Ptr); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c new file mode 100644 index 0000000..d10c6a6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c @@ -0,0 +1,156 @@ +/** @file + XSDT table parser + + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved. + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + @par Reference(s): + - ACPI 6.2 Specification - Errata A, September 2017 +**/ + +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" + +// Local variables +STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo; + +/** An ACPI_PARSER array describing the ACPI XSDT table. +*/ +STATIC CONST ACPI_PARSER XsdtParser[] = { + PARSE_ACPI_HEADER (&AcpiHdrInfo) +}; + +/** + Get the ACPI XSDT header info. +**/ +CONST ACPI_DESCRIPTION_HEADER_INFO * +EFIAPI +GetAcpiXsdtHeaderInfo ( + VOID +) +{ + return &AcpiHdrInfo; +} + +/** + This function parses the ACPI XSDT table and optionally traces the ACPI table fields. + + This function also performs validation of the XSDT table. + + @param [in] Trace If TRUE, trace the ACPI fields. + @param [in] Ptr Pointer to the start of the buffer. + @param [in] AcpiTableLength Length of the ACPI table. + @param [in] AcpiTableRevision Revision of the ACPI table. +**/ +VOID +EFIAPI +ParseAcpiXsdt ( + IN BOOLEAN Trace, + IN UINT8* Ptr, + IN UINT32 AcpiTableLength, + IN UINT8 AcpiTableRevision + ) +{ + UINT32 Offset; + UINT32 TableOffset; + UINT64* TablePointer; + UINTN EntryIndex; + CHAR16 Buffer[32]; + + // Parse the ACPI header to get the length + ParseAcpi ( + FALSE, + 0, + "XSDT", + Ptr, + ACPI_DESCRIPTION_HEADER_LENGTH, + PARSER_PARAMS (XsdtParser) + ); + + Offset = ParseAcpi ( + Trace, + 0, + "XSDT", + Ptr, + *AcpiHdrInfo.Length, + PARSER_PARAMS (XsdtParser) + ); + + TableOffset = Offset; + + if (Trace) { + EntryIndex = 0; + TablePointer = (UINT64*)(Ptr + TableOffset); + while (Offset < (*AcpiHdrInfo.Length)) { + CONST UINT32* Signature; + CONST UINT32* Length; + CONST UINT8* Revision; + + if ((UINT64*)(UINTN)(*TablePointer) != NULL) { + UINT8* SignaturePtr; + + ParseAcpiHeader ( + (UINT8*)(UINTN)(*TablePointer), + &Signature, + &Length, + &Revision + ); + + SignaturePtr = (UINT8*)Signature; + + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Entry[%d] - %c%c%c%c", + EntryIndex++, + SignaturePtr[0], + SignaturePtr[1], + SignaturePtr[2], + SignaturePtr[3] + ); + } else { + UnicodeSPrint ( + Buffer, + sizeof (Buffer), + L"Entry[%d]", + EntryIndex++ + ); + } + + PrintFieldName (2, Buffer); + Print (L"0x%lx\n", *TablePointer); + + // Validate the table pointers are not NULL + if ((UINT64*)(UINTN)(*TablePointer) == NULL) { + IncrementErrorCount (); + Print ( + L"ERROR: Invalid table entry at 0x%lx, table address is 0x%lx\n", + TablePointer, + *TablePointer + ); + } + Offset += sizeof (UINT64); + TablePointer++; + } // while + } + + // Process the tables + Offset = TableOffset; + TablePointer = (UINT64*)(Ptr + TableOffset); + while (Offset < (*AcpiHdrInfo.Length)) { + if ((UINT64*)(UINTN)(*TablePointer) != NULL) { + ProcessAcpiTable ((UINT8*)(UINTN)(*TablePointer)); + } + Offset += sizeof (UINT64); + TablePointer++; + } // while +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c new file mode 100644 index 0000000..43a9003 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c @@ -0,0 +1,174 @@ +/** @file + Main file for 'acpiview' Shell command function. + + Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include "AcpiParser.h" +#include "AcpiTableParser.h" +#include "AcpiView.h" +#include "UefiShellAcpiViewCommandLib.h" + +CONST CHAR16 gShellAcpiViewFileName[] = L"ShellCommand"; + +/** + A list of available table parsers. +*/ +STATIC +CONST +ACPI_TABLE_PARSER ParserList[] = { + {EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE, ParseAcpiBgrt}, + {EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, ParseAcpiDbg2}, + {EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + ParseAcpiDsdt}, + {EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiFadt}, + {EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiGtdt}, + {EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE, ParseAcpiIort}, + {EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiMadt}, + {EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE, + ParseAcpiMcfg}, + {EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE, + ParseAcpiPptt}, + {RSDP_TABLE_INFO, ParseAcpiRsdp}, + {EFI_ACPI_6_2_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE, ParseAcpiSlit}, + {EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE, ParseAcpiSpcr}, + {EFI_ACPI_6_2_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE, ParseAcpiSrat}, + {EFI_ACPI_6_2_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiSsdt}, + {EFI_ACPI_6_2_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiXsdt} +}; + +/** + This function registers all the available table parsers. + + @retval EFI_SUCCESS The parser is registered. + @retval EFI_ALREADY_STARTED The parser for the ACPI Table + was already registered. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES No space to register the + parser. +**/ +EFI_STATUS +RegisterAllParsers ( + ) +{ + EFI_STATUS Status; + UINTN Count; + + Status = EFI_SUCCESS; + Count = sizeof (ParserList) / sizeof (ParserList[0]); + + while (Count-- != 0) { + Status = RegisterParser ( + ParserList[Count].Signature, + ParserList[Count].Parser + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + return Status; +} + +/** + Return the file name of the help text file if not using HII. + + @return The string pointer to the file name. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameAcpiView ( + VOID + ) +{ + return gShellAcpiViewFileName; +} + +/** + Constructor for the Shell AcpiView Command library. + + Install the handlers for acpiview UEFI Shell command. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS The Shell command handlers were installed + successfully. + @retval EFI_DEVICE_ERROR Hii package failed to install. +**/ +EFI_STATUS +EFIAPI +UefiShellAcpiViewCommandLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + gShellAcpiViewHiiHandle = NULL; + + // Check Shell Profile Debug1 bit of the profiles mask + if ((PcdGet8 (PcdShellProfileMask) & BIT1) == 0) { + return EFI_SUCCESS; + } + + Status = RegisterAllParsers (); + if (EFI_ERROR (Status)) { + Print (L"acpiview: Error failed to register parser.\n"); + return Status; + } + + gShellAcpiViewHiiHandle = HiiAddPackages ( + &gShellAcpiViewHiiGuid, + gImageHandle, + UefiShellAcpiViewCommandLibStrings, + NULL + ); + if (gShellAcpiViewHiiHandle == NULL) { + return EFI_DEVICE_ERROR; + } + // Install our Shell command handler + ShellCommandRegisterCommandName ( + L"acpiview", + ShellCommandRunAcpiView, + ShellCommandGetManFileNameAcpiView, + 0, + L"acpiview", + TRUE, + gShellAcpiViewHiiHandle, + STRING_TOKEN (STR_GET_HELP_ACPIVIEW) + ); + + return EFI_SUCCESS; +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +UefiShellAcpiViewCommandLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellAcpiViewHiiHandle != NULL) { + HiiRemovePackages (gShellAcpiViewHiiHandle); + } + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h new file mode 100644 index 0000000..b8d4639 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h @@ -0,0 +1,32 @@ +/** @file + Header file for 'acpiview' Shell command functions. + + Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_ +#define UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_ + +extern EFI_HII_HANDLE gShellAcpiViewHiiHandle; + +/** + Function for 'acpiview' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAcpiView ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif // UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf new file mode 100644 index 0000000..84dfd58 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf @@ -0,0 +1,78 @@ +## @file +# Provides Shell 'acpiview' command functions +# +# Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = UefiShellAcpiViewCommandLib + FILE_GUID = FB5B305E-84F5-461F-940D-82D345757AFA + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = UefiShellAcpiViewCommandLibConstructor + DESTRUCTOR = UefiShellAcpiViewCommandLibDestructor + +[Sources.common] + UefiShellAcpiViewCommandLib.uni + UefiShellAcpiViewCommandLib.c + UefiShellAcpiViewCommandLib.h + AcpiParser.h + AcpiTableParser.h + AcpiView.h + AcpiParser.c + AcpiTableParser.c + AcpiView.c + Parsers/Bgrt/BgrtParser.c + Parsers/Dbg2/Dbg2Parser.c + Parsers/Dsdt/DsdtParser.c + Parsers/Fadt/FadtParser.c + Parsers/Gtdt/GtdtParser.c + Parsers/Iort/IortParser.c + Parsers/Madt/MadtParser.c + Parsers/Mcfg/McfgParser.c + Parsers/Pptt/PpttParser.c + Parsers/Rsdp/RsdpParser.c + Parsers/Slit/SlitParser.c + Parsers/Spcr/SpcrParser.c + Parsers/Srat/SratParser.c + Parsers/Ssdt/SsdtParser.c + Parsers/Xsdt/XsdtParser.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + PrintLib + FileHandleLib + + +[FixedPcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Guids] + gShellAcpiViewHiiGuid ## CONSUMES ## HII + gEfiAcpiTableGuid ## SOMETIMES_CONSUMES ## SystemTable diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni new file mode 100644 index 0000000..6b1e1e3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni @@ -0,0 +1,134 @@ +// /** +// +// Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellAcpiViewCommandLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell acpiview command +// +// +// */ + +/=# + +#langdef en-US "english" + +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n" +#string STR_GEN_MISSING_OPTION #language en-US "%H%s%N: Missing option '%H%s%N' required by flag - '%H%s%N'\r\n" +#string STR_GEN_READONLY_MEDIA #language en-US "%H%s%N: Unable to write to the current directory, check if media is writable.\r\n" + +#string STR_GET_HELP_ACPIVIEW #language en-US "" +".TH acpiview 0 "Display ACPI information."\r\n" +".SH NAME\r\n" +"Display ACPI Table information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"ACPIVIEW [[-?] | [[-l] | [-s AcpiTable [-d]]] [-c] [-v] [-h Highlight]]\r\n" +" \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -l - Display list of installed ACPI Tables.\r\n" +" -s - Display only the specified AcpiTable type.\r\n" +" AcpiTable : The required ACPI Table type.\r\n" +" -d - Generate a binary file dump of the specified AcpiTable.\r\n" +" -c - Consistency checking (enabled by default).\r\n" +" -v - Display verbose data (enabled by default).\r\n" +" -h - Enable/Disable Colour Highlighting.\r\n" +" Highlight : TRUE/ON enables highlighting;\r\n" +" FALSE/OFF (default) disables highlighting.\r\n" +" -? - Show help.\r\n" +" \r\n" +".SH DESCRIPTION\r\n" +" \r\n" +" This program is provided to allow examination of ACPI table values from the\r\n" +" UEFI Shell. This can help with investigations, especially at that stage where\r\n" +" the tables are not enabling an OS to boot.\r\n" +" The program is not exhaustive, and only encapsulates detailed knowledge of a\r\n" +" limited number of table types.\r\n" +" \r\n" +" Default behaviour is to display the content of all tables installed.\r\n" +" 'Known' table types (listed in NOTES below) will be parsed and displayed\r\n" +" with descriptions and field values. Where appropriate a degree of consistency\r\n" +" checking is done and errors may be reported in the output.\r\n" +" Other table types will be displayed as an array of Hexadecimal bytes.\r\n" +" \r\n" +" To facilitate debugging, the -s and -d options can be used to generate a\r\n" +" binary file image of a table that can be copied elsewhere for investigation\r\n" +" using tools such as those provided by acpica.org. This is especially relevant\r\n" +" for AML type tables like DSDT and SSDT.\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The AcpiTable parameter can match any installed table type.\r\n" +" Tables without specific handling will be displayed as a raw hex dump (or\r\n" +" dumped to a file if -d is used).\r\n" +" 2. -s option supports to display the specified AcpiTable type that is present\r\n" +" in the system. For normal type AcpiTable, it would display the data of the\r\n" +" AcpiTable and AcpiTable header. The following type may contain header type\r\n" +" other than AcpiTable header. The actual header can refer to the ACPI spec 6.2\r\n" +" Extra A. Particular types:\r\n" +" APIC - Multiple APIC Description Table (MADT)\r\n" +" BGRT - Boot Graphics Resource Table\r\n" +" DBG2 - Debug Port Table 2\r\n" +" DSDT - Differentiated System Description Table\r\n" +" FACP - Fixed ACPI Description Table (FADT)\r\n" +" GTDT - Generic Timer Description Table\r\n" +" IORT - IO Remapping Table\r\n" +" MCFG - Memory Mapped Config Space Base Address Description Table\r\n" +" PPTT - Processor Properties Topology Table\r\n" +" RSDP - Root System Description Pointer\r\n" +" SLIT - System Locality Information Table\r\n" +" SPCR - Serial Port Console Redirection Table\r\n" +" SRAT - System Resource Affinity Table\r\n" +" SSDT - Secondary SystemDescription Table\r\n" +" XSDT - Extended System Description Table\r\n" +" \r\n" +".SH STANDARDS\r\n" +" \r\n" +" Table details correspond to those in 'Advanced Configuration and Power\r\n" +" Interface Specification' Version 6.2 Errata A, [September 2017]\r\n" +" (http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf)\r\n" +" \r\n" +" NOTE: The nature of the ACPI standard means that almost all tables in 6.1 will\r\n" +" be 'backwards compatible' with prior version of the specification in\r\n" +" terms of structure, so formatted output should be correct. The main\r\n" +" exception will be that previously 'reserved' fields will be reported\r\n" +" with new names, where they have been added in later versions of the\r\n" +" specification.\r\n" +" \r\n" +".SH EXAMPLES\r\n" +" \r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display a list of the installed table types:\r\n" +" fs0:\> acpiview -l\r\n" +" \r\n" +" * To parse and display a specific table type:\r\n" +" fs0:\> acpiview -s GTDT\r\n" +" \r\n" +" * To save a binary dump of the contents of a table to a file\r\n" +" in the current working directory:\r\n" +" fs0:\> acpiview -s DSDT -d\r\n" +" \r\n" +" * To display contents of all ACPI tables:\r\n" +" fs0:\> acpiview\r\n" +" \r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS Data was displayed as requested.\r\n" +" SHELL_INVALID_PARAMETER ACPI Table parsing failed.\r\n" +" \r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c new file mode 100644 index 0000000..f6a3d97 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c @@ -0,0 +1,1906 @@ +/** @file + Main file for BCFG command. + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; +STATIC EFI_HANDLE gShellBcfgHiiHandle = NULL; + +typedef enum { + BcfgTargetBootOrder = 0, + BcfgTargetDriverOrder = 1, + BcfgTargetMax = 2 +} BCFG_OPERATION_TARGET; + +typedef enum { + BcfgTypeDump = 0, + BcfgTypeAdd = 1, + BcfgTypeAddp = 2, + BcfgTypeAddh = 3, + BcfgTypeRm = 4, + BcfgTypeMv = 5, + BcfgTypeOpt = 6, + BcfgTypeMod = 7, + BcfgTypeModf = 8, + BcfgTypeModp = 9, + BcfgTypeModh = 10, + BcfgTypeMax = 11 +} BCFG_OPERATION_TYPE; + +typedef struct { + BCFG_OPERATION_TARGET Target; + BCFG_OPERATION_TYPE Type; + UINT16 Number1; + UINT16 Number2; + UINTN HandleIndex; + CHAR16 *FileName; + CHAR16 *Description; + UINT16 *Order; + CONST CHAR16 *OptData; +} BGFG_OPERATION; + +/** + Update the optional data for a boot or driver option. + + If optional data exists it will be changed. + + @param[in] Index The boot or driver option index update. + @param[in] DataSize The size in bytes of Data. + @param[in] Data The buffer for the optioanl data. + @param[in] Target The target of the operation. + + @retval EFI_SUCCESS The data was sucessfully updated. + @retval other A error occured. +**/ +EFI_STATUS +UpdateOptionalData( + UINT16 Index, + UINTN DataSize, + UINT8 *Data, + IN CONST BCFG_OPERATION_TARGET Target + ) +{ + EFI_STATUS Status; + CHAR16 VariableName[12]; + UINTN OriginalSize; + UINT8 *OriginalData; + UINTN NewSize; + UINT8 *NewData; + UINTN OriginalOptionDataSize; + + UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index); + + OriginalSize = 0; + OriginalData = NULL; + NewData = NULL; + NewSize = 0; + + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &OriginalSize, + OriginalData); + if (Status == EFI_BUFFER_TOO_SMALL) { + OriginalData = AllocateZeroPool(OriginalSize); + if (OriginalData == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &OriginalSize, + OriginalData); + } + + if (!EFI_ERROR(Status)) { + // + // Allocate new struct and discard old optional data. + // + ASSERT (OriginalData != NULL); + OriginalOptionDataSize = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16)))); + OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32))); + OriginalOptionDataSize -= OriginalSize; + NewSize = OriginalSize - OriginalOptionDataSize + DataSize; + NewData = AllocatePool(NewSize); + if (NewData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + CopyMem (NewData, OriginalData, OriginalSize - OriginalOptionDataSize); + CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize); + } + } + + if (!EFI_ERROR(Status)) { + // + // put the data back under the variable + // + Status = gRT->SetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + NewSize, + NewData); + } + + SHELL_FREE_NON_NULL(OriginalData); + SHELL_FREE_NON_NULL(NewData); + return (Status); +} + +/** + This function will get a CRC for a boot option. + + @param[in, out] Crc The CRC value to return. + @param[in] BootIndex The boot option index to CRC. + + @retval EFI_SUCCESS The CRC was sucessfully returned. + @retval other A error occured. +**/ +EFI_STATUS +GetBootOptionCrc( + UINT32 *Crc, + UINT16 BootIndex + ) +{ + CHAR16 VariableName[12]; + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + + Buffer = NULL; + BufferSize = 0; + + // + // Get the data Buffer + // + UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex); + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool(BufferSize); + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer); + } + + // + // Get the CRC computed + // + if (!EFI_ERROR(Status)) { + Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc); + } + + SHELL_FREE_NON_NULL(Buffer); + return EFI_SUCCESS; +} + +/** + This function will populate the device path protocol parameter based on TheHandle. + + @param[in] TheHandle Driver handle. + @param[in, out] FilePath On a sucessful return the device path to the handle. + + @retval EFI_SUCCESS The device path was sucessfully returned. + @retval other A error from gBS->HandleProtocol. + + @sa HandleProtocol +**/ +EFI_STATUS +GetDevicePathForDriverHandle ( + IN EFI_HANDLE TheHandle, + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&ImageDevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { +// *DevPath = DuplicateDevicePath (ImageDevicePath); +// *FilePath = DuplicateDevicePath (LoadedImage->FilePath); + *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath); + gBS->CloseProtocol( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + gImageHandle, + NULL); + } + gBS->CloseProtocol( + TheHandle, + &gEfiLoadedImageProtocolGuid, + gImageHandle, + NULL); + } + return (Status); +} + +/** + Functino to get Device Path by a handle. + + @param[in] TheHandle Use it to get DevicePath. + @param[in] Target Boot option target. + @param[in, out] DevicePath On a sucessful return the device path to the handle. + + @retval SHELL_INVALID_PARAMETER The handle was NULL. + @retval SHELL_NOT_FOUND Not found device path by handle. + @retval SHELL_SUCCESS Get device path successfully. +**/ +SHELL_STATUS +GetDevicePathByHandle( + IN EFI_HANDLE TheHandle, + IN BCFG_OPERATION_TARGET Target, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + + UINTN DriverBindingHandleCount; + UINTN ParentControllerHandleCount; + UINTN ChildControllerHandleCount; + + ShellStatus = SHELL_SUCCESS; + + if (TheHandle == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); + return SHELL_INVALID_PARAMETER; + } + + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (TheHandle, &DriverBindingHandleCount, NULL); + if (EFI_ERROR(Status)) { + DriverBindingHandleCount = 0; + } + + Status = PARSE_HANDLE_DATABASE_PARENTS (TheHandle, &ParentControllerHandleCount, NULL); + if (EFI_ERROR (Status)) { + ParentControllerHandleCount = 0; + } + + Status = ParseHandleDatabaseForChildControllers (TheHandle, &ChildControllerHandleCount, NULL); + if (EFI_ERROR (Status)) { + ChildControllerHandleCount = 0; + } + + Status = gBS->HandleProtocol (TheHandle, &gEfiDevicePathProtocolGuid, (VOID**)DevicePath); + + if ( DriverBindingHandleCount > 0 || + ParentControllerHandleCount > 0 || + ChildControllerHandleCount > 0 || + !EFI_ERROR(Status) + ) { + // + // The handle points to a real controller which has a device path. + // + if (Target == BcfgTargetDriverOrder) { + ShellPrintHiiEx ( + -1, + -1, + NULL,STRING_TOKEN (STR_GEN_PARAM_INV), + gShellBcfgHiiHandle, + L"bcfg", + L"Handle should point to driver image." + ); + ShellStatus = SHELL_NOT_FOUND; + } + } else { + // + // The handle points to a driver image. + // + if (Target == BcfgTargetBootOrder) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PARAM_INV), + gShellBcfgHiiHandle, + L"bcfg", + L"Handle should point to controller." + ); + ShellStatus = SHELL_NOT_FOUND; + } else { + if (EFI_ERROR (GetDevicePathForDriverHandle (TheHandle, DevicePath))) { + ShellStatus = SHELL_NOT_FOUND; + } + } + } + + return (ShellStatus); +} + +/** + Function to modify an option. + + @param[in] BcfgOperation Pointer to BCFG operation. + @param[in] OrderCount The number if items in CurrentOrder. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_OUT_OF_RESOUCES A memory allocation failed. +**/ +SHELL_STATUS +BcfgMod ( + IN CONST BGFG_OPERATION *BcfgOperation, + IN CONST UINTN OrderCount + ) +{ + EFI_STATUS Status; + EFI_HANDLE CurHandle; + SHELL_STATUS ShellStatus; + CHAR16 OptionStr[40]; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Arg; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathBuffer; + EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker; + EFI_BOOT_MANAGER_LOAD_OPTION LoadOption; + + ShellStatus = SHELL_SUCCESS; + FileList = NULL; + DevicePath = NULL; + DevicePathBuffer = NULL; + + ZeroMem (&LoadOption, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION)); + + if ( (BcfgOperation->Type == BcfgTypeMod && BcfgOperation->Description == NULL) || + (BcfgOperation->Type == BcfgTypeModf && BcfgOperation->FileName == NULL) || + (BcfgOperation->Type == BcfgTypeModp && BcfgOperation->FileName == NULL) || + (BcfgOperation->Type == BcfgTypeModh && BcfgOperation->HandleIndex == 0) || + (BcfgOperation->Number1 > OrderCount) + ) { + return (SHELL_INVALID_PARAMETER); + } + + if (BcfgOperation->Type == BcfgTypeModh) { + CurHandle = ConvertHandleIndexToHandle (BcfgOperation->HandleIndex); + ShellStatus = GetDevicePathByHandle (CurHandle, BcfgOperation->Target, &DevicePathBuffer); + if (ShellStatus == SHELL_SUCCESS) { + DevicePath = DuplicateDevicePath (DevicePathBuffer); + } + } else if (BcfgOperation->Type == BcfgTypeModf || BcfgOperation->Type == BcfgTypeModp) { + // + // Get Device Path by FileName. + // + ShellOpenFileMetaArg ((CHAR16 *)BcfgOperation->FileName, EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL) { + // + // The name of file matched nothing. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + else if (FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // If the name of file expanded to multiple names, it's fail. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Arg = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link); + if (EFI_ERROR (Arg->Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", BcfgOperation->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + DevicePathBuffer = gEfiShellProtocol->GetDevicePathFromFilePath (Arg->FullName); + if (DevicePathBuffer == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (BcfgOperation->Type == BcfgTypeModp) { + ShellStatus = SHELL_INVALID_PARAMETER; + DevicePathWalker = DevicePathBuffer; + while (!IsDevicePathEnd (DevicePathWalker)) { + if ( DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH && + DevicePathSubType (DevicePathWalker) == MEDIA_HARDDRIVE_DP + ) { + // + // We found the portion of device path starting with the hard driver partition. + // + ShellStatus = SHELL_SUCCESS; + DevicePath = DuplicateDevicePath (DevicePathWalker); + break; + } else { + DevicePathWalker = NextDevicePathNode (DevicePathWalker); + } + } + } else { + DevicePath = DuplicateDevicePath (DevicePathBuffer); + } + + FreePool (DevicePathBuffer); + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (BcfgOperation->Target == BcfgTargetBootOrder) { + UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Boot%04x", BcfgOperation->Order[BcfgOperation->Number1]); + } else { + UnicodeSPrint (OptionStr, sizeof (OptionStr), L"Driver%04x", BcfgOperation->Order[BcfgOperation->Number1]); + } + Status = EfiBootManagerVariableToLoadOption (OptionStr, &LoadOption); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NONE), gShellBcfgHiiHandle); + ShellStatus = SHELL_NOT_FOUND; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (BcfgOperation->Type == BcfgTypeMod) { + SHELL_FREE_NON_NULL (LoadOption.Description); + LoadOption.Description = AllocateCopyPool (StrSize (BcfgOperation->Description), BcfgOperation->Description); + } else { + SHELL_FREE_NON_NULL (LoadOption.FilePath); + LoadOption.FilePath = DuplicateDevicePath (DevicePath); + } + + Status = EfiBootManagerLoadOptionToVariable (&LoadOption); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + EfiBootManagerFreeLoadOption (&LoadOption); + + if (DevicePath != NULL) { + FreePool (DevicePath); + } + + if (FileList != NULL) { + ShellCloseFileMetaArg (&FileList); + } + + return (ShellStatus); +} + +/** + Function to add a option. + + @param[in] Position The position to add Target at. + @param[in] File The file to make the target. + @param[in] Desc The description text. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] Target The info on the option to add. + @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc. + @param[in] UsePath TRUE to convert to devicepath. + @param[in] HandleNumber The handle number to add. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgAdd( + IN UINTN Position, + IN CONST CHAR16 *File, + IN CONST CHAR16 *Desc, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST BOOLEAN UseHandle, + IN CONST BOOLEAN UsePath, + IN CONST UINTN HandleNumber + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + CHAR16 *Str; + UINT8 *TempByteBuffer; + UINT8 *TempByteStart; + EFI_SHELL_FILE_INFO *Arg; + EFI_SHELL_FILE_INFO *FileList; + CHAR16 OptionStr[40]; + UINTN DescSize, FilePathSize; + BOOLEAN Found; + UINTN TargetLocation; + UINTN Index; + EFI_HANDLE *Handles; + EFI_HANDLE CurHandle; + UINTN DriverBindingHandleCount; + UINTN ParentControllerHandleCount; + UINTN ChildControllerHandleCount; + SHELL_STATUS ShellStatus; + UINT16 *NewOrder; + + if (!UseHandle) { + if (File == NULL || Desc == NULL) { + return (SHELL_INVALID_PARAMETER); + } + } else { + if (HandleNumber == 0) { + return (SHELL_INVALID_PARAMETER); + } + } + + if (Position > OrderCount) { + Position = OrderCount; + } + + Str = NULL; + FilePath = NULL; + FileList = NULL; + Handles = NULL; + ShellStatus = SHELL_SUCCESS; + TargetLocation = 0xFFFF; + + if (UseHandle) { + CurHandle = ConvertHandleIndexToHandle(HandleNumber); + if (CurHandle == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (Target == BcfgTargetBootOrder) { + // + //Make sure that the handle should point to a real controller + // + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( + CurHandle, + &DriverBindingHandleCount, + NULL); + + Status = PARSE_HANDLE_DATABASE_PARENTS ( + CurHandle, + &ParentControllerHandleCount, + NULL); + + Status = ParseHandleDatabaseForChildControllers ( + CurHandle, + &ChildControllerHandleCount, + NULL); + + if (DriverBindingHandleCount > 0 + || ParentControllerHandleCount > 0 + || ChildControllerHandleCount > 0) { + FilePath = NULL; + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&FilePath); + } + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + //Make sure that the handle should point to driver, not a controller. + // + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( + CurHandle, + &DriverBindingHandleCount, + NULL); + + Status = PARSE_HANDLE_DATABASE_PARENTS ( + CurHandle, + &ParentControllerHandleCount, + NULL); + + Status = ParseHandleDatabaseForChildControllers ( + CurHandle, + &ChildControllerHandleCount, + NULL); + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&FilePath); + + if (DriverBindingHandleCount > 0 + || ParentControllerHandleCount > 0 + || ChildControllerHandleCount > 0 + || !EFI_ERROR(Status) ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Get the DevicePath from the loaded image information. + // + Status = GetDevicePathForDriverHandle(CurHandle, &FilePath); + } + } + } + } else { + // + // Get file info + // + ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList); + + if (FileList == NULL) { + // + // If filename matched nothing fail + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // If filename expanded to multiple names, fail + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link); + if (EFI_ERROR(Arg->Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Build FilePath to the filename + // + + // + // get the device path + // + DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName); + if (DevicePath == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName); + ShellStatus = SHELL_UNSUPPORTED; + } else { + if (UsePath) { + DevPath = DevicePath; + ShellStatus = SHELL_INVALID_PARAMETER; + while (!IsDevicePathEnd(DevPath)) { + if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { + + // + // If we find it use it instead + // + ShellStatus = SHELL_SUCCESS; + FilePath = DuplicateDevicePath (DevPath); + break; + } + DevPath = NextDevicePathNode(DevPath); + } + } else { + FilePath = DuplicateDevicePath(DevicePath); + } + FreePool(DevicePath); + } + } + } + } + + + if (ShellStatus == SHELL_SUCCESS) { + // + // Find a free target ,a brute force implementation + // + Found = FALSE; + for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) { + Found = TRUE; + for (Index=0; Index < OrderCount; Index++) { + if (CurrentOrder[Index] == TargetLocation) { + Found = FALSE; + break; + } + } + + if (Found) { + break; + } + } + + if (TargetLocation == 0xFFFF) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation); + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Add the option + // + DescSize = StrSize(Desc); + FilePathSize = GetDevicePathSize (FilePath); + + TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize); + if (TempByteBuffer != NULL) { + TempByteStart = TempByteBuffer; + *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes + TempByteBuffer += sizeof (UINT32); + + *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength + TempByteBuffer += sizeof (UINT16); + + CopyMem (TempByteBuffer, Desc, DescSize); + TempByteBuffer += DescSize; + ASSERT (FilePath != NULL); + CopyMem (TempByteBuffer, FilePath, FilePathSize); + + UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation); + Status = gRT->SetVariable ( + OptionStr, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize, + TempByteStart + ); + + FreePool(TempByteStart); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr); + } else { + NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0])); + if (NewOrder != NULL) { + CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0])); + + // + // Insert target into order list + // + for (Index = OrderCount; Index > Position; Index--) { + NewOrder[Index] = NewOrder[Index - 1]; + } + + NewOrder[Position] = (UINT16) TargetLocation; + Status = gRT->SetVariable ( + Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + (OrderCount + 1) * sizeof (UINT16), + NewOrder + ); + + FreePool (NewOrder); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Print (L"bcfg: Add %s as %x\n", OptionStr, Position); + } + } + } + } + +// +//If always Free FilePath, will free devicepath in system when use "addh" +// + if (FilePath!=NULL && !UseHandle) { + FreePool (FilePath); + } + + if (Str != NULL) { + FreePool(Str); + } + + if (Handles != NULL) { + FreePool (Handles); + } + + if (FileList != NULL) { + ShellCloseFileMetaArg (&FileList); + } + + return (ShellStatus); +} + +/** + Funciton to remove an item. + + @param[in] Target The target item to move. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] Location The current location of the Target. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgRemove( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST UINT16 Location + ) +{ + CHAR16 VariableName[12]; + UINT16 *NewOrder; + EFI_STATUS Status; + UINTN NewCount; + + UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]); + Status = gRT->SetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + 0, + NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + return (SHELL_INVALID_PARAMETER); + } + NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0])); + if (NewOrder != NULL) { + NewCount = OrderCount; + CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0])); + CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0])); + NewCount--; + + Status = gRT->SetVariable( + Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + NewCount*sizeof(NewOrder[0]), + NewOrder); + FreePool(NewOrder); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder"); + return (SHELL_INVALID_PARAMETER); + } + return (SHELL_SUCCESS); +} + +/** + Funciton to move a item to another location. + + @param[in] Target The target item to move. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] OldLocation The current location of the Target. + @param[in] NewLocation The desired location of the Target. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgMove( + IN CONST BCFG_OPERATION_TARGET Target, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST UINT16 OldLocation, + IN UINT16 NewLocation + ) +{ + UINT16 *NewOrder; + EFI_STATUS Status; + UINT16 Temp; + + NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder); + if (NewOrder == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + // + // correct the new location + // + if (NewLocation >= OrderCount) { + if (OrderCount > 0) { + NewLocation = (UINT16)OrderCount - 1; + } else { + NewLocation = 0; + } + } + + Temp = CurrentOrder[OldLocation]; + CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0])); + CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0])); + NewOrder[NewLocation] = Temp; + + Status = gRT->SetVariable( + Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + OrderCount*sizeof(CurrentOrder[0]), + NewOrder); + + FreePool(NewOrder); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder"); + return (SHELL_INVALID_PARAMETER); + } + return (SHELL_SUCCESS); +} + +/** + Function to add optional data to an option. + + @param[in] OptData The optional data to add. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] OrderCount The number if items in CurrentOrder. + @param[in] Target The target of the operation. + + @retval SHELL_SUCCESS The operation was succesful. +**/ +SHELL_STATUS +BcfgAddOpt( + IN CONST CHAR16 *OptData, + IN CONST UINT16 *CurrentOrder, + IN CONST UINTN OrderCount, + IN CONST BCFG_OPERATION_TARGET Target + ) +{ + EFI_KEY_OPTION NewKeyOption; + EFI_KEY_OPTION *KeyOptionBuffer; + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + UINT16 OptionIndex; + UINT16 LoopCounter; + UINT64 Intermediate; + CONST CHAR16 *Temp; + CONST CHAR16 *Walker; + CHAR16 *FileName; + CHAR16 *Temp2; + CHAR16 *Data; + UINT32 KeyIndex; + CHAR16 VariableName[12]; + VOID *VariableData; + + SHELL_FILE_HANDLE FileHandle; + + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + Walker = OptData; + FileName = NULL; + Data = NULL; + KeyOptionBuffer = NULL; + VariableData = NULL; + + ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION)); + ZeroMem(VariableName, sizeof(VariableName)); + + while(Walker[0] == L' ') { + Walker++; + } + + // + // Get the index of the variable we are changing. + // + Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index"); + ShellStatus = SHELL_INVALID_PARAMETER; + return (ShellStatus); + } + OptionIndex = (UINT16)Intermediate; + + Temp = StrStr(Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + while(Walker[0] == L' ') { + Walker++; + } + + // + // determine whether we have file with data, quote delimited information, or a hot-key + // + if (Walker[0] == L'\"') { + // + // quoted filename or quoted information. + // + Temp = StrStr(Walker+1, L"\""); + if (Temp == NULL || StrLen(Temp) != 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0); + if (FileName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + return (ShellStatus); + } + Temp2 = StrStr(FileName, L"\""); + ASSERT(Temp2 != NULL); + Temp2[0] = CHAR_NULL; + Temp2++; + if (StrLen(Temp2)>0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + if (EFI_ERROR(ShellFileExists(Walker))) { + // + // Not a file. must be misc information. + // + Data = FileName; + FileName = NULL; + } else { + FileName = StrnCatGrow(&FileName, NULL, Walker, 0); + } + } + } else { + // + // filename or hot key information. + // + if (StrStr(Walker, L" ") == NULL) { + // + // filename + // + if (EFI_ERROR(ShellFileExists(Walker))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FileName = StrnCatGrow(&FileName, NULL, Walker, 0); + } + } else { + if (Target != BcfgTargetBootOrder) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Get hot key information + // + Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate; + Temp = StrStr(Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + while(Walker[0] == L' ') { + Walker++; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct. + // Re-allocate with the added information. + // + KeyOptionBuffer = AllocatePool (sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount)); + if (KeyOptionBuffer == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + return ShellStatus; + } + CopyMem (KeyOptionBuffer, &NewKeyOption, sizeof(EFI_KEY_OPTION)); + } + for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) { + // + // ScanCode + // + Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate; + Temp = StrStr(Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + while(Walker[0] == L' ') { + Walker++; + } + + // + // UnicodeChar + // + Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE); + if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker); + ShellStatus = SHELL_INVALID_PARAMETER; + } + ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate; + Temp = StrStr(Walker, L" "); + if (Temp != NULL) { + Walker = Temp; + } + while(Walker[0] == L' ') { + Walker++; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Now do the BootOption / BootOptionCrc + // + ASSERT (OptionIndex <= OrderCount); + KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex]; + Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex <= 0xFFFF ; KeyIndex++) { + UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex); + Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL); + if (Status == EFI_NOT_FOUND) { + break; + } + if (!EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(VariableData); + } + } + if (KeyIndex <= 0xFFFF) { + Status = gRT->SetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), + KeyOptionBuffer); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + ASSERT(FileName == NULL && Data == NULL); + } + } + } + + // + // Shouldn't be possible to have have both. Neither is ok though. + // + ASSERT(FileName == NULL || Data == NULL); + + if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) { + if (FileName != NULL) { + // + // Open the file and populate the data buffer. + // + Status = ShellOpenFileByName( + FileName, + &FileHandle, + EFI_FILE_MODE_READ, + 0); + if (!EFI_ERROR(Status)) { + Status = ShellGetFileSize(FileHandle, &Intermediate); + } + Data = AllocateZeroPool((UINTN)Intermediate); + if (Data == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } + if (!EFI_ERROR(Status)) { + Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data); + } + } else { + Intermediate = StrSize(Data); + } + + if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) { + Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + SHELL_FREE_NON_NULL(Data); + SHELL_FREE_NON_NULL(KeyOptionBuffer); + SHELL_FREE_NON_NULL(FileName); + return ShellStatus; +} + +/** + Function to dump the Bcfg information. + + @param[in] Op The operation. + @param[in] OrderCount How many to dump. + @param[in] CurrentOrder The pointer to the current order of items. + @param[in] VerboseOutput TRUE for extra output. FALSE otherwise. + + @retval SHELL_SUCCESS The dump was successful. + @retval SHELL_INVALID_PARAMETER A parameter was invalid. +**/ +SHELL_STATUS +BcfgDisplayDump( + IN CONST CHAR16 *Op, + IN CONST UINTN OrderCount, + IN CONST UINT16 *CurrentOrder, + IN CONST BOOLEAN VerboseOutput + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + CHAR16 VariableName[12]; + UINTN LoopVar; + CHAR16 *DevPathString; + VOID *FilePathList; + UINTN Errors; + EFI_LOAD_OPTION *LoadOption; + CHAR16 *Description; + UINTN DescriptionSize; + UINTN OptionalDataOffset; + + if (OrderCount == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg"); + return (SHELL_SUCCESS); + } + + Errors = 0; + + for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) { + Buffer = NULL; + BufferSize = 0; + DevPathString = NULL; + + UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]); + + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool(BufferSize); + Status = gRT->GetVariable( + VariableName, + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer); + } + + if (EFI_ERROR(Status) || Buffer == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName); + ++Errors; + goto Cleanup; + } + + // + // We expect the Attributes, FilePathListLength, and L'\0'-terminated + // Description fields to be present. + // + if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_BCFG_VAR_CORRUPT), + gShellBcfgHiiHandle, + L"bcfg", + VariableName + ); + ++Errors; + goto Cleanup; + } + + LoadOption = (EFI_LOAD_OPTION *)Buffer; + Description = (CHAR16*)(Buffer + sizeof (EFI_LOAD_OPTION)); + DescriptionSize = StrSize (Description); + + if (LoadOption->FilePathListLength != 0) { + FilePathList = (UINT8 *)Description + DescriptionSize; + DevPathString = ConvertDevicePathToText(FilePathList, TRUE, FALSE); + } + + OptionalDataOffset = sizeof *LoadOption + DescriptionSize + + LoadOption->FilePathListLength; + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_BCFG_LOAD_OPTIONS), + gShellBcfgHiiHandle, + LoopVar, + VariableName, + Description, + DevPathString, + OptionalDataOffset >= BufferSize ? L'N' : L'Y' + ); + if (VerboseOutput && (OptionalDataOffset < BufferSize)) { + DumpHex ( + 2, // Indent + 0, // Offset (displayed) + BufferSize - OptionalDataOffset, // DataSize + Buffer + OptionalDataOffset // UserData + ); + } + +Cleanup: + if (Buffer != NULL) { + FreePool(Buffer); + } + if (DevPathString != NULL) { + FreePool(DevPathString); + } + } + return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS; +} + +/** + Function to initialize the BCFG operation structure. + + @param[in] Struct The stuct to initialize. +**/ +VOID +InitBcfgStruct( + IN BGFG_OPERATION *Struct + ) +{ + ASSERT(Struct != NULL); + Struct->Target = BcfgTargetMax; + Struct->Type = BcfgTypeMax; + Struct->Number1 = 0; + Struct->Number2 = 0; + Struct->HandleIndex = 0; + Struct->FileName = NULL; + Struct->Description = NULL; + Struct->Order = NULL; + Struct->OptData = NULL; +} + + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-v", TypeFlag}, + {L"-opt", TypeMaxValue}, + {NULL, TypeMax} + }; + +/** + Function for 'bcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunBcfg ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamNumber; + CONST CHAR16 *CurrentParam; + BGFG_OPERATION CurrentOperation; + UINTN Length; + UINT64 Intermediate; + UINT16 Count; + + Length = 0; + ProblemParam = NULL; + Package = NULL; + ShellStatus = SHELL_SUCCESS; + + InitBcfgStruct(&CurrentOperation); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // Read in if we are doing -OPT + // + if (ShellCommandLineGetFlag(Package, L"-opt")) { + CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt"); + if (CurrentOperation.OptData == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BcfgTypeOpt; + } + + // + // small block to read the target of the operation + // + if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) || + (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) { + CurrentOperation.Target = BcfgTargetDriverOrder; + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) { + CurrentOperation.Target = BcfgTargetBootOrder; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + + // + // Read in the boot or driver order environment variable (not needed for opt) + // + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) { + Length = 0; + Status = gRT->GetVariable( + CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &Length, + CurrentOperation.Order); + if (Status == EFI_BUFFER_TOO_SMALL) { + CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0]))); + if (CurrentOperation.Order == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + Status = gRT->GetVariable( + CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder", + (EFI_GUID*)&gEfiGlobalVariableGuid, + NULL, + &Length, + CurrentOperation.Order); + } + } + } + + Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0])); + + // + // large block to read the type of operation and verify parameter types for the info. + // + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) { + for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) { + CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber); + if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) { + CurrentOperation.Type = BcfgTypeDump; + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else if (ShellCommandLineGetFlag(Package, L"-v")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BcfgTypeAdd; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + ASSERT(CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + ASSERT(CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BcfgTypeAddp; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + ASSERT(CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + ASSERT(CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) { + if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BcfgTypeAddh; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.HandleIndex = (UINT16)Intermediate; + ASSERT(CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0); + } + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) { + if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BcfgTypeRm; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + CurrentOperation.Type = BcfgTypeMv; + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number2 = (UINT16)Intermediate; + } + if (CurrentOperation.Number2 == CurrentOperation.Number1 + ||CurrentOperation.Number2 >= Count + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"mod") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeMod; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (CurrentOperation.Description == NULL); + CurrentOperation.Description = StrnCatGrow (&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modf") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeModf; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modp") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeModp; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT (CurrentOperation.FileName == NULL); + CurrentOperation.FileName = StrnCatGrow (&CurrentOperation.FileName, NULL, ShellCommandLineGetRawValue (Package, ++ParamNumber), 0); + } + } + } + } else if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)CurrentParam, L"modh") == 0) { + if ((ParamNumber + 2) >= ShellCommandLineGetCount (Package)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentOperation.Type = BcfgTypeModh; + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } + else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.Number1 = (UINT16)Intermediate; + if (CurrentOperation.Number1 >= Count) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + CurrentParam = ShellCommandLineGetRawValue (Package, ++ParamNumber); + if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber (CurrentParam, TRUE, FALSE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (CurrentParam, &Intermediate, TRUE, FALSE); + CurrentOperation.HandleIndex = (UINT16)Intermediate; + } + } + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) { + // + // we have all the info. Do the work + // + switch (CurrentOperation.Type) { + case BcfgTypeDump: + ShellStatus = BcfgDisplayDump( + CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver", + Count, + CurrentOperation.Order, + ShellCommandLineGetFlag(Package, L"-v")); + break; + case BcfgTypeMv: + ShellStatus = BcfgMove( + CurrentOperation.Target, + CurrentOperation.Order, + Count, + CurrentOperation.Number1, + CurrentOperation.Number2); + break; + case BcfgTypeRm: + ShellStatus = BcfgRemove( + CurrentOperation.Target, + CurrentOperation.Order, + Count, + CurrentOperation.Number1); + break; + case BcfgTypeAdd: + case BcfgTypeAddp: + case BcfgTypeAddh: + ShellStatus = BcfgAdd( + CurrentOperation.Number1, + CurrentOperation.FileName, + CurrentOperation.Description==NULL?L"":CurrentOperation.Description, + CurrentOperation.Order, + Count, + CurrentOperation.Target, + (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh), + (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp), + CurrentOperation.HandleIndex); + break; + case BcfgTypeMod: + case BcfgTypeModf: + case BcfgTypeModp: + case BcfgTypeModh: + ShellStatus = BcfgMod (&CurrentOperation, Count); + break; + case BcfgTypeOpt: + ShellStatus = BcfgAddOpt( + CurrentOperation.OptData, + CurrentOperation.Order, + Count, + CurrentOperation.Target); + break; + default: + ASSERT(FALSE); + } + } + } + + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + if (CurrentOperation.FileName != NULL) { + FreePool(CurrentOperation.FileName); + } + if (CurrentOperation.Description != NULL) { + FreePool(CurrentOperation.Description); + } + if (CurrentOperation.Order != NULL) { + FreePool(CurrentOperation.Order); + } + + return (ShellStatus); +} + + +/** + Function to get the filename with help context if HII will not be used. + + @return The filename with help text in it. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameBcfg ( + VOID + ) +{ + return (mFileName); +} + +/** + "Constructor" for the library. + + This will register the handler for the bcfg command. + + @param[in] ImageHandle the image handle of the process + @param[in] SystemTable the EFI System Table pointer + @param[in] Name the profile name to use + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +BcfgLibraryRegisterBcfgCommand ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable, + IN CONST CHAR16 *Name + ) +{ + if (gShellBcfgHiiHandle != NULL) { + return (EFI_SUCCESS); + } + + gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL); + if (gShellBcfgHiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handler + // + ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG)); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +BcfgLibraryUnregisterBcfgCommand ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellBcfgHiiHandle != NULL) { + HiiRemovePackages(gShellBcfgHiiHandle); + } + gShellBcfgHiiHandle = NULL; + return (EFI_SUCCESS); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf new file mode 100644 index 0000000..20d67ac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf @@ -0,0 +1,47 @@ +## @file +# Provides shell install1 functions +# +# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellBcfgCommandLib + FILE_GUID = F6A3BF5D-4095-4E4F-9670-408770C2DBDF + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.1 + LIBRARY_CLASS = BcfgCommandLib|UEFI_APPLICATION UEFI_DRIVER + +[Sources.common] + UefiShellBcfgCommandLib.c + UefiShellBcfgCommandLib.uni + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + UefiBootManagerLib + +[Guids] + gShellBcfgHiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni new file mode 100644 index 0000000..1e21d4f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni @@ -0,0 +1,159 @@ +// /** +// +// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiBcfgCommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 BCFG command +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_NO_DRIVER_BOOT #language en-US "%H%s%N: Driver or Boot must be selected.\r\n" +#string STR_GEN_BOOT_ONLY #language en-US "%H%s%N: Boot must be selected for hot key options.\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n" +#string STR_BCFG_WRITE_FAIL #language en-US "%H%s%N: Unable to write to '%H%s%N'\r\n" +#string STR_BCFG_READ_FAIL #language en-US "%H%s%N: Unable to read from '%H%s%N'\r\n" +#string STR_BCFG_VAR_CORRUPT #language en-US "%H%s%N: Variable '%H%s%N' corrupt.\r\n" +#string STR_BCFG_HANDLE #language en-US "%H%s%N: The handle [%H%02x%N] does not have DevicePath.\r\n" +#string STR_BCFG_FILE #language en-US "%H%s%N: The file '%H%s%N' matches multiple files.\r\n" +#string STR_BCFG_FILE_OPEN #language en-US "%H%s%N: The file '%H%s%N' did not open.\r\n" +#string STR_BCFG_FILE_DP #language en-US "%H%s%N: The file '%H%s%N' could not convert to DevPath.\r\n" +#string STR_BCFG_TARGET_NF #language en-US "%H%s%N: Could not find unused target index.\r\n" +#string STR_BCFG_TARGET #language en-US "Target = %04x.\r\n" +#string STR_BCFG_SET_VAR_FAIL #language en-US "%H%s%N: Unable to set %H%s%N\r\n" +#string STR_BCFG_VAR_NO_NUM #language en-US "%H%s%N: Cannot create Key#### variable: All the numbers from 0x0000 - 0xFFFF have been used.\r\n" +#string STR_BCFG_NUMB_RANGE #language en-US "%H%s%N: Numbers must be under %d.\r\n" +#string STR_BCFG_NONE #language en-US "No options found.\r\n" + +#string STR_BCFG_LOAD_OPTIONS #language en-US "Option: %B%02x%N. Variable: %B%-11s%N\r\n" + " Desc - %s\r\n" + " DevPath - %s\r\n" + " Optional- %c\r\n" +#string STR_GET_HELP_BCFG #language en-US "" +".TH bcfg 0 "configure boot and driver"\r\n" +".SH NAME\r\n" +"Manages the boot and driver options that are stored in NVRAM.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"BCFG driver|boot [dump [-v]] [add # file "desc"] [addp # file "desc"] \r\n" +" [addh # handle "desc"] [rm #] [mv # #] \r\n" +" [-opt # [[filename]|["data"]] | \r\n" +" [KeyData ]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -v - Displays verbose information about options, including the optional\r\n" +" data.\r\n" +" -opt - Displays or modifies the optional data associated with a \r\n" +" driver or boot option. This parameter is followed by the file name of the\r\n" +" file that contains the binary data to be associated with the\r\n" +" driver or boot option optional data, or the quote\r\n" +" delimited data to be associated with the driver or\r\n" +" boot option optional data.\r\n" +" driver - Displays or modifies the driver option list.\r\n" +" boot - Displays or modifies the boot option list.\r\n" +" dump - Displays the option list.\r\n" +" add - Adds an option. The # is the number of options to add in\r\n" +" hexadecimal format. The file name is the name of the UEFI application/driver for\r\n" +" the option. The quoted parameter is the description of the\r\n" +" option to be added.\r\n" +" addh - Adds an option that refers to the driver specified by a handle.\r\n" +" The # is the number of options to add, in hexadecimal format. The\r\n" +" handle is the driver handle, in hexadecimal format. The device path\r\n" +" for the option is retrieved from the handle. The quoted\r\n" +" parameter is the description of the option to be added.\r\n" +" addp - Adds an option that refers to a specific file. Only the portion\r\n" +" of the device path starting with the hard drive partition is\r\n" +" placed in the option. The # is the number of options to add,\r\n" +" in hexadecimal format. The quoted parameter is the description of the\r\n" +" option being added.\r\n" +" rm - Removes an option. The parameter lists the number of the options\r\n" +" to remove in hexadecimal format.\r\n" +" mv - Moves an option. The first numeric parameter is the number of\r\n" +" the option to move in hexadecimal format. The second numeric parameter\r\n" +" is the new number of the option to be moved.\r\n" +" KeyData - Specifies the packed value associated with a hot-key.\r\n" +" ScanCode - Specifies the UEFI-defined scan code portion of the\r\n" +" EFI_INPUT_KEY instruction. This value is directly associated\r\n" +" with the preceding KeyData value. When one instance of this\r\n" +" parameter has a non-zero value, the paired UnicodeChar value\r\n" +" will have a zero-based value.\r\n" +" UnicodeChar - Specifies the Unicode value for the character associated with\r\n" +" the preceding KeyData value. When one instance of this\r\n" +" parameter has a non-zero value, the paired ScanCode value\r\n" +" will have a zero-based value.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command manages the boot and driver options stored in NVRAM.\r\n" +" 2. Use the dump option to display Boot#### or Driver#### environment variables.\r\n" +" 3. Use the add option to add a new Boot#### or Driver#### \r\n" +" environment variable.\r\n" +" 4. Use the rm option to delete a Boot#### or Driver#### \r\n" +" environment variable, and then the mv option to reorder\r\n" +" the Boot#### and Driver#### environment variables.\r\n" +" 5. The add, rm, and mv options also update the BootOrder or DriverOrder\r\n" +" environment variables, as appropriate.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display driver options:\r\n" +" Shell> bcfg driver dump\r\n" +" \r\n" +" * To display boot options:\r\n" +" Shell> bcfg boot dump\r\n" +" \r\n" +" * To display verbose information about boot options:\r\n" +" Shell> bcfg boot dump -v\r\n" +" \r\n" +" * To add a driver option #5:\r\n" +" Shell> bcfg driver add 5 mydriver.efi "My Driver"\r\n" +" \r\n" +" * To add a boot option #3:\r\n" +" Shell> bcfg boot add 3 osloader.efi "My OS"\r\n" +" \r\n" +" * To remove boot option #3:\r\n" +" Shell> bcfg boot rm 3\r\n" +" \r\n" +" * To move boot option #3 to boot option #7:\r\n" +" Shell> bcfg boot mv 3 7\r\n" +" \r\n" +" * To assign a CTRL-B hot-key to boot option #3:\r\n" +" Shell> bcfg boot -opt 3 0x40000200 0 0x42\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_NOT_FOUND The requested option was not found.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient free space for the request\r\n" +" to be completed.\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c new file mode 100644 index 0000000..f8828e4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c @@ -0,0 +1,99 @@ +/** @file + Provides application point extension for "C" style main function + + Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include + +#include +#include + +/** + UEFI entry point for an application that will in turn call the + ShellAppMain function which has parameters similar to a standard C + main function. + + An application that uses UefiShellCEntryLib must have a ShellAppMain + function as prototyped in Include/Library/ShellCEntryLib.h. + + Note that the Shell uses POSITIVE integers for error values, while UEFI + uses NEGATIVE values. If the application is to be used within a script, + it needs to return one of the SHELL_STATUS values defined in Protocol/Shell.h. + + @param ImageHandle The image handle of the UEFI Application. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The application exited normally. + @retval Other An error occurred. + +**/ +EFI_STATUS +EFIAPI +ShellCEntryLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + INTN ReturnFromMain; + EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol; + EFI_SHELL_INTERFACE *EfiShellInterface; + EFI_STATUS Status; + + ReturnFromMain = -1; + EfiShellParametersProtocol = NULL; + EfiShellInterface = NULL; + + Status = SystemTable->BootServices->OpenProtocol(ImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **)&EfiShellParametersProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) { + // + // use shell 2.0 interface + // + ReturnFromMain = ShellAppMain ( + EfiShellParametersProtocol->Argc, + EfiShellParametersProtocol->Argv + ); + } else { + // + // try to get shell 1.0 interface instead. + // + Status = SystemTable->BootServices->OpenProtocol(ImageHandle, + &gEfiShellInterfaceGuid, + (VOID **)&EfiShellInterface, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) { + // + // use shell 1.0 interface + // + ReturnFromMain = ShellAppMain ( + EfiShellInterface->Argc, + EfiShellInterface->Argv + ); + } else { + ASSERT(FALSE); + } + } + return ReturnFromMain; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf new file mode 100644 index 0000000..99b88ad --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf @@ -0,0 +1,44 @@ +## @file +# Provides interface to shell functionality for shell commands and applications. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellCEntryLib + FILE_GUID = 0e205c8a-8586-4dec-9f5c-4f9e394aefe8 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = ShellCEntryLib|UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + UefiShellCEntryLib.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + DebugLib + + +[Protocols] + gEfiShellParametersProtocolGuid ## CONSUMES + gEfiShellInterfaceGuid ## SOMETIMES_CONSUMES + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c new file mode 100644 index 0000000..3032c83 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c @@ -0,0 +1,1698 @@ +/** @file + Main file for support of shell consist mapping. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include "UefiShellCommandLib.h" +#include +#include +#include +#include +#include +#include + + + +typedef enum { + MTDTypeUnknown, + MTDTypeFloppy, + MTDTypeHardDisk, + MTDTypeCDRom, + MTDTypeEnd +} MTD_TYPE; + +typedef struct { + CHAR16 *Str; + UINTN Len; +} POOL_PRINT; + +typedef struct { + UINTN Hi; + MTD_TYPE Mtd; + POOL_PRINT Csd; + BOOLEAN Digital; +} DEVICE_CONSIST_MAPPING_INFO; + +typedef struct { + MTD_TYPE MTDType; + CHAR16 *Name; +} MTD_NAME; + +/** + Serial Decode function. + + @param DevPath The Device path info. + @param MapInfo The map info. + @param OrigDevPath The original device path protocol. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +typedef +EFI_STATUS +(*SERIAL_DECODE_FUNCTION) ( + EFI_DEVICE_PATH_PROTOCOL *DevPath, + DEVICE_CONSIST_MAPPING_INFO *MapInfo, + EFI_DEVICE_PATH_PROTOCOL *OrigDevPath + ); + +typedef struct { + UINT8 Type; + UINT8 SubType; + SERIAL_DECODE_FUNCTION SerialFun; + INTN (EFIAPI *CompareFun) (EFI_DEVICE_PATH_PROTOCOL *DevPath, EFI_DEVICE_PATH_PROTOCOL *DevPath2); +} DEV_PATH_CONSIST_MAPPING_TABLE; + + +/** + 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 ... The data will be printed. + + @retval EFI_SUCCESS The string is concatenated successfully. + @retval EFI_OUT_OF_RESOURCES Out of resources. + +**/ +EFI_STATUS +EFIAPI +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *Fmt, + ... + ) +{ + UINT16 *AppendStr; + VA_LIST Args; + UINTN StringSize; + CHAR16 *NewStr; + + AppendStr = AllocateZeroPool (0x1000); + if (AppendStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + VA_START (Args, Fmt); + UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args); + VA_END (Args); + if (NULL == Str->Str) { + StringSize = StrSize (AppendStr); + NewStr = AllocateZeroPool (StringSize); + } else { + StringSize = StrSize (AppendStr); + StringSize += (StrSize (Str->Str) - sizeof (UINT16)); + + NewStr = ReallocatePool ( + StrSize (Str->Str), + StringSize, + Str->Str + ); + } + if (NewStr == NULL) { + FreePool (AppendStr); + return EFI_OUT_OF_RESOURCES; + } + + Str->Str = NewStr; + StrCatS (Str->Str, StringSize/sizeof(CHAR16), AppendStr); + Str->Len = StringSize; + + FreePool (AppendStr); + return EFI_SUCCESS; +} + +MTD_NAME mMTDName[] = { + { + MTDTypeUnknown, + L"F" + }, + { + MTDTypeFloppy, + L"FP" + }, + { + MTDTypeHardDisk, + L"HD" + }, + { + MTDTypeCDRom, + L"CD" + }, + { + MTDTypeEnd, + NULL + } +}; + +/** + Function to append a 64 bit number / 25 onto the string. + + @param[in, out] Str The string so append onto. + @param[in] Num The number to divide and append. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +AppendCSDNum2 ( + IN OUT POOL_PRINT *Str, + IN UINT64 Num + ) +{ + EFI_STATUS Status; + UINT64 Result; + UINT32 Rem; + + ASSERT (Str != NULL); + + Result = DivU64x32Remainder (Num, 25, &Rem); + if (Result > 0) { + Status = AppendCSDNum2 (Str, Result); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return CatPrint (Str, L"%c", Rem + 'a'); +} + +/** + Function to append a 64 bit number onto the mapping info. + + @param[in, out] MappingItem The mapping info object to append onto. + @param[in] Num The info to append. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. + +**/ +EFI_STATUS +AppendCSDNum ( + IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN UINT64 Num + ) +{ + EFI_STATUS Status; + ASSERT (MappingItem != NULL); + + if (MappingItem->Digital) { + Status = CatPrint (&MappingItem->Csd, L"%ld", Num); + } else { + Status = AppendCSDNum2 (&MappingItem->Csd, Num); + } + + if (!EFI_ERROR (Status)) { + MappingItem->Digital = (BOOLEAN) !(MappingItem->Digital); + } + + return Status; +} + +/** + Function to append string into the mapping info. + + @param[in, out] MappingItem The mapping info object to append onto. + @param[in] Str The info to append. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +AppendCSDStr ( + IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN CHAR16 *Str + ) +{ + CHAR16 *Index; + EFI_STATUS Status; + + ASSERT (Str != NULL && MappingItem != NULL); + + Status = EFI_SUCCESS; + + if (MappingItem->Digital) { + // + // To aVOID mult-meaning, the mapping is: + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + // 0 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // + for (Index = Str; *Index != 0; Index++) { + switch (*Index) { + case '0': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + Status = CatPrint (&MappingItem->Csd, L"%c", *Index); + break; + + case '1': + Status = CatPrint (&MappingItem->Csd, L"16"); + break; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'a' + '0'); + break; + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'A' + '0'); + break; + } + + if (EFI_ERROR (Status)) { + return Status; + } + } + } else { + for (Index = Str; *Index != 0; Index++) { + // + // The mapping is: + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + // a b c d e f g h i j k l m n o p + // + if (*Index >= '0' && *Index <= '9') { + Status = CatPrint (&MappingItem->Csd, L"%c", *Index - '0' + 'a'); + } else if (*Index >= 'a' && *Index <= 'f') { + Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'a' + 'k'); + } else if (*Index >= 'A' && *Index <= 'F') { + Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'A' + 'k'); + } + + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital); + + return (EFI_SUCCESS); +} + +/** + Function to append a Guid to the mapping item. + + @param[in, out] MappingItem The item to append onto. + @param[in] Guid The guid to append. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +AppendCSDGuid ( + DEVICE_CONSIST_MAPPING_INFO *MappingItem, + EFI_GUID *Guid + ) +{ + CHAR16 Buffer[64]; + + ASSERT (Guid != NULL && MappingItem != NULL); + + UnicodeSPrint ( + Buffer, + 0, + L"%g", + Guid + ); + + return AppendCSDStr (MappingItem, Buffer); +} + +/** + Function to compare 2 APCI device paths. + + @param[in] DevicePath1 The first device path to compare. + @param[in] DevicePath2 The second device path to compare. + + @retval 0 The device paths represent the same device. + @return Non zero if the devices are different, zero otherwise. +**/ +INTN +EFIAPI +DevPathCompareAcpi ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 + ) +{ + ACPI_HID_DEVICE_PATH *Acpi1; + ACPI_HID_DEVICE_PATH *Acpi2; + + if (DevicePath1 == NULL || DevicePath2 == NULL) { + return (-2); + } + + Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1; + Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2; + if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) { + return 1; + } + + if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) { + return 0; + } + + return -1; +} + +/** + Function to compare 2 PCI device paths. + + @param[in] DevicePath1 The first device path to compare. + @param[in] DevicePath2 The second device path to compare. + + @retval 0 The device paths represent the same device. + @return Non zero if the devices are different, zero otherwise. +**/ +INTN +EFIAPI +DevPathComparePci ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 + ) +{ + PCI_DEVICE_PATH *Pci1; + PCI_DEVICE_PATH *Pci2; + + ASSERT(DevicePath1 != NULL); + ASSERT(DevicePath2 != NULL); + + Pci1 = (PCI_DEVICE_PATH *) DevicePath1; + Pci2 = (PCI_DEVICE_PATH *) DevicePath2; + if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) { + return 1; + } + + if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) { + return 0; + } + + return -1; +} + +/** + Do a comparison on 2 device paths. + + @param[in] DevicePath1 The first device path. + @param[in] DevicePath2 The second device path. + + @retval 0 The 2 device paths are the same. + @retval <0 DevicePath2 is greater than DevicePath1. + @retval >0 DevicePath1 is greater than DevicePath2. +**/ +INTN +EFIAPI +DevPathCompareDefault ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 + ) +{ + UINTN DevPathSize1; + UINTN DevPathSize2; + + ASSERT(DevicePath1 != NULL); + ASSERT(DevicePath2 != NULL); + + DevPathSize1 = DevicePathNodeLength (DevicePath1); + DevPathSize2 = DevicePathNodeLength (DevicePath2); + if (DevPathSize1 > DevPathSize2) { + return 1; + } else if (DevPathSize1 < DevPathSize2) { + return -1; + } else { + return CompareMem (DevicePath1, DevicePath2, DevPathSize1); + } +} + +/** + DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialHardDrive ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode; + if (MappingItem->Mtd == MTDTypeUnknown) { + MappingItem->Mtd = MTDTypeHardDisk; + } + + return AppendCSDNum (MappingItem, Hd->PartitionNumber); +} + +/** + DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialAtapi ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode; + return AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster)); +} + +/** + DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialCdRom ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CDROM_DEVICE_PATH *Cd; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Cd = (CDROM_DEVICE_PATH *) DevicePathNode; + MappingItem->Mtd = MTDTypeCDRom; + return AppendCSDNum (MappingItem, Cd->BootEntry); +} + +/** + DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialFibre ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + FIBRECHANNEL_DEVICE_PATH *Fibre; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDNum (MappingItem, Fibre->WWN); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Fibre->Lun); + } + return Status; +} + +/** + DevicePathNode must be SerialUart type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialUart ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + UART_DEVICE_PATH *Uart; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Uart = (UART_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDNum (MappingItem, Uart->BaudRate); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Uart->DataBits); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Uart->Parity); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Uart->StopBits); + } + return Status; +} + +/** + DevicePathNode must be SerialUSB type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialUsb ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + USB_DEVICE_PATH *Usb; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_HANDLE TempHandle; + EFI_STATUS Status; + USB_INTERFACE_DESCRIPTOR InterfaceDesc; + + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Usb = (USB_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDNum (MappingItem, Usb->ParentPortNumber); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Usb->InterfaceNumber); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + if (PcdGetBool(PcdUsbExtendedDecode)) { + Status = gBS->LocateDevicePath( &gEfiUsbIoProtocolGuid, &DevicePath, &TempHandle ); + UsbIo = NULL; + if (!EFI_ERROR(Status)) { + Status = gBS->OpenProtocol(TempHandle, &gEfiUsbIoProtocolGuid, (VOID**)&UsbIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + } + + if (!EFI_ERROR(Status)) { + ASSERT(UsbIo != NULL); + Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc); + if (!EFI_ERROR(Status)) { + if (InterfaceDesc.InterfaceClass == USB_MASS_STORE_CLASS && MappingItem->Mtd == MTDTypeUnknown) { + switch (InterfaceDesc.InterfaceSubClass){ + case USB_MASS_STORE_SCSI: + MappingItem->Mtd = MTDTypeHardDisk; + break; + case USB_MASS_STORE_8070I: + case USB_MASS_STORE_UFI: + MappingItem->Mtd = MTDTypeFloppy; + break; + case USB_MASS_STORE_8020I: + MappingItem->Mtd = MTDTypeCDRom; + break; + } + } + } + } + } + return Status; +} + +/** + DevicePathNode must be SerialVendor type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialVendor ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + VENDOR_DEVICE_PATH *Vendor; + SAS_DEVICE_PATH *Sas; + UINTN TargetNameLength; + UINTN Index; + CHAR16 *Buffer; + CHAR16 *NewBuffer; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDGuid (MappingItem, &Vendor->Guid); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CompareGuid (&gEfiSasDevicePathGuid, &Vendor->Guid)) { + Sas = (SAS_DEVICE_PATH *) Vendor; + Status = AppendCSDNum (MappingItem, Sas->SasAddress); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Sas->Lun); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Sas->DeviceTopology); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Sas->RelativeTargetPort); + } + } else { + TargetNameLength = MIN(DevicePathNodeLength (DevicePathNode) - sizeof (VENDOR_DEVICE_PATH), PcdGet32(PcdShellVendorExtendedDecode)); + if (TargetNameLength != 0) { + // + // String is 2 chars per data byte, plus NULL terminator + // + Buffer = AllocateZeroPool (((TargetNameLength * 2) + 1) * sizeof(CHAR16)); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Build the string data + // + for (Index = 0; Index < TargetNameLength; Index++) { + NewBuffer = CatSPrint (Buffer, L"%02x", *((UINT8*)Vendor + sizeof (VENDOR_DEVICE_PATH) + Index)); + if (NewBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + Buffer = NewBuffer; + } + + // + // Append the new data block + // + if (!EFI_ERROR (Status)) { + Status = AppendCSDStr (MappingItem, Buffer); + } + + FreePool(Buffer); + } + } + return Status; +} + +/** + DevicePathNode must be SerialLun type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialLun ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode; + return AppendCSDNum (MappingItem, Lun->Lun); +} + +/** + DevicePathNode must be SerialSata type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialSata ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + SATA_DEVICE_PATH *Sata; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Sata = (SATA_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDNum (MappingItem, Sata->HBAPortNumber); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Sata->Lun); + } + return Status; +} + +/** + DevicePathNode must be SerialSCSI type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialIScsi ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + ISCSI_DEVICE_PATH *IScsi; + UINT8 *IScsiTargetName; + CHAR16 *TargetName; + UINTN TargetNameLength; + UINTN Index; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Status = EFI_SUCCESS; + + if (PcdGetBool(PcdShellDecodeIScsiMapNames)) { + IScsi = (ISCSI_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDNum (MappingItem, IScsi->NetworkProtocol); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, IScsi->LoginOption); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, IScsi->Lun); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag); + } + if (EFI_ERROR (Status)) { + return Status; + } + TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH); + if (TargetNameLength > 0) { + TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16)); + if (TargetName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + IScsiTargetName = (UINT8 *) (IScsi + 1); + for (Index = 0; Index < TargetNameLength; Index++) { + TargetName[Index] = (CHAR16) IScsiTargetName[Index]; + } + Status = AppendCSDStr (MappingItem, TargetName); + FreePool (TargetName); + } + } + } + return Status; +} + +/** + DevicePathNode must be SerialI20 type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialI2O ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + I2O_DEVICE_PATH *DevicePath_I20; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + DevicePath_I20 = (I2O_DEVICE_PATH *) DevicePathNode; + return AppendCSDNum (MappingItem, DevicePath_I20->Tid); +} + +/** + DevicePathNode must be Mac Address type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialMacAddr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + MAC_ADDR_DEVICE_PATH *Mac; + UINTN HwAddressSize; + UINTN Index; + CHAR16 Buffer[64]; + CHAR16 *PBuffer; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Mac = (MAC_ADDR_DEVICE_PATH *) DevicePathNode; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (Mac->IfType == 0x01 || Mac->IfType == 0x00) { + HwAddressSize = 6; + } + + for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) { + UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]); + } + + return AppendCSDStr (MappingItem, Buffer); +} + +/** + DevicePathNode must be InfiniBand type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialInfiniBand ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + INFINIBAND_DEVICE_PATH *InfiniBand; + UINTN Index; + CHAR16 Buffer[64]; + CHAR16 *PBuffer; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode; + for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { + UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]); + } + + Status = AppendCSDStr (MappingItem, Buffer); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, InfiniBand->ServiceId); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, InfiniBand->TargetPortId); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, InfiniBand->DeviceId); + } + return Status; +} + +/** + DevicePathNode must be IPv4 type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialIPv4 ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + IPv4_DEVICE_PATH *Ip; + CHAR16 Buffer[10]; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Ip = (IPv4_DEVICE_PATH *) DevicePathNode; + UnicodeSPrint ( + Buffer, + 0, + L"%02x%02x%02x%02x", + (UINTN) Ip->LocalIpAddress.Addr[0], + (UINTN) Ip->LocalIpAddress.Addr[1], + (UINTN) Ip->LocalIpAddress.Addr[2], + (UINTN) Ip->LocalIpAddress.Addr[3] + ); + Status = AppendCSDStr (MappingItem, Buffer); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Ip->LocalPort); + } + if (!EFI_ERROR (Status)) { + UnicodeSPrint ( + Buffer, + 0, + L"%02x%02x%02x%02x", + (UINTN) Ip->RemoteIpAddress.Addr[0], + (UINTN) Ip->RemoteIpAddress.Addr[1], + (UINTN) Ip->RemoteIpAddress.Addr[2], + (UINTN) Ip->RemoteIpAddress.Addr[3] + ); + Status = AppendCSDStr (MappingItem, Buffer); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Ip->RemotePort); + } + return Status; +} + +/** + DevicePathNode must be IPv6 type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialIPv6 ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + IPv6_DEVICE_PATH *Ip; + UINTN Index; + CHAR16 Buffer[64]; + CHAR16 *PBuffer; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Ip = (IPv6_DEVICE_PATH *) DevicePathNode; + for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { + UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]); + } + + Status = AppendCSDStr (MappingItem, Buffer); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Ip->LocalPort); + } + if (!EFI_ERROR (Status)) { + for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) { + UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]); + } + + Status = AppendCSDStr (MappingItem, Buffer); + } + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Ip->RemotePort); + } + return Status; +} + +/** + DevicePathNode must be SCSI type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialScsi ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + SCSI_DEVICE_PATH *Scsi; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Scsi = (SCSI_DEVICE_PATH *) DevicePathNode; + Status = AppendCSDNum (MappingItem, Scsi->Pun); + if (!EFI_ERROR (Status)) { + Status = AppendCSDNum (MappingItem, Scsi->Lun); + } + return Status; +} + +/** + DevicePathNode must be 1394 type and this will populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerial1394 ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + F1394_DEVICE_PATH *DevicePath_F1394; + CHAR16 Buffer[20]; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + DevicePath_F1394 = (F1394_DEVICE_PATH *) DevicePathNode; + UnicodeSPrint (Buffer, 0, L"%lx", DevicePath_F1394->Guid); + return AppendCSDStr (MappingItem, Buffer); +} + +/** + If the node is floppy type then populate the MappingItem. + + @param[in] DevicePathNode The node to get info on. + @param[in] MappingItem The info item to populate. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialAcpi ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + ASSERT(DevicePathNode != NULL); + ASSERT(MappingItem != NULL); + + Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { + MappingItem->Mtd = MTDTypeFloppy; + return AppendCSDNum (MappingItem, Acpi->UID); + } + } + return EFI_SUCCESS; +} + +/** + Empty function used for unknown devices. + + @param[in] DevicePathNode Ignored. + @param[in] MappingItem Ignored. + @param[in] DevicePath Ignored. + + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_SUCCESS The appending was successful. +**/ +EFI_STATUS +DevPathSerialDefault ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return EFI_SUCCESS; +} + +DEV_PATH_CONSIST_MAPPING_TABLE DevPathConsistMappingTable[] = { + { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + DevPathSerialDefault, + DevPathComparePci + }, + { + ACPI_DEVICE_PATH, + ACPI_DP, + DevPathSerialAcpi, + DevPathCompareAcpi + }, + { + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + DevPathSerialAtapi, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + DevPathSerialScsi, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + DevPathSerialFibre, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + DevPathSerial1394, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + DevPathSerialUsb, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + DevPathSerialI2O, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + DevPathSerialMacAddr, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + DevPathSerialIPv4, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + DevPathSerialIPv6, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + DevPathSerialInfiniBand, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + DevPathSerialUart, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + DevPathSerialVendor, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + DevPathSerialLun, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_SATA_DP, + DevPathSerialSata, + DevPathCompareDefault + }, + { + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + DevPathSerialIScsi, + DevPathCompareDefault + }, + { + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + DevPathSerialHardDrive, + DevPathCompareDefault + }, + { + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + DevPathSerialCdRom, + DevPathCompareDefault + }, + { + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP, + DevPathSerialVendor, + DevPathCompareDefault + }, + { + 0, + 0, + NULL, + NULL + } +}; + +/** + Function to determine if a device path node is Hi or not. + + @param[in] DevicePathNode The node to check. + + @retval TRUE The node is Hi. + @retval FALSE The node is not Hi. +**/ +BOOLEAN +IsHIDevicePathNode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + ASSERT(DevicePathNode != NULL); + + if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) { + return TRUE; + } + + if (DevicePathNode->Type == ACPI_DEVICE_PATH) { + Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode; + switch (EISA_ID_TO_NUM (Acpi->HID)) { + case 0x0301: + case 0x0401: + case 0x0501: + case 0x0604: + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + +/** + Function to convert a standard device path structure into a Hi version. + + @param[in] DevicePath The device path to convert. + + @return the device path portion that is Hi. +**/ +EFI_DEVICE_PATH_PROTOCOL * +GetHIDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN NonHIDevicePathNodeCount; + UINTN Index; + EFI_DEV_PATH Node; + EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + + ASSERT(DevicePath != NULL); + + NonHIDevicePathNodeCount = 0; + + HIDevicePath = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL)); + SetDevicePathEndNode (HIDevicePath); + + Node.DevPath.Type = END_DEVICE_PATH_TYPE; + Node.DevPath.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + Node.DevPath.Length[0] = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL); + Node.DevPath.Length[1] = 0; + + while (!IsDevicePathEnd (DevicePath)) { + if (IsHIDevicePathNode (DevicePath)) { + for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) { + TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath); + FreePool (HIDevicePath); + HIDevicePath = TempDevicePath; + } + + TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath); + FreePool (HIDevicePath); + HIDevicePath = TempDevicePath; + } else { + NonHIDevicePathNodeCount++; + } + // + // Next device path node + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); + } + + return HIDevicePath; +} + +/** + Function to walk the device path looking for a dumpable node. + + @param[in] MappingItem The Item to fill with data. + @param[in] DevicePath The path of the item to get data on. + + @return EFI_SUCCESS Always returns success. +**/ +EFI_STATUS +GetDeviceConsistMappingInfo ( + IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + SERIAL_DECODE_FUNCTION SerialFun; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *OriginalDevicePath; + + ASSERT(DevicePath != NULL); + ASSERT(MappingItem != NULL); + + SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0); + OriginalDevicePath = DevicePath; + + while (!IsDevicePathEnd (DevicePath)) { + // + // Find the handler to dump this device path node and + // initialize with generic function in case nothing is found + // + for (SerialFun = DevPathSerialDefault, Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) { + + if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type && + DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType + ) { + SerialFun = DevPathConsistMappingTable[Index].SerialFun; + break; + } + } + + Status = SerialFun (DevicePath, MappingItem, OriginalDevicePath); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (MappingItem->Csd.Str); + return Status; + } + + // + // Next device path node + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); + } + + return EFI_SUCCESS; +} + +/** + Function to initialize the table for creating consistent map names. + + @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object. + + @retval EFI_SUCCESS The table was created successfully. +**/ +EFI_STATUS +EFIAPI +ShellCommandConsistMappingInitialize ( + OUT EFI_DEVICE_PATH_PROTOCOL ***Table + ) +{ + EFI_HANDLE *HandleBuffer; + UINTN HandleNum; + UINTN HandleLoop; + EFI_DEVICE_PATH_PROTOCOL **TempTable; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + UINTN Index; + EFI_STATUS Status; + + HandleBuffer = NULL; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + ASSERT_EFI_ERROR(Status); + + TempTable = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *)); + if (TempTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) { + DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]); + if (DevicePath == NULL) { + continue; + } + + HIDevicePath = GetHIDevicePath (DevicePath); + if (HIDevicePath == NULL) { + continue; + } + + Status = gBS->HandleProtocol( HandleBuffer[HandleLoop], + &gEfiBlockIoProtocolGuid, + (VOID **)&BlockIo + ); + if (EFI_ERROR(Status)) { + Status = gBS->HandleProtocol( HandleBuffer[HandleLoop], + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&SimpleFileSystem + ); + if (EFI_ERROR(Status)) { + FreePool (HIDevicePath); + continue; + } + } + + for (Index = 0; TempTable[Index] != NULL; Index++) { + if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) { + FreePool (HIDevicePath); + break; + } + } + + if (TempTable[Index] == NULL) { + TempTable[Index] = HIDevicePath; + } + } + + for (Index = 0; TempTable[Index] != NULL; Index++); + PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); + *Table = TempTable; + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + Function to uninitialize the table for creating consistent map names. + + The parameter must have been received from ShellCommandConsistMappingInitialize. + + @param[out] Table The pointer to pointer to DevicePathProtocol object. + + @retval EFI_SUCCESS The table was deleted successfully. +**/ +EFI_STATUS +EFIAPI +ShellCommandConsistMappingUnInitialize ( + EFI_DEVICE_PATH_PROTOCOL **Table + ) +{ + UINTN Index; + + ASSERT(Table != NULL); + + for (Index = 0; Table[Index] != NULL; Index++) { + FreePool (Table[Index]); + } + + FreePool (Table); + return EFI_SUCCESS; +} + +/** + Create a consistent mapped name for the device specified by DevicePath + based on the Table. + + This must be called after ShellCommandConsistMappingInitialize() and + before ShellCommandConsistMappingUnInitialize() is called. + + @param[in] DevicePath The pointer to the dev path for the device. + @param[in] Table The Table of mapping information. + + @retval NULL A consistent mapped name could not be created. + @return A pointer to a string allocated from pool with the device name. +**/ +CHAR16 * +EFIAPI +ShellCommandConsistMappingGenMappingName ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_DEVICE_PATH_PROTOCOL **Table + ) +{ + EFI_STATUS Status; + POOL_PRINT Str; + DEVICE_CONSIST_MAPPING_INFO MappingInfo; + EFI_DEVICE_PATH_PROTOCOL *HIDevicePath; + UINTN Index; + + ASSERT(DevicePath != NULL); + ASSERT(Table != NULL); + + HIDevicePath = GetHIDevicePath (DevicePath); + if (HIDevicePath == NULL) { + return NULL; + } + + for (Index = 0; Table[Index] != NULL; Index++) { + if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) { + break; + } + } + + FreePool (HIDevicePath); + if (Table[Index] == NULL) { + return NULL; + } + + MappingInfo.Hi = Index; + MappingInfo.Mtd = MTDTypeUnknown; + MappingInfo.Digital = FALSE; + + Status = GetDeviceConsistMappingInfo (&MappingInfo, DevicePath); + if (EFI_ERROR (Status)) { + return NULL; + } + + SetMem (&Str, sizeof (Str), 0); + for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) { + if (MappingInfo.Mtd == mMTDName[Index].MTDType) { + break; + } + } + + if (mMTDName[Index].MTDType != MTDTypeEnd) { + Status = CatPrint (&Str, L"%s", mMTDName[Index].Name); + } + + if (!EFI_ERROR (Status)) { + Status = CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi); + } + if (!EFI_ERROR (Status) && MappingInfo.Csd.Str != NULL) { + Status = CatPrint (&Str, L"%s", MappingInfo.Csd.Str); + FreePool (MappingInfo.Csd.Str); + } + + if (!EFI_ERROR (Status) && Str.Str != NULL) { + Status = CatPrint (&Str, L":"); + } + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (Str.Str); + return NULL; + } + + return Str.Str; +} + +/** + Function to search the list of mappings for the node on the list based on the key. + + @param[in] MapKey String Key to search for on the map + + @return the node on the list. +**/ +SHELL_MAP_LIST * +EFIAPI +ShellCommandFindMapItem ( + IN CONST CHAR16 *MapKey + ) +{ + SHELL_MAP_LIST *MapListItem; + + for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsNull(&gShellMapList.Link, &MapListItem->Link) + ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link) + ){ + if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) { + return (MapListItem); + } + } + return (NULL); +} + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c new file mode 100644 index 0000000..5ad1ac7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c @@ -0,0 +1,1905 @@ +/** @file + Provides interface to shell internal functions for shell commands. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellCommandLib.h" + +// STATIC local variables +STATIC SHELL_COMMAND_INTERNAL_LIST_ENTRY mCommandList; +STATIC SCRIPT_FILE_LIST mScriptList; +STATIC ALIAS_LIST mAliasList; +STATIC BOOLEAN mEchoState; +STATIC BOOLEAN mExitRequested; +STATIC UINT64 mExitCode; +STATIC BOOLEAN mExitScript; +STATIC CHAR16 *mProfileList; +STATIC UINTN mProfileListSize; +STATIC UINTN mFsMaxCount = 0; +STATIC UINTN mBlkMaxCount = 0; +STATIC BUFFER_LIST mFileHandleList; + +STATIC CONST CHAR8 Hex[] = { + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F' +}; + +// global variables required by library class. +EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation = NULL; +SHELL_MAP_LIST gShellMapList; +SHELL_MAP_LIST *gShellCurMapping = NULL; + +CONST CHAR16* SupportLevel[] = { + L"Minimal", + L"Scripting", + L"Basic", + L"Interactive" +}; + +/** + Function to make sure that the global protocol pointers are valid. + must be called after constructor before accessing the pointers. +**/ +EFI_STATUS +EFIAPI +CommandInit( + VOID + ) +{ + UINTN NumHandles; + EFI_HANDLE *Handles; + EFI_UNICODE_COLLATION_PROTOCOL *Uc; + CHAR8 *BestLanguage; + UINTN Index; + EFI_STATUS Status; + CHAR8 *PlatformLang; + + GetEfiGlobalVariable2 (EFI_PLATFORM_LANG_VARIABLE_NAME, (VOID**)&PlatformLang, NULL); + if (PlatformLang == NULL) { + return EFI_UNSUPPORTED; + } + + if (gUnicodeCollation == NULL) { + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUnicodeCollation2ProtocolGuid, + NULL, + &NumHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + NumHandles = 0; + Handles = NULL; + } + for (Index = 0; Index < NumHandles; Index++) { + // + // Open Unicode Collation Protocol + // + Status = gBS->OpenProtocol ( + Handles[Index], + &gEfiUnicodeCollation2ProtocolGuid, + (VOID **) &Uc, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Find the best matching matching language from the supported languages + // of Unicode Collation2 protocol. + // + BestLanguage = GetBestLanguage ( + Uc->SupportedLanguages, + FALSE, + PlatformLang, + NULL + ); + if (BestLanguage != NULL) { + FreePool (BestLanguage); + gUnicodeCollation = Uc; + break; + } + } + if (Handles != NULL) { + FreePool (Handles); + } + FreePool (PlatformLang); + } + + return (gUnicodeCollation == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS; +} + +/** + Constructor for the Shell Command library. + + Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the initialization was complete sucessfully +**/ +RETURN_STATUS +EFIAPI +ShellCommandLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + InitializeListHead(&gShellMapList.Link); + InitializeListHead(&mCommandList.Link); + InitializeListHead(&mAliasList.Link); + InitializeListHead(&mScriptList.Link); + InitializeListHead(&mFileHandleList.Link); + mEchoState = TRUE; + + mExitRequested = FALSE; + mExitScript = FALSE; + mProfileListSize = 0; + mProfileList = NULL; + + Status = CommandInit (); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return (RETURN_SUCCESS); +} + +/** + Frees list of file handles. + + @param[in] List The list to free. +**/ +VOID +FreeFileHandleList ( + IN BUFFER_LIST *List + ) +{ + BUFFER_LIST *BufferListEntry; + + if (List == NULL){ + return; + } + // + // enumerate through the buffer list and free all memory + // + for ( BufferListEntry = ( BUFFER_LIST *)GetFirstNode(&List->Link) + ; !IsListEmpty (&List->Link) + ; BufferListEntry = (BUFFER_LIST *)GetFirstNode(&List->Link) + ){ + RemoveEntryList(&BufferListEntry->Link); + ASSERT(BufferListEntry->Buffer != NULL); + SHELL_FREE_NON_NULL(((SHELL_COMMAND_FILE_HANDLE*)(BufferListEntry->Buffer))->Path); + SHELL_FREE_NON_NULL(BufferListEntry->Buffer); + SHELL_FREE_NON_NULL(BufferListEntry); + } +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval RETURN_SUCCESS this function always returns success +**/ +RETURN_STATUS +EFIAPI +ShellCommandLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node; + ALIAS_LIST *Node2; + SCRIPT_FILE_LIST *Node3; + SHELL_MAP_LIST *MapNode; + // + // enumerate throught the list and free all the memory + // + while (!IsListEmpty (&mCommandList.Link)) { + Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link); + RemoveEntryList(&Node->Link); + SHELL_FREE_NON_NULL(Node->CommandString); + FreePool(Node); + DEBUG_CODE(Node = NULL;); + } + + // + // enumerate through the alias list and free all memory + // + while (!IsListEmpty (&mAliasList.Link)) { + Node2 = (ALIAS_LIST *)GetFirstNode(&mAliasList.Link); + RemoveEntryList(&Node2->Link); + SHELL_FREE_NON_NULL(Node2->CommandString); + SHELL_FREE_NON_NULL(Node2->Alias); + SHELL_FREE_NON_NULL(Node2); + DEBUG_CODE(Node2 = NULL;); + } + + // + // enumerate throught the list and free all the memory + // + while (!IsListEmpty (&mScriptList.Link)) { + Node3 = (SCRIPT_FILE_LIST *)GetFirstNode(&mScriptList.Link); + RemoveEntryList(&Node3->Link); + DeleteScriptFileStruct(Node3->Data); + FreePool(Node3); + } + + // + // enumerate throught the mappings list and free all the memory + // + if (!IsListEmpty(&gShellMapList.Link)) { + for (MapNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsListEmpty (&gShellMapList.Link) + ; MapNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ){ + ASSERT(MapNode != NULL); + RemoveEntryList(&MapNode->Link); + SHELL_FREE_NON_NULL(MapNode->DevicePath); + SHELL_FREE_NON_NULL(MapNode->MapName); + SHELL_FREE_NON_NULL(MapNode->CurrentDirectoryPath); + FreePool(MapNode); + } + } + if (!IsListEmpty(&mFileHandleList.Link)){ + FreeFileHandleList(&mFileHandleList); + } + + if (mProfileList != NULL) { + FreePool(mProfileList); + } + + gUnicodeCollation = NULL; + gShellCurMapping = NULL; + + return (RETURN_SUCCESS); +} + +/** + Find a dynamic command protocol instance given a command name string. + + @param CommandString the command name string + + @return instance the command protocol instance, if dynamic command instance found + @retval NULL no dynamic command protocol instance found for name +**/ +CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL * +ShellCommandFindDynamicCommand ( + IN CONST CHAR16 *CommandString + ) +{ + EFI_STATUS Status; + EFI_HANDLE *CommandHandleList; + EFI_HANDLE *NextCommand; + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand; + + CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid); + if (CommandHandleList == NULL) { + // + // not found or out of resources + // + return NULL; + } + + for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) { + Status = gBS->HandleProtocol( + *NextCommand, + &gEfiShellDynamicCommandProtocolGuid, + (VOID **)&DynamicCommand + ); + + if (EFI_ERROR(Status)) { + continue; + } + + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandString, + (CHAR16*)DynamicCommand->CommandName) == 0 + ){ + FreePool(CommandHandleList); + return (DynamicCommand); + } + } + + FreePool(CommandHandleList); + return (NULL); +} + +/** + Checks if a command exists as a dynamic command protocol instance + + @param[in] CommandString The command string to check for on the list. +**/ +BOOLEAN +ShellCommandDynamicCommandExists ( + IN CONST CHAR16 *CommandString + ) +{ + return (BOOLEAN) ((ShellCommandFindDynamicCommand(CommandString) != NULL)); +} + +/** + Checks if a command is already on the internal command list. + + @param[in] CommandString The command string to check for on the list. +**/ +BOOLEAN +ShellCommandIsCommandOnInternalList( + IN CONST CHAR16 *CommandString + ) +{ + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node; + + // + // assert for NULL parameter + // + ASSERT(CommandString != NULL); + + // + // check for the command + // + for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link) + ; !IsNull(&mCommandList.Link, &Node->Link) + ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandString, + Node->CommandString) == 0 + ){ + return (TRUE); + } + } + return (FALSE); +} + +/** + Checks if a command exists, either internally or through the dynamic command protocol. + + @param[in] CommandString The command string to check for on the list. +**/ +BOOLEAN +EFIAPI +ShellCommandIsCommandOnList( + IN CONST CHAR16 *CommandString + ) +{ + if (ShellCommandIsCommandOnInternalList(CommandString)) { + return TRUE; + } + + return ShellCommandDynamicCommandExists(CommandString); +} + +/** + Get the help text for a dynamic command. + + @param[in] CommandString The command name. + + @retval NULL No help text was found. + @return String of help text. Caller required to free. +**/ +CHAR16* +ShellCommandGetDynamicCommandHelp( + IN CONST CHAR16 *CommandString + ) +{ + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand; + + DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand(CommandString); + if (DynamicCommand == NULL) { + return (NULL); + } + + // + // TODO: how to get proper language? + // + return DynamicCommand->GetHelp(DynamicCommand, "en"); +} + +/** + Get the help text for an internal command. + + @param[in] CommandString The command name. + + @retval NULL No help text was found. + @return String of help text. Caller reuiqred to free. +**/ +CHAR16* +ShellCommandGetInternalCommandHelp( + IN CONST CHAR16 *CommandString + ) +{ + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node; + + // + // assert for NULL parameter + // + ASSERT(CommandString != NULL); + + // + // check for the command + // + for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link) + ; !IsNull(&mCommandList.Link, &Node->Link) + ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandString, + Node->CommandString) == 0 + ){ + return (HiiGetString(Node->HiiHandle, Node->ManFormatHelp, NULL)); + } + } + return (NULL); +} + +/** + Get the help text for a command. + + @param[in] CommandString The command name. + + @retval NULL No help text was found. + @return String of help text.Caller reuiqred to free. +**/ +CHAR16* +EFIAPI +ShellCommandGetCommandHelp ( + IN CONST CHAR16 *CommandString + ) +{ + CHAR16 *HelpStr; + HelpStr = ShellCommandGetInternalCommandHelp(CommandString); + + if (HelpStr == NULL) { + HelpStr = ShellCommandGetDynamicCommandHelp(CommandString); + } + + return HelpStr; +} + + +/** + Registers handlers of type SHELL_RUN_COMMAND and + SHELL_GET_MAN_FILENAME for each shell command. + + If the ShellSupportLevel is greater than the value of the + PcdShellSupportLevel then return RETURN_UNSUPPORTED. + + Registers the handlers specified by GetHelpInfoHandler and CommandHandler + with the command specified by CommandString. If the command named by + CommandString 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 CommandString is NULL, then ASSERT(). + If GetHelpInfoHandler is NULL, then ASSERT(). + If CommandHandler is NULL, then ASSERT(). + If ProfileName is NULL, then ASSERT(). + + @param[in] CommandString Pointer to the command name. This is the + name to look for on the command line in + the shell. + @param[in] CommandHandler Pointer to a function that runs the + specified command. + @param[in] GetManFileName Pointer to a function that provides man + filename. + @param[in] ShellMinSupportLevel minimum Shell Support Level which has this + function. + @param[in] ProfileName profile name to require for support of this + function. + @param[in] CanAffectLE indicates whether this command's return value + can change the LASTERROR environment variable. + @param[in] HiiHandle Handle of this command's HII entry. + @param[in] ManFormatHelp HII locator for the help text. + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + register the shell command. + @retval RETURN_UNSUPPORTED the ShellMinSupportLevel was higher than the + currently allowed support level. + @retval RETURN_ALREADY_STARTED The CommandString represents a command that + is already registered. Only 1 handler set for + a given command is allowed. + @sa SHELL_GET_MAN_FILENAME + @sa SHELL_RUN_COMMAND +**/ +RETURN_STATUS +EFIAPI +ShellCommandRegisterCommandName ( + IN CONST CHAR16 *CommandString, + IN SHELL_RUN_COMMAND CommandHandler, + IN SHELL_GET_MAN_FILENAME GetManFileName, + IN UINT32 ShellMinSupportLevel, + IN CONST CHAR16 *ProfileName, + IN CONST BOOLEAN CanAffectLE, + IN CONST EFI_HANDLE HiiHandle, + IN CONST EFI_STRING_ID ManFormatHelp + ) +{ + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node; + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Command; + SHELL_COMMAND_INTERNAL_LIST_ENTRY *PrevCommand; + INTN LexicalMatchValue; + + // + // Initialize local variables. + // + Command = NULL; + PrevCommand = NULL; + LexicalMatchValue = 0; + + // + // ASSERTs for NULL parameters + // + ASSERT(CommandString != NULL); + ASSERT(GetManFileName != NULL); + ASSERT(CommandHandler != NULL); + ASSERT(ProfileName != NULL); + + // + // check for shell support level + // + if (PcdGet8(PcdShellSupportLevel) < ShellMinSupportLevel) { + return (RETURN_UNSUPPORTED); + } + + // + // check for already on the list + // + if (ShellCommandIsCommandOnList(CommandString)) { + return (RETURN_ALREADY_STARTED); + } + + // + // allocate memory for new struct + // + Node = AllocateZeroPool(sizeof(SHELL_COMMAND_INTERNAL_LIST_ENTRY)); + if (Node == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + Node->CommandString = AllocateCopyPool(StrSize(CommandString), CommandString); + if (Node->CommandString == NULL) { + FreePool (Node); + return RETURN_OUT_OF_RESOURCES; + } + + Node->GetManFileName = GetManFileName; + Node->CommandHandler = CommandHandler; + Node->LastError = CanAffectLE; + Node->HiiHandle = HiiHandle; + Node->ManFormatHelp = ManFormatHelp; + + if ( StrLen(ProfileName)>0 + && ((mProfileList != NULL + && StrStr(mProfileList, ProfileName) == NULL) || mProfileList == NULL) + ){ + ASSERT((mProfileList == NULL && mProfileListSize == 0) || (mProfileList != NULL)); + if (mProfileList == NULL) { + // + // If this is the first make a leading ';' + // + StrnCatGrow(&mProfileList, &mProfileListSize, L";", 0); + } + StrnCatGrow(&mProfileList, &mProfileListSize, ProfileName, 0); + StrnCatGrow(&mProfileList, &mProfileListSize, L";", 0); + } + + // + // Insert a new entry on top of the list + // + InsertHeadList (&mCommandList.Link, &Node->Link); + + // + // Move a new registered command to its sorted ordered location in the list + // + for (Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link), + PrevCommand = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link) + ; !IsNull (&mCommandList.Link, &Command->Link) + ; Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Command->Link)) { + + // + // Get Lexical Comparison Value between PrevCommand and Command list entry + // + LexicalMatchValue = gUnicodeCollation->StriColl ( + gUnicodeCollation, + PrevCommand->CommandString, + Command->CommandString + ); + + // + // Swap PrevCommand and Command list entry if PrevCommand list entry + // is alphabetically greater than Command list entry + // + if (LexicalMatchValue > 0){ + Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *) SwapListEntries (&PrevCommand->Link, &Command->Link); + } else if (LexicalMatchValue < 0) { + // + // PrevCommand entry is lexically lower than Command entry + // + break; + } + } + + return (RETURN_SUCCESS); +} + +/** + Function to get the current Profile string. + + @retval NULL There are no installed profiles. + @return A semi-colon delimited list of profiles. +**/ +CONST CHAR16 * +EFIAPI +ShellCommandGetProfileList ( + VOID + ) +{ + return (mProfileList); +} + +/** + Checks if a command string has been registered for CommandString and if so it runs + the previously registered handler for that command with the command line. + + If CommandString is NULL, then ASSERT(). + + If Sections is specified, then each section name listed will be compared in a casesensitive + manner, to the section names described in Appendix B UEFI Shell 2.0 spec. If the section exists, + it will be appended to the returned help text. If the section does not exist, no + information will be returned. If Sections is NULL, then all help text information + available will be returned. + + @param[in] CommandString Pointer to the command name. This is the name + found on the command line in the shell. + @param[in, out] RetVal Pointer to the return vaule from the command handler. + + @param[in, out] CanAffectLE indicates whether this command's return value + needs to be placed into LASTERROR environment variable. + + @retval RETURN_SUCCESS The handler was run. + @retval RETURN_NOT_FOUND The CommandString did not match a registered + command name. + @sa SHELL_RUN_COMMAND +**/ +RETURN_STATUS +EFIAPI +ShellCommandRunCommandHandler ( + IN CONST CHAR16 *CommandString, + IN OUT SHELL_STATUS *RetVal, + IN OUT BOOLEAN *CanAffectLE OPTIONAL + ) +{ + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node; + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand; + + // + // assert for NULL parameters + // + ASSERT(CommandString != NULL); + + // + // check for the command + // + for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link) + ; !IsNull(&mCommandList.Link, &Node->Link) + ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandString, + Node->CommandString) == 0 + ){ + if (CanAffectLE != NULL) { + *CanAffectLE = Node->LastError; + } + if (RetVal != NULL) { + *RetVal = Node->CommandHandler(NULL, gST); + } else { + Node->CommandHandler(NULL, gST); + } + return (RETURN_SUCCESS); + } + } + + // + // An internal command was not found, try to find a dynamic command + // + DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand(CommandString); + if (DynamicCommand != NULL) { + if (RetVal != NULL) { + *RetVal = DynamicCommand->Handler(DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol); + } else { + DynamicCommand->Handler(DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol); + } + return (RETURN_SUCCESS); + } + + return (RETURN_NOT_FOUND); +} + +/** + Checks if a command string has been registered for CommandString and if so it + returns the MAN filename specified for that command. + + If CommandString is NULL, then ASSERT(). + + @param[in] CommandString Pointer to the command name. This is the name + found on the command line in the shell.\ + + @retval NULL the commandString was not a registered command. + @return other the name of the MAN file. + @sa SHELL_GET_MAN_FILENAME +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameHandler ( + IN CONST CHAR16 *CommandString + ) +{ + SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node; + + // + // assert for NULL parameters + // + ASSERT(CommandString != NULL); + + // + // check for the command + // + for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link) + ; !IsNull(&mCommandList.Link, &Node->Link) + ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandString, + Node->CommandString) == 0 + ){ + return (Node->GetManFileName()); + } + } + return (NULL); +} + +/** + Get the list of all available shell internal commands. This is a linked list + (via LIST_ENTRY structure). enumerate through it using the BaseLib linked + list functions. do not modify the values. + + @param[in] Sort TRUE to alphabetically sort the values first. FALSE otherwise. + + @return a Linked list of all available shell commands. +**/ +CONST COMMAND_LIST* +EFIAPI +ShellCommandGetCommandList ( + IN CONST BOOLEAN Sort + ) +{ +// if (!Sort) { +// return ((COMMAND_LIST*)(&mCommandList)); +// } + return ((COMMAND_LIST*)(&mCommandList)); +} + +/** + Registers aliases to be set as part of the initialization of the shell application. + + If Command is NULL, then ASSERT(). + If Alias is NULL, then ASSERT(). + + @param[in] Command Pointer to the Command + @param[in] Alias Pointer to Alias + + @retval RETURN_SUCCESS The handlers were registered. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to + register the shell command. +**/ +RETURN_STATUS +EFIAPI +ShellCommandRegisterAlias ( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias + ) +{ + ALIAS_LIST *Node; + ALIAS_LIST *CommandAlias; + ALIAS_LIST *PrevCommandAlias; + INTN LexicalMatchValue; + + // + // Asserts for NULL + // + ASSERT(Command != NULL); + ASSERT(Alias != NULL); + + // + // allocate memory for new struct + // + Node = AllocateZeroPool(sizeof(ALIAS_LIST)); + if (Node == NULL) { + return RETURN_OUT_OF_RESOURCES; + } + Node->CommandString = AllocateCopyPool(StrSize(Command), Command); + if (Node->CommandString == NULL) { + FreePool (Node); + return RETURN_OUT_OF_RESOURCES; + } + Node->Alias = AllocateCopyPool(StrSize(Alias), Alias); + if (Node->Alias == NULL) { + FreePool (Node->CommandString); + FreePool (Node); + return RETURN_OUT_OF_RESOURCES; + } + + InsertHeadList (&mAliasList.Link, &Node->Link); + + // + // Move a new pre-defined registered alias to its sorted ordered location in the list + // + for ( CommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link), + PrevCommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link) + ; !IsNull (&mAliasList.Link, &CommandAlias->Link) + ; CommandAlias = (ALIAS_LIST *) GetNextNode (&mAliasList.Link, &CommandAlias->Link) ) { + // + // Get Lexical comparison value between PrevCommandAlias and CommandAlias List Entry + // + LexicalMatchValue = gUnicodeCollation->StriColl ( + gUnicodeCollation, + PrevCommandAlias->Alias, + CommandAlias->Alias + ); + + // + // Swap PrevCommandAlias and CommandAlias list entry if PrevCommandAlias list entry + // is alphabetically greater than CommandAlias list entry + // + if (LexicalMatchValue > 0) { + CommandAlias = (ALIAS_LIST *) SwapListEntries (&PrevCommandAlias->Link, &CommandAlias->Link); + } else if (LexicalMatchValue < 0) { + // + // PrevCommandAlias entry is lexically lower than CommandAlias entry + // + break; + } + } + + return (RETURN_SUCCESS); +} + +/** + Get the list of all shell alias commands. This is a linked list + (via LIST_ENTRY structure). enumerate through it using the BaseLib linked + list functions. do not modify the values. + + @return a Linked list of all requested shell alias'. +**/ +CONST ALIAS_LIST* +EFIAPI +ShellCommandGetInitAliasList ( + VOID + ) +{ + return (&mAliasList); +} + +/** + Determine if a given alias is on the list of built in alias'. + + @param[in] Alias The alias to test for + + @retval TRUE The alias is a built in alias + @retval FALSE The alias is not a built in alias +**/ +BOOLEAN +EFIAPI +ShellCommandIsOnAliasList( + IN CONST CHAR16 *Alias + ) +{ + ALIAS_LIST *Node; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(&mAliasList.Link) + ; !IsNull(&mAliasList.Link, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(&mAliasList.Link, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)Alias, + Node->CommandString) == 0 + ){ + return (TRUE); + } + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)Alias, + Node->Alias) == 0 + ){ + return (TRUE); + } + } + return (FALSE); +} + +/** + Function to determine current state of ECHO. Echo determines if lines from scripts + and ECHO commands are enabled. + + @retval TRUE Echo is currently enabled + @retval FALSE Echo is currently disabled +**/ +BOOLEAN +EFIAPI +ShellCommandGetEchoState( + VOID + ) +{ + return (mEchoState); +} + +/** + Function to set current state of ECHO. Echo determines if lines from scripts + and ECHO commands are enabled. + + If State is TRUE, Echo will be enabled. + If State is FALSE, Echo will be disabled. + + @param[in] State How to set echo. +**/ +VOID +EFIAPI +ShellCommandSetEchoState( + IN BOOLEAN State + ) +{ + mEchoState = State; +} + +/** + Indicate that the current shell or script should exit. + + @param[in] ScriptOnly TRUE if exiting a script; FALSE otherwise. + @param[in] ErrorCode The 64 bit error code to return. +**/ +VOID +EFIAPI +ShellCommandRegisterExit ( + IN BOOLEAN ScriptOnly, + IN CONST UINT64 ErrorCode + ) +{ + mExitRequested = (BOOLEAN)(!mExitRequested); + if (mExitRequested) { + mExitScript = ScriptOnly; + } else { + mExitScript = FALSE; + } + mExitCode = ErrorCode; +} + +/** + Retrieve the Exit indicator. + + @retval TRUE Exit was indicated. + @retval FALSE Exis was not indicated. +**/ +BOOLEAN +EFIAPI +ShellCommandGetExit ( + VOID + ) +{ + return (mExitRequested); +} + +/** + Retrieve the Exit code. + + If ShellCommandGetExit returns FALSE than the return from this is undefined. + + @return the value passed into RegisterExit. +**/ +UINT64 +EFIAPI +ShellCommandGetExitCode ( + VOID + ) +{ + return (mExitCode); +} +/** + Retrieve the Exit script indicator. + + If ShellCommandGetExit returns FALSE than the return from this is undefined. + + @retval TRUE ScriptOnly was indicated. + @retval FALSE ScriptOnly was not indicated. +**/ +BOOLEAN +EFIAPI +ShellCommandGetScriptExit ( + VOID + ) +{ + return (mExitScript); +} + +/** + Function to cleanup all memory from a SCRIPT_FILE structure. + + @param[in] Script The pointer to the structure to cleanup. +**/ +VOID +EFIAPI +DeleteScriptFileStruct ( + IN SCRIPT_FILE *Script + ) +{ + UINT8 LoopVar; + + if (Script == NULL) { + return; + } + + for (LoopVar = 0 ; LoopVar < Script->Argc ; LoopVar++) { + SHELL_FREE_NON_NULL(Script->Argv[LoopVar]); + } + if (Script->Argv != NULL) { + SHELL_FREE_NON_NULL(Script->Argv); + } + Script->CurrentCommand = NULL; + while (!IsListEmpty (&Script->CommandList)) { + Script->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode(&Script->CommandList); + if (Script->CurrentCommand != NULL) { + RemoveEntryList(&Script->CurrentCommand->Link); + if (Script->CurrentCommand->Cl != NULL) { + SHELL_FREE_NON_NULL(Script->CurrentCommand->Cl); + } + if (Script->CurrentCommand->Data != NULL) { + SHELL_FREE_NON_NULL(Script->CurrentCommand->Data); + } + SHELL_FREE_NON_NULL(Script->CurrentCommand); + } + } + SHELL_FREE_NON_NULL(Script->ScriptName); + SHELL_FREE_NON_NULL(Script); +} + +/** + Function to return a pointer to the currently running script file object. + + @retval NULL A script file is not currently running. + @return A pointer to the current script file object. +**/ +SCRIPT_FILE* +EFIAPI +ShellCommandGetCurrentScriptFile ( + VOID + ) +{ + SCRIPT_FILE_LIST *List; + if (IsListEmpty (&mScriptList.Link)) { + return (NULL); + } + List = ((SCRIPT_FILE_LIST*)GetFirstNode(&mScriptList.Link)); + return (List->Data); +} + +/** + Function to set a new script as the currently running one. + + This function will correctly stack and unstack nested scripts. + + @param[in] Script Pointer to new script information structure. if NULL + will remove and de-allocate the top-most Script structure. + + @return A pointer to the current running script file after this + change. NULL if removing the final script. +**/ +SCRIPT_FILE* +EFIAPI +ShellCommandSetNewScript ( + IN SCRIPT_FILE *Script OPTIONAL + ) +{ + SCRIPT_FILE_LIST *Node; + if (Script == NULL) { + if (IsListEmpty (&mScriptList.Link)) { + return (NULL); + } + Node = (SCRIPT_FILE_LIST *)GetFirstNode(&mScriptList.Link); + RemoveEntryList(&Node->Link); + DeleteScriptFileStruct(Node->Data); + FreePool(Node); + } else { + Node = AllocateZeroPool(sizeof(SCRIPT_FILE_LIST)); + if (Node == NULL) { + return (NULL); + } + Node->Data = Script; + InsertHeadList(&mScriptList.Link, &Node->Link); + } + return (ShellCommandGetCurrentScriptFile()); +} + +/** + Function to generate the next default mapping name. + + If the return value is not NULL then it must be callee freed. + + @param Type What kind of mapping name to make. + + @retval NULL a memory allocation failed. + @return a new map name string +**/ +CHAR16* +EFIAPI +ShellCommandCreateNewMappingName( + IN CONST SHELL_MAPPING_TYPE Type + ) +{ + CHAR16 *String; + ASSERT(Type < MappingTypeMax); + + String = NULL; + + String = AllocateZeroPool(PcdGet8(PcdShellMapNameLength) * sizeof(String[0])); + UnicodeSPrint( + String, + PcdGet8(PcdShellMapNameLength) * sizeof(String[0]), + Type == MappingTypeFileSystem?L"FS%d:":L"BLK%d:", + Type == MappingTypeFileSystem?mFsMaxCount++:mBlkMaxCount++); + + return (String); +} + +/** + Function to add a map node to the list of map items and update the "path" environment variable (optionally). + + If Path is TRUE (during initialization only), the path environment variable will also be updated to include + default paths on the new map name... + + Path should be FALSE when this function is called from the protocol SetMap function. + + @param[in] Name The human readable mapped name. + @param[in] DevicePath The Device Path for this map. + @param[in] Flags The Flags attribute for this map item. + @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization). + + @retval EFI_SUCCESS The addition was sucessful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +EFIAPI +ShellCommandAddMapItemAndUpdatePath( + IN CONST CHAR16 *Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST UINT64 Flags, + IN CONST BOOLEAN Path + ) +{ + EFI_STATUS Status; + SHELL_MAP_LIST *MapListNode; + CONST CHAR16 *OriginalPath; + CHAR16 *NewPath; + UINTN NewPathSize; + + NewPathSize = 0; + NewPath = NULL; + OriginalPath = NULL; + Status = EFI_SUCCESS; + + MapListNode = AllocateZeroPool(sizeof(SHELL_MAP_LIST)); + if (MapListNode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + MapListNode->Flags = Flags; + MapListNode->MapName = AllocateCopyPool(StrSize(Name), Name); + MapListNode->DevicePath = DuplicateDevicePath(DevicePath); + if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)){ + Status = EFI_OUT_OF_RESOURCES; + } else { + InsertTailList(&gShellMapList.Link, &MapListNode->Link); + } + } + if (EFI_ERROR(Status)) { + if (MapListNode != NULL) { + if (MapListNode->DevicePath != NULL) { + FreePool(MapListNode->DevicePath); + } + if (MapListNode->MapName != NULL) { + FreePool(MapListNode->MapName); + } + FreePool(MapListNode); + } + } else if (Path) { + // + // Since there was no error and Path was TRUE + // Now add the correct path for that mapping + // + OriginalPath = gEfiShellProtocol->GetEnv(L"path"); + ASSERT((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL)); + if (OriginalPath != NULL) { + StrnCatGrow(&NewPath, &NewPathSize, OriginalPath, 0); + StrnCatGrow(&NewPath, &NewPathSize, L";", 0); + } + StrnCatGrow(&NewPath, &NewPathSize, Name, 0); + StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0); + StrnCatGrow(&NewPath, &NewPathSize, Name, 0); + StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\boot\\;", 0); + StrnCatGrow(&NewPath, &NewPathSize, Name, 0); + StrnCatGrow(&NewPath, &NewPathSize, L"\\", 0); + + Status = gEfiShellProtocol->SetEnv(L"path", NewPath, TRUE); + ASSERT_EFI_ERROR(Status); + FreePool(NewPath); + } + return (Status); +} + +/** + Creates the default map names for each device path in the system with + a protocol depending on the Type. + + Creates the consistent map names for each device path in the system with + a protocol depending on the Type. + + Note: This will reset all mappings in the system("map -r"). + + Also sets up the default path environment variable if Type is FileSystem. + + @retval EFI_SUCCESS All map names were created sucessfully. + @retval EFI_NOT_FOUND No protocols were found in the system. + @return Error returned from gBS->LocateHandle(). + + @sa LocateHandle +**/ +EFI_STATUS +EFIAPI +ShellCommandCreateInitialMappingsAndPaths( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleList; + UINTN Count; + EFI_DEVICE_PATH_PROTOCOL **DevicePathList; + CHAR16 *NewDefaultName; + CHAR16 *NewConsistName; + EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable; + SHELL_MAP_LIST *MapListNode; + CONST CHAR16 *CurDir; + CHAR16 *SplitCurDir; + CHAR16 *MapName; + SHELL_MAP_LIST *MapListItem; + + SplitCurDir = NULL; + MapName = NULL; + MapListItem = NULL; + HandleList = NULL; + + // + // Reset the static members back to zero + // + mFsMaxCount = 0; + mBlkMaxCount = 0; + + gEfiShellProtocol->SetEnv(L"path", L"", TRUE); + + // + // First empty out the existing list. + // + if (!IsListEmpty(&gShellMapList.Link)) { + for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ; !IsListEmpty(&gShellMapList.Link) + ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link) + ){ + RemoveEntryList(&MapListNode->Link); + SHELL_FREE_NON_NULL(MapListNode->DevicePath); + SHELL_FREE_NON_NULL(MapListNode->MapName); + SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath); + FreePool(MapListNode); + } // for loop + } + + // + // Find each handle with Simple File System + // + HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid); + if (HandleList != NULL) { + // + // Do a count of the handles + // + for (Count = 0 ; HandleList[Count] != NULL ; Count++); + + // + // Get all Device Paths + // + DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count); + if (DevicePathList == NULL) { + SHELL_FREE_NON_NULL (HandleList); + return EFI_OUT_OF_RESOURCES; + } + + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]); + } + + // + // Sort all DevicePaths + // + PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); + + ShellCommandConsistMappingInitialize(&ConsistMappingTable); + // + // Assign new Mappings to all... + // + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + // + // Get default name first + // + NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem); + ASSERT(NewDefaultName != NULL); + Status = ShellCommandAddMapItemAndUpdatePath(NewDefaultName, DevicePathList[Count], 0, TRUE); + ASSERT_EFI_ERROR(Status); + FreePool(NewDefaultName); + + // + // Now do consistent name + // + NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable); + if (NewConsistName != NULL) { + Status = ShellCommandAddMapItemAndUpdatePath(NewConsistName, DevicePathList[Count], 0, FALSE); + ASSERT_EFI_ERROR(Status); + FreePool(NewConsistName); + } + } + + ShellCommandConsistMappingUnInitialize(ConsistMappingTable); + + SHELL_FREE_NON_NULL(HandleList); + SHELL_FREE_NON_NULL(DevicePathList); + + HandleList = NULL; + + // + //gShellCurMapping point to node of current file system in the gShellMapList. When reset all mappings, + //all nodes in the gShellMapList will be free. Then gShellCurMapping will be a dangling pointer, So, + //after created new mappings, we should reset the gShellCurMapping pointer back to node of current file system. + // + if (gShellCurMapping != NULL) { + gShellCurMapping = NULL; + CurDir = gEfiShellProtocol->GetEnv(L"cwd"); + if (CurDir != NULL) { + MapName = AllocateCopyPool (StrSize(CurDir), CurDir); + if (MapName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + SplitCurDir = StrStr (MapName, L":"); + if (SplitCurDir == NULL) { + SHELL_FREE_NON_NULL (MapName); + return EFI_UNSUPPORTED; + } + *(SplitCurDir + 1) = CHAR_NULL; + MapListItem = ShellCommandFindMapItem (MapName); + if (MapListItem != NULL) { + gShellCurMapping = MapListItem; + } + SHELL_FREE_NON_NULL (MapName); + } + } + } else { + Count = (UINTN)-1; + } + + // + // Find each handle with Block Io + // + HandleList = GetHandleListByProtocol(&gEfiBlockIoProtocolGuid); + if (HandleList != NULL) { + for (Count = 0 ; HandleList[Count] != NULL ; Count++); + + // + // Get all Device Paths + // + DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count); + if (DevicePathList == NULL) { + SHELL_FREE_NON_NULL (HandleList); + return EFI_OUT_OF_RESOURCES; + } + + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]); + } + + // + // Sort all DevicePaths + // + PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); + + // + // Assign new Mappings to all... + // + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + // + // Get default name first + // + NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeBlockIo); + ASSERT(NewDefaultName != NULL); + Status = ShellCommandAddMapItemAndUpdatePath(NewDefaultName, DevicePathList[Count], 0, FALSE); + ASSERT_EFI_ERROR(Status); + FreePool(NewDefaultName); + } + + SHELL_FREE_NON_NULL(HandleList); + SHELL_FREE_NON_NULL(DevicePathList); + } else if (Count == (UINTN)-1) { + return (EFI_NOT_FOUND); + } + + return (EFI_SUCCESS); +} + +/** + Add mappings for any devices without one. Do not change any existing maps. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +ShellCommandUpdateMapping ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleList; + UINTN Count; + EFI_DEVICE_PATH_PROTOCOL **DevicePathList; + CHAR16 *NewDefaultName; + CHAR16 *NewConsistName; + EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable; + + HandleList = NULL; + Status = EFI_SUCCESS; + + // + // remove mappings that represent removed devices. + // + + // + // Find each handle with Simple File System + // + HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid); + if (HandleList != NULL) { + // + // Do a count of the handles + // + for (Count = 0 ; HandleList[Count] != NULL ; Count++); + + // + // Get all Device Paths + // + DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count); + if (DevicePathList == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + for (Count = 0 ; HandleList[Count] != NULL ; Count++) { + DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]); + } + + // + // Sort all DevicePaths + // + PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare); + + ShellCommandConsistMappingInitialize(&ConsistMappingTable); + + // + // Assign new Mappings to remainders + // + for (Count = 0 ; !EFI_ERROR(Status) && HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) { + // + // Skip ones that already have + // + if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) { + continue; + } + // + // Get default name + // + NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem); + if (NewDefaultName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + // + // Call shell protocol SetMap function now... + // + Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName); + + if (!EFI_ERROR(Status)) { + // + // Now do consistent name + // + NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable); + if (NewConsistName != NULL) { + Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName); + FreePool(NewConsistName); + } + } + + FreePool(NewDefaultName); + } + ShellCommandConsistMappingUnInitialize(ConsistMappingTable); + SHELL_FREE_NON_NULL(HandleList); + SHELL_FREE_NON_NULL(DevicePathList); + + HandleList = NULL; + } else { + Count = (UINTN)-1; + } + // + // Do it all over again for gEfiBlockIoProtocolGuid + // + + return (Status); +} + +/** + Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*. + + @param[in] Handle The SHELL_FILE_HANDLE to convert. + + @return a EFI_FILE_PROTOCOL* representing the same file. +**/ +EFI_FILE_PROTOCOL* +EFIAPI +ConvertShellHandleToEfiFileProtocol( + IN CONST SHELL_FILE_HANDLE Handle + ) +{ + return ((EFI_FILE_PROTOCOL*)(Handle)); +} + +/** + Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE. + + @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert. + @param[in] Path The path to the file for verification. + + @return A SHELL_FILE_HANDLE representing the same file. + @retval NULL There was not enough memory. +**/ +SHELL_FILE_HANDLE +EFIAPI +ConvertEfiFileProtocolToShellHandle( + IN CONST EFI_FILE_PROTOCOL *Handle, + IN CONST CHAR16 *Path + ) +{ + SHELL_COMMAND_FILE_HANDLE *Buffer; + BUFFER_LIST *NewNode; + + if (Path != NULL) { + Buffer = AllocateZeroPool(sizeof(SHELL_COMMAND_FILE_HANDLE)); + if (Buffer == NULL) { + return (NULL); + } + NewNode = AllocateZeroPool(sizeof(BUFFER_LIST)); + if (NewNode == NULL) { + SHELL_FREE_NON_NULL(Buffer); + return (NULL); + } + Buffer->FileHandle = (EFI_FILE_PROTOCOL*)Handle; + Buffer->Path = StrnCatGrow(&Buffer->Path, NULL, Path, 0); + if (Buffer->Path == NULL) { + SHELL_FREE_NON_NULL(NewNode); + SHELL_FREE_NON_NULL(Buffer); + return (NULL); + } + NewNode->Buffer = Buffer; + + InsertHeadList(&mFileHandleList.Link, &NewNode->Link); + } + return ((SHELL_FILE_HANDLE)(Handle)); +} + +/** + Find the path that was logged with the specified SHELL_FILE_HANDLE. + + @param[in] Handle The SHELL_FILE_HANDLE to query on. + + @return A pointer to the path for the file. +**/ +CONST CHAR16* +EFIAPI +ShellFileHandleGetPath( + IN CONST SHELL_FILE_HANDLE Handle + ) +{ + BUFFER_LIST *Node; + + for (Node = (BUFFER_LIST*)GetFirstNode(&mFileHandleList.Link) + ; !IsNull(&mFileHandleList.Link, &Node->Link) + ; Node = (BUFFER_LIST*)GetNextNode(&mFileHandleList.Link, &Node->Link) + ){ + if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)){ + return (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path); + } + } + return (NULL); +} + +/** + Remove a SHELL_FILE_HANDLE from the list of SHELL_FILE_HANDLES. + + @param[in] Handle The SHELL_FILE_HANDLE to remove. + + @retval TRUE The item was removed. + @retval FALSE The item was not found. +**/ +BOOLEAN +EFIAPI +ShellFileHandleRemove( + IN CONST SHELL_FILE_HANDLE Handle + ) +{ + BUFFER_LIST *Node; + + for (Node = (BUFFER_LIST*)GetFirstNode(&mFileHandleList.Link) + ; !IsNull(&mFileHandleList.Link, &Node->Link) + ; Node = (BUFFER_LIST*)GetNextNode(&mFileHandleList.Link, &Node->Link) + ){ + if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)){ + RemoveEntryList(&Node->Link); + SHELL_FREE_NON_NULL(((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path); + SHELL_FREE_NON_NULL(Node->Buffer); + SHELL_FREE_NON_NULL(Node); + return (TRUE); + } + } + return (FALSE); +} + +/** + Function to determine if a SHELL_FILE_HANDLE is at the end of the file. + + This will NOT work on directories. + + If Handle is NULL, then ASSERT. + + @param[in] Handle the file handle + + @retval TRUE the position is at the end of the file + @retval FALSE the position is not at the end of the file +**/ +BOOLEAN +EFIAPI +ShellFileHandleEof( + IN SHELL_FILE_HANDLE Handle + ) +{ + EFI_FILE_INFO *Info; + UINT64 Pos; + BOOLEAN RetVal; + + // + // ASSERT if Handle is NULL + // + ASSERT(Handle != NULL); + + gEfiShellProtocol->GetFilePosition(Handle, &Pos); + Info = gEfiShellProtocol->GetFileInfo (Handle); + gEfiShellProtocol->SetFilePosition(Handle, Pos); + + if (Info == NULL) { + return (FALSE); + } + + if (Pos == Info->FileSize) { + RetVal = TRUE; + } else { + RetVal = FALSE; + } + + FreePool (Info); + + return (RetVal); +} + +/** + Frees any BUFFER_LIST defined type. + + @param[in] List The BUFFER_LIST object to free. +**/ +VOID +EFIAPI +FreeBufferList ( + IN BUFFER_LIST *List + ) +{ + BUFFER_LIST *BufferListEntry; + + if (List == NULL){ + return; + } + // + // enumerate through the buffer list and free all memory + // + for ( BufferListEntry = ( BUFFER_LIST *)GetFirstNode(&List->Link) + ; !IsListEmpty (&List->Link) + ; BufferListEntry = (BUFFER_LIST *)GetFirstNode(&List->Link) + ){ + RemoveEntryList(&BufferListEntry->Link); + if (BufferListEntry->Buffer != NULL) { + FreePool(BufferListEntry->Buffer); + } + FreePool(BufferListEntry); + } +} + +/** + Dump some hexadecimal data to the screen. + + @param[in] Indent How many spaces to indent the output. + @param[in] Offset The offset of the printing. + @param[in] DataSize The size in bytes of UserData. + @param[in] UserData The data to print out. +**/ +VOID +EFIAPI +DumpHex ( + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID *UserData + ) +{ + UINT8 *Data; + + CHAR8 Val[50]; + + CHAR8 Str[20]; + + UINT8 TempByte; + UINTN Size; + UINTN Index; + + Data = UserData; + while (DataSize != 0) { + Size = 16; + if (Size > DataSize) { + Size = DataSize; + } + + for (Index = 0; Index < Size; Index += 1) { + TempByte = Data[Index]; + Val[Index * 3 + 0] = Hex[TempByte >> 4]; + Val[Index * 3 + 1] = Hex[TempByte & 0xF]; + Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' '); + Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > '~') ? '.' : TempByte); + } + + Val[Index * 3] = 0; + Str[Index] = 0; + ShellPrintEx(-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str); + + Data += Size; + Offset += Size; + DataSize -= Size; + } +} + +/** + Dump HEX data into buffer. + + @param[in] Buffer HEX data to be dumped in Buffer. + @param[in] Indent How many spaces to indent the output. + @param[in] Offset The offset of the printing. + @param[in] DataSize The size in bytes of UserData. + @param[in] UserData The data to print out. +**/ +CHAR16* +EFIAPI +CatSDumpHex ( + IN CHAR16 *Buffer, + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID *UserData + ) +{ + UINT8 *Data; + UINT8 TempByte; + UINTN Size; + UINTN Index; + CHAR8 Val[50]; + CHAR8 Str[20]; + CHAR16 *RetVal; + CHAR16 *TempRetVal; + + Data = UserData; + RetVal = Buffer; + while (DataSize != 0) { + Size = 16; + if (Size > DataSize) { + Size = DataSize; + } + + for (Index = 0; Index < Size; Index += 1) { + TempByte = Data[Index]; + Val[Index * 3 + 0] = Hex[TempByte >> 4]; + Val[Index * 3 + 1] = Hex[TempByte & 0xF]; + Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' '); + Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte); + } + + Val[Index * 3] = 0; + Str[Index] = 0; + TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str); + SHELL_FREE_NON_NULL (RetVal); + RetVal = TempRetVal; + + Data += Size; + Offset += Size; + DataSize -= Size; + } + + return RetVal; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h new file mode 100644 index 0000000..7fb769f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h @@ -0,0 +1,71 @@ +/** @file + Provides interface to shell internal functions for shell commands. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_COMMAND_LIB_INTERNAL_HEADER_ +#define _UEFI_COMMAND_LIB_INTERNAL_HEADER_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct{ + LIST_ENTRY Link; + CHAR16 *CommandString; + SHELL_GET_MAN_FILENAME GetManFileName; + SHELL_RUN_COMMAND CommandHandler; + BOOLEAN LastError; + EFI_HANDLE HiiHandle; + EFI_STRING_ID ManFormatHelp; +} SHELL_COMMAND_INTERNAL_LIST_ENTRY; + +typedef struct { + LIST_ENTRY Link; + SCRIPT_FILE *Data; +} SCRIPT_FILE_LIST; + +typedef struct { + EFI_FILE_PROTOCOL *FileHandle; + CHAR16 *Path; +} SHELL_COMMAND_FILE_HANDLE; + + +#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_ + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf new file mode 100644 index 0000000..961f4d0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf @@ -0,0 +1,69 @@ +## @file +# Provides interface to shell internal functions for shell commands. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellCommandLib + FILE_GUID = 5C12F31F-EBAC-466e-A400-FCA8C9EA3A05 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.1 + LIBRARY_CLASS = ShellCommandLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER + CONSTRUCTOR = ShellCommandLibConstructor + DESTRUCTOR = ShellCommandLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + UefiShellCommandLib.c + UefiShellCommandLib.h + ConsistMapping.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + PrintLib + UefiBootServicesTableLib + ShellLib + HiiLib + HandleParsingLib + +[Protocols] + gEfiUnicodeCollation2ProtocolGuid ## CONSUMES + gEfiShellProtocolGuid ## CONSUMES + gEfiShellParametersProtocolGuid ## CONSUMES + gEfiShellDynamicCommandProtocolGuid ## SOMETIMES_CONSUMES + gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gEfiSasDevicePathGuid ## SOMETIMES_CONSUMES ## GUID + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdUsbExtendedDecode ## SOMETIMES_CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellDecodeIScsiMapNames ## SOMETIMES_CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellVendorExtendedDecode ## SOMETIMES_CONSUMES + +[Depex] + gEfiUnicodeCollation2ProtocolGuid diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c new file mode 100644 index 0000000..34d645e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c @@ -0,0 +1,378 @@ +/** @file + Main file for Comp shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-n", TypeValue}, + {L"-s", TypeValue}, + {NULL, TypeMax} + }; + +typedef enum { + OutOfDiffPoint, + InDiffPoint, + InPrevDiffPoint +} READ_STATUS; + +/** + Function to print differnt point data. + + @param[in] FileName File name. + @param[in] FileTag File tag name. + @param[in] Buffer Data buffer to be printed. + @param[in] BufferSize Size of the data to be printed. + @param[in] Address Address of the differnt point. + @param[in] DifferentBytes Total size of the buffer. + +**/ +VOID +PrintDifferentPoint( + CONST CHAR16 *FileName, + CHAR16 *FileTag, + UINT8 *Buffer, + UINT64 BufferSize, + UINTN Address, + UINT64 DifferentBytes + ) +{ + UINTN Index; + + ShellPrintEx (-1, -1, L"%s: %s\r\n %08x:", FileTag, FileName, Address); + + // + // Print data in hex-format. + // + for (Index = 0; Index < BufferSize; Index++) { + ShellPrintEx (-1, -1, L" %02x", Buffer[Index]); + } + + if (BufferSize < DifferentBytes) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_END_OF_FILE), gShellDebug1HiiHandle); + } + + ShellPrintEx (-1, -1, L" *"); + + // + // Print data in char-format. + // + for (Index = 0; Index < BufferSize; Index++) { + if (Buffer[Index] >= 0x20 && Buffer[Index] <= 0x7E) { + ShellPrintEx (-1, -1, L"%c", Buffer[Index]); + } else { + // + // Print dots for control characters + // + ShellPrintEx (-1, -1, L"."); + } + } + + ShellPrintEx (-1, -1, L"*\r\n"); +} + +/** + Function for 'comp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunComp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CHAR16 *FileName1; + CHAR16 *FileName2; + CONST CHAR16 *TempParam; + SHELL_STATUS ShellStatus; + SHELL_FILE_HANDLE FileHandle1; + SHELL_FILE_HANDLE FileHandle2; + UINT64 Size1; + UINT64 Size2; + UINT64 DifferentBytes; + UINT64 DifferentCount; + UINT8 DiffPointNumber; + UINT8 OneByteFromFile1; + UINT8 OneByteFromFile2; + UINT8 *DataFromFile1; + UINT8 *DataFromFile2; + UINTN InsertPosition1; + UINTN InsertPosition2; + UINTN DataSizeFromFile1; + UINTN DataSizeFromFile2; + UINTN TempAddress; + UINTN Index; + UINTN DiffPointAddress; + READ_STATUS ReadStatus; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + FileName1 = NULL; + FileName2 = NULL; + FileHandle1 = NULL; + FileHandle2 = NULL; + DataFromFile1 = NULL; + DataFromFile2 = NULL; + ReadStatus = OutOfDiffPoint; + DifferentCount = 10; + DifferentBytes = 4; + DiffPointNumber = 0; + InsertPosition1 = 0; + InsertPosition2 = 0; + TempAddress = 0; + DiffPointAddress = 0; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"comp", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"comp"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"comp"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempParam = ShellCommandLineGetRawValue(Package, 1); + ASSERT(TempParam != NULL); + FileName1 = ShellFindFilePath(TempParam); + if (FileName1 == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); + ShellStatus = SHELL_NOT_FOUND; + } else { + Status = ShellOpenFileByName(FileName1, &FileHandle1, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); + ShellStatus = SHELL_NOT_FOUND; + } + } + TempParam = ShellCommandLineGetRawValue(Package, 2); + ASSERT(TempParam != NULL); + FileName2 = ShellFindFilePath(TempParam); + if (FileName2 == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); + ShellStatus = SHELL_NOT_FOUND; + } else { + Status = ShellOpenFileByName(FileName2, &FileHandle2, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); + ShellStatus = SHELL_NOT_FOUND; + } + } + if (ShellStatus == SHELL_SUCCESS) { + Status = gEfiShellProtocol->GetFileSize(FileHandle1, &Size1); + ASSERT_EFI_ERROR(Status); + Status = gEfiShellProtocol->GetFileSize(FileHandle2, &Size2); + ASSERT_EFI_ERROR(Status); + + if (ShellCommandLineGetFlag (Package, L"-n")) { + TempParam = ShellCommandLineGetValue (Package, L"-n"); + if (TempParam == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"comp", L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)TempParam, L"all") == 0) { + DifferentCount = MAX_UINTN; + } else { + Status = ShellConvertStringToUint64 (TempParam, &DifferentCount, FALSE, TRUE); + if (EFI_ERROR(Status) || DifferentCount == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"comp", TempParam, L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + + if (ShellCommandLineGetFlag (Package, L"-s")) { + TempParam = ShellCommandLineGetValue (Package, L"-s"); + if (TempParam == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"comp", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (TempParam, &DifferentBytes, FALSE, TRUE); + if (EFI_ERROR(Status) || DifferentBytes == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"comp", TempParam, L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (DifferentBytes > MAX (Size1, Size2)) { + DifferentBytes = MAX (Size1, Size2); + } + } + } + } + } + + if (ShellStatus == SHELL_SUCCESS) { + DataFromFile1 = AllocateZeroPool ((UINTN)DifferentBytes); + DataFromFile2 = AllocateZeroPool ((UINTN)DifferentBytes); + if (DataFromFile1 == NULL || DataFromFile2 == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + SHELL_FREE_NON_NULL (DataFromFile1); + SHELL_FREE_NON_NULL (DataFromFile2); + } + } + + if (ShellStatus == SHELL_SUCCESS) { + while (DiffPointNumber < DifferentCount) { + DataSizeFromFile1 = 1; + DataSizeFromFile2 = 1; + OneByteFromFile1 = 0; + OneByteFromFile2 = 0; + Status = gEfiShellProtocol->ReadFile (FileHandle1, &DataSizeFromFile1, &OneByteFromFile1); + ASSERT_EFI_ERROR (Status); + Status = gEfiShellProtocol->ReadFile (FileHandle2, &DataSizeFromFile2, &OneByteFromFile2); + ASSERT_EFI_ERROR (Status); + + TempAddress++; + + // + // 1.When end of file and no chars in DataFromFile buffer, then break while. + // 2.If no more char in File1 or File2, The ReadStatus is InPrevDiffPoint forever. + // So the previous different point is the last one, then break the while block. + // + if ( (DataSizeFromFile1 == 0 && InsertPosition1 == 0 && DataSizeFromFile2 == 0 && InsertPosition2 == 0) || + (ReadStatus == InPrevDiffPoint && (DataSizeFromFile1 == 0 || DataSizeFromFile2 == 0)) + ) { + break; + } + + if (ReadStatus == OutOfDiffPoint) { + if (OneByteFromFile1 != OneByteFromFile2) { + ReadStatus = InDiffPoint; + DiffPointAddress = TempAddress; + if (DataSizeFromFile1 == 1) { + DataFromFile1[InsertPosition1++] = OneByteFromFile1; + } + if (DataSizeFromFile2 == 1) { + DataFromFile2[InsertPosition2++] = OneByteFromFile2; + } + } + } else if (ReadStatus == InDiffPoint) { + if (DataSizeFromFile1 == 1) { + DataFromFile1[InsertPosition1++] = OneByteFromFile1; + } + if (DataSizeFromFile2 == 1) { + DataFromFile2[InsertPosition2++] = OneByteFromFile2; + } + } else if (ReadStatus == InPrevDiffPoint) { + if (OneByteFromFile1 == OneByteFromFile2) { + ReadStatus = OutOfDiffPoint; + } + } + + // + // ReadStatus should be always equal InDiffPoint. + // + if ( InsertPosition1 == DifferentBytes || + InsertPosition2 == DifferentBytes || + (DataSizeFromFile1 == 0 && DataSizeFromFile2 == 0) + ) { + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_DIFFERENCE_POINT), gShellDebug1HiiHandle, ++DiffPointNumber); + PrintDifferentPoint (FileName1, L"File1", DataFromFile1, InsertPosition1, DiffPointAddress, DifferentBytes); + PrintDifferentPoint (FileName2, L"File2", DataFromFile2, InsertPosition2, DiffPointAddress, DifferentBytes); + + // + // One of two buffuers is empty, it means this is the last different point. + // + if (InsertPosition1 == 0 || InsertPosition2 == 0) { + break; + } + + for (Index = 1; Index < InsertPosition1 && Index < InsertPosition2; Index++) { + if (DataFromFile1[Index] == DataFromFile2[Index]) { + ReadStatus = OutOfDiffPoint; + break; + } + } + + if (ReadStatus == OutOfDiffPoint) { + // + // Try to find a new different point in the rest of DataFromFile. + // + for (; Index < MAX (InsertPosition1,InsertPosition2); Index++) { + if (DataFromFile1[Index] != DataFromFile2[Index]) { + ReadStatus = InDiffPoint; + DiffPointAddress += Index; + break; + } + } + } else { + // + // Doesn't find a new different point, still in the same different point. + // + ReadStatus = InPrevDiffPoint; + } + + CopyMem (DataFromFile1, DataFromFile1 + Index, InsertPosition1 - Index); + CopyMem (DataFromFile2, DataFromFile2 + Index, InsertPosition2 - Index); + + SetMem (DataFromFile1 + InsertPosition1 - Index, (UINTN)DifferentBytes - InsertPosition1 + Index, 0); + SetMem (DataFromFile2 + InsertPosition2 - Index, (UINTN)DifferentBytes - InsertPosition2 + Index, 0); + + InsertPosition1 -= Index; + InsertPosition2 -= Index; + } + } + + SHELL_FREE_NON_NULL (DataFromFile1); + SHELL_FREE_NON_NULL (DataFromFile2); + + if (DiffPointNumber == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_PASS), gShellDebug1HiiHandle); + } else { + ShellStatus = SHELL_NOT_EQUAL; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_FAIL), gShellDebug1HiiHandle); + } + } + } + + ShellCommandLineFreeVarList (Package); + } + SHELL_FREE_NON_NULL(FileName1); + SHELL_FREE_NON_NULL(FileName2); + + if (FileHandle1 != NULL) { + gEfiShellProtocol->CloseFile(FileHandle1); + } + if (FileHandle2 != NULL) { + gEfiShellProtocol->CloseFile(FileHandle2); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c new file mode 100644 index 0000000..c3d3ec6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c @@ -0,0 +1,1388 @@ +/** @file + Main file for compression routine. + + Compression routine. The compression algorithm is a mixture of + LZ77 and Huffman coding. LZ77 transforms the source data into a + sequence of Original Characters and Pointers to repeated strings. + This sequence is further divided into Blocks and Huffman codings + are applied to each Block. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include +#include +#include +#include +#include + +#include "Compress.h" + +// +// Macro Definitions +// +typedef INT16 NODE; +#define UINT8_MAX 0xff +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 13 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define BLKSIZ (1U << 14) // 16 * 1024U +#define PERC_FLAG 0x8000U +#define CODE_BIT 16 +#define NIL 0 +#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) +#define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2) +#define CRCPOLY 0xA001 +#define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 0xFF] ^ (mCrc >> UINT8_BIT) + +// +// C: the Char&Len Set; P: the Position Set; T: the exTra Set +// +#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define NP (WNDBIT + 1) +#define PBIT 4 +#define NT (CODE_BIT + 3) +#define TBIT 5 +#if NT > NP + #define NPT NT +#else + #define NPT NP +#endif +// +// Function Prototypes +// + +/** + Put a dword to output stream + + @param[in] Data The dword to put. +**/ +VOID +PutDword( + IN UINT32 Data + ); + +// +// Global Variables +// +STATIC UINT8 *mSrc; +STATIC UINT8 *mDst; +STATIC UINT8 *mSrcUpperLimit; +STATIC UINT8 *mDstUpperLimit; + +STATIC UINT8 *mLevel; +STATIC UINT8 *mText; +STATIC UINT8 *mChildCount; +STATIC UINT8 *mBuf; +STATIC UINT8 mCLen[NC]; +STATIC UINT8 mPTLen[NPT]; +STATIC UINT8 *mLen; +STATIC INT16 mHeap[NC + 1]; +STATIC INT32 mRemainder; +STATIC INT32 mMatchLen; +STATIC INT32 mBitCount; +STATIC INT32 mHeapSize; +STATIC INT32 mTempInt32; +STATIC UINT32 mBufSiz = 0; +STATIC UINT32 mOutputPos; +STATIC UINT32 mOutputMask; +STATIC UINT32 mSubBitBuf; +STATIC UINT32 mCrc; +STATIC UINT32 mCompSize; +STATIC UINT32 mOrigSize; + +STATIC UINT16 *mFreq; +STATIC UINT16 *mSortPtr; +STATIC UINT16 mLenCnt[17]; +STATIC UINT16 mLeft[2 * NC - 1]; +STATIC UINT16 mRight[2 * NC - 1]; +STATIC UINT16 mCrcTable[UINT8_MAX + 1]; +STATIC UINT16 mCFreq[2 * NC - 1]; +STATIC UINT16 mCCode[NC]; +STATIC UINT16 mPFreq[2 * NP - 1]; +STATIC UINT16 mPTCode[NPT]; +STATIC UINT16 mTFreq[2 * NT - 1]; + +STATIC NODE mPos; +STATIC NODE mMatchPos; +STATIC NODE mAvail; +STATIC NODE *mPosition; +STATIC NODE *mParent; +STATIC NODE *mPrev; +STATIC NODE *mNext = NULL; +INT32 mHuffmanDepth = 0; + +/** + Make a CRC table. + +**/ +VOID +MakeCrcTable ( + VOID + ) +{ + UINT32 LoopVar1; + + UINT32 LoopVar2; + + UINT32 LoopVar4; + + for (LoopVar1 = 0; LoopVar1 <= UINT8_MAX; LoopVar1++) { + LoopVar4 = LoopVar1; + for (LoopVar2 = 0; LoopVar2 < UINT8_BIT; LoopVar2++) { + if ((LoopVar4 & 1) != 0) { + LoopVar4 = (LoopVar4 >> 1) ^ CRCPOLY; + } else { + LoopVar4 >>= 1; + } + } + + mCrcTable[LoopVar1] = (UINT16) LoopVar4; + } +} + +/** + Put a dword to output stream + + @param[in] Data The dword to put. +**/ +VOID +PutDword ( + IN UINT32 Data + ) +{ + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); + } +} + +/** + Allocate memory spaces for data structures used in compression process. + + @retval EFI_SUCCESS Memory was allocated successfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +AllocateMemory ( + VOID + ) +{ + mText = AllocateZeroPool (WNDSIZ * 2 + MAXMATCH); + mLevel = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); + mChildCount = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); + mPosition = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); + mParent = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mParent)); + mPrev = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mPrev)); + mNext = AllocateZeroPool ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + + mBufSiz = BLKSIZ; + mBuf = AllocateZeroPool (mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + + mBuf = AllocateZeroPool (mBufSiz); + } + + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +/** + Called when compression is completed to free memory previously allocated. + +**/ +VOID +FreeMemory ( + VOID + ) +{ + SHELL_FREE_NON_NULL (mText); + SHELL_FREE_NON_NULL (mLevel); + SHELL_FREE_NON_NULL (mChildCount); + SHELL_FREE_NON_NULL (mPosition); + SHELL_FREE_NON_NULL (mParent); + SHELL_FREE_NON_NULL (mPrev); + SHELL_FREE_NON_NULL (mNext); + SHELL_FREE_NON_NULL (mBuf); +} + +/** + Initialize String Info Log data structures. +**/ +VOID +InitSlide ( + VOID + ) +{ + NODE LoopVar1; + + SetMem (mLevel + WNDSIZ, (UINT8_MAX + 1) * sizeof (UINT8), 1); + SetMem (mPosition + WNDSIZ, (UINT8_MAX + 1) * sizeof (NODE), 0); + + SetMem (mParent + WNDSIZ, WNDSIZ * sizeof (NODE), 0); + + mAvail = 1; + for (LoopVar1 = 1; LoopVar1 < WNDSIZ - 1; LoopVar1++) { + mNext[LoopVar1] = (NODE) (LoopVar1 + 1); + } + + mNext[WNDSIZ - 1] = NIL; + SetMem (mNext + WNDSIZ * 2, (MAX_HASH_VAL - WNDSIZ * 2 + 1) * sizeof (NODE), 0); +} + +/** + Find child node given the parent node and the edge character + + @param[in] LoopVar6 The parent node. + @param[in] LoopVar5 The edge character. + + @return The child node. + @retval NIL(Zero) No child could be found. + +**/ +NODE +Child ( + IN NODE LoopVar6, + IN UINT8 LoopVar5 + ) +{ + NODE LoopVar4; + + LoopVar4 = mNext[HASH (LoopVar6, LoopVar5)]; + mParent[NIL] = LoopVar6; /* sentinel */ + while (mParent[LoopVar4] != LoopVar6) { + LoopVar4 = mNext[LoopVar4]; + } + + return LoopVar4; +} + +/** + Create a new child for a given parent node. + + @param[in] LoopVar6 The parent node. + @param[in] LoopVar5 The edge character. + @param[in] LoopVar4 The child node. +**/ +VOID +MakeChild ( + IN NODE LoopVar6, + IN UINT8 LoopVar5, + IN NODE LoopVar4 + ) +{ + NODE LoopVar12; + + NODE LoopVar10; + + LoopVar12 = (NODE) HASH (LoopVar6, LoopVar5); + LoopVar10 = mNext[LoopVar12]; + mNext[LoopVar12] = LoopVar4; + mNext[LoopVar4] = LoopVar10; + mPrev[LoopVar10] = LoopVar4; + mPrev[LoopVar4] = LoopVar12; + mParent[LoopVar4] = LoopVar6; + mChildCount[LoopVar6]++; +} + +/** + Split a node. + + @param[in] Old The node to split. +**/ +VOID +Split ( + IN NODE Old + ) +{ + NODE New; + + NODE LoopVar10; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + LoopVar10 = mPrev[Old]; + mPrev[New] = LoopVar10; + mNext[LoopVar10] = New; + LoopVar10 = mNext[Old]; + mNext[New] = LoopVar10; + mPrev[LoopVar10] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8) mMatchLen; + mPosition[New] = mPos; + MakeChild (New, mText[mMatchPos + mMatchLen], Old); + MakeChild (New, mText[mPos + mMatchLen], mPos); +} + +/** + Insert string info for current position into the String Info Log. + +**/ +VOID +InsertNode ( + VOID + ) +{ + NODE LoopVar6; + + NODE LoopVar4; + + NODE LoopVar2; + + NODE LoopVar10; + UINT8 LoopVar5; + UINT8 *TempString3; + UINT8 *TempString2; + + if (mMatchLen >= 4) { + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Travese the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + mMatchLen--; + LoopVar4 = (NODE) ((mMatchPos + 1) | WNDSIZ); + LoopVar6 = mParent[LoopVar4]; + while (LoopVar6 == NIL) { + LoopVar4 = mNext[LoopVar4]; + LoopVar6 = mParent[LoopVar4]; + } + + while (mLevel[LoopVar6] >= mMatchLen) { + LoopVar4 = LoopVar6; + LoopVar6 = mParent[LoopVar6]; + } + + LoopVar10 = LoopVar6; + while (mPosition[LoopVar10] < 0) { + mPosition[LoopVar10] = mPos; + LoopVar10 = mParent[LoopVar10]; + } + + if (LoopVar10 < WNDSIZ) { + mPosition[LoopVar10] = (NODE) (mPos | PERC_FLAG); + } + } else { + // + // Locate the target tree + // + LoopVar6 = (NODE) (mText[mPos] + WNDSIZ); + LoopVar5 = mText[mPos + 1]; + LoopVar4 = Child (LoopVar6, LoopVar5); + if (LoopVar4 == NIL) { + MakeChild (LoopVar6, LoopVar5, mPos); + mMatchLen = 1; + return ; + } + + mMatchLen = 2; + } + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + for (;;) { + if (LoopVar4 >= WNDSIZ) { + LoopVar2 = MAXMATCH; + mMatchPos = LoopVar4; + } else { + LoopVar2 = mLevel[LoopVar4]; + mMatchPos = (NODE) (mPosition[LoopVar4] & ~PERC_FLAG); + } + + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + + TempString3 = &mText[mPos + mMatchLen]; + TempString2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < LoopVar2) { + if (*TempString3 != *TempString2) { + Split (LoopVar4); + return ; + } + + mMatchLen++; + TempString3++; + TempString2++; + } + + if (mMatchLen >= MAXMATCH) { + break; + } + + mPosition[LoopVar4] = mPos; + LoopVar6 = LoopVar4; + LoopVar4 = Child (LoopVar6, *TempString3); + if (LoopVar4 == NIL) { + MakeChild (LoopVar6, *TempString3, mPos); + return ; + } + + mMatchLen++; + } + + LoopVar10 = mPrev[LoopVar4]; + mPrev[mPos] = LoopVar10; + mNext[LoopVar10] = mPos; + LoopVar10 = mNext[LoopVar4]; + mNext[mPos] = LoopVar10; + mPrev[LoopVar10] = mPos; + mParent[mPos] = LoopVar6; + mParent[LoopVar4] = NIL; + + // + // Special usage of 'next' + // + mNext[LoopVar4] = mPos; + +} + +/** + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion). + +**/ +VOID +DeleteNode ( + VOID + ) +{ + NODE LoopVar6; + + NODE LoopVar4; + + NODE LoopVar11; + + NODE LoopVar10; + + NODE LoopVar9; + + if (mParent[mPos] == NIL) { + return ; + } + + LoopVar4 = mPrev[mPos]; + LoopVar11 = mNext[mPos]; + mNext[LoopVar4] = LoopVar11; + mPrev[LoopVar11] = LoopVar4; + LoopVar4 = mParent[mPos]; + mParent[mPos] = NIL; + if (LoopVar4 >= WNDSIZ) { + return ; + } + + mChildCount[LoopVar4]--; + if (mChildCount[LoopVar4] > 1) { + return ; + } + + LoopVar10 = (NODE) (mPosition[LoopVar4] & ~PERC_FLAG); + if (LoopVar10 >= mPos) { + LoopVar10 -= WNDSIZ; + } + + LoopVar11 = LoopVar10; + LoopVar6 = mParent[LoopVar4]; + LoopVar9 = mPosition[LoopVar6]; + while ((LoopVar9 & PERC_FLAG) != 0){ + LoopVar9 &= ~PERC_FLAG; + if (LoopVar9 >= mPos) { + LoopVar9 -= WNDSIZ; + } + + if (LoopVar9 > LoopVar11) { + LoopVar11 = LoopVar9; + } + + mPosition[LoopVar6] = (NODE) (LoopVar11 | WNDSIZ); + LoopVar6 = mParent[LoopVar6]; + LoopVar9 = mPosition[LoopVar6]; + } + + if (LoopVar6 < WNDSIZ) { + if (LoopVar9 >= mPos) { + LoopVar9 -= WNDSIZ; + } + + if (LoopVar9 > LoopVar11) { + LoopVar11 = LoopVar9; + } + + mPosition[LoopVar6] = (NODE) (LoopVar11 | WNDSIZ | PERC_FLAG); + } + + LoopVar11 = Child (LoopVar4, mText[LoopVar10 + mLevel[LoopVar4]]); + LoopVar10 = mPrev[LoopVar11]; + LoopVar9 = mNext[LoopVar11]; + mNext[LoopVar10] = LoopVar9; + mPrev[LoopVar9] = LoopVar10; + LoopVar10 = mPrev[LoopVar4]; + mNext[LoopVar10] = LoopVar11; + mPrev[LoopVar11] = LoopVar10; + LoopVar10 = mNext[LoopVar4]; + mPrev[LoopVar10] = LoopVar11; + mNext[LoopVar11] = LoopVar10; + mParent[LoopVar11] = mParent[LoopVar4]; + mParent[LoopVar4] = NIL; + mNext[LoopVar4] = mAvail; + mAvail = LoopVar4; +} + +/** + Read in source data + + @param[out] LoopVar7 The buffer to hold the data. + @param[in] LoopVar8 The number of bytes to read. + + @return The number of bytes actually read. +**/ +INT32 +FreadCrc ( + OUT UINT8 *LoopVar7, + IN INT32 LoopVar8 + ) +{ + INT32 LoopVar1; + + for (LoopVar1 = 0; mSrc < mSrcUpperLimit && LoopVar1 < LoopVar8; LoopVar1++) { + *LoopVar7++ = *mSrc++; + } + + LoopVar8 = LoopVar1; + + LoopVar7 -= LoopVar8; + mOrigSize += LoopVar8; + LoopVar1--; + while (LoopVar1 >= 0) { + UPDATE_CRC (*LoopVar7++); + LoopVar1--; + } + + return LoopVar8; +} + +/** + Advance the current position (read in new data if needed). + Delete outdated string info. Find a match string for current position. + + @retval TRUE The operation was successful. + @retval FALSE The operation failed due to insufficient memory. +**/ +BOOLEAN +GetNextMatch ( + VOID + ) +{ + INT32 LoopVar8; + VOID *Temp; + + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + Temp = AllocateZeroPool (WNDSIZ + MAXMATCH); + if (Temp == NULL) { + return (FALSE); + } + CopyMem (Temp, &mText[WNDSIZ], WNDSIZ + MAXMATCH); + CopyMem (&mText[0], Temp, WNDSIZ + MAXMATCH); + FreePool (Temp); + LoopVar8 = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += LoopVar8; + mPos = WNDSIZ; + } + + DeleteNode (); + InsertNode (); + + return (TRUE); +} + +/** + Send entry LoopVar1 down the queue. + + @param[in] LoopVar1 The index of the item to move. +**/ +VOID +DownHeap ( + IN INT32 i + ) +{ + INT32 LoopVar1; + + INT32 LoopVar2; + + // + // priority queue: send i-th entry down heap + // + LoopVar2 = mHeap[i]; + LoopVar1 = 2 * i; + while (LoopVar1 <= mHeapSize) { + if (LoopVar1 < mHeapSize && mFreq[mHeap[LoopVar1]] > mFreq[mHeap[LoopVar1 + 1]]) { + LoopVar1++; + } + + if (mFreq[LoopVar2] <= mFreq[mHeap[LoopVar1]]) { + break; + } + + mHeap[i] = mHeap[LoopVar1]; + i = LoopVar1; + LoopVar1 = 2 * i; + } + + mHeap[i] = (INT16) LoopVar2; +} + +/** + Count the number of each code length for a Huffman tree. + + @param[in] LoopVar1 The top node. +**/ +VOID +CountLen ( + IN INT32 LoopVar1 + ) +{ + if (LoopVar1 < mTempInt32) { + mLenCnt[(mHuffmanDepth < 16) ? mHuffmanDepth : 16]++; + } else { + mHuffmanDepth++; + CountLen (mLeft[LoopVar1]); + CountLen (mRight[LoopVar1]); + mHuffmanDepth--; + } +} + +/** + Create code length array for a Huffman tree. + + @param[in] Root The root of the tree. +**/ +VOID +MakeLen ( + IN INT32 Root + ) +{ + INT32 LoopVar1; + + INT32 LoopVar2; + UINT32 Cum; + + for (LoopVar1 = 0; LoopVar1 <= 16; LoopVar1++) { + mLenCnt[LoopVar1] = 0; + } + + CountLen (Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) { + Cum += mLenCnt[LoopVar1] << (16 - LoopVar1); + } + + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (LoopVar1 = 15; LoopVar1 > 0; LoopVar1--) { + if (mLenCnt[LoopVar1] != 0) { + mLenCnt[LoopVar1]--; + mLenCnt[LoopVar1 + 1] += 2; + break; + } + } + + Cum--; + } + + for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) { + LoopVar2 = mLenCnt[LoopVar1]; + LoopVar2--; + while (LoopVar2 >= 0) { + mLen[*mSortPtr++] = (UINT8) LoopVar1; + LoopVar2--; + } + } +} + +/** + Assign code to each symbol based on the code length array. + + @param[in] LoopVar8 The number of symbols. + @param[in] Len The code length array. + @param[out] Code The stores codes for each symbol. +**/ +VOID +MakeCode ( + IN INT32 LoopVar8, + IN UINT8 Len[ ], + OUT UINT16 Code[ ] + ) +{ + INT32 LoopVar1; + UINT16 Start[18]; + + Start[1] = 0; + for (LoopVar1 = 1; LoopVar1 <= 16; LoopVar1++) { + Start[LoopVar1 + 1] = (UINT16) ((Start[LoopVar1] + mLenCnt[LoopVar1]) << 1); + } + + for (LoopVar1 = 0; LoopVar1 < LoopVar8; LoopVar1++) { + Code[LoopVar1] = Start[Len[LoopVar1]]++; + } +} + +/** + Generates Huffman codes given a frequency distribution of symbols. + + @param[in] NParm The number of symbols. + @param[in] FreqParm The frequency of each symbol. + @param[out] LenParm The code length for each symbol. + @param[out] CodeParm The code for each symbol. + + @return The root of the Huffman tree. +**/ +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[ ], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[ ] + ) +{ + INT32 LoopVar1; + + INT32 LoopVar2; + + INT32 LoopVar3; + + INT32 Avail; + + // + // make tree, calculate len[], return root + // + mTempInt32 = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mTempInt32; + mHeapSize = 0; + mHeap[1] = 0; + for (LoopVar1 = 0; LoopVar1 < mTempInt32; LoopVar1++) { + mLen[LoopVar1] = 0; + if ((mFreq[LoopVar1]) != 0) { + mHeapSize++; + mHeap[mHeapSize] = (INT16) LoopVar1; + } + } + + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + + for (LoopVar1 = mHeapSize / 2; LoopVar1 >= 1; LoopVar1--) { + // + // make priority queue + // + DownHeap (LoopVar1); + } + + mSortPtr = CodeParm; + do { + LoopVar1 = mHeap[1]; + if (LoopVar1 < mTempInt32) { + *mSortPtr++ = (UINT16) LoopVar1; + } + + mHeap[1] = mHeap[mHeapSize--]; + DownHeap (1); + LoopVar2 = mHeap[1]; + if (LoopVar2 < mTempInt32) { + *mSortPtr++ = (UINT16) LoopVar2; + } + + LoopVar3 = Avail++; + mFreq[LoopVar3] = (UINT16) (mFreq[LoopVar1] + mFreq[LoopVar2]); + mHeap[1] = (INT16) LoopVar3; + DownHeap (1); + mLeft[LoopVar3] = (UINT16) LoopVar1; + mRight[LoopVar3] = (UINT16) LoopVar2; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen (LoopVar3); + MakeCode (NParm, LenParm, CodeParm); + + // + // return root + // + return LoopVar3; +} + +/** + Outputs rightmost LoopVar8 bits of x + + @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used. + @param[in] x The data. +**/ +VOID +PutBits ( + IN INT32 LoopVar8, + IN UINT32 x + ) +{ + UINT8 Temp; + + if (LoopVar8 < mBitCount) { + mSubBitBuf |= x << (mBitCount -= LoopVar8); + } else { + + Temp = (UINT8)(mSubBitBuf | (x >> (LoopVar8 -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + if (LoopVar8 < UINT8_BIT) { + mSubBitBuf = x << (mBitCount = UINT8_BIT - LoopVar8); + } else { + + Temp = (UINT8)(x >> (LoopVar8 - UINT8_BIT)); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - LoopVar8); + } + } +} + +/** + Encode a signed 32 bit number. + + @param[in] LoopVar5 The number to encode. +**/ +VOID +EncodeC ( + IN INT32 LoopVar5 + ) +{ + PutBits (mCLen[LoopVar5], mCCode[LoopVar5]); +} + +/** + Encode a unsigned 32 bit number. + + @param[in] LoopVar7 The number to encode. +**/ +VOID +EncodeP ( + IN UINT32 LoopVar7 + ) +{ + UINT32 LoopVar5; + + UINT32 LoopVar6; + + LoopVar5 = 0; + LoopVar6 = LoopVar7; + while (LoopVar6 != 0) { + LoopVar6 >>= 1; + LoopVar5++; + } + + PutBits (mPTLen[LoopVar5], mPTCode[LoopVar5]); + if (LoopVar5 > 1) { + PutBits(LoopVar5 - 1, LoopVar7 & (0xFFFFU >> (17 - LoopVar5))); + } +} + +/** + Count the frequencies for the Extra Set. + +**/ +VOID +CountTFreq ( + VOID + ) +{ + INT32 LoopVar1; + + INT32 LoopVar3; + + INT32 LoopVar8; + + INT32 Count; + + for (LoopVar1 = 0; LoopVar1 < NT; LoopVar1++) { + mTFreq[LoopVar1] = 0; + } + + LoopVar8 = NC; + while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) { + LoopVar8--; + } + + LoopVar1 = 0; + while (LoopVar1 < LoopVar8) { + LoopVar3 = mCLen[LoopVar1++]; + if (LoopVar3 == 0) { + Count = 1; + while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) { + LoopVar1++; + Count++; + } + + if (Count <= 2) { + mTFreq[0] = (UINT16) (mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + ASSERT((LoopVar3+2)<(2 * NT - 1)); + mTFreq[LoopVar3 + 2]++; + } + } +} + +/** + Outputs the code length array for the Extra Set or the Position Set. + + @param[in] LoopVar8 The number of symbols. + @param[in] nbit The number of bits needed to represent 'LoopVar8'. + @param[in] Special The special symbol that needs to be take care of. + +**/ +VOID +WritePTLen ( + IN INT32 LoopVar8, + IN INT32 nbit, + IN INT32 Special + ) +{ + INT32 LoopVar1; + + INT32 LoopVar3; + + while (LoopVar8 > 0 && mPTLen[LoopVar8 - 1] == 0) { + LoopVar8--; + } + + PutBits (nbit, LoopVar8); + LoopVar1 = 0; + while (LoopVar1 < LoopVar8) { + LoopVar3 = mPTLen[LoopVar1++]; + if (LoopVar3 <= 6) { + PutBits (3, LoopVar3); + } else { + PutBits (LoopVar3 - 3, (1U << (LoopVar3 - 3)) - 2); + } + + if (LoopVar1 == Special) { + while (LoopVar1 < 6 && mPTLen[LoopVar1] == 0) { + LoopVar1++; + } + + PutBits (2, (LoopVar1 - 3) & 3); + } + } +} + +/** + Outputs the code length array for Char&Length Set. +**/ +VOID +WriteCLen ( + VOID + ) +{ + INT32 LoopVar1; + + INT32 LoopVar3; + + INT32 LoopVar8; + + INT32 Count; + + LoopVar8 = NC; + while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) { + LoopVar8--; + } + + PutBits (CBIT, LoopVar8); + LoopVar1 = 0; + while (LoopVar1 < LoopVar8) { + LoopVar3 = mCLen[LoopVar1++]; + if (LoopVar3 == 0) { + Count = 1; + while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) { + LoopVar1++; + Count++; + } + + if (Count <= 2) { + for (LoopVar3 = 0; LoopVar3 < Count; LoopVar3++) { + PutBits (mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, Count - 3); + } else if (Count == 19) { + PutBits (mPTLen[0], mPTCode[0]); + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, 15); + } else { + PutBits (mPTLen[2], mPTCode[2]); + PutBits (CBIT, Count - 20); + } + } else { + ASSERT((LoopVar3+2)= NC) { + CountTFreq (); + Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen (NT, TBIT, 3); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, Root); + } + + WriteCLen (); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, 0); + PutBits (CBIT, 0); + PutBits (CBIT, Root); + } + + Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen (NP, PBIT, -1); + } else { + PutBits (PBIT, 0); + PutBits (PBIT, Root); + } + + Pos = 0; + for (LoopVar1 = 0; LoopVar1 < Size; LoopVar1++) { + if (LoopVar1 % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + if ((Flags & (1U << (UINT8_BIT - 1))) != 0){ + EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); + LoopVar3 = mBuf[Pos++] << UINT8_BIT; + LoopVar3 += mBuf[Pos++]; + + EncodeP (LoopVar3); + } else { + EncodeC (mBuf[Pos++]); + } + } + + SetMem (mCFreq, NC * sizeof (UINT16), 0); + SetMem (mPFreq, NP * sizeof (UINT16), 0); +} + +/** + Start the huffman encoding. + +**/ +VOID +HufEncodeStart ( + VOID + ) +{ + SetMem (mCFreq, NC * sizeof (UINT16), 0); + SetMem (mPFreq, NP * sizeof (UINT16), 0); + + mOutputPos = mOutputMask = 0; + + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +/** + Outputs an Original Character or a Pointer. + + @param[in] LoopVar5 The original character or the 'String Length' element of + a Pointer. + @param[in] LoopVar7 The 'Position' field of a Pointer. +**/ +VOID +CompressOutput ( + IN UINT32 LoopVar5, + IN UINT32 LoopVar7 + ) +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { + SendBlock (); + mOutputPos = 0; + } + + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + mBuf[mOutputPos++] = (UINT8) LoopVar5; + mCFreq[LoopVar5]++; + if (LoopVar5 >= (1U << UINT8_BIT)) { + mBuf[CPos] = (UINT8)(mBuf[CPos]|mOutputMask); + mBuf[mOutputPos++] = (UINT8)(LoopVar7 >> UINT8_BIT); + mBuf[mOutputPos++] = (UINT8) LoopVar7; + LoopVar5 = 0; + while (LoopVar7!=0) { + LoopVar7 >>= 1; + LoopVar5++; + } + mPFreq[LoopVar5]++; + } +} + +/** + End the huffman encoding. + +**/ +VOID +HufEncodeEnd ( + VOID + ) +{ + SendBlock (); + + // + // Flush remaining bits + // + PutBits (UINT8_BIT - 1, 0); +} + +/** + The main controlling routine for compression process. + + @retval EFI_SUCCESS The compression is successful. + @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process. +**/ +EFI_STATUS +Encode ( + VOID + ) +{ + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory (); + if (EFI_ERROR (Status)) { + FreeMemory (); + return Status; + } + + InitSlide (); + + HufEncodeStart (); + + mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + if (!GetNextMatch ()) { + Status = EFI_OUT_OF_RESOURCES; + } + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + CompressOutput(mText[mPos - 1], 0); + } else { + // + // Outputting a pointer is beneficial enough, do it. + // + + CompressOutput(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); + LastMatchLen--; + while (LastMatchLen > 0) { + if (!GetNextMatch ()) { + Status = EFI_OUT_OF_RESOURCES; + } + LastMatchLen--; + } + + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd (); + FreeMemory (); + return (Status); +} + +/** + The compression routine. + + @param[in] SrcBuffer The buffer containing the source data. + @param[in] SrcSize Number of bytes in SrcBuffer. + @param[in] DstBuffer The buffer to put the compressed image in. + @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on + return the number of bytes placed in DstBuffer. + + @retval EFI_SUCCESS The compression was sucessful. + @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required. +**/ +EFI_STATUS +Compress ( + IN VOID *SrcBuffer, + IN UINT64 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT64 *DstSize + ) +{ + EFI_STATUS Status; + + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + + mSrc = SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst +*DstSize; + + PutDword (0L); + PutDword (0L); + + MakeCrcTable (); + + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + Status = Encode (); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword (mCompSize + 1); + PutDword (mOrigSize); + + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } + +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h new file mode 100644 index 0000000..b76a151 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h @@ -0,0 +1,39 @@ +/** @file + Header file for compression routine. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_SHELL_COMPRESS_H_ +#define _EFI_SHELL_COMPRESS_H_ + +/** + The compression routine. + + @param[in] SrcBuffer The buffer containing the source data. + @param[in] SrcSize Number of bytes in SrcBuffer. + @param[in] DstBuffer The buffer to put the compressed image in. + @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on + return the number of bytes placed in DstBuffer. + + @retval EFI_SUCCESS The compression was sucessful. + @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required. +**/ +EFI_STATUS +Compress ( + IN VOID *SrcBuffer, + IN UINT64 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT64 *DstSize + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c new file mode 100644 index 0000000..a79c9f9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c @@ -0,0 +1,207 @@ +/** @file + Main file for Dblk shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include + +/** + Display blocks to the screen. + + @param[in] DevPath The device path to get the blocks from. + @param[in] Lba The Lba number to start from. + @param[in] BlockCount How many blocks to display. + + @retval SHELL_SUCCESS The display was successful. +**/ +SHELL_STATUS +DisplayTheBlocks( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath, + IN CONST UINT64 Lba, + IN CONST UINT8 BlockCount + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_HANDLE BlockIoHandle; + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + UINT8 *Buffer; + UINT8 *OriginalBuffer; + UINTN BufferSize; + + ShellStatus = SHELL_SUCCESS; + + Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, (EFI_DEVICE_PATH_PROTOCOL **)&DevPath, &BlockIoHandle); + if (EFI_ERROR(Status)) { + return (SHELL_NOT_FOUND); + } + + Status = gBS->OpenProtocol(BlockIoHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + return (SHELL_NOT_FOUND); + } + + BufferSize = BlockIo->Media->BlockSize * BlockCount; + if(BlockIo->Media->IoAlign == 0) { + BlockIo->Media->IoAlign = 1; + } + + if (BufferSize > 0) { + OriginalBuffer = AllocateZeroPool(BufferSize + BlockIo->Media->IoAlign); + Buffer = ALIGN_POINTER (OriginalBuffer,BlockIo->Media->IoAlign); + } else { + ShellPrintEx(-1,-1,L" BlockSize: 0x%08x, BlockCount: 0x%08x\r\n", BlockIo->Media->BlockSize, BlockCount); + OriginalBuffer = NULL; + Buffer = NULL; + } + + Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, BufferSize, Buffer); + if (!EFI_ERROR(Status) && Buffer != NULL) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DBLK_HEADER), + gShellDebug1HiiHandle, + Lba, + BufferSize, + BlockIo + ); + + DumpHex(2,0,BufferSize,Buffer); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_READ_FAIL), gShellDebug1HiiHandle, L"dblk", L"BlockIo"); + ShellStatus = SHELL_DEVICE_ERROR; + } + + if (OriginalBuffer != NULL) { + FreePool (OriginalBuffer); + } + + gBS->CloseProtocol(BlockIoHandle, &gEfiBlockIoProtocolGuid, gImageHandle, NULL); + return (ShellStatus); +} + +/** + Function for 'dblk' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDblk ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *BlockName; + CONST CHAR16 *LbaString; + CONST CHAR16 *BlockCountString; + UINT64 Lba; + UINT64 BlockCount; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dblk", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dblk"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"dblk"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Parse the params + // + BlockName = ShellCommandLineGetRawValue(Package, 1); + LbaString = ShellCommandLineGetRawValue(Package, 2); + BlockCountString = ShellCommandLineGetRawValue(Package, 3); + + if (LbaString == NULL) { + Lba = 0; + } else { + if (!ShellIsHexOrDecimalNumber(LbaString, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", LbaString); + ShellStatus = SHELL_INVALID_PARAMETER; + } + ShellConvertStringToUint64(LbaString, &Lba, TRUE, FALSE); + } + + if (BlockCountString == NULL) { + BlockCount = 1; + } else { + if (!ShellIsHexOrDecimalNumber(BlockCountString, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", BlockCountString); + ShellStatus = SHELL_INVALID_PARAMETER; + } + ShellConvertStringToUint64(BlockCountString, &BlockCount, TRUE, FALSE); + if (BlockCount > 0x10) { + BlockCount = 0x10; + } else if (BlockCount == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", BlockCountString); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // do the work if we have a valid block identifier + // + if (gEfiShellProtocol->GetDevicePathFromMap(BlockName) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", BlockName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + DevPath = (EFI_DEVICE_PATH_PROTOCOL*)gEfiShellProtocol->GetDevicePathFromMap(BlockName); + if (gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &DevPath, NULL) == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MAP_PROTOCOL), gShellDebug1HiiHandle, L"dblk", BlockName, L"BlockIo"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellStatus = DisplayTheBlocks(gEfiShellProtocol->GetDevicePathFromMap(BlockName), Lba, (UINT8)BlockCount); + } + } + } + } + + ShellCommandLineFreeVarList (Package); + } + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c new file mode 100644 index 0000000..93f6c03 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c @@ -0,0 +1,233 @@ +/** @file + Main file for Dmem shell Debug1 function. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include +#include +#include +#include +#include + +/** + Make a printable character. + + If Char is printable then return it, otherwise return a question mark. + + @param[in] Char The character to make printable. + + @return A printable character representing Char. +**/ +CHAR16 +MakePrintable( + IN CONST CHAR16 Char + ) +{ + if ((Char < 0x20 && Char > 0)||(Char > 126)) { + return (L'?'); + } + return (Char); +} + +/** + Display some Memory-Mapped-IO memory. + + @param[in] Address The starting address to display. + @param[in] Size The length of memory to display. +**/ +SHELL_STATUS +DisplayMmioMemory( + IN CONST VOID *Address, + IN CONST UINTN Size + ) +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRbIo; + EFI_STATUS Status; + VOID *Buffer; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + + Status = gBS->LocateProtocol(&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID**)&PciRbIo); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"dmem"); + return (SHELL_NOT_FOUND); + } + Buffer = AllocateZeroPool(Size); + if (Buffer == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + + Status = PciRbIo->Mem.Read(PciRbIo, EfiPciWidthUint8, (UINT64)(UINTN)Address, Size, Buffer); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_ER), gShellDebug1HiiHandle, L"dmem"); + ShellStatus = SHELL_NOT_FOUND; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMEM_MMIO_HEADER_ROW), gShellDebug1HiiHandle, (UINT64)(UINTN)Address, Size); + DumpHex(2, (UINTN)Address, Size, Buffer); + } + + FreePool(Buffer); + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-mmio", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'dmem' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDmem ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + VOID *Address; + UINT64 Size; + CONST CHAR16 *Temp1; + UINT64 AcpiTableAddress; + UINT64 Acpi20TableAddress; + UINT64 SalTableAddress; + UINT64 SmbiosTableAddress; + UINT64 MpsTableAddress; + UINTN TableWalker; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Address = NULL; + Size = 0; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmem", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmem"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Temp1 = ShellCommandLineGetRawValue(Package, 1); + if (Temp1 == NULL) { + Address = gST; + Size = sizeof (*gST); + } else { + if (!ShellIsHexOrDecimalNumber(Temp1, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp1, (UINT64*)&Address, TRUE, FALSE))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmem", Temp1); + ShellStatus = SHELL_INVALID_PARAMETER; + } + Temp1 = ShellCommandLineGetRawValue(Package, 2); + if (Temp1 == NULL) { + Size = 512; + } else { + if (!ShellIsHexOrDecimalNumber(Temp1, FALSE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp1, &Size, TRUE, FALSE))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmem", Temp1); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (!ShellCommandLineGetFlag(Package, L"-mmio")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMEM_HEADER_ROW), gShellDebug1HiiHandle, (UINT64)(UINTN)Address, Size); + DumpHex(2, (UINTN)Address, (UINTN)Size, Address); + if (Address == (VOID*)gST) { + Acpi20TableAddress = 0; + AcpiTableAddress = 0; + SalTableAddress = 0; + SmbiosTableAddress = 0; + MpsTableAddress = 0; + for (TableWalker = 0 ; TableWalker < gST->NumberOfTableEntries ; TableWalker++) { + if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiAcpi20TableGuid)) { + Acpi20TableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable; + continue; + } + if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiAcpi10TableGuid)) { + AcpiTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable; + continue; + } + if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiSalSystemTableGuid)) { + SalTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable; + continue; + } + if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiSmbiosTableGuid)) { + SmbiosTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable; + continue; + } + if (CompareGuid (&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiSmbios3TableGuid)) { + SmbiosTableAddress = (UINT64) (UINTN) gST->ConfigurationTable[TableWalker].VendorTable; + continue; + } + if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiMpsTableGuid)) { + MpsTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable; + continue; + } + } + + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMEM_SYSTEM_TABLE), gShellDebug1HiiHandle, + (UINT64)(UINTN)Address, + gST->Hdr.HeaderSize, + gST->Hdr.Revision, + (UINT64)(UINTN)gST->ConIn, + (UINT64)(UINTN)gST->ConOut, + (UINT64)(UINTN)gST->StdErr, + (UINT64)(UINTN)gST->RuntimeServices, + (UINT64)(UINTN)gST->BootServices, + SalTableAddress, + AcpiTableAddress, + Acpi20TableAddress, + MpsTableAddress, + SmbiosTableAddress + ); + } + } else { + ShellStatus = DisplayMmioMemory(Address, (UINTN)Size); + } + } + + + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c new file mode 100644 index 0000000..acfc8a3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c @@ -0,0 +1,865 @@ +/** @file + Main file for DmpStore shell Debug1 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" + +typedef enum { + DmpStoreDisplay, + DmpStoreDelete, + DmpStoreSave, + DmpStoreLoad +} DMP_STORE_TYPE; + +typedef struct { + UINT32 Signature; + CHAR16 *Name; + EFI_GUID Guid; + UINT32 Attributes; + UINT32 DataSize; + UINT8 *Data; + LIST_ENTRY Link; +} DMP_STORE_VARIABLE; + +#define DMP_STORE_VARIABLE_SIGNATURE SIGNATURE_32 ('_', 'd', 's', 's') + +/** + Base on the input attribute value to return the attribute string. + + @param[in] Atts The input attribute value + + @retval The attribute string info. +**/ +CHAR16 * +GetAttrType ( + IN CONST UINT32 Atts + ) +{ + UINTN BufLen; + CHAR16 *RetString; + + BufLen = 0; + RetString = NULL; + + if ((Atts & EFI_VARIABLE_NON_VOLATILE) != 0) { + StrnCatGrow (&RetString, &BufLen, L"+NV", 0); + } + if ((Atts & EFI_VARIABLE_RUNTIME_ACCESS) != 0) { + StrnCatGrow (&RetString, &BufLen, L"+RT+BS", 0); + } else if ((Atts & EFI_VARIABLE_BOOTSERVICE_ACCESS) != 0) { + StrnCatGrow (&RetString, &BufLen, L"+BS", 0); + } + if ((Atts & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) { + StrnCatGrow (&RetString, &BufLen, L"+HR", 0); + } + if ((Atts & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) { + StrnCatGrow (&RetString, &BufLen, L"+AW", 0); + } + if ((Atts & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + StrnCatGrow (&RetString, &BufLen, L"+AT", 0); + } + + if (RetString == NULL) { + RetString = StrnCatGrow(&RetString, &BufLen, L"Invalid", 0); + } + + if ((RetString != NULL) && (RetString[0] == L'+')) { + CopyMem(RetString, RetString + 1, StrSize(RetString + 1)); + } + + return RetString; +} + +/** + Convert binary to hex format string. + + @param[in] Buffer The binary data. + @param[in] BufferSize The size in bytes of the binary data. + @param[in, out] HexString Hex format string. + @param[in] HexStringSize The size in bytes of the string. + + @return The hex format string. +**/ +CHAR16* +BinaryToHexString ( + IN VOID *Buffer, + IN UINTN BufferSize, + IN OUT CHAR16 *HexString, + IN UINTN HexStringSize + ) +{ + UINTN Index; + UINTN StringIndex; + + ASSERT (Buffer != NULL); + ASSERT ((BufferSize * 2 + 1) * sizeof (CHAR16) <= HexStringSize); + + for (Index = 0, StringIndex = 0; Index < BufferSize; Index += 1) { + StringIndex += + UnicodeSPrint ( + &HexString[StringIndex], + HexStringSize - StringIndex * sizeof (CHAR16), + L"%02x", + ((UINT8 *) Buffer)[Index] + ); + } + return HexString; +} + +/** + Load the variable data from file and set to variable data base. + + @param[in] FileHandle The file to be read. + @param[in] Name The name of the variables to be loaded. + @param[in] Guid The guid of the variables to be loaded. + @param[out] Found TRUE when at least one variable was loaded and set. + + @retval SHELL_DEVICE_ERROR Cannot access the file. + @retval SHELL_VOLUME_CORRUPTED The file is in bad format. + @retval SHELL_OUT_OF_RESOURCES There is not enough memory to perform the operation. + @retval SHELL_SUCCESS Successfully load and set the variables. +**/ +SHELL_STATUS +LoadVariablesFromFile ( + IN SHELL_FILE_HANDLE FileHandle, + IN CONST CHAR16 *Name, + IN CONST EFI_GUID *Guid, + OUT BOOLEAN *Found + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + UINT32 NameSize; + UINT32 DataSize; + UINTN BufferSize; + UINTN RemainingSize; + UINT64 Position; + UINT64 FileSize; + LIST_ENTRY List; + DMP_STORE_VARIABLE *Variable; + LIST_ENTRY *Link; + CHAR16 *Attributes; + UINT8 *Buffer; + UINT32 Crc32; + + Status = ShellGetFileSize (FileHandle, &FileSize); + if (EFI_ERROR (Status)) { + return SHELL_DEVICE_ERROR; + } + + ShellStatus = SHELL_SUCCESS; + + InitializeListHead (&List); + + Position = 0; + while (Position < FileSize) { + // + // NameSize + // + BufferSize = sizeof (NameSize); + Status = ShellReadFile (FileHandle, &BufferSize, &NameSize); + if (EFI_ERROR (Status) || (BufferSize != sizeof (NameSize))) { + ShellStatus = SHELL_VOLUME_CORRUPTED; + break; + } + + // + // DataSize + // + BufferSize = sizeof (DataSize); + Status = ShellReadFile (FileHandle, &BufferSize, &DataSize); + if (EFI_ERROR (Status) || (BufferSize != sizeof (DataSize))) { + ShellStatus = SHELL_VOLUME_CORRUPTED; + break; + } + + // + // Name, Guid, Attributes, Data, Crc32 + // + RemainingSize = NameSize + sizeof (EFI_GUID) + sizeof (UINT32) + DataSize + sizeof (Crc32); + BufferSize = sizeof (NameSize) + sizeof (DataSize) + RemainingSize; + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + break; + } + BufferSize = RemainingSize; + Status = ShellReadFile (FileHandle, &BufferSize, (UINT32 *) Buffer + 2); + if (EFI_ERROR (Status) || (BufferSize != RemainingSize)) { + ShellStatus = SHELL_VOLUME_CORRUPTED; + FreePool (Buffer); + break; + } + + // + // Check Crc32 + // + * (UINT32 *) Buffer = NameSize; + * ((UINT32 *) Buffer + 1) = DataSize; + BufferSize = RemainingSize + sizeof (NameSize) + sizeof (DataSize) - sizeof (Crc32); + gBS->CalculateCrc32 ( + Buffer, + BufferSize, + &Crc32 + ); + if (Crc32 != * (UINT32 *) (Buffer + BufferSize)) { + FreePool (Buffer); + ShellStatus = SHELL_VOLUME_CORRUPTED; + break; + } + + Position += BufferSize + sizeof (Crc32); + + Variable = AllocateZeroPool (sizeof (*Variable) + NameSize + DataSize); + if (Variable == NULL) { + FreePool (Buffer); + ShellStatus = SHELL_OUT_OF_RESOURCES; + break; + } + Variable->Signature = DMP_STORE_VARIABLE_SIGNATURE; + Variable->Name = (CHAR16 *) (Variable + 1); + Variable->DataSize = DataSize; + Variable->Data = (UINT8 *) Variable->Name + NameSize; + CopyMem (Variable->Name, Buffer + sizeof (NameSize) + sizeof (DataSize), NameSize); + CopyMem (&Variable->Guid, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize, sizeof (EFI_GUID)); + CopyMem (&Variable->Attributes, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID), sizeof (UINT32)); + CopyMem (Variable->Data, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID) + sizeof (UINT32), DataSize); + + InsertTailList (&List, &Variable->Link); + FreePool (Buffer); + } + + if ((Position != FileSize) || (ShellStatus != SHELL_SUCCESS)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_BAD_FILE), gShellDebug1HiiHandle, L"dmpstore"); + if (Position != FileSize) { + ShellStatus = SHELL_VOLUME_CORRUPTED; + } + } + + for ( Link = GetFirstNode (&List) + ; !IsNull (&List, Link) && (ShellStatus == SHELL_SUCCESS) + ; Link = GetNextNode (&List, Link) + ) { + Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE); + + if (((Name == NULL) || gUnicodeCollation->MetaiMatch (gUnicodeCollation, Variable->Name, (CHAR16 *) Name)) && + ((Guid == NULL) || CompareGuid (&Variable->Guid, Guid)) + ) { + Attributes = GetAttrType (Variable->Attributes); + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN(STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle, + Attributes, &Variable->Guid, Variable->Name, Variable->DataSize + ); + SHELL_FREE_NON_NULL(Attributes); + + *Found = TRUE; + Status = gRT->SetVariable ( + Variable->Name, + &Variable->Guid, + Variable->Attributes, + Variable->DataSize, + Variable->Data + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_GEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", Variable->Name, Status); + } + } + } + + for (Link = GetFirstNode (&List); !IsNull (&List, Link); ) { + Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE); + Link = RemoveEntryList (&Variable->Link); + FreePool (Variable); + } + + return ShellStatus; +} + +/** + Append one variable to file. + + @param[in] FileHandle The file to be appended. + @param[in] Name The variable name. + @param[in] Guid The variable GUID. + @param[in] Attributes The variable attributes. + @param[in] DataSize The variable data size. + @param[in] Data The variable data. + + @retval EFI_OUT_OF_RESOURCES There is not enough memory to perform the operation. + @retval EFI_SUCCESS The variable is appended to file successfully. + @retval others Failed to append the variable to file. +**/ +EFI_STATUS +AppendSingleVariableToFile ( + IN SHELL_FILE_HANDLE FileHandle, + IN CONST CHAR16 *Name, + IN CONST EFI_GUID *Guid, + IN UINT32 Attributes, + IN UINT32 DataSize, + IN CONST UINT8 *Data + ) +{ + UINT32 NameSize; + UINT8 *Buffer; + UINT8 *Ptr; + UINTN BufferSize; + EFI_STATUS Status; + + NameSize = (UINT32) StrSize (Name); + BufferSize = sizeof (NameSize) + sizeof (DataSize) + + sizeof (*Guid) + + sizeof (Attributes) + + NameSize + DataSize + + sizeof (UINT32); + + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = Buffer; + // + // NameSize and DataSize + // + * (UINT32 *) Ptr = NameSize; + Ptr += sizeof (NameSize); + *(UINT32 *) Ptr = DataSize; + Ptr += sizeof (DataSize); + + // + // Name + // + CopyMem (Ptr, Name, NameSize); + Ptr += NameSize; + + // + // Guid + // + CopyMem (Ptr, Guid, sizeof (*Guid)); + Ptr += sizeof (*Guid); + + // + // Attributes + // + * (UINT32 *) Ptr = Attributes; + Ptr += sizeof (Attributes); + + // + // Data + // + CopyMem (Ptr, Data, DataSize); + Ptr += DataSize; + + // + // Crc32 + // + gBS->CalculateCrc32 (Buffer, (UINTN) Ptr - (UINTN) Buffer, (UINT32 *) Ptr); + + Status = ShellWriteFile (FileHandle, &BufferSize, Buffer); + FreePool (Buffer); + + if (!EFI_ERROR (Status) && + (BufferSize != sizeof (NameSize) + sizeof (DataSize) + sizeof (*Guid) + sizeof (Attributes) + NameSize + DataSize + sizeof (UINT32)) + ) { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Recursive function to display or delete variables. + + This function will call itself to create a stack-based list of allt he variables to process, + then fromt he last to the first, they will do either printing or deleting. + + This is necessary since once a delete happens GetNextVariableName() will work. + + @param[in] Name The variable name of the EFI variable (or NULL). + @param[in] Guid The GUID of the variable set (or NULL). + @param[in] Type The operation type. + @param[in] FileHandle The file to operate on (or NULL). + @param[in] PrevName The previous variable name from GetNextVariableName. L"" to start. + @param[in] FoundVarGuid The previous GUID from GetNextVariableName. ignored at start. + @param[in] FoundOne If a VariableName or Guid was specified and one was printed or + deleted, then set this to TRUE, otherwise ignored. + @param[in] StandardFormatOutput TRUE indicates Standard-Format Output. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed. + @retval SHELL_ABORTED The abort message was received. + @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error. + @retval SHELL_NOT_FOUND the Name/Guid pair could not be found. +**/ +SHELL_STATUS +CascadeProcessVariables ( + IN CONST CHAR16 *Name OPTIONAL, + IN CONST EFI_GUID *Guid OPTIONAL, + IN DMP_STORE_TYPE Type, + IN EFI_FILE_PROTOCOL *FileHandle OPTIONAL, + IN CONST CHAR16 * CONST PrevName, + IN EFI_GUID FoundVarGuid, + IN BOOLEAN *FoundOne, + IN BOOLEAN StandardFormatOutput + ) +{ + EFI_STATUS Status; + CHAR16 *FoundVarName; + UINT8 *DataBuffer; + UINTN DataSize; + UINT32 Atts; + SHELL_STATUS ShellStatus; + UINTN NameSize; + CHAR16 *AttrString; + CHAR16 *HexString; + EFI_STATUS SetStatus; + CONST CHAR16 *GuidName; + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + NameSize = 0; + FoundVarName = NULL; + + if (PrevName!=NULL) { + StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0); + } else { + FoundVarName = AllocateZeroPool(sizeof(CHAR16)); + NameSize = sizeof(CHAR16); + } + + Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid); + if (Status == EFI_BUFFER_TOO_SMALL) { + SHELL_FREE_NON_NULL(FoundVarName); + FoundVarName = AllocateZeroPool (NameSize); + if (FoundVarName != NULL) { + if (PrevName != NULL) { + StrnCpyS(FoundVarName, NameSize/sizeof(CHAR16), PrevName, NameSize/sizeof(CHAR16) - 1); + } + + Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } + + // + // No more is fine. + // + if (Status == EFI_NOT_FOUND) { + SHELL_FREE_NON_NULL(FoundVarName); + return (SHELL_SUCCESS); + } else if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(FoundVarName); + return (SHELL_DEVICE_ERROR); + } + + // + // Recurse to the next iteration. We know "our" variable's name. + // + ShellStatus = CascadeProcessVariables (Name, Guid, Type, FileHandle, FoundVarName, FoundVarGuid, FoundOne, StandardFormatOutput); + + if (ShellGetExecutionBreakFlag() || (ShellStatus == SHELL_ABORTED)) { + SHELL_FREE_NON_NULL(FoundVarName); + return (SHELL_ABORTED); + } + + // + // No matter what happened we process our own variable + // Only continue if Guid and VariableName are each either NULL or a match + // + if ( ( Name == NULL + || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*) Name) ) + && ( Guid == NULL + || CompareGuid(&FoundVarGuid, Guid) ) + ) { + DataSize = 0; + DataBuffer = NULL; + // + // do the print or delete + // + *FoundOne = TRUE; + Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + SHELL_FREE_NON_NULL (DataBuffer); + DataBuffer = AllocatePool (DataSize); + if (DataBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer); + } + } + // + // Last error check then print this variable out. + // + if (Type == DmpStoreDisplay) { + if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) { + AttrString = GetAttrType(Atts); + if (StandardFormatOutput) { + HexString = AllocatePool ((DataSize * 2 + 1) * sizeof (CHAR16)); + if (HexString != NULL) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_VAR_SFO), gShellDebug1HiiHandle, + FoundVarName, &FoundVarGuid, Atts, DataSize, + BinaryToHexString ( + DataBuffer, DataSize, HexString, (DataSize * 2 + 1) * sizeof (CHAR16) + ) + ); + FreePool (HexString); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + } else { + Status = gEfiShellProtocol->GetGuidName(&FoundVarGuid, &GuidName); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle, + AttrString, &FoundVarGuid, FoundVarName, DataSize + ); + } else { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE2), gShellDebug1HiiHandle, + AttrString, GuidName, FoundVarName, DataSize + ); + } + DumpHex (2, 0, DataSize, DataBuffer); + } + SHELL_FREE_NON_NULL (AttrString); + } + } else if (Type == DmpStoreSave) { + if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) { + AttrString = GetAttrType (Atts); + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle, + AttrString, &FoundVarGuid, FoundVarName, DataSize + ); + Status = AppendSingleVariableToFile ( + FileHandle, + FoundVarName, + &FoundVarGuid, + Atts, + (UINT32) DataSize, + DataBuffer + ); + SHELL_FREE_NON_NULL (AttrString); + } + } else if (Type == DmpStoreDelete) { + // + // We only need name to delete it... + // + SetStatus = gRT->SetVariable (FoundVarName, &FoundVarGuid, Atts, 0, NULL); + if (StandardFormatOutput) { + if (SetStatus == EFI_SUCCESS) { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_NG_SFO), gShellDebug1HiiHandle, + FoundVarName, &FoundVarGuid + ); + } + } else { + ShellPrintHiiEx ( + -1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_DELETE_LINE), gShellDebug1HiiHandle, + &FoundVarGuid, FoundVarName, SetStatus + ); + } + } + SHELL_FREE_NON_NULL(DataBuffer); + } + + SHELL_FREE_NON_NULL(FoundVarName); + + if (Status == EFI_DEVICE_ERROR) { + ShellStatus = SHELL_DEVICE_ERROR; + } else if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_READY; + } + + return (ShellStatus); +} + +/** + Function to display or delete variables. This will set up and call into the recursive function. + + @param[in] Name The variable name of the EFI variable (or NULL). + @param[in] Guid The GUID of the variable set (or NULL). + @param[in] Type The operation type. + @param[in] FileHandle The file to save or load variables. + @param[in] StandardFormatOutput TRUE indicates Standard-Format Output. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed. + @retval SHELL_ABORTED The abort message was received. + @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error. + @retval SHELL_NOT_FOUND the Name/Guid pair could not be found. +**/ +SHELL_STATUS +ProcessVariables ( + IN CONST CHAR16 *Name OPTIONAL, + IN CONST EFI_GUID *Guid OPTIONAL, + IN DMP_STORE_TYPE Type, + IN SHELL_FILE_HANDLE FileHandle OPTIONAL, + IN BOOLEAN StandardFormatOutput + ) +{ + SHELL_STATUS ShellStatus; + BOOLEAN Found; + EFI_GUID FoundVarGuid; + + Found = FALSE; + ShellStatus = SHELL_SUCCESS; + ZeroMem (&FoundVarGuid, sizeof(EFI_GUID)); + + if (StandardFormatOutput) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_SFO_HEADER), gShellDebug1HiiHandle, L"dmpstore"); + } + + if (Type == DmpStoreLoad) { + ShellStatus = LoadVariablesFromFile (FileHandle, Name, Guid, &Found); + } else { + ShellStatus = CascadeProcessVariables (Name, Guid, Type, FileHandle, NULL, FoundVarGuid, &Found, StandardFormatOutput); + } + + if (!Found) { + if (ShellStatus == SHELL_OUT_OF_RESOURCES) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"dmpstore"); + return (ShellStatus); + } else if (Name != NULL && Guid == NULL) { + if (StandardFormatOutput) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N_SFO), gShellDebug1HiiHandle, Name); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, L"dmpstore", Name); + } + } else if (Name != NULL && Guid != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, L"dmpstore", Guid, Name); + } else if (Name == NULL && Guid == NULL) { + if (StandardFormatOutput) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_SFO), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND), gShellDebug1HiiHandle, L"dmpstore"); + } + } else if (Name == NULL && Guid != NULL) { + if (StandardFormatOutput) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G_SFO), gShellDebug1HiiHandle, Guid); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G), gShellDebug1HiiHandle, L"dmpstore", Guid); + } + } + return (SHELL_NOT_FOUND); + } + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-d", TypeFlag}, + {L"-l", TypeValue}, + {L"-s", TypeValue}, + {L"-all", TypeFlag}, + {L"-guid", TypeValue}, + {L"-sfo", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'dmpstore' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDmpStore ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + RETURN_STATUS RStatus; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *GuidStr; + CONST CHAR16 *File; + EFI_GUID *Guid; + EFI_GUID GuidData; + CONST CHAR16 *Name; + DMP_STORE_TYPE Type; + SHELL_FILE_HANDLE FileHandle; + EFI_FILE_INFO *FileInfo; + BOOLEAN StandardFormatOutput; + + ShellStatus = SHELL_SUCCESS; + Package = NULL; + FileHandle = NULL; + File = NULL; + Type = DmpStoreDisplay; + StandardFormatOutput = FALSE; + + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmpstore", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmpstore"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-all") && ShellCommandLineGetFlag(Package, L"-guid")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-all", L"-guid"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-l")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-d")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-sfo")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-sfo"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Determine the GUID to search for based on -all and -guid parameters + // + if (!ShellCommandLineGetFlag(Package, L"-all")) { + GuidStr = ShellCommandLineGetValue(Package, L"-guid"); + if (GuidStr != NULL) { + RStatus = StrToGuid (GuidStr, &GuidData); + if (RETURN_ERROR (RStatus) || (GuidStr[GUID_STRING_LENGTH] != L'\0')) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmpstore", GuidStr); + ShellStatus = SHELL_INVALID_PARAMETER; + } + Guid = &GuidData; + } else { + Guid = &gEfiGlobalVariableGuid; + } + } else { + Guid = NULL; + } + + // + // Get the Name of the variable to find + // + Name = ShellCommandLineGetRawValue(Package, 1); + + if (ShellStatus == SHELL_SUCCESS) { + if (ShellCommandLineGetFlag(Package, L"-s")) { + Type = DmpStoreSave; + File = ShellCommandLineGetValue(Package, L"-s"); + if (File == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR (Status)) { + // + // Delete existing file, but do not delete existing directory + // + FileInfo = ShellGetFileInfo (FileHandle); + if (FileInfo == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); + Status = EFI_DEVICE_ERROR; + } else { + if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File); + Status = EFI_INVALID_PARAMETER; + } else { + Status = ShellDeleteFile (&FileHandle); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_DELETE_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); + } + } + FreePool (FileInfo); + } + } else if (Status == EFI_NOT_FOUND) { + // + // Good when file doesn't exist + // + Status = EFI_SUCCESS; + } else { + // + // Otherwise it's bad. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); + } + + if (!EFI_ERROR (Status)) { + Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); + } + } + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if (ShellCommandLineGetFlag(Package, L"-l")) { + Type = DmpStoreLoad; + File = ShellCommandLineGetValue(Package, L"-l"); + if (File == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-l"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + FileInfo = ShellGetFileInfo (FileHandle); + if (FileInfo == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File); + ShellStatus = SHELL_DEVICE_ERROR; + } else { + if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File); + ShellStatus = SHELL_INVALID_PARAMETER; + } + FreePool (FileInfo); + } + } + } + } else if (ShellCommandLineGetFlag(Package, L"-d")) { + Type = DmpStoreDelete; + } + + if (ShellCommandLineGetFlag (Package,L"-sfo")) { + StandardFormatOutput = TRUE; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + if (Type == DmpStoreSave) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_SAVE), gShellDebug1HiiHandle, File); + } else if (Type == DmpStoreLoad) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD), gShellDebug1HiiHandle, File); + } + ShellStatus = ProcessVariables (Name, Guid, Type, FileHandle, StandardFormatOutput); + if ((Type == DmpStoreLoad) || (Type == DmpStoreSave)) { + ShellCloseFile (&FileHandle); + } + } + } + } + + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + return ShellStatus; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c new file mode 100644 index 0000000..73be5b2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c @@ -0,0 +1,162 @@ +/** @file + Main file for Edit shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "TextEditor.h" + +/** + Function for 'edit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEdit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CHAR16 *Buffer; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + LIST_ENTRY *Package; + CONST CHAR16 *Cwd; + CHAR16 *Nfs; + CHAR16 *Spot; + CONST CHAR16 *TempParam; +// SHELL_FILE_HANDLE TempHandle; + + Buffer = NULL; + ShellStatus = SHELL_SUCCESS; + Nfs = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"edit", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"edit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Cwd = gEfiShellProtocol->GetCurDir(NULL); + if (Cwd == NULL) { + Cwd = ShellGetEnvironmentVariable(L"path"); + if (Cwd != NULL) { + Nfs = StrnCatGrow(&Nfs, NULL, Cwd+3, 0); + if (Nfs != NULL) { + Spot = StrStr(Nfs, L";"); + if (Spot != NULL) { + *Spot = CHAR_NULL; + } + Spot = StrStr(Nfs, L"\\"); + if (Spot != NULL) { + Spot[1] = CHAR_NULL; + } + gEfiShellProtocol->SetCurDir(NULL, Nfs); + FreePool(Nfs); + } + } + } + + Status = MainEditorInit (); + + if (EFI_ERROR (Status)) { + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_INIT_FAILED), gShellDebug1HiiHandle); + } else { + MainEditorBackup (); + + // + // if editor launched with file named + // + if (ShellCommandLineGetCount(Package) == 2) { + TempParam = ShellCommandLineGetRawValue(Package, 1); + ASSERT(TempParam != NULL); + FileBufferSetFileName (TempParam); +// if (EFI_ERROR(ShellFileExists(MainEditor.FileBuffer->FileName))) { +// Status = ShellOpenFileByName(MainEditor.FileBuffer->FileName, &TempHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); +// if (!EFI_ERROR(Status)) { +// ShellCloseFile(&TempHandle); +// } +// } + } + + Status = FileBufferRead (MainEditor.FileBuffer->FileName, FALSE); + if (!EFI_ERROR (Status)) { + MainEditorRefresh (); + + Status = MainEditorKeyInput (); + } + + if (Status != EFI_OUT_OF_RESOURCES) { + // + // back up the status string + // + Buffer = CatSPrint (NULL, L"%s", StatusBarGetString()); + } + + MainEditorCleanup (); + + // + // print editor exit code on screen + // + if (Status == EFI_SUCCESS) { + } else if (Status == EFI_OUT_OF_RESOURCES) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"edit"); + } else { + if (Buffer != NULL) { + if (StrCmp (Buffer, L"") != 0) { + // + // print out the status string + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_BUFFER), gShellDebug1HiiHandle, Buffer); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle); + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle); + } + } + + if (Status != EFI_OUT_OF_RESOURCES) { + SHELL_FREE_NON_NULL (Buffer); + } + } + } + ShellCommandLineFreeVarList (Package); + } + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c new file mode 100644 index 0000000..856058a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c @@ -0,0 +1,3325 @@ +/** @file + Implements filebuffer interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "TextEditor.h" +#include +#include + +EFI_EDITOR_FILE_BUFFER FileBuffer; +EFI_EDITOR_FILE_BUFFER FileBufferBackupVar; + +// +// for basic initialization of FileBuffer +// +EFI_EDITOR_FILE_BUFFER FileBufferConst = { + NULL, + FileTypeUnicode, + NULL, + NULL, + 0, + { + 0, + 0 + }, + { + 0, + 0 + }, + { + 0, + 0 + }, + { + 0, + 0 + }, + FALSE, + TRUE, + FALSE, + NULL +}; + +// +// the whole edit area needs to be refreshed +// +BOOLEAN FileBufferNeedRefresh; + +// +// only the current line in edit area needs to be refresh +// +BOOLEAN FileBufferOnlyLineNeedRefresh; + +BOOLEAN FileBufferMouseNeedRefresh; + +extern BOOLEAN EditorMouseAction; + +/** + Initialization function for FileBuffer. + + @param EFI_SUCCESS The initialization was successful. + @param EFI_LOAD_ERROR A default name could not be created. + @param EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferInit ( + VOID + ) +{ + // + // basically initialize the FileBuffer + // + CopyMem (&FileBuffer , &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER)); + CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER)); + + // + // set default FileName + // + FileBuffer.FileName = EditGetDefaultFileName (L"txt"); + if (FileBuffer.FileName == NULL) { + return EFI_LOAD_ERROR; + } + + FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY)); + if (FileBuffer.ListHead == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + InitializeListHead (FileBuffer.ListHead); + + FileBuffer.DisplayPosition.Row = 2; + FileBuffer.DisplayPosition.Column = 1; + FileBuffer.LowVisibleRange.Row = 2; + FileBuffer.LowVisibleRange.Column = 1; + + FileBufferNeedRefresh = FALSE; + FileBufferMouseNeedRefresh = FALSE; + FileBufferOnlyLineNeedRefresh = FALSE; + + return EFI_SUCCESS; +} + +/** + Backup function for FileBuffer. Only backup the following items: + Mouse/Cursor position + File Name, Type, ReadOnly, Modified + Insert Mode + + This is for making the file buffer refresh as few as possible. + + @retval EFI_SUCCESS The backup operation was successful. +**/ +EFI_STATUS +FileBufferBackup ( + VOID + ) +{ + FileBufferBackupVar.MousePosition = FileBuffer.MousePosition; + + SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName); + FileBufferBackupVar.FileName = NULL; + FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0); + + FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert; + FileBufferBackupVar.FileType = FileBuffer.FileType; + + FileBufferBackupVar.FilePosition = FileBuffer.FilePosition; + FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange; + + FileBufferBackupVar.FileModified = FileBuffer.FileModified; + FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly; + + return EFI_SUCCESS; +} + +/** + Advance to the next Count lines + + @param[in] Count The line number to advance by. + @param[in] CurrentLine The pointer to the current line structure. + @param[in] LineList The pointer to the linked list of lines. + + @retval NULL There was an error. + @return The line structure after the advance. +**/ +EFI_EDITOR_LINE * +InternalEditorMiscLineAdvance ( + IN CONST UINTN Count, + IN CONST EFI_EDITOR_LINE *CurrentLine, + IN CONST LIST_ENTRY *LineList + ) + +{ + UINTN Index; + CONST EFI_EDITOR_LINE *Line; + + if (CurrentLine == NULL || LineList == NULL) { + return NULL; + } + + for (Line = CurrentLine, Index = 0; Index < Count; Index++) { + // + // if already last line + // + if (Line->Link.ForwardLink == LineList) { + return NULL; + } + + Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + } + + return ((EFI_EDITOR_LINE *)Line); +} + +/** + Retreat to the previous Count lines. + + @param[in] Count The line number to retreat by. + @param[in] CurrentLine The pointer to the current line structure. + @param[in] LineList The pointer to the linked list of lines. + + @retval NULL There was an error. + @return The line structure after the retreat. +**/ +EFI_EDITOR_LINE * +InternalEditorMiscLineRetreat ( + IN CONST UINTN Count, + IN CONST EFI_EDITOR_LINE *CurrentLine, + IN CONST LIST_ENTRY *LineList + ) + +{ + UINTN Index; + CONST EFI_EDITOR_LINE *Line; + + if (CurrentLine == NULL || LineList == NULL) { + return NULL; + } + + for (Line = CurrentLine, Index = 0; Index < Count; Index++) { + // + // already the first line + // + if (Line->Link.BackLink == LineList) { + return NULL; + } + + Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + } + + return ((EFI_EDITOR_LINE *)Line); +} + +/** + Advance/Retreat lines + + @param[in] Count line number to advance/retreat + >0 : advance + <0 : retreat + + @retval NULL An error occured. + @return The line after advance/retreat. +**/ +EFI_EDITOR_LINE * +MoveLine ( + IN CONST INTN Count + ) +{ + EFI_EDITOR_LINE *Line; + UINTN AbsCount; + + // + // if < 0, then retreat + // if > 0, the advance + // + if (Count <= 0) { + AbsCount = (UINTN)ABS(Count); + Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead); + } else { + Line = InternalEditorMiscLineAdvance ((UINTN)Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead); + } + + return Line; +} + +/** + Function to update the 'screen' to display the mouse position. + + @retval EFI_SUCCESS The backup operation was successful. +**/ +EFI_STATUS +FileBufferRestoreMousePosition ( + VOID + ) +{ + EFI_EDITOR_COLOR_UNION Orig; + EFI_EDITOR_COLOR_UNION New; + UINTN FRow; + UINTN FColumn; + BOOLEAN HasCharacter; + EFI_EDITOR_LINE *CurrentLine; + EFI_EDITOR_LINE *Line; + CHAR16 Value; + + // + // variable initialization + // + Line = NULL; + + if (MainEditor.MouseSupported) { + + if (FileBufferMouseNeedRefresh) { + + FileBufferMouseNeedRefresh = FALSE; + + // + // if mouse position not moved and only mouse action + // so do not need to refresh mouse position + // + if ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row && + FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column) + && EditorMouseAction) { + return EFI_SUCCESS; + } + // + // backup the old screen attributes + // + Orig = MainEditor.ColorAttributes; + New.Data = 0; + New.Colors.Foreground = Orig.Colors.Background & 0xF; + New.Colors.Background = Orig.Colors.Foreground & 0x7; + + // + // clear the old mouse position + // + FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2; + + FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1; + + HasCharacter = TRUE; + if (FRow > FileBuffer.NumLines) { + HasCharacter = FALSE; + } else { + CurrentLine = FileBuffer.CurrentLine; + Line = MoveLine (FRow - FileBuffer.FilePosition.Row); + + if (Line == NULL || FColumn > Line->Size) { + HasCharacter = FALSE; + } + + FileBuffer.CurrentLine = CurrentLine; + } + + ShellPrintEx ( + (INT32)FileBufferBackupVar.MousePosition.Column - 1, + (INT32)FileBufferBackupVar.MousePosition.Row - 1, + L" " + ); + + if (HasCharacter) { + Value = (Line->Buffer[FColumn - 1]); + ShellPrintEx ( + (INT32)FileBufferBackupVar.MousePosition.Column - 1, + (INT32)FileBufferBackupVar.MousePosition.Row - 1, + L"%c", + Value + ); + } + // + // set the new mouse position + // + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + + // + // clear the old mouse position + // + FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2; + FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1; + + HasCharacter = TRUE; + if (FRow > FileBuffer.NumLines) { + HasCharacter = FALSE; + } else { + CurrentLine = FileBuffer.CurrentLine; + Line = MoveLine (FRow - FileBuffer.FilePosition.Row); + + if (Line == NULL || FColumn > Line->Size) { + HasCharacter = FALSE; + } + + FileBuffer.CurrentLine = CurrentLine; + } + + ShellPrintEx ( + (INT32)FileBuffer.MousePosition.Column - 1, + (INT32)FileBuffer.MousePosition.Row - 1, + L" " + ); + + if (HasCharacter) { + Value = Line->Buffer[FColumn - 1]; + ShellPrintEx ( + (INT32)FileBuffer.MousePosition.Column - 1, + (INT32)FileBuffer.MousePosition.Row - 1, + L"%c", + Value + ); + } + // + // end of HasCharacter + // + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + } + // + // end of MouseNeedRefresh + // + } + // + // end of MouseSupported + // + return EFI_SUCCESS; +} + +/** + Free all the lines in FileBuffer + Fields affected: + Lines + CurrentLine + NumLines + ListHead + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferFreeLines ( + VOID + ) +{ + LIST_ENTRY *Link; + EFI_EDITOR_LINE *Line; + + // + // free all the lines + // + if (FileBuffer.Lines != NULL) { + + Line = FileBuffer.Lines; + Link = &(Line->Link); + do { + Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + Link = Link->ForwardLink; + + // + // free line's buffer and line itself + // + LineFree (Line); + } while (Link != FileBuffer.ListHead); + } + // + // clean the line list related structure + // + FileBuffer.Lines = NULL; + FileBuffer.CurrentLine = NULL; + FileBuffer.NumLines = 0; + + FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead; + FileBuffer.ListHead->BackLink = FileBuffer.ListHead; + + return EFI_SUCCESS; +} + +/** + Cleanup function for FileBuffer. + + @retval EFI_SUCCESS The cleanup was successful. +**/ +EFI_STATUS +FileBufferCleanup ( + VOID + ) +{ + EFI_STATUS Status; + + SHELL_FREE_NON_NULL (FileBuffer.FileName); + + // + // free all the lines + // + Status = FileBufferFreeLines (); + + SHELL_FREE_NON_NULL (FileBuffer.ListHead); + FileBuffer.ListHead = NULL; + + SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName); + return Status; + +} + +/** + Print a line specified by Line on a row specified by Row of the screen. + + @param[in] Line The line to print. + @param[in] Row The row on the screen to print onto (begin from 1). + + @retval EFI_SUCCESS The printing was successful. +**/ +EFI_STATUS +FileBufferPrintLine ( + IN CONST EFI_EDITOR_LINE *Line, + IN CONST UINTN Row + ) +{ + + CHAR16 *Buffer; + UINTN Limit; + CHAR16 *PrintLine; + CHAR16 *PrintLine2; + UINTN BufLen; + + // + // print start from correct character + // + Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1; + + Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1; + if (Limit > Line->Size) { + Limit = 0; + } + + BufLen = (MainEditor.ScreenSize.Column + 1) * sizeof (CHAR16); + PrintLine = AllocatePool (BufLen); + if (PrintLine != NULL) { + StrnCpyS (PrintLine, BufLen/sizeof(CHAR16), Buffer, MIN(Limit, MainEditor.ScreenSize.Column)); + for (Limit = StrLen (PrintLine); Limit < MainEditor.ScreenSize.Column; Limit++) { + PrintLine[Limit] = L' '; + } + + PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL; + + PrintLine2 = AllocatePool (BufLen * 2); + if (PrintLine2 != NULL) { + ShellCopySearchAndReplace(PrintLine, PrintLine2, BufLen * 2, L"%", L"^%", FALSE, FALSE); + + ShellPrintEx ( + 0, + (INT32)Row - 1, + L"%s", + PrintLine2 + ); + FreePool (PrintLine2); + } + FreePool (PrintLine); + } + + return EFI_SUCCESS; +} + +/** + Set the cursor position according to FileBuffer.DisplayPosition. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferRestorePosition ( + VOID + ) +{ + // + // set cursor position + // + return (gST->ConOut->SetCursorPosition ( + gST->ConOut, + FileBuffer.DisplayPosition.Column - 1, + FileBuffer.DisplayPosition.Row - 1 + )); +} + +/** + Refresh the screen with whats in the buffer. + + @retval EFI_SUCCESS The refresh was successful. + @retval EFI_LOAD_ERROR There was an error finding what to write. +**/ +EFI_STATUS +FileBufferRefresh ( + VOID + ) +{ + LIST_ENTRY *Link; + EFI_EDITOR_LINE *Line; + UINTN Row; + + // + // if it's the first time after editor launch, so should refresh + // + if (!EditorFirst) { + // + // no definite required refresh + // and file position displayed on screen has not been changed + // + if (!FileBufferNeedRefresh && + !FileBufferOnlyLineNeedRefresh && + FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row && + FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column + ) { + + FileBufferRestoreMousePosition (); + FileBufferRestorePosition (); + + return EFI_SUCCESS; + } + } + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + // + // only need to refresh current line + // + if (FileBufferOnlyLineNeedRefresh && + FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row && + FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column + ) { + + EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row); + FileBufferPrintLine ( + FileBuffer.CurrentLine, + FileBuffer.DisplayPosition.Row + ); + } else { + // + // the whole edit area need refresh + // + + // + // no line + // + if (FileBuffer.Lines == NULL) { + FileBufferRestoreMousePosition (); + FileBufferRestorePosition (); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + return EFI_SUCCESS; + } + // + // get the first line that will be displayed + // + Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row); + if (Line == NULL) { + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + return EFI_LOAD_ERROR; + } + + Link = &(Line->Link); + Row = 2; + do { + Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + // + // print line at row + // + FileBufferPrintLine (Line, Row); + + Link = Link->ForwardLink; + Row++; + } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 1)); + // + // while not file end and not screen full + // + while (Row <= (MainEditor.ScreenSize.Row - 1)) { + EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row); + Row++; + } + } + + FileBufferRestoreMousePosition (); + FileBufferRestorePosition (); + + FileBufferNeedRefresh = FALSE; + FileBufferOnlyLineNeedRefresh = FALSE; + + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; +} + +/** + Create a new line and append it to the line list. + Fields affected: + NumLines + Lines + + @retval NULL The create line failed. + @return The line created. +**/ +EFI_EDITOR_LINE * +FileBufferCreateLine ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + + // + // allocate a line structure + // + Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE)); + if (Line == NULL) { + return NULL; + } + // + // initialize the structure + // + Line->Signature = LINE_LIST_SIGNATURE; + Line->Size = 0; + Line->TotalSize = 0; + Line->Type = NewLineTypeDefault; + + // + // initial buffer of the line is "\0" + // + ASSERT(CHAR_NULL == CHAR_NULL); + Line->Buffer = CatSPrint (NULL, L"\0"); + if (Line->Buffer == NULL) { + return NULL; + } + + FileBuffer.NumLines++; + + // + // insert the line into line list + // + InsertTailList (FileBuffer.ListHead, &Line->Link); + + if (FileBuffer.Lines == NULL) { + FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + } + + return Line; +} + +/** + Set FileName field in FileBuffer. + + @param Str The file name to set. + + @retval EFI_SUCCESS The filename was successfully set. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER Str is not a valid filename. +**/ +EFI_STATUS +FileBufferSetFileName ( + IN CONST CHAR16 *Str + ) +{ + // + // Verify the parameters + // + if (!IsValidFileName(Str)) { + return (EFI_INVALID_PARAMETER); + } + // + // free the old file name + // + SHELL_FREE_NON_NULL (FileBuffer.FileName); + + // + // Allocate and set the new name + // + FileBuffer.FileName = CatSPrint (NULL, L"%s", Str); + if (FileBuffer.FileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} +/** + Free the existing file lines and reset the modified flag. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferFree ( + VOID + ) +{ + // + // free all the lines + // + FileBufferFreeLines (); + FileBuffer.FileModified = FALSE; + + return EFI_SUCCESS; +} + + +/** + Read a file from disk into the FileBuffer. + + @param[in] FileName The filename to read. + @param[in] Recover TRUE if is for recover mode, no information printouts. + + @retval EFI_SUCCESS The load was successful. + @retval EFI_LOAD_ERROR The load failed. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER FileName is a directory. +**/ +EFI_STATUS +FileBufferRead ( + IN CONST CHAR16 *FileName, + IN CONST BOOLEAN Recover + ) +{ + EFI_EDITOR_LINE *Line; + EE_NEWLINE_TYPE Type; + UINTN LoopVar1; + UINTN LoopVar2; + UINTN LineSize; + VOID *Buffer; + CHAR16 *UnicodeBuffer; + UINT8 *AsciiBuffer; + UINTN FileSize; + SHELL_FILE_HANDLE FileHandle; + BOOLEAN CreateFile; + EFI_STATUS Status; + UINTN LineSizeBackup; + EFI_FILE_INFO *Info; + + Line = NULL; + LoopVar1 = 0; + FileSize = 0; + UnicodeBuffer = NULL; + Type = NewLineTypeDefault; + FileHandle = NULL; + CreateFile = FALSE; + + // + // in this function, when you return error ( except EFI_OUT_OF_RESOURCES ) + // you should set status string via StatusBarSetStatusString(L"blah") + // since this function maybe called before the editorhandleinput loop + // so any error will cause editor return + // so if you want to print the error status + // you should set the status string + // + + // + // try to open the file + // + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + + if (!EFI_ERROR(Status)) { + CreateFile = FALSE; + if (FileHandle == NULL) { + StatusBarSetStatusString (L"Disk Error"); + return EFI_LOAD_ERROR; + } + + Info = ShellGetFileInfo(FileHandle); + + if (Info->Attribute & EFI_FILE_DIRECTORY) { + StatusBarSetStatusString (L"Directory Can Not Be Edited"); + FreePool (Info); + return EFI_INVALID_PARAMETER; + } + + if (Info->Attribute & EFI_FILE_READ_ONLY) { + FileBuffer.ReadOnly = TRUE; + } else { + FileBuffer.ReadOnly = FALSE; + } + // + // get file size + // + FileSize = (UINTN) Info->FileSize; + + FreePool (Info); + } else if (Status == EFI_NOT_FOUND) { + // + // file not exists. add create and try again + // + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR (Status)) { + if (Status == EFI_WRITE_PROTECTED || + Status == EFI_ACCESS_DENIED || + Status == EFI_NO_MEDIA || + Status == EFI_MEDIA_CHANGED + ) { + StatusBarSetStatusString (L"Access Denied"); + } else if (Status == EFI_DEVICE_ERROR || Status == EFI_VOLUME_CORRUPTED || Status == EFI_VOLUME_FULL) { + StatusBarSetStatusString (L"Disk Error"); + } else { + StatusBarSetStatusString (L"Invalid File Name or Current-working-directory"); + } + + return Status; + } else { + // + // it worked. now delete it and move on with the name (now validated) + // + Status = ShellDeleteFile (&FileHandle); + if (Status == EFI_WARN_DELETE_FAILURE) { + Status = EFI_ACCESS_DENIED; + } + FileHandle = NULL; + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Access Denied"); + return Status; + } + } + // + // file doesn't exist, so set CreateFile to TRUE + // + CreateFile = TRUE; + FileBuffer.ReadOnly = FALSE; + + // + // all the check ends + // so now begin to set file name, free lines + // + if (StrCmp (FileName, FileBuffer.FileName) != 0) { + FileBufferSetFileName (FileName); + } + // + // free the old lines + // + FileBufferFree (); + + } + // + // the file exists + // + if (!CreateFile) { + // + // allocate buffer to read file + // + Buffer = AllocateZeroPool (FileSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // read file into Buffer + // + Status = ShellReadFile (FileHandle, &FileSize, Buffer); + ShellCloseFile(&FileHandle); + FileHandle = NULL; + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read File Failed"); + SHELL_FREE_NON_NULL (Buffer); + return EFI_LOAD_ERROR; + } + // + // nothing in this file + // + if (FileSize == 0) { + SHELL_FREE_NON_NULL (Buffer); + // + // since has no head, so only can be an ASCII file + // + FileBuffer.FileType = FileTypeAscii; + + goto Done; + } + + AsciiBuffer = Buffer; + + if (FileSize < 2) { + // + // size < Unicode file header, so only can be ASCII file + // + FileBuffer.FileType = FileTypeAscii; + } else { + // + // Unicode file + // + if (*(UINT16 *) Buffer == EFI_UNICODE_BYTE_ORDER_MARK) { + // + // Unicode file's size should be even + // + if ((FileSize % 2) != 0) { + StatusBarSetStatusString (L"File Format Wrong"); + SHELL_FREE_NON_NULL (Buffer); + return EFI_LOAD_ERROR; + } + + FileSize /= 2; + + FileBuffer.FileType = FileTypeUnicode; + UnicodeBuffer = Buffer; + + // + // pass this 0xff and 0xfe + // + UnicodeBuffer++; + FileSize--; + } else { + FileBuffer.FileType = FileTypeAscii; + } + // + // end of AsciiBuffer == + // + } + // + // end of FileSize < 2 + // all the check ends + // so now begin to set file name, free lines + // + if (StrCmp (FileName, FileBuffer.FileName) != 0) { + FileBufferSetFileName (FileName); + } + + // + // free the old lines + // + FileBufferFree (); + + // + // parse file content line by line + // + for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) { + Type = NewLineTypeUnknown; + + for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) { + if (FileBuffer.FileType == FileTypeAscii) { + if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) { + Type = NewLineTypeCarriageReturn; + + // + // has LF following + // + if (LineSize < FileSize - 1) { + if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) { + Type = NewLineTypeCarriageReturnLineFeed; + } + } + + break; + } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) { + Type = NewLineTypeLineFeed; + + // + // has CR following + // + if (LineSize < FileSize - 1) { + if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) { + Type = NewLineTypeLineFeedCarriageReturn; + } + } + + break; + } + } else { + if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) { + Type = NewLineTypeCarriageReturn; + + // + // has LF following + // + if (LineSize < FileSize - 1) { + if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) { + Type = NewLineTypeCarriageReturnLineFeed; + } + } + + break; + } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) { + Type = NewLineTypeLineFeed; + + // + // has CR following + // + if (LineSize < FileSize - 1) { + if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) { + Type = NewLineTypeLineFeedCarriageReturn; + } + } + + break; + } + } + // + // endif == ASCII + // + } + // + // end of for LineSize + // + // if the type is wrong, then exit + // + if (Type == NewLineTypeUnknown) { + // + // Now if Type is NewLineTypeUnknown, it should be file end + // + Type = NewLineTypeDefault; + } + + LineSizeBackup = LineSize; + + // + // create a new line + // + Line = FileBufferCreateLine (); + if (Line == NULL) { + SHELL_FREE_NON_NULL (Buffer); + return EFI_OUT_OF_RESOURCES; + } + // + // calculate file length + // + LineSize -= LoopVar1; + + // + // Unicode and one CHAR_NULL + // + SHELL_FREE_NON_NULL (Line->Buffer); + Line->Buffer = AllocateZeroPool (LineSize * 2 + 2); + + if (Line->Buffer == NULL) { + RemoveEntryList (&Line->Link); + return EFI_OUT_OF_RESOURCES; + } + // + // copy this line to Line->Buffer + // + for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) { + if (FileBuffer.FileType == FileTypeAscii) { + Line->Buffer[LoopVar2] = (CHAR16) AsciiBuffer[LoopVar1]; + } else { + Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1]; + } + + LoopVar1++; + } + // + // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED; + // + Line->Buffer[LineSize] = 0; + + Line->Size = LineSize; + Line->TotalSize = LineSize; + Line->Type = Type; + + if (Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) { + LoopVar1++; + } + + // + // last character is a return, SO create a new line + // + if (((Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) && LineSizeBackup == FileSize - 2) || + ((Type == NewLineTypeLineFeed || Type == NewLineTypeCarriageReturn) && LineSizeBackup == FileSize - 1) + ) { + Line = FileBufferCreateLine (); + if (Line == NULL) { + SHELL_FREE_NON_NULL (Buffer); + return EFI_OUT_OF_RESOURCES; + } + } + // + // end of if + // + } + // + // end of LoopVar1 + // + SHELL_FREE_NON_NULL (Buffer); + + } + // + // end of if CreateFile + // +Done: + + FileBuffer.DisplayPosition.Row = 2; + FileBuffer.DisplayPosition.Column = 1; + FileBuffer.LowVisibleRange.Row = 1; + FileBuffer.LowVisibleRange.Column = 1; + FileBuffer.FilePosition.Row = 1; + FileBuffer.FilePosition.Column = 1; + FileBuffer.MousePosition.Row = 2; + FileBuffer.MousePosition.Column = 1; + + if (!Recover) { + UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines); + if (UnicodeBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StatusBarSetStatusString (UnicodeBuffer); + FreePool (UnicodeBuffer); + } +/* + // + // check whether we have fs?: in filename + // + LoopVar1 = 0; + FSMappingPtr = NULL; + while (FileName[LoopVar1] != 0) { + if (FileName[LoopVar1] == L':') { + FSMappingPtr = &FileName[LoopVar1]; + break; + } + + LoopVar1++; + } + + if (FSMappingPtr == NULL) { + CurDir = ShellGetCurrentDir (NULL); + } else { + LoopVar1 = 0; + LoopVar2 = 0; + while (FileName[LoopVar1] != 0) { + if (FileName[LoopVar1] == L':') { + break; + } + + FSMapping[LoopVar2++] = FileName[LoopVar1]; + + LoopVar1++; + } + + FSMapping[LoopVar2] = 0; + CurDir = ShellGetCurrentDir (FSMapping); + } + + if (CurDir != NULL) { + for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++); + + CurDir[LoopVar1] = 0; + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir); + FreePool (CurDir); + } else { + return EFI_LOAD_ERROR; + } + + Status = LibDevicePathToInterface ( + &gEfiSimpleFileSystemProtocolGuid, + DevicePath, + (VOID **) &Vol + ); + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + + Status = Vol->OpenVolume (Vol, &RootFs); + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + // + // Get volume information of file system + // + Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100; + VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size); + Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo); + if (EFI_ERROR (Status)) { + RootFs->Close (RootFs); + return EFI_LOAD_ERROR; + } + + if (VolumeInfo->ReadOnly) { + StatusBarSetStatusString (L"WARNING: Volume Read Only"); + } + + FreePool (VolumeInfo); + RootFs->Close (RootFs); + } +// +*/ + // + // has line + // + if (FileBuffer.Lines != 0) { + FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + } else { + // + // create a dummy line + // + Line = FileBufferCreateLine (); + if (Line == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FileBuffer.CurrentLine = Line; + } + + FileBuffer.FileModified = FALSE; + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + FileBufferMouseNeedRefresh = TRUE; + + + return EFI_SUCCESS; +} + +/** + According to FileBuffer.NewLineType & FileBuffer.FileType, + get the return buffer and size. + + @param[in] Type The type of line. + @param[out] Buffer The buffer to fill. + @param[out] Size The amount of the buffer used on return. +**/ +VOID +GetNewLine ( + IN CONST EE_NEWLINE_TYPE Type, + OUT CHAR8 *Buffer, + OUT UINT8 *Size + ) +{ + UINT8 NewLineSize; + + // + // give new line buffer, + // and will judge unicode or ascii + // + NewLineSize = 0; + + // + // not legal new line type + // + if (Type != NewLineTypeLineFeed && Type != NewLineTypeCarriageReturn && Type != NewLineTypeCarriageReturnLineFeed && Type != NewLineTypeLineFeedCarriageReturn) { + *Size = 0; + return ; + } + // + // use_cr: give 0x0d + // + if (Type == NewLineTypeCarriageReturn) { + if (MainEditor.FileBuffer->FileType == FileTypeUnicode) { + Buffer[0] = 0x0d; + Buffer[1] = 0; + NewLineSize = 2; + } else { + Buffer[0] = 0x0d; + NewLineSize = 1; + } + + *Size = NewLineSize; + return ; + } + // + // use_lf: give 0x0a + // + if (Type == NewLineTypeLineFeed) { + if (MainEditor.FileBuffer->FileType == FileTypeUnicode) { + Buffer[0] = 0x0a; + Buffer[1] = 0; + NewLineSize = 2; + } else { + Buffer[0] = 0x0a; + NewLineSize = 1; + } + + *Size = NewLineSize; + return ; + } + // + // use_crlf: give 0x0d 0x0a + // + if (Type == NewLineTypeCarriageReturnLineFeed) { + if (MainEditor.FileBuffer->FileType == FileTypeUnicode) { + Buffer[0] = 0x0d; + Buffer[1] = 0; + Buffer[2] = 0x0a; + Buffer[3] = 0; + + NewLineSize = 4; + } else { + Buffer[0] = 0x0d; + Buffer[1] = 0x0a; + NewLineSize = 2; + } + + *Size = NewLineSize; + return ; + } + // + // use_lfcr: give 0x0a 0x0d + // + if (Type == NewLineTypeLineFeedCarriageReturn) { + if (MainEditor.FileBuffer->FileType == FileTypeUnicode) { + Buffer[0] = 0x0a; + Buffer[1] = 0; + Buffer[2] = 0x0d; + Buffer[3] = 0; + + NewLineSize = 4; + } else { + Buffer[0] = 0x0a; + Buffer[1] = 0x0d; + NewLineSize = 2; + } + + *Size = NewLineSize; + return ; + } + +} + +/** + Change a Unicode string to an ASCII string. + + @param[in] UStr The Unicode string. + @param[in] Length The maximum size of AStr. + @param[out] AStr ASCII string to pass out. + + @return The actuall length. +**/ +UINTN +UnicodeToAscii ( + IN CONST CHAR16 *UStr, + IN CONST UINTN Length, + OUT CHAR8 *AStr + ) +{ + UINTN Index; + + // + // just buffer copy, not character copy + // + for (Index = 0; Index < Length; Index++) { + *AStr++ = (CHAR8) *UStr++; + } + + return Index; +} + +/** + Save lines in FileBuffer to disk + + @param[in] FileName The file name for writing. + + @retval EFI_SUCCESS Data was written. + @retval EFI_LOAD_ERROR + @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file. +**/ +EFI_STATUS +FileBufferSave ( + IN CONST CHAR16 *FileName + ) +{ + SHELL_FILE_HANDLE FileHandle; + LIST_ENTRY *Link; + EFI_EDITOR_LINE *Line; + CHAR16 *Str; + + EFI_STATUS Status; + UINTN Length; + UINTN NumLines; + CHAR8 NewLineBuffer[4]; + UINT8 NewLineSize; + + EFI_FILE_INFO *Info; + + UINT64 Attribute; + + EE_NEWLINE_TYPE Type; + + UINTN TotalSize; + // + // 2M + // + CHAR8 *Cache; + UINTN LeftSize; + UINTN Size; + CHAR8 *Ptr; + + Length = 0; + // + // 2M + // + TotalSize = 0x200000; + + Attribute = 0; + + + + // + // if is the old file + // + if (FileBuffer.FileName != NULL && StrCmp (FileName, FileBuffer.FileName) == 0) { + // + // file has not been modified + // + if (!FileBuffer.FileModified) { + return EFI_SUCCESS; + } + + // + // if file is read-only, set error + // + if (FileBuffer.ReadOnly) { + StatusBarSetStatusString (L"Read Only File Can Not Be Saved"); + return EFI_SUCCESS; + } + } + + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); + + if (!EFI_ERROR (Status)) { + Info = ShellGetFileInfo(FileHandle); + + if (Info != NULL && Info->Attribute & EFI_FILE_DIRECTORY) { + StatusBarSetStatusString (L"Directory Can Not Be Saved"); + ShellCloseFile(FileHandle); + FreePool(Info); + return EFI_LOAD_ERROR; + } + + if (Info != NULL) { + Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY; + FreePool(Info); + } + + // + // if file exits, so delete it + // + Status = ShellDeleteFile (&FileHandle); + if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) { + StatusBarSetStatusString (L"Write File Failed"); + return EFI_LOAD_ERROR; + } + } + + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute); + + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Create File Failed"); + return EFI_LOAD_ERROR; + } + + // + // if file is Unicode file, write Unicode header to it. + // + if (FileBuffer.FileType == FileTypeUnicode) { + Length = 2; + Status = ShellWriteFile (FileHandle, &Length, (VOID*)&gUnicodeFileTag); + if (EFI_ERROR (Status)) { + ShellDeleteFile (&FileHandle); + return EFI_LOAD_ERROR; + } + } + + Cache = AllocateZeroPool (TotalSize); + if (Cache == NULL) { + ShellDeleteFile (&FileHandle); + return EFI_OUT_OF_RESOURCES; + } + + // + // write all the lines back to disk + // + NumLines = 0; + Type = NewLineTypeCarriageReturnLineFeed; + + Ptr = Cache; + LeftSize = TotalSize; + + for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) { + Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + if (Line->Type != NewLineTypeDefault) { + Type = Line->Type; + } + // + // newline character is at most 4 bytes ( two Unicode characters ) + // + Length = 4; + if (Line->Buffer != NULL && Line->Size != 0) { + if (FileBuffer.FileType == FileTypeAscii) { + Length += Line->Size; + } else { + Length += (Line->Size * 2); + } + // + // end if FileTypeAscii + // + } + + // + // no cache room left, so write cache to disk + // + if (LeftSize < Length) { + Size = TotalSize - LeftSize; + Status = ShellWriteFile (FileHandle, &Size, Cache); + if (EFI_ERROR (Status)) { + ShellDeleteFile (&FileHandle); + FreePool (Cache); + return EFI_LOAD_ERROR; + } + Ptr = Cache; + LeftSize = TotalSize; + } + + if (Line->Buffer != NULL && Line->Size != 0) { + if (FileBuffer.FileType == FileTypeAscii) { + UnicodeToAscii (Line->Buffer, Line->Size, Ptr); + Length = Line->Size; + } else { + Length = (Line->Size * 2); + CopyMem (Ptr, (CHAR8 *) Line->Buffer, Length); + } + // + // end if FileTypeAscii + // + Ptr += Length; + LeftSize -= Length; + + } + // + // end of if Line -> Buffer != NULL && Line -> Size != 0 + // + // if not the last line , write return buffer to disk + // + if (Link->ForwardLink != FileBuffer.ListHead) { + GetNewLine (Type, NewLineBuffer, &NewLineSize); + CopyMem (Ptr, (CHAR8 *) NewLineBuffer, NewLineSize); + + Ptr += NewLineSize; + LeftSize -= NewLineSize; + } + + NumLines++; + } + + if (TotalSize != LeftSize) { + Size = TotalSize - LeftSize; + Status = ShellWriteFile (FileHandle, &Size, Cache); + if (EFI_ERROR (Status)) { + ShellDeleteFile (&FileHandle); + FreePool (Cache); + return EFI_LOAD_ERROR; + } + } + + FreePool (Cache); + + ShellCloseFile(&FileHandle); + + FileBuffer.FileModified = FALSE; + + // + // set status string + // + Str = CatSPrint (NULL, L"%d Lines Wrote", NumLines); + if (Str == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StatusBarSetStatusString (Str); + SHELL_FREE_NON_NULL (Str); + + // + // now everything is ready , you can set the new file name to filebuffer + // + if (FileName != NULL && FileBuffer.FileName != NULL && StrCmp (FileName, FileBuffer.FileName) != 0) { + // + // not the same + // + FileBufferSetFileName (FileName); + if (FileBuffer.FileName == NULL) { + ShellDeleteFile (&FileHandle); + return EFI_OUT_OF_RESOURCES; + } + } + + FileBuffer.ReadOnly = FALSE; + return EFI_SUCCESS; +} + +/** + Scroll cursor to left 1 character position. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferScrollLeft ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + Line = FileBuffer.CurrentLine; + + FRow = FileBuffer.FilePosition.Row; + FCol = FileBuffer.FilePosition.Column; + + // + // if already at start of this line, so move to the end of previous line + // + if (FCol <= 1) { + // + // has previous line + // + if (Line->Link.BackLink != FileBuffer.ListHead) { + FRow--; + Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + FCol = Line->Size + 1; + } else { + return EFI_SUCCESS; + } + } else { + // + // if not at start of this line, just move to previous column + // + FCol--; + } + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Delete a char in line + + @param[in, out] Line The line to delete in. + @param[in] Pos Position to delete the char at ( start from 0 ). +**/ +VOID +LineDeleteAt ( + IN OUT EFI_EDITOR_LINE *Line, + IN UINTN Pos + ) +{ + UINTN Index; + + // + // move the latter characters front + // + for (Index = Pos - 1; Index < Line->Size; Index++) { + Line->Buffer[Index] = Line->Buffer[Index + 1]; + } + + Line->Size--; +} + +/** + Concatenate Src into Dest. + + @param[in, out] Dest Destination string + @param[in] Src Src String. +**/ +VOID +LineCat ( + IN OUT EFI_EDITOR_LINE *Dest, + IN EFI_EDITOR_LINE *Src + ) +{ + CHAR16 *Str; + UINTN Size; + + Size = Dest->Size; + + Dest->Buffer[Size] = 0; + + // + // concatenate the two strings + // + Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer); + if (Str == NULL) { + Dest->Buffer = NULL; + return ; + } + + Dest->Size = Size + Src->Size; + Dest->TotalSize = Dest->Size; + + FreePool (Dest->Buffer); + FreePool (Src->Buffer); + + // + // put str to dest->buffer + // + Dest->Buffer = Str; +} + +/** + Delete the previous character. + + @retval EFI_SUCCESS The delete was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferDoBackspace ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + EFI_EDITOR_LINE *End; + LIST_ENTRY *Link; + UINTN FileColumn; + + FileColumn = FileBuffer.FilePosition.Column; + + Line = FileBuffer.CurrentLine; + + // + // the first column + // + if (FileColumn == 1) { + // + // the first row + // + if (FileBuffer.FilePosition.Row == 1) { + return EFI_SUCCESS; + } + + FileBufferScrollLeft (); + + Line = FileBuffer.CurrentLine; + Link = Line->Link.ForwardLink; + End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + // + // concatenate this line with previous line + // + LineCat (Line, End); + if (Line->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // remove End from line list + // + RemoveEntryList (&End->Link); + FreePool (End); + + FileBuffer.NumLines--; + + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + + } else { + // + // just delete the previous character + // + LineDeleteAt (Line, FileColumn - 1); + FileBufferScrollLeft (); + FileBufferOnlyLineNeedRefresh = TRUE; + } + + if (!FileBuffer.FileModified) { + FileBuffer.FileModified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Add a return into line at current position. + + @retval EFI_SUCCESS The insetrion of the character was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferDoReturn ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + EFI_EDITOR_LINE *NewLine; + UINTN FileColumn; + UINTN Index; + CHAR16 *Buffer; + UINTN Row; + UINTN Col; + + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + + Line = FileBuffer.CurrentLine; + + FileColumn = FileBuffer.FilePosition.Column; + + NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE)); + if (NewLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewLine->Signature = LINE_LIST_SIGNATURE; + NewLine->Size = Line->Size - FileColumn + 1; + NewLine->TotalSize = NewLine->Size; + NewLine->Buffer = CatSPrint (NULL, L"\0"); + if (NewLine->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewLine->Type = NewLineTypeDefault; + + if (NewLine->Size > 0) { + // + // UNICODE + CHAR_NULL + // + Buffer = AllocateZeroPool (2 * (NewLine->Size + 1)); + if (Buffer == NULL) { + FreePool (NewLine->Buffer); + FreePool (NewLine); + return EFI_OUT_OF_RESOURCES; + } + + FreePool (NewLine->Buffer); + + NewLine->Buffer = Buffer; + + for (Index = 0; Index < NewLine->Size; Index++) { + NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1]; + } + + NewLine->Buffer[NewLine->Size] = CHAR_NULL; + + Line->Buffer[FileColumn - 1] = CHAR_NULL; + Line->Size = FileColumn - 1; + } + // + // increase NumLines + // + FileBuffer.NumLines++; + + // + // insert it into the correct position of line list + // + NewLine->Link.BackLink = &(Line->Link); + NewLine->Link.ForwardLink = Line->Link.ForwardLink; + Line->Link.ForwardLink->BackLink = &(NewLine->Link); + Line->Link.ForwardLink = &(NewLine->Link); + + // + // move cursor to the start of next line + // + Row = FileBuffer.FilePosition.Row + 1; + Col = 1; + + FileBufferMovePosition (Row, Col); + + // + // set file is modified + // + if (!FileBuffer.FileModified) { + FileBuffer.FileModified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Delete current character from current line. This is the effect caused + by the 'del' key. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +FileBufferDoDelete ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + EFI_EDITOR_LINE *Next; + LIST_ENTRY *Link; + UINTN FileColumn; + + Line = FileBuffer.CurrentLine; + FileColumn = FileBuffer.FilePosition.Column; + + // + // the last column + // + if (FileColumn >= Line->Size + 1) { + // + // the last line + // + if (Line->Link.ForwardLink == FileBuffer.ListHead) { + return EFI_SUCCESS; + } + // + // since last character, + // so will add the next line to this line + // + Link = Line->Link.ForwardLink; + Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + LineCat (Line, Next); + if (Line->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + RemoveEntryList (&Next->Link); + FreePool (Next); + + FileBuffer.NumLines--; + + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + + } else { + // + // just delete current character + // + LineDeleteAt (Line, FileColumn); + FileBufferOnlyLineNeedRefresh = TRUE; + } + + if (!FileBuffer.FileModified) { + FileBuffer.FileModified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Scroll cursor to right 1 character. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferScrollRight ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + Line = FileBuffer.CurrentLine; + if (Line->Buffer == NULL) { + return EFI_SUCCESS; + } + + FRow = FileBuffer.FilePosition.Row; + FCol = FileBuffer.FilePosition.Column; + + // + // if already at end of this line, scroll it to the start of next line + // + if (FCol > Line->Size) { + // + // has next line + // + if (Line->Link.ForwardLink != FileBuffer.ListHead) { + FRow++; + FCol = 1; + } else { + return EFI_SUCCESS; + } + } else { + // + // if not at end of this line, just move to next column + // + FCol++; + } + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Insert a char into line + + + @param[in] Line The line to insert into. + @param[in] Char The char to insert. + @param[in] Pos The position to insert the char at ( start from 0 ). + @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character. + + @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ). +**/ +UINTN +LineStrInsert ( + IN EFI_EDITOR_LINE *Line, + IN CHAR16 Char, + IN UINTN Pos, + IN UINTN StrSize + ) +{ + UINTN Index; + CHAR16 *TempStringPtr; + CHAR16 *Str; + + Index = (StrSize) * 2; + + Str = Line->Buffer; + + // + // do not have free space + // + if (Line->TotalSize <= Line->Size) { + Str = ReallocatePool (Index, Index + 16, Str); + if (Str == NULL) { + return 0; + } + + Line->TotalSize += 8; + } + // + // move the later part of the string one character right + // + TempStringPtr = Str; + for (Index = StrSize; Index > Pos; Index--) { + TempStringPtr[Index] = TempStringPtr[Index - 1]; + } + // + // insert char into it. + // + TempStringPtr[Index] = Char; + + Line->Buffer = Str; + Line->Size++; + + return StrSize + 1; +} + +/** + Add a character to the current line. + + @param[in] Char The Character to input. + + @retval EFI_SUCCESS The input was succesful. +**/ +EFI_STATUS +FileBufferAddChar ( + IN CHAR16 Char + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FilePos; + + Line = FileBuffer.CurrentLine; + + // + // only needs to refresh current line + // + FileBufferOnlyLineNeedRefresh = TRUE; + + // + // when is insert mode, or cursor is at end of this line, + // so insert this character + // or replace the character. + // + FilePos = FileBuffer.FilePosition.Column - 1; + if (FileBuffer.ModeInsert || FilePos + 1 > Line->Size) { + LineStrInsert (Line, Char, FilePos, Line->Size + 1); + } else { + Line->Buffer[FilePos] = Char; + } + // + // move cursor to right + // + FileBufferScrollRight (); + + if (!FileBuffer.FileModified) { + FileBuffer.FileModified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Handles inputs from characters (ASCII key + Backspace + return) + + @param[in] Char The input character. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR There was an error. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferDoCharInput ( + IN CONST CHAR16 Char + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + switch (Char) { + case CHAR_NULL: + break; + + case CHAR_BACKSPACE: + Status = FileBufferDoBackspace (); + break; + + case CHAR_TAB: + // + // Tabs are ignored + // + break; + + case CHAR_LINEFEED: + case CHAR_CARRIAGE_RETURN: + Status = FileBufferDoReturn (); + break; + + default: + // + // DEAL WITH ASCII CHAR, filter out thing like ctrl+f + // + if (Char > 127 || Char < 32) { + Status = StatusBarSetStatusString (L"Unknown Command"); + } else { + Status = FileBufferAddChar (Char); + } + + break; + + } + + return Status; +} + +/** + Scroll cursor to the next line. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferScrollDown ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + Line = FileBuffer.CurrentLine; + if (Line->Buffer == NULL) { + return EFI_SUCCESS; + } + + FRow = FileBuffer.FilePosition.Row; + FCol = FileBuffer.FilePosition.Column; + + // + // has next line + // + if (Line->Link.ForwardLink != FileBuffer.ListHead) { + FRow++; + Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + // + // if the next line is not that long, so move to end of next line + // + if (FCol > Line->Size) { + FCol = Line->Size + 1; + } + + } else { + return EFI_SUCCESS; + } + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Scroll the cursor to previous line. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferScrollUp ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + Line = FileBuffer.CurrentLine; + + FRow = FileBuffer.FilePosition.Row; + FCol = FileBuffer.FilePosition.Column; + + // + // has previous line + // + if (Line->Link.BackLink != FileBuffer.ListHead) { + FRow--; + Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + // + // if previous line is not that long, so move to the end of previous line + // + if (FCol > Line->Size) { + FCol = Line->Size + 1; + } + + } else { + return EFI_SUCCESS; + } + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to next page. + + @retval EFI_SUCCESS The operation wa successful. +**/ +EFI_STATUS +FileBufferPageDown ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + UINTN Gap; + + Line = FileBuffer.CurrentLine; + + FRow = FileBuffer.FilePosition.Row; + FCol = FileBuffer.FilePosition.Column; + + // + // has next page + // + if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 2)) { + Gap = (MainEditor.ScreenSize.Row - 2); + } else { + // + // MOVE CURSOR TO LAST LINE + // + Gap = FileBuffer.NumLines - FRow; + } + // + // get correct line + // + Line = MoveLine (Gap); + + // + // if that line, is not that long, so move to the end of that line + // + if (Line != NULL && FCol > Line->Size) { + FCol = Line->Size + 1; + } + + FRow += Gap; + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to previous screen. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferPageUp ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + UINTN Gap; + INTN Retreat; + + Line = FileBuffer.CurrentLine; + + FRow = FileBuffer.FilePosition.Row; + FCol = FileBuffer.FilePosition.Column; + + // + // has previous page + // + if (FRow > (MainEditor.ScreenSize.Row - 2)) { + Gap = (MainEditor.ScreenSize.Row - 2); + } else { + // + // the first line of file will displayed on the first line of screen + // + Gap = FRow - 1; + } + + Retreat = Gap; + Retreat = -Retreat; + + // + // get correct line + // + Line = MoveLine (Retreat); + + // + // if that line is not that long, so move to the end of that line + // + if (Line != NULL && FCol > Line->Size) { + FCol = Line->Size + 1; + } + + FRow -= Gap; + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to end of the current line. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferEnd ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + Line = FileBuffer.CurrentLine; + + FRow = FileBuffer.FilePosition.Row; + + // + // goto the last column of the line + // + FCol = Line->Size + 1; + + FileBufferMovePosition (FRow, FCol); + + return EFI_SUCCESS; +} + +/** + Dispatch input to different handler + @param[in] Key The input key. One of: + ASCII KEY + Backspace/Delete + Return + Direction key: up/down/left/right/pgup/pgdn + Home/End + INS + + @retval EFI_SUCCESS The dispatch was done successfully. + @retval EFI_LOAD_ERROR The dispatch was not successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferHandleInput ( + IN CONST EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + switch (Key->ScanCode) { + // + // ordinary key input + // + case SCAN_NULL: + if (!FileBuffer.ReadOnly) { + Status = FileBufferDoCharInput (Key->UnicodeChar); + } else { + Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified"); + } + + break; + + // + // up arrow + // + case SCAN_UP: + Status = FileBufferScrollUp (); + break; + + // + // down arrow + // + case SCAN_DOWN: + Status = FileBufferScrollDown (); + break; + + // + // right arrow + // + case SCAN_RIGHT: + Status = FileBufferScrollRight (); + break; + + // + // left arrow + // + case SCAN_LEFT: + Status = FileBufferScrollLeft (); + break; + + // + // page up + // + case SCAN_PAGE_UP: + Status = FileBufferPageUp (); + break; + + // + // page down + // + case SCAN_PAGE_DOWN: + Status = FileBufferPageDown (); + break; + + // + // delete + // + case SCAN_DELETE: + if (!FileBuffer.ReadOnly) { + Status = FileBufferDoDelete (); + } else { + Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified"); + } + + break; + + // + // home + // + case SCAN_HOME: + FileBufferMovePosition (FileBuffer.FilePosition.Row, 1); + Status = EFI_SUCCESS; + break; + + // + // end + // + case SCAN_END: + Status = FileBufferEnd (); + break; + + // + // insert + // + case SCAN_INSERT: + FileBuffer.ModeInsert = (BOOLEAN)!FileBuffer.ModeInsert; + Status = EFI_SUCCESS; + break; + + default: + Status = StatusBarSetStatusString (L"Unknown Command"); + break; + } + + return Status; +} + +/** + Check user specified FileRow is above current screen. + + @param[in] FileRow The row of file position ( start from 1 ). + + @retval TRUE It is above the current screen. + @retval FALSE It is not above the current screen. +**/ +BOOLEAN +AboveCurrentScreen ( + IN UINTN FileRow + ) +{ + // + // if is to the above of the screen + // + if (FileRow < FileBuffer.LowVisibleRange.Row) { + return TRUE; + } + + return FALSE; +} + +/** + Check user specified FileRow is under current screen. + + @param[in] FileRow The row of file position ( start from 1 ). + + @retval TRUE It is under the current screen. + @retval FALSE It is not under the current screen. +**/ +BOOLEAN +UnderCurrentScreen ( + IN UINTN FileRow + ) +{ + // + // if is to the under of the screen + // + if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 2) - 1) { + return TRUE; + } + + return FALSE; +} + +/** + Check user specified FileCol is left to current screen. + + @param[in] FileCol The column of file position ( start from 1 ). + + @retval TRUE It is to the left. + @retval FALSE It is not to the left. +**/ +BOOLEAN +LeftCurrentScreen ( + IN UINTN FileCol + ) +{ + // + // if is to the left of the screen + // + if (FileCol < FileBuffer.LowVisibleRange.Column) { + return TRUE; + } + + return FALSE; +} + +/** + Check user specified FileCol is right to current screen. + + @param[in] FileCol The column of file position ( start from 1 ). + + @retval TRUE It is to the right. + @retval FALSE It is not to the right. +**/ +BOOLEAN +RightCurrentScreen ( + IN UINTN FileCol + ) +{ + // + // if is to the right of the screen + // + if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) { + return TRUE; + } + + return FALSE; +} + +/** + Advance/Retreat lines and set CurrentLine in FileBuffer to it + + @param[in] Count The line number to advance/retreat + >0 : advance + <0: retreat + + @retval NULL An error occured. + @return The line after advance/retreat. +**/ +EFI_EDITOR_LINE * +MoveCurrentLine ( + IN INTN Count + ) +{ + EFI_EDITOR_LINE *Line; + UINTN AbsCount; + + if (Count <= 0) { + AbsCount = (UINTN)ABS(Count); + Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead); + } else { + Line = InternalEditorMiscLineAdvance ((UINTN)Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead); + } + + if (Line == NULL) { + return NULL; + } + + MainEditor.FileBuffer->CurrentLine = Line; + + return Line; +} + +/** + According to cursor's file position, adjust screen display + + @param[in] NewFilePosRow The row of file position ( start from 1 ). + @param[in] NewFilePosCol The column of file position ( start from 1 ). +**/ +VOID +FileBufferMovePosition ( + IN CONST UINTN NewFilePosRow, + IN CONST UINTN NewFilePosCol + ) +{ + INTN RowGap; + INTN ColGap; + UINTN Abs; + BOOLEAN Above; + BOOLEAN Under; + BOOLEAN Right; + BOOLEAN Left; + + // + // CALCULATE gap between current file position and new file position + // + RowGap = NewFilePosRow - FileBuffer.FilePosition.Row; + ColGap = NewFilePosCol - FileBuffer.FilePosition.Column; + + Under = UnderCurrentScreen (NewFilePosRow); + Above = AboveCurrentScreen (NewFilePosRow); + // + // if is below current screen + // + if (Under) { + // + // display row will be unchanged + // + FileBuffer.FilePosition.Row = NewFilePosRow; + } else { + if (Above) { + // + // has enough above line, so display row unchanged + // not has enough above lines, so the first line is at the + // first display line + // + if (NewFilePosRow < (FileBuffer.DisplayPosition.Row - 1)) { + FileBuffer.DisplayPosition.Row = NewFilePosRow + 1; + } + + FileBuffer.FilePosition.Row = NewFilePosRow; + } else { + // + // in current screen + // + FileBuffer.FilePosition.Row = NewFilePosRow; + if (RowGap < 0) { + Abs = (UINTN)ABS(RowGap); + FileBuffer.DisplayPosition.Row -= Abs; + } else { + FileBuffer.DisplayPosition.Row += RowGap; + } + } + } + + FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2); + + Right = RightCurrentScreen (NewFilePosCol); + Left = LeftCurrentScreen (NewFilePosCol); + + // + // if right to current screen + // + if (Right) { + // + // display column will be changed to end + // + FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column; + FileBuffer.FilePosition.Column = NewFilePosCol; + } else { + if (Left) { + // + // has enough left characters , so display row unchanged + // not has enough left characters, + // so the first character is at the first display column + // + if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) { + FileBuffer.DisplayPosition.Column = NewFilePosCol; + } + + FileBuffer.FilePosition.Column = NewFilePosCol; + } else { + // + // in current screen + // + FileBuffer.FilePosition.Column = NewFilePosCol; + if (ColGap < 0) { + Abs = (UINTN)(-ColGap); + FileBuffer.DisplayPosition.Column -= Abs; + } else { + FileBuffer.DisplayPosition.Column += ColGap; + } + } + } + + FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1); + + // + // let CurrentLine point to correct line; + // + FileBuffer.CurrentLine = MoveCurrentLine (RowGap); + +} + +/** + Cut current line out and return a pointer to it. + + @param[out] CutLine Upon a successful return pointer to the pointer to + the allocated cut line. + + @retval EFI_SUCCESS The cut was successful. + @retval EFI_NOT_FOUND There was no selection to cut. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferCutLine ( + OUT EFI_EDITOR_LINE **CutLine + ) +{ + EFI_EDITOR_LINE *Line; + EFI_EDITOR_LINE *NewLine; + UINTN Row; + UINTN Col; + + if (FileBuffer.ReadOnly) { + StatusBarSetStatusString (L"Read Only File Can Not Be Modified"); + return EFI_SUCCESS; + } + + Line = FileBuffer.CurrentLine; + + // + // if is the last dummy line, SO CAN not cut + // + if (StrCmp (Line->Buffer, L"\0") == 0 && Line->Link.ForwardLink == FileBuffer.ListHead + // + // last line + // + ) { + // + // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING + // + StatusBarSetStatusString (L"Nothing to Cut"); + return EFI_NOT_FOUND; + } + // + // if is the last line, so create a dummy line + // + if (Line->Link.ForwardLink == FileBuffer.ListHead) { + // + // last line + // create a new line + // + NewLine = FileBufferCreateLine (); + if (NewLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + FileBuffer.NumLines--; + Row = FileBuffer.FilePosition.Row; + Col = 1; + // + // move home + // + FileBuffer.CurrentLine = CR ( + FileBuffer.CurrentLine->Link.ForwardLink, + EFI_EDITOR_LINE, + Link, + LINE_LIST_SIGNATURE + ); + + RemoveEntryList (&Line->Link); + + FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + FileBufferMovePosition (Row, Col); + + FileBuffer.FileModified = TRUE; + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + + *CutLine = Line; + + return EFI_SUCCESS; +} + +/** + Paste a line into line list. + + @retval EFI_SUCCESS The paste was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferPasteLine ( + VOID + ) +{ + EFI_EDITOR_LINE *Line; + EFI_EDITOR_LINE *NewLine; + UINTN Row; + UINTN Col; + + // + // if nothing is on clip board + // then do nothing + // + if (MainEditor.CutLine == NULL) { + return EFI_SUCCESS; + } + // + // read only file can not be pasted on + // + if (FileBuffer.ReadOnly) { + StatusBarSetStatusString (L"Read Only File Can Not Be Modified"); + return EFI_SUCCESS; + } + + NewLine = LineDup (MainEditor.CutLine); + if (NewLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // insert it above current line + // + Line = FileBuffer.CurrentLine; + NewLine->Link.BackLink = Line->Link.BackLink; + NewLine->Link.ForwardLink = &Line->Link; + + Line->Link.BackLink->ForwardLink = &NewLine->Link; + Line->Link.BackLink = &NewLine->Link; + + FileBuffer.NumLines++; + FileBuffer.CurrentLine = NewLine; + + FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + Col = 1; + // + // move home + // + Row = FileBuffer.FilePosition.Row; + + FileBufferMovePosition (Row, Col); + + // + // after paste, set some value so that refresh knows to do something + // + FileBuffer.FileModified = TRUE; + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + + return EFI_SUCCESS; +} + +/** + Search string from current position on in file + + @param[in] Str The search string. + @param[in] Offset The offset from current position. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND The string Str was not found. +**/ +EFI_STATUS +FileBufferSearch ( + IN CONST CHAR16 *Str, + IN CONST UINTN Offset + ) +{ + CHAR16 *Current; + UINTN Position; + UINTN Row; + UINTN Column; + EFI_EDITOR_LINE *Line; + CHAR16 *CharPos; + LIST_ENTRY *Link; + BOOLEAN Found; + + Column = 0; + Position = 0; + + // + // search if in current line + // + Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset; + + if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) { + // + // the end + // + Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size; + } + + Found = FALSE; + + CharPos = StrStr (Current, Str); + if (CharPos != NULL) { + Position = CharPos - Current + 1; + Found = TRUE; + } + + // + // found + // + if (Found) { + Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset; + Row = FileBuffer.FilePosition.Row; + } else { + // + // not found so find through next lines + // + Link = FileBuffer.CurrentLine->Link.ForwardLink; + + Row = FileBuffer.FilePosition.Row + 1; + while (Link != FileBuffer.ListHead) { + Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); +// Position = StrStr (Line->Buffer, Str); + CharPos = StrStr (Line->Buffer, Str); + if (CharPos != NULL) { + Position = CharPos - Line->Buffer + 1; + Found = TRUE; + } + + if (Found) { + // + // found + // + Column = Position; + break; + } + + Row++; + Link = Link->ForwardLink; + } + + if (Link == FileBuffer.ListHead) { + Found = FALSE; + } else { + Found = TRUE; + } + } + + if (!Found) { + return EFI_NOT_FOUND; + } + + FileBufferMovePosition (Row, Column); + + // + // call refresh to fresh edit area, + // because the outer may loop to find multiply occurrence of this string + // + FileBufferRefresh (); + + return EFI_SUCCESS; +} + +/** + Replace SearchLen characters from current position on with Replace. + + This will modify the current buffer at the current position. + + @param[in] Replace The string to replace. + @param[in] SearchLen Search string's length. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferReplace ( + IN CONST CHAR16 *Replace, + IN CONST UINTN SearchLen + ) +{ + UINTN ReplaceLen; + UINTN Index; + CHAR16 *Buffer; + UINTN NewSize; + UINTN OldSize; + UINTN Gap; + + ReplaceLen = StrLen (Replace); + + OldSize = FileBuffer.CurrentLine->Size + 1; + // + // include CHAR_NULL + // + NewSize = OldSize + (ReplaceLen - SearchLen); + + if (ReplaceLen > SearchLen) { + // + // do not have the enough space + // + if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) { + FileBuffer.CurrentLine->Buffer = ReallocatePool ( + 2 * OldSize, + 2 * NewSize, + FileBuffer.CurrentLine->Buffer + ); + FileBuffer.CurrentLine->TotalSize = NewSize - 1; + } + + if (FileBuffer.CurrentLine->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // the end CHAR_NULL character; + // + Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1); + Gap = ReplaceLen - SearchLen; + + // + // keep the latter part + // + for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) { + *Buffer = *(Buffer - Gap); + Buffer--; + } + // + // set replace into it + // + Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1; + for (Index = 0; Index < ReplaceLen; Index++) { + Buffer[Index] = Replace[Index]; + } + } + + if (ReplaceLen < SearchLen) { + Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1; + + for (Index = 0; Index < ReplaceLen; Index++) { + Buffer[Index] = Replace[Index]; + } + + Buffer += ReplaceLen; + Gap = SearchLen - ReplaceLen; + + // + // set replace into it + // + for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) { + *Buffer = *(Buffer + Gap); + Buffer++; + } + } + + if (ReplaceLen == SearchLen) { + Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1; + for (Index = 0; Index < ReplaceLen; Index++) { + Buffer[Index] = Replace[Index]; + } + } + + FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen); + + FileBufferOnlyLineNeedRefresh = TRUE; + + FileBuffer.FileModified = TRUE; + + MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0); + FileBufferRestorePosition (); + FileBufferRefresh (); + + return EFI_SUCCESS; +} + +/** + Move the mouse cursor position. + + @param[in] TextX The new x-coordinate. + @param[in] TextY The new y-coordinate. +**/ +VOID +FileBufferAdjustMousePosition ( + IN CONST INT32 TextX, + IN CONST INT32 TextY + ) +{ + UINTN CoordinateX; + UINTN CoordinateY; + UINTN AbsX; + UINTN AbsY; + + // + // TextX and TextY is mouse movement data returned by mouse driver + // This function will change it to MousePosition + // + // + // get absolute value + // + + AbsX = ABS(TextX); + AbsY = ABS(TextY); + + CoordinateX = FileBuffer.MousePosition.Column; + CoordinateY = FileBuffer.MousePosition.Row; + + if (TextX >= 0) { + CoordinateX += TextX; + } else { + if (CoordinateX >= AbsX) { + CoordinateX -= AbsX; + } else { + CoordinateX = 0; + } + } + + if (TextY >= 0) { + CoordinateY += TextY; + } else { + if (CoordinateY >= AbsY) { + CoordinateY -= AbsY; + } else { + CoordinateY = 0; + } + } + // + // check whether new mouse column position is beyond screen + // if not, adjust it + // + if (CoordinateX >= 1 && CoordinateX <= MainEditor.ScreenSize.Column) { + FileBuffer.MousePosition.Column = CoordinateX; + } else if (CoordinateX < 1) { + FileBuffer.MousePosition.Column = 1; + } else if (CoordinateX > MainEditor.ScreenSize.Column) { + FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column; + } + // + // check whether new mouse row position is beyond screen + // if not, adjust it + // + if (CoordinateY >= 2 && CoordinateY <= (MainEditor.ScreenSize.Row - 1)) { + FileBuffer.MousePosition.Row = CoordinateY; + } else if (CoordinateY < 2) { + FileBuffer.MousePosition.Row = 2; + } else if (CoordinateY > (MainEditor.ScreenSize.Row - 1)) { + FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 1); + } + +} + +/** + Search and replace operation. + + @param[in] SearchStr The string to search for. + @param[in] ReplaceStr The string to replace with. + @param[in] Offset The column to start at. +**/ +EFI_STATUS +FileBufferReplaceAll ( + IN CHAR16 *SearchStr, + IN CHAR16 *ReplaceStr, + IN UINTN Offset + ) +{ + CHAR16 *Buffer; + UINTN Position; + UINTN Column; + UINTN ReplaceLen; + UINTN SearchLen; + UINTN Index; + UINTN NewSize; + UINTN OldSize; + UINTN Gap; + EFI_EDITOR_LINE *Line; + LIST_ENTRY *Link; + CHAR16 *CharPos; + + SearchLen = StrLen (SearchStr); + ReplaceLen = StrLen (ReplaceStr); + + Column = FileBuffer.FilePosition.Column + Offset - 1; + + if (Column > FileBuffer.CurrentLine->Size) { + Column = FileBuffer.CurrentLine->Size; + } + + Link = &(FileBuffer.CurrentLine->Link); + + while (Link != FileBuffer.ListHead) { + Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + CharPos = StrStr (Line->Buffer + Column, SearchStr); + if (CharPos != NULL) { + Position = CharPos - Line->Buffer;// + Column; + // + // found + // + if (ReplaceLen > SearchLen) { + OldSize = Line->Size + 1; + // + // include CHAR_NULL + // + NewSize = OldSize + (ReplaceLen - SearchLen); + + // + // do not have the enough space + // + if (Line->TotalSize + 1 <= NewSize) { + Line->Buffer = ReallocatePool ( + 2 * OldSize, + 2 * NewSize, + Line->Buffer + ); + Line->TotalSize = NewSize - 1; + } + + if (Line->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // the end CHAR_NULL character; + // + Buffer = Line->Buffer + (NewSize - 1); + Gap = ReplaceLen - SearchLen; + + // + // keep the latter part + // + for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) { + *Buffer = *(Buffer - Gap); + Buffer--; + } + + } else if (ReplaceLen < SearchLen){ + Buffer = Line->Buffer + Position + ReplaceLen; + Gap = SearchLen - ReplaceLen; + + for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) { + *Buffer = *(Buffer + Gap); + Buffer++; + } + } else { + ASSERT(ReplaceLen == SearchLen); + } + // + // set replace into it + // + Buffer = Line->Buffer + Position; + for (Index = 0; Index < ReplaceLen; Index++) { + Buffer[Index] = ReplaceStr[Index]; + } + + Line->Size += (ReplaceLen - SearchLen); + Column += ReplaceLen; + } else { + // + // not found + // + Column = 0; + Link = Link->ForwardLink; + } + } + // + // call refresh to fresh edit area + // + FileBuffer.FileModified = TRUE; + FileBufferNeedRefresh = TRUE; + FileBufferRefresh (); + + return EFI_SUCCESS; +} + +/** + Set the modified state to TRUE. +**/ +VOID +FileBufferSetModified ( + VOID + ) +{ + FileBuffer.FileModified = TRUE; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h new file mode 100644 index 0000000..38e3c7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h @@ -0,0 +1,246 @@ +/** @file + Declares filebuffer interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_FILE_BUFFER_H_ +#define _LIB_FILE_BUFFER_H_ + +#include "TextEditorTypes.h" + +/** + Initialization function for FileBuffer. + + @param EFI_SUCCESS The initialization was successful. + @param EFI_LOAD_ERROR A default name could not be created. + @param EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferInit ( + VOID + ); + +/** + Cleanup function for FileBuffer. + + @retval EFI_SUCCESS The cleanup was successful. +**/ +EFI_STATUS +FileBufferCleanup ( + VOID + ); + +/** + Refresh the screen with whats in the buffer. + + @retval EFI_SUCCESS The refresh was successful. + @retval EFI_LOAD_ERROR There was an error finding what to write. +**/ +EFI_STATUS +FileBufferRefresh ( + VOID + ); + +/** + Dispatch input to different handler + @param[in] Key The input key. One of: + ASCII KEY + Backspace/Delete + Return + Direction key: up/down/left/right/pgup/pgdn + Home/End + INS + + @retval EFI_SUCCESS The dispatch was done successfully. + @retval EFI_LOAD_ERROR The dispatch was not successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferHandleInput ( + IN CONST EFI_INPUT_KEY * Key + ); + +/** + Backup function for FileBuffer. Only backup the following items: + Mouse/Cursor position + File Name, Type, ReadOnly, Modified + Insert Mode + + This is for making the file buffer refresh as few as possible. + + @retval EFI_SUCCESS The backup operation was successful. +**/ +EFI_STATUS +FileBufferBackup ( + VOID + ); + +/** + Set the cursor position according to FileBuffer.DisplayPosition. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +FileBufferRestorePosition ( + VOID + ); + +/** + Set FileName field in FileBuffer. + + @param Str The file name to set. + + @retval EFI_SUCCESS The filename was successfully set. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER Str is not a valid filename. +**/ +EFI_STATUS +FileBufferSetFileName ( + IN CONST CHAR16 *Str + ); + +/** + Read a file from disk into the FileBuffer. + + @param[in] FileName The filename to read. + @param[in] Recover TRUE if is for recover mode, no information printouts. + + @retval EFI_SUCCESS The load was successful. + @retval EFI_LOAD_ERROR The load failed. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER FileName is a directory. +**/ +EFI_STATUS +FileBufferRead ( + IN CONST CHAR16 *FileName, + IN CONST BOOLEAN Recover + ); + +/** + Save lines in FileBuffer to disk + + @param[in] FileName The file name for writing. + + @retval EFI_SUCCESS Data was written. + @retval EFI_LOAD_ERROR + @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file. +**/ +EFI_STATUS +FileBufferSave ( + CONST CHAR16 *FileName + ); + +/** + According to cursor's file position, adjust screen display + + @param[in] NewFilePosRow The row of file position ( start from 1 ). + @param[in] NewFilePosCol The column of file position ( start from 1 ). +**/ +VOID +FileBufferMovePosition ( + IN CONST UINTN NewFilePosRow, + IN CONST UINTN NewFilePosCol + ); + +/** + Cut current line out and return a pointer to it. + + @param[out] CutLine Upon a successful return pointer to the pointer to + the allocated cut line. + + @retval EFI_SUCCESS The cut was successful. + @retval EFI_NOT_FOUND There was no selection to cut. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferCutLine ( + OUT EFI_EDITOR_LINE **CutLine + ); + +/** + Paste a line into line list. + + @retval EFI_SUCCESS The paste was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferPasteLine ( + VOID + ); + +/** + Search string from current position on in file + + @param[in] Str The search string. + @param[in] Offset The offset from current position. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND The string Str was not found. +**/ +EFI_STATUS +FileBufferSearch ( + IN CONST CHAR16 *Str, + IN CONST UINTN Offset + ); + +/** + Replace SearchLen characters from current position on with Replace. + + This will modify the current buffer at the current position. + + @param[in] Replace The string to replace. + @param[in] SearchLen Search string's length. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +FileBufferReplace ( + IN CONST CHAR16 *Replace, + IN CONST UINTN SearchLen + ); + +/** + Search and replace operation. + + @param[in] SearchStr The string to search for. + @param[in] ReplaceStr The string to replace with. + @param[in] Offset The column to start at. +**/ +EFI_STATUS +FileBufferReplaceAll ( + IN CHAR16 *SearchStr, + IN CHAR16 *ReplaceStr, + IN UINTN Offset + ); + +/** + Move the mouse cursor position. + + @param[in] TextX The new x-coordinate. + @param[in] TextY The new y-coordinate. +**/ +VOID +FileBufferAdjustMousePosition ( + IN CONST INT32 TextX, + IN CONST INT32 TextY + ); + +/** + Set the modified state to TRUE. +**/ +VOID +FileBufferSetModified ( + VOID + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c new file mode 100644 index 0000000..9810c2f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c @@ -0,0 +1,1980 @@ +/** @file + Implements editor interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "TextEditor.h" +#include "EditStatusBar.h" +#include "EditInputBar.h" +#include "EditMenuBar.h" + +// +// the first time editor launch +// +BOOLEAN EditorFirst; + +// +// it's time editor should exit +// +BOOLEAN EditorExit; + +BOOLEAN EditorMouseAction; + +extern EFI_EDITOR_FILE_BUFFER FileBuffer; + +extern BOOLEAN FileBufferNeedRefresh; + +extern BOOLEAN FileBufferOnlyLineNeedRefresh; + +extern BOOLEAN FileBufferMouseNeedRefresh; + +extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar; + +EFI_EDITOR_GLOBAL_EDITOR MainEditor; + + +/** + Load a file from disk to editor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainCommandOpenFile ( + VOID + ); + +/** + Switch a file from ASCII to UNICODE or vise-versa. + + @retval EFI_SUCCESS The switch was ok or a warning was presented. +**/ +EFI_STATUS +MainCommandSwitchFileType ( + VOID + ); + +/** + move cursor to specified lines + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainCommandGotoLine ( + VOID + ); + +/** + Save current file to disk, you can save to current file name or + save to another file name. + + @retval EFI_SUCCESS The file was saved correctly. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A file access error occured. +**/ +EFI_STATUS +MainCommandSaveFile ( + VOID + ); + +/** + Show help information for the editor. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainCommandDisplayHelp ( + VOID + ); + +/** + exit editor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandExit ( + VOID + ); + +/** + search string in file buffer + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandSearch ( + VOID + ); + +/** + search string in file buffer, and replace it with another str + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandSearchReplace ( + VOID + ); + +/** + cut current line to clipboard + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandCutLine ( + VOID + ); + +/** + paste line to file buffer. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandPasteLine ( + VOID + ); + +/** + Help info that will be displayed. +**/ +EFI_STRING_ID MainMenuHelpInfo[] = { + STRING_TOKEN(STR_EDIT_HELP_TITLE), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_LIST_TITLE), + STRING_TOKEN(STR_EDIT_HELP_DIV), + STRING_TOKEN(STR_EDIT_HELP_GO_TO_LINE), + STRING_TOKEN(STR_EDIT_HELP_SAVE_FILE), + STRING_TOKEN(STR_EDIT_HELP_EXIT), + STRING_TOKEN(STR_EDIT_HELP_SEARCH), + STRING_TOKEN(STR_EDIT_HELP_SEARCH_REPLACE), + STRING_TOKEN(STR_EDIT_HELP_CUT_LINE), + STRING_TOKEN(STR_EDIT_HELP_PASTE_LINE), + STRING_TOKEN(STR_EDIT_HELP_OPEN_FILE), + STRING_TOKEN(STR_EDIT_HELP_FILE_TYPE), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_EXIT_HELP), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_BLANK), + STRING_TOKEN(STR_EDIT_HELP_DIV), +0 +}; + +MENU_ITEM_FUNCTION MainControlBasedMenuFunctions[] = { + NULL, + NULL, /* Ctrl - A */ + NULL, /* Ctrl - B */ + NULL, /* Ctrl - C */ + NULL, /* Ctrl - D */ + MainCommandDisplayHelp, /* Ctrl - E */ + MainCommandSearch, /* Ctrl - F */ + MainCommandGotoLine, /* Ctrl - G */ + NULL, /* Ctrl - H */ + NULL, /* Ctrl - I */ + NULL, /* Ctrl - J */ + MainCommandCutLine, /* Ctrl - K */ + NULL, /* Ctrl - L */ + NULL, /* Ctrl - M */ + NULL, /* Ctrl - N */ + MainCommandOpenFile, /* Ctrl - O */ + NULL, /* Ctrl - P */ + MainCommandExit, /* Ctrl - Q */ + MainCommandSearchReplace, /* Ctrl - R */ + MainCommandSaveFile, /* Ctrl - S */ + MainCommandSwitchFileType, /* Ctrl - T */ + MainCommandPasteLine, /* Ctrl - U */ + NULL, /* Ctrl - V */ + NULL, /* Ctrl - W */ + NULL, /* Ctrl - X */ + NULL, /* Ctrl - Y */ + NULL, /* Ctrl - Z */ +}; + +EDITOR_MENU_ITEM MainMenuItems[] = { + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1), + MainCommandGotoLine + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2), + MainCommandSaveFile + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3), + MainCommandExit + }, + + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4), + MainCommandSearch + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5), + MainCommandSearchReplace + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6), + MainCommandCutLine + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7), + MainCommandPasteLine + }, + + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8), + MainCommandOpenFile + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9), + MainCommandSwitchFileType + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F11), + MainCommandSwitchFileType + }, + + { + 0, + 0, + NULL + } +}; + + +/** + Load a file from disk to editor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainCommandOpenFile ( + VOID + ) +{ + BOOLEAN Done; + EFI_STATUS Status; + + // + // This command will open a file from current working directory. + // Read-only file can also be opened. But it can not be modified. + // Below is the scenario of Open File command: + // 1.IF currently opened file has not been modIFied, directly go to step . + // IF currently opened file has been modified, + // an Input Bar will be prompted as : + // "File Modified. Save ( Yes/No/Cancel) ?" + // IF user press 'y' or 'Y', currently opened file will be saved. + // IF user press 'n' or 'N', currently opened file will + // not be saved. + // IF user press 'c' or 'C' or ESC, Open File command ends and + // currently opened file is still opened. + // + // 2. An Input Bar will be prompted as : "File Name to Open: " + // IF user press ESC, Open File command ends and + // currently opened file is still opened. + // Any other inputs with a Return will + // cause currently opened file close. + // + // 3. IF user input file name is an existing file , this file will be read + // and opened. + // IF user input file name is a new file, this file will be created + // and opened. This file's type ( UNICODE or ASCII ) is the same + // with the old file. + // if current file is modified, so you need to choose + // whether to save it first. + // + if (MainEditor.FileBuffer->FileModified) { + + Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + // + // the answer is just one character + // + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + // + // loop for user's answer + // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' + // + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // want to save this file first + // + Status = FileBufferSave (MainEditor.FileBuffer->FileName); + if (EFI_ERROR (Status)) { + return Status; + } + + MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0); + FileBufferRestorePosition (); + Done = TRUE; + break; + + case L'n': + case L'N': + // + // the file won't be saved + // + Done = TRUE; + break; + + case L'c': + case L'C': + return EFI_SUCCESS; + } + } + } + // + // TO get the open file name + // + Status = InputBarSetPrompt (L"File Name to Open: "); + if (EFI_ERROR (Status)) { + FileBufferRead (MainEditor.FileBuffer->FileName, TRUE); + return Status; + } + + Status = InputBarSetStringSize (100); + if (EFI_ERROR (Status)) { + FileBufferRead (MainEditor.FileBuffer->FileName, TRUE); + return Status; + } + + while (1) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + // + // The input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + // + // CHECK if filename is valid + // + if (!IsValidFileName (InputBarGetString())) { + FileBufferRead (MainEditor.FileBuffer->FileName, TRUE); + StatusBarSetStatusString (L"Invalid File Name"); + return EFI_SUCCESS; + } + + break; + } + } + // + // read from disk + // + Status = FileBufferRead (InputBarGetString(), FALSE); + + if (EFI_ERROR (Status)) { + FileBufferRead (MainEditor.FileBuffer->FileName, TRUE); + return EFI_LOAD_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Switch a file from ASCII to UNICODE or vise-versa. + + @retval EFI_SUCCESS The switch was ok or a warning was presented. +**/ +EFI_STATUS +MainCommandSwitchFileType ( + VOID + ) +{ + // + // Below is the scenario of File Type command: + // After File Type is executed, file type will be changed to another type + // if file is read-only, can not be modified + // + if (MainEditor.FileBuffer->ReadOnly) { + StatusBarSetStatusString (L"Read Only File Can Not Be Modified"); + return EFI_SUCCESS; + } + + if (MainEditor.FileBuffer->FileType == FileTypeUnicode) { + MainEditor.FileBuffer->FileType = FileTypeAscii; + } else { + MainEditor.FileBuffer->FileType = FileTypeUnicode; + } + + MainEditor.FileBuffer->FileModified = TRUE; + + return EFI_SUCCESS; +} + +/** + cut current line to clipboard + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandCutLine ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EDITOR_LINE *Line; + + // + // This command will cut current line ( where cursor is on ) to clip board. + // And cursor will move to the beginning of next line. + // Below is the scenario of Cut Line command: + // 1. IF cursor is on valid line, current line will be cut to clip board. + // IF cursor is not on valid line, an Status String will be prompted : + // "Nothing to Cut". + // + Line = NULL; + Status = FileBufferCutLine (&Line); + if (Status == EFI_NOT_FOUND) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + MainEditor.CutLine = Line; + + return EFI_SUCCESS; +} + +/** + paste line to file buffer. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandPasteLine ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Below is the scenario of Paste Line command: + // 1. IF nothing is on clipboard, a Status String will be prompted : + // "No Line to Paste" and Paste Line command ends. + // IF something is on clipboard, insert it above current line. + // nothing on clipboard + // + if (MainEditor.CutLine == NULL) { + StatusBarSetStatusString (L"No Line to Paste"); + return EFI_SUCCESS; + } + + Status = FileBufferPasteLine (); + + return Status; +} + + +/** + search string in file buffer + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandSearch ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 *Buffer; + BOOLEAN Done; + UINTN Offset; + + // + // Below is the scenario of Search command: + // 1. An Input Bar will be prompted : "Enter Search String:". + // IF user press ESC, Search command ends. + // IF user just press Enter, Search command ends. + // IF user inputs the search string, do Step 2. + // + // 2. IF input search string is found, cursor will move to the first + // occurrence and do Step 3. + // IF input search string is not found, a Status String + // "Search String Not Found" will be prompted and Search command ends. + // + // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?". + // IF user press ESC, Search command ends. + // IF user press 'y' or 'Y', do Step 2. + // IF user press 'n' or 'N', Search command ends. + // IF user press 'c' or 'C', Search command ends. + // + Status = InputBarSetPrompt (L"Enter Search String: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (40); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + // + // just enter pressed + // + if (StrLen (InputBarGetString()) == 0) { + return EFI_SUCCESS; + } + + Buffer = CatSPrint (NULL, L"%s", InputBarGetString()); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // the first time , search from current position + // + Offset = 0; + do { + // + // since search may be continued to search multiple times + // so we need to backup editor each time + // + MainEditorBackup (); + + Status = FileBufferSearch (Buffer, Offset); + + if (Status == EFI_NOT_FOUND) { + break; + } + // + // Find next + // + Status = InputBarSetPrompt (L"Find Next (Yes/No) ?"); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + FreePool (Buffer); + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + Done = TRUE; + break; + + case L'n': + case L'N': + FreePool (Buffer); + return EFI_SUCCESS; + + } + // + // end of which + // + } + // + // end of while !Done + // for search second, third time, search from current position + strlen + // + Offset = StrLen (Buffer); + + } while (1); + // + // end of do + // + FreePool (Buffer); + StatusBarSetStatusString (L"Search String Not Found"); + + return EFI_SUCCESS; +} + +/** + Search string in file buffer, and replace it with another str. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandSearchReplace ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 *Search; + CHAR16 *Replace; + BOOLEAN Done; + BOOLEAN First; + BOOLEAN ReplaceOption; + UINTN SearchLen; + UINTN ReplaceLen; + BOOLEAN ReplaceAll; + + ReplaceOption = FALSE; + + // + // Below is the scenario of Search/Replace command: + // 1. An Input Bar is prompted : "Enter Search String:". + // IF user press ESC, Search/Replace command ends. + // IF user just press Enter, Search/Replace command ends. + // IF user inputs the search string S, do Step 2. + // + // 2. An Input Bar is prompted: "Replace With:". + // IF user press ESC, Search/Replace command ends. + // IF user inputs the replace string R, do Step 3. + // + // 3. IF input search string is not found, an Status String + // "Search String Not Found" will be prompted + // and Search/Replace command ends + // IF input search string is found, do Step 4. + // + // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?" + // IF user press 'y' or 'Y', S will be replaced with R and do Step 5 + // IF user press 'n' or 'N', S will not be replaced and do Step 5. + // IF user press 'a' or 'A', all the S from file current position on + // will be replaced with R and Search/Replace command ends. + // IF user press 'c' or 'C' or ESC, Search/Replace command ends. + // + // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?". + // IF user press ESC, Search/Replace command ends. + // IF user press 'y' or 'Y', do Step 3. + // IF user press 'n' or 'N', Search/Replace command ends. + // IF user press 'c' or 'C', Search/Replace command ends. + // input search string + // + Status = InputBarSetPrompt (L"Enter Search String: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (40); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + // + // if just pressed enter + // + if (StrLen (InputBarGetString()) == 0) { + return EFI_SUCCESS; + } + + Search = CatSPrint (NULL, L"%s", InputBarGetString()); + if (Search == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SearchLen = StrLen (Search); + + // + // input replace string + // + Status = InputBarSetPrompt (L"Replace With: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (40); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + Replace = CatSPrint (NULL, L"%s", InputBarGetString()); + if (Replace == NULL) { + FreePool (Search); + return EFI_OUT_OF_RESOURCES; + } + + ReplaceLen = StrLen (Replace); + + First = TRUE; + ReplaceAll = FALSE; + do { + // + // since search may be continued to search multiple times + // so we need to backup editor each time + // + MainEditorBackup (); + + if (First) { + Status = FileBufferSearch (Search, 0); + } else { + // + // if just replace, so skip this replace string + // if replace string is an empty string, so skip to next character + // + if (ReplaceOption) { + Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen); + } else { + Status = FileBufferSearch (Search, SearchLen); + } + } + + if (Status == EFI_NOT_FOUND) { + break; + } + // + // replace or not? + // + Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?"); + + if (EFI_ERROR (Status)) { + FreePool (Search); + FreePool (Replace); + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + FreePool (Search); + FreePool (Replace); + return Status; + } + + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + FreePool (Search); + FreePool (Replace); + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + Done = TRUE; + ReplaceOption = TRUE; + break; + + case L'n': + case L'N': + Done = TRUE; + ReplaceOption = FALSE; + break; + + case L'a': + case L'A': + Done = TRUE; + ReplaceOption = TRUE; + ReplaceAll = TRUE; + break; + + case L'c': + case L'C': + FreePool (Search); + FreePool (Replace); + return EFI_SUCCESS; + + } + // + // end of which + // + } + // + // end of while !Done + // Decide to Replace + // + if (ReplaceOption) { + // + // file is read-only + // + if (MainEditor.FileBuffer->ReadOnly) { + StatusBarSetStatusString (L"Read Only File Can Not Be Modified"); + return EFI_SUCCESS; + } + // + // replace all + // + if (ReplaceAll) { + Status = FileBufferReplaceAll (Search, Replace, 0); + FreePool (Search); + FreePool (Replace); + return Status; + } + // + // replace + // + Status = FileBufferReplace (Replace, SearchLen); + if (EFI_ERROR (Status)) { + FreePool (Search); + FreePool (Replace); + return Status; + } + } + // + // Find next + // + Status = InputBarSetPrompt (L"Find Next (Yes/No) ?"); + if (EFI_ERROR (Status)) { + FreePool (Search); + FreePool (Replace); + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + FreePool (Search); + FreePool (Replace); + return Status; + } + + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + FreePool (Search); + FreePool (Replace); + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + Done = TRUE; + break; + + case L'n': + case L'N': + FreePool (Search); + FreePool (Replace); + return EFI_SUCCESS; + + } + // + // end of which + // + } + // + // end of while !Done + // + First = FALSE; + + } while (1); + // + // end of do + // + FreePool (Search); + FreePool (Replace); + + StatusBarSetStatusString (L"Search String Not Found"); + + return EFI_SUCCESS; +} + +/** + exit editor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainCommandExit ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Below is the scenario of Exit command: + // 1. IF currently opened file is not modified, exit the editor and + // Exit command ends. + // IF currently opened file is modified, do Step 2 + // + // 2. An Input Bar will be prompted: + // "File modified. Save ( Yes/No/Cancel )?" + // IF user press 'y' or 'Y', currently opened file will be saved + // and Editor exits + // IF user press 'n' or 'N', currently opened file will not be saved + // and Editor exits. + // IF user press 'c' or 'C' or ESC, Exit command ends. + // if file has been modified, so will prompt user whether to save the changes + // + if (MainEditor.FileBuffer->FileModified) { + + Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // write file back to disk + // + Status = FileBufferSave (MainEditor.FileBuffer->FileName); + if (!EFI_ERROR (Status)) { + EditorExit = TRUE; + } + + return Status; + + case L'n': + case L'N': + EditorExit = TRUE; + return EFI_SUCCESS; + + case L'c': + case L'C': + return EFI_SUCCESS; + + } + } + } + + EditorExit = TRUE; + return EFI_SUCCESS; + +} + +/** + move cursor to specified lines + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainCommandGotoLine ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Row; + + // + // Below is the scenario of Go To Line command: + // 1. An Input Bar will be prompted : "Go To Line:". + // IF user press ESC, Go To Line command ends. + // IF user just press Enter, cursor remains unchanged. + // IF user inputs line number, do Step 2. + // + // 2. IF input line number is valid, move cursor to the beginning + // of specified line and Go To Line command ends. + // IF input line number is invalid, a Status String will be prompted: + // "No Such Line" and Go To Line command ends. + // + Status = InputBarSetPrompt (L"Go To Line: "); + if (EFI_ERROR (Status)) { + return Status; + } + // + // line number's digit <= 6 + // + Status = InputBarSetStringSize (6); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // press ESC + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + // + // if JUST press enter + // + if (StrLen (InputBarGetString()) == 0) { + return EFI_SUCCESS; + } + + Row = ShellStrToUintn (InputBarGetString()); + + // + // invalid line number + // + if (Row > MainEditor.FileBuffer->NumLines || Row <= 0) { + StatusBarSetStatusString (L"No Such Line"); + return EFI_SUCCESS; + } + // + // move cursor to that line's start + // + FileBufferMovePosition (Row, 1); + + return EFI_SUCCESS; +} + +/** + Save current file to disk, you can save to current file name or + save to another file name. + + @retval EFI_SUCCESS The file was saved correctly. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A file access error occured. +**/ +EFI_STATUS +MainCommandSaveFile ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 *FileName; + BOOLEAN OldFile; + CHAR16 *Str; + SHELL_FILE_HANDLE FileHandle; + EFI_FILE_INFO *Info; + + // + // This command will save currently opened file to disk. + // You can choose save to another file name or just save to + // current file name. + // Below is the scenario of Save File command: + // ( Suppose the old file name is A ) + // 1. An Input Bar will be prompted: "File To Save: [ old file name]" + // IF user press ESC, Save File command ends . + // IF user press Enter, input file name will be A. + // IF user inputs a new file name B, input file name will be B. + // + // 2. IF input file name is A, go to do Step 3. + // IF input file name is B, go to do Step 4. + // + // 3. IF A is read only, Status Bar will show "Access Denied" and + // Save File commands ends. + // IF A is not read only, save file buffer to disk and remove modified + // flag in Title Bar , then Save File command ends. + // + // 4. IF B does not exist, create this file and save file buffer to it. + // Go to do Step 7. + // IF B exits, do Step 5. + // + // 5.An Input Bar will be prompted: + // "File Exists. Overwrite ( Yes/No/Cancel )?" + // IF user press 'y' or 'Y', do Step 6. + // IF user press 'n' or 'N', Save File commands ends. + // IF user press 'c' or 'C' or ESC, Save File commands ends. + // + // 6. IF B is a read-only file, Status Bar will show "Access Denied" and + // Save File commands ends. + // IF B can be read and write, save file buffer to B. + // + // 7. Update File Name field in Title Bar to B and remove the modified + // flag in Title Bar. + // + Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName); + if (Str == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (StrLen (Str) >= 50) { + // + // replace the long file name with "..." + // + Str[46] = L'.'; + Str[47] = L'.'; + Str[48] = L'.'; + Str[49] = L']'; + Str[50] = CHAR_NULL; + } + + Status = InputBarSetPrompt (Str); + FreePool(Str); + + if (EFI_ERROR (Status)) { + return Status; + } + + + Status = InputBarSetStringSize (100); + if (EFI_ERROR (Status)) { + return Status; + } + // + // get new file name + // + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // if user pressed ESC + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + // + // if just enter pressed, so think save to current file name + // + if (StrLen (InputBarGetString()) == 0) { + FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName); + } else { + FileName = CatSPrint (NULL, L"%s", InputBarGetString()); + } + + if (FileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (!IsValidFileName (FileName)) { + StatusBarSetStatusString (L"Invalid File Name"); + FreePool (FileName); + return EFI_SUCCESS; + } + + OldFile = FALSE; + + // + // save to the old file + // + if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) { + OldFile = TRUE; + } + + if (OldFile) { + // + // if the file is read only, so can not write back to it. + // + if (MainEditor.FileBuffer->ReadOnly == TRUE) { + StatusBarSetStatusString (L"Access Denied"); + FreePool (FileName); + return EFI_SUCCESS; + } + } else { + // + // if the file exists + // + if (ShellFileExists(FileName) != EFI_NOT_FOUND) { + // + // check for read only + // + Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + StatusBarSetStatusString (L"Open Failed"); + FreePool (FileName); + return EFI_SUCCESS; + } + + Info = ShellGetFileInfo(FileHandle); + if (Info == NULL) { + StatusBarSetStatusString (L"Access Denied"); + FreePool (FileName); + return (EFI_SUCCESS); + } + + if (Info->Attribute & EFI_FILE_READ_ONLY) { + StatusBarSetStatusString (L"Access Denied - Read Only"); + FreePool (Info); + FreePool (FileName); + return (EFI_SUCCESS); + } + FreePool (Info); + + // + // ask user whether to overwrite this file + // + Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (FileName); + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (FileName); + return Status; + } + + while (TRUE) { + Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column); + StatusBarSetRefresh(); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + break; + + case L'n': + case L'N': + case L'c': + case L'C': + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } // end switch + } // while (!done) + } // file does exist + } // if old file name same + + // + // save file to disk with specified name + // + FileBufferSetModified(); + Status = FileBufferSave (FileName); + SHELL_FREE_NON_NULL (FileName); + + return Status; +} + +/** + Show help information for the editor. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainCommandDisplayHelp ( + VOID + ) +{ + INT32 CurrentLine; + CHAR16 *InfoString; + EFI_KEY_DATA KeyData; + EFI_STATUS Status; + UINTN EventIndex; + + // + // print helpInfo + // + for (CurrentLine = 0; 0 != MainMenuHelpInfo[CurrentLine]; CurrentLine++) { + InfoString = HiiGetString(gShellDebug1HiiHandle, MainMenuHelpInfo[CurrentLine], NULL); + ShellPrintEx (0, CurrentLine+1, L"%E%s%N", InfoString); + } + + // + // scan for ctrl+w + // + while (TRUE) { + Status = gBS->WaitForEvent (1, &MainEditor.TextInputEx->WaitForKeyEx, &EventIndex); + if (EFI_ERROR (Status) || (EventIndex != 0)) { + continue; + } + Status = MainEditor.TextInputEx->ReadKeyStrokeEx (MainEditor.TextInputEx, &KeyData); + if (EFI_ERROR (Status)) { + continue; + } + + if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || + (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID)) { + // + // For consoles that don't support/report shift state, + // CTRL+W is translated to L'W' - L'A' + 1. + // + if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) { + break; + } + } else if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) && + ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) && + ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0)) { + // + // For consoles that supports/reports shift state, + // make sure that only CONTROL shift key is pressed. + // + if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar == 'W')) { + break; + } + } + } + // + // update screen with file buffer's info + // + FileBufferRestorePosition (); + FileBufferNeedRefresh = TRUE; + FileBufferOnlyLineNeedRefresh = FALSE; + FileBufferRefresh (); + + return EFI_SUCCESS; +} + +EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors; +INTN OriginalMode; + + +// +// basic initialization for MainEditor +// +EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = { + &FileBuffer, + { + {0, 0} + }, + { + 0, + 0 + }, + NULL, + NULL, + FALSE, + NULL +}; + +/** + The initialization function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainEditorInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + + // + // basic initialization + // + CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor)); + + // + // set screen attributes + // + MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff; + + MainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4); + OriginalColors = MainEditor.ColorAttributes.Colors; + + OriginalMode = gST->ConOut->Mode->Mode; + + // + // query screen size + // + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &(MainEditor.ScreenSize.Column), + &(MainEditor.ScreenSize.Row) + ); + + // + // Find TextInEx in System Table ConsoleInHandle + // Per UEFI Spec, TextInEx is required for a console capable platform. + // + Status = gBS->HandleProtocol ( + gST->ConsoleInHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID**)&MainEditor.TextInputEx + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find mouse in System Table ConsoleInHandle + // + Status = gBS->HandleProtocol ( + gST->ConsoleInHandle, + &gEfiSimplePointerProtocolGuid, + (VOID**)&MainEditor.MouseInterface + ); + if (EFI_ERROR (Status)) { + // + // If there is no Simple Pointer Protocol on System Table + // + HandleBuffer = NULL; + MainEditor.MouseInterface = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimplePointerProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status) && HandleCount > 0) { + // + // Try to find the first available mouse device + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiSimplePointerProtocolGuid, + (VOID**)&MainEditor.MouseInterface + ); + if (!EFI_ERROR (Status)) { + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + } + + if (!EFI_ERROR (Status) && MainEditor.MouseInterface != NULL) { + MainEditor.MouseAccumulatorX = 0; + MainEditor.MouseAccumulatorY = 0; + MainEditor.MouseSupported = TRUE; + } + + // + // below will call the five components' init function + // + Status = MainTitleBarInit (L"UEFI EDIT"); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + Status = ControlHotKeyInit (MainControlBasedMenuFunctions); + Status = MenuBarInit (MainMenuItems); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + Status = StatusBarInit (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + InputBarInit (MainEditor.TextInputEx); + + Status = FileBufferInit (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + // + // clear whole screen and enable cursor + // + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + // + // initialize EditorFirst and EditorExit + // + EditorFirst = TRUE; + EditorExit = FALSE; + EditorMouseAction = FALSE; + + return EFI_SUCCESS; +} + +/** + The cleanup function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainEditorCleanup ( + VOID + ) +{ + EFI_STATUS Status; + + // + // call the five components' cleanup function + // if error, do not exit + // just print some warning + // + MainTitleBarCleanup(); + StatusBarCleanup(); + InputBarCleanup(); + MenuBarCleanup (); + + Status = FileBufferCleanup (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle); + } + // + // restore old mode + // + if (OriginalMode != gST->ConOut->Mode->Mode) { + gST->ConOut->SetMode (gST->ConOut, OriginalMode); + } + // + // restore old screen color + // + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background) + ); + + gST->ConOut->ClearScreen (gST->ConOut); + + return EFI_SUCCESS; +} + +/** + Refresh the main editor component. +**/ +VOID +MainEditorRefresh ( + VOID + ) +{ + // + // The Stall value is from experience. NOT from spec. avoids 'flicker' + // + gBS->Stall (50); + + // + // call the components refresh function + // + if (EditorFirst + || StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0 + || FileBufferBackupVar.FileType != FileBuffer.FileType + || FileBufferBackupVar.FileModified != FileBuffer.FileModified + || FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly) { + + MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0); + FileBufferRestorePosition (); + } + + if (EditorFirst + || FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row + || FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column + || FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert + || StatusBarGetRefresh()) { + + StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert); + FileBufferRestorePosition (); + } + + if (EditorFirst) { + FileBufferRestorePosition (); + } + + FileBufferRefresh (); + + // + // EditorFirst is now set to FALSE + // + EditorFirst = FALSE; +} + +/** + Get's the resultant location of the cursor based on the relative movement of the Mouse. + + @param[in] GuidX The relative mouse movement. + + @return The X location of the mouse. +**/ +INT32 +GetTextX ( + IN INT32 GuidX + ) +{ + INT32 Gap; + + MainEditor.MouseAccumulatorX += GuidX; + Gap = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX); + MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX); + MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32) MainEditor.ScreenSize.Column; + return Gap; +} + +/** + Get's the resultant location of the cursor based on the relative movement of the Mouse. + + @param[in] GuidY The relative mouse movement. + + @return The Y location of the mouse. +**/ +INT32 +GetTextY ( + IN INT32 GuidY + ) +{ + INT32 Gap; + + MainEditor.MouseAccumulatorY += GuidY; + Gap = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY); + MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY); + MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32) MainEditor.ScreenSize.Row; + + return Gap; +} + +/** + Support mouse movement. Move the cursor. + + @param[in] MouseState The current mouse state. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND There was no mouse support found. +**/ +EFI_STATUS +MainEditorHandleMouseInput ( + IN EFI_SIMPLE_POINTER_STATE MouseState + ) +{ + + INT32 TextX; + INT32 TextY; + UINTN FRow; + UINTN FCol; + + LIST_ENTRY *Link; + EFI_EDITOR_LINE *Line; + + UINTN Index; + BOOLEAN Action; + + // + // mouse action means: + // mouse movement + // mouse left button + // + Action = FALSE; + + // + // have mouse movement + // + if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) { + // + // handle + // + TextX = GetTextX (MouseState.RelativeMovementX); + TextY = GetTextY (MouseState.RelativeMovementY); + + FileBufferAdjustMousePosition (TextX, TextY); + + Action = TRUE; + + } + + // + // if left button pushed down + // + if (MouseState.LeftButton) { + + FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1; + + FRow = MainEditor.FileBuffer->FilePosition.Row + + MainEditor.FileBuffer->MousePosition.Row - + MainEditor.FileBuffer->DisplayPosition.Row; + + // + // beyond the file line length + // + if (MainEditor.FileBuffer->NumLines < FRow) { + FRow = MainEditor.FileBuffer->NumLines; + } + + Link = MainEditor.FileBuffer->ListHead->ForwardLink; + for (Index = 0; Index < FRow - 1; Index++) { + Link = Link->ForwardLink; + } + + Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE); + + // + // beyond the line's column length + // + if (FCol > Line->Size + 1) { + FCol = Line->Size + 1; + } + + FileBufferMovePosition (FRow, FCol); + + MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row; + + MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column; + + Action = TRUE; + } + // + // mouse has action + // + if (Action) { + return EFI_SUCCESS; + } + + // + // no mouse action + // + return EFI_NOT_FOUND; +} + +/** + Handle user key input. This routes to other functions for the actions. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainEditorKeyInput ( + VOID + ) +{ + EFI_KEY_DATA KeyData; + EFI_STATUS Status; + EFI_SIMPLE_POINTER_STATE MouseState; + BOOLEAN NoShiftState; + + do { + + Status = EFI_SUCCESS; + EditorMouseAction = FALSE; + + // + // backup some key elements, so that can aVOID some refresh work + // + MainEditorBackup (); + + // + // change priority of checking mouse/keyboard activity dynamically + // so prevent starvation of keyboard. + // if last time, mouse moves then this time check keyboard + // + if (MainEditor.MouseSupported) { + Status = MainEditor.MouseInterface->GetState ( + MainEditor.MouseInterface, + &MouseState + ); + if (!EFI_ERROR (Status)) { + + Status = MainEditorHandleMouseInput (MouseState); + + if (!EFI_ERROR (Status)) { + EditorMouseAction = TRUE; + FileBufferMouseNeedRefresh = TRUE; + } else if (Status == EFI_LOAD_ERROR) { + StatusBarSetStatusString (L"Invalid Mouse Movement "); + } + } + } + + // + // CheckEvent() returns Success when non-partial key is pressed. + // + Status = gBS->CheckEvent (MainEditor.TextInputEx->WaitForKeyEx); + if (!EFI_ERROR (Status)) { + Status = MainEditor.TextInputEx->ReadKeyStrokeEx (MainEditor.TextInputEx, &KeyData); + if (!EFI_ERROR (Status)) { + // + // dispatch to different components' key handling function + // so not everywhere has to set this variable + // + FileBufferMouseNeedRefresh = TRUE; + // + // clear previous status string + // + StatusBarSetRefresh(); + // + // NoShiftState: TRUE when no shift key is pressed. + // + NoShiftState = ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID); + // + // dispatch to different components' key handling function + // + if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey(&KeyData)) { + Status = EFI_SUCCESS; + } else if (NoShiftState && ((KeyData.Key.ScanCode == SCAN_NULL) || ((KeyData.Key.ScanCode >= SCAN_UP) && (KeyData.Key.ScanCode <= SCAN_PAGE_DOWN)))) { + Status = FileBufferHandleInput (&KeyData.Key); + } else if (NoShiftState && (KeyData.Key.ScanCode >= SCAN_F1) && (KeyData.Key.ScanCode <= SCAN_F12)) { + Status = MenuBarDispatchFunctionKey (&KeyData.Key); + } else { + StatusBarSetStatusString (L"Unknown Command"); + FileBufferMouseNeedRefresh = FALSE; + } + + if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) { + // + // not already has some error status + // + if (StatusBarGetString() != NULL && StrCmp (L"", StatusBarGetString()) == 0) { + StatusBarSetStatusString (L"Disk Error. Try Again"); + } + } + + } + } + // + // after handling, refresh editor + // + MainEditorRefresh (); + + } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit); + + return Status; +} + +/** + Set clipboard + + @param[in] Line A pointer to the line to be set to clipboard + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainEditorSetCutLine ( + EFI_EDITOR_LINE *Line + ) +{ + if (Line == NULL) { + return EFI_SUCCESS; + } + + if (MainEditor.CutLine != NULL) { + // + // free the old clipboard + // + LineFree (MainEditor.CutLine); + } + // + // duplicate the line to clipboard + // + MainEditor.CutLine = LineDup (Line); + if (MainEditor.CutLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Backup function for MainEditor + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainEditorBackup ( + VOID + ) +{ + FileBufferBackup (); + + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h new file mode 100644 index 0000000..11b9661 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h @@ -0,0 +1,72 @@ +/** @file + Declares editor interface functions. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_EDITOR_H_ +#define _LIB_EDITOR_H_ + +#include "TextEditorTypes.h" + +/** + The initialization function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainEditorInit ( + VOID + ); + +/** + The cleanup function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +MainEditorCleanup ( + VOID + ); + +/** + Refresh the main editor component. +**/ +VOID +MainEditorRefresh ( + VOID + ); + +/** + Handle user key input. This routes to other functions for the actions. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainEditorKeyInput ( + VOID + ); + +/** + Backup function for MainEditor + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainEditorBackup ( + VOID + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c new file mode 100644 index 0000000..370695b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c @@ -0,0 +1,90 @@ +/** @file + Implementation of various string and line routines. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "TextEditor.h" +#include "Misc.h" + +/** + Duplicate a EFI_EDITOR_LINE structure. + + @param Src The line structure to copy from. + + @retval NULL A memory allocation failed. + @return a pointer to the newly allcoated line. +**/ +EFI_EDITOR_LINE * +LineDup ( + IN EFI_EDITOR_LINE *Src + ) +{ + EFI_EDITOR_LINE *Dest; + + // + // allocate for the line structure + // + Dest = AllocateZeroPool (sizeof (EFI_EDITOR_LINE)); + if (Dest == NULL) { + return NULL; + } + // + // allocate and set the line buffer + // + Dest->Buffer = CatSPrint (NULL, L"%s", Src->Buffer); + if (Dest->Buffer == NULL) { + FreePool (Dest); + return NULL; + } + + // + // set the other structure members + // + Dest->Signature = LINE_LIST_SIGNATURE; + Dest->Size = Src->Size; + Dest->TotalSize = Dest->Size; + Dest->Type = Src->Type; + Dest->Link = Src->Link; + + return Dest; +} + +/** + Free a EFI_EDITOR_LINE structure. + + @param Src The line structure to free. +**/ +VOID +LineFree ( + IN EFI_EDITOR_LINE *Src + ) +{ + if (Src == NULL) { + return ; + } + // + // free the line buffer and then the line structure itself + // + SHELL_FREE_NON_NULL (Src->Buffer); + SHELL_FREE_NON_NULL (Src); + +} + + + + + + + + + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h new file mode 100644 index 0000000..288e25e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h @@ -0,0 +1,50 @@ +/** @file + Declares generic editor helper functions. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_MISC_H_ +#define _LIB_MISC_H_ + +#include "TextEditorTypes.h" + + + +/** + Free a EFI_EDITOR_LINE structure. + + @param Src The line structure to free. +**/ +VOID +LineFree ( + IN EFI_EDITOR_LINE *Src + ); + +/** + Duplicate a EFI_EDITOR_LINE structure. + + @param Src The line structure to copy from. + + @retval NULL A memory allocation failed. + @return a pointer to the newly allcoated line. +**/ +EFI_EDITOR_LINE * +LineDup ( + IN EFI_EDITOR_LINE *Src + ); + + + + + + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni new file mode 100644 index 0000000..e5bcb88 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni @@ -0,0 +1,75 @@ +// /** +// +// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Abstract: +// +// Additional string definitions for UEFI Shell 2.0 Debug1 profile Edit command +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_EDIT_LIBEDITOR_TITLEBAR #language en-US "%EMainEditor init failed on TitleBar init\r\n%N" +#string STR_EDIT_LIBEDITOR_MAINMENU #language en-US "%EMainEditor init was not successful on MainMenu init\r\n%N" +#string STR_EDIT_LIBEDITOR_STATUSBAR #language en-US "%EMainEditor init was not successful on StatusBar init\r\n%N" +#string STR_EDIT_LIBEDITOR_INPUTBAR #language en-US "%EMainEditor init was not successful on InputBar init\r\n%N" +#string STR_EDIT_LIBEDITOR_FILEBUFFER #language en-US "%EMainEditor init was not successful on FileBuffer init\r\n%N" +#string STR_EDIT_LIBEDITOR_TITLEBAR_CLEANUP #language en-US "TitleBar cleanup was not successful\r\n" +#string STR_EDIT_LIBEDITOR_MENUBAR_CLEANUP #language en-US "MenuBar cleanup was not successful\r\n" +#string STR_EDIT_LIBEDITOR_STATUSBAR_CLEANUP #language en-US "StatusBar cleanup was not successful\r\n" +#string STR_EDIT_LIBEDITOR_INPUTBAR_CLEANUP #language en-US "InputBar cleanup was not successful\r\n" +#string STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP #language en-US "FileBuffer cleanup was not successful\r\n" +#string STR_EDIT_LIBEDITOR_MAINEDITOR_INIT #language en-US "%EMainEditor init was not succesful on TitleBar init\r\n%N" +#string STR_EDIT_LIBINPUTBAR_MAININPUTBAR #language en-US "%s" +#string STR_EDIT_LIBMENUBAR_OPEN_FILE #language en-US "Open File" +#string STR_EDIT_LIBMENUBAR_SAVE_FILE #language en-US "Save File" +#string STR_EDIT_LIBMENUBAR_EXIT #language en-US "Exit" +#string STR_EDIT_LIBMENUBAR_CUT_LINE #language en-US "Cut Line" +#string STR_EDIT_LIBMENUBAR_PASTE_LINE #language en-US "Paste Line" +#string STR_EDIT_LIBMENUBAR_GO_TO_LINE #language en-US "Go To Line" +#string STR_EDIT_LIBMENUBAR_SEARCH #language en-US "Search" +#string STR_EDIT_LIBMENUBAR_SEARCH_REPLACE #language en-US "Search/Replace" +#string STR_EDIT_LIBMENUBAR_FILE_TYPE #language en-US "File Type" +#string STR_EDIT_LIBMENUBAR_F1 #language en-US "F1" +#string STR_EDIT_LIBMENUBAR_F2 #language en-US "F2" +#string STR_EDIT_LIBMENUBAR_F3 #language en-US "F3" +#string STR_EDIT_LIBMENUBAR_F4 #language en-US "F4" +#string STR_EDIT_LIBMENUBAR_F5 #language en-US "F5" +#string STR_EDIT_LIBMENUBAR_F6 #language en-US "F6" +#string STR_EDIT_LIBMENUBAR_F7 #language en-US "F7" +#string STR_EDIT_LIBMENUBAR_F8 #language en-US "F8" +#string STR_EDIT_LIBMENUBAR_F9 #language en-US "F9" +#string STR_EDIT_LIBMENUBAR_F10 #language en-US "F10" +#string STR_EDIT_LIBMENUBAR_F11 #language en-US "F11" +#string STR_EDIT_LIBMENUBAR_F12 #language en-US "F12" +#string STR_EDIT_LIBMENUBAR_CTRL_E #language en-US "Ctrl+E" +#string STR_EDIT_LIBMENUBAR_CTRL_W #language en-US "Ctrl+W" +#string STR_EDIT_HELP_TITLE #language en-US "Help \n" +#string STR_EDIT_HELP_BLANK #language en-US " \n" +#string STR_EDIT_HELP_LIST_TITLE #language en-US "Control Key Function Key Command \n" +#string STR_EDIT_HELP_DIV #language en-US "----------- ------------ ----------------- \n" +#string STR_EDIT_HELP_GO_TO_LINE #language en-US "Ctrl-G F1 Go To Line \n" +#string STR_EDIT_HELP_SAVE_FILE #language en-US "Ctrl-S F2 Save File \n" +#string STR_EDIT_HELP_EXIT #language en-US "Ctrl-Q F3 Exit \n" +#string STR_EDIT_HELP_SEARCH #language en-US "Ctrl-F F4 Search \n" +#string STR_EDIT_HELP_SEARCH_REPLACE #language en-US "Ctrl-R F5 Search/Replace \n" +#string STR_EDIT_HELP_CUT_LINE #language en-US "Ctrl-K F6 Cut Line \n" +#string STR_EDIT_HELP_PASTE_LINE #language en-US "Ctrl-U F7 Paste Line \n" +#string STR_EDIT_HELP_OPEN_FILE #language en-US "Ctrl-O F8 Open File \n" +#string STR_EDIT_HELP_FILE_TYPE #language en-US "Ctrl-T F9 File Type \n" +#string STR_EDIT_HELP_EXIT_HELP #language en-US "Use Ctrl-W to exit this help \n" +#string STR_EDIT_MAIN_INVALID_FILE_NAME #language en-US "%Hedit%N: Invalid File Name\r\n" +#string STR_EDIT_MAIN_INIT_FAILED #language en-US "%Hedit%N: Initialization was not successful\r\n" +#string STR_EDIT_MAIN_BUFFER #language en-US "%Hedit%N: %s\r\n" +#string STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR #language en-US "%Hedit%N: Unknown Editor Error\r\n" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h new file mode 100644 index 0000000..321fec7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h @@ -0,0 +1,32 @@ +/** @file + Main include file for Edit shell Debug1 function. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_EDIT_H_ +#define _EFI_EDIT_H_ + +#include "TextEditorTypes.h" + +#include "MainTextEditor.h" +#include "FileBuffer.h" +#include "EditTitleBar.h" +#include "EditStatusBar.h" +#include "EditInputBar.h" +#include "EditMenuBar.h" +#include "Misc.h" + +extern EFI_EDITOR_GLOBAL_EDITOR MainEditor; +extern BOOLEAN EditorFirst; +extern BOOLEAN EditorExit; + +#endif // _EFI_EDIT_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h new file mode 100644 index 0000000..4a8cdc2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h @@ -0,0 +1,103 @@ +/** @file + Declares editor types. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EDITOR_TYPE_H_ +#define _EDITOR_TYPE_H_ + +#include "UefiShellDebug1CommandsLib.h" +#include "EditTitleBar.h" +#include "EditMenuBar.h" + +#define MIN_POOL_SIZE 125 +#define MAX_STRING_LENGTH 127 + +typedef struct { + UINTN Row; + UINTN Column; +} EFI_EDITOR_POSITION; + +typedef +EFI_STATUS +(*EFI_MENU_ITEM_FUNCTION) ( + VOID + ); + +typedef enum { + NewLineTypeDefault, + NewLineTypeLineFeed, + NewLineTypeCarriageReturn, + NewLineTypeCarriageReturnLineFeed, + NewLineTypeLineFeedCarriageReturn, + NewLineTypeUnknown +} EE_NEWLINE_TYPE; + +#define LINE_LIST_SIGNATURE SIGNATURE_32 ('e', 'e', 'l', 'l') +typedef struct _EFI_EDITOR_LINE { + UINTN Signature; + CHAR16 *Buffer; + UINTN Size; // unit is Unicode + UINTN TotalSize; // unit is Unicode, exclude CHAR_NULL + EE_NEWLINE_TYPE Type; + LIST_ENTRY Link; +} EFI_EDITOR_LINE; + +typedef struct { + UINT32 Foreground : 4; + UINT32 Background : 4; +} EFI_EDITOR_COLOR_ATTRIBUTES; + +typedef union { + EFI_EDITOR_COLOR_ATTRIBUTES Colors; + UINTN Data; +} EFI_EDITOR_COLOR_UNION; + +typedef struct { + UINTN Columns; + UINTN Rows; +} EFI_EDITOR_TEXT_MODE; + +typedef struct { + CHAR16 *FileName; // file name current edited in editor + EDIT_FILE_TYPE FileType; // Unicode file or ASCII file + LIST_ENTRY *ListHead; // list head of lines + EFI_EDITOR_LINE *Lines; // lines of current file + UINTN NumLines; // total line numbers + EFI_EDITOR_POSITION DisplayPosition; // cursor position in screen + EFI_EDITOR_POSITION FilePosition; // cursor position in file + EFI_EDITOR_POSITION MousePosition; // mouse position in screen + // file position of first byte displayed on screen + // + EFI_EDITOR_POSITION LowVisibleRange; + + BOOLEAN FileModified; // file is modified or not + BOOLEAN ModeInsert; // input mode INS or OVR + BOOLEAN ReadOnly; // file is read-only or not + EFI_EDITOR_LINE *CurrentLine; // current line cursor is at +} EFI_EDITOR_FILE_BUFFER; + +typedef struct { + EFI_EDITOR_FILE_BUFFER *FileBuffer; + + EFI_EDITOR_COLOR_UNION ColorAttributes; + EFI_EDITOR_POSITION ScreenSize; // row number and column number + EFI_EDITOR_LINE *CutLine; // clip board + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx; + BOOLEAN MouseSupported; + EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface; + INT32 MouseAccumulatorX; + INT32 MouseAccumulatorY; + +} EFI_EDITOR_GLOBAL_EDITOR; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c new file mode 100644 index 0000000..b79fe7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c @@ -0,0 +1,330 @@ +/** @file + Implements inputbar interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "EditInputBar.h" +#include "UefiShellDebug1CommandsLib.h" + +CHAR16 *mPrompt; // Input bar mPrompt string. +CHAR16 *mReturnString; // The returned string. +UINTN StringSize; // Size of mReturnString space size. +EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *mTextInEx; + +/** + Initialize the input bar. + + @param[in] TextInEx Pointer to SimpleTextInEx instance in System Table. +**/ +VOID +InputBarInit ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +{ + mPrompt = NULL; + mReturnString = NULL; + StringSize = 0; + mTextInEx = TextInEx; +} + +/** + Cleanup function for input bar. +**/ +VOID +InputBarCleanup ( + VOID + ) +{ + // + // free input bar's prompt and input string + // + SHELL_FREE_NON_NULL (mPrompt); + SHELL_FREE_NON_NULL (mReturnString); + mPrompt = NULL; + mReturnString = NULL; +} + +/** + Display the prompt. + Do the requesting of input. + + @param[in] LastColumn The last printable column. + @param[in] LastRow The last printable row. +**/ +VOID +InputBarPrintInput ( + IN UINTN LastColumn, + IN UINTN LastRow + ) +{ + UINTN Limit; + UINTN Size; + CHAR16 *Buffer; + UINTN Index; + UINTN mPromptLen; + + mPromptLen = StrLen (mPrompt); + Limit = LastColumn - mPromptLen - 1; + Size = StrLen (mReturnString); + + // + // check whether the mPrompt length and input length will + // exceed limit + // + if (Size <= Limit) { + Buffer = mReturnString; + } else { + Buffer = mReturnString + Size - Limit; + } + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + ShellPrintEx (((INT32)mPromptLen), ((INT32)LastRow) - 1, L"%s", Buffer); + Size = StrLen (Buffer); + + // + // print " " after mPrompt + // + for (Index = Size; Index < Limit; Index++) { + ShellPrintEx ((INT32)(mPromptLen + Size), ((INT32)LastRow) - 1, L" "); + } + + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + gST->ConOut->SetCursorPosition (gST->ConOut, Size + mPromptLen, LastRow - 1); +} + +typedef struct { + UINT32 Foreground : 4; + UINT32 Background : 3; +} INPUT_BAR_COLOR_ATTRIBUTES; + +typedef union { + INPUT_BAR_COLOR_ATTRIBUTES Colors; + UINTN Data; +} INPUT_BAR_COLOR_UNION; + + +/** + The refresh function for InputBar, it will wait for user input + + @param[in] LastRow The last printable row. + @param[in] LastColumn The last printable column. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +InputBarRefresh ( + UINTN LastRow, + UINTN LastColumn + ) +{ + INPUT_BAR_COLOR_UNION Orig; + INPUT_BAR_COLOR_UNION New; + EFI_KEY_DATA KeyData; + UINTN Size; + EFI_STATUS Status; + BOOLEAN NoDisplay; + UINTN EventIndex; + UINTN CursorRow; + UINTN CursorCol; + + // + // variable initialization + // + Size = 0; + Status = EFI_SUCCESS; + + // + // back up the old screen attributes + // + CursorCol = gST->ConOut->Mode->CursorColumn; + CursorRow = gST->ConOut->Mode->CursorRow; + Orig.Data = gST->ConOut->Mode->Attribute; + New.Data = 0; + New.Colors.Foreground = Orig.Colors.Background & 0xF; + New.Colors.Background = Orig.Colors.Foreground & 0x7; + + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + + // + // clear input bar + // + EditorClearLine (LastRow , LastColumn, LastRow); + + gST->ConOut->SetCursorPosition (gST->ConOut, 0, LastRow - 1); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBINPUTBAR_MAININPUTBAR), gShellDebug1HiiHandle, mPrompt); + + // + // this is a selection mPrompt, cursor will stay in edit area + // actually this is for search , search/replace + // + if (StrStr (mPrompt, L"Yes/No")) { + NoDisplay = TRUE; + gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow); + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + } else { + NoDisplay = FALSE; + } + // + // wait for user input + // + for (;;) { + Status = gBS->WaitForEvent (1, &mTextInEx->WaitForKeyEx, &EventIndex); + if (EFI_ERROR (Status) || (EventIndex != 0)) { + continue; + } + Status = mTextInEx->ReadKeyStrokeEx (mTextInEx, &KeyData); + if (EFI_ERROR (Status)) { + continue; + } + if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) && + (KeyData.KeyState.KeyShiftState != EFI_SHIFT_STATE_VALID)) { + // + // Shift key pressed. + // + continue; + } + // + // pressed ESC + // + if (KeyData.Key.ScanCode == SCAN_ESC) { + Size = 0; + Status = EFI_NOT_READY; + break; + } + // + // return pressed + // + if (KeyData.Key.UnicodeChar == CHAR_LINEFEED || KeyData.Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } else if (KeyData.Key.UnicodeChar == CHAR_BACKSPACE) { + // + // backspace + // + if (Size > 0) { + Size--; + mReturnString[Size] = CHAR_NULL; + if (!NoDisplay) { + + InputBarPrintInput (LastColumn, LastRow); + + } + } + } else if (KeyData.Key.UnicodeChar <= 127 && KeyData.Key.UnicodeChar >= 32) { + // + // VALID ASCII char pressed + // + mReturnString[Size] = KeyData.Key.UnicodeChar; + + // + // should be less than specified length + // + if (Size >= StringSize) { + continue; + } + + Size++; + + mReturnString[Size] = CHAR_NULL; + + if (!NoDisplay) { + + InputBarPrintInput (LastColumn, LastRow); + + } else { + // + // if just choose yes/no + // + break; + } + + } + } + + mReturnString[Size] = CHAR_NULL; + + + // + // restore screen attributes + // + gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow); + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + + return Status; +} + +/** + SetPrompt and wait for input. + + @param[in] Str The prompt string. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +InputBarSetPrompt ( + IN CONST CHAR16 *Str + ) +{ + // + // FREE the old mPrompt string + // + SHELL_FREE_NON_NULL (mPrompt); + + mPrompt = CatSPrint (NULL, L"%s ", Str); + if (mPrompt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Set the size of the string in characters. + + @param[in] Size The max number of characters to accept. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +InputBarSetStringSize ( + UINTN Size + ) +{ + // + // free the old ReturnStirng + // + SHELL_FREE_NON_NULL (mReturnString); + + StringSize = Size; + mReturnString = AllocateZeroPool ((StringSize + 1) * sizeof(mReturnString[0])); + if (mReturnString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Function to retrieve the input from the user. + + @retval NULL No input has been received. + @return The string that was input. +**/ +CONST CHAR16* +InputBarGetString ( + VOID + ) +{ + return (mReturnString); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h new file mode 100644 index 0000000..475cca1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h @@ -0,0 +1,87 @@ +/** @file + Declares imputbar interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_INPUT_BAR_H_ +#define _LIB_INPUT_BAR_H_ + +/** + Initialize the input bar. + + @param[in] TextInEx Pointer to SimpleTextInEx instance in System Table. +**/ +VOID +InputBarInit ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ); + +/** + Cleanup function for input bar. +**/ +VOID +InputBarCleanup ( + VOID + ); + +/** + The refresh function for InputBar, it will wait for user input + + @param[in] LastRow The last printable row. + @param[in] LastColumn The last printable column. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +InputBarRefresh ( + UINTN LastRow, + UINTN LastColumn + ); + +/** + SetPrompt and wait for input. + + @param[in] Str The prompt string. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +InputBarSetPrompt ( + IN CONST CHAR16 *Str + ); + +/** + Set the size of the string in characters. + + @param[in] Size The max number of characters to accept. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +InputBarSetStringSize ( + UINTN Size + ); + +/** + Function to retrieve the input from the user. + + @retval NULL No input has been received. + @return The string that was input. +**/ +CONST CHAR16* +InputBarGetString ( + VOID + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c new file mode 100644 index 0000000..3047438 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c @@ -0,0 +1,216 @@ +/** @file + implements menubar interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "EditMenuBar.h" +#include "UefiShellDebug1CommandsLib.h" +#include "EditStatusBar.h" + +EDITOR_MENU_ITEM *MenuItems; +MENU_ITEM_FUNCTION *ControlBasedMenuFunctions; +UINTN NumItems; + +/** + Cleanup function for a menu bar. frees all allocated memory. +**/ +VOID +MenuBarCleanup ( + VOID + ) +{ + SHELL_FREE_NON_NULL(MenuItems); +} + +/** + Initialize the menu bar with the specified items. + + @param[in] Items The items to display and their functions. + + @retval EFI_SUCCESS The initialization was correct. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MenuBarInit ( + IN CONST EDITOR_MENU_ITEM *Items + ) +{ + CONST EDITOR_MENU_ITEM *ItemsWalker; + + for (NumItems = 0, ItemsWalker = Items ; ItemsWalker != NULL && ItemsWalker->Function != NULL ; ItemsWalker++,NumItems++); + + MenuItems = AllocateZeroPool((NumItems+1) * sizeof(EDITOR_MENU_ITEM)); + if (MenuItems == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem(MenuItems, Items, (NumItems+1) * sizeof(EDITOR_MENU_ITEM)); + return EFI_SUCCESS; +} + +/** + Initialize the control hot-key with the specified items. + + @param[in] Items The hot-key functions. + + @retval EFI_SUCCESS The initialization was correct. +**/ +EFI_STATUS +ControlHotKeyInit ( + IN MENU_ITEM_FUNCTION *Items + ) +{ + ControlBasedMenuFunctions = Items; + return EFI_SUCCESS; +} +/** + Refresh function for the menu bar. + + @param[in] LastRow The last printable row. + @param[in] LastCol The last printable column. + + @retval EFI_SUCCESS The refresh was successful. +**/ +EFI_STATUS +MenuBarRefresh ( + IN CONST UINTN LastRow, + IN CONST UINTN LastCol + ) +{ + EDITOR_MENU_ITEM *Item; + UINTN Col; + UINTN Row; + UINTN Width; + CHAR16 *NameString; + CHAR16 *FunctionKeyString; + + // + // variable initialization + // + Col = 1; + Row = (LastRow - 2); + + // + // clear menu bar rows + // + EditorClearLine (LastRow - 2, LastCol, LastRow); + EditorClearLine (LastRow - 1, LastCol, LastRow); + EditorClearLine (LastRow , LastCol, LastRow); + + + // + // print out the menu items + // + for (Item = MenuItems; Item != NULL && Item->Function != NULL; Item++) { + + + NameString = HiiGetString(gShellDebug1HiiHandle, Item->NameToken, NULL); + + + Width = MAX ((StrLen (NameString) + 6), 20); + if (((Col + Width) > LastCol)) { + Row++; + Col = 1; + } + + FunctionKeyString = HiiGetString(gShellDebug1HiiHandle, Item->FunctionKeyToken, NULL); + + ShellPrintEx ((INT32)(Col) - 1, (INT32)(Row) - 1, L"%E%s%N %H%s%N ", FunctionKeyString, NameString); + + FreePool (NameString); + FreePool (FunctionKeyString); + Col += Width; + } + + return EFI_SUCCESS; +} + +/** + Function to dispatch the correct function based on a function key (F1...) + + @param[in] Key The pressed key. + + @retval EFI_NOT_FOUND The key was not a valid function key + (an error was sent to the status bar). + @return The return value from the called dispatch function. +**/ +EFI_STATUS +MenuBarDispatchFunctionKey ( + IN CONST EFI_INPUT_KEY *Key + ) +{ + UINTN Index; + + Index = Key->ScanCode - SCAN_F1; + + // + // check whether in range + // + if (Index > (NumItems - 1)) { + StatusBarSetStatusString (L"Unknown Command"); + return EFI_SUCCESS; + } + + return (MenuItems[Index].Function ()); +} + +/** + Function to dispatch the correct function based on a control-based key (ctrl+o...) + + @param[in] KeyData The pressed key. + + @retval EFI_NOT_FOUND The key was not a valid control-based key + (an error was sent to the status bar). + @return EFI_SUCCESS. +**/ +EFI_STATUS +MenuBarDispatchControlHotKey ( + IN CONST EFI_KEY_DATA *KeyData + ) +{ + UINT16 ControlIndex; + + // + // Set to invalid value first. + // + ControlIndex = MAX_UINT16; + + if (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || + (KeyData->KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID)) { + // + // For consoles that don't support/report shift state, + // Ctrl+A is translated to 1 (UnicodeChar). + // + ControlIndex = KeyData->Key.UnicodeChar; + } else if (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) && + ((KeyData->KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)) != 0) && + ((KeyData->KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)) == 0)) { + // + // For consoles that supports/reports shift state, + // make sure only CONTROL is pressed. + // + if ((KeyData->Key.UnicodeChar >= L'A') && (KeyData->Key.UnicodeChar <= L'Z')) { + ControlIndex = KeyData->Key.UnicodeChar - L'A' + 1; + } else if ((KeyData->Key.UnicodeChar >= L'a') && (KeyData->Key.UnicodeChar <= L'z')) { + ControlIndex = KeyData->Key.UnicodeChar - L'a' + 1; + } + } + if ((SCAN_CONTROL_Z < ControlIndex) + ||(NULL == ControlBasedMenuFunctions[ControlIndex])) + { + return EFI_NOT_FOUND; + } + + ControlBasedMenuFunctions[ControlIndex](); + return EFI_SUCCESS; +} + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h new file mode 100644 index 0000000..f0fbefa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h @@ -0,0 +1,119 @@ +/** @file + Declares menubar interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_MENU_BAR_H_ +#define _LIB_MENU_BAR_H_ + +#define SCAN_CONTROL_E 5 +#define SCAN_CONTROL_F 6 +#define SCAN_CONTROL_G 7 +#define SCAN_CONTROL_K 11 +#define SCAN_CONTROL_O 15 +#define SCAN_CONTROL_Q 17 +#define SCAN_CONTROL_R 18 +#define SCAN_CONTROL_S 19 +#define SCAN_CONTROL_T 20 +#define SCAN_CONTROL_U 21 +#define SCAN_CONTROL_W 23 +#define SCAN_CONTROL_Z 26 + + +typedef +EFI_STATUS +(*MENU_ITEM_FUNCTION) ( + VOID + ); + +typedef struct _EDITOR_MENU_ITEM { + EFI_STRING_ID NameToken; + CHAR16 FunctionKeyToken; + MENU_ITEM_FUNCTION Function; +} EDITOR_MENU_ITEM; + +/** + Initializa the menu bar with the specified items. + + @param[in] Items The items to display and their functions. + + @retval EFI_SUCCESS The initialization was correct. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MenuBarInit ( + IN CONST EDITOR_MENU_ITEM *Items + ); + +/** + Initialize the control hot-key with the specified items. + + @param[in] Items The hot-key functions. + + @retval EFI_SUCCESS The initialization was correct. +**/ +EFI_STATUS +ControlHotKeyInit ( + IN MENU_ITEM_FUNCTION *Items + ); + +/** + Cleanup function for a menu bar. frees all allocated memory. +**/ +VOID +MenuBarCleanup ( + VOID + ); + +/** + Refresh function for the menu bar. + + @param[in] LastRow The last printable row. + @param[in] LastCol The last printable column. + + @retval EFI_SUCCESS The refresh was successful. +**/ +EFI_STATUS +MenuBarRefresh ( + IN CONST UINTN LastRow, + IN CONST UINTN LastCol + ); + +/** + Function to dispatch the correct function based on a function key (F1...) + + @param[in] Key The pressed key. + + @retval EFI_NOT_FOUND The key was not a valid function key + (an error was sent to the status bar). + @return The return value from the called dispatch function. +**/ +EFI_STATUS +MenuBarDispatchFunctionKey ( + IN CONST EFI_INPUT_KEY *Key + ); + +/** + Function to dispatch the correct function based on a control-based key (ctrl+o...) + + @param[in] KeyData The pressed key. + + @retval EFI_NOT_FOUND The key was not a valid control-based key + (an error was sent to the status bar). + @return EFI_SUCCESS. +**/ +EFI_STATUS +MenuBarDispatchControlHotKey ( + IN CONST EFI_KEY_DATA *KeyData + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c new file mode 100644 index 0000000..95f47fa --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c @@ -0,0 +1,230 @@ +/** @file + Implements statusbar interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "EditStatusBar.h" +#include "UefiShellDebug1CommandsLib.h" + +CHAR16 *StatusString; +BOOLEAN StatusBarNeedRefresh; +BOOLEAN StatusStringChanged; + +/** + Initialization function for Status Bar. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @sa StatusBarSetStatusString +**/ +EFI_STATUS +StatusBarInit ( + VOID + ) +{ + // + // initialize the statusbar + // + StatusString = NULL; + StatusBarNeedRefresh = TRUE; + StatusStringChanged = FALSE; + + // + // status string set to "" + // + return (StatusBarSetStatusString (L"")); +} + +/** + Cleanup function for the status bar. +**/ +VOID +StatusBarCleanup ( + VOID + ) +{ + // + // free the status string and backvar's status string + // + SHELL_FREE_NON_NULL (StatusString); +} + +typedef struct { + UINT32 Foreground : 4; + UINT32 Background : 3; +} STATUS_BAR_COLOR_ATTRIBUTES; + +typedef union { + STATUS_BAR_COLOR_ATTRIBUTES Colors; + UINTN Data; +} STATUS_BAR_COLOR_UNION; + +/** + Cause the status bar to refresh it's printing on the screen. + + @param[in] EditorFirst TRUE to indicate the first launch of the editor. + FALSE otherwise. + @param[in] LastRow LastPrintable row. + @param[in] LastCol Last printable column. + @param[in] FileRow Row in the file. + @param[in] FileCol Column in the file. + @param[in] InsertMode TRUE to indicate InsertMode. FALSE otherwise. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +StatusBarRefresh ( + IN BOOLEAN EditorFirst, + IN UINTN LastRow, + IN UINTN LastCol, + IN UINTN FileRow, + IN UINTN FileCol, + IN BOOLEAN InsertMode + ) +{ + STATUS_BAR_COLOR_UNION Orig; + STATUS_BAR_COLOR_UNION New; + + if (!StatusStringChanged && StatusBarNeedRefresh) { + StatusBarSetStatusString (L"\0"); + } + // + // when it's called first time after editor launch, so refresh is mandatory + // + if (!StatusBarNeedRefresh && !StatusStringChanged) { + return EFI_SUCCESS; + } + + // + // back up the screen attributes + // + Orig.Data = gST->ConOut->Mode->Attribute; + New.Data = 0; + New.Colors.Foreground = Orig.Colors.Background & 0xF; + New.Colors.Background = Orig.Colors.Foreground & 0x7; + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + + // + // clear status bar + // + EditorClearLine (LastRow, LastCol, LastRow); + + // + // print row, column fields + // + if (FileRow != (UINTN)(-1) && FileCol != (UINTN)(-1)) { + ShellPrintEx ( + 0, + (INT32)(LastRow) - 1, + L" %d,%d %s", + FileRow, + FileCol, + StatusString + ); + } else { + ShellPrintEx ( + 0, + (INT32)(LastRow) - 1, + L" %s", + StatusString + ); + } + + // + // print insert mode field + // + if (InsertMode) { + ShellPrintEx ((INT32)(LastCol) - 21, (INT32)(LastRow) - 1, L"|%s| Help: Ctrl-E", L"INS"); + } else { + ShellPrintEx ((INT32)(LastCol) - 21, (INT32)(LastRow) - 1, L"|%s| Help: Ctrl-E", L"OVR"); + } + // + // restore the old screen attributes + // + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + + // + // restore position in edit area + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + StatusBarNeedRefresh = FALSE; + StatusStringChanged = FALSE; + + return EFI_SUCCESS; +} + +/** + Set the status string text part. + + @param[in] Str The string to use. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +StatusBarSetStatusString ( + IN CHAR16 *Str + ) +{ + StatusStringChanged = TRUE; + + // + // free the old status string + // + SHELL_FREE_NON_NULL (StatusString); + StatusString = CatSPrint (NULL, L"%s", Str); + if (StatusString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Function to retrieve the current status string. + + @return The string that is used. +**/ +CONST CHAR16* +StatusBarGetString ( + VOID + ) +{ + return (StatusString); +} + +/** + Function to set the need refresh boolean to TRUE. +**/ +VOID +StatusBarSetRefresh( + VOID + ) +{ + StatusBarNeedRefresh = TRUE; +} + +/** + Function to get the need refresh boolean to TRUE. + + @retval TRUE The status bar needs to be refreshed. +**/ +BOOLEAN +StatusBarGetRefresh( + VOID + ) +{ + return (StatusBarNeedRefresh); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h new file mode 100644 index 0000000..02a9b66 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h @@ -0,0 +1,102 @@ +/** @file + Declares statusbar interface functions. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_STATUS_BAR_H_ +#define _LIB_STATUS_BAR_H_ + +/** + Initialization function for Status Bar. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @sa StatusBarSetStatusString +**/ +EFI_STATUS +StatusBarInit ( + VOID + ); + +/** + Cleanup function for the status bar. +**/ +VOID +StatusBarCleanup ( + VOID + ); + +/** + Cause the status bar to refresh it's printing on the screen. + + @param[in] EditorFirst TRUE to indicate the first launch of the editor. + FALSE otherwise. + @param[in] LastRow LastPrintable row. + @param[in] LastCol Last printable column. + @param[in] FileRow Row in the file. + @param[in] FileCol Column in the file. + @param[in] InsertMode TRUE to indicate InsertMode. FALSE otherwise. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +StatusBarRefresh ( + IN BOOLEAN EditorFirst, + IN UINTN LastRow, + IN UINTN LastCol, + IN UINTN FileRow, + IN UINTN FileCol, + IN BOOLEAN InsertMode + ); + +/** + Set the status string text part. + + @param[in] Str The string to use. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +StatusBarSetStatusString ( + IN CHAR16 *Str + ); + +/** + Function to retrieve the current status string. + + @return The string that is used. +**/ +CONST CHAR16* +StatusBarGetString ( + VOID + ); + +/** + Function to set the need refresh boolean to TRUE. +**/ +VOID +StatusBarSetRefresh( + VOID + ); + +/** + Function to get the need refresh boolean to TRUE. + + @retval TRUE The status bar needs to be refreshed. +**/ +BOOLEAN +StatusBarGetRefresh( + VOID + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c new file mode 100644 index 0000000..5c1852c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c @@ -0,0 +1,207 @@ +/** @file + Implements titlebar interface functions. + + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "EditTitleBar.h" +#include "UefiShellDebug1CommandsLib.h" + +CHAR16 *Title = NULL; + +/** + Initialize a title bar. + + @param[in] Prompt The prompt to print in the title bar. + + @retval EFI_SUCCESS The initialization was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainTitleBarInit ( + CONST CHAR16 *Prompt + ) +{ + SHELL_FREE_NON_NULL (Title); + if (Prompt == NULL) { + Title = CatSPrint (NULL, L""); + } else { + // + // set Title + // + Title = CatSPrint (NULL, L"%s", Prompt); + } + if (Title == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Clean up the memory used. +**/ +VOID +MainTitleBarCleanup ( + VOID + ) +{ + SHELL_FREE_NON_NULL (Title); + Title = NULL; +} + +typedef struct { + UINT32 Foreground : 4; + UINT32 Background : 4; +} TITLE_BAR_COLOR_ATTRIBUTES; + +typedef union { + TITLE_BAR_COLOR_ATTRIBUTES Colors; + UINTN Data; +} TITLE_BAR_COLOR_UNION; + +/** + Refresh function for MainTitleBar + + @param[in] FileName The open file's name (or NULL). + @param[in] FileType The type fo the file. + @param[in] ReadOnly TRUE if the file is read only. FALSE otherwise. + @param[in] Modified TRUE if the file was modified. FALSE otherwise. + @param[in] LastCol The last printable column. + @param[in] LastRow The last printable row. + @param[in] Offset The offset into the file. (only for mem/disk) + @param[in] Size The file's size. (only for mem/disk) + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainTitleBarRefresh ( + IN CONST CHAR16 *FileName OPTIONAL, + IN CONST EDIT_FILE_TYPE FileType, + IN CONST BOOLEAN ReadOnly, + IN CONST BOOLEAN Modified, + IN CONST UINTN LastCol, + IN CONST UINTN LastRow, + IN CONST UINTN Offset, + IN CONST UINTN Size + ) +{ + TITLE_BAR_COLOR_UNION Orig; + TITLE_BAR_COLOR_UNION New; + CONST CHAR16 *FileNameTmp; + INTN TempInteger; + + + // + // backup the old screen attributes + // + Orig.Data = gST->ConOut->Mode->Attribute; + New.Data = 0; + New.Colors.Foreground = Orig.Colors.Background & 0xF; + New.Colors.Background = Orig.Colors.Foreground & 0x7; + + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + + // + // clear the title line + // + EditorClearLine (1, LastCol, LastRow); + + if (Title != NULL) { + // + // print the new title bar prefix + // + ShellPrintEx ( + 0, + 0, + L"%s ", + Title + ); + } + if (FileName == NULL) { + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + return EFI_SUCCESS; + } + // + // First Extract the FileName from fullpath + // + FileNameTmp = FileName; + for (TempInteger = StrLen (FileNameTmp) - 1; TempInteger >= 0; TempInteger--) { + if (FileNameTmp[TempInteger] == L'\\') { + break; + } + } + + FileNameTmp = FileNameTmp + TempInteger + 1; + + // + // the space for file name is 20 characters + // + if (StrLen (FileNameTmp) <= 20) { + ShellPrintEx (-1,-1, L"%s ", FileNameTmp); + for (TempInteger = StrLen (FileNameTmp); TempInteger < 20; TempInteger++) { + ShellPrintEx (-1,-1, L" "); + } + + } else { + for (TempInteger = 0; TempInteger < 17; TempInteger++) { + ShellPrintEx (-1,-1, L"%c", FileNameTmp[TempInteger]); + } + // + // print "..." + // + ShellPrintEx (-1,-1, L"... "); + } + // + // print file type field + // + switch (FileType){ + case FileTypeAscii: + case FileTypeUnicode: + if (FileType == FileTypeAscii){ + ShellPrintEx (-1,-1, L" ASCII "); + } else { + ShellPrintEx (-1,-1, L" UNICODE "); + } + // + // print read-only field for text files + // + if (ReadOnly) { + ShellPrintEx (-1,-1, L"ReadOnly "); + } else { + ShellPrintEx (-1,-1, L" "); + } + break; + case FileTypeDiskBuffer: + case FileTypeMemBuffer: + // + // Print the offset. + // + ShellPrintEx (-1,-1, L"Offset %X | Size %X", Offset, Size); + case FileTypeFileBuffer: + break; + default: + break; + } + // + // print modified field + // + if (Modified) { + ShellPrintEx (-1,-1, L"Modified"); + } + // + // restore the old attribute + // + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h new file mode 100644 index 0000000..13acd21 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h @@ -0,0 +1,74 @@ +/** @file + Declares titlebar interface functions. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_TITLE_BAR_H_ +#define _LIB_TITLE_BAR_H_ + +/** + Initialize a title bar. + + @param[in] Prompt The prompt to print in the title bar. + + @retval EFI_SUCCESS The initialization was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MainTitleBarInit ( + CONST CHAR16 *Prompt + ); + +/** + Clean up the memory used. +**/ +VOID +MainTitleBarCleanup ( + VOID + ); + +typedef enum { + FileTypeNone, + FileTypeAscii, + FileTypeUnicode, + FileTypeDiskBuffer, + FileTypeMemBuffer, + FileTypeFileBuffer +} EDIT_FILE_TYPE; + +/** + Refresh function for MainTitleBar + + @param[in] FileName The open file's name (or NULL). + @param[in] FileType The type fo the file. + @param[in] ReadOnly TRUE if the file is read only. FALSE otherwise. + @param[in] Modified TRUE if the file was modified. FALSE otherwise. + @param[in] LastCol The last printable column. + @param[in] LastRow The last printable row. + @param[in] Offset The offset into the file. (only for mem/disk) + @param[in] Size The file's size. (only for mem/disk) + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +MainTitleBarRefresh ( + IN CONST CHAR16 *FileName OPTIONAL, + IN CONST EDIT_FILE_TYPE FileType, + IN CONST BOOLEAN ReadOnly, + IN CONST BOOLEAN Modified, + IN CONST UINTN LastCol, + IN CONST UINTN LastRow, + IN CONST UINTN Offset, + IN CONST UINTN Size + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c new file mode 100644 index 0000000..0327313 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c @@ -0,0 +1,164 @@ +/** @file + Main file for EfiCompress shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "Compress.h" + +/** + Function for 'compress' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEfiCompress ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + SHELL_FILE_HANDLE InShellFileHandle; + SHELL_FILE_HANDLE OutShellFileHandle; + UINT64 OutSize; + UINTN OutSize2; + VOID *OutBuffer; + UINT64 InSize; + UINTN InSize2; + VOID *InBuffer; + CHAR16 *InFileName; + CONST CHAR16 *OutFileName; + CONST CHAR16 *TempParam; + + InFileName = NULL; + OutFileName = NULL; + OutSize = 0; + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + OutBuffer = NULL; + InShellFileHandle = NULL; + OutShellFileHandle = NULL; + InBuffer = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"eficompress", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"eficompress"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"eficompress"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempParam = ShellCommandLineGetRawValue(Package, 1); + ASSERT(TempParam != NULL); + InFileName = ShellFindFilePath(TempParam); + OutFileName = ShellCommandLineGetRawValue(Package, 2); + if (InFileName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"eficompress", TempParam); + ShellStatus = SHELL_NOT_FOUND; + } else { + if (ShellIsDirectory(InFileName) == EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"eficompress", InFileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + if (ShellIsDirectory(OutFileName) == EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"eficompress", OutFileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + if (ShellStatus == SHELL_SUCCESS) { + Status = ShellOpenFileByName(InFileName, &InShellFileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"eficompress", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } + Status = ShellOpenFileByName(OutFileName, &OutShellFileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"eficompress", ShellCommandLineGetRawValue(Package, 2)); + ShellStatus = SHELL_NOT_FOUND; + } + } + if (ShellStatus == SHELL_SUCCESS) { + Status = gEfiShellProtocol->GetFileSize(InShellFileHandle, &InSize); + ASSERT_EFI_ERROR(Status); + InBuffer = AllocateZeroPool((UINTN)InSize); + if (InBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + InSize2 = (UINTN) InSize; + Status = gEfiShellProtocol->ReadFile (InShellFileHandle, &InSize2, InBuffer); + InSize = InSize2; + ASSERT_EFI_ERROR (Status); + Status = Compress (InBuffer, InSize, OutBuffer, &OutSize); + if (Status == EFI_BUFFER_TOO_SMALL) { + OutBuffer = AllocateZeroPool ((UINTN) OutSize); + if (OutBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = Compress (InBuffer, InSize, OutBuffer, &OutSize); + } + } + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_COMPRESS_FAIL), gShellDebug1HiiHandle, Status); + ShellStatus = ((Status == EFI_OUT_OF_RESOURCES) ? SHELL_OUT_OF_RESOURCES : SHELL_DEVICE_ERROR); + } else { + OutSize2 = (UINTN)OutSize; + Status = gEfiShellProtocol->WriteFile(OutShellFileHandle, &OutSize2, OutBuffer); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_WRITE_FAIL), gShellDebug1HiiHandle, L"eficompress", OutFileName); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } + } + } + + ShellCommandLineFreeVarList (Package); + } + if (InShellFileHandle != NULL) { + gEfiShellProtocol->CloseFile(InShellFileHandle); + } + if (OutShellFileHandle != NULL) { + gEfiShellProtocol->CloseFile(OutShellFileHandle); + } + SHELL_FREE_NON_NULL(InFileName); + SHELL_FREE_NON_NULL(InBuffer); + SHELL_FREE_NON_NULL(OutBuffer); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c new file mode 100644 index 0000000..cbd4e1c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c @@ -0,0 +1,186 @@ +/** @file + Main file for EfiDecompress shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include + + +/** + Function for 'decompress' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEfiDecompress ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + SHELL_FILE_HANDLE InFileHandle; + SHELL_FILE_HANDLE OutFileHandle; + UINT32 OutSize; + UINTN OutSizeTemp; + VOID *OutBuffer; + UINTN InSize; + VOID *InBuffer; + CHAR16 *InFileName; + CONST CHAR16 *OutFileName; + UINT64 Temp64Bit; + UINT32 ScratchSize; + VOID *ScratchBuffer; + EFI_DECOMPRESS_PROTOCOL *Decompress; + CONST CHAR16 *TempParam; + + InFileName = NULL; + OutFileName = NULL; + OutSize = 0; + ScratchSize = 0; + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + OutBuffer = NULL; + InBuffer = NULL; + ScratchBuffer = NULL; + InFileHandle = NULL; + OutFileHandle = NULL; + Decompress = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"efidecompress", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"efidecompress"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"efidecompress"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempParam = ShellCommandLineGetRawValue(Package, 1); + ASSERT(TempParam != NULL); + InFileName = ShellFindFilePath(TempParam); + OutFileName = ShellCommandLineGetRawValue(Package, 2); + if (InFileName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"efidecompress", TempParam); + ShellStatus = SHELL_NOT_FOUND; + } else { + if (ShellIsDirectory(InFileName) == EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"efidecompress", InFileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + if (ShellIsDirectory(OutFileName) == EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"efidecompress", OutFileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + if (ShellStatus == SHELL_SUCCESS) { + Status = ShellOpenFileByName(InFileName, &InFileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"efidecompress", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } + } + + if (ShellStatus == SHELL_SUCCESS) { + Status = FileHandleGetSize(InFileHandle, &Temp64Bit); + ASSERT(Temp64Bit <= (UINT32)(-1)); + InSize = (UINTN)Temp64Bit; + ASSERT_EFI_ERROR(Status); + InBuffer = AllocateZeroPool(InSize); + if (InBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = gEfiShellProtocol->ReadFile (InFileHandle, &InSize, InBuffer); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**) &Decompress); + ASSERT_EFI_ERROR (Status); + + Status = Decompress->GetInfo (Decompress, InBuffer, (UINT32) InSize, &OutSize, &ScratchSize); + } + + if (EFI_ERROR(Status) || OutSize == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_NOPE), gShellDebug1HiiHandle, InFileName); + ShellStatus = SHELL_NOT_FOUND; + } else { + Status = ShellOpenFileByName(OutFileName, &OutFileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_OPEN_FAIL), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, 2), Status); + ShellStatus = SHELL_NOT_FOUND; + } else { + OutBuffer = AllocateZeroPool(OutSize); + ScratchBuffer = AllocateZeroPool(ScratchSize); + if (OutBuffer == NULL || ScratchBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = Decompress->Decompress (Decompress, InBuffer, (UINT32) InSize, OutBuffer, OutSize, ScratchBuffer, ScratchSize); + } + } + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_FAIL), gShellDebug1HiiHandle, Status); + ShellStatus = ((Status == EFI_OUT_OF_RESOURCES) ? SHELL_OUT_OF_RESOURCES : SHELL_DEVICE_ERROR); + } else { + OutSizeTemp = OutSize; + Status = gEfiShellProtocol->WriteFile (OutFileHandle, &OutSizeTemp, OutBuffer); + OutSize = (UINT32) OutSizeTemp; + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_WRITE_FAIL), gShellDebug1HiiHandle, L"efidecompress", OutFileName, Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } + } + } + + ShellCommandLineFreeVarList (Package); + } + if (InFileHandle != NULL) { + gEfiShellProtocol->CloseFile(InFileHandle); + } + if (OutFileHandle != NULL) { + gEfiShellProtocol->CloseFile(OutFileHandle); + } + + SHELL_FREE_NON_NULL(InFileName); + SHELL_FREE_NON_NULL(InBuffer); + SHELL_FREE_NON_NULL(OutBuffer); + SHELL_FREE_NON_NULL(ScratchBuffer); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c new file mode 100644 index 0000000..df23511 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c @@ -0,0 +1,2475 @@ +/** @file + Defines HBufferImage - the view of the file that is visible at any point, + as well as the event handlers for editing the file + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" + +extern EFI_HANDLE HImageHandleBackup; + +extern HEFI_EDITOR_FILE_IMAGE HFileImage; +extern HEFI_EDITOR_DISK_IMAGE HDiskImage; +extern HEFI_EDITOR_MEM_IMAGE HMemImage; + +extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar; +extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar; +extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar; + +extern BOOLEAN HEditorMouseAction; + +extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; +extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar; + +HEFI_EDITOR_BUFFER_IMAGE HBufferImage; +HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar; + +// +// for basic initialization of HBufferImage +// +HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = { + NULL, + NULL, + 0, + NULL, + { + 0, + 0 + }, + { + 0, + 0 + }, + { + 0, + 0 + }, + 0, + TRUE, + FALSE, + FileTypeNone, + NULL, + NULL, + NULL +}; + +// +// the whole edit area needs to be refreshed +// +BOOLEAN HBufferImageNeedRefresh; + +// +// only the current line in edit area needs to be refresh +// +BOOLEAN HBufferImageOnlyLineNeedRefresh; + +BOOLEAN HBufferImageMouseNeedRefresh; + +/** + Initialization function for HBufferImage + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HBufferImageInit ( + VOID + ) +{ + EFI_STATUS Status; + + // + // basically initialize the HBufferImage + // + CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage)); + + // + // INIT listhead + // + HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY)); + if (HBufferImage.ListHead == NULL) { + return EFI_LOAD_ERROR; + } + + InitializeListHead (HBufferImage.ListHead); + + HBufferImage.DisplayPosition.Row = 2; + HBufferImage.DisplayPosition.Column = 10; + HBufferImage.MousePosition.Row = 2; + HBufferImage.MousePosition.Column = 10; + + HBufferImage.FileImage = &HFileImage; + HBufferImage.DiskImage = &HDiskImage; + HBufferImage.MemImage = &HMemImage; + + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageMouseNeedRefresh = FALSE; + + HBufferImageBackupVar.FileImage = &HFileImageBackupVar; + HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar; + HBufferImageBackupVar.MemImage = &HMemImageBackupVar; + + Status = HFileImageInit (); + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + + Status = HDiskImageInit (); + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + + Status = HMemImageInit (); + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Backup function for HBufferImage. Only a few fields need to be backup. + This is for making the file buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageBackup ( + VOID + ) +{ + HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition; + + HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition; + + HBufferImageBackupVar.Modified = HBufferImage.Modified; + + HBufferImageBackupVar.BufferType = HBufferImage.BufferType; + HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow; + HBufferImageBackupVar.HighBits = HBufferImage.HighBits; + + // + // three kinds of buffer supported + // file buffer + // disk buffer + // memory buffer + // + switch (HBufferImage.BufferType) { + case FileTypeFileBuffer: + HFileImageBackup (); + break; + + case FileTypeDiskBuffer: + HDiskImageBackup (); + break; + + case FileTypeMemBuffer: + HMemImageBackup (); + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +/** + Free all the lines in HBufferImage. + Fields affected: + Lines + CurrentLine + NumLines + ListHead + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageFreeLines ( + VOID + ) +{ + HFreeLines (HBufferImage.ListHead, HBufferImage.Lines); + + HBufferImage.Lines = NULL; + HBufferImage.CurrentLine = NULL; + HBufferImage.NumLines = 0; + + return EFI_SUCCESS; +} + +/** + Cleanup function for HBufferImage + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageCleanup ( + VOID + ) +{ + EFI_STATUS Status; + + // + // free all the lines + // + Status = HBufferImageFreeLines (); + + SHELL_FREE_NON_NULL (HBufferImage.ListHead); + HBufferImage.ListHead = NULL; + + HFileImageCleanup (); + HDiskImageCleanup (); + + return Status; + +} + +/** + Print Line on Row + + @param[in] Line The lline to print. + @param[in] Row The row on screen ( begin from 1 ). + @param[in] FRow The FRow. + @param[in] Orig The original color. + @param[in] New The color to print with. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImagePrintLine ( + IN HEFI_EDITOR_LINE *Line, + IN UINTN Row, + IN UINTN FRow, + IN HEFI_EDITOR_COLOR_UNION Orig, + IN HEFI_EDITOR_COLOR_UNION New + + ) +{ + + UINTN Index; + UINTN Pos; + BOOLEAN Selected; + BOOLEAN BeNewColor; + UINTN RowStart; + UINTN RowEnd; + UINTN ColStart; + UINTN ColEnd; + + // + // variable initialization + // + ColStart = 0; + ColEnd = 0; + Selected = FALSE; + + // + // print the selected area in opposite color + // + if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) { + RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1; + RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1; + + ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1; + ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1; + + if (FRow >= RowStart && FRow <= RowEnd) { + Selected = TRUE; + } + + if (FRow > RowStart) { + ColStart = 1; + } + + if (FRow < RowEnd) { + ColEnd = 0x10; + } + + } + + if (!HEditorMouseAction) { + ShellPrintEx ( + 0, + (INT32)Row - 1, + L"%8X ", + ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10 + ); + + } + + for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) { + + BeNewColor = FALSE; + + if (Selected) { + if (Index + 1 >= ColStart && Index + 1 <= ColEnd) { + BeNewColor = TRUE; + } + } + + if (BeNewColor) { + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + } else { + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); + } + + Pos = 10 + (Index * 3); + if (Line->Buffer[Index] < 0x10) { + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0"); + Pos++; + } + + if (Index < 0x07) { + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]); + } else { + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]); + } + + } + + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); + while (Index < 0x08) { + Pos = 10 + (Index * 3); + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); + Index++; + } + + while (Index < 0x10 && Index < Line->Size) { + + BeNewColor = FALSE; + + if (Selected) { + if (Index + 1 >= ColStart && Index + 1 <= ColEnd) { + BeNewColor = TRUE; + } + } + + if (BeNewColor) { + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + } else { + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); + } + + Pos = 10 + (Index * 3) + 1; + if (Line->Buffer[Index] < 0x10) { + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0"); + Pos++; + } + + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]); + Index++; + } + + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); + while (Index < 0x10) { + Pos = 10 + (Index * 3) + 1; + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); + Index++; + } + // + // restore the original color + // + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F); + + // + // PRINT the buffer content + // + if (!HEditorMouseAction) { + for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) { + Pos = ASCII_POSITION + Index; + + // + // learned from shelle.h -- IsValidChar + // + if (Line->Buffer[Index] >= L' ') { + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]); + } else { + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.'); + } + } + + while (Index < 0x10) { + Pos = ASCII_POSITION + Index; + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); + Index++; + } + } + // + // restore the abundant blank in hex edit area to original color + // + if (Selected) { + if (ColEnd <= 7) { + Pos = 10 + (ColEnd - 1) * 3 + 2; + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); + } else if (ColEnd == 8) { + Pos = 10 + (ColEnd - 1) * 3 + 2; + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); + } else { + Pos = 10 + (ColEnd - 1) * 3 + 3; + ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" "); + } + } + + return EFI_SUCCESS; +} + +/** + Function to decide if a column number is stored in the high bits. + + @param[in] Column The column to examine. + @param[out] FCol The actual column number. + + @retval TRUE The actual column was in high bits and is now in FCol. + @retval FALSE There was not a column number in the high bits. +**/ +BOOLEAN +HBufferImageIsAtHighBits ( + IN UINTN Column, + OUT UINTN *FCol + ) +{ + Column -= 10; + + // + // NOW AFTER THE SUB, Column start from 0 + // 23 AND 24 ARE BOTH BLANK + // + if (Column == 24) { + *FCol = 0; + return FALSE; + } + + if (Column > 24) { + Column--; + } + + *FCol = (Column / 3) + 1; + + if (Column % 3 == 0) { + return TRUE; + } + + if ((Column % 3 == 2)) { + *FCol = 0; + } + + return FALSE; +} + +/** + Decide if a point is in the already selected area. + + @param[in] MouseRow The row of the point to test. + @param[in] MouseCol The col of the point to test. + + @retval TRUE The point is in the selected area. + @retval FALSE The point is not in the selected area. +**/ +BOOLEAN +HBufferImageIsInSelectedArea ( + IN UINTN MouseRow, + IN UINTN MouseCol + ) +{ + UINTN FRow; + UINTN RowStart; + UINTN RowEnd; + UINTN ColStart; + UINTN ColEnd; + UINTN MouseColStart; + UINTN MouseColEnd; + + // + // judge mouse position whether is in selected area + // + // + // not select + // + if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) { + return FALSE; + } + // + // calculate the select area + // + RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1; + RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1; + + ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1; + ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1; + + FRow = HBufferImage.LowVisibleRow + MouseRow - 2; + if (FRow < RowStart || FRow > RowEnd) { + return FALSE; + } + + if (FRow > RowStart) { + ColStart = 1; + } + + if (FRow < RowEnd) { + ColEnd = 0x10; + } + + MouseColStart = 10 + (ColStart - 1) * 3; + if (ColStart > 8) { + MouseColStart++; + } + + MouseColEnd = 10 + (ColEnd - 1) * 3 + 1; + if (ColEnd > 8) { + MouseColEnd++; + } + + if (MouseCol < MouseColStart || MouseCol > MouseColEnd) { + return FALSE; + } + + return TRUE; +} + +/** + Set mouse position according to HBufferImage.MousePosition. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageRestoreMousePosition ( + VOID + ) +{ + HEFI_EDITOR_COLOR_UNION Orig; + HEFI_EDITOR_COLOR_UNION New; + UINTN FRow; + UINTN FColumn; + BOOLEAN HasCharacter; + HEFI_EDITOR_LINE *CurrentLine; + HEFI_EDITOR_LINE *Line; + UINT8 Value; + BOOLEAN HighBits; + + Line = NULL; + if (HMainEditor.MouseSupported) { + + if (HBufferImageMouseNeedRefresh) { + + HBufferImageMouseNeedRefresh = FALSE; + + // + // if mouse position not moved and only mouse action + // so do not need to refresh mouse position + // + if (( + HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row && + HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column + ) && + HEditorMouseAction + ) { + return EFI_SUCCESS; + } + // + // backup the old screen attributes + // + Orig = HMainEditor.ColorAttributes; + New.Data = 0; + New.Colors.Foreground = Orig.Colors.Background & 0xF; + New.Colors.Background = Orig.Colors.Foreground & 0x7; + + // + // if in selected area, + // so do not need to refresh mouse + // + if (!HBufferImageIsInSelectedArea ( + HBufferImageBackupVar.MousePosition.Row, + HBufferImageBackupVar.MousePosition.Column + )) { + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + } else { + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + } + // + // clear the old mouse position + // + FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2; + + HighBits = HBufferImageIsAtHighBits ( + HBufferImageBackupVar.MousePosition.Column, + &FColumn + ); + + HasCharacter = TRUE; + if (FRow > HBufferImage.NumLines || FColumn == 0) { + HasCharacter = FALSE; + } else { + CurrentLine = HBufferImage.CurrentLine; + Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row); + + if (Line == NULL || FColumn > Line->Size) { + HasCharacter = FALSE; + } + + HBufferImage.CurrentLine = CurrentLine; + } + + ShellPrintEx ( + (INT32)HBufferImageBackupVar.MousePosition.Column - 1, + (INT32)HBufferImageBackupVar.MousePosition.Row - 1, + L" " + ); + + if (HasCharacter) { + if (HighBits) { + Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0); + Value = (UINT8) (Value >> 4); + } else { + Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf); + } + + ShellPrintEx ( + (INT32)HBufferImageBackupVar.MousePosition.Column - 1, + (INT32)HBufferImageBackupVar.MousePosition.Row - 1, + L"%x", + Value + ); + } + + if (!HBufferImageIsInSelectedArea ( + HBufferImage.MousePosition.Row, + HBufferImage.MousePosition.Column + )) { + gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); + } else { + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + } + // + // clear the old mouse position + // + FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2; + + HighBits = HBufferImageIsAtHighBits ( + HBufferImage.MousePosition.Column, + &FColumn + ); + + HasCharacter = TRUE; + if (FRow > HBufferImage.NumLines || FColumn == 0) { + HasCharacter = FALSE; + } else { + CurrentLine = HBufferImage.CurrentLine; + Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row); + + if (Line == NULL || FColumn > Line->Size) { + HasCharacter = FALSE; + } + + HBufferImage.CurrentLine = CurrentLine; + } + + ShellPrintEx ( + (INT32)HBufferImage.MousePosition.Column - 1, + (INT32)HBufferImage.MousePosition.Row - 1, + L" " + ); + + if (HasCharacter) { + if (HighBits) { + Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0); + Value = (UINT8) (Value >> 4); + } else { + Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf); + } + + ShellPrintEx ( + (INT32)HBufferImage.MousePosition.Column - 1, + (INT32)HBufferImage.MousePosition.Row - 1, + L"%x", + Value + ); + } + // + // end of HasCharacter + // + gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); + } + // + // end of MouseNeedRefresh + // + } + // + // end of MouseSupported + // + return EFI_SUCCESS; +} + +/** + Set cursor position according to HBufferImage.DisplayPosition. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageRestorePosition ( + VOID + ) +{ + // + // set cursor position + // + gST->ConOut->SetCursorPosition ( + gST->ConOut, + HBufferImage.DisplayPosition.Column - 1, + HBufferImage.DisplayPosition.Row - 1 + ); + + return EFI_SUCCESS; +} + +/** + Refresh function for HBufferImage. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A Load error occured. + +**/ +EFI_STATUS +HBufferImageRefresh ( + VOID + ) +{ + LIST_ENTRY *Link; + HEFI_EDITOR_LINE *Line; + UINTN Row; + HEFI_EDITOR_COLOR_UNION Orig; + HEFI_EDITOR_COLOR_UNION New; + + UINTN StartRow; + UINTN EndRow; + UINTN FStartRow; + UINTN Tmp; + + Orig = HMainEditor.ColorAttributes; + New.Data = 0; + New.Colors.Foreground = Orig.Colors.Background; + New.Colors.Background = Orig.Colors.Foreground; + + // + // if it's the first time after editor launch, so should refresh + // + if (HEditorFirst == FALSE) { + // + // no definite required refresh + // and file position displayed on screen has not been changed + // + if (!HBufferImageNeedRefresh && + !HBufferImageOnlyLineNeedRefresh && + HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow + ) { + HBufferImageRestoreMousePosition (); + HBufferImageRestorePosition (); + return EFI_SUCCESS; + } + } + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + // + // only need to refresh current line + // + if (HBufferImageOnlyLineNeedRefresh && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) { + + HBufferImagePrintLine ( + HBufferImage.CurrentLine, + HBufferImage.DisplayPosition.Row, + HBufferImage.BufferPosition.Row, + Orig, + New + ); + } else { + // + // the whole edit area need refresh + // + if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) { + if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) { + if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) { + StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1; + } else { + StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1; + } + } else { + StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1; + } + + if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) { + EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1; + } else { + EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1; + } + // + // swap + // + if (StartRow > EndRow) { + Tmp = StartRow; + StartRow = EndRow; + EndRow = Tmp; + } + + FStartRow = StartRow; + + StartRow = 2 + StartRow - HBufferImage.LowVisibleRow; + EndRow = 2 + EndRow - HBufferImage.LowVisibleRow; + + } else { + // + // not mouse selection actions + // + FStartRow = HBufferImage.LowVisibleRow; + StartRow = 2; + EndRow = (HMainEditor.ScreenSize.Row - 1); + } + // + // no line + // + if (HBufferImage.Lines == NULL) { + HBufferImageRestoreMousePosition (); + HBufferImageRestorePosition (); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; + } + // + // get the first line that will be displayed + // + Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row); + if (Line == NULL) { + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_LOAD_ERROR; + } + + Link = &(Line->Link); + Row = StartRow; + do { + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + + // + // print line at row + // + HBufferImagePrintLine ( + Line, + Row, + HBufferImage.LowVisibleRow + Row - 2, + Orig, + New + ); + + Link = Link->ForwardLink; + Row++; + } while (Link != HBufferImage.ListHead && Row <= EndRow); + + while (Row <= EndRow) { + EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row); + Row++; + } + // + // while not file end and not screen full + // + } + + HBufferImageRestoreMousePosition (); + HBufferImageRestorePosition (); + + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = FALSE; + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + return EFI_SUCCESS; +} + +/** + Read an image into a buffer friom a source. + + @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer. + @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] BufferType The type of buffer to save. IGNORED. + @param[in] Recover TRUE for recovermode, FALSE otherwise. + + @return EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageRead ( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *DiskName, + IN UINTN DiskOffset, + IN UINTN DiskSize, + IN UINTN MemOffset, + IN UINTN MemSize, + IN EDIT_FILE_TYPE BufferType, + IN BOOLEAN Recover + ) +{ + EFI_STATUS Status; + EDIT_FILE_TYPE BufferTypeBackup; + + // + // variable initialization + // + Status = EFI_SUCCESS; + HBufferImage.BufferType = BufferType; + + // + // three types of buffer supported + // file buffer + // disk buffer + // memory buffer + // + BufferTypeBackup = HBufferImage.BufferType; + + switch (BufferType) { + case FileTypeFileBuffer: + Status = HFileImageRead (FileName, Recover); + break; + + case FileTypeDiskBuffer: + Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover); + break; + + case FileTypeMemBuffer: + Status = HMemImageRead (MemOffset, MemSize, Recover); + break; + + default: + Status = EFI_NOT_FOUND; + break; + } + + if (EFI_ERROR (Status)) { + HBufferImage.BufferType = BufferTypeBackup; + } + + return Status; +} + +/** + Save the current image. + + @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer. + @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] BufferType The type of buffer to save. IGNORED. + + @return EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageSave ( + IN CHAR16 *FileName, + IN CHAR16 *DiskName, + IN UINTN DiskOffset, + IN UINTN DiskSize, + IN UINTN MemOffset, + IN UINTN MemSize, + IN EDIT_FILE_TYPE BufferType + ) +{ + EFI_STATUS Status; + EDIT_FILE_TYPE BufferTypeBackup; + + // + // variable initialization + // + Status = EFI_SUCCESS; + BufferTypeBackup = HBufferImage.BufferType; + + switch (HBufferImage.BufferType) { + // + // file buffer + // + case FileTypeFileBuffer: + Status = HFileImageSave (FileName); + break; + + // + // disk buffer + // + case FileTypeDiskBuffer: + Status = HDiskImageSave (DiskName, DiskOffset, DiskSize); + break; + + // + // memory buffer + // + case FileTypeMemBuffer: + Status = HMemImageSave (MemOffset, MemSize); + break; + + default: + Status = EFI_NOT_FOUND; + break; + } + + if (EFI_ERROR (Status)) { + HBufferImage.BufferType = BufferTypeBackup; + } + + return Status; +} + +/** + Create a new line and append it to the line list. + Fields affected: + NumLines + Lines + + @retval NULL create line failed. + @return the line created. + +**/ +HEFI_EDITOR_LINE * +HBufferImageCreateLine ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + + // + // allocate for line structure + // + Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE)); + if (Line == NULL) { + return NULL; + } + + Line->Signature = EFI_EDITOR_LINE_LIST; + Line->Size = 0; + + HBufferImage.NumLines++; + + // + // insert to line list + // + InsertTailList (HBufferImage.ListHead, &Line->Link); + + if (HBufferImage.Lines == NULL) { + HBufferImage.Lines = CR ( + HBufferImage.ListHead->ForwardLink, + HEFI_EDITOR_LINE, + Link, + EFI_EDITOR_LINE_LIST + ); + } + + return Line; +} + +/** + Free the current image. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageFree ( + VOID + ) +{ + // + // free all lines + // + HBufferImageFreeLines (); + + return EFI_SUCCESS; +} + +/** + change char to int value based on Hex. + + @param[in] Char The input char. + + @return The character's index value. + @retval -1 The operation failed. +**/ +INTN +HBufferImageCharToHex ( + IN CHAR16 Char + ) +{ + // + // change the character to hex + // + if (Char >= L'0' && Char <= L'9') { + return (Char - L'0'); + } + + if (Char >= L'a' && Char <= L'f') { + return (Char - L'a' + 10); + } + + if (Char >= L'A' && Char <= L'F') { + return (Char - L'A' + 10); + } + + return -1; +} + +/** + Add character. + + @param[in] Char -- input char. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HBufferImageAddChar ( + IN CHAR16 Char + ) +{ + HEFI_EDITOR_LINE *Line; + HEFI_EDITOR_LINE *NewLine; + INTN Value; + UINT8 Old; + UINTN FRow; + UINTN FCol; + BOOLEAN High; + + Value = HBufferImageCharToHex (Char); + + // + // invalid input + // + if (Value == -1) { + return EFI_SUCCESS; + } + + Line = HBufferImage.CurrentLine; + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + High = HBufferImage.HighBits; + + // + // only needs to refresh current line + // + HBufferImageOnlyLineNeedRefresh = TRUE; + + // + // not a full line and beyond the last character + // + if (FCol > Line->Size) { + // + // cursor always at high 4 bits + // and always put input to the low 4 bits + // + Line->Buffer[Line->Size] = (UINT8) Value; + Line->Size++; + High = FALSE; + } else { + + Old = Line->Buffer[FCol - 1]; + + // + // always put the input to the low 4 bits + // + Old = (UINT8) (Old & 0x0f); + Old = (UINT8) (Old << 4); + Old = (UINT8) (Value + Old); + Line->Buffer[FCol - 1] = Old; + + // + // at the low 4 bits of the last character of a full line + // so if no next line, need to create a new line + // + if (!High && FCol == 0x10) { + + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageNeedRefresh = TRUE; + + if (Line->Link.ForwardLink == HBufferImage.ListHead) { + // + // last line + // + // create a new line + // + NewLine = HBufferImageCreateLine (); + if (NewLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // end of NULL + // + } + // + // end of == ListHead + // + } + // + // end of == 0x10 + // + // if already at end of this line, scroll it to the start of next line + // + if (FCol == 0x10 && !High) { + // + // definitely has next line + // + FRow++; + FCol = 1; + High = TRUE; + } else { + // + // if not at end of this line, just move to next column + // + if (!High) { + FCol++; + } + + if (High) { + High = FALSE; + } else { + High = TRUE; + } + + } + // + // end of ==FALSE + // + } + // + // move cursor to right + // + HBufferImageMovePosition (FRow, FCol, High); + + if (!HBufferImage.Modified) { + HBufferImage.Modified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Delete the previous character. + + @retval EFI_SUCCESS The operationw as successful. +**/ +EFI_STATUS +HBufferImageDoBackspace ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + + UINTN FileColumn; + UINTN FPos; + BOOLEAN LastLine; + + // + // variable initialization + // + LastLine = FALSE; + + // + // already the first character + // + if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) { + return EFI_SUCCESS; + } + + FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1; + + FileColumn = HBufferImage.BufferPosition.Column; + + Line = HBufferImage.CurrentLine; + LastLine = FALSE; + if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) { + LastLine = TRUE; + } + + HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL); + + // + // if is the last line + // then only this line need to be refreshed + // + if (LastLine) { + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = TRUE; + } else { + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + } + + if (!HBufferImage.Modified) { + HBufferImage.Modified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + ASCII key + Backspace + return. + + @param[in] Char The input char. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HBufferImageDoCharInput ( + IN CHAR16 Char + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + switch (Char) { + case 0: + break; + + case 0x08: + Status = HBufferImageDoBackspace (); + break; + + case 0x09: + case 0x0a: + case 0x0d: + // + // Tabs, Returns are thought as nothing + // + break; + + default: + // + // DEAL WITH ASCII CHAR, filter out thing like ctrl+f + // + if (Char > 127 || Char < 32) { + Status = StatusBarSetStatusString (L"Unknown Command"); + } else { + Status = HBufferImageAddChar (Char); + } + + break; + } + + return Status; +} + +/** + Check user specified FileRow is above current screen. + + @param[in] FileRow Row of file position ( start from 1 ). + + @retval TRUE It is above the current screen. + @retval FALSE It is not above the current screen. + +**/ +BOOLEAN +HAboveCurrentScreen ( + IN UINTN FileRow + ) +{ + if (FileRow < HBufferImage.LowVisibleRow) { + return TRUE; + } + + return FALSE; +} + +/** + Check user specified FileRow is under current screen. + + @param[in] FileRow Row of file position ( start from 1 ). + + @retval TRUE It is under the current screen. + @retval FALSE It is not under the current screen. + +**/ +BOOLEAN +HUnderCurrentScreen ( + IN UINTN FileRow + ) +{ + if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) { + return TRUE; + } + + return FALSE; +} + +/** + According to cursor's file position, adjust screen display. + + @param[in] NewFilePosRow Row of file position ( start from 1 ). + @param[in] NewFilePosCol Column of file position ( start from 1 ). + @param[in] HighBits Cursor will on high4 bits or low4 bits. +**/ +VOID +HBufferImageMovePosition ( + IN UINTN NewFilePosRow, + IN UINTN NewFilePosCol, + IN BOOLEAN HighBits + ) +{ + INTN RowGap; + UINTN Abs; + BOOLEAN Above; + BOOLEAN Under; + UINTN NewDisplayCol; + + // + // CALCULATE gap between current file position and new file position + // + RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row; + + Under = HUnderCurrentScreen (NewFilePosRow); + Above = HAboveCurrentScreen (NewFilePosRow); + + HBufferImage.HighBits = HighBits; + + // + // if is below current screen + // + if (Under) { + // + // display row will be unchanged + // + HBufferImage.BufferPosition.Row = NewFilePosRow; + } else { + if (Above) { + // + // has enough above line, so display row unchanged + // not has enough above lines, so the first line is + // at the first display line + // + if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) { + HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1; + } + + HBufferImage.BufferPosition.Row = NewFilePosRow; + } else { + // + // in current screen + // + HBufferImage.BufferPosition.Row = NewFilePosRow; + if (RowGap <= 0) { + Abs = (UINTN)ABS(RowGap); + HBufferImage.DisplayPosition.Row -= Abs; + } else { + HBufferImage.DisplayPosition.Row += RowGap; + } + + } + } + + HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2); + + // + // always in current screen + // + HBufferImage.BufferPosition.Column = NewFilePosCol; + + NewDisplayCol = 10 + (NewFilePosCol - 1) * 3; + if (NewFilePosCol > 0x8) { + NewDisplayCol++; + } + + if (!HighBits) { + NewDisplayCol++; + } + + HBufferImage.DisplayPosition.Column = NewDisplayCol; + + // + // let CurrentLine point to correct line; + // + HBufferImage.CurrentLine = HMoveCurrentLine (RowGap); + +} + +/** + Scroll cursor to right. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageScrollRight ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + // + // scroll right will always move to the high4 bits of the next character + // + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = FALSE; + + Line = HBufferImage.CurrentLine; + + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + + // + // this line is not full and no next line + // + if (FCol > Line->Size) { + return EFI_SUCCESS; + } + // + // if already at end of this line, scroll it to the start of next line + // + if (FCol == 0x10) { + // + // has next line + // + if (Line->Link.ForwardLink != HBufferImage.ListHead) { + FRow++; + FCol = 1; + + } else { + return EFI_SUCCESS; + } + } else { + // + // if not at end of this line, just move to next column + // + FCol++; + + } + + HBufferImageMovePosition (FRow, FCol, TRUE); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to left. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageScrollLeft ( + VOID + ) +{ + + HEFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = FALSE; + + Line = HBufferImage.CurrentLine; + + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + + // + // if already at start of this line, so move to the end of previous line + // + if (FCol <= 1) { + // + // has previous line + // + if (Line->Link.BackLink != HBufferImage.ListHead) { + FRow--; + Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + FCol = Line->Size; + } else { + return EFI_SUCCESS; + } + } else { + // + // if not at start of this line, just move to previous column + // + FCol--; + } + + HBufferImageMovePosition (FRow, FCol, TRUE); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to the next line + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageScrollDown ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + BOOLEAN HighBits; + + Line = HBufferImage.CurrentLine; + + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + HighBits = HBufferImage.HighBits; + + // + // has next line + // + if (Line->Link.ForwardLink != HBufferImage.ListHead) { + FRow++; + Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + + // + // if the next line is not that long, so move to end of next line + // + if (FCol > Line->Size) { + FCol = Line->Size + 1; + HighBits = TRUE; + } + + } else { + return EFI_SUCCESS; + } + + HBufferImageMovePosition (FRow, FCol, HighBits); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to previous line + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageScrollUp ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + + Line = HBufferImage.CurrentLine; + + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + + // + // has previous line + // + if (Line->Link.BackLink != HBufferImage.ListHead) { + FRow--; + + } else { + return EFI_SUCCESS; + } + + HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to next page + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImagePageDown ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + UINTN Gap; + BOOLEAN HighBits; + + Line = HBufferImage.CurrentLine; + + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + HighBits = HBufferImage.HighBits; + + // + // has next page + // + if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) { + Gap = (HMainEditor.ScreenSize.Row - 2); + } else { + // + // MOVE CURSOR TO LAST LINE + // + Gap = HBufferImage.NumLines - FRow; + } + // + // get correct line + // + Line = HMoveLine (Gap); + + // + // if that line, is not that long, so move to the end of that line + // + if (Line != NULL && FCol > Line->Size) { + FCol = Line->Size + 1; + HighBits = TRUE; + } + + FRow += Gap; + + HBufferImageMovePosition (FRow, FCol, HighBits); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to previous page + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImagePageUp ( + VOID + ) +{ + UINTN FRow; + UINTN FCol; + UINTN Gap; + INTN Retreat; + + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + + // + // has previous page + // + if (FRow > (HMainEditor.ScreenSize.Row - 2)) { + Gap = (HMainEditor.ScreenSize.Row - 2); + } else { + // + // the first line of file will displayed on the first line of screen + // + Gap = FRow - 1; + } + + Retreat = Gap; + Retreat = -Retreat; + + FRow -= Gap; + + HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to start of line + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageHome ( + VOID + ) +{ + UINTN FRow; + UINTN FCol; + BOOLEAN HighBits; + + // + // curosr will at the high bit + // + FRow = HBufferImage.BufferPosition.Row; + FCol = 1; + HighBits = TRUE; + + // + // move cursor position + // + HBufferImageMovePosition (FRow, FCol, HighBits); + + return EFI_SUCCESS; +} + +/** + Scroll cursor to end of line. + + @retval EFI_SUCCESS Teh operation was successful. +**/ +EFI_STATUS +HBufferImageEnd ( + VOID + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN FRow; + UINTN FCol; + BOOLEAN HighBits; + + // + // need refresh mouse + // + HBufferImageMouseNeedRefresh = TRUE; + + Line = HBufferImage.CurrentLine; + + FRow = HBufferImage.BufferPosition.Row; + + if (Line->Size == 0x10) { + FCol = Line->Size; + HighBits = FALSE; + } else { + FCol = Line->Size + 1; + HighBits = TRUE; + } + // + // move cursor position + // + HBufferImageMovePosition (FRow, FCol, HighBits); + + return EFI_SUCCESS; +} + +/** + Get the size of the open buffer. + + @retval The size in bytes. +**/ +UINTN +HBufferImageGetTotalSize ( + VOID + ) +{ + UINTN Size; + + HEFI_EDITOR_LINE *Line; + + // + // calculate the total size of whole line list's buffer + // + if (HBufferImage.Lines == NULL) { + return 0; + } + + Line = CR ( + HBufferImage.ListHead->BackLink, + HEFI_EDITOR_LINE, + Link, + EFI_EDITOR_LINE_LIST + ); + // + // one line at most 0x10 + // + Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size; + + return Size; +} + +/** + Delete character from buffer. + + @param[in] Pos Position, Pos starting from 0. + @param[in] Count The Count of characters to delete. + @param[out] DeleteBuffer The DeleteBuffer. + + @retval EFI_SUCCESS Success +**/ +EFI_STATUS +HBufferImageDeleteCharacterFromBuffer ( + IN UINTN Pos, + IN UINTN Count, + OUT UINT8 *DeleteBuffer + ) +{ + UINTN Index; + + VOID *Buffer; + UINT8 *BufferPtr; + UINTN Size; + + HEFI_EDITOR_LINE *Line; + LIST_ENTRY *Link; + + UINTN OldFCol; + UINTN OldFRow; + UINTN OldPos; + + UINTN NewPos; + + EFI_STATUS Status; + + Size = HBufferImageGetTotalSize (); + + if (Size < Count) { + return EFI_LOAD_ERROR; + } + + if (Size == 0) { + return EFI_SUCCESS; + } + + // + // relocate all the HBufferImage fields + // + OldFRow = HBufferImage.BufferPosition.Row; + OldFCol = HBufferImage.BufferPosition.Column; + OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1; + + if (Pos > 0) { + // + // has character before it, + // so locate according to block's previous character + // + NewPos = Pos - 1; + + } else { + // + // has no character before it, + // so locate according to block's next character + // + NewPos = 0; + } + + HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); + + Buffer = AllocateZeroPool (Size); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + HBufferImageListToBuffer (Buffer, Size); + + BufferPtr = (UINT8 *) Buffer; + + // + // pass deleted buffer out + // + if (DeleteBuffer != NULL) { + for (Index = 0; Index < Count; Index++) { + DeleteBuffer[Index] = BufferPtr[Pos + Index]; + } + } + // + // delete the part from Pos + // + for (Index = Pos; Index < Size - Count; Index++) { + BufferPtr[Index] = BufferPtr[Index + Count]; + } + + Size -= Count; + + HBufferImageFreeLines (); + + Status = HBufferImageBufferToList (Buffer, Size); + FreePool (Buffer); + + if (EFI_ERROR (Status)) { + return Status; + } + + Link = HMainEditor.BufferImage->ListHead->ForwardLink; + for (Index = 0; Index < NewPos / 0x10; Index++) { + Link = Link->ForwardLink; + } + + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + HBufferImage.CurrentLine = Line; + + // + // if current cursor position if inside select area + // then move it to the block's NEXT character + // + if (OldPos >= Pos && OldPos < (Pos + Count)) { + NewPos = Pos; + } else { + if (OldPos < Pos) { + NewPos = OldPos; + } else { + NewPos = OldPos - Count; + } + } + + HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); + + return EFI_SUCCESS; +} + +/** + Add character to buffer, add before pos. + + @param[in] Pos Position, Pos starting from 0. + @param[in] Count Count of characters to add. + @param[in] AddBuffer Add buffer. + + @retval EFI_SUCCESS Success. +**/ +EFI_STATUS +HBufferImageAddCharacterToBuffer ( + IN UINTN Pos, + IN UINTN Count, + IN UINT8 *AddBuffer + ) +{ + INTN Index; + + VOID *Buffer; + UINT8 *BufferPtr; + UINTN Size; + + HEFI_EDITOR_LINE *Line; + + LIST_ENTRY *Link; + + UINTN OldFCol; + UINTN OldFRow; + UINTN OldPos; + + UINTN NewPos; + + Size = HBufferImageGetTotalSize (); + + // + // relocate all the HBufferImage fields + // + OldFRow = HBufferImage.BufferPosition.Row; + OldFCol = HBufferImage.BufferPosition.Column; + OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1; + + // + // move cursor before Pos + // + if (Pos > 0) { + NewPos = Pos - 1; + } else { + NewPos = 0; + } + + HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); + + Buffer = AllocateZeroPool (Size + Count); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + HBufferImageListToBuffer (Buffer, Size); + + BufferPtr = (UINT8 *) Buffer; + + // + // get a place to add + // + for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) { + BufferPtr[Index] = BufferPtr[Index - Count]; + } + // + // add the buffer + // + for (Index = (INTN) 0; Index < (INTN) Count; Index++) { + BufferPtr[Index + Pos] = AddBuffer[Index]; + } + + Size += Count; + + HBufferImageFreeLines (); + + HBufferImageBufferToList (Buffer, Size); + + FreePool (Buffer); + + Link = HMainEditor.BufferImage->ListHead->ForwardLink; + for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) { + Link = Link->ForwardLink; + } + + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + HBufferImage.CurrentLine = Line; + + if (OldPos >= Pos) { + NewPos = OldPos + Count; + } else { + NewPos = OldPos; + } + + HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE); + + return EFI_SUCCESS; +} + +/** + Delete current character from line. + + @retval EFI_SUCCESS The operationw as successful. +**/ +EFI_STATUS +HBufferImageDoDelete ( + VOID + ) +{ + + HEFI_EDITOR_LINE *Line; + + BOOLEAN LastLine; + UINTN FileColumn; + UINTN FPos; + + FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1; + + FileColumn = HBufferImage.BufferPosition.Column; + + Line = HBufferImage.CurrentLine; + + // + // if beyond the last character + // + if (FileColumn > Line->Size) { + return EFI_SUCCESS; + } + + LastLine = FALSE; + if (Line->Link.ForwardLink == HBufferImage.ListHead) { + LastLine = TRUE; + } + + HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL); + + // + // if is the last line + // then only this line need to be refreshed + // + if (LastLine) { + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = TRUE; + } else { + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + } + + if (!HBufferImage.Modified) { + HBufferImage.Modified = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Change the raw buffer to a list of lines for the UI. + + @param[in] Buffer The pointer to the buffer to fill. + @param[in] Bytes The size of the buffer in bytes. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HBufferImageBufferToList ( + IN VOID *Buffer, + IN UINTN Bytes + ) +{ + UINTN TempI; + UINTN TempJ; + UINTN Left; + HEFI_EDITOR_LINE *Line; + UINT8 *BufferPtr; + + TempI = 0; + Left = 0; + BufferPtr = (UINT8 *) Buffer; + + // + // parse file content line by line + // + while (TempI < Bytes) { + if (Bytes - TempI >= 0x10) { + Left = 0x10; + } else { + Left = Bytes - TempI; + } + + // + // allocate a new line + // + Line = HBufferImageCreateLine (); + if (Line == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Line->Size = Left; + + for (TempJ = 0; TempJ < Left; TempJ++) { + Line->Buffer[TempJ] = BufferPtr[TempI]; + TempI++; + } + + } + + // + // last line is a full line, SO create a new line + // + if (Left == 0x10 || Bytes == 0) { + Line = HBufferImageCreateLine (); + if (Line == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + return EFI_SUCCESS; +} + +/** + Change the list of lines from the UI to a raw buffer. + + @param[in] Buffer The pointer to the buffer to fill. + @param[in] Bytes The size of the buffer in bytes. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageListToBuffer ( + IN VOID *Buffer, + IN UINTN Bytes + ) +{ + UINTN Count; + UINTN Index; + HEFI_EDITOR_LINE *Line; + LIST_ENTRY *Link; + UINT8 *BufferPtr; + + // + // change the line list to a large buffer + // + if (HBufferImage.Lines == NULL) { + return EFI_SUCCESS; + } + + Link = &HBufferImage.Lines->Link; + Count = 0; + BufferPtr = (UINT8 *) Buffer; + + // + // deal line by line + // + while (Link != HBufferImage.ListHead) { + + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + + //@todo shouldn't this be an error??? + if (Count + Line->Size > Bytes) { + return EFI_SUCCESS; + } + + for (Index = 0; Index < Line->Size; Index++) { + BufferPtr[Index] = Line->Buffer[Index]; + } + + Count += Line->Size; + BufferPtr += Line->Size; + + Link = Link->ForwardLink; + } + + return EFI_SUCCESS; +} + +/** + Move the mouse in the image buffer. + + @param[in] TextX The x-coordinate. + @param[in] TextY The y-coordinate. +**/ +VOID +HBufferImageAdjustMousePosition ( + IN INT32 TextX, + IN INT32 TextY + ) +{ + UINTN TempX; + UINTN TempY; + UINTN AbsX; + UINTN AbsY; + + // + // TextX and TextY is mouse movement data returned by mouse driver + // This function will change it to MousePosition + // + // + // get absolute TempX value + // + if (TextX >= 0) { + AbsX = TextX; + } else { + AbsX = -TextX; + } + // + // get absolute TempY value + // + if (TextY >= 0) { + AbsY = TextY; + } else { + AbsY = -TextY; + } + + TempX = HBufferImage.MousePosition.Column; + TempY = HBufferImage.MousePosition.Row; + + if (TextX >= 0) { + TempX += TextX; + } else { + if (TempX >= AbsX) { + TempX -= AbsX; + } else { + TempX = 0; + } + } + + if (TextY >= 0) { + TempY += TextY; + } else { + if (TempY >= AbsY) { + TempY -= AbsY; + } else { + TempY = 0; + } + } + // + // check whether new mouse column position is beyond screen + // if not, adjust it + // + if (TempX >= 10 && TempX <= (10 + 0x10 * 3 - 1)) { + HBufferImage.MousePosition.Column = TempX; + } else if (TempX < 10) { + HBufferImage.MousePosition.Column = 10; + } else if (TempX > (10 + 0x10 * 3 - 1)) { + HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1; + } + // + // check whether new mouse row position is beyond screen + // if not, adjust it + // + if (TempY >= 2 && TempY <= (HMainEditor.ScreenSize.Row - 1)) { + HBufferImage.MousePosition.Row = TempY; + } else if (TempY < 2) { + HBufferImage.MousePosition.Row = 2; + } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) { + HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1); + } + +} + +/** + Dispatch input to different handler + + @param[in] Key The input key: + the keys can be: + ASCII KEY + Backspace/Delete + Direction key: up/down/left/right/pgup/pgdn + Home/End + INS + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A Memory allocation failed. +**/ +EFI_STATUS +HBufferImageHandleInput ( + IN EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + switch (Key->ScanCode) { + // + // ordinary key + // + case SCAN_NULL: + Status = HBufferImageDoCharInput (Key->UnicodeChar); + break; + + // + // up arrow + // + case SCAN_UP: + Status = HBufferImageScrollUp (); + break; + + // + // down arrow + // + case SCAN_DOWN: + Status = HBufferImageScrollDown (); + break; + + // + // right arrow + // + case SCAN_RIGHT: + Status = HBufferImageScrollRight (); + break; + + // + // left arrow + // + case SCAN_LEFT: + Status = HBufferImageScrollLeft (); + break; + + // + // page up + // + case SCAN_PAGE_UP: + Status = HBufferImagePageUp (); + break; + + // + // page down + // + case SCAN_PAGE_DOWN: + Status = HBufferImagePageDown (); + break; + + // + // delete + // + case SCAN_DELETE: + Status = HBufferImageDoDelete (); + break; + + // + // home + // + case SCAN_HOME: + Status = HBufferImageHome (); + break; + + // + // end + // + case SCAN_END: + Status = HBufferImageEnd (); + break; + + default: + Status = StatusBarSetStatusString (L"Unknown Command"); + break; + } + + return Status; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h new file mode 100644 index 0000000..c113434 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h @@ -0,0 +1,273 @@ +/** @file + Defines BufferImage - the view of the file that is visible at any point, + as well as the event handlers for editing the file + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_BUFFER_IMAGE_H_ +#define _LIB_BUFFER_IMAGE_H_ + +#include "HexEditor.h" + +/** + Initialization function for HBufferImage + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HBufferImageInit ( + VOID + ); + +/** + Cleanup function for HBufferImage + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageCleanup ( + VOID + ); + +/** + Refresh function for HBufferImage. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A Load error occured. + +**/ +EFI_STATUS +HBufferImageRefresh ( + VOID + ); + +/** + Dispatch input to different handler + + @param[in] Key The input key: + the keys can be: + ASCII KEY + Backspace/Delete + Direction key: up/down/left/right/pgup/pgdn + Home/End + INS + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_OUT_OF_RESOURCES A Memory allocation failed. +**/ +EFI_STATUS +HBufferImageHandleInput ( + IN EFI_INPUT_KEY *Key + ); + +/** + Backup function for HBufferImage. Only a few fields need to be backup. + This is for making the file buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageBackup ( + VOID + ); + +/** + Read an image into a buffer friom a source. + + @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer. + @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] BufferType The type of buffer to save. IGNORED. + @param[in] Recover TRUE for recovermode, FALSE otherwise. + + @return EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageRead ( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *DiskName, + IN UINTN DiskOffset, + IN UINTN DiskSize, + IN UINTN MemOffset, + IN UINTN MemSize, + IN EDIT_FILE_TYPE BufferType, + IN BOOLEAN Recover + ); + +/** + Save the current image. + + @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer. + @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer. + @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer. + @param[in] BufferType The type of buffer to save. IGNORED. + + @return EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageSave ( + IN CHAR16 *FileName, + IN CHAR16 *DiskName, + IN UINTN DiskOffset, + IN UINTN DiskSize, + IN UINTN MemOffset, + IN UINTN MemSize, + IN EDIT_FILE_TYPE BufferType + ); + +/** + According to cursor's file position, adjust screen display. + + @param[in] NewFilePosRow Row of file position ( start from 1 ). + @param[in] NewFilePosCol Column of file position ( start from 1 ). + @param[in] HighBits Cursor will on high4 bits or low4 bits. +**/ +VOID +HBufferImageMovePosition ( + IN UINTN NewFilePosRow, + IN UINTN NewFilePosCol, + IN BOOLEAN HighBits + ); + + +/** + Create a new line and append it to the line list. + Fields affected: + NumLines + Lines + + @retval NULL create line failed. + @return the line created. + +**/ +HEFI_EDITOR_LINE * +HBufferImageCreateLine ( + VOID + ); + +/** + Free the current image. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageFree ( + VOID + ); + +/** + Delete character from buffer. + + @param[in] Pos Position, Pos starting from 0. + @param[in] Count The Count of characters to delete. + @param[out] DeleteBuffer The DeleteBuffer. + + @retval EFI_SUCCESS Success +**/ +EFI_STATUS +HBufferImageDeleteCharacterFromBuffer ( + IN UINTN Pos, + IN UINTN Count, + OUT UINT8 *DeleteBuffer + ); + +/** + Add character to buffer, add before pos. + + @param[in] Pos Position, Pos starting from 0. + @param[in] Count Count of characters to add. + @param[in] AddBuffer Add buffer. + + @retval EFI_SUCCESS Success. +**/ +EFI_STATUS +HBufferImageAddCharacterToBuffer ( + IN UINTN Pos, + IN UINTN Count, + IN UINT8 *AddBuffer + ); + +/** + Change the raw buffer to a list of lines for the UI. + + @param[in] Buffer The pointer to the buffer to fill. + @param[in] Bytes The size of the buffer in bytes. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HBufferImageBufferToList ( + IN VOID *Buffer, + IN UINTN Bytes + ); + +/** + Change the list of lines from the UI to a raw buffer. + + @param[in] Buffer The pointer to the buffer to fill. + @param[in] Bytes The size of the buffer in bytes. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HBufferImageListToBuffer ( + IN VOID *Buffer, + IN UINTN Bytes + ); + +/** + Move the mouse in the image buffer. + + @param[in] TextX The x-coordinate. + @param[in] TextY The y-coordinate. +**/ +VOID +HBufferImageAdjustMousePosition ( + IN INT32 TextX, + IN INT32 TextY + ); + +/** + Function to decide if a column number is stored in the high bits. + + @param[in] Column The column to examine. + @param[out] FCol The actual column number. + + @retval TRUE The actual column was in high bits and is now in FCol. + @retval FALSE There was not a column number in the high bits. +**/ +BOOLEAN +HBufferImageIsAtHighBits ( + IN UINTN Column, + OUT UINTN *FCol + ); + +/** + Get the size of the open buffer. + + @retval The size in bytes. +**/ +UINTN +HBufferImageGetTotalSize ( + VOID + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c new file mode 100644 index 0000000..e229799 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c @@ -0,0 +1,112 @@ +/** @file + Functions to deal with Clip Board + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" + +typedef struct { + UINT8 *Buffer; + UINTN Size; +} HEFI_EDITOR_CLIPBOARD; + +HEFI_EDITOR_CLIPBOARD HClipBoard; + +// +// for basic initialization of HClipBoard +// +HEFI_EDITOR_CLIPBOARD HClipBoardConst = { + NULL, + 0 +}; + +/** + Initialization function for HDiskImage. + + @param[in] EFI_SUCCESS The operation was successful. + @param[in] EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HClipBoardInit ( + VOID + ) +{ + // + // basiclly initialize the HDiskImage + // + CopyMem (&HClipBoard, &HClipBoardConst, sizeof (HClipBoard)); + + return EFI_SUCCESS; +} + +/** + Initialization function for HDiskImage. + + @param[in] EFI_SUCCESS The operation was successful. + @param[in] EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HClipBoardCleanup ( + VOID + ) +{ + + SHELL_FREE_NON_NULL (HClipBoard.Buffer); + + return EFI_SUCCESS; +} + +/** + Set a buffer into the clipboard. + + @param[in] Buffer The buffer to add to the clipboard. + @param[in] Size The size of Buffer in bytes. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HClipBoardSet ( + IN UINT8 *Buffer, + IN UINTN Size + ) +{ + // + // free the old clipboard buffer + // and set new clipboard buffer + // + SHELL_FREE_NON_NULL (HClipBoard.Buffer); + HClipBoard.Buffer = Buffer; + + HClipBoard.Size = Size; + + return EFI_SUCCESS; +} + +/** + Get a buffer from the clipboard. + + @param[out] Buffer The pointer to the buffer to add to the clipboard. + + @return the size of the buffer. +**/ +UINTN +HClipBoardGet ( + OUT UINT8 **Buffer + ) +{ + // + // return the clipboard buffer + // + *Buffer = HClipBoard.Buffer; + + return HClipBoard.Size; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h new file mode 100644 index 0000000..6a97b0d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h @@ -0,0 +1,69 @@ +/** @file + Defines DiskImage - the view of the file that is visible at any point, + as well as the event handlers for editing the file + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_CLIP_BOARD_H_ +#define _LIB_CLIP_BOARD_H_ + +#include "HexEditor.h" + +/** + Initialization function for HDiskImage + + @param[in] EFI_SUCCESS The operation was successful. + @param[in] EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HClipBoardInit ( + VOID + ); + +/** + Initialization function for HDiskImage. + + @param[in] EFI_SUCCESS The operation was successful. + @param[in] EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HClipBoardCleanup ( + VOID + ); + +/** + Set a buffer into the clipboard. + + @param[in] Buffer The buffer to add to the clipboard. + @param[in] Size The size of Buffer in bytes. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HClipBoardSet ( + IN UINT8 *Buffer, + IN UINTN Size + ); + +/** + Get a buffer from the clipboard. + + @param[out] Buffer The pointer to the buffer to add to the clipboard. + + @return the size of the buffer. +**/ +UINTN +HClipBoardGet ( + OUT UINT8 **Buffer + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c new file mode 100644 index 0000000..e782491 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c @@ -0,0 +1,417 @@ +/** @file + Functions to deal with Disk buffer. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" +#include + +extern EFI_HANDLE HImageHandleBackup; +extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage; + +extern BOOLEAN HBufferImageNeedRefresh; +extern BOOLEAN HBufferImageOnlyLineNeedRefresh; +extern BOOLEAN HBufferImageMouseNeedRefresh; + +extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; + +HEFI_EDITOR_DISK_IMAGE HDiskImage; +HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar; + +// +// for basic initialization of HDiskImage +// +HEFI_EDITOR_DISK_IMAGE HDiskImageConst = { + NULL, + 0, + 0, + 0 +}; + +/** + Initialization function for HDiskImage. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HDiskImageInit ( + VOID + ) +{ + // + // basically initialize the HDiskImage + // + CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage)); + + CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar)); + + return EFI_SUCCESS; +} + +/** + Backup function for HDiskImage. Only a few fields need to be backup. + This is for making the Disk buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES gST->ConOut of resources. +**/ +EFI_STATUS +HDiskImageBackup ( + VOID + ) +{ + // + // backup the disk name, offset and size + // + // + SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name); + + HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name); + if (HDiskImageBackupVar.Name == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + HDiskImageBackupVar.Offset = HDiskImage.Offset; + HDiskImageBackupVar.Size = HDiskImage.Size; + + return EFI_SUCCESS; +} + +/** + Cleanup function for HDiskImage. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HDiskImageCleanup ( + VOID + ) +{ + SHELL_FREE_NON_NULL (HDiskImage.Name); + SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name); + + return EFI_SUCCESS; +} + +/** + Set FileName field in HFileImage. + + @param[in] Str File name to set. + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HDiskImageSetDiskNameOffsetSize ( + IN CONST CHAR16 *Str, + IN UINTN Offset, + IN UINTN Size + ) +{ + if (Str == HDiskImage.Name) { + // + // This function might be called using HDiskImage.FileName as Str. + // Directly return without updating HDiskImage.FileName. + // + return EFI_SUCCESS; + } + + // + // free the old file name + // + SHELL_FREE_NON_NULL (HDiskImage.Name); + HDiskImage.Name = AllocateCopyPool (StrSize (Str), Str); + if (HDiskImage.Name == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + HDiskImage.Offset = Offset; + HDiskImage.Size = Size; + + return EFI_SUCCESS; +} + +/** + Read a disk from disk into HBufferImage. + + @param[in] DeviceName filename to read. + @param[in] Offset The offset. + @param[in] Size The size. + @param[in] Recover if is for recover, no information print. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +HDiskImageRead ( + IN CONST CHAR16 *DeviceName, + IN UINTN Offset, + IN UINTN Size, + IN BOOLEAN Recover + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree; + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + EFI_STATUS Status; + + VOID *Buffer; + CHAR16 *Str; + UINTN Bytes; + + HEFI_EDITOR_LINE *Line; + + HBufferImage.BufferType = FileTypeDiskBuffer; + + DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName); + if (DevicePath == NULL) { + StatusBarSetStatusString (L"Cannot Find Device"); + return EFI_INVALID_PARAMETER; + } + DupDevicePath = DuplicateDevicePath(DevicePath); + DupDevicePathForFree = DupDevicePath; + // + // get blkio interface + // + Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle); + FreePool(DupDevicePathForFree); + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read Disk Failed"); + return Status; + } + Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read Disk Failed"); + return Status; + } + // + // if Offset exceeds LastBlock, + // return error + // + if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) { + StatusBarSetStatusString (L"Invalid Offset + Size"); + return EFI_LOAD_ERROR; + } + + Bytes = BlkIo->Media->BlockSize * Size; + Buffer = AllocateZeroPool (Bytes); + + if (Buffer == NULL) { + StatusBarSetStatusString (L"Read Disk Failed"); + return EFI_OUT_OF_RESOURCES; + } + + // + // read from disk + // + Status = BlkIo->ReadBlocks ( + BlkIo, + BlkIo->Media->MediaId, + Offset, + Bytes, + Buffer + ); + + if (EFI_ERROR (Status)) { + FreePool (Buffer); + StatusBarSetStatusString (L"Read Disk Failed"); + return EFI_LOAD_ERROR; + } + + HBufferImageFree (); + + // + // convert buffer to line list + // + Status = HBufferImageBufferToList (Buffer, Bytes); + FreePool (Buffer); + + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read Disk Failed"); + return Status; + } + + Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size); + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read Disk Failed"); + return EFI_OUT_OF_RESOURCES; + } + // + // initialize some variables + // + HDiskImage.BlockSize = BlkIo->Media->BlockSize; + + HBufferImage.DisplayPosition.Row = 2; + HBufferImage.DisplayPosition.Column = 10; + + HBufferImage.MousePosition.Row = 2; + HBufferImage.MousePosition.Column = 10; + + HBufferImage.LowVisibleRow = 1; + HBufferImage.HighBits = TRUE; + + HBufferImage.BufferPosition.Row = 1; + HBufferImage.BufferPosition.Column = 1; + + if (!Recover) { + Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines); + if (Str == NULL) { + StatusBarSetStatusString (L"Read Disk Failed"); + return EFI_OUT_OF_RESOURCES; + } + + StatusBarSetStatusString (Str); + SHELL_FREE_NON_NULL (Str); + + HMainEditor.SelectStart = 0; + HMainEditor.SelectEnd = 0; + + } + + // + // has line + // + if (HBufferImage.Lines != NULL) { + HBufferImage.CurrentLine = CR ( + HBufferImage.ListHead->ForwardLink, + HEFI_EDITOR_LINE, + Link, + EFI_EDITOR_LINE_LIST + ); + } else { + // + // create a dummy line + // + Line = HBufferImageCreateLine (); + if (Line == NULL) { + StatusBarSetStatusString (L"Read Disk Failed"); + return EFI_OUT_OF_RESOURCES; + } + + HBufferImage.CurrentLine = Line; + } + + HBufferImage.Modified = FALSE; + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageMouseNeedRefresh = TRUE; + + return EFI_SUCCESS; +} + +/** + Save lines in HBufferImage to disk. + NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!! + + @param[in] DeviceName The device name. + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +HDiskImageSave ( + IN CHAR16 *DeviceName, + IN UINTN Offset, + IN UINTN Size + ) +{ + + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DupDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + EFI_STATUS Status; + EFI_HANDLE Handle; + VOID *Buffer; + UINTN Bytes; + + // + // if not modified, directly return + // + if (HBufferImage.Modified == FALSE) { + return EFI_SUCCESS; + } + + HBufferImage.BufferType = FileTypeDiskBuffer; + + DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName); + if (DevicePath == NULL) { +// StatusBarSetStatusString (L"Cannot Find Device"); + return EFI_INVALID_PARAMETER; + } + DupDevicePath = DuplicateDevicePath(DevicePath); + DupDevicePathForFree = DupDevicePath; + + // + // get blkio interface + // + Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle); + FreePool(DupDevicePathForFree); + if (EFI_ERROR (Status)) { +// StatusBarSetStatusString (L"Read Disk Failed"); + return Status; + } + Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR (Status)) { +// StatusBarSetStatusString (L"Read Disk Failed"); + return Status; + } + + Bytes = BlkIo->Media->BlockSize * Size; + Buffer = AllocateZeroPool (Bytes); + + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // concatenate the line list to a buffer + // + Status = HBufferImageListToBuffer (Buffer, Bytes); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + // + // write the buffer to disk + // + Status = BlkIo->WriteBlocks ( + BlkIo, + BlkIo->Media->MediaId, + Offset, + Bytes, + Buffer + ); + + FreePool (Buffer); + + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + // + // now not modified + // + HBufferImage.Modified = FALSE; + + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h new file mode 100644 index 0000000..dbbac88 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h @@ -0,0 +1,95 @@ +/** @file + Defines DiskImage - the view of the file that is visible at any point, + as well as the event handlers for editing the file + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_DISK_IMAGE_H_ +#define _LIB_DISK_IMAGE_H_ + +#include "HexEditor.h" + +/** + Initialization function for HDiskImage. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HDiskImageInit ( + VOID + ); + +/** + Cleanup function for HDiskImage. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HDiskImageCleanup ( + VOID + ); + +/** + Backup function for HDiskImage. Only a few fields need to be backup. + This is for making the Disk buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES gST->ConOut of resources. +**/ +EFI_STATUS +HDiskImageBackup ( + VOID + ); + +/** + Read a disk from disk into HBufferImage. + + @param[in] DeviceName filename to read. + @param[in] Offset The offset. + @param[in] Size The size. + @param[in] Recover if is for recover, no information print. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +HDiskImageRead ( + IN CONST CHAR16 *DeviceName, + IN UINTN Offset, + IN UINTN Size, + IN BOOLEAN Recover + ); + +/** + Save lines in HBufferImage to disk. + NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!! + + @param[in] DeviceName The device name. + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +HDiskImageSave ( + IN CHAR16 *DeviceName, + IN UINTN Offset, + IN UINTN Size + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c new file mode 100644 index 0000000..aa426d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c @@ -0,0 +1,398 @@ +/** @file + Functions to deal with file buffer. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" + +extern EFI_HANDLE HImageHandleBackup; +extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage; + +extern BOOLEAN HBufferImageNeedRefresh; +extern BOOLEAN HBufferImageOnlyLineNeedRefresh; +extern BOOLEAN HBufferImageMouseNeedRefresh; + +extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; + +HEFI_EDITOR_FILE_IMAGE HFileImage; +HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar; + +// +// for basic initialization of HFileImage +// +HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = { + NULL, + 0, + FALSE +}; + +/** + Initialization function for HFileImage + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HFileImageInit ( + VOID + ) +{ + // + // basically initialize the HFileImage + // + CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage)); + + CopyMem ( + &HFileImageBackupVar, + &HFileImageConst, + sizeof (HFileImageBackupVar) + ); + + return EFI_SUCCESS; +} + +/** + Backup function for HFileImage. Only a few fields need to be backup. + This is for making the file buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HFileImageBackup ( + VOID + ) +{ + SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName); + HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName); + if (HFileImageBackupVar.FileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Cleanup function for HFileImage. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HFileImageCleanup ( + VOID + ) +{ + + SHELL_FREE_NON_NULL (HFileImage.FileName); + SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName); + + return EFI_SUCCESS; +} + +/** + Set FileName field in HFileImage + + @param[in] Str File name to set. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HFileImageSetFileName ( + IN CONST CHAR16 *Str + ) +{ + if (Str == HFileImage.FileName) { + // + // This function might be called using HFileImage.FileName as Str. + // Directly return without updating HFileImage.FileName. + // + return EFI_SUCCESS; + } + // + // free the old file name + // + SHELL_FREE_NON_NULL (HFileImage.FileName); + HFileImage.FileName = AllocateCopyPool (StrSize (Str), Str); + if (HFileImage.FileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Read a file from disk into HBufferImage. + + @param[in] FileName filename to read. + @param[in] Recover if is for recover, no information print. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HFileImageRead ( + IN CONST CHAR16 *FileName, + IN BOOLEAN Recover + ) +{ + HEFI_EDITOR_LINE *Line; + UINT8 *Buffer; + CHAR16 *UnicodeBuffer; + EFI_STATUS Status; + + // + // variable initialization + // + Line = NULL; + + // + // in this function, when you return error ( except EFI_OUT_OF_RESOURCES ) + // you should set status string + // since this function maybe called before the editorhandleinput loop + // so any error will cause editor return + // so if you want to print the error status + // you should set the status string + // + Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly); + // + // NULL pointer is only also a failure for a non-zero file size. + // + if ((EFI_ERROR(Status)) || (Buffer == NULL && HFileImage.Size != 0)) { + UnicodeBuffer = CatSPrint(NULL, L"Read error on file %s: %r", FileName, Status); + if (UnicodeBuffer == NULL) { + SHELL_FREE_NON_NULL(Buffer); + return EFI_OUT_OF_RESOURCES; + } + + StatusBarSetStatusString (UnicodeBuffer); + FreePool (UnicodeBuffer); + return EFI_OUT_OF_RESOURCES; + } + + HFileImageSetFileName (FileName); + + // + // free the old lines + // + HBufferImageFree (); + + Status = HBufferImageBufferToList (Buffer, HFileImage.Size); + SHELL_FREE_NON_NULL (Buffer); + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Error parsing file."); + return Status; + } + + HBufferImage.DisplayPosition.Row = 2; + HBufferImage.DisplayPosition.Column = 10; + HBufferImage.MousePosition.Row = 2; + HBufferImage.MousePosition.Column = 10; + HBufferImage.LowVisibleRow = 1; + HBufferImage.HighBits = TRUE; + HBufferImage.BufferPosition.Row = 1; + HBufferImage.BufferPosition.Column = 1; + HBufferImage.BufferType = FileTypeFileBuffer; + + if (!Recover) { + UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines); + if (UnicodeBuffer == NULL) { + SHELL_FREE_NON_NULL(Buffer); + return EFI_OUT_OF_RESOURCES; + } + + StatusBarSetStatusString (UnicodeBuffer); + FreePool (UnicodeBuffer); + + HMainEditor.SelectStart = 0; + HMainEditor.SelectEnd = 0; + } + + // + // has line + // + if (HBufferImage.Lines != 0) { + HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + } else { + // + // create a dummy line + // + Line = HBufferImageCreateLine (); + if (Line == NULL) { + SHELL_FREE_NON_NULL(Buffer); + return EFI_OUT_OF_RESOURCES; + } + + HBufferImage.CurrentLine = Line; + } + + HBufferImage.Modified = FALSE; + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageMouseNeedRefresh = TRUE; + + return EFI_SUCCESS; +} + +/** + Save lines in HBufferImage to disk. + + @param[in] FileName The file name. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HFileImageSave ( + IN CHAR16 *FileName + ) +{ + + LIST_ENTRY *Link; + HEFI_EDITOR_LINE *Line; + CHAR16 *Str; + EFI_STATUS Status; + UINTN NumLines; + SHELL_FILE_HANDLE FileHandle; + UINTN TotalSize; + UINT8 *Buffer; + UINT8 *Ptr; + EDIT_FILE_TYPE BufferTypeBackup; + + BufferTypeBackup = HBufferImage.BufferType; + HBufferImage.BufferType = FileTypeFileBuffer; + + // + // if is the old file + // + if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) { + // + // check whether file exists on disk + // + if (ShellIsFile(FileName) == EFI_SUCCESS) { + // + // current file exists on disk + // so if not modified, then not save + // + if (HBufferImage.Modified == FALSE) { + return EFI_SUCCESS; + } + // + // if file is read-only, set error + // + if (HFileImage.ReadOnly == TRUE) { + StatusBarSetStatusString (L"Read Only File Can Not Be Saved"); + return EFI_SUCCESS; + } + } + } + + if (ShellIsDirectory(FileName) == EFI_SUCCESS) { + StatusBarSetStatusString (L"Directory Can Not Be Saved"); + return EFI_LOAD_ERROR; + } + + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); + + if (!EFI_ERROR (Status)) { + // + // the file exits, delete it + // + Status = ShellDeleteFile (&FileHandle); + if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) { + StatusBarSetStatusString (L"Write File Failed"); + return EFI_LOAD_ERROR; + } + } + + // + // write all the lines back to disk + // + NumLines = 0; + TotalSize = 0; + for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) { + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + + if (Line->Size != 0) { + TotalSize += Line->Size; + } + // + // end of if Line -> Size != 0 + // + NumLines++; + } + // + // end of for Link + // + Buffer = AllocateZeroPool (TotalSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = Buffer; + for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) { + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + + if (Line->Size != 0) { + CopyMem (Ptr, Line->Buffer, Line->Size); + Ptr += Line->Size; + } + // + // end of if Line -> Size != 0 + // + } + + + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Create File Failed"); + return EFI_LOAD_ERROR; + } + + Status = ShellWriteFile (FileHandle, &TotalSize, Buffer); + FreePool (Buffer); + if (EFI_ERROR (Status)) { + ShellDeleteFile (&FileHandle); + return EFI_LOAD_ERROR; + } + + ShellCloseFile(&FileHandle); + + HBufferImage.Modified = FALSE; + + // + // set status string + // + Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines); + StatusBarSetStatusString (Str); + FreePool (Str); + + // + // now everything is ready , you can set the new file name to filebuffer + // + if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) || + (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){ + // + // not the same + // + HFileImageSetFileName (FileName); + if (HFileImage.FileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + HFileImage.ReadOnly = FALSE; + + return EFI_SUCCESS; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h new file mode 100644 index 0000000..17263c1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h @@ -0,0 +1,83 @@ +/** @file + Defines FileImage - the view of the file that is visible at any point, + as well as the event handlers for editing the file + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_FILE_IMAGE_H_ +#define _LIB_FILE_IMAGE_H_ + +#include "HexEditor.h" + +/** + Initialization function for HFileImage + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HFileImageInit ( + VOID + ); + +/** + Cleanup function for HFileImage. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HFileImageCleanup ( + VOID + ); + +/** + Backup function for HFileImage. Only a few fields need to be backup. + This is for making the file buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HFileImageBackup ( + VOID + ); + +/** + Read a file from disk into HBufferImage. + + @param[in] FileName filename to read. + @param[in] Recover if is for recover, no information print. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HFileImageRead ( + IN CONST CHAR16 *FileName, + IN BOOLEAN Recover + ); + +/** + Save lines in HBufferImage to disk. + + @param[in] FileName The file name. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HFileImageSave ( + IN CHAR16 *FileName + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c new file mode 100644 index 0000000..d4c9b67 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c @@ -0,0 +1,277 @@ +/** @file + Main entry point of editor + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "HexEditor.h" + +// +// Global Variables +// +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-f", TypeFlag}, + {L"-d", TypeFlag}, + {L"-m", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'hexedit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunHexEdit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CHAR16 *Buffer; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + LIST_ENTRY *Package; + CHAR16 *NewName; + CONST CHAR16 *Name; + UINTN Offset; + UINTN Size; + EDIT_FILE_TYPE WhatToDo; + + Buffer = NULL; + ShellStatus = SHELL_SUCCESS; + NewName = NULL; + Buffer = NULL; + Name = NULL; + Offset = 0; + Size = 0; + WhatToDo = FileTypeNone; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"hexedit", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // Check for -d + // + if (ShellCommandLineGetFlag(Package, L"-d")){ + if (ShellCommandLineGetCount(Package) < 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) > 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + WhatToDo = FileTypeDiskBuffer; + Name = ShellCommandLineGetRawValue(Package, 1); + Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2)); + Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 3)); + } + if (Offset == (UINTN)-1 || Size == (UINTN)-1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"hexedit", L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + // + // check for -f + // + if (ShellCommandLineGetFlag(Package, L"-f") && (WhatToDo == FileTypeNone)){ + if (ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Name = ShellCommandLineGetRawValue(Package, 1); + if (Name == NULL || !IsValidFileName(Name)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"hexedit", Name); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + WhatToDo = FileTypeFileBuffer; + } + } + } + + // + // check for -m + // + if (ShellCommandLineGetFlag(Package, L"-m") && (WhatToDo == FileTypeNone)){ + if (ShellCommandLineGetCount(Package) < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + WhatToDo = FileTypeMemBuffer; + Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 1)); + Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2)); + } + } + Name = ShellCommandLineGetRawValue(Package, 1); + if (WhatToDo == FileTypeNone && Name != NULL) { + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (!IsValidFileName(Name)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"hexedit", Name); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + WhatToDo = FileTypeFileBuffer; + } + } else if (WhatToDo == FileTypeNone) { + if (gEfiShellProtocol->GetCurDir(NULL) == NULL) { + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellDebug1HiiHandle, L"hexedit"); + } else { + NewName = EditGetDefaultFileName(L"bin"); + Name = NewName; + WhatToDo = FileTypeFileBuffer; + } + } + + if (ShellStatus == SHELL_SUCCESS && WhatToDo == FileTypeNone) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (WhatToDo == FileTypeFileBuffer && ShellGetCurrentDir(NULL) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellDebug1HiiHandle, L"hexedit"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (ShellStatus == SHELL_SUCCESS) { + // + // Do the editor + // + Status = HMainEditorInit (); + if (EFI_ERROR (Status)) { + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_INIT_FAILED), gShellDebug1HiiHandle); + } else { + HMainEditorBackup (); + switch (WhatToDo) { + case FileTypeFileBuffer: + Status = HBufferImageRead ( + Name==NULL?L"":Name, + NULL, + 0, + 0, + 0, + 0, + FileTypeFileBuffer, + FALSE + ); + break; + + case FileTypeDiskBuffer: + Status = HBufferImageRead ( + NULL, + Name==NULL?L"":Name, + Offset, + Size, + 0, + 0, + FileTypeDiskBuffer, + FALSE + ); + break; + + case FileTypeMemBuffer: + Status = HBufferImageRead ( + NULL, + NULL, + 0, + 0, + (UINT32) Offset, + Size, + FileTypeMemBuffer, + FALSE + ); + break; + + default: + Status = EFI_NOT_FOUND; + break; + } + if (!EFI_ERROR (Status)) { + HMainEditorRefresh (); + Status = HMainEditorKeyInput (); + } + if (Status != EFI_OUT_OF_RESOURCES) { + // + // back up the status string + // + Buffer = CatSPrint (NULL, L"%s\r\n", StatusBarGetString()); + } + } + + // + // cleanup + // + HMainEditorCleanup (); + + if (EFI_ERROR (Status)) { + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = SHELL_UNSUPPORTED; + } + } + + // + // print editor exit code on screen + // + if (Status == EFI_OUT_OF_RESOURCES) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"hexedit"); + } else if (EFI_ERROR(Status)){ + if (Buffer != NULL) { + if (StrCmp (Buffer, L"") != 0) { + // + // print out the status string + // + ShellPrintEx(-1, -1, L"%s", Buffer); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle); + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle); + } + } + } + ShellCommandLineFreeVarList (Package); + } + + SHELL_FREE_NON_NULL (Buffer); + SHELL_FREE_NON_NULL (NewName); + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h new file mode 100644 index 0000000..a258f62 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h @@ -0,0 +1,41 @@ +/** @file + Main include file for hex editor + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_SHELL_HEXEDIT_H_ +#define _EFI_SHELL_HEXEDIT_H_ + +#include "UefiShellDebug1CommandsLib.h" +#include "HexEditorTypes.h" + +#include "MainHexEditor.h" + +#include "BufferImage.h" +#include "FileImage.h" +#include "DiskImage.h" +#include "MemImage.h" + +#include "EditTitleBar.h" +#include "EditStatusBar.h" +#include "EditInputBar.h" +#include "EditMenuBar.h" + +#include "Misc.h" + +#include "Clipboard.h" + +extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; +extern BOOLEAN HEditorFirst; +extern BOOLEAN HEditorExit; + +#endif // _HEDITOR_H diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h new file mode 100644 index 0000000..5afb0da --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h @@ -0,0 +1,126 @@ +/** @file + data types that are used by editor + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _HEDITOR_TYPE_H_ +#define _HEDITOR_TYPE_H_ + +#include "UefiShellDebug1CommandsLib.h" +#include "EditTitleBar.h" + +#define EFI_EDITOR_LINE_LIST SIGNATURE_32 ('e', 'e', 'l', 'l') + +#define ASCII_POSITION ((0x10 * 3) + 12) + + +typedef struct { + UINTN Row; + UINTN Column; +} HEFI_EDITOR_POSITION; + +typedef +EFI_STATUS +(*HEFI_MENU_ITEM_FUNCTION) ( + VOID + ); + +typedef struct { + CHAR16 Name[50]; + CHAR16 Key[3]; + HEFI_MENU_ITEM_FUNCTION Function; +} HMENU_ITEMS; + +typedef struct _HEFI_EDITOR_LINE { + UINTN Signature; + UINT8 Buffer[0x10]; + UINTN Size; // unit is Unicode + LIST_ENTRY Link; +} HEFI_EDITOR_LINE; + +typedef struct _HEFI_EDITOR_MENU_ITEM { + CHAR16 NameToken; + CHAR16 FunctionKeyToken; + HEFI_MENU_ITEM_FUNCTION Function; +} HEFI_EDITOR_MENU_ITEM; + +typedef struct { + UINT32 Foreground : 4; + UINT32 Background : 4; +} HEFI_EDITOR_COLOR_ATTRIBUTES; + +typedef union { + HEFI_EDITOR_COLOR_ATTRIBUTES Colors; + UINTN Data; +} HEFI_EDITOR_COLOR_UNION; + +typedef struct { + UINTN Columns; + UINTN Rows; +} HEFI_EDITOR_TEXT_MODE; + + +typedef struct { + CHAR16 *Name; + + UINTN BlockSize; + UINTN Size; + UINTN Offset; +} HEFI_EDITOR_DISK_IMAGE; + +typedef struct { + EFI_CPU_IO2_PROTOCOL *IoFncs; + UINTN Offset; + UINTN Size; +} HEFI_EDITOR_MEM_IMAGE; + +typedef struct { + CHAR16 *FileName; + UINTN Size; // file size + BOOLEAN ReadOnly; // file is read-only or not +} HEFI_EDITOR_FILE_IMAGE; + +typedef struct { + LIST_ENTRY *ListHead; // list head of lines + HEFI_EDITOR_LINE *Lines; // lines of current file + UINTN NumLines; // number of lines + HEFI_EDITOR_LINE *CurrentLine; // current line cursor is at + HEFI_EDITOR_POSITION DisplayPosition; // cursor position in screen + HEFI_EDITOR_POSITION MousePosition; // mouse position in screen + HEFI_EDITOR_POSITION BufferPosition; // cursor position in buffer + UINTN LowVisibleRow; // the lowest visible row of file position + BOOLEAN HighBits; // cursor is at the high4 bits or low4 bits + BOOLEAN Modified; // BUFFER is modified or not + EDIT_FILE_TYPE BufferType; + + HEFI_EDITOR_FILE_IMAGE *FileImage; + HEFI_EDITOR_DISK_IMAGE *DiskImage; + HEFI_EDITOR_MEM_IMAGE *MemImage; + +} HEFI_EDITOR_BUFFER_IMAGE; + +typedef struct { + HEFI_EDITOR_BUFFER_IMAGE *BufferImage; + + HEFI_EDITOR_COLOR_UNION ColorAttributes; + HEFI_EDITOR_POSITION ScreenSize; // row number and column number + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx; + BOOLEAN MouseSupported; + EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface; + INT32 MouseAccumulatorX; + INT32 MouseAccumulatorY; + + UINTN SelectStart; // starting from 1 + UINTN SelectEnd; // starting from 1 +} HEFI_EDITOR_GLOBAL_EDITOR; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni new file mode 100644 index 0000000..5f7855f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni @@ -0,0 +1,76 @@ +// /** +// +// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        +// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Abstract: +// +// Additional string definitions for UEFI Shell 2.0 Debug1 profile Edit command +// +// +// **/ + +/=# + +#langdef en-US "english" + + +#string STR_HEXEDIT_USAGE #language en-US "\n\n %EHexEditor Usage%N\n" +#string STR_HEXEDIT_FILENAME #language en-US " %H[-f] Filename%N Open File For Editing\n" +#string STR_HEXEDIT_DISKNAME #language en-US " %H-d DiskName FirstBlockNo. BlockNumber%N Open Disk Block For Editing\n" +#string STR_HEXEDIT_OFFSET_SIZE #language en-US " %H-m Offset Size%N Open Memory Region For Editing\n" +#string STR_HEXEDIT_FILE_NAME #language en-US "%Hhexedit%N: Invalid File Name\n" +#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE #language en-US "%EMainEditor init failed on TitleBar init\n%N" +#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU #language en-US "%EMainEditor init failed on MainMenu init\n%N" +#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS #language en-US "%EMainEditor init failed on StatusBar init\n%N" +#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_INPUTBAR #language en-US "%EMainEditor init failed on InputBar init\n%N" +#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE #language en-US "%EMainEditor init failed on BufferImage init\n%N" +#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD #language en-US "%EMainEditor init failed on ClipBoard init\n%N" +#string STR_HEXEDIT_LIBEDITOR_TITLEBAR_CLEAN #language en-US "TitleBar cleanup failed\n" +#string STR_HEXEDIT_LIBEDITOR_MENUBAR_CLEAN #language en-US "MenuBar cleanup failed\n" +#string STR_HEXEDIT_LIBEDITOR_STATUSBAR_CLEAN #language en-US "StatusBar cleanup failed\n" +#string STR_HEXEDIT_LIBEDITOR_INPUTBAR_CLEAN #language en-US "InputBar cleanup failed\n" +#string STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN #language en-US "BufferImage cleanup failed\n" +#string STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN #language en-US "ClipBoard cleanup failed\n" +#string STR_HEXEDIT_LIBINPUTBAR_MAININPUTBAR #language en-US "%s" +#string STR_HEXEDIT_LIBMENUBAR_OPEN_FILE #language en-US "Open File" +#string STR_HEXEDIT_LIBMENUBAR_OPEN_DISK #language en-US "Open Disk" +#string STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY #language en-US "Open Memory" +#string STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER #language en-US "Save Buffer" +#string STR_HEXEDIT_LIBMENUBAR_SELECT_START #language en-US "Select Start" +#string STR_HEXEDIT_LIBMENUBAR_SELECT_END #language en-US "Select End" +#string STR_HEXEDIT_LIBMENUBAR_CUT #language en-US "Cut" +#string STR_HEXEDIT_LIBMENUBAR_PASTE #language en-US "Paste" +#string STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET #language en-US "Go To Offset" +#string STR_HEXEDIT_LIBTITLEBAR_MAINEDITOR #language en-US "%s" +#string STR_HEXEDIT_LIBTITLEBAR_MAINEDITOR_C #language en-US "%c" +#string STR_HEXEDIT_LIBTITLEBAR_MAINEDITOR_TWOVARS #language en-US "( %X ~ %X ) " +#string STR_HEXEDIT_LIBTITLEBAR_FILE #language en-US " [FILE]" +#string STR_HEXEDIT_LIBTITLEBAR_DISK #language en-US " [DISK]" +#string STR_HEXEDIT_LIBTITLEBAR_MEM #language en-US " [MEM]" +#string STR_HEXEDIT_HELP_TITLE #language en-US "Help \n" +#string STR_HEXEDIT_HELP_BLANK #language en-US " \n" +#string STR_HEXEDIT_HELP_LIST_TITLE #language en-US "Control Key Function Key Command \n" +#string STR_HEXEDIT_HELP_DIV #language en-US "----------- ------------ ----------------- \n" +#string STR_HEXEDIT_HELP_GO_TO_OFFSET #language en-US "Ctrl-G F1 Go To Offset \n" +#string STR_HEXEDIT_HELP_SAVE_BUFFER #language en-US "Ctrl-S F2 Save Buffer \n" +#string STR_HEXEDIT_HELP_EXIT #language en-US "Ctrl-Q F3 Exit \n" +#string STR_HEXEDIT_HELP_SELECT_START #language en-US "Ctrl-T F4 Select Start \n" +#string STR_HEXEDIT_HELP_SELECT_END #language en-US "Ctrl-D F5 Select End \n" +#string STR_HEXEDIT_HELP_CUT #language en-US "Ctrl-X F6 Cut \n" +#string STR_HEXEDIT_HELP_PASTE #language en-US "Ctrl-V F7 Paste \n" +#string STR_HEXEDIT_HELP_OPEN_FILE #language en-US "Ctrl-O F8 Open File \n" +#string STR_HEXEDIT_HELP_OPEN_DISK #language en-US "Ctrl-I F9 Open Disk \n" +#string STR_HEXEDIT_HELP_OPEN_MEMORY #language en-US "Ctrl-M F10 Open Memory \n" +#string STR_HEXEDIT_HELP_EXIT_HELP #language en-US "Use Ctrl-W to exit this help \n" +#string STR_HEXEDIT_INIT_FAILED #language en-US "%Hhexedit%N: Initialization failed\n" +#string STR_HEXEDIT_ONE_VAR #language en-US "%Hhexedit%N: %s\n" +#string STR_HEXEDIT_UNKNOWN_EDITOR #language en-US "%Hhexedit%N: Unknown editor error\n" +#string STR_HEXEDIT_NOREDIRECT #language en-US "%Hhexedit%N: Redirection is not allowed\n" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c new file mode 100644 index 0000000..ffb6514 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c @@ -0,0 +1,2378 @@ +/** @file + Defines the Main Editor data type - + - Global variables + - Instances of the other objects of the editor + - Main Interfaces + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" +#include "EditStatusBar.h" +#include "EditInputBar.h" + +HEFI_EDITOR_COLOR_ATTRIBUTES HOriginalColors; +INTN HOriginalMode; + +// +// the first time editor launch +// +BOOLEAN HEditorFirst; + +// +// it's time editor should exit +// +BOOLEAN HEditorExit; + +BOOLEAN HEditorMouseAction; + +extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage; +extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar; + +extern BOOLEAN HBufferImageMouseNeedRefresh; +extern BOOLEAN HBufferImageNeedRefresh; +extern BOOLEAN HBufferImageOnlyLineNeedRefresh; + +HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; +HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar; + +// +// basic initialization for MainEditor +// +HEFI_EDITOR_GLOBAL_EDITOR HMainEditorConst = { + &HBufferImage, + { + {0, 0} + }, + { + 0, + 0 + }, + NULL, + FALSE, + NULL, + 0, + 0, + 1, + 1 +}; + +/** + Help info that will be displayed. +**/ +EFI_STRING_ID HexMainMenuHelpInfo[] = { + STRING_TOKEN(STR_HEXEDIT_HELP_TITLE), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_LIST_TITLE), + STRING_TOKEN(STR_HEXEDIT_HELP_DIV), + STRING_TOKEN(STR_HEXEDIT_HELP_GO_TO_OFFSET), + STRING_TOKEN(STR_HEXEDIT_HELP_SAVE_BUFFER), + STRING_TOKEN(STR_HEXEDIT_HELP_EXIT), + STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_START), + STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_END), + STRING_TOKEN(STR_HEXEDIT_HELP_CUT), + STRING_TOKEN(STR_HEXEDIT_HELP_PASTE), + STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_FILE), + STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_DISK), + STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_MEMORY), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_EXIT_HELP), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_BLANK), + STRING_TOKEN(STR_HEXEDIT_HELP_DIV), + 0 +}; + + +/** + show help menu. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HMainCommandDisplayHelp ( + VOID + ) +{ + INT32 CurrentLine; + CHAR16 *InfoString; + EFI_KEY_DATA KeyData; + EFI_STATUS Status; + UINTN EventIndex; + + // + // print helpInfo + // + for (CurrentLine = 0; 0 != HexMainMenuHelpInfo[CurrentLine]; CurrentLine++) { + InfoString = HiiGetString(gShellDebug1HiiHandle, HexMainMenuHelpInfo[CurrentLine] +, NULL); + ShellPrintEx (0,CurrentLine+1,L"%E%s%N",InfoString); + } + + // + // scan for ctrl+w + // + while (TRUE) { + Status = gBS->WaitForEvent (1, &HMainEditor.TextInputEx->WaitForKeyEx, &EventIndex); + if (EFI_ERROR (Status) || (EventIndex != 0)) { + continue; + } + Status = HMainEditor.TextInputEx->ReadKeyStrokeEx (HMainEditor.TextInputEx, &KeyData); + if (EFI_ERROR (Status)) { + continue; + } + + if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || + (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID)) { + // + // For consoles that don't support/report shift state, + // CTRL+W is translated to L'W' - L'A' + 1. + // + if (KeyData.Key.UnicodeChar == L'W' - L'A' + 1) { + break; + } + } else if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) && + ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) && + ((KeyData.KeyState.KeyShiftState & ~(EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) == 0)) { + // + // For consoles that supports/reports shift state, + // make sure that only CONTROL shift key is pressed. + // + if ((KeyData.Key.UnicodeChar == 'w') || (KeyData.Key.UnicodeChar == 'W')) { + break; + } + } + } + + // update screen with buffer's info + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageRefresh (); + + return EFI_SUCCESS; +} + +/** + Move cursor to specified lines. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HMainCommandGoToOffset ( + VOID + ) +{ + UINTN Size; + UINT64 Offset; + EFI_STATUS Status; + UINTN FRow; + UINTN FCol; + + // + // variable initialization + // + Size = 0; + Offset = 0; + FRow = 0; + FCol = 0; + + // + // get offset + // + Status = InputBarSetPrompt (L"Go To Offset: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (8); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + + return EFI_SUCCESS; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE); + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Invalid Offset"); + return EFI_SUCCESS; + } + + break; + } + } + + Size = HBufferImageGetTotalSize (); + if (Offset >= Size) { + StatusBarSetStatusString (L"Invalid Offset"); + return EFI_SUCCESS; + } + + FRow = (UINTN)DivU64x32(Offset , 0x10) + 1; + FCol = (UINTN)ModU64x32(Offset , 0x10) + 1; + + HBufferImageMovePosition (FRow, FCol, TRUE); + + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageMouseNeedRefresh = TRUE; + + return EFI_SUCCESS; +} + +/** + Save current opened buffer. + If is file buffer, you can save to current file name or + save to another file name. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandSaveBuffer ( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN Done; + CHAR16 *FileName; + BOOLEAN OldFile; + CHAR16 *Str; + EFI_FILE_INFO *Info; + SHELL_FILE_HANDLE ShellFileHandle; + + if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) { + if (!HMainEditor.BufferImage->Modified) { + return EFI_SUCCESS; + } + + Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + // + // the answer is just one character + // + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + // + // loop for user's answer + // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' + // + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // want to save this buffer first + // + Status = HBufferImageSave ( + NULL, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + HMainEditor.BufferImage->BufferType + ); + + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"BufferSave: Problems Writing"); + return Status; + } + + return EFI_SUCCESS; + + case L'n': + case L'N': + // + // the file won't be saved + // + return EFI_SUCCESS; + + case L'c': + case L'C': + return EFI_SUCCESS; + } + // + // end of switch + // + } + // + // ENDOF WHILE + // + } + // + // ENDOF != FILEBUFFER + // + // This command will save currently opened file to disk. + // You can choose save to another file name or just save to + // current file name. + // Below is the scenario of Save File command: ( + // Suppose the old file name is A ) + // 1. An Input Bar will be prompted: "File To Save: [ old file name]" + // IF user press ESC, Save File command ends . + // IF user press Enter, input file name will be A. + // IF user inputs a new file name B, input file name will be B. + // + // 2. IF input file name is A, go to do Step 3. + // IF input file name is B, go to do Step 4. + // + // 3. IF A is read only, Status Bar will show "Access Denied" + // and Save File commands ends. + // IF A is not read only, save file buffer to disk + // and remove Modified flag in Title Bar , then Save File command ends. + // + // 4. IF B does not exist, create this file and save file buffer to it. + // Go to do Step 7. + // IF B exits, do Step 5. + // + // 5. An Input Bar will be prompted: + // "File Exists. Overwrite ( Yes/No/Cancel ) ?" + // IF user press 'y' or 'Y', do Step 6. + // IF user press 'n' or 'N', Save File commands ends. + // IF user press 'c' or 'C' or ESC, Save File commands ends. + // + // 6. IF B is a read-only file, Status Bar will show "Access Denied" + // and Save File commands ends. + // IF B can be read and write, save file buffer to B. + // + // 7. Update File Name field in Title Bar to B + // and remove the Modified flag in Title Bar. + // + Str = CatSPrint(NULL, + L"File to Save: [%s]", + HMainEditor.BufferImage->FileImage->FileName + ); + if (Str == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (StrLen (Str) >= 50) { + // + // replace the long file name with "..." + // + Str[46] = L'.'; + Str[47] = L'.'; + Str[48] = L'.'; + Str[49] = L']'; + Str[50] = L'\0'; + } + + Status = InputBarSetPrompt (Str); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (100); + if (EFI_ERROR (Status)) { + return Status; + } + // + // get new file name + // + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // if user pressed ESC + // + if (Status == EFI_NOT_READY) { + SHELL_FREE_NON_NULL (Str); + return EFI_SUCCESS; + } + + SHELL_FREE_NON_NULL (Str); + + // + // if just enter pressed, so think save to current file name + // + if (StrLen (InputBarGetString()) == 0) { + FileName = CatSPrint(NULL, + L"%s", + HMainEditor.BufferImage->FileImage->FileName + ); + } else { + FileName = CatSPrint(NULL, L"%s", InputBarGetString()); + } + + if (FileName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (!IsValidFileName (FileName)) { + StatusBarSetStatusString (L"Invalid File Name"); + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } + + OldFile = FALSE; + + // + // save to the old file + // + if (StringNoCaseCompare ( + &FileName, + &HMainEditor.BufferImage->FileImage->FileName + ) == 0) { + OldFile = TRUE; + } + + if (OldFile) { + // + // if the file is read only, so can not write back to it. + // + if (HMainEditor.BufferImage->FileImage->ReadOnly) { + StatusBarSetStatusString (L"Access Denied"); + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } + } else { + Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0); + + if (!EFI_ERROR (Status)) { + + Info = ShellGetFileInfo(ShellFileHandle); + + ShellCloseFile(&ShellFileHandle); + // + // check if read only + // + if (Info->Attribute & EFI_FILE_READ_ONLY) { + StatusBarSetStatusString (L"Access Denied"); + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } + + SHELL_FREE_NON_NULL(Info); + // + // ask user whether to overwrite this file + // + Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (FileName); + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (FileName); + return Status; + } + + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + if (Status == EFI_NOT_READY) { + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + Done = TRUE; + break; + case L'n': + case L'N': + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + case L'c': + case L'C': + SHELL_FREE_NON_NULL (FileName); + return EFI_SUCCESS; + } // switch + } // while + } // if opened existing file + } // if OldFile + + // + // save file back to disk + // + Status = HBufferImageSave ( + FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + FileTypeFileBuffer + ); + SHELL_FREE_NON_NULL (FileName); + + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Load a disk buffer editor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandSelectStart ( + VOID + ) +{ + UINTN Start; + + Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column; + + // + // last line + // + if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) { + if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) { + StatusBarSetStatusString (L"Invalid Block Start"); + return EFI_LOAD_ERROR; + } + } + + if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) { + StatusBarSetStatusString (L"Invalid Block Start"); + return EFI_LOAD_ERROR; + } + + HMainEditor.SelectStart = Start; + + HBufferImageNeedRefresh = TRUE; + + return EFI_SUCCESS; +} + +/** + Load a disk buffer editor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandSelectEnd ( + VOID + ) +{ + UINTN End; + + End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column; + + // + // last line + // + if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) { + if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) { + StatusBarSetStatusString (L"Invalid Block End"); + return EFI_LOAD_ERROR; + } + } + + if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) { + StatusBarSetStatusString (L"Invalid Block End"); + return EFI_SUCCESS; + } + + HMainEditor.SelectEnd = End; + + HBufferImageNeedRefresh = TRUE; + + return EFI_SUCCESS; +} + +/** + Cut current line to clipboard. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandCut ( + VOID + ) +{ + UINTN Index; + LIST_ENTRY *Link; + UINT8 *Buffer; + UINTN Count; + + // + // not select, so not allowed to cut + // + if (HMainEditor.SelectStart == 0) { + StatusBarSetStatusString (L"No Block is Selected"); + return EFI_SUCCESS; + } + // + // not select, so not allowed to cut + // + if (HMainEditor.SelectEnd == 0) { + StatusBarSetStatusString (L"No Block is Selected"); + return EFI_SUCCESS; + } + + Link = HMainEditor.BufferImage->ListHead->ForwardLink; + for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) { + Link = Link->ForwardLink; + } + + Count = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1; + Buffer = AllocateZeroPool (Count); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // cut the selected area + // + HBufferImageDeleteCharacterFromBuffer ( + HMainEditor.SelectStart - 1, + Count, + Buffer + ); + + // + // put to clipboard + // + HClipBoardSet (Buffer, Count); + + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + + if (!HMainEditor.BufferImage->Modified) { + HMainEditor.BufferImage->Modified = TRUE; + } + + // + // now no select area + // + HMainEditor.SelectStart = 0; + HMainEditor.SelectEnd = 0; + + return EFI_SUCCESS; +} + +/** + Paste line to file buffer. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandPaste ( + VOID + ) +{ + + BOOLEAN OnlyLineRefresh; + HEFI_EDITOR_LINE *Line; + UINT8 *Buffer; + UINTN Count; + UINTN FPos; + + Count = HClipBoardGet (&Buffer); + if (Count == 0 || Buffer == NULL) { + StatusBarSetStatusString (L"Nothing to Paste"); + return EFI_SUCCESS; + } + + Line = HMainEditor.BufferImage->CurrentLine; + + OnlyLineRefresh = FALSE; + if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) { + // + // is at last line, and after paste will not exceed + // so only this line need to be refreshed + // + // if after add, the line is 0x10, then will append a new line + // so the whole page will need be refreshed + // + OnlyLineRefresh = TRUE; + + } + + FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1; + + HBufferImageAddCharacterToBuffer (FPos, Count, Buffer); + + if (OnlyLineRefresh) { + HBufferImageNeedRefresh = FALSE; + HBufferImageOnlyLineNeedRefresh = TRUE; + } else { + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + } + + if (!HMainEditor.BufferImage->Modified) { + HMainEditor.BufferImage->Modified = TRUE; + } + + return EFI_SUCCESS; + +} + +/** + Exit editor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandExit ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Below is the scenario of Exit command: + // 1. IF currently opened file is not modified, exit the editor and + // Exit command ends. + // IF currently opened file is modified, do Step 2 + // + // 2. An Input Bar will be prompted: + // "File modified. Save ( Yes/No/Cancel )?" + // IF user press 'y' or 'Y', currently opened file will be saved and + // Editor exits + // IF user press 'n' or 'N', currently opened file will not be saved + // and Editor exits. + // IF user press 'c' or 'C' or ESC, Exit command ends. + // + // + // if file has been modified, so will prompt user + // whether to save the changes + // + if (HMainEditor.BufferImage->Modified) { + + Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // write file back to disk + // + Status = HBufferImageSave ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + HMainEditor.BufferImage->BufferType + ); + if (!EFI_ERROR (Status)) { + HEditorExit = TRUE; + } + + return Status; + + case L'n': + case L'N': + HEditorExit = TRUE; + return EFI_SUCCESS; + + case L'c': + case L'C': + return EFI_SUCCESS; + + } + } + } + + HEditorExit = TRUE; + return EFI_SUCCESS; + +} + +/** + Load a file from disk to editor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainCommandOpenFile ( + VOID + ) +{ + BOOLEAN Done; + EFI_STATUS Status; + EDIT_FILE_TYPE BufferType; + + BufferType = HMainEditor.BufferImage->BufferType; + + // + // This command will open a file from current working directory. + // Read-only file can also be opened. But it can not be modified. + // Below is the scenario of Open File command: + // 1. IF currently opened file has not been modified, directly go to step . + // IF currently opened file has been modified, an Input Bar will be + // prompted as : + // "File Modified. Save ( Yes/No/Cancel) ?" + // IF user press 'y' or 'Y', currently opened file will be saved. + // IF user press 'n' or 'N', currently opened file will + // not be saved. + // IF user press 'c' or 'C' or ESC, Open File command ends and + // currently opened file is still opened. + // + // 2. An Input Bar will be prompted as : "File Name to Open: " + // IF user press ESC, Open File command ends and + // currently opened file is still opened. + // Any other inputs with a Return will cause + // currently opened file close. + // + // 3. IF user input file name is an existing file , + // this file will be read and opened. + // IF user input file name is a new file, this file will be created + // and opened. This file's type ( UNICODE or ASCII ) is the same with + // the old file. + // + // + // if current file is modified, so you need to choose whether to + // save it first. + // + if (HMainEditor.BufferImage->Modified) { + + Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + // + // the answer is just one character + // + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + // + // loop for user's answer + // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' + // + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // want to save this buffer first + // + Status = HBufferImageSave ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + HMainEditor.BufferImage->BufferType + ); + if (EFI_ERROR (Status)) { + return Status; + } + + MainTitleBarRefresh ( + HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL, + HMainEditor.BufferImage->BufferType, + HMainEditor.BufferImage->FileImage->ReadOnly, + FALSE, + HMainEditor.ScreenSize.Column, + HMainEditor.ScreenSize.Row, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0 + ); + Done = TRUE; + break; + + case L'n': + case L'N': + // + // the file won't be saved + // + Done = TRUE; + break; + + case L'c': + case L'C': + return EFI_SUCCESS; + } + } + } + // + // TO get the open file name + // + Status = InputBarSetPrompt (L"File Name to Open: "); + if (EFI_ERROR (Status)) { + HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + return Status; + } + + Status = InputBarSetStringSize (100); + if (EFI_ERROR (Status)) { + Status = HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + Status = HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + + return Status; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + // + // CHECK if filename's valid + // + if (!IsValidFileName (InputBarGetString())) { + HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + + StatusBarSetStatusString (L"Invalid File Name"); + return EFI_SUCCESS; + } + + break; + } + } + // + // read from disk + // + Status = HBufferImageRead ( + InputBarGetString(), + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + FileTypeFileBuffer, + FALSE + ); + + if (EFI_ERROR (Status)) { + HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + + return EFI_LOAD_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Load a disk buffer editor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_NOT_FOUND The disk was not found. +**/ +EFI_STATUS +HMainCommandOpenDisk ( + VOID + ) +{ + UINT64 Size; + UINT64 Offset; + CHAR16 *DeviceName; + EFI_STATUS Status; + BOOLEAN Done; + + EDIT_FILE_TYPE BufferType; + + // + // variable initialization + // + Size = 0; + Offset = 0; + BufferType = HMainEditor.BufferImage->BufferType; + + // + // if current file is modified, so you need to choose + // whether to save it first. + // + if (HMainEditor.BufferImage->Modified) { + + Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + // + // the answer is just one character + // + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + // + // loop for user's answer + // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' + // + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // want to save this buffer first + // + Status = HBufferImageSave ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType + ); + if (EFI_ERROR (Status)) { + return Status; + } + + MainTitleBarRefresh ( + HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL, + HMainEditor.BufferImage->BufferType, + HMainEditor.BufferImage->FileImage->ReadOnly, + FALSE, + HMainEditor.ScreenSize.Column, + HMainEditor.ScreenSize.Row, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0 + ); + Done = TRUE; + break; + + case L'n': + case L'N': + // + // the file won't be saved + // + Done = TRUE; + break; + + case L'c': + case L'C': + return EFI_SUCCESS; + } + } + } + // + // get disk block device name + // + Status = InputBarSetPrompt (L"Block Device to Open: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (100); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + + return EFI_SUCCESS; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + break; + } + } + + DeviceName = CatSPrint(NULL, L"%s", InputBarGetString()); + if (DeviceName == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // get starting offset + // + Status = InputBarSetPrompt (L"First Block No.: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (16); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + + return EFI_SUCCESS; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE); + if (EFI_ERROR (Status)) { + continue; + } + + break; + } + } + // + // get Number of Blocks: + // + Status = InputBarSetPrompt (L"Number of Blocks: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (8); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + + return EFI_SUCCESS; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE); + if (EFI_ERROR (Status)) { + continue; + } + + if (Size == 0) { + continue; + } + + break; + } + } + + Status = HBufferImageRead ( + NULL, + DeviceName, + (UINTN)Offset, + (UINTN)Size, + 0, + 0, + FileTypeDiskBuffer, + FALSE + ); + + if (EFI_ERROR (Status)) { + + HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Load memory content to editor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_NOT_FOUND The disk was not found. +**/ +EFI_STATUS +HMainCommandOpenMemory ( + VOID + ) +{ + UINT64 Size; + UINT64 Offset; + EFI_STATUS Status; + BOOLEAN Done; + EDIT_FILE_TYPE BufferType; + + // + // variable initialization + // + Size = 0; + Offset = 0; + BufferType = HMainEditor.BufferImage->BufferType; + + // + // if current buffer is modified, so you need to choose + // whether to save it first. + // + if (HMainEditor.BufferImage->Modified) { + + Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? "); + if (EFI_ERROR (Status)) { + return Status; + } + // + // the answer is just one character + // + Status = InputBarSetStringSize (1); + if (EFI_ERROR (Status)) { + return Status; + } + // + // loop for user's answer + // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C' + // + Done = FALSE; + while (!Done) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + return EFI_SUCCESS; + } + + switch (InputBarGetString()[0]) { + case L'y': + case L'Y': + // + // want to save this buffer first + // + Status = HBufferImageSave ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType + ); + if (EFI_ERROR (Status)) { + return Status; + } + + MainTitleBarRefresh ( + HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL, + HMainEditor.BufferImage->BufferType, + HMainEditor.BufferImage->FileImage->ReadOnly, + FALSE, + HMainEditor.ScreenSize.Column, + HMainEditor.ScreenSize.Row, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0 + ); + Done = TRUE; + break; + + case L'n': + case L'N': + // + // the file won't be saved + // + Done = TRUE; + break; + + case L'c': + case L'C': + return EFI_SUCCESS; + } + } + } + // + // get starting offset + // + Status = InputBarSetPrompt (L"Starting Offset: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (8); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + + return EFI_SUCCESS; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE); + if (EFI_ERROR (Status)) { + continue; + } + + break; + } + } + // + // get Number of Blocks: + // + Status = InputBarSetPrompt (L"Buffer Size: "); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = InputBarSetStringSize (8); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column); + + // + // ESC pressed + // + if (Status == EFI_NOT_READY) { + + return EFI_SUCCESS; + } + // + // THE input string length should > 0 + // + if (StrLen (InputBarGetString()) > 0) { + Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE); + if (EFI_ERROR (Status)) { + continue; + } + + if (Size == 0) { + continue; + } + + break; + } + } + + if ((Offset + Size - 1)> 0xffffffff) { + StatusBarSetStatusString (L"Invalid parameter"); + return EFI_LOAD_ERROR; + } + + Status = HBufferImageRead ( + NULL, + NULL, + 0, + 0, + (UINTN)Offset, + (UINTN)Size, + FileTypeMemBuffer, + FALSE + ); + + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read Device Error!"); + HBufferImageRead ( + HMainEditor.BufferImage->FileImage->FileName, + HMainEditor.BufferImage->DiskImage->Name, + HMainEditor.BufferImage->DiskImage->Offset, + HMainEditor.BufferImage->DiskImage->Size, + HMainEditor.BufferImage->MemImage->Offset, + HMainEditor.BufferImage->MemImage->Size, + BufferType, + TRUE + ); + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; + +} + +MENU_ITEM_FUNCTION HexMainControlBasedMenuFunctions[] = { + NULL, + NULL, /* Ctrl - A */ + NULL, /* Ctrl - B */ + NULL, /* Ctrl - C */ + HMainCommandSelectEnd, /* Ctrl - D */ + HMainCommandDisplayHelp, /* Ctrl - E */ + NULL, /* Ctrl - F */ + HMainCommandGoToOffset, /* Ctrl - G */ + NULL, /* Ctrl - H */ + HMainCommandOpenDisk, /* Ctrl - I */ + NULL, /* Ctrl - J */ + NULL, /* Ctrl - K */ + NULL, /* Ctrl - L */ + HMainCommandOpenMemory, /* Ctrl - M */ + NULL, /* Ctrl - N */ + HMainCommandOpenFile, /* Ctrl - O */ + NULL, /* Ctrl - P */ + HMainCommandExit, /* Ctrl - Q */ + NULL, /* Ctrl - R */ + HMainCommandSaveBuffer, /* Ctrl - S */ + HMainCommandSelectStart, /* Ctrl - T */ + NULL, /* Ctrl - U */ + HMainCommandPaste, /* Ctrl - V */ + NULL, /* Ctrl - W */ + HMainCommandCut, /* Ctrl - X */ + NULL, /* Ctrl - Y */ + NULL, /* Ctrl - Z */ +}; + +CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = { + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1), + HMainCommandGoToOffset + }, + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2), + HMainCommandSaveBuffer + }, + { + STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3), + HMainCommandExit + }, + + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4), + HMainCommandSelectStart + }, + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5), + HMainCommandSelectEnd + }, + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6), + HMainCommandCut + }, + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7), + HMainCommandPaste + }, + + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8), + HMainCommandOpenFile + }, + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9), + HMainCommandOpenDisk + }, + { + STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY), + STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10), + HMainCommandOpenMemory + }, + + { + 0, + 0, + NULL + } +}; + +/** + Init function for MainEditor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainEditorInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + + // + // basic initialization + // + CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor)); + + // + // set screen attributes + // + HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff; + + HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4); + + HOriginalColors = HMainEditor.ColorAttributes.Colors; + + HOriginalMode = gST->ConOut->Mode->Mode; + + // + // query screen size + // + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &(HMainEditor.ScreenSize.Column), + &(HMainEditor.ScreenSize.Row) + ); + + // + // Find TextInEx in System Table ConsoleInHandle + // Per UEFI Spec, TextInEx is required for a console capable platform. + // + Status = gBS->HandleProtocol ( + gST->ConsoleInHandle, + &gEfiSimpleTextInputExProtocolGuid, + (VOID**)&HMainEditor.TextInputEx + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find mouse in System Table ConsoleInHandle + // + Status = gBS->HandleProtocol ( + gST->ConsoleInHandle, + &gEfiSimplePointerProtocolGuid, + (VOID**)&HMainEditor.MouseInterface + ); + if (EFI_ERROR (Status)) { + // + // If there is no Simple Pointer Protocol on System Table + // + HandleBuffer = NULL; + HMainEditor.MouseInterface = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimplePointerProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status) && HandleCount > 0) { + // + // Try to find the first available mouse device + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiSimplePointerProtocolGuid, + (VOID**)&HMainEditor.MouseInterface + ); + if (!EFI_ERROR (Status)) { + break; + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + } + + if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) { + HMainEditor.MouseAccumulatorX = 0; + HMainEditor.MouseAccumulatorY = 0; + HMainEditor.MouseSupported = TRUE; + } + + // + // below will call the five components' init function + // + Status = MainTitleBarInit (L"UEFI HEXEDIT"); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + Status = ControlHotKeyInit (HexMainControlBasedMenuFunctions); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + Status = MenuBarInit (HexEditorMenuItems); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + Status = StatusBarInit (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + InputBarInit (HMainEditor.TextInputEx); + + Status = HBufferImageInit (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + + Status = HClipBoardInit (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle); + return EFI_LOAD_ERROR; + } + // + // clear whole screen and enable cursor + // + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + // + // initialize EditorFirst and EditorExit + // + HEditorFirst = TRUE; + HEditorExit = FALSE; + HEditorMouseAction = FALSE; + + return EFI_SUCCESS; +} + +/** + Cleanup function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainEditorCleanup ( + VOID + ) +{ + EFI_STATUS Status; + + // + // call the five components' cleanup function + // + MainTitleBarCleanup (); + + MenuBarCleanup (); + + StatusBarCleanup (); + + InputBarCleanup (); + + Status = HBufferImageCleanup (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle); + } + + Status = HClipBoardCleanup (); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle); + } + // + // restore old mode + // + if (HOriginalMode != gST->ConOut->Mode->Mode) { + gST->ConOut->SetMode (gST->ConOut, HOriginalMode); + } + + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background) + ); + gST->ConOut->ClearScreen (gST->ConOut); + + return EFI_SUCCESS; +} + +/** + Refresh function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HMainEditorRefresh ( + VOID + ) +{ + BOOLEAN NameChange; + BOOLEAN ReadChange; + + NameChange = FALSE; + ReadChange = FALSE; + + if (HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer) { + if (HMainEditor.BufferImage->DiskImage != NULL && + HBufferImageBackupVar.DiskImage != NULL && + (HMainEditor.BufferImage->DiskImage->Offset != HBufferImageBackupVar.DiskImage->Offset || + HMainEditor.BufferImage->DiskImage->Size != HBufferImageBackupVar.DiskImage->Size) ){ + NameChange = TRUE; + } + } else if (HMainEditor.BufferImage->BufferType == FileTypeMemBuffer) { + if (HMainEditor.BufferImage->MemImage != NULL && + HBufferImageBackupVar.MemImage != NULL && + (HMainEditor.BufferImage->MemImage->Offset != HBufferImageBackupVar.MemImage->Offset || + HMainEditor.BufferImage->MemImage->Size != HBufferImageBackupVar.MemImage->Size) ){ + NameChange = TRUE; + } + } else if (HMainEditor.BufferImage->BufferType == FileTypeFileBuffer) { + if ( HMainEditor.BufferImage->FileImage != NULL && + HMainEditor.BufferImage->FileImage->FileName != NULL && + HBufferImageBackupVar.FileImage != NULL && + HBufferImageBackupVar.FileImage->FileName != NULL && + StrCmp (HMainEditor.BufferImage->FileImage->FileName, HBufferImageBackupVar.FileImage->FileName) != 0 ) { + NameChange = TRUE; + } + } + if ( HMainEditor.BufferImage->FileImage != NULL && + HBufferImageBackupVar.FileImage != NULL && + HMainEditor.BufferImage->FileImage->ReadOnly != HBufferImageBackupVar.FileImage->ReadOnly ) { + ReadChange = TRUE; + } + + // + // to aVOID screen flicker + // the stall value is from experience + // + gBS->Stall (50); + + // + // call the components refresh function + // + if (HEditorFirst + || NameChange + || HMainEditor.BufferImage->BufferType != HBufferImageBackupVar.BufferType + || HBufferImageBackupVar.Modified != HMainEditor.BufferImage->Modified + || ReadChange ) { + + MainTitleBarRefresh ( + HMainEditor.BufferImage->BufferType == FileTypeFileBuffer&&HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Name:NULL, + HMainEditor.BufferImage->BufferType, + (BOOLEAN)(HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->ReadOnly:FALSE), + HMainEditor.BufferImage->Modified, + HMainEditor.ScreenSize.Column, + HMainEditor.ScreenSize.Row, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Offset:0, + HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Size :0 + ); + HBufferImageRefresh (); + } + if (HEditorFirst + || HBufferImageBackupVar.DisplayPosition.Row != HMainEditor.BufferImage->DisplayPosition.Row + || HBufferImageBackupVar.DisplayPosition.Column != HMainEditor.BufferImage->DisplayPosition.Column + || StatusBarGetRefresh()) { + + StatusBarRefresh ( + HEditorFirst, + HMainEditor.ScreenSize.Row, + HMainEditor.ScreenSize.Column, + (UINTN)(-1), + (UINTN)(-1), + FALSE + ); + HBufferImageRefresh (); + } + + if (HEditorFirst) { + HBufferImageRefresh (); + } + + // + // EditorFirst is now set to FALSE + // + HEditorFirst = FALSE; + + return EFI_SUCCESS; +} + +/** + Handle the mouse input. + + @param[in] MouseState The current mouse state. + @param[out] BeforeLeftButtonDown helps with selections. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_NOT_FOUND The disk was not found. +**/ +EFI_STATUS +HMainEditorHandleMouseInput ( + IN EFI_SIMPLE_POINTER_STATE MouseState, + OUT BOOLEAN *BeforeLeftButtonDown + ) +{ + + INT32 TextX; + INT32 TextY; + UINTN FRow; + UINTN FCol; + BOOLEAN HighBits; + LIST_ENTRY *Link; + HEFI_EDITOR_LINE *Line; + UINTN Index; + BOOLEAN Action; + + Action = FALSE; + + // + // have mouse movement + // + if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) { + // + // handle + // + TextX = HGetTextX (MouseState.RelativeMovementX); + TextY = HGetTextY (MouseState.RelativeMovementY); + + HBufferImageAdjustMousePosition (TextX, TextY); + + Action = TRUE; + + } + + if (MouseState.LeftButton) { + HighBits = HBufferImageIsAtHighBits ( + HMainEditor.BufferImage->MousePosition.Column, + &FCol + ); + + // + // not at an movable place + // + if (FCol == 0) { + // + // now just move mouse pointer to legal position + // + // + // move mouse position to legal position + // + HMainEditor.BufferImage->MousePosition.Column -= 10; + if (HMainEditor.BufferImage->MousePosition.Column > 24) { + HMainEditor.BufferImage->MousePosition.Column--; + FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1; + } else { + if (HMainEditor.BufferImage->MousePosition.Column < 24) { + FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1; + } else { + // + // == 24 + // + FCol = 9; + } + } + + HighBits = TRUE; + + } + + FRow = HMainEditor.BufferImage->BufferPosition.Row + + HMainEditor.BufferImage->MousePosition.Row - + HMainEditor.BufferImage->DisplayPosition.Row; + + if (HMainEditor.BufferImage->NumLines < FRow) { + // + // dragging + // + // + // now just move mouse pointer to legal position + // + FRow = HMainEditor.BufferImage->NumLines; + HighBits = TRUE; + } + + Link = HMainEditor.BufferImage->ListHead->ForwardLink; + for (Index = 0; Index < FRow - 1; Index++) { + Link = Link->ForwardLink; + } + + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + + // + // dragging + // + // + // now just move mouse pointer to legal position + // + if (FCol > Line->Size) { + if (*BeforeLeftButtonDown) { + HighBits = FALSE; + + if (Line->Size == 0) { + if (FRow > 1) { + FRow--; + FCol = 16; + } else { + FRow = 1; + FCol = 1; + } + + } else { + FCol = Line->Size; + } + } else { + FCol = Line->Size + 1; + HighBits = TRUE; + } + } + + HBufferImageMovePosition (FRow, FCol, HighBits); + + HMainEditor.BufferImage->MousePosition.Row = HMainEditor.BufferImage->DisplayPosition.Row; + + HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column; + + *BeforeLeftButtonDown = TRUE; + + Action = TRUE; + } else { + // + // else of if LButton + // + // release LButton + // + if (*BeforeLeftButtonDown) { + Action = TRUE; + } + // + // mouse up + // + *BeforeLeftButtonDown = FALSE; + } + + if (Action) { + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +/** + Handle user key input. will route it to other components handle function. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainEditorKeyInput ( + VOID + ) +{ + EFI_KEY_DATA KeyData; + EFI_STATUS Status; + EFI_SIMPLE_POINTER_STATE MouseState; + BOOLEAN NoShiftState; + BOOLEAN LengthChange; + UINTN Size; + UINTN OldSize; + BOOLEAN BeforeMouseIsDown; + BOOLEAN MouseIsDown; + BOOLEAN FirstDown; + BOOLEAN MouseDrag; + UINTN FRow; + UINTN FCol; + UINTN SelectStartBackup; + UINTN SelectEndBackup; + + // + // variable initialization + // + OldSize = 0; + FRow = 0; + FCol = 0; + LengthChange = FALSE; + + MouseIsDown = FALSE; + FirstDown = FALSE; + MouseDrag = FALSE; + + do { + + Status = EFI_SUCCESS; + + HEditorMouseAction = FALSE; + + // + // backup some key elements, so that can aVOID some refresh work + // + HMainEditorBackup (); + + // + // wait for user key input + // + // + // change priority of checking mouse/keyboard activity dynamically + // so prevent starvation of keyboard. + // if last time, mouse moves then this time check keyboard + // + if (HMainEditor.MouseSupported) { + Status = HMainEditor.MouseInterface->GetState ( + HMainEditor.MouseInterface, + &MouseState + ); + if (!EFI_ERROR (Status)) { + + BeforeMouseIsDown = MouseIsDown; + + Status = HMainEditorHandleMouseInput (MouseState, &MouseIsDown); + + if (!EFI_ERROR (Status)) { + if (!BeforeMouseIsDown) { + // + // mouse down + // + if (MouseIsDown) { + FRow = HBufferImage.BufferPosition.Row; + FCol = HBufferImage.BufferPosition.Column; + SelectStartBackup = HMainEditor.SelectStart; + SelectEndBackup = HMainEditor.SelectEnd; + + FirstDown = TRUE; + } + } else { + + SelectStartBackup = HMainEditor.SelectStart; + SelectEndBackup = HMainEditor.SelectEnd; + + // + // begin to drag + // + if (MouseIsDown) { + if (FirstDown) { + if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) { + HMainEditor.SelectStart = 0; + HMainEditor.SelectEnd = 0; + HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol; + + MouseDrag = TRUE; + FirstDown = FALSE; + } + } else { + if (( + (HBufferImage.BufferPosition.Row - 1) * + 0x10 + + HBufferImage.BufferPosition.Column + ) >= HMainEditor.SelectStart + ) { + HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) * + 0x10 + + HBufferImage.BufferPosition.Column; + } else { + HMainEditor.SelectEnd = 0; + } + } + // + // end of if RelativeX/Y + // + } else { + // + // mouse is up + // + if (MouseDrag) { + if (HBufferImageGetTotalSize () == 0) { + HMainEditor.SelectStart = 0; + HMainEditor.SelectEnd = 0; + FirstDown = FALSE; + MouseDrag = FALSE; + } + + if (( + (HBufferImage.BufferPosition.Row - 1) * + 0x10 + + HBufferImage.BufferPosition.Column + ) >= HMainEditor.SelectStart + ) { + HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) * + 0x10 + + HBufferImage.BufferPosition.Column; + } else { + HMainEditor.SelectEnd = 0; + } + + if (HMainEditor.SelectEnd == 0) { + HMainEditor.SelectStart = 0; + } + } + + FirstDown = FALSE; + MouseDrag = FALSE; + } + + if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) { + if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) { + HBufferImageNeedRefresh = TRUE; + } else { + if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) { + HBufferImageNeedRefresh = TRUE; + } else { + HBufferImageOnlyLineNeedRefresh = TRUE; + } + } + } + } + + HEditorMouseAction = TRUE; + HBufferImageMouseNeedRefresh = TRUE; + + } else if (Status == EFI_LOAD_ERROR) { + StatusBarSetStatusString (L"Invalid Mouse Movement "); + } + } + } + + // + // CheckEvent() returns Success when non-partial key is pressed. + // + Status = gBS->CheckEvent (HMainEditor.TextInputEx->WaitForKeyEx); + if (!EFI_ERROR (Status)) { + Status = HMainEditor.TextInputEx->ReadKeyStrokeEx (HMainEditor.TextInputEx, &KeyData); + if (!EFI_ERROR (Status)) { + // + // dispatch to different components' key handling function + // so not everywhere has to set this variable + // + HBufferImageMouseNeedRefresh = TRUE; + + // + // clear previous status string + // + StatusBarSetRefresh(); + // + // NoShiftState: TRUE when no shift key is pressed. + // + NoShiftState = ((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) == 0) || (KeyData.KeyState.KeyShiftState == EFI_SHIFT_STATE_VALID); + // + // dispatch to different components' key handling function + // + if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&KeyData)) { + Status = EFI_SUCCESS; + } else if (NoShiftState && KeyData.Key.ScanCode == SCAN_NULL) { + Status = HBufferImageHandleInput (&KeyData.Key); + } else if (NoShiftState && ((KeyData.Key.ScanCode >= SCAN_UP) && (KeyData.Key.ScanCode <= SCAN_PAGE_DOWN))) { + Status = HBufferImageHandleInput (&KeyData.Key); + } else if (NoShiftState && ((KeyData.Key.ScanCode >= SCAN_F1) && KeyData.Key.ScanCode <= SCAN_F12)) { + Status = MenuBarDispatchFunctionKey (&KeyData.Key); + } else { + StatusBarSetStatusString (L"Unknown Command"); + + HBufferImageMouseNeedRefresh = FALSE; + } + + if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) { + // + // not already has some error status + // + if (StrCmp (L"", StatusBarGetString()) == 0) { + StatusBarSetStatusString (L"Disk Error. Try Again"); + } + } + } + // + // decide if has to set length warning + // + if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) { + LengthChange = FALSE; + } else { + // + // still the old buffer + // + if (HBufferImage.BufferType != FileTypeFileBuffer) { + Size = HBufferImageGetTotalSize (); + + switch (HBufferImage.BufferType) { + case FileTypeDiskBuffer: + OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize; + break; + + case FileTypeMemBuffer: + OldSize = HBufferImage.MemImage->Size; + break; + + default: + OldSize = 0; + break; + } + + if (!LengthChange) { + if (OldSize != Size) { + StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed"); + } + } + + if (OldSize != Size) { + LengthChange = TRUE; + } else { + LengthChange = FALSE; + } + } + } + } + // + // after handling, refresh editor + // + HMainEditorRefresh (); + + } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit); + + return Status; +} + +/** + Backup function for MainEditor. +**/ +VOID +HMainEditorBackup ( + VOID + ) +{ + HMainEditorBackupVar.SelectStart = HMainEditor.SelectStart; + HMainEditorBackupVar.SelectEnd = HMainEditor.SelectEnd; + HBufferImageBackup (); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h new file mode 100644 index 0000000..edf7da2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h @@ -0,0 +1,75 @@ +/** @file + Defines the Main Editor data type - + - Global variables + - Instances of the other objects of the editor + - Main Interfaces + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_EDITOR_H_ +#define _LIB_EDITOR_H_ + +#include "HexEditor.h" + +/** + Init function for MainEditor + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainEditorInit ( + VOID + ); + +/** + Cleanup function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainEditorCleanup ( + VOID + ); + +/** + Refresh function for MainEditor. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HMainEditorRefresh ( + VOID + ); + +/** + Handle user key input. will route it to other components handle function. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation occured. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMainEditorKeyInput ( + VOID + ); + +/** + Backup function for MainEditor. +**/ +VOID +HMainEditorBackup ( + VOID + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c new file mode 100644 index 0000000..eec29dc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c @@ -0,0 +1,284 @@ +/** @file + Functions to deal with Mem buffer + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" + +extern EFI_HANDLE HImageHandleBackup; + +extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage; + +extern BOOLEAN HBufferImageNeedRefresh; +extern BOOLEAN HBufferImageOnlyLineNeedRefresh; +extern BOOLEAN HBufferImageMouseNeedRefresh; + +extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor; + +HEFI_EDITOR_MEM_IMAGE HMemImage; +HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar; + +// +// for basic initialization of HDiskImage +// +HEFI_EDITOR_MEM_IMAGE HMemImageConst = { + NULL, + 0, + 0 +}; + +/** + Initialization function for HDiskImage. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMemImageInit ( + VOID + ) +{ + EFI_STATUS Status; + + // + // basically initialize the HMemImage + // + CopyMem (&HMemImage, &HMemImageConst, sizeof (HMemImage)); + + Status = gBS->LocateProtocol ( + &gEfiCpuIo2ProtocolGuid, + NULL, + (VOID**)&HMemImage.IoFncs + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } else { + return EFI_LOAD_ERROR; + } +} + +/** + Backup function for HDiskImage. Only a few fields need to be backup. + This is for making the Disk buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HMemImageBackup ( + VOID + ) +{ + HMemImageBackupVar.Offset = HMemImage.Offset; + HMemImageBackupVar.Size = HMemImage.Size; + + return EFI_SUCCESS; +} + +/** + Set FileName field in HFileImage. + + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HMemImageSetMemOffsetSize ( + IN UINTN Offset, + IN UINTN Size + ) +{ + + HMemImage.Offset = Offset; + HMemImage.Size = Size; + + return EFI_SUCCESS; +} + +/** + Read a disk from disk into HBufferImage. + + @param[in] Offset The offset. + @param[in] Size The size. + @param[in] Recover if is for recover, no information print. + + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HMemImageRead ( + IN UINTN Offset, + IN UINTN Size, + IN BOOLEAN Recover + ) +{ + + EFI_STATUS Status; + void *Buffer; + CHAR16 *Str; + HEFI_EDITOR_LINE *Line; + + HBufferImage.BufferType = FileTypeMemBuffer; + + Buffer = AllocateZeroPool (Size); + if (Buffer == NULL) { + StatusBarSetStatusString (L"Read Memory Failed"); + return EFI_OUT_OF_RESOURCES; + } + + Status = HMemImage.IoFncs->Mem.Read ( + HMemImage.IoFncs, + EfiCpuIoWidthUint8, + Offset, + Size, + Buffer + ); + + if (EFI_ERROR (Status)) { + FreePool (Buffer); + StatusBarSetStatusString (L"Memory Specified Not Accessible"); + return EFI_LOAD_ERROR; + } + + HBufferImageFree (); + + Status = HBufferImageBufferToList (Buffer, Size); + FreePool (Buffer); + + if (EFI_ERROR (Status)) { + StatusBarSetStatusString (L"Read Memory Failed"); + return Status; + } + + Status = HMemImageSetMemOffsetSize (Offset, Size); + + HBufferImage.DisplayPosition.Row = 2; + HBufferImage.DisplayPosition.Column = 10; + + HBufferImage.MousePosition.Row = 2; + HBufferImage.MousePosition.Column = 10; + + HBufferImage.LowVisibleRow = 1; + HBufferImage.HighBits = TRUE; + + HBufferImage.BufferPosition.Row = 1; + HBufferImage.BufferPosition.Column = 1; + + if (!Recover) { + Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines); + if (Str == NULL) { + StatusBarSetStatusString (L"Read Memory Failed"); + return EFI_OUT_OF_RESOURCES; + } + + StatusBarSetStatusString (Str); + SHELL_FREE_NON_NULL (Str); + + HMainEditor.SelectStart = 0; + HMainEditor.SelectEnd = 0; + + } + + // + // has line + // + if (HBufferImage.Lines != NULL) { + HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + } else { + // + // create a dummy line + // + Line = HBufferImageCreateLine (); + if (Line == NULL) { + StatusBarSetStatusString (L"Read Memory Failed"); + return EFI_OUT_OF_RESOURCES; + } + + HBufferImage.CurrentLine = Line; + } + + HBufferImage.Modified = FALSE; + HBufferImageNeedRefresh = TRUE; + HBufferImageOnlyLineNeedRefresh = FALSE; + HBufferImageMouseNeedRefresh = TRUE; + + return EFI_SUCCESS; + +} + +/** + Save lines in HBufferImage to disk. + + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HMemImageSave ( + IN UINTN Offset, + IN UINTN Size + ) +{ + + EFI_STATUS Status; + VOID *Buffer; + + // + // not modified, so directly return + // + if (HBufferImage.Modified == FALSE) { + return EFI_SUCCESS; + } + + HBufferImage.BufferType = FileTypeMemBuffer; + + Buffer = AllocateZeroPool (Size); + + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = HBufferImageListToBuffer (Buffer, Size); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + // + // write back to memory + // + Status = HMemImage.IoFncs->Mem.Write ( + HMemImage.IoFncs, + EfiCpuIoWidthUint8, + Offset, + Size, + Buffer + ); + + FreePool (Buffer); + + if (EFI_ERROR (Status)) { + return EFI_LOAD_ERROR; + } + // + // now not modified + // + HBufferImage.Modified = FALSE; + + return EFI_SUCCESS; +} + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h new file mode 100644 index 0000000..09d3eb4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h @@ -0,0 +1,92 @@ +/** @file + Defines MemImage - the view of the file that is visible at any point, + as well as the event handlers for editing the file + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_MEM_IMAGE_H_ +#define _LIB_MEM_IMAGE_H_ + +#include "HexEditor.h" + +/** + Initialization function for HDiskImage. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_LOAD_ERROR A load error occured. +**/ +EFI_STATUS +HMemImageInit ( + VOID + ); + +/** + Backup function for HDiskImage. Only a few fields need to be backup. + This is for making the Disk buffer refresh as few as possible. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HMemImageBackup ( + VOID + ); + +/** + Set FileName field in HFileImage. + + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HMemImageSetMemOffsetSize ( + IN UINTN Offset, + IN UINTN Size + ); + +/** + Read a disk from disk into HBufferImage. + + @param[in] Offset The offset. + @param[in] Size The size. + @param[in] Recover if is for recover, no information print. + + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HMemImageRead ( + IN UINTN Offset, + IN UINTN Size, + IN BOOLEAN Recover + ); + +/** + Save lines in HBufferImage to disk. + + @param[in] Offset The offset. + @param[in] Size The size. + + @retval EFI_LOAD_ERROR A load error occured. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +HMemImageSave ( + IN UINTN Offset, + IN UINTN Size + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c new file mode 100644 index 0000000..e4c099c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c @@ -0,0 +1,262 @@ +/** @file + Implementation of various string and line routines + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "HexEditor.h" + +extern BOOLEAN HEditorMouseAction; + +/** + Free a line and it's internal buffer. + + @param[in] Src The line to be freed. +**/ +VOID +HLineFree ( + IN HEFI_EDITOR_LINE *Src + ) +{ + if (Src == NULL) { + return ; + } + + SHELL_FREE_NON_NULL (Src); + +} + +/** + Advance to the next Count lines. + + @param[in] Count The line number to advance. + + @retval NULL An error occured. + @return A pointer to the line after advance. +**/ +HEFI_EDITOR_LINE * +HLineAdvance ( + IN UINTN Count + ) +{ + UINTN Index; + HEFI_EDITOR_LINE *Line; + + Line = HMainEditor.BufferImage->CurrentLine; + if (Line == NULL) { + return NULL; + } + + for (Index = 0; Index < Count; Index++) { + // + // if already last line + // + if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead) { + return NULL; + } + + Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + } + + return Line; +} + +/** + Retreat to the previous Count lines. + + @param[in] Count The line number to retreat. + + @retval NULL An error occured. + @return A pointer to the line after retreat. +**/ +HEFI_EDITOR_LINE * +HLineRetreat ( + IN UINTN Count + ) +{ + UINTN Index; + HEFI_EDITOR_LINE *Line; + + Line = HMainEditor.BufferImage->CurrentLine; + if (Line == NULL) { + return NULL; + } + + for (Index = 0; Index < Count; Index++) { + // + // already the first line + // + if (Line->Link.BackLink == HMainEditor.BufferImage->ListHead) { + return NULL; + } + + Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + } + + return Line; +} + +/** + Advance/Retreat lines. + + @param[in] Count The line number to advance/retreat. + >0 : advance + <0: retreat + + @retval NULL An error occured. + @return A pointer to the line after move. +**/ +HEFI_EDITOR_LINE * +HMoveLine ( + IN INTN Count + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN AbsCount; + + // + // difference with MoveCurrentLine + // just return Line + // do not set currentline to Line + // + if (Count <= 0) { + AbsCount = (UINTN)ABS(Count); + Line = HLineRetreat (AbsCount); + } else { + Line = HLineAdvance ((UINTN)Count); + } + + return Line; +} + +/** + Advance/Retreat lines and set CurrentLine in BufferImage to it. + + @param[in] Count The line number to advance/retreat. + >0 : advance + <0: retreat + + @retval NULL An error occured. + @return A pointer to the line after move. +**/ +HEFI_EDITOR_LINE * +HMoveCurrentLine ( + IN INTN Count + ) +{ + HEFI_EDITOR_LINE *Line; + UINTN AbsCount; + + // + // <0: retreat + // >0: advance + // + if (Count <= 0) { + AbsCount = (UINTN)ABS(Count); + Line = HLineRetreat (AbsCount); + } else { + Line = HLineAdvance ((UINTN)Count); + } + + if (Line == NULL) { + return NULL; + } + + HMainEditor.BufferImage->CurrentLine = Line; + + return Line; +} + + +/** + Free all the lines in HBufferImage. + Fields affected: + Lines + CurrentLine + NumLines + ListHead + + @param[in] ListHead The list head. + @param[in] Lines The lines. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HFreeLines ( + IN LIST_ENTRY *ListHead, + IN HEFI_EDITOR_LINE *Lines + ) +{ + LIST_ENTRY *Link; + HEFI_EDITOR_LINE *Line; + + // + // release all the lines + // + if (Lines != NULL) { + + Line = Lines; + Link = &(Line->Link); + do { + Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST); + Link = Link->ForwardLink; + HLineFree (Line); + } while (Link != ListHead); + } + + ListHead->ForwardLink = ListHead; + ListHead->BackLink = ListHead; + + return EFI_SUCCESS; +} + +/** + Get the X information for the mouse. + + @param[in] GuidX The change. + + @return the new information. +**/ +INT32 +HGetTextX ( + IN INT32 GuidX + ) +{ + INT32 Gap; + + HMainEditor.MouseAccumulatorX += GuidX; + Gap = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX); + HMainEditor.MouseAccumulatorX = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX); + HMainEditor.MouseAccumulatorX = HMainEditor.MouseAccumulatorX / (INT32) HMainEditor.ScreenSize.Column; + return Gap; +} + +/** + Get the Y information for the mouse. + + @param[in] GuidY The change. + + @return the new information. +**/ +INT32 +HGetTextY ( + IN INT32 GuidY + ) +{ + INT32 Gap; + + HMainEditor.MouseAccumulatorY += GuidY; + Gap = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY); + HMainEditor.MouseAccumulatorY = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY); + HMainEditor.MouseAccumulatorY = HMainEditor.MouseAccumulatorY / (INT32) HMainEditor.ScreenSize.Row; + + return Gap; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h new file mode 100644 index 0000000..738d9e5 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h @@ -0,0 +1,93 @@ +/** @file + Definitions for various line and string routines + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_MISC_H_ +#define _LIB_MISC_H_ + +#include "HexEditor.h" + +/** + Advance/Retreat lines. + + @param[in] Count The line number to advance/retreat. + >0 : advance + <0: retreat + + @retval NULL An error occured. + @return A pointer to the line after move. +**/ +HEFI_EDITOR_LINE * +HMoveLine ( + IN INTN Count + ); + +/** + Advance/Retreat lines and set CurrentLine in BufferImage to it. + + @param[in] Count The line number to advance/retreat. + >0 : advance + <0: retreat + + @retval NULL An error occured. + @return A pointer to the line after move. +**/ +HEFI_EDITOR_LINE * +HMoveCurrentLine ( + IN INTN Count + ); + +/** + Free all the lines in HBufferImage. + Fields affected: + Lines + CurrentLine + NumLines + ListHead + + @param[in] ListHead The list head. + @param[in] Lines The lines. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +HFreeLines ( + IN LIST_ENTRY *ListHead, + IN HEFI_EDITOR_LINE *Lines + ); + +/** + Get the X information for the mouse. + + @param[in] GuidX The change. + + @return the new information. +**/ +INT32 +HGetTextX ( + IN INT32 GuidX + ); + +/** + Get the Y information for the mouse. + + @param[in] GuidY The change. + + @return the new information. +**/ +INT32 +HGetTextY ( + IN INT32 GuidY + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c new file mode 100644 index 0000000..bd7677e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c @@ -0,0 +1,409 @@ +/** @file + Main file for LoadPciRom shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include +#include +#include +#include + +/** + Connects all available drives and controllers. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The abort mechanism was received. +**/ +EFI_STATUS +LoadPciRomConnectAllDriversToAllControllers ( + VOID + ); + +/** + Command entry point. + + @param[in] RomBar The Rom Base address. + @param[in] RomSize The Rom size. + @param[in] FileName The file name. + + @retval EFI_SUCCESS The command completed successfully. + @retval EFI_INVALID_PARAMETER Command usage error. + @retval EFI_UNSUPPORTED Protocols unsupported. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval Other value Unknown error. +**/ +EFI_STATUS +LoadEfiDriversFromRomImage ( + VOID *RomBar, + UINTN RomSize, + CONST CHAR16 *FileName + ); + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-nc", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'loadpcirom' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLoadPciRom ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_SHELL_FILE_INFO *FileList; + UINTN SourceSize; + UINT8 *File1Buffer; + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + BOOLEAN Connect; + CONST CHAR16 *Param; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *Node; + // + // Local variable initializations + // + File1Buffer = NULL; + ShellStatus = SHELL_SUCCESS; + FileList = NULL; + + + // + // verify number of arguments + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"loadpcirom", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"loadpcirom"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetFlag(Package, L"-nc")) { + Connect = FALSE; + } else { + Connect = TRUE; + } + + // + // get a list with each file specified by parameters + // if parameter is a directory then add all the files below it to the list + // + for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ; Param != NULL + ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ){ + Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Param); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + } + if (ShellStatus == SHELL_SUCCESS && FileList != NULL) { + // + // loop through the list and make sure we are not aborting... + // + for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag() + ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link) + ){ + if (EFI_ERROR(Node->Status)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName); + ShellStatus = SHELL_INVALID_PARAMETER; + continue; + } + if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName); + ShellStatus = SHELL_INVALID_PARAMETER; + continue; + } + SourceSize = (UINTN) Node->Info->FileSize; + File1Buffer = AllocateZeroPool (SourceSize); + if (File1Buffer == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"loadpcirom"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + continue; + } + Status = gEfiShellProtocol->ReadFile(Node->Handle, &SourceSize, File1Buffer); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_READ_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = LoadEfiDriversFromRomImage ( + File1Buffer, + SourceSize, + Node->FullName + ); + + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_PCI_ROM_RES), gShellDebug1HiiHandle, Node->FullName, Status); + } + FreePool(File1Buffer); + } + } else if (ShellStatus == SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_SPEC), gShellDebug1HiiHandle, "loadpcirom"); + ShellStatus = SHELL_NOT_FOUND; + } + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + Status = ShellCloseFileMetaArg(&FileList); + } + FileList = NULL; + + if (Connect) { + Status = LoadPciRomConnectAllDriversToAllControllers (); + } + } + } + + return (ShellStatus); +} + +/** + Command entry point. + + @param[in] RomBar The Rom Base address. + @param[in] RomSize The Rom size. + @param[in] FileName The file name. + + @retval EFI_SUCCESS The command completed successfully. + @retval EFI_INVALID_PARAMETER Command usage error. + @retval EFI_UNSUPPORTED Protocols unsupported. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval Other value Unknown error. +**/ +EFI_STATUS +LoadEfiDriversFromRomImage ( + VOID *RomBar, + UINTN RomSize, + CONST CHAR16 *FileName + ) + +{ + EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; + PCI_DATA_STRUCTURE *Pcir; + UINTN ImageIndex; + UINTN RomBarOffset; + UINT32 ImageSize; + UINT16 ImageOffset; + EFI_HANDLE ImageHandle; + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + CHAR16 RomFileName[280]; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + BOOLEAN SkipImage; + UINT32 DestinationSize; + UINT32 ScratchSize; + UINT8 *Scratch; + VOID *ImageBuffer; + VOID *DecompressedImageBuffer; + UINT32 ImageLength; + EFI_DECOMPRESS_PROTOCOL *Decompress; + UINT32 InitializationSize; + + ImageIndex = 0; + ReturnStatus = EFI_NOT_FOUND; + RomBarOffset = (UINTN) RomBar; + + do { + + EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset; + + if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex); +// PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex); + return ReturnStatus; + } + + // + // If the pointer to the PCI Data Structure is invalid, no further images can be located. + // The PCI Data Structure must be DWORD aligned. + // + if (EfiRomHeader->PcirOffset == 0 || + (EfiRomHeader->PcirOffset & 3) != 0 || + RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) { + break; + } + + Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset); + // + // If a valid signature is not present in the PCI Data Structure, no further images can be located. + // + if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + break; + } + ImageSize = Pcir->ImageLength * 512; + if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) { + break; + } + + if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && + (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) && + ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || + (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) { + + ImageOffset = EfiRomHeader->EfiImageHeaderOffset; + InitializationSize = EfiRomHeader->InitializationSize * 512; + + if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) { + + ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset); + ImageLength = InitializationSize - ImageOffset; + DecompressedImageBuffer = NULL; + + // + // decompress here if needed + // + SkipImage = FALSE; + if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + SkipImage = TRUE; + } + + if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + SkipImage = TRUE; + } else { + SkipImage = TRUE; + Status = Decompress->GetInfo ( + Decompress, + ImageBuffer, + ImageLength, + &DestinationSize, + &ScratchSize + ); + if (!EFI_ERROR (Status)) { + DecompressedImageBuffer = AllocateZeroPool (DestinationSize); + if (ImageBuffer != NULL) { + Scratch = AllocateZeroPool (ScratchSize); + if (Scratch != NULL) { + Status = Decompress->Decompress ( + Decompress, + ImageBuffer, + ImageLength, + DecompressedImageBuffer, + DestinationSize, + Scratch, + ScratchSize + ); + if (!EFI_ERROR (Status)) { + ImageBuffer = DecompressedImageBuffer; + ImageLength = DestinationSize; + SkipImage = FALSE; + } + + FreePool (Scratch); + } + } + } + } + } + + if (!SkipImage) { + // + // load image and start image + // + UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex); + FilePath = FileDevicePath (NULL, RomFileName); + + Status = gBS->LoadImage ( + TRUE, + gImageHandle, + FilePath, + ImageBuffer, + ImageLength, + &ImageHandle + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex); +// PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status); + } else { + Status = gBS->StartImage (ImageHandle, NULL, NULL); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex); +// PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status); + } else { + ReturnStatus = Status; + } + } + } + + if (DecompressedImageBuffer != NULL) { + FreePool (DecompressedImageBuffer); + } + + } + } + + RomBarOffset = RomBarOffset + ImageSize; + ImageIndex++; + } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize)); + + return ReturnStatus; +} + +/** + Connects all available drives and controllers. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_ABORTED The abort mechanism was received. +**/ +EFI_STATUS +LoadPciRomConnectAllDriversToAllControllers ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + if (ShellGetExecutionBreakFlag ()) { + Status = EFI_ABORTED; + break; + } + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + return Status; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c new file mode 100644 index 0000000..d8e849a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c @@ -0,0 +1,410 @@ +/** @file + Main file for Mode shell Debug1 function. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which acModeanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// Need full names for Standard-Format Output +// +STATIC CONST CHAR16 NameEfiReservedMemoryType[] = L"Reserved"; +STATIC CONST CHAR16 NameEfiLoaderCode[] = L"LoaderCode"; +STATIC CONST CHAR16 NameEfiLoaderData[] = L"LoaderData"; +STATIC CONST CHAR16 NameEfiBootServicesCode[] = L"BootServiceCode"; +STATIC CONST CHAR16 NameEfiBootServicesData[] = L"BootServiceData"; +STATIC CONST CHAR16 NameEfiRuntimeServicesCode[] = L"RuntimeCode"; +STATIC CONST CHAR16 NameEfiRuntimeServicesData[] = L"RuntimeData"; +STATIC CONST CHAR16 NameEfiConventionalMemory[] = L"Available"; +STATIC CONST CHAR16 NameEfiPersistentMemory[] = L"Persistent"; +STATIC CONST CHAR16 NameEfiUnusableMemory[] = L"UnusableMemory"; +STATIC CONST CHAR16 NameEfiACPIReclaimMemory[] = L"ACPIReclaimMemory"; +STATIC CONST CHAR16 NameEfiACPIMemoryNVS[] = L"ACPIMemoryNVS"; +STATIC CONST CHAR16 NameEfiMemoryMappedIO[] = L"MemoryMappedIO"; +STATIC CONST CHAR16 NameEfiMemoryMappedIOPortSpace[] = L"MemoryMappedIOPortSpace"; +STATIC CONST CHAR16 NameEfiPalCode[] = L"PalCode"; + +// +// Need short names for some memory types +// +STATIC CONST CHAR16 NameEfiBootServicesCodeShort[] = L"BS_Code"; +STATIC CONST CHAR16 NameEfiBootServicesDataShort[] = L"BS_Data"; +STATIC CONST CHAR16 NameEfiRuntimeServicesCodeShort[] = L"RT_Code"; +STATIC CONST CHAR16 NameEfiRuntimeServicesDataShort[] = L"RT_Data"; +STATIC CONST CHAR16 NameEfiUnusableMemoryShort[] = L"Unusable"; +STATIC CONST CHAR16 NameEfiACPIReclaimMemoryShort[] = L"ACPI_Recl"; +STATIC CONST CHAR16 NameEfiACPIMemoryNVSShort[] = L"ACPI_NVS"; +STATIC CONST CHAR16 NameEfiMemoryMappedIOShort[] = L"MMIO"; +STATIC CONST CHAR16 NameEfiMemoryMappedIOPortSpaceShort[] = L"MMIO_Port"; + +#include "UefiShellDebug1CommandsLib.h" + +typedef struct { + UINT32 Type; + UINT64 NumberOfPages; + LIST_ENTRY Link; +} MEMORY_LENGTH_ENTRY; + +/** + Add the length of the specified type to List. + + @param List A list to hold all pairs of . + @param Type Memory type. + @param NumberOfPages Number of pages. +**/ +VOID +AddMemoryLength ( + LIST_ENTRY *List, + UINT32 Type, + UINT64 NumberOfPages + ) +{ + MEMORY_LENGTH_ENTRY *Entry; + MEMORY_LENGTH_ENTRY *NewEntry; + LIST_ENTRY *Link; + + Entry = NULL; + for (Link = GetFirstNode (List); !IsNull (List, Link); Link = GetNextNode (List, Link)) { + Entry = BASE_CR (Link, MEMORY_LENGTH_ENTRY, Link); + if (Entry->Type >= Type) { + break; + } + } + + if ((Entry != NULL) && (Entry->Type == Type)) { + // + // The Entry is the one we look for. + // + NewEntry = Entry; + } else { + // + // The search operation breaks due to: + // 1. Type of every entry < Type --> Insert to tail + // 2. Type of an entry > Type --> Insert to previous of this entry + // + NewEntry = AllocatePool (sizeof (*NewEntry)); + if (NewEntry == NULL) { + return; + } + NewEntry->Type = Type; + NewEntry->NumberOfPages = 0; + InsertTailList (Link, &NewEntry->Link); + } + + NewEntry->NumberOfPages += NumberOfPages; +} + +/** + Function for 'memmap' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMemMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN Size; + EFI_MEMORY_DESCRIPTOR *Descriptors; + UINTN MapKey; + UINTN ItemSize; + UINT32 Version; + EFI_MEMORY_DESCRIPTOR *Walker; + UINT64 ReservedPages; + UINT64 LoadCodePages; + UINT64 LoadDataPages; + UINT64 BSCodePages; + UINT64 BSDataPages; + UINT64 RTDataPages; + UINT64 RTCodePages; + UINT64 AvailPages; + UINT64 TotalPages; + UINT64 ReservedPagesSize; + UINT64 LoadCodePagesSize; + UINT64 LoadDataPagesSize; + UINT64 BSCodePagesSize; + UINT64 BSDataPagesSize; + UINT64 RTDataPagesSize; + UINT64 RTCodePagesSize; + UINT64 AvailPagesSize; + UINT64 TotalPagesSize; + UINT64 AcpiReclaimPages; + UINT64 AcpiNvsPages; + UINT64 MmioSpacePages; + UINT64 AcpiReclaimPagesSize; + UINT64 AcpiNvsPagesSize; + UINT64 MmioSpacePagesSize; + UINT64 MmioPortPages; + UINT64 MmioPortPagesSize; + UINT64 UnusableMemoryPages; + UINT64 UnusableMemoryPagesSize; + UINT64 PalCodePages; + UINT64 PalCodePagesSize; + UINT64 PersistentPages; + UINT64 PersistentPagesSize; + BOOLEAN Sfo; + LIST_ENTRY MemoryList; + MEMORY_LENGTH_ENTRY *Entry; + LIST_ENTRY *Link; + + AcpiReclaimPages = 0; + AcpiNvsPages = 0; + MmioSpacePages = 0; + TotalPages = 0; + ReservedPages = 0; + LoadCodePages = 0; + LoadDataPages = 0; + BSCodePages = 0; + BSDataPages = 0; + RTDataPages = 0; + RTCodePages = 0; + AvailPages = 0; + MmioPortPages = 0; + UnusableMemoryPages = 0; + PalCodePages = 0; + PersistentPages = 0; + Size = 0; + Descriptors = NULL; + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + InitializeListHead (&MemoryList); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"memmap", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"memmap"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = gBS->GetMemoryMap(&Size, Descriptors, &MapKey, &ItemSize, &Version); + if (Status == EFI_BUFFER_TOO_SMALL){ + Size += SIZE_1KB; + Descriptors = AllocateZeroPool(Size); + Status = gBS->GetMemoryMap(&Size, Descriptors, &MapKey, &ItemSize, &Version); + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_GET_FAILED), gShellDebug1HiiHandle, L"memmap"); + ShellStatus = SHELL_ACCESS_DENIED; + } else { + ASSERT(Version == EFI_MEMORY_DESCRIPTOR_VERSION); + + Sfo = ShellCommandLineGetFlag(Package, L"-sfo"); + if (!Sfo) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_HEAD), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDebug1HiiHandle, L"memmap"); + } + + for ( Walker = Descriptors + ; (Walker < (EFI_MEMORY_DESCRIPTOR *) ((UINT8*)Descriptors + Size)) && (Walker != NULL) + ; Walker = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *)Walker + ItemSize) + ){ + switch (Walker->Type) { + case EfiReservedMemoryType: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiReservedMemoryType, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + ReservedPages += Walker->NumberOfPages; + break; + case EfiLoaderCode: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiLoaderCode, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + LoadCodePages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiLoaderData: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiLoaderData, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + LoadDataPages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiBootServicesCode: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiBootServicesCodeShort:NameEfiBootServicesCode, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + BSCodePages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiBootServicesData: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiBootServicesDataShort:NameEfiBootServicesData, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + BSDataPages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiRuntimeServicesCode: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiRuntimeServicesCodeShort:NameEfiRuntimeServicesCode, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + RTCodePages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiRuntimeServicesData: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiRuntimeServicesDataShort:NameEfiRuntimeServicesData, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + RTDataPages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiConventionalMemory: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiConventionalMemory, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + AvailPages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiPersistentMemory: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiPersistentMemory, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + PersistentPages += Walker->NumberOfPages; + TotalPages += Walker->NumberOfPages; + break; + case EfiUnusableMemory: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiUnusableMemoryShort:NameEfiUnusableMemory, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + UnusableMemoryPages += Walker->NumberOfPages; + break; + case EfiACPIReclaimMemory: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiACPIReclaimMemoryShort:NameEfiACPIReclaimMemory, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + TotalPages += Walker->NumberOfPages; + AcpiReclaimPages += Walker->NumberOfPages; + break; + case EfiACPIMemoryNVS: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiACPIMemoryNVSShort:NameEfiACPIMemoryNVS, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + TotalPages += Walker->NumberOfPages; + AcpiNvsPages += Walker->NumberOfPages; + break; + case EfiMemoryMappedIO: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiMemoryMappedIOShort:NameEfiMemoryMappedIO, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + MmioSpacePages += Walker->NumberOfPages; + break; + case EfiMemoryMappedIOPortSpace: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiMemoryMappedIOPortSpaceShort:NameEfiMemoryMappedIOPortSpace, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + MmioPortPages += Walker->NumberOfPages; + break; + case EfiPalCode: + ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiPalCode, Walker->PhysicalStart, Walker->PhysicalStart+MultU64x64(SIZE_4KB,Walker->NumberOfPages)-1, Walker->NumberOfPages, Walker->Attribute); + TotalPages += Walker->NumberOfPages; + PalCodePages += Walker->NumberOfPages; + break; + default: + // + // Shell Spec defines the SFO format. + // Do not print the OEM/OS memory usage in the SFO format, to avoid conflict with Shell Spec. + // + if (!Sfo) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_ITEM_OTHER), gShellDebug1HiiHandle, Walker->Type, Walker->PhysicalStart, Walker->PhysicalStart + MultU64x64 (SIZE_4KB, Walker->NumberOfPages) - 1, Walker->NumberOfPages, Walker->Attribute); + } + TotalPages += Walker->NumberOfPages; + AddMemoryLength (&MemoryList, Walker->Type, Walker->NumberOfPages); + break; + } + } + // + // print the summary + // + ReservedPagesSize = MultU64x64(SIZE_4KB,ReservedPages); + LoadCodePagesSize = MultU64x64(SIZE_4KB,LoadCodePages); + LoadDataPagesSize = MultU64x64(SIZE_4KB,LoadDataPages); + BSCodePagesSize = MultU64x64(SIZE_4KB,BSCodePages); + BSDataPagesSize = MultU64x64(SIZE_4KB,BSDataPages); + RTDataPagesSize = MultU64x64(SIZE_4KB,RTDataPages); + RTCodePagesSize = MultU64x64(SIZE_4KB,RTCodePages); + AvailPagesSize = MultU64x64(SIZE_4KB,AvailPages); + TotalPagesSize = MultU64x64(SIZE_4KB,TotalPages); + AcpiReclaimPagesSize = MultU64x64(SIZE_4KB,AcpiReclaimPages); + AcpiNvsPagesSize = MultU64x64(SIZE_4KB,AcpiNvsPages); + MmioSpacePagesSize = MultU64x64(SIZE_4KB,MmioSpacePages); + MmioPortPagesSize = MultU64x64(SIZE_4KB,MmioPortPages); + PalCodePagesSize = MultU64x64(SIZE_4KB,PalCodePages); + PersistentPagesSize = MultU64x64(SIZE_4KB,PersistentPages); + UnusableMemoryPagesSize = MultU64x64(SIZE_4KB,UnusableMemoryPages); + if (!Sfo) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM), gShellDebug1HiiHandle, + ReservedPages, ReservedPagesSize, + LoadCodePages, LoadCodePagesSize, + LoadDataPages, LoadDataPagesSize, + BSCodePages, BSCodePagesSize, + BSDataPages, BSDataPagesSize, + RTCodePages, RTCodePagesSize, + RTDataPages, RTDataPagesSize, + AcpiReclaimPages, AcpiReclaimPagesSize, + AcpiNvsPages, AcpiNvsPagesSize, + MmioSpacePages, MmioSpacePagesSize, + MmioPortPages, MmioPortPagesSize, + PalCodePages, PalCodePagesSize, + AvailPages, AvailPagesSize, + PersistentPages, PersistentPagesSize + ); + + // + // Print out the total memory usage for OEM/OS types in the order of type. + // + for (Link = GetFirstNode (&MemoryList); !IsNull (&MemoryList, Link); Link = GetNextNode (&MemoryList, Link)) { + Entry = BASE_CR (Link, MEMORY_LENGTH_ENTRY, Link); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM_OTHER), gShellDebug1HiiHandle, + Entry->Type, Entry->NumberOfPages, MultU64x64 (SIZE_4KB, Entry->NumberOfPages) + ); + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM2), gShellDebug1HiiHandle, + DivU64x32(MultU64x64(SIZE_4KB,TotalPages), SIZE_1MB), TotalPagesSize + ); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM_SFO), gShellDebug1HiiHandle, + TotalPagesSize, + ReservedPagesSize, + BSCodePagesSize, + BSDataPagesSize, + RTCodePagesSize, + RTDataPagesSize, + LoadCodePagesSize, + LoadDataPagesSize, + AvailPagesSize, + MmioSpacePagesSize, + MmioPortPagesSize, + UnusableMemoryPagesSize, + AcpiReclaimPagesSize, + AcpiNvsPagesSize, + PalCodePagesSize, + PersistentPagesSize + ); + } + } + } + ShellCommandLineFreeVarList (Package); + } + + if (Descriptors != NULL) { + FreePool(Descriptors); + } + + // + // Free the memory list. + // + for (Link = GetFirstNode (&MemoryList); !IsNull (&MemoryList, Link); ) { + Link = RemoveEntryList (Link); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c new file mode 100644 index 0000000..b1d5f05 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c @@ -0,0 +1,637 @@ +/** @file + Main file for Mm shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include +#include +#include +#include + +typedef enum { + ShellMmMemory, + ShellMmMemoryMappedIo, + ShellMmIo, + ShellMmPci, + ShellMmPciExpress +} SHELL_MM_ACCESS_TYPE; + +CONST UINT16 mShellMmAccessTypeStr[] = { + STRING_TOKEN (STR_MM_MEM), + STRING_TOKEN (STR_MM_MMIO), + STRING_TOKEN (STR_MM_IO), + STRING_TOKEN (STR_MM_PCI), + STRING_TOKEN (STR_MM_PCIE) +}; + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-mmio", TypeFlag}, + {L"-mem", TypeFlag}, + {L"-io", TypeFlag}, + {L"-pci", TypeFlag}, + {L"-pcie", TypeFlag}, + {L"-n", TypeFlag}, + {L"-w", TypeValue}, + {NULL, TypeMax} + }; + +CONST UINT64 mShellMmMaxNumber[] = { + 0, MAX_UINT8, MAX_UINT16, 0, MAX_UINT32, 0, 0, 0, MAX_UINT64 +}; +CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH mShellMmRootBridgeIoWidth[] = { + 0, EfiPciWidthUint8, EfiPciWidthUint16, 0, EfiPciWidthUint32, 0, 0, 0, EfiPciWidthUint64 +}; +CONST EFI_CPU_IO_PROTOCOL_WIDTH mShellMmCpuIoWidth[] = { + 0, EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, 0, EfiCpuIoWidthUint32, 0, 0, 0, EfiCpuIoWidthUint64 +}; + +/** + Extract the PCI segment, bus, device, function, register from + from a PCI or PCIE format of address.. + + @param[in] PciFormat Whether the address is of PCI format of PCIE format. + @param[in] Address PCI or PCIE address. + @param[out] Segment PCI segment number. + @param[out] Bus PCI bus number. + @param[out] Device PCI device number. + @param[out] Function PCI function number. + @param[out] Register PCI register offset. +**/ +VOID +ShellMmDecodePciAddress ( + IN BOOLEAN PciFormat, + IN UINT64 Address, + OUT UINT32 *Segment, + OUT UINT8 *Bus, + OUT UINT8 *Device, OPTIONAL + OUT UINT8 *Function, OPTIONAL + OUT UINT32 *Register OPTIONAL + ) +{ + if (PciFormat) { + // + // PCI Configuration Space.The address will have the format ssssbbddffrr, + // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rr = Register. + // + *Segment = (UINT32) (RShiftU64 (Address, 32) & 0xFFFF); + *Bus = (UINT8) (((UINT32) Address) >> 24); + + if (Device != NULL) { + *Device = (UINT8) (((UINT32) Address) >> 16); + } + if (Function != NULL) { + *Function = (UINT8) (((UINT32) Address) >> 8); + } + if (Register != NULL) { + *Register = (UINT8) Address; + } + } else { + // + // PCI Express Configuration Space.The address will have the format ssssssbbddffrrr, + // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rrr = Register. + // + *Segment = (UINT32) (RShiftU64 (Address, 36) & 0xFFFF); + *Bus = (UINT8) RShiftU64 (Address, 28); + if (Device != NULL) { + *Device = (UINT8) (((UINT32) Address) >> 20); + } + if (Function != NULL) { + *Function = (UINT8) (((UINT32) Address) >> 12); + } + if (Register != NULL) { + *Register = (UINT32) (Address & 0xFFF); + } + } +} + +/** + Read or write some data from or into the Address. + + @param[in] AccessType Access type. + @param[in] PciRootBridgeIo PciRootBridgeIo instance. + @param[in] CpuIo CpuIo instance. + @param[in] Read TRUE for read, FALSE for write. + @param[in] Addresss The memory location to access. + @param[in] Size The size of Buffer in Width sized units. + @param[in, out] Buffer The buffer to read into or write from. +**/ +VOID +ShellMmAccess ( + IN SHELL_MM_ACCESS_TYPE AccessType, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN EFI_CPU_IO2_PROTOCOL *CpuIo, + IN BOOLEAN Read, + IN UINT64 Address, + IN UINTN Size, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM RootBridgeIoMem; + EFI_CPU_IO_PROTOCOL_IO_MEM CpuIoMem; + UINT32 Segment; + UINT8 Bus; + UINT8 Device; + UINT8 Function; + UINT32 Register; + + if (AccessType == ShellMmMemory) { + if (Read) { + CopyMem (Buffer, (VOID *) (UINTN) Address, Size); + } else { + CopyMem ((VOID *) (UINTN) Address, Buffer, Size); + } + } else { + RootBridgeIoMem = NULL; + CpuIoMem = NULL; + switch (AccessType) { + case ShellMmPci: + case ShellMmPciExpress: + ASSERT (PciRootBridgeIo != NULL); + ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, &Device, &Function, &Register); + if (Read) { + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], + EFI_PCI_ADDRESS (Bus, Device, Function, Register), + 1, Buffer + ); + } else { + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], + EFI_PCI_ADDRESS (Bus, Device, Function, Register), + 1, Buffer + ); + } + ASSERT_EFI_ERROR (Status); + return; + + case ShellMmMemoryMappedIo: + if (PciRootBridgeIo != NULL) { + RootBridgeIoMem = Read ? PciRootBridgeIo->Mem.Read : PciRootBridgeIo->Mem.Write; + } + if (CpuIo != NULL) { + CpuIoMem = Read ? CpuIo->Mem.Read : CpuIo->Mem.Write; + } + break; + + case ShellMmIo: + if (PciRootBridgeIo != NULL) { + RootBridgeIoMem = Read ? PciRootBridgeIo->Io.Read : PciRootBridgeIo->Io.Write; + } + if (CpuIo != NULL) { + CpuIoMem = Read ? CpuIo->Io.Read : CpuIo->Io.Write; + } + break; + default: + ASSERT (FALSE); + break; + } + + Status = EFI_UNSUPPORTED; + if (RootBridgeIoMem != NULL) { + Status = RootBridgeIoMem (PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], Address, 1, Buffer); + } + if (EFI_ERROR (Status) && (CpuIoMem != NULL)) { + Status = CpuIoMem (CpuIo, mShellMmCpuIoWidth[Size], Address, 1, Buffer); + } + + if (EFI_ERROR (Status)) { + if (AccessType == ShellMmIo) { + switch (Size) { + case 1: + if (Read) { + *(UINT8 *) Buffer = IoRead8 ((UINTN) Address); + } else { + IoWrite8 ((UINTN) Address, *(UINT8 *) Buffer); + } + break; + case 2: + if (Read) { + *(UINT16 *) Buffer = IoRead16 ((UINTN) Address); + } else { + IoWrite16 ((UINTN) Address, *(UINT16 *) Buffer); + } + break; + case 4: + if (Read) { + *(UINT32 *) Buffer = IoRead32 ((UINTN) Address); + } else { + IoWrite32 ((UINTN) Address, *(UINT32 *) Buffer); + } + break; + case 8: + if (Read) { + *(UINT64 *) Buffer = IoRead64 ((UINTN) Address); + } else { + IoWrite64 ((UINTN) Address, *(UINT64 *) Buffer); + } + break; + default: + ASSERT (FALSE); + break; + } + } else { + switch (Size) { + case 1: + if (Read) { + *(UINT8 *) Buffer = MmioRead8 ((UINTN) Address); + } else { + MmioWrite8 ((UINTN) Address, *(UINT8 *) Buffer); + } + break; + case 2: + if (Read) { + *(UINT16 *) Buffer = MmioRead16 ((UINTN) Address); + } else { + MmioWrite16 ((UINTN) Address, *(UINT16 *) Buffer); + } + break; + case 4: + if (Read) { + *(UINT32 *) Buffer = MmioRead32 ((UINTN) Address); + } else { + MmioWrite32 ((UINTN) Address, *(UINT32 *) Buffer); + } + break; + case 8: + if (Read) { + *(UINT64 *) Buffer = MmioRead64 ((UINTN) Address); + } else { + MmioWrite64 ((UINTN) Address, *(UINT64 *) Buffer); + } + break; + default: + ASSERT (FALSE); + break; + } + } + } + } +} + +/** + Find the CpuIo instance and PciRootBridgeIo instance in the platform. + If there are multiple PciRootBridgeIo instances, the instance which manages + the Address is returned. + + @param[in] AccessType Access type. + @param[in] Address Address to access. + @param[out] CpuIo Return the CpuIo instance. + @param[out] PciRootBridgeIo Return the proper PciRootBridgeIo instance. + + @retval TRUE There are PciRootBridgeIo instances in the platform. + @retval FALSE There isn't PciRootBridgeIo instance in the platform. +**/ +BOOLEAN +ShellMmLocateIoProtocol ( + IN SHELL_MM_ACCESS_TYPE AccessType, + IN UINT64 Address, + OUT EFI_CPU_IO2_PROTOCOL **CpuIo, + OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **PciRootBridgeIo + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Io; + UINT32 Segment; + UINT8 Bus; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) CpuIo); + if (EFI_ERROR (Status)) { + *CpuIo = NULL; + } + + *PciRootBridgeIo = NULL; + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) { + return FALSE; + } + + Segment = 0; + Bus = 0; + if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) { + ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, NULL, NULL, NULL); + } + + // + // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number + // + for (Index = 0; (Index < HandleCount) && (*PciRootBridgeIo == NULL); Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciRootBridgeIoProtocolGuid, + (VOID *) &Io + ); + if (EFI_ERROR (Status)) { + continue; + } + + if ((((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && (Io->SegmentNumber == Segment)) || + ((AccessType == ShellMmIo) || (AccessType == ShellMmMemoryMappedIo)) + ) { + Status = Io->Configuration (Io, (VOID **) &Descriptors); + if (!EFI_ERROR (Status)) { + while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) { + // + // Compare the segment and bus range for PCI/PCIE access + // + if ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) && + ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && + ((Bus >= Descriptors->AddrRangeMin) && (Bus <= Descriptors->AddrRangeMax)) + ) { + *PciRootBridgeIo = Io; + break; + + // + // Compare the address range for MMIO/IO access + // + } else if ((((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) && (AccessType == ShellMmIo)) || + ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && (AccessType == ShellMmMemoryMappedIo)) + ) && ((Address >= Descriptors->AddrRangeMin) && (Address <= Descriptors->AddrRangeMax)) + ) { + *PciRootBridgeIo = Io; + break; + } + Descriptors++; + } + } + } + } + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return TRUE; +} + +/** + Function for 'mm' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_CPU_IO2_PROTOCOL *CpuIo; + UINT64 Address; + UINT64 Value; + SHELL_MM_ACCESS_TYPE AccessType; + UINT64 Buffer; + UINTN Index; + UINTN Size; + BOOLEAN Complete; + CHAR16 *InputStr; + BOOLEAN Interactive; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Temp; + BOOLEAN HasPciRootBridgeIo; + + Value = 0; + Address = 0; + ShellStatus = SHELL_SUCCESS; + InputStr = NULL; + Size = 1; + AccessType = ShellMmMemory; + + // + // Parse arguments + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam); + FreePool (ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } else { + ASSERT (FALSE); + } + } else { + if (ShellCommandLineGetCount (Package) < 2) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } else if (ShellCommandLineGetCount (Package) > 3) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } else if (ShellCommandLineGetFlag (Package, L"-w") && ShellCommandLineGetValue (Package, L"-w") == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } else { + if (ShellCommandLineGetFlag (Package, L"-mmio")) { + AccessType = ShellMmMemoryMappedIo; + if (ShellCommandLineGetFlag (Package, L"-mem") + || ShellCommandLineGetFlag (Package, L"-io") + || ShellCommandLineGetFlag (Package, L"-pci") + || ShellCommandLineGetFlag (Package, L"-pcie") + ) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } else if (ShellCommandLineGetFlag (Package, L"-mem")) { + AccessType = ShellMmMemory; + if (ShellCommandLineGetFlag (Package, L"-io") + || ShellCommandLineGetFlag (Package, L"-pci") + || ShellCommandLineGetFlag (Package, L"-pcie") + ) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } else if (ShellCommandLineGetFlag (Package, L"-io")) { + AccessType = ShellMmIo; + if (ShellCommandLineGetFlag (Package, L"-pci") + || ShellCommandLineGetFlag (Package, L"-pcie") + ) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } else if (ShellCommandLineGetFlag (Package, L"-pci")) { + AccessType = ShellMmPci; + if (ShellCommandLineGetFlag (Package, L"-pcie") + ) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } else if (ShellCommandLineGetFlag (Package, L"-pcie")) { + AccessType = ShellMmPciExpress; + } + } + + // + // Non interactive for a script file or for the specific parameter + // + Interactive = TRUE; + if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) { + Interactive = FALSE; + } + + Temp = ShellCommandLineGetValue (Package, L"-w"); + if (Temp != NULL) { + Size = ShellStrToUintn (Temp); + } + if ((Size != 1) && (Size != 2) && (Size != 4) && (Size != 8)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + Temp = ShellCommandLineGetRawValue (Package, 1); + Status = ShellConvertStringToUint64 (Temp, &Address, TRUE, FALSE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + if ((Address & (Size - 1)) != 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + // + // locate IO protocol interface + // + HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo); + if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) { + if (!HasPciRootBridgeIo) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm"); + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + if (PciRootBridgeIo == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + + // + // Mode 1: Directly set a value + // + Temp = ShellCommandLineGetRawValue (Package, 2); + if (Temp != NULL) { + Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + if (Value > mShellMmMaxNumber[Size]) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value); + goto Done; + } + + // + // Mode 2: Directly show a value + // + if (!Interactive) { + if (!gEfiShellProtocol->BatchIsActive ()) { + ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle); + } + ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer); + + if (!gEfiShellProtocol->BatchIsActive ()) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]); + ShellPrintEx (-1, -1, L"\r\n"); + goto Done; + } + + // + // Mode 3: Show or set values in interactive mode + // + Complete = FALSE; + do { + ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer); + ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]); + ShellPrintEx (-1, -1, L" > "); + // + // wait user input to modify + // + if (InputStr != NULL) { + FreePool (InputStr); + InputStr = NULL; + } + ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr); + + if (InputStr != NULL) { + // + // skip space characters + // + for (Index = 0; InputStr[Index] == ' '; Index++); + + if (InputStr[Index] != CHAR_NULL) { + if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) { + Complete = TRUE; + } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) && + (Buffer <= mShellMmMaxNumber[Size]) + ) { + ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm"); + continue; + } + } + } + + Address += Size; + ShellPrintEx (-1, -1, L"\r\n"); + } while (!Complete); + } + ASSERT (ShellStatus == SHELL_SUCCESS); + +Done: + if (InputStr != NULL) { + FreePool (InputStr); + } + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c new file mode 100644 index 0000000..03bc0fd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c @@ -0,0 +1,128 @@ +/** @file + Main file for Mode shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which acModeanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" + +/** + Function for 'mode' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN NewCol; + UINTN NewRow; + UINTN Col; + UINTN Row; + CONST CHAR16 *Temp; + BOOLEAN Done; + INT32 LoopVar; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mode", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mode"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mode"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) == 3) { + Temp = ShellCommandLineGetRawValue(Package, 1); + if (!ShellIsHexOrDecimalNumber(Temp, FALSE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mode", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + } + NewCol = ShellStrToUintn(Temp); + Temp = ShellCommandLineGetRawValue(Package, 2); + if (!ShellIsHexOrDecimalNumber(Temp, FALSE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mode", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + } + NewRow = ShellStrToUintn(Temp); + + for (LoopVar = 0, Done = FALSE; LoopVar < gST->ConOut->Mode->MaxMode && ShellStatus == SHELL_SUCCESS ; LoopVar++) { + Status = gST->ConOut->QueryMode(gST->ConOut, LoopVar, &Col, &Row); + if (EFI_ERROR(Status)) { + continue; + } + if (Col == NewCol && Row == NewRow) { + Status = gST->ConOut->SetMode(gST->ConOut, LoopVar); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_SET_FAIL), gShellDebug1HiiHandle, L"mode"); + ShellStatus = SHELL_DEVICE_ERROR; + } else { + // worked fine... + Done = TRUE; + } + break; + } + } + + if (!Done) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_NO_MATCH), gShellDebug1HiiHandle, L"mode"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + } else if (ShellCommandLineGetCount(Package) == 1) { + // + // print out valid + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_LIST_HEAD), gShellDebug1HiiHandle); + for (LoopVar = 0, Done = FALSE; LoopVar < gST->ConOut->Mode->MaxMode && ShellStatus == SHELL_SUCCESS ; LoopVar++) { + Status = gST->ConOut->QueryMode(gST->ConOut, LoopVar, &Col, &Row); + if (EFI_ERROR(Status)) { + continue; + } + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_LIST_ITEM), gShellDebug1HiiHandle, Col, Row, LoopVar == gST->ConOut->Mode->Mode?L'*':L' '); + } + } + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c new file mode 100644 index 0000000..a553943 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c @@ -0,0 +1,5803 @@ +/** @file + Main file for Pci shell Debug1 function. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include +#include +#include +#include +#include "Pci.h" + +// +// Printable strings for Pci class code +// +typedef struct { + CHAR16 *BaseClass; // Pointer to the PCI base class string + CHAR16 *SubClass; // Pointer to the PCI sub class string + CHAR16 *PIFClass; // Pointer to the PCI programming interface string +} PCI_CLASS_STRINGS; + +// +// a structure holding a single entry, which also points to its lower level +// class +// +typedef struct PCI_CLASS_ENTRY_TAG { + UINT8 Code; // Class, subclass or I/F code + CHAR16 *DescText; // Description string + struct PCI_CLASS_ENTRY_TAG *LowerLevelClass; // Subclass or I/F if any +} PCI_CLASS_ENTRY; + +// +// Declarations of entries which contain printable strings for class codes +// in PCI configuration space +// +PCI_CLASS_ENTRY PCIBlankEntry[]; +PCI_CLASS_ENTRY PCISubClass_00[]; +PCI_CLASS_ENTRY PCISubClass_01[]; +PCI_CLASS_ENTRY PCISubClass_02[]; +PCI_CLASS_ENTRY PCISubClass_03[]; +PCI_CLASS_ENTRY PCISubClass_04[]; +PCI_CLASS_ENTRY PCISubClass_05[]; +PCI_CLASS_ENTRY PCISubClass_06[]; +PCI_CLASS_ENTRY PCISubClass_07[]; +PCI_CLASS_ENTRY PCISubClass_08[]; +PCI_CLASS_ENTRY PCISubClass_09[]; +PCI_CLASS_ENTRY PCISubClass_0a[]; +PCI_CLASS_ENTRY PCISubClass_0b[]; +PCI_CLASS_ENTRY PCISubClass_0c[]; +PCI_CLASS_ENTRY PCISubClass_0d[]; +PCI_CLASS_ENTRY PCISubClass_0e[]; +PCI_CLASS_ENTRY PCISubClass_0f[]; +PCI_CLASS_ENTRY PCISubClass_10[]; +PCI_CLASS_ENTRY PCISubClass_11[]; +PCI_CLASS_ENTRY PCISubClass_12[]; +PCI_CLASS_ENTRY PCISubClass_13[]; +PCI_CLASS_ENTRY PCIPIFClass_0100[]; +PCI_CLASS_ENTRY PCIPIFClass_0101[]; +PCI_CLASS_ENTRY PCIPIFClass_0105[]; +PCI_CLASS_ENTRY PCIPIFClass_0106[]; +PCI_CLASS_ENTRY PCIPIFClass_0107[]; +PCI_CLASS_ENTRY PCIPIFClass_0108[]; +PCI_CLASS_ENTRY PCIPIFClass_0109[]; +PCI_CLASS_ENTRY PCIPIFClass_0300[]; +PCI_CLASS_ENTRY PCIPIFClass_0604[]; +PCI_CLASS_ENTRY PCIPIFClass_0609[]; +PCI_CLASS_ENTRY PCIPIFClass_060b[]; +PCI_CLASS_ENTRY PCIPIFClass_0700[]; +PCI_CLASS_ENTRY PCIPIFClass_0701[]; +PCI_CLASS_ENTRY PCIPIFClass_0703[]; +PCI_CLASS_ENTRY PCIPIFClass_0800[]; +PCI_CLASS_ENTRY PCIPIFClass_0801[]; +PCI_CLASS_ENTRY PCIPIFClass_0802[]; +PCI_CLASS_ENTRY PCIPIFClass_0803[]; +PCI_CLASS_ENTRY PCIPIFClass_0904[]; +PCI_CLASS_ENTRY PCIPIFClass_0c00[]; +PCI_CLASS_ENTRY PCIPIFClass_0c03[]; +PCI_CLASS_ENTRY PCIPIFClass_0c07[]; +PCI_CLASS_ENTRY PCIPIFClass_0d01[]; +PCI_CLASS_ENTRY PCIPIFClass_0e00[]; + +// +// Base class strings entries +// +PCI_CLASS_ENTRY gClassStringList[] = { + { + 0x00, + L"Pre 2.0 device", + PCISubClass_00 + }, + { + 0x01, + L"Mass Storage Controller", + PCISubClass_01 + }, + { + 0x02, + L"Network Controller", + PCISubClass_02 + }, + { + 0x03, + L"Display Controller", + PCISubClass_03 + }, + { + 0x04, + L"Multimedia Device", + PCISubClass_04 + }, + { + 0x05, + L"Memory Controller", + PCISubClass_05 + }, + { + 0x06, + L"Bridge Device", + PCISubClass_06 + }, + { + 0x07, + L"Simple Communications Controllers", + PCISubClass_07 + }, + { + 0x08, + L"Base System Peripherals", + PCISubClass_08 + }, + { + 0x09, + L"Input Devices", + PCISubClass_09 + }, + { + 0x0a, + L"Docking Stations", + PCISubClass_0a + }, + { + 0x0b, + L"Processors", + PCISubClass_0b + }, + { + 0x0c, + L"Serial Bus Controllers", + PCISubClass_0c + }, + { + 0x0d, + L"Wireless Controllers", + PCISubClass_0d + }, + { + 0x0e, + L"Intelligent IO Controllers", + PCISubClass_0e + }, + { + 0x0f, + L"Satellite Communications Controllers", + PCISubClass_0f + }, + { + 0x10, + L"Encryption/Decryption Controllers", + PCISubClass_10 + }, + { + 0x11, + L"Data Acquisition & Signal Processing Controllers", + PCISubClass_11 + }, + { + 0x12, + L"Processing Accelerators", + PCISubClass_12 + }, + { + 0x13, + L"Non-Essential Instrumentation", + PCISubClass_13 + }, + { + 0xff, + L"Device does not fit in any defined classes", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +// +// Subclass strings entries +// +PCI_CLASS_ENTRY PCIBlankEntry[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_00[] = { + { + 0x00, + L"All devices other than VGA", + PCIBlankEntry + }, + { + 0x01, + L"VGA-compatible devices", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_01[] = { + { + 0x00, + L"SCSI", + PCIPIFClass_0100 + }, + { + 0x01, + L"IDE controller", + PCIPIFClass_0101 + }, + { + 0x02, + L"Floppy disk controller", + PCIBlankEntry + }, + { + 0x03, + L"IPI controller", + PCIBlankEntry + }, + { + 0x04, + L"RAID controller", + PCIBlankEntry + }, + { + 0x05, + L"ATA controller with ADMA interface", + PCIPIFClass_0105 + }, + { + 0x06, + L"Serial ATA controller", + PCIPIFClass_0106 + }, + { + 0x07, + L"Serial Attached SCSI (SAS) controller ", + PCIPIFClass_0107 + }, + { + 0x08, + L"Non-volatile memory subsystem", + PCIPIFClass_0108 + }, + { + 0x09, + L"Universal Flash Storage (UFS) controller ", + PCIPIFClass_0109 + }, + { + 0x80, + L"Other mass storage controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_02[] = { + { + 0x00, + L"Ethernet controller", + PCIBlankEntry + }, + { + 0x01, + L"Token ring controller", + PCIBlankEntry + }, + { + 0x02, + L"FDDI controller", + PCIBlankEntry + }, + { + 0x03, + L"ATM controller", + PCIBlankEntry + }, + { + 0x04, + L"ISDN controller", + PCIBlankEntry + }, + { + 0x05, + L"WorldFip controller", + PCIBlankEntry + }, + { + 0x06, + L"PICMG 2.14 Multi Computing", + PCIBlankEntry + }, + { + 0x07, + L"InfiniBand controller", + PCIBlankEntry + }, + { + 0x80, + L"Other network controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_03[] = { + { + 0x00, + L"VGA/8514 controller", + PCIPIFClass_0300 + }, + { + 0x01, + L"XGA controller", + PCIBlankEntry + }, + { + 0x02, + L"3D controller", + PCIBlankEntry + }, + { + 0x80, + L"Other display controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */PCIBlankEntry + } +}; + +PCI_CLASS_ENTRY PCISubClass_04[] = { + { + 0x00, + L"Video device", + PCIBlankEntry + }, + { + 0x01, + L"Audio device", + PCIBlankEntry + }, + { + 0x02, + L"Computer Telephony device", + PCIBlankEntry + }, + { + 0x03, + L"Mixed mode device", + PCIBlankEntry + }, + { + 0x80, + L"Other multimedia device", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_05[] = { + { + 0x00, + L"RAM memory controller", + PCIBlankEntry + }, + { + 0x01, + L"Flash memory controller", + PCIBlankEntry + }, + { + 0x80, + L"Other memory controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_06[] = { + { + 0x00, + L"Host/PCI bridge", + PCIBlankEntry + }, + { + 0x01, + L"PCI/ISA bridge", + PCIBlankEntry + }, + { + 0x02, + L"PCI/EISA bridge", + PCIBlankEntry + }, + { + 0x03, + L"PCI/Micro Channel bridge", + PCIBlankEntry + }, + { + 0x04, + L"PCI/PCI bridge", + PCIPIFClass_0604 + }, + { + 0x05, + L"PCI/PCMCIA bridge", + PCIBlankEntry + }, + { + 0x06, + L"NuBus bridge", + PCIBlankEntry + }, + { + 0x07, + L"CardBus bridge", + PCIBlankEntry + }, + { + 0x08, + L"RACEway bridge", + PCIBlankEntry + }, + { + 0x09, + L"Semi-transparent PCI-to-PCI bridge", + PCIPIFClass_0609 + }, + { + 0x0A, + L"InfiniBand-to-PCI host bridge", + PCIBlankEntry + }, + { + 0x0B, + L"Advanced Switching to PCI host bridge", + PCIPIFClass_060b + }, + { + 0x80, + L"Other bridge type", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_07[] = { + { + 0x00, + L"Serial controller", + PCIPIFClass_0700 + }, + { + 0x01, + L"Parallel port", + PCIPIFClass_0701 + }, + { + 0x02, + L"Multiport serial controller", + PCIBlankEntry + }, + { + 0x03, + L"Modem", + PCIPIFClass_0703 + }, + { + 0x04, + L"GPIB (IEEE 488.1/2) controller", + PCIBlankEntry + }, + { + 0x05, + L"Smart Card", + PCIBlankEntry + }, + { + 0x80, + L"Other communication device", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_08[] = { + { + 0x00, + L"PIC", + PCIPIFClass_0800 + }, + { + 0x01, + L"DMA controller", + PCIPIFClass_0801 + }, + { + 0x02, + L"System timer", + PCIPIFClass_0802 + }, + { + 0x03, + L"RTC controller", + PCIPIFClass_0803 + }, + { + 0x04, + L"Generic PCI Hot-Plug controller", + PCIBlankEntry + }, + { + 0x05, + L"SD Host controller", + PCIBlankEntry + }, + { + 0x06, + L"IOMMU", + PCIBlankEntry + }, + { + 0x07, + L"Root Complex Event Collector", + PCIBlankEntry + }, + { + 0x80, + L"Other system peripheral", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_09[] = { + { + 0x00, + L"Keyboard controller", + PCIBlankEntry + }, + { + 0x01, + L"Digitizer (pen)", + PCIBlankEntry + }, + { + 0x02, + L"Mouse controller", + PCIBlankEntry + }, + { + 0x03, + L"Scanner controller", + PCIBlankEntry + }, + { + 0x04, + L"Gameport controller", + PCIPIFClass_0904 + }, + { + 0x80, + L"Other input controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_0a[] = { + { + 0x00, + L"Generic docking station", + PCIBlankEntry + }, + { + 0x80, + L"Other type of docking station", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_0b[] = { + { + 0x00, + L"386", + PCIBlankEntry + }, + { + 0x01, + L"486", + PCIBlankEntry + }, + { + 0x02, + L"Pentium", + PCIBlankEntry + }, + { + 0x10, + L"Alpha", + PCIBlankEntry + }, + { + 0x20, + L"PowerPC", + PCIBlankEntry + }, + { + 0x30, + L"MIPS", + PCIBlankEntry + }, + { + 0x40, + L"Co-processor", + PCIBlankEntry + }, + { + 0x80, + L"Other processor", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_0c[] = { + { + 0x00, + L"IEEE 1394", + PCIPIFClass_0c00 + }, + { + 0x01, + L"ACCESS.bus", + PCIBlankEntry + }, + { + 0x02, + L"SSA", + PCIBlankEntry + }, + { + 0x03, + L"USB", + PCIPIFClass_0c03 + }, + { + 0x04, + L"Fibre Channel", + PCIBlankEntry + }, + { + 0x05, + L"System Management Bus", + PCIBlankEntry + }, + { + 0x06, + L"InfiniBand", + PCIBlankEntry + }, + { + 0x07, + L"IPMI", + PCIPIFClass_0c07 + }, + { + 0x08, + L"SERCOS Interface Standard (IEC 61491)", + PCIBlankEntry + }, + { + 0x09, + L"CANbus", + PCIBlankEntry + }, + { + 0x80, + L"Other bus type", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_0d[] = { + { + 0x00, + L"iRDA compatible controller", + PCIBlankEntry + }, + { + 0x01, + L"", + PCIPIFClass_0d01 + }, + { + 0x10, + L"RF controller", + PCIBlankEntry + }, + { + 0x11, + L"Bluetooth", + PCIBlankEntry + }, + { + 0x12, + L"Broadband", + PCIBlankEntry + }, + { + 0x20, + L"Ethernet (802.11a - 5 GHz)", + PCIBlankEntry + }, + { + 0x21, + L"Ethernet (802.11b - 2.4 GHz)", + PCIBlankEntry + }, + { + 0x80, + L"Other type of wireless controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_0e[] = { + { + 0x00, + L"I2O Architecture", + PCIPIFClass_0e00 + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_0f[] = { + { + 0x01, + L"TV", + PCIBlankEntry + }, + { + 0x02, + L"Audio", + PCIBlankEntry + }, + { + 0x03, + L"Voice", + PCIBlankEntry + }, + { + 0x04, + L"Data", + PCIBlankEntry + }, + { + 0x80, + L"Other satellite communication controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_10[] = { + { + 0x00, + L"Network & computing Encrypt/Decrypt", + PCIBlankEntry + }, + { + 0x01, + L"Entertainment Encrypt/Decrypt", + PCIBlankEntry + }, + { + 0x80, + L"Other Encrypt/Decrypt", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_11[] = { + { + 0x00, + L"DPIO modules", + PCIBlankEntry + }, + { + 0x01, + L"Performance Counters", + PCIBlankEntry + }, + { + 0x10, + L"Communications synchronization plus time and frequency test/measurement ", + PCIBlankEntry + }, + { + 0x20, + L"Management card", + PCIBlankEntry + }, + { + 0x80, + L"Other DAQ & SP controllers", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_12[] = { + { + 0x00, + L"Processing Accelerator", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCISubClass_13[] = { + { + 0x00, + L"Non-Essential Instrumentation Function", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +// +// Programming Interface entries +// +PCI_CLASS_ENTRY PCIPIFClass_0100[] = { + { + 0x00, + L"SCSI controller", + PCIBlankEntry + }, + { + 0x11, + L"SCSI storage device SOP using PQI", + PCIBlankEntry + }, + { + 0x12, + L"SCSI controller SOP using PQI", + PCIBlankEntry + }, + { + 0x13, + L"SCSI storage device and controller SOP using PQI", + PCIBlankEntry + }, + { + 0x21, + L"SCSI storage device SOP using NVMe", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0101[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"OM-primary", + PCIBlankEntry + }, + { + 0x02, + L"PI-primary", + PCIBlankEntry + }, + { + 0x03, + L"OM/PI-primary", + PCIBlankEntry + }, + { + 0x04, + L"OM-secondary", + PCIBlankEntry + }, + { + 0x05, + L"OM-primary, OM-secondary", + PCIBlankEntry + }, + { + 0x06, + L"PI-primary, OM-secondary", + PCIBlankEntry + }, + { + 0x07, + L"OM/PI-primary, OM-secondary", + PCIBlankEntry + }, + { + 0x08, + L"OM-secondary", + PCIBlankEntry + }, + { + 0x09, + L"OM-primary, PI-secondary", + PCIBlankEntry + }, + { + 0x0a, + L"PI-primary, PI-secondary", + PCIBlankEntry + }, + { + 0x0b, + L"OM/PI-primary, PI-secondary", + PCIBlankEntry + }, + { + 0x0c, + L"OM-secondary", + PCIBlankEntry + }, + { + 0x0d, + L"OM-primary, OM/PI-secondary", + PCIBlankEntry + }, + { + 0x0e, + L"PI-primary, OM/PI-secondary", + PCIBlankEntry + }, + { + 0x0f, + L"OM/PI-primary, OM/PI-secondary", + PCIBlankEntry + }, + { + 0x80, + L"Master", + PCIBlankEntry + }, + { + 0x81, + L"Master, OM-primary", + PCIBlankEntry + }, + { + 0x82, + L"Master, PI-primary", + PCIBlankEntry + }, + { + 0x83, + L"Master, OM/PI-primary", + PCIBlankEntry + }, + { + 0x84, + L"Master, OM-secondary", + PCIBlankEntry + }, + { + 0x85, + L"Master, OM-primary, OM-secondary", + PCIBlankEntry + }, + { + 0x86, + L"Master, PI-primary, OM-secondary", + PCIBlankEntry + }, + { + 0x87, + L"Master, OM/PI-primary, OM-secondary", + PCIBlankEntry + }, + { + 0x88, + L"Master, OM-secondary", + PCIBlankEntry + }, + { + 0x89, + L"Master, OM-primary, PI-secondary", + PCIBlankEntry + }, + { + 0x8a, + L"Master, PI-primary, PI-secondary", + PCIBlankEntry + }, + { + 0x8b, + L"Master, OM/PI-primary, PI-secondary", + PCIBlankEntry + }, + { + 0x8c, + L"Master, OM-secondary", + PCIBlankEntry + }, + { + 0x8d, + L"Master, OM-primary, OM/PI-secondary", + PCIBlankEntry + }, + { + 0x8e, + L"Master, PI-primary, OM/PI-secondary", + PCIBlankEntry + }, + { + 0x8f, + L"Master, OM/PI-primary, OM/PI-secondary", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0105[] = { + { + 0x20, + L"Single stepping", + PCIBlankEntry + }, + { + 0x30, + L"Continuous operation", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0106[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"AHCI", + PCIBlankEntry + }, + { + 0x02, + L"Serial Storage Bus", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0107[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"Obsolete", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0108[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"NVMHCI", + PCIBlankEntry + }, + { + 0x02, + L"NVM Express", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0109[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"UFSHCI", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0300[] = { + { + 0x00, + L"VGA compatible", + PCIBlankEntry + }, + { + 0x01, + L"8514 compatible", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0604[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"Subtractive decode", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0609[] = { + { + 0x40, + L"Primary PCI bus side facing the system host processor", + PCIBlankEntry + }, + { + 0x80, + L"Secondary PCI bus side facing the system host processor", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_060b[] = { + { + 0x00, + L"Custom", + PCIBlankEntry + }, + { + 0x01, + L"ASI-SIG Defined Portal", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0700[] = { + { + 0x00, + L"Generic XT-compatible", + PCIBlankEntry + }, + { + 0x01, + L"16450-compatible", + PCIBlankEntry + }, + { + 0x02, + L"16550-compatible", + PCIBlankEntry + }, + { + 0x03, + L"16650-compatible", + PCIBlankEntry + }, + { + 0x04, + L"16750-compatible", + PCIBlankEntry + }, + { + 0x05, + L"16850-compatible", + PCIBlankEntry + }, + { + 0x06, + L"16950-compatible", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0701[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x01, + L"Bi-directional", + PCIBlankEntry + }, + { + 0x02, + L"ECP 1.X-compliant", + PCIBlankEntry + }, + { + 0x03, + L"IEEE 1284", + PCIBlankEntry + }, + { + 0xfe, + L"IEEE 1284 target (not a controller)", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0703[] = { + { + 0x00, + L"Generic", + PCIBlankEntry + }, + { + 0x01, + L"Hayes-compatible 16450", + PCIBlankEntry + }, + { + 0x02, + L"Hayes-compatible 16550", + PCIBlankEntry + }, + { + 0x03, + L"Hayes-compatible 16650", + PCIBlankEntry + }, + { + 0x04, + L"Hayes-compatible 16750", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0800[] = { + { + 0x00, + L"Generic 8259", + PCIBlankEntry + }, + { + 0x01, + L"ISA", + PCIBlankEntry + }, + { + 0x02, + L"EISA", + PCIBlankEntry + }, + { + 0x10, + L"IO APIC", + PCIBlankEntry + }, + { + 0x20, + L"IO(x) APIC interrupt controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0801[] = { + { + 0x00, + L"Generic 8237", + PCIBlankEntry + }, + { + 0x01, + L"ISA", + PCIBlankEntry + }, + { + 0x02, + L"EISA", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0802[] = { + { + 0x00, + L"Generic 8254", + PCIBlankEntry + }, + { + 0x01, + L"ISA", + PCIBlankEntry + }, + { + 0x02, + L"EISA", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0803[] = { + { + 0x00, + L"Generic", + PCIBlankEntry + }, + { + 0x01, + L"ISA", + PCIBlankEntry + }, + { + 0x02, + L"EISA", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0904[] = { + { + 0x00, + L"Generic", + PCIBlankEntry + }, + { + 0x10, + L"", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0c00[] = { + { + 0x00, + L"", + PCIBlankEntry + }, + { + 0x10, + L"Using 1394 OpenHCI spec", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0c03[] = { + { + 0x00, + L"UHCI", + PCIBlankEntry + }, + { + 0x10, + L"OHCI", + PCIBlankEntry + }, + { + 0x20, + L"EHCI", + PCIBlankEntry + }, + { + 0x30, + L"xHCI", + PCIBlankEntry + }, + { + 0x80, + L"No specific programming interface", + PCIBlankEntry + }, + { + 0xfe, + L"(Not Host Controller)", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0c07[] = { + { + 0x00, + L"SMIC", + PCIBlankEntry + }, + { + 0x01, + L"Keyboard Controller Style", + PCIBlankEntry + }, + { + 0x02, + L"Block Transfer", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0d01[] = { + { + 0x00, + L"Consumer IR controller", + PCIBlankEntry + }, + { + 0x10, + L"UWB Radio controller", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + +PCI_CLASS_ENTRY PCIPIFClass_0e00[] = { + { + 0x00, + L"Message FIFO at offset 40h", + PCIBlankEntry + }, + { + 0x01, + L"", + PCIBlankEntry + }, + { + 0x00, + NULL, + /* null string ends the list */NULL + } +}; + + +/** + Generates printable Unicode strings that represent PCI device class, + subclass and programmed I/F based on a value passed to the function. + + @param[in] ClassCode Value representing the PCI "Class Code" register read from a + PCI device. The encodings are: + bits 23:16 - Base Class Code + bits 15:8 - Sub-Class Code + bits 7:0 - Programming Interface + @param[in, out] ClassStrings Pointer of PCI_CLASS_STRINGS structure, which contains + printable class strings corresponding to ClassCode. The + caller must not modify the strings that are pointed by + the fields in ClassStrings. +**/ +VOID +PciGetClassStrings ( + IN UINT32 ClassCode, + IN OUT PCI_CLASS_STRINGS *ClassStrings + ) +{ + INTN Index; + UINT8 Code; + PCI_CLASS_ENTRY *CurrentClass; + + // + // Assume no strings found + // + ClassStrings->BaseClass = L"UNDEFINED"; + ClassStrings->SubClass = L"UNDEFINED"; + ClassStrings->PIFClass = L"UNDEFINED"; + + CurrentClass = gClassStringList; + Code = (UINT8) (ClassCode >> 16); + Index = 0; + + // + // Go through all entries of the base class, until the entry with a matching + // base class code is found. If reaches an entry with a null description + // text, the last entry is met, which means no text for the base class was + // found, so no more action is needed. + // + while (Code != CurrentClass[Index].Code) { + if (NULL == CurrentClass[Index].DescText) { + return ; + } + + Index++; + } + // + // A base class was found. Assign description, and check if this class has + // sub-class defined. If sub-class defined, no more action is needed, + // otherwise, continue to find description for the sub-class code. + // + ClassStrings->BaseClass = CurrentClass[Index].DescText; + if (NULL == CurrentClass[Index].LowerLevelClass) { + return ; + } + // + // find Subclass entry + // + CurrentClass = CurrentClass[Index].LowerLevelClass; + Code = (UINT8) (ClassCode >> 8); + Index = 0; + + // + // Go through all entries of the sub-class, until the entry with a matching + // sub-class code is found. If reaches an entry with a null description + // text, the last entry is met, which means no text for the sub-class was + // found, so no more action is needed. + // + while (Code != CurrentClass[Index].Code) { + if (NULL == CurrentClass[Index].DescText) { + return ; + } + + Index++; + } + // + // A class was found for the sub-class code. Assign description, and check if + // this sub-class has programming interface defined. If no, no more action is + // needed, otherwise, continue to find description for the programming + // interface. + // + ClassStrings->SubClass = CurrentClass[Index].DescText; + if (NULL == CurrentClass[Index].LowerLevelClass) { + return ; + } + // + // Find programming interface entry + // + CurrentClass = CurrentClass[Index].LowerLevelClass; + Code = (UINT8) ClassCode; + Index = 0; + + // + // Go through all entries of the I/F entries, until the entry with a + // matching I/F code is found. If reaches an entry with a null description + // text, the last entry is met, which means no text was found, so no more + // action is needed. + // + while (Code != CurrentClass[Index].Code) { + if (NULL == CurrentClass[Index].DescText) { + return ; + } + + Index++; + } + // + // A class was found for the I/F code. Assign description, done! + // + ClassStrings->PIFClass = CurrentClass[Index].DescText; + return ; +} + +/** + Print strings that represent PCI device class, subclass and programmed I/F. + + @param[in] ClassCodePtr Points to the memory which stores register Class Code in PCI + configuration space. + @param[in] IncludePIF If the printed string should include the programming I/F part +**/ +VOID +PciPrintClassCode ( + IN UINT8 *ClassCodePtr, + IN BOOLEAN IncludePIF + ) +{ + UINT32 ClassCode; + PCI_CLASS_STRINGS ClassStrings; + + ClassCode = 0; + ClassCode |= (UINT32)ClassCodePtr[0]; + ClassCode |= (UINT32)(ClassCodePtr[1] << 8); + ClassCode |= (UINT32)(ClassCodePtr[2] << 16); + + // + // Get name from class code + // + PciGetClassStrings (ClassCode, &ClassStrings); + + if (IncludePIF) { + // + // Print base class, sub class, and programming inferface name + // + ShellPrintEx (-1, -1, L"%s - %s - %s", + ClassStrings.BaseClass, + ClassStrings.SubClass, + ClassStrings.PIFClass + ); + + } else { + // + // Only print base class and sub class name + // + ShellPrintEx (-1, -1, L"%s - %s", + ClassStrings.BaseClass, + ClassStrings.SubClass + ); + } +} + +/** + This function finds out the protocol which is in charge of the given + segment, and its bus range covers the current bus number. It lookes + each instances of RootBridgeIoProtocol handle, until the one meets the + criteria is found. + + @param[in] HandleBuf Buffer which holds all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles. + @param[in] HandleCount Count of all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles. + @param[in] Segment Segment number of device we are dealing with. + @param[in] Bus Bus number of device we are dealing with. + @param[out] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +PciFindProtocolInterface ( + IN EFI_HANDLE *HandleBuf, + IN UINTN HandleCount, + IN UINT16 Segment, + IN UINT16 Bus, + OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev + ); + +/** + This function gets the protocol interface from the given handle, and + obtains its address space descriptors. + + @param[in] Handle The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle. + @param[out] IoDev Handle used to access configuration space of PCI device. + @param[out] Descriptors Points to the address space descriptors. + + @retval EFI_SUCCESS The command completed successfully +**/ +EFI_STATUS +PciGetProtocolAndResource ( + IN EFI_HANDLE Handle, + OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev, + OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors + ); + +/** + This function get the next bus range of given address space descriptors. + It also moves the pointer backward a node, to get prepared to be called + again. + + @param[in, out] Descriptors Points to current position of a serial of address space + descriptors. + @param[out] MinBus The lower range of bus number. + @param[out] MaxBus The upper range of bus number. + @param[out] IsEnd Meet end of the serial of descriptors. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciGetNextBusRange ( + IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, + OUT UINT16 *MinBus, + OUT UINT16 *MaxBus, + OUT BOOLEAN *IsEnd + ); + +/** + Explain the data in PCI configuration space. The part which is common for + PCI device and bridge is interpreted in this function. It calls other + functions to interpret data unique for device or bridge. + + @param[in] ConfigSpace Data in PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. +**/ +VOID +PciExplainPci ( + IN PCI_CONFIG_SPACE *ConfigSpace, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ); + +/** + Explain the device specific part of data in PCI configuration space. + + @param[in] Device Data in PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainDeviceData ( + IN PCI_DEVICE_HEADER_TYPE_REGION *Device, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ); + +/** + Explain the bridge specific part of data in PCI configuration space. + + @param[in] Bridge Bridge specific data region in PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainBridgeData ( + IN PCI_BRIDGE_CONTROL_REGISTER *Bridge, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ); + +/** + Explain the Base Address Register(Bar) in PCI configuration space. + + @param[in] Bar Points to the Base Address Register intended to interpret. + @param[in] Command Points to the register Command. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + @param[in, out] Index The Index. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainBar ( + IN UINT32 *Bar, + IN UINT16 *Command, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev, + IN OUT UINTN *Index + ); + +/** + Explain the cardbus specific part of data in PCI configuration space. + + @param[in] CardBus CardBus specific region of PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainCardBusData ( + IN PCI_CARDBUS_CONTROL_REGISTER *CardBus, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ); + +/** + Explain each meaningful bit of register Status. The definition of Status is + slightly different depending on the PCI header type. + + @param[in] Status Points to the content of register Status. + @param[in] MainStatus Indicates if this register is main status(not secondary + status). + @param[in] HeaderType Header type of this PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainStatus ( + IN UINT16 *Status, + IN BOOLEAN MainStatus, + IN PCI_HEADER_TYPE HeaderType + ); + +/** + Explain each meaningful bit of register Command. + + @param[in] Command Points to the content of register Command. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainCommand ( + IN UINT16 *Command + ); + +/** + Explain each meaningful bit of register Bridge Control. + + @param[in] BridgeControl Points to the content of register Bridge Control. + @param[in] HeaderType The headertype. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainBridgeControl ( + IN UINT16 *BridgeControl, + IN PCI_HEADER_TYPE HeaderType + ); + +/** + Locate capability register block per capability ID. + + @param[in] ConfigSpace Data in PCI configuration space. + @param[in] CapabilityId The capability ID. + + @return The offset of the register block per capability ID. +**/ +UINT8 +LocatePciCapability ( + IN PCI_CONFIG_SPACE *ConfigSpace, + IN UINT8 CapabilityId + ); + +/** + Display Pcie device structure. + + @param[in] PciExpressCap PCI Express capability buffer. + @param[in] ExtendedConfigSpace PCI Express extended configuration space. + @param[in] ExtendedCapability PCI Express extended capability ID to explain. +**/ +VOID +PciExplainPciExpress ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap, + IN UINT8 *ExtendedConfigSpace, + IN CONST UINT16 ExtendedCapability + ); + +/** + Print out information of the capability information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieCapReg ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device capability information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieDeviceCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device control information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieDeviceControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieDeviceStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device link information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieLinkCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device link control information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieLinkControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device link status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieLinkStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device slot information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieSlotCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device slot control information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieSlotControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device slot status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieSlotStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device root information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieRootControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device root capability information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieRootCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +/** + Print out information of the device root status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieRootStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ); + +typedef EFI_STATUS (*PCIE_EXPLAIN_FUNCTION) (IN PCI_CAPABILITY_PCIEXP *PciExpressCap); + +typedef enum { + FieldWidthUINT8, + FieldWidthUINT16, + FieldWidthUINT32 +} PCIE_CAPREG_FIELD_WIDTH; + +typedef enum { + PcieExplainTypeCommon, + PcieExplainTypeDevice, + PcieExplainTypeLink, + PcieExplainTypeSlot, + PcieExplainTypeRoot, + PcieExplainTypeMax +} PCIE_EXPLAIN_TYPE; + +typedef struct +{ + UINT16 Token; + UINTN Offset; + PCIE_CAPREG_FIELD_WIDTH Width; + PCIE_EXPLAIN_FUNCTION Func; + PCIE_EXPLAIN_TYPE Type; +} PCIE_EXPLAIN_STRUCT; + +PCIE_EXPLAIN_STRUCT PcieExplainList[] = { + { + STRING_TOKEN (STR_PCIEX_CAPABILITY_CAPID), + 0x00, + FieldWidthUINT8, + NULL, + PcieExplainTypeCommon + }, + { + STRING_TOKEN (STR_PCIEX_NEXTCAP_PTR), + 0x01, + FieldWidthUINT8, + NULL, + PcieExplainTypeCommon + }, + { + STRING_TOKEN (STR_PCIEX_CAP_REGISTER), + 0x02, + FieldWidthUINT16, + ExplainPcieCapReg, + PcieExplainTypeCommon + }, + { + STRING_TOKEN (STR_PCIEX_DEVICE_CAP), + 0x04, + FieldWidthUINT32, + ExplainPcieDeviceCap, + PcieExplainTypeDevice + }, + { + STRING_TOKEN (STR_PCIEX_DEVICE_CONTROL), + 0x08, + FieldWidthUINT16, + ExplainPcieDeviceControl, + PcieExplainTypeDevice + }, + { + STRING_TOKEN (STR_PCIEX_DEVICE_STATUS), + 0x0a, + FieldWidthUINT16, + ExplainPcieDeviceStatus, + PcieExplainTypeDevice + }, + { + STRING_TOKEN (STR_PCIEX_LINK_CAPABILITIES), + 0x0c, + FieldWidthUINT32, + ExplainPcieLinkCap, + PcieExplainTypeLink + }, + { + STRING_TOKEN (STR_PCIEX_LINK_CONTROL), + 0x10, + FieldWidthUINT16, + ExplainPcieLinkControl, + PcieExplainTypeLink + }, + { + STRING_TOKEN (STR_PCIEX_LINK_STATUS), + 0x12, + FieldWidthUINT16, + ExplainPcieLinkStatus, + PcieExplainTypeLink + }, + { + STRING_TOKEN (STR_PCIEX_SLOT_CAPABILITIES), + 0x14, + FieldWidthUINT32, + ExplainPcieSlotCap, + PcieExplainTypeSlot + }, + { + STRING_TOKEN (STR_PCIEX_SLOT_CONTROL), + 0x18, + FieldWidthUINT16, + ExplainPcieSlotControl, + PcieExplainTypeSlot + }, + { + STRING_TOKEN (STR_PCIEX_SLOT_STATUS), + 0x1a, + FieldWidthUINT16, + ExplainPcieSlotStatus, + PcieExplainTypeSlot + }, + { + STRING_TOKEN (STR_PCIEX_ROOT_CONTROL), + 0x1c, + FieldWidthUINT16, + ExplainPcieRootControl, + PcieExplainTypeRoot + }, + { + STRING_TOKEN (STR_PCIEX_RSVDP), + 0x1e, + FieldWidthUINT16, + ExplainPcieRootCap, + PcieExplainTypeRoot + }, + { + STRING_TOKEN (STR_PCIEX_ROOT_STATUS), + 0x20, + FieldWidthUINT32, + ExplainPcieRootStatus, + PcieExplainTypeRoot + }, + { + 0, + 0, + (PCIE_CAPREG_FIELD_WIDTH)0, + NULL, + PcieExplainTypeMax + } +}; + +// +// Global Variables +// +PCI_CONFIG_SPACE *mConfigSpace = NULL; +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-s", TypeValue}, + {L"-i", TypeFlag}, + {L"-ec", TypeValue}, + {NULL, TypeMax} + }; + +CHAR16 *DevicePortTypeTable[] = { + L"PCI Express Endpoint", + L"Legacy PCI Express Endpoint", + L"Unknown Type", + L"Unknonw Type", + L"Root Port of PCI Express Root Complex", + L"Upstream Port of PCI Express Switch", + L"Downstream Port of PCI Express Switch", + L"PCI Express to PCI/PCI-X Bridge", + L"PCI/PCI-X to PCI Express Bridge", + L"Root Complex Integrated Endpoint", + L"Root Complex Event Collector" +}; + +CHAR16 *L0sLatencyStrTable[] = { + L"Less than 64ns", + L"64ns to less than 128ns", + L"128ns to less than 256ns", + L"256ns to less than 512ns", + L"512ns to less than 1us", + L"1us to less than 2us", + L"2us-4us", + L"More than 4us" +}; + +CHAR16 *L1LatencyStrTable[] = { + L"Less than 1us", + L"1us to less than 2us", + L"2us to less than 4us", + L"4us to less than 8us", + L"8us to less than 16us", + L"16us to less than 32us", + L"32us-64us", + L"More than 64us" +}; + +CHAR16 *ASPMCtrlStrTable[] = { + L"Disabled", + L"L0s Entry Enabled", + L"L1 Entry Enabled", + L"L0s and L1 Entry Enabled" +}; + +CHAR16 *SlotPwrLmtScaleTable[] = { + L"1.0x", + L"0.1x", + L"0.01x", + L"0.001x" +}; + +CHAR16 *IndicatorTable[] = { + L"Reserved", + L"On", + L"Blink", + L"Off" +}; + + +/** + Function for 'pci' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPci ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT16 Segment; + UINT16 Bus; + UINT16 Device; + UINT16 Func; + UINT64 Address; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev; + EFI_STATUS Status; + PCI_DEVICE_INDEPENDENT_REGION PciHeader; + PCI_CONFIG_SPACE ConfigSpace; + UINTN ScreenCount; + UINTN TempColumn; + UINTN ScreenSize; + BOOLEAN ExplainData; + UINTN Index; + UINTN SizeOfHeader; + BOOLEAN PrintTitle; + UINTN HandleBufSize; + EFI_HANDLE *HandleBuf; + UINTN HandleCount; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + UINT16 MinBus; + UINT16 MaxBus; + BOOLEAN IsEnd; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Temp; + UINT64 RetVal; + UINT16 ExtendedCapability; + UINT8 PcieCapabilityPtr; + UINT8 *ExtendedConfigSpace; + UINTN ExtendedConfigSize; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Address = 0; + IoDev = NULL; + HandleBuf = NULL; + Package = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"pci", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + + if (ShellCommandLineGetCount(Package) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + if (ShellCommandLineGetCount(Package) > 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (ShellCommandLineGetFlag(Package, L"-ec") && ShellCommandLineGetValue(Package, L"-ec") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"pci", L"-ec"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetValue(Package, L"-s") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"pci", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + // + // Get all instances of PciRootBridgeIo. Allocate space for 1 EFI_HANDLE and + // call LibLocateHandle(), if EFI_BUFFER_TOO_SMALL is returned, allocate enough + // space for handles and call it again. + // + HandleBufSize = sizeof (EFI_HANDLE); + HandleBuf = (EFI_HANDLE *) AllocateZeroPool (HandleBufSize); + if (HandleBuf == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &HandleBufSize, + HandleBuf + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuf = ReallocatePool (sizeof (EFI_HANDLE), HandleBufSize, HandleBuf); + if (HandleBuf == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto Done; + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &HandleBufSize, + HandleBuf + ); + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + + HandleCount = HandleBufSize / sizeof (EFI_HANDLE); + // + // Argument Count == 1(no other argument): enumerate all pci functions + // + if (ShellCommandLineGetCount(Package) == 1) { + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &TempColumn, + &ScreenSize + ); + + ScreenCount = 0; + ScreenSize -= 4; + if ((ScreenSize & 1) == 1) { + ScreenSize -= 1; + } + + PrintTitle = TRUE; + + // + // For each handle, which decides a segment and a bus number range, + // enumerate all devices on it. + // + for (Index = 0; Index < HandleCount; Index++) { + Status = PciGetProtocolAndResource ( + HandleBuf[Index], + &IoDev, + &Descriptors + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_HANDLE_CFG_ERR), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + // + // No document say it's impossible for a RootBridgeIo protocol handle + // to have more than one address space descriptors, so find out every + // bus range and for each of them do device enumeration. + // + while (TRUE) { + Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_BUS_RANGE_ERR), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + + if (IsEnd) { + break; + } + + for (Bus = MinBus; Bus <= MaxBus; Bus++) { + // + // For each devices, enumerate all functions it contains + // + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + // + // For each function, read its configuration space and print summary + // + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + goto Done; + } + Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0); + IoDev->Pci.Read ( + IoDev, + EfiPciWidthUint16, + Address, + 1, + &PciHeader.VendorId + ); + + // + // If VendorId = 0xffff, there does not exist a device at this + // location. For each device, if there is any function on it, + // there must be 1 function at Function 0. So if Func = 0, there + // will be no more functions in the same device, so we can break + // loop to deal with the next device. + // + if (PciHeader.VendorId == 0xffff && Func == 0) { + break; + } + + if (PciHeader.VendorId != 0xffff) { + + if (PrintTitle) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_TITLE), gShellDebug1HiiHandle); + PrintTitle = FALSE; + } + + IoDev->Pci.Read ( + IoDev, + EfiPciWidthUint32, + Address, + sizeof (PciHeader) / sizeof (UINT32), + &PciHeader + ); + + ShellPrintHiiEx( + -1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_P1), gShellDebug1HiiHandle, + IoDev->SegmentNumber, + Bus, + Device, + Func + ); + + PciPrintClassCode (PciHeader.ClassCode, FALSE); + ShellPrintHiiEx( + -1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_P2), gShellDebug1HiiHandle, + PciHeader.VendorId, + PciHeader.DeviceId, + PciHeader.ClassCode[0] + ); + + ScreenCount += 2; + if (ScreenCount >= ScreenSize && ScreenSize != 0) { + // + // If ScreenSize == 0 we have the console redirected so don't + // block updates + // + ScreenCount = 0; + } + // + // If this is not a multi-function device, we can leave the loop + // to deal with the next device. + // + if (Func == 0 && ((PciHeader.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00)) { + break; + } + } + } + } + } + // + // If Descriptor is NULL, Configuration() returns EFI_UNSUPPRORED, + // we assume the bus range is 0~PCI_MAX_BUS. After enumerated all + // devices on all bus, we can leave loop. + // + if (Descriptors == NULL) { + break; + } + } + } + + Status = EFI_SUCCESS; + goto Done; + } + + ExplainData = FALSE; + Segment = 0; + Bus = 0; + Device = 0; + Func = 0; + ExtendedCapability = 0xFFFF; + if (ShellCommandLineGetFlag(Package, L"-i")) { + ExplainData = TRUE; + } + + Temp = ShellCommandLineGetValue(Package, L"-s"); + if (Temp != NULL) { + // + // Input converted to hexadecimal number. + // + if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) { + Segment = (UINT16) RetVal; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + + // + // The first Argument(except "-i") is assumed to be Bus number, second + // to be Device number, and third to be Func number. + // + Temp = ShellCommandLineGetRawValue(Package, 1); + if (Temp != NULL) { + // + // Input converted to hexadecimal number. + // + if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) { + Bus = (UINT16) RetVal; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + if (Bus > PCI_MAX_BUS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + Temp = ShellCommandLineGetRawValue(Package, 2); + if (Temp != NULL) { + // + // Input converted to hexadecimal number. + // + if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) { + Device = (UINT16) RetVal; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + if (Device > PCI_MAX_DEVICE){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + + Temp = ShellCommandLineGetRawValue(Package, 3); + if (Temp != NULL) { + // + // Input converted to hexadecimal number. + // + if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) { + Func = (UINT16) RetVal; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + if (Func > PCI_MAX_FUNC){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + + Temp = ShellCommandLineGetValue (Package, L"-ec"); + if (Temp != NULL) { + // + // Input converted to hexadecimal number. + // + if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) { + ExtendedCapability = (UINT16) RetVal; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + + // + // Find the protocol interface who's in charge of current segment, and its + // bus range covers the current bus + // + Status = PciFindProtocolInterface ( + HandleBuf, + HandleCount, + Segment, + Bus, + &IoDev + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, -1, NULL, STRING_TOKEN (STR_PCI_NO_FIND), gShellDebug1HiiHandle, L"pci", + Segment, + Bus + ); + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + + Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0); + Status = IoDev->Pci.Read ( + IoDev, + EfiPciWidthUint8, + Address, + sizeof (ConfigSpace), + &ConfigSpace + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_NO_CFG), gShellDebug1HiiHandle, L"pci"); + ShellStatus = SHELL_ACCESS_DENIED; + goto Done; + } + + mConfigSpace = &ConfigSpace; + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_PCI_INFO), + gShellDebug1HiiHandle, + Segment, + Bus, + Device, + Func, + Segment, + Bus, + Device, + Func + ); + + // + // Dump standard header of configuration space + // + SizeOfHeader = sizeof (ConfigSpace.Common) + sizeof (ConfigSpace.NonCommon); + + DumpHex (2, 0, SizeOfHeader, &ConfigSpace); + ShellPrintEx(-1,-1, L"\r\n"); + + // + // Dump device dependent Part of configuration space + // + DumpHex ( + 2, + SizeOfHeader, + sizeof (ConfigSpace) - SizeOfHeader, + ConfigSpace.Data + ); + + ExtendedConfigSpace = NULL; + ExtendedConfigSize = 0; + PcieCapabilityPtr = LocatePciCapability (&ConfigSpace, EFI_PCI_CAPABILITY_ID_PCIEXP); + if (PcieCapabilityPtr != 0) { + ExtendedConfigSize = 0x1000 - EFI_PCIE_CAPABILITY_BASE_OFFSET; + ExtendedConfigSpace = AllocatePool (ExtendedConfigSize); + if (ExtendedConfigSpace != NULL) { + Status = IoDev->Pci.Read ( + IoDev, + EfiPciWidthUint32, + EFI_PCI_ADDRESS (Bus, Device, Func, EFI_PCIE_CAPABILITY_BASE_OFFSET), + ExtendedConfigSize / sizeof (UINT32), + ExtendedConfigSpace + ); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (ExtendedConfigSpace); + } + } + } + + if ((ExtendedConfigSpace != NULL) && !ShellGetExecutionBreakFlag ()) { + // + // Print the PciEx extend space in raw bytes ( 0xFF-0xFFF) + // + ShellPrintEx (-1, -1, L"\r\n%HStart dumping PCIex extended configuration space (0x100 - 0xFFF).%N\r\n\r\n"); + + DumpHex ( + 2, + EFI_PCIE_CAPABILITY_BASE_OFFSET, + ExtendedConfigSize, + ExtendedConfigSpace + ); + } + + // + // If "-i" appears in command line, interpret data in configuration space + // + if (ExplainData) { + PciExplainPci (&ConfigSpace, Address, IoDev); + if ((ExtendedConfigSpace != NULL) && !ShellGetExecutionBreakFlag ()) { + PciExplainPciExpress ( + (PCI_CAPABILITY_PCIEXP *) ((UINT8 *) &ConfigSpace + PcieCapabilityPtr), + ExtendedConfigSpace, + ExtendedCapability + ); + } + } + } +Done: + if (HandleBuf != NULL) { + FreePool (HandleBuf); + } + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + mConfigSpace = NULL; + return ShellStatus; +} + +/** + This function finds out the protocol which is in charge of the given + segment, and its bus range covers the current bus number. It lookes + each instances of RootBridgeIoProtocol handle, until the one meets the + criteria is found. + + @param[in] HandleBuf Buffer which holds all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles. + @param[in] HandleCount Count of all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles. + @param[in] Segment Segment number of device we are dealing with. + @param[in] Bus Bus number of device we are dealing with. + @param[out] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +PciFindProtocolInterface ( + IN EFI_HANDLE *HandleBuf, + IN UINTN HandleCount, + IN UINT16 Segment, + IN UINT16 Bus, + OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev + ) +{ + UINTN Index; + EFI_STATUS Status; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + UINT16 MinBus; + UINT16 MaxBus; + BOOLEAN IsEnd; + + // + // Go through all handles, until the one meets the criteria is found + // + for (Index = 0; Index < HandleCount; Index++) { + Status = PciGetProtocolAndResource (HandleBuf[Index], IoDev, &Descriptors); + if (EFI_ERROR (Status)) { + return Status; + } + // + // When Descriptors == NULL, the Configuration() is not implemented, + // so we only check the Segment number + // + if (Descriptors == NULL && Segment == (*IoDev)->SegmentNumber) { + return EFI_SUCCESS; + } + + if ((*IoDev)->SegmentNumber != Segment) { + continue; + } + + while (TRUE) { + Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd); + if (EFI_ERROR (Status)) { + return Status; + } + + if (IsEnd) { + break; + } + + if (MinBus <= Bus && MaxBus >= Bus) { + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + This function gets the protocol interface from the given handle, and + obtains its address space descriptors. + + @param[in] Handle The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle. + @param[out] IoDev Handle used to access configuration space of PCI device. + @param[out] Descriptors Points to the address space descriptors. + + @retval EFI_SUCCESS The command completed successfully +**/ +EFI_STATUS +PciGetProtocolAndResource ( + IN EFI_HANDLE Handle, + OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev, + OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors + ) +{ + EFI_STATUS Status; + + // + // Get inferface from protocol + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID**)IoDev + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Call Configuration() to get address space descriptors + // + Status = (*IoDev)->Configuration (*IoDev, (VOID**)Descriptors); + if (Status == EFI_UNSUPPORTED) { + *Descriptors = NULL; + return EFI_SUCCESS; + + } else { + return Status; + } +} + +/** + This function get the next bus range of given address space descriptors. + It also moves the pointer backward a node, to get prepared to be called + again. + + @param[in, out] Descriptors Points to current position of a serial of address space + descriptors. + @param[out] MinBus The lower range of bus number. + @param[out] MaxBus The upper range of bus number. + @param[out] IsEnd Meet end of the serial of descriptors. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciGetNextBusRange ( + IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, + OUT UINT16 *MinBus, + OUT UINT16 *MaxBus, + OUT BOOLEAN *IsEnd + ) +{ + *IsEnd = FALSE; + + // + // When *Descriptors is NULL, Configuration() is not implemented, so assume + // range is 0~PCI_MAX_BUS + // + if ((*Descriptors) == NULL) { + *MinBus = 0; + *MaxBus = PCI_MAX_BUS; + return EFI_SUCCESS; + } + // + // *Descriptors points to one or more address space descriptors, which + // ends with a end tagged descriptor. Examine each of the descriptors, + // if a bus typed one is found and its bus range covers bus, this handle + // is the handle we are looking for. + // + + while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) { + if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { + *MinBus = (UINT16) (*Descriptors)->AddrRangeMin; + *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax; + (*Descriptors)++; + return (EFI_SUCCESS); + } + + (*Descriptors)++; + } + + if ((*Descriptors)->Desc == ACPI_END_TAG_DESCRIPTOR) { + *IsEnd = TRUE; + } + + return EFI_SUCCESS; +} + +/** + Explain the data in PCI configuration space. The part which is common for + PCI device and bridge is interpreted in this function. It calls other + functions to interpret data unique for device or bridge. + + @param[in] ConfigSpace Data in PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. +**/ +VOID +PciExplainPci ( + IN PCI_CONFIG_SPACE *ConfigSpace, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ) +{ + PCI_DEVICE_INDEPENDENT_REGION *Common; + PCI_HEADER_TYPE HeaderType; + + Common = &(ConfigSpace->Common); + + ShellPrintEx (-1, -1, L"\r\n"); + + // + // Print Vendor Id and Device Id + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_VID_DID), gShellDebug1HiiHandle, + INDEX_OF (&(Common->VendorId)), + Common->VendorId, + INDEX_OF (&(Common->DeviceId)), + Common->DeviceId + ); + + // + // Print register Command + // + PciExplainCommand (&(Common->Command)); + + // + // Print register Status + // + PciExplainStatus (&(Common->Status), TRUE, PciUndefined); + + // + // Print register Revision ID + // + ShellPrintEx(-1, -1, L"\r\n"); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_RID), gShellDebug1HiiHandle, + INDEX_OF (&(Common->RevisionID)), + Common->RevisionID + ); + + // + // Print register BIST + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_BIST), gShellDebug1HiiHandle, INDEX_OF (&(Common->BIST))); + if ((Common->BIST & BIT7) != 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_CAP), gShellDebug1HiiHandle, 0x0f & Common->BIST); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_CAP_NO), gShellDebug1HiiHandle); + } + // + // Print register Cache Line Size + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CACHE_LINE_SIZE), + gShellDebug1HiiHandle, + INDEX_OF (&(Common->CacheLineSize)), + Common->CacheLineSize + ); + + // + // Print register Latency Timer + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_LATENCY_TIMER), + gShellDebug1HiiHandle, + INDEX_OF (&(Common->LatencyTimer)), + Common->LatencyTimer + ); + + // + // Print register Header Type + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_HEADER_TYPE), + gShellDebug1HiiHandle, + INDEX_OF (&(Common->HeaderType)), + Common->HeaderType + ); + + if ((Common->HeaderType & BIT7) != 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MULTI_FUNCTION), gShellDebug1HiiHandle); + + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SINGLE_FUNCTION), gShellDebug1HiiHandle); + } + + HeaderType = (PCI_HEADER_TYPE)(UINT8) (Common->HeaderType & 0x7f); + switch (HeaderType) { + case PciDevice: + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_PCI_DEVICE), gShellDebug1HiiHandle); + break; + + case PciP2pBridge: + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_P2P_BRIDGE), gShellDebug1HiiHandle); + break; + + case PciCardBusBridge: + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_BRIDGE), gShellDebug1HiiHandle); + break; + + default: + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESERVED), gShellDebug1HiiHandle); + HeaderType = PciUndefined; + } + + // + // Print register Class Code + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CLASS), gShellDebug1HiiHandle); + PciPrintClassCode ((UINT8 *) Common->ClassCode, TRUE); + ShellPrintEx (-1, -1, L"\r\n"); +} + +/** + Explain the device specific part of data in PCI configuration space. + + @param[in] Device Data in PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainDeviceData ( + IN PCI_DEVICE_HEADER_TYPE_REGION *Device, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ) +{ + UINTN Index; + BOOLEAN BarExist; + EFI_STATUS Status; + UINTN BarCount; + + // + // Print Base Address Registers(Bar). When Bar = 0, this Bar does not + // exist. If these no Bar for this function, print "none", otherwise + // list detail information about this Bar. + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BASE_ADDR), gShellDebug1HiiHandle, INDEX_OF (Device->Bar)); + + BarExist = FALSE; + BarCount = sizeof (Device->Bar) / sizeof (Device->Bar[0]); + for (Index = 0; Index < BarCount; Index++) { + if (Device->Bar[Index] == 0) { + continue; + } + + if (!BarExist) { + BarExist = TRUE; + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_START_TYPE), gShellDebug1HiiHandle); + ShellPrintEx (-1, -1, L" --------------------------------------------------------------------------"); + } + + Status = PciExplainBar ( + &(Device->Bar[Index]), + &(mConfigSpace->Common.Command), + Address, + IoDev, + &Index + ); + + if (EFI_ERROR (Status)) { + break; + } + } + + if (!BarExist) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NONE), gShellDebug1HiiHandle); + + } else { + ShellPrintEx (-1, -1, L"\r\n --------------------------------------------------------------------------"); + } + + // + // Print register Expansion ROM Base Address + // + if ((Device->ExpansionRomBar & BIT0) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_EXPANSION_ROM_DISABLED), gShellDebug1HiiHandle, INDEX_OF (&(Device->ExpansionRomBar))); + + } else { + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_EXPANSION_ROM_BASE), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->ExpansionRomBar)), + Device->ExpansionRomBar + ); + } + // + // Print register Cardbus CIS ptr + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CARDBUS_CIS), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->CISPtr)), + Device->CISPtr + ); + + // + // Print register Sub-vendor ID and subsystem ID + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SUB_VENDOR_ID), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->SubsystemVendorID)), + Device->SubsystemVendorID + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SUBSYSTEM_ID), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->SubsystemID)), + Device->SubsystemID + ); + + // + // Print register Capabilities Ptr + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CAPABILITIES_PTR), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->CapabilityPtr)), + Device->CapabilityPtr + ); + + // + // Print register Interrupt Line and interrupt pin + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_INTERRUPT_LINE), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->InterruptLine)), + Device->InterruptLine + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_INTERRUPT_PIN), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->InterruptPin)), + Device->InterruptPin + ); + + // + // Print register Min_Gnt and Max_Lat + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MIN_GNT), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->MinGnt)), + Device->MinGnt + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MAX_LAT), + gShellDebug1HiiHandle, + INDEX_OF (&(Device->MaxLat)), + Device->MaxLat + ); + + return EFI_SUCCESS; +} + +/** + Explain the bridge specific part of data in PCI configuration space. + + @param[in] Bridge Bridge specific data region in PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainBridgeData ( + IN PCI_BRIDGE_CONTROL_REGISTER *Bridge, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ) +{ + UINTN Index; + BOOLEAN BarExist; + UINTN BarCount; + UINT32 IoAddress32; + EFI_STATUS Status; + + // + // Print Base Address Registers. When Bar = 0, this Bar does not + // exist. If these no Bar for this function, print "none", otherwise + // list detail information about this Bar. + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BASE_ADDRESS), gShellDebug1HiiHandle, INDEX_OF (&(Bridge->Bar))); + + BarExist = FALSE; + BarCount = sizeof (Bridge->Bar) / sizeof (Bridge->Bar[0]); + + for (Index = 0; Index < BarCount; Index++) { + if (Bridge->Bar[Index] == 0) { + continue; + } + + if (!BarExist) { + BarExist = TRUE; + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_START_TYPE_2), gShellDebug1HiiHandle); + ShellPrintEx (-1, -1, L" --------------------------------------------------------------------------"); + } + + Status = PciExplainBar ( + &(Bridge->Bar[Index]), + &(mConfigSpace->Common.Command), + Address, + IoDev, + &Index + ); + + if (EFI_ERROR (Status)) { + break; + } + } + + if (!BarExist) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NONE), gShellDebug1HiiHandle); + } else { + ShellPrintEx (-1, -1, L"\r\n --------------------------------------------------------------------------"); + } + + // + // Expansion register ROM Base Address + // + if ((Bridge->ExpansionRomBAR & BIT0) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NO_EXPANSION_ROM), gShellDebug1HiiHandle, INDEX_OF (&(Bridge->ExpansionRomBAR))); + + } else { + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_EXPANSION_ROM_BASE_2), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->ExpansionRomBAR)), + Bridge->ExpansionRomBAR + ); + } + // + // Print Bus Numbers(Primary, Secondary, and Subordinate + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_BUS_NUMBERS), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->PrimaryBus)), + INDEX_OF (&(Bridge->SecondaryBus)), + INDEX_OF (&(Bridge->SubordinateBus)) + ); + + ShellPrintEx (-1, -1, L" ------------------------------------------------------\r\n"); + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->PrimaryBus); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->SecondaryBus); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->SubordinateBus); + + // + // Print register Secondary Latency Timer + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SECONDARY_TIMER), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->SecondaryLatencyTimer)), + Bridge->SecondaryLatencyTimer + ); + + // + // Print register Secondary Status + // + PciExplainStatus (&(Bridge->SecondaryStatus), FALSE, PciP2pBridge); + + // + // Print I/O and memory ranges this bridge forwards. There are 3 resource + // types: I/O, memory, and pre-fetchable memory. For each resource type, + // base and limit address are listed. + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESOURCE_TYPE), gShellDebug1HiiHandle); + ShellPrintEx (-1, -1, L"----------------------------------------------------------------------\r\n"); + + // + // IO Base & Limit + // + IoAddress32 = (Bridge->IoBaseUpper16 << 16 | Bridge->IoBase << 8); + IoAddress32 &= 0xfffff000; + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_TWO_VARS), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->IoBase)), + IoAddress32 + ); + + IoAddress32 = (Bridge->IoLimitUpper16 << 16 | Bridge->IoLimit << 8); + IoAddress32 |= 0x00000fff; + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR), gShellDebug1HiiHandle, IoAddress32); + + // + // Memory Base & Limit + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MEMORY), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->MemoryBase)), + (Bridge->MemoryBase << 16) & 0xfff00000 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_ONE_VAR), + gShellDebug1HiiHandle, + (Bridge->MemoryLimit << 16) | 0x000fffff + ); + + // + // Pre-fetch-able Memory Base & Limit + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_PREFETCHABLE), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->PrefetchableMemoryBase)), + Bridge->PrefetchableBaseUpper32, + (Bridge->PrefetchableMemoryBase << 16) & 0xfff00000 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_TWO_VARS_2), + gShellDebug1HiiHandle, + Bridge->PrefetchableLimitUpper32, + (Bridge->PrefetchableMemoryLimit << 16) | 0x000fffff + ); + + // + // Print register Capabilities Pointer + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CAPABILITIES_PTR_2), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->CapabilityPtr)), + Bridge->CapabilityPtr + ); + + // + // Print register Bridge Control + // + PciExplainBridgeControl (&(Bridge->BridgeControl), PciP2pBridge); + + // + // Print register Interrupt Line & PIN + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_INTERRUPT_LINE_2), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->InterruptLine)), + Bridge->InterruptLine + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_INTERRUPT_PIN), + gShellDebug1HiiHandle, + INDEX_OF (&(Bridge->InterruptPin)), + Bridge->InterruptPin + ); + + return EFI_SUCCESS; +} + +/** + Explain the Base Address Register(Bar) in PCI configuration space. + + @param[in] Bar Points to the Base Address Register intended to interpret. + @param[in] Command Points to the register Command. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + @param[in, out] Index The Index. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainBar ( + IN UINT32 *Bar, + IN UINT16 *Command, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev, + IN OUT UINTN *Index + ) +{ + UINT16 OldCommand; + UINT16 NewCommand; + UINT64 Bar64; + UINT32 OldBar32; + UINT32 NewBar32; + UINT64 OldBar64; + UINT64 NewBar64; + BOOLEAN IsMem; + BOOLEAN IsBar32; + UINT64 RegAddress; + + IsBar32 = TRUE; + Bar64 = 0; + NewBar32 = 0; + NewBar64 = 0; + + // + // According the bar type, list detail about this bar, for example: 32 or + // 64 bits; pre-fetchable or not. + // + if ((*Bar & BIT0) == 0) { + // + // This bar is of memory type + // + IsMem = TRUE; + + if ((*Bar & BIT1) == 0 && (*Bar & BIT2) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BAR), gShellDebug1HiiHandle, *Bar & 0xfffffff0); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM), gShellDebug1HiiHandle); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_32_BITS), gShellDebug1HiiHandle); + + } else if ((*Bar & BIT1) == 0 && (*Bar & BIT2) != 0) { + Bar64 = 0x0; + CopyMem (&Bar64, Bar, sizeof (UINT64)); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_2), gShellDebug1HiiHandle, (UINT32) RShiftU64 ((Bar64 & 0xfffffffffffffff0ULL), 32)); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_3), gShellDebug1HiiHandle, (UINT32) (Bar64 & 0xfffffffffffffff0ULL)); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM), gShellDebug1HiiHandle); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_64_BITS), gShellDebug1HiiHandle); + IsBar32 = FALSE; + *Index += 1; + + } else { + // + // Reserved + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BAR), gShellDebug1HiiHandle, *Bar & 0xfffffff0); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM_2), gShellDebug1HiiHandle); + } + + if ((*Bar & BIT3) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NO), gShellDebug1HiiHandle); + + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_YES), gShellDebug1HiiHandle); + } + + } else { + // + // This bar is of io type + // + IsMem = FALSE; + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_4), gShellDebug1HiiHandle, *Bar & 0xfffffffc); + ShellPrintEx (-1, -1, L"I/O "); + } + + // + // Get BAR length(or the amount of resource this bar demands for). To get + // Bar length, first we should temporarily disable I/O and memory access + // of this function(by set bits in the register Command), then write all + // "1"s to this bar. The bar value read back is the amount of resource + // this bar demands for. + // + // + // Disable io & mem access + // + OldCommand = *Command; + NewCommand = (UINT16) (OldCommand & 0xfffc); + RegAddress = Address | INDEX_OF (Command); + IoDev->Pci.Write (IoDev, EfiPciWidthUint16, RegAddress, 1, &NewCommand); + + RegAddress = Address | INDEX_OF (Bar); + + // + // Read after write the BAR to get the size + // + if (IsBar32) { + OldBar32 = *Bar; + NewBar32 = 0xffffffff; + + IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 1, &NewBar32); + IoDev->Pci.Read (IoDev, EfiPciWidthUint32, RegAddress, 1, &NewBar32); + IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 1, &OldBar32); + + if (IsMem) { + NewBar32 = NewBar32 & 0xfffffff0; + NewBar32 = (~NewBar32) + 1; + + } else { + NewBar32 = NewBar32 & 0xfffffffc; + NewBar32 = (~NewBar32) + 1; + NewBar32 = NewBar32 & 0x0000ffff; + } + } else { + + OldBar64 = 0x0; + CopyMem (&OldBar64, Bar, sizeof (UINT64)); + NewBar64 = 0xffffffffffffffffULL; + + IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 2, &NewBar64); + IoDev->Pci.Read (IoDev, EfiPciWidthUint32, RegAddress, 2, &NewBar64); + IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 2, &OldBar64); + + if (IsMem) { + NewBar64 = NewBar64 & 0xfffffffffffffff0ULL; + NewBar64 = (~NewBar64) + 1; + + } else { + NewBar64 = NewBar64 & 0xfffffffffffffffcULL; + NewBar64 = (~NewBar64) + 1; + NewBar64 = NewBar64 & 0x000000000000ffff; + } + } + // + // Enable io & mem access + // + RegAddress = Address | INDEX_OF (Command); + IoDev->Pci.Write (IoDev, EfiPciWidthUint16, RegAddress, 1, &OldCommand); + + if (IsMem) { + if (IsBar32) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32), gShellDebug1HiiHandle, NewBar32); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_2), gShellDebug1HiiHandle, NewBar32 + (*Bar & 0xfffffff0) - 1); + + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) RShiftU64 (NewBar64, 32)); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) NewBar64); + ShellPrintEx (-1, -1, L" "); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_RSHIFT), + gShellDebug1HiiHandle, + (UINT32) RShiftU64 ((NewBar64 + (Bar64 & 0xfffffffffffffff0ULL) - 1), 32) + ); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) (NewBar64 + (Bar64 & 0xfffffffffffffff0ULL) - 1)); + + } + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_3), gShellDebug1HiiHandle, NewBar32); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_4), gShellDebug1HiiHandle, NewBar32 + (*Bar & 0xfffffffc) - 1); + } + + return EFI_SUCCESS; +} + +/** + Explain the cardbus specific part of data in PCI configuration space. + + @param[in] CardBus CardBus specific region of PCI configuration space. + @param[in] Address Address used to access configuration space of this PCI device. + @param[in] IoDev Handle used to access configuration space of PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainCardBusData ( + IN PCI_CARDBUS_CONTROL_REGISTER *CardBus, + IN UINT64 Address, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev + ) +{ + BOOLEAN Io32Bit; + PCI_CARDBUS_DATA *CardBusData; + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CARDBUS_SOCKET), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->CardBusSocketReg)), + CardBus->CardBusSocketReg + ); + + // + // Print Secondary Status + // + PciExplainStatus (&(CardBus->SecondaryStatus), FALSE, PciCardBusBridge); + + // + // Print Bus Numbers(Primary bus number, CardBus bus number, and + // Subordinate bus number + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_BUS_NUMBERS_2), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->PciBusNumber)), + INDEX_OF (&(CardBus->CardBusBusNumber)), + INDEX_OF (&(CardBus->SubordinateBusNumber)) + ); + + ShellPrintEx (-1, -1, L" ------------------------------------------------------\r\n"); + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS), gShellDebug1HiiHandle, CardBus->PciBusNumber); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_2), gShellDebug1HiiHandle, CardBus->CardBusBusNumber); + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_3), gShellDebug1HiiHandle, CardBus->SubordinateBusNumber); + + // + // Print CardBus Latency Timer + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CARDBUS_LATENCY), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->CardBusLatencyTimer)), + CardBus->CardBusLatencyTimer + ); + + // + // Print Memory/Io ranges this cardbus bridge forwards + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESOURCE_TYPE_2), gShellDebug1HiiHandle); + ShellPrintEx (-1, -1, L"----------------------------------------------------------------------\r\n"); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MEM_3), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->MemoryBase0)), + CardBus->BridgeControl & BIT8 ? L" Prefetchable" : L"Non-Prefetchable", + CardBus->MemoryBase0 & 0xfffff000, + CardBus->MemoryLimit0 | 0x00000fff + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MEM_3), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->MemoryBase1)), + CardBus->BridgeControl & BIT9 ? L" Prefetchable" : L"Non-Prefetchable", + CardBus->MemoryBase1 & 0xfffff000, + CardBus->MemoryLimit1 | 0x00000fff + ); + + Io32Bit = (BOOLEAN) (CardBus->IoBase0 & BIT0); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_IO_2), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->IoBase0)), + Io32Bit ? L" 32 bit" : L" 16 bit", + CardBus->IoBase0 & (Io32Bit ? 0xfffffffc : 0x0000fffc), + (CardBus->IoLimit0 & (Io32Bit ? 0xffffffff : 0x0000ffff)) | 0x00000003 + ); + + Io32Bit = (BOOLEAN) (CardBus->IoBase1 & BIT0); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_IO_2), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->IoBase1)), + Io32Bit ? L" 32 bit" : L" 16 bit", + CardBus->IoBase1 & (Io32Bit ? 0xfffffffc : 0x0000fffc), + (CardBus->IoLimit1 & (Io32Bit ? 0xffffffff : 0x0000ffff)) | 0x00000003 + ); + + // + // Print register Interrupt Line & PIN + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_INTERRUPT_LINE_3), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBus->InterruptLine)), + CardBus->InterruptLine, + INDEX_OF (&(CardBus->InterruptPin)), + CardBus->InterruptPin + ); + + // + // Print register Bridge Control + // + PciExplainBridgeControl (&(CardBus->BridgeControl), PciCardBusBridge); + + // + // Print some registers in data region of PCI configuration space for cardbus + // bridge. Fields include: Sub VendorId, Subsystem ID, and Legacy Mode Base + // Address. + // + CardBusData = (PCI_CARDBUS_DATA *) ((UINT8 *) CardBus + sizeof (PCI_CARDBUS_CONTROL_REGISTER)); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SUB_VENDOR_ID_2), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBusData->SubVendorId)), + CardBusData->SubVendorId, + INDEX_OF (&(CardBusData->SubSystemId)), + CardBusData->SubSystemId + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_OPTIONAL), + gShellDebug1HiiHandle, + INDEX_OF (&(CardBusData->LegacyBase)), + CardBusData->LegacyBase + ); + + return EFI_SUCCESS; +} + +/** + Explain each meaningful bit of register Status. The definition of Status is + slightly different depending on the PCI header type. + + @param[in] Status Points to the content of register Status. + @param[in] MainStatus Indicates if this register is main status(not secondary + status). + @param[in] HeaderType Header type of this PCI device. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainStatus ( + IN UINT16 *Status, + IN BOOLEAN MainStatus, + IN PCI_HEADER_TYPE HeaderType + ) +{ + if (MainStatus) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_STATUS), gShellDebug1HiiHandle, INDEX_OF (Status), *Status); + + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SECONDARY_STATUS), gShellDebug1HiiHandle, INDEX_OF (Status), *Status); + } + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEW_CAPABILITIES), gShellDebug1HiiHandle, (*Status & BIT4) != 0); + + // + // Bit 5 is meaningless for CardBus Bridge + // + if (HeaderType == PciCardBusBridge) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_66_CAPABLE), gShellDebug1HiiHandle, (*Status & BIT5) != 0); + + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_66_CAPABLE_2), gShellDebug1HiiHandle, (*Status & BIT5) != 0); + } + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_FAST_BACK), gShellDebug1HiiHandle, (*Status & BIT7) != 0); + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MASTER_DATA), gShellDebug1HiiHandle, (*Status & BIT8) != 0); + // + // Bit 9 and bit 10 together decides the DEVSEL timing + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_DEVSEL_TIMING), gShellDebug1HiiHandle); + if ((*Status & BIT9) == 0 && (*Status & BIT10) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_FAST), gShellDebug1HiiHandle); + + } else if ((*Status & BIT9) != 0 && (*Status & BIT10) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEDIUM), gShellDebug1HiiHandle); + + } else if ((*Status & BIT9) == 0 && (*Status & BIT10) != 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SLOW), gShellDebug1HiiHandle); + + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESERVED_2), gShellDebug1HiiHandle); + } + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SIGNALED_TARGET), + gShellDebug1HiiHandle, + (*Status & BIT11) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_RECEIVED_TARGET), + gShellDebug1HiiHandle, + (*Status & BIT12) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_RECEIVED_MASTER), + gShellDebug1HiiHandle, + (*Status & BIT13) != 0 + ); + + if (MainStatus) { + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SIGNALED_ERROR), + gShellDebug1HiiHandle, + (*Status & BIT14) != 0 + ); + + } else { + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_RECEIVED_ERROR), + gShellDebug1HiiHandle, + (*Status & BIT14) != 0 + ); + } + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_DETECTED_ERROR), + gShellDebug1HiiHandle, + (*Status & BIT15) != 0 + ); + + return EFI_SUCCESS; +} + +/** + Explain each meaningful bit of register Command. + + @param[in] Command Points to the content of register Command. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainCommand ( + IN UINT16 *Command + ) +{ + // + // Print the binary value of register Command + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_COMMAND), gShellDebug1HiiHandle, INDEX_OF (Command), *Command); + + // + // Explain register Command bit by bit + // + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SPACE_ACCESS_DENIED), + gShellDebug1HiiHandle, + (*Command & BIT0) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MEMORY_SPACE), + gShellDebug1HiiHandle, + (*Command & BIT1) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_BEHAVE_BUS_MASTER), + gShellDebug1HiiHandle, + (*Command & BIT2) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MONITOR_SPECIAL_CYCLE), + gShellDebug1HiiHandle, + (*Command & BIT3) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MEM_WRITE_INVALIDATE), + gShellDebug1HiiHandle, + (*Command & BIT4) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_PALETTE_SNOOPING), + gShellDebug1HiiHandle, + (*Command & BIT5) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_ASSERT_PERR), + gShellDebug1HiiHandle, + (*Command & BIT6) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_DO_ADDR_STEPPING), + gShellDebug1HiiHandle, + (*Command & BIT7) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SERR_DRIVER), + gShellDebug1HiiHandle, + (*Command & BIT8) != 0 + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_FAST_BACK_2), + gShellDebug1HiiHandle, + (*Command & BIT9) != 0 + ); + + return EFI_SUCCESS; +} + +/** + Explain each meaningful bit of register Bridge Control. + + @param[in] BridgeControl Points to the content of register Bridge Control. + @param[in] HeaderType The headertype. + + @retval EFI_SUCCESS The command completed successfully. +**/ +EFI_STATUS +PciExplainBridgeControl ( + IN UINT16 *BridgeControl, + IN PCI_HEADER_TYPE HeaderType + ) +{ + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_BRIDGE_CONTROL), + gShellDebug1HiiHandle, + INDEX_OF (BridgeControl), + *BridgeControl + ); + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_PARITY_ERROR), + gShellDebug1HiiHandle, + (*BridgeControl & BIT0) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SERR_ENABLE), + gShellDebug1HiiHandle, + (*BridgeControl & BIT1) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_ISA_ENABLE), + gShellDebug1HiiHandle, + (*BridgeControl & BIT2) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_VGA_ENABLE), + gShellDebug1HiiHandle, + (*BridgeControl & BIT3) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_MASTER_ABORT), + gShellDebug1HiiHandle, + (*BridgeControl & BIT5) != 0 + ); + + // + // Register Bridge Control has some slight differences between P2P bridge + // and Cardbus bridge from bit 6 to bit 11. + // + if (HeaderType == PciP2pBridge) { + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SECONDARY_BUS_RESET), + gShellDebug1HiiHandle, + (*BridgeControl & BIT6) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_FAST_ENABLE), + gShellDebug1HiiHandle, + (*BridgeControl & BIT7) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_PRIMARY_DISCARD_TIMER), + gShellDebug1HiiHandle, + (*BridgeControl & BIT8)!=0 ? L"2^10" : L"2^15" + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_SECONDARY_DISCARD_TIMER), + gShellDebug1HiiHandle, + (*BridgeControl & BIT9)!=0 ? L"2^10" : L"2^15" + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_DISCARD_TIMER_STATUS), + gShellDebug1HiiHandle, + (*BridgeControl & BIT10) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_DISCARD_TIMER_SERR), + gShellDebug1HiiHandle, + (*BridgeControl & BIT11) != 0 + ); + + } else { + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_CARDBUS_RESET), + gShellDebug1HiiHandle, + (*BridgeControl & BIT6) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_IREQ_ENABLE), + gShellDebug1HiiHandle, + (*BridgeControl & BIT7) != 0 + ); + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_PCI2_WRITE_POSTING_ENABLE), + gShellDebug1HiiHandle, + (*BridgeControl & BIT10) != 0 + ); + } + + return EFI_SUCCESS; +} + +/** + Locate capability register block per capability ID. + + @param[in] ConfigSpace Data in PCI configuration space. + @param[in] CapabilityId The capability ID. + + @return The offset of the register block per capability ID, + or 0 if the register block cannot be found. +**/ +UINT8 +LocatePciCapability ( + IN PCI_CONFIG_SPACE *ConfigSpace, + IN UINT8 CapabilityId + ) +{ + UINT8 CapabilityPtr; + EFI_PCI_CAPABILITY_HDR *CapabilityEntry; + + // + // To check the cpability of this device supports + // + if ((ConfigSpace->Common.Status & EFI_PCI_STATUS_CAPABILITY) == 0) { + return 0; + } + + switch ((PCI_HEADER_TYPE)(ConfigSpace->Common.HeaderType & 0x7f)) { + case PciDevice: + CapabilityPtr = ConfigSpace->NonCommon.Device.CapabilityPtr; + break; + case PciP2pBridge: + CapabilityPtr = ConfigSpace->NonCommon.Bridge.CapabilityPtr; + break; + case PciCardBusBridge: + CapabilityPtr = ConfigSpace->NonCommon.CardBus.Cap_Ptr; + break; + default: + return 0; + } + + while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) { + CapabilityEntry = (EFI_PCI_CAPABILITY_HDR *) ((UINT8 *) ConfigSpace + CapabilityPtr); + if (CapabilityEntry->CapabilityID == CapabilityId) { + return CapabilityPtr; + } + + // + // Certain PCI device may incorrectly have capability pointing to itself, + // break to avoid dead loop. + // + if (CapabilityPtr == CapabilityEntry->NextItemPtr) { + break; + } + + CapabilityPtr = CapabilityEntry->NextItemPtr; + } + + return 0; +} + +/** + Print out information of the capability information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieCapReg ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + CHAR16 *DevicePortType; + + ShellPrintEx (-1, -1, + L" Capability Version(3:0): %E0x%04x%N\r\n", + PciExpressCap->Capability.Bits.Version + ); + if (PciExpressCap->Capability.Bits.DevicePortType < ARRAY_SIZE (DevicePortTypeTable)) { + DevicePortType = DevicePortTypeTable[PciExpressCap->Capability.Bits.DevicePortType]; + } else { + DevicePortType = L"Unknown Type"; + } + ShellPrintEx (-1, -1, + L" Device/PortType(7:4): %E%s%N\r\n", + DevicePortType + ); + // + // 'Slot Implemented' is only valid for: + // a) Root Port of PCI Express Root Complex, or + // b) Downstream Port of PCI Express Switch + // + if (PciExpressCap->Capability.Bits.DevicePortType== PCIE_DEVICE_PORT_TYPE_ROOT_PORT || + PciExpressCap->Capability.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT) { + ShellPrintEx (-1, -1, + L" Slot Implemented(8): %E%d%N\r\n", + PciExpressCap->Capability.Bits.SlotImplemented + ); + } + ShellPrintEx (-1, -1, + L" Interrupt Message Number(13:9): %E0x%05x%N\r\n", + PciExpressCap->Capability.Bits.InterruptMessageNumber + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device capability information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieDeviceCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + UINT8 DevicePortType; + UINT8 L0sLatency; + UINT8 L1Latency; + + DevicePortType = (UINT8)PciExpressCap->Capability.Bits.DevicePortType; + ShellPrintEx (-1, -1, L" Max_Payload_Size Supported(2:0): "); + if (PciExpressCap->DeviceCapability.Bits.MaxPayloadSize < 6) { + ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PciExpressCap->DeviceCapability.Bits.MaxPayloadSize + 7)); + } else { + ShellPrintEx (-1, -1, L"%EUnknown%N\r\n"); + } + ShellPrintEx (-1, -1, + L" Phantom Functions Supported(4:3): %E%d%N\r\n", + PciExpressCap->DeviceCapability.Bits.PhantomFunctions + ); + ShellPrintEx (-1, -1, + L" Extended Tag Field Supported(5): %E%d-bit Tag field supported%N\r\n", + PciExpressCap->DeviceCapability.Bits.ExtendedTagField ? 8 : 5 + ); + // + // Endpoint L0s and L1 Acceptable Latency is only valid for Endpoint + // + if (IS_PCIE_ENDPOINT (DevicePortType)) { + L0sLatency = (UINT8)PciExpressCap->DeviceCapability.Bits.EndpointL0sAcceptableLatency; + L1Latency = (UINT8)PciExpressCap->DeviceCapability.Bits.EndpointL1AcceptableLatency; + ShellPrintEx (-1, -1, L" Endpoint L0s Acceptable Latency(8:6): "); + if (L0sLatency < 4) { + ShellPrintEx (-1, -1, L"%EMaximum of %d ns%N\r\n", 1 << (L0sLatency + 6)); + } else { + if (L0sLatency < 7) { + ShellPrintEx (-1, -1, L"%EMaximum of %d us%N\r\n", 1 << (L0sLatency - 3)); + } else { + ShellPrintEx (-1, -1, L"%ENo limit%N\r\n"); + } + } + ShellPrintEx (-1, -1, L" Endpoint L1 Acceptable Latency(11:9): "); + if (L1Latency < 7) { + ShellPrintEx (-1, -1, L"%EMaximum of %d us%N\r\n", 1 << (L1Latency + 1)); + } else { + ShellPrintEx (-1, -1, L"%ENo limit%N\r\n"); + } + } + ShellPrintEx (-1, -1, + L" Role-based Error Reporting(15): %E%d%N\r\n", + PciExpressCap->DeviceCapability.Bits.RoleBasedErrorReporting + ); + // + // Only valid for Upstream Port: + // a) Captured Slot Power Limit Value + // b) Captured Slot Power Scale + // + if (DevicePortType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) { + ShellPrintEx (-1, -1, + L" Captured Slot Power Limit Value(25:18): %E0x%02x%N\r\n", + PciExpressCap->DeviceCapability.Bits.CapturedSlotPowerLimitValue + ); + ShellPrintEx (-1, -1, + L" Captured Slot Power Limit Scale(27:26): %E%s%N\r\n", + SlotPwrLmtScaleTable[PciExpressCap->DeviceCapability.Bits.CapturedSlotPowerLimitScale] + ); + } + // + // Function Level Reset Capability is only valid for Endpoint + // + if (IS_PCIE_ENDPOINT (DevicePortType)) { + ShellPrintEx (-1, -1, + L" Function Level Reset Capability(28): %E%d%N\r\n", + PciExpressCap->DeviceCapability.Bits.FunctionLevelReset + ); + } + return EFI_SUCCESS; +} + +/** + Print out information of the device control information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieDeviceControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" Correctable Error Reporting Enable(0): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.CorrectableError + ); + ShellPrintEx (-1, -1, + L" Non-Fatal Error Reporting Enable(1): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.NonFatalError + ); + ShellPrintEx (-1, -1, + L" Fatal Error Reporting Enable(2): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.FatalError + ); + ShellPrintEx (-1, -1, + L" Unsupported Request Reporting Enable(3): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.UnsupportedRequest + ); + ShellPrintEx (-1, -1, + L" Enable Relaxed Ordering(4): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.RelaxedOrdering + ); + ShellPrintEx (-1, -1, L" Max_Payload_Size(7:5): "); + if (PciExpressCap->DeviceControl.Bits.MaxPayloadSize < 6) { + ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PciExpressCap->DeviceControl.Bits.MaxPayloadSize + 7)); + } else { + ShellPrintEx (-1, -1, L"%EUnknown%N\r\n"); + } + ShellPrintEx (-1, -1, + L" Extended Tag Field Enable(8): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.ExtendedTagField + ); + ShellPrintEx (-1, -1, + L" Phantom Functions Enable(9): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.PhantomFunctions + ); + ShellPrintEx (-1, -1, + L" Auxiliary (AUX) Power PM Enable(10): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.AuxPower + ); + ShellPrintEx (-1, -1, + L" Enable No Snoop(11): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.NoSnoop + ); + ShellPrintEx (-1, -1, L" Max_Read_Request_Size(14:12): "); + if (PciExpressCap->DeviceControl.Bits.MaxReadRequestSize < 6) { + ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PciExpressCap->DeviceControl.Bits.MaxReadRequestSize + 7)); + } else { + ShellPrintEx (-1, -1, L"%EUnknown%N\r\n"); + } + // + // Read operation is only valid for PCI Express to PCI/PCI-X Bridges + // + if (PciExpressCap->Capability.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE) { + ShellPrintEx (-1, -1, + L" Bridge Configuration Retry Enable(15): %E%d%N\r\n", + PciExpressCap->DeviceControl.Bits.BridgeConfigurationRetryOrFunctionLevelReset + ); + } + return EFI_SUCCESS; +} + +/** + Print out information of the device status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieDeviceStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" Correctable Error Detected(0): %E%d%N\r\n", + PciExpressCap->DeviceStatus.Bits.CorrectableError + ); + ShellPrintEx (-1, -1, + L" Non-Fatal Error Detected(1): %E%d%N\r\n", + PciExpressCap->DeviceStatus.Bits.NonFatalError + ); + ShellPrintEx (-1, -1, + L" Fatal Error Detected(2): %E%d%N\r\n", + PciExpressCap->DeviceStatus.Bits.FatalError + ); + ShellPrintEx (-1, -1, + L" Unsupported Request Detected(3): %E%d%N\r\n", + PciExpressCap->DeviceStatus.Bits.UnsupportedRequest + ); + ShellPrintEx (-1, -1, + L" AUX Power Detected(4): %E%d%N\r\n", + PciExpressCap->DeviceStatus.Bits.AuxPower + ); + ShellPrintEx (-1, -1, + L" Transactions Pending(5): %E%d%N\r\n", + PciExpressCap->DeviceStatus.Bits.TransactionsPending + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device link information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieLinkCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + CHAR16 *MaxLinkSpeed; + CHAR16 *AspmValue; + + switch (PciExpressCap->LinkCapability.Bits.MaxLinkSpeed) { + case 1: + MaxLinkSpeed = L"2.5 GT/s"; + break; + case 2: + MaxLinkSpeed = L"5.0 GT/s"; + break; + case 3: + MaxLinkSpeed = L"8.0 GT/s"; + break; + default: + MaxLinkSpeed = L"Unknown"; + break; + } + ShellPrintEx (-1, -1, + L" Maximum Link Speed(3:0): %E%s%N\r\n", + MaxLinkSpeed + ); + ShellPrintEx (-1, -1, + L" Maximum Link Width(9:4): %Ex%d%N\r\n", + PciExpressCap->LinkCapability.Bits.MaxLinkWidth + ); + switch (PciExpressCap->LinkCapability.Bits.Aspm) { + case 0: + AspmValue = L"Not"; + break; + case 1: + AspmValue = L"L0s"; + break; + case 2: + AspmValue = L"L1"; + break; + case 3: + AspmValue = L"L0s and L1"; + break; + default: + AspmValue = L"Reserved"; + break; + } + ShellPrintEx (-1, -1, + L" Active State Power Management Support(11:10): %E%s Supported%N\r\n", + AspmValue + ); + ShellPrintEx (-1, -1, + L" L0s Exit Latency(14:12): %E%s%N\r\n", + L0sLatencyStrTable[PciExpressCap->LinkCapability.Bits.L0sExitLatency] + ); + ShellPrintEx (-1, -1, + L" L1 Exit Latency(17:15): %E%s%N\r\n", + L1LatencyStrTable[PciExpressCap->LinkCapability.Bits.L1ExitLatency] + ); + ShellPrintEx (-1, -1, + L" Clock Power Management(18): %E%d%N\r\n", + PciExpressCap->LinkCapability.Bits.ClockPowerManagement + ); + ShellPrintEx (-1, -1, + L" Surprise Down Error Reporting Capable(19): %E%d%N\r\n", + PciExpressCap->LinkCapability.Bits.SurpriseDownError + ); + ShellPrintEx (-1, -1, + L" Data Link Layer Link Active Reporting Capable(20): %E%d%N\r\n", + PciExpressCap->LinkCapability.Bits.DataLinkLayerLinkActive + ); + ShellPrintEx (-1, -1, + L" Link Bandwidth Notification Capability(21): %E%d%N\r\n", + PciExpressCap->LinkCapability.Bits.LinkBandwidthNotification + ); + ShellPrintEx (-1, -1, + L" Port Number(31:24): %E0x%02x%N\r\n", + PciExpressCap->LinkCapability.Bits.PortNumber + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device link control information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieLinkControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + UINT8 DevicePortType; + + DevicePortType = (UINT8)PciExpressCap->Capability.Bits.DevicePortType; + ShellPrintEx (-1, -1, + L" Active State Power Management Control(1:0): %E%s%N\r\n", + ASPMCtrlStrTable[PciExpressCap->LinkControl.Bits.AspmControl] + ); + // + // RCB is not applicable to switches + // + if (!IS_PCIE_SWITCH(DevicePortType)) { + ShellPrintEx (-1, -1, + L" Read Completion Boundary (RCB)(3): %E%d byte%N\r\n", + 1 << (PciExpressCap->LinkControl.Bits.ReadCompletionBoundary + 6) + ); + } + // + // Link Disable is reserved on + // a) Endpoints + // b) PCI Express to PCI/PCI-X bridges + // c) Upstream Ports of Switches + // + if (!IS_PCIE_ENDPOINT (DevicePortType) && + DevicePortType != PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT && + DevicePortType != PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE) { + ShellPrintEx (-1, -1, + L" Link Disable(4): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.LinkDisable + ); + } + ShellPrintEx (-1, -1, + L" Common Clock Configuration(6): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.CommonClockConfiguration + ); + ShellPrintEx (-1, -1, + L" Extended Synch(7): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.ExtendedSynch + ); + ShellPrintEx (-1, -1, + L" Enable Clock Power Management(8): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.ClockPowerManagement + ); + ShellPrintEx (-1, -1, + L" Hardware Autonomous Width Disable(9): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.HardwareAutonomousWidthDisable + ); + ShellPrintEx (-1, -1, + L" Link Bandwidth Management Interrupt Enable(10): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.LinkBandwidthManagementInterrupt + ); + ShellPrintEx (-1, -1, + L" Link Autonomous Bandwidth Interrupt Enable(11): %E%d%N\r\n", + PciExpressCap->LinkControl.Bits.LinkAutonomousBandwidthInterrupt + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device link status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieLinkStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + CHAR16 *CurLinkSpeed; + + switch (PciExpressCap->LinkStatus.Bits.CurrentLinkSpeed) { + case 1: + CurLinkSpeed = L"2.5 GT/s"; + break; + case 2: + CurLinkSpeed = L"5.0 GT/s"; + break; + case 3: + CurLinkSpeed = L"8.0 GT/s"; + break; + default: + CurLinkSpeed = L"Reserved"; + break; + } + ShellPrintEx (-1, -1, + L" Current Link Speed(3:0): %E%s%N\r\n", + CurLinkSpeed + ); + ShellPrintEx (-1, -1, + L" Negotiated Link Width(9:4): %Ex%d%N\r\n", + PciExpressCap->LinkStatus.Bits.NegotiatedLinkWidth + ); + ShellPrintEx (-1, -1, + L" Link Training(11): %E%d%N\r\n", + PciExpressCap->LinkStatus.Bits.LinkTraining + ); + ShellPrintEx (-1, -1, + L" Slot Clock Configuration(12): %E%d%N\r\n", + PciExpressCap->LinkStatus.Bits.SlotClockConfiguration + ); + ShellPrintEx (-1, -1, + L" Data Link Layer Link Active(13): %E%d%N\r\n", + PciExpressCap->LinkStatus.Bits.DataLinkLayerLinkActive + ); + ShellPrintEx (-1, -1, + L" Link Bandwidth Management Status(14): %E%d%N\r\n", + PciExpressCap->LinkStatus.Bits.LinkBandwidthManagement + ); + ShellPrintEx (-1, -1, + L" Link Autonomous Bandwidth Status(15): %E%d%N\r\n", + PciExpressCap->LinkStatus.Bits.LinkAutonomousBandwidth + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device slot information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieSlotCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" Attention Button Present(0): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.AttentionButton + ); + ShellPrintEx (-1, -1, + L" Power Controller Present(1): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.PowerController + ); + ShellPrintEx (-1, -1, + L" MRL Sensor Present(2): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.MrlSensor + ); + ShellPrintEx (-1, -1, + L" Attention Indicator Present(3): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.AttentionIndicator + ); + ShellPrintEx (-1, -1, + L" Power Indicator Present(4): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.PowerIndicator + ); + ShellPrintEx (-1, -1, + L" Hot-Plug Surprise(5): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.HotPlugSurprise + ); + ShellPrintEx (-1, -1, + L" Hot-Plug Capable(6): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.HotPlugCapable + ); + ShellPrintEx (-1, -1, + L" Slot Power Limit Value(14:7): %E0x%02x%N\r\n", + PciExpressCap->SlotCapability.Bits.SlotPowerLimitValue + ); + ShellPrintEx (-1, -1, + L" Slot Power Limit Scale(16:15): %E%s%N\r\n", + SlotPwrLmtScaleTable[PciExpressCap->SlotCapability.Bits.SlotPowerLimitScale] + ); + ShellPrintEx (-1, -1, + L" Electromechanical Interlock Present(17): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.ElectromechanicalInterlock + ); + ShellPrintEx (-1, -1, + L" No Command Completed Support(18): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.NoCommandCompleted + ); + ShellPrintEx (-1, -1, + L" Physical Slot Number(31:19): %E%d%N\r\n", + PciExpressCap->SlotCapability.Bits.PhysicalSlotNumber + ); + + return EFI_SUCCESS; +} + +/** + Print out information of the device slot control information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieSlotControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" Attention Button Pressed Enable(0): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.AttentionButtonPressed + ); + ShellPrintEx (-1, -1, + L" Power Fault Detected Enable(1): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.PowerFaultDetected + ); + ShellPrintEx (-1, -1, + L" MRL Sensor Changed Enable(2): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.MrlSensorChanged + ); + ShellPrintEx (-1, -1, + L" Presence Detect Changed Enable(3): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.PresenceDetectChanged + ); + ShellPrintEx (-1, -1, + L" Command Completed Interrupt Enable(4): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.CommandCompletedInterrupt + ); + ShellPrintEx (-1, -1, + L" Hot-Plug Interrupt Enable(5): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.HotPlugInterrupt + ); + ShellPrintEx (-1, -1, + L" Attention Indicator Control(7:6): %E%s%N\r\n", + IndicatorTable[ + PciExpressCap->SlotControl.Bits.AttentionIndicator] + ); + ShellPrintEx (-1, -1, + L" Power Indicator Control(9:8): %E%s%N\r\n", + IndicatorTable[PciExpressCap->SlotControl.Bits.PowerIndicator] + ); + ShellPrintEx (-1, -1, L" Power Controller Control(10): %EPower "); + if ( + PciExpressCap->SlotControl.Bits.PowerController) { + ShellPrintEx (-1, -1, L"Off%N\r\n"); + } else { + ShellPrintEx (-1, -1, L"On%N\r\n"); + } + ShellPrintEx (-1, -1, + L" Electromechanical Interlock Control(11): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.ElectromechanicalInterlock + ); + ShellPrintEx (-1, -1, + L" Data Link Layer State Changed Enable(12): %E%d%N\r\n", + PciExpressCap->SlotControl.Bits.DataLinkLayerStateChanged + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device slot status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieSlotStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" Attention Button Pressed(0): %E%d%N\r\n", + PciExpressCap->SlotStatus.Bits.AttentionButtonPressed + ); + ShellPrintEx (-1, -1, + L" Power Fault Detected(1): %E%d%N\r\n", + PciExpressCap->SlotStatus.Bits.PowerFaultDetected + ); + ShellPrintEx (-1, -1, + L" MRL Sensor Changed(2): %E%d%N\r\n", + PciExpressCap->SlotStatus.Bits.MrlSensorChanged + ); + ShellPrintEx (-1, -1, + L" Presence Detect Changed(3): %E%d%N\r\n", + PciExpressCap->SlotStatus.Bits.PresenceDetectChanged + ); + ShellPrintEx (-1, -1, + L" Command Completed(4): %E%d%N\r\n", + PciExpressCap->SlotStatus.Bits.CommandCompleted + ); + ShellPrintEx (-1, -1, L" MRL Sensor State(5): %EMRL "); + if ( + PciExpressCap->SlotStatus.Bits.MrlSensor) { + ShellPrintEx (-1, -1, L" Opened%N\r\n"); + } else { + ShellPrintEx (-1, -1, L" Closed%N\r\n"); + } + ShellPrintEx (-1, -1, L" Presence Detect State(6): "); + if ( + PciExpressCap->SlotStatus.Bits.PresenceDetect) { + ShellPrintEx (-1, -1, L"%ECard Present in slot%N\r\n"); + } else { + ShellPrintEx (-1, -1, L"%ESlot Empty%N\r\n"); + } + ShellPrintEx (-1, -1, L" Electromechanical Interlock Status(7): %EElectromechanical Interlock "); + if ( + PciExpressCap->SlotStatus.Bits.ElectromechanicalInterlock) { + ShellPrintEx (-1, -1, L"Engaged%N\r\n"); + } else { + ShellPrintEx (-1, -1, L"Disengaged%N\r\n"); + } + ShellPrintEx (-1, -1, + L" Data Link Layer State Changed(8): %E%d%N\r\n", + PciExpressCap->SlotStatus.Bits.DataLinkLayerStateChanged + ); + return EFI_SUCCESS; +} + +/** + Print out information of the device root information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieRootControl ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" System Error on Correctable Error Enable(0): %E%d%N\r\n", + PciExpressCap->RootControl.Bits.SystemErrorOnCorrectableError + ); + ShellPrintEx (-1, -1, + L" System Error on Non-Fatal Error Enable(1): %E%d%N\r\n", + PciExpressCap->RootControl.Bits.SystemErrorOnNonFatalError + ); + ShellPrintEx (-1, -1, + L" System Error on Fatal Error Enable(2): %E%d%N\r\n", + PciExpressCap->RootControl.Bits.SystemErrorOnFatalError + ); + ShellPrintEx (-1, -1, + L" PME Interrupt Enable(3): %E%d%N\r\n", + PciExpressCap->RootControl.Bits.PmeInterrupt + ); + ShellPrintEx (-1, -1, + L" CRS Software Visibility Enable(4): %E%d%N\r\n", + PciExpressCap->RootControl.Bits.CrsSoftwareVisibility + ); + + return EFI_SUCCESS; +} + +/** + Print out information of the device root capability information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieRootCap ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" CRS Software Visibility(0): %E%d%N\r\n", + PciExpressCap->RootCapability.Bits.CrsSoftwareVisibility + ); + + return EFI_SUCCESS; +} + +/** + Print out information of the device root status information. + + @param[in] PciExpressCap The pointer to the structure about the device. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ExplainPcieRootStatus ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + ShellPrintEx (-1, -1, + L" PME Requester ID(15:0): %E0x%04x%N\r\n", + PciExpressCap->RootStatus.Bits.PmeRequesterId + ); + ShellPrintEx (-1, -1, + L" PME Status(16): %E%d%N\r\n", + PciExpressCap->RootStatus.Bits.PmeStatus + ); + ShellPrintEx (-1, -1, + L" PME Pending(17): %E%d%N\r\n", + PciExpressCap->RootStatus.Bits.PmePending + ); + return EFI_SUCCESS; +} + +/** + Function to interpret and print out the link control structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityLinkControl ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_LINK_CONTROL), + gShellDebug1HiiHandle, + Header->RootComplexLinkCapabilities, + Header->RootComplexLinkControl, + Header->RootComplexLinkStatus + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the power budgeting structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityPowerBudgeting ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_POWER), + gShellDebug1HiiHandle, + Header->DataSelect, + Header->Data, + Header->PowerBudgetCapability + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the ACS structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityAcs ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED *Header; + UINT16 VectorSize; + UINT16 LoopCounter; + + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED*)HeaderAddress; + VectorSize = 0; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_ACS), + gShellDebug1HiiHandle, + Header->AcsCapability, + Header->AcsControl + ); + if (PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_CONTROL(Header)) { + VectorSize = PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_VECTOR_SIZE(Header); + if (VectorSize == 0) { + VectorSize = 256; + } + for (LoopCounter = 0 ; LoopCounter * 8 < VectorSize ; LoopCounter++) { + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_ACS2), + gShellDebug1HiiHandle, + LoopCounter + 1, + Header->EgressControlVectorArray[LoopCounter] + ); + } + } + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED) + (VectorSize / 8) - 1, + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the latency tolerance reporting structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityLatencyToleranceReporting ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_LAT), + gShellDebug1HiiHandle, + Header->MaxSnoopLatency, + Header->MaxNoSnoopLatency + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the serial number structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilitySerialNumber ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_SN), + gShellDebug1HiiHandle, + Header->SerialNumber + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the RCRB structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityRcrb ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_RCRB), + gShellDebug1HiiHandle, + Header->VendorId, + Header->DeviceId, + Header->RcrbCapabilities, + Header->RcrbControl + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the vendor specific structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityVendorSpecific ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_VEN), + gShellDebug1HiiHandle, + Header->VendorSpecificHeader + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_GET_SIZE(Header), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the Event Collector Endpoint Association structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityECEA ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_ECEA), + gShellDebug1HiiHandle, + Header->AssociationBitmap + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the ARI structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityAri ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_ARI), + gShellDebug1HiiHandle, + Header->AriCapability, + Header->AriControl + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the DPA structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityDynamicPowerAllocation ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION *Header; + UINT8 LinkCount; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_DPA), + gShellDebug1HiiHandle, + Header->DpaCapability, + Header->DpaLatencyIndicator, + Header->DpaStatus, + Header->DpaControl + ); + for (LinkCount = 0 ; LinkCount < PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(Header) + 1 ; LinkCount++) { + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_DPA2), + gShellDebug1HiiHandle, + LinkCount+1, + Header->DpaPowerAllocationArray[LinkCount] + ); + } + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION) - 1 + PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(Header), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the link declaration structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityLinkDeclaration ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION *Header; + UINT8 LinkCount; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_LINK_DECLAR), + gShellDebug1HiiHandle, + Header->ElementSelfDescription + ); + + for (LinkCount = 0 ; LinkCount < PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(Header) ; LinkCount++) { + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_LINK_DECLAR2), + gShellDebug1HiiHandle, + LinkCount+1, + Header->LinkEntry[LinkCount] + ); + } + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION) + (PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(Header)-1)*sizeof(UINT32), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the Advanced Error Reporting structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityAer ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_AER), + gShellDebug1HiiHandle, + Header->UncorrectableErrorStatus, + Header->UncorrectableErrorMask, + Header->UncorrectableErrorSeverity, + Header->CorrectableErrorStatus, + Header->CorrectableErrorMask, + Header->AdvancedErrorCapabilitiesAndControl, + Header->HeaderLog[0], + Header->HeaderLog[1], + Header->HeaderLog[2], + Header->HeaderLog[3], + Header->RootErrorCommand, + Header->RootErrorStatus, + Header->ErrorSourceIdentification, + Header->CorrectableErrorSourceIdentification, + Header->TlpPrefixLog[0], + Header->TlpPrefixLog[1], + Header->TlpPrefixLog[2], + Header->TlpPrefixLog[3] + ); + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING), + (VOID *) (HeaderAddress) + ); + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the multicast structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. + @param[in] PciExpressCapPtr The address of the PCIe capabilities structure. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityMulticast ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress, + IN CONST PCI_CAPABILITY_PCIEXP *PciExpressCapPtr + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_MULTICAST), + gShellDebug1HiiHandle, + Header->MultiCastCapability, + Header->MulticastControl, + Header->McBaseAddress, + Header->McReceiveAddress, + Header->McBlockAll, + Header->McBlockUntranslated, + Header->McOverlayBar + ); + + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST), + (VOID *) (HeaderAddress) + ); + + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the virtual channel and multi virtual channel structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityVirtualChannel ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY *Header; + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC *CapabilityItem; + UINT32 ItemCount; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_VC_BASE), + gShellDebug1HiiHandle, + Header->ExtendedVcCount, + Header->PortVcCapability1, + Header->PortVcCapability2, + Header->VcArbTableOffset, + Header->PortVcControl, + Header->PortVcStatus + ); + for (ItemCount = 0 ; ItemCount < Header->ExtendedVcCount ; ItemCount++) { + CapabilityItem = &Header->Capability[ItemCount]; + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_VC_ITEM), + gShellDebug1HiiHandle, + ItemCount+1, + CapabilityItem->VcResourceCapability, + CapabilityItem->PortArbTableOffset, + CapabilityItem->VcResourceControl, + CapabilityItem->VcResourceStatus + ); + } + + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY) + + Header->ExtendedVcCount * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC), + (VOID *) (HeaderAddress) + ); + + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the resizeable bar structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityResizeableBar ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR *Header; + UINT32 ItemCount; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR*)HeaderAddress; + + for (ItemCount = 0 ; ItemCount < (UINT32)GET_NUMBER_RESIZABLE_BARS(Header) ; ItemCount++) { + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_RESIZE_BAR), + gShellDebug1HiiHandle, + ItemCount+1, + Header->Capability[ItemCount].ResizableBarCapability, + Header->Capability[ItemCount].ResizableBarControl + ); + } + + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + (UINT32)GET_NUMBER_RESIZABLE_BARS(Header) * sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY), + (VOID *) (HeaderAddress) + ); + + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the TPH structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilityTph ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_TPH), + gShellDebug1HiiHandle, + Header->TphRequesterCapability, + Header->TphRequesterControl + ); + DumpHex ( + 8, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)Header->TphStTable - (UINT8*)HeadersBaseAddress), + GET_TPH_TABLE_SIZE(Header), + (VOID *)Header->TphStTable + ); + + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH) + GET_TPH_TABLE_SIZE(Header) - sizeof(UINT16), + (VOID *) (HeaderAddress) + ); + + return (EFI_SUCCESS); +} + +/** + Function to interpret and print out the secondary PCIe capability structure + + @param[in] HeaderAddress The Address of this capability header. + @param[in] HeadersBaseAddress The address of all the extended capability headers. + @param[in] PciExpressCapPtr The address of the PCIe capabilities structure. +**/ +EFI_STATUS +PrintInterpretedExtendedCompatibilitySecondary ( + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress, + IN CONST PCI_CAPABILITY_PCIEXP *PciExpressCap + ) +{ + CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE *Header; + Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE*)HeaderAddress; + + ShellPrintHiiEx( + -1, -1, NULL, + STRING_TOKEN (STR_PCI_EXT_CAP_SECONDARY), + gShellDebug1HiiHandle, + Header->LinkControl3.Uint32, + Header->LaneErrorStatus + ); + DumpHex ( + 8, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)Header->EqualizationControl - (UINT8*)HeadersBaseAddress), + PciExpressCap->LinkCapability.Bits.MaxLinkWidth * sizeof (PCI_EXPRESS_REG_LANE_EQUALIZATION_CONTROL), + (VOID *)Header->EqualizationControl + ); + + DumpHex ( + 4, + EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress), + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE) - sizeof (Header->EqualizationControl) + + PciExpressCap->LinkCapability.Bits.MaxLinkWidth * sizeof (PCI_EXPRESS_REG_LANE_EQUALIZATION_CONTROL), + (VOID *) (HeaderAddress) + ); + + return (EFI_SUCCESS); +} + +/** + Display Pcie extended capability details + + @param[in] HeadersBaseAddress The address of all the extended capability headers. + @param[in] HeaderAddress The address of this capability header. + @param[in] PciExpressCapPtr The address of the PCIe capabilities structure. +**/ +EFI_STATUS +PrintPciExtendedCapabilityDetails( + IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress, + IN CONST PCI_EXP_EXT_HDR *HeaderAddress, + IN CONST PCI_CAPABILITY_PCIEXP *PciExpressCapPtr + ) +{ + switch (HeaderAddress->CapabilityId){ + case PCI_EXPRESS_EXTENDED_CAPABILITY_ADVANCED_ERROR_REPORTING_ID: + return PrintInterpretedExtendedCompatibilityAer(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_CONTROL_ID: + return PrintInterpretedExtendedCompatibilityLinkControl(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_ID: + return PrintInterpretedExtendedCompatibilityLinkDeclaration(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_SERIAL_NUMBER_ID: + return PrintInterpretedExtendedCompatibilitySerialNumber(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_POWER_BUDGETING_ID: + return PrintInterpretedExtendedCompatibilityPowerBudgeting(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_ID: + return PrintInterpretedExtendedCompatibilityAcs(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_LATENCE_TOLERANCE_REPORTING_ID: + return PrintInterpretedExtendedCompatibilityLatencyToleranceReporting(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_ID: + return PrintInterpretedExtendedCompatibilityAri(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_RCRB_HEADER_ID: + return PrintInterpretedExtendedCompatibilityRcrb(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID: + return PrintInterpretedExtendedCompatibilityVendorSpecific(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_ID: + return PrintInterpretedExtendedCompatibilityDynamicPowerAllocation(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION_ID: + return PrintInterpretedExtendedCompatibilityECEA(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_VIRTUAL_CHANNEL_ID: + case PCI_EXPRESS_EXTENDED_CAPABILITY_MULTI_FUNCTION_VIRTUAL_CHANNEL_ID: + return PrintInterpretedExtendedCompatibilityVirtualChannel(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_MULTICAST_ID: + // + // should only be present if PCIE_CAP_DEVICEPORT_TYPE(PciExpressCapPtr->PcieCapReg) == 0100b, 0101b, or 0110b + // + return PrintInterpretedExtendedCompatibilityMulticast(HeaderAddress, HeadersBaseAddress, PciExpressCapPtr); + case PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID: + return PrintInterpretedExtendedCompatibilityResizeableBar(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_TPH_ID: + return PrintInterpretedExtendedCompatibilityTph(HeaderAddress, HeadersBaseAddress); + case PCI_EXPRESS_EXTENDED_CAPABILITY_SECONDARY_PCIE_ID: + return PrintInterpretedExtendedCompatibilitySecondary(HeaderAddress, HeadersBaseAddress, PciExpressCapPtr); + default: + ShellPrintEx (-1, -1, + L"Unknown PCIe extended capability ID (%04xh). No interpretation available.\r\n", + HeaderAddress->CapabilityId + ); + return EFI_SUCCESS; + }; + +} + +/** + Display Pcie device structure. + + @param[in] PciExpressCap PCI Express capability buffer. + @param[in] ExtendedConfigSpace PCI Express extended configuration space. + @param[in] ExtendedCapability PCI Express extended capability ID to explain. +**/ +VOID +PciExplainPciExpress ( + IN PCI_CAPABILITY_PCIEXP *PciExpressCap, + IN UINT8 *ExtendedConfigSpace, + IN CONST UINT16 ExtendedCapability + ) +{ + UINT8 DevicePortType; + UINTN Index; + UINT8 *RegAddr; + UINTN RegValue; + PCI_EXP_EXT_HDR *ExtHdr; + + DevicePortType = (UINT8)PciExpressCap->Capability.Bits.DevicePortType; + + ShellPrintEx (-1, -1, L"\r\nPci Express device capability structure:\r\n"); + + for (Index = 0; PcieExplainList[Index].Type < PcieExplainTypeMax; Index++) { + if (ShellGetExecutionBreakFlag()) { + return; + } + RegAddr = (UINT8 *) PciExpressCap + PcieExplainList[Index].Offset; + switch (PcieExplainList[Index].Width) { + case FieldWidthUINT8: + RegValue = *(UINT8 *) RegAddr; + break; + case FieldWidthUINT16: + RegValue = *(UINT16 *) RegAddr; + break; + case FieldWidthUINT32: + RegValue = *(UINT32 *) RegAddr; + break; + default: + RegValue = 0; + break; + } + ShellPrintHiiEx(-1, -1, NULL, + PcieExplainList[Index].Token, + gShellDebug1HiiHandle, + PcieExplainList[Index].Offset, + RegValue + ); + if (PcieExplainList[Index].Func == NULL) { + continue; + } + switch (PcieExplainList[Index].Type) { + case PcieExplainTypeLink: + // + // Link registers should not be used by + // a) Root Complex Integrated Endpoint + // b) Root Complex Event Collector + // + if (DevicePortType == PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT || + DevicePortType == PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR) { + continue; + } + break; + case PcieExplainTypeSlot: + // + // Slot registers are only valid for + // a) Root Port of PCI Express Root Complex + // b) Downstream Port of PCI Express Switch + // and when SlotImplemented bit is set in PCIE cap register. + // + if ((DevicePortType != PCIE_DEVICE_PORT_TYPE_ROOT_PORT && + DevicePortType != PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT) || + !PciExpressCap->Capability.Bits.SlotImplemented) { + continue; + } + break; + case PcieExplainTypeRoot: + // + // Root registers are only valid for + // Root Port of PCI Express Root Complex + // + if (DevicePortType != PCIE_DEVICE_PORT_TYPE_ROOT_PORT) { + continue; + } + break; + default: + break; + } + PcieExplainList[Index].Func (PciExpressCap); + } + + ExtHdr = (PCI_EXP_EXT_HDR*)ExtendedConfigSpace; + while (ExtHdr->CapabilityId != 0 && ExtHdr->CapabilityVersion != 0) { + // + // Process this item + // + if (ExtendedCapability == 0xFFFF || ExtendedCapability == ExtHdr->CapabilityId) { + // + // Print this item + // + PrintPciExtendedCapabilityDetails((PCI_EXP_EXT_HDR*)ExtendedConfigSpace, ExtHdr, PciExpressCap); + } + + // + // Advance to the next item if it exists + // + if (ExtHdr->NextCapabilityOffset != 0) { + ExtHdr = (PCI_EXP_EXT_HDR*)(ExtendedConfigSpace + ExtHdr->NextCapabilityOffset - EFI_PCIE_CAPABILITY_BASE_OFFSET); + } else { + break; + } + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h new file mode 100644 index 0000000..b470b04 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h @@ -0,0 +1,64 @@ +/** @file + Header file for Pci shell Debug1 function. + + Copyright (c) 2013 Hewlett-Packard Development Company, L.P. + Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _EFI_SHELL_PCI_H_ +#define _EFI_SHELL_PCI_H_ + +typedef enum { + PciDevice, + PciP2pBridge, + PciCardBusBridge, + PciUndefined +} PCI_HEADER_TYPE; + +#define INDEX_OF(Field) ((UINT8 *) (Field) - (UINT8 *) mConfigSpace) + +#define IS_PCIE_ENDPOINT(DevicePortType) \ + ((DevicePortType) == PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT || \ + (DevicePortType) == PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT || \ + (DevicePortType) == PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) + +#define IS_PCIE_SWITCH(DevicePortType) \ + ((DevicePortType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) || \ + (DevicePortType == PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT)) + +#pragma pack(1) +// +// Data region after PCI configuration header(for cardbus bridge) +// +typedef struct { + UINT16 SubVendorId; // Subsystem Vendor ID + UINT16 SubSystemId; // Subsystem ID + UINT32 LegacyBase; // Optional 16-Bit PC Card Legacy + // Mode Base Address + // + UINT32 Data[46]; +} PCI_CARDBUS_DATA; + +typedef union { + PCI_DEVICE_HEADER_TYPE_REGION Device; + PCI_BRIDGE_CONTROL_REGISTER Bridge; + PCI_CARDBUS_CONTROL_REGISTER CardBus; +} NON_COMMON_UNION; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Common; + NON_COMMON_UNION NonCommon; + UINT32 Data[48]; +} PCI_CONFIG_SPACE; + +#pragma pack() + +#endif // _PCI_H_ diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c new file mode 100644 index 0000000..2ffa30b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c @@ -0,0 +1,371 @@ +/** @file + Main file for SerMode shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include +#include + +/** + Display information about a serial device by it's handle. + + If HandleValid is FALSE, do all devices. + + @param[in] HandleIdx The handle index for the device. + @param[in] HandleValid TRUE if HandleIdx is valid. + + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +DisplaySettings ( + IN UINTN HandleIdx, + IN BOOLEAN HandleValid + ) +{ + EFI_SERIAL_IO_PROTOCOL *SerialIo; + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_STATUS Status; + UINTN Index; + CHAR16 *StopBits; + CHAR16 Parity; + SHELL_STATUS ShellStatus; + + Handles = NULL; + StopBits = NULL; + + ShellStatus = SHELL_SUCCESS; + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode"); + return SHELL_INVALID_PARAMETER; + } + + for (Index = 0; Index < NoHandles; Index++) { + if (HandleValid) { + if (ConvertHandleIndexToHandle(HandleIdx) != Handles[Index]) { + continue; + } + } + + Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo); + if (!EFI_ERROR (Status)) { + switch (SerialIo->Mode->Parity) { + case DefaultParity: + + Parity = 'D'; + break; + + case NoParity: + + Parity = 'N'; + break; + + case EvenParity: + + Parity = 'E'; + break; + + case OddParity: + + Parity = 'O'; + break; + + case MarkParity: + + Parity = 'M'; + break; + + case SpaceParity: + + Parity = 'S'; + break; + + default: + + Parity = 'U'; + } + + switch (SerialIo->Mode->StopBits) { + case DefaultStopBits: + + StopBits = L"Default"; + break; + + case OneStopBit: + + StopBits = L"1"; + break; + + case TwoStopBits: + + StopBits = L"2"; + break; + + case OneFiveStopBits: + + StopBits = L"1.5"; + break; + + default: + + StopBits = L"Unknown"; + } + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SERMODE_DISPLAY), + gShellDebug1HiiHandle, + ConvertHandleToHandleIndex (Handles[Index]), + Handles[Index], + SerialIo->Mode->BaudRate, + Parity, + SerialIo->Mode->DataBits, + StopBits + ); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode"); + ShellStatus = SHELL_NOT_FOUND; + break; + } + + if (HandleValid) { + break; + } + } + + if (Index == NoHandles) { + if ((NoHandles != 0 && HandleValid) || 0 == NoHandles) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NOT_FOUND), gShellDebug1HiiHandle, L"sermode"); + ShellStatus = SHELL_NOT_FOUND; + } + } + + return ShellStatus; +} + +/** + Function for 'sermode' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSerMode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + UINTN Index; + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_PARITY_TYPE Parity; + EFI_STOP_BITS_TYPE StopBits; + UINTN HandleIdx; + UINTN BaudRate; + UINTN DataBits; + UINTN Value; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Temp; + UINT64 Intermediate; + + ShellStatus = SHELL_SUCCESS; + HandleIdx = 0; + Parity = DefaultParity; + Handles = NULL; + NoHandles = 0; + Index = 0; + Package = NULL; + + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"sermode", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) < 6 && ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"sermode"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) > 6) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"sermode"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Temp = ShellCommandLineGetRawValue(Package, 1); + if (Temp != NULL) { + Status = ShellConvertStringToUint64(Temp, &Intermediate, TRUE, FALSE); + HandleIdx = (UINTN)Intermediate; + Temp = ShellCommandLineGetRawValue(Package, 2); + if (Temp == NULL) { + ShellStatus = DisplaySettings (HandleIdx, TRUE); + goto Done; + } + } else { + ShellStatus = DisplaySettings (0, FALSE); + goto Done; + } + Temp = ShellCommandLineGetRawValue(Package, 2); + if (Temp != NULL) { + BaudRate = ShellStrToUintn(Temp); + } else { + ASSERT(FALSE); + BaudRate = 0; + } + Temp = ShellCommandLineGetRawValue(Package, 3); + if (Temp == NULL || StrLen(Temp)>1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + switch(Temp[0]){ + case 'd': + case 'D': + Parity = DefaultParity; + break; + case 'n': + case 'N': + Parity = NoParity; + break; + case 'e': + case 'E': + Parity = EvenParity; + break; + case 'o': + case 'O': + Parity = OddParity; + break; + case 'm': + case 'M': + Parity = MarkParity; + break; + case 's': + case 'S': + Parity = SpaceParity; + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + Temp = ShellCommandLineGetRawValue(Package, 4); + if (Temp != NULL) { + DataBits = ShellStrToUintn(Temp); + } else { + // + // make sure this is some number not in the list below. + // + DataBits = 0; + } + switch (DataBits) { + case 4: + case 7: + case 8: + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + Temp = ShellCommandLineGetRawValue(Package, 5); + Value = ShellStrToUintn(Temp); + switch (Value) { + case 0: + StopBits = DefaultStopBits; + break; + + case 1: + StopBits = OneStopBit; + break; + + case 2: + StopBits = TwoStopBits; + break; + + case 15: + StopBits = OneFiveStopBits; + break; + + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + for (Index = 0; Index < NoHandles; Index++) { + if (ConvertHandleIndexToHandle (HandleIdx) != Handles[Index]) { + continue; + } + + Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo); + if (!EFI_ERROR (Status)) { + Status = SerialIo->SetAttributes ( + SerialIo, + (UINT64) BaudRate, + SerialIo->Mode->ReceiveFifoDepth, + SerialIo->Mode->Timeout, + Parity, + (UINT8) DataBits, + StopBits + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_INVALID_PARAMETER) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_UNSUPPORTED), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index])); + ShellStatus = SHELL_UNSUPPORTED; + } else if (Status == EFI_DEVICE_ERROR) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_DEV_ERROR), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index])); + ShellStatus = SHELL_ACCESS_DENIED; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_FAIL), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index])); + ShellStatus = SHELL_ACCESS_DENIED; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_HANDLE), gShellDebug1HiiHandle, ConvertHandleToHandleIndex(Handles[Index])); + } + break; + } + } + } + } + + if (ShellStatus == SHELL_SUCCESS && Index == NoHandles) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_BAD_HANDLE), gShellDebug1HiiHandle, L"sermode", HandleIdx); + ShellStatus = SHELL_INVALID_PARAMETER; + } + +Done: + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + if (Handles != NULL) { + FreePool (Handles); + } + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c new file mode 100644 index 0000000..39b6078 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c @@ -0,0 +1,110 @@ +/** @file + Main file for SetSize shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" + +/** + Function for 'setsize' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSetSize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Temp1; + UINTN NewSize; + UINTN LoopVar; + SHELL_FILE_HANDLE FileHandle; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"setsize", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"setsize"); + ShellStatus = SHELL_INVALID_PARAMETER; + NewSize = 0; + } else { + Temp1 = ShellCommandLineGetRawValue(Package, 1); + if (!ShellIsHexOrDecimalNumber(Temp1, FALSE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SIZE_NOT_SPEC), gShellDebug1HiiHandle, L"setsize"); + ShellStatus = SHELL_INVALID_PARAMETER; + NewSize = 0; + } else { + NewSize = ShellStrToUintn(Temp1); + } + } + for (LoopVar = 2 ; LoopVar < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS ; LoopVar++) { + Status = ShellOpenFileByName(ShellCommandLineGetRawValue(Package, LoopVar), &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(Status)) { + Status = ShellOpenFileByName(ShellCommandLineGetRawValue(Package, LoopVar), &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + } + if (EFI_ERROR(Status) && LoopVar == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_SPEC), gShellDebug1HiiHandle, L"setsize"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"setsize", ShellCommandLineGetRawValue(Package, LoopVar)); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } else { + Status = FileHandleSetSize(FileHandle, NewSize); + if (Status == EFI_VOLUME_FULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_VOLUME_FULL), gShellDebug1HiiHandle, L"setsize"); + ShellStatus = SHELL_VOLUME_FULL; + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_SIZE_FAIL), gShellDebug1HiiHandle, L"setsize", ShellCommandLineGetRawValue(Package, LoopVar)); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_SIZE_DONE), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, LoopVar)); + } + ShellCloseFile(&FileHandle); + } + } + + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c new file mode 100644 index 0000000..7589252 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c @@ -0,0 +1,475 @@ +/** @file + Main file for SetVar shell Debug1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-guid", TypeValue}, + {L"-bs", TypeFlag}, + {L"-rt", TypeFlag}, + {L"-nv", TypeFlag}, + {NULL, TypeMax} + }; + +typedef enum { + DataTypeHexNumber = 0, + DataTypeHexArray = 1, + DataTypeAscii = 2, + DataTypeUnicode = 3, + DataTypeDevicePath = 4, + DataTypeUnKnow = 5 +} DATA_TYPE; + +typedef union { + UINT8 HexNumber8; + UINT16 HexNumber16; + UINT32 HexNumber32; + UINT64 HexNumber64; +} HEX_NUMBER; + +/** + Check if the input is a (potentially empty) string of hexadecimal nibbles. + + @param[in] String The CHAR16 string to check. + + @retval FALSE A character has been found in String for which + ShellIsHexaDecimalDigitCharacter() returned FALSE. + + @retval TRUE Otherwise. (Note that this covers the case when String is + empty.) +**/ +BOOLEAN +IsStringOfHexNibbles ( + IN CONST CHAR16 *String + ) +{ + CONST CHAR16 *Pos; + + for (Pos = String; *Pos != L'\0'; ++Pos) { + if (!ShellIsHexaDecimalDigitCharacter (*Pos)) { + return FALSE; + } + } + return TRUE; +} + +/** + Function to check the TYPE of Data. + + @param[in] Data The Data to be check. + + @retval DATA_TYPE The TYPE of Data. +**/ +DATA_TYPE +TestDataType ( + IN CONST CHAR16 *Data + ) +{ + if (Data[0] == L'0' && (Data[1] == L'x' || Data[1] == L'X')) { + if (IsStringOfHexNibbles (Data+2) && StrLen (Data + 2) <= 16) { + return DataTypeHexNumber; + } else { + return DataTypeUnKnow; + } + } else if (Data[0] == L'H') { + if (IsStringOfHexNibbles (Data + 1) && StrLen (Data + 1) % 2 == 0) { + return DataTypeHexArray; + } else { + return DataTypeUnKnow; + } + } else if (Data[0] == L'S') { + return DataTypeAscii; + } else if (Data[0] == L'L') { + return DataTypeUnicode; + } else if (Data[0] == L'P' || StrnCmp (Data, L"--", 2) == 0) { + return DataTypeDevicePath; + } + + if (IsStringOfHexNibbles (Data) && StrLen (Data) % 2 == 0) { + return DataTypeHexArray; + } + + return DataTypeAscii; +} + +/** + Function to parse the Data by the type of Data, and save in the Buffer. + + @param[in] Data A pointer to a buffer to be parsed. + @param[out] Buffer A pointer to a buffer to hold the return data. + @param[in,out] BufferSize On input, indicates the size of Buffer in bytes. + On output,indicates the size of data return in Buffer. + Or the size in bytes of the buffer needed to obtain. + + @retval EFI_INVALID_PARAMETER The Buffer or BufferSize is NULL. + @retval EFI_BUFFER_TOO_SMALL The Buffer is too small to hold the data. + @retval EFI_OUT_OF_RESOURCES A memory allcation failed. + @retval EFI_SUCCESS The Data parsed successful and save in the Buffer. +**/ +EFI_STATUS +ParseParameterData ( + IN CONST CHAR16 *Data, + OUT VOID *Buffer, + IN OUT UINTN *BufferSize + ) +{ + UINT64 HexNumber; + UINTN HexNumberLen; + UINTN Size; + CHAR8 *AsciiBuffer; + DATA_TYPE DataType; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + + HexNumber = 0; + HexNumberLen = 0; + Size = 0; + AsciiBuffer = NULL; + DevPath = NULL; + Status = EFI_SUCCESS; + + if (Data == NULL || BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + DataType = TestDataType (Data); + if (DataType == DataTypeHexNumber) { + // + // hex number + // + StrHexToUint64S (Data + 2, NULL, &HexNumber); + HexNumberLen = StrLen (Data + 2); + if (HexNumberLen >= 1 && HexNumberLen <= 2) { + Size = 1; + } else if (HexNumberLen >= 3 && HexNumberLen <= 4) { + Size = 2; + } else if (HexNumberLen >= 5 && HexNumberLen <= 8) { + Size = 4; + } else if (HexNumberLen >= 9 && HexNumberLen <= 16) { + Size = 8; + } + if (Buffer != NULL && *BufferSize >= Size) { + CopyMem(Buffer, (VOID *)&HexNumber, Size); + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *BufferSize = Size; + } else if (DataType == DataTypeHexArray) { + // + // hex array + // + if (*Data == L'H') { + Data = Data + 1; + } + + Size = StrLen (Data) / 2; + if (Buffer != NULL && *BufferSize >= Size) { + StrHexToBytes(Data, StrLen (Data), (UINT8 *)Buffer, Size); + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *BufferSize = Size; + } else if (DataType == DataTypeAscii) { + // + // ascii text + // + if (*Data == L'S') { + Data = Data + 1; + } + AsciiBuffer = AllocateZeroPool (StrSize (Data) / 2); + if (AsciiBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + AsciiSPrint (AsciiBuffer, StrSize (Data) / 2, "%s", (CHAR8 *)Data); + + Size = StrSize (Data) / 2 - 1; + if (Buffer != NULL && *BufferSize >= Size) { + CopyMem (Buffer, AsciiBuffer, Size); + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *BufferSize = Size; + } + SHELL_FREE_NON_NULL (AsciiBuffer); + } else if (DataType == DataTypeUnicode) { + // + // unicode text + // + if (*Data == L'L') { + Data = Data + 1; + } + Size = StrSize (Data) - sizeof (CHAR16); + if (Buffer != NULL && *BufferSize >= Size) { + CopyMem (Buffer, Data, Size); + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *BufferSize = Size; + } else if (DataType == DataTypeDevicePath) { + if (*Data == L'P') { + Data = Data + 1; + } else if (StrnCmp (Data, L"--", 2) == 0) { + Data = Data + 2; + } + DevPath = ConvertTextToDevicePath (Data); + if (DevPath == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar"); + Status = EFI_INVALID_PARAMETER; + } else { + Size = GetDevicePathSize (DevPath); + if (Buffer != NULL && *BufferSize >= Size) { + CopyMem (Buffer, DevPath, Size); + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *BufferSize = Size; + } + SHELL_FREE_NON_NULL (DevPath); + } else { + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} + +/** + Function to get each data from parameters. + + @param[in] Package The package of checked values. + @param[out] Buffer A pointer to a buffer to hold the return data. + @param[out] BufferSize Indicates the size of data in bytes return in Buffer. + + @retval EFI_INVALID_PARAMETER Buffer or BufferSize is NULL. + @retval EFI_OUT_OF_RESOURCES A memory allcation failed. + @retval EFI_SUCCESS Get each parameter data was successful. +**/ +EFI_STATUS +GetVariableDataFromParameter ( + IN CONST LIST_ENTRY *Package, + OUT UINT8 **Buffer, + OUT UINTN *BufferSize + ) +{ + CONST CHAR16 *TempData; + UINTN Index; + UINTN TotalSize; + UINTN Size; + UINT8 *BufferWalker; + EFI_STATUS Status; + + TotalSize = 0; + Size = 0; + Status = EFI_SUCCESS; + + if (BufferSize == NULL || Buffer == NULL || ShellCommandLineGetCount (Package) < 3) { + return EFI_INVALID_PARAMETER; + } + + for (Index = 2; Index < ShellCommandLineGetCount (Package); Index++) { + TempData = ShellCommandLineGetRawValue (Package, Index); + ASSERT (TempData != NULL); + + if (TempData[0] != L'=') { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", TempData); + return EFI_INVALID_PARAMETER; + } + + TempData = TempData + 1; + Size = 0; + Status = ParseParameterData (TempData, NULL, &Size); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // We expect return EFI_BUFFER_TOO_SMALL when pass 'NULL' as second parameter to the function ParseParameterData. + // + TotalSize += Size; + } else { + if (Status == EFI_INVALID_PARAMETER) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", TempData); + } else if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar"); + } + return Status; + } + } + } + + *BufferSize = TotalSize; + *Buffer = AllocateZeroPool (TotalSize); + + if (*Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + BufferWalker = *Buffer; + for (Index = 2; Index < ShellCommandLineGetCount (Package); Index++) { + TempData = ShellCommandLineGetRawValue (Package, Index); + TempData = TempData + 1; + + Size = TotalSize; + Status = ParseParameterData (TempData, (VOID *)BufferWalker, &Size); + if (!EFI_ERROR (Status)) { + BufferWalker = BufferWalker + Size; + TotalSize = TotalSize - Size; + } else { + return Status; + } + } + } + + return EFI_SUCCESS; +} + +/** + Function for 'setvar' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSetVar ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + RETURN_STATUS RStatus; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *VariableName; + EFI_GUID Guid; + CONST CHAR16 *StringGuid; + UINT32 Attributes; + VOID *Buffer; + UINTN Size; + UINTN LoopVar; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Buffer = NULL; + Size = 0; + Attributes = 0; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"setvar", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else if (ShellCommandLineCheckDuplicate (Package,&ProblemParam) != EFI_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DUPLICATE), gShellDebug1HiiHandle, L"setvar", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"setvar"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + VariableName = ShellCommandLineGetRawValue(Package, 1); + if (!ShellCommandLineGetFlag(Package, L"-guid")){ + CopyGuid(&Guid, &gEfiGlobalVariableGuid); + } else { + StringGuid = ShellCommandLineGetValue(Package, L"-guid"); + RStatus = StrToGuid (StringGuid, &Guid); + if (RETURN_ERROR (RStatus) || (StringGuid[GUID_STRING_LENGTH] != L'\0')) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", StringGuid); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + + if (ShellCommandLineGetCount(Package) == 2) { + // + // Display + // + Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool(Size); + Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer); + } + if (!EFI_ERROR(Status) && Buffer != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_SETVAR_PRINT), gShellDebug1HiiHandle, &Guid, VariableName, Size); + for (LoopVar = 0; LoopVar < Size; LoopVar++) { + ShellPrintEx(-1, -1, L"%02x ", ((UINT8*)Buffer)[LoopVar]); + } + ShellPrintEx(-1, -1, L"\r\n"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_GET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName); + ShellStatus = SHELL_ACCESS_DENIED; + } + } else { + // + // Create, Delete or Modify. + // + Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = AllocateZeroPool(Size); + Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer); + } + if (EFI_ERROR(Status) || Buffer == NULL) { + // + // Creating a new variable. determine attributes from command line. + // + Attributes = 0; + if (ShellCommandLineGetFlag(Package, L"-bs")) { + Attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS; + } + if (ShellCommandLineGetFlag(Package, L"-rt")) { + Attributes |= EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS; + } + if (ShellCommandLineGetFlag(Package, L"-nv")) { + Attributes |= EFI_VARIABLE_NON_VOLATILE; + } + } + SHELL_FREE_NON_NULL(Buffer); + + Size = 0; + Status = GetVariableDataFromParameter(Package, (UINT8 **)&Buffer, &Size); + if (!EFI_ERROR(Status)) { + Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, Size, Buffer); + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName); + ShellStatus = SHELL_ACCESS_DENIED; + } else { + ASSERT(ShellStatus == SHELL_SUCCESS); + } + } + } + ShellCommandLineFreeVarList (Package); + } + + if (Buffer != NULL) { + FreePool(Buffer); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c new file mode 100644 index 0000000..7ada7d8 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c @@ -0,0 +1,407 @@ +/** @file + Module for clarifying the content of the smbios structure element info. + + Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "PrintInfo.h" +#include "QueryTable.h" +#include "EventLogInfo.h" + +/** + Function to display system event log access information. + + @param[in] Key Additional information to print. + @param[in] Option Whether to print the additional information. +**/ +VOID +DisplaySELAccessMethod ( + IN CONST UINT8 Key, + IN CONST UINT8 Option + ) +{ + // + // Print prompt + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ACCESS_METHOD), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + + // + // Print value info + // + switch (Key) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ONE_EIGHT_BIT), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TWO_EIGHT_BITS), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ONE_SIXTEEN_BIT), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MEM_MAPPED_PHYS), gShellDebug1HiiHandle); + break; + + case 4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_VIA_GENERAL), gShellDebug1HiiHandle); + break; + + default: + if (Key <= 0x7f) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE_ASSIGN), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR_OEM), gShellDebug1HiiHandle); + } + } +} + +/** + Function to display system event log status information. + + @param[in] Key Additional information to print. + @param[in] Option Whether to print the additional information. +**/ +VOID +DisplaySELLogStatus ( + UINT8 Key, + UINT8 Option + ) +{ + // + // Print prompt + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + + // + // Print value info + // + if ((Key & 0x01) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_VALID), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_VALID), gShellDebug1HiiHandle); + } + + if ((Key & 0x02) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_FULL), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_NOT_FULL), gShellDebug1HiiHandle); + } + + if ((Key & 0xFC) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_RES_BITS_NOT_ZERO), gShellDebug1HiiHandle, Key & 0xFC); + } +} + +/** + Function to display system event log header format information. + + @param[in] Key Additional information to print. + @param[in] Option Whether to print the additional information. +**/ +VOID +DisplaySysEventLogHeaderFormat ( + UINT8 Key, + UINT8 Option + ) +{ + // + // Print prompt + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_FORMAT), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + + // + // Print value info + // + if (Key == 0x00) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_NO_HEADER), gShellDebug1HiiHandle); + } else if (Key == 0x01) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TYPE_LOG_HEADER), gShellDebug1HiiHandle); + } else if (Key <= 0x7f) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR), gShellDebug1HiiHandle); + } +} + +/** + Display the header information for SEL log items. + + @param[in] Key The information key. + @param[in] Option The option index. +**/ +VOID +DisplaySELLogHeaderLen ( + UINT8 Key, + UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_LEN), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ONE_VAR_D), gShellDebug1HiiHandle, Key & 0x7F); + + // + // The most-significant bit of the field specifies + // whether (0) or not (1) the record has been read + // + if ((Key & 0x80) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_READ), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_NOT_READ), gShellDebug1HiiHandle); + } +} + +/** + Display the header information for type 1 items. + + @param[in] LogHeader The buffer with the information. +**/ +VOID +DisplaySysEventLogHeaderType1 ( + IN UINT8 *LogHeader + ) +{ + LOG_HEADER_TYPE1_FORMAT *Header; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG), gShellDebug1HiiHandle); + + // + // Print Log Header Type1 Format info + // + Header = (LOG_HEADER_TYPE1_FORMAT *) (LogHeader); + + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_OEM_RESERVED), + gShellDebug1HiiHandle, + Header->OEMReserved[0], + Header->OEMReserved[1], + Header->OEMReserved[2], + Header->OEMReserved[3], + Header->OEMReserved[4] + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_TIME), gShellDebug1HiiHandle, Header->Metw); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_COUNT), gShellDebug1HiiHandle, Header->Meci); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_ADDRESS), gShellDebug1HiiHandle, Header->CMOSAddress); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_INDEX), gShellDebug1HiiHandle, Header->CMOSBitIndex); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUM_STARTING_OFF), gShellDebug1HiiHandle, Header->StartingOffset); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUN_BYTE_COUNT), gShellDebug1HiiHandle, Header->ChecksumOffset); + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_RESERVED), + gShellDebug1HiiHandle, + Header->OEMReserved[0], + Header->OEMReserved[1], + Header->OEMReserved[2] + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_HEADER_REVISION), gShellDebug1HiiHandle, Header->HeaderRevision); +} + +/** + Function to display system event log header information. + + @param[in] LogHeaderFormat Format identifier. + @param[in] LogHeader Format informcation. +**/ +VOID +DisplaySysEventLogHeader ( + UINT8 LogHeaderFormat, + UINT8 *LogHeader + ) +{ + // + // Print prompt + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER), gShellDebug1HiiHandle); + + // + // Print value info + // + if (LogHeaderFormat == 0x00) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_NO_HEADER), gShellDebug1HiiHandle); + } else if (LogHeaderFormat == 0x01) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TYPE_LOG_HEADER), gShellDebug1HiiHandle); + DisplaySysEventLogHeaderType1 (LogHeader); + } else if (LogHeaderFormat <= 0x7f) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FUTURE_ASSIGN), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR), gShellDebug1HiiHandle); + } +} + +/** + Display the El Vdf information. + + @param[in] ElVdfType The information type. + @param[in] VarData The information buffer. +**/ +VOID +DisplayElVdfInfo ( + UINT8 ElVdfType, + UINT8 *VarData + ) +{ + UINT16 *Word; + UINT32 *Dword; + + // + // Display Type Name + // + DisplaySELVarDataFormatType (ElVdfType, SHOW_DETAIL); + + // + // Display Type description + // + switch (ElVdfType) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_NO_STD_FORMAT), gShellDebug1HiiHandle); + break; + + case 1: + Word = (UINT16 *) (VarData + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SMBIOS_STRUCT_ASSOC), gShellDebug1HiiHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_STRUCT_HANDLE), gShellDebug1HiiHandle, *Word); + break; + + case 2: + Dword = (UINT32 *) (VarData + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER), gShellDebug1HiiHandle, *Dword); + break; + + case 3: + Word = (UINT16 *) (VarData + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SMBIOS_STRUCT_ASSOC), gShellDebug1HiiHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_STRUCT_HANDLE), gShellDebug1HiiHandle, *Word); + // + // Followed by a multiple-event counter + // + Dword = (UINT32 *) (VarData + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER), gShellDebug1HiiHandle, *Dword); + break; + + case 4: + Dword = (UINT32 *) (VarData + 1); + DisplayPostResultsBitmapDw1 (*Dword, SHOW_DETAIL); + Dword++; + DisplayPostResultsBitmapDw2 (*Dword, SHOW_DETAIL); + break; + + case 5: + Dword = (UINT32 *) (VarData + 1); + DisplaySELSysManagementTypes (*Dword, SHOW_DETAIL); + break; + + case 6: + Dword = (UINT32 *) (VarData + 1); + DisplaySELSysManagementTypes (*Dword, SHOW_DETAIL); + // + // Followed by a multiple-event counter + // + Dword = (UINT32 *) (VarData + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER), gShellDebug1HiiHandle, *Dword); + break; + + default: + if (ElVdfType <= 0x7F) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_UNUSED_AVAIL_FOR_ASSIGN), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_SYSTEM), gShellDebug1HiiHandle); + } + } +} + +/** + Function to display system event log data. + + @param[in] LogData The data information. + @param[in] LogAreaLength Length of the data. +**/ +VOID +DisplaySysEventLogData ( + UINT8 *LogData, + UINT16 LogAreaLength + ) +{ + LOG_RECORD_FORMAT *Log; + UINT8 ElVdfType; + // + // Event Log Variable Data Format Types + // + UINTN Offset; + + // + // Print prompt + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG_2), gShellDebug1HiiHandle); + + // + // Print Log info + // + Offset = 0; + Log = (LOG_RECORD_FORMAT *) LogData; + while (Log != NULL && Log->Type != END_OF_LOG && Offset < LogAreaLength) { + // + // Get a Event Log Record + // + Log = (LOG_RECORD_FORMAT *) (LogData + Offset); + + if (Log != NULL) { + // + // Display Event Log Record Information + // + DisplaySELVarDataFormatType (Log->Type, SHOW_DETAIL); + DisplaySELLogHeaderLen (Log->Length, SHOW_DETAIL); + + Offset += Log->Length; + // + // Display Log Header Date/Time Fields + // These fields contain the BCD representation of the date and time + // (as read from CMOS) of the occurrence of the event + // So Print as hex and represent decimal + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_DATE), gShellDebug1HiiHandle); + if (Log != NULL && Log->Year >= 80 && Log->Year <= 99) { + Print (L"19"); + } else if (Log != NULL && Log->Year <= 79) { + Print (L"20"); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ERROR), gShellDebug1HiiHandle); + continue; + } + + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TIME_SIX_VARS), + gShellDebug1HiiHandle, + Log->Year, + Log->Month, + Log->Day, + Log->Hour, + Log->Minute, + Log->Second + ); + + // + // Display Variable Data Format + // + if (Log->Length <= (sizeof (LOG_RECORD_FORMAT) - 1)) { + continue; + } + + ElVdfType = Log->LogVariableData[0]; + DisplayElVdfInfo (ElVdfType, Log->LogVariableData); + } + } +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h new file mode 100644 index 0000000..5b7f439 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h @@ -0,0 +1,112 @@ +/** @file + Module to clarify system event log of smbios structure. + + Copyright (c) 2005-2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMBIOS_EVENT_LOG_INFO_H_ +#define _SMBIOS_EVENT_LOG_INFO_H_ + +#define END_OF_LOG 0xFF + +#pragma pack(1) + +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 LogVariableData[1]; +} LOG_RECORD_FORMAT; + +typedef struct { + UINT8 OEMReserved[5]; + UINT8 Metw; // Multiple Event Time Window + UINT8 Meci; // Multiple Event Count Increment + UINT8 CMOSAddress; // Pre-boot Event Log Reset - CMOS Address + UINT8 CMOSBitIndex; // Pre-boot Event Log Reset - CMOS Bit Index + UINT8 StartingOffset; // CMOS Checksum - Starting Offset + UINT8 ByteCount; // CMOS Checksum - Byte Count + UINT8 ChecksumOffset; // CMOS Checksum - Checksum Offset + UINT8 Reserved[3]; + UINT8 HeaderRevision; +} LOG_HEADER_TYPE1_FORMAT; + +#pragma pack() +// +// System Event Log (Type 15) +// + +/** + Function to display system event log access information. + + @param[in] Key Additional information to print. + @param[in] Option Whether to print the additional information. +**/ +VOID +DisplaySELAccessMethod ( + IN CONST UINT8 Key, + IN CONST UINT8 Option + ); + +/** + Function to display system event log status information. + + @param[in] Key Additional information to print. + @param[in] Option Whether to print the additional information. +**/ +VOID +DisplaySELLogStatus ( + UINT8 Key, + UINT8 Option + ); + +/** + Function to display system event log header format information. + + @param[in] Key Additional information to print. + @param[in] Option Whether to print the additional information. +**/ +VOID +DisplaySysEventLogHeaderFormat ( + UINT8 Key, + UINT8 Option + ); + +/** + Function to display system event log header information. + + @param[in] LogHeaderFormat Format identifier. + @param[in] LogHeader Format informcation. +**/ +VOID +DisplaySysEventLogHeader ( + UINT8 LogHeaderFormat, + UINT8 *LogHeader + ); + +/** + Function to display system event log data. + + @param[in] LogData The data information. + @param[in] LogAreaLength Length of the data. +**/ +VOID +DisplaySysEventLogData ( + UINT8 *LogData, + UINT16 LogAreaLength + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c new file mode 100644 index 0000000..f31b940 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c @@ -0,0 +1,373 @@ +/** @file + API for SMBIOS table. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "UefiShellDebug1CommandsLib.h" +#include +#include "LibSmbiosView.h" +#include "SmbiosView.h" + +STATIC UINT8 mInit = 0; +STATIC UINT8 m64Init = 0; +STATIC SMBIOS_TABLE_ENTRY_POINT *mSmbiosTable = NULL; +STATIC SMBIOS_TABLE_3_0_ENTRY_POINT *mSmbios64BitTable = NULL; +STATIC SMBIOS_STRUCTURE_POINTER m_SmbiosStruct; +STATIC SMBIOS_STRUCTURE_POINTER *mSmbiosStruct = &m_SmbiosStruct; +STATIC SMBIOS_STRUCTURE_POINTER m_Smbios64BitStruct; +STATIC SMBIOS_STRUCTURE_POINTER *mSmbios64BitStruct = &m_Smbios64BitStruct; + +/** + Init the SMBIOS VIEW API's environment. + + @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib. +**/ +EFI_STATUS +LibSmbiosInit ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Init only once + // + if (mInit == 1) { + return EFI_SUCCESS; + } + // + // Get SMBIOS table from System Configure table + // + Status = GetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID**)&mSmbiosTable); + + if (mSmbiosTable == NULL) { + return EFI_NOT_FOUND; + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR), gShellDebug1HiiHandle, Status); + return Status; + } + // + // Init SMBIOS structure table address + // + mSmbiosStruct->Raw = (UINT8 *) (UINTN) (mSmbiosTable->TableAddress); + + mInit = 1; + return EFI_SUCCESS; +} + +/** + Init the SMBIOS VIEW API's environment. + + @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib. +**/ +EFI_STATUS +LibSmbios64BitInit ( + VOID + ) +{ + EFI_STATUS Status; + + // + // Init only once + // + if (m64Init == 1) { + return EFI_SUCCESS; + } + // + // Get SMBIOS table from System Configure table + // + Status = GetSystemConfigurationTable (&gEfiSmbios3TableGuid, (VOID**)&mSmbios64BitTable); + + if (mSmbios64BitTable == NULL) { + return EFI_NOT_FOUND; + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR), gShellDebug1HiiHandle, Status); + return Status; + } + // + // Init SMBIOS structure table address + // + mSmbios64BitStruct->Raw = (UINT8 *) (UINTN) (mSmbios64BitTable->TableAddress); + + m64Init = 1; + return EFI_SUCCESS; +} + +/** + Cleanup the Smbios information. +**/ +VOID +LibSmbiosCleanup ( + VOID + ) +{ + // + // Release resources + // + if (mSmbiosTable != NULL) { + mSmbiosTable = NULL; + } + + mInit = 0; +} + +/** + Cleanup the Smbios information. +**/ +VOID +LibSmbios64BitCleanup ( + VOID + ) +{ + // + // Release resources + // + if (mSmbios64BitTable != NULL) { + mSmbios64BitTable = NULL; + } + + m64Init = 0; +} + +/** + Get the entry point structure for the table. + + @param[out] EntryPointStructure The pointer to populate. +**/ +VOID +LibSmbiosGetEPS ( + OUT SMBIOS_TABLE_ENTRY_POINT **EntryPointStructure + ) +{ + // + // return SMBIOS Table address + // + *EntryPointStructure = mSmbiosTable; +} + +/** + Get the entry point structure for the table. + + @param[out] EntryPointStructure The pointer to populate. +**/ +VOID +LibSmbios64BitGetEPS ( + OUT SMBIOS_TABLE_3_0_ENTRY_POINT **EntryPointStructure + ) +{ + // + // return SMBIOS Table address + // + *EntryPointStructure = mSmbios64BitTable; +} + +/** + Return SMBIOS string for the given string number. + + @param[in] Smbios Pointer to SMBIOS structure. + @param[in] StringNumber String number to return. -1 is used to skip all strings and + point to the next SMBIOS structure. + + @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1 +**/ +CHAR8* +LibGetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER *Smbios, + IN UINT16 StringNumber + ) +{ + UINT16 Index; + CHAR8 *String; + + ASSERT (Smbios != NULL); + + // + // Skip over formatted section + // + String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length); + + // + // Look through unformated section + // + for (Index = 1; Index <= StringNumber; Index++) { + if (StringNumber == Index) { + return String; + } + // + // Skip string + // + for (; *String != 0; String++); + String++; + + if (*String == 0) { + // + // If double NULL then we are done. + // Return pointer to next structure in Smbios. + // if you pass in a -1 you will always get here + // + Smbios->Raw = (UINT8 *)++String; + return NULL; + } + } + + return NULL; +} + +/** + Get SMBIOS structure for the given Handle, + Handle is changed to the next handle or 0xFFFF when the end is + reached or the handle is not found. + + @param[in, out] Handle 0xFFFF: get the first structure + Others: get a structure according to this value. + @param[out] Buffer The pointer to the pointer to the structure. + @param[out] Length Length of the structure. + + @retval DMI_SUCCESS Handle is updated with next structure handle or + 0xFFFF(end-of-list). + + @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or + 0xFFFF(end-of-list). +**/ +EFI_STATUS +LibGetSmbiosStructure ( + IN OUT UINT16 *Handle, + OUT UINT8 **Buffer, + OUT UINT16 *Length + ) +{ + SMBIOS_STRUCTURE_POINTER Smbios; + SMBIOS_STRUCTURE_POINTER SmbiosEnd; + UINT8 *Raw; + + if (*Handle == INVALID_HANDLE) { + *Handle = mSmbiosStruct->Hdr->Handle; + return DMI_INVALID_HANDLE; + } + + if ((Buffer == NULL) || (Length == NULL)) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC), gShellDebug1HiiHandle); + return DMI_INVALID_HANDLE; + } + + *Length = 0; + Smbios.Hdr = mSmbiosStruct->Hdr; + SmbiosEnd.Raw = Smbios.Raw + mSmbiosTable->TableLength; + while (Smbios.Raw < SmbiosEnd.Raw) { + if (Smbios.Hdr->Handle == *Handle) { + Raw = Smbios.Raw; + // + // Walk to next structure + // + LibGetSmbiosString (&Smbios, (UINT16) (-1)); + // + // Length = Next structure head - this structure head + // + *Length = (UINT16) (Smbios.Raw - Raw); + *Buffer = Raw; + // + // update with the next structure handle. + // + if (Smbios.Raw < SmbiosEnd.Raw) { + *Handle = Smbios.Hdr->Handle; + } else { + *Handle = INVALID_HANDLE; + } + return DMI_SUCCESS; + } + // + // Walk to next structure + // + LibGetSmbiosString (&Smbios, (UINT16) (-1)); + } + + *Handle = INVALID_HANDLE; + return DMI_INVALID_HANDLE; +} + +/** + Get SMBIOS structure for the given Handle, + Handle is changed to the next handle or 0xFFFF when the end is + reached or the handle is not found. + + @param[in, out] Handle 0xFFFF: get the first structure + Others: get a structure according to this value. + @param[out] Buffer The pointer to the pointer to the structure. + @param[out] Length Length of the structure. + + @retval DMI_SUCCESS Handle is updated with next structure handle or + 0xFFFF(end-of-list). + + @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or + 0xFFFF(end-of-list). +**/ +EFI_STATUS +LibGetSmbios64BitStructure ( + IN OUT UINT16 *Handle, + OUT UINT8 **Buffer, + OUT UINT16 *Length + ) +{ + SMBIOS_STRUCTURE_POINTER Smbios; + SMBIOS_STRUCTURE_POINTER SmbiosEnd; + UINT8 *Raw; + + if (*Handle == INVALID_HANDLE) { + *Handle = mSmbios64BitStruct->Hdr->Handle; + return DMI_INVALID_HANDLE; + } + + if ((Buffer == NULL) || (Length == NULL)) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC), gShellDebug1HiiHandle); + return DMI_INVALID_HANDLE; + } + + *Length = 0; + Smbios.Hdr = mSmbios64BitStruct->Hdr; + + SmbiosEnd.Raw = Smbios.Raw + mSmbios64BitTableLength; + while (Smbios.Raw < SmbiosEnd.Raw) { + if (Smbios.Hdr->Handle == *Handle) { + Raw = Smbios.Raw; + // + // Walk to next structure + // + LibGetSmbiosString (&Smbios, (UINT16) (-1)); + // + // Length = Next structure head - this structure head + // + *Length = (UINT16) (Smbios.Raw - Raw); + *Buffer = Raw; + // + // update with the next structure handle. + // + if (Smbios.Raw < SmbiosEnd.Raw) { + *Handle = Smbios.Hdr->Handle; + } else { + *Handle = INVALID_HANDLE; + } + return DMI_SUCCESS; + } + // + // Walk to next structure + // + LibGetSmbiosString (&Smbios, (UINT16) (-1)); + } + + *Handle = INVALID_HANDLE; + return DMI_INVALID_HANDLE; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h new file mode 100644 index 0000000..29a9ae4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h @@ -0,0 +1,159 @@ +/** @file + API for SMBIOS Plug and Play functions, access to SMBIOS table and structures. + + Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LIB_SMBIOS_VIEW_H_ +#define _LIB_SMBIOS_VIEW_H_ + +#include + +#define DMI_SUCCESS 0x00 +#define DMI_UNKNOWN_FUNCTION 0x81 +#define DMI_FUNCTION_NOT_SUPPORTED 0x82 +#define DMI_INVALID_HANDLE 0x83 +#define DMI_BAD_PARAMETER 0x84 +#define DMI_INVALID_SUBFUNCTION 0x85 +#define DMI_NO_CHANGE 0x86 +#define DMI_ADD_STRUCTURE_FAILED 0x87 +#define DMI_READ_ONLY 0x8D +#define DMI_LOCK_NOT_SUPPORTED 0x90 +#define DMI_CURRENTLY_LOCKED 0x91 +#define DMI_INVALID_LOCK 0x92 + +#define INVALID_HANDLE (UINT16) (-1) + +#define EFI_SMBIOSERR(val) EFIERR (0x30000 | val) + +#define EFI_SMBIOSERR_FAILURE EFI_SMBIOSERR (1) +#define EFI_SMBIOSERR_STRUCT_NOT_FOUND EFI_SMBIOSERR (2) +#define EFI_SMBIOSERR_TYPE_UNKNOWN EFI_SMBIOSERR (3) +#define EFI_SMBIOSERR_UNSUPPORTED EFI_SMBIOSERR (4) + +/** + Init the SMBIOS VIEW API's environment for the 32-bit table.. + + @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib. +**/ +EFI_STATUS +LibSmbiosInit ( + VOID + ); + +/** + Init the SMBIOS VIEW API's environment for the 64-bit table.. + + @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib. +**/ +EFI_STATUS +LibSmbios64BitInit ( + VOID + ); + +/** + Cleanup the Smbios information. +**/ +VOID +LibSmbiosCleanup ( + VOID + ); + +/** + Cleanup the Smbios information. +**/ +VOID +LibSmbios64BitCleanup ( + VOID + ); + +/** + Get the entry point structure for the table. + + @param[out] EntryPointStructure The pointer to populate. +**/ +VOID +LibSmbiosGetEPS ( + OUT SMBIOS_TABLE_ENTRY_POINT **EntryPointStructure + ); + +/** + Get the entry point structure for the 64-bit table. + + @param[out] EntryPointStructure The pointer to populate. +**/ +VOID +LibSmbios64BitGetEPS ( + OUT SMBIOS_TABLE_3_0_ENTRY_POINT **EntryPointStructure + ); + +/** + Return SMBIOS string for the given string number. + + @param[in] Smbios Pointer to SMBIOS structure. + @param[in] StringNumber String number to return. -1 is used to skip all strings and + point to the next SMBIOS structure. + + @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1 +**/ +CHAR8* +LibGetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER *Smbios, + IN UINT16 StringNumber + ); + +/** + Get SMBIOS structure for the given Handle, + Handle is changed to the next handle or 0xFFFF when the end is + reached or the handle is not found. + + @param[in, out] Handle 0xFFFF: get the first structure + Others: get a structure according to this value. + @param[out] Buffer The pointer to the pointer to the structure. + @param[out] Length Length of the structure. + + @retval DMI_SUCCESS Handle is updated with next structure handle or + 0xFFFF(end-of-list). + + @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or + 0xFFFF(end-of-list). +**/ +EFI_STATUS +LibGetSmbiosStructure ( + IN OUT UINT16 *Handle, + OUT UINT8 **Buffer, + OUT UINT16 *Length + ); + +/** + Get SMBIOS structure for the given Handle in 64-bit table, + Handle is changed to the next handle or 0xFFFF when the end is + reached or the handle is not found. + + @param[in, out] Handle 0xFFFF: get the first structure + Others: get a structure according to this value. + @param[out] Buffer The pointer to the pointer to the structure. + @param[out] Length Length of the structure. + + @retval DMI_SUCCESS Handle is updated with next structure handle or + 0xFFFF(end-of-list). + + @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or + 0xFFFF(end-of-list). +**/ +EFI_STATUS +LibGetSmbios64BitStructure ( + IN OUT UINT16 *Handle, + OUT UINT8 **Buffer, + OUT UINT16 *Length + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c new file mode 100644 index 0000000..7f236b3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c @@ -0,0 +1,3427 @@ +/** @file + Module for clarifying the content of the smbios structure element information. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "PrintInfo.h" +#include "LibSmbiosView.h" +#include "QueryTable.h" +#include "EventLogInfo.h" + + +// +// Get the certain bit of 'value' +// +#define BIT(value, bit) ((value) & ((UINT64) 1) << (bit)) + +// +// Check if above or equal to version +// +#define AE_SMBIOS_VERSION(MajorVersion, MinorVersion) \ + (SmbiosMajorVersion > (MajorVersion) || (SmbiosMajorVersion == (MajorVersion) && SmbiosMinorVersion >= (MinorVersion))) + +// +////////////////////////////////////////////////////////// +// Macros of print structure element, simplify coding. +// +#define PRINT_PENDING_STRING(pStruct, type, element) \ + do { \ + CHAR8 *StringBuf; \ + StringBuf = LibGetSmbiosString ((pStruct), (pStruct->type->element)); \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintEx(-1,-1,L": %a\n", (StringBuf != NULL) ? StringBuf: ""); \ + } while (0); + +#define PRINT_SMBIOS_STRING(pStruct, stringnumber, element) \ + do { \ + CHAR8 *StringBuf; \ + StringBuf = LibGetSmbiosString ((pStruct), (stringnumber)); \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintEx(-1,-1,L": %a\n", (StringBuf != NULL) ? StringBuf: ""); \ + } while (0); + +#define PRINT_STRUCT_VALUE(pStruct, type, element) \ + do { \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintEx(-1,-1,L": %d\n", (pStruct->type->element)); \ + } while (0); + +#define PRINT_STRUCT_VALUE_H(pStruct, type, element) \ + do { \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintEx(-1,-1,L": 0x%x\n", (pStruct->type->element)); \ + } while (0); + +#define PRINT_STRUCT_VALUE_LH(pStruct, type, element) \ + do { \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintEx(-1,-1,L": 0x%lx\n", (pStruct->type->element)); \ + } while (0); + +#define PRINT_BIT_FIELD(pStruct, type, element, size) \ + do { \ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DUMP), gShellDebug1HiiHandle); \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SIZE), gShellDebug1HiiHandle, size); \ + DumpHex (0, 0, size, &(pStruct->type->element)); \ + } while (0); + +#define PRINT_SMBIOS_BIT_FIELD(pStruct, startaddress, element, size) \ + do { \ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DUMP), gShellDebug1HiiHandle); \ + ShellPrintEx(-1,-1,L"%a",#element); \ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SIZE), gShellDebug1HiiHandle, size); \ + DumpHex (0, 0, size, startaddress); \ + } while (0); + +// +///////////////////////////////////////// +// + +/** + Copy Length of Src buffer to Dest buffer, + add a NULL termination to Dest buffer. + + @param[in, out] Dest Destination buffer head. + @param[in] Src Source buffer head. + @param[in] Length Length of buffer to be copied. +**/ +VOID +MemToString ( + IN OUT VOID *Dest, + IN VOID *Src, + IN UINTN Length + ) +{ + UINT8 *SrcBuffer; + UINT8 *DestBuffer; + SrcBuffer = (UINT8 *) Src; + DestBuffer = (UINT8 *) Dest; + // + // copy byte by byte + // + while ((Length--)!=0) { + *DestBuffer++ = *SrcBuffer++; + } + // + // append a NULL terminator + // + *DestBuffer = '\0'; +} + +// +////////////////////////////////////////////// +// +// Functions below is to show the information +// + +/** + Print the info of EPS(Entry Point Structure). + + @param[in] SmbiosTable Pointer to the SMBIOS table entry point. + @param[in] Option Display option. +**/ +VOID +SmbiosPrintEPSInfo ( + IN SMBIOS_TABLE_ENTRY_POINT *SmbiosTable, + IN UINT8 Option + ) +{ + UINT8 Anchor[5]; + UINT8 InAnchor[6]; + + if (SmbiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SMBIOSTABLE_NULL), gShellDebug1HiiHandle); + return ; + } + + if (Option == SHOW_NONE) { + return ; + } + + if (Option >= SHOW_NORMAL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_SIGN), gShellDebug1HiiHandle); + MemToString (Anchor, SmbiosTable->AnchorString, 4); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ANCHOR_STR), gShellDebug1HiiHandle, Anchor); + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EPS_CHECKSUM), + gShellDebug1HiiHandle, + SmbiosTable->EntryPointStructureChecksum + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_LEN), gShellDebug1HiiHandle, SmbiosTable->EntryPointLength); + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VERSION), + gShellDebug1HiiHandle, + SmbiosTable->MajorVersion, + SmbiosTable->MinorVersion + ); + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NUMBER_STRUCT), + gShellDebug1HiiHandle, + SmbiosTable->NumberOfSmbiosStructures + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MAX_STRUCT_SIZE), gShellDebug1HiiHandle, SmbiosTable->MaxStructureSize); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_ADDR), gShellDebug1HiiHandle, SmbiosTable->TableAddress); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_LENGTH), gShellDebug1HiiHandle, SmbiosTable->TableLength); + + } + // + // If SHOW_ALL, also print followings. + // + if (Option >= SHOW_DETAIL) { + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_REVISION), + gShellDebug1HiiHandle, + SmbiosTable->EntryPointRevision + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BCD_REVISION), gShellDebug1HiiHandle, SmbiosTable->SmbiosBcdRevision); + // + // Since raw data is not string, add a NULL terminater. + // + MemToString (InAnchor, SmbiosTable->IntermediateAnchorString, 5); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTER_ACHOR), gShellDebug1HiiHandle, InAnchor); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTER_CHECKSUM), gShellDebug1HiiHandle, SmbiosTable->IntermediateChecksum); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FORMATTED_AREA), gShellDebug1HiiHandle); + DumpHex (2, 0, 5, SmbiosTable->FormattedArea); + } + + Print (L"\n"); +} + +/** + Print the info of 64-bit EPS(Entry Point Structure). + + @param[in] SmbiosTable Pointer to the SMBIOS table entry point. + @param[in] Option Display option. +**/ +VOID +Smbios64BitPrintEPSInfo ( + IN SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosTable, + IN UINT8 Option + ) +{ + UINT8 Anchor[5]; + + if (SmbiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SMBIOSTABLE_NULL), gShellDebug1HiiHandle); + return ; + } + + if (Option == SHOW_NONE) { + return ; + } + + if (Option >= SHOW_NORMAL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_64_BIT_ENTRY_POINT_SIGN), gShellDebug1HiiHandle); + + MemToString (Anchor, SmbiosTable->AnchorString, 5); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ANCHOR_STR), gShellDebug1HiiHandle, Anchor); + + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EPS_CHECKSUM), + gShellDebug1HiiHandle, + SmbiosTable->EntryPointStructureChecksum + ); + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_LEN), gShellDebug1HiiHandle, SmbiosTable->EntryPointLength); + + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VERSION), + gShellDebug1HiiHandle, + SmbiosTable->MajorVersion, + SmbiosTable->MinorVersion + ); + + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DOCREV), + gShellDebug1HiiHandle, + SmbiosTable->DocRev + ); + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_MAX_SIZE), gShellDebug1HiiHandle, SmbiosTable->TableMaximumSize); + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_ADDR), gShellDebug1HiiHandle, SmbiosTable->TableAddress); + + } + // + // If SHOW_ALL, also print followings. + // + if (Option >= SHOW_DETAIL) { + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_REVISION), + gShellDebug1HiiHandle, + SmbiosTable->EntryPointRevision + ); + } + + Print (L"\n"); +} + +/** + This function print the content of the structure pointed by Struct. + + @param[in] Struct Point to the structure to be printed. + @param[in] Option Print option of information detail. + + @retval EFI_SUCCESS Successfully Printing this function. + @retval EFI_INVALID_PARAMETER Invalid Structure. + @retval EFI_UNSUPPORTED Unsupported. +**/ +EFI_STATUS +SmbiosPrintStructure ( + IN SMBIOS_STRUCTURE_POINTER *Struct, + IN UINT8 Option + ) +{ + UINT8 Index; + UINT8 *Buffer; + + if (Struct == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Option == SHOW_NONE) { + return EFI_SUCCESS; + } + + Buffer = (UINT8 *) (UINTN) (Struct->Raw); + + // + // Display structure header + // + DisplayStructureTypeInfo (Struct->Hdr->Type, SHOW_DETAIL); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FORMAT_PART_LEN), gShellDebug1HiiHandle, Struct->Hdr->Length); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STRUCT_HANDLE), gShellDebug1HiiHandle, Struct->Hdr->Handle); + + if (Option == SHOW_OUTLINE) { + return EFI_SUCCESS; + } + + switch (Struct->Hdr->Type) { + // + // BIOS Information (Type 0) + // + case 0: + PRINT_PENDING_STRING (Struct, Type0, Vendor); + PRINT_PENDING_STRING (Struct, Type0, BiosVersion); + PRINT_STRUCT_VALUE_H (Struct, Type0, BiosSegment); + PRINT_PENDING_STRING (Struct, Type0, BiosReleaseDate); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_SIZE), gShellDebug1HiiHandle, 64 * (Struct->Type0->BiosSize + 1)); + + DisplayBiosCharacteristics (ReadUnaligned64 ((UINT64 *) (UINTN) &(Struct->Type0->BiosCharacteristics)), Option); + + if (Struct->Hdr->Length > 0x12) { + DisplayBiosCharacteristicsExt1 (Struct->Type0->BIOSCharacteristicsExtensionBytes[0], Option); + } + if (Struct->Hdr->Length > 0x13) { + DisplayBiosCharacteristicsExt2 (Struct->Type0->BIOSCharacteristicsExtensionBytes[1], Option); + } + + if (AE_SMBIOS_VERSION (0x2, 0x4) && (Struct->Hdr->Length > 0x14)) { + PRINT_STRUCT_VALUE (Struct, Type0, SystemBiosMajorRelease); + PRINT_STRUCT_VALUE (Struct, Type0, SystemBiosMinorRelease); + PRINT_STRUCT_VALUE (Struct, Type0, EmbeddedControllerFirmwareMajorRelease); + PRINT_STRUCT_VALUE (Struct, Type0, EmbeddedControllerFirmwareMinorRelease); + } + if (AE_SMBIOS_VERSION (0x3, 0x1) && (Struct->Hdr->Length > 0x18)) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EXTENDED_BIOS_SIZE), + gShellDebug1HiiHandle, + Struct->Type0->ExtendedBiosSize.Size, + (Struct->Type0->ExtendedBiosSize.Unit == 0x0) ? L"MB": L"GB" + ); + } + break; + + // + // System Information (Type 1) + // + case 1: + PRINT_PENDING_STRING (Struct, Type1, Manufacturer); + PRINT_PENDING_STRING (Struct, Type1, ProductName); + PRINT_PENDING_STRING (Struct, Type1, Version); + PRINT_PENDING_STRING (Struct, Type1, SerialNumber); + PRINT_BIT_FIELD (Struct, Type1, Uuid, 16); + DisplaySystemWakeupType (Struct->Type1->WakeUpType, Option); + if (AE_SMBIOS_VERSION (0x2, 0x4) && (Struct->Hdr->Length > 0x19)) { + PRINT_PENDING_STRING (Struct, Type1, SKUNumber); + PRINT_PENDING_STRING (Struct, Type1, Family); + } + + break; + + // + // Baseboard Information (Type 2) + // + case 2: + PRINT_PENDING_STRING (Struct, Type2, Manufacturer); + PRINT_PENDING_STRING (Struct, Type2, ProductName); + PRINT_PENDING_STRING (Struct, Type2, Version); + PRINT_PENDING_STRING (Struct, Type2, SerialNumber); + if (Struct->Hdr->Length > 0x8) { + PRINT_PENDING_STRING (Struct, Type2, AssetTag); + DisplayBaseBoardFeatureFlags (*(UINT8 *) &Struct->Type2->FeatureFlag, Option); + PRINT_PENDING_STRING (Struct, Type2, LocationInChassis); + PRINT_STRUCT_VALUE_H (Struct, Type2, ChassisHandle); + DisplayBaseBoardBoardType (Struct->Type2->BoardType, Option); + } + break; + + // + // System Enclosure (Type 3) + // + case 3: + PRINT_PENDING_STRING (Struct, Type3, Manufacturer); + PRINT_STRUCT_VALUE (Struct, Type3, Type); + DisplaySystemEnclosureType (Struct->Type3->Type, Option); + PRINT_PENDING_STRING (Struct, Type3, Version); + PRINT_PENDING_STRING (Struct, Type3, SerialNumber); + PRINT_PENDING_STRING (Struct, Type3, AssetTag); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOTUP_STATE), gShellDebug1HiiHandle); + DisplaySystemEnclosureStatus (Struct->Type3->BootupState, Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_STATE), gShellDebug1HiiHandle); + DisplaySystemEnclosureStatus (Struct->Type3->PowerSupplyState, Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_THERMAL_STATE), gShellDebug1HiiHandle); + DisplaySystemEnclosureStatus (Struct->Type3->ThermalState, Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SECURITY_STATUS), gShellDebug1HiiHandle); + DisplaySESecurityStatus (Struct->Type3->SecurityStatus, Option); + if (AE_SMBIOS_VERSION (0x2, 0x3)) { + if (Struct->Hdr->Length > 0xD) { + PRINT_BIT_FIELD (Struct, Type3, OemDefined, 4); + } + if (Struct->Hdr->Length > 0x11) { + PRINT_STRUCT_VALUE (Struct, Type3, Height); + } + if (Struct->Hdr->Length > 0x12) { + PRINT_STRUCT_VALUE (Struct, Type3, NumberofPowerCords); + } + } + if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x13)) { + if (Struct->Hdr->Length > (0x15 + (Struct->Type3->ContainedElementCount * Struct->Type3->ContainedElementRecordLength))) { + PRINT_SMBIOS_STRING (Struct, Buffer[0x15 + (Struct->Type3->ContainedElementCount * Struct->Type3->ContainedElementRecordLength)], SKUNumber); + } + } + break; + + // + // Processor Information (Type 4) + // + case 4: + PRINT_SMBIOS_STRING (Struct, Struct->Type4->Socket, SocketDesignation) + DisplayProcessorType (Struct->Type4->ProcessorType, Option); + if (AE_SMBIOS_VERSION (0x2, 0x6) && (Struct->Hdr->Length > 0x28) && + (Struct->Type4->ProcessorFamily == 0xFE)) { + // + // Get family from ProcessorFamily2 field + // + DisplayProcessorFamily2 (Struct->Type4->ProcessorFamily2, Option); + } else { + DisplayProcessorFamily (Struct->Type4->ProcessorFamily, Option); + } + PRINT_PENDING_STRING (Struct, Type4, ProcessorManufacture); + PRINT_BIT_FIELD (Struct, Type4, ProcessorId, 8); + PRINT_PENDING_STRING (Struct, Type4, ProcessorVersion); + DisplayProcessorVoltage (*(UINT8 *) &(Struct->Type4->Voltage), Option); + PRINT_STRUCT_VALUE (Struct, Type4, ExternalClock); + PRINT_STRUCT_VALUE (Struct, Type4, MaxSpeed); + PRINT_STRUCT_VALUE (Struct, Type4, CurrentSpeed); + DisplayProcessorStatus (Struct->Type4->Status, Option); + DisplayProcessorUpgrade (Struct->Type4->ProcessorUpgrade, Option); + PRINT_STRUCT_VALUE_H (Struct, Type4, L1CacheHandle); + PRINT_STRUCT_VALUE_H (Struct, Type4, L2CacheHandle); + PRINT_STRUCT_VALUE_H (Struct, Type4, L3CacheHandle); + if (AE_SMBIOS_VERSION (0x2, 0x3) && (Struct->Hdr->Length > 0x20)) { + PRINT_PENDING_STRING (Struct, Type4, SerialNumber); + PRINT_PENDING_STRING (Struct, Type4, AssetTag); + PRINT_PENDING_STRING (Struct, Type4, PartNumber); + } + if (AE_SMBIOS_VERSION (0x2, 0x5) && (Struct->Hdr->Length > 0x23)) { + PRINT_STRUCT_VALUE (Struct, Type4, CoreCount); + PRINT_STRUCT_VALUE (Struct, Type4, EnabledCoreCount); + PRINT_STRUCT_VALUE (Struct, Type4, ThreadCount); + DisplayProcessorCharacteristics (Struct->Type4->ProcessorCharacteristics, Option); + } + if ((SmbiosMajorVersion >= 0x3) && (Struct->Hdr->Length > 0x2A)) { + PRINT_STRUCT_VALUE (Struct, Type4, CoreCount2); + PRINT_STRUCT_VALUE (Struct, Type4, EnabledCoreCount2); + PRINT_STRUCT_VALUE (Struct, Type4, ThreadCount2); + } + break; + + // + // Memory Controller Information (Type 5) + // + case 5: + { + UINT8 SlotNum; + SlotNum = Struct->Type5->AssociatedMemorySlotNum; + + DisplayMcErrorDetectMethod (Struct->Type5->ErrDetectMethod, Option); + DisplayMcErrorCorrectCapability (*(UINT8 *) &(Struct->Type5->ErrCorrectCapability), Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SUPOPRT), gShellDebug1HiiHandle); + DisplayMcInterleaveSupport (Struct->Type5->SupportInterleave, Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CURRENT), gShellDebug1HiiHandle); + DisplayMcInterleaveSupport (Struct->Type5->CurrentInterleave, Option); + DisplayMaxMemoryModuleSize (Struct->Type5->MaxMemoryModuleSize, SlotNum, Option); + DisplayMcMemorySpeeds (*(UINT16 *) &(Struct->Type5->SupportSpeed), Option); + DisplayMmMemoryType (Struct->Type5->SupportMemoryType, Option); + DisplayMemoryModuleVoltage (Struct->Type5->MemoryModuleVoltage, Option); + PRINT_STRUCT_VALUE (Struct, Type5, AssociatedMemorySlotNum); + // + // According to SMBIOS Specification, offset 0x0F + // + DisplayMemoryModuleConfigHandles ((UINT16 *) (&Buffer[0x0F]), SlotNum, Option); + DisplayMcErrorCorrectCapability (Buffer[0x0F + 2 * SlotNum], Option); + } + break; + + // + // Memory Module Information (Type 6) + // + case 6: + PRINT_PENDING_STRING (Struct, Type6, SocketDesignation); + DisplayMmBankConnections (Struct->Type6->BankConnections, Option); + PRINT_STRUCT_VALUE (Struct, Type6, CurrentSpeed); + DisplayMmMemoryType (*(UINT16 *) &(Struct->Type6->CurrentMemoryType), Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INSTALLED), gShellDebug1HiiHandle); + DisplayMmMemorySize (*(UINT8 *) &(Struct->Type6->InstalledSize), Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED), gShellDebug1HiiHandle); + DisplayMmMemorySize (*(UINT8 *) &(Struct->Type6->EnabledSize), Option); + DisplayMmErrorStatus (Struct->Type6->ErrorStatus, Option); + break; + + // + // Cache Information (Type 7) + // + case 7: + PRINT_PENDING_STRING (Struct, Type7, SocketDesignation); + DisplayCacheConfiguration (Struct->Type7->CacheConfiguration, Option); + PRINT_STRUCT_VALUE_H (Struct, Type7, MaximumCacheSize); + PRINT_STRUCT_VALUE_H (Struct, Type7, InstalledSize); + PRINT_STRUCT_VALUE_H (Struct, Type7, SupportedSRAMType); + PRINT_STRUCT_VALUE_H (Struct, Type7, CurrentSRAMType); + DisplayCacheSRAMType (ReadUnaligned16 ((UINT16 *) (UINTN) &(Struct->Type7->CurrentSRAMType)), Option); + PRINT_STRUCT_VALUE_H (Struct, Type7, CacheSpeed); + DisplayCacheErrCorrectingType (Struct->Type7->ErrorCorrectionType, Option); + DisplayCacheSystemCacheType (Struct->Type7->SystemCacheType, Option); + DisplayCacheAssociativity (Struct->Type7->Associativity, Option); + if (AE_SMBIOS_VERSION (0x3, 0x1) && (Struct->Hdr->Length > 0x13)) { + PRINT_STRUCT_VALUE_H (Struct, Type7, MaximumCacheSize2); + PRINT_STRUCT_VALUE_H (Struct, Type7, InstalledSize2); + } + break; + + // + // Port Connector Information (Type 8) + // + case 8: + PRINT_PENDING_STRING (Struct, Type8, InternalReferenceDesignator); + Print (L"Internal "); + DisplayPortConnectorType (Struct->Type8->InternalConnectorType, Option); + PRINT_PENDING_STRING (Struct, Type8, ExternalReferenceDesignator); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EXTERNAL), gShellDebug1HiiHandle); + DisplayPortConnectorType (Struct->Type8->ExternalConnectorType, Option); + DisplayPortType (Struct->Type8->PortType, Option); + break; + + // + // System Slots (Type 9) + // + case 9: + { + MISC_SLOT_PEER_GROUP *PeerGroupPtr; + UINT8 PeerGroupCount; + + PRINT_PENDING_STRING (Struct, Type9, SlotDesignation); + DisplaySystemSlotType (Struct->Type9->SlotType, Option); + DisplaySystemSlotDataBusWidth (Struct->Type9->SlotDataBusWidth, Option); + DisplaySystemSlotCurrentUsage (Struct->Type9->CurrentUsage, Option); + DisplaySystemSlotLength (Struct->Type9->SlotLength, Option); + DisplaySystemSlotId ( + Struct->Type9->SlotID, + Struct->Type9->SlotType, + Option + ); + DisplaySlotCharacteristics1 (*(UINT8 *) &(Struct->Type9->SlotCharacteristics1), Option); + DisplaySlotCharacteristics2 (*(UINT8 *) &(Struct->Type9->SlotCharacteristics2), Option); + if (AE_SMBIOS_VERSION (0x2, 0x6) && (Struct->Hdr->Length > 0xD)) { + PRINT_STRUCT_VALUE_H (Struct, Type9, SegmentGroupNum); + PRINT_STRUCT_VALUE_H (Struct, Type9, BusNum); + PRINT_STRUCT_VALUE_H (Struct, Type9, DevFuncNum); + } + if (AE_SMBIOS_VERSION (0x3, 0x2)) { + if (Struct->Hdr->Length > 0x11) { + PRINT_STRUCT_VALUE (Struct, Type9, DataBusWidth); + } + if (Struct->Hdr->Length > 0x12) { + PRINT_STRUCT_VALUE (Struct, Type9, PeerGroupingCount); + + PeerGroupCount = Struct->Type9->PeerGroupingCount; + PeerGroupPtr = Struct->Type9->PeerGroups; + for (Index = 0; Index < PeerGroupCount; Index++) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SLOT_PEER_GROUPS), gShellDebug1HiiHandle, Index + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SEGMENT_GROUP_NUM), gShellDebug1HiiHandle, PeerGroupPtr[Index].SegmentGroupNum); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BUS_NUM), gShellDebug1HiiHandle, PeerGroupPtr[Index].BusNum); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DEV_FUNC_NUM), gShellDebug1HiiHandle, PeerGroupPtr[Index].DevFuncNum); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DATA_BUS_WIDTH), gShellDebug1HiiHandle, PeerGroupPtr[Index].DataBusWidth); + } + } + } + } + break; + + // + // On Board Devices Information (Type 10) + // + case 10: + { + UINTN NumOfDevice; + NumOfDevice = (Struct->Type10->Hdr.Length - sizeof (SMBIOS_STRUCTURE)) / (2 * sizeof (UINT8)); + for (Index = 0; Index < NumOfDevice; Index++) { + ShellPrintEx(-1,-1,(((Struct->Type10->Device[Index].DeviceType) & 0x80) != 0) ? L"Device Enabled\n": L"Device Disabled\n"); + DisplayOnboardDeviceTypes ((Struct->Type10->Device[Index].DeviceType) & 0x7F, Option); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DESC_STRING), gShellDebug1HiiHandle); + ShellPrintEx(-1,-1,L"%a\n",LibGetSmbiosString (Struct, Struct->Type10->Device[Index].DescriptionString)); + } + } + break; + + // + // Oem Strings (Type 11) + // + case 11: + PRINT_STRUCT_VALUE (Struct, Type11, StringCount); + for (Index = 1; Index <= Struct->Type11->StringCount; Index++) { + ShellPrintEx(-1,-1,L"%a\n", LibGetSmbiosString (Struct, Index)); + } + break; + + // + // System Configuration Options (Type 12) + // + case 12: + PRINT_STRUCT_VALUE (Struct, Type12, StringCount); + for (Index = 1; Index <= Struct->Type12->StringCount; Index++) { + ShellPrintEx(-1,-1,L"%a\n", LibGetSmbiosString (Struct, Index)); + } + break; + + // + // BIOS Language Information (Type 13) + // + case 13: + PRINT_STRUCT_VALUE (Struct, Type13, InstallableLanguages); + PRINT_STRUCT_VALUE (Struct, Type13, Flags); + PRINT_BIT_FIELD (Struct, Type13, Reserved, 15); + PRINT_PENDING_STRING (Struct, Type13, CurrentLanguages); + break; + + // + // Group Associations (Type 14) + // + case 14: + { + UINT8 NumOfItem; + NumOfItem = (Struct->Type14->Hdr.Length - 5) / 3; + PRINT_PENDING_STRING (Struct, Type14, GroupName); + for (Index = 0; Index < NumOfItem; Index++) { + ShellPrintEx(-1,-1,L"ItemType %d: %d\n", Index + 1, Struct->Type14->Group[Index].ItemType); + ShellPrintEx(-1,-1,L"ItemHandle %d: %d\n", Index + 1, Struct->Type14->Group[Index].ItemHandle); + } + } + break; + + // + // System Event Log (Type 15) + // + case 15: + { + EVENT_LOG_TYPE *Ptr; + UINT8 Count; + UINT8 *AccessMethodAddress; + + PRINT_STRUCT_VALUE_H (Struct, Type15, LogAreaLength); + PRINT_STRUCT_VALUE_H (Struct, Type15, LogHeaderStartOffset); + PRINT_STRUCT_VALUE_H (Struct, Type15, LogDataStartOffset); + DisplaySELAccessMethod (Struct->Type15->AccessMethod, Option); + PRINT_STRUCT_VALUE_H (Struct, Type15, AccessMethodAddress); + DisplaySELLogStatus (Struct->Type15->LogStatus, Option); + PRINT_STRUCT_VALUE_H (Struct, Type15, LogChangeToken); + DisplaySysEventLogHeaderFormat (Struct->Type15->LogHeaderFormat, Option); + PRINT_STRUCT_VALUE_H (Struct, Type15, NumberOfSupportedLogTypeDescriptors); + PRINT_STRUCT_VALUE_H (Struct, Type15, LengthOfLogTypeDescriptor); + + Count = Struct->Type15->NumberOfSupportedLogTypeDescriptors; + if (Count > 0) { + Ptr = Struct->Type15->EventLogTypeDescriptors; + + // + // Display all Event Log type descriptors supported by system + // + for (Index = 0; Index < Count; Index++, Ptr++) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SUPOPRTED_EVENT), gShellDebug1HiiHandle, Index + 1); + DisplaySELTypes (Ptr->LogType, Option); + DisplaySELVarDataFormatType (Ptr->DataFormatType, Option); + } + + if (Option >= SHOW_DETAIL) { + switch (Struct->Type15->AccessMethod) { + case 03: + AccessMethodAddress = (UINT8 *) (UINTN) (Struct->Type15->AccessMethodAddress); + break; + + case 00: + case 01: + case 02: + case 04: + default: + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ACCESS_METHOD_NOT_SUPOPRTED), + gShellDebug1HiiHandle, + Struct->Type15->AccessMethod + ); + return EFI_UNSUPPORTED; + } + // + // Display Event Log Header + // + // Starting offset (or index) within the nonvolatile storage + // of the event-log's header, from the Access Method Address + // + DisplaySysEventLogHeader ( + Struct->Type15->LogHeaderFormat, + AccessMethodAddress + Struct->Type15->LogHeaderStartOffset + ); + + // + // Display all Event Log data + // + // Starting offset (or index) within the nonvolatile storage + // of the event-log's first data byte, from the Access Method Address(0x14) + // + DisplaySysEventLogData ( + AccessMethodAddress + Struct->Type15->LogDataStartOffset, + (UINT16) + ( + Struct->Type15->LogAreaLength - + (Struct->Type15->LogDataStartOffset - Struct->Type15->LogHeaderStartOffset) + ) + ); + } + + } + } + break; + + // + // Physical Memory Array (Type 16) + // + case 16: + DisplayPMALocation (Struct->Type16->Location, Option); + DisplayPMAUse (Struct->Type16->Use, Option); + DisplayPMAErrorCorrectionTypes ( + Struct->Type16->MemoryErrorCorrection, + Option + ); + PRINT_STRUCT_VALUE_H (Struct, Type16, MaximumCapacity); + PRINT_STRUCT_VALUE_H (Struct, Type16, MemoryErrorInformationHandle); + PRINT_STRUCT_VALUE_H (Struct, Type16, NumberOfMemoryDevices); + if (AE_SMBIOS_VERSION (0x2, 0x7) && Struct->Hdr->Length > 0xF) { + PRINT_STRUCT_VALUE_LH (Struct, Type16, ExtendedMaximumCapacity); + } + break; + + // + // Memory Device (Type 17) + // + case 17: + PRINT_STRUCT_VALUE_H (Struct, Type17, MemoryArrayHandle); + PRINT_STRUCT_VALUE_H (Struct, Type17, MemoryErrorInformationHandle); + PRINT_STRUCT_VALUE (Struct, Type17, TotalWidth); + PRINT_STRUCT_VALUE (Struct, Type17, DataWidth); + PRINT_STRUCT_VALUE (Struct, Type17, Size); + DisplayMemoryDeviceFormFactor (Struct->Type17->FormFactor, Option); + PRINT_STRUCT_VALUE_H (Struct, Type17, DeviceSet); + PRINT_PENDING_STRING (Struct, Type17, DeviceLocator); + PRINT_PENDING_STRING (Struct, Type17, BankLocator); + DisplayMemoryDeviceType (Struct->Type17->MemoryType, Option); + DisplayMemoryDeviceTypeDetail (ReadUnaligned16 ((UINT16 *) (UINTN) &(Struct->Type17->TypeDetail)), Option); + PRINT_STRUCT_VALUE_H (Struct, Type17, Speed); + PRINT_PENDING_STRING (Struct, Type17, Manufacturer); + PRINT_PENDING_STRING (Struct, Type17, SerialNumber); + PRINT_PENDING_STRING (Struct, Type17, AssetTag); + PRINT_PENDING_STRING (Struct, Type17, PartNumber); + if (AE_SMBIOS_VERSION (0x2, 0x6) && (Struct->Hdr->Length > 0x1B)) { + PRINT_STRUCT_VALUE_H (Struct, Type17, Attributes); + } + if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x1C)) { + PRINT_STRUCT_VALUE (Struct, Type17, ExtendedSize); + PRINT_STRUCT_VALUE (Struct, Type17, ConfiguredMemoryClockSpeed); + } + if (AE_SMBIOS_VERSION (0x2, 0x8) && (Struct->Hdr->Length > 0x22)) { + PRINT_STRUCT_VALUE (Struct, Type17, MinimumVoltage); + PRINT_STRUCT_VALUE (Struct, Type17, MaximumVoltage); + PRINT_STRUCT_VALUE (Struct, Type17, ConfiguredVoltage); + } + if (AE_SMBIOS_VERSION (0x3, 0x2)) { + if (Struct->Hdr->Length > 0x28) { + DisplayMemoryDeviceMemoryTechnology (Struct->Type17->MemoryTechnology, Option); + DisplayMemoryDeviceMemoryOperatingModeCapability (Struct->Type17->MemoryOperatingModeCapability.Uint16, Option); + PRINT_PENDING_STRING (Struct, Type17, FirwareVersion); + PRINT_STRUCT_VALUE_H (Struct, Type17, ModuleManufacturerID); + PRINT_STRUCT_VALUE_H (Struct, Type17, ModuleProductID); + PRINT_STRUCT_VALUE_H (Struct, Type17, MemorySubsystemControllerManufacturerID); + PRINT_STRUCT_VALUE_H (Struct, Type17, MemorySubsystemControllerProductID); + } + if (Struct->Hdr->Length > 0x34) { + PRINT_STRUCT_VALUE_H (Struct, Type17, NonVolatileSize); + } + if (Struct->Hdr->Length > 0x3C) { + PRINT_STRUCT_VALUE_H (Struct, Type17, VolatileSize); + } + if (Struct->Hdr->Length > 0x44) { + PRINT_STRUCT_VALUE_H (Struct, Type17, CacheSize); + } + if (Struct->Hdr->Length > 0x4C) { + PRINT_STRUCT_VALUE_H (Struct, Type17, LogicalSize); + } + } + break; + + // + // 32-bit Memory Error Information (Type 18) + // + case 18: + DisplayMemoryErrorType (Struct->Type18->ErrorType, Option); + DisplayMemoryErrorGranularity ( + Struct->Type18->ErrorGranularity, + Option + ); + DisplayMemoryErrorOperation (Struct->Type18->ErrorOperation, Option); + PRINT_STRUCT_VALUE_H (Struct, Type18, VendorSyndrome); + PRINT_STRUCT_VALUE_H (Struct, Type18, MemoryArrayErrorAddress); + PRINT_STRUCT_VALUE_H (Struct, Type18, DeviceErrorAddress); + PRINT_STRUCT_VALUE_H (Struct, Type18, ErrorResolution); + break; + + // + // Memory Array Mapped Address (Type 19) + // + case 19: + PRINT_STRUCT_VALUE_H (Struct, Type19, StartingAddress); + PRINT_STRUCT_VALUE_H (Struct, Type19, EndingAddress); + PRINT_STRUCT_VALUE_H (Struct, Type19, MemoryArrayHandle); + PRINT_STRUCT_VALUE_H (Struct, Type19, PartitionWidth); + if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0xF)) { + PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedStartingAddress); + PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedEndingAddress); + } + break; + + // + // Memory Device Mapped Address (Type 20) + // + case 20: + PRINT_STRUCT_VALUE_H (Struct, Type20, StartingAddress); + PRINT_STRUCT_VALUE_H (Struct, Type20, EndingAddress); + PRINT_STRUCT_VALUE_H (Struct, Type20, MemoryDeviceHandle); + PRINT_STRUCT_VALUE_H (Struct, Type20, MemoryArrayMappedAddressHandle); + PRINT_STRUCT_VALUE_H (Struct, Type20, PartitionRowPosition); + PRINT_STRUCT_VALUE_H (Struct, Type20, InterleavePosition); + PRINT_STRUCT_VALUE_H (Struct, Type20, InterleavedDataDepth); + if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x13)) { + PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedStartingAddress); + PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedEndingAddress); + } + break; + + // + // Built-in Pointing Device (Type 21) + // + case 21: + DisplayPointingDeviceType (Struct->Type21->Type, Option); + DisplayPointingDeviceInterface (Struct->Type21->Interface, Option); + PRINT_STRUCT_VALUE (Struct, Type21, NumberOfButtons); + break; + + // + // Portable Battery (Type 22) + // + case 22: + PRINT_PENDING_STRING (Struct, Type22, Location); + PRINT_PENDING_STRING (Struct, Type22, Manufacturer); + PRINT_PENDING_STRING (Struct, Type22, ManufactureDate); + PRINT_PENDING_STRING (Struct, Type22, SerialNumber); + PRINT_PENDING_STRING (Struct, Type22, DeviceName); + DisplayPBDeviceChemistry ( + Struct->Type22->DeviceChemistry, + Option + ); + PRINT_STRUCT_VALUE_H (Struct, Type22, DeviceCapacity); + PRINT_STRUCT_VALUE_H (Struct, Type22, DesignVoltage); + PRINT_PENDING_STRING (Struct, Type22, SBDSVersionNumber); + PRINT_STRUCT_VALUE_H (Struct, Type22, MaximumErrorInBatteryData); + PRINT_STRUCT_VALUE_H (Struct, Type22, SBDSSerialNumber); + DisplaySBDSManufactureDate ( + Struct->Type22->SBDSManufactureDate, + Option + ); + PRINT_PENDING_STRING (Struct, Type22, SBDSDeviceChemistry); + PRINT_STRUCT_VALUE_H (Struct, Type22, DesignCapacityMultiplier); + PRINT_STRUCT_VALUE_H (Struct, Type22, OEMSpecific); + break; + + // + // System Reset (Type 23) + // + case 23: + DisplaySystemResetCapabilities ( + Struct->Type23->Capabilities, + Option + ); + PRINT_STRUCT_VALUE_H (Struct, Type23, ResetCount); + PRINT_STRUCT_VALUE_H (Struct, Type23, ResetLimit); + PRINT_STRUCT_VALUE_H (Struct, Type23, TimerInterval); + PRINT_STRUCT_VALUE_H (Struct, Type23, Timeout); + break; + + // + // Hardware Security (Type 24) + // + case 24: + DisplayHardwareSecuritySettings ( + Struct->Type24->HardwareSecuritySettings, + Option + ); + break; + + // + // System Power Controls (Type 25) + // + case 25: + PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnMonth); + PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnDayOfMonth); + PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnHour); + PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnMinute); + PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnSecond); + break; + + // + // Voltage Probe (Type 26) + // + case 26: + PRINT_PENDING_STRING (Struct, Type26, Description); + DisplayVPLocation (*(UINT8 *) &(Struct->Type26->LocationAndStatus), Option); + DisplayVPStatus (*(UINT8 *) &(Struct->Type26->LocationAndStatus), Option); + PRINT_STRUCT_VALUE_H (Struct, Type26, MaximumValue); + PRINT_STRUCT_VALUE_H (Struct, Type26, MinimumValue); + PRINT_STRUCT_VALUE_H (Struct, Type26, Resolution); + PRINT_STRUCT_VALUE_H (Struct, Type26, Tolerance); + PRINT_STRUCT_VALUE_H (Struct, Type26, Accuracy); + PRINT_STRUCT_VALUE_H (Struct, Type26, OEMDefined); + PRINT_STRUCT_VALUE_H (Struct, Type26, NominalValue); + break; + + // + // Cooling Device (Type 27) + // + case 27: + PRINT_STRUCT_VALUE_H (Struct, Type27, TemperatureProbeHandle); + DisplayCoolingDeviceStatus (*(UINT8 *) &(Struct->Type27->DeviceTypeAndStatus), Option); + DisplayCoolingDeviceType (*(UINT8 *) &(Struct->Type27->DeviceTypeAndStatus), Option); + PRINT_STRUCT_VALUE_H (Struct, Type27, CoolingUnitGroup); + PRINT_STRUCT_VALUE_H (Struct, Type27, OEMDefined); + PRINT_STRUCT_VALUE_H (Struct, Type27, NominalSpeed); + if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0xE)) { + PRINT_PENDING_STRING (Struct, Type27, Description); + } + break; + + // + // Temperature Probe (Type 28) + // + case 28: + PRINT_PENDING_STRING (Struct, Type28, Description); + DisplayTemperatureProbeStatus (*(UINT8 *) &(Struct->Type28->LocationAndStatus), Option); + DisplayTemperatureProbeLoc (*(UINT8 *) &(Struct->Type28->LocationAndStatus), Option); + PRINT_STRUCT_VALUE_H (Struct, Type28, MaximumValue); + PRINT_STRUCT_VALUE_H (Struct, Type28, MinimumValue); + PRINT_STRUCT_VALUE_H (Struct, Type28, Resolution); + PRINT_STRUCT_VALUE_H (Struct, Type28, Tolerance); + PRINT_STRUCT_VALUE_H (Struct, Type28, Accuracy); + PRINT_STRUCT_VALUE_H (Struct, Type28, OEMDefined); + PRINT_STRUCT_VALUE_H (Struct, Type28, NominalValue); + break; + + // + // Electrical Current Probe (Type 29) + // + case 29: + PRINT_PENDING_STRING (Struct, Type29, Description); + DisplayECPStatus (*(UINT8 *) &(Struct->Type29->LocationAndStatus), Option); + DisplayECPLoc (*(UINT8 *) &(Struct->Type29->LocationAndStatus), Option); + PRINT_STRUCT_VALUE_H (Struct, Type29, MaximumValue); + PRINT_STRUCT_VALUE_H (Struct, Type29, MinimumValue); + PRINT_STRUCT_VALUE_H (Struct, Type29, Resolution); + PRINT_STRUCT_VALUE_H (Struct, Type29, Tolerance); + PRINT_STRUCT_VALUE_H (Struct, Type29, Accuracy); + PRINT_STRUCT_VALUE_H (Struct, Type29, OEMDefined); + PRINT_STRUCT_VALUE_H (Struct, Type29, NominalValue); + break; + + // + // Out-of-Band Remote Access (Type 30) + // + case 30: + PRINT_PENDING_STRING (Struct, Type30, ManufacturerName); + DisplayOBRAConnections (Struct->Type30->Connections, Option); + break; + + // + // Boot Integrity Services (BIS) Entry Point (Type 31) + // + case 31: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE31), gShellDebug1HiiHandle); + break; + + // + // System Boot Information (Type 32) + // + case 32: + PRINT_BIT_FIELD (Struct, Type32, Reserved, 6); + DisplaySystemBootStatus (Struct->Type32->BootStatus, Option); + break; + + // + // 64-Bit Memory Error Information (Type 33) + // + case 33: + DisplayMemoryErrorType (Struct->Type33->ErrorType, Option); + DisplayMemoryErrorGranularity ( + Struct->Type33->ErrorGranularity, + Option + ); + DisplayMemoryErrorOperation (Struct->Type33->ErrorOperation, Option); + PRINT_STRUCT_VALUE_H (Struct, Type33, VendorSyndrome); + PRINT_STRUCT_VALUE_LH (Struct, Type33, MemoryArrayErrorAddress); + PRINT_STRUCT_VALUE_LH (Struct, Type33, DeviceErrorAddress); + PRINT_STRUCT_VALUE_H (Struct, Type33, ErrorResolution); + break; + + // + // Management Device (Type 34) + // + case 34: + PRINT_PENDING_STRING (Struct, Type34, Description); + DisplayMDType (Struct->Type34->Type, Option); + PRINT_STRUCT_VALUE_H (Struct, Type34, Address); + DisplayMDAddressType (Struct->Type34->AddressType, Option); + break; + + // + // Management Device Component (Type 35) + // + case 35: + PRINT_PENDING_STRING (Struct, Type35, Description); + PRINT_STRUCT_VALUE_H (Struct, Type35, ManagementDeviceHandle); + PRINT_STRUCT_VALUE_H (Struct, Type35, ComponentHandle); + PRINT_STRUCT_VALUE_H (Struct, Type35, ThresholdHandle); + break; + + // + // Management Device Threshold Data (Type 36) + // + case 36: + PRINT_STRUCT_VALUE_H (Struct, Type36, LowerThresholdNonCritical); + PRINT_STRUCT_VALUE_H (Struct, Type36, UpperThresholdNonCritical); + PRINT_STRUCT_VALUE_H (Struct, Type36, LowerThresholdCritical); + PRINT_STRUCT_VALUE_H (Struct, Type36, UpperThresholdCritical); + PRINT_STRUCT_VALUE_H (Struct, Type36, LowerThresholdNonRecoverable); + PRINT_STRUCT_VALUE_H (Struct, Type36, UpperThresholdNonRecoverable); + break; + + // + // Memory Channel (Type 37) + // + case 37: + { + UINT8 Count; + MEMORY_DEVICE *Ptr; + DisplayMemoryChannelType (Struct->Type37->ChannelType, Option); + PRINT_STRUCT_VALUE_H (Struct, Type37, MaximumChannelLoad); + PRINT_STRUCT_VALUE_H (Struct, Type37, MemoryDeviceCount); + + Count = Struct->Type37->MemoryDeviceCount; + Ptr = Struct->Type37->MemoryDevice; + for (Index = 0; Index < Count; Index++) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_DEVICE), gShellDebug1HiiHandle, Index + 1); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DEV_LOAD), gShellDebug1HiiHandle, Ptr[Index].DeviceLoad); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DEV_HANDLE), gShellDebug1HiiHandle, Ptr[Index].DeviceHandle); + } + } + break; + + // + // IPMI Device Information (Type 38) + // + case 38: + DisplayIPMIDIBMCInterfaceType (Struct->Type38->InterfaceType, Option); + PRINT_STRUCT_VALUE_H (Struct, Type38, IPMISpecificationRevision); + PRINT_STRUCT_VALUE_H (Struct, Type38, I2CSlaveAddress); + PRINT_STRUCT_VALUE_H (Struct, Type38, NVStorageDeviceAddress); + PRINT_STRUCT_VALUE_LH (Struct, Type38, BaseAddress); + break; + + // + // System Power Supply (Type 39) + // + case 39: + PRINT_STRUCT_VALUE_H (Struct, Type39, PowerUnitGroup); + PRINT_PENDING_STRING (Struct, Type39, Location); + PRINT_PENDING_STRING (Struct, Type39, DeviceName); + PRINT_PENDING_STRING (Struct, Type39, Manufacturer); + PRINT_PENDING_STRING (Struct, Type39, SerialNumber); + PRINT_PENDING_STRING (Struct, Type39, AssetTagNumber); + PRINT_PENDING_STRING (Struct, Type39, ModelPartNumber); + PRINT_PENDING_STRING (Struct, Type39, RevisionLevel); + PRINT_STRUCT_VALUE_H (Struct, Type39, MaxPowerCapacity); + DisplaySPSCharacteristics ( + *(UINT16 *) &(Struct->Type39->PowerSupplyCharacteristics), + Option + ); + PRINT_STRUCT_VALUE_H (Struct, Type39, InputVoltageProbeHandle); + PRINT_STRUCT_VALUE_H (Struct, Type39, CoolingDeviceHandle); + PRINT_STRUCT_VALUE_H (Struct, Type39, InputCurrentProbeHandle); + break; + + // + // Additional Information (Type 40) + // + case 40: + { + UINT8 NumberOfEntries; + UINT8 EntryLength; + ADDITIONAL_INFORMATION_ENTRY *Entries; + + EntryLength = 0; + Entries = Struct->Type40->AdditionalInfoEntries; + NumberOfEntries = Struct->Type40->NumberOfAdditionalInformationEntries; + + PRINT_STRUCT_VALUE_H (Struct, Type40, NumberOfAdditionalInformationEntries); + + for (Index = 0; Index < NumberOfEntries; Index++) { + EntryLength = Entries->EntryLength; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ENTRYLEN), gShellDebug1HiiHandle, EntryLength); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDHANDLE), gShellDebug1HiiHandle, Entries->ReferencedHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDOFFSET), gShellDebug1HiiHandle, Entries->ReferencedOffset); + PRINT_SMBIOS_STRING (Struct, Entries->EntryString, String); + PRINT_SMBIOS_BIT_FIELD (Struct, Entries->Value, Value, EntryLength - 5); + Entries = (ADDITIONAL_INFORMATION_ENTRY *) ((UINT8 *)Entries + EntryLength); + } + } + break; + + // + // Onboard Devices Extended Information (Type 41) + // + case 41: + PRINT_PENDING_STRING (Struct, Type41, ReferenceDesignation); + ShellPrintEx(-1,-1,(((Struct->Type41->DeviceType) & 0x80) != 0) ? L"Device Enabled\n": L"Device Disabled\n"); + DisplayOnboardDeviceTypes ((Struct->Type41->DeviceType) & 0x7F, Option); + PRINT_STRUCT_VALUE_H (Struct, Type41, DeviceTypeInstance); + PRINT_STRUCT_VALUE_H (Struct, Type41, SegmentGroupNum); + PRINT_STRUCT_VALUE_H (Struct, Type41, BusNum); + PRINT_STRUCT_VALUE_H (Struct, Type41, DevFuncNum); + break; + + // + // Management Controller Host Interface (Type 42) + // + case 42: + DisplayMCHostInterfaceType (Struct->Type42->InterfaceType, Option); + if (AE_SMBIOS_VERSION (0x3, 0x2)) { + PRINT_STRUCT_VALUE_H (Struct, Type42, InterfaceTypeSpecificDataLength); + PRINT_BIT_FIELD (Struct, Type42, InterfaceTypeSpecificData, Struct->Type42->InterfaceTypeSpecificDataLength); + } + break; + + // + // TPM Device (Type 43) + // + case 43: + PRINT_BIT_FIELD (Struct, Type43, VendorID, 4); + PRINT_STRUCT_VALUE_H (Struct, Type43, MajorSpecVersion); + PRINT_STRUCT_VALUE_H (Struct, Type43, MinorSpecVersion); + PRINT_STRUCT_VALUE_H (Struct, Type43, FirmwareVersion1); + PRINT_STRUCT_VALUE_H (Struct, Type43, FirmwareVersion2); + PRINT_PENDING_STRING (Struct, Type43, Description); + DisplayTpmDeviceCharacteristics (ReadUnaligned64 ((UINT64 *) (UINTN) &(Struct->Type43->Characteristics)), Option); + PRINT_STRUCT_VALUE_H (Struct, Type43, OemDefined); + break; + + // + // Inactive (Type 126) + // + case 126: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INACTIVE_STRUCT), gShellDebug1HiiHandle); + break; + + // + // End-of-Table (Type 127) + // + case 127: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_THIS_STRUCT_END_TABLE), gShellDebug1HiiHandle); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE_UNDEFINED), gShellDebug1HiiHandle); + break; + } + + return EFI_SUCCESS; +} + +/** + Display BIOS Information (Type 0) information. + + @param[in] Chara The information bits. + @param[in] Option The optional information. +**/ +VOID +DisplayBiosCharacteristics ( + IN UINT64 Chara, + IN UINT8 Option + ) +{ + // + // Print header + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR), gShellDebug1HiiHandle); + // + // print option + // + PRINT_INFO_OPTION (Chara, Option); + + // + // Check all the bits and print information + // This function does not use Table because table of bits + // are designed not to deal with UINT64 + // + if (BIT (Chara, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 2) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN_BIT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_NOT_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ISA_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MSA_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 6) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EISA_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PCI_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 8) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PC_CARD_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 9) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PLUG_PLAY_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 10) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_APM_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 11) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_UPGRADEABLE), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 12) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_SHADOWING), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 13) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VESA_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 14) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ECSD_SUPPORT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 15) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_FORM_CD_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 16) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SELECTED_BOOT_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 17) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_ROM_SOCKETED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 18) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_PC_CARD), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 19) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EDD_ENHANCED_DRIVER), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 20) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_NEC), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 21) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_TOSHIBA), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 22) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FLOPPY_SERVICES_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 23) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_POINT_TWO_MB), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 24) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_720_KB), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 25) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TWO_POINT_EIGHT_EIGHT_MB), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 26) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PRINT_SCREEN_SUPPORT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 27) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_SERV_SUPPORT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 28) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SERIAL_SERVICES_SUPPORT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 29) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PRINTER_SERVICES_SUPPORT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 30) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MONO_VIDEO_SUPPORT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 31) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NEC_PC_98), gShellDebug1HiiHandle); + } + // + // Just print the Reserved + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_32_47), gShellDebug1HiiHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_48_64), gShellDebug1HiiHandle); +} + +/** + Display Bios Characteristice extensions1 information. + + @param[in] Byte1 The information. + @param[in] Option The optional information. +**/ +VOID +DisplayBiosCharacteristicsExt1 ( + IN UINT8 Byte1, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (Byte1, Option); + + // + // check bit and print + // + if (BIT (Byte1, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ACPI_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_USB_LEGACY_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 2) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AGP_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_I2O_BOOT_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LS_120_BOOT_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ATAPI_ZIP_DRIVE), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 6) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_1394_BOOT_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Byte1, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SMART_BATTERY_SUPPORTED), gShellDebug1HiiHandle); + } +} + +/** + Display Bios Characteristice extensions2 information. + + @param[in] byte2 The information. + @param[in] Option The optional information. +**/ +VOID +DisplayBiosCharacteristicsExt2 ( + IN UINT8 byte2, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION_2), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (byte2, Option); + + if (BIT (byte2, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_BOOT_SPEC_SUPP), gShellDebug1HiiHandle); + } + + if (BIT (byte2, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FUNCTION_KEY_INIT), gShellDebug1HiiHandle); + } + + if (AE_SMBIOS_VERSION (0x2, 0x4)) { + if (BIT (byte2, 2) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLE_TAR_CONT_DIST), gShellDebug1HiiHandle); + } + if (AE_SMBIOS_VERSION (0x2, 0x7)) { + if (BIT (byte2, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UEFI_SPEC_SUPPORT), gShellDebug1HiiHandle); + } + if (BIT (byte2, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VIRTUAL_MACHINE), gShellDebug1HiiHandle); + } + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE), gShellDebug1HiiHandle, 5); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE), gShellDebug1HiiHandle, 3); + } + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE), gShellDebug1HiiHandle, 2); + } +} + +/** + Display Processor Information (Type 4) information. + + @param[in] Family The family value. + @param[in] Option The option value. +**/ +VOID +DisplayProcessorFamily ( + UINT8 Family, + UINT8 Option + ) +{ + // + // Print prompt message + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROCESSOR_FAMILY), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (Family, Option); + + // + // Use switch to check + // + switch (Family) { + case 0x01: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER), gShellDebug1HiiHandle); + break; + + case 0x02: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + + case 0x03: + Print (L"8086\n"); + break; + + case 0x04: + Print (L"80286\n"); + break; + + case 0x05: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL386_PROCESSOR), gShellDebug1HiiHandle); + break; + + case 0x06: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL486_PROCESSOR), gShellDebug1HiiHandle); + break; + + case 0x07: + Print (L"8087\n"); + break; + + case 0x08: + Print (L"80287\n"); + break; + + case 0x09: + Print (L"80387\n"); + break; + + case 0x0A: + Print (L"80487\n"); + break; + + case 0x0B: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x0C: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PRO_PROC), gShellDebug1HiiHandle); + break; + + case 0x0D: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_II_PROC), gShellDebug1HiiHandle); + break; + + case 0x0E: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_MMX), gShellDebug1HiiHandle); + break; + + case 0x0F: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CELERON_PROC), gShellDebug1HiiHandle); + break; + + case 0x10: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_XEON_PROC), gShellDebug1HiiHandle); + break; + + case 0x11: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_PROC), gShellDebug1HiiHandle); + break; + + case 0x12: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_M1_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x13: + Print (L"M2 Family\n"); + break; + + case 0x14: + Print (L"Intel Celeron M\n"); + break; + + case 0x15: + Print (L"Intel Pentium 4 HT\n"); + break; + + case 0x18: + Print (L"AMD Duron\n"); + break; + + case 0x19: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_K5_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x1A: + Print (L"K6 Family\n"); + break; + + case 0x1B: + Print (L"K6-2\n"); + break; + + case 0x1C: + Print (L"K6-3\n"); + break; + + case 0x1D: + Print (L"AMD Althon Processor Family\n"); + break; + + case 0x1E: + Print (L"AMD 29000 Family\n"); + break; + + case 0x1F: + Print (L"K6-2+\n"); + break; + + case 0x20: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x21: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_601), gShellDebug1HiiHandle); + break; + + case 0x22: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603), gShellDebug1HiiHandle); + break; + + case 0x23: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603_PLUS), gShellDebug1HiiHandle); + break; + + case 0x24: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_604), gShellDebug1HiiHandle); + break; + + case 0x25: + Print (L"Power PC 620\n"); + break; + + case 0x26: + Print (L"Power PC 704\n"); + break; + + case 0x27: + Print (L"Power PC 750\n"); + break; + + case 0x28: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO), gShellDebug1HiiHandle); + break; + + case 0x29: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO_MOBILE), gShellDebug1HiiHandle); + break; + + case 0x2A: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_SOLO_MOBILE), gShellDebug1HiiHandle); + break; + + case 0x2B: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_ATOM), gShellDebug1HiiHandle); + break; + + case 0x2C: + Print (L"Intel(R) Core(TM) M processor\n"); + break; + + case 0x2D: + Print (L"Intel(R) Core(TM) m3 processor\n"); + break; + + case 0x2E: + Print (L"Intel(R) Core(TM) m5 processor\n"); + break; + + case 0x2F: + Print (L"Intel(R) Core(TM) m7 processor\n"); + break; + + case 0x30: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ALPHA_FAMILY_2), gShellDebug1HiiHandle); + break; + + case 0x31: + Print (L"Alpha 21064\n"); + break; + + case 0x32: + Print (L"Alpha 21066\n"); + break; + + case 0x33: + Print (L"Alpha 21164\n"); + break; + + case 0x34: + Print (L"Alpha 21164PC\n"); + break; + + case 0x35: + Print (L"Alpha 21164a\n"); + break; + + case 0x36: + Print (L"Alpha 21264\n"); + break; + + case 0x37: + Print (L"Alpha 21364\n"); + break; + + case 0x38: + Print (L"AMD Turion II Ultra Dual-Core Mobile M Processor Family\n"); + break; + + case 0x39: + Print (L"AMD Turion II Dual-Core Mobile M Processor Family\n"); + break; + + case 0x3A: + Print (L"AMD Althon II Dual-Core M Processor Family\n"); + break; + + case 0x3B: + Print (L"AMD Opteron 6100 Series Processor\n"); + break; + + case 0x3C: + Print (L"AMD Opteron 4100 Series Processor\n"); + break; + + case 0x3D: + Print (L"AMD Opteron 6200 Series Processor\n"); + break; + + case 0x3E: + Print (L"AMD Opteron 4200 Series Processor\n"); + break; + + case 0x3F: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_FX_SERIES), gShellDebug1HiiHandle); + break; + + case 0x40: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MIPS_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x41: + Print (L"MIPS R4000\n"); + break; + + case 0x42: + Print (L"MIPS R4200\n"); + break; + + case 0x43: + Print (L"MIPS R4400\n"); + break; + + case 0x44: + Print (L"MIPS R4600\n"); + break; + + case 0x45: + Print (L"MIPS R10000\n"); + break; + + case 0x46: + Print (L"AMD C-Series Processor\n"); + break; + + case 0x47: + Print (L"AMD E-Series Processor\n"); + break; + + case 0x48: + Print (L"AMD A-Series Processor\n"); + break; + + case 0x49: + Print (L"AMD G-Series Processor\n"); + break; + + case 0x4A: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_Z_SERIES), gShellDebug1HiiHandle); + break; + + case 0x4B: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_R_SERIES), gShellDebug1HiiHandle); + break; + + case 0x4C: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_4300_SERIES), gShellDebug1HiiHandle); + break; + + case 0x4D: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_6300_SERIES), gShellDebug1HiiHandle); + break; + + case 0x4E: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3300_SERIES), gShellDebug1HiiHandle); + break; + + case 0x4F: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_FIREPRO_SERIES), gShellDebug1HiiHandle); + break; + + case 0x50: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SPARC_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x51: + Print (L"SuperSparc\n"); + break; + + case 0x52: + Print (L"microSparc II\n"); + break; + + case 0x53: + Print (L"microSparc IIep\n"); + break; + + case 0x54: + Print (L"UltraSparc\n"); + break; + + case 0x55: + Print (L"UltraSparc II\n"); + break; + + case 0x56: + Print (L"UltraSparcIIi\n"); + break; + + case 0x57: + Print (L"UltraSparcIII\n"); + break; + + case 0x58: + Print (L"UltraSparcIIIi\n"); + break; + + case 0x60: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_68040_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x61: + Print (L"68xx\n"); + break; + + case 0x62: + Print (L"68000\n"); + break; + + case 0x63: + Print (L"68010\n"); + break; + + case 0x64: + Print (L"68020\n"); + break; + + case 0x65: + Print (L"68030\n"); + break; + + case 0x66: + Print (L"AMD Athlon(TM) X4 Quad-Core Processor Family\n"); + break; + + case 0x67: + Print (L"AMD Opteron(TM) X1000 Series Processor\n"); + break; + + case 0x68: + Print (L"AMD Opteron(TM) X2000 Series APU\n"); + break; + + case 0x69: + Print (L"AMD Opteron(TM) A-Series Processor\n"); + break; + + case 0x6A: + Print (L"AMD Opteron(TM) X3000 Series APU\n"); + break; + + case 0x6B: + Print (L"AMD Zen Processor Family\n"); + break; + + case 0x70: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HOBBIT_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x78: + Print (L"Crusoe TM5000\n"); + break; + + case 0x79: + Print (L"Crusoe TM3000\n"); + break; + + case 0x7A: + Print (L"Efficeon TM8000\n"); + break; + + case 0x80: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WEITEK), gShellDebug1HiiHandle); + break; + + case 0x82: + Print (L"Itanium\n"); + break; + + case 0x83: + Print (L"AMD Athlon64\n"); + break; + + case 0x84: + Print (L"AMD Opteron\n"); + break; + + case 0x85: + Print (L"AMD Sempron\n"); + break; + + case 0x86: + Print (L"AMD Turion64 Mobile\n"); + break; + + case 0x87: + Print (L"Dual-Core AMD Opteron\n"); + break; + + case 0x88: + Print (L"AMD Athlon 64X2 DualCore\n"); + break; + + case 0x89: + Print (L"AMD Turion 64X2 Mobile\n"); + break; + + case 0x8A: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0x8B: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_THIRD_GENERATION), gShellDebug1HiiHandle); + break; + + case 0x8C: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_FX_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0x8D: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X4_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0x8E: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X2_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0x8F: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_X2_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0x90: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PA_RISC_FAMILY), gShellDebug1HiiHandle); + break; + + case 0x91: + Print (L"PA-RISC 8500\n"); + break; + + case 0x92: + Print (L"PA-RISC 8000\n"); + break; + + case 0x93: + Print (L"PA-RISC 7300LC\n"); + break; + + case 0x94: + Print (L"PA-RISC 7200\n"); + break; + + case 0x95: + Print (L"PA-RISC 7100LC\n"); + break; + + case 0x96: + Print (L"PA-RISC 7100\n"); + break; + + case 0xA0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_V30_FAMILY), gShellDebug1HiiHandle); + break; + + case 0xA1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3200_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xA2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3000_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xA3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5300_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xA4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5100_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xA5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5000_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xA6: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_LV_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xA7: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_ULV_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xA8: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7100_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xA9: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5400_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xAA: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xAB: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5200_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xAC: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7200_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xAD: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7300_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xAE: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xAF: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_MULTI_CORE), gShellDebug1HiiHandle); + break; + + case 0xB0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_XEON), gShellDebug1HiiHandle); + break; + + case 0xB1: + Print (L"Pentium III Processorwith Intel SpeedStep Technology\n"); + break; + + case 0xB2: + Print (L"Pentium 4 processor\n"); + break; + + case 0xB3: + Print (L"Intel Xeon Processor\n"); + break; + + case 0xB4: + Print (L"AS400 Family\n"); + break; + + case 0xB5: + Print (L"Intel Xeon processor MP\n"); + break; + + case 0xB6: + Print (L"AMD Althon XP Processor Family\n"); + break; + + case 0xB7: + Print (L"AMD Althon MP Promcessor Family\n"); + break; + + case 0xB8: + Print (L"Intel Itanium 2 processor\n"); + break; + + case 0xB9: + Print (L"Intel Penium M processor\n"); + break; + + case 0xBA: + Print (L"Intel Celeron D processor\n"); + break; + + case 0xBB: + Print (L"Intel Pentium D processor\n"); + break; + + case 0xBC: + Print (L"Intel Pentium Processor Extreme Edition\n"); + break; + + case 0xBD: + Print (L"Intel Core Solo Processor\n"); + break; + + case 0xBF: + Print (L"Intel Core 2 Duo Processor\n"); + break; + + case 0xC0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO), gShellDebug1HiiHandle); + break; + + case 0xC1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME), gShellDebug1HiiHandle); + break; + + case 0xC2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_QUAD), gShellDebug1HiiHandle); + break; + + case 0xC3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME), gShellDebug1HiiHandle); + break; + + case 0xC4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_DUO_MOBILE), gShellDebug1HiiHandle); + break; + + case 0xC5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO_MOBILE), gShellDebug1HiiHandle); + break; + + case 0xC6: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_I7), gShellDebug1HiiHandle); + break; + + case 0xC7: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CELERON_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xC8: + Print (L"IBM 390\n"); + break; + + case 0xC9: + Print (L"G4\n"); + break; + + case 0xCA: + Print (L"G5\n"); + break; + + case 0xCB: + Print (L"G6\n"); + break; + + case 0xCC: + Print (L"zArchitecture\n"); + break; + + case 0xCD: + Print (L"Intel Core i5 processor\n"); + break; + + case 0xCE: + Print (L"Intel Core i3 processor\n"); + break; + + case 0xCF: + Print (L"Intel Core i9 processor\n"); + break; + + case 0xD2: + Print (L"ViaC7M\n"); + break; + + case 0xD3: + Print (L"ViaC7D\n"); + break; + + case 0xD4: + Print (L"ViaC7\n"); + break; + + case 0xD5: + Print (L"Eden\n"); + break; + + case 0xD6: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_MULTI_CORE), gShellDebug1HiiHandle); + break; + + case 0xD7: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xD8: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xDA: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xDB: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xDD: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xDE: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xDF: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_MULTI_CORE), gShellDebug1HiiHandle); + break; + + case 0xE0: + Print (L"Multi-Core Intel Xeon processor 3400 Series\n"); + break; + + case 0xE4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3000_SERIES), gShellDebug1HiiHandle); + break; + + case 0xE5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_II), gShellDebug1HiiHandle); + break; + + + case 0xE6: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_EMBEDDED_OPTERON_QUAD_CORE), gShellDebug1HiiHandle); + break; + + case 0xE7: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_TRIPLE_CORE), gShellDebug1HiiHandle); + break; + + case 0xE8: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_ULTRA_DUAL_CORE_MOBILE), gShellDebug1HiiHandle); + break; + + case 0xE9: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_DUAL_CORE_MOBILE), gShellDebug1HiiHandle); + break; + + case 0xEA: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_DUAL_CORE), gShellDebug1HiiHandle); + break; + + case 0xEB: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_SI), gShellDebug1HiiHandle); + break; + + case 0xEC: + Print (L"AMD Phenom II Processor Family\n"); + break; + + case 0xED: + Print (L"AMD Althon II Processor Family\n"); + break; + + case 0xEE: + Print (L"Six-Core AMD Opteron Processor Family\n"); + break; + + case 0xEF: + Print (L"AMD Sempron M Processor Family\n"); + break; + + case 0xFA: + Print (L"i860\n"); + break; + + case 0xFB: + Print (L"i960\n"); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_PROC_FAMILY), gShellDebug1HiiHandle); + } + // + // end switch + // +} + +/** + Display processor family information. + + @param[in] Family2 The family value. + @param[in] Option The option value. +**/ +VOID +DisplayProcessorFamily2 ( + IN UINT16 Family2, + IN UINT8 Option + ) +{ + // + // Print prompt message + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROCESSOR_FAMILY), gShellDebug1HiiHandle); + + // + // Print option + // + PRINT_INFO_OPTION (Family2, Option); + + // + // Use switch to check + // + switch (Family2) { + case 0x100: + Print (L"ARMv7\n"); + break; + + case 0x101: + Print (L"ARMv8\n"); + break; + + case 0x104: + Print (L"SH-3\n"); + break; + + case 0x105: + Print (L"SH-4\n"); + break; + + case 0x118: + Print (L"ARM\n"); + break; + + case 0x119: + Print (L"StrongARM\n"); + break; + + case 0x12C: + Print (L"6x86\n"); + break; + + case 0x12D: + Print (L"MediaGX\n"); + break; + + case 0x12E: + Print (L"MII\n"); + break; + + case 0x140: + Print (L"WinChip\n"); + break; + + case 0x15E: + Print (L"DSP\n"); + break; + + case 0x1F4: + Print (L"Video Processor\n"); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_PROC_FAMILY), gShellDebug1HiiHandle); + } + +} + +/** + Display processor voltage information. + + @param[in] Voltage The Voltage. + Bit 7 Set to 0, indicating 'legacy' mode for processor voltage + Bits 6:4 Reserved, must be zero + Bits 3:0 Voltage Capability. + A Set bit indicates that the voltage is supported. + Bit 0 - 5V + Bit 1 - 3.3V + Bit 2 - 2.9V + Bit 3 - Reserved, must be zero. + + Note: + Setting of multiple bits indicates the socket is configurable + If bit 7 is set to 1, the remaining seven bits of the field are set to + contain the processor's current voltage times 10. + For example, the field value for a processor voltage of 1.8 volts would be + 92h = 80h + (1.8 * 10) = 80h + 18 = 80h +12h. + + @param[in] Option The option. +**/ +VOID +DisplayProcessorVoltage ( + IN UINT8 Voltage, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROC_INFO), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (Voltage, Option); + + if (BIT (Voltage, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROC_CURRENT_VOLTAGE), gShellDebug1HiiHandle, (Voltage - 0x80)); + } else { + if (BIT (Voltage, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_5V_SUPOPRTED), gShellDebug1HiiHandle); + } + + if (BIT (Voltage, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_33V_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Voltage, 2) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_29V_SUPPORTED), gShellDebug1HiiHandle); + } + // + // check the reserved zero bits: + // + if (BIT (Voltage, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT3_NOT_ZERO), gShellDebug1HiiHandle); + } + + if (BIT (Voltage, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO), gShellDebug1HiiHandle); + } + + if (BIT (Voltage, 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT5_NOT_ZERO), gShellDebug1HiiHandle); + } + + if (BIT (Voltage, 6) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT6_NOT_ZERO), gShellDebug1HiiHandle); + } + } +} + +/** + Display processor information. + + @param[in] Status The status. +Bit 7 Reserved, must be 0 +Bit 6 CPU Socket Populated + 1 - CPU Socket Populated + 0 - CPU Socket Unpopulated +Bits 5:3 Reserved, must be zero +Bits 2:0 CPU Status + 0h - Unknown + 1h - CPU Enabled + 2h - CPU Disabled by User via BIOS Setup + 3h - CPU Disabled By BIOS (POST Error) + 4h - CPU is Idle, waiting to be enabled. + 5-6h - Reserved + 7h - Other + + @param[in] Option The option +**/ +VOID +DisplayProcessorStatus ( + IN UINT8 Status, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROC_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + + if (BIT (Status, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT7_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (Status, 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT5_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (Status, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (Status, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT3_NOT_ZERO), gShellDebug1HiiHandle); + } + // + // Check BIT 6 + // + if (BIT (Status, 6) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_POPULATED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_UNPOPULATED), gShellDebug1HiiHandle); + } + // + // Check BITs 2:0 + // + switch (Status & 0x07) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_ENABLED), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_DISABLED_BY_USER), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_DIABLED_BY_BIOS), gShellDebug1HiiHandle); + break; + + case 4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_IDLE), gShellDebug1HiiHandle); + break; + + case 7: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHERS), gShellDebug1HiiHandle); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle); + } +} + +/** + Display information about Memory Controller Information (Type 5). + + @param[in] Size Memory size. + @param[in] SlotNum Which slot is this about. + @param[in] Option Option for the level of detail output required. +**/ +VOID +DisplayMaxMemoryModuleSize ( + IN UINT8 Size, + IN UINT8 SlotNum, + IN UINT8 Option + ) +{ + UINTN MaxSize; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SIZE_LARGEST_MEM), gShellDebug1HiiHandle); + // + // MaxSize is determined by follow formula + // + MaxSize = (UINTN) 1 << Size; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_MB), gShellDebug1HiiHandle, MaxSize); + + if (Option >= SHOW_DETAIL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MAX_AMOUNT_MEM), gShellDebug1HiiHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_MB), gShellDebug1HiiHandle, MaxSize, SlotNum, MaxSize * SlotNum); + } +} + +/** + Display information about memory configuration handles. + + @param[in] Handles The buffer of handles to output info on. + @param[in] SlotNum The number of handles in the above buffer. + @param[in] Option Option for the level of detail output required. +**/ +VOID +DisplayMemoryModuleConfigHandles ( + IN UINT16 *Handles, + IN UINT8 SlotNum, + IN UINT8 Option + ) +{ + UINT8 Index; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HANDLES_CONTROLLED), gShellDebug1HiiHandle, SlotNum); + + if (Option >= SHOW_DETAIL) { + // + // No handle, Handles is INVALID. + // + if (SlotNum == 0) { + return ; + } + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HANDLES_LIST_CONTROLLED), gShellDebug1HiiHandle); + for (Index = 0; Index < SlotNum; Index++) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HANDLE), gShellDebug1HiiHandle, Index + 1, Handles[Index]); + } + } +} + +/** + Display Memory Module Information (Type 6). + + @param[in] BankConnections + @param[in] Option +**/ +VOID +DisplayMmBankConnections ( + IN UINT8 BankConnections, + IN UINT8 Option + ) +{ + UINT8 High; + UINT8 Low; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_CONNECTIONS), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (BankConnections, Option); + + // + // Divide it to high and low + // + High = (UINT8) (BankConnections & 0xF0); + Low = (UINT8) (BankConnections & 0x0F); + if (High != 0xF) { + if (Low != 0xF) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_RAS), gShellDebug1HiiHandle, High, Low, High, Low); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_RAS_2), gShellDebug1HiiHandle, High, High); + } + } else { + if (Low != 0xF) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_RAS_2), gShellDebug1HiiHandle, Low, Low); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NO_BANKS_CONNECTED), gShellDebug1HiiHandle); + } + } +} + +/** + Display memory informcation. + + Bits 0:6 Size (n), + where 2**n is the size in MB with three special-case values: + 7Dh Not determinable (Installed Size only) + 7Eh Module is installed, but no memory has been enabled + 7Fh Not installed + Bit 7 Defines whether the memory module has a single- (0) + or double-bank (1) connection. + + @param[in] Size - The size + @param[in] Option - The option +**/ +VOID +DisplayMmMemorySize ( + IN UINT8 Size, + IN UINT8 Option + ) +{ + UINT8 Value; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEMORY_SIZE), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (Size, Option); + + // + // Get the low bits(0-6 bit) + // + Value = (UINT8) (Size & 0x7F); + if (Value == 0x7D) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE_NOT_DETERMINABLE), gShellDebug1HiiHandle); + } else if (Value == 0x7E) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MODULE_INSTALLED), gShellDebug1HiiHandle); + } else if (Value == 0x7F) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_INSTALLED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE), gShellDebug1HiiHandle, 1 << Value); + } + + if (BIT (Size, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_DOUBLE_BANK), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_SINGLE_BANK), gShellDebug1HiiHandle); + } +} + +/** + Display Cache Configuration. + + @param[in] CacheConfiguration Cache Configuration. +Bits 15:10 Reserved, must be 0 +Bits 9:8 Operational Mode + 0h - Write Through + 1h - Write Back + 2h - Varies with Memory Address + 3h - Unknown +Bit 7 Enabled/Disabled + 1 - Enabled + 0 - Disabled +Bits 6:5 Location + 0h - Internal + 1h - External + 2h - Reserved + 3h - Unknown +Bit 4 Reserved, must be zero +Bit 3 Cache Socketed + 1 - Socketed + 0 - Unsocketed +Bits 2:0 Cache Level + 1 through 8 (For example, an L1 cache would + use value 000b and an L3 cache would use 010b.) + + @param[in] Option The option +**/ +VOID +DisplayCacheConfiguration ( + IN UINT16 CacheConfiguration, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_CONFIGURATION), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (CacheConfiguration, Option); + + if (BIT (CacheConfiguration, 15) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT15_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (CacheConfiguration, 14) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT14_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (CacheConfiguration, 13) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT13_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (CacheConfiguration, 12) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT12_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (CacheConfiguration, 11) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT11_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (CacheConfiguration, 10) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT10_NOT_ZERO), gShellDebug1HiiHandle); + } else if (BIT (CacheConfiguration, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO), gShellDebug1HiiHandle); + } + + // + // Check BITs 9:8 + // + switch ((CacheConfiguration & 0x300) >> 8) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_THROUGH), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_BACK), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_VARIES_WITH_MEM_ADDR), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + } + + // + // Check BIT 7 + // + if (BIT (CacheConfiguration, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle); + } + + // + // Check BITs 6:5 + // + switch ((CacheConfiguration & 0x60) >> 5) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_INTERNAL), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_EXTERNAL), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + } + + // + // Check BIT 3 + // + if (BIT (CacheConfiguration, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_SOCKETED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_NOT_SOCKETED), gShellDebug1HiiHandle); + } + + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_LEVEL), gShellDebug1HiiHandle, (CacheConfiguration & 0x07) + 1); +} + +/** + The Slot ID field of the System Slot structure provides a mechanism to + correlate the physical attributes of the slot to its logical access method + (which varies based on the Slot Type field). + + @param[in] SlotId - The slot ID + @param[in] SlotType - The slot type + @param[in] Option - The Option +**/ +VOID +DisplaySystemSlotId ( + IN UINT16 SlotId, + IN UINT8 SlotType, + IN UINT8 Option + ) +{ + // + // Display slot type first + // + DisplaySystemSlotType (SlotType, Option); + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SLOT_ID), gShellDebug1HiiHandle); + // + // print option + // + PRINT_INFO_OPTION (SlotType, Option); + + switch (SlotType) { + // + // Slot Type: MCA + // + case 0x04: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LOGICAL_MICRO_CHAN), gShellDebug1HiiHandle); + if (SlotId > 0 && SlotId < 15) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_D), gShellDebug1HiiHandle, SlotId); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ERROR_NOT_1_15), gShellDebug1HiiHandle); + } + break; + + // + // EISA + // + case 0x05: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LOGICAL_EISA_NUM), gShellDebug1HiiHandle); + if (SlotId > 0 && SlotId < 15) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_D), gShellDebug1HiiHandle, SlotId); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ERROR_NOT_1_15), gShellDebug1HiiHandle); + } + break; + + // + // Slot Type: PCI + // + case 0x06: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT), gShellDebug1HiiHandle, SlotId); + break; + + // + // PCMCIA + // + case 0x07: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_IDENTIFIES_ADAPTER_NUM), gShellDebug1HiiHandle, SlotId); + break; + + // + // Slot Type: PCI-E + // + case 0xA5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT), gShellDebug1HiiHandle, SlotId); + break; + + default: + if ((SlotType >= 0x0E && SlotType <= 0x12) || (SlotType >= 0xA6 && SlotType <= 0xB6)){ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT), gShellDebug1HiiHandle, SlotId); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_SLOT_ID), gShellDebug1HiiHandle); + } + } +} + +/** + Display System Boot Information (Type 32) information. + + @param[in] Parameter The parameter. + @param[in] Option The options. +**/ +VOID +DisplaySystemBootStatus ( + IN UINT8 Parameter, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_BOOT_STATUS), gShellDebug1HiiHandle); + // + // Print option + // + PRINT_INFO_OPTION (Parameter, Option); + + // + // Check value and print + // + if (Parameter == 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NO_ERRORS_DETECTED), gShellDebug1HiiHandle); + } else if (Parameter == 1) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NO_BOOTABLE_MEDIA), gShellDebug1HiiHandle); + } else if (Parameter == 2) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NORMAL_OP_SYSTEM), gShellDebug1HiiHandle); + } else if (Parameter == 3) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FIRMWARE_DETECTED), gShellDebug1HiiHandle); + } else if (Parameter == 4) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM), gShellDebug1HiiHandle); + } else if (Parameter == 5) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_USER_REQUESTED_BOOT), gShellDebug1HiiHandle); + } else if (Parameter == 6) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_SECURITY_VIOLATION), gShellDebug1HiiHandle); + } else if (Parameter == 7) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PREV_REQ_IMAGE), gShellDebug1HiiHandle); + } else if (Parameter == 8) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER), gShellDebug1HiiHandle); + } else if (Parameter >= 9 && Parameter <= 127) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RSVD_FUTURE_ASSIGNMENT), gShellDebug1HiiHandle); + } else if (Parameter >= 128 && Parameter <= 191) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VENDOR_OEM_SPECIFIC), gShellDebug1HiiHandle); + } else if (Parameter >= 192) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PRODUCT_SPEC_IMPLMENTATION), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ERROR_VALUE), gShellDebug1HiiHandle); + } +} + +/** + Display Portable Battery (Type 22) information. + + The date the cell pack was manufactured, in packed format: + Bits 15:9 Year, biased by 1980, in the range 0 to 127. + Bits 8:5 Month, in the range 1 to 12. + Bits 4:0 Date, in the range 1 to 31. + For example, 01 February 2000 would be identified as + 0010 1000 0100 0001b (0x2841). + + @param[in] Date The date + @param[in] Option The option +**/ +VOID +DisplaySBDSManufactureDate ( + IN UINT16 Date, + IN UINT8 Option + ) +{ + UINTN Day; + UINTN Month; + UINTN Year; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SBDS_MANUFACTURE_DATE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Date, Option); + // + // Print date + // + Day = Date & 0x001F; + Month = (Date & 0x01E0) >> 5; + Year = ((Date & 0xFE00) >> 9) + 1980; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MONTH_DAY_YEAR), gShellDebug1HiiHandle, Day, Month, Year); + +} + +/** + Display System Reset (Type 23) information. + + +Identifies the system-reset capabilities for the system. + Bits 7:6 Reserved for future assignment via this specification, set to 00b. + Bit 5 System contains a watchdog timer, either True (1) or False (0). + Bits 4:3 Boot Option on Limit. + Identifies the system action to be taken when the Reset Limit is reached, one of: + 00b Reserved, do not use. + 01b Operating system + 10b System utilities + 11b Do not rebootBits + 2:1 Boot Option. Indicates the action to be taken following a watchdog reset, one of: + 00b Reserved, do not use. + 01b Operating system + 10b System utilities + 11b Do not reboot + Bit 0 Status. + 1b The system reset is enabled by the user + 0b The system reset is not enabled by the user + + @param[in] Reset Reset + @param[in] Option The option +**/ +VOID +DisplaySystemResetCapabilities ( + IN UINT8 Reset, + IN UINT8 Option + ) +{ + UINTN Temp; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_RESET_CAPABILITIES), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Reset, Option); + + // + // Check reserved bits 7:6 + // + if ((Reset & 0xC0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO), gShellDebug1HiiHandle); + } + // + // Watch dog + // + if (BIT (Reset, 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER_2), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_NOT_CONTAIN_TIMER), gShellDebug1HiiHandle); + } + // + // Boot Option on Limit + // + Temp = (Reset & 0x18) >> 3; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION_LIMIT), gShellDebug1HiiHandle); + switch (Temp) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT_BITS), gShellDebug1HiiHandle); + break; + } + // + // Boot Option + // + Temp = (Reset & 0x06) >> 1; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION), gShellDebug1HiiHandle); + switch (Temp) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT), gShellDebug1HiiHandle); + break; + } + // + // Reset enable flag + // + if ((Reset & 0x01) != 0) { + Print (L"The system reset is enabled by the user\n"); + } else { + Print (L"The system reset is disabled by the user\n"); + } +} + +/** + Display Hardware Security (Type 24) information. + + +Identifies the password and reset status for the system: + +Bits 7:6 Power-on Password Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown +Bits 5:4 Keyboard Password Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown +Bits 3:2 Administrator Password Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown +Bits 1:0 Front Panel Reset Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown + + @param[in] Settings The device settings. + @param[in] Option The device options. +**/ +VOID +DisplayHardwareSecuritySettings ( + IN UINT8 Settings, + IN UINT8 Option + ) +{ + UINTN Temp; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HARDWARE_SECURITY_SET), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Settings, Option); + + // + // Power-on Password Status + // + Temp = (Settings & 0xC0) >> 6; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_ON_PASSWORD), gShellDebug1HiiHandle); + switch (Temp) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + } + // + // Keyboard Password Status + // + Temp = (Settings & 0x30) >> 4; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_PASSWORD), gShellDebug1HiiHandle); + switch (Temp) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + } + // + // Administrator Password Status + // + Temp = (Settings & 0x0C) >> 2; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ADMIN_PASSWORD_STATUS), gShellDebug1HiiHandle); + switch (Temp) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + } + // + // Front Panel Reset Status + // + Temp = Settings & 0x3; + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FRONT_PANEL_RESET), gShellDebug1HiiHandle); + switch (Temp) { + case 0: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle); + break; + + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + } +} + +/** + Display Out-of-Band Remote Access (Type 30) information. + + @param[in] Connections The device characteristics. + @param[in] Option The device options. +**/ +VOID +DisplayOBRAConnections ( + IN UINT8 Connections, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CONNECTIONS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Connections, Option); + + // + // Check reserved bits 7:2 + // + if ((Connections & 0xFC) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO_2), gShellDebug1HiiHandle); + } + // + // Outbound Connection + // + if (BIT (Connections, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OUTBOUND_CONN_ENABLED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTUBOUND_CONN_DISABLED), gShellDebug1HiiHandle); + } + // + // Inbound Connection + // + if (BIT (Connections, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INBOIUND_CONN_ENABLED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INBOUND_CONN_DISABLED), gShellDebug1HiiHandle); + } +} + +/** + Display System Power Supply (Type 39) information. + + @param[in] Characteristics The device characteristics. + @param[in] Option The device options. +**/ +VOID +DisplaySPSCharacteristics ( + IN UINT16 Characteristics, + IN UINT8 Option + ) +{ + UINTN Temp; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_CHAR), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Characteristics, Option); + + // + // Check reserved bits 15:14 + // + if ((Characteristics & 0xC000) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_15_14_RSVD), gShellDebug1HiiHandle); + } + // + // Bits 13:10 - DMTF Power Supply Type + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TYPE), gShellDebug1HiiHandle); + Temp = (Characteristics & 0x1C00) >> 10; + switch (Temp) { + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LINEAR), gShellDebug1HiiHandle); + break; + + case 4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SWITCHING), gShellDebug1HiiHandle); + break; + + case 5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BATTERY), gShellDebug1HiiHandle); + break; + + case 6: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UPS), gShellDebug1HiiHandle); + break; + + case 7: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CONVERTER), gShellDebug1HiiHandle); + break; + + case 8: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_REGULATOR), gShellDebug1HiiHandle); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_2), gShellDebug1HiiHandle); + } + // + // Bits 9:7 - Status + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STATUS_DASH), gShellDebug1HiiHandle); + Temp = (Characteristics & 0x380) >> 7; + switch (Temp) { + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OK), gShellDebug1HiiHandle); + break; + + case 4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NON_CRITICAL), gShellDebug1HiiHandle); + break; + + case 5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CRITICAL_POWER_SUPPLY), gShellDebug1HiiHandle); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED), gShellDebug1HiiHandle); + } + // + // Bits 6:3 - DMTF Input Voltage Range Switching + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INPUT_VOLTAGE_RANGE), gShellDebug1HiiHandle); + Temp = (Characteristics & 0x78) >> 3; + switch (Temp) { + case 1: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE), gShellDebug1HiiHandle); + break; + + case 2: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle); + break; + + case 3: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MANUAL), gShellDebug1HiiHandle); + break; + + case 4: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AUTO_SWITCH), gShellDebug1HiiHandle); + break; + + case 5: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WIDE_RANGE), gShellDebug1HiiHandle); + break; + + case 6: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_APPLICABLE), gShellDebug1HiiHandle); + break; + + default: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_3), gShellDebug1HiiHandle); + break; + } + // + // Power supply is unplugged from the wall + // + if (BIT (Characteristics, 2) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_UNPLUGGED), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PLUGGED), gShellDebug1HiiHandle); + } + // + // Power supply is present + // + if (BIT (Characteristics, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PRESENT), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_PRESENT), gShellDebug1HiiHandle); + } + // + // hot replaceable + // + if (BIT (Characteristics, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_REPLACE), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_REPLACE), gShellDebug1HiiHandle); + } +} + +/** + Display TPM Device (Type 43) Characteristics. + + @param[in] Chara The information bits. + @param[in] Option The optional information. +**/ +VOID +DisplayTpmDeviceCharacteristics ( + IN UINT64 Chara, + IN UINT8 Option + ) +{ + // + // Print header + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CHAR), gShellDebug1HiiHandle); + // + // print option + // + PRINT_INFO_OPTION (Chara, Option); + + // + // Check all the bits and print information + // This function does not use Table because table of bits + // are designed not to deal with UINT64 + // + if (BIT (Chara, 0) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 1) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT), gShellDebug1HiiHandle); + } + if (BIT (Chara, 2) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CHAR_NOT_SUPPORTED), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 3) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CONFIG_FWU), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CONFIG_PLAT_SW), gShellDebug1HiiHandle); + } + + if (BIT (Chara, 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CONFIG_OEM), gShellDebug1HiiHandle); + } + + // + // Just print the Reserved + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_06_63), gShellDebug1HiiHandle); + +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h new file mode 100644 index 0000000..3a5aa0a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h @@ -0,0 +1,436 @@ +/** @file + Module to clarify the element info of the smbios structure. + + Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.
        + (C) Copyright 2017 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMBIOS_PRINT_INFO_H_ +#define _SMBIOS_PRINT_INFO_H_ + +#include + +extern UINT8 SmbiosMajorVersion; +extern UINT8 SmbiosMinorVersion; + +#define SHOW_NONE 0x00 +#define SHOW_OUTLINE 0x01 +#define SHOW_NORMAL 0x02 +#define SHOW_DETAIL 0x03 +// +// SHOW_ALL: WaitEnter() not wait input. +// +#define SHOW_ALL 0x04 +#define SHOW_STATISTICS 0x05 + +#define AS_UINT16(pData) (*((UINT16 *) pData)) +#define AS_UINT32(pData) (*((UINT32 *) pData)) +#define AS_UINT64(pData) (*((UINT64 *) pData)) + +/** + Print the info of EPS(Entry Point Structure). + + @param[in] SmbiosTable Pointer to the SMBIOS table entry point. + @param[in] Option Display option. +**/ +VOID +SmbiosPrintEPSInfo ( + IN SMBIOS_TABLE_ENTRY_POINT *SmbiosTable, + IN UINT8 Option + ); + +/** + Print the info of 64-bit EPS(Entry Point Structure). + + @param[in] SmbiosTable Pointer to the SMBIOS table entry point. + @param[in] Option Display option. +**/ +VOID +Smbios64BitPrintEPSInfo ( + IN SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosTable, + IN UINT8 Option + ); + +/** + This function print the content of the structure pointed by Struct. + + @param[in] Struct Point to the structure to be printed. + @param[in] Option Print option of information detail. + + @retval EFI_SUCCESS Successfully Printing this function. + @retval EFI_INVALID_PARAMETER Invalid Structure. + @retval EFI_UNSUPPORTED Unsupported. +**/ +EFI_STATUS +SmbiosPrintStructure ( + IN SMBIOS_STRUCTURE_POINTER *Struct, + IN UINT8 Option + ); + +/** + Display BIOS Information (Type 0) information. + + @param[in] Chara The information bits. + @param[in] Option The optional information. +**/ +VOID +DisplayBiosCharacteristics ( + IN UINT64 Chara, + IN UINT8 Option + ); + +/** + Display Bios Characteristice extensions1 information. + + @param[in] Byte1 The information. + @param[in] Option The optional information. +**/ +VOID +DisplayBiosCharacteristicsExt1 ( + IN UINT8 Byte1, + IN UINT8 Option + ); + +/** + Display Bios Characteristice extensions2 information. + + @param[in] Byte2 The information. + @param[in] Option The optional information. +**/ +VOID +DisplayBiosCharacteristicsExt2 ( + IN UINT8 Byte2, + IN UINT8 Option + ); + +/** + Display Processor Information (Type 4) information. + + @param[in] Family The family value. + @param[in] Option The option value. +**/ +VOID +DisplayProcessorFamily ( + UINT8 Family, + UINT8 Option + ); + +/** + Display processor family information. + + @param[in] Family2 The family value. + @param[in] Option The option value. +**/ +VOID +DisplayProcessorFamily2 ( + IN UINT16 Family2, + IN UINT8 Option + ); + +/** + Display processor voltage information. + + @param[in] Voltage The Voltage. + Bit 7 Set to 0, indicating 'legacy' mode for processor voltage + Bits 6:4 Reserved, must be zero + Bits 3:0 Voltage Capability. + A Set bit indicates that the voltage is supported. + Bit 0 - 5V + Bit 1 - 3.3V + Bit 2 - 2.9V + Bit 3 - Reserved, must be zero. + + Note: + Setting of multiple bits indicates the socket is configurable + If bit 7 is set to 1, the remaining seven bits of the field are set to + contain the processor's current voltage times 10. + For example, the field value for a processor voltage of 1.8 volts would be + 92h = 80h + (1.8 * 10) = 80h + 18 = 80h +12h. + + @param[in] Option The option. +**/ +VOID +DisplayProcessorVoltage ( + IN UINT8 Voltage, + IN UINT8 Option + ); + +/** + Display processor information. + + @param[in] Status The status. +Bit 7 Reserved, must be 0 +Bit 6 CPU Socket Populated + 1 - CPU Socket Populated + 0 - CPU Socket Unpopulated +Bits 5:3 Reserved, must be zero +Bits 2:0 CPU Status + 0h - Unknown + 1h - CPU Enabled + 2h - CPU Disabled by User via BIOS Setup + 3h - CPU Disabled By BIOS (POST Error) + 4h - CPU is Idle, waiting to be enabled. + 5-6h - Reserved + 7h - Other + + @param[in] Option The option +**/ +VOID +DisplayProcessorStatus ( + IN UINT8 Status, + IN UINT8 Option + ); + +/** + Display information about Memory Controller Information (Type 5). + + @param[in] Size Memory size. + @param[in] SlotNum Which slot is this about. + @param[in] Option Option for the level of detail output required. +**/ +VOID +DisplayMaxMemoryModuleSize ( + IN UINT8 Size, + IN UINT8 SlotNum, + IN UINT8 Option + ); + +/** + Display information about memory configuration handles. + + @param[in] Handles The buffer of handles to output info on. + @param[in] SlotNum The number of handles in the above buffer. + @param[in] Option Option for the level of detail output required. +**/ +VOID +DisplayMemoryModuleConfigHandles ( + IN UINT16 *Handles, + IN UINT8 SlotNum, + IN UINT8 Option + ); + +/** + Display Memory Module Information (Type 6). + + @param[in] BankConnections + @param[in] Option +**/ +VOID +DisplayMmBankConnections ( + IN UINT8 BankConnections, + IN UINT8 Option + ); + +/** + Display memory informcation. + + Bits 0:6 Size (n), + where 2**n is the size in MB with three special-case values: + 7Dh Not determinable (Installed Size only) + 7Eh Module is installed, but no memory has been enabled + 7Fh Not installed + Bit 7 Defines whether the memory module has a single- (0) + or double-bank (1) connection. + + @param[in] Size - The size + @param[in] Option - The option +**/ +VOID +DisplayMmMemorySize ( + IN UINT8 Size, + IN UINT8 Option + ); + +/** + Display Cache Configuration. + + @param[in] CacheConfiguration Cache Configuration. +Bits 15:10 Reserved, must be 0 +Bits 9:8 Operational Mode + 0h - Write Through + 1h - Write Back + 2h - Varies with Memory Address + 3h - Unknown +Bit 7 Enabled/Disabled + 1 - Enabled + 0 - Disabled +Bits 6:5 Location + 0h - Internal + 1h - External + 2h - Reserved + 3h - Unknown +Bit 4 Reserved, must be zero +Bit 3 Cache Socketed + 1 - Socketed + 0 - Unsocketed +Bits 2:0 Cache Level + 1 through 8 (For example, an L1 cache would + use value 000b and an L3 cache would use 010b.) + + @param[in] Option The option +**/ +VOID +DisplayCacheConfiguration ( + IN UINT16 CacheConfiguration, + IN UINT8 Option + ); + +/** + The Slot ID field of the System Slot structure provides a mechanism to + correlate the physical attributes of the slot to its logical access method + (which varies based on the Slot Type field). + + @param[in] SlotId - The slot ID + @param[in] SlotType - The slot type + @param[in] Option - The Option +**/ +VOID +DisplaySystemSlotId ( + IN UINT16 SlotId, + IN UINT8 SlotType, + IN UINT8 Option + ); + +/** + Display Portable Battery (Type 22) information. + + The date the cell pack was manufactured, in packed format: + Bits 15:9 Year, biased by 1980, in the range 0 to 127. + Bits 8:5 Month, in the range 1 to 12. + Bits 4:0 Date, in the range 1 to 31. + For example, 01 February 2000 would be identified as + 0010 1000 0100 0001b (0x2841). + + @param[in] Date The date + @param[in] Option The option +**/ +VOID +DisplaySBDSManufactureDate ( + IN UINT16 Date, + IN UINT8 Option + ); + +/** + Display System Reset (Type 23) information. + + Routine Description: + Identifies the system-reset capabilities for the system. + Bits 7:6 Reserved for future assignment via this specification, set to 00b. + Bit 5 System contains a watchdog timer, either True (1) or False (0). + Bits 4:3 Boot Option on Limit. + Identifies the system action to be taken when the Reset Limit is reached, one of: + 00b Reserved, do not use. + 01b Operating system + 10b System utilities + 11b Do not rebootBits + 2:1 Boot Option. Indicates the action to be taken following a watchdog reset, one of: + 00b Reserved, do not use. + 01b Operating system + 10b System utilities + 11b Do not reboot + Bit 0 Status. + 1b The system reset is enabled by the user + 0b The system reset is not enabled by the user + + @param[in] Reset Reset + @param[in] Option The option +**/ +VOID +DisplaySystemResetCapabilities ( + IN UINT8 Reset, + IN UINT8 Option + ); + +/** + Display Hardware Security (Type 24) information. + + Routine Description: + Identifies the password and reset status for the system: + + Bits 7:6 Power-on Password Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown + Bits 5:4 Keyboard Password Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown + Bits 3:2 Administrator Password Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown + Bits 1:0 Front Panel Reset Status, one of: + 00b Disabled + 01b Enabled + 10b Not Implemented + 11b Unknown + + @param[in] Settings The device settings. + @param[in] Option The device options. +**/ +VOID +DisplayHardwareSecuritySettings ( + IN UINT8 Settings, + IN UINT8 Option + ); + +/** + Display Out-of-Band Remote Access (Type 30) information. + + @param[in] Connections The device characteristics. + @param[in] Option The device options. +**/ +VOID +DisplayOBRAConnections ( + IN UINT8 Connections, + IN UINT8 Option + ); + +/** + Display System Boot Information (Type 32) information. + + @param[in] Parameter The parameter. + @param[in] Option The options. +**/ +VOID +DisplaySystemBootStatus ( + IN UINT8 Parameter, + IN UINT8 Option + ); + +/** + Display System Power Supply (Type 39) information. + + @param[in] Characteristics The device characteristics. + @param[in] Option The device options. +**/ +VOID +DisplaySPSCharacteristics ( + IN UINT16 Characteristics, + IN UINT8 Option + ); + +/** + Display TPM Device (Type 43) Characteristics. + + @param[in] Chara The information bits. + @param[in] Option The optional information. +**/ +VOID +DisplayTpmDeviceCharacteristics ( + IN UINT64 Chara, + IN UINT8 Option + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c new file mode 100644 index 0000000..1036626 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c @@ -0,0 +1,4723 @@ +/** @file + Build a table, each item is (Key, Info) pair. + And give a interface of query a string out of a table. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "QueryTable.h" +#include "PrintInfo.h" + +TABLE_ITEM SystemWakeupTypeTable[] = { + { + 0x0, + L" Reserved" + }, + { + 0x1, + L" Other" + }, + { + 0x2, + L" Unknown" + }, + { + 0x3, + L" APM Timer" + }, + { + 0x4, + L" Modem Ring" + }, + { + 0x5, + L" LAN Remote" + }, + { + 0x6, + L" Power Switch" + }, + { + 0x7, + L" AC Power Restored" + } +}; + +TABLE_ITEM BaseBoardFeatureFlagsTable[] = { + { + 0, + L" Hosting board" + }, + { + 1, + L" Requires at least one daughter board or auxiliary card" + }, + { + 2, + L" Removable" + }, + { + 3, + L" Replaceable" + }, + { + 4, + L" Hot swappable" + } +}; + +TABLE_ITEM BaseBoardBoardTypeTable[] = { + { + 0x01, + L" Unknown" + }, + { + 0x02, + L" Other" + }, + { + 0x03, + L" Server Blade" + }, + { + 0x04, + L" Connectivity Switch" + }, + { + 0x05, + L" System Management Module" + }, + { + 0x06, + L" Processor Module" + }, + { + 0x07, + L" I/O Module" + }, + { + 0x08, + L" Memory Module" + }, + { + 0x09, + L" Daughter board" + }, + { + 0x0A, + L" Motherboard" + }, + { + 0x0B, + L" Processor/Memory Module" + }, + { + 0x0C, + L" Processor/IO Module" + }, + { + 0x0D, + L" Interconnect Board" + } +}; + +TABLE_ITEM SystemEnclosureTypeTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Desktop" + }, + { + 0x04, + L" Low Profile Desktop" + }, + { + 0x05, + L" Pizza Box" + }, + { + 0x06, + L" Mini Tower" + }, + { + 0x07, + L" Tower" + }, + { + 0x08, + L" Portable" + }, + { + 0x09, + L" Laptop" + }, + { + 0x0A, + L" Notebook" + }, + { + 0x0B, + L" Hand Held" + }, + { + 0x0C, + L" Docking Station" + }, + { + 0x0D, + L" All in One" + }, + { + 0x0E, + L" Sub Notebook" + }, + { + 0x0F, + L" Space-saving" + }, + { + 0x10, + L" Main Server Chassis" + }, + { + 0x11, + L" Expansion Chassis" + }, + { + 0x12, + L" SubChassis" + }, + { + 0x13, + L" Sub Notebook" + }, + { + 0x14, + L" Bus Expansion Chassis" + }, + { + 0x15, + L" Peripheral Chassis" + }, + { + 0x16, + L" RAID Chassis" + }, + { + 0x17, + L" Rack Mount Chassis" + }, + { + 0x18, + L" Sealed-case PC" + }, + { + 0x19, + L" Multi-system Chassis" + }, + { + 0x1A, + L" CompactPCI" + }, + { + 0x1B, + L" AdvancedTCA" + }, + { + 0x1C, + L" Blade" + }, + { + 0x1D, + L" Blade Enclosure" + }, + { + 0x1E, + L" Tablet" + }, + { + 0x1F, + L" Convertible" + }, + { + 0x20, + L" Detachable" + }, + { + 0x21, + L" IoT Gateway" + }, + { + 0x22, + L" Embedded PC" + }, + { + 0x23, + L" Mini PC" + }, + { + 0x24, + L" Stick PC" + }, +}; + +TABLE_ITEM SystemEnclosureStatusTable[] = { + { + 0x1, + L" Other" + }, + { + 0x2, + L" Unknown" + }, + { + 0x3, + L" Safe" + }, + { + 0x4, + L" Warning" + }, + { + 0x5, + L" Critical" + }, + { + 0x6, + L" Non-recoverable" + } +}; + +TABLE_ITEM SESecurityStatusTable[] = { + { + 0x1, + L" Other" + }, + { + 0x2, + L" Unknown" + }, + { + 0x3, + L" None" + }, + { + 0x4, + L" External interface locked out" + }, + { + 0x5, + L" External interface enabled" + } +}; + +TABLE_ITEM ProcessorTypeTable[] = { + { + 0x1, + L" Other" + }, + { + 0x2, + L" Unknown" + }, + { + 0x3, + L" Central Processor" + }, + { + 0x4, + L" Math Processor" + }, + { + 0x5, + L" DSP Processor" + }, + { + 0x6, + L" Video Processor " + }, +}; + +TABLE_ITEM ProcessorUpgradeTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"Daughter Board" + }, + { + 0x04, + L"ZIF Socket" + }, + { + 0x05, + L"Replaceable Piggy Back" + }, + { + 0x06, + L"None" + }, + { + 0x07, + L"LIF Socket" + }, + { + 0x08, + L"Slot 1" + }, + { + 0x09, + L"Slot 2" + }, + { + 0x0A, + L"370-pin socket" + }, + { + 0x0B, + L"Slot A" + }, + { + 0x0C, + L"Slot M" + }, + { + 0x0D, + L"Socket 423" + }, + { + 0x0E, + L"Socket A" + }, + { + 0x0F, + L"Socket 478" + }, + { + 0x10, + L"Socket 754" + }, + { + 0x11, + L"Socket 940" + }, + { + 0x12, + L"Socket 939" + }, + { + 0x13, + L"Socket mPGA604" + }, + { + 0x14, + L"Socket LGA771" + }, + { + 0x15, + L"Socket LGA775" + }, + { + 0x16, + L"Socket S1" + }, + { + 0x17, + L"Socket AM2" + }, + { + 0x18, + L"Socket F" + }, + { + 0x19, + L"Socket LGA1366" + }, + { + 0x1A, + L"Socket G34" + }, + { + 0x1B, + L"Socket AM3" + }, + { + 0x1C, + L"Socket C32" + }, + { + 0x1D, + L"Socket LGA1156" + }, + { + 0x1E, + L"Socket LGA1567" + }, + { + 0x1F, + L"Socket PGA988A" + }, + { + 0x20, + L"Socket BGA1288" + }, + { + 0x21, + L"Socket rPGA988B" + }, + { + 0x22, + L"Socket BGA1023" + }, + { + 0x23, + L"Socket BGA1224" + }, + { + 0x24, + L"Socket LGA1155" + }, + { + 0x25, + L"Socket LGA1356" + }, + { + 0x26, + L"Socket LGA2011" + }, + { + 0x27, + L"Socket FS1" + }, + { + 0x28, + L"Socket FS2" + }, + { + 0x29, + L"Socket FM1" + }, + { + 0x2A, + L"Socket FM2" + }, + { + 0x2B, + L"Socket LGA2011-3" + }, + { + 0x2C, + L"Socket LGA1356-3" + }, + { + 0x2D, + L"Socket LGA1150" + }, + { + 0x2E, + L"Socket BGA1168" + }, + { + 0x2F, + L"Socket BGA1234" + }, + { + 0x30, + L"Socket BGA1364" + }, + { + 0x31, + L"Socket AM4" + }, + { + 0x32, + L"Socket LGA1151" + }, + { + 0x33, + L"Socket BGA1356" + }, + { + 0x34, + L"Socket BGA1440" + }, + { + 0x35, + L"Socket BGA1515" + }, + { + 0x36, + L"Socket LGA3647-1" + }, + { + 0x37, + L"Socket SP3" + }, + { + 0x38, + L"Socket SP3r2" + }, + { + 0x39, + L"Socket LGA2066" + }, + { + 0x3A, + L"Socket BGA1392" + }, + { + 0x3B, + L"Socket BGA1510" + }, + { + 0x3C, + L"Socket BGA1528" + } +}; + +TABLE_ITEM ProcessorCharacteristicsTable[] = { + { + 1, + L" Unknown" + }, + { + 2, + L" 64-bit Capable" + }, + { + 3, + L" Multi-Core" + }, + { + 4, + L" Hardware Thread" + }, + { + 5, + L" Execute Protection" + }, + { + 6, + L" Enhanced Virtualization" + }, + { + 7, + L" Power/Performance Control" + } +}; + + +TABLE_ITEM McErrorDetectMethodTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"None" + }, + { + 0x04, + L"8-bit Parity" + }, + { + 0x05, + L"32-bit ECC" + }, + { + 0x06, + L"64-bit ECC" + }, + { + 0x07, + L"128-bit ECC" + }, + { + 0x08, + L"CRC" + }, +}; + +TABLE_ITEM McErrorCorrectCapabilityTable[] = { + { + 0, + L"Other" + }, + { + 1, + L"Unknown" + }, + { + 2, + L"None" + }, + { + 3, + L"Single Bit Error Correcting" + }, + { + 4, + L"Double Bit Error Correcting" + }, + { + 5, + L"Error Scrubbing" + }, +}; + +TABLE_ITEM McInterleaveSupportTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"One Way Interleave" + }, + { + 0x04, + L"Two Way Interleave" + }, + { + 0x05, + L"Four Way Interleave" + }, + { + 0x06, + L"Eight Way Interleave" + }, + { + 0x07, + L"Sixteen Way Interleave" + } +}; + +TABLE_ITEM McMemorySpeedsTable[] = { + { + 0, + L" Other" + }, + { + 1, + L" Unknown" + }, + { + 2, + L" 70ns" + }, + { + 3, + L" 60ns" + }, + { + 4, + L" 50ns" + }, +}; + +TABLE_ITEM MemoryModuleVoltageTable[] = { + { + 0, + L" 5V" + }, + { + 1, + L" 3.3V" + }, + { + 2, + L" 2.9V" + }, +}; + +TABLE_ITEM MmMemoryTypeTable[] = { + { + 0, + L" Other" + }, + { + 1, + L" Unknown" + }, + { + 2, + L" Standard" + }, + { + 3, + L" Fast Page Mode" + }, + { + 4, + L" EDO" + }, + { + 5, + L" Parity" + }, + { + 6, + L" ECC " + }, + { + 7, + L" SIMM" + }, + { + 8, + L" DIMM" + }, + { + 9, + L" Burst EDO" + }, + { + 10, + L" SDRAM" + } +}; + +TABLE_ITEM MmErrorStatusTable[] = { + { + 0, + L" Uncorrectable errors received" + }, + { + 1, + L" Correctable errors received" + }, + { + 2, + L" Error Status obtained from the event log" + } +}; + +TABLE_ITEM CacheSRAMTypeTable[] = { + { + 0, + L" Other" + }, + { + 1, + L" Unknown" + }, + { + 2, + L" Non-Burst" + }, + { + 3, + L" Burst" + }, + { + 4, + L" Pipeline Burst" + }, + { + 5, + L" Synchronous" + }, + { + 6, + L" Asynchronous" + }, +}; + +TABLE_ITEM CacheErrCorrectingTypeTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"None" + }, + { + 0x04, + L"Parity" + }, + { + 0x05, + L"Single-bit ECC" + }, + { + 0x06, + L"Multi-bit ECC" + } +}; + +TABLE_ITEM CacheSystemCacheTypeTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"Instruction" + }, + { + 0x04, + L"Data" + }, + { + 0x05, + L"Unified" + } +}; + +TABLE_ITEM CacheAssociativityTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"Direct Mapped" + }, + { + 0x04, + L"2-way Set-Associative" + }, + { + 0x05, + L"4-way Set-Associative" + }, + { + 0x06, + L"Fully Associative" + }, + { + 0x07, + L"8-way Set-Associative" + }, + { + 0x08, + L"16-way Set-Associative" + }, + { + 0x09, + L"12-way Set-Associative" + }, + { + 0x0A, + L"24-way Set-Associative" + }, + { + 0x0B, + L"32-way Set-Associative" + }, + { + 0x0C, + L"48-way Set-Associative" + }, + { + 0x0D, + L"64-way Set-Associative" + }, + { + 0x0E, + L"20-way Set-Associative" + } +}; + +TABLE_ITEM PortConnectorTypeTable[] = { + { + 0x00, + L"None" + }, + { + 0x01, + L"Centronics" + }, + { + 0x02, + L"Mini Centronics" + }, + { + 0x03, + L"Proprietary" + }, + { + 0x04, + L"DB-25 pin male" + }, + { + 0x05, + L"DB-25 pin female" + }, + { + 0x06, + L"DB-15 pin male" + }, + { + 0x07, + L"DB-15 pin female" + }, + { + 0x08, + L"DB-9 pin male" + }, + { + 0x09, + L"DB-9 pin female" + }, + { + 0x0A, + L"RJ-11" + }, + { + 0x0B, + L"RJ-45" + }, + { + 0x0C, + L"50 Pin MiniSCSI" + }, + { + 0x0D, + L"Mini-DIN" + }, + { + 0x0E, + L"Micro-DIN" + }, + { + 0x0F, + L"PS/2" + }, + { + 0x10, + L"Infrared" + }, + { + 0x11, + L"HP-HIL" + }, + { + 0x12, + L"Access Bus (USB)" + }, + { + 0x13, + L"SSA SCSI" + }, + { + 0x14, + L"Circular DIN-8 male" + }, + { + 0x15, + L"Circular DIN-8 female" + }, + { + 0x16, + L"On Board IDE" + }, + { + 0x17, + L"On Board Floppy" + }, + { + 0x18, + L"9 Pin Dual Inline (pin 10 cut)" + }, + { + 0x19, + L"25 Pin Dual Inline (pin 26 cut)" + }, + { + 0x1A, + L"50 Pin Dual Inline" + }, + { + 0x1B, + L"68 Pin Dual Inline" + }, + { + 0x1C, + L"On Board Sound Input from CD-ROM" + }, + { + 0x1D, + L"Mini-Centronics Type-14" + }, + { + 0x1E, + L"Mini-Centronics Type-26" + }, + { + 0x1F, + L"Mini-jack (headphones)" + }, + { + 0x20, + L"BNC" + }, + { + 0x21, + L"1394" + }, + { + 0x22, + L"SAS/SATA Plug Receptacle" + }, + { + 0x23, + L"USB Type-C Receptacle" + }, + { + 0xA0, + L"PC-98" + }, + { + 0xA1, + L"PC-98Hireso" + }, + { + 0xA2, + L"PC-H98" + }, + { + 0xA3, + L"PC-98Note" + }, + { + 0xA4, + L"PC-98Full" + }, + { + 0xFF, + L"Other" + }, +}; + +TABLE_ITEM PortTypeTable[] = { + { + 0x00, + L"None" + }, + { + 0x01, + L"Parallel Port XT/AT Compatible" + }, + { + 0x02, + L"Parallel Port PS/2" + }, + { + 0x03, + L"Parallel Port ECP" + }, + { + 0x04, + L"Parallel Port EPP" + }, + { + 0x05, + L"Parallel Port ECP/EPP" + }, + { + 0x06, + L"Serial Port XT/AT Compatible" + }, + { + 0x07, + L"Serial Port 16450 Compatible" + }, + { + 0x08, + L"Serial Port 16550 Compatible" + }, + { + 0x09, + L"Serial Port 16550A Compatible" + }, + { + 0x0A, + L"SCSI Port" + }, + { + 0x0B, + L"MIDI Port" + }, + { + 0x0C, + L"Joy Stick Port" + }, + { + 0x0D, + L"Keyboard Port" + }, + { + 0x0E, + L"Mouse Port" + }, + { + 0x0F, + L"SSA SCSI" + }, + { + 0x10, + L"USB" + }, + { + 0x11, + L"FireWire (IEEE P1394)" + }, + { + 0x12, + L"PCMCIA Type II" + }, + { + 0x13, + L"PCMCIA Type II" + }, + { + 0x14, + L"PCMCIA Type III" + }, + { + 0x15, + L"Cardbus" + }, + { + 0x16, + L"Access Bus Port" + }, + { + 0x17, + L"SCSI II" + }, + { + 0x18, + L"SCSI Wide" + }, + { + 0x19, + L"PC-98" + }, + { + 0x1A, + L"PC-98-Hireso" + }, + { + 0x1B, + L"PC-H98" + }, + { + 0x1C, + L"Video Port" + }, + { + 0x1D, + L"Audio Port" + }, + { + 0x1E, + L"Modem Port" + }, + { + 0x1F, + L"Network Port" + }, + { + 0x20, + L"SATA Port" + }, + { + 0x21, + L"SAS Port" + }, + { + 0x22, + L"Multi-Function Display Port (MFDP)" + }, + { + 0x23, + L"Thunderbolt" + }, + { + 0xA0, + L"8251 Compatible" + }, + { + 0xA1, + L"8251 FIFO Compatible" + }, + { + 0xFF, + L"Other " + }, +}; + +TABLE_ITEM SystemSlotTypeTable[] = { + { + 0x01, + L"Other" + }, + { + 0x02, + L"Unknown" + }, + { + 0x03, + L"ISA" + }, + { + 0x04, + L"MCA" + }, + { + 0x05, + L"EISA" + }, + { + 0x06, + L"PCI" + }, + { + 0x07, + L"PC Card (PCMCIA)" + }, + { + 0x08, + L"VL-VESA" + }, + { + 0x09, + L"Proprietary" + }, + { + 0x0A, + L"Processor Card Slot" + }, + { + 0x0B, + L"Proprietary Memory Card Slot" + }, + { + 0x0C, + L"I/O Riser Card Slot" + }, + { + 0x0D, + L"NuBus" + }, + { + 0x0E, + L"PCI - 66MHz Capable" + }, + { + 0x0F, + L"AGP" + }, + { + 0x10, + L"AGP 2X" + }, + { + 0x11, + L"AGP 4X" + }, + { + 0x12, + L"PCI-X" + }, + { + 0x13, + L"AGP 8X" + }, + { + 0x14, + L"M.2 Socket 1-DP (Mechanical Key A)" + }, + { + 0x15, + L"M.2 Socket 1-SD (Mechanical Key E)" + }, + { + 0x16, + L"M.2 Socket 2 (Mechanical Key B)" + }, + { + 0x17, + L"M.2 Socket 3 (Mechanical Key M)" + }, + { + 0x18, + L"MXM Type I" + }, + { + 0x19, + L"MXM Type II" + }, + { + 0x1A, + L"MXM Type III (standard connector)" + }, + { + 0x1B, + L"MXM Type III (HE connector)" + }, + { + 0x1C, + L"MXM Type IV" + }, + { + 0x1D, + L"MXM 3.0 Type A" + }, + { + 0x1E, + L"MXM 3.0 Type B" + }, + { + 0x1F, + L"PCI Express Gen 2 SFF-8639" + }, + { + 0x20, + L"PCI Express Gen 3 SFF-8639" + }, + { + 0x21, + L"PCI Express Mini 52-pin (CEM spec. 2.0) with bottom-side keep-outs" + }, + { + 0x22, + L"PCI Express Mini 52-pin (CEM spec. 2.0) without bottom-side keep-outs" + }, + { + 0x23, + L"PCI Express Mini 76-pin (CEM spec. 2.0) Corresponds to Display-Mini card" + }, + { + 0xA0, + L"PC-98/C20 " + }, + { + 0xA1, + L"PC-98/C24 " + }, + { + 0xA2, + L"PC-98/E " + }, + { + 0xA3, + L"PC-98/Local Bus " + }, + { + 0xA4, + L"PC-98/Card " + }, + { + 0xA5, + L"PCI Express " + }, + { + 0xA6, + L"PCI Express X1" + }, + { + 0xA7, + L"PCI Express X2" + }, + { + 0xA8, + L"PCI Express X4" + }, + { + 0xA9, + L"PCI Express X8" + }, + { + 0xAA, + L"PCI Express X16" + }, + { + 0xAB, + L"PCI Express Gen 2" + }, + { + 0xAC, + L"PCI Express Gen 2 X1" + }, + { + 0xAD, + L"PCI Express Gen 2 X2" + }, + { + 0xAE, + L"PCI Express Gen 2 X4" + }, + { + 0xAF, + L"PCI Express Gen 2 X8" + }, + { + 0xB0, + L"PCI Express Gen 2 X16" + }, + { + 0xB1, + L"PCI Express Gen 3" + }, + { + 0xB2, + L"PCI Express Gen 3 X1" + }, + { + 0xB3, + L"PCI Express Gen 3 X2" + }, + { + 0xB4, + L"PCI Express Gen 3 X4" + }, + { + 0xB5, + L"PCI Express Gen 3 X8" + }, + { + 0xB6, + L"PCI Express Gen 3 X16" + } +}; + +TABLE_ITEM SystemSlotDataBusWidthTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" 8 bit" + }, + { + 0x04, + L" 16 bit" + }, + { + 0x05, + L" 32 bit" + }, + { + 0x06, + L" 64 bit" + }, + { + 0x07, + L" 128 bit" + }, + { + 0x08, + L" 1x or x1" + }, + { + 0x09, + L" 2x or x2" + }, + { + 0x0A, + L" 4x or x4" + }, + { + 0x0B, + L" 8x or x8" + }, + { + 0x0C, + L" 12x or x12" + }, + { + 0x0D, + L" 16x or x16" + }, + { + 0x0E, + L" 32x or x32" + } +}; + +TABLE_ITEM SystemSlotCurrentUsageTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Available" + }, + { + 0x04, + L" In use" + }, + { + 0x05, + L" Unavailable" + } +}; + +TABLE_ITEM SystemSlotLengthTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Short length" + }, + { + 0x04, + L" Long Length" + }, +}; + +TABLE_ITEM SlotCharacteristics1Table[] = { + { + 0, + L" Characteristics Unknown" + }, + { + 1, + L" Provides 5.0 Volts" + }, + { + 2, + L" Provides 3.3 Volts" + }, + { + 3, + L" Slot's opening is shared with another slot, e.g. PCI/EISA shared slot." + }, + + { + 4, + L" PC Card slot supports PC Card-16" + }, + { + 5, + L" PC Card slot supports CardBus" + }, + { + 6, + L" PC Card slot supports Zoom Video " + }, + { + 7, + L" PC Card slot supports Modem Ring Resume " + } +}; + +TABLE_ITEM SlotCharacteristics2Table[] = { + { + 0, + L" PCI slot supports Power Management Enable (PME#) signal" + }, + { + 1, + L" Slot supports hot-plug devices" + }, + { + 2, + L" PCI slot supports SMBus signal" + }, + { + 3, + L" PCIe slot supports bifurcation" + } +}; + +TABLE_ITEM OnboardDeviceTypesTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Video" + }, + { + 0x04, + L" SCSI Controller" + }, + { + 0x05, + L" Ethernet" + }, + { + 0x06, + L" Token Ring" + }, + { + 0x07, + L" Sound" + }, + { + 0x08, + L" Pata Controller" + }, + { + 0x09, + L" Sata Controller" + }, + { + 0x0A, + L" Sas Controller" + }, +}; + +TABLE_ITEM SELTypesTable[] = { + { + 0x00, + L" Reserved." + }, + { + 0x01, + L" Single-bit ECC memory error" + }, + { + 0x02, + L" Multi-bit ECC memory error" + }, + { + 0x03, + L" Parity memory error" + }, + { + 0x04, + L" Bus time-out" + }, + { + 0x05, + L" I/O Channel Check" + }, + { + 0x06, + L" Software NMI" + }, + { + 0x07, + L" POST Memory Resize" + }, + { + 0x08, + L" POST Error" + }, + { + 0x09, + L" PCI Parity Error" + }, + { + 0x0A, + L" PCI System Error" + }, + { + 0x0B, + L" CPU Failure" + }, + { + 0x0C, + L" EISA FailSafe Timer time-out" + }, + { + 0x0D, + L" Correctable memory log disabled" + }, + { + 0x0E, + L" Logging disabled for a specific Event Type" + }, + { + 0x0F, + L" Reserved" + }, + { + 0x10, + L" System Limit Exceeded" + }, + { + 0x11, + L" Asynchronous hardware timer expired and issued a system reset" + }, + { + 0x12, + L" System configuration information" + }, + { + 0x13, + L" Hard-disk information" + }, + { + 0x14, + L" System reconfigured" + }, + { + 0x15, + L" Uncorrectable CPU-complex error" + }, + { + 0x16, + L" Log Area Reset/Cleared" + }, + { + 0x17, + L" System boot" + }, + { + 0x7F18, + L" Unused by SMBIOS specification" + }, + { + 0xFE80, + L" System and OEM specified" + }, + { + 0xFF, + L" End-of-log" + }, +}; + +TABLE_ITEM SELVarDataFormatTypeTable[] = { + { + 0x00, + L" None " + }, + { + 0x01, + L" Handle " + }, + { + 0x02, + L" Multiple-Event " + }, + { + 0x03, + L" Multiple-Event Handle " + }, + { + 0x04, + L" POST Results Bitmap " + }, + // + // Defined below + // + { + 0x05, + L" System Management Type" + }, + // + // Defined below + // + { + 0x06, + L" Multiple-Event System Management Type " + }, + { + 0x7F07, + L" Unused " + }, + { + 0xFF80, + L" OEM assigned " + }, +}; + +TABLE_ITEM PostResultsBitmapDw1Table[] = { + { + 0, + L" Channel 2 Timer error " + }, + { + 1, + L" Master PIC (8259 #1) error " + }, + { + 2, + L" Slave PIC (8259 #2) error " + }, + { + 3, + L" CMOS Battery Failure " + }, + { + 4, + L" CMOS System Options Not Set " + }, + { + 5, + L" CMOS Checksum Error " + }, + { + 6, + L" CMOS Configuration Error " + }, + { + 7, + L" Mouse and Keyboard Swapped " + }, + { + 8, + L" Keyboard Locked " + }, + { + 9, + L" Keyboard Not Functional " + }, + { + 10, + L" Keyboard Controller Not Functional " + }, + { + 11, + L" CMOS Memory Size Different " + }, + { + 12, + L" Memory Decreased in Size " + }, + { + 13, + L" Cache Memory Error " + }, + { + 14, + L" Floppy Drive 0 Error " + }, + { + 15, + L" Floppy Drive 1 Error " + }, + { + 16, + L" Floppy Controller Failure " + }, + { + 17, + L" Number of ATA Drives Reduced Error " + }, + { + 18, + L" CMOS Time Not Set " + }, + { + 19, + L" DDC Monitor Configuration Change " + }, + { + 20, + L" Reserved, set to 0 " + }, + { + 21, + L" Reserved, set to 0 " + }, + { + 22, + L" Reserved, set to 0 " + }, + { + 23, + L" Reserved, set to 0 " + }, + { + 24, + L" Second DWORD has valid data " + }, + { + 25, + L" Reserved, set to 0 " + }, + { + 26, + L" Reserved, set to 0 " + }, + { + 27, + L" Reserved, set to 0 " + }, + { + 28, + L" Normally 0; available for OEM assignment " + }, + { + 29, + L" Normally 0; available for OEM assignment " + }, + { + 30, + L" Normally 0; available for OEM assignment " + }, + { + 31, + L" Normally 0; available for OEM assignment " + }, +}; + +TABLE_ITEM PostResultsBitmapDw2Table[] = { + { + 0, + L" Normally 0; available for OEM assignment " + }, + { + 1, + L" Normally 0; available for OEM assignment " + }, + { + 2, + L" Normally 0; available for OEM assignment " + }, + { + 3, + L" Normally 0; available for OEM assignment " + }, + { + 4, + L" Normally 0; available for OEM assignment " + }, + { + 5, + L" Normally 0; available for OEM assignment " + }, + { + 6, + L" Normally 0; available for OEM assignment " + }, + { + 7, + L" PCI Memory Conflict " + }, + { + 8, + L" PCI I/O Conflict " + }, + { + 9, + L" PCI IRQ Conflict " + }, + { + 10, + L" PNP Memory Conflict " + }, + { + 11, + L" PNP 32 bit Memory Conflict " + }, + { + 12, + L" PNP I/O Conflict " + }, + { + 13, + L" PNP IRQ Conflict " + }, + { + 14, + L" PNP DMA Conflict " + }, + { + 15, + L" Bad PNP Serial ID Checksum " + }, + { + 16, + L" Bad PNP Resource Data Checksum " + }, + { + 17, + L" Static Resource Conflict " + }, + { + 18, + L" NVRAM Checksum Error, NVRAM Cleared " + }, + { + 19, + L" System Board Device Resource Conflict " + }, + { + 20, + L" Primary Output Device Not Found " + }, + { + 21, + L" Primary Input Device Not Found " + }, + { + 22, + L" Primary Boot Device Not Found " + }, + { + 23, + L" NVRAM Cleared By Jumper " + }, + { + 24, + L" NVRAM Data Invalid, NVRAM Cleared " + }, + { + 25, + L" FDC Resource Conflict " + }, + { + 26, + L" Primary ATA Controller Resource Conflict " + }, + { + 27, + L" Secondary ATA Controller Resource Conflict " + }, + { + 28, + L" Parallel Port Resource Conflict " + }, + { + 29, + L" Serial Port 1 Resource Conflict " + }, + { + 30, + L" Serial Port 2 Resource Conflict " + }, + { + 31, + L" Audio Resource Conflict " + }, +}; + +TABLE_ITEM SELSysManagementTypesTable[] = { + { + 0x01, + L" +2.5V Out of range, #2 " + }, + { + 0x02, + L" +3.3V Out of range " + }, + { + 0x03, + L" +5V Out of range " + }, + { + 0x04, + L" -5V Out of range " + }, + { + 0x05, + L" +12V Out of range " + }, + { + 0x06, + L" -12V Out of range " + }, + { + 0x0F07, + L" Reserved for future out-of-range voltage levels " + }, + { + 0x10, + L" System board temperature out of range " + }, + { + 0x11, + L" Processor #1 temperature out of range " + }, + { + 0x12, + L" Processor #2 temperature out of range " + }, + { + 0x13, + L" Processor #3 temperature out of range " + }, + { + 0x14, + L" Processor #4 temperature out of range " + }, + { + 0x1F15, + L" Reserved for future out-of-range temperatures" + }, + { + 0x2720, + L" Fan n (n = 0 to 7) Out of range " + }, + { + 0x2F28, + L" Reserved for future assignment via this specification " + }, + { + 0x30, + L" Chassis secure switch activated " + }, +}; + +TABLE_ITEM PMALocationTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" System board or motherboard" + }, + { + 0x04, + L" ISA add-on card" + }, + { + 0x05, + L" EISA add-on card" + }, + { + 0x06, + L" PCI add-on card" + }, + { + 0x07, + L" MCA add-on card" + }, + { + 0x08, + L" PCMCIA add-on card" + }, + { + 0x09, + L" Proprietary add-on card" + }, + { + 0x0A, + L" NuBus" + }, + { + 0xA0, + L" PC-98/C20 add-on card" + }, + { + 0xA1, + L" PC-98/C24 add-on card" + }, + { + 0xA2, + L" PC-98/E add-on card" + }, + { + 0xA3, + L" PC-98/Local bus add-on card" + } +}; + +TABLE_ITEM PMAUseTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" System memory" + }, + { + 0x04, + L" Video memory" + }, + { + 0x05, + L" Flash memory" + }, + { + 0x06, + L" Non-volatile RAM" + }, + { + 0x07, + L" Cache memory" + } +}; + +TABLE_ITEM PMAErrorCorrectionTypesTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" None" + }, + { + 0x04, + L" Parity" + }, + { + 0x05, + L" Single-bit ECC" + }, + { + 0x06, + L" Multi-bit ECC" + }, + { + 0x07, + L" CRC" + } +}; + +TABLE_ITEM MemoryDeviceFormFactorTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" SIMM" + }, + { + 0x04, + L" SIP" + }, + { + 0x05, + L" Chip" + }, + { + 0x06, + L" DIP" + }, + { + 0x07, + L" ZIP" + }, + { + 0x08, + L" Proprietary Card" + }, + { + 0x09, + L" DIMM" + }, + { + 0x0A, + L" TSOP" + }, + { + 0x0B, + L" Row of chips" + }, + { + 0x0C, + L" RIMM" + }, + { + 0x0D, + L" SODIMM" + }, + { + 0x0E, + L" SRIMM" + }, + { + 0x0F, + L" FB-DIMM" + } +}; + +TABLE_ITEM MemoryDeviceTypeTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" DRAM" + }, + { + 0x04, + L" EDRAM" + }, + { + 0x05, + L" VRAM" + }, + { + 0x06, + L" SRAM" + }, + { + 0x07, + L" RAM" + }, + { + 0x08, + L" ROM" + }, + { + 0x09, + L" FLASH" + }, + { + 0x0A, + L" EEPROM" + }, + { + 0x0B, + L" FEPROM" + }, + { + 0x0C, + L" EPROM" + }, + { + 0x0D, + L" CDRAM" + }, + { + 0x0E, + L" 3DRAM" + }, + { + 0x0F, + L" SDRAM" + }, + { + 0x10, + L" SGRAM" + }, + { + 0x11, + L" RDRAM" + }, + { + 0x12, + L" DDR" + }, + { + 0x13, + L" DDR2" + }, + { + 0x14, + L" DDR2 FB-DIMM" + }, + { + 0x18, + L" DDR3" + }, + { + 0x19, + L" FBD2" + }, + { + 0x1A, + L" DDR4" + }, + { + 0x1B, + L" LPDDR" + }, + { + 0x1C, + L" LPDDR2" + }, + { + 0x1D, + L" LPDDR3" + }, + { + 0x1E, + L" LPDDR4" + }, + { + 0x1F, + L" Logical non-volatile device" + } +}; + +TABLE_ITEM MemoryDeviceTypeDetailTable[] = { + { + 1, + L" Other" + }, + { + 2, + L" Unknown" + }, + { + 3, + L" Fast-paged" + }, + { + 4, + L" Static column" + }, + { + 5, + L" Pseudo-STATIC" + }, + { + 6, + L" RAMBUS " + }, + { + 7, + L" Synchronous" + }, + { + 8, + L" CMOS" + }, + { + 9, + L" EDO" + }, + { + 10, + L" Window DRAM" + }, + { + 11, + L" Cache DRAM" + }, + { + 12, + L" Non-volatile" + }, + { + 13, + L" Registered(Buffered)" + }, + { + 14, + L" Unbuffered(Unregistered)" + } +}; + +TABLE_ITEM MemoryDeviceMemoryTechnologyTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" DRAM" + }, + { + 0x04, + L" NVDIMM-N" + }, + { + 0x05, + L" NVDIMM-F" + }, + { + 0x06, + L" NVDIMM-P" + }, + { + 0x07, + L" Intel persistent memory" + } +}; + +TABLE_ITEM MemoryDeviceMemoryOperatingModeCapabilityTable[] = { + { + 1, + L" Other" + }, + { + 2, + L" Unknown" + }, + { + 3, + L" Volatile memory" + }, + { + 4, + L" Byte-accessible persistent memory" + }, + { + 5, + L" Block-accessible persistent memory" + } +}; + + +TABLE_ITEM MemoryErrorTypeTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" OK" + }, + { + 0x04, + L" Bad read" + }, + { + 0x05, + L" Parity error" + }, + { + 0x06, + L" Single-bit error" + }, + { + 0x07, + L" Double-bit error" + }, + { + 0x08, + L" Multi-bit error" + }, + { + 0x09, + L" Nibble error" + }, + { + 0x0A, + L" Checksum error" + }, + { + 0x0B, + L" CRC error" + }, + { + 0x0C, + L" Corrected single-bit error" + }, + { + 0x0D, + L" Corrected error" + }, + { + 0x0E, + L" Uncorrectable error" + }, +}; + +TABLE_ITEM MemoryErrorGranularityTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Device level" + }, + { + 0x04, + L" Memory partition level" + }, +}; + +TABLE_ITEM MemoryErrorOperationTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Read" + }, + { + 0x04, + L" Write" + }, + { + 0x05, + L" Partial Write" + }, +}; + +TABLE_ITEM PointingDeviceTypeTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Mouse" + }, + { + 0x04, + L" Track Ball" + }, + { + 0x05, + L" Track Point" + }, + { + 0x06, + L" Glide Point" + }, + { + 0x07, + L" Touch Pad" + }, +}; + +TABLE_ITEM PointingDeviceInterfaceTable[] = { + { + 0x01, + L" Other" + }, + { + 0x02, + L" Unknown" + }, + { + 0x03, + L" Serial" + }, + { + 0x04, + L" PS/2" + }, + { + 0x05, + L" Infrared" + }, + { + 0x06, + L" HP-HIL" + }, + { + 0x07, + L" Bus mouse" + }, + { + 0x08, + L" ADB(Apple Desktop Bus" + }, + { + 0xA0, + L" Bus mouse DB-9" + }, + { + 0xA1, + L" Bus mouse mirco-DIN" + }, + { + 0xA2, + L" USB" + }, +}; + +TABLE_ITEM PBDeviceChemistryTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" Lead Acid " + }, + { + 0x04, + L" Nickel Cadmium " + }, + { + 0x05, + L" Nickel metal hydride " + }, + { + 0x06, + L" Lithium-ion " + }, + { + 0x07, + L" Zinc air " + }, + { + 0x08, + L" Lithium Polymer " + }, +}; + +TABLE_ITEM VPLocationTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" OK " + }, + { + 0x04, + L" Non-critical " + }, + { + 0x05, + L" Critical " + }, + { + 0x06, + L" Non-recoverable " + }, +}; + +TABLE_ITEM VPStatusTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" Processor " + }, + { + 0x04, + L" Disk " + }, + { + 0x05, + L" Peripheral Bay " + }, + { + 0x06, + L" System Management Module " + }, + { + 0x07, + L" Motherboard " + }, + { + 0x08, + L" Memory Module " + }, + { + 0x09, + L" Processor Module " + }, + { + 0x0A, + L" Power Unit " + }, + { + 0x0B, + L" Add-in Card " + }, +}; + +TABLE_ITEM CoolingDeviceStatusTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" OK " + }, + { + 0x04, + L" Non-critical " + }, + { + 0x05, + L" Critical " + }, + { + 0x06, + L" Non-recoverable " + }, +}; + +TABLE_ITEM CoolingDeviceTypeTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" Fan " + }, + { + 0x04, + L" Centrifugal Blower " + }, + { + 0x05, + L" Chip Fan " + }, + { + 0x06, + L" Cabinet Fan " + }, + { + 0x07, + L" Power Supply Fan " + }, + { + 0x08, + L" Heat Pipe " + }, + { + 0x09, + L" Integrated Refrigeration " + }, + { + 0x10, + L" Active Cooling " + }, + { + 0x11, + L" Passive Cooling " + }, +}; + +TABLE_ITEM TemperatureProbeStatusTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" OK " + }, + { + 0x04, + L" Non-critical " + }, + { + 0x05, + L" Critical " + }, + { + 0x06, + L" Non-recoverable " + }, +}; + +TABLE_ITEM TemperatureProbeLocTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" Processor " + }, + { + 0x04, + L" Disk " + }, + { + 0x05, + L" Peripheral Bay " + }, + { + 0x06, + L" System Management Module " + }, + { + 0x07, + L" Motherboard " + }, + { + 0x08, + L" Memory Module " + }, + { + 0x09, + L" Processor Module " + }, + { + 0x0A, + L" Power Unit " + }, + { + 0x0B, + L" Add-in Card " + }, +}; + +TABLE_ITEM ECPStatusTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" OK " + }, + { + 0x04, + L" Non-critical " + }, + { + 0x05, + L" Critical " + }, + { + 0x06, + L" Non-recoverable " + }, +}; + +TABLE_ITEM ECPLocTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" Processor " + }, + { + 0x04, + L" Disk " + }, + { + 0x05, + L" Peripheral Bay " + }, + { + 0x06, + L" System Management Module " + }, + { + 0x07, + L" Motherboard " + }, + { + 0x08, + L" Memory Module " + }, + { + 0x09, + L" Processor Module " + }, + { + 0x0A, + L" Power Unit " + }, + { + 0x0B, + L" Add-in Card " + }, +}; + +TABLE_ITEM MDTypeTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" National Semiconductor LM75 " + }, + { + 0x04, + L" National Semiconductor LM78 " + }, + { + 0x05, + L" National Semiconductor LM79 " + }, + { + 0x06, + L" National Semiconductor LM80 " + }, + { + 0x07, + L" National Semiconductor LM81 " + }, + { + 0x08, + L" Analog Devices ADM9240 " + }, + { + 0x09, + L" Dallas Semiconductor DS1780 " + }, + { + 0x0A, + L" Maxim 1617 " + }, + { + 0x0B, + L" Genesys GL518SM " + }, + { + 0x0C, + L" Winbond W83781D " + }, + { + 0x0D, + L" Holtek HT82H791 " + }, +}; + +TABLE_ITEM MDAddressTypeTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" I/O Port " + }, + { + 0x04, + L" Memory " + }, + { + 0x05, + L" SM Bus " + }, +}; + +TABLE_ITEM MemoryChannelTypeTable[] = { + { + 0x01, + L" Other " + }, + { + 0x02, + L" Unknown " + }, + { + 0x03, + L" RamBus " + }, + { + 0x04, + L" SyncLink " + }, +}; + +TABLE_ITEM IPMIDIBMCInterfaceTypeTable[] = { + { + 0x00, + L" Unknown " + }, + { + 0x01, + L" KCS: Keyboard Controller Style " + }, + { + 0x02, + L" SMIC: Server Management Interface Chip " + }, + { + 0x03, + L" BT: Block Transfer " + }, + { + 0x04, + L" SSIF: SMBus System Interface " + }, + { + 0xFF05, + L" Reserved for future assignment by this specification " + }, +}; + +TABLE_ITEM MCHostInterfaceTypeTable[] = { + { + 0x3F00, + L" MCTP Host Interface " + }, + { + 0x40, + L" Network Host Interface " + }, + { + 0xF0, + L" OEM defined " + }, +}; + + +TABLE_ITEM StructureTypeInfoTable[] = { + { + 0, + L" BIOS Information" + }, + { + 1, + L" System Information" + }, + { + 2, + L" Base Board Information" + }, + { + 3, + L" System Enclosure" + }, + { + 4, + L" Processor Information" + }, + { + 5, + L" Memory Controller Information " + }, + { + 6, + L" Memory Module Information " + }, + { + 7, + L" Cache Information " + }, + { + 8, + L" Port Connector Information " + }, + { + 9, + L" System Slots " + }, + { + 10, + L" On Board Devices Information " + }, + { + 11, + L" OEM Strings" + }, + { + 12, + L" System Configuration Options " + }, + { + 13, + L" BIOS Language Information " + }, + { + 14, + L" Group Associations " + }, + { + 15, + L" System Event Log " + }, + { + 16, + L" Physical Memory Array " + }, + { + 17, + L" Memory Device " + }, + { + 18, + L" 32-bit Memory Error Information " + }, + { + 19, + L" Memory Array Mapped Address " + }, + { + 20, + L" Memory Device Mapped Address " + }, + { + 21, + L" Built-in Pointing Device " + }, + { + 22, + L" Portable Battery " + }, + { + 23, + L" System Reset " + }, + { + 24, + L" Hardware Security " + }, + { + 25, + L" System Power Controls " + }, + { + 26, + L" Voltage Probe " + }, + { + 27, + L" Cooling Device " + }, + { + 28, + L" Temperature Probe " + }, + { + 29, + L" Electrical Current Probe " + }, + { + 30, + L" Out-of-Band Remote Access " + }, + { + 31, + L" Boot Integrity Services (BIS) Entry Point" + }, + { + 32, + L" System Boot Information " + }, + { + 33, + L" 64-bit Memory Error Information " + }, + { + 34, + L" Management Device " + }, + { + 35, + L" Management Device Component " + }, + { + 36, + L" Management Device Threshold Data " + }, + { + 37, + L" Memory Channel " + }, + { + 38, + L" IPMI Device Information " + }, + { + 39, + L" System Power Supply" + }, + { + 40, + L" Additional Information" + }, + { + 41, + L" Onboard Devices Extended Information" + }, + { + 42, + L" Management Controller Host Interface" + }, + { + 43, + L" TPM Device" + }, + { + 0x7E, + L" Inactive" + }, + { + 0x7F, + L" End-of-Table " + }, +}; + + +/** + Given a table and a Key, return the responding info. + + Notes: + Table[Index].Key is change from UINT8 to UINT16, + in order to deal with "0xaa - 0xbb". + + For example: + DisplaySELVariableDataFormatTypes(UINT8 Type, UINT8 Option) + has a item: + "0x07-0x7F, Unused" + Now define Key = 0x7F07, that is to say: High = 0x7F, Low = 0x07. + Then all the Key Value between Low and High gets the same string + L"Unused". + + @param[in] Table The begin address of table. + @param[in] Number The number of table items. + @param[in] Key The query Key. + @param[in, out] Info Input as empty buffer; output as data buffer. + @param[in] InfoLen The max number of characters for Info. + + @return the found Key and Info is valid. + @retval QUERY_TABLE_UNFOUND and Info should be NULL. +**/ +UINT8 +QueryTable ( + IN TABLE_ITEM *Table, + IN UINTN Number, + IN UINT8 Key, + IN OUT CHAR16 *Info, + IN UINTN InfoLen + ) +{ + UINTN Index; + // + // High byte and Low byte of word + // + UINT8 High; + UINT8 Low; + + for (Index = 0; Index < Number; Index++) { + High = (UINT8) (Table[Index].Key >> 8); + Low = (UINT8) (Table[Index].Key & 0x00FF); + + // + // Check if Key is in the range + // or if Key == Value in the table + // + if ((High > Low && Key >= Low && Key <= High) + || (Table[Index].Key == Key)) { + StrnCpyS (Info, InfoLen, Table[Index].Info, InfoLen - 1); + StrnCatS (Info, InfoLen, L"\n", InfoLen - 1 - StrLen(Info)); + return Key; + } + } + + StrCpyS (Info, InfoLen, L"Undefined Value\n"); + return QUERY_TABLE_UNFOUND; +} + +/** + Given a table of bit info and a Key, return the responding info to the Key. + + @param[in] Table Point to a table which maintains a map of 'bit' to 'message'. + @param[in] Number Number of table items. + @param[in] Bits The Key of query the bit map information. +**/ +VOID +PrintBitsInfo ( + IN TABLE_ITEM *Table, + IN UINTN Number, + IN UINT32 Bits + ) +{ + // + // Get certain bit of 'Value': + // +#define BIT(Value, bit) ((Value) & ((UINT32) 1) << (bit)) + // + // Clear certain bit of 'Value': + // +#define CLR_BIT(Value, bit) ((Value) -= (BIT (Value, bit))) + + UINTN Index; + UINT32 Value; + BOOLEAN FirstInfo; + + FirstInfo = TRUE; + Value = Bits; + // + // query the table and print information + // + for (Index = 0; Index < Number; Index++) { + if (BIT (Value, Table[Index].Key) != 0) { + if (!FirstInfo) { + // + // If it is not first info, print the separator first. + // + Print (L" | "); + } + Print (Table[Index].Info); + + FirstInfo = FALSE; + // + // clear the bit, for reserved bits test + // + CLR_BIT (Value, Table[Index].Key); + } + } + + // + // There is no any info if FirstInfo is still TRUE. + // + if (FirstInfo) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_NO_INFO), gShellDebug1HiiHandle); + } + + if (Value != 0) { + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_RSVD_BITS_SET), + gShellDebug1HiiHandle, + Value + ); + } + + Print (L"\n"); +} +// +// ////////////////////////////////////////////////////////////////// +// +// Following uses QueryTable functions to simplify the coding. +// QueryTable(), PrintBitsInfo() +// +// +#define PRINT_TABLE_ITEM(Table, Key) \ + do { \ + UINTN Num; \ + CHAR16 Info[66]; \ + Num = sizeof (Table) / sizeof (TABLE_ITEM); \ + ZeroMem (Info, sizeof (Info)); \ + QueryTable (Table, Num, Key, Info, sizeof(Info)/sizeof(Info[0])); \ + Print (Info); \ + } while (0); + +#define PRINT_BITS_INFO(Table, bits) \ + do { \ + UINTN Num; \ + Num = sizeof (Table) / sizeof (TABLE_ITEM); \ + PrintBitsInfo (Table, Num, (UINT32) bits); \ + } while (0); + +/** + Display System Information (Type 1) Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemWakeupType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_WAKEUP_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (SystemWakeupTypeTable, Type); +} + +/** + Display Base Board (Type 2) Feature Flags. + + @param[in] FeatureFlags The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayBaseBoardFeatureFlags ( + IN UINT8 FeatureFlags, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_FEATURE_FLAGS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (FeatureFlags, Option); + PRINT_BITS_INFO (BaseBoardFeatureFlagsTable, FeatureFlags); +} + +/** + Display Base Board (Type 2) Board Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayBaseBoardBoardType( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_BOARD_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (BaseBoardBoardTypeTable, Type); +} + +/** + Display System Enclosure (Type 3) Enclosure Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemEnclosureType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + // + // query table and print info + // + PRINT_TABLE_ITEM (SystemEnclosureTypeTable, Type); + + if (BIT (Type, 7) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CHASSIS_LOCK_PRESENT), gShellDebug1HiiHandle); + } +} + +/** + Display System Enclosure (Type 3) Enclosure Status. + + @param[in] Status The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemEnclosureStatus ( + IN UINT8 Status, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_TABLE_ITEM (SystemEnclosureStatusTable, Status); +} + +/** + Display System Enclosure (Type 3) Security Status. + + @param[in] Status The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySESecurityStatus ( + IN UINT8 Status, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_SECURITY), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_TABLE_ITEM (SESecurityStatusTable, Status); +} + +/** + Display Processor Information (Type 4) Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayProcessorType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PROC_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (ProcessorTypeTable, Type); +} + +/** + Display Processor Information (Type 4) Upgrade. + + @param[in] Upgrade The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayProcessorUpgrade ( + IN UINT8 Upgrade, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PROC_UPDATE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Upgrade, Option); + PRINT_TABLE_ITEM (ProcessorUpgradeTable, Upgrade); +} + +/** + Display Processor Information (Type 4) Characteristics. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayProcessorCharacteristics ( + IN UINT16 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PROC_CHARACTERISTICS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_BITS_INFO (ProcessorCharacteristicsTable, Type); +} + +/** + Display Memory Controller Information (Type 5) method. + + @param[in] Method The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcErrorDetectMethod ( + IN UINT8 Method, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DETECTMETHOD), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Method, Option); + PRINT_TABLE_ITEM (McErrorDetectMethodTable, Method); +} + +/** + Display Memory Controller Information (Type 5) Capability. + + @param[in] Capability The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcErrorCorrectCapability ( + IN UINT8 Capability, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_CORRECT_CAPABILITY), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Capability, Option); + PRINT_BITS_INFO (McErrorCorrectCapabilityTable, Capability); +} + +/** + Display Memory Controller Information (Type 5) Support. + + @param[in] Support The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcInterleaveSupport ( + IN UINT8 Support, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_INTERLEAVE_SUPPORT), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Support, Option); + PRINT_TABLE_ITEM (McInterleaveSupportTable, Support); +} + +/** + Display Memory Controller Information (Type 5) speeds. + + @param[in] Speed The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcMemorySpeeds ( + IN UINT16 Speed, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_MEMORY_SPEED), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Speed, Option); + PRINT_BITS_INFO (McMemorySpeedsTable, Speed); +} + +/** + Display Memory Controller Information (Type 5) voltage. + + @param[in] Voltage The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryModuleVoltage ( + IN UINT8 Voltage, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_REQUIRED_VOLTAGES), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Voltage, Option); + PRINT_BITS_INFO (MemoryModuleVoltageTable, Voltage); +} + +/** + Display Memory Module Information (Type 6) type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMmMemoryType ( + IN UINT16 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_BITS_INFO (MmMemoryTypeTable, Type); +} + +/** + Display Memory Module Information (Type 6) status. + + @param[in] Status The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMmErrorStatus ( + IN UINT8 Status, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_ERROR_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_BITS_INFO (MmErrorStatusTable, Status); +} + +/** + Display Cache Information (Type 7) SRAM Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheSRAMType ( + IN UINT16 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_SRAM_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION ((UINT8) Type, Option); + PRINT_BITS_INFO (CacheSRAMTypeTable, (UINT8) Type); +} + +/** + Display Cache Information (Type 7) correcting Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheErrCorrectingType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_ERROR_CORRECTING), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (CacheErrCorrectingTypeTable, Type); +} + +/** + Display Cache Information (Type 7) Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheSystemCacheType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_SYSTEM_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (CacheSystemCacheTypeTable, Type); +} + +/** + Display Cache Information (Type 7) Associativity. + + @param[in] Associativity The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheAssociativity ( + IN UINT8 Associativity, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_ASSOCIATIVITY), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Associativity, Option); + PRINT_TABLE_ITEM (CacheAssociativityTable, Associativity); +} + +/** + Display Port Connector Information (Type 8) type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPortConnectorType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PORT_CONNECTOR_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (PortConnectorTypeTable, Type); +} + +/** + Display Port Connector Information (Type 8) port type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPortType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PORT_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (PortTypeTable, Type); +} + +/** + Display System Slots (Type 9) slot type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (SystemSlotTypeTable, Type); +} + +/** + Display System Slots (Type 9) data bus width. + + @param[in] Width The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotDataBusWidth ( + IN UINT8 Width, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_DATA), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Width, Option); + PRINT_TABLE_ITEM (SystemSlotDataBusWidthTable, Width); +} + +/** + Display System Slots (Type 9) usage information. + + @param[in] Usage The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotCurrentUsage ( + IN UINT8 Usage, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_CURRENT_USAGE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Usage, Option); + PRINT_TABLE_ITEM (SystemSlotCurrentUsageTable, Usage); +} + +/** + Display System Slots (Type 9) slot length. + + @param[in] Length The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotLength ( + IN UINT8 Length, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_LENGTH), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Length, Option); + PRINT_TABLE_ITEM (SystemSlotLengthTable, Length); +} + +/** + Display System Slots (Type 9) characteristics. + + @param[in] Chara1 The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySlotCharacteristics1 ( + IN UINT8 Chara1, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Chara1, Option); + PRINT_BITS_INFO (SlotCharacteristics1Table, Chara1); +} + +/** + Display System Slots (Type 9) characteristics. + + @param[in] Chara2 The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySlotCharacteristics2 ( + IN UINT8 Chara2, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS_2), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Chara2, Option); + PRINT_BITS_INFO (SlotCharacteristics2Table, Chara2); +} + +/** + Display On Board Devices Information (Type 10) types. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayOnboardDeviceTypes ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_ONBOARD_DEVICE_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (OnboardDeviceTypesTable, Type); +} + +/** + Display System Event Log (Type 15) types. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySELTypes ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_EVENT_LOG_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (SELTypesTable, Type); +} + +/** + Display System Event Log (Type 15) format type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySELVarDataFormatType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_EVENT_LOG_VAR_DATA_FORMAT), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (SELVarDataFormatTypeTable, Type); +} + +/** + Display System Event Log (Type 15) dw1. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPostResultsBitmapDw1 ( + IN UINT32 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_BITMAP), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_BITS_INFO (PostResultsBitmapDw1Table, Key); +} + +/** + Display System Event Log (Type 15) dw2. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPostResultsBitmapDw2 ( + IN UINT32 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_SECOND_DWORD), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_BITS_INFO (PostResultsBitmapDw2Table, Key); +} + +/** + Display System Event Log (Type 15) type. + + @param[in] SMType The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySELSysManagementTypes ( + IN UINT32 SMType, + IN UINT8 Option + ) +{ + UINT8 Temp; + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_TYPES), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (SMType, Option); + + // + // Deal with wide range Value + // + if (SMType >= 0x80000000) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_OEM_ASSIGNED), gShellDebug1HiiHandle); + } else if (SMType >= 0x00020000) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_RSVD_FOR_FUTURE_ASSIGN), gShellDebug1HiiHandle); + } else if (SMType >= 0x00010000) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_PROBE), gShellDebug1HiiHandle); + } else if (SMType >= 0x31) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_RSVD_FOR_FUTURE_ASSIGN), gShellDebug1HiiHandle); + } else { + // + // Deal with One byte data + // + Temp = (UINT8) (SMType & 0x3F); + PRINT_TABLE_ITEM (SELSysManagementTypesTable, Temp); + } +} + +/** + Display Physical Memory Array (Type 16) Location. + + @param[in] Location The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPMALocation ( + IN UINT8 Location, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_LOCATION), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Location, Option); + PRINT_TABLE_ITEM (PMALocationTable, Location); +} + +/** + Display Physical Memory Array (Type 16) Use. + + @param[in] Use The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPMAUse ( + IN UINT8 Use, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_USE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Use, Option); + PRINT_TABLE_ITEM (PMAUseTable, Use); +} + +/** + Display Physical Memory Array (Type 16) Types. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPMAErrorCorrectionTypes ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_ERROR), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (PMAErrorCorrectionTypesTable, Type); +} + +/** + Display Memory Device (Type 17) form factor. + + @param[in] FormFactor The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceFormFactor ( + IN UINT8 FormFactor, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_FORM_FACTOR), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (FormFactor, Option); + PRINT_TABLE_ITEM (MemoryDeviceFormFactorTable, FormFactor); +} + +/** + Display Memory Device (Type 17) type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (MemoryDeviceTypeTable, Type); +} + +/** + Display Memory Device (Type 17) details. + + @param[in] Para The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceTypeDetail ( + IN UINT16 Para, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE_DETAIL), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Para, Option); + PRINT_BITS_INFO (MemoryDeviceTypeDetailTable, Para); +} + +/** + Display Memory Device (Type 17) memory technology. + + @param[in] Para The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceMemoryTechnology ( + IN UINT8 Para, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_MEMORY_TECHNOLOGY), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Para, Option); + PRINT_TABLE_ITEM (MemoryDeviceMemoryTechnologyTable, Para); +} + +/** + Display Memory Device (Type 17) memory operating mode capability. + + @param[in] Para The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceMemoryOperatingModeCapability ( + IN UINT16 Para, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_MEM_OPER_MODE_CAPA), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Para, Option); + PRINT_BITS_INFO (MemoryDeviceMemoryOperatingModeCapabilityTable, Para); +} + +/** + Display 32-bit Memory Error Information (Type 18) type. + + @param[in] ErrorType The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryErrorType ( + IN UINT8 ErrorType, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_INFO), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (ErrorType, Option); + PRINT_TABLE_ITEM (MemoryErrorTypeTable, ErrorType); +} + +/** + Display 32-bit Memory Error Information (Type 18) error granularity. + + @param[in] Granularity The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryErrorGranularity ( + IN UINT8 Granularity, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_GRANULARITY), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Granularity, Option); + PRINT_TABLE_ITEM (MemoryErrorGranularityTable, Granularity); +} + +/** + Display 32-bit Memory Error Information (Type 18) error information. + + @param[in] Operation The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryErrorOperation ( + IN UINT8 Operation, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_OP), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Operation, Option); + PRINT_TABLE_ITEM (MemoryErrorOperationTable, Operation); +} + +/** + Display Built-in Pointing Device (Type 21) type information. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPointingDeviceType ( + IN UINT8 Type, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (PointingDeviceTypeTable, Type); +} + +/** + Display Built-in Pointing Device (Type 21) information. + + @param[in] Interface The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPointingDeviceInterface ( + IN UINT8 Interface, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_INTERFACE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Interface, Option); + PRINT_TABLE_ITEM (PointingDeviceInterfaceTable, Interface); +} + +/** + Display Portable Battery (Type 22) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPBDeviceChemistry ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PORTABLE_BATT_DEV_CHEM), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (PBDeviceChemistryTable, Key); +} + +/** + Display Voltage Probe (Type 26) location information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayVPLocation ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Loc; + + Loc = (UINT8) ((Key & 0xE0) >> 5); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_LOC), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Loc, Option); + PRINT_TABLE_ITEM (VPLocationTable, Loc); +} + +/** + Display Voltage Probe (Type 26) status ype information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayVPStatus ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Status; + + Status = (UINT8) (Key & 0x1F); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_TABLE_ITEM (VPStatusTable, Status); +} + +/** + Display Cooling (Type 27) status information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCoolingDeviceStatus ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Status; + + Status = (UINT8) ((Key & 0xE0) >> 5); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_TABLE_ITEM (CoolingDeviceStatusTable, Status); +} + +/** + Display Cooling (Type 27) type information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCoolingDeviceType ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Type; + + Type = (UINT8) (Key & 0x1F); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Type, Option); + PRINT_TABLE_ITEM (CoolingDeviceTypeTable, Type); +} + +/** + Display Temperature Probe (Type 28) status information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayTemperatureProbeStatus ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Status; + + Status = (UINT8) ((Key & 0xE0) >> 5); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_TEMP_PROBE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_TABLE_ITEM (TemperatureProbeStatusTable, Status); +} + +/** + Display Temperature Probe (Type 28) location information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayTemperatureProbeLoc ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Loc; + + Loc = (UINT8) (Key & 0x1F); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_LOC), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Loc, Option); + PRINT_TABLE_ITEM (TemperatureProbeLocTable, Loc); +} + +/** + Display Electrical Current Probe (Type 29) status information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayECPStatus ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Status; + + Status = (UINT8) ((Key & 0xE0) >> 5); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_STATUS), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Status, Option); + PRINT_TABLE_ITEM (ECPStatusTable, Status); +} + +/** + Display Type 29 information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayECPLoc ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + UINT8 Loc; + + Loc = (UINT8) (Key & 0x1F); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_LOC), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Loc, Option); + PRINT_TABLE_ITEM (ECPLocTable, Loc); +} + +/** + Display Management Device (Type 34) Type. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMDType ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (MDTypeTable, Key); +} + +/** + Display Management Device (Type 34) Address Type. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMDAddressType ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_ADDR_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (MDAddressTypeTable, Key); +} + +/** + Display Memory Channel (Type 37) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryChannelType ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_CHANNEL_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (MemoryChannelTypeTable, Key); +} + +/** + Display IPMI Device Information (Type 38) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayIPMIDIBMCInterfaceType ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_BMC_INTERFACE_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (IPMIDIBMCInterfaceTypeTable, Key); +} + +/** + Display Management Controller Host Interface (Type 42) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMCHostInterfaceType ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MC_HOST_INTERFACE_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (MCHostInterfaceTypeTable, Key); +} + +/** + Display the structure type information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayStructureTypeInfo ( + IN UINT8 Key, + IN UINT8 Option + ) +{ + // + // display + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_STRUCT_TYPE), gShellDebug1HiiHandle); + PRINT_INFO_OPTION (Key, Option); + PRINT_TABLE_ITEM (StructureTypeInfoTable, Key); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h new file mode 100644 index 0000000..e67872c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h @@ -0,0 +1,818 @@ +/** @file + Build a table, each item is (key, info) pair. + and give a interface of query a string out of a table. + + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMBIOS_QUERY_TABLE_H_ +#define _SMBIOS_QUERY_TABLE_H_ + +#define QUERY_TABLE_UNFOUND 0xFF + +typedef struct TABLE_ITEM { + UINT16 Key; + CHAR16 *Info; +} TABLE_ITEM; + +// +// Print info by option +// +#define PRINT_INFO_OPTION(Value, Option) \ + do { \ + if (Option == SHOW_NONE) { \ + return ; \ + } \ + if (Option < SHOW_DETAIL) { \ + Print (L"0x%x\n", Value); \ + return ; \ + } \ + } while (0); + +/** + Given a table and a Key, return the responding info. + + Notes: + Table[Index].Key is change from UINT8 to UINT16, + in order to deal with "0xaa - 0xbb". + + For example: + DisplaySELVariableDataFormatTypes(UINT8 Type, UINT8 Option) + has a item: + "0x07-0x7F, Unused" + Now define Key = 0x7F07, that is to say: High = 0x7F, Low = 0x07. + Then all the Key Value between Low and High gets the same string + L"Unused". + + @param[in] Table The begin address of table. + @param[in] Number The number of table items. + @param[in] Key The query Key. + @param[in, out] Info Input as empty buffer; output as data buffer. + @param[in] InfoLen The max number of characters for Info. + + @return the found Key and Info is valid. + @retval QUERY_TABLE_UNFOUND and Info should be NULL. +**/ +UINT8 +QueryTable ( + IN TABLE_ITEM *Table, + IN UINTN Number, + IN UINT8 Key, + IN OUT CHAR16 *Info, + IN UINTN InfoLen + ); + +/** + Display the structure type information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayStructureTypeInfo ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display System Information (Type 1) Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemWakeupType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Base Board (Type 2) Feature Flags. + + @param[in] FeatureFlags The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayBaseBoardFeatureFlags ( + IN UINT8 FeatureFlags, + IN UINT8 Option + ); + +/** + Display Base Board (Type 2) Board Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayBaseBoardBoardType( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Enclosure (Type 3) Enclosure Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemEnclosureType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Enclosure (Type 3) Enclosure Status. + + @param[in] Status The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemEnclosureStatus ( + IN UINT8 Status, + IN UINT8 Option + ); + +/** + Display System Enclosure (Type 3) Security Status. + + @param[in] Status The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySESecurityStatus ( + IN UINT8 Status, + IN UINT8 Option + ) +; + +/** + Display Processor Information (Type 4) Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayProcessorType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Processor Information (Type 4) Upgrade. + + @param[in] Upgrade The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayProcessorUpgrade ( + IN UINT8 Upgrade, + IN UINT8 Option + ); + +/** + Display Processor Information (Type 4) Characteristics. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayProcessorCharacteristics ( + IN UINT16 Type, + IN UINT8 Option + ); + +/** + Display Memory Controller Information (Type 5) method. + + @param[in] Method The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcErrorDetectMethod ( + IN UINT8 Method, + IN UINT8 Option + ); + +/** + Display Memory Controller Information (Type 5) Capability. + + @param[in] Capability The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcErrorCorrectCapability ( + IN UINT8 Capability, + IN UINT8 Option + ); + +/** + Display Memory Controller Information (Type 5) Support. + + @param[in] Support The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcInterleaveSupport ( + IN UINT8 Support, + IN UINT8 Option + ); + +/** + Display Memory Controller Information (Type 5) speeds. + + @param[in] Speed The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMcMemorySpeeds ( + IN UINT16 Speed, + IN UINT8 Option + ); + +/** + Display Memory Controller Information (Type 5) voltage. + + @param[in] Voltage The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryModuleVoltage ( + IN UINT8 Voltage, + IN UINT8 Option + ); + +/** + Display Memory Module Information (Type 6) type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMmMemoryType ( + IN UINT16 Type, + IN UINT8 Option + ); + +/** + Display Memory Module Information (Type 6) status. + + @param[in] Status The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMmErrorStatus ( + IN UINT8 Status, + IN UINT8 Option + ); + +/** + Display Cache Information (Type 7) SRAM Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheSRAMType ( + IN UINT16 Type, + IN UINT8 Option + ); + +/** + Display Cache Information (Type 7) correcting Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheErrCorrectingType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Cache Information (Type 7) Type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheSystemCacheType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Cache Information (Type 7) Associativity. + + @param[in] Associativity The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCacheAssociativity ( + IN UINT8 Associativity, + IN UINT8 Option + ); + +/** + Display Port Connector Information (Type 8) type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPortConnectorType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Port Connector Information (Type 8) port type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPortType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Slots (Type 9) slot type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Slots (Type 9) data bus width. + + @param[in] Width The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotDataBusWidth ( + IN UINT8 Width, + IN UINT8 Option + ); + +/** + Display System Slots (Type 9) usage information. + + @param[in] Usage The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotCurrentUsage ( + IN UINT8 Usage, + IN UINT8 Option + ); + +/** + Display System Slots (Type 9) slot length. + + @param[in] Length The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySystemSlotLength ( + IN UINT8 Length, + IN UINT8 Option + ); + +/** + Display System Slots (Type 9) characteristics. + + @param[in] Chara1 The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySlotCharacteristics1 ( + IN UINT8 Chara1, + IN UINT8 Option + ); + +/** + Display System Slots (Type 9) characteristics. + + @param[in] Chara2 The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySlotCharacteristics2 ( + IN UINT8 Chara2, + IN UINT8 Option + ); + +/** + Display On Board Devices Information (Type 10) types. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayOnboardDeviceTypes ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Event Log (Type 15) types. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySELTypes ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Event Log (Type 15) format type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySELVarDataFormatType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display System Event Log (Type 15) dw1. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPostResultsBitmapDw1 ( + IN UINT32 Key, + IN UINT8 Option + ); + +/** + Display System Event Log (Type 15) dw2. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPostResultsBitmapDw2 ( + IN UINT32 Key, + IN UINT8 Option + ); + +/** + Display System Event Log (Type 15) type. + + @param[in] SMType The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplaySELSysManagementTypes ( + IN UINT32 SMType, + IN UINT8 Option + ); + +/** + Display Physical Memory Array (Type 16) Location. + + @param[in] Location The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPMALocation ( + IN UINT8 Location, + IN UINT8 Option + ); + +/** + Display Physical Memory Array (Type 16) Use. + + @param[in] Use The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPMAUse ( + IN UINT8 Use, + IN UINT8 Option + ); + +/** + Display Physical Memory Array (Type 16) Types. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPMAErrorCorrectionTypes ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Memory Device (Type 17) form factor. + + @param[in] FormFactor The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceFormFactor ( + IN UINT8 FormFactor, + IN UINT8 Option + ); + +/** + Display Memory Device (Type 17) type. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Memory Device (Type 17) details. + + @param[in] Para The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceTypeDetail ( + IN UINT16 Para, + IN UINT8 Option + ); + +/** + Display Memory Device (Type 17) memory technology. + + @param[in] Para The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceMemoryTechnology ( + IN UINT8 Para, + IN UINT8 Option + ); + +/** + Display Memory Device (Type 17) memory operating mode capability. + + @param[in] Para The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryDeviceMemoryOperatingModeCapability ( + IN UINT16 Para, + IN UINT8 Option + ); + +/** + Display 32-bit Memory Error Information (Type 18) type. + + @param[in] ErrorType The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryErrorType ( + IN UINT8 ErrorType, + IN UINT8 Option + ); + +/** + Display 32-bit Memory Error Information (Type 18) error granularity. + + @param[in] Granularity The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryErrorGranularity ( + IN UINT8 Granularity, + IN UINT8 Option + ); + +/** + Display 32-bit Memory Error Information (Type 18) error information. + + @param[in] Operation The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryErrorOperation ( + IN UINT8 Operation, + IN UINT8 Option + ); + +/** + Display Built-in Pointing Device (Type 21) type information. + + @param[in] Type The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPointingDeviceType ( + IN UINT8 Type, + IN UINT8 Option + ); + +/** + Display Built-in Pointing Device (Type 21) information. + + @param[in] Interface The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPointingDeviceInterface ( + IN UINT8 Interface, + IN UINT8 Option + ); + +/** + Display Portable Battery (Type 22) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayPBDeviceChemistry ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Voltage Probe (Type 26) location information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayVPLocation ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Voltage Probe (Type 26) status ype information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayVPStatus ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Cooling (Type 27) status information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCoolingDeviceStatus ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Cooling (Type 27) type information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayCoolingDeviceType ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Temperature Probe (Type 28) status information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayTemperatureProbeStatus ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Temperature Probe (Type 28) location information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayTemperatureProbeLoc ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Electrical Current Probe (Type 29) status information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayECPStatus ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Electrical Current Probe (Type 29) location information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayECPLoc ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Management Device (Type 34) Type. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMDType ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Management Device (Type 34) Address Type. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMDAddressType ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Memory Channel (Type 37) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMemoryChannelType ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display IPMI Device Information (Type 38) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayIPMIDIBMCInterfaceType ( + IN UINT8 Key, + IN UINT8 Option + ); + +/** + Display Management Controller Host Interface (Type 42) information. + + @param[in] Key The key of the structure. + @param[in] Option The optional information. +**/ +VOID +DisplayMCHostInterfaceType ( + IN UINT8 Key, + IN UINT8 Option + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c new file mode 100644 index 0000000..9a0aa21 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c @@ -0,0 +1,1005 @@ +/** @file + Tools of clarify the content of the smbios table. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include "LibSmbiosView.h" +#include "SmbiosView.h" +#include "PrintInfo.h" +#include "QueryTable.h" + +UINT8 gShowType = SHOW_DETAIL; +STATIC STRUCTURE_STATISTICS *mStatisticsTable = NULL; +STATIC STRUCTURE_STATISTICS *mSmbios64BitStatisticsTable = NULL; + +UINT8 SmbiosMajorVersion; +UINT8 SmbiosMinorVersion; + +UINTN mNumberOfSmbios64BitStructures; +UINTN mSmbios64BitTableLength; + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-t", TypeValue}, + {L"-h", TypeValue}, + {L"-s", TypeFlag}, + {L"-a", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'smbiosview' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSmbiosView ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT8 StructType; + UINT16 StructHandle; + EFI_STATUS Status; + EFI_STATUS Status1; + EFI_STATUS Status2; + BOOLEAN RandomView; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Temp; + + mStatisticsTable = NULL; + mSmbios64BitStatisticsTable = NULL; + Package = NULL; + ShellStatus = SHELL_SUCCESS; + + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"smbiosview", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"smbiosview"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetValue(Package, L"-t") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"smbiosview", L"-t"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-h") && ShellCommandLineGetValue(Package, L"-h") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"smbiosview", L"-h"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ( + (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetFlag(Package, L"-h")) || + (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetFlag(Package, L"-s")) || + (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetFlag(Package, L"-a")) || + (ShellCommandLineGetFlag(Package, L"-h") && ShellCommandLineGetFlag(Package, L"-s")) || + (ShellCommandLineGetFlag(Package, L"-h") && ShellCommandLineGetFlag(Package, L"-a")) || + (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-a")) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"smbiosview"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + + // + // Init Lib + // + Status1 = LibSmbiosInit (); + Status2 = LibSmbios64BitInit (); + if (EFI_ERROR (Status1) && EFI_ERROR (Status2)) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_CANNOT_GET_TABLE), gShellDebug1HiiHandle); + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + + StructType = STRUCTURE_TYPE_RANDOM; + RandomView = TRUE; + + Temp = ShellCommandLineGetValue(Package, L"-t"); + if (Temp != NULL) { + StructType = (UINT8) ShellStrToUintn (Temp); + } + + if (ShellCommandLineGetFlag(Package, L"-a")) { + gShowType = SHOW_ALL; + } + + if (!EFI_ERROR (Status1)) { + // + // Initialize the StructHandle to be the first handle + // + StructHandle = INVALID_HANDLE; + LibGetSmbiosStructure (&StructHandle, NULL, NULL); + + Temp = ShellCommandLineGetValue(Package, L"-h"); + if (Temp != NULL) { + RandomView = FALSE; + StructHandle = (UINT16) ShellStrToUintn(Temp); + } + // + // build statistics table + // + Status = InitSmbiosTableStatistics (); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + + if (ShellCommandLineGetFlag(Package, L"-s")) { + Status = DisplayStatisticsTable (SHOW_DETAIL); + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + goto Show64Bit; + } + + // + // Show SMBIOS structure information + // + Status = SMBiosView (StructType, StructHandle, gShowType, RandomView); + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + } + +Show64Bit: + if (!EFI_ERROR (Status2)) { + // + // build statistics table + // + Status = InitSmbios64BitTableStatistics (); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + // + // Initialize the StructHandle to be the first handle + // + StructHandle = INVALID_HANDLE; + LibGetSmbios64BitStructure (&StructHandle, NULL, NULL); + + Temp = ShellCommandLineGetValue(Package, L"-h"); + if (Temp != NULL) { + RandomView = FALSE; + StructHandle = (UINT16) ShellStrToUintn(Temp); + } + + if (ShellCommandLineGetFlag(Package, L"-s")) { + Status = DisplaySmbios64BitStatisticsTable (SHOW_DETAIL); + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + goto Done; + } + + // + // Show SMBIOS structure information + // + Status = SMBios64View (StructType, StructHandle, gShowType, RandomView); + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + } + } + } +Done: + // + // Release resources + // + if (mStatisticsTable != NULL) { + // + // Release statistics table + // + FreePool (mStatisticsTable); + mStatisticsTable = NULL; + } + + if (mSmbios64BitStatisticsTable != NULL) { + // + // Release statistics table + // + FreePool (mSmbios64BitStatisticsTable); + mSmbios64BitStatisticsTable = NULL; + } + + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + + LibSmbiosCleanup (); + LibSmbios64BitCleanup (); + + return ShellStatus; +} + +/** + Query all structures Data from SMBIOS table and Display + the information to users as required display option. + + @param[in] QueryType Structure type to view. + @param[in] QueryHandle Structure handle to view. + @param[in] Option Display option: none,outline,normal,detail. + @param[in] RandomView Support for -h parameter. + + @retval EFI_SUCCESS print is successful. + @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table. +**/ +EFI_STATUS +SMBiosView ( + IN UINT8 QueryType, + IN UINT16 QueryHandle, + IN UINT8 Option, + IN BOOLEAN RandomView + ) +{ + UINT16 Handle; + UINT8 *Buffer; + UINT16 Length; + UINTN Index; + + SMBIOS_STRUCTURE_POINTER SmbiosStruct; + SMBIOS_TABLE_ENTRY_POINT *SMBiosTable; + + SMBiosTable = NULL; + LibSmbiosGetEPS (&SMBiosTable); + if (SMBiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle); + return EFI_BAD_BUFFER_SIZE; + } + + if (CompareMem (SMBiosTable->AnchorString, "_SM_", 4) == 0) { + // + // Have got SMBIOS table + // + SmbiosPrintEPSInfo (SMBiosTable, Option); + + SmbiosMajorVersion = SMBiosTable->MajorVersion; + SmbiosMinorVersion = SMBiosTable->MinorVersion; + + ShellPrintEx(-1,-1,L"=========================================================\n"); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERY_STRUCT_COND), gShellDebug1HiiHandle); + + if (QueryType == STRUCTURE_TYPE_RANDOM) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE_RANDOM), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE), gShellDebug1HiiHandle, QueryType); + } + + if (RandomView) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE_RANDOM), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE), gShellDebug1HiiHandle, QueryHandle); + } + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SHOWTYPE), gShellDebug1HiiHandle); + ShellPrintEx(-1,-1,GetShowTypeString (gShowType)); + ShellPrintEx(-1,-1,L"\n\n"); + +/* + // + // Get internal commands, such as change options. + // + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } +*/ + + // + // Searching and display structure info + // + Handle = QueryHandle; + for (Index = 0; Index < SMBiosTable->NumberOfSmbiosStructures; Index++) { + // + // if reach the end of table, break.. + // + if (Handle == INVALID_HANDLE) { + break; + } + // + // handle then point to the next! + // + if (LibGetSmbiosStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) { + break; + } + + SmbiosStruct.Raw = Buffer; + + // + // if QueryType==Random, print this structure. + // if QueryType!=Random, but Hdr->Type==QueryType, also print it. + // only if QueryType != Random and Hdr->Type != QueryType, skiped it. + // + if (QueryType != STRUCTURE_TYPE_RANDOM && SmbiosStruct.Hdr->Type != QueryType) { + continue; + } + + ShellPrintEx(-1,-1,L"\n=========================================================\n"); + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE_HANDLE_DUMP_STRUCT), + gShellDebug1HiiHandle, + SmbiosStruct.Hdr->Type, + SmbiosStruct.Hdr->Handle + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX_LENGTH), gShellDebug1HiiHandle, Index, Length); + // + // Addr of structure in structure in table + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ADDR), gShellDebug1HiiHandle, (UINTN) Buffer); + DumpHex (0, 0, Length, Buffer); + +/* + // + // Get internal commands, such as change options. + // + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } +*/ + + if (gShowType != SHOW_NONE) { + // + // Print structure information + // + SmbiosPrintStructure (&SmbiosStruct, gShowType); + ShellPrintEx(-1,-1,L"\n"); + +/* + // + // Get internal commands, such as change options. + // + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } +*/ + } + if (!RandomView) { + break; + } + // + // Support Execution Interrupt. + // + if (ShellGetExecutionBreakFlag ()) { + return EFI_ABORTED; + } + } + + ShellPrintEx(-1,-1,L"\n=========================================================\n"); + return EFI_SUCCESS; + } + + return EFI_BAD_BUFFER_SIZE; +} + +/** + Query all structures Data from SMBIOS table and Display + the information to users as required display option. + + @param[in] QueryType Structure type to view. + @param[in] QueryHandle Structure handle to view. + @param[in] Option Display option: none,outline,normal,detail. + @param[in] RandomView Support for -h parameter. + + @retval EFI_SUCCESS print is successful. + @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table. +**/ +EFI_STATUS +SMBios64View ( + IN UINT8 QueryType, + IN UINT16 QueryHandle, + IN UINT8 Option, + IN BOOLEAN RandomView + ) +{ + UINT16 Handle; + UINT8 *Buffer; + UINT16 Length; + UINTN Index; + SMBIOS_STRUCTURE_POINTER SmbiosStruct; + SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable; + + SMBiosTable = NULL; + LibSmbios64BitGetEPS (&SMBiosTable); + if (SMBiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle); + return EFI_BAD_BUFFER_SIZE; + } + + if (CompareMem (SMBiosTable->AnchorString, "_SM3_", 5) == 0) { + // + // Have got SMBIOS table + // + Smbios64BitPrintEPSInfo (SMBiosTable, Option); + + SmbiosMajorVersion = SMBiosTable->MajorVersion; + SmbiosMinorVersion = SMBiosTable->MinorVersion; + + ShellPrintEx(-1,-1,L"=========================================================\n"); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERY_STRUCT_COND), gShellDebug1HiiHandle); + + if (QueryType == STRUCTURE_TYPE_RANDOM) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE_RANDOM), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE), gShellDebug1HiiHandle, QueryType); + } + + if (RandomView) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE_RANDOM), gShellDebug1HiiHandle); + } else { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE), gShellDebug1HiiHandle, QueryHandle); + } + + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SHOWTYPE), gShellDebug1HiiHandle); + ShellPrintEx(-1,-1,GetShowTypeString (gShowType)); + ShellPrintEx(-1,-1,L"\n\n"); + +/* + // + // Get internal commands, such as change options. + // + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } +*/ + + // + // Searching and display structure info + // + Handle = QueryHandle; + for (Index = 0; Index < mNumberOfSmbios64BitStructures; Index++) { + // + // if reach the end of table, break.. + // + if (Handle == INVALID_HANDLE) { + break; + } + // + // handle then point to the next! + // + if (LibGetSmbios64BitStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) { + break; + } + + SmbiosStruct.Raw = Buffer; + + // + // if QueryType==Random, print this structure. + // if QueryType!=Random, but Hdr->Type==QueryType, also print it. + // only if QueryType != Random and Hdr->Type != QueryType, skiped it. + // + if (QueryType != STRUCTURE_TYPE_RANDOM && SmbiosStruct.Hdr->Type != QueryType) { + continue; + } + + ShellPrintEx(-1,-1,L"\n=========================================================\n"); + ShellPrintHiiEx(-1,-1,NULL, + STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE_HANDLE_DUMP_STRUCT), + gShellDebug1HiiHandle, + SmbiosStruct.Hdr->Type, + SmbiosStruct.Hdr->Handle + ); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX_LENGTH), gShellDebug1HiiHandle, Index, Length); + // + // Addr of structure in structure in table + // + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ADDR), gShellDebug1HiiHandle, (UINTN) Buffer); + DumpHex (0, 0, Length, Buffer); + +/* + // + // Get internal commands, such as change options. + // + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } +*/ + + if (gShowType != SHOW_NONE) { + // + // Print structure information + // + SmbiosPrintStructure (&SmbiosStruct, gShowType); + ShellPrintEx(-1,-1,L"\n"); + +/* + // + // Get internal commands, such as change options. + // + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } +*/ + } + if (!RandomView) { + break; + } + // + // Support Execution Interrupt. + // + if (ShellGetExecutionBreakFlag ()) { + return EFI_ABORTED; + } + } + + ShellPrintEx(-1,-1,L"\n=========================================================\n"); + return EFI_SUCCESS; + } + + return EFI_BAD_BUFFER_SIZE; +} + +/** + Function to initialize the global mStatisticsTable object. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +InitSmbiosTableStatistics ( + VOID + ) +{ + UINT16 Handle; + UINT8 *Buffer; + UINT16 Length; + UINT16 Offset; + UINT16 Index; + + SMBIOS_STRUCTURE_POINTER SmbiosStruct; + SMBIOS_TABLE_ENTRY_POINT *SMBiosTable; + STRUCTURE_STATISTICS *StatisticsPointer; + + SMBiosTable = NULL; + LibSmbiosGetEPS (&SMBiosTable); + if (SMBiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle); + return EFI_NOT_FOUND; + } + + if (CompareMem (SMBiosTable->AnchorString, "_SM_", 4) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_TABLE), gShellDebug1HiiHandle); + return EFI_INVALID_PARAMETER; + } + // + // Allocate memory to mStatisticsTable + // + if (mStatisticsTable != NULL) { + FreePool (mStatisticsTable); + mStatisticsTable = NULL; + } + + mStatisticsTable = (STRUCTURE_STATISTICS *) AllocateZeroPool (SMBiosTable->NumberOfSmbiosStructures * sizeof (STRUCTURE_STATISTICS)); + + if (mStatisticsTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OUT_OF_MEM), gShellDebug1HiiHandle); + return EFI_OUT_OF_RESOURCES; + } + + Offset = 0; + StatisticsPointer = mStatisticsTable; + + // + // search from the first one + // + Handle = INVALID_HANDLE; + LibGetSmbiosStructure (&Handle, NULL, NULL); + for (Index = 1; Index <= SMBiosTable->NumberOfSmbiosStructures; Index++) { + // + // If reach the end of table, break.. + // + if (Handle == INVALID_HANDLE) { + break; + } + // + // After LibGetSmbiosStructure(), handle then point to the next! + // + if (LibGetSmbiosStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) { + break; + } + + SmbiosStruct.Raw = Buffer; + + // + // general statistics + // + StatisticsPointer->Index = Index; + StatisticsPointer->Type = SmbiosStruct.Hdr->Type; + StatisticsPointer->Handle = SmbiosStruct.Hdr->Handle; + StatisticsPointer->Length = Length; + StatisticsPointer->Addr = Offset; + + Offset = (UINT16) (Offset + Length); + + StatisticsPointer = &mStatisticsTable[Index]; + } + + return EFI_SUCCESS; +} + +/** + @param[in] Smbios64EntryPoint SMBIOS 64-bit entry point. + @param[out] NumberOfSmbios64Structures The number of structures in 64-bit SMBIOS table. + @param[out] Smbios64TableLength The total length of 64-bit SMBIOS table. + + @retval EFI_SUCCESS Calculation was successful. +**/ +EFI_STATUS +CalculateSmbios64BitStructureCountAndLength ( + SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios64EntryPoint, + UINTN *NumberOfSmbios64Structures, + UINTN *Smbios64TableLength +) +{ + SMBIOS_STRUCTURE_POINTER Smbios; + UINT8 *Raw; + + *Smbios64TableLength = 0; + *NumberOfSmbios64Structures = 0; + + Smbios.Raw = (UINT8 *)(UINTN)(Smbios64EntryPoint->TableAddress); + while (TRUE) { + if (Smbios.Hdr->Type == 127) { + // + // Reach the end of table type 127 + // + (*NumberOfSmbios64Structures)++; + (*Smbios64TableLength) += sizeof (SMBIOS_STRUCTURE); + return EFI_SUCCESS; + } + + Raw = Smbios.Raw; + // + // Walk to next structure + // + LibGetSmbiosString (&Smbios, (UINT16) (-1)); + // + // Length = Next structure head - this structure head + // + (*Smbios64TableLength) += ((UINTN) Smbios.Raw - (UINTN) Raw); + if ((*Smbios64TableLength) > Smbios64EntryPoint->TableMaximumSize) { + // + // The actual table length exceeds maximum table size, + // There should be something wrong with SMBIOS table. + // + return EFI_INVALID_PARAMETER; + } + (*NumberOfSmbios64Structures)++; + } +} + +/** + Function to initialize the global mSmbios64BitStatisticsTable object. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +InitSmbios64BitTableStatistics ( + VOID + ) +{ + UINT16 Handle; + UINT8 *Buffer; + UINT16 Length; + UINT16 Offset; + UINT16 Index; + EFI_STATUS Status; + SMBIOS_STRUCTURE_POINTER SmbiosStruct; + SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable; + STRUCTURE_STATISTICS *StatisticsPointer; + + SMBiosTable = NULL; + LibSmbios64BitGetEPS (&SMBiosTable); + if (SMBiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle); + return EFI_NOT_FOUND; + } + + if (CompareMem (SMBiosTable->AnchorString, "_SM3_", 5) != 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_TABLE), gShellDebug1HiiHandle); + return EFI_INVALID_PARAMETER; + } + // + // Allocate memory to mSmbios64BitStatisticsTable + // + if (mSmbios64BitStatisticsTable != NULL) { + FreePool (mSmbios64BitStatisticsTable); + mSmbios64BitStatisticsTable = NULL; + } + // + // Calculate number of smbios structures + // + Status = CalculateSmbios64BitStructureCountAndLength (SMBiosTable, &mNumberOfSmbios64BitStructures, &mSmbios64BitTableLength); + if ((EFI_ERROR (Status)) || (mSmbios64BitTableLength > SMBiosTable->TableMaximumSize)) { + return EFI_INVALID_PARAMETER; + } + + mSmbios64BitStatisticsTable = (STRUCTURE_STATISTICS *) AllocateZeroPool (mNumberOfSmbios64BitStructures * sizeof (STRUCTURE_STATISTICS)); + + if (mSmbios64BitStatisticsTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OUT_OF_MEM), gShellDebug1HiiHandle); + return EFI_OUT_OF_RESOURCES; + } + + Offset = 0; + StatisticsPointer = mSmbios64BitStatisticsTable; + + // + // search from the first one + // + Handle = INVALID_HANDLE; + LibGetSmbios64BitStructure (&Handle, NULL, NULL); + for (Index = 1; Index <= mNumberOfSmbios64BitStructures; Index++) { + // + // If reach the end of table, break.. + // + if (Handle == INVALID_HANDLE) { + break; + } + // + // After LibGetSmbios64BitStructure(), handle then point to the next! + // + if (LibGetSmbios64BitStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) { + break; + } + + SmbiosStruct.Raw = Buffer; + + // + // general statistics + // + StatisticsPointer->Index = Index; + StatisticsPointer->Type = SmbiosStruct.Hdr->Type; + StatisticsPointer->Handle = SmbiosStruct.Hdr->Handle; + StatisticsPointer->Length = Length; + StatisticsPointer->Addr = Offset; + + Offset = (UINT16) (Offset + Length); + + StatisticsPointer = &mSmbios64BitStatisticsTable[Index]; + } + + return EFI_SUCCESS; +} + +/** + Function to display the global mStatisticsTable object. + + @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +DisplayStatisticsTable ( + IN UINT8 Option + ) +{ + UINTN Index; + UINTN Num; + STRUCTURE_STATISTICS *StatisticsPointer; + SMBIOS_TABLE_ENTRY_POINT *SMBiosTable; + + SMBiosTable = NULL; + if (Option < SHOW_OUTLINE) { + return EFI_SUCCESS; + } + // + // display EPS information firstly + // + LibSmbiosGetEPS (&SMBiosTable); + if (SMBiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle); + return EFI_UNSUPPORTED; + } + + ShellPrintEx(-1,-1,L"\n============================================================\n"); + SmbiosPrintEPSInfo (SMBiosTable, Option); + + if (Option < SHOW_NORMAL) { + return EFI_SUCCESS; + } + + if (mStatisticsTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_STATS), gShellDebug1HiiHandle); + return EFI_NOT_FOUND; + } + + ShellPrintEx(-1,-1,L"============================================================\n"); + StatisticsPointer = &mStatisticsTable[0]; + Num = SMBiosTable->NumberOfSmbiosStructures; + // + // display statistics table content + // + for (Index = 1; Index <= Num; Index++) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX), gShellDebug1HiiHandle, StatisticsPointer->Index); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE), gShellDebug1HiiHandle, StatisticsPointer->Type); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE), gShellDebug1HiiHandle, StatisticsPointer->Handle); + if (Option >= SHOW_DETAIL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OFFSET), gShellDebug1HiiHandle, StatisticsPointer->Addr); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_LENGTH), gShellDebug1HiiHandle, StatisticsPointer->Length); + } + + ShellPrintEx(-1,-1,L"\n"); + StatisticsPointer = &mStatisticsTable[Index]; +/* + // + // Display 20 lines and wait for a page break + // + if (Index % 20 == 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_CONTINUE), gShellDebug1HiiHandle); + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } + } +*/ + } + + return EFI_SUCCESS; +} + +/** + Function to display the global mSmbios64BitStatisticsTable object. + + @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +DisplaySmbios64BitStatisticsTable ( + IN UINT8 Option + ) +{ + UINTN Index; + UINTN Num; + STRUCTURE_STATISTICS *StatisticsPointer; + SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable; + + SMBiosTable = NULL; + if (Option < SHOW_OUTLINE) { + return EFI_SUCCESS; + } + // + // display EPS information firstly + // + LibSmbios64BitGetEPS (&SMBiosTable); + if (SMBiosTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle); + return EFI_UNSUPPORTED; + } + + ShellPrintEx(-1,-1,L"\n============================================================\n"); + Smbios64BitPrintEPSInfo (SMBiosTable, Option); + + if (Option < SHOW_NORMAL) { + return EFI_SUCCESS; + } + + if (mSmbios64BitStatisticsTable == NULL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_STATS), gShellDebug1HiiHandle); + return EFI_NOT_FOUND; + } + + ShellPrintEx(-1,-1,L"============================================================\n"); + StatisticsPointer = &mSmbios64BitStatisticsTable[0]; + Num = mNumberOfSmbios64BitStructures; + // + // display statistics table content + // + for (Index = 1; Index <= Num; Index++) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX), gShellDebug1HiiHandle, StatisticsPointer->Index); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE), gShellDebug1HiiHandle, StatisticsPointer->Type); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE), gShellDebug1HiiHandle, StatisticsPointer->Handle); + if (Option >= SHOW_DETAIL) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OFFSET), gShellDebug1HiiHandle, StatisticsPointer->Addr); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_LENGTH), gShellDebug1HiiHandle, StatisticsPointer->Length); + } + + ShellPrintEx(-1,-1,L"\n"); + StatisticsPointer = &mSmbios64BitStatisticsTable[Index]; +/* + // + // Display 20 lines and wait for a page break + // + if (Index % 20 == 0) { + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_CONTINUE), gShellDebug1HiiHandle); + Status = WaitEnter (); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + return Status; + } + } +*/ + } + + return EFI_SUCCESS; +} + +/** + function to return a string of the detail level. + + @param[in] ShowType The detail level whose name is desired in clear text. + + @return A pointer to a string representing the ShowType (or 'undefined type' if not known). +**/ +CHAR16 * +GetShowTypeString ( + UINT8 ShowType + ) +{ + // + // show type + // + switch (ShowType) { + + case SHOW_NONE: + return L"SHOW_NONE"; + + case SHOW_OUTLINE: + return L"SHOW_OUTLINE"; + + case SHOW_NORMAL: + return L"SHOW_NORMAL"; + + case SHOW_DETAIL: + return L"SHOW_DETAIL"; + + case SHOW_ALL: + return L"SHOW_ALL"; + + default: + return L"Undefined type"; + } +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h new file mode 100644 index 0000000..559fedf --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h @@ -0,0 +1,129 @@ +/** @file + Tools of clarify the content of the smbios table. + + Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SMBIOS_VIEW_H_ +#define _SMBIOS_VIEW_H_ + +#define STRUCTURE_TYPE_RANDOM (UINT8) 0xFE +#define STRUCTURE_TYPE_INVALID (UINT8) 0xFF + +typedef struct { + UINT16 Index; + UINT8 Type; + UINT16 Handle; + UINT16 Addr; // offset from table head + UINT16 Length; // total structure length +} STRUCTURE_STATISTICS; + +/** + Query all structures Data from SMBIOS table and Display + the information to users as required display option. + + @param[in] QueryType Structure type to view. + @param[in] QueryHandle Structure handle to view. + @param[in] Option Display option: none,outline,normal,detail. + @param[in] RandomView Support for -h parameter. + + @retval EFI_SUCCESS print is successful. + @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table. +**/ +EFI_STATUS +SMBiosView ( + IN UINT8 QueryType, + IN UINT16 QueryHandle, + IN UINT8 Option, + IN BOOLEAN RandomView + ); + +/** + Query all structures Data from SMBIOS table and Display + the information to users as required display option. + + @param[in] QueryType Structure type to view. + @param[in] QueryHandle Structure handle to view. + @param[in] Option Display option: none,outline,normal,detail. + @param[in] RandomView Support for -h parameter. + + @retval EFI_SUCCESS print is successful. + @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table. +**/ +EFI_STATUS +SMBios64View ( + IN UINT8 QueryType, + IN UINT16 QueryHandle, + IN UINT8 Option, + IN BOOLEAN RandomView + ); + +/** + Function to initialize the global mStatisticsTable object. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +InitSmbiosTableStatistics ( + VOID + ); + +/** + Function to initialize the global mSmbios64BitStatisticsTable object. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +InitSmbios64BitTableStatistics ( + VOID + ); + +/** + Function to display the global mStatisticsTable object. + + @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +DisplayStatisticsTable ( + IN UINT8 Option + ); + +/** + Function to display the global mSmbios64BitStatisticsTable object. + + @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed. + + @retval EFI_SUCCESS print is successful. +**/ +EFI_STATUS +DisplaySmbios64BitStatisticsTable ( + IN UINT8 Option + ); + +/** + function to return a string of the detail level. + + @param[in] ShowType The detail level whose name is desired in clear text. + + @return A pointer to a string representing the ShowType (or 'undefined type' if not known). +**/ +CHAR16* +GetShowTypeString ( + UINT8 ShowType + ); + +extern UINT8 gShowType; + +extern UINTN mSmbios64BitTableLength; + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni new file mode 100644 index 0000000..ebdebda --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni @@ -0,0 +1,506 @@ +// /** +// +// Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
        +// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        +// (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellDebug1CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 Debug1 profile SmBiosView command +// +// +// **/ +/=# +#langdef en-US "english" +#string STR_SMBIOSVIEW_EVENTLOGINFO_ACCESS_METHOD #language en-US "Access method: " +#string STR_SMBIOSVIEW_EVENTLOGINFO_ONE_EIGHT_BIT #language en-US "Indexed I/O: 1 8-bit index port, 1 8-bit data port\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_TWO_EIGHT_BITS #language en-US "Indexed I/O: 2 8-bit index ports, 1 8-bit data port\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_ONE_SIXTEEN_BIT #language en-US "Indexed I/O: 1 16-bit index port, 1 8-bit data port\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_MEM_MAPPED_PHYS #language en-US "Memory-mapped physical 32-bit address\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_VIA_GENERAL #language en-US "Available via General-Purpose NonVolatile Data functions\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE_ASSIGN #language en-US "Available for future assignment via this specification\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR_OEM #language en-US "BIOS Vendor/OEM-specific \r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_STATUS #language en-US "Log Status: " +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_VALID #language en-US "Log area valid\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_FULL #language en-US "Log area full\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_NOT_FULL #language en-US "Log area not full\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_RES_BITS_NOT_ZERO #language en-US "Reserved bits not zero - 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_FORMAT #language en-US "Log Header Format: \r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_NO_HEADER #language en-US "No Header\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_TYPE_LOG_HEADER #language en-US "Type 1 log header\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE #language en-US "Available for future\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR #language en-US "BIOS Vendor/OEM-specific format\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_LEN #language en-US "Log Header Len: " +#string STR_SMBIOSVIEW_EVENTLOGINFO_ONE_VAR_D #language en-US " %d\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_READ #language en-US "This record has been read\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_NOT_READ #language en-US "This record has not been read\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG #language en-US "System Event Log Header Type1 Format:\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_OEM_RESERVED #language en-US "OEM Reserved:\r\n0x%x 0x%x 0x%x 0x%x 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_TIME #language en-US "Multiple Event Time Window: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_COUNT #language en-US "Multiple Event Count Increment: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_ADDRESS #language en-US "Pre-boot Event Log Reset - CMOS Address: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_INDEX #language en-US "Pre-boot Event Log Reset - CMOS Bit Index: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUM_STARTING_OFF #language en-US "CMOS Checksum - Starting Offset: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUN_BYTE_COUNT #language en-US "CMOS Checksum - Byte Count: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_RESERVED #language en-US "Reserved: 0x%x 0x%x 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_HEADER_REVISION #language en-US "HeaderRevision: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER #language en-US "\r\nLog Header: " +#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FUTURE_ASSIGN #language en-US "Available for future assignment via this specification\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_NO_STD_FORMAT #language en-US "No standard format data is available\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_SMBIOS_STRUCT_ASSOC #language en-US "SMBIOS structure associated with the hardware element that failed\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_STRUCT_HANDLE #language en-US "Structure handle = 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER #language en-US "multiple-event counter: 0x%x\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_UNUSED_AVAIL_FOR_ASSIGN #language en-US "Unused, available for assignment by this specification\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_SYSTEM #language en-US "Available for system- and OEM-specific assignments\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG_2 #language en-US "\r\nSystem Event Log records:\r\n" +#string STR_SMBIOSVIEW_EVENTLOGINFO_DATE #language en-US "Date/Time: " +#string STR_SMBIOSVIEW_EVENTLOGINFO_ERROR #language en-US "error" +#string STR_SMBIOSVIEW_EVENTLOGINFO_TIME_SIX_VARS #language en-US "%02x/%02x/%02x, %x:%x:%x\r\n" +#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_CANNOT_GET_TABLE #language en-US "Cannot get SMBIOS Table\r\n" +#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR #language en-US "Get SMBIOS Table error - %r\r\n" +#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC #language en-US " Get SMBIOS Structure, no buffer or length specified!\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DUMP #language en-US "Dump " +#string STR_SMBIOSVIEW_PRINTINFO_SIZE #language en-US "\r\nsize=%d:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SMBIOSTABLE_NULL #language en-US "SMBiosTable is NULL!\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_SIGN #language en-US "%HSMBIOS Entry Point Structure:%N\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_64_BIT_ENTRY_POINT_SIGN #language en-US "%HSMBIOS 3.0 (64-bit) Entry Point Structure:%N\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BCD_REVISION #language en-US "SMBIOS BCD Revision: 0x%x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DOCREV #language en-US "SMBIOS Docrev: 0x%x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NUMBER_STRUCT #language en-US "Number of Structures: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MAX_STRUCT_SIZE #language en-US "Max Struct size: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TABLE_ADDR #language en-US "Table Address: 0x%p\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TABLE_LENGTH #language en-US "Table Length: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TABLE_MAX_SIZE #language en-US "Table Max Size: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ANCHOR_STR #language en-US "Anchor String: %a\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_EPS_CHECKSUM #language en-US "EPS Checksum: 0x%x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_LEN #language en-US "Entry Point Len: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_VERSION #language en-US "Version: %d.%d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MAJOR_VERSION #language en-US "Major version: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MINOR_VERSION #language en-US "Minor version: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_REVISION #language en-US "Entry Point revision: 0x%x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_FORMATTED_AREA_NONE #language en-US "Formatted Area: None\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_FORMATTED_AREA #language en-US "Formatted Area: \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTER_ACHOR #language en-US "Inter Anchor: %a\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTER_CHECKSUM #language en-US "Inter Checksum: 0x%x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_FORMAT_PART_LEN #language en-US "Format part Len : %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_STRUCT_HANDLE #language en-US "Structure Handle: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BOOTUP_STATE #language en-US "Bootup state " +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_STATE #language en-US "Power Supply State " +#string STR_SMBIOSVIEW_PRINTINFO_THERMAL_STATE #language en-US "Thermal state " +#string STR_SMBIOSVIEW_PRINTINFO_SECURITY_STATUS #language en-US "Security Status " +#string STR_SMBIOSVIEW_PRINTINFO_SUPOPRT #language en-US "Support " +#string STR_SMBIOSVIEW_PRINTINFO_CURRENT #language en-US "Current " +#string STR_SMBIOSVIEW_PRINTINFO_INSTALLED #language en-US "Installed " +#string STR_SMBIOSVIEW_PRINTINFO_ENABLED #language en-US "Enabled " +#string STR_SMBIOSVIEW_PRINTINFO_EXTERNAL #language en-US "External " +#string STR_SMBIOSVIEW_PRINTINFO_SLOT_PEER_GROUPS #language en-US "Peer Groups %d:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SEGMENT_GROUP_NUM #language en-US " SegmentGroup Num: 0x%04x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BUS_NUM #language en-US " Bus Num: 0x%02x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DEV_FUNC_NUM #language en-US " DevFunc Num: 0x%02x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DATA_BUS_WIDTH #language en-US " DataBus Width: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DESC_STRING #language en-US "Description String: " +#string STR_SMBIOSVIEW_PRINTINFO_SUPOPRTED_EVENT #language en-US "Supported Event Log Type Descriptors %d:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ACCESS_METHOD_NOT_SUPOPRTED #language en-US "Access Method %d has not supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE31 #language en-US "This structure is Type31, reserved by BIS (Boot Integrity Services)\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MEM_DEVICE #language en-US "Memory Device %d:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DEV_LOAD #language en-US "Device Load: 0x%02x," +#string STR_SMBIOSVIEW_PRINTINFO_DEV_HANDLE #language en-US "Device Handle: 0x%04x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INACTIVE_STRUCT #language en-US "Inactive structure --- Needn't interpret it.\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_THIS_STRUCT_END_TABLE #language en-US "This structure indicates the End-of-table!\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE_UNDEFINED #language en-US "Structure Type undefined!\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR #language en-US "BIOS Characteristics: \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT #language en-US "Reserved bit\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UNKNOWN_BIT #language en-US "Unknown bit\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_NOT_SUPPORTED #language en-US "BIOS Characteristics Not Supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ISA_SUPPORTED #language en-US "ISA is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MSA_SUPPORTED #language en-US "MSA is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_EISA_SUPPORTED #language en-US "EISA is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PCI_SUPPORTED #language en-US "PCI is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PC_CARD_SUPPORTED #language en-US "PC Card(PCMCIA) is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PLUG_PLAY_SUPPORTED #language en-US "Plug and play is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_APM_SUPPORTED #language en-US "APM is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_UPGRADEABLE #language en-US "BIOS is Upgradeable(FLASH)\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_SHADOWING #language en-US "BIOS shadowing is allowed\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_VESA_SUPPORTED #language en-US "VL-VESA is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ECSD_SUPPORT #language en-US "ESCD support is available\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FORM_CD_SUPPORTED #language en-US "Boot form CD is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SELECTED_BOOT_SUPPORTED #language en-US "Selectable Boot is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_ROM_SOCKETED #language en-US "BIOS ROM is socketed\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_PC_CARD #language en-US "Boot From PC Card(PCMCIA)is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_EDD_ENHANCED_DRIVER #language en-US "EDD (Enhanced Disk Driver) Specification is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_NEC #language en-US "Int 13h - Japanese Floppy for NEC 9800 1.2mb (3.5\",1k Bytes/Sector, 360 RPM) is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_TOSHIBA #language en-US "Int 13h - Japanese Floppy for Toshiba 1.2mn (3.5\", 360 RPM) is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_FLOPPY_SERVICES_SUPPORTED #language en-US "Int 13h - 5.25\"/360KB Floppy Services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ONE_POINT_TWO_MB #language en-US "Int 13h - 5.25\"/1.2MB Floppy services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_720_KB #language en-US "Int 13h - 3.5\"/720KB Floppy services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TWO_POINT_EIGHT_EIGHT_MB #language en-US "Int 13h - 3.5\"/2.88MB Floppy services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PRINT_SCREEN_SUPPORT #language en-US "Int 5h, Print screen Services is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_SERV_SUPPORT #language en-US "Int 9h, 8042 Keyboard services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SERIAL_SERVICES_SUPPORT #language en-US "Int 14h, Serial Services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PRINTER_SERVICES_SUPPORT #language en-US "Int 17h, Printer services are supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MONO_VIDEO_SUPPORT #language en-US "Int 10h, CGA/Mono Video services are supported2\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NEC_PC_98 #language en-US "NEC PC-98\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BITS_32_47 #language en-US " Bits 32:47 are reserved for BIOS Vendor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BITS_48_64 #language en-US " Bits 48:64 are reserved for System Vendor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION #language en-US "BIOS Characteristics Extension Byte1:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ACPI_SUPPORTED #language en-US "ACPI supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_USB_LEGACY_SUPPORTED #language en-US "USB Legacy is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AGP_SUPPORTED #language en-US "AGP is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_I2O_BOOT_SUPPORTED #language en-US "I2O boot is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_LS_120_BOOT_SUPPORTED #language en-US "LS-120 boot is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ATAPI_ZIP_DRIVE #language en-US "ATAPI ZIP Drive boot is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_1394_BOOT_SUPPORTED #language en-US "1394 boot is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SMART_BATTERY_SUPPORTED #language en-US "Smart battery supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION_2 #language en-US "BIOS Characteristics Extension Byte2:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_BOOT_SPEC_SUPP #language en-US "BIOS Boot Specification supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_FUNCTION_KEY_INIT #language en-US "Function key-initiated Network Service boot supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ENABLE_TAR_CONT_DIST #language en-US "Enable Targeted Content Distribution\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UEFI_SPEC_SUPPORT #language en-US "UEFI Specification is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_VIRTUAL_MACHINE #language en-US "The SMBIOS table describes a virtual machine\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE #language en-US " Bits %d:7 are reserved for future assignment\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PROCESSOR_FAMILY #language en-US "Processor Family: " +#string STR_SMBIOSVIEW_PRINTINFO_OTHER #language en-US "Other\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UNKNOWN #language en-US "Unknown\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL386_PROCESSOR #language en-US "Intel386(TM) Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL486_PROCESSOR #language en-US "Intel486(TM) Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_FAMILY #language en-US "Pentium(R) Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PRO_PROC #language en-US "Pentium(R) Pro processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_II_PROC #language en-US "Pentium(R) II processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_MMX #language en-US "Pentium(R) processor with MMX(TM) technology\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CELERON_PROC #language en-US "Celeron(TM) processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_XEON_PROC #language en-US "Pentium(R) II Xeon(TM) processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_PROC #language en-US "Pentium(R) III Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_M1_FAMILY #language en-US "M1 Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_K5_FAMILY #language en-US "K5 Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_FAMILY #language en-US "Power PC Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_601 #language en-US "Power PC 601\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603 #language en-US "Power PC 603\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603_PLUS #language en-US "Power PC 603+\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_604 #language en-US "Power PC 604\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ALPHA_FAMILY_2 #language en-US "Alpha Family 2\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO #language en-US "Intel(R) Core(TM) Duo processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO_MOBILE #language en-US "Intel(R) Core(TM) Duo mobile processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_SOLO_MOBILE #language en-US "Intel(R) Core(TM) Solo mobile processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_ATOM #language en-US "Intel(R) Atom(TM) processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_QUAD_CORE #language en-US "Quad-Core AMD Opteron(TM) Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_THIRD_GENERATION #language en-US "Third-Generation AMD Opteron(TM) Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_FX_QUAD_CORE #language en-US "AMD Phenom(TM) FX Quad-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X4_QUAD_CORE #language en-US "AMD Phenom(TM) X4 Quad-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X2_DUAL_CORE #language en-US "AMD Phenom(TM) X2 Dual-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_X2_DUAL_CORE #language en-US "AMD Athlon(TM) X2 Dual-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3200_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 3200 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3000_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 3000 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5300_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 5300 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5100_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5100 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5000_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5000 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_LV_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor LV\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_ULV_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor ULV\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7100_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 7100 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5400_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 5400 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5200_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5200 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7200_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 7200 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7300_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 7300 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 7400 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_MULTI_CORE #language en-US "Multi-Core Intel(R) Xeon(R) processor 7400 Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO #language en-US "Intel(R) Core(TM)2 Solo processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME #language en-US "Intel(R) Core(TM)2 Extreme processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_QUAD #language en-US "Intel(R) Core(TM)2 Quad processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME_MOBILE #language en-US "Intel(R) Core(TM)2 Extreme mobile processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_DUO_MOBILE #language en-US "Intel(R) Core(TM)2 Duo mobile processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO_MOBILE #language en-US "Intel(R) Core(TM)2 Solo mobile processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_I7 #language en-US "Intel(R) Core(TM) i7 processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CELERON_DUAL_CORE #language en-US "Dual-Core Intel(R) Celeron(R) processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_MULTI_CORE #language en-US "Multi-Core Intel(R) Xeon(R) processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 3xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 3xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 5xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 7xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 7xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_MULTI_CORE #language en-US "Multi-Core Intel(R) Xeon(R) processor 7xxx Series\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3000_SERIES #language en-US "AMD Opteron(TM) 3000 Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_II #language en-US "AMD Sempron(TM) II Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_FX_SERIES #language en-US "AMD FX(TM) Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_Z_SERIES #language en-US "AMD Z-Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_R_SERIES #language en-US "AMD R-Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_4300_SERIES #language en-US "AMD Opteron(TM) 4300 Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_6300_SERIES #language en-US "AMD Opteron(TM) 6300 Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3300_SERIES #language en-US "AMD Opteron(TM) 3300 Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_FIREPRO_SERIES #language en-US "AMD FirePro(TM) Series Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_EMBEDDED_OPTERON_QUAD_CORE #language en-US "Embedded AMD Opteron(TM) Quad-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_TRIPLE_CORE #language en-US "AMD Phenom(TM) Triple-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_ULTRA_DUAL_CORE_MOBILE #language en-US "AMD Turion(TM) Ultra Dual-Core Mobile Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_DUAL_CORE_MOBILE #language en-US "AMD Turion(TM) Dual-Core Mobile Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_DUAL_CORE #language en-US "AMD Athlon(TM) Dual-Core Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_SI #language en-US "AMD Sempron(TM) SI Processor Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MIPS_FAMILY #language en-US "MIPS Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SPARC_FAMILY #language en-US "SPARC Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_68040_FAMILY #language en-US "68040 Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_HOBBIT_FAMILY #language en-US "Hobbit Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_WEITEK #language en-US "Weitek\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PA_RISC_FAMILY #language en-US "PA-RISC Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_V30_FAMILY #language en-US "V30 Family\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_XEON #language en-US "Pentium(R) III Xeon(TM) Processor\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FOR_SPEC_M1 #language en-US "Reserved for specific M1 versions\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FOR_SPEC_K5 #language en-US "Reserved for specific K5 versions\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FOR_SPEC_PENTIUM #language en-US "Reserved for specific Pentium(R) Processor versions\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_PROC_FAMILY #language en-US "Undefined processor family and type\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PROC_INFO #language en-US "Processor Information - Voltage:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PROC_CURRENT_VOLTAGE #language en-US "Processor current voltage = (%d/10)V\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_5V_SUPOPRTED #language en-US " 5V is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_33V_SUPPORTED #language en-US " 3.3V is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_29V_SUPPORTED #language en-US " 2.9V is supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT3_NOT_ZERO #language en-US "Error, reserved BIT 3 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO #language en-US "Error, reserved BIT 4 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT5_NOT_ZERO #language en-US "Error, reserved BIT 5 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT6_NOT_ZERO #language en-US "Error, reserved BIT 6 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT7_NOT_ZERO #language en-US "Error, reserved BIT 7 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT10_NOT_ZERO #language en-US "Error, reserved BIT 10 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT11_NOT_ZERO #language en-US "Error, reserved BIT 11 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT12_NOT_ZERO #language en-US "Error, reserved BIT 12 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT13_NOT_ZERO #language en-US "Error, reserved BIT 13 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT14_NOT_ZERO #language en-US "Error, reserved BIT 14 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIT15_NOT_ZERO #language en-US "Error, reserved BIT 15 must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_PROC_STATUS #language en-US "Processor Status:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_POPULATED #language en-US "CPU Socket Populated\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_UNPOPULATED #language en-US "CPU Socket Unpopulated Bits\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CPU_ENABLED #language en-US "CPU Enabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CPU_DISABLED_BY_USER #language en-US "CPU Disabled by User via BIOS Setup\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CPU_DIABLED_BY_BIOS #language en-US "CPU Disabled By BIOS (POST Error)\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CPU_IDLE #language en-US "CPU is Idle, waiting to be enabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_OTHERS #language en-US "Others\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RESERVED #language en-US "Reserved\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SIZE_LARGEST_MEM #language en-US "The size of the largest memory module supported (per slot): " +#string STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_MB #language en-US "%d * %d = %d MB\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MAX_AMOUNT_MEM #language en-US "The maximum amount of memory supported by this controller: " +#string STR_SMBIOSVIEW_PRINTINFO_HANDLES_CONTROLLED #language en-US "There are %d Handles controlled by this controller\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_HANDLES_LIST_CONTROLLED #language en-US "Handles' List controlled by this controller:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_HANDLE #language en-US "Handle%d: 0x%04x\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BANK_CONNECTIONS #language en-US "Bank Connections:" +#string STR_SMBIOSVIEW_PRINTINFO_BANK_RAS #language en-US "Banks %d & %d(RAS# %d & %d)\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BANK_RAS_2 #language en-US "Bank %d(RAS# %d)\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NO_BANKS_CONNECTED #language en-US "No banks connected\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MEMORY_SIZE #language en-US "Memory Size:" +#string STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE_NOT_DETERMINABLE #language en-US " Memory Size Not determinable (Installed Size only)\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MODULE_INSTALLED #language en-US " Module is installed, but no memory has been enabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NOT_INSTALLED #language en-US " Not installed\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE #language en-US " Memory Size: %d MB\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_DOUBLE_BANK #language en-US "The memory module has a Double-bank connection\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_SINGLE_BANK #language en-US "The memory module has a Single-bank connection\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SLOT_ID #language en-US " Slot Id:" +#string STR_SMBIOSVIEW_PRINTINFO_LOGICAL_MICRO_CHAN #language en-US " the logical Micro Channel slot number is:" +#string STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_D #language en-US " %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ERROR_NOT_1_15 #language en-US " error, not 1-15.\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_LOGICAL_EISA_NUM #language en-US " the logical EISA slot number is:" +#string STR_SMBIOSVIEW_PRINTINFO_IDENTIFIES_ADAPTER_NUM #language en-US " Identifies the Adapter Number is: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT #language en-US " the value present in the Slot Number field of the PCI Interrupt Routing table entry that is associated with this slot is: %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_SLOT_ID #language en-US " undefined Slot Id\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_CONFIGURATION #language en-US "Cache Configuration:\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_THROUGH #language en-US "Write Through\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_BACK #language en-US "Write Back\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_VARIES_WITH_MEM_ADDR #language en-US "Varies with Memory Address\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_INTERNAL #language en-US "Internal\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_EXTERNAL #language en-US "External\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_SOCKETED #language en-US "Socketed\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_NOT_SOCKETED #language en-US "Not Socketed\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CACHE_LEVEL #language en-US "Level %d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_BOOT_STATUS #language en-US "System Boot Status: " +#string STR_SMBIOSVIEW_PRINTINFO_NO_ERRORS_DETECTED #language en-US " No errors detected" +#string STR_SMBIOSVIEW_PRINTINFO_NO_BOOTABLE_MEDIA #language en-US " No bootable media" +#string STR_SMBIOSVIEW_PRINTINFO_NORMAL_OP_SYSTEM #language en-US " The \"normal\" unable to load operating system." +#string STR_SMBIOSVIEW_PRINTINFO_FIRMWARE_DETECTED #language en-US " Firmware-detected hardware problem, including \"unknown\" failure types." +#string STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM #language en-US " Operating system-detected hardware failure." +#string STR_SMBIOSVIEW_PRINTINFO_USER_REQUESTED_BOOT #language en-US " User-requested boot, usually via a keystroke" +#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_SECURITY_VIOLATION #language en-US " System security violation" +#string STR_SMBIOSVIEW_PRINTINFO_PREV_REQ_IMAGE #language en-US " Previously-requested image. " +#string STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER #language en-US " A system watchdog timer expired, causing the system to reboot." +#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FUTURE_ASSIGNMENT #language en-US " Reserved for future assignment via this specification. " +#string STR_SMBIOSVIEW_PRINTINFO_VENDOR_OEM_SPECIFIC #language en-US " Vendor/OEM-specific implementations. The Vendor/OEM identifier is the \"Manufacturer\" string found in the System Identification structure." +#string STR_SMBIOSVIEW_PRINTINFO_PRODUCT_SPEC_IMPLMENTATION #language en-US "Product-specific implementations. The product identifier is formed by the concatenation of the \"Manufacturer\" and \"Product Name\" strings found in the System Information structure." +#string STR_SMBIOSVIEW_PRINTINFO_ERROR_VALUE #language en-US "Error value\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SBDS_MANUFACTURE_DATE #language en-US "SBDS Manufacture Date: " +#string STR_SMBIOSVIEW_PRINTINFO_MONTH_DAY_YEAR #language en-US "%02d/%02d/%4d\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_RESET_CAPABILITIES #language en-US "System Reset Capabilities: " +#string STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO #language en-US "Bits 7:6 are reserved bits, must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER_2 #language en-US "System contains a watchdog timer\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_NOT_CONTAIN_TIMER #language en-US "System does not contain a watchdog timer\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION_LIMIT #language en-US "Boot Option on Limit: " +#string STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2 #language en-US "Operating system\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL #language en-US "System utilities\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT_BITS #language en-US "Do not reboot Bits\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION #language en-US "Boot Option :" +#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT #language en-US "Do not reboot\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_HARDWARE_SECURITY_SET #language en-US "Hardware Security Settings: \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_ON_PASSWORD #language en-US "Power-on Password Status: " +#string STR_SMBIOSVIEW_PRINTINFO_DISABLED #language en-US "Disabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE #language en-US "Enabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED #language en-US "Not Implemented\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_PASSWORD #language en-US "Keyboard Password Status: " +#string STR_SMBIOSVIEW_PRINTINFO_ADMIN_PASSWORD_STATUS #language en-US "Administrator Password Status: " +#string STR_SMBIOSVIEW_PRINTINFO_FRONT_PANEL_RESET #language en-US "Front Panel Reset Status: " +#string STR_SMBIOSVIEW_PRINTINFO_CONNECTIONS #language en-US "Connections: " +#string STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO_2 #language en-US "Bits 7:2 are reserved bits, must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_OUTBOUND_CONN_ENABLED #language en-US "Outbound Connection Enabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_OTUBOUND_CONN_DISABLED #language en-US "Outbound Connection Disabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INBOIUND_CONN_ENABLED #language en-US "Inbound Connection Enabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INBOUND_CONN_DISABLED #language en-US "Inbound Connection Disabled\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_CHAR #language en-US "Power Supply Characteristics: \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BITS_15_14_RSVD #language en-US "Bits 15:14 are reserved bits, must be zero\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TYPE #language en-US "Type - " +#string STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE #language en-US " Other\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_LINEAR #language en-US " Linear\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_SWITCHING #language en-US " Switching\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BATTERY #language en-US " Battery\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UPS #language en-US " UPS\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CONVERTER #language en-US " Converter\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_REGULATOR #language en-US " Regulator\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_2 #language en-US " Reserved \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_STATUS_DASH #language en-US " Status - " +#string STR_SMBIOSVIEW_PRINTINFO_OK #language en-US " OK\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NON_CRITICAL #language en-US " Non-critical\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_CRITICAL_POWER_SUPPLY #language en-US " Critical, power supply has failed and has been taken off-line\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_UNDEFINED #language en-US " Undefined \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_INPUT_VOLTAGE_RANGE #language en-US "Input Voltage Range Switching - " +#string STR_SMBIOSVIEW_PRINTINFO_MANUAL #language en-US " Manual\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_AUTO_SWITCH #language en-US " Auto-switch\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_WIDE_RANGE #language en-US " Wide range\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_NOT_APPLICABLE #language en-US " Not applicable\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_3 #language en-US " Reserved \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_UNPLUGGED #language en-US "Power supply is unplugged from the wall\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PLUGGED #language en-US "Power supply is plugged from the wall\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PRESENT #language en-US "Power supply is present\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_PRESENT #language en-US "Power supply is not present\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_REPLACE #language en-US "Power supply is hot replaceable\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_REPLACE #language en-US "Power supply is not hot replaceable\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BIOS_SIZE #language en-US "BiosSize: %d KB\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_EXTENDED_BIOS_SIZE #language en-US "ExtendedBiosSize: %d %s\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_NO_INFO #language en-US "No Info" +#string STR_SMBIOSVIEW_QUERYTABLE_RSVD_BITS_SET #language en-US "\r\nIt also has reserved bits set 1 --- reserved bits: 0x%x" +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_WAKEUP_TYPE #language en-US "System Wakeup Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_FEATURE_FLAGS #language en-US "Base Board Feature Flags:" +#string STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_BOARD_TYPE #language en-US "Base Board Board Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_TYPE #language en-US "System Enclosure or Chassis Types:" +#string STR_SMBIOSVIEW_QUERYTABLE_CHASSIS_LOCK_PRESENT #language en-US "Chassis Lock present\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_STATUS #language en-US "System Enclosure or Chassis Status: " +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_SECURITY #language en-US "System Enclosure or Chassis Security Status: " +#string STR_SMBIOSVIEW_QUERYTABLE_PROC_TYPE #language en-US "Processor Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_PROC_UPDATE #language en-US "Processor Upgrade: " +#string STR_SMBIOSVIEW_QUERYTABLE_PROC_CHARACTERISTICS #language en-US "Processor Characteristics: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DETECTMETHOD #language en-US "Memory Controller Error DetectMethod:" +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_CORRECT_CAPABILITY #language en-US "Memory Controller Error Correct Capability:\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_INTERLEAVE_SUPPORT #language en-US "Memory Controller Interleave Support:" +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_MEMORY_SPEED #language en-US "Memory Controller Memory Speed:" +#string STR_SMBIOSVIEW_QUERYTABLE_REQUIRED_VOLTAGES #language en-US "The required voltages for each memory module sockets:\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_TYPE #language en-US "Memory Module Memory Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_ERROR_STATUS #language en-US "Memory Module Error Status: " +#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_SRAM_TYPE #language en-US "Cache SRAM Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_ERROR_CORRECTING #language en-US "Cache Error Correcting Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_SYSTEM_TYPE #language en-US "Cache System Cache Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_ASSOCIATIVITY #language en-US "Cache Associativity:" +#string STR_SMBIOSVIEW_QUERYTABLE_PORT_CONNECTOR_TYPE #language en-US "Port Connector Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_PORT_TYPE #language en-US "Port Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_TYPE #language en-US "System Slot Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_DATA #language en-US "System Slot Data Bus Width: " +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_CURRENT_USAGE #language en-US "System Slot Current Usage: " +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_LENGTH #language en-US "System Slot Length: " +#string STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS #language en-US "Slot characteristics 1: " +#string STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS_2 #language en-US "Slot characteristics 2: " +#string STR_SMBIOSVIEW_QUERYTABLE_ONBOARD_DEVICE_TYPE #language en-US "Onboard Device Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_EVENT_LOG_TYPE #language en-US "System Event Log Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_EVENT_LOG_VAR_DATA_FORMAT #language en-US "Event Log Variable Data Format Types: " +#string STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_BITMAP #language en-US "POST Results Bitmap - First DWORD:\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_SECOND_DWORD #language en-US "POST Results Bitmap - Second DWORD:\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_TYPES #language en-US "System Management Types: " +#string STR_SMBIOSVIEW_QUERYTABLE_OEM_ASSIGNED #language en-US "OEM assigned\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_RSVD_FOR_FUTURE_ASSIGN #language en-US "Reserved for future assignment via this specification\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_PROBE #language en-US "A system-management probe or cooling device is out-of-range\r\n" +#string STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_LOCATION #language en-US "Physical Memory Array Location: " +#string STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_USE #language en-US "Physical Memory Array Use: " +#string STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_ERROR #language en-US "Physical Memory Array Error Correction Types: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_FORM_FACTOR #language en-US "Memory Device - Form Factor: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE #language en-US "Memory Device - Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE_DETAIL #language en-US "Memory Device - Type Detail: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_MEMORY_TECHNOLOGY #language en-US "Memory Device - Memory Technology: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_MEM_OPER_MODE_CAPA #language en-US "Memory Device - Memory Operating Mode Capability: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_INFO #language en-US "32-bit Memory Error Information - Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_GRANULARITY #language en-US "Memory Error - Error granularity: " +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_OP #language en-US "Memory Error - Error Operation: " +#string STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_TYPE #language en-US "Pointing Device - Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_INTERFACE #language en-US "Pointing Device - Interface:" +#string STR_SMBIOSVIEW_QUERYTABLE_PORTABLE_BATT_DEV_CHEM #language en-US "Portable Battery - Device Chemistry:" +#string STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_LOC #language en-US "Voltage Probe - Location:" +#string STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_STATUS #language en-US "Voltage Probe - Status:" +#string STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_STATUS #language en-US "Cooling Device - Status: " +#string STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_TYPE #language en-US "Cooling Device - Type: " +#string STR_SMBIOSVIEW_QUERYTABLE_TEMP_PROBE #language en-US "Temperature Probe - Status:" +#string STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_STATUS #language en-US "Electrical Current Probe - Status:" +#string STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_LOC #language en-US "Electrical Current Probe - Location:" +#string STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_TYPE #language en-US "Management Device Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_ADDR_TYPE #language en-US "Management Device - Address Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_MEM_CHANNEL_TYPE #language en-US "Memory Channel Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_BMC_INTERFACE_TYPE #language en-US "BMC Interface Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_MC_HOST_INTERFACE_TYPE #language en-US "MC Host Interface Type:" +#string STR_SMBIOSVIEW_QUERYTABLE_STRUCT_TYPE #language en-US "Structure Type:" +#string STR_SMBIOSVIEW_SMBIOSVIEW_ONE_VAR_ARGV #language en-US "%s " +#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERY_STRUCT_COND #language en-US "Query Structure, conditions are:\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE_RANDOM #language en-US "QueryType = Random \r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE #language en-US "QueryType = %d\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE_RANDOM #language en-US "QueryHandle = Random\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE #language en-US "QueryHandle = 0x%x\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOWTYPE #language en-US "ShowType = " +#string STR_SMBIOSVIEW_SMBIOSVIEW_TYPE_HANDLE_DUMP_STRUCT #language en-US "Type=%d, Handle=0x%x\r\nDump Structure as:\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_INDEX_LENGTH #language en-US "Index=%d,Length=0x%x," +#string STR_SMBIOSVIEW_SMBIOSVIEW_ADDR #language en-US "Addr=0x%p\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_ENTRYLEN #language en-US "Entry Length: 0x%x\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDHANDLE #language en-US "Referenced Handle: 0x%x\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDOFFSET #language en-US "Referenced Offset: 0x%x\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_Q #language en-US "\r\n%HEnter%N to continue, %H:q%N to exit, %H:[0-3]%N to change mode, %H/?%N for help\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_UTILITY #language en-US " SMBIOS Utility ---- smbiosview HELP Information\r\n\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_USAGE #language en-US "Usage:\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_HSMBIOSVIEW #language en-US "%Hsmbiosview [-t type] | [-h handle] | [-s] | [-a]%N\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_EXAMPLES #language en-US "Examples:\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_STAT_INFO #language en-US "%H>smbiosview -s %N - Show statistics information\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_ALL_STRUCT_TYPE #language en-US "%H>smbiosview -t 8 %N - Show all structures of type=8\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_STRUCT_HANDLE #language en-US "%H>smbiosview -h 25 %N - Show structure of handle=0x25\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_ALL_OUTPUT_TO_FILE #language en-US "%H>smbiosview -a > 1.log%N - Show all and output to file 1.log\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_INTERNAL_COMMANDS #language en-US "Internal commands:\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_QUIT_SMBIOSVIEW #language en-US "%H:q%N -------- quit smbiosview\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_NONE #language en-US "%H:0%N -------- Change smbiosview display NONE info\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_OUTLINE #language en-US "%H:1%N -------- Change smbiosview display OUTLINE info\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_NORMAL #language en-US "%H:2%N -------- Change smbiosview display NORMAL info\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_DETAIL #language en-US "%H:3%N -------- Change smbiosview display DETAIL info\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_HELP #language en-US "%H/?%N -------- Show help\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_INDEX #language en-US "Index=%04d " +#string STR_SMBIOSVIEW_SMBIOSVIEW_TYPE #language en-US "Type=%03d " +#string STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE #language en-US "Handle=0x%04x " +#string STR_SMBIOSVIEW_SMBIOSVIEW_OFFSET #language en-US "Offset=0x%04x " +#string STR_SMBIOSVIEW_SMBIOSVIEW_LENGTH #language en-US "Length=0x%04x" +#string STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_CONTINUE #language en-US "Press Enter to continue..\r\n" +#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUF_SPEC_WHEN_STRUCT #language en-US "smbiosview: No buffer specified when get structure\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_NOT_SPEC #language en-US "SmbiosView: Type # not specified\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE_NOT_SPEC #language en-US "SmbiosView: Handle # not specified\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_UNKNOWN_FLAG #language en-US "\r\nSmbiosView: Unknown flag\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE #language en-US "SmbiosView: Cannot access SMBIOS table\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_UNKNOWN_INTERNAL_COMMAND #language en-US "\r\nSmbiosView: Unknown internal command\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_TABLE #language en-US "SmbiosView: SMBIOS table damaged\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_OUT_OF_MEM #language en-US "SmbiosView: Out of memory\r\n" +#string STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_STATS #language en-US "SmbiosView: Cannot access statistics table\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CHAR #language en-US "TPM Device Characteristics: \r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CHAR_NOT_SUPPORTED #language en-US "TPM Device Characteristics Not Supported\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CONFIG_FWU #language en-US "Family configurable via firmware update\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CONFIG_PLAT_SW #language en-US "Family configurable via platform software support\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_TPM_DEVICE_CONFIG_OEM #language en-US "Family configurable via OEM proprietary mechanism\r\n" +#string STR_SMBIOSVIEW_PRINTINFO_BITS_06_63 #language en-US "Bits 6:63 are reserved\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c new file mode 100644 index 0000000..19a4a72 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c @@ -0,0 +1,427 @@ +/** @file + Main file for NULL named library for debug1 profile shell command functions. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDebug1CommandsLib.h" +#include + +STATIC CONST CHAR16 mFileName[] = L"Debug1Commands"; +EFI_HANDLE gShellDebug1HiiHandle = NULL; + +/** + Gets the debug file name. This will be used if HII is not working. + + @retval NULL No file is available. + @return The NULL-terminated filename to get help from. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameDebug1 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Debug1 Commands library. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +UefiShellDebug1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // check our bit of the profiles mask + // + if ((PcdGet8(PcdShellProfileMask) & BIT1) == 0) { + return (EFI_SUCCESS); + } + + // + // install the HII stuff. + // + gShellDebug1HiiHandle = HiiAddPackages (&gShellDebug1HiiGuid, gImageHandle, UefiShellDebug1CommandsLibStrings, NULL); + if (gShellDebug1HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"setsize", ShellCommandRunSetSize , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETSIZE) ); + ShellCommandRegisterCommandName(L"comp", ShellCommandRunComp , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_COMP) ); + ShellCommandRegisterCommandName(L"mode", ShellCommandRunMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MODE) ); + ShellCommandRegisterCommandName(L"memmap", ShellCommandRunMemMap , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MEMMAP) ); + ShellCommandRegisterCommandName(L"eficompress", ShellCommandRunEfiCompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFICOMPRESS) ); + ShellCommandRegisterCommandName(L"efidecompress", ShellCommandRunEfiDecompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFIDCOMPRESS) ); + ShellCommandRegisterCommandName(L"dmem", ShellCommandRunDmem , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMEM) ); + ShellCommandRegisterCommandName(L"loadpcirom", ShellCommandRunLoadPciRom , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD_PCI_ROM) ); + ShellCommandRegisterCommandName(L"mm", ShellCommandRunMm , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MM) ); + ShellCommandRegisterCommandName(L"setvar", ShellCommandRunSetVar , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETVAR) ); + ShellCommandRegisterCommandName(L"sermode", ShellCommandRunSerMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SERMODE) ); + ShellCommandRegisterCommandName(L"pci", ShellCommandRunPci , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_PCI) ); + ShellCommandRegisterCommandName(L"smbiosview", ShellCommandRunSmbiosView , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SMBIOSVIEW) ); + ShellCommandRegisterCommandName(L"dmpstore", ShellCommandRunDmpStore , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMPSTORE) ); + ShellCommandRegisterCommandName(L"dblk", ShellCommandRunDblk , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DBLK) ); + ShellCommandRegisterCommandName(L"edit", ShellCommandRunEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EDIT) ); + ShellCommandRegisterCommandName(L"hexedit", ShellCommandRunHexEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_HEXEDIT) ); + + ShellCommandRegisterAlias(L"dmem", L"mem"); + + BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Debug1"); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +UefiShellDebug1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellDebug1HiiHandle != NULL) { + HiiRemovePackages(gShellDebug1HiiHandle); + } + + BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable); + return (EFI_SUCCESS); +} + + +/** + Function returns a system configuration table that is stored in the + EFI System Table based on the provided GUID. + + @param[in] TableGuid A pointer to the table's GUID type. + @param[in, out] Table On exit, a pointer to a system configuration table. + + @retval EFI_SUCCESS A configuration table matching TableGuid was found. + @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found. +**/ +EFI_STATUS +GetSystemConfigurationTable ( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ) +{ + UINTN Index; + ASSERT (Table != NULL); + + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) { + *Table = gST->ConfigurationTable[Index].VendorTable; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Clear the line at the specified Row. + + @param[in] Row The row number to be cleared ( start from 1 ) + @param[in] LastCol The last printable column. + @param[in] LastRow The last printable row. +**/ +VOID +EditorClearLine ( + IN UINTN Row, + IN UINTN LastCol, + IN UINTN LastRow + ) +{ + UINTN Col; + CHAR16 Line[200]; + + if (Row == 0) { + Row = 1; + } + + // + // prepare a blank line + // If max column is larger, split to multiple prints. + // + SetMem16 (Line, sizeof (Line), L' '); + Line[ARRAY_SIZE (Line) - 1] = CHAR_NULL; + + for (Col = 1; Col <= LastCol; Col += ARRAY_SIZE (Line) - 1) { + if (Col + ARRAY_SIZE (Line) - 1 > LastCol) { + if (Row == LastRow) { + // + // if CHAR_NULL is still at position LastCol, it will cause first line error + // + Line[(LastCol - 1) % (ARRAY_SIZE (Line) - 1)] = CHAR_NULL; + } else { + Line[LastCol % (ARRAY_SIZE (Line) - 1)] = CHAR_NULL; + } + } + + // + // print out the blank line + // + ShellPrintEx ((INT32) Col - 1, (INT32) Row - 1, Line); + } +} + +/** + Determine if the character is valid for a filename. + + @param[in] Ch The character to test. + + @retval TRUE The character is valid. + @retval FALSE The character is not valid. +**/ +BOOLEAN +IsValidFileNameChar ( + IN CONST CHAR16 Ch + ) +{ + // + // See if there are any illegal characters within the name + // + if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|') { + return FALSE; + } + + return TRUE; +} + +/** + Check if file name has illegal characters. + + @param Name The filename to check. + + @retval TRUE The filename is ok. + @retval FALSE The filename is not ok. +**/ +BOOLEAN +IsValidFileName ( + IN CONST CHAR16 *Name + ) +{ + + UINTN Index; + UINTN Len; + + // + // check the length of Name + // + for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) { + if (Name[Index] == '\\' || Name[Index] == ':') { + break; + } + } + + if (Len == 0 || Len > 255) { + return FALSE; + } + // + // check whether any char in Name not appears in valid file name char + // + for (Index = 0; Index < StrLen (Name); Index++) { + if (!IsValidFileNameChar (Name[Index])) { + return FALSE; + } + } + + return TRUE; +} + +/** + Find a filename that is valid (not taken) with the given extension. + + @param[in] Extension The file extension. + + @retval NULL Something went wrong. + @return the valid filename. +**/ +CHAR16 * +EditGetDefaultFileName ( + IN CONST CHAR16 *Extension + ) +{ + EFI_STATUS Status; + UINTN Suffix; + CHAR16 *FileNameTmp; + + Suffix = 0; + + do { + FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension); + + // + // after that filename changed to path + // + Status = ShellFileExists (FileNameTmp); + + if (Status == EFI_NOT_FOUND) { + return FileNameTmp; + } + + FreePool (FileNameTmp); + FileNameTmp = NULL; + Suffix++; + } while (Suffix != 0); + + FreePool (FileNameTmp); + return NULL; +} + +/** + Read a file into an allocated buffer. The buffer is the responsibility + of the caller to free. + + @param[in] FileName The filename of the file to open. + @param[out] Buffer Upon successful return, the pointer to the + address of the allocated buffer. + @param[out] BufferSize If not NULL, then the pointer to the size + of the allocated buffer. + @param[out] ReadOnly Upon successful return TRUE if the file is + read only. FALSE otherwise. + + @retval EFI_NOT_FOUND The filename did not represent a file in the + file system. + @retval EFI_SUCCESS The file was read into the buffer. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR The file read operation failed. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_INVALID_PARAMETER FileName was NULL. + @retval EFI_INVALID_PARAMETER FileName was a directory. +**/ +EFI_STATUS +ReadFileIntoBuffer ( + IN CONST CHAR16 *FileName, + OUT VOID **Buffer, + OUT UINTN *BufferSize OPTIONAL, + OUT BOOLEAN *ReadOnly + ) +{ + VOID *InternalBuffer; + UINTN FileSize; + SHELL_FILE_HANDLE FileHandle; + BOOLEAN CreateFile; + EFI_STATUS Status; + EFI_FILE_INFO *Info; + + InternalBuffer = NULL; + FileSize = 0; + FileHandle = NULL; + CreateFile = FALSE; + Status = EFI_SUCCESS; + Info = NULL; + + if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // try to open the file + // + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + + if (!EFI_ERROR(Status)) { + ASSERT(CreateFile == FALSE); + if (FileHandle == NULL) { + return EFI_LOAD_ERROR; + } + + Info = ShellGetFileInfo(FileHandle); + + if (Info->Attribute & EFI_FILE_DIRECTORY) { + FreePool (Info); + return EFI_INVALID_PARAMETER; + } + + if (Info->Attribute & EFI_FILE_READ_ONLY) { + *ReadOnly = TRUE; + } else { + *ReadOnly = FALSE; + } + // + // get file size + // + FileSize = (UINTN) Info->FileSize; + + FreePool (Info); + } else if (Status == EFI_NOT_FOUND) { + // + // file not exists. add create and try again + // + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR (Status)) { + return Status; + } else { + // + // it worked. now delete it and move on with the name (now validated) + // + Status = ShellDeleteFile (&FileHandle); + if (Status == EFI_WARN_DELETE_FAILURE) { + Status = EFI_ACCESS_DENIED; + } + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // file doesn't exist, so set CreateFile to TRUE and can't be read-only + // + CreateFile = TRUE; + *ReadOnly = FALSE; + } + + // + // the file exists + // + if (!CreateFile) { + // + // allocate buffer to read file + // + InternalBuffer = AllocateZeroPool (FileSize); + if (InternalBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // read file into InternalBuffer + // + Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer); + ShellCloseFile(&FileHandle); + FileHandle = NULL; + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL (InternalBuffer); + return EFI_LOAD_ERROR; + } + } + *Buffer = InternalBuffer; + if (BufferSize != NULL) { + *BufferSize = FileSize; + } + return (EFI_SUCCESS); + +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h new file mode 100644 index 0000000..35e4405 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h @@ -0,0 +1,383 @@ +/** @file + Main file for NULL named library for Profile1 shell command functions. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_DEBUG1_COMMANDS_LIB_H_ +#define _UEFI_SHELL_DEBUG1_COMMANDS_LIB_H_ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern EFI_HANDLE gShellDebug1HiiHandle; + +/** + Function returns a system configuration table that is stored in the + EFI System Table based on the provided GUID. + + @param[in] TableGuid A pointer to the table's GUID type. + @param[in, out] Table On exit, a pointer to a system configuration table. + + @retval EFI_SUCCESS A configuration table matching TableGuid was found. + @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found. +**/ +EFI_STATUS +GetSystemConfigurationTable ( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ); + +/** + Function for 'setsize' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSetSize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'comp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunComp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'mode' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'memmap' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMemMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'compress' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEfiCompress ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'decompress' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEfiDecompress ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'dmem' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDmem ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'loadpcirom' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLoadPciRom ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'mm' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'setvar' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSetVar ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'sermode' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSerMode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'bcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunBcfg ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'pci' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPci ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'smbiosview' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSmbiosView ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'dmpstore' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDmpStore ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'dblk' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDblk ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'edit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEdit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'hexedit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunHexEdit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Clear the line at the specified Row. + + @param[in] Row The row number to be cleared ( start from 1 ) + @param[in] LastCol The last printable column. + @param[in] LastRow The last printable row. +**/ +VOID +EditorClearLine ( + IN UINTN Row, + IN UINTN LastCol, + IN UINTN LastRow + ); + +/** + Check if file name has illegal characters. + + @param Name The filename to check. + + @retval TRUE The filename is ok. + @retval FALSE The filename is not ok. +**/ +BOOLEAN +IsValidFileName ( + IN CONST CHAR16 *Name + ); + +/** + Find a filename that is valid (not taken) with the given extension. + + @param[in] Extension The file extension. + + @retval NULL Something went wrong. + @return the valid filename. +**/ +CHAR16 * +EditGetDefaultFileName ( + IN CONST CHAR16 *Extension + ); + +/** + Read a file into an allocated buffer. The buffer is the responsibility + of the caller to free. + + @param[in] FileName The filename of the file to open. + @param[out] Buffer Upon successful return, the pointer to the + address of the allocated buffer. + @param[out] BufferSize If not NULL, then the pointer to the size + of the allocated buffer. + @param[out] ReadOnly Upon successful return TRUE if the file is + read only. FALSE otherwise. + + @retval EFI_NOT_FOUND The filename did not represent a file in the + file system. Directories cannot be read with + this method. + @retval EFI_SUCCESS The file was read into the buffer. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_LOAD_ERROR The file read operation failed. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_INVALID_PARAMETER FileName was NULL. + @retval EFI_INVALID_PARAMETER FileName was a directory. +**/ +EFI_STATUS +ReadFileIntoBuffer ( + IN CONST CHAR16 *FileName, + OUT VOID **Buffer, + OUT UINTN *BufferSize OPTIONAL, + OUT BOOLEAN *ReadOnly + ); + +#endif diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf new file mode 100644 index 0000000..bfaba9a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf @@ -0,0 +1,137 @@ +## @file +# Provides shell Debug1 profile functions +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellDebug1CommandsLib + FILE_GUID = 90330D51-A99B-4cc8-A2EB-AE22542A3F45 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.2 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = UefiShellDebug1CommandsLibConstructor + DESTRUCTOR = UefiShellDebug1CommandsLibDestructor + +[Sources] + SetSize.c + Comp.c + Mode.c + MemMap.c + Compress.h + Compress.c + EfiCompress.c + EfiDecompress.c + Dmem.c + LoadPciRom.c + Mm.c + SetVar.c + SerMode.c + Pci.c + Pci.h + DmpStore.c + Dblk.c + SmbiosView/EventLogInfo.c + SmbiosView/EventLogInfo.h + SmbiosView/PrintInfo.c + SmbiosView/QueryTable.c + SmbiosView/SmbiosView.c + SmbiosView/SmbiosViewStrings.uni + SmbiosView/LibSmbiosView.c + SmbiosView/PrintInfo.h + SmbiosView/LibSmbiosView.h + SmbiosView/QueryTable.h + SmbiosView/SmbiosView.h + UefiShellDebug1CommandsLib.c + UefiShellDebug1CommandsLib.h + UefiShellDebug1CommandsLib.uni + +## Files shared by both editors + EditTitleBar.h + EditTitleBar.c + EditInputBar.h + EditInputBar.c + EditStatusBar.h + EditStatusBar.c + EditMenuBar.h + EditMenuBar.c + +## Files specific to the text editor + Edit/Edit.c + Edit/TextEditor.h + Edit/TextEditorTypes.h + Edit/FileBuffer.h + Edit/FileBuffer.c + Edit/MainTextEditor.h + Edit/MainTextEditor.c + Edit/Misc.h + Edit/Misc.c + Edit/TextEditStrings.uni + +## Files specific to the HEX editor + HexEdit/BufferImage.h + HexEdit/BufferImage.c + HexEdit/Clipboard.h + HexEdit/Clipboard.c + HexEdit/DiskImage.h + HexEdit/DiskImage.c + HexEdit/FileImage.h + HexEdit/FileImage.c + HexEdit/HexEdit.c + HexEdit/HexEditor.h + HexEdit/HexEditorTypes.h + HexEdit/HexeditStrings.uni + HexEdit/MainHexEditor.h + HexEdit/MainHexEditor.c + HexEdit/MemImage.h + HexEdit/MemImage.c + HexEdit/Misc.h + HexEdit/Misc.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + IoLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + BcfgCommandLib + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimplePointerProtocolGuid ## SOMETIMES_CONSUMES + gEfiCpuIo2ProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## GUID + gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiMpsTableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiSalSystemTableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gShellDebug1HiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni new file mode 100644 index 0000000..1c135bc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni @@ -0,0 +1,1178 @@ +// /** +// +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellDebug1CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 Debug1 profile commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n" +#string STR_GEN_BOOT_ONLY #language en-US "%H%s%N: Boot must be selected for hot key options.\r\n" +#string STR_GEN_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" + +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n" +#string STR_GEN_DUPLICATE #language en-US "%H%s%N: Duplicate flag - '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n" +#string STR_GEN_NO_DRIVER_BOOT #language en-US "%H%s%N: Driver or Boot must be selected.\r\n" +#string STR_GEN_PCIRBIO_NF #language en-US "%H%s%N: Protocol - PciRootBridgeIo not found.\r\n" +#string STR_GEN_PCIRBIO_ER #language en-US "%H%s%N: Problem accessing the data using Protocol - PciRootBridgeIo\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_PARAM_INV_HEX #language en-US "%H%s%N: Invalid parameter - '%H%s%N'. Must be hexadecimal.\r\n" +#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n" +#string STR_GEN_MAP_PROTOCOL #language en-US "%H%s%N: Mapped device '%B%s%N' does not have protocol %B%s%N\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_FILE_DELETE_FAIL #language en-US "%H%s%N: Cannot delete file - '%H%s%N'\r\n" +#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified.\r\n" +#string STR_GEN_FILE_IS_DIRECTORY #language en-US "%H%s%N: The file '%H%s%N' is a directory.\r\n" +#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n" + + +#string STR_FILE_OPEN_FAIL #language en-US "Unable to open file on '%B%s%N' with: %r.\r\n" +#string STR_FILE_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_FILE_NOT_DIR #language en-US "%H%s%N: Directories are not permitted - '%H%s%N'\r\n" +#string STR_SIZE_NOT_SPEC #language en-US "%H%s%N: A valid size must be specified\r\n" +#string STR_FILE_NOT_SPEC #language en-US "%H%s%N: File not specified\r\n" +#string STR_FILE_WRITE_FAIL #language en-US "%H%s%N: Write file error - '%H%s%N'\r\n" +#string STR_FILE_READ_FAIL #language en-US "%H%s%N: Read file error - '%H%s%N'\r\n" +#string STR_VOLUME_FULL #language en-US "%H%s%N: The volume is full\r\n" + +#string STR_SET_SIZE_FAIL #language en-US "%H%s%N: Unable to change size on '%B%s%N'\r\n" +#string STR_SET_SIZE_DONE #language en-US "Size changed on '%B%s%N'.\r\n" + +#string STR_DBLK_HEADER #language en-US "LBA %016LX Size %08x bytes BlkIo %0x\r\n" + +#string STR_COMP_HEADER #language en-US "Compare %s to %s.\r\n" +#string STR_COMP_DIFFERENCE_POINT #language en-US "Difference #% 2u:\r\n" +#string STR_COMP_END_OF_FILE #language en-US " " + +#string STR_COMP_FOOTER_FAIL #language en-US "[difference(s) encountered] \r\n" +#string STR_COMP_FOOTER_PASS #language en-US "[no differences encountered]\r\n" + +#string STR_MODE_SET_FAIL #language en-US "%H%s%N: Unable to change the mode.\r\n" +#string STR_MODE_NO_MATCH #language en-US "%H%s%N: No matching mode found to set\r\n" +#string STR_MODE_LIST_HEAD #language en-US "Available modes for console output device.\r\n" +#string STR_MODE_LIST_ITEM #language en-US " Col % 5d Row % 5d %c\r\n" + +#string STR_MEMMAP_GET_FAILED #language en-US "%H%s%N: Unable to get memory map\r\n" +#string STR_MEMMAP_LIST_HEAD #language en-US "Type Start End # Pages Attributes\r\n" +#string STR_MEMMAP_LIST_ITEM #language en-US "% -10s %016LX-%016LX %016LX %016LX\r\n" +#string STR_MEMMAP_LIST_ITEM_OTHER #language en-US "%08x %016LX-%016LX %016LX %016LX\r\n" +#string STR_MEMMAP_LIST_SUMM #language en-US " \r\n" + " Reserved : %,14ld Pages (%,ld Bytes)\r\n" + " LoaderCode: %,14ld Pages (%,ld Bytes)\r\n" + " LoaderData: %,14ld Pages (%,ld Bytes)\r\n" + " BS_Code : %,14ld Pages (%,ld Bytes)\r\n" + " BS_Data : %,14ld Pages (%,ld Bytes)\r\n" + " RT_Code : %,14ld Pages (%,ld Bytes)\r\n" + " RT_Data : %,14ld Pages (%,ld Bytes)\r\n" + " ACPI_Recl : %,14ld Pages (%,ld Bytes)\r\n" + " ACPI_NVS : %,14ld Pages (%,ld Bytes)\r\n" + " MMIO : %,14ld Pages (%,ld Bytes)\r\n" + " MMIO_Port : %,14ld Pages (%,ld Bytes)\r\n" + " PalCode : %,14ld Pages (%,ld Bytes)\r\n" + " Available : %,14ld Pages (%,ld Bytes)\r\n" + " Persistent: %,14ld Pages (%,ld Bytes)\r\n" +#string STR_MEMMAP_LIST_SUMM_OTHER #language en-US " %08x : %,14ld Pages (%,ld Bytes)\r\n" +#string STR_MEMMAP_LIST_SUMM2 #language en-US " -------------- \r\n" + "Total Memory: %,14ld MB (%,ld Bytes)\r\n" +#string STR_MEMMAP_LIST_ITEM_SFO #language en-US "MemoryMap,"%s","%LX","%LX","%LX","%LX"\r\n" +#string STR_MEMMAP_LIST_SUMM_SFO #language en-US "MemoryMapSummary,"%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld"\r\n" + +#string STR_EFI_COMPRESS_FAIL #language en-US "Unable to compress: %r.\r\n" +#string STR_EFI_DECOMPRESS_FAIL #language en-US "Unable to decompress: %r.\r\n" +#string STR_EFI_DECOMPRESS_NOPE #language en-US "The file does not appear to be a compressed file. Cannot continue. \"%H%s%N\"\r\n" + +#string STR_DMEM_HEADER_ROW #language en-US "Memory Address %016LX %X Bytes\r\n" +#string STR_DMEM_MMIO_HEADER_ROW #language en-US "Memory Mapped IO Address %016LX %X Bytes\r\n" +#string STR_DMEM_DATA_ROW #language en-US "%08X: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x *%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c*\r\n" +#string STR_DMEM_SYSTEM_TABLE #language en-US "\r\nValid EFI Header at Address %016Lx\r\n" + "---------------------------------------------\r\n" + "System: Table Structure size %08x revision %08x\r\n" + "ConIn (%016LX) ConOut (%016LX) StdErr (%016LX)\r\n" + "Runtime Services %016LX\r\n" + "Boot Services %016LX\r\n" + "SAL System Table %016LX\r\n" + "ACPI Table %016LX\r\n" + "ACPI 2.0 Table %016LX\r\n" + "MPS Table %016LX\r\n" + "SMBIOS Table %016LX\r\n" + +#string STR_LOAD_PCI_ROM_RES #language en-US "Image '%B%s%N' load result: %r\r\n" +#string STR_LOADPCIROM_CORRUPT #language en-US "%H%s%N: File '%B%s%N' Image %d is corrupt.\r\n" +#string STR_LOADPCIROM_LOAD_FAIL #language en-US "%H%s%N: File '%B%s%N' Image %d unable to load.\r\n" +#string STR_LOADPCIROM_START_FAIL #language en-US "%H%s%N: File '%B%s%N' Image %d unable to start.\r\n" + +#string STR_MM_NOT_ALIGNED #language en-US "%H%s%N: Address parameter %016LX is not aligned.\r\n" +#string STR_MM_PCIE_ADDRESS_RANGE #language en-US "%H%s%N: Address parameter %016LX is not a valid PCI/PCIE address.\r\n" +#string STR_MM_MMIO #language en-US "%HMMIO%N" +#string STR_MM_IO #language en-US "%HIO%N" +#string STR_MM_PCI #language en-US "%HPCI%N" +#string STR_MM_MEM #language en-US "%HMEM%N" +#string STR_MM_PCIE #language en-US "%HPCIE%N" +#string STR_MM_ADDRESS #language en-US " 0x%016lx : " +#string STR_MM_BUF #language en-US "0x%0*lx" +#string STR_MM_ERROR #language en-US "%H%s%N: Input had incorrect format\r\n" + +#string STR_SETVAR_PRINT #language en-US "%g - %s - %04x Bytes\r\n" +#string STR_SETVAR_ERROR_SET #language en-US "%H%s%N: Unable to set - %H%g%N - %H%s%N\r\n" +#string STR_SETVAR_ERROR_GET #language en-US "%H%s%N: Unable to get - %H%g%N - %H%s%N\r\n" +#string STR_SETVAR_ERROR_DPFT #language en-US "%H%s%N: DevicePathFromText conversion was not successful.\r\n" + +#string STR_SERMODE_NO_FOUND #language en-US "%H%s%N: No serial ports found.\r\n" +#string STR_SERMODE_NOT_FOUND #language en-US "%H%s%N: No serial port or specified serial port found.\r\n" +#string STR_SERMODE_BAD_HANDLE #language en-US "%H%s%N: Handle %H%02x%N is not a serial device handle.\r\n" +#string STR_SERMODE_SET_HANDLE #language en-US "Mode set on handle %H%02x%N successfully.\r\n" +#string STR_SERMODE_SET_FAIL #language en-US "%H%s%N: Mode change on handle %H%02x%N was not successful.\r\n" +#string STR_SERMODE_DISPLAY #language en-US "%x(%08x) - (%ld, %c, %d, %s)\r\n" +#string STR_SERMODE_SET_UNSUPPORTED #language en-US "%H%s%N: One or more of the new settings is not supported on handle %H%02x%N.\r\n" +#string STR_SERMODE_SET_DEV_ERROR #language en-US "%H%s%N: The serial device on handle %H%02x%N is not functioning correctly.\r\n" + +#string STR_PCI_HANDLE_CFG_ERR #language en-US "%H%s%N: Handle protocol or configuration error.\r\n" +#string STR_PCI_BUS_RANGE_ERR #language en-US "%H%s%N: Get next bus range error.\r\n" +#string STR_PCI_NO_FIND #language en-US "%H%s%N: Cannot find protocol interface for segment %x, bus %x.\r\n" +#string STR_PCI_NO_CFG #language en-US "%H%s%N: Cannot read configuration data.\r\n" +#string STR_PCI_INFO #language en-US "%H PCI Segment %02x Bus %02x Device %02x Func %02x%N [EFI %02x%02x%02x%02x00]\r\n" +#string STR_PCI_TITLE #language en-US " Seg Bus Dev Func\r\n" + " --- --- --- ----\r\n" +#string STR_PCI_LINE_P1 #language en-US " %E%02x %02x %02x %02x ==> %N" +#string STR_PCI_LINE_P2 #language en-US "\r\n Vendor %04x Device %04x Prog Interface %x\r\n" +#string STR_PCIEX_CAPABILITY_CAPID #language en-US "CapID(%2x): %E%02x%N" +#string STR_PCIEX_NEXTCAP_PTR #language en-US " NextCap Ptr(%2x): %E%02x%N\r\n" +#string STR_PCIEX_CAP_REGISTER #language en-US "Cap Register(%2x): %E%04x%N\r\n" +#string STR_PCIEX_DEVICE_CAP #language en-US "Device Capabilities(%2x): %E%08x%N\r\n" +#string STR_PCIEX_DEVICE_CONTROL #language en-US "Device Control(%2x): %E%04x%N\r\n" +#string STR_PCIEX_DEVICE_STATUS #language en-US "Device Status(%2x): %E%04x%N\r\n" +#string STR_PCIEX_LINK_CAPABILITIES #language en-US "Link Capabilities(%2x): %E%08x%N\r\n" +#string STR_PCIEX_LINK_CONTROL #language en-US "Link Control(%2x): %E%04x%N\r\n" +#string STR_PCIEX_LINK_STATUS #language en-US "Link Status(%2x): %E%04x%N\r\n" +#string STR_PCIEX_SLOT_CAPABILITIES #language en-US "Slot Capabilities(%2x): %E%08x%N\r\n" +#string STR_PCIEX_SLOT_CONTROL #language en-US "Slot Control(%2x): %E%04x%N\r\n" +#string STR_PCIEX_SLOT_STATUS #language en-US "Slot Status(%2x): %E%04x%N\r\n" +#string STR_PCIEX_ROOT_CONTROL #language en-US "Root Control(%2x): %E%04x%N\r\n" +#string STR_PCIEX_RSVDP #language en-US "Root Capabilities(%2x): %E%04x%N\r\n" +#string STR_PCIEX_ROOT_STATUS #language en-US "Root Status(%2x): %E%08x%N\r\n" +#string STR_PCI_LINE_VID_DID #language en-US "Vendor ID(%x): %E%04x%N Device ID(%x): %E%04x%N\r\n" +#string STR_PCI_LINE_RID #language en-US "Revision ID(%x): %E%02x%N " +#string STR_PCI_LINE_BIST #language en-US "BIST(%02x): " +#string STR_PCI_LINE_CAP #language en-US "Capable,Return: %E%02x%N\r\n" +#string STR_PCI_LINE_CAP_NO #language en-US " Incapable\r\n" +#string STR_PCI2_CACHE_LINE_SIZE #language en-US "Cache Line Size(%x): %E%02x%N " +#string STR_PCI2_LATENCY_TIMER #language en-US "Latency Timer(%x): %E%02x%N\r\n" +#string STR_PCI2_HEADER_TYPE #language en-US "Header Type(%02x): %E%02x%N, " +#string STR_PCI2_MULTI_FUNCTION #language en-US "Multi-function, " +#string STR_PCI2_SINGLE_FUNCTION #language en-US "Single function, " +#string STR_PCI2_PCI_DEVICE #language en-US "PCI device\r\n" +#string STR_PCI2_P2P_BRIDGE #language en-US "P2P bridge\r\n" +#string STR_PCI2_CARDBUS_BRIDGE #language en-US "CardBus bridge\r\n" +#string STR_PCI2_RESERVED #language en-US "Reserved\r\n" +#string STR_PCI2_CLASS #language en-US "Class: " +#string STR_PCI2_BASE_ADDR #language en-US "Base Address Registers(%x):\r\n" +#string STR_PCI2_START_TYPE #language en-US " Start_Address Type Space Prefetchable? Size Limit\r\n" +#string STR_PCI2_NONE #language en-US " (None)" +#string STR_PCI2_EXPANSION_ROM_DISABLED #language en-US "\r\nExpansion ROM Disabled(%x)\r\n\r\n" +#string STR_PCI2_EXPANSION_ROM_BASE #language en-US "\r\nExpansion ROM Base Address(%x): %E%08x%N\r\n\r\n" +#string STR_PCI2_CARDBUS_CIS #language en-US "Cardbus CIS ptr(%x): %E%08x%N\r\n" +#string STR_PCI2_SUB_VENDOR_ID #language en-US "Sub VendorID(%x): %E%04x%N " +#string STR_PCI2_SUBSYSTEM_ID #language en-US "Subsystem ID(%x): %E%04x%N\r\n" +#string STR_PCI2_CAPABILITIES_PTR #language en-US "Capabilities Ptr(%x): %E%02x%N\r\n" +#string STR_PCI2_INTERRUPT_LINE #language en-US "Interrupt Line(%x): %E%02x%N " +#string STR_PCI2_INTERRUPT_PIN #language en-US "Interrupt Pin(%x): %E%02x%N\r\n" +#string STR_PCI2_MIN_GNT #language en-US "Min_Gnt(%x): %E%02x%N " +#string STR_PCI2_MAX_LAT #language en-US "Max_Lat(%x): %E%02x%N\r\n" +#string STR_PCI2_BASE_ADDRESS #language en-US "Base Address Registers(%x):" +#string STR_PCI2_START_TYPE_2 #language en-US " Start_Address Type Space Prefetchable? Size Limit\r\n" +#string STR_PCI2_NO_EXPANSION_ROM #language en-US "\r\nNo Expansion ROM(%x) " +#string STR_PCI2_EXPANSION_ROM_BASE_2 #language en-US "\r\nExpansion ROM Base Address(%x): %E%08x%N\r\n" +#string STR_PCI2_BUS_NUMBERS #language en-US "\r\n\r\n(Bus Numbers) Primary(%x) Secondary(%x) Subordinate(%x)\r\n" +#string STR_PCI2_BRIDGE #language en-US " %E%02x%N" +#string STR_PCI2_SECONDARY_TIMER #language en-US "\r\nSecondary Latency Timer(%x): %E%02x%N\n\n" +#string STR_PCI2_CARDBUS_LATENCY #language en-US "\r\nCardBus Latency Timer(%x): %E%02x%N\r\n" +#string STR_PCI2_RESOURCE_TYPE_2 #language en-US "\r\nResource Type Type Base Limit\r\n" +#string STR_PCI2_MEM_3 #language en-US "Mem(%x) %s %E%08x%N %E%08x%N\r\n" +#string STR_PCI2_IO_2 #language en-US "I/O(%x) %s %E%08x%N %E%08x%N\r\n" +#string STR_PCI2_INTERRUPT_LINE_3 #language en-US "\r\nInterrupt Line(%x): %E%02x%N Interrupt Pin(%x): %E%02x%N\r\n" +#string STR_PCI2_SUB_VENDOR_ID_2 #language en-US "\r\nSub VendorID(%x): %E%04x%N Subsystem ID(%x): %E%04x%N\r\n" +#string STR_PCI2_OPTIONAL #language en-US "Optional 16-Bit PC Card legacy Mode Base Address(%x): %E%08x%N\r\n" +#string STR_PCI2_STATUS #language en-US "Status(%x): %E%04x%N\r\n" +#string STR_PCI2_SECONDARY_STATUS #language en-US "Secondary Status(%2x): %E%4x%N\r\n" +#string STR_PCI2_NEW_CAPABILITIES #language en-US " (04)New Capabilities linked list: %E%d%N" +#string STR_PCI2_66_CAPABLE #language en-US " (05)66MHz Capable: %EN/A%N\r\n" +#string STR_PCI2_66_CAPABLE_2 #language en-US " (05)66MHz Capable: %E%d%N\r\n" +#string STR_PCI2_FAST_BACK #language en-US " (07)Fast Back-to-Back Capable: %E%d%N" +#string STR_PCI2_NO #language en-US "No " +#string STR_PCI2_YES #language en-US "YES " +#string STR_PCI2_ONE_VAR_4 #language en-US "\r\n %E%04x%N " +#string STR_PCI2_NEWBAR_32 #language en-US " %08x " +#string STR_PCI2_NEWBAR_32_2 #language en-US " %08x" +#string STR_PCI2_RSHIFT #language en-US "%08x" +#string STR_PCI2_NEWBAR_32_3 #language en-US "%04x " +#string STR_PCI2_NEWBAR_32_4 #language en-US "%04x" +#string STR_PCI2_CARDBUS_SOCKET #language en-US "\r\nCardBus Socket Registers/ExCA Base Address Register(%x): %E%8x%N\r\n\r\n" +#string STR_PCI2_BUS_NUMBERS_2 #language en-US "\r\n(Bus Numbers) Pci(%x) CardBus(%x) Subordinate(%x)\r\n" +#string STR_PCI2_CARDBUS #language en-US " %E%02x%N" +#string STR_PCI2_CARDBUS_2 #language en-US " %E%02x%N" +#string STR_PCI2_CARDBUS_3 #language en-US " %E%02x%N\r\n" +#string STR_PCI2_MASTER_DATA #language en-US " (08)Master Data Parity Error: %E%d%N\r\n" +#string STR_PCI2_DEVSEL_TIMING #language en-US " (09)DEVSEL timing: " +#string STR_PCI2_FAST #language en-US "%E Fast%N" +#string STR_PCI2_MEDIUM #language en-US "%E Medium%N" +#string STR_PCI2_SLOW #language en-US "%E Slow%N" +#string STR_PCI2_RESERVED_2 #language en-US "%EReserved%N" +#string STR_PCI2_SIGNALED_TARGET #language en-US " (11)Signaled Target Abort: %E%d%N\r\n" +#string STR_PCI2_RECEIVED_TARGET #language en-US " (12)Received Target Abort: %E%d%N" +#string STR_PCI2_RECEIVED_MASTER #language en-US " (13)Received Master Abort: %E%d%N\r\n" +#string STR_PCI2_SIGNALED_ERROR #language en-US " (14)Signaled System Error: %E%d%N" +#string STR_PCI2_RECEIVED_ERROR #language en-US " (14)Received System Error: %E%d%N" +#string STR_PCI2_DETECTED_ERROR #language en-US " (15)Detected Parity Error: %E%d%N\r\n" +#string STR_PCI2_COMMAND #language en-US "Command(%x): %E%04x%N\r\n" +#string STR_PCI2_SPACE_ACCESS_DENIED #language en-US " (00)I/O space access enabled: %E%d%N" +#string STR_PCI2_MEMORY_SPACE #language en-US " (01)Memory space access enabled: %E%d%N\r\n" +#string STR_PCI2_BEHAVE_BUS_MASTER #language en-US " (02)Behave as bus master: %E%d%N" +#string STR_PCI2_MONITOR_SPECIAL_CYCLE #language en-US " (03)Monitor special cycle enabled: %E%d%N\r\n" +#string STR_PCI2_MEM_WRITE_INVALIDATE #language en-US " (04)Mem Write & Invalidate enabled: %E%d%N" +#string STR_PCI2_PALETTE_SNOOPING #language en-US " (05)Palette snooping is enabled: %E%d%N\r\n" +#string STR_PCI2_ASSERT_PERR #language en-US " (06)Assert PERR# when parity error: %E%d%N" +#string STR_PCI2_DO_ADDR_STEPPING #language en-US " (07)Do address/data stepping: %E%d%N\r\n" +#string STR_PCI2_SERR_DRIVER #language en-US " (08)SERR# driver enabled: %E%d%N" +#string STR_PCI2_FAST_BACK_2 #language en-US " (09)Fast back-to-back transact...: %E%d%N\r\n\r\n" +#string STR_PCI2_BRIDGE_CONTROL #language en-US "Bridge Control(%x) %E%04x%N\r\n" +#string STR_PCI2_PARITY_ERROR #language en-US " (00)Parity Error Response: %E%d%N" +#string STR_PCI2_SERR_ENABLE #language en-US " (01)SERR# Enable: %E%d%N\r\n" +#string STR_PCI2_ISA_ENABLE #language en-US " (02)ISA Enable: %E%d%N" +#string STR_PCI2_RESOURCE_TYPE #language en-US "\r\nResource Type Base Limit\r\n" +#string STR_PCI2_TWO_VARS #language en-US "I/O(%x) %E%08x%N" +#string STR_PCI2_ONE_VAR #language en-US " %E%08x%N\r\n" +#string STR_PCI2_MEMORY #language en-US "Memory(%x) %E%08x%N" +#string STR_PCI2_PREFETCHABLE #language en-US "Prefetchable Memory(%x) %E%08x%08x%N" +#string STR_PCI2_TWO_VARS_2 #language en-US " %E%08x%08x%N\r\n" +#string STR_PCI2_CAPABILITIES_PTR_2 #language en-US "\r\nCapabilities Ptr(%x): %E%02x%N \r\n\r\n" +#string STR_PCI2_INTERRUPT_LINE_2 #language en-US "\r\nInterrupt Line(%x) %E%02x%N " +#string STR_PCI2_BAR #language en-US "\r\n %E%08x%N " +#string STR_PCI2_MEM #language en-US "Mem " +#string STR_PCI2_32_BITS #language en-US "32 bits " +#string STR_PCI2_ONE_VAR_2 #language en-US "\r\n %E%08x" +#string STR_PCI2_ONE_VAR_3 #language en-US "%08x%N " +#string STR_PCI2_64_BITS #language en-US "64 bits " +#string STR_PCI2_MEM_2 #language en-US "Mem " +#string STR_PCI2_VGA_ENABLE #language en-US " (03)VGA Enable: %E%d%N\r\n" +#string STR_PCI2_MASTER_ABORT #language en-US " (05)Master Abort Mode: %E%d%N" +#string STR_PCI2_SECONDARY_BUS_RESET #language en-US " (06)Secondary Bus Reset: %E%d%N\r\n" +#string STR_PCI2_FAST_ENABLE #language en-US " (07)Fast Back-to-Back Enable: %E%d%N" +#string STR_PCI2_PRIMARY_DISCARD_TIMER #language en-US " (08)Primary Discard Timer: %E%s%N\r\n" +#string STR_PCI2_SECONDARY_DISCARD_TIMER #language en-US " (09)Secondary Discard Timer: %E%s%N" +#string STR_PCI2_DISCARD_TIMER_STATUS #language en-US " (10)Discard Timer Status: %E%d%N\r\n" +#string STR_PCI2_DISCARD_TIMER_SERR #language en-US " (11)Discard Timer SERR# Enable: %E%d%N\r\n" +#string STR_PCI2_CARDBUS_RESET #language en-US " (06)CardBus Reset: %E%d%N\r\n" +#string STR_PCI2_IREQ_ENABLE #language en-US " (07)IREQ/INT Enable: %E%d%N" +#string STR_PCI2_WRITE_POSTING_ENABLE #language en-US " (10)Write Posting Enable: %E%d%N\r\n" +#string STR_PCI_EXT_CAP_AER #language en-US " Advanced Error Reporting\r\n" + " UncorrectableErrorStatus %08x\r\n" + " UncorrectableErrorMask %08x\r\n" + " UncorrectableErrorSeverity %08x\r\n" + " CorrectableErrorStatus %08x\r\n" + " CorrectableErrorMask %08x\r\n" + " AdvancedErrorCapAndControl %08x\r\n" + " HeaderLog1 %08x\r\n" + " HeaderLog2 %08x\r\n" + " HeaderLog3 %08x\r\n" + " HeaderLog4 %08x\r\n" + " RootErrorCommand %08x\r\n" + " RootErrorStatus %08x\r\n" + " ErrorSourceIdentification %04x\r\n" + " CorrectableErrorSourceIden %04x\r\n" + " TlpPrefixLog1 %08x\r\n" + " TlpPrefixLog2 %08x\r\n" + " TlpPrefixLog3 %08x\r\n" + " TlpPrefixLog4 %08x\r\n" +#string STR_PCI_EXT_CAP_LINK_CONTROL #language en-US " Link Control\r\n" + " RootComplexLinkCapabilities %08x\r\n" + " RootComplexLinkControl %04x\r\n" + " RootComplexLinkStatus %04x\r\n" +#string STR_PCI_EXT_CAP_LINK_DECLAR #language en-US " Link Declaration\r\n" + " ElementSelfDescription %08x\r\n" +#string STR_PCI_EXT_CAP_LINK_DECLAR2 #language en-US " LinkEntry[%x] %08x\r\n" +#string STR_PCI_EXT_CAP_SN #language en-US " Serial Number\r\n" + " SerialNumber %L16x\r\n" +#string STR_PCI_EXT_CAP_POWER #language en-US " Power Budgeting\r\n" + " DataSelect %02x\r\n" + " Data %08x\r\n" + " PowerBudgetCapability %02x\r\n" +#string STR_PCI_EXT_CAP_ACS #language en-US " ACS\r\n" + " CapabilityRegister %04x\r\n" + " ControlRegister %04x\r\n" +#string STR_PCI_EXT_CAP_ACS2 #language en-US " EgressControlVectorByte[%x] %02x\r\n" +#string STR_PCI_EXT_CAP_LAT #language en-US " Latency Tolerance Reporting\r\n" + " MaxSnoopLatency %04x\r\n" + " MaxNoSnoopLatency %04x\r\n" +#string STR_PCI_EXT_CAP_ARI #language en-US " ARI\r\n" + " AriCapability %04x\r\n" + " AriControl %04x\r\n" +#string STR_PCI_EXT_CAP_RCRB #language en-US " RCRB\r\n" + " VendorId %04x\r\n" + " DeviceId %04x\r\n" + " RcrbCapabilities %04x\r\n" + " RcrbControl %04x\r\n" +#string STR_PCI_EXT_CAP_VEN #language en-US " VendorSpecific\r\n" + " VendorSpecificHeader %04x\r\n" +#string STR_PCI_EXT_CAP_DPA #language en-US " DPA\r\n" + " DpaCapability %04x\r\n" + " DpaLatencyIndicator %04x\r\n" + " DpaStatus %04x\r\n" + " DpaControl %04x\r\n" +#string STR_PCI_EXT_CAP_DPA2 #language en-US " DpaPowerAllocationArray[%x] %02x\r\n" +#string STR_PCI_EXT_CAP_ECEA #language en-US " Event Collector Endpoint Association\r\n" + " AssociationBitmap %04x\r\n" +#string STR_PCI_EXT_CAP_VC_BASE #language en-US " Virtual (Multi) Channel Capability\r\n" + " ExtendedVcCount %08x\r\n" + " PortCapability1 %08x\r\n" + " PortCapability2 %08x\r\n" + " ArbitrationTableOffset %08x\r\n" + " PortVcControl %04x\r\n" + " PortVcStatus %04x\r\n" +#string STR_PCI_EXT_CAP_VC_ITEM #language en-US " Virtual Channel Capability Extended Item[%x]\r\n" + " ResourceCapability %08x\r\n" + " ArbitrationTableOffset %08x\r\n" + " ResourceControl %08x\r\n" + " ResourceStatus %04x\r\n" +#string STR_PCI_EXT_CAP_MULTICAST #language en-US " MultiCast Capability\r\n" + " MultiCastCapability %04x\r\n" + " MulticastControl %04x\r\n" + " McBaseAddress %L16x\r\n" + " McReceiveAddress %L16x\r\n" + " McBlockAll %L16x\r\n" + " McBlockUntranslated %L16x\r\n" + " McOverlayBar %L16x\r\n" +#string STR_PCI_EXT_CAP_RESIZE_BAR #language en-US " Resizeable Bar Capability [%x]\r\n" + " ResizableBarCapability %08x\r\n" + " ResizableBarControl %04x\r\n" +#string STR_PCI_EXT_CAP_TPH #language en-US " TPH\r\n" + " TphRequesterCapability %08x\r\n" + " TphRequesterControl %04x\r\n" + " TphTable (optional):\r\n" +#string STR_PCI_EXT_CAP_SECONDARY #language en-US " Secondary PCI Express Extended Capability\r\n" + " LinkControl3 %08x\r\n" + " LaneErrorStatus %08x\r\n" + " EqualizationControl:\r\n" + +#string STR_DMPSTORE_SAVE #language en-US "Save variable to file: %H%s%N.\r\n" +#string STR_DMPSTORE_LOAD #language en-US "Load and set variables from file: %H%s%N.\r\n" +#string STR_DMPSTORE_LOAD_GEN_FAIL #language en-US "%H%s%N: Failed to set variable %H%s%N: %r.\r\n" +#string STR_DMPSTORE_LOAD_BAD_FILE #language en-US "%H%s%N: Incorrect file format.\r\n" +#string STR_DMPSTORE_HEADER_LINE #language en-US "Variable %H%s%N '%H%g%N:%H%s%N' DataSize = 0x%02x\r\n" +#string STR_DMPSTORE_HEADER_LINE2 #language en-US "Variable %H%s%N '%H%s%N:%H%s%N' DataSize = 0x%02x\r\n" +#string STR_DMPSTORE_DELETE_LINE #language en-US "Delete variable '%H%g%N:%H%s%N': %r\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND #language en-US "%H%s%N: No matching variables found.\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_SFO #language en-US "VariableInfo,\"\",\"\",\"\",\"\",\"\"\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_GN #language en-US "%H%s%N: No matching variables found. Guid %g, Name %s\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_NG_SFO #language en-US "VariableInfo,\"%s\",\"%g\",\"\",\"\",\"\"\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_N #language en-US "%H%s%N: No matching variables found. Name %s\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_N_SFO #language en-US #language en-US "VariableInfo,\"%s\",\"\",\"\",\"\",\"\"\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_G #language en-US "%H%s%N: No matching variables found. Guid %g\r\n" +#string STR_DMPSTORE_NO_VAR_FOUND_G_SFO #language en-US "VariableInfo,\"\",\"%g\",\"\",\"\",\"\"\r\n" +#string STR_DMPSTORE_VAR_SFO #language en-US "VariableInfo,\"%s\",\"%g\",\"0x%x\",\"0x%x\",\"%s\"\r\n" + +#string STR_GET_HELP_COMP #language en-US "" +".TH comp 0 "Compare 2 files"\r\n" +".SH NAME\r\n" +"Compares the contents of two files on a byte-for-byte basis.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"COMP [-b] file1 file2\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time.\r\n" +" file1 - Specifies a first file name (directory name or wildcards not permitted).\r\n" +" file2 - Specifies a second file name (directory name or wildcards not permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command compares the contents of two files in binary mode.\r\n" +" 2. It displays up to 10 differences between the two files. For each\r\n" +" difference, up to 32 bytes from the location where the difference starts\r\n" +" is dumped.\r\n" +" 3. It will exit immediately if the lengths of the compared files are\r\n" +" different.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To compare two files with the same length but different contents:\r\n" +" fs0:\> comp bios.inf bios2.inf\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The function operated as expected.\r\n" +" SHELL_NOT_EQUAL The files were not identical.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The requested file was not found.\r\n" + +#string STR_GET_HELP_SETSIZE #language en-US "" +".TH setsize 0 "Set file size"\r\n" +".SH NAME\r\n" +"Adjusts the size of a file.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SETSIZE size file [file...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" size - Specifies the size of the file after it is adjusted.\r\n" +" file - Specifies the file or files to be adjusted.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. Setting the size smaller than the actual data contained in this file will\r\n" +" truncate its data.\r\n" +" 2. This command adjusts the size of a particular target file.\r\n" +" 3. This command automatically truncates or extends the size of a file based on the passed-in\r\n" +" parameters. If the file does not exist, it is created.\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_VOLUME_FULL The media has insufficient space to complete the\r\n" +" request.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_MODE #language en-US "" +".TH mode 0 "Shows or changes ConOut mode."\r\n" +".SH NAME\r\n" +"Displays or changes the console output device mode.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MODE [col row]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" col - Specifies the number of columns.\r\n" +" row - Specifies the number of rows.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command changes the display mode for the console output\r\n" +" device.\r\n" +" 2. When this command is used without any parameters, it shows the list of\r\n" +" modes that the standard output device currently supports.\r\n" +" 3. When used with the row and col parameter, this command\r\n" +" changes the number of rows and columns on the standard output device.\r\n" +" 4. The current selected mode is indicated by a '*'. \r\n" +" 5. The display is cleared every time this command is used to change the\r\n" +" currently selected display mode.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all available modes on standard output:\r\n" +" Shell> mode\r\n" +" \r\n" +" * To change the current mode setting:\r\n" +" Shell> mode 80 50\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_MEMMAP #language en-US "" +".TH memmap 0 "Displays the memory map."\r\n" +".SH NAME\r\n" +"Displays the memory map maintained by the UEFI environment.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MEMMAP [-b] [-sfo]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time\r\n" +" -sfo - Displays information as described in Standard-Format Output.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The UEFI environment keeps track of all the physical memory in the system\r\n" +" and how it is currently being used.\r\n" +" 2. Total Memory is the physical memory size excluding Reserved, Unusable,\r\n" +" MemoryMappedIO, and MemoryMappedIOPortSpace memory types.\r\n" +" 3. Refer to the UEFI specification for memory type definitions.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the system memory map:\r\n" +" Shell> memmap\r\n" +" \r\n" + +#string STR_GET_HELP_EFICOMPRESS #language en-US "" +".TH eficompress 0 "compresses a file."\r\n" +".SH NAME\r\n" +"Compresses a file using UEFI Compression Algorithm.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"EFICOMPRESS infile outfile\r\n" +".SH OPTIONS\r\n" +" \r\n" +" infile - Specifies the file name of the uncompressed input file.\r\n" +" outfile - Specifies the file name of the compressed output file.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command compresses a file using UEFI Compression Algorithm\r\n" +" and writes the compressed form out to a new file.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To compress a file named 'uncompressed' to a file named 'compressed':\r\n" +" fs0:\> eficompress uncompressed compressed\r\n" + +#string STR_GET_HELP_EFIDCOMPRESS #language en-US "" +".TH efidecompress 0 "Decompresses a file."\r\n" +".SH NAME\r\n" +"Decompresses a file using UEFI Decompression Algorithm.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"EFIDECOMPRESS infile outfile\r\n" +".SH OPTIONS\r\n" +" \r\n" +" infile - Specifies the file name of the compressed input file.\r\n" +" outfile - Specifies the file name of the decompressed output file.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This decompresses a file using UEFI Decompression\r\n" +" Algorithm and writes the decompressed form out to a new file.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To decompress a file named 'compressed' to a file named 'uncompressed':\r\n" +" fs0:\> efidecompress compressed uncompressed\r\n" + +#string STR_GET_HELP_DMEM #language en-US "" +".TH dmem 0 "Displays memory."\r\n" +".SH NAME\r\n" +"Displays the contents of system or device memory.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DMEM [-b] [address] [size] [-MMIO]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time.\r\n" +" -MMIO - Forces address cycles to the PCI bus.\r\n" +" address - Specifies a starting address in hexadecimal format.\r\n" +" size - Specifies the number of bytes to display in hexadecimal format.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays the contents of system memory or device memory.\r\n" +" 2. Enter address and size in hexadecimal format.\r\n" +" 3. If address is not specified, the contents of the UEFI System Table\r\n" +" are displayed. Otherwise, memory starting at the specified address is displayed.\r\n" +" 4. Size specifies the number of bytes to display. If size is not specified,\r\n" +" 512 bytes are displayed.\r\n" +" 5. If MMIO is not specified, main system memory is displayed. Otherwise,\r\n" +" device memory is displayed through the use of the\r\n" +" EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the UEFI system table pointer entries:\r\n" +" fs0:\> dmem\r\n" +" \r\n" +" * To display memory contents from 1af3088 with size of 16 bytes:\r\n" +" Shell> dmem 1af3088 16\r\n" +" \r\n" +" * To display memory mapped IO contents from 1af3088 with a size of 16 bytes:\r\n" +" Shell> dmem 1af3088 16 -MMIO\r\n" + +#string STR_GET_HELP_MM #language en-US "" +".TH mm 0 "Displays or modifies address space memory."\r\n" +".SH NAME\r\n" +"Displays or modifies MEM/MMIO/IO/PCI/PCIE address space.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MM Address [Value] [-w 1|2|4|8] [-MEM | -MMIO | -IO | -PCI | -PCIE] [-n]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" Address - Starting address in hexadecimal format.\r\n" +" Value - The value to write in hexadecimal format.\r\n" +" -MEM - Memory Address type\r\n" +" -MMIO - Memory Mapped IO Address type\r\n" +" -IO - IO Address type\r\n" +" -PCI - PCI Configuration Space Address type:\r\n" +" Address format: ssssbbddffrr\r\n" +" ssss - Segment\r\n" +" bb - Bus\r\n" +" dd - Device\r\n" +" ff - Function\r\n" +" rr - Register\r\n" +" -PCIE - PCIE Configuration Space Address type:\r\n" +" Address format: ssssbbddffrrr\r\n" +" ssss - Segment\r\n" +" bb - Bus\r\n" +" dd - Device\r\n" +" ff - Function\r\n" +" rrr - Register\r\n" +" -w - Unit size accessed in bytes:\r\n" +" 1 - 1 byte\r\n" +" 2 - 2 bytes\r\n" +" 4 - 4 bytes\r\n" +" 8 - 8 bytes\r\n" +" -n - Non-interactive mode\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. If the address type parameter is not specified, address type defaults\r\n" +" to the 'MEM' type.\r\n" +" 2. If the 'Value' parameter is specified, the '-n' option is used and\r\n" +" the command writes the value to the\r\n" +" specified address in non-interactive mode. If the 'Value' parameter is\r\n" +" not specified, only the current contents in the address are displayed.\r\n" +" 3. If the '-w' option is not specified, unit size defaults to 1 byte.\r\n" +" 4. If the PCI address type is specified, the 'Address' parameter must\r\n" +" follow the PCI Configuration Space Address format above. The 'PCI'\r\n" +" command can be used to determine the address for a specified device.\r\n" +" It is listed in the PCI configuration space dump information in the\r\n" +" following format: "[EFI ssbbddffxx]".\r\n" +" 5. If the PCIE address type is specified, the 'Address' parameter must\r\n" +" follow the PCIE Configuration Space Address format above.\r\n" +" 6. In interactive mode, type a hex value to modify, 'q' or '.' to exit.\r\n" +" If the '-n' option is specified, it runs in non-interactive mode,\r\n" +" which supports batch file operation without user intervention.\r\n" +" 7. Not all PCI configuration register locations are writable.\r\n" +" 8. MM will only write the specified value. Read-modify-write operations\r\n" +" are not supported.\r\n" +" 9. The 'Address' parameter must be aligned on a boundary of the\r\n" +" specified width.\r\n" +" 10. Not all addresses are safe to access. Access to any improper address\r\n" +" can bring unexpected results.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display or modify memory:\r\n" +" Address 0x1b07288, default width=1 byte:\r\n" +" fs0:\> mm 1b07288\r\n" +" MEM 0x0000000001B07288 : 0x6D >\r\n" +" MEM 0x0000000001B07289 : 0x6D >\r\n" +" MEM 0x0000000001B0728A : 0x61 > 80\r\n" +" MEM 0x0000000001B0728B : 0x70 > q\r\n" +" fs0:\> mm 1b07288\r\n" +" MEM 0x0000000001B07288 : 0x6D >\r\n" +" MEM 0x0000000001B07289 : 0x6D >\r\n" +" MEM 0x0000000001B0728A : 0x80 > *Modified\r\n" +" MEM 0x0000000001B0728B : 0x70 > q\r\n" +" \r\n" +" * To modify memory: Address 0x1b07288, width = 2 bytes:\r\n" +" Shell> mm 1b07288 -w 2\r\n" +" MEM 0x0000000001B07288 : 0x6D6D >\r\n" +" MEM 0x0000000001B0728A : 0x7061 > 55aa\r\n" +" MEM 0x0000000001B0728C : 0x358C > q\r\n" +" Shell> mm 1b07288 -w 2\r\n" +" MEM 0x0000000001B07288 : 0x6D6D >\r\n" +" MEM 0x0000000001B0728A : 0x55AA > *Modified\r\n" +" MEM 0x0000000001B0728C : 0x358C > q\r\n" +" \r\n" +" * To display IO space: Address 80h, width = 4 bytes:\r\n" +" Shell> mm 80 -w 4 -IO\r\n" +" IO 0x0000000000000080 : 0x000000FE >\r\n" +" IO 0x0000000000000084 : 0x00FF5E6D > q\r\n" +" \r\n" +" * To modify IO space using non-interactive mode:\r\n" +" Shell> mm 80 52 -w 1 -IO\r\n" +" Shell> mm 80 -w 1 -IO\r\n" +" IO 0x0000000000000080 : 0x52 > FE *Modified\r\n" +" IO 0x0000000000000081 : 0xFF >\r\n" +" IO 0x0000000000000082 : 0x00 >\r\n" +" IO 0x0000000000000083 : 0x00 >\r\n" +" IO 0x0000000000000084 : 0x6D >\r\n" +" IO 0x0000000000000085 : 0x5E >\r\n" +" IO 0x0000000000000086 : 0xFF >\r\n" +" IO 0x0000000000000087 : 0x00 > q\r\n" +" \r\n" +" * To display PCI configuration space, ss=0000, bb=00, dd=00, ff=00, rr=00:\r\n" +" Shell> mm 000000000000 -PCI\r\n" +" PCI 0x0000000000000000 : 0x86 >\r\n" +" PCI 0x0000000000000001 : 0x80 >\r\n" +" PCI 0x0000000000000002 : 0x30 >\r\n" +" PCI 0x0000000000000003 : 0x11 >\r\n" +" PCI 0x0000000000000004 : 0x06 >\r\n" +" PCI 0x0000000000000005 : 0x00 > q\r\n" +" These contents can also be displayed by 'PCI 00 00 00'.\r\n" +" \r\n" +" * To display PCIE configuration space, ss=0000, bb=06, dd=00, ff=00, rrr=000:\r\n" +" Shell> mm 0000060000000 -PCIE\r\n" +" PCIE 0x0000000060000000 : 0xAB >\r\n" +" PCIE 0x0000000060000001 : 0x11 >\r\n" +" PCIE 0x0000000060000002 : 0x61 >\r\n" +" PCIE 0x0000000060000003 : 0x43 >\r\n" +" \r\n" + +#string STR_GET_HELP_LOAD_PCI_ROM #language en-US "" +".TH loadpcirom 0 "Loads a PCI option ROM file."\r\n" +".SH NAME\r\n" +"Loads a PCI Option ROM.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"LoadPciRom [-nc] romfile [romfile...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -nc - Loads the ROM image(s) but does not connect drivers.\r\n" +" romfile - Specifies the PCI option ROM image file (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command loads PCI option ROM images into memory for\r\n" +" execution.\r\n" +" 2. The file can contain legacy images and multiple PE32 images, in which case\r\n" +" all PE32 images are loaded.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To load a rom file 'rom.bin':\r\n" +" fs0:\> LoadPciRom rom.bin\r\n" +" \r\n" +" * To load '*.bin' files without connecting drivers:\r\n" +" fs0:\> LoadPciRom -nc *.bin\r\n" + +#string STR_GET_HELP_SETVAR #language en-US "" +".TH setvar 0 "Displays or modifies a UEFI variable."\r\n" +".SH NAME\r\n" +"Displays or modifies a UEFI variable.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SETVAR variable-name [-guid guid][-bs][-rt][-nv] [=data]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" variable-name - Specifies the name of the UEFI variable to modify or display.\r\n" +" -guid - Specifies the GUID of the UEFI variable to modify or display.\r\n" +" If not present, GUID EFI_GLOBAL_VARIABLE is assumed.\r\n" +" -bs - Indicates that the variable is a boot variable. Applies to a new variable;\r\n" +" otherwise, it is ignored. \r\n" +" -rt - Indicates that the variable is a runtime variable. Applies to a new variable;\r\n" +" otherwise, it is ignored. \r\n" +" -nv - Indicates that the variable is non-volatile. If not present,\r\n" +" then the variable is assumed to be volatile. Applies to a new variable;\r\n" +" otherwise, it is ignored. \r\n" +" =data - Specifies there is new data for the variable. If there is nothing after the '='\r\n" +" then the variable is deleted. If '=' is not present, then the\r\n" +" current value of the variable is dumped as hex bytes.\r\n" +" The data can consist of zero or more of the following:\r\n" +" xx[xx] - Hexadecimal bytes\r\n" +" ^"ascii-string^" - ASCII-string with no null-terminator\r\n" +" L^"UCS2-string^" - UCS-2 encoded string with no\r\n" +" null-terminator\r\n" +" --device - Device path text format\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command changes the UEFI variable specified by name and GUID.\r\n" +" 2. If = is specified, but data is not, the variable is deleted, if it exists.\r\n" +" 3. If = is not specified, then the current variable contents are displayed.\r\n" +" 4. If =data is specified, then the variable's value is changed to the value\r\n" +" specified by data.\r\n" +" 5. -bs, -rt and -nv are only useful if the variable does not exist.\r\n" +" 6. If the variable already exists, the attributes cannot be changed, and the" +" flags will be ignored.\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The shell has stored the variable and its data with\r\n" +" the defined attributes.\r\n" +" SHELL_INVALID_PARAMETER Incorrect attributes were used.\r\n" +" SHELL_OUT_OF_RESOURCES Insufficient resources were available for storing\r\n" +" the variable and its data.\r\n" +" SHELL_DEVICE_ERROR The Variable could not be saved due to a hardware\r\n" +" error.\r\n" +" SHELL_WRITE_PROTECTED The variable in question is read-only.\r\n" +" SHELL_WRITE_PROTECTED The variable in question cannot be deleted.\r\n" +" SHELL_NOT_FOUND The variable could not be found.\r\n" + +#string STR_GET_HELP_SERMODE #language en-US "" +".TH sermode 0 "configure serial port"\r\n" +".SH NAME\r\n" +"Sets serial port attributes.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SERMODE [handle [baudrate parity databits stopbits]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" handle - Specifies a device handle for a serial port in hexadecimal format.\r\n" +" baudrate - Specifies a baud rate for specified serial port.\r\n" +" parity - Sets parity bit settings for specified serial port. Valid values\r\n" +" are:\r\n" +" d - Default parity\r\n" +" n - No parity\r\n" +" e - Even parity\r\n" +" o - Odd parity\r\n" +" m - Mark parity\r\n" +" s - Space parity\r\n" +" databits - Sets the data bits for the specified serial port.\r\n" +" stopbits - Sets the stop bits for the specified serial port.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The 'handle' parameter is the device handle of the desired serial port.\r\n" +" The 'DH' command can be used to retrieve this information.\r\n" +" 2. The 'stopbits' parameter supports the following settings:\r\n" +" 0 (0 stop bits - default setting)\r\n" +" 1 (1 stop bit)\r\n" +" 2 (2 stop bits)\r\n" +" 15 (1.5 stop bits)\r\n" +" All other settings are invalid.\r\n" +" 3. The 'baudrate' parameter supports the following settings:\r\n" +" 50, 75, 110, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800,\r\n" +" 7200, 9600(default), 19200, 38400, 57600, 115200, 230400, 460800\r\n" +" All other values will be converted to the next highest setting.\r\n" +" 4. The 'databits' parameter supports the following settings:\r\n" +" 4\r\n" +" 7\r\n" +" 8 (default)\r\n" +" All other settings are invalid.\r\n" +" 5. Parity attributes are mutually exclusive.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the settings for all serial port devices:\r\n" +" Shell> sermode\r\n" +" \r\n" +" * To display the settings for the serial port device whose handle is 0x6B:\r\n" +" Shell> sermode 6B\r\n" +" \r\n" +" * To configure the serial port settings for handle 0x6B to 9600bps, even\r\n" +" parity, 8 data bits, and 1 stop bit:\r\n" +" Shell> sermode 6B 9600 e 8 1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The new attributes were set on the serial device.\r\n" +" SHELL_INVALID_PARAMETER One or more of the attributes has an unsupported\r\n" +" value.\r\n" +" SHELL_DEVICE_ERROR The serial device is not functioning correctly.\r\n" + +#string STR_GET_HELP_PCI #language en-US "" +".TH pci 0 "Displays PCI device information."\r\n" +".SH NAME\r\n" +"Displays PCI device list or PCI function configuration space and PCIe extended\r\n" +"configuration space.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"PCI [Bus Dev [Func] [-s Seg] [-i [-ec ID]]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -s - Specifies optional segment number (hexadecimal number).\r\n" +" -i - Displays interpreted information.\r\n" +" -ec - Displays detailed interpretation of specified PCIe extended capability\r\n" +" ID (hexadecimal number).\r\n" +" Bus - Specifies a bus number (hexadecimal number).\r\n" +" Dev - Specifies a device number (hexadecimal number).\r\n" +" Func - Specifies a function number (hexadecimal number).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays a list of all the PCI devices found in the system. It\r\n" +" also displays the configuration space of a PCI device according to the\r\n" +" specified bus (Bus), device (Dev), and function (Func) addresses. If the\r\n" +" function address is not specified, it defaults to 0.\r\n" +" 2. The -i option displays verbose information for the specified PCI\r\n" +" device. The PCI configuration space for the device is displayed with\r\n" +" a detailed interpretation.\r\n" +" 3. If no parameters are specified, all PCI devices are listed.\r\n" +" 4. If the 'Bus' and 'Dev' parameters are specified but the 'Func' or\r\n" +" 'Seg' parameters are not, Function or Seg are set to the default value of 0.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all PCI devices in the system:\r\n" +" Shell> pci\r\n" +" \r\n" +" * To display the configuration space of Bus 0, Device 0, Function 0:\r\n" +" Shell> pci 00 00 00 -i\r\n" +" \r\n" +" * To display configuration space of Segment 0, Bus 0, Device 0, Function 0:\r\n" +" Shell> pci 00 00 00 -s 0\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS Data was displayed as requested.\r\n" +" SHELL_DEVICE_ERROR The specified device parameters did not match a physical\r\n" +" device in the system.\r\n" + +#string STR_GET_HELP_SMBIOSVIEW #language en-US "" +".TH smbiosview 0 "Displays SMBIOS information."\r\n" +".SH NAME\r\n" +"Displays SMBIOS information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SMBIOSVIEW [-t SmbiosType]|[-h SmbiosHandle]|[-s]|[-a]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -t - Displays all structures of SmbiosType.\r\n" +" -h - Displays structure of SmbiosHandle.\r\n" +" -s - Displays a statistics table.\r\n" +" -a - Displays all information.\r\n" +" SmbiosType - Specifies a SMBIOS structure type.\r\n" +" SmbiosHandle - Specifies a SMBIOS structure unique 16-bit handle.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The SmbiosType parameter supports the following types:\n" +" 0 - BIOS Information\r\n" +" 1 - System Information\r\n" +" 2 - Baseboard Information\r\n" +" 3 - System Enclosure\r\n" +" 4 - Processor Information\r\n" +" 5 - Memory Controller Information\r\n" +" 6 - Memory Module Information\r\n" +" 7 - Cache Information\r\n" +" 8 - Port Connector Information\r\n" +" 9 - System Slots\r\n" +" 10 - On Board Devices Information\r\n" +" 11 - OEM Strings\r\n" +" 12 - System Configuration Options\r\n" +" 13 - BIOS Language Information\r\n" +" 14 - Group Associations\r\n" +" 15 - System Event Log\r\n" +" 16 - Physical Memory Array\r\n" +" 17 - Memory Device\r\n" +" 18 - 32-bit Memory Error Information\r\n" +" 19 - Memory Array Mapped Address\r\n" +" 20 - Memory Device Mapped Address\r\n" +" 21 - Built-in Pointing Device\r\n" +" 22 - Portable Battery\r\n" +" 23 - System Reset\r\n" +" 24 - Hardware Security\r\n" +" 25 - System Power Controls\r\n" +" 26 - Voltage Probe\r\n" +" 27 - Cooling Device\r\n" +" 28 - Temperature Probe\r\n" +" 29 - Electrical Current Probe\r\n" +" 30 - Out-Of-Band Remote Access\r\n" +" 31 - Boot Integrity Services (BIS) Entry Point\r\n" +" 32 - System Boot Information\r\n" +" 33 - 64-Bit Memory Error Information\r\n" +" 34 - Management Device\r\n" +" 35 - Management Device Component\r\n" +" 36 - Management Device Threshold Data\r\n" +" 37 - Memory Channel\r\n" +" 38 - IPMI Device Information\r\n" +" 39 - System Power Supply\r\n" +" 40 - Additional Information\r\n" +" 41 - Onboard Devices Extended Information\r\n" +" 42 - Management Controller Host Interface\r\n" +" 43 - TPM Device\r\n" +" 2. Enter the SmbiosHandle parameter in hexadecimal format.\r\n" +" Do not use the '0x' prefix format for hexadecimal values.\r\n" +" 3. Internal commands:\r\n" +" :q -------- quit smbiosview\r\n" +" :0 -------- Change smbiosview display NONE info\r\n" +" :1 -------- Change smbiosview display OUTLINE info\r\n" +" :2 -------- Change smbiosview display NORMAL info\r\n" +" :3 -------- Change smbiosview display DETAIL info\r\n" +" /? -------- Show help\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS Data was displayed as requested.\r\n" +" SHELL_DEVICE_ERROR The requested structure was not found.\r\n" + +#string STR_GET_HELP_DMPSTORE #language en-US "" +".TH dmpstore 0 "Manages all UEFI variables."\r\n" +".SH NAME\r\n" +"Manages all UEFI variables.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DMPSTORE [-b] [-d] [-all | ([variable] [-guid guid])] [-sfo]\r\n" +"DMPSTORE [-all | ([variable] [-guid guid])] [-s file]\r\n" +"DMPSTORE [-all | ([variable] [-guid guid])] [-l file]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time.\r\n" +" -guid - Specifies the GUID of the variables to be displayed in\r\n" +" standard text format. If not specified and -all is not\r\n" +" specified, the EFI_GLOBAL_VARIABLE GUID is assumed.\r\n" +" -sfo - Displays information as described in Standard-Format Output.\r\n" +" -all - Dumps all variables, including those\r\n" +" with a different GUID than EFI_GLOBAL_VARIABLE.\r\n" +" -d - Delete variables.\r\n" +" -s - Saves variables to a file.\r\n" +" -l - Loads and sets variables from a file.\r\n" +" variable - Specifies a variable name. This can be a literal name or\r\n" +" a pattern as specified in the MetaiMatch() function of the\r\n" +" EFI_UNICODE_COLLATION2_PROCOOL.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command manages the UEFI variables. The variables\r\n" +" displayed or deleted depend on the command line options, as specified in\r\n" +" the following table:\r\n" +" Variable GUID -all Description\r\n" +" --- --- --- All variables with the GUID EFI_GLOBAL_VARIABLE will\r\n" +" be operated on.\r\n" +" --- --- X All variables (regardless of GUID or name) will be\r\n" +" operated on.\r\n" +" --- X --- All variables with the specified GUID will be\r\n" +" operated on.\r\n" +" X --- --- The variable with the GUID EFI_GLOBAL_VARIABLE and\r\n" +" the name Variable will be operated on.\r\n" +" X X --- The variable with the specified GUID and name\r\n" +" Variable will be operated on.\r\n" +" 2. The variable value is printed as a hexadecimal dump.\r\n" +" 3. Option -d is used to delete variables. Option -s and -l are used to save\r\n" +" and load variables to and from a file. The variable name can be specified\r\n" +" when using these flags so that the operation only takes effect on\r\n" +" that variable.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To dump all variables with the GUID EFI_GLOBAL_VARIABLE:\r\n" +" Shell> dmpstore\r\n" +" \r\n" +" * To dump all variables (regardless of GUID or name):\r\n" +" Shell> dmpstore -all\r\n" +" \r\n" +" * To dump the 'path' variable with the GUID '158DEF5A-F656-419C-B027-\r\n" +" 7A3192C079D2':\r\n" +" Shell> dmpstore path -guid 158DEF5A-F656-419C-B027-7A3192C079D2\r\n" +" \r\n" +" * To save all variables (regardless of GUID or name) to a file 'VarDump.txt':\r\n" +" fs0:\> dmpstore -all -s VarDump.txt\r\n" +" \r\n" +" * To delete the 'BootOrder' variable with the GUID EFI_GLOBAL_VARIABLE:\r\n" +" Shell> dmpstore -d BootOrder\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_DBLK #language en-US "" +".TH dblk 0 "Displays one or more blocks from a block device."\r\n" +".SH NAME\r\n" +"Displays one or more blocks from a block device.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DBLK device [lba] [blocks] [-b]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time.\r\n" +" device - Blocks the device name.\r\n" +" lba - Specifies the index of the first block to be displayed (a hexadecimal number).\r\n" +" The default is 0.\r\n" +" blocks - Specifies the number of blocks to display (a hexadecimal number). The default\r\n" +" is 1. If larger than 0x10, then only 0x10 are displayed.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays the contents of one or more blocks from a block\r\n" +" device. Enter a hexidecimal value for the lba and blocks variables. If lba is not\r\n" +" specified, block #0 is assumed. If blocks is not specified, on1y one\r\n" +" block is displayed. The maximum number of blocks that can be\r\n" +" displayed at one time is 0x10.\r\n" +" 2. If an MBR is found on the block, the partition information is displayed\r\n" +" after all the block contents are displayed.\r\n" +" 3. If the block is a FAT partition, some FAT parameters are displayed\r\n" +" (label, systemid, oemid, sectorsize, clustersize, media, and so forth) after all the\r\n" +" blocks are displayed.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display one block of blk0, beginning from block 0:\r\n" +" Shell> dblk blk0\r\n" +" \r\n" +" * To display one block of fs0, beginning from block 0x2:\r\n" +" Shell> dblk fs0 2\r\n" +" \r\n" +" * To display 0x5 blocks of fs0, beginning from block 0x12:\r\n" +" Shell> dblk fs0 12 5\r\n" +" \r\n" +" * To display 0x10 blocks of fs0, beginning from block 0x12:\r\n" +" Shell> dblk fs0 12 10\r\n" +" \r\n" +" * To attempt to display more than 0x10 blocks, resulting in only 0x10\r\n" +" blocks being displayed:\r\n" +" Shell> dblk fs0 12 20\r\n" +" \r\n" +" * To display one block of blk2, beginning from the first block (blk0):\r\n" +" fs1:\tmps1> dblk blk2 0 1\r\n" +" \r\n" + +#string STR_GET_HELP_EDIT #language en-US "" +".TH edit 0 "Provides a full screen text editor for ASCII or UCS-2 files."\r\n" +".SH NAME\r\n" +"Provides a full screen text editor for ASCII or UCS-2 files.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"EDIT [file]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" file - Specifies the name of file to be edited. If none is specified, an empty file\r\n" +" is created with a default file name.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command enables full screen file editing.\r\n" +" 2. The editor supports both UCS-2 and ASCII file types.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To edit the 'shell.log' file:\r\n" +" fs0:\> edit shell.log\r\n" + +#string STR_GET_HELP_HEXEDIT #language en-US "" +".TH hexedit 0 "Provides a full screen hex editor for files, block devices, or memory."\r\n" +".SH NAME\r\n" +"Provides a full screen hex editor for files, block devices, or memory.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"HEXEDIT [[-f] filename| [-d diskname offset size] | [-m address size]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -f - Specifies the name of the file to edit.\r\n" +" -d - Specifies the disk block to edit:\r\n" +" DiskName - Name of the disk to edit (for example fs0)\r\n" +" Offset - Starting block number (beginning from 0)\r\n" +" Size - Number of blocks to edit\r\n" +" -m - Specifies the memory region to edit:\r\n" +" Address - Starting 32-bit memory address (beginning from 0)\r\n" +" Size - Size of memory region to edit in bytes\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command enables you to edit a file, block device, or memory region.\r\n" +" 2. The region being edited is displayed as hexadecimal bytes. The\r\n" +" contents can be modified and saved.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To edit a file in hex mode:\r\n" +" fs0:\> hexedit test.bin\r\n" +" \r\n" +" * To edit block device fs0 starting at block 0 with size of 2 blocks:\r\n" +" fs0:\> hexedit -d fs0 0 2\r\n" +" \r\n" +" * To edit memory region starting at address 0x00000000 with size of 2 bytes:\r\n" +" fs0:\> hexedit -m 0 2\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c new file mode 100644 index 0000000..c6e4039 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c @@ -0,0 +1,549 @@ +/** @file + Main file for connect shell Driver1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +/** + Create all handles associate with every device path node. + + @param DevicePathToConnect The device path which will be connected. + + @retval EFI_SUCCESS All handles associate with every device path node + have been created. + @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL. + @retval EFI_NOT_FOUND Create the handle associate with one device path + node failed + +**/ +EFI_STATUS +ShellConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ) +{ + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_HANDLE PreviousHandle; + + if (DevicePathToConnect == NULL) { + return EFI_INVALID_PARAMETER; + } + + PreviousHandle = NULL; + do{ + RemainingDevicePath = DevicePathToConnect; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); + + if (!EFI_ERROR (Status) && (Handle != NULL)) { + if (PreviousHandle == Handle) { + Status = EFI_NOT_FOUND; + } else { + PreviousHandle = Handle; + Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); + } + } + + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath) ); + + return Status; + +} + +/** + Connect drivers for PCI root bridge. + + @retval EFI_SUCCESS Connect drivers successfully. + @retval EFI_NOT_FOUND Cannot find PCI root bridge device. + +**/ +EFI_STATUS +ShellConnectPciRootBridge ( + VOID + ) +{ + UINTN RootBridgeHandleCount; + EFI_HANDLE *RootBridgeHandleBuffer; + UINTN RootBridgeIndex; + EFI_STATUS Status; + + RootBridgeHandleCount = 0; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &RootBridgeHandleCount, + &RootBridgeHandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) { + gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE); + } + + FreePool (RootBridgeHandleBuffer); + + return EFI_SUCCESS; +} + + +/** + Connect controller(s) and driver(s). + + @param[in] ControllerHandle The handle to the controller. Should have driver binding on it. + @param[in] DriverHandle The handle to the driver. Should have driver binding. + @param[in] Recursive TRUE to connect recursively, FALSE otherwise. + @param[in] Output TRUE to have info on the screen, FALSE otherwise. + @param[in] AlwaysOutput Override Output for errors. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ConnectControllers ( + IN CONST EFI_HANDLE ControllerHandle OPTIONAL, + IN CONST EFI_HANDLE DriverHandle OPTIONAL, + IN CONST BOOLEAN Recursive, + IN CONST BOOLEAN Output, + IN CONST BOOLEAN AlwaysOutput + ) +{ + EFI_STATUS Status; + EFI_STATUS Status2; + EFI_HANDLE *ControllerHandleList; + EFI_HANDLE *DriverHandleList; + EFI_HANDLE *HandleWalker; + + ControllerHandleList = NULL; + Status = EFI_NOT_FOUND; + Status2 = EFI_NOT_FOUND; + + // + // If we have a single handle to connect make that a 'list' + // + if (DriverHandle == NULL) { + DriverHandleList = NULL; + } else { + DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); + if (DriverHandleList == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + DriverHandleList[0] = DriverHandle; + DriverHandleList[1] = NULL; + } + + // + // do we connect all controllers (with a loop) or a single one... + // This is where we call the gBS->ConnectController function. + // + if (ControllerHandle == NULL) { + ControllerHandleList = GetHandleListByProtocol(&gEfiDevicePathProtocolGuid); + for (HandleWalker = ControllerHandleList + ; HandleWalker != NULL && *HandleWalker != NULL + ; HandleWalker++ + ){ + Status = gBS->ConnectController(*HandleWalker, DriverHandleList, NULL, Recursive); + if (!EFI_ERROR(Status)) { + Status2 = EFI_SUCCESS; + } + if ((Output && !EFI_ERROR(Status)) || AlwaysOutput) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Connect", ConvertHandleToHandleIndex(*HandleWalker), Status); + } + } + } else { + Status = gBS->ConnectController(ControllerHandle, DriverHandleList, NULL, Recursive); + if (!EFI_ERROR(Status)) { + Status2 = EFI_SUCCESS; + } + if ((Output && !EFI_ERROR(Status)) || AlwaysOutput) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Connect", ConvertHandleToHandleIndex(ControllerHandle), Status); + } + } + + // + // Free any memory we allocated. + // + if (ControllerHandleList != NULL) { + FreePool(ControllerHandleList); + } + if (DriverHandleList != NULL) { + FreePool(DriverHandleList); + } + return (Status2); +} + +/** + Do a connect from an EFI variable via it's key name. + + @param[in] Key The name of the EFI Variable. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ShellConnectFromDevPaths ( + IN CONST CHAR16 *Key + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevPath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *Next; + UINTN Length; + UINTN Index; + UINTN HandleArrayCount; + UINTN Size; + EFI_HANDLE *HandleArray; + EFI_STATUS Status; + BOOLEAN AtLeastOneConnected; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Class[3]; + + DevPath = NULL; + Length = 0; + AtLeastOneConnected = FALSE; + + // + // Get the DevicePath buffer from the variable... + // + Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath); + if (Status == EFI_BUFFER_TOO_SMALL) { + DevPath = AllocateZeroPool(Length); + if (DevPath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath); + if (EFI_ERROR (Status)) { + if (DevPath != NULL) { + FreePool (DevPath); + } + return Status; + } + } else if (EFI_ERROR (Status)) { + return Status; + } + + Status = EFI_NOT_FOUND; + + CopyOfDevPath = DevPath; + // + // walk the list of devices and connect them + // + do { + // + // Check every instance of the console variable + // + Instance = GetNextDevicePathInstance (&CopyOfDevPath, &Size); + if (Instance == NULL) { + if (DevPath != NULL) { + FreePool (DevPath); + } + return EFI_UNSUPPORTED; + } + + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + // + // connect short form device path + // + if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) + || (DevicePathSubType (Instance) == MSG_USB_WWID_DP) + )) { + + Status = ShellConnectPciRootBridge (); + if (EFI_ERROR(Status)) { + FreePool(Instance); + FreePool(DevPath); + return Status; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleArrayCount, + &HandleArray + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < HandleArrayCount; Index++) { + Status = gBS->HandleProtocol ( + HandleArray[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + + if (!EFI_ERROR (Status)) { + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); + if (!EFI_ERROR (Status)) { + if ((PCI_CLASS_SERIAL == Class[2]) && + (PCI_CLASS_SERIAL_USB == Class[1])) { + Status = gBS->ConnectController ( + HandleArray[Index], + NULL, + Instance, + FALSE + ); + if (!EFI_ERROR(Status)) { + AtLeastOneConnected = TRUE; + } + } + } + } + } + } + + if (HandleArray != NULL) { + FreePool (HandleArray); + } + } else { + // + // connect the entire device path + // + Status = ShellConnectDevicePath (Instance); + if (!EFI_ERROR (Status)) { + AtLeastOneConnected = TRUE; + } + } + FreePool (Instance); + + } while (CopyOfDevPath != NULL); + + if (DevPath != NULL) { + FreePool(DevPath); + } + + if (AtLeastOneConnected) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } + +} + +/** + Convert the handle identifiers from strings and then connect them. + + One of them should have driver binding and either can be NULL. + + @param[in] Handle1 The first handle. + @param[in] Handle2 The second handle. + @param[in] Recursive TRUE to do connect recursively. FALSE otherwise. + @param[in] Output TRUE to have output to screen. FALSE otherwise. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ConvertAndConnectControllers ( + IN EFI_HANDLE *Handle1 OPTIONAL, + IN EFI_HANDLE *Handle2 OPTIONAL, + IN CONST BOOLEAN Recursive, + IN CONST BOOLEAN Output + ) +{ + // + // if only one is NULL verify it's the proper one... + // + if ( (Handle1 == NULL && Handle2 != NULL) + || (Handle1 != NULL && Handle2 == NULL) + ){ + // + // Figure out which one should be NULL and move the handle to the right place. + // If Handle1 is NULL then test Handle2 and vise versa. + // The one that DOES has driver binding must be Handle2 + // + if (Handle1 == NULL) { + if (EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + // swap + Handle1 = Handle2; + Handle2 = NULL; + } else { + // We're all good... + } + } else { + if (EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + // We're all good... + } else { + // swap + Handle2 = Handle1; + Handle1 = NULL; + } + } + } + + return (ConnectControllers(Handle1, Handle2, Recursive, Output, (BOOLEAN)(Handle2 != NULL && Handle1 != NULL))); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-c", TypeFlag}, + {L"-r", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'connect' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunConnect ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Param1; + CONST CHAR16 *Param2; + UINTN Count; + EFI_HANDLE Handle1; + EFI_HANDLE Handle2; + UINT64 Intermediate; + + ShellStatus = SHELL_SUCCESS; + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"connect", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // if more than 2 'value' parameters (plus the name one) or either -r or -c with any value parameters we have too many parameters + // + Count = (gInReconnect?0x4:0x3); + if ((ShellCommandLineGetCount(Package) > Count) + ||(ShellCommandLineGetFlag(Package, L"-c") && ShellCommandLineGetCount(Package)>1) + ||(ShellCommandLineGetFlag(Package, L"-r") && ShellCommandLineGetCount(Package)>2) + ||(ShellCommandLineGetFlag(Package, L"-r") && ShellCommandLineGetFlag(Package, L"-c") ) + ){ + // + // error for too many parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"connect"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-c")) { + // + // do the conin and conout from EFI variables + // if the first fails dont 'loose' the error + // + Status = ShellConnectFromDevPaths(L"ConInDev"); + if (EFI_ERROR(Status)) { + ShellConnectFromDevPaths(L"ConOutDev"); + } else { + Status = ShellConnectFromDevPaths(L"ConOutDev"); + } + if (EFI_ERROR(Status)) { + ShellConnectFromDevPaths(L"ErrOutDev"); + } else { + Status = ShellConnectFromDevPaths(L"ErrOutDev"); + } + if (EFI_ERROR(Status)) { + ShellConnectFromDevPaths(L"ErrOut"); + } else { + Status = ShellConnectFromDevPaths(L"ErrOut"); + } + if (EFI_ERROR(Status)) { + ShellConnectFromDevPaths(L"ConIn"); + } else { + Status = ShellConnectFromDevPaths(L"ConIn"); + } + if (EFI_ERROR(Status)) { + ShellConnectFromDevPaths(L"ConOut"); + } else { + Status = ShellConnectFromDevPaths(L"ConOut"); + } + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_DEVICE_ERROR; + } + } else { + // + // 0, 1, or 2 specific handles and possibly recursive + // + Param1 = ShellCommandLineGetRawValue(Package, 1); + Param2 = ShellCommandLineGetRawValue(Package, 2); + Count = ShellCommandLineGetCount(Package); + + if (Param1 != NULL) { + Status = ShellConvertStringToUint64(Param1, &Intermediate, TRUE, FALSE); + Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param1); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + Handle1 = NULL; + } + + if (Param2 != NULL) { + Status = ShellConvertStringToUint64(Param2, &Intermediate, TRUE, FALSE); + Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param2); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + Handle2 = NULL; + } + + if (ShellStatus == SHELL_SUCCESS) { + if (Param1 != NULL && Handle1 == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param1); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (Param2 != NULL && Handle2 == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param2); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (Handle2 != NULL && Handle1 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param2); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ConvertAndConnectControllers(Handle1, Handle2, ShellCommandLineGetFlag(Package, L"-r"), (BOOLEAN)(Count!=0)); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CONNECT_NONE), gShellDriver1HiiHandle); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } + } + + ShellCommandLineFreeVarList (Package); + } + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c new file mode 100644 index 0000000..f673b29 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c @@ -0,0 +1,277 @@ +/** @file + Main file for DevTree shell Driver1 function. + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-d", TypeFlag}, + {L"-l", TypeValue}, + {NULL, TypeMax} + }; + +/** + Display a tree starting from this handle. + + @param[in] TheHandle The handle to start with. + @param[in] Lang Optionally, a UEFI defined language code. + @param[in] UseDevPaths TRUE to display info from DevPath as identifiers. + FALSE will use component name protocol instead. + @param[in] IndentCharCount How many characters to indent (allows for recursion). + @param[in] HiiString The string from HII to use for output. + + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +DoDevTreeForHandle( + IN CONST EFI_HANDLE TheHandle, + IN CONST CHAR8 *Lang OPTIONAL, + IN CONST BOOLEAN UseDevPaths, + IN CONST UINTN IndentCharCount, + IN CONST CHAR16 *HiiString + ) +{ + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + CHAR16 *FormatString; + CHAR16 *Name; + EFI_HANDLE *ChildHandleBuffer; + UINTN ChildCount; + UINTN LoopVar; + + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + Name = NULL; + ChildHandleBuffer = NULL; + ChildCount = 0; + + ASSERT (TheHandle != NULL); + ASSERT (HiiString != NULL); + + if (ShellGetExecutionBreakFlag()) { + ShellStatus = SHELL_ABORTED; + return ShellStatus; + } + + // + // We want controller handles. they will not have LoadedImage or DriverBinding (or others...) + // + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiDriverBindingProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return SHELL_SUCCESS; + } + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return SHELL_SUCCESS; + } + + FormatString = AllocateZeroPool(StrSize(HiiString) + (10)*sizeof(FormatString[0])); + if (FormatString == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + + // + // we generate the format string on the fly so that we can control the + // number of space characters that the first (empty) string has. this + // handles the indenting. + // + + UnicodeSPrint(FormatString, StrSize(HiiString) + (10)*sizeof(FormatString[0]), L"%%%ds %s", IndentCharCount, HiiString); + gEfiShellProtocol->GetDeviceName((EFI_HANDLE)TheHandle, !UseDevPaths?EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH:EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Lang, &Name); + // + // print out the information for ourselves + // + ShellPrintEx( + -1, + -1, + FormatString, + L"", + ConvertHandleToHandleIndex(TheHandle), + Name==NULL?L"Unknown":Name); + + FreePool(FormatString); + if (Name != NULL) { + FreePool(Name); + } + + // + // recurse on each child handle with IndentCharCount + 2 + // + ParseHandleDatabaseForChildControllers(TheHandle, &ChildCount, &ChildHandleBuffer); + for (LoopVar = 0 ; LoopVar < ChildCount && ShellStatus == SHELL_SUCCESS; LoopVar++){ + ShellStatus = DoDevTreeForHandle(ChildHandleBuffer[LoopVar], Lang, UseDevPaths, IndentCharCount+2, HiiString); + if (ShellStatus == SHELL_ABORTED) { + break; + } + } + + if (ChildHandleBuffer != NULL) { + FreePool(ChildHandleBuffer); + } + + return (ShellStatus); +} + +/** + Function for 'devtree' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDevTree ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR8 *Language; + CONST CHAR16 *Lang; + CHAR16 *HiiString; + UINTN LoopVar; + EFI_HANDLE TheHandle; + BOOLEAN FlagD; + UINT64 Intermediate; + UINTN ParentControllerHandleCount; + EFI_HANDLE *ParentControllerHandleBuffer; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Language = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devtree", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devtree"); + ShellCommandLineFreeVarList (Package); + return (SHELL_INVALID_PARAMETER); + } + Lang = ShellCommandLineGetValue(Package, L"-l"); + if (Lang != NULL) { + Language = AllocateZeroPool(StrSize(Lang)); + AsciiSPrint(Language, StrSize(Lang), "%S", Lang); + } else if (!ShellCommandLineGetFlag(Package, L"-l")){ + ASSERT(Language == NULL); +// Language = AllocateZeroPool(10); +// AsciiSPrint(Language, 10, "en-us"); + } else { + ASSERT(Language == NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devtree", L"-l"); + ShellCommandLineFreeVarList (Package); + return (SHELL_INVALID_PARAMETER); + } + FlagD = ShellCommandLineGetFlag(Package, L"-d"); + + Lang = ShellCommandLineGetRawValue(Package, 1); + HiiString = HiiGetString(gShellDriver1HiiHandle, STRING_TOKEN (STR_DEV_TREE_OUTPUT), Language); + + if (Lang == NULL) { + for (LoopVar = 1 ; ; LoopVar++){ + TheHandle = ConvertHandleIndexToHandle(LoopVar); + if (TheHandle == NULL){ + break; + } + + // + // Skip handles that do not have device path protocol + // + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiDevicePathProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Skip handles that do have parents + // + ParentControllerHandleBuffer = NULL; + Status = PARSE_HANDLE_DATABASE_PARENTS ( + TheHandle, + &ParentControllerHandleCount, + &ParentControllerHandleBuffer + ); + SHELL_FREE_NON_NULL (ParentControllerHandleBuffer); + if (ParentControllerHandleCount > 0) { + continue; + } + + // + // Start a devtree from TheHandle that has a device path and no parents + // + ShellStatus = DoDevTreeForHandle(TheHandle, Language, FlagD, 0, HiiString); + } + } else { + Status = ShellConvertStringToUint64(Lang, &Intermediate, TRUE, FALSE); + if (EFI_ERROR(Status) || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"devtree", Lang); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellStatus = DoDevTreeForHandle(ConvertHandleIndexToHandle((UINTN)Intermediate), Language, FlagD, 0, HiiString); + } + } + + if (HiiString != NULL) { + FreePool(HiiString); + } + SHELL_FREE_NON_NULL(Language); + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c new file mode 100644 index 0000000..82f7d8c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c @@ -0,0 +1,269 @@ +/** @file + Main file for devices shell Driver1 function. + + (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +/** + Get lots of info about a device from its handle. + + @param[in] TheHandle The device handle to get info on. + @param[in, out] Type On successful return R, B, or D (root, bus, or + device) will be placed in this buffer. + @param[in, out] Cfg On successful return this buffer will be + TRUE if the handle has configuration, FALSE + otherwise. + @param[in, out] Diag On successful return this buffer will be + TRUE if the handle has disgnostics, FALSE + otherwise. + @param[in, out] Parents On successful return this buffer will be + contain the number of parent handles. + @param[in, out] Devices On successful return this buffer will be + contain the number of devices controlled. + @param[in, out] Children On successful return this buffer will be + contain the number of child handles. + @param[out] Name The pointer to a buffer that will be allocated + and contain the string name of the handle. + The caller must free this memory. + @param[in] Language The language code as defined by the UEFI spec. + + @retval EFI_SUCCESS The info is there. + @retval EFI_INVALID_PARAMETER A parameter was invalid. +**/ +EFI_STATUS +GetDeviceHandleInfo ( + IN EFI_HANDLE TheHandle, + IN OUT CHAR16 *Type, + IN OUT BOOLEAN *Cfg, + IN OUT BOOLEAN *Diag, + IN OUT UINTN *Parents, + IN OUT UINTN *Devices, + IN OUT UINTN *Children, + OUT CHAR16 **Name, + IN CONST CHAR8 *Language + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN Count; + + if (TheHandle == NULL + || Type == NULL + || Cfg == NULL + || Diag == NULL + || Parents == NULL + || Devices == NULL + || Children == NULL + || Name == NULL ) { + return (EFI_INVALID_PARAMETER); + } + + *Cfg = FALSE; + *Diag = FALSE; + *Children = 0; + *Parents = 0; + *Devices = 0; + *Type = L' '; + *Name = CHAR_NULL; + HandleBuffer = NULL; + Status = EFI_SUCCESS; + + gEfiShellProtocol->GetDeviceName(TheHandle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, Name); + + Status = ParseHandleDatabaseForChildControllers(TheHandle, Children, NULL); +// if (!EFI_ERROR(Status)) { + Status = PARSE_HANDLE_DATABASE_PARENTS(TheHandle, Parents, NULL); + if (/*!EFI_ERROR(Status) && */Parents != NULL && Children != NULL) { + if (*Parents == 0) { + *Type = L'R'; + } else if (*Children > 0) { + *Type = L'B'; + } else { + *Type = L'D'; + } + } +// } + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS(TheHandle, Devices, &HandleBuffer); + if (!EFI_ERROR(Status) && Devices != NULL && HandleBuffer != NULL) { + for (Count = 0 ; Count < *Devices ; Count++) { + if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + *Cfg = TRUE; + } + if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + *Diag = TRUE; + } + if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + *Diag = TRUE; + } + } + SHELL_FREE_NON_NULL(HandleBuffer); + } + + return (Status); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-sfo", TypeFlag}, + {L"-l", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'devices' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDevices ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR8 *Language; + EFI_HANDLE *HandleList; + EFI_HANDLE *HandleListWalker; + CHAR16 Type; + BOOLEAN Cfg; + BOOLEAN Diag; + UINTN Parents; + UINTN Devices; + UINTN Children; + CHAR16 *Name; + CONST CHAR16 *Lang; + BOOLEAN SfoFlag; + + ShellStatus = SHELL_SUCCESS; + Language = NULL; + SfoFlag = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devices", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // if more than 0 'value' parameters we have too many parameters + // + if (ShellCommandLineGetRawValue(Package, 1) != NULL){ + // + // error for too many parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devices"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // get the language if necessary + // + Lang = ShellCommandLineGetValue(Package, L"-l"); + if (Lang != NULL) { + Language = AllocateZeroPool(StrSize(Lang)); + AsciiSPrint(Language, StrSize(Lang), "%S", Lang); + } else if (!ShellCommandLineGetFlag(Package, L"-l")){ + ASSERT(Language == NULL); +// Language = AllocateZeroPool(10); +// AsciiSPrint(Language, 10, "en-us"); + } else { + ASSERT(Language == NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devices", L"-l"); + ShellCommandLineFreeVarList (Package); + return (SHELL_INVALID_PARAMETER); + } + + + // + // Print Header + + // + if (ShellCommandLineGetFlag (Package, L"-sfo")) { + ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDriver1HiiHandle, L"devices"); + SfoFlag = TRUE; + } else { + ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_DEVICES_HEADER_LINES), gShellDriver1HiiHandle); + } + + // + // loop through each handle + // + HandleList = GetHandleListByProtocol(NULL); + ASSERT(HandleList != NULL); + for (HandleListWalker = HandleList + ; HandleListWalker != NULL && *HandleListWalker != NULL /*&& !EFI_ERROR(Status)*/ + ; HandleListWalker++ + ){ + + // + // get all the info on each handle + // + Name = NULL; + Status = GetDeviceHandleInfo(*HandleListWalker, &Type, &Cfg, &Diag, &Parents, &Devices, &Children, &Name, Language); + if (Name != NULL && (Parents != 0 || Devices != 0 || Children != 0)) { + ShellPrintHiiEx ( + -1, + -1, + Language, + SfoFlag?STRING_TOKEN (STR_DEVICES_ITEM_LINE_SFO):STRING_TOKEN (STR_DEVICES_ITEM_LINE), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex (*HandleListWalker), + Type, + Cfg?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'), + Diag?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'), + Parents, + Devices, + Children, + Name!=NULL?Name:L""); + } + if (Name != NULL) { + FreePool(Name); + } + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + + } + + if (HandleList != NULL) { + FreePool(HandleList); + } + + } + SHELL_FREE_NON_NULL(Language); + ShellCommandLineFreeVarList (Package); + } + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c new file mode 100644 index 0000000..79417b0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c @@ -0,0 +1,1197 @@ +/** @file + Main file for Dh shell Driver1 function. + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2017 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-p", TypeValue}, + {L"-d", TypeFlag}, + {L"-v", TypeFlag}, + {L"-verbose", TypeFlag}, + {L"-sfo", TypeFlag}, + {L"-l", TypeValue}, + {NULL, TypeMax} + }; + +STATIC CONST EFI_GUID *UefiDriverModelProtocolsGuidArray[] = { + &gEfiDriverBindingProtocolGuid, + &gEfiPlatformDriverOverrideProtocolGuid, + &gEfiBusSpecificDriverOverrideProtocolGuid, + &gEfiDriverDiagnosticsProtocolGuid, + &gEfiDriverDiagnostics2ProtocolGuid, + &gEfiComponentNameProtocolGuid, + &gEfiComponentName2ProtocolGuid, + &gEfiPlatformToDriverConfigurationProtocolGuid, + &gEfiDriverSupportedEfiVersionProtocolGuid, + &gEfiDriverFamilyOverrideProtocolGuid, + &gEfiDriverHealthProtocolGuid, + &gEfiLoadedImageProtocolGuid, + NULL +}; + +UINTN mGuidDataLen[] = {8, 4, 4, 4, 12}; +/** + Function to determine if the string can convert to a GUID. + The string must be restricted as "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format. + + @param[in] String The string to test. + + @retval TRUE The string can convert to a GUID. + @retval FALSE The string can't convert to a GUID. +**/ +BOOLEAN +IsValidGuidString( + IN CONST CHAR16 *String + ) +{ + CONST CHAR16 *Walker; + CONST CHAR16 *PrevWalker; + UINTN Index; + + if (String == NULL) { + return FALSE; + } + + Walker = String; + PrevWalker = String; + Index = 0; + + while (Walker != NULL && *Walker != CHAR_NULL) { + if ( (*Walker >= '0' && *Walker <= '9') || + (*Walker >= 'a' && *Walker <= 'f') || + (*Walker >= 'A' && *Walker <= 'F') + ) { + Walker++; + } else { + if (*Walker == L'-' && (((UINTN)Walker - (UINTN)PrevWalker) / sizeof (CHAR16)) == mGuidDataLen[Index]) { + Walker++; + PrevWalker = Walker; + Index++; + } else { + return FALSE; + } + } + } + + if ((((UINTN)Walker - (UINTN)PrevWalker) / sizeof (CHAR16)) == mGuidDataLen[Index]) { + return TRUE; + } else { + return FALSE; + } +} + +/** + Convert a hex-character to decimal 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[in] Char The character to convert. + + @retval The numerical value converted. +**/ +UINTN +HexCharToDecimal( + IN CHAR16 Char + ) +{ + if (Char >= '0' && Char <= '9') { + return Char - L'0'; + } else if (Char >= 'a' && Char <= 'f') { + return Char - L'a' + 10; + } else { + return Char - L'A' + 10; + } +} + +/** + Function try to convert a string to GUID format. + + @param[in] String The string will be converted. + @param[out] Guid Save the result convert from string. + + @retval EFI_SUCCESS The string was successfully converted to a GUID. + @retval EFI_UNSUPPORTED The input string is not in registry format. +**/ +EFI_STATUS +ConvertStrToGuid( + IN CONST CHAR16 *String, + OUT GUID *Guid + ) +{ + CONST CHAR16 *Walker; + UINT8 TempValue; + UINTN Index; + + if (String == NULL || !IsValidGuidString (String)) { + return EFI_UNSUPPORTED; + } + + Index = 0; + + Walker = String; + Guid->Data1 = (UINT32)StrHexToUint64 (Walker); + + Walker += 9; + Guid->Data2 = (UINT16)StrHexToUint64 (Walker); + + Walker += 5; + Guid->Data3 = (UINT16)StrHexToUint64 (Walker); + + Walker += 5; + while (Walker != NULL && *Walker != CHAR_NULL) { + if (*Walker == L'-') { + Walker++; + } else { + TempValue = (UINT8)HexCharToDecimal (*Walker); + TempValue = (UINT8)LShiftU64 (TempValue, 4); + Walker++; + + TempValue += (UINT8)HexCharToDecimal (*Walker); + Walker++; + + Guid->Data4[Index] = TempValue; + Index++; + } + } + + return EFI_SUCCESS; +} + +/** + Get the name of a driver by it's handle. + + If a name is found the memory must be callee freed. + + @param[in] TheHandle The driver's handle. + @param[in] Language The language to use. + @param[in] NameFound Upon a successful return the name found. + + @retval EFI_SUCCESS The name was found. +**/ +EFI_STATUS +GetDriverName ( + IN EFI_HANDLE TheHandle, + IN CONST CHAR8 *Language, + IN CHAR16 **NameFound + ) +{ + CHAR8 *Lang; + EFI_STATUS Status; + EFI_COMPONENT_NAME2_PROTOCOL *CompName2; + CHAR16 *NameToReturn; + // + // Go through those handles until we get one that passes for GetComponentName + // + Status = gBS->OpenProtocol( + TheHandle, + &gEfiComponentName2ProtocolGuid, + (VOID**)&CompName2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + Status = gBS->OpenProtocol( + TheHandle, + &gEfiComponentNameProtocolGuid, + (VOID**)&CompName2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + } + + if (EFI_ERROR(Status)) { + return (EFI_NOT_FOUND); + } + Lang = GetBestLanguageForDriver (CompName2->SupportedLanguages, Language, FALSE); + Status = CompName2->GetDriverName(CompName2, Lang, &NameToReturn); + FreePool(Lang); + + if (!EFI_ERROR(Status) && NameToReturn != NULL) { + *NameFound = NULL; + StrnCatGrow(NameFound, NULL, NameToReturn, 0); + } + return (Status); +} + +/** + Discover if a protocol guid is one of the UEFI Driver Model Protocols. + + @param[in] Guid The guid to test. + + @retval TRUE The guid does represent a driver model protocol. + @retval FALSE The guid does not represent a driver model protocol. +**/ +BOOLEAN +IsDriverProt ( + IN CONST EFI_GUID *Guid + ) +{ + CONST EFI_GUID **GuidWalker; + BOOLEAN GuidFound; + GuidFound = FALSE; + for (GuidWalker = UefiDriverModelProtocolsGuidArray + ; GuidWalker != NULL && *GuidWalker != NULL + ; GuidWalker++ + ){ + if (CompareGuid(*GuidWalker, Guid)) { + GuidFound = TRUE; + break; + } + } + return (GuidFound); +} + +/** + Get information for a handle. + + @param[in] TheHandle The handles to show info on. + @param[in] Language Language string per UEFI specification. + @param[in] Separator Separator string between information blocks. + @param[in] Verbose TRUE for extra info, FALSE otherwise. + @param[in] ExtraInfo TRUE for extra info, FALSE otherwise. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid. +**/ +CHAR16* +GetProtocolInfoString( + IN CONST EFI_HANDLE TheHandle, + IN CONST CHAR8 *Language, + IN CONST CHAR16 *Separator, + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN ExtraInfo + ) +{ + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + UINTN ProtocolIndex; + EFI_STATUS Status; + CHAR16 *RetVal; + UINTN Size; + CHAR16 *Temp; + CHAR16 GuidStr[40]; + VOID *Instance; + CHAR16 InstanceStr[17]; + + ProtocolGuidArray = NULL; + RetVal = NULL; + Size = 0; + + Status = gBS->ProtocolsPerHandle ( + TheHandle, + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + Temp = GetStringNameFromGuid(ProtocolGuidArray[ProtocolIndex], Language); + ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL)); + if (Size != 0) { + StrnCatGrow(&RetVal, &Size, Separator, 0); + } + StrnCatGrow(&RetVal, &Size, L"%H", 0); + if (Temp == NULL) { + UnicodeSPrint (GuidStr, sizeof (GuidStr), L"%g", ProtocolGuidArray[ProtocolIndex]); + StrnCatGrow (&RetVal, &Size, GuidStr, 0); + } else { + StrnCatGrow(&RetVal, &Size, Temp, 0); + FreePool(Temp); + } + StrnCatGrow(&RetVal, &Size, L"%N", 0); + + if(Verbose) { + Status = gBS->HandleProtocol (TheHandle, ProtocolGuidArray[ProtocolIndex], &Instance); + if (!EFI_ERROR (Status)) { + StrnCatGrow (&RetVal, &Size, L"(%H", 0); + UnicodeSPrint (InstanceStr, sizeof (InstanceStr), L"%x", Instance); + StrnCatGrow (&RetVal, &Size, InstanceStr, 0); + StrnCatGrow (&RetVal, &Size, L"%N)", 0); + } + } + + if (ExtraInfo) { + Temp = GetProtocolInformationDump(TheHandle, ProtocolGuidArray[ProtocolIndex], Verbose); + if (Temp != NULL) { + ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL)); + if (!Verbose) { + StrnCatGrow(&RetVal, &Size, L"(", 0); + StrnCatGrow(&RetVal, &Size, Temp, 0); + StrnCatGrow(&RetVal, &Size, L")", 0); + } else { + StrnCatGrow(&RetVal, &Size, Separator, 0); + StrnCatGrow(&RetVal, &Size, Temp, 0); + } + FreePool(Temp); + } + } + } + } + + SHELL_FREE_NON_NULL(ProtocolGuidArray); + + if (RetVal == NULL) { + return (NULL); + } + + ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL)); + StrnCatGrow(&RetVal, &Size, Separator, 0); + return (RetVal); +} + +/** + Gets the name of the loaded image. + + @param[in] TheHandle The handle of the driver to get info on. + @param[out] Name The pointer to the pointer. Valid upon a successful return. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +GetDriverImageName ( + IN EFI_HANDLE TheHandle, + OUT CHAR16 **Name + ) +{ + // get loaded image and devicepathtotext on image->Filepath + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (TheHandle == NULL || Name == NULL) { + return (EFI_INVALID_PARAMETER); + } + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + return (Status); + } + DevicePath = LoadedImage->FilePath; + *Name = ConvertDevicePathToText(DevicePath, TRUE, TRUE); + return (EFI_SUCCESS); +} + +/** + Display driver model information for a given handle. + + @param[in] Handle The handle to display info on. + @param[in] BestName Use the best name? + @param[in] Language The language to output in. +**/ +EFI_STATUS +DisplayDriverModelHandle ( + IN EFI_HANDLE Handle, + IN BOOLEAN BestName, + IN CONST CHAR8 *Language OPTIONAL + ) +{ + EFI_STATUS Status; + BOOLEAN ConfigurationStatus; + BOOLEAN DiagnosticsStatus; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + UINTN ParentControllerHandleCount; + EFI_HANDLE *ParentControllerHandleBuffer; + UINTN ChildControllerHandleCount; + EFI_HANDLE *ChildControllerHandleBuffer; + CHAR16 *TempStringPointer; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Index; + CHAR16 *DriverName; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + UINTN NumberOfChildren; + UINTN HandleIndex; + UINTN ControllerHandleCount; + EFI_HANDLE *ControllerHandleBuffer; + UINTN ChildIndex; + BOOLEAN Image; + + DriverName = NULL; + + // + // See if Handle is a device handle and display its details. + // + DriverBindingHandleBuffer = NULL; + Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS ( + Handle, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + + ParentControllerHandleBuffer = NULL; + Status = PARSE_HANDLE_DATABASE_PARENTS ( + Handle, + &ParentControllerHandleCount, + &ParentControllerHandleBuffer + ); + + ChildControllerHandleBuffer = NULL; + Status = ParseHandleDatabaseForChildControllers ( + Handle, + &ChildControllerHandleCount, + &ChildControllerHandleBuffer + ); + + DiagnosticsStatus = FALSE; + ConfigurationStatus = FALSE; + + if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + ConfigurationStatus = TRUE; + } + if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfiguration2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + ConfigurationStatus = TRUE; + } + if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + DiagnosticsStatus = TRUE; + } + if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + DiagnosticsStatus = TRUE; + } + + Status = EFI_SUCCESS; + + if (DriverBindingHandleCount > 0 || ParentControllerHandleCount > 0 || ChildControllerHandleCount > 0) { + + + + DevicePath = NULL; + TempStringPointer = NULL; + Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID**)&DevicePath); + + Status = gEfiShellProtocol->GetDeviceName(Handle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER1), gShellDriver1HiiHandle, TempStringPointer!=NULL?TempStringPointer:L""); + SHELL_FREE_NON_NULL(TempStringPointer); + + TempStringPointer = ConvertDevicePathToText(DevicePath, TRUE, FALSE); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER2), + gShellDriver1HiiHandle, + TempStringPointer!=NULL?TempStringPointer:L"", + ParentControllerHandleCount == 0?L"ROOT":(ChildControllerHandleCount > 0)?L"BUS":L"DEVICE", + ConfigurationStatus?L"YES":L"NO", + DiagnosticsStatus?L"YES":L"NO" + ); + + SHELL_FREE_NON_NULL(TempStringPointer); + + if (DriverBindingHandleCount == 0) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER3), + gShellDriver1HiiHandle, + L"" + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER3), + gShellDriver1HiiHandle, + L"" + ); + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + Image = FALSE; + Status = GetDriverName ( + DriverBindingHandleBuffer[Index], + Language, + &DriverName + ); + if (EFI_ERROR (Status)) { + Status = GetDriverImageName ( + DriverBindingHandleBuffer[Index], + &DriverName + ); + if (EFI_ERROR (Status)) { + DriverName = NULL; + } + } + + if (Image) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER4A), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]), + DriverName!=NULL?DriverName:L"" + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER4B), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]), + DriverName!=NULL?DriverName:L"" + ); + } + SHELL_FREE_NON_NULL(DriverName); + } + } + + if (ParentControllerHandleCount == 0) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER5), + gShellDriver1HiiHandle, + L"" + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER5), + gShellDriver1HiiHandle, + L"" + ); + for (Index = 0; Index < ParentControllerHandleCount; Index++) { + Status = gEfiShellProtocol->GetDeviceName(ParentControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER5B), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex (ParentControllerHandleBuffer[Index]), + TempStringPointer!=NULL?TempStringPointer:L"" + ); + SHELL_FREE_NON_NULL(TempStringPointer); + } + } + + if (ChildControllerHandleCount == 0) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER6), + gShellDriver1HiiHandle, + L"" + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER6), + gShellDriver1HiiHandle, + L"" + ); + for (Index = 0; Index < ChildControllerHandleCount; Index++) { + Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex (ChildControllerHandleBuffer[Index]), + TempStringPointer!=NULL?TempStringPointer:L"" + ); + SHELL_FREE_NON_NULL(TempStringPointer); + } + } + } + + SHELL_FREE_NON_NULL(DriverBindingHandleBuffer); + + SHELL_FREE_NON_NULL(ParentControllerHandleBuffer); + + SHELL_FREE_NON_NULL(ChildControllerHandleBuffer); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // See if Handle is a driver binding handle and display its details. + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + NumberOfChildren = 0; + ControllerHandleBuffer = NULL; + Status = PARSE_HANDLE_DATABASE_DEVICES ( + Handle, + &ControllerHandleCount, + &ControllerHandleBuffer + ); + if (ControllerHandleCount > 0) { + for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) { + Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN ( + Handle, + ControllerHandleBuffer[HandleIndex], + &ChildControllerHandleCount, + NULL + ); + NumberOfChildren += ChildControllerHandleCount; + } + } + + Status = GetDriverName (Handle, Language, &DriverName); + if (EFI_ERROR (Status)) { + DriverName = NULL; + } + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER7), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(Handle), + DriverName!=NULL?DriverName:L"" + ); + SHELL_FREE_NON_NULL(DriverName); + Status = GetDriverImageName ( + Handle, + &DriverName + ); + if (EFI_ERROR (Status)) { + DriverName = NULL; + } + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER7B), + gShellDriver1HiiHandle, + DriverName!=NULL?DriverName:L"" + ); + SHELL_FREE_NON_NULL(DriverName); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER8), + gShellDriver1HiiHandle, + DriverBinding->Version, + NumberOfChildren > 0?L"Bus":ControllerHandleCount > 0?L"Device":L"", + ConfigurationStatus?L"YES":L"NO", + DiagnosticsStatus?L"YES":L"NO" + ); + + if (ControllerHandleCount == 0) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER9), + gShellDriver1HiiHandle, + L"None" + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER9), + gShellDriver1HiiHandle, + L"" + ); + for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) { + Status = gEfiShellProtocol->GetDeviceName(ControllerHandleBuffer[HandleIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER9B), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(ControllerHandleBuffer[HandleIndex]), + TempStringPointer!=NULL?TempStringPointer:L"" + ); + SHELL_FREE_NON_NULL(TempStringPointer); + + Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN ( + Handle, + ControllerHandleBuffer[HandleIndex], + &ChildControllerHandleCount, + &ChildControllerHandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (ChildIndex = 0; ChildIndex < ChildControllerHandleCount; ChildIndex++) { + Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[ChildIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_DRIVER6C), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(ChildControllerHandleBuffer[ChildIndex]), + TempStringPointer!=NULL?TempStringPointer:L"" + ); + SHELL_FREE_NON_NULL(TempStringPointer); + } + + SHELL_FREE_NON_NULL (ChildControllerHandleBuffer); + } + } + + SHELL_FREE_NON_NULL (ControllerHandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + Display information for a handle. + + @param[in] TheHandle The handles to show info on. + @param[in] Verbose TRUE for extra info, FALSE otherwise. + @param[in] Sfo TRUE to output in standard format output (spec). + @param[in] Language Language string per UEFI specification. + @param[in] DriverInfo TRUE to show all info about the handle. + @param[in] Multiple TRUE indicates more than will be output, + FALSE for a single one. +**/ +VOID +DoDhByHandle( + IN CONST EFI_HANDLE TheHandle, + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Sfo, + IN CONST CHAR8 *Language, + IN CONST BOOLEAN DriverInfo, + IN CONST BOOLEAN Multiple + ) +{ + CHAR16 *ProtocolInfoString; + + ProtocolInfoString = NULL; + + if (!Sfo) { + if (Multiple) { + ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L" ", Verbose, TRUE); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(TheHandle), + ProtocolInfoString==NULL?L"":ProtocolInfoString + ); + } else { + ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, Verbose ? L"\r\n" : L" ", Verbose, TRUE); + if (Verbose) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_SINGLE), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(TheHandle), + TheHandle, + ProtocolInfoString==NULL?L"":ProtocolInfoString + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_SINGLE_D), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(TheHandle), + ProtocolInfoString==NULL?L"":ProtocolInfoString + ); + } + } + + if (DriverInfo) { + DisplayDriverModelHandle ((EFI_HANDLE)TheHandle, TRUE, Language); + } + } else { + ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L";", FALSE, FALSE); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DH_OUTPUT_SFO), + gShellDriver1HiiHandle, + Multiple ?L"HandlesInfo":L"HandleInfo", + L"DriverName", + L"ControllerName", + ConvertHandleToHandleIndex(TheHandle), + L"DevPath", + ProtocolInfoString==NULL?L"":ProtocolInfoString + ); + } + + if (ProtocolInfoString != NULL) { + FreePool(ProtocolInfoString); + } +} + +/** + Display information for all handles on a list. + + @param[in] HandleList The NULL-terminated list of handles. + @param[in] Verbose TRUE for extra info, FALSE otherwise. + @param[in] Sfo TRUE to output in standard format output (spec). + @param[in] Language Language string per UEFI specification. + @param[in] DriverInfo TRUE to show all info about the handle. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_ABORTED The operation was aborted. +**/ +SHELL_STATUS +DoDhForHandleList( + IN CONST EFI_HANDLE *HandleList, + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Sfo, + IN CONST CHAR8 *Language, + IN CONST BOOLEAN DriverInfo + ) +{ + CONST EFI_HANDLE *HandleWalker; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + for (HandleWalker = HandleList; HandleWalker != NULL && *HandleWalker != NULL; HandleWalker++) { + DoDhByHandle (*HandleWalker, Verbose, Sfo, Language, DriverInfo, TRUE); + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + } + return (ShellStatus); +} + +/** + Display information for a GUID of protocol. + + @param[in] Guid The pointer to the name of the protocol. + @param[in] Verbose TRUE for extra info, FALSE otherwise. + @param[in] Sfo TRUE to output in standard format output (spec). + @param[in] Language Language string per UEFI specification. + @param[in] DriverInfo TRUE to show all info about the handle. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_NOT_FOUND The GUID was not found. + @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid. +**/ +SHELL_STATUS +DoDhByProtocolGuid( + IN CONST GUID *Guid, + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Sfo, + IN CONST CHAR8 *Language, + IN CONST BOOLEAN DriverInfo + ) +{ + CHAR16 *Name; + SHELL_STATUS ShellStatus; + EFI_HANDLE *HandleList; + + if (!Sfo) { + if (Guid == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_ALL_HEADER), gShellDriver1HiiHandle); + } else { + Name = GetStringNameFromGuid (Guid, NULL); + if (Name == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_GUID_HEADER), gShellDriver1HiiHandle, Guid); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_NAME_HEADER), gShellDriver1HiiHandle, Name); + } + } + } + HandleList = GetHandleListByProtocol(Guid); + ShellStatus = DoDhForHandleList(HandleList, Verbose, Sfo, Language, DriverInfo); + SHELL_FREE_NON_NULL(HandleList); + + return ShellStatus; +} + +/** + Function to determine use which method to print information. + If Protocol is NULL, The function will print all information. + + @param[in] Protocol The pointer to the name or GUID of protocol or NULL. + @param[in] Verbose TRUE for extra info, FALSE otherwise. + @param[in] Sfo TRUE to output in standard format output (spec). + @param[in] Language Language string per UEFI specification. + @param[in] DriverInfo TRUE to show all info about the handle. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_NOT_FOUND The protocol was not found. + @retval SHELL_INVALID_PARAMETER Protocol is invalid parameter. +**/ +SHELL_STATUS +DoDhByProtocol ( + IN CONST CHAR16 *Protocol, + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Sfo, + IN CONST CHAR8 *Language, + IN CONST BOOLEAN DriverInfo + ) +{ + EFI_GUID Guid; + EFI_GUID *GuidPtr; + EFI_STATUS Status; + + if (Protocol == NULL) { + return DoDhByProtocolGuid (NULL, Verbose, Sfo, Language, DriverInfo); + } else { + Status = ConvertStrToGuid (Protocol, &Guid); + if (!EFI_ERROR (Status)) { + GuidPtr = &Guid; + } else { + // + // Protocol is a Name, convert it to GUID + // + Status = GetGuidFromStringName (Protocol, Language, &GuidPtr); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_NAME_FOUND), gShellDriver1HiiHandle, Protocol); + return (SHELL_NOT_FOUND); + } + } + + return DoDhByProtocolGuid (GuidPtr, Verbose, Sfo, Language, DriverInfo); + } +} + +/** + Function to display decode information by Protocol. + The parameter Protocol is either a GUID or the name of protocol. + If the parameter Protocol is NULL, the function will print all + decode information. + + @param[in] Protocol The pointer to the name or GUID of protocol. + @param[in] Language Language string per UEFI specification. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_OUT_OT_RESOURCES A memory allocation failed. +**/ +SHELL_STATUS +DoDecodeByProtocol( + IN CONST CHAR16 *Protocol, + IN CONST CHAR8 *Language + ) +{ + EFI_STATUS Status; + EFI_GUID *Guids; + EFI_GUID Guid; + UINTN Counts; + UINTN Index; + CHAR16 *Name; + + if (Protocol == NULL) { + Counts = 0; + Status = GetAllMappingGuids (NULL, &Counts); + if (Status == EFI_BUFFER_TOO_SMALL) { + Guids = AllocatePool (Counts * sizeof(EFI_GUID)); + if (Guids == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + + Status = GetAllMappingGuids (Guids, &Counts); + if (Status == EFI_SUCCESS) { + for (Index = 0; Index < Counts; Index++) { + Name = GetStringNameFromGuid (&Guids[Index], Language); + if (Name != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DECODE), gShellDriver1HiiHandle, Name, &Guids[Index]); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_GUID_FOUND), gShellDriver1HiiHandle, &Guids[Index]); + } + SHELL_FREE_NON_NULL (Name); + } + } + FreePool (Guids); + } + } else { + if (ConvertStrToGuid (Protocol, &Guid) == EFI_SUCCESS) { + Name = GetStringNameFromGuid (&Guid, Language); + if (Name != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DECODE), gShellDriver1HiiHandle, Name, &Guid); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_GUID_FOUND), gShellDriver1HiiHandle, &Guid); + } + SHELL_FREE_NON_NULL(Name); + } else { + Status = GetGuidFromStringName (Protocol, Language, &Guids); + if (Status == EFI_SUCCESS) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DECODE), gShellDriver1HiiHandle, Protocol, Guids); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DH_NO_NAME_FOUND), gShellDriver1HiiHandle, Protocol); + } + } + } + + return SHELL_SUCCESS; +} + +/** + Function for 'dh' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDh ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR8 *Language; + CONST CHAR16 *Lang; + CONST CHAR16 *RawValue; + CONST CHAR16 *ProtocolVal; + BOOLEAN SfoFlag; + BOOLEAN DriverFlag; + BOOLEAN VerboseFlag; + UINT64 Intermediate; + EFI_HANDLE Handle; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Language = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"dh", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh"); + ShellCommandLineFreeVarList (Package); + return (SHELL_INVALID_PARAMETER); + } + + if (ShellCommandLineGetFlag(Package, L"-l")) { + Lang = ShellCommandLineGetValue(Package, L"-l"); + if (Lang != NULL) { + Language = AllocateZeroPool(StrSize(Lang)); + AsciiSPrint(Language, StrSize(Lang), "%S", Lang); + } else { + ASSERT(Language == NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-l"); + ShellCommandLineFreeVarList(Package); + return (SHELL_INVALID_PARAMETER); + } + } else { + Language = AllocateZeroPool(10); + AsciiSPrint(Language, 10, "en-us"); + } + + SfoFlag = ShellCommandLineGetFlag (Package, L"-sfo"); + DriverFlag = ShellCommandLineGetFlag (Package, L"-d"); + VerboseFlag = (BOOLEAN)(ShellCommandLineGetFlag (Package, L"-v") || ShellCommandLineGetFlag (Package, L"-verbose")); + RawValue = ShellCommandLineGetRawValue (Package, 1); + ProtocolVal = ShellCommandLineGetValue (Package, L"-p"); + + if (RawValue == NULL) { + if (ShellCommandLineGetFlag (Package, L"-p") && (ProtocolVal == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-p"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Print information by protocol, The ProtocolVal maybe is name or GUID or NULL. + // + ShellStatus = DoDhByProtocol (ProtocolVal, VerboseFlag, SfoFlag, Language, DriverFlag); + } + } else if ((RawValue != NULL) && + (gUnicodeCollation->StriColl(gUnicodeCollation, L"decode", (CHAR16 *) RawValue) == 0)) { + if (ShellCommandLineGetFlag (Package, L"-p") && (ProtocolVal == NULL)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-p"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Print decode informatino by protocol. + // + ShellStatus = DoDecodeByProtocol (ProtocolVal, Language); + } + } else { + if (ShellCommandLineGetFlag (Package, L"-p")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64 (RawValue, &Intermediate, TRUE, FALSE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"dh", RawValue); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Handle = ConvertHandleIndexToHandle ((UINTN) Intermediate); + if (Handle == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"dh", RawValue); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Print information by handle. + // + DoDhByHandle (Handle, VerboseFlag, SfoFlag, Language, DriverFlag, FALSE); + } + } + } + } + + ShellCommandLineFreeVarList (Package); + SHELL_FREE_NON_NULL(Language); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c new file mode 100644 index 0000000..178ab49 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c @@ -0,0 +1,204 @@ +/** @file + Main file for Disconnect shell Driver1 function. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-r", TypeFlag}, + {L"-nc", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Disconnect everything. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +DisconnectAll( + VOID + ) +{ + // + // Stolen from UEFI 2.3 spec (May 2009 version) + // Pages 171/172 + // Removed gBS local definition + // + + // + // Disconnect All Handles Example + // The following example recusively disconnects all drivers from all + // controllers in a platform. + // + EFI_STATUS Status; +// EFI_BOOT_SERVICES *gBS; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN HandleIndex; + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + Status = gBS->DisconnectController ( + HandleBuffer[HandleIndex], + NULL, + NULL + ); + } + gBS->FreePool(HandleBuffer); + // + // end of stealing + // + } + return (EFI_SUCCESS); +} + +/** + Function for 'disconnect' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDisconnect ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Param1; + CONST CHAR16 *Param2; + CONST CHAR16 *Param3; + EFI_HANDLE Handle1; + EFI_HANDLE Handle2; + EFI_HANDLE Handle3; + UINT64 Intermediate1; + UINT64 Intermediate2; + UINT64 Intermediate3; + + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"disconnect", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetFlag(Package, L"-r")){ + if (ShellCommandLineGetCount(Package) > 1){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"disconnect"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = DisconnectAll (); + // + // Reconnect all consoles if -nc is not provided + // + if (!ShellCommandLineGetFlag (Package, L"-nc")){ + ShellConnectFromDevPaths (L"ConInDev"); + ShellConnectFromDevPaths (L"ConOutDev"); + ShellConnectFromDevPaths (L"ErrOutDev"); + ShellConnectFromDevPaths (L"ErrOut"); + ShellConnectFromDevPaths (L"ConIn"); + ShellConnectFromDevPaths (L"ConOut"); + } + } + } else if (ShellCommandLineGetFlag (Package, L"-nc")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetCount(Package) > 4){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"disconnect"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // must have between 1 and 3 handles passed in ... + // + Param1 = ShellCommandLineGetRawValue(Package, 1); + Param2 = ShellCommandLineGetRawValue(Package, 2); + Param3 = ShellCommandLineGetRawValue(Package, 3); + ShellConvertStringToUint64(Param1, &Intermediate1, TRUE, FALSE); + Handle1 = Param1!=NULL?ConvertHandleIndexToHandle((UINTN)Intermediate1):NULL; + ShellConvertStringToUint64(Param2, &Intermediate2, TRUE, FALSE); + Handle2 = Param2!=NULL?ConvertHandleIndexToHandle((UINTN)Intermediate2):NULL; + ShellConvertStringToUint64(Param3, &Intermediate3, TRUE, FALSE); + Handle3 = Param3!=NULL?ConvertHandleIndexToHandle((UINTN)Intermediate3):NULL; + + if (Param1 != NULL && Handle1 == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param1); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (Param2 != NULL && Handle2 == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param2); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (Param3 != NULL && Handle3 == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param3); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (Handle2 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + ASSERT(Param2 != NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_HANDLE_NOT), gShellDriver1HiiHandle, L"disconnect", ShellStrToUintn(Param2), L"driver handle"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(Param1 != NULL); + Status = gBS->DisconnectController(Handle1, Handle2, Handle3); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_3P_RESULT), gShellDriver1HiiHandle, L"Disconnect", (UINTN)Intermediate1, (UINTN)Intermediate2, (UINTN)Intermediate3, Status); + } + } + } + } + if (ShellStatus == SHELL_SUCCESS) { + if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (Status == EFI_INVALID_PARAMETER) { + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + } + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c new file mode 100644 index 0000000..91b19c4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c @@ -0,0 +1,429 @@ +/** @file + Main file for Drivers shell Driver1 function. + + (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +#define MAX_LEN_DRIVER_NAME 35 + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-sfo", TypeFlag}, + {L"-l", TypeValue}, + {NULL, TypeMax} + }; + +/** + Get a device path (in text format) for a given handle. + + @param[in] TheHandle The handle to get the device path for. + + @retval NULL An error occured. + @return A pointer to the driver path as a string. The callee must + free this memory. +**/ +CHAR16* +GetDevicePathTextForHandle( + IN EFI_HANDLE TheHandle + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FinalPath; + CHAR16 *RetVal; + + FinalPath = NULL; + + Status = gBS->OpenProtocol ( + TheHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID**)&ImageDevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + FinalPath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath); + gBS->CloseProtocol( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + gImageHandle, + NULL); + } + gBS->CloseProtocol( + TheHandle, + &gEfiLoadedImageProtocolGuid, + gImageHandle, + NULL); + } + + if (FinalPath == NULL) { + return (NULL); + } + RetVal = gEfiShellProtocol->GetFilePathFromDevicePath(FinalPath); + if (RetVal == NULL) { + RetVal = ConvertDevicePathToText(FinalPath, TRUE, TRUE); + } + FreePool(FinalPath); + return (RetVal); +} + +/** + Determine if the given handle has Driver Configuration protocol. + + @param[in] TheHandle The handle to the driver to test. + + @retval TRUE The driver does have Driver Configuration. + @retval FALSE The driver does not have Driver Configuration. +**/ +BOOLEAN +ReturnDriverConfig( + IN CONST EFI_HANDLE TheHandle + ) +{ + EFI_STATUS Status; + Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverConfigurationProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + if (EFI_ERROR(Status)) { + return (FALSE); + } + return (TRUE); +} + +/** + Determine if the given handle has DriverDiagnostics protocol. + + @param[in] TheHandle The handle to the driver to test. + + @retval TRUE The driver does have Driver Diasgnostics. + @retval FALSE The driver does not have Driver Diagnostics. +**/ +BOOLEAN +ReturnDriverDiag( + IN CONST EFI_HANDLE TheHandle + ) +{ + EFI_STATUS Status; + Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + if (EFI_ERROR(Status)) { + Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverDiagnosticsProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + if (EFI_ERROR(Status)) { + return (FALSE); + } + } + return (TRUE); +} + +/** + Finds and returns the version of the driver specified by TheHandle. + + @param[in] TheHandle The driver handle to get the version of. + + @return The version of the driver. + @retval 0xFFFFFFFF An error ocurred. +**/ +UINT32 +ReturnDriverVersion( + IN CONST EFI_HANDLE TheHandle + ) +{ + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_STATUS Status; + UINT32 RetVal; + + RetVal = (UINT32)-1; + + Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverBindingProtocolGuid, (VOID**)&DriverBinding, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status)) { + RetVal = DriverBinding->Version; + gBS->CloseProtocol(TheHandle, &gEfiDriverBindingProtocolGuid, gImageHandle, NULL); + } + return (RetVal); +} + +/** + Get image name from Image Handle. + + @param[in] Handle Image Handle + + @return A pointer to the image name as a string. +**/ +CHAR16 * +GetImageNameFromHandle ( + IN CONST EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevPathNode; + EFI_GUID *NameGuid; + CHAR16 *ImageName; + UINTN BufferSize; + UINT32 AuthenticationStatus; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2; + + LoadedImage = NULL; + DriverBinding = NULL; + ImageName = NULL; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + Status = gBS->OpenProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID**)&LoadedImage, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + DevPathNode = LoadedImage->FilePath; + if (DevPathNode == NULL) { + return NULL; + } + while (!IsDevicePathEnd (DevPathNode)) { + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode); + if (NameGuid != NULL) { + Status = gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **)&Fv2 + ); + if (!EFI_ERROR (Status)) { + Status = Fv2->ReadSection ( + Fv2, + NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&ImageName, + &BufferSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + break; + } + ImageName = NULL; + } + } + // + // Next device path node + // + DevPathNode = NextDevicePathNode (DevPathNode); + } + if (ImageName == NULL) { + ImageName = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); + } + } + return ImageName; +} + +/** + Function for 'drivers' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDrivers ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR8 *Language; + CONST CHAR16 *Lang; + EFI_HANDLE *HandleList; + EFI_HANDLE *HandleWalker; + UINTN ChildCount; + UINTN DeviceCount; + CHAR16 ChildCountStr[3]; + CHAR16 DeviceCountStr[3]; + CHAR16 *Temp2; + CONST CHAR16 *FullDriverName; + CHAR16 *TruncatedDriverName; + CHAR16 *ImageName; + CHAR16 *FormatString; + UINT32 DriverVersion; + BOOLEAN DriverConfig; + BOOLEAN DriverDiag; + BOOLEAN SfoFlag; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Language = NULL; + FormatString = NULL; + SfoFlag = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drivers", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drivers"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetFlag(Package, L"-l")){ + Lang = ShellCommandLineGetValue(Package, L"-l"); + if (Lang != NULL) { + Language = AllocateZeroPool(StrSize(Lang)); + AsciiSPrint(Language, StrSize(Lang), "%S", Lang); + } else { + ASSERT(Language == NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drivers", L"-l"); + ShellCommandLineFreeVarList (Package); + return (SHELL_INVALID_PARAMETER); + } + } + + if (ShellCommandLineGetFlag (Package, L"-sfo")) { + SfoFlag = TRUE; + FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE_SFO), Language); + // + // print the SFO header + // + ShellPrintHiiEx ( + -1, + -1, + Language, + STRING_TOKEN (STR_GEN_SFO_HEADER), + gShellDriver1HiiHandle, + L"drivers"); + } else { + FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE), Language); + // + // print the header row + // + ShellPrintHiiEx( + -1, + -1, + Language, + STRING_TOKEN (STR_DRIVERS_HEADER_LINES), + gShellDriver1HiiHandle); + } + + HandleList = GetHandleListByProtocol(&gEfiDriverBindingProtocolGuid); + for (HandleWalker = HandleList ; HandleWalker != NULL && *HandleWalker != NULL ; HandleWalker++){ + ChildCount = 0; + DeviceCount = 0; + Status = ParseHandleDatabaseForChildDevices (*HandleWalker, &ChildCount , NULL); + Status = PARSE_HANDLE_DATABASE_DEVICES (*HandleWalker, &DeviceCount, NULL); + Temp2 = GetDevicePathTextForHandle(*HandleWalker); + DriverVersion = ReturnDriverVersion(*HandleWalker); + DriverConfig = ReturnDriverConfig(*HandleWalker); + DriverDiag = ReturnDriverDiag (*HandleWalker); + FullDriverName = GetStringNameFromHandle(*HandleWalker, Language); + ImageName = GetImageNameFromHandle (*HandleWalker); + + UnicodeValueToStringS (ChildCountStr, sizeof (ChildCountStr), 0, ChildCount, 0); + UnicodeValueToStringS (DeviceCountStr, sizeof (DeviceCountStr), 0, DeviceCount, 0); + TruncatedDriverName = NULL; + if (!SfoFlag && (FullDriverName != NULL)) { + TruncatedDriverName = AllocateZeroPool ((MAX_LEN_DRIVER_NAME + 1) * sizeof (CHAR16)); + StrnCpyS (TruncatedDriverName, MAX_LEN_DRIVER_NAME + 1, FullDriverName, MAX_LEN_DRIVER_NAME); + } + + if (!SfoFlag) { + ShellPrintEx ( + -1, + -1, + FormatString, + ConvertHandleToHandleIndex (*HandleWalker), + DriverVersion, + ChildCount > 0 ? L'B' : (DeviceCount > 0 ? L'D' : L'?'), + DriverConfig ? L'X' : L'-', + DriverDiag ? L'X' : L'-', + DeviceCount > 0 ? DeviceCountStr : L"-", + ChildCount > 0 ? ChildCountStr : L"-", + TruncatedDriverName, + ImageName == NULL ? L"" : ImageName + ); + } else { + ShellPrintEx ( + -1, + -1, + FormatString, + ConvertHandleToHandleIndex (*HandleWalker), + DriverVersion, + ChildCount > 0 ? L'B' : (DeviceCount > 0 ? L'D' : L'?'), + DriverConfig ? L'Y' : L'N', + DriverDiag ? L'Y' : L'N', + DeviceCount, + ChildCount, + FullDriverName, + Temp2 == NULL ? L"" : Temp2 + ); + } + if (TruncatedDriverName != NULL) { + FreePool (TruncatedDriverName); + } + if (Temp2 != NULL) { + FreePool(Temp2); + } + if (ImageName != NULL) { + FreePool (ImageName); + } + + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + } + } + SHELL_FREE_NON_NULL(Language); + ShellCommandLineFreeVarList (Package); + SHELL_FREE_NON_NULL(FormatString); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c new file mode 100644 index 0000000..bb07916 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c @@ -0,0 +1,1412 @@ +/** @file + Main file for DrvCfg shell Driver1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" +#include +#include + +STATIC CONST EFI_GUID *CfgGuidList[] = {&gEfiDriverConfigurationProtocolGuid, &gEfiDriverConfiguration2ProtocolGuid, NULL}; + +/** + Find the EFI_HII_HANDLE by device path. + + @param[in] DevPath1 The Device Path to match. + @param[out] HiiHandle The EFI_HII_HANDLE after the converstion. + @param[in] HiiDb The Hii database protocol + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND There was no EFI_HII_HANDLE found for that deviec path. +**/ +EFI_STATUS +FindHiiHandleViaDevPath( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath1, + OUT EFI_HII_HANDLE *HiiHandle, + IN EFI_HII_DATABASE_PROTOCOL *HiiDb + ) +{ + EFI_HII_HANDLE *HandleBuffer; + UINTN HandleBufferSize; + VOID *MainBuffer; + UINTN MainBufferSize; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + EFI_HII_PACKAGE_HEADER *PackageHeader; + UINTN LoopVariable; + EFI_DEVICE_PATH_PROTOCOL *DevPath2; + EFI_STATUS Status; + + ASSERT(DevPath1 != NULL); + ASSERT(HiiHandle != NULL); + ASSERT(*HiiHandle == NULL); + ASSERT(HiiDb != NULL); + + HandleBufferSize = 0; + HandleBuffer = NULL; + Status = HiiDb->ListPackageLists(HiiDb, EFI_HII_PACKAGE_DEVICE_PATH, NULL, &HandleBufferSize, HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool(HandleBufferSize); + if (HandleBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + Status = HiiDb->ListPackageLists (HiiDb, EFI_HII_PACKAGE_DEVICE_PATH, NULL, &HandleBufferSize, HandleBuffer); + } + } + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(HandleBuffer); + return (Status); + } + + if (HandleBuffer == NULL) { + return EFI_NOT_FOUND; + } + + for (LoopVariable = 0 ; LoopVariable < (HandleBufferSize/sizeof(HandleBuffer[0])) && *HiiHandle == NULL ; LoopVariable++) { + MainBufferSize = 0; + MainBuffer = NULL; + Status = HiiDb->ExportPackageLists(HiiDb, HandleBuffer[LoopVariable], &MainBufferSize, MainBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + MainBuffer = AllocateZeroPool(MainBufferSize); + if (MainBuffer != NULL) { + Status = HiiDb->ExportPackageLists (HiiDb, HandleBuffer[LoopVariable], &MainBufferSize, MainBuffer); + } + } + if (EFI_ERROR (Status)) { + continue; + } + // + // Enumerate through the block of returned memory. + // This should actually be a small block, but we need to be sure. + // + for (PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)MainBuffer + ; PackageListHeader != NULL && ((CHAR8*)PackageListHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && *HiiHandle == NULL + ; PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)(((CHAR8*)(PackageListHeader)) + PackageListHeader->PackageLength )) { + for (PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageListHeader))+sizeof(EFI_HII_PACKAGE_LIST_HEADER)) + ; PackageHeader != NULL && ((CHAR8*)PackageHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && PackageHeader->Type != EFI_HII_PACKAGE_END && *HiiHandle == NULL + ; PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageHeader))+PackageHeader->Length)) { + if (PackageHeader->Type == EFI_HII_PACKAGE_DEVICE_PATH) { + DevPath2 = (EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)); + if (DevicePathCompare(&DevPath1, &DevPath2) == 0) { + *HiiHandle = HandleBuffer[LoopVariable]; + break; + } + } + } + } + SHELL_FREE_NON_NULL(MainBuffer); + } + SHELL_FREE_NON_NULL(HandleBuffer); + + if (*HiiHandle == NULL) { + return (EFI_NOT_FOUND); + } + return (EFI_SUCCESS); +} + +/** + Convert a EFI_HANDLE to a EFI_HII_HANDLE. + + @param[in] Handle The EFI_HANDLE to convert. + @param[out] HiiHandle The EFI_HII_HANDLE after the converstion. + @param[in] HiiDb The Hii database protocol + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ConvertHandleToHiiHandle( + IN CONST EFI_HANDLE Handle, + OUT EFI_HII_HANDLE *HiiHandle, + IN EFI_HII_DATABASE_PROTOCOL *HiiDb + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevPath1; + + if (HiiHandle == NULL || HiiDb == NULL) { + return (EFI_INVALID_PARAMETER); + } + *HiiHandle = NULL; + + if (Handle == NULL) { + return (EFI_SUCCESS); + } + + DevPath1 = NULL; + Status = gBS->OpenProtocol(Handle, &gEfiDevicePathProtocolGuid, (VOID**)&DevPath1, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status) || DevPath1 == NULL) { + return (EFI_NOT_FOUND); + } + + return (FindHiiHandleViaDevPath(DevPath1, HiiHandle, HiiDb)); +} + +/** + Function to print out all HII configuration information to a file. + + @param[in] Handle The handle to get info on. NULL to do all handles. + @param[in] FileName The filename to rwite the info to. +**/ +SHELL_STATUS +ConfigToFile( + IN CONST EFI_HANDLE Handle, + IN CONST CHAR16 *FileName + ) +{ + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_STATUS Status; + VOID *MainBuffer; + UINTN MainBufferSize; + EFI_HII_HANDLE HiiHandle; + SHELL_FILE_HANDLE FileHandle; + + HiiDatabase = NULL; + MainBufferSize = 0; + MainBuffer = NULL; + FileHandle = NULL; + + Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_FILE_OPEN_FAIL), + gShellDriver1HiiHandle, + L"drvcfg", + FileName, + Status); + return (SHELL_DEVICE_ERROR); + } + + // + // Locate HII Database protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + (VOID **) &HiiDatabase + ); + + if (EFI_ERROR(Status) || HiiDatabase == NULL) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_PROTOCOL_NF), + gShellDriver1HiiHandle, + L"drvcfg", + L"EfiHiiDatabaseProtocol", + &gEfiHiiDatabaseProtocolGuid); + ShellCloseFile(&FileHandle); + return (SHELL_NOT_FOUND); + } + + HiiHandle = NULL; + Status = ConvertHandleToHiiHandle(Handle, &HiiHandle, HiiDatabase); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_HANDLE_NOT), + gShellDriver1HiiHandle, + L"drvcfg", + ConvertHandleToHandleIndex(Handle), + L"Device"); + ShellCloseFile(&FileHandle); + return (SHELL_DEVICE_ERROR); + } + + Status = HiiDatabase->ExportPackageLists(HiiDatabase, HiiHandle, &MainBufferSize, MainBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + MainBuffer = AllocateZeroPool(MainBufferSize); + Status = HiiDatabase->ExportPackageLists(HiiDatabase, HiiHandle, &MainBufferSize, MainBuffer); + } + + Status = ShellWriteFile(FileHandle, &MainBufferSize, MainBuffer); + + ShellCloseFile(&FileHandle); + SHELL_FREE_NON_NULL(MainBuffer); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_FILE_WRITE_FAIL), + gShellDriver1HiiHandle, + L"drvcfg", + FileName); + return (SHELL_DEVICE_ERROR); + } + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_DRVCFG_COMP), + gShellDriver1HiiHandle); + + return (SHELL_SUCCESS); +} + +/** + Function to read in HII configuration information from a file. + + @param[in] Handle The handle to get info for. + @param[in] FileName The filename to read the info from. +**/ +SHELL_STATUS +ConfigFromFile( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *FileName + ) +{ + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_STATUS Status; + VOID *MainBuffer; + UINT64 Temp; + UINTN MainBufferSize; + EFI_HII_HANDLE HiiHandle; + SHELL_FILE_HANDLE FileHandle; + CHAR16 *TempDevPathString; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + EFI_HII_PACKAGE_HEADER *PackageHeader; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + UINTN HandleIndex; + + HiiDatabase = NULL; + MainBufferSize = 0; + MainBuffer = NULL; + FileHandle = NULL; + + Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_FILE_OPEN_FAIL), + gShellDriver1HiiHandle, + L"drvcfg", + FileName, + Status); + return (SHELL_DEVICE_ERROR); + } + + // + // Locate HII Database protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + (VOID **) &HiiDatabase + ); + + if (EFI_ERROR(Status) || HiiDatabase == NULL) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_PROTOCOL_NF), + gShellDriver1HiiHandle, + L"drvcfg", + L"EfiHiiDatabaseProtocol", + &gEfiHiiDatabaseProtocolGuid); + ShellCloseFile(&FileHandle); + return (SHELL_NOT_FOUND); + } + + Status = ShellGetFileSize(FileHandle, &Temp); + MainBufferSize = (UINTN)Temp; + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_FILE_READ_FAIL), + gShellDriver1HiiHandle, + L"drvcfg", + FileName); + + ShellCloseFile(&FileHandle); + return (SHELL_DEVICE_ERROR); + } + MainBuffer = AllocateZeroPool((UINTN)MainBufferSize); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_OUT_MEM), + gShellDriver1HiiHandle, L"drvcfg"); + ShellCloseFile(&FileHandle); + return (SHELL_DEVICE_ERROR); + } + Status = ShellReadFile(FileHandle, &MainBufferSize, MainBuffer); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_FILE_READ_FAIL), + gShellDriver1HiiHandle, + L"drvcfg", + FileName); + + ShellCloseFile(&FileHandle); + SHELL_FREE_NON_NULL(MainBuffer); + return (SHELL_DEVICE_ERROR); + } + + ShellCloseFile(&FileHandle); + + if (Handle != NULL) { + // + // User override in place. Just do it. + // + HiiHandle = NULL; + Status = ConvertHandleToHiiHandle(Handle, &HiiHandle, HiiDatabase); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_HANDLE_NOT), + gShellDriver1HiiHandle, L"drvcfg", + ConvertHandleToHandleIndex(Handle), + L"Device"); + ShellCloseFile(&FileHandle); + return (SHELL_DEVICE_ERROR); + } + Status = HiiDatabase->UpdatePackageList(HiiDatabase, HiiHandle, MainBuffer); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_UEFI_FUNC_WARN), + gShellDriver1HiiHandle, + L"drvcfg", + L"HiiDatabase->UpdatePackageList", + Status); + return (SHELL_DEVICE_ERROR); + } + } else { + // + // we need to parse the buffer and try to match the device paths for each item to try to find it's device path. + // + + for (PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)MainBuffer + ; PackageListHeader != NULL && ((CHAR8*)PackageListHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) + ; PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)(((CHAR8*)(PackageListHeader)) + PackageListHeader->PackageLength )) { + for (PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageListHeader))+sizeof(EFI_HII_PACKAGE_LIST_HEADER)) + ; PackageHeader != NULL && ((CHAR8*)PackageHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && PackageHeader->Type != EFI_HII_PACKAGE_END + ; PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageHeader))+PackageHeader->Length)) { + if (PackageHeader->Type == EFI_HII_PACKAGE_DEVICE_PATH) { + HiiHandle = NULL; + Status = FindHiiHandleViaDevPath((EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)), &HiiHandle, HiiDatabase); + if (EFI_ERROR(Status)) { + // + // print out an error. + // + TempDevPathString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)), TRUE, TRUE); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_DRVCFG_IN_FILE_NF), + gShellDriver1HiiHandle, + TempDevPathString); + SHELL_FREE_NON_NULL(TempDevPathString); + } else { + Status = HiiDatabase->UpdatePackageList(HiiDatabase, HiiHandle, PackageListHeader); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_GEN_UEFI_FUNC_WARN), + gShellDriver1HiiHandle, + L"drvcfg", + L"HiiDatabase->UpdatePackageList", + Status); + return (SHELL_DEVICE_ERROR); + } else { + DevPath = (EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)); + gBS->LocateDevicePath(&gEfiHiiConfigAccessProtocolGuid, &DevPath, &Handle); + HandleIndex = ConvertHandleToHandleIndex(Handle); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_DRVCFG_DONE_HII), + gShellDriver1HiiHandle, + HandleIndex); + } + } + } + } + } + } + + SHELL_FREE_NON_NULL(MainBuffer); + + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_DRVCFG_COMP), + gShellDriver1HiiHandle); + return (SHELL_SUCCESS); +} + +/** + Present a requested action to the user. + + @param[in] DriverImageHandle The handle for the driver to configure. + @param[in] ControllerHandle The handle of the device being managed by the Driver specified. + @param[in] ChildHandle The handle of a child device of the specified device. + @param[in] ActionRequired The required HII action. + + @retval SHELL_INVALID_PARAMETER A parameter has a invalid value. +**/ +EFI_STATUS +ShellCmdDriverConfigurationProcessActionRequired ( + EFI_HANDLE DriverImageHandle, + EFI_HANDLE ControllerHandle, + EFI_HANDLE ChildHandle, + EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED ActionRequired + ) +{ + EFI_HANDLE ConnectControllerContextOverride[2]; + + switch (ActionRequired) { + case EfiDriverConfigurationActionNone: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_NONE), gShellDriver1HiiHandle); + break; + + case EfiDriverConfigurationActionStopController: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_STOP), gShellDriver1HiiHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_ENTER_S), gShellDriver1HiiHandle, L"stop controller"); + ShellPromptForResponse(ShellPromptResponseTypeEnterContinue, NULL, NULL); + + gBS->DisconnectController (ControllerHandle, DriverImageHandle, ChildHandle); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_CTLR_S), gShellDriver1HiiHandle, L"stopped"); + break; + + case EfiDriverConfigurationActionRestartController: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_RESTART_S), gShellDriver1HiiHandle, L"controller"); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_ENTER_S), gShellDriver1HiiHandle, L"restart controller"); + ShellPromptForResponse(ShellPromptResponseTypeEnterContinue, NULL, NULL); + + gBS->DisconnectController (ControllerHandle, DriverImageHandle, ChildHandle); + ConnectControllerContextOverride[0] = DriverImageHandle; + ConnectControllerContextOverride[1] = NULL; + gBS->ConnectController (ControllerHandle, ConnectControllerContextOverride, NULL, TRUE); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_CTLR_S), gShellDriver1HiiHandle, L"restarted"); + break; + + case EfiDriverConfigurationActionRestartPlatform: + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_RESTART_S), gShellDriver1HiiHandle, L"platform"); + ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_ENTER_S), gShellDriver1HiiHandle, L"restart platform"); + ShellPromptForResponse(ShellPromptResponseTypeEnterContinue, NULL, NULL); + + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + break; + + default: + return (EFI_INVALID_PARAMETER); + } + + return EFI_SUCCESS; +} + +/** + Do the configuration in an environment without HII. + + @param[in] Language The language code. + @param[in] ForceDefaults TRUE to force defaults, FALSE otherwise. + @param[in] DefaultType If ForceDefaults is TRUE, specifies the default type. + @param[in] AllChildren TRUE to configure all children, FALSE otherwise. + @param[in] ValidateOptions TRUE to validate existing options, FALSE otherwise. + @param[in] SetOptions TRUE to set options, FALSE otherwise. + @param[in] DriverImageHandle The handle for the driver to configure. + @param[in] DeviceHandle The handle of the device being managed by the Driver specified. + @param[in] ChildHandle The handle of a child device of the specified device. + + @retval SHELL_NOT_FOUND A specified handle could not be found. + @retval SHELL_INVALID_PARAMETER A parameter has a invalid value. +**/ +SHELL_STATUS +PreHiiDrvCfg ( + IN CONST CHAR8 *Language, + IN BOOLEAN ForceDefaults, + IN UINT32 DefaultType, + IN BOOLEAN AllChildren, + IN BOOLEAN ValidateOptions, + IN BOOLEAN SetOptions, + IN EFI_HANDLE DriverImageHandle, + IN EFI_HANDLE DeviceHandle, + IN EFI_HANDLE ChildHandle + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + UINTN OuterLoopCounter; + CHAR8 *BestLanguage; + UINTN DriverImageHandleCount; + EFI_HANDLE *DriverImageHandleBuffer; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN *HandleType; + UINTN LoopCounter; + UINTN ChildIndex; + UINTN ChildHandleCount; + EFI_HANDLE *ChildHandleBuffer; + UINTN *ChildHandleType; + EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED ActionRequired; + EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration; + BOOLEAN Iso639Language; + UINTN HandleIndex1; + UINTN HandleIndex2; + UINTN HandleIndex3; + + ShellStatus = SHELL_SUCCESS; + + if (ChildHandle == NULL && AllChildren) { + SetOptions = FALSE; + } + + if (ForceDefaults) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_FORCE_D), + gShellDriver1HiiHandle, + DefaultType); + } else if (ValidateOptions) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_VALIDATE), + gShellDriver1HiiHandle); + } else if (SetOptions) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_SET), + gShellDriver1HiiHandle); + } + + if (DriverImageHandle == 0) { + DriverImageHandleBuffer = GetHandleListByProtocolList(CfgGuidList); + if (DriverImageHandleBuffer == NULL) { + ShellStatus = SHELL_NOT_FOUND; + goto Done; + } + for ( + HandleBuffer = DriverImageHandleBuffer, DriverImageHandleCount = 0 + ; HandleBuffer != NULL && *HandleBuffer != NULL + ; HandleBuffer++,DriverImageHandleCount++); + } else { + DriverImageHandleCount = 1; + // + // Allocate buffer to hold the image handle so as to + // keep consistent with the above clause + // + DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE)); + ASSERT (DriverImageHandleBuffer); + DriverImageHandleBuffer[0] = DriverImageHandle; + } + + for (OuterLoopCounter = 0; OuterLoopCounter < DriverImageHandleCount; OuterLoopCounter++) { + Iso639Language = FALSE; + Status = gBS->OpenProtocol ( + DriverImageHandleBuffer[OuterLoopCounter], + &gEfiDriverConfiguration2ProtocolGuid, + (VOID **) &DriverConfiguration, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Iso639Language = TRUE; + Status = gBS->OpenProtocol ( + DriverImageHandleBuffer[OuterLoopCounter], + &gEfiDriverConfigurationProtocolGuid, + (VOID **) &DriverConfiguration, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + } + if (EFI_ERROR (Status)) { +// ShellPrintHiiEx( +// -1, +// -1, +// NULL, +// STRING_TOKEN (STR_DRVCFG_NOT_SUPPORT), +// gShellDriver1HiiHandle, +// ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]) +// ); + ShellStatus = SHELL_UNSUPPORTED; + continue; + } + + BestLanguage = GetBestLanguage ( + DriverConfiguration->SupportedLanguages, + Iso639Language, + Language!=NULL?Language:"", + DriverConfiguration->SupportedLanguages, + NULL + ); + if (BestLanguage == NULL) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_NO_VALUE), + gShellDriver1HiiHandle, + L"drvcfg", + L"-l" + ); + ShellStatus = SHELL_INVALID_PARAMETER; + continue; + } + + Status = ParseHandleDatabaseByRelationshipWithType ( + DriverImageHandleBuffer[OuterLoopCounter], + NULL, + &HandleCount, + &HandleBuffer, + &HandleType + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (SetOptions && DeviceHandle == NULL) { + + gST->ConOut->ClearScreen (gST->ConOut); + Status = DriverConfiguration->SetOptions ( + DriverConfiguration, + NULL, + NULL, + BestLanguage, + &ActionRequired + ); + gST->ConOut->ClearScreen (gST->ConOut); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_ALL_LANG), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]), + DriverConfiguration->SupportedLanguages + ); + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_SET), + gShellDriver1HiiHandle); + for (LoopCounter = 0; LoopCounter < HandleCount; LoopCounter++) { + if ((HandleType[LoopCounter] & HR_CONTROLLER_HANDLE) == HR_CONTROLLER_HANDLE) { + ShellCmdDriverConfigurationProcessActionRequired ( + DriverImageHandleBuffer[OuterLoopCounter], + HandleBuffer[LoopCounter], + NULL, + ActionRequired + ); + } + } + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_NOT_SET), + gShellDriver1HiiHandle, + Status); + } + continue; + } + + for (LoopCounter = 0; LoopCounter < HandleCount; LoopCounter++) { + if ((HandleType[LoopCounter] & HR_CONTROLLER_HANDLE) != HR_CONTROLLER_HANDLE) { + continue; + } + if (DeviceHandle != NULL && DeviceHandle != HandleBuffer[LoopCounter]) { + continue; + } + if (ChildHandle == NULL) { + HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]); + HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_CTRL_LANG), + gShellDriver1HiiHandle, + HandleIndex1, + HandleIndex2, + DriverConfiguration->SupportedLanguages + ); + + if (ForceDefaults) { + Status = DriverConfiguration->ForceDefaults ( + DriverConfiguration, + HandleBuffer[LoopCounter], + NULL, + DefaultType, + &ActionRequired + ); + + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_DEF_FORCED), + gShellDriver1HiiHandle); + ShellCmdDriverConfigurationProcessActionRequired ( + DriverImageHandleBuffer[OuterLoopCounter], + HandleBuffer[LoopCounter], + NULL, + ActionRequired + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_FORCE_FAILED), + gShellDriver1HiiHandle, + Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } else if (ValidateOptions) { + Status = DriverConfiguration->OptionsValid ( + DriverConfiguration, + HandleBuffer[LoopCounter], + NULL + ); + + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_VALID), + gShellDriver1HiiHandle); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_INV), + gShellDriver1HiiHandle, + Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } else if (SetOptions) { + gST->ConOut->ClearScreen (gST->ConOut); + Status = DriverConfiguration->SetOptions ( + DriverConfiguration, + HandleBuffer[LoopCounter], + NULL, + BestLanguage, + &ActionRequired + ); + gST->ConOut->ClearScreen (gST->ConOut); + HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]); + HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_CTRL_LANG), + gShellDriver1HiiHandle, + HandleIndex1, + HandleIndex2, + DriverConfiguration->SupportedLanguages + ); + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_SET), + gShellDriver1HiiHandle); + + ShellCmdDriverConfigurationProcessActionRequired ( + DriverImageHandleBuffer[OuterLoopCounter], + HandleBuffer[LoopCounter], + NULL, + ActionRequired + ); + + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_NOT_SET), + gShellDriver1HiiHandle, + Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } else { + Print (L"\n"); + } + } + + if (ChildHandle == NULL && !AllChildren) { + continue; + } + + Status = ParseHandleDatabaseByRelationshipWithType ( + DriverImageHandleBuffer[OuterLoopCounter], + HandleBuffer[LoopCounter], + &ChildHandleCount, + &ChildHandleBuffer, + &ChildHandleType + ); + if (EFI_ERROR (Status)) { + continue; + } + + for (ChildIndex = 0; ChildIndex < ChildHandleCount; ChildIndex++) { + + if ((ChildHandleType[ChildIndex] & HR_CHILD_HANDLE) != HR_CHILD_HANDLE) { + continue; + } + + if (ChildHandle != NULL && ChildHandle != ChildHandleBuffer[ChildIndex]) { + continue; + } + + HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]); + HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]); + HandleIndex3 = ConvertHandleToHandleIndex (ChildHandleBuffer[ChildIndex]); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_CHILD_LANG), + gShellDriver1HiiHandle, + HandleIndex1, + HandleIndex2, + HandleIndex3, + DriverConfiguration->SupportedLanguages); + + if (ForceDefaults) { + Status = DriverConfiguration->ForceDefaults ( + DriverConfiguration, + HandleBuffer[LoopCounter], + ChildHandleBuffer[ChildIndex], + DefaultType, + &ActionRequired + ); + + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_DEF_FORCED), + gShellDriver1HiiHandle); + + ShellCmdDriverConfigurationProcessActionRequired ( + DriverImageHandleBuffer[OuterLoopCounter], + HandleBuffer[LoopCounter], + ChildHandleBuffer[ChildIndex], + ActionRequired + ); + + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_FORCE_FAILED), + gShellDriver1HiiHandle, + Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } else if (ValidateOptions) { + Status = DriverConfiguration->OptionsValid ( + DriverConfiguration, + HandleBuffer[LoopCounter], + ChildHandleBuffer[ChildIndex] + ); + + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_VALID), + gShellDriver1HiiHandle); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_INV), + gShellDriver1HiiHandle, + Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } else if (SetOptions) { + gST->ConOut->ClearScreen (gST->ConOut); + Status = DriverConfiguration->SetOptions ( + DriverConfiguration, + HandleBuffer[LoopCounter], + ChildHandleBuffer[ChildIndex], + BestLanguage, + &ActionRequired + ); + gST->ConOut->ClearScreen (gST->ConOut); + HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]); + HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]); + HandleIndex3 = ConvertHandleToHandleIndex (ChildHandleBuffer[ChildIndex]); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_CHILD_LANG), + gShellDriver1HiiHandle, + HandleIndex1, + HandleIndex2, + HandleIndex3, + DriverConfiguration->SupportedLanguages + ); + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_OPTIONS_SET), + gShellDriver1HiiHandle); + + ShellCmdDriverConfigurationProcessActionRequired ( + DriverImageHandleBuffer[OuterLoopCounter], + HandleBuffer[LoopCounter], + ChildHandleBuffer[ChildIndex], + ActionRequired + ); + + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_NOT_SET), + gShellDriver1HiiHandle, + Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } else { + Print (L"\n"); + } + } + + FreePool (ChildHandleBuffer); + FreePool (ChildHandleType); + } + + FreePool (BestLanguage); + FreePool (HandleBuffer); + FreePool (HandleType); + } + + if (DriverImageHandle != NULL && DriverImageHandleCount != 0) { + FreePool (DriverImageHandleBuffer); + } + +Done: + return ShellStatus; +} + +/** + Function to print out configuration information on all configurable handles. + + @param[in] ChildrenToo TRUE to tewst for children. + @param[in] Language ASCII string for language code. + @param[in] UseHii TRUE to check for Hii and DPC, FALSE for DCP only. + + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +PrintConfigInfoOnAll( + IN CONST BOOLEAN ChildrenToo, + IN CONST CHAR8 *Language, + IN CONST BOOLEAN UseHii + ) +{ + EFI_HANDLE *HandleList; + EFI_HANDLE *CurrentHandle; + BOOLEAN Found; + UINTN Index2; + + + Found = FALSE; + HandleList = NULL; + CurrentHandle = NULL; + + if (UseHii) { + // + // HII method + // + HandleList = GetHandleListByProtocol(&gEfiHiiConfigAccessProtocolGuid); + for (CurrentHandle = HandleList ; CurrentHandle != NULL && *CurrentHandle != NULL; CurrentHandle++){ + Found = TRUE; + Index2 = *CurrentHandle == NULL ? 0 : ConvertHandleToHandleIndex(*CurrentHandle); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_LINE_HII), + gShellDriver1HiiHandle, + Index2 + ); + } + SHELL_FREE_NON_NULL(HandleList); + } + + if (PreHiiDrvCfg ( + Language, + FALSE, + 0, + ChildrenToo, + FALSE, + FALSE, + 0, + 0, + 0) == SHELL_SUCCESS) { + Found = TRUE; + } + + if (!Found) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVCFG_NONE_FOUND), gShellDriver1HiiHandle); + return (SHELL_SUCCESS); + } + + return (SHELL_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM ParamListHii[] = { + {L"-s", TypeFlag}, + {L"-l", TypeValue}, + {L"-f", TypeValue}, + {L"-o", TypeValue}, + {L"-i", TypeValue}, + {NULL, TypeMax} + }; +STATIC CONST SHELL_PARAM_ITEM ParamListPreHii[] = { + {L"-c", TypeFlag}, + {L"-s", TypeFlag}, + {L"-v", TypeFlag}, + {L"-l", TypeValue}, + {L"-f", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'drvcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDrvCfg ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR8 *Language; + CONST CHAR16 *Lang; + CONST CHAR16 *HandleIndex1; + CONST CHAR16 *HandleIndex2; + CONST CHAR16 *HandleIndex3; + CONST CHAR16 *ForceTypeString; + BOOLEAN Force; + BOOLEAN Set; + BOOLEAN Validate; + BOOLEAN InFromFile; + BOOLEAN OutToFile; + BOOLEAN AllChildren; + BOOLEAN UseHii; + UINT32 ForceType; + UINT64 Intermediate; + EFI_HANDLE Handle1; + EFI_HANDLE Handle2; + EFI_HANDLE Handle3; + CONST CHAR16 *FileName; + + ShellStatus = SHELL_SUCCESS; + Status = EFI_SUCCESS; + Language = NULL; + UseHii = TRUE; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamListHii, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status) || ShellCommandLineGetCount(Package) > 2) { + UseHii = FALSE; + if (Package != NULL) { + ShellCommandLineFreeVarList (Package); + } + SHELL_FREE_NON_NULL(ProblemParam); + Status = ShellCommandLineParse (ParamListPreHii, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drvcfg", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } else { + ASSERT(FALSE); + } + } + } + if (ShellStatus == SHELL_SUCCESS) { + if (ShellCommandLineGetCount(Package) > 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drvcfg"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + Lang = ShellCommandLineGetValue(Package, L"-l"); + if (Lang != NULL) { + Language = AllocateZeroPool(StrSize(Lang)); + AsciiSPrint(Language, StrSize(Lang), "%S", Lang); + } else if (ShellCommandLineGetFlag(Package, L"-l")){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvcfg", L"-l"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + Set = ShellCommandLineGetFlag (Package, L"-s"); + Validate = ShellCommandLineGetFlag (Package, L"-v"); + InFromFile = ShellCommandLineGetFlag (Package, L"-i"); + OutToFile = ShellCommandLineGetFlag (Package, L"-o"); + AllChildren = ShellCommandLineGetFlag (Package, L"-c"); + Force = ShellCommandLineGetFlag (Package, L"-f"); + ForceTypeString = ShellCommandLineGetValue(Package, L"-f"); + + if (OutToFile) { + FileName = ShellCommandLineGetValue(Package, L"-o"); + } else if (InFromFile) { + FileName = ShellCommandLineGetValue(Package, L"-i"); + } else { + FileName = NULL; + } + + if (InFromFile && EFI_ERROR(ShellFileExists(FileName))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellDriver1HiiHandle, L"drvcfg", FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (OutToFile && !EFI_ERROR(ShellFileExists(FileName))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_EXIST), gShellDriver1HiiHandle, L"drvcfg", FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (Force && ForceTypeString == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvcfg", L"-f"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (Force) { + Status = ShellConvertStringToUint64(ForceTypeString, &Intermediate, FALSE, FALSE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDriver1HiiHandle, L"drvcfg", ForceTypeString, L"-f"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + ForceType = (UINT32)Intermediate; + } else { + ForceType = 0; + } + HandleIndex1 = ShellCommandLineGetRawValue(Package, 1); + Handle1 = NULL; + if (HandleIndex1 != NULL && !EFI_ERROR(ShellConvertStringToUint64(HandleIndex1, &Intermediate, TRUE, FALSE))) { + Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate); + if (Handle1 == NULL || (UINT64)(UINTN)Intermediate != Intermediate) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"drvcfg", HandleIndex1); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + HandleIndex2 = ShellCommandLineGetRawValue(Package, 2); + Handle2 = NULL; + if (HandleIndex2 != NULL && !EFI_ERROR(ShellConvertStringToUint64(HandleIndex2, &Intermediate, TRUE, FALSE))) { + Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate); + if (Handle2 == NULL || (UINT64)(UINTN)Intermediate != Intermediate) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"drvcfg", HandleIndex2); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + HandleIndex3 = ShellCommandLineGetRawValue(Package, 3); + Handle3 = NULL; + if (HandleIndex3 != NULL && !EFI_ERROR(ShellConvertStringToUint64(HandleIndex3, &Intermediate, TRUE, FALSE))) { + Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate); + if (Handle3 == NULL || (UINT64)(UINTN)Intermediate != Intermediate) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"drvcfg", HandleIndex3); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + + if ((InFromFile || OutToFile) && (FileName == NULL)) { + if (FileName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvcfg", InFromFile?L"-i":L"-o"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_HANDLE_REQ), gShellDriver1HiiHandle, L"drvcfg"); + } + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (!UseHii && (InFromFile || OutToFile)) { + if (InFromFile) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDriver1HiiHandle, L"drvcfg", L"-i"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (OutToFile) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDriver1HiiHandle, L"drvcfg", L"-o"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + } + if (Validate && Force) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-v", L"-f"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (Validate && Set) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-v", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (Set && Force) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-s", L"-f"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + if (OutToFile && InFromFile) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-i", L"-o"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + // + // We do HII first. + // + if (UseHii) { + if (Handle1 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiHiiConfigAccessProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + // + // no HII on this handle. + // + ShellStatus = SHELL_UNSUPPORTED; + } else if (Validate) { + } else if (Force) { + } else if (Set) { + } else if (InFromFile) { + ShellStatus = ConfigFromFile(Handle1, FileName); + if (Handle1 != NULL && ShellStatus == SHELL_SUCCESS) { + goto Done; + } + } else if (OutToFile) { + ShellStatus = ConfigToFile(Handle1, FileName); + if (Handle1 != NULL && ShellStatus == SHELL_SUCCESS) { + goto Done; + } + } else if (HandleIndex1 == NULL) { + // + // display all that are configurable + // + ShellStatus = PrintConfigInfoOnAll(AllChildren, Language, UseHii); + goto Done; + } else { + if (!EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiHiiConfigAccessProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_LINE_HII), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(Handle1) + ); + goto Done; + } + } + } + + // + // We allways need to do this one since it does both by default. + // + if (!InFromFile && !OutToFile) { + ShellStatus = PreHiiDrvCfg ( + Language, + Force, + ForceType, + AllChildren, + Validate, + Set, + Handle1, + Handle2, + Handle3); + } + + if (ShellStatus == SHELL_UNSUPPORTED) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRVCFG_NOT_SUPPORT), + gShellDriver1HiiHandle, + ConvertHandleToHandleIndex(Handle1) + ); + } + } + +Done: + ShellCommandLineFreeVarList (Package); + SHELL_FREE_NON_NULL(Language); + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c new file mode 100644 index 0000000..f3d634f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c @@ -0,0 +1,463 @@ +/** @file + Main file for DrvDiag shell Driver1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST EFI_GUID *DiagGuidList[] = {&gEfiDriverDiagnosticsProtocolGuid, &gEfiDriverDiagnostics2ProtocolGuid, NULL}; +// +// We need 1 more item on the list... +// +typedef enum { + TestModeStandard = EfiDriverDiagnosticTypeStandard, + TestModeExtended = EfiDriverDiagnosticTypeExtended, + TestModeManufacturing = EfiDriverDiagnosticTypeManufacturing, + TestModeList, + TestModeMax +} DRV_DIAG_TEST_MODE; + +/** + Do the diagnostics call for some set of handles. + + @param[in] Mode The type of diagnostic test to run. + @param[in] Lang The language code to use. + @param[in] AllChilds Should the test be on all children. + @param[in] DriverHandle The driver handle to test with. + @param[in] ControllerHandle The specific controller handle to test. + @param[in] ChildHandle The specific child handle to test. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER A parameter had an invalid value. + @retval EFI_NOT_FOUND No diagnostic handle could be found. +**/ +EFI_STATUS +DoDiagnostics ( + IN CONST DRV_DIAG_TEST_MODE Mode, + IN CONST CHAR8 *Lang, + IN CONST BOOLEAN AllChilds, + IN CONST EFI_HANDLE DriverHandle, + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE ChildHandle + ) +{ + EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics; + EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2; + EFI_HANDLE *DriverHandleList; + EFI_HANDLE *ControllerHandleList; + EFI_HANDLE *ChildHandleList; + EFI_HANDLE *Walker; + UINTN DriverHandleListCount; + UINTN ControllerHandleListCount; + UINTN ChildHandleListCount; + UINTN DriverHandleListLoop; + UINTN ControllerHandleListLoop; + UINTN ChildHandleListLoop; + EFI_STATUS Status; + EFI_STATUS Status2; + EFI_GUID *ErrorType; + UINTN OutBufferSize; + CHAR16 *OutBuffer; + UINTN HandleIndex1; + UINTN HandleIndex2; + CHAR8 *Language; + BOOLEAN Found; + + if ((ChildHandle != NULL && AllChilds) || (Mode >= TestModeMax)){ + return (EFI_INVALID_PARAMETER); + } + + DriverDiagnostics = NULL; + DriverDiagnostics2 = NULL; + Status = EFI_SUCCESS; + Status2 = EFI_SUCCESS; + DriverHandleList = NULL; + ControllerHandleList = NULL; + ChildHandleList = NULL; + Language = NULL; + OutBuffer = NULL; + ErrorType = NULL; + DriverHandleListCount = 0; + ControllerHandleListCount = 0; + ChildHandleListCount = 0; + + if (DriverHandle != NULL) { + DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); + if (DriverHandleList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + DriverHandleList[0] = DriverHandle; + DriverHandleListCount = 1; + } else { + DriverHandleList = GetHandleListByProtocolList(DiagGuidList); + if (DriverHandleList == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnosticsProtocolGuid", &gEfiDriverDiagnosticsProtocolGuid); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnostics2ProtocolGuid", &gEfiDriverDiagnostics2ProtocolGuid); + return (EFI_NOT_FOUND); + } + for (Walker = DriverHandleList ; Walker != NULL && *Walker != NULL ; DriverHandleListCount++, Walker++); + } + + if (ControllerHandle != NULL) { + ControllerHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); + if (ControllerHandleList == NULL) { + SHELL_FREE_NON_NULL (DriverHandleList); + return EFI_OUT_OF_RESOURCES; + } + ControllerHandleList[0] = ControllerHandle; + ControllerHandleListCount = 1; + } else { + ControllerHandleList = NULL; + } + + if (ChildHandle != NULL) { + ChildHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE)); + if (ChildHandleList == NULL) { + SHELL_FREE_NON_NULL (ControllerHandleList); + SHELL_FREE_NON_NULL (DriverHandleList); + return EFI_OUT_OF_RESOURCES; + } + ChildHandleList[0] = ChildHandle; + ChildHandleListCount = 1; + } else if (AllChilds) { + ChildHandleList = NULL; + // + // This gets handled in the loop below. + // + } else { + ChildHandleList = NULL; + } + + if (Mode == TestModeList) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_HEADER), gShellDriver1HiiHandle); + } + for (DriverHandleListLoop = 0 + ; DriverHandleListLoop < DriverHandleListCount + ; DriverHandleListLoop++ + ){ + if (Mode == TestModeList) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_HEADER), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop])); + } + if (ControllerHandle == NULL) { + PARSE_HANDLE_DATABASE_DEVICES(DriverHandleList[DriverHandleListLoop], &ControllerHandleListCount, &ControllerHandleList); + } + if (ControllerHandleListCount == 0) { + if (Mode == TestModeList) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_NO_HANDLES), gShellDriver1HiiHandle); + } + } else { + if (Mode == TestModeList) { + ShellPrintEx(-1, -1, L"\r\n"); + } + for (ControllerHandleListLoop = 0 + ; ControllerHandleListLoop < ControllerHandleListCount + ; ControllerHandleListLoop++ + ){ + if (AllChilds) { + ASSERT(ChildHandleList == NULL); + PARSE_HANDLE_DATABASE_MANAGED_CHILDREN( + DriverHandleList[DriverHandleListLoop], + ControllerHandleList[ControllerHandleListLoop], + &ChildHandleListCount, + &ChildHandleList); + } + for (ChildHandleListLoop = 0 + ; (ChildHandleListLoop < ChildHandleListCount || ChildHandleList == NULL) + ; ChildHandleListLoop++ + ){ + Found = FALSE; + if (Mode != TestModeList) { + if (Lang == NULL || Lang[2] == '-') { + // + // Get the protocol pointer and call the function + // + Status = gBS->OpenProtocol( + DriverHandleList[DriverHandleListLoop], + &gEfiDriverDiagnostics2ProtocolGuid, + (VOID**)&DriverDiagnostics2, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status) && (DriverDiagnostics2 != NULL)) { + Language = GetBestLanguageForDriver(DriverDiagnostics2->SupportedLanguages, Lang, FALSE); + Found = TRUE; + Status = DriverDiagnostics2->RunDiagnostics( + DriverDiagnostics2, + ControllerHandleList[ControllerHandleListLoop], + ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop], + (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode, + Language, + &ErrorType, + &OutBufferSize, + &OutBuffer); + FreePool(Language); + } + } + if (!Found && (Lang == NULL||(Lang!=NULL&&(Lang[2]!='-')))){ + Status = gBS->OpenProtocol( + DriverHandleList[DriverHandleListLoop], + &gEfiDriverDiagnosticsProtocolGuid, + (VOID**)&DriverDiagnostics, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(Status)) { + Language = GetBestLanguageForDriver(DriverDiagnostics->SupportedLanguages, Lang, FALSE); + Status = DriverDiagnostics->RunDiagnostics( + DriverDiagnostics, + ControllerHandleList[ControllerHandleListLoop], + ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop], + (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode, + Language, + &ErrorType, + &OutBufferSize, + &OutBuffer); + FreePool(Language); + } + } + if (EFI_ERROR(Status)) { + Status2 = Status; + } + HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]); + HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_3P_RESULT), + gShellDriver1HiiHandle, + L"DrvDiag", + HandleIndex1, + HandleIndex2, + ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]), + Status); + if (OutBuffer!=NULL) { + FreePool(OutBuffer); + OutBuffer = NULL; + } + if (ErrorType!=NULL) { + FreePool(ErrorType); + ErrorType = NULL; + } + } else { + HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]); + HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]); + // + // Print out the information that this set can be tested + // + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_DRV_DIAG_ITEM_LINE), + gShellDriver1HiiHandle, + HandleIndex1, + HandleIndex2, + ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]) + ); + } + + // + // If we are doing a single pass with NULL child jump out after a single loop + // + if (ChildHandleList == NULL) { + break; + } + } + if (AllChilds) { + SHELL_FREE_NON_NULL(ChildHandleList); + ChildHandleList = NULL; + ChildHandleListCount = 0; + } + } + if (ControllerHandle == NULL) { + SHELL_FREE_NON_NULL(ControllerHandleList); + ControllerHandleList = NULL; + ControllerHandleListCount = 0; + } + } + } + + if (DriverHandleList != NULL) { + FreePool(DriverHandleList); + } + if (ControllerHandleList != NULL) { + FreePool(ControllerHandleList); + } + if (ChildHandleList != NULL) { + FreePool(ChildHandleList); + } + return (Status2); +} + + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-c", TypeFlag}, + {L"-s", TypeFlag}, + {L"-e", TypeFlag}, + {L"-m", TypeFlag}, + {L"-l", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'drvdiag' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDrvDiag ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + DRV_DIAG_TEST_MODE Mode; + CHAR8 *Language; + CONST CHAR16 *DriverHandleStr; + CONST CHAR16 *ControllerHandleStr; + CONST CHAR16 *ChildHandleStr; + CONST CHAR16 *Lang; + EFI_HANDLE Handle1; + EFI_HANDLE Handle2; + EFI_HANDLE Handle3; + UINT64 Intermediate; + + ShellStatus = SHELL_SUCCESS; + Mode = TestModeMax; + Language = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drvdiag", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // if more than 3 'value' parameters (plus the name one) or we have any 2 mode flags + // + if ((ShellCommandLineGetCount(Package) > 4) + ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-e")) + ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-m")) + ||(ShellCommandLineGetFlag(Package, L"-e") && ShellCommandLineGetFlag(Package, L"-m")) + ){ + // + // error for too many parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drvdiag"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((ShellCommandLineGetFlag(Package, L"-s")) + || (ShellCommandLineGetFlag(Package, L"-e")) + || (ShellCommandLineGetFlag(Package, L"-m")) + ){ + // + // Run the appropriate test + // + if (ShellCommandLineGetFlag(Package, L"-s")) { + Mode = TestModeStandard; + } else if (ShellCommandLineGetFlag(Package, L"-e")) { + Mode = TestModeExtended; + } else if (ShellCommandLineGetFlag(Package, L"-m")) { + Mode = TestModeManufacturing; + } else { + ASSERT(FALSE); + } + } else { + // + // Do a listing of what's available to test + // + Mode = TestModeList; + } + + Lang = ShellCommandLineGetValue(Package, L"-l"); + if (ShellCommandLineGetFlag(Package, L"-l") && Lang == NULL) { + ASSERT(Language == NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvdiag", L"-l"); + ShellCommandLineFreeVarList (Package); + return (SHELL_INVALID_PARAMETER); + } else if (Lang != NULL) { + Language = AllocateZeroPool(StrSize(Lang)); + AsciiSPrint(Language, StrSize(Lang), "%S", Lang); + } + + DriverHandleStr = ShellCommandLineGetRawValue(Package, 1); + ControllerHandleStr = ShellCommandLineGetRawValue(Package, 2); + ChildHandleStr = ShellCommandLineGetRawValue(Package, 3); + + if (DriverHandleStr == NULL) { + Handle1 = NULL; + } else { + ShellConvertStringToUint64(DriverHandleStr, &Intermediate, TRUE, FALSE); + Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate); + } + if (ControllerHandleStr == NULL) { + Handle2 = NULL; + } else { + ShellConvertStringToUint64(ControllerHandleStr, &Intermediate, TRUE, FALSE); + Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate); + } + if (ChildHandleStr == NULL) { + Handle3 = NULL; + } else { + ShellConvertStringToUint64(ChildHandleStr, &Intermediate, TRUE, FALSE); + Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate); + } + + Status = DoDiagnostics ( + Mode, + Language, + ShellCommandLineGetFlag(Package, L"-c"), + Handle1, + Handle2, + Handle3 + ); + + SHELL_FREE_NON_NULL(Language); + ShellCommandLineFreeVarList (Package); + + } + if (ShellStatus == SHELL_SUCCESS) { + if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (Status == EFI_INVALID_PARAMETER) { + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (Status == EFI_NOT_FOUND) { + ShellStatus = SHELL_NOT_FOUND; + } else if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c new file mode 100644 index 0000000..ff7e4be --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c @@ -0,0 +1,216 @@ +/** @file + Main file for OpenInfo shell Driver1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST CHAR16 StringHandProt[] = L"HandProt "; +STATIC CONST CHAR16 StringGetProt[] = L"GetProt "; +STATIC CONST CHAR16 StringTestProt[] = L"TestProt "; +STATIC CONST CHAR16 StringChild[] = L"Child "; +STATIC CONST CHAR16 StringDriver[] = L"Driver "; +STATIC CONST CHAR16 StringExclusive[] = L"Exclusive"; +STATIC CONST CHAR16 StringDriverEx[] = L"DriverEx "; +STATIC CONST CHAR16 StringUnknown[] = L"Unknown "; + +/** + Open the database and print out all the info about TheHandle. + + @param[in] TheHandle The handle to print info on. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_INVALID_PARAMETER TheHandle was NULL. +**/ +EFI_STATUS +TraverseHandleDatabase ( + IN CONST EFI_HANDLE TheHandle + ) +{ + EFI_STATUS Status; + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + UINTN ProtocolIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + CONST CHAR16 *OpenTypeString; + CHAR16 *TempString; + UINTN HandleIndex; + CONST CHAR16 *Name; + UINTN ControllerIndex; + + if (TheHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // Retrieve the list of all the protocols on the handle + // + Status = gBS->ProtocolsPerHandle ( + TheHandle, + &ProtocolGuidArray, + &ArrayCount + ); + ASSERT_EFI_ERROR(Status); + if (!EFI_ERROR (Status)) { + + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + // + // print out the human readable name for this one. + // + TempString = GetStringNameFromGuid(ProtocolGuidArray[ProtocolIndex], NULL); + if (TempString == NULL) { + continue; + } + ShellPrintEx(-1, -1, L"%H%s%N\r\n", TempString); + FreePool(TempString); + + // + // Retrieve the list of agents that have opened each protocol + // + Status = gBS->OpenProtocolInformation ( + TheHandle, + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + ASSERT_EFI_ERROR(Status); + if (!EFI_ERROR (Status)) { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + switch (OpenInfo[OpenInfoIndex].Attributes) { + case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL: OpenTypeString = StringHandProt; break; + case EFI_OPEN_PROTOCOL_GET_PROTOCOL: OpenTypeString = StringGetProt; break; + case EFI_OPEN_PROTOCOL_TEST_PROTOCOL: OpenTypeString = StringTestProt; break; + case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER: OpenTypeString = StringChild; break; + case EFI_OPEN_PROTOCOL_BY_DRIVER: OpenTypeString = StringDriver; break; + case EFI_OPEN_PROTOCOL_EXCLUSIVE: OpenTypeString = StringExclusive; break; + case EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE: + OpenTypeString = StringDriverEx; break; + default: OpenTypeString = StringUnknown; break; + } + HandleIndex = ConvertHandleToHandleIndex(OpenInfo[OpenInfoIndex].AgentHandle); + Name = GetStringNameFromHandle(OpenInfo[OpenInfoIndex].AgentHandle, NULL); + ControllerIndex = ConvertHandleToHandleIndex(OpenInfo[OpenInfoIndex].ControllerHandle); + if (ControllerIndex != 0) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_OPENINFO_LINE), + gShellDriver1HiiHandle, + HandleIndex, + ControllerIndex, + OpenInfo[OpenInfoIndex].OpenCount, + OpenTypeString, + Name + ); + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_OPENINFO_MIN_LINE), + gShellDriver1HiiHandle, + HandleIndex, + OpenInfo[OpenInfoIndex].OpenCount, + OpenTypeString, + Name + ); + } + } + FreePool (OpenInfo); + } + } + FreePool (ProtocolGuidArray); + } + + return Status; +} + +/** + Function for 'openinfo' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunOpenInfo ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + EFI_HANDLE TheHandle; + CONST CHAR16 *Param1; + UINT64 Intermediate; + + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"openinfo", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 2){ + // + // error for too many parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"openinfo"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"openinfo"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Param1 = ShellCommandLineGetRawValue(Package, 1); + Status = ShellConvertStringToUint64(Param1, &Intermediate, TRUE, FALSE); + if (EFI_ERROR(Status) || Param1 == NULL || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"openinfo", Param1); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TheHandle = ConvertHandleIndexToHandle((UINTN)Intermediate); + ASSERT(TheHandle != NULL); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_OPENINFO_HEADER_LINE), gShellDriver1HiiHandle, (UINTN)Intermediate, TheHandle); + + Status = TraverseHandleDatabase (TheHandle); + if (!EFI_ERROR(Status)) { + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"openinfo", Param1); + ShellStatus = SHELL_NOT_FOUND; + } + } + } + } + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c new file mode 100644 index 0000000..00dbcc1 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c @@ -0,0 +1,99 @@ +/** @file + Main file for Reconnect shell Driver1 function. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2015 Hewlett Packard Enterprise Development LP
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-r", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Connect all the possible console devices. + +**/ +VOID +ConnectAllConsoles ( + VOID + ) +{ + ShellConnectFromDevPaths(L"ConInDev"); + ShellConnectFromDevPaths(L"ConOutDev"); + ShellConnectFromDevPaths(L"ErrOutDev"); + + ShellConnectFromDevPaths(L"ErrOut"); + ShellConnectFromDevPaths(L"ConIn"); + ShellConnectFromDevPaths(L"ConOut"); +} + + +/** + Function for 'reconnect' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunReconnect ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + SHELL_STATUS ShellStatus; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + EFI_STATUS Status; + + gInReconnect = TRUE; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"reconnect", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + ShellStatus = ShellCommandRunDisconnect(ImageHandle, SystemTable); + if (ShellStatus == SHELL_SUCCESS) { + if (ShellCommandLineGetFlag(Package, L"-r")) { + ConnectAllConsoles(); + } + ShellStatus = ShellCommandRunConnect(ImageHandle, SystemTable); + } + } + + gInReconnect = FALSE; + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c new file mode 100644 index 0000000..dc69d46 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c @@ -0,0 +1,104 @@ +/** @file + Main file for NULL named library for level 1 shell command functions. + + Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +STATIC CONST CHAR16 mFileName[] = L"Driver1Commands"; +EFI_HANDLE gShellDriver1HiiHandle = NULL; +BOOLEAN gInReconnect = FALSE; + +/** + Function to return the name of the file containing help if HII will not be used. + + @return The filename. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameDriver1 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Driver1 Commands library. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +UefiShellDriver1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // check our bit of the profiles mask + // + if ((PcdGet8(PcdShellProfileMask) & BIT0) == 0) { + return (EFI_SUCCESS); + } + + // + // install the HII stuff. + // + gShellDriver1HiiHandle = HiiAddPackages (&gShellDriver1HiiGuid, gImageHandle, UefiShellDriver1CommandsLibStrings, NULL); + if (gShellDriver1HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"connect", ShellCommandRunConnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_CONNECT) ); + ShellCommandRegisterCommandName(L"devices", ShellCommandRunDevices , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DEVICES) ); + ShellCommandRegisterCommandName(L"openinfo", ShellCommandRunOpenInfo , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_OPENINFO) ); + ShellCommandRegisterCommandName(L"disconnect", ShellCommandRunDisconnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DISCONNECT)); + ShellCommandRegisterCommandName(L"reconnect", ShellCommandRunReconnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_RECONNECT) ); + ShellCommandRegisterCommandName(L"unload", ShellCommandRunUnload , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_UNLOAD) ); + ShellCommandRegisterCommandName(L"drvdiag", ShellCommandRunDrvDiag , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DRVDIAG) ); + ShellCommandRegisterCommandName(L"dh", ShellCommandRunDh , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DH) ); + ShellCommandRegisterCommandName(L"drivers", ShellCommandRunDrivers , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DRIVERS) ); + ShellCommandRegisterCommandName(L"devtree", ShellCommandRunDevTree , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DEVTREE) ); + ShellCommandRegisterCommandName(L"drvcfg", ShellCommandRunDrvCfg , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DRVCFG) ); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +UefiShellDriver1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellDriver1HiiHandle != NULL) { + HiiRemovePackages(gShellDriver1HiiHandle); + } + return (EFI_SUCCESS); +} + + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h new file mode 100644 index 0000000..952710f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h @@ -0,0 +1,228 @@ +/** @file + Main file for NULL named library for Profile1 shell command functions. + + Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_DRIVER1_COMMANDS_LIB_H_ +#define _UEFI_SHELL_DRIVER1_COMMANDS_LIB_H_ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern EFI_HANDLE gShellDriver1HiiHandle; +extern BOOLEAN gInReconnect; + +/** + Function for 'connect' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunConnect ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'devices' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDevices ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'openinfo' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunOpenInfo ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'devtree' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDevTree ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'dh' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDh ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'disconnect' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDisconnect ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'drivers' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDrivers ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'drvcfg' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDrvCfg ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'drvdiag' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDrvDiag ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'reconnect' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunReconnect ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'unload' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunUnload ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Do a connect from an EFI variable via it's key name. + + @param[in] Key The name of the EFI Variable. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ShellConnectFromDevPaths ( + IN CONST CHAR16 *Key + ); + + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf new file mode 100644 index 0000000..6c9f760 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf @@ -0,0 +1,73 @@ +## @file +# Provides shell driver1 profile functions +# +# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellDriver1CommandsLib + FILE_GUID = 313D3674-3ED4-48fd-BF97-7DB35D4190D1 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = UefiShellDriver1CommandsLibConstructor + DESTRUCTOR = UefiShellDriver1CommandsLibDestructor + +[Sources] + Connect.c + Devices.c + OpenInfo.c + Disconnect.c + Reconnect.c + Unload.c + DrvDiag.c + Dh.c + Drivers.c + DevTree.c + DrvCfg.c + UefiShellDriver1CommandsLib.c + UefiShellDriver1CommandsLib.h + UefiShellDriver1CommandsLib.uni + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + PeCoffGetEntryPointLib + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Protocols] + gEfiDriverHealthProtocolGuid ## UNDEFINED + gEfiDriverFamilyOverrideProtocolGuid ## UNDEFINED + gEfiHiiConfigAccessProtocolGuid ## SOMETIMES_CONSUMES + gEfiHiiDatabaseProtocolGuid ## CONSUMES + +[Guids] + gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## GUID + gEfiConsoleInDeviceGuid ## CONSUMES ## GUID + gEfiConsoleOutDeviceGuid ## CONSUMES ## GUID + gShellDriver1HiiGuid ## PRODUCES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni new file mode 100644 index 0000000..0df4eb3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni @@ -0,0 +1,759 @@ +// /** +// +// (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
        +// (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php. +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellDriver1CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 driver1 profile commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n" +#string STR_GEN_INV_HANDLE #language en-US "%H%s%N: Handle - '%H%s%N' not found\r\n" +#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_HANDLE_NOT #language en-US "%H%s%N: Handle [%H%02x%N] is not a valid %s\r\n" +#string STR_GEN_HANDLE_REQ #language en-US "%H%s%N: Handle required with the specified options\r\n" +#string STR_GEN_PROTOCOL_NF #language en-US "%H%s%N: The protocol '%H%s%N' is required and not found (%g)\r\n" +#string STR_GEN_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_GEN_FILE_EXIST #language en-US "%H%s%N: File already exists - '%H%s%N'\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_FILE_WRITE_FAIL #language en-US "%H%s%N: Write file error - '%H%s%N'\r\n" +#string STR_FILE_READ_FAIL #language en-US "%H%s%N: Read file error - '%H%s%N'\r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful\r\n" +#string STR_GEN_UEFI_FUNC_ERROR #language en-US "%H%s%N: UEFI function '%H%s%N' returned an incorrect value for: %s (%x)\r\n" +#string STR_GEN_UEFI_FUNC_WARN #language en-US "%H%s%N: UEFI function '%H%s%N' returned: %r\r\n" +#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n" + +#string STR_DRVDIAG_HEADER #language en-US "%EAvailable Diagnostics%N.\r\n" +#string STR_DRVDIAG_DRIVER_HEADER #language en-US "Driver [%H%02x%N]: " +#string STR_DRVDIAG_DRIVER_NO_HANDLES #language en-US "No controller handles found.\r\n" + +#string STR_HANDLE_RESULT #language en-US "%H%s%N - Handle [%H%02x%N] Result %r.\r\n" +#string STR_3P_RESULT #language en-US "%H%s%N - (%H%02x%N,%H%02x%N,%H%02x%N) Result %r.\r\n" +#string STR_CONNECT_NONE #language en-US "%HConnect%N No drivers could be connected.\r\n" + +#string STR_DRVCFG_NONE_FOUND #language en-US "%HDrvCfg%N No configurable devices were found.\r\n" +#string STR_DRVCFG_COMP #language en-US "%HDrvCfg%N - operation complete.\r\n" +#string STR_DRVCFG_DONE_HII #language en-US "Handle[%H%02x%N] successfully updated from file.\r\n" +#string STR_DRVCFG_LINE_HII #language en-US "Handle[%H%02x%N] HII Config Access\r\n" +#string STR_DRVCFG_ALL_LANG #language en-US "Driver[%H%02x%N] Ctrl[--] Lang[%H%a%N] Driver Configuration" +#string STR_DRVCFG_CTRL_LANG #language en-US "Driver[%H%02x%N] Ctrl[%H%02x%N] Lang[%H%a%N] Driver Configuration" +#string STR_DRVCFG_CHILD_LANG #language en-US "Driver[%H%02x%N] Ctrl[%H%02x%N] Child[%H%02x%N] Lang[%H%a%N] Driver Configuration" +#string STR_DRVCFG_RESTART_S #language en-US "Restart %s\r\n" +#string STR_DRVCFG_STOP #language en-US "Stop Controller\n" +#string STR_DRVCFG_ENTER_S #language en-US "\nPress [ENTER] to %s" +#string STR_DRVCFG_NONE #language en-US "None\n" +#string STR_DRVCFG_CTLR_S #language en-US "Controller %s\n" +#string STR_DRVCFG_FORCE_D #language en-US "Force Default Configuration to DefaultType %08x\n" +#string STR_DRVCFG_VALIDATE #language en-US "Validate Configuration Options\n" +#string STR_DRVCFG_SET #language en-US "Set Configuration Options\n" +#string STR_DRVCFG_NOT_SUPPORT #language en-US "Handle [%H%02x%N] does not support configuration.\n" +#string STR_DRVCFG_OPTIONS_SET #language en-US " - Options set. Action Required is " +#string STR_DRVCFG_NOT_SET #language en-US " - Options not set. Status = %r\n" +#string STR_DRVCFG_DEF_FORCED #language en-US " - Defaults forced. Action Required is " +#string STR_DRVCFG_FORCE_FAILED #language en-US " - Force of defaults failed. Status = %r\n" +#string STR_DRVCFG_OPTIONS_VALID #language en-US " - Options valid\n" +#string STR_DRVCFG_OPTIONS_INV #language en-US " - Options not valid. Status = %r\n" +#string STR_DRVCFG_IN_FILE_NF #language en-US "DevicePath '%B%s%N' from file not found in HII DB. Skipped.\r\n" + + +#string STR_DEVICES_HEADER_LINES #language en-US "%N" +" T D\r\n" +" Y C I\r\n" +" P F A\r\n" +"CTRL E G G #P #D #C Device Name\r\n" +"==== = = = == == === =========================================================\r\n" +#string STR_DEVICES_ITEM_LINE #language en-US "%H%4x%N %1c %1c %1c %2d %2d %3d %s\r\n" +#string STR_DEVICES_ITEM_LINE_SFO #language en-US "DevicesInfo,"%x","%c","%c","%c","%d","%d","%d","%s"\r\n" + +#string STR_DRIVERS_HEADER_LINES #language en-US "%N" +"%H T D%N\r\n" +"%HD Y C I%N\r\n" +"%HR P F A%N\r\n" +"%HV VERSION E G G #D #C DRIVER NAME IMAGE NAME%N\r\n" +"== ======== = = = == == =================================== ==========\r\n" +#string STR_DRIVERS_ITEM_LINE #language en-US "%H%2x%N %08x %1c %1c %1c %2s %2s %-35s %s\r\n" +#string STR_DRIVERS_ITEM_LINE_SFO #language en-US "DriversInfo,"%x","%x","%c","%c","%c","%d","%d","%s","%s"\r\n" + +#string STR_DH_OUTPUT_DECODE #language en-US "%s: %g\r\n" +#string STR_DH_NO_NAME_FOUND #language en-US "Protocol Name '%s' could not be identified.\r\n" +#string STR_DH_NO_GUID_FOUND #language en-US "Protocol GUID '%g' could not be identified.\r\n" +#string STR_DH_SFO_OUTPUT #language en-US "%s, %s, %H%02x%N, %s, &s\r\n" +#string STR_DH_OUTPUT #language en-US "%H%02x%N: %s\r\n" +#string STR_DH_OUTPUT_ALL_HEADER #language en-US "Handle dump\r\n" +#string STR_DH_OUTPUT_GUID_HEADER #language en-US "Handle dump by protocol '%g'\r\n" +#string STR_DH_OUTPUT_NAME_HEADER #language en-US "Handle dump by protocol '%s'\r\n" +#string STR_DH_OUTPUT_SINGLE_D #language en-US "%H%02x%N: %s\r\n" +#string STR_DH_OUTPUT_SINGLE #language en-US "%H%02x%N: %x\r\n%s" +#string STR_DH_OUTPUT_SFO #language en-US "%s, %s, %s, %H%02x%N, %s, %s\r\n" +#string STR_DH_OUTPUT_DRIVER1 #language en-US " Controller Name : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER2 #language en-US " Device Path : %H%s%N\r\n" + " Controller Type : %H%s%N\r\n" + " Configuration : %H%s%N\r\n" + " Diagnostics : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER3 #language en-US " Managed by : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER4A #language en-US " Drv[%H%02x%N] : Image(%H%s%N)r\n" +#string STR_DH_OUTPUT_DRIVER4B #language en-US " Drv[%H%02x%N] : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER5 #language en-US " Parent Controllers : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER5B #language en-US " Parent[%H%02x%N] : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER6 #language en-US " Child Controllers : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER6B #language en-US " Child[%H%02x%N] : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER6C #language en-US " Child[%H%02x%N] : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER7 #language en-US " Driver Name [%H%02x%N] : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER7B #language en-US " Driver Image Name : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER8 #language en-US " Driver Version : %H%08x%N\r\n" + " Driver Type : %H%s%N\r\n" + " Configuration : %H%s%N\r\n" + " Diagnostics : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER9 #language en-US " Managing : %H%s%N\r\n" +#string STR_DH_OUTPUT_DRIVER9B #language en-US " Ctrl[%H%02x%N] : %H%s%N\r\n" + +#string STR_DEV_TREE_OUTPUT #language en-US "Ctrl[%H%02x%N] %s\r\n" + +#string STR_UNLOAD_CONF #language en-US "%HUnload%N - Handle [%H%02x%N]. [y/n]?\r\n" +#string STR_UNLOAD_VERBOSE #language en-US "" +"Handle [%H%02x%N] (%08x)\r\n" +" Image (%08x)\r\n" +" ParentHandle..: %08x\r\n" +" SystemTable...: %08x\r\n" +" DeviceHandle..: %08x\r\n" +" FilePath......: %s\r\n" +" PDBFileName...: %a\r\n" +" ImageBase.....: %08x\r\n" +" ImageSize.....: %Ld\r\n" +" CodeType......: %s\r\n" +" DataType......: %s\r\n" + +#string STR_OPENINFO_HEADER_LINE #language en-US "Handle %H%02x%N (%H%0p%N)\r\n" +#string STR_OPENINFO_LINE #language en-US " Drv[%H%02x%N] Ctrl[%H%02x%N] Cnt(%H%02x%N) %H%s Image%N(%s)\r\n" +#string STR_OPENINFO_MIN_LINE #language en-US " Drv[%H%02x%N] Ctrl[ ] Cnt(%H%02x%N) %H%s Image%N(%s)\r\n" + +#string STR_DRV_DIAG_ITEM_LINE #language en-US " Drv[%H%02x%N] Ctrl[%H%02x%N] Child[%H%02x%N]\r\n" + +#string STR_GET_HELP_DRVCFG #language en-US "" +".TH drvcfg 0 "configure a UEFI driver."\r\n" +".SH NAME\r\n" +"Invokes the driver configuration.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DRVCFG [-l XXX] [-c] [-f |-v|-s] \r\n" +" [DriverHandle [DeviceHandle [ChildHandle]]] [-i filename] [-o filename]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -c - Configures all child devices.\r\n" +" -l - Configures using the ISO 3066 language specified by XXX.\r\n" +" -f - Forces defaults.\r\n" +" -v - Validates options.\r\n" +" -s - Sets options.\r\n" +" -i - Receives configuration updates from an input file.\r\n" +" -o - Exports the settings of the specified driver instance to a\r\n" +" file.\r\n" +" Type - Specifies the type of default configuration options to force on the\r\n" +" controller.\r\n" +" 0 - Standard Defaults.\r\n" +" 1 - Manufacturing Defaults.\r\n" +" 2 - Safe Defaults.\r\n" +" 4000-FFFF - Custom Defaults.\r\n" +" DriverHandle - Specifies the the handle of the driver to configure.\r\n" +" DeviceHandle - Specifies the handle of a device that the DriverHandle is managing.\r\n" +" ChildHandle - Specifies the handle of a device that is a child of the DeviceHandle. \r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. Default Type:\r\n" +" 0 - Safe Defaults. Places a controller in a safe configuration with\r\n" +" the greatest probability of functioning correctly in a platform.\r\n" +" 1 - Manufacturing Defaults. Optional type that places the controller in\r\n" +" a configuration suitable for a manufacturing and test environment.\r\n" +" 2 - Custom Defaults. Optional type that places the controller in a\r\n" +" custom configuration.\r\n" +" 3 - Performance Defaults. Optional type that places the controller in a\r\n" +" configuration that maximizes the controller's performance in a \r\n" +" platform. \r\n" +" Other Value - Depends on the driver's implementation.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the list of devices that are available for configuration:\r\n" +" Shell> drvcfg\r\n" +" \r\n" +" * To display the list of devices and child devices that are available for\r\n" +" configuration:\r\n" +" Shell> drvcfg -c\r\n" +" \r\n" +" * To force defaults on all devices:\r\n" +" Shell> drvcfg -f 0\r\n" +" \r\n" +" * To force defaults on all devices that are managed by driver 0x17:\r\n" +" Shell> drvcfg -f 0 17\r\n" +" \r\n" +" * To force defaults on device 0x28 that is managed by driver 0x17:\r\n" +" Shell> drvcfg -f 0 17 28\r\n" +" \r\n" +" * To force defaults on all child devices of device 0x28 that is managed by\r\n" +" driver 0x17:\r\n" +" Shell> drvcfg -f 0 17 28 -c\r\n" +" \r\n" +" * To force defaults on child device 0x30 of device 0x28 that is managed by\r\n" +" driver 0x17:\r\n" +" Shell> drvcfg -f 0 17 28 30\r\n" +" \r\n" +" * To validate options on all devices:\r\n" +" Shell> drvcfg -v\r\n" +" \r\n" +" * To validate options on all devices that are managed by driver 0x17:\r\n" +" Shell> drvcfg -v 17\r\n" +" \r\n" +" * To validate options on device 0x28 that is managed by driver 0x17:\r\n" +" Shell> drvcfg -v 17 28\r\n" +" \r\n" +" * To validate options on all child devices of device 0x28 that is managed by\r\n" +" driver 0x17:\r\n" +" Shell> drvcfg -v 17 28 -c\r\n" +" \r\n" +" * To validate options on child device 0x30 of device 0x28 that is managed by\r\n" +" driver 0x17:\r\n" +" Shell> drvcfg -v 17 28 30\r\n" +" \r\n" +" * To set options on device 0x28 that is managed by driver 0x17: \r\n" +" Shell> drvcfg -s 17 28\r\n" +" \r\n" +" * To set options on child device 0x30 of device 0x28 that is managed by\r\n" +" driver 0x17:\r\n" +" Shell> drvcfg -s 17 28 30\r\n" +" \r\n" +" * To set options on device 0x28 that is managed by driver 0x17 in English:\r\n" +" Shell> drvcfg -s 17 28 -l eng\r\n" +" \r\n" +" * To set options on device 0x28 that is managed by driver 0x17 in Spanish:\r\n" +" Shell> drvcfg -s 17 28 -l spa\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_DRIVERS #language en-US "" +".TH drivers 0 "display a list of drivers"\r\n" +".SH NAME\r\n" +"Displays the UEFI driver list.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DRIVERS [-l XXX] [-sfo] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -l - Displays drivers using the specified language (e.g. ISO 639-2) \r\n" +" -sfo - Displays information as described in Standard-Format Output.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays a list of information for drivers that follow the\r\n" +" UEFI Driver Model in the UEFI environment. The list includes:\r\n" +" DRV - The handle number of the UEFI driver.\r\n" +" VERSION - The version number of the UEFI driver.\r\n" +" TYPE - The driver type:\r\n" +" [B] - Bus Driver\r\n" +" [D] - Device Driver\r\n" +" CFG - Driver supports the Driver Configuration Protocol.\r\n" +" DIAG - Driver supports the Driver Diagnostics Protocol.\r\n" +" #D - The number of devices that this driver is managing.\r\n" +" #C - The number of child devices that this driver has produced.\r\n" +" DRIVER NAME - The name of the driver from the Component Name Protocol.\r\n" +" IMAGE PATH - The file path from which the driver was loaded.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the list:\r\n" +" Shell> drivers\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_DISCONNECT #language en-US "" +".TH disconnect 0 "disconnect a driver"\r\n" +".SH NAME\r\n" +"Disconnects one or more drivers from the specified devices. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DISCONNECT DeviceHandle [DriverHandle [ChildHandle]] \r\n" +"DISCONNECT -r [-nc] \r\n" +".SH OPTIONS\r\n" +" \r\n" +"NOTES:\r\n" +" -r - Disconnects all drivers from all devices, then reconnect\r\n" +" consoles.\r\n" +" -nc - Do not reconnect the console devices.\r\n" +" DeviceHandle - Specifies a device handle (a hexadecimal number). If not\r\n" +" specified, then disconnect DriverHandle.\r\n" +" DriverHandle - Specifies a driver handle (a hexadecimal number).\r\n" +" ChildHandle - Specifies a child handle of a device (a hexadecimal number).\r\n" +" If not specified, then all child handles of DeviceHandle are\r\n" +" disconnected.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. If the 'DriverHandle' parameter is not specified, the default is to\r\n" +" disconnect 'DeviceHandle'.\r\n" +" 2. If the 'ChildHandle' parameter is not specified, the default is to\r\n" +" disconnect all child handles of the 'DeviceHandle'.\r\n" +" 3. If the '-r' option is specified, all consoles and drivers will be\r\n" +" disconnected from all devices in the system, then consoles are\r\n" +" reconnected. If the '-nc' option is also spcified, then console devices\r\n" +" are not reconnected.\r\n" +" 4. This command does not support output redirection.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To disconnect all drivers from all devices, then reconnect console\r\n" +" devices:\r\n" +" Shell> disconnect -r\r\n" +" \r\n" +" * To disconnect all drivers from all devices, including console devices:\r\n" +" Shell> disconnect -r -nc\r\n" +" \r\n" +" * To disconnect all drivers from device 0x28:\r\n" +" fs0:\> disconnect 28\r\n" +" \r\n" +" * To disconnect driver 0x17 from device 0x28:\r\n" +" fs0:\> disconnect 28 17\r\n" +" \r\n" +" * To disconnect driver 0x17 from controlling the child 0x32 of device 0x28:\r\n" +" fs0:\> disconnect 28 17 32\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_DH #language en-US "" +".TH dh 0 "displays list of handles"\r\n" +".SH NAME\r\n" +"Displays the device handles in the UEFI environment. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DH [-l ] [handle | -p ] [-d] [-v] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -p - Dumps all handles of a protocol specified by the GUID.\r\n" +" -d - Dumps UEFI Driver Model-related information.\r\n" +" -l - Dumps information using the language codes (e.g. ISO 639-2).\r\n" +" -sfo - Displays information as described in Standard-Format Output.\r\n" +" -v - Dumps verbose information about a specific handle.\r\n" +" handle - Specifies a handle to dump information about (a hexadecimal number).\r\n" +" If not present, then all information will be dumped.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. When neither 'handle' nor 'prot_id' is specified, a list of all the\r\n" +" device handles in the UEFI environment is displayed. \r\n" +" 2. The '-d' option displays UEFI Driver Model related information including\r\n" +" parent handles, child handles, all drivers installed on the handle, etc.\r\n" +" 3. The '-v' option displays verbose information for the specified handle\r\n" +" including all the protocols on the handle and their details.\r\n" +" 4. If the '-p' option is specified, all handles containing the specified\r\n" +" protocol will be displayed. Otherwise, the 'handle' parameter has to be\r\n" +" specified for display. In this case, the '-d' option will be enabled\r\n" +" automatically if the '-v' option is not specified.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all handles and display one screen at a time:\r\n" +" Shell> dh -b\r\n" +" \r\n" +" * To display the detailed information on handle 0x30:\r\n" +" Shell> dh 30\r\n" +" \r\n" +" * To display all handles with 'diskio' protocol:\r\n" +" Shell> dh -p diskio\r\n" +" \r\n" +" * To display all handles with 'LoadedImage' protocol and break when the screen is\r\n" +" full:\r\n" +" Shell> dh -p LoadedImage -b\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_DEVTREE #language en-US "" +".TH devtree 0 "display device tree"\r\n" +".SH NAME\r\n" +"Displays the UEFI Driver Model compliant device tree.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DEVTREE [-b] [-d] [-l XXX] [DeviceHandle] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time.\r\n" +" -d - Displays the device tree using device paths.\r\n" +" -l - Displays the device tree using the specified language.\r\n" +" DeviceHandle - Displays the device tree below a certain handle.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command prints a tree of devices that are being managed by drivers\r\n" +" that follow the UEFI Driver Model. By default, the devices are printed in\r\n" +" device names that are retrieved from the Component Name Protocol.\r\n" +" 2. If the option -d is specified, the device paths will be printed instead.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the tree of all devices compliant with the UEFI Driver Model:\r\n" +" Shell> devtree\r\n" +" \r\n" +" * To display the tree of all devices below device 28 compliant with the UEFI\r\n" +" Driver Model:\r\n" +" Shell> devtree 28\r\n" +" \r\n" +" * To display the tree of all devices compliant with the UEFI Driver Model\r\n" +" one screen at a time:\r\n" +" Shell> devtree -b\r\n" +" \r\n" + +#string STR_GET_HELP_DEVICES #language en-US "" +".TH devices 0 "display a list of devices"\r\n" +".SH NAME\r\n" +"Displays the list of devices managed by UEFI drivers. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DEVICES [-b] [-l XXX] [-sfo] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Display one screen at a time\r\n" +" -l XXX - Display devices using the specified ISO 639-2 language\r\n" +" -sfo - Displays information as described in Standard-Format Output.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The command prints a list of devices that are being managed by drivers\r\n" +" that follow the UEFI Driver Model.\r\n" +" 2. Display Format:\r\n" +" CTRL - The handle number of the UEFI device\r\n" +" TYPE - The device type:\r\n" +" [R] - Root Controller\r\n" +" [B] - Bus Controller\r\n" +" [D] - Device Controller\r\n" +" CFG - A managing driver supports the Driver Configuration\r\n" +" Protocol. Yes if 'Y' or 'X'; No if 'N' or '-'.\r\n" +" DIAG - A managing driver supports the Driver Diagnostics\r\n" +" Protocol. Yes if 'Y' or 'X'; No if 'N' or '-'.\r\n" +" #P - The number of parent controllers for this device\r\n" +" #D - The number of drivers managing the device\r\n" +" #C - The number of child controllers produced by this device\r\n" +" DEVICE NAME - The name of the device from the Component Name Protocol\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all devices compliant with the UEFI Driver Model:\r\n" +" Shell> devices\r\n" +" \r\n" + +#string STR_GET_HELP_CONNECT #language en-US "" +".TH connect 0 "connect a driver"\r\n" +".SH NAME\r\n" +"Binds a driver to a specific device and starts the driver. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"CONNECT [[DeviceHandle] [DriverHandle] | [-c] | [-r]] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -c - Connects console devices\r\n" +" -r - Connects recursively\r\n" +" DeviceHandle - Specifies a device handle in hexadecimal format.\r\n" +" DriverHandle - Specifies a driver handle in hexadecimal format.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. If no 'DeviceHandle' parameter is specified, all device handles in the\r\n" +" current system will be the default.\r\n" +" 2. If no 'DriverHandle' parameter is specified, all matched drivers will be\r\n" +" bound to the specified device.\r\n" +" 3. If 'DriverHandle' parameter is provided, the specified driver will have\r\n" +" highest priority on connecting the device(s).\r\n" +" 4. If the '-c' option is specified, only console devices described in the\r\n" +" UEFI Shell environment variables and related devices will be connected.\r\n" +" 5. If the '-r' option is specified, the command will recursively scan all\r\n" +" handles and check to see if any loaded or embedded driver can match the\r\n" +" specified device. If so, the driver will be bound to the device.\r\n" +" Additionally, if more device handles are created during the binding, \r\n" +" these handles will also be checked to see if a matching driver can bind\r\n" +" to these devices as well. The process is repeated until no more drivers\r\n" +" are able to connect to any devices. However, without the option, the\r\n" +" newly created device handles will not be further bound to any\r\n" +" drivers.\r\n" +" 6. If only a single handle is specified and the handle has an\r\n" +" EFI_DRIVER_BINDING_PROTOCOL on it, then the handle is assumed to be a\r\n" +" driver handle. Otherwise, it is assumed to be a device handle.\r\n" +" 7. If no parameters are specified, then the command will attempt to bind\r\n" +" all proper drivers to all devices without recursion. Each connection\r\n" +" status will be displayed.\r\n" +" 8. Output redirection is not supported for 'connect -r' usage.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To connect all drivers to all devices recursively:\r\n" +" Shell> connect -r\r\n" +" \r\n" +" * To display all connections:\r\n" +" Shell> connect\r\n" +" \r\n" +" * To connect drivers with 0x17 as highest priority to all the devices they\r\n" +" can manage:\r\n" +" Shell> connect 17\r\n" +" \r\n" +" * To connect all possible drivers to device 0x19:\r\n" +" Shell> connect 19\r\n" +" \r\n" +" * To connect drivers with 0x17 as highest priority to device 0x19 they can\r\n" +" manage:\r\n" +" Shell> connect 19 17\r\n" +" \r\n" +" * To connect console devices described in the UEFI Shell environment\r\n" +" variables:\r\n" +" Shell> connect -c\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_OPENINFO #language en-US "" +".TH openinfo 0 "display info about a handle."\r\n" +".SH NAME\r\n" +"Displays the protocols and agents associated with a handle. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"OPENINFO Handle [-b] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -b - Displays one screen at a time.\r\n" +" Handle - Displays open protocol information for the specified handle.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command is used to display the open protocols on a given handle.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To show open protocols on handle 0x23:\r\n" +" Shell> openinfo 23\r\n" +" \r\n" + +#string STR_GET_HELP_DRVDIAG #language en-US "" +".TH drvdiag 0 "diagnose a driver"\r\n" +".SH NAME\r\n" +"Invokes the Driver Diagnostics Protocol. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DRVDIAG [-c] [-l XXX] [-s|-e|-m] [DriverHandle [DeviceHandle [ChildHandle]]] \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -c - Diagnoses all child devices.\r\n" +" -l - Diagnoses using the ISO 639-2 language specified by XXX.\r\n" +" -s - Runs diagnostics in standard mode.\r\n" +" -e - Runs diagnostics in extended mode.\r\n" +" -m - Runs diagnostics in manufacturing mode.\r\n" +" DriverHandle - Specifies the handle of the driver to diagnose.\r\n" +" DeviceHandle - Specifies the handle of a device that DriverHandle is managing.\r\n" +" ChildHandle - Specifies the handle of a device that is a child of DeviceHandle.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command invokes the Driver Diagnostics Protocol.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the list of devices that are available for diagnostics:\r\n" +" Shell> drvdiag\r\n" +" \r\n" +" * To display the list of devices and child devices that are available for\r\n" +" diagnostics:\r\n" +" Shell> drvdiag -c\r\n" +" \r\n" +" * To run diagnostics in standard mode on all devices:\r\n" +" Shell> drvdiag -s\r\n" +" \r\n" +" * To run diagnostics in standard mode on all devices in English:\r\n" +" Shell> drvdiag -s -l eng\r\n" +" \r\n" +" * To run diagnostics in standard mode on all devices in Spanish:\r\n" +" Shell> drvdiag -s -l spa\r\n" +" \r\n" +" * To run diagnostics in standard mode on all devices and child devices:\r\n" +" Shell> drvdiag -s -c\r\n" +" \r\n" +" * To run diagnostics in extended mode on all devices:\r\n" +" Shell> drvdiag -e\r\n" +" \r\n" +" * To run diagnostics in manufacturing mode on all devices:\r\n" +" Shell> drvdiag -m\r\n" +" \r\n" +" * To run diagnostics in standard mode on all devices managed by driver 0x17:\r\n" +" Shell> drvdiag -s 17\r\n" +" \r\n" +" * To run diagnostics in standard mode on device 0x28 managed by driver 0x17:\r\n" +" Shell> drvdiag -s 17 28\r\n" +" \r\n" +" * To run diagnostics in standard mode on all child devices of device 0x28\r\n" +" managed by driver 0x17:\r\n" +" Shell> drvdiag -s 17 28 -c\r\n" +" \r\n" +" * To run diagnostics in standard mode on child device 0x30 of device 0x28\r\n" +" managed by driver 0x17:\r\n" +" Shell> drvdiag -s 17 28 30\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_RECONNECT #language en-US "" +".TH reconnect 0 "reconnect drivers"\r\n" +".SH NAME\r\n" +"Reconnects drivers to the specific device. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"RECONNECT DeviceHandle [DriverHandle [ChildHandle]]\r\n" +"RECONNECT -r \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Reconnects drivers to all devices.\r\n" +" DeviceHandle - Specifies a device handle (a hexadecimal number).\r\n" +" DriverHandle - Specifies a driver handle (a hexadecimal number). If not specified, all\r\n" +" drivers on the specified device will be reconnected. \r\n" +" ChildHandle - Specifies the child handle of device (a hexadecimal number). If not\r\n" +" specified, then all child handles of the specified device are\r\n" +" reconnected.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command reconnects drivers to the specific device. It will first\r\n" +" disconnect the specified driver from the specified device and then connect\r\n" +" the driver to the device recursively.\r\n" +" 2. If the -r option is used, then all drivers will be reconnected to all\r\n" +" devices. Any drivers that are bound to any devices will be disconnected\r\n" +" first and then connected recursively.\r\n" +" 3. See the connect and disconnect commands for more details. \r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To reconnect all drivers to all devices:\r\n" +" Shell> reconnect -r\r\n" +" \r\n" +" * To reconnect all drivers to device 0x28:\r\n" +" fs0:\> reconnect 28\r\n" +" \r\n" +" * To disconnect 0x17 from 0x28 then reconnect drivers with 0x17 as highest\r\n" +" priority to device 0x28:\r\n" +" fs0:\> reconnect 28 17\r\n" +" \r\n" +" * To disconnect 0x17 from 0x28 destroying child 0x32 then reconnect drivers\r\n" +" with 0x17 as highest priority to device 0x28\r\n" +" fs0:\> reconnect 28 17 32\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_UNLOAD #language en-US "" +".TH unload 0 "unload a driver"\r\n" +".SH NAME\r\n" +"Unloads a driver image that was already loaded. \r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"UNLOAD [-n] [-v|-verbose] Handle \r\n" +".SH OPTIONS\r\n" +" \r\n" +" -n - Skips all prompts during unloading, so that it can be used\r\n" +" in a script file.\r\n" +" -v, -verbose - Dumps verbose status information before the image is unloaded.\r\n" +" Handle - Specifies the handle of driver to unload, always taken as hexadecimal number.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The '-n' option can be used to skip all prompts during unloading.\r\n" +" 2. If the '-v' option is specified, verbose image information will be\r\n" +" displayed before the image is unloaded.\r\n" +" 3. Only drivers that support unloading can be successfully unloaded.\r\n" +" 4. Use the 'LOAD' command to load a driver.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To find the handle for the UEFI driver image to unload:\r\n" +" Shell> dh -b\r\n" +" \r\n" +" * To unload the UEFI driver image with handle 27:\r\n" +" Shell> unload 27\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + + + + + + + + + + + + + + + + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c new file mode 100644 index 0000000..15c2a0c --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c @@ -0,0 +1,148 @@ +/** @file + Main file for Unload shell Driver1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellDriver1CommandsLib.h" + +/** + Function to dump LoadedImage info from TheHandle. + + @param[in] TheHandle The handle to dump info from. + + @retval EFI_SUCCESS The info was dumped. + @retval EFI_INVALID_PARAMETER The handle did not have LoadedImage +**/ +EFI_STATUS +DumpLoadedImageProtocolInfo ( + IN EFI_HANDLE TheHandle + ) +{ + CHAR16 *TheString; + + TheString = GetProtocolInformationDump(TheHandle, &gEfiLoadedImageProtocolGuid, TRUE); + + ShellPrintEx(-1, -1, L"%s", TheString); + + SHELL_FREE_NON_NULL(TheString); + + return (EFI_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-n", TypeFlag}, + {L"-v", TypeFlag}, + {L"-verbose", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'unload' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunUnload ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + EFI_HANDLE TheHandle; + CONST CHAR16 *Param1; + SHELL_PROMPT_RESPONSE *Resp; + UINT64 Value; + + ShellStatus = SHELL_SUCCESS; + Package = NULL; + Resp = NULL; + Value = 0; + TheHandle = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle,L"unload", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetCount(Package) > 2){ + // + // error for too many parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"unload"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetCount(Package) < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"unload"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Param1 = ShellCommandLineGetRawValue(Package, 1); + if (Param1 != NULL) { + Status = ShellConvertStringToUint64(Param1, &Value, TRUE, FALSE); + TheHandle = ConvertHandleIndexToHandle((UINTN)Value); + } + + if (EFI_ERROR(Status) || Param1 == NULL || TheHandle == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"unload", Param1); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(TheHandle != NULL); + if (ShellCommandLineGetFlag(Package, L"-v") || ShellCommandLineGetFlag(Package, L"-verbose")) { + DumpLoadedImageProtocolInfo(TheHandle); + } + + if (!ShellCommandLineGetFlag(Package, L"-n")) { + Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_UNLOAD_CONF), gShellDriver1HiiHandle, (UINTN)TheHandle); + Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp); + } + if (ShellCommandLineGetFlag(Package, L"-n") || (Resp != NULL && *Resp == ShellPromptResponseYes)) { + Status = gBS->UnloadImage(TheHandle); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Unload", (UINTN)TheHandle, Status); + } + SHELL_FREE_NON_NULL(Resp); + } + } + } + if (ShellStatus == SHELL_SUCCESS) { + if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (Status == EFI_INVALID_PARAMETER) { + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (EFI_ERROR(Status)) { + ShellStatus = SHELL_NOT_FOUND; + } + } + + if (Package != NULL) { + ShellCommandLineFreeVarList(Package); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c new file mode 100644 index 0000000..205ebd9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c @@ -0,0 +1,59 @@ +/** @file + Main file for NULL named library for install1 shell command functions. + + Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +/** + Constructor for the Shell Level 1 Commands library. + + Install the handlers for level 1 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellInstall1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // check our bit of the profiles mask + // + if ((PcdGet8(PcdShellProfileMask) & BIT2) == 0) { + return (EFI_SUCCESS); + } + + return (BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Install1")); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +ShellInstall1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return (BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable)); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf new file mode 100644 index 0000000..c244d93 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf @@ -0,0 +1,51 @@ +## @file +# Provides shell install1 functions +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellInstall1CommandsLib + FILE_GUID = D250E364-51C6-49ed-AEBF-6D83F5130F74 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellInstall1CommandsLibConstructor + DESTRUCTOR = ShellInstall1CommandsLibDestructor + +[Sources.common] + UefiShellInstall1CommandsLib.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + BcfgCommandLib + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Guids] + gShellInstall1HiiGuid ## UNDEFINED diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c new file mode 100644 index 0000000..d8ca4a3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c @@ -0,0 +1,97 @@ +/** @file + Main file for exit shell level 1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"/b", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'exit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT64 RetVal; + CONST CHAR16 *Return; + + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, L"exit", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + + // + // return the specified error code + // + Return = ShellCommandLineGetRawValue(Package, 1); + if (Return != NULL) { + Status = ShellConvertStringToUint64(Return, &RetVal, FALSE, FALSE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel1HiiHandle, L"exit", Return); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // If we are in a batch file and /b then pass TRUE otherwise false... + // + ShellCommandRegisterExit((BOOLEAN)(gEfiShellProtocol->BatchIsActive() && ShellCommandLineGetFlag(Package, L"/b")), RetVal); + + ShellStatus = SHELL_SUCCESS; + } + } else { + // If we are in a batch file and /b then pass TRUE otherwise false... + // + ShellCommandRegisterExit((BOOLEAN)(gEfiShellProtocol->BatchIsActive() && ShellCommandLineGetFlag(Package, L"/b")), 0); + + ShellStatus = SHELL_SUCCESS; + } + + ShellCommandLineFreeVarList (Package); + } + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c new file mode 100644 index 0000000..30ad006 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c @@ -0,0 +1,751 @@ +/** @file + Main file for endfor and for shell level 1 functions. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" +#include + +/** + Determine if a valid string is a valid number for the 'for' command. + + @param[in] Number The pointer to the string representation of the number to test. + + @retval TRUE The number is valid. + @retval FALSE The number is not valid. +**/ +BOOLEAN +ShellIsValidForNumber ( + IN CONST CHAR16 *Number + ) +{ + if (Number == NULL || *Number == CHAR_NULL) { + return (FALSE); + } + + if (*Number == L'-') { + Number++; + } + + if (StrLen(Number) == 0) { + return (FALSE); + } + + if (StrLen(Number) >= 7) { + if ((StrStr(Number, L" ") == NULL) || (((StrStr(Number, L" ") != NULL) && (StrStr(Number, L" ") - Number) >= 7))) { + return (FALSE); + } + } + + if (!ShellIsDecimalDigitCharacter(*Number)) { + return (FALSE); + } + + return (TRUE); +} + +/** + Function for 'endfor' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + BOOLEAN Found; + SCRIPT_FILE *CurrentScriptFile; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"endfor"); + return (SHELL_UNSUPPORTED); + } + + if (gEfiShellParametersProtocol->Argc > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"endfor"); + return (SHELL_INVALID_PARAMETER); + } + + Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE); + + if (!Found) { + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"For", + L"EndFor", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + return (SHELL_NOT_FOUND); + } + return (SHELL_SUCCESS); +} + +typedef struct { + UINT32 Signature; + INTN Current; + INTN End; + INTN Step; + CHAR16 *ReplacementName; + CHAR16 *CurrentValue; + BOOLEAN RemoveSubstAlias; + CHAR16 Set[1]; + } SHELL_FOR_INFO; +#define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set) +#define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's') + +/** + Update the value of a given alias on the list. If the alias is not there then add it. + + @param[in] Alias The alias to test for. + @param[in] CommandString The updated command string. + @param[in, out] List The list to search. + + @retval EFI_SUCCESS The operation was completed successfully. + @retval EFI_OUT_OF_RESOURCES There was not enough free memory. +**/ +EFI_STATUS +InternalUpdateAliasOnList( + IN CONST CHAR16 *Alias, + IN CONST CHAR16 *CommandString, + IN OUT LIST_ENTRY *List + ) +{ + ALIAS_LIST *Node; + BOOLEAN Found; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE + ; !IsNull(List, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (StrCmp(Node->Alias, Alias)==0) { + FreePool(Node->CommandString); + Node->CommandString = NULL; + Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0); + Found = TRUE; + break; + } + } + if (!Found) { + Node = AllocateZeroPool(sizeof(ALIAS_LIST)); + if (Node == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + ASSERT(Node->Alias == NULL); + Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0); + ASSERT(Node->CommandString == NULL); + Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0); + InsertTailList(List, &Node->Link); + } + return (EFI_SUCCESS); +} + +/** + Find out if an alias is on the given list. + + @param[in] Alias The alias to test for. + @param[in] List The list to search. + + @retval TRUE The alias is on the list. + @retval FALSE The alias is not on the list. +**/ +BOOLEAN +InternalIsAliasOnList( + IN CONST CHAR16 *Alias, + IN CONST LIST_ENTRY *List + ) +{ + ALIAS_LIST *Node; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(List) + ; !IsNull(List, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (StrCmp(Node->Alias, Alias)==0) { + return (TRUE); + } + } + return (FALSE); +} + +/** + Remove an alias from the given list. + + @param[in] Alias The alias to remove. + @param[in, out] List The list to search. +**/ +BOOLEAN +InternalRemoveAliasFromList( + IN CONST CHAR16 *Alias, + IN OUT LIST_ENTRY *List + ) +{ + ALIAS_LIST *Node; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(List) + ; !IsNull(List, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (StrCmp(Node->Alias, Alias)==0) { + RemoveEntryList(&Node->Link); + FreePool(Node->Alias); + FreePool(Node->CommandString); + FreePool(Node); + return (TRUE); + } + } + return (FALSE); +} + +/** + Function to determine whether a string is decimal or hex representation of a number + and return the number converted from the string. + + @param[in] String String representation of a number + + @return the number + @retval (UINTN)(-1) An error ocurred. +**/ +UINTN +ReturnUintn( + IN CONST CHAR16 *String + ) +{ + UINT64 RetVal; + + if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, FALSE, TRUE))) { + return ((UINTN)RetVal); + } + return ((UINTN)(-1)); +} + +/** + Function for 'for' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + SCRIPT_FILE *CurrentScriptFile; + CHAR16 *ArgSet; + CHAR16 *ArgSetWalker; + CHAR16 *Parameter; + UINTN ArgSize; + UINTN LoopVar; + SHELL_FOR_INFO *Info; + CHAR16 *TempString; + CHAR16 *TempSpot; + BOOLEAN FirstPass; + EFI_SHELL_FILE_INFO *Node; + EFI_SHELL_FILE_INFO *FileList; + UINTN NewSize; + + ArgSet = NULL; + ArgSize = 0; + ShellStatus = SHELL_SUCCESS; + ArgSetWalker = NULL; + TempString = NULL; + Parameter = NULL; + FirstPass = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"for"); + return (SHELL_UNSUPPORTED); + } + + if (gEfiShellParametersProtocol->Argc < 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"for"); + return (SHELL_INVALID_PARAMETER); + } + + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ASSERT(CurrentScriptFile != NULL); + + if ((CurrentScriptFile->CurrentCommand != NULL) && (CurrentScriptFile->CurrentCommand->Data == NULL)) { + FirstPass = TRUE; + + // + // Make sure that an End exists. + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"EndFor", + L"For", + CurrentScriptFile->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + + // + // Process the line. + // + if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL + ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z') + ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z')) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[1]); + return (SHELL_INVALID_PARAMETER); + } + + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + L"in", + gEfiShellParametersProtocol->Argv[2]) == 0) { + for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL)); + if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL + ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL + ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL + ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) { + FileList = NULL; + Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } else { + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } + ShellCloseFileMetaArg(&FileList); + } + } else { + Parameter = gEfiShellParametersProtocol->Argv[LoopVar]; + if (Parameter[0] == L'\"' && Parameter[StrLen(Parameter)-1] == L'\"') { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0); + } else { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } + } + } + if (ArgSet == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + // + // set up for an 'in' for loop + // + NewSize = StrSize(ArgSet); + NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]); + Info = AllocateZeroPool(NewSize); + if (Info == NULL) { + FreePool (ArgSet); + return SHELL_OUT_OF_RESOURCES; + } + Info->Signature = SHELL_FOR_INFO_SIGNATURE; + CopyMem(Info->Set, ArgSet, StrSize(ArgSet)); + NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]); + CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize); + Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]); + Info->CurrentValue = (CHAR16*)Info->Set; + Info->Step = 0; + Info->Current = 0; + Info->End = 0; + + if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) { + Info->RemoveSubstAlias = FALSE; + } else { + Info->RemoveSubstAlias = TRUE; + } + CurrentScriptFile->CurrentCommand->Data = Info; + } + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + L"run", + gEfiShellParametersProtocol->Argv[2]) == 0) { + for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL)); + if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L")") != NULL && + (LoopVar + 1) < gEfiShellParametersProtocol->Argc + ) { + return (SHELL_INVALID_PARAMETER); + } + if (ArgSet == NULL) { +// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } else { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); + } + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); +// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); + } + if (ArgSet == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + // + // set up for a 'run' for loop + // + Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1])); + if (Info == NULL) { + FreePool (ArgSet); + return SHELL_OUT_OF_RESOURCES; + } + Info->Signature = SHELL_FOR_INFO_SIGNATURE; + CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1])); + Info->ReplacementName = Info->Set; + Info->CurrentValue = NULL; + ArgSetWalker = ArgSet; + if (ArgSetWalker[0] != L'(') { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + ArgSet, + CurrentScriptFile->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempSpot = StrStr(ArgSetWalker, L")"); + if (TempSpot != NULL) { + TempString = TempSpot+1; + if (*(TempString) != CHAR_NULL) { + while(TempString != NULL && *TempString == L' ') { + TempString++; + } + if (StrLen(TempString) > 0) { + TempSpot = NULL; + } + } + } + if (TempSpot == NULL) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + CurrentScriptFile->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + *TempSpot = CHAR_NULL; + ArgSetWalker++; + while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { + ArgSetWalker++; + } + if (!ShellIsValidForNumber(ArgSetWalker)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + ArgSet, + CurrentScriptFile->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ArgSetWalker[0] == L'-') { + Info->Current = 0 - (INTN)ReturnUintn(ArgSetWalker+1); + } else { + Info->Current = (INTN)ReturnUintn(ArgSetWalker); + } + ArgSetWalker = StrStr(ArgSetWalker, L" "); + while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { + ArgSetWalker++; + } + if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){ + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + ArgSet, + CurrentScriptFile->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ArgSetWalker[0] == L'-') { + Info->End = 0 - (INTN)ReturnUintn(ArgSetWalker+1); + } else { + Info->End = (INTN)ReturnUintn(ArgSetWalker); + } + if (Info->Current < Info->End) { + Info->Step = 1; + } else { + Info->Step = -1; + } + + ArgSetWalker = StrStr(ArgSetWalker, L" "); + while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { + ArgSetWalker++; + } + if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) { + if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){ + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + ArgSet, + CurrentScriptFile->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (*ArgSetWalker == L')') { + ASSERT(Info->Step == 1 || Info->Step == -1); + } else { + if (ArgSetWalker[0] == L'-') { + Info->Step = 0 - (INTN)ReturnUintn(ArgSetWalker+1); + } else { + Info->Step = (INTN)ReturnUintn(ArgSetWalker); + } + + if (StrStr(ArgSetWalker, L" ") != NULL) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + ArgSet, + CurrentScriptFile->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + + } + } + } + } + } + if (ShellStatus == SHELL_SUCCESS) { + if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) { + Info->RemoveSubstAlias = FALSE; + } else { + Info->RemoveSubstAlias = TRUE; + } + } + if (CurrentScriptFile->CurrentCommand != NULL) { + CurrentScriptFile->CurrentCommand->Data = Info; + } + } + } else { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), + gShellLevel1HiiHandle, + ArgSet, + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // These need to be NULL since they are used to determine if this is the first pass later on... + // + ASSERT(ArgSetWalker == NULL); + ASSERT(ArgSet == NULL); + } + + if (CurrentScriptFile != NULL && CurrentScriptFile->CurrentCommand != NULL) { + Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data; + if (CurrentScriptFile->CurrentCommand->Reset) { + if (Info != NULL) { + Info->CurrentValue = (CHAR16*)Info->Set; + } + FirstPass = TRUE; + CurrentScriptFile->CurrentCommand->Reset = FALSE; + } + } else { + ShellStatus = SHELL_UNSUPPORTED; + Info = NULL; + } + if (ShellStatus == SHELL_SUCCESS) { + ASSERT(Info != NULL); + if (Info->Step != 0) { + // + // only advance if not the first pass + // + if (!FirstPass) { + // + // sequence version of for loop... + // + Info->Current += Info->Step; + } + + TempString = AllocateZeroPool(50*sizeof(CHAR16)); + UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current); + InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList); + FreePool(TempString); + + if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) { + CurrentScriptFile->CurrentCommand->Data = NULL; + // + // find the matching endfor (we're done with the loop) + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"EndFor", + L"For", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + ShellStatus = SHELL_DEVICE_ERROR; + } + if (Info->RemoveSubstAlias) { + // + // remove item from list + // + InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList); + } + FreePool(Info); + } + } else { + // + // Must be in 'in' version of for loop... + // + ASSERT(Info->Set != NULL); + if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) { + if (Info->CurrentValue[0] == L' ') { + Info->CurrentValue++; + } + if (Info->CurrentValue[0] == L'\"') { + Info->CurrentValue++; + } + // + // do the next one of the set + // + ASSERT(TempString == NULL); + TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0); + if (TempString == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + TempSpot = StrStr(TempString, L"\" \""); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + while (TempString[StrLen(TempString)-1] == L'\"') { + TempString[StrLen(TempString)-1] = CHAR_NULL; + } + InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList); + Info->CurrentValue += StrLen(TempString); + + if (Info->CurrentValue[0] == L'\"') { + Info->CurrentValue++; + } + FreePool(TempString); + } + } else { + CurrentScriptFile->CurrentCommand->Data = NULL; + // + // find the matching endfor (we're done with the loop) + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"EndFor", + L"For", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + ShellStatus = SHELL_DEVICE_ERROR; + } + if (Info->RemoveSubstAlias) { + // + // remove item from list + // + InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList); + } + FreePool(Info); + } + } + } + if (ArgSet != NULL) { + FreePool(ArgSet); + } + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c new file mode 100644 index 0000000..78f24c9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c @@ -0,0 +1,105 @@ +/** @file + Main file for goto shell level 1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +/** + Function for 'goto' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunGoto ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR16 *CompareString; + UINTN Size; + SCRIPT_FILE *CurrentScriptFile; + + ShellStatus = SHELL_SUCCESS; + CompareString = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Goto"); + return (SHELL_UNSUPPORTED); + } + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, L"goto", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"goto"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"goto"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Size = 0; + ASSERT((CompareString == NULL && Size == 0) || (CompareString != NULL)); + CompareString = StrnCatGrow(&CompareString, &Size, L":", 0); + CompareString = StrnCatGrow(&CompareString, &Size, ShellCommandLineGetRawValue(Package, 1), 0); + // + // Check forwards and then backwards for a label... + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", CompareString, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, TRUE)) { + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + CompareString, + L"Goto", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + ShellStatus = SHELL_NOT_FOUND; + } + FreePool(CompareString); + } + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c new file mode 100644 index 0000000..1fc1551 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c @@ -0,0 +1,1111 @@ +/** @file + Main file for If and else shell level 1 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" +#include + +typedef enum { + EndTagOr, + EndTagAnd, + EndTagThen, + EndTagMax +} END_TAG_TYPE; + +typedef enum { + OperatorGreaterThan, + OperatorLessThan, + OperatorEqual, + OperatorNotEqual, + OperatorGreatorOrEqual, + OperatorLessOrEqual, + OperatorUnisgnedGreaterThan, + OperatorUnsignedLessThan, + OperatorUnsignedGreaterOrEqual, + OperatorUnsignedLessOrEqual, + OperatorMax +} BIN_OPERATOR_TYPE; + +/** + Extract the next fragment, if there is one. + + @param[in, out] Statement The current remaining statement. + @param[in] Fragment The current fragment. + @param[out] Match TRUE when there is another Fragment in Statement, + FALSE otherwise. + + @retval EFI_SUCCESS The match operation is performed successfully. + @retval EFI_OUT_OF_RESOURCES Out of resources. +**/ +EFI_STATUS +IsNextFragment ( + IN OUT CONST CHAR16 **Statement, + IN CONST CHAR16 *Fragment, + OUT BOOLEAN *Match + ) +{ + CHAR16 *Tester; + + Tester = NULL; + + Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment)); + if (Tester == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Tester[StrLen(Fragment)] = CHAR_NULL; + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)Fragment, + Tester) == 0) { + // + // increment the string pointer to the end of what we found and then chop off spaces... + // + *Statement+=StrLen(Fragment); + while (*Statement[0] == L' ') { + (*Statement)++; + } + *Match = TRUE; + } else { + *Match = FALSE; + } + FreePool(Tester); + return EFI_SUCCESS; +} + +/** + Determine if String represents a valid profile. + + @param[in] String The pointer to the string to test. + + @retval TRUE String is a valid profile. + @retval FALSE String is not a valid profile. +**/ +BOOLEAN +IsValidProfile ( + IN CONST CHAR16 *String + ) +{ + CONST CHAR16 *ProfilesString; + CONST CHAR16 *TempLocation; + + ProfilesString = ShellGetEnvironmentVariable(L"profiles"); + ASSERT(ProfilesString != NULL); + TempLocation = StrStr(ProfilesString, String); + if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) { + return (TRUE); + } + return (FALSE); +} + +/** + Do a comparison between 2 things. + + @param[in] Compare1 The first item to compare. + @param[in] Compare2 The second item to compare. + @param[in] BinOp The type of comparison to perform. + @param[in] CaseInsensitive TRUE to do non-case comparison, FALSE otherwise. + @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise. + + @return The result of the comparison. +**/ +BOOLEAN +TestOperation ( + IN CONST CHAR16 *Compare1, + IN CONST CHAR16 *Compare2, + IN CONST BIN_OPERATOR_TYPE BinOp, + IN CONST BOOLEAN CaseInsensitive, + IN CONST BOOLEAN ForceStringCompare + ) +{ + INTN Cmp1; + INTN Cmp2; + + // + // "Compare1 BinOp Compare2" + // + switch (BinOp) { + case OperatorUnisgnedGreaterThan: + case OperatorGreaterThan: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (BinOp == OperatorGreaterThan) { + if (Cmp1 > Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 > (UINTN)Cmp2) { + return (TRUE); + } + } + } + return (FALSE); + case OperatorUnsignedLessThan: + case OperatorLessThan: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (BinOp == OperatorLessThan) { + if (Cmp1 < Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 < (UINTN)Cmp2) { + return (TRUE); + } + } + + } + return (FALSE); + case OperatorEqual: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (Cmp1 == Cmp2) { + return (TRUE); + } + } + return (FALSE); + case OperatorNotEqual: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (Cmp1 != Cmp2) { + return (TRUE); + } + } + return (FALSE); + case OperatorUnsignedGreaterOrEqual: + case OperatorGreatorOrEqual: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (BinOp == OperatorGreatorOrEqual) { + if (Cmp1 >= Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 >= (UINTN)Cmp2) { + return (TRUE); + } + } + } + return (FALSE); + case OperatorLessOrEqual: + case OperatorUnsignedLessOrEqual: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (BinOp == OperatorLessOrEqual) { + if (Cmp1 <= Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 <= (UINTN)Cmp2) { + return (TRUE); + } + } + } + return (FALSE); + default: + ASSERT(FALSE); + return (FALSE); + } +} + +/** + Process an if statement and determine if its is valid or not. + + @param[in, out] PassingState Opon entry, the current state. Upon exit, + the new state. + @param[in] StartParameterNumber The number of the first parameter of + this statement. + @param[in] EndParameterNumber The number of the final parameter of + this statement. + @param[in] OperatorToUse The type of termination operator. + @param[in] CaseInsensitive TRUE for case insensitive, FALSE otherwise. + @param[in] ForceStringCompare TRUE for all string based, FALSE otherwise. + + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ProcessStatement ( + IN OUT BOOLEAN *PassingState, + IN UINTN StartParameterNumber, + IN UINTN EndParameterNumber, + IN CONST END_TAG_TYPE OperatorToUse, + IN CONST BOOLEAN CaseInsensitive, + IN CONST BOOLEAN ForceStringCompare + ) +{ + EFI_STATUS Status; + BOOLEAN OperationResult; + BOOLEAN NotPresent; + CHAR16 *StatementWalker; + BIN_OPERATOR_TYPE BinOp; + CHAR16 *Compare1; + CHAR16 *Compare2; + CHAR16 HexString[20]; + CHAR16 *TempSpot; + BOOLEAN Match; + + ASSERT((END_TAG_TYPE)OperatorToUse != EndTagThen); + + Status = EFI_SUCCESS; + BinOp = OperatorMax; + OperationResult = FALSE; + Match = FALSE; + StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber]; + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not", &Match)) && Match) { + NotPresent = TRUE; + StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber]; + } else { + NotPresent = FALSE; + } + + // + // now check for 'boolfunc' operators + // + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint", &Match)) && Match) { + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match + && StatementWalker[StrLen(StatementWalker)-1] == L')') { + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE); + } else { + Status = EFI_INVALID_PARAMETER; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint"); + } + } else if ((!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists", &Match)) && Match) || + (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist", &Match)) && Match)) { + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && + StatementWalker[StrLen(StatementWalker)-1] == L')') { + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + // + // is what remains a file in CWD??? + // + OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS); + } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) { + OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)"); + Status = EFI_INVALID_PARAMETER; + } + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available", &Match)) && Match) { + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && + StatementWalker[StrLen(StatementWalker)-1] == L')') { + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + // + // is what remains a file in the CWD or path??? + // + OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available"); + Status = EFI_INVALID_PARAMETER; + } + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile", &Match)) && Match) { + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && + StatementWalker[StrLen(StatementWalker)-1] == L')') { + // + // Chop off that ')' + // + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + OperationResult = IsValidProfile(StatementWalker); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile"); + Status = EFI_INVALID_PARAMETER; + } + } else if (StartParameterNumber+1 >= EndParameterNumber) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]); + Status = EFI_INVALID_PARAMETER; + } else { + // + // must be 'item binop item' style + // + Compare1 = NULL; + Compare2 = NULL; + BinOp = OperatorMax; + + // + // get the first item + // + StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber]; + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror", &Match)) && Match) { + TempSpot = StrStr(StatementWalker, L")"); + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) { + *TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT); + ASSERT(Compare1 == NULL); + Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror", &Match)) && Match) { + TempSpot = StrStr(StatementWalker, L")"); + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) { + *TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2)); + ASSERT(Compare1 == NULL); + Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16**)(&StatementWalker), L"oemerror", &Match)) && Match) { + TempSpot = StrStr(StatementWalker, L")"); + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1)); + ASSERT(Compare1 == NULL); + Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ASSERT(Compare1 == NULL); + if (EndParameterNumber - StartParameterNumber > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]); + Status = EFI_INVALID_PARAMETER; + } else { + // + // must be a raw string + // + Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0); + } + } + + // + // get the operator + // + ASSERT(StartParameterNumber+1Argv[StartParameterNumber+1]; + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt", &Match)) && Match) { + BinOp = OperatorGreaterThan; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt", &Match)) && Match) { + BinOp = OperatorLessThan; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq", &Match)) && Match) { + BinOp = OperatorEqual; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne", &Match)) && Match) { + BinOp = OperatorNotEqual; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge", &Match)) && Match) { + BinOp = OperatorGreatorOrEqual; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le", &Match)) && Match) { + BinOp = OperatorLessOrEqual; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==", &Match)) && Match) { + BinOp = OperatorEqual; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt", &Match)) && Match) { + BinOp = OperatorUnisgnedGreaterThan; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult", &Match)) && Match) { + BinOp = OperatorUnsignedLessThan; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge", &Match)) && Match) { + BinOp = OperatorUnsignedGreaterOrEqual; + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule", &Match)) && Match) { + BinOp = OperatorUnsignedLessOrEqual; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker); + Status = EFI_INVALID_PARAMETER; + } + + // + // get the second item + // + ASSERT(StartParameterNumber+2<=EndParameterNumber); + StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2]; + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror", &Match)) && Match) { + TempSpot = StrStr(StatementWalker, L")"); + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT); + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + // + // can this be collapsed into the above? + // + } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror", &Match)) && Match) { + TempSpot = StrStr(StatementWalker, L")"); + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2)); + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16**)(&StatementWalker), L"oemerror", &Match)) && Match) { + TempSpot = StrStr(StatementWalker, L")"); + if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1)); + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + // + // must be a raw string + // + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0); + } + + if (Compare1 != NULL && Compare2 != NULL && BinOp != OperatorMax) { + OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare); + } + + SHELL_FREE_NON_NULL(Compare1); + SHELL_FREE_NON_NULL(Compare2); + } + + // + // done processing do result... + // + + if (!EFI_ERROR(Status)) { + if (NotPresent) { + OperationResult = (BOOLEAN)(!OperationResult); + } + switch(OperatorToUse) { + case EndTagOr: + *PassingState = (BOOLEAN)(*PassingState || OperationResult); + break; + case EndTagAnd: + *PassingState = (BOOLEAN)(*PassingState && OperationResult); + break; + case EndTagMax: + *PassingState = (BOOLEAN)(OperationResult); + break; + default: + ASSERT(FALSE); + } + } + return (Status); +} + +/** + Break up the next part of the if statement (until the next 'and', 'or', or 'then'). + + @param[in] ParameterNumber The current parameter number. + @param[out] EndParameter Upon successful return, will point to the + parameter to start the next iteration with. + @param[out] EndTag Upon successful return, will point to the + type that was found at the end of this statement. + + @retval TRUE A valid statement was found. + @retval FALSE A valid statement was not found. +**/ +BOOLEAN +BuildNextStatement ( + IN UINTN ParameterNumber, + OUT UINTN *EndParameter, + OUT END_TAG_TYPE *EndTag + ) +{ + *EndTag = EndTagMax; + + for( + ; ParameterNumber < gEfiShellParametersProtocol->Argc + ; ParameterNumber++ + ) { + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[ParameterNumber], + L"or") == 0) { + *EndParameter = ParameterNumber - 1; + *EndTag = EndTagOr; + break; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[ParameterNumber], + L"and") == 0) { + *EndParameter = ParameterNumber - 1; + *EndTag = EndTagAnd; + break; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[ParameterNumber], + L"then") == 0) { + *EndParameter = ParameterNumber - 1; + *EndTag = EndTagThen; + break; + } + } + if (*EndTag == EndTagMax) { + return (FALSE); + } + return (TRUE); +} + +/** + Move the script file pointer to a different place in the script file. + This one is special since it handles the if/else/endif syntax. + + @param[in] ScriptFile The script file from GetCurrnetScriptFile(). + + @retval TRUE The move target was found and the move was successful. + @retval FALSE Something went wrong. +**/ +BOOLEAN +MoveToTagSpecial ( + IN SCRIPT_FILE *ScriptFile + ) +{ + SCRIPT_COMMAND_LIST *CommandNode; + BOOLEAN Found; + UINTN TargetCount; + CHAR16 *CommandName; + CHAR16 *CommandWalker; + CHAR16 *TempLocation; + + TargetCount = 1; + Found = FALSE; + + if (ScriptFile == NULL) { + return FALSE; + } + + for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE + ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found + ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link) + ){ + + // + // get just the first part of the command line... + // + CommandName = NULL; + CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0); + if (CommandName == NULL) { + continue; + } + CommandWalker = CommandName; + + // + // Skip leading spaces and tabs. + // + while ((CommandWalker[0] == L' ') || (CommandWalker[0] == L'\t')) { + CommandWalker++; + } + TempLocation = StrStr(CommandWalker, L" "); + + if (TempLocation != NULL) { + *TempLocation = CHAR_NULL; + } + + // + // did we find a nested item ? + // + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandWalker, + L"If") == 0) { + TargetCount++; + } else if (TargetCount == 1 && gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandWalker, + (CHAR16*)L"else") == 0) { + // + // else can only decrement the last part... not an nested if + // hence the TargetCount compare added + // + TargetCount--; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandWalker, + (CHAR16*)L"endif") == 0) { + TargetCount--; + } + if (TargetCount == 0) { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link); + Found = TRUE; + } + + // + // Free the memory for this loop... + // + SHELL_FREE_NON_NULL(CommandName); + } + return (Found); +} + +/** + Deal with the result of the if operation. + + @param[in] Result The result of the if. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND The ending tag could not be found. +**/ +EFI_STATUS +PerformResultOperation ( + IN CONST BOOLEAN Result + ) +{ + if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) { + return (EFI_SUCCESS); + } + return (EFI_NOT_FOUND); +} + +/** + Function for 'if' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + BOOLEAN CaseInsensitive; + BOOLEAN ForceString; + UINTN CurrentParameter; + UINTN EndParameter; + BOOLEAN CurrentValue; + END_TAG_TYPE Ending; + END_TAG_TYPE PreviousEnding; + SCRIPT_FILE *CurrentScriptFile; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"if"); + return (SHELL_UNSUPPORTED); + } + + if (gEfiShellParametersProtocol->Argc < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"if"); + return (SHELL_INVALID_PARAMETER); + } + + // + // Make sure that an End exists. + // + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"EndIf", + L"If", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + return (SHELL_DEVICE_ERROR); + } + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + CurrentParameter = 1; + EndParameter = 0; + + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[1], + L"/i") == 0 || + gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[2], + L"/i") == 0 || + (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[3], + L"/i") == 0)) { + CaseInsensitive = TRUE; + CurrentParameter++; + } else { + CaseInsensitive = FALSE; + } + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[1], + L"/s") == 0 || + gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[2], + L"/s") == 0 || + (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[3], + L"/s") == 0)) { + ForceString = TRUE; + CurrentParameter++; + } else { + ForceString = FALSE; + } + + for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = EndTagMax + ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS + ; CurrentParameter++) { + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[CurrentParameter], + L"then") == 0) { + // + // we are at the then + // + if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle, L"if"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = PerformResultOperation(CurrentValue); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else { + PreviousEnding = Ending; + // + // build up the next statement for analysis + // + if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) { + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"Then", + L"If", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Analyze the statement + // + Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString); + if (EFI_ERROR(Status)) { +// ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Optomize to get out of the loop early... + // + if ((Ending == EndTagOr && CurrentValue) || (Ending == EndTagAnd && !CurrentValue)) { + Status = PerformResultOperation(CurrentValue); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]); + ShellStatus = SHELL_INVALID_PARAMETER; + } + break; + } + } + } + if (ShellStatus == SHELL_SUCCESS){ + CurrentParameter = EndParameter; + // + // Skip over the or or and parameter. + // + if (Ending == EndTagOr || Ending == EndTagAnd) { + CurrentParameter++; + } + } + } + } + return (ShellStatus); +} + +/** + Function for 'else' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunElse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SCRIPT_FILE *CurrentScriptFile; + + Status = CommandInit (); + ASSERT_EFI_ERROR (Status); + + if (gEfiShellParametersProtocol->Argc > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if"); + return (SHELL_INVALID_PARAMETER); + } + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else"); + return (SHELL_UNSUPPORTED); + } + + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + + if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"If", + L"Else", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + return (SHELL_DEVICE_ERROR); + } + if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"If", + L"Else", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + return (SHELL_DEVICE_ERROR); + } + + if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, FALSE, FALSE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"EndIf", + "Else", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + return (SHELL_DEVICE_ERROR); + } + + return (SHELL_SUCCESS); +} + +/** + Function for 'endif' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SCRIPT_FILE *CurrentScriptFile; + + Status = CommandInit (); + ASSERT_EFI_ERROR (Status); + + if (gEfiShellParametersProtocol->Argc > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if"); + return (SHELL_INVALID_PARAMETER); + } + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif"); + return (SHELL_UNSUPPORTED); + } + + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_SYNTAX_NO_MATCHING), + gShellLevel1HiiHandle, + L"If", + L"EndIf", + CurrentScriptFile!=NULL + && CurrentScriptFile->CurrentCommand!=NULL + ? CurrentScriptFile->CurrentCommand->Line:0); + return (SHELL_DEVICE_ERROR); + } + + return (SHELL_SUCCESS); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c new file mode 100644 index 0000000..6ad079f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c @@ -0,0 +1,64 @@ +/** @file + Main file for Shift shell level 1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +/** + Function for 'shift' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunShift ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SCRIPT_FILE *CurrentScriptFile; + UINTN LoopVar; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"shift"); + return (SHELL_UNSUPPORTED); + } + + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ASSERT(CurrentScriptFile != NULL); + + if (CurrentScriptFile->Argc < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"shift"); + return (SHELL_UNSUPPORTED); + } + + for (LoopVar = 0 ; LoopVar < CurrentScriptFile->Argc ; LoopVar++) { + if (LoopVar == 0) { + SHELL_FREE_NON_NULL(CurrentScriptFile->Argv[LoopVar]); + } + if (LoopVar < CurrentScriptFile->Argc -1) { + CurrentScriptFile->Argv[LoopVar] = CurrentScriptFile->Argv[LoopVar+1]; + } else { + CurrentScriptFile->Argv[LoopVar] = NULL; + } + } + CurrentScriptFile->Argc--; + return (SHELL_SUCCESS); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c new file mode 100644 index 0000000..8f12a2a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c @@ -0,0 +1,84 @@ +/** @file + Main file for stall shell level 1 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +/** + Function for 'stall' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunStall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT64 Intermediate; + + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, L"stall", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"stall"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"stall"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellConvertStringToUint64(ShellCommandLineGetRawValue(Package, 1), &Intermediate, FALSE, FALSE); + if (EFI_ERROR(Status) || ((UINT64)(UINTN)(Intermediate)) != Intermediate) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel1HiiHandle, L"stall", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = gBS->Stall((UINTN)Intermediate); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_STALL_FAILED), gShellLevel1HiiHandle, L"stall"); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } + ShellCommandLineFreeVarList (Package); + } + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c new file mode 100644 index 0000000..a097802 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c @@ -0,0 +1,308 @@ +/** @file + Main file for NULL named library for level 1 shell command functions. + + (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; +EFI_HANDLE gShellLevel1HiiHandle = NULL; + +/** + Return the help text filename. Only used if no HII information found. + + @retval the filename. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameLevel1 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Level 1 Commands library. + + Install the handlers for level 1 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellLevel1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // if shell level is less than 2 do nothing + // + if (PcdGet8(PcdShellSupportLevel) < 1) { + return (EFI_SUCCESS); + } + + gShellLevel1HiiHandle = HiiAddPackages (&gShellLevel1HiiGuid, gImageHandle, UefiShellLevel1CommandsLibStrings, NULL); + if (gShellLevel1HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"stall", ShellCommandRunStall , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_STALL) )); + ShellCommandRegisterCommandName(L"for", ShellCommandRunFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_FOR) )); + ShellCommandRegisterCommandName(L"goto", ShellCommandRunGoto , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_GOTO) )); + ShellCommandRegisterCommandName(L"if", ShellCommandRunIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_IF) )); + ShellCommandRegisterCommandName(L"shift", ShellCommandRunShift , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_SHIFT) )); + ShellCommandRegisterCommandName(L"exit", ShellCommandRunExit , ShellCommandGetManFileNameLevel1, 1, L"", TRUE , gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_EXIT) )); + ShellCommandRegisterCommandName(L"else", ShellCommandRunElse , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ELSE) )); + ShellCommandRegisterCommandName(L"endif", ShellCommandRunEndIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDIF) )); + ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDFOR))); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +ShellLevel1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellLevel1HiiHandle != NULL) { + HiiRemovePackages(gShellLevel1HiiHandle); + } + return (EFI_SUCCESS); +} + +/** + Test a node to see if meets the criterion. + + It functions so that count starts at 1 and it increases or decreases when it + hits the specified tags. when it hits zero the location has been found. + + DecrementerTag and IncrementerTag are used to get around for/endfor and + similar paired types where the entire middle should be ignored. + + If label is used it will be used instead of the count. + + @param[in] Function The function to use to enumerate through the + list. Normally GetNextNode or GetPreviousNode. + @param[in] DecrementerTag The tag to decrement the count at. + @param[in] IncrementerTag The tag to increment the count at. + @param[in] Label A label to look for. + @param[in, out] ScriptFile The pointer to the current script file structure. + @param[in] MovePast TRUE makes function return 1 past the found + location. + @param[in] FindOnly TRUE to not change the ScriptFile. + @param[in] CommandNode The pointer to the Node to test. + @param[in, out] TargetCount The pointer to the current count. +**/ +BOOLEAN +TestNodeForMove ( + IN CONST LIST_MANIP_FUNC Function, + IN CONST CHAR16 *DecrementerTag, + IN CONST CHAR16 *IncrementerTag, + IN CONST CHAR16 *Label OPTIONAL, + IN OUT SCRIPT_FILE *ScriptFile, + IN CONST BOOLEAN MovePast, + IN CONST BOOLEAN FindOnly, + IN CONST SCRIPT_COMMAND_LIST *CommandNode, + IN OUT UINTN *TargetCount + ) +{ + BOOLEAN Found; + CHAR16 *CommandName; + CHAR16 *CommandNameWalker; + CHAR16 *TempLocation; + + Found = FALSE; + + // + // get just the first part of the command line... + // + CommandName = NULL; + CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0); + if (CommandName == NULL) { + return (FALSE); + } + + CommandNameWalker = CommandName; + + // + // Skip leading spaces and tabs. + // + while ((CommandNameWalker[0] == L' ') || (CommandNameWalker[0] == L'\t')) { + CommandNameWalker++; + } + TempLocation = StrStr(CommandNameWalker, L" "); + + if (TempLocation != NULL) { + *TempLocation = CHAR_NULL; + } + + // + // did we find a nested item ? + // + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandNameWalker, + (CHAR16*)IncrementerTag) == 0) { + (*TargetCount)++; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandNameWalker, + (CHAR16*)DecrementerTag) == 0) { + if (*TargetCount > 0) { + (*TargetCount)--; + } + } + + // + // did we find the matching one... + // + if (Label == NULL) { + if (*TargetCount == 0) { + Found = TRUE; + if (!FindOnly) { + if (MovePast) { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link); + } else { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode; + } + } + } + } else { + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandNameWalker, + (CHAR16*)Label) == 0 + && (*TargetCount) == 0) { + Found = TRUE; + if (!FindOnly) { + // + // we found the target label without loops + // + if (MovePast) { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link); + } else { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode; + } + } + } + } + + // + // Free the memory for this loop... + // + FreePool(CommandName); + return (Found); +} + +/** + Move the script pointer from 1 tag (line) to another. + + It functions so that count starts at 1 and it increases or decreases when it + hits the specified tags. when it hits zero the location has been found. + + DecrementerTag and IncrementerTag are used to get around for/endfor and + similar paired types where the entire middle should be ignored. + + If label is used it will be used instead of the count. + + @param[in] Function The function to use to enumerate through the + list. Normally GetNextNode or GetPreviousNode. + @param[in] DecrementerTag The tag to decrement the count at. + @param[in] IncrementerTag The tag to increment the count at. + @param[in] Label A label to look for. + @param[in, out] ScriptFile The pointer to the current script file structure. + @param[in] MovePast TRUE makes function return 1 past the found + location. + @param[in] FindOnly TRUE to not change the ScriptFile. + @param[in] WrapAroundScript TRUE to wrap end-to-begining or vise versa in + searching. +**/ +BOOLEAN +MoveToTag ( + IN CONST LIST_MANIP_FUNC Function, + IN CONST CHAR16 *DecrementerTag, + IN CONST CHAR16 *IncrementerTag, + IN CONST CHAR16 *Label OPTIONAL, + IN OUT SCRIPT_FILE *ScriptFile, + IN CONST BOOLEAN MovePast, + IN CONST BOOLEAN FindOnly, + IN CONST BOOLEAN WrapAroundScript + ) +{ + SCRIPT_COMMAND_LIST *CommandNode; + BOOLEAN Found; + UINTN TargetCount; + + if (Label == NULL) { + TargetCount = 1; + } else { + TargetCount = 0; + } + + if (ScriptFile == NULL) { + return FALSE; + } + + for (CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE + ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link)&& !Found + ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link) + ){ + Found = TestNodeForMove( + Function, + DecrementerTag, + IncrementerTag, + Label, + ScriptFile, + MovePast, + FindOnly, + CommandNode, + &TargetCount); + } + + if (WrapAroundScript && !Found) { + for (CommandNode = (SCRIPT_COMMAND_LIST *)GetFirstNode(&ScriptFile->CommandList), Found = FALSE + ; CommandNode != ScriptFile->CurrentCommand && !Found + ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link) + ){ + Found = TestNodeForMove( + Function, + DecrementerTag, + IncrementerTag, + Label, + ScriptFile, + MovePast, + FindOnly, + CommandNode, + &TargetCount); + } + } + return (Found); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h new file mode 100644 index 0000000..4b9a77b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h @@ -0,0 +1,209 @@ +/** @file + Main file for NULL named library for level 1 shell command functions. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_LEVEL1_COMMANDS_LIB_H_ +#define _UEFI_SHELL_LEVEL1_COMMANDS_LIB_H_ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE gShellLevel1HiiHandle; + +/** + Function for 'stall' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunStall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'exit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'endif' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'for' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'endfor' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'if' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'goto' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunGoto ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'shift' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunShift ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Function for 'else' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunElse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/// +/// Function prototype for BOTH GetNextNode and GetPreviousNode... +/// This is used to control the MoveToTag function direction... +/// +typedef +LIST_ENTRY * +(EFIAPI *LIST_MANIP_FUNC)( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + +/** + Move the script pointer from 1 tag (line) to another. + + It functions so that count starts at 1 and it increases or decreases when it + hits the specified tags. when it hits zero the location has been found. + + DecrementerTag and IncrementerTag are used to get around for/endfor and + similar paired types where the entire middle should be ignored. + + If label is used it will be used instead of the count. + + @param[in] Function The function to use to enumerate through the + list. Normally GetNextNode or GetPreviousNode. + @param[in] DecrementerTag The tag to decrement the count at. + @param[in] IncrementerTag The tag to increment the count at. + @param[in] Label A label to look for. + @param[in, out] ScriptFile The pointer to the current script file structure. + @param[in] MovePast TRUE makes function return 1 past the found + location. + @param[in] FindOnly TRUE to not change the ScriptFile. + @param[in] WrapAroundScript TRUE to wrap end-to-begining or vise versa in + searching. +**/ +BOOLEAN +MoveToTag ( + IN CONST LIST_MANIP_FUNC Function, + IN CONST CHAR16 *DecrementerTag, + IN CONST CHAR16 *IncrementerTag, + IN CONST CHAR16 *Label OPTIONAL, + IN OUT SCRIPT_FILE *ScriptFile, + IN CONST BOOLEAN MovePast, + IN CONST BOOLEAN FindOnly, + IN CONST BOOLEAN WrapAroundScript + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf new file mode 100644 index 0000000..3aabf24 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf @@ -0,0 +1,58 @@ +## @file +# Provides shell level 1 functions +# +# Copyright (c) 2009-2015, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellLevel1CommandsLib + FILE_GUID = 50cb6037-1102-47af-b2dd-9944b6eb1abe + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellLevel1CommandsLibConstructor + DESTRUCTOR = ShellLevel1CommandsLibDestructor + +[Sources.common] + UefiShellLevel1CommandsLib.c + UefiShellLevel1CommandsLib.h + UefiShellLevel1CommandsLib.uni + Exit.c + Goto.c + If.c + For.c + Shift.c + Stall.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES + +[Guids] + gShellLevel1HiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni new file mode 100644 index 0000000..acc1cef --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni @@ -0,0 +1,504 @@ +// /** +// +// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellLevel2CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 level 1 commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_NO_SCRIPT #language en-US "The command '%H%s%N' is incorrect outside of a script\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_SCRIPT #language en-US "The argument '%B%s%N' is incorrect. Line: %d\r\n" +#string STR_GEN_INV_VAR #language en-US "The script's Indexvar '%B%s%N' is incorrect\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" + +#string STR_TEXT_AFTER_THEN #language en-US "%H%s%N: Then cannot be followed by anything\r\n" +#string STR_SYNTAX_AFTER_BAD #language en-US "%H%s%N: Syntax after '%H%s%N' is incorrect\r\n" +#string STR_SYNTAX_IN #language en-US "Syntax after analyzing %s\r\n" +#string STR_SYNTAX_NO_MATCHING #language en-US "No matching '%H%s%N' for '%H%s%N' statement found. Line: %d\r\n" +#string STR_INVALID_BINOP #language en-US "Binary operator not found first in '%H%s%N'\r\n" +#string STR_SYNTAX_STARTING #language en-US "Syntax after %s\r\n" + +#string STR_STALL_FAILED #language en-US "%H%s%N: BootService Stall() failed\r\n" + +#string STR_GET_HELP_EXIT #language en-US "" +".TH exit 0 "exits the script or shell"\r\n" +".SH NAME\r\n" +"Exits the UEFI Shell or the current script.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"EXIT [/b] [exit-code]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" /b - Indicates that only the current UEFI shell script should be\r\n" +" terminated. Ignored if not used within a script.\r\n" +" exit-code - If exiting a UEFI shell script, the value that will be placed\r\n" +" into the environment variable lasterror. If exiting an instance\r\n" +" of the UEFI shell, the value that will be returned to the\r\n" +" caller. If not specified, then 0 will be returned.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command exits the UEFI Shell or, if /b is specified, the current\r\n" +" script.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To exit shell successfully:\r\n" +" Shell> exit\r\n" +" \r\n" +" * To exit the current UEFI shell script:\r\n" +" Shell> exit /b \r\n" +" \r\n" +" * To exit a UEFI shell script with exit-code value returned to the caller:\r\n" +" Shell> exit 0\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" 0 Exited normally\r\n" +" exit-code The return value specified as an option.\r\n" + +#string STR_GET_HELP_FOR #language en-US "" +".TH for 0 "starts a for loop"\r\n" +".SH NAME\r\n" +"Starts a loop based on 'for' syntax.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"FOR %indexvar IN set\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +"ENDFOR\r\n" +" \r\n" +"FOR %indexvar RUN (start end [step])\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +"ENDFOR\r\n" +".SH OPTIONS\r\n" +" \r\n" +" %indexvar - Variable name used to index a set\r\n" +" set - Set to be searched\r\n" +" command [arguments] - Command to be executed with optional arguments\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The FOR command executes one or more commands for each item in a set of\r\n" +" items. The set may be text strings or filenames or a mixture of both,\r\n" +" separated by spaces (if not in a quotation).\r\n" +" 2. If the length of an element in the set is between 0 and 256, and if the\r\n" +" string contains wildcards, the string will be treated as a file name\r\n" +" containing wildcards, and be expanded before command is executed.\r\n" +" 3. If after expansion no such files are found, the literal string itself is\r\n" +" kept. %indexvar is any alphabet character from 'a' to 'z' or 'A' to 'Z',\r\n" +" and they are case sensitive. It should not be a digit (0-9) because\r\n" +" %digit will be interpreted as a positional argument on the command line\r\n" +" that launches the script. The namespace for index variables is separate\r\n" +" from that for environment variables, so if %indexvar has the same name as\r\n" +" an existing environment variable, the environment variable will remain\r\n" +" unchanged by the FOR loop.\r\n" +" 4. Each command is executed once for each item in the set, with any\r\n" +" occurrence of %indexvar in the command replacing with the current item.\r\n" +" In the second format of FOR ... ENDFOR statement, %indexvar will be\r\n" +" assigned a value from start to end with an interval of step. Start and\r\n" +" end can be any integer whose length is less than 7 digits excluding sign,\r\n" +" and it can also applied to step with one exception of zero. Step is\r\n" +" optional, if step is not specified it will be automatically determined by\r\n" +" following rule:\r\n" +" if start <= end then step = 1, otherwise step = -1.\r\n" +" start, end and step are divided by space.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * Sample FOR loop - listing all .txt files:\r\n" +" echo -off\r\n" +" for %a in *.txt\r\n" +" echo %a exists\r\n" +" endfor\r\n" +" \r\n" +" # \r\n" +" # If in current directory, there are 2 files named file1.txt and file2.txt\r\n" +" # then the output of the sample script will be as shown below.\r\n" +" # \r\n" +" Sample1> echo -off\r\n" +" file1.txt exists\r\n" +" file2.txt exists\r\n" +" \r\n" +" * Theoretically it is legal for 2 nested FOR commands to use the same\r\n" +" alphabet letter as their index variable, for instance, a: \r\n" +" #\r\n" +" # Sample FOR loop from 1 to 3 with step 1\r\n" +" #\r\n" +" echo -off\r\n" +" for %a run (1 3)\r\n" +" echo %a\r\n" +" endfor\r\n" +" \r\n" +" #\r\n" +" # Sample FOR loop from 3 down to 1 with step -1\r\n" +" #\r\n" +" echo -off\r\n" +" for %a run (3 1 -1)\r\n" +" echo %a\r\n" +" endfor\r\n" +" \r\n" +" #\r\n" +" # Sample FOR loop - 2 nested for using same index variable\r\n" +" #\r\n" +" echo -off\r\n" +" for %a in value1 value2\r\n" +" for %a in value3 value4\r\n" +" echo %a\r\n" +" endfor\r\n" +" endfor\r\n" +" \r\n" +" Note: When processing first FOR and before seeing the ENDFOR, the index\r\n" +" variable %a has the value "value1", so in second FOR, the %a has\r\n" +" been already defined and it will be replaced with the current value\r\n" +" of %a. The string after substitution becomes FOR value1 in value3\r\n" +" value4, which is not a legal FOR command. Thus only when the value\r\n" +" of %a is also a single alphabet letter, the script will be executed\r\n" +" without error. If 2 independent FOR commands use the same index\r\n" +" variable, when the second FOR is encountered, the first FOR has\r\n" +" already freed the variable so there will be no problem in this case.\r\n" + +#string STR_GET_HELP_ENDFOR #language en-US "" +".TH endfor 0 "ends a for loop"\r\n" +".SH NAME\r\n" +"Ends a 'for' loop.\r\n" +".SH SYNOPSIS\r\n" +"See 'for' for usage.\r\n" +".SH EXAMPLES\r\n" +"See 'for' for examples.\r\n" + +#string STR_GET_HELP_GOTO #language en-US "" +".TH goto 0 "moves to a label"\r\n" +".SH NAME\r\n" +"Moves around the point of execution in a script.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"GOTO label\r\n" +".SH OPTIONS\r\n" +" \r\n" +" label - Specifies a location in batch file\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The GOTO command directs script file execution to the line in the script\r\n" +" file after the given label. The command is not supported from the\r\n" +" interactive shell.\r\n" +" 2. A label is a line beginning with a colon (:). It can appear either after\r\n" +" the GOTO command, or before the GOTO command. The search for label is\r\n" +" done forward in the script file, from the current file position. If the\r\n" +" end of the file is reached, the search resumes at the top of the file and\r\n" +" continues until label is found or the starting point is reached. If label\r\n" +" is not found, the script process terminates and an error message is\r\n" +" displayed. If a label is encountered but there is no GOTO command\r\n" +" executed, the label lines are ignored.\r\n" +" 3. Using GOTO command to jump into another for loop is not allowed,\r\n" +" but jumping into an if statement is legal.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * This is a script:\r\n" +" goto Done\r\n" +" ...\r\n" +" :Done\r\n" +" cleanup.nsh\r\n" + +#string STR_GET_HELP_ENDIF #language en-US "" +".TH endif 0 "ends an if block"\r\n" +".SH NAME\r\n" +"Ends the block of a script controlled by an 'if' statement.\r\n" +".SH SYNOPSIS\r\n" +"See 'if' for usage.\r\n" +".SH EXAMPLES\r\n" +"See 'if' for examples.\r\n" + +#string STR_GET_HELP_IF #language en-US "" +".TH if 0 "controls the execution of a block of a script"\r\n" +".SH NAME\r\n" +"Executes commands in specified conditions.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"IF [NOT] EXIST filename THEN\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +"[ELSE\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +" ]\r\n" +"ENDIF\r\n" +" \r\n" +"IF [/i] [NOT] string1 == string2 THEN\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +"[ELSE\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +" ]\r\n" +"ENDIF\r\n" +"if [/i][/s] ConditionalExpression THEN\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +"[ELSE\r\n" +" command [arguments]\r\n" +" [command [arguments]]\r\n" +" ...\r\n" +" ]\r\n" +"ENDIF\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The IF command executes one or more commands before the ELSE or ENDIF\r\n" +" commands, if the specified condition is TRUE; otherwise commands between\r\n" +" ELSE (if present) and ENDIF are executed.\r\n" +" 2. In the first usage of IF, the EXIST condition is true when the file\r\n" +" specified by filename exists. The filename argument may include device\r\n" +" and path information. Also wildcard expansion is supported by this form.\r\n" +" If more than one file matches the wildcard pattern, the condition\r\n" +" evaluates to TRUE.\r\n" +" 3. In the second usage, the string1 == string2 condition is TRUE if the two\r\n" +" strings are identical. Here the comparison can be case sensitive or\r\n" +" insensitive, it depends on the optional switch /i. If /i is specified,\r\n" +" it will compare strings in the case insensitive manner; otherwise, it\r\n" +" compares strings in the case sensitive manner.\r\n" +" 4. In the third usage, general purpose comparison is supported using\r\n" +" expressions optionally separated by AND or OR. Since < and > are used for\r\n" +" redirection, the expressions use common two character (FORTRAN)\r\n" +" abbreviations for the operators (augmented with unsigned equivalents):\r\n" +" - Expressions : Conditional expressions are evaluated strictly from left\r\n" +" to right. Complex conditionals requiring precedence may\r\n" +" be implemented as nested IFs.\r\n" +" The expressions used in the third usage can have the\r\n" +" following syntax:\r\n" +" conditional-expression := expression |\r\n" +" expression and expression |\r\n" +" expression or expression\r\n" +" expression := expr | not expr\r\n" +" expr := item binop item | boolfunc(string)\r\n" +" item := mapfunc(string) | string\r\n" +" mapfunc := efierror | pierror | oemerror\r\n" +" boolfunc := isint | exists | available | profile\r\n" +" binop := gt | lt | eq | ne | ge | le | == | ugt | ult |\r\n" +" uge | ule\r\n" +" - Comparisons : By default, comparisons are done numerically if the\r\n" +" strings on both sides of the operator are numbers\r\n" +" (as defined below) and in case sensitive character sort\r\n" +" order otherwise. Spaces separate the operators from\r\n" +" operands.\r\n" +" 5. The /s option forces string comparisons and the /i option forces\r\n" +" case-insensitive string comparisons. If either of these is used, the\r\n" +" signed or unsigned versions of the operators have the same results.\r\n" +" The /s and /i apply to the entire line and must appear at the start of\r\n" +" the line (just after the if itself). The two may appear in either order.\r\n" +" 6. When performing comparisons, the Unicode Byte Ordering Character is\r\n" +" ignored at the beginning of any argument.\r\n" +" 7. Comparison Operator Definition:\r\n" +" gt : Greater than\r\n" +" ugt : Unsigned Greater than\r\n" +" lt : Less than\r\n" +" ult : Unsigned Less than\r\n" +" ge : Greater than or equal\r\n" +" uge : Unsigned greater than or equal\r\n" +" le : Less than or equal\r\n" +" ule : Unsigned less than or equal\r\n" +" ne : Not equal\r\n" +" eq : Equals (semantically equivalent to ==)\r\n" +" == : Equals (semantically equivalent to eq)\r\n" +" 8. Error Mapping Functions are used to convert integers into UEFI, PI or OEM\r\n" +" error codes.\r\n" +" Functions used to convert integers into UEFI, PI or OEM error codes:\r\n" +" UefiError : Sets top nibble of parameter to 1000 binary (0x8)\r\n" +" PiError : Sets top nibble of parameter to 1010 binary (0xA)\r\n" +" OemError : Sets top nibble of parameter to 1100 binary (0xC)\r\n" +" Each function maps the small positive parameter into its equivalent error\r\n" +" classification.\r\n" +" For example:\r\n" +" if %lasterror% == EfiError(8) then # Check for write protect.\r\n" +" ...\r\n" +" 9. Boolean Functions may only be used to modify operators in comparisons.\r\n" +" The following built-in Boolean functions are also available:\r\n" +" IsInt : Evaluates to true if the parameter string that follows\r\n" +" is a number (as defined below) and false otherwise.\r\n" +" Exists : Evaluates to true if the file specified by string exists\r\n" +" is in the current working directory or false if not.\r\n" +" Available : Evaluates to true if the file specified by string is in the\r\n" +" current working directory or current path.\r\n" +" Profile : Determines whether the parameter string matches one of the\r\n" +" profile names in the profiles environment variable.\r\n" +" 10. No spaces are allowed between function names and the open parenthesis,\r\n" +" between the open parenthesis and the string or between the string and\r\n" +" the closed parenthesis. Constant strings containing spaces must be\r\n" +" quoted.\r\n" +" 11. To avoid ambiguity and current or future incompatibility, users are\r\n" +" strongly encouraged to surround constant strings that contain\r\n" +" parenthesis with quotes in if statements.\r\n" +" 12. Allowable number formats are decimal numbers and C-style case\r\n" +" insensitive hexadecimal numbers. Numbers may be preceded by a\r\n" +" "-" indicating a negative number.\r\n" +" Examples:\r\n" +" 13\r\n" +" 46\r\n" +" -0x3FFF\r\n" +" 0x3fff\r\n" +" 0x1234\r\n" +" 13. Unsigned values must be less than 264. Signed integer values are bounded\r\n" +" by -/+263.\r\n" +" 14. Numbers are internally represented in two's compliment form. The\r\n" +" representation of the number in the string has no bearing on the way\r\n" +" that number is treated in an numeric expression - type is assigned by\r\n" +" the operator. So, for example, -1 lt 2 is true but -1 ult 2 is false.\r\n" +" 15. The IF command is only available in scripts.\r\n" +" 16. The ELSE command is optional in an IF/ELSE statement.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * Sample script for "if" command usages 1 and 2:\r\n" +" if exist fs0:\myscript.nsh then\r\n" +" myscript myarg1 myarg2\r\n" +" endif\r\n" +" if %myvar% == runboth then\r\n" +" myscript1\r\n" +" myscript2\r\n" +" else\r\n" +" echo ^%myvar^% != runboth\r\n" +" endif\r\n" +" Note: In this example, if the script file myscript.nsh exists in fs0:\,\r\n" +" this script will be launched with 2 arguments, myarg1 and myarg2.\r\n" +" After that, environment variable %myvar% is checked to see if its\r\n" +" value is runboth, if so, script myscript1 and myscript2 will be\r\n" +" executed one after the other, otherwise a message %myvar% != runboth\r\n" +" is printed.\r\n" +" \r\n" +" * Sample script for "if" command usage 3:\r\n" +" :Redo\r\n" +" echo Enter 0-6 or q to quit\r\n" +" # assumes "input y" stores a character of user input into variable y\r\n" +" InputCh MyVar\r\n" +" if x%MyVar% eq x then\r\n" +" echo Empty line. Try again\r\n" +" goto Redo\r\n" +" endif\r\n" +" if IsInt(%MyVar%) and %MyVar% le 6 then\r\n" +" myscript1 %MyVar%\r\n" +" goto Redo\r\n" +" endif\r\n" +" if /i %MyVar% ne q then\r\n" +" echo Invalid input\r\n" +" goto Redo\r\n" +" endif\r\n" +" Note: In this example, the script requests user input and uses the if\r\n" +" command for input validation. It checks for empty line first and\r\n" +" then range checks the input.\r\n" + +#string STR_GET_HELP_SHIFT #language en-US "" +".TH shift 0 "move parameters 1 down"\r\n" +".SH NAME\r\n" +"Shifts in-script parameter positions.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SHIFT\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The SHIFT command shifts the contents of a UEFI Shell script's positional\r\n" +" parameters so that %1 is discarded, %2 is copied to %1, %3 is copied to\r\n" +" %2, %4 is copied to %3 and so on. This allows UEFI Shell scripts to\r\n" +" process script parameters from left to right.\r\n" +" 2. This command does not change the UEFI shell environment variable\r\n" +" lasterror.\r\n" +" 3. The SHIFT command is available only in UEFI Shell scripts.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * Following script is a sample of 'shift' command:\r\n" +" fs0:\> type shift.nsh\r\n" +" #\r\n" +" # shift.nsh\r\n" +" # \r\n" +" echo %1 %2 %3\r\n" +" shift\r\n" +" echo %1 %2\r\n" +" \r\n" +" * To execute the script with echo on:\r\n" +" fs0:\> shift.nsh welcome UEFI world\r\n" +" shift.nsh> echo welcome UEFI world\r\n" +" welcome UEFI world\r\n" +" shift\r\n" +" echo UEFI world\r\n" +" UEFI world\r\n" +" \r\n" +" * To execute the script with echo off:\r\n" +" fs0:\> echo -off\r\n" +" fs0:\> shift.nsh welcome UEFI world\r\n" +" welcome UEFI world\r\n" +" UEFI world\r\n" + +#string STR_GET_HELP_ELSE #language en-US "" +".TH else 0 "part of an 'if' conditional statement"\r\n" +".SH NAME\r\n" +"Identifies the code executed when 'if' is FALSE.\r\n" +".SH SYNOPSIS\r\n" +"See 'else' for usage.\r\n" +".SH EXAMPLES\r\n" +"See 'if' for examples.\r\n" + +#string STR_GET_HELP_STALL #language en-US "" +".TH stall 0 "stall the operation"\r\n" +".SH NAME\r\n" +"Stalls the operation for a specified number of microseconds.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"STALL time\r\n" +".SH OPTIONS\r\n" +" \r\n" +" time - The number of microseconds for the processor to stall.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command would be used to establish a timed STALL of operations\r\n" +" during a script.\r\n" +" 2. Microseconds is in decimal units.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To stall the processor for 1000000 microseconds:\r\n" +" Shell> stall 1000000\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_NOT_FOUND The requested option was not found.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_DEVICE_ERROR There was a hardware error associated with this\r\n" +" request.\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c new file mode 100644 index 0000000..b0c3ddd --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c @@ -0,0 +1,277 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +STATIC CONST CHAR16 AllFiles[] = L"*"; + +STATIC CONST SHELL_PARAM_ITEM AttribParamList[] = { + {L"-a", TypeFlag}, + {L"+a", TypeFlag}, + {L"-s", TypeFlag}, + {L"+s", TypeFlag}, + {L"-h", TypeFlag}, + {L"+h", TypeFlag}, + {L"-r", TypeFlag}, + {L"+r", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'attrib' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAttrib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINT64 FileAttributesToAdd; + UINT64 FileAttributesToRemove; + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamNumberCount; + CONST CHAR16 *FileName; + EFI_SHELL_FILE_INFO *ListOfFiles; + EFI_SHELL_FILE_INFO *FileNode; + EFI_FILE_INFO *FileInfo; + + ListOfFiles = NULL; + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (AttribParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"attrib", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else { + FileAttributesToAdd = 0; + FileAttributesToRemove = 0; + + // + // apply or remove each flag + // + if (ShellCommandLineGetFlag(Package, L"+a")) { + FileAttributesToAdd |= EFI_FILE_ARCHIVE; + } + if (ShellCommandLineGetFlag(Package, L"-a")) { + FileAttributesToRemove |= EFI_FILE_ARCHIVE; + } + if (ShellCommandLineGetFlag(Package, L"+s")) { + FileAttributesToAdd |= EFI_FILE_SYSTEM; + } + if (ShellCommandLineGetFlag(Package, L"-s")) { + FileAttributesToRemove |= EFI_FILE_SYSTEM; + } + if (ShellCommandLineGetFlag(Package, L"+h")) { + FileAttributesToAdd |= EFI_FILE_HIDDEN; + } + if (ShellCommandLineGetFlag(Package, L"-h")) { + FileAttributesToRemove |= EFI_FILE_HIDDEN; + } + if (ShellCommandLineGetFlag(Package, L"+r")) { + FileAttributesToAdd |= EFI_FILE_READ_ONLY; + } + if (ShellCommandLineGetFlag(Package, L"-r")) { + FileAttributesToRemove |= EFI_FILE_READ_ONLY; + } + + if (FileAttributesToRemove == 0 && FileAttributesToAdd == 0) { + // + // Do display as we have no attributes to change + // + for ( ParamNumberCount = 1 + ; + ; ParamNumberCount++ + ){ + FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount); + // if we dont have anything left, move on... + if (FileName == NULL && ParamNumberCount == 1) { + FileName = (CHAR16*)AllFiles; + } else if (FileName == NULL) { + break; + } + ASSERT(ListOfFiles == NULL); + Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link) + ; !IsNull(&ListOfFiles->Link, &FileNode->Link) + ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link) + ){ + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_ATTRIB_OUTPUT_LINE), + gShellLevel2HiiHandle, + FileNode->Info->Attribute&EFI_FILE_DIRECTORY? L'D':L' ', + FileNode->Info->Attribute&EFI_FILE_ARCHIVE? L'A':L' ', + FileNode->Info->Attribute&EFI_FILE_SYSTEM? L'S':L' ', + FileNode->Info->Attribute&EFI_FILE_HIDDEN? L'H':L' ', + FileNode->Info->Attribute&EFI_FILE_READ_ONLY? L'R':L' ', + FileNode->FileName + ); + + if (ShellGetExecutionBreakFlag()) { + ShellStatus = SHELL_ABORTED; + break; + } + } + Status = ShellCloseFileMetaArg(&ListOfFiles); + ListOfFiles = NULL; + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } + } // for loop for handling wildcard filenames + } // for loop for printing out the info + } else if ((FileAttributesToRemove & FileAttributesToAdd) != 0) { + // + // fail as we have conflcting params. + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"attrib"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // enumerate through all the files/directories and apply the attributes + // + for ( ParamNumberCount = 1 + ; + ; ParamNumberCount++ + ){ + FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount); + // if we dont have anything left, move on... + if (FileName == NULL) { + // + // make sure we are not failing on the first one we do... if yes that's an error... + // + if (ParamNumberCount == 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"attrib"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + break; + } + + // + // OpenFileByName / GetFileInfo / Change attributes / SetFileInfo / CloseFile / free memory + // for each file or directory on the line. + // + + // + // Open the file(s) + // + ASSERT(ListOfFiles == NULL); + Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link) + ; !IsNull(&ListOfFiles->Link, &FileNode->Link) + ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(FileNode->FileName, L".") == 0 || StrCmp(FileNode->FileName, L"..") == 0) { + continue; + } + + FileInfo = gEfiShellProtocol->GetFileInfo(FileNode->Handle); + + // + // if we are removing Read-Only we need to do that alone + // + if ((FileAttributesToRemove & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) { + FileInfo->Attribute &= ~EFI_FILE_READ_ONLY; + // + // SetFileInfo + // + Status = ShellSetFileInfo(FileNode->Handle, FileInfo); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_ACCESS_DENIED; + } + } + + // + // change the attribute + // + FileInfo->Attribute &= ~FileAttributesToRemove; + FileInfo->Attribute |= FileAttributesToAdd; + + // + // SetFileInfo + // + Status = ShellSetFileInfo(FileNode->Handle, FileInfo); + if (EFI_ERROR(Status)) {; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_ACCESS_DENIED; + } + + SHELL_FREE_NON_NULL(FileInfo); + } + Status = ShellCloseFileMetaArg(&ListOfFiles); + ListOfFiles = NULL; + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount)); + ShellStatus = SHELL_NOT_FOUND; + } + } // for loop for handling wildcard filenames + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c new file mode 100644 index 0000000..c79fd59 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c @@ -0,0 +1,351 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + Copyright (c) 2018, Dell Technologies. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Function will replace drive identifier with CWD. + + If FullPath begining with ':' is invalid path, then ASSERT. + If FullPath not include dirve identifier , then do nothing. + If FullPath likes "fs0:\xx" or "fs0:/xx" , then do nothing. + If FullPath likes "fs0:xxx" or "fs0:", the drive replaced by CWD. + + @param[in, out] FullPath The pointer to the string containing the path. + @param[in] Cwd Current directory. + + @retval EFI_SUCCESS Success. + @retval EFI_OUT_OF_SOURCES A memory allocation failed. +**/ +EFI_STATUS +ReplaceDriveWithCwd ( + IN OUT CHAR16 **FullPath, + IN CONST CHAR16 *Cwd + ) +{ + CHAR16 *Splitter; + CHAR16 *TempBuffer; + UINTN TotalSize; + + Splitter = NULL; + TempBuffer = NULL; + TotalSize = 0; + + if (FullPath == NULL || *FullPath == NULL) { + return EFI_SUCCESS; + } + + Splitter = StrStr (*FullPath, L":"); + ASSERT(Splitter != *FullPath); + + if (Splitter != NULL && *(Splitter + 1) != L'\\' && *(Splitter + 1) != L'/') { + TotalSize = StrSize (Cwd) + StrSize (Splitter + 1); + TempBuffer = AllocateZeroPool (TotalSize); + if (TempBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StrCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd); + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), L"\\"); + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Splitter + 1); + + FreePool(*FullPath); + *FullPath = TempBuffer; + } + + return EFI_SUCCESS; +} + +/** + function to determine if FullPath is under current filesystem. + + @param[in] FullPath The target location to determine. + @param[in] Cwd Current directory. + + @retval TRUE The FullPath is in the current filesystem. + @retval FALSE The FullPaht isn't in the current filesystem. +**/ +BOOLEAN +IsCurrentFileSystem ( + IN CONST CHAR16 *FullPath, + IN CONST CHAR16 *Cwd + ) +{ + CHAR16 *Splitter1; + CHAR16 *Splitter2; + + Splitter1 = NULL; + Splitter2 = NULL; + + ASSERT(FullPath != NULL); + + Splitter1 = StrStr (FullPath, L":"); + if (Splitter1 == NULL) { + return TRUE; + } + + Splitter2 = StrStr (Cwd, L":"); + + if (((UINTN) Splitter1 - (UINTN) FullPath) != ((UINTN) Splitter2 - (UINTN) Cwd)) { + return FALSE; + } else { + if (StrniCmp (FullPath, Cwd, ((UINTN) Splitter1 - (UINTN) FullPath) / sizeof (CHAR16)) == 0) { + return TRUE; + } else { + return FALSE; + } + } +} + +/** + Extract drive string and path string from FullPath. + + The caller must be free Drive and Path. + + @param[in] FullPath A path to be extracted. + @param[out] Drive Buffer to save drive identifier. + @param[out] Path Buffer to save path. + + @retval EFI_SUCCESS Success. + @retval EFI_OUT_OF_RESOUCES A memory allocation failed. +**/ +EFI_STATUS +ExtractDriveAndPath ( + IN CONST CHAR16 *FullPath, + OUT CHAR16 **Drive, + OUT CHAR16 **Path + ) +{ + CHAR16 *Splitter; + + ASSERT (FullPath != NULL); + + Splitter = StrStr (FullPath, L":"); + + if (Splitter == NULL) { + *Drive = NULL; + *Path = AllocateCopyPool (StrSize (FullPath), FullPath); + if (*Path == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + if (*(Splitter + 1) == CHAR_NULL) { + *Drive = AllocateCopyPool (StrSize (FullPath), FullPath); + *Path = NULL; + if (*Drive == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + *Drive = AllocateCopyPool ((Splitter - FullPath + 2) * sizeof(CHAR16), FullPath); + if (*Drive == NULL) { + return EFI_OUT_OF_RESOURCES; + } + (*Drive)[Splitter - FullPath + 1] = CHAR_NULL; + + *Path = AllocateCopyPool (StrSize (Splitter + 1), Splitter + 1); + if (*Path == NULL) { + FreePool (*Drive); + return EFI_OUT_OF_RESOURCES; + } + } + } + + return EFI_SUCCESS; +} + +/** + Function for 'cd' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCd ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CONST CHAR16 *Cwd; + CHAR16 *Path; + CHAR16 *Drive; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Param1; + CHAR16 *Param1Copy; + CHAR16 *Walker; + CHAR16 *Splitter; + CHAR16 *TempBuffer; + UINTN TotalSize; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + Cwd = NULL; + Path = NULL; + Drive = NULL; + Splitter = NULL; + TempBuffer = NULL; + TotalSize = 0; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } + + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // remember that param 0 is the command name + // If there are 0 value parameters, then print the current directory + // else If there are 2 value parameters, then print the error message + // else If there is 1 value paramerer , then change the directory + // + Cwd = ShellGetCurrentDir (NULL); + if (Cwd == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd"); + ShellStatus = SHELL_NOT_FOUND; + } else { + Param1 = ShellCommandLineGetRawValue (Package, 1); + if (Param1 == NULL) { + // + // display the current directory + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_CD_PRINT), gShellLevel2HiiHandle, Cwd); + } else { + Param1Copy = CatSPrint (NULL, L"%s", Param1, NULL); + for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL; Walker++) { + if (*Walker == L'\"') { + CopyMem (Walker, Walker + 1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + if (Param1Copy != NULL && IsCurrentFileSystem (Param1Copy, Cwd)) { + Status = ReplaceDriveWithCwd (&Param1Copy,Cwd); + } else { + // + // Can't use cd command to change filesystem. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd"); + Status = EFI_NOT_FOUND; + } + + if (!EFI_ERROR(Status) && Param1Copy != NULL) { + Splitter = StrStr (Cwd, L":"); + if (Param1Copy[0] == L'\\') { + // + // Absolute Path on current drive letter. + // + TotalSize = ((Splitter - Cwd + 1) * sizeof(CHAR16)) + StrSize(Param1Copy); + TempBuffer = AllocateZeroPool (TotalSize); + if (TempBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + StrnCpyS (TempBuffer, TotalSize / sizeof(CHAR16), Cwd, (Splitter - Cwd + 1)); + StrCatS (TempBuffer, TotalSize / sizeof(CHAR16), Param1Copy); + + FreePool (Param1Copy); + Param1Copy = TempBuffer; + TempBuffer = NULL; + } + } else { + if (StrStr (Param1Copy,L":") == NULL) { + TotalSize = StrSize (Cwd) + StrSize (Param1Copy); + TempBuffer = AllocateZeroPool (TotalSize); + if (TempBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + StrCpyS (TempBuffer, TotalSize / sizeof (CHAR16), Cwd); + StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), L"\\"); + StrCatS (TempBuffer, TotalSize / sizeof (CHAR16), Param1Copy); + + FreePool (Param1Copy); + Param1Copy = TempBuffer; + TempBuffer = NULL; + } + } + } + } + + if (!EFI_ERROR(Status)) { + Param1Copy = PathCleanUpDirectories (Param1Copy); + Status = ExtractDriveAndPath (Param1Copy, &Drive, &Path); + } + + if (!EFI_ERROR (Status) && Drive != NULL && Path != NULL) { + if (EFI_ERROR(ShellIsDirectory (Param1Copy))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy); + ShellStatus = SHELL_NOT_FOUND; + } else { + Status = gEfiShellProtocol->SetCurDir (Drive, Path + 1); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy); + ShellStatus = SHELL_NOT_FOUND; + } + } + } + + if (Drive != NULL) { + FreePool (Drive); + } + + if (Path != NULL) { + FreePool (Path); + } + + FreePool (Param1Copy); + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c new file mode 100644 index 0000000..64d4d42 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c @@ -0,0 +1,779 @@ +/** @file + Main file for cp shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include +#include + +/** + Function to take a list of files to copy and a destination location and do + the verification and copying of those files to that location. This function + will report any errors to the user and halt. + + @param[in] FileList A LIST_ENTRY* based list of files to move. + @param[in] DestDir The destination location. + @param[in] SilentMode TRUE to eliminate screen output. + @param[in] RecursiveMode TRUE to copy directories. + @param[in] Resp The response to the overwrite query (if always). + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_SECURITY_VIOLATION a security violation ocurred + @retval SHELL_WRITE_PROTECTED the destination was write protected + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +SHELL_STATUS +ValidateAndCopyFiles( + IN CONST EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir, + IN BOOLEAN SilentMode, + IN BOOLEAN RecursiveMode, + IN VOID **Resp + ); + +/** + Function to Copy one file to another location + + If the destination exists the user will be prompted and the result put into *resp + + @param[in] Source pointer to source file name + @param[in] Dest pointer to destination file name + @param[out] Resp pointer to response from question. Pass back on looped calling + @param[in] SilentMode whether to run in quiet mode or not + @param[in] CmdName Source command name requesting single file copy + + @retval SHELL_SUCCESS The source file was copied to the destination +**/ +SHELL_STATUS +CopySingleFile( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Dest, + OUT VOID **Resp, + IN BOOLEAN SilentMode, + IN CONST CHAR16 *CmdName + ) +{ + VOID *Response; + UINTN ReadSize; + SHELL_FILE_HANDLE SourceHandle; + SHELL_FILE_HANDLE DestHandle; + EFI_STATUS Status; + VOID *Buffer; + CHAR16 *TempName; + UINTN Size; + EFI_SHELL_FILE_INFO *List; + SHELL_STATUS ShellStatus; + UINT64 SourceFileSize; + UINT64 DestFileSize; + EFI_FILE_PROTOCOL *DestVolumeFP; + EFI_FILE_SYSTEM_INFO *DestVolumeInfo; + UINTN DestVolumeInfoSize; + + ASSERT(Resp != NULL); + + SourceHandle = NULL; + DestHandle = NULL; + Response = *Resp; + List = NULL; + DestVolumeInfo = NULL; + ShellStatus = SHELL_SUCCESS; + + ReadSize = PcdGet32(PcdShellFileOperationSize); + // Why bother copying a file to itself + if (StrCmp(Source, Dest) == 0) { + return (SHELL_SUCCESS); + } + + // + // if the destination file existed check response and possibly prompt user + // + if (ShellFileExists(Dest) == EFI_SUCCESS) { + if (Response == NULL && !SilentMode) { + Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response); + } + // + // possibly return based on response + // + if (!SilentMode) { + switch (*(SHELL_PROMPT_RESPONSE*)Response) { + case ShellPromptResponseNo: + // + // return success here so we dont stop the process + // + return (SHELL_SUCCESS); + case ShellPromptResponseCancel: + *Resp = Response; + // + // indicate to stop everything + // + return (SHELL_ABORTED); + case ShellPromptResponseAll: + *Resp = Response; + case ShellPromptResponseYes: + break; + default: + return SHELL_ABORTED; + } + } + } + + if (ShellIsDirectory(Source) == EFI_SUCCESS) { + Status = ShellCreateDirectory(Dest, &DestHandle); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, CmdName, Dest); + return (SHELL_ACCESS_DENIED); + } + + // + // Now copy all the files under the directory... + // + TempName = NULL; + Size = 0; + StrnCatGrow(&TempName, &Size, Source, 0); + StrnCatGrow(&TempName, &Size, L"\\*", 0); + if (TempName != NULL) { + ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List); + *TempName = CHAR_NULL; + StrnCatGrow(&TempName, &Size, Dest, 0); + StrnCatGrow(&TempName, &Size, L"\\", 0); + ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp); + ShellCloseFileMetaArg(&List); + SHELL_FREE_NON_NULL(TempName); + Size = 0; + } + } else { + Status = ShellDeleteFileByName(Dest); + + // + // open file with create enabled + // + Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Dest); + return (SHELL_ACCESS_DENIED); + } + + // + // open source file + // + Status = ShellOpenFileByName (Source, &SourceHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SRC_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Source); + return (SHELL_ACCESS_DENIED); + } + + // + //get file size of source file and freespace available on destination volume + // + ShellGetFileSize(SourceHandle, &SourceFileSize); + ShellGetFileSize(DestHandle, &DestFileSize); + + // + //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space + // + if(DestFileSize < SourceFileSize){ + SourceFileSize -= DestFileSize; + } else { + SourceFileSize = 0; + } + + // + //get the system volume info to check the free space + // + DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle); + DestVolumeInfo = NULL; + DestVolumeInfoSize = 0; + Status = DestVolumeFP->GetInfo( + DestVolumeFP, + &gEfiFileSystemInfoGuid, + &DestVolumeInfoSize, + DestVolumeInfo + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize); + Status = DestVolumeFP->GetInfo( + DestVolumeFP, + &gEfiFileSystemInfoGuid, + &DestVolumeInfoSize, + DestVolumeInfo + ); + } + + // + //check if enough space available on destination drive to complete copy + // + if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) { + // + //not enough space on destination directory to copy file + // + SHELL_FREE_NON_NULL(DestVolumeInfo); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle, CmdName); + return(SHELL_VOLUME_FULL); + } else { + // + // copy data between files + // + Buffer = AllocateZeroPool(ReadSize); + if (Buffer == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, CmdName); + return SHELL_OUT_OF_RESOURCES; + } + while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) { + Status = ShellReadFile(SourceHandle, &ReadSize, Buffer); + if (!EFI_ERROR(Status)) { + Status = ShellWriteFile(DestHandle, &ReadSize, Buffer); + if (EFI_ERROR(Status)) { + ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, CmdName, Dest); + break; + } + } else { + ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, CmdName, Source); + break; + } + } + } + SHELL_FREE_NON_NULL(DestVolumeInfo); + } + + // + // close files + // + if (DestHandle != NULL) { + ShellCloseFile(&DestHandle); + DestHandle = NULL; + } + if (SourceHandle != NULL) { + ShellCloseFile(&SourceHandle); + SourceHandle = NULL; + } + + // + // return + // + return ShellStatus; +} + +/** + function to take a list of files to copy and a destination location and do + the verification and copying of those files to that location. This function + will report any errors to the user and halt. + + The key is to have this function called ONLY once. this allows for the parameter + verification to happen correctly. + + @param[in] FileList A LIST_ENTRY* based list of files to move. + @param[in] DestDir The destination location. + @param[in] SilentMode TRUE to eliminate screen output. + @param[in] RecursiveMode TRUE to copy directories. + @param[in] Resp The response to the overwrite query (if always). + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_SECURITY_VIOLATION a security violation ocurred + @retval SHELL_WRITE_PROTECTED the destination was write protected + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +SHELL_STATUS +ValidateAndCopyFiles( + IN CONST EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir, + IN BOOLEAN SilentMode, + IN BOOLEAN RecursiveMode, + IN VOID **Resp + ) +{ + CHAR16 *HiiOutput; + CHAR16 *HiiResultOk; + CONST EFI_SHELL_FILE_INFO *Node; + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + CHAR16 *DestPath; + VOID *Response; + UINTN PathSize; + CONST CHAR16 *Cwd; + UINTN NewSize; + CHAR16 *CleanFilePathStr; + + if (Resp == NULL) { + Response = NULL; + } else { + Response = *Resp; + } + + DestPath = NULL; + ShellStatus = SHELL_SUCCESS; + PathSize = 0; + Cwd = ShellGetCurrentDir(NULL); + CleanFilePathStr = NULL; + + ASSERT(FileList != NULL); + ASSERT(DestDir != NULL); + + + Status = ShellLevel2StripQuotes (DestDir, &CleanFilePathStr); + if (EFI_ERROR (Status)) { + if (Status == EFI_OUT_OF_RESOURCES) { + return SHELL_OUT_OF_RESOURCES; + } else { + return SHELL_INVALID_PARAMETER; + } + } + + ASSERT (CleanFilePathStr != NULL); + + // + // If we are trying to copy multiple files... make sure we got a directory for the target... + // + if (EFI_ERROR(ShellIsDirectory(CleanFilePathStr)) && FileList->Link.ForwardLink != FileList->Link.BackLink) { + // + // Error for destination not a directory + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + NewSize = StrSize(CleanFilePathStr); + NewSize += StrSize(Node->FullName); + NewSize += (Cwd == NULL)? 0 : (StrSize(Cwd) + sizeof(CHAR16)); + if (NewSize > PathSize) { + PathSize = NewSize; + } + + // + // Make sure got -r if required + // + if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle, L"cp"); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + + // + // make sure got dest as dir if needed + // + if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(CleanFilePathStr))) { + // + // Error for destination not a directory + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + } + + HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL); + HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); + DestPath = AllocateZeroPool(PathSize); + + if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) { + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + FreePool (CleanFilePathStr); + return (SHELL_OUT_OF_RESOURCES); + } + + // + // Go through the list of files to copy... + // + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag()) { + break; + } + ASSERT(Node->FileName != NULL); + ASSERT(Node->FullName != NULL); + + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item + && EFI_ERROR(ShellIsDirectory(CleanFilePathStr)) // not an existing directory + ) { + if (StrStr(CleanFilePathStr, L":") == NULL) { + // + // simple copy of a single file + // + if (Cwd != NULL) { + StrCpyS(DestPath, PathSize / sizeof(CHAR16), Cwd); + StrCatS(DestPath, PathSize / sizeof(CHAR16), L"\\"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool (CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') { + StrCatS(DestPath, PathSize / sizeof(CHAR16), L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + } else { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + } + } else { + // + // we have multiple files or a directory in the DestDir + // + + // + // Check for leading slash + // + if (CleanFilePathStr[0] == L'\\') { + // + // Copy to the root of CWD + // + if (Cwd != NULL) { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), Cwd); + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool(CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + while (PathRemoveLastItem(DestPath)); + StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr+1); + StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName); + } else if (StrStr(CleanFilePathStr, L":") == NULL) { + if (Cwd != NULL) { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), Cwd); + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr); + FreePool(CleanFilePathStr); + return (SHELL_INVALID_PARAMETER); + } + if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') { + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') { + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName); + + } else { + StrCpyS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr); + if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') { + StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\"); + } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') { + ((CHAR16*)CleanFilePathStr)[StrLen(CleanFilePathStr)-1] = CHAR_NULL; + } + StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName); + } + } + + // + // Make sure the path exists + // + if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle, L"cp", DestPath); + ShellStatus = SHELL_DEVICE_ERROR; + break; + } + + if ( !EFI_ERROR(ShellIsDirectory(Node->FullName)) + && !EFI_ERROR(ShellIsDirectory(DestPath)) + && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == 0 + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + if ((StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName)) == 0) + && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\') + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + PathCleanUpDirectories(DestPath); + + if (!SilentMode) { + ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath); + } + + // + // copy single file... + // + ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode, L"cp"); + if (ShellStatus != SHELL_SUCCESS) { + break; + } + } + if (ShellStatus == SHELL_SUCCESS && Resp == NULL) { + ShellPrintEx(-1, -1, L"%s", HiiResultOk); + } + + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + SHELL_FREE_NON_NULL(CleanFilePathStr); + if (Resp == NULL) { + SHELL_FREE_NON_NULL(Response); + } + + return (ShellStatus); + +} + +/** + Validate and if successful copy all the files from the list into + destination directory. + + @param[in] FileList The list of files to copy. + @param[in] DestDir The directory to copy files to. + @param[in] SilentMode TRUE to eliminate screen output. + @param[in] RecursiveMode TRUE to copy directories. + + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +ProcessValidateAndCopyFiles( + IN EFI_SHELL_FILE_INFO *FileList, + IN CONST CHAR16 *DestDir, + IN BOOLEAN SilentMode, + IN BOOLEAN RecursiveMode + ) +{ + SHELL_STATUS ShellStatus; + EFI_SHELL_FILE_INFO *List; + EFI_FILE_INFO *FileInfo; + CHAR16 *FullName; + + List = NULL; + FullName = NULL; + FileInfo = NULL; + + ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List); + if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, L"cp", DestDir); + ShellStatus = SHELL_INVALID_PARAMETER; + ShellCloseFileMetaArg(&List); + } else if (List != NULL) { + ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL); + ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL); + FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle); + ASSERT(FileInfo != NULL); + StrnCatGrow(&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0); + ShellCloseFileMetaArg(&List); + if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) { + ShellStatus = ValidateAndCopyFiles(FileList, FullName, SilentMode, RecursiveMode, NULL); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_ACCESS_DENIED; + } + } else { + ShellCloseFileMetaArg(&List); + ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL); + } + + SHELL_FREE_NON_NULL(FileInfo); + SHELL_FREE_NON_NULL(FullName); + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-r", TypeFlag}, + {L"-q", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'cp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + UINTN LoopCounter; + EFI_SHELL_FILE_INFO *FileList; + BOOLEAN SilentMode; + BOOLEAN RecursiveMode; + CONST CHAR16 *Cwd; + CHAR16 *FullCwd; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cp", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + // + // Initialize SilentMode and RecursiveMode + // + if (gEfiShellProtocol->BatchIsActive()) { + SilentMode = TRUE; + } else { + SilentMode = ShellCommandLineGetFlag(Package, L"-q"); + } + RecursiveMode = ShellCommandLineGetFlag(Package, L"-r"); + + switch (ParamCount = ShellCommandLineGetCount(Package)) { + case 0: + case 1: + // + // we have insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + case 2: + // + // must have valid CWD for single parameter... + // + Cwd = ShellGetCurrentDir(NULL); + if (Cwd == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16)); + if (FullCwd == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cp"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS (FullCwd, StrSize (Cwd) / sizeof (CHAR16) + 1, Cwd); + ShellStatus = ProcessValidateAndCopyFiles (FileList, FullCwd, SilentMode, RecursiveMode); + FreePool (FullCwd); + } + } + } + + break; + default: + // + // Make a big list of all the files... + // + for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) { + if (ShellGetExecutionBreakFlag()) { + break; + } + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue(Package, LoopCounter)); + ShellStatus = SHELL_NOT_FOUND; + } + } + if (ShellStatus != SHELL_SUCCESS) { + Status = ShellCloseFileMetaArg(&FileList); + } else { + // + // now copy them all... + // + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + ShellStatus = ProcessValidateAndCopyFiles(FileList, PathCleanUpDirectories((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode); + Status = ShellCloseFileMetaArg(&FileList); + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue(Package, ParamCount), ShellStatus|MAX_BIT); + ShellStatus = SHELL_ACCESS_DENIED; + } + } + } + break; + } // switch on parameter count + + if (FileList != NULL) { + ShellCloseFileMetaArg(&FileList); + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c new file mode 100644 index 0000000..a3efb3b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c @@ -0,0 +1,279 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +// This function was from from the BdsLib implementation in +// IntelFrameworkModulePkg\Library\GenericBdsLib\BdsConnect.c +// function name: BdsLibConnectAllEfi +/** + This function will connect all current system handles recursively. The + connection will finish until every handle's child handle created if it have. + + @retval EFI_SUCCESS All handles and it's child handle have been + connected + @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +ConnectAllEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + function to load a .EFI driver into memory and possible connect the driver. + + if FileName is NULL then ASSERT. + + @param[in] FileName FileName of the driver to load + @param[in] Connect Whether to connect or not + + @retval EFI_SUCCESS the driver was loaded and if Connect was + true then connect was attempted. Connection may + have failed. + @retval EFI_OUT_OF_RESOURCES there was insufficient memory +**/ +EFI_STATUS +LoadDriver( + IN CONST CHAR16 *FileName, + IN CONST BOOLEAN Connect + ) +{ + EFI_HANDLE LoadedDriverHandle; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage; + + LoadedDriverImage = NULL; + FilePath = NULL; + LoadedDriverHandle = NULL; + Status = EFI_SUCCESS; + + ASSERT (FileName != NULL); + + // + // Fix local copies of the protocol pointers + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // Convert to DEVICE_PATH + // + FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName); + + if (FilePath == NULL) { + ASSERT(FALSE); + return (EFI_INVALID_PARAMETER); + } + + // + // Use LoadImage to get it into memory + // + Status = gBS->LoadImage( + FALSE, + gImageHandle, + FilePath, + NULL, + 0, + &LoadedDriverHandle); + + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status); + } else { + // + // Make sure it is a driver image + // + Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage); + + ASSERT (LoadedDriverImage != NULL); + + if ( EFI_ERROR(Status) + || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode + && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName); + + // + // Exit and unload the non-driver image + // + gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL); + Status = EFI_INVALID_PARAMETER; + } + } + + if (!EFI_ERROR(Status)) { + // + // Start the image + // + Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status); + } + } + + if (!EFI_ERROR(Status) && Connect) { + // + // Connect it... + // + Status = ConnectAllEfi(); + } + + // + // clean up memory... + // + if (FilePath != NULL) { + FreePool(FilePath); + } + + return (Status); +} + +STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = { + {L"-nc", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'load' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLoad ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *ListHead; + EFI_SHELL_FILE_INFO *Node; + + ListHead = NULL; + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"load", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we didnt get a single file to load parameter + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"load"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + for ( ParamCount = 1 + ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL + ; ParamCount++ + ){ + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead); + if (!EFI_ERROR(Status)) { + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + // + // once we have an error preserve that value, but finish the loop. + // + if (EFI_ERROR(Status)) { + LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE)); + } else { + Status = LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE)); + } + } // for loop for multi-open + if (EFI_ERROR(Status)) { + ShellCloseFileMetaArg(&ListHead); + } else { + Status = ShellCloseFileMetaArg(&ListHead);; + } + } else { + // + // no files found. + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"load", (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)); + ShellStatus = SHELL_NOT_FOUND; + } + } // for loop for params + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellStatus = SHELL_DEVICE_ERROR; + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c new file mode 100644 index 0000000..f269db7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c @@ -0,0 +1,874 @@ +/** @file + Main file for ls shell level 2 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include + +UINTN mDayOfMonth[] = {31, 28, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30}; + +/** + print out the standard format output volume entry. + + @param[in] TheList a list of files from the volume. +**/ +EFI_STATUS +PrintSfoVolumeInfoTableEntry( + IN CONST EFI_SHELL_FILE_INFO *TheList + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *Node; + CHAR16 *DirectoryName; + EFI_FILE_SYSTEM_INFO *SysInfo; + UINTN SysInfoSize; + SHELL_FILE_HANDLE ShellFileHandle; + EFI_FILE_PROTOCOL *EfiFpHandle; + + // + // Get the first valid handle (directories) + // + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link) + ; !IsNull(&TheList->Link, &Node->Link) && Node->Handle == NULL + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&TheList->Link, &Node->Link) + ); + + if (Node->Handle == NULL) { + DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link))->FullName); + + // + // We need to open something up to get system information + // + Status = gEfiShellProtocol->OpenFileByName( + DirectoryName, + &ShellFileHandle, + EFI_FILE_MODE_READ + ); + + ASSERT_EFI_ERROR(Status); + FreePool(DirectoryName); + + // + // Get the Volume Info from ShellFileHandle + // + SysInfo = NULL; + SysInfoSize = 0; + EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo + ); + } + + ASSERT_EFI_ERROR(Status); + + gEfiShellProtocol->CloseFile(ShellFileHandle); + } else { + // + // Get the Volume Info from Node->Handle + // + SysInfo = NULL; + SysInfoSize = 0; + EfiFpHandle = ConvertShellHandleToEfiFileProtocol(Node->Handle); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo + ); + } + + ASSERT_EFI_ERROR(Status); + } + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_GEN_SFO_HEADER), + gShellLevel2HiiHandle, + L"ls" + ); + // + // print VolumeInfo table + // + ASSERT(SysInfo != NULL); + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_SFO_VOLINFO), + gShellLevel2HiiHandle, + SysInfo->VolumeLabel, + SysInfo->VolumeSize, + SysInfo->ReadOnly?L"TRUE":L"FALSE", + SysInfo->FreeSpace, + SysInfo->BlockSize + ); + + SHELL_FREE_NON_NULL(SysInfo); + + return (Status); +} + +/** + print out the info on a single file. + + @param[in] Sfo TRUE if in SFO, false otherwise. + @param[in] TheNode the EFI_SHELL_FILE_INFO node to print out information on. + @param[in] Files incremented if a file is printed. + @param[in] Size incremented by file size. + @param[in] Dirs incremented if a directory is printed. + +**/ +VOID +PrintFileInformation( + IN CONST BOOLEAN Sfo, + IN CONST EFI_SHELL_FILE_INFO *TheNode, + IN UINT64 *Files, + IN UINT64 *Size, + IN UINT64 *Dirs + ) +{ + ASSERT(Files != NULL); + ASSERT(Size != NULL); + ASSERT(Dirs != NULL); + ASSERT(TheNode != NULL); + + if (Sfo) { + // + // Print the FileInfo Table + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_SFO_FILEINFO), + gShellLevel2HiiHandle, + TheNode->FullName, + TheNode->Info->FileSize, + TheNode->Info->PhysicalSize, + (TheNode->Info->Attribute & EFI_FILE_ARCHIVE) != 0?L"a":L"", + (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"", + (TheNode->Info->Attribute & EFI_FILE_HIDDEN) != 0?L"h":L"", + (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"", + (TheNode->Info->Attribute & EFI_FILE_SYSTEM) != 0?L"s":L"", + TheNode->Info->CreateTime.Hour, + TheNode->Info->CreateTime.Minute, + TheNode->Info->CreateTime.Second, + TheNode->Info->CreateTime.Day, + TheNode->Info->CreateTime.Month, + TheNode->Info->CreateTime.Year, + TheNode->Info->LastAccessTime.Hour, + TheNode->Info->LastAccessTime.Minute, + TheNode->Info->LastAccessTime.Second, + TheNode->Info->LastAccessTime.Day, + TheNode->Info->LastAccessTime.Month, + TheNode->Info->LastAccessTime.Year, + TheNode->Info->ModificationTime.Hour, + TheNode->Info->ModificationTime.Minute, + TheNode->Info->ModificationTime.Second, + TheNode->Info->ModificationTime.Day, + TheNode->Info->ModificationTime.Month, + TheNode->Info->ModificationTime.Year + ); + } else { + // + // print this one out... + // first print the universal start, next print the type specific name format, last print the CRLF + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_START_ALL), + gShellLevel2HiiHandle, + &TheNode->Info->ModificationTime, + (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"

        ":L"", + (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ', + TheNode->Info->FileSize + ); + if (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) { + (*Dirs)++; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_DIR), + gShellLevel2HiiHandle, + TheNode->FileName + ); + } else { + (*Files)++; + (*Size) += TheNode->Info->FileSize; + if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0) + || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0) + ){ + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_EXE), + gShellLevel2HiiHandle, + TheNode->FileName + ); + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_LINE_END_FILE), + gShellLevel2HiiHandle, + TheNode->FileName + ); + } + } + } +} + +/** + print out the header when not using standard format output. + + @param[in] Path String with starting path. +**/ +VOID +PrintNonSfoHeader( + IN CONST CHAR16 *Path + ) +{ + CHAR16 *DirectoryName; + + // + // get directory name from path... + // + DirectoryName = GetFullyQualifiedPath(Path); + + if (DirectoryName != NULL) { + // + // print header + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_LS_HEADER_LINE1), + gShellLevel2HiiHandle, + DirectoryName + ); + + SHELL_FREE_NON_NULL(DirectoryName); + } +} + +/** + print out the footer when not using standard format output. + + @param[in] Files The number of files. + @param[in] Size The size of files in bytes. + @param[in] Dirs The number of directories. +**/ +VOID +PrintNonSfoFooter( + IN UINT64 Files, + IN UINT64 Size, + IN UINT64 Dirs + ) +{ + // + // print footer + // + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_LS_FOOTER_LINE), + gShellLevel2HiiHandle, + Files, + Size, + Dirs + ); +} + +/** + Change the file time to local time based on the timezone. + + @param[in] Time The file time. + @param[in] LocalTimeZone Local time zone. +**/ +VOID +FileTimeToLocalTime ( + IN EFI_TIME *Time, + IN INT16 LocalTimeZone + ) +{ + INTN MinuteDiff; + INTN TempMinute; + INTN HourNumberOfTempMinute; + INTN TempHour; + INTN DayNumberOfTempHour; + INTN TempDay; + INTN MonthNumberOfTempDay; + INTN TempMonth; + INTN YearNumberOfTempMonth; + INTN MonthRecord; + + ASSERT ((Time->TimeZone >= -1440) && (Time->TimeZone <=1440)); + ASSERT ((LocalTimeZone >= -1440) && (LocalTimeZone <=1440)); + ASSERT ((Time->Month >= 1) && (Time->Month <= 12)); + + if(Time->TimeZone == LocalTimeZone) { + // + //if the file timezone is equal to the local timezone, there is no need to adjust the file time. + // + return; + } + + if((Time->Year % 4 == 0 && Time->Year / 100 != 0)||(Time->Year % 400 == 0)) { + // + // Day in February of leap year is 29. + // + mDayOfMonth[1] = 29; + } + + MinuteDiff = Time->TimeZone - LocalTimeZone; + TempMinute = Time->Minute + MinuteDiff; + + // + // Calculate Time->Minute + // TempHour will be used to calculate Time->Hour + // + HourNumberOfTempMinute = TempMinute / 60; + if(TempMinute < 0) { + HourNumberOfTempMinute --; + } + TempHour = Time->Hour + HourNumberOfTempMinute; + Time->Minute = (UINT8)(TempMinute - 60 * HourNumberOfTempMinute); + + // + // Calculate Time->Hour + // TempDay will be used to calculate Time->Day + // + DayNumberOfTempHour = TempHour / 24 ; + if(TempHour < 0){ + DayNumberOfTempHour--; + } + TempDay = Time->Day + DayNumberOfTempHour; + Time->Hour = (UINT8)(TempHour - 24 * DayNumberOfTempHour); + + // + // Calculate Time->Day + // TempMonth will be used to calculate Time->Month + // + MonthNumberOfTempDay = (TempDay - 1) / (INTN)mDayOfMonth[Time->Month - 1]; + MonthRecord = (INTN)(Time->Month) ; + if(TempDay - 1 < 0){ + MonthNumberOfTempDay -- ; + MonthRecord -- ; + } + TempMonth = Time->Month + MonthNumberOfTempDay; + Time->Day = (UINT8)(TempDay - (INTN)mDayOfMonth[(MonthRecord - 1 + 12) % 12] * MonthNumberOfTempDay); + + // + // Calculate Time->Month, Time->Year + // + YearNumberOfTempMonth = (TempMonth - 1) / 12; + if(TempMonth - 1 < 0){ + YearNumberOfTempMonth --; + } + Time->Month = (UINT8)(TempMonth - 12 * (YearNumberOfTempMonth)); + Time->Year = (UINT16)(Time->Year + YearNumberOfTempMonth); +} + +/** + print out the list of files and directories from the LS command + + @param[in] Rec TRUE to automatically recurse into each found directory + FALSE to only list the specified directory. + @param[in] Attribs List of required Attribute for display. + If 0 then all non-system and non-hidden files will be printed. + @param[in] Sfo TRUE to use Standard Format Output, FALSE otherwise + @param[in] RootPath String with starting path to search in. + @param[in] SearchString String with search string. + @param[in] Found Set to TRUE, if anyone were found. + @param[in] Count The count of bits enabled in Attribs. + @param[in] TimeZone The current time zone offset. + + @retval SHELL_SUCCESS the printing was sucessful. +**/ +SHELL_STATUS +PrintLsOutput( + IN CONST BOOLEAN Rec, + IN CONST UINT64 Attribs, + IN CONST BOOLEAN Sfo, + IN CONST CHAR16 *RootPath, + IN CONST CHAR16 *SearchString, + IN BOOLEAN *Found, + IN CONST UINTN Count, + IN CONST INT16 TimeZone + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *ListHead; + EFI_SHELL_FILE_INFO *Node; + SHELL_STATUS ShellStatus; + UINT64 FileCount; + UINT64 DirCount; + UINT64 FileSize; + UINTN LongestPath; + CHAR16 *CorrectedPath; + BOOLEAN FoundOne; + BOOLEAN HeaderPrinted; + EFI_TIME LocalTime; + + HeaderPrinted = FALSE; + FileCount = 0; + DirCount = 0; + FileSize = 0; + ListHead = NULL; + ShellStatus = SHELL_SUCCESS; + LongestPath = 0; + CorrectedPath = NULL; + + if (Found != NULL) { + FoundOne = *Found; + } else { + FoundOne = FALSE; + } + + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0); + if (CorrectedPath == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\' + &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') { + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0); + } + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, SearchString, 0); + if (CorrectedPath == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + PathCleanUpDirectories(CorrectedPath); + + Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead); + if (!EFI_ERROR(Status)) { + if (ListHead == NULL || IsListEmpty(&ListHead->Link)) { + SHELL_FREE_NON_NULL(CorrectedPath); + return (SHELL_SUCCESS); + } + + if (Sfo && Found == NULL) { + PrintSfoVolumeInfoTableEntry(ListHead); + } + + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link), LongestPath = 0 + ; !IsNull(&ListHead->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + ASSERT(Node != NULL); + + // + // Change the file time to local time. + // + Status = gRT->GetTime(&LocalTime, NULL); + if (!EFI_ERROR (Status)) { + if ((Node->Info->CreateTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) && + (Node->Info->CreateTime.Month >= 1 && Node->Info->CreateTime.Month <= 12)) { + // + // FileTimeToLocalTime () requires Month is in a valid range, other buffer out-of-band access happens. + // + FileTimeToLocalTime (&Node->Info->CreateTime, LocalTime.TimeZone); + } + if ((Node->Info->LastAccessTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) && + (Node->Info->LastAccessTime.Month >= 1 && Node->Info->LastAccessTime.Month <= 12)) { + FileTimeToLocalTime (&Node->Info->LastAccessTime, LocalTime.TimeZone); + } + if ((Node->Info->ModificationTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) && + (Node->Info->ModificationTime.Month >= 1 && Node->Info->ModificationTime.Month <= 12)) { + FileTimeToLocalTime (&Node->Info->ModificationTime, LocalTime.TimeZone); + } + } + + if (LongestPath < StrSize(Node->FullName)) { + LongestPath = StrSize(Node->FullName); + } + ASSERT(Node->Info != NULL); + ASSERT((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute); + if (Attribs == 0) { + // + // NOT system & NOT hidden + // + if ( (Node->Info->Attribute & EFI_FILE_SYSTEM) + || (Node->Info->Attribute & EFI_FILE_HIDDEN) + ){ + continue; + } + } else if ((Attribs != EFI_FILE_VALID_ATTR) || + (Count == 5)) { + // + // Only matches the bits which "Attribs" contains, not + // all files/directories with any of the bits. + // Count == 5 is used to tell the difference between a user + // specifying all bits (EX: -arhsda) and just specifying + // -a (means display all files with any attribute). + // + if ( (Node->Info->Attribute & Attribs) != Attribs) { + continue; + } + } + + if (!Sfo && !HeaderPrinted) { + PathRemoveLastItem (CorrectedPath); + PrintNonSfoHeader(CorrectedPath); + } + PrintFileInformation(Sfo, Node, &FileCount, &FileSize, &DirCount); + FoundOne = TRUE; + HeaderPrinted = TRUE; + } + + if (!Sfo && ShellStatus != SHELL_ABORTED) { + PrintNonSfoFooter(FileCount, FileSize, DirCount); + } + } + + if (Rec && ShellStatus != SHELL_ABORTED) { + // + // Re-Open all the files under the starting path for directories that didnt necessarily match our file filter + // + ShellCloseFileMetaArg(&ListHead); + CorrectedPath[0] = CHAR_NULL; + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0); + if (CorrectedPath == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\' + &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') { + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0); + } + CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"*", 0); + Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead); + + if (!EFI_ERROR(Status)) { + for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link) + ; !IsNull(&ListHead->Link, &Node->Link) && ShellStatus == SHELL_SUCCESS + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag ()) { + ShellStatus = SHELL_ABORTED; + break; + } + + // + // recurse on any directory except the traversing ones... + // + if (((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) + && StrCmp(Node->FileName, L".") != 0 + && StrCmp(Node->FileName, L"..") != 0 + ){ + ShellStatus = PrintLsOutput( + Rec, + Attribs, + Sfo, + Node->FullName, + SearchString, + &FoundOne, + Count, + TimeZone); + + // + // Since it's running recursively, we have to break immediately when returned SHELL_ABORTED + // + if (ShellStatus == SHELL_ABORTED) { + break; + } + } + } + } + } + + SHELL_FREE_NON_NULL(CorrectedPath); + ShellCloseFileMetaArg(&ListHead); + + if (Found == NULL && !FoundOne) { + return (SHELL_NOT_FOUND); + } + + if (Found != NULL) { + *Found = FoundOne; + } + + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM LsParamList[] = { + {L"-r", TypeFlag}, + {L"-a", TypeStart}, + {L"-sfo", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'ls' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLs ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Attribs; + SHELL_STATUS ShellStatus; + UINT64 RequiredAttributes; + CONST CHAR16 *PathName; + CONST CHAR16 *CurDir; + UINTN Count; + CHAR16 *FullPath; + UINTN Size; + EFI_TIME TheTime; + CHAR16 *SearchString; + + Size = 0; + FullPath = NULL; + ProblemParam = NULL; + Attribs = NULL; + ShellStatus = SHELL_SUCCESS; + RequiredAttributes = 0; + PathName = NULL; + SearchString = NULL; + CurDir = NULL; + Count = 0; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // Fix local copies of the protocol pointers + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"ls", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"ls"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // check for -a + // + if (ShellCommandLineGetFlag(Package, L"-a")) { + for ( Attribs = ShellCommandLineGetValue(Package, L"-a") + ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS + ; Attribs++ + ){ + switch (*Attribs) { + case L'a': + case L'A': + RequiredAttributes |= EFI_FILE_ARCHIVE; + Count++; + continue; + case L's': + case L'S': + RequiredAttributes |= EFI_FILE_SYSTEM; + Count++; + continue; + case L'h': + case L'H': + RequiredAttributes |= EFI_FILE_HIDDEN; + Count++; + continue; + case L'r': + case L'R': + RequiredAttributes |= EFI_FILE_READ_ONLY; + Count++; + continue; + case L'd': + case L'D': + RequiredAttributes |= EFI_FILE_DIRECTORY; + Count++; + continue; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, L"ls", ShellCommandLineGetValue(Package, L"-a")); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } // switch + } // for loop + // + // if nothing is specified all are specified + // + if (RequiredAttributes == 0) { + RequiredAttributes = EFI_FILE_VALID_ATTR; + } + } // if -a present + if (ShellStatus == SHELL_SUCCESS) { + PathName = ShellCommandLineGetRawValue(Package, 1); + if (PathName == NULL) { + // + // Nothing specified... must start from current directory + // + CurDir = gEfiShellProtocol->GetCurDir(NULL); + if (CurDir == NULL) { + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls"); + } + // + // Copy to the 2 strings for starting path and file search string + // + ASSERT(SearchString == NULL); + ASSERT(FullPath == NULL); + StrnCatGrow(&SearchString, NULL, L"*", 0); + StrnCatGrow(&FullPath, NULL, CurDir, 0); + Size = FullPath != NULL? StrSize(FullPath) : 0; + StrnCatGrow(&FullPath, &Size, L"\\", 0); + } else { + if (StrStr(PathName, L":") == NULL && gEfiShellProtocol->GetCurDir(NULL) == NULL) { + // + // If we got something and it doesnt have a fully qualified path, then we needed to have a CWD. + // + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls"); + } else { + // + // We got a valid fully qualified path or we have a CWD + // + ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL)); + if (StrStr(PathName, L":") == NULL) { + StrnCatGrow(&FullPath, &Size, gEfiShellProtocol->GetCurDir(NULL), 0); + if (FullPath == NULL) { + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + Size = FullPath != NULL? StrSize(FullPath) : 0; + StrnCatGrow(&FullPath, &Size, L"\\", 0); + } + StrnCatGrow(&FullPath, &Size, PathName, 0); + if (FullPath == NULL) { + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + + if (ShellIsDirectory(PathName) == EFI_SUCCESS) { + // + // is listing ends with a directory, then we list all files in that directory + // + StrnCatGrow(&SearchString, NULL, L"*", 0); + } else { + // + // must split off the search part that applies to files from the end of the directory part + // + StrnCatGrow(&SearchString, NULL, FullPath, 0); + if (SearchString == NULL) { + FreePool (FullPath); + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + PathRemoveLastItem (FullPath); + CopyMem (SearchString, SearchString + StrLen (FullPath), StrSize (SearchString + StrLen (FullPath))); + } + } + } + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"ls", L"gRT->GetTime", Status); + TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; + } + + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PrintLsOutput( + ShellCommandLineGetFlag(Package, L"-r"), + RequiredAttributes, + ShellCommandLineGetFlag(Package, L"-sfo"), + FullPath, + SearchString, + NULL, + Count, + TheTime.TimeZone + ); + if (ShellStatus == SHELL_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LS_FILE_NOT_FOUND), gShellLevel2HiiHandle, L"ls", FullPath); + } else if (ShellStatus == SHELL_INVALID_PARAMETER) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath); + } else if (ShellStatus == SHELL_ABORTED) { + // + // Ignore aborting. + // + } else if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath); + } + } + } + } + } + + // + // Free memory allocated + // + SHELL_FREE_NON_NULL(SearchString); + SHELL_FREE_NON_NULL(FullPath); + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c new file mode 100644 index 0000000..e829154 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c @@ -0,0 +1,1302 @@ +/** @file + Main file for map shell level 2 command. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include +#include +#include +#include +#include + +/** + Determine if a string has only numbers and letters. + + This is useful for such things as Map names which can only be letters and numbers. + + @param[in] String pointer to the string to analyze, + @param[in] Len Number of characters to analyze. + + @retval TRUE String has only numbers and letters + @retval FALSE String has at least one other character. +**/ +BOOLEAN +IsNumberLetterOnly( + IN CONST CHAR16 *String, + IN CONST UINTN Len + ) +{ + UINTN Count; + for (Count = 0 ; Count < Len && String != NULL && *String != CHAR_NULL ; String++,Count++) { + if (! ((*String >= L'a' && *String <= L'z') || + (*String >= L'A' && *String <= L'Z') || + (*String >= L'0' && *String <= L'9')) + ){ + return (FALSE); + } + } + return (TRUE); +} + +/** + Do a search in the Target delimited list. + + @param[in] List The list to seatch in. + @param[in] MetaTarget The item to search for. MetaMatching supported. + @param[out] FullName Optional pointer to an allocated buffer containing + the match. + @param[in] Meta TRUE to use MetaMatching. + @param[in] SkipTrailingNumbers TRUE to allow for numbers after the MetaTarget. + @param[in] Target The single character that delimits list + items (";" normally). +**/ +BOOLEAN +SearchList( + IN CONST CHAR16 *List, + IN CONST CHAR16 *MetaTarget, + OUT CHAR16 **FullName OPTIONAL, + IN CONST BOOLEAN Meta, + IN CONST BOOLEAN SkipTrailingNumbers, + IN CONST CHAR16 *Target + + ) +{ + CHAR16 *TempList; + CONST CHAR16 *ListWalker; + BOOLEAN Result; + CHAR16 *TempSpot; + + for (ListWalker = List , TempList = NULL + ; ListWalker != NULL && *ListWalker != CHAR_NULL + ; + ) { + TempList = StrnCatGrow(&TempList, NULL, ListWalker, 0); + ASSERT(TempList != NULL); + TempSpot = StrStr(TempList, Target); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + + while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter(TempList[StrLen(TempList)-1]) || TempList[StrLen(TempList)-1] == L':')) { + TempList[StrLen(TempList)-1] = CHAR_NULL; + } + + ListWalker = StrStr(ListWalker, Target); + while(ListWalker != NULL && *ListWalker == *Target) { + ListWalker++; + } + if (Meta) { + Result = gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)TempList, (CHAR16*)MetaTarget); + } else { + Result = (BOOLEAN)(StrCmp(TempList, MetaTarget)==0); + } + if (Result) { + if (FullName != NULL) { + *FullName = TempList; + } else { + FreePool(TempList); + } + return (TRUE); + } + FreePool(TempList); + TempList = NULL; + } + + return (FALSE); +} + +/** + Determine what type of device is represented and return it's string. The + string is in allocated memory and must be callee freed. The HII is is listed below. + The actual string cannot be determined. + + @param[in] DevicePath The device to analyze. + + @retval STR_MAP_MEDIA_UNKNOWN The media type is unknown. + @retval STR_MAP_MEDIA_HARDDISK The media is a hard drive. + @retval STR_MAP_MEDIA_CDROM The media is a CD ROM. + @retval STR_MAP_MEDIA_FLOPPY The media is a floppy drive. +**/ +CHAR16* +GetDeviceMediaType ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + // + // Parse the device path: + // Devicepath sub type mediatype + // MEDIA_HANRDDRIVE_DP -> Hard Disk + // MEDIA_CDROM_DP -> CD Rom + // Acpi.HID = 0X0604 -> Floppy + // + if (NULL == DevicePath) { + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL); + } + + for (;!IsDevicePathEndType (DevicePath) ;DevicePath = NextDevicePathNode (DevicePath)) { + if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) { + switch (DevicePathSubType (DevicePath)) { + case MEDIA_HARDDRIVE_DP: + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_HARDDISK), NULL); + case MEDIA_CDROM_DP: + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_CDROM), NULL); + } + } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) { + Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; + if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) { + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_FLOPPY), NULL); + } + } + } + + return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL); +} + +/** + Function to detemine if a handle has removable storage. + + @param[in] DevicePath DevicePath to test. + + @retval TRUE The handle has removable storage. + @retval FALSE The handle does not have removable storage. +**/ +BOOLEAN +IsRemoveableDevice ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + if (NULL == DevicePath) { + return FALSE; + } + + while (!IsDevicePathEndType (DevicePath)) { + if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) { + switch (DevicePathSubType (DevicePath)) { + case MSG_USB_DP: + case MSG_SCSI_DP: + return TRUE; + default: + return FALSE; + } + } + DevicePath = NextDevicePathNode (DevicePath); + } + return FALSE; +} + +/** + Function to detemine if a something on the map list matches. + + @param[in] MapList The pointer to the list to test. + @param[in] Specific The pointer to a specific name to test for. + @param[in] TypeString The pointer to the list of types. + @param[in] Normal Always show normal mappings. + @param[in] Consist Always show consistent mappings. + + @retval TRUE The map should be displayed. + @retval FALSE The map should not be displayed. +**/ +BOOLEAN +MappingListHasType( + IN CONST CHAR16 *MapList, + IN CONST CHAR16 *Specific, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN Normal, + IN CONST BOOLEAN Consist + ) +{ + CHAR16 *NewSpecific; + RETURN_STATUS Status; + UINTN Length; + + // + // specific has priority + // + if (Specific != NULL) { + Length = StrLen (Specific); + // + // Allocate enough buffer for Specific and potential ":" + // + NewSpecific = AllocatePool ((Length + 2) * sizeof(CHAR16)); + if (NewSpecific == NULL){ + return FALSE; + } + StrCpyS (NewSpecific, Length + 2, Specific); + if (Specific[Length - 1] != L':') { + Status = StrnCatS(NewSpecific, Length + 2, L":", StrLen(L":")); + if (EFI_ERROR (Status)) { + FreePool(NewSpecific); + return FALSE; + } + } + + if (SearchList(MapList, NewSpecific, NULL, TRUE, FALSE, L";")) { + FreePool(NewSpecific); + return (TRUE); + } + FreePool(NewSpecific); + } + if ( Consist + && Specific == NULL + && (SearchList(MapList, L"HD*", NULL, TRUE, TRUE, L";") + ||SearchList(MapList, L"CD*", NULL, TRUE, TRUE, L";") + ||SearchList(MapList, L"F*", NULL, TRUE, TRUE, L";") + ||SearchList(MapList, L"FP*", NULL, TRUE, TRUE, L";"))){ + return (TRUE); + } + + if ( Normal + && Specific == NULL + && (SearchList(MapList, L"FS", NULL, FALSE, TRUE, L";") + ||SearchList(MapList, L"BLK", NULL, FALSE, TRUE, L";"))){ + return (TRUE); + } + + if (TypeString != NULL && SearchList(MapList, TypeString, NULL, TRUE, TRUE, L";")) { + return (TRUE); + } + return (FALSE); +} + + +/** + Display a single map line for device Handle if conditions are met. + + @param[in] Verbose TRUE to display (extra) verbose information. + @param[in] Consist TRUE to display consistent mappings. + @param[in] Normal TRUE to display normal (not consist) mappings. + @param[in] TypeString pointer to string of filter types. + @param[in] SFO TRUE to display output in Standard Output Format. + @param[in] Specific pointer to string for specific map to display. + @param[in] Handle The handle to display from. + + @retval EFI_SUCCESS The mapping was displayed. +**/ +EFI_STATUS +PerformSingleMappingDisplay( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL, + IN CONST EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPathCopy; + CONST CHAR16 *MapList; + CHAR16 *CurrentName; + CHAR16 *MediaType; + CHAR16 *DevPathString; + CHAR16 *TempSpot; + CHAR16 *Alias; + UINTN TempLen; + BOOLEAN Removable; + CONST CHAR16 *TempSpot2; + + Alias = NULL; + TempSpot2 = NULL; + CurrentName = NULL; + DevPath = DevicePathFromHandle(Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy); + if (MapList == NULL) { + return EFI_NOT_FOUND; + } + + if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){ + return EFI_NOT_FOUND; + } + + if (Normal || !Consist) { + // + // need the Normal here since people can use both on command line. otherwise unused. + // + + // + // Allocate a name + // + CurrentName = NULL; + CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0); + if (CurrentName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + // + // Chop off the other names that become "Alias(s)" + // leaving just the normal name + // + TempSpot = StrStr(CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } else { + CurrentName = NULL; + + // + // Skip the first name. This is the standard name. + // + TempSpot = StrStr(MapList, L";"); + if (TempSpot != NULL) { + TempSpot++; + } + SearchList(TempSpot, L"HD*", &CurrentName, TRUE, FALSE, L";"); + if (CurrentName == NULL) { + SearchList(TempSpot, L"CD*", &CurrentName, TRUE, FALSE, L";"); + } + if (CurrentName == NULL) { + SearchList(TempSpot, L"FP*", &CurrentName, TRUE, FALSE, L";"); + } + if (CurrentName == NULL) { + SearchList(TempSpot, L"F*", &CurrentName, TRUE, FALSE, L";"); + } + if (CurrentName == NULL) { + // + // We didnt find anything, so just the first one in the list... + // + CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0); + if (CurrentName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + TempSpot = StrStr(CurrentName, L";"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } else { + Alias = StrnCatGrow(&Alias, 0, MapList, 0); + if (Alias == NULL) { + return EFI_OUT_OF_RESOURCES; + } + TempSpot = StrStr(Alias, CurrentName); + if (TempSpot != NULL) { + TempSpot2 = StrStr(TempSpot, L";"); + if (TempSpot2 != NULL) { + TempSpot2++; // Move past ";" from CurrentName + CopyMem(TempSpot, TempSpot2, StrSize(TempSpot2)); + } else { + *TempSpot = CHAR_NULL; + } + } + if (Alias[StrLen(Alias)-1] == L';') { + Alias[StrLen(Alias)-1] = CHAR_NULL; + } + } + } + DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE); + TempLen = StrLen(CurrentName); + if (!SFO) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY), + gShellLevel2HiiHandle, + CurrentName, + Alias!=NULL?Alias:(TempLen < StrLen(MapList)?MapList + TempLen+1:L""), + DevPathString + ); + if (Verbose) { + // + // also print handle, media type, removable (y/n), and current directory + // + MediaType = GetDeviceMediaType(DevPath); + if ((TypeString != NULL &&MediaType != NULL && StrStr(TypeString, MediaType) != NULL) || TypeString == NULL) { + Removable = IsRemoveableDevice(DevPath); + TempSpot2 = ShellGetCurrentDir(CurrentName); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_ENTRY_VERBOSE), + gShellLevel2HiiHandle, + ConvertHandleToHandleIndex(Handle), + MediaType, + Removable?L"Yes":L"No", + TempSpot2 + ); + } + SHELL_FREE_NON_NULL(MediaType); + } + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_MAP_SFO_MAPPINGS), + gShellLevel2HiiHandle, + CurrentName, + DevPathString, + Consist?L"":(TempLen < StrLen(MapList)?MapList + TempLen+1:L"") + ); + } + SHELL_FREE_NON_NULL(DevPathString); + SHELL_FREE_NON_NULL(CurrentName); + SHELL_FREE_NON_NULL(Alias); + return EFI_SUCCESS; +} + +/** + Delete Specific from the list of maps for device Handle. + + @param[in] Specific The name to delete. + @param[in] Handle The device to look on. + + @retval EFI_SUCCESS The delete was successful. + @retval EFI_NOT_FOUND Name was not a map on Handle. +**/ +EFI_STATUS +PerformSingleMappingDelete( + IN CONST CHAR16 *Specific, + IN CONST EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *DevPathCopy; + CONST CHAR16 *MapList; + CHAR16 *CurrentName; + + DevPath = DevicePathFromHandle(Handle); + DevPathCopy = DevPath; + MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy); + CurrentName = NULL; + + if (MapList == NULL) { + return (EFI_NOT_FOUND); + } + // + // if there is a specific and its not on the list... + // + if (!SearchList(MapList, Specific, &CurrentName, TRUE, FALSE, L";")) { + return (EFI_NOT_FOUND); + } + return (gEfiShellProtocol->SetMap(NULL, CurrentName)); +} + +CONST CHAR16 Cd[] = L"cd*"; +CONST CHAR16 Hd[] = L"hd*"; +CONST CHAR16 Fp[] = L"fp*"; +CONST CHAR16 AnyF[] = L"F*"; +/** + Function to display mapping information to the user. + + If Specific is specified then Consist and Normal will be ignored since information will + be printed for the specific item only. + + @param[in] Verbose TRUE to display (extra) verbose information. + @param[in] Consist TRUE to display consistent mappings. + @param[in] Normal TRUE to display normal (not consist) mappings. + @param[in] TypeString Pointer to string of filter types. + @param[in] SFO TRUE to display output in Standard Output Format. + @param[in] Specific Pointer to string for specific map to display. + @param[in] Header TRUE to print the header block. + + @retval SHELL_SUCCESS The display was printed. + @retval SHELL_INVALID_PARAMETER One of Consist or Normal must be TRUE if no Specific. + +**/ +SHELL_STATUS +PerformMappingDisplay( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL, + IN CONST BOOLEAN Header + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + UINTN LoopVar; + CHAR16 *Test; + BOOLEAN Found; + + if (!Consist && !Normal && Specific == NULL && TypeString == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map"); + return (SHELL_INVALID_PARAMETER); + } + + if (TypeString != NULL) { + Test = (CHAR16*)Cd; + if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) { + Test = (CHAR16*)Hd; + if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) { + Test = (CHAR16*)Fp; + if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", TypeString); + return (SHELL_INVALID_PARAMETER); + } + } else if (Test == NULL) { + Test = (CHAR16*)AnyF; + } + } + } else { + Test = NULL; + } + + if (Header) { + // + // Print the header + // + if (!SFO) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map"); + } + } + + BufferSize = 0; + HandleBuffer = NULL; + + // + // Look up all SimpleFileSystems in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0, Found = FALSE + ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) && HandleBuffer != NULL + ; LoopVar ++ + ){ + Status = PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + if (!EFI_ERROR(Status)) { + Found = TRUE; + } + } + + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + SHELL_FREE_NON_NULL(HandleBuffer); + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + if (!EFI_ERROR(Status) && HandleBuffer != NULL) { + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof(EFI_HANDLE) + ; LoopVar ++ + ){ + // + // Skip any that were already done... + // + if (gBS->OpenProtocol( + HandleBuffer[LoopVar], + &gEfiSimpleFileSystemProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) { + continue; + } + Status = PerformSingleMappingDisplay( + Verbose, + Consist, + Normal, + Test, + SFO, + Specific, + HandleBuffer[LoopVar]); + if (!EFI_ERROR(Status)) { + Found = TRUE; + } + } + FreePool(HandleBuffer); + } + if (!Found) { + if (Specific != NULL) { + ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", Specific); + } else { + ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"map"); + } + } + return (SHELL_SUCCESS); +} + +/** + Perform a mapping display and parse for multiple types in the TypeString. + + @param[in] Verbose TRUE to use verbose output. + @param[in] Consist TRUE to display consistent names. + @param[in] Normal TRUE to display normal names. + @param[in] TypeString An optional comma-delimited list of types. + @param[in] SFO TRUE to display in SFO format. See Spec. + @param[in] Specific An optional specific map name to display alone. + + @retval SHELL_INVALID_PARAMETER A parameter was invalid. + @retval SHELL_SUCCESS The display was successful. + @sa PerformMappingDisplay +**/ +SHELL_STATUS +PerformMappingDisplay2( + IN CONST BOOLEAN Verbose, + IN CONST BOOLEAN Consist, + IN CONST BOOLEAN Normal, + IN CONST CHAR16 *TypeString, + IN CONST BOOLEAN SFO, + IN CONST CHAR16 *Specific OPTIONAL + ) +{ + CONST CHAR16 *TypeWalker; + SHELL_STATUS ShellStatus; + CHAR16 *Comma; + + + if (TypeString == NULL) { + return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE)); + } + ShellStatus = SHELL_SUCCESS; + for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) { + Comma = StrStr(TypeWalker, L","); + if (Comma == NULL) { + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } else { + PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } + break; + } else { + *Comma = CHAR_NULL; + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } else { + PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString)); + } + *Comma = L','; + TypeWalker = Comma + 1; + } + } + + return (ShellStatus); +} + +/** + Delete a specific map. + + @param[in] Specific The pointer to the name of the map to delete. + + @retval EFI_INVALID_PARAMETER Specific was NULL. + @retval EFI_SUCCESS The operation was successful. + @retval EFI_NOT_FOUND Specific could not be found. +**/ +EFI_STATUS +PerformMappingDelete( + IN CONST CHAR16 *Specific + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN BufferSize; + UINTN LoopVar; + BOOLEAN Deleted; + + if (Specific == NULL) { + return (EFI_INVALID_PARAMETER); + } + + BufferSize = 0; + HandleBuffer = NULL; + Deleted = FALSE; + + // + // Look up all SimpleFileSystems in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(HandleBuffer); + return (Status); + } + + if (HandleBuffer != NULL) { + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof(EFI_HANDLE) + ; LoopVar ++ + ){ + if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) { + Deleted = TRUE; + } + } + } + // + // Look up all BlockIo in the platform + // + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool(HandleBuffer); + HandleBuffer = AllocateZeroPool(BufferSize); + if (HandleBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &BufferSize, + HandleBuffer); + } + if (EFI_ERROR(Status)) { + SHELL_FREE_NON_NULL(HandleBuffer); + return (Status); + } + + if (HandleBuffer != NULL) { + // + // Get the map name(s) for each one. + // + for ( LoopVar = 0 + ; LoopVar < BufferSize / sizeof(EFI_HANDLE) + ; LoopVar ++ + ){ + // + // Skip any that were already done... + // + if (gBS->OpenProtocol( + HandleBuffer[LoopVar], + &gEfiDevicePathProtocolGuid, + NULL, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) { + continue; + } + if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) { + Deleted = TRUE; + } + } + } + SHELL_FREE_NON_NULL(HandleBuffer); + if (!Deleted) { + return (EFI_NOT_FOUND); + } + return (EFI_SUCCESS); +} + +/** + function to add a mapping from mapping. + + This function will get the device path associated with the mapping and call SetMap. + + @param[in] Map The Map to add a mapping for + @param[in] SName The name of the new mapping + + @retval SHELL_SUCCESS the mapping was added + @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved. + @return Shell version of a return value from EfiShellProtocol->SetMap + +**/ +SHELL_STATUS +AddMappingFromMapping( + IN CONST CHAR16 *Map, + IN CONST CHAR16 *SName + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + CHAR16 *NewSName; + RETURN_STATUS StrRetStatus; + + NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName); + if (NewSName == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + if (NewSName[StrLen(NewSName)-1] != L':') { + StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":")); + if (EFI_ERROR(StrRetStatus)) { + FreePool(NewSName); + return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT))); + } + } + + if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) { + FreePool(NewSName); + return (SHELL_INVALID_PARAMETER); + } + + DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map); + if (DevPath == NULL) { + FreePool(NewSName); + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->SetMap(DevPath, NewSName); + FreePool(NewSName); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + return (SHELL_SUCCESS); +} + +/** + function to add a mapping from an EFI_HANDLE. + + This function will get the device path associated with the Handle and call SetMap. + + @param[in] Handle The handle to add a mapping for + @param[in] SName The name of the new mapping + + @retval SHELL_SUCCESS the mapping was added + @retval SHELL_INVALID_PARAMETER SName was not valid for a map name. + @return Shell version of a return value from either + gBS->OpenProtocol or EfiShellProtocol->SetMap + +**/ +SHELL_STATUS +AddMappingFromHandle( + IN CONST EFI_HANDLE Handle, + IN CONST CHAR16 *SName + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_STATUS Status; + CHAR16 *NewSName; + RETURN_STATUS StrRetStatus; + + NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName); + if (NewSName == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + if (NewSName[StrLen(NewSName)-1] != L':') { + StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":")); + if (EFI_ERROR(StrRetStatus)) { + FreePool(NewSName); + return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT))); + } + } + + if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) { + FreePool(NewSName); + return (SHELL_INVALID_PARAMETER); + } + + Status = gBS->OpenProtocol( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID**)&DevPath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + FreePool(NewSName); + return (SHELL_DEVICE_ERROR); + } + Status = gEfiShellProtocol->SetMap(DevPath, NewSName); + FreePool(NewSName); + if (EFI_ERROR(Status)) { + return (SHELL_DEVICE_ERROR); + } + return (SHELL_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM MapParamList[] = { + {L"-d", TypeValue}, + {L"-r", TypeFlag}, + {L"-v", TypeFlag}, + {L"-c", TypeFlag}, + {L"-f", TypeFlag}, + {L"-u", TypeFlag}, + {L"-t", TypeValue}, + {L"-sfo", TypeValue}, + {NULL, TypeMax} + }; + +/** + The routine issues dummy read for every physical block device to cause + the BlockIo re-installed if media change happened. +**/ +VOID +ProbeForMediaChange ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *Handles; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINTN Index; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + // + // Probe for media change for every physical block io + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + Handles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo + ); + if (!EFI_ERROR (Status)) { + if (!BlockIo->Media->LogicalPartition) { + // + // Per spec: + // The function (ReadBlocks) must return EFI_NO_MEDIA or + // EFI_MEDIA_CHANGED even if LBA, BufferSize, or Buffer are invalid so the caller can probe + // for changes in media state. + // + BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + 0, + NULL + ); + } + } + } +} + +/** + Function for 'map' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *SName; + CONST CHAR16 *Mapping; + EFI_HANDLE MapAsHandle; + SHELL_STATUS ShellStatus; + BOOLEAN SfoMode; + BOOLEAN ConstMode; + BOOLEAN NormlMode; + CONST CHAR16 *Param1; + CONST CHAR16 *TypeString; + UINTN TempStringLength; + + ProblemParam = NULL; + Mapping = NULL; + SName = NULL; + ShellStatus = SHELL_SUCCESS; + MapAsHandle = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"map", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + SfoMode = ShellCommandLineGetFlag(Package, L"-sfo"); + ConstMode = ShellCommandLineGetFlag(Package, L"-c"); + NormlMode = ShellCommandLineGetFlag(Package, L"-f"); + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Deleting a map name... + // + if (ShellCommandLineGetFlag(Package, L"-d")) { + if ( ShellCommandLineGetFlag(Package, L"-r") + || ShellCommandLineGetFlag(Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag(Package, L"-u") + || ShellCommandLineGetFlag(Package, L"-t") + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + SName = ShellCommandLineGetValue(Package, L"-d"); + if (SName != NULL) { + Status = PerformMappingDelete(SName); + if (EFI_ERROR(Status)) { + if (Status == EFI_ACCESS_DENIED) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_ACCESS_DENIED; + } else if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", SName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else if ( ShellCommandLineGetFlag(Package, L"-r") +// || ShellCommandLineGetFlag(Package, L"-v") + || ConstMode + || NormlMode + || ShellCommandLineGetFlag(Package, L"-u") + || ShellCommandLineGetFlag(Package, L"-t") + ){ + ProbeForMediaChange (); + if ( ShellCommandLineGetFlag(Package, L"-r")) { + // + // Do the reset + // + Status = ShellCommandCreateInitialMappingsAndPaths(); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) { + // + // Do the Update + // + Status = ShellCommandUpdateMapping (); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status); + ShellStatus = SHELL_UNSUPPORTED; + } + } + if (ShellStatus == SHELL_SUCCESS) { + Param1 = ShellCommandLineGetRawValue(Package, 1); + TypeString = ShellCommandLineGetValue(Package, L"-t"); + if (!ConstMode + &&!NormlMode + &&TypeString == NULL + ) { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay( + ShellCommandLineGetFlag(Package, L"-v"), + TRUE, + TRUE, + NULL, + SfoMode, + Param1, + TRUE + ); + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay2( + ShellCommandLineGetFlag(Package, L"-v"), + ConstMode, + NormlMode, + TypeString, + SfoMode, + Param1 + ); + } + } + } else { + // + // adding or displaying (there were no flags) + // + SName = ShellCommandLineGetRawValue(Package, 1); + Mapping = ShellCommandLineGetRawValue(Package, 2); + if ( SName == NULL + && Mapping == NULL + ){ + // + // display only since no flags + // + ShellStatus = PerformMappingDisplay( + ShellCommandLineGetFlag(Package, L"-v"), + TRUE, + TRUE, + NULL, + SfoMode, + NULL, + TRUE + ); + } else if ( SName == NULL + || Mapping == NULL + ){ + // + // Display only the one specified + // + ShellStatus = PerformMappingDisplay( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, // note the variable here... + TRUE + ); + } else { + if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) { + MapAsHandle = ConvertHandleIndexToHandle(ShellStrToUintn(Mapping)); + } else { + MapAsHandle = NULL; + } + if (MapAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempStringLength = StrLen(SName); + if (!IsNumberLetterOnly(SName, TempStringLength-(SName[TempStringLength-1]==L':'?1:0))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", SName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + + if (ShellStatus == SHELL_SUCCESS) { + if (MapAsHandle != NULL) { + ShellStatus = AddMappingFromHandle(MapAsHandle, SName); + } else { + ShellStatus = AddMappingFromMapping(Mapping, SName); + } + + if (ShellStatus != SHELL_SUCCESS) { + switch (ShellStatus) { + case SHELL_ACCESS_DENIED: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map"); + break; + case SHELL_INVALID_PARAMETER: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping); + break; + case SHELL_DEVICE_ERROR: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, L"map", Mapping); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", ShellStatus|MAX_BIT); + } + } else { + // + // now do the display... + // + ShellStatus = PerformMappingDisplay( + FALSE, + FALSE, + FALSE, + NULL, + SfoMode, + SName, + TRUE + ); + } // we were sucessful so do an output + } + } // got a valid map target + } // got 2 variables + } // we are adding a mapping + } // got valid parameters + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c new file mode 100644 index 0000000..77ebfb6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c @@ -0,0 +1,167 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Function for 'mkdir' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMkDir ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + CONST CHAR16 *NewDirName; + CHAR16 *NewDirNameCopy; + CHAR16 *SplitName; + CHAR16 SaveSplitChar; + UINTN DirCreateCount; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_FILE_HANDLE FileHandle; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + NewDirNameCopy = NULL; + SplitName = NULL; + SaveSplitChar = CHAR_NULL; + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"mkdir", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + // + // create a set of directories + // + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we didnt get a single parameter + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"mkdir"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + for ( DirCreateCount = 1 + ; + ; DirCreateCount++ + ){ + // + // loop through each directory specified + // + + NewDirName = ShellCommandLineGetRawValue(Package, DirCreateCount); + if (NewDirName == NULL) { + break; + } + // + // check if that already exists... if yes fail + // + FileHandle = NULL; + Status = ShellOpenFileByName(NewDirName, + &FileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, + EFI_FILE_DIRECTORY + ); + if (!EFI_ERROR(Status)) { + ShellCloseFile(&FileHandle); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_ALREADY), gShellLevel2HiiHandle, NewDirName); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FileHandle == NULL); + // + // create the nested directory from parent to child. + // if NewDirName = test1\test2\test3, first create "test1\" directory, then "test1\test2\", finally "test1\test2\test3". + // + NewDirNameCopy = AllocateCopyPool (StrSize(NewDirName), NewDirName); + NewDirNameCopy = PathCleanUpDirectories (NewDirNameCopy); + if(NewDirNameCopy == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + break; + } + SplitName = NewDirNameCopy; + while (SplitName != NULL) { + SplitName = StrStr (SplitName + 1, L"\\"); + if (SplitName != NULL) { + SaveSplitChar = *(SplitName + 1); + *(SplitName + 1) = '\0'; + } + // + // check if current nested directory already exists... continue to create the child directory. + // + Status = ShellOpenFileByName (NewDirNameCopy, + &FileHandle, + EFI_FILE_MODE_READ, + EFI_FILE_DIRECTORY + ); + if (!EFI_ERROR(Status)) { + ShellCloseFile (&FileHandle); + } else { + Status = ShellCreateDirectory (NewDirNameCopy, &FileHandle); + if (EFI_ERROR(Status)) { + break; + } + if (FileHandle != NULL) { + gEfiShellProtocol->CloseFile (FileHandle); + } + } + if (SplitName != NULL) { + *(SplitName + 1) = SaveSplitChar; + } + } + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MKDIR_CREATEFAIL), gShellLevel2HiiHandle, NewDirName); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + SHELL_FREE_NON_NULL (NewDirNameCopy); + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c new file mode 100644 index 0000000..392c2a9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c @@ -0,0 +1,863 @@ +/** @file + Main file for mv shell level 2 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + function to determine if a move is between file systems. + + @param FullName [in] The name of the file to move. + @param Cwd [in] The current working directory + @param DestPath [in] The target location to move to + + @retval TRUE The move is across file system. + @retval FALSE The move is within a file system. +**/ +BOOLEAN +IsBetweenFileSystem( + IN CONST CHAR16 *FullName, + IN CONST CHAR16 *Cwd, + IN CONST CHAR16 *DestPath + ) +{ + CHAR16 *Test; + CHAR16 *Test1; + UINTN Result; + + Test = StrStr(FullName, L":"); + if (Test == NULL && Cwd != NULL) { + Test = StrStr(Cwd, L":"); + } + Test1 = StrStr(DestPath, L":"); + if (Test1 == NULL && Cwd != NULL) { + Test1 = StrStr(Cwd, L":"); + } + if (Test1 != NULL && Test != NULL) { + *Test = CHAR_NULL; + *Test1 = CHAR_NULL; + Result = StringNoCaseCompare(&FullName, &DestPath); + *Test = L':'; + *Test1 = L':'; + if (Result != 0) { + return (TRUE); + } + } + return (FALSE); +} + +/** + function to determine if SrcPath is valid to mv. + + if SrcPath equal CWD then it's invalid. + if SrcPath is the parent path of CWD then it's invalid. + is SrcPath is NULL return FALSE. + + if CwdPath is NULL then ASSERT() + + @param SrcPath [in] The source path. + @param CwdPath [in] The current working directory. + + @retval TRUE The source path is valid. + @retval FALSE The source path is invalid. +**/ +BOOLEAN +IsSoucePathValid( + IN CONST CHAR16* SrcPath, + IN CONST CHAR16* CwdPath + ) +{ + CHAR16* SrcPathBuffer; + CHAR16* CwdPathBuffer; + BOOLEAN Ret; + + ASSERT (CwdPath != NULL); + if (SrcPath == NULL) { + return FALSE; + } + + Ret = TRUE; + + SrcPathBuffer = AllocateCopyPool (StrSize (SrcPath), SrcPath); + if (SrcPathBuffer == NULL) { + return FALSE; + } + + CwdPathBuffer = AllocateCopyPool (StrSize (CwdPath), CwdPath); + if (CwdPathBuffer == NULL) { + FreePool(SrcPathBuffer); + return FALSE; + } + + gUnicodeCollation->StrUpr (gUnicodeCollation, SrcPathBuffer); + gUnicodeCollation->StrUpr (gUnicodeCollation, CwdPathBuffer); + + if (SrcPathBuffer[StrLen (SrcPathBuffer) -1 ] == L'\\') { + SrcPathBuffer[StrLen (SrcPathBuffer) - 1] = CHAR_NULL; + } + + if (CwdPathBuffer[StrLen (CwdPathBuffer) - 1] == L'\\') { + CwdPathBuffer[StrLen (CwdPathBuffer) - 1] = CHAR_NULL; + } + + if (StrCmp (CwdPathBuffer, SrcPathBuffer) == 0 || + ((StrStr (CwdPathBuffer, SrcPathBuffer) == CwdPathBuffer) && + (CwdPathBuffer[StrLen (SrcPathBuffer)] == L'\\')) + ) { + Ret = FALSE; + } + + FreePool (SrcPathBuffer); + FreePool (CwdPathBuffer); + + return Ret; +} + +/** + Function to validate that moving a specific file (FileName) to a specific + location (DestPath) is valid. + + This function will verify that the destination is not a subdirectory of + FullName, that the Current working Directory is not being moved, and that + the directory is not read only. + + if the move is invalid this function will report the error to StdOut. + + @param SourcePath [in] The name of the file to move. + @param Cwd [in] The current working directory + @param DestPath [in] The target location to move to + @param Attribute [in] The Attribute of the file + @param DestAttr [in] The Attribute of the destination + @param FileStatus [in] The Status of the file when opened + + @retval TRUE The move is valid + @retval FALSE The move is not +**/ +BOOLEAN +IsValidMove( + IN CONST CHAR16 *SourcePath, + IN CONST CHAR16 *Cwd, + IN CONST CHAR16 *DestPath, + IN CONST UINT64 Attribute, + IN CONST UINT64 DestAttr, + IN CONST EFI_STATUS FileStatus + ) +{ + CHAR16 *DestPathCopy; + CHAR16 *DestPathWalker; + + if ((Cwd != NULL) && ((Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)) { + if (!IsSoucePathValid (SourcePath, Cwd)) { + // + // Invalid move + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_MV_INV_CWD), gShellLevel2HiiHandle); + return FALSE; + } + } + + // + // invalid to move read only or move to a read only destination + // + if (((Attribute & EFI_FILE_READ_ONLY) != 0) + || (FileStatus == EFI_WRITE_PROTECTED) + || ((DestAttr & EFI_FILE_READ_ONLY) != 0) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle, SourcePath); + return (FALSE); + } + + DestPathCopy = AllocateCopyPool(StrSize(DestPath), DestPath); + if (DestPathCopy == NULL) { + return (FALSE); + } + + for (DestPathWalker = DestPathCopy; *DestPathWalker == L'\\'; DestPathWalker++) ; + + while(DestPathWalker != NULL && DestPathWalker[StrLen(DestPathWalker)-1] == L'\\') { + DestPathWalker[StrLen(DestPathWalker)-1] = CHAR_NULL; + } + + ASSERT(DestPathWalker != NULL); + ASSERT(SourcePath != NULL); + + // + // If they're the same, or if source is "above" dest on file path tree + // + if ( StringNoCaseCompare (&DestPathWalker, &SourcePath) == 0 || + ((StrStr(DestPathWalker, SourcePath) == DestPathWalker) && + (DestPathWalker[StrLen(SourcePath)] == '\\') + ) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle); + FreePool(DestPathCopy); + return (FALSE); + } + FreePool(DestPathCopy); + + return (TRUE); +} + +/** + Function to take a destination path that might contain wildcards and verify + that there is only a single possible target (IE we cant have wildcards that + have 2 possible destination). + + if the result is sucessful the caller must free *DestPathPointer. + + @param[in] DestParameter The original path to the destination. + @param[in, out] DestPathPointer A pointer to the callee allocated final path. + @param[in] Cwd A pointer to the current working directory. + @param[in] SingleSource TRUE to have only one source file. + @param[in, out] DestAttr A pointer to the destination information attribute. + + @retval SHELL_INVALID_PARAMETER The DestParameter could not be resolved to a location. + @retval SHELL_INVALID_PARAMETER The DestParameter could be resolved to more than 1 location. + @retval SHELL_INVALID_PARAMETER Cwd is required and is NULL. + @retval SHELL_SUCCESS The operation was sucessful. +**/ +SHELL_STATUS +GetDestinationLocation( + IN CONST CHAR16 *DestParameter, + IN OUT CHAR16 **DestPathPointer, + IN CONST CHAR16 *Cwd, + IN CONST BOOLEAN SingleSource, + IN OUT UINT64 *DestAttr + ) +{ + EFI_SHELL_FILE_INFO *DestList; + EFI_SHELL_FILE_INFO *Node; + CHAR16 *DestPath; + UINTN NewSize; + UINTN CurrentSize; + + DestList = NULL; + DestPath = NULL; + + ASSERT(DestAttr != NULL); + + if (StrStr(DestParameter, L"\\") == DestParameter) { + if (Cwd == NULL) { + return SHELL_INVALID_PARAMETER; + } + DestPath = AllocateZeroPool(StrSize(Cwd)); + if (DestPath == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + StrCpyS(DestPath, StrSize(Cwd) / sizeof(CHAR16), Cwd); + while (PathRemoveLastItem(DestPath)) ; + + // + // Append DestParameter beyond '\' which may be present + // + CurrentSize = StrSize(DestPath); + StrnCatGrow(&DestPath, &CurrentSize, &DestParameter[1], 0); + + *DestPathPointer = DestPath; + return (SHELL_SUCCESS); + } + // + // get the destination path + // + ShellOpenFileMetaArg((CHAR16*)DestParameter, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE, &DestList); + if (DestList == NULL || IsListEmpty(&DestList->Link)) { + // + // Not existing... must be renaming + // + if (StrStr(DestParameter, L":") == NULL) { + if (Cwd == NULL) { + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + NewSize = StrSize(Cwd); + NewSize += StrSize(DestParameter); + DestPath = AllocateZeroPool(NewSize); + if (DestPath == NULL) { + ShellCloseFileMetaArg(&DestList); + return (SHELL_OUT_OF_RESOURCES); + } + StrCpyS(DestPath, NewSize / sizeof(CHAR16), Cwd); + if (DestPath[StrLen(DestPath)-1] != L'\\' && DestParameter[0] != L'\\') { + StrCatS(DestPath, NewSize / sizeof(CHAR16), L"\\"); + } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestParameter[0] == L'\\') { + ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL; + } + StrCatS(DestPath, NewSize / sizeof(CHAR16), DestParameter); + } else { + ASSERT(DestPath == NULL); + DestPath = StrnCatGrow(&DestPath, NULL, DestParameter, 0); + if (DestPath == NULL) { + ShellCloseFileMetaArg(&DestList); + return (SHELL_OUT_OF_RESOURCES); + } + } + } else { + Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&DestList->Link); + *DestAttr = Node->Info->Attribute; + // + // Make sure there is only 1 node in the list. + // + if (!IsNodeAtEnd(&DestList->Link, &Node->Link)) { + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, L"mv", DestParameter); + return (SHELL_INVALID_PARAMETER); + } + + // + // If we are a directory or a single file, then one node is fine. + // + if (ShellIsDirectory(Node->FullName)==EFI_SUCCESS || SingleSource) { + DestPath = AllocateZeroPool(StrSize(Node->FullName)+sizeof(CHAR16)); + if (DestPath == NULL) { + ShellCloseFileMetaArg(&DestList); + return (SHELL_OUT_OF_RESOURCES); + } + StrCpyS(DestPath, (StrSize(Node->FullName)+sizeof(CHAR16)) / sizeof(CHAR16), Node->FullName); + StrCatS(DestPath, (StrSize(Node->FullName)+sizeof(CHAR16)) / sizeof(CHAR16), L"\\"); + } else { + // + // cant move multiple files onto a single file. + // + ShellCloseFileMetaArg(&DestList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_ERROR), gShellLevel2HiiHandle, L"mv", DestParameter); + return (SHELL_INVALID_PARAMETER); + } + } + + *DestPathPointer = DestPath; + ShellCloseFileMetaArg(&DestList); + + return (SHELL_SUCCESS); +} + +/** + Function to do a move across file systems. + + @param[in] Node A pointer to the file to be removed. + @param[in] DestPath A pointer to the destination file path. + @param[out] Resp A pointer to response from question. Pass back on looped calling + + @retval SHELL_SUCCESS The source file was moved to the destination. +**/ +EFI_STATUS +MoveBetweenFileSystems( + IN EFI_SHELL_FILE_INFO *Node, + IN CONST CHAR16 *DestPath, + OUT VOID **Resp + ) +{ + SHELL_STATUS ShellStatus; + + // + // First we copy the file + // + ShellStatus = CopySingleFile (Node->FullName, DestPath, Resp, TRUE, L"mv"); + + // + // Check our result + // + if (ShellStatus == SHELL_SUCCESS) { + // + // The copy was successful. delete the source file. + // + CascadeDelete(Node, TRUE); + Node->Handle = NULL; + } else if (ShellStatus == SHELL_ABORTED) { + return EFI_ABORTED; + } else if (ShellStatus == SHELL_ACCESS_DENIED) { + return EFI_ACCESS_DENIED; + } else if (ShellStatus == SHELL_VOLUME_FULL) { + return EFI_VOLUME_FULL; + } else { + return EFI_UNSUPPORTED; + } + + return (EFI_SUCCESS); +} + +/** + Function to take the destination path and target file name to generate the full destination path. + + @param[in] DestPath A pointer to the destination file path string. + @param[out] FullDestPath A pointer to the full destination path string. + @param[in] FileName Name string of the targe file. + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +EFI_STATUS +CreateFullDestPath( + IN CONST CHAR16 **DestPath, + OUT CHAR16 **FullDestPath, + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + if (FullDestPath == NULL || FileName == NULL || DestPath == NULL || *DestPath == NULL){ + return (EFI_INVALID_PARAMETER); + } + + Size = StrSize(*DestPath) + StrSize(FileName); + + *FullDestPath = AllocateZeroPool(Size); + if (*FullDestPath == NULL){ + return (EFI_OUT_OF_RESOURCES); + } + + StrCpyS(*FullDestPath, Size / sizeof(CHAR16), *DestPath); + if ((*FullDestPath)[StrLen(*FullDestPath)-1] != L'\\' && FileName[0] != L'\\') { + StrCatS(*FullDestPath, Size / sizeof(CHAR16), L"\\"); + } + StrCatS(*FullDestPath, Size / sizeof(CHAR16), FileName); + + return (EFI_SUCCESS); +} + +/** + Function to do a move within a file system. + + @param[in] Node A pointer to the file to be removed. + @param[in] DestPath A pointer to the destination file path. + @param[out] Resp A pointer to response from question. Pass back on looped calling. + + @retval SHELL_SUCCESS The source file was moved to the destination. + @retval SHELL_OUT_OF_RESOURCES A memory allocation failed. +**/ +EFI_STATUS +MoveWithinFileSystems( + IN EFI_SHELL_FILE_INFO *Node, + IN CHAR16 *DestPath, + OUT VOID **Resp + ) +{ + EFI_FILE_INFO *NewFileInfo; + CHAR16 *TempLocation; + UINTN NewSize; + UINTN Length; + EFI_STATUS Status; + + // + // Chop off map info from DestPath + // + if ((TempLocation = StrStr(DestPath, L":")) != NULL) { + CopyMem(DestPath, TempLocation+1, StrSize(TempLocation+1)); + } + + // + // construct the new file info block + // + NewSize = StrSize(DestPath); + NewSize += StrSize(Node->FileName) + SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16); + NewFileInfo = AllocateZeroPool(NewSize); + if (NewFileInfo == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle); + Status = EFI_OUT_OF_RESOURCES; + } else { + CopyMem(NewFileInfo, Node->Info, SIZE_OF_EFI_FILE_INFO); + if (DestPath[0] != L'\\') { + StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), L"\\"); + StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath); + } else { + StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath); + } + Length = StrLen(NewFileInfo->FileName); + if (Length > 0) { + Length--; + } + if (NewFileInfo->FileName[Length] == L'\\') { + if (Node->FileName[0] == L'\\') { + // + // Don't allow for double slashes. Eliminate one of them. + // + NewFileInfo->FileName[Length] = CHAR_NULL; + } + StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), Node->FileName); + } + NewFileInfo->Size = SIZE_OF_EFI_FILE_INFO + StrSize(NewFileInfo->FileName); + + // + // Perform the move operation + // + Status = ShellSetFileInfo(Node->Handle, NewFileInfo); + + // + // Free the info object we used... + // + FreePool(NewFileInfo); + } + + return (Status); +} +/** + function to take a list of files to move and a destination location and do + the verification and moving of those files to that location. This function + will report any errors to the user and continue to move the rest of the files. + + @param[in] FileList A LIST_ENTRY* based list of files to move + @param[out] Resp pointer to response from question. Pass back on looped calling + @param[in] DestParameter the originally specified destination location + + @retval SHELL_SUCCESS the files were all moved. + @retval SHELL_INVALID_PARAMETER a parameter was invalid + @retval SHELL_SECURITY_VIOLATION a security violation ocurred + @retval SHELL_WRITE_PROTECTED the destination was write protected + @retval SHELL_OUT_OF_RESOURCES a memory allocation failed +**/ +SHELL_STATUS +ValidateAndMoveFiles( + IN EFI_SHELL_FILE_INFO *FileList, + OUT VOID **Resp, + IN CONST CHAR16 *DestParameter + ) +{ + EFI_STATUS Status; + CHAR16 *HiiOutput; + CHAR16 *HiiResultOk; + CHAR16 *DestPath; + CHAR16 *FullDestPath; + CONST CHAR16 *Cwd; + CHAR16 *FullCwd; + SHELL_STATUS ShellStatus; + EFI_SHELL_FILE_INFO *Node; + VOID *Response; + UINT64 Attr; + CHAR16 *CleanFilePathStr; + + ASSERT(FileList != NULL); + ASSERT(DestParameter != NULL); + + DestPath = NULL; + FullDestPath = NULL; + Cwd = ShellGetCurrentDir(NULL); + Response = *Resp; + Attr = 0; + CleanFilePathStr = NULL; + FullCwd = NULL; + + if (Cwd != NULL) { + FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16)); + if (FullCwd == NULL) { + return SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, Cwd); + StrCatS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, L"\\"); + } + } + + Status = ShellLevel2StripQuotes (DestParameter, &CleanFilePathStr); + if (EFI_ERROR (Status)) { + SHELL_FREE_NON_NULL(FullCwd); + if (Status == EFI_OUT_OF_RESOURCES) { + return SHELL_OUT_OF_RESOURCES; + } else { + return SHELL_INVALID_PARAMETER; + } + } + + ASSERT (CleanFilePathStr != NULL); + + // + // Get and validate the destination location + // + ShellStatus = GetDestinationLocation(CleanFilePathStr, &DestPath, FullCwd, (BOOLEAN)(FileList->Link.ForwardLink == FileList->Link.BackLink), &Attr); + FreePool (CleanFilePathStr); + + if (ShellStatus != SHELL_SUCCESS) { + SHELL_FREE_NON_NULL (FullCwd); + return (ShellStatus); + } + DestPath = PathCleanUpDirectories(DestPath); + if (DestPath == NULL) { + FreePool (FullCwd); + return (SHELL_OUT_OF_RESOURCES); + } + + HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL); + HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL); + if (HiiOutput == NULL || HiiResultOk == NULL) { + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + SHELL_FREE_NON_NULL(FullCwd); + return (SHELL_OUT_OF_RESOURCES); + } + + // + // Go through the list of files and directories to move... + // + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + if (ShellGetExecutionBreakFlag()) { + break; + } + + // + // These should never be NULL + // + ASSERT(Node->FileName != NULL); + ASSERT(Node->FullName != NULL); + ASSERT(Node->Info != NULL); + + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + SHELL_FREE_NON_NULL(FullDestPath); + FullDestPath = NULL; + if (ShellIsDirectory(DestPath)==EFI_SUCCESS) { + CreateFullDestPath((CONST CHAR16 **)&DestPath, &FullDestPath, Node->FileName); + } + + // + // Validate that the move is valid + // + if (!IsValidMove(Node->FullName, FullCwd, FullDestPath!=NULL? FullDestPath:DestPath, Node->Info->Attribute, Attr, Node->Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + continue; + } + + ShellPrintEx(-1, -1, HiiOutput, Node->FullName, FullDestPath!=NULL? FullDestPath:DestPath); + + // + // See if destination exists + // + if (!EFI_ERROR(ShellFileExists(FullDestPath!=NULL? FullDestPath:DestPath))) { + if (Response == NULL) { + ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response); + } + switch (*(SHELL_PROMPT_RESPONSE*)Response) { + case ShellPromptResponseNo: + FreePool(Response); + Response = NULL; + continue; + case ShellPromptResponseCancel: + *Resp = Response; + // + // indicate to stop everything + // + SHELL_FREE_NON_NULL(FullCwd); + return (SHELL_ABORTED); + case ShellPromptResponseAll: + *Resp = Response; + break; + case ShellPromptResponseYes: + FreePool(Response); + Response = NULL; + break; + default: + FreePool(Response); + SHELL_FREE_NON_NULL(FullCwd); + return SHELL_ABORTED; + } + Status = ShellDeleteFileByName(FullDestPath!=NULL? FullDestPath:DestPath); + } + + if (IsBetweenFileSystem(Node->FullName, FullCwd, DestPath)) { + while (FullDestPath == NULL && DestPath != NULL && DestPath[0] != CHAR_NULL && DestPath[StrLen(DestPath) - 1] == L'\\') { + DestPath[StrLen(DestPath) - 1] = CHAR_NULL; + } + Status = MoveBetweenFileSystems(Node, FullDestPath!=NULL? FullDestPath:DestPath, &Response); + } else { + Status = MoveWithinFileSystems(Node, DestPath, &Response); + // + // Display error status + // + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"mv", Status); + } + } + + // + // Check our result + // + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (Status == EFI_WRITE_PROTECTED) { + ShellStatus = SHELL_WRITE_PROTECTED; + } else if (Status == EFI_OUT_OF_RESOURCES) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else if (Status == EFI_DEVICE_ERROR) { + ShellStatus = SHELL_DEVICE_ERROR; + } else if (Status == EFI_ACCESS_DENIED) { + ShellStatus = SHELL_ACCESS_DENIED; + } + } else { + ShellPrintEx(-1, -1, L"%s", HiiResultOk); + } + + } // main for loop + + SHELL_FREE_NON_NULL(FullDestPath); + SHELL_FREE_NON_NULL(DestPath); + SHELL_FREE_NON_NULL(HiiOutput); + SHELL_FREE_NON_NULL(HiiResultOk); + SHELL_FREE_NON_NULL(FullCwd); + return (ShellStatus); +} + +/** + Function for 'mv' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMv ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CHAR16 *Cwd; + UINTN CwdSize; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + UINTN LoopCounter; + EFI_SHELL_FILE_INFO *FileList; + VOID *Response; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + Response = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"mv", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + switch (ParamCount = ShellCommandLineGetCount(Package)) { + case 0: + case 1: + // + // we have insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"mv"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + case 2: + // + // must have valid CWD for single parameter... + // + if (ShellGetCurrentDir(NULL) == NULL){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"mv"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"mv", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_NOT_FOUND; + } else { + // + // ValidateAndMoveFiles will report errors to the screen itself + // + CwdSize = StrSize(ShellGetCurrentDir(NULL)) + sizeof(CHAR16); + Cwd = AllocateZeroPool(CwdSize); + if (Cwd == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"mv"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS (Cwd, CwdSize / sizeof (CHAR16), ShellGetCurrentDir (NULL)); + StrCatS (Cwd, CwdSize / sizeof (CHAR16), L"\\"); + ShellStatus = ValidateAndMoveFiles (FileList, &Response, Cwd); + FreePool (Cwd); + } + } + } + + break; + default: + ///@todo make sure this works with error half way through and continues... + for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount ; LoopCounter++) { + if (ShellGetExecutionBreakFlag()) { + break; + } + Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"mv", ShellCommandLineGetRawValue(Package, LoopCounter)); + ShellStatus = SHELL_NOT_FOUND; + } else { + // + // ValidateAndMoveFiles will report errors to the screen itself + // Only change ShellStatus if it's sucessful + // + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = ValidateAndMoveFiles(FileList, &Response, ShellCommandLineGetRawValue(Package, ParamCount)); + } else { + ValidateAndMoveFiles(FileList, &Response, ShellCommandLineGetRawValue(Package, ParamCount)); + } + } + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + Status = ShellCloseFileMetaArg(&FileList); + if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) { + ShellStatus = SHELL_ACCESS_DENIED; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, L"mv", ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT); + } + } + } + break; + } // switch on parameter count + + if (FileList != NULL) { + ShellCloseFileMetaArg(&FileList); + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + SHELL_FREE_NON_NULL(Response); + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c new file mode 100644 index 0000000..b0614bb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c @@ -0,0 +1,317 @@ +/** @file + Main file for Parse shell level 2 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Check if data is coming from StdIn output. + + @param[in] None + + @retval TRUE StdIn stream data available to parse + @retval FALSE StdIn stream data is not available to parse. +**/ +BOOLEAN +IsStdInDataAvailable ( + VOID + ) +{ + SHELL_FILE_HANDLE FileHandle; + EFI_STATUS Status; + CHAR16 CharBuffer; + UINTN CharSize; + UINT64 OriginalFilePosition; + + Status = EFI_SUCCESS; + FileHandle = NULL; + OriginalFilePosition = 0; + + if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) { + CharSize = sizeof(CHAR16); + gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition); + Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer); + if (EFI_ERROR (Status) || (CharSize != sizeof(CHAR16))) { + return FALSE; + } + gEfiShellProtocol->SetFilePosition(FileHandle, OriginalFilePosition); + } + + if (FileHandle == NULL) { + return FALSE; + } else { + return TRUE; + } +} + +/** + Handle stings for SFO Output with escape character ^ in a string + 1. Quotation marks in the string must be escaped by using a ^ character (i.e. ^"). + 2. The ^ character may be inserted using ^^. + + @param[in] String The Unicode NULL-terminated string. + + @retval NewString The new string handled for SFO. +**/ +EFI_STRING +HandleStringWithEscapeCharForParse ( + IN CHAR16 *String + ) +{ + EFI_STRING NewStr; + EFI_STRING StrWalker; + EFI_STRING ReturnStr; + + if (String == NULL) { + return NULL; + } + + // + // start to parse the input string. + // + NewStr = AllocateZeroPool (StrSize (String)); + if (NewStr == NULL) { + return NULL; + } + ReturnStr = NewStr; + StrWalker = String; + while (*StrWalker != CHAR_NULL) { + if (*StrWalker == L'^' && (*(StrWalker + 1) == L'^' || *(StrWalker + 1) == L'"')) { + *NewStr = *(StrWalker + 1); + StrWalker++; + } else { + *NewStr = *StrWalker; + } + StrWalker++; + NewStr++; + } + + return ReturnStr; +} + + +/** + Do the actual parsing of the file. the file should be SFO output from a + shell command or a similar format. + + @param[in] FileName The filename to open. + @param[in] TableName The name of the table to find. + @param[in] ColumnIndex The column number to get. + @param[in] TableNameInstance Which instance of the table to get (row). + @param[in] ShellCommandInstance Which instance of the command to get. + @param[in] StreamingUnicode Indicates Input file is StdIn Unicode streaming data or not + + @retval SHELL_NOT_FOUND The requested instance was not found. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +PerformParsing( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *TableName, + IN CONST UINTN ColumnIndex, + IN CONST UINTN TableNameInstance, + IN CONST UINTN ShellCommandInstance, + IN BOOLEAN StreamingUnicode + ) +{ + SHELL_FILE_HANDLE FileHandle; + EFI_STATUS Status; + BOOLEAN Ascii; + UINTN LoopVariable; + UINTN ColumnLoop; + CHAR16 *TempLine; + CHAR16 *ColumnPointer; + SHELL_STATUS ShellStatus; + CHAR16 *TempSpot; + CHAR16 *SfoString; + + ASSERT(FileName != NULL); + ASSERT(TableName != NULL); + + ShellStatus = SHELL_SUCCESS; + + Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"parse", FileName); + ShellStatus = SHELL_NOT_FOUND; + } else if (!EFI_ERROR (FileHandleIsDirectory (FileHandle))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, L"parse", FileName); + ShellStatus = SHELL_NOT_FOUND; + } else { + for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) { + TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); + + if ((TempLine == NULL) || (*TempLine == CHAR_NULL && StreamingUnicode)) { + break; + } + + // + // Search for "ShellCommand," in the file to start the SFO table + // for a given ShellCommand. The UEFI Shell spec does not specify + // a space after the comma. + // + if (StrStr (TempLine, L"ShellCommand,") == TempLine) { + LoopVariable++; + } + SHELL_FREE_NON_NULL(TempLine); + } + if (LoopVariable == ShellCommandInstance) { + LoopVariable = 0; + while(1) { + TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); + if (TempLine == NULL + || *TempLine == CHAR_NULL + || StrStr (TempLine, L"ShellCommand,") == TempLine) { + SHELL_FREE_NON_NULL(TempLine); + break; + } + if (StrStr (TempLine, TableName) == TempLine) { + LoopVariable++; + if (LoopVariable == TableNameInstance + || (TableNameInstance == (UINTN)-1)) { + for (ColumnLoop = 1, ColumnPointer = TempLine; ColumnLoop < ColumnIndex && ColumnPointer != NULL && *ColumnPointer != CHAR_NULL; ColumnLoop++) { + ColumnPointer = StrStr (ColumnPointer, L",\""); + if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL){ + ColumnPointer++; + } + } + if (ColumnLoop == ColumnIndex) { + if (ColumnPointer == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + TempSpot = StrStr (ColumnPointer, L",\""); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + while (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L' '){ + ColumnPointer++; + } + if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L'\"'){ + ColumnPointer++; + } + if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[StrLen (ColumnPointer) - 1] == L'\"'){ + ColumnPointer[StrLen (ColumnPointer) - 1] = CHAR_NULL; + } + SfoString = HandleStringWithEscapeCharForParse (ColumnPointer); + if (SfoString != NULL) { + ShellPrintEx (-1, -1, L"%s\r\n", SfoString); + SHELL_FREE_NON_NULL (SfoString); + } + } + } + } + } + SHELL_FREE_NON_NULL(TempLine); + } + } + } + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-i", TypeValue}, + {L"-s", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'parse' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunParse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *FileName; + CONST CHAR16 *TableName; + CONST CHAR16 *ColumnString; + SHELL_STATUS ShellStatus; + UINTN ShellCommandInstance; + UINTN TableNameInstance; + BOOLEAN StreamingUnicode; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + StreamingUnicode = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + StreamingUnicode = IsStdInDataAvailable (); + if ((!StreamingUnicode && (ShellCommandLineGetCount(Package) < 4)) || + (ShellCommandLineGetCount(Package) < 3)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if ((StreamingUnicode && (ShellCommandLineGetCount(Package) > 3)) || + (ShellCommandLineGetCount(Package) > 4)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (StreamingUnicode) { + FileName = L">i"; + TableName = ShellCommandLineGetRawValue(Package, 1); + ColumnString = ShellCommandLineGetRawValue(Package, 2); + } else { + FileName = ShellCommandLineGetRawValue(Package, 1); + TableName = ShellCommandLineGetRawValue(Package, 2); + ColumnString = ShellCommandLineGetRawValue(Package, 3); + } + if (ShellCommandLineGetValue(Package, L"-i") == NULL) { + TableNameInstance = (UINTN)-1; + } else { + TableNameInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-i")); + } + if (ShellCommandLineGetValue(Package, L"-s") == NULL) { + ShellCommandInstance = 1; + } else { + ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s")); + } + + ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance, StreamingUnicode); + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c new file mode 100644 index 0000000..753e422 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c @@ -0,0 +1,170 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ResetParamList[] = { + {L"-w", TypeValue}, + {L"-s", TypeValue}, + {L"-c", TypeValue}, + {L"-fwui", TypeFlag }, + {NULL, TypeMax } + }; + +/** + Function for 'reset' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CONST CHAR16 *String; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT64 OsIndications; + UINT32 Attr; + UINTN DataSize; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ResetParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"reset", ProblemParam); + FreePool(ProblemParam); + return (SHELL_INVALID_PARAMETER); + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + + if (ShellCommandLineGetFlag (Package, L"-fwui")) { + + DataSize = sizeof (OsIndications); + Status = gRT->GetVariable ( + EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Attr, &DataSize, &OsIndications + ); + if (!EFI_ERROR (Status)) { + if ((OsIndications & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0) { + DataSize = sizeof (OsIndications); + Status = gRT->GetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Attr, &DataSize, &OsIndications + ); + if (!EFI_ERROR (Status)) { + OsIndications |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + } else { + OsIndications = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + } + Status = gRT->SetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (OsIndications), &OsIndications + ); + } + } + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_UNSUPPORTED; + goto Error; + } + } + + // + // check for warm reset flag, then shutdown reset flag, then cold (default) reset flag + // + if (ShellCommandLineGetFlag(Package, L"-w")) { + if (ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-c")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + String = ShellCommandLineGetValue(Package, L"-w"); + if (String != NULL) { + gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + } + } else if (ShellCommandLineGetFlag(Package, L"-s")) { + if (ShellCommandLineGetFlag(Package, L"-c")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + String = ShellCommandLineGetValue(Package, L"-s"); + DEBUG_CODE(ShellPrintEx(-1,-1,L"Reset with %s (%d bytes)", String, String!=NULL?StrSize(String):0);); + if (String != NULL) { + gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + } + } + } else { + // + // this is default so dont worry about flag... + // + String = ShellCommandLineGetValue(Package, L"-c"); + if (String != NULL) { + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, StrSize(String), (VOID*)String); + } else { + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + } + } + } + } + + // + // we should never get here... so the free and return are for formality more than use + // as the ResetSystem function should not return... + // + +Error: + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c new file mode 100644 index 0000000..f79b5b6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c @@ -0,0 +1,380 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-q", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Determine if a directory has no files in it. + + @param[in] FileHandle The EFI_HANDLE to the directory. + + @retval TRUE The directory has no files (or directories). + @retval FALSE The directory has at least 1 file or directory in it. +**/ +BOOLEAN +IsDirectoryEmpty ( + IN EFI_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *FileInfo; + BOOLEAN NoFile; + BOOLEAN RetVal; + + RetVal = TRUE; + NoFile = FALSE; + FileInfo = NULL; + + for (Status = FileHandleFindFirstFile(FileHandle, &FileInfo) + ; !NoFile && !EFI_ERROR (Status) + ; FileHandleFindNextFile(FileHandle, FileInfo, &NoFile) + ){ + if (StrStr(FileInfo->FileName, L".") != FileInfo->FileName + &&StrStr(FileInfo->FileName, L"..") != FileInfo->FileName) { + RetVal = FALSE; + } + } + return (RetVal); +} + +/** + Delete a node and all nodes under it (including sub directories). + + @param[in] Node The node to start deleting with. + @param[in] Quiet TRUE to print no messages. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_ACCESS_DENIED A file was read only. + @retval SHELL_ABORTED The abort message was received. + @retval SHELL_DEVICE_ERROR A device error occured reading this Node. +**/ +SHELL_STATUS +CascadeDelete( + IN EFI_SHELL_FILE_INFO *Node, + IN CONST BOOLEAN Quiet + ) +{ + SHELL_STATUS ShellStatus; + EFI_SHELL_FILE_INFO *List; + EFI_SHELL_FILE_INFO *Node2; + EFI_STATUS Status; + SHELL_PROMPT_RESPONSE *Resp; + CHAR16 *TempName; + UINTN NewSize; + + Resp = NULL; + ShellStatus = SHELL_SUCCESS; + List = NULL; + Status = EFI_SUCCESS; + + if ((Node->Info->Attribute & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DETELE_RO), gShellLevel2HiiHandle, L"rm", Node->FullName); + return (SHELL_ACCESS_DENIED); + } + + if ((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) { + if (!IsDirectoryEmpty(Node->Handle)) { + if (!Quiet) { + Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_RM_LOG_DELETE_CONF), gShellLevel2HiiHandle, Node->FullName); + Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp); + ASSERT(Resp != NULL); + if (EFI_ERROR(Status) || *Resp != ShellPromptResponseYes) { + SHELL_FREE_NON_NULL(Resp); + return (SHELL_ABORTED); + } + SHELL_FREE_NON_NULL(Resp); + } + // + // empty out the directory + // + Status = gEfiShellProtocol->FindFilesInDir(Node->Handle, &List); + if (EFI_ERROR(Status)) { + if (List!=NULL) { + gEfiShellProtocol->FreeFileList(&List); + } + return (SHELL_DEVICE_ERROR); + } + for (Node2 = (EFI_SHELL_FILE_INFO *)GetFirstNode(&List->Link) + ; !IsNull(&List->Link, &Node2->Link) + ; Node2 = (EFI_SHELL_FILE_INFO *)GetNextNode(&List->Link, &Node2->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(Node2->FileName, L".") == 0 || StrCmp(Node2->FileName, L"..") == 0) { + continue; + } + Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE); + if (EFI_ERROR(Node2->Status) && StrStr(Node2->FileName, L":") == NULL) { + // + // Update the node filename to have full path with file system identifier + // + NewSize = StrSize(Node->FullName) + StrSize(Node2->FullName); + TempName = AllocateZeroPool(NewSize); + if (TempName == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + StrCpyS(TempName, NewSize/sizeof(CHAR16), Node->FullName); + TempName[StrStr(TempName, L":")+1-TempName] = CHAR_NULL; + StrCatS(TempName, NewSize/sizeof(CHAR16), Node2->FullName); + FreePool((VOID*)Node2->FullName); + Node2->FullName = TempName; + + // + // Now try again to open the file + // + Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE); + } + } + if (!EFI_ERROR(Node2->Status)) { + ShellStatus = CascadeDelete(Node2, Quiet); + } else if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = (SHELL_STATUS)(Node2->Status&(~0x80000000)); + } + if (ShellStatus != SHELL_SUCCESS) { + if (List!=NULL) { + gEfiShellProtocol->FreeFileList(&List); + } + return (ShellStatus); + } + } + if (List!=NULL) { + gEfiShellProtocol->FreeFileList(&List); + } + } + } + + if (!(StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0)) { + // + // now delete the current node... + // + if (!Quiet) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE), gShellLevel2HiiHandle, Node->FullName); + } + Status = gEfiShellProtocol->DeleteFile(Node->Handle); + Node->Handle = NULL; + } + + // + // We cant allow for the warning here! (Dont use EFI_ERROR Macro). + // + if (Status != EFI_SUCCESS){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR), gShellLevel2HiiHandle, Status); + return (SHELL_ACCESS_DENIED); + } else { + if (!Quiet) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_COMP), gShellLevel2HiiHandle); + } + return (SHELL_SUCCESS); + } +} + +/** + Determines if a Node is a valid delete target. Will prevent deleting the root directory. + + @param[in] List RESERVED. Not used. + @param[in] Node The node to analyze. + @param[in] Package RESERVED. Not used. +**/ +BOOLEAN +IsValidDeleteTarget( + IN CONST EFI_SHELL_FILE_INFO *List, + IN CONST EFI_SHELL_FILE_INFO *Node, + IN CONST LIST_ENTRY *Package + ) +{ + CONST CHAR16 *TempLocation; + BOOLEAN RetVal; + CHAR16 *SearchString; + CHAR16 *Pattern; + UINTN Size; + + if (Node == NULL || Node->FullName == NULL) { + return (FALSE); + } + + TempLocation = StrStr(Node->FullName, L":"); + if (StrLen(TempLocation) <= 2) { + // + // Deleting the root directory is invalid. + // + return (FALSE); + } + + TempLocation = ShellGetCurrentDir(NULL); + if (TempLocation == NULL) { + // + // No working directory is specified so whatever is left is ok. + // + return (TRUE); + } + + Pattern = NULL; + SearchString = NULL; + Size = 0; + Pattern = StrnCatGrow(&Pattern, &Size, TempLocation , 0); + Pattern = StrnCatGrow(&Pattern, &Size, L"\\" , 0); + Size = 0; + SearchString = StrnCatGrow(&SearchString, &Size, Node->FullName, 0); + if (!EFI_ERROR(ShellIsDirectory(SearchString))) { + SearchString = StrnCatGrow(&SearchString, &Size, L"\\", 0); + SearchString = StrnCatGrow(&SearchString, &Size, L"*", 0); + } + + if (Pattern == NULL || SearchString == NULL) { + RetVal = FALSE; + } else { + RetVal = TRUE; + if (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Pattern, SearchString)) { + RetVal = FALSE; + } + } + + SHELL_FREE_NON_NULL(Pattern ); + SHELL_FREE_NON_NULL(SearchString); + + return (RetVal); +} + +/** + Function for 'rm' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunRm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Param; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Node; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"rm", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"rm"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // get a list with each file specified by parameters + // if parameter is a directory then add all the files below it to the list + // + for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ; Param != NULL + ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ){ + Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"rm", (CHAR16*)Param); + ShellStatus = SHELL_NOT_FOUND; + break; + } + } + + if (ShellStatus == SHELL_SUCCESS){ + // + // loop through the list and make sure we are not aborting... + // + for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag() + ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link) + ){ + // + // skip the directory traversing stuff... + // + if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) { + continue; + } + + // + // do the deleting of nodes + // + if (EFI_ERROR(Node->Status)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR2), gShellLevel2HiiHandle, Node->Status); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + if (!IsValidDeleteTarget(FileList, Node, Package)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR3), gShellLevel2HiiHandle, Node->FullName); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + } + + ShellStatus = CascadeDelete(Node, ShellCommandLineGetFlag(Package, L"-q")); + } + } + // + // Free the fileList + // + if (FileList != NULL) { + Status = ShellCloseFileMetaArg(&FileList); + } + FileList = NULL; + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c new file mode 100644 index 0000000..d299ff3 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c @@ -0,0 +1,174 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Print out each environment variable registered with the Shell 2.0 GUID. + + If you spawn a pre 2.0 shell from the Shell 2.0 the environment variable may not carry through. + + @retval STATUS_SUCCESS the printout was sucessful + @return any return code from GetNextVariableName except EFI_NOT_FOUND +**/ +SHELL_STATUS +PrintAllShellEnvVars( + VOID + ) +{ + CONST CHAR16 *Value; + CONST CHAR16 *ConstEnvNameList; + + ConstEnvNameList = gEfiShellProtocol->GetEnv(NULL); + if (ConstEnvNameList == NULL) { + return (SHELL_SUCCESS); + } + while (*ConstEnvNameList != CHAR_NULL){ + Value = gEfiShellProtocol->GetEnv(ConstEnvNameList); + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, ConstEnvNameList, Value); + ConstEnvNameList += StrLen(ConstEnvNameList)+1; + } + + return (SHELL_SUCCESS); +} + +STATIC CONST SHELL_PARAM_ITEM SetParamList[] = { + {L"-d", TypeValue}, + {L"-v", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'set' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSet ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CONST CHAR16 *KeyName; + CONST CHAR16 *Value; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // Make sure globals are good... + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (SetParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"set", ProblemParam); + FreePool(ProblemParam); + return (SHELL_INVALID_PARAMETER); + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"set"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 1) != NULL && ShellCommandLineGetFlag(Package, L"-d")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"set"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-d")) { + // + // delete a environment variable + // + KeyName = ShellCommandLineGetValue(Package, L"-d"); + if (KeyName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"set", L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = ShellSetEnvironmentVariable(KeyName, L"", ShellCommandLineGetFlag(Package, L"-v")); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ND), gShellLevel2HiiHandle, L"set", KeyName); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // print out all current environment variables + // + return(PrintAllShellEnvVars()); + } else { + // + // we are either printing one or assigning one + // + KeyName = ShellCommandLineGetRawValue(Package, 1); + Value = ShellCommandLineGetRawValue(Package, 2); + if (KeyName != NULL && Value != NULL) { + // + // assigning one + // + Status = ShellSetEnvironmentVariable(KeyName, Value, ShellCommandLineGetFlag(Package, L"-v")); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ERROR_SET), gShellLevel2HiiHandle, L"set", KeyName); + ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); + } + + } else { + if (KeyName != NULL) { + // + // print out value for this one only. + // + Value = ShellGetEnvironmentVariable(KeyName); + if (Value == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_NF), gShellLevel2HiiHandle, L"set", KeyName); + ShellStatus = SHELL_SUCCESS; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, KeyName, Value); + ShellStatus = SHELL_SUCCESS; + } + } else { + ASSERT(FALSE); + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c new file mode 100644 index 0000000..ea51620 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c @@ -0,0 +1,972 @@ +/** @file + Main file for time, timezone, and date shell level 2 and shell level 3 functions. + + (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" + +/** + Determine if String is a valid representation for a time or date. + + @param[in] String The pointer to the string to test. + @param[in] Char The delimeter character. + @param[in] Min The minimum value allowed. + @param[in] Max The maximum value allowed. + @param[in] MinusOk Whether negative numbers are permitted. + + @retval TRUE String is a valid representation. + @retval FALSE String is invalid. +**/ +BOOLEAN +InternalIsTimeLikeString ( + IN CONST CHAR16 *String, + IN CONST CHAR16 Char, + IN CONST UINTN Min, + IN CONST UINTN Max, + IN CONST BOOLEAN MinusOk + ) +{ + UINTN Count; + Count = 0; + + if (MinusOk) { + // + // A single minus is ok. + // + if (*String == L'-') { + String++; + } + } + + // + // the first char must be numeric. + // + if (!ShellIsDecimalDigitCharacter(*String)) { + return (FALSE); + } + // + // loop through the characters and use the lib function + // + for ( ; String != NULL && *String != CHAR_NULL ; String++){ + if (*String == Char) { + Count++; + if (Count > Max) { + return (FALSE); + } + continue; + } + if (!ShellIsDecimalDigitCharacter(*String)) { + return (FALSE); + } + } + if (Count < Min) { + return (FALSE); + } + return (TRUE); +} + +/** + Verify that the DateString is valid and if so set that as the current + date. + + @param[in] DateString The pointer to a string representation of the date. + + @retval SHELL_INVALID_PARAMETER DateString was NULL. + @retval SHELL_INVALID_PARAMETER DateString was mis-formatted. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +CheckAndSetDate ( + IN CONST CHAR16 *DateString + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CHAR16 *DateStringCopy; + CHAR16 *Walker; + CHAR16 *Walker1; + + if (!InternalIsTimeLikeString(DateString, L'/', 2, 2, FALSE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + DateStringCopy = NULL; + DateStringCopy = StrnCatGrow(&DateStringCopy, NULL, DateString, 0); + if (DateStringCopy == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Walker = DateStringCopy; + + TheTime.Month = 0xFF; + TheTime.Day = 0xFF; + TheTime.Year = 0xFFFF; + + Walker1 = StrStr(Walker, L"/"); + if (Walker1 != NULL && *Walker1 == L'/') { + *Walker1 = CHAR_NULL; + } + + TheTime.Month = (UINT8)ShellStrToUintn (Walker); + if (Walker1 != NULL) { + Walker = Walker1 + 1; + } + Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL; + if (Walker1 != NULL && *Walker1 == L'/') { + *Walker1 = CHAR_NULL; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Day = (UINT8)ShellStrToUintn (Walker); + if (Walker1 != NULL) { + Walker = Walker1 + 1; + } + Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL; + if (Walker1 != NULL && *Walker1 == L'/') { + *Walker1 = CHAR_NULL; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + TheTime.Year = (UINT16)ShellStrToUintn (Walker); + } + } + + if (TheTime.Year < 100) { + if (TheTime.Year >= 98) { + TheTime.Year = (UINT16)(1900 + TheTime.Year); + } else { + TheTime.Year = (UINT16)(2000 + TheTime.Year); + } + } + + Status = gRT->SetTime(&TheTime); + + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + return (SHELL_INVALID_PARAMETER); +} + +/** + Function for 'date' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDate ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + EFI_TIME TheTime; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Param1; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"date", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"date"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // If there are 0 value parameters, then print the current date + // else If there are any value paramerers, then print error + // + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // get the current date + // + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + // + // ShellPrintEx the date in SFO or regular format + // + if (ShellCommandLineGetFlag(Package, L"-sfo")) { + // + // Match UEFI Shell spec: + // ShellCommand,"date" + // Date,"DD","MM","YYYY" + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"date"); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Day, TheTime.Month, TheTime.Year); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year); + } + } else { + if (PcdGet8(PcdShellSupportLevel) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"date"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // perform level 3 operation here. + // + Param1 = ShellCommandLineGetRawValue(Package, 1); + if (Param1 == NULL) { + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellStatus = CheckAndSetDate(Param1); + } + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"date", Param1); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + +// +// Note "-tz" is invalid for this (non-interactive) version of 'time'. +// +STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = { + {L"-d", TypeValue}, + {NULL, TypeMax} + }; + +STATIC CONST SHELL_PARAM_ITEM TimeParamList3[] = { + {L"-d", TypeValue}, + {L"-tz", TypeValue}, + {NULL, TypeMax} + }; + +/** + Verify that the TimeString is valid and if so set that as the current + time. + + @param[in] TimeString The pointer to a string representation of the time. + @param[in] Tz The value to set for TimeZone. + @param[in] Daylight The value to set for Daylight. + + @retval SHELL_INVALID_PARAMETER TimeString was NULL. + @retval SHELL_INVALID_PARAMETER TimeString was mis-formatted. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +CheckAndSetTime ( + IN CONST CHAR16 *TimeString, + IN CONST INT16 Tz, + IN CONST UINT8 Daylight + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CHAR16 *TimeStringCopy; + CHAR16 *Walker1; + CHAR16 *Walker2; + + if (TimeString != NULL && !InternalIsTimeLikeString(TimeString, L':', 1, 2, FALSE)) { + return (SHELL_INVALID_PARAMETER); + } + if (Daylight != 0xFF &&((Daylight & (EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT)) != Daylight)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + if (TimeString != NULL) { + TimeStringCopy = NULL; + TimeStringCopy = StrnCatGrow(&TimeStringCopy, NULL, TimeString, 0); + Walker1 = TimeStringCopy; + TheTime.Hour = 0xFF; + TheTime.Minute = 0xFF; + + Walker2 = Walker1!=NULL?StrStr(Walker1, L":"):NULL; + if (Walker2 != NULL && *Walker2 == L':') { + *Walker2 = CHAR_NULL; + } + TheTime.Hour = (UINT8)ShellStrToUintn (Walker1); + if (Walker2 != NULL) { + Walker1 = Walker2 + 1; + } + Walker2 = Walker1!=NULL?StrStr(Walker1, L":"):NULL; + if (Walker2 != NULL && *Walker2 == L':') { + *Walker2 = CHAR_NULL; + TheTime.Second = (UINT8)0; + } + else if (Walker2 == NULL) { + TheTime.Second = (UINT8)0; + } + if (Walker1 != NULL && Walker1[0] != CHAR_NULL) { + TheTime.Minute = (UINT8)ShellStrToUintn (Walker1); + if (Walker2 != NULL) { + Walker1 = Walker2 + 1; + if (Walker1 != NULL && Walker1[0] != CHAR_NULL) { + TheTime.Second = (UINT8)ShellStrToUintn (Walker1); + } + } + } + SHELL_FREE_NON_NULL(TimeStringCopy); + } + + + if (Tz >= -1440 && Tz <= 1440) { + // + // EFI_TIME TimeZone is stored to meet the following calculation (see UEFI Spec): + // Localtime = UTC - TimeZone + // This means the sign must be changed for the user provided Tz. + // EX: User wants to set TimeZone to Pacific Standard Time, so runs + // time -tz -480 # set to UTC-08:00 + // To meet the calculation, the sign must be changed. + // + TheTime.TimeZone = -Tz; + } else if (Tz == EFI_UNSPECIFIED_TIMEZONE) { + TheTime.TimeZone = Tz; + } + + if (Daylight != 0xFF) { + TheTime.Daylight = Daylight; + } + + Status = gRT->SetTime(&TheTime); + + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + + return (SHELL_INVALID_PARAMETER); +} + +/** + Function for 'time' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTime ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + EFI_TIME TheTime; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + INT16 Tz; + UINT8 Daylight; + CONST CHAR16 *TempLocation; + UINTN TzMinutes; + + // + // Initialize variables + // + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + if (PcdGet8(PcdShellSupportLevel) == 2) { + Status = ShellCommandLineParseEx (TimeParamList2, &Package, &ProblemParam, TRUE, TRUE); + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + Status = ShellCommandLineParseEx (TimeParamList3, &Package, &ProblemParam, TRUE, TRUE); + } + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"time", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // If there are no parameters, then print the current time + // + if (ShellCommandLineGetRawValue(Package, 1) == NULL + && !ShellCommandLineGetFlag(Package, L"-d") + && !ShellCommandLineGetFlag(Package, L"-tz")) { + // + // ShellPrintEx the current time + // + if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) { + TzMinutes = 0; + } else { + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + } + + if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second, + (TheTime.TimeZone > 0?L"-":L"+"), + ((ABS(TheTime.TimeZone)) / 60), + TzMinutes + ); + } else { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT_LOCAL), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second + ); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle); + } else if (ShellCommandLineGetFlag(Package, L"-d") && ShellCommandLineGetValue(Package, L"-d") == NULL) { + if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT_LOCAL), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second + ); + } else { + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_TIME_FORMAT), + gShellLevel2HiiHandle, + TheTime.Hour, + TheTime.Minute, + TheTime.Second, + (TheTime.TimeZone > 0?L"-":L"+"), + ((ABS(TheTime.TimeZone)) / 60), + TzMinutes + ); + } + switch (TheTime.Daylight) { + case 0: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST0), gShellLevel2HiiHandle); + break; + case EFI_TIME_ADJUST_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST1), gShellLevel2HiiHandle); + break; + case EFI_TIME_IN_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST2), gShellLevel2HiiHandle); + break; + case EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST3), gShellLevel2HiiHandle); + break; + default: + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight); + } + } else { + if (PcdGet8(PcdShellSupportLevel) == 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // perform level 3 operation here. + // + if ((TempLocation = ShellCommandLineGetValue(Package, L"-tz")) != NULL) { + if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16 *)TempLocation, L"_local") == 0) { + Tz = EFI_UNSPECIFIED_TIMEZONE; + } else if (TempLocation[0] == L'-') { + + Tz = (INT16) ShellStrToUintn (++TempLocation); + // + // When the argument of "time [-tz tz]" is not numeric, ShellStrToUintn() returns "-1". + // Here we can detect the argument error by checking the return of ShellStrToUintn(). + // + if (Tz == -1) { + Tz = 1441; //make it to be out of bounds value + } else { + Tz *= (-1); //sign convert + } + } else { + if (TempLocation[0] == L'+') { + Tz = (INT16)ShellStrToUintn (++TempLocation); + } else { + Tz = (INT16)ShellStrToUintn (TempLocation); + } + // + // Detect the return of ShellStrToUintn() to make sure the argument is valid. + // + if (Tz == -1) { + Tz = 1441; //make it to be out of bounds value + } + } + if (!(Tz >= -1440 && Tz <= 1440) && Tz != EFI_UNSPECIFIED_TIMEZONE) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-tz"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // intentionally out of bounds value will prevent changing it... + // + Tz = 1441; + } + TempLocation = ShellCommandLineGetValue(Package, L"-d"); + if (TempLocation != NULL) { + Daylight = (UINT8)ShellStrToUintn(TempLocation); + // + // The argument of "time [-d dl]" is unsigned, if the first character is '-', + // the argument is incorrect. That's because ShellStrToUintn() will skip past + // any '-' sign and convert what's next, forgetting the sign is here. + // + if (TempLocation[0] == '-') { + Daylight = 0xff; //make it invalid = will not use + } + if (Daylight != 0 && Daylight != 1 && Daylight != 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-d"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // invalid = will not use + // + Daylight = 0xFF; + } + if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = CheckAndSetTime(ShellCommandLineGetRawValue(Package, 1), Tz, Daylight); + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"time", ShellCommandLineGetRawValue(Package, 1)); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + +typedef struct { + INT16 TimeZone; + EFI_STRING_ID StringId; +} TIME_ZONE_ITEM; + +STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = { + {L"-l", TypeFlag}, + {L"-f", TypeFlag}, + {NULL, TypeMax} + }; +STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList3[] = { + {L"-l", TypeFlag}, + {L"-f", TypeFlag}, + {L"-s", TypeTimeValue}, + {NULL, TypeMax} + }; + + STATIC CONST TIME_ZONE_ITEM TimeZoneList[] = { + {720, STRING_TOKEN (STR_TIMEZONE_M12)}, + {660, STRING_TOKEN (STR_TIMEZONE_M11)}, + {600, STRING_TOKEN (STR_TIMEZONE_M10)}, + {540, STRING_TOKEN (STR_TIMEZONE_M9)}, + {480, STRING_TOKEN (STR_TIMEZONE_M8)}, + {420, STRING_TOKEN (STR_TIMEZONE_M7)}, + {360, STRING_TOKEN (STR_TIMEZONE_M6)}, + {300, STRING_TOKEN (STR_TIMEZONE_M5)}, + {270, STRING_TOKEN (STR_TIMEZONE_M430)}, + {240, STRING_TOKEN (STR_TIMEZONE_M4)}, + {210, STRING_TOKEN (STR_TIMEZONE_M330)}, + {180, STRING_TOKEN (STR_TIMEZONE_M3)}, + {120, STRING_TOKEN (STR_TIMEZONE_M2)}, + {60 , STRING_TOKEN (STR_TIMEZONE_M1)}, + {0 , STRING_TOKEN (STR_TIMEZONE_0)}, + {-60 , STRING_TOKEN (STR_TIMEZONE_P1)}, + {-120 , STRING_TOKEN (STR_TIMEZONE_P2)}, + {-180 , STRING_TOKEN (STR_TIMEZONE_P3)}, + {-210 , STRING_TOKEN (STR_TIMEZONE_P330)}, + {-240 , STRING_TOKEN (STR_TIMEZONE_P4)}, + {-270 , STRING_TOKEN (STR_TIMEZONE_P430)}, + {-300 , STRING_TOKEN (STR_TIMEZONE_P5)}, + {-330 , STRING_TOKEN (STR_TIMEZONE_P530)}, + {-345 , STRING_TOKEN (STR_TIMEZONE_P545)}, + {-360 , STRING_TOKEN (STR_TIMEZONE_P6)}, + {-390 , STRING_TOKEN (STR_TIMEZONE_P630)}, + {-420 , STRING_TOKEN (STR_TIMEZONE_P7)}, + {-480 , STRING_TOKEN (STR_TIMEZONE_P8)}, + {-540 , STRING_TOKEN (STR_TIMEZONE_P9)}, + {-570 , STRING_TOKEN (STR_TIMEZONE_P930)}, + {-600 , STRING_TOKEN (STR_TIMEZONE_P10)}, + {-660 , STRING_TOKEN (STR_TIMEZONE_P11)}, + {-720 , STRING_TOKEN (STR_TIMEZONE_P12)}, + {-780 , STRING_TOKEN (STR_TIMEZONE_P13)}, + {-840 , STRING_TOKEN (STR_TIMEZONE_P14)}, + {EFI_UNSPECIFIED_TIMEZONE, STRING_TOKEN (STR_TIMEZONE_LOCAL)} +}; + +/** + Verify that the TimeZoneString is valid and if so set that as the current + timezone. + + @param[in] TimeZoneString The pointer to a string representation of the timezone. + + @retval SHELL_INVALID_PARAMETER TimeZoneString was NULL. + @retval SHELL_INVALID_PARAMETER TimeZoneString was mis-formatted. + @retval SHELL_SUCCESS The operation was successful. +**/ +SHELL_STATUS +CheckAndSetTimeZone ( + IN CONST CHAR16 *TimeZoneString + ) +{ + EFI_TIME TheTime; + EFI_STATUS Status; + CHAR16 *TimeZoneCopy; + CHAR16 *Walker; + CHAR16 *Walker2; + UINTN LoopVar; + + if (TimeZoneString == NULL) { + return (SHELL_INVALID_PARAMETER); + } + + if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16 *)TimeZoneString, L"_local") == 0) { + Status = gRT->GetTime (&TheTime, NULL); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; + Status = gRT->SetTime (&TheTime); + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + return (SHELL_INVALID_PARAMETER); + } + if (TimeZoneString != NULL && !InternalIsTimeLikeString(TimeZoneString, L':', 1, 1, TRUE)) { + return (SHELL_INVALID_PARAMETER); + } + + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + TimeZoneCopy = NULL; + TimeZoneCopy = StrnCatGrow(&TimeZoneCopy, NULL, TimeZoneString, 0); + if (TimeZoneCopy == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Walker = TimeZoneCopy; + Walker2 = StrStr(Walker, L":"); + if (Walker2 != NULL && *Walker2 == L':') { + *Walker2 = CHAR_NULL; + } + if (*Walker == L'-') { + TheTime.TimeZone = (INT16)((ShellStrToUintn (++Walker)) * 60); + } else { + TheTime.TimeZone = (INT16)((INT16)(ShellStrToUintn (Walker)) * -60); + } + if (Walker2 != NULL) { + Walker = Walker2 + 1; + } + if (Walker != NULL && Walker[0] != CHAR_NULL) { + if (TheTime.TimeZone < 0) { + TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)ShellStrToUintn (Walker)); + } else { + TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)ShellStrToUintn (Walker)); + } + } + + Status = EFI_INVALID_PARAMETER; + + for ( LoopVar = 0 + ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0]) + ; LoopVar++ + ){ + if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) { + Status = gRT->SetTime(&TheTime); + break; + } + } + + FreePool(TimeZoneCopy); + + if (!EFI_ERROR(Status)){ + return (SHELL_SUCCESS); + } + return (SHELL_INVALID_PARAMETER); +} + + +/** + Function for 'timezone' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTimeZone ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // non interactive + // + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT8 LoopVar; + EFI_TIME TheTime; + BOOLEAN Found; + UINTN TzMinutes; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + if (PcdGet8(PcdShellSupportLevel) == 2) { + Status = ShellCommandLineParse (TimeZoneParamList2, &Package, &ProblemParam, TRUE); + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + Status = ShellCommandLineParseEx (TimeZoneParamList3, &Package, &ProblemParam, TRUE, TRUE); + } + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"timezone", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetCount(Package) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"timezone"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetFlag(Package, L"-s")) { + if ((ShellCommandLineGetFlag(Package, L"-l")) || (ShellCommandLineGetFlag(Package, L"-f"))) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"timezone", L"-l or -f"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(PcdGet8(PcdShellSupportLevel) == 3); + if (ShellCommandLineGetValue(Package, L"-s") == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"timezone", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Set the time zone + // + ShellStatus = CheckAndSetTimeZone(ShellCommandLineGetValue(Package, L"-s")); + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"timezone", ShellCommandLineGetValue(Package, L"-s")); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } + } else if (ShellCommandLineGetFlag(Package, L"-l")) { + // + // Print a list of all time zones + // + for ( LoopVar = 0 + ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0]) + ; LoopVar++ + ){ + ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle); + } + } else { + // + // Get Current Time Zone Info + // + Status = gRT->GetTime(&TheTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + Found = FALSE; + for ( LoopVar = 0 + ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0]) + ; LoopVar++ + ){ + if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) { + if (ShellCommandLineGetFlag(Package, L"-f")) { + // + // Print all info about current time zone + // + ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle); + } else { + // + // Print basic info only + // + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN(STR_TIMEZONE_SIMPLE), + gShellLevel2HiiHandle, + (TheTime.TimeZone > 0?L"-":L"+"), + (ABS(TheTime.TimeZone)) / 60, + TzMinutes); + } + Found = TRUE; + break; + } + } + if (!Found) { + // + // Print basic info only + // + TzMinutes = (ABS(TheTime.TimeZone)) % 60; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN(STR_TIMEZONE_SIMPLE), + gShellLevel2HiiHandle, + (TheTime.TimeZone > 0?L"-":L"+"), + (ABS(TheTime.TimeZone)) / 60, + TzMinutes); + + if (ShellCommandLineGetFlag(Package, L"-f")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_TIMEZONE_NI), gShellLevel2HiiHandle); + } + } + } else { + // + // TimeZone was EFI_UNSPECIFIED_TIMEZONE (local) from GetTime() + // + if (ShellCommandLineGetFlag (Package, L"-f")) { + for ( LoopVar = 0 + ; LoopVar < ARRAY_SIZE (TimeZoneList) + ; LoopVar++ + ){ + if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) { + // + // Print all info about current time zone + // + ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle); + break; + } + } + } else { + // + // Print basic info only + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIMEZONE_SIMPLE_LOCAL), gShellLevel2HiiHandle); + } + } + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c new file mode 100644 index 0000000..adecb5f --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c @@ -0,0 +1,350 @@ +/** @file + Main file for NULL named library for level 2 shell command functions. + + these functions are: + attrib, + cd, + cp, + date*, + time*, + load, + ls, + map, + mkdir, + mv, + parse, + rm, + reset, + set, + timezone*, + vol + + * functions are non-interactive only + + Copyright (c) 2014 Hewlett-Packard Development Company, L.P. + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "UefiShellLevel2CommandsLib.h" + +CONST CHAR16 mFileName[] = L"ShellCommands"; +EFI_HANDLE gShellLevel2HiiHandle = NULL; + +/** + Get the filename to get help text from if not using HII. + + @retval The filename. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameLevel2 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Level 2 Commands library. + + Install the handlers for level 2 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellLevel2CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // if shell level is less than 2 do nothing + // + if (PcdGet8(PcdShellSupportLevel) < 2) { + return (EFI_SUCCESS); + } + + gShellLevel2HiiHandle = HiiAddPackages (&gShellLevel2HiiGuid, gImageHandle, UefiShellLevel2CommandsLibStrings, NULL); + if (gShellLevel2HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"attrib", ShellCommandRunAttrib , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_ATTRIB) ); + ShellCommandRegisterCommandName(L"cd", ShellCommandRunCd , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CD) ); + ShellCommandRegisterCommandName(L"cp", ShellCommandRunCp , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CP) ); + ShellCommandRegisterCommandName(L"load", ShellCommandRunLoad , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD) ); + ShellCommandRegisterCommandName(L"map", ShellCommandRunMap , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MAP) ); + ShellCommandRegisterCommandName(L"mkdir", ShellCommandRunMkDir , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MKDIR) ); + ShellCommandRegisterCommandName(L"mv", ShellCommandRunMv , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MV) ); + ShellCommandRegisterCommandName(L"parse", ShellCommandRunParse , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_PARSE) ); + ShellCommandRegisterCommandName(L"reset", ShellCommandRunReset , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RESET) ); + ShellCommandRegisterCommandName(L"set", ShellCommandRunSet , ShellCommandGetManFileNameLevel2, 2, L"",FALSE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_SET) ); + ShellCommandRegisterCommandName(L"ls", ShellCommandRunLs , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LS) ); + ShellCommandRegisterCommandName(L"rm", ShellCommandRunRm , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RM) ); + ShellCommandRegisterCommandName(L"vol", ShellCommandRunVol , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_VOL) ); + + // + // support for permanent (built in) aliases + // + ShellCommandRegisterAlias(L"rm", L"del"); + ShellCommandRegisterAlias(L"ls", L"dir"); + ShellCommandRegisterAlias(L"cp", L"copy"); + ShellCommandRegisterAlias(L"mkdir", L"md"); + ShellCommandRegisterAlias(L"cd ..", L"cd.."); + ShellCommandRegisterAlias(L"cd \\", L"cd\\"); + ShellCommandRegisterAlias(L"mv", L"ren"); + ShellCommandRegisterAlias(L"mv", L"move"); + ShellCommandRegisterAlias(L"map", L"mount"); + // + // These are installed in level 2 or 3... + // + if (PcdGet8(PcdShellSupportLevel) == 2 || PcdGet8(PcdShellSupportLevel) == 3) { + ShellCommandRegisterCommandName(L"date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) ); + ShellCommandRegisterCommandName(L"time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) ); + ShellCommandRegisterCommandName(L"timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE)); + } else { + DEBUG_CODE_BEGIN(); + // + // we want to be able to test these so install them under a different name in debug mode... + // + ShellCommandRegisterCommandName(L"l2date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) ); + ShellCommandRegisterCommandName(L"l2time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) ); + ShellCommandRegisterCommandName(L"l2timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE)); + DEBUG_CODE_END(); + } + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS Always returned. +**/ +EFI_STATUS +EFIAPI +ShellLevel2CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellLevel2HiiHandle != NULL) { + HiiRemovePackages(gShellLevel2HiiHandle); + } + return (EFI_SUCCESS); +} + +/** + returns a fully qualified directory (contains a map drive at the begining) + path from a unknown directory path. + + If Path is already fully qualified this will return a duplicat otherwise this + will use get the current directory and use that to build the fully qualified + version. + + if the return value is not NULL it must be caller freed. + + @param[in] Path The unknown Path Value + + @retval NULL A memory allocation failed + @retval NULL A fully qualified path could not be discovered. + @retval other An allocated pointer to a fuly qualified path. +**/ +CHAR16* +GetFullyQualifiedPath( + IN CONST CHAR16* Path + ) +{ + CHAR16 *PathToReturn; + UINTN Size; + CONST CHAR16 *CurDir; + + PathToReturn = NULL; + Size = 0; + + ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL)); + // + // convert a local path to an absolute path + // + if (StrStr(Path, L":") == NULL) { + CurDir = gEfiShellProtocol->GetCurDir(NULL); + StrnCatGrow(&PathToReturn, &Size, CurDir, 0); + StrnCatGrow(&PathToReturn, &Size, L"\\", 0); + if (*Path == L'\\') { + Path++; + } + } + StrnCatGrow(&PathToReturn, &Size, Path, 0); + + PathCleanUpDirectories(PathToReturn); + + if (PathToReturn == NULL) { + return NULL; + } + + while (PathToReturn[StrLen(PathToReturn)-1] == L'*') { + PathToReturn[StrLen(PathToReturn)-1] = CHAR_NULL; + } + + return (PathToReturn); +} + +/** + Function to verify all intermediate directories in the path. + + @param[in] Path The pointer to the path to fix. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +VerifyIntermediateDirectories ( + IN CONST CHAR16 *Path + ) +{ + EFI_STATUS Status; + CHAR16 *PathCopy; + CHAR16 *TempSpot; + SHELL_FILE_HANDLE FileHandle; + + ASSERT(Path != NULL); + + Status = EFI_SUCCESS; + PathCopy = NULL; + PathCopy = StrnCatGrow(&PathCopy, NULL, Path, 0); + FileHandle = NULL; + + if (PathCopy == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + for (TempSpot = &PathCopy[StrLen(PathCopy)-1] ; *TempSpot != CHAR_NULL && *TempSpot != L'\\' ; TempSpot = &PathCopy[StrLen(PathCopy)-1]){ + *TempSpot = CHAR_NULL; + } + if (*TempSpot == L'\\') { + *TempSpot = CHAR_NULL; + } + + if (PathCopy != NULL && *PathCopy != CHAR_NULL) { + Status = VerifyIntermediateDirectories(PathCopy); + + if (PathCopy[StrLen(PathCopy)-1] != L':') { + if (!EFI_ERROR(Status)) { + Status = ShellOpenFileByName(PathCopy, &FileHandle, EFI_FILE_MODE_READ, 0); + if (FileHandle != NULL) { + ShellCloseFile(&FileHandle); + } + } + } + } + + SHELL_FREE_NON_NULL(PathCopy); + + return (Status); +} + +/** + String comparison without regard to case for a limited number of characters. + + @param[in] Source The first item to compare. + @param[in] Target The second item to compare. + @param[in] Count How many characters to compare. + + @retval 0 Source and Target are identical strings without regard to case. + @retval !=0 Source is not identical to Target. + +**/ +INTN +StrniCmp( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Target, + IN CONST UINTN Count + ) +{ + CHAR16 *SourceCopy; + CHAR16 *TargetCopy; + UINTN SourceLength; + UINTN TargetLength; + INTN Result; + + if (Count == 0) { + return 0; + } + + SourceLength = StrLen (Source); + TargetLength = StrLen (Target); + SourceLength = MIN (SourceLength, Count); + TargetLength = MIN (TargetLength, Count); + SourceCopy = AllocateCopyPool ((SourceLength + 1) * sizeof (CHAR16), Source); + if (SourceCopy == NULL) { + return -1; + } + TargetCopy = AllocateCopyPool ((TargetLength + 1) * sizeof (CHAR16), Target); + if (TargetCopy == NULL) { + FreePool (SourceCopy); + return -1; + } + + SourceCopy[SourceLength] = L'\0'; + TargetCopy[TargetLength] = L'\0'; + Result = gUnicodeCollation->StriColl (gUnicodeCollation, SourceCopy, TargetCopy); + FreePool (SourceCopy); + FreePool (TargetCopy); + return Result; +} + + +/** + Cleans off all the quotes in the string. + + @param[in] OriginalString pointer to the string to be cleaned. + @param[out] CleanString The new string with all quotes removed. + Memory allocated in the function and free + by caller. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ShellLevel2StripQuotes ( + IN CONST CHAR16 *OriginalString, + OUT CHAR16 **CleanString + ) +{ + CHAR16 *Walker; + + if (OriginalString == NULL || CleanString == NULL) { + return EFI_INVALID_PARAMETER; + } + + *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString); + if (*CleanString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { + if (*Walker == L'\"') { + CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + return EFI_SUCCESS; +} + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h new file mode 100644 index 0000000..f1e5b99 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h @@ -0,0 +1,369 @@ +/** @file + Main file for NULL named library for level 2 shell command functions. + + these functions are: + attrib, cd, cp, date*, time*, rm, reset, + load, ls, map, mkdir, mv, parse, set, timezone* + + + * functions are non-interactive only + + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_LEVEL2_COMMANDS_LIB_H_ +#define _UEFI_SHELL_LEVEL2_COMMANDS_LIB_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern CONST CHAR16 mFileName[]; +extern EFI_HANDLE gShellLevel2HiiHandle; + +/** + Function for 'attrib' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAttrib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'date' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunDate ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'time' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTime ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'load' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLoad ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'ls' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunLs ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'map' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMap ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'reset' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'timezone' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTimeZone ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'set' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunSet ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'mkdir' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMkDir ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'cd' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCd ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'cp' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'parse' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunParse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'rm' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunRm ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'mv' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunMv ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + returns a fully qualified directory (contains a map drive at the begining) + path from a unknown directory path. + + If Path is already fully qualified this will return a duplicat otherwise this + will use get the current directory and use that to build the fully qualified + version. + + if the return value is not NULL it must be caller freed. + + @param[in] Path The unknown Path Value + + @retval NULL A memory allocation failed + @retval NULL a fully qualified path could not be discovered. + @retval other pointer to a fuly qualified path. +**/ +CHAR16* +GetFullyQualifiedPath( + IN CONST CHAR16* Path + ); + +/** + Function to verify all intermediate directories in the path. + + @param[in] Path The pointer to the path to fix. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +VerifyIntermediateDirectories ( + IN CONST CHAR16 *Path + ); + +/** + String comparison without regard to case for a limited number of characters. + + @param[in] Source The first item to compare. + @param[in] Target The second item to compare. + @param[in] Count How many characters to compare. + + @retval 0 Source and Target are identical strings without regard to case. + @retval !=0 Source is not identical to Target. + +**/ +INTN +StrniCmp( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Target, + IN CONST UINTN Count + ); + +/** + Cleans off all the quotes in the string. + + @param[in] OriginalString pointer to the string to be cleaned. + @param[out] CleanString The new string with all quotes removed. + Memory allocated in the function and free + by caller. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +ShellLevel2StripQuotes ( + IN CONST CHAR16 *OriginalString, + OUT CHAR16 **CleanString + ); + +/** + Function for 'Vol' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunVol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function to Copy one file to another location + + If the destination exists the user will be prompted and the result put into *resp + + @param[in] Source pointer to source file name + @param[in] Dest pointer to destination file name + @param[out] Resp pointer to response from question. Pass back on looped calling + @param[in] SilentMode whether to run in quiet mode or not + @param[in] CmdName Source command name requesting single file copy + + @retval SHELL_SUCCESS The source file was copied to the destination +**/ +SHELL_STATUS +CopySingleFile( + IN CONST CHAR16 *Source, + IN CONST CHAR16 *Dest, + OUT VOID **Resp, + IN BOOLEAN SilentMode, + IN CONST CHAR16 *CmdName + ); + +/** + Delete a node and all nodes under it (including sub directories). + + @param[in] Node The node to start deleting with. + @param[in] Quiet TRUE to print no messages. + + @retval SHELL_SUCCESS The operation was successful. + @retval SHELL_ACCESS_DENIED A file was read only. + @retval SHELL_ABORTED The abort message was received. + @retval SHELL_DEVICE_ERROR A device error occured reading this Node. +**/ +SHELL_STATUS +CascadeDelete( + IN EFI_SHELL_FILE_INFO *Node, + IN CONST BOOLEAN Quiet + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf new file mode 100644 index 0000000..8391601 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf @@ -0,0 +1,84 @@ +## @file +# Provides shell level 2 functions +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellLevel2CommandsLib + FILE_GUID = CBF3931C-A2DF-40e5-B77E-CCA9555E9755 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellLevel2CommandsLibConstructor + DESTRUCTOR = ShellLevel2CommandsLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + UefiShellLevel2CommandsLib.c + UefiShellLevel2CommandsLib.h + UefiShellLevel2CommandsLib.uni + TimeDate.c + Load.c + Ls.c + Map.c + Reset.c + Set.c + MkDir.c + Cd.c + Cp.c + Parse.c + Rm.c + Mv.c + Attrib.c + Vol.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + HandleParsingLib + DevicePathLib + +[Protocols] + gEfiUnicodeCollation2ProtocolGuid ## CONSUMES + gEfiShellProtocolGuid ## CONSUMES + gEfiShellParametersProtocolGuid ## CONSUMES + gEfiDevicePathProtocolGuid ## CONSUMES + gEfiLoadedImageProtocolGuid ## CONSUMES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## CONSUMES + +[Guids] + gEfiFileSystemInfoGuid ## SOMETIMES_CONSUMES ## GUID + gEfiFileInfoGuid ## UNDEFINED + gShellLevel2HiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni new file mode 100644 index 0000000..65e1d38 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni @@ -0,0 +1,1085 @@ +// /** +// +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellLevel2CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 level 2 commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n" +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n" +#string STR_GEN_ATTRIBUTE #language en-US "%H%s%N: Invalid argument - '%H-a%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n" +#string STR_GEN_ERR_FILE #language en-US "%H%s%N: File '%H%s%N' error - %r\r\n" +#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n" +#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict.\r\n" +#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_FILE_CLOSE_FAIL #language en-US "%H%s%N: Cannot close file - '%H%s%N'\r\n" +#string STR_GEN_FILE_AD #language en-US "%H%s%N: File access error - '%H%s%N'\r\n" +#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_GEN_CRLF #language en-US "\r\n" +#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified.\r\n" +#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found.\r\n" +#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n" +#string STR_GEN_RES_OK #language en-US "- [ok]\r\n" +#string STR_GEN_NOT_DIR #language en-US "%H%s%N: '%H%s%N' is not a directory.\r\n" +#string STR_GEN_NOT_FILE #language en-US "%H%s%N: '%H%s%N' is not a file.\r\n" +#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n" +#string STR_GEN_MARG_ERROR #language en-US "%H%s%N: The destination '%H%s%N' is ambiguous.\r\n" +#string STR_GEN_FILE_ERROR #language en-US "%H%s%N: The destination is an existing file '%H%s%N'.\r\n" +#string STR_GEN_UEFI_FUNC_ERROR #language en-US "%H%s%N: UEFI function '%H%s%N' returned an incorrect value for: %s (%x).\r\n" +#string STR_GEN_UEFI_FUNC_WARN #language en-US "%H%s%N: UEFI function '%H%s%N' returned: %r\r\n" +#string STR_GEN_DEST_EXIST_OVR #language en-US "Destination file already exists. Overwrite? %BY%Nes, %BN%No, %BA%Nll, %BC%Nancel " +#string STR_GEN_CPY_FAIL #language en-US "%H%s%N: Copy failure: insufficient capacity on destination media.\r\n" +#string STR_GEN_CPY_READ_ERROR #language en-US "%H%s%N: reading '%B%s%N': IO Error \r\n" +#string STR_GEN_CPY_WRITE_ERROR #language en-US "%H%s%N: writing '%B%s%N': IO Error \r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n" + +#string STR_SET_DISP #language en-US "%V%8s %N= %H%s%N\r\n" +#string STR_SET_NF #language en-US "%H%s%N: Environment Variable '%H%s%N' not defined.\r\n" +#string STR_SET_ND #language en-US "%H%s%N: Environment Variable '%H%s%N' could not be deleted.\r\n" +#string STR_SET_ERROR_SET #language en-US "%H%s%N: Unable to set %H%s%N\r\n" + +#string STR_CD_PRINT #language en-US "%s\r\n" +#string STR_CD_NF #language en-US "%H%s%N: No mapping found.\r\n" + +#string STR_MAP_NF #language en-US "%H%s%N: Cannot find mapped device - '%H%s%N'\r\n" +#string STR_MAP_NOF #language en-US "%H%s%N: No mappable target found - '%H%s%N'\r\n" +#string STR_MAP_SFO_MAPPINGS #language en-US "Mappings,"%s","%s","%s"\r\n" +#string STR_MAP_HEADER #language en-US "%EMapping table%N\r\n" +#string STR_MAP_ENTRY #language en-US "%E%10s%N %HAlias(s):%N%s\r\n %s\r\n" +#string STR_MAP_ENTRY_VERBOSE #language en-US " Handle: [%H%02x%N]\r\n" + " Media Type: %s\r\n" + " Removable: %s\r\n" + " Current Dir: %s\r\n" + +#string STR_ATTRIB_OUTPUT_LINE #language en-US "Attrib: %1c%1c%1c%1c%1c %s\r\n" + +#string STR_MAP_MEDIA_FLOPPY #language en-US "Floppy" +#string STR_MAP_MEDIA_UNKNOWN #language en-US "Unknown" +#string STR_MAP_MEDIA_HARDDISK #language en-US "HardDisk" +#string STR_MAP_MEDIA_CDROM #language en-US "CD-Rom" + +#string STR_MKDIR_ALREADY #language en-US "Directory '%B%s%N' already exists.\r\n" +#string STR_MKDIR_CREATEFAIL #language en-US "Directory '%B%s%N' unable to create.\r\n" + +#string STR_DATE_FORMAT #language en-US "%02d/%02d/%04d\r\n" +#string STR_DATE_SFO_FORMAT #language en-US "Date,"%02d","%02d","%04d"\r\n" + +#string STR_TIME_FORMAT #language en-US "%02d:%02d:%02d (UTC%1s%02d:%02d)" +#string STR_TIME_FORMAT_LOCAL #language en-US "%02d:%02d:%02d (LOCAL)" +#string STR_TIME_DST0 #language en-US " DST: Not Affected\r\n" +#string STR_TIME_DST1 #language en-US " DST: Affected\r\n" +#string STR_TIME_DST2 #language en-US " DST: Adjusted\r\n" +#string STR_TIME_DST3 #language en-US " DST: Affected and Adjusted\r\n" + +#string STR_TIMEZONE_M12 #language en-US "UTC-12:00, International Date Line West\r\n" +#string STR_TIMEZONE_M11 #language en-US "UTC-11:00, Midway Island, Samoa\r\n" +#string STR_TIMEZONE_M10 #language en-US "UTC-10:00, Hawaii\r\n" +#string STR_TIMEZONE_M9 #language en-US "UTC-09:00, Alaska\r\n" +#string STR_TIMEZONE_M8 #language en-US "UTC-08:00, Pacific Time(US & Canada), Tijuana, Portland\r\n" +#string STR_TIMEZONE_M7 #language en-US "UTC-07:00, Arizona, Chihuahua, La Paz, Mazatlan, Mountain Time (US & Canada)\r\n" +#string STR_TIMEZONE_M6 #language en-US "UTC-06:00, Central America, Central Time(US & Canada)\r\n" +#string STR_TIMEZONE_M5 #language en-US "UTC-05:00, Bogota, Lima, Quito, Eastern Time(US & Canada)\r\n" +#string STR_TIMEZONE_M430 #language en-US "UTC-04:30, Caracas\r\n" +#string STR_TIMEZONE_M4 #language en-US "UTC-04:00, Atlantic Time(Canada), Caracas, Santiago\r\n" +#string STR_TIMEZONE_M330 #language en-US "UTC-03:30, Newfoundland\r\n" +#string STR_TIMEZONE_M3 #language en-US "UTC-03:00, Brasilia, Buenos Aires, Georgetown, Greenland\r\n" +#string STR_TIMEZONE_M2 #language en-US "UTC-02:00, Mid-Atlantic\r\n" +#string STR_TIMEZONE_M1 #language en-US "UTC-01:00, Azores, Cape Verde Is.\r\n" +#string STR_TIMEZONE_0 #language en-US "UTC , Greenwich Mean Time, Casablanca, Monrovia, Dublin, London\r\n" +#string STR_TIMEZONE_P1 #language en-US "UTC+01:00, Amsterdam, Berlin, Bern, Rome, Paris, West Central Africa\r\n" +#string STR_TIMEZONE_P2 #language en-US "UTC+02:00, Athens, Istanbul, Bucharest, Cairo, Jerusalem\r\n" +#string STR_TIMEZONE_P3 #language en-US "UTC+03:00, Baghdad, Kuwait, Riyadh, Moscow, Nairobi\r\n" +#string STR_TIMEZONE_P330 #language en-US "UTC+03:30, Tehran\r\n" +#string STR_TIMEZONE_P4 #language en-US "UTC+04:00, Abu Dhabi, Muscat, Baku, Tbilisi, Yerevan\r\n" +#string STR_TIMEZONE_P430 #language en-US "UTC+04:30, Kabul\r\n" +#string STR_TIMEZONE_P5 #language en-US "UTC+05:00, Ekaterinburg, Islamabad, Karachi, Tashkent\r\n" +#string STR_TIMEZONE_P530 #language en-US "UTC+05:30, Chennai, Kolkata, Mumbai, New Delhi\r\n" +#string STR_TIMEZONE_P545 #language en-US "UTC+05:45, Kathmandu\r\n" +#string STR_TIMEZONE_P6 #language en-US "UTC+06:00, Almaty, Novosibirsk, Astana, Dhaka, Sri Jayawardenepura\r\n" +#string STR_TIMEZONE_P630 #language en-US "UTC+06:30, Rangoon\r\n" +#string STR_TIMEZONE_P7 #language en-US "UTC+07:00, Bangkok, Hanio, Jakarta, Krasnoyarsk\r\n" +#string STR_TIMEZONE_P8 #language en-US "UTC+08:00, Beijing, Chongqing, Hong Kong, Urumqi, Taipei, Perth\r\n" +#string STR_TIMEZONE_P9 #language en-US "UTC+09:00, Osaka, Sapporo, Tokyo, Seoul, Yakutsk\r\n" +#string STR_TIMEZONE_P930 #language en-US "UTC+09:30, Adelaide, Darwin\r\n" +#string STR_TIMEZONE_P10 #language en-US "UTC+10:00, Canberra, Melbourne, Sydney, Guam, Hobart, Vladivostok\r\n" +#string STR_TIMEZONE_P11 #language en-US "UTC+11:00, Magadan, Solomon Is., New Caledonia\r\n" +#string STR_TIMEZONE_P12 #language en-US "UTC+12:00, Auckland, Wellington, Fiji, Kamchatka, Marshall Is.\r\n" +#string STR_TIMEZONE_P13 #language en-US "UTC+13:00, Nuku'alofa\r\n" +#string STR_TIMEZONE_P14 #language en-US "UTC+14:00, Line Islands\r\n" +#string STR_TIMEZONE_LOCAL #language en-US "LOCAL , Local Time\r\n" +#string STR_TIMEZONE_SIMPLE #language en-US "UTC%1s%02d:%02d\r\n" +#string STR_TIMEZONE_SIMPLE_LOCAL #language en-US "LOCAL\r\n" +#string STR_TIMEZONE_NI #language en-US "No additional information known." + +#string STR_LOAD_NOT_IMAGE #language en-US "Image '%s' is not an image.\r\n" +#string STR_LOAD_NOT_DRIVER #language en-US "Image '%s' is not a driver.\r\n" +#string STR_LOAD_LOADED #language en-US "Image '%s' loaded at %x - %r\r\n" +#string STR_LOAD_ERROR #language en-US "Image '%s' error in StartImage: %r\r\n" + +#string STR_LS_LINE_START_ALL #language en-US "%t %5s %1c % ,L11d " +#string STR_LS_LINE_END_FILE #language en-US "%s\r\n" +#string STR_LS_LINE_END_EXE #language en-US "%V%s%N\r\n" +#string STR_LS_LINE_END_DIR #language en-US "%B%s%N\r\n" +#string STR_LS_FOOTER_LINE #language en-US "% ,L11d File(s) % ,L11d bytes\r\n% ,L11d Dir(s)\r\n" +#string STR_LS_HEADER_LINE1 #language en-US "Directory of: %H%s%N\r\n" +#string STR_LS_FILE_NOT_FOUND #language en-US "%H%s%N: File Not Found - '%H%s%N'\r\n" +#string STR_LS_SFO_VOLINFO #language en-US "VolumeInfo,"%s","%Ld","%5s","%Ld","%Ld"\r\n" +#string STR_LS_SFO_FILEINFO #language en-US "FileInfo,"%s","%Ld","%Ld","%s%s%s%s%s","%02d:%02d:%02d","%02d.%02d.%04d","%02d:%02d:%02d","%02d.%02d.%04d","%02d:%02d:%02d","%02d.%02d.%04d"\r\n" + +#string STR_VOL_VOLINFO #language en-US "Volume %s (%s)\r\n" + "%Ld bytes total disk space\r\n" + "%Ld bytes available on disk\r\n" + "%d bytes in each allocation unit\r\n" + +#string STR_RM_LOG_DELETE_CONF #language en-US "Remove Subtree '%B%s%N' [y/n]?" +#string STR_RM_LOG_DELETE #language en-US "Deleting '%B%s%N'\r\n" +#string STR_RM_LOG_DELETE_ERR #language en-US "Delete error: %r\r\n" +#string STR_RM_LOG_DELETE_ERR2 #language en-US "Delete error. Couldn't open file: %r\r\n" +#string STR_RM_LOG_DELETE_ERR3 #language en-US "Delete error. Invalid target '%B%s%N'\r\n" +#string STR_RM_LOG_DELETE_COMP #language en-US "Delete successful.\r\n" +#string STR_RM_LOG_DETELE_RO #language en-US "%H%s%N: '%H%s%N' is read-only\r\n" + +#string STR_MV_OUTPUT #language en-US "Moving %s -> %s\r\n" +#string STR_MV_INV_SUB #language en-US "Cannot move a directory into itself or its subdirectory.\r\n" +#string STR_MV_INV_RO #language en-US "Cannot move to or from a read-only file or directory '%B%s%N'\r\n" +#string STR_MV_INV_CWD #language en-US "Cannot move current working directory or its subdirectory.\r\n" + +#string STR_CP_OUTPUT #language en-US "Copying %s -> %s\r\n" +#string STR_CP_ERROR #language en-US "%H%s%N: Could not copy - '%H%s%N'\r\n" +#string STR_CP_DIR_REQ #language en-US "%H%s%N: Copying a directory requires -r.\r\n" +#string STR_CP_DIR_WNF #language en-US "%H%s%N: The specified path does not exist - '%H%s%N'\r\n" +#string STR_CP_SD_SAME #language en-US "%H%s%N: The source and destination are the same.\r\n" +#string STR_CP_SD_PARENT #language en-US "%H%s%N: The destination is a parent of the source.\r\n" +#string STR_CP_DEST_ERROR #language en-US "%H%s%N: The destination is read-only.\r\n" +#string STR_CP_DEST_OPEN_FAIL #language en-US "%H%s%N: The destination file '%B%s%N' failed to open with create.\r\n" +#string STR_CP_DEST_DIR_FAIL #language en-US "%H%s%N: The destination directory '%B%s%N' could not be created.\r\n" +#string STR_CP_SRC_OPEN_FAIL #language en-US "%H%s%N: The source file '%B%s%N' failed to open with read.\r\n" + +#string STR_GET_HELP_ATTRIB #language en-US "" +".TH attrib 0 "Displays or modifies the attributes of files or directories."\r\n" +".SH NAME\r\n" +"Displays or modifies the attributes of files or directories.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"ATTRIB [+a|-a] [+s|-s] [+h|-h] [+r|-r] [file...] [directory...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" +a|-a - Sets or clears the 'archive' attribute.\r\n" +" +s|-s - Sets or clears the 'system' attribute.\r\n" +" +h|-h - Sets or clears the 'hidden' attribute.\r\n" +" +r|-r - Sets or clears the 'read-only' attribute.\r\n" +" file - Specifies the file name (wild cards are permitted).\r\n" +" directory - Specifies the directory name (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. Four attribute types are supported in the UEFI file system:\r\n" +" - Archive [A]\r\n" +" - System [S]\r\n" +" - Hidden [H]\r\n" +" - Read only [R]\r\n" +" 2. If a file (in general meaning) is a directory, then it is also shown\r\n" +" to have the attribute [D].\r\n" +" 3. If any file in the file list that is specified \r\n" +" does not exist, attrib will continue processing the remaining files\r\n" +" while reporting the error.\r\n" +" 4. If no attributes parameters are specified, the current attributes of\r\n" +" the specified files or directories are displayed.\r\n" +" 5. If no files or directories are specified, the command applies to\r\n" +" all files and sub-directories within the current directory.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the attributes of a directory:\r\n" +" fs0:\> attrib fs0:\ \r\n" +" \r\n" +" * To display the attributes of all files and sub-directories in the current\r\n" +" directory:\r\n" +" fs0:\> attrib *\r\n" +" \r\n" +" * To add the system attribute to all files with extension '.efi':\r\n" +" fs0:\> attrib +s *.efi\r\n" +" \r\n" +" * To remove the read-only attribute from all files with extension '.inf':\r\n" +" fs0:\> attrib -r *.inf\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_NOT_FOUND The requested file was not found.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED The media that the action was to take place on is\r\n" +" write-protected.\r\n" + +#string STR_GET_HELP_CD #language en-US "" +".TH cd 0 "Displays or changes the current directory."\r\n" +".SH NAME\r\n" +"Displays or changes the current directory.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"CD [path]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" path - Specifies the relative or absolute directory path.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command changes the current working directory that is used by the\r\n" +" UEFI Shell environment. If a file system mapping is specified, then the\r\n" +" current working directory is changed for that device. Otherwise, the\r\n" +" current working directory is changed for the current device.\r\n" +" 2. If path is not present, then the current working directory (including\r\n" +" file system mapping) is displayed to standard out.\r\n" +" 3. The table below describes the conventions that are used to refer to the\r\n" +" directory, its parent, and the root directory in the UEFI Shell\r\n" +" environment.\r\n" +" Convention Description\r\n" +" '.' Refers to the current directory.\r\n" +" '..' Refers to the directory's parent.\r\n" +" '\\\' Refers to the root of the current file system.\r\n" +" 4. The current working directory is maintained in the environment\r\n" +" variable %cwd%.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To change the current file system to the mapped fs0 file system:\r\n" +" Shell> fs0:\r\n" +" \r\n" +" * To change the current directory to subdirectory 'efi':\r\n" +" fs0:\> cd efi\r\n" +" \r\n" +" * To change the current directory to the parent directory (fs0:\):\r\n" +" fs0:\efi\> cd ..\r\n" +" \r\n" +" * To change the current directory to 'fs0:\efi\Tools':\r\n" +" fs0:\> cd efi\Tools\r\n" +" \r\n" +" * To change the current directory to the root of the current fs (fs0):\r\n" +" fs0:\efi\Tools\> cd \ \r\n" +" \r\n" +" * To move between volumes and maintain the current path, and then copy\r\n" +" all of files in fs0:\efi\Tools into the fs1:\Tmp directory:\r\n" +" fs0:\> cd \efi\Tools\r\n" +" fs0:\efi\Tools\> fs1:\r\n" +" fs1:\> cd Tmp\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_CP #language en-US "" +".TH cp 0 "Copies files or directories."\r\n" +".SH NAME\r\n" +"Copies one or more files or directories to another location.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"CP [-r] [-q] src [src...] [dst]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Makes a recursive copy.\r\n" +" -q - Makes a quiet copy (without a prompt).\r\n" +" src - Specifies a source file/directory name (wildcards are permitted).\r\n" +" dst - Specifies a destination file/directory name (wildcards are not permitted). \r\n" +" If more than one directory is specified, the last directory is\r\n" +" assumed to be the destination.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. '-r' must be specified if src is a directory. If '-r' is specified,\r\n" +" the source directory is recursively copied to the destination.\r\n" +" 'src' itself is copied.\r\n" +" 2. If a destination is not specified, the current working directory is\r\n" +" assumed to be the destination.\r\n" +" 3. 'CP -r src1 src2 dst' copies all files and subdirectories in 'src1' and\r\n" +" 'src2' to the destination 'dst'. 'src1' and 'src2' themselves are also\r\n" +" copied. The 'dst' parameter is interpreted as a directory.\r\n" +" 4. Copying a directory or file to itself is not allowed.\r\n" +" 5. If an error occurs, this command exits immediately and the remaining files or\r\n" +" directories are not copied.\r\n" +" 6. When 'cp' is executed with a script file, it always performs quiet\r\n" +" copying, regardless of whether the '-q' option is specified.\r\n" +" 7. If you are copying multiple files, the destination must be an existing\r\n" +" directory.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the contents of the current directory:\r\n" +" fs0:\> ls\r\n" +" \r\n" +" * To copy a file in the same directory and change the file name:\r\n" +" fs0:\> cp temp.txt readme.txt\r\n" +" \r\n" +" * To copy multiple files to another directory:\r\n" +" fs0:\> cp temp.txt isaBus.efi \Test\r\n" +" \r\n" +" * To copy multiple directories recursively to another directory:\r\n" +" fs0:\> cp -r test1 test2 boot \Test\r\n" +" \r\n" +" * To see the results of the above operations:\r\n" +" fs0:\> ls \Test\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly \r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient space to save the \r\n" +" requested file at the destination.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security \r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED An attempt was made to create a file on media that\r\n" +" was write-protected.\r\n" + +#string STR_GET_HELP_MAP #language en-US "" +".TH map 0 "Displays or defines file system mappings"\r\n" +".SH NAME\r\n" +"Displays or defines file system mappings.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MAP [-d ]\r\n" +"MAP [[-r][-v][-c][-f][-u][-t ][sname]]\r\n" +"MAP [sname handle | mapping]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Deletes a file system mapping.\r\n" +" -r - Resets file system mappings to default values.\r\n" +" -u - Adds file system mappings for newly-installed devices and\r\n" +" removes mappings for uninstalled devices. This does not change\r\n" +" the mappings of existing devices and preserves user-defined mappings.\r\n" +" -v - Displays verbose information about all file system mappings.\r\n" +" -c - Displays the consistent mappings.\r\n" +" -f - Displays the normal mappings (not the consistent mappings).\r\n" +" -t - Displays the device mappings, filtered according to the device type.\r\n" +" Supported types are:\r\n" +" fp - Floppy\r\n" +" hd - Hard Disk\r\n" +" cd - CD-ROM\r\n" +" Types can be combined by putting a comma between two types. Spaces\r\n" +" are not allowed between types.\r\n" +" -sfo - Displays information in Standard-Format Output.\r\n" +" sname - Specifies a mapping name.\r\n" +" handle - Specifies the number of a handle. Use the same value that is\r\n" +" displayed by the 'dh' command.\r\n" +" mapping - Specifies a new mapping name to assign to a device.\r\n" +" This value must end with a ':'.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command creates a mapping between a user-defined name and a device.\r\n" +" The most common use of this command is to create a mapped name for\r\n" +" devices that support a file system protocol. After these mappings are\r\n" +" created, the names can be used with all the file manipulation commands.\r\n" +" 2. The UEFI Shell environment creates default mappings for all of the\r\n" +" devices that support a recognized file system.\r\n" +" 3. This command can be used to create additional mappings, or \r\n" +" when used with the -d option, to delete an existing mapping. If it is\r\n" +" used without any parameters, all of the current mappings are listed.\r\n" +" If the -v option is used, the mappings are shown with additional\r\n" +" information about each device.\r\n" +" 4. The -r option is used to reset all the default mappings in a system,\r\n" +" which is useful if the system configuration has changed since the\r\n" +" last boot.\r\n" +" 5. The -u option adds mappings for newly-installed devices and removes\r\n" +" mappings for uninstalled devices without changing the mappings of\r\n" +" existing devices. User-defined mappings are also preserved. A mapping\r\n" +" history is saved, which preserves the original mapping name for\r\n" +" a device with a specific device path. The current directory is also\r\n" +" preserved if the current device is not changed.\r\n" +" 6. Each device in the system has a consistent mapping. If the hardware\r\n" +" configuration has not changed, the device's consistent mappings do not\r\n" +" change. If two or more machines have the same hardware configurations,\r\n" +" the device's consistent mapping remains the same. Use the -c option to\r\n" +" list all the consistent mappings in the system.\r\n" +" 7. The mapping value must consist of digits and characters. Other\r\n" +" characters are illegal.\r\n" +" 8. This command support wildcards. You can use the wildcards to delete\r\n" +" or show the mapping. However, when you assign the mapping, wildcards\r\n" +" are forbidden.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display verbose mapping table information:\r\n" +" Shell> map -v\r\n" +" \r\n" +" * To assign a different name to fs0:\r\n" +" Shell> map floppy fs0:\r\n" +" \r\n" +" * To operate with the mapped name:\r\n" +" Shell> floppy:\r\n" +" \r\n" +" * To delete a mapped name:\r\n" +" Shell> map -d floppy:\r\n" +" \r\n" +" * To display all the mapped names starting with 'f': \r\n" +" Shell> map f* \r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_MKDIR #language en-US "" +".TH mkdir 0 "Creates directories."\r\n" +".SH NAME\r\n" +"Creates one or more new directories.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MKDIR dir [dir...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" dir - Specifies the name of a directory or directories to create.\r\n" +" (Wildcards are not allowed)\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. Mkdir can create one or more new directories.\r\n" +" 2. If dir includes nested directories, then parent directories will be\r\n" +" created before child directories.\r\n" +" 3. If the directory already exists, mkdir will exit with an error.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To create a new directory:\r\n" +" fs0:\> mkdir rafter\r\n" +" \r\n" +" * To create multiple directories:\r\n" +" fs0:\> mkdir temp1 temp2\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly \r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient space on the destination \r\n" +" to create the requested directory.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security \r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED An attempt was made to create a directory when the\r\n" +" target media was write-protected.\r\n" + +#string STR_GET_HELP_MV #language en-US "" +".TH mv 0 "Moves files."\r\n" +".SH NAME\r\n" +"Moves one or more files to a destination within or between file systems.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"MV src [src...] [dst]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" src - Specifies a source file/directory name (wildcards are permitted).\r\n" +" dst - Specifies a destination file/directory name (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command moves one or more files to a destination within or between\r\n" +" file systems.\r\n" +" 2. If the destination is an existing directory, the sources are moved\r\n" +" into that directory. You cannot move the sources to a non-existing\r\n" +" directory.\r\n" +" 3. If a destination is not specified, the current directory is assumed to be\r\n" +" the destination. If there is more than one argument on the command line,\r\n" +" the last one is assumed to be the destination.\r\n" +" 4. Attempting to move a read-only file/directory results in an error.\r\n" +" Moving a directory that contains read-only files is allowed.\r\n" +" 5. You cannot move a directory into itself or its subdirectories.\r\n" +" 6. You cannot move a directory if the current working directory is itself or\r\n" +" its subdirectories.\r\n" +" 7. If an error occurs, the remaining files or directories are still be\r\n" +" moved.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To rename a file:\r\n" +" fs0:\> mv IsaBus.efi Bus.efi\r\n" +" \r\n" +" * To move a directory to the current directory:\r\n" +" fs0:\> mkdir Test1\Temp\r\n" +" fs0:\> mv Test1\Temp\r\n" +" \r\n" +" * To rename a directory:\r\n" +" fs0:\> mv efi efi1.1\r\n" +" \r\n" +" * To move multiple directories at a time:\r\n" +" fs0:\> mv Test1 Test2 Test\r\n" +" \r\n" +" * To attempt moving a read-only directory, which results in a failure:\r\n" +" fs0:\Test> attrib +r Temp1\r\n" +" DA R fs0:\Test\Temp1\r\n" +" fs0:\Test> mv Temp1 Temp2\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_NOT_FOUND The source file was not able to be found.\r\n" +" SHELL_OUT_OF_RESOURCES There was insufficient free space to move the\r\n" +" requested file to its destination.\r\n" +" SHELL_WRITE_PROTECTED An attempt was made to create a file on media that\r\n" +" was write-protected.\r\n" + +#string STR_GET_HELP_PARSE #language en-US "" +".TH parse 0 "Parses standard format output files."\r\n" +".SH NAME\r\n" +"Retrieves a value from a standard format output file.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"PARSE filename tablename column [-i ] [-s ]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" filename - Specifies a source file name.\r\n" +" tablename - Specifies the name of the table to be parsed.\r\n" +" column - Specifies the one-based column index to use to determine which value\r\n" +" from a particular record to parse.\r\n" +" -i - Specifies an instance number to use to start parsing the ShellCommand table,\r\n" +" and then the specified tablename. If not specified, all instances are returned.\r\n" +" -s - Specifies an instance number to use to start parsing the ShellCommand\r\n" +" table. If not present, then 1 is assumed.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command enables you to parse data from a file that has been output\r\n" +" using the -sfo parameter.\r\n" +" 2. Since the standard formatted output has a well known means of parsing,\r\n" +" this command is intended to provide an easy way of enabling\r\n" +" scripts to consume retrieved data from such constructed output files, and\r\n" +" use it in the logic of scripts written for the UEFI shell.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * The following data is contained in a temporary file (temp.txt):\r\n" +" ShellCommand,"ls"\r\n" +" VolumeInfo,"MikesVolume","400000000","FALSE","32000000","16000000"\r\n" +" FileInfo,"FS0:\efi\\boot\winloader.efi","45670","45900","arsh","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n" +" FileInfo,"FS0:\efi\\boot\mikesfile.txt","1250","1280","a","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n" +" FileInfo,"FS0:\efi\\boot\\readme.txt","795","900","a","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n" +" \r\n" +" * To display VolumeInfo column 2 in temp.txt:\r\n" +" fs0:\> parse temp.txt VolumeInfo 2\r\n" +" MikesVolume\r\n" +" \r\n" +" * To display FileInfo column 3 in temp.txt, starting with instance 3:\r\n" +" fs0:\> parse temp.txt FileInfo 3 -i 3\r\n" +" 795\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_NOT_FOUND The source file was not able to be found.\r\n" + +#string STR_GET_HELP_RESET #language en-US "" +".TH reset 0 "Reset the system."\r\n" +".SH NAME\r\n" +"Resets the system.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"RESET [-w [string]]\r\n" +"RESET [-s [string]]\r\n" +"RESET [-c [string]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -s - Performs a shutdown.\r\n" +" -w - Performs a warm boot.\r\n" +" -c - Performs a cold boot.\r\n" +" string - Describes a reason for the reset.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command resets the system.\r\n" +" 2. The default is to perform a cold reset unless the -w parameter is\r\n" +" specified.\r\n" +" 3. If a reset string is specified, it is passed into the Reset() \r\n" +" function, and the system records the reason for the system reset.\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly \r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_RM #language en-US "" +".TH rm 0 "Deletes one or more files or directories."\r\n" +".SH NAME\r\n" +"Deletes one or more files or directories.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"RM [-q] file/directory [file/directory ...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -q - Specifies quiet mode. Does not prompt for a confirmation.\r\n" +" file - Specifies a file name (wildcards are permitted).\r\n" +" directory - Specifies a directory name (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command deletes one or more files or directories.\r\n" +" 2. If the target is a directory, it deletes the directory, including all\r\n" +" its subdirectories.\r\n" +" 3. Redirecting a file whose parent directory (or the file\r\n" +" itself) is being deleted is not allowed.\r\n" +" 4. Removing a read-only file/directory results in a failure.\r\n" +" 5. Removing a directory containing read-only file(s) results in\r\n" +" a failure. If an error occurs, the command exits immediately and stops\r\n" +" removing files/directories.\r\n" +" 6. You cannot remove a directory when the current directory is itself or its\r\n" +" subdirectory. If a file contains wildcards, you are not prompted for\r\n" +" confirmation.\r\n" +" 7. The root directory cannot be removed.\r\n" +" 8. The current directory or its ancestor directories cannot be removed.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To remove multiple directories at a time:\r\n" +" fs0:\> rm Test\Temp1 Temp2\r\n" +" \r\n" +" * To remove multiple directories with wildcards:\r\n" +" fs0:\> rm Test\Temp*\r\n" +" \r\n" +" * To attempt removing a directory that contains a read-only file,\r\n" +" which results in a failure:\r\n" +" fs0:\> attrib +r Test\Temp1\readme.txt\r\n" +" A R fs0:\Test\Temp1\readme.txt\r\n" +" fs0:\> rm Test\Temp1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The source file was not able to be found.\r\n" +" SHELL_WRITE_PROTECTED The target was write protected.\r\n" + +#string STR_GET_HELP_SET #language en-US "" +".TH set 0 "Displays or modifies UEFI Shell environment variables."\r\n" +".SH NAME\r\n" +"Displays or modifies UEFI Shell environment variables.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"SET [-v] [sname [value]]\r\n" +"SET [-d ]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Deletes the environment variable.\r\n" +" -v - Displays or modifies a volatile variable.\r\n" +" sname - Specifies an environment variable name.\r\n" +" value - Specifies an environment variable value.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command is used to maintain the UEFI Shell environment variables.\r\n" +" This command can do the following:\r\n" +" - Display environment variables.\r\n" +" - Create new environment variables.\r\n" +" - Change the value of existing environment variables.\r\n" +" - Delete environment variables.\r\n" +" 2. This command sets an environment variable to a specified \r\n" +" value. You can use it to create a new environment\r\n" +" variable or to modify an existing environment variable.\r\n" +" 3. If used without any parameters, all the environment variables\r\n" +" are displayed.\r\n" +" 4. If used with the -d option, the environment variable that\r\n" +" is specified by sname is deleted.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To add an environment variable:\r\n" +" Shell> set DiagnosticPath fs0:\efi\diag;fs1:\efi\diag\r\n" +" \r\n" +" * To display environment variables:\r\n" +" Shell> set\r\n" +" \r\n" +" * To delete an environment variable:\r\n" +" Shell> set -d diagnosticpath\r\n" +" \r\n" +" * To change an environment variable:\r\n" +" fs0:\> set src efi\r\n" +" fs0:\> set src efi1.1\r\n" +" \r\n" +" * To append an environment variable:\r\n" +" Shell> set path %path%;fs0:\efi\Tools;fs0:\efi\boot;fs0:\\r\n" +" \r\n" +" * To set a volatile variable that will disappear at the next boot:\r\n" +" Shell> set -v EFI_SOURCE c:\project\EFI1.1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_OUT_OF_RESOURCES A request to set a variable in a non-volatile \r\n" +" fashion could not be completed. The resulting \r\n" +" non-volatile request has been converted into a \r\n" +" volatile request.\r\n" + +#string STR_GET_HELP_DATE #language en-US "" +".TH date 0 "Displays and sets the current date for the system."\r\n" +".SH NAME\r\n" +"Displays and sets the current date for the system.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"DATE [mm/dd/[yy]yy][-sfo]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -sfo - Displays information in Standard-Format Output.\r\n" +" mm - Specifies the month of the date to be set. (1-12)\r\n" +" dd - Specifies the day of the date to be set (1-31)\r\n" +" yy/yyyy - Specifies the year of the date to be set. If only two digits,\r\n" +" then enter 9x = 199x. Otherwise enter 20xx.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays and/or sets the current date for the system.\r\n" +" If no parameters are used, it shows the current date. If a valid month,\r\n" +" day, and year are specified, the system's date is updated.\r\n" +" The following rules apply:\r\n" +" - Except for numeric characters and /, all other characters in the\r\n" +" argument are invalid.\r\n" +" - The Shell reports an error if the number is in the wrong\r\n" +" month/date/year range.\r\n" +" - A space before or after the numeric character is not allowed. Inserting\r\n" +" a space into the number is invalid.\r\n" +" - Repeated zeros are allowed before the number. For example:\r\n" +" Shell > date 0000008/000004/000097\r\n" +" Shell > date\r\n" +" 08/04/2097\r\n" +" Shell >\r\n" +" - The year range must be greater than or equal to 1998.\r\n" +" - Two numeric characters indicate the year. Numbers below 98 are\r\n" +" regarded as 20xx, and numbers equal to or above 98 are regarded as\r\n" +" 19xx. 00 means 2000. For example:\r\n" +" Shell > date 8/4/97\r\n" +" Shell > date\r\n" +" 08/04/2097\r\n" +" Shell >\r\n" +" Shell > date 8/4/98\r\n" +" Shell > date\r\n" +" 08/04/1998\r\n" +" Shell >\r\n" +" 2. The range of valid years is from 1998-2099.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the current date in the system:\r\n" +" fs0:\> date\r\n" +" \r\n" +" * To set the date with long year format:\r\n" +" fs0:\> date 01/01/2050\r\n" +" \r\n" +" * To set the date with short year format:\r\n" +" fs0:\> date 06/18/01\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_DEVICE_ERROR There was a hardware error preventing the\r\n" +" completion of this command.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_TIME #language en-US "" +".TH time 0 "Displays or sets the time for the system."\r\n" +".SH NAME\r\n" +"Displays or sets the current time for the system.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TIME [hh:mm[:ss]] [-tz tz] [-d dl]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Sets or displays a daylight savings time value.\r\n" +" -tz - Specifies a time zone adjustment, measured in minutes offset from UTC. Valid values\r\n" +" are between -1440 and 1440 or 2047. If not present or set to 2047,\r\n" +" time is interpreted as local time.\r\n" +" hh - Specifies a new hour (0-23) (required).\r\n" +" mm - Specifies a new minute (0-59) (required).\r\n" +" ss - Specifies a new second (0-59). If not specified, zero is used.\r\n" +" dl - Specifies a daylight saving time value to set.\r\n" +" 0 : Time is not affected.\r\n" +" 1 : Time is affected, and has not been adjusted for daylight\r\n" +" savings.\r\n" +" 3 : Time is affected, and has been adjusted for daylight savings.\r\n" +" All other values are invalid. If no value follows -d, the\r\n" +" current daylight savings time is displayed.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays or sets the current time for the system.\r\n" +" If no parameters are used, it shows the current time. If valid hours, \r\n" +" minutes, and seconds are provided, the system time is\r\n" +" updated. Note the following rules:\r\n" +" - Except for numeric characters and the : character, all other\r\n" +" characters in the argument are invalid.\r\n" +" - The Shell reports an error if the number is in the wrong \r\n" +" hour/minute/second range.\r\n" +" - Spaces before or after the numeric character and spaces inserted into\r\n" +" the number are not allowed.\r\n" +" - Repeated zeros are allowed before the number. For example:\r\n" +" Shell> time 00000017:000004:0000\r\n" +" Shell> time\r\n" +" 17:04:00 (UTC+08:00)\r\n" +" 2. The seconds parameter is optional. If none is specified, it is\r\n" +" set to zero.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display current system time:\r\n" +" fs0:\> time\r\n" +" \r\n" +" * To set the system time:\r\n" +" fs0:\> time 9:51:30\r\n" +" \r\n" +" * To display the system time, including daylight savings time:\r\n" +" fs0:\> time -d\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_DEVICE_ERROR There was a hardware error preventing the\r\n" +" completion of this command\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_TIMEZONE #language en-US "" +".TH timezone 0 "Displays or sets time zone information."\r\n" +".SH NAME\r\n" +"Displays or sets time zone information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TIMEZONE [-s hh:mm | -l] [-b] [-f]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -s - Sets the time zone associated with hh:mm offset from UTC.\r\n" +" -l - Displays a list of all time zones.\r\n" +" -b - Displays one screen at a time.\r\n" +" -f - Displays full information for the specified time zone.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays and sets the current time zone for the system.\r\n" +" 2. If no parameters are used, it shows the current time zone.\r\n" +" 3. If a valid hh:mm parameter is provided, the time zone\r\n" +" information is updated.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all available time zones:\r\n" +" Shell> timezone -l\r\n" +" \r\n" +" * To set the time zone:\r\n" +" Shell> timezone -s -7:00\r\n" +" \r\n" +" * To display detailed information for the current time zone:\r\n" +" Shell> timezone -f\r\n" + +#string STR_GET_HELP_LS #language en-US "" +".TH ls 0 "Lists the contents of a directory or file information."\r\n" +".SH NAME\r\n" +"Lists the contents of a directory or file information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"LS [-r] [-a[attrib]][-sfo][file]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Displays recursively (including subdirectories).\r\n" +" -a - Displays files with a specified attribute. If \r\n" +" attribute is not specified, all files are listed. If -a is not\r\n" +" specified, all non-system and non-hidden files are listed.\r\n" +" -sfo - Displays information in Standard-Format Output.\r\n" +" attrib - Specifies a file attribute list value:\r\n" +" a - Archive\r\n" +" s - System\r\n" +" h - Hidden\r\n" +" r - Read-only\r\n" +" d - Directory\r\n" +" file - Specifies a name of a file or directory (wildcards are permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command lists directory contents or file information. If no file\r\n" +" name or directory name is specified, the current working directory\r\n" +" is assumed.\r\n" +" 2. The contents of a directory are listed if all of the following are true:\r\n" +" - If option -r is not specified.\r\n" +" - If no wildcard characters are specified in the file parameter.\r\n" +" - If the file specified represents an existing directory.\r\n" +" 3. In all other cases, the command functions as follows:\r\n" +" - All files/directories that match the specified name are displayed.\r\n" +" - The -r flag determines whether a recursive search is performed.\r\n" +" - The option flag -a[attrib] only displays those\r\n" +" files with the attributes that are specified.\r\n" +" - If more than one attribute is specified, only the files that have all\r\n" +" those attributes are listed.\r\n" +" - If -a is followed by nothing, then all files/directories are\r\n" +" displayed, regardless of their attributes.\r\n" +" - If -a itself is not specified, then all files except system and\r\n" +" hidden files are displayed.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To hide files by adding the hidden or system attribute to them:\r\n" +" fs0:\> attrib +s +h *.efi\r\n" +" \r\n" +" * To display all, except the files/directories with 'h' or 's' attribute:\r\n" +" fs0:\> ls\r\n" +" \r\n" +" * To display files with all attributes in the current directory:\r\n" +" fs0:\> ls -a\r\n" +" \r\n" +" * To display files with read-only attributes in the current directory:\r\n" +" fs0:\> ls -ar\r\n" +" \r\n" +" * To display the files with attribute of 's':\r\n" +" fs0:\> ls -as isabus.efi\r\n" +" \r\n" +" * To display all in fs0:\efi directory recursively:\r\n" +" fs0:\> ls -r -a efi\r\n" +" \r\n" +" * To display files with a specified type in the current directory: \r\n" +" recursively:\r\n" +" fs0:\> ls -r -a *.efi -b\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The requested file or directory was not found.\r\n" + +#string STR_GET_HELP_LOAD #language en-US "" +".TH load 0 "Loads a UEFI driver into memory."\r\n" +".SH NAME\r\n" +"Loads a UEFI driver into memory.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"LOAD [-nc] file [file...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -nc - Loads the driver, but does not connect the driver.\r\n" +" File - Specifies a file that contains the image of the UEFI driver (wildcards are\r\n" +" permitted).\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command loads a driver into memory. It can load multiple files at\r\n" +" one time. The file name supports wildcards.\r\n" +" 2. If the -nc flag is not specified, this command attempts to connect the\r\n" +" driver to a proper device. It might also cause previously loaded drivers\r\n" +" to be connected to their corresponding devices.\r\n" +" 3. Use the 'UNLOAD' command to unload a driver.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To load a driver:\r\n" +" fs0:\> load Isabus.efi\r\n" +" \r\n" +" * To load multiple drivers:\r\n" +" fs0:\> load Isabus.efi IsaSerial.efi\r\n" +" \r\n" +" * To load multiple drivers using file name wildcards:\r\n" +" fs0:\> load Isa*.efi\r\n" +" \r\n" +" * To load a driver without connecting it to a device:\r\n" +" fs0:\> load -nc IsaBus.efi\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The requested file was not found.\r\n" + +#string STR_GET_HELP_VOL #language en-US "" +".TH vol 0 "Displays or modifies information about a disk volume."\r\n" +".SH NAME\r\n" +"Displays or modifies information about a disk volume.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"VOL [fs] [-n ]\r\n" +"VOL [fs] [-d]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -n - Displays or modifies a new volume label.\r\n" +" -d - Displays or modifies an empty volume label.\r\n" +" fs - Specifies the name of the file system.\r\n" +" VolumeLabel - Specifies a volume label.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The following characters cannot be used in a volume label:\r\n" +" % ^ * + = [ ] | : ; \" < > ? / . \r\n" +" 2. No spaces are allowed in a volume label.\r\n" +" 3. This command displays the volume information for the specified file\r\n" +" system. If fs is not specified, the current file system is used.\r\n" +" 4. If -n is specified, the volume label for fs is set to\r\n" +" VolumeLabel.\r\n" +" 5. The maximum length for volume label is 11 characters.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the volume of the current file system:\r\n" +" fs0:\> vol\r\n" +" \r\n" +" * To change the label of fs0:\r\n" +" Shell> vol fs0 -n help_test\r\n" +" \r\n" +" * To delete the volume label of fs0:\r\n" +" fs0:\> vol fs0 -d\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The target file-system was not found.\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c new file mode 100644 index 0000000..76a0b1b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c @@ -0,0 +1,313 @@ +/** @file + Main file for vol shell level 2 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel2CommandsLib.h" +#include +#include + +/** + Print the info or change the volume info. + + @param[in] Path String with starting path. + @param[in] Delete TRUE to delete the volume label. FALSE otherwise. + @param[in] Name New name to set to the volume label. + + @retval SHELL_SUCCESS The operation was sucessful. +**/ +SHELL_STATUS +HandleVol( + IN CONST CHAR16 *Path, + IN CONST BOOLEAN Delete, + IN CONST CHAR16 *Name OPTIONAL + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + EFI_FILE_SYSTEM_INFO *SysInfo; + UINTN SysInfoSize; + SHELL_FILE_HANDLE ShellFileHandle; + EFI_FILE_PROTOCOL *EfiFpHandle; + UINTN Size1; + UINTN Size2; + + ShellStatus = SHELL_SUCCESS; + + if ( + Name != NULL && ( + StrStr(Name, L"%") != NULL || + StrStr(Name, L"^") != NULL || + StrStr(Name, L"*") != NULL || + StrStr(Name, L"+") != NULL || + StrStr(Name, L"=") != NULL || + StrStr(Name, L"[") != NULL || + StrStr(Name, L"]") != NULL || + StrStr(Name, L"|") != NULL || + StrStr(Name, L":") != NULL || + StrStr(Name, L";") != NULL || + StrStr(Name, L"\"") != NULL || + StrStr(Name, L"<") != NULL || + StrStr(Name, L">") != NULL || + StrStr(Name, L"?") != NULL || + StrStr(Name, L"/") != NULL || + StrStr(Name, L" ") != NULL ) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"vol", Name); + return (SHELL_INVALID_PARAMETER); + } + + Status = gEfiShellProtocol->OpenFileByName( + Path, + &ShellFileHandle, + Name != NULL?EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE:EFI_FILE_MODE_READ); + + if (EFI_ERROR(Status) || ShellFileHandle == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"vol", Path); + return (SHELL_ACCESS_DENIED); + } + + // + // Get the Volume Info from ShellFileHandle + // + SysInfo = NULL; + SysInfoSize = 0; + EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + } + + ASSERT(SysInfo != NULL); + + if (Delete) { + *((CHAR16 *) SysInfo->VolumeLabel) = CHAR_NULL; + SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(SysInfo->VolumeLabel); + Status = EfiFpHandle->SetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + (UINTN)SysInfo->Size, + SysInfo); + } else if (Name != NULL) { + Size1 = StrSize(Name); + Size2 = StrSize(SysInfo->VolumeLabel); + if (Size1 > Size2) { + SysInfo = ReallocatePool((UINTN)SysInfo->Size, (UINTN)SysInfo->Size + Size1 - Size2, SysInfo); + if (SysInfo == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"vol"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } + } + if (SysInfo != NULL) { + StrCpyS ( (CHAR16 *) SysInfo->VolumeLabel, + (Size1>Size2? Size1/sizeof(CHAR16) : Size2/sizeof(CHAR16)), + Name + ); + SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + Size1; + Status = EfiFpHandle->SetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + (UINTN)SysInfo->Size, + SysInfo); + } + } + + FreePool(SysInfo); + + if (Delete || Name != NULL) { + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"vol", Path); + ShellStatus = SHELL_ACCESS_DENIED; + } + } + + SysInfoSize = 0; + SysInfo = NULL; + + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + + if (Status == EFI_BUFFER_TOO_SMALL) { + SysInfo = AllocateZeroPool(SysInfoSize); + Status = EfiFpHandle->GetInfo( + EfiFpHandle, + &gEfiFileSystemInfoGuid, + &SysInfoSize, + SysInfo); + } + + gEfiShellProtocol->CloseFile(ShellFileHandle); + + ASSERT(SysInfo != NULL); + + if (SysInfo != NULL) { + // + // print VolumeInfo table + // + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_VOL_VOLINFO), + gShellLevel2HiiHandle, + SysInfo->VolumeLabel, + SysInfo->ReadOnly?L"r":L"rw", + SysInfo->VolumeSize, + SysInfo->FreeSpace, + SysInfo->BlockSize + ); + SHELL_FREE_NON_NULL(SysInfo); + } + + return (ShellStatus); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-d", TypeFlag}, + {L"-n", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'Vol' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunVol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *PathName; + CONST CHAR16 *CurDir; + BOOLEAN DeleteMode; + CHAR16 *FullPath; + CHAR16 *TempSpot; + UINTN Length; + CONST CHAR16 *NewName; + + Length = 0; + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + PathName = NULL; + CurDir = NULL; + FullPath = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // Fix local copies of the protocol pointers + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"vol", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + + if (ShellCommandLineGetCount(Package) > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"vol"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + PathName = ShellCommandLineGetRawValue(Package, 1); + if (PathName == NULL) { + CurDir = gEfiShellProtocol->GetCurDir(NULL); + if (CurDir == NULL) { + ShellStatus = SHELL_NOT_FOUND; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"vol"); + } else { + PathName = CurDir; + } + } + if (PathName != NULL) { + TempSpot = StrStr(PathName, L":"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + TempSpot = StrStr(PathName, L"\\"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + StrnCatGrow(&FullPath, &Length, PathName, 0); + StrnCatGrow(&FullPath, &Length, L":\\", 0); + DeleteMode = ShellCommandLineGetFlag(Package, L"-d"); + NewName = ShellCommandLineGetValue(Package, L"-n"); + if (DeleteMode && ShellCommandLineGetFlag(Package, L"-n")) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellLevel2HiiHandle, L"vol", L"-d", L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetFlag(Package, L"-n") && NewName == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"vol", L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (NewName != NULL && StrLen(NewName) > 11) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"vol", NewName, L"-n"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellStatus == SHELL_SUCCESS) { + ShellStatus = HandleVol( + FullPath, + DeleteMode, + NewName + ); + } + } + } + } + + SHELL_FREE_NON_NULL(FullPath); + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c new file mode 100644 index 0000000..36aa7ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c @@ -0,0 +1,286 @@ +/** @file + Main file for Alias shell level 3 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include + +/** + Print out single alias registered with the Shell. + + @param[in] Alias Points to the NULL-terminated shell alias. + If this parameter is NULL, then all + aliases will be returned in ReturnedData. + @retval SHELL_SUCCESS the printout was sucessful +**/ +SHELL_STATUS +PrintSingleShellAlias( + IN CONST CHAR16 *Alias + ) +{ + CONST CHAR16 *ConstAliasVal; + SHELL_STATUS ShellStatus; + BOOLEAN Volatile; + + ShellStatus = SHELL_SUCCESS; + ConstAliasVal = gEfiShellProtocol->GetAlias (Alias, &Volatile); + if (ConstAliasVal == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"alias", Alias); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandIsOnAliasList (Alias)) { + Volatile = FALSE; + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_ALIAS_OUTPUT), gShellLevel3HiiHandle, !Volatile ? L' ' : L'*', Alias, ConstAliasVal); + } + return ShellStatus; +} + +/** + Print out each alias registered with the Shell. + + @retval STATUS_SUCCESS the printout was sucessful + @return any return code from GetNextVariableName except EFI_NOT_FOUND +**/ +SHELL_STATUS +PrintAllShellAlias( + VOID + ) +{ + CONST CHAR16 *ConstAllAliasList; + CHAR16 *Alias; + CHAR16 *Walker; + + ConstAllAliasList = gEfiShellProtocol->GetAlias(NULL, NULL); + if (ConstAllAliasList == NULL) { + return (SHELL_SUCCESS); + } + Alias = AllocateZeroPool(StrSize(ConstAllAliasList)); + if (Alias == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + Walker = (CHAR16*)ConstAllAliasList; + + do { + CopyMem(Alias, Walker, StrSize(Walker)); + Walker = StrStr(Alias, L";"); + if (Walker != NULL) { + Walker[0] = CHAR_NULL; + Walker = Walker + 1; + } + PrintSingleShellAlias(Alias); + } while (Walker != NULL && Walker[0] != CHAR_NULL); + + FreePool(Alias); + + return (SHELL_SUCCESS); +} + +/** + Changes a shell command alias. + + This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias. + + + @param[in] Command Points to the NULL-terminated shell command or existing alias. + @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and + Command refers to an alias, that alias will be deleted. + @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If + FALSE and the alias already exists, then the existing alias is unchanged and + EFI_ACCESS_DENIED is returned. + @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the + Alias being set will be stored in a non-volatile fashion. + + @retval SHELL_SUCCESS Alias created or deleted successfully. + @retval SHELL_NOT_FOUND the Alias intended to be deleted was not found + @retval SHELL_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to + FALSE. + @retval SHELL_DEVICE_ERROR Command is null or the empty string. +**/ +SHELL_STATUS +ShellLevel3CommandsLibSetAlias( + IN CONST CHAR16 *Command, + IN CONST CHAR16 *Alias, + IN BOOLEAN Replace, + IN BOOLEAN Volatile + ) +{ + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + + ShellStatus = SHELL_SUCCESS; + Status = gEfiShellProtocol->SetAlias (Command, Alias, Replace, Volatile); + if (EFI_ERROR(Status)) { + if (Status == EFI_ACCESS_DENIED) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel3HiiHandle, L"alias"); + ShellStatus = SHELL_ACCESS_DENIED; + } else if (Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_NOT_FOUND), gShellLevel3HiiHandle, L"alias", Command); + ShellStatus = SHELL_NOT_FOUND; + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel3HiiHandle, L"alias", Status); + ShellStatus = SHELL_DEVICE_ERROR; + } + } + return ShellStatus; +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-v", TypeFlag}, + {L"-d", TypeValue}, + {NULL, TypeMax} + }; + +/** + Function for 'alias' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAlias ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Param1; + CONST CHAR16 *Param2; + CONST CHAR16 *ParamStrD; + CHAR16 *CleanParam2; + BOOLEAN DeleteFlag; + BOOLEAN VolatileFlag; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + CleanParam2 = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"alias", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + Param1 = ShellCommandLineGetRawValue(Package, 1); + Param2 = ShellCommandLineGetRawValue(Package, 2); + + DeleteFlag = ShellCommandLineGetFlag (Package, L"-d"); + VolatileFlag = ShellCommandLineGetFlag (Package, L"-v"); + + if (Param2 != NULL) { + CleanParam2 = AllocateCopyPool (StrSize(Param2), Param2); + if (CleanParam2 == NULL) { + ShellCommandLineFreeVarList (Package); + return SHELL_OUT_OF_RESOURCES; + } + + if (CleanParam2[0] == L'\"' && CleanParam2[StrLen(CleanParam2)-1] == L'\"') { + CleanParam2[StrLen(CleanParam2)-1] = L'\0'; + CopyMem (CleanParam2, CleanParam2 + 1, StrSize(CleanParam2) - sizeof(CleanParam2[0])); + } + } + + if (!DeleteFlag && !VolatileFlag) { + switch (ShellCommandLineGetCount (Package)) { + case 1: + // + // "alias" + // + ShellStatus = PrintAllShellAlias (); + break; + case 2: + // + // "alias Param1" + // + ShellStatus = PrintSingleShellAlias (Param1); + break; + case 3: + // + // "alias Param1 CleanParam2" + // + ShellStatus = ShellLevel3CommandsLibSetAlias (CleanParam2, Param1, FALSE, VolatileFlag); + break; + default: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else if (DeleteFlag) { + if (VolatileFlag || ShellCommandLineGetCount (Package) > 1) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ParamStrD = ShellCommandLineGetValue (Package, L"-d"); + if (ParamStrD == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"alias"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Delete an alias: "alias -d ParamStrD" + // + ShellStatus = ShellLevel3CommandsLibSetAlias (ParamStrD, NULL, TRUE, FALSE); + } + } + } else { + // + // Set volatile alias. + // + ASSERT (VolatileFlag); + ASSERT (!DeleteFlag); + switch (ShellCommandLineGetCount (Package)) { + case 1: + case 2: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"alias"); + ShellStatus = SHELL_INVALID_PARAMETER; + break; + case 3: + // + // "alias -v Param1 CleanParam2" + // + ShellStatus = ShellLevel3CommandsLibSetAlias (CleanParam2, Param1, FALSE, VolatileFlag); + break; + default: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias"); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + SHELL_FREE_NON_NULL (CleanParam2); + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c new file mode 100644 index 0000000..b3fbde6 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c @@ -0,0 +1,230 @@ +/** @file + Main file for attrib shell level 2 function. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-sfo", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'cls' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCls ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + UINTN Background; + UINTN Foreground; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CONST CHAR16 *BackColorStr; + CONST CHAR16 *ForeColorStr; + + // + // Initialize variables + // + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + Background = 0; + Foreground = 0; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"cls", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetFlag (Package, L"-sfo")) { + if (ShellCommandLineGetCount (Package) > 1) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"cls"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Background = (gST->ConOut->Mode->Attribute >> 4) & 0x7; + Foreground = gST->ConOut->Mode->Attribute & 0x0F; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel3HiiHandle, L"cls"); + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_CLS_OUTPUT_SFO), + gShellLevel3HiiHandle, + gST->ConOut->Mode->Attribute, + Foreground, + Background + ); + } + } else { + // + // If there are 0 value parameters, clear sceen + // + BackColorStr = ShellCommandLineGetRawValue (Package, 1); + ForeColorStr = ShellCommandLineGetRawValue (Package, 2); + + if (BackColorStr == NULL && ForeColorStr == NULL) { + // + // clear screen + // + gST->ConOut->ClearScreen (gST->ConOut); + } else if (ShellCommandLineGetCount (Package) > 3) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"cls"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (BackColorStr != NULL) { + if ((ShellStrToUintn (BackColorStr) > 7) || (StrLen (BackColorStr) > 1) || (!ShellIsDecimalDigitCharacter (*BackColorStr))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"cls", BackColorStr); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + switch (ShellStrToUintn (BackColorStr)) { + case 0: + Background = EFI_BACKGROUND_BLACK; + break; + case 1: + Background = EFI_BACKGROUND_BLUE; + break; + case 2: + Background = EFI_BACKGROUND_GREEN; + break; + case 3: + Background = EFI_BACKGROUND_CYAN; + break; + case 4: + Background = EFI_BACKGROUND_RED; + break; + case 5: + Background = EFI_BACKGROUND_MAGENTA; + break; + case 6: + Background = EFI_BACKGROUND_BROWN; + break; + case 7: + Background = EFI_BACKGROUND_LIGHTGRAY; + break; + } + + if (ForeColorStr != NULL) { + if ((ShellStrToUintn (ForeColorStr) > 15) || (StrLen (ForeColorStr) > 2) || (!ShellIsDecimalDigitCharacter (*ForeColorStr))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"cls", ForeColorStr); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + switch (ShellStrToUintn (ForeColorStr)) { + case 0: + Foreground = EFI_BLACK; + break; + case 1: + Foreground = EFI_BLUE; + break; + case 2: + Foreground = EFI_GREEN; + break; + case 3: + Foreground = EFI_CYAN; + break; + case 4: + Foreground = EFI_RED; + break; + case 5: + Foreground = EFI_MAGENTA; + break; + case 6: + Foreground = EFI_BROWN; + break; + case 7: + Foreground = EFI_LIGHTGRAY; + break; + case 8: + Foreground = EFI_DARKGRAY; + break; + case 9: + Foreground = EFI_LIGHTBLUE; + break; + case 10: + Foreground = EFI_LIGHTGREEN; + break; + case 11: + Foreground = EFI_LIGHTCYAN; + break; + case 12: + Foreground = EFI_LIGHTRED; + break; + case 13: + Foreground = EFI_LIGHTMAGENTA; + break; + case 14: + Foreground = EFI_YELLOW; + break; + case 15: + Foreground = EFI_WHITE; + break; + } + } + } else { + // + // Since foreground color is not modified, so retain + // existing foreground color without any change to it. + // + Foreground = gST->ConOut->Mode->Attribute & 0x0F; + } + + if (ShellStatus == SHELL_SUCCESS) { + Status = gST->ConOut->SetAttribute (gST->ConOut, (Foreground | Background) & 0x7F); + ASSERT_EFI_ERROR (Status); + Status = gST->ConOut->ClearScreen (gST->ConOut); + ASSERT_EFI_ERROR (Status); + } + } + } + } + } + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + + // + // return the status + // + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c new file mode 100644 index 0000000..302a1a0 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c @@ -0,0 +1,121 @@ +/** @file + Main file for Echo shell level 3 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-on", TypeFlag}, + {L"-off", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'echo' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEcho ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + CHAR16 *ProblemParam; + UINTN Size; + CHAR16 *PrintString; + + Size = 0; + ProblemParam = NULL; + PrintString = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"echo", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + if (ShellCommandLineGetFlag(Package, L"-on")) { + // + // Turn it on + // + ShellCommandSetEchoState(TRUE); + } else if (ShellCommandLineGetFlag(Package, L"-off")) { + // + // turn it off + // + ShellCommandSetEchoState(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // output its current state + // + if (ShellCommandGetEchoState()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_ON), gShellLevel3HiiHandle); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_OFF), gShellLevel3HiiHandle); + } + } else { + // + // print the line + // + for ( ParamCount = 1 + ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL + ; ParamCount++ + ) { + StrnCatGrow(&PrintString, &Size, ShellCommandLineGetRawValue(Package, ParamCount), 0); + if (ShellCommandLineGetRawValue(Package, ParamCount+1) != NULL) { + StrnCatGrow(&PrintString, &Size, L" ", 0); + } + } + ShellPrintEx(-1, -1, L"%s\r\n", PrintString); + SHELL_FREE_NON_NULL(PrintString); + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c new file mode 100644 index 0000000..57e7c1e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c @@ -0,0 +1,97 @@ +/** @file + Main file for GetMtc shell level 3 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include + +/** + Function for 'getmtc' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunGetMtc ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT64 Mtc; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"getmtc", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"getmtc"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Get the monotonic counter count + // + Status = gBS->GetNextMonotonicCount(&Mtc); + if (Status == EFI_DEVICE_ERROR) { + ShellStatus = SHELL_DEVICE_ERROR; + } else if (Status == EFI_SECURITY_VIOLATION) { + ShellStatus = SHELL_SECURITY_VIOLATION; + } else if (EFI_ERROR(Status)) { + ShellStatus = SHELL_DEVICE_ERROR; + } + + // + // print it... + // + if (ShellStatus == SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GET_MTC_OUTPUT), gShellLevel3HiiHandle, Mtc); + } + } + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c new file mode 100644 index 0000000..f9f3eac --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c @@ -0,0 +1,474 @@ +/** @file + Main file for Help shell level 3 function. + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + Copyright (c) 2014, ARM Limited. All rights reserved.
        + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include +#include + +#include + +/** + function to insert string items into a list in the correct alphabetical place + + the resultant list is a double NULL terminated list of NULL terminated strings. + + upon successful return the memory must be caller freed (unless passed back in + via a loop where it will get reallocated). + + @param[in,out] DestList double pointer to the list. may be NULL. + @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL. + @param[in] Item the item to insert. + + @retval EFI_SUCCESS the operation was successful. +**/ +EFI_STATUS +LexicalInsertIntoList( + IN OUT CHAR16 **DestList, + IN OUT UINTN *DestSize, + IN CONST CHAR16 *Item + ) +{ + CHAR16 *NewList; + INTN LexicalMatchValue; + CHAR16 *LexicalSpot; + UINTN SizeOfAddedNameInBytes; + + // + // If there are none, then just return with success + // + if (Item == NULL || *Item == CHAR_NULL || StrLen(Item)==0) { + return (EFI_SUCCESS); + } + + NewList = *DestList; + + SizeOfAddedNameInBytes = StrSize(Item); + NewList = ReallocatePool(*DestSize, (*DestSize) + SizeOfAddedNameInBytes, NewList); + (*DestSize) = (*DestSize) + SizeOfAddedNameInBytes; + + // + // Find the correct spot in the list + // + for (LexicalSpot = NewList + ; LexicalSpot != NULL && LexicalSpot < NewList + (*DestSize) + ; LexicalSpot += StrLen(LexicalSpot) + 1 + ) { + // + // Get Lexical Comparison Value between PrevCommand and Command list entry + // + LexicalMatchValue = gUnicodeCollation->StriColl ( + gUnicodeCollation, + (CHAR16 *)LexicalSpot, + (CHAR16 *)Item + ); + // + // The new item goes before this one. + // + if (LexicalMatchValue > 0 || StrLen(LexicalSpot) == 0) { + if (StrLen(LexicalSpot) != 0) { + // + // Move this and all other items out of the way + // + CopyMem( + LexicalSpot + (SizeOfAddedNameInBytes/sizeof(CHAR16)), + LexicalSpot, + (*DestSize) - SizeOfAddedNameInBytes - ((LexicalSpot - NewList) * sizeof(CHAR16)) + ); + } + + // + // Stick this one in place + // + StrCpyS(LexicalSpot, SizeOfAddedNameInBytes/sizeof(CHAR16), Item); + break; + } + } + + *DestList = NewList; + return (EFI_SUCCESS); +} + +/** + function to add each command name from the linked list to the string list. + + the resultant list is a double NULL terminated list of NULL terminated strings. + + @param[in,out] DestList double pointer to the list. may be NULL. + @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL. + @param[in] SourceList the double linked list of commands. + + @retval EFI_SUCCESS the operation was successful. +**/ +EFI_STATUS +CopyListOfCommandNames( + IN OUT CHAR16 **DestList, + IN OUT UINTN *DestSize, + IN CONST COMMAND_LIST *SourceList + ) +{ + CONST COMMAND_LIST *Node; + + for ( Node = (COMMAND_LIST*)GetFirstNode(&SourceList->Link) + ; SourceList != NULL && !IsListEmpty(&SourceList->Link) && !IsNull(&SourceList->Link, &Node->Link) + ; Node = (COMMAND_LIST*)GetNextNode(&SourceList->Link, &Node->Link) + ) { + LexicalInsertIntoList(DestList, DestSize, Node->CommandString); + } + return (EFI_SUCCESS); +} + +/** + function to add each dynamic command name to the string list. + + the resultant list is a double NULL terminated list of NULL terminated strings. + + @param[in,out] DestList double pointer to the list. may be NULL. + @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL. + + @retval EFI_SUCCESS the operation was successful. + @return an error from HandleProtocol +**/ +STATIC +EFI_STATUS +CopyListOfCommandNamesWithDynamic( + IN OUT CHAR16** DestList, + IN OUT UINTN *DestSize + ) +{ + EFI_HANDLE *CommandHandleList; + CONST EFI_HANDLE *NextCommand; + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand; + EFI_STATUS Status; + + CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid); + + // + // If there are none, then just return with success + // + if (CommandHandleList == NULL) { + return (EFI_SUCCESS); + } + + Status = EFI_SUCCESS; + + // + // Append those to the list. + // + for (NextCommand = CommandHandleList ; *NextCommand != NULL && !EFI_ERROR(Status) ; NextCommand++) { + Status = gBS->HandleProtocol( + *NextCommand, + &gEfiShellDynamicCommandProtocolGuid, + (VOID **)&DynamicCommand + ); + + if (EFI_ERROR(Status)) { + continue; + } + + Status = LexicalInsertIntoList(DestList, DestSize, DynamicCommand->CommandName); + } + + SHELL_FREE_NON_NULL(CommandHandleList); + return (Status); +} + + +/** + Attempt to print help from a dynamically added command. + + @param[in] CommandToGetHelpOn The unicode name of the command that help is + requested on. + @param[in] SectionToGetHelpOn Pointer to the section specifier(s). + @param[in] PrintCommandText Print the command followed by the help content + or just help. + + @retval EFI_SUCCESS The help was displayed + @retval EFI_NOT_FOUND The command name could not be found + @retval EFI_DEVICE_ERROR The help data format was incorrect. +**/ +EFI_STATUS +PrintDynamicCommandHelp( + IN CONST CHAR16 *CommandToGetHelpOn, + IN CONST CHAR16 *SectionToGetHelpOn, + IN BOOLEAN PrintCommandText + ) +{ + EFI_STATUS Status; + BOOLEAN Found; + EFI_HANDLE *CommandHandleList; + EFI_HANDLE *NextCommand; + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand; + + Status = EFI_NOT_FOUND; + Found = FALSE; + CommandHandleList = NULL; + + CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid); + + if (CommandHandleList == NULL) { + // + // not found or out of resources + // + return Status; + } + + for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) { + Status = gBS->HandleProtocol( + *NextCommand, + &gEfiShellDynamicCommandProtocolGuid, + (VOID **)&DynamicCommand + ); + + if (EFI_ERROR(Status)) { + continue; + } + + // + // Check execution break flag when printing multiple command help information. + // + if (ShellGetExecutionBreakFlag ()) { + break; + } + + if ((gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)CommandToGetHelpOn)) || + (gEfiShellProtocol->GetAlias (CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) { + // Print as Shell Help if in ManPage format. + Status = ShellPrintHelp (DynamicCommand->CommandName, SectionToGetHelpOn, + PrintCommandText); + if (Status == EFI_DEVICE_ERROR) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), + gShellLevel3HiiHandle, DynamicCommand->CommandName); + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), + gShellLevel3HiiHandle, DynamicCommand->CommandName); + } else { + Found = TRUE; + } + } + } + + SHELL_FREE_NON_NULL(CommandHandleList); + + return (Found ? EFI_SUCCESS : Status); + +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-usage", TypeFlag}, + {L"-section", TypeMaxValue}, + {L"-verbose", TypeFlag}, + {L"-v", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'help' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunHelp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR16 *SortedCommandList; + CONST CHAR16 *CurrentCommand; + CHAR16 *CommandToGetHelpOn; + CHAR16 *SectionToGetHelpOn; + CHAR16 *HiiString; + BOOLEAN Found; + BOOLEAN PrintCommandText; + UINTN SortedCommandListSize; + + PrintCommandText = TRUE; + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + CommandToGetHelpOn = NULL; + SectionToGetHelpOn = NULL; + SortedCommandList = NULL; + Found = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"help", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // Check for conflicting parameters. + // + if (ShellCommandLineGetFlag(Package, L"-usage") + &&ShellCommandLineGetFlag(Package, L"-section") + &&(ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v")) + ){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel3HiiHandle, L"help"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"help"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Get the command name we are getting help on + // + ASSERT(CommandToGetHelpOn == NULL); + StrnCatGrow(&CommandToGetHelpOn, NULL, ShellCommandLineGetRawValue(Package, 1), 0); + if (CommandToGetHelpOn == NULL && ShellCommandLineGetFlag(Package, L"-?")) { + // + // If we dont have a command and we got a simple -? + // we are looking for help on help command. + // + StrnCatGrow(&CommandToGetHelpOn, NULL, L"help", 0); + } + + if (CommandToGetHelpOn == NULL) { + StrnCatGrow(&CommandToGetHelpOn, NULL, L"*", 0); + ASSERT(SectionToGetHelpOn == NULL); + StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME", 0); + } else { + PrintCommandText = FALSE; + ASSERT(SectionToGetHelpOn == NULL); + // + // Get the section name for the given command name + // + if (ShellCommandLineGetFlag(Package, L"-section")) { + StrnCatGrow(&SectionToGetHelpOn, NULL, ShellCommandLineGetValue(Package, L"-section"), 0); + } else if (ShellCommandLineGetFlag(Package, L"-usage")) { + StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS", 0); + } else if (ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v")) { + } else { + // + // The output of help will display NAME, SYNOPSIS, OPTIONS, DESCRIPTION, and EXAMPLES sections. + // + StrnCatGrow (&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS,OPTIONS,DESCRIPTION,EXAMPLES", 0); + } + } + + if (gUnicodeCollation->StriColl(gUnicodeCollation, CommandToGetHelpOn, L"special") == 0) { + // + // we need info on the special characters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_SC_HEADER), gShellLevel3HiiHandle); + HiiString = HiiGetString(gShellLevel3HiiHandle, STRING_TOKEN(STR_HELP_SC_DATA), NULL); + ShellPrintEx(-1, -1, L"%s", HiiString); + FreePool(HiiString); + Found = TRUE; + } else { + SortedCommandList = NULL; + SortedCommandListSize = 0; + CopyListOfCommandNames(&SortedCommandList, &SortedCommandListSize, ShellCommandGetCommandList(TRUE)); + CopyListOfCommandNamesWithDynamic(&SortedCommandList, &SortedCommandListSize); + + for (CurrentCommand = SortedCommandList + ; CurrentCommand != NULL && CurrentCommand < SortedCommandList + SortedCommandListSize/sizeof(CHAR16) && *CurrentCommand != CHAR_NULL + ; CurrentCommand += StrLen(CurrentCommand) + 1 + ) { + // + // Checking execution break flag when print multiple command help information. + // + if (ShellGetExecutionBreakFlag ()) { + break; + } + + if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)CurrentCommand, CommandToGetHelpOn)) || + (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)CurrentCommand, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) { + // + // We have a command to look for help on. + // + Status = ShellPrintHelp(CurrentCommand, SectionToGetHelpOn, PrintCommandText); + if (EFI_ERROR(Status)) { + // + // now try to match against the dynamic command list and print help + // + Status = PrintDynamicCommandHelp (CurrentCommand, SectionToGetHelpOn, PrintCommandText); + } + if (Status == EFI_DEVICE_ERROR) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CurrentCommand); + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CurrentCommand); + } else { + Found = TRUE; + } + } + } + + // + // Search the .man file for Shell applications (Shell external commands). + // + if (!Found) { + Status = ShellPrintHelp(CommandToGetHelpOn, SectionToGetHelpOn, FALSE); + if (Status == EFI_DEVICE_ERROR) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CommandToGetHelpOn); + } else if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CommandToGetHelpOn); + } else { + Found = TRUE; + } + } + } + + if (!Found) { + ShellStatus = SHELL_NOT_FOUND; + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + } + + if (CommandToGetHelpOn != NULL && StrCmp(CommandToGetHelpOn, L"*") == 0){ + // + // If '*' then the command entered was 'Help' without qualifiers, This footer + // provides additional info on help switches + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_FOOTER), gShellLevel3HiiHandle); + } + if (CommandToGetHelpOn != NULL) { + FreePool(CommandToGetHelpOn); + } + if (SectionToGetHelpOn != NULL) { + FreePool(SectionToGetHelpOn); + } + SHELL_FREE_NON_NULL(SortedCommandList); + + return (ShellStatus); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c new file mode 100644 index 0000000..7e28dfb --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c @@ -0,0 +1,107 @@ +/** @file + Main file for Pause shell level 3 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-q", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'pause' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPause ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + SHELL_PROMPT_RESPONSE *Resp; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + Resp = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel3HiiHandle, L"pause"); + return (SHELL_UNSUPPORTED); + } + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"pause", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"pause"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (!ShellCommandLineGetFlag(Package, L"-q")) { + Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN (STR_PAUSE_PROMPT), gShellLevel3HiiHandle, (VOID**)&Resp); + } else { + Status = ShellPromptForResponse(ShellPromptResponseTypeQuitContinue, NULL, (VOID**)&Resp); + } + + if (EFI_ERROR(Status) || Resp == NULL || *Resp == ShellPromptResponseQuit) { + ShellCommandRegisterExit(TRUE, 0); + ShellStatus = SHELL_ABORTED; + } + + if (Resp != NULL) { + FreePool(Resp); + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c new file mode 100644 index 0000000..651c043 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c @@ -0,0 +1,292 @@ +/** @file + Main file for Touch shell level 3 function. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include + +/** + Do the touch operation on a single handle. + + @param[in] Handle The handle to update the date/time on. + + @retval EFI_ACCESS_DENIED The file referenced by Handle is read only. + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +TouchFileByHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *FileInfo; + + FileInfo = gEfiShellProtocol->GetFileInfo(Handle); + if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) != 0){ + return (EFI_ACCESS_DENIED); + } + Status = gRT->GetTime(&FileInfo->ModificationTime, NULL); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"gRT->GetTime", Status); + return (SHELL_DEVICE_ERROR); + } + + CopyMem(&FileInfo->LastAccessTime, &FileInfo->ModificationTime, sizeof(EFI_TIME)); + + Status = gEfiShellProtocol->SetFileInfo(Handle, FileInfo); + + FreePool(FileInfo); + + return (Status); +} + +/** + Touch a given file and potantially recurse down if it was a directory. + + @param[in] Name The name of this file. + @param[in] FS The name of the file system this file is on. + @param[in] Handle The handle of this file already opened. + @param[in] Rec TRUE to recurse if possible. + + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +DoTouchByHandle ( + IN CONST CHAR16 *Name, + IN CHAR16 *FS, + IN SHELL_FILE_HANDLE Handle, + IN BOOLEAN Rec + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Walker; + CHAR16 *TempSpot; + + Status = EFI_SUCCESS; + FileList = NULL; + Walker = NULL; + + if (FS == NULL) { + FS = StrnCatGrow(&FS, NULL, Name, 0); + if (FS != NULL) { + TempSpot = StrStr(FS, L"\\"); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + } + } + if (FS == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // do it + // + Status = TouchFileByHandle(Handle); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Name); + return (Status); + } + + // + // if it's a directory recurse... + // + if (FileHandleIsDirectory(Handle) == EFI_SUCCESS && Rec) { + // + // get each file under this directory + // + if (EFI_ERROR(gEfiShellProtocol->FindFilesInDir(Handle, &FileList))) { + Status = EFI_INVALID_PARAMETER; + } + + // + // recurse on each + // + for (Walker = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; FileList != NULL && !IsNull(&FileList->Link, &Walker->Link) && !EFI_ERROR(Status) + ; Walker = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Walker->Link) + ){ + if ( (StrCmp(Walker->FileName, L".") != 0) + && (StrCmp(Walker->FileName, L"..") != 0) + ){ + // + // Open the file since we need that handle. + // + Status = gEfiShellProtocol->OpenFileByName (Walker->FullName, &Walker->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Walker->FullName); + Status = EFI_ACCESS_DENIED; + } else { + Status = DoTouchByHandle(Walker->FullName, FS, Walker->Handle, TRUE); + gEfiShellProtocol->CloseFile(Walker->Handle); + Walker->Handle = NULL; + } + } + } + + // + // free stuff + // + if (FileList != NULL && EFI_ERROR(gEfiShellProtocol->FreeFileList(&FileList))) { + Status = EFI_INVALID_PARAMETER; + } + } + + return (Status); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-r", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'touch' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTouch ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Param; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Node; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"touch", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"touch"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // get a list with each file specified by parameters + // if parameter is a directory then add all the files below it to the list + // + for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ; Param != NULL + ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ){ + Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, &FileList); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"touch", (CHAR16*)Param); + ShellStatus = SHELL_NOT_FOUND; + break; + } + // + // make sure we completed the param parsing sucessfully... + // Also make sure that any previous action was sucessful + // + if (ShellStatus == SHELL_SUCCESS) { + // + // check that we have at least 1 file + // + if (FileList == NULL || IsListEmpty(&FileList->Link)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"touch", Param); + continue; + } else { + // + // loop through the list and make sure we are not aborting... + // + for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag() + ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link) + ){ + // + // make sure the file opened ok + // + if (EFI_ERROR(Node->Status)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Node->FileName); + ShellStatus = SHELL_NOT_FOUND; + continue; + } + + Status = DoTouchByHandle(Node->FullName, NULL, Node->Handle, ShellCommandLineGetFlag(Package, L"-r")); + if (EFI_ERROR(Status) && Status != EFI_ACCESS_DENIED) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Node->FileName); + ShellStatus = SHELL_NOT_FOUND; + } + } + } + } + // + // Free the fileList + // + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + Status = ShellCloseFileMetaArg(&FileList); + ASSERT_EFI_ERROR(Status); + } + FileList = NULL; + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c new file mode 100644 index 0000000..4fcfbf9 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c @@ -0,0 +1,327 @@ +/** @file + Main file for Type shell level 3 function. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include + +/** + Display a single file to StdOut. + + If both Ascii and UCS2 are FALSE attempt to discover the file type. + + @param[in] Handle The handle to the file to display. + @param[in] Ascii TRUE to force ASCII, FALSE othewise. + @param[in] UCS2 TRUE to force UCS2, FALSE othewise. + + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +TypeFileByHandle ( + IN SHELL_FILE_HANDLE Handle, + IN BOOLEAN Ascii, + IN BOOLEAN UCS2 + ) +{ + UINTN ReadSize; + VOID *Buffer; + VOID *AllocatedBuffer; + EFI_STATUS Status; + UINTN LoopVar; + UINTN LoopSize; + CHAR16 AsciiChar; + CHAR16 Ucs2Char; + + ReadSize = PcdGet32(PcdShellFileOperationSize); + AllocatedBuffer = AllocateZeroPool(ReadSize); + if (AllocatedBuffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + Status = ShellSetFilePosition(Handle, 0); + ASSERT_EFI_ERROR(Status); + + while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))) { + Buffer = AllocatedBuffer; + ZeroMem(Buffer, ReadSize); + Status = ShellReadFile(Handle, &ReadSize, Buffer); + if (EFI_ERROR(Status)){ + break; + } + + if (!(Ascii|UCS2)) { + if (*(UINT16*)Buffer == gUnicodeFileTag) { + UCS2 = TRUE; + } else { + Ascii = TRUE; + } + } + + if (Ascii) { + LoopSize = ReadSize; + for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) { + // + // The valid range of ASCII characters is 0x20-0x7E. + // Display "." when there is an invalid character. + // + AsciiChar = CHAR_NULL; + AsciiChar = ((CHAR8*)Buffer)[LoopVar]; + if (AsciiChar == '\r' || AsciiChar == '\n') { + // + // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD) + // characters to be displayed as is. + // + if (AsciiChar == '\n' && ((CHAR8*)Buffer)[LoopVar-1] != '\r') { + // + // In case Line Feed (0xA) is encountered & Carriage Return (0xD) + // was not the previous character, print CR and LF. This is because + // Shell 2.0 requires carriage return with line feed for displaying + // each new line from left. + // + ShellPrintEx (-1, -1, L"\r\n"); + continue; + } + } else { + // + // For all other characters which are not printable, display '.' + // + if (AsciiChar < 0x20 || AsciiChar >= 0x7F) { + AsciiChar = '.'; + } + } + ShellPrintEx (-1, -1, L"%c", AsciiChar); + } + } else { + if (*(UINT16*)Buffer == gUnicodeFileTag) { + // + // For unicode files, skip displaying the byte order marker. + // + Buffer = ((UINT16*)Buffer) + 1; + LoopSize = (ReadSize / (sizeof (CHAR16))) - 1; + } else { + LoopSize = ReadSize / (sizeof (CHAR16)); + } + + for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) { + // + // An invalid range of characters is 0x0-0x1F. + // Display "." when there is an invalid character. + // + Ucs2Char = CHAR_NULL; + Ucs2Char = ((CHAR16*)Buffer)[LoopVar]; + if (Ucs2Char == '\r' || Ucs2Char == '\n') { + // + // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD) + // characters to be displayed as is. + // + if (Ucs2Char == '\n' && ((CHAR16*)Buffer)[LoopVar-1] != '\r') { + // + // In case Line Feed (0xA) is encountered & Carriage Return (0xD) + // was not the previous character, print CR and LF. This is because + // Shell 2.0 requires carriage return with line feed for displaying + // each new line from left. + // + ShellPrintEx (-1, -1, L"\r\n"); + continue; + } + } + else if (Ucs2Char < 0x20) { + // + // For all other characters which are not printable, display '.' + // + Ucs2Char = L'.'; + } + ShellPrintEx (-1, -1, L"%c", Ucs2Char); + } + } + + if (ShellGetExecutionBreakFlag()) { + break; + } + } + FreePool (AllocatedBuffer); + ShellPrintEx (-1, -1, L"\r\n"); + return (Status); +} + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-a", TypeFlag}, + {L"-u", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'type' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunType ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + CONST CHAR16 *Param; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + EFI_SHELL_FILE_INFO *FileList; + EFI_SHELL_FILE_INFO *Node; + BOOLEAN AsciiMode; + BOOLEAN UnicodeMode; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + ParamCount = 0; + FileList = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"type", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + AsciiMode = ShellCommandLineGetFlag(Package, L"-a"); + UnicodeMode = ShellCommandLineGetFlag(Package, L"-u"); + + if (AsciiMode && UnicodeMode) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"type", L"-a & -u"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + // + // we insufficient parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"type"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // get a list with each file specified by parameters + // if parameter is a directory then add all the files below it to the list + // + for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ; Param != NULL + ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount) + ){ + Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", (CHAR16*)Param); + ShellStatus = SHELL_NOT_FOUND; + break; + } + // + // make sure we completed the param parsing sucessfully... + // Also make sure that any previous action was sucessful + // + if (ShellStatus == SHELL_SUCCESS) { + // + // check that we have at least 1 file + // + if (FileList == NULL || IsListEmpty(&FileList->Link)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"type", Param); + continue; + } else { + // + // loop through the list and make sure we are not aborting... + // + for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag() + ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link) + ){ + + if (ShellGetExecutionBreakFlag()) { + break; + } + + // + // make sure the file opened ok + // + if (EFI_ERROR(Node->Status)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", Node->FileName); + ShellStatus = SHELL_NOT_FOUND; + continue; + } + + // + // make sure its not a directory + // + if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_IS_DIR), gShellLevel3HiiHandle, L"type", Node->FileName); + ShellStatus = SHELL_NOT_FOUND; + continue; + } + + // + // do it + // + Status = TypeFileByHandle (Node->Handle, AsciiMode, UnicodeMode); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, L"type", Node->FileName); + ShellStatus = SHELL_INVALID_PARAMETER; + } + ASSERT(ShellStatus == SHELL_SUCCESS); + } + } + } + // + // Free the fileList + // + if (FileList != NULL && !IsListEmpty(&FileList->Link)) { + Status = ShellCloseFileMetaArg(&FileList); + } + ASSERT_EFI_ERROR(Status); + FileList = NULL; + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + if (ShellGetExecutionBreakFlag()) { + return (SHELL_ABORTED); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c new file mode 100644 index 0000000..9528fdc --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c @@ -0,0 +1,101 @@ +/** @file + Main file for NULL named library for level 3 shell command functions. + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "UefiShellLevel3CommandsLib.h" + +CONST CHAR16 gShellLevel3FileName[] = L"ShellCommands"; +EFI_HANDLE gShellLevel3HiiHandle = NULL; + +/** + return the filename to get help from is not using HII. + + @retval The filename. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameLevel3 ( + VOID + ) +{ + return (gShellLevel3FileName); +} + +/** + Constructor for the Shell Level 3 Commands library. + + Install the handlers for level 3 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellLevel3CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + gShellLevel3HiiHandle = NULL; + // + // if shell level is less than 3 do nothing + // + if (PcdGet8(PcdShellSupportLevel) < 3) { + return (EFI_SUCCESS); + } + + gShellLevel3HiiHandle = HiiAddPackages (&gShellLevel3HiiGuid, gImageHandle, UefiShellLevel3CommandsLibStrings, NULL); + if (gShellLevel3HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + // + // install our shell command handlers that are always installed + // + // Note: that Time, Timezone, and Date are part of level 2 library + // + ShellCommandRegisterCommandName(L"type", ShellCommandRunType , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_TYPE)); + ShellCommandRegisterCommandName(L"touch", ShellCommandRunTouch , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_TOUCH)); + ShellCommandRegisterCommandName(L"ver", ShellCommandRunVer , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_VER)); + ShellCommandRegisterCommandName(L"alias", ShellCommandRunAlias , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_ALIAS)); + ShellCommandRegisterCommandName(L"cls", ShellCommandRunCls , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_CLS)); + ShellCommandRegisterCommandName(L"echo", ShellCommandRunEcho , ShellCommandGetManFileNameLevel3, 3, L"", FALSE, gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_ECHO)); + ShellCommandRegisterCommandName(L"pause", ShellCommandRunPause , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_PAUSE)); + ShellCommandRegisterCommandName(L"getmtc", ShellCommandRunGetMtc , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_GETMTC)); + ShellCommandRegisterCommandName(L"help", ShellCommandRunHelp , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_HELP)); + + ShellCommandRegisterAlias(L"type", L"cat"); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +ShellLevel3CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellLevel3HiiHandle != NULL) { + HiiRemovePackages(gShellLevel3HiiHandle); + } + return (EFI_SUCCESS); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h new file mode 100644 index 0000000..0e42491 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h @@ -0,0 +1,161 @@ +/** @file + header file for NULL named library for level 3 shell command functions. + + Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_LEVEL3_COMMANDS_LIB_H_ +#define _UEFI_SHELL_LEVEL3_COMMANDS_LIB_H_ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE gShellLevel3HiiHandle; + +/** + Function for 'type' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunType ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'touch' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunTouch ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'ver' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunVer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'alias' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunAlias ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'cls' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunCls ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'echo' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEcho ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'pause' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPause ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'getmtc' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunGetMtc ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'help' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunHelp ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf new file mode 100644 index 0000000..a1cf331 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf @@ -0,0 +1,74 @@ +## @file +# Provides shell level 3 functions +# Note that the interactive versions of the time, date, and timezone functions are handled in the level 2 library. +# +# (C) Copyright 2013 Hewlett-Packard Development Company, L.P.
        +# Copyright (c) 2009-2015, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellLevel3CommandsLib + FILE_GUID = 71374B42-85D7-4753-AD17-AA84C3A0EB93 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellLevel3CommandsLibConstructor + DESTRUCTOR = ShellLevel3CommandsLibDestructor + +[Sources.common] +# note that time, timezone, and date are part of the level 2 library + Type.c + Touch.c + Ver.c + UefiShellLevel3CommandsLib.uni + UefiShellLevel3CommandsLib.c + UefiShellLevel3CommandsLib.h + Cls.c + Alias.c + Echo.c + Pause.c + GetMtc.c + Help.c + + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + FileHandleLib + HandleParsingLib + +[Guids] + gEfiFileInfoGuid ## UNDEFINED + gShellLevel3HiiGuid ## SOMETIMES_CONSUMES ## HII + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## SOMETIMES_CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellSupplier ## SOMETIMES_CONSUMES + +[Protocols] + gEfiShellDynamicCommandProtocolGuid ## SOMETIMES_CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni new file mode 100644 index 0000000..1ea5522 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni @@ -0,0 +1,545 @@ +// /** +// +// (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellLevel3CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 level 3 commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n" +#string STR_GEN_ERR_NOT_FOUND #language en-US "%H%s%N: '%H%s%N' does not exist.\r\n" +#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n" +#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict\r\n" +#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_FILE_AD #language en-US "%H%s%N: Access file error - '%H%s%N'\r\n" +#string STR_GEN_CRLF #language en-US "\r\n" +#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified\r\n" +#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found\r\n" +#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n" +#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_GEN_IS_DIR #language en-US "%H%s%N: '%H%s%N' is a directory\r\n" +#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n" +#string STR_NO_SCRIPT #language en-US "The command '%H%s%N' is not allowed outside of a script\r\n" + +#string STR_TYP_ERROR #language en-US "%H%s%N: Operation was not successful on '%H%s%N'\r\n" + +#string STR_TOUCH_ERROR #language en-US "%H%s%N: Operation was not successful on '%H%s%N'\r\n" + +#string STR_VER_OUTPUT_SHELL #language en-US "UEFI %s Shell v%d.%d\r\n" +#string STR_VER_OUTPUT_SIMPLE #language en-US "%d.%d\r\n" +#string STR_VER_OUTPUT_UEFI #language en-US "UEFI v%d.%02d (%s, 0x%08x)\r\n" +#string STR_VER_OUTPUT_SUPPLIER #language en-US "%s\r\n" + +#string STR_ECHO_ON #language en-US "Echo is on.\r\n" +#string STR_ECHO_OFF #language en-US "Echo is off.\r\n" + +#string STR_PAUSE_PROMPT #language en-US "Enter 'q' to quit, any other key to continue:\r\n" + +#string STR_HELP_NF #language en-US "No help could be found for command '%B%s%N'.\r\n" +#string STR_HELP_INV #language en-US "The help data for command '%B%s%N' was incorrect format.\r\n" +#string STR_HELP_SC_HEADER #language en-US "Character Description\r\n" + "--------- ---------------------------------------------- \r\n" +#string STR_HELP_SC_DATA #language en-US " Ends a command line.\r\n" + " Ends an argument, if it is not in a quotation.\r\n" + "# Starts a comment.\r\n" + "> Used for output redirection.\r\n" + "< Used for input redirection.\r\n" + "| Used for pipe command support.\r\n" + "% Used to delimit a variable or an argument.\r\n" + "\" Used to delimit a quotation.\r\n" + "^ Prevents the next character from being\r\n" + " interpreted as having special meaning.\r\n" + " Can be used inside quoted strings.\r\n" + "*, ?, [, ] Wildcards to specify multiple similar file names.\r\n" +#string STR_HELP_COMMAND #language en-US "%H%-14s%N- %s\r\n" +#string STR_HELP_FOOTER #language en-US "%N\r\nHelp usage:help [%Hcmd%N|%Hpattern%N|%Hspecial%N] [%H-usage%N] [%H-verbose%N] [%H-section name%N][%H-b%N]\r\n" + +#string STR_HELP_PAGE_COMMAND #language en-US "%N%s\r\n" + +#string STR_ALIAS_OUTPUT #language en-US "%1c %10s:%s\r\n" + +#string STR_GET_MTC_OUTPUT #language en-US "%016Lx\r\n" +#string STR_CLS_OUTPUT_SFO #language en-US "ConOutAttribInfo,"%d","%d","%d"\r\n" + +#string STR_GET_HELP_HELP #language en-US "" +".TH help 0 "Displays help information from the UEFI Shell."\r\n" +".SH NAME\r\n" +"Displays the UEFI Shell command list or verbose command help.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"HELP [cmd | pattern | special] [-usage] [-verbose] [-section sectionname][-b]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -usage - Displays the usage information for the command. The same as\r\n" +" specifying "-section NAME" and "-section SYNOPSIS" \r\n" +" -section - Displays the specified section of the help information.\r\n" +" -b - Displays one page on screen and allows user to continue\r\n" +" to next page\r\n" +" cmd - Specifies a command to display help about.\r\n" +" pattern - Specifies a pattern which describes the commands to be displayed.\r\n" +" special - Displays a list of the special characters used in the shell\r\n" +" command line.\r\n" +" sectionname - Specifies a section name. Supported options are:\r\n" +" - NAME\r\n" +" - SYNOPSIS\r\n" +" - OPTIONS\r\n" +" - DESCRIPTION\r\n" +" - EXAMPLES\r\n" +" - RETURNVALUES\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The HELP command displays information about one or more shell commands.\r\n" +" 2. If no other options are specified, each command will be displayed along\r\n" +" with a brief description of its function.\r\n" +" 3. If -verbose is specified, then display all help information for the\r\n" +" specified commands.\r\n" +" 4. If -section is specified, only the help section specified will be\r\n" +" displayed.\r\n" +" 5. If -usage is specified, then the command, a brief description\r\n" +" and the usage will be displayed.\r\n" +" 6. The help text is gathered from UCS-2 text files found in the directory\r\n" +" where the shell or shell command executable was located. The files have\r\n" +" the name commandname.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the list of commands in the UEFI Shell and break after one\r\n" +" screen:\r\n" +" Shell> help -b\r\n" +" \r\n" +" * To display help information of a Shell command - ls:\r\n" +" Shell> help ls\r\n" +" Shell> -? ls\r\n" +" Shell> ls -?\r\n" +" \r\n" +" * To display the list of commands that start with character 'p':\r\n" +" Shell> help p*\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" 0 The help was displayed\r\n" +" 1 No command help was displayed\r\n" + +#string STR_GET_HELP_ALIAS #language en-US "" +".TH alias 0 "Handles aliases in the Shell."\r\n" +".SH NAME\r\n" +"Displays, creates, or deletes UEFI Shell aliases.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"ALIAS [-d|-v] [alias-name] [command-name]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -d - Deletes an alias. Command-name must not be specified.\r\n" +" -v - Makes the alias volatile.\r\n" +" alias-name - Specifies an alias name.\r\n" +" command-name - Specifies an original command's name or path.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays, creates, or deletes aliases in the UEFI Shell\r\n" +" environment.\r\n" +" 2. An alias provides a new name for an existing UEFI Shell\r\n" +" command or UEFI application. Once the alias is created, it can be used\r\n" +" to run the command or launch the UEFI application.\r\n" +" 3. There are some aliases that are predefined in the UEFI Shell environment.\r\n" +" These aliases provide the MS-DOS and UNIX equivalent names for the file\r\n" +" manipulation commands.\r\n" +" 4. Aliases will be retained even after exiting the shell unless the -v option\r\n" +" is specified. If -v is specified then the alias will not be valid after\r\n" +" leaving the shell.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display all aliases in the UEFI Shell environment:\r\n" +" Shell> alias\r\n" +" \r\n" +" * To create an alias in the UEFI Shell environment:\r\n" +" Shell> alias shutdown "reset -s" \r\n" +" \r\n" +" * To delete an alias in the UEFI Shell environment:\r\n" +" Shell> alias -d shutdown\r\n" +" \r\n" +" * To add a volatile alias in the current UEFI environment, which has a star *\r\n" +" at the line head. This volatile alias will disappear at next boot.\r\n" +" Shell> alias -v fs0 floppy\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_OUT_OF_RESOURCES A request to set a variable in a non-volatile\r\n" +" fashion could not be completed. The resulting\r\n" +" non-volatile request has been converted into\r\n" +" a volatile request.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" + +#string STR_GET_HELP_CLS #language en-US "" +".TH cls 0 "clear screen"\r\n" +".SH NAME\r\n" +"Clears the console output and optionally changes the background and foreground color.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"CLS [background] [foreground] | [-sfo]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" background - Sets a new background color:\r\n" +" 0 - Black\r\n" +" 1 - Blue\r\n" +" 2 - Green\r\n" +" 3 - Cyan\r\n" +" 4 - Red\r\n" +" 5 - Magenta\r\n" +" 6 - Yellow\r\n" +" 7 - Light gray\r\n" +" foreground - Sets a new foreground color:\r\n" +" 0 - Black\r\n" +" 1 - Blue\r\n" +" 2 - Green\r\n" +" 3 - Cyan\r\n" +" 4 - Red\r\n" +" 5 - Magenta\r\n" +" 6 - Yellow\r\n" +" 7 - Light gray\r\n" +" 8 - Dark gray\r\n" +" 9 - Light blue\r\n" +" 10 - Light green\r\n" +" 11 - Light cyan\r\n" +" 12 - Light red\r\n" +" 13 - Light magenta\r\n" +" 14 - Yellow\r\n" +" 15 - White\r\n" +" -sfo - Displays current console color settings in Standard Format\r\n" +" Output.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command clears the standard output device with an optional\r\n" +" background and foreground color attribute.\r\n" +" 2. If background color is not specified, or if background and foreground\r\n" +" colors are not specified, then the colors do not change.\r\n" +" 3. When -sfo flag is used, console output is not cleared and instead it\r\n" +" displays current console foreground and background attribute settings.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To clear standard output without changing the background or foreground\r\n" +" color:\r\n" +" fs0:\> cls\r\n" +" \r\n" +" * To clear standard output and change the background color to cyan:\r\n" +" fs0:\> cls 3\r\n" +" \r\n" +" * To clear standard output and change the background to black and foreground\r\n" +" to white:\r\n" +" fs0:\> cls 0 15\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The requested file was not found.\r\n" + +#string STR_GET_HELP_ECHO #language en-US "" +".TH echo 0 "display text or control text output"\r\n" +".SH NAME\r\n" +"Controls script file command echoing or displays a message.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"ECHO [-on|-off]\r\n" +"ECHO [message]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -on - Enables display when reading commands from script files.\r\n" +" -off - Disables display when reading commands from script files.\r\n" +" message - Specifies a message to display.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The first form of this command controls whether script commands are\r\n" +" displayed as they are read from the script file. If no argument is given,\r\n" +" the current "on" or "off" status is displayed.\r\n" +" 2. The second form prints the given message to the display.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display a message string of 'Hello World':\r\n" +" fs0:\> echo Hello World\r\n" +" \r\n" +" * To turn command echoing on:\r\n" +" fs0:\> echo -on\r\n" +" \r\n" +" * To execute HelloWorld.nsh, and display when reading lines from the script\r\n" +" file:\r\n" +" fs0:\> HelloWorld.nsh\r\n" +" +HelloWorld.nsh> echo Hello World\r\n" +" \r\n" +" * To turn command echoing off:\r\n" +" fs0:\> echo -off\r\n" +" \r\n" +" * To display the current echo setting:\r\n" +" fs0:\> echo\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" + +#string STR_GET_HELP_GETMTC #language en-US "" +".TH getmtc 0 "gets the MTC count"\r\n" +".SH NAME\r\n" +"Gets the MTC from BootServices and displays it.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"GETMTC\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays the current monotonic counter value. The lower 32\r\n" +" bits increment every time this command is executed. Every time the system\r\n" +" is reset, the upper 32 bits will be incremented, and the lower 32 bits\r\n" +" will be reset to 0.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display the current monotonic counter value:\r\n" +" fs0:\> getmtc\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_DEVICE_ERROR The underlying device was not working correctly.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" + +#string STR_GET_HELP_PAUSE #language en-US "" +".TH pause 0 "pauses scripts"\r\n" +".SH NAME\r\n" +"Pauses a script and waits for an operator to press a key.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"PAUSE [-q]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -q - Does not display a test output prompt.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. The PAUSE command prints a message to the display, then suspends script\r\n" +" file execution, and waits for keyboard input. Pressing any key resumes\r\n" +" execution, except for q or Q. If either q or Q is pressed, script\r\n" +" processing terminates; otherwise, execution continues with the next line\r\n" +" after the pause command.\r\n" +" 2. The PAUSE command is available only in scripts. Switch -q can hide the\r\n" +" message and it's optional.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * Following script is a sample of 'pause' command:\r\n" +" fs0:\> type pause.nsh\r\n" +" #\r\n" +" # Example script for 'pause' command\r\n" +" #\r\n" +" echo pause.nsh begin..\r\n" +" date\r\n" +" time\r\n" +" pause\r\n" +" echo pause.nsh done.\r\n" +" \r\n" +" * To execute the script with echo on:\r\n" +" fs0:\> pause.nsh\r\n" +" +pause.nsh> echo pause.nsh begin..\r\n" +" pause.nsh begin..\r\n" +" +pause.nsh> date\r\n" +" 06/19/2001\r\n" +" +pause.nsh> time\r\n" +" 00:51:45\r\n" +" +pause.nsh> pause\r\n" +" Enter 'q' to quit, or any other key to continue:\r\n" +" +pause.nsh> echo pause.nsh done.\r\n" +" pause.nsh done.\r\n" +" \r\n" +" * To execute the script with echo off:\r\n" +" fs0:\> echo -off\r\n" +" fs0:\> pause.nsh\r\n" +" pause.nsh begin..\r\n" +" 06/19/2001\r\n" +" 00:52:50\r\n" +" Enter 'q' to quit, or any other key to continue: q\r\n" +" fs0:\>\r\n" + +#string STR_GET_HELP_TOUCH #language en-US "" +".TH touch 0 "Touch a file to update a directory"\r\n" +".SH NAME\r\n" +"Updates the filename timestamp with the current system date and time.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TOUCH [-r] file [file ...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Sets the update as recurse into subdirectories.\r\n" +" file - Specifies the name or pattern of the file or directory. There can be multiple \r\n" +" files on the command-line.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command updates to the current time and date the time and date on\r\n" +" the file that is specified by the file parameter.\r\n" +" 2. If multiple files are specified on the command line, it will continue\r\n" +" processing. It will touch the files one by one and errors will be\r\n" +" ignored.\r\n" +" 3. TOUCH cannot change the time and date of read-only files and directories.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To update the timestamp of a specific file:\r\n" +" fs0:\> touch for.nsh\r\n" +" \r\n" +" * To touch a directory recursively:\r\n" +" fs0:\> touch -r efi1.1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_NOT_FOUND The target file or set of files were not found.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_WRITE_PROTECTED The media was write-protected or the file had a\r\n" +" read-only attribute associated with it.\r\n" + +#string STR_GET_HELP_TYPE #language en-US "" +".TH type 0 "print a file to StdOut"\r\n" +".SH NAME\r\n" +"Sends the contents of a file to the standard output device.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"TYPE [-a|-u] file [file...]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -a - Displays the file as if it is encoded as 8-bit ASCII\r\n" +" -u - Displays the file as if it were encoded as UCS-2 Unicode.\r\n" +" file - Specifies the name of the file to display.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command sends the contents of a file to the standard output device.\r\n" +" If no options are used, then the command attempts to automatically detect\r\n" +" the file type. If it fails, then UCS-2 is presumed.\r\n" +" 2. If the -a option is specified, the file is sent to the standard output\r\n" +" device as a stream of ASCII characters.\r\n" +" 3. If the -u option is specified, the file is sent to the standard output\r\n" +" device as a stream of Unicode (UCS-2) characters.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display a file in UCS-2 format:\r\n" +" fs0:\> type -u pause.nsh\r\n" +" \r\n" +" * To display a file in ASCII format:\r\n" +" fs0:\> type -a pause.nsh\r\n" +" \r\n" +" * To display multiple files:\r\n" +" fs0:\> type test.*\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" +" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n" +" violation.\r\n" +" SHELL_NOT_FOUND The target file or set of files were not found.\r\n" + +#string STR_GET_HELP_VER #language en-US "" +".TH ver 0 "prints out version info"\r\n" +".SH NAME\r\n" +"Displays UEFI Firmware version information.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"VER [-s|-terse]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -s - Displays only the UEFI Shell version.\r\n" +" -terse - Displays only the first part of the data.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command displays the version information for this UEFI Firmware, or\r\n" +" the version information for the UEFI Shell itself. The information is\r\n" +" retrieved through the UEFI System Table or the Shell image.\r\n" +" \r\n" +" 2. Standard format for ver output as shown below with a sample:\r\n" +" UEFI Shell v\r\n" +" shell-supplier-specific-data\r\n" +" UEFI v (, 0x )\r\n" +" #\r\n" +" # Sample \r\n" +" #\r\n" +" UEFI Basic Shell v2.0\r\n" +" Copyright 2008 by Intel(R) Corporation.\r\n" +" UEFI v2.31 (Intel(R) Corporation., 0x00010100)\r\n" +" \r\n" +" 3. UEFI version tag information:\r\n" +" \r\n" +" 0 = Minimal\r\n" +" 1 = Scripting\r\n" +" 2 = Basic\r\n" +" 3 = Interactive\r\n" +" \r\n" +" Comes from the Shell specification upon which the Shell\r\n" +" implementation is based.\r\n" +" \r\n" +" Build, copyright, etc.\r\n" +" \r\n" +" Comes from the UEFI specification upon which the firmware\r\n" +" implementation is based\r\n" +" \r\n" +" Indicates Vendor Name\r\n" +" \r\n" +" Indicates Vendor's firmware version\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To display UEFI Firmware version information:\r\n" +" fs0:\> ver\r\n" +" \r\n" +" * To display UEFI Shell version information only:\r\n" +" Shell> ver -s\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c new file mode 100644 index 0000000..da43d7d --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c @@ -0,0 +1,153 @@ +/** @file + Main file for Ver shell level 3 function. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel3CommandsLib.h" + +#include + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-s", TypeFlag}, + {L"-terse", TypeFlag}, + {L"-t", TypeFlag}, + {L"-_pa", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'ver' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunVer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + UINT8 Level; + + Level = PcdGet8(PcdShellSupportLevel); + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"ver", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + // + // check for "-?" + // + if (ShellCommandLineGetFlag(Package, L"-?")) { + ASSERT(FALSE); + } + if (ShellCommandLineGetRawValue(Package, 1) != NULL) { + // + // we have too many parameters + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"ver"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ShellCommandLineGetFlag(Package, L"-s")) { + if (ShellCommandLineGetFlag(Package, L"-terse") || ShellCommandLineGetFlag(Package, L"-t")){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellLevel3HiiHandle, L"ver", L"-t or -terse", L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_SIMPLE), + gShellLevel3HiiHandle, + gEfiShellProtocol->MajorVersion, + gEfiShellProtocol->MinorVersion + ); + } + } else { + ShellPrintHiiEx ( + 0, + gST->ConOut->Mode->CursorRow, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_SHELL), + gShellLevel3HiiHandle, + SupportLevel[Level], + gEfiShellProtocol->MajorVersion, + gEfiShellProtocol->MinorVersion + ); + if (!ShellCommandLineGetFlag(Package, L"-terse") && !ShellCommandLineGetFlag(Package, L"-t")){ + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_SUPPLIER), + gShellLevel3HiiHandle, + (CHAR16 *) PcdGetPtr (PcdShellSupplier) + ); + + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_VER_OUTPUT_UEFI), + gShellLevel3HiiHandle, + (gST->Hdr.Revision&0xffff0000)>>16, + (gST->Hdr.Revision&0x0000ffff), + gST->FirmwareVendor, + gST->FirmwareRevision + ); + } + } + // + // implementation specific support for displaying processor architecture + // + if (ShellCommandLineGetFlag(Package, L"-_pa")) { + ShellPrintEx(-1, -1, L"%d\r\n", sizeof(UINTN)==sizeof(UINT64)?64:32); + } + } + + // + // free the command line package + // + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.c new file mode 100644 index 0000000..8cff0ed --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.c @@ -0,0 +1,4375 @@ +/** @file + Provides interface to shell functionality for shell commands and applications. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + Copyright 2016-2018 Dell Technologies.
        + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLib.h" +#include +#include + +// +// globals... +// +SHELL_PARAM_ITEM EmptyParamList[] = { + {NULL, TypeMax} + }; +SHELL_PARAM_ITEM SfoParamList[] = { + {L"-sfo", TypeFlag}, + {NULL, TypeMax} + }; +EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2; +EFI_SHELL_INTERFACE *mEfiShellInterface; +EFI_SHELL_PROTOCOL *gEfiShellProtocol; +EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol; +EFI_HANDLE mEfiShellEnvironment2Handle; +FILE_HANDLE_FUNCTION_MAP FileFunctionMap; +EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollationProtocol; + +/** + Return a clean, fully-qualified version of an input path. If the return value + is non-NULL the caller must free the memory when it is no longer needed. + + If asserts are disabled, and if the input parameter is NULL, NULL is returned. + + If there is not enough memory available to create the fully-qualified path or + a copy of the input path, NULL is returned. + + If there is no working directory, a clean copy of Path is returned. + + Otherwise, the current file system or working directory (as appropriate) is + prepended to Path and the resulting path is cleaned and returned. + + NOTE: If the input path is an empty string, then the current working directory + (if it exists) is returned. In other words, an empty input path is treated + exactly the same as ".". + + @param[in] Path A pointer to some file or directory path. + + @retval NULL The input path is NULL or out of memory. + + @retval non-NULL A pointer to a clean, fully-qualified version of Path. + If there is no working directory, then a pointer to a + clean, but not necessarily fully-qualified version of + Path. The caller must free this memory when it is no + longer needed. +**/ +CHAR16* +EFIAPI +FullyQualifyPath( + IN CONST CHAR16 *Path + ) +{ + CONST CHAR16 *WorkingPath; + CONST CHAR16 *InputPath; + CHAR16 *CharPtr; + CHAR16 *InputFileSystem; + UINTN FileSystemCharCount; + CHAR16 *FullyQualifiedPath; + UINTN Size; + + FullyQualifiedPath = NULL; + + ASSERT(Path != NULL); + // + // Handle erroneous input when asserts are disabled. + // + if (Path == NULL) { + return NULL; + } + // + // In paths that contain ":", like fs0:dir/file.ext and fs2:\fqpath\file.ext, + // we have to consider the file system part separately from the "path" part. + // If there is a file system in the path, we have to get the current working + // directory for that file system. Then we need to use the part of the path + // following the ":". If a path does not contain ":", we use it as given. + // + InputPath = StrStr(Path, L":"); + if (InputPath != NULL) { + InputPath++; + FileSystemCharCount = ((UINTN)InputPath - (UINTN)Path + sizeof(CHAR16)) / sizeof(CHAR16); + InputFileSystem = AllocateCopyPool(FileSystemCharCount * sizeof(CHAR16), Path); + if (InputFileSystem != NULL) { + InputFileSystem[FileSystemCharCount - 1] = CHAR_NULL; + } + WorkingPath = ShellGetCurrentDir(InputFileSystem); + SHELL_FREE_NON_NULL(InputFileSystem); + } else { + InputPath = Path; + WorkingPath = ShellGetEnvironmentVariable(L"cwd"); + } + + if (WorkingPath == NULL) { + // + // With no working directory, all we can do is copy and clean the input path. + // + FullyQualifiedPath = AllocateCopyPool(StrSize(Path), Path); + } else { + // + // Allocate space for both strings plus one more character. + // + Size = StrSize(WorkingPath) + StrSize(InputPath); + FullyQualifiedPath = AllocateZeroPool(Size); + if (FullyQualifiedPath == NULL) { + // + // Try to copy and clean just the input. No harm if not enough memory. + // + FullyQualifiedPath = AllocateCopyPool(StrSize(Path), Path); + } else { + if (*InputPath == L'\\' || *InputPath == L'/') { + // + // Absolute path: start with the current working directory, then + // truncate the new path after the file system part. + // + StrCpyS(FullyQualifiedPath, Size/sizeof(CHAR16), WorkingPath); + CharPtr = StrStr(FullyQualifiedPath, L":"); + if (CharPtr != NULL) { + *(CharPtr + 1) = CHAR_NULL; + } + } else { + // + // Relative path: start with the working directory and append "\". + // + StrCpyS(FullyQualifiedPath, Size/sizeof(CHAR16), WorkingPath); + StrCatS(FullyQualifiedPath, Size/sizeof(CHAR16), L"\\"); + } + // + // Now append the absolute or relative path. + // + StrCatS(FullyQualifiedPath, Size/sizeof(CHAR16), InputPath); + } + } + + PathCleanUpDirectories(FullyQualifiedPath); + + return FullyQualifiedPath; +} + +/** + Check if a Unicode character is a hexadecimal character. + + This internal function checks if a Unicode character is a + numeric character. The valid hexadecimal characters are + 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 +ShellIsHexaDecimalDigitCharacter ( + IN CHAR16 Char + ) +{ + return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f')); +} + +/** + Check if a Unicode character is a decimal character. + + This internal function checks if a Unicode character is a + decimal character. The valid characters are + L'0' to L'9'. + + + @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 +ShellIsDecimalDigitCharacter ( + IN CHAR16 Char + ) +{ + return (BOOLEAN) (Char >= L'0' && Char <= L'9'); +} + +/** + Helper function to find ShellEnvironment2 for constructor. + + @param[in] ImageHandle A copy of the calling image's handle. + + @retval EFI_OUT_OF_RESOURCES Memory allocation failed. +**/ +EFI_STATUS +ShellFindSE2 ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Buffer; + UINTN BufferSize; + UINTN HandleIndex; + + BufferSize = 0; + Buffer = NULL; + Status = gBS->OpenProtocol(ImageHandle, + &gEfiShellEnvironment2Guid, + (VOID **)&mEfiShellEnvironment2, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + // + // look for the mEfiShellEnvironment2 protocol at a higher level + // + if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){ + // + // figure out how big of a buffer we need. + // + Status = gBS->LocateHandle (ByProtocol, + &gEfiShellEnvironment2Guid, + NULL, // ignored for ByProtocol + &BufferSize, + Buffer + ); + // + // maybe it's not there??? + // + if (Status == EFI_BUFFER_TOO_SMALL) { + Buffer = (EFI_HANDLE*)AllocateZeroPool(BufferSize); + if (Buffer == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + Status = gBS->LocateHandle (ByProtocol, + &gEfiShellEnvironment2Guid, + NULL, // ignored for ByProtocol + &BufferSize, + Buffer + ); + } + if (!EFI_ERROR (Status) && Buffer != NULL) { + // + // now parse the list of returned handles + // + Status = EFI_NOT_FOUND; + for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) { + Status = gBS->OpenProtocol(Buffer[HandleIndex], + &gEfiShellEnvironment2Guid, + (VOID **)&mEfiShellEnvironment2, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) { + mEfiShellEnvironment2Handle = Buffer[HandleIndex]; + Status = EFI_SUCCESS; + break; + } + } + } + } + if (Buffer != NULL) { + FreePool (Buffer); + } + return (Status); +} + +/** + Function to do most of the work of the constructor. Allows for calling + multiple times without complete re-initialization. + + @param[in] ImageHandle A copy of the ImageHandle. + @param[in] SystemTable A pointer to the SystemTable for the application. + + @retval EFI_SUCCESS The operationw as successful. +**/ +EFI_STATUS +ShellLibConstructorWorker ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (gEfiShellProtocol == NULL) { + // + // UEFI 2.0 shell interfaces (used preferentially) + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiShellProtocolGuid, + (VOID **)&gEfiShellProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + // + // Search for the shell protocol + // + Status = gBS->LocateProtocol ( + &gEfiShellProtocolGuid, + NULL, + (VOID **)&gEfiShellProtocol + ); + if (EFI_ERROR (Status)) { + gEfiShellProtocol = NULL; + } + } + } + + if (gEfiShellParametersProtocol == NULL) { + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **)&gEfiShellParametersProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + gEfiShellParametersProtocol = NULL; + } + } + + if (gEfiShellProtocol == NULL) { + // + // Moved to seperate function due to complexity + // + Status = ShellFindSE2(ImageHandle); + + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status)); + mEfiShellEnvironment2 = NULL; + } + Status = gBS->OpenProtocol(ImageHandle, + &gEfiShellInterfaceGuid, + (VOID **)&mEfiShellInterface, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) { + mEfiShellInterface = NULL; + } + } + + // + // Getting either EDK Shell's ShellEnvironment2 and ShellInterface protocol + // or UEFI Shell's Shell protocol. + // When ShellLib is linked to a driver producing DynamicCommand protocol, + // ShellParameters protocol is set by DynamicCommand.Handler(). + // + if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || + (gEfiShellProtocol != NULL) + ) { + if (gEfiShellProtocol != NULL) { + FileFunctionMap.GetFileInfo = gEfiShellProtocol->GetFileInfo; + FileFunctionMap.SetFileInfo = gEfiShellProtocol->SetFileInfo; + FileFunctionMap.ReadFile = gEfiShellProtocol->ReadFile; + FileFunctionMap.WriteFile = gEfiShellProtocol->WriteFile; + FileFunctionMap.CloseFile = gEfiShellProtocol->CloseFile; + FileFunctionMap.DeleteFile = gEfiShellProtocol->DeleteFile; + FileFunctionMap.GetFilePosition = gEfiShellProtocol->GetFilePosition; + FileFunctionMap.SetFilePosition = gEfiShellProtocol->SetFilePosition; + FileFunctionMap.FlushFile = gEfiShellProtocol->FlushFile; + FileFunctionMap.GetFileSize = gEfiShellProtocol->GetFileSize; + } else { + FileFunctionMap.GetFileInfo = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo; + FileFunctionMap.SetFileInfo = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo; + FileFunctionMap.ReadFile = (EFI_SHELL_READ_FILE)FileHandleRead; + FileFunctionMap.WriteFile = (EFI_SHELL_WRITE_FILE)FileHandleWrite; + FileFunctionMap.CloseFile = (EFI_SHELL_CLOSE_FILE)FileHandleClose; + FileFunctionMap.DeleteFile = (EFI_SHELL_DELETE_FILE)FileHandleDelete; + FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition; + FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition; + FileFunctionMap.FlushFile = (EFI_SHELL_FLUSH_FILE)FileHandleFlush; + FileFunctionMap.GetFileSize = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize; + } + return (EFI_SUCCESS); + } + return (EFI_NOT_FOUND); +} +/** + Constructor for the Shell library. + + Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the initialization was complete sucessfully + @return others an error ocurred during initialization +**/ +EFI_STATUS +EFIAPI +ShellLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + mEfiShellEnvironment2 = NULL; + gEfiShellProtocol = NULL; + gEfiShellParametersProtocol = NULL; + mEfiShellInterface = NULL; + mEfiShellEnvironment2Handle = NULL; + mUnicodeCollationProtocol = NULL; + + // + // verify that auto initialize is not set false + // + if (PcdGetBool(PcdShellLibAutoInitialize) == 0) { + return (EFI_SUCCESS); + } + + return (ShellLibConstructorWorker(ImageHandle, SystemTable)); +} + +/** + Destructor for the library. free any resources. + + @param[in] ImageHandle A copy of the ImageHandle. + @param[in] SystemTable A pointer to the SystemTable for the application. + + @retval EFI_SUCCESS The operation was successful. + @return An error from the CloseProtocol function. +**/ +EFI_STATUS +EFIAPI +ShellLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (mEfiShellEnvironment2 != NULL) { + Status = gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle, + &gEfiShellEnvironment2Guid, + ImageHandle, + NULL); + if (!EFI_ERROR (Status)) { + mEfiShellEnvironment2 = NULL; + mEfiShellEnvironment2Handle = NULL; + } + } + if (mEfiShellInterface != NULL) { + Status = gBS->CloseProtocol(ImageHandle, + &gEfiShellInterfaceGuid, + ImageHandle, + NULL); + if (!EFI_ERROR (Status)) { + mEfiShellInterface = NULL; + } + } + if (gEfiShellProtocol != NULL) { + Status = gBS->CloseProtocol(ImageHandle, + &gEfiShellProtocolGuid, + ImageHandle, + NULL); + if (!EFI_ERROR (Status)) { + gEfiShellProtocol = NULL; + } + } + if (gEfiShellParametersProtocol != NULL) { + Status = gBS->CloseProtocol(ImageHandle, + &gEfiShellParametersProtocolGuid, + ImageHandle, + NULL); + if (!EFI_ERROR (Status)) { + gEfiShellParametersProtocol = NULL; + } + } + + return (EFI_SUCCESS); +} + +/** + This function causes the shell library to initialize itself. If the shell library + is already initialized it will de-initialize all the current protocol poitners and + re-populate them again. + + When the library is used with PcdShellLibAutoInitialize set to true this function + will return EFI_SUCCESS and perform no actions. + + This function is intended for internal access for shell commands only. + + @retval EFI_SUCCESS the initialization was complete sucessfully + +**/ +EFI_STATUS +EFIAPI +ShellInitialize ( + VOID + ) +{ + EFI_STATUS Status; + + // + // if auto initialize is not false then skip + // + if (PcdGetBool(PcdShellLibAutoInitialize) != 0) { + return (EFI_SUCCESS); + } + + // + // deinit the current stuff + // + Status = ShellLibDestructor (gImageHandle, gST); + ASSERT_EFI_ERROR (Status); + + // + // init the new stuff + // + return (ShellLibConstructorWorker(gImageHandle, gST)); +} + +/** + 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 +ShellGetFileInfo ( + IN SHELL_FILE_HANDLE FileHandle + ) +{ + return (FileFunctionMap.GetFileInfo(FileHandle)); +} + +/** + This function sets the information about the file for the opened handle + specified. + + @param[in] FileHandle The file handle of the file for which information + is being set. + + @param[in] FileInfo The information to set. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid. + @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellSetFileInfo ( + IN SHELL_FILE_HANDLE FileHandle, + IN EFI_FILE_INFO *FileInfo + ) +{ + return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo)); +} + + /** + This function will open a file or directory referenced by DevicePath. + + This function opens a file with the open mode according to the file path. The + Attributes is valid only for EFI_FILE_MODE_CREATE. + + @param FilePath on input the device path to the file. On output + the remaining device path. + @param FileHandle pointer to the file handle. + @param OpenMode the mode to open the file with. + @param Attributes the file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found on + the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellOpenFileByDevicePath( + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + CHAR16 *FileName; + EFI_STATUS Status; + EFI_FILE_PROTOCOL *File; + + if (FilePath == NULL || FileHandle == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // which shell interface should we use + // + if (gEfiShellProtocol != NULL) { + // + // use UEFI Shell 2.0 method. + // + FileName = gEfiShellProtocol->GetFilePathFromDevicePath(*FilePath); + if (FileName == NULL) { + return (EFI_INVALID_PARAMETER); + } + Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes); + FreePool(FileName); + return (Status); + } + + + // + // use old shell method. + // + Status = EfiOpenFileByDevicePath (FilePath, &File, OpenMode, Attributes); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also! + // + *FileHandle = (VOID*)File; + return (EFI_SUCCESS); +} + +/** + This function will open a file or directory referenced by filename. + + If return is EFI_SUCCESS, the Filehandle is the opened file's handle; + otherwise, the Filehandle is NULL. The Attributes is valid only for + EFI_FILE_MODE_CREATE. + + if FileName is NULL then ASSERT() + + @param FileName pointer to file name + @param FileHandle pointer to the file handle. + @param OpenMode the mode to open the file with. + @param Attributes the file's file attributes. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. +**/ +EFI_STATUS +EFIAPI +ShellOpenFileByName( + IN CONST CHAR16 *FileName, + OUT SHELL_FILE_HANDLE *FileHandle, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_STATUS Status; + EFI_FILE_INFO *FileInfo; + CHAR16 *FileNameCopy; + EFI_STATUS Status2; + + // + // ASSERT if FileName is NULL + // + ASSERT(FileName != NULL); + + if (FileName == NULL) { + return (EFI_INVALID_PARAMETER); + } + + if (gEfiShellProtocol != NULL) { + if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE) { + + // + // Create only a directory + // + if ((Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) { + return ShellCreateDirectory(FileName, FileHandle); + } + + // + // Create the directory to create the file in + // + FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName); + if (FileNameCopy == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + PathCleanUpDirectories (FileNameCopy); + if (PathRemoveLastItem (FileNameCopy)) { + if (!EFI_ERROR(ShellCreateDirectory (FileNameCopy, FileHandle))) { + ShellCloseFile (FileHandle); + } + } + SHELL_FREE_NON_NULL (FileNameCopy); + } + + // + // Use UEFI Shell 2.0 method to create the file + // + Status = gEfiShellProtocol->OpenFileByName(FileName, + FileHandle, + OpenMode); + if (EFI_ERROR(Status)) { + return Status; + } + + if (mUnicodeCollationProtocol == NULL) { + Status = gBS->LocateProtocol (&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&mUnicodeCollationProtocol); + if (EFI_ERROR (Status)) { + gEfiShellProtocol->CloseFile (*FileHandle); + return Status; + } + } + + if ((mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NUL") != 0) && + (mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NULL") != 0) && + !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){ + FileInfo = FileFunctionMap.GetFileInfo(*FileHandle); + ASSERT(FileInfo != NULL); + FileInfo->Attribute = Attributes; + Status2 = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo); + FreePool(FileInfo); + if (EFI_ERROR (Status2)) { + gEfiShellProtocol->CloseFile(*FileHandle); + } + Status = Status2; + } + return (Status); + } + // + // Using EFI Shell version + // this means convert name to path and call that function + // since this will use EFI method again that will open it. + // + ASSERT(mEfiShellEnvironment2 != NULL); + FilePath = mEfiShellEnvironment2->NameToPath ((CHAR16*)FileName); + if (FilePath != NULL) { + return (ShellOpenFileByDevicePath(&FilePath, + FileHandle, + OpenMode, + Attributes)); + } + return (EFI_DEVICE_ERROR); +} +/** + This function create a directory + + If return is EFI_SUCCESS, the Filehandle is the opened directory's handle; + otherwise, the Filehandle is NULL. If the directory already existed, this + function opens the existing directory. + + @param DirectoryName pointer to directory name + @param FileHandle pointer to the file handle. + + @retval EFI_SUCCESS The information was set. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED Could not open the file path. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval EFI_VOLUME_FULL The volume is full. + @sa ShellOpenFileByName +**/ +EFI_STATUS +EFIAPI +ShellCreateDirectory( + IN CONST CHAR16 *DirectoryName, + OUT SHELL_FILE_HANDLE *FileHandle + ) +{ + if (gEfiShellProtocol != NULL) { + // + // Use UEFI Shell 2.0 method + // + return (gEfiShellProtocol->CreateFile(DirectoryName, + EFI_FILE_DIRECTORY, + FileHandle + )); + } else { + return (ShellOpenFileByName(DirectoryName, + FileHandle, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + EFI_FILE_DIRECTORY + )); + } +} + +/** + 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 +ShellReadFile( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + return (FileFunctionMap.ReadFile(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 +ShellWriteFile( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + return (FileFunctionMap.WriteFile(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 sucessfully. +**/ +EFI_STATUS +EFIAPI +ShellCloseFile ( + IN SHELL_FILE_HANDLE *FileHandle + ) +{ + return (FileFunctionMap.CloseFile(*FileHandle)); +} + +/** + Delete a file and close the handle + + This function closes and deletes a file. In all cases the file handle is closed. + If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is + returned, but the handle is still closed. + + @param FileHandle the file handle to delete + + @retval EFI_SUCCESS the file was closed sucessfully + @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 +ShellDeleteFile ( + IN SHELL_FILE_HANDLE *FileHandle + ) +{ + return (FileFunctionMap.DeleteFile(*FileHandle)); +} + +/** + Set the current position in a file. + + This function sets the current file position for the handle to the position + supplied. With the exception of 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 begining of file + + @retval EFI_SUCCESS Operation completed sucessfully. + @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 +ShellSetFilePosition ( + IN SHELL_FILE_HANDLE FileHandle, + IN UINT64 Position + ) +{ + return (FileFunctionMap.SetFilePosition(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 begining of file. + + @retval EFI_SUCCESS the operation completed sucessfully. + @retval INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_UNSUPPORTED the request is not valid on directories. +**/ +EFI_STATUS +EFIAPI +ShellGetFilePosition ( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64 *Position + ) +{ + return (FileFunctionMap.GetFilePosition(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 +ShellFlushFile ( + IN SHELL_FILE_HANDLE FileHandle + ) +{ + return (FileFunctionMap.FlushFile(FileHandle)); +} + +/** 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 ShellFindNextFile() to get subsequent directory entries. + + The buffer will be freed by ShellFindNextFile() 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 the buffer for the 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 ShellGetFileInfo, ShellSetFilePosition, + or ShellReadFile +**/ +EFI_STATUS +EFIAPI +ShellFindFirstFile ( + IN SHELL_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO **Buffer + ) +{ + // + // pass to file handle lib + // + return (FileHandleFindFirstFile(DirHandle, Buffer)); +} +/** Retrieve next entries from a directory. + + To use this function, the caller must first call the ShellFindFirstFile() + function to get the first directory entry. Subsequent directory entries are + retrieved by using the ShellFindNextFile() function. This function can + be called several times to get each entry from the directory. If the call of + ShellFindNextFile() 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 +ShellFindNextFile( + IN SHELL_FILE_HANDLE DirHandle, + OUT EFI_FILE_INFO *Buffer, + OUT BOOLEAN *NoFile + ) +{ + // + // pass to file handle lib + // + return (FileHandleFindNextFile(DirHandle, Buffer, NoFile)); +} +/** + Retrieve the size of a file. + + if FileHandle is NULL then ASSERT() + if Size is NULL then ASSERT() + + This function extracts the file size info from the FileHandle's EFI_FILE_INFO + data. + + @param FileHandle file handle from which size is retrieved + @param Size pointer to size + + @retval EFI_SUCCESS operation was completed sucessfully + @retval EFI_DEVICE_ERROR cannot access the file +**/ +EFI_STATUS +EFIAPI +ShellGetFileSize ( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64 *Size + ) +{ + return (FileFunctionMap.GetFileSize(FileHandle, Size)); +} +/** + Retrieves the status of the break execution flag + + this function is useful to check whether the application is being asked to halt by the shell. + + @retval TRUE the execution break is enabled + @retval FALSE the execution break is not enabled +**/ +BOOLEAN +EFIAPI +ShellGetExecutionBreakFlag( + VOID + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + + // + // We are using UEFI Shell 2.0; see if the event has been triggered + // + if (gBS->CheckEvent(gEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) { + return (FALSE); + } + return (TRUE); + } + + // + // using EFI Shell; call the function to check + // + if (mEfiShellEnvironment2 != NULL) { + return (mEfiShellEnvironment2->GetExecutionBreak()); + } + + return (FALSE); +} +/** + return the value of an environment variable + + this function gets the value of the environment variable set by the + ShellSetEnvironmentVariable function + + @param EnvKey The key name of the environment variable. + + @retval NULL the named environment variable does not exist. + @return != NULL pointer to the value of the environment variable +**/ +CONST CHAR16* +EFIAPI +ShellGetEnvironmentVariable ( + IN CONST CHAR16 *EnvKey + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + return (gEfiShellProtocol->GetEnv(EnvKey)); + } + + // + // Check for EFI shell + // + if (mEfiShellEnvironment2 != NULL) { + return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey)); + } + + return NULL; +} +/** + set the value of an environment variable + +This function changes the current value of the specified environment variable. If the +environment variable exists and the Value is an empty string, then the environment +variable is deleted. If the environment variable exists and the Value is not an empty +string, then the value of the environment variable is changed. If the environment +variable does not exist and the Value is an empty string, there is no action. If the +environment variable does not exist and the Value is a non-empty string, then the +environment variable is created and assigned the specified value. + + This is not supported pre-UEFI Shell 2.0. + + @param EnvKey The key name of the environment variable. + @param EnvVal The Value of the environment variable + @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE). + + @retval EFI_SUCCESS the operation was completed sucessfully + @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments +**/ +EFI_STATUS +EFIAPI +ShellSetEnvironmentVariable ( + IN CONST CHAR16 *EnvKey, + IN CONST CHAR16 *EnvVal, + IN BOOLEAN Volatile + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile)); + } + + // + // This feature does not exist under EFI shell + // + return (EFI_UNSUPPORTED); +} + +/** + Cause the shell to parse and execute a command line. + + This function creates a nested instance of the shell and executes the specified + command (CommandLine) with the specified environment (Environment). Upon return, + the status code returned by the specified command is placed in StatusCode. + If Environment is NULL, then the current environment is used and all changes made + by the commands executed will be reflected in the current environment. If the + Environment is non-NULL, then the changes made will be discarded. + The CommandLine is executed from the current working directory on the current + device. + + The EnvironmentVariables pararemeter is ignored in a pre-UEFI Shell 2.0 + environment. The values pointed to by the parameters will be unchanged by the + ShellExecute() function. The Output parameter has no effect in a + UEFI Shell 2.0 environment. + + @param[in] ParentHandle The parent image starting the operation. + @param[in] CommandLine The pointer to a NULL terminated command line. + @param[in] Output True to display debug output. False to hide it. + @param[in] EnvironmentVariables Optional pointer to array of environment variables + in the form "x=y". If NULL, the current set is used. + @param[out] Status The status of the run command line. + + @retval EFI_SUCCESS The operation completed sucessfully. Status + contains the status code returned. + @retval EFI_INVALID_PARAMETER A parameter contains an invalid value. + @retval EFI_OUT_OF_RESOURCES Out of resources. + @retval EFI_UNSUPPORTED The operation is not allowed. +**/ +EFI_STATUS +EFIAPI +ShellExecute ( + IN EFI_HANDLE *ParentHandle, + IN CHAR16 *CommandLine OPTIONAL, + IN BOOLEAN Output OPTIONAL, + IN CHAR16 **EnvironmentVariables OPTIONAL, + OUT EFI_STATUS *Status OPTIONAL + ) +{ + EFI_STATUS CmdStatus; + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + // + // Call UEFI Shell 2.0 version (not using Output parameter) + // + return (gEfiShellProtocol->Execute(ParentHandle, + CommandLine, + EnvironmentVariables, + Status)); + } + + // + // Check for EFI shell + // + if (mEfiShellEnvironment2 != NULL) { + // + // Call EFI Shell version. + // Due to oddity in the EFI shell we want to dereference the ParentHandle here + // + CmdStatus = (mEfiShellEnvironment2->Execute(*ParentHandle, + CommandLine, + Output)); + // + // No Status output parameter so just use the returned status + // + if (Status != NULL) { + *Status = CmdStatus; + } + // + // If there was an error, we can't tell if it was from the command or from + // the Execute() function, so we'll just assume the shell ran successfully + // and the error came from the command. + // + return EFI_SUCCESS; + } + + return (EFI_UNSUPPORTED); +} + +/** + Retreives the current directory path + + If the DeviceName is NULL, it returns the current device's current directory + name. If the DeviceName is not NULL, it returns the current directory name + on specified drive. + + Note that the current directory string should exclude the tailing backslash character. + + @param DeviceName the name of the drive to get directory on + + @retval NULL the directory does not exist + @return != NULL the directory +**/ +CONST CHAR16* +EFIAPI +ShellGetCurrentDir ( + IN CHAR16 * CONST DeviceName OPTIONAL + ) +{ + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + return (gEfiShellProtocol->GetCurDir(DeviceName)); + } + + // + // Check for EFI shell + // + if (mEfiShellEnvironment2 != NULL) { + return (mEfiShellEnvironment2->CurDir(DeviceName)); + } + + return (NULL); +} +/** + sets (enabled or disabled) the page break mode + + when page break mode is enabled the screen will stop scrolling + and wait for operator input before scrolling a subsequent screen. + + @param CurrentState TRUE to enable and FALSE to disable +**/ +VOID +EFIAPI +ShellSetPageBreakMode ( + IN BOOLEAN CurrentState + ) +{ + // + // check for enabling + // + if (CurrentState != 0x00) { + // + // check for UEFI Shell 2.0 + // + if (gEfiShellProtocol != NULL) { + // + // Enable with UEFI 2.0 Shell + // + gEfiShellProtocol->EnablePageBreak(); + return; + } else { + // + // Check for EFI shell + // + if (mEfiShellEnvironment2 != NULL) { + // + // Enable with EFI Shell + // + mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF); + return; + } + } + } else { + // + // check for UEFI Shell 2.0 + // + if (gEfiShellProtocol != NULL) { + // + // Disable with UEFI 2.0 Shell + // + gEfiShellProtocol->DisablePageBreak(); + return; + } else { + // + // Check for EFI shell + // + if (mEfiShellEnvironment2 != NULL) { + // + // Disable with EFI Shell + // + mEfiShellEnvironment2->DisablePageBreak (); + return; + } + } + } +} + +/// +/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers. +/// This allows for the struct to be populated. +/// +typedef struct { + LIST_ENTRY Link; + EFI_STATUS Status; + CHAR16 *FullName; + CHAR16 *FileName; + SHELL_FILE_HANDLE Handle; + EFI_FILE_INFO *Info; +} EFI_SHELL_FILE_INFO_NO_CONST; + +/** + Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list. + + if OldStyleFileList is NULL then ASSERT() + + this function will convert a SHELL_FILE_ARG based list into a callee allocated + EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via + the ShellCloseFileMetaArg function. + + @param[in] FileList the EFI shell list type + @param[in, out] ListHead the list to add to + + @retval the resultant head of the double linked new format list; +**/ +LIST_ENTRY* +InternalShellConvertFileListType ( + IN LIST_ENTRY *FileList, + IN OUT LIST_ENTRY *ListHead + ) +{ + SHELL_FILE_ARG *OldInfo; + LIST_ENTRY *Link; + EFI_SHELL_FILE_INFO_NO_CONST *NewInfo; + + // + // ASSERTs + // + ASSERT(FileList != NULL); + ASSERT(ListHead != NULL); + + // + // enumerate through each member of the old list and copy + // + for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) { + OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); + ASSERT(OldInfo != NULL); + + // + // Skip ones that failed to open... + // + if (OldInfo->Status != EFI_SUCCESS) { + continue; + } + + // + // make sure the old list was valid + // + ASSERT(OldInfo->Info != NULL); + ASSERT(OldInfo->FullName != NULL); + ASSERT(OldInfo->FileName != NULL); + + // + // allocate a new EFI_SHELL_FILE_INFO object + // + NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + if (NewInfo == NULL) { + ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead)); + ListHead = NULL; + break; + } + + // + // copy the simple items + // + NewInfo->Handle = OldInfo->Handle; + NewInfo->Status = OldInfo->Status; + + // old shell checks for 0 not NULL + OldInfo->Handle = 0; + + // + // allocate new space to copy strings and structure + // + NewInfo->FullName = AllocateCopyPool(StrSize(OldInfo->FullName), OldInfo->FullName); + NewInfo->FileName = AllocateCopyPool(StrSize(OldInfo->FileName), OldInfo->FileName); + NewInfo->Info = AllocateCopyPool((UINTN)OldInfo->Info->Size, OldInfo->Info); + + // + // make sure all the memory allocations were sucessful + // + if (NULL == NewInfo->FullName || NewInfo->FileName == NULL || NewInfo->Info == NULL) { + // + // Free the partially allocated new node + // + SHELL_FREE_NON_NULL(NewInfo->FullName); + SHELL_FREE_NON_NULL(NewInfo->FileName); + SHELL_FREE_NON_NULL(NewInfo->Info); + SHELL_FREE_NON_NULL(NewInfo); + + // + // Free the previously converted stuff + // + ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead)); + ListHead = NULL; + break; + } + + // + // add that to the list + // + InsertTailList(ListHead, &NewInfo->Link); + } + return (ListHead); +} +/** + Opens a group of files based on a path. + + This function uses the Arg to open all the matching files. Each matched + file has a SHELL_FILE_INFO structure to record the file information. These + structures are placed on the list ListHead. Users can get the SHELL_FILE_INFO + structures from ListHead to access each file. This function supports wildcards + and will process '?' and '*' as such. the list must be freed with a call to + ShellCloseFileMetaArg(). + + If you are NOT appending to an existing list *ListHead must be NULL. If + *ListHead is NULL then it must be callee freed. + + @param Arg pointer to path string + @param OpenMode mode to open files with + @param ListHead head of linked list of results + + @retval EFI_SUCCESS the operation was sucessful and the list head + contains the list of opened files + @return != EFI_SUCCESS the operation failed + + @sa InternalShellConvertFileListType +**/ +EFI_STATUS +EFIAPI +ShellOpenFileMetaArg ( + IN CHAR16 *Arg, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **ListHead + ) +{ + EFI_STATUS Status; + LIST_ENTRY mOldStyleFileList; + CHAR16 *CleanFilePathStr; + + // + // ASSERT that Arg and ListHead are not NULL + // + ASSERT(Arg != NULL); + ASSERT(ListHead != NULL); + + CleanFilePathStr = NULL; + + Status = InternalShellStripQuotes (Arg, &CleanFilePathStr); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + if (*ListHead == NULL) { + *ListHead = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + if (*ListHead == NULL) { + FreePool(CleanFilePathStr); + return (EFI_OUT_OF_RESOURCES); + } + InitializeListHead(&((*ListHead)->Link)); + } + Status = gEfiShellProtocol->OpenFileList(CleanFilePathStr, + OpenMode, + ListHead); + if (EFI_ERROR(Status)) { + gEfiShellProtocol->RemoveDupInFileList(ListHead); + } else { + Status = gEfiShellProtocol->RemoveDupInFileList(ListHead); + } + if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) { + FreePool(*ListHead); + FreePool(CleanFilePathStr); + *ListHead = NULL; + return (EFI_NOT_FOUND); + } + FreePool(CleanFilePathStr); + return (Status); + } + + // + // Check for EFI shell + // + if (mEfiShellEnvironment2 != NULL) { + // + // make sure the list head is initialized + // + InitializeListHead(&mOldStyleFileList); + + // + // Get the EFI Shell list of files + // + Status = mEfiShellEnvironment2->FileMetaArg(CleanFilePathStr, &mOldStyleFileList); + if (EFI_ERROR(Status)) { + *ListHead = NULL; + FreePool(CleanFilePathStr); + return (Status); + } + + if (*ListHead == NULL) { + *ListHead = (EFI_SHELL_FILE_INFO *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO)); + if (*ListHead == NULL) { + FreePool(CleanFilePathStr); + return (EFI_OUT_OF_RESOURCES); + } + InitializeListHead(&((*ListHead)->Link)); + } + + // + // Convert that to equivalent of UEFI Shell 2.0 structure + // + InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link); + + // + // Free the EFI Shell version that was converted. + // + mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList); + + if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) { + FreePool(*ListHead); + *ListHead = NULL; + Status = EFI_NOT_FOUND; + } + FreePool(CleanFilePathStr); + return (Status); + } + + FreePool(CleanFilePathStr); + return (EFI_UNSUPPORTED); +} +/** + Free the linked list returned from ShellOpenFileMetaArg. + + if ListHead is NULL then ASSERT(). + + @param ListHead the pointer to free. + + @retval EFI_SUCCESS the operation was sucessful. +**/ +EFI_STATUS +EFIAPI +ShellCloseFileMetaArg ( + IN OUT EFI_SHELL_FILE_INFO **ListHead + ) +{ + LIST_ENTRY *Node; + + // + // ASSERT that ListHead is not NULL + // + ASSERT(ListHead != NULL); + + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellProtocol != NULL) { + return (gEfiShellProtocol->FreeFileList(ListHead)); + } else if (mEfiShellEnvironment2 != NULL) { + // + // Since this is EFI Shell version we need to free our internally made copy + // of the list + // + for ( Node = GetFirstNode(&(*ListHead)->Link) + ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link) + ; Node = GetFirstNode(&(*ListHead)->Link)) { + RemoveEntryList(Node); + ((EFI_FILE_PROTOCOL*)((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle)->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle); + FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName); + FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName); + FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info); + FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node); + } + SHELL_FREE_NON_NULL(*ListHead); + return EFI_SUCCESS; + } + + return (EFI_UNSUPPORTED); +} + +/** + Find a file by searching the CWD and then the path. + + If FileName is NULL then ASSERT. + + If the return value is not NULL then the memory must be caller freed. + + @param FileName Filename string. + + @retval NULL the file was not found + @return !NULL the full path to the file. +**/ +CHAR16 * +EFIAPI +ShellFindFilePath ( + IN CONST CHAR16 *FileName + ) +{ + CONST CHAR16 *Path; + SHELL_FILE_HANDLE Handle; + EFI_STATUS Status; + CHAR16 *RetVal; + CHAR16 *TestPath; + CONST CHAR16 *Walker; + UINTN Size; + CHAR16 *TempChar; + + RetVal = NULL; + + // + // First make sure its not an absolute path. + // + Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR(Status)){ + if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) { + ASSERT(RetVal == NULL); + RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0); + ShellCloseFile(&Handle); + return (RetVal); + } else { + ShellCloseFile(&Handle); + } + } + + Path = ShellGetEnvironmentVariable(L"cwd"); + if (Path != NULL) { + Size = StrSize(Path) + sizeof(CHAR16); + Size += StrSize(FileName); + TestPath = AllocateZeroPool(Size); + if (TestPath == NULL) { + return (NULL); + } + StrCpyS(TestPath, Size/sizeof(CHAR16), Path); + StrCatS(TestPath, Size/sizeof(CHAR16), L"\\"); + StrCatS(TestPath, Size/sizeof(CHAR16), FileName); + Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR(Status)){ + if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) { + ASSERT(RetVal == NULL); + RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0); + ShellCloseFile(&Handle); + FreePool(TestPath); + return (RetVal); + } else { + ShellCloseFile(&Handle); + } + } + FreePool(TestPath); + } + Path = ShellGetEnvironmentVariable(L"path"); + if (Path != NULL) { + Size = StrSize(Path)+sizeof(CHAR16); + Size += StrSize(FileName); + TestPath = AllocateZeroPool(Size); + if (TestPath == NULL) { + return (NULL); + } + Walker = (CHAR16*)Path; + do { + CopyMem(TestPath, Walker, StrSize(Walker)); + if (TestPath != NULL) { + TempChar = StrStr(TestPath, L";"); + if (TempChar != NULL) { + *TempChar = CHAR_NULL; + } + if (TestPath[StrLen(TestPath)-1] != L'\\') { + StrCatS(TestPath, Size/sizeof(CHAR16), L"\\"); + } + if (FileName[0] == L'\\') { + FileName++; + } + StrCatS(TestPath, Size/sizeof(CHAR16), FileName); + if (StrStr(Walker, L";") != NULL) { + Walker = StrStr(Walker, L";") + 1; + } else { + Walker = NULL; + } + Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR(Status)){ + if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) { + ASSERT(RetVal == NULL); + RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0); + ShellCloseFile(&Handle); + break; + } else { + ShellCloseFile(&Handle); + } + } + } + } while (Walker != NULL && Walker[0] != CHAR_NULL); + FreePool(TestPath); + } + return (RetVal); +} + +/** + Find a file by searching the CWD and then the path with a variable set of file + extensions. If the file is not found it will append each extension in the list + in the order provided and return the first one that is successful. + + If FileName is NULL, then ASSERT. + If FileExtension is NULL, then behavior is identical to ShellFindFilePath. + + If the return value is not NULL then the memory must be caller freed. + + @param[in] FileName Filename string. + @param[in] FileExtension Semi-colon delimeted list of possible extensions. + + @retval NULL The file was not found. + @retval !NULL The path to the file. +**/ +CHAR16 * +EFIAPI +ShellFindFilePathEx ( + IN CONST CHAR16 *FileName, + IN CONST CHAR16 *FileExtension + ) +{ + CHAR16 *TestPath; + CHAR16 *RetVal; + CONST CHAR16 *ExtensionWalker; + UINTN Size; + CHAR16 *TempChar; + CHAR16 *TempChar2; + + ASSERT(FileName != NULL); + if (FileExtension == NULL) { + return (ShellFindFilePath(FileName)); + } + RetVal = ShellFindFilePath(FileName); + if (RetVal != NULL) { + return (RetVal); + } + Size = StrSize(FileName); + Size += StrSize(FileExtension); + TestPath = AllocateZeroPool(Size); + if (TestPath == NULL) { + return (NULL); + } + for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension; TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){ + StrCpyS(TestPath, Size/sizeof(CHAR16), FileName); + if (ExtensionWalker != NULL) { + StrCatS(TestPath, Size/sizeof(CHAR16), ExtensionWalker); + } + TempChar = StrStr(TestPath, L";"); + if (TempChar != NULL) { + *TempChar = CHAR_NULL; + } + RetVal = ShellFindFilePath(TestPath); + if (RetVal != NULL) { + break; + } + ASSERT(ExtensionWalker != NULL); + TempChar2 = StrStr(ExtensionWalker, L";"); + } + FreePool(TestPath); + return (RetVal); +} + +typedef struct { + LIST_ENTRY Link; + CHAR16 *Name; + SHELL_PARAM_TYPE Type; + CHAR16 *Value; + UINTN OriginalPosition; +} SHELL_PARAM_PACKAGE; + +/** + Checks the list of valid arguments and returns TRUE if the item was found. If the + return value is TRUE then the type parameter is set also. + + if CheckList is NULL then ASSERT(); + if Name is NULL then ASSERT(); + if Type is NULL then ASSERT(); + + @param Name pointer to Name of parameter found + @param CheckList List to check against + @param Type pointer to type of parameter if it was found + + @retval TRUE the Parameter was found. Type is valid. + @retval FALSE the Parameter was not found. Type is not valid. +**/ +BOOLEAN +InternalIsOnCheckList ( + IN CONST CHAR16 *Name, + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT SHELL_PARAM_TYPE *Type + ) +{ + SHELL_PARAM_ITEM *TempListItem; + CHAR16 *TempString; + + // + // ASSERT that all 3 pointer parameters aren't NULL + // + ASSERT(CheckList != NULL); + ASSERT(Type != NULL); + ASSERT(Name != NULL); + + // + // question mark and page break mode are always supported + // + if ((StrCmp(Name, L"-?") == 0) || + (StrCmp(Name, L"-b") == 0) + ) { + *Type = TypeFlag; + return (TRUE); + } + + // + // Enumerate through the list + // + for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) { + // + // If the Type is TypeStart only check the first characters of the passed in param + // If it matches set the type and return TRUE + // + if (TempListItem->Type == TypeStart) { + if (StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) { + *Type = TempListItem->Type; + return (TRUE); + } + TempString = NULL; + TempString = StrnCatGrow(&TempString, NULL, Name, StrLen(TempListItem->Name)); + if (TempString != NULL) { + if (StringNoCaseCompare(&TempString, &TempListItem->Name) == 0) { + *Type = TempListItem->Type; + FreePool(TempString); + return (TRUE); + } + FreePool(TempString); + } + } else if (StringNoCaseCompare(&Name, &TempListItem->Name) == 0) { + *Type = TempListItem->Type; + return (TRUE); + } + } + + return (FALSE); +} +/** + Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+' + + @param[in] Name pointer to Name of parameter found + @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not. + @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise. + + @retval TRUE the Parameter is a flag. + @retval FALSE the Parameter not a flag. +**/ +BOOLEAN +InternalIsFlag ( + IN CONST CHAR16 *Name, + IN CONST BOOLEAN AlwaysAllowNumbers, + IN CONST BOOLEAN TimeNumbers + ) +{ + // + // ASSERT that Name isn't NULL + // + ASSERT(Name != NULL); + + // + // If we accept numbers then dont return TRUE. (they will be values) + // + if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE, TimeNumbers)) && AlwaysAllowNumbers) { + return (FALSE); + } + + // + // If the Name has a /, +, or - as the first character return TRUE + // + if ((Name[0] == L'/') || + (Name[0] == L'-') || + (Name[0] == L'+') + ) { + return (TRUE); + } + return (FALSE); +} + +/** + Checks the command line arguments passed against the list of valid ones. + + If no initialization is required, then return RETURN_SUCCESS. + + @param[in] CheckList pointer to list of parameters to check + @param[out] CheckPackage pointer to pointer to list checked values + @param[out] ProblemParam optional pointer to pointer to unicode string for + the paramater that caused failure. If used then the + caller is responsible for freeing the memory. + @param[in] AutoPageBreak will automatically set PageBreakEnabled for "b" parameter + @param[in] Argv pointer to array of parameters + @param[in] Argc Count of parameters in Argv + @param[in] AlwaysAllowNumbers TRUE to allow numbers always, FALSE otherwise. + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed + @retval EFI_INVALID_PARAMETER A parameter was invalid + @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was + duplicated. the duplicated command line argument + was returned in ProblemParam if provided. + @retval EFI_NOT_FOUND a argument required a value that was missing. + the invalid command line argument was returned in + ProblemParam if provided. +**/ +EFI_STATUS +InternalCommandLineParse ( + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT LIST_ENTRY **CheckPackage, + OUT CHAR16 **ProblemParam OPTIONAL, + IN BOOLEAN AutoPageBreak, + IN CONST CHAR16 **Argv, + IN UINTN Argc, + IN BOOLEAN AlwaysAllowNumbers + ) +{ + UINTN LoopCounter; + SHELL_PARAM_TYPE CurrentItemType; + SHELL_PARAM_PACKAGE *CurrentItemPackage; + UINTN GetItemValue; + UINTN ValueSize; + UINTN Count; + CONST CHAR16 *TempPointer; + UINTN CurrentValueSize; + CHAR16 *NewValue; + + CurrentItemPackage = NULL; + GetItemValue = 0; + ValueSize = 0; + Count = 0; + + // + // If there is only 1 item we dont need to do anything + // + if (Argc < 1) { + *CheckPackage = NULL; + return (EFI_SUCCESS); + } + + // + // ASSERTs + // + ASSERT(CheckList != NULL); + ASSERT(Argv != NULL); + + // + // initialize the linked list + // + *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY)); + if (*CheckPackage == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + InitializeListHead(*CheckPackage); + + // + // loop through each of the arguments + // + for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) { + if (Argv[LoopCounter] == NULL) { + // + // do nothing for NULL argv + // + } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) { + // + // We might have leftover if last parameter didnt have optional value + // + if (GetItemValue != 0) { + GetItemValue = 0; + InsertHeadList(*CheckPackage, &CurrentItemPackage->Link); + } + // + // this is a flag + // + CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE)); + if (CurrentItemPackage == NULL) { + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_OUT_OF_RESOURCES); + } + CurrentItemPackage->Name = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]); + if (CurrentItemPackage->Name == NULL) { + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_OUT_OF_RESOURCES); + } + CurrentItemPackage->Type = CurrentItemType; + CurrentItemPackage->OriginalPosition = (UINTN)(-1); + CurrentItemPackage->Value = NULL; + + // + // Does this flag require a value + // + switch (CurrentItemPackage->Type) { + // + // possibly trigger the next loop(s) to populate the value of this item + // + case TypeValue: + case TypeTimeValue: + GetItemValue = 1; + ValueSize = 0; + break; + case TypeDoubleValue: + GetItemValue = 2; + ValueSize = 0; + break; + case TypeMaxValue: + GetItemValue = (UINTN)(-1); + ValueSize = 0; + break; + default: + // + // this item has no value expected; we are done + // + InsertHeadList(*CheckPackage, &CurrentItemPackage->Link); + ASSERT(GetItemValue == 0); + break; + } + } else if (GetItemValue != 0 && CurrentItemPackage != NULL && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, (BOOLEAN)(CurrentItemPackage->Type == TypeTimeValue))) { + // + // get the item VALUE for a previous flag + // + CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16); + NewValue = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value); + if (NewValue == NULL) { + SHELL_FREE_NON_NULL (CurrentItemPackage->Value); + SHELL_FREE_NON_NULL (CurrentItemPackage); + ShellCommandLineFreeVarList (*CheckPackage); + *CheckPackage = NULL; + return EFI_OUT_OF_RESOURCES; + } + CurrentItemPackage->Value = NewValue; + if (ValueSize == 0) { + StrCpyS( CurrentItemPackage->Value, + CurrentValueSize/sizeof(CHAR16), + Argv[LoopCounter] + ); + } else { + StrCatS( CurrentItemPackage->Value, + CurrentValueSize/sizeof(CHAR16), + L" " + ); + StrCatS( CurrentItemPackage->Value, + CurrentValueSize/sizeof(CHAR16), + Argv[LoopCounter] + ); + } + ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16); + + GetItemValue--; + if (GetItemValue == 0) { + InsertHeadList(*CheckPackage, &CurrentItemPackage->Link); + } + } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, FALSE)){ + // + // add this one as a non-flag + // + + TempPointer = Argv[LoopCounter]; + if ((*TempPointer == L'^' && *(TempPointer+1) == L'-') + || (*TempPointer == L'^' && *(TempPointer+1) == L'/') + || (*TempPointer == L'^' && *(TempPointer+1) == L'+') + ){ + TempPointer++; + } + CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE)); + if (CurrentItemPackage == NULL) { + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_OUT_OF_RESOURCES); + } + CurrentItemPackage->Name = NULL; + CurrentItemPackage->Type = TypePosition; + CurrentItemPackage->Value = AllocateCopyPool(StrSize(TempPointer), TempPointer); + if (CurrentItemPackage->Value == NULL) { + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_OUT_OF_RESOURCES); + } + CurrentItemPackage->OriginalPosition = Count++; + InsertHeadList(*CheckPackage, &CurrentItemPackage->Link); + } else { + // + // this was a non-recognised flag... error! + // + if (ProblemParam != NULL) { + *ProblemParam = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]); + } + ShellCommandLineFreeVarList(*CheckPackage); + *CheckPackage = NULL; + return (EFI_VOLUME_CORRUPTED); + } + } + if (GetItemValue != 0) { + GetItemValue = 0; + InsertHeadList(*CheckPackage, &CurrentItemPackage->Link); + } + // + // support for AutoPageBreak + // + if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) { + ShellSetPageBreakMode(TRUE); + } + return (EFI_SUCCESS); +} + +/** + Checks the command line arguments passed against the list of valid ones. + Optionally removes NULL values first. + + If no initialization is required, then return RETURN_SUCCESS. + + @param[in] CheckList The pointer to list of parameters to check. + @param[out] CheckPackage The package of checked values. + @param[out] ProblemParam Optional pointer to pointer to unicode string for + the paramater that caused failure. + @param[in] AutoPageBreak Will automatically set PageBreakEnabled. + @param[in] AlwaysAllowNumbers Will never fail for number based flags. + + @retval EFI_SUCCESS The operation completed sucessfully. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_VOLUME_CORRUPTED The command line was corrupt. + @retval EFI_DEVICE_ERROR The commands contained 2 opposing arguments. One + of the command line arguments was returned in + ProblemParam if provided. + @retval EFI_NOT_FOUND A argument required a value that was missing. + The invalid command line argument was returned in + ProblemParam if provided. +**/ +EFI_STATUS +EFIAPI +ShellCommandLineParseEx ( + IN CONST SHELL_PARAM_ITEM *CheckList, + OUT LIST_ENTRY **CheckPackage, + OUT CHAR16 **ProblemParam OPTIONAL, + IN BOOLEAN AutoPageBreak, + IN BOOLEAN AlwaysAllowNumbers + ) +{ + // + // ASSERT that CheckList and CheckPackage aren't NULL + // + ASSERT(CheckList != NULL); + ASSERT(CheckPackage != NULL); + + // + // Check for UEFI Shell 2.0 protocols + // + if (gEfiShellParametersProtocol != NULL) { + return (InternalCommandLineParse(CheckList, + CheckPackage, + ProblemParam, + AutoPageBreak, + (CONST CHAR16**) gEfiShellParametersProtocol->Argv, + gEfiShellParametersProtocol->Argc, + AlwaysAllowNumbers)); + } + + // + // ASSERT That EFI Shell is not required + // + ASSERT (mEfiShellInterface != NULL); + return (InternalCommandLineParse(CheckList, + CheckPackage, + ProblemParam, + AutoPageBreak, + (CONST CHAR16**) mEfiShellInterface->Argv, + mEfiShellInterface->Argc, + AlwaysAllowNumbers)); +} + +/** + Frees shell variable list that was returned from ShellCommandLineParse. + + This function will free all the memory that was used for the CheckPackage + list of postprocessed shell arguments. + + this function has no return value. + + if CheckPackage is NULL, then return + + @param CheckPackage the list to de-allocate + **/ +VOID +EFIAPI +ShellCommandLineFreeVarList ( + IN LIST_ENTRY *CheckPackage + ) +{ + LIST_ENTRY *Node; + + // + // check for CheckPackage == NULL + // + if (CheckPackage == NULL) { + return; + } + + // + // for each node in the list + // + for ( Node = GetFirstNode(CheckPackage) + ; !IsListEmpty(CheckPackage) + ; Node = GetFirstNode(CheckPackage) + ){ + // + // Remove it from the list + // + RemoveEntryList(Node); + + // + // if it has a name free the name + // + if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { + FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name); + } + + // + // if it has a value free the value + // + if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) { + FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value); + } + + // + // free the node structure + // + FreePool((SHELL_PARAM_PACKAGE*)Node); + } + // + // free the list head node + // + FreePool(CheckPackage); +} +/** + Checks for presence of a flag parameter + + flag arguments are in the form of "-" or "/", but do not have a value following the key + + if CheckPackage is NULL then return FALSE. + if KeyString is NULL then ASSERT() + + @param CheckPackage The package of parsed command line arguments + @param KeyString the Key of the command line argument to check for + + @retval TRUE the flag is on the command line + @retval FALSE the flag is not on the command line + **/ +BOOLEAN +EFIAPI +ShellCommandLineGetFlag ( + IN CONST LIST_ENTRY * CONST CheckPackage, + IN CONST CHAR16 * CONST KeyString + ) +{ + LIST_ENTRY *Node; + CHAR16 *TempString; + + // + // return FALSE for no package or KeyString is NULL + // + if (CheckPackage == NULL || KeyString == NULL) { + return (FALSE); + } + + // + // enumerate through the list of parametrs + // + for ( Node = GetFirstNode(CheckPackage) + ; !IsNull (CheckPackage, Node) + ; Node = GetNextNode(CheckPackage, Node) + ){ + // + // If the Name matches, return TRUE (and there may be NULL name) + // + if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { + // + // If Type is TypeStart then only compare the begining of the strings + // + if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) { + if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) { + return (TRUE); + } + TempString = NULL; + TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name)); + if (TempString != NULL) { + if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { + FreePool(TempString); + return (TRUE); + } + FreePool(TempString); + } + } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { + return (TRUE); + } + } + } + return (FALSE); +} +/** + Returns value from command line argument. + + Value parameters are in the form of "- value" or "/ value". + + If CheckPackage is NULL, then return NULL. + + @param[in] CheckPackage The package of parsed command line arguments. + @param[in] KeyString The Key of the command line argument to check for. + + @retval NULL The flag is not on the command line. + @retval !=NULL The pointer to unicode string of the value. +**/ +CONST CHAR16* +EFIAPI +ShellCommandLineGetValue ( + IN CONST LIST_ENTRY *CheckPackage, + IN CHAR16 *KeyString + ) +{ + LIST_ENTRY *Node; + CHAR16 *TempString; + + // + // return NULL for no package or KeyString is NULL + // + if (CheckPackage == NULL || KeyString == NULL) { + return (NULL); + } + + // + // enumerate through the list of parametrs + // + for ( Node = GetFirstNode(CheckPackage) + ; !IsNull (CheckPackage, Node) + ; Node = GetNextNode(CheckPackage, Node) + ){ + // + // If the Name matches, return TRUE (and there may be NULL name) + // + if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) { + // + // If Type is TypeStart then only compare the begining of the strings + // + if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) { + if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) { + return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString)); + } + TempString = NULL; + TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name)); + if (TempString != NULL) { + if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { + FreePool(TempString); + return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString)); + } + FreePool(TempString); + } + } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) { + return (((SHELL_PARAM_PACKAGE*)Node)->Value); + } + } + } + return (NULL); +} + +/** + Returns raw value from command line argument. + + Raw value parameters are in the form of "value" in a specific position in the list. + + If CheckPackage is NULL, then return NULL. + + @param[in] CheckPackage The package of parsed command line arguments. + @param[in] Position The position of the value. + + @retval NULL The flag is not on the command line. + @retval !=NULL The pointer to unicode string of the value. + **/ +CONST CHAR16* +EFIAPI +ShellCommandLineGetRawValue ( + IN CONST LIST_ENTRY * CONST CheckPackage, + IN UINTN Position + ) +{ + LIST_ENTRY *Node; + + // + // check for CheckPackage == NULL + // + if (CheckPackage == NULL) { + return (NULL); + } + + // + // enumerate through the list of parametrs + // + for ( Node = GetFirstNode(CheckPackage) + ; !IsNull (CheckPackage, Node) + ; Node = GetNextNode(CheckPackage, Node) + ){ + // + // If the position matches, return the value + // + if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) { + return (((SHELL_PARAM_PACKAGE*)Node)->Value); + } + } + return (NULL); +} + +/** + returns the number of command line value parameters that were parsed. + + this will not include flags. + + @param[in] CheckPackage The package of parsed command line arguments. + + @retval (UINTN)-1 No parsing has ocurred + @return other The number of value parameters found +**/ +UINTN +EFIAPI +ShellCommandLineGetCount( + IN CONST LIST_ENTRY *CheckPackage + ) +{ + LIST_ENTRY *Node1; + UINTN Count; + + if (CheckPackage == NULL) { + return (0); + } + for ( Node1 = GetFirstNode(CheckPackage), Count = 0 + ; !IsNull (CheckPackage, Node1) + ; Node1 = GetNextNode(CheckPackage, Node1) + ){ + if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) { + Count++; + } + } + return (Count); +} + +/** + Determines if a parameter is duplicated. + + If Param is not NULL then it will point to a callee allocated string buffer + with the parameter value if a duplicate is found. + + If CheckPackage is NULL, then ASSERT. + + @param[in] CheckPackage The package of parsed command line arguments. + @param[out] Param Upon finding one, a pointer to the duplicated parameter. + + @retval EFI_SUCCESS No parameters were duplicated. + @retval EFI_DEVICE_ERROR A duplicate was found. + **/ +EFI_STATUS +EFIAPI +ShellCommandLineCheckDuplicate ( + IN CONST LIST_ENTRY *CheckPackage, + OUT CHAR16 **Param + ) +{ + LIST_ENTRY *Node1; + LIST_ENTRY *Node2; + + ASSERT(CheckPackage != NULL); + + for ( Node1 = GetFirstNode(CheckPackage) + ; !IsNull (CheckPackage, Node1) + ; Node1 = GetNextNode(CheckPackage, Node1) + ){ + for ( Node2 = GetNextNode(CheckPackage, Node1) + ; !IsNull (CheckPackage, Node2) + ; Node2 = GetNextNode(CheckPackage, Node2) + ){ + if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) { + if (Param != NULL) { + *Param = NULL; + *Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0); + } + return (EFI_DEVICE_ERROR); + } + } + } + return (EFI_SUCCESS); +} + +/** + This is a find and replace function. Upon successful return the NewString is a copy of + SourceString with each instance of FindTarget replaced with ReplaceWith. + + If SourceString and NewString overlap the behavior is undefined. + + If the string would grow bigger than NewSize it will halt and return error. + + @param[in] SourceString The string with source buffer. + @param[in, out] NewString The string with resultant buffer. + @param[in] NewSize The size in bytes of NewString. + @param[in] FindTarget The string to look for. + @param[in] ReplaceWith The string to replace FindTarget with. + @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^' + immediately before it. + @param[in] ParameterReplacing If TRUE will add "" around items with spaces. + + @retval EFI_INVALID_PARAMETER SourceString was NULL. + @retval EFI_INVALID_PARAMETER NewString was NULL. + @retval EFI_INVALID_PARAMETER FindTarget was NULL. + @retval EFI_INVALID_PARAMETER ReplaceWith was NULL. + @retval EFI_INVALID_PARAMETER FindTarget had length < 1. + @retval EFI_INVALID_PARAMETER SourceString had length < 1. + @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold + the new string (truncation occurred). + @retval EFI_SUCCESS The string was successfully copied with replacement. +**/ +EFI_STATUS +EFIAPI +ShellCopySearchAndReplace( + IN CHAR16 CONST *SourceString, + IN OUT CHAR16 *NewString, + IN UINTN NewSize, + IN CONST CHAR16 *FindTarget, + IN CONST CHAR16 *ReplaceWith, + IN CONST BOOLEAN SkipPreCarrot, + IN CONST BOOLEAN ParameterReplacing + ) +{ + UINTN Size; + CHAR16 *Replace; + + if ( (SourceString == NULL) + || (NewString == NULL) + || (FindTarget == NULL) + || (ReplaceWith == NULL) + || (StrLen(FindTarget) < 1) + || (StrLen(SourceString) < 1) + ){ + return (EFI_INVALID_PARAMETER); + } + Replace = NULL; + if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) { + Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0); + } else { + Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16)); + if (Replace != NULL) { + UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith); + } + } + if (Replace == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + NewString = ZeroMem(NewString, NewSize); + while (*SourceString != CHAR_NULL) { + // + // if we find the FindTarget and either Skip == FALSE or Skip and we + // dont have a carrot do a replace... + // + if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0 + && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot) + ){ + SourceString += StrLen(FindTarget); + Size = StrSize(NewString); + if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) { + FreePool(Replace); + return (EFI_BUFFER_TOO_SMALL); + } + StrCatS(NewString, NewSize/sizeof(CHAR16), Replace); + } else { + Size = StrSize(NewString); + if (Size + sizeof(CHAR16) > NewSize) { + FreePool(Replace); + return (EFI_BUFFER_TOO_SMALL); + } + StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1); + SourceString++; + } + } + FreePool(Replace); + return (EFI_SUCCESS); +} + +/** + Internal worker function to output a string. + + This function will output a string to the correct StdOut. + + @param[in] String The string to print out. + + @retval EFI_SUCCESS The operation was sucessful. + @retval !EFI_SUCCESS The operation failed. +**/ +EFI_STATUS +InternalPrintTo ( + IN CONST CHAR16 *String + ) +{ + UINTN Size; + Size = StrSize(String) - sizeof(CHAR16); + if (Size == 0) { + return (EFI_SUCCESS); + } + if (gEfiShellParametersProtocol != NULL) { + return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String)); + } + if (mEfiShellInterface != NULL) { + if (mEfiShellInterface->RedirArgc == 0) { + // + // Divide in half for old shell. Must be string length not size. + // + Size /=2; // Divide in half only when no redirection. + } + return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String)); + } + ASSERT(FALSE); + return (EFI_UNSUPPORTED); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + if either Row or Col is out of range for the current console, then ASSERT + if Format is NULL, then ASSERT + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col the column to print at + @param[in] Row the row to print at + @param[in] Format the format string + @param[in] Marker the marker for the variable argument list + + @return EFI_SUCCESS The operation was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +InternalShellPrintWorker( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + CHAR16 *ResumeLocation; + CHAR16 *FormatWalker; + UINTN OriginalAttribute; + CHAR16 *mPostReplaceFormat; + CHAR16 *mPostReplaceFormat2; + + mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize)); + mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize)); + + if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) { + SHELL_FREE_NON_NULL(mPostReplaceFormat); + SHELL_FREE_NON_NULL(mPostReplaceFormat2); + return (EFI_OUT_OF_RESOURCES); + } + + Status = EFI_SUCCESS; + OriginalAttribute = gST->ConOut->Mode->Attribute; + + // + // Back and forth each time fixing up 1 of our flags... + // + Status = ShellCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE); + ASSERT_EFI_ERROR(Status); + + // + // Use the last buffer from replacing to print from... + // + UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker); + + if (Col != -1 && Row != -1) { + Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row); + } + + FormatWalker = mPostReplaceFormat2; + while (*FormatWalker != CHAR_NULL) { + // + // Find the next attribute change request + // + ResumeLocation = StrStr(FormatWalker, L"%"); + if (ResumeLocation != NULL) { + *ResumeLocation = CHAR_NULL; + } + // + // print the current FormatWalker string + // + if (StrLen(FormatWalker)>0) { + Status = InternalPrintTo(FormatWalker); + if (EFI_ERROR(Status)) { + break; + } + } + + // + // update the attribute + // + if (ResumeLocation != NULL) { + if ((ResumeLocation != mPostReplaceFormat2) && (*(ResumeLocation-1) == L'^')) { + // + // Move cursor back 1 position to overwrite the ^ + // + gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow); + + // + // Print a simple '%' symbol + // + Status = InternalPrintTo(L"%"); + ResumeLocation = ResumeLocation - 1; + } else { + switch (*(ResumeLocation+1)) { + case (L'N'): + gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute); + break; + case (L'E'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'H'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'B'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTBLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'V'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTGREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + default: + // + // Print a simple '%' symbol + // + Status = InternalPrintTo(L"%"); + if (EFI_ERROR(Status)) { + break; + } + ResumeLocation = ResumeLocation - 1; + break; + } + } + } else { + // + // reset to normal now... + // + break; + } + + // + // update FormatWalker to Resume + 2 (skip the % and the indicator) + // + FormatWalker = ResumeLocation + 2; + } + + gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute); + + SHELL_FREE_NON_NULL(mPostReplaceFormat); + SHELL_FREE_NON_NULL(mPostReplaceFormat2); + return (Status); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string. + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + If either Row or Col is out of range for the current console, then ASSERT. + If Format is NULL, then ASSERT. + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col the column to print at + @param[in] Row the row to print at + @param[in] Format the format string + @param[in] ... The variable argument list. + + @return EFI_SUCCESS The printing was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +ShellPrintEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + EFI_STATUS RetVal; + if (Format == NULL) { + return (EFI_INVALID_PARAMETER); + } + VA_START (Marker, Format); + RetVal = InternalShellPrintWorker(Col, Row, Format, Marker); + VA_END(Marker); + return(RetVal); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string. + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + If either Row or Col is out of range for the current console, then ASSERT. + If Format is NULL, then ASSERT. + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal. + %H - Set output attribute to highlight. + %E - Set output attribute to error. + %B - Set output attribute to blue color. + %V - Set output attribute to green color. + + Note: The background color is controlled by the shell command cls. + + @param[in] Col The column to print at. + @param[in] Row The row to print at. + @param[in] Language The language of the string to retrieve. If this parameter + is NULL, then the current platform language is used. + @param[in] HiiFormatStringId The format string Id for getting from Hii. + @param[in] HiiFormatHandle The format string Handle for getting from Hii. + @param[in] ... The variable argument list. + + @return EFI_SUCCESS The printing was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +ShellPrintHiiEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR8 *Language OPTIONAL, + IN CONST EFI_STRING_ID HiiFormatStringId, + IN CONST EFI_HANDLE HiiFormatHandle, + ... + ) +{ + VA_LIST Marker; + CHAR16 *HiiFormatString; + EFI_STATUS RetVal; + + RetVal = EFI_DEVICE_ERROR; + + VA_START (Marker, HiiFormatHandle); + HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language); + if (HiiFormatString != NULL) { + RetVal = InternalShellPrintWorker (Col, Row, HiiFormatString, Marker); + SHELL_FREE_NON_NULL (HiiFormatString); + } + VA_END(Marker); + + return (RetVal); +} + +/** + Function to determine if a given filename represents a file or a directory. + + @param[in] DirName Path to directory to test. + + @retval EFI_SUCCESS The Path represents a directory + @retval EFI_NOT_FOUND The Path does not represent a directory + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @return The path failed to open +**/ +EFI_STATUS +EFIAPI +ShellIsDirectory( + IN CONST CHAR16 *DirName + ) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE Handle; + CHAR16 *TempLocation; + CHAR16 *TempLocation2; + + ASSERT(DirName != NULL); + + Handle = NULL; + TempLocation = NULL; + + Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + // + // try good logic first. + // + if (gEfiShellProtocol != NULL) { + TempLocation = StrnCatGrow(&TempLocation, NULL, DirName, 0); + if (TempLocation == NULL) { + ShellCloseFile(&Handle); + return (EFI_OUT_OF_RESOURCES); + } + TempLocation2 = StrStr(TempLocation, L":"); + if (TempLocation2 != NULL && StrLen(StrStr(TempLocation, L":")) == 2) { + *(TempLocation2+1) = CHAR_NULL; + } + if (gEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) { + FreePool(TempLocation); + return (EFI_SUCCESS); + } + FreePool(TempLocation); + } else { + // + // probably a map name?!?!!? + // + TempLocation = StrStr(DirName, L"\\"); + if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) { + return (EFI_SUCCESS); + } + } + return (Status); + } + + if (FileHandleIsDirectory(Handle) == EFI_SUCCESS) { + ShellCloseFile(&Handle); + return (EFI_SUCCESS); + } + ShellCloseFile(&Handle); + return (EFI_NOT_FOUND); +} + +/** + Function to determine if a given filename represents a file. + + @param[in] Name Path to file to test. + + @retval EFI_SUCCESS The Path represents a file. + @retval EFI_NOT_FOUND The Path does not represent a file. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellIsFile( + IN CONST CHAR16 *Name + ) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE Handle; + + ASSERT(Name != NULL); + + Handle = NULL; + + Status = ShellOpenFileByName(Name, &Handle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) { + return (Status); + } + + if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) { + ShellCloseFile(&Handle); + return (EFI_SUCCESS); + } + ShellCloseFile(&Handle); + return (EFI_NOT_FOUND); +} + +/** + Function to determine if a given filename represents a file. + + This will search the CWD and then the Path. + + If Name is NULL, then ASSERT. + + @param[in] Name Path to file to test. + + @retval EFI_SUCCESS The Path represents a file. + @retval EFI_NOT_FOUND The Path does not represent a file. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellIsFileInPath( + IN CONST CHAR16 *Name + ) +{ + CHAR16 *NewName; + EFI_STATUS Status; + + if (!EFI_ERROR(ShellIsFile(Name))) { + return (EFI_SUCCESS); + } + + NewName = ShellFindFilePath(Name); + if (NewName == NULL) { + return (EFI_NOT_FOUND); + } + Status = ShellIsFile(NewName); + FreePool(NewName); + return (Status); +} + +/** + Function return the number converted from a hex representation of a number. + + Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid + result. Use ShellConvertStringToUint64 instead. + + @param[in] String String representation of a number. + + @return The unsigned integer result of the conversion. + @retval (UINTN)(-1) An error occured. +**/ +UINTN +EFIAPI +ShellHexStrToUintn( + IN CONST CHAR16 *String + ) +{ + UINT64 RetVal; + + if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, TRUE, TRUE))) { + return ((UINTN)RetVal); + } + + return ((UINTN)(-1)); +} + +/** + Function to determine whether a string is decimal or hex representation of a number + and return the number converted from the string. Spaces are always skipped. + + @param[in] String String representation of a number + + @return the number + @retval (UINTN)(-1) An error ocurred. +**/ +UINTN +EFIAPI +ShellStrToUintn( + IN CONST CHAR16 *String + ) +{ + UINT64 RetVal; + BOOLEAN Hex; + + Hex = FALSE; + + if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE, FALSE)) { + Hex = TRUE; + } + + if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, Hex, TRUE))) { + return ((UINTN)RetVal); + } + return ((UINTN)(-1)); +} + +/** + Safely append 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 ASSERT() + 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 +StrnCatGrow ( + IN OUT CHAR16 **Destination, + IN OUT UINTN *CurrentSize, + IN CONST CHAR16 *Source, + IN UINTN Count + ) +{ + UINTN DestinationStartSize; + UINTN NewSize; + + // + // ASSERTs + // + ASSERT(Destination != NULL); + + // + // If there's nothing to do then just return Destination + // + if (Source == NULL) { + return (*Destination); + } + + // + // allow for un-initialized pointers, based on size being 0 + // + if (CurrentSize != NULL && *CurrentSize == 0) { + *Destination = NULL; + } + + // + // 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 = StrLen(Source); + } + + // + // Test and grow if required + // + if (CurrentSize != NULL) { + NewSize = *CurrentSize; + if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) { + while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) { + NewSize += 2 * Count * sizeof(CHAR16); + } + *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination); + *CurrentSize = NewSize; + } + } else { + NewSize = (Count+1)*sizeof(CHAR16); + *Destination = AllocateZeroPool(NewSize); + } + + // + // Now use standard StrnCat on a big enough buffer + // + if (*Destination == NULL) { + return (NULL); + } + + StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count); + return *Destination; +} + +/** + Prompt the user and return the resultant answer to the requestor. + + This function will display the requested question on the shell prompt and then + wait for an appropriate answer to be input from the console. + + if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue + or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE. + + if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type + CHAR16*. + + In either case *Response must be callee freed if Response was not NULL; + + @param Type What type of question is asked. This is used to filter the input + to prevent invalid answers to question. + @param Prompt Pointer to string prompt to use to request input. + @param Response Pointer to Response which will be populated upon return. + + @retval EFI_SUCCESS The operation was sucessful. + @retval EFI_UNSUPPORTED The operation is not supported as requested. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @return other The operation failed. +**/ +EFI_STATUS +EFIAPI +ShellPromptForResponse ( + IN SHELL_PROMPT_REQUEST_TYPE Type, + IN CHAR16 *Prompt OPTIONAL, + IN OUT VOID **Response OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINTN EventIndex; + SHELL_PROMPT_RESPONSE *Resp; + UINTN Size; + CHAR16 *Buffer; + + Status = EFI_UNSUPPORTED; + Resp = NULL; + Buffer = NULL; + Size = 0; + if (Type != ShellPromptResponseTypeFreeform) { + Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE)); + if (Resp == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + } + + switch(Type) { + case ShellPromptResponseTypeQuitContinue: + if (Prompt != NULL) { + ShellPrintEx(-1, -1, L"%s", Prompt); + } + // + // wait for valid response + // + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR(Status)) { + break; + } + ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar); + if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') { + *Resp = ShellPromptResponseQuit; + } else { + *Resp = ShellPromptResponseContinue; + } + break; + case ShellPromptResponseTypeYesNoCancel: + if (Prompt != NULL) { + ShellPrintEx(-1, -1, L"%s", Prompt); + } + // + // wait for valid response + // + *Resp = ShellPromptResponseMax; + while (*Resp == ShellPromptResponseMax) { + if (ShellGetExecutionBreakFlag()) { + Status = EFI_ABORTED; + break; + } + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR(Status)) { + break; + } + ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar); + switch (Key.UnicodeChar) { + case L'Y': + case L'y': + *Resp = ShellPromptResponseYes; + break; + case L'N': + case L'n': + *Resp = ShellPromptResponseNo; + break; + case L'C': + case L'c': + *Resp = ShellPromptResponseCancel; + break; + } + } + break; + case ShellPromptResponseTypeYesNoAllCancel: + if (Prompt != NULL) { + ShellPrintEx(-1, -1, L"%s", Prompt); + } + // + // wait for valid response + // + *Resp = ShellPromptResponseMax; + while (*Resp == ShellPromptResponseMax) { + if (ShellGetExecutionBreakFlag()) { + Status = EFI_ABORTED; + break; + } + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR(Status)) { + break; + } + + if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) { + ShellPrintEx (-1, -1, L"%c", Key.UnicodeChar); + } + + switch (Key.UnicodeChar) { + case L'Y': + case L'y': + *Resp = ShellPromptResponseYes; + break; + case L'N': + case L'n': + *Resp = ShellPromptResponseNo; + break; + case L'A': + case L'a': + *Resp = ShellPromptResponseAll; + break; + case L'C': + case L'c': + *Resp = ShellPromptResponseCancel; + break; + } + } + break; + case ShellPromptResponseTypeEnterContinue: + case ShellPromptResponseTypeAnyKeyContinue: + if (Prompt != NULL) { + ShellPrintEx(-1, -1, L"%s", Prompt); + } + // + // wait for valid response + // + *Resp = ShellPromptResponseMax; + while (*Resp == ShellPromptResponseMax) { + if (ShellGetExecutionBreakFlag()) { + Status = EFI_ABORTED; + break; + } + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + if (Type == ShellPromptResponseTypeEnterContinue) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR(Status)) { + break; + } + ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar); + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + *Resp = ShellPromptResponseContinue; + break; + } + } + if (Type == ShellPromptResponseTypeAnyKeyContinue) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + ASSERT_EFI_ERROR(Status); + *Resp = ShellPromptResponseContinue; + break; + } + } + break; + case ShellPromptResponseTypeYesNo: + if (Prompt != NULL) { + ShellPrintEx(-1, -1, L"%s", Prompt); + } + // + // wait for valid response + // + *Resp = ShellPromptResponseMax; + while (*Resp == ShellPromptResponseMax) { + if (ShellGetExecutionBreakFlag()) { + Status = EFI_ABORTED; + break; + } + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR(Status)) { + break; + } + ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar); + switch (Key.UnicodeChar) { + case L'Y': + case L'y': + *Resp = ShellPromptResponseYes; + break; + case L'N': + case L'n': + *Resp = ShellPromptResponseNo; + break; + } + } + break; + case ShellPromptResponseTypeFreeform: + if (Prompt != NULL) { + ShellPrintEx(-1, -1, L"%s", Prompt); + } + while(1) { + if (ShellGetExecutionBreakFlag()) { + Status = EFI_ABORTED; + break; + } + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR(Status)) { + break; + } + ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar); + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } + ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL)); + StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1); + } + break; + // + // This is the location to add new prompt types. + // If your new type loops remember to add ExecutionBreak support. + // + default: + ASSERT(FALSE); + } + + if (Response != NULL) { + if (Resp != NULL) { + *Response = Resp; + } else if (Buffer != NULL) { + *Response = Buffer; + } + } else { + if (Resp != NULL) { + FreePool(Resp); + } + if (Buffer != NULL) { + FreePool(Buffer); + } + } + + ShellPrintEx(-1, -1, L"\r\n"); + return (Status); +} + +/** + Prompt the user and return the resultant answer to the requestor. + + This function is the same as ShellPromptForResponse, except that the prompt is + automatically pulled from HII. + + @param Type What type of question is asked. This is used to filter the input + to prevent invalid answers to question. + @param[in] HiiFormatStringId The format string Id for getting from Hii. + @param[in] HiiFormatHandle The format string Handle for getting from Hii. + @param Response Pointer to Response which will be populated upon return. + + @retval EFI_SUCCESS the operation was sucessful. + @return other the operation failed. + + @sa ShellPromptForResponse +**/ +EFI_STATUS +EFIAPI +ShellPromptForResponseHii ( + IN SHELL_PROMPT_REQUEST_TYPE Type, + IN CONST EFI_STRING_ID HiiFormatStringId, + IN CONST EFI_HANDLE HiiFormatHandle, + IN OUT VOID **Response + ) +{ + CHAR16 *Prompt; + EFI_STATUS Status; + + Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL); + Status = ShellPromptForResponse(Type, Prompt, Response); + FreePool(Prompt); + return (Status); +} + +/** + Function to determin if an entire string is a valid number. + + If Hex it must be preceeded with a 0x or has ForceHex, set TRUE. + + @param[in] String The string to evaluate. + @param[in] ForceHex TRUE - always assume hex. + @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going. + @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise. + + @retval TRUE It is all numeric (dec/hex) characters. + @retval FALSE There is a non-numeric character. +**/ +BOOLEAN +InternalShellIsHexOrDecimalNumber ( + IN CONST CHAR16 *String, + IN CONST BOOLEAN ForceHex, + IN CONST BOOLEAN StopAtSpace, + IN CONST BOOLEAN TimeNumbers + ) +{ + BOOLEAN Hex; + BOOLEAN LeadingZero; + + if (String == NULL) { + return FALSE; + } + + // + // chop off a single negative sign + // + if (*String == L'-') { + String++; + } + + if (*String == CHAR_NULL) { + return FALSE; + } + + // + // chop leading zeroes + // + LeadingZero = FALSE; + while(*String == L'0'){ + String++; + LeadingZero = TRUE; + } + // + // allow '0x' or '0X', but not 'x' or 'X' + // + if (*String == L'x' || *String == L'X') { + if (!LeadingZero) { + // + // we got an x without a preceeding 0 + // + return (FALSE); + } + String++; + Hex = TRUE; + } else if (ForceHex) { + Hex = TRUE; + } else { + Hex = FALSE; + } + + // + // loop through the remaining characters and use the lib function + // + for ( ; *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){ + if (TimeNumbers && (String[0] == L':')) { + continue; + } + if (Hex) { + if (!ShellIsHexaDecimalDigitCharacter(*String)) { + return (FALSE); + } + } else { + if (!ShellIsDecimalDigitCharacter(*String)) { + return (FALSE); + } + } + } + + return (TRUE); +} + +/** + Function to determine if a given filename exists. + + @param[in] Name Path to test. + + @retval EFI_SUCCESS The Path represents a file. + @retval EFI_NOT_FOUND The Path does not represent a file. + @retval other The path failed to open. +**/ +EFI_STATUS +EFIAPI +ShellFileExists( + IN CONST CHAR16 *Name + ) +{ + EFI_STATUS Status; + EFI_SHELL_FILE_INFO *List; + + ASSERT(Name != NULL); + + List = NULL; + Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List); + if (EFI_ERROR(Status)) { + return (Status); + } + + ShellCloseFileMetaArg(&List); + + return (EFI_SUCCESS); +} + +/** + 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 +InternalShellHexCharToUintn ( + IN CHAR16 Char + ) +{ + if (ShellIsDecimalDigitCharacter (Char)) { + return Char - L'0'; + } + + return (10 + CharToUpper (Char) - L'A'); +} + +/** + 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 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. + + @param[in] String A pointer to a Null-terminated Unicode string. + @param[out] Value Upon a successful return the value of the conversion. + @param[in] StopAtSpace FALSE to skip spaces. + + @retval EFI_SUCCESS The conversion was successful. + @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid. + @retval EFI_DEVICE_ERROR An overflow occured. +**/ +EFI_STATUS +InternalShellStrHexToUint64 ( + IN CONST CHAR16 *String, + OUT UINT64 *Value, + IN CONST BOOLEAN StopAtSpace + ) +{ + UINT64 Result; + + if (String == NULL || StrSize(String) == 0 || Value == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // 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') { + return 0; + } + // + // Skip the 'X' + // + String++; + } + + Result = 0; + + // + // there is a space where there should't be + // + if (*String == L' ') { + return (EFI_INVALID_PARAMETER); + } + + while (ShellIsHexaDecimalDigitCharacter (*String)) { + // + // If the Hex Number represented by String overflows according + // to the range defined by UINT64, then return EFI_DEVICE_ERROR. + // + if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) { +// if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) { + return (EFI_DEVICE_ERROR); + } + + Result = (LShiftU64(Result, 4)); + Result += InternalShellHexCharToUintn (*String); + String++; + + // + // stop at spaces if requested + // + if (StopAtSpace && *String == L' ') { + break; + } + } + + *Value = Result; + return (EFI_SUCCESS); +} + +/** + 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 has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + + @param[in] String A pointer to a Null-terminated Unicode string. + @param[out] Value Upon a successful return the value of the conversion. + @param[in] StopAtSpace FALSE to skip spaces. + + @retval EFI_SUCCESS The conversion was successful. + @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid. + @retval EFI_DEVICE_ERROR An overflow occured. +**/ +EFI_STATUS +InternalShellStrDecimalToUint64 ( + IN CONST CHAR16 *String, + OUT UINT64 *Value, + IN CONST BOOLEAN StopAtSpace + ) +{ + UINT64 Result; + + if (String == NULL || StrSize (String) == 0 || Value == NULL) { + return (EFI_INVALID_PARAMETER); + } + + // + // 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++; + } + + Result = 0; + + // + // Stop upon space if requested + // (if the whole value was 0) + // + if (StopAtSpace && *String == L' ') { + *Value = Result; + return (EFI_SUCCESS); + } + + while (ShellIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according + // to the range defined by UINT64, then return EFI_DEVICE_ERROR. + // + + if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) { + return (EFI_DEVICE_ERROR); + } + + Result = MultU64x32(Result, 10) + (*String - L'0'); + String++; + + // + // Stop at spaces if requested + // + if (StopAtSpace && *String == L' ') { + break; + } + } + + *Value = Result; + + return (EFI_SUCCESS); +} + +/** + Function to verify and convert a string to its numerical value. + + If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE. + + @param[in] String The string to evaluate. + @param[out] Value Upon a successful return the value of the conversion. + @param[in] ForceHex TRUE - always assume hex. + @param[in] StopAtSpace FALSE to skip spaces. + + @retval EFI_SUCCESS The conversion was successful. + @retval EFI_INVALID_PARAMETER String contained an invalid character. + @retval EFI_NOT_FOUND String was a number, but Value was NULL. +**/ +EFI_STATUS +EFIAPI +ShellConvertStringToUint64( + IN CONST CHAR16 *String, + OUT UINT64 *Value, + IN CONST BOOLEAN ForceHex, + IN CONST BOOLEAN StopAtSpace + ) +{ + UINT64 RetVal; + CONST CHAR16 *Walker; + EFI_STATUS Status; + BOOLEAN Hex; + + Hex = ForceHex; + + if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) { + if (!Hex) { + Hex = TRUE; + if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) { + return (EFI_INVALID_PARAMETER); + } + } else { + return (EFI_INVALID_PARAMETER); + } + } + + // + // Chop off leading spaces + // + for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++); + + // + // make sure we have something left that is numeric. + // + if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace, FALSE)) { + return (EFI_INVALID_PARAMETER); + } + + // + // do the conversion. + // + if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){ + Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace); + } else { + Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace); + } + + if (Value == NULL && !EFI_ERROR(Status)) { + return (EFI_NOT_FOUND); + } + + if (Value != NULL) { + *Value = RetVal; + } + + return (Status); +} + +/** + Function to determin if an entire string is a valid number. + + If Hex it must be preceeded with a 0x or has ForceHex, set TRUE. + + @param[in] String The string to evaluate. + @param[in] ForceHex TRUE - always assume hex. + @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going. + + @retval TRUE It is all numeric (dec/hex) characters. + @retval FALSE There is a non-numeric character. +**/ +BOOLEAN +EFIAPI +ShellIsHexOrDecimalNumber ( + IN CONST CHAR16 *String, + IN CONST BOOLEAN ForceHex, + IN CONST BOOLEAN StopAtSpace + ) +{ + if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) { + return (TRUE); + } + return (FALSE); +} + +/** + Function to read a single line from a SHELL_FILE_HANDLE. 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 SHELL_FILE_HANDLE 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. + @retval NULL There was not enough memory available. + + @sa ShellFileHandleReadLine +**/ +CHAR16* +EFIAPI +ShellFileHandleReturnLine( + IN SHELL_FILE_HANDLE Handle, + IN OUT BOOLEAN *Ascii + ) +{ + CHAR16 *RetVal; + UINTN Size; + EFI_STATUS Status; + + Size = 0; + RetVal = NULL; + + Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii); + if (Status == EFI_BUFFER_TOO_SMALL) { + RetVal = AllocateZeroPool(Size); + if (RetVal == NULL) { + return (NULL); + } + Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii); + + } + if (Status == EFI_END_OF_FILE && RetVal != NULL && *RetVal != CHAR_NULL) { + Status = EFI_SUCCESS; + } + 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 SHELL_FILE_HANDLE. + + 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. + + NOTE: LINES THAT ARE RETURNED BY THIS FUNCTION ARE UCS2, EVEN IF THE FILE BEING READ + IS IN ASCII FORMAT. + + @param[in] Handle SHELL_FILE_HANDLE to read from. + @param[in, out] Buffer The pointer to buffer to read into. If this function + returns EFI_SUCCESS, then on output Buffer will + contain a UCS2 string, even if the file being + read is ASCII. + @param[in, out] Size On input, pointer to number of bytes in Buffer. + On output, unchanged unless Buffer is too small + to contain the next line of the file. In that + case Size is set to the number of bytes needed + to hold the next line of the file (as a UCS2 + string, even if it is an ASCII file). + @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_END_OF_FILE There are no more lines in the file. + @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. +**/ +EFI_STATUS +EFIAPI +ShellFileHandleReadLine( + IN SHELL_FILE_HANDLE Handle, + IN OUT CHAR16 *Buffer, + IN OUT UINTN *Size, + IN BOOLEAN Truncate, + IN OUT BOOLEAN *Ascii + ) +{ + EFI_STATUS Status; + CHAR16 CharBuffer; + UINTN CharSize; + UINTN CountSoFar; + UINT64 OriginalFilePosition; + + + if (Handle == NULL + ||Size == NULL + ){ + return (EFI_INVALID_PARAMETER); + } + if (Buffer == NULL) { + ASSERT(*Size == 0); + } else { + *Buffer = CHAR_NULL; + } + gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition); + if (OriginalFilePosition == 0) { + CharSize = sizeof(CHAR16); + Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer); + ASSERT_EFI_ERROR(Status); + if (CharBuffer == gUnicodeFileTag) { + *Ascii = FALSE; + } else { + *Ascii = TRUE; + gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition); + } + } + + if (*Ascii) { + CharSize = sizeof(CHAR8); + } else { + CharSize = sizeof(CHAR16); + } + for (CountSoFar = 0;;CountSoFar++){ + CharBuffer = 0; + Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer); + if ( EFI_ERROR(Status) + || CharSize == 0 + || (CharBuffer == L'\n' && !(*Ascii)) + || (CharBuffer == '\n' && *Ascii) + ){ + if (CharSize == 0) { + Status = EFI_END_OF_FILE; + } + break; + } + // + // if we have space save it... + // + if ((CountSoFar+1)*sizeof(CHAR16) < *Size){ + ASSERT(Buffer != NULL); + ((CHAR16*)Buffer)[CountSoFar] = CharBuffer; + ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL; + } + } + + // + // if we ran out of space tell when... + // + if ((CountSoFar+1)*sizeof(CHAR16) > *Size){ + *Size = (CountSoFar+1)*sizeof(CHAR16); + if (!Truncate) { + gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition); + } else { + DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine")); + } + return (EFI_BUFFER_TOO_SMALL); + } + while(Buffer[StrLen(Buffer)-1] == L'\r') { + Buffer[StrLen(Buffer)-1] = CHAR_NULL; + } + + return (Status); +} + +/** + Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function. + + @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed. + @param[in] SectionToGetHelpOn Pointer to the section specifier(s). + @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints + the help content only. + @retval EFI_DEVICE_ERROR The help data format was incorrect. + @retval EFI_NOT_FOUND The help data could not be found. + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +ShellPrintHelp ( + IN CONST CHAR16 *CommandToGetHelpOn, + IN CONST CHAR16 *SectionToGetHelpOn, + IN BOOLEAN PrintCommandText + ) +{ + EFI_STATUS Status; + CHAR16 *OutText; + + OutText = NULL; + + // + // Get the string to print based + // + Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText); + + // + // make sure we got a valid string + // + if (EFI_ERROR(Status)){ + return Status; + } + if (OutText == NULL || StrLen(OutText) == 0) { + return EFI_NOT_FOUND; + } + + // + // Chop off trailing stuff we dont need + // + while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') { + OutText[StrLen(OutText)-1] = CHAR_NULL; + } + + // + // Print this out to the console + // + if (PrintCommandText) { + ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText); + } else { + ShellPrintEx(-1, -1, L"%N%s\r\n", OutText); + } + + SHELL_FREE_NON_NULL(OutText); + + return EFI_SUCCESS; +} + +/** + Function to delete a file by name + + @param[in] FileName Pointer to file name to delete. + + @retval EFI_SUCCESS the file was deleted sucessfully + @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not + deleted + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + @retval EFI_NOT_FOUND The specified file could not be found on the + device or the file system could not be found + on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the + medium is no longer supported. + @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_OUT_OF_RESOURCES Not enough resources were available to open the + file. + @retval other The file failed to open +**/ +EFI_STATUS +EFIAPI +ShellDeleteFileByName( + IN CONST CHAR16 *FileName + ) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE FileHandle; + + Status = ShellFileExists(FileName); + + if (Status == EFI_SUCCESS){ + Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0); + if (Status == EFI_SUCCESS){ + Status = ShellDeleteFile(&FileHandle); + } + } + + return(Status); + +} + +/** + Cleans off all the quotes in the string. + + @param[in] OriginalString pointer to the string to be cleaned. + @param[out] CleanString The new string with all quotes removed. + Memory allocated in the function and free + by caller. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +InternalShellStripQuotes ( + IN CONST CHAR16 *OriginalString, + OUT CHAR16 **CleanString + ) +{ + CHAR16 *Walker; + + if (OriginalString == NULL || CleanString == NULL) { + return EFI_INVALID_PARAMETER; + } + + *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString); + if (*CleanString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { + if (*Walker == L'\"') { + CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); + } + } + + return EFI_SUCCESS; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.h new file mode 100644 index 0000000..bcada33 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.h @@ -0,0 +1,96 @@ +/** @file + Provides interface to shell functionality for shell commands and applications. + + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_LIB_INTERNAL_H_ +#define _UEFI_SHELL_LIB_INTERNAL_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + EFI_SHELL_GET_FILE_INFO GetFileInfo; + EFI_SHELL_SET_FILE_INFO SetFileInfo; + EFI_SHELL_READ_FILE ReadFile; + EFI_SHELL_WRITE_FILE WriteFile; + EFI_SHELL_CLOSE_FILE CloseFile; + EFI_SHELL_DELETE_FILE DeleteFile; + EFI_SHELL_GET_FILE_POSITION GetFilePosition; + EFI_SHELL_SET_FILE_POSITION SetFilePosition; + EFI_SHELL_FLUSH_FILE FlushFile; + EFI_SHELL_GET_FILE_SIZE GetFileSize; +} FILE_HANDLE_FUNCTION_MAP; + +/** + Function to determin if an entire string is a valid number. + + If Hex it must be preceeded with a 0x or has ForceHex, set TRUE. + + @param[in] String The string to evaluate. + @param[in] ForceHex TRUE - always assume hex. + @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going. + @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise. + + @retval TRUE It is all numeric (dec/hex) characters. + @retval FALSE There is a non-numeric character. +**/ +BOOLEAN +InternalShellIsHexOrDecimalNumber ( + IN CONST CHAR16 *String, + IN CONST BOOLEAN ForceHex, + IN CONST BOOLEAN StopAtSpace, + IN CONST BOOLEAN TimeNumbers + ); + +/** + Cleans off all the quotes in the string. + + @param[in] OriginalString pointer to the string to be cleaned. + @param[out] CleanString The new string with all quotes removed. + Memory allocated in the function and free + by caller. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +InternalShellStripQuotes ( + IN CONST CHAR16 *OriginalString, + OUT CHAR16 **CleanString + ); + + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.inf new file mode 100644 index 0000000..065a179 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellLib/UefiShellLib.inf @@ -0,0 +1,70 @@ +## @file +# Provides interface to shell functionality for shell commands and applications. +# +# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellLib + FILE_GUID = 449D0F00-2148-4a43-9836-F10B3980ECF5 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.2 + LIBRARY_CLASS = ShellLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER DXE_DRIVER + CONSTRUCTOR = ShellLibConstructor + DESTRUCTOR = ShellLibDestructor + +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# + +[Sources.common] + UefiShellLib.c + UefiShellLib.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + DevicePathLib + BaseLib + BaseMemoryLib + DebugLib + FileHandleLib + PrintLib + UefiLib + HiiLib + SortLib + +[Protocols] + gEfiUnicodeCollation2ProtocolGuid ## CONSUMES + + # shell 2.0 + gEfiShellProtocolGuid ## SOMETIMES_CONSUMES + gEfiShellParametersProtocolGuid ## SOMETIMES_CONSUMES + + # 'old' shell + gEfiShellEnvironment2Guid ## SOMETIMES_CONSUMES + gEfiShellInterfaceGuid ## SOMETIMES_CONSUMES + +[Guids] + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID + gEfiShellEnvironment2ExtGuid ## SOMETIMES_CONSUMES ## GUID + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize ## CONSUMES + gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize ## CONSUMES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c new file mode 100644 index 0000000..8e96630 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c @@ -0,0 +1,1447 @@ +/** @file + The implementation for Shell command ifconfig based on IP4Config2 protocol. + + (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellNetwork1CommandsLib.h" + +typedef enum { + IfConfigOpList = 1, + IfConfigOpSet = 2, + IfConfigOpClear = 3 +} IFCONFIG_OPCODE; + +typedef enum { + VarCheckReserved = -1, + VarCheckOk = 0, + VarCheckDuplicate, + VarCheckConflict, + VarCheckUnknown, + VarCheckLackValue, + VarCheckOutOfMem +} VAR_CHECK_CODE; + +typedef enum { + FlagTypeSingle = 0, + FlagTypeNeedVar, + FlagTypeNeedSet, + FlagTypeSkipUnknown +} VAR_CHECK_FLAG_TYPE; + +#define MACADDRMAXSIZE 32 + +typedef struct _IFCONFIG_INTERFACE_CB { + EFI_HANDLE NicHandle; + LIST_ENTRY Link; + EFI_IP4_CONFIG2_PROTOCOL *IfCfg; + EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo; + EFI_IP4_CONFIG2_POLICY Policy; + UINT32 DnsCnt; + EFI_IPv4_ADDRESS DnsAddr[1]; +} IFCONFIG_INTERFACE_CB; + +typedef struct _ARG_LIST ARG_LIST; + +struct _ARG_LIST { + ARG_LIST *Next; + CHAR16 *Arg; +}; + +typedef struct _IFCONFIG4_PRIVATE_DATA { + LIST_ENTRY IfList; + + UINT32 OpCode; + CHAR16 *IfName; + ARG_LIST *VarArg; +} IFCONFIG_PRIVATE_DATA; + +typedef struct _VAR_CHECK_ITEM{ + CHAR16 *FlagStr; + UINT32 FlagID; + UINT32 ConflictMask; + VAR_CHECK_FLAG_TYPE FlagType; +} VAR_CHECK_ITEM; + +SHELL_PARAM_ITEM mIfConfigCheckList[] = { + { + L"-b", + TypeFlag + }, + { + L"-l", + TypeValue + }, + { + L"-r", + TypeValue + }, + { + L"-c", + TypeValue + }, + { + L"-s", + TypeMaxValue + }, + { + NULL, + TypeMax + }, +}; + +VAR_CHECK_ITEM mSetCheckList[] = { + { + L"static", + 0x00000001, + 0x00000001, + FlagTypeSingle + }, + { + L"dhcp", + 0x00000002, + 0x00000001, + FlagTypeSingle + }, + { + L"dns", + 0x00000008, + 0x00000004, + FlagTypeSingle + }, + { + NULL, + 0x0, + 0x0, + FlagTypeSkipUnknown + }, +}; + +STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT"; + +/** + Free the ARG_LIST. + + @param List Pointer to ARG_LIST to free. +**/ +VOID +FreeArgList ( + ARG_LIST *List +) +{ + ARG_LIST *Next; + while (List->Next != NULL) { + Next = List->Next; + FreePool (List); + List = Next; + } + + FreePool (List); +} + +/** + Split a string with specified separator and save the substring to a list. + + @param[in] String The pointer of the input string. + @param[in] Separator The specified separator. + + @return The pointer of headnode of ARG_LIST. + +**/ +ARG_LIST * +SplitStrToList ( + IN CONST CHAR16 *String, + IN CHAR16 Separator + ) +{ + CHAR16 *Str; + CHAR16 *ArgStr; + ARG_LIST *ArgList; + ARG_LIST *ArgNode; + + if (*String == L'\0') { + return NULL; + } + + // + // Copy the CONST string to a local copy. + // + Str = AllocateCopyPool (StrSize (String), String); + if (Str == NULL) { + return NULL; + } + ArgStr = Str; + + // + // init a node for the list head. + // + ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST)); + if (ArgNode == NULL) { + return NULL; + } + ArgList = ArgNode; + + // + // Split the local copy and save in the list node. + // + while (*Str != L'\0') { + if (*Str == Separator) { + *Str = L'\0'; + ArgNode->Arg = ArgStr; + ArgStr = Str + 1; + ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST)); + if (ArgNode->Next == NULL) { + // + // Free the local copy of string stored in the first node + // + FreePool (ArgList->Arg); + FreeArgList (ArgList); + return NULL; + } + ArgNode = ArgNode->Next; + } + + Str++; + } + + ArgNode->Arg = ArgStr; + ArgNode->Next = NULL; + + return ArgList; +} + +/** + Check the correctness of input Args with '-s' option. + + @param[in] CheckList The pointer of VAR_CHECK_ITEM array. + @param[in] Name The pointer of input arg. + @param[in] Init The switch to execute the check. + + @return VarCheckOk Valid parameter or Initialize check successfully. + @return VarCheckDuplicate Duplicated parameter happened. + @return VarCheckConflict Conflicted parameter happened + @return VarCheckUnknown Unknown parameter. + +**/ +VAR_CHECK_CODE +IfConfigRetriveCheckListByName( + IN VAR_CHECK_ITEM *CheckList, + IN CHAR16 *Name, + IN BOOLEAN Init +) +{ + STATIC UINT32 CheckDuplicate; + STATIC UINT32 CheckConflict; + VAR_CHECK_CODE RtCode; + UINT32 Index; + VAR_CHECK_ITEM Arg; + + if (Init) { + CheckDuplicate = 0; + CheckConflict = 0; + return VarCheckOk; + } + + RtCode = VarCheckOk; + Index = 0; + Arg = CheckList[Index]; + + // + // Check the Duplicated/Conflicted/Unknown input Args. + // + while (Arg.FlagStr != NULL) { + if (StrCmp (Arg.FlagStr, Name) == 0) { + + if (CheckDuplicate & Arg.FlagID) { + RtCode = VarCheckDuplicate; + break; + } + + if (CheckConflict & Arg.ConflictMask) { + RtCode = VarCheckConflict; + break; + } + + CheckDuplicate |= Arg.FlagID; + CheckConflict |= Arg.ConflictMask; + break; + } + + Arg = CheckList[++Index]; + } + + if (Arg.FlagStr == NULL) { + RtCode = VarCheckUnknown; + } + + return RtCode; +} + +/** + The notify function of create event when performing a manual config. + + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. + +**/ +VOID +EFIAPI +IfConfigManualAddressNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + *((BOOLEAN *) Context) = TRUE; +} + +/** + Print MAC address. + + @param[in] Node The pointer of MAC address buffer. + @param[in] Size The size of MAC address buffer. + +**/ +VOID +IfConfigPrintMacAddr ( + IN UINT8 *Node, + IN UINT32 Size + ) +{ + UINTN Index; + + ASSERT (Size <= MACADDRMAXSIZE); + + for (Index = 0; Index < Size; Index++) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]); + if (Index + 1 < Size) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle); + } + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle); +} + + +/** + The get current status of all handles. + + @param[in] IfName The pointer of IfName(interface name). + @param[in] IfList The pointer of IfList(interface list). + + @retval EFI_SUCCESS The get status processed successfully. + @retval others The get status process failed. + +**/ +EFI_STATUS +IfConfigGetInterfaceInfo ( + IN CHAR16 *IfName, + IN LIST_ENTRY *IfList + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + UINTN HandleNum; + EFI_HANDLE *HandleBuffer; + EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2; + EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo; + IFCONFIG_INTERFACE_CB *IfCb; + UINTN DataSize; + + HandleBuffer = NULL; + HandleNum = 0; + + IfInfo = NULL; + IfCb = NULL; + + // + // Locate all the handles with ip4 service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIp4ServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status) || (HandleNum == 0)) { + return Status; + } + + // + // Enumerate all handles that installed with ip4 service binding protocol. + // + for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) { + IfCb = NULL; + IfInfo = NULL; + DataSize = 0; + + // + // Ip4config protocol and ip4 service binding protocol are installed + // on the same handle. + // + ASSERT (HandleBuffer != NULL); + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + &gEfiIp4Config2ProtocolGuid, + (VOID **) &Ip4Cfg2 + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Get the interface information size. + // + Status = Ip4Cfg2->GetData ( + Ip4Cfg2, + Ip4Config2DataTypeInterfaceInfo, + &DataSize, + NULL + ); + + if (Status != EFI_BUFFER_TOO_SMALL) { + goto ON_ERROR; + } + + IfInfo = AllocateZeroPool (DataSize); + + if (IfInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + + // + // Get the interface info. + // + Status = Ip4Cfg2->GetData ( + Ip4Cfg2, + Ip4Config2DataTypeInterfaceInfo, + &DataSize, + IfInfo + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Check the interface name if required. + // + if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) { + FreePool (IfInfo); + continue; + } + + DataSize = 0; + + // + // Get the size of dns server list. + // + Status = Ip4Cfg2->GetData ( + Ip4Cfg2, + Ip4Config2DataTypeDnsServer, + &DataSize, + NULL + ); + + if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) { + goto ON_ERROR; + } + + IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize); + + if (IfCb == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + + IfCb->NicHandle = HandleBuffer[HandleIndex]; + IfCb->IfInfo = IfInfo; + IfCb->IfCfg = Ip4Cfg2; + IfCb->DnsCnt = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS)); + + // + // Get the dns server list if has. + // + if (DataSize > 0) { + Status = Ip4Cfg2->GetData ( + Ip4Cfg2, + Ip4Config2DataTypeDnsServer, + &DataSize, + IfCb->DnsAddr + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + } + + // + // Get the config policy. + // + DataSize = sizeof (EFI_IP4_CONFIG2_POLICY); + Status = Ip4Cfg2->GetData ( + Ip4Cfg2, + Ip4Config2DataTypePolicy, + &DataSize, + &IfCb->Policy + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + InsertTailList (IfList, &IfCb->Link); + + if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) { + // + // Only need the appointed interface, keep the allocated buffer. + // + IfCb = NULL; + IfInfo = NULL; + break; + } + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; + +ON_ERROR: + + if (IfInfo != NULL) { + FreePool (IfInfo); + } + + if (IfCb != NULL) { + FreePool (IfCb); + } + + return Status; +} + +/** + The list process of the ifconfig command. + + @param[in] IfList The pointer of IfList(interface list). + + @retval SHELL_SUCCESS The ifconfig command list processed successfully. + @retval others The ifconfig command list process failed. + +**/ +SHELL_STATUS +IfConfigShowInterfaceInfo ( + IN LIST_ENTRY *IfList + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + IFCONFIG_INTERFACE_CB *IfCb; + EFI_STATUS MediaStatus; + EFI_IPv4_ADDRESS Gateway; + UINT32 Index; + + MediaStatus = EFI_SUCCESS; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle); + } + + // + // Go through the interface list. + // + NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) { + IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle); + + // + // Print interface name. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name); + + // + // Get Media State. + // + if (EFI_SUCCESS == NetLibDetectMediaWaitTimeout (IfCb->NicHandle, 0, &MediaStatus)) { + if (MediaStatus != EFI_SUCCESS) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media disconnected"); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media present"); + } + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media state unknown"); + } + + // + // Print interface config policy. + // + if (IfCb->Policy == Ip4Config2PolicyDhcp) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle); + } + + // + // Print mac address of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle); + + IfConfigPrintMacAddr ( + IfCb->IfInfo->HwAddress.Addr, + IfCb->IfInfo->HwAddressSize + ); + + // + // Print IPv4 address list of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY), + gShellNetwork1HiiHandle, + (UINTN)IfCb->IfInfo->StationAddress.Addr[0], + (UINTN)IfCb->IfInfo->StationAddress.Addr[1], + (UINTN)IfCb->IfInfo->StationAddress.Addr[2], + (UINTN)IfCb->IfInfo->StationAddress.Addr[3] + ); + + // + // Print subnet mask list of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY), + gShellNetwork1HiiHandle, + (UINTN)IfCb->IfInfo->SubnetMask.Addr[0], + (UINTN)IfCb->IfInfo->SubnetMask.Addr[1], + (UINTN)IfCb->IfInfo->SubnetMask.Addr[2], + (UINTN)IfCb->IfInfo->SubnetMask.Addr[3] + ); + + // + // Print default gateway of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle); + + ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS)); + + for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) { + if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) && + (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){ + CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS)); + } + } + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY), + gShellNetwork1HiiHandle, + (UINTN)Gateway.Addr[0], + (UINTN)Gateway.Addr[1], + (UINTN)Gateway.Addr[2], + (UINTN)Gateway.Addr[3] + ); + + // + // Print route table entry. + // + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize); + + for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Subnet ", + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0], + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1], + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2], + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3] + ); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Netmask", + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0], + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1], + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2], + (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3] + ); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Gateway", + (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0], + (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1], + (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2], + (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3] + ); + } + + // + // Print dns server addresses list of the interface if has. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle); + + for (Index = 0; Index < IfCb->DnsCnt; Index++) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY), + gShellNetwork1HiiHandle, + (UINTN) IfCb->DnsAddr[Index].Addr[0], + (UINTN) IfCb->DnsAddr[Index].Addr[1], + (UINTN) IfCb->DnsAddr[Index].Addr[2], + (UINTN) IfCb->DnsAddr[Index].Addr[3] + ); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle); + } + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle); + + return SHELL_SUCCESS; +} + +/** + The clean process of the ifconfig command to clear interface info. + + @param[in] IfList The pointer of IfList(interface list). + @param[in] IfName The pointer of interface name. + + @retval SHELL_SUCCESS The ifconfig command clean processed successfully. + @retval others The ifconfig command clean process failed. + +**/ +SHELL_STATUS +IfConfigClearInterfaceInfo ( + IN LIST_ENTRY *IfList, + IN CHAR16 *IfName + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + IFCONFIG_INTERFACE_CB *IfCb; + EFI_IP4_CONFIG2_POLICY Policy; + + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle); + } + + // + // Go through the interface list. + // If the interface name is specified, DHCP DORA process will be + // triggered by the policy transition (static -> dhcp). + // + NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) { + IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link); + + if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) { + Policy = Ip4Config2PolicyStatic; + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + } + + Policy = Ip4Config2PolicyDhcp; + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + } + + return ShellStatus; +} + +/** + The set process of the ifconfig command. + + @param[in] IfList The pointer of IfList(interface list). + @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option). + + @retval SHELL_SUCCESS The ifconfig command set processed successfully. + @retval others The ifconfig command set process failed. + +**/ +SHELL_STATUS +IfConfigSetInterfaceInfo ( + IN LIST_ENTRY *IfList, + IN ARG_LIST *VarArg + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + IFCONFIG_INTERFACE_CB *IfCb; + VAR_CHECK_CODE CheckCode; + EFI_EVENT TimeOutEvt; + EFI_EVENT MappedEvt; + BOOLEAN IsAddressOk; + + EFI_IP4_CONFIG2_POLICY Policy; + EFI_IP4_CONFIG2_MANUAL_ADDRESS ManualAddress; + UINTN DataSize; + EFI_IPv4_ADDRESS Gateway; + IP4_ADDR SubnetMask; + IP4_ADDR TempGateway; + EFI_IPv4_ADDRESS *Dns; + ARG_LIST *Tmp; + UINTN Index; + + CONST CHAR16* TempString; + + Dns = NULL; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle); + return SHELL_INVALID_PARAMETER; + } + + // + // Make sure to set only one interface each time. + // + IfCb = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link); + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + + // + // Initialize check list mechanism. + // + CheckCode = IfConfigRetriveCheckListByName( + NULL, + NULL, + TRUE + ); + + // + // Create events & timers for asynchronous settings. + // + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeOutEvt + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + IfConfigManualAddressNotify, + &IsAddressOk, + &MappedEvt + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Parse the setting variables. + // + while (VarArg != NULL) { + // + // Check invalid parameters (duplication & unknown & conflict). + // + CheckCode = IfConfigRetriveCheckListByName( + mSetCheckList, + VarArg->Arg, + FALSE + ); + + if (VarCheckOk != CheckCode) { + switch (CheckCode) { + case VarCheckDuplicate: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg); + break; + + case VarCheckConflict: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg); + break; + + case VarCheckUnknown: + // + // To handle unsupported option. + // + TempString = PermanentString; + if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString); + goto ON_EXIT; + } + + // + // To handle unknown option. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg); + break; + + default: + break; + } + + VarArg = VarArg->Next; + continue; + } + + // + // Process valid variables. + // + if (StrCmp(VarArg->Arg, L"dhcp") == 0) { + // + // Set dhcp config policy + // + Policy = Ip4Config2PolicyDhcp; + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + VarArg= VarArg->Next; + + } else if (StrCmp (VarArg->Arg, L"static") == 0) { + VarArg= VarArg->Next; + if (VarArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + ZeroMem (&ManualAddress, sizeof (ManualAddress)); + + // + // Get manual IP address. + // + Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // Get subnetmask. + // + VarArg = VarArg->Next; + if (VarArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // Get gateway. + // + VarArg = VarArg->Next; + if (VarArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = NetLibStrToIp4 (VarArg->Arg, &Gateway); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // Need to check the gateway validity before set Manual Address. + // In case we can set manual address but fail to configure Gateway. + // + CopyMem (&SubnetMask, &ManualAddress.SubnetMask, sizeof (IP4_ADDR)); + CopyMem (&TempGateway, &Gateway, sizeof (IP4_ADDR)); + SubnetMask = NTOHL (SubnetMask); + TempGateway = NTOHL (TempGateway); + if ((SubnetMask != 0) && + (SubnetMask != 0xFFFFFFFFu) && + !NetIp4IsUnicast (TempGateway, SubnetMask)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle, VarArg->Arg); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // Set manual config policy. + // + Policy = Ip4Config2PolicyStatic; + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Set Manual Address. + // + IsAddressOk = FALSE; + + Status = IfCb->IfCfg->RegisterDataNotify ( + IfCb->IfCfg, + Ip4Config2DataTypeManualAddress, + MappedEvt + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS); + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypeManualAddress, + DataSize, + &ManualAddress + ); + + if (Status == EFI_NOT_READY) { + gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000); + + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { + if (IsAddressOk) { + Status = EFI_SUCCESS; + break; + } + } + } + + IfCb->IfCfg->UnregisterDataNotify ( + IfCb->IfCfg, + Ip4Config2DataTypeManualAddress, + MappedEvt + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Set gateway. + // + DataSize = sizeof (EFI_IPv4_ADDRESS); + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypeGateway, + DataSize, + &Gateway + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + VarArg = VarArg->Next; + + } else if (StrCmp (VarArg->Arg, L"dns") == 0) { + // + // Get DNS addresses. + // + VarArg = VarArg->Next; + Tmp = VarArg; + Index = 0; + while (Tmp != NULL) { + Index ++; + Tmp = Tmp->Next; + } + + Dns = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS)); + if (Dns == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Tmp = VarArg; + Index = 0; + while (Tmp != NULL) { + Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, Tmp->Arg); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + Index ++; + Tmp = Tmp->Next; + } + + VarArg = Tmp; + + // + // Set DNS addresses. + // + DataSize = Index * sizeof (EFI_IPv4_ADDRESS); + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip4Config2DataTypeDnsServer, + DataSize, + Dns + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + } + } + +ON_EXIT: + if (Dns != NULL) { + FreePool (Dns); + } + + return ShellStatus; + +} + +/** + The ifconfig command main process. + + @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA. + + @retval SHELL_SUCCESS ifconfig command processed successfully. + @retval others The ifconfig command process failed. + +**/ +SHELL_STATUS +IfConfig ( + IN IFCONFIG_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + + // + // Get configure information of all interfaces. + // + Status = IfConfigGetInterfaceInfo ( + Private->IfName, + &Private->IfList + ); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + goto ON_EXIT; + } + + switch (Private->OpCode) { + case IfConfigOpList: + ShellStatus = IfConfigShowInterfaceInfo (&Private->IfList); + break; + + case IfConfigOpClear: + ShellStatus = IfConfigClearInterfaceInfo (&Private->IfList, Private->IfName); + break; + + case IfConfigOpSet: + ShellStatus = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg); + break; + + default: + ShellStatus = SHELL_UNSUPPORTED; + } + +ON_EXIT: + return ShellStatus; +} + +/** + The ifconfig command cleanup process, free the allocated memory. + + @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA. + +**/ +VOID +IfConfigCleanup ( + IN IFCONFIG_PRIVATE_DATA *Private + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + IFCONFIG_INTERFACE_CB *IfCb; + + ASSERT (Private != NULL); + + // + // Clean the list which save the set config Args. + // + if (Private->VarArg != NULL) { + FreeArgList (Private->VarArg); + } + + if (Private->IfName != NULL) { + FreePool (Private->IfName); + } + + // + // Clean the IFCONFIG_INTERFACE_CB list. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) { + IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link); + + RemoveEntryList (&IfCb->Link); + + if (IfCb->IfInfo != NULL) { + + FreePool (IfCb->IfInfo); + } + + FreePool (IfCb); + } + + FreePool (Private); +} + +/** + Function for 'ifconfig' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @retval EFI_SUCCESS ifconfig command processed successfully. + @retval others The ifconfig command process failed. + +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIfconfig ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + IFCONFIG_PRIVATE_DATA *Private; + LIST_ENTRY *ParamPackage; + SHELL_STATUS ShellStatus; + CONST CHAR16 *ValueStr; + ARG_LIST *ArgList; + CHAR16 *ProblemParam; + CHAR16 *Str; + + Status = EFI_INVALID_PARAMETER; + Private = NULL; + ShellStatus = SHELL_SUCCESS; + + Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR (Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + + goto ON_EXIT; + } + + // + // To handle unsupported option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-c")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // To handle no option. + // + if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") && + !ShellCommandLineGetFlag (ParamPackage, L"-l")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // To handle conflict options. + // + if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA)); + if (Private == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + InitializeListHead (&Private->IfList); + + // + // To get interface name for the list option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-l")) { + Private->OpCode = IfConfigOpList; + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l"); + if (ValueStr != NULL) { + Str = AllocateCopyPool (StrSize (ValueStr), ValueStr); + if (Str == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Private->IfName = Str; + } + } + + // + // To get interface name for the clear option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-r")) { + Private->OpCode = IfConfigOpClear; + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r"); + if (ValueStr != NULL) { + Str = AllocateCopyPool (StrSize (ValueStr), ValueStr); + if (Str == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Private->IfName = Str; + } + } + + // + // To get interface name and corresponding Args for the set option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-s")) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s"); + if (ValueStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // To split the configuration into multi-section. + // + ArgList = SplitStrToList (ValueStr, L' '); + if (ArgList == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Private->OpCode = IfConfigOpSet; + Private->IfName = ArgList->Arg; + + Private->VarArg = ArgList->Next; + + if (Private->IfName == NULL || Private->VarArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + + // + // Main process of ifconfig. + // + ShellStatus = IfConfig (Private); + +ON_EXIT: + + ShellCommandLineFreeVarList (ParamPackage); + + if (Private != NULL) { + IfConfigCleanup (Private); + } + + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c new file mode 100644 index 0000000..35d581b --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c @@ -0,0 +1,1713 @@ +/** @file + The implementation for Ping shell command. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
        + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        + (C) Copyright 2016 Hewlett Packard Enterprise Development LP
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellNetwork1CommandsLib.h" + +#define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS))) + +UINT64 mCurrentTick = 0; + +// +// Function templates to match the IPv4 and IPv6 commands that we use. +// +typedef +EFI_STATUS +(EFIAPI *PING_IPX_POLL)( + IN VOID *This + ); + +typedef +EFI_STATUS +(EFIAPI *PING_IPX_TRANSMIT)( + IN VOID *This, + IN VOID *Token + ); + +typedef +EFI_STATUS +(EFIAPI *PING_IPX_RECEIVE)( + IN VOID *This, + IN VOID *Token + ); + +typedef +EFI_STATUS +(EFIAPI *PING_IPX_CANCEL)( + IN VOID *This, + IN VOID *Token OPTIONAL + ); + +/// +/// A set of pointers to either IPv6 or IPv4 functions. +/// Unknown which one to the ping command. +/// +typedef struct { + PING_IPX_TRANSMIT Transmit; + PING_IPX_RECEIVE Receive; + PING_IPX_CANCEL Cancel; + PING_IPX_POLL Poll; +}PING_IPX_PROTOCOL; + + +typedef union { + VOID *RxData; + VOID *TxData; +} PING_PACKET; + +// +// PING_IPX_COMPLETION_TOKEN +// structures are used for both transmit and receive operations. +// This version is IP-unaware. +// +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + PING_PACKET Packet; +} PING_IPX_COMPLETION_TOKEN; + +#pragma pack(1) +typedef struct _ICMPX_ECHO_REQUEST_REPLY { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + UINT16 Identifier; + UINT16 SequenceNum; + UINT32 TimeStamp; + UINT8 Data[1]; +} ICMPX_ECHO_REQUEST_REPLY; +#pragma pack() + +typedef struct _PING_ICMP_TX_INFO { + LIST_ENTRY Link; + UINT16 SequenceNum; + UINT32 TimeStamp; + PING_IPX_COMPLETION_TOKEN *Token; +} PING_ICMPX_TX_INFO; + +#define DEFAULT_TIMEOUT 5000 +#define MAX_SEND_NUMBER 10000 +#define MAX_BUFFER_SIZE 32768 +#define DEFAULT_TIMER_PERIOD 358049 +#define ONE_SECOND 10000000 +#define PING_IP_CHOICE_IP4 1 +#define PING_IP_CHOICE_IP6 2 +#define DEFAULT_SEND_COUNT 10 +#define DEFAULT_BUFFER_SIZE 16 +#define ICMP_V4_ECHO_REQUEST 0x8 +#define ICMP_V4_ECHO_REPLY 0x0 +#define STALL_1_MILLI_SECOND 1000 + +#define PING_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'i', 'n', 'g') +typedef struct _PING_PRIVATE_DATA { + UINT32 Signature; + EFI_HANDLE NicHandle; + EFI_HANDLE IpChildHandle; + EFI_EVENT Timer; + + UINT32 TimerPeriod; + UINT32 RttTimerTick; + EFI_EVENT RttTimer; + + EFI_STATUS Status; + LIST_ENTRY TxList; + UINT16 RxCount; + UINT16 TxCount; + UINT64 RttSum; + UINT64 RttMin; + UINT64 RttMax; + UINT32 SequenceNum; + + UINT32 SendNum; + UINT32 BufferSize; + UINT32 IpChoice; + + PING_IPX_PROTOCOL ProtocolPointers; + VOID *IpProtocol; + UINT8 SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )]; + UINT8 DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )]; + PING_IPX_COMPLETION_TOKEN RxToken; + UINT16 FailedCount; +} PING_PRIVATE_DATA; + +/** + Calculate the internet checksum (see RFC 1071). + + @param[in] Packet Buffer which contains the data to be checksummed. + @param[in] Length Length to be checksummed. + + @retval Checksum Returns the 16 bit ones complement of + ones complement sum of 16 bit words +**/ +UINT16 +NetChecksum ( + IN UINT8 *Buffer, + IN UINT32 Length + ) +{ + UINT32 Sum; + UINT8 Odd; + UINT16 *Packet; + + Packet = (UINT16 *) Buffer; + + Sum = 0; + Odd = (UINT8) (Length & 1); + Length >>= 1; + while ((Length--) != 0) { + Sum += *Packet++; + } + + if (Odd != 0) { + Sum += *(UINT8 *) Packet; + } + + Sum = (Sum & 0xffff) + (Sum >> 16); + + // + // in case above carried + // + Sum += Sum >> 16; + + return (UINT16) Sum; +} + +/** + Reads and returns the current value of register. + In IA64, the register is the Interval Timer Vector (ITV). + In X86(IA32/X64), the register is the Time Stamp Counter (TSC) + + @return The current value of the register. + +**/ + +STATIC CONST SHELL_PARAM_ITEM PingParamList[] = { + { + L"-l", + TypeValue + }, + { + L"-n", + TypeValue + }, + { + L"-s", + TypeValue + }, + { + L"-_s", + TypeValue + }, + { + L"-_ip6", + TypeFlag + }, + { + NULL, + TypeMax + }, +}; + +// +// Global Variables in Ping command. +// +STATIC CONST CHAR16 *mDstString; +STATIC CONST CHAR16 *mSrcString; + +/** + RTT timer tick routine. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +RttTimerTickRoutine ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 *RttTimerTick; + + RttTimerTick = (UINT32*) Context; + (*RttTimerTick)++; +} + +/** + Get the timer period of the system. + + This function tries to get the system timer period by creating + an 1ms period timer. + + @return System timer period in MS, or 0 if operation failed. + +**/ +UINT32 +GetTimerPeriod( + VOID + ) +{ + EFI_STATUS Status; + UINT32 RttTimerTick; + EFI_EVENT TimerEvent; + UINT32 StallCounter; + EFI_TPL OldTpl; + + RttTimerTick = 0; + StallCounter = 0; + + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + RttTimerTickRoutine, + &RttTimerTick, + &TimerEvent + ); + if (EFI_ERROR (Status)) { + return 0; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Status = gBS->SetTimer ( + TimerEvent, + TimerPeriodic, + TICKS_PER_MS + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (TimerEvent); + return 0; + } + + while (RttTimerTick < 10) { + gBS->Stall (STALL_1_MILLI_SECOND); + ++StallCounter; + } + + gBS->RestoreTPL (OldTpl); + + gBS->SetTimer (TimerEvent, TimerCancel, 0); + gBS->CloseEvent (TimerEvent); + + return StallCounter / RttTimerTick; +} + +/** + Initialize the timer event for RTT (round trip time). + + @param[in] Private The pointer to PING_PRIVATE_DATA. + + @retval EFI_SUCCESS RTT timer is started. + @retval Others Failed to start the RTT timer. + +**/ +EFI_STATUS +PingInitRttTimer ( + PING_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + Private->TimerPeriod = GetTimerPeriod (); + if (Private->TimerPeriod == 0) { + return EFI_ABORTED; + } + + Private->RttTimerTick = 0; + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + RttTimerTickRoutine, + &Private->RttTimerTick, + &Private->RttTimer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + Private->RttTimer, + TimerPeriodic, + TICKS_PER_MS + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (Private->RttTimer); + return Status; + } + + return EFI_SUCCESS; +} + +/** + Free RTT timer event resource. + + @param[in] Private The pointer to PING_PRIVATE_DATA. + +**/ +VOID +PingFreeRttTimer ( + PING_PRIVATE_DATA *Private + ) +{ + if (Private->RttTimer != NULL) { + gBS->SetTimer (Private->RttTimer, TimerCancel, 0); + gBS->CloseEvent (Private->RttTimer); + } +} + +/** + Read the current time. + + @param[in] Private The pointer to PING_PRIVATE_DATA. + + @retval the current tick value. +**/ +UINT32 +ReadTime ( + PING_PRIVATE_DATA *Private + ) +{ + return Private->RttTimerTick; +} + +/** + Calculate a duration in ms. + + @param[in] Private The pointer to PING_PRIVATE_DATA. + @param[in] Begin The start point of time. + @param[in] End The end point of time. + + @return The duration in ms. + @retval 0 The parameters were not valid. +**/ +UINT32 +CalculateTick ( + PING_PRIVATE_DATA *Private, + IN UINT32 Begin, + IN UINT32 End + ) +{ + if (End < Begin) { + return (0); + } + + return (End - Begin) * Private->TimerPeriod; +} + +/** + Destroy PING_ICMPX_TX_INFO, and recollect the memory. + + @param[in] TxInfo The pointer to PING_ICMPX_TX_INFO. + @param[in] IpChoice Whether the token is IPv4 or IPv6 +**/ +VOID +PingDestroyTxInfo ( + IN PING_ICMPX_TX_INFO *TxInfo, + IN UINT32 IpChoice + ) +{ + EFI_IP6_TRANSMIT_DATA *Ip6TxData; + EFI_IP4_TRANSMIT_DATA *Ip4TxData; + EFI_IP6_FRAGMENT_DATA *FragData; + UINTN Index; + + if (TxInfo == NULL) { + return; + } + + if (TxInfo->Token != NULL) { + + if (TxInfo->Token->Event != NULL) { + gBS->CloseEvent (TxInfo->Token->Event); + } + + if (TxInfo->Token->Packet.TxData != NULL) { + if (IpChoice == PING_IP_CHOICE_IP6) { + Ip6TxData = TxInfo->Token->Packet.TxData; + + if (Ip6TxData->OverrideData != NULL) { + FreePool (Ip6TxData->OverrideData); + } + + if (Ip6TxData->ExtHdrs != NULL) { + FreePool (Ip6TxData->ExtHdrs); + } + + for (Index = 0; Index < Ip6TxData->FragmentCount; Index++) { + FragData = Ip6TxData->FragmentTable[Index].FragmentBuffer; + if (FragData != NULL) { + FreePool (FragData); + } + } + } else { + Ip4TxData = TxInfo->Token->Packet.TxData; + + if (Ip4TxData->OverrideData != NULL) { + FreePool (Ip4TxData->OverrideData); + } + + for (Index = 0; Index < Ip4TxData->FragmentCount; Index++) { + FragData = Ip4TxData->FragmentTable[Index].FragmentBuffer; + if (FragData != NULL) { + FreePool (FragData); + } + } + } + } + + FreePool (TxInfo->Token); + } + + FreePool (TxInfo); +} + +/** + Match the request, and reply with SequenceNum/TimeStamp. + + @param[in] Private The pointer to PING_PRIVATE_DATA. + @param[in] Packet The pointer to ICMPX_ECHO_REQUEST_REPLY. + + @retval EFI_SUCCESS The match is successful. + @retval EFI_NOT_FOUND The reply can't be matched with any request. + +**/ +EFI_STATUS +Ping6MatchEchoReply ( + IN PING_PRIVATE_DATA *Private, + IN ICMPX_ECHO_REQUEST_REPLY *Packet + ) +{ + PING_ICMPX_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link); + + if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) { + Private->RxCount++; + RemoveEntryList (&TxInfo->Link); + PingDestroyTxInfo (TxInfo, Private->IpChoice); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + The original intention is to send a request. + Currently, the application retransmits an icmp6 echo request packet + per second in sendnumber times that is specified by the user. + Because nothing can be done here, all things move to the timer rountine. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6OnEchoRequestSent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + +/** + receive reply, match and print reply infomation. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to context. + +**/ +VOID +EFIAPI +Ping6OnEchoReplyReceived ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + PING_PRIVATE_DATA *Private; + ICMPX_ECHO_REQUEST_REPLY *Reply; + UINT32 PayLoad; + UINT32 Rtt; + + Private = (PING_PRIVATE_DATA *) Context; + + if (Private == NULL || Private->Status == EFI_ABORTED || Private->Signature != PING_PRIVATE_DATA_SIGNATURE) { + return; + } + + if (Private->RxToken.Packet.RxData == NULL) { + return; + } + + if (Private->IpChoice == PING_IP_CHOICE_IP6) { + Reply = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer; + PayLoad = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength; + if (((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->NextHeader != IP6_ICMP) { + goto ON_EXIT; + } + if (!IP6_IS_MULTICAST ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && + !EFI_IP6_EQUAL (&((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv6_ADDRESS*)&Private->DstAddress)) { + goto ON_EXIT; + } + + if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) { + goto ON_EXIT; + } + } else { + Reply = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer; + PayLoad = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength; + if (!IP4_IS_MULTICAST (EFI_IP4(*(EFI_IPv4_ADDRESS*)Private->DstAddress)) && + !EFI_IP4_EQUAL (&((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv4_ADDRESS*)&Private->DstAddress)) { + goto ON_EXIT; + } + + if ((Reply->Type != ICMP_V4_ECHO_REPLY) || (Reply->Code != 0)) { + goto ON_EXIT; + } + } + + + if (PayLoad != Private->BufferSize) { + goto ON_EXIT; + } + // + // Check whether the reply matches the sent request before. + // + Status = Ping6MatchEchoReply (Private, Reply); + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + // + // Display statistics on this icmp6 echo reply packet. + // + Rtt = CalculateTick (Private, Reply->TimeStamp, ReadTime (Private)); + + Private->RttSum += Rtt; + Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin; + Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING_REPLY_INFO), + gShellNetwork1HiiHandle, + PayLoad, + mDstString, + Reply->SequenceNum, + Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0, + Rtt, + Rtt + Private->TimerPeriod + ); + +ON_EXIT: + + if (Private->RxCount < Private->SendNum) { + // + // Continue to receive icmp echo reply packets. + // + Private->RxToken.Status = EFI_ABORTED; + + Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status); + Private->Status = EFI_ABORTED; + } + } else { + // + // All reply have already been received from the dest host. + // + Private->Status = EFI_SUCCESS; + } + // + // Singal to recycle the each rxdata here, not at the end of process. + // + gBS->SignalEvent (Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal:((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal); +} + +/** + Create a PING_IPX_COMPLETION_TOKEN. + + @param[in] Private The pointer of PING_PRIVATE_DATA. + @param[in] TimeStamp The TimeStamp of request. + @param[in] SequenceNum The SequenceNum of request. + + @return The pointer of PING_IPX_COMPLETION_TOKEN. + +**/ +PING_IPX_COMPLETION_TOKEN * +PingGenerateToken ( + IN PING_PRIVATE_DATA *Private, + IN UINT32 TimeStamp, + IN UINT16 SequenceNum + ) +{ + EFI_STATUS Status; + PING_IPX_COMPLETION_TOKEN *Token; + VOID *TxData; + ICMPX_ECHO_REQUEST_REPLY *Request; + UINT16 HeadSum; + UINT16 TempChecksum; + + Request = AllocateZeroPool (Private->BufferSize); + if (Request == NULL) { + return NULL; + } + TxData = AllocateZeroPool (Private->IpChoice==PING_IP_CHOICE_IP6?sizeof (EFI_IP6_TRANSMIT_DATA):sizeof (EFI_IP4_TRANSMIT_DATA)); + if (TxData == NULL) { + FreePool (Request); + return NULL; + } + Token = AllocateZeroPool (sizeof (PING_IPX_COMPLETION_TOKEN)); + if (Token == NULL) { + FreePool (Request); + FreePool (TxData); + return NULL; + } + + // + // Assembly echo request packet. + // + Request->Type = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST); + Request->Code = 0; + Request->SequenceNum = SequenceNum; + Request->Identifier = 0; + Request->Checksum = 0; + + // + // Assembly token for transmit. + // + if (Private->IpChoice==PING_IP_CHOICE_IP6) { + Request->TimeStamp = TimeStamp; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength = 0; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs = NULL; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData = 0; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->DataLength = Private->BufferSize; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentCount = 1; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request; + ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize; + } else { + ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsLength = 0; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsBuffer = NULL; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->OverrideData = 0; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->TotalDataLength = Private->BufferSize; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentCount = 1; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[0] = Private->DstAddress[0]; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[1] = Private->DstAddress[1]; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[2] = Private->DstAddress[2]; + ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[3] = Private->DstAddress[3]; + + HeadSum = NetChecksum ((UINT8 *) Request, Private->BufferSize); + Request->TimeStamp = TimeStamp; + TempChecksum = NetChecksum ((UINT8 *) &Request->TimeStamp, sizeof (UINT64)); + Request->Checksum = (UINT16)(~NetAddChecksum (HeadSum, TempChecksum)); + } + + + Token->Status = EFI_ABORTED; + Token->Packet.TxData = TxData; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnEchoRequestSent, + Private, + &Token->Event + ); + + if (EFI_ERROR (Status)) { + FreePool (Request); + FreePool (TxData); + FreePool (Token); + return NULL; + } + + return Token; +} + +/** + Transmit the PING_IPX_COMPLETION_TOKEN. + + @param[in] Private The pointer of PING_PRIVATE_DATA. + + @retval EFI_SUCCESS Transmitted successfully. + @retval EFI_OUT_OF_RESOURCES No memory is available on the platform. + @retval others Transmitted unsuccessfully. + +**/ +EFI_STATUS +PingSendEchoRequest ( + IN PING_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + PING_ICMPX_TX_INFO *TxInfo; + + TxInfo = AllocateZeroPool (sizeof (PING_ICMPX_TX_INFO)); + + if (TxInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TxInfo->TimeStamp = ReadTime (Private); + TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1); + TxInfo->Token = PingGenerateToken ( + Private, + TxInfo->TimeStamp, + TxInfo->SequenceNum + ); + + if (TxInfo->Token == NULL) { + PingDestroyTxInfo (TxInfo, Private->IpChoice); + return EFI_OUT_OF_RESOURCES; + } + + ASSERT(Private->ProtocolPointers.Transmit != NULL); + + InsertTailList (&Private->TxList, &TxInfo->Link); + + Status = Private->ProtocolPointers.Transmit (Private->IpProtocol, TxInfo->Token); + + if (EFI_ERROR (Status)) { + RemoveEntryList (&TxInfo->Link); + PingDestroyTxInfo (TxInfo, Private->IpChoice); + return Status; + } + + Private->TxCount++; + + return EFI_SUCCESS; +} + +/** + Place a completion token into the receive packet queue to receive the echo reply. + + @param[in] Private The pointer of PING_PRIVATE_DATA. + + @retval EFI_SUCCESS Put the token into the receive packet queue successfully. + @retval others Put the token into the receive packet queue unsuccessfully. + +**/ +EFI_STATUS +Ping6ReceiveEchoReply ( + IN PING_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + ZeroMem (&Private->RxToken, sizeof (PING_IPX_COMPLETION_TOKEN)); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnEchoReplyReceived, + Private, + &Private->RxToken.Event + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Private->RxToken.Status = EFI_NOT_READY; + + Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status); + } + return Status; +} + +/** + Remove the timeout request from the list. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6OnTimerRoutine ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + PING_PRIVATE_DATA *Private; + PING_ICMPX_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + UINT64 Time; + + Private = (PING_PRIVATE_DATA *) Context; + if (Private->Signature != PING_PRIVATE_DATA_SIGNATURE) { + Private->Status = EFI_NOT_FOUND; + return; + } + + // + // Retransmit icmp6 echo request packets per second in sendnumber times. + // + if (Private->TxCount < Private->SendNum) { + + Status = PingSendEchoRequest (Private); + if (Private->TxCount != 0){ + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_SEND_REQUEST), gShellNetwork1HiiHandle, Private->TxCount + 1); + } + } + } + // + // Check whether any icmp6 echo request in the list timeout. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link); + Time = CalculateTick (Private, TxInfo->TimeStamp, ReadTime (Private)); + + // + // Remove the timeout echo request from txlist. + // + if (Time > DEFAULT_TIMEOUT) { + + if (EFI_ERROR (TxInfo->Token->Status)) { + Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token); + } + // + // Remove the timeout icmp6 echo request from list. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_TIMEOUT), gShellNetwork1HiiHandle, TxInfo->SequenceNum); + + RemoveEntryList (&TxInfo->Link); + PingDestroyTxInfo (TxInfo, Private->IpChoice); + + Private->RxCount++; + Private->FailedCount++; + + if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) { + // + // All the left icmp6 echo request in the list timeout. + // + Private->Status = EFI_TIMEOUT; + } + } + } +} + +/** + Determine if a IP4 address is Link Local. + + 169.254.1.0 through 169.254.254.255 is link local. + + @param[in] Address The address to test. + + @retval TRUE It is. + @retval FALSE It is not. +**/ +BOOLEAN +PingNetIp4IsLinkLocalAddr ( + IN CONST EFI_IPv4_ADDRESS *Address + ) +{ + return ((BOOLEAN)(Address->Addr[0] == 169 && Address->Addr[1] == 254 && Address->Addr[2] >= 1 && Address->Addr[2] <= 254)); +} + +/** + Determine if a IP4 address is unspecified. + + @param[in] Address The address to test. + + @retval TRUE It is. + @retval FALSE It is not. +**/ +BOOLEAN +PingNetIp4IsUnspecifiedAddr ( + IN CONST EFI_IPv4_ADDRESS *Address + ) +{ + return ((BOOLEAN)((ReadUnaligned32 ((UINT32*)&Address->Addr[0])) == 0x00000000)); +} + +/** + Create a valid IP instance. + + @param[in] Private The pointer of PING_PRIVATE_DATA. + + @retval EFI_SUCCESS Create a valid IPx instance successfully. + @retval EFI_ABORTED Locate handle with ipx service binding protocol unsuccessfully. + @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link-local address. + @retval EFI_OUT_OF_RESOURCES No memory is available on the platform. + @retval EFI_NOT_FOUND The source address is not found. +**/ +EFI_STATUS +PingCreateIpInstance ( + IN PING_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + UINTN HandleNum; + EFI_HANDLE *HandleBuffer; + BOOLEAN UnspecifiedSrc; + EFI_STATUS MediaStatus; + EFI_SERVICE_BINDING_PROTOCOL *EfiSb; + VOID *IpXCfg; + EFI_IP6_CONFIG_DATA Ip6Config; + EFI_IP4_CONFIG_DATA Ip4Config; + VOID *IpXInterfaceInfo; + UINTN IfInfoSize; + EFI_IPv6_ADDRESS *Addr; + UINTN AddrIndex; + + HandleBuffer = NULL; + UnspecifiedSrc = FALSE; + MediaStatus = EFI_SUCCESS; + EfiSb = NULL; + IpXInterfaceInfo = NULL; + IfInfoSize = 0; + + // + // Locate all the handles with ip6 service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) { + return EFI_ABORTED; + } + + if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \ + PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) { + // + // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected. + // + UnspecifiedSrc = TRUE; + } + + // + // Source address is required when pinging a link-local address. + // + if (Private->IpChoice == PING_IP_CHOICE_IP6) { + if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle); + Status = EFI_INVALID_PARAMETER; + goto ON_ERROR; + } + } else { + ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4); + if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle); + Status = EFI_INVALID_PARAMETER; + goto ON_ERROR; + } + } + + // + // For each ip6 protocol, check interface addresses list. + // + for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) { + EfiSb = NULL; + IpXInterfaceInfo = NULL; + IfInfoSize = 0; + + if (UnspecifiedSrc) { + // + // Check media. + // + NetLibDetectMediaWaitTimeout (HandleBuffer[HandleIndex], 0, &MediaStatus); + if (MediaStatus != EFI_SUCCESS) { + // + // Skip this one. + // + continue; + } + } + + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid, + (VOID **) &EfiSb + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Ip6config protocol and ip6 service binding protocol are installed + // on the same handle. + // + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid, + (VOID **) &IpXCfg + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + // + // Get the interface information size. + // + if (Private->IpChoice == PING_IP_CHOICE_IP6) { + Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData ( + IpXCfg, + Ip6ConfigDataTypeInterfaceInfo, + &IfInfoSize, + NULL + ); + } else { + Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData ( + IpXCfg, + Ip4Config2DataTypeInterfaceInfo, + &IfInfoSize, + NULL + ); + } + + // + // Skip the ones not in current use. + // + if (Status == EFI_NOT_STARTED) { + continue; + } + + if (Status != EFI_BUFFER_TOO_SMALL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status); + goto ON_ERROR; + } + + IpXInterfaceInfo = AllocateZeroPool (IfInfoSize); + + if (IpXInterfaceInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + // + // Get the interface info. + // + if (Private->IpChoice == PING_IP_CHOICE_IP6) { + Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData ( + IpXCfg, + Ip6ConfigDataTypeInterfaceInfo, + &IfInfoSize, + IpXInterfaceInfo + ); + } else { + Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData ( + IpXCfg, + Ip4Config2DataTypeInterfaceInfo, + &IfInfoSize, + IpXInterfaceInfo + ); + } + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status); + goto ON_ERROR; + } + // + // Check whether the source address is one of the interface addresses. + // + if (Private->IpChoice == PING_IP_CHOICE_IP6) { + for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) { + Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address); + + if (UnspecifiedSrc) { + if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) { + // + // Select the interface automatically. + // + CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress)); + break; + } + } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) { + // + // Match a certain interface address. + // + break; + } + } + + if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) { + // + // Found a nic handle with right interface address. + // + break; + } + } else { + if (UnspecifiedSrc) { + if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) && + !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) { + // + // Select the interface automatically. + // + break; + } + } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) { + // + // Match a certain interface address. + // + break; + } + } + + FreePool (IpXInterfaceInfo); + IpXInterfaceInfo = NULL; + } + // + // No exact interface address matched. + // + + if (HandleIndex == HandleNum) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIGD_NIC_NF), gShellNetwork1HiiHandle, L"ping"); + Status = EFI_NOT_FOUND; + goto ON_ERROR; + } + + Private->NicHandle = HandleBuffer[HandleIndex]; + + ASSERT (EfiSb != NULL); + Status = EfiSb->CreateChild (EfiSb, &Private->IpChildHandle); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + if (Private->IpChoice == PING_IP_CHOICE_IP6) { + Status = gBS->OpenProtocol ( + Private->IpChildHandle, + &gEfiIp6ProtocolGuid, + &Private->IpProtocol, + gImageHandle, + Private->IpChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + + ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA)); + + // + // Configure the ip6 instance for icmp6 packet exchange. + // + Ip6Config.DefaultProtocol = 58; + Ip6Config.AcceptAnyProtocol = FALSE; + Ip6Config.AcceptIcmpErrors = TRUE; + Ip6Config.AcceptPromiscuous = FALSE; + Ip6Config.TrafficClass = 0; + Ip6Config.HopLimit = 128; + Ip6Config.FlowLabel = 0; + Ip6Config.ReceiveTimeout = 0; + Ip6Config.TransmitTimeout = 0; + + IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress); + IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress); + + Status = ((EFI_IP6_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip6Config); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status); + goto ON_ERROR; + } + + Private->ProtocolPointers.Transmit = (PING_IPX_TRANSMIT )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Transmit; + Private->ProtocolPointers.Receive = (PING_IPX_RECEIVE )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Receive; + Private->ProtocolPointers.Cancel = (PING_IPX_CANCEL )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Cancel; + Private->ProtocolPointers.Poll = (PING_IPX_POLL )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Poll; + } else { + Status = gBS->OpenProtocol ( + Private->IpChildHandle, + &gEfiIp4ProtocolGuid, + &Private->IpProtocol, + gImageHandle, + Private->IpChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + + ZeroMem (&Ip4Config, sizeof (EFI_IP4_CONFIG_DATA)); + + // + // Configure the ip4 instance for icmp4 packet exchange. + // + Ip4Config.DefaultProtocol = 1; + Ip4Config.AcceptAnyProtocol = FALSE; + Ip4Config.AcceptBroadcast = FALSE; + Ip4Config.AcceptIcmpErrors = TRUE; + Ip4Config.AcceptPromiscuous = FALSE; + Ip4Config.DoNotFragment = FALSE; + Ip4Config.RawData = FALSE; + Ip4Config.ReceiveTimeout = 0; + Ip4Config.TransmitTimeout = 0; + Ip4Config.UseDefaultAddress = TRUE; + Ip4Config.TimeToLive = 128; + Ip4Config.TypeOfService = 0; + + Status = ((EFI_IP4_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip4Config); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status); + goto ON_ERROR; + } + + Private->ProtocolPointers.Transmit = (PING_IPX_TRANSMIT )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Transmit; + Private->ProtocolPointers.Receive = (PING_IPX_RECEIVE )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Receive; + Private->ProtocolPointers.Cancel = (PING_IPX_CANCEL )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Cancel; + Private->ProtocolPointers.Poll = (PING_IPX_POLL )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Poll; + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; + +ON_ERROR: + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + if (IpXInterfaceInfo != NULL) { + FreePool (IpXInterfaceInfo); + } + + if ((EfiSb != NULL) && (Private->IpChildHandle != NULL)) { + EfiSb->DestroyChild (EfiSb, Private->IpChildHandle); + } + + return Status; +} + +/** + Destroy the IP instance. + + @param[in] Private The pointer of PING_PRIVATE_DATA. + +**/ +VOID +Ping6DestroyIp6Instance ( + IN PING_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + EFI_SERVICE_BINDING_PROTOCOL *IpSb; + + gBS->CloseProtocol ( + Private->IpChildHandle, + Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ProtocolGuid:&gEfiIp4ProtocolGuid, + gImageHandle, + Private->IpChildHandle + ); + + Status = gBS->HandleProtocol ( + Private->NicHandle, + Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid, + (VOID **) &IpSb + ); + + if (!EFI_ERROR(Status)) { + IpSb->DestroyChild (IpSb, Private->IpChildHandle); + } +} + + +/** + The Ping Process. + + @param[in] SendNumber The send request count. + @param[in] BufferSize The send buffer size. + @param[in] SrcAddress The source address. + @param[in] DstAddress The destination address. + @param[in] IpChoice The choice between IPv4 and IPv6. + + @retval SHELL_SUCCESS The ping processed successfullly. + @retval others The ping processed unsuccessfully. +**/ +SHELL_STATUS +ShellPing ( + IN UINT32 SendNumber, + IN UINT32 BufferSize, + IN EFI_IPv6_ADDRESS *SrcAddress, + IN EFI_IPv6_ADDRESS *DstAddress, + IN UINT32 IpChoice + ) +{ + EFI_STATUS Status; + PING_PRIVATE_DATA *Private; + PING_ICMPX_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + Private = AllocateZeroPool (sizeof (PING_PRIVATE_DATA)); + + if (Private == NULL) { + return (SHELL_OUT_OF_RESOURCES); + } + + Private->IpChoice = IpChoice; + Private->Signature = PING_PRIVATE_DATA_SIGNATURE; + Private->SendNum = SendNumber; + Private->BufferSize = BufferSize; + Private->RttMin = ~((UINT64 )(0x0)); + Private->Status = EFI_NOT_READY; + + CopyMem(&Private->SrcAddress, SrcAddress, sizeof(Private->SrcAddress)); + CopyMem(&Private->DstAddress, DstAddress, sizeof(Private->DstAddress)); + + InitializeListHead (&Private->TxList); + + // + // Open and configure a ip instance for us. + // + Status = PingCreateIpInstance (Private); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Print the command line itself. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_START), gShellNetwork1HiiHandle, mDstString, Private->BufferSize); + // + // Create a ipv6 token to receive the first icmp6 echo reply packet. + // + Status = Ping6ReceiveEchoReply (Private); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Create and start timer to send icmp6 echo request packet per second. + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnTimerRoutine, + Private, + &Private->Timer + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Start a timer to calculate the RTT. + // + Status = PingInitRttTimer (Private); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Create a ipv6 token to send the first icmp6 echo request packet. + // + Status = PingSendEchoRequest (Private); + // + // EFI_NOT_READY for IPsec is enable and IKE is not established. + // + if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { + ShellStatus = SHELL_ACCESS_DENIED; + if(Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOSOURCE_INDO), gShellNetwork1HiiHandle, mDstString); + } else if (Status == RETURN_NO_MAPPING) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, L"ping", Status); + } + + goto ON_EXIT; + } + + Status = gBS->SetTimer ( + Private->Timer, + TimerPeriodic, + ONE_SECOND + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Control the ping6 process by two factors: + // 1. Hot key + // 2. Private->Status + // 2.1. success means all icmp6 echo request packets get reply packets. + // 2.2. timeout means the last icmp6 echo reply request timeout to get reply. + // 2.3. noready means ping6 process is on-the-go. + // + while (Private->Status == EFI_NOT_READY) { + Status = Private->ProtocolPointers.Poll (Private->IpProtocol); + if (ShellGetExecutionBreakFlag()) { + Private->Status = EFI_ABORTED; + goto ON_STAT; + } + } + +ON_STAT: + // + // Display the statistics in all. + // + gBS->SetTimer (Private->Timer, TimerCancel, 0); + + if (Private->TxCount != 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING_STAT), + gShellNetwork1HiiHandle, + Private->TxCount, + (Private->RxCount - Private->FailedCount), + (100 - ((100 * (Private->RxCount - Private->FailedCount)) / Private->TxCount)), + Private->RttSum + ); + } + + if (Private->RxCount > Private->FailedCount) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING_RTT), + gShellNetwork1HiiHandle, + Private->RttMin, + Private->RttMin + Private->TimerPeriod, + Private->RttMax, + Private->RttMax + Private->TimerPeriod, + DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL), + DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL) + Private->TimerPeriod + ); + } + +ON_EXIT: + + if (Private != NULL) { + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link); + + if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) { + Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token); + } + + RemoveEntryList (&TxInfo->Link); + PingDestroyTxInfo (TxInfo, Private->IpChoice); + } + + PingFreeRttTimer (Private); + + if (Private->Timer != NULL) { + gBS->CloseEvent (Private->Timer); + } + + if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) { + Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, &Private->RxToken); + } + + if (Private->RxToken.Event != NULL) { + gBS->CloseEvent (Private->RxToken.Event); + } + + if (Private->IpChildHandle != NULL) { + Ping6DestroyIp6Instance (Private); + } + + FreePool (Private); + } + + return ShellStatus; +} + +/** + Function for 'ping' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @retval SHELL_SUCCESS The ping processed successfullly. + @retval others The ping processed unsuccessfully. + +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPing ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + EFI_IPv6_ADDRESS DstAddress; + EFI_IPv6_ADDRESS SrcAddress; + UINT64 BufferSize; + UINTN SendNumber; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *ValueStr; + UINTN NonOptionCount; + UINT32 IpChoice; + CHAR16 *ProblemParam; + + // + // we use IPv6 buffers to hold items... + // make sure this is enough space! + // + ASSERT(sizeof(EFI_IPv4_ADDRESS ) <= sizeof(EFI_IPv6_ADDRESS )); + ASSERT(sizeof(EFI_IP4_COMPLETION_TOKEN) <= sizeof(EFI_IP6_COMPLETION_TOKEN )); + + IpChoice = PING_IP_CHOICE_IP4; + + ShellStatus = SHELL_SUCCESS; + ProblemParam = NULL; + + Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + if (ShellCommandLineGetFlag (ParamPackage, L"-_ip6")) { + IpChoice = PING_IP_CHOICE_IP6; + } + + // + // Parse the parameter of count number. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n"); + if (ValueStr != NULL) { + SendNumber = ShellStrToUintn (ValueStr); + + // + // ShellStrToUintn will return 0 when input is 0 or an invalid input string. + // + if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } else { + SendNumber = DEFAULT_SEND_COUNT; + } + // + // Parse the parameter of buffer size. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l"); + if (ValueStr != NULL) { + BufferSize = ShellStrToUintn (ValueStr); + + // + // ShellStrToUintn will return 0 when input is 0 or an invalid input string. + // + if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } else { + BufferSize = DEFAULT_BUFFER_SIZE; + } + + ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS)); + ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS)); + + // + // Parse the parameter of source ip address. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s"); + if (ValueStr == NULL) { + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s"); + } + + if (ValueStr != NULL) { + mSrcString = ValueStr; + if (IpChoice == PING_IP_CHOICE_IP6) { + Status = NetLibStrToIp6 (ValueStr, &SrcAddress); + } else { + Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress); + } + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Parse the parameter of destination ip address. + // + NonOptionCount = ShellCommandLineGetCount(ParamPackage); + if (NonOptionCount < 2) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ping"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + if (NonOptionCount > 2) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle, L"ping"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1); + if (ValueStr != NULL) { + mDstString = ValueStr; + if (IpChoice == PING_IP_CHOICE_IP6) { + Status = NetLibStrToIp6 (ValueStr, &DstAddress); + } else { + Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress); + } + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + + // + // Enter into ping process. + // + ShellStatus = ShellPing ( + (UINT32)SendNumber, + (UINT32)BufferSize, + &SrcAddress, + &DstAddress, + IpChoice + ); + +ON_EXIT: + ShellCommandLineFreeVarList (ParamPackage); + return ShellStatus; +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c new file mode 100644 index 0000000..aeac3d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c @@ -0,0 +1,90 @@ +/** @file + Main file for NULL named library for network1 shell command functions. + + Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
        + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "UefiShellNetwork1CommandsLib.h" + +CONST CHAR16 gShellNetwork1FileName[] = L"ShellCommands"; +EFI_HANDLE gShellNetwork1HiiHandle = NULL; + +/** + return the file name of the help text file if not using HII. + + @return The string pointer to the file name. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameNetwork1 ( + VOID + ) +{ + return (gShellNetwork1FileName); +} + +/** + Constructor for the Shell Network1 Commands library. + + Install the handlers for Network1 UEFI Shell 2.0 profile commands. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS The shell command handlers were installed sucessfully. + @retval EFI_UNSUPPORTED The shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellNetwork1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + gShellNetwork1HiiHandle = NULL; + + // + // check our bit of the profiles mask + // + if ((PcdGet8(PcdShellProfileMask) & BIT3) == 0) { + return (EFI_SUCCESS); + } + + gShellNetwork1HiiHandle = HiiAddPackages (&gShellNetwork1HiiGuid, gImageHandle, UefiShellNetwork1CommandsLibStrings, NULL); + if (gShellNetwork1HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + // + // install our shell command handlers + // + ShellCommandRegisterCommandName(L"ping", ShellCommandRunPing , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_PING)); + ShellCommandRegisterCommandName(L"ifconfig",ShellCommandRunIfconfig , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_IFCONFIG)); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +ShellNetwork1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellNetwork1HiiHandle != NULL) { + HiiRemovePackages(gShellNetwork1HiiHandle); + } + return (EFI_SUCCESS); +} diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h new file mode 100644 index 0000000..6df747a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h @@ -0,0 +1,76 @@ +/** @file + header file for NULL named library for network1 shell command functions. + + Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_ +#define _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE gShellNetwork1HiiHandle; + +/** + Function for 'ping' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPing ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'ifconfig' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIfconfig ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf new file mode 100644 index 0000000..b7c81d7 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf @@ -0,0 +1,68 @@ +## @file +# Provides shell network1 functions +# +# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellNetwork1CommandsLib + FILE_GUID = 9A929F7E-3861-45ce-87AB-7371219AE255 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellNetwork1CommandsLibConstructor + DESTRUCTOR = ShellNetwork1CommandsLibDestructor + +[Sources.common] + UefiShellNetwork1CommandsLib.uni + UefiShellNetwork1CommandsLib.c + UefiShellNetwork1CommandsLib.h + Ping.c + Ifconfig.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + FileHandleLib + NetLib + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Protocols] + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid ## CONSUMES + gEfiIp6ProtocolGuid ## SOMETIMES_CONSUMES + gEfiIp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES + + gEfiIp4ProtocolGuid ## SOMETIMES_CONSUMES + gEfiIp4ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gShellNetwork1HiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni new file mode 100644 index 0000000..e281e67 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni @@ -0,0 +1,182 @@ +// /** +// +// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
        +// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
        +// (C) Copyright 2017 Hewlett Packard Enterprise Development LP
        +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// UefiShellNetwork1CommandsLib.uni +// +// Abstract: +// +// String definitions for UEFI Shell 2.0 network 1 commands +// +// +// **/ + +/=# + +#langdef en-US "english" + +#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n" +#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n" +#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n" +#string STR_GEN_PROBLEM_OP2 #language en-US "%H%s%N: Invalid argument - '%H%s%N'. Expected '%B%s%N' or '%B%s%N'.\r\n" +#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n" +#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n" +#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n" +#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n" +#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict.\r\n" +#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n" +#string STR_GEN_FILE_AD #language en-US "%H%s%N: Access file error - '%H%s%N'\r\n" +#string STR_GEN_CRLF #language en-US "\r\n" +#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found.\r\n" +#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n" +#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n" +#string STR_GEN_IS_DIR #language en-US "%H%s%N: '%H%s%N' is a directory\r\n" +#string STR_GEN_PROTOCOL_NF #language en-US "%H%s%N: The protocol '%H%s%N' is required and not found (%g).\r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n" + +#string STR_PING_INVALID_SOURCE #language en-US "%Ping: Require source interface option\r\n" +#string STR_PING_CONFIG #language en-US "Config %r\r\n" +#string STR_PING_GETMODE #language en-US "GetModeData %r\r\n" +#string STR_PING_GETDATA #language en-US "GetData %r\r\n" +#string STR_PING_RECEIVE #language en-US "Receive %r\r\n" +#string STR_PING_SEND_REQUEST #language en-US "Echo request sequence %d did not complete successfully.\r\n" +#string STR_PING_NOSOURCE_INDO #language en-US "There are no sources in %s's multicast domain.\r\n" +#string STR_PING_NETWORK_ERROR #language en-US "%H%s%N: Network function failed with %r\r\n" +#string STR_PING_CONFIGD_NIC_NF #language en-US "%H%s%N: No configured interfaces were found.\r\n" +#string STR_PING_NOROUTE_FOUND #language en-US "There is no route to the destination '%B%s%N' from the source '%B%s%N' was found.\r\n" +#string STR_PING_START #language en-US "Ping %s %d data bytes.\r\n" +#string STR_PING_TIMEOUT #language en-US "Echo request sequence %d timeout.\r\n" +#string STR_PING_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%d~%dms\r\n" +#string STR_PING_STAT #language en-US "\n%d packets transmitted, %d received, %d%% packet loss, time %dms\r\n" +#string STR_PING_RTT #language en-US "\nRtt(round trip time) min=%d~%dms max=%d~%dms avg=%d~%dms\r\n" + +#string STR_IFCONFIG_UNSUPPORTED_OPTION #language en-US "The option '%H%s%N' is unsupported now.\n" +#string STR_IFCONFIG_LACK_OPTION #language en-US "Flags lack. Please type 'ifConfig -?' for help info.\n" +#string STR_IFCONFIG_LACK_INTERFACE #language en-US "Lack interface name.\n" +#string STR_IFCONFIG_LACK_COMMAND #language en-US "Lack interface config option.\n" +#string STR_IFCONFIG_INVALID_INTERFACE #language en-US "Invalid interface name.\n" +#string STR_IFCONFIG_INVALID_IPADDRESS #language en-US "Invalid ipv4 address: '%H%s%N'\n" +#string STR_IFCONFIG_INVALID_GATEWAY #language en-US "Invalid gateway address: '%H%s%N'\n" +#string STR_IFCONFIG_DUPLICATE_COMMAND #language en-US "Duplicate commands. Bad command %H%s%N is skipped.\n" +#string STR_IFCONFIG_CONFLICT_COMMAND #language en-US "Conflict commands. Bad command %H%s%N is skipped.\n" +#string STR_IFCONFIG_UNKNOWN_COMMAND #language en-US "Unknown commands. Bad command %H%s%N is skipped.\n" +#string STR_IFCONFIG_SET_ADDR_FAILED #language en-US "Failed to set address.\n" +#string STR_IFCONFIG_ROUTES_SIZE #language en-US "\n%H Routes (%d entries):\n" +#string STR_IFCONFIG_ROUTES_ENTRY_INDEX #language en-US "%H Entry[%d]\n" +#string STR_IFCONFIG_SHOW_IP_ADDR #language en-US "%12s: %N%d.%d.%d.%d\n" +#string STR_IFCONFIG_INFO_NEWLINE #language en-US "\n" +#string STR_IFCONFIG_INFO_DNS_ADDR_BODY #language en-US "%8d.%d.%d.%d\n" +#string STR_IFCONFIG_INFO_BREAK #language en-US "\n-----------------------------------------------------------------\n" +#string STR_IFCONFIG_INFO_COLON #language en-US ":" +#string STR_IFCONFIG_INFO_IF_NAME #language en-US "\n%Hname : %s%N\n" +#string STR_IFCONFIG_INFO_MEDIA_STATE #language en-US "%HMedia State : %s%N\n" +#string STR_IFCONFIG_INFO_POLICY_DHCP #language en-US "%Hpolicy : dhcp%N\n" +#string STR_IFCONFIG_INFO_POLICY_MAN #language en-US "%Hpolicy : static%N\n" +#string STR_IFCONFIG_INFO_MAC_ADDR_HEAD #language en-US "%Hmac addr : %N" +#string STR_IFCONFIG_INFO_MAC_ADDR_BODY #language en-US "%02x" +#string STR_IFCONFIG_INFO_IP_ADDR_HEAD #language en-US "\n%Hipv4 address : %N" +#string STR_IFCONFIG_INFO_SUBNET_MASK_HEAD #language en-US "\n%Hsubnet mask : %N" +#string STR_IFCONFIG_INFO_GATEWAY_HEAD #language en-US "\n%Hdefault gateway: %N" +#string STR_IFCONFIG_INFO_DNS_ADDR_HEAD #language en-US "\n%HDNS server : %N\n" +#string STR_IFCONFIG_INFO_IP_ADDR_BODY #language en-US "%d.%d.%d.%d\n" + +#string STR_GET_HELP_PING #language en-US "" +".TH ping 0 "Ping the target host with an IPv4 stack."\r\n" +".SH NAME\r\n" +"Ping the target host with an IPv4 stack.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"PING [-n count] [-l size] [-s SourceIp] TargetIp\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -n - Specifies the number of echo request datagrams to be sent.\r\n" +" -l - Specifies the size of the data buffer in the echo request datagram.\r\n" +" -s - Specifies the source adapter as IPv4 address.\r\n" +" SourceIp - Specifies the IPv4 address of the source machine.\r\n" +" TargetIp - Specifies the IPv4 address of the target machine.\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command uses the ICMPv4 ECHO_REQUEST datagram to elicit an\r\n" +" ECHO_REPLY from a host.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To ping the target host with 64 bytes data:\r\n" +" fs0:\> ping -l 64 192.168.0.1\r\n" +" \r\n" +" * To ping the target host by sending 20 echo request datagrams:\r\n" +" fs0:\> ping -n 20 202.120.100.1\r\n" +" \r\n" +" * To ping the target host by specifying the source adapter as IPv4 address:\r\n" +" fs0:\> ping -s 202.120.100.12 202.120.100.1\r\n" +".SH RETURNVALUES\r\n" +" \r\n" +"RETURN VALUES:\r\n" +" SHELL_SUCCESS The action was completed as requested.\r\n" +" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n" +" formatted or its value was out of bounds.\r\n" + +#string STR_GET_HELP_IFCONFIG #language en-US "" +".TH ifconfig 0 "Modifies the default IP address of the UEFI IPv4 Network Stack."\r\n" +".SH NAME\r\n" +"Modifies the default IP address of the UEFI IPv4 Network Stack.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"IFCONFIG [-r [Name]] [-l [Name]]\r\n" +"IFCONFIG [-s dhcp | > | >]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -r - Renew configuration of interface and set dhcp policy.\r\n" +" -l - Lists the configuration.\r\n" +" -s - Sets the configuration.\r\n" +" Name - Specifies an adapter name (for example, eth0).\r\n" +" IP - Specifies the IPv4 address in four integer values:\r\n" +" - Example: 192.168.0.10\r\n" +" SubnetMask - Specifies a subnet mask in four integer values:\r\n" +" - Example: 255.255.255.0\r\n" +" GatewayMask - Specifies a default gateway in four integer values:\r\n" +" - Example: 192.168.0.1\r\n" +".SH DESCRIPTION\r\n" +" \r\n" +"NOTES:\r\n" +" 1. This command modifies the default IP address for the UEFI IPv4\r\n" +" network stack.\r\n" +" 2. Use '-r' to renew configuration of interface and set dhcp policy.\r\n" +" 3. Use '-l' to list the DNS and other address related settings for all\r\n" +" interfaces or the specified interface.\r\n" +" 4. Use '-s static ' with \r\n" +" static IPv4 address configuration for specified interface.\r\n" +" 5. Use '-s dhcp' for DHCPv4 to request the IPv4 address\r\n" +" configuration dynamically for specified interface.\r\n" +" 6. Use '-s dns ' must under manual policy.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To list the configuration for the eth0 interface:\r\n" +" fs0:\> ifconfig -l eth0\r\n" +" \r\n" +" * To use DHCPv4 to request the IPv4 address configuration dynamically for the\r\n" +" eth0 interface:\r\n" +" fs0:\> ifconfig -s eth0 dhcp\r\n" +" \r\n" +" * To use the static IPv4 address configuration for the eth0 interface:\r\n" +" fs0:\> ifconfig -s eth0 static 192.168.0.5 255.255.255.0 192.168.0.1\r\n" +" \r\n" +" * To configure DNS server address for the eth0 interface:\r\n" +" fs0:\> ifconfig -s eth0 dns 192.168.0.8 192.168.0.9\r\n" + + + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c new file mode 100644 index 0000000..5ff0d60 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c @@ -0,0 +1,1912 @@ +/** @file + The implementation for Shell command IfConfig6. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + (C) Copyright 2017 Hewlett Packard Enterprise Development LP
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "UefiShellNetwork2CommandsLib.h" + +enum { + IfConfig6OpList = 1, + IfConfig6OpSet = 2, + IfConfig6OpClear = 3 +}; + +typedef enum { + VarCheckReserved = -1, + VarCheckOk = 0, + VarCheckDuplicate, + VarCheckConflict, + VarCheckUnknown, + VarCheckLackValue, + VarCheckOutOfMem +} VAR_CHECK_CODE; + +typedef enum { + FlagTypeSingle = 0, + FlagTypeNeedVar, + FlagTypeNeedSet, + FlagTypeSkipUnknown +} VAR_CHECK_FLAG_TYPE; + +#define MACADDRMAXSIZE 32 +#define PREFIXMAXLEN 16 + +typedef struct _IFCONFIG6_INTERFACE_CB { + EFI_HANDLE NicHandle; + LIST_ENTRY Link; + EFI_IP6_CONFIG_PROTOCOL *IfCfg; + EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo; + EFI_IP6_CONFIG_INTERFACE_ID *IfId; + EFI_IP6_CONFIG_POLICY Policy; + EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS Xmits; + UINT32 DnsCnt; + EFI_IPv6_ADDRESS DnsAddr[1]; +} IFCONFIG6_INTERFACE_CB; + +typedef struct _ARG_LIST ARG_LIST; + +struct _ARG_LIST { + ARG_LIST *Next; + CHAR16 *Arg; +}; + +typedef struct _IFCONFIG6_PRIVATE_DATA { + EFI_HANDLE ImageHandle; + LIST_ENTRY IfList; + + UINT32 OpCode; + CHAR16 *IfName; + ARG_LIST *VarArg; +} IFCONFIG6_PRIVATE_DATA; + +typedef struct _VAR_CHECK_ITEM{ + CHAR16 *FlagStr; + UINT32 FlagID; + UINT32 ConflictMask; + VAR_CHECK_FLAG_TYPE FlagType; +} VAR_CHECK_ITEM; + + +SHELL_PARAM_ITEM mIfConfig6CheckList[] = { + { + L"-b", + TypeFlag + }, + { + L"-s", + TypeMaxValue + }, + { + L"-l", + TypeValue + }, + { + L"-r", + TypeValue + }, + { + L"-?", + TypeFlag + }, + { + NULL, + TypeMax + }, +}; + +VAR_CHECK_ITEM mIfConfig6SetCheckList[] = { + { + L"auto", + 0x00000001, + 0x00000001, + FlagTypeSingle + }, + { + L"man", + 0x00000002, + 0x00000001, + FlagTypeSingle + }, + { + L"host", + 0x00000004, + 0x00000002, + FlagTypeSingle + }, + { + L"dad", + 0x00000008, + 0x00000004, + FlagTypeSingle + }, + { + L"gw", + 0x00000010, + 0x00000008, + FlagTypeSingle + }, + { + L"dns", + 0x00000020, + 0x00000010, + FlagTypeSingle + }, + { + L"id", + 0x00000040, + 0x00000020, + FlagTypeSingle + }, + { + NULL, + 0x0, + 0x0, + FlagTypeSkipUnknown + }, +}; + +/** + Free the ARG_LIST. + + @param List Pointer to ARG_LIST to free. +**/ +VOID +IfConfig6FreeArgList ( + ARG_LIST *List +) +{ + ARG_LIST *Next; + while (List->Next != NULL) { + Next = List->Next; + FreePool (List); + List = Next; + } + + FreePool (List); +} + +/** + Split a string with specified separator and save the substring to a list. + + @param[in] String The pointer of the input string. + @param[in] Separator The specified separator. + + @return The pointer of headnode of ARG_LIST. + +**/ +ARG_LIST * +IfConfig6SplitStrToList ( + IN CONST CHAR16 *String, + IN CHAR16 Separator + ) +{ + CHAR16 *Str; + CHAR16 *ArgStr; + ARG_LIST *ArgList; + ARG_LIST *ArgNode; + + if (String == NULL || *String == L'\0') { + return NULL; + } + + // + // Copy the CONST string to a local copy. + // + Str = AllocateCopyPool (StrSize (String), String); + if (Str == NULL) { + return NULL; + } + ArgStr = Str; + + // + // init a node for the list head. + // + ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST)); + if (ArgNode == NULL) { + return NULL; + } + ArgList = ArgNode; + + // + // Split the local copy and save in the list node. + // + while (*Str != L'\0') { + if (*Str == Separator) { + *Str = L'\0'; + ArgNode->Arg = ArgStr; + ArgStr = Str + 1; + ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST)); + if (ArgNode->Next == NULL) { + // + // Free the local copy of string stored in the first node + // + FreePool (ArgList->Arg); + IfConfig6FreeArgList (ArgList); + return NULL; + } + ArgNode = ArgNode->Next; + } + + Str++; + } + + ArgNode->Arg = ArgStr; + ArgNode->Next = NULL; + + return ArgList; +} + +/** + Check the correctness of input Args with '-s' option. + + @param[in] CheckList The pointer of VAR_CHECK_ITEM array. + @param[in] Name The pointer of input arg. + @param[in] Init The switch to execute the check. + + @return The value of VAR_CHECK_CODE. + +**/ +VAR_CHECK_CODE +IfConfig6RetriveCheckListByName( + IN VAR_CHECK_ITEM *CheckList, + IN CHAR16 *Name, + IN BOOLEAN Init +) +{ + STATIC UINT32 CheckDuplicate; + STATIC UINT32 CheckConflict; + VAR_CHECK_CODE RtCode; + UINT32 Index; + VAR_CHECK_ITEM Arg; + + if (Init) { + CheckDuplicate = 0; + CheckConflict = 0; + return VarCheckOk; + } + + RtCode = VarCheckOk; + Index = 0; + Arg = CheckList[Index]; + + // + // Check the Duplicated/Conflicted/Unknown input Args. + // + while (Arg.FlagStr != NULL) { + if (StrCmp (Arg.FlagStr, Name) == 0) { + + if (CheckDuplicate & Arg.FlagID) { + RtCode = VarCheckDuplicate; + break; + } + + if (CheckConflict & Arg.ConflictMask) { + RtCode = VarCheckConflict; + break; + } + + CheckDuplicate |= Arg.FlagID; + CheckConflict |= Arg.ConflictMask; + break; + } + + Arg = CheckList[++Index]; + } + + if (Arg.FlagStr == NULL) { + RtCode = VarCheckUnknown; + } + + return RtCode; +} + +/** + The notify function of create event when performing a manual config. + + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. + +**/ +VOID +EFIAPI +IfConfig6ManualAddressNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + *((BOOLEAN *) Context) = TRUE; +} + +/** + Print MAC address. + + @param[in] Node The pointer of MAC address buffer. + @param[in] Size The size of MAC address buffer. + +**/ +VOID +IfConfig6PrintMacAddr ( + IN UINT8 *Node, + IN UINT32 Size + ) +{ + UINTN Index; + + ASSERT (Size <= MACADDRMAXSIZE); + + for (Index = 0; Index < Size; Index++) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_BODY), gShellNetwork2HiiHandle, Node[Index]); + if (Index + 1 < Size) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle); + } + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle); +} + +/** + Print IPv6 address. + + @param[in] Ip The pointer of Ip bufffer in EFI_IPv6_ADDRESS format. + @param[in] PrefixLen The pointer of PrefixLen that describes the size Prefix. + +**/ +VOID +IfConfig6PrintIpAddr ( + IN EFI_IPv6_ADDRESS *Ip, + IN UINT8 *PrefixLen + ) +{ + UINTN Index; + BOOLEAN Short; + + Short = FALSE; + + for (Index = 0; Index < PREFIXMAXLEN; Index = Index + 2) { + + if (!Short && (Index + 1 < PREFIXMAXLEN) && (Index % 2 == 0) && (Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0)) { + // + // Deal with the case of ::. + // + if (Index == 0) { + // + // :: is at the beginning of the address. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle); + } + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle); + + while ((Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0) && (Index < PREFIXMAXLEN)) { + Index = Index + 2; + if (Index > PREFIXMAXLEN - 2) { + break; + } + } + + Short = TRUE; + + if (Index == PREFIXMAXLEN) { + // + // :: is at the end of the address. + // + break; + } + } + + if (Index < PREFIXMAXLEN - 1) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index]); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index + 1]); + } + + if (Index + 2 < PREFIXMAXLEN) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle); + } + } + + if (PrefixLen != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), gShellNetwork2HiiHandle, *PrefixLen); + } +} + +/** + Pick up host IPv6 address in string format from Args with "-s" option and convert it to EFI_IP6_CONFIG_MANUAL_ADDRESS format. + + @param[in, out] Arg The pointer of the address of ARG_LIST which save Args with the "-s" option. + @param[out] Buf The pointer of the address of EFI_IP6_CONFIG_MANUAL_ADDRESS. + @param[out] BufSize The pointer of BufSize that describes the size of Buf in bytes. + + @retval EFI_SUCCESS The convertion is successful. + @retval Others Does't find the host address, or it is an invalid IPv6 address in string format. + +**/ +EFI_STATUS +IfConfig6ParseManualAddressList ( + IN OUT ARG_LIST **Arg, + OUT EFI_IP6_CONFIG_MANUAL_ADDRESS **Buf, + OUT UINTN *BufSize + ) +{ + EFI_STATUS Status; + EFI_IP6_CONFIG_MANUAL_ADDRESS *AddrBuf; + ARG_LIST *VarArg; + EFI_IPv6_ADDRESS Address; + UINT8 Prefix; + UINT8 AddrCnt; + + Prefix = 0; + AddrCnt = 0; + *BufSize = 0; + *Buf = NULL; + VarArg = *Arg; + Status = EFI_SUCCESS; + + // + // Go through the list to check the correctness of input host ip6 address. + // + while ((!EFI_ERROR (Status)) && (VarArg != NULL)) { + + Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix); + + if (EFI_ERROR (Status)) { + // + // host ip ip ... gw + // + break; + } + + VarArg = VarArg->Next; + AddrCnt++; + } + + if (AddrCnt == 0) { + return EFI_INVALID_PARAMETER; + } + + AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); + ASSERT (AddrBuf != NULL); + + AddrCnt = 0; + VarArg = *Arg; + Status = EFI_SUCCESS; + + // + // Go through the list to fill in the EFI_IP6_CONFIG_MANUAL_ADDRESS structure. + // + while ((!EFI_ERROR (Status)) && (VarArg != NULL)) { + + Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix); + + if (EFI_ERROR (Status)) { + break; + } + + // + // If prefix length is not set, set it as Zero here. In the IfConfigSetInterfaceInfo() + // Zero prefix, length will be transfered to default prefix length. + // + if (Prefix == 0xFF) { + Prefix = 0; + } + AddrBuf[AddrCnt].IsAnycast = FALSE; + AddrBuf[AddrCnt].PrefixLength = Prefix; + IP6_COPY_ADDRESS (&AddrBuf[AddrCnt].Address, &Address); + VarArg = VarArg->Next; + AddrCnt++; + } + + *Arg = VarArg; + + if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) { + goto ON_ERROR; + } + + *Buf = AddrBuf; + *BufSize = AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS); + + return EFI_SUCCESS; + +ON_ERROR: + + FreePool (AddrBuf); + return Status; +} + +/** + Pick up gw/dns IPv6 address in string format from Args with "-s" option and convert it to EFI_IPv6_ADDRESS format. + + @param[in, out] Arg The pointer of the address of ARG_LIST that save Args with the "-s" option. + @param[out] Buf The pointer of the address of EFI_IPv6_ADDRESS. + @param[out] BufSize The pointer of BufSize that describes the size of Buf in bytes. + + @retval EFI_SUCCESS The conversion is successful. + @retval Others Doesn't find the host address, or it is an invalid IPv6 address in string format. + +**/ +EFI_STATUS +IfConfig6ParseGwDnsAddressList ( + IN OUT ARG_LIST **Arg, + OUT EFI_IPv6_ADDRESS **Buf, + OUT UINTN *BufSize + ) +{ + EFI_STATUS Status; + EFI_IPv6_ADDRESS *AddrBuf; + ARG_LIST *VarArg; + EFI_IPv6_ADDRESS Address; + UINT8 Prefix; + UINT8 AddrCnt; + + AddrCnt = 0; + *BufSize = 0; + *Buf = NULL; + VarArg = *Arg; + Status = EFI_SUCCESS; + + // + // Go through the list to check the correctness of input gw/dns address. + // + while ((!EFI_ERROR (Status)) && (VarArg != NULL)) { + + Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix); + + if (EFI_ERROR (Status)) { + // + // gw ip ip ... host + // + break; + } + + VarArg = VarArg->Next; + AddrCnt++; + } + + if (AddrCnt == 0) { + return EFI_INVALID_PARAMETER; + } + + AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IPv6_ADDRESS)); + ASSERT (AddrBuf != NULL); + + AddrCnt = 0; + VarArg = *Arg; + Status = EFI_SUCCESS; + + // + // Go through the list to fill in the EFI_IPv6_ADDRESS structure. + // + while ((!EFI_ERROR (Status)) && (VarArg != NULL)) { + + Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix); + + if (EFI_ERROR (Status)) { + break; + } + + IP6_COPY_ADDRESS (&AddrBuf[AddrCnt], &Address); + + VarArg = VarArg->Next; + AddrCnt++; + } + + *Arg = VarArg; + + if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) { + goto ON_ERROR; + } + + *Buf = AddrBuf; + *BufSize = AddrCnt * sizeof (EFI_IPv6_ADDRESS); + + return EFI_SUCCESS; + +ON_ERROR: + + FreePool (AddrBuf); + return Status; +} + +/** + Parse InterfaceId in string format from Args with the "-s" option and convert it to EFI_IP6_CONFIG_INTERFACE_ID format. + + @param[in, out] Arg The pointer of the address of ARG_LIST that saves Args with the "-s" option. + @param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID. + + @retval EFI_SUCCESS The get status processed successfullly. + @retval EFI_INVALID_PARAMETER The get status process failed. + +**/ +EFI_STATUS +IfConfig6ParseInterfaceId ( + IN OUT ARG_LIST **Arg, + OUT EFI_IP6_CONFIG_INTERFACE_ID **IfId + ) +{ + UINT8 Index; + UINT8 NodeVal; + CHAR16 *IdStr; + + if (*Arg == NULL) { + return EFI_INVALID_PARAMETER; + } + + Index = 0; + IdStr = (*Arg)->Arg; + ASSERT (IfId != NULL); + *IfId = AllocateZeroPool (sizeof (EFI_IP6_CONFIG_INTERFACE_ID)); + ASSERT (*IfId != NULL); + + while ((*IdStr != L'\0') && (Index < 8)) { + + NodeVal = 0; + while ((*IdStr != L':') && (*IdStr != L'\0')) { + + if ((*IdStr <= L'F') && (*IdStr >= L'A')) { + NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'A' + 10); + } else if ((*IdStr <= L'f') && (*IdStr >= L'a')) { + NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'a' + 10); + } else if ((*IdStr <= L'9') && (*IdStr >= L'0')) { + NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'0'); + } else { + FreePool (*IfId); + return EFI_INVALID_PARAMETER; + } + + IdStr++; + } + + (*IfId)->Id[Index++] = NodeVal; + + if (*IdStr == L':') { + IdStr++; + } + } + + *Arg = (*Arg)->Next; + return EFI_SUCCESS; +} + +/** + Parse dad in string format from Args with the "-s" option and convert it to UINT32 format. + + @param[in, out] Arg The pointer of the address of ARG_LIST that saves Args with the "-s" option. + @param[out] Xmits The pointer of Xmits. + + @retval EFI_SUCCESS The get status processed successfully. + @retval others The get status process failed. + +**/ +EFI_STATUS +IfConfig6ParseDadXmits ( + IN OUT ARG_LIST **Arg, + OUT UINT32 *Xmits + ) +{ + CHAR16 *ValStr; + + if (*Arg == NULL) { + return EFI_INVALID_PARAMETER; + } + + ValStr = (*Arg)->Arg; + *Xmits = 0; + + while (*ValStr != L'\0') { + + if ((*ValStr <= L'9') && (*ValStr >= L'0')) { + + *Xmits = (*Xmits * 10) + (*ValStr - L'0'); + + } else { + + return EFI_INVALID_PARAMETER; + } + + ValStr++; + } + + *Arg = (*Arg)->Next; + return EFI_SUCCESS; +} + +/** + The get current status of all handles. + + @param[in] ImageHandle The handle of ImageHandle. + @param[in] IfName The pointer of IfName(interface name). + @param[in] IfList The pointer of IfList(interface list). + + @retval EFI_SUCCESS The get status processed successfully. + @retval others The get status process failed. + +**/ +EFI_STATUS +IfConfig6GetInterfaceInfo ( + IN EFI_HANDLE ImageHandle, + IN CHAR16 *IfName, + IN LIST_ENTRY *IfList + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + UINTN HandleNum; + EFI_HANDLE *HandleBuffer; + EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; + EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo; + IFCONFIG6_INTERFACE_CB *IfCb; + UINTN DataSize; + + HandleBuffer = NULL; + HandleNum = 0; + + IfInfo = NULL; + IfCb = NULL; + + // + // Locate all the handles with ip6 service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIp6ServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status) || (HandleNum == 0)) { + return Status; + } + + // + // Enumerate all handles that installed with ip6 service binding protocol. + // + for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) { + IfCb = NULL; + IfInfo = NULL; + DataSize = 0; + + // + // Ip6config protocol and ip6 service binding protocol are installed + // on the same handle. + // + ASSERT (HandleBuffer != NULL); + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + &gEfiIp6ConfigProtocolGuid, + (VOID **) &Ip6Cfg + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + // + // Get the interface information size. + // + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeInterfaceInfo, + &DataSize, + NULL + ); + + if (Status != EFI_BUFFER_TOO_SMALL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + + IfInfo = AllocateZeroPool (DataSize); + + if (IfInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + // + // Get the interface info. + // + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeInterfaceInfo, + &DataSize, + IfInfo + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + // + // Check the interface name if required. + // + if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) { + FreePool (IfInfo); + continue; + } + + DataSize = 0; + // + // Get the size of dns server list. + // + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeDnsServer, + &DataSize, + NULL + ); + + if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + + IfCb = AllocateZeroPool (sizeof (IFCONFIG6_INTERFACE_CB) + DataSize); + + if (IfCb == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + + IfCb->NicHandle = HandleBuffer[HandleIndex]; + IfCb->IfInfo = IfInfo; + IfCb->IfCfg = Ip6Cfg; + IfCb->DnsCnt = (UINT32) (DataSize / sizeof (EFI_IPv6_ADDRESS)); + + // + // Get the dns server list if has. + // + if (DataSize > 0) { + + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeDnsServer, + &DataSize, + IfCb->DnsAddr + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + } + // + // Get the interface id if has. + // + DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID); + IfCb->IfId = AllocateZeroPool (DataSize); + + if (IfCb->IfId == NULL) { + goto ON_ERROR; + } + + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeAltInterfaceId, + &DataSize, + IfCb->IfId + ); + + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + + if (Status == EFI_NOT_FOUND) { + FreePool (IfCb->IfId); + IfCb->IfId = NULL; + } + // + // Get the config policy. + // + DataSize = sizeof (EFI_IP6_CONFIG_POLICY); + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypePolicy, + &DataSize, + &IfCb->Policy + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + // + // Get the dad transmits. + // + DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeDupAddrDetectTransmits, + &DataSize, + &IfCb->Xmits + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + + InsertTailList (IfList, &IfCb->Link); + + if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) { + // + // Only need the appointed interface, keep the allocated buffer. + // + IfCb = NULL; + IfInfo = NULL; + break; + } + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; + +ON_ERROR: + + if (IfInfo != NULL) { + FreePool (IfInfo); + } + + if (IfCb != NULL) { + if (IfCb->IfId != NULL) { + FreePool (IfCb->IfId); + } + + FreePool (IfCb); + } + + return Status; +} + +/** + The list process of the IfConfig6 application. + + @param[in] IfList The pointer of IfList(interface list). + + @retval SHELL_SUCCESS The IfConfig6 list processed successfully. + @retval others The IfConfig6 list process failed. + +**/ +SHELL_STATUS +IfConfig6ShowInterfaceInfo ( + IN LIST_ENTRY *IfList + ) +{ + LIST_ENTRY *Entry; + IFCONFIG6_INTERFACE_CB *IfCb; + UINTN Index; + + Entry = IfList->ForwardLink; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle); + } + + // + // Go through the interface list. + // + while (Entry != IfList) { + + IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link); + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle); + + // + // Print interface name. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), gShellNetwork2HiiHandle, IfCb->IfInfo->Name); + + // + // Print interface config policy. + // + if (IfCb->Policy == Ip6ConfigPolicyAutomatic) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), gShellNetwork2HiiHandle); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), gShellNetwork2HiiHandle); + } + + // + // Print dad transmit. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), gShellNetwork2HiiHandle, IfCb->Xmits); + + // + // Print interface id if has. + // + if (IfCb->IfId != NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), gShellNetwork2HiiHandle); + + IfConfig6PrintMacAddr ( + IfCb->IfId->Id, + 8 + ); + } + // + // Print mac address of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), gShellNetwork2HiiHandle); + + IfConfig6PrintMacAddr ( + IfCb->IfInfo->HwAddress.Addr, + IfCb->IfInfo->HwAddressSize + ); + + // + // Print ip addresses list of the interface. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_HEAD), gShellNetwork2HiiHandle); + + for (Index = 0; Index < IfCb->IfInfo->AddressInfoCount; Index++) { + IfConfig6PrintIpAddr ( + &IfCb->IfInfo->AddressInfo[Index].Address, + &IfCb->IfInfo->AddressInfo[Index].PrefixLength + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle); + } + + // + // Print dns server addresses list of the interface if has. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), gShellNetwork2HiiHandle); + + for (Index = 0; Index < IfCb->DnsCnt; Index++) { + IfConfig6PrintIpAddr ( + &IfCb->DnsAddr[Index], + NULL + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle); + } + + // + // Print route table of the interface if has. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), gShellNetwork2HiiHandle); + + for (Index = 0; Index < IfCb->IfInfo->RouteCount; Index++) { + IfConfig6PrintIpAddr ( + &IfCb->IfInfo->RouteTable[Index].Destination, + &IfCb->IfInfo->RouteTable[Index].PrefixLength + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_JOINT), gShellNetwork2HiiHandle); + + IfConfig6PrintIpAddr ( + &IfCb->IfInfo->RouteTable[Index].Gateway, + NULL + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle); + } + + Entry = Entry->ForwardLink; + } + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle); + + return SHELL_SUCCESS; +} + +/** + The clean process of the IfConfig6 application. + + @param[in] IfList The pointer of IfList(interface list). + @param[in] IfName The pointer of interface name. + + @retval SHELL_SUCCESS The IfConfig6 clean processed successfully. + @retval others The IfConfig6 clean process failed. + +**/ +SHELL_STATUS +IfConfig6ClearInterfaceInfo ( + IN LIST_ENTRY *IfList, + IN CHAR16 *IfName + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + LIST_ENTRY *Entry; + IFCONFIG6_INTERFACE_CB *IfCb; + EFI_IP6_CONFIG_POLICY Policy; + + Entry = IfList->ForwardLink; + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle); + } + + // + // Go through the interface list.If the interface name is specified, then + // need to refresh the configuration. + // + while (Entry != IfList) { + + IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link); + + if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) { + Policy = Ip6ConfigPolicyManual; + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypePolicy, + sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6"); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + } + + Policy = Ip6ConfigPolicyAutomatic; + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypePolicy, + sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6"); + ShellStatus = SHELL_ACCESS_DENIED; + break; + } + + Entry = Entry->ForwardLink; + } + + return ShellStatus; +} + +/** + The set process of the IfConfig6 application. + + @param[in] IfList The pointer of IfList(interface list). + @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option). + + @retval SHELL_SUCCESS The IfConfig6 set processed successfully. + @retval others The IfConfig6 set process failed. + +**/ +SHELL_STATUS +IfConfig6SetInterfaceInfo ( + IN LIST_ENTRY *IfList, + IN ARG_LIST *VarArg + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + IFCONFIG6_INTERFACE_CB *IfCb; + EFI_IP6_CONFIG_MANUAL_ADDRESS *CfgManAddr; + EFI_IPv6_ADDRESS *CfgAddr; + UINTN AddrSize; + EFI_IP6_CONFIG_INTERFACE_ID *InterfaceId; + UINT32 DadXmits; + UINT32 CurDadXmits; + UINTN CurDadXmitsLen; + EFI_IP6_CONFIG_POLICY Policy; + + VAR_CHECK_CODE CheckCode; + EFI_EVENT TimeOutEvt; + EFI_EVENT MappedEvt; + BOOLEAN IsAddressOk; + + UINTN DataSize; + UINT32 Index; + UINT32 Index2; + BOOLEAN IsAddressSet; + EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo; + + CfgManAddr = NULL; + CfgAddr = NULL; + TimeOutEvt = NULL; + MappedEvt = NULL; + IfInfo = NULL; + InterfaceId = NULL; + CurDadXmits = 0; + + if (IsListEmpty (IfList)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle); + return SHELL_INVALID_PARAMETER; + } + // + // Make sure to set only one interface each time. + // + IfCb = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link); + Status = EFI_SUCCESS; + ShellStatus = SHELL_SUCCESS; + + // + // Initialize check list mechanism. + // + CheckCode = IfConfig6RetriveCheckListByName( + NULL, + NULL, + TRUE + ); + + // + // Create events & timers for asynchronous settings. + // + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeOutEvt + ); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + IfConfig6ManualAddressNotify, + &IsAddressOk, + &MappedEvt + ); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Parse the setting variables. + // + while (VarArg != NULL) { + // + // Check invalid parameters (duplication & unknown & conflict). + // + CheckCode = IfConfig6RetriveCheckListByName( + mIfConfig6SetCheckList, + VarArg->Arg, + FALSE + ); + + if (VarCheckOk != CheckCode) { + switch (CheckCode) { + case VarCheckDuplicate: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg); + break; + + case VarCheckConflict: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg); + break; + + case VarCheckUnknown: + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg); + break; + + default: + break; + } + + VarArg = VarArg->Next; + continue; + } + // + // Process valid variables. + // + if (StrCmp(VarArg->Arg, L"auto") == 0) { + // + // Set automaic config policy + // + Policy = Ip6ConfigPolicyAutomatic; + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypePolicy, + sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + VarArg= VarArg->Next; + + if (VarArg != NULL) { + if (StrCmp (VarArg->Arg, L"host") == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_IP_CONFIG), gShellNetwork2HiiHandle, Status); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } else if (StrCmp (VarArg->Arg, L"gw") == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_GW_CONFIG), gShellNetwork2HiiHandle, Status); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } else if (StrCmp (VarArg->Arg, L"dns") == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_DNS_CONFIG), gShellNetwork2HiiHandle, Status); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + } else if (StrCmp (VarArg->Arg, L"man") == 0) { + // + // Set manual config policy. + // + Policy = Ip6ConfigPolicyManual; + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypePolicy, + sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + VarArg= VarArg->Next; + + } else if (StrCmp (VarArg->Arg, L"host") == 0) { + // + // Parse till the next tag or the end of command line. + // + VarArg = VarArg->Next; + Status = IfConfig6ParseManualAddressList ( + &VarArg, + &CfgManAddr, + &AddrSize + ); + + if (EFI_ERROR (Status)) { + if (Status == EFI_INVALID_PARAMETER) { + ShellStatus = SHELL_INVALID_PARAMETER; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"host"); + continue; + } else { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + } + // + // Set static host ip6 address list. + // This is a asynchronous process. + // + IsAddressOk = FALSE; + + Status = IfCb->IfCfg->RegisterDataNotify ( + IfCb->IfCfg, + Ip6ConfigDataTypeManualAddress, + MappedEvt + ); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeManualAddress, + AddrSize, + CfgManAddr + ); + + if (Status == EFI_NOT_READY) { + // + // Get current dad transmits count. + // + CurDadXmitsLen = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); + IfCb->IfCfg->GetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeDupAddrDetectTransmits, + &CurDadXmitsLen, + &CurDadXmits + ); + + gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000 + 10000000 * CurDadXmits); + + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { + if (IsAddressOk) { + Status = EFI_SUCCESS; + break; + } + } + } + + IfCb->IfCfg->UnregisterDataNotify ( + IfCb->IfCfg, + Ip6ConfigDataTypeManualAddress, + MappedEvt + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_HOST), gShellNetwork2HiiHandle, Status); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Check whether the address is set successfully. + // + DataSize = 0; + + Status = IfCb->IfCfg->GetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeInterfaceInfo, + &DataSize, + NULL + ); + + if (Status != EFI_BUFFER_TOO_SMALL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + IfInfo = AllocateZeroPool (DataSize); + + if (IfInfo == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = IfCb->IfCfg->GetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeInterfaceInfo, + &DataSize, + IfInfo + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + for ( Index = 0; Index < (UINTN) (AddrSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); Index++) { + IsAddressSet = FALSE; + // + // By default, the prefix length 0 is regarded as 64. + // + if (CfgManAddr[Index].PrefixLength == 0) { + CfgManAddr[Index].PrefixLength = 64; + } + + for (Index2 = 0; Index2 < IfInfo->AddressInfoCount; Index2++) { + if (EFI_IP6_EQUAL (&IfInfo->AddressInfo[Index2].Address, &CfgManAddr[Index].Address) && + (IfInfo->AddressInfo[Index2].PrefixLength == CfgManAddr[Index].PrefixLength)) { + IsAddressSet = TRUE; + break; + } + } + + if (!IsAddressSet) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_ADDRESS_FAILED), gShellNetwork2HiiHandle); + IfConfig6PrintIpAddr ( + &CfgManAddr[Index].Address, + &CfgManAddr[Index].PrefixLength + ); + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle); + } + } + + } else if (StrCmp (VarArg->Arg, L"gw") == 0) { + // + // Parse till the next tag or the end of command line. + // + VarArg = VarArg->Next; + Status = IfConfig6ParseGwDnsAddressList ( + &VarArg, + &CfgAddr, + &AddrSize + ); + + if (EFI_ERROR (Status)) { + if (Status == EFI_INVALID_PARAMETER) { + ShellStatus = SHELL_INVALID_PARAMETER; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"gw"); + continue; + } else { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + } + // + // Set static gateway ip6 address list. + // + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeGateway, + AddrSize, + CfgAddr + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_GW), gShellNetwork2HiiHandle, Status); + goto ON_EXIT; + } + + } else if (StrCmp (VarArg->Arg, L"dns") == 0) { + // + // Parse till the next tag or the end of command line. + // + VarArg = VarArg->Next; + Status = IfConfig6ParseGwDnsAddressList ( + &VarArg, + &CfgAddr, + &AddrSize + ); + + if (EFI_ERROR (Status)) { + if (Status == EFI_INVALID_PARAMETER) { + ShellStatus = SHELL_INVALID_PARAMETER; + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"dns"); + continue; + } else { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + } + // + // Set static DNS server ip6 address list. + // + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeDnsServer, + AddrSize, + CfgAddr + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + } else if (StrCmp (VarArg->Arg, L"id") == 0) { + // + // Parse till the next tag or the end of command line. + // + VarArg = VarArg->Next; + Status = IfConfig6ParseInterfaceId (&VarArg, &InterfaceId); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + // + // Set alternative interface id. + // + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeAltInterfaceId, + sizeof (EFI_IP6_CONFIG_INTERFACE_ID), + InterfaceId + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + } else if (StrCmp (VarArg->Arg, L"dad") == 0) { + // + // Parse till the next tag or the end of command line. + // + VarArg = VarArg->Next; + Status = IfConfig6ParseDadXmits (&VarArg, &DadXmits); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Set dad transmits count. + // + Status = IfCb->IfCfg->SetData ( + IfCb->IfCfg, + Ip6ConfigDataTypeDupAddrDetectTransmits, + sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS), + &DadXmits + ); + + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + } + } + +ON_EXIT: + + if (CfgManAddr != NULL) { + FreePool (CfgManAddr); + } + + if (CfgAddr != NULL) { + FreePool (CfgAddr); + } + + if (MappedEvt != NULL) { + gBS->CloseEvent (MappedEvt); + } + + if (TimeOutEvt != NULL) { + gBS->CloseEvent (TimeOutEvt); + } + + if (IfInfo != NULL) { + FreePool (IfInfo); + } + + return ShellStatus; + +} + +/** + The IfConfig6 main process. + + @param[in] Private The pointer of IFCONFIG6_PRIVATE_DATA. + + @retval SHELL_SUCCESS IfConfig6 processed successfully. + @retval others The IfConfig6 process failed. + +**/ +SHELL_STATUS +IfConfig6 ( + IN IFCONFIG6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + + // + // Get configure information of all interfaces. + // + Status = IfConfig6GetInterfaceInfo ( + Private->ImageHandle, + Private->IfName, + &Private->IfList + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + goto ON_EXIT; + } + + switch (Private->OpCode) { + case IfConfig6OpList: + ShellStatus = IfConfig6ShowInterfaceInfo (&Private->IfList); + break; + + case IfConfig6OpClear: + ShellStatus = IfConfig6ClearInterfaceInfo (&Private->IfList, Private->IfName); + break; + + case IfConfig6OpSet: + ShellStatus = IfConfig6SetInterfaceInfo (&Private->IfList, Private->VarArg); + break; + + default: + ShellStatus = SHELL_UNSUPPORTED; + } + +ON_EXIT: + + return ShellStatus; +} + +/** + The IfConfig6 cleanup process, free the allocated memory. + + @param[in] Private The pointer of IFCONFIG6_PRIVATE_DATA. + +**/ +VOID +IfConfig6Cleanup ( + IN IFCONFIG6_PRIVATE_DATA *Private + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + IFCONFIG6_INTERFACE_CB *IfCb; + + ASSERT (Private != NULL); + + // + // Clean the list which save the set config Args. + // + if (Private->VarArg != NULL) { + IfConfig6FreeArgList (Private->VarArg); + } + + if (Private->IfName != NULL) + FreePool (Private->IfName); + + + // + // Clean the IFCONFIG6_INTERFACE_CB list. + // + Entry = Private->IfList.ForwardLink; + NextEntry = Entry->ForwardLink; + + while (Entry != &Private->IfList) { + + IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link); + + RemoveEntryList (&IfCb->Link); + + if (IfCb->IfId != NULL) { + + FreePool (IfCb->IfId); + } + + if (IfCb->IfInfo != NULL) { + + FreePool (IfCb->IfInfo); + } + + FreePool (IfCb); + + Entry = NextEntry; + NextEntry = Entry->ForwardLink; + } + + FreePool (Private); +} + +/** + Function for 'ifconfig6' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @retval SHELL_SUCCESS ifconfig6 command processed successfully. + @retval others The ifconfig6 command process failed. + +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIfconfig6 ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + IFCONFIG6_PRIVATE_DATA *Private; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *ValueStr; + ARG_LIST *ArgList; + CHAR16 *ProblemParam; + CHAR16 *Str; + + Private = NULL; + Status = EFI_INVALID_PARAMETER; + ShellStatus = SHELL_SUCCESS; + + Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), gShellNetwork2HiiHandle, L"ifconfig6", ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + // + // To handle no option. + // + if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") && + !ShellCommandLineGetFlag (ParamPackage, L"-?") && !ShellCommandLineGetFlag (ParamPackage, L"-l")) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_LACK_OPTION), gShellNetwork2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + // + // To handle conflict options. + // + if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) || + ((ShellCommandLineGetFlag (ParamPackage, L"-l")) && (ShellCommandLineGetFlag (ParamPackage, L"-?")))) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_CONFLICT_OPTIONS), gShellNetwork2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + Private = AllocateZeroPool (sizeof (IFCONFIG6_PRIVATE_DATA)); + + if (Private == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + InitializeListHead (&Private->IfList); + + // + // To get interface name for the list option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-l")) { + Private->OpCode = IfConfig6OpList; + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l"); + if (ValueStr != NULL) { + Str = AllocateCopyPool (StrSize (ValueStr), ValueStr); + if (Str == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Private->IfName = Str; + } + } + // + // To get interface name for the clear option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-r")) { + Private->OpCode = IfConfig6OpClear; + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r"); + if (ValueStr != NULL) { + Str = AllocateCopyPool (StrSize (ValueStr), ValueStr); + if (Str == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + Private->IfName = Str; + } + } + // + // To get interface name and corresponding Args for the set option. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-s")) { + + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s"); + if (ValueStr == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_INTERFACE), gShellNetwork2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + // + // To split the configuration into multi-section. + // + ArgList = IfConfig6SplitStrToList (ValueStr, L' '); + if (ArgList == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Private->OpCode = IfConfig6OpSet; + Private->IfName = ArgList->Arg; + + Private->VarArg = ArgList->Next; + + if (Private->IfName == NULL || Private->VarArg == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_COMMAND), gShellNetwork2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Main process of ifconfig6. + // + ShellStatus = IfConfig6 (Private); + +ON_EXIT: + + ShellCommandLineFreeVarList (ParamPackage); + if (Private != NULL) { + IfConfig6Cleanup (Private); + } + return ShellStatus; + +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c new file mode 100644 index 0000000..222a95a --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c @@ -0,0 +1,1373 @@ +/** @file + The implementation for Ping6 application. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellNetwork2CommandsLib.h" + +#define PING6_DEFAULT_TIMEOUT 5000 +#define PING6_MAX_SEND_NUMBER 10000 +#define PING6_MAX_BUFFER_SIZE 32768 +#define PING6_ONE_SECOND 10000000 +#define STALL_1_MILLI_SECOND 1000 + +#pragma pack(1) + +typedef struct _ICMP6_ECHO_REQUEST_REPLY { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + UINT16 Identifier; + UINT16 SequenceNum; + UINT32 TimeStamp; + UINT8 Data[1]; +} ICMP6_ECHO_REQUEST_REPLY; + +#pragma pack() + +typedef struct _PING6_ICMP6_TX_INFO { + LIST_ENTRY Link; + UINT16 SequenceNum; + UINT32 TimeStamp; + EFI_IP6_COMPLETION_TOKEN *Token; +} PING6_ICMP6_TX_INFO; + +typedef struct _PING6_PRIVATE_DATA { + EFI_HANDLE ImageHandle; + EFI_HANDLE NicHandle; + EFI_HANDLE Ip6ChildHandle; + EFI_IP6_PROTOCOL *Ip6; + EFI_EVENT Timer; + + UINT32 TimerPeriod; + UINT32 RttTimerTick; + EFI_EVENT RttTimer; + + EFI_STATUS Status; + LIST_ENTRY TxList; + EFI_IP6_COMPLETION_TOKEN RxToken; + UINT16 RxCount; + UINT16 TxCount; + UINT64 RttSum; + UINT64 RttMin; + UINT64 RttMax; + UINT32 SequenceNum; + + EFI_IPv6_ADDRESS SrcAddress; + EFI_IPv6_ADDRESS DstAddress; + UINT32 SendNum; + UINT32 BufferSize; +} PING6_PRIVATE_DATA; + + +SHELL_PARAM_ITEM Ping6ParamList[] = { + { + L"-l", + TypeValue + }, + { + L"-n", + TypeValue + }, + { + L"-s", + TypeValue + }, + { + L"-?", + TypeFlag + }, + { + NULL, + TypeMax + }, +}; + +// +// Global Variables in Ping6 application. +// +CONST CHAR16 *mIp6DstString; +CONST CHAR16 *mIp6SrcString; +EFI_CPU_ARCH_PROTOCOL *Cpu = NULL; + +/** + RTT timer tick routine. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6RttTimerTickRoutine ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 *RttTimerTick; + + RttTimerTick = (UINT32*) Context; + (*RttTimerTick)++; +} + +/** + Get the timer period of the system. + + This function tries to get the system timer period by creating + an 1ms period timer. + + @return System timer period in MS, or 0 if operation failed. + +**/ +UINT32 +Ping6GetTimerPeriod( + VOID + ) +{ + EFI_STATUS Status; + UINT32 RttTimerTick; + EFI_EVENT TimerEvent; + UINT32 StallCounter; + EFI_TPL OldTpl; + + RttTimerTick = 0; + StallCounter = 0; + + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + Ping6RttTimerTickRoutine, + &RttTimerTick, + &TimerEvent + ); + if (EFI_ERROR (Status)) { + return 0; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Status = gBS->SetTimer ( + TimerEvent, + TimerPeriodic, + TICKS_PER_MS + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (TimerEvent); + return 0; + } + + while (RttTimerTick < 10) { + gBS->Stall (STALL_1_MILLI_SECOND); + ++StallCounter; + } + + gBS->RestoreTPL (OldTpl); + + gBS->SetTimer (TimerEvent, TimerCancel, 0); + gBS->CloseEvent (TimerEvent); + + return StallCounter / RttTimerTick; +} + + +/** + Initialize the timer event for RTT (round trip time). + + @param[in] Private The pointer to PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS RTT timer is started. + @retval Others Failed to start the RTT timer. + +**/ +EFI_STATUS +Ping6InitRttTimer ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + Private->TimerPeriod = Ping6GetTimerPeriod (); + if (Private->TimerPeriod == 0) { + return EFI_ABORTED; + } + + Private->RttTimerTick = 0; + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + Ping6RttTimerTickRoutine, + &Private->RttTimerTick, + &Private->RttTimer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + Private->RttTimer, + TimerPeriodic, + TICKS_PER_MS + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (Private->RttTimer); + return Status; + } + + return EFI_SUCCESS; + +} + +/** + Free RTT timer event resource. + + @param[in] Private The pointer to PING6_PRIVATE_DATA. + +**/ +VOID +Ping6FreeRttTimer ( + IN PING6_PRIVATE_DATA *Private + ) +{ + if (Private->RttTimer != NULL) { + gBS->SetTimer (Private->RttTimer, TimerCancel, 0); + gBS->CloseEvent (Private->RttTimer); + } +} + +/** + Read the current time. + + @param[in] Private The pointer to PING6_PRIVATE_DATA. + + @retval the current tick value. +**/ +UINT32 +Ping6ReadTime ( + IN PING6_PRIVATE_DATA *Private + ) +{ + return Private->RttTimerTick; +} + +/** + Get and calculate the duration in ms. + + @param[in] Private The pointer to PING6_PRIVATE_DATA. + @param[in] Begin The start point of time. + @param[in] End The end point of time. + + @return The duration in ms. + +**/ +UINT32 +Ping6CalculateTick ( + IN PING6_PRIVATE_DATA *Private, + IN UINT32 Begin, + IN UINT32 End + ) +{ + if (End < Begin) { + return (0); + } + + return (End - Begin) * Private->TimerPeriod; + +} + +/** + Destroy IPING6_ICMP6_TX_INFO, and recollect the memory. + + @param[in] TxInfo The pointer to PING6_ICMP6_TX_INFO. + +**/ +VOID +Ping6DestroyTxInfo ( + IN PING6_ICMP6_TX_INFO *TxInfo + ) +{ + EFI_IP6_TRANSMIT_DATA *TxData; + EFI_IP6_FRAGMENT_DATA *FragData; + UINTN Index; + + ASSERT (TxInfo != NULL); + + if (TxInfo->Token != NULL) { + + if (TxInfo->Token->Event != NULL) { + gBS->CloseEvent (TxInfo->Token->Event); + } + + TxData = TxInfo->Token->Packet.TxData; + if (TxData != NULL) { + + if (TxData->OverrideData != NULL) { + FreePool (TxData->OverrideData); + } + + if (TxData->ExtHdrs != NULL) { + FreePool (TxData->ExtHdrs); + } + + for (Index = 0; Index < TxData->FragmentCount; Index++) { + FragData = TxData->FragmentTable[Index].FragmentBuffer; + if (FragData != NULL) { + FreePool (FragData); + } + } + } + + FreePool (TxInfo->Token); + } + + FreePool (TxInfo); +} + +/** + Match the request, and reply with SequenceNum/TimeStamp. + + @param[in] Private The pointer to PING6_PRIVATE_DATA. + @param[in] Packet The pointer to ICMP6_ECHO_REQUEST_REPLY. + + @retval EFI_SUCCESS The match is successful. + @retval EFI_NOT_FOUND The reply can't be matched with any request. + +**/ +EFI_STATUS +Ping6OnMatchEchoReply ( + IN PING6_PRIVATE_DATA *Private, + IN ICMP6_ECHO_REQUEST_REPLY *Packet + ) +{ + PING6_ICMP6_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link); + + if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) { + Private->RxCount++; + RemoveEntryList (&TxInfo->Link); + Ping6DestroyTxInfo (TxInfo); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + The original intention is to send a request. + Currently, the application retransmits an icmp6 echo request packet + per second in sendnumber times that is specified by the user. + Because nothing can be done here, all things move to the timer rountine. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6OnEchoRequestSent6 ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + +/** + receive reply, match and print reply infomation. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to context. + +**/ +VOID +EFIAPI +Ping6OnEchoReplyReceived6 ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + PING6_PRIVATE_DATA *Private; + EFI_IP6_COMPLETION_TOKEN *RxToken; + EFI_IP6_RECEIVE_DATA *RxData; + ICMP6_ECHO_REQUEST_REPLY *Reply; + UINT32 PayLoad; + UINT32 Rtt; + + Private = (PING6_PRIVATE_DATA *) Context; + + if (Private->Status == EFI_ABORTED) { + return; + } + + RxToken = &Private->RxToken; + RxData = RxToken->Packet.RxData; + Reply = RxData->FragmentTable[0].FragmentBuffer; + PayLoad = RxData->DataLength; + + if (RxData->Header->NextHeader != IP6_ICMP) { + goto ON_EXIT; + } + + if (!IP6_IS_MULTICAST (&Private->DstAddress) && + !EFI_IP6_EQUAL (&RxData->Header->SourceAddress, &Private->DstAddress)) { + goto ON_EXIT; + } + + if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) { + goto ON_EXIT; + } + + if (PayLoad != Private->BufferSize) { + goto ON_EXIT; + } + // + // Check whether the reply matches the sent request before. + // + Status = Ping6OnMatchEchoReply (Private, Reply); + if (EFI_ERROR(Status)) { + goto ON_EXIT; + } + // + // Display statistics on this icmp6 echo reply packet. + // + Rtt = Ping6CalculateTick (Private, Reply->TimeStamp, Ping6ReadTime (Private)); + + Private->RttSum += Rtt; + Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin; + Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax; + + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING6_REPLY_INFO), + gShellNetwork2HiiHandle, + PayLoad, + mIp6DstString, + Reply->SequenceNum, + RxData->Header->HopLimit, + Rtt, + Rtt + Private->TimerPeriod + ); + +ON_EXIT: + + if (Private->RxCount < Private->SendNum) { + // + // Continue to receive icmp6 echo reply packets. + // + RxToken->Status = EFI_ABORTED; + + Status = Private->Ip6->Receive (Private->Ip6, RxToken); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_RECEIVE), gShellNetwork2HiiHandle, Status); + Private->Status = EFI_ABORTED; + } + } else { + // + // All reply have already been received from the dest host. + // + Private->Status = EFI_SUCCESS; + } + // + // Singal to recycle the each rxdata here, not at the end of process. + // + gBS->SignalEvent (RxData->RecycleSignal); +} + +/** + Initial EFI_IP6_COMPLETION_TOKEN. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + @param[in] TimeStamp The TimeStamp of request. + @param[in] SequenceNum The SequenceNum of request. + + @return The pointer of EFI_IP6_COMPLETION_TOKEN. + +**/ +EFI_IP6_COMPLETION_TOKEN * +Ping6GenerateToken ( + IN PING6_PRIVATE_DATA *Private, + IN UINT32 TimeStamp, + IN UINT16 SequenceNum + ) +{ + EFI_STATUS Status; + EFI_IP6_COMPLETION_TOKEN *Token; + EFI_IP6_TRANSMIT_DATA *TxData; + ICMP6_ECHO_REQUEST_REPLY *Request; + + Request = AllocateZeroPool (Private->BufferSize); + + if (Request == NULL) { + return NULL; + } + // + // Assembly icmp6 echo request packet. + // + Request->Type = ICMP_V6_ECHO_REQUEST; + Request->Code = 0; + Request->SequenceNum = SequenceNum; + Request->TimeStamp = TimeStamp; + Request->Identifier = 0; + // + // Leave check sum to ip6 layer, since it has no idea of source address + // selection. + // + Request->Checksum = 0; + + TxData = AllocateZeroPool (sizeof (EFI_IP6_TRANSMIT_DATA)); + + if (TxData == NULL) { + FreePool (Request); + return NULL; + } + // + // Assembly ipv6 token for transmit. + // + TxData->OverrideData = 0; + TxData->ExtHdrsLength = 0; + TxData->ExtHdrs = NULL; + TxData->DataLength = Private->BufferSize; + TxData->FragmentCount = 1; + TxData->FragmentTable[0].FragmentBuffer = (VOID *) Request; + TxData->FragmentTable[0].FragmentLength = Private->BufferSize; + + Token = AllocateZeroPool (sizeof (EFI_IP6_COMPLETION_TOKEN)); + + if (Token == NULL) { + FreePool (Request); + FreePool (TxData); + return NULL; + } + + Token->Status = EFI_ABORTED; + Token->Packet.TxData = TxData; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnEchoRequestSent6, + Private, + &Token->Event + ); + + if (EFI_ERROR (Status)) { + FreePool (Request); + FreePool (TxData); + FreePool (Token); + return NULL; + } + + return Token; +} + +/** + Transmit the EFI_IP6_COMPLETION_TOKEN. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS Transmitted successfully. + @retval EFI_OUT_OF_RESOURCES No memory is available on the platform. + @retval others Transmitted unsuccessfully. + +**/ +EFI_STATUS +Ping6SendEchoRequest ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + PING6_ICMP6_TX_INFO *TxInfo; + + TxInfo = AllocateZeroPool (sizeof (PING6_ICMP6_TX_INFO)); + + if (TxInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TxInfo->TimeStamp = Ping6ReadTime (Private); + TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1); + + TxInfo->Token = Ping6GenerateToken ( + Private, + TxInfo->TimeStamp, + TxInfo->SequenceNum + ); + + if (TxInfo->Token == NULL) { + Ping6DestroyTxInfo (TxInfo); + return EFI_OUT_OF_RESOURCES; + } + + Status = Private->Ip6->Transmit (Private->Ip6, TxInfo->Token); + + if (EFI_ERROR (Status)) { + Ping6DestroyTxInfo (TxInfo); + return Status; + } + + InsertTailList (&Private->TxList, &TxInfo->Link); + Private->TxCount++; + + return EFI_SUCCESS; +} + +/** + Place a completion token into the receive packet queue to receive the echo reply. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS Put the token into the receive packet queue successfully. + @retval others Put the token into the receive packet queue unsuccessfully. + +**/ +EFI_STATUS +Ping6OnReceiveEchoReply ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + + ZeroMem (&Private->RxToken, sizeof (EFI_IP6_COMPLETION_TOKEN)); + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnEchoReplyReceived6, + Private, + &Private->RxToken.Event + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Private->RxToken.Status = EFI_NOT_READY; + + Status = Private->Ip6->Receive (Private->Ip6, &Private->RxToken); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_RECEIVE), gShellNetwork2HiiHandle, Status); + } + return Status; +} + +/** + Remove the timeout request from the list. + + @param[in] Event A EFI_EVENT type event. + @param[in] Context The pointer to Context. + +**/ +VOID +EFIAPI +Ping6OnTimerRoutine6 ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + PING6_PRIVATE_DATA *Private; + PING6_ICMP6_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + UINT64 Time; + + Private = (PING6_PRIVATE_DATA *) Context; + + // + // Retransmit icmp6 echo request packets per second in sendnumber times. + // + if (Private->TxCount < Private->SendNum) { + + Status = Ping6SendEchoRequest (Private); + if (Private->TxCount != 0){ + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SEND_REQUEST), gShellNetwork2HiiHandle, Private->TxCount + 1); + } + } + } + // + // Check whether any icmp6 echo request in the list timeout. + // + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link); + Time = Ping6CalculateTick (Private, TxInfo->TimeStamp, Ping6ReadTime (Private)); + + // + // Remove the timeout echo request from txlist. + // + if (Time > PING6_DEFAULT_TIMEOUT) { + + if (EFI_ERROR (TxInfo->Token->Status)) { + Private->Ip6->Cancel (Private->Ip6, TxInfo->Token); + } + // + // Remove the timeout icmp6 echo request from list. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_TIMEOUT), gShellNetwork2HiiHandle, TxInfo->SequenceNum); + + RemoveEntryList (&TxInfo->Link); + Ping6DestroyTxInfo (TxInfo); + + if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) { + // + // All the left icmp6 echo request in the list timeout. + // + Private->Status = EFI_TIMEOUT; + } + } + } +} + +/** + Create a valid IP6 instance. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + + @retval EFI_SUCCESS Create a valid IP6 instance successfully. + @retval EFI_ABORTED Locate handle with ip6 service binding protocol unsuccessfully. + @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link -ocal address. + @retval EFI_OUT_OF_RESOURCES No memory is available on the platform. + @retval EFI_NOT_FOUND The source address is not found. +**/ +EFI_STATUS +Ping6CreateIpInstance ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN HandleIndex; + UINTN HandleNum; + EFI_HANDLE *HandleBuffer; + BOOLEAN UnspecifiedSrc; + EFI_STATUS MediaStatus; + EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb; + EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; + EFI_IP6_CONFIG_DATA Ip6Config; + EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo; + UINTN IfInfoSize; + EFI_IPv6_ADDRESS *Addr; + UINTN AddrIndex; + + HandleBuffer = NULL; + UnspecifiedSrc = FALSE; + MediaStatus = EFI_SUCCESS; + Ip6Sb = NULL; + IfInfo = NULL; + IfInfoSize = 0; + + // + // Locate all the handles with ip6 service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIp6ServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status) || (HandleNum == 0)) { + return EFI_ABORTED; + } + + if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) { + // + // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected. + // + UnspecifiedSrc = TRUE; + } + + // + // Source address is required when pinging a link-local address. + // + if (NetIp6IsLinkLocalAddr (&Private->DstAddress) && UnspecifiedSrc) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), gShellNetwork2HiiHandle); + Status = EFI_INVALID_PARAMETER; + goto ON_ERROR; + } + + // + // For each ip6 protocol, check interface addresses list. + // + for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) { + + Ip6Sb = NULL; + IfInfo = NULL; + IfInfoSize = 0; + + if (UnspecifiedSrc) { + // + // Check media. + // + NetLibDetectMediaWaitTimeout (HandleBuffer[HandleIndex], 0, &MediaStatus); + if (MediaStatus != EFI_SUCCESS) { + // + // Skip this one. + // + continue; + } + } + + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + &gEfiIp6ServiceBindingProtocolGuid, + (VOID **) &Ip6Sb + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Ip6config protocol and ip6 service binding protocol are installed + // on the same handle. + // + Status = gBS->HandleProtocol ( + HandleBuffer[HandleIndex], + &gEfiIp6ConfigProtocolGuid, + (VOID **) &Ip6Cfg + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + // + // Get the interface information size. + // + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeInterfaceInfo, + &IfInfoSize, + NULL + ); + + if (Status != EFI_BUFFER_TOO_SMALL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + + IfInfo = AllocateZeroPool (IfInfoSize); + + if (IfInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + // + // Get the interface info. + // + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeInterfaceInfo, + &IfInfoSize, + IfInfo + ); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + // + // Check whether the source address is one of the interface addresses. + // + for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) { + Addr = &(IfInfo->AddressInfo[AddrIndex].Address); + + if (UnspecifiedSrc) { + if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) { + // + // Select the interface automatically. + // + CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress)); + break; + } + } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) { + // + // Match a certain interface address. + // + break; + } + } + + if (AddrIndex < IfInfo->AddressInfoCount) { + // + // Found a nic handle with right interface address. + // + break; + } + + FreePool (IfInfo); + IfInfo = NULL; + } + // + // No exact interface address matched. + // + + if (HandleIndex == HandleNum) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_CONFIGD_NIC_NF), gShellNetwork2HiiHandle); + Status = EFI_NOT_FOUND; + goto ON_ERROR; + } + + Private->NicHandle = HandleBuffer[HandleIndex]; + + ASSERT (Ip6Sb != NULL); + Status = Ip6Sb->CreateChild (Ip6Sb, &Private->Ip6ChildHandle); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + Status = gBS->OpenProtocol ( + Private->Ip6ChildHandle, + &gEfiIp6ProtocolGuid, + (VOID **) &Private->Ip6, + Private->ImageHandle, + Private->Ip6ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA)); + + // + // Configure the ip6 instance for icmp6 packet exchange. + // + Ip6Config.DefaultProtocol = 58; + Ip6Config.AcceptAnyProtocol = FALSE; + Ip6Config.AcceptIcmpErrors = TRUE; + Ip6Config.AcceptPromiscuous = FALSE; + Ip6Config.TrafficClass = 0; + Ip6Config.HopLimit = 128; + Ip6Config.FlowLabel = 0; + Ip6Config.ReceiveTimeout = 0; + Ip6Config.TransmitTimeout = 0; + + IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress); + + IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress); + + Status = Private->Ip6->Configure (Private->Ip6, &Ip6Config); + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_CONFIG), gShellNetwork2HiiHandle, Status); + goto ON_ERROR; + } + + return EFI_SUCCESS; + +ON_ERROR: + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + if (IfInfo != NULL) { + FreePool (IfInfo); + } + + if ((Ip6Sb != NULL) && (Private->Ip6ChildHandle != NULL)) { + Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle); + } + + return Status; +} + +/** + Destroy the IP6 instance. + + @param[in] Private The pointer of PING6_PRIVATE_DATA. + +**/ +VOID +Ping6DestroyIpInstance ( + IN PING6_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb; + + gBS->CloseProtocol ( + Private->Ip6ChildHandle, + &gEfiIp6ProtocolGuid, + Private->ImageHandle, + Private->Ip6ChildHandle + ); + + Status = gBS->HandleProtocol ( + Private->NicHandle, + &gEfiIp6ServiceBindingProtocolGuid, + (VOID **) &Ip6Sb + ); + + if (!EFI_ERROR(Status)) { + Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle); + } +} + +/** + The Ping6 Process. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SendNumber The send request count. + @param[in] BufferSize The send buffer size. + @param[in] SrcAddress The source IPv6 address. + @param[in] DstAddress The destination IPv6 address. + + @retval SHELL_SUCCESS The ping6 processed successfullly. + @retval others The ping6 processed unsuccessfully. + +**/ +SHELL_STATUS +ShellPing6 ( + IN EFI_HANDLE ImageHandle, + IN UINT32 SendNumber, + IN UINT32 BufferSize, + IN EFI_IPv6_ADDRESS *SrcAddress, + IN EFI_IPv6_ADDRESS *DstAddress + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + PING6_PRIVATE_DATA *Private; + PING6_ICMP6_TX_INFO *TxInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA)); + + if (Private == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"Ping6"); + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Private->ImageHandle = ImageHandle; + Private->SendNum = SendNumber; + Private->BufferSize = BufferSize; + Private->RttMin = ~((UINT64 )(0x0)); + Private->Status = EFI_NOT_READY; + + InitializeListHead (&Private->TxList); + + IP6_COPY_ADDRESS (&Private->SrcAddress, SrcAddress); + IP6_COPY_ADDRESS (&Private->DstAddress, DstAddress); + + // + // Open and configure a ip6 instance for ping6. + // + Status = Ping6CreateIpInstance (Private); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Print the command line itself. + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_START), gShellNetwork2HiiHandle, mIp6DstString, Private->BufferSize); + // + // Create a ipv6 token to receive the first icmp6 echo reply packet. + // + Status = Ping6OnReceiveEchoReply (Private); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Create and start timer to send icmp6 echo request packet per second. + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + Ping6OnTimerRoutine6, + Private, + &Private->Timer + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Start a timer to calculate the RTT. + // + Status = Ping6InitRttTimer (Private); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + + // + // Create a ipv6 token to send the first icmp6 echo request packet. + // + Status = Ping6SendEchoRequest (Private); + // + // EFI_NOT_READY for IPsec is enable and IKE is not established. + // + if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { + ShellStatus = SHELL_ACCESS_DENIED; + if(Status == EFI_NOT_FOUND) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_NOSOURCE_INDOMAIN), gShellNetwork2HiiHandle, mIp6DstString); + } + + goto ON_EXIT; + } + + Status = gBS->SetTimer ( + Private->Timer, + TimerPeriodic, + PING6_ONE_SECOND + ); + + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + goto ON_EXIT; + } + // + // Control the ping6 process by two factors: + // 1. Hot key + // 2. Private->Status + // 2.1. success means all icmp6 echo request packets get reply packets. + // 2.2. timeout means the last icmp6 echo reply request timeout to get reply. + // 2.3. noready means ping6 process is on-the-go. + // + while (Private->Status == EFI_NOT_READY) { + Private->Ip6->Poll (Private->Ip6); + + // + // Terminate the ping6 process by 'esc' or 'ctl-c'. + // + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + if (!EFI_ERROR(Status)) { + if ((Key.UnicodeChar == 0x1b) || (Key.UnicodeChar == 0x03) || + ((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_ESC))) { + goto ON_STAT; + } + } + } + +ON_STAT: + // + // Display the statistics in all. + // + gBS->SetTimer (Private->Timer, TimerCancel, 0); + + if (Private->TxCount != 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING6_STAT), + gShellNetwork2HiiHandle, + Private->TxCount, + Private->RxCount, + (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount, + Private->RttSum + ); + } + + if (Private->RxCount != 0) { + ShellPrintHiiEx ( + -1, + -1, + NULL, + STRING_TOKEN (STR_PING6_RTT), + gShellNetwork2HiiHandle, + Private->RttMin, + Private->RttMin + Private->TimerPeriod, + Private->RttMax, + Private->RttMax + Private->TimerPeriod, + DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL), + DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL) + Private->TimerPeriod + ); + } + +ON_EXIT: + + if (Private != NULL) { + Private->Status = EFI_ABORTED; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) { + TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link); + + Status = Private->Ip6->Cancel (Private->Ip6, TxInfo->Token); + + RemoveEntryList (&TxInfo->Link); + Ping6DestroyTxInfo (TxInfo); + } + + Ping6FreeRttTimer (Private); + + if (Private->Timer != NULL) { + gBS->CloseEvent (Private->Timer); + } + + if (Private->Ip6 != NULL) { + Status = Private->Ip6->Cancel (Private->Ip6, &Private->RxToken); + } + + if (Private->RxToken.Event != NULL) { + gBS->CloseEvent (Private->RxToken.Event); + } + + if (Private->Ip6ChildHandle != NULL) { + Ping6DestroyIpInstance (Private); + } + + FreePool (Private); + } + + return ShellStatus; +} + +/** + Function for 'ping6' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @retval SHELL_SUCCESS The ping6 processed successfullly. + @retval others The ping6 processed unsuccessfully. + +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPing6 ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + EFI_IPv6_ADDRESS DstAddress; + EFI_IPv6_ADDRESS SrcAddress; + UINT64 BufferSize; + UINTN SendNumber; + LIST_ENTRY *ParamPackage; + CONST CHAR16 *ValueStr; + CONST CHAR16 *ValueStrPtr; + UINTN NonOptionCount; + CHAR16 *ProblemParam; + + ProblemParam = NULL; + ShellStatus = SHELL_SUCCESS; + + Status = ShellCommandLineParseEx (Ping6ParamList, &ParamPackage, &ProblemParam, TRUE, FALSE); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), gShellNetwork2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + + SendNumber = 10; + BufferSize = 16; + + // + // Parse the parameter of count number. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n"); + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + SendNumber = ShellStrToUintn (ValueStrPtr); + + // + // ShellStrToUintn will return 0 when input is 0 or an invalid input string. + // + if ((SendNumber == 0) || (SendNumber > PING6_MAX_SEND_NUMBER)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SEND_NUMBER), gShellNetwork2HiiHandle, ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Parse the parameter of buffer size. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l"); + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + BufferSize = ShellStrToUintn (ValueStrPtr); + + // + // ShellStrToUintn will return 0 when input is 0 or an invalid input string. + // + if ((BufferSize < 16) || (BufferSize > PING6_MAX_BUFFER_SIZE)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_BUFFER_SIZE), gShellNetwork2HiiHandle, ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + + ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS)); + ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS)); + + // + // Parse the parameter of source ip address. + // + ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s"); + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + mIp6SrcString = ValueStr; + Status = NetLibStrToIp6 (ValueStrPtr, &SrcAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), gShellNetwork2HiiHandle, ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + // + // Parse the parameter of destination ip address. + // + NonOptionCount = ShellCommandLineGetCount(ParamPackage); + ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1)); + if (NonOptionCount != 2) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), gShellNetwork2HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + ValueStrPtr = ValueStr; + if (ValueStr != NULL) { + mIp6DstString = ValueStr; + Status = NetLibStrToIp6 (ValueStrPtr, &DstAddress); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), gShellNetwork2HiiHandle, ValueStr); + ShellStatus = SHELL_INVALID_PARAMETER; + goto ON_EXIT; + } + } + + // + // Enter into ping6 process. + // + ShellStatus = ShellPing6 ( + ImageHandle, + (UINT32)SendNumber, + (UINT32)BufferSize, + &SrcAddress, + &DstAddress + ); + +ON_EXIT: + ShellCommandLineFreeVarList (ParamPackage); + return ShellStatus; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c new file mode 100644 index 0000000..3e5c337 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c @@ -0,0 +1,91 @@ +/** @file + Main file for NULL named library for network2 shell command functions. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License which accompanies this distribution. + The full text of the license may be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "UefiShellNetwork2CommandsLib.h" + +CONST CHAR16 gShellNetwork2FileName[] = L"ShellCommands"; +EFI_HANDLE gShellNetwork2HiiHandle = NULL; + +/** + return the file name of the help text file if not using HII. + + @return The string pointer to the file name. +**/ +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameNetwork2 ( + VOID + ) +{ + return (gShellNetwork2FileName); +} + +/** + Constructor for the Shell Network2 Commands library. + + Install the handlers for Network2 UEFI Shell 2.0 profile commands. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. + + @retval EFI_SUCCESS The shell command handlers were installed sucessfully. + @retval EFI_UNSUPPORTED The shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellNetwork2CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + gShellNetwork2HiiHandle = NULL; + + // + // check our bit of the profiles mask + // + if ((PcdGet8(PcdShellProfileMask) & BIT4) == 0) { + return (EFI_SUCCESS); + } + + gShellNetwork2HiiHandle = HiiAddPackages (&gShellNetwork2HiiGuid, gImageHandle, UefiShellNetwork2CommandsLibStrings, NULL); + if (gShellNetwork2HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + // + // install our shell command handlers + // + ShellCommandRegisterCommandName(L"ping6", ShellCommandRunPing6 , ShellCommandGetManFileNameNetwork2, 0, L"network2", TRUE , gShellNetwork2HiiHandle, STRING_TOKEN(STR_GET_HELP_PING6)); + ShellCommandRegisterCommandName(L"ifconfig6",ShellCommandRunIfconfig6 , ShellCommandGetManFileNameNetwork2, 0, L"network2", TRUE , gShellNetwork2HiiHandle, STRING_TOKEN(STR_GET_HELP_IFCONFIG6)); + + return EFI_SUCCESS; + +} + +/** + Destructor for the library. free any resources. + + @param ImageHandle The image handle of the process. + @param SystemTable The EFI System Table pointer. +**/ +EFI_STATUS +EFIAPI +ShellNetwork2CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellNetwork2HiiHandle != NULL) { + HiiRemovePackages(gShellNetwork2HiiHandle); + } + return EFI_SUCCESS; +} + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h new file mode 100644 index 0000000..e4671af --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h @@ -0,0 +1,72 @@ +/** @file + Main file for NULL named library for network2 shell command functions. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License which accompanies this distribution. + The full text of the license may be found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UEFI_SHELL_NETWORK2_COMMANDS_LIB_H_ +#define _UEFI_SHELL_NETWORK2_COMMANDS_LIB_H_ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE gShellNetwork2HiiHandle; + +/** + Function for 'ping6' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @retval SHELL_SUCCESS The ping6 processed successfullly. + @retval others The ping6 processed unsuccessfully. + +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunPing6 ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'ifconfig6' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). + + @retval SHELL_SUCCESS The ifconfig6 command processed successfully. + @retval others The ifconfig6 command process failed. + +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIfconfig6 ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +#endif + diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf new file mode 100644 index 0000000..d3adbff --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf @@ -0,0 +1,64 @@ +## @file +# Provides shell network2 functions +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellNetwork2CommandsLib + FILE_GUID = D94E3B82-908E-46bf-A7B9-C7B7F17B1B7D + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellNetwork2CommandsLibConstructor + DESTRUCTOR = ShellNetwork2CommandsLibDestructor + +[Sources.common] + UefiShellNetwork2CommandsLib.uni + UefiShellNetwork2CommandsLib.c + UefiShellNetwork2CommandsLib.h + Ping6.c + Ifconfig6.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + PcdLib + HiiLib + FileHandleLib + NetLib + +[Pcd] + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES + +[Protocols] + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid ## CONSUMES + gEfiIp6ProtocolGuid ## SOMETIMES_CONSUMES + gEfiIp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES + gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES + +[Guids] + gShellNetwork2HiiGuid ## SOMETIMES_CONSUMES ## HII diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni new file mode 100644 index 0000000..fef856e --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni @@ -0,0 +1,167 @@ +/** @file + + String definitions for UEFI Shell network 2 commands + Copyright (c) 2016, Intel Corporation. All rights reserved.
        + (C) Copyright 2017 Hewlett Packard Enterprise Development LP
        + + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The full + text of the license may be found at
        + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: + + UefiShellNetwork2CommandsLib.uni + + Abstract: + + String definitions for UEFI Shell 2.0 network 2 commands +**/ + +#langdef en-US "english" + +#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n" +#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n" + +#string STR_PING6_INVALID_IP #language en-US "%Ping6: Invalid IP6 address, %s\r\n" +#string STR_PING6_INVALID_INPUT #language en-US "%Ping6: Invalid input, please type 'Ping6 -?'for help\r\n" +#string STR_PING6_INVALID_SEND_NUMBER #language en-US "%Ping6: Invalid send number, %s\r\n" +#string STR_PING6_INVALID_BUFFER_SIZE #language en-US "%Ping6: Invalid buffer size, %s\r\n" +#string STR_PING6_INVALID_SOURCE #language en-US "%Ping6: Require source interface option\r\n" +#string STR_PING6_IP6_CONFIG #language en-US "%Ping6: The process of Ip6 Configure %r\r\n" +#string STR_PING6_IP6_RECEIVE #language en-US "%Ping6: Place the receive token %r\r\n" +#string STR_PING6_IP6CFG_GETDATA #language en-US "%Ping6: Get data of the interface information %r\r\n" +#string STR_PING6_SEND_REQUEST #language en-US "Echo request sequence %d fails.\r\n" +#string STR_PING6_CONFIGD_NIC_NF #language en-US "%Ping6: No configured interfaces were found.\r\n" +#string STR_PING6_NOSOURCE_INDOMAIN #language en-US "No sources in %s's multicast domain.\r\n" +#string STR_PING6_START #language en-US "Ping %s %d data bytes\r\n" +#string STR_PING6_TIMEOUT #language en-US "Echo request sequence %d timeout.\r\n" +#string STR_PING6_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%d~%dms\r\n" +#string STR_PING6_STAT #language en-US "\n%d packets transmitted, %d received, %d%% packet loss, time %dms\r\n" +#string STR_PING6_RTT #language en-US "\nRtt(round trip time) min=%d~%dms max=%d~%dms avg=%d~%dms\r\n" + +#string STR_IFCONFIG6_ERR_IP6CFG_GETDATA #language en-US "Get data of the interface information %hr\r\n" +#string STR_IFCONFIG6_INFO_BREAK #language en-US "-----------------------------------------------------------------" +#string STR_IFCONFIG6_INFO_COLON #language en-US ":" +#string STR_IFCONFIG6_INFO_JOINT #language en-US " >> " +#string STR_IFCONFIG6_INFO_NEWLINE #language en-US "\r\n" +#string STR_IFCONFIG6_INFO_IF_NAME #language en-US "\n%Hname : %s%N\r\n" +#string STR_IFCONFIG6_INFO_POLICY_AUTO #language en-US "%Hpolicy : automatic%N\r\n" +#string STR_IFCONFIG6_INFO_POLICY_MAN #language en-US "%Hpolicy : manual%N\r\n" +#string STR_IFCONFIG6_INFO_DAD_TRANSMITS #language en-US "%Hdad xmits : %d%N\r\n" +#string STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD #language en-US "%Hinterface id : %N" +#string STR_IFCONFIG6_INFO_MAC_ADDR_HEAD #language en-US "%Hmac addr : %N" +#string STR_IFCONFIG6_INFO_MAC_ADDR_BODY #language en-US "%02x" +#string STR_IFCONFIG6_INFO_IP_ADDR_HEAD #language en-US "\n%Hhost addr : %N\r\n" +#string STR_IFCONFIG6_INFO_DNS_ADDR_HEAD #language en-US "\n%Hdns server : %N\r\n" +#string STR_IFCONFIG6_INFO_IP_ADDR_BODY #language en-US "%02x" +#string STR_IFCONFIG6_INFO_IP_ADDR_BODY4BIT #language en-US "%x" +#string STR_IFCONFIG6_INFO_ROUTE_HEAD #language en-US "\n%Hroute table : %N\r\n" +#string STR_IFCONFIG6_INFO_PREFIX_LEN #language en-US "/%d" +#string STR_IFCONFIG6_LINE_HELP #language en-US "Displays or modifies the IPv6 configuration" +#string STR_IFCONFIG6_ERR_LACK_INTERFACE #language en-US "Lack interface name.\r\n" + "Usage: IfConfig6 -s \r\n" + "Example: IfConfig6 -s eth0 auto\r\n" +#string STR_IFCONFIG6_LACK_OPTION #language en-US "Flags lack. Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_CONFLICT_OPTIONS #language en-US "Flags conflict. Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_LACK_COMMAND #language en-US "Lack interface config option.\r\n" + "Hint: Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_INVALID_INTERFACE #language en-US "Invalid interface name.\r\n" + "Hint: Use {IfConfig6 -l} to check existing interface names.\r\n" +#string STR_IFCONFIG6_ERR_INVALID_COMMAND #language en-US "Invalid command. Bad command %H%s%N is skipped.\r\n" + "Hint: Incorrect option or arguments. Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_LACK_ARGUMENTS #language en-US "Lack arguments. Bad command %H%s%N is skipped.\r\n" + "Hint: Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_LACK_OPTION #language en-US "Lack options.\r\n" + "Hint: Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_MAN_HOST #language en-US "Manual address configuration failed. Please retry.\r\n" + +#string STR_IFCONFIG6_ERR_MAN_GW #language en-US "Gateway address configuration failed. Please check the argument.\r\n" + +#string STR_IFCONFIG6_ERR_INVALID_IP_CONFIG #language en-US "The IP address is not configurable when the policy is Ip6ConfigPolicyAutomatic.\r\n" + +#string STR_IFCONFIG6_ERR_INVALID_GW_CONFIG #language en-US "The gateway address is not configurable when the policy is Ip6ConfigPolicyAutomatic.\r\n" + +#string STR_IFCONFIG6_ERR_INVALID_DNS_CONFIG #language en-US "The DNS server address is not configurable when the policy is Ip6ConfigPolicyAutomatic.\r\n" + +#string STR_IFCONFIG6_ERR_DUPLICATE_COMMAND #language en-US "Duplicate commands. Bad command %H%s%N is skipped.\r\n" + "Hint: Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_CONFLICT_COMMAND #language en-US "Conflict commands. Bad command %H%s%N is skipped.\r\n" + "Hint: Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_UNKNOWN_COMMAND #language en-US "Unknown commands. Bad command %H%s%N is skipped.\r\n" + "Hint: Please type 'IfConfig6 -?' for help info.\r\n" +#string STR_IFCONFIG6_ERR_ADDRESS_FAILED #language en-US "Failed to configure IPv6 address: " + + +#string STR_GET_HELP_PING6 #language en-US "" +".TH ping6 0 "Ping a target machine with UEFI IPv6 network stack."\r\n" +".SH NAME\r\n" +"Ping a target machine with UEFI IPv6 network stack.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"Ping6 [-l size] [-n count] [-s SourceIp] TargetIp\r\n" +".SH OPTIONS\r\n" +" \r\n" +" -l size Send buffer size, in bytes(default=16, min=16, max=32768).\r\n" +" -n count Send request count, (default=10, min=1, max=10000).\r\n" +" -s SourceIp Source IPv6 address.\r\n" +" TargetIp Target IPv6 address.\r\n" +"NOTES:\r\n" +" 1. When TargetIp is a link local address, SourceIp needs to be specified.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"Examples:\r\n" +" * To ping the target host by sending 5 request with 1000 bytes from 2002::1\r\n" +" Shell:\> Ping6 -s 2002::1 2002::2 -l 1000 -n 5\r\n" +" \r\n" +" * To ping the target host with 1000 bytes\r\n" +" Shell:\> Ping6 2002::2 -l 1000\r\n" + +#string STR_GET_HELP_IFCONFIG6 #language en-US "" +".TH ifconfig6 0 "Displays or modifies IPv6 configuration for network interface."\r\n" +".SH NAME\r\n" +"Displays or modifies IPv6 configuration for network interface.\r\n" +".SH SYNOPSIS\r\n" +" \r\n" +"IfConfig6 -r [Name] | -l [Name] \r\n" +"IfConfig6 -s [dad ] [auto | [man [id ] [host gw ]\r\n" +" [dns ]]]\r\n" +".SH OPTIONS\r\n" +" \r\n" +" Name Adapter name, i.e., eth0\r\n" +" -r [Name] Reconfigure all or specified interface, and set\r\n" +" automatic policy. If specified interface is already\r\n" +" set to automatic,then refresh the IPv6 configuration.\r\n" +" -l [Name] List the configuration of the specified interface.\r\n" +" -s dad Set dad transmits count of the specified interface.\r\n" +" -s auto Set automatic policy of the specified interface.\r\n" +" -s man id Set alternative interface id of the specified \r\n" +" interface. Must under manual policy.\r\n" +" -s man host gw \r\n" +" Set static host IP and gateway address of the\r\n" +" specified interface. Must under manual policy.\r\n" +" -s man dns Set DNS server IP addresses of the specified\r\n" +" interface.Must under manual policy.\r\n" +".SH EXAMPLES\r\n" +" \r\n" +"EXAMPLES:\r\n" +" * To list the configuration for the interface eth0:\r\n" +" Shell:\> ifConfig6 -l eth0\r\n" +" \r\n" +" * To use automatic configuration to request the IPv6 address configuration\r\n" +" dynamically for the interface eth0:\r\n" +" Shell:\> ifconfig6 -s eth0 auto\r\n" +" \r\n" +" * To set the dad transmits count for eth0 under automatic policy:\r\n" +" Shell:\> ifconfig6 -s eth0 auto dad 10\r\n" +" \r\n" +" * To set the alternative interface id of eth0 under manual policy:\r\n" +" Shell:\> ifconfig6 -s eth0 man id ff:dd:aa:88:66:cc\r\n" +" \r\n" +" * To use the static IP6 addresses configuration for the interface eth0,\r\n" +" and this configuration survives the network reload:\r\n" +" Shell:\> ifconfig6 -s eth0 man host 2002::1/64 2002::2/64 gw 2002::3/64\r\n" diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dec b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dec new file mode 100644 index 0000000..c407cc4 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dec @@ -0,0 +1,140 @@ +## @file ShellPkg.dec +# This Package provides all definitions for EFI and UEFI Shell +# +# (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.
        +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
        +# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
        +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = ShellPkg + PACKAGE_GUID = C1014BB7-4092-43D4-984F-0738EB424DBF + PACKAGE_VERSION = 1.02 + +[Includes] + Include + +[LibraryClasses] + ## @libraryclass Provides most Shell APIs. Only available for Shell applications + ShellLib|Include/Library/ShellLib.h + + ## @libraryclass Provides shell internal support Only available for shell internal commands + ShellCommandLib|Include/Library/ShellCommandLib.h + + ## @libraryclass Allows for a shell application to have a C style entry point + ShellCEntryLib|Include/Library/ShellCEntryLib.h + + ## @libraryclass Provides advanced parsing functions + HandleParsingLib|Include/Library/HandleParsingLib.h + + ## @libraryclass provides BCFG command + BcfgCommandLib|Include/Library/BcfgCommandLib.h + +[Guids] + gEfiShellEnvironment2ExtGuid = {0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87}} + gEfiShellPkgTokenSpaceGuid = {0x171e9188, 0x31d3, 0x40f5, {0xb1, 0x0c, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd}} + gShellVariableGuid = {0x158def5a, 0xf656, 0x419c, {0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2}} + gShellMapGuid = {0x51271e13, 0x7de3, 0x43af, {0x8b, 0xc2, 0x71, 0xad, 0x3b, 0x82, 0x43, 0x25}} + gShellAliasGuid = {0x0053d9d6, 0x2659, 0x4599, {0xa2, 0x6b, 0xef, 0x45, 0x36, 0xe6, 0x31, 0xa9}} + gHandleParsingHiiGuid = {0xb8969637, 0x81de, 0x43af, {0xbc, 0x9a, 0x24, 0xd9, 0x89, 0x13, 0xf2, 0xf6}} + gShellDebug1HiiGuid = {0x25f200aa, 0xd3cb, 0x470a, {0xbf, 0x51, 0xe7, 0xd1, 0x62, 0xd2, 0x2e, 0x6f}} + gShellDriver1HiiGuid = {0xaf0b742, 0x63ec, 0x45bd, {0x8d, 0xb6, 0x71, 0xad, 0x7f, 0x2f, 0xe8, 0xe8}} + gShellInstall1HiiGuid = {0x7d574d54, 0xd364, 0x4d4a, {0x95, 0xe3, 0x49, 0x45, 0xdb, 0x7a, 0xd3, 0xee}} + gShellLevel1HiiGuid = {0xdec5daa4, 0x6781, 0x4820, {0x9c, 0x63, 0xa7, 0xb0, 0xe4, 0xf1, 0xdb, 0x31}} + gShellLevel2HiiGuid = {0xf95a7ccc, 0x4c55, 0x4426, {0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae}} + gShellLevel3HiiGuid = {0x4344558d, 0x4ef9, 0x4725, {0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f}} + gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}} + gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, {0xaa, 0x60, 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37}} + gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}} + gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}} + gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc, {0xb5, 0xef, 0x2e, 0xf5, 0x5e, 0x24, 0x93, 0x2a}} + # FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf + gUefiShellFileGuid = {0x7c04a583, 0x9e3e, 0x4f1c, {0xad, 0x65, 0xe0, 0x52, 0x68, 0xd0, 0xb4, 0xd1}} + +[Protocols] + gEfiShellEnvironment2Guid = {0x47c7b221, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}} + gEfiShellInterfaceGuid = {0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}} + +[PcdsFeatureFlag] + ## This flag is used to control whether the shell includes NT32 platform Guids + # and thereby prevents dependancy on that Pkg + gEfiShellPkgTokenSpaceGuid.PcdShellIncludeNtGuids|TRUE|BOOLEAN|0x0000000E + + ## This flag is used to control HII required by the shell + gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform|TRUE|BOOLEAN|0x00000003 + + ## This flag is used to control HII required by the shell + gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii|FALSE|BOOLEAN|0x00000004 + + ## This flag forces the shell to present a user console. Allows for earlier debugging of platforms. + gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole|FALSE|BOOLEAN|0x0000000F + +[PcdsFixedAtBuild] + ## This flag is used to control initialization of the shell library + # This should be FALSE for compiling the shell application itself only. + # This should be FALSE for compiling the dynamic command drivers. + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|TRUE|BOOLEAN|0x00000005 + + ## This is the max buffer for ShellLib and internal Shell printings. + gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize|16000|UINT16|0x0000000C + + ## This flag is used to control the commands available in the shell + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel|3|UINT8|0x00000001 + + ## This flag is used to control the profiles available in the shell + # don't forget to update the text file if you change this. + # bit 0 = Drivers1 + # bit 1 = Debug1 + # bit 2 = Install1 + # bit 3 = Network1 + # bit 4 = Network2 + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask|0xFF|UINT8|0x0000000D + + ## This is the character count for allocation for consistent mappings + gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength|50|UINT8|0x00000009 + + ## This determines how many bytes are read out of files at a time for file operations (type, copy, etc...) + gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x1000|UINT32|0x0000000A + + ## This determines the max count of history commands + gEfiShellPkgTokenSpaceGuid.PcdShellMaxHistoryCommandCount|0x0020|UINT16|0x00000014 + +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] + ## This flag is used to control the protocols produced by the shell + # If TRUE the shell will produce EFI_SHELL_ENVIRONMENT2 and EFI_SHELL_INTERFACE + gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols|FALSE|BOOLEAN|0x00000002 + + ## this flag determines whether Page Break (-b) defaults to on or off in the shell + gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault|FALSE|BOOLEAN|0x00000006 + + ## this flag determines whether insert mode for typing is default (FALSE means typeover) + gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault|TRUE|BOOLEAN|0x00000007 + + ## this flag determines the default number of screens kept for history log. + # the spec defines 3 as the minimum + gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount|3|UINT8|0x00000008 + + ## Unicode string of the shell supplier + gEfiShellPkgTokenSpaceGuid.PcdShellSupplier|L"EDK II"|VOID*|0x00000010 + + ## Do extended decode of USB for determining media type + gEfiShellPkgTokenSpaceGuid.PcdUsbExtendedDecode|TRUE|BOOLEAN|0x00000011 + + ## Do iSCSI decode for map names. + # This is disabled by default due to the length of generated strings + gEfiShellPkgTokenSpaceGuid.PcdShellDecodeIScsiMapNames|FALSE|BOOLEAN|0x00000012 + + ## Controls Extended decode for Vendor device path nodes for map names. + # Up to this many bytes of vendor specific data will be used. Default is 0 + # (disabled). + gEfiShellPkgTokenSpaceGuid.PcdShellVendorExtendedDecode|0|UINT32|0x00000013 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dsc b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dsc new file mode 100644 index 0000000..0fac7d2 --- /dev/null +++ b/Voyager-2/Voyager-2 (1703-1511)/edk2/ShellPkg/ShellPkg.dsc @@ -0,0 +1,136 @@ +## @file +# Shell Package +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
        +# Copyright (c) 2018, Arm Limited. All rights reserved.
        +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + PLATFORM_NAME = Shell + PLATFORM_GUID = E1DC9BF8-7013-4c99-9437-795DAA45F3BD + PLATFORM_VERSION = 1.02 + DSC_SPECIFICATION = 0x00010006 + OUTPUT_DIRECTORY = Build/Shell + SUPPORTED_ARCHITECTURES = IA32|X64|EBC|ARM|AARCH64 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses.common] + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!else + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf +!endif + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + +[LibraryClasses.ARM] + # + # It is not possible to prevent the ARM compiler for generic intrinsic functions. + # This library provides the instrinsic functions generate by a given compiler. + # [LibraryClasses.ARM] and NULL mean link this library into all ARM images. + # + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + + # Add support for GCC stack protector + NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf + +[LibraryClasses.AARCH64] + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + +[PcdsFixedAtBuild] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|16000 +!ifdef $(NO_SHELL_PROFILES) + gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask|0x00 +!endif #$(NO_SHELL_PROFILES) + +[Components] + # + # Build all the libraries when building this package. + # This helps developers test changes and how they affect the package. + # + ShellPkg/Library/UefiShellLib/UefiShellLib.inf + ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf + ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf + ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf + ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf + + ShellPkg/Application/Shell/Shell.inf { + + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf +!ifndef $(NO_SHELL_PROFILES) + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf +!endif #$(NO_SHELL_PROFILES) + } + + ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf { + + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } + ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf + ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf { + + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + } + ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf + +[BuildOptions] + *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiApplicationEntryPoint.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiApplicationEntryPoint.lib new file mode 100644 index 0000000000000000000000000000000000000000..925b38f192fc00d2caca8ed67af06c80fb50a857 GIT binary patch literal 7758 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 G3jPCB0b#`e literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiBootServicesTableLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiBootServicesTableLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..7ea64587e65f0af2fcb681a579193b67227b216a GIT binary patch literal 8616 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 literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiDriverEntryPoint.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiDriverEntryPoint.lib new file mode 100644 index 0000000000000000000000000000000000000000..e5a7e7ac84e1895e9d3d41110925a6afd6ade272 GIT binary patch literal 9754 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 Q1(X)xVP9ViKbQ>v1BUNuf&c&j literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiFileHandleLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiFileHandleLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..e2ea2297f492ec8841a22d573351ad59ef2cc869 GIT binary patch literal 30844 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 literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiHiiLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiHiiLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..3f3b00cd633a7fa22e2d0d22994a7edce2e8ac05 GIT binary patch literal 136052 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 OC>hU8*__}rIrs}-z)ZUU literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiHiiServicesLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiHiiServicesLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..ce3b4f93031932f9ec9d54f252bc269f0180ceeb GIT binary patch literal 13228 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 DO>Mg* literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..14af1d4135d32c2aa280585220c689bb82bd7305 GIT binary patch literal 179896 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

        !;ks282q% z>_O&gX5*__QFE2zN@iZdH!n!ks3!woehRScRrt4}v@Lru*CTrf|Lt3RQgAK1m$%ug zBx)R#kdQtc;^qR;z7jAVs0i1k;w_3J;R=|_oN;Y9ko zzvrC~7yVV?{W%O=K~Mk3dy!~6}c_ zyD{vECWVER!gMsG2OFcMj3HOn=8#z{Q{eBsSDv+;%|+IBMSCdM0YrF(^T^r;SX!rg zi%jqulHQW^k)*FA{Uqrx$pA?PN-{{2!IBJ-WE4oDnchNEy&u9@ zloM;FN7z1WopmXapBOGh@)d0~$1Dg;>oHt5KTyWMJ7cUu4lnegOVQQKybtltj!rug zOHsbspl5T*AyKQ<1Q{ns$zH(o2J4ty&tJiME*B?MAR87b)+AmhtVFX{iKQ}rWiJ#9 z7_MH9OcVigy2H>%Oj&+plFR&fWh+?U)SUnsR(V)!zyLUDA_sA+16(%^Qe!u_&{xOp zHCU7w<;3HvmhAc5R<1NApo>ciEsvSsOtV`u-vp|V77w#}60yedo|WOTH_=;#Zh?=?rq zaK=6{`h2u0G|QV^Hl}sfKyi*N^Iq$$i3C$%7{L@6Cbr8Z991D^zBn~xCW&x2(+l#! zvS;yCNwh47mK%A?vo%Q?Kku*gE$ ziq00>Ha}xsi!6#w#BV?jB%o3qcdorH_AqU^WJu}}cCrS1kbE??w>`{^bblu6@E%3@D$j&y~+0afz++XD1ZXa(q z&nrjDnVNPR4$W8xon|`h=eW6E*^TT{0D^HxIBv1GkRw(F_Zx1nZ_?RqqLqW&juRTv zm&fub8W~4JOxZ{=WfzNNmkRYD29$$XKu)K?|aOTKS-{z-&wp1%;MxI75N+|9##0im~TSRA(=&U$8Gr`<))VxP}hP2Ex8 z#Rhwgj~EzFIEXw&EU$B;&3UIPZsvr><`v>%9X)*%@1TQ1i@g7z_Goi4xyzMV#I=?#qfsyOq(){u3{>+e=B}8|Hrb!-TdiQW zkn1eI9Ov)Y(Eji{Wjr#gt>^&%flR)5{FjbOc_%~x{(--E8bnI1xE_4pus(8v;cJ46 zH(naNa0(|$(?Ttr8X6gQLM)uGh=p@$z{2_JqYGz#zlD?c6|`__2HN1J1-;?iam!pd zF`$7Gd{8=qD}D2Gxe!$23xQ8zyIuI*=fc(`=bBZ?vQsF;;aS86bRQO1>A^ec@22Q`J+%<9qs$_cRp? z%vqe(`GUFga7QrRspP_|{BA1zn&Q$B;`_AkW3JW=zP0#O$}aVW(xE7>dY}*zsTkg3QNtB5C4H@U z_GQX1ELbv0Q~}lSGu{v;0UIS7;tH5jykQLPbw&vjet-!B7)%&N<(fE(uVPEoE|7Ci z(9BsZotzR{0q+T&m~ZO*Y9%)yY-*m zckp12-PX(-$?J{Svb=dXA6%5$-qI`Tp4eqkYP-F);@e1SYbz+P>(B&Wxt8DAj`^u- zeM@s29^gl{Xba`F82^hxxu`$Q{}?apM`zk#w$=7;uO+eW-|-DIv#hk$_Afx|RL7GF z{=)xwE#)$5^6!nCKvj9#f%>_QymnMD>Yyy@qAcnPi%_w})=g>L-KS|g?1tj|_FNrR zNjn1Sa78;pA@PWS-%wUtC$Gi)`ncctsNjTg2Vz_s#u=t+^A7jA1V2L7=5>se`Zz{O z4?9MC@g-5<$4b4N<3Q2gK3?fLLGcq6KS@yT;eLo=jT#No8~W+3VEF+8GUD68`E8TdfEPv08hC@W9XLiF;r$uXfw04hHf0+G-oZgYskj^x7!6 z{8iOjjZksf@9LmOLx%8}1+HX>xT~haRTh}ON`+{(3eisGx?OM`zrI_#&bC*{_bK^) zB|og>N0j`ilAlrio<+ZKspFQ!Ic`gwQrD}J+FqB`@rI%W1mz(_ee3e+P0aY=E8c(OX<$V?>*$7i49>O}J!nMjA9w@6Vn}?}ZquO;)L|cY}T6C*z29In|sdlSvp?|ysx|xkD zRU4;QSI;9=z#|uymM%>4f|encO!-Axt8GzmR*13Ydo2Nfi#8Rpaz*Bv`UOZ)4;v#T zHxg4=DWZ#&U?yBpzb1_Ftq}EuopZdFl)8TpG;)EM?jiDYo&X1oxWsFTYm8YNu%-z0 zm*Qh}^T`{(VMQL8v)8}KJ%4Z3IFWLv>-p6wc_kAyCI+B}#2_+IAB?IAL&-{1n`o|& zB>mWE(neoKHlupNdDK4Wr%$A-*(y2#Pq6pE)5b&aq;YRN(cATrdL)A*heckByc~Hg zG7}Xonv+(j<@Xp2c+3sF;V^ z6HCc5RG3(aN)qc)L1H7c+Df*O?Wh#7i|j^ih<&IFaey2ohshCg3^gE5kW;Aqa0XQ$ z&XY^13ULdSAey4~0_;E)gi)wsFa;F{R-tY{KRm6@>#dByQ|DvwwD|-)RXznzlTX8w zoL|hAu%&oneg)&zPS pCmPo;+`kXNva+COdbU1CpR3Q)7wC)h#rhI` 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 Tu|7hCjTd<6GeqtmVaWS$c*yT< literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiMemoryLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiMemoryLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..da0cefa6435f30c052d8761e8a9bde5e14b54fe8 GIT binary patch literal 63718 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 z zc^e4LF=Zk=#0V!sm=RKS6bNTQ9tbNK7z$Je!u>$_zV3O~0_j1!b+Er+aveavOCUFx zAnCD;?E3(jp~0R}v+v4~n{Yp1xRp@DaH%>9xGj(e${?def$D(!EZ}~udp@+_wxT`n zu1WS|8@3MzVLQy&!jNHXR2>Dj<&X!Yr3?uLssr1rz~=CJgjeowRv3IMjms)rvJTu+ zc;CD!Fs-K43ppt00g3PL7;9sJml{)O#C{DtsH9PuS?D$8SqUxp{b+WNHMOiEo-y8R zp=ks62GDsQqVr(V5?M=J_S;N@_&?HYH=PF2OkF05X<0#cE2`<(=dU-moxBZMKZ1#3 zKsu5Mq8+7)0WyJjjA6el=Qf}jF)Q{86S)ahosS^7kK<5Y2%aIqzK8_rrXIz96hq>6 z$fG}Q!i9U3>KGC)VMrYB^-S`5%DkTO*1*^esx1-J!0(S~j%_pN7=3$~Jsw^irq00g zu$XDrso62g&9OoqY#f@Z|y17kX4Gdy+(%J<%$a!@v6|hukN(04Fo{7om``Q*{*B%bbjT zEH2y?R0sCI1N#iGXS&y;c|FrC_!B|3!Cwpb7ZLo2O!)MSPj&{NK1fg>RI}4jmg_%e zmDvr`hB$KyJ97fmvolm3g)y-me+Ht*Hd9R69CobjCJQ7 zPHiNoequUB&)#J#ZH~;cl~1*mE98hXM^_a)wGd|5DXQk2aw_xnY4~QaR8f?o^Uotui@HnmU0G^`E!LzXZTi1L-sbh>&sk0QEd1M8j8$m%c6ex<*u|O{Z5~pLK zjxW@44e5pWqQ&V5o9%68`xngixY@qQY(L9rFZ`m>Uic-Wy|CSAFZ#04Ui1~Cy{N;~ z(`D*On0l6*dXlD|ubO(!G4*ttdRCcwdW?2wuYNN5QP5{xoomec*Ub7lvwog&9rJbL zTKo-@{!NpfG3ghW^Z~w74+U_af`1(yqsIbmz4S*64n^_nBDkt^MWVU0rz?+4Uuu>* z6h{#9{IhsGrY;n8FuqkTb(R*C7Uq49DJ?23EH4pYxgQ_oGNo?WJ%n@v5p z812s8Wz=luifQvt=1CA8> z`#JQb3eUI)?UkRQV$9!1@N*XW0X_fd&77!sx|KR#Q69#(uJ|!rG@4CCh}3`Kbi6W{*({+#hr9+;2fE*8B)AlE)l zDtXdU^2Cvuer+-Ra#$usd0H23iJq=x&kCCnl|6q7smFYbHfNtm?8Gyc>fatg^*$+& zr*IJi`mwyqqJOePpErVQGi?O@IeXBJl!^dOXIQ`2g)g1%O)l+END zC)LXjOysC4$8$fZ_O~?T=;unmUbevfWkgjkj;KmeUdX2#<0sD*j>TJ+xi^jwi`VV3 zunoY2d2!fC6dGpzit^fsz+cG+W{aQ|gF_amw{<~3v@u?Fk&70^n&E$7alQ{Y#w#Uk z8U;uFU3fsh$Y@CRtxomfO%|yh+f-sbhb=uHA6d_bpRA|AI}K0eI32}aV@W*DOQXW+ z80$5b#8NLUHI$JYUO~UZX-;%@*#N)KfQ5Htz=~sxSJ2O%Ldl+UNZMEuGA!*VB+WzG zu_!pP6ifv`1HkcKVLs?X@8HPA_Ao=3L=gIx^(I%RQ@xAuq7w?5y_3uA3`4Thc&}(l ztV;E+gYH2@j`ztHjFWJnTGpAy@7tR?(<|xi9(V_eJ<*-$r5wetBHMR1jsx#SxTxl_)bFgn1mjBeDYDeI%@Y=IluA>pX5;2zNHl83m zZ_1R}r+n~G-EU_t+`V<#pI#`~cM$h-j{eu=NB1l3VSYsY)|=&`Xv)NIsXtXOR=mEThy)U_tfjuZR!o`c6EokQ{AQBtlp~LrtVhnQ14XlR_{^oRqs>p zS07LxRDY!6V59y7m>*RiQy*7b+FXam|s@aa;M?0jwtG%bak0^bpeWZP?9o8;z4Y)3JUF6#6+T^;#b(!mO*Hx~~ zt}U+XT-#hXx^}pBxo$-?f8e?cQQhPEA>x{KeM+1tre=JYNfYYmRR@*Ht_RL7P!1m! z!YS&OCpy!WRaIBuY+|(7-xNWk$f?k~BJ%(2Z;8NB6+HBwi2OhM8zOL60uQ|-BL9zh z%(p`nFwen!2Gp3xd^1EL^U%8?^8c8}d@BSpJ8aQ=A@cv2$9y9MRsrzPJ0bG_2*dvZ DoXX;h literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiRuntimeServicesTableLib.lib b/Voyager-2/Voyager-2 (1703-1511)/edk2/UefiRuntimeServicesTableLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..df44d4f46e6a65e3d6bbb576fc5c29aef1bad454 GIT binary patch literal 7630 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 literal 0 HcmV?d00001 diff --git a/Voyager-2/Voyager-2 (2004-1709)/Hvax64.c b/Voyager-2/Voyager-2 (2004-1709)/Hvax64.c index c243131..515f919 100644 --- a/Voyager-2/Voyager-2 (2004-1709)/Hvax64.c +++ b/Voyager-2/Voyager-2 (2004-1709)/Hvax64.c @@ -103,7 +103,7 @@ VOID MakeVoyagerData VoyagerData->ModuleBase = PayLoadBase; VoyagerData->ModuleSize = PayLoadSize; - VOID* VCpuRunCall = + VOID* VmExitHandlerCall = FindPattern( HypervAlloc, HypervAllocSize, @@ -111,19 +111,14 @@ VOID MakeVoyagerData VCPU_RUN_HANDLER_MASK ); - UINT64 VCpuRunCallRip = (UINT64)VCpuRunCall + 5; // + 5 bytes because "call vmexit_c_handler" is 5 bytes - UINT64 VCpuRunFunction = VCpuRunCallRip + *(INT32*)((UINT64)VCpuRunCall + 1); // + 1 to skip E8 (call) and read 4 bytes (RVA) - VoyagerData->VCpuRunHandlerRVA = ((UINT64)PayLoadEntry(PayLoadBase)) - VCpuRunFunction; - - DBG_PRINT("VCpuRunCall -> 0x%p\n", VCpuRunCall); - DBG_PRINT("VCpuRunCallRip -> 0x%p\n", VCpuRunCallRip); - DBG_PRINT("VCpuRunFunction -> 0x%p\n", VCpuRunFunction); - DBG_PRINT("VoyagerData->VCpuRunHandlerRVA -> 0x%p\n", VoyagerData->VCpuRunHandlerRVA); + UINT64 VmExitHandlerCallRip = (UINT64)VmExitHandlerCall + 5; // + 5 bytes because "call vmexit_c_handler" is 5 bytes + UINT64 VmExitHandlerFunc = VmExitHandlerCallRip + *(INT32*)((UINT64)VmExitHandlerCall + 1); // + 1 to skip E8 (call) and read 4 bytes (RVA) + VoyagerData->VmExitHandlerRVA = ((UINT64)PayLoadEntry(PayLoadBase)) - VmExitHandlerFunc; } -VOID* HookVCpuRun(VOID* HypervBase, VOID* HypervSize, VOID* VCpuRunHook) +VOID* HookVmExitHandler(VOID* HypervBase, VOID* HypervSize, VOID* VCpuRunHook) { - VOID* VCpuRunCall = + VOID* VmExitHandlerCall = FindPattern( HypervBase, HypervSize, @@ -131,14 +126,9 @@ VOID* HookVCpuRun(VOID* HypervBase, VOID* HypervSize, VOID* VCpuRunHook) VCPU_RUN_HANDLER_MASK ); - UINT64 VCpuRunCallRip = ((UINT64)VCpuRunCall) + 5; // + 5 bytes to next instructions address... - UINT64 VCpuRunFunction = VCpuRunCallRip + *(INT32*)(((UINT64)VCpuRunCall) + 1); // + 1 to skip E8 (call) and read 4 bytes (RVA) - INT32 NewVCpuRunRVA = ((INT64)VCpuRunHook) - VCpuRunCallRip; - *(INT32*)((UINT64)VCpuRunCall + 1) = NewVCpuRunRVA; - - DBG_PRINT("VCpuRunCall -> 0x%p\n", VCpuRunCall); - DBG_PRINT("VCpuRunCallRip -> 0x%p\n", VCpuRunCallRip); - DBG_PRINT("VCpuRunFunction -> 0x%p\n", VCpuRunFunction); - DBG_PRINT("NewVCpuRunRVA -> 0x%p\n", NewVCpuRunRVA); - return VCpuRunFunction; + UINT64 VmExitHandlerCallRip = ((UINT64)VmExitHandlerCall) + 5; // + 5 bytes to next instructions address... + UINT64 VmExitHandlerFunc = VmExitHandlerCallRip + *(INT32*)(((UINT64)VmExitHandlerCall) + 1); // + 1 to skip E8 (call) and read 4 bytes (RVA) + INT32 NewVmExitHandlerRVA = ((INT64)VCpuRunHook) - VmExitHandlerCallRip; + *(INT32*)((UINT64)VmExitHandlerCall + 1) = NewVmExitHandlerRVA; + return VmExitHandlerFunc; } \ No newline at end of file diff --git a/Voyager-2/Voyager-2 (2004-1709)/Hvax64.h b/Voyager-2/Voyager-2 (2004-1709)/Hvax64.h index a60d2f3..c0867fd 100644 --- a/Voyager-2/Voyager-2 (2004-1709)/Hvax64.h +++ b/Voyager-2/Voyager-2 (2004-1709)/Hvax64.h @@ -18,7 +18,7 @@ VOID* MapModule(PVOYAGER_T VoyagerData, UINT8* ImageBase); // // returns a pointer to the original vmexit function address... // -VOID* HookVCpuRun(VOID* HypervBase, VOID* HypervSize, VOID* VmExitHook); +VOID* HookVmExitHandler(VOID* HypervBase, VOID* HypervSize, VOID* VmExitHook); // // creates a structure with all the data needed to be passed to the golden record... diff --git a/Voyager-2/Voyager-2 (2004-1709)/PayLoad.h b/Voyager-2/Voyager-2 (2004-1709)/PayLoad.h index 9bb7f81..cce752e 100644 --- a/Voyager-2/Voyager-2 (2004-1709)/PayLoad.h +++ b/Voyager-2/Voyager-2 (2004-1709)/PayLoad.h @@ -5,7 +5,7 @@ extern unsigned char PayLoad[2560]; #pragma pack(push, 1) typedef struct _VOYAGER_T { - UINT64 VCpuRunHandlerRVA; + UINT64 VmExitHandlerRVA; UINT64 HypervModuleBase; UINT64 HypervModuleSize; UINT64 ModuleBase; diff --git a/Voyager-2/Voyager-2 (2004-1709)/WinLoad.c b/Voyager-2/Voyager-2 (2004-1709)/WinLoad.c index e6bc338..56597fc 100644 --- a/Voyager-2/Voyager-2 (2004-1709)/WinLoad.c +++ b/Voyager-2/Voyager-2 (2004-1709)/WinLoad.c @@ -62,7 +62,7 @@ EFI_STATUS EFIAPI BlLdrLoadImage(VOID* Arg1, CHAR16* ModulePath, CHAR16* ModuleN DBG_PRINT(".reloc section end (aka payload base address) -> 0x%p\n", TableEntry->ModuleBase + pSection->VirtualAddress + pSection->Misc.VirtualSize); VOID* VCpuRunHook = MapModule(&VoyagerData, PayLoad); - VOID* VmExitFunction = HookVCpuRun + VOID* VmExitFunction = HookVmExitHandler ( VoyagerData.HypervModuleBase, VoyagerData.HypervModuleSize, diff --git a/Voyager-2/Voyager-2.sln b/Voyager-2/Voyager-2.sln index 237ba50..b8d6bd5 100644 --- a/Voyager-2/Voyager-2.sln +++ b/Voyager-2/Voyager-2.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.30503.244 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PayLoad", "PayLoad\PayLoad.vcxproj", "{C5122D8B-DEC8-458F-9342-3A4AC3152BEF}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Voyager-1 (2004-1709)", "Voyager-2 (2004-1709)\Voyager-2 (2004-1709).vcxproj", "{540D433F-C2DF-49A6-895C-F5C74B014777}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Voyager-2 (2004-1709)", "Voyager-2 (2004-1709)\Voyager-2 (2004-1709).vcxproj", "{540D433F-C2DF-49A6-895C-F5C74B014777}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Voyager-2 (1703-1511)", "Voyager-2 (1703-1511)\Voyager-1 (1703-1511).vcxproj", "{C4B6B437-62DF-4166-9023-44CFC8A52258}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -55,6 +57,18 @@ Global {540D433F-C2DF-49A6-895C-F5C74B014777}.Release|x64.Build.0 = Release|x64 {540D433F-C2DF-49A6-895C-F5C74B014777}.Release|x86.ActiveCfg = Release|Win32 {540D433F-C2DF-49A6-895C-F5C74B014777}.Release|x86.Build.0 = Release|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Debug|ARM.ActiveCfg = Debug|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Debug|ARM64.ActiveCfg = Debug|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Debug|x64.ActiveCfg = Debug|x64 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Debug|x64.Build.0 = Debug|x64 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Debug|x86.ActiveCfg = Debug|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Debug|x86.Build.0 = Debug|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Release|ARM.ActiveCfg = Release|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Release|ARM64.ActiveCfg = Release|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Release|x64.ActiveCfg = Release|x64 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Release|x64.Build.0 = Release|x64 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Release|x86.ActiveCfg = Release|Win32 + {C4B6B437-62DF-4166-9023-44CFC8A52258}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE

        25`%eIeSK6_!!CGktoA25K)zRi{Y$5Y+<-0Xa~ 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Ť_c%1 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�naLep`X+#x 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 z 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

    +5zj7cWFT|KU@Z}eNT0H;0eIdTR&MB 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%0D0&?+Uy-OwgSpjA#AD~*qg&!JW7jOnHflhi8fph# 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 ff=he>M3u+hdMYXHE6!T3~v{0 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 ^D8Mum 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 z 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

  • if1r61_$6AofDoVLJe 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%0DM=#XsJ5m#52iD00noPC$CM0M#kw4$LGI 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 gn#OnLDkS+j-2x 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